Repository navigation
A kill that reached the agent ends it, so the next message after Stop goes through - #34653
Conversation
…message goes through
After Stop, tab close, idle rest or workspace sleep, Orca force-kills the
agent. It used to accept the old agent as gone only when it saw the exit
report within about a second; otherwise every later message re-ran the kill
and was refused with "Couldn't stop {agent} from before." A kill delivered to
the agent itself now ends it and releases the chat with kill-delivered
evidence; the refusal remains only when the kill could not reach the agent.
When writing the chat's journal fails and the following kill can't be
confirmed, recovery now records the close with its fault instead of silently
returning, so the turn no longer stays Working and later sends retry the stop.
Tracked in STA-12354 and STA-12355.
|
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:
Walkthrough
Priority: Merge Risk:
|
There was a problem hiding this comment.
Actionable comments posted: 2

Review info
-
Run configuration-
- Source mode: Auto
- Repository: Unavailable
- Branch: Unavailable
- File: No configuration file from this repository applied
- Commit: Unavailable
- Layers: Repository UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
b2f0a5bd-9331-4e01-a3cd-6ae2a38ffb1c
Files selected for processing: 56-
config/vitest.config.tssrc/main/acp/acp-agent-connection.test.tssrc/main/acp/acp-agent-connection.tssrc/main/acp/acp-detached-cleanup.test.tssrc/main/acp/acp-structured-child-lifecycle.tssrc/main/acp/acp-structured-connection.tssrc/main/acp/acp-structured-session-adapter.tssrc/main/acp/acp-structured-session.tssrc/main/claude/claude-agent-sdk-exit-proof.test.tssrc/main/claude/claude-agent-sdk-exit-proof.tssrc/main/claude/claude-stream-json-connection.tssrc/main/claude/claude-structured-acquisition-launch.tssrc/main/claude/claude-structured-session-close.tssrc/main/claude/structured/claude-structured-session-state.tssrc/main/codex/codex-app-server-connection.tssrc/main/codex/codex-structured-acquisition-lifecycle.tssrc/main/codex/codex-structured-session-close.tssrc/main/codex/codex-structured-session-teardown.tssrc/main/ipc/pty-spawn-saved-resume-admission.test.tssrc/main/native-chat/agent-session-wire/structured-agent-session-acquisition-errors.tssrc/main/native-chat/agent-session-wire/structured-agent-session-acquisition-route.tssrc/main/native-chat/agent-session-wire/structured-agent-session-adapter-router.tssrc/main/native-chat/agent-session-wire/structured-agent-session-adapter.tssrc/main/native-chat/agent-session-wire/structured-agent-session-attach-failure.tssrc/main/native-chat/agent-session-wire/structured-agent-session-child-close.tssrc/main/native-chat/agent-session-wire/structured-agent-session-child-exit.tssrc/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-exit-ends-record.test.tssrc/main/native-chat/agent-session-wire/structured-agent-session-codex-input-host.test.tssrc/main/native-chat/agent-session-wire/structured-agent-session-current-work.test.tssrc/main/native-chat/agent-session-wire/structured-agent-session-event-recovery.tssrc/main/native-chat/agent-session-wire/structured-agent-session-failed-create-refusal.tssrc/main/native-chat/agent-session-wire/structured-agent-session-host-types.tssrc/main/native-chat/agent-session-wire/structured-agent-session-lease-release.tssrc/main/native-chat/agent-session-wire/structured-agent-session-provider-exit-proof.tssrc/main/native-chat/agent-session-wire/structured-agent-session-queued-quit.test.tssrc/main/native-chat/agent-session-wire/structured-agent-session-restart-interruption-test-harness.tssrc/main/native-chat/agent-session-wire/structured-agent-session-stale-turn-open.test.tssrc/main/native-chat/agent-session-wire/structured-agent-session-workspace-sleep-stop.tssrc/main/pi/rpc-session-adapter.tssrc/main/pi/rpc-session.tssrc/main/provider-process/managed-provider-process-fallback-tree.test.tssrc/main/provider-process/managed-provider-process.tssrc/main/provider-process/managed-provider-writer-close.test.tssrc/main/provider-process/provider-acquisition-starts.tssrc/main/provider-process/provider-process-close.tssrc/main/provider-process/provider-process-teardown.test.tssrc/main/provider-process/provider-process-teardown.tssrc/main/provider-process/supervised-child-process-stop.tssrc/main/runtime/agent-session-acquisition-exit-transition.tssrc/main/runtime/agent-session-acquisition-failure-settlement.tssrc/main/runtime/agent-session-death-evidence-persistence.test.tssrc/main/runtime/agent-session/ownership/agent-session-surface-release-transition.tssrc/main/runtime/structured-agent-session-codex-goal-stop-settings.test.tssrc/main/runtime/structured-agent-session-pi-kill-retry.test.tssrc/main/runtime/structured-claude-runtime-adapter.tssrc/shared/agent-session-record.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.
-
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

