fix: prevent double compaction from destroying preserved messages (#26458)#26502
Open
jaden-clovervnd wants to merge 1 commit intoopenclaw:mainfrom
Open
fix: prevent double compaction from destroying preserved messages (#26458)#26502jaden-clovervnd wants to merge 1 commit intoopenclaw:mainfrom
jaden-clovervnd wants to merge 1 commit intoopenclaw:mainfrom
Conversation
After a successful safeguard compaction, a second compaction could fire immediately due to stale usage.totalTokens from kept assistant messages. The pre-compaction check in pi-coding-agent's prompt() finds a kept assistant with pre-compaction usage (e.g., 184K tokens) and triggers shouldCompact() even though the session is already compacted to ~1-5K tokens. This second compaction destroys all messages the first one preserved, causing complete conversation amnesia. Two defense-in-depth fixes: 1. compaction-safeguard.ts: Cancel compaction in session_before_compact when messagesToSummarize has no real conversation messages (user, assistant, or toolResult). In the double compaction scenario, only custom/compaction entries remain, so this guard prevents the spurious re-compaction from proceeding. 2. attempt.ts: Skip cache-ttl custom entry insertion when compaction occurred during the same attempt. The cache-ttl entry was the only non-compaction entry after compaction, bypassing prepareCompaction()'s existing double-compaction guard (which checks if the last entry is a compaction type). Verified against 22 double compaction events across 8 real sessions where every instance showed: Comp1 keeps 1-193 messages, then Comp2 immediately destroys all of them (0 messages kept). Fixes openclaw#26458
|
Nice catch on the root cause analysis — the stale The comment in |
|
This pull request has been automatically marked as stale due to inactivity. |
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
Fixes #26458 — After a successful safeguard compaction, a second compaction fires immediately due to stale
usage.totalTokensfrom kept assistant messages, destroying all preserved conversation history.Root Cause
Pi-coding-agent's
prompt()method checks_findLastAssistantMessage()before each prompt and calls_checkCompaction()with that message'susage.totalTokens. After compaction, kept assistant messages still carry their pre-compaction usage values (e.g., 184K tokens), which makesshouldCompact()returntrueeven though the session is already compacted to ~1-5K actual tokens. This triggers a second compaction that finds 0 real messages to keep.Evidence
totalTokensfrom kept assistants exceeds theshouldCompactthresholdChanges
1.
compaction-safeguard.ts— Cancel compaction with no real messagesAdded a guard at the top of
session_before_compactthat cancels compaction whenmessagesToSummarizehas no real conversation messages (user,assistant, ortoolResult). In the double compaction scenario, onlycustom/compactionentries remain after the first compaction, so this guard prevents the destructive second compaction.2.
attempt.ts— Skip cache-ttl insertion after compactionWhen compaction occurs during an attempt, the
openclaw.cache-ttlcustom entry is no longer appended. Previously, this entry was the only non-compaction entry in the session, which bypassedprepareCompaction()'s existing guard (checking if the last entry is a compaction type).Tests
Added 3 test cases to
compaction-safeguard.test.ts:messagesToSummarizeis emptymessagesToSummarizehas only custom entriesNote on upstream fix
The root cause is in pi-coding-agent's
prompt()→_checkCompaction(), which should either skip the check when the last assistant predates the latest compaction, or useestimateContextTokens()on current messages instead of staleusage.totalTokens. The fixes in this PR are defense-in-depth on the OpenClaw side to prevent the destructive outcome regardless of the upstream behavior.Greptile Summary
Fixed double compaction bug that destroyed preserved conversation history after successful compaction. The issue occurred when stale
usage.totalTokensfrom kept assistant messages triggered immediate re-compaction, with 22 confirmed incidents across 8 sessions showing 100% reproduction rate.Two defensive fixes were implemented:
compaction-safeguard.tsthat cancels compaction when no real conversation messages exist to summarizeattempt.tsto skipcache-ttlcustom entry insertion after compaction, preventing bypass of existing double-compaction guardsTest coverage includes three new test cases validating the guard behavior for empty messages, custom-only entries, and normal conversation flow.
Confidence Score: 5/5
Last reviewed commit: 25c7355
(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!