@aicopycoders/exodus 2026.9.2000-beta.2 → 2026.9.2000-beta.20

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.
@@ -152,7 +152,8 @@ run options:
152
152
  --mode auto|manual|hybrid Generation mode (default: auto)
153
153
  --render-mode images|prompts prompts = skip render, return LLM prompts only (default: images)
154
154
  --aspect 1:1|9:16 Image aspect ratio (default: 1:1)
155
- --model gpt-image-2|nano-banana-pro Kie.ai model (default: gpt-image-2)
155
+ --model gpt-image-2.5|gpt-image-2.5-sunburst|gpt-image-2|nano-banana-pro
156
+ Kie.ai model (default: gpt-image-2.5)
156
157
  --realism off|realistic Realism enforcement (default: off)
157
158
  --quantities "slug:N,slug:N" manual-mode per-type counts (e.g. "testimonial:3,hero:2")
158
159
  --pairings '<JSON>' hybrid-mode host/modifier pairs: '[{"host":"testimonial","modifier":"hero"}]'
@@ -244,6 +244,7 @@ internals into chat.
244
244
  - The rig's child image runs are still `creativeSuiteRuns` with engine `meme`,
245
245
  so finished memes appear in the creative-suite library alongside other engines
246
246
  and `exodus browse --agent meme` still covers them.
247
- - `run` accepts only the two models the rig renders (`gpt-image-2`,
248
- `nano-banana-pro`, or their Kie slugs); anything else is a 400 listing the
249
- accepted values. It used to accept any value and silently ignore it.
247
+ - `run` accepts only the models the rig renders (`gpt-image-2.5`, the house
248
+ default, plus `gpt-image-2.5-sunburst`, `gpt-image-2` and `nano-banana-pro`,
249
+ or their Kie slugs); anything else is a 400 listing the accepted values. It
250
+ used to accept any value and silently ignore it.
@@ -17,7 +17,8 @@ run options:
17
17
  --mode auto|manual|hybrid Generation mode (default: auto)
18
18
  --render-mode images|prompts prompts = skip render, return LLM prompts only (default: images)
19
19
  --aspect 1:1|9:16 Image aspect ratio (default: 1:1)
20
- --model gpt-image-2|nano-banana-pro Kie.ai model (default: gpt-image-2)
20
+ --model gpt-image-2.5|gpt-image-2.5-sunburst|gpt-image-2|nano-banana-pro
21
+ Kie.ai model (default: gpt-image-2.5)
21
22
  --realism off|realistic Realism enforcement (default: off)
22
23
  --quantities "slug:N,slug:N" manual-mode per-type counts (e.g. "testimonial:3,hero:2")
23
24
  --pairings '<JSON>' hybrid-mode host/modifier pairs: '[{"host":"testimonial","modifier":"hero"}]'
@@ -21,12 +21,27 @@ Your job in this skill is to drive that loop, hand over the pieces with the
21
21
  facts about them, and make whatever cut the user asked for. **How to edit is the
22
22
  user's call, not this skill's** — see "Cutting the ad".
23
23
 
24
+ This file ships on the member's machine. It holds commands, the manifest's
25
+ shape, and recipes for the cut. It does not hold prompt text, house primers,
26
+ judge wording, or model instructions.
27
+
24
28
  ## How a run starts
25
29
 
26
30
  The ad is a saved workflow in the brand, started script-first with `exodus
27
31
  workflow run`. From there the same nodes render, `video status` reads the run,
28
32
  `video pull` writes the folder, and `video upload` and `approve` finish it.
29
33
 
34
+ A Show is no longer required. `exodus video start` starts from a script, a
35
+ conceit, and a style, and the same parks follow. The full line is under
36
+ "Starting a run". An optional `--direction` note is whole-ad rules, and that
37
+ note cannot contain a colon. "The script file" shows the right form and the
38
+ wrong one.
39
+
40
+ The Rig box on that workflow is where the run's Conceit and Style come from.
41
+ Conceit is the family plus Wrapper, Narrator Person, and Delivery. Style is the
42
+ look. Narrated Story is the voice-over family and Acted Story is the dialogue
43
+ family (`familyTree.ts`). Those family names stay the code's names.
44
+
30
45
  ## Before anything
31
46
 
32
47
  - `npx @aicopycoders/exodus video --help` and `workflow --help` are the
@@ -69,6 +84,11 @@ exodus workflow run <workflowId|name> --input <field>=@script.txt --voices @voic
69
84
  exodus workflow run <workflowId|name> --input <field>=@script.txt --voice-treatment @voice-treatment.json --wait
70
85
  same, with the video model speaking voices you WROTE
71
86
  exodus video status <runId> where it is, per scene
87
+ exodus video start --script <file> --conceit <podcast|ugc|stage|street|personification> --style <slug> [--direction "…"] [--voice-path <path>] [--video-model <id>] [--voice native] [--music] [--wait]
88
+ start from a script, a conceit and a look.
89
+ No music bed unless you pass --music.
90
+ Each conceit has its own video model and voice;
91
+ --video-model / --voice override them for one run
72
92
  ```
73
93
 
74
94
  **From the storyboard on.**
@@ -81,7 +101,7 @@ exodus video approve <runId> keep going
81
101
  exodus video retry-frame <runId> --node <nodeId> --scene <n> redo one still at the pixel gate
82
102
  exodus video status <runId> where it is, per scene
83
103
  exodus video pull <runId> --out ./ad-<runId> every piece + manifest.json
84
- exodus video retry-clip <runId> --scene <n> [--node <nodeId>] [--note "…"]
104
+ exodus video retry-clip <runId> --scene <n> [--node <nodeId>] [--note "…"] [--voice-first]
85
105
  redo one clip at the final watch
86
106
  exodus video revoice <runId> --all | --scene <n> redo only the voice; no new video
87
107
  … make the cut (your choice of tool)
@@ -98,7 +118,15 @@ already printed the same stop block, and `workflow inbox` lists a parked video
98
118
  run, but neither shows the per-scene detail, and the checkpoint verbs cannot
99
119
  resolve a video park — see "What the CLI can and cannot do".
100
120
 
101
- **Where a run can stop.** Five stops, each with the exact next command printed
121
+ **Where a run can stop.** The two video parks come in order when the run has
122
+ both. The storyboard gate is first. You read the cards there and you set the
123
+ voices there. Approving that gate releases the voices and the clips. That is the
124
+ expensive part. The final watch is next, after the pieces exist, and only when
125
+ the video node sets `finalWatch: true`. That park is for the cut. You pull, you
126
+ cut, and you upload. Approving the upload makes it the ad. A node with
127
+ `finalWatch` off skips the second park and the run finishes.
128
+
129
+ Five stops, each with the exact next command printed
102
130
  under it:
103
131
 
104
132
  - storyboard gate: needs `approve`. When the stop block prints a `Redo one
@@ -110,11 +138,20 @@ under it:
110
138
  lines under `guidance`). It is also
111
139
  the one park where a finished clip can be redone, with `retry-clip`. A run
112
140
  only reaches this park if its video node sets `finalWatch: true` — otherwise
113
- it skips straight to finished.
141
+ it skips straight to finished. If a scene has no clip, the stop block names
142
+ it instead (`stop.missingScenes` in `--json`) and approval is refused until
143
+ it has one. A scene whose picture the video service refused needs
144
+ `retry-frame --note` before `retry-clip`; the clip redo alone resends the
145
+ refused picture.
114
146
  - paused: a builder checkpoint neither video verb resolves —
115
147
  `exodus workflow checkpoint <runId>` is the verb for that one.
116
148
  - failed: `status` shows how far it got, and a `--wait` that was running exits
117
149
  1 with the error. Tell the user; do not start another run on your own.
