fix(server): send messages queued during context compaction - #10096
Open
f4llenz wants to merge 5 commits into
Open
fix(server): send messages queued during context compaction#10096f4llenz wants to merge 5 commits into
f4llenz wants to merge 5 commits into
Conversation
f4llenz
marked this pull request as ready for review
September 5, 2026 11:48
f4llenz
force-pushed
the
t3code/restore-compaction-message-queue
branch
from
September 5, 2026 11:49
6bdc009 to
6831075
Compare
Contributor
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This focused server fix introduces per-thread asynchronous latching and FIFO coordination that changes when existing user messages reach the provider. Although targeted tests cover the main scenarios and no schema or infrastructure changes are involved, the runtime concurrency behavior is non-trivial and warrants human review. No code changes detected at You can add or adjust custom eligibility rules. Learn more. |
f4llenz
force-pushed
the
t3code/restore-compaction-message-queue
branch
6 times, most recently
from
September 5, 2026 19:02
2f61f32 to
6fc36bf
Compare
Contributor
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
Since pingdotgg#9293 turned /compact into a server-side operation, a message sent while a thread compacts was rejected with a turn-start failure and the client dropped it. Messages sent during a running turn steer into that turn, but compaction runs outside any turn, so there was nothing to steer into. The reactor now keeps a per-thread latch for the in-flight compaction instead of a bare flag. A turn start that arrives while the latch is held waits for it, then sends through the normal path once the session is restored. If the thread stopped or errored meanwhile, the message gets a turn-start failure so the client restores the draft. The message was already persisted before the reactor saw it, so nothing new needs to survive a restart.
Waiters woken by the same latch ran as independent fibers, so two messages queued during compaction could reach the provider out of order. Each queued send now waits for the one queued before it and awaits its own provider call before releasing the next, so the thread sees them in the order they were sent.
A turn requested after the compaction latch settles found no latch to wait on, so it took the fast path and could overtake a queued send that was still draining.
f4llenz
force-pushed
the
t3code/restore-compaction-message-queue
branch
from
September 5, 2026 19:12
6fc36bf to
4505e07
Compare
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 Changed
Fixes a regression from #9293: sending a message while
/compactis running failed with "Wait for context compaction to finish before sending another message." and the message was dropped.The send now waits for compaction to restore the session, then goes to the provider. Several messages sent during one compaction reach the provider one at a time, in the order they were sent. If the thread stops or errors before compaction settles, the queued send fails with "The thread stopped before this message could be sent." instead of hanging.
In
ProviderCommandReactor, the per-thread compaction marker is now aDeferredlatch instead of aSetentry. A turn requested during compaction, or while an earlier queued send is still draining, forks a fiber that waits on the previous queued send, then on the latch, re-resolves the thread shell, and starts the turn. There is no in-memory queue to persist or project: the message is already in the event log, so a restart mid-compaction leaves it in the same place as any other in-flight send.Why
Before #9293 (
c5ba51d62),/compactwas a message steered into the running provider turn, so a follow-up sent during it queued like any other message. That PR made compaction a server-side command that runs outside any provider turn, and the reactor started rejecting sends while it ran. Users lost the message and had to notice and resend.#9620 attempted the same fix with a FIFO queue in the reactor plus projection changes. It lost queued sends on restart and had a drain-order race, and was closed. Making the marker itself the latch fixes both with no new state.
Known gap, unchanged from before: the composer's send button becomes Stop while compaction runs, so the follow-up has to be submitted with Enter.
Verification
provider.turn.start.failed; a turn arriving after the latch settles still queues behind a draining send; and a queued send fails when the thread stops before compaction finishes. The fullProviderCommandReactor.test.tssuite passes (63 tests).UI Changes
Before.
/compactthen a follow-up. The follow-up is rejected and never answered, even after "Compacted context" lands.before.mp4
After. Same sequence. The follow-up waits, compaction lands, then it is sent and answered.
after.mp4
Checklist
Claude Fable 5.1 in T3 Code via the Claude Code harness.
Note
Queue
thread.turn.startrequests during context compaction inProviderCommandReactorPreviously, turn requests arriving while a thread was undergoing context compaction were failed instead of sent. The reactor now uses deferred compaction latches and per-thread queued-turn tails so that incoming turns wait for compaction to settle, then send in FIFO submission order.
ProviderCommandReactor.make; verify that stopped-thread failure messages match expectations for errored sessions, as the failure path now applies to both stopped and errored states.Macroscope summarized 4505e07.