/** * Acceptance criteria: what would prove an issue is actually fixed. * * Every issue carries them from the moment it is filed, because "is it fixed" * is not a question anybody should be answering from memory of what the defect * looked like. They are written to be decidable from a screenshot of the same * view: an agent handed the issue reads the same list lookout will rule against. * * Where they come from depends on the channel: * * - Deterministic findings derive theirs mechanically, from the check that * fired and the axes of the shot it fired on. No model, no cost, and exact: * the criterion is the same check, stated as the passing state. * - Judged findings get theirs from the judge, which saw the defect and is the * only thing that can say what its absence looks like. A finding filed before * the judge emitted them falls back to its own `expected` prose, which is the * same sentence written for a different purpose. * - Every issue also carries the guard the verdict rule already enforces * silently: pixels have to have moved. Making it a criterion means the one * rule that stops judge variance closing real defects is visible on the card * rather than buried in a comment. * * Only lookout rules on them. There is no path by which a person ticks a box: * the verdicts are written by `verify-fix` and rendered read-only. */ import type { BacklogFinding } from "../backlog/lib.js"; export type CriterionVerdict = "pending" | "met" | "unmet" | "not-verifiable"; export type CriterionSource = "derived" | "judge" | "universal"; export interface AcceptanceCriterion { /** Stable within the issue: derived from the source, origin and text. */ id: string; text: string; source: CriterionSource; /** * Fingerprint of the finding this came from, when it came from one. A derived * criterion is ruled by re-running that finding's own check. */ from?: string; verdict: CriterionVerdict; /** What the ruling saw. Present once it has been ruled at least once. */ note?: string; /** When it was last ruled, and by which run. Absent means never ruled. */ ruledAt?: string; runId?: string; /** The shots the verifier named as deciding it, when it named any. */ evidence?: string[]; /** The verifier's one-line remedy, when it offered one. */ suggestion?: string; } /** The universal criterion for anything photographed. */ export declare const RECAPTURE_CRITERION = "Every screenshot this issue was filed against was photographed again, and at least one of them changed."; /** * The universal criterion for an issue no screenshot was ever involved in. * A code cluster used to carry the screenshot one and have it blanket-marked * met by the code pass: a checked box for a capture that never happened, in * the record that exists so nobody answers "is it fixed" from memory. */ export declare const CODE_RECAPTURE_CRITERION = "lookout re-read the source and no longer sees this."; /** * The criterion a deterministic check states when it passes. * * Keyed off the attribute the check ingested under, so it stays in step with * DETERMINISTIC_MAP: an axe rule keeps its rule id, and everything else names * the failure it is the absence of. */ export declare function derivedCriterion(f: BacklogFinding): string; /** Everything one finding contributes, in the order it should be read. */ export declare function criteriaFor(f: BacklogFinding): AcceptanceCriterion[]; /** * Compose an issue's list from its findings, keeping every verdict already * ruled. Criteria are matched by id, which is derived from their text, so * re-composing after a merge neither duplicates them nor forgets what lookout * has already decided about them. * * A criterion whose finding is gone is dropped: it describes a defect this * issue no longer has. */ export declare function composeAcceptance(members: BacklogFinding[], existing?: AcceptanceCriterion[]): AcceptanceCriterion[]; /** A criterion ruled `unmet` blocks a pass; `not-verifiable` does not. */ export declare function blocksPass(criteria: AcceptanceCriterion[]): AcceptanceCriterion[]; export declare function acceptanceTally(criteria: AcceptanceCriterion[]): { met: number; unmet: number; notVerifiable: number; pending: number; total: number; };