import type { BaselineCatalog } from "./catalog.js"; import type { BaselineEvidenceLock } from "./schema.js"; /** * Is the committed evidence still describing the pins this build declares? * * The baseline vet is a function of its pin set. Every input it consumes is * content-addressed — sources by commit SHA, SkillSpector by image digest, the * scanner environments by hash-pinned `uv.lock`, `aih-native` by a content * digest over its own source closure — so between two runs at an unchanged pin * set nothing can differ except the machine. A green vet therefore stays valid * until a pin moves, and re-running it in the meantime recomputes a constant. * * What that makes load-bearing is knowing, cheaply and exactly, *whether* a pin * moved. This module answers that by comparing the pin set the build declares * against the pin set the committed lock actually recorded. It replaces * inferring the answer from which file paths a diff touched: a path pattern is * a proxy that can both over- and under-fire, whereas an identity comparison is * the fact itself. */ export type PinDriftKind = "source" | "analyzer"; export interface PinDrift { readonly kind: PinDriftKind; /** Source id (`ecc`) or analyzer name (`skillspector@docker`). */ readonly id: string; /** What this build declares today. `(not declared)` when it is gone. */ readonly declared: string; /** What the committed lock recorded. `(absent)` when the lock lacks it. */ readonly recorded: string; } /** * Compare declared pins against the pins the lock recorded. * * Analyzer drift is deduplicated by (name, recorded identity): the lock repeats * the same receipt on every component, and 151 identical rows would bury the * one line a reader needs. Deliberately does NOT compare component *content* * hashes — that is `baseline:check`'s job, and re-deriving them here would make * the cheap gate as expensive as the thing it exists to avoid. */ export declare function comparePinSets(input: { readonly lock: BaselineEvidenceLock; readonly catalogs: readonly BaselineCatalog[]; readonly analyzerVersions: Readonly>; }): PinDrift[]; /** * Operator-facing report. Says what to do, not merely that something is wrong: * drift here is not a defect to be fixed in place, it is a signal that the * committed evidence describes different bytes than this build declares, and * the only correct response is a fresh from-scratch vet. */ export declare function formatPinCurrency(drift: readonly PinDrift[]): string;