@pixel-point/toolcraft 0.0.17 → 0.0.19

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 (503) hide show
  1. package/package.json +1 -1
  2. package/src/generate-demand-only-lifecycle.test.mjs +9 -1
  3. package/src/generate-performance-iteration-execution.test.mjs +3 -3
  4. package/src/generate-test-delivery-architecture-assertions.mjs +11 -73
  5. package/src/generate-test-demand-only-lifecycle.mjs +34 -36
  6. package/src/generate-test-dependency-sandbox.mjs +4 -1
  7. package/src/generate-test-doc-assertions.mjs +81 -89
  8. package/src/generate-test-doc-assertions.test.mjs +44 -1
  9. package/src/generate-test-doc-policy-assertions.mjs +92 -0
  10. package/src/generate-test-export-doc-assertions.mjs +53 -0
  11. package/src/generate-test-file-assertions.mjs +77 -83
  12. package/src/generate-test-integrity-assertions.mjs +5 -2
  13. package/src/generate-test-integrity-manifest-assertions.mjs +16 -5
  14. package/src/generate-test-integrity-ownership-assertions.mjs +36 -4
  15. package/src/generate-test-package-assertions.mjs +4 -0
  16. package/src/generate-test-product-fixture.mjs +1 -1
  17. package/src/generate-test-product-fixture.test.mjs +35 -38
  18. package/src/generate-test-product-iteration.mjs +0 -1
  19. package/src/generate-test-product-iteration.test.mjs +17 -1
  20. package/src/generate-test-runtime-boundary-assertions.mjs +178 -0
  21. package/src/generate-test-standalone-assertions.mjs +7 -13
  22. package/src/generate-test-standalone-delivery-stages.mjs +2 -86
  23. package/src/generate.test.mjs +4 -0
  24. package/src/generated-integrity-manifest.test.mjs +5 -2
  25. package/src/generated-source-policy.test.mjs +0 -4
  26. package/src/package-json.mjs +5 -0
  27. package/src/package-json.test.mjs +21 -0
  28. package/src/package-manager.mjs +2 -0
  29. package/src/package-manager.test.mjs +8 -0
  30. package/src/packaged-template-fallback-helpers.mjs +254 -0
  31. package/src/packaged-template-fallback.test.mjs +121 -46
  32. package/src/packaged-template-runtime-assertions.mjs +150 -0
  33. package/templates/runtime/contracts/component-contracts.choices.test.ts +64 -5
  34. package/templates/runtime/contracts/component-contracts.choices.ts +55 -5
  35. package/templates/runtime/contracts/component-contracts.inputs.test.ts +6 -6
  36. package/templates/runtime/contracts/component-contracts.inputs.ts +8 -7
  37. package/templates/runtime/contracts/component-contracts.media-custom.test.ts +8 -2
  38. package/templates/runtime/contracts/component-contracts.media-custom.ts +8 -2
  39. package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +22 -8
  40. package/templates/runtime/contracts/component-contracts.runtime-labels.test.ts +7 -1
  41. package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +3 -0
  42. package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +4 -1
  43. package/templates/runtime/contracts/component-contracts.runtime.ts +19 -12
  44. package/templates/runtime/contracts/component-contracts.test.ts +2 -0
  45. package/templates/runtime/contracts/component-contracts.visual.test.ts +20 -0
  46. package/templates/runtime/contracts/component-contracts.visual.ts +4 -0
  47. package/templates/runtime/contracts/decision-contracts.test.ts +35 -11
  48. package/templates/runtime/contracts/decision-contracts.ts +12 -12
  49. package/templates/runtime/contracts/performance-verification-policy.test.ts +12 -12
  50. package/templates/runtime/contracts/performance-verification-policy.ts +8 -8
  51. package/templates/runtime/export/artifact-download.ts +1 -0
  52. package/templates/runtime/export/artifact-frame-renderer.ts +2 -15
  53. package/templates/runtime/export/artifact-frame-state.ts +16 -0
  54. package/templates/runtime/export/artifact-scene-frame.test.ts +3 -3
  55. package/templates/runtime/export/artifact-scene-frame.ts +3 -3
  56. package/templates/runtime/export/export-background.ts +0 -19
  57. package/templates/runtime/export/export-error.ts +5 -0
  58. package/templates/runtime/export/export-renderer-coverage.ts +54 -0
  59. package/templates/runtime/export/export.test.ts +45 -42
  60. package/templates/runtime/export/image-artifact-export.ts +2 -2
  61. package/templates/runtime/export/index.ts +57 -16
  62. package/templates/runtime/export/product-export-renderer.test.ts +38 -4
  63. package/templates/runtime/export/product-export-renderer.ts +0 -41
  64. package/templates/runtime/export/product-svg-export-renderer.ts +21 -0
  65. package/templates/runtime/export/svg-artifact-export.test.ts +98 -0
  66. package/templates/runtime/export/svg-artifact-export.ts +120 -0
  67. package/templates/runtime/export/svg-document.test.ts +221 -0
  68. package/templates/runtime/export/svg-document.ts +400 -0
  69. package/templates/runtime/export/svg-policy.ts +47 -0
  70. package/templates/runtime/index.ts +3 -0
  71. package/templates/runtime/model-import/model-import-limits.ts +15 -4
  72. package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +21 -1
  73. package/templates/runtime/react/app-shell/settings-transfer.test.ts +21 -0
  74. package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +75 -1
  75. package/templates/runtime/react/app-shell/toolcraft-app.tsx +24 -9
  76. package/templates/runtime/react/canvas/canvas-shell-interactions.test.tsx +30 -0
  77. package/templates/runtime/react/canvas/canvas-shell-pinch-interactions.test.tsx +155 -0
  78. package/templates/runtime/react/canvas/canvas-shell-rendering.test.tsx +77 -1
  79. package/templates/runtime/react/canvas/canvas-shell-test-utils.tsx +13 -1
  80. package/templates/runtime/react/canvas/canvas-shell.tsx +32 -6
  81. package/templates/runtime/react/canvas/canvas-viewport-geometry.ts +133 -0
  82. package/templates/runtime/react/canvas/product-scene-surface.test.tsx +195 -0
  83. package/templates/runtime/react/canvas/product-scene-surface.tsx +155 -0
  84. package/templates/runtime/react/canvas/runtime-scene-export.ts +1 -1
  85. package/templates/runtime/react/canvas/use-canvas-viewport-interactions.ts +285 -36
  86. package/templates/runtime/react/controls-panel/__tests__/control-conditions.test.ts +61 -0
  87. package/templates/runtime/react/controls-panel/__tests__/controls-panel.collection-actions.test.tsx +89 -0
  88. package/templates/runtime/react/controls-panel/__tests__/controls-panel.color-applicability-layout.test.tsx +134 -0
  89. package/templates/runtime/react/controls-panel/__tests__/controls-panel.color-layout.test.tsx +16 -1
  90. package/templates/runtime/react/controls-panel/__tests__/controls-panel.control-visibility.test.tsx +40 -19
  91. package/templates/runtime/react/controls-panel/__tests__/controls-panel.render-isolation.test.tsx +2 -0
  92. package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +40 -1
  93. package/templates/runtime/react/controls-panel/__tests__/controls-panel.setup-controls.test.tsx +3 -3
  94. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-collection.test.tsx +59 -0
  95. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-color-bank.test.tsx +67 -0
  96. package/templates/runtime/react/controls-panel/__tests__/controls-panel.vector-interaction.test.tsx +6 -6
  97. package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +4 -6
  98. package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +41 -6
  99. package/templates/runtime/react/controls-panel/conditions/control-conditions.ts +32 -119
  100. package/templates/runtime/react/controls-panel/layout/controls-panel-control-group.tsx +5 -2
  101. package/templates/runtime/react/controls-panel/layout/controls-panel-layout.tsx +41 -10
  102. package/templates/runtime/react/controls-panel/layout/controls-panel-section.tsx +7 -4
  103. package/templates/runtime/react/controls-panel/renderers/controls-panel-action-renderer.tsx +2 -1
  104. package/templates/runtime/react/controls-panel/renderers/controls-panel-basic-renderers.tsx +2 -52
  105. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.test.tsx +63 -0
  106. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.tsx +138 -0
  107. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-items.tsx +104 -0
  108. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-renderer.tsx +115 -236
  109. package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.test.tsx +95 -0
  110. package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.tsx +82 -0
  111. package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.test.tsx +73 -1
  112. package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.tsx +50 -1
  113. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.test.ts +1 -1
  114. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.ts +2 -1
  115. package/templates/runtime/react/controls-panel/values/controls-panel-collection-values.ts +38 -6
  116. package/templates/runtime/react/controls-panel/values/controls-panel-color-values.ts +1 -9
  117. package/templates/runtime/react/controls-panel/values/controls-panel-spatial-values.ts +7 -2
  118. package/templates/runtime/react/controls-panel/values/controls-panel-value-labels.ts +1 -0
  119. package/templates/runtime/react/index.ts +4 -0
  120. package/templates/runtime/react/model-rendering/model-export.ts +1 -1
  121. package/templates/runtime/react/orientation-gizmo/orientation-gizmo-math.ts +9 -69
  122. package/templates/runtime/react/orientation-gizmo/orientation-gizmo-selection.ts +5 -5
  123. package/templates/runtime/react/orientation-gizmo/use-toolcraft-orientation-control-selection.ts +2 -2
  124. package/templates/runtime/scene/scene-bounds.test.ts +23 -0
  125. package/templates/runtime/scene/scene-bounds.ts +31 -17
  126. package/templates/runtime/schema/app-capabilities.test.ts +4 -0
  127. package/templates/runtime/schema/artifact-export-actions.test.ts +47 -0
  128. package/templates/runtime/schema/artifact-export-actions.ts +49 -0
  129. package/templates/runtime/schema/collection-item-controls.ts +29 -0
  130. package/templates/runtime/schema/control-applicability.test.ts +127 -0
  131. package/templates/runtime/schema/control-applicability.ts +433 -0
  132. package/templates/runtime/schema/control-schema-normalization.ts +177 -11
  133. package/templates/runtime/schema/controls-panel-actions.ts +2 -2
  134. package/templates/runtime/schema/controls-panel-section-layout.ts +14 -9
  135. package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +59 -0
  136. package/templates/runtime/schema/define-toolcraft.collection-actions-item-controls.test.ts +127 -0
  137. package/templates/runtime/schema/define-toolcraft.control-sections.test.ts +10 -4
  138. package/templates/runtime/schema/define-toolcraft.file-drop-item-controls.test.ts +98 -0
  139. package/templates/runtime/schema/define-toolcraft.file-drop-normalization.test.ts +27 -0
  140. package/templates/runtime/schema/define-toolcraft.segmented-control-fit.test.ts +20 -2
  141. package/templates/runtime/schema/define-toolcraft.setup-canvas.test.ts +16 -3
  142. package/templates/runtime/schema/define-toolcraft.source-collection.test.ts +79 -0
  143. package/templates/runtime/schema/runtime-setup-section.ts +24 -5
  144. package/templates/runtime/schema/types.ts +69 -13
  145. package/templates/runtime/state/canvas-background-state.ts +1 -16
  146. package/templates/runtime/state/canvas-state.ts +32 -20
  147. package/templates/runtime/state/control-value-codecs.test.ts +98 -0
  148. package/templates/runtime/state/control-value-codecs.ts +700 -0
  149. package/templates/runtime/state/control-value-normalization.test.ts +1 -1
  150. package/templates/runtime/state/control-value-normalization.ts +127 -135
  151. package/templates/runtime/state/controls-reducer.ts +26 -3
  152. package/templates/runtime/state/create-template-state.test.ts +30 -0
  153. package/templates/runtime/state/create-template-state.ts +52 -31
  154. package/templates/runtime/state/orientation-pose.ts +80 -0
  155. package/templates/runtime/state/persistence-control-values.test.ts +59 -0
  156. package/templates/runtime/state/reducer-controls.test.ts +45 -0
  157. package/templates/runtime/state/reducer-media-reset.test.ts +1 -1
  158. package/templates/runtime/state/reducer-timeline.test.ts +70 -0
  159. package/templates/runtime/state/timeline-reducer.ts +40 -2
  160. package/templates/runtime/testing/performance-schema-queries.ts +2 -2
  161. package/templates/starter/AGENTS.md +29 -28
  162. package/templates/starter/docs/toolcraft/README.md +6 -6
  163. package/templates/starter/docs/toolcraft/acceptance-testing.md +34 -48
  164. package/templates/starter/docs/toolcraft/agent-worklog.md +103 -1
  165. package/templates/starter/docs/toolcraft/assembly-workflow.md +16 -8
  166. package/templates/starter/docs/toolcraft/component-rules.md +9 -7
  167. package/templates/starter/docs/toolcraft/core/control-selection.md +9 -3
  168. package/templates/starter/docs/toolcraft/core/layout.md +13 -8
  169. package/templates/starter/docs/toolcraft/core/media-upload.md +3 -1
  170. package/templates/starter/docs/toolcraft/core/performance.md +8 -10
  171. package/templates/starter/docs/toolcraft/core/reference-study.md +80 -19
  172. package/templates/starter/docs/toolcraft/core/runtime-boundary.md +15 -3
  173. package/templates/starter/docs/toolcraft/core/setup-export.md +67 -11
  174. package/templates/starter/docs/toolcraft/custom-controls.md +6 -4
  175. package/templates/starter/docs/toolcraft/decision-contract.md +4 -2
  176. package/templates/starter/docs/toolcraft/performance.md +8 -10
  177. package/templates/starter/docs/toolcraft/renderer-technique.md +6 -2
  178. package/templates/starter/docs/toolcraft/schema-reference.md +24 -22
  179. package/templates/starter/docs/toolcraft/workflow.md +14 -14
  180. package/templates/starter/e2e/app-browser-control-applicability-requirements.spec.ts +163 -0
  181. package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +45 -2
  182. package/templates/starter/e2e/app-browser-motion-reference-requirements.spec.ts +411 -0
  183. package/templates/starter/e2e/app-browser-orientation-evidence.spec.ts +174 -21
  184. package/templates/starter/e2e/app-browser-proof-session.spec.ts +85 -0
  185. package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +63 -33
  186. package/templates/starter/e2e/app-browser-selection-scope-evidence.spec.ts +137 -0
  187. package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +61 -15
  188. package/templates/starter/e2e/{browser-conditional-output-evidence-helpers.ts → browser-background-output-evidence.ts} +0 -68
  189. package/templates/starter/e2e/browser-control-applicability-evidence.ts +114 -0
  190. package/templates/starter/e2e/browser-infinity-canvas-evidence.ts +20 -11
  191. package/templates/starter/e2e/browser-infinity-canvas-svg-evidence.ts +42 -0
  192. package/templates/starter/e2e/browser-layer-evidence-helpers.ts +15 -36
  193. package/templates/starter/e2e/browser-orientation-gizmo-evidence-helpers.ts +4 -0
  194. package/templates/starter/e2e/browser-orientation-gizmo-live-preconditions.ts +86 -0
  195. package/templates/starter/e2e/browser-product-raster-snapshot.ts +213 -0
  196. package/templates/starter/e2e/browser-proof-session.ts +43 -15
  197. package/templates/starter/e2e/browser-proof-surface-action.ts +79 -0
  198. package/templates/starter/e2e/browser-proof-types.ts +15 -0
  199. package/templates/starter/e2e/browser-runtime-applicability-requirements.ts +84 -0
  200. package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +9 -2
  201. package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +51 -32
  202. package/templates/starter/e2e/browser-selection-scope-evidence.ts +269 -0
  203. package/templates/starter/e2e/browser-semantic-evidence-test-helpers.ts +122 -0
  204. package/templates/starter/e2e/browser-svg-export-evidence.spec.ts +79 -0
  205. package/templates/starter/e2e/browser-svg-export-evidence.ts +152 -0
  206. package/templates/starter/e2e/export-artifact-helpers.ts +70 -0
  207. package/templates/starter/e2e/product-observable-helpers.ts +8 -129
  208. package/templates/starter/e2e/svg-artifact-inspection.spec.ts +136 -0
  209. package/templates/starter/e2e/svg-artifact-inspection.ts +331 -0
  210. package/templates/starter/e2e/svg-download-test-fixtures.ts +34 -0
  211. package/templates/starter/e2e/toolcraft-delivery-catalog-reporter.ts +198 -15
  212. package/templates/starter/e2e/toolcraft-feature-verification-reporter.spec.ts +149 -0
  213. package/templates/starter/e2e/toolcraft-feature-verification-reporter.ts +223 -0
  214. package/templates/starter/package.json +2 -0
  215. package/templates/starter/scripts/check-toolcraft-docs.mjs +1 -0
  216. package/templates/starter/scripts/create-toolcraft-motion-reference-study.mjs +233 -0
  217. package/templates/starter/scripts/create-toolcraft-motion-reference-study.test.mjs +459 -0
  218. package/templates/starter/scripts/playwright-test-title-selection.d.mts +45 -0
  219. package/templates/starter/scripts/run-browser-performance-test-helpers.mjs +0 -27
  220. package/templates/starter/scripts/run-browser-performance.mjs +0 -6
  221. package/templates/starter/scripts/run-browser-performance.test.mjs +5 -13
  222. package/templates/starter/scripts/run-delivery-verification-test-helpers.mjs +0 -34
  223. package/templates/starter/scripts/run-delivery-verification.test.mjs +135 -31
  224. package/templates/starter/scripts/run-feature-verification.mjs +212 -0
  225. package/templates/starter/scripts/run-feature-verification.test.mjs +226 -0
  226. package/templates/starter/scripts/toolcraft-checkpoint-delivery-state.mjs +21 -8
  227. package/templates/starter/scripts/toolcraft-checkpoint-delivery-state.test.mjs +32 -92
  228. package/templates/starter/scripts/toolcraft-checkpoint-transaction.mjs +28 -6
  229. package/templates/starter/scripts/toolcraft-checkpoint-transaction.test.mjs +8 -63
  230. package/templates/starter/scripts/toolcraft-contract-manifest.json +1 -0
  231. package/templates/starter/scripts/toolcraft-delivery-anchor.mjs +28 -8
  232. package/templates/starter/scripts/toolcraft-delivery-anchor.test.mjs +50 -61
  233. package/templates/starter/scripts/toolcraft-delivery-architecture-inventory.mjs +0 -4
  234. package/templates/starter/scripts/toolcraft-delivery-architecture-policy.mjs +0 -1
  235. package/templates/starter/scripts/toolcraft-delivery-evidence.test.mjs +2 -3
  236. package/templates/starter/scripts/toolcraft-delivery-executor.mjs +5 -1
  237. package/templates/starter/scripts/toolcraft-delivery-executor.test.mjs +5 -12
  238. package/templates/starter/scripts/toolcraft-delivery-functional-context.d.mts +1 -48
  239. package/templates/starter/scripts/toolcraft-delivery-functional-context.mjs +2 -30
  240. package/templates/starter/scripts/toolcraft-delivery-functional-context.test.mjs +4 -166
  241. package/templates/starter/scripts/toolcraft-delivery-functional-initial.test.mjs +4 -20
  242. package/templates/starter/scripts/toolcraft-delivery-lifecycle.mjs +43 -192
  243. package/templates/starter/scripts/toolcraft-delivery-performance-iteration-lifecycle.test.mjs +79 -440
  244. package/templates/starter/scripts/toolcraft-delivery-plan-authority.test.mjs +102 -297
  245. package/templates/starter/scripts/toolcraft-delivery-plan-construction.mjs +46 -97
  246. package/templates/starter/scripts/toolcraft-delivery-plan-test-helpers.mjs +125 -0
  247. package/templates/starter/scripts/toolcraft-delivery-plan-validation.test.mjs +58 -0
  248. package/templates/starter/scripts/toolcraft-delivery-plan.d.mts +19 -31
  249. package/templates/starter/scripts/toolcraft-delivery-plan.mjs +254 -252
  250. package/templates/starter/scripts/toolcraft-delivery-plan.test.mjs +29 -457
  251. package/templates/starter/scripts/toolcraft-delivery-receipt-performance.test.mjs +1 -1
  252. package/templates/starter/scripts/toolcraft-delivery-receipt-strictness.test.mjs +3 -72
  253. package/templates/starter/scripts/toolcraft-delivery-receipt-test-helpers.mjs +7 -36
  254. package/templates/starter/scripts/toolcraft-delivery-receipt.d.mts +3 -5
  255. package/templates/starter/scripts/toolcraft-delivery-receipt.mjs +15 -31
  256. package/templates/starter/scripts/toolcraft-delivery-receipt.test.mjs +28 -20
  257. package/templates/starter/scripts/toolcraft-delivery-receipt.types.test.mts +22 -30
  258. package/templates/starter/scripts/toolcraft-feature-verification-plan.d.mts +20 -0
  259. package/templates/starter/scripts/toolcraft-feature-verification-plan.mjs +146 -0
  260. package/templates/starter/scripts/toolcraft-feature-verification-plan.test.mjs +96 -0
  261. package/templates/starter/scripts/toolcraft-functional-proof-model.d.mts +3 -18
  262. package/templates/starter/scripts/toolcraft-functional-proof-model.mjs +39 -127
  263. package/templates/starter/scripts/toolcraft-functional-proof-model.test.mjs +25 -362
  264. package/templates/starter/scripts/toolcraft-functional-proof-model.types.test.mts +6 -83
  265. package/templates/starter/scripts/toolcraft-functional-proof-primitives.d.mts +11 -0
  266. package/templates/starter/scripts/toolcraft-functional-proof-primitives.mjs +61 -0
  267. package/templates/starter/scripts/toolcraft-functional-proof-primitives.test.mjs +43 -0
  268. package/templates/starter/scripts/toolcraft-integrity-policy.mjs +13 -0
  269. package/templates/starter/scripts/toolcraft-integrity-test-utils.mjs +1 -1
  270. package/templates/starter/scripts/toolcraft-layer-evidence-facade.test.mjs +58 -22
  271. package/templates/starter/scripts/toolcraft-motion-reference-analysis-protocol.mjs +111 -0
  272. package/templates/starter/scripts/toolcraft-motion-reference-analysis-protocol.test.mjs +116 -0
  273. package/templates/starter/scripts/toolcraft-motion-reference-artifacts.d.mts +37 -0
  274. package/templates/starter/scripts/toolcraft-motion-reference-artifacts.mjs +308 -0
  275. package/templates/starter/scripts/toolcraft-motion-reference-artifacts.test.mjs +420 -0
  276. package/templates/starter/scripts/toolcraft-motion-reference-artifacts.types.test.mts +50 -0
  277. package/templates/starter/scripts/toolcraft-motion-reference-command-options.mjs +195 -0
  278. package/templates/starter/scripts/toolcraft-motion-reference-command-options.test.mjs +224 -0
  279. package/templates/starter/scripts/toolcraft-motion-reference-contact-sheet.mjs +122 -0
  280. package/templates/starter/scripts/toolcraft-motion-reference-contact-sheet.test.mjs +153 -0
  281. package/templates/starter/scripts/toolcraft-motion-reference-evidence-assembly.mjs +270 -0
  282. package/templates/starter/scripts/toolcraft-motion-reference-evidence.test.mjs +432 -0
  283. package/templates/starter/scripts/toolcraft-motion-reference-ffmpeg-output.mjs +275 -0
  284. package/templates/starter/scripts/toolcraft-motion-reference-ffmpeg-output.test.mjs +294 -0
  285. package/templates/starter/scripts/toolcraft-motion-reference-group-inventory.mjs +148 -0
  286. package/templates/starter/scripts/toolcraft-motion-reference-image-filter-graph.mjs +101 -0
  287. package/templates/starter/scripts/toolcraft-motion-reference-image-filter-graph.test.mjs +124 -0
  288. package/templates/starter/scripts/toolcraft-motion-reference-image-source.mjs +259 -0
  289. package/templates/starter/scripts/toolcraft-motion-reference-image-source.test.mjs +338 -0
  290. package/templates/starter/scripts/toolcraft-motion-reference-image-timing.mjs +96 -0
  291. package/templates/starter/scripts/toolcraft-motion-reference-image-timing.test.mjs +81 -0
  292. package/templates/starter/scripts/toolcraft-motion-reference-lock-recovery.test.mjs +144 -0
  293. package/templates/starter/scripts/toolcraft-motion-reference-media-source.mjs +165 -0
  294. package/templates/starter/scripts/toolcraft-motion-reference-media-source.test.mjs +299 -0
  295. package/templates/starter/scripts/toolcraft-motion-reference-publication-discovery.test.mjs +142 -0
  296. package/templates/starter/scripts/toolcraft-motion-reference-publication-isolation.test.mjs +234 -0
  297. package/templates/starter/scripts/toolcraft-motion-reference-publication-journal-schema.mjs +122 -0
  298. package/templates/starter/scripts/toolcraft-motion-reference-publication-journal-store.mjs +89 -0
  299. package/templates/starter/scripts/toolcraft-motion-reference-publication-journal-store.test.mjs +74 -0
  300. package/templates/starter/scripts/toolcraft-motion-reference-publication-journal.mjs +264 -0
  301. package/templates/starter/scripts/toolcraft-motion-reference-publication-journal.test.mjs +377 -0
  302. package/templates/starter/scripts/toolcraft-motion-reference-publication-lease.mjs +254 -0
  303. package/templates/starter/scripts/toolcraft-motion-reference-publication-lease.test.mjs +130 -0
  304. package/templates/starter/scripts/toolcraft-motion-reference-publication-staging.mjs +128 -0
  305. package/templates/starter/scripts/toolcraft-motion-reference-publication-staging.test.mjs +209 -0
  306. package/templates/starter/scripts/toolcraft-motion-reference-publication.fixtures.mjs +88 -0
  307. package/templates/starter/scripts/toolcraft-motion-reference-publication.mjs +249 -0
  308. package/templates/starter/scripts/toolcraft-motion-reference-publication.test.mjs +433 -0
  309. package/templates/starter/scripts/toolcraft-motion-reference-review-output.mjs +38 -0
  310. package/templates/starter/scripts/toolcraft-motion-reference-review-output.test.mjs +29 -0
  311. package/templates/starter/scripts/toolcraft-motion-reference-root-safety.test.mjs +84 -0
  312. package/templates/starter/scripts/toolcraft-motion-reference-roots.mjs +83 -0
  313. package/templates/starter/scripts/toolcraft-motion-reference-sampling.mjs +283 -0
  314. package/templates/starter/scripts/toolcraft-motion-reference-sampling.test.mjs +480 -0
  315. package/templates/starter/scripts/toolcraft-motion-reference-stage-registry.mjs +39 -0
  316. package/templates/starter/scripts/toolcraft-motion-reference-stage-registry.test.mjs +59 -0
  317. package/templates/starter/scripts/toolcraft-motion-reference-stage.mjs +71 -0
  318. package/templates/starter/scripts/toolcraft-motion-reference-stage.test.mjs +61 -0
  319. package/templates/starter/scripts/toolcraft-motion-review-numeric.mjs +74 -0
  320. package/templates/starter/scripts/toolcraft-motion-review-numeric.test.mjs +65 -0
  321. package/templates/starter/scripts/toolcraft-motion-review-partitioning.mjs +268 -0
  322. package/templates/starter/scripts/toolcraft-motion-review-partitioning.test.mjs +329 -0
  323. package/templates/starter/scripts/toolcraft-motion-review-protected-units.mjs +120 -0
  324. package/templates/starter/scripts/toolcraft-motion-review-protected-units.test.mjs +111 -0
  325. package/templates/starter/scripts/toolcraft-performance-escalation-policy.test.mjs +77 -345
  326. package/templates/starter/scripts/toolcraft-performance-receipt-validation.test.mjs +19 -21
  327. package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +85 -115
  328. package/templates/starter/scripts/toolcraft-product-boundary-module-policy.mjs +101 -0
  329. package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +0 -72
  330. package/templates/starter/scripts/toolcraft-product-control-bindings.mjs +182 -0
  331. package/templates/starter/scripts/toolcraft-product-control-boundary.mjs +146 -0
  332. package/templates/starter/scripts/toolcraft-product-control-boundary.test.mjs +186 -0
  333. package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +16 -18
  334. package/templates/starter/scripts/toolcraft-product-export-boundary.test.mjs +200 -0
  335. package/templates/starter/scripts/toolcraft-product-observable-facade.test.mjs +46 -1
  336. package/templates/starter/scripts/toolcraft-receipt-boundary.test.mjs +0 -1
  337. package/templates/starter/scripts/toolcraft-source-inventory.d.mts +5 -0
  338. package/templates/starter/scripts/toolcraft-source-inventory.mjs +25 -14
  339. package/templates/starter/scripts/toolcraft-source-inventory.test.mjs +48 -0
  340. package/templates/starter/scripts/toolcraft-source-ownership.mjs +0 -1
  341. package/templates/starter/scripts/toolcraft-source-ownership.test.mjs +30 -5
  342. package/templates/starter/scripts/toolcraft-typescript-source-evidence-structure.test.mjs +20 -0
  343. package/templates/starter/scripts/toolcraft-typescript-source-evidence.mjs +1 -0
  344. package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +2 -0
  345. package/templates/starter/scripts/toolcraft-verification-receipt-test-helpers.mjs +5 -26
  346. package/templates/starter/scripts/toolcraft-verification-receipt.d.mts +0 -7
  347. package/templates/starter/scripts/toolcraft-verification-receipt.mjs +3 -47
  348. package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +6 -87
  349. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.d.mts +19 -0
  350. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.mjs +107 -0
  351. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.test.mjs +114 -0
  352. package/templates/starter/scripts/toolcraft-vitest-runtime-evidence-reporter.mjs +13 -2
  353. package/templates/starter/scripts/toolcraft-vitest-runtime-evidence-reporter.test.mjs +110 -0
  354. package/templates/starter/src/app/acceptance/artifact-export-intent.ts +161 -0
  355. package/templates/starter/src/app/acceptance/canvas-coverage.ts +1 -0
  356. package/templates/starter/src/app/acceptance/color-bank-labels.ts +11 -15
  357. package/templates/starter/src/app/acceptance/color-row-grouping.ts +33 -0
  358. package/templates/starter/src/app/acceptance/conditions.ts +1 -1
  359. package/templates/starter/src/app/acceptance/control-acceptance-context.ts +2 -2
  360. package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +6 -31
  361. package/templates/starter/src/app/acceptance/control-acceptance-kind-rules.ts +24 -5
  362. package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +4 -16
  363. package/templates/starter/src/app/acceptance/control-applicability-cases.test.ts +321 -0
  364. package/templates/starter/src/app/acceptance/control-applicability-cases.ts +290 -0
  365. package/templates/starter/src/app/acceptance/control-applicability.ts +332 -0
  366. package/templates/starter/src/app/acceptance/control-component-rules.ts +0 -10
  367. package/templates/starter/src/app/acceptance/control-labels.ts +30 -1
  368. package/templates/starter/src/app/acceptance/control-layout-dependency-rules.ts +20 -9
  369. package/templates/starter/src/app/acceptance/control-layout-entity-rules.ts +4 -6
  370. package/templates/starter/src/app/acceptance/control-layout-model.ts +4 -4
  371. package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +21 -10
  372. package/templates/starter/src/app/acceptance/control-parts.ts +8 -0
  373. package/templates/starter/src/app/acceptance/control-section-entity-cohesion.test.ts +215 -0
  374. package/templates/starter/src/app/acceptance/control-section-entity-cohesion.ts +132 -0
  375. package/templates/starter/src/app/acceptance/control-section-inventory.test.ts +87 -0
  376. package/templates/starter/src/app/acceptance/control-section-inventory.ts +74 -44
  377. package/templates/starter/src/app/acceptance/custom-controls.ts +11 -3
  378. package/templates/starter/src/app/acceptance/export-artifact-coverage.ts +25 -17
  379. package/templates/starter/src/app/acceptance/feature-verification-selection.test.ts +295 -0
  380. package/templates/starter/src/app/acceptance/feature-verification-selection.ts +161 -0
  381. package/templates/starter/src/app/acceptance/infinity-canvas.ts +10 -0
  382. package/templates/starter/src/app/acceptance/inline-layout.ts +64 -9
  383. package/templates/starter/src/app/acceptance/interaction-ownership-intent.ts +19 -1
  384. package/templates/starter/src/app/acceptance/interaction-ownership.ts +18 -2
  385. package/templates/starter/src/app/acceptance/media-upload.ts +5 -1
  386. package/templates/starter/src/app/acceptance/motion-reference-evidence-validation.mjs +65 -0
  387. package/templates/starter/src/app/acceptance/motion-reference-evidence-windows.mjs +301 -0
  388. package/templates/starter/src/app/acceptance/motion-reference-evidence.d.mts +11 -0
  389. package/templates/starter/src/app/acceptance/motion-reference-evidence.mjs +145 -0
  390. package/templates/starter/src/app/acceptance/motion-reference-study-behaviors.ts +162 -0
  391. package/templates/starter/src/app/acceptance/motion-reference-study-coverage.ts +206 -0
  392. package/templates/starter/src/app/acceptance/motion-reference-study-identity.ts +129 -0
  393. package/templates/starter/src/app/acceptance/motion-reference-study-partitions.ts +186 -0
  394. package/templates/starter/src/app/acceptance/motion-reference-study.ts +90 -0
  395. package/templates/starter/src/app/acceptance/orientation-gizmo.ts +18 -11
  396. package/templates/starter/src/app/acceptance/output-background-rules.ts +2 -2
  397. package/templates/starter/src/app/acceptance/output-export-actions.test.ts +9 -1
  398. package/templates/starter/src/app/acceptance/output-export-actions.ts +14 -22
  399. package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +22 -10
  400. package/templates/starter/src/app/acceptance/output-export-model.ts +58 -11
  401. package/templates/starter/src/app/acceptance/output-export.ts +25 -10
  402. package/templates/starter/src/app/acceptance/output-video-export-rules.ts +99 -0
  403. package/templates/starter/src/app/acceptance/reference-study-types.ts +167 -17
  404. package/templates/starter/src/app/acceptance/runtime-coverage.ts +6 -1
  405. package/templates/starter/src/app/acceptance/selection-scope.test.ts +200 -0
  406. package/templates/starter/src/app/acceptance/selection-scope.ts +151 -0
  407. package/templates/starter/src/app/acceptance/transfer-mode-types.ts +114 -0
  408. package/templates/starter/src/app/acceptance/types.ts +65 -125
  409. package/templates/starter/src/app/acceptance/validate-coverage.ts +33 -5
  410. package/templates/starter/src/app/starter-acceptance-data.ts +1 -0
  411. package/templates/starter/src/app/starter-acceptance.animation-intent.test.ts +3 -0
  412. package/templates/starter/src/app/starter-acceptance.artifact-export-intent.test.ts +312 -0
  413. package/templates/starter/src/app/starter-acceptance.background-export.test.ts +35 -0
  414. package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +18 -1
  415. package/templates/starter/src/app/starter-acceptance.color-row-grouping.test.ts +118 -0
  416. package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +66 -1
  417. package/templates/starter/src/app/starter-acceptance.contract-fixtures.test.ts +41 -0
  418. package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +113 -16
  419. package/templates/starter/src/app/starter-acceptance.control-applicability.test.ts +225 -0
  420. package/templates/starter/src/app/starter-acceptance.control-label-context.test.ts +1 -0
  421. package/templates/starter/src/app/starter-acceptance.control-labels.test.ts +78 -3
  422. package/templates/starter/src/app/starter-acceptance.control-naming-rules.test.ts +77 -1
  423. package/templates/starter/src/app/starter-acceptance.control-order.test.ts +58 -3
  424. package/templates/starter/src/app/starter-acceptance.control-state.test.ts +0 -111
  425. package/templates/starter/src/app/starter-acceptance.custom-control-collections.test.ts +3 -1
  426. package/templates/starter/src/app/starter-acceptance.custom-control-fit-check.test.ts +1 -1
  427. package/templates/starter/src/app/starter-acceptance.custom-control-valid.test.ts +1 -1
  428. package/templates/starter/src/app/starter-acceptance.export-artifact.test.ts +74 -3
  429. package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +26 -0
  430. package/templates/starter/src/app/{starter-acceptance.image-video-export-settings.test.ts → starter-acceptance.image-export-settings.test.ts} +39 -9
  431. package/templates/starter/src/app/starter-acceptance.interaction-ownership.test.ts +31 -3
  432. package/templates/starter/src/app/starter-acceptance.layers.test.ts +2 -1
  433. package/templates/starter/src/app/starter-acceptance.media-upload.fixtures.ts +11 -1
  434. package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +56 -0
  435. package/templates/starter/src/app/starter-acceptance.motion-reference-evidence.test.ts +17 -0
  436. package/templates/starter/src/app/starter-acceptance.motion-reference-identity.test.ts +163 -0
  437. package/templates/starter/src/app/starter-acceptance.motion-reference-mapping.test.ts +133 -0
  438. package/templates/starter/src/app/starter-acceptance.motion-reference-ownership.test.ts +121 -0
  439. package/templates/starter/src/app/starter-acceptance.motion-reference-partitions.test.ts +210 -0
  440. package/templates/starter/src/app/starter-acceptance.motion-reference-test-utils.ts +313 -0
  441. package/templates/starter/src/app/starter-acceptance.output-export-intent.test.ts +458 -0
  442. package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +4 -0
  443. package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +116 -104
  444. package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +29 -0
  445. package/templates/starter/src/app/starter-acceptance.product-worklog.test.ts +123 -2
  446. package/templates/starter/src/app/starter-acceptance.reference-custom-timeline.test.ts +2 -0
  447. package/templates/starter/src/app/starter-acceptance.reference-foundation.test.ts +8 -0
  448. package/templates/starter/src/app/starter-acceptance.reference-timeline.test.ts +7 -0
  449. package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +3 -1
  450. package/templates/starter/src/app/starter-acceptance.section-dependencies.test.ts +35 -24
  451. package/templates/starter/src/app/starter-acceptance.section-size.test.ts +72 -0
  452. package/templates/starter/src/app/starter-acceptance.timeline-playback.test.ts +5 -0
  453. package/templates/starter/src/app/starter-acceptance.ts +45 -10
  454. package/templates/starter/src/app/starter-acceptance.video-export-settings.test.ts +338 -0
  455. package/templates/starter/src/app/starter-acceptance.video-reference-study.test.ts +34 -236
  456. package/templates/starter/src/app/starter-acceptance.view-interaction.test.ts +12 -0
  457. package/templates/starter/src/app/starter-acceptance.worklog-test-utils.ts +122 -6
  458. package/templates/starter/src/app/starter-acceptance.worklog.test.ts +152 -16
  459. package/templates/starter/src/app/starter-performance.gates.test.ts +20 -18
  460. package/templates/starter/src/app/starter-performance.lifecycle.test.ts +22 -6
  461. package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +5 -2
  462. package/templates/starter/src/routes/index.tsx +1 -0
  463. package/templates/starter/tsconfig.json +1 -0
  464. package/templates/ui/components/composites/tabs.tsx +2 -2
  465. package/templates/ui/components/controls/collection-actions/collection-item-groups.test.tsx +38 -0
  466. package/templates/ui/components/controls/collection-actions/collection-item-groups.tsx +36 -0
  467. package/templates/ui/components/controls/collection-actions/index.ts +2 -0
  468. package/templates/ui/components/controls/file-drop/file-drop-collection-control.tsx +137 -0
  469. package/templates/ui/components/controls/file-drop/file-drop-control.test.tsx +189 -0
  470. package/templates/ui/components/controls/file-drop/file-drop-control.tsx +81 -88
  471. package/templates/ui/components/controls/file-drop/file-drop-presentation.tsx +131 -9
  472. package/templates/ui/components/controls/file-drop/file-drop-types.ts +36 -22
  473. package/templates/ui/components/controls/file-drop/index.ts +1 -0
  474. package/templates/ui/components/controls/index.ts +3 -0
  475. package/templates/ui/components/controls/range-slider/range-slider-control.tsx +1 -1
  476. package/templates/ui/components/controls/range-slider/range-slider-value.test.ts +14 -0
  477. package/templates/ui/components/controls/range-slider/range-slider-value.ts +3 -2
  478. package/templates/starter/scripts/toolcraft-browser-impact-selection.mjs +0 -26
  479. package/templates/starter/scripts/toolcraft-delivery-framework-refresh.test.mjs +0 -141
  480. package/templates/starter/scripts/toolcraft-delivery-functional-changed.test.mjs +0 -468
  481. package/templates/starter/scripts/toolcraft-delivery-functional-model-lifecycle.test.mjs +0 -254
  482. package/templates/starter/scripts/toolcraft-delivery-functional-semantic-regression.test.mjs +0 -135
  483. package/templates/starter/scripts/toolcraft-delivery-performance-iteration-durability.test.mjs +0 -329
  484. package/templates/starter/scripts/toolcraft-delivery-plan-errors.test.mjs +0 -430
  485. package/templates/starter/scripts/toolcraft-delivery-plan-functional-model.test.mjs +0 -358
  486. package/templates/starter/scripts/toolcraft-functional-proof-regression-fixtures.mjs +0 -298
  487. package/templates/starter/scripts/toolcraft-verification-impact-inventory.d.mts +0 -62
  488. package/templates/starter/scripts/toolcraft-verification-impact-inventory.mjs +0 -344
  489. package/templates/starter/scripts/toolcraft-verification-impact-inventory.test.mjs +0 -204
  490. package/templates/starter/scripts/toolcraft-verification-impact-performance-candidates.test.mjs +0 -210
  491. package/templates/starter/scripts/toolcraft-verification-impact-resolution.mjs +0 -344
  492. package/templates/starter/scripts/toolcraft-verification-impact-resolution.test.mjs +0 -270
  493. package/templates/starter/scripts/toolcraft-verification-impact-semantic-resolution.test.mjs +0 -449
  494. package/templates/starter/scripts/toolcraft-verification-impact-support-resolution.test.mjs +0 -195
  495. package/templates/starter/scripts/toolcraft-verification-impact.d.mts +0 -132
  496. package/templates/starter/scripts/toolcraft-verification-impact.mjs +0 -169
  497. package/templates/starter/scripts/toolcraft-verification-impact.test.mjs +0 -300
  498. package/templates/starter/scripts/toolcraft-verification-input-roles.mjs +0 -197
  499. package/templates/starter/scripts/toolcraft-verification-input-roles.test.mjs +0 -225
  500. package/templates/starter/src/app/acceptance/condition-exclusivity.test.ts +0 -60
  501. package/templates/starter/src/app/acceptance/condition-exclusivity.ts +0 -221
  502. package/templates/starter/src/app/acceptance/video-reference-study.ts +0 -217
  503. package/templates/starter/src/app/starter-verification-impact.json +0 -15
