Skip to content

fix(compression): stop cross-session _previous_summary contamination#41717

Merged
teknium1 merged 3 commits into
mainfrom
fix/compaction-cross-session-contamination
Jun 8, 2026
Merged

fix(compression): stop cross-session _previous_summary contamination#41717
teknium1 merged 3 commits into
mainfrom
fix/compaction-cross-session-contamination

Conversation

@teknium1

@teknium1 teknium1 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Compaction summaries no longer leak across session boundaries — a cron/background session's summary can no longer contaminate the next live conversation (#38788).

Root cause: ContextCompressor._previous_summary is per-session iterative-summary state. It was cleared by on_session_reset() (only /new and /reset), but ContextCompressor never overrode on_session_end() — it inherited a no-op from ContextEngine. On a reused compressor instance, a cron session's _previous_summary survived a real session boundary and got injected as the "PREVIOUS SUMMARY:" block into the next live session's summarizer prompt, producing off-topic / fabricated output.

Two complementary layers, covering genuinely different leak paths (verified below):

Changes

  • agent/context_compressor.py:
    • Point-of-use guard (in compress(), @basilalshukaili): when no handoff summary is found in the current messages but _previous_summary is non-empty, discard it before _generate_summary(). Catches the leak regardless of how the stale state arrived.
    • Lifecycle clear (on_session_end() override, @dusterbloom): clear _previous_summary the moment the owning session ends. Closes the remaining hole the point-of-use guard alone leaves open — when the live session has its own prior summary in messages (handoff present), the elif doesn't fire, so a stale cron summary would otherwise survive on a reused instance.
  • scripts/release.py: add basilalshukaili to AUTHOR_MAP.
  • tests/agent/test_context_compressor_cross_session_guard.py: 3 tests for the point-of-use guard (@basilalshukaili).

Validation

Scenario Before After
Fresh session compacts, stale cron summary present, no handoff cron summary injected → contamination discarded before summarizer
Session ends on reused instance _previous_summary survives cleared at boundary
Same-session re-compaction (real handoff present) iterative update works iterative update preserved (not broken)
  • 3 new tests pass; 192 compressor/context-engine tests pass, 0 regressions.
  • E2E (real ContextCompressor, real method calls): confirmed both guards fire on their respective paths, and that legitimate intra-session iterative summarization is preserved (real summary prefix is still recognized and kept).

Credit

Closes #38788. Supersedes #38832 and #39725.

Infographic

session-isolation-compaction-fix

basilalshukaili and others added 3 commits June 7, 2026 19:49
… 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 #38788
…depth)

ContextCompressor inherited a no-op on_session_end() from ContextEngine, so
per-session iterative-summary state (_previous_summary) survived a real session
boundary on a reused compressor instance. Override it to clear the summary the
moment the owning session ends, complementing the point-of-use guard in
compress(). Closes the cross-session contamination path in #38788.

Co-authored-by: dusterbloom <32869278+dusterbloom@users.noreply.github.com>
@alt-glitch alt-glitch added type/bug Something isn't working P1 High — major feature broken, no workaround comp/agent Core agent loop, run_agent.py, prompt builder labels Jun 8, 2026
@liuhao1024

Copy link
Copy Markdown
Contributor

Positive verification — clean security review

Reviewed the cross-session _previous_summary contamination fix. Two complementary guards, both correct:

  1. on_session_end() clears stale state — the method was inherited as a no-op from ContextEngine; this override drops _previous_summary at a real session boundary (CLI exit, gateway expiry, session-id rotation), preventing cron/background session summaries from leaking into the next live session.

  2. compress() defense-in-depth — when no handoff summary is found in the current messages but _previous_summary is non-empty, it's discarded before _generate_summary() can inject it into the summarizer prompt via the iterative-update path. The elif self._previous_summary: branch is correctly placed after the handoff-detection block, so same-session iterative updates (where a handoff IS found) are preserved.

  3. Test coverage is thorough — three tests cover: stale summary cleared when no handoff, summary preserved when handoff exists, and no false-positive when already None. The test uses a minimal _make_compressor() constructor with __new__ to avoid heavy __init__ dependencies — a pragmatic approach for unit-level isolation.

No issues found.

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: fix/compaction-cross-session-contamination vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 10036 on HEAD, 10033 on base (🆕 +3)

🆕 New issues (1):

Rule Count
no-matching-overload 1
First entries
tests/agent/test_context_compressor_cross_session_guard.py:26: [no-matching-overload] no-matching-overload: No overload of bound method `MutableMapping.setdefault` matches arguments

✅ Fixed issues: none

Unchanged: 5201 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@teknium1 teknium1 merged commit b5f7a1f into main Jun 8, 2026
23 checks passed
@teknium1 teknium1 deleted the fix/compaction-cross-session-contamination branch June 8, 2026 05:09
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

5 participants