feat(sdk): flag bracketed-placeholder result values (#3184)

Cycle 13 of ~15: 'result: [pending]' (template placeholder
copy-pasted without being filled) was previously dropped by
the \w+ regex. Now flagged as BRACKETED_PLACEHOLDER.
De-conflicted against ORPHAN_ITEM_MISSING_RESULT so an item
with a bracketed result doesn't double-report.
This commit is contained in:
Tom Boucher
2026-05-18 22:54:23 -04:00
parent f78f26688b
commit b116bb07b9
2 changed files with 30 additions and 1 deletions

View File

@@ -306,6 +306,35 @@ result: pass
}
});
it("emits BRACKETED_PLACEHOLDER reason when result value is wrapped in brackets", async () => {
const localTmp = await mkdtemp(join(tmpdir(), 'gsd-uat-c13-'));
try {
const phaseDir = join(localTmp, '.planning', 'phases', '05-bracketed-placeholder');
await mkdir(phaseDir, { recursive: true });
const content = `---
status: complete
phase: 5
source: roadmap
started: 2026-05-18T00:00:00Z
updated: 2026-05-18T00:00:00Z
---
### 1. Forgot to fill in result
expected: thing
result: [pending]
`;
await writeFile(join(phaseDir, '05-HUMAN-UAT.md'), content);
const result = await isPhaseUatPassed(localTmp, '5');
expect(result.passed).toBe(false);
expect(result.items.length).toBe(0);
expect(result.reasons.length).toBe(1);
expect(result.reasons[0].code).toBe(REASON_CODE.BRACKETED_PLACEHOLDER);
} finally {
await rm(localTmp, { recursive: true, force: true });
}
});
it("emits ORPHAN_ITEM_MISSING_RESULT reason for headings missing the result field", async () => {
const localTmp = await mkdtemp(join(tmpdir(), 'gsd-uat-c12-'));
try {

View File

@@ -170,7 +170,7 @@ export async function isPhaseUatPassed(
while ((bm = BRACK_RESULT_PATTERN.exec(strippedBody)) !== null) {
// find nearest preceding heading
const before = strippedBody.slice(0, bm.index);
const headingMatch = before.match(/###\s*(\d+)\.\s*([^\n]+)\s*$/);
const headingMatch = before.match(/###\s*(\d+)\.\s*([^\n]+)\s*$/m);
if (headingMatch) {
const num = parseInt(headingMatch[1], 10);
const name = headingMatch[2].trim();