fix: treat any extracted verdict as terminal in isValidationTerminal (#2774)
* fix: treat any extracted verdict as terminal in isValidationTerminal If the LLM writes a VALIDATION file with an unrecognized verdict like `fail`, the allowlist in isValidationTerminal() returned false, keeping the state machine in validating-milestone phase and re-dispatching validate-milestone indefinitely (14+ times observed). Any non-null verdict from extractVerdict() means validation completed. Only return false when no verdict could be parsed. Closes #2769 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add regression tests for isValidationTerminal with fail verdict Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: update existing test to match new any-verdict-is-terminal behavior Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d5b318a222
commit
f4736f47ae
2 changed files with 17 additions and 12 deletions
|
|
@ -90,18 +90,13 @@ export function isMilestoneComplete(roadmap: Roadmap): boolean {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check whether a VALIDATION file's verdict is terminal (pass or needs-attention).
|
||||
* A non-terminal verdict (needs-remediation) means validation must re-run
|
||||
* after remediation slices are executed.
|
||||
* Check whether a VALIDATION file's verdict is terminal.
|
||||
* Any successfully extracted verdict (pass, needs-attention, needs-remediation,
|
||||
* fail, etc.) means validation completed. Only return false when no verdict
|
||||
* could be parsed — i.e. extractVerdict() returns undefined (#2769).
|
||||
*/
|
||||
export function isValidationTerminal(validationContent: string): boolean {
|
||||
const v = extractVerdict(validationContent);
|
||||
if (!v) return false;
|
||||
// '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 v === 'pass' || v === 'needs-attention' || v === 'needs-remediation';
|
||||
return extractVerdict(validationContent) != null;
|
||||
}
|
||||
|
||||
// ─── State Derivation ──────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -110,6 +110,16 @@ test("isValidationTerminal returns true for verdict: passed (#1429)", () => {
|
|||
assert.equal(isValidationTerminal(content), true);
|
||||
});
|
||||
|
||||
test("isValidationTerminal returns true for verdict: fail (#2769)", () => {
|
||||
const content = "---\nverdict: fail\nremediation_round: 1\n---\n\n# Validation";
|
||||
assert.equal(isValidationTerminal(content), true);
|
||||
});
|
||||
|
||||
test("isValidationTerminal returns true for any arbitrary verdict string (#2769)", () => {
|
||||
const content = "---\nverdict: custom-verdict\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);
|
||||
|
|
@ -327,14 +337,14 @@ test("verifyExpectedArtifact rejects VALIDATION with missing verdict field", ()
|
|||
}
|
||||
});
|
||||
|
||||
test("verifyExpectedArtifact rejects VALIDATION with unrecognized verdict", () => {
|
||||
test("verifyExpectedArtifact accepts VALIDATION with any extracted verdict", () => {
|
||||
const base = makeTmpBase();
|
||||
try {
|
||||
writeValidation(base, "M001", "---\nverdict: unknown-value\nremediation_round: 0\n---\n\n# Validation");
|
||||
clearPathCache();
|
||||
clearParseCache();
|
||||
const result = verifyExpectedArtifact("validate-milestone", "M001", base);
|
||||
assert.equal(result, false, "VALIDATION with unrecognized verdict should fail verification");
|
||||
assert.equal(result, true, "VALIDATION with any extracted verdict should pass verification");
|
||||
} finally {
|
||||
cleanup(base);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue