fix(windows): refresh PATH ordering for newly installed tools - #13545
fix(windows): refresh PATH ordering for newly installed tools#13545OrcaWin wants to merge 3 commits into
Conversation
New terminals now preserve Orca-injected entries while adopting current machine and user PATH precedence, so newly installed tools are not shadowed by stale aliases. Invalidate the cached registry snapshot on Windows setting changes and guard in-flight refreshes from restoring stale cache data.
|
Warning Review limit reached
Next review available in: 4 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe change adds generation-based invalidation for the persisted Windows PATH cache and prevents stale asynchronous refreshes from repopulating it. PATH merging now normalizes, deduplicates, and orders injected and persisted entries. A Windows setting-change listener invalidates the cache on 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Native Windows low-spec evidenceFinal commit The capture is uncropped and shows the branch/workspace context, real terminal surface, exact final commit, executable ordering, version output, and PASS verdict. |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: d6d1ce58-b617-4507-a5aa-aee2721f3753
📒 Files selected for processing (2)
src/main/pty/windows-environment-path.test.tssrc/main/pty/windows-environment-path.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/main/pty/windows-environment-path.test.ts
| if (cacheGeneration !== persistedWindowsPathCacheGeneration) { | ||
| // Why: callers must not merge or inspect a snapshot invalidated while its queries ran. | ||
| return readPersistedWindowsPathSegmentsAsync({ forceRefresh: true }) | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
Prevent the retry from awaiting its own promise.
When the generation changes, Line 222 starts a forced refresh while pendingPersistedWindowsPathRefresh still references the current refresh promise. The pending-refresh check at Line 202 does not exclude forceRefresh, so the retry awaits its parent promise and never resolves.
Add !options.forceRefresh to the pending-refresh guard, or replace the pending promise before retrying. Add a regression test for invalidation during an active registry read.
Suggested fix
- if (useProductionCache && pendingPersistedWindowsPathRefresh) {
+ if (!options.forceRefresh && useProductionCache && pendingPersistedWindowsPathRefresh) {🧰 Tools
🪛 ast-grep (0.45.0)
[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execFile, execFileSync } from 'node:child_process'
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(detect-child-process-typescript)
Windows Electron QA — STA-3175 / PR #13545Verdict: PASS on native Windows low-spec host Identity
User-visible PATH refresh / precedence (new Orca
|



Summary
Fixes #11992. Related to #12050; this branch reproduces the failure on current
mainand revalidates the fix on native Windows.New Windows terminals inherited Orca's launch-time PATH and only appended missing persisted entries. Because executable lookup is first-match-wins, a stale
WindowsAppsalias stayed ahead of Python installed while Orca was running.This change:
WM_SETTINGCHANGE, with a generation guard so an in-flight read cannot restore stale data.Screenshots
Final commit
8dc9c3f665was launched on Windows Low with the inheritedC:\Python314entries deliberately removed while the live registry retained the post-install order. CDP identity matched this worktree, and the rendered terminal plus main-owned PTY buffer both reported Python at PATH index 15,WindowsAppsat index 30,Get-Command pythonresolving toC:\Python314\python.exe, andPython 3.14.6.Testing
pnpm run typecheck:nodepnpm test— the focused and affected suites below passed; the full matrix is running in CI.pnpm build— local Electron dev build passed; release packaging is covered by CI.Results:
WindowsAppsindex 2.windows-environment-path.test.ts+windows-path-registry-change.test.ts: 28/28 passed on the final rebased commit.oxlint --deny-warnings: passed.pnpm run check:max-lines-ratchet: passed with no new bypasses.AI Review Report
Security Audit
reg.exe querycalls and timeouts are unchanged.Notes
WM_SETTINGCHANGEbroadcast was not synthesized during validation to avoid changing registry or system-wide state. Listener installation, invalidation, and the in-flight race are covered deterministically in tests.ERR_INSUFFICIENT_RESOURCESwhile several unrelated dev servers were active. The final-commit run rendered without that error and passed end to end.