video-editing 1.3.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,254 +1,189 @@
1
1
  ---
2
2
  name: video-editing
3
3
  description: >-
4
- Edit a talking-head video reel into a tight, clean cut using ONLY the local
5
- `video-editing` CLI never the video-use repo, never the clean-cut skill,
6
- never raw Python helpers or ffmpeg by hand. Removes bad retakes, false starts,
7
- stutters and cut-off words (keep the LAST complete take, but keep the CLEANEST
8
- take when an earlier one is clean and a later one stutters), tightens every
9
- pause to ~0.13s, cold-opens on the strongest hook, trims outro dead air.
10
- Vertical 9:16, clean cuts only (no grade/subtitles/overlays by default). Two
11
- mandatory gates: SCREEN before cutting and CONTENT-VERIFY (re-transcribe the
12
- rendered preview at every join) after. Use whenever the user drops a
13
- talking-head clip / reel / vlog / interview and wants it edited or tightened —
14
- phrasings like "edit this reel", "cut the bad retakes", "remove the false
15
- starts", "clean up this recording", "tighten this reel", "tighten this", "I
16
- flubbed some lines, fix it", "get rid of the dead air", "make a clean cut of
17
- this", or just a video path with "make this cleaner". Handles Hebrew/RTL.
18
- This is the single source of truth for reel edits; it supersedes and replaces
19
- the clean-cut and video-use skills.
4
+ Cloud agent workflow for editing a talking-head video into a tight, clean
5
+ cut with the `video-editing` CLI + the ClipReady cloud. The CLI is a PURE
6
+ API client requirements are Node 20 and a ClipReady API key
7
+ (`CLIPREADY_API_KEY`) only; no ffmpeg, no ffprobe, no local rendering
8
+ tools. The source uploads once at init; transcription, editorial
9
+ screening, timeline compilation, rendering, verification, and QA visuals
10
+ all run server-side; the editorial brief arrives from the server as pulled
11
+ `prompts/*.md`. Use whenever the user drops a talking-head clip / reel /
12
+ vlog / interview and wants it edited or tightened "edit this reel",
13
+ "cut the bad retakes", "clean up this recording", "tighten this",
14
+ "add captions", or just a video path with an editing ask — or when
15
+ working a ClipReady review round. Handles Hebrew/RTL.
20
16
  ---
21
17
 
22
- # Video Editing (CLI-only)
18
+ # Video Editing (ClipReady cloud — pure API client)
23
19
 
24
- Turn a raw talking-head recording into a tight, clean vertical cut. The local
25
- **`video-editing`** CLI is the single source of truth and owns ALL execution
26
- (probe, transcribe, screen, bake master, render, QC, content-verify). **You**
27
- read the transcript and author the EDL; the CLI does everything executable.
20
+ Turn a raw talking-head recording into a tight, clean cut. The
21
+ **`video-editing`** CLI (v3) is a pure API client for the ClipReady cloud: the
22
+ cloud owns EVERYTHING executable — probing, transcription, screening,
23
+ editorial prompts, timeline compilation, rendering, verification, and QA
24
+ visuals. Your machine only streams the source up once and pulls small
25
+ artifacts back. **You** read the pulled transcript + brief and author
26
+ `timeline.json`; the CLI does the rest over HTTP.
28
27
 
