anomalyco / anomalyco/opencode
compact silently lands reasoning-only (empty-body) summaries, causing irrecoverable context loss
@rekram1-node is already working on this.
Since Aug 22, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
When the model used for /compact returns a response containing only reasoning parts and no text part, opencode lands that empty-body message as the session summary and reports compact as successful. The epoch replacement then permanently destroys the original conversation history — yet everything reports success, so the agent continues with an essentially empty (corrupted) context and no warning.
Reproduction — 100% reproducible (2/2 triggers)
- opencode v1.18.21 (latest)
- Model:
opencode-go/glm-5.3(reasoning model) - Triggered compaction twice on this model; both times compact reported success while the summary message had only a
reasoningpart and notextpart, and the original history was lost.
Steps:
- Use
opencode-go/glm-5.3in a session. - Trigger
/compact. - Compact reports success; the resulting summary message has no text body; the original history is gone and cannot be recovered.
Relationship to #41571
Shares the same core failure as #41571 (Kimi K3-256k): a reasoning model produces a reasoning-only summary (no text part), opencode marks it summary: true, lands it, and swaps in an empty summary — silently dropping history. #41571 traces this to the v1.18.15 serialize() flattening change in compaction.ts (history flattened to a wall of plain text → reasoning model analyzes instead of summarizing). opencode-go/glm-5.3 on v1.18.21 exhibits the identical symptom at a 100% rate, suggesting the serialize-format issue affects reasoning models broadly, not just k3-256k. (I have not yet read compaction.ts to confirm glm-5.3's exact trigger mechanism, but the symptom + 100% rate + reasoning-model + same serialize code path make a shared root cause highly likely.)
Additional proposals
- L0 (stream layer): detect/reject reasoning-only (no-text-part) responses as incomplete at stream end — upstream defense before compaction even runs.
- Structural detection basis: per the
@opencode-ai/sdkPart union,TextPart(type:"text") andReasoningPart(type:"reasoning") are independent union members — a reasoning-only response has no text part at all and is structurally detectable, not a length-threshold heuristic (negligible false-positive risk). - Irrecoverability: once the epoch is replaced, the source material is destroyed, so any retry afterward is useless — the failure is silent and permanent. The failure must be caught before epoch replacement.
Expected behavior
- Compact should fail and retry the LLM while source material still exists when the produced summary has no non-empty
TextPart— not land it and replace the epoch. - The success/"compacted" marker must not be set until the summary passes body validation.
Suggested fix
Add a hasNonEmptyTextBody(message) check (iterate message.parts; require at least one type === "text" with non-whitespace content) at:
- L0 (stream layer): at stream end, reject reasoning-only responses as incomplete.
- L1 (compact landing): before epoch replacement, validate the summary body; on failure, retry the LLM (source still intact) instead of landing.
The same detection function can live in the SDK so plugins/tools share one definition. This is the "at minimum detect empty summaries and fail" bottom-line from #41571, plus an upstream L0 defense.
Impact
- Severity: high — irrecoverable, silent context loss; the agent continues on a broken session with no warning because the compacted flag is set despite no real content.
Environment
- opencode v1.18.21 (latest)
- Model:
opencode-go/glm-5.3(reasoning model) - Repro rate: 2/2 (100%)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.