Repository navigation
AI buttons stop writing a launch record - #28209
Conversation
5fd4004 to
2fee7f2
Compare
|
Closing and reopening to trigger CI after the retarget to main. |
7395063 to
b05ffd5
Compare
…it starts even when the record store cannot open
…user close, and E's leftover prompt store write, hold release and stale comment go
… with its own id, as the real store does, so an AI-button launch is not read as closed by the user
…rds the tab, so an agent that starts late is stopped, not shown
b05ffd5 to
328c23e
Compare
|
Status: ready for review. Merge together with #28210, this one first. Head Reviews. Round 1 (fresh reviewers) found 1 P2 and 4 P3s:
Round 2 found one wording fix (an agent that starts late is stopped, not shown), now fixed. Then a CI fix: the shared launch-test store now keeps a tab made with its own id, as the real store does (test only). No open findings. Syncs with main. Two syncs with main, approved by the lane owner: the first for #28351, the second for #27692, which #28210 needed. This PR needed no change in either. Checks on this head.
Live QA. This PR ships together with #28210, so live QA ran on #28210's head, which contains this one. See #28210's status comment. This PR's own visible change was QA'd on an earlier head: an AI button starts even when the launch record store can't be opened. Main dropped the click silently: its tab appeared and closed, with no notice and no agent. On this PR, Claude started and answered the prompt. Not verified. This PR alone, without #28210, was not QA'd live. It never ships alone. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to
|
ELI5
When you click an AI button such as "Fix checks", Orca opens a tab and asks the host to start the agent in it. Until now the host also wrote a bookkeeping entry for that click (a "launch record"). If that record store couldn't be opened, the click was silently dropped: its tab appeared and closed at once, with no agent and no message, even though nothing was wrong with the agent. Nothing ever reads that entry back, so this PR stops writing it, and the click no longer depends on it.
What Changed
The problem. Since #25624, an AI button's click is started by the host's
agent.launchunder an operation id, so the host writes a launch record for it. After #28043 (merged), nothing reads those records back for AI buttons:admitAndClaimOperation,agent-launch-replay.ts:206-207). The window never resends: it makes one id per click and calls once (agent-launch-through-host.ts, onecallRuntimeRpc, no retry).structured-agent-session-create.ts:100,structured-agent-session-agent-start.ts:232,structured-agent-session-failed-create-refusal.ts:203,structured-agent-session-create-adoption.ts:36) look up their own chat operations, never a terminal launch's. Session History, the phone's lists, the agent status store,worktree psand the dashboard don't read launch records at all.#25624 described the record as being for "replay after a restart", and said of AI buttons: "the window still delivers their prompt (main's paste), so for them delivery is not host-owned: no host receipt, no replay of the prompt after a restart." It also said "Bookkeeping never blocks the click", yet a record store that couldn't open still refused the click.
What you'll see differently.
An AI button starts its agent even when the launch record store can't be opened. Before, the click was dropped silently: its tab appeared and closed at once, with no notice, no toast and no agent (seen in live QA).
Temporary, until AI-button and OpenCode-model tabs start their agent in their own terminal #28210 lands: a failed AI-button launch closes its tab and shows "The agent couldn't start." with Copy prompt as a notice at the corner of the window, instead of inside the tab. The notice gives that short line without the reason the tab used to add (for example "Its command wasn't found on this machine.").
Temporary, until AI-button and OpenCode-model tabs start their agent in their own terminal #28210 lands: an AI-button launch whose outcome can't be confirmed no longer shows "Couldn't confirm the agent started." inside the tab. If the agent's terminal had already appeared, the tab stays and the same words show as a corner notice with Copy prompt. If the start was lost before the terminal appeared, it reads as "The agent couldn't start." and the tab closes; an agent that did start after all is stopped, because the closed tab's record refuses its terminal (as main does for any closed tab).
Temporary, until AI-button and OpenCode-model tabs start their agent in their own terminal #28210 lands: while this PR is on its own, when an AI button's agent appears, Orca switches to its workspace and focuses its terminal even if you moved on.
Temporary, until AI-button and OpenCode-model tabs start their agent in their own terminal #28210 lands: an agent that starts after its failed tab was closed is stopped, not shown. AI-button and OpenCode-model tabs start their agent in their own terminal #28210 removes this: the tab's own terminal starts the agent, so there is no separate late start.
All four temporary changes end with #28210, where the tab's own terminal starts the agent and says again, inside the tab, how it ended. That includes the corner notice "Couldn't confirm the agent started." shown when the host fails after the agent's terminal appeared: it is temporary too.
Based on current main. This PR and #28210 merge together, this one first, so the temporary changes never ship alone.
Nothing else changes. "+" tabs, phone, CLI and orchestration launches still name an operation and keep their record. The prompt is still pasted by the window once the agent is ready, as before.
Mechanism.
agent.launchwith no operation id (it calledagent.launchReplaywith one). The host's existing no-id path runs: no record is opened or written, and no tab is shown ahead of the agent. The pane key is still sent, so the agent starts in the tab the window made, and the host's reveal of that terminal lets the tab's waiting pane attach, as it already does for a pane the host never showed early.terminal-surface-close.ts,pty-binding-refusals.ts).Why
"Bookkeeping must never gate a user action": a record nothing reads should not be able to refuse a click. Dropping the operation id uses the host's existing no-id path instead of adding a fallback. The alternative, keeping the record and starting anyway when it can't be written, keeps writing entries that nothing reads.
What the window gives up: an answer to a resend it never makes; AI clicks no longer count toward the desktop's 512-a-day launch cap, and can no longer be refused by it.
Linked Issue
Part of the launch-convergence plan (restart step, follow-up 3 folded in). Builds on #28043 (merged); merges together with #28210, this one first.
Visual Proof
N/A in this PR alone: it ships together with #28210, whose live QA covers the AI-button rows.
Testing
I manually tested these changes locally
Automated tests added/updated
Starts without a record. A reserved pane launched with no operation id starts its terminal in that pane and never opens the launch record store, which is unavailable in the test (
agent-launch-pane-reservation.test.ts).No operation id sent. The AI button's request is
agent.launchwith the pane key and no operation id, and each click has its own pane (agent-launch-through-host.test.ts).Temporary failure surface. A failure before the agent's terminal appeared closes the tab and reports "couldn't start"; a failure after it appeared keeps the tab and reports "couldn't confirm"; a tab the user closed reports nothing (
agent-launch-through-host.test.ts,launch-agent-new-tab-host-route*.test.ts). The shared launch test store now keeps a tab made with its own id, as the real store does, so the caller suites don't read every AI-button launch as closed by the user. The temporary surfaces get no further tests, since AI-button and OpenCode-model tabs start their agent in their own terminal #28210 removes them.Verified:
tc:node,tc:web, the changed-code quality check, oxlint, and the layout-writer check pass; every test file that imports a changed module passes.Size
Measured with
git diff --numstat <base> HEAD -- src, TypeScript only; test files count as tests and locale JSON on its own. Against main: production −10, tests +4, locale strings 0.AI Disclosure
Review
Agent skill upstream boundary
Notes
Ensure no issues in: Security, Cross-platoform support (Linux, Windows, Mac), Remote SSH, Mobile, general backwards compatibility, performance
agent.launchwithout an id is the method's original contract, which every host supports.Checklist
N/Awith reason (ships with AI-button and OpenCode-model tabs start their agent in their own terminal #28210)