/** * Run-contract persistence: a per-scene snapshot of the EXACT resolved submit * payload at produce/execute time (prompt + referencePaths + referenceRole + * inputKind + duration + characters), plus the run-level execution profile and * route. This is the FROZEN baseline the live run dashboard diffs the CURRENT * contract against — when an `@tag` silently hijacks the references between * submit and a later re-render, the dashboard paints the card red. * * Distinct from scene-candidates (status + job id) and the execution-report * (run outcome): this artifact records "what was actually sent to the model". * It is purely additive — never read by the execution path, only by the run * dashboard — so an absent file just degrades the dashboard's diff alarm * gracefully (like every other optional portal artifact). * * Written via `writeTextFileAtomic` (not the typed `writeArtifact` helper) so it * stays decoupled from the `VideoStageArtifactName` union; allowlisted in * `scripts/check-artifact-schema-coverage.mjs` against * `schemas/video/artifacts/run-contract.schema.json`. */ import type { ProviderWirePreview } from './provider-wire-preview.js'; import type { ProviderRouteId } from './provider-platform/types.js'; import type { VideoExecutionPayload, VideoExecutionTask } from './types.js'; /** A reference slot as the contract freezes it: the human slot plan only * (`slot`/`role`/`label`/`path`). Discovery-side slots carry more (`status`, * `characterName`, `assetUri`); both sides go through this so the diff compares * the same shape in the same key order. Slot ORDER is kept — a reorder is real. */ export interface RunContractReferenceSlot { slot: string; role: string; label: string; path?: string; } export declare function canonicalReferenceSlot(slot: { slot: string; role: string; label: string; path?: string; }): RunContractReferenceSlot; /** * The BYTES behind one submitted reference. Every other identity here covers a * reference's PATH: replace `keyframes/scene-3.png` with different pixels at the * same path and the prompt, the paths and the slot plan all still match, so the * dashboard said "unchanged" about a submit that no longer matches what was * reviewed. Only a local file has bytes to measure; an `Asset://` URI or a hosted * URL is recorded as `remote-unverified` and a file that was not there as * `missing` — the statuses of film-reference-evidence.ts, reused rather than * reclassified. */ export interface RunContractReferenceHash { path: string; status: 'hashed' | 'missing' | 'remote-unverified'; sha256?: string; } export declare function canonicalReferenceHash(entry: RunContractReferenceHash): RunContractReferenceHash; /** The files one task submits: its reference array plus its end keyframe, in order, once each. */ export declare function submittedReferenceFiles(task: Pick): string[]; /** * Hash what each task is about to submit. I/O, so it is NOT part of the pure * builder: `execute.ts` calls this first and hands the result to * `buildRunContract`. Paths resolve against the project directory (absolute * paths resolve to themselves). * * NEVER THROWS. The film-reference hasher rethrows anything but ENOENT — a * directory in the reference list, EACCES, a symlink loop — and that throw is * load-bearing where it gates a render (`assertFilmReferenceEvidence`). Here it * would be fatal in the wrong way: this runs first inside the best-effort block * that writes the run contract, so one unreadable reference silently cost the * WHOLE contract, on a dry run most of all, which is the review surface. A scene * that cannot be measured is simply left out: it freezes no hashes, exactly like * a contract written before hashes existed, and never alarms. */ export declare function captureSubmittedReferenceHashes(projectDir: string, tasks: ReadonlyArray>): Promise>; export interface RunContractScene { sceneIndex: number; /** The candidate created for THIS submission (candidate mode), else null. */ candidateId: string | null; externalJobId: string | null; submittedAt: string; /** The SUBMITTED contract snapshot (frozen; the diff baseline). */ submittedPrompt: string; /** Resolved Asset://, @tag, chain-seed, voice — the exact array sent. */ submittedReferencePaths: string[]; /** The ordered slot plan the packet bound (present when a filmmaking-prompts * packet drove the task). */ submittedReferenceSlots?: RunContractReferenceSlot[]; /** sha256 of each submitted reference FILE, in submit order (see * RunContractReferenceHash). Absent on a contract written before this existed. */ submittedReferenceHashes?: RunContractReferenceHash[]; submittedReferenceRole?: 'character' | 'keyframe'; submittedInputKind: 'text' | 'image' | 'video'; submittedDurationSeconds?: number; submittedCharacters: string[]; submittedChainedFromCandidateId?: string; /** * Provider settings frozen at submit. `submittedResolution` and * `submittedPromptPacketVariant` come from the packet and the dashboard * re-derives them, so they can drift; the rest (end keyframe, voice preset, * V2V media id, first-frame, Flow character refs) are resolved inside * execution-runtime, so they are provenance — what was sent — not a diff. */ submittedResolution?: string; submittedPromptPacketVariant?: string; submittedEndKeyframePath?: string; submittedVoicePreset?: string; submittedReferenceVideoMediaId?: string; submittedFirstFrame?: boolean; submittedCharacterRefs?: string[]; /** * The EXACT wire body the route's transport would send for this scene, from * the transport's own planner (provider-wire-preview.ts) — or the planner's * refusal, verbatim, so a dry run shows the refusal before any spend. Absent * on routes without a planner and on contracts written before this existed. * Provenance, not part of `contractHash`: it is derived from the fields that * hash already covers. */ submittedProviderWire?: ProviderWirePreview; /** sha256 of the stable-stringified contract fields — the diff fast-path. */ contractHash: string; } export interface RunContractArtifact { schemaVersion: 1; projectSlug: string; routeId: ProviderRouteId; /** The submit timestamp identifying this run (= report.generatedAt). */ runId: string; recordedAt: string; executionProfile: { aspectRatio: '16:9' | '9:16' | '1:1'; quality: 'fast' | 'quality'; resolution: '720p' | '1080p'; generateAudio: boolean; outputCount: number; veoModel?: 'fast' | 'quality' | 'lite' | 'free' | 'omni-flash'; }; scenes: RunContractScene[]; } export declare function runContractPathFor(root: string, slug: string): string; /** * Stable canonical hash of the per-scene contract fields used for the diff * fast-path. The field order is fixed and characters are sorted (set semantics); * referencePaths keep ORDER (a reorder is a meaningful divergence). Excludes * `submittedAt`/`candidateId`/`externalJobId` (run-instance metadata, not the * contract). */ export declare function hashRunContractScene(fields: { prompt: string; referencePaths: string[]; referenceSlots?: RunContractReferenceSlot[]; referenceRole?: 'character' | 'keyframe'; inputKind: 'text' | 'image' | 'video'; durationSeconds?: number; characters: string[]; chainedFromCandidateId?: string; resolution?: string; promptPacketVariant?: string; endKeyframePath?: string; voicePreset?: string; referenceVideoMediaId?: string; firstFrame?: boolean; characterRefs?: string[]; referenceHashes?: RunContractReferenceHash[]; }): string; export interface BuildRunContractInput { payload: VideoExecutionPayload; submittedAt: string; /** sceneIndex → candidateId for this submission (candidate mode). */ candidatesByScene?: Array<{ sceneIndex: number; candidateId: string; }>; externalJobId?: string | null; /** From `captureSubmittedReferenceHashes` — measured before this pure builder runs. */ referenceHashes?: Array<{ sceneIndex: number; entries: RunContractReferenceHash[]; }>; /** From `previewProviderWire` — computed before this pure builder runs. */ providerWire?: Map; } /** Build the run-contract artifact from a just-submitted payload. PURE. */ export declare function buildRunContract(input: BuildRunContractInput): RunContractArtifact; export declare function writeRunContract(root: string, slug: string, artifact: RunContractArtifact): Promise; /** Read `artifacts/run-contract.json` (null when absent or malformed). */ export declare function readRunContract(root: string, slug: string): Promise; //# sourceMappingURL=run-status.d.ts.map