Skip to content

The token-budget breaker is unreachable: agent-rate-limit-gate.sh never consults arl_token_budget_gate or arl_token_weekly_glide_gate #1155

Closed

Description

@don-petry

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

  1. scripts/agent-rate-limit-gate.sh consults the org-wide token-budget breaker in its decision path, in addition to the existing per-agent-type checks. A defer from either half defers the dispatch; the existing decision= output contract and exit codes are unchanged.
  2. 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.
  3. 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.
  4. session and weekly_all are both consulted; weekly_scoped is never consulted (ADR §2.5 — per-model exhaustion is the engine's model-fallback chain, not a fleet pause).
  5. 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.
  6. A bats test asserts that with AGENT_TOKEN_BUDGET_ENABLED set and a mocked over-threshold envelope, --mode enforce yields decision=defer; and that with the flag unset the gate's output is byte-identical to today's.
  7. 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_FILE seam; 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.enabled to true in standards/agent-rate-limits.json. Arming is a separate, deliberate maintainer change.

References

Activity

  1. don-petry commented on Sep 22, 2026

    @don-petry
    ContributorAuthor

    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, behind AGENT_TOKEN_BUDGET_ENABLED, so a defer from 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: add argate_token_budget() helper that fetches the telemetry envelope once and consults arl_token_budget_gate session + arl_token_weekly_glide_gate (weekly_all); weekly_scoped never 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: consult argate_token_budget inside argate_gate only when AGENT_TOKEN_BUDGET_ENABLED=true; a defer sets decision=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)

    Test Command

    ./node_modules/.bin/bats tests/test_agent_rate_limit_gate.bats (full suite: ./node_modules/.bin/bats tests/)

  2. don-petry commented on Sep 22, 2026

    @don-petry
    ContributorAuthor

    Dev-Lead: Progress (in progress — not yet durable)

    Provisional. Nothing is pushed yet; the automation posts the authoritative
    completion record (with PR number + head SHA) after the push. Treat the notes
    below as intent, not delivered results.

    Plan Execution (intended)

    • Wired the org-wide token-budget breaker into scripts/agent-rate-limit-gate.sh via a new argate_token_budget helper that fetches the telemetry envelope once and consults arl_token_budget_gate session + arl_token_weekly_glide_gate (weekly_all). weekly_scoped is never consulted (ADR §2.5).
    • Consultation is gated on AGENT_TOKEN_BUDGET_ENABLED; unset ⇒ the block is skipped entirely (inert / byte-identical). A defer from the token-budget half defers dispatch alongside the per-agent checks; the existing decision= contract, exit codes, log-only and DRY_RUN branches are unchanged.
    • Observability: logs each window's percent + threshold and distinctly whether telemetry was actually obtained (200) vs a degraded fail-open.
    • Corrected 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: new argate_token_budget helper + gated consultation in argate_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 _note corrected.

    Notes

    • No workflow .yml files were modified — arming (setting the env flag / forwarding it through caller stubs, and flipping weekly_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.
    • Local runs of the affected bats files and the required lint were exercised during development (provisional — not the pushed run).
  3. don-petry commented on Sep 22, 2026

    @don-petry
    ContributorAuthor

    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.

    Review 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.

  4. added a commit that references this issue on Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugBug reportsdev-leadFor dev-lead agent pickup

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions