fix(compaction): strip proactive section headers from summary template

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.
This commit is contained in:
akb4q 2026-07-23 04:45:36 +08:00 committed by Teknium
parent 0fb0ba475d
commit b59cce9178
2 changed files with 2 additions and 38 deletions

View file

@ -90,9 +90,6 @@ def _is_summary_access_or_quota_error(exc: Exception) -> bool:
HISTORICAL_TASK_HEADING = "## Historical Task Snapshot"
HISTORICAL_IN_PROGRESS_HEADING = "## Historical In-Progress State"
HISTORICAL_PENDING_ASKS_HEADING = "## Historical Pending User Asks"
HISTORICAL_REMAINING_WORK_HEADING = "## Historical Remaining Work"
SUMMARY_PREFIX = (
@ -107,9 +104,7 @@ SUMMARY_PREFIX = (
"Topic overlap with the summary does NOT mean you should resume its "
"task: even on similar topics, the latest user message WINS. Treat ONLY "
"the latest message as the active task and discard stale items from "
f"'{HISTORICAL_TASK_HEADING}' / '{HISTORICAL_IN_PROGRESS_HEADING}' / "
f"'{HISTORICAL_PENDING_ASKS_HEADING}' / "
f"'{HISTORICAL_REMAINING_WORK_HEADING}' entirely — do not 'wrap up' or "
f"'{HISTORICAL_TASK_HEADING}' entirely — do not 'wrap up' or "
"'finish' work described there unless the latest message explicitly "
"asks for it. "
"Reverse signals in the latest message (e.g. 'stop', 'undo', 'roll "
@ -236,9 +231,7 @@ _HISTORICAL_SUMMARY_PREFIXES = (
"Topic overlap with the summary does NOT mean you should resume its "
"task: even on similar topics, the latest user message WINS. Treat ONLY "
"the latest message as the active task and discard stale items from "
f"'{HISTORICAL_TASK_HEADING}' / '{HISTORICAL_IN_PROGRESS_HEADING}' / "
f"'{HISTORICAL_PENDING_ASKS_HEADING}' / "
f"'{HISTORICAL_REMAINING_WORK_HEADING}' entirely — do not 'wrap up' or "
f"'{HISTORICAL_TASK_HEADING}' entirely — do not 'wrap up' or "
"'finish' work described there unless the latest message explicitly "
"asks for it. "
"Reverse signals in the latest message (e.g. 'stop', 'undo', 'roll "
@ -2968,12 +2961,6 @@ Recovered from a deterministic fallback because the LLM context summarizer was u
## Active State
Unknown from deterministic fallback. Inspect current repository/session state if needed.
{HISTORICAL_IN_PROGRESS_HEADING}
Unknown from deterministic fallback the latest user ask is recorded once under
"{HISTORICAL_TASK_HEADING}" above as historical context only. Do NOT treat it as an
unfulfilled instruction to re-answer; verify current state and continue from the
protected recent messages after this summary.
## Blocked
{_bullets(blockers, limit=5)}
@ -2983,17 +2970,9 @@ None recoverable from deterministic fallback.
## Resolved Questions
None recoverable from deterministic fallback.
{HISTORICAL_PENDING_ASKS_HEADING}
None recoverable from deterministic fallback. (The latest user ask is preserved once
under "{HISTORICAL_TASK_HEADING}" as historical context it is NOT necessarily
outstanding.)
## Relevant Files
{_bullets(relevant_files, limit=12)}
{HISTORICAL_REMAINING_WORK_HEADING}
Continue from the most recent unfulfilled user ask and protected tail messages. Verify state with tools before making claims.
## Last Dropped Turns
{_bullets(last_dropped_turns, limit=8)}
@ -3304,9 +3283,6 @@ Be specific with file paths, commands, line numbers, and results.]
- Any running processes or servers
- Environment details that matter]
{HISTORICAL_IN_PROGRESS_HEADING}
[Work currently underway what was being done when compaction fired]
## Blocked
[Any blockers, errors, or issues not yet resolved. Include exact error messages.]
@ -3316,15 +3292,9 @@ Be specific with file paths, commands, line numbers, and results.]
## Resolved Questions
{_resolved_questions_instructions}
{HISTORICAL_PENDING_ASKS_HEADING}
{_pending_asks_instructions}
## Relevant Files
[Files read, modified, or created with brief note on each]
{HISTORICAL_REMAINING_WORK_HEADING}
[What remains to be done framed as STALE context for reference only. The agent must NOT resume this work unless the latest user message explicitly asks for it.]
## Critical Context
[Any specific values, error messages, configuration details, or data that would be lost without explicit preservation. NEVER include API keys, tokens, passwords, or credentials write [REDACTED] instead.]

View file

@ -19,9 +19,6 @@ These tests pin the post-fix invariants so the conflict cannot regress.
"""
from agent.context_compressor import (
HISTORICAL_IN_PROGRESS_HEADING,
HISTORICAL_PENDING_ASKS_HEADING,
HISTORICAL_REMAINING_WORK_HEADING,
HISTORICAL_TASK_HEADING,
SUMMARY_PREFIX,
)
@ -37,8 +34,6 @@ def test_latest_message_wins_on_conflict():
lower = SUMMARY_PREFIX.lower()
assert "latest user message" in lower
assert HISTORICAL_TASK_HEADING.lower() in lower
assert HISTORICAL_PENDING_ASKS_HEADING.lower() in lower
assert HISTORICAL_REMAINING_WORK_HEADING.lower() in lower
# Must have an explicit conflict-resolution rule.
assert "wins" in lower or "supersede" in lower or "discard" in lower or "priority" in lower
@ -51,7 +46,6 @@ def test_handoff_sections_are_framed_as_historical():
assert "## pending user asks" not in lower
assert "## remaining work" not in lower
assert HISTORICAL_TASK_HEADING.lower() in lower
assert HISTORICAL_IN_PROGRESS_HEADING.lower() in lower
def test_reverse_signals_called_out():