Loop
Autonomous iteration that continues until spec is satisfied or limits reached.
Before You Start (Required Checklist)
□ Score the spec (use rubric below)
□ Determine shape (Tool ≥8, Colleague 5-7, Intent <5)
□ Classify reversibility (see below)
□ Extract success criteria from spec (explicit list)
□ Decompose into concrete steps
□ Create task with state schema
□ Write .loop/state.json with criteria array
□ Announce: [LOOP] Starting | Shape: X | Workflow: [A/B/C] | Steps: N | Budget: $Y
If any checkbox is unclear, STOP and clarify before proceeding.
Reversibility Classification
| Type | Rollback | Examples | Action |
|---|---|---|---|
| 2A | < 1 min | Config changes, renames | Execute freely |
| 2B | < 5 min | Dependencies, refactors | Checkpoint each step |
| 1 | Hours+ | Schema changes, public APIs | Require adversarial pre-check |
See fit-decision.md for full delegation scoring.
SHAPE.md Integration
If .loop/shape/SHAPE.md exists (generated by /hope:shape), extract:
- criteria: → Add to criteriaStatus initialization
- mustNot: → Add as circuit breaker triggers
- verification: → Map to verification types per criterion
{
"criteriaStatus": {
"tests pass": {"met": false, "verification": "execution output"},
"API returns 200": {"met": false, "verification": "execution output"},
"UI renders": {"met": false, "verification": "observation"}
}
}
mustNot Circuit Breaker: If any mustNot condition becomes true during execution → pause immediately.
Exit Blocked: If any criterion has verification: "assumption", exit_signal cannot be true.
Spec Clarity Rubric (Inline)
Score on 5 dimensions (0-2 each, max 10):
| Dimension | 0 | 1 | 2 |
|---|---|---|---|
| Outcome | "Make it better" | "Improve performance" | "p95 latency <100ms" |
| Scope | "Fix the app" | "Fix auth" | "Fix /api/auth/token" |
| Constraints | None stated | "Use existing stack" | "No new deps, <500 LOC" |
| Success | None stated | "Tests pass" | "All tests + manual QA" |
| Done | Implied | "When it works" | "PR merged to main" |
Decision:
- ≥8: Tool-shaped — execute silently, report on completion
- 5-7: Colleague-shaped — check in after each iteration
- <5: Run
/hope:intentfirst
Workflow Type Detection
After scoring spec, detect workflow type from content:
| Workflow | Indicators | Gate |
|---|---|---|
| A (Build) | "add", "implement", "create", "new feature" | Library search required |
| B (Debug) | "fix", "debug", "broken", "error", "failing" | Root cause before workaround |
| C (Refactor) | "refactor", "clean up", "reorganize", "migrate" | Deletion before redesign |
Update announcement to include workflow: [LOOP] Starting | Shape: X | Workflow: [A/B/C] | Steps: N
Reference hope/skills/soul for workflow details.
Confirmation Gates by Shape
Tool-Shaped (≥8)
Execute autonomously. No confirmation gates.
[LOOP] Starting | Shape: Tool (9/10) | Workflow: A | Steps: 5
... executes all steps without pausing ...
<loop-complete>
Colleague-Shaped (5-7)
Pause at three checkpoints:
| Gate | When | Question |
|---|---|---|
| G1 | After spec decomposition | "Here are N steps. Proceed?" |
| G2 | After each iteration | "Step X complete. Continue?" |
| G3 | Before completion claim | "All criteria met. Confirm done?" |
[LOOP] Starting | Shape: Colleague (6/10) | Workflow: B | Steps: 4
G1: Decomposed into 4 steps:
1. Identify failing test
2. Add instrumentation
3. Fix root cause
4. Verify fix
Proceed? [Y/n]
Skip gates: User says "proceed without confirmation" to run uninterrupted.
Intent-Required (<5)
Block and route to /hope:intent before proceeding.
State File Schema (CRITICAL)
Transparency: Loop writes .loop/state.json to track progress.
On loop start, disclose: "Writing state to .loop/state.json. Delete after session? [Y/n]"
Cleanup: State files auto-delete on /loop cancel unless user opts to keep.
Write .loop/state.json at loop start and update after EVERY iteration:
{
"spec": "original user request verbatim",
"criteria": ["tests pass", "all routes refactored", "no lint errors"],
"criteriaStatus": {
"tests pass": false,
"all routes refactored": false,
"no lint errors": true
},
"exit_signal": false,
"steps": ["step1", "step2", "step3"],
"completedSteps": ["step1"],
"remainingSteps": ["step2", "step3"],
"iteration": 2,
"status": "in_progress",
"circuitBreaker": {
"stuckCount": 0,
"lastUnmet": "tests pass"
}
}
The stop hook reads this file to decide whether to continue.
Dual-Condition Exit (CRITICAL)
The stop hook requires BOTH conditions to stop:
- All
criteriaStatusvalues aretrue exit_signalistrue
If either condition is false, the loop continues.
Why Dual-Condition?
Prevents premature stops. Claude must:
- Actually verify each criterion (tests pass, lint clean, etc.)
- Explicitly signal completion intent
Iteration Protocol
1. TaskGet → Retrieve current state
2. Read .loop/state.json if exists (recovery case)
3. Announce → [LOOP] Iteration N/max | Cost: $X | Step: [name]
4. Execute → Do ONE logical unit of work
5. Verify → Run verification commands for affected criteria
6. Update state → Write .loop/state.json with updated criteriaStatus
7. Check circuit breaker → Increment stuckCount if same criteria unmet
8. Output status block → ---LOOP_STATUS--- (required)
9. TaskUpdate → Save to Tasks API (backup)
Status Block (REQUIRED)
After EACH iteration, output this exact format:
---LOOP_STATUS---
EXIT_SIGNAL: false
CRITERIA: {"tests pass": false, "lint clean": true}
STUCK_COUNT: 0
NEXT: Fix failing tests
---END_STATUS---
Rules:
EXIT_SIGNAL: trueONLY when ALL criteria verified trueCRITERIAmust matchcriteriaStatusin state fileSTUCK_COUNTincrements when same criteria remain unmetNEXTdescribes the next action
State Update Protocol
After each iteration:
- Run verification commands for criteria you worked on
- Update
criteriaStatusbased on actual verification results - Check for stuck state:
- If same criteria unmet as last iteration, increment
circuitBreaker.stuckCount - If different criteria unmet, reset
stuckCountto 0
- If same criteria unmet as last iteration, increment
- Set
exit_signal:trueONLY if ALL criteriaStatus values are truefalseotherwise
- Write updated state to
.loop/state.json - Output status block
Circuit Breakers
| Trigger | Threshold | Action |
|---|---|---|
| Same criteria unmet | 5x consecutive | Stop hook opens circuit |
| Same error | 3x consecutive | Pause, request help |
| Same file edits | 5x in one iteration | Pause, likely thrashing |
| Budget exceeded | $25 default | Pause, offer continue |
| Iteration limit | 10 default | Pause, offer continue |
The stop hook checks circuitBreaker.stuckCount >= 5 and returns {ok: true} to stop.
Announcements
Before Each Iteration
[LOOP] Iteration N/max | Cost: $X/$budget | Step: [current step]
After Each Iteration
[LOOP] ✓ [step name] complete | Progress: N/total | Next: [next step]
On Completion
<loop-complete>
All success criteria satisfied:
- [criterion 1]: ✓
- [criterion 2]: ✓
- [criterion 3]: ✓
</loop-complete>
Output <loop-complete> ONLY after:
- All criteriaStatus values are true
- exit_signal set to true in state file
Quality Footer Required: After <loop-complete>, include a verdict box:
╭─ 🟢 SHIP ──────────────────────────╮
│ Verified: [execution output/observation/measurement] │
│ Checklist: N/N criteria verified │
│ Subjective: ~X% · Type 2A/2B · Npt │
├────────────────────────────────────┤
│ ↳ Alt: [alternative approach] │
│ ↳ Risk: [key assumption] │
╰────────────────────────────────────╯
Map loop outcomes to verdicts:
- 🟢 SHIP: All criteria verified with execution output/observation/measurement
- 🟡 MONITOR: Criteria passed but verification was code review only
- 🔴 RESEARCH: Any criterion verified by assumption only
See quality-footer.md for format details.
On Pause
[LOOP] ⏸ Paused: [reason]
Progress: N steps complete, M remaining
Resume: /loop continue
Commands
| Command | Effect |
|---|---|
/loop [spec] |
Start new loop |
/loop continue |
Resume paused loop |
/loop continue --budget=25 |
Add budget and resume |
/loop cancel |
Terminate and clean up |
/loop status |
Show current state |
Cost Controls
| Protection | Default | Max | Override |
|---|---|---|---|
| Budget cap | $25 | $100 | --budget=N |
| Iterations | 10 | 50 | --iterations=N |
Principle: Pause, don't kill. User can always continue.
Example
User: "loop - refactor all API routes to use validation middleware"
[LOOP] Starting | Shape: Colleague (7/10) | Steps: 4 | Budget: $25
Spec scoring:
- Outcome: 2 (clear refactor)
- Scope: 2 (API routes)
- Constraints: 1 (middleware implied)
- Success: 1 (implicit: works)
- Done: 1 (implicit: all routes)
Total: 7/10 → Colleague-shaped
[LOOP] Iteration 1/10 | Cost: $0.50/$25 | Step: Refactor /api/users
... work happens ...
[LOOP] ✓ /api/users complete | Progress: 1/4 | Next: /api/auth
---LOOP_STATUS---
EXIT_SIGNAL: false
CRITERIA: {"/api/users refactored": true, "/api/auth refactored": false, "tests pass": false}
STUCK_COUNT: 0
NEXT: Refactor /api/auth
---END_STATUS---
Continue? [Y/n]
On completion:
---LOOP_STATUS---
EXIT_SIGNAL: true
CRITERIA: {"/api/users refactored": true, "/api/auth refactored": true, "tests pass": true}
STUCK_COUNT: 0
NEXT: none
---END_STATUS---
<loop-complete>
All success criteria satisfied:
- /api/users refactored: ✓
- /api/auth refactored: ✓
- /api/products refactored: ✓
- /api/orders refactored: ✓
- All tests pass: ✓
</loop-complete>
Boundary
Loop executes, never decides.
- User controls what gets built — loop executes the spec, doesn't expand it
- User controls persistence — state files disclosed, cleanup offered
- User controls continuation — pause is always honored, "cancel" is immediate
Loop must not do work the user should learn. If same pattern repeats 3+ times, suggest: "This is a learnable pattern. Want the steps to run yourself?"
References
references/loop-mechanics.md— Command-based stop hook, state schema, circuit breakerreferences/spec-rubric.md— Scoring examplesreferences/cost-controls.md— Override syntax, continuationreferences/headless.md— CI/CD integrationreferences/prd-mode.md— PRD execution mode for pre-decomposed tasks