@plaintake/scenario 1.24.0 → 1.30.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.
@@ -4,6 +4,7 @@ export declare const CueSchema: z.ZodObject<{
4
4
  startMs: z.ZodNumber;
5
5
  endMs: z.ZodNumber;
6
6
  lines: z.ZodArray<z.ZodString>;
7
+ words: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
7
8
  }, z.core.$strip>;
8
9
  /**
9
10
  * The closing credit card. Absent means no card, which is a Pro-Tier-only outcome.
@@ -54,6 +55,41 @@ export declare const IntroSchema: z.ZodObject<{
54
55
  assPath: z.ZodLiteral<"captions/intro.ass">;
55
56
  }, z.core.$strip>;
56
57
  export type Intro = z.infer<typeof IntroSchema>;
58
+ /**
59
+ * The hook: one or two lines of author text drawn in the top band of a portrait video for its
60
+ * first seconds — the scroll-stopper a short-form feed shows before anyone has decided to watch.
61
+ *
62
+ * **Not the intro, and not narration.** The intro is a full-frame card that takes its own time
63
+ * at the head of the video; the hook sits *over* the recording, in the band above the picture,
64
+ * and costs no time at all. It is never spoken and never a caption cue, so it stays out of the
65
+ * SRT, the VTT, the `mov_text` track and `cueCount`, exactly as the cards do.
66
+ *
67
+ * `lines` are frozen already wrapped — by the author's own line break, or balanced to the
68
+ * hook's measured width (`wrapHook`, `@plaintake/subtitles`) — because nothing downstream
69
+ * re-wraps text. Frozen on every plan whose scenario declares one, whatever the aspect: only a
70
+ * portrait frame has a band to draw it in, so a 16:9 plan carries it undrawn and a later
71
+ * `render --aspect 9:16` re-cut picks it up, the same way a re-cut carries every other field.
72
+ */
73
+ export declare const HookSchema: z.ZodObject<{
74
+ lines: z.ZodArray<z.ZodString>;
75
+ durationMs: z.ZodNumber;
76
+ assPath: z.ZodLiteral<"captions/hook.ass">;
77
+ imagePath: z.ZodOptional<z.ZodLiteral<"captions/hook.png">>;
78
+ }, z.core.$strip>;
79
+ export type Hook = z.infer<typeof HookSchema>;
80
+ /** The hook as the application layer supplies it; `assPath` is filled in by `buildRenderPlan`. */
81
+ export type HookInput = Omit<Hook, 'assPath'>;
82
+ /**
83
+ * Rounded corners on the box a letterbox lays the picture in, drawn by libass in the pad colour
84
+ * over the box's four corners. Present only on the two layouts that frame the picture as an
85
+ * object on a background — `social` and `inset` — and absent on every plain letterbox, whose
86
+ * picture runs edge to edge across the frame and has no corner a radius could round.
87
+ */
88
+ export declare const FrameSchema: z.ZodObject<{
89
+ radius: z.ZodNumber;
90
+ assPath: z.ZodLiteral<"captions/frame.ass">;
91
+ }, z.core.$strip>;
92
+ export type Frame = z.infer<typeof FrameSchema>;
57
93
  /**
58
94
  * One MP4 chapter marker. `endMs` is stored rather than derived from the next mark, so
59
95
  * `render/chapters.ffmetadata` is a pure function of the plan and nothing is recomputed at
@@ -99,8 +135,9 @@ export type ChapterMark = z.infer<typeof ChapterMarkSchema>;
99
135
  *
100
136
  * `arriveMs` is when the cursor reaches the point — no later than the step's start, and
101
137
  * pulled earlier for clicks so the arrow is parked and visible before it ripples — and
102
- * `departMs` is when it may leave for the next point, pulled back from the step's finish
103
- * to leave the glide room. `rippleMs` is when a click's ripple *starts*: the step's own
138
+ * `departMs` is when it leaves for the next point: it parks until one distance-scaled glide
139
+ * (200–500ms) before the next arrival rather than leaving at the step's finish, so a gap of
140
+ * untargeted narration is spent waiting, not crawling. `rippleMs` is when a click's ripple *starts*: the step's own
104
141
  * start minus a measured 200ms lead, so the ripple is visibly under way before the
105
142
  * screen the click changes — the step start rather than the action end because whatever
106
143
  * `run()` awaits after the click is the change itself. Present only on `action: 'click'`
@@ -124,6 +161,7 @@ export declare const CursorPointSchema: z.ZodObject<{
124
161
  }>;
125
162
  rippleMs: z.ZodOptional<z.ZodNumber>;
126
163
  scale: z.ZodOptional<z.ZodNumber>;
164
+ cutMs: z.ZodOptional<z.ZodNumber>;
127
165
  }, z.core.$strip>;
128
166
  export declare const CursorSchema: z.ZodObject<{
129
167
  assPath: z.ZodLiteral<"captions/cursor.ass">;
@@ -140,6 +178,7 @@ export declare const CursorSchema: z.ZodObject<{
140
178
  }>;
141
179
  rippleMs: z.ZodOptional<z.ZodNumber>;
142
180
  scale: z.ZodOptional<z.ZodNumber>;
181
+ cutMs: z.ZodOptional<z.ZodNumber>;
143
182
  }, z.core.$strip>>;
144
183
  }, z.core.$strip>;
145
184
  export type Cursor = z.infer<typeof CursorSchema>;
@@ -216,8 +255,34 @@ export declare const SegmentSchema: z.ZodObject<{
216
255
  actorId: z.ZodString;
217
256
  startMs: z.ZodNumber;
218
257
  endMs: z.ZodNumber;
258
+ sourceStartMs: z.ZodOptional<z.ZodNumber>;
259
+ sourceEndMs: z.ZodOptional<z.ZodNumber>;
219
260
  }, z.core.$strip>;
220
261
  export type Segment = z.infer<typeof SegmentSchema>;
262
+ /**
263
+ * The length FFmpeg's `trim=start=S:end=E` actually keeps of a CFR stream, in ms: `trim`
264
+ * rescales both bounds onto the frame grid rounding to nearest (measured: `[0, 2743)` keeps 82
265
+ * frames, `[1400, 2640)` keeps 37), so it keeps `round(E·fps) − round(S·fps)` frames, expressed
266
+ * as `ceil(frames · 1000 / fps)` — exact integer arithmetic, no float `FRAME_MS`. The one place
267
+ * this lives, so a cut's freeze (`cutFreezeMs`) and the badge window it extends cannot disagree
268
+ * by the sub-frame residue of an off-grid span (Chromium's segment files end on a 40ms packet
269
+ * cadence, not on the 30 fps grid).
270
+ */
271
+ export declare const trimmedSpanMs: (window: {
272
+ startMs: number;
273
+ endMs: number;
274
+ }, fps?: number) => number;
275
+ /**
276
+ * A segment's window into `raw/session.webm` that the splice trims: the measured
277
+ * `sourceStartMs`/`sourceEndMs` when the plan carries them (any plan with a cut, and any
278
+ * `terminal.browser` plan), else the capture-derived `startMs`/`endMs` — so every other plan is
279
+ * read exactly as it always was. The splice and the badge windows both read through this, so
280
+ * they cannot disagree about a segment's on-screen length.
281
+ */
282
+ export declare const segmentSourceWindow: (segment: Pick<Segment, "startMs" | "endMs" | "sourceStartMs" | "sourceEndMs">) => {
283
+ startMs: number;
284
+ endMs: number;
285
+ };
221
286
  /**
222
287
  * A full-frame card drawn between two actors' segments on a hand-off — structurally
223
288
  * `Intro`/`Outro`'s sibling, down to the same `HEX_COLOUR` injection guard on its colours,
@@ -236,8 +301,58 @@ export declare const TransitionCardSchema: z.ZodObject<{
236
301
  backgroundColor: z.ZodString;
237
302
  textColor: z.ZodString;
238
303
  assPath: z.ZodString;
304
+ freezeMs: z.ZodOptional<z.ZodNumber>;
239
305
  }, z.core.$strip>;
240
306
  export type TransitionCard = z.infer<typeof TransitionCardSchema>;
307
+ /**
308
+ * A hard cut: the other occupant a joint where the actor changes can have. No card, no gap,
309
+ * no ASS file — the two capture segments either side of it simply abut in the output. It
310
+ * still takes its joint's one slot in `transitionCards` (so "one entry per joint" and the
311
+ * gap-count refine below hold unchanged), and it still names who hands off to whom (so the
312
+ * declared-actor refine holds unchanged too).
313
+ *
314
+ * `kind` exists on the cut alone, never on a card: a card frozen before cuts existed has no
315
+ * `kind` key, and adding one to it would change every existing plan's JSON. The card branch
316
+ * of `TransitionSchema` cannot swallow a cut — it requires `lines`, `durationMs`, both
317
+ * colours and `assPath`, none of which a cut carries — and a cut carrying stray card keys
318
+ * parses as a cut with those keys stripped (Zod's default for unknown keys).
319
+ */
320
+ export declare const TransitionCutSchema: z.ZodObject<{
321
+ kind: z.ZodLiteral<"cut">;
322
+ fromActorId: z.ZodString;
323
+ toActorId: z.ZodString;
324
+ freezeMs: z.ZodOptional<z.ZodNumber>;
325
+ }, z.core.$strip>;
326
+ export type TransitionCut = z.infer<typeof TransitionCutSchema>;
327
+ /**
328
+ * One joint where the actor changes: a card or a cut. **Card first**, so every entry frozen
329
+ * before cuts existed parses through branch one exactly as it always did — same keys, same
330
+ * order — and serialises byte-identically.
331
+ */
332
+ export declare const TransitionSchema: z.ZodUnion<readonly [z.ZodObject<{
333
+ fromActorId: z.ZodString;
334
+ toActorId: z.ZodString;
335
+ durationMs: z.ZodNumber;
336
+ lines: z.ZodArray<z.ZodString>;
337
+ backgroundColor: z.ZodString;
338
+ textColor: z.ZodString;
339
+ assPath: z.ZodString;
340
+ freezeMs: z.ZodOptional<z.ZodNumber>;
341
+ }, z.core.$strip>, z.ZodObject<{
342
+ kind: z.ZodLiteral<"cut">;
343
+ fromActorId: z.ZodString;
344
+ toActorId: z.ZodString;
345
+ freezeMs: z.ZodOptional<z.ZodNumber>;
346
+ }, z.core.$strip>]>;
347
+ export type Transition = z.infer<typeof TransitionSchema>;
348
+ /** Whether a joint is a hard cut rather than a card. Accepts the input shape too (no `assPath`). */
349
+ export declare const isTransitionCut: (transition: TransitionCard | TransitionCut | Omit<TransitionCard, "assPath">) => transition is TransitionCut;
350
+ /**
351
+ * The screen time a hand-off joint claims: 0 for a cut, the card's own `durationMs` otherwise.
352
+ * The one place this arithmetic lives, so the derivation's offsets, the badge windows and the
353
+ * splice graph cannot disagree about it.
354
+ */
355
+ export declare const transitionGapMs: (transition: TransitionCard | TransitionCut | Omit<TransitionCard, "assPath">) => number;
241
356
  /**
242
357
  * One frozen explain scene's real render file, occupying one of the gaps between `segments`.
243
358
  *
@@ -249,7 +364,8 @@ export type TransitionCard = z.infer<typeof TransitionCardSchema>;
249
364
  * `demo.turn()` boundary always changes who is filming (`runtime.ts` refuses a turn to the
250
365
  * actor already holding the browser), and a `demo.explain()` boundary never does (the same
251
366
  * actor's capture merely pauses for the cut-away) — so an "actor changed" gap is always a
252
- * card, and an "actor unchanged" gap is always an explain, and the renderer recovers the
367
+ * `transitionCards` entry (a card, or a zero-length cut — `TransitionCutSchema`), and an
368
+ * "actor unchanged" gap is always an explain, and the renderer recovers the
253
369
  * interleaving from that invariant rather than from a stored index. `segments` may also
254
370
  * carry no `actorId` at all — the no-cast, explain-only case — in which every gap is,
255
371
  * necessarily, an explain (there is no hand-off to draw a card for).
@@ -263,6 +379,7 @@ export declare const ExplainSegmentPlanSchema: z.ZodObject<{
263
379
  id: z.ZodString;
264
380
  segmentPath: z.ZodString;
265
381
  durationMs: z.ZodNumber;
382
+ freezeMs: z.ZodOptional<z.ZodNumber>;
266
383
  }, z.core.$strip>;
267
384
  export type ExplainSegmentPlan = z.infer<typeof ExplainSegmentPlanSchema>;
268
385
  /**
@@ -362,13 +479,14 @@ export type HighlightRect = z.infer<typeof HighlightRectSchema>;
362
479
  * `source` distinguishes a synthesised clip from an author-supplied WAV, because they are the
363
480
  * same bytes by the time they reach here and the distinction is not otherwise recoverable.
364
481
  *
365
- * `explain` is the third provenance: a cut-away scene's narration, synthesised by *plainmotion*
366
- * at record time rather than by this project's own narrator. It never requires the `engine`
367
- * block below, because that block describes one synthesiser — the recorder's kokoro worker —
368
- * and these clips were made by the other one; plainmotion's identity is recorded where the
369
- * rest of its contribution is, the manifest's toolchain block. The rule the refine below
370
- * actually states is "every clip must be accounted for": `synth` is accounted for by `engine`,
371
- * `file` by the author who supplied it, `explain` by the toolchain.
482
+ * `explain` is the third provenance: a cut-away scene's whole laid-out narration track, made
483
+ * by the explain compile (`@plaintake/motion`) rather than by this project's step narrator. It
484
+ * never requires the `engine` block below, because that block describes the run's one step
485
+ * synthesiser and voice; an explain scene may speak in another voice, and its identity is
486
+ * frozen in that scene's own `explain-plan.json` (or, for bundles recorded by 1.28.0 or earlier, in the
487
+ * manifest's `toolchain.plainmotion`). The rule the refine below actually states is "every clip
488
+ * must be accounted for": `synth` is accounted for by `engine`,
489
+ * `file` by the author who supplied it, `explain` by its scene's frozen plan.
372
490
  */
