Repository navigation
fix(native-chat): offer resume after restart for chats whose only work was in the background - #27167
Conversation
…background The quit started the chat teardown and then stopped the hook server, which emptied the status store holding each chat's subagents and background commands. The teardown reads that store to decide which chats were still working, so a chat whose turn had finished but whose background command or subagent was still running was never offered to resume after a restart or update. The quit now stops hook ingress without clearing the store.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to Quit teardown can retain the status needed to offer eligible chats for resume. No identified issue prevents merging after normal checks. Pre-merge checks |
|
|
When Orca quit or restarted after an update, a native chat could finish its main reply while a background command or subagent was still running. Hook shutdown cleared the status records before chat teardown read that work, so the chat disappeared from the next launch’s Resume dialog. This change preserves the existing records during quit until each chat captures its unfinished work before stopping the agent. Chats interrupted with background work are offered in the existing Resume dialog; work that already finished stays absent. Two review rounds retained the production approach and added ten permanent regression cases to the existing Claude and Codex runtime tests. They cover commands and subagents, quit and update, saved recovery information, the Resume list after restart, and finished-command controls. Independent architecture, correctness, regression, readiness and final merge reviews found no proven meaningful code findings. No code findings were deferred. At Remote Electron QA on M4Air verified a real native Codex chat with a completed reply and a live background command. After the production restart path, the saved recovery candidate matched that chat and command; the rendered Resume dialog offered it, and clicking Resume 1 chat restored the conversation with the normal continuation prompt and an agent reply. The development server stopped during automatic relaunch, so the dialog was checked on a fresh dev launch of the same saved profile after the production restart. Rendered QA did not exercise Claude, subagents, finished-work exclusion, dismissal, the actual update installer, remote-server restart, live SSH/WSL or other platforms. The provider, command/subagent and finished-work cases above have automated coverage. The PR remains unmerged. Before restart: the native Codex chat starts its command. The later recorded session history confirms that the reply finished while the command stayed active. After restart and a fresh launch of the saved profile: the existing Resume dialog offers the interrupted chat. After clicking Resume 1 chat: the conversation contains the continuation prompt and reply. |
…k was in the background (#27167) * fix(native-chat): offer restart resume for chats whose only work was background The quit started the chat teardown and then stopped the hook server, which emptied the status store holding each chat's subagents and background commands. The teardown reads that store to decide which chats were still working, so a chat whose turn had finished but whose background command or subagent was still running was never offered to resume after a restart or update. The quit now stops hook ingress without clearing the store. * test: preserve background-only chat resume across shutdown (cherry picked from commit 2201653)
…k was in the background (#27167) * fix(native-chat): offer restart resume for chats whose only work was background The quit started the chat teardown and then stopped the hook server, which emptied the status store holding each chat's subagents and background commands. The teardown reads that store to decide which chats were still working, so a chat whose turn had finished but whose background command or subagent was still running was never offered to resume after a restart or update. The quit now stops hook ingress without clearing the store. * test: preserve background-only chat resume across shutdown (cherry picked from commit 2201653)



ELI5
When Orca quits or installs an update, it notes which chats were still working so it can offer to pick them up after the restart. A chat whose agent had finished replying but still had a background command or a subagent running was missing from that list. Orca was throwing away its record of that background work a moment before checking it.
What Changed
Before: say a chat's agent finished its reply but left a background command running, like a long wait for another agent's report, or a subagent still working. The sidebar shows it as working. Then Orca restarts for an update. After the restart, the "Resume" dialog doesn't list that chat. The background command is gone, and the chat just shows a red "Claude stopped while this response was in progress" row. Nothing carries on unless the user notices and types something.
After: that chat shows up in the Resume dialog alongside the others, with its background work named. Resuming asks the agent to carry on, as it already did for chats that were mid-reply.
Mechanism: before Orca stops each chat's agent at quit, it takes a snapshot to decide whether to offer that chat for resume. A chat whose own reply had finished counts only if its subagents or background commands were still running. Orca keeps those in the agent-status store inside the agent hook server. The quit sequence (
main-process-quit.ts) starts the chat teardown without waiting for it, then immediately callsagentHookServer.stop(), which empties that store. The chat teardown waits on other work before it takes any snapshot, so every snapshot read an empty list and judged these chats finished.agentHookServer.stop()now takes a quit-only{ keepStatus: true }. It still stops the hook listener and saves terminal status exactly as before, but leaves the in-memory store for the chat teardown to read. The process exit frees that memory.Why
This is a regression from #22614 (merged 2026-09-30). Resume offers for chats whose only remaining work was a subagent or background command came in with #22560 (09-24). At that point the quit snapshot read each chat's background work from the agent adapter's own task tracker, which lives in the chat host and survives the quit. #22614 moved every reader of that work, including this snapshot, onto the hook server's agent-status store. It did not account for the quit stopping and clearing that store before the snapshot runs. The tests that cover this case run the chat host without the real quit sequence, so they kept passing. From #22614 on, Claude and Codex chats with only background work at quit were never offered.
Seen on a real update: one restart dropped 4 chats this way. Each had finished its reply while a background command was still running, and the agent's own journal shows the command stopped and the turn cut by the quit. Every chat that was offered had a reply in progress, which the snapshot can see without the store.
Alternatives considered:
killAllPty(). Otherwise terminal panes exiting during quit would clear agent statuses that are meant to survive the restart.Keeping the store alive through quit fixes the ordering itself, so every chat-status reader is covered, not just this one.
Linked Issue
N/A (maintainer). Found from a user report after an Orca update.
Visual Proof
N/A. The visible change is that one more row appears in the existing Resume dialog. Hitting this case live needs a real update restart with a chat in exactly this state. The proof is the journal evidence above and the tests below.
Testing
New hook server test: subagent and background-task records stay readable after
stop({ keepStatus: true }), and a plainstop()still clears them. It fails without the fix.New quit-sequence test: the quit stops the hook server with
keepStatus. It fails without the fix.src/main/agent-hooksandsrc/main/startuptest suites pass.orca-ci-checkspasses (24/24 locally, typecheck included).Platforms: macOS locally. The quit path is shared by all platforms.
I manually tested these changes locally
Automated tests added/updated, or explained why not below
Review
Agent skill upstream boundary
Notes
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)PR author: @BrennanKB5