@pixel-point/toolcraft 0.0.14 → 0.0.15

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 (577) hide show
  1. package/README.md +13 -2
  2. package/package.json +1 -1
  3. package/scripts/prepare-pack.mjs +2 -28
  4. package/src/cli-io.mjs +174 -0
  5. package/src/cli-package-manager-flow.test.mjs +206 -0
  6. package/src/cli.mjs +7 -495
  7. package/src/cli.test.mjs +34 -177
  8. package/src/create-command.mjs +152 -0
  9. package/src/create-options.mjs +194 -0
  10. package/src/generate-test-assertions.mjs +27 -0
  11. package/src/generate-test-doc-assertions.mjs +162 -0
  12. package/src/generate-test-file-assertions.mjs +251 -0
  13. package/src/generate-test-fs-utils.mjs +59 -0
  14. package/src/generate-test-integrity-assertions.mjs +30 -0
  15. package/src/generate-test-integrity-framework-assertions.mjs +222 -0
  16. package/src/generate-test-integrity-manifest-assertions.mjs +150 -0
  17. package/src/generate-test-integrity-ownership-assertions.mjs +127 -0
  18. package/src/generate-test-integrity-test-utils.mjs +102 -0
  19. package/src/generate-test-package-assertions.mjs +75 -0
  20. package/src/generate-test-product-fixture.mjs +84 -0
  21. package/src/generate-test-product-fixture.test.mjs +73 -0
  22. package/src/generate-test-standalone-assertions.mjs +209 -0
  23. package/src/generate-transactional.test.mjs +151 -0
  24. package/src/generate.mjs +182 -102
  25. package/src/generate.test.mjs +242 -338
  26. package/src/generated-integrity-manifest.mjs +127 -0
  27. package/src/generated-integrity-manifest.test.mjs +151 -0
  28. package/src/generated-source-policy.mjs +22 -0
  29. package/src/generated-source-policy.test.mjs +35 -0
  30. package/src/generated-target-policy.mjs +55 -0
  31. package/src/generation-transaction.mjs +135 -0
  32. package/src/generation-transaction.test.mjs +74 -0
  33. package/src/package-json.mjs +18 -1
  34. package/src/package-json.test.mjs +38 -5
  35. package/src/package-manager.mjs +2 -0
  36. package/src/package-manager.test.mjs +5 -1
  37. package/src/packaged-template-fallback.test.mjs +126 -0
  38. package/src/prepare-pack-templates.mjs +34 -0
  39. package/templates/runtime/contracts/component-contract-builders.ts +95 -0
  40. package/templates/runtime/contracts/component-contracts.choices.test.ts +293 -0
  41. package/templates/runtime/contracts/component-contracts.choices.ts +322 -0
  42. package/templates/runtime/contracts/component-contracts.inputs.test.ts +210 -0
  43. package/templates/runtime/contracts/component-contracts.inputs.ts +252 -0
  44. package/templates/runtime/contracts/component-contracts.media-custom.test.ts +116 -0
  45. package/templates/runtime/contracts/component-contracts.media-custom.ts +144 -0
  46. package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +229 -0
  47. package/templates/runtime/contracts/component-contracts.runtime-labels.test.ts +76 -0
  48. package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +135 -0
  49. package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +148 -0
  50. package/templates/runtime/contracts/component-contracts.runtime.ts +361 -0
  51. package/templates/runtime/contracts/component-contracts.test.ts +39 -1458
  52. package/templates/runtime/contracts/component-contracts.ts +44 -1505
  53. package/templates/runtime/contracts/component-contracts.visual.test.ts +316 -0
  54. package/templates/runtime/contracts/component-contracts.visual.ts +385 -0
  55. package/templates/runtime/contracts/contract-manifest.test.ts +64 -0
  56. package/templates/runtime/contracts/decision-contracts.test.ts +29 -4
  57. package/templates/runtime/contracts/decision-contracts.ts +38 -1
  58. package/templates/runtime/index.ts +1 -0
  59. package/templates/runtime/react/{runtime-public-api.test.tsx → app-shell/runtime-public-api.test.tsx} +29 -7
  60. package/templates/runtime/react/{settings-transfer.test.ts → app-shell/settings-transfer.test.ts} +4 -4
  61. package/templates/runtime/react/{settings-transfer.ts → app-shell/settings-transfer.ts} +3 -3
  62. package/templates/runtime/react/{toolbar-panel.test.tsx → app-shell/toolbar-panel.test.tsx} +2 -2
  63. package/templates/runtime/react/{toolbar-panel.tsx → app-shell/toolbar-panel.tsx} +3 -3
  64. package/templates/runtime/react/{toolcraft-app.integration.test.tsx → app-shell/toolcraft-app.integration.test.tsx} +6 -6
  65. package/templates/runtime/react/{toolcraft-app.test.tsx → app-shell/toolcraft-app.test.tsx} +3 -3
  66. package/templates/runtime/react/{toolcraft-app.tsx → app-shell/toolcraft-app.tsx} +11 -8
  67. package/templates/runtime/react/{toolcraft-root.test.tsx → app-shell/toolcraft-root.test.tsx} +1 -1
  68. package/templates/runtime/react/{toolcraft-root.tsx → app-shell/toolcraft-root.tsx} +5 -5
  69. package/templates/runtime/react/{use-toolcraft.ts → app-shell/use-toolcraft.ts} +1 -1
  70. package/templates/runtime/react/canvas/canvas-default-media-layer.tsx +81 -0
  71. package/templates/runtime/react/canvas/canvas-media-transform.ts +33 -0
  72. package/templates/runtime/react/canvas/canvas-shell-interactions.test.tsx +156 -0
  73. package/templates/runtime/react/canvas/canvas-shell-media-rendering.test.tsx +87 -0
  74. package/templates/runtime/react/canvas/canvas-shell-rendering.test.tsx +102 -0
  75. package/templates/runtime/react/canvas/canvas-shell-test-utils.tsx +108 -0
  76. package/templates/runtime/react/canvas/canvas-shell-upload.test.tsx +106 -0
  77. package/templates/runtime/react/canvas/canvas-shell.tsx +146 -0
  78. package/templates/runtime/react/canvas/canvas-upload-routing.ts +84 -0
  79. package/templates/runtime/react/{media-file.ts → canvas/media-file.ts} +1 -1
  80. package/templates/runtime/react/canvas/use-canvas-drop-import.ts +145 -0
  81. package/templates/runtime/react/canvas/use-canvas-viewport-interactions.ts +227 -0
  82. package/templates/runtime/react/controls-panel/__tests__/control-conditions.test.ts +89 -0
  83. package/templates/runtime/react/{controls-panel-filedrop-reorder.test.tsx → controls-panel/__tests__/controls-panel-filedrop-reorder.test.tsx} +4 -4
  84. package/templates/runtime/react/controls-panel/__tests__/controls-panel.actions-layout.test.tsx +91 -0
  85. package/templates/runtime/react/controls-panel/__tests__/controls-panel.collection-actions.test.tsx +213 -0
  86. package/templates/runtime/react/controls-panel/__tests__/controls-panel.color-layout.test.tsx +366 -0
  87. package/templates/runtime/react/controls-panel/__tests__/controls-panel.color-picker-models.test.tsx +169 -0
  88. package/templates/runtime/react/controls-panel/__tests__/controls-panel.compound-layout.test.tsx +160 -0
  89. package/templates/runtime/react/controls-panel/__tests__/controls-panel.control-visibility.test.tsx +352 -0
  90. package/templates/runtime/react/controls-panel/__tests__/controls-panel.curves.test.tsx +226 -0
  91. package/templates/runtime/react/controls-panel/__tests__/controls-panel.floating-shell.test.tsx +13 -0
  92. package/templates/runtime/react/controls-panel/__tests__/controls-panel.font-picker.test.tsx +302 -0
  93. package/templates/runtime/react/controls-panel/__tests__/controls-panel.footer-actions.test.tsx +401 -0
  94. package/templates/runtime/react/controls-panel/__tests__/controls-panel.gradient-control.test.tsx +139 -0
  95. package/templates/runtime/react/controls-panel/__tests__/controls-panel.help-policy.test.tsx +103 -0
  96. package/templates/runtime/react/controls-panel/__tests__/controls-panel.image-picker.test.tsx +16 -0
  97. package/templates/runtime/react/controls-panel/__tests__/controls-panel.inline-layout.test.tsx +290 -0
  98. package/templates/runtime/react/controls-panel/__tests__/controls-panel.keyframes.test.tsx +175 -0
  99. package/templates/runtime/react/controls-panel/__tests__/controls-panel.media-upload-files.test.tsx +121 -0
  100. package/templates/runtime/react/controls-panel/__tests__/controls-panel.media-upload-image.test.tsx +363 -0
  101. package/templates/runtime/react/controls-panel/__tests__/controls-panel.media-upload-multi-image.test.tsx +105 -0
  102. package/templates/runtime/react/controls-panel/__tests__/controls-panel.range-slider-editing.test.tsx +149 -0
  103. package/templates/runtime/react/controls-panel/__tests__/controls-panel.section-shell.test.tsx +138 -0
  104. package/templates/runtime/react/controls-panel/__tests__/controls-panel.select-layout.test.tsx +148 -0
  105. package/templates/runtime/react/controls-panel/__tests__/controls-panel.setup-controls.test.tsx +189 -0
  106. package/templates/runtime/react/controls-panel/__tests__/controls-panel.slider-rendering.test.tsx +317 -0
  107. package/templates/runtime/react/controls-panel/__tests__/controls-panel.state-reset.test.tsx +137 -0
  108. package/templates/runtime/react/controls-panel/__tests__/controls-panel.structure.test.tsx +66 -0
  109. package/templates/runtime/react/controls-panel/__tests__/controls-panel.text-input.test.tsx +205 -0
  110. package/templates/runtime/react/controls-panel/__tests__/controls-panel.vector-interaction.test.tsx +388 -0
  111. package/templates/runtime/react/controls-panel/__tests__/controls-panel.vector-layout.test.tsx +155 -0
  112. package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +172 -0
  113. package/templates/runtime/react/{control-conditions.ts → controls-panel/conditions/control-conditions.ts} +26 -3
  114. package/templates/runtime/react/{control-renderers.ts → controls-panel/control-renderers.ts} +2 -2
  115. package/templates/runtime/react/controls-panel/controls-panel.tsx +250 -0
  116. package/templates/runtime/react/controls-panel/keyframes/controls-panel-keyframes.tsx +265 -0
  117. package/templates/runtime/react/controls-panel/layout/controls-panel-collapse-storage.ts +131 -0
  118. package/templates/runtime/react/controls-panel/layout/controls-panel-help.tsx +132 -0
  119. package/templates/runtime/react/controls-panel/layout/controls-panel-inline-layout.tsx +311 -0
  120. package/templates/runtime/react/controls-panel/layout/controls-panel-layout.tsx +216 -0
  121. package/templates/runtime/react/controls-panel/layout/controls-panel-section.tsx +401 -0
  122. package/templates/runtime/react/controls-panel/renderers/controls-panel-action-renderer.tsx +137 -0
  123. package/templates/runtime/react/controls-panel/renderers/controls-panel-basic-renderers.tsx +421 -0
  124. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-renderer.tsx +286 -0
  125. package/templates/runtime/react/controls-panel/renderers/controls-panel-compound-renderers.tsx +366 -0
  126. package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.tsx +173 -0
  127. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.test.ts +23 -0
  128. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.ts +55 -0
  129. package/templates/runtime/react/controls-panel/renderers/controls-panel-settings-transfer-renderer.tsx +45 -0
  130. package/templates/runtime/react/controls-panel/testing/controls-panel-test-utils.tsx +300 -0
  131. package/templates/runtime/react/controls-panel/values/controls-panel-aspect-ratio-values.ts +94 -0
  132. package/templates/runtime/react/controls-panel/values/controls-panel-collection-values.ts +87 -0
  133. package/templates/runtime/react/controls-panel/values/controls-panel-color-values.ts +82 -0
  134. package/templates/runtime/react/controls-panel/values/controls-panel-font-values.ts +69 -0
  135. package/templates/runtime/react/controls-panel/values/controls-panel-spatial-values.ts +64 -0
  136. package/templates/runtime/react/controls-panel/values/controls-panel-value-labels.ts +93 -0
  137. package/templates/runtime/react/controls-panel/values/controls-panel-value-primitives.ts +30 -0
  138. package/templates/runtime/react/controls-panel/values/controls-panel-values.ts +7 -0
  139. package/templates/runtime/react/index.ts +13 -13
  140. package/templates/runtime/react/{layer-tree.ts → layers/layer-tree.ts} +1 -1
  141. package/templates/runtime/react/layers/layers-panel-drag-drop.test.tsx +190 -0
  142. package/templates/runtime/react/layers/layers-panel-editing.test.tsx +41 -0
  143. package/templates/runtime/react/layers/layers-panel-insert-targets.test.ts +87 -0
  144. package/templates/runtime/react/layers/layers-panel-insert-targets.ts +254 -0
  145. package/templates/runtime/react/layers/layers-panel-model.ts +15 -0
  146. package/templates/runtime/react/layers/layers-panel-rendering.test.tsx +43 -0
  147. package/templates/runtime/react/layers/layers-panel-reorder.ts +148 -0
  148. package/templates/runtime/react/layers/layers-panel-row.tsx +475 -0
  149. package/templates/runtime/react/layers/layers-panel-test-utils.tsx +135 -0
  150. package/templates/runtime/react/layers/layers-panel-visibility.test.tsx +126 -0
  151. package/templates/runtime/react/layers/layers-panel.tsx +349 -0
  152. package/templates/runtime/react/layers/use-layers-panel-drag-controller.ts +327 -0
  153. package/templates/runtime/react/{panel-host-types.ts → panel-host/panel-host-types.ts} +2 -2
  154. package/templates/runtime/react/{panel-host.test.tsx → panel-host/panel-host.test.tsx} +3 -3
  155. package/templates/runtime/react/{panel-host.tsx → panel-host/panel-host.tsx} +1 -1
  156. package/templates/runtime/react/timeline/timeline-easing-editor.tsx +409 -0
  157. package/templates/runtime/react/timeline/timeline-easing-geometry.ts +42 -0
  158. package/templates/runtime/react/timeline/timeline-easing-icons.tsx +135 -0
  159. package/templates/runtime/react/timeline/timeline-easing-model.test.ts +87 -0
  160. package/templates/runtime/react/timeline/timeline-easing-model.ts +271 -0
  161. package/templates/runtime/react/timeline/timeline-easing-popover-content.tsx +227 -0
  162. package/templates/runtime/react/timeline/timeline-easing-popover-layout.ts +69 -0
  163. package/templates/runtime/react/timeline/timeline-easing-popover.tsx +60 -0
  164. package/templates/runtime/react/timeline/timeline-event-targets.ts +19 -0
  165. package/templates/runtime/react/timeline/timeline-expanded-content.tsx +299 -0
  166. package/templates/runtime/react/timeline/timeline-icon-button.tsx +51 -0
  167. package/templates/runtime/react/timeline/timeline-keyframe-row.tsx +360 -0
  168. package/templates/runtime/react/timeline/timeline-keyframes.ts +23 -0
  169. package/templates/runtime/react/timeline/timeline-panel-floating-layout.test.tsx +328 -0
  170. package/templates/runtime/react/timeline/timeline-panel-header.tsx +404 -0
  171. package/templates/runtime/react/timeline/timeline-panel-keyframes.test.tsx +90 -0
  172. package/templates/runtime/react/timeline/timeline-panel-layout.ts +30 -0
  173. package/templates/runtime/react/timeline/timeline-panel-responsive-layout.ts +182 -0
  174. package/templates/runtime/react/timeline/timeline-panel-test-utils.tsx +88 -0
  175. package/templates/runtime/react/timeline/timeline-panel-transport.test.tsx +202 -0
  176. package/templates/runtime/react/timeline/timeline-panel-upload.test.tsx +53 -0
  177. package/templates/runtime/react/timeline/timeline-panel.tsx +449 -0
  178. package/templates/runtime/react/timeline/timeline-playback-hooks.ts +254 -0
  179. package/templates/runtime/schema/assembly-contract.ts +271 -0
  180. package/templates/runtime/schema/control-schema-normalization.ts +55 -0
  181. package/templates/runtime/schema/controls-panel-actions.ts +141 -0
  182. package/templates/runtime/schema/controls-panel-layout-groups.ts +144 -0
  183. package/templates/runtime/schema/controls-panel-normalization.ts +19 -0
  184. package/templates/runtime/schema/controls-panel-section-layout.ts +140 -0
  185. package/templates/runtime/schema/controls-panel-section-titles.ts +161 -0
  186. package/templates/runtime/schema/define-toolcraft-test-utils.ts +18 -0
  187. package/templates/runtime/schema/define-toolcraft.actions.test.ts +182 -0
  188. package/templates/runtime/schema/define-toolcraft.assembly.test.ts +246 -0
  189. package/templates/runtime/schema/define-toolcraft.canvas.test.ts +150 -0
  190. package/templates/runtime/schema/define-toolcraft.control-layout.test.ts +345 -0
  191. package/templates/runtime/schema/define-toolcraft.control-sections.test.ts +304 -0
  192. package/templates/runtime/schema/define-toolcraft.setup-canvas.test.ts +69 -0
  193. package/templates/runtime/schema/define-toolcraft.setup-persistence.test.ts +66 -0
  194. package/templates/runtime/schema/define-toolcraft.setup-render-scale-timeline.test.ts +116 -0
  195. package/templates/runtime/schema/define-toolcraft.setup-settings-transfer.test.ts +291 -0
  196. package/templates/runtime/schema/define-toolcraft.ts +24 -1449
  197. package/templates/runtime/schema/panels-schema-normalization.ts +49 -0
  198. package/templates/runtime/schema/runtime-section-titles.ts +1 -0
  199. package/templates/runtime/schema/runtime-setup-section.ts +282 -0
  200. package/templates/runtime/schema/schema-resolvers.ts +168 -0
  201. package/templates/runtime/schema/types.ts +17 -0
  202. package/templates/runtime/state/canvas-reducer.ts +106 -0
  203. package/templates/runtime/state/canvas-state.ts +209 -0
  204. package/templates/runtime/state/controls-reducer.ts +277 -0
  205. package/templates/runtime/state/history-patches.ts +174 -0
  206. package/templates/runtime/state/layer-state.ts +12 -0
  207. package/templates/runtime/state/layers-reducer.ts +318 -0
  208. package/templates/runtime/state/media-reducer.ts +283 -0
  209. package/templates/runtime/state/media-state.ts +105 -0
  210. package/templates/runtime/state/panels-reducer.ts +58 -0
  211. package/templates/runtime/state/persistence-merge.ts +53 -0
  212. package/templates/runtime/state/persistence-reader-canvas.ts +27 -0
  213. package/templates/runtime/state/persistence-reader-layers.ts +73 -0
  214. package/templates/runtime/state/persistence-reader-media.ts +82 -0
  215. package/templates/runtime/state/persistence-reader-panels.ts +56 -0
  216. package/templates/runtime/state/persistence-reader-primitives.ts +27 -0
  217. package/templates/runtime/state/persistence-reader-timeline.ts +145 -0
  218. package/templates/runtime/state/persistence-reader-values.ts +40 -0
  219. package/templates/runtime/state/persistence-readers.ts +72 -0
  220. package/templates/runtime/state/persistence-shared.ts +23 -0
  221. package/templates/runtime/state/persistence-snapshot.ts +57 -0
  222. package/templates/runtime/state/persistence.ts +16 -581
  223. package/templates/runtime/state/reducer-canvas-panels.test.ts +324 -0
  224. package/templates/runtime/state/reducer-controls.test.ts +158 -0
  225. package/templates/runtime/state/reducer-layers.test.ts +306 -0
  226. package/templates/runtime/state/reducer-media-import-sizing.test.ts +197 -0
  227. package/templates/runtime/state/reducer-media-reorder-history.test.ts +116 -0
  228. package/templates/runtime/state/reducer-media-reset.test.ts +249 -0
  229. package/templates/runtime/state/reducer-media-test-utils.ts +40 -0
  230. package/templates/runtime/state/reducer-media-transform.test.ts +52 -0
  231. package/templates/runtime/state/reducer-test-utils.ts +30 -0
  232. package/templates/runtime/state/reducer-timeline.test.ts +242 -0
  233. package/templates/runtime/state/reducer.ts +57 -1785
  234. package/templates/runtime/state/timeline-reducer.ts +412 -0
  235. package/templates/runtime/state/timeline-values.test.ts +45 -0
  236. package/templates/runtime/state/timeline-values.ts +45 -0
  237. package/templates/runtime/testing/performance-browser-policy.test.ts +81 -0
  238. package/templates/runtime/testing/performance-browser-policy.ts +102 -0
  239. package/templates/runtime/testing/performance-budget-validation.ts +84 -0
  240. package/templates/runtime/testing/performance-control-classification.test.ts +106 -0
  241. package/templates/runtime/testing/performance-control-classification.ts +101 -0
  242. package/templates/runtime/testing/performance-coverage-context.ts +44 -0
  243. package/templates/runtime/testing/performance-coverage-renderer-policy.ts +221 -0
  244. package/templates/runtime/testing/performance-coverage-scenario-policy.ts +147 -0
  245. package/templates/runtime/testing/performance-coverage-target-policy.ts +121 -0
  246. package/templates/runtime/testing/performance-coverage-validator.ts +34 -0
  247. package/templates/runtime/testing/performance-export-coverage.test.ts +234 -0
  248. package/templates/runtime/testing/performance-fixture-load-profile.test.ts +360 -0
  249. package/templates/runtime/testing/performance-fixture-media.test.ts +80 -0
  250. package/templates/runtime/testing/performance-fixture-stress.test.ts +314 -0
  251. package/templates/runtime/testing/performance-fixture-validation.ts +255 -0
  252. package/templates/runtime/testing/performance-fixture-values.ts +275 -0
  253. package/templates/runtime/testing/performance-fixture-workload.test.ts +140 -0
  254. package/templates/runtime/testing/performance-load-profile-validation.ts +467 -0
  255. package/templates/runtime/testing/performance-renderer-coverage.test.ts +325 -0
  256. package/templates/runtime/testing/performance-renderer-pipeline-coverage.test.ts +115 -0
  257. package/templates/runtime/testing/performance-renderer-pipeline-interactions.test.ts +201 -0
  258. package/templates/runtime/testing/performance-renderer-pipeline-passes.test.ts +247 -0
  259. package/templates/runtime/testing/performance-renderer-pipeline-validation.ts +360 -0
  260. package/templates/runtime/testing/performance-renderer-technique-validation.ts +329 -0
  261. package/templates/runtime/testing/performance-renderer-technique.test.ts +275 -0
  262. package/templates/runtime/testing/performance-renderer-validation.ts +2 -0
  263. package/templates/runtime/testing/performance-scenario-coverage.test.ts +303 -0
  264. package/templates/runtime/testing/performance-scenario-validation.ts +49 -0
  265. package/templates/runtime/testing/performance-schema-derived-workloads.test.ts +231 -0
  266. package/templates/runtime/testing/performance-schema-queries.ts +181 -0
  267. package/templates/runtime/testing/performance-test-fixtures/index.ts +4 -0
  268. package/templates/runtime/testing/performance-test-fixtures/renderer-pipelines.ts +322 -0
  269. package/templates/runtime/testing/performance-test-fixtures/scenarios.ts +172 -0
  270. package/templates/runtime/testing/performance-test-fixtures/schemas.ts +151 -0
  271. package/templates/runtime/testing/performance-test-fixtures/stress-fixtures.ts +133 -0
  272. package/templates/runtime/testing/performance-test-fixtures.ts +1 -0
  273. package/templates/runtime/testing/performance-types.ts +338 -0
  274. package/templates/runtime/testing/performance.ts +15 -2485
  275. package/templates/starter/AGENTS.md +41 -26
  276. package/templates/starter/LICENSE.md +18 -95
  277. package/templates/starter/NOTICE.md +3 -3
  278. package/templates/starter/docs/toolcraft/README.md +5 -5
  279. package/templates/starter/docs/toolcraft/acceptance-testing.md +36 -8
  280. package/templates/starter/docs/toolcraft/assembly-workflow.md +12 -15
  281. package/templates/starter/docs/toolcraft/component-rules.md +6 -2
  282. package/templates/starter/docs/toolcraft/core/layout.md +1 -0
  283. package/templates/starter/docs/toolcraft/core/performance.md +7 -4
  284. package/templates/starter/docs/toolcraft/core/runtime-boundary.md +11 -4
  285. package/templates/starter/docs/toolcraft/core/timeline-animation.md +1 -0
  286. package/templates/starter/docs/toolcraft/custom-controls.md +8 -1
  287. package/templates/starter/docs/toolcraft/decision-contract.md +26 -22
  288. package/templates/starter/docs/toolcraft/performance.md +42 -16
  289. package/templates/starter/docs/toolcraft/schema-reference.md +34 -23
  290. package/templates/starter/docs/toolcraft/workflow.md +25 -17
  291. package/templates/starter/e2e/app-browser-acceptance-evidence.spec.ts +111 -0
  292. package/templates/starter/e2e/app-browser-control-coverage.spec.ts +118 -0
  293. package/templates/starter/e2e/app-browser-performance-evidence.spec.ts +217 -0
  294. package/templates/starter/e2e/app-browser-performance-probe.spec.ts +322 -0
  295. package/templates/starter/e2e/app-browser-proof-session.spec.ts +196 -0
  296. package/templates/starter/e2e/app-browser-runtime-evidence.spec.ts +9 -0
  297. package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +240 -0
  298. package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +180 -0
  299. package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +310 -0
  300. package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +432 -0
  301. package/templates/starter/e2e/app-browser-shell.spec.ts +171 -0
  302. package/templates/starter/e2e/app-browser-timeline-layers-reference.spec.ts +70 -0
  303. package/templates/starter/e2e/app-performance.spec.ts +0 -491
  304. package/templates/starter/e2e/browser-acceptance-outcome-helpers.ts +97 -0
  305. package/templates/starter/e2e/browser-acceptance-transition-helpers.ts +74 -0
  306. package/templates/starter/e2e/browser-conditional-output-evidence-helpers.ts +230 -0
  307. package/templates/starter/e2e/browser-control-target-helpers.ts +109 -0
  308. package/templates/starter/e2e/browser-layer-evidence-helpers.ts +229 -0
  309. package/templates/starter/e2e/browser-proof-session.ts +392 -0
  310. package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +136 -0
  311. package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +290 -0
  312. package/templates/starter/e2e/browser-runtime-evidence.ts +27 -0
  313. package/templates/starter/e2e/browser-state-evidence-helpers.ts +205 -0
  314. package/templates/starter/e2e/browser-timeline-evidence-helpers.ts +319 -0
  315. package/templates/starter/e2e/canvas-handle-helpers.ts +86 -4
  316. package/templates/starter/e2e/export-artifact-helpers.ts +132 -0
  317. package/templates/starter/e2e/performance-budget-helpers.ts +159 -0
  318. package/templates/starter/e2e/performance-canvas-helpers.ts +123 -0
  319. package/templates/starter/e2e/performance-control-helpers.ts +3 -0
  320. package/templates/starter/e2e/performance-control-layout-helpers.ts +161 -0
  321. package/templates/starter/e2e/performance-fixture-helpers.ts +217 -0
  322. package/templates/starter/e2e/performance-frame-probe.ts +247 -0
  323. package/templates/starter/e2e/performance-helpers.ts +6 -854
  324. package/templates/starter/e2e/performance-interaction-measurement.ts +251 -0
  325. package/templates/starter/e2e/performance-measurement-evidence.ts +72 -0
  326. package/templates/starter/e2e/performance-output-action-helpers.spec.ts +43 -0
  327. package/templates/starter/e2e/performance-output-action-helpers.ts +109 -0
  328. package/templates/starter/e2e/performance-probe-helpers.ts +12 -0
  329. package/templates/starter/e2e/performance-render-scale-helpers.ts +55 -0
  330. package/templates/starter/e2e/performance-slider-helpers.ts +271 -0
  331. package/templates/starter/e2e/product-observable-helpers.ts +72 -17
  332. package/templates/starter/e2e/stable-outcome-helpers.ts +208 -0
  333. package/templates/starter/package.json +10 -5
  334. package/templates/starter/playwright.config.ts +5 -2
  335. package/templates/starter/scripts/check-ai-skills.mjs +14 -8
  336. package/templates/starter/scripts/check-ai-skills.test.mjs +64 -0
  337. package/templates/starter/scripts/check-toolcraft-code-health.mjs +108 -0
  338. package/templates/starter/scripts/check-toolcraft-code-health.test.mjs +213 -0
  339. package/templates/starter/scripts/check-toolcraft-docs.mjs +47 -34
  340. package/templates/starter/scripts/check-toolcraft-integrity.mjs +141 -144
  341. package/templates/starter/scripts/run-browser-performance.mjs +118 -0
  342. package/templates/starter/scripts/run-browser-performance.test.mjs +53 -0
  343. package/templates/starter/scripts/toolcraft-code-health-core.mjs +297 -0
  344. package/templates/starter/scripts/toolcraft-contract-doc-integrity.mjs +77 -0
  345. package/templates/starter/scripts/toolcraft-contract-doc-integrity.test.mjs +81 -0
  346. package/templates/starter/scripts/toolcraft-contract-manifest.json +113 -0
  347. package/templates/starter/scripts/toolcraft-contract-manifest.mjs +128 -0
  348. package/templates/starter/scripts/toolcraft-contract-manifest.test.mjs +72 -0
  349. package/templates/starter/scripts/toolcraft-integrity-manifest.mjs +172 -0
  350. package/templates/starter/scripts/toolcraft-integrity-policy.mjs +60 -0
  351. package/templates/starter/scripts/toolcraft-product-boundary-ast-utils.mjs +23 -0
  352. package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +264 -0
  353. package/templates/starter/scripts/toolcraft-product-boundary-test-fixtures.mjs +16 -0
  354. package/templates/starter/scripts/toolcraft-product-boundary.mjs +243 -0
  355. package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +289 -0
  356. package/templates/starter/scripts/toolcraft-product-dependency-graph.mjs +176 -0
  357. package/templates/starter/scripts/toolcraft-product-dependency-graph.test.mjs +196 -0
  358. package/templates/starter/scripts/toolcraft-product-dependency-resolution.mjs +279 -0
  359. package/templates/starter/scripts/toolcraft-product-evidence-boundary-ast.mjs +91 -0
  360. package/templates/starter/scripts/toolcraft-product-evidence-boundary.test.mjs +138 -0
  361. package/templates/starter/scripts/toolcraft-product-style-boundary.mjs +219 -0
  362. package/templates/starter/scripts/toolcraft-source-inventory.d.mts +46 -0
  363. package/templates/starter/scripts/toolcraft-source-inventory.mjs +187 -0
  364. package/templates/starter/scripts/toolcraft-source-inventory.test.mjs +132 -0
  365. package/templates/starter/scripts/toolcraft-source-ownership.mjs +167 -0
  366. package/templates/starter/scripts/toolcraft-source-ownership.test.mjs +113 -0
  367. package/templates/starter/scripts/toolcraft-static-string.mjs +104 -0
  368. package/templates/starter/scripts/toolcraft-verification-inventory.mjs +123 -0
  369. package/templates/starter/scripts/toolcraft-verification-receipt.d.mts +19 -0
  370. package/templates/starter/scripts/toolcraft-verification-receipt.mjs +284 -0
  371. package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +282 -0
  372. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.d.mts +32 -0
  373. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.mjs +88 -0
  374. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.test.mjs +87 -0
  375. package/templates/starter/scripts/toolcraft-vitest-runtime-evidence-reporter.mjs +109 -0
  376. package/templates/starter/scripts/toolcraft-vitest-runtime-evidence-reporter.test.mjs +111 -0
  377. package/templates/starter/scripts/toolcraft-workflow-routes.mjs +314 -0
  378. package/templates/starter/scripts/toolcraft-workflow-routes.test.mjs +204 -0
  379. package/templates/starter/src/app/acceptance/actions.ts +30 -0
  380. package/templates/starter/src/app/acceptance/animation-intent.ts +184 -0
  381. package/templates/starter/src/app/acceptance/canvas-handle-acceptance.ts +70 -0
  382. package/templates/starter/src/app/acceptance/color-bank-labels.ts +164 -0
  383. package/templates/starter/src/app/acceptance/conditions.ts +80 -0
  384. package/templates/starter/src/app/acceptance/control-acceptance-context.ts +70 -0
  385. package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +271 -0
  386. package/templates/starter/src/app/acceptance/control-acceptance-kind-rules.ts +149 -0
  387. package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +189 -0
  388. package/templates/starter/src/app/acceptance/control-acceptance.ts +70 -0
  389. package/templates/starter/src/app/acceptance/control-component-rules.ts +277 -0
  390. package/templates/starter/src/app/acceptance/control-labels.ts +223 -0
  391. package/templates/starter/src/app/acceptance/control-layout-dependency-rules.ts +107 -0
  392. package/templates/starter/src/app/acceptance/control-layout-entity-rules.ts +104 -0
  393. package/templates/starter/src/app/acceptance/control-layout-model.ts +159 -0
  394. package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +164 -0
  395. package/templates/starter/src/app/acceptance/control-layout.ts +45 -0
  396. package/templates/starter/src/app/acceptance/control-order.ts +123 -0
  397. package/templates/starter/src/app/acceptance/control-parts.ts +47 -0
  398. package/templates/starter/src/app/acceptance/control-section-inventory.ts +183 -0
  399. package/templates/starter/src/app/acceptance/controls.ts +27 -0
  400. package/templates/starter/src/app/acceptance/coverage.ts +81 -0
  401. package/templates/starter/src/app/acceptance/custom-controls.ts +140 -0
  402. package/templates/starter/src/app/acceptance/inline-layout.ts +192 -0
  403. package/templates/starter/src/app/acceptance/media-upload.ts +55 -0
  404. package/templates/starter/src/app/acceptance/output-background-rules.ts +135 -0
  405. package/templates/starter/src/app/acceptance/output-export-actions.test.ts +76 -0
  406. package/templates/starter/src/app/acceptance/output-export-actions.ts +34 -0
  407. package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +46 -0
  408. package/templates/starter/src/app/acceptance/output-export-model.ts +146 -0
  409. package/templates/starter/src/app/acceptance/output-export.ts +45 -0
  410. package/templates/starter/src/app/acceptance/output-image-export-rules.ts +87 -0
  411. package/templates/starter/src/app/acceptance/reference-runtime-coverage.ts +96 -0
  412. package/templates/starter/src/app/acceptance/reference-runtime-feature-inventory.ts +171 -0
  413. package/templates/starter/src/app/acceptance/reference-runtime-study.ts +73 -0
  414. package/templates/starter/src/app/acceptance/reference-runtime-timeline.ts +291 -0
  415. package/templates/starter/src/app/acceptance/reference-runtime.ts +99 -0
  416. package/templates/starter/src/app/acceptance/runtime-coverage.ts +290 -0
  417. package/templates/starter/src/app/acceptance/runtime-setup.ts +117 -0
  418. package/templates/starter/src/app/acceptance/section-title-rules.ts +8 -0
  419. package/templates/starter/src/app/acceptance/sections.ts +6 -0
  420. package/templates/starter/src/app/acceptance/semantic.ts +63 -0
  421. package/templates/starter/src/app/acceptance/timeline-loop.ts +21 -0
  422. package/templates/starter/src/app/acceptance/types.ts +363 -0
  423. package/templates/starter/src/app/acceptance/validate-coverage.ts +217 -0
  424. package/templates/starter/src/app/acceptance/validation-pipeline.test.ts +56 -0
  425. package/templates/starter/src/app/acceptance/validation-pipeline.ts +60 -0
  426. package/templates/starter/src/app/acceptance/video-reference-study.ts +217 -0
  427. package/templates/starter/src/app/starter-acceptance-data.ts +21 -0
  428. package/templates/starter/src/app/starter-acceptance.animation-intent.test.ts +383 -0
  429. package/templates/starter/src/app/starter-acceptance.background-export.test.ts +349 -0
  430. package/templates/starter/src/app/starter-acceptance.base-coverage.test.ts +47 -0
  431. package/templates/starter/src/app/starter-acceptance.canvas-handles.test.ts +71 -0
  432. package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +199 -0
  433. package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +244 -0
  434. package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +63 -0
  435. package/templates/starter/src/app/starter-acceptance.control-label-context.test.ts +172 -0
  436. package/templates/starter/src/app/starter-acceptance.control-labels.test.ts +387 -0
  437. package/templates/starter/src/app/starter-acceptance.control-naming-rules.test.ts +215 -0
  438. package/templates/starter/src/app/starter-acceptance.control-order.test.ts +274 -0
  439. package/templates/starter/src/app/starter-acceptance.control-state.test.ts +275 -0
  440. package/templates/starter/src/app/starter-acceptance.curves-rules.test.ts +184 -0
  441. package/templates/starter/src/app/starter-acceptance.custom-control-collections.test.ts +200 -0
  442. package/templates/starter/src/app/starter-acceptance.custom-control-coverage.test.ts +111 -0
  443. package/templates/starter/src/app/starter-acceptance.custom-control-fit-check.test.ts +135 -0
  444. package/templates/starter/src/app/starter-acceptance.custom-control-valid.test.ts +74 -0
  445. package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +107 -0
  446. package/templates/starter/src/app/starter-acceptance.framework-boundary.test.ts +327 -0
  447. package/templates/starter/src/app/starter-acceptance.image-video-export-settings.test.ts +328 -0
  448. package/templates/starter/src/app/starter-acceptance.keyframes.test.ts +242 -0
  449. package/templates/starter/src/app/starter-acceptance.layers.test.ts +203 -0
  450. package/templates/starter/src/app/starter-acceptance.media-upload.fixtures.ts +110 -0
  451. package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +153 -0
  452. package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +97 -0
  453. package/templates/starter/src/app/starter-acceptance.persistence-coverage.test.ts +134 -0
  454. package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +202 -0
  455. package/templates/starter/src/app/starter-acceptance.product-readiness-rules.test.ts +14 -0
  456. package/templates/starter/src/app/starter-acceptance.product-readiness-test-utils.ts +25 -0
  457. package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +50 -0
  458. package/templates/starter/src/app/starter-acceptance.product-worklog.test.ts +27 -0
  459. package/templates/starter/src/app/starter-acceptance.range-slider-rules.test.ts +147 -0
  460. package/templates/starter/src/app/starter-acceptance.reference-custom-timeline.test.ts +197 -0
  461. package/templates/starter/src/app/starter-acceptance.reference-foundation.test.ts +304 -0
  462. package/templates/starter/src/app/starter-acceptance.reference-test-utils.ts +102 -0
  463. package/templates/starter/src/app/starter-acceptance.reference-timeline.test.ts +267 -0
  464. package/templates/starter/src/app/starter-acceptance.schema-test-utils.ts +116 -0
  465. package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +373 -0
  466. package/templates/starter/src/app/starter-acceptance.section-dependencies.test.ts +260 -0
  467. package/templates/starter/src/app/starter-acceptance.section-titles.test.ts +180 -0
  468. package/templates/starter/src/app/starter-acceptance.setup-readiness.test.ts +205 -0
  469. package/templates/starter/src/app/starter-acceptance.slider-rules.test.ts +470 -0
  470. package/templates/starter/src/app/starter-acceptance.slider-unit-rules.test.ts +61 -0
  471. package/templates/starter/src/app/starter-acceptance.source-test-utils.ts +43 -0
  472. package/templates/starter/src/app/starter-acceptance.test-utils.ts +21 -0
  473. package/templates/starter/src/app/starter-acceptance.text-control-kind.test.ts +89 -0
  474. package/templates/starter/src/app/starter-acceptance.timeline-playback.test.ts +264 -0
  475. package/templates/starter/src/app/starter-acceptance.timeline-test-utils.ts +56 -0
  476. package/templates/starter/src/app/starter-acceptance.toggle-pair-layout.test.ts +200 -0
  477. package/templates/starter/src/app/starter-acceptance.toggle-parameter-layout.test.ts +277 -0
  478. package/templates/starter/src/app/starter-acceptance.ts +151 -4576
  479. package/templates/starter/src/app/starter-acceptance.video-export-test-utils.ts +37 -0
  480. package/templates/starter/src/app/starter-acceptance.video-reference-study.test.ts +262 -0
  481. package/templates/starter/src/app/starter-acceptance.worklog-test-utils.ts +428 -0
  482. package/templates/starter/src/app/starter-acceptance.worklog.test.ts +283 -0
  483. package/templates/starter/src/app/starter-automated-runtime-evidence.test.ts +34 -0
  484. package/templates/starter/src/app/starter-composition.tsx +7 -0
  485. package/templates/starter/src/app/starter-performance-test-utils.ts +275 -0
  486. package/templates/starter/src/app/starter-performance.budgets.test.ts +374 -0
  487. package/templates/starter/src/app/starter-performance.gates.test.ts +128 -0
  488. package/templates/starter/src/app/starter-performance.renderer-source.test.ts +136 -0
  489. package/templates/starter/src/app/starter-performance.renderer-technique.test.ts +291 -0
  490. package/templates/starter/src/app/starter-performance.scenarios.test.ts +355 -0
  491. package/templates/starter/src/app/test-evidence/browser-runtime-contract.test.ts +253 -0
  492. package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +243 -0
  493. package/templates/starter/src/routes/index.tsx +11 -2
  494. package/templates/starter/vite.config.ts +8 -0
  495. package/templates/ui/components/controls/color/color-control-types.ts +38 -0
  496. package/templates/ui/components/controls/color/color-control.tsx +19 -437
  497. package/templates/ui/components/controls/color/color-footer.tsx +272 -0
  498. package/templates/ui/components/controls/color/color-model-slider.tsx +271 -0
  499. package/templates/ui/components/controls/color/color-opacity-input.tsx +94 -0
  500. package/templates/ui/components/controls/color/color-surface.tsx +194 -0
  501. package/templates/ui/components/controls/color/color-value-control.tsx +159 -0
  502. package/templates/ui/components/controls/color/color-value-utils.ts +170 -0
  503. package/templates/ui/components/controls/color/index.ts +10 -3
  504. package/templates/ui/components/controls/color/palette-control-controller.ts +407 -0
  505. package/templates/ui/components/controls/color/palette-control-layout.ts +14 -0
  506. package/templates/ui/components/controls/color/palette-control-types.ts +50 -0
  507. package/templates/ui/components/controls/color/palette-control-view.tsx +174 -0
  508. package/templates/ui/components/controls/color/palette-control.tsx +6 -544
  509. package/templates/ui/components/controls/color/style-guide-color-picker-color-utils.ts +39 -0
  510. package/templates/ui/components/controls/color/style-guide-color-picker-controller.ts +370 -0
  511. package/templates/ui/components/controls/color/style-guide-color-picker-hue-handlers.ts +66 -0
  512. package/templates/ui/components/controls/color/style-guide-color-picker-interaction-state.ts +49 -0
  513. package/templates/ui/components/controls/color/style-guide-color-picker-interactions.ts +2 -2
  514. package/templates/ui/components/controls/color/style-guide-color-picker-model.ts +125 -0
  515. package/templates/ui/components/controls/color/style-guide-color-picker-parts.tsx +10 -707
  516. package/templates/ui/components/controls/color/style-guide-color-picker-surface-drag.ts +93 -0
  517. package/templates/ui/components/controls/color/style-guide-color-picker-surface-geometry.ts +114 -0
  518. package/templates/ui/components/controls/color/style-guide-color-picker-surface-preview.ts +45 -0
  519. package/templates/ui/components/controls/color/style-guide-color-picker-types.ts +84 -0
  520. package/templates/ui/components/controls/color/style-guide-color-picker-view.tsx +69 -0
  521. package/templates/ui/components/controls/color/style-guide-color-picker.tsx +6 -495
  522. package/templates/ui/components/controls/curves/curves-control.tsx +4 -3
  523. package/templates/ui/components/controls/file-drop/file-drop-control.tsx +39 -515
  524. package/templates/ui/components/controls/file-drop/file-drop-empty-state.tsx +35 -0
  525. package/templates/ui/components/controls/file-drop/file-drop-file-list.tsx +160 -0
  526. package/templates/ui/components/controls/file-drop/file-drop-image-grid.tsx +175 -0
  527. package/templates/ui/components/controls/file-drop/file-drop-model.tsx +170 -0
  528. package/templates/ui/components/controls/file-drop/file-drop-single-preview.tsx +63 -0
  529. package/templates/ui/components/controls/file-drop/file-drop-types.ts +48 -0
  530. package/templates/ui/components/controls/file-drop/index.ts +2 -2
  531. package/templates/ui/components/controls/font-picker/font-picker-control.tsx +133 -906
  532. package/templates/ui/components/controls/font-picker/font-picker-footer.tsx +116 -0
  533. package/templates/ui/components/controls/font-picker/font-picker-list.tsx +194 -0
  534. package/templates/ui/components/controls/font-picker/font-picker-popover-content.tsx +191 -0
  535. package/templates/ui/components/controls/font-picker/font-picker-value.ts +222 -0
  536. package/templates/ui/components/controls/font-picker/index.ts +4 -1
  537. package/templates/ui/components/controls/font-picker/use-font-picker-preview-pipeline.ts +163 -0
  538. package/templates/ui/components/controls/font-picker/use-font-picker-virtual-list.ts +293 -0
  539. package/templates/ui/components/controls/gradient/gradient-control-utils.ts +2 -25
  540. package/templates/ui/components/controls/gradient/gradient-control.tsx +4 -464
  541. package/templates/ui/components/controls/gradient/gradient-stops-controller.ts +332 -0
  542. package/templates/ui/components/controls/gradient/gradient-stops-track.tsx +159 -0
  543. package/templates/ui/components/controls/vector/vector-control-types.ts +26 -0
  544. package/templates/ui/components/controls/vector/vector-control.tsx +10 -486
  545. package/templates/ui/components/controls/vector/vector-pad-field.tsx +211 -0
  546. package/templates/ui/components/controls/vector/vector-pad-geometry.ts +61 -0
  547. package/templates/ui/components/controls/vector/vector-pad-parts.tsx +72 -0
  548. package/templates/ui/components/controls/vector/vector-pad-variants.ts +20 -0
  549. package/templates/ui/components/controls/vector/vector-size-field.tsx +104 -0
  550. package/templates/ui/components/controls/vector/vector-value.ts +46 -0
  551. package/templates/ui/components/primitives/slider/slider-discrete-state.ts +181 -0
  552. package/templates/ui/components/primitives/slider/slider-marker-policy.ts +52 -0
  553. package/templates/ui/components/primitives/slider/slider-pointer-dragging.ts +87 -0
  554. package/templates/ui/components/primitives/slider/slider-runtime.ts +109 -0
  555. package/templates/ui/components/primitives/slider/slider-types.ts +21 -0
  556. package/templates/ui/components/primitives/slider/slider.tsx +2 -403
  557. package/templates/runtime/react/canvas-shell.test.tsx +0 -554
  558. package/templates/runtime/react/canvas-shell.tsx +0 -585
  559. package/templates/runtime/react/controls-panel.test.tsx +0 -5446
  560. package/templates/runtime/react/controls-panel.tsx +0 -3220
  561. package/templates/runtime/react/layers-panel.test.tsx +0 -487
  562. package/templates/runtime/react/layers-panel.tsx +0 -1348
  563. package/templates/runtime/react/timeline-panel.test.tsx +0 -751
  564. package/templates/runtime/react/timeline-panel.tsx +0 -3078
  565. package/templates/runtime/schema/define-toolcraft.test.ts +0 -1742
  566. package/templates/runtime/state/reducer.test.ts +0 -1703
  567. package/templates/runtime/testing/performance.test.ts +0 -3081
  568. package/templates/starter/e2e/app-browser-acceptance.spec.ts +0 -785
  569. package/templates/starter/src/app/starter-acceptance.test.ts +0 -10068
  570. package/templates/starter/src/app/starter-performance.test.ts +0 -1583
  571. package/templates/ui/components/controls/color/style-guide-color-picker-logic.ts +0 -490
  572. /package/templates/runtime/react/{storage-key-migration.ts → app-shell/storage-key-migration.ts} +0 -0
  573. /package/templates/runtime/react/{theme-runtime.tsx → app-shell/theme-runtime.tsx} +0 -0
  574. /package/templates/runtime/react/{curve-geometry.test.ts → controls-panel/__tests__/curve-geometry.test.ts} +0 -0
  575. /package/templates/runtime/react/{panel-host-config.ts → panel-host/panel-host-config.ts} +0 -0
  576. /package/templates/runtime/react/{panel-host-geometry.test.ts → panel-host/panel-host-geometry.test.ts} +0 -0
  577. /package/templates/runtime/react/{panel-host-geometry.ts → panel-host/panel-host-geometry.ts} +0 -0
