fix(runtime): make the compaction landing target reachable (#74) #1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/issue-74-reachable-compaction-target"
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?
Closes #74 (the original tracker issue is not on this forge yet —
migrate-from-github.shimported git history only: 0 issues, 0 PRs, 0 labels. See note at the bottom.)Two arithmetic defects in the R78 compaction path
D1 — the estimate ignored the undroppable prompt. The loop decided with
est = pt * kept_chars / total_chars, but that ratio covers only the DROPPABLE transcript whilept(usage.prompt_tokens) also contains the UNDROPPABLE system block — operating core + soul +MEMORY tail + tool schemas, ~13,700 tokens measured on this host and growing with the memory tail.
The estimate understated the real prompt by exactly that overhead, so the loop dropped to its
one-message floor and destroyed the live transcript. This is the mechanism behind
"the 32k window lobotomizes you / duplicated answers".
D2 — the landing target was unreachable. Target was 25% of window = 8,192 tokens on a 32,768
window, below what the smallest possible context already costs. Unreachable, so every turn paid a
summary, lost detail, and re-fired the trigger.
What this does
Implements Heike's shape —
target = max(0.25·cw, overhead + margin)— plus the case she leftopen: when even the floored target cannot sit under the trigger with headroom, compaction is not
the lever, so the code says so instead of thrashing.
Adds
prompt_overhead_tokens();compaction_target() = max(0.25·cw, overhead + 0.05·cw),declared unreachable when it leaves <10% of the window as headroom under the trigger;
estnowadds the overhead back (equals
ptwhen nothing is dropped); overflow protection trims to0.75·cw instead of collapsing, logged once. Backward compatible: a one-char system block gives
overhead 0, so the old 200/500 and 1000/2100 landings still pass.
The R78 ruling itself is untouched — this fixes arithmetic underneath it, not the ruling.
Verification (suite named, because I got this wrong once already)
services/runtime/testswith this patch on the forge head7f13629: 145 passed, 3 skippedservices/runtime/tests/test_issue74_compaction_target.py(6 tests, also verified alone)Migration note
migrate-from-github.shon this head brings git history (branches arrive;mainis complete) butnot issue/PR/label data. The original #74 with its discussion lives on GitHub
(nstern-digital-solution/TreeGent) until the tracker data is imported.
verified — see follow-up comment
Verified review — code, math, and execution.
Suites (run on this branch, local checkout at
51bbad7):tests/test_issue74_compaction_target.py— 6/6 passedMath checked by hand — the target table is correct:
None(unreachable) — that IS the reported failure mode, and pre-#74 the loop answered it by dropping to the one-message floorD1 diagnosis is right and the fix is anchored correctly:
est == ptwhen nothing is dropped (overhead + transcript_pt = pt at acc=0), so the loop now stops the moment the TRUE prompt — undroppable system block included — lands under target. The old ratio scaled the overhead away as if it could be dropped; that's the lobotomy mechanism.What I like specifically:
test_reachable_window_still_lands_at_25_percentis the regression guard that matters: R78's 25% landing is untouched anywhere it was already achievable — plus the over-drop assertion (one-more-message wouldn't fit)usage.prompt_tokens; no hardcoded windows — per-model config decidesOne nit (non-blocking):
prompt_overhead_tokenscounts system-message chars only; tool schemas that ride in the request outside message content would sit inptbut not in the estimate — understatingest_afterslightly on tool-heavy models. Themin(est, pt)clamp and the 10% headroom absorb this today; if #75 lands real per-model windows, worth revisiting the estimate together with it.Approving — merge gate is yours, Felix (approvals whitelist = felix/rosa; author can't approve her own PR).
— Heike