diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index a8bb559..bd7b175 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "agent-loop", "source": "./", "description": "Autonomous generator-evaluator agent loop for long-running coding tasks. Plan interactively, then execute with full visibility.", - "version": "0.5.0", + "version": "0.6.0", "author": { "name": "Sheldon" }, diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index f7a85a5..23132a6 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agent-loop", - "version": "0.5.0", + "version": "0.6.0", "description": "Autonomous generator-evaluator agent loop for long-running coding tasks. Plan with /agent-loop:init, then execute with /agent-loop:run.", "author": { "name": "Sheldon" diff --git a/skills/run/SKILL.md b/skills/run/SKILL.md index 31d51ff..63ace77 100644 --- a/skills/run/SKILL.md +++ b/skills/run/SKILL.md @@ -1,45 +1,113 @@ --- name: run -description: Execute the generator-evaluator loop interactively inside Claude Code. Dispatches subagents with full visibility. Run /agent-loop:init and /agent-loop:stories first. +description: "Agent Loop — single entry point. Scaffolds .loop/ if missing, generates stories if no prd.json, then runs the generator-evaluator loop with full visibility." --- -# /run — Execute Agent Loop Inside Claude Code +# /run — Agent Loop -Run the generator-evaluator loop natively in Claude Code. You see every tool call and can intervene at any point. +Single entry point for the agent loop. Handles setup, planning, and execution automatically based on what's already done. ## Usage ``` -/agent-loop:run # Run until all stories pass or max iterations -/agent-loop:run 3 # Run at most 3 iterations +/agent-loop:run # Full flow: setup → stories → loop +/agent-loop:run 3 # Limit to 3 loop iterations /agent-loop:run --skip-eval # Skip evaluator pass /agent-loop:run --story US-003 # Run only a specific story ``` ## Instructions -Follow this orchestration sequence exactly. +Follow this sequence. Each phase checks what exists and skips if already done. -### Step 0: Validate Prerequisites +--- -1. Check `.loop/config.json` exists. If not: tell user to run `/agent-loop:init` and stop. -2. Check `.loop/prd.json` exists. If not: tell user to run `/agent-loop:stories` and stop. -3. **Validate prd.json schema.** Read the file and verify: +## Phase 1: Scaffold (if needed) + +Check if `.loop/config.json` exists. + +**If it does NOT exist**, run the setup script: + +Ask the user: **Mode?** (a) Implement (b) Explore (c) Fix — default is Implement. + +Then run: + +```bash +bash "$(ls -d ~/.claude/plugins/cache/agent-loop/agent-loop/*/setup.sh 2>/dev/null | head -1)" +``` + +Show the output. If setup fails, stop. + +**If it already exists**, skip to Phase 2. + +--- + +## Phase 2: Generate Stories (if needed) + +Check if `.loop/prd.json` exists. + +**If it does NOT exist**, generate it: + +1. Search for existing specs: + - `docs/superpowers/specs/*.md` + - `docs/specs/*.md` + - `SPEC.md`, `PRD.md`, `DESIGN.md` at project root + + If found: "I found a spec at `{path}`. Using it to generate stories." + If not found: ask "What do you want to build? 1-3 sentences." + +2. Read the project root and tech stack info. + +3. Dispatch the **agent-loop:planner** agent: + +``` +Agent( + subagent_type: "agent-loop:planner", + prompt: "Generate prd.json and sprint contracts.\n\nMode: {mode}\nProject root: {path}\n\nSpec:\n{spec content}\n\nTech stack: {detected stack}", + description: "Planning: generate stories" +) +``` + +4. After the planner finishes, read `.loop/prd.json` and present: + +> **Stories generated — Review before running** +> +> 1. US-001: {title} +> 2. US-002: {title} +> ... +> +> **Review:** +> - `.loop/prd.json` — stories and acceptance criteria +> - `.loop/contracts/` — done conditions per story +> +> Let me know if you want changes, or say **go** to start the loop. + +5. **STOP and wait for the user.** Do NOT start the loop automatically. The user must say "go", "start", "run", "looks good", or similar before proceeding to Phase 3. + +**If `prd.json` already exists**, skip to Phase 3. + +--- + +## Phase 3: Validate + +1. Read `.loop/prd.json` and verify: - Has a `userStories` array (NOT `sprints`, `stories`, or `tasks`) - Each story has: `id`, `title`, `passes`, `priority` - - If validation fails, show the error and stop. Do NOT attempt to fix it automatically. -4. Check prompts exist. Look for `.loop/prompts/generator/_base.md` in these locations (first match wins): - - `.loop/prompts/` (local project copy) - - `${CLAUDE_PLUGIN_ROOT}/prompts/` (plugin install) + - If invalid, show the error and stop. + +2. Read `.loop/config.json` for `mode`, `maxIterations`, `evalRetries`, `scopeBudgets`. + +3. Find prompts. Check these paths (first match wins): + - `.loop/prompts/` (local) - `~/.claude/plugins/cache/agent-loop/agent-loop/*/prompts/` (plugin cache) - Save the resolved prompt base path for later use. If no prompts found, tell user to run `/agent-loop:init` and stop. + If no prompts found, stop with error. -### Step 1: Parse Arguments and Load State +4. Parse arguments: number → max iterations, `--skip-eval`, `--story ` -- Parse arguments: number → max iterations, `--skip-eval`, `--story ` -- Read `.loop/config.json` for defaults -- Read `.loop/prd.json` for story list +--- + +## Phase 4: Execute Loop Report: @@ -51,47 +119,45 @@ Report: > > Starting. Interrupt me at any time. -### Step 2: Iteration Loop - For each iteration (1 to max iterations): -#### 2a. Find Next Story +### 4a. Find Next Story -Find the story with the lowest `priority` number where `passes` is `false` and `blocked` is not `true`. If `--story` was specified, use that story. +Find the story with the lowest `priority` where `passes` is `false` and `blocked` is not `true`. If `--story` was specified, use that story. **If no actionable story remains:** - All `passes: true` → report success and stop -- Some `blocked: true` → report which and suggest `/agent-loop:triage` -- Stop the loop +- Some `blocked: true` → report which ones +- Stop -#### 2b. Report Iteration Start +### 4b. Report Iteration Start > **Iteration {N}/{max} — {story.id}: {story.title}** -If the story has `[REJECTED]` in its `notes`, summarize the feedback. +If the story has `[REJECTED]` in `notes`, summarize the feedback. -#### 2c. Assemble Generator Prompt +### 4c. Assemble Generator Prompt Read and concatenate with `---` separator: -1. `{prompt_base_path}/generator/_base.md` -2. `{prompt_base_path}/generator/{mode}.md` +1. `{prompt_path}/generator/_base.md` +2. `{prompt_path}/generator/{mode}.md` -Substitute template variables: +Substitute variables: - `{{MAX_FILES_TO_READ}}` → from config scopeBudgets - `{{MAX_LINES_TO_WRITE}}` → from config scopeBudgets - `{{MAX_FILES_TO_MODIFY}}` → from config scopeBudgets -- `{{MODE}}` → mode from config +- `{{MODE}}` → mode - `{{ITERATION}}` → current iteration - `{{MAX_ITERATIONS}}` → max iterations - `{{LOOP_DIR}}` → absolute path to `.loop/` -- `{{PROJECT_ROOT}}` → project root absolute path +- `{{PROJECT_ROOT}}` → project root - `{{CURRENT_STORY_ID}}` → story ID -#### 2d. Capture Pre-Generator Git State +### 4d. Capture Pre-Generator Git State Run `git rev-parse HEAD` and save the SHA. -#### 2e. Dispatch Generator Agent +### 4e. Dispatch Generator Agent ``` Agent( @@ -102,27 +168,19 @@ Agent( ) ``` -Wait for completion. +### 4f. Check Completion Signal -#### 2f. Check for Completion Signal +If output contains `COMPLETE`, report done and stop. -If output contains `COMPLETE`, report all stories complete and stop. +### 4g. Evaluator (unless skipped) -#### 2g. Skip Evaluator (if configured) +If `--skip-eval` or `config.skipEval` is true, skip to 4h and treat as PASS. -If `--skip-eval` or `config.skipEval` is true, skip to 2j and treat as PASS. +Otherwise, read and concatenate: +1. `{prompt_path}/evaluator/_base.md` +2. `{prompt_path}/evaluator/{mode}.md` -#### 2h. Assemble Evaluator Prompt - -Read and concatenate: -1. `{prompt_base_path}/evaluator/_base.md` -2. `{prompt_base_path}/evaluator/{mode}.md` - -Substitute same variables plus: -- `{{PRE_GENERATOR_SHA}}` → SHA from step 2d -- `{{CURRENT_STORY_ID}}` → story ID - -#### 2i. Dispatch Evaluator Agent +Substitute same variables plus `{{PRE_GENERATOR_SHA}}` and `{{CURRENT_STORY_ID}}`. ``` Agent( @@ -133,52 +191,48 @@ Agent( ) ``` -Parse the verdict: +Parse verdict: - `PASS` → PASS -- `REJECT` → REJECT, extract `...` -- No verdict tag → REJECT (fail-safe) +- `REJECT` → REJECT, extract reason +- No verdict → REJECT (fail-safe) -#### 2j. Update State +### 4h. Update State -**On PASS:** -1. Read `.loop/prd.json`, set `passes: true` for the story, write it back -2. Report: **{story.id} PASSED** +**PASS:** Set `passes: true` in prd.json. Report: **{story.id} PASSED** -**On REJECT:** -1. Read `.loop/prd.json`, increment `rejections`, append `[REJECTED] {reason}` to `notes`, write back -2. Report: **{story.id} REJECTED** — {reason} -3. If `rejections >= evalRetries`: set `blocked: true`, append `[BLOCKED]` to notes - - Report: **{story.id} BLOCKED** — rejected {N} times, needs human review +**REJECT:** Increment `rejections`, append `[REJECTED] {reason}` to `notes`. Report: **{story.id} REJECTED** — {reason} -#### 2k. Append Progress +If `rejections >= evalRetries`: set `blocked: true`. Report: **{story.id} BLOCKED** + +### 4i. Append Progress Append to `.loop/progress.md`: ```markdown ### {story.id} — {story.title} -Date: {current date and time} +Date: {date} Iteration: {N} -Verdict: {PASS/REJECT/SKIP-EVAL} +Verdict: {verdict} --- ``` -#### 2l. Report and Continue +### 4j. Continue Show: `{passed}/{total} stories complete` Continue to next iteration. -### Step 3: Loop Exit +--- + +## Loop Exit > **Loop Complete** -> - Iterations used: {N} +> - Iterations: {N} > - Stories: {passed}/{total} complete, {blocked} blocked -If incomplete, suggest `/agent-loop:triage`. +## Error Handling -### Error Handling - -- Agent fails or empty output → warn and continue to next iteration -- prd.json unparseable → stop immediately -- User says "stop" → end loop, report current status +- Agent fails or empty output → warn and continue +- prd.json unparseable → stop +- User says "stop" → end loop, report status