Conversation
|
Substantially expanded after receiving the reporter's full field debugging notes (Windows 11 / PowerShell 5.1 + pwsh 7.6.6 / Node 26 / mcode 0.4.12; identities sanitized). Their four findings, mapped to this PR:
New regressions reproduce the reporter's exact on-disk layout from POSIX (extensionless shim + mcode.cmd + ps1 + stale flat node_modules + releases/0.4.12): red 3/3 on the previous head, green after. Suite now 10/10 launcher tests, 92/92 plugin-wide, packaged smoke 1/1, byte-reproducible rebuild. The reporter also supplied maintainer-runnable repro commands for the PS 5.1/PS7 pair and the direct |
hetaoBackend
left a comment
There was a problem hiding this comment.
Request changes for exact current head 67980640498827fd2f7feec688127eb79e2ca4f4.
Two Windows-launcher correctness/evidence blockers remain:
-
The resolver does not follow the authoritative active release.
src/mcode-location.mjs:53-70enumerates everyreleases/*directory and chooses the numerically largest parsed package version. It never resolves a launcher/current pointer, and theparseIntcomparison does not implement SemVer or define stable-versus-prerelease/tie behavior. A retained beta/newer directory or rollback can therefore select a different CLI from the release the installed launcher would run.checks/win-launcher.check.mjs:103-112currently locks in highest-numeric-directory behavior rather than testing the active release contract. Resolve the authoritative active target, or document and implement a complete version/channel/tie policy with rollback tests. -
The Windows-specific test is not run on Windows.
checks/win-launcher.check.mjs:5-9says real Windows behavior is covered by repository CI, but.github/workflows/dynamic-workflow.yml:37-48runs onlychecks/process-tree.check.mjsin the Windows job. The launcher suite currently runs under POSIX while merely injectingplatform: win32, so it does not exercise Windows path, PATHEXT, filesystem, or spawn semantics. Runwin-launcher.check.mjsin the Windows job and preferably add an end-to-end fakecli.jsspawn with spaces and flag-shaped argv.
I confirmed the good parts: .cmd and PATHEXT probing, npm-prefix layout, separated argv with shell:false, PowerShell fallback only when no Node entry is found, source/dist sync, and the existing exact-head CI are sound. [code]smith is skipped and was not used as evidence.
…ile hop On win32, a resolved mcode.cmd currently prefers the sibling mcode.ps1 via powershell -NoProfile -File, then falls back to dirname(cmd)/node_modules. Two field failure modes on real installs (anonymized deployment report): - PowerShell 5.1 binds flag-shaped tokens (-input, --cwd, ...) as its own named parameters under -File, breaking the exec argv entirely - with the .ps1 renamed away, the fallback accepts whatever cli.js sits next to the PATH shim; when an old install (0.2.x) provides that shim while a newer official install exists, resolution silently picks the stale entry, which lacks current exec flags Resolution now prefers a directly spawnable node entry, picking the NEWEST cli.js across the candidate layouts (shim sibling, official lib/node_modules, official root node_modules) by package version; the powershell -File hop remains only as a documented last resort when no node entry exists anywhere. POSIX resolution is unchanged. checks/win-launcher.check.mjs covers the mixed-install matrix by faking the win32 layout + PATH/PATHEXT from POSIX (resolution is pure filesystem probing); real-Windows behavior is exercised by the repository's windows CI job.
…wsh first From a full field debugging report on a real Windows deployment (anonymized): - executablePath probed the empty PATHEXT extension first for bare names, resolving mcode to the extensionless POSIX shim shipped beside mcode.cmd — spawn then fails with ENOENT. Bare names now match PATHEXT variants only; commands that already carry an extension (pwsh.exe) still probe directly. - the candidate pool for the node entry now includes the staged-installer layout releases/<version>/node_modules/@minimax-ai/code/cli.js — the same entry .mcode-launcher.cmd targets. A stale flat node_modules (0.2.x) beside a current releases/<v> now loses the version comparison instead of winning by proximity. - the last-resort PowerShell hop prefers pwsh.exe (PS7): PS 5.1 binds flag-shaped argv as its own named parameters under -File and does not forward piped stdin through the nested invocation (field-verified pair)
The field-layout test probed mcode.CMD (uppercase PATHEXT) against a lowercase mcode.cmd fixture — Windows filesystems are case-insensitive so the behavior is fine in production, but the Linux CI runner simulating win32 is case-sensitive and resolution returned null. PATHEXT in the test now matches the fixture files; assertion gains an explicit non-null guard.
…ck policy - when .mcode-launcher.cmd sits beside the resolved shim, the cli.js it references is returned verbatim before any version arithmetic — whatever the installed launcher runs is what we run, so rollbacks and channel switches are followed for free (%~dp0 expanded, backslashes normalized) - without a launcher pointer, candidates rank by full SemVer with an explicit channel/tie policy documented in-source: stable globally outranks prerelease (the fallback never auto-upgrades into a prerelease channel), numeric vs alphanumeric prerelease identifiers, build metadata ignored, ties broken by directory name - end-to-end spawn fidelity test: a fake cli.js echoes its argv as JSON and the test asserts every token (spaced --cwd, flag-shaped tokens, trailing dash) survives a real node subprocess — real on whichever host runs it - 15 launcher tests; the three new policy tests fail against the previous resolver (discriminative), all prior behavior tests unchanged
6798064 to
4c9915e
Compare
|
Both blockers addressed at exact head
--- a/.github/workflows/dynamic-workflow.yml
+++ b/.github/workflows/dynamic-workflow.yml
@@ -45,4 +45,4 @@
with:
node-version: 22
- run: npm ci --ignore-scripts --registry=https://registry.npmjs.org
- - run: node --test checks/process-tree.check.mjs
+ - run: node --test checks/process-tree.check.mjs checks/win-launcher.check.mjsWe cannot push workflow files (OAuth token lacks Validation at this head: plugin suite 117/117, packaged MCP smoke 1/1, byte-reproducible rebuild, and the full 345-test repository gate on a local Ubuntu box (345/345). |
…ite in Windows CI Real-Windows evidence (fork preview, windows-latest, Node 22): running checks/win-launcher.check.mjs on a real runner surfaced a resolver bug the POSIX+win32-injected suite could never catch — fs.promises.mkdir(recursive) returns a \\?\-namespaced path on Windows, every join below keeps the prefix, and node's main resolution (realpathSync on argv[1]) dies with EISDIR lstat 'C:' (nodejs/node#62446, fixed by #65378 first in v24.21.0 / v26.8.0 — this plugin supports Node >=22, so we self-defend). loadableEntry() strips the namespace marker (drive + UNC forms) at all three node-entry return points; POSIX strings pass through unchanged. dist regenerated in lockstep. The Windows job now runs the launcher suite next to process-tree.check.mjs, closing the second review blocker.
|
Windows CI wiring + a real-Windows resolver fix, at exact head 1. Blocker 2 closed — the Windows job now runs the launcher suite. 2. Running the suite on a real runner surfaced a bug the POSIX+win32-injected suite structurally cannot catch — fixed in the same head. On windows-latest (Node 22) the end-to-end argv-fidelity case died inside node's own main resolution: Evidence trail (fork-side preview mirrors, windows-latest / Node 22): diagnosis run 35491670398 (14/15, EISDIR), ENTRY-instrumented run 35492809510 (captured the namespaced entry verbatim), fixed run 35493004045 — 16/16 pass, 0 fail (one new unit test for The Windows check on this PR should now reproduce the green directly. |
hetaoBackend
left a comment
There was a problem hiding this comment.
Approved exact head e3d016661df26d523ab9fde67d0daf34a6262bb1. The resolver now follows the authoritative active release from .mcode-launcher.cmd before fallback scanning, and its no-pointer fallback implements an explicit stable/prerelease SemVer and tie policy with rollback/channel tests. The Windows job now runs the launcher suite on a real runner; namespace-path normalization, PATHEXT/extensionless-shim selection, direct trusted cli.js execution, argv fidelity, PowerShell last-resort behavior, and source/dist consistency are covered. Exact-head Ubuntu, Windows, package, and CodeQL checks are green. [code]smith is skipped and was not used as evidence.
What changes
Fixes Windows mcode launcher resolution in
mcode-location.mjs— two failure modes observed on a real Windows deployment (details anonymized; a user's debugging session was shared with us verbatim):-Filehop. A resolvedmcode.cmdwith a siblingmcode.ps1is invoked aspowershell -NoProfile -File mcode.ps1 exec --input - --cwd .... Under-File, PowerShell binds flag-shaped tokens (-input,--cwd,--timeout …) as its own named parameters, so the exec argv never reaches the CLI — parameter-binding errors on every invocation. (The user's attempted--%stop-parsing cannot help: it affects interactive command lines, not-Fileargument passing.).ps1renamed away (the user's workaround), resolution falls back todirname(mcode.cmd)/node_modules/@minimax-ai/code/cli.js— the npm-global layout, whichever version sits there. On a machine with an old install (0.2.x, missing current exec flags) providing the PATH shim while a newer official install exists, resolution silently picked the 0.2.x entry and every exec call died on an unknown flag. The user eventually junction-linked the newcli.jsinto the expected path — a workaround this PR makes unnecessary.The fix
.ps1hop: collect candidatecli.jslocations (shim siblingnode_modules, officiallib/node_modules, official rootnode_modules) and pick the newest by package version — mixed installs resolve to the freshest CLI regardless of which install owns the PATH shim.powershell -Filehop remains only as a documented last resort when no node entry exists in any layout.Test evidence
checks/win-launcher.check.mjs(7 tests): the mixed-install matrix is reproduced from POSIX by faking the win32 on-disk layout and passingplatform:'win32'+ controlledPATH/PATHEXT(resolution is pure filesystem probing): ps1-present-with-old-sibling + newer official → direct node entry of the newest; ps1 renamed + stale sibling → newest official, never the stale one; newest-wins regardless of origin; single npm layout; ps1 last resort preserved (with-NoProfile,-File,<launcher>argv pinned); no-entry error message preserved; POSIX unchanged.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.