From cca3b77a4b4217bb13288f0c4cac9710d82432c8 Mon Sep 17 00:00:00 2001 From: dusterbloom <32869278+dusterbloom@users.noreply.github.com> Date: Sun, 7 Jun 2026 19:47:34 -0700 Subject: [PATCH] fix(compression): clear _previous_summary on session end (defense-in-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> --- agent/context_compressor.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/agent/context_compressor.py b/agent/context_compressor.py index 4dbb189866e..98d226b46af 100644 --- a/agent/context_compressor.py +++ b/agent/context_compressor.py @@ -553,6 +553,22 @@ class ContextCompressor(ContextEngine): self.last_rough_tokens_when_real_prompt_fit = 0 self.awaiting_real_usage_after_compression = False + def on_session_end(self, session_id: str, messages: List[Dict[str, Any]]) -> None: + """Clear per-session compaction state at a real session boundary. + + ``_previous_summary`` is per-session iterative-summary state. It is + cleared on ``on_session_reset()`` (/new, /reset), but session *end* + (CLI exit, gateway expiry, session-id rotation) goes through + ``on_session_end()`` instead — which inherited a no-op from + ``ContextEngine``. Without clearing here, a cron/background session's + summary could survive on a reused compressor instance and leak into the + next live session via the ``_generate_summary()`` iterative-update path + (#38788). ``compress()`` already guards the leak at the point of use; + this is defense-in-depth that drops the stale summary the moment the + owning session ends. + """ + self._previous_summary = None + def update_model( self, model: str,