fix(gsd): import all-done milestones as complete during DB migration

migrateHierarchyToDb imported milestones with all-done roadmap slices
as "active" when SUMMARY.md was missing. This let plan-milestone
overwrite already-completed work.

Now checks parsed roadmap slices — if all are done, imports as
"complete" even without SUMMARY.md.

Closes #3390
Closes #3379

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tibsfox 2026-04-06 20:07:42 -07:00
parent b4c6229360
commit f65f92cf76

View file

@ -530,11 +530,6 @@ export function migrateHierarchyToDb(basePath: string): {
// Ghost milestone: no CONTEXT, ROADMAP, or SUMMARY → skip
if (!hasRoadmap && !hasContext && !hasSummary) continue;
// Determine milestone status
let milestoneStatus = 'active';
if (hasSummary) milestoneStatus = 'complete';
else if (hasParked) milestoneStatus = 'parked';
// Determine milestone title from roadmap H1 or CONTEXT heading
let milestoneTitle = '';
let roadmapContent: string | null = null;
@ -544,6 +539,16 @@ export function migrateHierarchyToDb(basePath: string): {
roadmap = parseRoadmap(roadmapContent);
milestoneTitle = roadmap.title;
}
// Determine milestone status
let milestoneStatus = 'active';
if (hasSummary) milestoneStatus = 'complete';
else if (hasParked) milestoneStatus = 'parked';
// Import milestones with all-done roadmap slices as complete (#3390, #3379)
// even when SUMMARY.md is missing — the roadmap checkboxes are authoritative.
else if (roadmap && roadmap.slices.length > 0 && roadmap.slices.every(s => s.done)) {
milestoneStatus = 'complete';
}
if (!milestoneTitle && hasContext) {
const contextContent = readFileSync(contextPath!, 'utf-8');
const h1Match = contextContent.match(/^#\s+(.+)/m);