fix(#2641): strip YAML quotes from STATE.md milestone version

Address CodeRabbit review on PR #3046: extractCurrentMilestone read the
`milestone:` value from STATE.md frontmatter via `.trim()` only, while
parseMilestoneFromState() and getMilestoneInfo() both also strip
surrounding YAML quotes via `.replace(/^["']|["']$/g, '')`.

For projects whose STATE.md uses quoted YAML (`milestone: "v0.9"`),
`version` carried literal quotes, `escapedVersion` became `\"v0\.9\"`,
and neither the markdown-heading regex nor the new <details><summary>
fallback could match anything — falling through to
stripShippedMilestones() and reintroducing the same archived-milestone
misrouting this PR addresses.

Strip quotes for parity. Three-line addition + one new test.
All 41 roadmap.test.ts tests pass.
This commit is contained in:
Ben Lamm
2026-05-02 23:34:22 -04:00
committed by Tom Boucher
parent 592b676414
commit ba6a3efc3e
2 changed files with 35 additions and 2 deletions

View File

@@ -153,13 +153,19 @@ export async function getMilestoneInfo(projectDir: string, workstream?: string):
* @returns Content scoped to current milestone
*/
export async function extractCurrentMilestone(content: string, projectDir: string, workstream?: string): Promise<string> {
// Get version from STATE.md frontmatter
// Get version from STATE.md frontmatter.
// Strip optional surrounding YAML quotes (e.g. `milestone: "v0.9"`) for parity
// with parseMilestoneFromState() above and getMilestoneInfo()'s STATE.md path.
// Without this, a quoted version yields `escapedVersion = '\\"v0\\.9\\"'`
// which matches neither markdown headings nor <summary> text, falling
// through to stripShippedMilestones() — and reintroducing the same archived-
// milestone misrouting this fallback addresses.
let version: string | null = null;
try {
const stateRaw = await readFile(planningPaths(projectDir, workstream).state, 'utf-8');
const milestoneMatch = stateRaw.match(/^milestone:\s*(.+)/m);
if (milestoneMatch) {
version = milestoneMatch[1].trim();
version = milestoneMatch[1].trim().replace(/^["']|["']$/g, '');
}
} catch { /* intentionally empty */ }