loop-controller
Why this is a deliberate (disable-model-invocation) skill. A loop edits,
commits, and spends tokens on its own. You want to type /loop-controller
(or have the orchestrator dispatch it), not have Claude silently start an
autonomous loop because a test happened to fail. The discipline below is what
makes that safe.
The one rule that governs every loop
A loop is only as good as its stopping condition. Loops converge when
"done" is an external signal the agent cannot argue with — a test exit code, a
coverage percentage, an empty queue, a fresh evaluator's verdict. They diverge
— oscillate, thrash, or run the budget to zero — when "done" is a subjective
judgment the agent grades itself on. Agents are pathological optimists about
their own work; left to self-assess, they declare victory early.
There is a subtler failure an objective proof does not cure: a signal that
is mechanical, default-FAIL, and un-gameable can still measure the wrong
thing. A test suite green against a mock, a stub, or a fixture is all three of
those — and proves nothing about whether the real product works. That is
convergence on a fiction, and because it wears the costume of rigor (an exit
code! a number!) it slips past review more easily than a subjective claim would.
65 green tests against a mocked backend look exactly like 65 green tests against
the real one. So the proof must measure the real goal, not a stand-in for it
(Step 2) — un-gameable and pointed at the thing that actually matters.
So the entire job of this skill is to turn a fuzzy "keep working on X" into a
convergent loop: a mechanical proof of the real goal, the right execution
primitive, and a guardrail stack that stops the loop whether or not the proof is
ever met.
Everything else here — fix-until-green, coverage-loop, perf-loop — is a config
of this harness: a specific proof plugged into the same machinery. Author new
loops against this skill; don't reinvent the loop engine.
First — does a concrete loop already exist?
Twelve configs of this harness already ship in skills/loops/. Route the intent
to one of them before authoring anything — Steps 0–6 below are for the loop that
doesn't exist yet. (Every one of these is disable-model-invocation: true:
dispatch it by its slash command, or let the orchestrator dispatch the build
loops. None auto-fires.)
| The intent is… |
Dispatch |
| "make tests / lint / typecheck pass", red CI, "run until green" |
fix-until-green |
| Drain a multi-agent build's shared task list until every task passes its gate (Agent Teams) |
orchestrator-task-loop |
| Build until an authored contract's criteria all hold (build-until-spec) |
contract-conformance-loop |
| "Keep my PR green / rebased / answer review comments while I'm away" |
babysit |
| "Raise test coverage to N%" |
coverage-loop |
| "Get this metric under its budget" (latency, bundle size, memory) |
perf-loop |
| "Watch the logs / CI and fix what breaks" |
self-healing-loop |
| "Migrate / transform every file in this enumerated set" |
migration-loop |
| "Keep the docs + changelog from rotting" (nightly) |
nightly-docs-and-changelog |
| "Keep dependencies current and audited" |
dependency-health-loop |
| "Map this unfamiliar codebase until my questions are answered" |
codebase-exploration-loop |
| "Weekly repo hygiene — stale branches, PRs, worktrees" |
repo-cleanup-loop |
No row fits → continue below and author the new loop against this harness.
Step 0 — Should this even be a loop?
A loop has real setup cost and its own failure modes; the mistake is looping
things that don't earn one. Before building anything, put the task through four
questions — a "no" on any of them is a strong signal to just do the work manually
(or once) instead:
- Does it repeat? A one-off is usually faster by hand. Loops pay off on work
that comes back — every PR, every night, every new ticket.
- Can "done" be verified mechanically? If nothing but a human can reject a
bad result, the human is still the real gate and the loop saves little. This is
the same requirement as Step 2 — no mechanical proof, no convergent loop.
- Can the agent act end-to-end? If it must stop for permission or missing
context every few minutes, that's assisted manual work, not a loop.
- Is "done" objective? "Tests pass" / "queue empty" loops; "the design feels
right" / "the strategy is sound" does not. Subjective, high-stakes, judgment-
heavy work (architecture rewrites, auth, payments, prod deploys) is where a
human stays in the driver's seat — keep it manual, or gate it hard (guardrail 4).
Pass all four and the 5-part contract below will fill in cleanly. Fail one and
the honest move is to not build the loop.
The 5-part loop contract (required)
Before running anything, write the loop's contract. A loop that can't fill in
all five lines isn't ready — the blank is the bug.
| Part |
Question it answers |
Example |
| trigger |
What starts this loop? |
"red CI on branch X" / "every 30m" / "user runs /fix-until-green" |
| action |
What does one iteration do? |
"run the gate, fix one root-cause failure, re-run the whole gate" |
| proof |
What mechanical signal proves done? |
"npm test exits 0 and lint exits 0 and typecheck exits 0" |
| memory |
What state survives between iterations? |
"PROGRESS.md, the feature-list JSON, git history" |
| stop |
Every way this loop ends |
"proof passes OR 20 iterations OR no-progress for 3 rounds OR budget cap" |
The proof and stop lines are load-bearing. Keep this contract in the loop
skill's body (or at the top of the run) so any reviewer can audit convergence at
a glance. This is the Forward Future "loop library" 5-part schema, adopted as the
required contract. The taxonomy of common loop shapes (fix-until-green,
build-until-spec, refine-until-quality, research, review, migration, coverage,
perf, self-healing, exploration) lives in references/authoring.md.
Step 1 — Choose the primitive
The first decision is which engine runs the loop. Get this wrong and you burn
money: a scheduler pointed at finishable work re-runs blindly on the clock; a
"work until done" wrapper pointed at an external poll spins forever.
The decision rule: Are you pushing work to a finish line, or watching for
something to change?
| If the job is… |
Use |
Because |
| Push to a finish line, proof is provable from Claude's own output (test exits 0, git clean) |
/goal |
A small fast model judges the transcript each turn; "no" feeds the reason back. The closest native "loop until done." |
| Push to a finish line, proof needs a script/file/tool check the model can't just assert |
Stop-hook gate |
A hook runs the real check and blocks exit until it passes — ships with the skill. |
| Watch / poll for an external change on a cadence |
/loop |
A thin scheduler that re-runs a prompt or slash command on an interval; it does not push to a finish line. |
| One big mechanical change across many files in parallel |
/batch / dynamic workflow |
Fans out across worktree-isolated subagents; compose with the orchestrator's Workflow mode. |
| Greenfield, want a fresh context window every iteration |
claude -p bash loop (Ralph) |
State lives on disk; each pass starts clean. Needs a sandbox (--dangerously-skip-permissions). |
Do not conflate /goal (finish line) with /loop (watch). They are different
primitives with different failure modes. Full mechanics, constraints, and the
exact invocations for each — including /goal's evaluator-can't-read-files
limit and /loop's session-scope/expiry/no-catch-up rules — are in
references/primitives.md. Read it before authoring.
Step 2 — Make "done" mechanical and default-FAIL
A convergent loop needs a proof signal the agent cannot rationalize past.
- Phrase "done" as an observable. "all tests in
test/auth pass and lint is
clean," not "the auth code looks correct." If the proof is a number, name the
artifact that produces it (coverage report, benchmark output, the gate's exit
code).
- Default-FAIL. Every criterion starts
false and only flips on evidence.
Store the criteria as JSON, not prose — a model is far less likely to quietly
rewrite a JSON "passed": false than to soften a sentence. (Anthropic's
long-running-agent harness stores the feature list as JSON for exactly this
reason.)
- Measure the goal, not a stand-in. An objective signal is necessary but not
sufficient — it also has to exercise the real thing the loop is for. If the
goal depends on a real dependency (a live service, real data, an integration, a
deploy) and the proof only touches a mock / stub / fixture of it, the loop will
converge — green, confident, and wrong. Either the proof exercises the real
path at least once, or it is explicitly labelled scaffold-level ("the mocked
build is internally consistent") with a separate goal-level proof named. A
green that came from measuring the stand-in instead of the goal is a coverage
gap wearing a green badge — the same class of bug as a green that came from
moving the number instead of fixing the cause (Step 3, guardrail 6), and just
as much a finding.
- Separate the grader from the doer for any subjective bar. When "done"
can't be reduced to an exit code (UI quality, doc clarity, API ergonomics),
the proof is a fresh-context evaluator subagent — spawned with no
Write/Edit tools so it cannot "fix" a failure by lowering the bar, and
blind to how the work was built so it can't rubber-stamp its own reasoning.
This is the GAN / Plan-Generate-Evaluate pattern. A same-model critic that
saw the build approves mediocre work; an external signal (tests) or a fresh
evaluator is what stops the rubber-stamp. See
references/authoring.md.
Step 3 — Install the guardrail stack (mandatory)
Every loop ships with all of these. They are not optional polish — a documented
multi-agent loop ran 11 days and burned tens of thousands of dollars because
it had observability but no enforcement. Alerting is not a guardrail;
termination is.
- Iteration cap. A hard
--max-iterations (or "stop after N turns" baked
into the /goal condition — /goal has no native cap). This is the primary
backstop when the proof is never met.
- Token / cost budget with enforcement. A ceiling that terminates the
loop, not just warns.
/goal has no built-in budget — embed a turn cap and
watch /cost; dynamic workflows take an explicit token budget; bash loops
need an external counter. A 50-iteration run on a large codebase can cost
$50–100+. The number that actually tells you whether the loop is worth running
is cost per accepted result, not tokens spent or iterations run: a loop
that opens five PRs where you merge one, or emits a daily report no one reads,
can cost more than doing the work by hand. Track yield, not spend — a low
accept rate means the loop is manufacturing review debt, and the fix is a
tighter proof (Step 2), not a bigger budget.
- No-progress / oscillation detection. Stop if iterations stop changing
state, or if output repeats (≥~90% similarity to a recent iteration), or if
token use grows quadratically rather than linearly. Thrashing and budget
exhaustion are the two dominant non-convergence modes — detect both.
- HITL checkpoint before anything irreversible. Pause for a human before a
DB write, a deploy, an external API call, a force-push. Unattended loops run
only what is reversible and has a hard verifier.
- Checkpoint commits. Commit working state every iteration with a
descriptive message. On a wedged codebase,
git reset --hard to the last
green checkpoint and re-loop is usually cheaper than rescuing it.
- Never let the loop weaken its own gate. Forbid editing or deleting tests
to make them pass, silencing a check with an ignore directive, or relocating
a violation into the checker's blind spot. A green that came from moving the
number instead of fixing the cause is a finding, not a win. When a gate
flips red→green, read the diff that did it.
The full stack — including the stop_hook_active guard for Stop-hook loops, the
oscillation thresholds, and the staged-adoption / rollback ladder — is in
references/safety.md.
Step 4 — Externalize state (so iterations are stateless)
A loop that remembers across iterations only through the conversation breaks the
moment context compacts or a fresh-context pass starts. Externalize to
path-addressable files:
- a progress file (
PROGRESS.md / claude-progress.txt) — what's done, what's next;
- a task / feature-list JSON — the default-FAIL criteria;
- a live plan/TODO (
fix_plan.md) — rewritten freely each pass;
- an
init.sh — how to build and run;
- git history — the durable checkpoint trail.
Each iteration starts by reading these, does one increment, then updates
them and commits. Read the caps (max-iterations, budget) and the state-file
paths from .claude/profile.yaml when present, so the same loop skill works
across projects without hard-coding. (This is the orchestrator/role-skill
convention; loops follow it.)
Step 5 — Run, watch for divergence, know when to kill
- One task per iteration. Trust the loop to pick the most important next
thing; don't batch. Spawn subagents for expensive search/verification, but
cap build/test parallelism at 1 — two agents building at once destroy the
backpressure signal.
- Re-verify the whole, not just the change. After each fix, re-run the
entire proof (full suite, every page, the whole rubric), not only the unit
you touched. "Restart the streak" is how you catch a fix that broke something
else.
- Roll a loop back to attended (or kill it) when any of: token spend grows
non-linearly, output similarity >90% across iterations, a fresh evaluator and
your own judgment disagree, or it's about to touch an irreversible resource
without a checkpoint. A suspiciously easy convergence is itself a finding —
inspect before trusting.
Step 6 — Long-run behavioral hygiene (Claude 5 family)
Steps 1–5 make the loop converge. This step keeps the model's behavior honest over
a long run on the Claude 5 family (Fable 5 / Mythos 5), where a single turn can run for
minutes and an autonomous run for hours. These are prompt-level additions to the loop's
brief — the harness enforces convergence; these keep the agent from lying, quitting early,
or panicking about context on the way there. Drop-in instruction text and the 5-part
mapping for each are in model-adaptation/references/long-run-hygiene.md; wire what the
loop needs:
- Evidence-backed progress (anti-fabrication). Instruct the agent to audit each
progress claim against an actual tool result before reporting it. This is distinct from
guardrail 6: guardrail 6 stops the loop from gaming the mechanical gate; this stops the
model from narrating work it never verified. Both matter; neither substitutes.
- Don't end a turn on a promise. Deep in a run the model can say "I'll now run X" with
no tool call, or pause to ask when it already has enough.
/goal + Stop-hooks catch this
mechanically (Step 1); add the prompt-level last-paragraph self-check and, for unattended
runs, the autonomous-operation reminder so the agent doesn't lean on the hook.
- Don't surface the budget countdown to the model. Guardrail 2 watches
/cost for
enforcement — but that number is a harness stop signal, not something to show the
model. Seeing a remaining-token countdown makes the Claude 5 family prematurely summarize,
offer to hand off, or trim its own work. Read the budget from externalized state (Step 4)
and decide in the harness; if a count must be visible, add the "you have ample context,
continue" reassurance.
- Model & effort per iteration. Effort is the primary intelligence/latency/cost dial:
high
default, xhigh for the hardest proof/verify steps, medium/low for routine passes.
Lower effort on the Claude 5 family often beats xhigh on prior models — reduce it if a
loop converges but each iteration runs longer than the work needs. Model tiers the same
way — pick both per model-adaptation's Model & effort tiering policy: workers and
routine passes tier down, but the fresh-context evaluator (Step 2) stays on the top tier.
- Send-to-user for verbatim mid-turn output. A loop otherwise only speaks by ending
its turn for HITL. For long async loops that must surface a deliverable or a direct answer
without stopping, give the agent a client-side
send_to_user tool plus the elicitation
line — never route the model's reasoning through it (that's the reasoning_extraction
refusal landmine; see model-adaptation).
The fresh-context evaluator (Step 2) is itself one of these patterns — the guide's
"fresh verifiers beat self-critique" — so it's already wired; just run it periodically
on a long build, not only at the end.
Comprehension debt — the human-side stop condition
Steps 1–6 keep the machine honest. There is one failure they don't catch,
because it lands on the human, not the loop: a loop that ships correct, green
diffs faster than anyone reads them. Each merge feels like progress, but the
codebase starts moving faster than the team's understanding of it — the tests
pass, yet nobody can say why the code is shaped the way it is. That's
comprehension debt, and it's the antidote's mirror image of convergence-on-a-
fiction: there the proof was too weak, here the proof was fine but human
understanding silently fell behind. The bill arrives at the next bug, in a module
no one can reason about.
The guardrails don't fix this because it isn't a convergence problem — it's a
review problem. Keep it in check by keeping loops on small, readable diffs,
having a human actually read the diff a red→green flip produced (guardrail 6
already asks for this), and — for any substantial or fully agent-driven change —
running a comprehension quiz before merge: find-unknowns owns that move
(explain the diff and what it touches, then test that you can pass a quiz on the
non-obvious behavior). Autonomy that outruns understanding isn't a faster team;
it's a deferred debugging session.
Using it as the harness other loops compose on
Concrete loop skills don't re-implement any of the above — they fill in the
contract and inherit the machinery:
fix-until-green — proof = test+lint+typecheck all exit 0; primitive =
/goal or a Stop-hook gate; the canonical first instance.
- A new loop = a new
skills/loops/<name>/ whose SKILL.md states its 5-part
contract, names its proof artifact, and points back here for the guardrails.
The authoring walkthrough (with the loop taxonomy and a frontmatter template)
is references/authoring.md.
Under the orchestrator, loops slot in at two levels — and both are built:
orchestrator-task-loop is the outer loop over the shared task list (re-assign
until every task passes its gate), while the inner loops run per role —
fix-until-green at the wave/QA gates, and contract-conformance-loop /
coverage-loop / perf-loop / migration-loop dispatched when the mission
calls for them (see the orchestrator's references/phase-guide.md, Optional
build loops).
Reference files
references/primitives.md — /goal, /loop, /batch, dynamic workflows,
Stop-hooks, and the bash-Ralph loop: exact mechanics, constraints, invocations,
and the implementation-approach tradeoff table. Read before choosing a primitive.
references/safety.md — the full guardrail stack, stop_hook_active,
oscillation/no-progress detection, the cost footguns, and the staged-adoption
and rollback ladder.
references/authoring.md — the 10-archetype loop taxonomy, the fresh-context
evaluator / default-FAIL pattern in detail, and a step-by-step template for
writing a new loop skill that composes on this one.
1---2name: loop-controller3description: Wrap any task in a verifiable stop condition plus a mandatory guardrail stack so an autonomous loop converges instead of thrashing or burning the budget — the foundation harness every loop skill composes on. Use whenever you want Claude to keep working until something is provably true (tests pass, coverage hits a target, a contract's criteria hold, a queue is empty), to schedule a recurring check, or to pick the right loop primitive (/goal vs /loop vs Stop-hook vs a bash Ralph loop vs a dynamic workflow). Trigger on: "loop until", "keep going until", "run until green", "work until done", "autonomous loop", "agentic loop", "ralph loop", "/goal", "iterate until", "loop safely", "iteration cap", "loop budget", "runaway agent", "overnight build". Read it first when authoring any new loop skill.4---56# loop-controller78> **Why this is a deliberate (`disable-model-invocation`) skill.** A loop edits,9> commits, and spends tokens on its own. You want to *type* `/loop-controller`10> (or have the orchestrator dispatch it), not have Claude silently start an11> autonomous loop because a test happened to fail. The discipline below is what12> makes that safe.1314## The one rule that governs every loop1516**A loop is only as good as its stopping condition.** Loops *converge* when17"done" is an external signal the agent cannot argue with — a test exit code, a18coverage percentage, an empty queue, a fresh evaluator's verdict. They *diverge*19— oscillate, thrash, or run the budget to zero — when "done" is a subjective20judgment the agent grades itself on. Agents are pathological optimists about21their own work; left to self-assess, they declare victory early.2223There is a subtler failure an objective proof does **not** cure: a signal that24is mechanical, default-FAIL, and un-gameable can still measure the **wrong25thing**. A test suite green against a mock, a stub, or a fixture is all three of26those — and proves nothing about whether the real product works. That is27*convergence on a fiction*, and because it wears the costume of rigor (an exit28code! a number!) it slips past review more easily than a subjective claim would.2965 green tests against a mocked backend look exactly like 65 green tests against30the real one. So the proof must measure the **real goal**, not a stand-in for it31(Step 2) — un-gameable *and* pointed at the thing that actually matters.3233So the entire job of this skill is to turn a fuzzy "keep working on X" into a34**convergent** loop: a mechanical proof *of the real goal*, the right execution35primitive, and a guardrail stack that stops the loop whether or not the proof is36ever met.3738Everything else here — fix-until-green, coverage-loop, perf-loop — is a *config*39of this harness: a specific proof plugged into the same machinery. Author new40loops against this skill; don't reinvent the loop engine.4142## First — does a concrete loop already exist?4344Twelve configs of this harness already ship in `skills/loops/`. Route the intent45to one of them before authoring anything — Steps 0–6 below are for the loop that46*doesn't* exist yet. (Every one of these is `disable-model-invocation: true`:47dispatch it by its slash command, or let the orchestrator dispatch the build48loops. None auto-fires.)4950| The intent is… | Dispatch |51|---|---|52| "make tests / lint / typecheck pass", red CI, "run until green" | `fix-until-green` |53| Drain a multi-agent build's shared task list until every task passes its gate (Agent Teams) | `orchestrator-task-loop` |54| Build until an authored contract's criteria all hold (build-until-spec) | `contract-conformance-loop` |55| "Keep my PR green / rebased / answer review comments while I'm away" | `babysit` |56| "Raise test coverage to N%" | `coverage-loop` |57| "Get this metric under its budget" (latency, bundle size, memory) | `perf-loop` |58| "Watch the logs / CI and fix what breaks" | `self-healing-loop` |59| "Migrate / transform every file in this enumerated set" | `migration-loop` |60| "Keep the docs + changelog from rotting" (nightly) | `nightly-docs-and-changelog` |61| "Keep dependencies current and audited" | `dependency-health-loop` |62| "Map this unfamiliar codebase until my questions are answered" | `codebase-exploration-loop` |63| "Weekly repo hygiene — stale branches, PRs, worktrees" | `repo-cleanup-loop` |6465No row fits → continue below and author the new loop against this harness.6667## Step 0 — Should this even be a loop?6869A loop has real setup cost and its own failure modes; the mistake is looping70things that don't earn one. Before building anything, put the task through four71questions — a "no" on any of them is a strong signal to just do the work manually72(or once) instead:73741. **Does it repeat?** A one-off is usually faster by hand. Loops pay off on work75 that comes back — every PR, every night, every new ticket.762. **Can "done" be verified mechanically?** If nothing but a human can reject a77 bad result, the human is still the real gate and the loop saves little. This is78 the same requirement as Step 2 — no mechanical proof, no convergent loop.793. **Can the agent act end-to-end?** If it must stop for permission or missing80 context every few minutes, that's assisted manual work, not a loop.814. **Is "done" objective?** "Tests pass" / "queue empty" loops; "the design feels82 right" / "the strategy is sound" does not. Subjective, high-stakes, judgment-83 heavy work (architecture rewrites, auth, payments, prod deploys) is where a84 human stays in the driver's seat — keep it manual, or gate it hard (guardrail 4).8586Pass all four and the 5-part contract below will fill in cleanly. Fail one and87the honest move is to not build the loop.8889## The 5-part loop contract (required)9091Before running anything, write the loop's contract. A loop that can't fill in92all five lines isn't ready — the blank is the bug.9394| Part | Question it answers | Example |95|---|---|---|96| **trigger** | What starts this loop? | "red CI on branch X" / "every 30m" / "user runs `/fix-until-green`" |97| **action** | What does one iteration *do*? | "run the gate, fix one root-cause failure, re-run the whole gate" |98| **proof** | What mechanical signal proves done? | "`npm test` exits 0 **and** lint exits 0 **and** typecheck exits 0" |99| **memory** | What state survives between iterations? | "`PROGRESS.md`, the feature-list JSON, git history" |100| **stop** | Every way this loop ends | "proof passes **OR** 20 iterations **OR** no-progress for 3 rounds **OR** budget cap" |101102The `proof` and `stop` lines are load-bearing. Keep this contract in the loop103skill's body (or at the top of the run) so any reviewer can audit convergence at104a glance. This is the Forward Future "loop library" 5-part schema, adopted as the105required contract. The taxonomy of common loop shapes (fix-until-green,106build-until-spec, refine-until-quality, research, review, migration, coverage,107perf, self-healing, exploration) lives in `references/authoring.md`.108109## Step 1 — Choose the primitive110111The first decision is *which engine runs the loop*. Get this wrong and you burn112money: a scheduler pointed at finishable work re-runs blindly on the clock; a113"work until done" wrapper pointed at an external poll spins forever.114115**The decision rule:** *Are you pushing work to a finish line, or watching for116something to change?*117118| If the job is… | Use | Because |119|---|---|---|120| Push to a finish line, proof is **provable from Claude's own output** (test exits 0, git clean) | **`/goal`** | A small fast model judges the transcript each turn; "no" feeds the reason back. The closest native "loop until done." |121| Push to a finish line, proof needs a **script/file/tool check** the model can't just assert | **Stop-hook gate** | A hook runs the real check and blocks exit until it passes — ships *with* the skill. |122| **Watch / poll** for an external change on a cadence | **`/loop`** | A thin scheduler that re-runs a prompt or slash command on an interval; it does not push to a finish line. |123| One big mechanical change across **many files in parallel** | **`/batch` / dynamic workflow** | Fans out across worktree-isolated subagents; compose with the `orchestrator`'s Workflow mode. |124| **Greenfield**, want a fresh context window every iteration | **`claude -p` bash loop (Ralph)** | State lives on disk; each pass starts clean. Needs a sandbox (`--dangerously-skip-permissions`). |125126Do not conflate `/goal` (finish line) with `/loop` (watch). They are different127primitives with different failure modes. Full mechanics, constraints, and the128exact invocations for each — including `/goal`'s evaluator-can't-read-files129limit and `/loop`'s session-scope/expiry/no-catch-up rules — are in130`references/primitives.md`. **Read it before authoring.**131132## Step 2 — Make "done" mechanical and default-FAIL133134A convergent loop needs a proof signal the agent cannot rationalize past.135136- **Phrase "done" as an observable.** "all tests in `test/auth` pass and lint is137 clean," not "the auth code looks correct." If the proof is a number, name the138 artifact that produces it (coverage report, benchmark output, the gate's exit139 code).140- **Default-FAIL.** Every criterion starts `false` and only flips on *evidence*.141 Store the criteria as JSON, not prose — a model is far less likely to quietly142 rewrite a JSON `"passed": false` than to soften a sentence. (Anthropic's143 long-running-agent harness stores the feature list as JSON for exactly this144 reason.)145- **Measure the goal, not a stand-in.** An objective signal is necessary but not146 sufficient — it also has to exercise the *real* thing the loop is for. If the147 goal depends on a real dependency (a live service, real data, an integration, a148 deploy) and the proof only touches a mock / stub / fixture of it, the loop will149 converge — green, confident, and wrong. Either the proof exercises the real150 path at least once, or it is *explicitly* labelled scaffold-level ("the mocked151 build is internally consistent") with a separate goal-level proof named. A152 green that came from measuring the stand-in instead of the goal is a coverage153 gap wearing a green badge — the same class of bug as a green that came from154 moving the number instead of fixing the cause (Step 3, guardrail 6), and just155 as much a *finding*.156- **Separate the grader from the doer for any subjective bar.** When "done"157 can't be reduced to an exit code (UI quality, doc clarity, API ergonomics),158 the proof is a **fresh-context evaluator subagent** — spawned with **no159 Write/Edit tools** so it cannot "fix" a failure by lowering the bar, and160 blind to how the work was built so it can't rubber-stamp its own reasoning.161 This is the GAN / Plan-Generate-Evaluate pattern. A same-model critic that162 saw the build approves mediocre work; an external signal (tests) or a fresh163 evaluator is what stops the rubber-stamp. See `references/authoring.md`.164165## Step 3 — Install the guardrail stack (mandatory)166167Every loop ships with all of these. They are not optional polish — a documented168multi-agent loop ran **11 days and burned tens of thousands of dollars** because169it had observability but no *enforcement*. Alerting is not a guardrail;170termination is.1711721. **Iteration cap.** A hard `--max-iterations` (or "stop after N turns" baked173 into the `/goal` condition — `/goal` has no native cap). This is the primary174 backstop when the proof is never met.1752. **Token / cost budget with enforcement.** A ceiling that *terminates* the176 loop, not just warns. `/goal` has no built-in budget — embed a turn cap and177 watch `/cost`; dynamic workflows take an explicit token budget; bash loops178 need an external counter. A 50-iteration run on a large codebase can cost179 $50–100+. The number that actually tells you whether the loop is worth running180 is **cost per *accepted* result**, not tokens spent or iterations run: a loop181 that opens five PRs where you merge one, or emits a daily report no one reads,182 can cost more than doing the work by hand. Track yield, not spend — a low183 accept rate means the loop is manufacturing review debt, and the fix is a184 tighter proof (Step 2), not a bigger budget.1853. **No-progress / oscillation detection.** Stop if iterations stop changing186 state, or if output repeats (≥~90% similarity to a recent iteration), or if187 token use grows quadratically rather than linearly. Thrashing and budget188 exhaustion are the two dominant non-convergence modes — detect both.1894. **HITL checkpoint before anything irreversible.** Pause for a human before a190 DB write, a deploy, an external API call, a force-push. Unattended loops run191 only what is reversible and has a hard verifier.1925. **Checkpoint commits.** Commit working state every iteration with a193 descriptive message. On a wedged codebase, `git reset --hard` to the last194 green checkpoint and re-loop is usually cheaper than rescuing it.1956. **Never let the loop weaken its own gate.** Forbid editing or deleting tests196 to make them pass, silencing a check with an ignore directive, or relocating197 a violation into the checker's blind spot. A green that came from moving the198 number instead of fixing the cause is a *finding*, not a win. When a gate199 flips red→green, read the diff that did it.200201The full stack — including the `stop_hook_active` guard for Stop-hook loops, the202oscillation thresholds, and the staged-adoption / rollback ladder — is in203`references/safety.md`.204205## Step 4 — Externalize state (so iterations are stateless)206207A loop that remembers across iterations only through the conversation breaks the208moment context compacts or a fresh-context pass starts. Externalize to209**path-addressable files**:210211- a **progress file** (`PROGRESS.md` / `claude-progress.txt`) — what's done, what's next;212- a **task / feature-list JSON** — the default-FAIL criteria;213- a live **plan/TODO** (`fix_plan.md`) — rewritten freely each pass;214- an **`init.sh`** — how to build and run;215- **git history** — the durable checkpoint trail.216217Each iteration starts by *reading* these, does one increment, then *updates*218them and commits. Read the caps (max-iterations, budget) and the state-file219paths from `.claude/profile.yaml` when present, so the same loop skill works220across projects without hard-coding. (This is the orchestrator/role-skill221convention; loops follow it.)222223## Step 5 — Run, watch for divergence, know when to kill224225- **One task per iteration.** Trust the loop to pick the most important next226 thing; don't batch. Spawn subagents for expensive search/verification, but227 **cap build/test parallelism at 1** — two agents building at once destroy the228 backpressure signal.229- **Re-verify the whole, not just the change.** After each fix, re-run the230 *entire* proof (full suite, every page, the whole rubric), not only the unit231 you touched. "Restart the streak" is how you catch a fix that broke something232 else.233- **Roll a loop back to attended (or kill it) when** any of: token spend grows234 non-linearly, output similarity >90% across iterations, a fresh evaluator and235 your own judgment disagree, or it's about to touch an irreversible resource236 without a checkpoint. A suspiciously easy convergence is itself a finding —237 inspect before trusting.238239## Step 6 — Long-run behavioral hygiene (Claude 5 family)240241Steps 1–5 make the loop *converge*. This step keeps the **model's behavior** honest over242a long run on the Claude 5 family (Fable 5 / Mythos 5), where a single turn can run for243minutes and an autonomous run for hours. These are prompt-level additions to the loop's244brief — the harness enforces convergence; these keep the agent from lying, quitting early,245or panicking about context on the way there. Drop-in instruction text and the 5-part246mapping for each are in `model-adaptation/references/long-run-hygiene.md`; wire what the247loop needs:248249- **Evidence-backed progress (anti-fabrication).** Instruct the agent to audit each250 progress claim against an actual tool result before reporting it. This is *distinct from*251 guardrail 6: guardrail 6 stops the loop from gaming the mechanical *gate*; this stops the252 model from *narrating* work it never verified. Both matter; neither substitutes.253- **Don't end a turn on a promise.** Deep in a run the model can say "I'll now run X" with254 no tool call, or pause to ask when it already has enough. `/goal` + Stop-hooks catch this255 mechanically (Step 1); add the prompt-level last-paragraph self-check and, for unattended256 runs, the autonomous-operation reminder so the agent doesn't lean on the hook.257- **Don't surface the budget countdown to the model.** Guardrail 2 watches `/cost` for258 *enforcement* — but that number is a **harness** stop signal, not something to show the259 model. Seeing a remaining-token countdown makes the Claude 5 family prematurely summarize,260 offer to hand off, or trim its own work. Read the budget from externalized state (Step 4)261 and decide in the harness; if a count must be visible, add the "you have ample context,262 continue" reassurance.263- **Model & effort per iteration.** Effort is the primary intelligence/latency/cost dial: `high`264 default, `xhigh` for the hardest proof/verify steps, `medium`/`low` for routine passes.265 Lower effort on the Claude 5 family often beats `xhigh` on prior models — reduce it if a266 loop converges but each iteration runs longer than the work needs. Model tiers the same267 way — pick both per `model-adaptation`'s *Model & effort tiering* policy: workers and268 routine passes tier down, but the fresh-context evaluator (Step 2) stays on the top tier.269- **Send-to-user for verbatim mid-turn output.** A loop otherwise only speaks by *ending*270 its turn for HITL. For long async loops that must surface a deliverable or a direct answer271 *without* stopping, give the agent a client-side `send_to_user` tool plus the elicitation272 line — never route the model's reasoning through it (that's the `reasoning_extraction`273 refusal landmine; see `model-adaptation`).274275The fresh-context evaluator (Step 2) is itself one of these patterns — the guide's276"fresh verifiers beat self-critique" — so it's already wired; just run it *periodically*277on a long build, not only at the end.278279## Comprehension debt — the human-side stop condition280281Steps 1–6 keep the *machine* honest. There is one failure they don't catch,282because it lands on the human, not the loop: a loop that ships correct, green283diffs faster than anyone reads them. Each merge feels like progress, but the284codebase starts moving faster than the team's understanding of it — the tests285pass, yet nobody can say *why* the code is shaped the way it is. That's286**comprehension debt**, and it's the antidote's mirror image of convergence-on-a-287fiction: there the proof was too weak, here the proof was fine but human288understanding silently fell behind. The bill arrives at the next bug, in a module289no one can reason about.290291The guardrails don't fix this because it isn't a convergence problem — it's a292review problem. Keep it in check by keeping loops on **small, readable diffs**,293having a human actually read the diff a red→green flip produced (guardrail 6294already asks for this), and — for any substantial or fully agent-driven change —295running a **comprehension quiz before merge**: `find-unknowns` owns that move296(explain the diff and what it touches, then test that you can pass a quiz on the297non-obvious behavior). Autonomy that outruns understanding isn't a faster team;298it's a deferred debugging session.299300## Using it as the harness other loops compose on301302Concrete loop skills don't re-implement any of the above — they *fill in the303contract* and inherit the machinery:304305- **`fix-until-green`** — proof = test+lint+typecheck all exit 0; primitive =306 `/goal` or a Stop-hook gate; the canonical first instance.307- A new loop = a new `skills/loops/<name>/` whose SKILL.md states its 5-part308 contract, names its proof artifact, and points back here for the guardrails.309 The authoring walkthrough (with the loop taxonomy and a frontmatter template)310 is `references/authoring.md`.311312Under the **orchestrator**, loops slot in at two levels — and both are built:313`orchestrator-task-loop` is the outer loop over the shared task list (re-assign314until every task passes its gate), while the inner loops run per role —315`fix-until-green` at the wave/QA gates, and `contract-conformance-loop` /316`coverage-loop` / `perf-loop` / `migration-loop` dispatched when the mission317calls for them (see the orchestrator's `references/phase-guide.md`, *Optional318build loops*).319320## Reference files321322- `references/primitives.md` — `/goal`, `/loop`, `/batch`, dynamic workflows,323 Stop-hooks, and the bash-Ralph loop: exact mechanics, constraints, invocations,324 and the implementation-approach tradeoff table. Read before choosing a primitive.325- `references/safety.md` — the full guardrail stack, `stop_hook_active`,326 oscillation/no-progress detection, the cost footguns, and the staged-adoption327 and rollback ladder.328- `references/authoring.md` — the 10-archetype loop taxonomy, the fresh-context329 evaluator / default-FAIL pattern in detail, and a step-by-step template for330 writing a new loop skill that composes on this one.