@pixel-point/toolcraft 0.0.16 → 0.0.18

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 (313) hide show
  1. package/package.json +1 -1
  2. package/src/generate-performance-iteration-execution.test.mjs +2 -2
  3. package/src/generate-test-demand-only-lifecycle.mjs +14 -3
  4. package/src/generate-test-dependency-sandbox.mjs +42 -5
  5. package/src/generate-test-doc-assertions.mjs +109 -69
  6. package/src/generate-test-doc-assertions.test.mjs +65 -0
  7. package/src/generate-test-doc-policy-assertions.mjs +92 -0
  8. package/src/generate-test-file-assertions.mjs +36 -118
  9. package/src/generate-test-output-assertions.mjs +95 -0
  10. package/src/generate-test-package-assertions.mjs +6 -0
  11. package/src/generate-test-performance-boundary-assertions.mjs +45 -0
  12. package/src/generate-test-product-fixture.mjs +1 -0
  13. package/src/generate-test-product-fixture.test.mjs +18 -0
  14. package/src/generate-test-product-iteration.mjs +1 -0
  15. package/src/generate-test-product-iteration.test.mjs +18 -0
  16. package/src/generate-test-runtime-boundary-assertions.mjs +158 -0
  17. package/src/generate-test-standalone-assertions.mjs +10 -0
  18. package/src/generate-test-standalone-delivery-stages.mjs +14 -6
  19. package/src/generate.test.mjs +14 -0
  20. package/templates/runtime/contracts/component-contracts.choices.test.ts +59 -12
  21. package/templates/runtime/contracts/component-contracts.choices.ts +58 -12
  22. package/templates/runtime/contracts/component-contracts.inputs.test.ts +6 -6
  23. package/templates/runtime/contracts/component-contracts.inputs.ts +6 -6
  24. package/templates/runtime/contracts/component-contracts.media-custom.test.ts +8 -2
  25. package/templates/runtime/contracts/component-contracts.media-custom.ts +8 -2
  26. package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +21 -6
  27. package/templates/runtime/contracts/component-contracts.runtime-labels.test.ts +7 -1
  28. package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +4 -1
  29. package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +4 -1
  30. package/templates/runtime/contracts/component-contracts.runtime.ts +15 -10
  31. package/templates/runtime/contracts/component-contracts.test.ts +2 -0
  32. package/templates/runtime/contracts/decision-contracts.test.ts +43 -4
  33. package/templates/runtime/contracts/decision-contracts.ts +10 -10
  34. package/templates/runtime/contracts/performance-verification-policy.test.ts +59 -6
  35. package/templates/runtime/contracts/performance-verification-policy.ts +5 -2
  36. package/templates/runtime/export/artifact-download.test.ts +71 -0
  37. package/templates/runtime/export/artifact-download.ts +80 -0
  38. package/templates/runtime/export/artifact-export-request.ts +23 -0
  39. package/templates/runtime/export/artifact-export-settings.test.ts +75 -0
  40. package/templates/runtime/export/artifact-export-settings.ts +96 -0
  41. package/templates/runtime/export/artifact-frame-renderer.test.ts +107 -0
  42. package/templates/runtime/export/artifact-frame-renderer.ts +96 -0
  43. package/templates/runtime/export/artifact-frame-state.test.ts +54 -0
  44. package/templates/runtime/export/artifact-frame-state.ts +44 -0
  45. package/templates/runtime/export/artifact-scene-frame.test.ts +84 -0
  46. package/templates/runtime/export/artifact-scene-frame.ts +118 -0
  47. package/templates/runtime/export/export-background.ts +46 -0
  48. package/templates/runtime/export/export-error.ts +43 -0
  49. package/templates/runtime/export/export.test.ts +49 -226
  50. package/templates/runtime/export/image-artifact-export.test.ts +111 -0
  51. package/templates/runtime/export/image-artifact-export.ts +145 -0
  52. package/templates/runtime/export/index.ts +44 -3
  53. package/templates/runtime/export/product-export-renderer.test.ts +77 -0
  54. package/templates/runtime/export/product-export-renderer.ts +63 -0
  55. package/templates/runtime/export/video-artifact-export.test.ts +166 -0
  56. package/templates/runtime/export/video-artifact-export.ts +164 -0
  57. package/templates/runtime/export/video-encoding-backend.ts +124 -0
  58. package/templates/runtime/export/video-encoding-policy.test.ts +68 -0
  59. package/templates/runtime/export/video-encoding-policy.ts +86 -0
  60. package/templates/runtime/export/video-frame-schedule.test.ts +58 -0
  61. package/templates/runtime/export/video-frame-schedule.ts +42 -0
  62. package/templates/runtime/index.ts +3 -0
  63. package/templates/runtime/model-import/model-import-limits.ts +15 -4
  64. package/templates/runtime/react/app-shell/runtime-public-api-runtime.test.tsx +291 -0
  65. package/templates/runtime/react/app-shell/runtime-public-api-test-support.ts +21 -0
  66. package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +15 -304
  67. package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +41 -27
  68. package/templates/runtime/react/app-shell/toolcraft-app.tsx +39 -11
  69. package/templates/runtime/react/app-shell/toolcraft-source-asset-context.test.tsx +16 -57
  70. package/templates/runtime/react/app-shell/toolcraft-source-asset-context.tsx +75 -434
  71. package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.test.ts +194 -0
  72. package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.ts +227 -0
  73. package/templates/runtime/react/app-shell/toolcraft-source-asset-provider-ownership.test.tsx +243 -0
  74. package/templates/runtime/react/app-shell/toolcraft-source-asset-test-support.ts +51 -0
  75. package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.test.ts +138 -0
  76. package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.ts +378 -0
  77. package/templates/runtime/react/canvas/canvas-shell-rendering.test.tsx +76 -0
  78. package/templates/runtime/react/canvas/canvas-shell-test-utils.tsx +13 -1
  79. package/templates/runtime/react/canvas/canvas-shell.tsx +16 -1
  80. package/templates/runtime/react/canvas/product-scene-surface.test.tsx +195 -0
  81. package/templates/runtime/react/canvas/product-scene-surface.tsx +155 -0
  82. package/templates/runtime/react/canvas/runtime-scene-export.ts +1 -1
  83. package/templates/runtime/react/controls-panel/__tests__/control-conditions.test.ts +61 -0
  84. package/templates/runtime/react/controls-panel/__tests__/controls-panel.collection-actions.test.tsx +89 -0
  85. package/templates/runtime/react/controls-panel/__tests__/controls-panel.control-visibility.test.tsx +40 -19
  86. package/templates/runtime/react/controls-panel/__tests__/controls-panel.footer-actions.test.tsx +7 -12
  87. package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +18 -84
  88. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-collection.test.tsx +62 -0
  89. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-color-bank.test.tsx +67 -0
  90. package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +43 -87
  91. package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +68 -0
  92. package/templates/runtime/react/controls-panel/conditions/control-conditions.ts +32 -119
  93. package/templates/runtime/react/controls-panel/layout/controls-panel-control-group.tsx +5 -2
  94. package/templates/runtime/react/controls-panel/layout/controls-panel-layout.tsx +10 -8
  95. package/templates/runtime/react/controls-panel/layout/controls-panel-section.tsx +3 -3
  96. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.test.tsx +63 -0
  97. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.tsx +138 -0
  98. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-items.tsx +104 -0
  99. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-renderer.tsx +115 -236
  100. package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.test.tsx +95 -0
  101. package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.tsx +82 -0
  102. package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.test.tsx +73 -1
  103. package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.tsx +50 -1
  104. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.test.ts +1 -1
  105. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.ts +2 -1
  106. package/templates/runtime/react/controls-panel/values/controls-panel-collection-values.ts +38 -6
  107. package/templates/runtime/react/controls-panel/values/controls-panel-value-labels.ts +1 -0
  108. package/templates/runtime/react/index.ts +4 -0
  109. package/templates/runtime/react/model-rendering/model-export.ts +1 -1
  110. package/templates/runtime/react/orientation-gizmo/orientation-gizmo-selection.ts +5 -5
  111. package/templates/runtime/react/orientation-gizmo/use-toolcraft-orientation-control-selection.ts +2 -2
  112. package/templates/runtime/react/panel-host/panel-host-runtime-placement.test.tsx +30 -0
  113. package/templates/runtime/react/panel-host/panel-host.tsx +4 -0
  114. package/templates/runtime/scene/scene-bounds.test.ts +23 -0
  115. package/templates/runtime/scene/scene-bounds.ts +32 -19
  116. package/templates/runtime/schema/app-capabilities.test.ts +4 -0
  117. package/templates/runtime/schema/canvas-render-scale.ts +62 -0
  118. package/templates/runtime/schema/collection-item-controls.ts +29 -0
  119. package/templates/runtime/schema/control-applicability.test.ts +127 -0
  120. package/templates/runtime/schema/control-applicability.ts +433 -0
  121. package/templates/runtime/schema/control-schema-normalization.ts +177 -11
  122. package/templates/runtime/schema/controls-panel-actions.ts +2 -2
  123. package/templates/runtime/schema/controls-panel-section-id.test.ts +1 -1
  124. package/templates/runtime/schema/controls-panel-section-layout.ts +14 -9
  125. package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +62 -3
  126. package/templates/runtime/schema/define-toolcraft.collection-actions-item-controls.test.ts +127 -0
  127. package/templates/runtime/schema/define-toolcraft.control-sections.test.ts +10 -4
  128. package/templates/runtime/schema/define-toolcraft.file-drop-item-controls.test.ts +98 -0
  129. package/templates/runtime/schema/define-toolcraft.file-drop-normalization.test.ts +27 -0
  130. package/templates/runtime/schema/define-toolcraft.segmented-control-fit.test.ts +20 -2
  131. package/templates/runtime/schema/define-toolcraft.setup-background.test.ts +1 -1
  132. package/templates/runtime/schema/define-toolcraft.setup-canvas.test.ts +16 -3
  133. package/templates/runtime/schema/define-toolcraft.setup-render-scale-timeline.test.ts +71 -3
  134. package/templates/runtime/schema/define-toolcraft.source-collection.test.ts +79 -0
  135. package/templates/runtime/schema/define-toolcraft.ts +1 -1
  136. package/templates/runtime/schema/runtime-setup-section.ts +24 -5
  137. package/templates/runtime/schema/schema-resolvers.ts +0 -56
  138. package/templates/runtime/schema/types.ts +72 -17
  139. package/templates/runtime/state/canvas-background-state.ts +6 -0
  140. package/templates/runtime/testing/performance-render-plan-integration.test.ts +64 -0
  141. package/templates/runtime/testing/performance-renderer-pipeline-validation.ts +18 -1
  142. package/templates/starter/AGENTS.md +18 -15
  143. package/templates/starter/NOTICE.md +6 -0
  144. package/templates/starter/docs/toolcraft/README.md +2 -1
  145. package/templates/starter/docs/toolcraft/acceptance-testing.md +23 -35
  146. package/templates/starter/docs/toolcraft/agent-worklog.md +18 -3
  147. package/templates/starter/docs/toolcraft/assembly-workflow.md +13 -5
  148. package/templates/starter/docs/toolcraft/component-rules.md +8 -6
  149. package/templates/starter/docs/toolcraft/core/control-selection.md +9 -3
  150. package/templates/starter/docs/toolcraft/core/layout.md +7 -7
  151. package/templates/starter/docs/toolcraft/core/media-upload.md +4 -2
  152. package/templates/starter/docs/toolcraft/core/performance.md +14 -3
  153. package/templates/starter/docs/toolcraft/core/runtime-boundary.md +16 -3
  154. package/templates/starter/docs/toolcraft/core/setup-export.md +49 -19
  155. package/templates/starter/docs/toolcraft/core/timeline-animation.md +4 -4
  156. package/templates/starter/docs/toolcraft/custom-controls.md +6 -4
  157. package/templates/starter/docs/toolcraft/decision-contract.md +3 -1
  158. package/templates/starter/docs/toolcraft/performance.md +20 -6
  159. package/templates/starter/docs/toolcraft/renderer-technique.md +5 -1
  160. package/templates/starter/docs/toolcraft/schema-reference.md +23 -25
  161. package/templates/starter/docs/toolcraft/workflow.md +7 -2
  162. package/templates/starter/e2e/app-browser-control-applicability-requirements.spec.ts +163 -0
  163. package/templates/starter/e2e/app-browser-control-coverage.spec.ts +33 -0
  164. package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +50 -3
  165. package/templates/starter/e2e/app-browser-orientation-evidence.spec.ts +174 -21
  166. package/templates/starter/e2e/app-browser-render-scale-evidence.spec.ts +60 -6
  167. package/templates/starter/e2e/app-browser-render-scale-requirements.spec.ts +77 -1
  168. package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +8 -0
  169. package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +35 -0
  170. package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +5 -34
  171. package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +61 -16
  172. package/templates/starter/e2e/app-browser-shell.spec.ts +13 -5
  173. package/templates/starter/e2e/app-performance-path-adapters.ts +8 -1
  174. package/templates/starter/e2e/app-performance.spec.ts +16 -9
  175. package/templates/starter/e2e/{browser-conditional-output-evidence-helpers.ts → browser-background-output-evidence.ts} +0 -68
  176. package/templates/starter/e2e/browser-control-applicability-evidence.ts +114 -0
  177. package/templates/starter/e2e/browser-infinity-canvas-evidence.ts +29 -341
  178. package/templates/starter/e2e/browser-infinity-canvas-unavailable-image-evidence.ts +370 -0
  179. package/templates/starter/e2e/browser-media-export-evidence.spec.ts +77 -0
  180. package/templates/starter/e2e/browser-media-export-evidence.ts +208 -0
  181. package/templates/starter/e2e/browser-orientation-gizmo-evidence-helpers.ts +4 -0
  182. package/templates/starter/e2e/browser-orientation-gizmo-live-preconditions.ts +86 -0
  183. package/templates/starter/e2e/browser-render-scale-evidence.ts +37 -29
  184. package/templates/starter/e2e/browser-runtime-applicability-requirements.ts +84 -0
  185. package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +13 -3
  186. package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +72 -35
  187. package/templates/starter/e2e/browser-semantic-evidence-test-helpers.ts +25 -0
  188. package/templates/starter/e2e/browser-standard-timeline-evidence.ts +106 -0
  189. package/templates/starter/e2e/decoded-pixel-observation.spec.ts +74 -0
  190. package/templates/starter/e2e/decoded-pixel-observation.ts +227 -0
  191. package/templates/starter/e2e/export-artifact-helpers.ts +206 -25
  192. package/templates/starter/e2e/image-artifact-inspection.spec.ts +41 -0
  193. package/templates/starter/e2e/image-artifact-inspection.ts +99 -0
  194. package/templates/starter/e2e/performance-canvas-helpers.ts +22 -21
  195. package/templates/starter/e2e/performance-canvas-quality-guard.spec.ts +312 -0
  196. package/templates/starter/e2e/performance-canvas-quality-guard.ts +196 -0
  197. package/templates/starter/e2e/performance-canvas-quality-observer.ts +351 -0
  198. package/templates/starter/e2e/performance-control-layout-helpers.ts +2 -2
  199. package/templates/starter/e2e/performance-path-adapter-contract.ts +4 -4
  200. package/templates/starter/e2e/performance-path-helpers.spec.ts +203 -70
  201. package/templates/starter/e2e/performance-path-helpers.ts +210 -91
  202. package/templates/starter/e2e/performance-pipeline-evidence-continuity.spec.ts +76 -0
  203. package/templates/starter/e2e/performance-pipeline-evidence-test-fixtures.ts +11 -2
  204. package/templates/starter/e2e/performance-pipeline-invariants.ts +47 -4
  205. package/templates/starter/e2e/performance-render-scale-runner.spec.ts +140 -38
  206. package/templates/starter/e2e/video-artifact-inspection.spec.ts +64 -0
  207. package/templates/starter/e2e/video-artifact-inspection.ts +281 -0
  208. package/templates/starter/gitignore +1 -0
  209. package/templates/starter/package.json +1 -0
  210. package/templates/starter/scripts/check-toolcraft-docs.mjs +17 -0
  211. package/templates/starter/scripts/toolcraft-contract-manifest.json +1 -0
  212. package/templates/starter/scripts/toolcraft-delivery-plan-authority.test.mjs +60 -0
  213. package/templates/starter/scripts/toolcraft-delivery-plan-errors.test.mjs +7 -2
  214. package/templates/starter/scripts/toolcraft-delivery-plan.mjs +7 -3
  215. package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +95 -103
  216. package/templates/starter/scripts/toolcraft-product-boundary-module-policy.mjs +101 -0
  217. package/templates/starter/scripts/toolcraft-product-boundary.mjs +12 -0
  218. package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +0 -26
  219. package/templates/starter/scripts/toolcraft-product-control-bindings.mjs +182 -0
  220. package/templates/starter/scripts/toolcraft-product-control-boundary.mjs +146 -0
  221. package/templates/starter/scripts/toolcraft-product-control-boundary.test.mjs +186 -0
  222. package/templates/starter/scripts/toolcraft-product-evidence-boundary.test.mjs +85 -20
  223. package/templates/starter/scripts/toolcraft-product-evidence-import-policy.mjs +43 -0
  224. package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +157 -0
  225. package/templates/starter/scripts/toolcraft-product-export-boundary.test.mjs +196 -0
  226. package/templates/starter/scripts/toolcraft-typescript-analysis.d.mts +73 -0
  227. package/templates/starter/scripts/toolcraft-typescript-source-evidence-structure.test.mjs +20 -0
  228. package/templates/starter/scripts/toolcraft-typescript-source-evidence.mjs +1 -0
  229. package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade-test-helpers.mjs +318 -0
  230. package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +157 -206
  231. package/templates/starter/scripts/toolcraft-verification-inventory.mjs +1 -0
  232. package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +51 -0
  233. package/templates/starter/scripts/toolcraft-vite-env-activation.test.mjs +128 -59
  234. package/templates/starter/src/app/acceptance/artifact-export-intent.ts +130 -0
  235. package/templates/starter/src/app/acceptance/conditions.ts +1 -1
  236. package/templates/starter/src/app/acceptance/control-acceptance-context.ts +2 -2
  237. package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +6 -20
  238. package/templates/starter/src/app/acceptance/control-acceptance-kind-rules.ts +24 -5
  239. package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +2 -13
  240. package/templates/starter/src/app/acceptance/control-applicability-cases.test.ts +321 -0
  241. package/templates/starter/src/app/acceptance/control-applicability-cases.ts +290 -0
  242. package/templates/starter/src/app/acceptance/control-applicability.ts +332 -0
  243. package/templates/starter/src/app/acceptance/control-layout-dependency-rules.ts +20 -9
  244. package/templates/starter/src/app/acceptance/control-layout-entity-rules.ts +4 -6
  245. package/templates/starter/src/app/acceptance/control-layout-model.ts +4 -4
  246. package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +3 -10
  247. package/templates/starter/src/app/acceptance/control-parts.ts +8 -0
  248. package/templates/starter/src/app/acceptance/control-section-entity-cohesion.test.ts +215 -0
  249. package/templates/starter/src/app/acceptance/control-section-entity-cohesion.ts +132 -0
  250. package/templates/starter/src/app/acceptance/control-section-inventory.test.ts +87 -0
  251. package/templates/starter/src/app/acceptance/control-section-inventory.ts +74 -44
  252. package/templates/starter/src/app/acceptance/custom-controls.ts +11 -3
  253. package/templates/starter/src/app/acceptance/export-artifact-coverage.ts +113 -0
  254. package/templates/starter/src/app/acceptance/inline-layout.ts +64 -9
  255. package/templates/starter/src/app/acceptance/media-upload.ts +5 -1
  256. package/templates/starter/src/app/acceptance/orientation-gizmo.ts +18 -11
  257. package/templates/starter/src/app/acceptance/output-background-rules.ts +2 -2
  258. package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +18 -10
  259. package/templates/starter/src/app/acceptance/output-export-model.ts +54 -11
  260. package/templates/starter/src/app/acceptance/output-export.ts +35 -12
  261. package/templates/starter/src/app/acceptance/output-video-export-rules.ts +99 -0
  262. package/templates/starter/src/app/acceptance/types.ts +30 -8
  263. package/templates/starter/src/app/acceptance/validate-coverage.ts +20 -2
  264. package/templates/starter/src/app/starter-acceptance.artifact-export-intent.test.ts +239 -0
  265. package/templates/starter/src/app/starter-acceptance.background-export.test.ts +33 -0
  266. package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +16 -1
  267. package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +65 -0
  268. package/templates/starter/src/app/starter-acceptance.contract-fixtures.test.ts +41 -0
  269. package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +112 -16
  270. package/templates/starter/src/app/starter-acceptance.control-applicability.test.ts +224 -0
  271. package/templates/starter/src/app/starter-acceptance.control-order.test.ts +58 -3
  272. package/templates/starter/src/app/starter-acceptance.control-state.test.ts +0 -111
  273. package/templates/starter/src/app/starter-acceptance.custom-control-collections.test.ts +3 -1
  274. package/templates/starter/src/app/starter-acceptance.custom-control-valid.test.ts +1 -1
  275. package/templates/starter/src/app/starter-acceptance.export-artifact.test.ts +131 -0
  276. package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +22 -0
  277. package/templates/starter/src/app/{starter-acceptance.image-video-export-settings.test.ts → starter-acceptance.image-export-settings.test.ts} +37 -9
  278. package/templates/starter/src/app/starter-acceptance.interaction-ownership.test.ts +12 -0
  279. package/templates/starter/src/app/starter-acceptance.keyframes.test.ts +14 -4
  280. package/templates/starter/src/app/starter-acceptance.media-upload.fixtures.ts +11 -1
  281. package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +28 -0
  282. package/templates/starter/src/app/starter-acceptance.output-export-intent.test.ts +384 -0
  283. package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +46 -1
  284. package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +112 -105
  285. package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +12 -0
  286. package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +1 -1
  287. package/templates/starter/src/app/starter-acceptance.section-dependencies.test.ts +35 -24
  288. package/templates/starter/src/app/starter-acceptance.section-size.test.ts +72 -0
  289. package/templates/starter/src/app/starter-acceptance.ts +13 -2
  290. package/templates/starter/src/app/starter-acceptance.video-export-settings.test.ts +336 -0
  291. package/templates/starter/src/app/starter-acceptance.view-interaction.test.ts +8 -0
  292. package/templates/starter/src/app/starter-performance-test-utils.ts +103 -0
  293. package/templates/starter/src/app/starter-performance.gates.test.ts +231 -278
  294. package/templates/starter/src/app/starter-performance.lifecycle.test.ts +261 -0
  295. package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +4 -2
  296. package/templates/starter/src/routes/index.tsx +2 -0
  297. package/templates/ui/components/composites/tabs.tsx +2 -2
  298. package/templates/ui/components/controls/collection-actions/collection-item-groups.test.tsx +38 -0
  299. package/templates/ui/components/controls/collection-actions/collection-item-groups.tsx +36 -0
  300. package/templates/ui/components/controls/collection-actions/index.ts +2 -0
  301. package/templates/ui/components/controls/file-drop/file-drop-collection-control.tsx +137 -0
  302. package/templates/ui/components/controls/file-drop/file-drop-control.test.tsx +189 -0
  303. package/templates/ui/components/controls/file-drop/file-drop-control.tsx +81 -88
  304. package/templates/ui/components/controls/file-drop/file-drop-presentation.tsx +131 -9
  305. package/templates/ui/components/controls/file-drop/file-drop-types.ts +36 -22
  306. package/templates/ui/components/controls/file-drop/index.ts +1 -0
  307. package/templates/ui/components/controls/index.ts +3 -0
  308. package/templates/ui/components/controls/range-slider/range-slider-control.tsx +1 -1
  309. package/templates/ui/components/controls/range-slider/range-slider-value.test.ts +14 -0
  310. package/templates/ui/components/controls/range-slider/range-slider-value.ts +3 -2
  311. package/templates/runtime/export/export.ts +0 -166
  312. package/templates/starter/src/app/acceptance/condition-exclusivity.test.ts +0 -60
  313. package/templates/starter/src/app/acceptance/condition-exclusivity.ts +0 -221
