Implementation spec: governance, decision intelligence, theme system, and E2E bug fixes
Implements the 2026-04-02 transformation spec (Phases 1-8) and fixes all critical bugs found during 5-pipeline E2E testing. Governance & Decision Intelligence: - Pipeline-specific stage order in checkpoint (replaces global STAGES list) - Provider scoring engine (lib/scoring.py) with 7-dimension weighted ranking - Decision log artifact enforced at proposal/idea stage across all 10 pipelines - Delivery promise classifier prevents silent motion-to-still downgrades - Structured shot language in scene_plan schema (camera, lens, lighting, DOF) - Variation checker and slideshow risk scorer block samey output before render - Creative intake, capability extension, and creative-intake meta skills - Final self-review artifact with 5 mandatory checks before presenting output - Source media review contract for user-supplied footage Render & Theme System: - Remotion AnimatedBackground now derives colors from playbook (no more hardcoded dark blue fintech gradient on every video) - video_compose builds custom ThemeConfig from playbook YAML colors/fonts — custom playbooks flow through to Remotion automatically - Explainer component wires theme to all child components (charts, cards, etc.) - resolveAsset() handles absolute paths on Windows/Unix via file:// URIs - RENDERER_FAMILY_MAP synced with actual Remotion compositions Critical Bug Fixes: - Windows npx subprocess: run_command() resolves .cmd wrappers via shutil.which() - Silent renderer downgrade: Remotion failure now returns explicit error with options instead of silently falling back to FFmpeg - .env inline comment parsing strips trailing # comments from API keys - concat_path UnboundLocalError in video_compose finally block - audio_mixer and showcase_card capture=True kwarg bug - Selector estimate_cost() calls fixed (_select_tool -> _select_best_tool) - asset_manifest schema expanded with provider, license, subtype fields - screen-demo subtitle_gen moved from required to optional tools - Duration drift detection in post-render final review (>25% warns)
This commit is contained in:
@@ -22,6 +22,9 @@ ARTIFACT_NAMES = [
|
||||
"publish_log",
|
||||
"review",
|
||||
"cost_log",
|
||||
"decision_log",
|
||||
"source_media_review",
|
||||
"final_review",
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,12 @@
|
||||
"duration_seconds": { "type": "number", "minimum": 0 },
|
||||
"resolution": { "type": "string" },
|
||||
"format": { "type": "string" },
|
||||
"quality_score": { "type": "number", "minimum": 0, "maximum": 1 }
|
||||
"quality_score": { "type": "number", "minimum": 0, "maximum": 1 },
|
||||
"subtype": { "type": "string", "description": "Sub-classification (e.g. 'background', 'stock', 'generated')" },
|
||||
"generation_summary": { "type": "string", "description": "Brief summary of how the asset was generated or sourced" },
|
||||
"provider": { "type": "string", "description": "Provider name (e.g. pixabay, google_imagen)" },
|
||||
"license": { "type": "string", "description": "License type (e.g. Pixabay License, CC0)" },
|
||||
"original_url": { "type": "string", "description": "Source URL if downloaded from a stock service" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/decision_log",
|
||||
"title": "Decision Log",
|
||||
"description": "Audit trail of every meaningful choice made during production. Prevents hidden system behavior, enables reviewer inspection, and guards against context drift.",
|
||||
"type": "object",
|
||||
"required": ["version", "project_id", "decisions"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"project_id": { "type": "string" },
|
||||
"decisions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["decision_id", "stage", "category", "subject", "options_considered", "selected", "reason"],
|
||||
"properties": {
|
||||
"decision_id": {
|
||||
"type": "string",
|
||||
"description": "Unique ID, e.g., d-001, d-002"
|
||||
},
|
||||
"stage": {
|
||||
"type": "string",
|
||||
"description": "Pipeline stage where this decision was made"
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"pipeline_selection",
|
||||
"provider_selection",
|
||||
"renderer_family_selection",
|
||||
"playbook_selection",
|
||||
"fallback_decision",
|
||||
"budget_tradeoff",
|
||||
"downgrade_approval",
|
||||
"music_source",
|
||||
"motion_commitment",
|
||||
"concept_selection",
|
||||
"voice_selection",
|
||||
"capability_extension",
|
||||
"playbook_override",
|
||||
"visual_accuracy_check"
|
||||
],
|
||||
"description": "What class of decision this is"
|
||||
},
|
||||
"subject": {
|
||||
"type": "string",
|
||||
"description": "What is being decided, e.g., 'TTS provider for narration'"
|
||||
},
|
||||
"options_considered": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["option_id", "label", "score", "reason"],
|
||||
"properties": {
|
||||
"option_id": { "type": "string" },
|
||||
"label": { "type": "string", "description": "Human-readable name" },
|
||||
"score": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"description": "Normalized score 0-1 (1 is best)"
|
||||
},
|
||||
"reason": { "type": "string", "description": "Why this option scored this way" },
|
||||
"rejected_because": { "type": "string", "description": "If rejected, why" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 1,
|
||||
"description": "All options evaluated (including rejected ones)"
|
||||
},
|
||||
"selected": {
|
||||
"type": "string",
|
||||
"description": "option_id of the selected option"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"description": "Why this option was selected over alternatives"
|
||||
},
|
||||
"user_visible": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Whether this decision was surfaced to the user"
|
||||
},
|
||||
"user_approved": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Whether the user explicitly approved this decision"
|
||||
},
|
||||
"confidence": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"description": "Agent's confidence in this decision (0 = uncertain, 1 = certain)"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -189,6 +189,19 @@
|
||||
"required": ["type", "at_seconds", "duration_seconds"]
|
||||
}
|
||||
},
|
||||
"renderer_family": {
|
||||
"type": "string",
|
||||
"enum": ["explainer-data", "explainer-teacher", "cinematic-trailer", "product-reveal", "screen-demo", "presenter", "animation-first"],
|
||||
"description": "Locked at proposal stage — determines which Remotion composition renders this video"
|
||||
},
|
||||
"slideshow_risk_score": {
|
||||
"type": "object",
|
||||
"description": "Slideshow risk assessment from lib/slideshow_risk.py",
|
||||
"properties": {
|
||||
"average": { "type": "number" },
|
||||
"verdict": { "type": "string", "enum": ["strong", "acceptable", "revise", "fail"] }
|
||||
}
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/final_review",
|
||||
"title": "Final Review",
|
||||
"description": "Structured self-review of the rendered output. The compose stage must produce this artifact to prove the agent inspected the actual rendered video before presenting it to the user. If status is 'revise' or 'fail', the agent must not present the video as complete.",
|
||||
"type": "object",
|
||||
"required": ["version", "output_path", "status", "checks"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"output_path": {
|
||||
"type": "string",
|
||||
"description": "Path to the rendered output file that was reviewed"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["pass", "revise", "fail"],
|
||||
"description": "pass=ready to present, revise=fixable issues found, fail=critical problems"
|
||||
},
|
||||
"checks": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"technical_probe",
|
||||
"visual_spotcheck",
|
||||
"audio_spotcheck",
|
||||
"promise_preservation",
|
||||
"subtitle_check"
|
||||
],
|
||||
"properties": {
|
||||
"technical_probe": {
|
||||
"type": "object",
|
||||
"description": "ffprobe validation of the output file",
|
||||
"properties": {
|
||||
"valid_container": { "type": "boolean" },
|
||||
"duration_seconds": { "type": "number" },
|
||||
"resolution": { "type": "string" },
|
||||
"fps": { "type": "number" },
|
||||
"has_audio": { "type": "boolean" },
|
||||
"codec": { "type": "string" },
|
||||
"file_size_bytes": { "type": "integer" },
|
||||
"issues": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"visual_spotcheck": {
|
||||
"type": "object",
|
||||
"description": "Sample frames inspected from opening, middle, climax, ending",
|
||||
"properties": {
|
||||
"frames_sampled": { "type": "integer", "minimum": 4 },
|
||||
"frame_paths": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"black_frames_detected": { "type": "boolean" },
|
||||
"broken_overlays": { "type": "boolean" },
|
||||
"missing_assets": { "type": "boolean" },
|
||||
"unreadable_text": { "type": "boolean" },
|
||||
"issues": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"audio_spotcheck": {
|
||||
"type": "object",
|
||||
"description": "Audio quality verification",
|
||||
"properties": {
|
||||
"narration_present": { "type": "boolean" },
|
||||
"music_present": { "type": "boolean" },
|
||||
"unexpected_silence": { "type": "boolean" },
|
||||
"clipping_detected": { "type": "boolean" },
|
||||
"mix_intelligible": { "type": "boolean" },
|
||||
"issues": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"promise_preservation": {
|
||||
"type": "object",
|
||||
"description": "Delivery promise and renderer governance checks",
|
||||
"properties": {
|
||||
"delivery_promise_honored": { "type": "boolean" },
|
||||
"renderer_family_used": { "type": "string" },
|
||||
"motion_ratio_actual": { "type": "number" },
|
||||
"silent_downgrade_detected": { "type": "boolean" },
|
||||
"issues": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"subtitle_check": {
|
||||
"type": "object",
|
||||
"description": "Subtitle/caption verification against source script",
|
||||
"properties": {
|
||||
"subtitles_expected": { "type": "boolean" },
|
||||
"subtitles_present": { "type": "boolean" },
|
||||
"coverage_ratio": { "type": "number", "minimum": 0, "maximum": 1 },
|
||||
"timing_drift_detected": { "type": "boolean" },
|
||||
"issues": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"transcript_comparison": {
|
||||
"type": "object",
|
||||
"description": "Optional: transcribe the output and compare to source script",
|
||||
"properties": {
|
||||
"transcript_matches_script": { "type": "boolean" },
|
||||
"word_accuracy": { "type": "number", "minimum": 0, "maximum": 1 },
|
||||
"issues": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"issues_found": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "All issues found across all checks, summarized for the user"
|
||||
},
|
||||
"recommended_action": {
|
||||
"type": "string",
|
||||
"enum": ["present_to_user", "re_render", "revise_edit", "revise_assets", "block"],
|
||||
"description": "What the agent should do next based on the review findings"
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -127,6 +127,126 @@
|
||||
"additionalProperties": false
|
||||
},
|
||||
"description": "Alternative production paths at different price/quality points"
|
||||
},
|
||||
"delivery_promise": {
|
||||
"type": "object",
|
||||
"description": "Explicit classification of what this production promises to deliver",
|
||||
"required": ["promise_type", "motion_required", "tone_mode", "quality_floor"],
|
||||
"properties": {
|
||||
"promise_type": {
|
||||
"type": "string",
|
||||
"enum": ["motion_led", "source_led", "data_explainer", "teacher_explainer", "screen_demo", "avatar_presenter", "hybrid", "localization"]
|
||||
},
|
||||
"motion_required": { "type": "boolean", "description": "True when the video's quality depends on actual motion, not still-image animation" },
|
||||
"source_required": { "type": "boolean", "description": "True when user-provided footage is the primary medium" },
|
||||
"tone_mode": { "type": "string", "description": "cinematic, educational, corporate, playful, raw, intimate, epic" },
|
||||
"quality_floor": { "type": "string", "enum": ["draft", "presentable", "broadcast"] },
|
||||
"approved_fallback": { "type": ["string", "null"], "description": "animatic, still_led, or null (no fallback approved)" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"renderer_family": {
|
||||
"type": "string",
|
||||
"enum": ["explainer-data", "explainer-teacher", "cinematic-trailer", "product-reveal", "screen-demo", "presenter", "animation-first"],
|
||||
"description": "Locked at proposal stage — compose cannot change without logging a decision"
|
||||
},
|
||||
"music_source": {
|
||||
"type": "object",
|
||||
"description": "Resolved music plan from the proposal stage",
|
||||
"properties": {
|
||||
"source_type": { "type": "string", "enum": ["user_library", "ai_generated", "bring_your_own", "none"] },
|
||||
"track_path": { "type": "string", "description": "Path to selected track, if known" },
|
||||
"provider": { "type": "string", "description": "Music generation provider, if AI-generated" },
|
||||
"mood_direction": { "type": "string", "description": "Music mood description from research" },
|
||||
"estimated_cost_usd": { "type": "number", "minimum": 0 }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"voice_selection": {
|
||||
"type": "object",
|
||||
"description": "Selected voice/TTS provider and rationale",
|
||||
"properties": {
|
||||
"provider": { "type": "string" },
|
||||
"voice_id": { "type": "string" },
|
||||
"rationale": { "type": "string" },
|
||||
"estimated_cost_usd": { "type": "number", "minimum": 0 }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"decision_log_ref": {
|
||||
"type": "string",
|
||||
"description": "Path to the decision_log artifact for this project"
|
||||
},
|
||||
"provider_rankings": {
|
||||
"type": "object",
|
||||
"description": "Scored provider rankings for each asset category used in this production",
|
||||
"properties": {
|
||||
"video": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["tool_name", "provider", "weighted_score"],
|
||||
"properties": {
|
||||
"tool_name": { "type": "string" },
|
||||
"provider": { "type": "string" },
|
||||
"weighted_score": { "type": "number" },
|
||||
"task_fit": { "type": "number" },
|
||||
"output_quality": { "type": "number" },
|
||||
"explanation": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"image": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["tool_name", "provider", "weighted_score"],
|
||||
"properties": {
|
||||
"tool_name": { "type": "string" },
|
||||
"provider": { "type": "string" },
|
||||
"weighted_score": { "type": "number" },
|
||||
"task_fit": { "type": "number" },
|
||||
"output_quality": { "type": "number" },
|
||||
"explanation": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"tts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["tool_name", "provider", "weighted_score"],
|
||||
"properties": {
|
||||
"tool_name": { "type": "string" },
|
||||
"provider": { "type": "string" },
|
||||
"weighted_score": { "type": "number" },
|
||||
"task_fit": { "type": "number" },
|
||||
"output_quality": { "type": "number" },
|
||||
"explanation": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"music": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["tool_name", "provider", "weighted_score"],
|
||||
"properties": {
|
||||
"tool_name": { "type": "string" },
|
||||
"provider": { "type": "string" },
|
||||
"weighted_score": { "type": "number" },
|
||||
"task_fit": { "type": "number" },
|
||||
"output_quality": { "type": "number" },
|
||||
"explanation": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -36,6 +36,27 @@
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"render_grammar": {
|
||||
"type": "string",
|
||||
"description": "Which renderer family was used for this render",
|
||||
"enum": ["explainer-data", "explainer-teacher", "cinematic-trailer", "product-reveal", "screen-demo", "presenter", "animation-first"]
|
||||
},
|
||||
"slideshow_risk_score": {
|
||||
"type": "object",
|
||||
"description": "Final slideshow risk assessment",
|
||||
"properties": {
|
||||
"average": { "type": "number" },
|
||||
"verdict": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"decision_log_ref": {
|
||||
"type": "string",
|
||||
"description": "Path to the project's cumulative decision log"
|
||||
},
|
||||
"final_review_ref": {
|
||||
"type": "string",
|
||||
"description": "Path or inline reference to the final_review artifact produced by post-render self-review. Provides durable audit linkage between the render output and its quality inspection."
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -28,6 +28,51 @@
|
||||
"transition_in": { "type": "string" },
|
||||
"transition_out": { "type": "string" },
|
||||
"overlay_notes": { "type": "string" },
|
||||
"shot_language": {
|
||||
"type": "object",
|
||||
"description": "Structured cinematography vocabulary for this scene",
|
||||
"properties": {
|
||||
"shot_size": {
|
||||
"type": "string",
|
||||
"enum": ["extreme_wide", "wide", "medium_wide", "medium", "medium_close", "close_up", "extreme_close_up", "over_shoulder", "insert", "establishing"]
|
||||
},
|
||||
"camera_movement": {
|
||||
"type": "string",
|
||||
"enum": ["static", "pan_left", "pan_right", "tilt_up", "tilt_down", "dolly_in", "dolly_out", "tracking_left", "tracking_right", "crane_up", "crane_down", "handheld", "steadicam", "whip_pan", "orbital", "zoom_in", "zoom_out", "rack_focus"]
|
||||
},
|
||||
"lens_mm": { "type": "integer", "enum": [14, 24, 35, 50, 85, 135, 200] },
|
||||
"lighting_key": {
|
||||
"type": "string",
|
||||
"enum": ["high_key", "low_key", "natural", "golden_hour", "blue_hour", "tungsten_warm", "neon", "silhouette", "rim_lit", "volumetric", "overcast_soft"]
|
||||
},
|
||||
"depth_of_field": { "type": "string", "enum": ["shallow", "medium", "deep"] },
|
||||
"color_temperature": { "type": "string", "enum": ["cool", "neutral", "warm", "mixed"] }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"shot_intent": {
|
||||
"type": "string",
|
||||
"description": "WHY this shot exists — what purpose it serves in the video"
|
||||
},
|
||||
"narrative_role": {
|
||||
"type": "string",
|
||||
"enum": ["establish_context", "introduce_subject", "build_tension", "deliver_payload", "transition", "emotional_beat", "evidence", "comparison", "resolution", "call_to_action"],
|
||||
"description": "What role this scene plays in the narrative structure"
|
||||
},
|
||||
"information_role": {
|
||||
"type": "string",
|
||||
"description": "What the viewer learns or feels from this scene"
|
||||
},
|
||||
"hero_moment": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "True if this is the visual peak of the video — deserves extra attention"
|
||||
},
|
||||
"texture_keywords": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Visual texture descriptors: grain, clean, anamorphic, gritty, ethereal, etc."
|
||||
},
|
||||
"required_assets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
||||
@@ -43,6 +43,10 @@
|
||||
},
|
||||
"required": ["word", "phonetic"]
|
||||
}
|
||||
},
|
||||
"source_ref": {
|
||||
"type": "string",
|
||||
"description": "Reference to the research_brief data point or URL that supports this claim. Every factual claim should be traceable."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/source_media_review",
|
||||
"title": "Source Media Review",
|
||||
"description": "Structured review of user-supplied media files. Created before the first planning stage when user media exists. Ensures the agent inspects actual media content instead of planning around assumptions.",
|
||||
"type": "object",
|
||||
"required": ["version", "files", "summary", "planning_implications"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"files": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["path", "media_type", "reviewed"],
|
||||
"properties": {
|
||||
"path": { "type": "string" },
|
||||
"media_type": {
|
||||
"type": "string",
|
||||
"enum": ["video", "audio", "image"]
|
||||
},
|
||||
"reviewed": {
|
||||
"type": "boolean",
|
||||
"const": true,
|
||||
"description": "Must be true — the file was actually inspected, not assumed"
|
||||
},
|
||||
"technical_probe": {
|
||||
"type": "object",
|
||||
"description": "Raw ffprobe or metadata output for this file",
|
||||
"properties": {
|
||||
"duration_seconds": { "type": "number" },
|
||||
"resolution": { "type": "string" },
|
||||
"fps": { "type": "number" },
|
||||
"codec": { "type": "string" },
|
||||
"audio_codec": { "type": "string" },
|
||||
"sample_rate": { "type": "integer" },
|
||||
"channels": { "type": "integer" },
|
||||
"file_size_bytes": { "type": "integer" },
|
||||
"bitrate_kbps": { "type": "number" }
|
||||
}
|
||||
},
|
||||
"content_summary": {
|
||||
"type": "string",
|
||||
"description": "What the file actually contains — described from observation, not assumption"
|
||||
},
|
||||
"transcript_summary": {
|
||||
"type": "string",
|
||||
"description": "Summary of spoken content, if audio/video with speech"
|
||||
},
|
||||
"representative_frames": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Paths to sampled frames (video/image only)"
|
||||
},
|
||||
"quality_risks": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Quality issues that affect planning (low resolution, poor audio, shaky footage, etc.)"
|
||||
},
|
||||
"usable_for": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "What this file can be used for in the production (hero footage, b-roll, background audio, etc.)"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 1
|
||||
},
|
||||
"summary": {
|
||||
"type": "string",
|
||||
"description": "What the supplied media actually contains and what it does not. Be specific — 'contains 45s of interview footage, no b-roll, mono audio at 44.1kHz' not 'user provided footage'"
|
||||
},
|
||||
"planning_implications": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Concrete constraints or opportunities that must affect proposal/script/scene planning. Each item should be actionable.",
|
||||
"minItems": 1
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
Reference in New Issue
Block a user