bfbb34bbec
`Start-UiServer` printed the -SelfTestUi URL (and opened the browser window) as soon as the TcpListener was bound, but the runspace that answers /progress starts asynchronously — BeginInvoke returns before the pipeline is open and the script block is JIT'd, which is seconds on a loaded runner. The kernel accepted connections into the backlog during that gap and nobody answered them. The self-test hit it three times (#90371 and two follow-ups each widened a timeout instead of removing the race) and it just failed an unrelated hermes_state.py PR (run 33591547099, two 5s stale-backlog timeouts = red). - windows.ps1: readiness handshake after BeginInvoke — one /progress round-trip must succeed (≤15s) before the server is returned; on failure tear the listener down and continue without UI. The URL now means "serving", not "bound". Also fixes the browser opening to a page that never loads on a slow machine. - test: 1s per-attempt probe timeout so a single dead backlog socket cannot consume half the readiness budget. - CI: new `desktop_updater` classifier lane. tests/test_desktop_update_windows_*.py spawn the real PowerShell script; the Windows-only job now runs them only when scripts/desktop-update/**, the Electron updater launcher, conftest, pyproject, or those tests change (push/dispatch fail open). A PR that never touched that surface cannot be failed by its process timing.