/** * Decides whether an issue is "done" based on the final verification verdict and * an acceptance-criteria comparison. * * An issue is "done" ONLY if the verdict is PASS AND every acceptance criterion * is matched-and-checked by the verifier. Otherwise it is "needs-human" with the * reason and the unmet/unmatched criteria listed. * * Two robustness properties (issue 06): * * 1. Matching is by NORMALIZED TEXT, not list position. The verifier's * `CRITERIA:` checklist is free-form LLM output; it may reorder, reword * slightly, or add extra lines. Each issue criterion is matched to a verifier * entry by a normalized key (lowercased, collapsed whitespace, stripped * trailing punctuation), so a reorder or cosmetic difference does not produce * a false "needs-human". An issue criterion with no matching checked verifier * entry is unmet. * * 2. "No criteria" is distinguished from "criteria failed to parse". A trivial * ticket with NO acceptance-criteria section is a deliberate weak gate * (warn-and-proceed → done on PASS). But a criteria SECTION that was present * yet parsed to zero items is a malformed spec — you cannot verify what did * not parse — so it is needs-human, never a silent done. The caller passes * `sectionPresent` to make that distinction; omitted, it defaults to the * trivial-ticket reading for back-compat. * * Pure (no I/O) so it is unit-tested directly. */ import type { Verdict } from "./verdict.ts"; import type { AcceptanceCriterion } from "./acceptance.ts"; export type DoneDecision = { status: "done"; } | { status: "needs-human"; unmet: string[]; reason: string; }; export interface DecideDoneOpts { /** * Whether the issue markdown actually had an "## Acceptance criteria" section. * true + zero parsed criteria = a malformed/unparseable spec (needs-human); * false = a trivial ticket with no criteria (weak gate → done on pass). * Defaults to false (trivial-ticket reading) for back-compat. */ sectionPresent?: boolean; } export declare function decideDone(verdict: Verdict, issueCriteria: AcceptanceCriterion[], verifierResults: AcceptanceCriterion[], opts?: DecideDoneOpts): DoneDecision;