Minor · Use an in-memory transaction for the late… · structured-agent-session-lease-release.ts:46-79
src/main/native-chat/agent-session-wire/structured-agent-session-lease-release.ts:46-79
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse an in-memory transaction for the late evidence upgrade.
When no live child matches,
settleStructuredAgentSessionChildExitcalls the upgrade.transitionHandoffcallsmutatewithout transaction options, so a read-only store rejects the upgrade. The rejection propagates fromstructured-agent-session-event-recovery.handle, and the record remainskill-delivered.Forward an optional transaction option through
mutate, and enable it only for this evidence-only transition.Suggested fix
transitionHandoff = ( sessionId: string, - transition: (record: AgentSessionRecord) => AgentSessionRecord - ): Promise<AgentSessionRecord> => this.mutate(sessionId, transition) + transition: (record: AgentSessionRecord) => AgentSessionRecord, + options: { inMemoryWhenReadOnly?: boolean } = {} + ): Promise<AgentSessionRecord> => this.mutate(sessionId, transition, options) ... private async mutate( sessionId: string, - apply: (record: AgentSessionRecord) => AgentSessionRecord + apply: (record: AgentSessionRecord) => AgentSessionRecord, + options: { inMemoryWhenReadOnly?: boolean } = {} ): Promise<AgentSessionRecord> { - return this.transact((draft) => { + return this.transact((draft) => { const record = requireWritableAgentSessionRecord(draft, sessionId) const next = apply(record) draft.records.set(sessionId, next) return next - }) + }, options) }- await store.transitionHandoff(event.sessionId, (current) => { + await store.transitionHandoff(event.sessionId, (current) => { if ( current.lease.claimStatus !== 'released' || current.lease.deathEvidence?.kind !== 'kill-delivered' || @@ } } } - }) + }, { inMemoryWhenReadOnly: true })

