From 95f585d18354621fc45da03144039574a46401c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=82CHES?= Date: Thu, 19 Mar 2026 17:33:15 -0600 Subject: [PATCH] fix(gsd): accept 'passed' as terminal validation verdict (#1429) (#1509) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit isValidationTerminal() now normalizes verdict: passed → pass before comparison. LLM-generated validation files that write "passed" instead of "pass" are accepted as terminal, preventing milestones from being treated as incomplete. Closes #1429 Co-authored-by: Claude Opus 4.6 (1M context) --- src/resources/extensions/gsd/state.ts | 3 ++- .../extensions/gsd/tests/validate-milestone.test.ts | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/resources/extensions/gsd/state.ts b/src/resources/extensions/gsd/state.ts index 3f0b31c98..d97f320a3 100644 --- a/src/resources/extensions/gsd/state.ts +++ b/src/resources/extensions/gsd/state.ts @@ -64,11 +64,12 @@ export function isValidationTerminal(validationContent: string): boolean { if (!match) return false; const verdict = match[1].match(/verdict:\s*(\S+)/); if (!verdict) return false; + const v = verdict[1] === 'passed' ? 'pass' : verdict[1]; // 'pass' and 'needs-attention' are always terminal. // 'needs-remediation' is treated as terminal to prevent infinite loops // when no remediation slices exist in the roadmap (#832). The validation // report is preserved on disk for manual review. - return verdict[1] === 'pass' || verdict[1] === 'needs-attention' || verdict[1] === 'needs-remediation'; + return v === 'pass' || v === 'needs-attention' || v === 'needs-remediation'; } // ─── State Derivation ────────────────────────────────────────────────────── diff --git a/src/resources/extensions/gsd/tests/validate-milestone.test.ts b/src/resources/extensions/gsd/tests/validate-milestone.test.ts index e87dd4972..9a1ed7f25 100644 --- a/src/resources/extensions/gsd/tests/validate-milestone.test.ts +++ b/src/resources/extensions/gsd/tests/validate-milestone.test.ts @@ -104,6 +104,11 @@ test("isValidationTerminal returns true for verdict: needs-remediation (#832)", assert.equal(isValidationTerminal(content), true); }); +test("isValidationTerminal returns true for verdict: passed (#1429)", () => { + const content = "---\nverdict: passed\nremediation_round: 0\n---\n\n# Validation"; + assert.equal(isValidationTerminal(content), true); +}); + test("isValidationTerminal returns false for missing frontmatter", () => { const content = "# Validation\nNo frontmatter here."; assert.equal(isValidationTerminal(content), false);