fix(#1455): resolve project-code-prefixed roadmap headings
* fix: remove hardcoded phase project-code prefix cap
Centralize project-code prefix stripping/matching and replace fixed {1,6} caps so long codes (for example MANIFOLD-117) resolve across phase, roadmap parser, roadmap upgrade, and validate flows.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address review feedback on prefix parsing
- allow project_code prefixes with digits and underscores while preserving milestone parsing
- use shared optional project-code prefix source in phase dir parsing
- extend regression coverage for APP1/APP_1 prefixed phases
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: resolve review nit in phase-id test comment
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: resolve project-code-prefixed roadmap headings
Make getRoadmapPhaseInternal recover from drifted project-code-prefixed ROADMAP headings while preserving canonical bare-heading preference. Add init.phase-op and parser regressions for #1455 and guard gsd-roadmapper against emitting project_code in headings.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: add changeset for project-code phase fix
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: update roadmapper agent size baseline
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(#1455): tighten project-code prefix regex to [A-Z] start; add boundary test; document source order
Resolves blockers from review:
- Regex changed from [A-Z_][A-Z0-9_]* to [A-Z][A-Z0-9_]* so leading
underscores (_FOO-7, _-7) are never misread as project-code prefixes;
adds boundary test asserting both do NOT strip.
- Adds comment to roadmapPhaseLookupSources explaining why 3 sources are
needed (order-dependent canonical-heading preference).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Solvely-Colin <211764741+Solvely-Colin@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -250,6 +250,52 @@ describe('roadmap-parser: getRoadmapPhaseInternal', () => {
|
||||
assert.strictEqual(result.goal, 'Set up infrastructure');
|
||||
});
|
||||
|
||||
test('finds drifted project-code-prefixed headings by bare number (#1455)', () => {
|
||||
writeRoadmap(tmpDir, [
|
||||
'## v1.0: Current',
|
||||
'### Phase MANIFOLD-117: Prefixed Heading',
|
||||
'**Goal:** Recover from roadmapper heading drift',
|
||||
].join('\n'));
|
||||
|
||||
const result = getRoadmapPhaseInternal(tmpDir, '117');
|
||||
assert.ok(result !== null, 'bare number lookup should tolerate a prefixed heading');
|
||||
assert.strictEqual(result.found, true);
|
||||
assert.strictEqual(result.phase_number, '117');
|
||||
assert.strictEqual(result.phase_name, 'Prefixed Heading');
|
||||
assert.strictEqual(result.goal, 'Recover from roadmapper heading drift');
|
||||
});
|
||||
|
||||
test('finds drifted project-code-prefixed headings by prefixed query (#1455)', () => {
|
||||
writeRoadmap(tmpDir, [
|
||||
'## v1.0: Current',
|
||||
'### Phase MANIFOLD-117: Prefixed Heading',
|
||||
'**Goal:** Exact prefixed lookup works on init resolver',
|
||||
].join('\n'));
|
||||
|
||||
const result = getRoadmapPhaseInternal(tmpDir, 'MANIFOLD-117');
|
||||
assert.ok(result !== null, 'prefixed lookup should resolve the matching prefixed heading');
|
||||
assert.strictEqual(result.found, true);
|
||||
assert.strictEqual(result.phase_number, 'MANIFOLD-117');
|
||||
assert.strictEqual(result.phase_name, 'Prefixed Heading');
|
||||
assert.strictEqual(result.goal, 'Exact prefixed lookup works on init resolver');
|
||||
});
|
||||
|
||||
test('prefers canonical bare heading before prefixed drift fallback (#1455)', () => {
|
||||
writeRoadmap(tmpDir, [
|
||||
'## v1.0: Current',
|
||||
'### Phase MANIFOLD-117: Prefixed Heading',
|
||||
'**Goal:** Drift fallback',
|
||||
'',
|
||||
'### Phase 117: Bare Heading',
|
||||
'**Goal:** Canonical bare',
|
||||
].join('\n'));
|
||||
|
||||
const result = getRoadmapPhaseInternal(tmpDir, '117');
|
||||
assert.ok(result !== null, 'bare lookup should resolve');
|
||||
assert.strictEqual(result.phase_name, 'Bare Heading');
|
||||
assert.strictEqual(result.goal, 'Canonical bare');
|
||||
});
|
||||
|
||||
test('returns null for missing phase number', () => {
|
||||
writeRoadmap(tmpDir, '### Phase 1: Foo\n**Goal:** bar\n');
|
||||
const result = getRoadmapPhaseInternal(tmpDir, '99');
|
||||
|
||||
Reference in New Issue
Block a user