Review info
-
Run configuration-
- Source mode: Auto
- Repository: Unavailable
- Branch: Unavailable
- File: No configuration file from this repository applied
- Commit: Unavailable
- Layers: Repository UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
c59e1b2f-fa2f-4449-8e4a-3ec2b972dc67
Files selected for processing: 3-
src/main/claude/claude-stream-json-connection.tssrc/main/native-chat/agent-session-wire/structured-agent-session-current-work.test.tssrc/main/runtime/agent-session-death-evidence-persistence.test.ts
Files skipped from review as they are similar to previous changes: 1-
- src/main/claude/claude-stream-json-connection.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.
-
[High impact] No actionable code issue was found; the author's stated runtime QA gate still applies before merging. SummaryThe PR lets a delivered kill end the current agent child and release its ownership fence without waiting for a missing exit callback.
No new actionable issue was found. This review did not run tests or runtime QA. Acknowledged limitations in the PR description supplied by
|
|
After Stop force-killed an agent, a missing exit callback could leave later sends waiting on the old process. A journal failure could also leave a turn Working without showing its failure. The PR carries confirmed writer termination through the existing ownership and failure-settlement paths, and keeps unknown termination conservative. Four formal review rounds are complete, with zero new findings in round 4. Fixes include teardown evidence, same-child close-result retention, failed acquisition and attachment, and exact-child Stop feedback through cached and already-retired close paths. Independent pause, interrupt, workload and request errors retain their existing feedback. Final source, reference, performance and readiness reviews agreed. QA evidence is on 87d49d9. After the pre-QA main sync, a proven merge conflict required integrating pinned main 54fa316. Independent review confirmed the two test-infrastructure resolutions and erased Pi return-type repair preserve the exercised behavior. Current head: b602e74. CI GREEN: same-head watcher completed successfully; primary campaign 40897984016 covers static analysis/typechecking, ten unit shards, packaging and cross-version checks; campaigns 40897983863 and 40897983986 cover WSL/templates and three-platform runtime checks. Mandatory hooks and nine retained Stop-to-SQLite contract cases passed after the final fixture maintenance; the prescribed merge hook also passed. Temporary: the pre-existing Windows wrapper-exit authority boundary remains tracked in STA-12558 under the binding scope ruling. Optional late same-fence refinement remains deferred without a confirmed user-visible failure. The required QA round is complete. Accepted evidence covers a real graceful upgrade with preserved settings, setup, default tabs and histories; two Claude/Codex replies; normal published Sleep/wake; Claude and Codex Stop/reply; Claude and Codex journal-failure recovery (including the retained-close legitimate wake); and both agents' failed-attachment/reopen/reply and acquired-unpublished Sleep/cancel/wake/reply. The final Codex Stop capture shows the actual clean wind-down, no new warning, real next reply and late-event isolation. Windows Pi termination, its closeAll continuation and its existing queued-card recovery/reply are accepted, with the first forced stop distinguished from the later graceful same-profile restart. Historical instrumentation gaps remain disclosed in the private ledger. Supplemental new-kind reload and folder contracts are covered by tests and the accepted upgrade rather than duplicate app campaigns. Windows Claude termination, real next reply and late-callback isolation are accepted after independent source/artifact review. Its session-only acknowledgment and absence of a Codex composite outcome are disclosed rather than replaced with fabricated fields. Windows Codex termination is also accepted: default process-tree termination returned true while the original callback was held; independent queries found the recorded writer processes absent; the exact child’s kill-delivered receipt released the captured ownership fence; Stop showed Interrupted; one new message produced a real reply under the sole successor. The complete observed Codex outcome retained root=unproven with delivered termination, workload=exited, acknowledged pause, accepted interrupt and no errors. Restoring the genuine old callback left the successor intact. A fresh restoration acknowledgment preceded return to the driver. ACP output-failure lifecycle evidence is accepted: actual resolver rejection, automatic close, released ownership, ordinary same-native reopen and a completed real reply. On reopen, native history imported the failed prompt and one provider assistant record with five lines beneath a ‘Continued outside this chat’ divider; independent source and saved-artifact tracing classifies that attribution as a pre-existing P2 tracked in STA-12826, with no demonstrated PR regression or history loss. ACP acquired-unpublished cancellation/wake/reply is accepted; its helper’s exact text locator missed the actual trailing period, with completion independently confirmed in UI and persisted records. Owned copies and controllers were stopped and cleanup verified. The earlier failed attempts remain failed; the accepted outcomes come from the later completed attempts. The final Windows Codex screenshot shows Interrupted and the successor request, but its assistant text is outside the captured viewport; the actual DOM, loaded state and persisted completed turn independently contain the new reply. The pre-send image was stale and is not draft proof, and the requested tool yield argument was not exposed. No result is inferred from those missing fields. For Brennan’s review: three judgment points are irreversible writer-delivery evidence, release of the captured owner fence, and Stop feedback that retains independent errors. For Brennan’s review: whole-window captures of each exercised flow. Visible outcomes are supported by process, ownership and persistence artifacts; screenshots alone do not establish those facts. QA screenshots| Windows Codex F10 Interrupted and completed successor request; reply text confirmed by DOM and persistence | |
































