/** * Adversarial verification: a second, independent `claude -p` pass whose * explicit mandate is to REFUTE a finding against the same evidence. Findings * that survive are marked verified; refuted ones are dropped from the results * (kept in the report for transparency). In practice roughly a quarter of * serious findings do not survive it. * * What gets verified follows RISK, not severity alone. Severity says how much a * defect costs if it is real; it says nothing about how likely the judge was to * be wrong. The design-quality categories are the ones most easily argued into * existence, because they rest on a principle rather than on something plainly * broken, so they are refuted at every severity. A critical render failure and a * low-severity claim about hierarchy are both worth a second opinion, for * opposite reasons. */ import type { ShotRecord } from "../types.js"; import { type Pieces } from "./manifest.js"; import { type AiFinding } from "./engine.js"; /** * Whether a finding is worth a refuting pass. Every AI finding is. * * There used to be a boundary here: critical and high always, plus six * design-quality categories at any severity, on the theory that a minor * claim about something plainly broken needed no second look. The rubric's * own ladder contradicted it: low is defined as "a named principle broken", * which makes every low finding exactly the arguable kind, and the boundary * left design-parity ("you judged the hand-off the better of the two") and * the comparative categories color-scheme and responsive, the ones the * refuter was given whole-view evidence FOR, unrefuted at medium and low. * * Widening costs no extra subprocess: the refuter already runs once per * judged batch, and this predicate only decided which findings rode along. * The function stays because it is the single choke point, and the place the * next boundary argument belongs if one ever returns. */ export declare function needsRefuting(_f: AiFinding): boolean; export interface VerifiedFinding extends AiFinding { verified: boolean; verifierNote?: string; } /** A confirmed finding whose problem the refuter opened with a sentence a person can follow. */ export interface RepairedFinding { shotId: string; category: string; attribute: string; title: string; judge?: string; plain: string; } /** One acceptance criterion the refuter could not let stand, and why. */ export interface DroppedCriterion { shotId: string; category: string; attribute: string; judge?: string; text: string; reason: "undecidable-from-pixels" | "passes-on-the-defective-shot"; /** The observable replacement the refuter supplied, when it could. */ rewrite?: string; } export interface VerifyResult { confirmed: VerifiedFinding[]; /** * Criteria dropped or rewritten at filing time. * * A criterion that cannot be decided from a screenshot does not fail a * verify-fix: it comes back not-verifiable, blocks nothing, and quietly * degrades the ruling to "the defect was not re-filed". Catching it here * costs nothing, because the refuter is already reading this finding and * this shot. */ droppedCriteria: DroppedCriterion[]; /** The plain halves the refuter supplied, so the panel that skipped them can learn. */ repaired: RepairedFinding[]; refuted: (AiFinding & { verifierNote: string; })[]; costUsd?: number; } /** * What the refuter is asked, with the whole view attached. * * The rubric has the judge compare a view's dark/light pair and its form-factor * progression, so a colour-scheme or responsive finding is a claim ABOUT that * comparison. The refuter used to be handed the single shot the finding was * filed on and told to lean refuted when uncertain, so the findings that needed * the most evidence were given the least and died for want of the partner shot * that would have settled them either way. */ export declare function buildRefutePrompt(skillText: string, findings: AiFinding[], shotsById: Map, evidenceDir: string, pieces?: Pieces, /** * What the project declared (its never-file lines, its design direction), * for the skill's own section. "" is a legitimate value: the heading stands * and says nothing is declared. */ declared?: string): string; export declare function verifyFindings(skillText: string, findings: AiFinding[], shotsById: Map, evidenceDir: string, model: string, /** Whose incident log a refuter failure belongs in. */ projectDir?: string, /** What the project declared; see buildRefutePrompt. */ declared?: string): Promise;