fabro/lib/components
Bryan Helmkamp b32164b086
Add [run.limits] run budgets: halt runs on token/cost spend
A run can now carry an optional spend budget. New [run.limits] settings
table with max_cost (USD) and max_tokens; when accumulated LLM spend
exceeds either limit, the run halts immediately and fails with the
existing BudgetExhausted failure reason.

- RunBudget (fabro-model): thread-safe accumulator shared across the
  engine, agent sessions, hooks, and the prompt path. Charges per LLM
  response; queues one-shot 80% warnings drained into run notices.
- Enforcement is inline at every usage-recording site: the agent turn
  loop (interrupting like the wall-clock timeout via a new
  InterruptReason::BudgetExhausted), subagent sessions, the one-shot
  prompt path with schema-repair retries, context compaction, web_fetch
  summarization, and prompt/agent hooks (which skip once the budget is
  spent, matching their fail-open posture).
- Budget exhaustion terminates the run as an engine-level error
  (fabro_core::Error::BudgetExhausted, following the StallTimeout
  pattern) so fail edges are not followed, plus a between-stage gate for
  non-LLM stages and a run-start gate that makes a resumed
  budget-failed run fail fast until the limit is raised (spend is
  seeded from the billing projection).
- Exposed on the RunNamespace OpenAPI schema (RunLimitsSettings);
  Rust and TypeScript clients regenerated; docs updated.

Known gaps, by design for now: ACP external agents report no usable
per-response usage (cumulative UsageUpdate capture is a follow-up), and
post-run PR content generation is outside the engine.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 14:22:10 -04:00
..
fabro-acp refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-agent Add [run.limits] run budgets: halt runs on token/cost spend 2026-08-06 14:22:10 -04:00
fabro-automation Move GitHub coordinate validation to shared types 2026-08-03 14:53:46 -04:00
fabro-checkpoint refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-dump Remove the recorded pre-run push outcome, keep the push 2026-08-03 19:27:33 -04:00
fabro-environment refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-github Simplify async pull request creation 2026-08-04 14:51:29 -04:00
fabro-graphviz Merge pull request #686 from fabro-sh/fix/space-separated-node-classes 2026-07-29 22:31:48 -04:00
fabro-hooks Add [run.limits] run budgets: halt runs on token/cost spend 2026-08-06 14:22:10 -04:00
fabro-install refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-interview refactor: remove duplicated review target rendering and validation 2026-07-28 15:14:23 -04:00
fabro-llm feat(models): add Fireworks Kimi K3 Fast 2026-08-04 13:55:48 -04:00
fabro-manifest Remove the recorded pre-run push outcome, keep the push 2026-08-03 19:27:33 -04:00
fabro-mcp refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-mcp-store refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-sandbox fix(daytona): accept newer permission scopes 2026-07-31 12:22:08 -04:00
fabro-slack fix: stop a pipe in a link label from splitting Slack link markup 2026-07-28 15:31:20 -04:00
fabro-store Merge remote-tracking branch 'origin/main' into feat/async-pr-create 2026-08-04 15:04:24 -04:00
fabro-tool Move input scalar coercion to shared types 2026-08-03 19:17:03 -04:00
fabro-tracker refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-validate Merge remote-tracking branch 'origin/main' into feat/command-stdin-source 2026-07-29 11:37:27 -04:00
fabro-variable refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-workflow Add [run.limits] run budgets: halt runs on token/cost spend 2026-08-06 14:22:10 -04:00