import type { Finding } from "../../hub/finding.js"; import type { SeoReport, SeoWorkflow } from "../types.js"; /** One labelled benchmark case (mirrors a `corpus/manifest.json` entry). */ export interface SeoBenchmarkCase { /** Stable id, unique in the corpus. */ id: string; label: "known-good" | "known-bad"; workflow: SeoWorkflow; target: string; /** Written to a temp `//imports/` dir before the run. */ imports: Array<{ file: string; content: string; }>; /** The recorded raw text the `ScriptedClient` returns (a `{"findings":[...]}` JSON string, or garbage to prove fail-closed parsing). */ analyzerResponse: string; expected: { /** Each expected finding names its `playbookRef` and whether it should survive the citation gate. */ findings: Array<{ playbookRef: string; cited: boolean; }>; droppedUncited: number; verdict: "pass" | "blocked"; }; } export interface CorpusMetrics { /** ΣTP/(ΣTP+ΣFP) across every case, matched by the `playbook:` tag. */ findingPrecision: number; /** ΣTP/(ΣTP+ΣFN) across every case. */ findingRecall: number; /** Σ correctlyDropped / Σ expectedDropped — how well the uncited-drop count matches expectation. */ uncitedDropRecall: number; /** INVARIANT: MUST be 0 — count of emitted findings lacking a well-formed `cite:` evidence entry. */ uncitedReachedSink: number; /** INVARIANT: MUST be 0 — count of emitted findings whose text matches a never-encode tactic pattern. */ neverEncodeEmitted: number; cases: Array<{ id: string; emitted: Finding[]; report?: SeoReport; exitCode: 0 | 2; }>; } /** * Run the real `SeoWorkflowRunner` over `corpus`, offline and deterministic * (both egress axes off, an injected `ScriptedClient`-backed analyzer, and a * capturing sink standing in for the hub). Writes each case's inline * `imports[]` under `//imports/` before running so * `LocalExportSource` reads real files (no fs mocks, principle L44). * * NEVER throws: `SeoWorkflowRunner.run` itself never throws (runner.ts:256), * and every step here is either that call or pure aggregation. */ export declare function runBenchmark(corpus: SeoBenchmarkCase[], projectRoot: string): Promise; //# sourceMappingURL=harness.d.ts.map