Hardening follow-up to the #69619 review fix. The previous regression
byte-pinned only the rescued pre-#69619 generation; older frozen entries
were covered solely by fragment assertions and a self-matching loop that
cannot detect a frozen entry mutating (the loop tests each entry against
itself).
- Pin all four _HISTORICAL_SUMMARY_PREFIXES generations as literals in
_FROZEN_PREFIX_GENERATIONS and assert order-sensitive tuple equality
plus detect/strip for each
- State the prepend-only contract explicitly on the tuple: never mutate
or reorder existing entries
Negative controls verified: mutating, dropping, or reordering a frozen
entry each fail the new test, while the legacy self-matching loop still
passes under mutation — confirming the closed coverage gap.
Address review on #69619: the previous commit mutated the newest frozen
entry in _HISTORICAL_SUMMARY_PREFIXES and never froze the live prefix it
retired (the generation with both the four-heading discard clause and
the tools-active clause). A summary persisted immediately before
upgrading was therefore treated as an ordinary message on
resume/re-compaction, keeping the old handoff text embedded in the body.
- Prepend the exact pre-change live prefix as a new frozen entry
(newest-first), leaving all existing frozen entries byte-identical
- Restore the Jul 2026 (#65848 class) frozen entry to its original
four-heading text
- Pin the retired generation as a literal in
test_summary_prefix_semantics.py so mutating or dropping it fails CI
- Make the #65848 tool-use regression position-agnostic (match the
pre-clause generation by content, not tuple index)
Verified byte-identity of both rescued generations against the parent
commit. 233 focused prefix/resume/compressor tests pass.
Remove three directive-heavy section headers from both the LLM
and deterministic summary templates that caused the agent to
resume stale tasks after context compression:
- Historical In-Progress State
- Historical Pending User Asks
- Historical Remaining Work
These sections read as actionable instructions even within a
REFERENCE-ONLY wrapper, hijacking the user's latest message.
The remaining sections are purely descriptive/past-tense.
Frozen prefix copies in _HISTORICAL_SUMMARY_PREFIXES updated
to match. Test 8/8 passed.
The prompt consolidation above retires the carveout-era prefix. Without a
frozen copy in _HISTORICAL_SUMMARY_PREFIXES, summaries persisted by
pre-upgrade builds would lose detection (_is_context_summary_content) and
renormalization (_strip_summary_prefix) — the exact regression class the
tuple exists to prevent. Adds contract tests covering every frozen prefix.
Refs #41607#38364#42812
SUMMARY_PREFIX previously contained two contradictory directives:
1. "treat it as background reference, NOT as active instructions"
"Do NOT answer questions or fulfill requests mentioned in this summary"
"Respond ONLY to the latest user message that appears AFTER this summary"
2. "Your current task is identified in the '## Active Task' section of the
summary — resume exactly from there."
When the latest user message contradicted Active Task (e.g. 'stop the
i18n refactor', 'never mind, look at grafana instead'), models tended to
follow (2) anyway because 'resume exactly' is a strong, unambiguous
directive — leading to repeated re-surfacing of already-cancelled work
across turns, even after explicit 'stop'/'don't keep bringing that up'
messages from the user.
This change:
- Removes the conflicting 'resume exactly from Active Task' clause.
- Makes the precedence explicit: latest user message is the single source
of truth; it WINS on conflict; cancelled Active Task / In Progress /
Pending User Asks / Remaining Work must be discarded entirely (no
'wrap up the old task first').
- Names canonical reverse signals (stop, undo, roll back, never mind,
just verify, topic change) so the model recognizes them as cancellation
triggers, not background context.
- Updates the summarizer template instruction so the LLM doesn't
mechanically copy a cancelled task into Active Task on the next
compaction (it's instructed to copy the reverse signal verbatim).
- Preserves: REFERENCE ONLY framing, MEMORY.md/USER.md authority, and
the 'don't repeat work already reflected in session state' clause.
Adds tests/agent/test_summary_prefix_semantics.py to pin invariants so
the conflict can't regress.
Tested:
- All compaction tests pass: tests/agent/test_context_compressor.py,
tests/agent/test_context_compressor_summary_continuity.py,
tests/run_agent/test_413_compression.py,
tests/run_agent/test_compression_persistence.py,
tests/run_agent/test_compression_boundary_hook.py,
tests/cli/test_manual_compress.py — 117/117 passing.
- Tested on macOS.