Skip to content

fix(compression): clear all per-session state in on_session_end, not just _previous_summary#42891

Open
blut-agent wants to merge 1 commit into
NousResearch:mainfrom
blut-agent:bugfix-compressor-session-end-stale-state-20260609
Open

fix(compression): clear all per-session state in on_session_end, not just _previous_summary#42891
blut-agent wants to merge 1 commit into
NousResearch:mainfrom
blut-agent:bugfix-compressor-session-end-stale-state-20260609

Conversation

@blut-agent

Copy link
Copy Markdown
Contributor

Summary

The cross-session contamination fix (#38788) only cleared _previous_summary in on_session_end(), but on_session_reset() clears 14+ per-session variables. When a session ends (cron exit, gateway expiry, session-id rotation) and the compressor instance is reused, the surviving stale state causes real user-visible bugs:

Impact of stale state surviving across sessions

Stale variable Symptom in next session
_ineffective_compression_count Compression skipped prematurely (anti-thrashing guard misfires from prior session's count)
_summary_failure_cooldown_until Summary generation blocked for an unrelated transient error
_last_compress_aborted Callers think compression is still aborted
_last_aux_model_failure_* Stale error warnings shown to user
_last_summary_dropped_count Misleading dropped-turns warnings
_last_summary_fallback_used Misleading fallback warnings
_context_probed / _context_probe_persistable Stale context-probe state from prior session

Bonus fix

on_session_reset() was also missing _last_compress_aborted clearing — a /new or /reset would inherit the aborted flag from the prior conversation.

Changes

  • agent/context_compressor.py: on_session_end() now clears all 16 per-session variables (matching on_session_reset() surface). on_session_reset() now also clears _last_compress_aborted.
  • tests/agent/test_context_compressor_session_end_clears_state.py: 6 new tests:
    1. test_on_session_end_clears_all_per_session_state — comprehensive check of every field
    2. test_on_session_end_matches_on_session_reset_surface — parity test ensuring both methods clear the same surface
    3. test_ineffective_compression_count_does_not_leak_across_sessions
    4. test_summary_failure_cooldown_does_not_leak_across_sessions
    5. test_compress_aborted_flag_does_not_leak_across_sessions
    6. test_aux_model_failure_does_not_leak_across_sessions

Test results

All 110 context compressor tests pass (including 3 existing cross-session guard tests + 6 new).

Related

…just _previous_summary

The original cross-session contamination fix (NousResearch#38788) only cleared
_previous_summary in on_session_end(), but on_session_reset() clears
14+ per-session variables. When a session ends (cron exit, gateway
expiry, session-id rotation) and the compressor instance is reused,
the surviving stale state causes:

- _ineffective_compression_count surviving → next session skips
  compression prematurely (anti-thrashing guard misfires)
- _summary_failure_cooldown_until surviving → next session blocks
  summary generation for an unrelated transient error
- _last_compress_aborted surviving → callers think compression is
  still aborted
- _last_aux_model_failure_* surviving → stale error warnings shown
- _last_summary_dropped_count / _last_summary_fallback_used
  surviving → misleading user warnings
- _context_probed / _context_probe_persistable surviving → stale
  context-probe state

Also fix on_session_reset() which was missing _last_compress_aborted
clearing — a /new or /reset would inherit the aborted flag from the
prior conversation.

Add 6 targeted tests covering the leak vectors and a parity test
ensuring on_session_end and on_session_reset always clear the same
surface.
@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 9, 2026
@liuhao1024

Copy link
Copy Markdown
Contributor

Code Review — clean ✅

Reviewed the full diff (context_compressor.py + tests).

The fix correctly identifies the root cause: on_session_end() (added in #38788) only cleared _previous_summary, while on_session_reset() clears 14+ per-session variables. This meant stale state from a cron/background session could leak into the next live session.

The fix extends on_session_end() to clear the full per-session surface, matching on_session_reset() exactly. The test test_on_session_end_matches_on_session_reset_surface is particularly good — it programmatically verifies both methods produce identical attribute values, so future drift between the two will be caught immediately.

No issues found. 🚀

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