Skip to content

fix(compression): guard against cross-session stale _previous_summary contamination#38832

Closed
basilalshukaili wants to merge 1 commit into
NousResearch:mainfrom
basilalshukaili:fix/compaction-cross-session-stale-summary-guard
Closed

fix(compression): guard against cross-session stale _previous_summary contamination#38832
basilalshukaili wants to merge 1 commit into
NousResearch:mainfrom
basilalshukaili:fix/compaction-cross-session-stale-summary-guard

Conversation

@basilalshukaili

Copy link
Copy Markdown
Contributor

What

When a cron or background session compacts, the ContextCompressor sets _previous_summary for iterative summary updates. If that session ends without /new or /reset (which call on_session_reset()), the stale summary survives on the shared instance. A subsequent live messaging session's compaction then injects it as PREVIOUS SUMMARY: into the summarizer prompt — contaminating the live session with unrelated content.

Root Cause

In compress(), when no handoff summary is found in the current messages (via _find_latest_context_summary), but _previous_summary is non-empty from a prior session, the code silently carries the stale value forward. _generate_summary() then enters its iterative-update branch (line 1343), injecting the stale cron summary into the summarizer prompt.

Fix

Added an elif guard in compress() (after the handoff-search block, line 1911): when no handoff summary is found in the current messages but _previous_summary is non-empty, discard it. This ensures _generate_summary() starts fresh when the summary state belongs to a different session.

The guard does NOT fire when a handoff summary IS found in the current messages — iterative updates within the same session are preserved.

Tests

Three new tests in tests/agent/test_context_compressor_cross_session_guard.py:

  • Stale summary cleared_previous_summary set from a simulated prior session, no handoff in current messages → cleared to None
  • Handoff preserved — handoff found in current messages → _previous_summary preserved (guard doesn't fire)
  • No false positive_previous_summary already None → guard is no-op

All 33 tests pass (26 existing + 7 in this change set).

Related

Fixes #38788

… contamination

When a cron or background session compacts, it sets _previous_summary for
iterative updates. If that session ends without /new or /reset (which calls
on_session_reset()), the stale summary survives on the ContextCompressor
instance. A subsequent live messaging session's compaction then injects it as
'PREVIOUS SUMMARY:' into the summarizer prompt — contaminating the live
session with unrelated content from the prior session.

Add an else guard in compress(): when no handoff summary is found in the
current messages but _previous_summary is non-empty, discard it so
_generate_summary() starts fresh instead of iteratively updating a stale
cross-session summary.

Fixes NousResearch#38788
@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent loop, run_agent.py, prompt builder P1 High — major feature broken, no workaround labels Jun 4, 2026
@teknium1

teknium1 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Merged via #41717 (commit 8513a6a) — your point-of-use guard in compress() is the primary fix and landed with your authorship preserved via rebase. Paired it with a defense-in-depth on_session_end() clear (crediting @dusterbloom's #39725 approach) since E2E showed the point-of-use guard alone leaves a gap when the live session has its own prior summary in messages. Your test file is included as-is. Thanks!

#41717

@teknium1 teknium1 closed this Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder P1 High — major feature broken, no workaround type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Context compaction cross-contamination — cron session summaries leak into unrelated live conversations

3 participants