Repository navigation
fix(terminal): every start in a deleted folder opens at the workspace root and says so - #30747
Conversation
…ved folder is gone, and say so A terminal whose start folder was deleted opened at the workspace root only when the window started it; the CLI, phone restore, orchestration and other host starts failed with the raw "Working directory ... does not exist" error, because the renderer had to opt in with a cwdFallback flag. The execution host now makes that decision for every start that may create a process (anything but a known live pane), with no caller flag. The fallback is reported only when a process was proven started at the requested folder, so a reattach or a crash restore in its recovered folder never claims "workspace root", and only then does the saved start folder heal. A recovered folder that was itself deleted yields to the request's resolved folder. The notice reaches each caller through surfaces it already has: the window's terminal line (now also written when a host-created tab attaches, and on a restored reattach), the agent.launch warning (also for callers that show the tab themselves), and a toast when a phone tap restores the tab.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Priority: ⚪ Pending latest changes Merge Risk: 🟡 Moderate · up to
|
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
be3e21f9-330b-4f6b-ae99-048f9b8a8d6b
📒 Files selected for processing: 65
mobile/src/session/session-write-reply-schema.tsmobile/src/session/startup-cwd-fallback-mobile-reply.test.tsmobile/src/session/use-mobile-session-tab-switching.tssrc/main/daemon/daemon-pty-adapter-cold-restore-reanchor.test.tssrc/main/daemon/daemon-pty-adapter-history-checkpoints.test.tssrc/main/daemon/daemon-pty-session-spawn.tssrc/main/daemon/daemon-pty-spawn-result.tssrc/main/ipc/pty-agent-pane-launch.test.tssrc/main/ipc/pty-launch-parity.test-fixture.tssrc/main/ipc/pty-launch-parity.test.tssrc/main/ipc/pty-pane-materialization-race.test.tssrc/main/ipc/pty-spawn-cwd-fallback.test.tssrc/main/ipc/pty/host-env/spawn-cwd.tssrc/main/ipc/pty/host-env/startup-cwd-directory-exists.test.tssrc/main/ipc/pty/host-env/startup-cwd-directory-exists.tssrc/main/ipc/pty/ipc/spawn-agent-launch.tssrc/main/ipc/pty/ipc/spawn-commit-persist.tssrc/main/ipc/pty/ipc/spawn-commit.tssrc/main/ipc/pty/ipc/spawn-preflight.tssrc/main/ipc/pty/ipc/spawn-state.tssrc/main/ipc/pty/ipc/spawn-types.tssrc/main/ipc/pty/pane/stable-owner.tssrc/main/ipc/pty/register-handlers.tssrc/main/ipc/pty/runtime/spawn-commit.tssrc/main/ipc/pty/runtime/spawn-options.tssrc/main/ipc/pty/runtime/spawn-preflight.tssrc/main/ipc/pty/runtime/spawn-state.tssrc/main/ipc/pty/runtime/spawn.tssrc/main/ipc/pty/spawn-options-agent-workspace-trust.test.tssrc/main/ipc/pty/spawn-startup-target.tssrc/main/persistence/loading-store/pty-binding-fast-lane.tssrc/main/persistence/loading-store/pty-binding-persistence.tssrc/main/persistence/loading-store/pty-binding-placement-inertness.test.tssrc/main/persistence/loading-store/pty-binding-session-update.tssrc/main/persistence/loading-store/pty-spawn-commit-dependencies-fixture.tssrc/main/providers/local-pty-session-activation.tssrc/main/providers/pty-spawn-result.tssrc/main/runtime/orca-runtime-terminal-cwd.test.tssrc/main/runtime/rpc/methods/agent-launch-caller-selection.test.tssrc/main/runtime/rpc/methods/agent-launch-surfaces.tssrc/main/runtime/rpc/methods/agent-launch.test-fixture.tssrc/main/runtime/rpc/methods/session-tab-mutation-methods.tssrc/main/runtime/rpc/methods/terminal/terminal-create-sort-stamp.test.tssrc/main/runtime/rpc/methods/terminal/terminal-lifecycle-methods.tssrc/main/runtime/runtime-pty-controller-contract.tssrc/main/runtime/session-lifecycle/projection/perform-mobile-session-pty-records-refresh.tssrc/main/runtime/terminal/launch/mobile-terminal-owned-create.tssrc/main/runtime/terminal/launch/terminal-create.tssrc/preload/api/pty-api.tssrc/preload/api/pty-bridge-session-control.tssrc/renderer/src/components/terminal-pane/codex-detached-pane-restart.tssrc/renderer/src/components/terminal-pane/ipc-pty-connect-result.tssrc/renderer/src/components/terminal-pane/ipc-pty-spawn-request.tssrc/renderer/src/components/terminal-pane/pty-connection-reattach-mode-reset.spec.tssrc/renderer/src/components/terminal-pane/pty-connection-runtime-owner-spawn-routing.spec.tssrc/renderer/src/components/terminal-pane/pty-connection/deferred-session-reattach-connect.tssrc/renderer/src/components/terminal-pane/pty-connection/pane-transport-options.tssrc/renderer/src/components/terminal-pane/pty-connection/startup-cwd-fallback-notice.tssrc/renderer/src/components/terminal-pane/pty-transport-connect-spawn.test.tssrc/renderer/src/components/terminal-pane/pty-transport-reattach-admission.test.tssrc/renderer/src/components/terminal-pane/pty-transport-types.tssrc/shared/launch-parity-window-request.test-fixture.tssrc/shared/runtime-session-contracts.tssrc/shared/runtime-terminal-contracts.tssrc/shared/startup-cwd-fallback.ts
💤 Files with no reviewable changes: 14
- src/main/ipc/pty-pane-materialization-race.test.ts
- src/main/ipc/pty/register-handlers.ts
- src/preload/api/pty-bridge-session-control.ts
- src/shared/launch-parity-window-request.test-fixture.ts
- src/renderer/src/components/terminal-pane/pty-connection/pane-transport-options.ts
- src/main/persistence/loading-store/pty-spawn-commit-dependencies-fixture.ts
- src/main/ipc/pty/ipc/spawn-types.ts
- src/preload/api/pty-api.ts
- src/main/ipc/pty/spawn-options-agent-workspace-trust.test.ts
- src/main/ipc/pty/host-env/spawn-cwd.ts
- src/main/ipc/pty/ipc/spawn-agent-launch.ts
- src/renderer/src/components/terminal-pane/pty-transport-types.ts
- src/renderer/src/components/terminal-pane/codex-detached-pane-restart.ts
- src/renderer/src/components/terminal-pane/ipc-pty-spawn-request.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review.
|
A terminal whose saved start folder was deleted could open from the desktop window but fail through the host. Host starts now resolve the folder on the execution host before launch preparation and can open at the workspace root with the existing caller warning or explicit phone toast. Window restore writes its existing sentence once after replay; normal restore writes none. The saved tab folder has two writers: the window tab snapshot replaces the host snapshot. The retained saved folder now travels through the existing reveal folder field so a newly revealed tab writes the right value. TEMPORARY: consolidation to one writer is owed to rows 14–18 (window starts moving onto the host path), tracked in #30861, the layout-owner migration that removes the second writer. Reviewed head: Only proven absence permits a host saved-folder correction. Unreadable or unverifiable folders retain their saved choice; recovered unknown is retained. Async probes preserve the shared resolver with no deadline. A pending probe cannot authorize healing or complete the spawn binding commit; inherited admission can save a NEW tab’s original request first. Existing ownership and durable-save refusal behavior remains. Final exact-head QA: PASS, M4Air ticket 1059. Both main
Earlier phone-toast and Windows/WSL evidence is accepted by the launcher, with its original revision All scored QA processes were stopped; source and lockfiles stayed clean. Headless healing and unreadable saved-folder retention are backed by RPC, renderer/Store memory and SQLite evidence, rather than inferred from screenshots. Deferred and accepted: early agent-launch/window phone-copy omissions are TEMPORARY STA-11295 and rows 14–18; the host-tab in-terminal line is owed to rows 14–18 and tracked in STA-11517; explicit UNC requests remain STA-11218; renderer remount can remove its notice. Existing guest permission ambiguity remains. Bounded reservation/notice and indirect-activation concerns remain unconfirmed, with no added guard or state. For Brennan’s review
Earlier phone evidence at c90a82b (accepted unchanged mobile code):
Three judgment points: only proven absence permits correction, both restore branches preserve the outcome, and retained folder uses the existing reveal field. |











