@cueframe/kernel 0.2.1 → 0.2.3

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 (332) hide show
  1. package/dist/_members/animate/index.d.ts +8 -2
  2. package/dist/_members/animate/layout/FlexLayout.d.ts +69 -0
  3. package/dist/_members/animate/layout/fit.d.ts +44 -0
  4. package/dist/_members/animate/layout/index.d.ts +3 -0
  5. package/dist/_members/animate/layout/solveFlex.d.ts +70 -0
  6. package/dist/_members/animate/media/MediaTileScene.d.ts +65 -0
  7. package/dist/_members/animate/media/recipes.d.ts +61 -0
  8. package/dist/_members/animate/scene/FocusPass.d.ts +76 -0
  9. package/dist/_members/animate/scene/UnlitPlane.d.ts +45 -0
  10. package/dist/_members/animate/scene/__oracle__/cssProjection.d.ts +24 -0
  11. package/dist/_members/animate/scene/assets.d.ts +21 -0
  12. package/dist/_members/animate/scene/backdrop.d.ts +7 -0
  13. package/dist/_members/animate/scene/coordinates.d.ts +58 -0
  14. package/dist/_members/animate/scene/deviceOpacity.d.ts +18 -0
  15. package/dist/_members/animate/scene/errors.d.ts +14 -0
  16. package/dist/_members/animate/scene/finishing.d.ts +69 -0
  17. package/dist/_members/animate/scene/finishingMath.d.ts +60 -0
  18. package/dist/_members/animate/scene/finishingPass.d.ts +35 -0
  19. package/dist/_members/animate/scene/focusBlur.d.ts +56 -0
  20. package/dist/_members/animate/scene/focusResources.d.ts +190 -0
  21. package/dist/_members/animate/scene/focusShaders.d.ts +68 -0
  22. package/dist/_members/animate/scene/fontReadiness.d.ts +27 -0
  23. package/dist/_members/animate/scene/grainNoise.d.ts +118 -0
  24. package/dist/_members/animate/scene/index.d.ts +19 -0
  25. package/dist/_members/animate/scene/internal.d.ts +29 -0
  26. package/dist/_members/animate/scene/planeFit.d.ts +46 -0
  27. package/dist/_members/animate/scene/preparedWorldText.d.ts +25 -0
  28. package/dist/_members/animate/scene/rasterCache.d.ts +30 -0
  29. package/dist/_members/animate/scene/rasterReadiness.d.ts +33 -0
  30. package/dist/_members/animate/scene/readiness.d.ts +69 -0
  31. package/dist/_members/animate/scene/redraw.d.ts +10 -0
  32. package/dist/_members/animate/scene/render.d.ts +9 -0
  33. package/dist/_members/animate/scene/scaling.d.ts +13 -0
  34. package/dist/_members/animate/scene/text.d.ts +40 -0
  35. package/dist/_members/animate/scene/textLayout.d.ts +78 -0
  36. package/dist/_members/animate/scene/textureImageSize.d.ts +4 -0
  37. package/dist/_members/animate/scene/useSceneImageTexture.d.ts +21 -0
  38. package/dist/_members/animate/scene/useWorldTextTexture.d.ts +21 -0
  39. package/dist/_members/animate/scene/v2/MeasuredPlaneGeometry.d.ts +7 -0
  40. package/dist/_members/animate/scene/v2/PhotographicStudioRig.d.ts +11 -0
  41. package/dist/_members/animate/scene/v2/PreparedSceneShotV1.d.ts +12 -0
  42. package/dist/_members/animate/scene/v2/SceneShotV2.d.ts +59 -0
  43. package/dist/_members/animate/scene/v2/builders.d.ts +170 -0
  44. package/dist/_members/animate/scene/v2/finishes.d.ts +152 -0
  45. package/dist/_members/animate/scene/v2/lighting.d.ts +119 -0
  46. package/dist/_members/animate/scene/v2/observePmremTargets.d.ts +4 -0
  47. package/dist/_members/animate/scene/v2/preparationFacts.d.ts +32 -0
  48. package/dist/_members/animate/scene/v2/preparedSurface.d.ts +17 -0
  49. package/dist/_members/animate/scene/v2/projectedResolution.d.ts +2 -0
  50. package/dist/_members/animate/scene/v2/renderTargetObserver.d.ts +5 -0
  51. package/dist/_members/animate/scene/v2/runtimeAllocations.d.ts +55 -0
  52. package/dist/_members/animate/scene/v2/shadow.d.ts +23 -0
  53. package/dist/_members/animate/scene/v2/slabGeometry.d.ts +134 -0
  54. package/dist/_members/animate/scene/v2/slots.d.ts +73 -0
  55. package/dist/_members/animate/scene/v2/videoBinding.d.ts +39 -0
  56. package/dist/_members/animate/scene/worldBounds.d.ts +19 -0
  57. package/dist/_members/animate/scene/worldTextRaster.d.ts +87 -0
  58. package/dist/_members/animate/scene/worldTextTexture.d.ts +32 -0
  59. package/dist/_members/animate/stage/PerspectiveStage.d.ts +73 -0
  60. package/dist/_members/animate/stage/camera.d.ts +143 -0
  61. package/dist/_members/animate/stage/dof.d.ts +9 -0
  62. package/dist/_members/animate/stage/index.d.ts +6 -0
  63. package/dist/_members/animate/stage/presets.d.ts +17 -0
  64. package/dist/_members/animate/three/DeviceMesh.d.ts +256 -0
  65. package/dist/_members/animate/three/SceneCameraRig.d.ts +12 -0
  66. package/dist/_members/animate/three/StageCameraRig.d.ts +7 -0
  67. package/dist/_members/animate/three/StudioRig.d.ts +228 -0
  68. package/dist/_members/animate/three/ThreeCanvas.d.ts +22 -0
  69. package/dist/_members/animate/three/defaultScreen.d.ts +23 -0
  70. package/dist/_members/animate/three/index.d.ts +7 -1
  71. package/dist/_members/animate/three/textureLifecycle.d.ts +29 -0
  72. package/dist/_members/animate/three/toneMapping.d.ts +113 -0
  73. package/dist/_members/animate/three/useImageTexture.d.ts +17 -0
  74. package/dist/_members/authoring/index.d.ts +2 -0
  75. package/dist/_members/authoring/scene/index.d.ts +6 -0
  76. package/dist/_members/authoring/scene/materialize.d.ts +47 -0
  77. package/dist/_members/authoring/scene/validate.d.ts +80 -0
  78. package/dist/_members/authoring/scene/wrapper.d.ts +41 -0
  79. package/dist/_members/component-runtime/allowedImports.d.ts +3 -0
  80. package/dist/_members/component-runtime/allowedImports.d.ts.map +1 -0
  81. package/dist/_members/component-runtime/bake.d.ts +8 -0
  82. package/dist/_members/component-runtime/bake.d.ts.map +1 -1
  83. package/dist/_members/component-runtime/browserFirewall.d.ts +7 -1
  84. package/dist/_members/component-runtime/browserFirewall.d.ts.map +1 -1
  85. package/dist/_members/component-runtime/browserOptions.d.ts +59 -3
  86. package/dist/_members/component-runtime/browserOptions.d.ts.map +1 -1
  87. package/dist/_members/component-runtime/canonicalIdentity.d.ts +14 -0
  88. package/dist/_members/component-runtime/canonicalIdentity.d.ts.map +1 -1
  89. package/dist/_members/component-runtime/contracts.d.ts +341 -1
  90. package/dist/_members/component-runtime/contracts.d.ts.map +1 -1
  91. package/dist/_members/component-runtime/fixtures/imageTileDriftWall.d.ts +5 -0
  92. package/dist/_members/component-runtime/fixtures/imageTileDriftWall.d.ts.map +1 -0
  93. package/dist/_members/component-runtime/fixtures/mediaTileMixed.d.ts +5 -0
  94. package/dist/_members/component-runtime/fixtures/mediaTileMixed.d.ts.map +1 -0
  95. package/dist/_members/component-runtime/fixtures/mediaTileVideo.d.ts +8 -0
  96. package/dist/_members/component-runtime/fixtures/mediaTileVideo.d.ts.map +1 -0
  97. package/dist/_members/component-runtime/importPolicy.d.ts +3 -2
  98. package/dist/_members/component-runtime/importPolicy.d.ts.map +1 -1
  99. package/dist/_members/component-runtime/index.d.ts +3 -0
  100. package/dist/_members/component-runtime/index.d.ts.map +1 -1
  101. package/dist/_members/component-runtime/livePreviewProxy.d.ts +7 -0
  102. package/dist/_members/component-runtime/livePreviewProxy.d.ts.map +1 -0
  103. package/dist/_members/component-runtime/localRoot.d.ts +37 -0
  104. package/dist/_members/component-runtime/localRoot.d.ts.map +1 -0
  105. package/dist/_members/component-runtime/mediaResolution.d.ts +25 -0
  106. package/dist/_members/component-runtime/mediaResolution.d.ts.map +1 -0
  107. package/dist/_members/component-runtime/render.d.ts +151 -13
  108. package/dist/_members/component-runtime/render.d.ts.map +1 -1
  109. package/dist/_members/component-runtime/renderDiagnostics.d.ts +14 -0
  110. package/dist/_members/component-runtime/renderDiagnostics.d.ts.map +1 -0
  111. package/dist/_members/component-runtime/sceneAdmission.d.ts +47 -0
  112. package/dist/_members/component-runtime/sceneAdmission.d.ts.map +1 -0
  113. package/dist/_members/component-runtime/sourceWorkspace.d.ts +8 -0
  114. package/dist/_members/component-runtime/sourceWorkspace.d.ts.map +1 -1
  115. package/dist/_members/component-runtime/webglProbe.d.ts +191 -0
  116. package/dist/_members/component-runtime/webglProbe.d.ts.map +1 -0
  117. package/dist/_members/composition/fonts/bundledFaces.d.ts +150 -0
  118. package/dist/_members/composition/fonts/captionFaces.d.ts +268 -0
  119. package/dist/_members/composition/fonts.d.ts +11 -4
  120. package/dist/_members/composition/graphics-plan/schemas.d.ts +4 -4
  121. package/dist/_members/composition/ops/types.d.ts +1 -1
  122. package/dist/_members/composition/primitive-catalog/types.d.ts +1 -0
  123. package/dist/_members/composition/projection/behind-readiness.d.ts +3 -0
  124. package/dist/_members/composition/projection/brandKit.d.ts +6 -0
  125. package/dist/_members/composition/projection/composition-floor.d.ts +2 -1
  126. package/dist/_members/composition/scene/animation.d.ts +25 -0
  127. package/dist/_members/composition/scene/budget.d.ts +29 -0
  128. package/dist/_members/composition/scene/budgetPolicy.d.mts +13 -0
  129. package/dist/_members/composition/scene/clipRules.d.ts +119 -0
  130. package/dist/_members/composition/scene/constraints.d.ts +61 -0
  131. package/dist/_members/composition/scene/device.d.ts +21 -0
  132. package/dist/_members/composition/scene/examples.d.ts +11 -0
  133. package/dist/_members/composition/scene/index.d.ts +11 -0
  134. package/dist/_members/composition/scene/photographicRig.d.ts +242 -0
  135. package/dist/_members/composition/scene/preparedRender.d.ts +239 -0
  136. package/dist/_members/composition/scene/resolution.d.ts +178 -0
  137. package/dist/_members/composition/scene/schema.d.ts +351 -0
  138. package/dist/_members/composition/scene/videoSchedule.d.ts +43 -0
  139. package/dist/_members/composition/validators/brandKit.d.ts +1 -0
  140. package/dist/_members/composition/validators/render.d.ts +2 -0
  141. package/dist/_members/composition-ops/index.d.ts +45 -0
  142. package/dist/_members/composition-ops/opRecorder.d.ts +1 -1
  143. package/dist/_members/core/render/compositionRender.d.ts +41 -9
  144. package/dist/_members/core/render/index.d.ts +9 -2
  145. package/dist/_members/core/render/sceneCaptureIdentity.d.ts +14 -0
  146. package/dist/_members/core/render/sceneShotPlan.d.ts +142 -0
  147. package/dist/_members/core/render/sceneShotPreparation.d.ts +57 -0
  148. package/dist/_members/core/render/slabDescriptor.d.ts +21 -0
  149. package/dist/_members/core/render/trackProjection.d.ts +33 -0
  150. package/dist/_members/core/render/types.d.ts +142 -0
  151. package/dist/_members/errors/registry.d.ts +6 -0
  152. package/dist/_members/mcp/adapter.d.ts +5 -0
  153. package/dist/_members/mcp/generated/sceneContract.d.ts +155 -0
  154. package/dist/_members/mcp/sceneShot.d.ts +38 -0
  155. package/dist/_members/mcp/sceneShotExample.d.ts +22 -0
  156. package/dist/_members/media-model/api.d.ts +1 -0
  157. package/dist/_members/media-model/media-kind.d.ts +1 -1
  158. package/dist/_members/media-model/testing/mediaStoreContract.d.ts +1 -1
  159. package/dist/_members/primitives/effects/index.d.ts +1 -0
  160. package/dist/_members/primitives/effects/stage-camera/config.d.ts +50 -0
  161. package/dist/_members/primitives/effects/stage-camera/index.d.ts +31 -0
  162. package/dist/_members/primitives/layouts/flex-layout/config.d.ts +73 -0
  163. package/dist/_members/primitives/layouts/flex-layout/index.d.ts +4 -0
  164. package/dist/_members/primitives/layouts/index.d.ts +1 -0
  165. package/dist/_members/primitives/layouts/picture-in-picture/config.d.ts +1 -1
  166. package/dist/_members/primitives/lib/frameScale.d.ts +4 -0
  167. package/dist/_members/primitives/lib/index.d.ts +1 -0
  168. package/dist/_members/primitives/lib/palette.d.ts +30 -30
  169. package/dist/_members/primitives/lib/text/contrast.d.ts +2 -1
  170. package/dist/_members/primitives/lib/text/spec.d.ts +0 -8
  171. package/dist/_members/primitives/lib/types.d.ts +2 -0
  172. package/dist/_members/primitives/scenes/device-showcase/config.d.ts +41 -0
  173. package/dist/_members/primitives/scenes/device-showcase/index.d.ts +36 -0
  174. package/dist/_members/primitives/scenes/hero-device-assemble/config.d.ts +1 -0
  175. package/dist/_members/primitives/scenes/hero-device-assemble/index.d.ts +2 -1
  176. package/dist/_members/primitives/scenes/index.d.ts +1 -0
  177. package/dist/_members/primitives/ui-blocks/badge-pop/config.d.ts +1 -1
  178. package/dist/_members/primitives/ui-blocks/device-mockup-zoom/config.d.ts +1 -0
  179. package/dist/_members/primitives/ui-blocks/device-mockup-zoom/index.d.ts +2 -1
  180. package/dist/_members/primitives/ui-blocks/terminal-simulator/config.d.ts +1 -1
  181. package/dist/_members/primitives/ui-blocks/toast-notification/config.d.ts +1 -1
  182. package/dist/_members/render-harness/cardAssetAdmission.d.ts.map +1 -1
  183. package/dist/_members/render-harness/cardRender.d.ts.map +1 -1
  184. package/dist/_members/render-harness/css-tree-subpaths.d.ts +11 -0
  185. package/dist/_members/render-harness/extractSegments.d.ts +1 -0
  186. package/dist/_members/render-harness/extractSegments.d.ts.map +1 -1
  187. package/dist/_members/render-harness/imageHeader.d.ts +14 -0
  188. package/dist/_members/render-harness/imageHeader.d.ts.map +1 -0
  189. package/dist/_members/render-harness/index.d.ts +6 -0
  190. package/dist/_members/render-harness/index.d.ts.map +1 -1
  191. package/dist/_members/render-harness/materializeSources.d.ts +46 -2
  192. package/dist/_members/render-harness/materializeSources.d.ts.map +1 -1
  193. package/dist/_members/render-harness/nodeScenePreparation.d.ts +97 -0
  194. package/dist/_members/render-harness/nodeScenePreparation.d.ts.map +1 -0
  195. package/dist/_members/render-harness/remotion-runtime.d.ts +16 -2
  196. package/dist/_members/render-harness/renderInputAssets.d.ts +1 -1
  197. package/dist/_members/render-harness/renderInputAssets.d.ts.map +1 -1
  198. package/dist/_members/render-harness/resolveAssets.d.ts +2 -2
  199. package/dist/_members/render-harness/resolveAssets.d.ts.map +1 -1
  200. package/dist/_members/render-harness/sceneShotAssets.d.ts +17 -0
  201. package/dist/_members/render-harness/sceneShotAssets.d.ts.map +1 -0
  202. package/dist/animate/preparation-facts.d.ts +1 -0
  203. package/dist/animate/preparation-facts.js +22 -0
  204. package/dist/animate.js +336 -1005
  205. package/dist/authoring/build-tools.js +7 -6
  206. package/dist/authoring/context.js +5 -4
  207. package/dist/authoring/prompts.js +1 -1
  208. package/dist/authoring/scene.d.ts +1 -0
  209. package/dist/authoring/scene.js +50 -0
  210. package/dist/authoring/tools.js +6 -5
  211. package/dist/authoring.js +49 -29
  212. package/dist/chunk-2L7PYYJK.js +23 -0
  213. package/dist/{chunk-ZN6P3KOJ.js → chunk-32TH76H3.js} +2 -2
  214. package/dist/chunk-5DJ3IEJR.js +4424 -0
  215. package/dist/chunk-6BVVCRRD.js +26488 -0
  216. package/dist/{chunk-DQKSCHFC.js → chunk-6EWRIAZA.js} +187 -66
  217. package/dist/{chunk-YQ7FFW3G.js → chunk-6VWICHOZ.js} +26 -5
  218. package/dist/{chunk-2PGLNTB7.js → chunk-A74FZCPY.js} +45 -5
  219. package/dist/{chunk-C5SEPOWD.js → chunk-AS5EXBNS.js} +1792 -707
  220. package/dist/{chunk-BKHGL4MB.js → chunk-B3GSTQLR.js} +341 -274
  221. package/dist/chunk-BVA3537Z.js +63 -0
  222. package/dist/{chunk-DHKQ47Q6.js → chunk-DAARYRNT.js} +6 -1
  223. package/dist/chunk-DQLYWNLC.js +2063 -0
  224. package/dist/chunk-E6WHXIDF.js +3619 -0
  225. package/dist/{chunk-NOEBAV2G.js → chunk-E7GIZEPS.js} +1 -1
  226. package/dist/{chunk-M2TLRXEO.js → chunk-EXY4JJPH.js} +1 -1
  227. package/dist/{chunk-GEGRJKKO.js → chunk-F2DJL7P7.js} +1 -1
  228. package/dist/{chunk-AWT3P5ZN.js → chunk-FVDFPJHT.js} +1 -1
  229. package/dist/{chunk-EMGFZ3PR.js → chunk-FWSJLHSV.js} +5 -1
  230. package/dist/{chunk-TMIBBD5E.js → chunk-I5QWBM3M.js} +280 -113
  231. package/dist/{chunk-IBMJ33EL.js → chunk-I5RX2QZT.js} +1 -1
  232. package/dist/{chunk-4FOOBSEE.js → chunk-J3DIUG24.js} +1 -0
  233. package/dist/{chunk-AD5HWBCE.js → chunk-JX53CVJV.js} +14 -5
  234. package/dist/{chunk-LNBVTDFR.js → chunk-L2AHS3AW.js} +1 -1
  235. package/dist/{chunk-BDMTUEEZ.js → chunk-LT4PWSR2.js} +2 -2
  236. package/dist/chunk-MH3UPKWR.js +3415 -0
  237. package/dist/{chunk-RFXR7ATW.js → chunk-NUKDEOK6.js} +13 -1
  238. package/dist/{chunk-IJ7PVJTK.js → chunk-ODUWCQI3.js} +3 -2
  239. package/dist/chunk-QAGGJHAF.js +16 -0
  240. package/dist/chunk-QS36DMFG.js +332 -0
  241. package/dist/{chunk-G5BFI32U.js → chunk-RAXHCRVV.js} +1 -1
  242. package/dist/{chunk-BIBYZJL3.js → chunk-RL5SO653.js} +3 -3
  243. package/dist/{chunk-ZSZABOE5.js → chunk-S5H6GH6M.js} +1 -1
  244. package/dist/{chunk-EEXCDFY5.js → chunk-SD25VQDE.js} +1 -1
  245. package/dist/{chunk-Y3QGYASW.js → chunk-SX523NDS.js} +14 -14
  246. package/dist/chunk-TARKDVP6.js +430 -0
  247. package/dist/{chunk-IHFREGFA.js → chunk-TCHPRGC5.js} +18 -2
  248. package/dist/{chunk-ZCAQHNPI.js → chunk-UKGNHZS4.js} +1 -1
  249. package/dist/{chunk-KU376ELE.js → chunk-UY77TMKD.js} +31 -44
  250. package/dist/chunk-VKATKWWR.js +1462 -0
  251. package/dist/{chunk-CX2IIQ4R.js → chunk-W2245F6G.js} +29 -29
  252. package/dist/{chunk-XHUYWVYK.js → chunk-WBNFSG6T.js} +1 -1
  253. package/dist/chunk-WIHXXF3X.js +221 -0
  254. package/dist/{chunk-XVBOSPZI.js → chunk-X74EEFXV.js} +6 -6
  255. package/dist/{chunk-7KEUL3FI.js → chunk-XF2QMKRG.js} +9 -1
  256. package/dist/{chunk-HFC3MKXA.js → chunk-Y4HPN4BC.js} +1 -0
  257. package/dist/{chunk-6XI57FZZ.js → chunk-YFSBFCXO.js} +1022 -46
  258. package/dist/{chunk-6ID2J64H.js → chunk-YHC3RXS7.js} +162 -25
  259. package/dist/{chunk-KKEY5MIW.js → chunk-ZS3A3QUM.js} +16 -16
  260. package/dist/{chunk-LQUWKBST.js → chunk-ZVG446DJ.js} +139 -10
  261. package/dist/component-runtime/browserOptions.js +14 -3
  262. package/dist/component-runtime/contracts.js +35 -3
  263. package/dist/component-runtime/identity/browser.js +1 -1
  264. package/dist/component-runtime/identity.js +2 -2
  265. package/dist/component-runtime/importPolicy.js +2 -2
  266. package/dist/component-runtime/mediaResolution.d.ts +1 -0
  267. package/dist/component-runtime/mediaResolution.js +11 -0
  268. package/dist/component-runtime/render.js +38 -5
  269. package/dist/component-runtime.js +118 -14
  270. package/dist/compose.js +27 -21
  271. package/dist/composition/fonts.js +64 -67
  272. package/dist/composition/graphics-plan.js +3 -2
  273. package/dist/composition/ops.js +4 -3
  274. package/dist/composition/primitive-catalog.js +1 -1
  275. package/dist/composition/projection.js +10 -3
  276. package/dist/composition/scene/budget-policy.d.ts +1 -0
  277. package/dist/composition/scene/budget-policy.js +17 -0
  278. package/dist/composition/scene/schema.json +2757 -0
  279. package/dist/composition/scene.d.ts +1 -0
  280. package/dist/composition/scene.js +275 -0
  281. package/dist/composition/validators.js +3 -2
  282. package/dist/composition-ops.js +103 -13
  283. package/dist/composition.js +12 -5
  284. package/dist/{context-4GSDBFT3.js → context-IUPQ54V4.js} +5 -4
  285. package/dist/core/render.js +54 -3
  286. package/dist/core/select.js +2 -2
  287. package/dist/core.js +6 -3
  288. package/dist/director/ai-sdk.js +3 -3
  289. package/dist/director/domain.js +2 -2
  290. package/dist/director.js +3 -3
  291. package/dist/errors.js +1 -1
  292. package/dist/mcp/adapter.js +4 -4
  293. package/dist/mcp/core.js +1 -1
  294. package/dist/mcp/curation.js +1 -1
  295. package/dist/mcp/server.js +4 -4
  296. package/dist/mcp.js +4 -4
  297. package/dist/media-model/media-kind.js +2 -0
  298. package/dist/media-model/testing.js +16 -11
  299. package/dist/media-model.js +1 -1
  300. package/dist/nle-export.js +27 -21
  301. package/dist/primitives/backgrounds.js +2 -2
  302. package/dist/primitives/captions.js +21 -11
  303. package/dist/primitives/effects.js +14 -4
  304. package/dist/primitives/graphics.json +3 -0
  305. package/dist/primitives/hero-text.js +4 -3
  306. package/dist/primitives/layouts.js +9 -2
  307. package/dist/primitives/lib/frameScale.d.ts +1 -0
  308. package/dist/primitives/lib/frameScale.js +11 -0
  309. package/dist/primitives/lib/index.js +18 -10
  310. package/dist/primitives/lib/palette.js +1 -1
  311. package/dist/primitives/lib/text/contrast.js +2 -1
  312. package/dist/primitives/lib/text/typeface.js +1 -1
  313. package/dist/primitives/lib.js +18 -10
  314. package/dist/primitives/params-required.json +3 -0
  315. package/dist/primitives/scenes.js +12 -3
  316. package/dist/primitives/text.js +5 -5
  317. package/dist/primitives/transitions.js +2 -2
  318. package/dist/primitives/ui-blocks.js +7 -6
  319. package/dist/primitives/version-map.json +5 -2
  320. package/dist/primitives.js +27 -20
  321. package/dist/render-harness/cardAssetAdmission.js +2 -2
  322. package/dist/render-harness/renderInputAssets.js +2 -2
  323. package/dist/render-harness.js +876 -126
  324. package/package.json +51 -17
  325. package/dist/_members/animate/three/drei.d.ts +0 -6
  326. package/dist/_members/component-runtime/fixtures/webgpuTiledRefraction.d.ts +0 -9
  327. package/dist/_members/component-runtime/fixtures/webgpuTiledRefraction.d.ts.map +0 -1
  328. package/dist/chunk-4JRUGT2Y.js +0 -544
  329. package/dist/chunk-5OTQ7M43.js +0 -718
  330. package/dist/chunk-CGHTMZNC.js +0 -6
  331. package/dist/chunk-QBKDEO7J.js +0 -9521
  332. /package/dist/{chunk-H5LMJKZU.js → chunk-JVDUSOYG.js} +0 -0
