* test(phase-plans): red — shared scanPhasePlans contract + parity across call sites (#3262)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(phase-plans): extract shared scanPhasePlans helper (k014) (#3262)
Eliminates four divergent copies of the plan-scan algorithm:
- roadmap.cjs:countPhasePlansAndSummaries (root call site)
- state.cjs:buildStateFrontmatter (1 of 3)
- state.cjs:cmdStateValidate (2 of 3)
- state.cjs:cmdStateSync (3 of 3)
- init.cjs:listPhasePlanFiles / listPhaseSummaryFiles
New bin/lib/plan-scan.cjs exports scanPhasePlans(phaseDir) → {
planCount, summaryCount, completed, hasNestedPlans,
planFiles, summaryFiles
}
Divergences resolved:
- roadmap.cjs used a broad isPlanFile (any .md containing PLAN in name,
matching the extended layout 5-PLAN-01-setup.md); canonical helper
adopts this wider pattern as the reference implementation.
- state.cjs used a strict endsWith(-PLAN.md) filter, missing extended-
layout root files; now unified with roadmap.cjs semantics.
- init.cjs listPhasePlanFiles used ^PLAN-\d+ for nested, missing
the -PLAN-\d+ variant state.cjs also matched; helper includes both.
- pre-bounce exclusion broadened to /.pre-bounce.md$/i (any pre-bounce
file), not just -PLAN.*\.pre-bounce\.md (roadmap form) or flat
.pre-bounce.md (state form).
- OUTLINE exclusion broadened to /-OUTLINE\.md$/i to catch both
flat (-PLAN-OUTLINE.md) and nested (PLAN-01-OUTLINE.md) forms.
Sibling audit: no 5th call site found. phase.cjs:looksLikePlanFile is
a diagnostic probe for non-canonical naming (not a counter) — left
in place per its distinct purpose.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(changelog): add entry for #3262 scanPhasePlans extraction
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(changeset): add changeset fragment for #3262
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(inventory): add plan-scan.cjs row to INVENTORY.md CLI Modules table (#3262)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(3262): update bug-3128 test + INVENTORY counts for plan-scan.cjs
- Update tests/bug-3128-roadmap-plan-count-slug-layout.test.cjs to verify
that roadmap.cjs delegates to plan-scan.cjs (require check) and that the
extended filter lives in plan-scan.cjs as isRootPlanFile with /PLAN/i
- Bump docs/INVENTORY.md CLI Modules headline from 46 to 47 (plan-scan.cjs)
- Regenerate docs/INVENTORY-MANIFEST.json to include cli_modules/plan-scan.cjs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(3262): migrate two missed call sites to scanPhasePlans (k014)
- init.cjs cmdInitExecutePhase: replace inline /-PLAN\.md$/i filter
with listPhasePlanFiles(path) to honour nested, extended-layout, OUTLINE
and pre-bounce exclusions (CR finding)
- state.cjs cmdStateUpdateProgress: replace dual /-PLAN\.md$/i and
/-SUMMARY\.md$/i filters with scanPhasePlans() so the progress-bar
body field uses the same counts as buildStateFrontmatter frontmatter
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(3262): correct INVENTORY-MANIFEST.json to tracked files only
Remove 3 untracked local entries from cli_modules so the manifest matches
what CI sees (47 tracked .cjs files, not 50 local). Previous regeneration
ran against the local filesystem which included cjs-command-router-adapter.cjs,
state-document.cjs, and workstream-inventory.cjs (all untracked on this branch).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>