fix: harden native Windows runtime - #1994
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bde87f1. Configure here.
|
Fixed the native Windows shutdown failure in Validation:
The failing Windows log is from https://github.com/PrimeIntellect-ai/prime-agent/actions/runs/34067874964/job/101579752358. Fresh native Windows validation is required on the new head. No installer, shell-discovery, or protocol changes were made. |
|
Native Windows passed on current head Verified in the hosted log:
This is native Windows x64 execution; Windows Arm64 is cross-compilation and PE inspection only. All current functional CI and both review bots have passed. JavaScript/TypeScript CodeQL is still running; final readiness is not yet claimed. |
|
Final stack readiness audit passed.
JavaScript/TypeScript CodeQL has completed successfully. Current-head native Windows, both review bots, root checks, isolated Docker behavioral tests, and all 19 process-stress tests passed. Full review threads, review summaries, and issue comments were audited; no unresolved actionable findings remain. Design-conflicting shell-discovery advice was rejected with the trust-boundary rationale rather than reverted. Fresh fetch confirms current Only human approval remains. No PR was merged. Automated monitoring is being stopped. |
Import selective Bun-independent fixes from #1994 at ce2d04f, relative to declared #1982 base 9680ac3. Preserve #2036 Windows seams and current Node runtime. Keep Bun, installer, shell-policy rollout, scratch directories, and CPython batch overrides outside this consolidation. #1994 remains partial. Atomic writer and bootstrap-lock overlap awaits canonical #2035 reconciliation after parent stacks land.
* fix(coding-agent): resolve the kernel venv python under Scripts on win32 uv creates <venv>/Scripts/python.exe on Windows, but both bootstrap sites joined <venv>/bin/python unconditionally, so first-run kernel bootstrap always failed on native Windows. Mirror the existing win32 uv.exe branch with one kernelVenvPython helper used at both sites. * fix(coding-agent): expand ~/ with the platform path separator Tilde expansion concatenated homedir() with the posix remainder at three sites (expandPath, expandTildePath, and an inline PI_PACKAGE_DIR copy), producing mixed-separator paths like C:\Users\u/rest on Windows. Join through the platform path module instead and route PI_PACKAGE_DIR through expandTildePath. * fix(coding-agent): prefer non-System32 bash over the WSL trampoline on PATH findBashOnPath took the first where-match, and System32\bash.exe (the WSL launcher, which executes Linux-side) precedes per-user Git Bash installs on default PATHs. Order matches so %SystemRoot% entries are only a last resort. * fix(coding-agent): dial the Herdr socket inside the named-pipe namespace on win32 The built-in Herdr reporter connected to the exported unix-style socket path verbatim; on Windows a local-domain connection must target \\.\pipe\, and the reporter swallows connect errors by design, so the mismatch was invisible. Map unmapped paths into the pipe namespace before dialing. * fix(coding-agent): cache the win32 process start id per pid for a short TTL getWindowsProcessStartId spawns a synchronous powershell query that blocks the event loop, and supervisor liveness checks plus daemon-ps poll loops call it repeatedly for the same pid. Memoize successful ids for 5s so hot paths reuse one query. * fix(coding-agent): derive handshake budgets from the outer connect deadline connectWorker granted every hello/worker_auth attempt a fixed 1s clock, so a handshake that consistently needs longer (slow win32 boxes) failed every retry regardless of the 30s outer budget, and the adopt/recover paths shrank even the outer budget to 1.5-2s. Per-attempt waits now consume the remaining outer deadline, all connectWorker callers use the one 30s constant, and the downward 1s hello/auth overrides in daemon-mode and the routed client fall back to the client defaults. * fix(coding-agent): route background spawns through hidden-window wrappers windowsHide defaults to false, so console-subsystem children of a windowless daemon or detached worker allocate a fresh console and flash or steal focus on every spawn; only one call site in the repo set the flag. Add spawnHidden/spawnSyncHidden/execSyncHidden/execFileHidden/ execFileSyncHidden to utils/child-process.ts and migrate all 49 non-interactive coding-agent spawn/exec sites; the tui package's two background spawns set windowsHide inline. Interactive spawns (editors, inherit-stdio installers and relaunches) intentionally keep their console. * chore(coding-agent): add windows-seams changelog fragments; tighten new comments * test(coding-agent): align clipboard and login-dialog spawn assertions with hidden-window wrappers * revert(coding-agent): drop the win32 start-id TTL cache The per-pid cache could hand a recycled pid the dead process's start id for up to 5s. The start id exists solely to detect pid recycling, and its consumers act on that identity: the orphan-process journal decides taskkill /T from it and daemon-ps shutdown waits poll it for change, so a stale match can kill a replacement process tree or mask an exited owner. No caller is both hot and staleness-tolerant; the handshake latency issue is already addressed by deriving budgets from the outer deadline. * fix(coding-agent): match Herdr pipe-namespace prefixes case-insensitively Windows pipe names are case-insensitive, but the pass-through check was case-sensitive, so a valid \\.\PIPE\... target was re-joined into a different pipe name and the error-swallowing reporter failed silently. Lowercase only the prefix check; the returned path keeps its casing. * refactor(coding-agent): tighten windows-seam comments and consolidate pins Collapse the wrapper doc block to one line, drop test comments that restate assertions, share one recording wrapper in the child-process mock, unwrap single-test describes, and remove one posix assertion already covered by its sibling. No behavior coverage removed; all pins keep their failing assertions. * fix(coding-agent,tui): harden current-runtime Windows sessions Import selective Bun-independent fixes from #1994 at ce2d04f, relative to declared #1982 base 9680ac3. Preserve #2036 Windows seams and current Node runtime. Keep Bun, installer, shell-policy rollout, scratch directories, and CPython batch overrides outside this consolidation. #1994 remains partial. Atomic writer and bootstrap-lock overlap awaits canonical #2035 reconciliation after parent stacks land. * fix(coding-agent): normalize Windows bash candidate paths --------- Co-authored-by: Seth <seth@primeintellect.ai>

