--- name: stage-assemble description: Deterministically assemble an approved cross-modal EDL (plan.json) into a finished video — produce each segment (edit/compose/generate/provided, delegated to its line), then assemble in ffmpeg tiers: concat primaries → overlay composed layers → mix narration once (coverage check) → burn captions → verify loudness; idempotent-resumable, with QA before the draft gate. Trigger after a plan is validated and approved; do NOT trigger to ingest or re-author the plan (stage-plan). --- # stage-assemble How to execute a validated `project/plan.json` into one finished file. By the time you are here the plan passed `ovs plan validate` and the user approved it at gate B. Walk it; do not re-plan. The producers are `ovs edit`, `ovs draft`, `ovs video`/`ovs image`, `ovs speak`, and the assembler is `ovs edit` (or the equivalent MCP tools). ## Step 1 — Produce each segment (delegate by source) Iterate segments in `order`. For each, produce its `produced_path` according to `source`, then write that path + `status:"done"` back into the segment so a resume never re-produces it: - **edit** → `stage-edit`: `ovs edit trim` the `input_id` to `[in_sec, out_sec]` → `project/cuts/.mp4`. - **compose** → `stage-compose`: build a small visual-only manifest-owned composition for `spec.kind` (title card, lower-third, stat card, captions) under `project/compositions//` → run `ovs draft project/compositions/ --out project/parts/.mp4 --quality draft --report project/reports/-compose-report.json`. This keeps compose segments on the same manifest/source/check/video-QA path as standalone COMPOSE while still letting the assembler own narration and loudness. - **generate** → `stage-generate` (+ `stage-consistency` for recurring characters): only AFTER gate C. `ovs video`/`ovs image` → `project/assets/.mp4`. For `operation:"edit"`, pass the exact original reference video and obey top-level `references` plus `edit_strategy`; never widen it into regeneration. A failed/unknown paid attempt is not an automatic retry. Preserve completed siblings and require a new output path for any later authorized attempt. - **provided** → use `spec.asset_id` as-is (probe it first; conform aspect/fps if needed). Billable `generate` segments must not run before gate C has confirmed the count from `cost_estimate`. Produce cheap/free segments (edit, compose, provided) freely. ## Step 2 — Assemble in ffmpeg tiers (the default path) Assemble deterministically, bottom-up. This tiered order is the default; it is predictable and cheap, and keeps each clip's real audio intact: 1. **Primary track** — `ovs edit concat` the primary-layer `produced_path`s in `order` → `project/render/primary.mp4`. Conform aspect/fps on the way in if sources differ; read the returned conformance report and verify it still matches the approved canvas. 2. **Overlays / bg** — Do not place a full-frame opaque composed video over source footage: it erases the base. Use genuinely transparent or bounded overlays, or amend the plan to make it a primary beat. Do not bypass the opaque-overlay refusal with resizing tricks. for each overlay/bg segment, `ovs edit overlay` its part onto the primary over the window of the segment named in `over` (title cards, lower-thirds, logos). Composed layers are VISUAL-ONLY — they must not carry their own narration audio. **This includes a compose segment that IS the primary track (a full-video composition): render it SILENT — do not put a narration `