Files
loop-loop/skills/run/SKILL.md

185 lines
5.4 KiB
Markdown

---
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.
---
# /run — Execute Agent Loop Inside Claude Code
Run the generator-evaluator loop natively in Claude Code. You see every tool call and can intervene at any point.
## Usage
```
/agent-loop:run # Run until all stories pass or max iterations
/agent-loop:run 3 # Run at most 3 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.
### 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:
- 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)
- `~/.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.
### Step 1: Parse Arguments and Load State
- Parse arguments: number → max iterations, `--skip-eval`, `--story <ID>`
- Read `.loop/config.json` for defaults
- Read `.loop/prd.json` for story list
Report:
> **Loop Ready**
> - Mode: {mode}
> - Stories: {passed}/{total} complete
> - Max iterations: {N}
> - Eval: {on/off}
>
> Starting. Interrupt me at any time.
### Step 2: Iteration Loop
For each iteration (1 to max iterations):
#### 2a. 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.
**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
#### 2b. Report Iteration Start
> **Iteration {N}/{max} — {story.id}: {story.title}**
If the story has `[REJECTED]` in its `notes`, summarize the feedback.
#### 2c. Assemble Generator Prompt
Read and concatenate with `---` separator:
1. `{prompt_base_path}/generator/_base.md`
2. `{prompt_base_path}/generator/{mode}.md`
Substitute template 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
- `{{ITERATION}}` → current iteration
- `{{MAX_ITERATIONS}}` → max iterations
- `{{LOOP_DIR}}` → absolute path to `.loop/`
- `{{PROJECT_ROOT}}` → project root absolute path
- `{{CURRENT_STORY_ID}}` → story ID
#### 2d. Capture Pre-Generator Git State
Run `git rev-parse HEAD` and save the SHA.
#### 2e. Dispatch Generator Agent
```
Agent(
prompt: <assembled generator prompt>,
description: "Generator: {story.id}",
subagent_type: "general-purpose",
mode: "auto"
)
```
Wait for completion.
#### 2f. Check for Completion Signal
If output contains `<promise>COMPLETE</promise>`, report all stories complete and stop.
#### 2g. Skip Evaluator (if configured)
If `--skip-eval` or `config.skipEval` is true, skip to 2j and treat as PASS.
#### 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
```
Agent(
prompt: <assembled evaluator prompt>,
description: "Evaluator: {story.id}",
subagent_type: "general-purpose",
mode: "auto"
)
```
Parse the verdict:
- `<verdict>PASS</verdict>` → PASS
- `<verdict>REJECT</verdict>` → REJECT, extract `<rejection_reason>...</rejection_reason>`
- No verdict tag → REJECT (fail-safe)
#### 2j. Update State
**On PASS:**
1. Read `.loop/prd.json`, set `passes: true` for the story, write it back
2. 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
#### 2k. Append Progress
Append to `.loop/progress.md`:
```markdown
### {story.id} — {story.title}
Date: {current date and time}
Iteration: {N}
Verdict: {PASS/REJECT/SKIP-EVAL}
---
```
#### 2l. Report and Continue
Show: `{passed}/{total} stories complete`
Continue to next iteration.
### Step 3: Loop Exit
> **Loop Complete**
> - Iterations used: {N}
> - Stories: {passed}/{total} complete, {blocked} blocked
If incomplete, suggest `/agent-loop:triage`.
### 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