@onmark/cli 0.5.0 → 0.6.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.
package/README.md CHANGED
@@ -84,10 +84,71 @@ Validate or inspect the same production plan without launching Chromium:
84
84
  ```bash
85
85
  onmark check film.html
86
86
  onmark inspect film.html --json
87
+ onmark snapshot film.html --frame 42
88
+ onmark review film.html
87
89
  onmark doctor
88
90
  onmark benchmark film.html --runs 3 --json
89
91
  ```
90
92
 
93
+ `snapshot` writes a lossless production frame to
94
+ `renders/film-frame-42.png`. It uses the same render region, browser/native
95
+ path, and verified pixel contract as the complete film; it is not a preview
96
+ approximation.
97
+
98
+ `review` reuses the production region cache and writes lossless checkpoints,
99
+ objective empty-or-clipped semantic-layout findings, `manifest.json`, and a
100
+ static contact sheet under a content-addressed `reviews/film-*/` directory.
101
+ Pass `--against <prior-manifest>` to compare exact region identities after an
102
+ edit.
103
+
104
+ Declare typed presentation fields when one film needs many data variants:
105
+
106
+ ```html
107
+ <om-film>
108
+ <om-fields>
109
+ <om-field name="headline" type="text" default="Summer edit"></om-field>
110
+ <om-field name="accent" type="color" default="#ff4d36"></om-field>
111
+ </om-fields>
112
+ <om-scene>
113
+ <om-shot duration="3s">
114
+ <om-title data-om-text="headline">Summer edit</om-title>
115
+ <div data-om-css="accent" style="--accent:#ff4d36"></div>
116
+ </om-shot>
117
+ </om-scene>
118
+ </om-film>
119
+ ```
120
+
121
+ Override only the values you need:
122
+
123
+ ```json
124
+ { "headline": "Autumn edit", "accent": "#c56cff" }
125
+ ```
126
+
127
+ ```bash
128
+ onmark check film.html --variant autumn.json
129
+ onmark render film.html --variant autumn.json --output autumn.mp4
130
+ ```
131
+
132
+ For a bounded campaign, `onmark batch batch.json` resolves the screenplay,
133
+ freezes its assets, and bundles its presentation once. Paths are relative to
134
+ the manifest:
135
+
136
+ ```json
137
+ {
138
+ "version": 1,
139
+ "screenplay": "film.html",
140
+ "renders": [
141
+ { "variant": "variants/summer.json", "output": "renders/summer.mp4" },
142
+ { "variant": "variants/autumn.json", "output": "renders/autumn.mp4" }
143
+ ]
144
+ }
145
+ ```
146
+
147
+ Unchanged render regions are reused across items and later managed-browser
148
+ invocations; each run reports aggregate region and frame reuse. Variant values
149
+ cannot change timing, media sources, dimensions, or output profiles. Caption
150
+ tracks declared by the screenplay are shared by the complete batch.
151
+
91
152
  Use the default opaque H.264/AAC MP4 for delivery, or select the
92
153
  alpha-preserving ProRes 4444/PCM MOV profile by filename:
93
154
 
@@ -95,7 +156,13 @@ alpha-preserving ProRes 4444/PCM MOV profile by filename:
95
156
  onmark render film.html --output film.mov
96
157
  ```
97
158
 
98
- Resolution, exact rational frame rates, and imported subtitles stay explicit:
159
+ Declare one or more external caption tracks in the film. Onmark burns every
160
+ declared track by default; `--captions` selects an ordered subset:
161
+
162
+ ```html
163
+ <om-captions id="en" src="captions/en.vtt" lang="en"></om-captions>
164
+ <om-captions id="zh" src="captions/zh.srt" lang="zh-CN"></om-captions>
165
+ ```
99
166
 
100
167
  ```bash
101
168
  onmark render film.html \
@@ -103,7 +170,7 @@ onmark render film.html \
103
170
  --width 1920 \
104
171
  --height 1080 \
105
172
  --fps 30000/1001 \
