/** * Coverage guard for the surface list. * * StyleProof captures exactly the surfaces a spec declares, and the diff matches * surfaces by key — so a route nobody added to `surfaces` is invisible to the * gate: the change it introduces has no baseline capture AND no head capture, so * it never appears in any diff. The gate goes green having never looked at it. * This is the one failure StyleProof can't catch from the captures alone, because * it's about a capture that was never taken. * * `expected` closes the hole: a spec declares its full route/view/state universe * (e.g. an app's route + overlay-flow registry), and the guard fails when that * universe drifts from what's actually captured — turning a silent coverage hole * into a red test, in the app's own suite, the moment the route or flow is added. */ export type CoverageGaps = { /** Expected surfaces that are neither captured nor explicitly excluded. */ uncovered: string[]; /** `exclude` entries absent from `expected` — a renamed or removed route whose * opt-out has gone stale (the same drift, in reverse). */ staleExclusions: string[]; }; /** * Compare the captured surface keys against a declared `expected` universe. * * A surface is covered if it's captured OR listed in `exclude` (a deliberate, * documented opt-out — `key → reason`). Captured surfaces NOT in `expected` are * allowed: a project may start by requiring only route keys, then tighten the * universe with explicit state keys such as `landing-nav-open` or * `dashboard-dialog-open`. * * Pure and side-effect-free so it's unit-testable; `defineStyleMapCapture` wraps * it in a Playwright test that runs in the normal suite (not gated on a capture * dir), and it's exported so a consumer can assert coverage however it likes. */ export declare function coverageGaps(capturedKeys: Iterable, expected: Iterable, exclude?: Record): CoverageGaps; /** * Translate captured surface keys into the DECLARED keys they satisfy for coverage. * * `expected` is stated in base surface keys (`home`), but a surface with `liveStates` * is captured ONLY as its split expansions (`home-loading`, `home-loaded`) — the bare * base key is dropped by design (the base live state is fuzzy). Comparing the expanded * keys literally against `expected` would report the declared `home` as uncovered on a * fully-captured app. Each expansion still carries its originating `surfaceKey`, so the * declared base key is exactly recoverable: a capture satisfies its own key AND its * `surfaceKey`. This is precise (it maps only real expansions back to their real base), * not a suffix heuristic — an unrelated `home-banner` never satisfies an uncaptured `home`. */ export declare function coverageKeys(captured: Iterable<{ key: string; metadata?: { surfaceKey?: string; }; }>): string[]; /** * Rewrite a declared `expected` universe (base keys) into the keys that are actually * captured to disk, so the GATE — which reads expanded map filenames (`home-loading`) * and can't see each capture's `surfaceKey` metadata — can compare literally. * * A declared key `K` is replaced by its captured liveState expansions when `K` is NOT * itself a captured key but expansions carrying `surfaceKey === K` exist. A directly * captured `K` is kept; a genuinely uncaptured `K` is kept verbatim so the gate still * flags it. This is the write-time half of {@link coverageKeys}: the ledger travels * pre-translated, so `auditCoverage` needs no metadata at gate time. */ export declare function translateExpected(expected: readonly string[], captured: Iterable<{ key: string; metadata?: { surfaceKey?: string; }; }>): string[]; /** Bundled next to the maps, so the completeness basis travels with the capture. */ export declare const COVERAGE_LEDGER = "styleproof-coverage.json"; /** * How a capture's determinism was established — the second half of a trustworthy green. * `self-checked`: captured twice and the computed styles matched (a drift would have * failed the capture). `replayed`: rendered against a recorded HAR, so deterministic by * construction. `unproven`: neither — the styles could have drifted and no one checked. */ export type DeterminismBasis = 'self-checked' | 'replayed' | 'unproven'; export type CoverageLedger = { version: 1; /** The declared surface registry, or null when the spec asserted none. */ expected: string[] | null; /** Reviewed opt-outs (`key → reason`). */ exclude: Record; /** How this capture's determinism was established (3.10.0). Absent on older bundles. */ determinism?: DeterminismBasis; /** * The data-residue guard mode this capture ran under (issue #205). `'gate'` (the v4 * default) — an unacknowledged failing data endpoint blocks the diff; `'warn'` — the * explicit opt-out, residue is recorded and warned but never blocks. Absent on bundles * captured before the field existed, and read as warn so they never gate retroactively. */ dataResidue?: 'warn' | 'gate'; }; export type DeterminismVerdict = { /** `proven` — both sides self-checked or replayed; `unproven` — a side was neither, so * a clean diff might just be two matching NONDETERMINISTIC captures; `unknown` — an * older bundle with no determinism field (fail closed at the gate unless diagnostic * `--allow-unasserted`). */ status: 'proven' | 'unproven' | 'unknown'; base: DeterminismBasis | 'unknown'; head: DeterminismBasis | 'unknown'; }; /** The gate's determinism call: a green needs BOTH sides proven (self-checked or replayed). */ export declare function auditDeterminism(base: CoverageLedger | null, head: CoverageLedger | null): DeterminismVerdict; export type CoverageVerdict = { /** `complete` — every registered surface captured; `incomplete` — a registered * surface is missing (gates); `unasserted` — no registry (gates certification * unless `--allow-unasserted` diagnostic mode). */ basis: 'complete' | 'incomplete' | 'unasserted'; /** Size of the declared registry, or null when unasserted. */ registrySize: number | null; /** Registered surfaces neither captured nor excluded — the coverage hole. */ uncovered: string[]; /** `exclude` entries no longer in `expected` — a rotted opt-out. */ staleExclusions: string[]; }; /** The gate's completeness call: audit what was actually captured against the ledger. */ export declare function auditCoverage(capturedKeys: Iterable, ledger: CoverageLedger | null): CoverageVerdict;