@@ -3,6 +3,10 @@ import {
3
3
  buildEasedZooms,
4
4
  buildPannedCenters
5
5
  } from "./chunk-QH3YI3ND.js";
6
+ import {
7
+ flattenCompoundClips,
8
+ hasCompoundClips
9
+ } from "./chunk-QISFYLBB.js";
6
10
  import {
7
11
  DOMINANCE_WEIGHTS,
8
12
  ENTER_SEC,
@@ -20,11 +24,7 @@ import {
20
24
  scoreAndRank,
21
25
  segmentShots,
22
26
  stabilizeSelectionHysteresis
23
- } from "./chunk-LNBVTDFR.js";
24
- import {
25
- flattenCompoundClips,
26
- hasCompoundClips
27
- } from "./chunk-QISFYLBB.js";
27
+ } from "./chunk-L2AHS3AW.js";
28
28
  import {
29
29
  compositionHasVo,
30
30
  roleDefaultGainDb
@@ -36,7 +36,856 @@ import {
36
36
  import {
37
37
  CueframeError,
38
38
  encodeError
39
- } from "./chunk-4FOOBSEE.js";
39
+ } from "./chunk-J3DIUG24.js";
40
+ import {
41
+ bundledFontFaceExists,
42
+ mergedCaptionFaceIssues,
43
+ unrenderableFaceField
44
+ } from "./chunk-TARKDVP6.js";
45
+ import {
46
+ SCENE_CAPTURE_IDENTITY_FIELDS_V1,
47
+ SCENE_PRESET_TRIANGLES,
48
+ SCENE_SLAB_CONTENT_FACE_TRIANGLES,
49
+ SCENE_SLAB_CONTENT_OFFSET,
50
+ collectSceneClipIssues,
51
+ evaluateScene,
52
+ evaluateSceneSeparationV2,
53
+ isSceneShotClip,
54
+ parseSceneShotSpecV2,
55
+ prepareSceneVideoScheduleV1,
56
+ sceneFullMipLevels,
57
+ sceneTextureBytes,
58
+ selectSceneBakeScale
59
+ } from "./chunk-MH3UPKWR.js";
60
+ import {
61
+ SCENE_CONTEXT_GL_BUDGET_BYTES,
62
+ SCENE_MAX_TRIANGLES,
63
+ SCENE_SURFACE_TEXTURE_BUDGET_BYTES
64
+ } from "./chunk-2L7PYYJK.js";
65
+
66
+ // ../execution/core/src/render/sceneCaptureIdentity.ts
67
+ var INTENT_FIELDS = [
68
+ "componentId",
69
+ "sourceVersionId",
70
+ "params",
71
+ "assetBindings",
72
+ "layoutWidth",
73
+ "layoutHeight",
74
+ "bakeScale",
75
+ "captureFrame",
76
+ "durationInFrames",
77
+ "fps",
78
+ "seed",
79
+ "brandFacts",
80
+ "fontFacts",
81
+ "mediaFacts",
82
+ "rasterWidth",
83
+ "rasterHeight",
84
+ "expectedDeviceScaleFactor",
85
+ "runtimeIdentity",
86
+ "dependencyIdentity",
87
+ "requestedGlBackend",
88
+ "rasterAffectingFlags"
89
+ ];
90
+ var SCENE_CAPTURE_IDENTITY_FIELDS = SCENE_CAPTURE_IDENTITY_FIELDS_V1;
91
+ var SceneCaptureIdentityRefusal = class extends Error {
92
+ constructor(path, message) {
93
+ super(message);
94
+ this.path = path;
95
+ this.name = "SceneCaptureIdentityRefusal";
96
+ }
97
+ path;
98
+ };
99
+ function canonical(value) {
100
+ if (Array.isArray(value)) return value.map(canonical);
101
+ if (value !== null && typeof value === "object") {
102
+ return Object.fromEntries(
103
+ Object.keys(value).sort().map((key) => [key, canonical(value[key])])
104
+ );
105
+ }
106
+ return value;
107
+ }
108
+ function canonicalSceneJsonV1(value, path = "value") {
109
+ assertJson(value, path);
110
+ return JSON.stringify(canonical(value));
111
+ }
112
+ function assertJson(value, path) {
113
+ if (value === null || typeof value === "string" || typeof value === "boolean") return;
114
+ if (typeof value === "number") {
115
+ if (Number.isFinite(value)) return;
116
+ throw new SceneCaptureIdentityRefusal(path, `${path} must be finite.`);
117
+ }
118
+ if (Array.isArray(value)) {
119
+ value.forEach((entry, index) => assertJson(entry, `${path}.${index}`));
120
+ return;
121
+ }
122
+ if (typeof value === "object") {
123
+ for (const [key, entry] of Object.entries(value)) assertJson(entry, `${path}.${key}`);
124
+ return;
125
+ }
126
+ throw new SceneCaptureIdentityRefusal(path, `${path} must be canonical JSON.`);
127
+ }
128
+ function normalizedRate(value, path = "fps") {
129
+ const fps = value;
130
+ if (!fps || typeof fps !== "object" || Array.isArray(fps) || Object.keys(fps).length !== 2 || Object.keys(fps).some((key) => key !== "num" && key !== "den") || !Number.isSafeInteger(fps.num) || !Number.isSafeInteger(fps.den) || fps.num <= 0 || fps.den <= 0) throw new SceneCaptureIdentityRefusal(path, `${path} must be an exact positive safe-integer rational.`);
131
+ const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
132
+ const divisor = gcd(fps.num, fps.den);
133
+ return { num: fps.num / divisor, den: fps.den / divisor };
134
+ }
135
+ function parseSceneComponentCaptureIntentV1(value) {
136
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new SceneCaptureIdentityRefusal("captureIntent", "captureIntent must be an object.");
137
+ const record = value;
138
+ const allowed = new Set(INTENT_FIELDS);
139
+ const unknown = Object.keys(record).find((key) => !allowed.has(key));
140
+ if (unknown) throw new SceneCaptureIdentityRefusal(unknown, `Unknown capture intent field ${unknown}.`);
141
+ for (const field of INTENT_FIELDS) if (!(field in record)) throw new SceneCaptureIdentityRefusal(field, `Missing capture intent field ${field}.`);
142
+ for (const field of ["params", "assetBindings", "brandFacts", "fontFacts", "mediaFacts", "rasterAffectingFlags"]) assertJson(record[field], field);
143
+ for (const field of ["layoutWidth", "layoutHeight", "durationInFrames", "rasterWidth", "rasterHeight"]) if (!Number.isSafeInteger(record[field]) || record[field] <= 0) throw new SceneCaptureIdentityRefusal(field, `${field} must be a positive safe integer.`);
144
+ if (!Number.isSafeInteger(record.captureFrame) || record.captureFrame < 0 || record.captureFrame >= record.durationInFrames) throw new SceneCaptureIdentityRefusal("captureFrame", "captureFrame must be within component duration.");
145
+ if (record.bakeScale !== 2 && record.bakeScale !== 3) throw new SceneCaptureIdentityRefusal("bakeScale", "bakeScale must be 2 or 3.");
146
+ if (record.expectedDeviceScaleFactor !== record.bakeScale) throw new SceneCaptureIdentityRefusal("expectedDeviceScaleFactor", "Expected page DPR must equal selected bakeScale.");
147
+ if (record.rasterWidth !== record.layoutWidth * record.bakeScale || record.rasterHeight !== record.layoutHeight * record.bakeScale) throw new SceneCaptureIdentityRefusal("rasterWidth", "Raster dimensions must equal layout multiplied by bakeScale.");
148
+ for (const field of ["componentId", "sourceVersionId", "seed", "runtimeIdentity", "dependencyIdentity", "requestedGlBackend"]) if (typeof record[field] !== "string" || !record[field].length) throw new SceneCaptureIdentityRefusal(field, `${field} must be a non-empty string.`);
149
+ if (!/^[a-f0-9]{64}$/.test(record.sourceVersionId)) throw new SceneCaptureIdentityRefusal("sourceVersionId", "sourceVersionId must be a lowercase SHA-256 digest.");
150
+ return { ...record, fps: normalizedRate(record.fps) };
151
+ }
152
+ var integerFields = /* @__PURE__ */ new Set([
153
+ "layoutWidth",
154
+ "layoutHeight",
155
+ "captureFrame",
156
+ "durationInFrames",
157
+ "rasterWidth",
158
+ "rasterHeight"
159
+ ]);
160
+ var jsonFields = /* @__PURE__ */ new Set([
161
+ "params",
162
+ "assetBindings",
163
+ "brandFacts",
164
+ "fontFacts",
165
+ "mediaFacts",
166
+ "rasterAffectingFlags"
167
+ ]);
168
+ function parseSceneComponentCaptureIdentityV1(value) {
169
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
170
+ throw new SceneCaptureIdentityRefusal("captureIdentity", "captureIdentity must be an object.");
171
+ }
172
+ const record = value;
173
+ const allowed = new Set(SCENE_CAPTURE_IDENTITY_FIELDS);
174
+ const unknown = Object.keys(record).find((key) => !allowed.has(key));
175
+ if (unknown) throw new SceneCaptureIdentityRefusal(unknown, `Unknown capture identity field ${unknown}.`);
176
+ for (const field of SCENE_CAPTURE_IDENTITY_FIELDS) {
177
+ if (!(field in record)) throw new SceneCaptureIdentityRefusal(field, `Missing capture identity field ${field}.`);
178
+ const entry = record[field];
179
+ if (jsonFields.has(field)) assertJson(entry, field);
180
+ else if (integerFields.has(field) && (!Number.isSafeInteger(entry) || entry < (field === "captureFrame" ? 0 : 1))) {
181
+ throw new SceneCaptureIdentityRefusal(field, `${field} must be a ${field === "captureFrame" ? "non-negative" : "positive"} safe integer.`);
182
+ }
183
+ }
184
+ if (record.bakeScale !== 2 && record.bakeScale !== 3) throw new SceneCaptureIdentityRefusal("bakeScale", "bakeScale must be 2 or 3.");
185
+ if (record.headless !== true && record.headless !== false) throw new SceneCaptureIdentityRefusal("headless", "headless must be boolean.");
186
+ if (typeof record.deviceScaleFactor !== "number" || !Number.isFinite(record.deviceScaleFactor) || record.deviceScaleFactor <= 0) throw new SceneCaptureIdentityRefusal("deviceScaleFactor", "deviceScaleFactor must be positive and finite.");
187
+ const fps = normalizedRate(record.fps);
188
+ if (record.captureFrame >= record.durationInFrames) throw new SceneCaptureIdentityRefusal("captureFrame", "captureFrame must be before durationInFrames.");
189
+ if (record.rasterWidth !== record.layoutWidth * record.bakeScale || record.rasterHeight !== record.layoutHeight * record.bakeScale) throw new SceneCaptureIdentityRefusal("rasterWidth", "raster dimensions must equal layout multiplied by bakeScale.");
190
+ for (const field of SCENE_CAPTURE_IDENTITY_FIELDS) {
191
+ if (jsonFields.has(field) || integerFields.has(field) || field === "fps" || field === "bakeScale" || field === "headless" || field === "deviceScaleFactor") continue;
192
+ if (field === "gpuIdentity" && record[field] === null) continue;
193
+ if (typeof record[field] !== "string" || record[field].length === 0) throw new SceneCaptureIdentityRefusal(field, `${field} must be a non-empty string.`);
194
+ }
195
+ for (const digestField of ["sourceVersionId", "browserExecutableSha256"]) {
196
+ if (!/^[a-f0-9]{64}$/.test(record[digestField])) throw new SceneCaptureIdentityRefusal(digestField, `${digestField} must be a lowercase SHA-256 digest.`);
197
+ }
198
+ return { ...record, fps };
199
+ }
200
+ function completeSceneComponentCaptureIdentityV1(intent, attestation) {
201
+ intent = parseSceneComponentCaptureIntentV1(intent);
202
+ if (attestation.loadedRuntimeIdentity !== intent.runtimeIdentity) throw new SceneCaptureIdentityRefusal("runtimeIdentity", "The admitted session loaded a different runtime identity.");
203
+ if (attestation.loadedDependencyIdentity !== intent.dependencyIdentity) throw new SceneCaptureIdentityRefusal("dependencyIdentity", "The admitted session loaded a different dependency identity.");
204
+ const intendedFlags = intent.rasterAffectingFlags.browserArguments;
205
+ const observedFlags = attestation.observedRasterAffectingFlags.browserArguments;
206
+ if (!Array.isArray(intendedFlags) || !Array.isArray(observedFlags) || intendedFlags.some((flag) => typeof flag !== "string") || observedFlags.some((flag) => typeof flag !== "string"))
207
+ throw new SceneCaptureIdentityRefusal("rasterAffectingFlags", "The admitted session did not report canonical browser arguments.");
208
+ const dynamicVideoThreads = observedFlags.filter((flag) => /^--video-threads=[1-9]\d*$/.test(flag));
209
+ const comparableObserved = observedFlags.filter((flag) => !flag.startsWith("--video-threads="));
210
+ if (dynamicVideoThreads.length !== 1 || JSON.stringify(canonical(comparableObserved)) !== JSON.stringify(canonical(intendedFlags)))
211
+ throw new SceneCaptureIdentityRefusal("rasterAffectingFlags", "The admitted session used different raster-affecting flags.");
212
+ if (attestation.deviceScaleFactor !== intent.expectedDeviceScaleFactor) throw new SceneCaptureIdentityRefusal("deviceScaleFactor", "The capture page device scale factor differs from the selected bake scale.");
213
+ const { loadedRuntimeIdentity: _runtime, loadedDependencyIdentity: _dependency, observedRasterAffectingFlags: _flags, ...observedIdentity } = attestation;
214
+ const { expectedDeviceScaleFactor: _expectedDsf, ...identityIntent } = intent;
215
+ return parseSceneComponentCaptureIdentityV1({ ...identityIntent, ...observedIdentity, rasterAffectingFlags: attestation.observedRasterAffectingFlags });
216
+ }
217
+ function canonicalSceneComponentCaptureIdentityV1(value) {
218
+ const identity = parseSceneComponentCaptureIdentityV1(value);
219
+ const ordered = Object.fromEntries(
220
+ SCENE_CAPTURE_IDENTITY_FIELDS.map((field) => [field, canonical(identity[field])])
221
+ );
222
+ return JSON.stringify(ordered);
223
+ }
224
+
225
+ // ../execution/core/src/render/slabDescriptor.ts
226
+ var SCENE_SLAB_CONTENT_OFFSET_V1 = SCENE_SLAB_CONTENT_OFFSET;
227
+ function sceneSlabBuilderDescriptorV1(slab, allocations, measuredBodyTriangles) {
228
+ const z = slab.thickness / 2 + SCENE_SLAB_CONTENT_OFFSET_V1;
229
+ return {
230
+ kind: "slab",
231
+ builderVersion: 1,
232
+ tessellationVersion: 1,
233
+ budgetTriangles: SCENE_PRESET_TRIANGLES.slab,
234
+ parts: [
235
+ { partId: "body", materialRole: "body", triangles: measuredBodyTriangles, mounted: true },
236
+ { partId: "front", materialRole: "face", triangles: SCENE_SLAB_CONTENT_FACE_TRIANGLES, mounted: slab.surfaces?.front !== void 0 }
237
+ ],
238
+ surfaceSlots: [{
239
+ slot: "front",
240
+ attachment: { partId: "front", materialRole: "face" },
241
+ dimensions: { width: slab.width, height: slab.height },
242
+ projectionQuad: [
243
+ [-slab.width / 2, slab.height / 2, z],
244
+ [slab.width / 2, slab.height / 2, z],
245
+ [slab.width / 2, -slab.height / 2, z],
246
+ [-slab.width / 2, -slab.height / 2, z]
247
+ ],
248
+ uvOrigin: "top-left",
249
+ fit: "contain",
250
+ alpha: "straight",
251
+ depth: "test-only",
252
+ required: false,
253
+ bakeScales: [2, 3]
254
+ }],
255
+ materialRoles: ["body", "face"],
256
+ localBounds: { center: [0, 0, 0], halfExtents: [slab.width / 2, slab.height / 2, slab.thickness / 2] },
257
+ allocations
258
+ };
259
+ }
260
+ function createSceneSlabDescriptorRegistryV1(factsFor) {
261
+ return {
262
+ resolve(object) {
263
+ if (object.kind !== "slab") return null;
264
+ const facts = factsFor(object);
265
+ return sceneSlabBuilderDescriptorV1(object, facts.allocations, facts.measuredBodyTriangles);
266
+ }
267
+ };
268
+ }
269
+ function createSceneBuilderDescriptorRegistryV1(resolveDescriptor) {
270
+ return {
271
+ resolve(object, context) {
272
+ const descriptor = resolveDescriptor(object, context);
273
+ if (!descriptor) return null;
274
+ if (descriptor.kind !== object.kind) throw new Error(`scene_builder_descriptor_kind_mismatch: ${object.id}`);
275
+ return descriptor;
276
+ }
277
+ };
278
+ }
279
+
280
+ // ../execution/core/src/render/sceneShotPlan.ts
281
+ var ScenePlanRefusal = class extends Error {
282
+ constructor(code, path, message, detail = {}) {
283
+ super(message);
284
+ this.code = code;
285
+ this.path = path;
286
+ this.detail = detail;
287
+ this.name = "ScenePlanRefusal";
288
+ }
289
+ code;
290
+ path;
291
+ detail;
292
+ };
293
+ function normalizeOutput(output) {
294
+ if (!Number.isSafeInteger(output.width) || output.width <= 0) throw new ScenePlanRefusal("scene_evaluated_value_invalid", "output.width", "Output width must be a positive safe integer.");
295
+ if (!Number.isSafeInteger(output.height) || output.height <= 0) throw new ScenePlanRefusal("scene_evaluated_value_invalid", "output.height", "Output height must be a positive safe integer.");
296
+ if (!Number.isSafeInteger(output.durationInFrames) || output.durationInFrames <= 0) throw new ScenePlanRefusal("scene_evaluated_value_invalid", "output.durationInFrames", "Duration must be a positive safe integer.");
297
+ if (!Number.isSafeInteger(output.fps.num) || !Number.isSafeInteger(output.fps.den) || output.fps.num <= 0 || output.fps.den <= 0) throw new ScenePlanRefusal("scene_evaluated_value_invalid", "output.fps", "Output fps must be an exact positive rational.");
298
+ const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
299
+ const divisor = gcd(output.fps.num, output.fps.den);
300
+ return { ...output, fps: { num: output.fps.num / divisor, den: output.fps.den / divisor } };
301
+ }
302
+ function flatten(objects, parentId = null, prefix = "layers") {
303
+ const out = [];
304
+ objects.forEach((object, index) => {
305
+ const path = `${prefix}.${index}`;
306
+ out.push({ object, parentId, path });
307
+ if (object.kind === "group") out.push(...flatten(object.children, object.id, `${path}.children`));
308
+ });
309
+ return out;
310
+ }
311
+ function evaluatedChains(objects, ancestors = [], out = /* @__PURE__ */ new Map()) {
312
+ for (const object of objects) {
313
+ if (object.kind === "text" && object.space === "screen") continue;
314
+ const chain = [...ancestors, object.transform];
315
+ out.set(object.id, chain);
316
+ if (object.kind === "group" && object.children) evaluatedChains(object.children, chain, out);
317
+ }
318
+ return out;
319
+ }
320
+ function evaluatedById(objects, out = /* @__PURE__ */ new Map()) {
321
+ for (const object of objects) {
322
+ out.set(object.id, object);
323
+ if (object.kind === "group" && object.children) evaluatedById(object.children, out);
324
+ }
325
+ return out;
326
+ }
327
+ function assertFiniteEvaluation(frame, evaluation) {
328
+ const { layers: objects, camera } = evaluation;
329
+ const cameraValues = [...camera.position, ...camera.rotation, camera.fov];
330
+ if (cameraValues.some((value) => !Number.isFinite(value)) || camera.fov < 18 * Math.PI / 180 || camera.fov > 80 * Math.PI / 180) {
331
+ throw new ScenePlanRefusal("scene_evaluated_value_invalid", "camera", `Camera is invalid at content frame ${frame}.`, { frame, camera });
332
+ }
333
+ for (const entry of flatten(objects)) {
334
+ const object = entry.object;
335
+ if (!Number.isFinite(object.opacity) || object.opacity < 0 || object.opacity > 1) throw new ScenePlanRefusal("scene_evaluated_value_invalid", `${entry.path}.opacity`, `Object ${object.id} opacity is invalid at content frame ${frame}.`, { frame, authoredId: object.id });
336
+ if (object.kind === "text" && object.space === "screen") {
337
+ if ([object.x, object.y, object.rotation, object.scale].some((value) => !Number.isFinite(value)) || object.scale <= 0) throw new ScenePlanRefusal("scene_evaluated_value_invalid", entry.path, `Screen text ${object.id} is invalid at content frame ${frame}.`, { frame, authoredId: object.id });
338
+ continue;
339
+ }
340
+ const values = [...object.transform.position, ...object.transform.rotation, object.transform.scale, object.opacity];
341
+ if (values.some((value) => !Number.isFinite(value)) || object.transform.scale <= 0) {
342
+ throw new ScenePlanRefusal("scene_evaluated_value_invalid", entry.path, `Object ${object.id} is invalid at content frame ${frame}.`, { frame, authoredId: object.id });
343
+ }
344
+ const evaluated = object;
345
+ if (!evaluated.worldMatrix || evaluated.worldMatrix.some((value) => !Number.isFinite(value))) throw new ScenePlanRefusal("scene_evaluated_value_invalid", `${entry.path}.transform`, `Object ${object.id} world matrix is invalid at content frame ${frame}.`, { frame, authoredId: object.id });
346
+ if (object.kind === "laptop" && (!Number.isFinite(object.openAngle) || object.openAngle < 0 || object.openAngle > Math.PI)) throw new ScenePlanRefusal("scene_evaluated_value_invalid", `${entry.path}.openAngle`, `Laptop hinge is invalid at content frame ${frame}.`, { frame, authoredId: object.id });
347
+ }
348
+ if (evaluation.environment.kind !== "photographic-studio-v1" && (!Number.isFinite(evaluation.environment.intensity) || evaluation.environment.intensity < 0)) throw new ScenePlanRefusal("scene_evaluated_value_invalid", "environment.intensity", `Environment intensity is invalid at content frame ${frame}.`, { frame });
349
+ if (evaluation.focus && (!Number.isFinite(evaluation.focus.distance) || evaluation.focus.distance <= 0 || !Number.isFinite(evaluation.focus.range) || evaluation.focus.range <= 0 || !Number.isFinite(evaluation.focus.maxBlur) || evaluation.focus.maxBlur < 0 || evaluation.focus.maxBlur > 64)) throw new ScenePlanRefusal("scene_evaluated_value_invalid", "post.focus", `Focus is invalid at content frame ${frame}.`, { frame, focus: evaluation.focus });
350
+ }
351
+ function descriptorFor(entry, registry, context) {
352
+ if (entry.object.kind === "group" || entry.object.kind === "text" && entry.object.space === "screen") return null;
353
+ const descriptor = registry.resolve(entry.object, context);
354
+ if (!descriptor) throw new ScenePlanRefusal("scene_builder_descriptor_unavailable", `${entry.path}.kind`, `No implemented builder descriptor is available for ${entry.object.kind}.`, { authoredId: entry.object.id, kind: entry.object.kind });
355
+ if (descriptor.kind !== entry.object.kind || !Number.isSafeInteger(descriptor.builderVersion) || descriptor.builderVersion <= 0 || !Number.isSafeInteger(descriptor.tessellationVersion) || descriptor.tessellationVersion <= 0) {
356
+ throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.kind`, `Builder descriptor for ${entry.object.id} does not match its materialized object state.`, { descriptor });
357
+ }
358
+ const presetBudget = SCENE_PRESET_TRIANGLES[entry.object.kind];
359
+ if (presetBudget !== void 0 && descriptor.budgetTriangles !== presetBudget) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.kind`, `Builder descriptor for ${entry.object.id} does not match the frozen preset triangle contribution.`);
360
+ const finiteVec = (value) => value.length === 3 && value.every(Number.isFinite);
361
+ if (!finiteVec(descriptor.localBounds.center) || !finiteVec(descriptor.localBounds.halfExtents) || descriptor.localBounds.halfExtents.some((value) => value < 0) || descriptor.localBounds.halfExtents.every((value) => value === 0)) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.kind`, `Builder descriptor for ${entry.object.id} has invalid bounds.`);
362
+ if (descriptor.parts.some((part) => !part.partId || !part.materialRole || typeof part.mounted !== "boolean" || !Number.isSafeInteger(part.triangles) || part.triangles < 0)) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.kind`, `Builder descriptor for ${entry.object.id} has invalid part facts.`);
363
+ if (descriptor.surfaceSlots.some((slot) => slot.dimensions.width <= 0 || slot.dimensions.height <= 0 || slot.projectionQuad.length !== 4 || slot.projectionQuad.some((point) => !finiteVec(point)))) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.kind`, `Builder descriptor for ${entry.object.id} has invalid slot facts.`);
364
+ if (!descriptor.materialRoles.length || descriptor.allocations.some((allocation) => !allocation.owner || !allocation.name || !["gl", "cpu"].includes(allocation.domain) || !["texture", "renderbuffer", "geometry", "pmrem-source", "pmrem-target", "encoded-image", "decoded-image"].includes(allocation.resource) || !allocation.format || !["preparation", "context"].includes(allocation.lifetime) || !Number.isSafeInteger(allocation.bytes) || allocation.bytes < 0)) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.kind`, `Builder descriptor for ${entry.object.id} has invalid allocation facts.`);
365
+ const partIds = descriptor.parts.map((part) => part.partId);
366
+ const slotIds = descriptor.surfaceSlots.map((slot) => slot.slot);
367
+ if (new Set(partIds).size !== partIds.length || new Set(slotIds).size !== slotIds.length || new Set(descriptor.materialRoles).size !== descriptor.materialRoles.length) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.kind`, `Builder descriptor for ${entry.object.id} has duplicate identities.`);
368
+ for (const part of descriptor.parts) if (!descriptor.materialRoles.includes(part.materialRole)) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.kind`, `Part ${part.partId} references undeclared material role ${part.materialRole}.`);
369
+ for (const slot of descriptor.surfaceSlots) if (!partIds.includes(slot.attachment.partId) || !descriptor.materialRoles.includes(slot.attachment.materialRole) || !slot.bakeScales.length || slot.bakeScales.some((scale) => scale !== 2 && scale !== 3)) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.kind`, `Slot ${slot.slot} has invalid attachment or scale facts.`);
370
+ for (const slot of descriptor.surfaceSlots) {
371
+ const part = descriptor.parts.find((candidate) => candidate.partId === slot.attachment.partId);
372
+ if (!part || part.materialRole !== slot.attachment.materialRole) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.surfaces.${slot.slot}`, `Slot ${slot.slot} attachment role does not match its part.`);
373
+ if (slot.bakeScales.length !== 2 || slot.bakeScales[0] !== 2 || slot.bakeScales[1] !== 3) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.surfaces.${slot.slot}`, `Slot ${slot.slot} must declare the complete supported bake-scale set.`);
374
+ }
375
+ if ("materials" in entry.object && entry.object.materials) {
376
+ const unlitRoles = entry.object.kind === "page" ? /* @__PURE__ */ new Set(["base"]) : /* @__PURE__ */ new Set(["screen", "face"]);
377
+ for (const [index, material] of entry.object.materials.entries()) {
378
+ if (!descriptor.materialRoles.includes(material.role)) throw new ScenePlanRefusal("scene_material_role_unsupported", `${entry.path}.materials.${index}.role`, `Builder ${entry.object.kind} has no material role ${material.role}.`);
379
+ const expected = unlitRoles.has(material.role) ? "unlit" : "physical";
380
+ if (material.type !== expected) throw new ScenePlanRefusal("scene_material_type_mismatch", `${entry.path}.materials.${index}.type`, `${material.role} is a ${expected} material role.`);
381
+ }
382
+ }
383
+ if (descriptor.kind === "slab" && entry.object.kind === "slab") {
384
+ const body = descriptor.parts.find((part) => part.partId === "body");
385
+ const front = descriptor.parts.find((part) => part.partId === "front");
386
+ if (descriptor.parts.length !== 2 || !body || !Number.isSafeInteger(body.triangles) || body.triangles <= 0 || body.materialRole !== "body" || !body.mounted || front?.triangles !== SCENE_SLAB_CONTENT_FACE_TRIANGLES || front.materialRole !== "face" || descriptor.surfaceSlots.length !== 1 || descriptor.surfaceSlots[0]?.slot !== "front" || descriptor.materialRoles.join(",") !== "body,face" || descriptor.allocations.length === 0) {
387
+ throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.kind`, "Slab descriptor does not match the admitted production builder facts.");
388
+ }
389
+ const canonical2 = sceneSlabBuilderDescriptorV1(entry.object, descriptor.allocations, body.triangles);
390
+ if (canonicalSceneJsonV1(descriptor) !== canonicalSceneJsonV1(canonical2)) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", `${entry.path}.kind`, "Slab descriptor differs from the canonical production descriptor for its materialized parameters.");
391
+ }
392
+ return descriptor;
393
+ }
394
+ function prepareSceneShotPreflightV1(args) {
395
+ const output = normalizeOutput(args.output);
396
+ const scene = parseSceneShotSpecV2(args.authoredScene);
397
+ if (scene.referenceSize.width * output.height !== scene.referenceSize.height * output.width) throw new ScenePlanRefusal("scene_reference_aspect_mismatch", "referenceSize", "Scene reference size and requested output have different aspect ratios.", { referenceSize: scene.referenceSize, output: { width: output.width, height: output.height } });
398
+ const entries = flatten(scene.layers);
399
+ const descriptorById = /* @__PURE__ */ new Map();
400
+ const objects = entries.map((entry) => {
401
+ const builder = descriptorFor(entry, args.descriptors, { referenceSize: scene.referenceSize, output });
402
+ descriptorById.set(entry.object.id, builder);
403
+ return {
404
+ authoredId: entry.object.id,
405
+ parentId: entry.parentId,
406
+ kind: entry.object.kind,
407
+ builder,
408
+ parts: builder?.parts.map((part) => ({
409
+ id: `${entry.object.id}:${part.partId}`,
410
+ partId: part.partId,
411
+ materialRole: part.materialRole,
412
+ triangles: part.triangles,
413
+ mounted: part.mounted
414
+ })) ?? []
415
+ };
416
+ });
417
+ const frameEvaluations = Array.from({ length: output.durationInFrames }, (_, frame) => {
418
+ const evaluated = evaluateScene(scene, frame, output.durationInFrames);
419
+ assertFiniteEvaluation(frame, evaluated);
420
+ return { evaluated, chains: evaluatedChains(evaluated.layers), byId: evaluatedById(evaluated.layers) };
421
+ });
422
+ const worldBounds = { minX: -scene.referenceSize.width / 2, maxX: scene.referenceSize.width / 2, minY: Math.min(-scene.referenceSize.height / 2, scene.environment.kind === "photographic-studio-v1" ? -scene.referenceSize.height / 2 : scene.environment.floorY), maxY: scene.referenceSize.height / 2, minZ: 0, maxZ: 0 };
423
+ const include = (x, y, z) => {
424
+ worldBounds.minX = Math.min(worldBounds.minX, x);
425
+ worldBounds.maxX = Math.max(worldBounds.maxX, x);
426
+ worldBounds.minY = Math.min(worldBounds.minY, y);
427
+ worldBounds.maxY = Math.max(worldBounds.maxY, y);
428
+ worldBounds.minZ = Math.min(worldBounds.minZ, z);
429
+ worldBounds.maxZ = Math.max(worldBounds.maxZ, z);
430
+ };
431
+ for (const frame of frameEvaluations) for (const entry of entries) {
432
+ const evaluated = frame.byId.get(entry.object.id);
433
+ if (!evaluated || evaluated.kind === "group" || evaluated.kind === "text" && evaluated.space === "screen" || !evaluated.worldMatrix) continue;
434
+ const descriptor = args.descriptors.resolve(evaluated, { referenceSize: scene.referenceSize, output });
435
+ if (!descriptor) continue;
436
+ const { center, halfExtents } = descriptor.localBounds;
437
+ for (const dx of [-halfExtents[0], halfExtents[0]]) for (const dy of [-halfExtents[1], halfExtents[1]]) for (const dz of [-halfExtents[2], halfExtents[2]]) {
438
+ const x = center[0] + dx, y = center[1] + dy, z = center[2] + dz, m = evaluated.worldMatrix;
439
+ include(m[0] * x + m[4] * y + m[8] * z + m[12], m[1] * x + m[5] * y + m[9] * z + m[13], m[2] * x + m[6] * y + m[10] * z + m[14]);
440
+ }
441
+ }
442
+ const rigFacts = args.resolveRigFacts(scene, worldBounds);
443
+ if (!rigFacts) throw new ScenePlanRefusal("scene_builder_descriptor_unavailable", "environment", "No admitted production rig identity is available.");
444
+ const cameraClipPlanes = frameEvaluations.map((_, frame) => {
445
+ const planes = args.resolveCameraClipPlanes(scene, frame, output.durationInFrames);
446
+ if (!Number.isFinite(planes.near) || !Number.isFinite(planes.far) || planes.near <= 0 || planes.far <= planes.near) throw new ScenePlanRefusal("scene_evaluated_value_invalid", "camera", `Production camera clip planes are invalid at content frame ${frame}.`, { frame, planes });
447
+ return planes;
448
+ });
449
+ const surfaces = [];
450
+ for (const entry of entries) {
451
+ const builder = descriptorById.get(entry.object.id);
452
+ if (!builder || !("surfaces" in entry.object) || !entry.object.surfaces) continue;
453
+ for (const [slot, binding] of Object.entries(entry.object.surfaces)) {
454
+ const descriptor = builder.surfaceSlots.find((candidate) => candidate.slot === slot);
455
+ const path = `${entry.path}.surfaces.${slot}`;
456
+ if (!descriptor) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", path, `Builder descriptor does not declare bound slot ${slot}.`);
457
+ const prepared = { path, authoredObjectId: entry.object.id, slot, binding, descriptor };
458
+ if (binding.source === "component") {
459
+ const facts = args.resolveComponentFacts?.(binding, path);
460
+ if (!facts) throw new ScenePlanRefusal("scene_component_facts_missing", path, `Component capture facts are unavailable for ${path}.`);
461
+ const selection = selectSceneBakeScale({
462
+ surfaceId: entry.object.id,
463
+ slotName: slot,
464
+ slot: descriptor.dimensions,
465
+ layout: binding.layout,
466
+ contentDuration: output.durationInFrames,
467
+ output,
468
+ referenceSize: scene.referenceSize,
469
+ evaluate: (frame) => {
470
+ const evaluation = frameEvaluations[frame];
471
+ const evaluatedObject = evaluation.byId.get(entry.object.id);
472
+ if (!evaluatedObject) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", path, `Evaluated object ${entry.object.id} is missing.`);
473
+ const evaluatedDescriptor = args.descriptors.resolve(evaluatedObject, { referenceSize: scene.referenceSize, output });
474
+ const evaluatedSlot = evaluatedDescriptor?.surfaceSlots.find((candidate) => candidate.slot === slot);
475
+ if (!evaluatedDescriptor || evaluatedDescriptor.kind !== builder.kind || evaluatedDescriptor.builderVersion !== builder.builderVersion || evaluatedDescriptor.tessellationVersion !== builder.tessellationVersion || !evaluatedSlot) throw new ScenePlanRefusal("scene_builder_descriptor_invalid", path, `Builder did not supply stable evaluated attachment facts for ${path}.`, { frame });
476
+ return { camera: evaluation.evaluated.camera, chain: evaluation.chains.get(entry.object.id), projectionQuad: evaluatedSlot.projectionQuad };
477
+ }
478
+ }, binding.bakeScale);
479
+ prepared.bakeScale = selection.selected;
480
+ prepared.bakeScaleReason = selection.reason;
481
+ prepared.resolutionCheck = selection;
482
+ prepared.captureIntent = {
483
+ componentId: binding.component.componentId,
484
+ sourceVersionId: binding.component.sourceVersionId,
485
+ params: facts.params,
486
+ assetBindings: facts.assetBindings,
487
+ layoutWidth: binding.layout.width,
488
+ layoutHeight: binding.layout.height,
489
+ bakeScale: selection.selected,
490
+ captureFrame: binding.captureFrame,
491
+ durationInFrames: facts.durationInFrames,
492
+ fps: output.fps,
493
+ seed: facts.seed,
494
+ brandFacts: facts.brandFacts,
495
+ fontFacts: facts.fontFacts,
496
+ mediaFacts: facts.mediaFacts,
497
+ rasterWidth: binding.layout.width * selection.selected,
498
+ rasterHeight: binding.layout.height * selection.selected,
499
+ expectedDeviceScaleFactor: selection.selected,
500
+ runtimeIdentity: facts.runtimeIdentity,
501
+ dependencyIdentity: facts.dependencyIdentity,
502
+ requestedGlBackend: facts.requestedGlBackend,
503
+ rasterAffectingFlags: facts.rasterAffectingFlags
504
+ };
505
+ }
506
+ surfaces.push(prepared);
507
+ }
508
+ }
509
+ const separation = evaluateSceneSeparationV2(scene.constraints, frameEvaluations.map(({ evaluated, chains }) => ({
510
+ frame: evaluated.contentFrame,
511
+ resolveBody: (authoredId) => {
512
+ const chain = chains.get(authoredId);
513
+ const object = evaluated.layers.length ? evaluatedById(evaluated.layers).get(authoredId) : void 0;
514
+ if (!object || !chain) return null;
515
+ const builder = args.descriptors.resolve(object, { referenceSize: scene.referenceSize, output });
516
+ if (!builder) return null;
517
+ return { bounds: builder.localBounds, transforms: chain, opacity: object.worldOpacity };
518
+ }
519
+ })));
520
+ const frame0 = frameEvaluations[0].evaluated.camera;
521
+ return {
522
+ version: 1,
523
+ scene,
524
+ output,
525
+ cameraIdentity: { position: [...frame0.position], fov: frame0.fov, ...cameraClipPlanes[0] },
526
+ motion: { channels: structuredClone(scene.animation), contentDurationInFrames: output.durationInFrames, finalContentFrame: output.durationInFrames - 1, cameraClipPlanes },
527
+ objects,
528
+ surfaces,
529
+ separation,
530
+ rigIdentity: structuredClone(rigFacts.identity),
531
+ rigAllocations: structuredClone(rigFacts.allocations),
532
+ fonts: structuredClone(args.fonts ?? [])
533
+ };
534
+ }
535
+ function assertScenePlanOutputV1(plan, requested) {
536
+ const normalized = normalizeOutput(requested);
537
+ if (plan.output.width !== normalized.width || plan.output.height !== normalized.height || plan.output.durationInFrames !== normalized.durationInFrames || plan.output.fps.num !== normalized.fps.num || plan.output.fps.den !== normalized.fps.den) {
538
+ throw new ScenePlanRefusal("scene_plan_output_mismatch", "output", "The sealed scene plan targets a different output; prepare it again.", { sealed: plan.output, requested: normalized });
539
+ }
540
+ }
541
+ function deepFreeze(value) {
542
+ if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
543
+ Object.freeze(value);
544
+ for (const entry of Object.values(value)) deepFreeze(entry);
545
+ }
546
+ return value;
547
+ }
548
+ async function settleCleanup(cleanups) {
549
+ const results = await Promise.allSettled(cleanups.map((cleanup) => cleanup()));
550
+ const failures = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
551
+ if (failures.length) throw new AggregateError(failures, "scene_plan_cleanup_failed");
552
+ }
553
+ async function realizeSceneShotPlanV1(preflight, deps) {
554
+ const intents = /* @__PURE__ */ new Map();
555
+ for (const surface of preflight.surfaces) {
556
+ if (!surface.captureIntent) continue;
557
+ const intent = parseSceneComponentCaptureIntentV1(surface.captureIntent);
558
+ intents.set(surface.path, intent);
559
+ const execution = await deps.capture.resolveExecutionFacts(intent, deps.signal);
560
+ for (const key of ["runtimeIdentity", "dependencyIdentity", "requestedGlBackend", "rasterAffectingFlags"]) {
561
+ if (canonicalSceneJsonV1(intent[key]) !== canonicalSceneJsonV1(execution[key])) throw new ScenePlanRefusal("scene_component_capture_invalid", `captureIntent.${key}`, `Capture execution fact ${key} changed after preflight.`);
562
+ }
563
+ }
564
+ const cleanups = [];
565
+ try {
566
+ const surfaces = [];
567
+ const componentCaptures = /* @__PURE__ */ new Map();
568
+ for (const surface of preflight.surfaces) {
569
+ const { captureIntent: _captureIntent, ...sealedBase } = surface;
570
+ if (surface.binding.source === "video") {
571
+ const lease = await deps.resolveVideo?.(surface.binding, surface.path, deps.signal);
572
+ if (!lease) throw new ScenePlanRefusal("scene_video_facts_missing", surface.path, `Verified presentation-index facts are unavailable for ${surface.path}.`);
573
+ cleanups.push(lease.release);
574
+ const schedule = prepareSceneVideoScheduleV1({ presentationIndex: lease.video.presentationIndex, shotRate: preflight.output.fps, contentDuration: preflight.output.durationInFrames, startFrame: surface.binding.startFrame, endFrame: surface.binding.endFrame });
575
+ surfaces.push({ ...sealedBase, realized: { source: "video", video: lease.video, schedule } });
576
+ continue;
577
+ }
578
+ if (surface.binding.source === "color") {
579
+ surfaces.push({ ...sealedBase, realized: { source: "color", color: surface.binding.color } });
580
+ continue;
581
+ }
582
+ if (surface.binding.source === "image") {
583
+ const lease = await deps.resolveImage(surface.binding, surface.path);
584
+ if (!lease) throw new ScenePlanRefusal("scene_image_facts_missing", surface.path, `Verified decoded image facts are unavailable for ${surface.path}.`);
585
+ cleanups.push(lease.release);
586
+ const { image } = lease;
587
+ if (!["image/png", "image/jpeg", "image/webp"].includes(image.mimeType) || !Number.isSafeInteger(image.width) || image.width <= 0 || !Number.isSafeInteger(image.height) || image.height <= 0 || !Number.isSafeInteger(image.byteLength) || image.byteLength <= 0 || !/^[a-f0-9]{64}$/.test(image.decodedSha256)) throw new ScenePlanRefusal("scene_image_facts_missing", surface.path, `Verified decoded image facts are invalid for ${surface.path}.`);
588
+ surfaces.push({ ...sealedBase, realized: { source: "image", image } });
589
+ continue;
590
+ }
591
+ const intent = intents.get(surface.path);
592
+ if (!intent) throw new ScenePlanRefusal("scene_component_facts_missing", surface.path, "Component capture intent is missing.");
593
+ const captureKey = canonicalSceneJsonV1(intent);
594
+ let capture = componentCaptures.get(captureKey);
595
+ if (!capture) {
596
+ capture = (async () => {
597
+ const session = await deps.capture.openSession(intent, deps.signal);
598
+ cleanups.push(session.close);
599
+ const result2 = await session.capture(intent, deps.signal);
600
+ const captureIdentityFacts2 = completeSceneComponentCaptureIdentityV1(intent, result2.attestation);
601
+ const captureIdentitySha2562 = await deps.sha256(canonicalSceneComponentCaptureIdentityV1(captureIdentityFacts2));
602
+ return { result: result2, captureIdentityFacts: captureIdentityFacts2, captureIdentitySha256: captureIdentitySha2562 };
603
+ })();
604
+ componentCaptures.set(captureKey, capture);
605
+ }
606
+ const { result, captureIdentityFacts, captureIdentitySha256 } = await capture;
607
+ if (!/^[a-f0-9]{64}$/.test(captureIdentitySha256) || result.cacheScope !== "session" || result.png.width !== intent.rasterWidth || result.png.height !== intent.rasterHeight || result.png.mimeType !== "image/png" || !/^[a-f0-9]{64}$/.test(result.png.decodedSha256) || !Number.isSafeInteger(result.png.byteLength) || result.png.byteLength <= 0) throw new ScenePlanRefusal("scene_component_capture_invalid", surface.path, `Captured PNG facts do not match the sealed intent for ${surface.path}.`);
608
+ surfaces.push({ ...sealedBase, realized: { source: "component", captureIdentitySha256, captureIdentityFacts, image: result.png } });
609
+ }
610
+ const baseAllocations = [
611
+ ...preflight.objects.flatMap((object) => (object.builder?.allocations ?? []).map((allocation) => ({ ...allocation, owner: `${object.authoredId}:${allocation.owner}` }))),
612
+ ...preflight.rigAllocations.map((allocation) => ({ ...allocation, owner: `rig:${allocation.owner}` }))
613
+ ];
614
+ const textureAllocations = surfaces.flatMap((surface) => surface.realized.source === "color" ? [] : [{
615
+ owner: surface.path,
616
+ name: "surface-texture",
617
+ domain: "gl",
618
+ resource: "texture",
619
+ format: "rgba8",
620
+ bytes: sceneTextureBytes({ width: (surface.realized.source === "video" ? surface.realized.video : surface.realized.image).width, height: (surface.realized.source === "video" ? surface.realized.video : surface.realized.image).height, format: "rgba8", mipLevels: sceneFullMipLevels((surface.realized.source === "video" ? surface.realized.video : surface.realized.image).width, (surface.realized.source === "video" ? surface.realized.video : surface.realized.image).height) }),
621
+ lifetime: "context"
622
+ }]);
623
+ const seenCpuHandles = /* @__PURE__ */ new Set();
624
+ const cpuAllocations = surfaces.flatMap((surface) => {
625
+ if (surface.realized.source === "color") return [];
626
+ const media = surface.realized.source === "video" ? surface.realized.video : surface.realized.image;
627
+ const firstHandle = !seenCpuHandles.has(media.handle);
628
+ seenCpuHandles.add(media.handle);
629
+ if (surface.realized.source === "video") return [
630
+ ...firstHandle ? [{ owner: `capture:${media.handle}`, name: "encoded-video", domain: "cpu", resource: "encoded-video", format: media.mimeType, bytes: media.byteLength, lifetime: "context" }] : [],
631
+ { owner: surface.path, name: "owned-video-canvas", domain: "cpu", resource: "decoded-video", format: "rgba8", bytes: media.width * media.height * 4, lifetime: "context" }
632
+ ];
633
+ if (!firstHandle) return [];
634
+ return [
635
+ { owner: `capture:${media.handle}`, name: "encoded-image", domain: "cpu", resource: "encoded-image", format: media.mimeType, bytes: media.byteLength, lifetime: "context" },
636
+ { owner: `capture:${media.handle}`, name: "decoded-rgba", domain: "cpu", resource: "decoded-image", format: "rgba8", bytes: media.width * media.height * 4, lifetime: "preparation" }
637
+ ];
638
+ });
639
+ const allocations = [...baseAllocations, ...textureAllocations, ...cpuAllocations];
640
+ const byOwner = {};
641
+ for (const allocation of allocations) {
642
+ const row = byOwner[allocation.owner] ??= { contextGlBytes: 0, preparationGlBytes: 0, cpuBytes: 0 };
643
+ if (allocation.domain === "cpu") row.cpuBytes += allocation.bytes;
644
+ else if (allocation.lifetime === "context") row.contextGlBytes += allocation.bytes;
645
+ else row.preparationGlBytes += allocation.bytes;
646
+ }
647
+ const surfaceTextureBytes = textureAllocations.reduce((sum, allocation) => sum + allocation.bytes, 0);
648
+ const contextGlBytes = Object.values(byOwner).reduce((sum, row) => sum + row.contextGlBytes, 0);
649
+ const preparationGlBytes = Object.values(byOwner).reduce((sum, row) => sum + row.preparationGlBytes, 0);
650
+ const cpuBytes = Object.values(byOwner).reduce((sum, row) => sum + row.cpuBytes, 0);
651
+ const budgetTriangles = preflight.objects.reduce((sum, object) => sum + (object.builder?.budgetTriangles ?? 0), 0);
652
+ const instantiatedTriangles = preflight.objects.flatMap((object) => object.parts).reduce((sum, part) => sum + (part.mounted ? part.triangles : 0), 0);
653
+ const ledger = {
654
+ owner: `scene-plan:${preflight.objects.map((object) => object.authoredId).join(",")}`,
655
+ invariant: "one-plan-one-webgl-context",
656
+ allocations,
657
+ byOwner,
658
+ surfaceTextureBytes,
659
+ contextGlBytes,
660
+ preparationPeakGlBytes: contextGlBytes + preparationGlBytes,
661
+ cpuBytes,
662
+ peakDeclaredLiveBytes: contextGlBytes + preparationGlBytes + cpuBytes,
663
+ budgetTriangles,
664
+ instantiatedTriangles,
665
+ exclusions: {
666
+ crossContextAndHostAggregation: "W7",
667
+ videoDecode: surfaces.some((surface) => surface.realized.source === "video") ? "binding-owned" : "W6",
668
+ browserProcess: "host-owned",
669
+ sourceBundles: "host-owned",
670
+ captureSession: "provider-owned",
671
+ driverAllocations: "excluded-unmeasured",
672
+ compositorSurfaces: "excluded-unmeasured",
673
+ decoderCaches: "excluded-unmeasured"
674
+ }
675
+ };
676
+ if (surfaceTextureBytes > SCENE_SURFACE_TEXTURE_BUDGET_BYTES || ledger.preparationPeakGlBytes > SCENE_CONTEXT_GL_BUDGET_BYTES || budgetTriangles > SCENE_MAX_TRIANGLES) throw new ScenePlanRefusal("scene_budget_exceeded", "ledger", "The prepared scene exceeds its per-shot or per-context budget.", { ledger, limits: { surfaceTextureBytes: SCENE_SURFACE_TEXTURE_BUDGET_BYTES, contextGlBytes: SCENE_CONTEXT_GL_BUDGET_BYTES, triangles: SCENE_MAX_TRIANGLES }, corrective: "Reduce surfaces or objects, or change camera/layout and prepare a new seal; lower bakeScale only when a new resolution check passes." });
677
+ const planFacts = { ...preflight, status: "sealed", surfaces, ledger };
678
+ const sealSha256 = await deps.sha256(canonicalSceneJsonV1(planFacts));
679
+ if (!/^[a-f0-9]{64}$/.test(sealSha256)) throw new ScenePlanRefusal("scene_component_capture_invalid", "sealSha256", "Plan hash supplier returned an invalid SHA-256 digest.");
680
+ const plan = deepFreeze(structuredClone({ ...planFacts, sealSha256 }));
681
+ let cleanupPromise = null;
682
+ return { plan, cleanup: () => cleanupPromise ??= settleCleanup(cleanups) };
683
+ } catch (error) {
684
+ try {
685
+ await settleCleanup(cleanups);
686
+ } catch (cleanupError) {
687
+ if (error instanceof Error && error.cause === void 0) error.cause = cleanupError;
688
+ else throw new AggregateError([error, cleanupError], "Scene realization and cleanup both failed.");
689
+ }
690
+ throw error;
691
+ }
692
+ }
693
+
694
+ // ../execution/core/src/render/sceneShotPreparation.ts
695
+ var SCENE_SHOT_PREPARATION_STAGE = "preparation";
696
+ var SCENE_SHOT_PARAM = "scene";
697
+ var SCENE_SHOT_IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/webp"];
698
+ var SCENE_SHOT_VIDEO_MIME_TYPES = ["video/mp4", "video/webm"];
699
+ function readSceneShotManifest(manifest, context) {
700
+ if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) return null;
701
+ const record = manifest;
702
+ if (record.sceneShot === void 0) return null;
703
+ const sceneShot = record.sceneShot;
704
+ if (sceneShot?.version !== 2) throw new ScenePlanRefusal("scene_evaluated_value_invalid", "manifest.sceneShot.version", `Scene source ${context.componentId ?? ""} does not declare authored scene version 2.`);
705
+ const graphics = record.graphics;
706
+ if (graphics?.api !== "webgl") throw new ScenePlanRefusal("scene_evaluated_value_invalid", "manifest.graphics.api", "Scene sources require WebGL.");
707
+ const assets = record.assets;
708
+ if (!assets || typeof assets !== "object" || Array.isArray(assets)) throw new ScenePlanRefusal("scene_evaluated_value_invalid", "manifest.assets", "Scene source assets must be declared.");
709
+ return { version: 2, api: "webgl", assets };
710
+ }
711
+ function sceneSourceResolverForPinnedRows(rows) {
712
+ return (componentId, sourceVersionId) => {
713
+ const row = Object.values(rows).find(
714
+ (candidate) => candidate.source.componentId === componentId && candidate.sourceVersionId === sourceVersionId
715
+ );
716
+ if (!row) return null;
717
+ return { componentId, manifest: row.source.manifest };
718
+ };
719
+ }
720
+ function assertSceneClipShapes(composition, context) {
721
+ const issues = collectSceneClipIssues(composition, context);
722
+ if (issues[0]) throw new ScenePlanRefusal("scene_evaluated_value_invalid", issues[0].path, issues[0].message, { clipId: issues[0].clipId });
723
+ }
724
+ var HEX = /^#[0-9a-f]{6}(?:[0-9a-f]{2})?$/i;
725
+ function resolveBrandValue(value, kind, brand, path) {
726
+ const prefix = `$brand:${kind}.`;
727
+ if (!value.startsWith(prefix)) return value;
728
+ const key = value.slice(prefix.length);
729
+ const record = brand?.[kind];
730
+ const raw = record?.[key];
731
+ const resolved = kind === "fonts" && raw && typeof raw === "object" ? raw.family : raw;
732
+ if (typeof resolved !== "string" || resolved.length === 0 || kind === "colors" && !HEX.test(resolved)) {
733
+ throw new ScenePlanRefusal("scene_brand_unresolved", path, `Brand reference ${value} has no admitted ${kind === "colors" ? "color" : "font family"} fact.`);
734
+ }
735
+ return kind === "colors" ? resolved.toLowerCase() : resolved;
736
+ }
737
+ function resolvePinnedSceneFactsV1(authored, context, componentFactsByPath = {}) {
738
+ const brand = context.input.brandKit;
739
+ const faces = /* @__PURE__ */ new Map();
740
+ const custom = new Map((brand?.fontAssets ?? []).map((asset) => [`${asset.family}\0${asset.weight}\0${asset.style ?? "normal"}`, asset.url]));
741
+ const customFamilies = new Set((brand?.fontAssets ?? []).map((asset) => asset.family));
742
+ const customFacts = {
743
+ hasFamily: (family) => customFamilies.has(family),
744
+ hasWeight: (family, weight) => [...custom.keys()].some((key) => key.startsWith(`${family}\0${weight}\0`))
745
+ };
746
+ const visit = (objects, prefix = "layers") => objects.map((object, index) => {
747
+ const path = `${prefix}.${index}`;
748
+ if (object.kind === "group") return { ...object, children: visit(object.children, `${path}.children`) };
749
+ const materials = "materials" in object && object.materials?.map((material, materialIndex) => ({
750
+ ...material,
751
+ ...material.color ? { color: resolveBrandValue(material.color, "colors", brand, `${path}.materials.${materialIndex}.color`) } : {}
752
+ }));
753
+ const surfaces = "surfaces" in object && object.surfaces ? Object.fromEntries(Object.entries(object.surfaces).map(([slot, binding]) => [
754
+ slot,
755
+ binding.source === "color" ? { ...binding, color: resolveBrandValue(binding.color, "colors", brand, `${path}.surfaces.${slot}.color`) } : binding
756
+ ])) : void 0;
757
+ if (object.kind !== "text") return { ...object, ...materials ? { materials } : {}, ...surfaces ? { surfaces } : {} };
758
+ const family = resolveBrandValue(object.fontFamily, "fonts", brand, `${path}.fontFamily`);
759
+ const key = `${family}\0${object.fontWeight}\0${object.fontStyle}`;
760
+ const url = custom.get(key);
761
+ if (!url && !bundledFontFaceExists(family, object.fontWeight, object.fontStyle)) {
762
+ const field = unrenderableFaceField(family, object.fontWeight, object.fontStyle, customFacts);
763
+ throw new ScenePlanRefusal("scene_font_unavailable", `${path}.${field}`, `Font face ${family} ${object.fontWeight} ${object.fontStyle} has no admitted bytes.`);
764
+ }
765
+ const existing = faces.get(key);
766
+ if (existing) existing.paths.push(path);
767
+ else faces.set(key, { family, weight: object.fontWeight, style: object.fontStyle, ...url ? { url } : {}, paths: [path] });
768
+ return {
769
+ ...object,
770
+ fontFamily: family,
771
+ color: resolveBrandValue(object.color, "colors", brand, `${path}.color`),
772
+ lines: object.lines.map((line, lineIndex) => ({ runs: line.runs.map((run, runIndex) => ({
773
+ ...run,
774
+ ...run.color ? { color: resolveBrandValue(run.color, "colors", brand, `${path}.lines.${lineIndex}.runs.${runIndex}.color`) } : {}
775
+ })) }))
776
+ };
777
+ });
778
+ const backdrop = authored.backdrop.kind === "solid" ? { ...authored.backdrop, color: resolveBrandValue(authored.backdrop.color, "colors", brand, "backdrop.color") } : authored.backdrop.kind === "linear" || authored.backdrop.kind === "radial" ? { ...authored.backdrop, stops: authored.backdrop.stops.map((stop, index) => ({ ...stop, color: resolveBrandValue(stop.color, "colors", brand, `backdrop.stops.${index}.color`) })) } : authored.backdrop;
779
+ const scene = parseSceneShotSpecV2({ ...authored, backdrop, layers: visit(authored.layers) });
780
+ return { scene, componentFactsByPath, fonts: [...faces.values()] };
781
+ }
782
+ function exactOutput(input, durationInFrames) {
783
+ const width = input.outputWidth ?? input.width;
784
+ const height = input.outputHeight ?? input.height;
785
+ const fps = input.fpsRational ?? (Number.isSafeInteger(input.fps) ? { num: input.fps, den: 1 } : null);
786
+ if (!fps) throw new ScenePlanRefusal("scene_evaluated_value_invalid", "fpsRational", "A non-integer render rate requires authoritative exact rational transport.");
787
+ if (input.fps * fps.den !== fps.num) throw new ScenePlanRefusal("scene_plan_output_mismatch", "fpsRational", "Numeric fps and exact rational fps disagree.");
788
+ return { width, height, fps, durationInFrames };
789
+ }
790
+ async function prepareOverlay(input, overlay, dependencies) {
791
+ if (!overlay.componentId || !overlay.sourceVersionId) return null;
792
+ if (overlay.template !== "component") throw new ScenePlanRefusal("scene_evaluated_value_invalid", "overlay.template", `Scene candidate ${overlay.id} must use the component overlay template.`);
793
+ const row = input.componentSources?.[overlay.id];
794
+ if (!row) throw new ScenePlanRefusal("scene_component_facts_missing", `componentSources.${overlay.id}`, `Pinned source facts are missing for scene candidate ${overlay.id}.`);
795
+ if (row.source.componentId !== overlay.componentId || row.sourceVersionId !== overlay.sourceVersionId) throw new ScenePlanRefusal("scene_component_facts_missing", `componentSources.${overlay.id}`, `Pinned source facts do not match scene candidate ${overlay.id}.`);
796
+ const manifest = readSceneShotManifest(row.source.manifest, { clipId: overlay.id, componentId: overlay.componentId });
797
+ if (!manifest) return null;
798
+ const rawScene = overlay.params[SCENE_SHOT_PARAM];
799
+ const authored = parseSceneShotSpecV2(rawScene);
800
+ const referencedImageSlots = /* @__PURE__ */ new Set();
801
+ const checkAssets = (objects, prefix = "layers") => {
802
+ objects.forEach((object, index) => {
803
+ const path = `${prefix}.${index}`;
804
+ if (object.kind === "group") checkAssets(object.children, `${path}.children`);
805
+ for (const [slot, binding] of Object.entries("surfaces" in object ? object.surfaces ?? {} : {})) {
806
+ if (binding.source !== "image" && binding.source !== "video") continue;
807
+ const assetSlot = binding.source === "image" ? binding.assetSlot : binding.mediaId;
808
+ const mimes = binding.source === "image" ? SCENE_SHOT_IMAGE_MIME_TYPES : SCENE_SHOT_VIDEO_MIME_TYPES;
809
+ referencedImageSlots.add(assetSlot);
810
+ const declaration = manifest.assets[assetSlot];
811
+ const expectedKind = binding.source;
812
+ if (!declaration || declaration.kind !== expectedKind || declaration.required !== true || !Array.isArray(declaration.mimeTypes) || !declaration.mimeTypes.some((mime) => mimes.includes(mime))) {
813
+ throw new ScenePlanRefusal(binding.source === "image" ? "scene_image_facts_missing" : "scene_video_facts_missing", `${path}.surfaces.${slot}`, `Manifest does not declare required admitted ${expectedKind} slot ${assetSlot}.`);
814
+ }
815
+ const admitted = declaration.mimeTypes;
816
+ if (!admitted.every((mime) => typeof mime === "string" && mimes.includes(mime))) throw new ScenePlanRefusal(binding.source === "image" ? "scene_image_facts_missing" : "scene_video_facts_missing", `${path}.surfaces.${slot}`, `Manifest ${expectedKind} slot ${assetSlot} contains an unsupported MIME type.`);
817
+ const asset = row.assets[assetSlot];
818
+ if (!asset || asset.kind !== expectedKind || !admitted.includes(asset.mimeType) || !mimes.includes(asset.mimeType) || !Number.isSafeInteger(asset.width) || (asset.width ?? 0) <= 0 || !Number.isSafeInteger(asset.height) || (asset.height ?? 0) <= 0) {
819
+ throw new ScenePlanRefusal(binding.source === "image" ? "scene_image_facts_missing" : "scene_video_facts_missing", `${path}.surfaces.${slot}`, `Pinned ${expectedKind} slot ${assetSlot} has no admitted MIME and decoded dimensions.`);
820
+ }
821
+ }
822
+ });
823
+ };
824
+ checkAssets(authored.layers);
825
+ for (const slot of Object.keys(manifest.assets)) if (!referencedImageSlots.has(slot)) throw new ScenePlanRefusal("scene_image_facts_missing", `manifest.assets.${slot}`, `Pinned scene source declares stale unreferenced asset slot ${slot}.`);
826
+ for (const slot of Object.keys(row.assets)) if (!referencedImageSlots.has(slot)) throw new ScenePlanRefusal("scene_image_facts_missing", `componentSources.${overlay.id}.assets.${slot}`, `Pinned scene source binds stale unreferenced asset slot ${slot}.`);
827
+ const extension = dependencies.resolveComponentFacts ? await dependencies.resolveComponentFacts(authored, { input, overlay }) : null;
828
+ const resolved = resolvePinnedSceneFactsV1(
829
+ authored,
830
+ { input, overlay },
831
+ extension ?? dependencies.componentFactsByPath
832
+ );
833
+ const preflight = prepareSceneShotPreflightV1({
834
+ authoredScene: resolved.scene,
835
+ output: exactOutput(input, overlay.durationInFrames),
836
+ descriptors: dependencies.descriptors,
837
+ resolveComponentFacts: (_binding, path) => resolved.componentFactsByPath[path] ?? null,
838
+ resolveRigFacts: dependencies.resolveRigFacts,
839
+ resolveCameraClipPlanes: dependencies.resolveCameraClipPlanes,
840
+ fonts: resolved.fonts
841
+ });
842
+ return realizeSceneShotPlanV1(preflight, dependencies.realizationForOverlay?.({ input, overlay }) ?? dependencies.realization);
843
+ }
844
+ async function prepareSceneShotRenderInput(input, dependencies) {
845
+ const clone = structuredClone(input);
846
+ const leases = [];
847
+ try {
848
+ for (let index = 0; index < clone.overlays.length; index += 1) {
849
+ const overlay = clone.overlays[index];
850
+ const lease = await prepareOverlay(clone, overlay, dependencies);
851
+ if (!lease) continue;
852
+ leases.push(lease);
853
+ clone.overlays[index] = {
854
+ ...overlay,
855
+ params: {
856
+ ...overlay.params,
857
+ scene: lease.plan.scene
858
+ },
859
+ sceneShot: {
860
+ version: 1,
861
+ authoredSceneVersion: 2,
862
+ componentId: overlay.componentId,
863
+ sourceVersionId: overlay.sourceVersionId,
864
+ sealSha256: lease.plan.sealSha256,
865
+ contentDurationInFrames: lease.plan.output.durationInFrames,
866
+ plan: lease.plan
867
+ }
868
+ };
869
+ }
870
+ let cleanupPromise = null;
871
+ return {
872
+ input: clone,
873
+ cleanup: () => cleanupPromise ??= Promise.allSettled(leases.map((lease) => lease.cleanup())).then((results) => {
874
+ const failures = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
875
+ if (failures.length) throw new AggregateError(failures, "scene_render_input_cleanup_failed");
876
+ })
877
+ };
878
+ } catch (error) {
879
+ const results = await Promise.allSettled(leases.map((lease) => lease.cleanup()));
880
+ const failures = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
881
+ if (failures.length) {
882
+ const cleanupError = new AggregateError(failures, "scene_render_input_cleanup_failed");
883
+ if (error instanceof Error && error.cause === void 0) error.cause = cleanupError;
884
+ else throw new AggregateError([error, cleanupError], "Scene input preparation and cleanup both failed.");
885
+ }
886
+ throw error;
887
+ }
888
+ }
40
889
 
