From 09e56893c8962ee18d18044a3d3e88d834bdaa2d Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Mon, 6 Apr 2026 08:54:18 -0400 Subject: [PATCH] fix(milestone): preserve 999.x backlog phases during phases clear (#1858) * fix(milestone): preserve 999.x backlog phases during phases clear Fixes #1853 * fix: remove accidentally bundled plan-stall-detection test Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 --- get-shit-done/bin/lib/milestone.cjs | 2 +- tests/milestone.test.cjs | 72 +++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/get-shit-done/bin/lib/milestone.cjs b/get-shit-done/bin/lib/milestone.cjs index adfb149a7..f406634c8 100644 --- a/get-shit-done/bin/lib/milestone.cjs +++ b/get-shit-done/bin/lib/milestone.cjs @@ -253,7 +253,7 @@ function cmdPhasesClear(cwd, raw, args) { if (fs.existsSync(phasesDir)) { const entries = fs.readdirSync(phasesDir, { withFileTypes: true }); - const dirs = entries.filter(e => e.isDirectory()); + const dirs = entries.filter(e => e.isDirectory() && !/^999(?:\.|$)/.test(e.name)); if (dirs.length > 0 && !confirm) { error( diff --git a/tests/milestone.test.cjs b/tests/milestone.test.cjs index 1d810937a..80f1b0e67 100644 --- a/tests/milestone.test.cjs +++ b/tests/milestone.test.cjs @@ -514,6 +514,78 @@ describe('milestone complete command', () => { }); }); +// ───────────────────────────────────────────────────────────────────────────── +// phases clear command +// ───────────────────────────────────────────────────────────────────────────── + +describe('phases clear command', () => { + let tmpDir; + + beforeEach(() => { + tmpDir = createTempProject(); + }); + + afterEach(() => { + cleanup(tmpDir); + }); + + test('deletes normal phase directories when --confirm is passed', () => { + const p1 = path.join(tmpDir, '.planning', 'phases', '01-setup'); + fs.mkdirSync(p1, { recursive: true }); + fs.writeFileSync(path.join(p1, '01-01-PLAN.md'), '# Plan\n'); + + const result = runGsdTools('phases clear --confirm', tmpDir); + assert.ok(result.success, `Command failed: ${result.error}`); + + const output = JSON.parse(result.output); + assert.strictEqual(output.cleared, 1, 'should have cleared 1 directory'); + assert.ok(!fs.existsSync(p1), '01-setup should be deleted'); + }); + + test('requires --confirm when phase directories exist', () => { + const p1 = path.join(tmpDir, '.planning', 'phases', '01-setup'); + fs.mkdirSync(p1, { recursive: true }); + + const result = runGsdTools('phases clear', tmpDir); + assert.ok(!result.success, 'should fail without --confirm'); + }); + + test('preserves 999.x backlog phase directories during clear (#1853)', () => { + const p1 = path.join(tmpDir, '.planning', 'phases', '01-setup'); + const p999a = path.join(tmpDir, '.planning', 'phases', '999.1-some-idea'); + const p999b = path.join(tmpDir, '.planning', 'phases', '999.2-another-idea'); + + fs.mkdirSync(p1, { recursive: true }); + fs.mkdirSync(p999a, { recursive: true }); + fs.mkdirSync(p999b, { recursive: true }); + + fs.writeFileSync(path.join(p1, '01-01-PLAN.md'), '# Plan\n'); + fs.writeFileSync(path.join(p999a, 'PLAN.md'), '# Backlog idea\n'); + fs.writeFileSync(path.join(p999b, 'PLAN.md'), '# Another backlog idea\n'); + + const result = runGsdTools('phases clear --confirm', tmpDir); + assert.ok(result.success, `Command failed: ${result.error}`); + + const output = JSON.parse(result.output); + assert.strictEqual(output.cleared, 1, 'should have cleared only 1 directory (not backlog)'); + assert.ok(!fs.existsSync(p1), '01-setup should be deleted'); + assert.ok(fs.existsSync(p999a), '999.1-some-idea should be preserved'); + assert.ok(fs.existsSync(p999b), '999.2-another-idea should be preserved'); + }); + + test('reports 0 cleared when only backlog phases exist', () => { + const p999a = path.join(tmpDir, '.planning', 'phases', '999.1-idea'); + fs.mkdirSync(p999a, { recursive: true }); + + const result = runGsdTools('phases clear --confirm', tmpDir); + assert.ok(result.success, `Command failed: ${result.error}`); + + const output = JSON.parse(result.output); + assert.strictEqual(output.cleared, 0, 'cleared should be 0 when only backlog phases exist'); + assert.ok(fs.existsSync(p999a), '999.1-idea should be preserved'); + }); +}); + // ───────────────────────────────────────────────────────────────────────────── // requirements mark-complete command // ─────────────────────────────────────────────────────────────────────────────