@jokerized/decksmith 0.9.3 → 0.9.5
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.
- package/README.md +449 -90
- package/dist/animate/LICENSE +21 -0
- package/dist/animate/NOTICE +32 -0
- package/dist/animate/core.js +530 -0
- package/dist/animate/cut-paper.js +206 -0
- package/dist/animate/morph.js +131 -0
- package/dist/cli.js +13424 -8867
- package/dist/ds-animate.js +1 -0
- package/dist/index.js +13251 -8697
- package/dist/mcp.js +9845 -7577
- package/dist/types/bespoke/art.d.ts +172 -6
- package/dist/types/bespoke/cache.d.ts +10 -0
- package/dist/types/bespoke/cards.d.ts +66 -0
- package/dist/types/bespoke/contract.d.ts +0 -8
- package/dist/types/bespoke/databuild.d.ts +50 -0
- package/dist/types/bespoke/depth.d.ts +127 -0
- package/dist/types/bespoke/grammar.d.ts +73 -0
- package/dist/types/bespoke/inspect.d.ts +40 -1
- package/dist/types/bespoke/pipeline.d.ts +195 -11
- package/dist/types/bespoke/probe.d.ts +2 -2
- package/dist/types/bespoke/prompt.d.ts +110 -34
- package/dist/types/bespoke/references.d.ts +13 -14
- package/dist/types/bespoke/repair.d.ts +23 -29
- package/dist/types/bespoke/scene.d.ts +55 -10
- package/dist/types/bespoke/select.d.ts +28 -21
- package/dist/types/bespoke/sheet.d.ts +66 -1
- package/dist/types/bespoke/shots.d.ts +225 -22
- package/dist/types/build/files.d.ts +7 -0
- package/dist/types/build/piece.d.ts +8 -0
- package/dist/types/emit/animate-runtime.d.ts +149 -0
- package/dist/types/emit/archetypes/claim-figure.d.ts +84 -1
- package/dist/types/emit/archetypes/equation-walk.d.ts +2 -2
- package/dist/types/emit/archetypes/hero-number.d.ts +21 -0
- package/dist/types/emit/archetypes/index.d.ts +2 -2
- package/dist/types/emit/archetypes/kinetic.d.ts +2 -0
- package/dist/types/emit/archetypes/pipeline.d.ts +14 -2
- package/dist/types/emit/archetypes/stage.d.ts +57 -0
- package/dist/types/emit/backdrop.d.ts +114 -0
- package/dist/types/emit/kit.d.ts +8 -0
- package/dist/types/emit/look.d.ts +14 -0
- package/dist/types/emit/motion.d.ts +78 -46
- package/dist/types/emit/type.d.ts +48 -5
- package/dist/types/images/providers.d.ts +6 -0
- package/dist/types/plan/codex.d.ts +18 -4
- package/dist/types/plan/direct.d.ts +1 -1
- package/dist/types/plan/duration.d.ts +1 -1
- package/dist/types/plan/prompt.d.ts +1 -1
- package/dist/types/plan/refs.d.ts +2 -2
- package/dist/types/plan/variety.d.ts +74 -0
- package/dist/types/prefs.d.ts +20 -1
- package/dist/types/render/captions.d.ts +4 -5
- package/dist/types/render/capture.d.ts +7 -0
- package/dist/types/types.d.ts +680 -4
- package/dist/types/verify/drift.d.ts +5 -0
- package/dist/types/verify/fidelity.d.ts +15 -1
- package/dist/types/verify/index.d.ts +17 -0
- package/dist/types/verify/scenes.d.ts +185 -5
- package/package.json +1 -1
- package/dist/types/bespoke/callouts.d.ts +0 -76
|
@@ -139,6 +139,11 @@ export declare function judge(m: {
|
|
|
139
139
|
db: number;
|
|
140
140
|
};
|
|
141
141
|
motion: Motion;
|
|
142
|
+
/**
|
|
143
|
+
* The worker count of each render, so the passing note says what was
|
|
144
|
+
* compared: `--workers 1` pins both, and must not be reported as two counts.
|
|
145
|
+
*/
|
|
146
|
+
workers?: readonly [number | "auto" | undefined, number | "auto" | undefined];
|
|
142
147
|
}): DriftReport;
|
|
143
148
|
/**
|
|
144
149
|
* `frame_000001.png` → `frame_%06d.png`, for ffmpeg's image2 demuxer.
|
|
@@ -139,6 +139,7 @@
|
|
|
139
139
|
* demo moves 5.81s to 6.32s, and that is a cold cache. A gate too slow to run is
|
|
140
140
|
* a gate nobody runs; this one costs nothing, so it runs by default.
|
|
141
141
|
*/
|
|
142
|
+
import type { BrokenFrame } from "../emit/animate-runtime.js";
|
|
142
143
|
import type { Finding } from "../types.js";
|
|
143
144
|
import { type FillRow } from "./fill.js";
|
|
144
145
|
/**
|
|
@@ -257,7 +258,7 @@ export declare function decodePng(png: Uint8Array): Promise<Frame>;
|
|
|
257
258
|
* bounding box, and it does not ask the DOM whether an element is visible; both
|
|
258
259
|
* of those have been wrong in this project inside the last week.
|
|
259
260
|
*/
|
|
260
|
-
export declare function inkBelow(frame: Frame, bandTopPx: number): number;
|
|
261
|
+
export declare function inkBelow(frame: Frame, bandTopPx: number, plate?: Frame | null): number;
|
|
261
262
|
/**
|
|
262
263
|
* Where a scene's BODY is, in device px: the part of the frame that is not its
|
|
263
264
|
* chrome. Classic chrome is a block across the top, so the body is everything
|
|
@@ -344,6 +345,19 @@ export declare function collectUnfit(attr: string): Unfit[];
|
|
|
344
345
|
* shorten.
|
|
345
346
|
*/
|
|
346
347
|
export declare function gradeUnfit(rows: readonly Unfit[]): Finding[];
|
|
348
|
+
/**
|
|
349
|
+
* Run IN THE PAGE: every mounted animate piece drawn at each of its own frames
|
|
350
|
+
* (`sweep`, src/emit/animate-runtime.ts). Empty on a deck with no piece, whose
|
|
351
|
+
* page never loads the runtime.
|
|
352
|
+
*/
|
|
353
|
+
export declare function collectBrokenPieces(): BrokenFrame[];
|
|
354
|
+
/**
|
|
355
|
+
* An error per piece that throws at ANY of its frames. A drawing error is a
|
|
356
|
+
* page error only where `hyperframes check` happens to seek, and on a long deck
|
|
357
|
+
* it samples coarsely enough to miss a throw confined to a short window — which
|
|
358
|
+
* `render` then draws half-painted and exits 0 over.
|
|
359
|
+
*/
|
|
360
|
+
export declare function gradePieces(rows: readonly BrokenFrame[]): Finding[];
|
|
347
361
|
/**
|
|
348
362
|
* Seek every declared stop and count the ink below its caption.
|
|
349
363
|
*
|
|
@@ -427,3 +427,20 @@ export declare function scanNarrationLead(beats: readonly Beat[], timing: {
|
|
|
427
427
|
}): Finding[];
|
|
428
428
|
/** Flag render-time nondeterminism in one composition file (invariant 7). */
|
|
429
429
|
export declare function scanDeterminism(html: string, file: string): Finding[];
|
|
430
|
+
/**
|
|
431
|
+
* Every script under the deck's `assets/` — which is where an animate piece's
|
|
432
|
+
* assembled script lives (src/build/piece.ts), and the only file holding code
|
|
433
|
+
* an AUTHOR wrote. It runs at render time like the composition does, so the
|
|
434
|
+
* determinism scan reads it; the type and budget gates, which read markup, do
|
|
435
|
+
* not.
|
|
436
|
+
*/
|
|
437
|
+
export declare function readAssetScripts(dir: string): Promise<Array<[string, string]>>;
|
|
438
|
+
/**
|
|
439
|
+
* ROUND 5, the deck's variety: the camera grammars its illustrated scenes are
|
|
440
|
+
* staged in (`data-ds-grammar`, stamped by the shell) and the builds of its
|
|
441
|
+
* data scenes (`data-ds-build`), in scene order. Two consecutive illustrated
|
|
442
|
+
* scenes in one grammar, or two data scenes that build alike, is the "same
|
|
443
|
+
* animation every card" one level up; fewer distinct grammars than
|
|
444
|
+
* `diversityWanted` is reported.
|
|
445
|
+
*/
|
|
446
|
+
export declare function scanStagingVariety(compositions: readonly string[]): Finding[];
|
|
@@ -1,3 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Three gates on a scene's MOTION, which no other gate here looks at, run in
|
|
3
|
+
* the renderer's own browser at the narration's cue boundaries.
|
|
4
|
+
*
|
|
5
|
+
* 1. `static_hold` — the picture must change during every narration cue. A
|
|
6
|
+
* v2 archetype finishes building in about five seconds and then holds still
|
|
7
|
+
* for fifteen to twenty seconds of speech (spike, 2026-10-07: 0 px changed
|
|
8
|
+
* between cue ends on two of four beats). A bespoke scene exists to keep
|
|
9
|
+
* explaining while the voice does, so for one this is an error.
|
|
10
|
+
* 2. `graphic_crosses_text` (with `text_overlap`, `bespoke_type_floor`,
|
|
11
|
+
* `off_canvas`) — a drawn stroke must not run through a label, and a filled
|
|
12
|
+
* shape painted later must not cover one. The spike's worst defect was a
|
|
13
|
+
* giant stray arc across a whole diagram that every gate passed, including a
|
|
14
|
+
* text-on-text overlap check; strokes were simply not text. Strokes are
|
|
15
|
+
* sampled along their geometry and their dash pattern, so a line drawn by
|
|
16
|
+
* DrawSVG is checked only where it is visible at that instant.
|
|
17
|
+
* Round 2 adds what round 1's frames showed a person and no gate: the
|
|
18
|
+
* settled drawing must span `STAGE_FILL` of its box (`stage_fill`) and carry
|
|
19
|
+
* one label of `KEY_TYPE_PX` or more (`type_hierarchy`), none over
|
|
20
|
+
* `MAX_TYPE_PX` (`type_ceiling`, 2026-10-10); an arrowhead must
|
|
21
|
+
* not show where its line is not drawn (`stray_marker`); and a group the
|
|
22
|
+
* scene tags `data-cue="N"` must not show before cue N starts
|
|
23
|
+
* (`early_reveal`, with `cue_groups` failing a scene that tags nothing).
|
|
24
|
+
* Round 6, after the founder's "animated UI elements are old-fashioned, and
|
|
25
|
+
* the fonts are too large": no word in a bespoke scene renders above the
|
|
26
|
+
* deck's headline size (`type_scale`, TYPE_SCALE in src/emit/type.ts —
|
|
27
|
+
* round 2's 64px floor for a key label is gone), and no label, plate,
|
|
28
|
+
* chip, card or bar is animated into place (`ui_motion`, read off the
|
|
29
|
+
* scene's own GSAP timeline).
|
|
30
|
+
* 3. `seek_order` — the frame at time t must not depend on which times were
|
|
31
|
+
* seeked before it. Capture shards a render across workers and the deck
|
|
32
|
+
* player jumps around, so a frame that depends on history is a frame that
|
|
33
|
+
* differs between two renders of one input. Ascending, descending (after
|
|
34
|
+
* jumping past the scene), a fixed scramble, and a cold page are compared.
|
|
35
|
+
* This is what found v2's equation-walk bug: a `fromTo` authored with
|
|
36
|
+
* `immediateRender` set its from-state at BUILD time, so a cold seek showed
|
|
37
|
+
* a swollen term that a warm seek did not.
|
|
38
|
+
*
|
|
39
|
+
* The graders are pure and take what the browser measured, so each is tested
|
|
40
|
+
* without one; `probeScenes` is the one place a browser is opened.
|
|
41
|
+
*/
|
|
1
42
|
import type { DeckPage } from "../render/capture.js";
|
|
2
43
|
import type { Timing } from "../render/timing.js";
|
|
3
44
|
import type { Finding } from "../types.js";
|
|
@@ -15,7 +56,7 @@ export declare const PIXEL_DELTA = 24;
|
|
|
15
56
|
*/
|
|
16
57
|
export declare const SEEK_TOLERANCE_PX = 1500;
|
|
17
58
|
/** Bump whenever a gate's verdict can change: cached rejections from another version are retried. */
|
|
18
|
-
export declare const GATES_VERSION = "gates-
|
|
59
|
+
export declare const GATES_VERSION = "gates-7";
|
|
19
60
|
/**
|
|
20
61
|
* A cue whose picture changes by less than this share of the frame held still:
|
|
21
62
|
* about 310 px at 1080p. A frame that does not move renders to the same bytes,
|
|
@@ -60,10 +101,42 @@ export declare function gradeStillCues(rows: readonly CueChange[], min?: number)
|
|
|
60
101
|
* bottom band empty, at a size the founder called small.
|
|
61
102
|
*/
|
|
62
103
|
export declare const STAGE_FILL = 0.8;
|
|
63
|
-
/**
|
|
64
|
-
|
|
104
|
+
/**
|
|
105
|
+
* The settled frame's largest label, px at 1080p: one label reaches the body
|
|
106
|
+
* size (`TYPE_SCALE`), so something is read first…
|
|
107
|
+
*/
|
|
108
|
+
export declare const KEY_TYPE_PX: 44;
|
|
109
|
+
/**
|
|
110
|
+
* …and nothing passes the headline's size. The founder's verdict on the 88-120px
|
|
111
|
+
* focal numbers this gate used to ASK for was "the fonts are too large"
|
|
112
|
+
* (2026-10-10): the picture is the focus, the subtitles carry the words.
|
|
113
|
+
*/
|
|
114
|
+
export declare const MAX_TYPE_PX: 56;
|
|
115
|
+
/**
|
|
116
|
+
* The largest a bespoke scene's own words may RENDER, px at 1080p, at any graded
|
|
117
|
+
* frame, camera zoom included (`type_scale`, round 6): `type_ceiling` reads the
|
|
118
|
+
* size a word declares, this one what the audience sees.
|
|
119
|
+
*/
|
|
120
|
+
export declare const TYPE_MAX_PX: number;
|
|
65
121
|
/** A cue group may appear this long before its cue starts (the prompt's own sync window). */
|
|
66
122
|
export declare const EARLY_SLACK = 0.5;
|
|
123
|
+
/**
|
|
124
|
+
* The longest a seam may leave the stage empty (round 6): r1's final review
|
|
125
|
+
* found 12 of 15 seams showing nothing but the headline for ~0.6s — the
|
|
126
|
+
* outgoing scene gone, the incoming one's first group not yet in.
|
|
127
|
+
*/
|
|
128
|
+
export declare const SEAM_BLANK_MAX = 0.15;
|
|
129
|
+
/**
|
|
130
|
+
* The height share of its box a bespoke scene's drawing spans while a later
|
|
131
|
+
* cue holds (`hollow_hold`): the fill module's EMPTY band. r1's final s8 held
|
|
132
|
+
* three calipers across the top 58% for seconds; its settled end frame filled.
|
|
133
|
+
*/
|
|
134
|
+
export declare const HOLD_SPAN_MIN = 0.7;
|
|
135
|
+
/**
|
|
136
|
+
* Below this share of the frame painted (headlines aside), the stage is empty:
|
|
137
|
+
* about one 64px mark. r1's blank seams read exactly 0.
|
|
138
|
+
*/
|
|
139
|
+
export declare const SEAM_PAINT_MIN = 0.002;
|
|
67
140
|
/**
|
|
68
141
|
* At the settled frame, at most this share of a scene's parts may be ones it
|
|
69
142
|
* showed lit (>= `LIT`) earlier and has left dimmed (< `DIM`). Round 2 kept
|
|
@@ -92,6 +165,8 @@ export interface GeoLabel {
|
|
|
92
165
|
export interface Geo {
|
|
93
166
|
w: number;
|
|
94
167
|
h: number;
|
|
168
|
+
/** The shell camera's scale at this frame (1 when it has none). */
|
|
169
|
+
cs?: number;
|
|
95
170
|
labels: GeoLabel[];
|
|
96
171
|
/** Filled shapes and pictures: address, owning label unit, paint order, box. */
|
|
97
172
|
boxes: Array<{
|
|
@@ -102,7 +177,7 @@ export interface Geo {
|
|
|
102
177
|
}>;
|
|
103
178
|
/** Visible stroke samples, body px, with the label unit they belong to. */
|
|
104
179
|
points: Array<[number, number, string | null]>;
|
|
105
|
-
/** Each visible part's opacity and what dims it (`tag:index`, `#id` appended when it has one). */
|
|
180
|
+
/** Each visible part's opacity and what dims it (`tag:index`, `#id` appended when it has one, then `@` its own opacity). */
|
|
106
181
|
parts: Array<{
|
|
107
182
|
a: string;
|
|
108
183
|
al: number;
|
|
@@ -125,8 +200,15 @@ export interface Layout {
|
|
|
125
200
|
fill?: number;
|
|
126
201
|
/** Share of a 6x4 grid over the body box that something is drawn in. Reported, not graded. */
|
|
127
202
|
cells?: number;
|
|
128
|
-
/** The largest visible label in the body box, px. */
|
|
203
|
+
/** The largest visible label in the body box, px as drawn (a camera push-in scales it). */
|
|
129
204
|
maxType?: number;
|
|
205
|
+
/**
|
|
206
|
+
* The largest font-size a visible label in the body box DECLARES, KaTeX
|
|
207
|
+
* excluded (it sets itself at 1.21em of its box): what `type_ceiling` holds
|
|
208
|
+
* to `MAX_TYPE_PX`. Not `maxType`, which a camera push-in or a viewBox zoom
|
|
209
|
+
* grows past the size the scene asked for.
|
|
210
|
+
*/
|
|
211
|
+
maxDeclared?: number;
|
|
130
212
|
/** Share of the body box the settled drawing paints (`paintedShare`). Reported; the rubric probe reads it. */
|
|
131
213
|
mass?: number;
|
|
132
214
|
/** Share of the drawn labels and shapes in the body box at under 0.6 opacity. */
|
|
@@ -161,6 +243,14 @@ export interface Layout {
|
|
|
161
243
|
}>;
|
|
162
244
|
/** Labels with digits in them sitting on the illustration. */
|
|
163
245
|
onPicture?: number;
|
|
246
|
+
/** Visible text in the body box under `TEXT_CONTRAST` against its backdrop, as `id [box] ratio`. */
|
|
247
|
+
faint?: string[];
|
|
248
|
+
/** End row: the scene's own tweens that animate a label, plate, chip, card or bar into place (`ui_motion`). */
|
|
249
|
+
uiMotion?: string[];
|
|
250
|
+
/** Height share of the body box the drawing spans (bespoke scenes), for \`hollow_hold\`. */
|
|
251
|
+
span?: number;
|
|
252
|
+
/** Pairs of alike filled dots drawn into each other (\`marks_overlap\`). */
|
|
253
|
+
marksOverlap?: string[];
|
|
164
254
|
}
|
|
165
255
|
/**
|
|
166
256
|
* A label that names a subject sits within this many box px of that
|
|
@@ -185,6 +275,12 @@ export interface CamSample {
|
|
|
185
275
|
shot: [number, number, number, number, number];
|
|
186
276
|
/** How many subjects the scene's illustration has. */
|
|
187
277
|
subjects: number;
|
|
278
|
+
/** The camera grammar the shell stamped on the scene (src/bespoke/grammar.ts). */
|
|
279
|
+
grammar?: string;
|
|
280
|
+
/** The backdrop's scale, x, y (round 5's second layer), when it has one. */
|
|
281
|
+
plate?: [number, number, number];
|
|
282
|
+
/** How much of the box's width a wiped-on picture shows, 0..1, when it is wiped. */
|
|
283
|
+
wipe?: number;
|
|
188
284
|
}
|
|
189
285
|
/**
|
|
190
286
|
* The distinct shots a scene's camera HOLDS: a push-in counts when two
|
|
@@ -197,6 +293,12 @@ export declare function shotsOf(samples: readonly CamSample[]): {
|
|
|
197
293
|
wide: boolean;
|
|
198
294
|
close: Array<[number, number]>;
|
|
199
295
|
};
|
|
296
|
+
/**
|
|
297
|
+
* Whether the camera did what its grammar says (src/bespoke/grammar.ts), read
|
|
298
|
+
* off the samples alone — so a shell that compiled every grammar to round 4's
|
|
299
|
+
* tour would fail here, not pass on the stamp.
|
|
300
|
+
*/
|
|
301
|
+
export declare function grammarBroken(grammar: string, list: readonly CamSample[], t0?: number): string[];
|
|
200
302
|
/**
|
|
201
303
|
* `shot_variety`: an illustrated scene is staged — it OPENS on the whole
|
|
202
304
|
* picture (every sample in the first second of its first cue is wide), and the
|
|
@@ -205,6 +307,67 @@ export declare function shotsOf(samples: readonly CamSample[]): {
|
|
|
205
307
|
* first cue start.
|
|
206
308
|
*/
|
|
207
309
|
export declare function gradeShots(samples: readonly CamSample[], opens?: ReadonlyMap<string, number>): Finding[];
|
|
310
|
+
/**
|
|
311
|
+
* `text_clipped`: a word the frame cuts in two while it is HELD there. A
|
|
312
|
+
* camera push or a clipped viewBox crops what lies at its edge, and a shape cut
|
|
313
|
+
* off reads as framing — a label cut mid-word does not (r1, 2026-10-10: '…인된
|
|
314
|
+
* 결과' held for 2.5s at s12's left edge, '구조 맵' cropped by s7's push-ins).
|
|
315
|
+
* Sampled every `CAM_STEP`; a text counts when it is partly inside the frame
|
|
316
|
+
* (more than `CUT_MIN` of it) and has lost more than a sliver across (under
|
|
317
|
+
* `CUT_MAX` of its width) or more than its leading down (under `CUT_DEEP` of
|
|
318
|
+
* its height), at `CUT_HOLD` consecutive samples — so a label sliding out
|
|
319
|
+
* during a 1.1s move is not one.
|
|
320
|
+
*/
|
|
321
|
+
export declare const CUT_MIN = 0.05;
|
|
322
|
+
/** Under this share of its width inside the frame, a word has lost a glyph. */
|
|
323
|
+
export declare const CUT_MAX = 0.96;
|
|
324
|
+
/** Under this share of its line box's height, a word has lost ink (the rest is leading). */
|
|
325
|
+
export declare const CUT_DEEP = 0.75;
|
|
326
|
+
export declare const CUT_HOLD = 3;
|
|
327
|
+
/** One dense sample of one scene: the texts the frame cuts, as `id (share%)`. */
|
|
328
|
+
export interface CutSample {
|
|
329
|
+
sid: string;
|
|
330
|
+
t: number;
|
|
331
|
+
cut: Array<{
|
|
332
|
+
id: string;
|
|
333
|
+
share: number;
|
|
334
|
+
}>;
|
|
335
|
+
}
|
|
336
|
+
export declare function gradeCuts(samples: readonly CutSample[]): Finding[];
|
|
337
|
+
/**
|
|
338
|
+
* `morph_glitch`: a path tween that throws its shape across the stage on the
|
|
339
|
+
* way. An `attr: { d }` tween pairs the two paths' numbers in order, so between
|
|
340
|
+
* paths of different commands (`V455 L1090 320` against `L1090 405 L1240 495`)
|
|
341
|
+
* an x is tweened into a y and back (r1 s4 at 61.75s: a green wedge over half
|
|
342
|
+
* the frame, between two shapes on its right); a morphSVG between mismatched
|
|
343
|
+
* shapes can do the same. Between matched paths every in-between point lies
|
|
344
|
+
* between its two ends, so the shape stays inside their union. A tween counts
|
|
345
|
+
* when, at any in-between sample of one iteration, the shape is visible and
|
|
346
|
+
* reaches more than `MORPH_REACH` of the larger side of its two ends' union
|
|
347
|
+
* (and 60px at least) past that union.
|
|
348
|
+
*/
|
|
349
|
+
export declare const MORPH_REACH = 0.35;
|
|
350
|
+
/** One morph tween's shape box at shares of its duration: [x, y, w, h] in page px, and its opacity. */
|
|
351
|
+
export interface MorphSample {
|
|
352
|
+
sid: string;
|
|
353
|
+
id: string;
|
|
354
|
+
start: number;
|
|
355
|
+
dur: number;
|
|
356
|
+
boxes: Array<{
|
|
357
|
+
f: number;
|
|
358
|
+
b: [number, number, number, number];
|
|
359
|
+
o: number;
|
|
360
|
+
}>;
|
|
361
|
+
}
|
|
362
|
+
export declare function gradeMorphs(samples: readonly MorphSample[]): Finding[];
|
|
363
|
+
/**
|
|
364
|
+
* `dim_text`: a word left under 3:1 contrast with what is behind it, at a held
|
|
365
|
+
* frame (a cue's end, the settled end). Every bespoke label is 40px or more —
|
|
366
|
+
* large text — so 3:1 is the WCAG floor; focus dimming had taken key numbers to
|
|
367
|
+
* 1.6:1 (r1 s13 "75.1 %") and named subjects to 1.5:1 (s8) while the voice was
|
|
368
|
+
* on them.
|
|
369
|
+
*/
|
|
370
|
+
export declare const TEXT_CONTRAST = 3;
|
|
208
371
|
export declare function gradeLayout(rows: readonly Layout[]): Finding[];
|
|
209
372
|
/**
|
|
210
373
|
* What the page did that a scene must not, pinned to the scenes it implicates.
|
|
@@ -281,6 +444,17 @@ export interface ProbedFrame {
|
|
|
281
444
|
t: number;
|
|
282
445
|
png: Buffer;
|
|
283
446
|
}
|
|
447
|
+
/** How long the stage stood empty across the seam into one scene (`seam_blank`). */
|
|
448
|
+
export interface SeamSample {
|
|
449
|
+
sid: string;
|
|
450
|
+
/** The longest run, seconds, with under `SEAM_PAINT_MIN` of the frame painted. */
|
|
451
|
+
blank: number;
|
|
452
|
+
/** Scene seconds (negative: before the seam) where that run starts. */
|
|
453
|
+
at: number;
|
|
454
|
+
/** Whether the incoming scene is a generated (bespoke) one. */
|
|
455
|
+
bespoke: boolean;
|
|
456
|
+
}
|
|
457
|
+
export declare function gradeSeams(rows: readonly SeamSample[]): Finding[];
|
|
284
458
|
export interface Probe {
|
|
285
459
|
findings: Finding[];
|
|
286
460
|
/** Ascending-pass frames, for a contact sheet. */
|
|
@@ -290,6 +464,12 @@ export interface Probe {
|
|
|
290
464
|
seek: SeekDiff[];
|
|
291
465
|
/** The shell's camera every `CAM_STEP` through each illustrated scene (`shot_variety`). */
|
|
292
466
|
cams: CamSample[];
|
|
467
|
+
/** The words the frame cuts, every `CAM_STEP` through each bespoke scene (`text_clipped`). */
|
|
468
|
+
cuts: CutSample[];
|
|
469
|
+
/** Each morphSVG tween's shape through its run (`morph_glitch`). */
|
|
470
|
+
morphs: MorphSample[];
|
|
471
|
+
/** The stage across each seam into a probed scene (`seam_blank`). */
|
|
472
|
+
seams: SeamSample[];
|
|
293
473
|
}
|
|
294
474
|
export interface ProbeOptions {
|
|
295
475
|
/** Which gates. Default all three. `seek` alone is what `verify` runs on plain v2 scenes. */
|
package/package.json
CHANGED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The labels of an illustrated scene, drawn by the shell ON their subjects.
|
|
3
|
-
*
|
|
4
|
-
* WHY THE SHELL AND NOT THE SCENE. Round 3's labels were plates in a row along
|
|
5
|
-
* the top of the box. Round 4's first run (2026-10-09, en deck) asked the scene
|
|
6
|
-
* to put each label on its subject itself: the labels went on their subjects
|
|
7
|
-
* (3-4 of 3-4 within 96px in every draft), and four of five scenes then failed
|
|
8
|
-
* on their own plates and leader lines running through their own text — the
|
|
9
|
-
* model guesses a label's width, and at 56px a guess is wrong by more than the
|
|
10
|
-
* plate's margin. The shell knows the width (the same estimator the archetypes
|
|
11
|
-
* lay out with), so the scene says WHAT each subject is called (`labels`) and
|
|
12
|
-
* the shell says WHERE: a plate in a zone just above the subject (or across
|
|
13
|
-
* its top when there is no room above), a leader line to a dot on it, entering
|
|
14
|
-
* when the camera first arrives on that subject. One grammar for every deck.
|
|
15
|
-
*
|
|
16
|
-
* Zones are fixed from the subjects alone, before the scene is written, so the
|
|
17
|
-
* prompt can tell the scene where they are and to keep its own drawing out.
|
|
18
|
-
*/
|
|
19
|
-
import type { Theme } from "../emit/kit.js";
|
|
20
|
-
import type { Box, CamMove } from "./shots.js";
|
|
21
|
-
/** One subject's label, as the scene names it. */
|
|
22
|
-
export interface Label {
|
|
23
|
-
subject: number;
|
|
24
|
-
text: string;
|
|
25
|
-
}
|
|
26
|
-
/** Where a subject's label goes: its zone (box px), and the dot its leader ends on. */
|
|
27
|
-
export interface Zone extends Box {
|
|
28
|
-
subject: number;
|
|
29
|
-
/** "above" the subject, or across its "top" inside it. */
|
|
30
|
-
side: "above" | "top";
|
|
31
|
-
dot: {
|
|
32
|
-
x: number;
|
|
33
|
-
y: number;
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
/** The label's size, and the floor it may shrink to to fit its zone. */
|
|
37
|
-
export declare const LABEL_PX = 56;
|
|
38
|
-
export declare const LABEL_MIN_PX = 44;
|
|
39
|
-
/**
|
|
40
|
-
* Each subject's label zone: centred over the subject, as wide as half the
|
|
41
|
-
* distance to each neighbour allows (so neighbours' zones never meet), above
|
|
42
|
-
* the subject when there is room, else across its top.
|
|
43
|
-
*/
|
|
44
|
-
export declare function calloutZones(subjects: readonly Box[], W: number): Zone[];
|
|
45
|
-
/** How a label is set: its size and its line(s). */
|
|
46
|
-
export interface Fit {
|
|
47
|
-
fs: number;
|
|
48
|
-
lines: string[];
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* How a label fits its zone: one line from `LABEL_PX` down to `LABEL_MIN_PX`,
|
|
52
|
-
* else two lines (the plate grows away from the subject, as far as the box
|
|
53
|
-
* allows), else not at all.
|
|
54
|
-
*/
|
|
55
|
-
export declare function fitLabel(text: string, zone: Zone, theme: Theme, boxH?: number): Fit | undefined;
|
|
56
|
-
/**
|
|
57
|
-
* Roughly how many characters fit a zone at the floor size, for the prompt
|
|
58
|
-
* ("at most N characters"): Latin lowercase if the deck is Latin, else the
|
|
59
|
-
* deck's script, at `LABEL_MIN_PX`. The fit itself is `fitLabel`'s.
|
|
60
|
-
*/
|
|
61
|
-
export declare function longestFit(zone: Zone, theme: Theme): number;
|
|
62
|
-
/** What the camera frames for a subject: the subject and its label zone together. */
|
|
63
|
-
export declare function withZone(s: Box, z: Zone | undefined): Box;
|
|
64
|
-
/** When each subject's label enters: as the camera arrives on it, else at the reveal. */
|
|
65
|
-
export declare function entrances(moves: readonly CamMove[], subjects: number): Map<number, number>;
|
|
66
|
-
/**
|
|
67
|
-
* The labels as markup and GSAP for the shell to put in the scene: a layer of
|
|
68
|
-
* `<g data-subject="K">` groups (so `label_anchor` measures them like any
|
|
69
|
-
* label), each hidden until its entrance, then the plate rises in, the leader
|
|
70
|
-
* draws to the dot. Labels that do not fit their zone are left out (the
|
|
71
|
-
* static check refuses a scene that has one, so this is belt and braces).
|
|
72
|
-
*/
|
|
73
|
-
export declare function calloutLayer(sid: string, labels: readonly Label[], zones: readonly Zone[], moves: readonly CamMove[], theme: Theme, W: number, H: number): {
|
|
74
|
-
markup: string;
|
|
75
|
-
script: string;
|
|
76
|
-
};
|