fix(roadmap): mark individual plan checkboxes when summaries exist

`cmdRoadmapUpdatePlanProgress` only marked phase-level checkboxes
(e.g. `- [ ] Phase 50: Build`) but skipped plan-level entries
(e.g. `- [ ] 50-01-PLAN.md`). Now iterates phase summaries and
marks matching plan checkboxes as complete.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
j2h4u
2026-03-04 03:12:53 +05:00
parent 1427aab41b
commit 459f7f3b64
2 changed files with 48 additions and 0 deletions

View File

@@ -287,6 +287,18 @@ function cmdRoadmapUpdatePlanProgress(cwd, phaseNum, raw) {
roadmapContent = replaceInCurrentMilestone(roadmapContent, checkboxPattern, `$1x$2 (completed ${today})`);
}
// Mark completed plan checkboxes (e.g. "- [ ] 50-01-PLAN.md" or "- [ ] 50-01:")
for (const summaryFile of phaseInfo.summaries) {
const planId = summaryFile.replace('-SUMMARY.md', '').replace('SUMMARY.md', '');
if (!planId) continue;
const planEscaped = escapeRegex(planId);
const planCheckboxPattern = new RegExp(
`(-\\s*\\[) (\\]\\s*${planEscaped})`,
'i'
);
roadmapContent = roadmapContent.replace(planCheckboxPattern, '$1x$2');
}
fs.writeFileSync(roadmapPath, roadmapContent, 'utf-8');
output({

View File

@@ -756,6 +756,42 @@ describe('roadmap update-plan-progress command', () => {
assert.strictEqual(output.updated, false, 'should not update');
assert.ok(output.reason.includes('ROADMAP.md not found'), 'reason should mention missing ROADMAP.md');
});
test('marks completed plan checkboxes', () => {
const roadmapContent = `# Roadmap
- [ ] Phase 50: Build
- [ ] 50-01-PLAN.md
- [ ] 50-02-PLAN.md
### Phase 50: Build
**Goal:** Build stuff
**Plans:** 2 plans
## Progress
| Phase | Plans Complete | Status | Completed |
|-------|---------------|--------|-----------|
| 50. Build | 0/2 | Planned | |
`;
fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), roadmapContent);
const p50 = path.join(tmpDir, '.planning', 'phases', '50-build');
fs.mkdirSync(p50, { recursive: true });
fs.writeFileSync(path.join(p50, '50-01-PLAN.md'), '# Plan 1');
fs.writeFileSync(path.join(p50, '50-02-PLAN.md'), '# Plan 2');
// Only plan 1 has a summary (completed)
fs.writeFileSync(path.join(p50, '50-01-SUMMARY.md'), '# Summary 1');
const result = runGsdTools('roadmap update-plan-progress 50', tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const roadmap = fs.readFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), 'utf-8');
assert.ok(roadmap.includes('[x] 50-01-PLAN.md') || roadmap.includes('[x] 50-01'),
'completed plan checkbox should be marked');
assert.ok(roadmap.includes('[ ] 50-02-PLAN.md') || roadmap.includes('[ ] 50-02'),
'incomplete plan checkbox should remain unchecked');
});
});
// ─────────────────────────────────────────────────────────────────────────────