import type { PrMeta, WindtunnelLock } from '@mmnto/totem'; export interface FreezeOptions { lcDir?: string; lockPath?: string; } /** * `totem spine windtunnel freeze` * * Validates that the lock file at `LOCK_REL_PATH` (or `opts.lockPath`) is * schema-valid and that `resolvedPrs === selectionRule(asOfCommit)` (S4 — * completeness assertion). Writes the canonical lock path. * * The completeness assertion requires the lc clone (`--lc-dir`) so the * command can re-derive the full code-touching PR set at `asOfCommit` and * diff it against `resolvedPrs`. In the harness phase (no real lc run yet) * the assertion is skipped with a loud warning. */ export declare function freezeCommand(opts: FreezeOptions): Promise; /** * #2237 papercut-2: compute the llm-replay seal hash `freeze` stamps into * `controls.integrity.llmReplaySha`. Returns `computeArtifactHash` over the parsed * `llm-replay.v1.json` at `replayPath` — byte-for-byte the SAME external L2 hash * `buildReplayAdapters` re-verifies at run time — or `null` when the fixture is * absent (record hasn't run yet). Pure: no lock write (freeze owns the stamp), so * the hash derivation is unit-testable without a full lock/commit/clone setup. */ export declare function computeReplaySeal(replayPath: string): Promise; export interface RunOptions { lcDir?: string; lockPath?: string; phase?: string; /** * 5c-ii injection seam (out of 5c-i scope to populate): the certifying corpus * — resolved-PR diffs (corpus + controls), the active compiled rules, and the * frozen ground-truth labels. When omitted on a certifying run, the real * engine path throws a structured "corpus provider not wired" error rather * than silently scoring an empty set. 5c-ii (the orchestrator) supplies the * live-recorded corpus here; 5c-i unit tests supply a deterministic fixture. */ certifyingCorpus?: CertifyingCorpusProvider; } /** * The certifying corpus the real engine scores (5c-ii supplies this; 5c-i * defines the seam + the deterministic engine that consumes it). Returns the * active compiled rules (archived MUST be excluded — fold-F throws otherwise), * the resolved-PR diffs (corpus + positive/negative controls), and the frozen * ground-truth labels keyed by firingLabelId. */ export type CertifyingCorpusProvider = (lock: WindtunnelLock) => Promise | CertifyingCorpus; export interface CertifyingCorpus { rules: import('@mmnto/totem').CompiledRule[]; prDiffs: import('@mmnto/totem').ResolvedPrDiff[]; groundTruth: Map; /** * Mining provenance per rule (lessonHash → provenance) — supplied by the * orchestrator from the candidate/emission records. fold-B needs it to stamp * legitimacy; a survivor without provenance is surfaced as a skip, never * fabricated. */ provenanceByRule: Map; /** * ADR-112 §6/§9 Slice D1 — the authored §6 emission controls (positive / * negative / nonEmissions). Present IFF this corpus is authored-provenance * (single-provenance §7): `buildAuthoredCertifyingCorpus` derives it from the * sidecar provenance; the mined `buildCertifyingCorpus` never sets it, so a mined * corpus has `authoredControls === undefined` (the miner path is byte-unchanged). * Defined-with-EMPTY-arrays for an authored corpus that emitted no fixtures, never * undefined-for-authored. INERT in D1: assembled here, scored by nobody (D3/D4 * consume it — the engine reads only rules/prDiffs/groundTruth/provenanceByRule). */ authoredControls?: import('@mmnto/totem').AuthoredControls; } /** * ADR-112 §5.3/§8 Slice D4 — the scored run, discriminated by producer kind. The * `kind` is a lineage marker (gemini Q3): it is DERIVED once at the §8 single home * (`resolveCertifyingCorpusProvider`) and carried on the result — never re-read from * the lock downstream (Tenet-20 derive-not-mirror). The authored arm carries the * verdict-inert Gate-2 eligibility emission (§5.3, §1(k)-guarded). */ export type ScoredRun = { kind: 'mined'; verdict: import('@mmnto/totem').WindtunnelVerdict; } | { kind: 'authored'; verdict: import('@mmnto/totem').AuthoredWindtunnelVerdict; gate2: import('@mmnto/totem').Gate2Eligibility; /** * The AUTHORED C1 map (option-(i) ruling, #2291): per-rule positive-control * verdicts proven by the §4 differential AT EMISSION, computed in the * resolver's score closure (the §8 single home). Persist consumes this * INSTEAD of the mined fire-on-target derivation — data-driven, so no * producer-kind branch ever reaches the persist path. */ perRuleControls: Map; }; /** * ADR-112 §8 Slice D4 — what the §8 single dispatch home resolves: the corpus * provider PLUS the producer-kind-bound scorer. Binding the scorer at the resolver * (not branching at the score step) keeps `producerKind` read in ONE place — a * second read at the score step could drift to the mined scorer over an authored * corpus, silently PASSing a culled differential (strategy Q1 ruling 2026-07-01). */ export interface ResolvedCertifyingRun { provider: CertifyingCorpusProvider; /** Bound to this run's producer kind (+ authored substrate). `score(base)` is unconditional at the score step. */ score: (base: import('@mmnto/totem').ScorerInput) => ScoredRun; } /** Internal shape the run command's scorer + persist step consume (engine-agnostic). */ interface EngineResult { mintedRuleIds: string[]; firings: import('@mmnto/totem').RuleFiring[]; groundTruth: Map; positiveControlTargets: Array<{ pr: number; targetRuleId: string; }>; /** C2 — real touched-file exposure (0 for the harness mock). */ filesTouchedInWindow: number; /** Candidate rules eligible for fold-B stamping (empty for the harness mock). */ candidates: import('@mmnto/totem').CompiledRule[]; /** Mining provenance per rule for fold-B (empty for the harness mock). */ provenanceByRule: Map; } /** * `totem spine windtunnel run` * * Reads and validates the lock, derives the freeze proof from git history (C3), * rejects a harness lock when `--phase certifying` is passed (P1), builds the * shared post-image readStrategy, runs the engine (mock for harness phase), * scores the result, and prints the verdict. * * Exit codes: 0 = PASS, 1 = FAIL / HONEST-NEGATIVE / needs-adjudication. */ export declare function runCommand(opts: RunOptions): Promise; type SafeExecFn = typeof import('@mmnto/totem').safeExec; /** * Boolean predicate: is `ancestor` an ancestor of `descendant` in the repo at * `cwd`? `git merge-base --is-ancestor` encodes the answer in its exit code * (0 = yes, 1 = no), so a non-zero exit is a legitimate FALSE, not an error to * swallow. Any other failure (bad ref, repo unreadable) re-throws so it is not * masked as a clean "false". */ export declare function isCommitAncestor(ancestor: string, descendant: string, cwd: string, safeExec: SafeExecFn): boolean; /** * Build a post-image readStrategy (S1/C1). * When lcDir is provided, resolves blobs via `git show :` in * the lc clone. Throws on unresolvable blob for an evaluated added file (C2). * When lcDir is absent, returns null for all files (fail-open — harness mock). */ export declare function buildReadStrategy(lcDir: string | undefined, asOfCommit: string, safeExec: SafeExecFn): (file: string) => Promise; /** * Verify the freeze proof from git history (C3). * `git log --format=%H -- ` must return at least one commit that is * an ancestor of HEAD. The lock blob at that commit must be byte-identical to * the current lock. */ export declare function verifyFreezeProof(lockPath: string, repoRoot: string, safeExec: SafeExecFn): void; /** * Compute gate-1-scoped fixtureSha via `git hash-object` over ALL control dirs * (positive AND negative), so the single fixtureSha protects every fixture * (OQ3 — do NOT extend the existing .totem/tests FIXTURE_DIR). */ export declare function computeFixtureSha(controlDirs: string[], repoRoot: string, safeExec: SafeExecFn): string | null; /** * Verify control-fixture integrity (C6 / §5 no-silent-shrink). The lock ALWAYS * declares a fixtureSha (schema-required) covering ALL control dirs (positive * AND negative), so any missing/empty control dir or hash mismatch is corpus * shrinkage / tampering — it MUST fail loud, never silently pass. */ export declare function verifyControlIntegrity(controlDirs: string[], expectedSha: string, repoRoot: string, safeExec: SafeExecFn): void; /** * Assert corpus completeness (S4, ADR-110 §6): the manifest's `resolvedPrs` must * deep-set-equal `selectionRule(asOfCommit)` re-derived from the offline lc clone. * * - **Harness phase:** warn-only (no real corpus yet) — surfaces accessibility * but skips the re-derivation. * - **Certifying phase:** hard error. Re-derives the code-touching PR set from * lc's squash history and throws on ANY membership/count divergence (§6: a * dropped/added/substituted PR voids the run). Requires a frozen * `codePathClassifier`. */ export declare function assertCorpusCompleteness(lock: WindtunnelLock, lcDir: string, repoRoot: string, safeExec: SafeExecFn): Promise; /** * Enumerate merged (squash) PRs reachable from `asOfCommit` in the lc clone as * `PrMeta`. lc is 100% squash-merge: each ancestor commit's subject carries a * trailing `(#N)`. Commits with no trailing ref are direct-to-main non-PRs and * are SKIPPED (not errors); a malformed trailing ref throws (via `parsePrNumber`). * All git output is CRLF-normalized before parsing (Windows hygiene). */ export declare function enumeratePrMetas(asOfCommit: string, lcDir: string, safeExec: SafeExecFn, helpers: { parsePrNumber: (subject: string) => number | null; parseRevertSha: (body: string) => string | undefined; isBotIdentity: (author: string) => boolean; }): PrMeta[]; /** * Build the certifying-run firings from a corpus's rules + prDiffs — the SHARED * firing-setup the certifying run AND the 5d-iii label-deriver both call, so they * enumerate byte-identical `RuleFiring` labelIds over the same fixtures. The panel * anti-drift mandate: any divergence here (cwd resolution / ruleEngineCtx / the * buildFirings call) would silently break the deriver↔run labelId join and void * the answer key. Encapsulates: * - cwd resolution (`resolveGitRoot(process.cwd())` — NOT raw `process.cwd()`, #1304), * - the per-invocation `ruleEngineCtx` (logger + shield-warn state), * - `buildFirings` (fold-F archived-assert runs inside it), * - the A1 (fold-D) post-dedup labelId-uniqueness hard-gate. * `logPrefix` differentiates the caller in warn output ([WindtunnelRun] / [DeriveLabels]). */ export declare function buildCertifyingFirings(input: { rules: import('@mmnto/totem').CompiledRule[]; prDiffs: import('@mmnto/totem').ResolvedPrDiff[]; readStrategy: (file: string) => Promise; logPrefix: string; }): Promise; /** * Run the REAL engine for the certifying phase (5c-i — #2189 item 1). * * Replaces the mock for `--phase certifying`: drives each resolved-PR diff * through `buildFirings` (core), which runs `enrichWithAstContext` + * `applyAstRulesToAdditions` with the shared post-image `readStrategy` (S1/C1) * and maps every violation to a `RuleFiring` (content-based labelId). Then: * - **fold-F**: `buildFirings` throws if any archived rule is in the scored set * (the engine never runs on an archived rule). * - **A1 (fold-D)**: `assertUniqueFiringLabels` hard-gates labelId uniqueness * BEFORE scoring (throws on collision, surfacing the offending refs). * - **C2**: `filesTouchedInWindow` is the real distinct-file exposure. * - **fold-H**: neg-control firings flow through as `controlKind:'negative'`; * unlabeled firings route to needsAdjudication via the scorer. * * The corpus itself (resolved-PR diffs + active rules + frozen ground truth) is * supplied by the 5c-ii orchestrator via the `certifyingCorpus` seam. 5c-i owns * the deterministic engine; it does NOT fetch/compile live data (out of scope). */ export declare function runCertifyingEngine(lock: WindtunnelLock, readStrategy: (file: string) => Promise, corpusProvider?: CertifyingCorpusProvider): Promise; export {}; //# sourceMappingURL=spine-windtunnel.d.ts.map