Repository navigation
Land the WSL project mover dark (merges only after verify-15b, the flag-off audit and green CI) - #34059
Merged
Conversation
…collectors Co-Authored-By: Claude <noreply@anthropic.com>
…urce-kind scope A local-WSL scope lives on host local and owns only its projects, so host-wide matches stay an SSH whole-host rule. SSH bytes are pinned by the collector golden. Co-Authored-By: Claude <noreply@anthropic.com>
…ormant state (D1b-3c) Collects the scoped projects, their groups and every dormant-state kind through the local-WSL export scope, rewrites UNC paths to the distro's, and returns blockers for anything the collectors can't carry instead of dropping it. Automations move disabled, as the wire requires, and come back as a list to re-enable on the host after commit. Co-Authored-By: Claude <noreply@anthropic.com>
…the host proves a commit Co-Authored-By: Claude <noreply@anthropic.com>
… large for a request Co-Authored-By: Claude <noreply@anthropic.com>
…d move forward on a by-reference commit only once the host flushed it Co-Authored-By: Claude <noreply@anthropic.com>
… stays readable Co-Authored-By: Claude <noreply@anthropic.com>
… scrollback, and never read bytes in render (D1b-6d-1)
…the focused one (D1b-6d-1)
…e the shared RPC error check, after main moved both (D1b-6d-1)
…umable on this computer (D1b-7a)
…ad of writing layout directly (D1b-7a)
…dden-repo API (D1b-7a)
…ssion after a move (D1b-7c) Registers the main-side desktop rewrite stores ui-routing, session-globals and host-session-seed. Adds a +2 main layout-writer baseline line for wsl-move-main-rewrite-stores.ts: these are one-shot, ledgered move rewrites, and no LayoutCommand can set focus or seed a runtime host's partition.
… one copy of each moved tab, and copy instead of move (D1b-7c)
…heir UI through catalog prunes (D1b-7d) Registers the renderer-side desktop rewrite stores quick-open-history, file-view-preferences and notebook-environments. The renderer copies each moved workspace's entry to its WSL host key, marks it applied in the same storage, and records the ledger entry; main requests a storage flush first and accepts only the main window. Committed moves are re-listed for re-application at every startup. Catalog prunes keep filters, hook trust and setup-script dismissals of moved repos.
…migration folder (D1b-7d)
…manifest exporter, where 7d moved it (D1b-7d)
…he desktop (D1b-7e) Settled local worker dispatches and their worker-terminal rows in a moved project take the WSL host's worktree id, in one ledgered, idempotent store. Chat workers, live rows, federated attachments and JSON receipts stay as written; automations keep their unchanged local copy (the scheduler only advances it). Per-table dispositions for orchestration.db. Co-Authored-By: Claude <noreply@anthropic.com>
…is live; skip federated rows (D1b-7e review) Co-Authored-By: Claude <noreply@anthropic.com>
…ve (D1b-7f) A committed WSL move now copies each in-app browser profile's cookies once into the WSL host's stable route partition (owner decision 3a), merging without overwriting what the host jar holds and never touching the source. Where that is infeasible (no deployment link so no stable partition, the destination is not a WSL host or is gone, or the partition name is held by another identity) the host starts fresh and the move journal records why (3b). Registered as the ledgered browser-cookies rewrite store; it runs only once browser sessions and an app window exist. WSL_MOVE_DESKTOP_REWRITE_REGISTRY_COMPLETE stays false.
…nd plan delta moves (D1b-8)
…duction gate facts and journaled restore folders One entry point (and preview/start/cancel/listUnfinished IPC for D1b-9) plans the move, gates terminals on the hook server's agent status, the close-tab process probe, running automation runs and live dispatches, pauses and proves exit, stages, sends blobs, commits only from blobs-transferred (#29825), and finishes on the desktop. Any failure resets to zero or goes forward when the host committed. Restore folders and the automations to turn back on are kept in the journal; the host turns those automations back on after commit, retried until it confirms. A real-PTY test pauses daemon shells, and runs on a real distro in the WSL orcad lane.
…ult behind the internal WSL hosts gate (D1b-9)
…fter a reload, and lets a start settle an unfinished move (D1b-9 review)
… through Reflect (D1b-9)
…/wsl-mover-land-2 # Conflicts: # src/renderer/src/i18n/locales/zh.json
OrcaWin
added a commit
that referenced
this pull request
Oct 28, 2026
…on, as #34059's mover now requires Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit bfeb4fe3ae7f278ac452e376d426315dbf7b985c)
This was referenced Oct 28, 2026
Merged
…/wsl-mover-land-2 # Conflicts: # src/renderer/src/i18n/locales/es.json # src/renderer/src/i18n/locales/fr.json # src/renderer/src/i18n/locales/ja.json # src/renderer/src/i18n/locales/ko.json
8 of 9 tasks
OrcaWin
added a commit
that referenced
this pull request
Oct 28, 2026
…core registration under its line cap The optional commit-message resolvers pass straight through, so the call is the same with or without them. #34059 left this file at the 300-line cap and the WSL drive-project wiring adds to it. Co-Authored-By: Claude <noreply@anthropic.com>
OrcaWin
added a commit
that referenced
this pull request
Oct 28, 2026
…on, as #34059's mover now requires Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit bfeb4fe3ae7f278ac452e376d426315dbf7b985c)
…/wsl-mover-land-2 # Conflicts: # src/main/ipc/ui.ts
nwparker
added a commit
that referenced
this pull request
Oct 28, 2026
… label moved automations Follow-ups from the #34059 undo review, stacked on it: - A host workspace's terminal count reads as zero only when the host says it no longer has the workspace (selector_not_found); any other error, or an answer it cannot read, now counts as the host not answering, so undo refuses. - The exit wait keeps one wall-clock deadline for the whole stop instead of counting polls, so a slow host can no longer stretch it many times over. - A test for D1b-7a's hydration purge rule: a moved project's chats survive, a stale worktree still goes. - A moved project's local automation reads "Runs on the <distro> host" in the list, where it read Enabled though this computer never runs it.
8 of 9 tasks
nwparker
added a commit
that referenced
this pull request
Oct 28, 2026
…el moved automations (#34686) * fix(wsl-mover): undo's host checks fail closed and keep one deadline; label moved automations Follow-ups from the #34059 undo review, stacked on it: - A host workspace's terminal count reads as zero only when the host says it no longer has the workspace (selector_not_found); any other error, or an answer it cannot read, now counts as the host not answering, so undo refuses. - The exit wait keeps one wall-clock deadline for the whole stop instead of counting polls, so a slow host can no longer stretch it many times over. - A test for D1b-7a's hydration purge rule: a moved project's chats survive, a stale worktree still goes. - A moved project's local automation reads "Runs on the <distro> host" in the list, where it read Enabled though this computer never runs it. * fix(wsl-mover): undo gives the host's terminals a minimum window to exit after the last sleep A slow but healthy host with many workspaces could spend the whole stop budget sleeping them and then read as still running on the first exit check. The exit wait now runs at least 5 s past the last sleep, within or beyond the overall deadline.
1 task done
OrcaWin
added a commit
that referenced
this pull request
Oct 28, 2026
…core registration under its line cap The optional commit-message resolvers pass straight through, so the call is the same with or without them. #34059 left this file at the 300-line cap and the WSL drive-project wiring adds to it. Co-Authored-By: Claude <noreply@anthropic.com>
OrcaWin
added a commit
that referenced
this pull request
Oct 28, 2026
…on, as #34059's mover now requires Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit bfeb4fe3ae7f278ac452e376d426315dbf7b985c)
OrcaWin
added a commit
that referenced
this pull request
Oct 28, 2026
…on, as #34059's mover now requires Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit bfeb4fe3ae7f278ac452e376d426315dbf7b985c)
OrcaWin
added a commit
that referenced
this pull request
Oct 28, 2026
…core registration under its line cap The optional commit-message resolvers pass straight through, so the call is the same with or without them. #34059 left this file at the 300-line cap and the WSL drive-project wiring adds to it. Co-Authored-By: Claude <noreply@anthropic.com>
OrcaWin
added a commit
that referenced
this pull request
Oct 28, 2026
…on, as #34059's mover now requires Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit bfeb4fe3ae7f278ac452e376d426315dbf7b985c)
7 of 9 tasks
OrcaWin
added a commit
that referenced
this pull request
Oct 28, 2026
…core registration under its line cap The optional commit-message resolvers pass straight through, so the call is the same with or without them. #34059 left this file at the 300-line cap and the WSL drive-project wiring adds to it. Co-Authored-By: Claude <noreply@anthropic.com>
OrcaWin
added a commit
that referenced
this pull request
Oct 28, 2026
…on, as #34059's mover now requires Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit bfeb4fe3ae7f278ac452e376d426315dbf7b985c)
nwparker
added a commit
that referenced
this pull request
Oct 28, 2026
…D1c-2) (#33090) * feat(wsl): run Git for Windows for a WSL project on a Windows drive A project on C:\ whose runtime is WSL ran every Orca Git command through wsl.exe on /mnt/c: ~300x slower than Windows Git, and blind to Windows-side edits. The project's WSL runtime preference gains an optional `git: 'windows-host'`. With it, Orca's Git (and where new worktrees go) is Windows; terminals, agents, accounts and hooks still resolve to WSL, so nothing else changes. Older builds drop the field and go back to WSL Git. The conversion checks first, then the caller saves the returned preference through the normal project update: - Git for Windows must exist. - New worktrees must not be set to go inside the distro. - No linked worktree may have a Linux-path link. WSL Git made those; Windows Git sees them as prunable, and Orca's prune after a worktree removal would delete their metadata. - Optionally writes core.autocrlf=true into the repo when Windows Git uses it, so WSL Git in the project's terminals stops seeing CRLF changes. Never core.checkStat. IPC is refused off Windows and with the internal WSL hosts gate closed. Co-Authored-By: Claude <noreply@anthropic.com> * test(wsl): mock the drive-project IPC in the core handler registration test Co-Authored-By: Claude <noreply@anthropic.com> * test(wsl): pin WSL Git for a drive project that never chose Windows Git, and record which Git ran * fix(wsl): base-ref lookups and the remote-identity sweep run Git where the project's runtime does * fix(wsl): route base-ref and remote-identity reads by runtime only with WSL hosts on These reads ran host Git on main. Routing them into a WSL-runtime project's distro is part of D1c, so with the WSL hosts gate closed they run host Git exactly as before. (cherry picked from commit 2ed82987dc5b82c3a86ea7e03ce05e9efc3e77fb) * refactor(ipc): register the filesystem handlers in one call, keeping core registration under its line cap The optional commit-message resolvers pass straight through, so the call is the same with or without them. #34059 left this file at the 300-line cap and the WSL drive-project wiring adds to it. Co-Authored-By: Claude <noreply@anthropic.com> * fix(wsl): skip folder repos in the Windows Git check, and read worktree links with the prune guard's reader Folder repos run no Git, so rev-parse on them always failed the preview. The link reader and the WSL-authored test now come from worktree-prune-guard.ts; the copy's startsWith('/') wrongly refused //wsl.localhost links, which Windows Git writes itself. Co-Authored-By: Claude <noreply@anthropic.com> * fix(wsl): the remote-identity sweep checks the distro a drive project's Git runs in, so it never boots a stopped one --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
OrcaWin
added a commit
that referenced
this pull request
Oct 28, 2026
…on, as #34059's mover now requires Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit bfeb4fe3ae7f278ac452e376d426315dbf7b985c)
OrcaWin
added a commit
that referenced
this pull request
Oct 29, 2026
…on, as #34059's mover now requires Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit bfeb4fe3ae7f278ac452e376d426315dbf7b985c)
nwparker
pushed a commit
that referenced
this pull request
Oct 29, 2026
…on, as #34059's mover now requires Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit bfeb4fe3ae7f278ac452e376d426315dbf7b985c)
nwparker
pushed a commit
that referenced
this pull request
Oct 29, 2026
…on, as #34059's mover now requires Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit bfeb4fe3ae7f278ac452e376d426315dbf7b985c)
nwparker
added a commit
that referenced
this pull request
Oct 29, 2026
… restart (D1c-4c) (#33135) * feat(wsl): convert UNC Windows-drive projects to drive paths across a restart (D1c-4c) * fix(wsl): read the conversion's field table from its shared home * test(wsl): the conversion runs Windows Git only on the drive path, since WSL denies UNC drive folders WSL 2.7.11 answers EPERM for \\wsl.localhost\<distro>\mnt\c\... from Windows. Pin that the preflight's Git runs and worktree-link reads use C:\... by making every UNC access throw EPERM. * fix(wsl): name the cause when a conversion refuses over saved state A refusal over saved state now says whether a project also holds an unconverted repo, or a drive key already holds different data (and which key), instead of a bare collision code. The fields are optional, so the window's copy still reads an older host's refusal. The seeded shape (a saved UNC worktree with tabs beside the bare drive row startup discovery wrote) now converts. * test(wsl): startup rolls back only when the drive key holds different user data * fix(wsl): connect the conversion's pause to a WSL host as a user action, as #34059's mover now requires Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit bfeb4fe3ae7f278ac452e376d426315dbf7b985c) * fix(wsl): never report a committed conversion as rolled back; record and check its profile; refuse paths off a Windows drive mount - The journal's post-commit phase write sat inside the rollback catch, so a failure there dropped the journal and reported rolled-back for a profile already rewritten. The write now follows the commit outside the catch: a failure leaves the journal 'prepared', whose rewrite is idempotent, and reports resuming. - The journal records the profile it rewrites, and startup runs only the active profile's. - The run reads the distro's Windows-drive mounts and passes them to the scope. Co-Authored-By: Claude <noreply@anthropic.com> * test(wsl): type the journal-failure switch without a cast * fix(wsl): only this profile's waiting conversion blocks starting another * test(wsl): compare the two profiles' journals without depending on directory order * fix(wsl): a torn shell-history meta.json never stalls a conversion, it is written atomically, and only a prepared conversion blocks a new one --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
9 of 10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ELI5
This lands the WSL project mover on main dark. It's the feature that moves a local project, with its terminals, history, chats, browser logins and drafts, into the desktop's WSL host and can bring it back ("Use on this computer again"). Every code path stays inert unless
ORCA_INTERNAL_WSL_HOSTS=1, the same way Track C and D0 landed. Shipped builds see no change.Merges dark only after verify-15b, the independent flag-off audit and green CI.
What Changed
This is the mover's review base plus its restore stack (#32956 → #32965 → #32969 → #33040) and the move orchestrator (D3a, #33802, with its fix #34087), merged with current main. Every theme below was already reviewed as the PRs listed beside it.
Total: about 14.7k product lines and 19.3k test lines across 402 files.
Commits on top of the reviewed stack:
runtime-environment-connectivity-handlers.ts: kept both. The undo spawn fence runs ahead of main's new chat-creation recording, so refused starts aren't recorded.orcad-migration-blob-transfer.test.ts: took main's deletion of the inventory test (test: remove low-value wrapper and inventory suites #33736). A narrower pin is re-added below.ipc/session.ts: imports only; kept both.restored-pane-materialize.ts: imports only; kept both.renderer-shutdown-checkpoint.ts: kept main'serror = formatShutdownCheckpointFailureReason(...), andupdateUIstays wrapped in!isWslMoveWindowWriteHeld().session-tabs-runtime-capabilities.ts: kept both new entries. The scrollback-read entry was later moved out of the static list; see the wire section.workspace-session-host-hydration.tsis kept exactly as main has it, because adding to it pushed it over the line limit. The moved-rows filter moved to startup's session read (wslMovedSessionReadApi), with its test updated.nwparker/wsl-mover-restore-undo-liveat 8a54590):wsl-move-handlers.ts: took D3a's deletion of the inline undo; it moved intowsl-move-release-here.ts. That file keeps the gate check first, refuses before any host stop (X1), and keeps the spawn fence until the reload.nwparker/wsl-mover-restore-undo-liveat 2a90632, fix(wsl-mover): D3a waits out a move still being retained; orchestrator-over-driver tests #34087): no conflicts.wsl-move-storage-dispositions.ts: kept the stack's layout and added main'sremoved_orchestration_workandremoved_orchestration_work_coverageto the receipts list.wsl-host-service.test.ts: imports only; kept both.wsl-host-service.ts: imports only; kept both. D3a's Remove note pushed the file one line over the limit, so the Remove teardown (stop the server, disconnect, release the holder) moved unchanged intowsl-host-remove-teardown.ts.service.connect, which may boot the distro and lifts a park). Neither reconnects a host that is already ready (the orchestrator readies it before the driver runs). The orchestrator and its startup recovery keep the no-boot path. A host whose Remove is still pending is never connected.session.readTerminalScrollbackout of the method manifest had dropped it from the generated params catalog (verify:rpc-params-catalogfailed). The method is static in the manifest again, so the catalog types it; the dispatcher leaves it unregistered on any host that does not serve moved panes' history.daemon-pty-spawn-result.tsand its wake test: identical to main's fix(terminal): save a woken terminal's first history as a full snapshot #34060.AddWslHostFormPanel.test.tsx: took main's removal of three tests (test: remove 68 low-value cases and 18 suites #34112) and kept this PR's mover-copy test.orcad-source-automation-state.ts: main now moves enabled SSH automations (always sent disabled, re-enabled after commit) and lists the ones blocked by a running run; this PR records which WSL-moved automations were enabled. Kept both. The WSL list now reads the source row'senabled, since main's projection always sends it disabled (the manifest-export test pins it).orcad-source-dormant-state.ts: kept main'srunningAutomationItemsand this PR'sautomationsEnabledAtSource.wsl-host-service.test.ts: kept main's new imports and tests; the two Remove-as-user-action tests moved unchanged towsl-host-service-user-actions.test.tsto stay under the line limit.ssh-orcad-legacy-relay-bridge.spec.ts, whose Move anyway lookup also matched fix(ssh): make Move anyway the next step when saved items refuse a host's move #34041's refusal toast.wsl-host-service-test-connector.ts, byte-identical to this PR'swsl-host-service.test-support.ts; took main's file and pointed this PR's tests at it.WslHostServicenever reconnects a serving host and adds a bridge host once. Its fixture import points at main's file.browser-cookie-clear-store.ts(main's shared debugger session, plus this PR's cookie-jar read on it);confirmation-dialog.test.tsxanden.json(both additions);repo-header-project-actions.tsx(main's moved import plus the move menu item);fetch-all-worktrees.ts(main moved the hydration purge intohydrated-worktree-purge.ts; this PR's keep-a-moved-project's-chats rule moved with it).Why
One PR instead of a themed chain, for two reasons:
Flag-off safety (read-only audit of every modified shared file)
wslHostsGateOpen(). What runs ungated only registers stores and a journal listener.repos:listWslMovedIPC call is added at startup.orcadRetainedis only validated, and only the mover writes it. The catalog actions pass data through unchanged.local-wslbranches are unreachable for SSH, and the ambiguity rule is gated tolocal-wsl.Wire surface
session.readTerminalScrollback(defined in the manifest and params catalog, registered by the dispatcher only there),session.terminal-scrollback-read.v1(advertised),orcad.migration-blob.terminal-history.v1(advertised) and the terminal-history installer.isWslHostOrcadProcess) or an e2e host standing in for one (ORCA_E2E_WSL_MOVE_DESTINATION=1). Every other host answers method-not-found and advertises neither capability.durableCommittedfield on abort-by-reference, and its extra flush before acommittedanswer.orcad-migration-blob-transfer.test.tspins the advertised blob kinds for both a WSL host and any other host.session-terminal-scrollback.test.tsdispatches the method end to end: registered, params-validated and served on a move destination; method-not-found elsewhere.Known limits
ORCA_INTERNAL_WSL_HOSTS=1and is then opened by a release build shows the moved-projects section, and "Use on this computer again" refuses. This affects internal testers only; release users can't make a move.Linked Issue
N/A (maintainer).
Visual Proof
N/A: dark behind
ORCA_INTERNAL_WSL_HOSTS. Real-host evidence comes from verify-15b on awin, run against this head.Testing
I manually tested these changes locally
Automated tests added/updated, or explained why not below
New tests on top of the reviewed stack:
Local checks:
pnpm tcandcheck:code-quality:changedpass, the ratchets pass, and the touched tests pass. Full lint and the full test suite are left to CI while the build Mac is overloaded.Real host: verify-15a ran on the stack. verify-15b will run on this head.
Review
Agent skill upstream boundary
Notes
durableCommittedfield on abort-by-reference (see Wire surface), which older peers ignore.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)