@jokerized/decksmith 0.8.0 → 0.9.1
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 +333 -4
- package/dist/cli.js +14057 -4749
- package/dist/deck-player-element.js +1 -1
- package/dist/deck-player.js +1 -1
- package/dist/deck-runtime.js +70 -2
- package/dist/index.js +13309 -4178
- package/dist/mcp.js +5131 -765
- package/dist/types/bespoke/art.d.ts +173 -0
- package/dist/types/bespoke/cache.d.ts +69 -0
- package/dist/types/bespoke/callouts.d.ts +76 -0
- package/dist/types/bespoke/contract.d.ts +57 -0
- package/dist/types/bespoke/inspect.d.ts +69 -0
- package/dist/types/bespoke/pipeline.d.ts +207 -0
- package/dist/types/bespoke/probe.d.ts +34 -0
- package/dist/types/bespoke/prompt.d.ts +182 -0
- package/dist/types/bespoke/references.d.ts +73 -0
- package/dist/types/bespoke/repair.d.ts +121 -0
- package/dist/types/bespoke/scene.d.ts +97 -0
- package/dist/types/bespoke/select.d.ts +52 -0
- package/dist/types/bespoke/sheet.d.ts +26 -0
- package/dist/types/bespoke/shots.d.ts +128 -0
- package/dist/types/bespoke/untangle.d.ts +5 -0
- package/dist/types/build/files.d.ts +13 -1
- package/dist/types/deck/motion.d.ts +64 -0
- package/dist/types/deck/playback.d.ts +206 -0
- package/dist/types/deck/repack.d.ts +10 -0
- package/dist/types/deck/runtime.d.ts +96 -1
- package/dist/types/deck/subtitles.d.ts +29 -1
- package/dist/types/emit/archetypes/annotated-figure.d.ts +1 -1
- package/dist/types/emit/archetypes/bar-compare.d.ts +0 -28
- package/dist/types/emit/archetypes/callout.d.ts +0 -5
- package/dist/types/emit/archetypes/claim-figure.d.ts +15 -0
- package/dist/types/emit/archetypes/grid.d.ts +0 -14
- package/dist/types/emit/archetypes/index.d.ts +0 -7
- package/dist/types/emit/archetypes/line-chart.d.ts +0 -8
- package/dist/types/emit/archetypes/pipeline.d.ts +15 -1
- package/dist/types/emit/archetypes/stack.d.ts +1 -1
- package/dist/types/emit/composition.d.ts +83 -3
- package/dist/types/emit/faces.d.ts +22 -0
- package/dist/types/emit/fit.d.ts +127 -0
- package/dist/types/emit/kit.d.ts +121 -2
- package/dist/types/emit/look.d.ts +138 -0
- package/dist/types/emit/motion.d.ts +244 -0
- package/dist/types/emit/svg.d.ts +54 -16
- package/dist/types/emit/theme.d.ts +1 -1
- package/dist/types/emit/themes/index.d.ts +19 -1
- package/dist/types/emit/themes/packs.d.ts +15 -0
- package/dist/types/emit/themes/pick.d.ts +107 -0
- package/dist/types/emit/type.d.ts +111 -0
- package/dist/types/index.d.ts +52 -1
- package/dist/types/plan/codex.d.ts +36 -0
- package/dist/types/plan/direct.d.ts +66 -0
- package/dist/types/prefs.d.ts +25 -2
- package/dist/types/render/capture.d.ts +6 -0
- package/dist/types/render/timing.d.ts +3 -0
- package/dist/types/source/fonts.d.ts +11 -1
- package/dist/types/types.d.ts +109 -0
- package/dist/types/verify/check.d.ts +1 -1
- package/dist/types/verify/fidelity.d.ts +34 -0
- package/dist/types/verify/fill.d.ts +205 -0
- package/dist/types/verify/index.d.ts +14 -0
- package/dist/types/verify/motion.d.ts +33 -0
- package/dist/types/verify/scenes.d.ts +325 -0
- package/package.json +5 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type specs: the typographic half of a v2 style pack.
|
|
3
|
+
*
|
|
4
|
+
* A pack used to be a palette (`themes/`), and every deck set the same Inter at
|
|
5
|
+
* the same 42/64/40 scale, which is half of why the founder's verdict on 219
|
|
6
|
+
* decks was "always the same". A `TypeSpec` is the rest of a look: which face
|
|
7
|
+
* draws the headline and which draws the body, the eyebrow's size, case, weight
|
|
8
|
+
* and tracking, the headline's size, weight, tracking and leading, and how the
|
|
9
|
+
* title slide's big headline grows.
|
|
10
|
+
*
|
|
11
|
+
* EVERY NUMBER HERE IS GEOMETRY, which is why this is not CSS. `chromeHeight`
|
|
12
|
+
* charges the chrome from these numbers and `chromeCss` draws it from the same
|
|
13
|
+
* numbers, so the two cannot disagree. A spec is chosen by the font stack a theme
|
|
14
|
+
* declares (see `faceOf` in svg.ts), so every emitter that already threads a
|
|
15
|
+
* `Face` gets the right measurement without learning that packs exist.
|
|
16
|
+
*
|
|
17
|
+
* `CLASSIC_TYPE` is today's look, number for number. It is never looked up by
|
|
18
|
+
* stack: any stack no spec claims — `ink`, `mono`, `paper`, a user's own theme —
|
|
19
|
+
* measures as classic, which is what keeps v0.8.0's bytes.
|
|
20
|
+
*/
|
|
21
|
+
import type { MeasuredFace } from "./faces.js";
|
|
22
|
+
/** A Latin face a deck can be measured in. `inter` is svg.ts's own table. */
|
|
23
|
+
export type LatinFace = "inter" | MeasuredFace;
|
|
24
|
+
export interface TypeSpec {
|
|
25
|
+
/** Stable id, for messages and the gallery. */
|
|
26
|
+
key: string;
|
|
27
|
+
/** Face of everything but the chrome. Measured with this face's table. */
|
|
28
|
+
body: LatinFace;
|
|
29
|
+
/** Face of the eyebrow, the headline and the title slide's headline. */
|
|
30
|
+
display: LatinFace;
|
|
31
|
+
/**
|
|
32
|
+
* The body stack. It IDENTIFIES the spec (`faceOf` matches its tail), so no two
|
|
33
|
+
* specs may share one; the display family rides in it after Inter, where it
|
|
34
|
+
* never draws, purely so a stack names its pair. See `stackFor`.
|
|
35
|
+
*/
|
|
36
|
+
stack: string;
|
|
37
|
+
/** The chrome's stack: display face, then Inter for any glyph it lacks. */
|
|
38
|
+
displayStack: string;
|
|
39
|
+
/** `color` is a palette role, so one spec suits a light and a dark pack. */
|
|
40
|
+
eyebrow: {
|
|
41
|
+
size: number;
|
|
42
|
+
weight: 400 | 500 | 600 | 700;
|
|
43
|
+
tracking: number;
|
|
44
|
+
upper: boolean;
|
|
45
|
+
lh: number;
|
|
46
|
+
gap: number;
|
|
47
|
+
color: "muted" | "accent";
|
|
48
|
+
};
|
|
49
|
+
headline: {
|
|
50
|
+
size: number;
|
|
51
|
+
weight: 400 | 500 | 600 | 700;
|
|
52
|
+
tracking: number;
|
|
53
|
+
lh: number;
|
|
54
|
+
};
|
|
55
|
+
/** `fitText`'s bounds for the title slide, and how the big headline is set. */
|
|
56
|
+
title: {
|
|
57
|
+
lo: number;
|
|
58
|
+
hi: number;
|
|
59
|
+
weight: 400 | 500 | 600 | 700;
|
|
60
|
+
tracking: number;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** The CSS family a face is declared under — what `vendorFace` writes. */
|
|
64
|
+
export declare function familyOf(face: LatinFace): string;
|
|
65
|
+
/**
|
|
66
|
+
* `"<body>", "Inter", "<display>", system-ui, sans-serif`, with duplicates gone.
|
|
67
|
+
*
|
|
68
|
+
* Inter second, always: every Latin deck vendors it, and `measure-faces.mjs`
|
|
69
|
+
* measured each face with Inter as its fallback, so a glyph the face lacks is
|
|
70
|
+
* drawn by the face the table assumed. The display family after Inter never
|
|
71
|
+
* draws a glyph; it is there so (body, display) pairs give distinct stacks.
|
|
72
|
+
*/
|
|
73
|
+
export declare function stackFor(body: LatinFace, display: LatinFace): string;
|
|
74
|
+
/** Today's chrome, exactly. `title.ts` exported these numbers before specs existed. */
|
|
75
|
+
export declare const CLASSIC_TYPE: TypeSpec;
|
|
76
|
+
/**
|
|
77
|
+
* The v2 type specs. Five pairings, each a different voice rather than a
|
|
78
|
+
* different size of the same one:
|
|
79
|
+
*
|
|
80
|
+
* - `grotesk-inter`: a geometric grotesk headline, tight and large, over Inter.
|
|
81
|
+
* - `plex`: IBM Plex Sans throughout, a little compact — engineering drawings.
|
|
82
|
+
* - `serif-inter`: a text serif headline at display size over Inter.
|
|
83
|
+
* - `serif`: Source Serif 4 throughout, the eyebrow in sentence case — a journal.
|
|
84
|
+
* - `grotesk-plex`: Space Grotesk headline over a Plex body.
|
|
85
|
+
* - `plex-serif`: a Plex headline over a serif body, the inverse of `serif-inter`.
|
|
86
|
+
*
|
|
87
|
+
* HEIGHT. A one-line eyebrow plus a one-line headline costs at most classic's
|
|
88
|
+
* 146px in every spec, so a pack's bigger type comes out of its leading and
|
|
89
|
+
* gaps rather than out of the body's room. Measured why: `serif` at 44/70 cost
|
|
90
|
+
* a real deck a six-bar chart (`costsNothing` in themes/pick.ts now refuses
|
|
91
|
+
* such a pack, but a pack that rarely needs refusing is the better pack).
|
|
92
|
+
*
|
|
93
|
+
* FLOORS. Every eyebrow is at least 40px (invariant 5). Title tracking is never
|
|
94
|
+
* positive: `fitText` measures untracked, so only a tightening is free.
|
|
95
|
+
*/
|
|
96
|
+
export declare const TYPES: Readonly<Record<string, TypeSpec>>;
|
|
97
|
+
/**
|
|
98
|
+
* The spec a theme's stack names, or undefined for classic.
|
|
99
|
+
*
|
|
100
|
+
* Exact, after the one prefix `deckLook` adds: a CJK deck puts its bundled Noto
|
|
101
|
+
* family first and keeps the pack's stack behind it. A stack that merely
|
|
102
|
+
* CONTAINS a spec's families — a user's own theme — is not that spec.
|
|
103
|
+
*/
|
|
104
|
+
export declare function typeForStack(fontStack: string): TypeSpec | undefined;
|
|
105
|
+
/** One line box, the way `title.ts` has always rounded it. */
|
|
106
|
+
export declare function lineBox(size: number, lh: number): number;
|
|
107
|
+
/**
|
|
108
|
+
* A tracking value as the CSS this project has always written: `.14em`,
|
|
109
|
+
* `-.015em`, `0`. Leading zero dropped, so the classic chrome is byte-identical.
|
|
110
|
+
*/
|
|
111
|
+
export declare function em(tracking: number): string;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { BespokeMap } from "./bespoke/scene.js";
|
|
1
2
|
import { type DeckNarration } from "./emit/composition.js";
|
|
2
3
|
import type { Cut } from "./plan/select.js";
|
|
3
|
-
import { type Format, type Source, type Storyboard } from "./types.js";
|
|
4
|
+
import { type Design, type Format, type Source, type Storyboard } from "./types.js";
|
|
4
5
|
/**
|
|
5
6
|
* Markdown (and LaTeX-ish markdown) in, typed `Source` out. The one parser we
|
|
6
7
|
* have; a consumer that already holds structured text can skip it and hand
|
|
@@ -103,10 +104,22 @@ export type { Deck, DeckNarration, DeckOptions } from "./emit/composition.js";
|
|
|
103
104
|
* itself, exported so it can be run against a budget no `Format` states.
|
|
104
105
|
*/
|
|
105
106
|
export { selectBeats } from "./plan/select.js";
|
|
107
|
+
/**
|
|
108
|
+
* `--design v2`: the Director that picks each beat's look, the look vocabulary
|
|
109
|
+
* it picks from, and the sameness numbers it reports. Exported so an eval can
|
|
110
|
+
* measure a corpus of storyboards without building each one.
|
|
111
|
+
*/
|
|
112
|
+
export { direct, summarize } from "./plan/direct.js";
|
|
113
|
+
export type { BeatLook, Direction, LookSummary } from "./plan/direct.js";
|
|
114
|
+
export { candidates, classicLook, LOOK_FILE, signature, VARIANTS } from "./emit/look.js";
|
|
115
|
+
export type { Look, Placement } from "./emit/look.js";
|
|
106
116
|
export type { Cut, Dangling, Dropped, DropRule, SelectionBudget } from "./plan/select.js";
|
|
107
117
|
/** Themes are a named, closed set; a consumer needs to enumerate and validate. */
|
|
108
118
|
export { resolveTheme, THEME_NAMES, THEMES } from "./emit/themes/index.js";
|
|
109
119
|
export type { DeckTheme } from "./emit/themes/index.js";
|
|
120
|
+
export { PACKS } from "./emit/themes/packs.js";
|
|
121
|
+
export { chooseLook, type Design, type LookChoice, pickTheme, rankPacks, } from "./emit/themes/pick.js";
|
|
122
|
+
export { TYPES, type TypeSpec } from "./emit/type.js";
|
|
110
123
|
/**
|
|
111
124
|
* The gates. `verify` is ours plus HyperFrames'; `check` is HyperFrames' alone
|
|
112
125
|
* and needs its CLI. A build that never opens a browser can still run `verify`
|
|
@@ -137,7 +150,25 @@ export type { CheckOptions } from "./verify/check.js";
|
|
|
137
150
|
* verdict. `verify` runs it; nothing else has to.
|
|
138
151
|
*/
|
|
139
152
|
export { gradeOverprint, MIN_OVERLAP, overprints } from "./verify/overprint.js";
|
|
153
|
+
/**
|
|
154
|
+
* Motion variety measured off a built composition: modal-entrance share, seam
|
|
155
|
+
* kinds, ease shares. The M4 exit metrics; see experiments/019-motion.
|
|
156
|
+
*/
|
|
157
|
+
export { motionStats, topTwoEaseShare } from "./verify/motion.js";
|
|
158
|
+
export type { MotionStats } from "./verify/motion.js";
|
|
140
159
|
export type { Overprint, Overprinted, TextRun } from "./verify/overprint.js";
|
|
160
|
+
/**
|
|
161
|
+
* The frame gate on its own, and the fill measure it carries: one browser over
|
|
162
|
+
* a built deck, every stop seeked and captured. `verify` runs it beside `check`;
|
|
163
|
+
* exported so an eval can read `fills` — main-axis fill at each scene's last
|
|
164
|
+
* hold, on a classic deck as on a v2 one — without running the slower half.
|
|
165
|
+
* `fillBand` and `FIT_FILE` are the definition and the manifest both sides use.
|
|
166
|
+
*/
|
|
167
|
+
export { fidelity } from "./verify/fidelity.js";
|
|
168
|
+
export type { FidelityReport } from "./verify/fidelity.js";
|
|
169
|
+
export { fillBand, FIT_FILE } from "./emit/fit.js";
|
|
170
|
+
export type { Fit, FillBand, FitManifest } from "./emit/fit.js";
|
|
171
|
+
export type { FillRow } from "./verify/fill.js";
|
|
141
172
|
/**
|
|
142
173
|
* The determinism gate: render the deck twice and compare. Separate from
|
|
143
174
|
* `verify` because it costs two full renders — minutes, not milliseconds — so
|
|
@@ -190,6 +221,17 @@ export { guardTmpdir } from "./tmpdir.js";
|
|
|
190
221
|
* consumers restate the halves they need.
|
|
191
222
|
*/
|
|
192
223
|
export * from "./types.js";
|
|
224
|
+
/**
|
|
225
|
+
* `--design v2 --bespoke`: generated scenes for a few mechanism beats per deck.
|
|
226
|
+
* The pass, its contract checker, its selection rule and its cache are all
|
|
227
|
+
* exported so a host can run them on its own schedule.
|
|
228
|
+
*/
|
|
229
|
+
export { BESPOKE_FILE, type BespokeEntry, type BespokeMap, bespokeScene } from "./bespoke/scene.js";
|
|
230
|
+
export { checkFragment, type Fragment, instantiate } from "./bespoke/contract.js";
|
|
231
|
+
export { selectBespoke } from "./bespoke/select.js";
|
|
232
|
+
export { cacheKey, SceneCache } from "./bespoke/cache.js";
|
|
233
|
+
export { type BespokeReport, type BespokeResult, bespokePass, type GateFn, } from "./bespoke/pipeline.js";
|
|
234
|
+
export { browserGate } from "./bespoke/probe.js";
|
|
193
235
|
/** Where the emitted deck's parts came from and where they went. */
|
|
194
236
|
export interface BuildResult {
|
|
195
237
|
/** Absolute path of the directory written. */
|
|
@@ -221,8 +263,17 @@ export interface BuildDeckOptions {
|
|
|
221
263
|
onBeatWarning?: (beatId: string, warning: string) => void;
|
|
222
264
|
/** Any name in `THEME_NAMES`. Overrides `storyboard.theme`. */
|
|
223
265
|
theme?: string;
|
|
266
|
+
/** `classic` (default) or `v2`. Overrides `storyboard.design`. See `designSchema`. */
|
|
267
|
+
design?: Design;
|
|
268
|
+
/** v2: the seed the style pack is ranked by. Default `storyboard.sourceId`. */
|
|
269
|
+
packSeed?: string;
|
|
224
270
|
/** Multiplies every duration and hold. 1 leaves the bytes untouched. */
|
|
225
271
|
speed?: number;
|
|
272
|
+
/**
|
|
273
|
+
* `--design v2` only: beats drawn by a generated scene (src/bespoke/), from
|
|
274
|
+
* `bespokePass`. Absent on every other build, which keeps their bytes.
|
|
275
|
+
*/
|
|
276
|
+
bespoke?: BespokeMap;
|
|
226
277
|
/** Default `FORMATS["deck-16x9"]`. */
|
|
227
278
|
format?: Format;
|
|
228
279
|
/** From `narrate`. `dir` is where the mp3s sit relative to `deck.html`. */
|
|
@@ -33,6 +33,14 @@ export interface RunnerArgs {
|
|
|
33
33
|
* `cwd` to fence the writes to.
|
|
34
34
|
*/
|
|
35
35
|
sandbox?: "read-only" | "workspace-write";
|
|
36
|
+
/** Images attached to the prompt (`codex exec -i`). The bespoke critique round sends its frames. */
|
|
37
|
+
images?: string[];
|
|
38
|
+
/** The CLI to run. Absent: `codex` on PATH. */
|
|
39
|
+
bin?: string;
|
|
40
|
+
/** Told the run's token count when the CLI reports one. */
|
|
41
|
+
onUsage?: (tokens: number) => void;
|
|
42
|
+
/** Extra `-c key=value` overrides, in order (see `leanCodexConfig`). */
|
|
43
|
+
config?: readonly string[];
|
|
36
44
|
}
|
|
37
45
|
/** What the planner needs from the outside world: a prompt in, a final message out. */
|
|
38
46
|
export type Runner = (args: RunnerArgs) => Promise<void>;
|
|
@@ -48,5 +56,33 @@ export declare function codexCommand(args: RunnerArgs): {
|
|
|
48
56
|
argv: string[];
|
|
49
57
|
env?: NodeJS.ProcessEnv;
|
|
50
58
|
};
|
|
59
|
+
/**
|
|
60
|
+
* Features that give a `codex exec` run TOOLS. A call that is a pure text
|
|
61
|
+
* transform — a prompt in, a schema-held JSON reply out — needs none of them,
|
|
62
|
+
* and with them the agent spends turns on the account's own setup instead:
|
|
63
|
+
* MEASURED 2026-10-08 on one bespoke draft prompt, the default config ran
|
|
64
|
+
* `cat` on the user's global AGENTS.md and an animation skill before
|
|
65
|
+
* answering — 56,679 input tokens over several turns and 135-488s — where the
|
|
66
|
+
* same prompt with these off was one turn of 18,247 input tokens.
|
|
67
|
+
*/
|
|
68
|
+
export declare const TOOL_FEATURES: readonly ["shell_tool", "unified_exec", "apps", "plugins", "multi_agent", "browser_use", "computer_use", "image_generation", "skill_search", "tool_suggest"];
|
|
69
|
+
/**
|
|
70
|
+
* `-c` overrides for a tool-less, single-turn `codex exec`: every tool feature
|
|
71
|
+
* off, web search off, and every MCP server the account configured disabled by
|
|
72
|
+
* name (the config's own names, read once per process with `codex mcp list`;
|
|
73
|
+
* a name the config does not define cannot be disabled, only invented). If the
|
|
74
|
+
* list cannot be read, the features alone still remove the shell.
|
|
75
|
+
*/
|
|
76
|
+
export declare function leanCodexConfig(bin?: string, list?: (bin: string) => Promise<string>): Promise<string[]>;
|
|
77
|
+
/**
|
|
78
|
+
* `leanCodexConfig` with ONE tool back: the image tool, for the bespoke pass's
|
|
79
|
+
* illustration call (src/bespoke/art.ts). The shell stays off — the agent
|
|
80
|
+
* reports where the tool saved the picture and the caller reads it from there —
|
|
81
|
+
* and so does `view_image`, which would spend the call's tokens looking at a
|
|
82
|
+
* picture the scene call is shown anyway. MEASURED 2026-10-09: 42s and 19k
|
|
83
|
+
* tokens for one picture this way, against 49s and 45k with the agent asked to
|
|
84
|
+
* inspect it.
|
|
85
|
+
*/
|
|
86
|
+
export declare function artCodexConfig(bin?: string, list?: (bin: string) => Promise<string>): Promise<string[]>;
|
|
51
87
|
/** The production `Runner`: `codex exec` on PATH, stdin in, a file out. */
|
|
52
88
|
export declare function runCodex(args: RunnerArgs): Promise<void>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { EmitContext, Scene, Theme } from "../emit/kit.js";
|
|
2
|
+
import { type Look } from "../emit/look.js";
|
|
3
|
+
import type { Archetype, Beat, Design, Format, Source } from "../types.js";
|
|
4
|
+
export interface DirectOptions {
|
|
5
|
+
source: Source;
|
|
6
|
+
format: Format;
|
|
7
|
+
theme: Theme;
|
|
8
|
+
/** Normally `storyboard.sourceId`. */
|
|
9
|
+
seed: string;
|
|
10
|
+
/**
|
|
11
|
+
* The design every candidate is emitted under. `v2` from `emitDeck`, so each
|
|
12
|
+
* look is measured as the fit engine will actually draw it; absent in tests
|
|
13
|
+
* that exercise the Director on its own.
|
|
14
|
+
*/
|
|
15
|
+
design?: Design;
|
|
16
|
+
/** The emitter. `emitScene` unless a test substitutes one that misbehaves. */
|
|
17
|
+
emit?: (beat: Beat, ctx: EmitContext) => Scene;
|
|
18
|
+
}
|
|
19
|
+
/** One beat's decision, as `out/look.json` records it. */
|
|
20
|
+
export interface BeatLook {
|
|
21
|
+
beat: string;
|
|
22
|
+
archetype: Archetype;
|
|
23
|
+
variant: string;
|
|
24
|
+
placement: Look["placement"];
|
|
25
|
+
signature: string;
|
|
26
|
+
/** The chosen look's `Scene.fill`, when its emitter reports one. */
|
|
27
|
+
fill?: number;
|
|
28
|
+
/** Candidates that drew and kept the classic timing. Always ≥ 1. */
|
|
29
|
+
viable: number;
|
|
30
|
+
/** Candidates that were refused, and why — the emitter's own sentence. */
|
|
31
|
+
refused: {
|
|
32
|
+
signature: string;
|
|
33
|
+
reason: string;
|
|
34
|
+
}[];
|
|
35
|
+
}
|
|
36
|
+
export interface Direction {
|
|
37
|
+
/** One per beat, in order: what `EmitContext.look` is set to. */
|
|
38
|
+
looks: Look[];
|
|
39
|
+
beats: BeatLook[];
|
|
40
|
+
summary: LookSummary;
|
|
41
|
+
}
|
|
42
|
+
export interface LookSummary {
|
|
43
|
+
beats: number;
|
|
44
|
+
distinct: number;
|
|
45
|
+
/** Share of beats whose chrome sits on top of the slide (title excluded from the numerator). */
|
|
46
|
+
modalChrome: number;
|
|
47
|
+
/** Adjacent pairs with the same signature. */
|
|
48
|
+
adjacentRepeats: number;
|
|
49
|
+
/** The four most-used signatures' share of beats. */
|
|
50
|
+
top4: number;
|
|
51
|
+
}
|
|
52
|
+
export declare function direct(beats: readonly Beat[], opts: DirectOptions): Direction;
|
|
53
|
+
/**
|
|
54
|
+
* The least share of the classic look's figure area another look may draw the
|
|
55
|
+
* figure at. The review (2026-10-08) measured v2's rail and foot looks shrinking
|
|
56
|
+
* the paper's own figure to 43-61% of its classic area (ja s4, ko s6, en s5) to
|
|
57
|
+
* make room for a headline: fill went up because white plate and bigger text
|
|
58
|
+
* count as ink, and the most informative thing on the slide got smaller. A
|
|
59
|
+
* look that keeps 80% or more is still a different slide; one below it is not
|
|
60
|
+
* worth the variety.
|
|
61
|
+
*/
|
|
62
|
+
export declare const FIGURE_FLOOR = 0.8;
|
|
63
|
+
/** The sameness numbers for one deck. Also used by the corpus measurement. */
|
|
64
|
+
export declare function summarize(beats: readonly Pick<BeatLook, "archetype" | "signature" | "placement">[]): LookSummary;
|
|
65
|
+
/** 32-bit FNV-1a. Deterministic, dependency-free, and enough to spread ties. */
|
|
66
|
+
export declare function fnv1a(s: string): number;
|
package/dist/types/prefs.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { z } from "zod";
|
|
2
|
-
import { prefsSchema, type Source } from "./types.js";
|
|
2
|
+
import { type Design, prefsSchema, type Source } from "./types.js";
|
|
3
3
|
export type Prefs = z.infer<typeof prefsSchema>;
|
|
4
4
|
/**
|
|
5
5
|
* A partial Prefs. `narration` and `images` are the two nested objects, so they
|
|
@@ -7,9 +7,10 @@ export type Prefs = z.infer<typeof prefsSchema>;
|
|
|
7
7
|
* wipe a `rate` the config file set, and `--image-style` must not wipe its
|
|
8
8
|
* `provider`.
|
|
9
9
|
*/
|
|
10
|
-
export type PrefsPatch = Partial<Omit<Prefs, "narration" | "images">> & {
|
|
10
|
+
export type PrefsPatch = Partial<Omit<Prefs, "narration" | "images" | "bespoke">> & {
|
|
11
11
|
narration?: Partial<Prefs["narration"]>;
|
|
12
12
|
images?: Partial<Prefs["images"]>;
|
|
13
|
+
bespoke?: Partial<NonNullable<Prefs["bespoke"]>>;
|
|
13
14
|
};
|
|
14
15
|
export declare const CONFIG_FILE = "decksmith.config.json";
|
|
15
16
|
/**
|
|
@@ -33,6 +34,16 @@ export declare function loadPrefs(overrides?: PrefsPatch, cwd?: string, source?:
|
|
|
33
34
|
* schema, so there is exactly one place that decides what a legal tone is.
|
|
34
35
|
*/
|
|
35
36
|
export declare function prefsFromFlags(flags: PrefFlags): PrefsPatch;
|
|
37
|
+
/**
|
|
38
|
+
* The design a build uses: a `--design` flag or a config file, else what the
|
|
39
|
+
* storyboard was planned under, else `classic`.
|
|
40
|
+
*
|
|
41
|
+
* NOT `stated()`, which treats a value at its default as unsaid. `design` has
|
|
42
|
+
* no default — it is optional in the schema — so an explicit `classic` is
|
|
43
|
+
* distinguishable from silence, and it IS the rollback: it has to win over a
|
|
44
|
+
* storyboard planned under v2.
|
|
45
|
+
*/
|
|
46
|
+
export declare function designFor(prefs: Pick<Prefs, "design">, recorded?: Design): Design;
|
|
36
47
|
/** The flag surface the CLI exposes. Every one optional: absent means unstated. */
|
|
37
48
|
export interface PrefFlags {
|
|
38
49
|
slides?: string | number;
|
|
@@ -42,6 +53,10 @@ export interface PrefFlags {
|
|
|
42
53
|
genre?: string;
|
|
43
54
|
duration?: string | number;
|
|
44
55
|
theme?: string;
|
|
56
|
+
/** `--design classic | v2`. */
|
|
57
|
+
design?: string;
|
|
58
|
+
/** `--pack-seed`: what v2 hashes to pick a pack. */
|
|
59
|
+
packSeed?: string;
|
|
45
60
|
speed?: string | number;
|
|
46
61
|
narrate?: boolean;
|
|
47
62
|
voice?: string;
|
|
@@ -56,4 +71,12 @@ export interface PrefFlags {
|
|
|
56
71
|
imageModel?: string;
|
|
57
72
|
imageStyle?: string;
|
|
58
73
|
imageMax?: string | number;
|
|
74
|
+
/** `--bespoke`: generated scenes for a few mechanism beats (v2 only). */
|
|
75
|
+
bespoke?: boolean;
|
|
76
|
+
bespokeCalls?: string | number;
|
|
77
|
+
bespokeSeconds?: string | number;
|
|
78
|
+
bespokeModel?: string;
|
|
79
|
+
bespokeCli?: string;
|
|
80
|
+
bespokeCache?: string;
|
|
81
|
+
bespokeArt?: string | number;
|
|
59
82
|
}
|
|
@@ -107,6 +107,12 @@ export interface DeckPage {
|
|
|
107
107
|
}
|
|
108
108
|
export interface OpenOptions {
|
|
109
109
|
timeoutMs?: number;
|
|
110
|
+
/**
|
|
111
|
+
* Collect what the page did that a deck must not: script errors, console
|
|
112
|
+
* errors (a CSP refusal is one), and any request or navigation that is not
|
|
113
|
+
* a local file. Registered before the page loads, so load-time ones count.
|
|
114
|
+
*/
|
|
115
|
+
watch?: string[];
|
|
110
116
|
}
|
|
111
117
|
/**
|
|
112
118
|
* Open `dir`'s deck in the renderer's own browser, ready to seek.
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
* rendering a deck whose audio is aimed at the wrong frames.
|
|
49
49
|
*/
|
|
50
50
|
import type { z } from "zod";
|
|
51
|
+
import type { BespokeMap } from "../bespoke/scene.js";
|
|
51
52
|
import { type Cue } from "../deck/subtitles.js";
|
|
52
53
|
import { type DeckNarration } from "../emit/composition.js";
|
|
53
54
|
import type { Beat, Format, Source, Storyboard, segmentSchema } from "../types.js";
|
|
@@ -218,6 +219,8 @@ export interface TimingInput {
|
|
|
218
219
|
beats?: readonly Beat[];
|
|
219
220
|
narration?: DeckNarration;
|
|
220
221
|
theme?: string;
|
|
222
|
+
/** `DeckOptions.bespoke`, exactly as `emitDeck` was given it. */
|
|
223
|
+
bespoke?: BespokeMap;
|
|
221
224
|
}
|
|
222
225
|
/**
|
|
223
226
|
* One pass over the built deck, producing the manifest `render` consumes.
|
|
@@ -6,10 +6,20 @@ export interface FontBundle {
|
|
|
6
6
|
/** The woff2 basenames written into `dir`, beside `fonts.css`. */
|
|
7
7
|
files: string[];
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* The serif companion to `familyFor`: what a v2 pack whose type spec sets a role
|
|
11
|
+
* in a serif draws that role's CJK in. Without it every CJK deck set its
|
|
12
|
+
* headlines in Noto Sans whatever the pack said, so the font change that makes
|
|
13
|
+
* a serif pack a serif pack disappeared for three languages out of four
|
|
14
|
+
* (review, 2026-10-08).
|
|
15
|
+
*/
|
|
16
|
+
export declare function serifFamilyFor(lang: string): string | null;
|
|
9
17
|
/** The CJK family a language needs subset, or null: the deck ships Inter (`vendorInter`). */
|
|
10
18
|
export declare function familyFor(lang: string): string | null;
|
|
11
19
|
/**
|
|
12
20
|
* Write `dir/fonts.css` plus its woff2 for `lang`, covering `glyphs`. Returns
|
|
13
21
|
* null for languages the renderer already resolves, which needs no bundle.
|
|
14
22
|
*/
|
|
15
|
-
export declare function bundleFont(lang: string, glyphs: string, dir: string
|
|
23
|
+
export declare function bundleFont(lang: string, glyphs: string, dir: string, opts?: {
|
|
24
|
+
serif?: boolean;
|
|
25
|
+
}): Promise<FontBundle | null>;
|