Summary
The CLI test suite is POSIX-only in three independent ways, and the sharpest consequence is not "tests fail on Windows" — it is that eight tests silently bypass their own gh stub and call the real GitHub API from the developer's machine.
Run context: Windows 11, Node 22.23.2, pnpm 11.20.0 (stable, no flags), clean main, pnpm install --frozen-lockfile green. node --test test/*.test.mjs in packages/cli: 86 pass / 11 fail.
Failure class 1 — the gh stub never engages (8 tests, the important one)
test/delivery.test.mjs and test/doctor-policy.test.mjs stub gh by writing an extensionless shell script, chmod 0o755, and prepending the fixture dir to PATH joined with a hard-coded colon:
// delivery.test.mjs:149
PATH: `${fixture.dir}:${process.env.PATH}`,
// delivery.test.mjs:140, doctor-policy.test.mjs:421
chmodSync(ghPath, 0o755);
On Windows the PATH delimiter is ;, so the whole variable is corrupted rather than prepended — and even with the right delimiter, an extensionless script is not executable there. The child process therefore resolves the real gh, and the tests fire live requests:
gh: Not Found (HTTP 404)
Error: Command failed: gh api repos/acme/demo/pulls/7
Five delivery-verifier tests and the three resolver tests fail this way — including the one named "resolver integrates with deterministic GitHub fixtures", which on this platform is hitting api.github.com. If a repo named acme/demo existed with a permissive API surface, these tests would read from it. A unit suite whose stub failure mode is "talk to production GitHub with the developer's credentials" is worth closing on any platform.
Failure class 2 — POSIX permission assertions (2 tests)
login verifies /v1/me and writes config with 0600 permissions and profiles can be listed and switched assert mode 0600; NTFS has no POSIX modes, so the assertion can never hold on Windows.
Failure class 3 — the .agents/skills symlink (1 test)
init installs the method end to end dies on ENOENT … .agents\skills — this is the product-side bug already filed as #230 showing up in the suite; listed here only for completeness of the 11.
Suggested fix (small, mechanical)
- Join PATH with
path.delimiter, not ":".
- Write the stub as
gh.cmd on Windows (or use a tiny .mjs invoked via a gh.cmd/gh pair) — the fixture helper can emit both in one place since both test files share the pattern.
- Guard the
0600 assertions with process.platform !== "win32" (or assert via fs.stat only where modes are meaningful).
- Optionally the deeper safety: have the stub tests set
GH_HOST/GH_TOKEN to an invalid value so that if the stub ever fails to engage again, the suite fails fast offline instead of reaching the real API.
Happy to send the PR — I have the failing Windows environment live for verification, and it complements the Windows arc already in flight (#182, #230, #240).
Summary
The CLI test suite is POSIX-only in three independent ways, and the sharpest consequence is not "tests fail on Windows" — it is that eight tests silently bypass their own
ghstub and call the real GitHub API from the developer's machine.Run context: Windows 11, Node 22.23.2, pnpm 11.20.0 (stable, no flags), clean
main,pnpm install --frozen-lockfilegreen.node --test test/*.test.mjsinpackages/cli: 86 pass / 11 fail.Failure class 1 — the
ghstub never engages (8 tests, the important one)test/delivery.test.mjsandtest/doctor-policy.test.mjsstubghby writing an extensionless shell script,chmod 0o755, and prepending the fixture dir to PATH joined with a hard-coded colon:On Windows the PATH delimiter is
;, so the whole variable is corrupted rather than prepended — and even with the right delimiter, an extensionless script is not executable there. The child process therefore resolves the realgh, and the tests fire live requests:Five delivery-verifier tests and the three resolver tests fail this way — including the one named "resolver integrates with deterministic GitHub fixtures", which on this platform is hitting api.github.com. If a repo named
acme/demoexisted with a permissive API surface, these tests would read from it. A unit suite whose stub failure mode is "talk to production GitHub with the developer's credentials" is worth closing on any platform.Failure class 2 — POSIX permission assertions (2 tests)
login verifies /v1/me and writes config with 0600 permissionsandprofiles can be listed and switchedassert mode0600; NTFS has no POSIX modes, so the assertion can never hold on Windows.Failure class 3 — the
.agents/skillssymlink (1 test)init installs the method end to enddies onENOENT … .agents\skills— this is the product-side bug already filed as #230 showing up in the suite; listed here only for completeness of the 11.Suggested fix (small, mechanical)
path.delimiter, not":".gh.cmdon Windows (or use a tiny.mjsinvoked via agh.cmd/ghpair) — the fixture helper can emit both in one place since both test files share the pattern.0600assertions withprocess.platform !== "win32"(or assert viafs.statonly where modes are meaningful).GH_HOST/GH_TOKENto an invalid value so that if the stub ever fails to engage again, the suite fails fast offline instead of reaching the real API.Happy to send the PR — I have the failing Windows environment live for verification, and it complements the Windows arc already in flight (#182, #230, #240).