Repository navigation
fix(web): a thread started from a draft goes live without a reload - #2005
Merged
Merged
Conversation
lidge-jun
added a commit
that referenced
this pull request
Oct 28, 2026
This was referenced Oct 28, 2026
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.
A thread started from a draft showed "Send a message to start the conversation." and no agent activity after the first send, until the page was reloaded.
#1982 made
useQueuedRunEditreadpendingRequestsAtom(routeThreadRef)on every route. On a draft route that ref is the draft's reserved thread id, which the server does not have yet. Mounting it starts the thread's detail stream: the bounded snapshot answers 404, and the stream parks as deleted and never opens its socket. The route keeps the same ChatView mounted through promotion, so after the first send ChatView read that same parked node and rendered an empty timeline. A reload built a fresh node, which is why the reply appeared then.useQueuedRunEditnow takes the detail ref ChatView already resolves withresolveThreadDetailRef(null while the draft waits for its shell), both for its render-time read and forbeginEdit. I checked the other readers on draft routes: DiffPanel gets a null route ref, the route view only reads unlisted server routes, the queued-runs control renders only for server threads, and the remaining handler-timeregistry.getcalls dispose at once (setIdleTTL(0)), so none of them can park the thread.The thread stream itself is unchanged. It has no shell signal, rebuilding it on shell changes would refetch cold deep links, and a socket subscribe for an unknown id fails its snapshot and retries every 250 ms, so the reader-side gate is the contract.
Validation
useQueuedRunEdit.browser.test.tsxruns the real client-runtime thread atoms over a fake environment: render as a draft, create the thread on the server, give the same mounted harness the detail ref, and expectlivewith the first message, then a reply delivered over the socket. Ondev's source it fails withstatus deleted; with the fix all 5 tests pass. The 4 existing tests were already failing ondev(the mock had nopendingRequestsAtom) and pass again.vp run check:changed(Node 26): format, lint, knip, typecheck, tests pass.Before: the draft route fetched the bounded snapshot (404) before sending; the reply stayed hidden until reload. After: no draft-time fetch, and the reply rendered live.
Follow-up, not in this PR: on mobile,
HardwareKeyboardCommandProvidermountsuseThreadProjectionfrom the pathname, andNewTaskDraftScreensets the route's thread id before creation is delivered, so a new mobile thread can park the same way.Reviewed by gpt-6.1-sol (high) through GOAT task review.
Made by claude-opus-5-5 in the Codex harness on GOAT.