From cbb24bd034f2dbb9dfc88d658dd248c25fda47e6 Mon Sep 17 00:00:00 2001 From: cxw Date: Wed, 12 Aug 2026 01:43:26 +0800 Subject: [PATCH] =?UTF-8?q?docs(skills):=20plan/assemble=20craft=20?= =?UTF-8?q?=E2=80=94=20validator-true=20prose,=20the=20signature-safe=20en?= =?UTF-8?q?velope,=20and=20coverage=20as=20QA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sync of the plan/edit/assemble refinements from Orkas release_1.6.5 (9378b315a, e2a2797f3, 33904ce59, f9cd7a16d, 13c145d6a, 3b9451d78, fb1cd2991, 8a94dc1c0 context), prompt-only, re-mapped onto the ovs pack: - stage-plan: edit_strategy is four non-empty string ARRAYS at the plan top level with a closed decision-signal set (the validator already enforced E_EDIT_STRATEGY_BOUNDARY/E_EDIT_STRATEGY_SIGNAL; the prose never said so); target_sec is a DURATION and windows must not overlap (E_NARRATION_WINDOWS_OVERLAP, landed in #15); a temporal anchor signs the consumed interval; flagged risks resolve at the Production plan confirmation (both stray "direction confirmation" pointers fixed); full-frame overlays are a plan-shape problem (the guard landed in #14); silent beats are reserved, not speech budget; Gate B is two turns — present the validator's own summary verbatim, never twice, and "an unapproved plan after the user answered means you owe the transition, not another confirmation". - stage-edit: the array-shape rule with its error code; may_change must name every authorized change class; delivery locators move into the reserved `_runtime` envelope — the old instruction to write top-level `draft`/`video` keys invalidated the Gate B signature on success, because unknown top-level plan fields are approval-bearing by gate-control's own rule (approval.ts reserves `_runtime`/`_catalog`). - stage-assemble: the real trim flags (`--start/--end/--out`); only compose segments need frame evidence (media segments are captured by their produced_path); the overlay-opaque refusal is a re-plan, not a retry; the coverage report is QA — coverageRatio only says how far the LAST line reached, a half-silent track can still score 0.95; never speed up speech or pad with filler; skip a caption line that repeats visible on-screen copy; delivery QA holds every route to the same bar, including hand-written ffmpeg; `_runtime` write-back rule. - orchestration: the plan.json record points at `_runtime.render.*` instead of a top-level `draft` key; narration fit revises OVER only. Verified: full OVS_E2E=1 suite 275/276; content tests pin the error codes, the envelope rule, the 0.95 trap, and the two-turn Gate B. Prompt audit: every added clause states behavior the code actually has (validator codes from #15, the overlay guard from #14, the reserved envelope in approval.ts) or fixes prose that contradicted it (top-level draft/video keys, "direction confirmation" pointers, over/under fit); no clause duplicates gate-control authorization or #19's checkpoint craft; the trim command was verified against the CLI definition. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01VL7mRpmEphLAbcH7YmABnV --- packages/skills/orchestration/SKILL.md | 4 ++-- packages/skills/stage-assemble/SKILL.md | 14 +++++++----- packages/skills/stage-edit/SKILL.md | 4 ++-- packages/skills/stage-plan/SKILL.md | 16 ++++++------- packages/skills/test/skills-content.test.ts | 25 +++++++++++++++++++++ 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/packages/skills/orchestration/SKILL.md b/packages/skills/orchestration/SKILL.md index 51dd74c..ce4d669 100644 --- a/packages/skills/orchestration/SKILL.md +++ b/packages/skills/orchestration/SKILL.md @@ -45,7 +45,7 @@ For COMPOSE or AUTO compose segments, also apply `frontend-design` before writin ## 2.6 Narration voice -When the piece has voiceover, run `ovs speech-capabilities` and copy its executable route/model/voice/format into the Gate B plan together with the BCP-47 video language and a natural speed. Do not invent a voice id. Before Gate B, run `ovs narration fit --text ... --target ...`; revise over/under text internally before any paid synthesis. After `ovs speak`, probe the produced audio and run the same fit with `--measured`; retime scenes from the measured duration without silently shortening the approved target. If no TTS provider is configured, tell the user and explicitly choose silent delivery or wait for configuration. +When the piece has voiceover, run `ovs speech-capabilities` and copy its executable route/model/voice/format into the Gate B plan together with the BCP-47 video language and a natural speed. Do not invent a voice id. Before Gate B, run `ovs narration fit --text ... --target ...`; revise OVER-budget text internally before any paid synthesis — a read that finishes early is an accepted delivery, so pad or extend only when the trailing silence is not the ending you intended. After `ovs speak`, probe the produced audio and run the same fit with `--measured`; retime scenes from the measured duration without silently shortening the approved target. If no TTS provider is configured, tell the user and explicitly choose silent delivery or wait for configuration. TALKING-HEAD note: if a GENERATE clip already returned lip-synced built-in speech, THAT is the voice — do NOT synthesize a narration over it (a fresh TTS track desyncs from the mouth). Use `ovs speak` only for a silent clip, or for COMPOSE / EDIT / off-screen voiceover. @@ -92,7 +92,7 @@ Ingest every supplied clip from evidence (probe + transcribe/OCR-or-frame-readin ## plan.json as the editable record (all lines) — keep follow-up edits cheap -Once a draft exists, keep `project/plan.json` faithful so a later tweak only re-touches one piece (never the whole video): (1) every produced segment carries its real output under `produced_path` + `status:"done"`; (2) narration is `tracks.narration` whose lines each carry their own `produced_path`, so one line can be re-voiced alone; (3) captions are DATA in `tracks.captions.lines` ({text, start_sec, target_sec}) — NOT burned into the picture — so a typo is a one-line edit re-burned at assemble; (4) set top-level `"draft": "render/draft.mp4"`. +Once a draft exists, keep `project/plan.json` faithful so a later tweak only re-touches one piece (never the whole video): (1) every produced segment carries its real output under `produced_path` + `status:"done"`; (2) narration is `tracks.narration` whose lines each carry their own `produced_path`, so one line can be re-voiced alone; (3) captions are DATA in `tracks.captions.lines` ({text, start_sec, target_sec}) — NOT burned into the picture — so a typo is a one-line edit re-burned at assemble; (4) record delivery outputs under the reserved `_runtime` envelope (`"_runtime": {"render": {"draft": "render/draft.mp4"}}`), never as a new top-level key — unknown top-level plan fields are approval-bearing, so a root `draft` key would invalidate the recorded Gate B approval. **Local follow-up edits — make the minimal targeted change; never redo the whole video.** Once a `plan.json` is present and the user asks to change ONE local thing (a segment's narration / caption / text, a trim, volume / speed, a single shot swap), edit ONLY the matching entry in `plan.json` and re-produce ONLY what it touched (`ovs speak` for that one line, `ovs draft` for that one compose segment, or `ovs edit` for that one cut), then re-assemble. Do NOT re-author the whole EDL and DO NOT regenerate a segment whose `status` is `done` that the user did not touch. Fall back to a full re-plan only when the request genuinely restructures the timeline. diff --git a/packages/skills/stage-assemble/SKILL.md b/packages/skills/stage-assemble/SKILL.md index e203010..832c532 100644 --- a/packages/skills/stage-assemble/SKILL.md +++ b/packages/skills/stage-assemble/SKILL.md @@ -11,22 +11,24 @@ How to execute a validated `project/plan.json` into one finished file. By the ti 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`. +- **edit** → `stage-edit`: `ovs edit trim` the `input_id` to `[in_sec, out_sec]` → `project/cuts/.mp4`. Those are the EDL's field names, not flags — the command is `ovs edit trim --start --end --out 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. +Only `compose` segments need snapshot/frame QA evidence, because their artifact is HTML. An `edit`/`generate`/`provided` segment is captured by its own `produced_path` file the moment that file exists — never run a composition QA phase on one, and never treat it as unfinished work because it has no frame evidence. + ## 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. -2. **Overlays / bg** — 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 `