From 4e00c50022e337f3e8f1bf469b69f22a5e5dfdfe Mon Sep 17 00:00:00 2001 From: Tibsfox Date: Sat, 28 Feb 2026 04:48:04 -0800 Subject: [PATCH] fix(phase): add ROADMAP.md fallback to cmdPhaseComplete next-phase scan cmdPhaseComplete determines is_last_phase and next_phase by scanning .planning/phases/ directories on disk. Phases defined in ROADMAP.md but not yet planned (no directory created) are invisible to this scan, causing premature is_last_phase:true when only the first phase has been scaffolded. Add a fallback that parses ROADMAP.md phase headings when the filesystem scan finds no next phase. Uses the existing comparePhaseNum utility for consistent ordering with letter suffixes and decimals. Closes #709 Co-Authored-By: Claude Opus 4.6 --- get-shit-done/bin/lib/phase.cjs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/get-shit-done/bin/lib/phase.cjs b/get-shit-done/bin/lib/phase.cjs index 4e4cbff60..408d95df0 100644 --- a/get-shit-done/bin/lib/phase.cjs +++ b/get-shit-done/bin/lib/phase.cjs @@ -783,7 +783,9 @@ function cmdPhaseComplete(cwd, phaseNum, raw) { } } - // Find next phase + // Find next phase — check both filesystem AND roadmap + // Phases may be defined in ROADMAP.md but not yet scaffolded to disk, + // so a filesystem-only scan would incorrectly report is_last_phase:true let nextPhaseNum = null; let nextPhaseName = null; let isLastPhase = true; @@ -806,6 +808,24 @@ function cmdPhaseComplete(cwd, phaseNum, raw) { } } catch {} + // Fallback: if filesystem found no next phase, check ROADMAP.md + // for phases that are defined but not yet planned (no directory on disk) + if (isLastPhase && fs.existsSync(roadmapPath)) { + try { + const roadmapForPhases = fs.readFileSync(roadmapPath, 'utf-8'); + const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:\s*([^\n]+)/gi; + let pm; + while ((pm = phasePattern.exec(roadmapForPhases)) !== null) { + if (comparePhaseNum(pm[1], phaseNum) > 0) { + nextPhaseNum = pm[1]; + nextPhaseName = pm[2].replace(/\(INSERTED\)/i, '').trim().toLowerCase().replace(/\s+/g, '-'); + isLastPhase = false; + break; + } + } + } catch {} + } + // Update STATE.md if (fs.existsSync(statePath)) { let stateContent = fs.readFileSync(statePath, 'utf-8');