Problem and behavior
After Stop force-killed an agent, a late or missing exit callback could leave the native chat permanently closing. Later provider actions repeated the stop ladder and could refuse with “Couldn't stop {agent} from before.” A journal-write failure could likewise leave a turn Working because recovery abandoned the unconfirmed close.
An irreversible kill delivered to the conversation writer now settles the child and releases its existing ownership fence with
kill-deliveredevidence. The next message resumes the same conversation without repeating the kill ladder just to rediscover that fact. If writer termination remains unproven, Orca retains the closing child and retries through the existing action path. Next-turn option intent can still be saved without waiting for a provider close; old approval cards remain tied to their original child.Journal failure retains the existing host-fault cause while closing. Once writer death is established, the turn ends with the existing failure presentation and a later send can resume. Without death proof, the child remains closing with that fault retained until a legitimate termination or exit; this does not manufacture a successful close.
Mechanism and compatibility
The common pattern is to finalize a stopped context and serialize the next operation. The intended difference is Orca's durable ownership fence across chat, terminal and paired clients: failed termination cannot authorize another writer.
Scope and validation
Full review path: this changes process lifecycle, ownership, recovery and persisted evidence. The pre-code plan was independently reviewed; the review loop found and repaired evidence-retention, detached-cleanup and evidence-forwarding defects in place. Brennan's 10-27 scope ruling keeps this PR on the two reported bugs. The pre-existing case where a wrapper exits while its writer survives is a temporary limitation tracked in STA-12558; this PR does not claim to replace root-exit authority with a new process-containment system.
Four formal review rounds are complete. The final production review, reference comparison and readiness review passed on the current head, with no new confirmed findings. Main was integrated before QA. A later proven merge conflict required integrating pinned main 54fa316; independent review confirmed that the two test-infrastructure resolutions and compiler-erased Pi return annotation preserve the QA’d behavior. Targeted production-contract tests run through actual Claude connections, managed teardown, routing, host/journal and SQLite settlement, including failed acquisition, healthy continuation, retained non-root exits and close before acknowledgment; three controlled pre-fix cases reproduce the wrong evidence kind. The Stop feedback consumer also accepts the exact child’s delivered termination, including cached and already-retired close paths, so a missing root callback alone does not produce an unconfirmed Stop warning. Independent pause, interrupt, workload and request errors still produce their existing feedback. Mandatory commit hooks passed.
CI is green on current head
b602e74d21a4b8a43fde4bdc6c2440694a9d1bbd(primary run 40897984016, WSL/templates 40897983863, three-platform runtime 40897983986). The exact-head watcher completed successfully, covering static analysis/typechecking, the test shards, persistence, cross-version compatibility and packaging. Final maintenance uses the canonical test-fixture provider-handle reader; all nine retained Stop-evidence cases and mandatory hooks passed.The required runtime QA round is complete on
87d49d9adef8f274defad4b165a909af68751bf9, carried across the reviewed main integration above. Accepted evidence covers a real graceful previous-build upgrade preserving setup results, default tabs, settings and histories, plus two Claude/Codex replies; published Sleep/wake; both agents’ Stop/continuation, journal-failure recovery, failed attachment/reopen/reply, and acquired-unpublished Sleep/cancel/wake/reply. Windows Claude and Codex termination both reached Interrupted and a real next reply, with independent writer absence, ownership release and genuine old-callback isolation. The final Codex outcome is observed as pause acknowledged, interrupt accepted, root unproven, workload exited, kill-delivered and errors empty. Windows Pi termination, closeAll continuation and existing queued-message recovery are accepted. OpenCode exercised ACP output-failure/automatic-close/reopen/reply and startup cancellation/recovery.The final review comment links 32 original whole-window captures. Historical failed attempts remain failed, with their instrumentation and containment limits preserved in the private evidence ledger. The last Windows Codex image shows Interrupted and the successor request but omits the reply paragraph from its viewport; actual DOM, loaded state and the saved completed turn confirm the distinct reply. Its pre-send image was stale, and the requested tool yield argument was unexposed. These are disclosed capture limits, not fabricated passes. Owned QA copies, controllers, leads and readers are stopped and both machine admissions released.
A temporary, pre-existing P2 observed during ACP recovery is tracked in STA-12826: recovered output from the same local request can be labelled as an outside continuation. Independent source and saved-artifact review confirmed the misleading attribution without demonstrating a PR regression or history loss; the failed turn remains and the next reply completed. Recovery presentation is unchanged in this PR.
Tracked in STA-12354 and STA-12355. Earlier attempts: #25866 and #24507 (left open).