@@ -6,8 +6,14 @@ import {
6
6
  assertGeneratedDeliveryArchitecture,
7
7
  deliveryArchitecturePaths,
8
8
  } from "./generate-test-delivery-architecture-assertions.mjs";
9
- import { listRelativeFiles, readTextFiles, repoRoot } from "./generate-test-fs-utils.mjs";
10
- import { isGeneratedTestSupportPath } from "./generated-source-policy.mjs";
9
+ import { listRelativeFiles, repoRoot } from "./generate-test-fs-utils.mjs";
10
+ import { assertGeneratedPerformanceCanvasBoundary } from "./generate-test-performance-boundary-assertions.mjs";
11
+ import { assertGeneratedRuntimePublicBoundary } from "./generate-test-runtime-boundary-assertions.mjs";
12
+
13
+ export {
14
+ assertGeneratedRoutesAndStyles,
15
+ assertGeneratedTextIsStandalone,
16
+ } from "./generate-test-output-assertions.mjs";
11
17
 
12
18
  function assertSignedProtectedFiles(manifest, relativePaths, responsibility) {
13
19
  for (const relativePath of relativePaths) {
@@ -38,16 +44,7 @@ export async function assertGeneratedFiles(targetDir) {
38
44
  "scripts/toolcraft-targeted-verification-selection.mjs",
39
45
  ];
40
46
 
41
- assert.ok(await fs.stat(path.join(targetDir, "src/toolcraft/ui/index.ts")));
42
- assert.ok(await fs.stat(path.join(targetDir, "src/toolcraft/runtime/react/index.ts")));
43
- assert.ok(
44
- await fs.stat(
45
- path.join(
46
- targetDir,
47
- "src/toolcraft/runtime/model-import/worker/model-import.worker.bundle.js",
48
- ),
49
- ),
50
- );
47
+ await assertGeneratedRuntimePublicBoundary(targetDir);
51
48
  assert.ok(await fs.stat(path.join(targetDir, "playwright.config.ts")));
52
49
  await assert.rejects(
53
50
  fs.stat(path.join(targetDir, ".toolcraft")),
@@ -55,37 +52,6 @@ export async function assertGeneratedFiles(targetDir) {
55
52
  "Fresh generated apps must not inherit starter server ports or verification receipts.",
56
53
  );
57
54
 
58
- const generatedToolcraftFiles = await listRelativeFiles(
59
- path.join(targetDir, "src/toolcraft"),
60
- );
61
- const expectedRuntimeFiles = (await listRelativeFiles(
62
- path.join(repoRoot, "packages/toolcraft-runtime/src"),
63
- ))
64
- .filter((relativePath) => !isGeneratedTestSupportPath(relativePath))
65
- .map((relativePath) => `runtime/${relativePath}`);
66
- assert.deepEqual(
67
- generatedToolcraftFiles.filter((relativePath) => relativePath.startsWith("runtime/")),
68
- expectedRuntimeFiles,
69
- "Generated standalone runtime must contain every production runtime module.",
70
- );
71
- for (const relativePath of generatedToolcraftFiles) {
72
- assert.equal(
73
- isGeneratedTestSupportPath(relativePath),
74
- false,
75
- `Generated runtime contains test support: ${relativePath}`,
76
- );
77
- }
78
-
79
- const removedRuntimeTestHelpers = [
80
- "runtime/react/canvas/canvas-shell-test-utils.tsx",
81
- "runtime/react/controls-panel/testing/controls-panel-test-utils.tsx",
82
- "runtime/react/layers/layers-panel-test-utils.tsx",
83
- "runtime/react/timeline/timeline-panel-test-utils.tsx",
84
- ];
85
- for (const relativePath of removedRuntimeTestHelpers) {
86
- assert.equal(generatedToolcraftFiles.includes(relativePath), false);
87
- }
88
-
89
55
  const playwrightConfigSource = await fs.readFile(
90
56
  path.join(targetDir, "playwright.config.ts"),
91
57
  "utf8",
@@ -96,9 +62,7 @@ export async function assertGeneratedFiles(targetDir) {
96
62
  await listRelativeFiles(path.join(repoRoot, "starter/e2e")),
97
63
  );
98
64
  assert.ok(await fs.stat(path.join(targetDir, "e2e/app-controls.spec.ts")));
99
- assert.ok(
100
- await fs.stat(path.join(targetDir, "e2e/app-performance-path-adapters.ts")),
101
- );
65
+ await assertGeneratedPerformanceCanvasBoundary(targetDir);
102
66
 
103
67
  const generatedAppSourceFiles = await listRelativeFiles(path.join(targetDir, "src/app"));
104
68
  assert.ok(await fs.stat(path.join(targetDir, "src/app/app-schema.ts")));
@@ -107,11 +71,35 @@ export async function assertGeneratedFiles(targetDir) {
107
71
  assert.ok(await fs.stat(path.join(targetDir, "src/app/app-acceptance-data.ts")));
108
72
  assert.ok(await fs.stat(path.join(targetDir, "src/app/app-composition.tsx")));
109
73
  assert.ok(await fs.stat(path.join(targetDir, "src/app/app-acceptance.base-coverage.test.ts")));
74
+ assert.ok(
75
+ await fs.stat(
76
+ path.join(
77
+ targetDir,
78
+ "src/app/acceptance/control-section-entity-cohesion.ts",
79
+ ),
80
+ ),
81
+ );
82
+ const generatedApplicabilityValidatorSource = await fs.readFile(
83
+ path.join(targetDir, "src/app/acceptance/control-applicability.ts"),
84
+ "utf8",
85
+ );
86
+ assert.match(
87
+ generatedApplicabilityValidatorSource,
88
+ /getToolcraftControlApplicabilityErrors/,
89
+ );
110
90
  const appAcceptanceSource = await fs.readFile(
111
91
  path.join(targetDir, "src/app/app-acceptance.ts"),
112
92
  "utf8",
113
93
  );
114
94
  assert.match(appAcceptanceSource, /from "\.\/app-acceptance-data"/);
95
+ const generatedValidationPipeline = await fs.readFile(
96
+ path.join(targetDir, "src/app/acceptance/validate-coverage.ts"),
97
+ "utf8",
98
+ );
99
+ assert.match(
100
+ generatedValidationPipeline,
101
+ /validate:\s*\(\{ sectionInventory \}\)\s*=>\s*getToolcraftControlSectionEntityCohesionErrors\(sectionInventory\)/,
102
+ );
115
103
  assert.ok(await fs.stat(path.join(targetDir, "src/app/app-performance.ts")));
116
104
  assert.ok(
117
105
  await fs.stat(path.join(targetDir, "src/app/app-verification-impact.json")),
@@ -350,6 +338,8 @@ export async function assertGeneratedFiles(targetDir) {
350
338
  "e2e/performance-measurement-evidence.ts",
351
339
  "e2e/performance-path-adapter-contract.ts",
352
340
  "e2e/performance-path-helpers.ts",
341
+ "e2e/performance-canvas-quality-observer.ts",
342
+ "e2e/performance-canvas-quality-guard.ts",
353
343
  "e2e/performance-slider-helpers.ts",
354
344
  "scripts/toolcraft-performance-report.mjs",
355
345
  "scripts/toolcraft-kernel-benchmark-receipt.mjs",
@@ -415,75 +405,3 @@ export async function assertGeneratedFiles(targetDir) {
415
405
  undefined,
416
406
  );
417
407
  }
418
-
419
- export async function assertGeneratedRoutesAndStyles(targetDir) {
420
- await assert.rejects(
421
- () => fs.stat(path.join(targetDir, "src/toolcraft/runtime/react/canvas-shell.test.tsx")),
422
- /ENOENT/,
423
- );
424
-
425
- const routeSource = await fs.readFile(path.join(targetDir, "src/routes/index.tsx"), "utf8");
426
- assert.match(routeSource, /@\/toolcraft\/runtime\/react/);
427
- assert.match(routeSource, /\.\.\/app\/app-composition/);
428
- assert.match(routeSource, /canvasContent=\{appComposition\.canvasContent\}/);
429
- assert.match(routeSource, /controlRenderers=\{appComposition\.controlRenderers\}/);
430
- assert.match(routeSource, /modelPresentation=\{appComposition\.modelPresentation\}/);
431
- assert.match(routeSource, /onPanelAction=\{appComposition\.onPanelAction\}/);
432
- assert.match(
433
- routeSource,
434
- /renderDefaultCanvasMedia=\{appComposition\.renderDefaultCanvasMedia\}/,
435
- );
436
- assert.match(
437
- routeSource,
438
- /rendererPipelineRegistration=\{appComposition\.rendererPipelineRegistration\}/,
439
- );
440
- assert.match(
441
- routeSource,
442
- /sceneBoundsProvider=\{appComposition\.sceneBoundsProvider\}/,
443
- );
444
- assert.match(routeSource, /schema=\{appComposition\.schema\}/);
445
- assert.match(routeSource, /className="h-dvh min-h-dvh"/);
446
- assert.doesNotMatch(routeSource, /\{\.\.\.appComposition\}/);
447
- assert.doesNotMatch(routeSource, /appSchema|ProductCanvas/);
448
-
449
- const compositionSource = await fs.readFile(
450
- path.join(targetDir, "src/app/app-composition.tsx"),
451
- "utf8",
452
- );
453
- assert.match(
454
- compositionSource,
455
- /import type \{ ToolcraftAppComposition \} from "@\/toolcraft\/runtime\/react"/,
456
- );
457
- assert.match(compositionSource, /export const appComposition/);
458
- assert.match(compositionSource, /appComposition\s*:\s*ToolcraftAppComposition\s*=/);
459
- assert.match(compositionSource, /modelPresentation:\s*\{\s*mode:\s*"runtime"\s*\}/);
460
-
461
- const stylesSource = await fs.readFile(path.join(targetDir, "src/styles.css"), "utf8");
462
- assert.match(stylesSource, /@source "\.\/toolcraft\/ui";/);
463
- assert.match(stylesSource, /@import "@\/toolcraft\/ui\/styles\.css";/);
464
- }
465
-
466
- export async function assertGeneratedTextIsStandalone(targetDir) {
467
- const allText = await readTextFiles(targetDir);
468
- assert.doesNotMatch(allText, /BEGIN PRIVATE KEY/);
469
- assert.doesNotMatch(allText, /@repo\/ui|@repo\/toolcraft-runtime|workspace:/);
470
- assert.doesNotMatch(allText, new RegExp("template" + "-runtime"));
471
- assert.doesNotMatch(allText, /packages\/typescript-config/);
472
- assert.doesNotMatch(
473
- allText,
474
- /prototype-smoke|browser-functional-smoke|performance-smoke|app-performance-smoke|toolcraft-performance-smoke-runner/,
475
- );
476
- assert.doesNotMatch(
477
- allText,
478
- /starterComposition|starter-composition|starterSchema|starter-schema|starterAcceptance|starterControlSectionInventory|starter-acceptance|starterProductReadiness|starterTransferMode|starterPerformance|starter-performance|StarterHome|Toolcraft Starter/,
479
- );
480
-
481
- const kernelReceiptDeclaration = await fs.readFile(
482
- path.join(targetDir, "scripts/toolcraft-kernel-benchmark-receipt.d.mts"),
483
- "utf8",
484
- );
485
- assert.match(
486
- kernelReceiptDeclaration,
487
- /from "@\/toolcraft\/runtime"/,
488
- );
489
- }
@@ -0,0 +1,95 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+
5
+ import { readTextFiles } from "./generate-test-fs-utils.mjs";
6
+
7
+ export async function assertGeneratedRoutesAndStyles(targetDir) {
8
+ await assert.rejects(
9
+ () =>
10
+ fs.stat(
11
+ path.join(
12
+ targetDir,
13
+ "src/toolcraft/runtime/react/canvas-shell.test.tsx",
14
+ ),
15
+ ),
16
+ /ENOENT/,
17
+ );
18
+
19
+ const routeSource = await fs.readFile(
20
+ path.join(targetDir, "src/routes/index.tsx"),
21
+ "utf8",
22
+ );
23
+ assert.match(routeSource, /@\/toolcraft\/runtime\/react/);
24
+ assert.match(routeSource, /\.\.\/app\/app-composition/);
25
+ assert.match(routeSource, /canvasContent=\{appComposition\.canvasContent\}/);
26
+ assert.match(routeSource, /controlRenderers=\{appComposition\.controlRenderers\}/);
27
+ assert.match(routeSource, /modelPresentation=\{appComposition\.modelPresentation\}/);
28
+ assert.match(routeSource, /onPanelAction=\{appComposition\.onPanelAction\}/);
29
+ assert.match(
30
+ routeSource,
31
+ /renderDefaultCanvasMedia=\{appComposition\.renderDefaultCanvasMedia\}/,
32
+ );
33
+ assert.match(
34
+ routeSource,
35
+ /rendererPipelineRegistration=\{appComposition\.rendererPipelineRegistration\}/,
36
+ );
37
+ assert.match(
38
+ routeSource,
39
+ /sceneBoundsProvider=\{appComposition\.sceneBoundsProvider\}/,
40
+ );
41
+ assert.match(routeSource, /schema=\{appComposition\.schema\}/);
42
+ assert.match(routeSource, /className="h-dvh min-h-dvh"/);
43
+ assert.doesNotMatch(routeSource, /\{\.\.\.appComposition\}/);
44
+ assert.doesNotMatch(routeSource, /appSchema|ProductCanvas/);
45
+
46
+ const compositionSource = await fs.readFile(
47
+ path.join(targetDir, "src/app/app-composition.tsx"),
48
+ "utf8",
49
+ );
50
+ assert.match(
51
+ compositionSource,
52
+ /import type \{ ToolcraftAppComposition \} from "@\/toolcraft\/runtime\/react"/,
53
+ );
54
+ assert.match(compositionSource, /export const appComposition/);
55
+ assert.match(
56
+ compositionSource,
57
+ /appComposition\s*:\s*ToolcraftAppComposition\s*=/,
58
+ );
59
+ assert.match(
60
+ compositionSource,
61
+ /modelPresentation:\s*\{\s*mode:\s*"runtime"\s*\}/,
62
+ );
63
+
64
+ const stylesSource = await fs.readFile(
65
+ path.join(targetDir, "src/styles.css"),
66
+ "utf8",
67
+ );
68
+ assert.match(stylesSource, /@source "\.\/toolcraft\/ui";/);
69
+ assert.match(stylesSource, /@import "@\/toolcraft\/ui\/styles\.css";/);
70
+ }
71
+
72
+ export async function assertGeneratedTextIsStandalone(targetDir) {
73
+ const allText = await readTextFiles(targetDir);
74
+ assert.doesNotMatch(allText, /BEGIN PRIVATE KEY/);
75
+ assert.doesNotMatch(allText, /@repo\/ui|@repo\/toolcraft-runtime|workspace:/);
76
+ assert.doesNotMatch(allText, new RegExp("template" + "-runtime"));
77
+ assert.doesNotMatch(allText, /packages\/typescript-config/);
78
+ assert.doesNotMatch(
79
+ allText,
80
+ /prototype-smoke|browser-functional-smoke|performance-smoke|app-performance-smoke|toolcraft-performance-smoke-runner/,
81
+ );
82
+ assert.doesNotMatch(
83
+ allText,
84
+ /starterComposition|starter-composition|starterSchema|starter-schema|starterAcceptance|starterControlSectionInventory|starter-acceptance|starterProductReadiness|starterTransferMode|starterPerformance|starter-performance|StarterHome|Toolcraft Starter/,
85
+ );
86
+
87
+ const kernelReceiptDeclaration = await fs.readFile(
88
+ path.join(
89
+ targetDir,
90
+ "scripts/toolcraft-kernel-benchmark-receipt.d.mts",
91
+ ),
92
+ "utf8",
93
+ );
94
+ assert.match(kernelReceiptDeclaration, /from "@\/toolcraft\/runtime"/);
95
+ }
@@ -16,6 +16,11 @@ export async function assertGeneratedPackageJson(targetDir) {
16
16
  assert.equal(packageJson.dependencies.fflate, "0.8.3");
17
17
  assert.equal(packageJson.dependencies.draco3dgltf, undefined);
18
18
  assert.equal(packageJson.dependencies.meshoptimizer, "1.2.0");
19
+ assert.equal(
20
+ packageJson.dependencies.mediabunny,
21
+ "1.52.2",
22
+ "Generated apps must pin the runtime-owned timestamped video encoder.",
23
+ );
19
24
  assert.equal(packageJson.dependencies["react-resizable-panels"], "^4.10.0");
20
25
  assert.equal(packageJson.dependencies.sonner, "^2.0.7");
21
26
  assert.equal(packageJson.dependencies.three, "0.185.1");
@@ -76,6 +81,7 @@ export async function assertGeneratedGitignore(targetDir) {
76
81
  assert.match(gitignoreSource, /node_modules/);
77
82
  assert.match(gitignoreSource, /dist/);
78
83
  assert.match(gitignoreSource, /playwright-report/);
84
+ assert.match(gitignoreSource, /^\.playwright-mcp$/mu);
79
85
  assert.match(gitignoreSource, /\.env\.\*/);
80
86
  assert.match(gitignoreSource, /\.toolcraft/);
81
87
  await assert.rejects(() => fs.stat(path.join(targetDir, "gitignore")), /ENOENT/);
@@ -0,0 +1,45 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+
5
+ export async function assertGeneratedPerformanceCanvasBoundary(targetDir) {
6
+ const [
7
+ adaptersSource,
8
+ adapterContractSource,
9
+ guardSource,
10
+ helpersSource,
11
+ ] = await Promise.all([
12
+ fs.readFile(
13
+ path.join(targetDir, "e2e/app-performance-path-adapters.ts"),
14
+ "utf8",
15
+ ),
16
+ fs.readFile(
17
+ path.join(targetDir, "e2e/performance-path-adapter-contract.ts"),
18
+ "utf8",
19
+ ),
20
+ fs.readFile(
21
+ path.join(targetDir, "e2e/performance-canvas-quality-guard.ts"),
22
+ "utf8",
23
+ ),
24
+ fs.readFile(
25
+ path.join(targetDir, "e2e/performance-path-helpers.ts"),
26
+ "utf8",
27
+ ),
28
+ fs.stat(path.join(targetDir, "e2e/performance-canvas-quality-observer.ts")),
29
+ fs.stat(
30
+ path.join(targetDir, "e2e/performance-canvas-quality-guard.spec.ts"),
31
+ ),
32
+ ]);
33
+
34
+ assert.match(adaptersSource, /appPerformanceCanvasBacking/u);
35
+ assert.doesNotMatch(adapterContractSource, /renderScaleBacking\?:/u);
36
+ assert.match(helpersSource, /schema\.canvas\.renderScale\.enabled/u);
37
+ assert.match(
38
+ guardSource,
39
+ /from "\.\/performance-canvas-quality-observer"/u,
40
+ );
41
+ assert.match(
42
+ helpersSource,
43
+ /from "\.\/performance-canvas-quality-guard"/u,
44
+ );
45
+ }
@@ -38,6 +38,7 @@ export const generatedProductFixturePaths = Object.freeze([
38
38
  "e2e/product-canvas.spec.ts",
39
39
  "e2e/product-export.spec.ts",
40
40
  "e2e/product-material.spec.ts",
41
+ "e2e/product-media-export-fixture.ts",
41
42
  "e2e/product-runtime.spec.ts",
42
43
  "e2e/product-test-utils.ts",
43
44
  generatedProductPresentationResourcePath,
@@ -15,6 +15,11 @@ import {
15
15
  writeGeneratedProductFixture,
16
16
  } from "./generate-test-product-fixture.mjs";
17
17
 
18
+ const generatedProductFixtureRoot = new URL(
19
+ "../fixtures/generated-product/",
20
+ import.meta.url,
21
+ );
22
+
18
23
  it("rejects unknown and missing product fixture paths", () => {
19
24
  assert.deepEqual(generatedProductAuthorityFixturePaths, [
20
25
  "docs/toolcraft/agent-worklog.md",
@@ -106,6 +111,19 @@ it("rejects unknown and missing product fixture paths", () => {
106
111
  );
107
112
  });
108
113
 
114
+ it("keeps the vector product overlay explicit about canvas backing", async () => {
115
+ const adaptersSource = await fs.readFile(
116
+ new URL("e2e/app-performance-path-adapters.ts", generatedProductFixtureRoot),
117
+ "utf8",
118
+ );
119
+
120
+ assert.match(adaptersSource, /ToolcraftPerformanceCanvasBacking/u);
121
+ assert.match(
122
+ adaptersSource,
123
+ /appPerformanceCanvasBacking[\s\S]*undefined\s*=\s*undefined/u,
124
+ );
125
+ });
126
+
109
127
  it("reads only an exact supported command from generated authority policy", async () => {
110
128
  const targetDir = await fs.mkdtemp(
111
129
  path.join(os.tmpdir(), "toolcraft-product-manager-"),
@@ -21,6 +21,7 @@ export const generatedProductMaterialIterationFixturePaths = Object.freeze([
21
21
  "public/material-sprinkles.svg",
22
22
  "src/app/app-acceptance-data.ts",
23
23
  "src/app/app-verification-impact.json",
24
+ "src/app/material-acceptance-data.ts",
24
25
  "src/app/material-output.test.tsx",
25
26
  "src/app/material-output.tsx",
26
27
  "src/app/material-schema.ts",
@@ -11,6 +11,11 @@ import {
11
11
  generatedProductMaterialIterationFixturePaths,
12
12
  } from "./generate-test-product-iteration.mjs";
13
13
 
14
+ const materialIterationFixtureRoot = new URL(
15
+ "../fixtures/generated-product-material-iteration/",
16
+ import.meta.url,
17
+ );
18
+
14
19
  const expectedPaths = [
15
20
  "e2e/product-material.spec.ts",
16
21
  "public/material-chocolate.svg",
@@ -18,6 +23,7 @@ const expectedPaths = [
18
23
  "public/material-sprinkles.svg",
19
24
  "src/app/app-acceptance-data.ts",
20
25
  "src/app/app-verification-impact.json",
26
+ "src/app/material-acceptance-data.ts",
21
27
  "src/app/material-output.test.tsx",
22
28
  "src/app/material-output.tsx",
23
29
  "src/app/material-schema.ts",
@@ -82,6 +88,18 @@ it("keeps the material iteration overlay exact and immutable", () => {
82
88
  );
83
89
  });
84
90
 
91
+ it("keeps the material iteration video request explicit", async () => {
92
+ const acceptanceSource = await fs.readFile(
93
+ new URL("src/app/app-acceptance-data.ts", materialIterationFixtureRoot),
94
+ "utf8",
95
+ );
96
+
97
+ assert.match(
98
+ acceptanceSource,
99
+ /video:\s*\{\s*evidence:\s*"The generated export validation fixture explicitly requests one-second video export coverage\.",\s*mode: "user-requested",\s*\}/u,
100
+ );
101
+ });
102
+
85
103
  it("atomically applies only the material product overlay", async () => {
86
104
  const targetDir = await fs.mkdtemp(
87
105
  path.join(os.tmpdir(), "toolcraft-material-iteration-target-"),
@@ -0,0 +1,158 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+
5
+ import { listRelativeFiles, repoRoot } from "./generate-test-fs-utils.mjs";
6
+ import { isGeneratedTestSupportPath } from "./generated-source-policy.mjs";
7
+
8
+ const productSafeRuntimeExportIndex = [
9
+ 'export {',
10
+ ' toolcraftImageExportFormatTarget,',
11
+ ' toolcraftImageExportResolutionTarget,',
12
+ ' toolcraftVideoExportFormatTarget,',
13
+ ' toolcraftVideoExportResolutionTarget,',
14
+ '} from "./artifact-export-settings";',
15
+ 'export type {',
16
+ ' ToolcraftImageExportFormat,',
17
+ ' ToolcraftImageExportPresetResolution,',
18
+ ' ToolcraftResolvedImageExportSettings,',
19
+ ' ToolcraftResolvedVideoExportSettings,',
20
+ ' ToolcraftVideoExportFormat,',
21
+ ' ToolcraftVideoExportPresetResolution,',
22
+ '} from "./artifact-export-settings";',
23
+ 'export { shouldIncludeToolcraftPreviewBackground } from "./export-background";',
24
+ 'export type { ToolcraftPreviewBackgroundOptions } from "./export-background";',
25
+ 'export {',
26
+ ' TOOLCRAFT_MAX_EXPORT_EDGE_PX,',
27
+ ' TOOLCRAFT_MAX_EXPORT_PIXELS,',
28
+ ' validateToolcraftArtifactSize,',
29
+ '} from "./export-frame";',
30
+ 'export type {',
31
+ ' ToolcraftArtifactSize,',
32
+ ' ToolcraftExportFrame,',
33
+ '} from "./export-frame";',
34
+ 'export {',
35
+ ' getToolcraftImageExportSize,',
36
+ ' getToolcraftRetinaExportPixelRatio,',
37
+ ' getToolcraftRetinaExportSize,',
38
+ ' getToolcraftVideoExportSize,',
39
+ '} from "./export-sizing";',
40
+ 'export type {',
41
+ ' ToolcraftExportSizeOptions,',
42
+ ' ToolcraftImageExportResolution,',
43
+ ' ToolcraftImageExportSizeOptions,',
44
+ ' ToolcraftRetinaExportSize,',
45
+ ' ToolcraftVideoExportResolution,',
46
+ ' ToolcraftVideoExportSizeOptions,',
47
+ '} from "./export-sizing";',
48
+ 'export type {',
49
+ ' ToolcraftProductExportFrameContext,',
50
+ ' ToolcraftProductExportFrameRenderer,',
51
+ ' ToolcraftProductExportRenderer,',
52
+ '} from "./product-export-renderer";',
53
+ '',
54
+ ].join("\n");
55
+
56
+ const requiredRuntimeExportImplementationPaths = [
57
+ "runtime/export/artifact-export-settings.ts",
58
+ "runtime/export/artifact-export-request.ts",
59
+ "runtime/export/artifact-frame-renderer.ts",
60
+ "runtime/export/artifact-frame-state.ts",
61
+ "runtime/export/artifact-scene-frame.ts",
62
+ "runtime/export/image-artifact-export.ts",
63
+ "runtime/export/product-export-renderer.ts",
64
+ "runtime/export/video-artifact-export.ts",
65
+ "runtime/export/video-encoding-backend.ts",
66
+ "runtime/export/video-frame-schedule.ts",
67
+ ];
68
+
69
+ const generatedMediaExportEvidencePaths = [
70
+ "e2e/browser-media-export-evidence.ts",
71
+ "e2e/decoded-pixel-observation.ts",
72
+ "e2e/image-artifact-inspection.ts",
73
+ "e2e/video-artifact-inspection.ts",
74
+ ];
75
+
76
+ const removedRuntimeTestHelperPaths = [
77
+ "runtime/react/canvas/canvas-shell-test-utils.tsx",
78
+ "runtime/react/controls-panel/testing/controls-panel-test-utils.tsx",
79
+ "runtime/react/layers/layers-panel-test-utils.tsx",
80
+ "runtime/react/timeline/timeline-panel-test-utils.tsx",
81
+ ];
82
+
83
+ export async function assertGeneratedRuntimePublicBoundary(targetDir) {
84
+ assert.ok(await fs.stat(path.join(targetDir, "src/toolcraft/ui/index.ts")));
85
+ assert.ok(await fs.stat(path.join(targetDir, "src/toolcraft/runtime/react/index.ts")));
86
+
87
+ const generatedRuntimeRootSource = await fs.readFile(
88
+ path.join(targetDir, "src/toolcraft/runtime/index.ts"),
89
+ "utf8",
90
+ );
91
+ assert.match(generatedRuntimeRootSource, /export \* from "\.\/export";/u);
92
+ assert.doesNotMatch(
93
+ generatedRuntimeRootSource,
94
+ /exportToolcraft(?:Image|Video)Artifact|createToolcraftVideoEncoderBackend/u,
95
+ );
96
+
97
+ const generatedRuntimeExportIndexSource = await fs.readFile(
98
+ path.join(targetDir, "src/toolcraft/runtime/export/index.ts"),
99
+ "utf8",
100
+ );
101
+ assert.equal(
102
+ generatedRuntimeExportIndexSource,
103
+ productSafeRuntimeExportIndex,
104
+ "Generated runtime export index must expose the exact product-safe allowlist.",
105
+ );
106
+
107
+ assert.ok(
108
+ await fs.stat(
109
+ path.join(
110
+ targetDir,
111
+ "src/toolcraft/runtime/model-import/worker/model-import.worker.bundle.js",
112
+ ),
113
+ ),
114
+ );
115
+
116
+ const generatedToolcraftFiles = await listRelativeFiles(
117
+ path.join(targetDir, "src/toolcraft"),
118
+ );
119
+ const expectedRuntimeFiles = (await listRelativeFiles(
120
+ path.join(repoRoot, "packages/toolcraft-runtime/src"),
121
+ ))
122
+ .filter((relativePath) => !isGeneratedTestSupportPath(relativePath))
123
+ .map((relativePath) => `runtime/${relativePath}`);
124
+ assert.deepEqual(
125
+ generatedToolcraftFiles.filter((relativePath) => relativePath.startsWith("runtime/")),
126
+ expectedRuntimeFiles,
127
+ "Generated standalone runtime must contain every production runtime module.",
128
+ );
129
+
130
+ for (const relativePath of requiredRuntimeExportImplementationPaths) {
131
+ assert.ok(
132
+ generatedToolcraftFiles.includes(relativePath),
133
+ `Generated runtime must contain ${relativePath}.`,
134
+ );
135
+ }
136
+ assert.equal(
137
+ generatedToolcraftFiles.includes("runtime/export/export.ts"),
138
+ false,
139
+ "Generated runtime must not copy the removed legacy export helper.",
140
+ );
141
+
142
+ for (const relativePath of generatedMediaExportEvidencePaths) {
143
+ assert.ok(
144
+ await fs.stat(path.join(targetDir, relativePath)),
145
+ `Generated output must contain ${relativePath}.`,
146
+ );
147
+ }
148
+ for (const relativePath of generatedToolcraftFiles) {
149
+ assert.equal(
150
+ isGeneratedTestSupportPath(relativePath),
151
+ false,
152
+ `Generated runtime contains test support: ${relativePath}`,
153
+ );
154
+ }
155
+ for (const relativePath of removedRuntimeTestHelperPaths) {
156
+ assert.equal(generatedToolcraftFiles.includes(relativePath), false);
157
+ }
158
+ }
@@ -87,6 +87,16 @@ export async function assertGeneratedProductStandalone({ execFileAsync, targetDi
87
87
  await writeGeneratedProductFixture(targetDir);
88
88
  await assertGeneratedProductWorklog(targetDir);
89
89
 
90
+ const appSchemaSource = await fs.readFile(
91
+ path.join(targetDir, "src/app/app-schema.ts"),
92
+ "utf8",
93
+ );
94
+ assert.match(
95
+ appSchemaSource,
96
+ /applicability:\s*\{\s*mode:\s*"always"\s*\}/u,
97
+ );
98
+ assert.doesNotMatch(appSchemaSource, /visibleWhen\s*:/u);
99
+
90
100
  const verificationImpact = JSON.parse(
91
101
  await fs.readFile(
92
102
  path.join(targetDir, "src/app/app-verification-impact.json"),
@@ -6,7 +6,7 @@ import {
6
6
  assertGeneratedExecutionLedger,
7
7
  runGeneratedDeliveryWithLedger,
8
8
  } from "./generate-test-browser-execution-ledger.mjs";
9
- import { runGeneratedScript } from "./generate-test-dependency-sandbox.mjs";
9
+ import { runGeneratedExecutable } from "./generate-test-dependency-sandbox.mjs";
10
10
 
11
11
  export async function assertGeneratedRuntimeProbe({
12
12
  execFileAsync,
@@ -15,8 +15,11 @@ export async function assertGeneratedRuntimeProbe({
15
15
  const productTestPath = path.join(targetDir, "src/app/app-schema.test.ts");
16
16
  const productTestSource = await fs.readFile(productTestPath, "utf8");
17
17
  const failingSource = productTestSource.replace(
18
- 'it("ambient speed changes product output"',
19
- 'it.fails("ambient speed changes product output"',
18
+ 'it("ambient speed changes product output", () => {',
19
+ [
20
+ 'it.fails("ambient speed changes product output", () => {',
21
+ ' throw new Error("runtime evidence probe failure");',
22
+ ].join("\n"),
20
23
  );
21
24
  assert.notEqual(
22
25
  failingSource,
@@ -26,14 +29,19 @@ export async function assertGeneratedRuntimeProbe({
26
29
  await fs.writeFile(productTestPath, failingSource);
27
30
  try {
28
31
  await assert.rejects(
29
- runGeneratedScript(execFileAsync, targetDir, "test"),
32
+ runGeneratedExecutable(execFileAsync, targetDir, "vitest", [
33
+ "run",
34
+ "src",
35
+ "--passWithNoTests",
36
+ "--reporter=default",
37
+ "--reporter=./scripts/toolcraft-vitest-runtime-evidence-reporter.mjs",
38
+ ]),
30
39
  (error) => {
31
40
  const output = `${String(error.stdout)}\n${String(error.stderr)}`;
32
41
  assert.match(
33
- output.slice(-12_000),
42
+ output,
34
43
  /Toolcraft automated runtime coverage failed:[\s\S]*must not use expected-failure mode/u,
35
44
  );
36
- assert.match(output, /TOOLCRAFT_GENERATED_SCRIPT_TEST_EXECUTED/u);
37
45
  return true;
38
46
  },
39
47
  );