41
890
  // ../execution/core/src/render/emphasis.ts
42
891
  function buildEmphasisSet(emphasisWords) {
@@ -400,7 +1249,7 @@ function assertBehindSubjectCaptionCoverage(captionSegments, clips, fps) {
400
1249
  }
401
1250
  }
402
1251
 
403
- // ../execution/core/src/render/compositionRender.ts
1252
+ // ../execution/core/src/render/trackProjection.ts
404
1253
  function projectClipEffects(clip, renderClipId, identity) {
405
1254
  const effects = clip.effects;
406
1255
  if (!effects || effects.length === 0) return [];
@@ -420,33 +1269,6 @@ function visualIdentity(track, trackIndex, trackCount, contentIndex) {
420
1269
  contentIndex
421
1270
  };
422
1271
  }
423
- function compositionFormatDimensions(format) {
424
- const fps = format.fps ?? 30;
425
- const resolution = format.resolution ?? "fhd";
426
- const dims = {
427
- "9:16": {
428
- hd: { width: 720, height: 1280 },
429
- fhd: { width: 1080, height: 1920 },
430
- "4k": { width: 2160, height: 3840 }
431
- },
432
- "1:1": {
433
- hd: { width: 720, height: 720 },
434
- fhd: { width: 1080, height: 1080 },
435
- "4k": { width: 2160, height: 2160 }
436
- },
437
- "4:5": {
438
- hd: { width: 720, height: 900 },
439
- fhd: { width: 1080, height: 1350 },
440
- "4k": { width: 2160, height: 2700 }
441
- },
442
- "16:9": {
443
- hd: { width: 1280, height: 720 },
444
- fhd: { width: 1920, height: 1080 },
445
- "4k": { width: 3840, height: 2160 }
446
- }
447
- };
448
- return { ...dims[format.aspectRatio][resolution], fps };
449
- }
450
1272
  function frames(seconds, fps) {
451
1273
  return Math.max(0, Math.round(seconds * fps));
452
1274
  }
