Resolve the entry-point path so the CLI is not a silent no-op - #104
Merged
portdeveloper merged 1 commit intoSep 22, 2026
Merged
Conversation
The guard compared a percent-encoded URL pathname against a raw argv path, so it never matched on Windows, on a path holding a space, or through a symlink, and every side effect in the script sits behind it.
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 #102
The entry-point guard compared
new URL(import.meta.url).pathnameagainstprocess.argv[1]. A URL pathname is percent-encoded and always POSIX-shaped, while argv holds the raw platform path, so the two only agree on a plain POSIX path with no spaces. They disagree on a path containing a space (%20on one side, a literal space on the other), when the script is reached through a symlink (Node resolvesimport.meta.urlto the realpath, argv keeps the link), and on every Windows checkout (/C:/…againstC:\…). Since the whole CLI sits insideif (isEntryPoint), a mismatch madenpm run fetch-modelprint nothing, create nomodels/directory and exit 0.The guard now compares resolved filesystem paths:
fileURLToPathdecodes the escape and emits a native path on Windows,realpathSynccollapses the symlink, and theBooleanguard keepsnode -eand the REPL — whereargv[1]is undefined — from throwing insiderealpathSync. This is the formsrc/mcp.mjs,src/policy.mjsandsrc/addressBook.mjsalready use;fetch-model.mjswas the last one on the URL comparison. Importing the module still leaves the guard false, which the rest of the suite depends on.GGUFDownloader, the resume logic and the MD5 check are untouched.Three tests in
test/fetch-model.test.mjs, all spawning the script for real because the mismatch is invisible to an in-process import:node:builtins, so a copy runs standalone, and this reproduces on POSIX exactly what Windows does;EPERM, for Windows without developer mode).Tested:
node --test test/fetch-model.test.mjs— 27 pass, 0 fail. Against the guard as it stands on main the space and symlink tests fail, and the missing-URL test is the one that turns windows-latest red on the matrixci.ymlalready runs; I checked both directions by putting the old guard back and restoring it. The rest of the suite is unchanged by this PR — the 16 unrelated failures in my sandbox areERR_MODULE_NOT_FOUND: ethers, identical with and without the change, since I did not runnpm installfor the QVAC prebuild.