/** * How ONE prerequisite is judged: its body markers, and the soft-pass * downgrade a missing file gets inside a back-compat window. * * WHY THIS IS A SIBLING AND NOT THREE MORE LINES IN THE TABLE. * `artifact-prerequisites.ts` is over the 300-line file-size cap and * `fileSizeExcessLines` is a ratchet that may only go DOWN * (`.husky/peaks-gate-baseline-monotonic.mjs` — "Split the file; do not raise * the ceiling"). The soft-pass branch this module was split out for must ADD * lines to that file, so the body check its two enforcers share lives here, * where the census counts no debt. `prerequisiteBodyViolations` moved verbatim; * only its location changed. */ import type { ArtifactPrerequisite } from './artifact-prerequisites.js'; /** * The warning `code` for a prerequisite whose file is missing inside its * back-compat window, derived from the prerequisite itself: the artifact's own * filename stem plus the release that closes the window. * * The stem is what makes the code name WHICH artifact is missing — the branch * this replaced emitted the literal `mut-report-missing-deprecated-in-v2.14.0` * for EVERY `backCompat` prerequisite, so the `rd/third-party-review-.md` * warning carried the same code as the `mut/mut-report.json` one and a * consumer filtering on it matched both. `backCompatUntil` keeps the * deprecation semantics legible and is per-prerequisite, because the two live * windows close in different releases (v2.14.0 and v2.15.0). * * The stem is taken verbatim from `relativePath`, so no character is rewritten * — including a `` placeholder. * * TWO KNOWN LIMITS OF THE STEM, stated so neither is read as a guarantee: * - a ``-templated soft prerequisite keeps the placeholder, producing * the LITERAL `-missing-deprecated-in-…` — the same code for every * request. One live prerequisite now does (`rd/third-party-review-.md`): * its code is filterable by ARTIFACT CLASS but not by slice. That is the * deliberate trade — resolving the rid into the code would give every * slice a code a consumer would have to already know to match. * - the stem comes from the FILENAME only, so two prerequisites sharing a * stem collide (`x.md` and `x.json` both yield `x-…`). Measured 0 live * collisions, and the pair that exists (`mut/mut-report.json` vs * `rd/third-party-review-.md`) differs by stem as well as by directory. */ export declare function backCompatWarningCode(prerequisite: ArtifactPrerequisite): string; /** Negative when `a` predates `b`, positive when it follows, 0 when their * release triples are equal. * * Exported because the commit-leg expiry gate makes the same comparison the * soft warning makes: an acceptance entry is current only while its `reviewBy` * is still ahead of the installed release. One comparator, so the two legs * cannot disagree about where a window boundary sits. */ export declare function compareReleaseVersions(a: string, b: string): number; /** * The soft-pass warning for a missing `prerequisite`, or `null` when a missing * file is a HARD failure and belongs in `missing` instead. * * The `null` is the whole decision, and it is the caller's only input to it. The * invariant the two destinations have, stated exactly: * - `warnings` does NOT feed `ok` — a soft pass is reported, never enforced, * which is why this can be a warning at all; * - `missing` IS what decides `ok` (`ok = missing.length === 0`), so choosing * the `missing` branch is choosing to fail the gate. That is the point of * the `null`, and the acceptance evidence for this change depends on it. * * `expiredWindow` is set only when the declared window has closed, so its * PRESENCE is the verdict and `path` / `code` / `message` stay byte-identical for * the consumers that already read them. */ export declare function missingPrerequisiteWarning(prerequisite: ArtifactPrerequisite, relativePath: string, installedVersion?: string): { path: string; code: string; message: string; expiredWindow?: string; } | null; /** * The contract's BODY checks for one prerequisite, applied to `body`. Returns * one human-readable message per failed check, empty when the body satisfies * the contract. * * Exported because this contract has a SECOND enforcer: `peaks workflow * verify-pipeline` probes the same table for the paths it checks * (`pipeline-verify-gate-support.ts`), and a resolver that probed only * `existsSync` passed files this function rejects — a guard laxer than the * contract it claims to read. Both callers now share this one implementation, * so the checker cannot drift from the table again. */ export declare function prerequisiteBodyViolations(prerequisite: ArtifactPrerequisite, body: string): string[]; /** * The body violations for `prerequisite`, or `[]` when it declares no body * contract — and in that case `read` is NEVER called, so a prerequisite with * nothing to check never has its file opened (unchanged behaviour: the guard has * always been a guard on the READ, which is why it takes the read as a thunk * rather than the body). */ export declare function bodyViolationsIfDeclared(prerequisite: ArtifactPrerequisite, read: () => Promise): Promise; /** * One unmet prerequisite as `checkPrerequisites` reports it. `path` and * `description` are unchanged from the pre-`kind` shape so every existing * consumer keeps reading them; `kind` is the machine-readable answer to "is the * file absent, or present and failing its body contract?" — the question a * consumer previously had to infer by parsing the prose. * * - `absent`: nothing resolved at `path`. * - `body`: a file resolved and failed the body markers its prerequisite * declares. */ export type UnmetPrerequisite = { path: string; description: string; kind: 'absent' | 'body'; }; /** * The transition refusal's message line: the total plus the split a reader * needs to tell "you have not written it" from "you wrote it and it does not * satisfy the contract". A bare total sent a producer to produce a file that * already existed. * * A zero count is omitted, so the line never reads * `…: 0 missing artifacts, 1 present but invalid`. */ export declare function unmetPrerequisiteMessage(role: string, newState: string, sessionId: string, missing: ReadonlyArray>): string;