import { z } from 'zod'; import { type PrMeta, type PrSetDiff } from './selection-rule.js'; /** * ADR-111 §5 — the frozen split artifact, committed before extraction. The * concrete `cutIndex` is the deferred window-open scalar (Deferred Decisions); * the field is required in the committed artifact, only its value is deferred. */ export declare const SplitArtifactSchema: z.ZodEffects; /** The NEWER held-out segment — control evaluation. Controls are tags within this. */ heldOutPrs: z.ZodArray; /** Explicitly enumerated drops (the atomic revert pairs). */ excludedPrs: z.ZodArray; /** Positive controls — a designated subset (tag) of `heldOutPrs`, never a separate cover bucket. */ positiveControlPrs: z.ZodArray; /** Negative controls — a designated subset (tag) of `heldOutPrs`. */ negativeControlPrs: z.ZodArray; splitRule: z.ZodObject<{ /** Human-readable predicate expression that generated the corpus (mirrors the windtunnel lock's `selectionRule.predicate`). */ predicate: z.ZodEffects; /** * Forward-chronological ancestry cut: `trainPrs` = the `cutIndex` OLDEST * corpus PRs (ancestry order), `heldOutPrs` = the newer remainder. Concrete * value deferred to window-open (ADR-111 Deferred Decisions). */ cutIndex: z.ZodNumber; }, "strip", z.ZodTypeAny, { predicate: string; cutIndex: number; }, { predicate: string; cutIndex: number; }>; /** * ADR-112 §5.1 Slice D5 — the mechanical FREEZE INSTANT, stamped by the authored * producer at materialize. Full ISO-8601 (offset-bearing); the Q3 temporal gate * (`assertAuthoredFreezePreconditions`) asserts this precedes every effective * authoring-ledger `authoredAt` — §5.1's "frozen BEFORE authoring" embargo made * MECHANICAL, not attestational. Dereferenced from the split artifact (Tenet-20), * never recomputed. Additive-optional, no `.default()`: a mined/legacy split omits * it and parses/serializes BYTE-UNCHANGED. */ frozenAt: z.ZodOptional; }, "strip", z.ZodTypeAny, { asOfCommit: string; trainPrs: number[]; heldOutPrs: number[]; excludedPrs: number[]; positiveControlPrs: number[]; negativeControlPrs: number[]; splitRule: { predicate: string; cutIndex: number; }; frozenAt?: string | undefined; }, { asOfCommit: string; trainPrs: number[]; heldOutPrs: number[]; excludedPrs: number[]; positiveControlPrs: number[]; negativeControlPrs: number[]; splitRule: { predicate: string; cutIndex: number; }; frozenAt?: string | undefined; }>, { asOfCommit: string; trainPrs: number[]; heldOutPrs: number[]; excludedPrs: number[]; positiveControlPrs: number[]; negativeControlPrs: number[]; splitRule: { predicate: string; cutIndex: number; }; frozenAt?: string | undefined; }, { asOfCommit: string; trainPrs: number[]; heldOutPrs: number[]; excludedPrs: number[]; positiveControlPrs: number[]; negativeControlPrs: number[]; splitRule: { predicate: string; cutIndex: number; }; frozenAt?: string | undefined; }>; export type SplitArtifact = z.infer; /** Thrown when `resolveSplit` cannot produce a clean three-way disjoint cover (Tenet 4, fail-loud). */ export declare class SplitCoverError extends Error { readonly result: SplitCoverResult; constructor(result: SplitCoverResult); } /** Structured result of the §5/§8 split-ledger mechanical check. `ok` iff every diagnostic list is empty. */ export interface SplitCoverResult { ok: boolean; /** * Cover vs the frozen corpus, direction-disambiguated so each side falsifies * its own clause: `missing` = a corpus PR assigned to no slice (FM(g), silent * drop); `extra` = a slice PR outside the corpus (FM(d), out-of-corpus member). */ cover: PrSetDiff; /** Pairwise PR# intersections of {train, heldOut, excluded} that must be empty (the `⊎` disjointness). */ overlaps: { trainHeldOut: number[]; trainExcluded: number[]; heldOutExcluded: number[]; }; /** Control PRs not contained in `heldOutPrs` — controls must be tags WITHIN heldOut, not a separate bucket. */ controlsOutsideHeldOut: number[]; /** PRs tagged as BOTH a positive and a negative control — a PR cannot be both (per-rule control coherence). */ controlOverlap: number[]; /** Merge-commit SHAs appearing in more than one slice — disjoint by merge-commit, not only PR# (revert/target straddle guard). */ mergeCommitCollisions: string[]; } /** * The §8 split-ledger check: verifies the split is a three-way disjoint cover of * `corpus` (= `selectionRule(asOfCommit)`), that the controls are tags within * `heldOutPrs`, and that the slices are disjoint by merge-commit (not only PR#). * Pure; the harness asserts `ok` and reads the per-field diffs to pin the exact * Falsifying-Metric clause (FM(d) extra / FM(g) missing). */ export declare function validateSplitCover(split: SplitArtifact, corpus: number[], mergeCommitByPr: ReadonlyMap): SplitCoverResult; /** * Produce a frozen split from the resolved corpus by the forward-chronological * ancestry cut. `corpus` is `selectionRule(asOfCommit)` (the cover base); * `orderedNewestFirst` is the same ancestry enumeration `resolveSelectionRule` * consumes (`git log --topo-order`, newest-first) and MUST cover the corpus. * `excludedPrs` (the atomic revert pairs) are removed from train/heldOut but * remain in the cover. Validates the result and throws `SplitCoverError` on any * cover/disjointness violation (Tenet 4) — a malformed split never freezes. * * CONTRACT (corpus-scope model A, confirmed by totem-codex's #2200 review; pending * strategy-claude's final §5 word): `corpus` is the cover BASE that INCLUDES the * PRs later assigned to `excludedPrs` — i.e. `selectionRule` is resolved here with * reverts retained, and `excludedPrs` enumerates them explicitly, so * `train ⊎ heldOut ⊎ excluded == corpus` holds and every `excludedPr` is a corpus * member. (The alternative — `selectionRule(asOfCommit)` pre-excludes reverts yet * the split still records them in `excludedPrs` — is NOT supported by the current * schema, which rejects excluded PRs outside the corpus; revisit only if strategy * pins that model.) The fail-loud `excludedPrs ⊆ corpus` guard below enforces this. */ export declare function resolveSplit(params: { asOfCommit: string; corpus: number[]; orderedNewestFirst: number[]; excludedPrs: number[]; cutIndex: number; positiveControlPrs?: number[]; negativeControlPrs?: number[]; predicate: string; mergeCommitByPr: ReadonlyMap; /** ADR-112 §5.1 D5 — the mechanical freeze instant (full ISO-8601), stamped by the authored producer. Omitted ⇒ mined/legacy split (byte-unchanged). */ frozenAt?: string; }): SplitArtifact; /** Re-export for callers building the `mergeCommitByPr` map from enumerated metas. */ export declare function mergeCommitMap(metas: PrMeta[]): Map; //# sourceMappingURL=split.d.ts.map