Initial release — OpenMontage: the first open-source agentic video production system
11 production pipelines, 47 tools, 124 agent skills. Supports cloud APIs (fal.ai, OpenAI, ElevenLabs, Suno, HeyGen, Runway) and free local providers (diffusers, Piper TTS, WAN 2.1, Hunyuan, CogVideo). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
"""Artifact schema loading and validation utilities."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import jsonschema
|
||||
|
||||
SCHEMA_DIR = Path(__file__).parent
|
||||
|
||||
ARTIFACT_NAMES = [
|
||||
"research_brief",
|
||||
"proposal_packet",
|
||||
"brief",
|
||||
"script",
|
||||
"scene_plan",
|
||||
"asset_manifest",
|
||||
"edit_decisions",
|
||||
"render_report",
|
||||
"publish_log",
|
||||
"review",
|
||||
"cost_log",
|
||||
]
|
||||
|
||||
|
||||
def load_schema(name: str) -> dict:
|
||||
"""Load a JSON schema by artifact name."""
|
||||
path = SCHEMA_DIR / f"{name}.schema.json"
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(f"Schema not found: {path}")
|
||||
with open(path) as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def validate_artifact(name: str, data: dict[str, Any]) -> None:
|
||||
"""Validate artifact data against its schema. Raises on failure."""
|
||||
schema = load_schema(name)
|
||||
jsonschema.validate(instance=data, schema=schema)
|
||||
|
||||
|
||||
def list_schemas() -> list[str]:
|
||||
"""List all available artifact schema names."""
|
||||
return [p.stem.replace(".schema", "") for p in SCHEMA_DIR.glob("*.schema.json")]
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/asset_manifest",
|
||||
"title": "Asset Manifest",
|
||||
"description": "Inventory of generated/sourced assets produced by the Asset Generator.",
|
||||
"type": "object",
|
||||
"required": ["version", "assets"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"assets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "type", "path", "source_tool", "scene_id"],
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["image", "video", "audio", "narration", "music", "sfx", "diagram", "animation", "code_snippet", "subtitle", "font", "lut"]
|
||||
},
|
||||
"path": { "type": "string", "description": "Relative path within the pipeline project directory" },
|
||||
"source_tool": { "type": "string" },
|
||||
"scene_id": { "type": "string" },
|
||||
"prompt": { "type": "string", "description": "Generation prompt if AI-generated" },
|
||||
"seed": { "type": "integer", "description": "Seed if applicable" },
|
||||
"model": { "type": "string", "description": "Model used for generation" },
|
||||
"cost_usd": { "type": "number", "minimum": 0 },
|
||||
"duration_seconds": { "type": "number", "minimum": 0 },
|
||||
"resolution": { "type": "string" },
|
||||
"format": { "type": "string" },
|
||||
"quality_score": { "type": "number", "minimum": 0, "maximum": 1 }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"total_cost_usd": { "type": "number", "minimum": 0 },
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/brief",
|
||||
"title": "Video Brief",
|
||||
"description": "Creative brief produced by the Idea Explorer agent.",
|
||||
"type": "object",
|
||||
"required": ["version", "title", "hook", "key_points", "tone", "style", "target_platform", "target_duration_seconds"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"title": { "type": "string", "minLength": 1 },
|
||||
"hook": { "type": "string", "description": "Opening hook / attention grabber" },
|
||||
"key_points": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"minItems": 1
|
||||
},
|
||||
"core_message": { "type": "string" },
|
||||
"cta": { "type": "string", "description": "Call to action" },
|
||||
"tone": { "type": "string" },
|
||||
"style": { "type": "string", "description": "Style playbook name or custom description" },
|
||||
"target_audience": { "type": "string" },
|
||||
"target_platform": {
|
||||
"type": "string",
|
||||
"enum": ["youtube", "instagram", "tiktok", "linkedin", "generic"]
|
||||
},
|
||||
"target_duration_seconds": { "type": "number", "minimum": 1 },
|
||||
"reference_material": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Paths or URLs to source material"
|
||||
},
|
||||
"angle_options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": { "type": "string" },
|
||||
"description": { "type": "string" }
|
||||
},
|
||||
"required": ["name", "description"]
|
||||
},
|
||||
"description": "2-3 angle options for user to choose from"
|
||||
},
|
||||
"selected_angle": { "type": "string" },
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/cost_log",
|
||||
"title": "Cost Log",
|
||||
"description": "Estimated, reserved, and actual spend by operation.",
|
||||
"type": "object",
|
||||
"required": ["version", "entries"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"budget_total_usd": { "type": "number", "minimum": 0 },
|
||||
"budget_reserved_usd": { "type": "number", "minimum": 0 },
|
||||
"budget_spent_usd": { "type": "number", "minimum": 0 },
|
||||
"entries": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "tool", "operation", "status", "timestamp"],
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"tool": { "type": "string" },
|
||||
"operation": { "type": "string" },
|
||||
"status": { "type": "string", "enum": ["estimated", "reserved", "completed", "failed", "refunded"] },
|
||||
"estimated_usd": { "type": "number", "minimum": 0 },
|
||||
"reserved_usd": { "type": "number", "minimum": 0 },
|
||||
"actual_usd": { "type": "number", "minimum": 0 },
|
||||
"timestamp": { "type": "string", "format": "date-time" },
|
||||
"details": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/edit_decisions",
|
||||
"title": "Edit Decisions",
|
||||
"description": "Editorial decisions produced by the Edit Agent.",
|
||||
"type": "object",
|
||||
"required": ["version", "cuts"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"cuts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "source", "in_seconds", "out_seconds"],
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"source": { "type": "string", "description": "Source file path or asset-manifest ID" },
|
||||
"in_seconds": { "type": "number", "minimum": 0 },
|
||||
"out_seconds": { "type": "number", "minimum": 0 },
|
||||
"speed": { "type": "number", "minimum": 0.1, "default": 1.0 },
|
||||
"layer": {
|
||||
"type": "string",
|
||||
"enum": ["primary", "overlay", "background"],
|
||||
"default": "primary"
|
||||
},
|
||||
"transform": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"scale": { "type": "number", "minimum": 0, "default": 1.0 },
|
||||
"position": { "type": "string", "default": "center" },
|
||||
"animation": {
|
||||
"type": "string",
|
||||
"description": "Motion applied to still images (e.g. ken-burns-slow-zoom, pan-left, static)"
|
||||
},
|
||||
"crop": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"x": { "type": "number" },
|
||||
"y": { "type": "number" },
|
||||
"width": { "type": "number" },
|
||||
"height": { "type": "number" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"transition_in": {
|
||||
"type": "string",
|
||||
"description": "Transition type entering this cut (e.g. fade, dissolve, cut, wipe)"
|
||||
},
|
||||
"transition_out": {
|
||||
"type": "string",
|
||||
"description": "Transition type leaving this cut"
|
||||
},
|
||||
"transition_duration": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"description": "Duration of transition in seconds"
|
||||
},
|
||||
"reason": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["asset_id", "start_seconds", "end_seconds", "position"],
|
||||
"properties": {
|
||||
"asset_id": { "type": "string" },
|
||||
"start_seconds": { "type": "number", "minimum": 0 },
|
||||
"end_seconds": { "type": "number", "minimum": 0 },
|
||||
"position": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"x": { "type": "number" },
|
||||
"y": { "type": "number" },
|
||||
"width": { "type": "number" },
|
||||
"height": { "type": "number" }
|
||||
},
|
||||
"required": ["x", "y"]
|
||||
},
|
||||
"animation": { "type": "string" },
|
||||
"opacity": { "type": "number", "minimum": 0, "maximum": 1 }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"type": "object",
|
||||
"description": "Audio configuration for narration, music, and SFX.",
|
||||
"properties": {
|
||||
"narration": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"segments": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["asset_id", "start_seconds"],
|
||||
"properties": {
|
||||
"asset_id": { "type": "string" },
|
||||
"start_seconds": { "type": "number", "minimum": 0 },
|
||||
"end_seconds": { "type": "number", "minimum": 0 }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"music": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"asset_id": { "type": "string" },
|
||||
"volume": { "type": "number", "minimum": 0, "maximum": 1 },
|
||||
"fade_in_seconds": { "type": "number", "minimum": 0 },
|
||||
"fade_out_seconds": { "type": "number", "minimum": 0 },
|
||||
"ducking": {
|
||||
"oneOf": [
|
||||
{ "type": "boolean" },
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": { "type": "boolean", "default": true },
|
||||
"threshold_db": { "type": "number" },
|
||||
"reduction_db": { "type": "number" },
|
||||
"attack_ms": { "type": "number", "minimum": 0 },
|
||||
"release_ms": { "type": "number", "minimum": 0 }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"sfx": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"asset_id": { "type": "string" },
|
||||
"start_seconds": { "type": "number", "minimum": 0 },
|
||||
"volume": { "type": "number", "minimum": 0, "maximum": 1, "default": 1.0 }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"subtitles": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": { "type": "boolean" },
|
||||
"style": { "type": "string", "description": "Display style: sentence, word-by-word, karaoke" },
|
||||
"source": { "type": "string", "description": "Path to subtitle file or asset ID" },
|
||||
"font": { "type": "string" },
|
||||
"font_size": { "type": "integer" },
|
||||
"color": { "type": "string", "description": "Primary text color (hex or ASS format)" },
|
||||
"outline_color": { "type": "string" },
|
||||
"background": { "type": "string", "description": "Background color with optional alpha (e.g. #00000088)" },
|
||||
"position": { "type": "string", "enum": ["top-center", "bottom-center", "center"] },
|
||||
"max_words_per_line": { "type": "integer", "minimum": 1 }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"music": {
|
||||
"type": "object",
|
||||
"description": "Legacy top-level music config. Prefer audio.music for new pipelines.",
|
||||
"properties": {
|
||||
"asset_id": { "type": "string" },
|
||||
"volume": { "type": "number", "minimum": 0, "maximum": 1 },
|
||||
"ducking": { "type": "boolean", "default": true },
|
||||
"fade_in_seconds": { "type": "number", "minimum": 0 },
|
||||
"fade_out_seconds": { "type": "number", "minimum": 0 }
|
||||
}
|
||||
},
|
||||
"transitions": {
|
||||
"type": "array",
|
||||
"description": "Global transition list. Per-cut transitions in cuts[].transition_in/out are preferred.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": { "type": "string" },
|
||||
"at_seconds": { "type": "number" },
|
||||
"duration_seconds": { "type": "number", "minimum": 0 }
|
||||
},
|
||||
"required": ["type", "at_seconds", "duration_seconds"]
|
||||
}
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/proposal_packet",
|
||||
"title": "Proposal Packet",
|
||||
"description": "Pre-production proposal containing concept options, production plan, cost estimate, and approval gate. The user reviews and approves this before any assets are generated or money is spent.",
|
||||
"type": "object",
|
||||
"required": ["version", "concept_options", "selected_concept", "production_plan", "cost_estimate", "approval"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"concept_options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "title", "hook", "narrative_structure", "visual_approach", "target_duration_seconds", "why_this_works"],
|
||||
"properties": {
|
||||
"id": { "type": "string", "description": "c1, c2, c3, etc." },
|
||||
"title": { "type": "string", "description": "Specific, compelling — not generic" },
|
||||
"hook": { "type": "string", "description": "Opening line that creates curiosity. Under 20 words." },
|
||||
"narrative_structure": {
|
||||
"type": "string",
|
||||
"enum": ["analogy", "problem_solution", "journey", "debate", "myth_busting", "timeline", "comparison", "tutorial", "story", "data_narrative"],
|
||||
"description": "The structural approach to telling this story"
|
||||
},
|
||||
"visual_approach": { "type": "string", "description": "Primary visual strategy — specific enough to guide scene planning" },
|
||||
"suggested_playbook": { "type": "string", "description": "Style playbook name from styles/" },
|
||||
"target_audience": { "type": "string", "description": "Specific audience segment this angle serves best" },
|
||||
"target_platform": {
|
||||
"type": "string",
|
||||
"enum": ["youtube", "instagram", "tiktok", "linkedin", "generic"]
|
||||
},
|
||||
"target_duration_seconds": { "type": "number", "minimum": 1 },
|
||||
"key_points": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"minItems": 2,
|
||||
"description": "Concrete claims the video will prove — not vague topics"
|
||||
},
|
||||
"core_message": { "type": "string", "description": "The one thing the viewer remembers tomorrow" },
|
||||
"cta": { "type": "string", "description": "Call to action — specific and relevant" },
|
||||
"tone": { "type": "string" },
|
||||
"grounded_in": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Which research_brief findings support this concept"
|
||||
},
|
||||
"why_this_works": { "type": "string", "description": "Rationale citing research findings — not vibes" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 3,
|
||||
"description": "At least 3 genuinely different concept directions"
|
||||
},
|
||||
"selected_concept": {
|
||||
"type": "object",
|
||||
"required": ["concept_id", "rationale"],
|
||||
"properties": {
|
||||
"concept_id": { "type": "string", "description": "ID of the chosen concept from concept_options" },
|
||||
"rationale": { "type": "string", "description": "Why this concept was selected (user choice or agent recommendation)" },
|
||||
"modifications": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Any modifications the user requested to the selected concept"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"production_plan": {
|
||||
"type": "object",
|
||||
"required": ["pipeline", "stages"],
|
||||
"properties": {
|
||||
"pipeline": { "type": "string", "description": "Pipeline manifest name, e.g., 'animated-explainer'" },
|
||||
"playbook": { "type": "string", "description": "Selected style playbook" },
|
||||
"stages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["stage", "tools", "approach"],
|
||||
"properties": {
|
||||
"stage": { "type": "string" },
|
||||
"tools": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["tool_name", "role", "available"],
|
||||
"properties": {
|
||||
"tool_name": { "type": "string" },
|
||||
"role": { "type": "string", "description": "What this tool does in this stage" },
|
||||
"provider": { "type": "string" },
|
||||
"available": { "type": "boolean" },
|
||||
"estimated_cost_usd": { "type": "number", "minimum": 0 },
|
||||
"why_this_provider": { "type": "string", "description": "Rationale for choosing this specific provider" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"approach": { "type": "string", "description": "What happens in this stage and how" },
|
||||
"fallback_if_unavailable": { "type": "string", "description": "What happens if primary tool is unavailable" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"quality_tradeoffs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["tradeoff", "recommendation"],
|
||||
"properties": {
|
||||
"tradeoff": { "type": "string", "description": "e.g., 'ElevenLabs TTS ($0.30) vs Piper local (free)'" },
|
||||
"recommendation": { "type": "string" },
|
||||
"quality_impact": { "type": "string", "description": "What the user gains or loses" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"description": "Explicit quality/cost tradeoffs for the user to consider"
|
||||
},
|
||||
"alternative_paths": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["description", "total_cost_usd", "quality_level"],
|
||||
"properties": {
|
||||
"description": { "type": "string" },
|
||||
"total_cost_usd": { "type": "number", "minimum": 0 },
|
||||
"quality_level": { "type": "string", "enum": ["premium", "standard", "budget", "free"] },
|
||||
"what_changes": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"description": "Alternative production paths at different price/quality points"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"cost_estimate": {
|
||||
"type": "object",
|
||||
"required": ["total_estimated_usd", "line_items", "budget_verdict"],
|
||||
"properties": {
|
||||
"total_estimated_usd": { "type": "number", "minimum": 0 },
|
||||
"line_items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["tool", "operation", "estimated_usd"],
|
||||
"properties": {
|
||||
"tool": { "type": "string" },
|
||||
"operation": { "type": "string", "description": "What this tool call does" },
|
||||
"quantity": { "type": "number", "description": "How many calls, e.g., 6 images, 1 TTS run" },
|
||||
"estimated_usd": { "type": "number", "minimum": 0 },
|
||||
"notes": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"budget_cap_usd": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"description": "User-set budget cap, if any"
|
||||
},
|
||||
"budget_verdict": {
|
||||
"type": "string",
|
||||
"enum": ["within_budget", "near_limit", "over_budget", "no_budget_set"],
|
||||
"description": "How the estimate compares to the budget cap"
|
||||
},
|
||||
"savings_options": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Concrete ways to reduce cost if over budget"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"approval": {
|
||||
"type": "object",
|
||||
"required": ["status"],
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["pending", "approved", "approved_with_changes", "rejected"],
|
||||
"description": "User's approval decision"
|
||||
},
|
||||
"user_notes": { "type": "string", "description": "Any feedback or changes requested" },
|
||||
"approved_budget_usd": { "type": "number", "minimum": 0, "description": "Budget the user explicitly approved" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/publish_log",
|
||||
"title": "Publish Log",
|
||||
"description": "Per-platform publish/export results produced by the Publisher agent.",
|
||||
"type": "object",
|
||||
"required": ["version", "entries"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"entries": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["platform", "status", "timestamp"],
|
||||
"properties": {
|
||||
"platform": { "type": "string" },
|
||||
"status": { "type": "string", "enum": ["published", "exported", "failed", "draft", "pending_review"] },
|
||||
"url": { "type": "string" },
|
||||
"video_id": { "type": "string" },
|
||||
"visibility": { "type": "string", "enum": ["public", "private", "unlisted"] },
|
||||
"export_path": { "type": "string" },
|
||||
"timestamp": { "type": "string", "format": "date-time" },
|
||||
"metadata_used": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": { "type": "string" },
|
||||
"description": { "type": "string" },
|
||||
"hashtags": { "type": "array", "items": { "type": "string" } },
|
||||
"chapters": { "type": "array", "items": { "type": "object" } }
|
||||
}
|
||||
},
|
||||
"error": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/render_report",
|
||||
"title": "Render Report",
|
||||
"description": "Output report produced by the Composer agent after rendering.",
|
||||
"type": "object",
|
||||
"required": ["version", "outputs"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"outputs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["path", "format", "resolution", "duration_seconds"],
|
||||
"properties": {
|
||||
"path": { "type": "string" },
|
||||
"format": { "type": "string" },
|
||||
"codec": { "type": "string" },
|
||||
"audio_codec": { "type": "string" },
|
||||
"resolution": { "type": "string" },
|
||||
"fps": { "type": "number" },
|
||||
"duration_seconds": { "type": "number", "minimum": 0 },
|
||||
"file_size_bytes": { "type": "integer" },
|
||||
"platform_target": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 1
|
||||
},
|
||||
"render_time_seconds": { "type": "number", "minimum": 0 },
|
||||
"warnings": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"verification_notes": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/research_brief",
|
||||
"title": "Research Brief",
|
||||
"description": "Structured web research findings that ground a video in real data, trends, and audience insights. Produced by the Research Director before any creative work begins.",
|
||||
"type": "object",
|
||||
"required": ["version", "topic", "research_date", "landscape", "data_points", "audience_insights", "angles_discovered", "sources"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"topic": {
|
||||
"type": "string",
|
||||
"description": "The core topic as stated by the user"
|
||||
},
|
||||
"research_date": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "When the research was conducted — freshness matters"
|
||||
},
|
||||
"landscape": {
|
||||
"type": "object",
|
||||
"description": "What already exists in the content landscape",
|
||||
"required": ["existing_content", "saturated_angles", "underserved_gaps"],
|
||||
"properties": {
|
||||
"existing_content": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["title", "source", "angle", "what_it_covers"],
|
||||
"properties": {
|
||||
"title": { "type": "string" },
|
||||
"url": { "type": "string", "format": "uri" },
|
||||
"source": { "type": "string", "description": "youtube, blog, tiktok, etc." },
|
||||
"angle": { "type": "string", "description": "The narrative approach used" },
|
||||
"what_it_covers": { "type": "string" },
|
||||
"what_it_misses": { "type": "string" },
|
||||
"engagement_signal": { "type": "string", "description": "View count, upvotes, comments — whatever is available" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 3,
|
||||
"description": "Top existing content on this topic — at least 3 entries"
|
||||
},
|
||||
"saturated_angles": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Angles that have been done to death — avoid these"
|
||||
},
|
||||
"underserved_gaps": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"minItems": 1,
|
||||
"description": "Angles or questions that existing content does NOT cover well"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"trending": {
|
||||
"type": "object",
|
||||
"description": "What is happening RIGHT NOW around this topic",
|
||||
"properties": {
|
||||
"recent_developments": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["headline", "date", "relevance"],
|
||||
"properties": {
|
||||
"headline": { "type": "string" },
|
||||
"url": { "type": "string", "format": "uri" },
|
||||
"date": { "type": "string" },
|
||||
"relevance": { "type": "string", "description": "Why this matters for our video" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"active_discussions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["platform", "topic_or_url", "sentiment"],
|
||||
"properties": {
|
||||
"platform": { "type": "string", "description": "reddit, hackernews, twitter, etc." },
|
||||
"topic_or_url": { "type": "string" },
|
||||
"sentiment": { "type": "string", "description": "What people feel about this — excitement, frustration, debate, confusion" },
|
||||
"key_quotes": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Direct quotes that capture the community's voice"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"timeliness_window": {
|
||||
"type": "string",
|
||||
"description": "How time-sensitive is this angle? 'evergreen', 'weeks', 'days', 'hours'"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"data_points": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["claim", "source_url", "credibility"],
|
||||
"properties": {
|
||||
"claim": { "type": "string", "description": "The specific fact, statistic, or data point" },
|
||||
"source_url": { "type": "string", "format": "uri" },
|
||||
"source_name": { "type": "string", "description": "e.g., 'Stack Overflow 2025 Developer Survey'" },
|
||||
"credibility": {
|
||||
"type": "string",
|
||||
"enum": ["primary_source", "secondary_source", "anecdotal"],
|
||||
"description": "How reliable is this data point?"
|
||||
},
|
||||
"surprise_factor": {
|
||||
"type": "string",
|
||||
"enum": ["expected", "notable", "surprising", "counterintuitive"],
|
||||
"description": "How unexpected is this for the target audience?"
|
||||
},
|
||||
"usable_as": {
|
||||
"type": "string",
|
||||
"description": "How this could be used: hook, stat_card, script_anchor, closing_punch"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 3,
|
||||
"description": "Verified facts and statistics — at least 3, aim for 5-8"
|
||||
},
|
||||
"audience_insights": {
|
||||
"type": "object",
|
||||
"required": ["common_questions", "misconceptions", "knowledge_level"],
|
||||
"properties": {
|
||||
"common_questions": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"minItems": 3,
|
||||
"description": "Real questions people ask about this topic — sourced from forums, PAA, Quora"
|
||||
},
|
||||
"misconceptions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["myth", "reality"],
|
||||
"properties": {
|
||||
"myth": { "type": "string" },
|
||||
"reality": { "type": "string" },
|
||||
"source": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"description": "What people commonly get wrong"
|
||||
},
|
||||
"knowledge_level": {
|
||||
"type": "string",
|
||||
"description": "What the target audience likely already knows vs. what will be new"
|
||||
},
|
||||
"pain_points": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Frustrations, confusions, or complaints related to this topic"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"expert_voices": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["name", "position"],
|
||||
"properties": {
|
||||
"name": { "type": "string" },
|
||||
"title_or_affiliation": { "type": "string" },
|
||||
"position": { "type": "string", "description": "Their stance or notable quote on this topic" },
|
||||
"source_url": { "type": "string", "format": "uri" },
|
||||
"contrarian": { "type": "boolean", "description": "Does this challenge the mainstream view?" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"description": "Named experts and their takes — useful for authority and debate framing"
|
||||
},
|
||||
"angles_discovered": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["name", "hook", "type", "why_now"],
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Short angle title (5-8 words)" },
|
||||
"hook": { "type": "string", "description": "One-sentence attention grabber" },
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["trending", "evergreen", "contrarian", "narrative", "data_driven"],
|
||||
"description": "What kind of angle is this?"
|
||||
},
|
||||
"why_now": { "type": "string", "description": "Why this angle is compelling right now — cite research findings" },
|
||||
"grounded_in": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Which data_points or audience_insights support this angle?"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 3,
|
||||
"description": "Angle candidates discovered through research — raw material for the Proposal Director"
|
||||
},
|
||||
"visual_references": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": { "type": "string" },
|
||||
"url": { "type": "string", "format": "uri" },
|
||||
"what_works": { "type": "string", "description": "Why this visual approach is effective" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"description": "How the best existing content visualizes this topic"
|
||||
},
|
||||
"sources": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["url", "title", "used_for"],
|
||||
"properties": {
|
||||
"url": { "type": "string", "format": "uri" },
|
||||
"title": { "type": "string" },
|
||||
"used_for": { "type": "string", "description": "Which section of the brief this source supports" },
|
||||
"reliability": {
|
||||
"type": "string",
|
||||
"enum": ["primary", "secondary", "anecdotal"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 5,
|
||||
"description": "All sources used — at least 5. Full bibliography."
|
||||
},
|
||||
"research_summary": {
|
||||
"type": "string",
|
||||
"description": "One paragraph: the single most important insight from this research and why it matters for the video"
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/review",
|
||||
"title": "Stage Review",
|
||||
"description": "Structured review findings and stage-agent dispositions from the Reviewer.",
|
||||
"type": "object",
|
||||
"required": ["version", "stage", "findings"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"stage": { "type": "string", "enum": ["idea", "script", "scene_plan", "assets", "edit", "compose", "publish"] },
|
||||
"round": { "type": "integer", "minimum": 1, "maximum": 2 },
|
||||
"findings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "severity", "description"],
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"severity": { "type": "string", "enum": ["critical", "suggestion", "nitpick"] },
|
||||
"category": { "type": "string" },
|
||||
"description": { "type": "string" },
|
||||
"disposition": {
|
||||
"type": "string",
|
||||
"enum": ["accepted", "rejected", "pending"],
|
||||
"default": "pending"
|
||||
},
|
||||
"agent_response": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/scene_plan",
|
||||
"title": "Scene Plan",
|
||||
"description": "Ordered scene list produced by the Scene Planner agent.",
|
||||
"type": "object",
|
||||
"required": ["version", "scenes"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"style_playbook": { "type": "string", "description": "Name of the active style playbook" },
|
||||
"scenes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "type", "description", "start_seconds", "end_seconds"],
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["talking_head", "broll", "animation", "diagram", "text_card", "transition", "generated", "screen_recording"]
|
||||
},
|
||||
"description": { "type": "string" },
|
||||
"start_seconds": { "type": "number", "minimum": 0 },
|
||||
"end_seconds": { "type": "number", "minimum": 0 },
|
||||
"script_section_id": { "type": "string" },
|
||||
"framing": { "type": "string" },
|
||||
"movement": { "type": "string" },
|
||||
"transition_in": { "type": "string" },
|
||||
"transition_out": { "type": "string" },
|
||||
"overlay_notes": { "type": "string" },
|
||||
"required_assets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": { "type": "string" },
|
||||
"description": { "type": "string" },
|
||||
"source": { "type": "string", "enum": ["generate", "source", "provided", "record"] }
|
||||
},
|
||||
"required": ["type", "description", "source"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 1
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "openmontage/artifacts/script",
|
||||
"title": "Production Script",
|
||||
"description": "Timestamped script produced by the Script Writer agent.",
|
||||
"type": "object",
|
||||
"required": ["version", "title", "total_duration_seconds", "sections"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "const": "1.0" },
|
||||
"title": { "type": "string" },
|
||||
"total_duration_seconds": { "type": "number", "minimum": 1 },
|
||||
"sections": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "text", "start_seconds", "end_seconds"],
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"label": { "type": "string" },
|
||||
"text": { "type": "string" },
|
||||
"start_seconds": { "type": "number", "minimum": 0 },
|
||||
"end_seconds": { "type": "number", "minimum": 0 },
|
||||
"speaker_directions": { "type": "string" },
|
||||
"enhancement_cues": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": { "type": "string", "enum": ["overlay", "broll", "diagram", "stat_card", "code_snippet", "animation"] },
|
||||
"description": { "type": "string" },
|
||||
"timestamp_seconds": { "type": "number" }
|
||||
},
|
||||
"required": ["type", "description"]
|
||||
}
|
||||
},
|
||||
"pronunciation_guides": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"word": { "type": "string" },
|
||||
"phonetic": { "type": "string" }
|
||||
},
|
||||
"required": ["word", "phonetic"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 1
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
Reference in New Issue
Block a user