[Bug]: Windows SSH device-host startup prints JSON but never closes SSH#24367
On native Windows 11 with Windows OpenSSH, the SSH device-host start / agent-start bootstrap prints its response but SSH does not return. T3 waits for its 1,300-second startup timeout, leaving device_list / device_open waiting. probe returns normally.
Observed on 0.1.3-nightly.20261023.3579. Field report: https://github.com/pingdotgg/t3code/pull/18172#issuecomment-6381659534
Reproduction and cause
Run remoteDeviceScript(uniqueOwner, 'start') from apps/server/src/device/sshDeviceScript.ts through Windows OpenSSH and Git Bash with Node 22+ and Android platform tools available. Use an isolated owner directory. The detached hub starts, health checks succeed and the script prints JSON, but the SSH session remains open. agent-start also creates an agent-device daemon.
A live minimal reproduction on Windows 11 / Node 24 created a detached Node child with stdio: ['ignore', logFd, logFd] and unref(), then printed JSON. SSH still had not returned after 10 seconds. Stopping only that recorded child immediately released SSH (exit 0). The long-lived child retains inheritable session pipe handles even though its configured stdout/stderr point at files. unref() only releases the parent's event-loop reference.
Intended behavior and focused fix
start and agent-start should return their existing JSON response and close SSH once the hub/daemon is ready, while those services continue running. Break Windows handle inheritance before creating long-lived processes; preserve the existing environment, owner isolation, readiness checks and error reporting. Keep macOS/Linux behavior unchanged.
Implementation/verification plan: reproduce both generated-script modes with unique owners, isolate Windows startup from the SSH pipe handles using the native process launcher, add focused generated-script regression tests, run the adjacent device-host tests and changed-file checks, then repeat the live Windows scripts and clean up only their recorded processes/state.
This report concerns the bootstrap lifetime only. Missing ps, SDK discovery, the WSL adb port conflict and the shell/npm transport fixes in #18172 are separate problems. The live reproduction may use existing npm/ps shims and an explicit SDK/adb port to isolate this failure; any such prerequisites will be disclosed in the fix PR.