mirror of
https://github.com/stablyai/orca.git
synced 2026-09-25 00:02:35 +00:00
* 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.