Skip to content

compaction: summary reports work as Active/Pending that was completed ~19h earlier — stale Work State propagates to handoffs #50816

Closed as not planned

Description

@tczank

Summary

An automatic compaction produced a summary whose ## Work State → Active, ## Work State → Pending, and ## Next Move sections described work that had already been completed ~19 hours earlier. The agent then operated on that false state — it repeatedly told the user the work was outstanding, and its final handoff to a new session carried the same false status forward.

Unlike the tool-dispatch corruption reported elsewhere, this is a silent correctness failure: no error is raised, and the summary reads as confident and authoritative.

Environment

  • opencode version: 2.0.14 (install/channel: /usr/bin/opencode, latest)
  • OS: Linux 7.2.6-arch2-1 (linux x86_64, Arch)
  • Terminal: TERM_PROGRAM=tmux, TERM=xterm-256color, COLORTERM=truecolor
  • Shell: /bin/zsh
  • Model: mimo-v2.6-flash-free (provider opencode), agent build
  • Active plugins: none found (no opencode.json/opencode.jsonc, no .opencode/plugin(s)/, no ~/.config/opencode/opencode.json)

Reproduction

  1. Complete a multi-step task (commit → push → update PR), with verifiable external state.
  2. Continue the session until an auto-compaction fires.
  3. Read the compaction summary's Work State / Next Move.
  4. Observe that already-finished items are still listed as Active/Pending.

Expected Behavior

Compaction summaries should reflect actual work state at the moment of compaction. Items completed before the compaction point should be recorded as completed, not pending.

Actual Behavior

Ground truth (all verified read-only from the repo, the fork remote, and the GitHub API):

Fact Evidence Timestamp (UTC)
Commit created 6042e3f "Show live prompt-processing rate during fills and compaction" 2026-09-22 07:29:52
Pushed to fork fork/main == local HEAD == 6042e3f 2026-09-22 07:29:5x
PR body updated PR #1 body contains ## Update: live prompt-processing rate … 2026-09-22 07:29:5x
PR comment posted comment by tczank, "Pushed 6042e3f …" 2026-09-22 07:29:58
Build completed build3.log → Build complete!; binary mtime 16:26:15 +0900 2026-09-22 07:26:15
Working tree clean git status -sb → only ?? _deps/; git diff on both patched files empty verified 2026-09-23

Compaction #5 (session_message.seq = 1396) fired at 2026-09-23 02:36:50 UTC — roughly 19 hours after all of the above — and its summary stated:

Active

  • Refined patch applied (7 edits in llamacpp_source.hpp/.cpp …) — needs rebuild + retest.

Blocked

  • (none — server up, gh authed, llmtop pane %4 identified)

Next Move

  1. Kill running llmtop (pid 651664, first-patch build), run …/build_llmtop.py, verify ldd …
  2. Live retest: fire a ~6k-token fill …
  3. Commit only src/sources/llamacpp_source.{hpp,cpp} on local main …
  4. Push to fork head: …
  5. gh pr view 1 … → append section … → gh pr edit 1 …

