Phase 3: wire AgentBudgetGuard onto the LLM USD cost seam - #38
Open
cryptoxdog wants to merge 2 commits into
Open
Phase 3: wire AgentBudgetGuard onto the LLM USD cost seam#38cryptoxdog wants to merge 2 commits into
cryptoxdog wants to merge 2 commits into
Conversation
Activate AgentBudgetGuard in LlmService.execute against real USD signals: - Admission/reserve: before each call the guard is seeded with the day's real persistent spend (getDailySpend → llm_usage) and reserves the call's real pre-dispatch estimate (router.route().estimatedCost). If the reservation cannot fit even after the guard downshifts its ADR-0008 mode, the call is deferred BEFORE any spend — earlier and stricter than the previous post-hoc `spent >= cap` check, which ignored the incoming call's cost. - Reconcile: after a successful call the guard reconciles the real response.cost; a post-dispatch breach flips mode to `stop` (logged, not thrown — the response was already paid for). - getBudgetMode() exposes the current ADR-0008 mode so callers can route to a cheaper tier / narrow scope under pressure. Opt-in via DAILY_SPEND_CAP; unset ⇒ guard inert, behaviour unchanged. Replaces the ad-hoc enforceDailyCap. budget_violations persistence stays deferred (its NOT NULL FK to agent_jobs needs an agent-job execution model that does not yet exist) — recorded in TODO.md. RUNBOOK documents the guard and the new env var. Validated: tsc --noEmit 0 errors, eslint src/ 0 errors, vitest 149/149, manifest:check clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SjcHn8jZErKo37ZJi6qybX
The `typecheck` gate (tsconfig.check.json, which includes tests/) inferred DAILY_SPEND_CAP as `number` from baseConfig, so the DAILY_SPEND_CAP: undefined override in the "cap unset" case failed with TS2322. Widen the field to `number | undefined`. No behavior change; the 4 budget-guard tests still pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SjcHn8jZErKo37ZJi6qybX
|
This was referenced Jul 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Stacked PR — 3 of 3
Top of the stack. Stacked on #37 (Phase 2), which is stacked on #36 (Phase 1). Base is
claude/new-session-br7qjb-phase-2; this PR's diff shows only Phase 3. Merge #36 then #37 first (or retarget tomainonce they land).What this does
Activates
AgentBudgetGuard(ADR-0008) inLlmService.executeagainst real USD signals — the seam left deferred in Phase 2.getDailySpend()→llm_usage); reserves the call's real estimate fromrouter.route().estimatedCostresponse.costgetLlmService().getBudgetMode()exposes the ADR-0008 mode (normal→stop) for cheaper-tier routingKey behavioral win: a call is now deferred before any spend when its estimate wouldn't fit under the cap — earlier and stricter than the old
enforceDailyCap, which only reacted after the day was already over. Opt-in viaDAILY_SPEND_CAP; unset ⇒ guard inert, behavior unchanged.Deferred (documented, not faked)
budget_violationsrows are still not persisted: that table'sjob_idisNOT NULL REFERENCES agent_jobs(job_id), and no agent-job execution model exists yet to own the parent row. Left inTODO.mditem 3 with the exact unblock trigger.Validation
tsc --noEmit0 errors ·eslint src/0 errors ·vitest149/149 (4 new budget-guard-on-LLM tests) ·manifest:checkcleanGenerated by Claude Code