Problem
Terminals whose saved start folder was deleted could open from the desktop window but fail when started through the host, phone, restore or orchestration. These callers made the folder decision at different stages, so some reached launch preparation with a deleted folder.
The saved tab folder also has two writers: the host’s snapshot and the window’s tab snapshot. The window’s snapshot replaces the host’s. This fix makes a newly revealed window tab write the right value by passing the retained saved folder through the existing reveal folder field.
User-facing change
Starts share the folder decision on the machine running the terminal, before launch preparation. A deleted requested folder opens at a usable workspace root. The existing CLI/RPC warning reports fallback; an explicit phone restore gets one toast and automatic restore stays quiet. A window-created terminal writes its existing sentence once after restored output, and normal restore writes none. The host-created terminal line remains deferred below.
Host-owned saved tabs correct their saved folder only after proven absence. Access errors, I/O errors, timeouts and inconclusive probes never authorize correction. Recovery keeps a present or unverifiable historical folder; a proven-missing historical folder can yield to the resolved request. Attaching to a live terminal preserves its identity and saved folder. A deleted workspace root still fails.
Native folder checks are asynchronous, preserving main’s shared resolver and ownership/commit rules. There is no probe deadline: an unanswered check can hold its start indefinitely while the main event loop remains free. It cannot authorize a fallback-derived correction or complete the spawn binding commit. Existing admission can save a new tab’s original requested folder before probing; that is distinct from healing an existing choice.
Differences and limits
Validation
Current head:
000e41e17a38a26f8953f68de9332acd7d4ff001, composed with mainfc8439e05f1eceb33e7178214725de408c5d73ca.Formatted production additions/deletions: +326/−117 in 51 paths, including fixtures. Tests: +317/−154 in 22 paths. These satisfy the authorized absolute production ceiling of +355 and test additions do not exceed production additions. All 163 tests in nine named suites passed through the machine queue; the normal commit hook passed without changing the approved tree. Both fresh full source reviews found no new concrete defect, including the final whole-mechanism comparison and readiness audit.
The exact-head full PR workflow and its aggregate gate passed. All PR checks were successful or skipped.
Runtime QA
Final exact-head QA: PASS, M4Air ticket 1059. Both main
fc8439e05f1eceb33e7178214725de408c5d73caand PR000e41e17a38a26f8953f68de9332acd7d4ff001were built in this run, plus main-owned-layout variants of both. Codex drove isolated hidden Electron through CDP/RPC; real Claude Code 2.1.306 and Codex 0.163.0 ran as the agents under test.Earlier phone-toast and Windows/WSL evidence is accepted by the launcher, with its original revision
c90a82b94cb3e14e08fa60ba92379ced8725e357. Explicit phone tap produced one toast; automatic restore remained silent; Windows mounted-drive denial preserved the saved original through restart. SSH and never-settling probes remain source-only; no unsafe hung mount was manufactured. Other I/O, timeout and inconclusive cases remain source/test evidence. The pending-probe ordering claim excludes inherited new-tab admission of the original requested folder.All scored QA processes were stopped; source and lockfiles stayed clean. Headless healing and unreadable saved-folder retention are backed by RPC, renderer/Store memory and SQLite evidence, rather than inferred from screenshots.
Visual proof
Final-head normal restore, unreadable start and held handle
Final-head real Claude and Codex replies, and command split
Earlier phone evidence at c90a82b (accepted unchanged mobile code):
Author: @BrennanKB5