106
- --subtitle captions.vtt
173
+ --captions zh
107
174
  ```
108
175
 
109
176
  Install the optional agent skill for a product-owned create/check/inspect/render
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "packageName": "@onmark/cli",
4
- "version": "0.5.0",
5
- "sourceRevision": "770428f38a704d4f08eb117e64d52fc37a164931",
4
+ "version": "0.6.0",
5
+ "sourceRevision": "ae455abdd274a90da46a487dec0e7f41bb4bc44c",
6
6
  "files": [
7
7
  {
8
8
  "path": "LICENSE",
@@ -11,13 +11,13 @@
11
11
  },
12
12
  {
13
13
  "path": "README.md",
14
- "bytes": 6341,
15
- "sha256": "a747c29224c33dd8431506467134f1b86e54bad92720c0bf3b751f0cba7d6d5d"
14
+ "bytes": 8543,
15
+ "sha256": "5c4a3330e165b8d8dbe945b098e246ebbbd8935d9a2b18cb0e75db2ff83f5ea6"
16
16
  },
17
17
  {
18
18
  "path": "package.json",
19
19
  "bytes": 1406,
20
- "sha256": "91721649e92466ab8a096460c959146c113b6f3d18a9f8f2617b3b2af6af023d"
20
+ "sha256": "d242147758574422f027a250f34ffc51e214360ad751807e58106ac6cc45c201"
21
21
  },
22
22
  {
23
23
  "path": "packages/authoring/dist/src/frame-motion.d.ts",
@@ -66,8 +66,8 @@
66
66
  },
67
67
  {
68
68
  "path": "packages/authoring/dist/src/presentation.js",
69
- "bytes": 14927,
70
- "sha256": "0a47ca310dce4c37db3a241cb63301d504aa8d767063a395aa520d519e14a874"
69
+ "bytes": 15437,
70
+ "sha256": "129841bd4530ed1ac039f84241d2c451963e66588f96a242a95e12f619f436e9"
71
71
  },
72
72
  {
73
73
  "path": "packages/authoring/dist/src/resource.d.ts",
@@ -99,6 +99,16 @@
99
99
  "bytes": 78,
100
100
  "sha256": "d4010927313e03e84d25e63d9359f90d7af2c676ee5ad4f253928ac983b2e903"
101
101
  },
102
+ {
103
+ "path": "packages/authoring/dist/src/variant.d.ts",
104
+ "bytes": 249,
105
+ "sha256": "a5c9b6a1c19a0be73141eca24078058ff864b99e280a33cb2a6170410ff9ac1d"
106
+ },
107
+ {
108
+ "path": "packages/authoring/dist/src/variant.js",
109
+ "bytes": 2683,
110
+ "sha256": "e730a944fd0e7b77116363bbe6db2b03516027c48ca31085cfece97824d19ac0"
111
+ },
102
112
  {
103
113
  "path": "packages/bundler/dist/src/authored_html.d.ts",
104
114
  "bytes": 2278,
@@ -106,8 +116,8 @@
106
116
  },
107
117
  {
108
118
  "path": "packages/bundler/dist/src/authored_html.js",
109
- "bytes": 17153,
110
- "sha256": "841d2fc962b65d7f5cfafd4805eac28990d76f15cf298173ca1d7ac424a2480e"
119
+ "bytes": 17225,
120
+ "sha256": "394f4b2be4d173f08eb04bb72317745057e22bde09d22acccd6a344414671e15"
111
121
  },
112
122
  {
113
123
  "path": "packages/bundler/dist/src/bundle_projection.d.ts",
@@ -291,8 +301,8 @@
291
301
  },
292
302
  {
293
303
  "path": "packages/motion-gsap/dist/src/index.js",
294
- "bytes": 5806,
295
- "sha256": "4041d9b2bd3736d4c72c21ed298d65258f8e5703d3e54986f8706553c5c2f354"
304
+ "bytes": 6027,
305
+ "sha256": "3017d8fc5033b545c4f0d796e982e751b8943e7b35a6631ae25367615b7992a3"
296
306
  },
297
307
  {
298
308
  "path": "packages/runtime/dist/src/clock.d.ts",
@@ -306,8 +316,8 @@
306
316
  },
307
317
  {
308
318
  "path": "packages/runtime/dist/src/generated/browser-request.d.ts",
309
- "bytes": 5010,
310
- "sha256": "9bd56a97a68aa2a48c4ef94c104a77e18d4b6b95e4444d76fb461468f54640ce"
319
+ "bytes": 5933,
320
+ "sha256": "d9b4619c90d1f8e636a3cdab07fed5d0b068cf890d6954e77aad88d70c353130"
311
321
  },
312
322
  {
313
323
  "path": "packages/runtime/dist/src/generated/browser-request.js",
@@ -316,8 +326,8 @@
316
326
  },
317
327
  {
318
328
  "path": "packages/runtime/dist/src/generated/browser-response.d.ts",
319
- "bytes": 2540,
320
- "sha256": "f0345c35a41f7f09961fa7df181a30d991116769e9ecb28dd0627e76a0a20034"
329
+ "bytes": 3086,
330
+ "sha256": "0d3004a8bb5216a9c711546d9e5dc36874d7c85c509d3ed5c4ddfbc013701db9"
321
331
  },
322
332
  {
323
333
  "path": "packages/runtime/dist/src/generated/browser-response.js",
@@ -346,23 +356,23 @@
346
356
  },
347
357
  {
348
358
  "path": "packages/runtime/dist/src/generated/runtime-contract.d.ts",
349
- "bytes": 609,
350
- "sha256": "ba1fac50be3c9494935fbc5d31c1e3037934e2d6dd1ca3adfe3d692575f68d27"
359
+ "bytes": 770,
360
+ "sha256": "6023fe29092e8a9458cdf4714ccb9df4b792ec85b4bd392972d3201b8d98ae49"
351
361
  },
352
362
  {
353
363
  "path": "packages/runtime/dist/src/generated/runtime-contract.js",
354
- "bytes": 604,
355
- "sha256": "3cc8116cc4d37c92643c672ef313bed7aa32ac466aeb8724e9563548a6d981ce"
364
+ "bytes": 744,
365
+ "sha256": "3ddcfc0631b073e9810d0ff4e085bc589b0b6cb776d89fa93ffb748b65b26ac7"
356
366
  },
357
367
  {
358
368
  "path": "packages/runtime/dist/src/generated/validators.d.ts",
359
369
  "bytes": 594,
360
- "sha256": "def2eb2646ee3084b86e3871fae68581ab51f0a1af917e7cdf8913567d9d4667"
370
+ "sha256": "14f1af4a54550f15be7c45f0c4a3b6ad58482f5700690904093319343ac2d887"
361
371
  },
362
372
  {
363
373
  "path": "packages/runtime/dist/src/generated/validators.js",
364
- "bytes": 274203,
365
- "sha256": "8e1309412309eeda69cd27a8b3a88935cdb8a8b61d0e6776a0a4ac472039e930"
374
+ "bytes": 327066,
375
+ "sha256": "97176a72110caa13189e9bc89763f5c44846f22c66f7cc0ddfd75e879f5d7d00"
366
376
  },
367
377
  {
368
378
  "path": "packages/runtime/dist/src/host.d.ts",
@@ -376,13 +386,13 @@
376
386
  },
377
387
  {
378
388
  "path": "packages/runtime/dist/src/index.d.ts",
379
- "bytes": 1895,
380
- "sha256": "5faebc8e4726ec5261e174a55811536991ae0cf42135e0f43e5fb67e9df77eba"
389
+ "bytes": 1989,
390
+ "sha256": "5046728fde0dc312339a2f2f54031e965054949fb3dc6a0840cf9508ecfacdeb"
381
391
  },
382
392
  {
383
393
  "path": "packages/runtime/dist/src/index.js",
384
- "bytes": 1152,
385
- "sha256": "10bb00b68b1aba0106334606c72a68227c2dbc9f997aaf99afd14c0502b18872"
394
+ "bytes": 1181,
395
+ "sha256": "df2e6dc7116577d81c5adb1be5b9980a97897b29ebf401b43fdc237416c023fe"
386
396
  },
387
397
  {
388
398
  "path": "packages/runtime/dist/src/media.d.ts",
@@ -396,13 +406,13 @@
396
406
  },
397
407
  {
398
408
  "path": "packages/runtime/dist/src/presentation.d.ts",
399
- "bytes": 3943,
400
- "sha256": "9f2abf95bc614f0a41a42c52f2563574afa24b126c1b266983cc72e1a0f83ee1"
409
+ "bytes": 3983,
410
+ "sha256": "941914faf7cb05a1221c76b3d1f05fa977ddce2920936fa40920aa4a4f57571a"
401
411
  },
402
412
  {
403
413
  "path": "packages/runtime/dist/src/presentation.js",
404
- "bytes": 17755,
405
- "sha256": "de785ba109f6cf446d211cb05387f5d42d406a61f9cb9c5e38925fbd9c4bccbe"
414
+ "bytes": 20436,
415
+ "sha256": "2a860f928b718ff7f6b2df74b8f3e024201d4d7b074667a115d8f4445829976f"
406
416
  },
407
417
  {
408
418
  "path": "packages/runtime/dist/src/resource.d.ts",
@@ -416,18 +426,18 @@
416
426
  },
417
427
  {
418
428
  "path": "packages/runtime/dist/src/session.d.ts",
419
- "bytes": 2298,
420
- "sha256": "28b12b59ac2e042ae6e571f861b5b70dec0779a08b6ad1cf8897b262bdbc51db"
429
+ "bytes": 2352,
430
+ "sha256": "c0b98072a15c5d3c5c8089454a0dd727fc40d08f92d5ce4e797c6252af35afb6"
421
431
  },
422
432
  {
423
433
  "path": "packages/runtime/dist/src/session.js",
424
- "bytes": 20533,
425
- "sha256": "6383f8ff8fda51e0c51b5c20d736c45bf9d36cc76dfb41bb87588ff0b72654b6"
434
+ "bytes": 25351,
435
+ "sha256": "139ad87e132e22a45c16406520dbe8ce3a0c394c2e52dbe955b993f9d3012dee"
426
436
  },
427
437
  {
428
438
  "path": "packages/runtime/dist/src/types.d.ts",
429
- "bytes": 753,
430
- "sha256": "20d1e1c41b5ed7ac43341b928a6ba331dd73fcf2fea2fe8534f0c523233358ff"
439
+ "bytes": 818,
440
+ "sha256": "0452c79469d5146621101c9b337403ac606868fa04d35558684b6772a27e1123"
431
441
  },
432
442
  {
433
443
  "path": "packages/runtime/dist/src/types.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onmark/cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Screenplay-first deterministic browser video compiler",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -45,8 +45,8 @@
45
45
  "yauzl": "3.4.0"
46
46
  },
47
47
  "optionalDependencies": {
48
- "@onmark/cli-darwin-arm64": "0.5.0",
49
- "@onmark/cli-linux-x64": "0.5.0",
50
- "@onmark/cli-win32-x64": "0.5.0"
48
+ "@onmark/cli-darwin-arm64": "0.6.0",
49
+ "@onmark/cli-linux-x64": "0.6.0",
50
+ "@onmark/cli-win32-x64": "0.6.0"
51
51
  }
52
52
  }
@@ -2,6 +2,7 @@
2
2
  // Rust owns structure and timing; this module owns browser node lifetimes.
3
3
  import { EMPTY_PRESENTATION_EXTENSIONS, ownExtension, ownExtensions, } from "./motion.js";
4
4
  import { authoredImageResources } from "./resource.js";
5
+ import { applyVariantFields } from "./variant.js";
5
6
  const ELEMENTS = Object.freeze({
6
7
  callToAction: "om-cta",
7
8
  caption: "om-caption",
@@ -16,13 +17,14 @@ const ELEMENTS = Object.freeze({
16
17
  // plan. Authored display rules cannot make those unbound nodes visible.
17
18
  const VISIBILITY_RULE = [
18
19
  "[data-om-node][hidden],",
20
+ "[data-om-show][hidden],",
19
21
  "om-film > om-scene:not([data-om-node]),",
20
22
  "om-scene > om-shot:not([data-om-node]),",
21
23
  "om-scene > om-transition,",
22
24
  "om-shot > :is(video, om-title, om-cta):not([data-om-node]) {",
23
25
  " display: none !important;",
24
26
  "}",
25
- "om-cues, om-cue, om-music, om-sfx, om-vo {",
27
+ "om-cues, om-cue, om-captions, om-music, om-sfx, om-vo {",
26
28
  " display: none !important;",
27
29
  "}",
28
30
  ].join("\n");
@@ -38,6 +40,7 @@ export function createDomPresentationBindings(options) {
38
40
  bindVideo: document.bindVideo.bind(document),
39
41
  bindOverlay: document.bindOverlay.bind(document),
40
42
  async bindExtensions(plan) {
43
+ document.applyVariantFields(plan);
41
44
  // Static authored images exist before extensions may add their own
42
45
  // explicitly owned resources. Snapshot them once to avoid two owners for
43
46
  // a motion-created image.
@@ -142,8 +145,17 @@ class AuthoredDocument {
142
145
  imageElements() {
143
146
  return Array.from(this.#document.images).filter((element) => element.hasAttribute("src"));
144
147
  }
148
+ applyVariantFields(plan) {
149
+ applyVariantFields(this.#document, plan.variantFields);
150
+ }
145
151
  #bindCaption(placement) {
152
+ const track = placement.captionTrack;
153
+ if (track === undefined || track === null) {
154
+ throw new Error("caption placement requires track metadata");
155
+ }
146
156
  const element = this.#document.createElement(ELEMENTS.caption);
157
+ element.dataset["track"] = track.id;
158
+ element.lang = track.language;
147
159
  element.textContent = placement.text;
148
160
  this.#nodeIndex().film.append(element);
149
161
  const bound = bindElement(element, placement.node, () => element.remove());
@@ -0,0 +1,3 @@
1
+ import type { RuntimePlan } from "../../../runtime/dist/src/index.js";
2
+ /** Applies only the typed fields projected into one Browser Plan. */
3
+ export declare function applyVariantFields(document: Document, fields: RuntimePlan["variantFields"]): void;
@@ -0,0 +1,76 @@
1
+ // Literal DOM sinks for Rust-owned canonical presentation values.
2
+ // Missing region fields deliberately retain their truthful authored fallback.
3
+ const BINDING_SELECTOR = "[data-om-text], [data-om-css], [data-om-show]";
4
+ const MAX_VARIANT_BINDING_ELEMENTS = 65_536;
5
+ /** Applies only the typed fields projected into one Browser Plan. */
6
+ export function applyVariantFields(document, fields) {
7
+ if (fields.length === 0) {
8
+ return;
9
+ }
10
+ const values = new Map(fields.map((field) => [field.name, field.value]));
11
+ const applied = new Set();
12
+ const elements = document.querySelectorAll(BINDING_SELECTOR);
13
+ if (elements.length > MAX_VARIANT_BINDING_ELEMENTS) {
14
+ throw new Error("authored HTML variant binding count exceeds its limit");
15
+ }
16
+ for (const element of elements) {
17
+ applyTextBinding(element, values, applied);
18
+ applyCssBindings(element, values, applied);
19
+ applyShowBinding(element, values, applied);
20
+ }
21
+ for (const field of fields) {
22
+ if (!applied.has(field.name)) {
23
+ throw new Error(`authored HTML has no projected binding for variant field "${field.name}"`);
24
+ }
25
+ }
26
+ }
27
+ function applyTextBinding(element, values, applied) {
28
+ const name = element.getAttribute("data-om-text");
29
+ if (name === null) {
30
+ return;
31
+ }
32
+ const value = values.get(name);
33
+ if (value === undefined) {
34
+ return;
35
+ }
36
+ if (value.kind !== "text") {
37
+ throw incompatibleBinding(name, "data-om-text");
38
+ }
39
+ element.textContent = value.value;
40
+ applied.add(name);
41
+ }
42
+ function applyCssBindings(element, values, applied) {
43
+ const attribute = element.getAttribute("data-om-css");
44
+ if (attribute === null) {
45
+ return;
46
+ }
47
+ for (const name of attribute.split(/[\t\n\f\r ]+/u)) {
48
+ const value = values.get(name);
49
+ if (value === undefined) {
50
+ continue;
51
+ }
52
+ if (value.kind !== "color" && value.kind !== "integer") {
53
+ throw incompatibleBinding(name, "data-om-css");
54
+ }
55
+ element.style.setProperty(`--${name}`, String(value.value));
56
+ applied.add(name);
57
+ }
58
+ }
59
+ function applyShowBinding(element, values, applied) {
60
+ const name = element.getAttribute("data-om-show");
61
+ if (name === null) {
62
+ return;
63
+ }
64
+ const value = values.get(name);
65
+ if (value === undefined) {
66
+ return;
67
+ }
68
+ if (value.kind !== "boolean") {
69
+ throw incompatibleBinding(name, "data-om-show");
70
+ }
71
+ element.hidden = !value.value;
72
+ applied.add(name);
73
+ }
74
+ function incompatibleBinding(name, attribute) {
75
+ return new Error(`variant field "${name}" is incompatible with authored ${attribute}`);
76
+ }
@@ -402,7 +402,9 @@ function isCompilerOnlyElement(tagName) {
402
402
  // This closed list mirrors the language boundary, not HTML vocabulary.
403
403
  // New spellings require the Rust compiler, specification, and identity
404
404
  // conformance to change together before they may disappear from the browser.
405
- return (tagName === "om-cues" ||
405
+ return (tagName === "om-fields" ||
406
+ tagName === "om-cues" ||
407
+ tagName === "om-captions" ||
406
408
  tagName === "om-music" ||
407
409
  tagName === "om-sfx" ||
408
410
  tagName === "om-vo");
@@ -1,6 +1,7 @@
1
1
  // Exact-frame GSAP integration over Onmark's vendor-neutral extension contract.
2
2
  // Authors describe local motion; this adapter owns paused playheads and cleanup.
3
3
  import { gsap } from "gsap";
4
+ const GSAP_TIME_PRECISION_SECONDS = 1e-7;
4
5
  /** Creates exact-frame GSAP effects without exposing runtime lifecycle code. */
5
6
  export function gsapMotion(definition) {
6
7
  const rules = ownRules(definition);
@@ -142,7 +143,9 @@ function transitionContext(context, target) {
142
143
  });
143
144
  }
144
145
  function requireLocalTimeline(timeline, durationSeconds, label) {
145
- if (timeline.duration() <= durationSeconds) {
146
+ // GSAP rounds animation boundaries to seven decimal places. Admit that
147
+ // representation error while retaining the compiler-owned interval.
148
+ if (timeline.duration() - durationSeconds <= GSAP_TIME_PRECISION_SECONDS) {
146
149
  return;
147
150
  }
148
151
  throw new RangeError(`${label} motion exceeds its compiler-owned interval of ${durationSeconds} seconds`);
@@ -46,6 +46,34 @@ export type BrowserNodeId = number;
46
46
  * Closed overlay roles understood by the browser presentation.
47
47
  */
48
48
  export type BrowserOverlayKind = "title" | "callToAction" | "caption";
49
+ /**
50
+ * Closed wire values accepted by the browser's literal binding layer.
51
+ */
52
+ export type BrowserVariantValue = {
53
+ kind: "text";
54
+ /**
55
+ * Exact UTF-8 value.
56
+ */
57
+ value: string;
58
+ } | {
59
+ kind: "integer";
60
+ /**
61
+ * Exact integer value.
62
+ */
63
+ value: number;
64
+ } | {
65
+ kind: "boolean";
66
+ /**
67
+ * Exact boolean value.
68
+ */
69
+ value: boolean;
70
+ } | {
71
+ kind: "color";
72
+ /**
73
+ * Canonical color value.
74
+ */
75
+ value: string;
76
+ };
49
77
  /**
50
78
  * Exact source-frame timing projected into the browser runtime.
51
79
  */
@@ -70,7 +98,7 @@ export type RequestId = number;
70
98
  /**
71
99
  * Version of the native-to-browser message contract.
72
100
  */
73
- export type ProtocolVersion = 5;
101
+ export type ProtocolVersion = 9;
74
102
  /**
75
103
  * One versioned command sent from the native executor to the browser.
76
104
  */
@@ -100,11 +128,15 @@ export interface BrowserPlan {
100
128
  */
101
129
  shots: BrowserShot[];
102
130
  timeline: WireInterval;
103
- timelineVersion: 3;
131
+ timelineVersion: 7;
104
132
  /**
105
133
  * @maxItems 10000
106
134
  */
107
135
  transitions: BrowserTransition[];
136
+ /**
137
+ * @maxItems 256
138
+ */
139
+ variantFields: BrowserVariantField[];
108
140
  /**
109
141
  * @maxItems 10000
110
142
  */
@@ -135,12 +167,20 @@ export interface WireFrameRate {
135
167
  * One solved overlay placement consumed by the browser presentation.
136
168
  */
137
169
  export interface BrowserOverlay {
170
+ captionTrack?: BrowserCaptionTrack | null;
138
171
  interval: WireInterval;
139
172
  kind: BrowserOverlayKind;
140
173
  node: BrowserNode;
141
174
  shotId?: BrowserNodeId | null;
142
175
  text: string;
143
176
  }
177
+ /**
178
+ * Stable caption-track metadata projected into browser presentation.
179
+ */
180
+ export interface BrowserCaptionTrack {
181
+ id: string;
182
+ language: string;
183
+ }
144
184
  /**
145
185
  * One scene container intersecting this unit, with its complete Timeline interval.
146
186
  */
@@ -165,6 +205,13 @@ export interface BrowserTransition {
165
205
  node: BrowserNode;
166
206
  outgoingShotId: BrowserNodeId;
167
207
  }
208
+ /**
209
+ * One canonical typed presentation input carried by this render region.
210
+ */
211
+ export interface BrowserVariantField {
212
+ name: string;
213
+ value: BrowserVariantValue;
214
+ }
168
215
  /**
169
216
  * One primary video placement consumed by the browser presentation adapter.
170
217
  */
@@ -22,6 +22,7 @@ export type BrowserEvent = {
22
22
  */
23
23
  frame: number;
24
24
  type: "frameReady";
25
+ visualFindings: BrowserVisualFindings;
25
26
  } | {
26
27
  /**
27
28
  * Stable machine-readable failure category.
@@ -60,6 +61,16 @@ export type BrowserObjectFit = "fill" | "contain" | "cover";
60
61
  * @maxItems 16
61
62
  */
62
63
  export type BrowserMediaLayout = BrowserMediaPlacement[];
64
+ /**
65
+ * Closed objective defects measured from an active semantic element.
66
+ */
67
+ export type BrowserVisualIssue = "emptyBox" | "clippedHorizontally" | "clippedVertically";
68
+ /**
69
+ * Objective semantic-layout facts observed for the captured state.
70
+ *
71
+ * @maxItems 256
72
+ */
73
+ export type BrowserVisualFindings = BrowserVisualFinding[];
63
74
  /**
64
75
  * Correlation identity shared by one request and its response events.
65
76
  */
@@ -67,7 +78,7 @@ export type RequestId = number;
67
78
  /**
68
79
  * Version of the native-to-browser message contract.
69
80
  */
70
- export type ProtocolVersion = 5;
81
+ export type ProtocolVersion = 9;
71
82
  /**
72
83
  * One versioned event returned by the browser runtime.
73
84
  */
@@ -101,3 +112,10 @@ export interface BrowserPixelRectangle {
101
112
  x: number;
102
113
  y: number;
103
114
  }
115
+ /**
116
+ * One semantic node and the objective layout defect observed for it.
117
+ */
118
+ export interface BrowserVisualFinding {
119
+ issue: BrowserVisualIssue;
120
+ nodeId: BrowserNodeId;
121
+ }
@@ -1,11 +1,14 @@
1
1
  export declare const RUNTIME_HOST_NAME: "__ONMARK_RUNTIME__";
2
- export declare const BROWSER_PROTOCOL_VERSION: 5;
2
+ export declare const BROWSER_PROTOCOL_VERSION: 9;
3
+ export declare const MAX_BROWSER_TEXT_BYTES: 1048576;
4
+ export declare const MAX_VARIANT_TEXT_BYTES: 16384;
3
5
  export declare const MAX_BROWSER_VIDEOS: 10000;
4
6
  export declare const MAX_BROWSER_MEDIA_LAYOUTS: 16;
5
7
  export declare const BROWSER_OBJECT_POSITION_SCALE: 1000000;
6
8
  export declare const MAX_BROWSER_TRANSITIONS: 10000;
7
9
  export declare const MAX_BROWSER_OVERLAYS: 10000;
8
10
  export declare const MAX_BROWSER_OVERLAY_TEXT_CHARACTERS: 65536;
11
+ export declare const MAX_BROWSER_VISUAL_FINDINGS: 256;
9
12
  export declare const MAX_FAILURE_MESSAGE_CHARACTERS: 4096;
10
13
  export declare const MAX_PENDING_RESOURCES: 256;
11
14
  export declare const MAX_PENDING_RESOURCE_CHARACTERS: 1024;
@@ -1,12 +1,15 @@
1
1
  // Generated by `cargo xtask schema`; edit Rust protocol types instead.
2
2
  export const RUNTIME_HOST_NAME = "__ONMARK_RUNTIME__";
3
- export const BROWSER_PROTOCOL_VERSION = 5;
3
+ export const BROWSER_PROTOCOL_VERSION = 9;
4
+ export const MAX_BROWSER_TEXT_BYTES = 1048576;
5
+ export const MAX_VARIANT_TEXT_BYTES = 16384;
4
6
  export const MAX_BROWSER_VIDEOS = 10000;
5
7
  export const MAX_BROWSER_MEDIA_LAYOUTS = 16;
6
8
  export const BROWSER_OBJECT_POSITION_SCALE = 1000000;
7
9
  export const MAX_BROWSER_TRANSITIONS = 10000;
8
10
  export const MAX_BROWSER_OVERLAYS = 10000;
9
11
  export const MAX_BROWSER_OVERLAY_TEXT_CHARACTERS = 65536;
12
+ export const MAX_BROWSER_VISUAL_FINDINGS = 256;
10
13
  export const MAX_FAILURE_MESSAGE_CHARACTERS = 4096;
11
14
  export const MAX_PENDING_RESOURCES = 256;
12
15
  export const MAX_PENDING_RESOURCE_CHARACTERS = 1024;
@@ -4,8 +4,8 @@ declare function validate20(data: any, { instancePath, parentData, parentDataPro
4
4
  instancePath?: string | undefined;
5
5
  rootData?: any;
6
6
  }): boolean;
7
- export declare const validateBrowserResponse: typeof validate55;
8
- declare function validate55(data: any, { instancePath, parentData, parentDataProperty, rootData, dynamicAnchors }?: {
7
+ export declare const validateBrowserResponse: typeof validate57;
8
+ declare function validate57(data: any, { instancePath, parentData, parentDataProperty, rootData, dynamicAnchors }?: {
9
9
  dynamicAnchors?: {} | undefined;
10
10
  instancePath?: string | undefined;
11
11
  rootData?: any;