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