Repository navigation
fix(opencode): reject empty or length-cut compaction summaries - #52786
pauldupuyjr wants to merge 2 commits into
Conversation
A compaction whose summary message has no non-empty text part, or whose summary call ended on finish reason "length", no longer becomes the history boundary. The summary message is errored and the process stops, so the original history stays visible instead of being silently dropped behind an empty or truncated summary. Co-Authored-By: Claude Opus 5.5 <[email protected]> Co-Authored-By: GLM-5.3 <[email protected]>
The empty-summary guard picked its error text from summary presence, so a length-cut run that produced no text reported "Compaction produced no summary" instead of the length-limit message. Select the message from the finish reason first so both failure shapes report accurately. Co-Authored-By: Claude Opus 5.5 <[email protected]> Co-Authored-By: GLM-5.3 <[email protected]>
|
The following comment was made by an LLM, it may be inaccurate: |
|
I hit the same empty-summary issue independently and ended up testing a very similar guard locally. One thing I’m not completely sure about is rejecting every finish === "length" case.
Those summaries were also carried forward as My concern with I think a narrower rule would be less restrictive while still protecting against the zero-text failure:
I’d also suggest covering these cases in tests:
One small extra: publishing Session.Event.Error on rejection makes the stop visible in the TUI instead of looking like a silent halt. |
Issue for this PR
Closes #44080
Closes #41571
Type of change
What does this PR do?
Compaction could succeed with a summary that has no text (the model spent its whole output budget on reasoning) or that was cut off by the output length limit. That empty or partial summary still became the compaction boundary, so everything before it was hidden and the session carried on with no context.
After the summary call, if nothing has errored yet and the summary has no text or finished with
length, the summary message is now marked as an error and compaction stops.completedCompactions()already skips errored summaries, so the earlier history stays visible andCompactedis not published.This re-derives the guard from #42063 by @vladislav-miroshnikov (closed for age, not rejected), which covered empty text only; this also rejects summaries cut off by
finish: "length".How did you verify your code works?
Three tests in
packages/opencode/test/session/compaction.test.ts: a reasoning-only summary is rejected, alength-finished summary (with or without partial text) is rejected, and a normal text summary still compacts. The two rejection tests fail ondevwithout the fix.I also ran a real session against a reasoning model (GLM 5.3 Flash via OpenRouter) with the compaction model's output capped at 64 tokens and tail turns off. On
devthe cut-off summary was accepted and the next turn had lost the earlier messages; with this change the summary is marked as an error and the next turn still sees the full history.Screenshots / recordings
Not a UI change.
Checklist