fix(#2522): fold wrapped success-criteria lines into their criterion (#2637)

* test(#2522): wrapped + blank-line success-criteria parse

* fix(#2522): fold wrapped success-criteria lines into their criterion

* chore(#2522): backfill changeset pr to 2637
This commit is contained in:
Tom Boucher
2026-07-25 00:36:05 -04:00
committed by GitHub
parent 1a9ae7601b
commit 461c744c31
3 changed files with 82 additions and 3 deletions

View File

@@ -175,10 +175,17 @@ function searchPhaseInContent(content: string, escapedPhase: string, phaseNum: s
const modeMatch = section.match(/\*\*Mode(?::\*\*|\*\*:)\s*([^\n]+)/i);
const mode = modeMatch ? modeMatch[1].trim().toLowerCase() : null;
// Extract success criteria as structured array
const criteriaMatch = section.match(/\*\*Success Criteria\*\*[^\n]*:\s*\n((?:\s*\d+\.\s*[^\n]+\n?)+)/i);
// Extract success criteria as structured array. A criterion may wrap onto extra
// indented lines (no `N.` prefix); those continuations must fold INTO their
// criterion, not end the run (#2522 — the old `(?:\s*\d+\.\s*[^\n]+)+` broke on a
// wrapped line, truncating it and silently dropping every criterion below it).
// `\n*` before each numbered line keeps blank-line-separated criteria working.
const criteriaMatch = section.match(
/\*\*Success Criteria\*\*[^\n]*:\s*\n((?:\n*[ \t]*\d+\.[^\n]*\n?(?:[ \t]+(?!\d+\.)[^\n]*\n?)*)+)/i);
const success_criteria = criteriaMatch
? criteriaMatch[1].trim().split('\n').map(line => line.replace(/^\s*\d+\.\s*/, '').trim()).filter(Boolean)
? criteriaMatch[1].trim().split(/\n+(?=[ \t]*\d+\.)/)
.map(entry => entry.replace(/^\s*\d+\.\s*/, '').replace(/\s*\n\s*/g, ' ').trim())
.filter(Boolean)
: [];
return {