Repository navigation
[Phase 2] standards/agent-rate-limits.json config + standard doc (single source of truth) #638
Description
Story
As a platform engineer,
I want add standards/agent-rate-limits.json as the machine-readable single source of truth for per-agent-type limits, with a standards/agent-rate-limits.md companion and a JSON contract test,
so that every gate and workflow reads limits from one signed-off file instead of hardcoding them in scripts.
Acceptance Criteria
- standards/agent-rate-limits.json exists and mirrors the shape of standards/pr-limits.json: a _schema_version, inline _note fields recording the human sign-off + rationale, a per-agent-type map of controls, and exempt-actor / exempt-label lists.
- Per the ADR taxonomy, each in-scope agent type carries max_concurrent_runs, max_runtime_minutes, cooldown_minutes, daily_run_budget, and a circuit_breaker (consecutive_failure_threshold + pause/backoff duration); plus an org_wide token_budget block with the 5-hour-window threshold (default 90%) and a Claude-priority flag.
- The config is inert on merge: values are documented as requiring human sign-off before any gate enforces them (mirroring the pr-limits sign-off gate), and no workflow reads it yet.
- A bats contract test asserts the file is parseable JSON, required keys are present, numeric limits are positive integers, and the token threshold is within range — mirroring the pr-limits config contract.
- standards/agent-rate-limits.md documents each control and cites the ADR as the decision record and, like pr-limits.md, does NOT restate the changeable numeric values in prose (it points readers at the JSON).
- The AGENTS.md standards table gains a row linking the new standard, keeping standards discoverable.
- The per-agent daily_run_budget is documented in agent-rate-limits.md as the concrete per-agent cost bound, so the epic's cost cap is traceable to a specific config key.
Tasks / Subtasks
- Author standards/agent-rate-limits.json mirroring pr-limits.json (schema_version, _note sign-off, per-agent map, exempt lists) (AC: Addressing PR comments #1, Add multi-agent isolation strategy using git worktrees #2)
- Encode the org_wide token_budget block (5-hour window, 90% default, Claude priority) (AC: Add multi-agent isolation strategy using git worktrees #2)
- Mark the config inert pending human sign-off; add no consumer wiring (AC: Add coding standards & principles section to AGENTS.md #3)
- Add tests/test_agent_rate_limits_config.bats contract test (parseable, keys, ranges) (AC: Add workflow, environment, and orchestration guidance #4)
- Write standards/agent-rate-limits.md companion citing the ADR, without restating numbers, and naming daily_run_budget as the per-agent cost bound (AC: Add stacked PR strategy and Epic-level workflow guidance #5, docs: document branch protection rules, rulesets, and auto-merge policy #7)
- Add the standard to the AGENTS.md standards table (AC: feat: add Structured Logging and CQRS standards #6)
Dev Notes
- Mirror standards/pr-limits.json (petry-projects/.github) in spirit: it carries status: signed-off, a top-level _note with the human sign-off date + epic/gate reference, a _schema_version, an org_wide block, an (intentionally empty) per_source_caps map, and exempt_actors / exempt_labels. Reuse the exempt_actors set (dependabot[bot], @petry-projects/org-leads break-glass, etc.) so the same actors bypass rate limits.
- The pr-limits standard doc deliberately does NOT restate the numeric cap in prose ('a changeable value stated in prose is a second place to forget to update'); the reader runs jq over the JSON. Follow that convention exactly in agent-rate-limits.md.
- Per AGENTS.md: 'all standards and rulesets belong in .github/standards/'; the standards table at the top of AGENTS.md is the discovery index — add a row like the existing 'PR limits' row.
- Tests: the repo uses bats under tests/ (e.g. canary_rollout.bats, test_bootstrap_new_repo.bats); TDD is mandatory per AGENTS.md (tests in the same PR). The config contract test mirrors how pr-limits.json validity is asserted.
- Do NOT activate values: like the pr-limits config's sign-off gate (epic Enable GitHub pull request limits to cut automation-PR noise #505 gate [Phase 3 gate] Human sign-off: final PR-limit caps + exempt list + rollout scope #566), the numbers require human sign-off. The config is a data file; the gate library (Phase 3) and wiring (Phases 4-5) consume it later.
Project Structure Notes
New files land under standards/ in the target public repo, next to pr-limits.json / pr-limits.md. Test lands under tests/ per the repo bats convention.
References
- standards/pr-limits.json (petry-projects/.github — config shape and single-source-of-truth pattern to mirror)
- standards/pr-limits.md (petry-projects/.github — companion-doc convention: never restate numbers)
- AGENTS.md
Likely target surface
standards/agent-rate-limits.json (new — machine-readable per-agent limits)standards/agent-rate-limits.md (new — companion standard doc)tests/test_agent_rate_limits_config.bats (new — JSON contract test)AGENTS.md
Story prepared by the BMAD Scrum Master (Bob) for epic #636. Status: ready-for-dev.
⚠️ Post-ADR clarification (added 2026-08-30, after PR #995 merged — read before implementing)
The Phase 1 ADR (docs/initiatives/agent-rate-limits-adr.md, merged in f720a092) settled a contradiction that was open when this story was written. The ADR as merged is authoritative; where this story's wording predates it, follow the ADR.
-
The 5-hour
sessionwindow and the 7-dayweekly_allwindow are FIXED windows, not rolling/sliding ones. Each carries an authoritativeresets_at. Within a window,percentis monotonically non-decreasing; the only event that lowers it is the reset. Do not describe either window as "rolling" in the JSON_notefields or inagent-rate-limits.md. (The per-minuteanthropic-ratelimit-*token bucket is continuously replenished — that one is genuinely not a fixed window, and is a different mechanism.) -
There is NO percentage resume mark. Do not add one. An earlier ADR draft proposed a half-open resume at 80% utilization; that was removed, not re-tuned, because under a fixed window a downward percentage dip cannot occur, making the mark unreachable by construction. Do not emit a
resume_pct,resume_threshold,hysteresis, or equivalent key in theorg_wide.token_budgetblock. AC Add multi-agent isolation strategy using git worktrees #2 asks for the 90% threshold and the Claude-priority flag — that is the complete set. -
The two breakers close on different events, so do not model them with one shared resume key:
session(5-hour): closes only atresets_at.weekly_all(7-day): closes atresets_ator whenpercent < 100 - (reserve_pct_per_day * days_until_reset)stops holding — which can happen earlier because the glide-path threshold rises asdays_until_resetshrinks. The threshold moves; utilization never falls. If areserve_pct_per_daykey is included, default it to2and mark it inert pending sign-off like every other value.
-
weekly_scoped(per-model exhaustion) is never pause-worthy — onlysessionandweekly_allare. If the config enumerates limit kinds, encode that distinction rather than leaving it to the consumer. -
AC Add coding standards & principles section to AGENTS.md #3's "inert on merge" still stands in full: no workflow reads this file in this PR.
Activity
don-petry commentedon Aug 30, 2026
Dev-Lead Implementation Plan
Issue: #638 — [Phase 2] standards/agent-rate-limits.json config + standard doc (single source of truth)
Scope
Add
standards/agent-rate-limits.jsonas the machine-readable single source of truth for per-agent-type rate limits + circuit breakers (mirroringpr-limits.json), an inert-pending-sign-offorg_wide.token_budgetblock, a companionstandards/agent-rate-limits.mdthat never restates the numbers, a bats contract test, and a discovery-index row in AGENTS.md — with no consumer wiring (AC #3).Implementation Checklist
standards/agent-rate-limits.json—status: provisional, top-level_note(human sign-off pending, epic Agentic Activity Circuit Breakers & Org-Wide Rate-Limiting Standard #636 gate, cites ADR),_schema_version, per-agent-typecontrolsmap (dev-lead, compliance-audit, feature-ideation, initiative-driver) withmax_concurrent_runs,max_runtime_minutes,cooldown_minutes,daily_run_budget,circuit_breaker{consecutive_failure_threshold, backoff_minutes};org_wide.token_budget(fixed 5hsession+ 7dweekly_allwindows,pause_threshold_pctdefault 90,reserve_pct_per_day2 inert,claude_priority: true,pause_worthy_kinds= session+weekly_all,weekly_scopednon-pausing); reuseexempt_actors/exempt_labelsfrom pr-limitsstandards/agent-rate-limits.md— companion doc citing the ADR as decision record, documents each control WITHOUT restating numbers (jq-the-JSON convention), namesdaily_run_budgetas the concrete per-agent cost bound (AC docs: document branch protection rules, rulesets, and auto-merge policy #7)AGENTS.md— add an "Agent rate limits" row to the standards discovery table.github/workflows/agent-rate-limits-tests.yml— CI runner mirroringpr-limits-tests.ymlso the contract test is actually enforced (AGENTS.md CI-gate mandate)Tests to Write
tests/test_agent_rate_limits_config.bats— parseable JSON; required top-level keys; each agent's numeric limits are positive integers; circuit_breaker keys present/positive;org_wide.token_budget.pause_threshold_pctwithin (0,100];claude_priorityboolean;weekly_scopedmarked non-pause-worthy; NOresume_pct/hysteresiskey exists (per post-ADR clarification); exempt lists mirror pr-limits (dependabot[bot], security)Post-ADR guardrails honored
Fixed windows (not "rolling"); no percentage resume mark /
resume_pct;weekly_scopednever pause-worthy;reserve_pct_per_daydefault 2 inert; config inert on merge (no workflow reads it).Test Command
bats --print-output-on-failure tests/test_agent_rate_limits_config.batsdon-petry commentedon Aug 30, 2026
Dev-Lead: Implementation Complete
Plan Execution
standards/agent-rate-limits.json— machine-readable single source of truth mirroringpr-limits.json(status: provisional, top-level_notewith sign-off + rationale,_schema_version, per-agent-typeagent_typesmap,org_wide.token_budget, exempt lists reused from pr-limits) (AC Addressing PR comments #1, Add multi-agent isolation strategy using git worktrees #2, Add coding standards & principles section to AGENTS.md #3)org_wide.token_budget— 5-hoursessionthreshold (default 90%), 7-dayweekly_allglide path (reserve_pct_per_day: 2, inert),weekly_scopednon-pausing,claude_priority: true(AC Add multi-agent isolation strategy using git worktrees #2)tests/test_agent_rate_limits_config.bats— 26-assertion contract test (AC Add workflow, environment, and orchestration guidance #4)standards/agent-rate-limits.md— companion doc citing the ADR, never restating numbers, namingdaily_run_budgetas the per-agent cost bound (AC Add stacked PR strategy and Epic-level workflow guidance #5, docs: document branch protection rules, rulesets, and auto-merge policy #7).github/workflows/agent-rate-limits-tests.yml— CI runner mirroringpr-limits-tests.ymlso the contract test is actually enforced (AGENTS.md CI-gate mandate)Post-ADR clarifications honored
Fixed windows (never called "rolling" in the token-budget block); no percentage resume mark /
resume_pct/hysteresiskey (guarded by a test);weekly_scopednever pause-worthy;reserve_pct_per_daydefault 2 kept inert; config inert on merge (no workflow reads it).Test Results
Files Changed
standards/agent-rate-limits.json(new): per-agent limits + circuit breakers + org-wide token-budget breaker; single source of truth, provisional/inert.standards/agent-rate-limits.md(new): companion standard, cites the ADR, points readers at the JSON instead of restating values.tests/test_agent_rate_limits_config.bats(new): JSON contract test (parseable, keys, positive-integer limits, threshold range, pause-worthy distinction, no-resume-mark / no-"rolling" guards)..github/workflows/agent-rate-limits-tests.yml(new): CI gate for the config + test.AGENTS.md: added the "Agent rate limits" discovery-index row.Notes
.github/workflows/agent-rate-limits-tests.yml. AC Add workflow, environment, and orchestration guidance #4 asks to "mirror the pr-limits config contract," which includes CI enforcement (pr-limits-tests.yml); AGENTS.md mandates gating bats in CI, and the repo treats an unenforced test as a defect (see thecanary-rollout-tests.ymlheader). The workflow is a verbatim-style mirror ofpr-limits-tests.yml(read-only, path-scoped, SHA-pinned). Trivial to drop if out of scope.compliance-audit,feature-ideation) is encoded as0(= n/a) rather than a faked positive value; the test asserts cooldown is a non-negative int and the other three limits are strictly positive.feat: implement issue #638 — [Phase 2] standards/agent-rate-limits.js…