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>
|
Kevin takeover: the prepared work is published across Bun #1970 → Windows #1982 → Windows2 #1994. This PR is at Full handoff, evidence limits and remaining plan/TODO. Native repair/hardening CI and newer-main integration remain to be verified; this is not a full-stack readiness claim. No further fix rounds are running. |

Kevin handoff — Windows2 published, validation remains
Published head
e1ebab8d389c60283c58f9e6aa7c2675efe5cd41, treef946db82b2600cd185380ad1f586af79cf4c715c. Ordinary merge parents: the previously local Windows2 work4396b2fdand published Windows repair9282f0e8. Review order remains #1970 → #1982 → #1994. This is a handoff, not a merge-ready claim.Current residual scope
The cleanup removes duplicated production fixes already covered by the integrated main/Windows parent. The retained residual is 21 files: five production files, fourteen test files, CI and a changelog fragment. All 20 non-CI residual files and their patch are byte-identical to the prepared Windows2 version; CI combines the existing Windows2 checks with the updated parent.
shellPath..cmd/.batoverrides remain rejected. Earlier proposed batch-shim support and duplicate persistence/display implementations are not current residual features.Validation and limitations
1.4.0+34cbb9a40, 1,008 files, no automatic fixes; types, installer rendering and browser smoke passed. The inherited informationalnoUselessStringRawremains unchanged. Localpwshparsing is unavailable.f812bdf3NUL startup/installer/native-build results are not proof that those repairs or this Windows2 combination pass. Arm64 has only cross-compilation/PE-inspection evidence, not native execution.Kevin's remaining plan
UNKNOWNmergeability.bf8894afa55832f7cfa2094c8a0d041bc680a691; snapshot4ec05a0969825a32261ffed43ab5740071a73ae6includes fix(ai): build from the committed model catalog instead of refetching it #2038 committed-catalog builds, fix(coding-agent): always render inactive sessions in the agents view #2091 inactive agents view and default prime inference to glm 5.3 #2123 GLM 5.3 default. These were deliberately left for takeover.Refs RES-1268.
Historical description and old-source validation — superseded scope, not current-head proof
The original description below includes implementations later deduplicated or withdrawn. Use the current residual scope above, particularly for CPython batch-shim behavior.
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
Changes RLM/kernel temp layout and daemon env inheritance on all platforms, and Windows now errors instead of picking bash from PATH—both need careful rollout despite broad new tests.
Overview
Adds session-owned scratch directories for persisted sessions (
artifactDir/tmp), exposes them to the kernel viaPRIME_AGENT_SESSION_TMPand standard temp env vars, and documents them in the system prompt—while pinning daemon socket dir/endpoint to inherited defaults so nested scratch hosts do not relocate worker IPC.Daemon runtime paths now honor
PRIME_AGENT_INTERNAL_DAEMON_SOCKET_DIRand the supervisor socket env (with absolute-path validation and normalization), and worker stop only clearsworker.clientif it is still the client that was shut down, avoiding races on disconnect or replacement.On Windows, automatic shell selection is limited to Git Bash under standard Program Files locations—PATH fallback for Cygwin/MSYS2/WSL is removed; nonstandard installs must set
shellPath. CI gains isolated/long-timeout Windows runs for scratch isolation, RLM deletion races, and a full supervisor→worker named-pipe lifecycle test, plus coverage for settings atomic writes, session-lease EPERM handling, and bootstrap lock reclaim/wait behavior.Reviewed by Cursor Bugbot for commit e1ebab8. Bugbot is set up for automated code reviews on this repo. Configure here.