| name | budget-guard |
| version | 0.1.0 |
| description | 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.
|
| allowed-tools | ["Bash","Read","AskUserQuestion"] |
| argument-hint | [the run to bound — a phase, a loop, or the whole pipeline] |
| arguments | ["run"] |
| when_to_use | Load at the start of ANY unattended run — a converge-loop, a fan-out, an auto-phase, the autonomous
pipeline — to set and enforce its stop conditions. Especially load before a run that will spawn many
agents or execute many rounds without a human in between. Do NOT skip it because "this will be quick" —
the runs that grind for hours are exactly the ones that started without a declared budget.
|
An autonomous run without a declared budget is a bug, not a feature. Non-negotiable:
1. NO RUN STARTS WITHOUT A STOP DECLARATION: a done-condition, a hard cap (iterations AND/OR agents), a
budget (tokens/tool-calls/wall-clock), a no-progress rule, and named escalation triggers. If you can't
state all five, don't run it unattended — do a bounded piece and report.
2. THE BUDGET IS A CEILING, NOT A SUGGESTION. When the cap or budget is reached, the run STOPS — even
mid-task — and reports what's done and what's left. Never "just a bit more" past the ceiling.
3. FAIL CLOSED. Hitting a limit without meeting the done-condition is an HONEST PARTIAL result
(`converged:false` + the remaining gap), never a fabricated success to look finished.
4. ESCALATE ON NAMED TRIGGERS. Irreversible/destructive actions, ambiguous requirements, repeated
no-progress, and "about to exceed budget" are STOP-and-ask points — the run does not decide these for
the user.
5. NEVER RAISE THE CAP TO KEEP GOING. If the declared budget wasn't enough, that is a finding to surface,
not a number to quietly bump. Re-scoping is a user decision.
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)