import { type PairedTaskOutcome } from './flywheel-sequential-evidence.js'; export declare const RECEIPT_SCHEMA = "ruflo.flywheel-receipt/v1"; export declare const RECEIPT_DOMAIN = "ruflo/flywheel-receipt/v1"; export declare const GENESIS_LEDGER_HEAD: string; export type VerificationKind = 'recomputed' | 'signature-verified' | 'trusted-assertion'; export type ProposerName = 'local' | 'darwin'; export interface ReceiptSignature { algorithm: 'ed25519'; domain: typeof RECEIPT_DOMAIN; publicKeyPem: string; signatureBase64: string; } export interface ResourceEvidence { p95LatencyMicros: number; costMicrosPerTask: number; tokensPerTask: number; failureRate: string; evaluationCostMicros: number; energyMicrojoules?: number; currency: string; } export interface PromotionStatistics { ruleVersion: 'ruflo.flywheel-gate/v1'; relativeLift: string; pairedBootstrapProbability: string; pairedBootstrapDeltaCILow95: string; frozenAnchorRegression: string; iterations: number; seedHex: string; significant: boolean; accepted: boolean; } export interface TermVerification { term: string; verification: VerificationKind; evidenceRef: string; attestor?: string; } export interface EvaluationEvidence { corpusRoles: { selectionTaskIds: string[]; promotionHoldoutTaskIds: string[]; guardTaskIds: string[]; }; verification: Record; canary: Record; } export interface FlywheelReceiptPayload { schemaVersion: typeof RECEIPT_SCHEMA; receiptId: string; lineageId: string; candidateId: string; evaluationRunId: string; baselineRef: string; expectedLedgerHead: string; candidatePolicy: Record; gateVersion: string; policySchemaVersion: string; safetyEnvelopeRef: string; /** Hash-pinned human relevance anchor used for this evaluation (#2840). */ anchorRef?: string; requestedProposer: 'auto' | ProposerName; effectiveProposer: ProposerName; proposerSubstitution?: string; corpusVersion: string; corpusHash: string; baselineScore: string; candidateScore: string; heldOutDeltas: string[]; /** * Task-level paired outcomes behind heldOutDeltas — same order, same length, * per-task delta reproducible from the two scores. Optional in the payload * so pre-existing receipts still verify byte-identically, but the promotion * authority (flywheel-transaction.ts) REQUIRES it by default: aggregate-only * evidence is refused rather than silently falling back to the weaker gate. */ pairedOutcomes?: Array<{ taskId: string; baselineScore: string; candidateScore: string; }>; statistics: PromotionStatistics; gates: Record; resourceEvidence: ResourceEvidence; evidence: EvaluationEvidence; termVerification: TermVerification[]; decision: 'accepted' | 'rejected'; issuedAt: string; expiresAt: string; } export interface FlywheelEvaluationReceipt { payload: FlywheelReceiptPayload; signature?: ReceiptSignature; } export interface CreateReceiptInput { lineageId?: string; evaluationRunId?: string; baselineRef: string; expectedLedgerHead?: string; candidatePolicy: Record; gateVersion?: string; policySchemaVersion?: string; safetyEnvelopeRef: string; anchorRef?: string; requestedProposer?: 'auto' | ProposerName; effectiveProposer?: ProposerName; proposerSubstitution?: string; corpusVersion: string; corpusHash: string; baselineScore: number; candidateScore: number; heldOutDeltas: number[]; /** Task-level paired outcomes behind heldOutDeltas (same order). */ pairedOutcomes?: PairedTaskOutcome[]; frozenAnchorRegression: number; gates: Record; resourceEvidence?: Partial; evidence?: EvaluationEvidence; termVerification?: TermVerification[]; now?: number; ttlMs?: number; privateKeyPem?: string; publicKeyPem?: string; bootstrapIterations?: number; } /** Names present on `value` that the contract does not define, as `unknown field: `. */ export declare function collectUnknownFields(value: unknown, allowed: readonly string[], path: string): string[]; /** * ADR-322C: unknown fields fail verification for a given schema version. * Enforced here rather than delegated to out-of-band schema validation, because * a signature is valid over whatever the producer canonicalized — including * fields the contract never defined — so a permissive verifier lets a producer * attach arbitrary signed data that still verifies cleanly. */ export declare function collectUnknownReceiptFields(receipt: FlywheelEvaluationReceipt): string[]; /** * RFC-8785-compatible for the JSON domain accepted above: ECMAScript primitive * serialization plus recursively sorted UTF-16 property names. */ export declare function canonicalizeJcs(value: unknown): string; export declare function sha256Ref(value: string | Buffer): string; /** * Enforce ADR-322C rule 2 / conformance-checklist A3 over a receipt payload: * "Every fractional value is a canonical decimal string, not a binary float." * * This lives at the RECEIPT boundary rather than inside `canonicalizeJcs`, * which is shared with the proposer envelope (`flywheel-proposer.ts`) and the * promotion ledger (`flywheel-transaction.ts`) — structures the contract does * not govern. A first attempt put the check in the canonicalizer and broke * those callers, which is the reason the scope is spelled out here. * * Integers and scaled integers stay JSON numbers (currency micros, durations, * iteration counts). A fractional JSON number anywhere in the payload is a * contract violation, and the error names the path — the original bug * (ruvnet/ruflo#3229) needed a live fixture to find precisely because neither * verifier said which field was wrong. */ export declare function assertReceiptNumberDomain(value: unknown, path?: string): void; export declare function policyCandidateId(policy: Record): string; /** UUIDv7 with a 48-bit millisecond timestamp and RFC-4122 variant bits. */ export declare function uuidV7(now?: number): string; /** * Encode an opaque policy object so every fractional value is a scale-12 * decimal string, per ADR-322C rule 2 and conformance-checklist A3. * * `candidatePolicy` is declared "Opaque to this contract; its shape is owned by * policySchemaVersion. Must still satisfy the ADR-322C number rules" — a rule * the JSON Schema cannot express for an opaque object, so nothing enforced it * and the producer wrote binary floats (`{"alpha": 0.3, "mmrLambda": 0.5}`). * Ruflo's own verifier accepted them because `assertJsonValue` only checked * finite-and-not-negative-zero; autogenous's stricter verifier correctly * rejected the receipt (ruvnet/ruflo#3229, ruvnet/autogenous#15). * * Integers stay JSON numbers and only non-integers are encoded, which is what * the contract's own example shows: `{"hnswEf": 128, "hybridWeight": "0.65"}`. * Recurses through nested objects and arrays, because "every fractional value" * is not limited to the top level. */ export declare function encodePolicyFractions(value: unknown): unknown; export declare function computePromotionStatistics(input: { baselineScore: number; candidateScore: number; heldOutDeltas: number[]; frozenAnchorRegression: number; corpusHash: string; candidateId: string; baselineRef: string; evaluationRunId: string; iterations?: number; metricEpsilon?: number; }): PromotionStatistics; export declare function createFlywheelReceipt(input: CreateReceiptInput): FlywheelEvaluationReceipt; export interface ReceiptVerification { valid: boolean; signed: boolean; errors: string[]; } export declare function verifyFlywheelReceipt(receipt: FlywheelEvaluationReceipt, trustedPublicKeys?: Set): ReceiptVerification; //# sourceMappingURL=flywheel-receipt.d.ts.map