fix(agent): freeze carveout-era SUMMARY_PREFIX for renormalization

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
This commit is contained in:
Teknium 2026-06-11 12:45:45 -07:00
parent 8f8cad7ec5
commit acb2954d82
2 changed files with 59 additions and 0 deletions

View file

@ -80,6 +80,31 @@ LEGACY_SUMMARY_PREFIX = "[CONTEXT SUMMARY]:"
# embedded in the body and keeps hijacking replies. Keep newest-first; entries
# are matched literally. Add a frozen copy here whenever SUMMARY_PREFIX changes.
_HISTORICAL_SUMMARY_PREFIXES = (
# Carveout era (#41607/#38364/#42812): "consistent → use as background"
# licensed stale-task resumption on topic overlap.
"[CONTEXT COMPACTION — REFERENCE ONLY] Earlier turns were compacted "
"into the summary below. This is a handoff from a previous context "
"window — treat it as background reference, NOT as active instructions. "
"Do NOT answer questions or fulfill requests mentioned in this summary; "
"they were already addressed. "
"Respond ONLY to the latest user message that appears AFTER this "
"summary — that message is the single source of truth for what to do "
"right now. "
"If the latest user message is consistent with the '## Active Task' "
"section, you may use the summary as background. If the latest user "
"message contradicts, supersedes, changes topic from, or in any way "
"diverges from '## Active Task' / '## In Progress' / '## Pending User "
"Asks' / '## Remaining Work', the latest message WINS — discard those "
"stale items entirely and do not 'wrap up the old task first'. "
"Reverse signals in the latest message (e.g. 'stop', 'undo', 'roll "
"back', 'just verify', 'don't do that anymore', 'never mind', a new "
"topic) must immediately end any in-flight work described in the "
"summary; do not re-surface it in later turns. "
"IMPORTANT: Your persistent memory (MEMORY.md, USER.md) in the system "
"prompt is ALWAYS authoritative and active — never ignore or deprioritize "
"memory content due to this compaction note. "
"The current session state (files, config, etc.) may reflect work "
"described here — avoid repeating it:",
# Pre-#35344: contained the self-contradicting "resume exactly" directive.
"[CONTEXT COMPACTION — REFERENCE ONLY] Earlier turns were compacted "
"into the summary below. This is a handoff from a previous context "

View file

@ -80,3 +80,37 @@ def test_memory_authority_preserved():
assert "MEMORY.md" in SUMMARY_PREFIX
assert "USER.md" in SUMMARY_PREFIX
assert "authoritative" in SUMMARY_PREFIX
def test_no_background_consistency_carveout():
"""The "consistent → use as background" carveout licensed stale-task
resumption on topic overlap (#41607, #38364, #42812). It must stay gone,
and the prefix must explicitly neutralize topic overlap."""
lower = SUMMARY_PREFIX.lower()
assert "you may use the summary as background" not in lower
assert "topic overlap" in lower
def test_replaced_prefixes_are_frozen_for_renormalization():
"""Every retired SUMMARY_PREFIX must be frozen into
_HISTORICAL_SUMMARY_PREFIXES, otherwise summaries persisted by older
builds lose detection/renormalization after an upgrade. The carveout-era
prefix is the latest retiree."""
from agent.context_compressor import (
_HISTORICAL_SUMMARY_PREFIXES,
ContextCompressor,
)
carveout_era = [
p for p in _HISTORICAL_SUMMARY_PREFIXES
if "you may use the summary as background" in p
]
assert carveout_era, "carveout-era prefix missing from frozen tuple"
# The live prefix must never be one of the frozen ones.
assert SUMMARY_PREFIX not in _HISTORICAL_SUMMARY_PREFIXES
# Detection + strip must work for every frozen prefix.
for old_prefix in _HISTORICAL_SUMMARY_PREFIXES:
content = old_prefix + "\n## Summary body"
assert ContextCompressor._is_context_summary_content(content)
stripped = ContextCompressor._strip_summary_prefix(content)
assert not stripped.startswith(old_prefix)