fix(compression): decay head protection after restart when a persisted summary exists - #69342
Merged
Conversation
Contributor
૮ >ﻌ< ა ci reviewrunning on 17e6617 CI timingsCI timings · View jobWall time 7m17s vs 9m59s (-27.0%). 12 job(s) slower, 6 faster, 2 unchanged.
|
Collaborator
teknium1
force-pushed
the
salvage/57835-protect-head-decay
branch
from
July 22, 2026 14:44
81c6bf2 to
af9a21d
Compare
protect_first_n decay state (compression_count / _previous_summary) is in-memory only, so a gateway restart re-protected the persisted handoff summary and head fossils, growing the head unboundedly across restart+compaction cycles (#57814). _effective_protect_first_n now probes a bounded resumed-head window for a persisted handoff summary (by metadata or content prefix) and decays protection when one is found, before compress_start is computed. The first post-restart compaction self-heals: stacked summary fossils are folded into the next summary prompt instead of preserved verbatim, rehydration is rolled back on abort, deterministic fallback carries a bounded redacted previous-summary snapshot, and forced user-leading merged summaries keep the live tail request after the summary end marker so they stay rehydratable. Squashed reapply of the 12-commit series from PR #57835 onto current main (branch was 1210 commits behind; single add/add conflict with the task-snapshot grounding helpers resolved by keeping both). Fixes #57814.
…dd restart-simulation test - Three '_previous_summary == "fresh summary"' exact pins and one transcript-wide fossil-absence pin predated main's deterministic task-snapshot grounding (761a0b1), which prepends a '## Historical Task Snapshot' section to stored summaries and may quote a folded head turn inside the handoff. Re-pin the contracts (fresh body present, fossil absent from non-summary messages) instead of exact strings. - Add test_restart_simulation_fresh_compressor_does_not_reprotect_head: a fresh ContextCompressor over a transcript containing a persisted handoff summary computes the same decayed protected-head boundary (compress_start base) as a live already-compacted process, and the first post-restart compaction does not preserve pre-restart head fossils (#57814).
…he decay scan Composing #57835's multi-fossil summary scan with #47274's merged-handoff unwrap: when the restart-decay path pulls a merged handoff into the compression window, its genuine prior-tail user content must enter the summarizer input (folded into the fresh summary) rather than being dropped with the summary row. Standalone handoffs still drop. The continuity test now pins the composed contract: recovered verbatim OR via summarizer input, never silently deleted, never duplicated.
teknium1
force-pushed
the
salvage/57835-protect-head-decay
branch
from
July 22, 2026 15:58
af9a21d to
17e6617
Compare
This was referenced Jul 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
After a gateway restart, the first compaction no longer re-protects the persisted handoff summary and pre-restart head turns, so the head stops growing one fossil layer per restart+compaction cycle. Root cause:
protect_first_ndecay keyed off in-memory state only (compression_count/_previous_summary), and_previous_summaryrehydration from the persisted handoff ran AFTERcompress_start = _protect_head_size(...)was computed.Changes
agent/context_compressor.py:_effective_protect_first_n(messages)now probes a bounded resumed-head window (protect_first_n + 4messages past the system prompt) for a persisted handoff summary (metadata key or content prefix) and decays protection when found — BEFORE boundary computation, so a restarted process decays exactly like a live one. Applies to in_place mode too.agent/context_compressor.py: first post-restart compaction self-heals — stacked summary fossils (incl. beyond-probe and tail-protected ones) fold into the next summary prompt instead of being copied forward verbatim;_previous_summaryrehydration rolls back on compaction abort; deterministic fallback carries a bounded redacted previous-summary snapshot; forced user-leading merged summaries keep the live tail request after the summary end marker so they stay rehydratable.tests/agent/test_context_compressor_summary_continuity.py: 12 new regressions from the source PR (restart fossil folding, stacked handoffs, probe boundary in/out, zero-protect, fallback preservation, abort-then-retry, merged-tail rehydration) plus a restart-simulation test: a freshContextCompressorover a transcript containing a persisted handoff computes the same decayed protected-head boundary (compress_startbase) as a live already-compacted process.tests/agent/test_context_compressor.py: no-system resumed-handoff role-ordering regression.Validation
bash scripts/run_tests.sh tests/agent/ -k 'protect or head or decay'test_context_compressor.py+test_context_compressor_summary_continuity.pySibling guards green:
test_compression_rotation_state.py,test_resume_stale_active_task.py,test_summary_prefix_tool_use.py(26 passed). Ruff + windows-footguns clean.Credit
Salvaged from #57835 by @harjothkhara (12-commit series squash-reapplied onto current main with authorship preserved; branch was 1210 commits behind — single add/add conflict with the task-snapshot grounding helpers resolved by keeping both). Follow-up commit adapts three exact-string test pins to main's deterministic task-snapshot grounding (761a0b1) and adds the restart-simulation test.
Fixes #57814.
Infographic