You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
spec-2.3's loop changes are confined to the FinishToolUse arm + per-turn Tools assembly (nil filter = identity); the failing path is the no-tool FinishStop chain — untouched.
llmapp/model.gostreamDoneMsg handler recovers residual = previewNodes + stream.Drain() to preserve partial text on cancel paths. On the NORMAL path the comment asserts both are empty — but there is a window: loopStartCmd goroutine teardown runs ts.Close() (flushes the final partial line into the TokenStream's pending nodes) before close(ctrl). If the Model's SealedText handler performed its discard-drain BEFORE the Close-flush landed, the flushed final line survives in the closed stream and streamDoneMsg's stream.Drain() re-commits the already-sealed text → duplicate assistant block.Message.
Candidate fixes (for the owning spec/hotfix, NOT verified):
streamDoneMsg: skip residual commit when finishHandled == true (normal-finish path needs no recovery — recovery exists for the lost-EventFinish cancel path only)
or: dedupe residual against the last sealed segment text
Scope
Pre-existing 1.21.1-adjacent race; candidate for a spec-1.21.2 hotfix branch (hotfix matrix: 不动 spec 设计, 三路 code review). Not blocking spec-2.3 (FROZEN @ v0.53.0-stage2.53).
Activity
fix(db): spec-2.3a post-impl R-fix (cr+go dual-route absorb)