29
- ## Install
30
-
31
- Requirements: **Node ≥ 20**, **ffmpeg**/**ffprobe** on PATH, and an **ElevenLabs API key**
32
- (`ELEVENLABS_API_KEY`) for transcription.
28
+ ## Install & auth
33
29
 
34
30
  ```bash
35
- npm install -g video-editing # the CLI
31
+ npm install -g video-editing # the CLI (v3)
36
32
  npx skills add ItayElgazar/clipready --skill video-editing # this skill
37
33
  ```
38
34
 
35
+ Requirements — this is the FULL list:
36
+
37
+ - **Node ≥ 20**
38
+ - **A ClipReady API key** — one-time login: `video-editing auth api-key` (paste
39
+ the key from the ClipReady settings page; the base URL defaults to the hosted
40
+ cloud). Env vars `CLIPREADY_API_KEY`/`CLIPREADY_API_BASE` override when set.
41
+
42
+ **No ffmpeg. No ffprobe. No hyperframes. No ElevenLabs key.** Nothing runs on
43
+ the local machine except the CLI itself — do not install media tools, and do
44
+ not set or ask for `ELEVENLABS_API_KEY`.
45
+
46
+ **Every command fails without the API key.** If a verb errors with a
47
+ missing-key message, stop and ask the user for their ClipReady API key;
48
+ never work around it.
49
+
39
50
  ## HARD RULE — execution boundary (read first)
40
51
 
41
52
  - Use **only** the `video-editing` CLI (`video-editing <subcommand>`). Run
42
53
  `video-editing --help` to see commands.
43
- - **NEVER** run ffmpeg/ffprobe/transcription by hand — the CLI owns all execution.
44
- - If a capability seems missing, STOP and report it as a CLI gap. Do not reach around the CLI.
45
- - Your only hand-authored artifact is `<job>/edl.json`.
46
-
47
- ## Prerequisites
48
-
49
- - `video-editing` on PATH (`which video-editing`), plus `ffmpeg`/`ffprobe`.
50
- - ElevenLabs key: the CLI owns it (env `ELEVENLABS_API_KEY` or `~/.config/video-editing/.env`;
51
- set once with `video-editing config set-key <key>`). Transcription is cached per source
52
- and is a paid call — never force a re-transcribe of an unchanged source.
53
-
54
- ## Workflow
55
-
56
- 1. **Init** `video-editing init-job --source "<video>" --job-dir "/vercel/sandbox/jobs/<job_id>"`
57
- job dir + `source.json`. Always pass `--job-dir` explicitly (there is no `~/Downloads` on
58
- the sandbox); use the job dir given in the task prompt.
59
- 2. **Transcribe + screen** `video-editing transcribe --job-dir "<job>"` → word-level
60
- transcript + screening artifacts (`flags.txt`, `takes_packed.md`, `word_dump.txt`, `coverage.json`).
61
- 3. **GATE 1 SCREEN before cutting** — read `<job>/flags.txt`: resolve every **[A]**
62
- over-long/collapsed token (retakes hide here), judge every **[B]** repeated phrase
63
- (retake vs intentional), note **[C]** gaps/audio-events. Confirm `<job>/coverage.json`
64
- (last word within ~2s of duration). See `references/scribe-collapse.md`.
65
- 4. **Author the EDL** read `<job>/word_dump.txt` (and `prompts/author-edl.prompt.md` if present),
66
- then write `<job>/edl.json` per the brief below. To inspect any moment visually:
67
- `video-editing inspect --job-dir "<job>" --video vertical_src --start <a> --end <b>`.
68
- (Or let the CLI scaffold the prompt: `video-editing cut-bad-retakes --job-dir "<job>"`.)
69
- 5. **Render preview** `video-editing render --job-dir "<job>" --mode preview`.
70
- Render **auto-runs the amplitude silence-trim pass** (Gate 3) first: it scans the audio
71
- with `silencedetect` and excises every sub-floor silence the transcript can't see —
72
- pauses baked *inside* a stretched word token, room tone, breaths — then trims silent
73
- range edges. Your authored `edl.json` is backed up to `edl.raw.json` and rewritten with
74
- the tightened ranges (more ranges, shorter total). It is **transcript-aware**: it never
75
- splits inside a single word token (spelled acronyms like "WWX", held vowels, numbers).
76
- Tune or disable: `video-editing desilence --job-dir "<job>"` (flags below) /
77
- `render --no-desilence`.
78
- 6. **GATE 2 — CONTENT-VERIFY** — `video-editing verify --job-dir "<job>" --json`.
79
- It re-transcribes the preview at every join (healing OFF) and flags duplicated phrases
80
- across a join (= a retake left in) and over-long gaps (= dead air). Adjudicate with
81
- `video-editing inspect --job-dir "<job>" --join <i>`. See `references/adversarial-review.md`.
82
- 7. **Fix re-render re-verify** until `verify` is clean (`references/fix` rules apply).
83
- 8. **Final** `video-editing render --job-dir "<job>" --mode final`.
84
-
85
- ## The standing editing brief (apply exactly)
86
-
87
- - Output **VERTICAL 9:16**, **CLEAN CUTS ONLY** (`grade:"none"`, no subtitles, no overlays).
88
- - **CUT** bad retakes / false starts / cut-off / stuttered words — keep the **LAST complete take**,
89
- BUT keep the **CLEANEST** take when an earlier take is clean and a later one stutters.
90
- - **TIGHTEN every pause** to ~0.12–0.14s of air (remove dead air). The render's amplitude
91
- pass (Gate 3) enforces this automatically it cuts **every silence below the dB floor**
92
- (default −36 dB, pauses ≥0.14s, leaving ~0.09s air). This catches the silences the
93
- transcript misses (dead air baked inside a long word token, room tone, breaths). It runs
94
- on every render; you don't hand-tighten silences in the EDL.
95
- - **CUT ALL SILENCES below the dB floor** — for a more/less aggressive cut, tune the pass:
96
- `video-editing desilence --job-dir "<job>" --noise-db -39 --min-silence 0.30` (gentler) or
97
- `--noise-db -34 --min-silence 0.12 --lead-pad 0.03 --trail-pad 0.04` (harder). Re-render +
98
- re-verify after. To start clean, restore `cp edl.raw.json edl.json` then re-run.
99
- - **COLD-OPEN** on the strongest hook (trim weak/dead intro).
100
- - **TRIM outro dead air** (trailing breaths/ambient/silence/device noise).
101
- - **KEEP intentional rhetorical repeats.**
102
- - Never cut inside a word snap every edge to a transcript word boundary; pad cut edges
103
- 30–200ms (lead ~0.05s, trail ~0.08s; ~0.03–0.05s at retake joins, staying inside the silence).
104
- The renderer adds 30ms audio fades, so tight pads are safe.
105
- - Hebrew/RTL: read the transcript word-by-word with explicit timestamps to avoid reorder confusion.
106
-
107
- ## The gates
108
-
109
- 1. **SCREEN before cutting** — Scribe hides retakes in over-long/dropped tokens; always read `flags.txt` first.
110
- 2. **DESILENCE on render** (automatic) the amplitude pass cuts every sub-dB-floor silence the
111
- transcript can't see and trims silent edges. Transcript-aware (won't split spelled acronyms).
112
- 3. **CONTENT-VERIFY after preview**`video-editing verify` re-transcribes joins; a waveform/visual check
113
- alone does NOT catch a retake left in (abandoned take + keeper render as one continuous clean span).
114
- A **≥3-word** duplicate across a join = a real retake left in → **error**, fix it. A bare **2-word**
115
- repeat = **warning**: adjudicate with `inspect` it is usually a spelled acronym / number / emphasis
116
- (e.g. "WW" → "דבל יו דבל יו"), not a retake, and is safe to keep.
117
-
118
- ## EDL format
119
-
120
- ```json
121
- {
122
- "version": 1,
123
- "sources": {"SRC": "<job>/vertical_src.mp4"},
124
- "grade": "none",
125
- "ranges": [
126
- {"source": "SRC", "start": 11.35, "end": 14.12, "beat": "HOOK", "quote": "…", "reason": "cleanest take; stops before the slip at 38.46"}
127
- ],
128
- "overlays": [],
129
- "total_duration_s": 51.33
130
- }
131
- ```
132
-
133
- Ranges are KEEP segments in source seconds; the gaps between them are the cuts. A retake range
134
- must END at the **last clean word before the abandoned attempt**. `total_duration_s` = Σ(end−start).
135
-
136
- ## Timeline v2 (preferred when present)
137
-
138
- When the CLI exposes a `timeline compile` verb (run `video-editing timeline --help`),
139
- **author `<job>/timeline.json` instead of hand-writing `edl.json`.** timeline.json is the
140
- single authored artifact: cuts (keep-ranges) plus optional **captions, zooms, overlays, and
141
- audio blocks**. The compiler is compiler-grade — it validates, resolves phrase anchors to exact
142
- source seconds, and emits `resolved/plan.json`, `resolved/diagnostics.json`, and a legacy
143
- `edl.json`.
144
-
145
- **Prerequisite bake the vertical master first.** `timeline compile` probes
146
- `<job>/vertical_src.mp4`, and `transcribe` alone does NOT create it: after transcribing, run
147
- `video-editing cut-bad-retakes --job-dir "<job>" --render none` once (it bakes the vertical
148
- master AND writes the screening artifacts the SCREEN gate needs anyway). Skipping this makes
149
- `timeline compile` fail with a raw ffprobe "No such file or directory" — that error means run
150
- the bake, not that your timeline is wrong.
151
-
152
- Loop until clean:
153
-
154
- 1. Author/patch `<job>/timeline.json`.
155
- 2. `video-editing timeline compile --job-dir "<job>" --json` — read the diagnostics and iterate
156
- until it exits **0**:
157
- - **exit 2 = validation failed** (schema / semantic / capability) — fix the reported `path`s.
158
- - **exit 3 = ambiguous anchor** disambiguate with
159
- `video-editing timeline resolve --phrase "…" --near <t>` (or `--occurrence <n>`), then bake the
160
- resolved seconds / occurrence into the anchor and re-compile.
161
- 3. **Never hand-edit anything under `resolved/`** — it is generated; re-compile instead.
162
- 4. compile emits the legacy `edl.json`, so the **render → desilence → verify → final** steps are
163
- **unchanged** run them exactly as in the workflow above.
164
-
165
- **Phrase seconds ONLY via `timeline resolve`.** Never eyeball `word_dump.txt` for anchor
166
- times `resolve` returns word-accurate `start`/`end` and flags ambiguity so you disambiguate
167
- deliberately (`--near <srcSeconds>` or `--occurrence <n>`).
168
-
169
- Captions: enable with `video-editing timeline captions generate --job-dir "<job>" [--preset grouped]`
170
- — cues are **derived at compile**, you don't hand-write cue timings. The default preset `grouped`
171
- puts up to 4 words in each cue, starting a new cue on long word gaps (>0.6s), cut joins (a cue
172
- never spans a join), and sentence-ending `.` `?` `!` (same characters in Hebrew); `opus-karaoke`
173
- is the word-by-word opt-in. Timing/grouping knobs live in `captions.style` in timeline.json:
174
- `maxWords` (default 4), `leadS` (default 0.08 — each cue appears that many seconds early, clamped
175
- to the previous cue / segment start), `holdS` (default 0.9 — each cue holds on screen up to that
176
- long past its last word to bridge the gap to the next cue, killing blink). **Word styling**: an
177
- `op:"style"` caption override colors and/or emphasizes the anchored words — e.g. "make word X red"
178
- is `{"op":"style","anchor":{"type":"words","source":"SRC","phrase":"X"},"color":"#ff5c5c"}`;
179
- `emphasis:"pop"|"highlight"` animates the word at its onset. `captions.style.karaoke: true`
180
- adds a per-word highlight sweep inside grouped cues (staged). Validate anytime with
181
- `video-editing timeline validate --job-dir "<job>" --json`.
182
-
183
- ### Authoring zooms
184
-
185
- A zoom is a punch-in on `rect` (unit-canvas crop, `x+w<=1`, `y+h<=1`) at `scale`
186
- (`1 < scale <= 3`), anchored to a phrase or source span. Static by default (hard in/out).
187
- For a **ramp**, add `to: {scale?, rect?}` — the zoom animates from the base rect/scale to
188
- `to` over the zoom window, shaped by `ease: {in, out}` (both > 0 → smooth in-out). Zooms
189
- resolve onCut like everything else (`clip` default). Full examples:
190
- `references/timeline-v2-vocabulary.md`.
191
-
192
- ### Authoring overlays & assets
193
-
194
- - Text: `kind:"text"` (positioned) / `kind:"title-card"` (full-frame card) + `text`.
195
- - **Image/sticker**: `kind:"sticker"` (or `"image"`) + `asset: {ref: "assets/logo.png"}` —
196
- `ref` is a **job-dir-relative path**; keep files under `<job>/assets/`. Position with
197
- `layout.x/y` (center), size with `size.w/h` (canvas fractions; sticker default ~0.25 of
198
- width), stack with `z` (0–50). Animate with `enter`/`exit`
199
- (`{preset: fade|pop|slide-up|slide-down|scale-in, durationS ≤ 2}`).
200
- - A referenced file that does not exist fails `timeline compile` with `asset-missing` —
201
- put the file in place first.
202
- - On `review push --timeline` / `--complete`, referenced assets are **uploaded to
203
- clipready automatically** (sha256-cached in `<job>/review/assets.json`, so unchanged
204
- files are never re-uploaded); the push payload carries the `{ref: asset_id}` manifest.
205
- - `compose` copies referenced assets into `<job>/composition/media/` and renders them.
206
-
207
- ### Delivering captions/zooms
208
-
209
- The ffmpeg `render --mode final` path is **CUT-ONLY** — it never draws the compiled
210
- captions/zooms/overlays from `resolved/plan.json`. Deliver those visual layers with either:
211
-
212
- - **`video-editing compose --job-dir "<job>" --render`** — local and free. Builds a declarative
213
- HyperFrames composition in `<job>/composition/` (compressed proxy of `vertical_src.mp4`,
214
- the CONTINUOUS cut audio extracted from `preview.mp4`, and `index.html`) and renders it with
215
- the `hyperframes` CLI (needs it on PATH: `npm install -g hyperframes`). Prerequisites:
216
- `resolved/plan.json` (run `timeline compile`) and `preview.mp4` (run `render --mode preview`).
217
- Without `--render` it only builds the composition and prints the exact `hyperframes render`
218
- command to run. Output defaults to `<job>/composed.mp4`.
219
- - **The ClipReady cloud render** (`cloud render`), which renders the same plan server-side
220
- (requires a ClipReady account + API key — see the review-round section below).
221
-
222
- Do **NOT** fall back to the legacy `render --build-subtitles` ASS burn for timeline-v2 jobs —
223
- it requires a libass ffmpeg and renders the old 2-word subtitle style, not the compiled cues.
224
-
225
- ### Working a ClipReady review round
226
-
227
- > Cloud features require a ClipReady account + API key (`CLIPREADY_API_BASE`, `CLIPREADY_API_KEY`).
228
-
229
- When the job is a clipready review round (you have an API base + credential + video id), the
230
- CLI syncs the round for you — no hand-rolled curl:
231
-
232
- 1. `video-editing review pull --job-dir "<job>"` — writes `<job>/review/round.json` (run id,
233
- requested changes) and `<job>/review/instruction.md`, and hydrates `<job>/timeline.json`
234
- from the server when you don't already have one (it never overwrites a local timeline).
235
- Add `--source` if the source video isn't local yet.
236
- 2. `video-editing review push --stage edl --job-dir "<job>"` when you start working the round.
237
- 3. Edit `timeline.json` per the instruction, then
238
- `video-editing review push --timeline --job-dir "<job>"` after each meaningful change — it
239
- compiles locally (diagnostics + exit 2 if not clean) and the review page updates live.
240
- 4. Preview/verify locally exactly as in the workflow above (render preview, CONTENT-VERIFY, QC).
241
- 5. `video-editing review push --complete --duration <s> --outcomes outcomes.json --job-dir "<job>"`
242
- — compiles fresh (must be clean) and delivers the terminal payload (edl + timeline + plan).
243
- `outcomes.json` is `[{"change_id": "chg_…", "ok": true, "note": "…"}]`, one entry per
244
- `[chg_…]` marker in the instruction; omit `--outcomes` when there are no markers.
54
+ - **NEVER** run ffmpeg/ffprobe/transcription by hand — there is simply no
55
+ local media in this workflow at all; every frame lives in the cloud. If you
56
+ have a memory of local renders, `compose`, `--master`, or "extract the WAV
57
+ first", that memory is from a retired pipeline — discard it.
58
+ - If a capability seems missing, STOP and report it as a CLI gap. Do not
59
+ reach around the CLI.
60
+ - Your only hand-authored artifact is `<job>/timeline.json`.
61
+ - **Captions are timeline-authored and rendered by the cloud renderer
62
+ NEVER ffmpeg subtitle filters, libass, `.srt` sidecars, or `drawtext`.**
63
+
64
+ ## The workflow
65
+
66
+ 1. **Init** — `video-editing init --source "<path>"` (add `--job-dir "<dir>"`
67
+ to choose the working dir). ONE command does everything through
68
+ transcription: it streams the source up (chunked, retried, 2GB-safe),
69
+ creates the cloud job, runs server-side ingest (probe + transcription +
70
+ editorial screening), and pulls the results into the job dir:
71
+ `transcripts/`, `word_dump.txt`, `takes_packed.md`, `flags.txt`,
72
+ `coverage.json`, `probe.json` — **and `prompts/author-edl.prompt.md`**,
73
+ your editorial brief. Writes `<job>/job.json` (the `video_id` every later
74
+ verb uses) and prints the video's web link. There is no separate
75
+ transcribe step `transcribe` exists only to re-pull/re-run later.
76
+ Filenames with apostrophes, spaces, or unicode are safe the internal
77
+ stem is sanitized automatically; never rename the user's file.
78
+ 2. **READ the pulled `prompts/*.md` and follow them** they are your
79
+ editorial brief (what to cut, what to keep, the screening gate, the pad
80
+ and boundary rules). They are authoritative and may change between runs;
81
+ never edit them, never substitute a remembered brief.
82
+ 3. **Author `<job>/timeline.json`** per the pulled brief plus
83
+ `references/timeline-v2-vocabulary.md` (cut ranges, captions, zooms,
84
+ overlays, audio). The **sources KEY must equal the transcript stem** (the
85
+ filename of `transcripts/<stem>.json`) captions and resolve bind
86
+ through it. Resolve phrase seconds ONLY with
87
+ `video-editing timeline resolve --phrase "…" [--occurrence <n>]`
88
+ — never eyeball `word_dump.txt`. Sanity-check locally anytime with
89
+ `video-editing timeline validate --job-dir "<job>" --json`.
90
+ 4. **Compile** `video-editing timeline compile --job-dir "<job>" --json`.
91
+ Compiles in the cloud; writes `resolved/plan.json` +
92
+ `resolved/diagnostics.json` and prints the `View & comment` watch link —
93
+ the user can already watch/comment on the compiled cut. Read the
94
+ diagnostics and fix until it exits `0` (`2` = validation failed — fix the
95
+ reported paths; `3` = ambiguous anchor — disambiguate with
96
+ `timeline resolve`). Never hand-edit `resolved/`.
97
+ 5. **Render the preview** — `video-editing render --job-dir "<job>"`
98
+ (cloud render, preview mode, waits and downloads `<job>/preview.mp4` by
99
+ default; it works right after `timeline compile`). Share the printed
100
+ watch link with the user.
101
+ 6. **Verify** `video-editing verify --job-dir "<job>" --json`. Fully
102
+ server-side verification of the rendered preview (catches retakes left in
103
+ across a join and dead air a visual check misses); nothing is uploaded.
104
+ Can run while the user reviews. Fix `timeline.json`, re-compile,
105
+ re-render, re-verify until clean; cap at ~3 fix passes and surface
106
+ remaining findings rather than looping.
107
+ 7. **QA looks** spot-check any window with server-rendered visuals.
108
+ THE close-look tool is
109
+ `video-editing qa inspect --start <a> --end <b> --job-dir "<job>"`:
110
+ one composite PNG with the filmstrip, the waveform, word labels, AND
111
+ the compiled plan's cut regions shaded red ("cut") everything needed
112
+ to adjudicate a moment in a single image. Same addressing as frames:
113
+ `qa inspect --join <i>` (the two sides of plan join i → `-a`/`-b`
114
+ PNGs) and `qa inspect --out-start <a> --out-end <b>` (OUTPUT seconds
115
+ mapped through the compiled plan). The narrower views still exist:
116
+ `video-editing qa frames …` (filmstrip only, same addressing modes)
117
+ and `video-editing qa waveform --start <a> --end <b>` (waveform PNG +
118
+ word-timing sidecar JSON). Read the PNGs to adjudicate.
119
+ 8. **Final** — `video-editing render --mode final --job-dir "<job>"`.
120
+
121
+ ## Your editorial brief arrives from the cloud
122
+
123
+ The deep editorial briefretake/keep rules, pause tightening, cold-open,
124
+ screening and verification procedure is **not in this skill**. It is pulled
125
+ from the server into `<job>/prompts/*.md` by `init` (and refreshed by
126
+ `files pull`). Old references in this skill (`editing-brief.md`,
127
+ `hard-rules.md`, `adversarial-review.md`, `scribe-collapse.md`) are stubs
128
+ pointing there. If `prompts/author-edl.prompt.md` is missing, run
129
+ `video-editing files pull --job-dir "<job>"` — do not improvise a brief.
130
+
131
+ ## Known caveats
132
+
133
+ - **`verify` over-triggers on thematically narrow monologues.** The
134
+ duplicated-phrase join check flags legitimately repeated wording as
135
+ "retake left in". If EVERY join comes back flagged — including plain
136
+ pause-tightening joins that obviously aren't retakes — adjudicate each
137
+ finding against `flags.txt` (the screening output) instead of blindly
138
+ recutting; only recut joins that flags.txt corroborates as real retakes.
139
+ - **Caption mistranscriptions** are fixed with a captions override in
140
+ `timeline.json` (anchored on the MIS-transcribed text — see
141
+ `references/timeline-v2-vocabulary.md`), then recompile + re-render.
142
+ Never with subtitle files or filters.
143
+
144
+ ## File sync
145
+
146
+ `video-editing files pull --job-dir "<job>" [--only <name,name>]` fetches the
147
+ cloud job's artifacts into the job dir preserving relative paths (transcripts,
148
+ `prompts/*.md`, `resolved/plan.json`, `timeline.json`, …);
149
+ `video-editing files push --job-dir "<job>" <paths…>` uploads local artifacts
150
+ (e.g. a hand-authored `timeline.json`, referenced assets) back to the job. Use
151
+ `pull` to recover state on a fresh machine the cloud job is the source of
152
+ truth.
153
+
154
+ ## Working a ClipReady review round
155
+
156
+ When the job is a clipready review round (the video has an active round):
157
+
158
+ 1. `video-editing review pull --job-dir "<job>"` writes
159
+ `<job>/review/round.json` (round/run ids, requested changes) and
160
+ `<job>/review/instruction.md`; hydrates `<job>/timeline.json` from the
161
+ server only when you don't already have one (never overwrites yours).
162
+ 2. Edit `timeline.json` per the instruction, then
163
+ `video-editing review push --timeline --job-dir "<job>"` after each
164
+ meaningful change — it compiles in the cloud (diagnostics; exit `2` if
165
+ not clean) and the review page updates live. Referenced assets (stickers,
166
+ audio beds) upload automatically, sha256-cached.
167
+ 3. Render + verify exactly as in the workflow above.
168
+ 4. `video-editing review push --complete --duration <s> --outcomes outcomes.json --job-dir "<job>"`
169
+ compiles fresh (must be clean) and delivers the terminal payload.
170
+ `outcomes.json` is `[{"change_id": "chg_…", "ok": true, "note": "…"}]`,
171
+ one entry per `[chg_…]` marker in the instruction; omit `--outcomes` when
172
+ there are no markers.
173
+
174
+ ## Hebrew / RTL
175
+
176
+ Hebrew/RTL sources are fully supported. Read the transcript word-by-word with
177
+ explicit timestamps to avoid visual-reorder confusion; anchor phrases via
178
+ `timeline resolve` exactly as with LTR text. Sentence-ending punctuation for
179
+ caption grouping is the same characters in Hebrew.
245
180
 
246
181
  ## References
247
182
 
248
- - `references/cli-reference.md` — every subcommand + flag (incl. `verify`, `inspect`).
249
- - `references/timeline-v2-vocabulary.md` — the full timeline.json v2 vocabulary, one JSON
250
- example per feature (word styling, karaoke, zoom ramps, stickers, enter/exit, grade).
251
- - `references/editing-brief.md` the full EDL-authoring procedure.
252
- - `references/hard-rules.md` — production-correctness rules + anti-patterns.
253
- - `references/scribe-collapse.md` — why retakes hide in the transcript (Gate 1).
254
- - `references/adversarial-review.md` the content-verify pass (Gate 2).
183
+ - `references/cli-reference.md` — every v3 subcommand + flag.
184
+ - `references/timeline-v2-vocabulary.md` — the full `timeline.json` v2
185
+ vocabulary, one JSON example per feature (captions + word styling, karaoke,
186
+ zoom ramps, stickers, enter/exit, audio beds, grade).
187
+ - `references/editing-brief.md`, `references/hard-rules.md`,
188
+ `references/scribe-collapse.md`, `references/adversarial-review.md`
189
+ stubs; the live content is server-pulled into `<job>/prompts/*.md`.
@@ -1,44 +1,4 @@
1
- # Gate 2 content-verify after preview
1
+ # Content-verify gate (moved server-side)
2
2
 
3
- A single editing pass leaves retakes in. The reliable failure mode: the abandoned
4
- first attempt and the keeper render as **one continuous clean-audio span**, so a
5
- waveform / visual self-eval looks perfect while the *content* is duplicated across
6
- the join. The fix is to **re-transcribe the rendered preview at each join** — which
7
- is exactly what `video-editing verify` does. Run it for every real cut.
8
-
9
- ## Run it
10
-
11
- ```
12
- video-editing verify --job-dir "<job>" --json
13
- ```
14
-
15
- - Default (per-join): re-transcribes a ~6s window centered on each cut boundary
16
- (from `cut_boundaries.json`), **healing OFF**.
17
- - `--full`: re-transcribes the whole preview and also checks head/tail dead air.
18
-
19
- It reports, per join:
20
- - **duplicated phrase across the join** → a retake left in (severity `error`). It only
21
- flags **near-adjacent** duplication (the retake fingerprint), not legitimate topical
22
- repeats spaced apart.
23
- - **over-long gap straddling the join** → dead air not tightened (warning, or error if large).
24
-
25
- Writes `verify.json` (same shape family as `review.json`); exit code 2 on `needs-fixes`.
26
-
27
- ## Adjudicate + fix
28
-
29
- For any finding, eyeball it: `video-editing inspect --job-dir "<job>" --join <i>` and read
30
- the PNG (clipped word, leftover false-start syllable, audio pop, broken frame?).
31
-
32
- Then FIX the EDL and re-render + re-verify:
33
- - **Retake still present** → set that range's END at the **last clean word BEFORE the
34
- abandoned attempt**.
35
- - **Intentional repeat wrongly cut** → restore it.
36
- - **Clipped boundary** → re-snap to the transcript word boundary.
37
- - **Leading / trailing dead air** → trim it.
38
-
39
- Re-snap every edge to a word boundary; keep pads tight (30–200ms); keep `grade:"none"`,
40
- `overlays:[]`; update `total_duration_s`. Re-render `--mode preview`, re-run `verify`.
41
- Cap at ~3 fix passes; if findings persist, surface them rather than looping forever.
42
-
43
- A real retake left in / an intentional repeat wrongly cut / a clipped word at a join /
44
- leading-or-trailing dead air ⇒ not clean. Minor taste calls are not defects.
3
+ The verification procedure (Gate 2) now arrives from the ClipReady cloud inside `<job>/prompts/*.md`
4
+ (pulled by `video-editing transcribe` / `files pull`); run it via `video-editing verify`. This file is a stub.