@@ -1,497 +1,6 @@
1
- import { readdirSync, readFileSync } from "node:fs";
2
- import { basename, dirname, join } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
-
5
1
  import { expect, test } from "@playwright/test";
6
2
 
7
3
  import { starterPerformance } from "../src/app/starter-performance";
8
- import { starterSchema } from "../src/app/starter-schema";
9
-
10
- const currentFileName = basename(fileURLToPath(import.meta.url));
11
- const e2eDir = dirname(fileURLToPath(import.meta.url));
12
-
13
- type BrowserTestSource = {
14
- fileName: string;
15
- source: string;
16
- };
17
-
18
- function escapeRegExp(value: string): string {
19
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
20
- }
21
-
22
- function stripJsComments(source: string): string {
23
- return source
24
- .replace(/\/\*[\s\S]*?\*\//g, "")
25
- .replace(/(^|[^:])\/\/.*$/gm, "$1");
26
- }
27
-
28
- function hasRealLayerRowInteraction(source: string): boolean {
29
- return /data-layer-id|data-template-layer-name|selectLayerByName\s*\(|layerRowByName\s*\(|getByRole\s*\(\s*(["'`])option\1/i.test(
30
- source,
31
- );
32
- }
33
-
34
- function hasRealLayerVisibilityInteraction(source: string): boolean {
35
- return /toggleLayerVisibilityByName\s*\(|getByRole\s*\([\s\S]*?(Hide|Show|Disable|Enable).*layer|aria-label[\s\S]*?(Hide|Show|Disable|Enable)/i.test(
36
- source,
37
- );
38
- }
39
-
40
- function hasRealLayerDragInteraction(source: string): boolean {
41
- return /\.dragTo\s*\(|page\.mouse\.(?:down|move|up)\s*\(|dragLayer(?:Before|After|ToGroup|ByName)?\s*\(/i.test(
42
- source,
43
- );
44
- }
45
-
46
- function readSiblingBrowserTestSources(): BrowserTestSource[] {
47
- return readdirSync(e2eDir)
48
- .filter((fileName) => /\.(test|spec)\.[cm]?[jt]sx?$/.test(fileName))
49
- .filter((fileName) => fileName !== currentFileName)
50
- .map((fileName) => ({
51
- fileName,
52
- source: readFileSync(join(e2eDir, fileName), "utf8"),
53
- }));
54
- }
55
-
56
- function findNamedBrowserTestSource(
57
- sources: readonly BrowserTestSource[],
58
- testName: string,
59
- ): string | undefined {
60
- const testStartPattern = new RegExp(
61
- `(?:test|it)(?:\\.[\\w]+)?\\(\\s*(["'\`])${escapeRegExp(testName)}\\1`,
62
- );
63
- const nextTestPattern = /\n\s*(?:test|it)(?:\.[\w]+)?\(\s*["'`]/;
64
-
65
- for (const { source } of sources) {
66
- const cleanSource = stripJsComments(source);
67
- const match = testStartPattern.exec(cleanSource);
68
- if (!match) {
69
- continue;
70
- }
71
-
72
- const startIndex = match.index;
73
- const afterStart = cleanSource.slice(startIndex + 1);
74
- const nextMatchIndex = afterStart.search(nextTestPattern);
75
-
76
- return cleanSource.slice(
77
- startIndex,
78
- nextMatchIndex === -1 ? undefined : startIndex + 1 + nextMatchIndex,
79
- );
80
- }
81
-
82
- return undefined;
83
- }
84
-
85
- function getDiscreteControlLabels(): Set<string> {
86
- const labels = new Set<string>();
87
-
88
- for (const section of starterSchema.panels.controls?.sections ?? []) {
89
- for (const control of Object.values(section.controls)) {
90
- if (
91
- (control.type === "slider" || control.type === "rangeSlider") &&
92
- control.variant === "discrete" &&
93
- typeof control.label === "string"
94
- ) {
95
- labels.add(control.label);
96
- }
97
- }
98
- }
99
-
100
- return labels;
101
- }
102
-
103
- function getScenarioBudgetAssertionPattern(scenarioId: string): RegExp {
104
- return new RegExp(
105
- `expectToolcraftScenarioPerformanceBudget\\s*\\([\\s\\S]*?,\\s*(?:starterPerformance|appPerformance)\\s*,\\s*(["'\`])${escapeRegExp(
106
- scenarioId,
107
- )}\\1`,
108
- );
109
- }
110
-
111
- function getScenarioStressFixturePattern(scenarioId: string): RegExp {
112
- return new RegExp(
113
- `(?:getToolcraftPerformanceStressValue(?:\\s*<[^>]+>)?\\s*\\(\\s*(?:starterPerformance|appPerformance)|dragToolcraftSliderToPerformanceStressValue\\s*\\([\\s\\S]*?(?:starterPerformance|appPerformance)|applyToolcraftPerformanceStressFixture\\s*\\(\\s*page\\s*,\\s*(?:starterPerformance|appPerformance))\\s*,\\s*(["'\`])${escapeRegExp(
114
- scenarioId,
115
- )}\\1`,
116
- );
117
- }
118
-
119
- function getScenarioWorkloadFixturePattern(scenarioId: string): RegExp {
120
- return new RegExp(
121
- `(?:getToolcraftPerformanceWorkloadValue(?:\\s*<[^>]+>)?\\s*\\(\\s*(?:starterPerformance|appPerformance)|applyToolcraftPerformanceWorkloadFixture\\s*\\(\\s*page\\s*,\\s*(?:starterPerformance|appPerformance))\\s*,\\s*(["'\`])${escapeRegExp(
122
- scenarioId,
123
- )}\\1`,
124
- );
125
- }
126
-
127
- function getScenarioCustomStressFixturePattern(scenarioId: string): RegExp {
128
- return new RegExp(
129
- `applyToolcraftPerformanceStressFixture\\s*\\(\\s*page\\s*,\\s*(?:starterPerformance|appPerformance)\\s*,\\s*(["'\`])${escapeRegExp(
130
- scenarioId,
131
- )}\\1`,
132
- );
133
- }
134
-
135
- function getScenarioCustomWorkloadFixturePattern(scenarioId: string): RegExp {
136
- return new RegExp(
137
- `applyToolcraftPerformanceWorkloadFixture\\s*\\(\\s*page\\s*,\\s*(?:starterPerformance|appPerformance)\\s*,\\s*(["'\`])${escapeRegExp(
138
- scenarioId,
139
- )}\\1`,
140
- );
141
- }
142
-
143
- function getScenarioSliderStressValuePattern(scenarioId: string): RegExp {
144
- return new RegExp(
145
- `dragToolcraftSliderToPerformanceStressValue\\s*\\([\\s\\S]*?(?:starterPerformance|appPerformance)\\s*,\\s*(["'\`])${escapeRegExp(
146
- scenarioId,
147
- )}\\1`,
148
- );
149
- }
150
-
151
- function fixtureValueUsesRenderScale(value: unknown, pathPrefix = ""): boolean {
152
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
153
- return false;
154
- }
155
-
156
- return Object.entries(value).some(([key, itemValue]) => {
157
- const itemPath = pathPrefix ? `${pathPrefix}.${key}` : key;
158
-
159
- return (
160
- /^(?:canvas\.)?renderScale$|(?:^|[._-])resolutionScale$/i.test(itemPath) ||
161
- fixtureValueUsesRenderScale(itemValue, itemPath)
162
- );
163
- });
164
- }
165
-
166
- function scenarioUsesRenderScaleFixture(
167
- scenario: (typeof starterPerformance.scenarios)[number],
168
- ): boolean {
169
- return (
170
- scenario.target === "canvas.renderScale" ||
171
- fixtureValueUsesRenderScale(scenario.stressFixture?.value) ||
172
- fixtureValueUsesRenderScale(scenario.workloadFixture?.value)
173
- );
174
- }
175
-
176
- function scenarioUsesLoadProfile(
177
- scenario: (typeof starterPerformance.scenarios)[number],
178
- ): boolean {
179
- return Boolean(scenario.stressFixture?.loadProfile || scenario.workloadFixture?.loadProfile);
180
- }
181
-
182
- function getFirstMatchIndex(source: string, pattern: RegExp): number {
183
- const match = pattern.exec(source);
184
- return match?.index ?? -1;
185
- }
186
-
187
- test("browser perf: performance matrix points at real fallback browser tests", () => {
188
- const browserTestSources = readSiblingBrowserTestSources();
189
-
190
- for (const scenario of starterPerformance.scenarios) {
191
- if (!scenario.browser) {
192
- continue;
193
- }
194
-
195
- expect(
196
- Boolean(findNamedBrowserTestSource(browserTestSources, scenario.browserTestName)),
197
- `${scenario.id} must be backed by a fallback browser performance test named "${scenario.browserTestName}".`,
198
- ).toBe(true);
199
- }
200
- });
201
-
202
- test("browser perf: performance tests use real Toolcraft interactions", () => {
203
- if (starterPerformance.scenarios.length === 0) {
204
- return;
205
- }
206
-
207
- const browserTestSources = readSiblingBrowserTestSources();
208
- const discreteControlLabels = getDiscreteControlLabels();
209
-
210
- for (const scenario of starterPerformance.scenarios) {
211
- const browserTestSource = findNamedBrowserTestSource(
212
- browserTestSources,
213
- scenario.browserTestName,
214
- );
215
-
216
- expect(
217
- browserTestSource,
218
- `${scenario.id} must be backed by a browser performance test named "${scenario.browserTestName}".`,
219
- ).toBeDefined();
220
-
221
- if (!browserTestSource) {
222
- continue;
223
- }
224
-
225
- if (scenario.workload || scenario.stress === true || scenario.stressFixture) {
226
- expect(
227
- scenario.stressFixture,
228
- `${scenario.id} stress scenario must declare stressFixture so browser tests cannot use toy inputs.`,
229
- ).toBeDefined();
230
- expect(
231
- browserTestSource,
232
- `${scenario.id} must read the declared stress fixture with getToolcraftPerformanceStressValue(appPerformance, "${scenario.id}") before measuring performance.`,
233
- ).toMatch(getScenarioStressFixturePattern(scenario.id));
234
-
235
- if (
236
- scenario.stressFixture?.kind === "custom" &&
237
- typeof scenario.stressFixture.value === "object" &&
238
- scenario.stressFixture.value !== null &&
239
- !Array.isArray(scenario.stressFixture.value)
240
- ) {
241
- expect(
242
- browserTestSource,
243
- `${scenario.id} custom stress fixture must be applied with applyToolcraftPerformanceStressFixture so every heavy-state key is mapped through the real UI before measurement.`,
244
- ).toMatch(getScenarioCustomStressFixturePattern(scenario.id));
245
- }
246
- }
247
-
248
- if (scenario.workloadFixture) {
249
- const workloadFixtureIndex = getFirstMatchIndex(
250
- browserTestSource,
251
- getScenarioWorkloadFixturePattern(scenario.id),
252
- );
253
- const stressFixtureIndex = getFirstMatchIndex(
254
- browserTestSource,
255
- getScenarioStressFixturePattern(scenario.id),
256
- );
257
- const budgetAssertionIndex = getFirstMatchIndex(
258
- browserTestSource,
259
- getScenarioBudgetAssertionPattern(scenario.id),
260
- );
261
-
262
- expect(
263
- browserTestSource,
264
- `${scenario.id} must apply the declared workloadFixture with getToolcraftPerformanceWorkloadValue(appPerformance, "${scenario.id}") or applyToolcraftPerformanceWorkloadFixture before measuring performance.`,
265
- ).toMatch(getScenarioWorkloadFixturePattern(scenario.id));
266
- expect(
267
- workloadFixtureIndex,
268
- `${scenario.id} must apply workloadFixture before stressFixture so the measured control runs inside the heavy app baseline.`,
269
- ).toBeGreaterThanOrEqual(0);
270
- expect(
271
- stressFixtureIndex,
272
- `${scenario.id} must read/apply stressFixture after workloadFixture.`,
273
- ).toBeGreaterThan(workloadFixtureIndex);
274
- expect(
275
- budgetAssertionIndex,
276
- `${scenario.id} must assert budget only after workloadFixture is applied.`,
277
- ).toBeGreaterThan(workloadFixtureIndex);
278
-
279
- if (
280
- scenario.workloadFixture.kind === "custom" &&
281
- typeof scenario.workloadFixture.value === "object" &&
282
- scenario.workloadFixture.value !== null &&
283
- !Array.isArray(scenario.workloadFixture.value)
284
- ) {
285
- expect(
286
- browserTestSource,
287
- `${scenario.id} custom workload fixture must be applied with applyToolcraftPerformanceWorkloadFixture so every baseline-state key is mapped through the real UI before measurement.`,
288
- ).toMatch(getScenarioCustomWorkloadFixturePattern(scenario.id));
289
- }
290
- }
291
-
292
- if (scenario.interaction === "control-drag") {
293
- expect(
294
- browserTestSource,
295
- `${scenario.id} must measure a real Toolcraft pointer drag instead of filling a hidden/numeric editor.`,
296
- ).toMatch(/dragToolcraftSliderByLabel\s*\(/);
297
-
298
- if (scenario.controlLabel) {
299
- expect(
300
- browserTestSource,
301
- `${scenario.id} must drag the declared control label "${scenario.controlLabel}".`,
302
- ).toMatch(
303
- new RegExp(
304
- `dragToolcraftSliderByLabel\\s*\\([\\s\\S]*?(["'\`])${escapeRegExp(
305
- scenario.controlLabel,
306
- )}\\1`,
307
- ),
308
- );
309
- }
310
-
311
- if (scenario.controlLabel && discreteControlLabels.has(scenario.controlLabel)) {
312
- expect(
313
- browserTestSource,
314
- `${scenario.id} drags discrete slider "${scenario.controlLabel}" and must verify Toolcraft marker-budget behavior plus smooth drag.`,
315
- ).toMatch(/expectToolcraftDiscreteSliderDragSmoothness\s*\(/);
316
- }
317
-
318
- if (scenario.workload && scenario.controlLabel) {
319
- expect(
320
- browserTestSource,
321
- `${scenario.id} workload slider drags must apply the exact stressFixture.value with dragToolcraftSliderToPerformanceStressValue instead of hand-dividing by max or typing a ratio.`,
322
- ).toMatch(getScenarioSliderStressValuePattern(scenario.id));
323
- }
324
- }
325
-
326
- if (scenarioUsesRenderScaleFixture(scenario)) {
327
- expect(
328
- browserTestSource,
329
- `${scenario.id} uses canvas.renderScale and must prove the selected Resolution scale changes backing canvas pixels instead of only changing declarative state.`,
330
- ).toMatch(/expectToolcraftCanvasBackingPixelsForRenderScale\s*\(/);
331
- }
332
-
333
- if (scenarioUsesLoadProfile(scenario)) {
334
- expect(
335
- browserTestSource,
336
- `${scenario.id} declares a loadProfile and must apply the documented smoothTarget through appPerformance fixtures instead of recalculating a smaller browser-only target.`,
337
- ).toMatch(
338
- scenario.workloadFixture
339
- ? getScenarioWorkloadFixturePattern(scenario.id)
340
- : getScenarioStressFixturePattern(scenario.id),
341
- );
342
- expect(
343
- browserTestSource,
344
- `${scenario.id} declares a loadProfile and must keep budget assertions tied to app-performance.ts.`,
345
- ).toMatch(getScenarioBudgetAssertionPattern(scenario.id));
346
- }
347
-
348
- if (scenario.interaction === "control-change") {
349
- expect(
350
- browserTestSource,
351
- `${scenario.id} must change the declared control through the browser UI.`,
352
- ).toMatch(/\.fill\s*\(|\.pressSequentially\s*\(|\.selectOption\s*\(|getByRole\s*\([\s\S]*?\.click\s*\(/);
353
- }
354
-
355
- if (scenario.uiSelector) {
356
- expect(
357
- browserTestSource,
358
- `${scenario.id} must interact with the declared UI selector "${scenario.uiSelector}".`,
359
- ).toContain(scenario.uiSelector);
360
- }
361
-
362
- expect(
363
- browserTestSource,
364
- `${scenario.id} must measure browser responsiveness with measureToolcraftInteraction.`,
365
- ).toMatch(
366
- /measureToolcraftInteraction\s*\(|measureToolcraftAnimationFrames\s*\(|expectToolcraftCanvasViewportStable\s*\(/,
367
- );
368
-
369
- if (scenario.interaction === "viewport-stability") {
370
- expect(
371
- browserTestSource,
372
- `${scenario.id} must use expectToolcraftCanvasViewportStable to catch canvas zoom/offset jumps.`,
373
- ).toMatch(/expectToolcraftCanvasViewportStable\s*\(/);
374
-
375
- if (scenario.target === "timeline.keyframes") {
376
- expect(
377
- browserTestSource,
378
- `${scenario.id} must exercise toolbar zoom or radar before checking keyframe viewport stability.`,
379
- ).toMatch(/Zoom in|Zoom out|Center canvas|canvas\.zoom|canvas\.center/);
380
- expect(
381
- browserTestSource,
382
- `${scenario.id} must open the expanded keyframe editor while checking viewport stability.`,
383
- ).toMatch(/Expand timeline panel|timeline\.setExpanded|timeline-expanded/);
384
- expect(
385
- browserTestSource,
386
- `${scenario.id} must create or update at least one keyframe while checking viewport stability.`,
387
- ).toMatch(/Add .* keyframe|Disable .* keyframes|timeline-keyframe-row/);
388
- expect(
389
- browserTestSource,
390
- `${scenario.id} must scrub or play the timeline while checking viewport stability.`,
391
- ).toMatch(/Playback position|Play playback|Pause playback|timeline\.setCurrentTime/);
392
- }
393
-
394
- if (scenario.target === "layers.interactions") {
395
- expect(
396
- browserTestSource,
397
- `${scenario.id} must exercise toolbar zoom or radar before checking layer viewport stability.`,
398
- ).toMatch(/Zoom in|Zoom out|Center canvas|canvas\.zoom|canvas\.center/);
399
- expect(
400
- hasRealLayerRowInteraction(browserTestSource),
401
- `${scenario.id} must select real LayersPanel rows while checking viewport stability.`,
402
- ).toBe(true);
403
- expect(
404
- hasRealLayerVisibilityInteraction(browserTestSource),
405
- `${scenario.id} must toggle real layer visibility while checking viewport stability.`,
406
- ).toBe(true);
407
- expect(
408
- hasRealLayerDragInteraction(browserTestSource),
409
- `${scenario.id} must drag real layer rows for reorder or grouping while checking viewport stability.`,
410
- ).toBe(true);
411
- expect(
412
- browserTestSource,
413
- `${scenario.id} must assert selected-layer or product output after layer interactions.`,
414
- ).toMatch(/selected layer|selectedLayer|product-output|rendered-pixels|canvas|export|output/i);
415
- }
416
- }
417
-
418
- if (scenario.interaction === "animation-frame") {
419
- expect(
420
- browserTestSource,
421
- `${scenario.id} must use measureToolcraftAnimationFrames so animated renderers are sampled for at least 120 frames.`,
422
- ).toMatch(/measureToolcraftAnimationFrames\s*\(/);
423
- expect(
424
- browserTestSource,
425
- `${scenario.id} must not satisfy animation coverage with a short waitForToolcraftAnimationFrames probe.`,
426
- ).not.toMatch(/waitForToolcraftAnimationFrames\s*\(\s*page\s*,\s*(?:[1-9]|[1-9]\d|1[01]\d)\s*\)/);
427
- }
428
-
429
- if (scenario.interaction === "animation-viewport-drag") {
430
- expect(
431
- browserTestSource,
432
- `${scenario.id} must measure a real canvas viewport drag while the renderer is animated.`,
433
- ).toMatch(/measureToolcraftInteraction\s*\([\s\S]*dragToolcraftCanvasViewport\s*\(/);
434
- expect(
435
- browserTestSource,
436
- `${scenario.id} must not fake animated viewport coverage with toolbar zoom or direct canvas commands.`,
437
- ).not.toMatch(/canvas\.setOffset|canvas\.panBy|canvas\.zoom|Zoom in|Zoom out|Center canvas/);
438
- }
439
-
440
- if (scenario.interaction === "timeline-playback") {
441
- expect(
442
- browserTestSource,
443
- `${scenario.id} must use the real timeline playback UI while measuring frames.`,
444
- ).toMatch(/measureToolcraftInteraction\s*\([\s\S]*(Play playback|Pause playback|timeline-playback|data-slot=["']timeline-playback)/);
445
- expect(
446
- browserTestSource,
447
- `${scenario.id} must not satisfy timeline playback performance by dispatching timeline state directly.`,
448
- ).not.toMatch(/timeline\.setCurrentTime|timeline\.setPlaying|timeline\.play|timeline\.pause/);
449
- }
450
-
451
- if (scenario.interaction === "timeline-scrub") {
452
- expect(
453
- browserTestSource,
454
- `${scenario.id} must scrub the real timeline UI while measuring interaction responsiveness.`,
455
- ).toMatch(/measureToolcraftInteraction\s*\([\s\S]*(Playback position|timeline-playback-handle|data-slot=["']timeline-playback-handle|page\.mouse\.(?:down|move|up))/);
456
- expect(
457
- browserTestSource,
458
- `${scenario.id} must not satisfy timeline scrub performance by setting timeline time directly.`,
459
- ).not.toMatch(/timeline\.setCurrentTime|canvas\.setCurrentTime/);
460
- }
461
-
462
- if (scenario.interaction === "mask-drag") {
463
- expect(
464
- browserTestSource,
465
- `${scenario.id} must measure a real canvas handle/mask drag.`,
466
- ).toMatch(/measureToolcraftInteraction\s*\([\s\S]*dragCanvasHandle\s*\(/);
467
- expect(
468
- browserTestSource,
469
- `${scenario.id} must not fake mask drag coverage with direct runtime state mutation.`,
470
- ).not.toMatch(/mask\.(?:set|update|move)|canvas\.setOffset|canvas\.panBy/);
471
- }
472
-
473
- if (scenario.interaction === "viewport-zoom-stress") {
474
- expect(
475
- browserTestSource,
476
- `${scenario.id} must measure real toolbar zoom while sampling frame gaps.`,
477
- ).toMatch(/measureToolcraftInteraction\s*\([\s\S]*zoomToolcraftCanvasViewport\s*\(/);
478
- expect(
479
- browserTestSource,
480
- `${scenario.id} must not fake zoom stress with direct runtime canvas commands.`,
481
- ).not.toMatch(/canvas\.setZoom|canvas\.zoom|canvas\.setScale|canvas\.setOffset|canvas\.panBy/);
482
- }
483
-
484
- expect(
485
- browserTestSource,
486
- `${scenario.id} must assert product or UI output after the measured interaction so a no-op control cannot pass.`,
487
- ).toMatch(/await\s+expect\s*\(|expect\s*\(/);
488
-
489
- expect(
490
- browserTestSource,
491
- `${scenario.id} must assert its typed budget through expectToolcraftScenarioPerformanceBudget(..., appPerformance, "${scenario.id}") so browser thresholds cannot drift from app-performance.ts.`,
492
- ).toMatch(getScenarioBudgetAssertionPattern(scenario.id));
493
- }
494
- });
495
4
 
496
5
  test("browser perf: declared renderer layer selectors are present", async ({ page }) => {
497
6
  if (!starterPerformance.usesCustomRenderer) {
@@ -0,0 +1,97 @@
1
+ import { expect } from "@playwright/test";
2
+
3
+ import type { ToolcraftBrowserAcceptanceOutcomeEvidenceType } from "../src/app/test-evidence/browser-runtime-contract";
4
+ import { attachToolcraftBrowserRuntimeEvidence } from "./browser-runtime-evidence";
5
+ import {
6
+ getToolcraftBrowserActionTarget,
7
+ isToolcraftBrowserAction,
8
+ runToolcraftBrowserValueAction,
9
+ type ToolcraftBrowserAction,
10
+ } from "./browser-proof-session";
11
+ import {
12
+ assertToolcraftProducedArtifact,
13
+ type ToolcraftExportArtifactInspectionResult,
14
+ validateToolcraftExportArtifactInspection,
15
+ } from "./export-artifact-helpers";
16
+ import { expectToolcraftPersistentOutcomeAfterAction } from "./stable-outcome-helpers";
17
+
18
+ export async function expectToolcraftAcceptanceOutcome<T>(
19
+ observeOutcome: () => Promise<T>,
20
+ action: () => Promise<void>,
21
+ {
22
+ evidenceType,
23
+ requirementId,
24
+ stabilityIntervalMs,
25
+ stabilitySamples,
26
+ timeoutMs = 5_000,
27
+ }: {
28
+ evidenceType: ToolcraftBrowserAcceptanceOutcomeEvidenceType;
29
+ requirementId: string;
30
+ stabilityIntervalMs?: number;
31
+ stabilitySamples?: number;
32
+ timeoutMs?: number;
33
+ },
34
+ ): Promise<T> {
35
+ if (evidenceType !== "command-side-effect") {
36
+ throw new Error(
37
+ `Generic acceptance outcomes cannot emit specialized evidence "${String(evidenceType)}". Use the protected semantic recipe for that behavior.`,
38
+ );
39
+ }
40
+ const result = await expectToolcraftPersistentOutcomeAfterAction(
41
+ observeOutcome,
42
+ action,
43
+ {
44
+ message: `Acceptance outcome "${requirementId}" should change after the tested action.`,
45
+ stabilityIntervalMs,
46
+ stabilitySamples,
47
+ timeoutMs,
48
+ },
49
+ );
50
+ await attachToolcraftBrowserRuntimeEvidence({ evidenceType, requirementId });
51
+ return result;
52
+ }
53
+
54
+ export async function expectToolcraftReferenceParity<T>(
55
+ observeActual: () => Promise<T>,
56
+ expected: T,
57
+ { requirementId }: { requirementId: string },
58
+ ): Promise<T> {
59
+ const actual = await observeActual();
60
+ expect(actual, `Reference outcome "${requirementId}" should match the inspected baseline.`).toEqual(
61
+ expected,
62
+ );
63
+ await attachToolcraftBrowserRuntimeEvidence({
64
+ evidenceType: "reference-parity",
65
+ requirementId,
66
+ });
67
+ return actual;
68
+ }
69
+
70
+ export async function expectToolcraftExportedArtifact<
71
+ TArtifact,
72
+ TObservation extends ToolcraftExportArtifactInspectionResult,
73
+ >(
74
+ produceArtifact:
75
+ | (() => Promise<TArtifact>)
76
+ | ToolcraftBrowserAction<"interaction", TArtifact>,
77
+ verifyArtifact: (
78
+ artifact: TArtifact,
79
+ ) => Promise<TObservation> | TObservation,
80
+ { requirementId }: { requirementId: string },
81
+ ): Promise<TArtifact> {
82
+ const target = isToolcraftBrowserAction(produceArtifact)
83
+ ? getToolcraftBrowserActionTarget(produceArtifact)
84
+ : undefined;
85
+ const artifact = isToolcraftBrowserAction(produceArtifact)
86
+ ? await runToolcraftBrowserValueAction(produceArtifact)
87
+ : await produceArtifact();
88
+ assertToolcraftProducedArtifact(artifact, requirementId);
89
+ const observation = await verifyArtifact(artifact);
90
+ validateToolcraftExportArtifactInspection(observation, requirementId);
91
+ await attachToolcraftBrowserRuntimeEvidence({
92
+ evidenceType: "exported-artifact",
93
+ requirementId,
94
+ target,
95
+ });
96
+ return artifact;
97
+ }
@@ -0,0 +1,74 @@
1
+ import { expect } from "@playwright/test";
2
+
3
+ import {
4
+ expectToolcraftPersistentExpectedOutcome,
5
+ expectToolcraftStableOutcomeBaseline,
6
+ snapshotToolcraftOutcome,
7
+ type ToolcraftStableOutcomeOptions,
8
+ } from "./stable-outcome-helpers";
9
+ import {
10
+ assertToolcraftBrowserProofSession,
11
+ readToolcraftBrowserObservation,
12
+ runToolcraftBrowserAction,
13
+ type ToolcraftBrowserAction,
14
+ type ToolcraftBrowserObservation,
15
+ } from "./browser-proof-session";
16
+
17
+ export type ToolcraftExpectedTransitionResult<T> = {
18
+ after: T;
19
+ before: T;
20
+ };
21
+
22
+ export type ToolcraftSemanticEvidenceOptions = {
23
+ requirementId: string;
24
+ stabilityIntervalMs?: number;
25
+ stabilitySamples?: number;
26
+ timeoutMs?: number;
27
+ };
28
+
29
+ export function createToolcraftSemanticTransitionOptions(
30
+ message: string,
31
+ options: ToolcraftSemanticEvidenceOptions,
32
+ ): ToolcraftStableOutcomeOptions {
33
+ return {
34
+ message,
35
+ ...(options.stabilityIntervalMs === undefined
36
+ ? {}
37
+ : { stabilityIntervalMs: options.stabilityIntervalMs }),
38
+ ...(options.stabilitySamples === undefined
39
+ ? {}
40
+ : { stabilitySamples: options.stabilitySamples }),
41
+ ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
42
+ };
43
+ }
44
+
45
+ export async function expectToolcraftExpectedOutcomeAfterAction<T>(
46
+ observeOutcome: ToolcraftBrowserObservation<T>,
47
+ action: ToolcraftBrowserAction,
48
+ expected: T,
49
+ options: ToolcraftStableOutcomeOptions,
50
+ ): Promise<ToolcraftExpectedTransitionResult<T>> {
51
+ assertToolcraftBrowserProofSession(observeOutcome, action);
52
+ const observe = () => readToolcraftBrowserObservation(observeOutcome);
53
+ const before = snapshotToolcraftOutcome(
54
+ await observe(),
55
+ options.message,
56
+ );
57
+ const expectedSnapshot = snapshotToolcraftOutcome(expected, options.message);
58
+
59
+ expect(
60
+ before,
61
+ `${options.message} The expected state must differ from the pre-action state so the tested action proves a transition.`,
62
+ ).not.toEqual(expectedSnapshot);
63
+
64
+ await expectToolcraftStableOutcomeBaseline(observe, before, options);
65
+
66
+ await runToolcraftBrowserAction(action);
67
+ const after = await expectToolcraftPersistentExpectedOutcome(
68
+ observe,
69
+ expectedSnapshot,
70
+ options,
71
+ );
72
+
73
+ return { after, before };
74
+ }