fix(feedback): make comment delivery exactly-once across channels#14
Merged
Conversation
The server's agentSeq cursor was advanced by every delivery channel but read by none: the CLI kept its own cursor in a state file, the stdio MCP in a process-local variable, and the /mcp transport defaulted to 0. A fresh `sideshow wait` process (or restarted stdio MCP server) replayed comments the agent had already received via piggyback or another channel. An author=user session read with no explicit `after` now resumes from the session's agentSeq, and all three clients drop their private cursors — CLI, both MCP transports, and piggyback share one exactly-once stream. Explicit `--after <seq>` / `afterSeq` remains as a deliberate replay. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Problem
The server's
agentSeqcursor ("highest comment seq already delivered to the agent") was advanced by every delivery channel but read by none. Each client kept a private cursor defaulting to 0:sideshow wait) in a per-process state file/mcptransport expected the model to passafterSeqback, defaulting to 0So mixing channels — exactly the combo the docs recommend (piggyback on writes + a background
sideshow wait) — replayed comments the agent had already received. Found in the wild: a backgroundsideshow waitarmed after an MCPwait_for_feedbackimmediately re-delivered the same comment.Fix
server/app.ts: anauthor=usersession read with no explicitafternow resumes from the session'sagentSeq— "where the agent left off" lives server-side and is shared by every channel. An explicitafter/afterSeqremains as a deliberate replay (and can't regress the cursor;markAgentSeenis monotonic in both stores).bin/sideshow.js,mcp/server.ts,server/mcpHttp.ts: the three client-side cursors are deleted; clients omitafterand let the server resume.guide/, MCP tool descriptions, AGENTS.md invariant, CHANGELOG).Tests
author=userreads deliver once and not again across fresh processes; piggyback delivery advances the cursor seen by waits; viewer reads stay unconsumed.after=0explicitly, since a bareauthor=userread now (correctly) consumes the cursor.npm test(51/51),npm run typecheck,npm run lint,npm run format:checkall pass; also verified live against a throwaway server (deliver once → fresh process gets nothing → piggybacked comment not re-delivered →--after 0replays).🤖 Generated with Claude Code