export const PRODUCTION_CONTRACT_VERSIONS = { sourceAnalysis: 'source_analysis_v1', adaptationBible: 'adaptation_bible_v1', episodePlan: 'episode_plan_v1', sceneScript: 'scene_script_v1', assetPlan: 'asset_plan_v1', sceneGeography: 'scene_geography_v1', shotExecution: 'shot_execution_v1', stageQuality: 'stage_quality_v1', stageReviewDelta: 'stage_review_delta_v1', shotQcDelta: 'shot_qc_delta_v1', promptRule: 'prompt_rule_v1' } as const; export type ProductionContractVersion = (typeof PRODUCTION_CONTRACT_VERSIONS)[keyof typeof PRODUCTION_CONTRACT_VERSIONS]; export interface SourceRefV1 { source_type: 'novel_snapshot' | 'chapter' | 'story_bible' | 'memory' | 'approved_decision'; source_id: string; locator?: string; quote?: string; } export interface SourceFactRefV1 { fact: string; source_refs: SourceRefV1[]; } export interface SourceCharacterFactV1 { character_id?: string; name: string; role: string; goal: string; fear?: string; secrets: string[]; state: string; source_refs: SourceRefV1[]; } export interface SourceEventV1 { id: string; order: number; event: string; participants: string[]; consequence: string; source_refs: SourceRefV1[]; } export interface SourceAnalysisSpecV1 { schema_version: typeof PRODUCTION_CONTRACT_VERSIONS.sourceAnalysis; source_snapshot_id: string; premise: string; genre_promises: string[]; timeline: SourceEventV1[]; characters: SourceCharacterFactV1[]; relationships: SourceFactRefV1[]; world_rules: SourceFactRefV1[]; conflicts: SourceFactRefV1[]; mysteries: SourceFactRefV1[]; emotional_assets: SourceFactRefV1[]; visual_assets: SourceFactRefV1[]; immutable_facts: SourceFactRefV1[]; uncertain_facts: SourceFactRefV1[]; source_refs: SourceRefV1[]; } export interface AdaptationDecisionV1 { id: string; operation: 'keep' | 'compress' | 'merge' | 'reorder' | 'remove' | 'add'; source_refs: SourceRefV1[]; target: string; reason: string; impact: string[]; continuity_risk: string; approval_status: 'draft' | 'approved' | 'rejected'; } export interface HookPolicyV1 { mode: 'aggressive_0_3s' | 'suspense_0_5s' | 'cinematic_0_8s'; max_setup_ms: number; require_visible_question: boolean; require_episode_payoff: boolean; max_repeated_hook_type: number; } export interface DialoguePolicyV1 { language: string; target_chars_per_second: number; preserve_confirmed_lines: boolean; require_listener_reaction: boolean; } export interface AdaptationBibleSpecV1 { schema_version: typeof PRODUCTION_CONTRACT_VERSIONS.adaptationBible; source_analysis_version_id: string; format: { orientation: '16:9'; target_episode_seconds: number; episode_count_range: [number, number]; audience: string; }; genre_contract: string; tone_contract: string; protagonist_contract: string; central_dramatic_question: string; main_arc: string; character_arcs: Array<{ character_id: string; arc: string }>; season_beats: Array<{ id: string; beat: string; consequence: string }>; adaptation_decisions: AdaptationDecisionV1[]; hook_policy: HookPolicyV1; dialogue_policy: DialoguePolicyV1; visual_policy: string[]; sound_policy: string[]; prohibited_changes: string[]; source_refs: SourceRefV1[]; } export type HookTypeV1 = | 'crisis' | 'result_first' | 'identity_contrast' | 'relationship_break' | 'impossible_event' | 'secret_exposure' | 'countdown' | 'forced_choice' | 'high_value_promise' | 'previous_hook_payoff'; export interface HookTimelineBeatV1 { start_ms: number; end_ms: number; visual: string; audio: string; information_gain: string; } export interface OpeningHookSpecV1 { type: HookTypeV1; secondary_type?: HookTypeV1; viewer_question: string; character_at_risk: string[]; stakes: string; visual_event: string; audio_event: string; timeline: HookTimelineBeatV1[]; relation_to_episode_conflict: string; payoff_beat_id: string; source_refs: SourceRefV1[]; anti_clickbait_check: string; } export interface EndingHookSpecV1 { hook: string; new_information: string; next_episode_question: string; state_change: string; source_refs: SourceRefV1[]; } export interface StoryStateRefV1 { character_states: Record; active_conflicts: string[]; known_information: string[]; location_state?: string; } export interface EpisodeBeatV1 { id: string; type: 'setup' | 'escalation' | 'reversal' | 'choice' | 'climax' | 'aftermath' | 'hook'; beat: string; character_action: string; consequence: string; source_refs: SourceRefV1[]; } export interface EpisodePlanSpecV1 { schema_version: typeof PRODUCTION_CONTRACT_VERSIONS.episodePlan; adaptation_bible_version_id: string; episode_number: number; target_duration_ms: number; hook_policy: HookPolicyV1; opening_hook: OpeningHookSpecV1; protagonist_goal: string; obstacle: string; stakes: string; dramatic_question: string; beats: EpisodeBeatV1[]; midpoint_change: string; climax_choice: string; irreversible_change: string; ending_hook: EndingHookSpecV1; entry_state: StoryStateRefV1; exit_state: StoryStateRefV1; source_refs: SourceRefV1[]; adaptation_decision_refs: string[]; } export interface DialogueBeatV1 { id: string; character_id: string; line: string; intention: string; subtext: string; reaction_target?: string; estimated_duration_ms: number; } export interface ActionBeatV1 { id: string; character_id?: string; action: string; trigger: string; result: string; estimated_duration_ms: number; } export interface SceneSpecV1 { id: string; location_asset_ref: string; time_of_day: string; entry_state: StoryStateRefV1; scene_goal: string; active_characters: string[]; character_objectives: Array<{ character_id: string; objective: string }>; obstacle: string; tactics: Array<{ character_id: string; tactic: string }>; action_beats: ActionBeatV1[]; dialogue_beats: DialogueBeatV1[]; subtext: string; turn: string; exit_state: StoryStateRefV1; estimated_duration_ms: number; source_refs: SourceRefV1[]; } export interface SceneScriptSpecV1 { schema_version: typeof PRODUCTION_CONTRACT_VERSIONS.sceneScript; episode_plan_version_id: string; episode_number: number; target_duration_ms: number; scenes: SceneSpecV1[]; opening_hook_scene_id: string; climax_scene_id: string; ending_hook_scene_id: string; dialogue_duration_estimate_ms: number; total_duration_estimate_ms: number; character_voice_checks: Array<{ character_id: string; check?: string; passed: boolean; issue?: string }>; continuity_checks: Array<{ check?: string; passed: boolean; issue?: string }>; } export type AssetRequirementKindV1 = | 'character_identity' | 'character_state' | 'crowd' | 'location' | 'prop' | 'vfx'; export type AssetEntityTypeV1 = | 'project_character' | 'character_state' | 'project_visual_asset' | 'global_character' | 'asset'; export interface AssetEntityRefV1 { entity_type: AssetEntityTypeV1; id: string; } export interface AssetCandidateRefV1 extends AssetEntityRefV1 { reason: string; approval_status: 'manual_review_required' | 'approved' | 'rejected'; } export interface AssetRequirementV1 { id: string; kind: AssetRequirementKindV1; name: string; source_character_id?: string; source_location_ref?: string; reuse_decision: 'reuse' | 'create' | 'upgrade' | 'manual_review'; existing_ref: AssetEntityRefV1 | null; candidate_refs: AssetCandidateRefV1[]; applies_to_scene_ids: string[]; priority: 'blocking' | 'high' | 'normal'; visual_brief: string; continuity_locks: string[]; deliverables: string[]; acceptance_criteria: string[]; dependencies: string[]; source_refs: SourceRefV1[]; } export interface AssetSceneBindingV1 { scene_id: string; location_requirement_ref: string; character_requirement_refs: string[]; crowd_requirement_refs: string[]; prop_requirement_refs: string[]; vfx_requirement_refs: string[]; } export interface AssetPlanSpecV1 { schema_version: typeof PRODUCTION_CONTRACT_VERSIONS.assetPlan; scene_script_version_id: string; episode_number: number; format: { orientation: '16:9'; keyframe_resolution: '2560x1440'; video_resolution: '1920x1080'; }; inventory_snapshot: { project_character_ids: string[]; project_visual_asset_ids: string[]; matching_global_character_ids: string[]; legacy_candidate_asset_ids: string[]; }; requirements: AssetRequirementV1[]; scene_bindings: AssetSceneBindingV1[]; creation_order: string[]; blocking_requirement_refs: string[]; quality_checks: Array<{ check: string; passed: boolean; issue?: string }>; source_refs: SourceRefV1[]; } export interface SpatialVectorV1 { x: number; y: number; z: number; } export interface SceneGeographyZoneV1 { id: string; name: string; purpose: string; center: SpatialVectorV1; bounds: string; adjacent_zone_ids: string[]; } export interface SceneGeographyPlacementV1 { subject_ref: string; subject_type: 'character' | 'faction' | 'crowd' | 'prop' | 'vfx_origin' | 'vfx_target'; faction_ref?: string; zone_id: string; world_position: SpatialVectorV1; facing_vector: SpatialVectorV1; screen_side: 'left' | 'center' | 'right' | 'background' | 'foreground'; eyeline_target_ref?: string; vertical_relation: 'ground' | 'below' | 'above' | 'overhead'; } export interface SceneGeographyAxisV1 { id: string; endpoint_a_ref: string; endpoint_b_ref: string; description: string; screen_left_ref: string; screen_right_ref: string; safe_camera_side: string; forbidden_camera_side: string; crossing_policy: 'forbidden' | 'neutral_bridge_required' | 'motivated_crossing_allowed'; } export interface SceneGeographyCameraPositionV1 { id: string; name: string; world_position: SpatialVectorV1; viewing_direction: SpatialVectorV1; axis_side: 'safe' | 'on_axis' | 'forbidden'; allowed: boolean; purpose: string; preserves_screen_relationship: string; } export interface SceneGeographyActionVectorV1 { id: string; source_ref: string; target_ref: string; origin_zone_id: string; target_zone_id: string; world_direction: SpatialVectorV1; screen_direction: string; trajectory: string; must_keep_origin_and_target_visible: boolean; } export interface SceneGeographyBlockingBeatV1 { id: string; trigger: string; actor_ref: string; start_zone_id: string; end_zone_id: string; facing_target_ref: string; eyeline_target_ref: string; action_vector_ref?: string; continuity_result: string; } export interface SceneGeographySceneV1 { scene_id: string; location_requirement_ref: string; world_layout: string; coordinate_system: { origin: string; x_axis: string; y_axis: string; z_axis: string; }; zones: SceneGeographyZoneV1[]; placements: SceneGeographyPlacementV1[]; primary_axis: SceneGeographyAxisV1; camera_positions: SceneGeographyCameraPositionV1[]; action_vectors: SceneGeographyActionVectorV1[]; blocking_beats: SceneGeographyBlockingBeatV1[]; continuity_locks: string[]; forbidden_outcomes: string[]; required_spatial_anchor_refs: string[]; acceptance_criteria: string[]; source_refs: SourceRefV1[]; } export interface SceneGeographySpecV1 { schema_version: typeof PRODUCTION_CONTRACT_VERSIONS.sceneGeography; asset_plan_version_id: string; scene_script_version_id: string; episode_number: number; format: { orientation: '16:9'; world_unit: 'meter'; coordinate_handedness: 'right_handed'; }; scene_geographies: SceneGeographySceneV1[]; global_continuity_locks: string[]; global_forbidden_outcomes: string[]; quality_checks: Array<{ check: string; passed: boolean; issue?: string }>; source_refs: SourceRefV1[]; } export interface FrameStateV1 { composition: string; character_positions: string; eyelines: string; action_state: string; emotional_state: string; camera_axis: string; screen_direction: string; lighting_state: string; } export interface ContinuityAnchorV1 { type: 'character' | 'action' | 'eyeline' | 'camera_axis' | 'screen_direction' | 'sound' | 'prop' | 'light'; value: string; } export interface PerformanceBeatV1 { character_id: string; start_ms: number; end_ms: number; start_state: string; trigger: string; visible_action: string; end_state: string; } export interface DialogueTimingV1 { character_id: string; start_ms: number; end_ms: number; spoken_text: string; delivery: string; listener_reaction?: string; } export interface ShotExecutionSpecV1 { schema_version: typeof PRODUCTION_CONTRACT_VERSIONS.shotExecution; scene_script_version_id: string; scene_geography_version_id: string; scene_id: string; shot_number: number; dramatic_purpose: string; generation_unit: 'single_shot' | 'continuous_shot' | 'montage_unit'; target_duration_ms: number; assets: { character_state_refs: string[]; location_asset_ref: string; prop_asset_refs: string[]; wardrobe_refs: string[]; vfx_asset_refs: string[]; }; blocking: { focus: string; pressure_source: string; reaction_receiver: string; positions: string; movement_path: string; }; geography_binding: { axis_id: string; camera_position_id: string; placement_subject_refs: string[]; action_vector_refs: string[]; zone_ids: string[]; }; performance_timeline: PerformanceBeatV1[]; dialogue_timeline: DialogueTimingV1[]; camera: { shot_size: string; angle: string; lens_intent: string; movement: string; movement_motivation: string; camera_axis: string; screen_direction: string; landing_point: string; }; lighting: { key_light: string; contrast: string; dynamic_change: string; }; vfx: Array<{ effect: string; trigger: string; interaction: string; intensity_arc: string; }>; sound: { ambience: string[]; dialogue_source: 'native_audio' | 'post_tts' | 'none'; sfx_hits: Array<{ at_ms: number; cue: string }>; music_cue?: string; sound_bridge?: string; }; start_state: FrameStateV1; end_state: FrameStateV1; continuity_from_previous: ContinuityAnchorV1[]; continuity_to_next: ContinuityAnchorV1[]; edit_relation_to_previous: | 'new_scene_cut' | 'motivated_hard_cut' | 'reaction_cut' | 'match_cut' | 'sound_bridge' | 'continuous_motion'; cut_motivation: string; generation_strategy: { mode: 'text_only' | 'first_frame' | 'first_last_frame' | 'multi_reference'; reference_assets: Array<{ asset_id: string; responsibility: | 'character_identity' | 'wardrobe_state' | 'location_layout' | 'prop_identity' | 'start_frame' | 'end_frame' | 'action_pose' | 'style_reference'; priority: number; }>; }; provider_requirements: { native_audio_required: boolean; dialogue_required: boolean; max_reference_images?: number; allowed_duration_ms?: number[]; }; acceptance_criteria: Array<{ field_path: string; expected: string; severity: 'minor' | 'major' | 'fatal' }>; forbidden_outcomes: string[]; } export interface QualityIssueV1 { code: string; field_path: string; message: string; severity: 'minor' | 'major' | 'fatal'; } export interface StageQualityResultV1 { schema_version: typeof PRODUCTION_CONTRACT_VERSIONS.stageQuality; hard_gate_status: 'pass' | 'blocked'; hard_gate_issues: QualityIssueV1[]; dimension_scores: Record; weighted_score: number; confidence: number; fatal_issues: QualityIssueV1[]; repair_instructions: Array<{ field_path: string; instruction: string }>; rubric_version: string; } export interface StageReviewDeltaV1 { schema_version: typeof PRODUCTION_CONTRACT_VERSIONS.stageReviewDelta; contract_type: 'source_analysis' | 'adaptation_bible' | 'episode_plan' | 'scene_script' | 'asset_plan' | 'scene_geography'; expected_contract_id: string; reviewer_version: string; verdict: 'pass' | 'repair_required'; issues: QualityIssueV1[]; repairs: Array<{ field_path: string; instruction: string; evidence_refs: SourceRefV1[]; }>; reviewer_notes: string[]; } export interface ShotQcDeltaV1 { schema_version: typeof PRODUCTION_CONTRACT_VERSIONS.shotQcDelta; expected_spec_version: string; observed_asset_id: string; matched: string[]; mismatches: Array<{ field_path: string; expected: string; observed: string; severity: 'minor' | 'major' | 'fatal'; }>; repair_scope: 'prompt' | 'reference' | 'duration' | 'route' | 'script'; repair_instructions: string[]; } export type PromptRuleStageV1 = | 'source' | 'adaptation' | 'episode' | 'script' | 'assets' | 'geography' | 'shot' | 'qc' | 'timeline'; export interface PromptRuleCandidateV1 { id: string; source_prompt_refs: string[]; stage: PromptRuleStageV1; scope: 'global' | 'genre' | 'provider' | 'project'; genre_tags: string[]; provider_codes: string[]; original_text: string; normalized_rule: string; activation_condition: string; expected_improvement: string; evidence_refs: string[]; positive_examples: string[]; negative_examples: string[]; conflicts_with: string[]; status: 'candidate' | 'testing' | 'approved' | 'deprecated'; reviewer_id?: string; rule_version: typeof PRODUCTION_CONTRACT_VERSIONS.promptRule; }