@cueframe/kernel 0.1.0 → 0.1.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.
Files changed (355) hide show
  1. package/LICENSE +661 -0
  2. package/dist/_members/composition/ops/compositionOps.d.ts +1 -0
  3. package/dist/_members/composition/projection/behind-readiness.d.ts +127 -0
  4. package/dist/_members/composition/projection/index.d.ts +2 -0
  5. package/dist/_members/composition/projection/reframe-readiness.d.ts +156 -0
  6. package/dist/_members/composition/validators/composition.d.ts +42 -25
  7. package/dist/_members/composition/validators/render.d.ts +32 -0
  8. package/dist/_members/core/render/compositionRender.d.ts +17 -1
  9. package/dist/_members/core/render/types.d.ts +31 -0
  10. package/dist/authoring/build-tools.js +6 -6
  11. package/dist/authoring/context.js +4 -4
  12. package/dist/authoring/tools.js +5 -5
  13. package/dist/authoring.js +11 -9
  14. package/dist/{chunk-ZB3C3HM7.js → chunk-7FO3ZJ43.js} +3 -0
  15. package/dist/{chunk-ODL7GQJG.js → chunk-AP6ZIVAV.js} +2 -2
  16. package/dist/{chunk-IBYQG46O.js → chunk-AQBREB5O.js} +1 -1
  17. package/dist/{chunk-YIOY2XEO.js → chunk-DK2ODBNT.js} +15 -5
  18. package/dist/{chunk-JRQVPFLF.js → chunk-HY3RIEZW.js} +1 -1
  19. package/dist/{chunk-GEA7E2FL.js → chunk-JJ6XD7NG.js} +151 -1
  20. package/dist/{chunk-COYMZ76S.js → chunk-MBCXCJOE.js} +1 -1
  21. package/dist/{chunk-37NJ27UU.js → chunk-OCFDUCF4.js} +3 -0
  22. package/dist/{chunk-VOO5FQSS.js → chunk-PDYO3DOJ.js} +5 -5
  23. package/dist/{chunk-MXFAADCQ.js → chunk-PODIYN2K.js} +9 -2
  24. package/dist/{chunk-NFEGPWGS.js → chunk-TOJEXFXL.js} +1 -1
  25. package/dist/{chunk-LM4WDUQJ.js → chunk-UHGSZZDI.js} +1 -1
  26. package/dist/{chunk-XWKZB5U5.js → chunk-ZWMV6DD2.js} +24 -1
  27. package/dist/compose/renderer.js +3 -3
  28. package/dist/compose.js +6 -6
  29. package/dist/composition/graphics-plan.js +1 -1
  30. package/dist/composition/ops.js +3 -3
  31. package/dist/composition/primitive-catalog.js +1 -1
  32. package/dist/composition/projection.js +19 -3
  33. package/dist/composition/validators.js +6 -4
  34. package/dist/composition-ops.js +8 -6
  35. package/dist/composition.js +24 -6
  36. package/dist/{context-OKX3HHFS.js → context-YWUZDG5X.js} +4 -4
  37. package/dist/core/render.js +3 -3
  38. package/dist/core/select.js +2 -2
  39. package/dist/core.js +3 -3
  40. package/dist/errors.js +1 -1
  41. package/dist/mcp/adapter.js +1 -0
  42. package/dist/media-model/testing.js +1071 -718
  43. package/dist/nle-export/server.js +328 -130
  44. package/dist/nle-export.js +7 -6
  45. package/package.json +13 -14
  46. package/dist/_members/account-model/index.js +0 -4
  47. package/dist/_members/account-model/testing/conversationStoreContract.js +0 -168
  48. package/dist/_members/account-model/testing/index.js +0 -7
  49. package/dist/_members/account-model/testing/restorePointStoreContract.js +0 -69
  50. package/dist/_members/account-model/types/index.js +0 -1
  51. package/dist/_members/account-model/validators/contextFile.js +0 -18
  52. package/dist/_members/account-model/validators/conversation.js +0 -95
  53. package/dist/_members/account-model/validators/dashboardInsight.js +0 -16
  54. package/dist/_members/account-model/validators/index.js +0 -7
  55. package/dist/_members/account-model/validators/sessionToken.js +0 -49
  56. package/dist/_members/account-model/validators/uploadToken.js +0 -16
  57. package/dist/_members/account-model/validators/userSettings.js +0 -12
  58. package/dist/_members/account-model/validators/workingComposition.js +0 -20
  59. package/dist/_members/brand-derivation/constants.js +0 -20
  60. package/dist/_members/brand-derivation/contrastSafe.js +0 -114
  61. package/dist/_members/brand-derivation/index.js +0 -1
  62. package/dist/_members/cloud-import/chunk-XKO6ZSWI.js +0 -162
  63. package/dist/_members/cloud-import/chunk-XKO6ZSWI.js.map +0 -1
  64. package/dist/_members/cloud-import/index.js +0 -241
  65. package/dist/_members/cloud-import/index.js.map +0 -1
  66. package/dist/_members/cloud-import/multipartUpload.js +0 -7
  67. package/dist/_members/cloud-import/multipartUpload.js.map +0 -1
  68. package/dist/_members/composition/audio/audioMix.js +0 -61
  69. package/dist/_members/composition/audio/index.js +0 -5
  70. package/dist/_members/composition/audio/mixStaging.js +0 -195
  71. package/dist/_members/composition/audio/musicPack.generated.js +0 -136
  72. package/dist/_members/composition/audio/musicPack.js +0 -36
  73. package/dist/_members/composition/audio/pack.generated.js +0 -603
  74. package/dist/_members/composition/audio/pack.js +0 -48
  75. package/dist/_members/composition/audio/palette.js +0 -134
  76. package/dist/_members/composition/autozoom/index.js +0 -83
  77. package/dist/_members/composition/brand-kit.js +0 -45
  78. package/dist/_members/composition/brief/contract.js +0 -209
  79. package/dist/_members/composition/color-grade.js +0 -80
  80. package/dist/_members/composition/depth.js +0 -8
  81. package/dist/_members/composition/fixtures/index.js +0 -143
  82. package/dist/_members/composition/fixtures/vaayaErrored.d.ts +0 -25
  83. package/dist/_members/composition/fixtures/vaayaErrored.js +0 -203
  84. package/dist/_members/composition/fonts.js +0 -162
  85. package/dist/_members/composition/graphics-plan/compile.js +0 -221
  86. package/dist/_members/composition/graphics-plan/index.js +0 -10
  87. package/dist/_members/composition/graphics-plan/instantiateMotif.js +0 -44
  88. package/dist/_members/composition/graphics-plan/motion.js +0 -66
  89. package/dist/_members/composition/graphics-plan/schemas.js +0 -261
  90. package/dist/_members/composition/graphics-plan/solve.js +0 -145
  91. package/dist/_members/composition/index.js +0 -5
  92. package/dist/_members/composition/invariants/clipPlacement.js +0 -69
  93. package/dist/_members/composition/invariants/composition.js +0 -28
  94. package/dist/_members/composition/invariants/errors.js +0 -10
  95. package/dist/_members/composition/invariants/etag.js +0 -38
  96. package/dist/_members/composition/invariants/ids.js +0 -33
  97. package/dist/_members/composition/invariants/index.js +0 -9
  98. package/dist/_members/composition/invariants/keyframes.js +0 -45
  99. package/dist/_members/composition/invariants/markers.js +0 -29
  100. package/dist/_members/composition/invariants/time.js +0 -20
  101. package/dist/_members/composition/invariants/tracks.js +0 -304
  102. package/dist/_members/composition/ops/compositionOps.js +0 -1056
  103. package/dist/_members/composition/ops/headlessStore.js +0 -94
  104. package/dist/_members/composition/ops/index.js +0 -4
  105. package/dist/_members/composition/ops/selectors.js +0 -118
  106. package/dist/_members/composition/ops/timeline-word.js +0 -1
  107. package/dist/_members/composition/ops/transcript.js +0 -77
  108. package/dist/_members/composition/ops/types.js +0 -16
  109. package/dist/_members/composition/primitive-catalog/catalogQuery.js +0 -150
  110. package/dist/_members/composition/primitive-catalog/disabled.js +0 -32
  111. package/dist/_members/composition/primitive-catalog/generated/meta.js +0 -15161
  112. package/dist/_members/composition/primitive-catalog/index.js +0 -46
  113. package/dist/_members/composition/primitive-catalog/paramValidation.js +0 -231
  114. package/dist/_members/composition/primitive-catalog/projection.js +0 -164
  115. package/dist/_members/composition/primitive-catalog/types.js +0 -14
  116. package/dist/_members/composition/projection/behind-placement.js +0 -62
  117. package/dist/_members/composition/projection/brandKit.js +0 -482
  118. package/dist/_members/composition/projection/cardTokens.js +0 -209
  119. package/dist/_members/composition/projection/composition-floor.js +0 -582
  120. package/dist/_members/composition/projection/cropProjection.js +0 -257
  121. package/dist/_members/composition/projection/index.js +0 -7
  122. package/dist/_members/composition/projection/occlusion-budget.js +0 -104
  123. package/dist/_members/composition/projection/safe-zones.js +0 -99
  124. package/dist/_members/composition/reframe/aspectLoss.js +0 -115
  125. package/dist/_members/composition/reframe/coverage.js +0 -62
  126. package/dist/_members/composition/reframe/derive.js +0 -73
  127. package/dist/_members/composition/reframe/index.js +0 -109
  128. package/dist/_members/composition/reframe/kenBurns.js +0 -64
  129. package/dist/_members/composition/reframe/shotScale.js +0 -176
  130. package/dist/_members/composition/reframe/trajectory.js +0 -124
  131. package/dist/_members/composition/timeline/compound.js +0 -134
  132. package/dist/_members/composition/timeline/index.js +0 -9
  133. package/dist/_members/composition/timeline/intent.js +0 -228
  134. package/dist/_members/composition/timeline/keyframes.js +0 -121
  135. package/dist/_members/composition/timeline/link.js +0 -59
  136. package/dist/_members/composition/timeline/occupancy.js +0 -36
  137. package/dist/_members/composition/timeline/placement.js +0 -74
  138. package/dist/_members/composition/timeline/plan.js +0 -31
  139. package/dist/_members/composition/timeline/resolve.js +0 -170
  140. package/dist/_members/composition/timeline/trims.js +0 -278
  141. package/dist/_members/composition/types/index.js +0 -1
  142. package/dist/_members/composition/validators/brandKit.js +0 -295
  143. package/dist/_members/composition/validators/composePlan.js +0 -113
  144. package/dist/_members/composition/validators/composition.js +0 -703
  145. package/dist/_members/composition/validators/font.js +0 -34
  146. package/dist/_members/composition/validators/graphicKinds.js +0 -30
  147. package/dist/_members/composition/validators/index.js +0 -9
  148. package/dist/_members/composition/validators/project.js +0 -29
  149. package/dist/_members/composition/validators/registry.js +0 -41
  150. package/dist/_members/composition/validators/render.js +0 -139
  151. package/dist/_members/composition/validators/session.js +0 -37
  152. package/dist/_members/composition/validators/webhook.js +0 -72
  153. package/dist/_members/composition-ops/alphaLayers.js +0 -141
  154. package/dist/_members/composition-ops/index.js +0 -637
  155. package/dist/_members/composition-ops/materializeGrid.js +0 -99
  156. package/dist/_members/composition-ops/opRecorder.js +0 -196
  157. package/dist/_members/composition-ops/recordingStore.js +0 -14
  158. package/dist/_members/composition-ops/replaceRegion.js +0 -102
  159. package/dist/_members/composition-ops/testFixtures.js +0 -19
  160. package/dist/_members/core/index.js +0 -5
  161. package/dist/_members/core/render/bookends.js +0 -53
  162. package/dist/_members/core/render/captions.js +0 -127
  163. package/dist/_members/core/render/compositionRender.js +0 -1249
  164. package/dist/_members/core/render/deriveTrajectory.js +0 -889
  165. package/dist/_members/core/render/emphasis.js +0 -16
  166. package/dist/_members/core/render/eval/cropBox.js +0 -139
  167. package/dist/_members/core/render/eval/inclusion.js +0 -96
  168. package/dist/_members/core/render/eval/index.js +0 -146
  169. package/dist/_members/core/render/eval/metrics.js +0 -94
  170. package/dist/_members/core/render/exportSettings.js +0 -65
  171. package/dist/_members/core/render/index.js +0 -20
  172. package/dist/_members/core/render/mapFaceToPerson.js +0 -73
  173. package/dist/_members/core/render/types.js +0 -8
  174. package/dist/_members/core/render/vcam/cameraPath.js +0 -248
  175. package/dist/_members/core/render/vcam/constants.js +0 -115
  176. package/dist/_members/core/render/vcam/errorCodes.js +0 -39
  177. package/dist/_members/core/render/vcam/framing.js +0 -136
  178. package/dist/_members/core/render/vcam/requiredRegion.js +0 -137
  179. package/dist/_members/core/render/vcam/shots.js +0 -53
  180. package/dist/_members/core/render/vcam/subjectSet.js +0 -388
  181. package/dist/_members/core/select/errorCodes.js +0 -38
  182. package/dist/_members/core/select/index.js +0 -26
  183. package/dist/_members/core/select/model.js +0 -18
  184. package/dist/_members/core/select/select.js +0 -244
  185. package/dist/_members/core/select/stabilize.js +0 -242
  186. package/dist/_members/core/types.js +0 -7
  187. package/dist/_members/errors/index.js +0 -1
  188. package/dist/_members/errors/registry.js +0 -560
  189. package/dist/_members/foundation/codes/index.js +0 -31
  190. package/dist/_members/foundation/index.js +0 -2
  191. package/dist/_members/foundation/primitives/index.js +0 -5
  192. package/dist/_members/mcp/adapter.js +0 -771
  193. package/dist/_members/mcp/burnedNames.js +0 -73
  194. package/dist/_members/mcp/core.js +0 -390
  195. package/dist/_members/mcp/curation.js +0 -792
  196. package/dist/_members/mcp/executor.js +0 -142
  197. package/dist/_members/mcp/format.js +0 -9
  198. package/dist/_members/mcp/generated/catalogPreviews.js +0 -95
  199. package/dist/_members/mcp/generated/harness.js +0 -81
  200. package/dist/_members/mcp/generated/operations.js +0 -131
  201. package/dist/_members/mcp/index.js +0 -50
  202. package/dist/_members/mcp/internalLoopTools.js +0 -109
  203. package/dist/_members/mcp/prompts.js +0 -45
  204. package/dist/_members/mcp/resources.js +0 -166
  205. package/dist/_members/mcp/server.js +0 -340
  206. package/dist/_members/mcp/wait.js +0 -378
  207. package/dist/_members/mcp/x402Meta.js +0 -66
  208. package/dist/_members/media-model/api.js +0 -175
  209. package/dist/_members/media-model/index.js +0 -1
  210. package/dist/_members/media-model/media-kind.js +0 -116
  211. package/dist/_members/media-model/testing/index.js +0 -1
  212. package/dist/_members/media-model/testing/mediaStoreContract.js +0 -82
  213. package/dist/_members/media-model/transcriptSearch.js +0 -70
  214. package/dist/_members/media-model/transcriptSearchCases.json +0 -79
  215. package/dist/_members/nle-export/compact-timeline.js +0 -73
  216. package/dist/_members/nle-export/compact-timeline.js.map +0 -1
  217. package/dist/_members/nle-export/composition-to-input.js +0 -147
  218. package/dist/_members/nle-export/composition-to-input.js.map +0 -1
  219. package/dist/_members/nle-export/fcpxml.js +0 -159
  220. package/dist/_members/nle-export/fcpxml.js.map +0 -1
  221. package/dist/_members/nle-export/index.js +0 -12
  222. package/dist/_members/nle-export/index.js.map +0 -1
  223. package/dist/_members/nle-export/premiere.js +0 -161
  224. package/dist/_members/nle-export/premiere.js.map +0 -1
  225. package/dist/_members/nle-export/server/index.js +0 -2
  226. package/dist/_members/nle-export/server/index.js.map +0 -1
  227. package/dist/_members/nle-export/server/pack-zip.js +0 -38
  228. package/dist/_members/nle-export/server/pack-zip.js.map +0 -1
  229. package/dist/_members/nle-export/srt.js +0 -50
  230. package/dist/_members/nle-export/srt.js.map +0 -1
  231. package/dist/_members/nle-export/types.js +0 -9
  232. package/dist/_members/nle-export/types.js.map +0 -1
  233. package/dist/_members/nle-export/xml/index.js +0 -11
  234. package/dist/_members/nle-export/xml/index.js.map +0 -1
  235. package/dist/_members/nle-export/xml-utils.js +0 -48
  236. package/dist/_members/nle-export/xml-utils.js.map +0 -1
  237. package/dist/_members/perception/activeSpeaker.js +0 -103
  238. package/dist/_members/perception/audioQuality.js +0 -76
  239. package/dist/_members/perception/energyBeat.js +0 -99
  240. package/dist/_members/perception/identityMatch.js +0 -91
  241. package/dist/_members/perception/index.js +0 -48
  242. package/dist/_members/perception/visualQuality.js +0 -95
  243. package/dist/_members/plane/conformance.js +0 -90
  244. package/dist/_members/plane/contract.js +0 -49
  245. package/dist/_members/plane/index.js +0 -16
  246. package/dist/_members/primitives/backgrounds/index.js +0 -32
  247. package/dist/_members/primitives/backgrounds/index.js.map +0 -1
  248. package/dist/_members/primitives/captions/index.js +0 -398
  249. package/dist/_members/primitives/captions/index.js.map +0 -1
  250. package/dist/_members/primitives/chunk-2LVE4UIT.js +0 -139
  251. package/dist/_members/primitives/chunk-2LVE4UIT.js.map +0 -1
  252. package/dist/_members/primitives/chunk-3IQUH6KK.js +0 -20
  253. package/dist/_members/primitives/chunk-3IQUH6KK.js.map +0 -1
  254. package/dist/_members/primitives/chunk-3OMURV6Q.js +0 -112
  255. package/dist/_members/primitives/chunk-3OMURV6Q.js.map +0 -1
  256. package/dist/_members/primitives/chunk-4IS6TMEG.js +0 -21
  257. package/dist/_members/primitives/chunk-4IS6TMEG.js.map +0 -1
  258. package/dist/_members/primitives/chunk-5MWGAEGQ.js +0 -1644
  259. package/dist/_members/primitives/chunk-5MWGAEGQ.js.map +0 -1
  260. package/dist/_members/primitives/chunk-7RRPFPQK.js +0 -15
  261. package/dist/_members/primitives/chunk-7RRPFPQK.js.map +0 -1
  262. package/dist/_members/primitives/chunk-DH5TRZK2.js +0 -125
  263. package/dist/_members/primitives/chunk-DH5TRZK2.js.map +0 -1
  264. package/dist/_members/primitives/chunk-E3KNUSFG.js +0 -2337
  265. package/dist/_members/primitives/chunk-E3KNUSFG.js.map +0 -1
  266. package/dist/_members/primitives/chunk-G2B3G4HK.js +0 -47
  267. package/dist/_members/primitives/chunk-G2B3G4HK.js.map +0 -1
  268. package/dist/_members/primitives/chunk-HFPFGZXT.js +0 -1494
  269. package/dist/_members/primitives/chunk-HFPFGZXT.js.map +0 -1
  270. package/dist/_members/primitives/chunk-HIWVFZVH.js +0 -19
  271. package/dist/_members/primitives/chunk-HIWVFZVH.js.map +0 -1
  272. package/dist/_members/primitives/chunk-IDAL6G3Y.js +0 -134
  273. package/dist/_members/primitives/chunk-IDAL6G3Y.js.map +0 -1
  274. package/dist/_members/primitives/chunk-KNC6JP5F.js +0 -34
  275. package/dist/_members/primitives/chunk-KNC6JP5F.js.map +0 -1
  276. package/dist/_members/primitives/chunk-KYRDVZST.js +0 -459
  277. package/dist/_members/primitives/chunk-KYRDVZST.js.map +0 -1
  278. package/dist/_members/primitives/chunk-LWLHS2NS.js +0 -3410
  279. package/dist/_members/primitives/chunk-LWLHS2NS.js.map +0 -1
  280. package/dist/_members/primitives/chunk-QAQ3P7DR.js +0 -8855
  281. package/dist/_members/primitives/chunk-QAQ3P7DR.js.map +0 -1
  282. package/dist/_members/primitives/chunk-ROV2ODWC.js +0 -81
  283. package/dist/_members/primitives/chunk-ROV2ODWC.js.map +0 -1
  284. package/dist/_members/primitives/chunk-TCRC2FH3.js +0 -183
  285. package/dist/_members/primitives/chunk-TCRC2FH3.js.map +0 -1
  286. package/dist/_members/primitives/chunk-US4YEDAA.js +0 -96
  287. package/dist/_members/primitives/chunk-US4YEDAA.js.map +0 -1
  288. package/dist/_members/primitives/chunk-UVKRO5ER.js +0 -13
  289. package/dist/_members/primitives/chunk-UVKRO5ER.js.map +0 -1
  290. package/dist/_members/primitives/chunk-W4EIIF2I.js +0 -10
  291. package/dist/_members/primitives/chunk-W4EIIF2I.js.map +0 -1
  292. package/dist/_members/primitives/chunk-WPGKIPCO.js +0 -3563
  293. package/dist/_members/primitives/chunk-WPGKIPCO.js.map +0 -1
  294. package/dist/_members/primitives/chunk-WZFLEGMD.js +0 -1435
  295. package/dist/_members/primitives/chunk-WZFLEGMD.js.map +0 -1
  296. package/dist/_members/primitives/chunk-XHU3WBEI.js +0 -33
  297. package/dist/_members/primitives/chunk-XHU3WBEI.js.map +0 -1
  298. package/dist/_members/primitives/chunk-YN7WTZZ7.js +0 -46
  299. package/dist/_members/primitives/chunk-YN7WTZZ7.js.map +0 -1
  300. package/dist/_members/primitives/effects/index.js +0 -30
  301. package/dist/_members/primitives/effects/index.js.map +0 -1
  302. package/dist/_members/primitives/hero-text/index.js +0 -14
  303. package/dist/_members/primitives/hero-text/index.js.map +0 -1
  304. package/dist/_members/primitives/index.js +0 -64
  305. package/dist/_members/primitives/index.js.map +0 -1
  306. package/dist/_members/primitives/layouts/index.js +0 -24
  307. package/dist/_members/primitives/layouts/index.js.map +0 -1
  308. package/dist/_members/primitives/lib/easings.js +0 -26
  309. package/dist/_members/primitives/lib/easings.js.map +0 -1
  310. package/dist/_members/primitives/lib/index.js +0 -74
  311. package/dist/_members/primitives/lib/index.js.map +0 -1
  312. package/dist/_members/primitives/lib/palette.js +0 -72
  313. package/dist/_members/primitives/lib/palette.js.map +0 -1
  314. package/dist/_members/primitives/lib/preview.js +0 -8
  315. package/dist/_members/primitives/lib/preview.js.map +0 -1
  316. package/dist/_members/primitives/lib/schema.js +0 -12
  317. package/dist/_members/primitives/lib/schema.js.map +0 -1
  318. package/dist/_members/primitives/lib/seeded-random.js +0 -14
  319. package/dist/_members/primitives/lib/seeded-random.js.map +0 -1
  320. package/dist/_members/primitives/lib/text/contrast.js +0 -12
  321. package/dist/_members/primitives/lib/text/contrast.js.map +0 -1
  322. package/dist/_members/primitives/lib/text/fill.js +0 -8
  323. package/dist/_members/primitives/lib/text/fill.js.map +0 -1
  324. package/dist/_members/primitives/lib/text/fitText.js +0 -10
  325. package/dist/_members/primitives/lib/text/fitText.js.map +0 -1
  326. package/dist/_members/primitives/lib/text/marker.js +0 -8
  327. package/dist/_members/primitives/lib/text/marker.js.map +0 -1
  328. package/dist/_members/primitives/lib/text/motion.js +0 -16
  329. package/dist/_members/primitives/lib/text/motion.js.map +0 -1
  330. package/dist/_members/primitives/lib/text/recolor.js +0 -8
  331. package/dist/_members/primitives/lib/text/recolor.js.map +0 -1
  332. package/dist/_members/primitives/lib/text/spec.js +0 -1
  333. package/dist/_members/primitives/lib/text/spec.js.map +0 -1
  334. package/dist/_members/primitives/lib/text/stage.js +0 -8
  335. package/dist/_members/primitives/lib/text/stage.js.map +0 -1
  336. package/dist/_members/primitives/lib/text/typeface.js +0 -8
  337. package/dist/_members/primitives/lib/text/typeface.js.map +0 -1
  338. package/dist/_members/primitives/lib/tokens.js +0 -24
  339. package/dist/_members/primitives/lib/tokens.js.map +0 -1
  340. package/dist/_members/primitives/lib/types.js +0 -1
  341. package/dist/_members/primitives/lib/types.js.map +0 -1
  342. package/dist/_members/primitives/params-required.json +0 -153
  343. package/dist/_members/primitives/scenes/index.js +0 -25
  344. package/dist/_members/primitives/scenes/index.js.map +0 -1
  345. package/dist/_members/primitives/subject-foreground/index.js +0 -30
  346. package/dist/_members/primitives/subject-foreground/index.js.map +0 -1
  347. package/dist/_members/primitives/text/index.js +0 -57
  348. package/dist/_members/primitives/text/index.js.map +0 -1
  349. package/dist/_members/primitives/transitions/index.js +0 -67
  350. package/dist/_members/primitives/transitions/index.js.map +0 -1
  351. package/dist/_members/primitives/ui-blocks/index.js +0 -76
  352. package/dist/_members/primitives/ui-blocks/index.js.map +0 -1
  353. package/dist/_members/primitives/version-map.json +0 -105
  354. package/dist/_members/primitives/workspace.js +0 -60
  355. package/dist/_members/primitives/workspace.js.map +0 -1
