3b08a0f9b5
Live failure on the first real use of #82328 (2026-08-09): clicking Update closed the Desktop with "an updater will happen", then nothing. desktop.log showed `launched repo hand-off script`, but desktop-update-handoff.log was never created - PowerShell exited 0 without executing a single line. Root cause, isolated by spawning the exact production shape against a sandbox HERMES_HOME: `spawn('powershell', [..., '-File', script], { detached: true, stdio: 'ignore', windowsHide: true })` kills powershell.exe during console-subsystem init, before -File processing. Variant matrix: plain pipes -> runs; hide only -> runs; detached only -> runs; detached+hide -> exits 0, script never starts. Unit tests and foreground invocations can't see this class of bug. Fix: wrapHandoffForDetachedConsole() routes the invocation through `cmd /d /s /c start "" /min powershell ...` - `start` allocates the script its own minimized console and fully detaches it; the cmd wrapper exits immediately. Verified the wrapped form survives the full detached+hidden production spawn. Knock-on: child.pid is now the short-lived wrapper, not the script, so the Electron-side marker pre-write can't represent the script. The script now claims the update marker itself as step 0 (its own $PID, byte-exact "<pid>\n<ts>\n" via WriteAllText - Set-Content emits CRLF and would break the three readers' framing). The Electron pre-write is kept as a bridge for the spawn window: the script overwrites it, and if the script never starts the wrapper's dead pid reads as stale and self-deletes (no wedge). `hermes update` adopts the script's claim via update_lock.py's process-ancestry rule, unchanged. E2E in exact production shape (cmd start wrapper, detached, hidden, parent exits 1.5s after spawn) against a sandbox HERMES_HOME with a compiled fake hermes.exe: script ran, claimed marker with its own pid (fake observed "<script-pid>|<ts>|" LF-framed DURING the update), desktop-pid wait worked, update invoked with correct argv, marker removed on completion. vitest 13/13 (new wrapper-shape test), 3-project typecheck clean, eslint clean, PS 5.1 parse + windows-footguns clean.