Skip to content

fix(native-chat): a /compact sent while the agent works waits in line instead of being refused - #25704

Merged
brennanb2025 merged 43 commits into
mainfrom
brennanb2025/chat-command-waits-in-line
Oct 8, 2026
Merged

brennanb2025 merged 43 commits into
mainfrom
brennanb2025/chat-command-waits-in-line

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 27 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1897 $\color{#cf222e}{\Huge{\mathbf{−}}}$​83 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1814
Prod 68 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1464 $\color{#cf222e}{\Huge{\mathbf{−}}}$​439 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1025

ELI5

If you type /compact in a native chat while the agent is busy, Orca refuses it today: "A message you sent earlier isn't confirmed yet. The command didn't run. Wait for your earlier message to go through, or retry it." This PR makes /compact wait its turn in the message queue, like a message typed mid-turn, and run when the agent is free.

That waiting reaches users only when the message queue is switched on. The queue is still turned off in shipped builds. Until it launches, /compact is still refused while the agent is busy, but in plain words. What changes for everyone today is listed under "What changes live today".

What Changed

The problem

A native chat refuses /compact and /clear whenever anything is still in flight:

  • a turn is running,
  • a question or approval is waiting, or
  • an earlier message hasn't been answered yet. With Claude, that covers the 3–18 s before it echoes the message back, and, for a message sent during a turn, the rest of that turn.

The user sees one of two sentences. The desktop's own check says "Wait for pending work and messages to finish before using this command." The host says "A message you sent earlier isn't confirmed yet. The command didn't run. …". Neither says whether the message was sent, what "confirmed" means, or what to do.

Why it happens: /compact is accepted as an ordinary submission, and the delivery loop hands every submission to the agent at once, even mid-turn. A plain message steers into the running turn, but a command can't, so the host refused it whenever anything was in flight. The host-held message queue (the cards above the composer) already waits for exactly these states before it sends anything. /compact just never entered it.

What changes live today, for everyone

  • The /clear refusal is said once, in plain words.

    • While a turn runs or an earlier message is unanswered: "The agent is still working. Run /clear when it's done."
    • With a question or approval pending: "Answer the agent's question or approval, then run /clear."
    • When the desktop's only leftover is a message that failed and shows its Retry (the chat is idle): "Retry your earlier message, then run /clear."
    • When it is a message still on its way with the agent idle (one this window hasn't handed to the host yet, or one a Stop kept), which shows no Retry: "Your earlier message is still being sent. Run /clear once it has gone."

    This covers the host's refusal and the desktop's and phone's own checks, in every shipped language. Background tasks, rewind and handoff keep their words.

  • A refused /compact reads the same way: "The agent is still working. Run /compact when it's done.", and the matching question and Retry sentences. On shipped hosts /compact still refuses while the agent works, until the queue launches. The desktop now also checks the chat's Working state before sending a /compact or /clear. So in the moment between a message being accepted and the agent opening a turn, it answers with the plain sentence locally instead of the host's "isn't confirmed" one.

  • On desktop, a second command pressed while one is on its way says "The agent is still working. Run /… when it's done." Before, it said "Wait for pending work…". The phone is unchanged: it has always taken no second command silently.

  • A message handed back into a composer holding only /compact or /clear (a queued card's Edit, the draft hold, or the phone's rejected-send restore) now replaces that command. Before, it became /compact followed by the message, which then failed with "Use /compact without arguments". Any other draft is kept, a lone slash word that isn't one of those two commands (/clearly, /tmp) included, with the message after it as before. A Stop no longer hands a message back into a composer that holds text (main's feat(native-chat): keep a message a Stop took back on screen, with one stop row after it #25051): behind a typed command the message stays on screen with its Retry.

  • A refusal line by the composer goes once what it names has ended, on desktop (a row of the notice card above the message box) and phone. "The agent is still working…" goes when the agent stops (and while the queue is about to send its next card, the chat still reads as working), the question/approval line when it is answered, and on desktop "Background tasks are still running…" when they end, "…still being sent…" when that send lands or fails, and "Retry your earlier message…" once it is resent. It is dropped, not hidden, so the state coming back later doesn't bring it back. Before, the line stayed until the next send and could state something no longer true. Other errors keep their existing lifetime: on desktop, until the next send or Dismiss; on phone, a temporary banner or toast. The phone can't see background tasks, so that refusal uses its ordinary timeout too.

  • The host's "earlier message unsettled" rule (shared by /clear, /compact from older clients, and rewind) is now the chat's Working rule (isUnansweredStructuredAgentSessionDispatch), not a near-copy. It no longer refuses for two things the chat already shows as idle: a handed-over message left by an earlier agent process, and an older host's restart doubt.

  • The new host capability agent-session.queued-commands.v1 is advertised. On its own it does nothing: clients use it only together with the queue's capability.

What changes when the message queue is switched on

  • /compact sent while a turn runs, a question is pending, or an earlier message is unanswered appears at once as a /compact card in the queue. There is no notice, and the composer clears. The card runs after the earlier work, in send order. Messages sent after it queue behind it, even with "queue follow-ups" off. A command card whose conversion into a send failed is skipped until its Send is retried. Cards kept after a quit or close retain one order with kept messages; reopening sends none of them on its own, and the next accepted turn or Resume releases that pause.
  • The card reads /compact, as typed.
  • It never steers into a running turn. While the agent works it offers no Steer or Send. While the agent is idle it offers Send (for example, under a paused queue, or after a send failure whose caption says "press Send to retry").
  • Its other ways out are Delete and Stop then Resume: Stop pauses the queue, and Resume sends it.
  • It offers no Edit, because editing a command's text would turn it into a message.
  • All of this works on desktop and phone.
  • If it is refused at hand-over (the agent's "Not enough messages to compact", or background tasks running, a handoff or a race), the card is spent, not returned. The command's own turn says why, once, in its row in the transcript, in the reason's words, with the step after the wait: for example "Background tasks are still running. Wait for the background tasks to finish. Run /compact again." Cards behind it keep draining. A failed agent start is not a refusal of the command, so its card is returned like any card, with the start's words on it.
  • A command card whose own send failed says "Couldn't send — press Send to retry once the agent finishes." while the agent works, when its Send is hidden.
  • On desktop, /compact pressed while a message from this window is still on its way to the host is not taken. The text stays in the composer, the earlier message reads "Sending…", and the send control is in its busy (Stop) state. Nothing is armed. Once the host has the message, the next Enter sends it.
    • With the agent idle, "Sending…" is on the message's transcript row.
    • Mid-turn, a send asking to be queued is not a transcript bubble. It now shows at once as the card it is about to become, reading "Sending…" with nothing to press, until the host's card replaces it under the same id.
      • It counts as on its way only while the host has no record of it. A send the host took straight through is drawn once, from the journal.
      • Queue lists now skip the client's 48 ms coalescing, so the host's card lands with the frame that carries it. That frame is published from the card's commit, ahead of the reply that retires the "Sending…" card. I checked that order in the code; I didn't measure it.

Mechanism

  • Host admission (structured-conversation-compaction.ts): agentSession.conversationCommand gains an optional delivery: 'queue-if-active', for /compact only. A /clear sent with delivery is refused by the host: its operation fingerprints no delivery, so it reads as a conflict and nothing queues. A test proves it. With it, the host first runs the queue's own accept rule (maybeQueueStructuredAgentSessionSend, the same one a queue-if-active send uses). If anything holds the queue, the command is stored as a card whose body is the existing /compact body. The RPC answers at once with { state: 'completed', queued: {…} }. Otherwise today's path runs unchanged.
  • Draining and hand-over: cards drain only when nothing holds the queue, so earlier work is ahead by construction. At hand-over the existing command path runs it as its own turn.
  • A refused card (queued-message-settlement.ts and queued-message-table.ts): a failure-verdict rejection of a command card's hand-off settles the card as spent (withdrawn) instead of returned, but only when the command's own turn is in the journal, because that turn's row says why. A failed start has no command turn, so its card is returned like any card.
    • Refused before hand-over (structured-agent-session-queued-command-refusal.ts), the host records no hand-off. It writes the ended turn and its row in one batch, then rejects the submission while it is still queued. A crash between leaves a queued submission, which a restart returns to waiting. It never leaves a card gone with no row, or a command that "may have run".
    • The words come from the refusal's reason (agent-session-command-refusal-words.ts), the same sentences the composer line uses, so the direct path's answer reads the same.
  • Replays: the same operation id answers from the card, then from the submission it became (queuedSendAnswer). It never makes a second card or a second run.
  • Send on a command card: the host refuses it only while the agent is working. Clients don't offer it then. An older queue-capable client that does gets the generic "not done" line, since the host's sentence is for logs.
  • /clear drops a waiting command card instead of carrying it to the new conversation. Other cards are carried in order and wait for the new conversation's next turn or Resume.
  • A command card cut short by a restart or a close waits again in the same ordered queue as kept messages, regardless of whether the queue or the person sent it. Reopening holds those cards silently until the next accepted turn or Resume; it adds no per-card "not sent yet" caption. A command is spent only when its own turn records a refusal. A direct /compact (no opt-in) cut short by a restart is never turned into a card; the person runs it again.
  • Desktop (structured-conversation-command-send.ts, structuredConversationCommandHold and structuredConversationCommandRunner):
    • /compact sends delivery only when the host advertises both capabilities.
    • Then it is held only by background tasks, or by a message this window hasn't handed to the host yet (hasUnsentStructuredAgentSessionOutboxEntry). That second case takes nothing, as described above.
    • The busy state is the composer's existing one (canStop, derived every render from the turn, the Working rule and that same unsent check). It ends whenever the earlier entry settles: accepted (the host owns it), refused or never recorded (it waits for its Retry), or taken back by Stop.
    • A send stuck behind one whose outcome is in doubt doesn't pin it: the busy control is Stop, and Stop takes the unsent message out of line. With /compact in the composer that message stays on screen with its Retry, and /compact then goes.
    • The words for messages left in the outbox follow what each row offers (structuredAgentSessionDeliveryNotices): a Retry, or "Sending…" for one a Stop kept.
  • Phone: the same opt-in. Its turn and prompt pre-check is skipped for a /compact that waits in line. The phone has no outbox.
  • Words: new write kinds clear and compact (agentSessionWriteKindForMethod) map turnActive/messagesUnsettled/promptPending to the plain sentences. structuredConversationCommandHold uses the same sentences for the clients' own checks.
  • The command card concept is generic. body.command marks it on the host (no Send while working, spent when refused, dropped by /clear), and card.command marks it on both clients. The stacked /clear follow-up can reuse it as is.

Why

The user asked for the state to be fixed, not the wording: a command should wait in line behind earlier work, like any queued message. The queue already models "wait until the agent is free", with persistence, publication to every device, Delete, pause on Stop and restart, and Resume. Admitting /compact into it reuses all of that and adds no new latch.

Alternatives considered:

  • Reword the refusal only. It still refuses a reasonable request, which is the complaint.
  • Client-side wait-then-send (an earlier revision of this PR held the command and sent it later). It sent the command after a Stop, never ended behind a stuck message, and could leave /compact in the composer after it ran. It was replaced by taking nothing while Send is busy.
  • Make the delivery loop hold a journal-queued /compact until idle. A queued submission counts as working itself, so the loop would wait on itself without a special case. It also has no Delete, pause or Resume surface.
  • Let /clear wait in line too. It stops the agent and moves the tab to a new chat, which needs a deferred tab move and a reply that arrives later. That is a stacked follow-up.

Differences from the common pattern. In the common pattern, compact is an ordinary queued message that runs in order, /clear is queued like any message while busy, and Send is disabled while the previous send is still on its way.

  • /compact waits as a host-held queue card. Intended: same mechanism, one ordered host queue.

  • A command card never steers into a running turn. Intended: handed over mid-turn, the host can only refuse it, so offering Steer would offer a guaranteed failure. Send stays available whenever the agent is idle.

  • On desktop, /compact behind a message still on its way takes nothing and arms nothing to send later. That part is the common pattern's disabled-while-submitting mechanism. Three things differ:

    • only a command does nothing (a plain message is still taken);
    • the visible control is the composer's busy Stop, not a disabled Send;
    • behind a send whose outcome is in doubt, the wait lasts until the user presses Retry or Stop, not a sub-second.

    Temporary: the follow-up has the command ride the outbox in order after fix(native-chat): every chat send ends one of three ways, decided by the host's answer #25207, which removes the client-side check altogether.

  • /clear is refused while busy. Temporary: the follow-up is "/clear waits in line", stacked on this PR.

  • /compact waiting in line is off until the message queue launches (agent-session.queued-messages.v1 advertised). Until then, /compact is refused while busy, in plain words. Temporary: it goes live with the queue launch, with no further change here. This PR doesn't touch what gates the queue's launch.

  • An older host with a new client, or an older client with a new host, keeps today's refusal. Temporary: until those versions age out.

  • A message with an image skips the text-only queue: maybeQueueStructuredAgentSessionSend in structured-agent-session-queued-messages.ts returns null for any send that isn't text only. So it can run ahead of a waiting /compact card. Temporary: the follow-up is the queue's attachment support.

Linked Issue

N/A (maintainer change).

Visual Proof / QA

Final head 47f4087be85 — round 5 QA

After the final main merge, A–F passed: quitting and reopening sends nothing automatically; the next own message or Resume releases kept messages and /compact in order; the command keeps its action restrictions; a refused command explains itself once and later text proceeds. G's unsettled-clear case also passed. Typing during a successful /clear still loses the draft from the replacement composer, but this is a pre-existing main bug: the same result reproduces on main parent 4f4f021f8a1. It is not introduced by this PR or the merge.

Checked October 7–8, 2026 on Windows using hidden windows, private profiles and homes, hooks disabled, mock keychain and a stand-in agent. The message-queue capability was enabled only in the QA artifacts for A–F and the matched parent comparison; shipped gating is unchanged. A separate unmodified-source final artifact with that capability off reproduced the clear failure too. This is separate from the follow-up preference, which was tested on and off for message order. Original uncropped frames, a 50 ms/mutation sampler, provider logs and host journal records back these results; this does not establish phone, SSH or real-provider behavior.

Row Final-head result
A — typed message then /compact, follow-ups on PASS: quiet reopen for over three minutes; next own message, typed message, compact, once each.
B/D — follow-ups off and genuine kept message PASS: the host accepted the kept message before actual quit; reopen stayed quiet; next own message, kept typed message, compact. B also checked command-first saved order.
C — Resume after quit PASS: real Resume 1 chat click sent continuation, then waiting compact and typed text; the original prompt was not resent.
E — earlier send unsettled and command actions PASS: earlier card showed Sending while compact stayed in the box; it then became a waiting card. No Send/Steer/Edit on the command; Stop paused and queue Resume released in order.
F — refused compact PASS: one transcript explanation, no blocking returned command or extra toast, next text completed.
G — unsettled clear PASS: text stayed in the box and no old-session send appeared accepted.
G — draft typed during successful clear PRE-EXISTING MAIN BUG: replacement box empty on main capability on and final capability on/OFF.

No duplicate waiting/sending cards were observed. D's host journal records the accepted kept submission before quit and recovery under the same message ID; a merely local unaccepted send was excluded. E's first frame has the command popup over part of the earlier card; accessible state and the sampler confirm Sending.

A — follow-ups on, quit/reopen and ordered release

Before actual quit: typed message and compact wait.

Before actual quit: typed message and compact wait

Quiet reopened chat.

Quiet reopened chat

Next own message runs first.

Next own message runs first

Own message, typed message, then compact complete.

Own message, typed message, then compact complete

B/C — follow-ups off and restart Resume

Follow-ups off: quiet reopen.

Follow-ups off: quiet reopen

Follow-ups off: saved command-first order.

Follow-ups off: saved command-first order

Real Resume starts continuation first.

Real Resume starts continuation first

Resume continuation then saved waiting order.

Resume continuation then saved waiting order

D — host-accepted kept message, follow-ups off

Accepted kept text and compact before actual quit.

Accepted kept text and compact before actual quit

Kept work remains quiet after reopening.

Kept work remains quiet after reopening

Next own message precedes kept work.

Next own message precedes kept work

Own message, kept typed text, then compact complete.

Own message, kept typed text, then compact complete

E/F — unsettled earlier send, restrictions and refusal

Earlier Sending; compact remains in the box.

Earlier Sending; compact remains in the box

Compact waits with restricted actions.

Compact waits with restricted actions

Stop and queue Resume preserve order.

Stop and queue Resume preserve order

Waiting command that will be refused.

Waiting command that will be refused

One refusal explanation and next text completes.

One refusal explanation and next text completes

G — pre-existing successful-clear draft disappearance

Each clean deciding probe started after normal Warmup completion, held clear for five seconds, typed Draft exactly once while clear was pending, and performed no later UI action or Enter on that draft. All three pending frames show Draft; all three replacement frames show an empty composer. Stored text remains under the old conversation's draft scope. Host records show completed clear replacements, no Draft submission or queue card, and no submission in the replacement conversation. The loss is from the visible composer when its conversation scope changes; it is not evidence that the saved bytes were erased. Main capability off was not separately tested; the final on/off control establishes flag independence.

The original longer-draft run included later re-entry by the driver. That later action is excluded; the clean one-fill probes below are the retention evidence. An existing rating popup overlays the right side of the main frame, but Draft and the empty replacement placeholder are visible and independently confirmed by accessible state.

Unsettled clear — final head PASS

Unsettled clear keeps typed text with inline feedback.

Unsettled clear keeps typed text with inline feedback

Text remains after earlier send settles.

Text remains after earlier send settles

Successful clear — final head, message-queue capability on

Final ON: Draft typed while clear is pending.

Final ON: Draft typed while clear is pending

Final ON: replacement composer is empty.

Final ON: replacement composer is empty

Successful clear — final head, message-queue capability off

Final OFF: Draft typed while clear is pending.

Final OFF: Draft typed while clear is pending

Final OFF: replacement composer is empty.

Final OFF: replacement composer is empty

Successful clear — main parent `4f4f021f8a1`, message-queue capability on

Main parent: Draft typed while clear is pending.

Main parent: Draft typed while clear is pending

Main parent: replacement composer is empty.

Main parent: replacement composer is empty

The successful-clear draft bug remains unfixed and is recorded as main pre-existing. No ready or merge action was taken.


The existing screenshots compare baseline 5cf3585b78d with stacked PR #25842 at f1f69c818bb, which includes this PR at 338a57c898b. The after images show the shared /compact implementation and queue-off refusal paths; PR #25842 additionally changes /clear only when queueing is enabled. These images cover admission, send order, Stop/Resume and refusal behavior preserved by this merge, and do not verify its new recovery behavior. How this was checked: on a Windows machine, in an isolated copy of Orca running hidden (its own profile and home folder, never the user's real one), with a stand-in agent instead of a real Claude or Codex, driven by a non-Claude test agent. The message queue is still switched off in shipped builds, so it was switched on in that copy only, to show what happens once the queue launches.

Before: /compact sent right after a message is refused.

Before: /compact right after a message is refused

After: /compact waits as a card with Delete and More actions, and no Send, Steer or Edit while the agent works.

After: /compact waits as a card without Send or Steer

After the agent's reply, the waiting /compact runs and its card is gone.

After the reply, /compact runs and the card is gone

Send order is kept: Second, then /compact, then Third.

Order kept: Second, then /compact, then Third

The same order with follow-ups switched off.

Order kept with follow-ups switched off

While the earlier message is still on its way, it reads "Sending…" and /compact stays in the composer.

Earlier message reads Sending…, /compact stays in the composer

A message sent mid-turn shows as a "Sending…" card until the host holds it.

Mid-turn send shown as a Sending… card

Stop pauses the queue; Resume runs the waiting /compact card.

Stop pauses the queue, Resume runs the card

When the agent refuses the compaction, that is said once, in one row, and the queue moves on.

Refused compaction: one row, the queue moves on

With the queue switched off (what shipped builds do today), a busy /clear gets the plain refusal line:

Queue off: plain /clear refusal

and so does a busy /compact:

Queue off: plain /compact refusal

Not verified on screen: the phone. No simulator can pair with the hidden Windows copy; the phone is covered by unit tests. These screenshots were taken before the fix that removes a stale refusal line (the line now goes away once its cause ends) and before the last merges from main. One of those merges brought in the notice card above the message box, so on desktop the refusal now shows as a row of that card rather than a loose line under the transcript; its words and when it goes away are unchanged.

Current recovery verification — round 4

The quit/recovery row now passes at b6cbc76c74b344c3defd1d55301c69dcf483b797. On the earlier head, a recovered typed message could remain held while a later /compact ran after the next own message. On this head, both cards reopen quietly in their submitted order and follow the chat's next accepted turn; both complete without the retired kept-message caption.

Checked October 7, 2026 PDT, on the Windows high-spec host, using hidden Orca windows with private profiles and homes, hooks disabled, mock keychain and a stand-in agent. Both builds had the queue capability enabled only for QA; shipped queue gating is unchanged. These are fresh captures, separate from the 11 historical images above. The PR remains a draft.

Current-head run Submitted before quit Release action Delivered after reopening Result
Quit during a running turn; next own message Typed Kept message, then /compact New own message Next turn Next turn → Kept message → /compact PASS
Quit during a running turn; Resume /compact, then typed Kept second message Existing Resume 1 chat button Resume continuation → /compact → Kept second message PASS
Genuinely accepted but unused typed message Typed Actually kept after message, then /compact New own message Next turn after kept New own message → recovered typed message → /compact PASS

The first two rows use ordinary waiting cards; the label Kept message is fixture text. The third row proves actual unused-message recovery: the host journal records that recovery, and the provider received the typed frame but never initialized or started a turn before the real app.quit(). The valid third-row setup used an existing conversation after a completed warmup turn. Every relaunch used the same profile. All restored current-head queues stayed quiet before release (at least 15 seconds, over 90 seconds for Resume). The pending-start case offered no Resume action, so its next own message was used. The opposite input orders in the first two runs were submitted deliberately; Resume did not reverse the queue.

The full, uncropped screenshots below agree with the provider logs, renderer states and read-only journal snapshots.

After b6cbc76 — typed then /compact, released by the next own message

The final capture includes the existing Enjoying Orca rating popover; the delivered transcript remains readable.

After b6cbc76c74b, before real mid-turn quit: typed card first, /compact second

After b6cbc76c74b: reopened quietly behind the existing interrupted-chats dialog

After b6cbc76c74b: next own turn running, typed then /compact still waiting

After b6cbc76c74b: next own message, typed message and /compact all completed in order

After b6cbc76 — /compact then typed message, released by Resume

The prequit capture includes the existing rating popover. The real Resume click showed the existing Resumed 1 chat feedback.

After b6cbc76c74b, before real mid-turn quit: /compact first, typed card second

After b6cbc76c74b: quiet reopened chat with the existing Resume 1 chat action

After b6cbc76c74b: pointer-clicked Resume, continuation running, /compact then typed card

After b6cbc76c74b: continuation, /compact and typed message all completed in submitted order

After b6cbc76 — genuine kept message before /compact

After b6cbc76c74b: typed submission accepted, /compact command card waiting before quit

After b6cbc76c74b: recovered typed card first, /compact second, quiet and without kept captions

After b6cbc76c74b: next own message running with kept typed message before /compact

After b6cbc76c74b: next own message, recovered typed message and /compact completed; no cards left

Earlier-head comparison — fc7a25199a7a6cfa0f5cf50929443d27519e3444: submit typed Actually kept before message, then /compact, and quit before provider initialization. Both reopen quietly in that order, but the typed card says “Not sent yet — press Send to send it.” After Next turn before kept, only the new own message and /compact run; the recovered typed card remains waiting. Its journal row retains the old per-message hold. No manual Send or deletion was used to repair this comparison. On b6cbc76c74b, the next own message releases the typed message before compaction, and both finish.

Before fc7a251 — kept typed message stays waiting while /compact runs

Before fc7a25199a7: typed submission first, actual /compact command card second, before real quit

Before fc7a25199a7: quiet restored cards in order, with the retired typed-message caption

Before fc7a25199a7: next own message running, typed card still held ahead of /compact

Before fc7a25199a7: /compact completed after the own message, but the recovered typed card remains unsent

Pre-existing limitation on both tested heads: /compact submitted in a fresh chat before provider initialization shows the exact inline refusal “/compact is not supported by this chat host.” The text stays in the composer and no command card is created. The fresh-chat probe reproduced the same result at fc7a25199a7 and b6cbc76c74b; it is separate from the passing initialized-conversation recovery case above.

Same early fresh-chat refusal on both heads

Before fc7a25199a7: early /compact refusal, text retained, no command card

After b6cbc76c74b: identical early /compact refusal, text retained, no command card

This focused run checks the real Windows native-chat host and renderer with a protocol stand-in. Real-agent, phone, SSH, folder-workspace and other desktop-platform flows were not checked in this round.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

New and updated tests:

  • Host, structured-agent-session-queued-compact.test.ts (real host rig). /compact waits as a card behind:

    • an unanswered message,
    • a running command turn,
    • a pending approval,
    • a refused earlier message.

    Also covered:

    • a replay answers from the card, then its submission, with one run;
    • Send is refused mid-turn and works once idle (after Stop);
    • a later send queues behind it;
    • at rest it runs at once;
    • without the opt-in it is refused as today;
    • after a restart, a kept message stays ahead of a waiting /compact; the chat's next accepted turn releases both, and compaction runs only after the kept message;
    • Delete; Stop then Resume;
    • refused by the agent, or refused before it starts (background tasks): the card is spent, there is exactly one failure row in the reason's words, no hand-off is recorded, and the next card drains (the agent refuses every compaction, so a loop or block would show);
    • a failed write of the refusal never drops the card without its row;
    • a failed agent start returns the card instead of spending it;
    • /clear drops command cards;
    • delivery parses only as queue-if-active, and a /clear sent with it is refused by the host with nothing queued.
  • Host, structured-conversation-command-admission.test.ts and structured-agent-session-rewind.test.ts: the unified Working rule.

  • Desktop, use-structured-agent-session.queued-gating.test.tsx. Lit:

    • the opt-in is sent with fingerprint parity;
    • behind a message on its way, Send is busy (Stop), the message reads Sending, nothing is armed, and the next press sends;
    • a send stuck behind one in doubt: Stop takes it out of line (kept on screen with its Retry), and the command can go;
    • after a Stop kept the earlier message on screen, /clear names its Retry and /compact goes;
    • a refused command names what it waits on (working, prompt, background, sending, retry); a failed send drops "still being sent", a resend drops "Retry";
    • /clear behind only a failed message names its Retry, and after a Stop names no Retry it doesn't show;
    • mid-turn, a queue send on its way reads "Sending…" as a card and nothing is armed;
    • a send behind a waiting command card queues, even with follow-ups off.

    Dark: exactly today's behaviour, plus the plain words.

  • Desktop, structured-conversation-command-send.test.ts (holds, the in-flight second command, every sentence), structured-agent-session-queued-cards.test.ts, and NativeChatQueuedMessageList.test.tsx (no Steer, Send only while idle, no Edit, Delete and Resume work).

  • Shared, agent-session-refusal-notice.test.ts, and returned-draft-text.test.ts (a lone /compact or /clear gives way to the message handed back; /clearly is kept), and structured-agent-session-coalescer.test.ts (a queue list lands at once).

  • Phone: mobile-structured-composer-command.test.ts, mobile-structured-agent-session-host-support.test.ts, mobile-structured-queued-message-cards.test.ts, MobileNativeChatQueuedMessages.test.tsx.

  • Ablations (each behaviour removed, tests fail, then restored):

    Behaviour removed Tests that fail
    Card admission 9 of the compact tests
    Unified rule 3
    /clear filter 2
    Spent settlement both refused-card tests
    Refused-before-start row 1
    Taking nothing behind an unsent message 3
    In-flight second-command words 1
    Retry words 2
    Send on an idle command card 2
    /compact words 1
    Edit hidden desktop and phone card tests
    Spending only when the command's turn exists the failed-start test
    No hand-off record before the refusal 2
    The refusal's reason words 2
    Sending cards mid-turn 1
    A lone command giving way 1
    Recorded sends are no sending card 2
    Queue lists skip coalescing 2
    "Run /compact again" after the wait 2
    Only /compact and /clear give way 1
    Retry vs sending words 2
    Send-failed caption matching Send desktop and phone caption tests

Earlier directory runs, by explicit file list (historical evidence, before the current head):

  • src/main/native-chat/agent-session-wire and agent-session-journal: 220 of 221 files pass; one can't load locally (see below). Two restart tests hit temp-directory races once under load and pass on a rerun.
  • src/renderer/src/components/native-chat and src/renderer/src/runtime: 471 files pass.
  • src/shared: 866 pass; 11 can't load locally.
  • mobile/src/session: 217 files pass.

Gates: localization (catalogs, extraction, coverage) passes. The sentences are hand-translated in es/fr/ja/ko/zh, and the runtime English catalog was regenerated. Typecheck: web, node and cli show no errors beyond the known stream-json/stream-chain ones. The mobile app and mobile tests show nothing new: only the existing missing generated-file errors, and every src/session error file is already in the ratchet baseline. Locally, the full oxlint over every file this PR changes (the changed-lines gate can't see max-lines), anti-slop, the changed-code quality gate and React Doctor pass.

Current head b6cbc76c74b includes main through 7f43d9b2c26, the ordered recovery integration, and the failed-send fixture correction. Web, node and CLI typechecks passed, and all 22 static checks passed. The initial explicit-file host/renderer run had 573 passing files and 5,482 passing tests; its recovery test failure was corrected and the full compaction file then passed 23/23. Four files added by the latest main merge passed 43/43. Four failures remain in two unchanged main test files: three exact elapsed-time labels drifted under load, and a historical-edit stream test exceeded its 30-second limit while recording zero repeated edit work. Their source and components have no PR changes; no broader rerun or unrelated timeout fix was made. Final-head CI completed successfully: all 16 checks that ran passed, including all five test shards, static analysis/typechecking, both packages, mobile verification/bundling, relay integration and cross-version wire compatibility. Sixteen other checks were skipped; they are not counted as passes.

Review

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Mixed versions: ConversationCommandParams is strict, so delivery is sent only after the host advertises agent-session.queued-commands.v1, and only while it also advertises the queue. A queued command card is a card body the queue already publishes (AgentJournalMessageItem with its existing optional command).
  • Rebase overlap with fix(native-chat): every chat send ends one of three ways, decided by the host's answer #25207: the desktop command pre-check and the phone command dispatch. Small and mechanical.
  • "Turn off queueing" has no effect while a command card waits, because later sends still queue behind it to keep send order. Temporary: the follow-up is to hide that menu item on a waiting command card.
  • The queue's hold ignores background tasks and handoffs, so a card it admits may be refused at hand-over. That is now said once, in the command's turn, with the reason. Temporary: the follow-up is to make the queue's hold wait on background tasks and handoffs too.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

…nly; a /compact behind an unsent message waits for it quietly
…mmand card offers Send while the agent is idle; /compact behind an unsent message is not taken
…mand-waits-in-line

# Conflicts:
#	src/main/native-chat/agent-session-wire/structured-agent-session-queued-mutations.ts
…y; refuse a queued command without a hand-off, with its reason; a queue send on its way reads as sending
…d at once; a spent card's wait says to run it again; only /compact or /clear give way to returned text
…mand-waits-in-line

# Conflicts:
#	src/renderer/src/components/native-chat/use-structured-agent-session.ts
…under the line limit; the send capabilities get their own module
… own unsent message says it is still being sent
…nt beside the others; main's send capabilities back to its text
…mand-waits-in-line

# Conflicts:
#	src/renderer/src/components/native-chat/use-structured-agent-session.ts
…mand-waits-in-line

# Conflicts:
#	mobile/src/session/mobile-structured-queued-message-cards.ts
#	mobile/src/session/use-mobile-structured-queued-message-controls.ts
#	src/main/native-chat/agent-session-journal/journal-dispatch-settlement.ts
#	src/main/native-chat/agent-session-journal/queued-message-settlement.ts
#	src/main/native-chat/agent-session-journal/queued-message-table.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-queued-mutations.ts
#	src/renderer/src/components/native-chat/NativeChatQueuedMessageCard.tsx
#	src/renderer/src/i18n/locales/en.json
#	src/renderer/src/i18n/locales/es.json
#	src/renderer/src/i18n/locales/fr.json
#	src/renderer/src/i18n/locales/ja.json
#	src/renderer/src/i18n/locales/ko.json
#	src/renderer/src/i18n/locales/zh.json
…kept like any card; kept-card captions name only controls shown
… is gone

A refusal that names something the chat shows (the agent working, a pending prompt, background
tasks, an unsent message) is said only while that still holds, derived each render, and dropped
once it ends. Other composer errors are unchanged.
… gone

The phone's banner keeps a refusal naming the agent working or a pending prompt only while the
chat still shows it, dropped each render once it ends. Background tasks, which the phone can't
see, and generic errors behave as before. The host-reason mapping is shared with desktop.
…t is being sent or offers Retry

Each line now goes when its own state ends: a send that fails stops being sent, and a resend
stops offering Retry.
@brennanb2025

brennanb2025 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Native chat refuses /compact while earlier work is unfinished because the command bypasses the message queue and is tried immediately. After a quit or close, a message Orca accepted but never handed to the agent could also be kept separately from a waiting command, allowing the command to pass it.

This PR puts /compact and kept messages in one ordered queue on the machine running the agent. Reopening sends neither automatically; Resume or the next accepted turn releases them in order. A refused command explains itself once and lets later messages proceed. The queue remains off in shipped builds; waiting commands become available with its launch. Until then, busy commands still refuse in plain words once. Waiting /clear is the separate stacked PR #25842.

Review fixed commands running after Stop, cards offering unavailable actions, refusal settlement blocking the queue or reporting twice, and a message briefly appearing twice. A command refusal spends its card only when its own turn records the reason; failed starts return the card for retry. The final sync with main at 4f4f021f8a1 preserves those rules while adopting main's desktop sender: it sends one message at a time, holds unsettled text in memory, returns failed text to the composer, and leaves accepted messages owned by the host. Sending cards and command admission now read that sender; /clear still holds new sends while moving to a replacement chat. Small existing operations and types were moved to satisfy the source-size limit, with no rule suppression.

Deferred limits remain in the PR body: attachments can bypass the text queue; Cmd/Ctrl+Enter does nothing when the newest card is a command; turning follow-up queueing off cannot move later messages ahead of a waiting command; and background work can cause an admitted command to be refused when its turn comes. The fresh-chat early /compact refusal, /compact is not supported by this chat host., was reproduced on both the earlier head and the QA head, retaining the text with no command card; it is pre-existing and outside this PR.

Final head: b15c5976d3aa26b64e36b17984c9e01a9754e6a4, after a conflict-only sync with main at a4854ac1e9696c7fb620f084b1a7ef59adfa9777. The sole conflict resolution keeps command-queue and workspace-attachment capabilities together, preserves the grouped skill capabilities, and removes the unused skill-result export. Node, web and CLI typechecks passed sequentially through the machine queue after deleting stale build info. Protocol compatibility, capabilities and the changed consumers passed 14 files / 236 tests. All 22 local CI static checks passed on this commit, and the lockfile exactly matches merged main. Final-head GitHub CI finished with 21 checks passed and 16 skipped, including all ten test shards, relay integration, mobile verification, static analysis, both packages and cross-version wire compatibility. All 37 reported checks completed; skipped checks are not counted as passes, and there is no red check to classify. The earlier review recorded 79 files / 906 tests, 10 files / 113 tests, and the real-Claude suites' 2 files / 12 tests on 47f4087be855ffdcdd8ca425e7d07e94f55a0191; those broader runs were not repeated for this conflict-only sync. The earlier local mobile collection failure remains attributed to that head; no local mobile tests were run for this sync.

Rendered recovery QA passed on b6cbc76c74b, using a hidden Windows app with the queue enabled only in its isolated build and a scripted stand-in agent. It verified quiet reopen, both submitted card orders after a next turn or Resume, and a genuinely accepted but unused message running before /compact without the retired kept-message caption. The PR body contains 18 fresh round-4 images and retains all 11 earlier images with their original head attribution. The earlier comparison at fc7a25199a7 left the kept message behind while /compact ran; the QA head delivered the new turn, kept message and command in order.

After the final main sync, a fresh review (round 10) found no problems in the merge and listed seven behaviours it could have changed. Rendered QA round 5 then re-checked all seven on 47f4087be85 (hidden Windows app, scripted stand-in agent, queue on): quiet reopen after a quit; the next message, the kept message and /compact going out in order with follow-ups on and off; Resume running its carry-on first, then the waiting cards in their saved order; a message the host had accepted before the quit coming back as a quiet card; /compact waiting behind an earlier message still being sent; a refused /compact explaining itself once without blocking the next message; and /clear while a message is unsettled. All passed. 25 round-5 images are in the PR body.

One pre-existing main bug found, not caused by this PR: text typed while a successful /clear is running ends up saved under the old session, so the new session's box is empty. Main before this PR (4f4f021f8a1) does the same, and so does this PR with the queue off. It needs its own fix.

The later conflict-only sync to b15c5976d3a changed only the capability list. The newer main commits it brought in touch composer attachment previews, file drop, OMP/OpenCode chat, workspace references and a fingerprint helper refactor; none touch the queue, waiting commands, restart recovery or /clear, so the round-5 QA still covers this head. No phone UI, SSH or mixed-version UI QA is claimed.

Main sync 4 (a3114b7f9b4) and one fix (62bde788186). Main's #26553 (never refuse a queued card because 20 were waiting) and #26543 (never refuse a write because the retry record is full) conflicted with this PR in four files. The resolution keeps both: no count limit or queue-full notice comes back, and /compact still waits in line. An independent review of the merge found one problem, now fixed: #26553 keeps part of the queue's space free for the person's own messages, but a queued /compact didn't say it came from the person, so a queue already full of background messages refused it. It now carries the same "sent by the person" marking an ordinary message gets at the same point (never taken from what a client sends), and a new test shows the person's /compact accepted and a background one refused at that limit. A second review of the fix was clean. Locally: 100 tests in the 6 affected files and the main-process typecheck passed. CI on 62bde788186: all test shards, static analysis and typecheck, cross-version wire compatibility, both packages and the mobile checks passed; the rest were skipped by path. These changes touch only how much queue space a person's /compact may use, so the round-5 rendered QA above still covers the screens.

@brennanb2025
brennanb2025 marked this pull request as ready for review October 8, 2026 08:01
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: aaddb9e4-91b0-4f34-b02e-0120495e5aee
📥 Commits

Reviewing files that changed from the base of the PR and between b15c597 and 62bde78.

📒 Files selected for processing (30)
  • mobile/src/session/use-mobile-native-chat-controller.ts
  • mobile/src/session/use-mobile-native-chat-session-lane.ts
  • mobile/src/session/use-mobile-structured-agent-session-prompt-cancel.test.tsx
  • mobile/src/session/use-mobile-structured-agent-session.ts
  • mobile/src/session/use-mobile-structured-send-with-outcome.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-command-turn.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-compact.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-message-rig.test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-messages.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-mutations.ts
  • src/main/native-chat/agent-session-wire/structured-conversation-command.ts
  • src/main/native-chat/agent-session-wire/structured-conversation-compaction.ts
  • src/main/runtime/rpc/methods/structured-agent-session.ts
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.test-harness.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.tsx
  • src/renderer/src/components/native-chat/agent-session-failure-words-text.ts
  • src/renderer/src/components/native-chat/agent-session-write-notice-text.ts
  • src/renderer/src/components/native-chat/use-structured-agent-session.ts
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/shared/agent-session-failure-copy.ts
  • src/shared/agent-session-failure-words.ts
  • src/shared/agent-session-write-failure.ts
  • src/shared/agent-session-write-notice-copy.ts
  • src/shared/protocol-version.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-messages.ts
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/en.json
  • src/shared/agent-session-write-notice-copy.ts
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/i18n/locales/ja.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review.


📝 Walkthrough

Walkthrough

The changes add capability-gated queued /compact delivery and update host queue processing, command admission, and journal settlement. Renderer and mobile clients project queued commands and pending sends into cards, adjust card actions, and track refusal causes in error notices. Shared refusal copy, localized guidance, prompt-response handling, returned-draft behavior, and queue-frame coalescing are also updated.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 62bde

No identified issue currently blocks merging. Queueing remains opt-in, and the checked rewind path preserves command ordering.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.69% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 64 functions across 57 files. (7 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description is complete and directly matches the template. It explains the user impact, implementation, rationale, linked-issue exception for a maintainer change, visual QA, automated testing, lim…
Title check ✅ Passed The title clearly identifies the primary change: /compact now waits in the queue while the agent is working instead of being refused.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 54.69% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 64 functions across 57 files. (7 skipped: 7 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
mobile/src/session/use-mobile-native-chat-send-error.ts (1)

72-78: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reset refusedWhile when the hold timer or a scope change clears the message.

show stores refusedWhile. The 4-second timer, clear, and the scope-change effect clear only message. A later show(next) without a cause sets the cause to undefined, so the banner logic stays correct. The stale cause is still kept in state after other clears. This is a small consistency fix. Clear both values in the same places.

mobile/src/session/use-mobile-structured-agent-session.ts (1)

214-228: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse isWorking instead of computing the working state a second time.

Line 228 calls isStructuredAgentSessionMainAgentWorking(turnId, state.submissions, state.fence). Line 167 already computes that value as isWorking. Pass isWorking to the hook instead. This keeps both values tied to one source.

♻️ Proposed change
-    agentWorking: isStructuredAgentSessionMainAgentWorking(turnId, state.submissions, state.fence),
+    agentWorking: isWorking,
src/renderer/src/components/native-chat/use-structured-agent-session.ts (1)

225-237: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Move the hook call out of the object literal.

Line 230 calls useStructuredAgentSessionHostQueuesCommands(target) inside the returned object spread. The call is unconditional, so hook order stays stable. Lint rules and later edits can still break it, for example if someone adds a short-circuit before it. Move the call to a top-level const.


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 943c2825-f533-4909-a683-db3eb9de4cc1
📥 Commits

Reviewing files that changed from the base of the PR and between a4854ac and b15c597.

📒 Files selected for processing (94)
  • config/tsconfig.node.json
  • mobile/src/session/MobileNativeChatQueuedMessages.test.tsx
  • mobile/src/session/MobileNativeChatQueuedMessages.tsx
  • mobile/src/session/mobile-dictation-refused-start-routing.test.tsx
  • mobile/src/session/mobile-native-chat-controller-contract.ts
  • mobile/src/session/mobile-native-chat-merged-snapshot-parity-hooks.test.tsx
  • mobile/src/session/mobile-structured-agent-session-contract.ts
  • mobile/src/session/mobile-structured-agent-session-host-support.test.ts
  • mobile/src/session/mobile-structured-agent-session-host-support.ts
  • mobile/src/session/mobile-structured-composer-command.test.ts
  • mobile/src/session/mobile-structured-composer-command.ts
  • mobile/src/session/mobile-structured-queued-message-cards.test.ts
  • mobile/src/session/mobile-structured-queued-message-cards.ts
  • mobile/src/session/use-mobile-native-chat-controller.ts
  • mobile/src/session/use-mobile-native-chat-send-error.test.ts
  • mobile/src/session/use-mobile-native-chat-send-error.ts
  • mobile/src/session/use-mobile-native-chat-session-lane.ts
  • mobile/src/session/use-mobile-session-native-chat-dictation.ts
  • mobile/src/session/use-mobile-structured-agent-session-prompt-cancel.test.tsx
  • mobile/src/session/use-mobile-structured-agent-session-queued.test-fixture.ts
  • mobile/src/session/use-mobile-structured-agent-session.ts
  • mobile/src/session/use-mobile-structured-queued-message-controls.ts
  • mobile/src/session/use-mobile-structured-send-with-outcome.ts
  • mobile/src/session/use-mobile-structured-turn-indicator.test.tsx
  • src/main/native-chat/agent-session-journal/journal-dispatch-settlement.ts
  • src/main/native-chat/agent-session-journal/queued-message-settlement.ts
  • src/main/native-chat/agent-session-journal/queued-message-table.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-command-turn.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-mutation-plans.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-command-refusal.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-compact.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-message-rig-provider.test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-message-rig.test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-messages.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-mutations.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-rewind.test.ts
  • src/main/native-chat/agent-session-wire/structured-conversation-command-admission.test.ts
  • src/main/native-chat/agent-session-wire/structured-conversation-command-admission.ts
  • src/main/native-chat/agent-session-wire/structured-conversation-command.ts
  • src/main/native-chat/agent-session-wire/structured-conversation-compaction.test.ts
  • src/main/native-chat/agent-session-wire/structured-conversation-compaction.ts
  • src/renderer/src/components/native-chat/NativeChatQueuedMessageCard.tsx
  • src/renderer/src/components/native-chat/NativeChatQueuedMessageList.test.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.command-refusal-line.test.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.notice-card.test.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.test-harness.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.tsx
  • src/renderer/src/components/native-chat/agent-session-failure-words-text.test.ts
  • src/renderer/src/components/native-chat/agent-session-failure-words-text.ts
  • src/renderer/src/components/native-chat/agent-session-write-notice-text.ts
  • src/renderer/src/components/native-chat/native-chat-composer-types.ts
  • src/renderer/src/components/native-chat/native-chat-mock-slot-types.test-support.ts
  • src/renderer/src/components/native-chat/native-chat-structured-composer-dispatch.ts
  • src/renderer/src/components/native-chat/native-chat-structured-send-composition-clear.test.tsx
  • src/renderer/src/components/native-chat/structured-agent-session-prompt-response.ts
  • src/renderer/src/components/native-chat/structured-agent-session-queued-cards.test.ts
  • src/renderer/src/components/native-chat/structured-agent-session-queued-cards.ts
  • src/renderer/src/components/native-chat/structured-conversation-command-send.test.ts
  • src/renderer/src/components/native-chat/structured-conversation-command-send.ts
  • src/renderer/src/components/native-chat/use-native-chat-composer-notice.ts
  • src/renderer/src/components/native-chat/use-native-chat-structured-composer-send.test.tsx
  • src/renderer/src/components/native-chat/use-native-chat-structured-composer-send.ts
  • src/renderer/src/components/native-chat/use-structured-agent-session-command-send-gate.test.tsx
  • src/renderer/src/components/native-chat/use-structured-agent-session-command-write.ts
  • src/renderer/src/components/native-chat/use-structured-agent-session-queued-messages.ts
  • src/renderer/src/components/native-chat/use-structured-agent-session-write-refusal.test.tsx
  • src/renderer/src/components/native-chat/use-structured-agent-session.queued-gating.test.tsx
  • src/renderer/src/components/native-chat/use-structured-agent-session.ts
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/runtime/structured-agent-session-host-capability.ts
  • src/shared/agent-session-command-refusal-words.ts
  • src/shared/agent-session-conversation-command.ts
  • src/shared/agent-session-failure-copy.ts
  • src/shared/agent-session-failure-words.ts
  • src/shared/agent-session-refusal-notice.test.ts
  • src/shared/agent-session-refusal-notice.ts
  • src/shared/agent-session-write-failure.ts
  • src/shared/agent-session-write-notice-copy.ts
  • src/shared/protocol-version.ts
  • src/shared/returned-draft-text.test.ts
  • src/shared/returned-draft-text.ts
  • src/shared/rpc-contract/structured-agent-session-params.ts
  • src/shared/skill-install-capability.ts
  • src/shared/structured-agent-session-coalescer.test.ts
  • src/shared/structured-agent-session-coalescer.ts
  • src/shared/structured-agent-session-command-refusal-cause.ts
  • src/shared/structured-agent-session-command-turn-identity.ts
  • src/shared/structured-agent-session-composer.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.

@brennanb2025
brennanb2025 marked this pull request as draft October 8, 2026 19:10
@brennanb2025
brennanb2025 marked this pull request as ready for review October 8, 2026 20:12
@brennanb2025
brennanb2025 merged commit 4735ece into main Oct 8, 2026
56 checks passed
brennanb2025 added a commit that referenced this pull request Oct 9, 2026
Send and /compact now route on acceptsWithCommandReceipt: main made /clear and
rewind settlesWithWrite plans with their own success receipts, and they stay on
ledger settlement. /compact keeps #25704's queued answer under receipt replay.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant