Repository navigation
fix(native-chat): start Windows chats without reading process creation times - #25718
Conversation
…n times
Native chat on Windows refused to start ("Orca can't run this agent in a chat
here") whenever the process-table addon could not report process creation
times. Chat never needed them; only the bookkeeping around stopping the agent
did.
Windows now follows the common pattern: Stop ends the agent's tree with
`taskkill /T /F` on the child Orca still holds, and reports the tree gone only
when taskkill exits 0. A saved pid is never signalled after a restart.
- Remove the Claude and Codex location gate and the Codex launch refusal.
- A start time that cannot be read is recorded as unknown instead of refusing
the session; recovery already releases such an owner without signalling it.
- Delete Claude's Windows creation-time descendant snapshot and its verifier.
- Codex's Windows teardown reports the real taskkill outcome.
- The renderer no longer waits on the capability flag; the host keeps
publishing it for older clients (temporary).
…oven close On Windows an idle Claude leaves on its own once its stdin ends, so every Stop and close read as unproven: live background work settled as unknown and the trace logged a close that "did not finish cleanly". As with the Codex close, that exit is now the close and Orca makes no claim about processes Claude started; a forced close still rests on taskkill's own report. Also drop the Settings clause about Windows needing process start times, and fix comments and the tracked process-enumeration doc that still described the removed start-time gate and descendant snapshot.
An owner recorded without a process start time could never renew: the renewer re-proves every live owner by PID identity, and with no start time and no spawn-token echo that probe is indeterminate. The lease's last renewal then stayed at the spawn, so a turn cut by an Orca crash was dated to its own start, and every tick logged a failed renewal and split the batch into one store transaction per chat. The runtime now renews a lease for a child it still holds at the record's fence and whose exit it has not received, recorded as a `held-child` match. Receipt of the exit ends that proof before the exit is settled, and a restart holds no child, so a dead owner's lease still expires and restart adjudication is unchanged. Records this runtime does not hold keep the PID probe. Also correct the identity probe's comment about shipped addons and note that recovery's stop ladder is POSIX-only.
…tried close A Windows close counts Claude leaving on its own after its stdin ends as the close. That shortcut also caught a retried close whose first attempt forced a taskkill that failed: once the root exited, the retry returned true and the failure read as a proven close. The tree reaper now records whether a reap ever reached the live root, here, on an earlier close or from a transport failure, and the shortcut applies only when none did; otherwise taskkill's verdict stands and no new taskkill runs against the exited root. Pin the platform on the existing tests that assume the POSIX close, and say what `exit-proven` means on Windows in the acquisition-failure docs.
…wn handle Lease renewal trusted a held child until the host settled its exit, and the host hears of an exit late: Claude runs its close ladder and a store write first, unexpected exits wait on one delivery chain shared by every chat, and a Claude close that cannot prove its tree publishes nothing at all. A dead root could keep renewing through that window, so a crash in it dated the cut turn late. Renewal now asks the adapter, which owns the process handle and sees the exit first: a child is held only while it is on record at the lease's fence and its adapter still runs that exact acquisition with no root exit seen. An adapter that cannot answer falls back to the PID probe. The stored exit-received mark is gone. The held-child read is now required by the runtime state and the renewer, and a host-level test drives renewal through the real host wiring.
…agent-tree-job-object # Conflicts: # src/renderer/src/i18n/locales/es.json # src/renderer/src/i18n/locales/ko.json # src/renderer/src/i18n/locales/zh.json
…agent-tree-job-object Main moved the provider close ladder into the shared managed-process close (#25204) and kept the Windows creation-time refusal in Codex launch resolution. Resolved by keeping that refusal removed, taking main's pinned config variable, and re-expressing this branch's Windows close rules on the shared close: the Windows teardown reports taskkill's verdict ('exited' on exit 0, else 'unverifiable'), and a Claude root that leaves on its own after stdin end with no forced reap on its tree is a proven close (Claude's close policy on win32).
…agent-tree-job-object Main deleted the Claude and Codex location-support tests (#25791) that this branch had edited; the deletion is kept. The Codex launch-resolution test still pins that a Windows host without process creation times starts a chat.
|
Review and QA summary The problem. On Windows, native chat (Claude and Codex) refused to start whenever Orca couldn't read process start times, for example when the native add-on that reports them failed to load. Users saw "Chat could not be started." with a Retry that never helped. The chat itself never needed those times. Orca used them only as bookkeeping for stopping the agent. What changes for the user
What the review fixed
Deferred
Verified
Not verified
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (16)
💤 Files with no reviewable changes (2)
🚧 Files skipped from review as they are similar to previous changes (6)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review. 📝 WalkthroughWalkthroughThe changes revise Windows provider-process exit proof to use taskkill’s result or an eligible natural root exit, while retaining POSIX descendant-snapshot proof. Claude and Codex structured-chat support no longer depends on Windows process-start-time availability, and owner identities can have a null start time. The host lease renewer can use a matching, live child held by its runtime as identity evidence. Windows recovery no longer signals a saved owner PID. Runtime status and renderer capability data no longer expose the process-start-time availability field. Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to No actionable merge-blocking regression is established by the reviewed evidence. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 47.06% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 51 functions across 51 files. (6 skipped: 6 unsupported.)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
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. Comment |
…agent-tree-job-object Main (#25159) kept the Windows creation-time refusal in Codex launch resolution and moved the pinned config variable onto the Codex agent definition; the refusal stays removed and main's pin is taken. Main's host constructor grew to its line limit, so the held-child read moves into the runtime state: it now takes the host's conversations (required) and builds the renewer's read from them and the adapter.
…agent-tree-job-object Main (#22302) gave the Codex launch resolver a launch-directory pin, changed its test store fakes and added a test passing the creation-time seam this branch removed. Kept main's store shape and new test without that seam, and kept this branch's Windows test that resolves a launch without creation times.
ELI5
On Windows, native chat would sometimes refuse to start: Orca treated the chat as unsupported on that machine. It refused because Orca couldn't read the time each process was started. Orca only used those times as bookkeeping for stopping the agent later; the chat itself never needed them. Now Windows stops the agent the common way, by ending the process tree of the agent Orca launched and still holds, so chat no longer depends on those times and always starts.
What Changed
The problem. Orca reads Windows process start times through a native process-table add-on. Whenever that add-on couldn't report them (for example, it failed to load), native chat for Claude and Codex was refused outright. Structured chat checked for this in three places:
Start times were used only to stop the agent safely on Windows. Claude took a snapshot of the agent's child processes with their start times, so a later forced kill could never hit an unrelated process that had reused a process ID. After a restart, the same times decided whether a saved process ID still belonged to our agent.
Before → after for the user
Mechanism
taskkill /T /Fon the agent process it launched and still holds. It reports the agent's processes as gone only whentaskkillexits 0; otherwise it reports "couldn't confirm". This applies to both Claude and Codex.windows-descendant-exit-verification.ts), plus its now-unused process-walk helper.windowsProcessStartTimeAvailablefrom the runtime status and the shared contract once those clients are out of support.macOS and Linux behave as before, apart from the startup throw being gone.
Why
The common pattern stops the agent on Windows with a tree kill on the child process it still holds, and needs no start times. Because Orca still holds the child, the process ID can't belong to anyone else while Orca uses it, which is exactly the protection the start times were adding.
Differences from the common pattern, labelled:
taskkill /T /Fon it.Linked Issue
N/A: maintainer change, from an internal report.
Visual Proof
Windows (high-spec test machine), isolated test profile, stand-in agents. To reproduce a machine that can't read process start times, the creation-time add-on was hidden in each build. The runtime status confirmed the flag was absent on both builds.
9def4b9ba19. After = this branch at6935e0de2dafor the start-up screenshots, and at1f17327cc28for Stop.Before: Claude and Codex chats both fail to start ("Chat could not be started." with Retry), and the sidebar shows the chat as failed.
After: the Claude chat starts and answers. The Codex chat opens as a native chat, but its stand-in crashed on this machine, so no reply is shown.
After, Settings: the scope line no longer mentions process start times.
After, closing a chat with background work running: no "status unavailable" or any other new text appears.
Stop with a running tool (after =
1f17327cc28with start times hidden; before = main with them available). Both read "Stopped.", with no notice or new status text, and look the same.Testing
Tests that now assert the new behaviour:
taskkillon the held root;taskkillresult.Test runs:
Windows QA (stand-in agents; after = this branch, before = main):
Not verified:
taskkillfailure on Windows. Unit tests only.1f17327cc28, before those merges.Real Claude CLI suite: run once on the final head, 10/10 passed.
Review
Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.Notes
taskkill.exeper stop, as before.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)