v1.1.1
Canonical source: 8c29f5d; Canonical dist/commitlore.mjs SHA-256: 96141692eaeff0d8a711fe5e54c2d26dadf9c96045847db2d8e65ed245cee62f
1.1.0 said plainly that host wiring did not work on Windows. Every host that failed for a defect in this project now wires on a real machine: Codex, Gemini CLI and Hermes.
What was fixed
A command could not be found, and could not be run.
hasCommand joined each PATH entry with the bare command name and stopped there, never consulting PATHEXT. Windows installs cursor.cmd, codex.cmd, claude.cmd — there is no extensionless file — so detection was false for every host whose executable is a shim, and claude-code reported notDetected with its config sitting on disk. Separately, spawnSync ran with shell: false, which cannot execute a .cmd shim at all; that produced codex mcp add failed.
Resolution now finds one concrete executable through PATHEXT, and both detection and execution use it. The original defect was those two disagreeing about what "present" means; they are now the same function and can no longer differ. A batch shim is invoked through an explicit cmd.exe argument vector with shell: false preserved — the wrapper path and user config paths reach these calls, and a shell would make quoting an attack surface.
What is still reported failed
ok is still false on that machine, and it should be.
.cursor/mcp.jsonwas zero bytes. That is a user file, not a defect here — the installer read the file it says it reads and reported the true reason, sinceUnexpected end of JSON inputis what parsing an empty string produces. It now names the file in that message, so the next reader does not have to establish which of Cursor's config locations was meant.windsurf,opencodeandclaude-codewerenotDetected. The first two were genuinely absent.claude-codehad a config file but no executable, and detection for it is executable-based; whether that asymmetry is right is open (#728).
Observed
Windows 10.0.19045.0, PowerShell 5.1.19041.6456, with agents installed:
codex custom-preserved healthy plugin installed
gemini-cli custom-preserved healthy
hermes installed healthy Hermes setup verified
cursor failed C:\Users\u\.cursor\mcp.json is not parseable JSON
Registrations verified through a live MCP Initialize and read back from the configs on disk.
CI cannot establish any of that: a GitHub runner has no coding agents, so every host short-circuits at detection and the Windows job prints "hosts":[] on every run. #722 is the plan to stop that being true.
Two repairs that came from review rather than from the machine
A trailing backslash — which every Windows directory path can carry — reached the cmd.exe argument vector unescaped. The closing quote consumes it and the following argument is absorbed, so a --verify passed that way would vanish and the step would report verified for a verification that never ran. That is the exact failure this project exists to remove, arriving inside the fix for it — and it was not hypothetical: --data-root ends with a backslash on Windows, so this was the argument that broke, and repairing it is what made Hermes work.
Executable resolution now checks X_OK. Without it, a non-executable file of the same name earlier on PATH is selected and spawned — a regression on macOS and Linux, where host wiring already worked. It is guarded by a test that places a mode-0644 shadow ahead of a mode-0755 CLI and runs on POSIX, because every fixture in that suite had been executable and nothing could have failed on it.
A failed host now says why
The Hermes step ran with stdio: 'ignore', so whatever it printed about its own failure was discarded and the report was a bare Hermes setup failed. The reason now reaches the summary. That mattered while Hermes was still failing; the trailing-backslash repair turned out to be its cause, so the message it would have carried is one nobody has to read — but the next failure of any host arrives with its reason attached instead of requiring another trip to the machine.
A literal % in a path is legal on Windows and is handled rather than refused; the reason %% escaping is not the answer is recorded in the code beside it.
Full notes: CHANGELOG.md. Upgrade from 1.1.0 is a drop-in; nothing about capture, policy or records changed.