Repository navigation
The token-budget breaker is unreachable: agent-rate-limit-gate.sh never consults arl_token_budget_gate or arl_token_weekly_glide_gate #1155
Description
Summary
Epic #636 closed on 2026-09-07 with phases 1–6 all merged, but the token-budget breaker it delivered cannot fire. scripts/agent-rate-limit-gate.sh — the only entrypoint any workflow invokes — contains no reference to arl_token_budget_gate, arl_token_weekly_glide_gate, or AGENT_TOKEN_BUDGET_ENABLED. Both breakers are fully implemented in scripts/lib/agent-rate-limit.sh, covered by tests/test_agent_rate_limit_token_budget.bats and tests/test_agent_rate_limit_weekly_glide.bats, and reachable from nothing.
The per-agent-type half of the standard (concurrency / cooldown / daily run budget / consecutive-failure) is wired and working. It is only the org-wide token-budget half that is orphaned.
Evidence
$ grep -nE 'token_budget|weekly_glide|arl_token|AGENT_TOKEN' scripts/agent-rate-limit-gate.sh
(no matches)
Gate call sites today:
| Caller | Mode | Consults token budget? |
|---|---|---|
.github/workflows/feature-ideation-reusable.yml |
--mode log-only (+ || true) |
no |
.github/workflows/initiative-driver.yml (consumer stub) |
--mode enforce |
no |
So even the enforcing canary enforces only run-rate limits, never budget.
Why this matters right now
Measured on the fleet on 2026-09-20, with no breaker able to act:
session 33% normal resets 2026-09-21T05:20Z
weekly_all 79% warning resets 2026-09-22T16:00Z
weekly_scoped 36% normal
79% of the weekly subscription budget consumed with two days left in the window, while ~2,500 agent workflow runs over two days churned on pull requests that could not merge. Nothing paused, nothing warned, because the only code that could have is unreachable.
Acceptance Criteria
scripts/agent-rate-limit-gate.shconsults the org-wide token-budget breaker in its decision path, in addition to the existing per-agent-type checks. Adeferfrom either half defers the dispatch; the existingdecision=output contract and exit codes are unchanged.- The token-budget consultation is behind
AGENT_TOKEN_BUDGET_ENABLED(unset ⇒ skipped entirely, today's behaviour), so this change is inert until a maintainer arms it. - When armed and
--mode log-only, the gate logs the breaker's decision and window percent but never defers — the same canary discipline phases 4–6 used. sessionandweekly_allare both consulted;weekly_scopedis never consulted (ADR §2.5 — per-model exhaustion is the engine's model-fallback chain, not a fleet pause).- The decision is observable: the gate emits which windows it read, each percent, each threshold, and — critically — whether telemetry was actually obtained. A fail-open due to absent telemetry must be visibly distinct in the log from a genuine under-threshold allow. Today they are indistinguishable, which is how an unarmed breaker looks exactly like a healthy one.
- A bats test asserts that with
AGENT_TOKEN_BUDGET_ENABLEDset and a mocked over-threshold envelope,--mode enforceyieldsdecision=defer; and that with the flag unset the gate's output is byte-identical to today's. standards/agent-rate-limits.md§Status is corrected: the token-budget breaker is described as wired-but-disarmed rather than signed-off-and-wired.
Out of scope
- Supplying the telemetry itself. The library reads it through the
AGENT_TOKEN_BUDGET_TELEMETRY_CMD/AGENT_TOKEN_BUDGET_TELEMETRY_FILEseam; producing that envelope from the OAuth usage endpoint is the private companion,petry-projects/.github-private#1565, and must land for this to do anything observable. - Flipping
org_wide.limits.weekly_all.enabledtotrueinstandards/agent-rate-limits.json. Arming is a separate, deliberate maintainer change.
References
- Agentic Activity Circuit Breakers & Org-Wide Rate-Limiting Standard #636 — epic (closed; this is the gap that closure hid)
- [Phase 4] Wire the gate into the PR/agent-dispatch workflows #640 — Phase 4, the gate this extends
- [Phase 5] Token-budget circuit breaker: pause at the configured % of the 5-hour Claude window #641 / [Phase 6] Weekly-budget glide-path breaker: pause at 100 − 2×days-until-reset of the 7-day Claude window #994 — the two breakers being wired
docs/initiatives/agent-rate-limits-adr.md§4.1 (telemetry), §7 (thresholds, fail-safe direction), §2.5 (scope guard)petry-projects/.github-private#1565— the telemetry producer this depends on
Activity
don-petry commentedon Sep 22, 2026
Dev-Lead Implementation Plan
Issue: #1155 — The token-budget breaker is unreachable: agent-rate-limit-gate.sh never consults arl_token_budget_gate or arl_token_weekly_glide_gate
Scope
Wire the org-wide token-budget breaker (session + weekly_all) into
scripts/agent-rate-limit-gate.sh's decision path, behindAGENT_TOKEN_BUDGET_ENABLED, so adeferfrom the token-budget half defers dispatch alongside the existing per-agent-type checks — inert (byte-identical) until a maintainer arms the flag.Implementation Checklist
scripts/agent-rate-limit-gate.sh: addargate_token_budget()helper that fetches the telemetry envelope once and consultsarl_token_budget_gate session+arl_token_weekly_glide_gate(weekly_all);weekly_scopednever consulted (ADR §2.5). Observable logging: which windows read, each percent, each threshold, and — distinctly — whether telemetry was actually obtained (fail-open vs healthy allow).scripts/agent-rate-limit-gate.sh: consultargate_token_budgetinsideargate_gateonly whenAGENT_TOKEN_BUDGET_ENABLED=true; adefersetsdecision=defer. Existing log-only/DRY_RUN/emit contract unchanged.scripts/agent-rate-limit-gate.sh: update header doc comment + Env list.standards/agent-rate-limits.md§3 Status: correct the token-budget breaker description to wired-but-disarmed rather than out-of-path.Tests to Write (tests/test_agent_rate_limit_gate.bats)
--mode enforce→decision=defer(AC feat: add Structured Logging and CQRS standards #6)--mode log-only→ emits allow but logs the would-be defer + percent (AC Add coding standards & principles section to AGENTS.md #3)weekly_scopedat 100% but session under threshold → allow (scope guard, AC Add workflow, environment, and orchestration guidance #4)Test Command
./node_modules/.bin/bats tests/test_agent_rate_limit_gate.bats(full suite:./node_modules/.bin/bats tests/)don-petry commentedon Sep 22, 2026
Dev-Lead: Progress (in progress — not yet durable)
Plan Execution (intended)
scripts/agent-rate-limit-gate.shvia a newargate_token_budgethelper that fetches the telemetry envelope once and consultsarl_token_budget_gate session+arl_token_weekly_glide_gate(weekly_all).weekly_scopedis never consulted (ADR §2.5).AGENT_TOKEN_BUDGET_ENABLED; unset ⇒ the block is skipped entirely (inert / byte-identical). Adeferfrom the token-budget half defers dispatch alongside the per-agent checks; the existingdecision=contract, exit codes, log-only and DRY_RUN branches are unchanged.standards/agent-rate-limits.md§3 (and the config_note) to describe the breaker as wired-but-disarmed rather than out-of-path.Files touched (this workspace, not yet pushed)
scripts/agent-rate-limit-gate.sh: newargate_token_budgethelper + gated consultation inargate_gate; header/env docs.tests/test_agent_rate_limit_gate.bats: token-budget config/telemetry helpers + 7 new tests (armed defer, inert/byte-identical, log-only, scope guard, degraded-vs-healthy observability).standards/agent-rate-limits.md: §3 Status corrected.standards/agent-rate-limits.json: top-level_notecorrected.Notes
.ymlfiles were modified — arming (setting the env flag / forwarding it through caller stubs, and flippingweekly_all.enabled) is a separate, deliberately out-of-scope maintainer change, so the channel-skew guardrail (Codify the off-peak scheduling standard and offset this repo's 11 minute-0 crons #1052) does not apply here.don-petry commentedon Sep 22, 2026
Dev-Lead: Implementation Complete — PR #1164
The implementation for issue #1155 is durable: commits are pushed and a pull request is open. This record is backed by verifiable artifacts you can confirm in one click.
e97fccc61192dcc67e81f29c238d837814b6a17fmain: 4 file(s), +244/-7 linesReview happens on the PR. Acceptance criteria and test results are evidenced by the PR's diff and CI checks — not asserted here. If a later stage fails, this claim is retracted in place.
feat: implement issue #1155 — The token-budget breaker is unreachable…