/** * Recompute an evidence `tests:` block against a committed run report * (docs/DEFECT_LEDGER_DESIGN.md §5, acceptance 9-10). * * §5.1's incident, written against its own author on the day the section was * drafted: `tests: total: 1301` was typed into an evidence file that `es govern` * reads, scores, and posts to a countersigned immutable record. NO CODE PATH * RECOMPUTED IT. A grep for a reader of `tests.total` in `packages/core` and * `packages/cli` returned nothing — the number was scored but never checked. * (Re-run on this branch before building: still nothing.) * * §5.2 states why that is the same defect as the control-must-fire invariant, * one level up. The policy lint exists because *a check that cannot fire is * indistinguishable from a check that passes*. The evidence case is identical in * shape: **a number nobody recomputes is indistinguishable from a number that is * right.** * * Everything here inspects the CLAIM rather than the codebase, which is the one * artefact in this system that is purely claim. */ /** * The date from which a self-reported count stops being free (§9.4). * * §9.4 asked whether a missing run report should DEGRADE or BLOCK, and recorded * it as the owner's decision rather than engineering's. The answer taken is * BOTH, separated by a date — the "dated deadline with a visible count" §9.4 * itself predicts, now that the visible count exists. * * Neither pole survives on its own. Blocking on day one fails every repository * that has not yet wired a reporter, and PB-005 measured what that produces: a * gate red on merit from run one is a gate somebody switches off. Degrading * forever is the other failure and it is on the record twice — `^3.11.0` sat * stale in published copy for months, and `check:published` reported agreement * for weeks while six packages shipped unpublished code. A degradation nobody * looks at is indistinguishable from a verification. * * The severity after the date is `high`, NEVER `critical`, and that is not * timidity. A missing report means the count is UNVERIFIED; a contradicted * count means it is FALSE. Those are different claims and must not share a * severity — the same line this module already draws between `unreadable` and * `mismatch`. A `critical` would also be unacceptable-by-construction under the * scorer's own rule that a critical can never be `accepted`. */ export declare const REPORT_REQUIRED_FROM = "2026-10-01"; /** Is a self-reported count still free on this date? */ export declare function selfReportedIsFree(today: Date, requiredFrom?: string): boolean; /** The `tests:` block as it appears in evidence. Untrusted YAML — any shape. */ export interface DeclaredTests { suite?: unknown; total?: unknown; passed?: unknown; failed?: unknown; /** Repo-relative path to a committed machine-readable run report. */ report?: unknown; } export interface RunReportTotals { total: number; passed: number; failed: number; } export type TestsVerdict = /** Recomputed from a committed report and the numbers agree. */ 'verified' /** Recomputed and they DISAGREE — the claim is false. */ | 'mismatch' /** No committed report to recompute against. Degraded, visible, never silent. */ | 'self_reported' /** A report was named but cannot be used, which is not the same as absent. */ | 'unreadable' /** No `tests:` block at all — nothing claimed, so nothing to check. */ | 'absent'; export interface TestsVerification { verdict: TestsVerdict; /** Always populated for a human: what was compared, or why nothing was. */ detail: string; declared?: Partial; recomputed?: RunReportTotals; /** Repo-relative path of the report actually read. */ reportPath?: string; } /** * Where a report lives when the evidence does not say. * * A convention rather than a requirement: an explicit `tests.report` always * wins. Both vitest and jest write this shape from `--reporter=json`. */ export declare function conventionalReportPath(skillId: string): string; /** * Where the SHARED report for a suite lives. * * One `npm test` run backs every feeder that declares the same suite, so * requiring a per-skill copy would mean writing the same document three times * and keeping the copies in step — new drift, invented by the drift check. * `npm run test:report` in this repository writes exactly this path. */ export declare function suiteReportPath(suite: string): string; /** * Parse a vitest/jest `--reporter=json` document into totals. * * Vitest deliberately mirrors jest's schema, so one reader covers both. A * document missing the counters is REJECTED rather than defaulted to zero: * zeroes would compare as "0 tests, and you claimed 1382", which is a mismatch * for the wrong reason — and "the report is unreadable" must not be able to * masquerade as "the author lied". */ export declare function parseRunReport(raw: string): RunReportTotals | { error: string; }; /** * Read a repo-relative file AS IT WAS at a commit, or null when it was not * there. `git show :` with a list argv — a shell would re-parse * the ref-colon-path form, which is D-012's exact incident. A null is * "absent at that commit", never an error masquerading as absence: git * distinguishes a missing path (exit 128, caught here) from a bad object id * the same way, and both honestly mean "this commit cannot back the claim". */ export declare function readFileAtCommit(root: string, commit: string, relPath: string): string | null; /** Options for {@link verifyTests}. */ export interface VerifyTestsOptions { /** * RC-2 — recompute against the report AS IT WAS at this commit, not against * the working tree. * * The incident: stale evidence (bound to an earlier commit) had its counts * compared against the CURRENT tree's report, so a count that was RIGHT when * written read as `mismatch` — "the claim is false" — when the only true * statement was "the binding is stale", which the Governor already fails * separately with its own reason. UNVERIFIED and FALSE are different claims; * conflating them here is the same severity error §9.4 refused to make. * * With `atCommit`, a stale file's counts are judged against ITS OWN tree: * right-when-written verifies (staleness remains the only failure), and * false-when-written still reads `mismatch` — no weakening, anywhere. */ atCommit?: string; /** Injectable for tests. Defaults to {@link readFileAtCommit}. */ readAtCommit?: (root: string, commit: string, relPath: string) => string | null; } /** * Verify a declared `tests:` block. * * The report must be TRACKED BY GIT, not merely present. An untracked report is * writable between the run and the read and is outside the tree digest the * evidence is bound to, so recomputing against one would prove only that a file * existed at some moment. Tracked means it is part of the bound tree. */ export declare function verifyTests(root: string, skillId: string, declared: DeclaredTests | undefined, options?: VerifyTestsOptions): TestsVerification; //# sourceMappingURL=test-report.d.ts.map