150
+ When the storyboard is the step that failed, `status` adds a "What happened
151
+ to the storyboard" block: which parts of the plan were accepted, which part
152
+ was turned down, and why (#1902). Relay it as written. On an admin key it may
153
+ also offer `status <runId> --rejected-draft`. That prints the draft the system
154
+ threw away. It is a record only: never build on it, edit it, or re-run it.
118
155
  - finished: pull what it made.
119
156
 
120
157
  **`--wait` stops at both video parks** (#1818). `workflow run --wait` ends at
@@ -206,11 +243,42 @@ anything:
206
243
 
207
244
  ## The script file
208
245
 
209
- Plain text. A `CAST:` block naming the speakers, one line per turn, then a
210
- `CTA:` block. The planner sizes every line at
211
- 2.5 words per second (`WORD_LADDER_WPS`), so a turn near 14 words plans a clip
212
- near 6 seconds. If a line does get truncated in its clip, the manifest says so
213
- (`speech-cutoff`).
246
+ Plain text. An optional `DIRECTION:` block may open the file, before `CAST:` or
247
+ the first spoken line. Then a `CAST:` block naming the speakers, one line per
248
+ turn, then a `CTA:` block.
249
+
250
+ `DIRECTION:` carries whole-ad rules and no spoken words. The header is its own
251
+ line. The lines under it are the rules. The block ends at a blank line, at
252
+ `CAST:`, at `CTA:`, or at the first line that names a speaker. A second
253
+ `DIRECTION:` block is refused. So is a `DIRECTION:` after the first spoken line.
254
+ An empty block is refused too. The error code is `malformed-direction`.
255
+
256
+ Do not put a colon inside direction prose. The reader splits a line at its first
257
+ colon to find a speaker, so a colon in that prose is read as a name.
258
+
259
+ Right.
260
+
261
+ ```
262
+ DIRECTION:
263
+ Nobody looks at the camera. The product stays on the table until the last line.
264
+ ```
265
+
266
+ Wrong.
267
+
268
+ ```
269
+ DIRECTION:
270
+ Rule: nobody looks at the camera.
271
+ ```
272
+
273
+ The wrong line is not direction. `Rule` is read as the speaker, and the
274
+ block above it is empty, so the file is refused.
275
+
276
+ The planner sizes every line at 2.5 words per second (`WORD_LADDER_WPS`), so a
277
+ turn near 14 words plans a clip near 6 seconds. If a line does get truncated in
278
+ its clip, the manifest says so (`speech-cutoff`). That finding means the clip
279
+ cut the words off. Redo the clip. Do not speed the speech or cut it short to
280
+ hide the finding. The product rule is under "What the product actually
281
+ requires".
214
282
 
215
283
  ```
216
284
  CAST:
@@ -224,6 +292,15 @@ CTA:
224
292
  THE SOFTGEL: Tap below and give your eyes ClearBlink.
225
293
  ```
226
294
 
295
+ The dash in a `CAST:` line is the parser's own separator. The example above
296
+ already shows that dash. A cast line may separate the name from the description
297
+ with an em dash, an en dash, or a hyphen with a space on each side. Keep that
298
+ dash on cast lines. A reader who strips it makes the line fail.
299
+
300
+ Do not use a long dash in words a character says, or in words shown on screen.
301
+ Synthesised speech reads a long dash oddly, and so does burned-in text. A spoken
302
+ line stays `NAME: what they say`.
303
+
227
304
  **How many speakers you may have depends on the rig.** Three by default. A rig
228
305
  that carries saved format rules sets its own number: an ensemble rig seats more,
229
306
  a talking-head rig seats one. Over the number, the launch refuses before
@@ -256,9 +333,13 @@ unattended.
256
333
  By default a workflow run's characters have no voice of their own. A character
257
334
  without one gets the run's default voice (the workflow's narrator voice) when the
258
335
  run has one; with no default either, the clip keeps the voice the video model
259
- invents. `exodus video voices` shows which of the three applies and is where it
260
- gets fixed, and it only works **before** the storyboard is approved — once clips start
261
- it refuses.
336
+ invents. `exodus video voices` shows which of the three applies, and it is where you
337
+ fix the mapping. Fix it before you approve the storyboard gate. Approving that
338
+ gate locks the mapping, and `exodus video voices` refuses afterwards. On a
339
+ finished clip whose voice was never applied, the later command is `exodus video
340
+ revoice`, and that pass bills again. A clip that already went through the voice
341
+ pass is refused there. Use `retry-clip` for that one. See "Redoing only the
342
+ voice on finished clips".
262
343
 
263
344
  ```
264
345
  exodus video voices <runId>
@@ -332,7 +413,7 @@ nobody knows the speaker names yet. When the storyboard arrives, the voices are
332
413
  already set and `exodus video voices <runId>` shows them.
333
414
 
334
415
  **Choosing how the voices are made.** `--voice-treatment` on `workflow run` says
335
- HOW a run makes its voices, and it is the only door. Two
416
+ HOW a run makes its voices, and it is the only way. Two
336
417
  kinds of answer.
337
418
 
338
419
  A name on its own picks a way of working that plays a voice you already have,
@@ -405,7 +486,8 @@ person made at a keyboard for one run, and nobody made it for the sub-workflow.
405
486
  **Written voices cannot be changed at the review.** They are chosen when the run
406
487
  starts. `exodus video voices <runId>` on a described run names the treatment and
407
488
  prints each written voice, and says plainly that `--voice-treatment` at launch is
408
- what changes them. Do not set a voice path in node config — it is not a door.
489
+ what changes them. Do not set a voice path in node config. Node config does
490
+ not set the treatment.
409
491
 
410
492
  **Where it shows up afterwards.** The launch receipt and `exodus workflow status`
411
493
  both print one line naming the treatment and the speakers who got a written
@@ -483,6 +565,15 @@ manifest.json the index below
483
565
  runId, pulledAt, dashboardUrl the run and the page that opens it:
484
566
  /workflows/<workflowId>/runs/<runId>
485
567
  storyboard, reference, music filenames, or null when not delivered
568
+ musicBed on | off | unknown — whether the RUN has a
569
+ music bed, which is not the same question
570
+ as the `music` filename above. "unknown" is
571
+ a run made before the run carried the
572
+ answer; it is not "off"
573
+ musicHeardScenes[] scene numbers whose clip came back with
574
+ music the video model baked in. A run with
575
+ the bed off can still list scenes here, and
576
+ those are the ones to listen to
486
577
  narration { file, timing }, or null on a per-scene run
487
578
  cast[] one per identity still
488
579
  characterId, name from the run's cast lock; null for an
@@ -515,6 +606,9 @@ scenes[] one per scene, in order
515
606
  on record when the voice pass replaced the
516
607
  clip with a new file; null when the clip IS
517
608
  that file, or there is no clip
609
+ voiceMode "voice-first" when the clip was redone voice
610
+ first (its line recorded, then the clip made
611
+ to match it); null otherwise
518
612
  provenance which saved rulebook this run followed:
519
613
  {format: {via, nodeId, rigId, rigName,
520
614
  rulesFrom, specVersion}}. Absent when the
@@ -537,15 +631,19 @@ depends on the scene; see "Which scenes carry their voice where" below.
537
631
  terms. `script[]` is the ad's spoken words in order — `{lineId, speakerId, text}`,
538
632
  with `speakerId: null` meaning narrator VO. Each scene carries `sceneIndex`,
539
633
  `durationSec`, `dialogue[]`, `voText`, `notes`, and `lineIds` (the script lines
540
- that scene renders). A scene with `kind: "cutaway"` carries `cueLineId` instead:
541
- it is a picture-only takeover of the frame while the spoken track underneath
542
- keeps running, so it adds no audio and takes no place in the running order. The
634
+ that scene renders). A scene with `kind: "cutaway"` carries `cueLineId` and a
635
+ `cutawayType` instead. Most cutaways are a picture-only takeover of the frame
636
+ while the spoken track underneath keeps running, so they add no audio and take
637
+ no place in the running order. A `cutawayType: "reaction"` cutaway is the room
638
+ reacting out loud to its cue line: it is its own short beat after that line,
639
+ heard with its own sound while the speaker is silent. The
543
640
  envelope also carries `overlays[]` (each with a `cueLineId` and a `placement`)
544
641
  and `audio` (`roomTone`, `music`, `sfxCues[]`) — the planner's notes on what
545
642
  should sit on top. The image and motion prompts (`framePrompt`, `videoPrompt`,
546
643
  `referencePrompt`) reach an admin key in full. A caller who cannot use video on
547
- this brand gets them stripped before the file arrives — they are style-pack IP
548
- (`redactVideoIp` in `convex/workflows.ts`).
644
+ this brand gets them stripped before the file arrives. They are private Style
645
+ fragment IP (`redactVideoIp` in `convex/workflows.ts`). Style pack is the
646
+ retired name.
549
647
 
550
648
  **The narration track** (`narration.mp3` + `narration.json`). Present when the
551
649
  run recorded continuously: every narrated scene's `voText` joined into one
@@ -572,9 +670,9 @@ speech inside the clip — under the default voice treatment the video model's
572
670
  invented voice is then replaced, in place, with the cast member's pinned
573
671
  ElevenLabs voice (that is `revoiced: true`). Other treatments leave the render
574
672
  owning its own audio, e.g. lip-sync retargeting a VO track onto the video. The
575
- treatment is frozen on the run when it starts, and there is exactly one door
673
+ treatment is frozen on the run when it starts, and there is exactly one flag
576
674
  that sets it: `--voice-treatment` on `workflow run` (see **Choosing how the
577
- voices are made**). Node config is never a door — nothing on the canvas sets a
675
+ voices are made**). Node config never sets it. Nothing on the canvas sets a
578
676
  voice treatment, and a run that was given none renders the default. Read
579
677
  `wordsFrom` and `revoiced` per scene rather than assuming.
580
678
 
@@ -636,6 +734,11 @@ blocking the run.
636
734
  A `speech-cutoff` on the CTA scene is the one to worry about; the ad's last
637
735
  words are missing. `status` shows the checker's own wording behind each
638
736
  finding; the manifest carries only the verdict.
737
+ - A `pass` verdict is not a review. The checks are often optimistic. Watch the
738
+ frames and listen to the audio before you call the run good. Two checks fail
739
+ the wrong way. A cast-count check can reject a silent
740
+ listener who belongs in the shot. A clip check can flag a clip that is fine.
741
+ Read the finding, then watch the scene.
639
742
  - `clipStatus: "failed"` or `"missing"` with a `keyframe`: `durationSec` is null
640
743
  (it comes from the clip), but the scene can still hold its place as a still —
641
744
  for the length of its voice track, or the storyboard's planned duration when
@@ -653,6 +756,7 @@ is no second run, no new storyboard and no re-render of anything else.
653
756
  exodus video retry-clip <runId> --scene 3
654
757
  exodus video retry-clip <runId> --scene 3 --note "keep both hands in frame on the handshake"
655
758
  exodus video retry-clip <runId> --scene 3 --node video-2
759
+ exodus video retry-clip <runId> --scene 3 --voice-first
656
760
  ```
657
761
 
658
762
  `--node` is only needed when a run has clips for that scene on two video steps;
@@ -675,7 +779,17 @@ revoiced and trimmed the same way, with fresh findings and fresh word timings.
675
779
  scene's motion prompt only (`withRedoDirection`,
676
780
  `scout/src/trigger/workflow-scene-retry.ts`); the spoken line still comes from
