diff --git a/get-shit-done/bin/lib/phase.cjs b/get-shit-done/bin/lib/phase.cjs index 2244b9f02..3bda6758b 100644 --- a/get-shit-done/bin/lib/phase.cjs +++ b/get-shit-done/bin/lib/phase.cjs @@ -341,11 +341,13 @@ function cmdPhaseAdd(cwd, description, raw, customId) { _dirName = `${prefix}${_newPhaseId}-${slug}`; } else { // Sequential mode: find highest integer phase number (in current milestone only) + // Skip 999.x backlog phases — they live outside the active sequence const phasePattern = /#{2,4}\s*Phase\s+(\d+)[A-Z]?(?:\.\d+)*:/gi; let maxPhase = 0; let m; while ((m = phasePattern.exec(content)) !== null) { const num = parseInt(m[1], 10); + if (num >= 999) continue; // backlog phases use 999.x numbering if (num > maxPhase) maxPhase = num; } diff --git a/tests/phase.test.cjs b/tests/phase.test.cjs index 38da0a662..4225be9a8 100644 --- a/tests/phase.test.cjs +++ b/tests/phase.test.cjs @@ -655,6 +655,43 @@ describe('phase add command', () => { const roadmap = fs.readFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), 'utf-8'); assert.ok(roadmap.includes('**Requirements**: TBD'), 'new phase entry should include Requirements TBD'); }); + + test('skips 999.x backlog phases when calculating next phase number', () => { + fs.writeFileSync( + path.join(tmpDir, '.planning', 'ROADMAP.md'), + `# Roadmap v1.0 + +### Phase 1: Foundation +**Goal:** Setup + +### Phase 2: API +**Goal:** Build API + +### Phase 3: UI +**Goal:** Build UI + +### Phase 999.1: Future Idea A +**Goal:** Backlog item + +### Phase 999.2: Future Idea B +**Goal:** Backlog item + +--- +` + ); + + const result = runGsdTools('phase add Dashboard', tmpDir); + assert.ok(result.success, `Command failed: ${result.error}`); + + const output = JSON.parse(result.output); + assert.strictEqual(output.phase_number, 4, 'should be phase 4, not 1000'); + assert.strictEqual(output.slug, 'dashboard'); + + assert.ok( + fs.existsSync(path.join(tmpDir, '.planning', 'phases', '04-dashboard')), + 'directory should be 04-dashboard, not 1000-dashboard' + ); + }); }); // ─────────────────────────────────────────────────────────────────────────────