Summary
This PR hardens native Windows support after #1982. It keeps Git Bash as the default shell and does not use WSL.
.cmdand.batshims through a controlledcmd.execommand string with exact metacharacter testsshellPathPRIME_AGENT_SESSION_TMP,TMP,TEMP, andTMPDIRSafety boundaries
PATHshell: trueipykernelLocal validation
~/.bun/bin/bun run checkgit diff --checkNative Windows validation
Final run: https://github.com/PrimeIntellect-ai/prime-agent/actions/runs/33650350794
D:\a\_temp\Prime Agent ø\kernel-venv: 19 passed, 2 skipped0x86640xAA640.9.1, update, and uninstall: passedpi.exe --version(0.9.1) andpi.exe --help: passedStack
Base:
feat/windows-supportfrom #1982. This PR does not modify #1982 and should be reviewed after it.Current stack integration
Ordinary merges include the updated Windows-support base. The daemon launch resolution retains launcher-aware subprocesses and
windowsHide. Root checks passed. Isolated Linux Docker validation passed 445 targeted tests and 19 process stress tests, with one Windows-only case deferred to the native runner. Native Windows CI is rerunning on the updated head.Related tracking: RES-1268 covers the overlapping Windows runtime and kernel compatibility work.
Note
Harden Windows runtime: bootstrap locks, shell selection, batch shims, and rename retries
acquireBootstrapLockto atomically publish UUID-named candidate directories, reclaim stale locks through a proper-lockfile guard, and return an idempotent release that only removes a lock still owned by the current processacquireSessionLeaseto fail closed on unreadable or corrupt owner files, retry candidate-vanishing races, and quarantine stale lease directories before deletion.cmd/.batPython shims throughcmd.exewith arguments passed via validated environment variables, rejecting unsafe metacharactersEBUSY/EPERM/EACCESrename failures across bootstrap locks, session leases, settings writes, and RLM display entriesPRIME_AGENT_SESSION_TMP,TMP,TEMP,TMPDIR) and system prompt guidancetui.StdinBufferso embedded-newline input without escape characters emits as a single paste eventgetShellConfignow throws on Windows when no Git Bash is found in standard locations, where it previously fell back to PATH-resolved bash; users with non-standard Git Bash installs must set an explicit shell pathMacroscope summarized 9063904.
Note
Medium Risk
Touches session leases, bootstrap locking, daemon worker handshakes, and RLM deletion persistence with behavior changes (fail-closed lease reads, stricter process liveness) that affect reliability on all platforms, not only Windows.
Overview
This PR extends native Windows support with runtime and durability fixes across the daemon, kernel bootstrap, session locking, and RLM lifecycle—without adding WSL/Cygwin/MSYS2 fallbacks from
PATH.Daemon and workers: Detached spawns set
windowsHideon Windows so background daemons, workers, and catalog/update processes do not flash consoles. Worker connect uses longer budgets and exponential backoff on win32 (90s handshake, larger per-probe timeouts);createrequests get a 120s default timeout on Windows only. Supervisor shutdown avoids clearing a replacement worker client if disconnect races shutdown.Persistence and races: Settings saves use atomic temp+rename with Windows rename retries; session leases fail closed on corrupt
owner.json, treat only ESRCH as a dead PID, and classify Windows rename contention when reclaiming. Kernel bootstrap locks are rebuilt (candidate rename, stale quarantine,proper-lockfileguard, transient rename retries). RLM display files retry Windows sharing violations, honor deletion tombstones (writers returnfalseinstead of resurrecting state), and deletion retries emit one failure notice per attempt.Kernel/shell paths: Windows runs
.cmd/.batshims viacmd.exewith env-based argument passing andPYTHONUTF8=1for venv/REPL; executable lookup respectsPATHEXT. Default shell selection uses canonical Git for Windows paths only (explicitshellPathotherwise). Tilde expansion accepts~\on Windows; persisted sessions get a scratchtmpdir wired into kernel env and the system prompt.UX/integration: Herdr state reporting maps socket paths to named pipes on Windows; frontmatter strips a UTF-8 BOM; TUI
StdinBuffertreats raw multiline chunks as paste when bracketed paste is absent. CI adds a broad Windows behavior suite including named-pipe lifecycle and RLM race tests.Reviewed by Cursor Bugbot for commit 9063904. Bugbot is set up for automated code reviews on this repo. Configure here.