@@ -467,12 +1289,32 @@ function mapTransitionType(type) {
467
1289
  return "fade";
468
1290
  }
469
1291
  }
470
- function overlayTransitionFields(c, fps) {
471
- return c.transitionIn ? {
1292
+ function overlayTransitionFields(c, fps, isSceneClip, locator) {
1293
+ if (!c.transitionIn) return {};
1294
+ const exact = c.transitionIn.duration * fps;
1295
+ const frames2 = Math.round(exact);
1296
+ if (isSceneClip(c)) {
1297
+ if (Math.abs(exact - frames2) > FRAME_LATTICE_EPSILON) {
1298
+ throw renderInputError(
1299
+ "component_scene_invalid",
1300
+ `${locator.compositionPath}.transitionIn.duration: scene shot '${c.id}' authors a ${c.transitionIn.duration}s boundary, which is ${exact} frames at ${fps} fps. Quantize it through the frame lattice (n/${fps} s) rather than letting the render round it.`,
1301
+ { ...locator, path: "transitionIn.duration" }
1302
+ );
1303
+ }
1304
+ if (c.transitionIn.type === "fade" && frames2 < 1) {
1305
+ throw renderInputError(
1306
+ "component_scene_invalid",
1307
+ `${locator.compositionPath}.transitionIn.duration: scene shot '${c.id}' authors a ${c.transitionIn.duration}s fade, which is zero frames at ${fps} fps. Lengthen the fade to at least one frame or author the boundary as a cut.`,
1308
+ { ...locator, path: "transitionIn.duration" }
1309
+ );
1310
+ }
1311
+ }
1312
+ return {
472
1313
  transitionIn: mapTransitionType(c.transitionIn.type),
473
- transitionDurationFrames: Math.max(1, Math.round(c.transitionIn.duration * fps))
474
- } : {};
1314
+ transitionDurationFrames: Math.max(1, frames2)
1315
+ };
475
1316
  }
1317
+ var FRAME_LATTICE_EPSILON = 1e-6;
476
1318
  function rendersNoFrames(c) {
477
1319
  return !(c.duration > 0);
478
1320
  }
@@ -690,10 +1532,15 @@ function clipTransformChannel(c) {
690
1532
  ...c.animate !== void 0 ? { animate: c.animate } : {}
691
1533
  };
692
1534
  }
