fix(compression): stop an aborted rotation from growing the parent it could not publish - #88411
Merged
kshitijk4poor merged 1 commit intoAug 17, 2026
Conversation
… could not publish The rotation path flushes its un-persisted transcript to the parent (NousResearch#47202) and only then calls publish_compression_child. The abort handler rolls back the in-memory transcript and keeps agent.session_id on the parent - its own comment says "keep the parent live and discard the stale compacted snapshot" - but the rows the flush just wrote are not part of what it discards. Every failed rotation therefore leaves the parent transcript longer than it found it, whatever the failure was. That is survivable for a one-off failure and pathological for a sticky one. A parent row carrying ended_at fails the publish on every attempt and nothing in this path clears it, so each auto-compaction appends another copy of the current turn to the transcript it was supposed to shrink. Worse, the growth then satisfies conversation_compression's own len(durable_parent) > len(messages) check, so the next attempt adopts the inflated snapshot as if it were genuine concurrent activity and the in-memory transcript doubles too. Check that one precondition before writing. It is a plain read of the row the publish is about to read anyway, and it raises the publish's own message, so split_status=aborted, failure_class=session_split_failed and the rollback path are all unchanged; a live parent reaches the flush exactly as before. Deliberately not extended to the compression lease, which is re-acquirable - a transient miss there would abort a rotation that would otherwise have committed. old_session_id moves above the flush so a failure raised from here takes the same in-memory rollback as any other pre-publish failure. Scope: this fixes the amplification for every abort cause. It does not fix what marks a live session as ended in the first place (NousResearch#88197 Bug 1), which needs a maintainer decision on end-reason taxonomy and is tracked on the issue; an affected session still aborts every attempt, it just stops making itself larger while it does. Refs NousResearch#88197
kshitijk4poor
enabled auto-merge (rebase)
August 17, 2026 12:41
Closed
19 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stops an aborted compression rotation from growing the parent transcript it could not publish — when the parent session already carries
ended_at, the pre-flush guard raises before the durable #47202 flush writes rows that survive the abort.Root cause: the rotation path flushes un-persisted current-turn messages to the parent (#47202) and then calls
publish_compression_child. The abort handler rolls back in-memory state but not the durable rows. On a sticky failure (parent already ended, e.g. by staletui_shutdown), each auto-compaction appends another copy of the current turn — the session grows instead of shrinking until the provider rejects the request (#88197: 303 messages became 2,611 rows, HTTP 400).Changes
agent/conversation_compression.py: hoistold_session_idabove the flush (so the except handler rolls back correctly), add a pre-flush guard that reads the parent row and raises the publish's ownRuntimeErrorifended_atis set. Fails open on an unreadable row. Deliberately not extended to the compression lease (re-acquirable, transient).tests/agent/test_compression_rotation_state.py:TestAbortedRotationDoesNotGrowParent— 3 tests covering ended-parent (the bug), live-parent (no regression), fail-open (unreadable row).Validation
Salvage of #88227 by @jackulau — cherry-picked with authorship preserved. Closes #88227.