🧺 refactor: Move the Chat Follow-Up Queue State to Jotai - #16615
Merged
berry-13 merged 2 commits intoOct 1, 2026
Merged
Conversation
The follow-up queue, its settled receipts and pending enqueue ids, the pane and parked run-end signals, and the interrupt-drain flag are written and read only by chat logic (queue drain, steering, the SSE hook, the queue rail). They now live in store/queue as Jotai atoms with every consumer converted. The run-end FIFO keeps its nullable one-shot API as a writable derived atom.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
berry-13
merged commit Oct 1, 2026
8093dc1
into
berry-13/chat-settings-owners
28 of 29 checks passed
This was referenced Oct 1, 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.
Summary
The follow-up queue and its run-end bookkeeping lived on the Recoil store even though only chat logic reads and writes it: the queue drain, steering, the SSE hook and the queue rail. That covers
queuedMessagesByConvoId,settledQueuedTurnReceiptsByConvoId,pendingQueuedTurnEnqueueIdsByConvoId, the pane and parked run-end signals (runEndByIndex,pendingRunEndByConvoId) and the interrupt-drain flag (drainAfterAbortByIndex). The client state ownership rule inAGENTS.mdmakes state that a feature both writes and reads feature-owned Jotai, converted together with every reader and writer. The conversion was waiting onuseResumeOnLoad.spec(#13811), which has merged.This PR moves the group to Jotai in
client/src/store/queue.tsand converts every consumer:useQueueDrain,useSteering,useSteerCancel,useSteerConvert,useChatHelpers,useResumableSSEandQueue.tsx. The run-end signals keep their nullable one-shot API as a writable derived atom over a FIFO: writing a value appends it, writingnullconsumes the oldest, andRESETclears the queue. Callbacks whose only state was this group became plainuseCallbacks. Mixed callbacks keep their Recoil transaction and write the queue through the Jotai store in the same order as before.Second link of the
chat-ownersstack, on top of #16604. Part of berry-13#186, which closes with #16604.Type of change
Testing
Tested environments/configuration:
reviewctl verify(desktop light, desktop dark, mobile).Automated tests:
npx jest --findRelatedTests <changed files> --maxWorkers=2: 494 suites, 6517 tests.resetQueueFamilies()isolates tests that share the default store. TheuseSteeringcontext harness seeds the queue into its own provider store.e2e/specs/mock/scenarios/queue-owners.spec.ts: interrupt and send stops the run and sends the follow-up next. The composer-queue scenarios cover queueing, draining, reordering and steer-to-queue on this branch.npx tsc --noEmit -p client/tsconfig.json: clean. ESLint and Prettier: clean.atoms.sh(chat C2): Jotai-defined feature-owned atoms go from 6 to 12 of the 26 in the audit list.queuedMessagesByConvoId,runEndByIndex,pendingRunEndByConvoId,drainAfterAbortByIndex,settledQueuedTurnReceiptsByConvoIdandpendingQueuedTurnEnqueueIdsByConvoIdnow have Jotai definitions. Chat C1 is unchanged: each touched hook still imports Recoil for other atoms.Screenshots / recordings
No user-facing change.
Risk / compatibility
The diff is 2,247 lines, but 1,277 with whitespace ignored. Removing the
useRecoilCallbackwrapper re-indents the callback bodies inuseSteeringanduseQueueDrain, so review with "Hide whitespace" on.Recoil callback snapshots were frozen at callback start, while Jotai store reads are live. Every converted callback reads before it writes in one synchronous pass, so the values it decides on are the same. Jotai's
atomFamilystampsDate.now()when it creates a member, so one spec that relied on the first clock read being the submit time now pins the clock to the ACK instead.useResumableSSE.spec.tsalso changes in #14731, and the two auto-merge cleanly.Checklist