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>
2026-03-29 08:25:17 -07:00
|
|
|
"""Checkpoint writer/reader for pipeline state persistence.
|
|
|
|
|
|
|
|
|
|
Each stage writes a checkpoint after completion. The orchestrator uses
|
|
|
|
|
checkpoints to resume pipelines and to present state at human checkpoints.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import json
|
|
|
|
|
from functools import lru_cache
|
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
from typing import Any, Optional
|
|
|
|
|
|
|
|
|
|
import jsonschema
|
|
|
|
|
|
|
|
|
|
from schemas.artifacts import ARTIFACT_NAMES, validate_artifact
|
|
|
|
|
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
# All known stages across all pipelines (used only for artifact name lookup).
|
|
|
|
|
ALL_KNOWN_STAGES = frozenset([
|
|
|
|
|
"research", "proposal", "idea", "script", "scene_plan",
|
|
|
|
|
"assets", "edit", "compose", "publish",
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
# Backward-compatible alias — existing code / tests that import STAGES still work.
|
|
|
|
|
# New code should use get_pipeline_stages(pipeline_type) instead.
|
|
|
|
|
STAGES = ["research", "proposal", "idea", "script", "scene_plan",
|
|
|
|
|
"assets", "edit", "compose", "publish"]
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
|
|
|
|
|
CANONICAL_STAGE_ARTIFACTS = {
|
|
|
|
|
"research": "research_brief",
|
|
|
|
|
"proposal": "proposal_packet",
|
|
|
|
|
"idea": "brief",
|
|
|
|
|
"script": "script",
|
|
|
|
|
"scene_plan": "scene_plan",
|
|
|
|
|
"assets": "asset_manifest",
|
|
|
|
|
"edit": "edit_decisions",
|
|
|
|
|
"compose": "render_report",
|
|
|
|
|
"publish": "publish_log",
|
|
|
|
|
}
|
|
|
|
|
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
# Additional artifacts that may be produced alongside canonical ones.
|
|
|
|
|
# These are not stage-defining but are required by governance contracts.
|
|
|
|
|
SUPPLEMENTARY_ARTIFACTS = {
|
|
|
|
|
"source_media_review", # Required before first planning stage when user media exists
|
|
|
|
|
"final_review", # Required by compose stage before presenting to user
|
2026-04-04 10:01:11 -07:00
|
|
|
"video_analysis_brief", # Reference-video grounding artifact carried alongside stages
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_pipeline_stages(pipeline_type: str | None) -> list[str]:
|
|
|
|
|
"""Return the ordered stage list for a specific pipeline.
|
|
|
|
|
|
|
|
|
|
Falls back to STAGES (deterministic canonical order) when pipeline_type
|
|
|
|
|
is not provided or the manifest cannot be loaded.
|
|
|
|
|
|
|
|
|
|
Previous versions used a set intersection here, which produced
|
|
|
|
|
nondeterministic ordering. The fallback now uses a stable list.
|
|
|
|
|
"""
|
|
|
|
|
if pipeline_type is None:
|
|
|
|
|
# Deterministic canonical fallback — sorted to ensure stable ordering
|
|
|
|
|
import logging
|
|
|
|
|
logging.getLogger(__name__).warning(
|
|
|
|
|
"get_pipeline_stages called without pipeline_type — "
|
|
|
|
|
"using canonical fallback order. Pass pipeline_type for correctness."
|
|
|
|
|
)
|
|
|
|
|
return list(STAGES)
|
|
|
|
|
|
|
|
|
|
try:
|
2026-07-01 23:24:11 -07:00
|
|
|
from lib.pipeline_loader import load_pipeline_readonly, get_stage_order
|
|
|
|
|
manifest = load_pipeline_readonly(pipeline_type)
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
return get_stage_order(manifest)
|
|
|
|
|
except (FileNotFoundError, Exception):
|
|
|
|
|
# Graceful fallback: return all known stages in canonical order
|
|
|
|
|
return list(STAGES)
|
|
|
|
|
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
CHECKPOINT_SCHEMA_PATH = (
|
|
|
|
|
Path(__file__).resolve().parent.parent
|
|
|
|
|
/ "schemas"
|
|
|
|
|
/ "checkpoints"
|
|
|
|
|
/ "checkpoint.schema.json"
|
|
|
|
|
)
|
|
|
|
|
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
# Canonical project root. Checkpoints, artifacts, and the project marker all
|
|
|
|
|
# live under PROJECTS_DIR/<project_id>/ — this is the location the Backlot
|
|
|
|
|
# board watches. Callers may still pass a different pipeline_dir (tests do),
|
|
|
|
|
# but production runs should use the default.
|
2026-07-01 23:24:11 -07:00
|
|
|
from lib.paths import PROJECTS_DIR # noqa: E402 (single source of truth)
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
|
|
|
|
|
PROJECT_MARKER_FILENAME = "project.json"
|
|
|
|
|
HISTORY_DIRNAME = "history"
|
|
|
|
|
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
|
|
|
|
|
class CheckpointValidationError(ValueError):
|
|
|
|
|
"""Raised when a checkpoint or its canonical artifacts are invalid."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@lru_cache(maxsize=1)
|
|
|
|
|
def _load_checkpoint_schema() -> dict[str, Any]:
|
|
|
|
|
with open(CHECKPOINT_SCHEMA_PATH) as f:
|
|
|
|
|
return json.load(f)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _validate_artifacts_for_stage(
|
|
|
|
|
stage: str,
|
|
|
|
|
status: str,
|
|
|
|
|
artifacts: dict[str, Any],
|
|
|
|
|
) -> None:
|
|
|
|
|
required_artifact = CANONICAL_STAGE_ARTIFACTS[stage]
|
|
|
|
|
if status in {"completed", "awaiting_human"} and required_artifact not in artifacts:
|
|
|
|
|
raise CheckpointValidationError(
|
|
|
|
|
f"Stage {stage!r} with status {status!r} must include "
|
|
|
|
|
f"canonical artifact {required_artifact!r}"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
for artifact_name, artifact_data in artifacts.items():
|
|
|
|
|
if artifact_name not in ARTIFACT_NAMES:
|
|
|
|
|
continue
|
|
|
|
|
if not isinstance(artifact_data, dict):
|
|
|
|
|
raise CheckpointValidationError(
|
|
|
|
|
f"Artifact {artifact_name!r} must be a JSON object matching its schema"
|
|
|
|
|
)
|
|
|
|
|
try:
|
|
|
|
|
validate_artifact(artifact_name, artifact_data)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
raise CheckpointValidationError(
|
|
|
|
|
f"Artifact {artifact_name!r} failed schema validation: {exc}"
|
|
|
|
|
) from exc
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def validate_checkpoint(checkpoint: dict[str, Any]) -> None:
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
"""Validate checkpoint structure and canonical artifact payloads.
|
|
|
|
|
|
|
|
|
|
Uses pipeline_type (if present) to resolve the valid stage list.
|
|
|
|
|
Falls back to ALL_KNOWN_STAGES when pipeline_type is absent.
|
|
|
|
|
"""
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
stage = checkpoint.get("stage")
|
|
|
|
|
status = checkpoint.get("status")
|
|
|
|
|
artifacts = checkpoint.get("artifacts")
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
pipeline_type = checkpoint.get("pipeline_type")
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
valid_stages = (
|
|
|
|
|
set(get_pipeline_stages(pipeline_type)) if pipeline_type
|
|
|
|
|
else ALL_KNOWN_STAGES
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if not isinstance(stage, str) or stage not in valid_stages:
|
|
|
|
|
raise CheckpointValidationError(
|
|
|
|
|
f"Invalid stage: {stage!r} for pipeline {pipeline_type!r}. "
|
|
|
|
|
f"Valid stages: {sorted(valid_stages)}"
|
|
|
|
|
)
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
if not isinstance(status, str):
|
|
|
|
|
raise CheckpointValidationError(f"Invalid status: {status!r}")
|
|
|
|
|
if not isinstance(artifacts, dict):
|
|
|
|
|
raise CheckpointValidationError("Checkpoint artifacts must be a dictionary")
|
|
|
|
|
|
|
|
|
|
_validate_artifacts_for_stage(stage, status, artifacts)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
jsonschema.validate(instance=checkpoint, schema=_load_checkpoint_schema())
|
|
|
|
|
except jsonschema.ValidationError as exc:
|
|
|
|
|
raise CheckpointValidationError(f"Checkpoint failed schema validation: {exc.message}") from exc
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _checkpoint_path(pipeline_dir: Path, project_id: str, stage: str) -> Path:
|
|
|
|
|
return pipeline_dir / project_id / f"checkpoint_{stage}.json"
|
|
|
|
|
|
|
|
|
|
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
def init_project(
|
|
|
|
|
project_id: str,
|
|
|
|
|
*,
|
|
|
|
|
title: str,
|
|
|
|
|
pipeline_type: str,
|
|
|
|
|
pipeline_dir: Optional[Path] = None,
|
|
|
|
|
style_playbook: Optional[str] = None,
|
|
|
|
|
) -> Path:
|
|
|
|
|
"""Initialize a project workspace with the canonical layout + marker file.
|
|
|
|
|
|
|
|
|
|
Creates projects/<project_id>/ with the standard subdirectories and writes
|
|
|
|
|
project.json — the marker the Backlot board uses to render a project's
|
|
|
|
|
identity and stage rail before the first checkpoint exists.
|
|
|
|
|
|
|
|
|
|
Idempotent: re-running preserves the original created_at and merges fields.
|
|
|
|
|
Returns the project directory.
|
|
|
|
|
"""
|
|
|
|
|
base = pipeline_dir or PROJECTS_DIR
|
|
|
|
|
project_dir = base / project_id
|
|
|
|
|
for sub in (
|
|
|
|
|
"artifacts",
|
|
|
|
|
"assets/images",
|
|
|
|
|
"assets/video",
|
|
|
|
|
"assets/audio",
|
|
|
|
|
"assets/music",
|
|
|
|
|
"renders",
|
|
|
|
|
):
|
|
|
|
|
(project_dir / sub).mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
marker_path = project_dir / PROJECT_MARKER_FILENAME
|
|
|
|
|
marker: dict[str, Any] = {}
|
|
|
|
|
if marker_path.exists():
|
|
|
|
|
try:
|
|
|
|
|
with open(marker_path) as f:
|
|
|
|
|
marker = json.load(f)
|
|
|
|
|
except (json.JSONDecodeError, OSError):
|
|
|
|
|
marker = {}
|
|
|
|
|
|
|
|
|
|
marker.setdefault("version", "1.0")
|
|
|
|
|
marker.setdefault("created_at", datetime.now(timezone.utc).isoformat())
|
|
|
|
|
marker["project_id"] = project_id
|
|
|
|
|
marker["title"] = title
|
|
|
|
|
marker["pipeline_type"] = pipeline_type
|
|
|
|
|
if style_playbook is not None:
|
|
|
|
|
marker["style_playbook"] = style_playbook
|
|
|
|
|
|
|
|
|
|
with open(marker_path, "w") as f:
|
|
|
|
|
json.dump(marker, f, indent=2)
|
|
|
|
|
|
|
|
|
|
return project_dir
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _stage_requires_approval(pipeline_type: Optional[str], stage: str) -> Optional[bool]:
|
|
|
|
|
"""Read human_approval_default for a stage from its pipeline manifest.
|
|
|
|
|
|
2026-07-01 23:24:11 -07:00
|
|
|
Returns None when the stage isn't declared in the manifest or no
|
|
|
|
|
pipeline_type was given — the caller then falls back to the value the
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
agent passed in.
|
2026-07-01 23:24:11 -07:00
|
|
|
|
|
|
|
|
A *provided but unknown* pipeline_type raises: a typo must not silently
|
|
|
|
|
disable gate enforcement (fail-closed, not fail-open). Other manifest
|
|
|
|
|
load failures are logged and fall back — a corrupt manifest shouldn't
|
|
|
|
|
strand an otherwise-valid run, but the degradation must be visible.
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
"""
|
|
|
|
|
if not pipeline_type or pipeline_type == "unknown":
|
|
|
|
|
return None
|
2026-07-01 23:24:11 -07:00
|
|
|
from lib.pipeline_loader import get_stage_human_approval_default, load_pipeline_readonly
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
try:
|
2026-07-01 23:24:11 -07:00
|
|
|
manifest = load_pipeline_readonly(pipeline_type)
|
|
|
|
|
except FileNotFoundError:
|
|
|
|
|
raise CheckpointValidationError(
|
|
|
|
|
f"Unknown pipeline_type {pipeline_type!r} — cannot resolve gate "
|
|
|
|
|
f"policy for stage {stage!r}. Check the spelling against "
|
|
|
|
|
f"pipeline_defs/*.yaml."
|
|
|
|
|
)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
import logging
|
|
|
|
|
logging.getLogger(__name__).warning(
|
|
|
|
|
"Gate policy unavailable for pipeline %r (%s) — falling back to "
|
|
|
|
|
"the caller's human_approval_required flag.", pipeline_type, exc,
|
|
|
|
|
)
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
return None
|
2026-07-01 23:24:11 -07:00
|
|
|
return get_stage_human_approval_default(manifest, stage)
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def _archive_superseded_checkpoint(path: Path, stage: str) -> None:
|
2026-07-01 23:24:11 -07:00
|
|
|
"""Copy an existing checkpoint into history/ before it is overwritten.
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
|
|
|
|
|
Preserves the full run record: stage re-runs (script v1 → v2) and gate
|
|
|
|
|
transitions (awaiting_human → completed) remain reconstructable. Repeated
|
|
|
|
|
in_progress refreshes are NOT archived — they are partial-progress
|
|
|
|
|
heartbeats, not versions.
|
2026-07-01 23:24:11 -07:00
|
|
|
|
|
|
|
|
Archiving is best-effort and must never crash a checkpoint write: the
|
|
|
|
|
Backlot watcher may hold the file open (Windows denies renames of open
|
|
|
|
|
files), so we copy rather than move, and swallow archival I/O failures.
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
"""
|
|
|
|
|
if not path.exists():
|
|
|
|
|
return
|
|
|
|
|
try:
|
|
|
|
|
with open(path) as f:
|
|
|
|
|
existing = json.load(f)
|
|
|
|
|
except (json.JSONDecodeError, OSError):
|
|
|
|
|
existing = {}
|
|
|
|
|
if existing.get("status") == "in_progress":
|
|
|
|
|
return
|
|
|
|
|
|
2026-07-01 23:24:11 -07:00
|
|
|
try:
|
|
|
|
|
import shutil
|
|
|
|
|
stamp = str(existing.get("timestamp", ""))
|
|
|
|
|
safe_stamp = "".join(c for c in stamp if c.isalnum()) or f"{path.stat().st_mtime_ns}"
|
|
|
|
|
history_dir = path.parent / HISTORY_DIRNAME
|
|
|
|
|
history_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
target = history_dir / f"checkpoint_{stage}_{safe_stamp}.json"
|
|
|
|
|
if target.exists():
|
|
|
|
|
target = history_dir / f"checkpoint_{stage}_{safe_stamp}_{path.stat().st_mtime_ns}.json"
|
|
|
|
|
shutil.copyfile(path, target)
|
|
|
|
|
except OSError:
|
|
|
|
|
import logging
|
|
|
|
|
logging.getLogger(__name__).warning(
|
|
|
|
|
"Could not archive superseded checkpoint %s to history/", path
|
|
|
|
|
)
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
|
|
|
|
|
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
def _decision_log_path(pipeline_dir: Path, project_id: str) -> Path:
|
|
|
|
|
return pipeline_dir / project_id / "decision_log.json"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _merge_decision_log(
|
|
|
|
|
pipeline_dir: Path, project_id: str, new_log: dict[str, Any]
|
|
|
|
|
) -> None:
|
|
|
|
|
"""Append new decisions to the project-level decision log.
|
|
|
|
|
|
|
|
|
|
Each stage may produce decisions. This function merges them into a
|
|
|
|
|
single cumulative file so reviewers and the bench can inspect the
|
|
|
|
|
full audit trail.
|
|
|
|
|
"""
|
|
|
|
|
path = _decision_log_path(pipeline_dir, project_id)
|
|
|
|
|
if path.exists():
|
|
|
|
|
with open(path) as f:
|
|
|
|
|
existing = json.load(f)
|
|
|
|
|
else:
|
|
|
|
|
existing = {
|
|
|
|
|
"version": "1.0",
|
|
|
|
|
"project_id": project_id,
|
|
|
|
|
"decisions": [],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
existing_ids = {d["decision_id"] for d in existing.get("decisions", [])}
|
|
|
|
|
for decision in new_log.get("decisions", []):
|
|
|
|
|
if decision.get("decision_id") not in existing_ids:
|
|
|
|
|
existing["decisions"].append(decision)
|
|
|
|
|
|
|
|
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
with open(path, "w") as f:
|
|
|
|
|
json.dump(existing, f, indent=2)
|
|
|
|
|
|
|
|
|
|
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
def write_checkpoint(
|
|
|
|
|
pipeline_dir: Path,
|
|
|
|
|
project_id: str,
|
|
|
|
|
stage: str,
|
|
|
|
|
status: str,
|
|
|
|
|
artifacts: dict[str, Any],
|
|
|
|
|
*,
|
|
|
|
|
pipeline_type: Optional[str] = None,
|
|
|
|
|
style_playbook: Optional[str] = None,
|
|
|
|
|
checkpoint_policy: str = "guided",
|
|
|
|
|
human_approval_required: bool = False,
|
|
|
|
|
human_approved: bool = False,
|
|
|
|
|
review: Optional[dict] = None,
|
|
|
|
|
cost_snapshot: Optional[dict] = None,
|
|
|
|
|
error: Optional[str] = None,
|
|
|
|
|
metadata: Optional[dict] = None,
|
|
|
|
|
) -> Path:
|
|
|
|
|
"""Write a checkpoint file for a pipeline stage."""
|
2026-07-01 23:24:11 -07:00
|
|
|
# Backfill a missing pipeline_type from the project marker so that
|
|
|
|
|
# omitting the kwarg doesn't quietly bypass gate enforcement.
|
|
|
|
|
if not pipeline_type:
|
|
|
|
|
marker = None
|
|
|
|
|
marker_path = pipeline_dir / project_id / PROJECT_MARKER_FILENAME
|
|
|
|
|
if marker_path.exists():
|
|
|
|
|
try:
|
|
|
|
|
with open(marker_path) as f:
|
|
|
|
|
marker = json.load(f)
|
|
|
|
|
except (json.JSONDecodeError, OSError):
|
|
|
|
|
marker = None
|
|
|
|
|
if isinstance(marker, dict) and marker.get("pipeline_type"):
|
|
|
|
|
pipeline_type = marker["pipeline_type"]
|
|
|
|
|
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
valid_stages = (
|
|
|
|
|
set(get_pipeline_stages(pipeline_type)) if pipeline_type
|
|
|
|
|
else ALL_KNOWN_STAGES
|
|
|
|
|
)
|
|
|
|
|
if stage not in valid_stages:
|
|
|
|
|
raise ValueError(
|
|
|
|
|
f"Invalid stage: {stage!r} for pipeline {pipeline_type!r}. "
|
|
|
|
|
f"Valid stages: {sorted(valid_stages)}"
|
|
|
|
|
)
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
# --- Gate enforcement (GI-4) ---
|
|
|
|
|
# The pipeline manifest is the binding source of truth for whether a stage
|
2026-07-01 23:24:11 -07:00
|
|
|
# gates on human approval; a caller may gate MORE strictly (e.g. a
|
|
|
|
|
# manual_all checkpoint policy) but never less. A gated stage can only be
|
|
|
|
|
# written "completed" with explicit evidence of approval
|
|
|
|
|
# (human_approved=True). Skipping a gate is a hard error.
|
|
|
|
|
#
|
|
|
|
|
# Enforcement happens at write time only: pre-existing checkpoints written
|
|
|
|
|
# before gating (or by hand) still read as completed — deliberate
|
|
|
|
|
# back-compat so in-flight and legacy projects keep resuming.
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
manifest_gate = _stage_requires_approval(pipeline_type, stage)
|
2026-07-01 23:24:11 -07:00
|
|
|
gated = bool(manifest_gate) or human_approval_required
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
if gated:
|
|
|
|
|
human_approval_required = True
|
|
|
|
|
if status == "completed" and not human_approved:
|
2026-07-01 23:24:11 -07:00
|
|
|
gate_source = (
|
|
|
|
|
f"human_approval_default: true in the {pipeline_type!r} manifest"
|
|
|
|
|
if manifest_gate
|
|
|
|
|
else "human_approval_required=True was passed by the caller"
|
|
|
|
|
)
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
raise CheckpointValidationError(
|
|
|
|
|
f"GATE VIOLATION: stage {stage!r} requires human approval "
|
2026-07-01 23:24:11 -07:00
|
|
|
f"({gate_source}) but status='completed' was written without "
|
|
|
|
|
f"human_approved=True. Correct protocol: write "
|
|
|
|
|
f"status='awaiting_human', present the artifact summary to the "
|
|
|
|
|
f"user, END YOUR TURN, and only after the user approves "
|
|
|
|
|
f"re-write with status='completed', human_approved=True."
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
)
|
|
|
|
|
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
checkpoint = {
|
|
|
|
|
"version": "1.0",
|
|
|
|
|
"project_id": project_id,
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
"pipeline_type": pipeline_type or "unknown",
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
"stage": stage,
|
|
|
|
|
"status": status,
|
|
|
|
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
|
|
|
"checkpoint_policy": checkpoint_policy,
|
|
|
|
|
"human_approval_required": human_approval_required,
|
|
|
|
|
"human_approved": human_approved,
|
|
|
|
|
"artifacts": artifacts,
|
|
|
|
|
}
|
|
|
|
|
if style_playbook is not None:
|
|
|
|
|
checkpoint["style_playbook"] = style_playbook
|
|
|
|
|
if review is not None:
|
|
|
|
|
checkpoint["review"] = review
|
|
|
|
|
if cost_snapshot is not None:
|
|
|
|
|
checkpoint["cost_snapshot"] = cost_snapshot
|
|
|
|
|
if error is not None:
|
|
|
|
|
checkpoint["error"] = error
|
|
|
|
|
if metadata is not None:
|
|
|
|
|
checkpoint["metadata"] = metadata
|
|
|
|
|
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
# Merge decision_log: if this checkpoint carries new decisions,
|
|
|
|
|
# append them to the project-level decision log file, then write the
|
|
|
|
|
# reference back into relevant artifacts so downstream consumers can find it.
|
|
|
|
|
if "decision_log" in artifacts and isinstance(artifacts["decision_log"], dict):
|
|
|
|
|
_merge_decision_log(pipeline_dir, project_id, artifacts["decision_log"])
|
|
|
|
|
log_ref = str(_decision_log_path(pipeline_dir, project_id))
|
|
|
|
|
|
|
|
|
|
# Write decision_log_ref into proposal_packet and render_report
|
|
|
|
|
# artifacts if they are present in this checkpoint.
|
|
|
|
|
for artifact_key in ("proposal_packet", "render_report"):
|
|
|
|
|
if artifact_key in artifacts and isinstance(artifacts[artifact_key], dict):
|
|
|
|
|
plan_or_top = artifacts[artifact_key]
|
|
|
|
|
# proposal_packet stores it under production_plan
|
|
|
|
|
if artifact_key == "proposal_packet":
|
|
|
|
|
plan = plan_or_top.get("production_plan")
|
|
|
|
|
if isinstance(plan, dict):
|
|
|
|
|
plan["decision_log_ref"] = log_ref
|
|
|
|
|
else:
|
|
|
|
|
plan_or_top["decision_log_ref"] = log_ref
|
|
|
|
|
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
validate_checkpoint(checkpoint)
|
|
|
|
|
|
|
|
|
|
path = _checkpoint_path(pipeline_dir, project_id, stage)
|
|
|
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
2026-07-01 23:24:11 -07:00
|
|
|
# Serialize to a temp file first so a mid-write failure (disk full,
|
|
|
|
|
# unserializable metadata) can never leave the stage with a truncated
|
|
|
|
|
# current checkpoint; then archive the superseded file and swap in the
|
|
|
|
|
# new one atomically.
|
|
|
|
|
tmp_path = path.with_suffix(".json.tmp")
|
|
|
|
|
with open(tmp_path, "w") as f:
|
|
|
|
|
json.dump(checkpoint, f, indent=2)
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
# Preserve run history: a superseded completed/awaiting_human checkpoint
|
2026-07-01 23:24:11 -07:00
|
|
|
# is copied to history/ (stage versioning, gate audit trail, replay).
|
backlot phase 0: artifact contract + gate hardening
- init_project() writes project.json marker + canonical workspace layout
- write_checkpoint enforces approval gates: completed on a gated stage
requires human_approved=True (GATE VIOLATION otherwise)
- superseded checkpoints archived to projects/<id>/history/ (stage
versioning, gate audit trail, replay)
- BaseTool auto-instruments execute() -> projects/<id>/events.jsonl
(start/finish/error, scene_id, cost) for the Backlot live board
- assets stage now gates (human_approval_default: true) in all manifests
- checkpoint-protocol + AGENT_GUIDE: manifest gate value is binding,
awaiting_human + end-turn protocol, per-gate approval, canonical
checkpoint location fixed to projects/<id>/
- gate reminder footer on all gating stage director skills
- /backlot command files for Claude Code, Codex, Cursor, Copilot
2026-07-01 23:08:51 -07:00
|
|
|
_archive_superseded_checkpoint(path, stage)
|
2026-07-01 23:24:11 -07:00
|
|
|
import os
|
|
|
|
|
os.replace(tmp_path, path)
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
|
|
|
|
|
return path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def read_checkpoint(
|
|
|
|
|
pipeline_dir: Path, project_id: str, stage: str
|
|
|
|
|
) -> Optional[dict[str, Any]]:
|
|
|
|
|
"""Read a checkpoint file. Returns None if not found."""
|
|
|
|
|
path = _checkpoint_path(pipeline_dir, project_id, stage)
|
|
|
|
|
if not path.exists():
|
|
|
|
|
return None
|
|
|
|
|
with open(path) as f:
|
|
|
|
|
checkpoint = json.load(f)
|
|
|
|
|
validate_checkpoint(checkpoint)
|
|
|
|
|
return checkpoint
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_latest_checkpoint(
|
|
|
|
|
pipeline_dir: Path, project_id: str
|
|
|
|
|
) -> Optional[dict[str, Any]]:
|
|
|
|
|
"""Find the most recent checkpoint for a project (by file mtime)."""
|
|
|
|
|
project_dir = pipeline_dir / project_id
|
|
|
|
|
if not project_dir.exists():
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
checkpoints = sorted(
|
|
|
|
|
project_dir.glob("checkpoint_*.json"),
|
|
|
|
|
key=lambda p: p.stat().st_mtime,
|
|
|
|
|
reverse=True,
|
|
|
|
|
)
|
|
|
|
|
if not checkpoints:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
with open(checkpoints[0]) as f:
|
|
|
|
|
checkpoint = json.load(f)
|
|
|
|
|
validate_checkpoint(checkpoint)
|
|
|
|
|
return checkpoint
|
|
|
|
|
|
|
|
|
|
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
def get_completed_stages(
|
|
|
|
|
pipeline_dir: Path, project_id: str, pipeline_type: str | None = None
|
|
|
|
|
) -> list[str]:
|
|
|
|
|
"""Return list of stages that have a completed checkpoint.
|
|
|
|
|
|
|
|
|
|
When pipeline_type is provided, only checks stages defined in that
|
|
|
|
|
pipeline's manifest — preventing false positives from leftover
|
|
|
|
|
checkpoints of a different pipeline type.
|
|
|
|
|
"""
|
|
|
|
|
stages_to_check = get_pipeline_stages(pipeline_type)
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
completed = []
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
for stage in stages_to_check:
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
cp = read_checkpoint(pipeline_dir, project_id, stage)
|
|
|
|
|
if cp and cp.get("status") == "completed":
|
|
|
|
|
completed.append(stage)
|
|
|
|
|
return completed
|
|
|
|
|
|
|
|
|
|
|
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)
2026-04-03 09:35:09 -07:00
|
|
|
def get_next_stage(
|
|
|
|
|
pipeline_dir: Path, project_id: str, pipeline_type: str | None = None
|
|
|
|
|
) -> Optional[str]:
|
|
|
|
|
"""Determine the next stage to run based on completed checkpoints.
|
|
|
|
|
|
|
|
|
|
Uses pipeline-specific stage order so that pipelines with different
|
|
|
|
|
stage sequences (e.g. cinematic vs explainer) progress correctly.
|
|
|
|
|
"""
|
|
|
|
|
stages = get_pipeline_stages(pipeline_type) if pipeline_type else STAGES
|
|
|
|
|
completed = set(get_completed_stages(pipeline_dir, project_id, pipeline_type))
|
|
|
|
|
for stage in stages:
|
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>
2026-03-29 08:25:17 -07:00
|
|
|
if stage not in completed:
|
|
|
|
|
return stage
|
|
|
|
|
return None
|