context_pack ships over-budget responses with budget_exceeded: false — the payload contradicts itself, and the safety net stays silent #212
Labels
No labels
code-review
correctness
dos
performance
security
severity/high
severity/low
severity/medium
tech-debt
Kind/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
h-dv/code-index#212
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found by dogfooding v0.27.0-rc (
caa62fe) against this repository, over the live daemon.Measured, two budgets an order of magnitude apart
Same seed (
symbol_ids: [736650],check_index_freshness), onlytoken_budgetvaried:token_budgettokens_usedbudget_exceededfalsetargets,dependencies,dependents,witness_path,test_role_filesfalseAt 256,
allocationreadsdiscretionary: 3withtargets/dependencies/dependents/small/redistributedall0, andbudget.omitted_*accounts for everything dropped (omitted_targets: 1,omitted_dependents: 12,omitted_dependencies: 2,omitted_test_files: 2,omitted_witness_hops: 3). So the assembler dropped every discretionary item it had and the response STILL came back 51.6% over budget.The payload contradicts itself on its face
Whatever the internal cause, one response cannot honestly say all three of:
token_budget: 256tokens_used: 388budget_exceeded: falseAnd the tool's own documented contract makes it sharper. The description states the budget is "strict-bounded on the complete serialized response" and that
budget_exceeded: truemarks "the only case where the response can exceed the budget" — namely when the core alone did not fit. The 256 row IS that case: the core alone did not fit, and the flag reportsfalse.crates/mcp-server/src/server.rs:13024computes it the way you would want:388 > 256is true, so the shippedtokens_usedand the shipped flag cannot both be describing the same measurement.Hypothesis for the mechanism — stated as a hypothesis, not a finding
crates/mcp-server/src/server.rs:12966:The value written into
tokens_usedand the value returned asusedare two different measurements of two different payload states — the return is taken after the last write. The trim loop then breaks onused <= token_budget, andbudget_exceededis computed fromused, while the caller readstokens_used. That would let the two disagree in exactly the observed direction. I have not proved this is the cause — it is the reading that fits, and whoever fixes it should confirm by instrumenting both values rather than trusting this paragraph.A second candidate, not exclusive with the first:
measure()runs onrespbeforeanswer_provenanceandevidence_gapsare attached, so neither block is inside the bound at all. On the 256 response those two blocks are a large fraction of 388 tokens, which would explain why the overshoot is proportionally far worse at small budgets (+132 at 256, +28 at 2000) — a roughly fixed unmeasured tail.The safety net did not fire
server.rs:12979calls the trim loop a SAFETY NET and says:The caller was handed an over-budget response, and
safety_net_dropsis absent from both replies. (Absent is correct-by-design here —mcp_smoke.rs:4857documents and asserts that it is emitted only when non-zero — so the finding is not the absence; it is that the arithmetic was wrong and the net that exists to catch exactly that stayed at zero.)That comment is also now falsified as written: "by construction it never fires" is only true if the arithmetic is right, and the arithmetic is not right.
Why the tests did not catch it
The comment says "CI can assert across a budget sweep that it stayed silent" — and a sweep asserting
safety_net_dropsis absent will pass happily while every response in the sweep is over budget, because the net is downstream of the same faulty measurement. The sweep asserts the net stayed quiet; it never assertstokens_used <= token_budget. That is the vacuity: the gate measures the alarm, not the property.What the fix must do
answer_provenanceandevidence_gapsincluded.tokens_usedand the valuebudget_exceededis computed from must be the same number, by construction rather than by coincidence.budget_exceeded: trueand say what could not be shed. The current third option — quietly overshoot and reportfalse— is the one that must go.Mutations the fix must run
tokens_used <= token_budgetacross a budget sweep (256, 512, 1000, 2000, 4000, 16000) with a seed that has real dependents. On today's code this must FAIL at the low end — if it passes, the assertion is not measuring the shipped payload.budget_exceededa constantfalse→ the over-budget assertion must go red. If it stays green the flag is untested.answer_provenancefrom whatever the final measurement covers → the sweep must go red at small budgets, proving the measurement spans the whole response.used < args.token_budget(off by one) → a boundary case must go red, proving the sweep has a case exactly at the budget.Related: this is the same shape as #209/#210 — a disclosure that reports a state it did not measure — but here the number and the flag derived from it are in the same JSON object, disagreeing with each other.
changed_symbolsships a bareref_count: 0wheresearch_symbolssays the zero was never measured — same symbol, same index, opposite honesty #213evidence_gaps.semanticstells the reader to consultpartial_sources, and no tool ever emits that field #216Fixed in
1201be4— "context_pack measures the response it ships, and the flag says so" — onmaster, shipping in v0.27.0.context_packshipped over-budget responses withbudget_exceeded: false. Six of eleven budgets were over. The cause was that theevidence_gapsblock attached above the router sat outside the budget arithmetic entirely. The flag and the number are now one measurement of the bytes actually shipped.Closing on merge.