677
781
  the approved storyboard. Asking for different words in a note will not change
678
- them. If the words are wrong, that is a new run.
782
+ them. If the script's words are wrong, that is a new run.
783
+
784
+ **`--voice-first` fixes a clip that said its line wrong** (#2299). It is for a
785
+ clip whose findings include `speech-mismatch`, `speech-repeat`,
786
+ `speech-after-line`, `speech-extra-words` or `speech-long-pause`. The scene's line is recorded in each
787
+ speaker's pinned ElevenLabs voice, and MiniMax (`minimax-h3/reference-to-video`)
788
+ makes the clip to match the recording. Only that clip changes; the word check
789
+ and the other checks still run on it. It needs an ElevenLabs key and a voice for
790
+ every speaker in the scene, and it is refused for a scene with no spoken line.
791
+ The clip then reads `clip: redone voice first` in `status`, carries
792
+ `voiceMode: "voice-first"` in the manifest, and is listed in the `pull` summary.
679
793
 
680
794
  **A redo whose take fails the checks keeps the original clip.** On a finished
681
795
  clip the row stays `done` with the ORIGINAL take and only its findings are
@@ -762,7 +876,10 @@ they want; if they have not said and are not around, say which you used and why.
762
876
  - **HyperFrames** — HTML/CSS compositions rendered to video. Suits an ad that
763
877
  needs captions, title cards, overlays or motion graphics laid over the clips.
764
878
  It is a separate skill pack; check that a `hyperframes` skill is installed
765
- before offering it.
879
+ before offering it. The cut is made outside Exodus. `exodus video pull` is the
880
+ handover. The folder it writes is what the next tool reads. When a HyperFrames
881
+ skill pack is installed, that pack is the route for an HTML and CSS
882
+ composition. Do not look for a stitch inside Exodus.
766
883
  - **An NLE over MCP** — DaVinci Resolve publishes an MCP server, so a timeline
767
884
  can be built in a real editor and the user can carry on by hand afterwards.
768
885
  Suits a user who wants to keep editing after you stop. Check what MCP servers
@@ -784,6 +901,13 @@ Read these out of `storyboard.json` before you build anything, in any tool:
784
901
  running order. To find the moment, locate the A-roll scene whose `lineIds`
785
902
  contain the cue line, then read the start time of the first word of that line
786
903
  out of that scene's `words.json`.
904
+ - **Reactions.** A cutaway with `cutawayType: "reaction"` is the exception. Do
905
+ not lay it over the speech. Put it into the running order as its own beat
906
+ right after its cue line ends, play its own sound (the audience laughing),
907
+ keep it to about 1.5 s, then carry on with the speaker. Nobody talks during
908
+ it. When more lines follow the cue line in the same scene, cut that scene
909
+ where the cue line's last word ends in its `words.json` and put the reaction
910
+ between the two halves.
787
911
  - **Overlays and SFX.** `overlays[]` and `audio.sfxCues[]` are cued the same
788
912
  way, by `cueLineId`. Nothing renders them for you.
789
913
  - **Captions.** Nothing is burned into any clip. Captions belong in post; the
@@ -800,12 +924,20 @@ the pieces:
800
924
  holds its last frame for the difference. The narration is never sped up,
801
925
  slowed down or cut short, so every scene plays at the speed it was recorded,
802
926
  and the word times are handed on as they were measured.
927
+ - **It closes the dead air at the joins.** A clip that plays its own dialogue
928
+ keeps about 0.15 s after its last word and about 0.1 s before its first (0.25 s
929
+ when a different speaker answers), read from its `words.json`, so one clip
930
+ runs into the next like one conversation. It only ever shortens a clip's
931
+ silence and never cuts into a word. The ad's first lead-in and last tail, a
932
+ narrated scene, a still and a reaction beat are left as they are.
803
933
  - **It ignores the continuous master.** It reads only `scene-NN.voice` files;
804
934
  it never opens `narration.mp3` or `manifest.narration`. A tool that lays the
805
935
  master down whole and cuts the pictures to it keeps the read intact.
806
- - Otherwise: A-roll in manifest order as the spine, each cutaway laid over the
807
- spine at its cued word (falling back to a proportional estimate when the scene
808
- has no word times, and saying which method it used), a narrated scene's voice
936
+ - Otherwise: A-roll in manifest order as the spine, each reaction put in as its
937
+ own beat of at most 1.5 s right after its cue line with its own sound, each
938
+ other cutaway laid over the spine at its cued word (falling back to a
939
+ proportional estimate when the scene has no word times, and saying which
940
+ method it used), a narrated scene's voice
809
941
  replacing whatever the clip recorded, a dialogue scene keeping its performed
810
942
  line, a clip-less scene becoming a still, everything normalized to 1080×1920
811
943
  at 24 fps and −16 LUFS per segment, a generated room-tone bed under the whole
@@ -817,14 +949,15 @@ the pieces:
817
949
  ad with its start and end) and `cut.srt` (the same words grouped into subtitle
818
950
  lines), named from the `--out` basename. Those times are on the finished ad's
819
951
  timeline, each scene's own word times offset by where that scene starts in the
820
- cut and otherwise unaltered. Scenes with no word times leave
952
+ cut, less any lead-in trimmed at the join, and otherwise unaltered. Scenes with no word times leave
821
953
  gaps and are named in the report; when no scene delivered any, neither file is
822
954
  written. These sidecars are the script's own output — another tool will not
823
955
  produce them.
824
956
 
825
957
  Before uploading anything, from any tool, check what you made:
826
958
  `ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 cut.mp4`
827
- should be close to the sum of the scene durations you kept. A cut that is a few
959
+ should be close to the sum of the scene durations you kept (the bundled
960
+ script's cut runs somewhat shorter, by the silence it trimmed at the joins). A cut that is a few
828
961
  seconds long when five clips went in means a filter dropped inputs; do not
829
962
  upload it.
830
963
 
@@ -859,6 +992,11 @@ lines, re-recording narration, or cutting words out of the CTA will ship,
859
992
  silently. Cut the pictures to the words, not the words to the pictures. If the
860
993
  words are wrong, that is a new run, not an edit.
861
994
 
995
+ Never stretch speech, speed it up, slow it down, or cut it short so it fits a
996
+ clip. That is a product rule, and it holds for every tool that makes the cut,
997
+ including the bundled script. If the audio does not fit, redo the clip with
998
+ `exodus video retry-clip`. Do not repair the fit in the editor.
999
+
862
1000
  ## Reporting to the user
863
1001
 
864
1002
  Lead with where the run is and what it needs from them. Then, when you pulled