All five items were already done. The prior compaction (#4, seq 1087) had correctly shown this task as Active; the completed state was never reconciled into #5.

Downstream effects

  1. The agent believed the false state. At seq 1511 (~24 h after the work finished, post-compaction) it wrote a handoff to the user instructing the next session to "commit → push → update PR feat: compact and other improvements #1", listing the patch as uncommitted.
  2. The false state propagated into a file. That handoff was saved as a working note (HANDOFF-mimo-session.md) and had to be manually corrected against the repo.
  3. Silent. No warning, no error, no time_compacting anomaly — session_v2.time_compacting is set, but nothing flags the mismatch. status: "completed", reason: "auto".

This creates real risk of redoing completed work (re-running builds/tests, duplicating commits, re-pushing) or, worse, of a downstream session reporting stale status to the user as fact.

Additional Context

  • Diagnosis performed read-only against ~/.local/share/opencode/opencode.db (session_v2, session_message); no session data was modified.
  • The session had 5 compactions (seq 448, 731, 911, 1087, 1396). Comparing them, Work State items appear to be carried forward from the previous summary and updated by the summarizing model rather than re-derived from the actual message log — which would explain an item getting "stuck" in Active/Pending once it is there.
  • Possibly related but distinct: after compaction the model also began emitting tool calls as literal text ([Assistant tool call]: shell({...})) instead of structured tool parts — tracked separately.
  • Suggested directions:
    • Feed the summarizer the tool results that occurred after the previous compaction (not just the prior summary) so completed items can be closed out.
    • Cross-check Next Move items against observable state (git status, PR state, process liveness) before emitting the summary, and drop items that verify as done.
    • Mark Work State entries with the sequence number at which they were recorded, so staleness is visible to the next turn.

Activity

  1. github-actions commented on Sep 23, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    You may also want to coordinate with #50814 (filed by you) since both were observed in the same session and may share a common trigger.

    If you believe this is distinct enough to remain open, it would help to clarify how it differs from #28063.

  2. tczank commented on Sep 23, 2026

    @tczank
    Author

    Checked — I'd keep this open rather than close as duplicate.

    #28063 describes the same mechanism, but it was auto-closed NOT_PLANNED by github-actions after 60 days of inactivity (2026-05-17 → 2026-07-17), with no fix landed. This reproduces on v2.0.14, so the bug was never resolved — it was dropped.

    The numbers behind this report:

    Commit + push + PR body + PR comment 2026-09-22 07:29:52 → 07:29:58 UTC
    Compaction #5 (seq 1396) fired 2026-09-23 02:36:50 UTC
    Staleness gap ~19 h 07 m — all 5 Next Move items already done
    Compactions in session 5 (seq 448, 731, 911, 1087, 1396)
    Prior summary (#4, seq 1087) showed the task as correctly Active → never reconciled into #5
    False-state propagation repeated at seq 1511 (~24 h after completion) and written into a handoff file
    Verified against git status clean, fork/main == 6042e3f, PR comment API

    Differences from #28063 that I think matter:

    1. Trigger — /compact summary can show stale Next Steps because preserved recent tail is excluded from summary reconciliation #28063 is manual /compact; this is automatic ("reason": "auto"), fires with no user action.
    2. Section labels — /compact summary can show stale Next Steps because preserved recent tail is excluded from summary reconciliation #28063 targets ## Next Steps; here the stale entries are in ## Work State → Active and ## Next Move. A fix scoped only to Next Steps would miss these.
    3. Downstream propagation — the stale state reached a later session, which reported it to the user as fact. /compact summary can show stale Next Steps because preserved recent tail is excluded from summary reconciliation #28063 covers in-session repetition only.

    Happy to consolidate if #28063 is reopened instead.

    Filed alongside #50814 (tool-call corruption after compaction), same session, different failure.

  3. liudongyan13701205717-source commented on Oct 1, 2026

    @liudongyan13701205717-source

    Environment data point: desktop app on Windows — plus blast-radius context

    Not a reproduction. I have not verified stale Work State in my own session store, so I'm not claiming this bug reproduces for me. What I can offer is an environment the existing reports don't cover and a sense of scale.

    Environment: Windows 11, opencode desktop (Electron) app (@opencode-aidesktop, plugin SDK @opencode-ai/plugin@^1.18.32), provider opencode, model big-pickle. The reports I read here were against CLI installs (/usr/bin/opencode on Arch, mimo-v2.6-flash-free). If the desktop build has a separate compaction code path, that would matter for reaching a fix to those users.

    No user-facing config knob. I found no key for compaction frequency or thresholds in ~/.config/opencode/opencode.json or tui.json. The only public surface is experimental.session.compacting (pre-compaction; prompt replaces the summarization prompt) and experimental.compaction.autocontinue (post-compaction). So the prompt is user-customizable but the frequency is not — meaning any mitigation for stale Work State has to land in the summarizer input or the default prompt.

    Scale from the local store (~/.local/share/opencode/opencode.db, read-only):

    Measurement Value
    message rows (total) 23,189
    Compaction messages ("mode":"compaction" + "agent":"compaction" + "summary":true) 1,380
    Distinct sessions with ≥1 compaction 40 of 300
    Most-affected session 308 compactions

    Exact-match note so the number isn't read as inflated: a loose LIKE '%compaction%' OR LIKE '%summar%' filter returns 5,351 — ordinary message bodies also contain summar. The 1,380 figure matches the exact JSON keys, which co-occur on those same rows.

    One thing that may bear on the suggested fix direction

    @tczank's first suggested direction — feeding the summarizer the tool results that occurred after the previous compaction, rather than only the prior summary — implies a per-session record of where the previous compaction boundary sat.

    In my store, the table that looks like it would hold that (session_context_epoch, columns session_id, baseline, snapshot, baseline_seq) contains 0 rows across all 300 sessions, despite 40 of them having compacted.

    I'm not claiming that's the bug — I don't know what writes it, and it may simply be unused in this build. But if it is meant to carry compaction baselines, its being permanently empty while 1,380 compaction messages exist would be consistent with the summarizer having no reliable "what happened since last time" signal to reconcile against. Is there an existing mechanism tracking the previous compaction boundary, and does it work on desktop? If it does exist, the reconciliation gap is purely in the summarizer input; if it doesn't, that may be the cheaper thing to fix first.

    Cross-referencing #51711: the budget problem there produces a compounding effect here — more frequent compaction means more summaries inheriting un-reconciled state.

  4. opencodejr commented on Oct 28, 2026

    @opencodejr
    Contributor

    Thanks for the detailed write-up. I tried this on 2.0.14 with a simulated model and logged exactly what OpenCode sends to the model when it compacts:

    1. First compaction: the summary lists "Patch applied — needs commit + push" under Work State → Active and "Commit the patch" under Next Move.
    2. The agent then runs a real shell call that "commits and pushes", and the tool result goes back into the conversation.
    3. Second compaction: the request to the summarizer contained the previous summary, the tool call and its full output, and the update instruction ("Newer history always takes precedence… Reconcile Work State and Next Move: move completed work out of Active…").

    So OpenCode does give the summarizer the evidence that the work was done and explicitly tells it to move completed items out of Active. A summary that still lists them, like your compaction #5, looks like the summarizing model (here mimo-v2.6-flash-free) not following that instruction, rather than OpenCode dropping history. I couldn't reproduce an OpenCode defect.

    Two things would help if you think something else is going on:

    • Whether the completed work (the git commit/git push/gh pr edit tool results) actually appears in the request that produced compaction tweak: glob should be able to read certain hidden files/dirs #5. In a very long session, tool outputs can be cut down to make the history fit, and I didn't test that case.
    • Whether the same thing happens with a stronger model as the summarizer.

    Your other suggestions (checking Next Move items against git/PR state, tagging Work State entries with sequence numbers) would be new features, so they may be better filed as a feature request. Related: #50814 (tool calls written as plain text after compaction, from the same session) and #41358 (the agent losing track of its task after auto-compaction).

  5. opencodejr commented on Oct 31, 2026

    @opencodejr
    Contributor

    Closing this as not planned, since we haven't heard back. On 2.0.14 the summarizer request contained the previous summary, the tool results showing the work was finished and the instruction to move completed items out of Active. A summary that still lists them looks like the summarizing model (mimo-v2.6-flash-free) not following that instruction, not OpenCode losing history.

    If you can show that the commit/push/PR results were missing from the request behind compaction #5 (for example, cut down in a very long session), or that a stronger model as summarizer gives the same stale Work State, please comment and we can reopen this. The ideas about checking Next Move against git/PR state, or tagging Work State entries with sequence numbers, would fit well as a separate feature request. Thanks for the detailed report.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions