import { type PromotionVerdict, type AcceptResult } from './harness-benchmark.js'; import { SEQUENTIAL_EVIDENCE_VERSION } from './flywheel-sequential-evidence.js'; import { type ProvenConfigManifest } from '../config/proven-config.js'; /** * The promotion rule is versioned so a receipt pins exactly which semantics * decided it. v1+sig = the accept() conjunction AND a statistical-significance * term: the per-held-out-task deltas must have a positive one-sided 95% bootstrap * lower bound, so a small-N mean gain can't ride on noise. The canary term is a * SEPARATE deployment-safety signal (a distinct slice), not held-out dominance. * * v2+seq (ADR-381 §3) adds a third conjunct: an anytime-valid sequential- * evidence e-process over the holdout's paired per-task scores, judged at the * alpha allocated to this bundle's position in the lineage's adaptive test * stream (alpha_k = alphaTotal · 6/(π²k²)). The rule version is pinned PER * BUNDLE, so a lineage may contain both v1 and v2 bundles and each replays * under its own recorded semantics. */ export declare const PROMOTION_RULE_VERSION = "accept/v1+sig"; export declare const PROMOTION_RULE_VERSION_V2 = "accept/v2+seq"; export declare const PROOF_LABEL = "single-round proof-of-mechanism"; export declare const NOT_CLAIMS: readonly ["not flywheel proof", "not compounding learning", "not production learning"]; export interface HoldoutTask { taskId: string; baselineScore: number; candidateScore: number; } export interface DecisionReceipt { promotionRuleVersion: string; verdictInputs: PromotionVerdict; result: AcceptResult; significant: boolean; deltaCILow: number; promoted: boolean; reason: string; } export interface ShadowRegistration { registrationId: string; state: 'shadow'; served: false; candidateManifestHash: string; registeredAt: number; } export interface CostReceipt { usd: number; llmCalls: number; tier: string; notes: string; } /** Multi-dimensional deltas vs the parent — distinguishes *why* a change is (un)safe. */ export interface ChangeDeltas { benchmark: number; security: number; cost: number; humanRelevance?: number; } /** * Causal promotion record (not just provenance). Answers *why* a candidate won — * and, aggregated across the lineage, *which mutation classes* reliably pay off. * This is what turns the lineage from an audit trail into a knowledge base. */ export interface PromotionRecord { parentManifestHash: string | null; candidateManifestHash: string; mutationClass: string; mutationSummary: string; deltas: ChangeDeltas; decisionReceipt: DecisionReceipt; } /** Regression ancestry — a rejected candidate records the gate that killed it + its ancestor. */ export interface RegressionRecord { candidateManifestHash: string; ancestor: string | null; mutationClass: string; failureCause: 'holdout' | 'security' | 'drift' | 'replay' | 'governance' | 'canary' | 'significance' | 'sequential'; failedTerms: string[]; } /** * The v2 sequential-evidence term, embedded so `verifyReceiptBundle` can * replay it from the bundle's own holdout: the recorded testIndex/alphaTotal/ * lambda fully determine the threshold, and the e-value recomputes from the * embedded per-task scores. */ export interface SequentialEvidenceRecord { version: typeof SEQUENTIAL_EVIDENCE_VERSION; testIndex: number; alphaTotal: number; lambda: number; alphaAllocated: number; eValue: number; threshold: number; informativePairs: number; significant: boolean; } export interface EvolveReceiptBundle { label: typeof PROOF_LABEL; disclaimers: typeof NOT_CLAIMS; generation: number; parent: string | null; branch: string; kind: 'synthetic' | 'real'; createdAt: number; inputHoldoutHash: string; baselineManifestHash: string; candidateManifestHash: string; meetsPromotionRule: { version: string; result: boolean; }; /** Present iff the bundle was decided under accept/v2+seq (ADR-381 §3). */ sequentialEvidence?: SequentialEvidenceRecord; decisionReceipt: DecisionReceipt; shadow: ShadowRegistration | null; costReceipt: CostReceipt; mutationClass: string; mutationSummary: string; deltas: ChangeDeltas; humanEvalHash?: string; promotion: PromotionRecord | null; regression: RegressionRecord | null; holdout: HoldoutTask[]; baselineManifest: ProvenConfigManifest; candidateManifest: ProvenConfigManifest; } /** Classify a policy mutation by which fields changed → a repeatable mutation CLASS + a diff summary. */ export declare function classifyMutation(baseline: Record, candidate: Record): { mutationClass: string; mutationSummary: string; }; export interface AssembleOpts { generation: number; parent: string | null; branch: string; now: number; kind: 'synthetic' | 'real'; cost: { tier: string; notes: string; }; redblue?: 'PASS' | 'FAIL' | 'SKIPPED'; drift?: number; canaryRollbackRate?: number; humanRelevanceDelta?: number; humanEvalHash?: string; layer?: string; corpus?: string; /** * ADR-381 §3 — supply to decide the bundle under accept/v2+seq: the bundle's * 1-based position in the lineage's adaptive test stream, plus optional * alpha/lambda overrides. Omit for legacy v1+sig semantics. */ sequential?: { testIndex: number; alphaTotal?: number; lambda?: number; }; } /** * Assemble a receipt bundle from a holdout + configs. This is the SHARED core: * the synthetic proof and a REAL measured round produce byte-identical bundle * structure and run the SAME versioned accept() — so `verifyReceiptBundle` * replays a real bundle exactly as it replays the synthetic fixture. */ export declare function assembleBundle(baseline: Record, candidate: Record, holdout: HoldoutTask[], o: AssembleOpts): EvolveReceiptBundle; /** * Build a REAL evolve-round receipt bundle from MEASURED holdout scores (live * retrieval over a frozen anchor). Same gate, same replayability as the * synthetic proof — but `kind: 'real'` and the scores come from actual runs. * `redblue` should be 'FAIL' if the candidate regressed a frozen security/anchor * slice; drift from real distribution shift. $0 (no LLM/network on this path). */ export declare function runRealEvolveRound(opts: { baseline: Record; candidate: Record; holdout: HoldoutTask[]; generation: number; parent: string | null; branch?: string; now: number; redblue?: 'PASS' | 'FAIL' | 'SKIPPED'; drift?: number; canaryRollbackRate?: number; humanRelevanceDelta?: number; humanEvalHash?: string; corpus: string; sequential?: AssembleOpts['sequential']; }): EvolveReceiptBundle; /** * Run ONE deterministic synthetic evolve round and produce the receipt bundle. * `now` is injected (no Date in the pure path) for reproducible fixtures. * The default scenario is a strict Pareto improvement (candidate ≥ baseline on * every task, > on the mean) so the full PROMOTE→SHADOW path is exercised; pass * `regress: true` to exercise the REJECT path instead. */ export declare function runSyntheticProofRound(opts?: { now: number; generation?: number; regress?: boolean; parent?: string | null; branch?: string; baseline?: Record; candidate?: Record; }): EvolveReceiptBundle; export interface VerifyReport { valid: boolean; hashChecks: { inputHoldout: boolean; baselineManifest: boolean; candidateManifest: boolean; }; recomputed: { baselineHeldOut: number; candidateHeldOut: number; canaryRollbackRate: number; decision: AcceptResult; }; decisionMatches: boolean; ruleVersionMatches: boolean; noAutoServe: boolean; causalConsistent: boolean; explanation: string; mismatches: string[]; } /** * Independently verify a receipt bundle WITHOUT trusting any service log: rehash * the embedded holdout + manifests, recompute the held-out means + canary rate * from the embedded per-task scores, RE-RUN the same versioned accept(), and * confirm the recomputed decision equals the recorded one. Also confirms the * SHADOW registration is not served (no auto-serve). Pure; never throws. */ export declare function verifyReceiptBundle(bundle: EvolveReceiptBundle): VerifyReport; export interface LineageTelemetry { generations: number; candidatesEvaluated: number; promotions: number; rejections: number; cumulativeHeldOutImprovement: number; rootHash: string | null; branches: string[]; lineageIntact: boolean; allReplayable: boolean; nodes: Array<{ generation: number; branch: string; promoted: boolean; parent: string | null; candidateManifestHash: string; mutationClass: string; delta: number; replayable: boolean; }>; problems: string[]; } /** * Reconstruct + audit a lineage DAG. Independently replays every bundle and * checks the graph invariants back to the immutable root. Pure; never throws. */ export declare function reconstructLineage(bundles: EvolveReceiptBundle[]): LineageTelemetry; export interface MutationStat { mutationClass: string; attempts: number; promotions: number; meanDelta: number; } /** * Aggregate per-mutation-class effectiveness across a lineage. After enough * generations the optimizer can bias toward classes with higher historical * payoff — meta-learning grounded in evidence, not intuition. */ export declare function mutationEffectiveness(bundles: EvolveReceiptBundle[]): MutationStat[]; export type PlateauStatus = 'insufficient-data' | 'active' | 'local-optimum' | 'noisy-benchmark' | 'optimizer-failure'; export interface PlateauReport { status: PlateauStatus; window: number; medianImprovement: number; promotionRate: number; varianceShrinking: boolean; candidateVariance: number; rationale: string; } /** * Distinguish local optimum vs noisy benchmark vs optimizer failure — rigorously, * not by intuition. Over a rolling window: near-zero median improvement AND low * promotion rate is a plateau; shrinking candidate variance ⇒ converged * (local optimum); high, non-shrinking variance ⇒ the benchmark is noisy; low * variance with no promotions ⇒ the optimizer stopped exploring (failure). */ export declare function detectPlateau(bundles: EvolveReceiptBundle[], opts?: { window?: number; epsilon?: number; maxPromotionRate?: number; }): PlateauReport; //# sourceMappingURL=evolve-proof.d.ts.map