Phase 3: Department Interpretation — Directing + Cinematography per scene

Layer 4 implementation:
- Per-scene directing: scene_objective, audience_takeaway, pacing, dramatic
  beats, subtext, continuity considerations
- Per-scene cinematography: camera style, lens, movement, framing, DoF,
  color palette, visual emphasis, continuity considerations
- All interpretation grounded in L2 scene data + L3 Production Bible
- Bible entries passed as context per scene (matching characters + location)
- Validator: empty fields, broken refs, bible ref checks, uncertain values
- Per-scene versioned output + combined department_interpretation_v1.json
- CLI: --phase 3, --scene N for single-scene re-run

Tested on the_last_backup: 12/12 scenes valid, 0 failures, 5 warnings
(false positives from prop names in all-caps like BLACK PORTABLE SSD)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-06 17:31:23 -07:00
co-authored by Claude Opus 4.6
parent 17e410751c
commit 3b5ef3596a
7 changed files with 564 additions and 40 deletions
+21 -1
View File
@@ -14,7 +14,7 @@ def main():
parser = argparse.ArgumentParser(description="AI Movie Production Pipeline")
parser.add_argument("--script", type=str, help="Path to .fountain script file (Phase 1)")
parser.add_argument("--project", type=str, help="Project name (determines output directory)")
parser.add_argument("--phase", type=int, default=None, choices=[1, 2], help="Run specific phase only (1=ingestion+extraction, 2=bible)")
parser.add_argument("--phase", type=int, default=None, choices=[1, 2, 3], help="Run specific phase (1=extraction, 2=bible, 3=departments)")
parser.add_argument("--model", type=str, default="qwen3:14b", help="Model ID (default: qwen3:14b)")
parser.add_argument("--backend", type=str, default="ollama", choices=["ollama", "anthropic"], help="AI backend (default: ollama)")
parser.add_argument("--ollama-url", type=str, default="http://localhost:11434", help="Ollama server URL")
@@ -40,6 +40,7 @@ def main():
run_phase1_flag = args.phase is None or args.phase == 1
run_phase2_flag = args.phase is None or args.phase == 2
run_phase3_flag = args.phase is None or args.phase == 3
# Phase 1: Script Ingestion + Understanding
if run_phase1_flag:
@@ -88,6 +89,25 @@ def main():
print(f"\nPHASE 2 FAILED: {bible_result.stop_reason}")
sys.exit(1)
# Phase 3: Department Interpretation
if run_phase3_flag:
from src.departments.runner import run_phase3
dept_result = run_phase3(
project_name=args.project,
model=args.model,
backend=args.backend,
ollama_url=args.ollama_url,
api_key=api_key,
output_dir=args.output_dir,
scene_filter=args.scene,
dry_run=args.dry_run,
)
if not dept_result.success:
print(f"\nPHASE 3 FAILED: {dept_result.stop_reason}")
sys.exit(1)
print("\nPIPELINE COMPLETE")
sys.exit(0)