Restore stored history when it is ahead of the join snapshot - #334
Open
nicklaunches wants to merge 1 commit into
Open
Restore stored history when it is ahead of the join snapshot#334nicklaunches wants to merge 1 commit into
nicklaunches wants to merge 1 commit into
Conversation
Opening a channel joins the realtime gateway, and the join replaces the agent's messages with the gateway's snapshot of the thread. That snapshot can lag the durable store, so a turn that had finished, been persisted and answered in full came back without its last exchange. History was restored only into an empty agent, so the stale snapshot stayed for good: the gap was there on every reload, with no unreadable count to explain it. The store now wins when it holds more than the agent does and holds everything the agent already has. The second half is the guard this replaces: a message typed while history was loading is not in the store yet, and a run still streaming has messages the store has not seen, so neither is rolled back. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaHWJ1niprhBc5NzJ9pxme
nicklaunches
requested review from
MikeRyanDev,
davidmckayv,
guidovizoso and
tylerslaton
as code owners
September 2, 2026 14:53
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.
The problem
Opening a channel does two things: it loads the thread from the durable store, and it joins the
realtime gateway. The join replaces the agent's messages with the gateway's own snapshot of that
thread, and that snapshot can lag the store.
When it did, the transcript came back missing the end of the last conversation: a turn that had
finished, been persisted, and been answered in full, gone from the view. Stored history was only
restored into an empty agent, a guard written to protect a message typed while history was still
loading, so the stale snapshot won every time. The gap was there on every reload, and nothing on
screen explained it, since there was no unreadable count to mark the missing messages.
What changed
ChannelChatapplies the stored thread when the store is ahead of the agent: it holds more messagesthan the agent does, and every message the agent holds is in the store.
The second half of that condition is exactly what the old empty-agent check was protecting, stated
directly rather than by proxy. A message typed while history was loading has not been persisted yet,
so it is not in the store, so the store is not applied and the message is not overwritten. A run
still streaming has messages the store has not seen, so its snapshot is never rolled back either.
How it was verified
bun run --cwd app typecheckclean.bun test app/tests/channel-event-patch.test.ts app/tests/channel-unread.test.ts app/tests/chat-messages.test.ts app/tests/repair-history.test.tsgives 35 pass, 0 fail.bunx biome check app/src/components/channels/channel-chat.tsxclean.🤖 Generated with Claude Code