diff --git a/src/resources/extensions/gsd/auto-worktree.ts b/src/resources/extensions/gsd/auto-worktree.ts index 0ff06f4bf..742c75677 100644 --- a/src/resources/extensions/gsd/auto-worktree.ts +++ b/src/resources/extensions/gsd/auto-worktree.ts @@ -1137,6 +1137,7 @@ function copyPlanningArtifacts(srcBase: string, wtPath: string): void { const srcGsd = join(srcBase, ".gsd"); const dstGsd = join(wtPath, ".gsd"); if (!existsSync(srcGsd)) return; + if (isSamePath(srcGsd, dstGsd)) return; // Copy milestones/ directory (planning files, roadmaps, plans, research) safeCopyRecursive(join(srcGsd, "milestones"), join(dstGsd, "milestones"), { @@ -2020,4 +2021,3 @@ export function mergeMilestoneToMain( return { commitMessage, pushed, prCreated, codeFilesChanged }; } - diff --git a/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts b/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts new file mode 100644 index 000000000..6a73fef13 --- /dev/null +++ b/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts @@ -0,0 +1,21 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { join } from "node:path"; + +test("copyPlanningArtifacts skips when source and destination .gsd resolve to the same path", () => { + const srcPath = join(import.meta.dirname, "..", "auto-worktree.ts"); + const src = readFileSync(srcPath, "utf-8"); + + const fnIdx = src.indexOf("function copyPlanningArtifacts"); + assert.ok(fnIdx !== -1, "copyPlanningArtifacts function exists"); + + const fnBody = src.slice(fnIdx, fnIdx + 2400); + + const guardIdx = fnBody.indexOf("if (isSamePath(srcGsd, dstGsd)) return;"); + const copyIdx = fnBody.indexOf("safeCopyRecursive(join(srcGsd, \"milestones\")"); + + assert.ok(guardIdx !== -1, "copyPlanningArtifacts should guard same-path .gsd copies"); + assert.ok(copyIdx !== -1, "copyPlanningArtifacts should still copy milestones when paths differ"); + assert.ok(guardIdx < copyIdx, "same-path guard should run before any copy attempt"); +});