373
491
  export declare const SpeechClipSchema: z.ZodObject<{
374
492
  id: z.ZodString;
@@ -434,6 +552,10 @@ export declare const SpeechSchema: z.ZodObject<{
434
552
  modelSha256: z.ZodString;
435
553
  voice: z.ZodString;
436
554
  }, z.core.$strip>>;
555
+ loudness: z.ZodOptional<z.ZodObject<{
556
+ targetLufs: z.ZodNumber;
557
+ maxPeakDbfs: z.ZodNumber;
558
+ }, z.core.$strip>>;
437
559
  }, z.core.$strip>;
438
560
  export type Speech = z.infer<typeof SpeechSchema>;
439
561
  export type SpeechClip = z.infer<typeof SpeechClipSchema>;
@@ -470,9 +592,11 @@ export type IntroInput = Omit<Intro, 'assPath'>;
470
592
  * practice, which resolves a hand-off's concrete `durationMs` via `transitionCardDurationMs`
471
593
  * before this is ever built, exactly as `intro`/`outro` durations are resolved before
472
594
  * `buildRenderPlan` is called. `assPath` is filled in by `buildRenderPlan`, indexed by
473
- * position in the array against the schema's own `captions/turn-[0-9]+\.ass` family.
595
+ * position in the array against the schema's own `captions/turn-[0-9]+\.ass` family. A cut
596
+ * passes through as it is — it has no file — and keeps its slot, so a card's index is still its
597
+ * joint's position in the whole array and a cards-only plan's paths are unchanged.
474
598
  */
475
- export type TransitionCardInput = Omit<TransitionCard, 'assPath'>;
599
+ export type TransitionCardInput = Omit<TransitionCard, 'assPath'> | TransitionCut;
476
600
  /**
477
601
  * The brand accent: one colour shared by the cursor's fill, its click-ripple ring and the
478
602
  * highlight label's text. One field rather than one per consumer, because the cursor and
@@ -604,6 +728,11 @@ export declare const RenderPlanSchema: z.ZodObject<{
604
728
  x: z.ZodNumber;
605
729
  y: z.ZodNumber;
606
730
  padColor: z.ZodString;
731
+ reframe: z.ZodOptional<z.ZodLiteral<"follow">>;
732
+ layout: z.ZodOptional<z.ZodEnum<{
733
+ social: "social";
734
+ inset: "inset";
735
+ }>>;
607
736
  }, z.core.$strip>>;
608
737
  durationMs: z.ZodNumber;
609
738
  tailPadMs: z.ZodNumber;
@@ -618,6 +747,7 @@ export declare const RenderPlanSchema: z.ZodObject<{
618
747
  startMs: z.ZodNumber;
619
748
  endMs: z.ZodNumber;
620
749
  lines: z.ZodArray<z.ZodString>;
750
+ words: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
621
751
  }, z.core.$strip>>;
622
752
  }, z.core.$strip>;
623
753
  style: z.ZodObject<{
@@ -634,6 +764,9 @@ export declare const RenderPlanSchema: z.ZodObject<{
634
764
  boxColor: z.ZodDefault<z.ZodString>;
635
765
  boxOpacity: z.ZodDefault<z.ZodNumber>;
636
766
  alignment: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<2>, z.ZodLiteral<8>]>>;
767
+ social: z.ZodOptional<z.ZodObject<{
768
+ highlightColor: z.ZodString;
769
+ }, z.core.$strip>>;
637
770
  }, z.core.$strip>;
638
771
  ffmpeg: z.ZodObject<{
639
772
  base: z.ZodArray<z.ZodString>;
@@ -654,6 +787,16 @@ export declare const RenderPlanSchema: z.ZodObject<{
654
787
  textColor: z.ZodString;
655
788
  assPath: z.ZodLiteral<"captions/outro.ass">;
656
789
  }, z.core.$strip>>;
790
+ hook: z.ZodOptional<z.ZodObject<{
791
+ lines: z.ZodArray<z.ZodString>;
792
+ durationMs: z.ZodNumber;
793
+ assPath: z.ZodLiteral<"captions/hook.ass">;
794
+ imagePath: z.ZodOptional<z.ZodLiteral<"captions/hook.png">>;
795
+ }, z.core.$strip>>;
796
+ frame: z.ZodOptional<z.ZodObject<{
797
+ radius: z.ZodNumber;
798
+ assPath: z.ZodLiteral<"captions/frame.ass">;
799
+ }, z.core.$strip>>;
657
800
  chapters: z.ZodOptional<z.ZodObject<{
658
801
  metadataPath: z.ZodLiteral<"render/chapters.ffmetadata">;
659
802
  marks: z.ZodArray<z.ZodObject<{
@@ -677,6 +820,7 @@ export declare const RenderPlanSchema: z.ZodObject<{
677
820
  }>;
678
821
  rippleMs: z.ZodOptional<z.ZodNumber>;
679
822
  scale: z.ZodOptional<z.ZodNumber>;
823
+ cutMs: z.ZodOptional<z.ZodNumber>;
680
824
  }, z.core.$strip>>;
681
825
  }, z.core.$strip>>;
682
826
  camera: z.ZodOptional<z.ZodObject<{
@@ -733,6 +877,10 @@ export declare const RenderPlanSchema: z.ZodObject<{
733
877
  modelSha256: z.ZodString;
734
878
  voice: z.ZodString;
735
879
  }, z.core.$strip>>;
880
+ loudness: z.ZodOptional<z.ZodObject<{
881
+ targetLufs: z.ZodNumber;
882
+ maxPeakDbfs: z.ZodNumber;
883
+ }, z.core.$strip>>;
736
884
  }, z.core.$strip>>;
737
885
  theme: z.ZodOptional<z.ZodObject<{
738
886
  accentColor: z.ZodString;
@@ -747,8 +895,10 @@ export declare const RenderPlanSchema: z.ZodObject<{
747
895
  actorId: z.ZodString;
748
896
  startMs: z.ZodNumber;
749
897
  endMs: z.ZodNumber;
898
+ sourceStartMs: z.ZodOptional<z.ZodNumber>;
899
+ sourceEndMs: z.ZodOptional<z.ZodNumber>;
750
900
  }, z.core.$strip>>>;
751
- transitionCards: z.ZodOptional<z.ZodArray<z.ZodObject<{
901
+ transitionCards: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
752
902
  fromActorId: z.ZodString;
753
903
  toActorId: z.ZodString;
754
904
  durationMs: z.ZodNumber;
@@ -756,12 +906,19 @@ export declare const RenderPlanSchema: z.ZodObject<{
756
906
  backgroundColor: z.ZodString;
757
907
  textColor: z.ZodString;
758
908
  assPath: z.ZodString;
759
- }, z.core.$strip>>>;
909
+ freezeMs: z.ZodOptional<z.ZodNumber>;
910
+ }, z.core.$strip>, z.ZodObject<{
911
+ kind: z.ZodLiteral<"cut">;
912
+ fromActorId: z.ZodString;
913
+ toActorId: z.ZodString;
914
+ freezeMs: z.ZodOptional<z.ZodNumber>;
915
+ }, z.core.$strip>]>>>;
760
916
  badgesAssPath: z.ZodOptional<z.ZodLiteral<"captions/badges.ass">>;
761
917
  explainSegments: z.ZodOptional<z.ZodArray<z.ZodObject<{
762
918
  id: z.ZodString;
763
919
  segmentPath: z.ZodString;
764
920
  durationMs: z.ZodNumber;
921
+ freezeMs: z.ZodOptional<z.ZodNumber>;
765
922
  }, z.core.$strip>>>;
766
923
  }, z.core.$strip>;
767
924
  export type RenderPlan = z.infer<typeof RenderPlanSchema>;
@@ -15,6 +15,13 @@ export declare const ValidationResultSchema: z.ZodObject<{
15
15
  session: "session";
16
16
  }>>;
17
17
  sha256: z.ZodString;
18
+ terminal: z.ZodDefault<z.ZodNullable<z.ZodObject<{
19
+ cols: z.ZodNumber;
20
+ rows: z.ZodNumber;
21
+ shell: z.ZodString;
22
+ command: z.ZodOptional<z.ZodArray<z.ZodString>>;
23
+ browser: z.ZodOptional<z.ZodLiteral<true>>;
24
+ }, z.core.$strip>>>;
18
25
  }, z.core.$strip>>;
19
26
  schema: z.ZodLiteral<"agent-demo.result/v1">;
20
27
  kind: z.ZodLiteral<"validate">;
@@ -523,11 +530,10 @@ export declare const DoctorResultSchema: z.ZodObject<{
523
530
  voices: z.ZodArray<z.ZodString>;
524
531
  notes: z.ZodArray<z.ZodString>;
525
532
  }, z.core.$strip>;
526
- plainmotion: z.ZodObject<{
527
- installed: z.ZodBoolean;
528
- version: z.ZodOptional<z.ZodString>;
529
- note: z.ZodOptional<z.ZodString>;
530
- }, z.core.$strip>;
533
+ terminal: z.ZodOptional<z.ZodObject<{
534
+ ready: z.ZodBoolean;
535
+ notes: z.ZodArray<z.ZodString>;
536
+ }, z.core.$strip>>;
531
537
  schema: z.ZodLiteral<"agent-demo.result/v1">;
532
538
  kind: z.ZodLiteral<"doctor">;
533
539
  ok: z.ZodBoolean;
@@ -595,6 +601,7 @@ export declare const PublishResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
595
601
  "hash-mismatch": "hash-mismatch";
596
602
  "length-mismatch": "length-mismatch";
597
603
  conflict: "conflict";
604
+ "taken-down": "taken-down";
598
605
  }>;
599
606
  schema: z.ZodLiteral<"agent-demo.result/v1">;
600
607
  kind: z.ZodLiteral<"publish">;
@@ -604,6 +611,7 @@ export declare const PublishResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
604
611
  videoId: z.ZodString;
605
612
  url: z.ZodString;
606
613
  uploaded: z.ZodBoolean;
614
+ restored: z.ZodDefault<z.ZodBoolean>;
607
615
  remembered: z.ZodOptional<z.ZodBoolean>;
608
616
  expiresAt: z.ZodOptional<z.ZodString>;
609
617
  captions: z.ZodBoolean;
@@ -613,6 +621,44 @@ export declare const PublishResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
613
621
  kind: z.ZodLiteral<"publish">;
614
622
  problems: z.ZodArray<z.ZodString>;
615
623
  }, z.core.$strip>], "ok">;
624
+ /**
625
+ * A share taken down, or not. The service tombstones: the link answers 410 at once and
626
+ * the bytes stay until `purgeAfter`, so publishing the same bundle again before then
627
+ * restores it. Discriminated on `ok` for the same reason as `PublishResultSchema`.
628
+ */
629
+ export declare const UnpublishResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
630
+ ok: z.ZodLiteral<false>;
631
+ reason: z.ZodEnum<{
632
+ "not-found": "not-found";
633
+ "unexpected-response": "unexpected-response";
634
+ "no-endpoint": "no-endpoint";
635
+ "no-key": "no-key";
636
+ "invalid-store": "invalid-store";
637
+ "not-a-bundle": "not-a-bundle";
638
+ unauthorized: "unauthorized";
639
+ unreachable: "unreachable";
640
+ "invalid-target": "invalid-target";
641
+ "endpoint-mismatch": "endpoint-mismatch";
642
+ forbidden: "forbidden";
643
+ }>;
644
+ schema: z.ZodLiteral<"agent-demo.result/v1">;
645
+ kind: z.ZodLiteral<"unpublish">;
646
+ problems: z.ZodArray<z.ZodString>;
647
+ }, z.core.$strip>, z.ZodObject<{
648
+ ok: z.ZodLiteral<true>;
649
+ videoId: z.ZodString;
650
+ url: z.ZodString;
651
+ deletedAt: z.ZodString;
652
+ deletedBy: z.ZodEnum<{
653
+ producer: "producer";
654
+ admin: "admin";
655
+ expired: "expired";
656
+ }>;
657
+ purgeAfter: z.ZodString;
658
+ schema: z.ZodLiteral<"agent-demo.result/v1">;
659
+ kind: z.ZodLiteral<"unpublish">;
660
+ problems: z.ZodArray<z.ZodString>;
661
+ }, z.core.$strip>], "ok">;
616
662
  export type ArtifactRef = z.infer<typeof ArtifactRefSchema>;
617
663
  export type ValidationResult = z.infer<typeof ValidationResultSchema>;
618
664
  export type RunCommandResult = z.infer<typeof RunCommandResultSchema>;
@@ -630,7 +676,8 @@ export type DoctorResult = z.infer<typeof DoctorResultSchema>;
630
676
  export type ActivateResult = z.infer<typeof ActivateResultSchema>;
631
677
  export type LicenceResult = z.infer<typeof LicenceResultSchema>;
632
678
  export type PublishResult = z.infer<typeof PublishResultSchema>;
633
- export type DemoResult = ValidationResult | RunCommandResult | CheckCommandResult | RenderCommandResult | VerificationReport | WarmCommandResult | DiffCommandResult | CompareCommandResult | InitResult | PruneCommandResult | ImportCommandResult | InspectResult | DoctorResult | ActivateResult | LicenceResult | PublishResult;
679
+ export type UnpublishResult = z.infer<typeof UnpublishResultSchema>;
680
+ export type DemoResult = ValidationResult | RunCommandResult | CheckCommandResult | RenderCommandResult | VerificationReport | WarmCommandResult | DiffCommandResult | CompareCommandResult | InitResult | PruneCommandResult | ImportCommandResult | InspectResult | DoctorResult | ActivateResult | LicenceResult | PublishResult | UnpublishResult;
634
681
  /**
635
682
  * Renders a filesystem location for display in a result, relative to `root` when it
636
683
  * lies inside it.
@@ -23,6 +23,22 @@ export declare const ScenarioIntroSchema: z.ZodObject<{
23
23
  durationMs: z.ZodOptional<z.ZodNumber>;
24
24
  }, z.core.$strip>;
25
25
  export type ScenarioIntro = z.infer<typeof ScenarioIntroSchema>;
26
+ /**
27
+ * The hook: a line or two of text over the top band of a portrait video for its first seconds
28
+ * (`HookSchema` in the render plan says what it is and is not). A string, or `{ text,
29
+ * durationMs }` to hold it for other than the default 3 s.
30
+ *
31
+ * `text` is author-chosen and never generated. A `\n` in it is a line break the author chose;
32
+ * otherwise a long hook is balanced onto two lines at the hook's measured width. Whether every
33
+ * character can be drawn, and whether it fits on two lines, depends on the bundled fonts, which
34
+ * this package cannot see — `validate` checks both (`hookProblems`, `apps/cli`), before a browser
35
+ * opens, and `run` refuses with exit 2 on the same grounds.
36
+ */
37
+ export declare const ScenarioHookSchema: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
38
+ text: z.ZodString;
39
+ durationMs: z.ZodOptional<z.ZodNumber>;
40
+ }, z.core.$strip>]>;
41
+ export type ScenarioHook = z.infer<typeof ScenarioHookSchema>;
26
42
  /**
27
43
  * Per-scenario camera framing, for the demos whose pages the defaults do not suit.
28
44
  *
@@ -78,6 +94,28 @@ export declare const ScenarioSpeechSchema: z.ZodObject<{
78
94
  voices: z.ZodOptional<z.ZodArray<z.ZodString>>;
79
95
  }, z.core.$strip>;
80
96
  export type ScenarioSpeech = z.infer<typeof ScenarioSpeechSchema>;
97
+ export declare const TerminalMetaSchema: z.ZodObject<{
98
+ shell: z.ZodDefault<z.ZodEnum<{
99
+ bash: "bash";
100
+ zsh: "zsh";
101
+ sh: "sh";
102
+ }>>;
103
+ command: z.ZodOptional<z.ZodArray<z.ZodString>>;
104
+ cols: z.ZodDefault<z.ZodNumber>;
105
+ rows: z.ZodDefault<z.ZodNumber>;
106
+ cwd: z.ZodOptional<z.ZodString>;
107
+ env: z.ZodDefault<z.ZodArray<z.ZodString>>;
108
+ secrets: z.ZodDefault<z.ZodArray<z.ZodString>>;
109
+ browser: z.ZodOptional<z.ZodBoolean>;
110
+ label: z.ZodOptional<z.ZodString>;
111
+ transition: z.ZodOptional<z.ZodEnum<{
112
+ cut: "cut";
113
+ card: "card";
114
+ }>>;
115
+ }, z.core.$strip>;
116
+ export type TerminalMeta = z.infer<typeof TerminalMetaSchema>;
117
+ /** What an author writes: every defaulted field (`shell`, `cols`, `rows`, `env`, `secrets`) optional. */
118
+ export type TerminalMetaInput = z.input<typeof TerminalMetaSchema>;
81
119
  export declare const ScenarioMetaSchema: z.ZodObject<{
82
120
  schema: z.ZodLiteral<"agent-demo.scenario/v1">;
83
121
  id: z.ZodString;
@@ -88,6 +126,7 @@ export declare const ScenarioMetaSchema: z.ZodObject<{
88
126
  height: z.ZodLiteral<1080>;
89
127
  deviceScaleFactor: z.ZodLiteral<1>;
90
128
  }, z.core.$strip>;
129
+ uiScale: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<1.5>, z.ZodLiteral<2>]>>;
91
130
  locale: z.ZodLiteral<"en-US">;
92
131
  timezoneId: z.ZodLiteral<"UTC">;
93
132
  colorScheme: z.ZodLiteral<"light">;
@@ -104,6 +143,10 @@ export declare const ScenarioMetaSchema: z.ZodObject<{
104
143
  narration: z.ZodOptional<z.ZodString>;
105
144
  durationMs: z.ZodOptional<z.ZodNumber>;
106
145
  }, z.core.$strip>>;
146
+ hook: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
147
+ text: z.ZodString;
148
+ durationMs: z.ZodOptional<z.ZodNumber>;
149
+ }, z.core.$strip>]>>;
107
150
  camera: z.ZodOptional<z.ZodObject<{
108
151
  maxZoom: z.ZodOptional<z.ZodNumber>;
109
152
  margin: z.ZodOptional<z.ZodNumber>;
@@ -114,6 +157,25 @@ export declare const ScenarioMetaSchema: z.ZodObject<{
114
157
  speed: z.ZodOptional<z.ZodNumber>;
115
158
  voices: z.ZodOptional<z.ZodArray<z.ZodString>>;
116
159
  }, z.core.$strip>>;
160
+ terminal: z.ZodOptional<z.ZodObject<{
161
+ shell: z.ZodDefault<z.ZodEnum<{
162
+ bash: "bash";
163
+ zsh: "zsh";
164
+ sh: "sh";
165
+ }>>;
166
+ command: z.ZodOptional<z.ZodArray<z.ZodString>>;
167
+ cols: z.ZodDefault<z.ZodNumber>;
168
+ rows: z.ZodDefault<z.ZodNumber>;
169
+ cwd: z.ZodOptional<z.ZodString>;
170
+ env: z.ZodDefault<z.ZodArray<z.ZodString>>;
171
+ secrets: z.ZodDefault<z.ZodArray<z.ZodString>>;
172
+ browser: z.ZodOptional<z.ZodBoolean>;
173
+ label: z.ZodOptional<z.ZodString>;
174
+ transition: z.ZodOptional<z.ZodEnum<{
175
+ cut: "cut";
176
+ card: "card";
177
+ }>>;
178
+ }, z.core.$strip>>;
117
179
  pronunciations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
118
180
  }, z.core.$strip>;
119
181
  /** Which phase, if any, hands the browser over. Read by the recorder and the surfaces. */