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:
|
|
|
|
|
from lib.pipeline_loader import load_pipeline, get_stage_order
|
|
|
|
|
manifest = load_pipeline(pipeline_type)
|
|
|
|
|
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"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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"
|
|
|
|
|
|
|
|
|
|
|
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."""
|
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
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
with open(path, "w") as f:
|
|
|
|
|
json.dump(checkpoint, f, indent=2)
|
|
|
|
|
|
|
|
|
|
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
|