Skip to content

feat(context): token-budget accounting for context assembly (bo-ne9k)#32

Merged
scbrown merged 1 commit into
mainfrom
bo-ne9k-token-budget
Jun 28, 2026
Merged

feat(context): token-budget accounting for context assembly (bo-ne9k)#32
scbrown merged 1 commit into
mainfrom
bo-ne9k-token-budget

Conversation

@scbrown

@scbrown scbrown commented Jun 28, 2026

Copy link
Copy Markdown
Owner

What

Adds a [context] budget_unit = "line" | "token" toggle so the context-assembly budget can be enforced in tokens instead of source lines.

Why (bo-ne9k)

Budgets were counted in LINES everywhere, but agents have TOKEN budgets — a 50-line dense-code chunk costs far more tokens than 50 lines of comments. Line-counting makes injection size unpredictable against the model window.

How

  • New BudgetUnit enum (serde lowercase, FromStr/Display) + estimate_tokens() (deterministic ~chars/4, no tokenizer files) + chunk_cost() helper in search::context.
  • In token mode each chunk's cost comes from its content; budget_lines and all derived caps (max_chunk_lines, pin reserve, bridged/knowledge budgets) are interpreted in tokens.
  • budget_unit threaded through ContextConfig and the 3 live builders (CLI context, HTTP context, hook). calibrate/review keep line mode via ..default().
  • Config knob + docs/configuration.md.

Default stays line → zero behavior change unless opted in.

Tests

  • test_estimate_tokens, test_budget_unit_roundtrip
  • test_token_budget_enforcement — a huge-line-span / tiny-content chunk is admitted (proving tokens, not lines, are counted) and an over-budget chunk is dropped
  • config parse (budget_unit = "token") + default (line) assertions

cargo build/clippy clean (0 errors); all context + config tests pass.

🤖 Generated with Claude Code

Budgets were counted in source LINES everywhere, but agents have TOKEN
budgets and a 50-line dense-code chunk costs far more tokens than 50 lines
of comments. Add a `[context] budget_unit = "line" | "token"` toggle.

In token mode each chunk's cost is estimated from its content (~chars/4,
deterministic, no tokenizer files) instead of its line span, so injection
size is predictable against the model window. `budget_lines` and all derived
caps (max_chunk_lines, pin reserve, bridged/knowledge budgets) are then
interpreted in tokens. Default stays `line` — zero behavior change unless
opted in.

- BudgetUnit enum (serde lowercase, FromStr/Display) + estimate_tokens()
  + chunk_cost() helper in search::context
- budget_unit threaded through ContextConfig and the 3 live builders
  (cli/context, http/handlers/context, cli/hook); calibrate/review keep
  line mode via ..default()
- config: [context].budget_unit knob + docs/configuration.md
- tests: estimate_tokens, unit roundtrip, token-mode budget enforcement
  (huge-span/tiny-content chunk admitted; over-budget chunk dropped),
  config parse + default assertions

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UHPGrbayqXRFaMHuvs6yLX
@scbrown
scbrown merged commit 3b04054 into main Jun 28, 2026
5 checks passed
@scbrown
scbrown deleted the bo-ne9k-token-budget branch June 28, 2026 02:25
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