Summary
On Windows, a fused edit/write whose path comes from a Git Bash, MSYS, Cygwin, or WSL shell mutates one file while Action Fusion's queue and hash guard address another, so then_run is skipped with ENOENT.
resolveToolPath() handles @, file://, ~, and ~/, then calls path.resolve().
|
function stripToolPathPrefix(filePath: string): string { |
|
return filePath.startsWith("@") ? filePath.slice(1) : filePath; |
|
} |
|
|
|
export function resolveToolPath(cwd: string, filePath: string): string { |
|
const stripped = stripToolPathPrefix(filePath); |
|
// Pi accepts file URLs; the queue and hash guard must use the same target. |
|
const expanded = stripped.startsWith("file://") ? fileURLToPath(stripped) : stripped; |
|
if (expanded === "~") return homedir(); |
|
if (expanded.startsWith("~/")) return resolve(homedir(), expanded.slice(2)); |
|
return resolve(cwd, expanded); |
|
} |
Pi's resolveToCwd() does two more things on Windows, in utils/paths.js:
if (process.platform === "win32") {
normalized = normalizeWindowsShellPath(normalized); // /c/src -> C:\src
}
if (options.expandTilde ?? true) {
if (normalized.startsWith("~/") || (process.platform === "win32" && normalized.startsWith("~\\"))) {
return join(home, normalized.slice(2));
}
}
export function normalizeWindowsShellPath(filePath) {
if (!filePath.startsWith("/") || filePath.startsWith("//") || filePath.includes("\\")) return filePath;
const match = filePath.match(/^\/(?:mnt\/|cygdrive\/)?([a-z])(?:\/(.*))?$/i);
if (!match) return filePath;
const suffix = match[2]?.replaceAll("/", "\\");
return `${match[1].toUpperCase()}:\\${suffix ?? ""}`;
}
Actual behavior
For path: "/c/src/app.ts" the built-in mutation writes C:\src\app.ts, while resolveToolPath() returns a literal \c\src\app.ts for the queue slot and the assertUnchangedBeforeCommand() hash. The mutation succeeds, the guard reads a path that does not exist, and the model gets:
Error: [then_run:skipped] ENOENT: no such file or directory, open '...\c\src\app.ts'; the command was not run.
The same applies to ~\notes.txt, which Pi expands and SoL-Pi treats as a relative filename.
Scope of the claim
I do not have a Windows machine, so this is derived from Pi 0.84.2's own resolver source quoted above rather than executed on Windows. The divergence itself is checkable without a Windows runner; a confirmation on one would be welcome before merging anything.
This is the same parity class as #2 and #7, on a different input class — the file-URL fix in #4 and the Unicode-space work in #7 do not touch shell drive paths. Given #16, Windows users are running this.
Expected behavior
Action Fusion should apply the same drive-path conversion and ~\ expansion Pi's own resolver applies, so the queue and hash guard observe the file the built-in mutation tool wrote. Both should stay no-ops off Windows, so a POSIX user whose repository genuinely contains /c/src/app.ts is unaffected.
I have a fix that mirrors Pi's function, with tests that drive the platform branch explicitly.
Summary
On Windows, a fused
edit/writewhose path comes from a Git Bash, MSYS, Cygwin, or WSL shell mutates one file while Action Fusion's queue and hash guard address another, sothen_runis skipped with ENOENT.resolveToolPath()handles@,file://,~, and~/, then callspath.resolve().SoL-Pi/src/sol-pi/extensions/action-fusion/file-queue.ts
Lines 13 to 24 in d7ecfc0
Pi's
resolveToCwd()does two more things on Windows, inutils/paths.js:Actual behavior
For
path: "/c/src/app.ts"the built-in mutation writesC:\src\app.ts, whileresolveToolPath()returns a literal\c\src\app.tsfor the queue slot and theassertUnchangedBeforeCommand()hash. The mutation succeeds, the guard reads a path that does not exist, and the model gets:The same applies to
~\notes.txt, which Pi expands and SoL-Pi treats as a relative filename.Scope of the claim
I do not have a Windows machine, so this is derived from Pi 0.84.2's own resolver source quoted above rather than executed on Windows. The divergence itself is checkable without a Windows runner; a confirmation on one would be welcome before merging anything.
This is the same parity class as #2 and #7, on a different input class — the file-URL fix in #4 and the Unicode-space work in #7 do not touch shell drive paths. Given #16, Windows users are running this.
Expected behavior
Action Fusion should apply the same drive-path conversion and
~\expansion Pi's own resolver applies, so the queue and hash guard observe the file the built-in mutation tool wrote. Both should stay no-ops off Windows, so a POSIX user whose repository genuinely contains/c/src/app.tsis unaffected.I have a fix that mirrors Pi's function, with tests that drive the platform branch explicitly.