Skip to content

fix(terminal): the chat view returns to the terminal when the agent quits to the shell - #30804

Open
brennanb2025 wants to merge 48 commits into
mainfrom
brennanb2025/bug-terminal-pane-remains-stuck-in-chatview-when
Open

brennanb2025 wants to merge 48 commits into
mainfrom
brennanb2025/bug-terminal-pane-remains-stuck-in-chatview-when

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 52 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​4077 $\color{#cf222e}{\Huge{\mathbf{−}}}$​388 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​3689
Prod 123 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​3171 $\color{#cf222e}{\Huge{\mathbf{−}}}$​309 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​2862

Problem

Quitting an agent can leave Chat selected over a shell because its terminal title never changes. Text entered in the composer can then execute in the shell. Tracked in #30613; includes the reporter's contribution from #30614, credited as co-author.

User-facing change

When the execution host confirms that the agent interface has released the terminal, desktop and phone return to Terminal. Chat stays available through slow launch and recovery. The user's saved Chat choice and phone draft remain intact so a later launch can select Chat again. Commands, aliases, functions, folder workspaces and existing close confirmation keep their behavior.

How it works

The execution host maintains a runtime terminal observation independently of turn completion and sidebar rows. Consumers derive Chat availability from that observation and the current terminal identity. Discovery continues after a completed turn, a silent quit or an unmounted pane. The common pattern keeps observations with their execution owner and delivers them independently of session structure.

The existing command-finished path owns its delayed fresh confirmation and removes the same turn's sidebar row before reconciliation. Foreground presentation observations must not cancel that obligation. Process lifetime remains separate: a current local hook owner can retire only after sustained explicit no-children evidence and the existing binding, input, owner and recovery checks.

Process inspection shares host-wide table captures and keeps the existing cheap steady-state checks. Periodic renderer inspection preserves main's live-agent exit confirmation and adds no confirmation demand beyond main. The phone consumes the existing observation event and joins it with its session tabs; observation changes must cause no browser reads, persistence requests, tab projections or structural version changes. Browser membership, titles and URLs remain owned by ordinary session publication.

Existing capability negotiation preserves older clients and hosts without a minimum version. Missing names, unavailable reads and contact loss do not prove departure. Input does not wait for observation or cleanup. Launch commands and the existing raw-input path remain unchanged; no observation or cleanup result becomes a send guard.

Verification status

This PR is not ready to merge. The pushed candidate is 29892a7, following 95a288a and the accepted merge with exact main bb47718. Independent review approved the exact scheduler and fixture correction. The normal commit hook passed, and the committed tree equals the reviewed candidate. The complete formatted contribution is 3046 canonical production lines against that main revision, within the 3053-line ceiling. The one standard CI watch failed on unit shard 3/5. All other workflows and selected PR checks passed, including static analysis/typecheck, mobile, shard 2/5, WSL, Headless and packaged Windows D7. Both failures are in the startup-mobile fixture after it changes mocked inventory without a notification. The broader source audit also found direct connectivity changes during retained-PTY output and floating liveness that can bypass observation discovery. A production edge correction is being prepared before correcting the fixture; no unchanged retry is planned.

The observation owner now keeps one timer for the first needed 250 ms admission slot and skips empty slots. Existing PTY creation, identity, input, activity, launch completion, recovery, stop and sleep events wake that same owner. A fast entry can rearm while a slower wave peer is still pending. Native-work limits, currentness and age proof, publication grouping and the command-finished confirmation are preserved. The earlier fixture also now stops its real hook-server owner before restoring the clock. Focused gated checks provide passing evidence for 91 distinct cases across recorded runs, including the unchanged seven-frame bound, native-operation contracts and whole-flow Chat recovery. The idle fixture identified a separate machine-name startup timeout and awaits existing readiness before asserting zero wakeups and inventory work over 60 seconds, then discovering a real newly registered PTY. These checks do not establish CPU savings or runtime latency.

Incoming main's live-agent exit confirmation, its wiring and regression suite are preserved. The operation contract requires the same confirmation count as main. At N=10 and N=100 it checks one shared ordinary full capture, then one shared fresh successor after releasing the held confirmations, with no cheap or narrow capture in that controlled wave. The generic daemon result remains unchanged. This is a deterministic work bound, not a latency measurement. Host observation carries the actual dispatch time with each coalesced inspection result, excluding time queued before dispatch consistently from both conservative capture bounds. The age limit, input and identity fences, unavailable behavior and ownership of native work are unchanged. The whole-flow regression covers unavailable and stale evidence, input during a read, coalesced successors, conservative cached age, manual re-entry and preserved draft/settings.

The targeted M4Air diagnostic run reproduced successful Chat shortcut entry after fg on 57a8490, 95a288a and main bb47718. The earlier shortcut failure did not reproduce. The header Continue action is refused while the live CLI holds the conversation, through the same writer gate on 95a288a and main; this is inherited behavior, not a PR regression. The older 57a8490 header trace has a coverage gap. The complete 95a288a refusal trace had a qualified foreground observation and no queue-age rejection. No foreground correction is selected.

On the diagnostic 95a288a comparison, all three zsh row cases, sh Claude Ctrl+C and bash Codex Ctrl+C passed. Three sh row cases still exceeded main by more than 150 ms: Codex /exit, Codex Ctrl+C and Claude /exit. Every slower case was removed by the same-turn command-finished path. Main also showed substantial timing variance; per-trial causal analysis is pending. The candidate released Chat after quit in all 18 primary trials. These are evidence for 95a288a, not runtime verification of the new scheduler. The owner will repeat the remaining sh cases five times each on the final candidate. Temporary metadata-only diagnostic patches remain outside the PR. The new-head patch passed independent source and clean application checks; logging overhead is not assumed timing-neutral. No completion marker has been added.

Deliberate limits

Ctrl+Z returns to Terminal after confirmed shell foreground. Suspension identity keeps the existing limits, including no automatic Chat selection after fg. An agent never recognized in the foreground, with no command-finished mark, keeps the existing Done row until the next turn or tab close.

Ambiguous cold-restored Chat remains TEMPORARY, tracked in STA-11546. A restored row alone cannot authorize process retirement. The presentation fallback requires fresh local shell/no-children evidence and no launch or resume expectation.

Terminal-backed Chat writes to the agent's terminal. A write already issued at the instant the agent quits retains the existing process/write race. A composer remaining available after confirmed, settled release is a failure.

Review scope

Full review: terminal Chat lifecycle, asynchronous process observations and independently updated desktop, server and phone versions. No upstream agent skill source is copied or translated.

brennanb2025 and others added 2 commits October 19, 2026 10:13
… the agent

Codex and grok leave their terminal title set when they quit, so the title
tracker never reports the exit and the chat view stayed over the shell
prompt. The confirmed-shell proof (process read or command-finished mark)
already retires the agent row and title; it now also ends the chat view,
except for Orca's own hibernation or restart stops.

Tracked in #30613
Co-authored-by: zhangxaochen <zhangxaochen@163.com>
@brennanb2025
brennanb2025 marked this pull request as ready for review October 19, 2026 17:25
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review.

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 5ef75acf-34b7-49ba-a1e1-b1045bdc6b73
📥 Commits

Reviewing files that changed from the base of the PR and between 842f870 and 0ae44cb.

📒 Files selected for processing: 43
  • config/scripts/benchmark-preflight-compilers.mjs
  • config/scripts/run-typecheck-bun-queue.test.mjs
  • config/scripts/run-typecheck-projects-in-parallel.mjs
  • config/scripts/run-typecheck-projects-in-parallel.test.mjs
  • config/scripts/typecheck-project-coverage.test.mjs
  • config/tsconfig.node.json
  • config/tsconfig.tc.web.json
  • config/tsconfig.terminal-interface.test.json
  • config/tsconfig.web.json
  • mobile/src/session/mobile-native-chat-eligibility.ts
  • mobile/src/session/mobile-terminal-interface-flow.test.ts
  • mobile/src/session/use-mobile-native-chat-active-resolution.ts
  • src/main/agent-hooks/server/server-status-update.ts
  • src/main/agent-hooks/server/terminal-interface-authority.ts
  • src/main/agent-hooks/server/terminal-interface-hook-owner.ts
  • src/main/agent-hooks/terminal-interface-host-flow.test.ts
  • src/main/runtime/construction/runtime-construction-services.ts
  • src/main/runtime/construction/runtime-construction.ts
  • src/main/runtime/orca-runtime-terminal-interfaces.ts
  • src/main/runtime/rpc/methods/client-events.test.ts
  • src/main/runtime/runtime-pty-controller-contract.ts
  • src/renderer/src/components/native-chat/terminal-interface-replica-flow.test.ts
  • src/renderer/src/components/native-chat/use-native-chat-toggle-shortcut.ts
  • src/renderer/src/components/sidebar/folder-workspace-composer-submit.test.ts
  • src/renderer/src/components/tab-bar/use-tab-bar-runtime-model.ts
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator-types.ts
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator.ts
  • src/renderer/src/components/terminal-pane/pty-connection/connect-pane-pty.ts
  • src/renderer/src/components/terminal-pane/pty-connection/deferred-session-reattach-connect.ts
  • src/renderer/src/components/terminal-pane/pty-connection/fresh-spawn-start.ts
  • src/renderer/src/components/terminal-pane/pty-connection/hidden-agent-resume-deferral.ts
  • src/renderer/src/components/terminal-pane/pty-connection/pane-pty-visibility-bind.ts
  • src/renderer/src/components/terminal-pane/pty-connection/pane-terminal-interface-presentation.test.ts
  • src/renderer/src/components/terminal-pane/pty-connection/pane-terminal-interface-presentation.ts
  • src/renderer/src/components/terminal-pane/pty-connection/pty-input-recovery.ts
  • src/renderer/src/components/terminal-pane/pty-connection/session-reconcile-dispose.ts
  • src/renderer/src/components/terminal-pane/pty-connection/spawn-deferred-sleep.ts
  • src/renderer/src/components/terminal-pane/pty-connection/terminal-keydown-fit.ts
  • src/renderer/src/components/terminal-pane/pty-connection/transport-output-callbacks.ts
  • src/renderer/src/lib/launch-agent-in-new-tab.test.ts
  • src/renderer/src/lib/terminal-interface-startup-flow.test-support.ts
  • src/shared/runtime-mobile-session-tab-contracts.ts
  • src/shared/terminal-runtime-capabilities.ts
🚧 Files skipped from review as they are similar to previous changes: 1
  • src/renderer/src/components/terminal-pane/pty-connection/hidden-agent-resume-deferral.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Walkthrough

The change adds host-side terminal-interface inspection and ownership tracking. The runtime publishes versioned observations to capable clients and includes them in mobile terminal-tab projections. Renderer pane tracking now separates foreground ownership from agent lifetime and validates asynchronous process observations against pane identity. Renderer and mobile chat routing use terminal-interface and shell-foreground state. The diff also adds lifecycle tests and updates TypeScript test-project configuration.

Priority: Normal

Merge Risk: Moderate · up to 0ae44

Chat should return to Terminal when an agent quits to the shell. On hosts where a process-table capture takes longer than one second, that release may not be published, and the original problem of composer input reaching the shell may persist. Active agent panes also trigger repeated fresh whole-machine process scans, which can raise CPU and I/O under load. Resolve or explicitly accept both before merging.

Pre-merge checks: Passed 3 · Failed 2

Failed Failed checks: 2 warnings

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 32.81% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 64 functions across 100 files. (4 skipped… Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check Warning The description provides detailed problem, user-facing behavior, implementation scope, issue references, verification status, limitations, and review scope. It does not follow the required template fu… Add all required template sections. Include visual before/after proof or write N/A with a reason, document testing platforms and completed checks, state AI disclosure or the applicable internal-contributor exception, complete the Agent skil…
Passed Passed checks: 3 passed
Check name Status Explanation
Title check Passed The title clearly describes the primary user-facing fix: returning the chat view to the terminal when the agent quits to the shell.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 32.81% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 64 functions across 100 files. (4 skipped: 4 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Full details: Description check

Explanation

The description provides detailed problem, user-facing behavior, implementation scope, issue references, verification status, limitations, and review scope. It does not follow the required template fully: it omits the required Visual Proof section or an explicit N/A explanation, the Testing checklist, AI Disclosure, Agent skill upstream boundary, Notes, and Checklist. The linked issue is mentioned as #30613 but is not formatted under the required Linked Issue section.

Resolution

Add all required template sections. Include visual before/after proof or write N/A with a reason, document testing platforms and completed checks, state AI disclosure or the applicable internal-contributor exception, complete the Agent skill upstream boundary, Notes, and Checklist sections, and place the issue reference under Linked Issue using the required format such as Fixes #30613 if appropriate.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

A shell back in front now releases the chat view through one accepted
departure per pane; only a confirmed process exit retires the row, launch
config and sleeping duplicates. Ctrl+Z keeps the agent's identity and chat
is available again after fg. Launch hints no longer count as an agent that
ran, so a slow start or reveal keeps the chat view. The process monitor
delivers hook-only exits and reads a stopped job as child work. The tab bar,
shortcut and pane apply the same shell-in-front rule.

Tracked in #30613

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 09f88bae-78e5-410a-967a-b266d3a6a5fe
📥 Commits

Reviewing files that changed from the base of the PR and between 7e3e140 and 3d63ee6.

📒 Files selected for processing: 44
  • src/main/daemon/daemon-pty-process-inspection.ts
  • src/main/daemon/session.ts
  • src/main/daemon/terminal-host-cheap-tier-ps-scan-volume.test.ts
  • src/main/daemon/terminal-host-non-agent-foreground.test.ts
  • src/main/daemon/terminal-host-process-inspection-cheap-tier.test.ts
  • src/main/daemon/terminal-host-process-inspection.ts
  • src/main/providers/local-pty-child-process-verdict.test.ts
  • src/main/providers/local-pty-foreground-inspection.ts
  • src/renderer/src/components/native-chat/native-chat-availability.ts
  • src/renderer/src/components/native-chat/native-chat-leaf-routing.ts
  • src/renderer/src/components/native-chat/use-native-chat-toggle-shortcut.ts
  • src/renderer/src/components/tab-bar/TabBarItemRow.test.tsx
  • src/renderer/src/components/tab-bar/tab-agent-types-by-tab-id.ts
  • src/renderer/src/components/tab-bar/tab-bar-item-surface.tsx
  • src/renderer/src/components/tab-bar/use-tab-bar-runtime-model-worktree-write-probe.ts
  • src/renderer/src/components/tab-bar/use-tab-bar-runtime-model.ts
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator-queued-inspection-disposal.test.ts
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator-test-harness.ts
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator-types.ts
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator.ts
  • src/renderer/src/components/terminal-pane/agent-completion-inspection-result.ts
  • src/renderer/src/components/terminal-pane/agent-completion-process-monitor.ts
  • src/renderer/src/components/terminal-pane/agent-completion-process-types.ts
  • src/renderer/src/components/terminal-pane/agent-completion-stale-evidence-backoff.test.ts
  • src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker-contract.ts
  • src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.test.ts
  • src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.ts
  • src/renderer/src/components/terminal-pane/pane-foreground-monitor-observations.ts
  • src/renderer/src/components/terminal-pane/pane-foreground-process-exit-retire.test.ts
  • src/renderer/src/components/terminal-pane/pty-connection-command-finished-cleanup.spec.ts
  • src/renderer/src/components/terminal-pane/pty-connection-foreground-agent-routing.spec.ts
  • src/renderer/src/components/terminal-pane/pty-connection-foreground-agent-sampling.spec.ts
  • src/renderer/src/components/terminal-pane/pty-connection-foreground-process-exit.spec.ts
  • src/renderer/src/components/terminal-pane/pty-connection-hibernation-kill-shell-foreground.test.ts
  • src/renderer/src/components/terminal-pane/pty-connection-process-exit-row-retire.test.ts
  • src/renderer/src/components/terminal-pane/pty-connection-test-environment.ts
  • src/renderer/src/components/terminal-pane/pty-connection-unanswered-command-finish.spec.ts
  • src/renderer/src/components/terminal-pane/pty-connection/agent-departure.ts
  • src/renderer/src/components/terminal-pane/pty-connection/agent-idle-working-handlers.ts
  • src/renderer/src/components/terminal-pane/pty-connection/confirmed-process-exit-row-retire.ts
  • src/renderer/src/components/terminal-pane/pty-connection/pane-agent-identity.ts
  • src/renderer/src/components/terminal-pane/pty-connection/terminal-keydown-fit.ts
  • src/renderer/src/components/terminal-pane/terminal-chat-ownership-lifecycle.test.tsx
  • src/renderer/src/components/terminal-pane/use-terminal-pane-chat-state.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.

Comment thread src/main/daemon/daemon-pty-process-inspection.ts Outdated
Comment thread src/renderer/src/components/native-chat/native-chat-leaf-routing.ts
@brennanb2025

brennanb2025 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor Author

Quitting an agent without resetting its terminal title could leave Chat selected over the returned shell, allowing composer text to execute there. This PR makes the execution host observe the current terminal interface and lets Chat follow that snapshot, independently of the latest turn row or a view remount. Slow launch, recovery and remote uncertainty must still preserve Chat.

Not ready on current head b9d96ae69ed08b578f5bc675a517bbe7f32d5353: the renderer repair and authorized main integration are pushed; independent source review passed without a new proven defect; required CI is red and final runtime acceptance is pending. The Windows evidence in the next paragraphs is for preceding head 0e4ca54e, not acceptance of the repair. The native Windows comparison against 0985d6f1 exercised real replied Codex conversations followed by double interrupt in three fresh Git Bash panes, PowerShell and cmd; real Claude Git Bash normal exit and double interrupt; and Chat availability/relaunch. The branch returned to Terminal within five seconds in all these controls. Main retained Chat through forty seconds in the double-interrupt cases; Claude normal exit passed on both. These preceding-head results supersede the older intermittent Git Bash failure shown below. Some marker attempts required corrected CDP key events and tab reselection, so the report does not establish every no-refocus input path. Codex hooks failed on both builds; this validates the process-based flows, not successful hook delivery.

Enter regression: a matched 120-second/eight-PTY/30-chunk control preserved all 480 ordered bytes, completed a real normal launch and took no screenshots inside the measurement windows. Same-renderer input to the later xterm onData listener measured p50/p95/max 37.5/45.1/51.5 ms on the branch versus 0.5/0.8/1.5 ms on main. Independent raw/profile review identified unnecessary synchronous React work before sampled input forwarding: Enter discovery notifies startup state, a presentation refresh replaces the shared observation-map identity, and terminal panes subscribe to that identity even when their own derived values are unchanged. A direct sample shows refresh, then React work, then forwarding. These development-build sampled timings include instrumentation and unequal surrounding UI/listener counts; they are not exact function spans or packaged-build timing. They establish the unnecessary rendering mechanism and the workload failure, without attributing downstream host cost to it.

The bounded renderer repair now separates real host-observation publication from coalesced presentation notifications. Pane readers select stable values for both availability and confirmed Chat release; tab projections and mounted cleanup observe the same presentation notifications. Two regression controls fail against the old code, and a separate mutation verifies the confirmed-release dependency; all 65 targeted tests pass on the candidate. A fresh independent reviewer completed the whole source and mechanism comparison, readiness and performance scans, plus the pushed merge check, without a new proven defect. This is source acceptance; it does not establish runtime timing or complete QA. The execution-host lifecycle design, startup/recovery checks, old-peer support and input ordering stay in place. The same Windows timing/quit workload, a bounded idle control and affected macOS agent flows still need to pass on the fix head. Several single-attempt sidebar rows also cleared later on the branch (about3.2–4.5s versus0.6–2.3s on main); their cause and acceptance remain undecided, and the repair does not change lifetime policy.

The preceding identity correction preserves the existing terminal incarnation through IPC connection-result projections into real session installation. A production-seam regression covers eight response shapes and rejects mismatched or absent identities. The prior 0e4ca54e head changed only the healthy recycled-PTY test assertion relative to source-reviewed 5e2ae4e2; the new repair changes the five renderer paths described above. The mobile row-lookup move preserves its lazy behavior; host/renderer fixtures retain their compiler semantics. All benchmark production/config changes were reverted to integrated main. The current counted diff is 2,506 production /2,261 test-support changed lines, within the approved 2,700 production ceiling. No new saved truth, stream opcode, typed-command rewrite or second send guard is added.

CI: required PR workflow 39698417263 failed on current head b9d96ae69ed. All failed logs are accounted: two line-limit errors come from files whose tested blobs exactly match the newer main parent; repairs are tracked in #31729 and #31734. The required core compiler did not run: its successful wrapper exited before invoking the compiler after lint failed. Main units, Windows packaging and WSL checks were skipped, so they provide no passing evidence. Separate mobile CI executed its compiler and passed 10,871 tests with six skipped; the required mobile web bundle also passed. CI used the current-main merge tree, rather than the branch alone. No retry or PR code change was made. The normal merge through main commit d0854276 preserved both existing capability entries in its sole conflict; seven focused suites/29 tests and the normal commit hook passed. The remaining main integration waits for both main line-limit repairs, #31729 and #31734. No hook bypass or unrelated browser repair was added. On preceding head 0e4ca54e, required workflow 39669036854 failed in mobile web bundle job119461872826 and its dependent aggregate119474666113. The bundle build succeeded; a subsequent Chromium positive-navigation precondition timed out waiting for its own-origin request. All unit shards and the actual typecheck passed. The failing test/readiness paths match integrated main, which alone does not prove a flaky or environment cause. All failed logs are accounted; no blind retry or test weakening was performed. The earlier unchanged fake-timer failure remains unproved and its test unchanged. Historical compiler comparison39655264501 hit its unchanged 25-minute limit; the separate investigation remains tracked in STA-11601. Historical green runs do not satisfy this head's gate.

Other evidence and remaining gates: the copied historical macOS 544e82cb evidence corroborates tested reply/quit, split-marker destination, slow launch, service restart and corrected same-identity upgrade flows. The recovered CPU profiles corroborate their narrow launch attribution: no sampled PR-specific frame of 50 ms or more was observed in those launches. They do not prove absence of all stalls or current-head acceptance. Both review threads remain open: execution-host capture cost, including daemon/transient-capture CPU and mobile fanout, and slow capture freshness/progress, including an actual slow target return and host-only late-exit convergence. A sampling cadence over one second alone does not make a freshly returned observation stale.

Current mobile comparison on b9d96ae6 versus d0854276 completed and exposed an unexpected relaunch difference: main automatically returns the phone to Chat and its unsent draft after a new real reply, while the branch requires selecting Chat again. The exact draft survives on both. A bounded independent source/raw-evidence check confirmed that shell release persists a replacement phone view choice. The same fixer is restoring the existing phone behavior in two mobile paths: preserve the saved choice while deriving availability, and use the existing resolver for the menu. Retained launch hints remain covered by the host-release gate; desktop explicit-return and terminal input-mode behavior stay in place. The repaired-head phone flow still needs real acceptance. For manual launches the phone already falls back to Terminal on main, while only main’s desktop reproduces the stale Chat. Phone-connected resource measurements recorded 90 interface inspections/94 total process-probe API calls in 60.072 seconds versus 72/72 in 60.066 seconds disconnected, on the branch only. They do not measure kernel capture counts or CPU cost. A completed isolated WSL run on this head additionally reports Claude /exit returning to the shell while Chat stays visible for more than nine seconds. Codex and Claude double interrupt and toggle/relaunch passed in that run. Its main comparison was not run; raw evidence and the host/hook/application cause are pending independent review. This normal-flow gap remains open. Full acceptance still requires applicable final-head macOS/Windows evidence and the remaining hook-only, Ctrl+Z/fg with and without command marks, startup/reveal, sleep/hibernation/restart, upgrade, folder workspace, mobile/paired, SSH and mixed-version consumers. The native Windows run tested no WSL distro, and its actual WSL hook-script pre-run hashes were omitted; native/config/wrapper hashes were unchanged, but full script before/after assurance is unavailable. No changed flow is waived.

TEMPORARY: the exact ambiguous cold-restored case retains Chat when pending launch or resume cannot be distinguished safely; tracked in STA-11546. This does not cover hot launch defects or restored-row retirement. The physical exit/write race of external PTY conversations remains a main limitation; settled post-exit Chat exposure is a failure.

For Brennan’s review: preceding-head Windows comparisons are first below, followed by historical evidence with its original labels. Review and final-head QA remain incomplete; no completion marker is posted.

Current mobile relaunch b9d96ae6 versus main d0854276 Main Branch before correction
Same-terminal Codex relaunch after a real reply Main automatically returns to Chat Branch requires selecting Chat
Desktop five seconds after quitting Main desktop stale Chat Branch desktop returned shell
Current 0e4ca54 Windows quit comparison Main Branch
Five seconds after double interrupt Main stale Chat Branch returned shell
Shell Chat availability — Branch shell menu omits Chat

Historical captures:

Core exit Main Branch
Before quitting Main Chat before quit Branch Chat before quit
After quitting Main stuck in Chat Branch returned to Terminal
Split after quitting; focus unresolved Main split retains Chat Branch split returns Terminal
Bounded split control: external signal exit, then ordinary keyboard marker Main Branch
Marker executes in left shell; both builds retain left focus Main marker in left shell Branch marker in left shell
Windows Git Bash quit Main, +30 seconds Branch, initial failing run
Chat remains selected Main Git Bash remains in Chat Branch Git Bash unsafe Chat remains
Same-head diagnostic, +5 seconds after quit Failed second attempt Successful third attempt
Intermittent Git Bash result Git Bash diagnostic retains Chat Git Bash diagnostic returns Terminal

Keep interface observations independent of turn rows and derive shell release on the host, with negotiated snapshots for desktop and mobile readers. Preserve ordinary lifetime cleanup, launch intent and legacy peer behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 178cf971-b9b2-4ca4-a270-7c9f43e45b70
📥 Commits

Reviewing files that changed from the base of the PR and between 6a3a1bb and 842f870.

📒 Files selected for processing: 106
  • mobile/src/session/mobile-native-chat-eligibility.ts
  • mobile/src/session/mobile-native-chat-toggle-action.ts
  • mobile/src/session/mobile-session-route-types.ts
  • mobile/src/session/mobile-terminal-interface-flow.test.ts
  • mobile/src/session/mobile-terminal-records.ts
  • mobile/src/session/use-mobile-native-chat-active-resolution.ts
  • src/main/agent-hooks/agent-hook-runtime-deps.ts
  • src/main/agent-hooks/server/agent-exit-evidence.ts
  • src/main/agent-hooks/server/server-lifecycle.ts
  • src/main/agent-hooks/server/server-listeners.ts
  • src/main/agent-hooks/server/server-state.ts
  • src/main/agent-hooks/server/server-status-admission.ts
  • src/main/agent-hooks/server/server-status-update.ts
  • src/main/agent-hooks/server/server-terminal-interface-status.ts
  • src/main/agent-hooks/server/terminal-interface-authority.ts
  • src/main/agent-hooks/server/terminal-interface-contracts.ts
  • src/main/agent-hooks/server/terminal-interface-hook-ingress.ts
  • src/main/agent-hooks/server/terminal-interface-hook-owner.ts
  • src/main/agent-hooks/server/terminal-interface-inventory.ts
  • src/main/agent-hooks/server/terminal-interface-probe.ts
  • src/main/agent-hooks/terminal-interface-host-flow.test.ts
  • src/main/daemon/daemon-foreground-process-protocol.ts
  • src/main/daemon/daemon-pty-process-inspection.ts
  • src/main/daemon/daemon-request-router.ts
  • src/main/daemon/pty-subprocess/subprocess-handle.ts
  • src/main/daemon/session-subprocess-handle.ts
  • src/main/daemon/session.ts
  • src/main/daemon/terminal-host-process-inspection.ts
  • src/main/ipc/desktop-renderer-runtime-capabilities.ts
  • src/main/ipc/pty/runtime/operations.ts
  • src/main/providers/local-pty-child-process-verdict.test.ts
  • src/main/providers/local-pty-provider-foreground-process.test.ts
  • src/main/providers/local-pty-provider.ts
  • src/main/providers/pty-process-inspection.ts
  • src/main/providers/terminal-interface-process-evidence.test.ts
  • src/main/providers/terminal-interface-process-evidence.ts
  • src/main/runtime/construction/runtime-construction-dependencies.ts
  • src/main/runtime/construction/runtime-construction-services.ts
  • src/main/runtime/construction/runtime-construction.ts
  • src/main/runtime/orca-runtime-get-status.ts
  • src/main/runtime/orca-runtime-terminal-interfaces.ts
  • src/main/runtime/orca-runtime.ts
  • src/main/runtime/rpc/methods/client-events.test.ts
  • src/main/runtime/rpc/methods/client-events.ts
  • src/main/runtime/rpc/methods/session-tab-agent-status-projection.ts
  • src/main/runtime/runtime-mobile-session-incarnation-projection.test.ts
  • src/main/runtime/runtime-mobile-session-projection-contract.ts
  • src/main/runtime/runtime-mobile-session-projection.ts
  • src/main/runtime/runtime-pty-controller-contract.ts
  • src/main/runtime/session-lifecycle/projection/prune-mobile-session-tab-group-layout.ts
  • src/main/runtime/terminal-intentional-stops.ts
  • src/main/runtime/terminal-run-facts.ts
  • src/main/runtime/terminal/output/pty-output-ingestion.ts
  • src/renderer/src/components/native-chat/terminal-interface-presentation.ts
  • src/renderer/src/components/native-chat/terminal-interface-replica-flow.test.ts
  • src/renderer/src/components/native-chat/use-native-chat-toggle-shortcut.ts
  • src/renderer/src/components/tab-bar/tab-agent-types-by-tab-id.ts
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator-process-cadence.test.ts
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator-queued-inspection-disposal.test.ts
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator-test-harness.ts
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator-types.ts
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator.ts
  • src/renderer/src/components/terminal-pane/agent-completion-inspection-result.ts
  • src/renderer/src/components/terminal-pane/agent-completion-process-monitor.ts
  • src/renderer/src/components/terminal-pane/agent-completion-stale-evidence-backoff.test.ts
  • src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.ts
  • src/renderer/src/components/terminal-pane/pane-foreground-observation-transitions.ts
  • src/renderer/src/components/terminal-pane/pty-connection-hook-completion-side-effects.spec.ts
  • src/renderer/src/components/terminal-pane/pty-connection-notification-settings-gating.spec.ts
  • src/renderer/src/components/terminal-pane/pty-connection-process-exit-row-retire.test.ts
  • src/renderer/src/components/terminal-pane/pty-connection/agent-departure.ts
  • src/renderer/src/components/terminal-pane/pty-connection/connect-pane-pty-session.ts
  • src/renderer/src/components/terminal-pane/pty-connection/connect-pane-pty.ts
  • src/renderer/src/components/terminal-pane/pty-connection/deferred-cold-restore-and-snapshot.ts
  • src/renderer/src/components/terminal-pane/pty-connection/deferred-session-reattach-connect.ts
  • src/renderer/src/components/terminal-pane/pty-connection/fresh-spawn-start.ts
  • src/renderer/src/components/terminal-pane/pty-connection/hidden-agent-resume-deferral.ts
  • src/renderer/src/components/terminal-pane/pty-connection/pane-agent-identity.ts
  • src/renderer/src/components/terminal-pane/pty-connection/pane-pty-visibility-bind.ts
  • src/renderer/src/components/terminal-pane/pty-connection/pane-serializer-settle.ts
  • src/renderer/src/components/terminal-pane/pty-connection/pane-terminal-interface-presentation.ts
  • src/renderer/src/components/terminal-pane/pty-connection/pty-exit-hibernate.ts
  • src/renderer/src/components/terminal-pane/pty-connection/pty-input-recovery.ts
  • src/renderer/src/components/terminal-pane/pty-connection/reattach-result-handler.ts
  • src/renderer/src/components/terminal-pane/pty-connection/restart-replacement-on-show.ts
  • src/renderer/src/components/terminal-pane/pty-connection/session-reconcile-dispose.ts
  • src/renderer/src/components/terminal-pane/pty-connection/spawn-deferred-sleep.ts
  • src/renderer/src/components/terminal-pane/pty-connection/terminal-keydown-fit.ts
  • src/renderer/src/components/terminal-pane/pty-connection/transport-output-callbacks.ts
  • src/renderer/src/components/terminal-pane/terminal-chat-ownership-lifecycle.test.tsx
  • src/renderer/src/components/terminal-pane/use-terminal-pane-chat-state.ts
  • src/renderer/src/components/terminal-pane/use-terminal-pane-projection.ts
  • src/renderer/src/hooks/ipc-events/runtime-client-ipc-bridge.ts
  • src/renderer/src/lib/pane-spawn-deferral-registry.ts
  • src/renderer/src/runtime/runtime-client-events.ts
  • src/renderer/src/store/slices/pane-foreground-agent.ts
  • src/shared/electron-remote-runtime-client-capabilities.ts
  • src/shared/process-evidence-budget.ts
  • src/shared/process-table-snapshot-reader.ts
  • src/shared/protocol-version.ts
  • src/shared/remote-runtime-client-capabilities.ts
  • src/shared/runtime-client-events.ts
  • src/shared/runtime-mobile-session-tab-contracts.ts
  • src/shared/terminal-interface-observation.ts
  • src/shared/terminal-process-inspection.ts
  • tests/e2e/terminal-foreground-confirmation.unit.test.ts
💤 Files with no reviewable changes: 1
  • src/renderer/src/components/terminal-pane/agent-completion-coordinator.ts
🚧 Files skipped from review as they are similar to previous changes: 5
  • src/renderer/src/components/native-chat/use-native-chat-toggle-shortcut.ts
  • src/renderer/src/components/terminal-pane/use-terminal-pane-chat-state.ts
  • src/renderer/src/components/terminal-pane/terminal-chat-ownership-lifecycle.test.tsx
  • src/renderer/src/components/terminal-pane/pty-connection-process-exit-row-retire.test.ts
  • src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment on lines +246 to +252
entry.due =
performance.now() +
(entry.owner?.current() ||
(entry.actual && entry.observation?.state !== 'shell') ||
performance.now() < entry.discoverUntil
? 750
: 15000)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

🔎 Supported by static analysis

🏁 Script executed:

set -u
printf '%s\n' '--- revision ---'
git rev-parse HEAD
printf '%s\n' '--- diff stat ---'
git diff --stat d4813638d20e7269764dc941d4778ed581628e68 842f870c9a51e793be5b51d5fcd8ac649291937f -- src/main/agent-hooks/server/terminal-interface-authority.ts
printf '%s\n' '--- authority symbols ---'
rg -n -F -- 'getFreshSnapshot' 'inspectPosixTerminalInterface' 'inspectDaemonTerminalInterface' 'input(' 'sample(' 'due =' 'discoverUntil' 'shellSince' 'setTimeout' 'setInterval' 'capture' src/main/agent-hooks/server/terminal-interface-authority.ts src/main/agent-hooks || true
printf '%s\n' '--- authority source 1-360 ---'
nl -ba src/main/agent-hooks/server/terminal-interface-authority.ts | sed -n '1,360p'
printf '%s\n' '--- authority source 361-760 ---'
nl -ba src/main/agent-hooks/server/terminal-interface-authority.ts | sed -n '361,760p'
printf '%s\n' '--- changed diff ---'
git diff --unified=35 d4813638d20e7269764dc941d4778ed581628e68 842f870c9a51e793be5b51d5fcd8ac649291937f -- src/main/agent-hooks/server/terminal-interface-authority.ts

Repository: stablyai/orca

Length of output: 22392


🏁 Script executed:

set -u
printf '%s\n' '--- probe and contracts files ---'
rg --files src/main/agent-hooks/server | sort
printf '%s\n' '--- exact symbols ---'
rg -n -F -e 'class TerminalInterfaceProbe' -e 'getFreshSnapshot' -e 'inspectPosixTerminalInterface' -e 'inspectDaemonTerminalInterface' -e 'inspect(' -e 'ps ' -e 'ps)' -e '/proc/' -e 'TTL' src/main/agent-hooks src/main shared || true
printf '%s\n' '--- probe source ---'
probe=$(rg -l -F 'class TerminalInterfaceProbe' src/main/agent-hooks/server | head -n 1)
if [ -n "$probe" ]; then nl -ba "$probe"; fi
printf '%s\n' '--- related inspector source files ---'
for f in $(rg -l -F -e 'getFreshSnapshot' -e 'inspectPosixTerminalInterface' -e 'inspectDaemonTerminalInterface' src/main/agent-hooks src/main shared 2>/dev/null | sort -u); do
  echo "### $f"
  nl -ba "$f"
done
printf '%s\n' '--- contracts source ---'
for f in src/main/agent-hooks/server/terminal-interface-contracts.ts src/main/agent-hooks/server/terminal-interface-inventory.ts; do
  if [ -f "$f" ]; then echo "### $f"; nl -ba "$f"; fi
done

Repository: stablyai/orca

Length of output: 45658


🏁 Script executed:

set -u
printf '%s\n' '--- terminal interface probe ---'
nl -ba src/main/agent-hooks/server/terminal-interface-probe.ts
printf '%s\n' '--- exact inspector definitions and calls ---'
rg -n -F -- 'inspectPosixTerminalInterface' src || true
rg -n -F -- 'inspectDaemonTerminalInterface' src || true
rg -n -F -- 'getFreshSnapshot' src/main || true
rg -n -F -- 'getSnapshot' src/main/agent-hooks src/shared || true
printf '%s\n' '--- terminal interface driver construction ---'
rg -n -F -e 'TerminalInterfaceDriver' -e 'inspect: ' -e 'inspect =' src/main/agent-hooks/server src/main | head -200 || true

Repository: stablyai/orca

Length of output: 16638


🏁 Script executed:

set -u
printf '%s\n' '--- process evidence ---'
nl -ba src/main/providers/terminal-interface-process-evidence.ts
printf '%s\n' '--- local PTY provider inspection ---'
nl -ba src/main/providers/local-pty-provider.ts | sed -n '140,225p'
printf '%s\n' '--- runtime terminal interfaces ---'
nl -ba src/main/runtime/orca-runtime-terminal-interfaces.ts
printf '%s\n' '--- snapshot reader implementation ---'
nl -ba src/shared/process-table-snapshot-reader.ts | sed -n '1,155p'
printf '%s\n' '--- all runtime authority install/use sites ---'
rg -n -F -e '.install(' -e 'TerminalInterfaceAuthority' -e 'terminalInterfaceAuthority' src/main/runtime src/main/daemon src/main/providers src/main/agent-hooks | head -250 || true

Repository: stablyai/orca

Length of output: 31376


🏁 Script executed:

set -u
printf '%s\n' '--- strict fresh reader binding ---'
rg -n -F -e 'getFreshStrictProcessTableSnapshotWithAge' -e 'getStrictProcessTableSnapshotWithAge' src/shared/process-table-snapshot-reader.ts src/main/providers/terminal-interface-process-evidence.ts
nl -ba src/shared/process-table-snapshot-reader.ts | sed -n '280,345p'
printf '%s\n' '--- process inspection implementations ---'
rg -n -F -e 'async inspectProcess' -e 'inspectProcess(' -e 'terminalInterface:' src/main | head -250 || true
printf '%s\n' '--- daemon and local provider definitions ---'
rg -n -F -e 'class Daemon' -e 'class LocalPtyProvider' -e 'inspectChildProcesses' -e 'inspectProcess' src/main/daemon src/main/providers src/main/runtime | head -300 || true

Repository: stablyai/orca

Length of output: 34013


Reduce fresh process-table sampling for active terminal entries.

OrcaRuntimeWithTerminalInterfaces requests terminal-interface inspection for each local sample. On POSIX, that path always calls getFreshStrictProcessTableSnapshotWithAge(), which bypasses the TTL snapshot. Active entries are rescheduled after 750 ms, and each input sets due = 0. This can repeatedly trigger expensive whole-machine process-table captures and increase CPU and I/O under load.

The reader already coalesces concurrent fresh requests, so sharing concurrent captures does not fix the steady-state rate. Use the TTL-backed snapshot for routine samples. Reserve fresh reads for confirming a candidate shell transition or another explicit freshness boundary. Debounce input-triggered sampling so a burst of keystrokes schedules one follow-up sample.

The capture is not continuously in progress: pending prevents duplicate samples for one entry, and the next sample is scheduled 750 ms after the current sample completes.

children: 'unverifiable',
capturedAgeMs
}
if (!root || !root.tty || root.tty === '?' || capturedAgeMs > 1000) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

The 1,000 ms age limit rejects every capture that takes longer than about 1 s, so shell is never published on ordinary hosts.

  • getFreshStrictProcessTableSnapshotWithAge sets capturedAgeMs to the full wall time from request to completion. That time includes the wait for any capture already in flight, because getFreshSnapshot waits for it before it starts a new one.
  • This line rejects ages above 1,000 ms. terminal-interface-authority.ts Line 205 repeats the same literal.
  • process-evidence-budget.ts documents these capture times:
    • 1.15 s for the command= column on an idle host with 1,948 processes.
    • 2.5–9.0 s on an idle laptop with 2,002 processes.
  • On those hosts every sample returns children: 'unverifiable'. The authority then never publishes shell, and Chat stays selected after the agent quits. That is the defect this PR fixes.
  • Both callers make this worse, because each runs a second capture after the first one:
    • The daemon path (inspectTerminalHostProcess) first calls getStrictProcessTableSnapshotWithAge.
    • The local path (LocalPtyProvider.inspectProcess) first calls inspectLocalPtyChildProcesses(id, true).
    • inspectSessionTerminalInterface / inspectPosixTerminalInterface then wait for that capture and start another fresh one, which roughly doubles the elapsed time.

Recommended changes:

  • Define the limit once, in process-evidence-budget.ts, and set it from the documented capture cost. Use the same constant in both places.
  • Pass the rows already captured in the same inspection to terminalInterfaceEvidenceFromRows, so each inspection runs only one capture.
🐛 Proposed change for the shared age limit
--- "a/src/main/providers/terminal-interface-process-evidence.ts"
+++ "b/src/main/providers/terminal-interface-process-evidence.ts"
@@ -24,7 +24,12 @@
     children: 'unverifiable',
     capturedAgeMs
   }
-  if (!root || !root.tty || root.tty === '?' || capturedAgeMs > 1000) {
+  if (
+    !root ||
+    !root.tty ||
+    root.tty === '?' ||
+    capturedAgeMs > TERMINAL_INTERFACE_EVIDENCE_MAX_AGE_MS
+  ) {
     return unknown
   }
   const tree = [{ ...root, depth: 0 }, ...collectDescendantsFromIndex(index, rootPid)]

Use TERMINAL_INTERFACE_EVIDENCE_MAX_AGE_MS in terminal-interface-authority.ts Line 205 as well.

Keep main's confirmation guard, option, wiring and regression coverage.
Update the cohort contract from zero confirmations to one per admitted
monitor, with one shared ordinary capture and one shared fresh capture.
Unverifiable child evidence still adds no confirmation; a later verifiable
shell result does. Retain the actual dispatch/result ownership proof.
Keep cross-layer tests in the joint unit program and use a no-children shell fixture for the existing confirmation branch. Tighten the full-tree bundle measurement from 91 to the observed 90 chunks without changing its margin.
Retain incoming Claude view routing and preserve hook ingress timing. Move transport rollback unchanged into the existing lifecycle base to keep the merged file within its line limit.
Preserve fake-time completion ordering and align the mobile budget assertions with the measured chunk count.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant