Repository navigation
Native chat: every agent takes a message while it starts, and Stop ends the session for every agent - #26561
Native chat: every agent takes a message while it starts, and Stop ends the session for every agent#26561brennanb2025 wants to merge 16 commits into
Conversation
…ain) Rebuilds #26561 on main now that #26416 is squash-merged. Same change as before, re-applied onto what main has since: - Every adapter answers acquire at spawn and reports `started` on protocol readiness with its real handle (Claude initialize, Codex thread, ACP session new/load plus restore, Pi session file plus restore). No bridge, no per-adapter phase or Stop opt-outs. - Picks made while starting are intents applied model then effort before the start is accepted; rewind, goal, rewind recovery and compact wait for a proven start outside the session queue. - One Stop rule: Stop ends the session for every agent (Codex: interrupt, up to 2 s for the turn to end, then close). - Orchestration worker starts share one deadline; a send's answer copies its row; a re-attach during start keeps the start wait. Integrated with main: - ACP: the subagent-stop probe, child-work delivery and new/loaded origin move into the handshake; the sign-in rule (#26544) classifies a failed handshake; acpAgentName stays in acp-structured-agent-definitions. - Codex: the session journal translator and account kind (#26407) reach the start step. - Pi: the start choice (#26821) and the signed-out verdict (#26743) are read in Pi's start, so both exist when `started` is reported; commands follow. - openWithAgent keeps main's pre-agent check and replay rule. - A report with no model drops the saved one, as #26587 decided. - The renderer re-reads a start's sign-in verdict once the start is proven.
a0a8038 to
1a07fc6
Compare
…ad wait out an agent's start A signed-out Grok, OpenCode or OMP that wrote to stderr before refusing its start showed that log line instead of its sign-in message. A sign-in refusal now keeps the agent's own words; other start failures keep the stderr tail. While a chat's agent proves its start, the model-catalog read answers listingInProgress and a waiting read waits the start out (bounded), so a client that re-reads only then still hears Pi's signed-out verdict.
The gap it closed exists only for a desktop app built between #26743 and this change; no released app shows the Pi notice yet, and the first send still says not signed in. Not worth a held read on every agent's start.
Review summaryReviews: two rounds on the original branch, plus a fresh full review of the rebuild on current main (1a07fc6). The rebuild review found no P0/P1. It checked file by file that main's behaviour survives: the first message travels with the create call (#26332), learned defaults (#26407/#26821), Grok subagent Stop (#26508), the empty-model rule (#26587), and the Pi sign-in notice (#26743). Fixed after the rebuild:
Visual proof (in the body), on Windows with stand-in agents and screenshots checked against the stand-in logs:
CI: cross-version wire compatibility fails on main's own "kiro" search tests, and the verify job only reports that result. All five test shards and both package jobs pass. Not verified: real Codex (whether its background terminals and subagents end when the app-server closes), a second message sent while the agent starts (the claim comes from the code), Pi/OpenCode/OMP live, and SSH/WSL/macOS/Linux. Whichever of this PR and #26982 merges second needs a sync with main. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
|
ELI5
While an agent finishes starting, a native chat used to hold later messages at “Sending…” and hide its model and effort pickers. The first message already appeared immediately; this change makes later sends immediate too, keeps saved picks visible, and makes Stop end every agent’s session, including Codex’s background work. The next message resumes the same conversation.
What Changed
The chat becomes addressable as soon as its process exists. The execution host holds accepted messages in the durable journal, finishes the handshake in the background, records the real provider handle, applies saved picks, and delivers only after the single started signal. A silent start ends after 60 seconds; output can extend it only to ten minutes. Codex’s mandatory start requests use that same host deadline.
Final correctness fixes
Why
A spawned process is owned before its protocol session is ready. Separating those facts lets Stop, messages, picks and reads remain responsive without sending protocol calls too early. Holding input and startup deadlines on the execution host also lets remote work continue through client contact loss. Descendant cleanup must track process identities across separate process groups; signalling one group cannot prove that all commands ended.
Differences from the common pattern
Linked Issue
None; maintainer change. Builds on #26416 and #26332.
Visual Proof
These are hidden Orca dev builds on a Windows test machine. The agents are stand-ins: small scripts that speak the Codex app-server protocol and Grok's ACP protocol. No real agent ran. "Before" is this PR's base,
2cb2bef67e3(main), and "after" isa6c3a0fada3. For every screenshot, the time it was captured was checked against the stand-in's own log.1. Sending a message while the agent starts. The stand-in takes 8 s to answer
initialize. Open a new chat, type "hello" and press Enter at once. Each screenshot was taken 1.5–5 s after Enter, before the stand-in had answered.initializeanswer).2. Stop ends Codex's background work. The Codex stand-in's first turn starts a background terminal (
npm run dev) and leaves it running when the turn ends, the way Codex does. While its app-server process is alive, the stand-in writes a line to its log every 2 s. A second turn keeps working, then Stop is pressed.Main. Stop interrupts the turn only. Ten seconds later the running-tasks card still shows "1 shell command". The background terminal kept writing its 2 s log line until the test app was shut down 3 minutes later (Stop at 23:26:33.72, still logging at 23:29:45). The next message ran on the same app-server.
This PR. Stop interrupts the turn, then closes the app-server. The stand-in logged:
turn/interruptat 23:15:01.93The card is gone in the screenshot captured at 23:15:11.91–14.63. The next message started a new app-server, which resumed the same thread (
thread/resumewith the first app-server's thread id) and answered.What this does not prove. The stand-in fills the running-tasks card the way Codex does: a background command whose turn has ended while the command is still running. A real Codex was checked separately on macOS, as described in "What the user sees now".
3. Live QA across macOS, Windows and an SSH host (dev builds of this PR vs main, hidden windows driven over the DevTools protocol, screenshots checked against agent or stand-in logs; real agent homes hashed before and after, unchanged).
Real Codex 0.159 (macOS): Stop with a background shell and a running subagent. With this PR the card clears and both shells are gone within 2 s (still gone at 30 s), and the next message resumes the same thread. On main both keep running and the subagent keeps spending tokens (23.6k at Stop, 95.2k 90 s later).
A second message while the agent starts (stand-ins, 8–20 s start). Main shows it as "Sending…" and holds further sends; this PR shows it at once and delivers both in order (checked for Codex, Grok, OpenCode, OMP and Pi).
A saved model pick stays on screen while the agent starts (head 05ccab6; the pickers are disabled during a start that a message triggered). Codex Terra/High, Grok 4.7/Low and Pi Sonnet 4/High each show in every frame from the send to after the start; a pick the agent refuses goes back to what it runs.
Start limits are the host's for every agent (head 5c66c69). A Codex that answers
initializeafter 25 s starts normally (it used to be cut off at 15 s); one that never answers is ended at 60.0 s with the host's wording. A signed-out Pi starts once and the message settles with Pi's sign-in line (an earlier head restarted it in a loop).SSH host: the client's connection drops during a 25 s start (throwaway Debian SSH host running this build's managed server). The host keeps starting, delivers the held message during the outage, and the reply is on screen at reconnect; the app only says the host is reconnecting.
Testing
Previous QA at 05ccab6 covered real Codex and Claude on macOS, all five stand-in agents on Windows, and SSH. These are earlier-head results, retained above for context.
Targeted registration/start-deadline/signed-out tests: 51 passed. Folder-scoped first-frame, learned-default, older-client fallback and catalog tests: 57 passed. Cleanup/Stop/router tests: 96 passed; the five-second deadline cases passed; the restored connection/teardown suite passed 39 tests after the new grandchild case failed against the old root-only close.
The single real Codex hung-process probe on macOS froze Codex after starting foreground and background commands. Close reported root and workload exited in 4.317 seconds; all marked processes stayed gone through the 30-second observation. The user's configuration hash, excluding project trust entries, was unchanged. This probe tested teardown directly, not rendered UI.
Final pre-push checks on
34e53888a3d: 24/25 passed, including all four CI-pinned typechecks, root lint, changed-code quality, localization and runtime/wire checks. Full native typechecks and the freshly synced full anti-slop check also passed. The remaining local mobile import-cycle warning is the documented false red in unchanged files; remote static analysis passed.CI on
34e53888a3d: all 19 required checks passed, with no failures or pending checks. All five unit-test shards, package jobs, cross-version wire compatibility, relay, macOS/Linux/Windows runtime, persistence and verification passed; 14 path/platform-selected checks were skipped.The corrected queued Stop test reproduces the original timeout under Node, then passes 27 affected tests after advancing its frozen five-millisecond fixture timer before awaiting the Stop lane. Every assertion and timeout is preserved; product Stop, delivery and five-second grace code are unchanged.
The coordinator reported four macOS rechecks passing on the same production diff at
18ec576514e: real Codex Stop with stopped subagent row and shells gone, held startup picks, folder-scoped first frames, and a second startup message. The final commit changes only the test clock.The coordinator owns rendered UI rechecks; this implementation worker launched no Electron app.
I manually tested these changes locally
Automated tests added/updated
AI Disclosure
AI coding agents (Codex and Claude Code).
Review
Four architecture reviews agreed on publish-at-spawn, execution-host holds and one readiness signal. They identified descendant-exit evidence and option ownership as the material remaining gaps; this update completes the pre-merge fixes and leaves the larger consolidation to draft stacked PRs.
Agent skill upstream boundary
Notes
Checklist