693
- function projectOverlayTrack(track, trackIndex, trackCount, fps, alphaUrls = {}) {
1535
+ function projectOverlayTrack(track, trackIndex, trackCount, fps, alphaUrls = {}, isSceneClip = () => false) {
694
1536
  const overlays = [];
695
1537
  for (let i = 0; i < track.contents.length; i++) {
696
1538
  const c = track.contents[i];
1539
+ const transitionLocator = {
1540
+ trackId: track.id,
1541
+ clipId: c.id,
1542
+ compositionPath: `composition.tracks[${track.id}].contents[${i}]`
1543
+ };
697
1544
  if (!("source" in c) || !c.source) continue;
698
1545
  if (c.effects && c.effects.length > 0) {
699
1546
  throw renderInputError(
@@ -702,6 +1549,45 @@ function projectOverlayTrack(track, trackIndex, trackCount, fps, alphaUrls = {})
702
1549
  { trackId: track.id, clipId: c.id, compositionPath: `composition.tracks[${track.id}].contents[${i}].effects` }
703
1550
  );
704
1551
  }
1552
+ if (c.source.kind === "component") {
1553
+ const { startFrame: startFrame2, durationInFrames: durationInFrames2 } = timelineSpanFrames(
1554
+ c.startTime,
1555
+ c.startTime + c.duration,
1556
+ fps
1557
+ );
1558
+ if (durationInFrames2 === 0) continue;
1559
+ const rawRef = c.source.props.componentRef;
1560
+ const ref = rawRef && typeof rawRef === "object" && !Array.isArray(rawRef) ? rawRef : null;
1561
+ if (ref?.version !== 1 || typeof ref.sourceVersionId !== "string" || !/^[a-f0-9]{64}$/.test(ref.sourceVersionId)) {
1562
+ throw renderInputError(
1563
+ "invalid_composition",
1564
+ `composition.tracks[${track.id}].contents[${i}].source: component clip ${c.id} has no immutable source version`,
1565
+ { trackId: track.id, clipId: c.id, componentId: c.source.componentId }
1566
+ );
1567
+ }
1568
+ const { componentRef: _reserved, renderSeed, ...params } = c.source.props;
1569
+ if (renderSeed !== void 0 && (typeof renderSeed !== "string" || renderSeed.length === 0)) {
1570
+ throw renderInputError("invalid_composition", `composition.tracks[${track.id}].contents[${i}].source.props.renderSeed must be a non-empty string`, transitionLocator);
1571
+ }
1572
+ overlays.push({
1573
+ ...visualIdentity(track, trackIndex, trackCount, i),
1574
+ id: c.id,
1575
+ template: "component",
1576
+ componentId: c.source.componentId,
1577
+ sourceVersionId: ref.sourceVersionId,
1578
+ ...renderSeed !== void 0 ? { renderSeed } : {},
1579
+ componentAssets: c.source.assets ?? {},
1580
+ startFrame: startFrame2,
1581
+ durationInFrames: durationInFrames2,
1582
+ params,
1583
+ ...c.source.zPlane !== void 0 ? { zPlane: c.source.zPlane } : {},
1584
+ ...c.region !== void 0 ? { region: c.region } : {},
1585
+ ...c.fit !== void 0 ? { fit: c.fit } : {},
1586
+ ...overlayTransitionFields(c, fps, isSceneClip, transitionLocator),
1587
+ ...clipTransformChannel(c)
1588
+ });
1589
+ continue;
1590
+ }
705
1591
  if (c.source.kind === "alpha-layer") {
706
1592
  const { startFrame: startFrame2, durationInFrames: durationInFrames2 } = timelineSpanFrames(
707
1593
  c.startTime,
@@ -732,7 +1618,7 @@ function projectOverlayTrack(track, trackIndex, trackCount, fps, alphaUrls = {})
732
1618
  ...c.source.zPlane !== void 0 ? { zPlane: c.source.zPlane } : {},
733
1619
  ...c.region !== void 0 ? { region: c.region } : {},
734
1620
  ...c.fit !== void 0 ? { fit: c.fit } : {},
735
- ...overlayTransitionFields(c, fps),
1621
+ ...overlayTransitionFields(c, fps, isSceneClip, transitionLocator),
736
1622
  ...clipTransformChannel(c)
737
1623
  });
738
1624
  continue;
@@ -757,7 +1643,7 @@ function projectOverlayTrack(track, trackIndex, trackCount, fps, alphaUrls = {})
757
1643
  ...c.source.zPlane !== void 0 ? { zPlane: c.source.zPlane } : {},
758
1644
  ...c.region !== void 0 ? { region: c.region } : {},
759
1645
  ...c.fit !== void 0 ? { fit: c.fit } : {},
760
- ...overlayTransitionFields(c, fps),
1646
+ ...overlayTransitionFields(c, fps, isSceneClip, transitionLocator),
761
1647
  ...clipTransformChannel(c)
762
1648
  });
763
1649
  continue;
@@ -795,7 +1681,7 @@ function projectOverlayTrack(track, trackIndex, trackCount, fps, alphaUrls = {})
795
1681
  ...c.source.parallax !== void 0 ? { parallax: c.source.parallax } : {},
796
1682
  ...c.region !== void 0 ? { region: c.region } : {},
797
1683
  ...c.fit !== void 0 ? { fit: c.fit } : {},
798
- ...overlayTransitionFields(c, fps),
1684
+ ...overlayTransitionFields(c, fps, isSceneClip, transitionLocator),
799
1685
  ...clipTransformChannel(c)
800
1686
  });
801
1687
  }
@@ -831,6 +1717,35 @@ function projectEffectTrack(track, trackIndex, trackCount, fps) {
831
1717
  }
832
1718
  return effects;
833
1719
  }
1720
+
1721
+ // ../execution/core/src/render/compositionRender.ts
1722
+ function compositionFormatDimensions(format) {
1723
+ const fps = format.fps ?? 30;
1724
+ const resolution = format.resolution ?? "fhd";
1725
+ const dims = {
1726
+ "9:16": {
1727
+ hd: { width: 720, height: 1280 },
1728
+ fhd: { width: 1080, height: 1920 },
1729
+ "4k": { width: 2160, height: 3840 }
1730
+ },
1731
+ "1:1": {
1732
+ hd: { width: 720, height: 720 },
1733
+ fhd: { width: 1080, height: 1080 },
1734
+ "4k": { width: 2160, height: 2160 }
1735
+ },
1736
+ "4:5": {
1737
+ hd: { width: 720, height: 900 },
1738
+ fhd: { width: 1080, height: 1350 },
1739
+ "4k": { width: 2160, height: 2700 }
1740
+ },
1741
+ "16:9": {
1742
+ hd: { width: 1280, height: 720 },
1743
+ fhd: { width: 1920, height: 1080 },
1744
+ "4k": { width: 3840, height: 2160 }
1745
+ }
1746
+ };
1747
+ return { ...dims[format.aspectRatio][resolution], fps };
1748
+ }
834
1749
  function referencedMediaIds(composition) {
835
1750
  const ids = /* @__PURE__ */ new Set();
836
1751
  for (const track of composition.tracks) {
@@ -843,9 +1758,25 @@ function referencedMediaIds(composition) {
843
1758
  }
844
1759
  return [...ids];
845
1760
  }
846
- function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUrls, alphaUrls, subCompositions, trajectories) {
1761
+ function assertMergedCaptionFacesDrawable(composition) {
1762
+ const captions = composition.captions;
1763
+ if (!captions?.segments.some((segment) => segment.words.length > 0)) return;
1764
+ const brandCaption = composition.brandKit?.caption;
1765
+ const issues = mergedCaptionFaceIssues(captions.style, brandCaption);
1766
+ if (issues.length === 0) return;
1767
+ throw renderInputError(
1768
+ "font_not_reproducible",
1769
+ "The caption style this render draws is the brand kit's caption block over the composition's own style, and that merge names a face with no file behind it: " + issues.map((issue) => `${issue.path}: ${issue.message}`).join(" "),
1770
+ {
1771
+ compositionPath: issues[0].path,
1772
+ fields: issues.map((issue) => issue.path)
1773
+ }
1774
+ );
1775
+ }
1776
+ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUrls, alphaUrls, subCompositions, trajectories, options) {
847
1777
  const flattened = hasCompoundClips(composition) ? flattenCompoundClips(composition, (id) => subCompositions?.[id]) : composition;
848
1778
  composition = flattened;
1779
+ assertMergedCaptionFacesDrawable(composition);
849
1780
  const { width, height, fps } = compositionFormatDimensions(composition.format);
850
1781
  const clips = [];
851
1782
  const overlays = [];
@@ -884,7 +1815,8 @@ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUr
884
1815
  trackIndex,
885
1816
  trackCount,
886
1817
  fps,
887
- alphaUrls ?? {}
1818
+ alphaUrls ?? {},
1819
+ options?.isSceneClip
888
1820
  ));
