Skip to content

fix(agent-status): status follows a terminal re-homed into a new tab after a restart - #33601

Merged
nwparker merged 3 commits into
mainfrom
nwparker/agint-pane-key-after-restart
Oct 25, 2026
Merged

nwparker merged 3 commits into
mainfrom
nwparker/agint-pane-key-after-restart

Conversation

@nwparker

@nwparker nwparker commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​192 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​192
Prod 9 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​80 $\color{#cf222e}{\Huge{\mathbf{−}}}$​2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​78

ELI5

An agent's hook knows which Orca pane it belongs to only through the ORCA_PANE_KEY its shell was started with, and a running process's environment can't change. If Orca restarts while the terminal keeps running and the terminal comes back in a tab with a new id, the agent keeps reporting to the old, dead pane key. The status row with the prompt and session was filed under a tab that no longer exists, and the live tab only had the weaker terminal-title (OSC) status with no prompt or session. Now that status follows the terminal to the pane it is actually in.

This is #31841 by @AmoabaKelvin, rebased onto current main. Their two fix commits are kept as-is. Their daemon commit is dropped because #33380 already makes the daemon list each session's spawn paneKey. One small commit on top switches to that field.

Root cause

  • The daemon records the spawn ORCA_PANE_KEY and lists it as paneKey (src/main/daemon/terminal-host-session-listing.ts, from fix(terminal): don't resume an agent whose spawned PTY is still live #33380), but nothing in main compared it with the pane the terminal is now shown in.
  • placeUnshownLiveTerminals / the renderer adoption gate put a surviving terminal whose tab is gone into a new tab (tabId: randomUUID()), so its pane key changes.
  • Hooks keep posting the old key: Claude hooks inherit the env of the shell that started them. Orca's managed hook reads ORCA_PANE_KEY from the env. Main had no alias from the old key to the new pane, unlike a pane move, which calls transferPaneAuthority (src/main/runtime/moved-pane-owner-rekey.ts).

What changed

  • The runtime terminal record stores the host-reported spawn pane key (spawnPaneKey) from each inventory.
  • After inventory refresh, window-graph sync, orphan adoption and restored placement, followExportedPaneKeys moves that key's status to the pane the terminal is now shown in, using the existing transferPaneAuthority. This is the same persisted alias a pane move uses, and it is cleared when the PTY exits.
  • It never guesses. If another live terminal exported or shows either key, nothing moves, and an earlier move is undone (returnPaneAuthority).

Mixed versions: older daemons and orcad don't list paneKey, so they keep today's behavior. The legacy SSH relay doesn't report it either, so it is unchanged. Mobile and paired clients read the host's per-pane status, so they follow without client changes.

How verified

A real repro in an isolated dev Electron (separate userData and HOME), with a real Claude Code 2.1.310 and the PTY daemon kept alive across the restart:

  1. Created a terminal (tab 1b248014…), started claude and sent a prompt. The hook row landed on 1b248014…:5657a812….
  2. Quit Orca (the daemon and Claude survived). Removed the tab from the saved workspace session, which is the "renderer lost the tab" trigger, then relaunched.
  3. main (a944e37): the terminal was re-homed into a new tab d484763d…. Sent "reply with just the word hello". In last-status.json the hook row (prompt "hello") was filed under the dead key 1b248014…. The live pane d484763d… had only an origin: osc row with prompt: "". The renderer store and orca worktree ps showed only that OSC row.
  4. This branch, relaunched on the same profile and daemon: on start the dead-key row moved to d484763d…. A new prompt ("live") from the same Claude process, which still has ORCA_PANE_KEY=1b248014… (checked with ps eww), landed on d484763d… as an origin: hook row with the prompt, in last-status.json, the renderer store and orca worktree ps.

Tests: src/main/runtime/exported-pane-key-follow.test.ts (from #31841) drives the real runtime and hook server. pnpm test src/main/runtime src/main/providers src/main/agent-hooks src/main/daemon/terminal-host.test.ts passes, and pnpm tc:node and check:code-quality:changed are clean.

Risk

  • Runs on every inventory and graph sync. It is O(live PTYs) and a no-op when the shown pane equals the spawn key.
  • If a pane move reaches the hook server before the graph sync, the alias can briefly be undone and then redone on the next sync, so status may bounce for one sync.
  • Not covered: the legacy SSH relay, and the in-process fallback provider, whose terminals don't survive a restart.

Fixes #23753
Supersedes #31841

Co-authored-by: Kelvin Amoaba 97001695+AmoabaKelvin@users.noreply.github.com

AmoabaKelvin and others added 3 commits October 25, 2026 09:48
…after a restart

A surviving terminal's hooks keep posting the ORCA_PANE_KEY its env exported,
but after a relaunch nothing in main knew that key once the terminal came back
in a newly minted tab. The terminal host now reports the key it exported, and
when main records the terminal in a different pane it moves that key's status
with the existing transferPaneAuthority, as a pane move does.
…biguous

Status moved off a terminal's exported pane key now goes back under that key
when another live terminal also exported or shows either key, or when the
terminal is shown in its exported pane again. A move also needs its
destination to be unambiguous.
@coderabbitai

coderabbitai Bot commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent 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: 1835b146-3c07-46ac-82dd-56c6e0858171
Commits

Reviewing files that changed from the base of the PR and between f37c1f6 and 3ca20ff.

Files selected for processing: 10
  • src/main/agent-hooks/server/server-authority-aliases.ts
  • src/main/runtime/exported-pane-key-follow.test.ts
  • src/main/runtime/runtime-terminal-state-records.ts
  • src/main/runtime/session-graph/session-graph-promotion.ts
  • src/main/runtime/session-graph/session-window-graph.ts
  • src/main/runtime/terminal/adoption/adopt-terminal-orphans-from-inventory.ts
  • src/main/runtime/terminal/identity/exported-pane-key-follow.ts
  • src/main/runtime/terminal/identity/pty-worktree-record.ts
  • src/main/runtime/terminal/lifecycle/pty-controller-inventory-refresh.ts
  • src/main/runtime/workspaces/persisted-surfaces/restored-terminal-placement.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.

Walkthrough

The runtime records the pane key reported by the execution host for each PTY. It reconciles authority between that exported key and the PTY’s current pane key based on connected terminals and key-claim counts. Reconciliation runs after inventory refresh, terminal adoption, restored placement, and window graph synchronization. Tests cover agent status and hook routing when terminals retain exported keys across restarts, including cases with missing keys or competing claims.

Priority: Normal

Severity of issue fixed: Medium

Merge Risk: Minimal · up to 3ca20

The change is mergeable on the supplied evidence, subject to normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 10 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the primary change: agent status follows a terminal moved to a new tab after restart.
Description check Passed The description is detailed and covers the user impact, root cause, implementation, linked issue, verification steps, compatibility scope, and risks. It omits several template sections and unchecked c…
Linked Issues check Passed #23753 requires status from a surviving terminal to follow the pane that owns the terminal after restart. The runtime records the host-reported spawnPaneKey and calls followExportedPaneKeys after …
Out of Scope Changes check Passed The changes stay within #23753. Production changes record the exported pane key, reconcile it with the current pane, invoke reconciliation at terminal lifecycle points, and restore authority when the …
Full details: Description check

Explanation

The description is detailed and covers the user impact, root cause, implementation, linked issue, verification steps, compatibility scope, and risks. It omits several template sections and unchecked checklist items, but the core information is mostly complete and relevant.

Full details: Linked Issues check

Explanation

#23753 requires status from a surviving terminal to follow the pane that owns the terminal after restart. The runtime records the host-reported spawnPaneKey and calls followExportedPaneKeys after inventory and graph updates. The helper transfers authority only for unique live claims and routes later hook reports through the new pane key. Tests cover the restart case, later hooks, missing host keys, key collisions, and return to the exported pane. The existing per-pane status consumers therefore receive the status for the restored pane.

Full details: Out of Scope Changes check

Explanation

The changes stay within #23753. Production changes record the exported pane key, reconcile it with the current pane, invoke reconciliation at terminal lifecycle points, and restore authority when the mapping is unsafe. The added test file verifies these cases. No unrelated feature, client change, or separate #22873 work is included.

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.

@nwparker
nwparker merged commit 76029bf into main Oct 25, 2026
44 checks passed
tomarai85 added a commit to tomarai85/orca that referenced this pull request Oct 26, 2026
Keep both methods main (stablyai#33601) and this change add to pty-worktree-record.ts,
and import rekeyMigrationUnsupportedEntries from agent-status/, where main
moved the module (stablyai#33665).
tomarai85 added a commit to tomarai85/orca that referenced this pull request Oct 26, 2026
Keep both methods main (stablyai#33601) and this change add to pty-worktree-record.ts,
and import rekeyMigrationUnsupportedEntries from agent-status/, where main
moved the module (stablyai#33665).
tomarai85 added a commit to tomarai85/orca that referenced this pull request Oct 26, 2026
Keep both methods main (stablyai#33601) and this change add to pty-worktree-record.ts,
and import rekeyMigrationUnsupportedEntries from agent-status/, where main
moved the module (stablyai#33665).
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.

[Bug]: Agent status goes to a dead tab after Orca restart — surviving shells keep the old ORCA_PANE_KEY, mobile hides Switch to chat view

2 participants