A customer's question is drawn once, however long the answer takes - #35
Merged
Merged
Conversation
Seen on the demo shop the night the film went in: a visitor typed one question and saw it twice, one bubble under the other, and then one answer. The widget draws what was typed straight away and asks the Worker for the reply. While the model thinks, the six-second poll — there to collect what a person on the shop's side may type — asked for every row after the last one it knew, and the Worker, which had already stored the question, handed it straight back, so the widget drew it again. Two writers to one transcript. It cannot happen on a visitor's first message, because there is no session to poll for until the Worker has answered once; from the second message on it happened whenever the reply took longer than the time to the next tick. The rule now: - A turn that is out is drawn by its own answer. While a send is in flight the poll does not go out, and a poll that was out already and comes back during the send is discarded: the send's answer carries the reply and the seq that covers both rows. - Every row is drawn once, by seq. A poll answered late, after a send has moved lastSeen past its rows, brings nothing new. `a-question-is-drawn-once.test.ts` runs the real widget script against a stub of the little DOM it touches, with fetch under the test's control so the poll can be made to land in the middle of a send. With the bug put back, three of its four cases fail. 960 tests, lint and typecheck clean. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDkiHs276KQhSWxQnHQdLg
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.
What a visitor saw
On the demo shop's widget, one question typed → two identical bubbles → one answer.
The mechanism
The widget draws the question straight away and calls
/send. While the model thinks (seconds), the six-second poll — there to collect what a person on the shop's side may type — asked for every row after the last it knew. The Worker had already stored the question, handed it back, and the widget drew it again. Two writers to one transcript.It cannot happen on the very first message (no session to poll for until the Worker has answered once); from the second message on it happens whenever the reply outlasts the time to the next tick — which is most replies.
The rule now (
widget.ts, 24 lines)seqcovering both rows.Tests — 960 passing (+4)
a-question-is-drawn-once.test.tsruns the real widget script against a stub of the DOM it touches, withfetchunder the test's control so the poll lands mid-send:With the bug put back (
git stashthe widget), 3 of 4 fail. The existingnew Function(script)syntax check still passes.After merge
bash scripts/first-sync.sh thankywal/muxel-demo→ Cloudflare rebuilds the demo Worker (~3 min) → the widget at/w/…serves the new script.🤖 Generated with Claude Code
https://claude.ai/code/session_01NDkiHs276KQhSWxQnHQdLg