889
1821
  } else if (track.kind === "effect") {
890
1822
  effects.push(...projectEffectTrack(track, trackIndex, trackCount, fps));
@@ -948,6 +1880,7 @@ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUr
948
1880
  const captionStyle = hasCaptions && (cap || baseStyle || captionMotion) ? {
949
1881
  ...baseStyle ?? {},
950
1882
  ...cap?.fontFamily ? { fontFamily: cap.fontFamily } : {},
1883
+ ...cap?.fontWeight != null ? { fontWeight: cap.fontWeight } : {},
951
1884
  ...cap?.color ? { color: cap.color } : {},
952
1885
  ...cap?.plate ? { plate: cap.plate } : {},
953
1886
  ...cap?.emphasisFontFamily ? { emphasisFontFamily: cap.emphasisFontFamily } : {},
@@ -984,18 +1917,37 @@ function compositionToRenderInput(composition, srcUrls, trajectoryUrls, coViewUr
984
1917
  };
985
1918
  }
986
1919
  function assembleRenderInput(composition, resolved) {
1920
+ const resolveSource = resolved.componentSources ? sceneSourceResolverForPinnedRows(resolved.componentSources) : null;
1921
+ if (resolveSource) {
1922
+ assertSceneClipShapes(composition, {
1923
+ fps: compositionFormatDimensions(composition.format).fps,
1924
+ resolveSource
1925
+ });
1926
+ }
987
1927
  const renderInput = compositionToRenderInput(
988
1928
  composition,
989
1929
  resolved.srcUrls,
990
1930
  resolved.trajectoryUrls ?? {},
991
1931
  resolved.coViewUrls ?? {},
992
- resolved.alphaUrls ?? {}
1932
+ resolved.alphaUrls ?? {},
1933
+ void 0,
1934
+ resolved.trajectories,
1935
+ // The same manifest-backed answer the shape rules used, so projection cannot floor a scene
1936
+ // clip's boundary into a length the rules above would have refused.
1937
+ resolveSource ? { isSceneClip: (clip) => isSceneShotClip(clip, resolveSource) } : void 0
993
1938
  );
994
1939
  if (renderInput.brandKit && resolved.fontAssets && resolved.fontAssets.length > 0) {
995
1940
  renderInput.brandKit.fontAssets = resolved.fontAssets;
996
1941
  }
1942
+ if (resolved.componentSources && Object.keys(resolved.componentSources).length > 0) {
1943
+ return structuredClone({ ...renderInput, componentSources: resolved.componentSources });
1944
+ }
997
1945
  return renderInput;
998
1946
  }
1947
+ async function assemblePreparedRenderInput(composition, resolved, dependencies) {
1948
+ const input = assembleRenderInput(composition, resolved);
1949
+ return prepareSceneShotRenderInput(input, dependencies);
1950
+ }
999
1951
 
1000
1952
  // ../execution/core/src/render/exportSettings.ts
1001
1953
  var DEFAULT_FPS = 30;
@@ -1965,6 +2917,29 @@ function mapFaceIdToPersonId(faceTrack, personTrack, faceId) {
1965
2917
  }
1966
2918
 
1967
2919
  export {
2920
+ SCENE_CAPTURE_IDENTITY_FIELDS,
2921
+ SceneCaptureIdentityRefusal,
2922
+ canonicalSceneJsonV1,
2923
+ parseSceneComponentCaptureIntentV1,
2924
+ parseSceneComponentCaptureIdentityV1,
2925
+ completeSceneComponentCaptureIdentityV1,
2926
+ canonicalSceneComponentCaptureIdentityV1,
2927
+ SCENE_SLAB_CONTENT_OFFSET_V1,
2928
+ sceneSlabBuilderDescriptorV1,
2929
+ createSceneSlabDescriptorRegistryV1,
2930
+ createSceneBuilderDescriptorRegistryV1,
2931
+ ScenePlanRefusal,
2932
+ prepareSceneShotPreflightV1,
2933
+ assertScenePlanOutputV1,
2934
+ realizeSceneShotPlanV1,
2935
+ SCENE_SHOT_PREPARATION_STAGE,
2936
+ SCENE_SHOT_PARAM,
2937
+ SCENE_SHOT_IMAGE_MIME_TYPES,
2938
+ readSceneShotManifest,
2939
+ sceneSourceResolverForPinnedRows,
2940
+ assertSceneClipShapes,
2941
+ resolvePinnedSceneFactsV1,
2942
+ prepareSceneShotRenderInput,
1968
2943
  buildEmphasisSet,
1969
2944
  isEmphasized,
1970
2945
  sliceTranscriptWords,
@@ -1976,11 +2951,12 @@ export {
1976
2951
  resolveBookendTimeline,
1977
2952
  validateComposition,
1978
2953
  assertBehindSubjectCaptionCoverage,
1979
- compositionFormatDimensions,
1980
2954
  playableSpans,
2955
+ compositionFormatDimensions,
1981
2956
  referencedMediaIds,
1982
2957
  compositionToRenderInput,
1983
2958
  assembleRenderInput,
2959
+ assemblePreparedRenderInput,
1984
2960
  DEFAULT_FPS,
1985
2961
  DEFAULT_WIDTH,
1986
2962
  DEFAULT_HEIGHT,