Skip to content

feat(router): hard cost-envelope enforcement — warn/downgrade/block (A6) - #116

Merged
mrobinson2 merged 2 commits into
mainfrom
feat/a6-hard-cost-enforcement
Jul 12, 2026
Merged

feat(router): hard cost-envelope enforcement — warn/downgrade/block (A6)#116
mrobinson2 merged 2 commits into
mainfrom
feat/a6-hard-cost-enforcement

Conversation

@mrobinson2

Copy link
Copy Markdown
Owner

What

Extends the v1.5 cost-governance layer from observe-only to enforce-with-downgrade/block for every router path, behind a single env knob. Default is warn — behavior identical to today (ship-dark safe).

Provenance: port of the upstream private deployment's just-merged M5 "acting budget enforcement". The decision module (services/model-router/budget_enforcement.py) was designed there as a portability contract — stdlib-only, framework-free, zero host imports — and is vendored verbatim (docstring host references sanitized). The host wiring is thin and adapted to this router's shape.

Semantics

Mode (BUDGET_ENFORCE_MODE) Over-budget behavior
warn (default) Serve the requested tier + budget_enforce WARN log — exactly the pre-A6 behavior
downgrade Serve BUDGET_FALLBACK_TIER (default gpt4o-mini); response carries X-Router-Budget-Downgrade: <from>-><to> + _router.budget_downgraded_from
block HTTP 429 with machine-readable budget_exceeded body (error, tier, spent_usd, limit_usd, mode)

Guarantees:

  • Invalid mode fails open to warn (a config typo must not brick the router).
  • The fallback tier is exempt — it is the designated floor; an unregistered or self-referential fallback degrades to warn rather than stranding requests.
  • No selftest/probe exemption needed — this router has no selftest traffic (unlike upstream).

Path coverage (where this router differs from upstream)

