From c58bf4233360aba0ce28991e4daea6df38a9b93a Mon Sep 17 00:00:00 2001 From: HyperDev1 Date: Fri, 20 Mar 2026 01:54:19 +0300 Subject: [PATCH] fix: create milestones/ directory in worktree when missing (#1374) syncGsdStateToWorktree() assumed the milestones/ directory already existed in the worktree. On a fresh worktree bootstrap this directory is absent, causing milestone sync to silently skip all entries and auto-mode to report "All milestones complete" immediately. Create the directory before iterating if the main repo has milestones but the worktree does not. Co-authored-by: Berat Can Co-authored-by: Claude Opus 4.6 (1M context) --- .../tests/worktree-sync-milestones.test.ts | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts b/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts index bb2f4288f..40fb064c8 100644 --- a/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +++ b/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts @@ -148,6 +148,37 @@ async function main(): Promise { assertTrue(true, 'no crash on missing directories'); } + // ─── 7. milestones/ directory created in worktree when missing ──────── + console.log('\n=== 7. milestones/ directory created in worktree when missing ==='); + { + const mainBase = createBase('main'); + const wtBase = mkdtempSync(join(tmpdir(), 'gsd-wt-sync-wt-')); + + try { + // Worktree has .gsd/ but NO milestones/ subdirectory + mkdirSync(join(wtBase, '.gsd'), { recursive: true }); + + // Main repo has M001 + const m001Dir = join(mainBase, '.gsd', 'milestones', 'M001'); + mkdirSync(m001Dir, { recursive: true }); + writeFileSync(join(m001Dir, 'M001-CONTEXT.md'), '# M001 Context'); + writeFileSync(join(m001Dir, 'M001-ROADMAP.md'), '# M001 Roadmap'); + + assertTrue(!existsSync(join(wtBase, '.gsd', 'milestones')), 'milestones/ missing before sync'); + + const result = syncGsdStateToWorktree(mainBase, wtBase); + + assertTrue(existsSync(join(wtBase, '.gsd', 'milestones')), 'milestones/ created in worktree'); + assertTrue(existsSync(join(wtBase, '.gsd', 'milestones', 'M001')), 'M001 synced to worktree'); + assertTrue(existsSync(join(wtBase, '.gsd', 'milestones', 'M001', 'M001-CONTEXT.md')), 'M001 CONTEXT synced'); + assertTrue(existsSync(join(wtBase, '.gsd', 'milestones', 'M001', 'M001-ROADMAP.md')), 'M001 ROADMAP synced'); + assertTrue(result.synced.length > 0, 'sync reported files'); + } finally { + cleanup(mainBase); + rmSync(wtBase, { recursive: true, force: true }); + } + } + report(); }