@@ -1,221 +0,0 @@
1
- import { resolveBrandRefsDeep } from "../projection/brandKit.js";
2
- // Brand-ref leaves (see brandKit ResolvedBrandKit). Fonts MUST use `.family`.
3
- const B = {
4
- textOnMedia: "$brand:colors.textOnMedia",
5
- textOnAccent: "$brand:colors.textOnAccent",
6
- textOnSurface: "$brand:colors.textOnSurface",
7
- accent: "$brand:colors.accent",
8
- overlay: "$brand:colors.overlay",
9
- surface: "$brand:colors.surface",
10
- fontHeading: "$brand:fonts.heading.family",
11
- fontBody: "$brand:fonts.body.family",
12
- motionEasing: "$brand:motion.easing",
13
- motionEntrance: "$brand:motion.entrance",
14
- };
15
- function textColorRef(styleRole) {
16
- return styleRole === "on-accent" ? B.textOnAccent : styleRole === "on-surface" ? B.textOnSurface : B.textOnMedia;
17
- }
18
- function fontRef(styleRole) {
19
- return styleRole === "body" ? B.fontBody : B.fontHeading;
20
- }
21
- /** Font px from a box's height so the text FITS its box (leaves line room). */
22
- function fontPx(boxH, frameH, fill = 0.62) {
23
- return Math.round(Math.max(16, Math.min(240, boxH * frameH * fill)));
24
- }
25
- /** Bounding box of the front element boxes (clear of the face iff each is). */
26
- function unionBox(rects) {
27
- const x = Math.min(...rects.map((r) => r.x));
28
- const y = Math.min(...rects.map((r) => r.y));
29
- const x2 = Math.max(...rects.map((r) => r.x + r.w));
30
- const y2 = Math.max(...rects.map((r) => r.y + r.h));
31
- return { x, y, w: x2 - x, h: y2 - y };
32
- }
33
- /** Parse a stat string ("5 yrs", "100%", "$0 raised", "3,000 downloads") into
34
- * stat-counter's numeric value + prefix/suffix. Non-digit prefix is greedy so a
35
- * hyphen after letters ("Top-10") is NOT read as a negative; thousands commas
36
- * are stripped from the number. null ⇒ no leading number. */
37
- export function parseStatValue(raw) {
38
- const m = raw.trim().match(/^(\D*)(\d[\d,]*(?:\.\d+)?)(.*)$/);
39
- if (!m)
40
- return null;
41
- const value = Number(m[2].replace(/,/g, ""));
42
- if (!Number.isFinite(value))
43
- return null;
44
- return { value, prefix: m[1].trim(), suffix: m[3] };
45
- }
46
- const asSource = (s) => s;
47
- /** True iff two rects overlap. */
48
- const overlaps = (a, b) => a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
49
- /** Compile one beat (its content role + solved layout) into overlay clips. */
50
- export function compileBeat(beat, layout, _motion, opts = {}) {
51
- const prefix = opts.idPrefix ?? "gfx";
52
- const frameH = layout.frame.h;
53
- const kit = opts.brandKit;
54
- // Resolve nested $brand: refs to literals at compile time when a kit is given
55
- // (the render inflater only does top-level). Identity passthrough otherwise.
56
- const finalize = (s) => kit ? { ...s, params: resolveBrandRefsDeep(s.params, kit) } : s;
57
- const src = (s) => asSource(finalize(s));
58
- // The behind-subject hero (heroText) — RE-ENABLED 2026-07-29. It was
59
- // denylisted 2026-07-08 for "matte compositing desyncs lip movement"; the
60
- // root cause was the matte bake re-timing the co-view at average fps (fixed
61
- // by the CFR timing invariant — plan 2026-07-28-cfr-timing-invariant), not
62
- // this emission. heroText is world-locked (zPlane, no authored anchor) so
63
- // the silhouette gate places it — not the plan. Cross-beat duplicate
64
- // protection (the OTHER disable reason: an agent plan authored two
65
- // overlapping hero beats 0.14s apart) lives in compileGraphicsPlan.
66
- // Text is REQUIRED: heroText's schema is min(1), and a Copy.headline of ""
67
- // is schema-legal upstream (the solver omits `text` for falsy copy) — an
68
- // unguarded emission would compile a clip the write boundary/render rejects
69
- // for the whole plan. A textless hero drops out like other non-emitted roles.
70
- const hero = layout.elements.find((e) => e.z === "behind-subject" && e.text?.trim());
71
- // Only TEXT-emitting front roles composite here; logo/accent-shape/backdrop
72
- // are non-text decoration (P1 skips them rather than emitting a blank title).
73
- const front = layout.elements.filter((e) => e.z !== "behind-subject" && e.role !== "logo" && e.role !== "accent-shape" && e.role !== "backdrop");
74
- const clips = [];
75
- if (hero) {
76
- clips.push({
77
- id: `${prefix}-${beat.id}-hero`,
78
- startTime: beat.atSec,
79
- duration: beat.durSec,
80
- kind: "overlay",
81
- source: src({
82
- kind: "overlay",
83
- primitiveId: "heroText",
84
- params: { text: hero.text, fontSizePct: 14, textColor: B.textOnMedia, fontFamily: B.fontHeading, entrance: B.motionEntrance, easing: B.motionEasing },
85
- zPlane: "behind-subject",
86
- }),
87
- });
88
- }
89
- if (front.length === 0)
90
- return clips;
91
- const region = unionBox(front.map((e) => e.box));
92
- // GUARD: the union of individually-clear boxes could still span the face (a
93
- // split layout). If it does, skip the front graphic rather than composite it
94
- // OVER the speaker — the invariant holds even when the solver doesn't stack
95
- // contiguously (e.g. a future agent-proposed layout).
96
- if (layout.keepOut.some((ko) => overlaps(region, ko)))
97
- return clips;
98
- // A text graphic MUST have a primary line (headline/value). No fallback to
99
- // front[0] — a beat with only a subtitle is malformed; fail loud.
100
- const head = front.find((e) => e.role === "headline" || e.role === "value");
101
- if (!head) {
102
- throw new Error(`graphics-plan: beat "${beat.id}" (role ${beat.role}) has front elements but no headline/value line — malformed copy.`);
103
- }
104
- // sub must be a DISTINCT element from head (else a subtitle-only beat would
105
- // render the same string twice).
106
- const sub = front.find((e) => (e.role === "sublabel" || e.role === "label") && e !== head);
107
- const headFont = fontPx(head.box.h, frameH);
108
- // Subtitle never larger than the headline (hierarchy), regardless of box math.
109
- const subFont = sub ? Math.min(fontPx(sub.box.h, frameH), Math.round(headFont * 0.8)) : undefined;
110
- const base = { id: `${prefix}-${beat.id}`, startTime: beat.atSec, duration: beat.durSec, kind: "overlay", region };
111
- const titleSource = (styleRole) => ({
112
- kind: "overlay",
113
- primitiveId: "cinematic-title",
114
- params: {
115
- text: head.text ?? "",
116
- ...(sub?.text ? { subtitle: sub.text } : {}),
117
- tokens: { fontSize: headFont, ...(subFont ? { subtextFontSize: subFont } : {}), textColor: textColorRef(styleRole), accentColor: B.accent, fontFamily: fontRef(styleRole) },
118
- },
119
- });
120
- switch (beat.role) {
121
- case "title-card":
122
- clips.push({ ...base, source: src(titleSource(head.styleRole)) });
123
- break;
124
- case "lower-third":
125
- clips.push({
126
- ...base,
127
- source: src({
128
- kind: "overlay",
129
- primitiveId: "lower-third",
130
- params: {
131
- text: head.text ?? "",
132
- ...(sub?.text ? { subtitle: sub.text } : {}),
133
- tokens: { fontSize: headFont, ...(subFont ? { subtitleFontSize: subFont } : {}), textColor: B.textOnMedia, accentColor: B.accent, backgroundColor: B.overlay, fontFamily: B.fontBody },
134
- },
135
- }),
136
- });
137
- break;
138
- case "stat": {
139
- const parsed = head.text ? parseStatValue(head.text) : null;
140
- if (parsed) {
141
- clips.push({
142
- ...base,
143
- source: src({
144
- kind: "overlay",
145
- primitiveId: "stat-counter",
146
- params: { value: parsed.value, ...(parsed.prefix ? { prefix: parsed.prefix } : {}), ...(parsed.suffix ? { suffix: parsed.suffix } : {}), ...(sub?.text ? { label: sub.text } : {}), accentColor: B.accent },
147
- }),
148
- });
149
- }
150
- else {
151
- // A stat REQUIRES a leading number — no silent degrade to a title card.
152
- throw new Error(`graphics-plan: beat "${beat.id}" role "stat" has non-numeric value "${head.text}" — a stat needs a leading number (e.g. "5 yrs", "100%", "498").`);
153
- }
154
- break;
155
- }
156
- case "pull-quote":
157
- clips.push({ ...base, source: src({ kind: "overlay", primitiveId: "quote-card", params: { text: head.text ?? "", ...(sub?.text ? { subtext: sub.text } : {}), accentColor: B.accent } }) });
158
- break;
159
- case "enumeration":
160
- case "sequence":
161
- case "comparison":
162
- // The ARGUMENT roles are DESIGNER-AUTHORED, by design. There is no deterministic
163
- // role→primitive mapping for them and there should not be: an `enumeration` might be
164
- // three badges, a numbered list or a build-on-reveal, and a `sequence` might be
165
- // `reasoning-trace`, `tool-call-stack` or a bespoke component — that choice is the
166
- // designer's job, made with eyes on the frame and the whole catalog in hand.
167
- //
168
- // This deterministic FC5 compiler was DEMOTED to critics in any case (director.ts: "they
169
- // no longer COMPILE the design") and `compilePlanGraphics` has no live callers. It is kept
170
- // for an optional deterministic seed. Failing loud HERE — rather than silently rendering a
171
- // title card — is the honest behaviour if it is ever re-promoted.
172
- throw new Error(`graphics-plan: beat "${beat.id}" role "${beat.role}" is a DESIGNER-AUTHORED argument role ` +
173
- `(enumeration / sequence / comparison). It has no deterministic primitive mapping by ` +
174
- `design — the designer picks the component from the catalog or writes one. This ` +
175
- `compiler only handles the text-shaped roles.`);
176
- default:
177
- // hero/logo-tag never reach here (no front text elements); any role that
178
- // does is unhandled — fail loud instead of silently rendering a title.
179
- throw new Error(`graphics-plan: beat "${beat.id}" role "${beat.role}" reached the compiler with front text but no handler.`);
180
- }
181
- return clips;
182
- }
183
- /** Compile a whole GraphicsPlan (all beats) into overlay clips. */
184
- export function compileGraphicsPlan(plan, opts = {}) {
185
- const motionByBeat = new Map(plan.motions.map((m) => [m.beatId, m]));
186
- const layoutByBeat = new Map(plan.layouts.map((l) => [l.beatId, l]));
187
- const clips = [];
188
- for (const beat of plan.content.beats) {
189
- const layout = layoutByBeat.get(beat.id);
190
- if (!layout)
191
- continue;
192
- clips.push(...compileBeat(beat, layout, motionByBeat.get(beat.id), opts));
193
- }
194
- return dedupeOverlappingHeroes(clips);
195
- }
196
- /**
197
- * MECHANICAL guard for the hero param-snag that co-motivated the 2026-07-08
198
- * disable: the 2026-07-07 prod e2e produced TWO overlapping heroText beats
199
- * (7.93s & 8.07s) — stacked display phrases rendering over each other. One
200
- * hero at a time is the grammar ("ration it hard: ONE hero beat per clip"),
201
- * so enforce it here rather than trusting the planner prompt: when two
202
- * compiled heroText windows overlap in time, the EARLIER one wins and the
203
- * later duplicate is dropped. Non-overlapping heroes (distinct moments in a
204
- * long film) all survive.
205
- */
206
- function dedupeOverlappingHeroes(clips) {
207
- const isHero = (c) => c.source?.primitiveId === "heroText";
208
- const heroes = clips
209
- .filter(isHero)
210
- .sort((a, b) => a.startTime - b.startTime || a.id.localeCompare(b.id));
211
- const dropped = new Set();
212
- let lastEnd = -Infinity;
213
- for (const h of heroes) {
214
- if (h.startTime < lastEnd) {
215
- dropped.add(h.id);
216
- continue;
217
- }
218
- lastEnd = h.startTime + h.duration;
219
- }
220
- return dropped.size === 0 ? clips : clips.filter((c) => !dropped.has(c.id));
221
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * Graphics-plan IR — public surface. See ./schemas.ts for the contract and
3
- * brain/Projects/CueFrame/plans/2026-07-07-structure-first-graphics-pipeline.md
4
- * for the design.
5
- */
6
- export * from "./schemas.js";
7
- export * from "./solve.js";
8
- export * from "./motion.js";
9
- export * from "./compile.js";
10
- export { instantiateMotif, MotifInstantiationError } from "./instantiateMotif.js";
@@ -1,44 +0,0 @@
1
- /**
2
- * Deterministic instantiation of a REPRODUCED brand-kit motif skin — Lane A of
3
- * the two-lane graphics agent (plan 2026-07-16). A skin is the motif's verified
4
- * authored form (`brandMotif.body`, pixel-diffed against the reference at
5
- * ingestion); at compose time the graphic's copy is slotted into it with NO
6
- * LLM: pure text replacement under the slot convention.
7
- *
8
- * SLOT CONVENTION (defined here, enforced here, authored by the reproduction
9
- * loop): copy-bearing elements carry `data-slot="<copyKey>"` and contain ONLY
10
- * text. That constraint is what makes regex replacement sound — no HTML parser
11
- * dependency enters the composition leaf. Every violation FAILS LOUD; a silent
12
- * redesign is exactly the variance this lane exists to remove.
13
- */
14
- export class MotifInstantiationError extends Error {
15
- }
16
- const SLOT_RE = /(<[^>]*\bdata-slot="([^"]+)"[^>]*>)([\s\S]*?)(<\/)/g;
17
- const escapeHtml = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
18
- /** Fill a reproduced card skin's slots with the graphic's copy. Throws
19
- * MotifInstantiationError on any deviation from the convention. */
20
- export function instantiateMotif(motif, copy) {
21
- if (motif.coverage !== "reproduced") {
22
- throw new MotifInstantiationError(`motif coverage is '${motif.coverage}' — only 'reproduced' skins instantiate; approximated/skipped motifs go to the designer`);
23
- }
24
- if (motif.body.kind !== "card") {
25
- throw new MotifInstantiationError(`v1 instantiates card bodies only (got '${motif.body.kind}')`);
26
- }
27
- const seen = new Set();
28
- const html = motif.body.html.replace(SLOT_RE, (_m, open, slot, inner, close) => {
29
- if (/[<>]/.test(inner)) {
30
- throw new MotifInstantiationError(`slot '${slot}' contains nested markup — skins must keep slots text-only`);
31
- }
32
- if (!(slot in copy)) {
33
- throw new MotifInstantiationError(`slot '${slot}' not filled — copy carries [${Object.keys(copy).join(", ")}]`);
34
- }
35
- seen.add(slot);
36
- return `${open}${escapeHtml(copy[slot])}${close}`;
37
- });
38
- for (const key of Object.keys(copy)) {
39
- if (!seen.has(key)) {
40
- throw new MotifInstantiationError(`copy has no slot '${key}' in the skin`);
41
- }
42
- }
43
- return { html, ...(motif.body.tokens ? { tokens: motif.body.tokens } : {}) };
44
- }
@@ -1,66 +0,0 @@
1
- /**
2
- * Motion stage: LayoutPlan → MotionPlan. Assigns a sensible default
3
- * entrance/emphasis/exit per element role, staggered so elements don't all
4
- * arrive at once. This is the inspectable MOTION artifact of the plan (a
5
- * checkpoint surface, and what an agent revises).
6
- *
7
- * NOTE (honest status): the compiler does NOT yet consume MotionPlan — the
8
- * primitives currently animate from their own `$brand:motion` defaults
9
- * (entrance/duration/easing). Wiring MotionPlan → per-primitive animation
10
- * params is a follow-up (FC3). Until then this plan is descriptive, not
11
- * yet the driver.
12
- */
13
- import { GRAPHICS_PLAN_VERSION, } from "./schemas.js";
14
- /** Per-role entrance intent. Values (the number to remember) count up; supporting
15
- * text rises; the primary headline reveals; decoration fades. */
16
- const ENTER = {
17
- headline: { type: "reveal", atMs: 0, durMs: 600, ease: "spring" },
18
- value: { type: "count-up", atMs: 0, durMs: 800, ease: "spring" },
19
- label: { type: "rise", atMs: 0, durMs: 500, ease: "ease-out" },
20
- sublabel: { type: "fade", atMs: 0, durMs: 500, ease: "ease-out" },
21
- logo: { type: "fade", atMs: 0, durMs: 400, ease: "ease-out" },
22
- "accent-shape": { type: "wipe", atMs: 0, durMs: 500, ease: "ease-out" },
23
- backdrop: { type: "fade", atMs: 0, durMs: 300, ease: "linear" },
24
- };
25
- /** Per-element entrance stagger (ms), applied in element order. */
26
- const STAGGER_MS = 120;
27
- /**
28
- * Build the motion plan for a laid-out beat. Entrances stagger by element order;
29
- * everything fades out together in the last ~350ms of the beat so a graphic never
30
- * hard-cuts. `durSec` is the beat length (from the ContentPlan beat).
31
- */
32
- export function planMotion(layout, durSec) {
33
- const beatMs = Math.max(0, durSec * 1000);
34
- const exitDur = Math.min(350, beatMs * 0.2);
35
- const exitAt = Math.max(0, beatMs - exitDur);
36
- const n = layout.elements.length;
37
- // Fit ALL entrances within [0, exitAt]: an entrance must finish before the
38
- // fade starts (on a short beat the nominal 800ms count-up + stagger would
39
- // otherwise run past the exit or start after the beat ends). Scale the
40
- // nominal durations + stagger by whatever factor makes the last entrance land
41
- // by exitAt. `scale === 0` (zero-length beat) yields instantaneous entrances.
42
- let nominalMaxEnd = 0;
43
- layout.elements.forEach((el, i) => {
44
- nominalMaxEnd = Math.max(nominalMaxEnd, i * STAGGER_MS + ENTER[el.role].durMs);
45
- });
46
- const scale = nominalMaxEnd > 0 && nominalMaxEnd > exitAt ? exitAt / nominalMaxEnd : 1;
47
- const elements = layout.elements.map((el, i) => {
48
- const base = ENTER[el.role];
49
- const atMs = Math.round(i * STAGGER_MS * scale);
50
- const durMs = Math.max(1, Math.round(base.durMs * scale));
51
- const enter = { ...base, atMs, durMs };
52
- const me = { elId: el.elId, enter };
53
- // Emphasis pulse only if it fully FITS between the entrance and the exit
54
- // fade (start AND end before exitAt — a pulse overrunning the fade jitters).
55
- if (n > 0 && (el.role === "value" || el.role === "headline")) {
56
- const emphAt = atMs + durMs + Math.round(150 * scale);
57
- const emphDur = Math.round(300 * scale);
58
- if (emphDur > 0 && emphAt + emphDur <= exitAt)
59
- me.emphasis = { type: "pulse", atMs: emphAt, durMs: emphDur };
60
- }
61
- if (exitDur > 0)
62
- me.exit = { type: "fade", atMs: exitAt, durMs: exitDur };
63
- return me;
64
- });
65
- return { version: GRAPHICS_PLAN_VERSION, beatId: layout.beatId, elements };
66
- }
@@ -1,261 +0,0 @@
1
- /**
2
- * Graphics-plan IR — the structure-first authoring contract (plan
3
- * 2026-07-07-structure-first-graphics-pipeline). Instead of the designer
4
- * authoring Remotion JSX blind, it produces these three inspectable,
5
- * versioned artifacts; a compiler turns them into brand-bound, animatable
6
- * Remotion. The SAME schema is the client-agent CHECKPOINT payload AND the
7
- * compiler input — no translation layer to drift.
8
- *
9
- * Split by concern so each stage boundary is a review/edit point:
10
- * ContentPlan — WHAT to say (editorial, text-owned; never pixels).
11
- * LayoutPlan — WHERE it sits (spatial structure, content-aware: element
12
- * boxes are solved CLEAR of the face keep-outs the
13
- * composition-floor already computes → text-over-face is
14
- * impossible by construction, not by prompt).
15
- * MotionPlan — HOW it animates (entrance / emphasis / exit intent).
16
- *
17
- * `styleRole` binds to brand tokens (never a raw hex/font) so off-brand
18
- * output is impossible; the compiler resolves it via the same `$brand:`
19
- * mechanism as packages/authoring/src/tools/brandTokens.ts.
20
- */
21
- import { z } from "zod";
22
- import { Region } from "../validators/composition.js";
23
- /** Bump when a field's meaning changes; the compiler + checkpoint clients
24
- * branch on it. Kept a literal so an old client sees a hard mismatch, not a
25
- * silent misread. */
26
- export const GRAPHICS_PLAN_VERSION = "gp-1";
27
- const Version = z.literal(GRAPHICS_PLAN_VERSION);
28
- /** A rect in output-frame fractions [0,1] — the SAME placement vocabulary as
29
- * the composition-floor `Rect` and the wire `Region` (reused so a plan box and
30
- * a rendered layer can never disagree about coordinates). */
31
- export const PlanRect = Region;
32
- // ── ContentPlan ────────────────────────────────────────────────────────────
33
- /**
34
- * What the beat must COMMUNICATE. An EDITORIAL vocabulary — deliberately not a list of
35
- * primitive names.
36
- *
37
- * The first six are named after primitive families, and that was the bug: the DESIGNER's
38
- * decision (which component draws this) had leaked into the PLANNER's schema. It meant the
39
- * vocabulary could only grow by adding primitive names, so it could never keep up with the
40
- * catalog — and on 2026-07-13 a brief demanding a chain-trace, comparison bars and a
41
- * three-item build got exactly ONE lower-third, because a lower-third was close to the most
42
- * the planner was ABLE to say. It was not being lazy. It had no word for what the brief wanted.
43
- *
44
- * The last three are the fix, and they name a JOB, not a picture:
45
- * the planner says "this beat must show a sequence"; the DESIGNER decides whether that is
46
- * `reasoning-trace`, `tool-call-stack`, or something it writes itself.
47
- *
48
- * Closed on purpose (the critics and the layout solver switch on it) — but closed around
49
- * editorial intent, which is a small and stable set, instead of around a 103-component catalog,
50
- * which is neither.
51
- */
52
- export const GraphicRole = z.enum([
53
- "title-card", // topic-setter / opener card
54
- "stat", // a single headline number + label
55
- "lower-third", // name/title tag over the speaker
56
- "pull-quote", // a short quoted line
57
- "hero", // big behind-subject phrase (zPlane: behind-subject)
58
- "logo-tag", // small brand mark / watermark beat
59
- // ── the beat carries an ARGUMENT, not a caption ──
60
- "enumeration", // a list of short items ("LBO modelling / VDR diligence / customer cubes")
61
- "sequence", // an ordered chain of steps — often the POINT is that it is too long
62
- "comparison", // labelled values set against each other (a benchmark, a before/after)
63
- ]);
64
- /**
65
- * The words for a beat — ALWAYS plan-owned (a text-to-image model can't spell; the Remotion code
66
- * renders these crisply). All optional; a role uses the subset it needs
67
- * (stat → value+label; title-card → headline+sub; enumeration/sequence → items; comparison → series).
68
- *
69
- * `items` and `series` exist because the plan OWNS the words, and a role it cannot supply the
70
- * words for is a role it cannot actually request. Four scalars could not carry a list or a
71
- * labelled series, so even a widened role vocabulary would have had nowhere to put its content —
72
- * the second half of the same 2026-07-13 bug, and the one that would have silently defeated the
73
- * fix for the first half.
74
- */
75
- export const Copy = z
76
- .object({
77
- headline: z.string().max(120).optional(),
78
- sub: z.string().max(200).optional(),
79
- value: z.string().max(40).optional(),
80
- label: z.string().max(80).optional(),
81
- /** Ordered short items — an `enumeration`'s bullets, a `sequence`'s steps. */
82
- items: z.array(z.string().max(80)).max(8).optional(),
83
- /**
84
- * Labelled values for a `comparison`.
85
- *
86
- * `value` is a STRING, deliberately — not `number | string`. The plan owns the words, and a
87
- * comparison's words include their units: a planner writes "10 min", "98%", "$4.2M", never
88
- * 600. A number would have to be re-unitised downstream by someone who doesn't know what it
89
- * meant.
90
- *
91
- * It is also a hard constraint: `submit_compose_plan` is a STRICT Anthropic tool
92
- * (`strict: true`, schemas.ts), and a `z.union` here becomes an `anyOf` in the tool schema.
93
- * That is what stalled the planner on 2026-07-13 — it ran, could not satisfy the schema, and
94
- * never called the tool at all. Keep every field in this schema a single concrete type.
95
- */
96
- series: z
97
- .array(z.object({ label: z.string().max(40), value: z.string().max(16) }))
98
- .max(8)
99
- .optional(),
100
- })
101
- .strict();
102
- export const ContentBeat = z
103
- .object({
104
- id: z.string().min(1),
105
- /** Clip-relative seconds. */
106
- atSec: z.number().min(0),
107
- durSec: z.number().positive(),
108
- role: GraphicRole,
109
- copy: Copy,
110
- /** Editorial WHY — the beat this graphic serves (for review + the judge). */
111
- intent: z.string().min(1).max(400),
112
- /** Higher = more important; drives drop order under budget. */
113
- priority: z.number().int().min(0).max(10).default(5),
114
- })
115
- .strict();
116
- export const ContentPlan = z
117
- .object({
118
- version: Version,
119
- beats: z.array(ContentBeat),
120
- })
121
- .strict();
122
- // ── LayoutPlan ───────────────────────────────────────────────────────────────
123
- /** The role of ONE element within a graphic — maps to a primitive slot. */
124
- export const ElementRole = z.enum([
125
- "headline", // primary large text
126
- "value", // the stat number / the one word to remember
127
- "label", // supporting text
128
- "sublabel", // secondary supporting text
129
- "logo", // brand mark
130
- "accent-shape", // decorative block/line/underline
131
- "backdrop", // solid fill (takeover cards only)
132
- ]);
133
- /** Semantic style binding → resolved to `$brand:` refs by the compiler; NEVER a
134
- * raw hex/font. This is the guarantee that on-brand is the only option.
135
- * Mapping (compiler): heading→fonts.heading+colors.text, accent→colors.accent,
136
- * body→fonts.body+colors.text, surface→colors.surface/background,
137
- * on-accent→colors.textOnAccent, on-surface→colors.textOnSurface. */
138
- export const StyleRole = z.enum([
139
- "heading",
140
- "body",
141
- "accent",
142
- "surface",
143
- "on-accent",
144
- "on-surface",
145
- ]);
146
- /** Depth plane — matches OverlayClipSource.zPlane. `behind-subject` is the
147
- * intentional hero look (the subject cut-out bites the letters). */
148
- export const ZPlane = z.enum(["front", "behind-subject"]);
149
- export const LayoutElement = z
150
- .object({
151
- elId: z.string().min(1),
152
- role: ElementRole,
153
- /** Solved CLEAR of `keepOut` (except intentional behind-subject heroes). */
154
- box: PlanRect,
155
- styleRole: StyleRole,
156
- z: ZPlane.default("front"),
157
- /** The text this element renders (from the ContentPlan). Omitted for
158
- * logo / accent-shape / backdrop. */
159
- text: z.string().max(200).optional(),
160
- /** Index into the editorial type scale (mirrors composition-floor
161
- * Treatment.typeScaleStep) — a SCALE STEP, not a raw px guess. */
162
- typeScaleStep: z.number().int().min(0).max(8).optional(),
163
- })
164
- .strict();
165
- const EPS = 1e-6;
166
- const rectsOverlapEps = (a, b) => a.x < b.x + b.w - EPS && a.x + a.w > b.x + EPS && a.y < b.y + b.h - EPS && a.y + a.h > b.y + EPS;
167
- export const LayoutPlan = z
168
- .object({
169
- version: Version,
170
- beatId: z.string().min(1),
171
- /** Output aspect context (pixels); placement itself is in [0,1] fractions. */
172
- frame: z.object({ w: z.number().positive(), h: z.number().positive() }).strict(),
173
- /** INPUT (not authored): face keep-out rects at this beat, from the
174
- * composition-floor. The layout stage MUST place `front` elements clear of
175
- * these — carried on the plan so a reviewer/compiler can verify it. */
176
- keepOut: z.array(PlanRect),
177
- /** INPUT: safe-zone insets (title-safe / action-safe fractions). */
178
- safe: z
179
- .object({
180
- titleSafe: z.number().min(0).max(1),
181
- actionSafe: z.number().min(0).max(1),
182
- })
183
- .strict(),
184
- elements: z.array(LayoutElement),
185
- /** Set when the solver could NOT place a beat's graphic legally (e.g. the
186
- * face fills the legal area). Makes a drop OBSERVABLE — distinct from a
187
- * beat that legitimately had no copy (both yield elements:[]). The producer
188
- * can surface it; the compiler skips it. */
189
- dropped: z.object({ reason: z.string().min(1) }).strict().optional(),
190
- })
191
- .strict()
192
- // The IR ENFORCES its own headline invariant: a `front` element box must be
193
- // in-frame AND clear of every face keep-out. A mis-solved OR (P4) agent-
194
- // proposed plan that puts text on the speaker FAILS parse — the guarantee is
195
- // structural, not just solver-code-dependent. behind-subject heroes are
196
- // exempt (the subject intentionally occludes them).
197
- .superRefine((plan, ctx) => {
198
- for (const el of plan.elements) {
199
- if (el.z === "behind-subject")
200
- continue;
201
- const b = el.box;
202
- if (b.x + b.w > 1 + EPS || b.y + b.h > 1 + EPS) {
203
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: `element ${el.elId} box spills past the frame`, path: ["elements"] });
204
- }
205
- for (const ko of plan.keepOut) {
206
- if (rectsOverlapEps(b, ko)) {
207
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: `element ${el.elId} overlaps a face keep-out (text on the speaker)`, path: ["elements"] });
208
- }
209
- }
210
- }
211
- });
212
- // ── MotionPlan ───────────────────────────────────────────────────────────────
213
- export const EnterType = z.enum(["reveal", "fade", "rise", "count-up", "wipe"]);
214
- export const EmphasisType = z.enum(["pulse", "underline", "color-shift"]);
215
- export const ExitType = z.enum(["fade", "fall", "wipe", "cut"]);
216
- /** Ease vocabulary → compiler maps to real spring/interpolate. Named, not raw
217
- * bezier/ms, so the brand's motion pace stays a decision not a magic number. */
218
- export const Ease = z.enum(["spring", "ease-out", "ease-in-out", "linear"]);
219
- export const EnterMotion = z
220
- .object({
221
- type: EnterType,
222
- atMs: z.number().min(0),
223
- durMs: z.number().positive(),
224
- ease: Ease.default("spring"),
225
- /** Per-child stagger (ms) for multi-part reveals. */
226
- stagger: z.number().min(0).optional(),
227
- })
228
- .strict();
229
- export const EmphasisMotion = z
230
- .object({ type: EmphasisType, atMs: z.number().min(0), durMs: z.number().positive() })
231
- .strict();
232
- export const ExitMotion = z
233
- .object({ type: ExitType, atMs: z.number().min(0), durMs: z.number().positive() })
234
- .strict();
235
- export const MotionElement = z
236
- .object({
237
- elId: z.string().min(1),
238
- enter: EnterMotion,
239
- emphasis: EmphasisMotion.optional(),
240
- exit: ExitMotion.optional(),
241
- })
242
- .strict();
243
- export const MotionPlan = z
244
- .object({
245
- version: Version,
246
- beatId: z.string().min(1),
247
- elements: z.array(MotionElement),
248
- })
249
- .strict();
250
- // ── Bundle ───────────────────────────────────────────────────────────────────
251
- /** The full graphics plan for a compose run: one ContentPlan, and a
252
- * Layout+Motion pair per beat (keyed by beatId). This is the object a
253
- * checkpoint returns and the compiler consumes. */
254
- export const GraphicsPlan = z
255
- .object({
256
- version: Version,
257
- content: ContentPlan,
258
- layouts: z.array(LayoutPlan),
259
- motions: z.array(MotionPlan),
260
- })
261
- .strict();