fix(cli): complete Windows cliproxy platform handling + pid probe (#11236) - #11263
Merged
diegosouzapw merged 2 commits intoAug 23, 2026
Merged
Conversation
…1236) Residuals of #11236 after #10371/#10491 landed on the tip: - Dist-fold residuals (bugs 2+3): managedBinaryName() (binaryManager), resolveSpawnArgs() (installers/cliproxy) and the per-OS memory probes in getProcessInfo() (processManager) still read the process.platform literal, which the Linux build of the published artifact constant-folds (precedent: b43a212 / #10244). Converted to call-time os.platform() reads, matching the module's documented anti-fold pattern. Test-side process.platform uses are not bundled and stay. - Fold guard: new tests/unit/windows-platform-fold-guard-11236.test.ts pins zero out-of-comment process.platform occurrences in the four artifact runtime files, with a comment-stripping tokenizer plus mutation self-checks. - Bug 6 (pid null on Windows): portProbe.resolvePortPid() only probed lsof/ss/net-tools netstat. Added a netstat -ano probe with a dedicated LISTENING-row parser (parseWindowsNetstatPid) as the last fallback; Unix probes unchanged, and the Windows parser never matches Unix rows (LISTEN vs LISTENING). Also converted the darwin args branch in the same array to os.platform() (same fold class, same hunk). - Bug 5 hardening: runOAuthStatus coerces an out-of-contract 200 payload to an empty list with a sanitized stderr warning instead of crashing on .filter over a non-array. TDD: guard test, parser tests and the oauth hardening test all failed RED before the fix and pass GREEN after; sibling suites (binaryManager, processManager, portProbePid, cli-oauth-commands, installers, ServiceSupervisor, version-manager) green. The 6877 spawn-args test's win32 mock moved from defineProperty(process.platform) to mock.method(os, "platform") to match the new runtime read — assertion unchanged.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #11236
Bugs 1, 4 and 5 of the issue are already fixed on the tip (#10371, #10491, and the combos PATCH/CLI work). This PR closes the remaining residuals validated against
release/v3.8.50.1. Dist-fold residuals (bugs 2+3 — root cause of the
.exefailures)#10371 fixed the Windows
.exename in the source, but three runtime reads of theprocess.platformliteral survived in the same paths. The published npm artifact is bundled on Linux, and the bundler constant-folds that literal to the build machine's platform, pruning the win32 branch from the shipped artifact — so installs still copied the binary as extension-lesscliproxyapiand spawn still ENOENT'd on Windows. Precedent: b43a212 (#10244/#10293), which converteddetectPlatform/detectArchfor the same fold class.Converted to call-time
os.platform()reads, matching the module's documented anti-fold pattern:src/lib/versionManager/binaryManager.ts—managedBinaryName()(install/rollback/getCurrentBinaryPath name)src/lib/services/installers/cliproxy.ts—resolveSpawnArgs()executable name (bug 3's spawn path)src/lib/versionManager/processManager.ts—getProcessInfo()per-OS memory probes (same file family, same fold class; the darwinpsbranch would be pruned on macOS)Deliberately not converted:
process.platformuses inside test files (binaryManager.test.ts,cliproxy-resolve-spawn-args-6877.test.ts) — tests are never bundled into the artifact.2. Fold guard (new test)
tests/unit/windows-platform-fold-guard-11236.test.ts— structural guard that fails ifprocess.platformreappears outside a comment in the four artifact runtime files above (plusportProbe.ts). Uses a comment-stripping tokenizer (line + block comments blanked, line numbers preserved) and ships mutation self-checks proving a code occurrence is caught while comment mentions (the fold-explanation comments reference the pattern by name) are let through.3. Bug 6 —
pid: nullon Windows while healthyresolvePortPid()(src/lib/services/portProbe.ts) only probedlsof,ssand net-toolsnetstat— none exist on a stock Windows host, so an adopted service keptpid: nullforever. Added a last-fallbacknetstat -anoprobe with a dedicated parser (parseWindowsNetstatPid) that matches TCPLISTENINGrows on the local-address column (:anchor prevents suffix false-positives like 128 vs 20128) and reads the pid from the last column. Unix probes are untouched; on Unix the Windows probe degrades to a no-op (Linux/macOS rows sayLISTEN, neverLISTENING), and on Windows the Unix probes fail fast via ENOENT/invalid-args. The darwin args branch in the same probe array was also converted toos.platform()(same fold class, same hunk).Parser unit tests use a realistic Windows 11
netstat -anosample (CRLF, IPv4/IPv6 listeners, ESTABLISHED foreign-address trap, stateless UDP row).4. Bug 5 hardening —
oauth statusout-of-contract 200bin/cli/commands/oauth.mjsrunOAuthStatus: #10491'sdata.connections ??envelope still fell through todataitself when the API returns a 200 with noconnections/providers/itemsarray (e.g.{"status":"ok"}), crashing on.filter is not a function(+ the libuv teardown assertion reported on Windows). Now guarded withArray.isArray(): coerces to an empty list and writes a sanitized one-line stderr warning — no stack trace, no throw.TDD evidence (Hard Rule #18)
RED before the fix, GREEN after:
parseWindowsNetstatPidtestsTypeError: ...filter is not a function(the exact bug 5 crash)Sibling suites green: binaryManager, processManager, extract-zip-5590, windows-hide-spawns-8131, windows-process-stop-8045, version-manager (×3), db-versionManager (72 tests), ServiceSupervisor, installers (cliproxy ×2, ninerouter, bifrost, mux), ninerouter-embed-6205, cli-process-supervisor (×2) (87 tests).
One test alignment (not masking):
cliproxy-resolve-spawn-args-6877.test.ts's win32 case mockedprocess.platformviadefineProperty, which the new runtime read no longer consults; the mock moved tomock.method(os, "platform")— the.exeassertion itself is unchanged.Checks
npm run typecheck:corecleannpx eslinton all touched files clean — the new oauth test avoidsas any(as unknown as) socli-oauth-commands.test.tsstays at its frozen suppression count of 20buildon the EndpointPageClient JSX defect; fix in review at #11256 — this PR does not touch that file)