Skip to content

fix(contextview): never trim a compaction summary before newer raw rows - #1116

Merged
chen-ran merged 2 commits into
felinics:mainfrom
ChrAlpha:fix/summary-must-keep
Sep 4, 2026
Merged

chen-ran merged 2 commits into
felinics:mainfrom
ChrAlpha:fix/summary-must-keep

Conversation

@ChrAlpha

@ChrAlpha ChrAlpha commented Aug 31, 2026 •

Copy link
Copy Markdown
Member

Problem

Selection treats a compaction summary as ordinary droppable history. The summary sits at the oldest anchor position, so under history-budget pressure it is the first fragment evicted — a successful compaction pass renders zero value at exactly the moment the budget needs it, and the compacted span is silently re-lost.

Live evidence (500-turn LongMemEval haystack, window 32000, budget plan history_budget≈6.9k): after a successful automatic pass (438 rows covered, 12k-char summary), every subsequent turn's selection_decisions showed the summary fragment as decision=dropped, retention_tier=None while newer raw rows survived; the rendered breakdown was byte-identical to a no-compaction run. ~90s and ~125k summarizer tokens spent for zero rendered value.

Fix

KindConversationSummary fragments are must-keep in selection. Trimming funds itself from raw rows; the compacted span stays represented. The new test reproduces the production shape (summary dropped first among 12 drops) and pins the fixed behavior (summary kept, oldest raw rows fund the trim, newest raw row kept).

Trade-off, disclosed: where the history budget cannot hold even the summary, selection now fails closed (protected overflow) instead of silently re-losing the compacted span; that regime previously produced an unusable context either way.

Verification

  • go test over contextview, application, agent/context/…, native: green; go test -race contextview + application: green; golangci-lint run (2.10.1): clean.
  • Live harness validation on this branch (same seeded protocol as the reproduction): post-compaction turns now render conversation_summary (est 1,577) alongside the trimmed raw tail on every turn, and the cross-turn prompt-cache classification stays hit/stable across the compacted render.

⚠️ No human QA — this PR has not been verified by a human yet. Remove this line once a human confirms the happy path.

Selection treated conversation summaries as ordinary droppable history, so
under history-budget pressure the oldest fragment - the summary - was the
first eviction: a successful compaction pass rendered zero value exactly
when the budget needed it (observed live: the persisted summary fragment
left selection as decision=dropped while newer raw rows survived). Summary
fragments are now must-keep, so trimming funds itself from raw rows and
the compacted span stays represented.

Where the history budget cannot hold even the summary, selection now fails
closed (protected overflow) instead of silently re-losing the compacted
span; that regime previously produced an unusable context either way.

Claude-Session: https://claude.ai/code/session_01BQNmA3AKE3nh6AnArrG54g
@ChrAlpha
ChrAlpha requested a review from a team as a code owner August 31, 2026 05:54
…e selection

The must-keep tier meant a summary larger than the history slot turned
into a protected overflow: the whole selection failed closed exactly in
the small-window regime compaction exists to serve. Under protected
pressure the selector now shortens must-keep conversation summaries —
UTF-8 safe, head-preserving, with a model-visible truncation notice and
the </summary> wrapper re-closed — and fails closed only when even the
minimum viable summary cannot fit.

Allocation is feasibility-preserving: the trim-notice cost is charged
against the summary ceiling only when droppable rows actually force
spatial drops (a summary-only selection keeps the full budget, and a
summary that fits raw budget but would squeeze the notice out yields
the difference instead of failing); under-target summaries settle at
their actual cost so their unused share funds oversized ones; and the
geometric descent probes exactly the floor before giving up, since
mixed-density (CJK-heavy) text can otherwise overshoot past a floor
size that fit. Applied shrinks surface as summary_budget_truncate
edits.
@chen-ran
chen-ran merged commit a2a6110 into felinics:main Sep 4, 2026
14 checks passed
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.

2 participants