@@ -0,0 +1,206 @@
1
+ import type { ToolcraftMotionReferenceInput } from "./types";
2
+
3
+ const validEventClassifications = new Set<string>([
4
+ "edit-boundary",
5
+ "encoding-artifact",
6
+ "irrelevant-change",
7
+ "product-behavior",
8
+ ]);
9
+
10
+ export function validateStudyCoverage(
11
+ input: ToolcraftMotionReferenceInput,
12
+ ): string[] {
13
+ const errors: string[] = [];
14
+ const behaviorsById = new Map<string, typeof input.behaviors>();
15
+ for (const behavior of input.behaviors) {
16
+ behaviorsById.set(behavior.id, [
17
+ ...(behaviorsById.get(behavior.id) ?? []),
18
+ behavior,
19
+ ]);
20
+ }
21
+
22
+ function validateBehaviorId({
23
+ behaviorId,
24
+ owner,
25
+ }: {
26
+ behaviorId: string;
27
+ owner: string;
28
+ }): void {
29
+ const behaviors = behaviorsById.get(behaviorId) ?? [];
30
+ if (behaviors.length === 0) {
31
+ errors.push(`${owner} cites unknown behaviorId "${behaviorId}".`);
32
+ } else if (behaviors.length > 1) {
33
+ errors.push(
34
+ `${owner} cites ambiguous behaviorId "${behaviorId}" with ${behaviors.length} definitions.`,
35
+ );
36
+ }
37
+ }
38
+
39
+ for (const study of input.studies) {
40
+ const reviewedFrameIndex = new Map(
41
+ study.evidence.reviewedFrames.map((frame, index) => [frame.frameId, index]),
42
+ );
43
+ const overviewFrameIndex = new Map<string, number>();
44
+ let previousReviewedFrameIndex = -1;
45
+
46
+ for (const [overviewIndex, frameId] of study.evidence.overviewFrameIds.entries()) {
47
+ const reviewedIndex = reviewedFrameIndex.get(frameId);
48
+
49
+ if (reviewedIndex === undefined) {
50
+ errors.push(
51
+ `motion reference study "${study.studyId}" overview frameId "${frameId}" must resolve to reviewedFrames.`,
52
+ );
53
+ continue;
54
+ }
55
+
56
+ if (reviewedIndex <= previousReviewedFrameIndex) {
57
+ errors.push(
58
+ `motion reference study "${study.studyId}" overviewFrameIds must follow reviewedFrames order; "${frameId}" resolves to index ${reviewedIndex} after ${previousReviewedFrameIndex}.`,
59
+ );
60
+ }
61
+
62
+ previousReviewedFrameIndex = reviewedIndex;
63
+ overviewFrameIndex.set(frameId, overviewIndex);
64
+ }
65
+
66
+ if (study.evidence.overviewFrameIds.length > 0 && study.phases.length === 0) {
67
+ errors.push(
68
+ `motion reference study "${study.studyId}" phases must cover the complete overview range.`,
69
+ );
70
+ }
71
+
72
+ let previousPhaseEndIndex: number | undefined;
73
+ for (const [phaseIndex, phase] of study.phases.entries()) {
74
+ const fromIndex = overviewFrameIndex.get(phase.fromFrameId);
75
+ const toIndex = overviewFrameIndex.get(phase.toFrameId);
76
+
77
+ if (fromIndex === undefined || toIndex === undefined) {
78
+ errors.push(
79
+ `motion reference study "${study.studyId}" phase "${phase.id}" frame range must resolve to overviewFrameIds.`,
80
+ );
81
+ continue;
82
+ }
83
+
84
+ if (fromIndex > toIndex) {
85
+ errors.push(
86
+ `motion reference study "${study.studyId}" phase "${phase.id}" must not end before it starts.`,
87
+ );
88
+ }
89
+
90
+ if (phaseIndex === 0 && fromIndex !== 0) {
91
+ errors.push(
92
+ `motion reference study "${study.studyId}" phases must start at overview index 0; "${phase.id}" starts at ${fromIndex}.`,
93
+ );
94
+ }
95
+
96
+ if (
97
+ previousPhaseEndIndex !== undefined &&
98
+ fromIndex !== previousPhaseEndIndex + 1
99
+ ) {
100
+ errors.push(
101
+ `motion reference study "${study.studyId}" phases must be contiguous; "${phase.id}" starts at overview index ${fromIndex} after index ${previousPhaseEndIndex}.`,
102
+ );
103
+ }
104
+ previousPhaseEndIndex = toIndex;
105
+
106
+ if (!phase.visualState.trim()) {
107
+ errors.push(
108
+ `motion reference study "${study.studyId}" phase "${phase.id}" must describe its visualState.`,
109
+ );
110
+ }
111
+
112
+ for (const behaviorId of phase.behaviorIds) {
113
+ validateBehaviorId({
114
+ behaviorId,
115
+ owner: `motion reference study "${study.studyId}" phase "${phase.id}"`,
116
+ });
117
+ }
118
+ }
119
+
120
+ const lastOverviewIndex = study.evidence.overviewFrameIds.length - 1;
121
+ if (
122
+ study.phases.length > 0 &&
123
+ previousPhaseEndIndex !== undefined &&
124
+ previousPhaseEndIndex !== lastOverviewIndex
125
+ ) {
126
+ errors.push(
127
+ `motion reference study "${study.studyId}" phases must end at overview index ${lastOverviewIndex}; received ${previousPhaseEndIndex}.`,
128
+ );
129
+ }
130
+
131
+ const evidenceEventsById = new Map(
132
+ study.evidence.detectedEvents.map((event) => [event.eventId, event]),
133
+ );
134
+ const authoredEventsByEvidenceId = new Map<string, typeof study.events>();
135
+
136
+ for (const event of study.events) {
137
+ const existing = authoredEventsByEvidenceId.get(event.evidenceEventId) ?? [];
138
+ authoredEventsByEvidenceId.set(event.evidenceEventId, [...existing, event]);
139
+
140
+ if (!evidenceEventsById.has(event.evidenceEventId)) {
141
+ errors.push(
142
+ `motion reference study "${study.studyId}" event "${event.id}" must cite a detected evidenceEventId.`,
143
+ );
144
+ }
145
+
146
+ if (!validEventClassifications.has(event.classification)) {
147
+ errors.push(
148
+ `motion reference study "${study.studyId}" event "${event.id}" has unsupported classification "${String(event.classification)}".`,
149
+ );
150
+ continue;
151
+ }
152
+
153
+ if (event.classification === "product-behavior") {
154
+ if (event.behaviorIds.length === 0) {
155
+ errors.push(
156
+ `motion reference study "${study.studyId}" product event "${event.id}" must cite at least one behaviorId.`,
157
+ );
158
+ }
159
+
160
+ for (const behaviorId of event.behaviorIds) {
161
+ validateBehaviorId({
162
+ behaviorId,
163
+ owner: `motion reference study "${study.studyId}" event "${event.id}"`,
164
+ });
165
+ }
166
+ } else {
167
+ if (event.behaviorIds.length !== 0) {
168
+ errors.push(
169
+ `motion reference study "${study.studyId}" event "${event.id}" classification "${event.classification}" must not cite behaviorIds.`,
170
+ );
171
+ }
172
+
173
+ if (!event.reason.trim()) {
174
+ errors.push(
175
+ `motion reference study "${study.studyId}" event "${event.id}" classification "${event.classification}" requires a non-empty reason.`,
176
+ );
177
+ }
178
+ }
179
+ }
180
+
181
+ for (const evidenceEvent of study.evidence.detectedEvents) {
182
+ const matchingAuthoredEvents =
183
+ authoredEventsByEvidenceId.get(evidenceEvent.eventId) ?? [];
184
+ if (matchingAuthoredEvents.length !== 1) {
185
+ errors.push(
186
+ `motion reference study "${study.studyId}" evidence event "${evidenceEvent.eventId}" must have exactly one authored event; found ${matchingAuthoredEvents.length}.`,
187
+ );
188
+ }
189
+
190
+ for (const frameId of [
191
+ evidenceEvent.beforeFrameId,
192
+ evidenceEvent.peakFrameId,
193
+ evidenceEvent.afterFrameId,
194
+ ...evidenceEvent.windowFrameIds,
195
+ ]) {
196
+ if (!reviewedFrameIndex.has(frameId)) {
197
+ errors.push(
198
+ `motion reference study "${study.studyId}" evidence event "${evidenceEvent.eventId}" frameId "${frameId}" must resolve to reviewedFrames.`,
199
+ );
200
+ }
201
+ }
202
+ }
203
+ }
204
+
205
+ return errors;
206
+ }
@@ -0,0 +1,129 @@
1
+ import type { ToolcraftMotionReferenceInput } from "./types";
2
+
3
+ export function getMotionReferenceSourceSha256(
4
+ input: ToolcraftMotionReferenceInput,
5
+ ): string | undefined {
6
+ const sourceSha256Values = new Set(
7
+ input.studies.map((study) => study.evidence.sourceSha256),
8
+ );
9
+
10
+ return sourceSha256Values.size === 1
11
+ ? sourceSha256Values.values().next().value
12
+ : undefined;
13
+ }
14
+
15
+ export function validateStudyIdentity(
16
+ input: ToolcraftMotionReferenceInput,
17
+ ): string[] {
18
+ const errors: string[] = [];
19
+ const studyIds = new Set<string>();
20
+ const evidencePaths = new Set<string>();
21
+ const sourceSha256Values = new Set<string>();
22
+ const behaviorIds = new Set<string>();
23
+
24
+ if (input.studies.length === 0) {
25
+ errors.push(
26
+ `motion reference "${input.referenceId}" must declare at least one study.`,
27
+ );
28
+ }
29
+
30
+ for (const behavior of input.behaviors) {
31
+ if (!behavior.id.trim()) {
32
+ errors.push(
33
+ `motion reference "${input.referenceId}" behaviors must include non-empty ids.`,
34
+ );
35
+ } else if (behaviorIds.has(behavior.id)) {
36
+ errors.push(
37
+ `motion reference "${input.referenceId}" behavior id "${behavior.id}" is duplicated.`,
38
+ );
39
+ }
40
+ behaviorIds.add(behavior.id);
41
+ }
42
+
43
+ for (const study of input.studies) {
44
+ const studyLabel = study.studyId.trim() || "<missing-study-id>";
45
+
46
+ if (!study.studyId.trim()) {
47
+ errors.push(
48
+ `motion reference "${input.referenceId}" studies must include non-empty studyId values.`,
49
+ );
50
+ } else if (studyIds.has(study.studyId)) {
51
+ errors.push(
52
+ `motion reference "${input.referenceId}" studyId "${study.studyId}" is duplicated.`,
53
+ );
54
+ }
55
+ studyIds.add(study.studyId);
56
+
57
+ if (evidencePaths.has(study.evidencePath)) {
58
+ errors.push(
59
+ `motion reference "${input.referenceId}" evidencePath "${study.evidencePath}" is duplicated.`,
60
+ );
61
+ }
62
+ evidencePaths.add(study.evidencePath);
63
+
64
+ if (study.evidence.studyId !== study.studyId) {
65
+ errors.push(
66
+ `motion reference study "${studyLabel}" must match evidence.studyId "${study.evidence.studyId}".`,
67
+ );
68
+ }
69
+
70
+ sourceSha256Values.add(study.evidence.sourceSha256);
71
+
72
+ const frameIds = new Set<string>();
73
+ for (const frame of study.evidence.reviewedFrames) {
74
+ if (frameIds.has(frame.frameId)) {
75
+ errors.push(
76
+ `motion reference study "${studyLabel}" reviewed frameId "${frame.frameId}" is duplicated.`,
77
+ );
78
+ }
79
+ frameIds.add(frame.frameId);
80
+
81
+ if (frame.sourceSha256 !== study.evidence.sourceSha256) {
82
+ errors.push(
83
+ `motion reference study "${studyLabel}" frame "${frame.frameId}" sourceSha256 must match its evidence sourceSha256.`,
84
+ );
85
+ }
86
+ }
87
+
88
+ const evidenceEventIds = new Set<string>();
89
+ for (const event of study.evidence.detectedEvents) {
90
+ if (evidenceEventIds.has(event.eventId)) {
91
+ errors.push(
92
+ `motion reference study "${studyLabel}" evidence eventId "${event.eventId}" is duplicated.`,
93
+ );
94
+ }
95
+ evidenceEventIds.add(event.eventId);
96
+ }
97
+
98
+ const eventIds = new Set<string>();
99
+ for (const event of study.events) {
100
+ if (eventIds.has(event.id)) {
101
+ errors.push(
102
+ `motion reference study "${studyLabel}" event id "${event.id}" is duplicated.`,
103
+ );
104
+ }
105
+ eventIds.add(event.id);
106
+ }
107
+
108
+ const phaseIds = new Set<string>();
109
+ for (const phase of study.phases) {
110
+ if (phaseIds.has(phase.id)) {
111
+ errors.push(
112
+ `motion reference study "${studyLabel}" phase id "${phase.id}" is duplicated.`,
113
+ );
114
+ }
115
+ phaseIds.add(phase.id);
116
+ }
117
+ }
118
+
119
+ if (sourceSha256Values.size > 1) {
120
+ const sortedSourceSha256Values = [...sourceSha256Values].sort((left, right) =>
121
+ left.localeCompare(right, "en"),
122
+ );
123
+ errors.push(
124
+ `motion reference "${input.referenceId}" studies must share one sourceSha256; found ${sortedSourceSha256Values.join(", ")}.`,
125
+ );
126
+ }
127
+
128
+ return errors;
129
+ }
@@ -0,0 +1,186 @@
1
+ import type { ToolcraftMotionReferenceInput } from "./types";
2
+
3
+ type TimedStudyEvidence = Extract<
4
+ ToolcraftMotionReferenceInput["studies"][number]["evidence"],
5
+ { timingMode: "seconds" }
6
+ >;
7
+ type ReviewPartition = NonNullable<TimedStudyEvidence["reviewPartition"]>;
8
+
9
+ type PartitionStudy = {
10
+ evidence: TimedStudyEvidence;
11
+ partition: ReviewPartition;
12
+ studyId: string;
13
+ };
14
+
15
+ function formatNumber(value: number): string {
16
+ return String(value);
17
+ }
18
+
19
+ function compareNumbers(left: number, right: number): number {
20
+ if (Number.isFinite(left) && Number.isFinite(right)) {
21
+ return left - right;
22
+ }
23
+ return formatNumber(left).localeCompare(formatNumber(right), "en");
24
+ }
25
+
26
+ export function validatePartitionCoverage(
27
+ input: ToolcraftMotionReferenceInput,
28
+ ): string[] {
29
+ const errors: string[] = [];
30
+ const groups = new Map<string, PartitionStudy[]>();
31
+
32
+ for (const study of input.studies) {
33
+ if (study.evidence.timingMode !== "seconds") {
34
+ continue;
35
+ }
36
+ const partition = study.evidence.reviewPartition;
37
+ if (!partition) {
38
+ continue;
39
+ }
40
+
41
+ const group = groups.get(partition.groupId) ?? [];
42
+ group.push({ evidence: study.evidence, partition, studyId: study.studyId });
43
+ groups.set(partition.groupId, group);
44
+ }
45
+
46
+ for (const [groupId, group] of groups) {
47
+ const countValues = [...new Set(group.map(({ partition }) => partition.count))];
48
+ const invalidCounts = countValues
49
+ .filter((count) => !Number.isSafeInteger(count) || count <= 0)
50
+ .sort(compareNumbers);
51
+ for (const count of invalidCounts) {
52
+ errors.push(
53
+ `motion reference partition "${groupId}" count must be a finite safe positive integer; received ${formatNumber(count)}.`,
54
+ );
55
+ }
56
+
57
+ const countIsShared = countValues.length === 1;
58
+ if (!countIsShared) {
59
+ errors.push(
60
+ `motion reference partition "${groupId}" studies must declare one shared count.`,
61
+ );
62
+ }
63
+
64
+ const validCounts = countValues.filter(
65
+ (count) => Number.isSafeInteger(count) && count > 0,
66
+ );
67
+ const oversizedCounts = validCounts
68
+ .filter((count) => count > group.length)
69
+ .sort(compareNumbers);
70
+ for (const count of oversizedCounts) {
71
+ errors.push(
72
+ `motion reference partition "${groupId}" count ${count} cannot exceed group cardinality ${group.length}.`,
73
+ );
74
+ }
75
+
76
+ const planValues = new Set(
77
+ group.map(({ partition }) => partition.planSha256),
78
+ );
79
+ const planIsShared = planValues.size === 1;
80
+ if (!planIsShared) {
81
+ errors.push(
82
+ `motion reference partition "${groupId}" studies must declare one shared planSha256.`,
83
+ );
84
+ }
85
+
86
+ const scopeStarts = new Set(
87
+ group.map(({ partition }) => partition.scope.startSeconds),
88
+ );
89
+ const scopeEnds = new Set(
90
+ group.map(({ partition }) => partition.scope.endSeconds),
91
+ );
92
+ const scopeIsShared = scopeStarts.size === 1 && scopeEnds.size === 1;
93
+ if (!scopeIsShared) {
94
+ errors.push(
95
+ `motion reference partition "${groupId}" studies must declare one shared scope.`,
96
+ );
97
+ }
98
+
99
+ const metadataIsValid =
100
+ invalidCounts.length === 0 &&
101
+ oversizedCounts.length === 0 &&
102
+ countIsShared &&
103
+ planIsShared &&
104
+ scopeIsShared;
105
+ if (!metadataIsValid) {
106
+ continue;
107
+ }
108
+
109
+ const [expectedCount] = countValues;
110
+ const [scopeStart] = scopeStarts;
111
+ const [scopeEnd] = scopeEnds;
112
+ if (
113
+ expectedCount === undefined ||
114
+ scopeStart === undefined ||
115
+ scopeEnd === undefined
116
+ ) {
117
+ continue;
118
+ }
119
+
120
+ const orderedGroup = [...group].sort((left, right) => {
121
+ const indexOrder = compareNumbers(
122
+ left.partition.index,
123
+ right.partition.index,
124
+ );
125
+ return indexOrder || left.studyId.localeCompare(right.studyId, "en");
126
+ });
127
+ const receivedIndices = orderedGroup.map(({ partition }) => partition.index);
128
+ const indicesAreExact =
129
+ orderedGroup.length === expectedCount &&
130
+ receivedIndices.every((index, position) => index === position);
131
+ if (!indicesAreExact) {
132
+ errors.push(
133
+ `motion reference partition "${groupId}" must contain indices 0..${expectedCount - 1} exactly; received ${receivedIndices.join(", ")}.`,
134
+ );
135
+ continue;
136
+ }
137
+
138
+ let previousEnd: number | undefined;
139
+ for (const { evidence, partition, studyId } of orderedGroup) {
140
+ const segment = evidence.segment;
141
+ if (!segment) {
142
+ errors.push(
143
+ `motion reference partition "${groupId}" study "${studyId}" must declare an explicit segment.`,
144
+ );
145
+ continue;
146
+ }
147
+
148
+ if (segment.endSeconds <= segment.startSeconds) {
149
+ errors.push(
150
+ `motion reference partition "${groupId}" study "${studyId}" segment must have positive duration.`,
151
+ );
152
+ }
153
+ if (partition.index === 0 && segment.startSeconds !== scopeStart) {
154
+ errors.push(
155
+ `motion reference partition "${groupId}" segments must start at scope.startSeconds ${scopeStart}; received ${segment.startSeconds}.`,
156
+ );
157
+ }
158
+ if (previousEnd !== undefined && segment.startSeconds !== previousEnd) {
159
+ errors.push(
160
+ `motion reference partition "${groupId}" segments must be contiguous and non-overlapping; index ${partition.index} starts at ${segment.startSeconds} after ${previousEnd}.`,
161
+ );
162
+ }
163
+ previousEnd = segment.endSeconds;
164
+
165
+ const scopeCoversFullSource =
166
+ scopeStart === 0 && scopeEnd === evidence.durationSeconds;
167
+ if (
168
+ scopeCoversFullSource &&
169
+ partition.index !== 0 &&
170
+ evidence.detectedEvents.some((event) => event.kind === "loop-seam")
171
+ ) {
172
+ errors.push(
173
+ `motion reference partition "${groupId}" original loop-seam evidence must appear only in index 0.`,
174
+ );
175
+ }
176
+ }
177
+
178
+ if (previousEnd !== undefined && previousEnd !== scopeEnd) {
179
+ errors.push(
180
+ `motion reference partition "${groupId}" segments must end at scope.endSeconds ${scopeEnd}; received ${previousEnd}.`,
181
+ );
182
+ }
183
+ }
184
+
185
+ return errors;
186
+ }
@@ -0,0 +1,90 @@
1
+ import { validateBehaviorCoverage } from "./motion-reference-study-behaviors";
2
+ import { validateStudyCoverage } from "./motion-reference-study-coverage";
3
+ import {
4
+ getMotionReferenceSourceSha256,
5
+ validateStudyIdentity,
6
+ } from "./motion-reference-study-identity";
7
+ import { validatePartitionCoverage } from "./motion-reference-study-partitions";
8
+ import type {
9
+ ToolcraftComponentAcceptance,
10
+ ToolcraftTransferMode,
11
+ } from "./types";
12
+
13
+ export function getToolcraftMotionReferenceStudyErrors({
14
+ acceptance,
15
+ transferMode,
16
+ }: {
17
+ acceptance: readonly ToolcraftComponentAcceptance[];
18
+ transferMode: ToolcraftTransferMode;
19
+ }): string[] {
20
+ const errors: string[] = [];
21
+ const acceptanceRowsById = new Map<string, ToolcraftComponentAcceptance[]>();
22
+ for (const entry of acceptance) {
23
+ acceptanceRowsById.set(entry.id, [
24
+ ...(acceptanceRowsById.get(entry.id) ?? []),
25
+ entry,
26
+ ]);
27
+ }
28
+ const referenceIds = new Set<string>();
29
+ const sourceOwners = new Map<string, string>();
30
+ const behaviorCountsByReferenceId = new Map<string, Map<string, number>>();
31
+
32
+ for (const input of transferMode.referenceInputs) {
33
+ if (referenceIds.has(input.referenceId)) {
34
+ errors.push(`motion reference id "${input.referenceId}" is duplicated.`);
35
+ }
36
+ referenceIds.add(input.referenceId);
37
+
38
+ errors.push(
39
+ ...validateStudyIdentity(input),
40
+ ...validateStudyCoverage(input),
41
+ ...validatePartitionCoverage(input),
42
+ ...validateBehaviorCoverage(input, acceptanceRowsById),
43
+ );
44
+
45
+ const sourceSha256 = getMotionReferenceSourceSha256(input);
46
+ if (sourceSha256) {
47
+ const existingOwner = sourceOwners.get(sourceSha256);
48
+ if (existingOwner) {
49
+ errors.push(
50
+ `motion reference sourceSha256 "${sourceSha256}" is declared by multiple reference inputs; merge their studies under one input.`,
51
+ );
52
+ } else {
53
+ sourceOwners.set(sourceSha256, input.referenceId);
54
+ }
55
+ }
56
+
57
+ const behaviorCounts =
58
+ behaviorCountsByReferenceId.get(input.referenceId) ??
59
+ new Map<string, number>();
60
+ for (const behavior of input.behaviors) {
61
+ behaviorCounts.set(
62
+ behavior.id,
63
+ (behaviorCounts.get(behavior.id) ?? 0) + 1,
64
+ );
65
+ }
66
+ behaviorCountsByReferenceId.set(input.referenceId, behaviorCounts);
67
+ }
68
+
69
+ for (const acceptanceEntry of acceptance) {
70
+ for (const coverage of acceptanceEntry.motionReferenceCoverage ?? []) {
71
+ const behaviorCount =
72
+ behaviorCountsByReferenceId
73
+ .get(coverage.referenceId)
74
+ ?.get(coverage.behaviorId) ?? 0;
75
+ if (behaviorCount === 0) {
76
+ errors.push(
77
+ `acceptance "${acceptanceEntry.id}" has dangling motion reference coverage for "${coverage.referenceId}" behavior "${coverage.behaviorId}".`,
78
+ );
79
+ } else if (behaviorCount > 1) {
80
+ errors.push(
81
+ `acceptance "${acceptanceEntry.id}" motion reference coverage for "${coverage.referenceId}" behavior "${coverage.behaviorId}" resolves to ${behaviorCount} behavior definitions; expected exactly one.`,
82
+ );
83
+ }
84
+ }
85
+ }
86
+
87
+ return [...new Set(errors)].sort((left, right) =>
88
+ left.localeCompare(right, "en"),
89
+ );
90
+ }
@@ -1,10 +1,13 @@
1
1
  import type {
2
2
  ResolvedToolcraftAppSchema,
3
- ToolcraftControlSchema,
3
+ ResolvedToolcraftControlSchema,
4
+ } from "@repo/toolcraft-runtime";
5
+ import {
6
+ areToolcraftPredicateSetsProvablyExclusive,
7
+ getToolcraftApplicabilityPredicates,
4
8
  } from "@repo/toolcraft-runtime";
