Skip to content

feat: orçamento de tokens por run/fase + timeout de fase com corte mid-stream - #49

Merged
elberrd merged 1 commit into
mainfrom
feat/orcamento-tokens
Aug 23, 2026
Merged

feat: orçamento de tokens por run/fase + timeout de fase com corte mid-stream#49
elberrd merged 1 commit into
mainfrom
feat/orcamento-tokens

Conversation

@elberrd

@elberrd elberrd commented Aug 23, 2026

Copy link
Copy Markdown
Owner

Contexto

Terceira PR do estudo de consumo (após #47 e #48). Não existia nenhum teto de tokens no runtime: run.tokens era acumulado e nunca comparado a limite, fases agent não tinham timeout nem cap de turnos (os CLIs claude/pi não expõem --max-turns — verificado), e um --resume resetava o medidor. No ledger real: um run de 112M tokens e uma única fase de 36M.

O que muda

Três chaves novas no stop: (todas ligadas por default, com folga generosa; 0 desliga; tolerantes a typo como as demais):

chave default comportamento
token_budget 30M teto de vida do run (resume carrega baseline de sessions.total_tokens, fail-open); warnings únicos em 50%/80% (budget_warning); parada limpa budget_exhausted, checada entre fases E entre sends
phase_token_budget 8M teto de uma fase (sends+correções+relay legs); o filho do engine é cortado mid-send no espaço restante (novo modules/agent-limits.mjs: SIGTERM→SIGKILL, armado nos 3 adapters). Nunca arma relay — refazer noutra engine re-gastaria tudo
phase_timeout_minutes 50 kill com <500k tokens = CLI travado ⇒ tratado como crash (1 retry mesma engine, depois relay); kill com gasto real ⇒ StopCondition — nunca re-paga a fase

Run parado por orçamento não troca de LLM sozinho: pausa com o painel calmo apontando o knob (alinhado à decisão do Elber de que corte seco cego não é a solução). Cursor não reporta usage ⇒ tetos de token não o enxergam (timeout aplica; documentado).

Extras: label do outcome vira "budget exhausted (time or tokens)" (+ espelho do viewer — a lição do PAGE), tracer.sessionTokens() fail-open, DOCS.md §9.7 (tabela nova) e cookbook run_fda.md (regra: reportar o gasto e deixar o engenheiro decidir entre corrigir a abordagem e subir o knob — nunca subir sozinho).

Testes

test/fia-token-budget.test.js (8 testes, harness de engines fake): defaults/0-off/typos; armLimits (corte único no teto, timeout, finish limpa e reporta); orçamento de run parando a 2ª fase com warnings 50/80 exatamente uma vez; orçamento de fase isolado; baseline no resume (e run fresh ignora); timeout hung (2 tentativas → EngineFailure) vs busy (StopCondition); asserts de fonte nos 3 adapters. deepEqual do stopPolicyOf existente atualizado. Suite completa 1457 pass + lint limpo (re-testada pós-rebase na main).

🤖 Generated with Claude Code

https://claude.ai/code/session_01NPYaKxNaVRhPumKbawFNT3

…com corte mid-stream

Não existia NENHUM teto de tokens/custo no runtime: run.tokens era acumulado e
nunca comparado a limite, fases agent não tinham timeout nem max-turns (os CLIs
não expõem), e um resume resetava o medidor. Medido em projeto real: um run de
112M tokens e uma única fase de 36M.

- stop.token_budget (default 30M, LIGADO): teto de VIDA do run — resume carrega
  o baseline de sessions.total_tokens (fail open); warnings únicos em 50%/80%
  (evento budget_warning) e parada limpa como budget_exhausted, checada entre
  fases e entre sends.
- stop.phase_token_budget (default 8M, LIGADO): teto de UMA fase (sends +
  correções + relay legs); o filho do engine é cortado mid-send no espaço
  restante (SIGTERM→SIGKILL em modules/agent-limits.mjs, armado nos 3 adapters
  via request.limits). Nunca arma relay — refazer noutra engine re-gastaria.
- stop.phase_timeout_minutes (default 50, LIGADO): kill com quase nenhum gasto
  (<500k) = CLI travado, tratado como crash (1 retry mesma engine, depois
  relay); kill com gasto real = StopCondition, nunca re-paga a fase.
- Label do outcome corrigido para "budget exhausted (time or tokens)" (outcome
  + espelho do viewer); tracer ganha sessionTokens() (reader fail-open).
- fia.config.yaml (3 chaves no bloco stop), DOCS.md §9.7 (tabela + parágrafo) e
  cookbook run_fda.md atualizados — run parado por orçamento nunca troca de LLM
  sozinho: decisão humana no knob.
- Testes em test/fia-token-budget.test.js (harness de engines fake): defaults
  ON/0-off/typos, armLimits (corte único, timeout, finish), orçamento de run
  com warnings 50/80, orçamento de fase, baseline no resume (e fresh ignora),
  timeout hung vs busy, asserts de fonte nos 3 adapters.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPYaKxNaVRhPumKbawFNT3
@elberrd
elberrd merged commit 53403de into main Aug 23, 2026
7 checks passed
@elberrd
elberrd deleted the feat/orcamento-tokens branch August 23, 2026 20:55
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