Path Coverage
/v1/chat/completions Enforcement wraps select_tier as its final stage — covers explicit tiers, persona routing, ephemeral passthrough tiers, and the Anthropic direct-SDK dispatch inside _call_model. The pre-existing gpt4o-miniphi4 over-budget redirect is untouched.
/v1/messages (native Anthropic, bypasses select_tier) Explicit check. block returns an Anthropic-shaped 429 (rate_limit_error) so anthropic_messages transports parse it like any upstream error. Divergence from upstream: this router has no Anthropic→OpenAI response translation, so downgrade only takes effect when BUDGET_FALLBACK_TIER is itself Anthropic-backed; otherwise it degrades to warn (module's fallback-unavailable rule). This path also now records its spend (streaming + non-streaming, via list-price estimate) — previously it recorded nothing, which would have left enforcement blind on the exact path the feature was built for.
/v1/embeddings (#112, no tier at all) Decision: embeddings spend IS budgeted. It now accrues to a dedicated embeddings ledger bucket (visible in daily_cost_rollup) capped by EMBEDDING_DAILY_BUDGET_USD (default 1.00; 0 disables, mirroring PER_CALLER_DAILY_USD). No same-vector-space downgrade target exists (the model pin is the point), so downgrade degrades to warn here; block 429s. Also gains the aaf-0005 per-caller budget gate for parity with the chat endpoints.

Config

  • BUDGET_ENFORCE_MODEwarn (default) | downgrade | block
  • BUDGET_FALLBACK_TIER — default gpt4o-mini
  • EMBEDDING_DAILY_BUDGET_USD — default 1.00; 0 disables
  • EMBEDDING_PRICE_PER_MTOK — list-price estimator fallback (default 0.02, matches text-embedding-3-small)

Plumbed through .env.example, root + mac-site compose, and both Terraform router sidecars (hermes pod + memory-governor pod) via new validated module variables (budget_enforce_mode, budget_fallback_tier, embedding_daily_budget_usd). Dockerfile now ships budget_enforcement.py alongside main.py.

Test evidence

before: 200 passed
after:  237 passed  (+37 in services/model-router/tests/test_budget_enforcement.py)

New coverage: pure module (resolve_mode normalization + invalid-mode fail-open, decide matrix, block_detail/downgrade_header shapes), warn-is-ship-dark (select_tier + endpoint unchanged, no header/meta), downgrade (+header, +_router meta, generic across tiers, unavailable-fallback degradation), block (429 before any upstream call), native /v1/messages (warn serves direct, block 429 Anthropic-shaped, non-Anthropic fallback degrades to warn, Anthropic fallback served natively with header, spend now recorded), embeddings (bucket accrual, warn/block/downgrade, zero-cap disable, per-caller gate), and floor-tier exemption.

scripts/scan-internal-refs.sh: clean. docker compose config: valid. terraform fmt -check: clean.

🤖 Generated with Claude Code

Michael Robinson and others added 2 commits July 12, 2026 03:05
… paths (A6)

Per-tier daily budgets only ever warned; upstream evidence shows a Claude
tier running ~25x its daily budget with nothing but budget_exceeded WARN
lines. This vendors the upstream private deployment's stdlib-only decision
module (budget_enforcement.py: resolve_mode / decide / BudgetDecision /
downgrade_header / block_detail) verbatim and wires it into every router
path behind BUDGET_ENFORCE_MODE:

- warn (default): behavior unchanged — serve + WARN log (ship-dark safe)
- downgrade: serve BUDGET_FALLBACK_TIER (default gpt4o-mini) and mark the
  response with X-Router-Budget-Downgrade + _router.budget_downgraded_from
- block: 429 with a machine-readable budget_exceeded body

Coverage:
- /v1/chat/completions: enforcement wraps select_tier as its final stage
  (covers Anthropic direct-SDK dispatch and ephemeral passthrough tiers;
  the pre-existing gpt4o-mini->phi4 redirect is untouched)
- /v1/messages (native Anthropic path, bypasses select_tier): explicit
  check; block returns an Anthropic-shaped 429; downgrade only serves an
  Anthropic-backed fallback (response must stay Anthropic-shaped),
  otherwise degrades to warn. The path also now records its spend to the
  daily ledger (streaming + non-streaming) — it previously recorded
  nothing, which would have left enforcement blind on this exact path
- /v1/embeddings (no tier at all): spend now accrues to a dedicated
  'embeddings' ledger bucket capped by EMBEDDING_DAILY_BUDGET_USD (0
  disables, mirroring PER_CALLER_DAILY_USD); no same-vector-space
  downgrade target exists so downgrade degrades to warn; block 429s.
  Also gains the aaf-0005 per-caller budget gate for parity

Fail-open guarantees: invalid mode -> warn; unregistered/self-referential
fallback -> warn (the fallback tier is the designated floor and is exempt).
No selftest/probe traffic exists in this router, so nothing needs a spend
exemption. Dockerfile now ships the new module alongside main.py.

Tests: 200 -> 237 (37 new in tests/test_budget_enforcement.py) covering
the pure module, warn-is-ship-dark, downgrade + header/meta, block 429,
both bypass paths, fallback exemption, and invalid-mode fail-open.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…terraform

BUDGET_ENFORCE_MODE + BUDGET_FALLBACK_TIER + EMBEDDING_DAILY_BUDGET_USD
(and the EMBEDDING_PRICE_PER_MTOK estimator fallback) documented and
defaulted ship-dark (warn) everywhere the router's budget env already
lives: .env.example, root docker-compose.yml, deploy/mac-site compose
anchor, and both Terraform router sidecars (hermes pod + memory-governor
pod, the latter carrying the embeddings cap for governor vector
retrieval). New module variables budget_enforce_mode (validated),
budget_fallback_tier, embedding_daily_budget_usd. Router README gains a
'Budget enforcement' section with the mode table and per-path semantics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mrobinson2
mrobinson2 merged commit 6788def into main Jul 12, 2026
11 checks passed
@mrobinson2
mrobinson2 deleted the feat/a6-hard-cost-enforcement branch July 12, 2026 08:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant