Commit Graph
1786 Commits
Author SHA1 Message Date
NeilandRod Boev adcf74a9fb fix: root monorepo subfolder imports at the git repo while keeping the first terminal in the subfolder (#6336) (#6574)
Add Project → Browse folder on a monorepo subfolder (e.g. /tmp/monorepo/packages/web)
stored the subfolder as Repo.path because isGitRepo() uses
`git rev-parse --is-inside-work-tree`, which is true for any subdirectory.
Authoritative worktree resolution then snapped activation back to the repo root,
so the import identity mismatched and the first terminal landed at the repo root
rather than the selected subfolder.

Canonicalize local git imports to the actual repo root via getGitRepoRoot()
(mirroring the SSH import path that snaps to check.rootPath, including its
post-resolution dedup), and preserve the user-selected subfolder as a one-shot
initial terminal cwd consumed only by the first activation-created pane.
Selecting the repo root applies no override, and re-importing a subfolder of an
existing project dedupes.

Supersedes community PR #6362.

Fixes #6336

Co-authored-by: Rod Boev <rodboev@users.noreply.github.com>
2026-06-28 16:33:06 -07:00
Jinjing cea920a3e4 Harden failed check details links (#6661)
* fix: harden failed check details links

* chore: remove tracked node_modules symlink
2026-06-28 16:17:32 -07:00
Jinjing 3d3453c216 Propagate upstream errors from branch-based PR discovery (#6660)
Previously, transient errors during candidate branch discovery (such as
rate limits or network issues) were silently ignored, leading to a
false "no-pr" result and causing the sidebar PR state to flicker.

Now, track and return any pending error encountered during branch
lookups, propagating it as an upstream error if no PR is successfully
recovered.
2026-06-28 16:17:01 -07:00
Jinjing b6c0cb4f62 Migrate terminal scrollback setting from bytes to rows (#6593)
* Migrate terminal scrollback setting from bytes to rows

Transition terminal scrollback configuration from a byte-based (MB)
limit to a row-based count to align with standard terminal emulator
behavior.

- Introduce a shared scrollback policy to handle normalization and
  safe migration of legacy byte presets to row equivalents.
- Update persistence logic to automatically convert and clean up legacy
  settings on startup and write-back.
- Refactor the advanced settings interface and localization strings
  to let users configure scrollback in terms of rows (up to 50k).
- Live-apply row limit changes directly to mounted xterm instances
  without recreating panes or restarting PTY sessions.

* Migrate terminal scrollback setting from bytes to rows

Transition terminal scrollback configuration from a byte-based (MB)
limit to a row-based count to align with standard terminal emulator
behavior.

- Introduce a shared scrollback policy to handle normalization and
  safe migration of legacy byte presets to row equivalents.
- Update persistence logic to automatically convert and clean up legacy
  settings on startup and write-back.
- Refactor the advanced settings interface and localization strings
  to let users configure scrollback in terms of rows (up to 50k).
- Live-apply row limit changes directly to mounted xterm instances
  without recreating panes or restarting PTY sessions.

* defer updating terminal scrollback rows until blur or Enter

Avoid committing terminal scrollback row setting changes on every
keystroke, which can trigger rapid updates with incomplete or
invalid numbers. Instead, manage a local draft state and commit to
settings only when the input is blurred or the user presses Enter.
2026-06-28 16:13:16 -07:00
Neil 654dafb4f1 fix: use plain orca CLI shim for Claude Agent Teams on SSH remotes (#6586) 2026-06-28 16:03:16 -07:00
NeilandOrca da48fa71dd Refuse cross-worktree global fallback for browser text insertion (#5093) (#6563)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 15:58:15 -07:00
b916248294 Polish desktop native chat view (#6641)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
2026-06-28 15:43:07 -07:00
Brennan BensonandOrca b847a9df89 Run setup scripts for scheduled automation worktrees (#6236)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 15:25:35 -07:00
Brennan BensonandOrca 710d567e82 Suppress Codex auto-approval notifications (#6230)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 15:25:06 -07:00
Rod BoevandJinwoo Hong 5e3d8a12bf fix(terminal): support Windows shell selection for SSH hosts (#6466)
* fix(terminal): support Windows shell selection for SSH hosts

* fix(runtime): register SSH Windows capability preflight RPC

* fix(terminal): honor remote Git Bash and split preflight IPC seams

* fix(terminal): keep SSH Windows shell state tied to the selected host

* fix(terminal): preserve Windows SSH shell selection

---------

Co-authored-by: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
2026-06-28 15:08:13 -07:00
Brennan BensonandOrca a278a30b1c Let agents wait for setup when requested (#6298)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 13:50:00 -07:00
Brennan BensonandOrca 8ed890374a Refresh project worktrees created outside Orca (#6241)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 13:09:05 -07:00
Brennan BensonandNeil 5cb02a9420 Keep Orca visible when Windows startup stalls (#6462)
Co-authored-by: Neil <neil@stably.ai>
2026-06-28 12:31:57 -07:00
Brennan BensonandOrca e58a5e9e17 Simplify Appearance settings (#6459)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 11:50:29 -07:00
Brennan BensonandOrca 6015ad07a0 Show working tree in file explorer for repos using a separate Git directory (#6482)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 11:46:59 -07:00
Brennan BensonandOrca 5c3ba7be91 Improve inactive workspace cleanup UX (#3600)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 11:38:23 -07:00
Brennan BensonandOrca a71b865867 Show PR status for branch worktrees at a merged PR head (#6607)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 11:22:07 -07:00
Brennan Bensonandbrennanb2025 9a7b2e1e2e Validate WSL UNC worktrees inside the distro (#6536)
Opening a workspace whose worktree lives on a \wsl.localhost\<distro>
UNC path failed with 'Working directory ... does not exist' even though it
exists. validateWorkingDirectory relied on Win32 fs.statSync, which is
unreliable against the WSL 9P share and can report ENOENT for directories
that exist on the Linux side.

Make working-directory validation WSL-aware: when the cwd is a WSL UNC path,
ask the distro itself via 'wsl.exe -d <distro> -- test -d <linuxPath>' and only
fall back to the fs check when wsl.exe is inconclusive. Native Windows path
validation is unchanged.

Fixes #6331

Co-authored-by: brennanb2025 <brennanb2025@users.noreply.github.com>
2026-06-28 01:06:20 -07:00
Brennan Bensonandbrennanb2025 f768e6b503 Run the packaged orca CLI even when an Orca GUI instance holds the single-instance lock (#6542)
On Windows the bundled orca.cmd runs Orca.exe with the unpacked CLI
entrypoint and ELECTRON_RUN_AS_NODE=1. When that env var is dropped, Orca
boots as a GUI, loses the single-instance lock to an already-running
window, and exits silently with no stdout.

Add a packaged-CLI-entry redirect that detects a Windows launch whose argv
carries the known in-package CLI entrypoint and re-runs it in Electron node
mode before the single-instance lock gate can bounce it, then exits with the
CLI's status. Mirrors the existing maybeRedirectAppImageCliLaunch pattern.

Fixes #5774

Co-authored-by: brennanb2025 <brennanb2025@users.noreply.github.com>
2026-06-28 00:58:57 -07:00
Brennan Bensonandbrennanb2025 e47b3364d9 Preserve terminal scrollback when restoring a hidden alternate-screen pane (#6532)
* Preserve terminal scrollback when restoring a hidden alternate-screen pane

On Windows, an alternate-screen TUI pane (Claude Code) could lose scroll-up
after being hidden (tab/worktree switch or app backgrounded) and shown again.

Root cause: on hidden->visible restore, applyMainBufferSnapshot
unconditionally wrote a destructive clear (\x1b[2J\x1b[3J\x1b[H) before
replaying the snapshot, wiping xterm's scrollback. The attach/reattach path
already guards this same clear behind !isAlternateScreen (pty-transport.ts);
the snapshot path did not.

Thread an alternateScreen flag from the backend headless serialization
through the pty:getMainBufferSnapshot IPC + preload types into
applyMainBufferSnapshot, and skip the destructive clear when restoring an
alternate-screen buffer. Add a regression test asserting the clear is NOT
emitted for an alt-screen restore (and the existing normal-buffer test still
asserts it IS).

Fixes #5723

* test: account for alternateScreen flag in empty headless snapshot assertions

The alt-screen scrollback fix threads an alternateScreen flag through the
headless snapshot return type. Two sibling empty-buffer tests used exact
toEqual() assertions that did not include the new (legitimately false) key.
Update them to reflect the correct snapshot shape.

---------

Co-authored-by: brennanb2025 <brennanb2025@users.noreply.github.com>
2026-06-28 00:57:56 -07:00
Brennan Bensonandbrennanb2025 0af0102957 Resolve PowerShell to a real executable so terminals spawn (Windows error code 5) (#6537)
* Resolve PowerShell to a real executable so terminals spawn (Windows error code 5)

On Windows, launching a PowerShell terminal could fail with:
  Failed to spawn shell "pwsh.exe": Cannot create process, error code: 5

error code 5 = ERROR_ACCESS_DENIED from CreateProcessW inside node-pty's
ConPTY. Orca handed ConPTY a bare family name ("pwsh.exe" /
"powershell.exe"). When pwsh resolved to the Microsoft Store App Execution
Alias stub under WindowsApps (or was blocked by AV/AppLocker/SAC),
CreateProcessW rejected it with access-denied. isPwshAvailable probes via
execFileSync (which DOES follow the alias), so detection and launch disagreed.

Fix: resolve the PowerShell executable to a real absolute path before
spawning, skipping the WindowsApps alias stub, and add a Windows fallback
chain: pwsh (resolved abs) -> Windows PowerShell (System32 abs) -> cmd.exe.
SSH/remote and WSL/Git Bash/cmd paths are unaffected.

Fixes #5161

* test(pty): assert resolved absolute PowerShell path in win32 spawn tests

The PowerShell-resolution fix (#5161) now hands ConPTY a real absolute
executable instead of a bare 'powershell.exe'/'pwsh.exe' family name. The
pre-existing win32 spawn assertions in pty.test.ts (not in the worker's
per-file affected set) still expected the bare names and went red on the
full CI verify suite. Mock the fs seam and pin the install roots the
resolver probes so the resolved path is deterministic on Linux CI and
Windows alike, and assert the resolved System32 / Program Files paths.

* fix(pty): derive Windows shell name with win32 basename for determinism

getForegroundProcess() falls back to the spawned shell's basename when
Windows node-pty reports only the terminal name. The basename was taken
with the host-native path.basename, so on a non-Windows host (Linux CI)
the Windows absolute path 'C:\...\powershell.exe' was not split and the
whole path was stored as the shell name — making getForegroundProcess
return the absolute path instead of 'powershell.exe'. This produced a
host-dependent result for the same forced win32 platform.

Parse the spawned shell basename for the target platform (win32 basename
on Windows, POSIX otherwise), matching the daemon path
(pty-subprocess.ts already uses pathWin32.basename). The win32 spawn
foreground test is now deterministic on Linux CI and Windows alike.

---------

Co-authored-by: brennanb2025 <brennanb2025@users.noreply.github.com>
2026-06-28 00:33:00 -07:00
Brennan BensonandNeil 38483d5a69 Fix WSL watcher shutdown hang (#6489)
* Fix WSL watcher shutdown hang

* fix: harden WSL watcher startup failures

---------

Co-authored-by: Neil <neil@stably.ai>
2026-06-27 02:47:54 -07:00
Jinjing a8f949d24d Prevent review lookup failures from blocking PR preparation (#6490)
Catch errors during hosted review lookup if local blockers are present.
This ensures that network or API failures do not completely hide the
Create PR preparation UI if we can still guide the user to resolve local
issues first.
2026-06-27 02:37:59 -07:00
Jinjing 6729f683f6 Fix Orca CLI path resolution and improve registration UI (#6484)
* fix Orca CLI path resolution and improve registration UI

- Hydrate the shell PATH before running installer actions on macOS to
  match the user's terminal instead of launchd.
- Resolve the active macOS command path dynamically against shell PATH
  candidates, ignoring broken symlinks and non-executable files.
- Detect and report conflicts with unmanaged executables shadowing the
  configured command path.
- Add "Preparing..." and "Registering..." loading states to the settings
  and setup panels during preflight checks.

* Fix Orca CLI detection and installation path conflict checks

- Allow detecting a managed Orca command located later in PATH when the
  default path entry is missing or non-executable.
- Avoid raising installation conflicts for unmanaged commands located
  after the default install path, as they will be safely shadowed.
- Translate terminal setup and Orca CLI registration strings for
  Spanish, Japanese, Korean, and Chinese locales.

* Only open terminal when pre-install checks succeed

Prevent the terminal from opening and setting the terminal command if
onBeforeOpenTerminal or refreshPreInstallNotice throws an error.
2026-06-27 02:05:23 -07:00
Brennan BensonandOrca bf4ed350ae Materialize mobile-only pending session terminals (#6465)
Co-authored-by: Orca <help@stably.ai>
2026-06-26 20:16:52 -07:00
1f968b92c9 Fix browser pane stuck in HTML fullscreen (#6442) (#6451)
* Fix browser pane stuck in HTML fullscreen (#6442)

Guest content in a browser pane could enter HTML fullscreen but not
exit it: requestFullscreen() resized the host BrowserWindow into native
fullscreen, and exitFullscreen() had nothing to restore, leaving the
pane stuck.

Set the webview's disableHtmlFullscreenWindowResize preference so HTML
fullscreen is contained to the <webview> element. Exit then works and
fullscreenchange fires as guests expect.

* Apply browser guest fullscreen policy consistently

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-06-26 20:05:47 -07:00
Brennan BensonandOrca 5fd9f0c62c Prevent mobile worktree selection from focusing desktop (#6461)
Co-authored-by: Orca <help@stably.ai>
2026-06-26 19:34:33 -07:00
Brennan Benson 5578ffe318 Show the correct agent icon for terminal helpers (#6455) 2026-06-26 15:51:50 -07:00
Brennan Benson ccb09db440 Keep interrupted Claude turns from appearing active (#6452) 2026-06-26 15:01:55 -07:00
Brennan BensonandNeil 85d626b998 Fix fork PR detection for same-name upstreams (#6446)
Co-authored-by: Neil <neil@stably.ai>
2026-06-26 14:49:19 -07:00
Jinwoo HongandOrca 4904ffda9a Fix Remote Host downloads and agent status parity (#6436)
* Fix remote host downloads and agent status parity

Co-authored-by: Orca <help@stably.ai>

* Address remote download review comments

Co-authored-by: Orca <help@stably.ai>

* Avoid inefficient SSH chunk fallback

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-06-26 14:28:16 -07:00
Jinwoo Hong 59def7474a Revert Windows terminal clear repaint fix
Manual Windows testing still reproduces displaced input after Ctrl+K.
2026-06-26 14:05:09 -07:00
Jinwoo Hong daab519c5c Fix Windows terminal clear repaint (#6382) 2026-06-26 16:59:00 -04:00
Brennan BensonandNeil d188e7d2f6 Recover Windows worktree deletes from long paths (#6433)
Co-authored-by: Neil <neil@stably.ai>
2026-06-26 13:28:10 -07:00
Brennan BensonandOrca 4a98b11e77 Import linked worktrees under one project (#6441)
Co-authored-by: Orca <help@stably.ai>
2026-06-26 13:26:58 -07:00
Brennan Benson 996ab4a224 Preserve terminal output after hidden recovery fallback (#6435) 2026-06-26 12:39:28 -07:00
Neil 0f26a1bb5e Fix p10k wizard blocking terminal startup 2026-06-26 12:22:42 -07:00
Brennan Benson af52e418ea Keep sleeping agent panes resumable in place (#6411) 2026-06-26 12:10:08 -07:00
Brennan BensonandNeil b6ac7b9c92 Harden Windows hook command resolution (#6409)
* Keep spaced Windows Codex hook paths fast

* Harden Windows hook command resolution

---------

Co-authored-by: Neil <neil@stably.ai>
2026-06-25 22:43:25 -07:00
Jinjing dd0fa77882 Enhance PR auto-merge controls and switch to GraphQL mutation (#6405)
- Centralize and align auto-merge eligibility logic across web and
  mobile clients.
- Use the `enablePullRequestAutoMerge` GraphQL mutation instead of
  `gh pr merge --auto` to prevent immediate merges on clean branches.
- Fall back to `gh pr merge --auto` when a merge queue is required on
  the base branch.
- Hide the auto-merge control when only optional checks are pending.
2026-06-25 22:00:34 -07:00
Brennan BensonandNeil 6a23099594 Fix Windows agent hook regressions (#6407)
Co-authored-by: Neil <neil@stably.ai>
2026-06-25 21:59:19 -07:00
d0d257189c Speed up Windows Codex/Claude hooks without dropping events (#6402)
Windows runs managed hooks through a shell, and #6078 wrapped the
launcher in `powershell -EncodedCommand` to survive spaces in profile
paths. Combined with the inner PowerShell Invoke-WebRequest post, every
hook spawned two PowerShell processes (~300ms startup each), so a hook
took ~650ms+ and fired up to 6x per turn. Codex 0.140 renders that as
lingering "Running <event> hook" rows. The earlier RC worked around it
by deleting SessionStart/UserPromptSubmit/Stop, which loses lifecycle
status fidelity.

Keep all six Codex events and make them fast instead:

- Codex runs hooks as `cmd.exe /C <command>` and forwards our string
  verbatim when it has no spaces/quotes, so emit the bare .cmd path for
  cmd-safe profiles (zero shell startup) and fall back to the encoded
  PowerShell launcher only for spaced/metachar paths (#6078 robustness).
- Replace the inner PowerShell post with curl.exe (Windows 10 1803+),
  posting the same form fields as the POSIX hook and reading the raw
  payload from stdin via `--data-urlencode payload@-` so UTF-8 (e.g. CJK)
  survives without code-page translation.

Result: the common Codex case is 0 PowerShell (~70-150ms vs ~650ms);
spaced-path profiles drop to 1.

Claude runs hooks through Git Bash, so its launcher must stay
PowerShell-encoded (a bare path is what breaks it), but its inner post
moves to curl.exe too, cutting Claude from two PowerShell startups to
one.

Validated against the real Codex 0.140 binary (interactive TUI + exec):
all managed hooks fire, render briefly, and clear with no lingering
rows; the listener receives every post in 1-6ms.

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 20:53:58 -07:00
fe53387747 Fix automation run terminal targeting (#6374)
* fix(automations): track exact run terminal targets

Record terminal pane keys and PTY ids on automation dispatches, persist them across run updates, and propagate them through runtime launch results.

Use the recorded pane and PTY for completion detection, session reuse, prompt submission, and View run navigation so split-pane tabs reopen the actual run terminal.

Keep legacy runs compatible by falling back to workspace resume when exact terminal identity is absent.

* chore: address automation targeting review cleanup

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-06-25 20:51:34 -07:00
Brennan BensonandNeil fa3fd3ae02 Fix slow Codex hook statuses on Windows (#6398)
Co-authored-by: Neil <neil@stably.ai>
2026-06-25 19:24:04 -07:00
Brennan BensonandNeil 829f8d9618 Reduce duplicate diff loading work (#6389)
* Deduplicate in-flight diff reads

* Clear diff dedupe for ref-moving SSH operations

* Clear diff dedupe for worktree ref mutations

* Document diff dedupe mutation invalidation

---------

Co-authored-by: Neil <neil@stably.ai>
2026-06-25 18:47:26 -07:00
a12566b962 fix(onboarding): stop wrong-host Open as Folder fallback (#6393)
* fix(onboarding): stop wrong-host folder fallback (#6367)

* test(repos): isolate runtime fallback proofs

* test(repos): cover runtime status RPC failures

* test(repos): drop obsolete max-lines suppression

* Prevent runtime path probes from leaking project groups

* fix(onboarding): gate runtime folder fallback status

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-06-25 18:42:46 -07:00
6881475532 fix(ports): stop cursor-move redraws corrupting advertised dev-server hosts (#6371)
* fix(ports): stop cursor-move redraws corrupting advertised dev-server hosts

The Live Ports panel showed `localhst:5199` (and opened a broken URL with the
missing `o`) for a dev server that printed `http://localhost:5199`.

AdvertisedUrlWatcher cleans raw PTY bytes with stripTerminalControls, which
*deletes* ANSI/cursor sequences instead of emulating them. CLIs that redraw a
line differentially step the cursor forward over characters already on screen
(`ESC[1C`) rather than reprinting them; a real terminal renders the underlying
glyph, but deleting the move splices the two text runs together and drops the
skipped cell — `http://localh` + `ESC[1C` + `st` collapses to `localhst`.
`new URL()` then accepts the corrupted, plausible-looking host verbatim, so it
gets cached, displayed, copied, and opened.

Neutralize horizontal cursor moves (forward/back `C`/`D`, absolute column `G`,
position `H`/`f`) to a space before the CSI delete pass, so the URL candidate
matcher breaks at the seam and can't fuse a corrupted hostname. Worst case we
skip that frame and fall back to the kernel bind, which is the safe default.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(ports): document stripTerminalControls

Add a docstring to the exported helper to clear CodeRabbit's docstring
coverage warning and explain why horizontal cursor moves are neutralized.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ports): invalidate cursor-redrawn URL candidates

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-06-25 18:36:37 -07:00
Brennan BensonandNeil e257d79294 Prevent Codex hook trust prompts on Windows upgrades (#6388)
Co-authored-by: Neil <neil@stably.ai>
2026-06-25 17:24:09 -07:00
Damir Vandic e21ddd378c Fix pending remote terminal tab creation (#6353)
* Adopt pending terminal tab reveals

* Materialize pending remote terminal tabs

Wait for mobile terminal creates to produce a ready PTY handle before resolving. If the renderer only publishes a pending tab shell, materialize a headless PTY into the same tab/leaf identity so later renderer focus adopts it instead of duplicating the tab.

Add a pane-key spawn reservation shared by runtime materialization and renderer pty:spawn so focus racing fallback reuses the winning PTY, including when SSH env stripping removes ORCA_PANE_KEY. Cover the pending-surface fallback and both overlapping spawn race directions with regression tests.

* Settle pane spawn reservation on any post-spawn failure

The per-paneKey spawn reservation was only settled on spawn error, persist
error, or final resolve. A throw in the post-spawn region (seedHeadlessTerminal,
registerPty, rememberPaneKeyForPty, track) rejected the IPC promise but left the
reservation in paneSpawnReservationsByPaneKey forever, so every later spawn for
that pane awaited a promise that never settled and hung.

Wrap each post-reservation body (both spawn paths) in a catch-all that rejects
the reservation with the real error and rethrows; reject is a no-op once
resolved. Remove the now-redundant inner reject calls. Add regression tests for
both paths.

* Tear down runtime-owned headless tabs on mobile session close

The renderer-attached branch of closeMobileSessionTab closed the renderer's
pane but never pruned mobileSessionTabsByWorktree or dropped the persisted
binding. For runtime-owned headless terminals — serve/SSH materialized, or a
pending shell the renderer never adopted, all introduced by the pending-surface
materialize fallback — syncMobileSessionTabs then re-hydrates the closed tab
from the persisted session, resurrecting it with a live PTY. "Close others" on
a paired client showed closed remote tabs reappearing with their sessions still
running.

Add isRuntimeOwnedHeadlessMobileTab (serve/SSH-owned, or no live PTY and absent
from the renderer graph). When the whole parent of such a tab is closed, route
through closeHeadlessMobileTerminalTab to kill the PTY, remove the persisted
binding, and prune+emit, then best-effort notify the renderer so no adopted
pane is left dead. Genuinely renderer-owned tabs and exact split-leaf closes
keep the existing path. Cover the serve parent close, renderer-published vs
runtime-unadopted pending tabs, and the serve split-leaf case with regressions.

* Tear down only headless tabs the renderer never published on mobile close

The close-others teardown discriminator returned false for any resolved
non-serve/ssh PTY, so headless tabs carrying a daemon session id
(<worktreeId>@@<shortUuid>) that the host materialized but the renderer never
published leaked into the session snapshot and the client mirrored them
(confirmed live: host published 5 tabs for a worktree the renderer showed 1 for).

That id shape is ALSO minted for ordinary renderer-owned daemon-backed local
terminals, so it can't classify ownership by shape — the renderer graph
(this.tabs) does. Classify a tab as runtime-owned when it is serve/ssh (always,
they're preserved + re-hydrated) or when the renderer graph never published it
(a leaked/unadopted shell); delegate everything the renderer graph lists,
including ordinary @@ local terminals and pending tabs.

Regression tests: renderer-owned @@ tab is delegated (not de-persisted); leaked
@@ tab the renderer never published is torn down + de-persisted.
2026-06-25 14:36:35 -07:00
WolfieandNeil 8ed4218aa9 perf(git-status): throttle trailing refreshes and coalesce main-process reads (#6341)
Co-authored-by: Neil <neil@stably.ai>
2026-06-25 13:48:07 -07:00