Repository navigation
feat(wsl): connect to a WSL distro's orcad over wsl.exe stdio only (WSL-via-orcad C5) - #27834
Conversation
ca22e1a to
21a0166
Compare
67bff99 to
5e76a1b
Compare
c745dd1 to
a0524da
Compare
5e76a1b to
3fb1697
Compare
a0524da to
cd98e85
Compare
3fb1697 to
4e55a67
Compare
5881524 to
c6338e9
Compare
4e55a67 to
6837a61
Compare
📝 Walkthrough
Priority: ➖ Normal 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:
e0cec902-3727-4e42-8d37-8f67104c5636
📒 Files selected for processing (7)
src/main/ssh/orcad-stdio-bridge-provider.tssrc/main/wsl/wsl-orcad-bridge-test-child.tssrc/main/wsl/wsl-orcad-connection.test.tssrc/main/wsl/wsl-orcad-connection.tssrc/main/wsl/wsl-orcad-deploy.tssrc/main/wsl/wsl-orcad-stdio-bridge.test.tssrc/main/wsl/wsl-orcad-stdio-bridge.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.
| // Every call relaunches a stopped orcad, so a distro restart is recovered here. | ||
| const launch = await (this.dependencies.deployAndLaunch ?? deployAndLaunchWslOrcad)(distro, { | ||
| environmentId, | ||
| label, | ||
| force: options.force, | ||
| signal: options.signal, | ||
| holder: this.dependencies.holder, | ||
| createTransport: () => transport | ||
| }) | ||
| if (launch.outcome === 'deferred') { | ||
| throw new WslOrcadLaunchDeferredError(launch) | ||
| } | ||
| if (this.generation(key) !== generation) { | ||
| throw new WslOrcadConnectionSupersededError(distro) | ||
| } | ||
| const current = this.active.get(key) | ||
| if ( | ||
| current && | ||
| current.connection.remotePort === launch.port && | ||
| current.connection.environmentId === environmentId | ||
| ) { |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
sed -n '145,310p' src/main/wsl/wsl-orcad-deploy.ts
rg -n 'runtimeId|readiness|pairingOffer|already.running|alreadyRunning' src/main/wsl/wsl-orcad-deploy.ts src/main/wsl/wsl-orcad-connection.ts src/main/wsl/wsl-orcad-connection.test.tsRepository: stablyai/orca
Length of output: 4863
🏁 Script executed:
set -e
printf '%s\n' '--- connection manager ---'
sed -n '1,330p' src/main/wsl/wsl-orcad-connection.ts
printf '%s\n' '--- deploy definitions and imports ---'
sed -n '1,230p' src/main/wsl/wsl-orcad-deploy.ts
printf '%s\n' '--- bound symbols ---'
rg -n -F --glob '*.ts' -e 'deployAndLaunchWslOrcad' -e 'verifyWslOrcadIdentity' -e 'probeManagedOrcadReadiness' -e 'adopt' -e 'already-active' -e 'isManagedOrcadReady' src/main src | head -240
printf '%s\n' '--- identity and readiness definitions ---'
sed -n '1,220p' src/main/server/serve-readiness.ts
rg -n -F --glob '*.ts' -e 'function verifyWslOrcadIdentity' -e 'const verifyWslOrcadIdentity' -e 'verifyWslOrcadIdentity =' -e 'parsePairingCode' -e 'tunneledOrcadPairingCode' src/main src
printf '%s\n' '--- connection tests ---'
sed -n '1,280p' src/main/wsl/wsl-orcad-connection.test.ts
printf '%s\n' '--- deploy tests ---'
rg -n -F --glob '*.test.ts' -e 'deployAndLaunchWslOrcad' -e 'already-running' -e 'adoptedInstance' -e 'rotated-token' -e 'runtimeId' src/main/wslRepository: stablyai/orca
Length of output: 42920
🏁 Script executed:
set -e
printf '%s\n' '--- identity implementation ---'
sed -n '1,240p' src/main/ssh/orcad-managed-tunnel-identity.ts
printf '%s\n' '--- identity restart tests ---'
sed -n '1,260p' src/main/ssh/orcad-managed-tunnel-identity-restart.test.ts
printf '%s\n' '--- readiness probe implementation ---'
rg -n -F -- 'probeManagedOrcadReadiness' src/main/ssh
sed -n '1,360p' src/main/ssh/orcad-managed-runtime-context.ts
printf '%s\n' '--- deploy implementation and active-instance behavior ---'
rg -n -F -- 'export async function deployOrcad' src/main/ssh
rg -n -F -- 'outcome: '\''already-active'\''' src/main/ssh
sed -n '1,360p' src/main/ssh/orcad-remote-deploy.ts
printf '%s\n' '--- related deploy/adoption test blocks ---'
sed -n '80,270p' src/main/wsl/wsl-orcad-deploy.test.ts
sed -n '1,220p' src/main/wsl/wsl-orcad-instance-adoption.test.tsRepository: stablyai/orca
Length of output: 37753
🏁 Script executed:
set -e
printf '%s\n' '--- activation result implementation ---'
sed -n '1,360p' src/main/ssh/orcad-installed-activation.ts
printf '%s\n' '--- wake implementation ---'
sed -n '1,300p' src/main/ssh/orcad-managed-wake.ts
printf '%s\n' '--- active readiness implementation ---'
sed -n '1,340p' src/main/ssh/orcad-active-readiness.ts
printf '%s\n' '--- relevant callers and tests ---'
rg -n -F --glob '*.ts' -e 'wakeStoppedManagedOrcad' -e 'probeActiveOrcadReadiness' -e 'outcome: '\''already-active'\''' -e 'serving' src/main/ssh src/main/wslRepository: stablyai/orca
Length of output: 42387
🏁 Script executed:
set -e
printf '%s\n' '--- update-plan action conditions ---'
rg -n -F -- 'export function planOrcadUpdate' src/main/ssh
sed -n '1,300p' src/main/ssh/orcad-update-plan.ts
printf '%s\n' '--- complete active readiness probe ---'
sed -n '75,230p' src/main/ssh/orcad-active-readiness.ts
printf '%s\n' '--- launch and port behavior ---'
rg -n -F -- 'launchAndJudgeOrcadSlot' src/main/ssh/orcad-candidate-launch-verdict.ts src/main/ssh
sed -n '1,260p' src/main/ssh/orcad-candidate-launch-verdict.tsRepository: stablyai/orca
Length of output: 17872
Verify the refreshed offer before reusing the bridge.
When an update changes the active version but keeps the same remote port, activation stops the incumbent and starts the candidate. The same-port branch then refreshes the offer without performing the pairing handshake. The previous bridge verification does not prove the identity of the replacement process.
Suggested fix
private refreshOffer(
key: string,
entry: ActiveWslOrcadConnection,
launch: Extract<WslOrcadLaunch, { outcome: 'ready' }>
- ): WslOrcadConnection {
+ ): Promise<WslOrcadConnection> {
const pairingOffer = tunneledOrcadPairingCode(launch.readiness, entry.connection.localPort)
+ const identity = await (this.dependencies.verifyIdentity ?? verifyWslOrcadIdentity)(
+ pairingOffer,
+ launch.readiness
+ )
+ if (identity.verdict === 'foreign') {
+ this.active.delete(key)
+ await entry.forward.close()
+ this.dependencies.onChange?.(entry.connection.distro, null)
+ throw new OrcadManagedIdentityError(launch.port, identity.detail)
+ }
+ if (identity.verdict === 'unreachable') {
+ console.warn(
+ `[wsl] Orca server in ${entry.connection.distro} did not answer its bridge: ${identity.detail}`
+ )
+ }
if (
pairingOffer === entry.connection.pairingOffer &&
launch.fullVersion === entry.connection.fullVersion
Stacked on #27941 (C4c, wake-path perf), which sits on #27923 and #27819 (C4, deploy and launch orcad in WSL). Do not merge.
ELI5
C4 can start Orca's server (orcad) inside a WSL distro. This change lets the desktop actually talk to that server. Every connection is carried through its own
wsl.exeprocess, just like a pipe. The desktop never opens a network connection into WSL, because WSL's localhost forwarding is unreliable for the first second after a server starts listening, and it behaves differently in each WSL networking mode. Nothing in the UI changes yet. C7 wires this up and saves it.What Changed
src/main/wsl/wsl-orcad-stdio-bridge.ts):listenWslOrcadStdioBridge(transport, { environmentId, remotePort, localPort, label })starts the mergedlistenOrcadStdioBridgelistener on127.0.0.1.wsl.exe --exec sh -ctransport.~/.orca-remote/runtimes, and the existing READY/REFUSED/NO_NODE sentinel decides what happens to the socket.src/main/wsl/wsl-orcad-connection.ts):WslOrcadConnectionManager.ensure(distro, opts)returnsWslOrcadConnection { distro, environmentId, localPort, remotePort, fullVersion, pairingOffer, close() }. It:deployAndLaunchWslOrcad, which installs, wakes, or adopts orcad (a deferral throwsWslOrcadLaunchDeferredError);ws://127.0.0.1:<localPort>with the sametunneledOrcadPairingCodethat SSH uses;verifyOrcadPairingIdentity). An answer from another runtime is refused.ensurecalls share one run.close()that arrives while a connect is still running cancels that connect.get,list,close,dispose, and anonChange(distro, connection | null)callback for C7 to save to disk.startOrcadStdioBridgeand its dependency type are now exported from the SSH provider file. SSH behavior is byte-identical.defaultWslOrcadEnvironmentId(distro)is pulled out of C4's deploy function.Why
The merged listener, bridge script, sentinel, pairing rewrite and identity check already work with any transport, so WSL reuses them as-is. The managed-tunnel manager does not: it depends on SSH targets, the SSH connection manager, and SSH resume recovery. Widening it would have meant changing SSH code paths, so a small WSL manager owns the reconnect policy instead.
Real-host finding: every WSL2 distro shares one network namespace. Another distro's orcad already held 6768 and 6769, so this one bound 6770. The bridge followed the bound port, and the identity check stops a bridge from pairing with another distro's orcad.
Linked Issue
Internal WSL-via-orcad tracker, step C5.
Visual Proof
N/A: no UI. C7 adds the surface.
Testing
Real host (win-lowspec, Windows 11, WSL 2.7.10). I used a throwaway Ubuntu 24.04 distro,
orca-c5-probe, withsystemd=falseplaced in the rootfs before its first boot (PID 1 wasinit), and a non-root user. I ran the bundled branch code withOrca.exeas Node and the daily-build orcad template. Then I pointed the installed Windowsorca.exeCLI at the rewritten code.orca status --pairing-code: reachable.orca repo add --path /home/u/repo: ok.orca terminal create --worktree path:/home/u/repo --command 'echo VIA_C5'followed byterminal read --screenshows theu@win:~/repo$prompt and theVIA_C5output line.Get-NetTCPConnectionfor the harness showed only its127.0.0.1listener.orca statuscalls: 12/12 ok in 2.7 s.wsl.exechildren (8 bridges plus the holder), so 4 were queued. Releasing 4 sockets admitted the queued ones, still 8 bridges. With everything closed, only the holder was left.wsl.exeprocesses (a launcher and its child): 6 held sockets meant 12 bridgewsl.exeprocesses and 6 bridgenodeprocesses in the guest.ensureagain (14 s). orcad came back on 6771. The local port stayed the same. The old and new pairing codes both returnedstatusok, and the terminal survived (terminal list= 1).wsl.exeprocesses on Windows and zero bridgenodeprocesses in the guest. The onlyorca-c5-probeprocesses left were the 2 detached-holder ones.wsl -l -vmatches the starting state.Automated.
wsl-orcad-stdio-bridge.test.ts: the real listener and the real WSL transport, with only thewsl.exespawn faked. Covers one child per socket, the cap of 8 with queueing and slot reuse, a refused port, and teardown.wsl-orcad-connection.test.ts: the pairing rewrite, a shared concurrent connect, bridge reuse on the same port, a rotated offer, a port move to the same local port, a deferral, a foreign identity, a close racing a connect, and teardown.pnpm tc, oxlint,check:code-quality:changed, the static-analysis ratchets, andpnpm formatall pass.src/main/{ssh,wsl,orcad,ipc}: everything passes exceptpreflight-agent-detection("does not double-count … install-dir resolver"). That test also fails when run alone, and it covers C4's install-dir code, which this PR does not touch. The other failures were timing flakes under full parallel load and pass when run alone.AI Disclosure
Review
Agent skill upstream boundary
Notes
exporton the existing transport-agnostic bridge starter.wsl.exe --execchild through process-host (buildWslExecArgs), never a shell, and never a TCP connection into the VM.onChangereports.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)