export type CinemaSha256 = `sha256:${string}`; export interface CinemaIdentityAnchor { assetId: string; path: string; contentHash: CinemaSha256; identityBearingFaceCount: 1; locked: true; } export interface CinemaBodyPlate { assetId: string; path: string; contentHash: CinemaSha256; view: 'front' | 'back'; headTreatment: 'removed'; identityBearingFaceCount: 0; faceFragmentCount: number; maskArtifactId: string; garmentBoundaryEvidence: { maskContentHash: CinemaSha256; requiredFeatures: string[]; preservedFeatures: string[]; evidenceIds: string[]; }; garmentBoundaryStatus: 'pass' | 'fail'; } export interface CinemaCompositeCharacterSheet { assetId: string; path: string; contentHash: CinemaSha256; template: 'single-face-front-back-v1'; identityBearingFaceCount: number; componentAssetIds: string[]; } export interface CinemaCharacterSheetArtifact { schemaVersion: 1; projectSlug: string; characterVersionId: string; characterName: string; generatedAt: string; identityAnchor: CinemaIdentityAnchor; bodyPlates: CinemaBodyPlate[]; compositeSheet: CinemaCompositeCharacterSheet; qc: { status: 'pass' | 'fail'; automatedCheckedAt: string; issues: string[]; humanReview: { status: 'approved' | 'rejected' | 'pending'; reviewerId: string; reviewedAt: string; evidenceIds: string[]; }; }; } export type CinemaReferenceRole = | 'identity_face' | 'body_front_headless' | 'body_back_headless' | 'wardrobe' | 'silhouette' | 'environment' | 'lighting' | 'prop' | 'vehicle' | 'component' | 'start_state' | 'end_state' | 'motion_donor' | 'voice_track'; /** * What a reference file IS. Absent means `image` — every pack written before * video/audio references existed stays valid and means what it meant. A * `motion_donor` is a `video`, a `voice_track` is an `audio`; the provider * adapter forwards each kind on its own flag and counts each against its own cap. */ export type CinemaReferenceMediaKind = 'image' | 'video' | 'audio'; export type CinemaReferenceVisibilityIntent = | 'visible_subject' | 'visible_environment' | 'lighting_only' | 'offscreen_context' | 'start_state' | 'end_state' | 'component_detail'; export interface CinemaReferenceEntry { assetId: string; path: string; contentHash: CinemaSha256; role: CinemaReferenceRole; mediaKind?: CinemaReferenceMediaKind; visibilityIntent: CinemaReferenceVisibilityIntent; subjectId: string; characterVersionId?: string; identityBearingFaceCount: 0 | 1; identityVariant?: 'canonical' | 'profile' | 'expression' | 'injury'; state?: { group: string; value: string; }; } export interface CinemaMechanicalTransition { subjectId: string; stateGroup: string; startValue: string; endValue: string; trigger: string; direction: string; orderedSteps: string[]; interaction: string; startSeconds: number; endSeconds: number; } export interface CinemaReferencePackArtifact { schemaVersion: 1; projectSlug: string; packId: string; shotId: string; generatedAt: string; references: CinemaReferenceEntry[]; transitions: CinemaMechanicalTransition[]; referenceBudget: { maximum: number; actual: number; withinLimit: boolean; }; } export type CinemaAudioMode = 'required' | 'forbidden' | 'optional'; export interface CinemaActionBeat { order: number; startSeconds: number; endSeconds: number; description: string; timingMode: 'realtime' | 'slow-motion' | 'speed-ramp' | 'hold'; transition: 'continuous' | 'hard-cut' | 'match-cut' | 'none'; } export interface CinemaShotManifestArtifact { schemaVersion: 1; projectSlug: string; shotId: string; sceneIndex: number; ordinal: number; durationSeconds: number; referencePackId: string; generatedAt: string; story: { act: 'setup' | 'confrontation' | 'resolution'; beatId: string; scenePurpose: string; characterObjective: string; expectedChange: string; }; visualLaw: { prefix: string; prefixHash: CinemaSha256; overrides: Array<{ field: string; from: string; to: string; reason: string; }>; }; camera: { shotSize: 'extreme-wide' | 'wide' | 'medium' | 'close-up' | 'extreme-close-up'; position: string; movement: string; stability: 'locked' | 'controlled' | 'handheld' | 'violent'; }; actionBeats: CinemaActionBeat[]; occupancy: { characterIds: string[]; vehicleIds: string[]; propIds: string[]; }; audio: { music: CinemaAudioMode; dialogue: CinemaAudioMode; sfx: CinemaAudioMode; ambience: CinemaAudioMode; intentionalSilence: boolean; notes: string; }; compiledPrompt: { text: string; contentHash: CinemaSha256; }; providerParameters: { contentHash: CinemaSha256; values: Record; }; } export type CinemaAttemptStatus = | 'prepared' | 'dry-run-complete' | 'submitted' | 'completed' | 'failed' | 'cancelled'; export interface CinemaGenerationAttempt { attemptId: string; shotId: string; parentAttemptId: string | null; payloadHash: CinemaSha256; routeId: string; status: CinemaAttemptStatus; preparedAt: string; completedAt?: string; providerJobId?: string; changedVariables: string[]; failureTags: string[]; evidenceIds: string[]; estimatedCost: { currency: string; amount: number }; actualCost: { currency: string; amount: number }; } export interface CinemaPromotionEvent { promotionId: string; shotId: string; attemptId: string; reviewerId: string; editorialSlot: string; decidedAt: string; supersedesPromotionId: string | null; evidenceIds: string[]; storyPurposeVerified: true; } export interface CinemaAttemptOutcome { outcomeId: string; attemptId: string; shotId: string; queueTaskId: string; executionHash: CinemaSha256; payloadHash: CinemaSha256; status: 'completed'; observedAt: string; providerJobId: string; media: { path: string; contentHash: CinemaSha256; byteLength: number; }; actualCost: { currency: string; amount: number }; evidenceIds: string[]; contentHash: CinemaSha256; } export interface CinemaGenerationLedgerArtifact { schemaVersion: 1; projectSlug: string; generatedAt: string; attempts: CinemaGenerationAttempt[]; outcomes?: CinemaAttemptOutcome[]; promotions: CinemaPromotionEvent[]; } export interface CinemaWalkingSkeletonBundle { characterSheets: CinemaCharacterSheetArtifact[]; referencePacks: CinemaReferencePackArtifact[]; shotManifests: CinemaShotManifestArtifact[]; ledger: CinemaGenerationLedgerArtifact; } export interface CinemaContractIssue { code: string; path: string; message: string; } export interface CinemaContractValidation { ok: boolean; issues: CinemaContractIssue[]; }