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');