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:
@@ -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({
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user