fix: harden post-compaction continuation guard (supersedes #61) - #62
Merged
Conversation
Merged
Contributor
|
@willytop8 Thanks for your help! |
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
Follow-up to #61 (and #58 before it) hardening the post-compaction goal
continuation guard. This branch keeps @harryzhou2000's epoch-guard work from #61
as its base — his commit is preserved — and corrects three issues that only
surface against the event shapes OpenCode actually emits.
The event shapes were confirmed against the vendored
@opencode-ai/sdktype definitions rather than inferred from test fixtures:
EventMessageUpdatedis{ type, properties: { sessionID, info } }— it nevercarries
parts. Parts arrive onmessage.part.updated, which this plugin doesnot observe.
EventSessionCompactedis{ type, properties: { sessionID } }— noid, nocompactionID/summaryID/messageID, and no sync variant in the plugin-facingEventunion.What changes
Identity-less compaction re-delivery no longer trips the breaker. Because a
real
session.compactedhas no identity field, the identity-based dedup fromfix: guard goal continuation across compaction epochs #61 can never fire against a live host, so a single duplicate delivery would
reach
MAX_STALLED_COMPACTIONSand abort the session. Re-deliveries are nowrecognized by the absence of any message activity since the previous
compaction (a genuine new compaction is always preceded by messages, since the
context has to grow again to trigger one). New
messageSeenSinceCompactionflag, persisted and restored fail-open.
A completion/blocked claim on the retained compaction source is honored.
The terminal checks (
[goal:complete]/[goal:blocked]) are split off fromthe progress/checkpoint boundary. The compaction source still gates
checkpointing and stall heuristics, but no longer suppresses a terminal claim
on the retained turn — which had survived the compaction unprocessed, so
swallowing it discarded a real result and spent another continuation.
Remove the inert tool-part detection branch.
messageHasToolCallagainstthe
message.updatedenvelope is always false (no parts on that event), so itwas dead. The breaker resets on assistant output-token progress, which a
tool-using turn also produces.
messageHasToolCallis unchanged and stillcorrect at its other call site, which reads API-fetched messages that do carry
parts.
Tests
properties.infoshape withrealistic output tokens (the original used an envelope OpenCode does not emit and
output: 0, which rested the assertion entirely on the now-removed branch).on the retained compaction source is honored; identity-less compactions
separated by message activity still trip the breaker; tool parts on a
message.updatedevent are not a productive-turn signal. The first two failagainst this branch's base with the source fix reverted.
Verification
npm test(394/394),npm run type:check,npm run test:mutation(67/67),npm run smoke, all green; also green on Node 18.Not included (deliberately)
MAX_STALLED_COMPACTIONSor drop thesession.aborton tripis left as a separate discussion; the false-positive paths that made the abort
dangerous are closed here.
event?.id, butEventSessionStatus/EventSessionIdlecarry noideither, soseenIdleEventIDsnever dedups inproduction. Same class of issue as (1), predates fix: guard goal continuation across compaction epochs #61 — worth its own issue.
Closes #61.
🤖 Generated with Claude Code