Budget Guard
Inputs
$run: the run to bound — a phase, a loop, or the whole pipeline. Defaults to the run being
launched in the current turn.
Overview
Give every autonomous run a contract it cannot exceed. Budget-guard is not an action so much as a
discipline the other skills wrap themselves in: it forces the five stop conditions to exist before the run
starts, holds the run to them during, and makes the exit honest. It's what turns a loop that could run
forever into one that provably terminates within a known cost.
The five stop conditions (declare all before running)
| Condition |
What it bounds |
Example |
| done-condition |
success — machine-checkable |
validate exits 0 / finder returns 0 / all DAG units done |
| hard cap |
count of iterations and/or agents |
≤6 loop rounds; ≤40 total agents |
| budget |
cost — tokens / tool-calls / wall-clock |
≤150k output tokens; ≤20 min |
| no-progress rule |
futility |
stop after 2 rounds with no measured improvement |
| escalation triggers |
user-owned decisions |
destructive op, ambiguous spec, repeated stall, near-budget |
A run is safe only when ALL five exist. Missing one is the hole a runaway escapes through.
Phase 0: Size the budget to the task and the directive
Set the numbers deliberately, not by reflex:
- If the user gave a token/scale directive (e.g. "+500k", "quick pass", "be thorough"), map it to the
budget: a big target → a wider fan-out and more rounds; "quick" → tight caps. In a Workflow, read
budget.total / budget.remaining(); the target is a HARD ceiling once reached.
- Scale the hard cap to the work: a typecheck-fix loop rarely needs >6 rounds; a broad audit might take 8.
Total agents scale with the item count but stay bounded (and concurrency-capped — see
fan-out-work).
- Default token budget when none is given: bound it (e.g. ~150k output tokens for a phase) rather than
leaving it open. An unbounded default is not a default.
Success criteria: all five conditions have concrete values, justified by the task and any directive.
Phase 1: Enforce during the run
Check the conditions every iteration / at every barrier, cheaply:
- decrement the iteration/agent counters; compare spend to the budget BEFORE launching the next expensive
step (don't discover you're over budget after paying for the overshoot);
- track the progress signal (see
converge-loop) so the no-progress rule can fire;
- watch the escalation triggers continuously — an irreversible step or an ambiguity is a stop, whenever it
appears.
When any condition fires, halt at the next safe boundary (finish the in-flight unit's commit, don't abort
mid-write) and go to Phase 2.
Success criteria: the run cannot exceed any declared limit; a limit hit halts it at a safe point.
Phase 2: Exit honestly (or escalate)
Classify and report the exit:
- done — done-condition met within budget. Report cost used.
- capped / over-budget — limit hit first. Report the honest partial: what's done, what remains, the
cost spent. Offer the user the re-scope decision (raise budget / narrow scope / hand off) — never raise
it yourself.
- escalated — a named trigger fired. STOP and surface the specific decision (with
AskUserQuestion
when interactive), then wait. Resume only on the user's answer.
Success criteria: exactly one exit reason; cost reported; any user decision surfaced, not assumed.
Common Rationalizations
| Rationalization |
Reality |
| "It's almost done, let me go a little over the cap." |
"Almost" is unmeasured optimism. The cap exists precisely for the case that feels almost-done and isn't. Stop and report. |
| "I'll set the budget after I see how it goes." |
Then there is no budget. The runs that grind for hours all started this way. Declare it first. |
| "No progress this round, but the next one might work." |
"Might" past the no-progress rule is thrash. Stop after the declared stalls and escalate. |
| "This delete/deploy is obviously fine, no need to ask." |
Irreversible actions are escalation triggers by definition. Obvious-to-you is not authorization. |
| "Budget ran out, I'll just bump it and finish." |
Re-scoping is the user's call. Raising your own ceiling silently defeats the guard. |
| "A budget will make me stop before it's perfect." |
Bounded-and-honest beats unbounded-and-runaway. A reported partial is more useful than an hours-long grind. |
Red Flags
- A loop/workflow launched with no stated caps in the transcript.
- Iteration or agent counts climbing past the declared cap.
- "Just one more round" after the no-progress rule should have fired.
- A cap or budget number quietly increased mid-run.
- An irreversible action taken inside an autonomous run without a stop-and-ask.
- A run reported "done" that actually hit a limit (a capped run wearing a success badge).
Guardrails
- Never start an unattended run without all five stop conditions declared.
- Never exceed a declared cap/budget; halt at the next safe boundary and report.
- Never raise your own budget to keep going — that's a user decision.
- Never take an irreversible action or resolve a real ambiguity inside the run — escalate.
- Never report a capped/escalated run as a clean success.
Native goal/loop routing
On Claude Code, compile the five stop conditions into the native machinery instead of only tracking
them by hand: the done-condition becomes the /goal objective (verified each turn by a separate
model — the strongest form of "machine-checkable"); the hard cap becomes /loop's count/time stop;
the budget is the session/turn token target (in a Workflow, budget.remaining() — a HARD ceiling);
escalation triggers stay in the run body plus the deterministic guard hooks. The no-progress
rule has no native equivalent on Claude Code — keep it hand-tracked (Codex's /goal has it natively:
blocked after 3 consecutive stuck turns). Full mapping: converge-loop's
references/native-goal-loop.md.
When To Load References
converge-loop (skill) — the loop-level termination set and no-progress/anti-thrash detectors this
guard enforces at the iteration level; its references/native-goal-loop.md holds the /goal + /loop
compilation table.
checkpoint-resume (skill) — so a run stopped at a budget/escalation boundary resumes without redoing
finished work.
Output Contract
Report:
- the five stop conditions used (with values)
- cost spent (iterations / agents / tokens / time) vs. the budget
- exit reason — done / capped / over-budget / escalated
- on a non-done exit: the honest remaining gap + the user decision offered (never taken unilaterally)
1---2name: budget-guard3description: The discipline that keeps an autonomous run from becoming a runaway: before any unattended loop or workflow, declare the five stop conditions — done-condition, hard cap, token/time budget, no-progress rule, escalation triggers — then hold the run to them and stop the instant one fires. Fails closed: a capped run reports an honest partial, never fabricated success. Load at the start of ANY unattended run.4---56<EXTREMELY-IMPORTANT>7An autonomous run without a declared budget is a bug, not a feature. Non-negotiable:81. NO RUN STARTS WITHOUT A STOP DECLARATION: a done-condition, a hard cap (iterations AND/OR agents), a9 budget (tokens/tool-calls/wall-clock), a no-progress rule, and named escalation triggers. If you can't10 state all five, don't run it unattended — do a bounded piece and report.112. THE BUDGET IS A CEILING, NOT A SUGGESTION. When the cap or budget is reached, the run STOPS — even12 mid-task — and reports what's done and what's left. Never "just a bit more" past the ceiling.133. FAIL CLOSED. Hitting a limit without meeting the done-condition is an HONEST PARTIAL result14 (`converged:false` + the remaining gap), never a fabricated success to look finished.154. ESCALATE ON NAMED TRIGGERS. Irreversible/destructive actions, ambiguous requirements, repeated16 no-progress, and "about to exceed budget" are STOP-and-ask points — the run does not decide these for17 the user.185. NEVER RAISE THE CAP TO KEEP GOING. If the declared budget wasn't enough, that is a finding to surface,19 not a number to quietly bump. Re-scoping is a user decision.20</EXTREMELY-IMPORTANT>2122# Budget Guard2324## Inputs2526- `$run`: the run to bound — a phase, a loop, or the whole pipeline. Defaults to the run being27 launched in the current turn.2829## Overview3031Give every autonomous run a contract it cannot exceed. Budget-guard is not an action so much as a32discipline the other skills wrap themselves in: it forces the five stop conditions to exist before the run33starts, holds the run to them during, and makes the exit honest. It's what turns a loop that *could* run34forever into one that *provably* terminates within a known cost.3536## The five stop conditions (declare all before running)3738| Condition | What it bounds | Example |39|---|---|---|40| **done-condition** | success — machine-checkable | validate exits 0 / finder returns 0 / all DAG units done |41| **hard cap** | count of iterations and/or agents | ≤6 loop rounds; ≤40 total agents |42| **budget** | cost — tokens / tool-calls / wall-clock | ≤150k output tokens; ≤20 min |43| **no-progress rule** | futility | stop after 2 rounds with no measured improvement |44| **escalation triggers** | user-owned decisions | destructive op, ambiguous spec, repeated stall, near-budget |4546A run is safe only when ALL five exist. Missing one is the hole a runaway escapes through.4748## Phase 0: Size the budget to the task and the directive4950Set the numbers deliberately, not by reflex:5152- If the user gave a token/scale directive (e.g. "+500k", "quick pass", "be thorough"), map it to the53 budget: a big target → a wider fan-out and more rounds; "quick" → tight caps. In a Workflow, read54 `budget.total` / `budget.remaining()`; the target is a HARD ceiling once reached.55- Scale the hard cap to the work: a typecheck-fix loop rarely needs >6 rounds; a broad audit might take 8.56 Total agents scale with the item count but stay bounded (and concurrency-capped — see `fan-out-work`).57- Default token budget when none is given: bound it (e.g. ~150k output tokens for a phase) rather than58 leaving it open. An unbounded default is not a default.5960**Success criteria:** all five conditions have concrete values, justified by the task and any directive.6162## Phase 1: Enforce during the run6364Check the conditions every iteration / at every barrier, cheaply:6566- decrement the iteration/agent counters; compare spend to the budget BEFORE launching the next expensive67 step (don't discover you're over budget after paying for the overshoot);68- track the progress signal (see `converge-loop`) so the no-progress rule can fire;69- watch the escalation triggers continuously — an irreversible step or an ambiguity is a stop, whenever it70 appears.7172When any condition fires, halt at the next safe boundary (finish the in-flight unit's commit, don't abort73mid-write) and go to Phase 2.7475**Success criteria:** the run cannot exceed any declared limit; a limit hit halts it at a safe point.7677## Phase 2: Exit honestly (or escalate)7879Classify and report the exit:8081- **done** — done-condition met within budget. Report cost used.82- **capped / over-budget** — limit hit first. Report the honest partial: what's done, what remains, the83 cost spent. Offer the user the re-scope decision (raise budget / narrow scope / hand off) — never raise84 it yourself.85- **escalated** — a named trigger fired. STOP and surface the specific decision (with `AskUserQuestion`86 when interactive), then wait. Resume only on the user's answer.8788**Success criteria:** exactly one exit reason; cost reported; any user decision surfaced, not assumed.8990## Common Rationalizations9192| Rationalization | Reality |93|---|---|94| "It's almost done, let me go a little over the cap." | "Almost" is unmeasured optimism. The cap exists precisely for the case that feels almost-done and isn't. Stop and report. |95| "I'll set the budget after I see how it goes." | Then there is no budget. The runs that grind for hours all started this way. Declare it first. |96| "No progress this round, but the next one might work." | "Might" past the no-progress rule is thrash. Stop after the declared stalls and escalate. |97| "This delete/deploy is obviously fine, no need to ask." | Irreversible actions are escalation triggers by definition. Obvious-to-you is not authorization. |98| "Budget ran out, I'll just bump it and finish." | Re-scoping is the user's call. Raising your own ceiling silently defeats the guard. |99| "A budget will make me stop before it's perfect." | Bounded-and-honest beats unbounded-and-runaway. A reported partial is more useful than an hours-long grind. |100101## Red Flags102103- A loop/workflow launched with no stated caps in the transcript.104- Iteration or agent counts climbing past the declared cap.105- "Just one more round" after the no-progress rule should have fired.106- A cap or budget number quietly increased mid-run.107- An irreversible action taken inside an autonomous run without a stop-and-ask.108- A run reported "done" that actually hit a limit (a capped run wearing a success badge).109110## Guardrails111112- Never start an unattended run without all five stop conditions declared.113- Never exceed a declared cap/budget; halt at the next safe boundary and report.114- Never raise your own budget to keep going — that's a user decision.115- Never take an irreversible action or resolve a real ambiguity inside the run — escalate.116- Never report a capped/escalated run as a clean success.117118## Native goal/loop routing119120On Claude Code, compile the five stop conditions into the native machinery instead of only tracking121them by hand: the **done-condition** becomes the `/goal` objective (verified each turn by a separate122model — the strongest form of "machine-checkable"); the **hard cap** becomes `/loop`'s count/time stop;123the **budget** is the session/turn token target (in a Workflow, `budget.remaining()` — a HARD ceiling);124**escalation triggers** stay in the run body plus the deterministic guard hooks. The **no-progress125rule** has no native equivalent on Claude Code — keep it hand-tracked (Codex's `/goal` has it natively:126`blocked` after 3 consecutive stuck turns). Full mapping: `converge-loop`'s127`references/native-goal-loop.md`.128129## When To Load References130131- `converge-loop` (skill) — the loop-level termination set and no-progress/anti-thrash detectors this132 guard enforces at the iteration level; its `references/native-goal-loop.md` holds the /goal + /loop133 compilation table.134- `checkpoint-resume` (skill) — so a run stopped at a budget/escalation boundary resumes without redoing135 finished work.136137## Output Contract138139Report:1401411. the five stop conditions used (with values)1422. cost spent (iterations / agents / tokens / time) vs. the budget1433. exit reason — done / capped / over-budget / escalated1444. on a non-done exit: the honest remaining gap + the user decision offered (never taken unilaterally)