5
9
 
6
10
  import { isToolcraftProductSectionControl } from "./controls";
7
- import { areToolcraftConditionSetsProvablyExclusive } from "./condition-exclusivity";
8
11
 
9
12
  const vectorOrbitIntentPattern =
10
13
  /\b(camera\s+orbit|object\s+orbit|model\s+orbit|3d\s+(?:orientation|rotation)|view\s+orientation|model\s+rotation|object\s+rotation)\b/i;
@@ -34,7 +37,7 @@ function getCrossLength(
34
37
  );
35
38
  }
36
39
 
37
- function hasValidOrientationDefault(control: ToolcraftControlSchema): boolean {
40
+ function hasValidOrientationDefault(control: ResolvedToolcraftControlSchema): boolean {
38
41
  if (!control.defaultValue || typeof control.defaultValue !== "object") {
39
42
  return false;
40
43
  }
@@ -55,7 +58,7 @@ function getOrientationControlErrors({
55
58
  controlId,
56
59
  sectionTitle,
57
60
  }: {
58
- control: ToolcraftControlSchema;
61
+ control: ResolvedToolcraftControlSchema;
59
62
  controlId: string;
60
63
  sectionTitle: string;
61
64
  }): string[] {
@@ -112,16 +115,20 @@ export function getToolcraftOrientationGizmoErrors(
112
115
  }
113
116
 
114
117
  const leftConditions = [
115
- left.section.visibleWhen,
116
- left.control.visibleWhen,
117
- ].filter((condition) => condition !== undefined);
118
+ ...(left.section.visibleWhen ? [left.section.visibleWhen] : []),
119
+ ...getToolcraftApplicabilityPredicates(
120
+ left.control.applicability,
121
+ ),
122
+ ];
118
123
  const rightConditions = [
119
- right.section.visibleWhen,
120
- right.control.visibleWhen,
121
- ].filter((condition) => condition !== undefined);
124
+ ...(right.section.visibleWhen ? [right.section.visibleWhen] : []),
125
+ ...getToolcraftApplicabilityPredicates(
126
+ right.control.applicability,
127
+ ),
128
+ ];
122
129
 
123
130
  if (
124
- !areToolcraftConditionSetsProvablyExclusive(
131
+ !areToolcraftPredicateSetsProvablyExclusive(
125
132
  leftConditions,
126
133
  rightConditions,
127
134
  )
@@ -83,7 +83,7 @@ export function getToolcraftOutputBackgroundErrors({
83
83
 
84
84
  if (!schemaHasOutputBackgroundColorControl(controls)) {
85
85
  errors.push(
86
- "Product apps with Export PNG must expose a user-facing background color control such as appearance.background or scene.background. Preview, PNG export, and video export must read that runtime value instead of hardcoding the product background.",
86
+ "Product apps with artifact export must expose a user-facing background color control such as appearance.background or scene.background. Preview, image export, and video export must read that runtime value instead of hardcoding the product background.",
87
87
  );
88
88
  }
89
89
 
@@ -103,7 +103,7 @@ export function getToolcraftOutputBackgroundErrors({
103
103
 
104
104
  if (!schemaHasOutputBackgroundToggleControl(controls)) {
105
105
  errors.push(
106
- 'Product apps with Export PNG must expose export.includeBackground in runtime Setup as a Switch labeled "Background". Runtime artifact export owns PNG alpha and preserves the background for JPEG and video; bounded live preview must use shouldIncludeToolcraftPreviewBackground(state).',
106
+ 'Product apps with artifact export must expose export.includeBackground in runtime Setup as a Switch labeled "Background". Runtime artifact export owns image alpha and preserves the background for opaque image formats and video; bounded live preview must use shouldIncludeToolcraftPreviewBackground(state).',
107
107
  );
108
108
  }
109
109