@pixel-point/toolcraft 0.0.13 → 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 (582) 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 +241 -294
  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 +45 -29
  276. package/templates/starter/LICENSE.md +18 -95
  277. package/templates/starter/NOTICE.md +3 -3
  278. package/templates/starter/docs/toolcraft/README.md +19 -4
  279. package/templates/starter/docs/toolcraft/acceptance-testing.md +38 -8
  280. package/templates/starter/docs/toolcraft/assembly-workflow.md +46 -185
  281. package/templates/starter/docs/toolcraft/component-rules.md +18 -190
  282. package/templates/starter/docs/toolcraft/core/control-selection.md +93 -0
  283. package/templates/starter/docs/toolcraft/core/layout.md +105 -0
  284. package/templates/starter/docs/toolcraft/core/media-upload.md +85 -0
  285. package/templates/starter/docs/toolcraft/core/performance.md +86 -0
  286. package/templates/starter/docs/toolcraft/core/reference-study.md +115 -0
  287. package/templates/starter/docs/toolcraft/core/runtime-boundary.md +60 -0
  288. package/templates/starter/docs/toolcraft/core/setup-export.md +86 -0
  289. package/templates/starter/docs/toolcraft/core/timeline-animation.md +68 -0
  290. package/templates/starter/docs/toolcraft/custom-controls.md +10 -1
  291. package/templates/starter/docs/toolcraft/decision-contract.md +26 -22
  292. package/templates/starter/docs/toolcraft/performance.md +44 -16
  293. package/templates/starter/docs/toolcraft/renderer-technique.md +2 -0
  294. package/templates/starter/docs/toolcraft/schema-reference.md +127 -366
  295. package/templates/starter/docs/toolcraft/workflow.md +26 -16
  296. package/templates/starter/e2e/app-browser-acceptance-evidence.spec.ts +111 -0
  297. package/templates/starter/e2e/app-browser-control-coverage.spec.ts +118 -0
  298. package/templates/starter/e2e/app-browser-performance-evidence.spec.ts +217 -0
  299. package/templates/starter/e2e/app-browser-performance-probe.spec.ts +322 -0
  300. package/templates/starter/e2e/app-browser-proof-session.spec.ts +196 -0
  301. package/templates/starter/e2e/app-browser-runtime-evidence.spec.ts +9 -0
  302. package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +240 -0
  303. package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +180 -0
  304. package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +310 -0
  305. package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +432 -0
  306. package/templates/starter/e2e/app-browser-shell.spec.ts +171 -0
  307. package/templates/starter/e2e/app-browser-timeline-layers-reference.spec.ts +70 -0
  308. package/templates/starter/e2e/app-performance.spec.ts +0 -491
  309. package/templates/starter/e2e/browser-acceptance-outcome-helpers.ts +97 -0
  310. package/templates/starter/e2e/browser-acceptance-transition-helpers.ts +74 -0
  311. package/templates/starter/e2e/browser-conditional-output-evidence-helpers.ts +230 -0
  312. package/templates/starter/e2e/browser-control-target-helpers.ts +109 -0
  313. package/templates/starter/e2e/browser-layer-evidence-helpers.ts +229 -0
  314. package/templates/starter/e2e/browser-proof-session.ts +392 -0
  315. package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +136 -0
  316. package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +290 -0
  317. package/templates/starter/e2e/browser-runtime-evidence.ts +27 -0
  318. package/templates/starter/e2e/browser-state-evidence-helpers.ts +205 -0
  319. package/templates/starter/e2e/browser-timeline-evidence-helpers.ts +319 -0
  320. package/templates/starter/e2e/canvas-handle-helpers.ts +86 -4
  321. package/templates/starter/e2e/export-artifact-helpers.ts +132 -0
  322. package/templates/starter/e2e/performance-budget-helpers.ts +159 -0
  323. package/templates/starter/e2e/performance-canvas-helpers.ts +123 -0
  324. package/templates/starter/e2e/performance-control-helpers.ts +3 -0
  325. package/templates/starter/e2e/performance-control-layout-helpers.ts +161 -0
  326. package/templates/starter/e2e/performance-fixture-helpers.ts +217 -0
  327. package/templates/starter/e2e/performance-frame-probe.ts +247 -0
  328. package/templates/starter/e2e/performance-helpers.ts +6 -854
  329. package/templates/starter/e2e/performance-interaction-measurement.ts +251 -0
  330. package/templates/starter/e2e/performance-measurement-evidence.ts +72 -0
  331. package/templates/starter/e2e/performance-output-action-helpers.spec.ts +43 -0
  332. package/templates/starter/e2e/performance-output-action-helpers.ts +109 -0
  333. package/templates/starter/e2e/performance-probe-helpers.ts +12 -0
  334. package/templates/starter/e2e/performance-render-scale-helpers.ts +55 -0
  335. package/templates/starter/e2e/performance-slider-helpers.ts +271 -0
  336. package/templates/starter/e2e/product-observable-helpers.ts +72 -17
  337. package/templates/starter/e2e/stable-outcome-helpers.ts +208 -0
  338. package/templates/starter/package.json +10 -5
  339. package/templates/starter/playwright.config.ts +5 -2
  340. package/templates/starter/scripts/check-ai-skills.mjs +14 -8
  341. package/templates/starter/scripts/check-ai-skills.test.mjs +64 -0
  342. package/templates/starter/scripts/check-toolcraft-code-health.mjs +108 -0
  343. package/templates/starter/scripts/check-toolcraft-code-health.test.mjs +213 -0
  344. package/templates/starter/scripts/check-toolcraft-docs.mjs +70 -35
  345. package/templates/starter/scripts/check-toolcraft-integrity.mjs +141 -144
  346. package/templates/starter/scripts/run-browser-performance.mjs +118 -0
  347. package/templates/starter/scripts/run-browser-performance.test.mjs +53 -0
  348. package/templates/starter/scripts/toolcraft-code-health-core.mjs +297 -0
  349. package/templates/starter/scripts/toolcraft-contract-doc-integrity.mjs +77 -0
  350. package/templates/starter/scripts/toolcraft-contract-doc-integrity.test.mjs +81 -0
  351. package/templates/starter/scripts/toolcraft-contract-manifest.json +113 -0
  352. package/templates/starter/scripts/toolcraft-contract-manifest.mjs +128 -0
  353. package/templates/starter/scripts/toolcraft-contract-manifest.test.mjs +72 -0
  354. package/templates/starter/scripts/toolcraft-integrity-manifest.mjs +172 -0
  355. package/templates/starter/scripts/toolcraft-integrity-policy.mjs +60 -0
  356. package/templates/starter/scripts/toolcraft-product-boundary-ast-utils.mjs +23 -0
  357. package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +264 -0
  358. package/templates/starter/scripts/toolcraft-product-boundary-test-fixtures.mjs +16 -0
  359. package/templates/starter/scripts/toolcraft-product-boundary.mjs +243 -0
  360. package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +289 -0
  361. package/templates/starter/scripts/toolcraft-product-dependency-graph.mjs +176 -0
  362. package/templates/starter/scripts/toolcraft-product-dependency-graph.test.mjs +196 -0
  363. package/templates/starter/scripts/toolcraft-product-dependency-resolution.mjs +279 -0
  364. package/templates/starter/scripts/toolcraft-product-evidence-boundary-ast.mjs +91 -0
  365. package/templates/starter/scripts/toolcraft-product-evidence-boundary.test.mjs +138 -0
  366. package/templates/starter/scripts/toolcraft-product-style-boundary.mjs +219 -0
  367. package/templates/starter/scripts/toolcraft-source-inventory.d.mts +46 -0
  368. package/templates/starter/scripts/toolcraft-source-inventory.mjs +187 -0
  369. package/templates/starter/scripts/toolcraft-source-inventory.test.mjs +132 -0
  370. package/templates/starter/scripts/toolcraft-source-ownership.mjs +167 -0
  371. package/templates/starter/scripts/toolcraft-source-ownership.test.mjs +113 -0
  372. package/templates/starter/scripts/toolcraft-static-string.mjs +104 -0
  373. package/templates/starter/scripts/toolcraft-verification-inventory.mjs +123 -0
  374. package/templates/starter/scripts/toolcraft-verification-receipt.d.mts +19 -0
  375. package/templates/starter/scripts/toolcraft-verification-receipt.mjs +284 -0
  376. package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +282 -0
  377. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.d.mts +32 -0
  378. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.mjs +88 -0
  379. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.test.mjs +87 -0
  380. package/templates/starter/scripts/toolcraft-vitest-runtime-evidence-reporter.mjs +109 -0
  381. package/templates/starter/scripts/toolcraft-vitest-runtime-evidence-reporter.test.mjs +111 -0
  382. package/templates/starter/scripts/toolcraft-workflow-routes.mjs +314 -0
  383. package/templates/starter/scripts/toolcraft-workflow-routes.test.mjs +204 -0
  384. package/templates/starter/src/app/acceptance/actions.ts +30 -0
  385. package/templates/starter/src/app/acceptance/animation-intent.ts +184 -0
  386. package/templates/starter/src/app/acceptance/canvas-handle-acceptance.ts +70 -0
  387. package/templates/starter/src/app/acceptance/color-bank-labels.ts +164 -0
  388. package/templates/starter/src/app/acceptance/conditions.ts +80 -0
  389. package/templates/starter/src/app/acceptance/control-acceptance-context.ts +70 -0
  390. package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +271 -0
  391. package/templates/starter/src/app/acceptance/control-acceptance-kind-rules.ts +149 -0
  392. package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +189 -0
  393. package/templates/starter/src/app/acceptance/control-acceptance.ts +70 -0
  394. package/templates/starter/src/app/acceptance/control-component-rules.ts +277 -0
  395. package/templates/starter/src/app/acceptance/control-labels.ts +223 -0
  396. package/templates/starter/src/app/acceptance/control-layout-dependency-rules.ts +107 -0
  397. package/templates/starter/src/app/acceptance/control-layout-entity-rules.ts +104 -0
  398. package/templates/starter/src/app/acceptance/control-layout-model.ts +159 -0
  399. package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +164 -0
  400. package/templates/starter/src/app/acceptance/control-layout.ts +45 -0
  401. package/templates/starter/src/app/acceptance/control-order.ts +123 -0
  402. package/templates/starter/src/app/acceptance/control-parts.ts +47 -0
  403. package/templates/starter/src/app/acceptance/control-section-inventory.ts +183 -0
  404. package/templates/starter/src/app/acceptance/controls.ts +27 -0
  405. package/templates/starter/src/app/acceptance/coverage.ts +81 -0
  406. package/templates/starter/src/app/acceptance/custom-controls.ts +140 -0
  407. package/templates/starter/src/app/acceptance/inline-layout.ts +192 -0
  408. package/templates/starter/src/app/acceptance/media-upload.ts +55 -0
  409. package/templates/starter/src/app/acceptance/output-background-rules.ts +135 -0
  410. package/templates/starter/src/app/acceptance/output-export-actions.test.ts +76 -0
  411. package/templates/starter/src/app/acceptance/output-export-actions.ts +34 -0
  412. package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +46 -0
  413. package/templates/starter/src/app/acceptance/output-export-model.ts +146 -0
  414. package/templates/starter/src/app/acceptance/output-export.ts +45 -0
  415. package/templates/starter/src/app/acceptance/output-image-export-rules.ts +87 -0
  416. package/templates/starter/src/app/acceptance/reference-runtime-coverage.ts +96 -0
  417. package/templates/starter/src/app/acceptance/reference-runtime-feature-inventory.ts +171 -0
  418. package/templates/starter/src/app/acceptance/reference-runtime-study.ts +73 -0
  419. package/templates/starter/src/app/acceptance/reference-runtime-timeline.ts +291 -0
  420. package/templates/starter/src/app/acceptance/reference-runtime.ts +99 -0
  421. package/templates/starter/src/app/acceptance/runtime-coverage.ts +290 -0
  422. package/templates/starter/src/app/acceptance/runtime-setup.ts +117 -0
  423. package/templates/starter/src/app/acceptance/section-title-rules.ts +8 -0
  424. package/templates/starter/src/app/acceptance/sections.ts +6 -0
  425. package/templates/starter/src/app/acceptance/semantic.ts +63 -0
  426. package/templates/starter/src/app/acceptance/timeline-loop.ts +21 -0
  427. package/templates/starter/src/app/acceptance/types.ts +363 -0
  428. package/templates/starter/src/app/acceptance/validate-coverage.ts +217 -0
  429. package/templates/starter/src/app/acceptance/validation-pipeline.test.ts +56 -0
  430. package/templates/starter/src/app/acceptance/validation-pipeline.ts +60 -0
  431. package/templates/starter/src/app/acceptance/video-reference-study.ts +217 -0
  432. package/templates/starter/src/app/starter-acceptance-data.ts +21 -0
  433. package/templates/starter/src/app/starter-acceptance.animation-intent.test.ts +383 -0
  434. package/templates/starter/src/app/starter-acceptance.background-export.test.ts +349 -0
  435. package/templates/starter/src/app/starter-acceptance.base-coverage.test.ts +47 -0
  436. package/templates/starter/src/app/starter-acceptance.canvas-handles.test.ts +71 -0
  437. package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +199 -0
  438. package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +244 -0
  439. package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +63 -0
  440. package/templates/starter/src/app/starter-acceptance.control-label-context.test.ts +172 -0
  441. package/templates/starter/src/app/starter-acceptance.control-labels.test.ts +387 -0
  442. package/templates/starter/src/app/starter-acceptance.control-naming-rules.test.ts +215 -0
  443. package/templates/starter/src/app/starter-acceptance.control-order.test.ts +274 -0
  444. package/templates/starter/src/app/starter-acceptance.control-state.test.ts +275 -0
  445. package/templates/starter/src/app/starter-acceptance.curves-rules.test.ts +184 -0
  446. package/templates/starter/src/app/starter-acceptance.custom-control-collections.test.ts +200 -0
  447. package/templates/starter/src/app/starter-acceptance.custom-control-coverage.test.ts +111 -0
  448. package/templates/starter/src/app/starter-acceptance.custom-control-fit-check.test.ts +135 -0
  449. package/templates/starter/src/app/starter-acceptance.custom-control-valid.test.ts +74 -0
  450. package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +107 -0
  451. package/templates/starter/src/app/starter-acceptance.framework-boundary.test.ts +327 -0
  452. package/templates/starter/src/app/starter-acceptance.image-video-export-settings.test.ts +328 -0
  453. package/templates/starter/src/app/starter-acceptance.keyframes.test.ts +242 -0
  454. package/templates/starter/src/app/starter-acceptance.layers.test.ts +203 -0
  455. package/templates/starter/src/app/starter-acceptance.media-upload.fixtures.ts +110 -0
  456. package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +153 -0
  457. package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +97 -0
  458. package/templates/starter/src/app/starter-acceptance.persistence-coverage.test.ts +134 -0
  459. package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +202 -0
  460. package/templates/starter/src/app/starter-acceptance.product-readiness-rules.test.ts +14 -0
  461. package/templates/starter/src/app/starter-acceptance.product-readiness-test-utils.ts +25 -0
  462. package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +50 -0
  463. package/templates/starter/src/app/starter-acceptance.product-worklog.test.ts +27 -0
  464. package/templates/starter/src/app/starter-acceptance.range-slider-rules.test.ts +147 -0
  465. package/templates/starter/src/app/starter-acceptance.reference-custom-timeline.test.ts +197 -0
  466. package/templates/starter/src/app/starter-acceptance.reference-foundation.test.ts +304 -0
  467. package/templates/starter/src/app/starter-acceptance.reference-test-utils.ts +102 -0
  468. package/templates/starter/src/app/starter-acceptance.reference-timeline.test.ts +267 -0
  469. package/templates/starter/src/app/starter-acceptance.schema-test-utils.ts +116 -0
  470. package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +373 -0
  471. package/templates/starter/src/app/starter-acceptance.section-dependencies.test.ts +260 -0
  472. package/templates/starter/src/app/starter-acceptance.section-titles.test.ts +180 -0
  473. package/templates/starter/src/app/starter-acceptance.setup-readiness.test.ts +205 -0
  474. package/templates/starter/src/app/starter-acceptance.slider-rules.test.ts +470 -0
  475. package/templates/starter/src/app/starter-acceptance.slider-unit-rules.test.ts +61 -0
  476. package/templates/starter/src/app/starter-acceptance.source-test-utils.ts +43 -0
  477. package/templates/starter/src/app/starter-acceptance.test-utils.ts +21 -0
  478. package/templates/starter/src/app/starter-acceptance.text-control-kind.test.ts +89 -0
  479. package/templates/starter/src/app/starter-acceptance.timeline-playback.test.ts +264 -0
  480. package/templates/starter/src/app/starter-acceptance.timeline-test-utils.ts +56 -0
  481. package/templates/starter/src/app/starter-acceptance.toggle-pair-layout.test.ts +200 -0
  482. package/templates/starter/src/app/starter-acceptance.toggle-parameter-layout.test.ts +277 -0
  483. package/templates/starter/src/app/starter-acceptance.ts +151 -4576
  484. package/templates/starter/src/app/starter-acceptance.video-export-test-utils.ts +37 -0
  485. package/templates/starter/src/app/starter-acceptance.video-reference-study.test.ts +262 -0
  486. package/templates/starter/src/app/starter-acceptance.worklog-test-utils.ts +428 -0
  487. package/templates/starter/src/app/starter-acceptance.worklog.test.ts +283 -0
  488. package/templates/starter/src/app/starter-automated-runtime-evidence.test.ts +34 -0
  489. package/templates/starter/src/app/starter-composition.tsx +7 -0
  490. package/templates/starter/src/app/starter-performance-test-utils.ts +275 -0
  491. package/templates/starter/src/app/starter-performance.budgets.test.ts +374 -0
  492. package/templates/starter/src/app/starter-performance.gates.test.ts +128 -0
  493. package/templates/starter/src/app/starter-performance.renderer-source.test.ts +136 -0
  494. package/templates/starter/src/app/starter-performance.renderer-technique.test.ts +291 -0
  495. package/templates/starter/src/app/starter-performance.scenarios.test.ts +355 -0
  496. package/templates/starter/src/app/test-evidence/browser-runtime-contract.test.ts +253 -0
  497. package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +243 -0
  498. package/templates/starter/src/routes/index.tsx +11 -2
  499. package/templates/starter/vite.config.ts +8 -0
  500. package/templates/ui/components/controls/color/color-control-types.ts +38 -0
  501. package/templates/ui/components/controls/color/color-control.tsx +19 -437
  502. package/templates/ui/components/controls/color/color-footer.tsx +272 -0
  503. package/templates/ui/components/controls/color/color-model-slider.tsx +271 -0
  504. package/templates/ui/components/controls/color/color-opacity-input.tsx +94 -0
  505. package/templates/ui/components/controls/color/color-surface.tsx +194 -0
  506. package/templates/ui/components/controls/color/color-value-control.tsx +159 -0
  507. package/templates/ui/components/controls/color/color-value-utils.ts +170 -0
  508. package/templates/ui/components/controls/color/index.ts +10 -3
  509. package/templates/ui/components/controls/color/palette-control-controller.ts +407 -0
  510. package/templates/ui/components/controls/color/palette-control-layout.ts +14 -0
  511. package/templates/ui/components/controls/color/palette-control-types.ts +50 -0
  512. package/templates/ui/components/controls/color/palette-control-view.tsx +174 -0
  513. package/templates/ui/components/controls/color/palette-control.tsx +6 -544
  514. package/templates/ui/components/controls/color/style-guide-color-picker-color-utils.ts +39 -0
  515. package/templates/ui/components/controls/color/style-guide-color-picker-controller.ts +370 -0
  516. package/templates/ui/components/controls/color/style-guide-color-picker-hue-handlers.ts +66 -0
  517. package/templates/ui/components/controls/color/style-guide-color-picker-interaction-state.ts +49 -0
  518. package/templates/ui/components/controls/color/style-guide-color-picker-interactions.ts +2 -2
  519. package/templates/ui/components/controls/color/style-guide-color-picker-model.ts +125 -0
  520. package/templates/ui/components/controls/color/style-guide-color-picker-parts.tsx +10 -707
  521. package/templates/ui/components/controls/color/style-guide-color-picker-surface-drag.ts +93 -0
  522. package/templates/ui/components/controls/color/style-guide-color-picker-surface-geometry.ts +114 -0
  523. package/templates/ui/components/controls/color/style-guide-color-picker-surface-preview.ts +45 -0
  524. package/templates/ui/components/controls/color/style-guide-color-picker-types.ts +84 -0
  525. package/templates/ui/components/controls/color/style-guide-color-picker-view.tsx +69 -0
  526. package/templates/ui/components/controls/color/style-guide-color-picker.tsx +6 -495
  527. package/templates/ui/components/controls/curves/curves-control.tsx +4 -3
  528. package/templates/ui/components/controls/file-drop/file-drop-control.tsx +39 -515
  529. package/templates/ui/components/controls/file-drop/file-drop-empty-state.tsx +35 -0
  530. package/templates/ui/components/controls/file-drop/file-drop-file-list.tsx +160 -0
  531. package/templates/ui/components/controls/file-drop/file-drop-image-grid.tsx +175 -0
  532. package/templates/ui/components/controls/file-drop/file-drop-model.tsx +170 -0
  533. package/templates/ui/components/controls/file-drop/file-drop-single-preview.tsx +63 -0
  534. package/templates/ui/components/controls/file-drop/file-drop-types.ts +48 -0
  535. package/templates/ui/components/controls/file-drop/index.ts +2 -2
  536. package/templates/ui/components/controls/font-picker/font-picker-control.tsx +133 -906
  537. package/templates/ui/components/controls/font-picker/font-picker-footer.tsx +116 -0
  538. package/templates/ui/components/controls/font-picker/font-picker-list.tsx +194 -0
  539. package/templates/ui/components/controls/font-picker/font-picker-popover-content.tsx +191 -0
  540. package/templates/ui/components/controls/font-picker/font-picker-value.ts +222 -0
  541. package/templates/ui/components/controls/font-picker/index.ts +4 -1
  542. package/templates/ui/components/controls/font-picker/use-font-picker-preview-pipeline.ts +163 -0
  543. package/templates/ui/components/controls/font-picker/use-font-picker-virtual-list.ts +293 -0
  544. package/templates/ui/components/controls/gradient/gradient-control-utils.ts +2 -25
  545. package/templates/ui/components/controls/gradient/gradient-control.tsx +4 -464
  546. package/templates/ui/components/controls/gradient/gradient-stops-controller.ts +332 -0
  547. package/templates/ui/components/controls/gradient/gradient-stops-track.tsx +159 -0
  548. package/templates/ui/components/controls/vector/vector-control-types.ts +26 -0
  549. package/templates/ui/components/controls/vector/vector-control.tsx +10 -486
  550. package/templates/ui/components/controls/vector/vector-pad-field.tsx +211 -0
  551. package/templates/ui/components/controls/vector/vector-pad-geometry.ts +61 -0
  552. package/templates/ui/components/controls/vector/vector-pad-parts.tsx +72 -0
  553. package/templates/ui/components/controls/vector/vector-pad-variants.ts +20 -0
  554. package/templates/ui/components/controls/vector/vector-size-field.tsx +104 -0
  555. package/templates/ui/components/controls/vector/vector-value.ts +46 -0
  556. package/templates/ui/components/primitives/slider/slider-discrete-state.ts +181 -0
  557. package/templates/ui/components/primitives/slider/slider-marker-policy.ts +52 -0
  558. package/templates/ui/components/primitives/slider/slider-pointer-dragging.ts +87 -0
  559. package/templates/ui/components/primitives/slider/slider-runtime.ts +109 -0
  560. package/templates/ui/components/primitives/slider/slider-types.ts +21 -0
  561. package/templates/ui/components/primitives/slider/slider.tsx +2 -403
  562. package/templates/runtime/react/canvas-shell.test.tsx +0 -554
  563. package/templates/runtime/react/canvas-shell.tsx +0 -585
  564. package/templates/runtime/react/controls-panel.test.tsx +0 -5446
  565. package/templates/runtime/react/controls-panel.tsx +0 -3220
  566. package/templates/runtime/react/layers-panel.test.tsx +0 -487
  567. package/templates/runtime/react/layers-panel.tsx +0 -1348
  568. package/templates/runtime/react/timeline-panel.test.tsx +0 -751
  569. package/templates/runtime/react/timeline-panel.tsx +0 -3078
  570. package/templates/runtime/schema/define-toolcraft.test.ts +0 -1742
  571. package/templates/runtime/state/reducer.test.ts +0 -1703
  572. package/templates/runtime/testing/performance.test.ts +0 -3081
  573. package/templates/starter/e2e/app-browser-acceptance.spec.ts +0 -785
  574. package/templates/starter/src/app/starter-acceptance.test.ts +0 -10067
  575. package/templates/starter/src/app/starter-performance.test.ts +0 -1583
  576. package/templates/ui/components/controls/color/style-guide-color-picker-logic.ts +0 -490
  577. /package/templates/runtime/react/{storage-key-migration.ts → app-shell/storage-key-migration.ts} +0 -0
  578. /package/templates/runtime/react/{theme-runtime.tsx → app-shell/theme-runtime.tsx} +0 -0
  579. /package/templates/runtime/react/{curve-geometry.test.ts → controls-panel/__tests__/curve-geometry.test.ts} +0 -0
  580. /package/templates/runtime/react/{panel-host-config.ts → panel-host/panel-host-config.ts} +0 -0
  581. /package/templates/runtime/react/{panel-host-geometry.test.ts → panel-host/panel-host-geometry.test.ts} +0 -0
  582. /package/templates/runtime/react/{panel-host-geometry.ts → panel-host/panel-host-geometry.ts} +0 -0
@@ -0,0 +1,385 @@
1
+ import { control, decisionCatalog } from "./component-contract-builders";
2
+ import type { ToolcraftComponentContract } from "./types";
3
+ export const TOOLCRAFT_VISUAL_COMPONENT_CONTRACTS = {
4
+ colorOpacity: {
5
+ ...control("colorOpacity", "ColorOpacity", "standalone", "component-owned"),
6
+ decisionCatalog: decisionCatalog({
7
+ strictness: "exact-owner",
8
+ ownsValueModel: [
9
+ "color plus opacity for one entity",
10
+ "hex color and percent opacity",
11
+ ],
12
+ useWhen: [
13
+ "Use ColorOpacity when one product entity owns both a color and opacity.",
14
+ ],
15
+ doNotReplaceWith: [
16
+ "Do not split ColorOpacity into separate Color and opacity Slider/Input controls.",
17
+ ],
18
+ acceptableAlternatives: [
19
+ "Use Color only when opacity is not editable.",
20
+ "Use Gradient when the entity is a color transition or gradient fill.",
21
+ ],
22
+ layoutConstraints: [
23
+ "ColorOpacity stays stacked and does not share inline color rows.",
24
+ ],
25
+ requiredAcceptance: [
26
+ "Prove colorOpacity.hex and colorOpacity.opacity both affect product output.",
27
+ ],
28
+ }),
29
+ aiUsageRules: [
30
+ "Use ColorOpacity when one product entity needs both a color and an opacity value, such as text color, shadow color, glow color, overlay color, or stroke color.",
31
+ "Do not split ColorOpacity into a separate Color plus Slider/Input for opacity; use type: \"colorOpacity\" so the color popover and percent input stay visually connected.",
32
+ "ColorOpacity is the only color control variant that may expose opacity in the color picker popover; plain Color popovers hide opacity controls.",
33
+ "Use one object value with hex and opacity. Renderers and exports must consume both parts.",
34
+ "Do not place ColorOpacity in inline two-column layout groups. If either color control has opacity, keep the controls stacked.",
35
+ "Only plain Color controls without opacity may render in two-column color rows.",
36
+ "Acceptance must prove colorOpacity.hex and colorOpacity.opacity both affect the product output; testing only the swatch or only runtime state is not enough.",
37
+ ],
38
+ },
39
+ palette: {
40
+ ...control("palette", "Palette", "standalone", "component-owned"),
41
+ decisionCatalog: decisionCatalog({
42
+ strictness: "best-fit",
43
+ ownsValueModel: [
44
+ "constrained palette choice",
45
+ "palette family and shade",
46
+ "design-token color selection",
47
+ "style-guide color token",
48
+ ],
49
+ useWhen: [
50
+ "Use Palette when users choose from a constrained palette family and shade rather than a free color value.",
51
+ "Use Palette for token-based color choices such as brand palettes, Tailwind-like shade scales, semantic palette families, or style-guide colors.",
52
+ ],
53
+ doNotReplaceWith: [
54
+ "Do not use Palette for arbitrary color picking.",
55
+ "Do not use Palette for gradients, free hex colors, text color inside FontPicker, or a color value that owns opacity.",
56
+ ],
57
+ acceptableAlternatives: [
58
+ "Use Color for a free single color.",
59
+ "Use ColorOpacity when opacity belongs to the same color entity.",
60
+ "Use Gradient for color transitions, gradient fills, stops, type, and angle.",
61
+ "Use FontPicker when the color belongs to product typography.",
62
+ ],
63
+ layoutConstraints: [
64
+ "Palette is a standalone compound control.",
65
+ "Palette renders content-width internal dividers only when it shares a panel section with sibling controls, with 18px vertical spacing between each divider and the control content; if it is the first control in that section, only the bottom internal divider renders; if it is the last control in that section, only the top internal divider renders; and if it is the only control in the section, only the parent section dividers render.",
66
+ ],
67
+ requiredAcceptance: [
68
+ "Prove palette.family and palette.shade both affect product output.",
69
+ "Prove Palette family and shade selections update runtime state immediately, before delayed persistence/commit settles.",
70
+ ],
71
+ }),
72
+ aiUsageRules: [
73
+ "Use Palette only when the product value is a constrained design-token palette choice with both family and shade.",
74
+ "Good Palette examples: brand palette family and shade, Tailwind-like token color, style-guide color scale, semantic palette family, or theme accent token.",
75
+ "Do not use Palette for arbitrary free color picking; use Color instead.",
76
+ "Do not use Palette when opacity belongs to the same color entity; use ColorOpacity instead.",
77
+ "Do not use Palette for gradients or color transitions; use Gradient instead.",
78
+ "Do not split typography color out to Palette when the text styling belongs to FontPicker.",
79
+ "Palette is a live control like Color and Slider: family and shade changes must update runtime state immediately so the next canvas interaction uses the selected token without waiting for delayed commit or persistence timers.",
80
+ "Palette is a compound control; acceptance must prove palette.family and palette.shade both affect the product output.",
81
+ "Do not accept a palette test that only changes a swatch preview without proving the renderer/export consumes the selected family and shade.",
82
+ ],
83
+ },
84
+ vector: {
85
+ ...control("vector", "Vector", "standalone", "component-owned"),
86
+ decisionCatalog: decisionCatalog({
87
+ strictness: "exact-owner",
88
+ ownsValueModel: [
89
+ "x/y vector",
90
+ "user-authored stable position",
91
+ "user-authored stable offset",
92
+ "user-authored stable direction",
93
+ "focus point",
94
+ "light vector",
95
+ "color balance pad",
96
+ ],
97
+ useWhen: [
98
+ "Use Vector for paired X/Y values only when the user is meant to manually author a stable two-axis product parameter such as position, offset, direction, focus, anchor, light direction, or color-balance movement.",
99
+ ],
100
+ doNotReplaceWith: [
101
+ "Do not replace Vector with two unrelated sliders or text inputs when direct two-axis editing is the product interaction.",
102
+ "Do not replace animation, keyboard input, pointer input, physics, timeline phase, velocity, or simulated pose state with Vector just because the internal value has x/y coordinates.",
103
+ ],
104
+ acceptableAlternatives: [
105
+ "Use two numeric text fields only when exact numeric entry is the primary product requirement.",
106
+ "Use timeline, keyboard/pointer handlers, motion sliders, path/step controls, or renderer simulation state when movement is generated by animation or user input rather than authored as a stable panel value.",
107
+ ],
108
+ layoutConstraints: [
109
+ "One vector renders as a square pad; multiple vectors render compact pads.",
110
+ ],
111
+ requiredAcceptance: [
112
+ "Prove vector.x and vector.y both affect product output.",
113
+ ],
114
+ }),
115
+ aiUsageRules: [
116
+ "If the controls panel contains exactly one vector control, the runtime renders the vector pad as a square.",
117
+ "If the controls panel contains multiple vector controls, the runtime renders compact vector pads.",
118
+ "Multiple vector controls should live in separate semantic sections unless they intentionally belong to the same entity with other related controls.",
119
+ "Use Vector only for user-authored stable two-axis product parameters. Do not expose Vector for current animation state, keyboard movement, pointer movement, physics state, timeline phase, velocity, target pose, current pose, or simulated position/direction.",
120
+ "Before adding a Vector control to an animated or interactive product, classify movement ownership as direct-authored, timeline-driven, keyboard/pointer-driven, or simulation-owned. Only direct-authored movement may become a visible Vector control; the other ownership modes stay in renderer/runtime interaction state and use controls such as Speed, Step, Spread, Path, Duration, or Timeline when the user needs tuning.",
121
+ 'Use variant: "whiteBalance" for temperature/tint pads: X maps cool blue to warm amber, Y maps green to magenta.',
122
+ 'Use variant: "colorBalance" for paired color-balance axes such as cyan/red and blue/yellow correction.',
123
+ 'Use variant: "chromaOffset" for RGB/chromatic offset vectors where the X/Y movement controls channel separation.',
124
+ 'Use variant: "toneBias" for split-tone, duotone, or color-grading vectors where both axes describe tone or hue bias.',
125
+ 'Use the default vector variant for spatial values such as position, offset, direction, focus, anchor, and light direction.',
126
+ 'Default spatial vector pads use coordinateMode: "screen": dragging left/up makes vector.x and vector.y smaller so canvas objects move left/up without renderer-side Y inversion.',
127
+ "Vector pad value labels render compact rounded coordinates. Do not expose raw floating-point strings such as -0.07070312499999998 in the controls panel.",
128
+ "Double-clicking a vector pad resets both axes to the control default through the normal runtime value update, matching section header reset semantics; if no default is defined, the fallback is 0,0. Do not add a separate custom reset UI for this basic pad reset behavior.",
129
+ "Holding Shift while dragging a vector pad locks movement to the dominant axis and must not select text or page content; do not build a custom pad just to support axis-constrained movement.",
130
+ 'Use coordinateMode: "cartesian" only when the product intentionally exposes mathematical Y-up coordinates instead of canvas/screen movement.',
131
+ "Do not add custom vector sizing props in generated schemas; choose the number, variant, and section grouping from product need and let the runtime size the pads.",
132
+ "Vector is a compound control; acceptance must prove vector.x and vector.y both affect the product output and that the vector represents a user-authored stable two-axis parameter rather than current animation, input, or simulation state.",
133
+ ],
134
+ },
135
+ color: {
136
+ ...control("color", "Color", "standalone", "component-owned"),
137
+ decisionCatalog: decisionCatalog({
138
+ strictness: "best-fit",
139
+ ownsValueModel: [
140
+ "single free color",
141
+ "hex color value",
142
+ "role color",
143
+ ],
144
+ useWhen: [
145
+ "Use Color for one editable free color without opacity or gradient stops.",
146
+ ],
147
+ doNotReplaceWith: [
148
+ "Do not use multiple Color controls as a substitute for an adjustable Gradient.",
149
+ "Do not pair Color with a separate opacity control when ColorOpacity fits.",
150
+ ],
151
+ acceptableAlternatives: [
152
+ "Use ColorOpacity when opacity belongs to the color entity.",
153
+ "Use Gradient for color transitions, fills with stops, or angle/type editing.",
154
+ "Use Palette for constrained design-token choices.",
155
+ ],
156
+ layoutConstraints: [
157
+ "Plain Color controls may render two per row only when no opacity is present.",
158
+ "Odd trailing plain Color controls in a multi-color bank keep the same half-width footprint as paired colors.",
159
+ "Color label visibility depends on user usefulness: palette variation banks omit per-item labels; distinct color roles keep labels.",
160
+ ],
161
+ requiredAcceptance: [
162
+ "Prove the selected color affects product output, preview, or export.",
163
+ ],
164
+ }),
165
+ aiUsageRules: [
166
+ "Color controls can be standalone color sections or grouped fields inside a semantic control section.",
167
+ "First identify the semantic entity the color belongs to, such as Square 1, Square 2, Background, Object, Connector, Glow, Tone Mapping, Brand, or Export.",
168
+ "Keep a color inside a section when it configures the same entity as nearby controls. Example: Square 1 (Right) contains Connections, Hover radius, and Color in one section.",
169
+ "Use a standalone color section only when the color itself is the whole semantic section; the section title must describe the product role such as Background, Object, Connector, Accent, Gradient, or Brand.",
170
+ "When color belongs to the same object or effect as nearby controls, keep it inside that section and use a concise field label that is unambiguous in context, such as Color in a Square section or Symbol color in a mixed Style section.",
171
+ "Decide color label visibility from the user's point of view. Omit labels for color banks that only add palette variety, such as Accent Shades, Bead Colors, or palette.accent1..5.",
172
+ "Make color label visibility a group-level decision: do not mix labeled and unlabeled items inside one semantic color bank.",
173
+ "Keep visible labels when colors edit distinct user-facing entities or roles, such as Fill, Stroke, Background, Connector, Object, or Highlight.",
174
+ "A color bank can share a section with distribution controls such as Spread, Mix, or Randomness and still keep each color item unlabeled when the section title names the palette context.",
175
+ "The standalone default applies only to color-only sections; mixed semantic sections keep color grouped with nearby controls.",
176
+ "Never use generic Color or Colors as a generated section title. If no meaningful color role exists and the colors are just basic colors, use a neutral section title such as Appearance instead of omitting the title.",
177
+ "Do not split a grouped object section into a separate generated Color section; if the color role is unclear, ask the user before implementation.",
178
+ "When one short numeric/text field and one Color field configure the same entity, keep them in one two-column inline layout group.",
179
+ 'Mixed inline rows usually require visible labels on both controls. Toggle-plus-parameter rows are the section-owned exception: keep the Switch/Checkbox label visible and set the non-toggle parameter label to false; if the parameter label is needed, stack the controls instead. All 50/50 inline rows use the same horizontal column gap as paired Select controls. The required Background row uses the Switch label "Include" and sets the background Color control label to false. Palette variation color banks are the other exception when the group/section label already names the color bank.',
180
+ "Plain Color popovers must not show opacity controls. If opacity is editable, use ColorOpacity instead.",
181
+ "Product-output apps always expose renderer-owned output background color as a schema color target such as appearance.background or scene.background.",
182
+ 'Pair renderer-owned output background color with export.includeBackground in one Background section directly before export settings. Use an equal-width inline row with the export.includeBackground Switch labeled "Include" on the left and the background Color parameter with label false on the right; each control occupies one half of the row.',
183
+ "Preview, PNG export, and video export must read the runtime background color value instead of hardcoding that background in CSS, Canvas fillStyle, or WebGL clearColor. export.includeBackground controls live preview product background and PNG alpha; it must not make the Toolcraft canvas shell/backing or video output transparent.",
184
+ "Render multiple related color fields in one section with at most two colors per row.",
185
+ "If a multi-color bank has an odd trailing plain Color, keep that last Color at half width; only ColorOpacity or intentionally full-width compound controls occupy a full row.",
186
+ ],
187
+ },
188
+ gradient: {
189
+ ...control("gradient", "Gradient", "standalone", "component-owned"),
190
+ decisionCatalog: decisionCatalog({
191
+ strictness: "exact-owner",
192
+ ownsValueModel: [
193
+ "gradient fill",
194
+ "gradient type",
195
+ "gradient angle",
196
+ "gradient stops",
197
+ "stop colors",
198
+ "stop opacity",
199
+ "stop positions",
200
+ ],
201
+ useWhen: [
202
+ "Use Gradient when the product needs an adjustable gradient, color transition, multi-stop fill, linear fill, radial fill, angular fill, or diamond fill.",
203
+ "Use Gradient when the prompt or reference mentions gradient stops, gradient angle, gradient type, or editable color transition.",
204
+ ],
205
+ doNotReplaceWith: [
206
+ "Do not replace Gradient with two Color controls.",
207
+ "Do not replace Gradient with ColorOpacity plus sliders.",
208
+ "Do not build custom gradient UI unless the built-in Gradient cannot express the interaction and the custom escape hatch is documented.",
209
+ ],
210
+ acceptableAlternatives: [
211
+ "Use Color or ColorOpacity only when the product explicitly needs fixed single colors, not an adjustable gradient.",
212
+ ],
213
+ layoutConstraints: [
214
+ "Gradient is a full standalone compound control.",
215
+ "Gradient renders content-width internal dividers only when it shares a panel section with sibling controls, with 18px vertical spacing between each divider and the control content; if it is the first control in that section, only the bottom internal divider renders; if it is the last control in that section, only the top internal divider renders; and if it is the only control in the section, only the parent section dividers render.",
216
+ ],
217
+ requiredAcceptance: [
218
+ "Prove gradientType, angle, stop position, stop color, and stop opacity affect product output or export output.",
219
+ ],
220
+ }),
221
+ aiUsageRules: [
222
+ "Gradient is a compound control; acceptance must prove gradient.gradientType, gradient.angle, gradient.stops.position, gradient.stops.color, and gradient.stops.opacity all affect the product output when visible.",
223
+ "Keep Gradient type/angle, draggable stop track, and Stops list inside the built-in Gradient control. The full Gradient control is visually separated with content-width dividers only when it shares a section with sibling controls; do not put dividers only around the Stops list and do not rebuild it as separate schema controls.",
224
+ "Do not accept a gradient test that edits only a stop color; Linear/Radial/Angular/Diamond selection, angle, stop position, stop color, and stop opacity must be wired or the control should be simplified.",
225
+ "If the renderer intentionally supports only a subset of gradient behavior, do not use the full Gradient control; use simpler controls that match the renderer behavior.",
226
+ ],
227
+ },
228
+ fontPicker: {
229
+ ...control("fontPicker", "FontPicker", "standalone", "component-owned"),
230
+ decisionCatalog: decisionCatalog({
231
+ strictness: "exact-owner",
232
+ ownsValueModel: [
233
+ "font family",
234
+ "font preview",
235
+ "font weight",
236
+ "font size",
237
+ "text case",
238
+ "letter spacing",
239
+ "line height",
240
+ "text color",
241
+ "text opacity",
242
+ ],
243
+ useWhen: [
244
+ "Use FontPicker when product typography needs font family, weight, size, case, letter spacing, line height, text color, or text opacity.",
245
+ ],
246
+ doNotReplaceWith: [
247
+ "Do not replace FontPicker with a plain Select plus separate typography controls.",
248
+ "Do not build a custom font popup for product typography.",
249
+ "Do not add sibling controls for text color, text opacity, case, weight, size, letter spacing, or line height when they belong to the same typography entity.",
250
+ ],
251
+ acceptableAlternatives: [
252
+ "Use TextInput or Select only for non-typographic labels or finite text choices.",
253
+ ],
254
+ layoutConstraints: [
255
+ "FontPicker owns its popup and internal footer controls.",
256
+ "FontPicker renders content-width internal dividers only when it shares a panel section with sibling controls, with 18px vertical spacing between each divider and the control content; if it is the first control in that section, only the bottom internal divider renders; if it is the last control in that section, only the top internal divider renders; and if it is the only control in the section, only the parent section dividers render.",
257
+ ],
258
+ requiredAcceptance: [
259
+ "Prove fontId, fontWeight, fontSize, letterSpacing, lineHeight, textCase, color, and opacity affect actual product text output.",
260
+ ],
261
+ }),
262
+ aiUsageRules: [
263
+ "FontPicker owns the font preview select, virtualized font popup, category filters, search, preview loading, font-weight select, font-size input, text-case select, text color/opacity control, letter-spacing slider, and line-height slider.",
264
+ "Do not recreate FontPicker with a plain Select plus separate sliders; use type: \"fontPicker\" so the popup mechanics and footer controls stay intact.",
265
+ "Use one object value with fontId, fontWeight, fontSize, letterSpacing, lineHeight, textCase, color, and opacity. Keep typography renderers wired to all eight parts.",
266
+ "FontPicker standard/default text color is #FFFFFF with opacity 100; omit color/opacity or use those values unless the prompt or reference explicitly requires a different initial text color.",
267
+ "Any product text controlled by FontPicker must render fontId, fontWeight, fontSize, letterSpacing, lineHeight, textCase, color, and opacity in preview and export; do not leave typography values as panel-only runtime state.",
268
+ "FontPicker is an atomic compound typography control. Do not split any owned typography part into a neighboring schema control for the same product text entity.",
269
+ "Do not put a help tooltip on FontPicker just to list its owned fields. If the section title and FontPicker labels already make the text target clear, omit description.",
270
+ "FontPicker is a compound control; acceptance must prove fontPicker.fontId, fontPicker.fontWeight, fontPicker.fontSize, fontPicker.letterSpacing, fontPicker.lineHeight, fontPicker.textCase, fontPicker.color, and fontPicker.opacity all affect the product output.",
271
+ "FontPicker acceptance must inspect the actual product text output after changing font, weight, size, letter spacing, line height, text case, color, and opacity; runtime state, select labels, or popup preview text alone are not enough.",
272
+ "Browser verification must open the popup, choose a different font, change font weight, change font size, change text case, change text color/opacity, move the letter-spacing footer slider, and move the line-height footer slider.",
273
+ ],
274
+ },
275
+ curves: {
276
+ ...control("curves", "Curves", "standalone", "component-owned"),
277
+ decisionCatalog: decisionCatalog({
278
+ strictness: "exact-owner",
279
+ ownsValueModel: [
280
+ "editable curve",
281
+ "tone curve",
282
+ "response curve",
283
+ "easing curve",
284
+ "remapping curve",
285
+ "channel curve",
286
+ ],
287
+ useWhen: [
288
+ "Use Curves for editable remapping, tone, response, easing, opacity, depth, mask, or channel curves.",
289
+ ],
290
+ doNotReplaceWith: [
291
+ "Do not replace Curves with generic sliders when the product needs an editable curve.",
292
+ "Do not build custom curve UI just to remove RGB tabs; use variant single.",
293
+ ],
294
+ acceptableAlternatives: [
295
+ "Use Slider only when the product needs one scalar strength value, not a curve shape.",
296
+ ],
297
+ layoutConstraints: [
298
+ "Use variant single for one standalone curve and RGB variant only for color-correction or channel-specific curves.",
299
+ "Single Curves is one labeled control and does not render internal dividers, even inside mixed sections.",
300
+ "RGB Curves is a compound channel control and renders content-width internal dividers only when it shares a panel section with sibling controls, with 18px vertical spacing between each rendered divider and the control content; if it is the first control in that section, only the bottom internal divider renders and the top internal padding is removed; if it is the last control in that section, only the top internal divider renders and the bottom internal padding is removed; and if it is the only control in the section, only the parent section dividers render.",
301
+ ],
302
+ requiredAcceptance: [
303
+ "Prove curves.points affect product output; RGB curves also prove activeChannel affects output.",
304
+ ],
305
+ }),
306
+ aiUsageRules: [
307
+ 'Use Curves for editable remapping curves. RGB/R/G/B tabs are only for color-correction or channel-specific curves; use variant: "single" for one standalone curve without channel tabs.',
308
+ 'Every curves control declares curveIntent: "single-value-map" or "color-channels". Labels and target names are not curve-composition evidence.',
309
+ 'curveIntent: "single-value-map" requires variant: "single"; curveIntent: "color-channels" uses the channel composition.',
310
+ 'Use variant: "single" for a single acceleration, bend, easing, opacity, response, depth, mask, threshold, tone-response, or mapping curve. Do not create a custom curve UI just to remove RGB tabs.',
311
+ "RGB Curves is a color-correction-specific case; do not force RGB/R/G/B tabs onto products that need only one response, bend, depth, or easing curve.",
312
+ 'Use interpolation: "smooth" for photo/editor-like visual tone, color, and RGB curves where the curve should feel like a creative editor spline.',
313
+ 'Use interpolation: "monotone" for depth, response, mask, opacity, threshold, and data-mapping curves where order must be preserved and overshoot is unsafe. Single curves default to monotone unless smooth is explicitly requested.',
314
+ "Single Curves is one labeled control without internal dividers; RGB Curves is the compound variant with channel tabs and section dividers when mixed with sibling controls.",
315
+ "RGB curves acceptance must prove curves.activeChannel and curves.points both affect the product output. Single curves acceptance proves curves.points.",
316
+ "Curves acceptance should include an off-center control point near an edge so smooth-vs-monotone interpolation mistakes are visible in product output.",
317
+ "Do not accept a curves test that only opens the UI or changes selected point state without proving renderer/export output changes.",
318
+ ],
319
+ },
320
+ anchorGrid: {
321
+ ...control("anchorGrid", "AnchorGrid", "standalone", "component-owned"),
322
+ decisionCatalog: decisionCatalog({
323
+ strictness: "best-fit",
324
+ ownsValueModel: [
325
+ "anchor position",
326
+ "edge or corner placement",
327
+ "nine-point alignment",
328
+ ],
329
+ useWhen: [
330
+ "Use AnchorGrid for choosing an anchor, alignment point, or edge/corner placement.",
331
+ ],
332
+ doNotReplaceWith: [
333
+ "Do not use AnchorGrid for freeform two-axis movement; use Vector.",
334
+ ],
335
+ acceptableAlternatives: [
336
+ "Use Vector only for stable direct-authored continuous position or direction parameters.",
337
+ ],
338
+ layoutConstraints: [
339
+ "AnchorGrid is a standalone position selector.",
340
+ ],
341
+ requiredAcceptance: [
342
+ "Prove selected anchor changes product placement.",
343
+ ],
344
+ }),
345
+ aiUsageRules: [
346
+ "AnchorGrid is a position selector; acceptance must prove anchorGrid.position changes product placement, not only selected button state.",
347
+ "Choose representative edge/corner anchors in browser tests so center-only behavior cannot pass.",
348
+ ],
349
+ },
350
+ channelMixer: {
351
+ ...control("channelMixer", "ChannelMixer", "standalone", "component-owned"),
352
+ decisionCatalog: decisionCatalog({
353
+ strictness: "exact-owner",
354
+ ownsValueModel: [
355
+ "RGB channel mixer",
356
+ "RGB channel matrix",
357
+ "active RGB output channel and RGB source-channel values",
358
+ ],
359
+ useWhen: [
360
+ "Use ChannelMixer only when product behavior edits RGB channel mixing, channel swapping, or an RGB channel matrix.",
361
+ ],
362
+ doNotReplaceWith: [
363
+ "Do not replace ChannelMixer with disconnected sliders for each channel when the active channel matrix matters.",
364
+ "Do not use ChannelMixer for arbitrary non-RGB channels, data channels, audio bands, masks, layers, or option groups.",
365
+ ],
366
+ acceptableAlternatives: [
367
+ "Use Color or Curves for simple color choice or tone curves that are not channel matrix mixing.",
368
+ "Use Select, Segmented, Slider, Curves, or a justified custom control for non-RGB channel-like product domains.",
369
+ ],
370
+ layoutConstraints: [
371
+ "ChannelMixer is a standalone compound control.",
372
+ "ChannelMixer renders content-width internal dividers only when it shares a panel section with sibling controls, with 18px vertical spacing between each divider and the control content; if it is the first control in that section, only the bottom internal divider renders; if it is the last control in that section, only the top internal divider renders; and if it is the only control in the section, only the parent section dividers render.",
373
+ ],
374
+ requiredAcceptance: [
375
+ "Prove channelMixer.activeChannel and channelMixer.values both affect product output.",
376
+ ],
377
+ }),
378
+ aiUsageRules: [
379
+ "ChannelMixer is RGB-specific: it renders R/G/B tabs and Red, Green, Blue sliders for an RGB channel matrix.",
380
+ "Use ChannelMixer only for RGB channel mixing, channel swapping, or color-correction matrix behavior; do not use it for arbitrary channel lists.",
381
+ "ChannelMixer is a compound control; acceptance must prove channelMixer.activeChannel and channelMixer.values both affect the product output.",
382
+ "Do not accept a channel mixer test that changes only the active tab or only one slider without proving the selected channel matrix is consumed by the renderer/export.",
383
+ ],
384
+ },
385
+ } as const satisfies Record<string, ToolcraftComponentContract>;
@@ -0,0 +1,64 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ import * as toolcraftUiControls from "@repo/ui/controls";
6
+ import * as toolcraftUiPanel from "@repo/ui/panel";
7
+ import { describe, expect, it } from "vitest";
8
+
9
+ import * as toolcraftRuntimeReact from "../react";
10
+ import {
11
+ TOOLCRAFT_BUILT_IN_CONTROL_TYPES,
12
+ TOOLCRAFT_COMPONENT_CONTRACTS,
13
+ } from "./component-contracts";
14
+ import { TOOLCRAFT_DECISION_CONTRACT } from "./decision-contracts";
15
+
16
+ const contractsDir = dirname(fileURLToPath(import.meta.url));
17
+ const repoRoot = resolve(contractsDir, "../../../..");
18
+ const manifest = JSON.parse(
19
+ readFileSync(
20
+ resolve(repoRoot, "starter/scripts/toolcraft-contract-manifest.json"),
21
+ "utf8",
22
+ ),
23
+ );
24
+
25
+ describe("Toolcraft machine-readable contract manifest", () => {
26
+ it("matches every runtime decision rule with level and area", () => {
27
+ expect(manifest.decisionRules).toEqual(
28
+ TOOLCRAFT_DECISION_CONTRACT.map(({ area, id, level }) => ({
29
+ area,
30
+ id,
31
+ level,
32
+ })),
33
+ );
34
+ });
35
+
36
+ it("matches the canonical built-in registry and visual ownership", () => {
37
+ expect(manifest.builtInControls).toEqual(
38
+ TOOLCRAFT_BUILT_IN_CONTROL_TYPES.map((type) => ({
39
+ type,
40
+ visualComponent: TOOLCRAFT_COMPONENT_CONTRACTS[type].visualComponent,
41
+ })),
42
+ );
43
+ });
44
+
45
+ it("names only real protected UI exports and runtime surfaces", () => {
46
+ const publicUiExports = {
47
+ ...toolcraftUiControls,
48
+ ...toolcraftUiPanel,
49
+ };
50
+
51
+ for (const exportName of manifest.protectedControlExportNames) {
52
+ expect(
53
+ exportName in publicUiExports,
54
+ `Protected control export "${exportName}" must exist in @repo/ui.`,
55
+ ).toBe(true);
56
+ }
57
+ for (const exportName of manifest.runtimeSurfaceComponentNames) {
58
+ expect(
59
+ exportName in toolcraftRuntimeReact,
60
+ `Runtime surface "${exportName}" must exist in @repo/toolcraft-runtime/react.`,
61
+ ).toBe(true);
62
+ }
63
+ });
64
+ });
@@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url";
5
5
  import { describe, expect, it } from "vitest";
6
6
 
7
7
  import {
8
+ getToolcraftDecisionDiagnosticSeverity,
8
9
  getToolcraftDecisionRule,
9
10
  getToolcraftDecisionRulesByArea,
10
11
  TOOLCRAFT_DECISION_CONTRACT,
@@ -77,6 +78,30 @@ describe("Toolcraft template decision contract", () => {
77
78
  );
78
79
  });
79
80
 
81
+ it("derives blocking severity from the canonical rule level", () => {
82
+ expect(getToolcraftDecisionDiagnosticSeverity("controls-layout-heuristics")).toBe(
83
+ "warning",
84
+ );
85
+ expect(getToolcraftDecisionDiagnosticSeverity("runtime-shell-required")).toBe(
86
+ "error",
87
+ );
88
+ expect(getToolcraftDecisionDiagnosticSeverity("renderer-technique-inventory")).toBe(
89
+ "error",
90
+ );
91
+ });
92
+
93
+ it("separates mandatory section inventory and component fit from layout heuristics", () => {
94
+ expect(getToolcraftDecisionRule("controls-section-inventory-required")?.level).toBe(
95
+ "invariant",
96
+ );
97
+ expect(getToolcraftDecisionRule("controls-component-layout-invariants")?.level).toBe(
98
+ "invariant",
99
+ );
100
+ expect(getToolcraftDecisionRule("controls-layout-heuristics")?.level).toBe(
101
+ "heuristic",
102
+ );
103
+ });
104
+
80
105
  it("makes renderer technology a default with escape hatches", () => {
81
106
  const rule = getToolcraftDecisionRule("renderer-technique-inventory");
82
107
 
@@ -178,11 +203,11 @@ describe("Toolcraft template decision contract", () => {
178
203
  starterDecisionSource,
179
204
  `Starter local decision docs must list decision rule "${rule.id}".`,
180
205
  ).toContain(rule.id);
181
- expect(
182
- starterDocsCheckSource,
183
- `Starter docs check must enforce decision rule "${rule.id}".`,
184
- ).toContain(rule.id);
185
206
  }
207
+ expect(starterDocsCheckSource).toContain("toolcraftDecisionRuleIds");
208
+ expect(starterDocsCheckSource).toContain(
209
+ "getToolcraftContractFragmentFailures",
210
+ );
186
211
  });
187
212
 
188
213
  it("keeps root AGENTS.md as a concise entry map instead of duplicated rule prose", () => {
@@ -27,6 +27,8 @@ export type ToolcraftDecisionVerdict =
27
27
  | "relax-to-heuristic"
28
28
  | "remove-duplicate";
29
29
 
30
+ export type ToolcraftDecisionDiagnosticSeverity = "error" | "warning";
31
+
30
32
  export type ToolcraftDecisionEnforcement =
31
33
  | "acceptance-validator"
32
34
  | "browser-helper"
@@ -185,12 +187,36 @@ export const TOOLCRAFT_DECISION_CONTRACT = [
185
187
  title: "Product output always has export",
186
188
  verdict: "move-to-validator",
187
189
  },
190
+ {
191
+ area: "controls",
192
+ currentConstraint:
193
+ "Every product controls section must be represented in the exported Control Section Inventory before schema authoring.",
194
+ desiredBehavior:
195
+ "Generated product apps publish a typed Control Section Inventory with section title, product entity or workflow stage, exact targets, and a concrete grouping reason so section ownership is machine-checkable without prescribing the final product layout.",
196
+ enforcement: ["acceptance-validator", "docs", "starter-agents", "spec-checklist"],
197
+ id: "controls-section-inventory-required",
198
+ level: "invariant",
199
+ title: "Product control sections require typed inventory",
200
+ verdict: "move-to-validator",
201
+ },
202
+ {
203
+ area: "controls",
204
+ currentConstraint:
205
+ "Built-in control owners have structural layout constraints that prevent clipping, ambiguous value ownership, and unsupported inline composition.",
206
+ desiredBehavior:
207
+ "Exact component constraints such as full-width range sliders, compound-control ownership, and supported inline group membership remain hard runtime and acceptance invariants, while product grouping and ordering preferences remain heuristics.",
208
+ enforcement: ["acceptance-validator", "schema-normalization", "docs"],
209
+ id: "controls-component-layout-invariants",
210
+ level: "invariant",
211
+ title: "Built-in component layout constraints stay hard",
212
+ verdict: "move-to-validator",
213
+ },
188
214
  {
189
215
  area: "controls",
190
216
  currentConstraint:
191
217
  "Labels, color placement, section grouping, selector order, and inline density need product-aware decisions.",
192
218
  desiredBehavior:
193
- "Apps export a Control Section Inventory before schema authoring: every product controls section has a product entity or workflow stage, exact targets, a grouping reason, and split evidence when one target entity is intentionally divided.",
219
+ "Given a valid Control Section Inventory, ordering, section cohesion, labels, color placement, and compact density remain product-aware recommendations. Validators report questionable grouping without rejecting a coherent product-specific choice solely because it differs from a preferred heuristic.",
194
220
  enforcement: ["acceptance-validator", "schema-normalization", "docs", "starter-agents"],
195
221
  id: "controls-layout-heuristics",
196
222
  level: "heuristic",
@@ -294,3 +320,14 @@ export function getToolcraftDecisionRulesByArea(
294
320
  ): ToolcraftDecisionRule[] {
295
321
  return TOOLCRAFT_DECISION_CONTRACT.filter((rule) => rule.area === area);
296
322
  }
323
+
324
+ export type ToolcraftDecisionRuleId =
325
+ (typeof TOOLCRAFT_DECISION_CONTRACT)[number]["id"];
326
+
327
+ export function getToolcraftDecisionDiagnosticSeverity(
328
+ id: ToolcraftDecisionRuleId,
329
+ ): ToolcraftDecisionDiagnosticSeverity {
330
+ const level = getToolcraftDecisionRule(id)?.level;
331
+
332
+ return level === "heuristic" || level === "recommendation" ? "warning" : "error";
333
+ }
@@ -11,5 +11,6 @@ export * from "./state/keyframe-evaluation";
11
11
  export * from "./state/persistence";
12
12
  export * from "./state/reducer";
13
13
  export * from "./state/timeline-loop";
14
+ export * from "./state/timeline-values";
14
15
  export * from "./state/types";
15
16
  export * from "./testing/performance";
@@ -1,14 +1,17 @@
1
1
  import type * as React from "react";
2
2
  import { describe, expect, expectTypeOf, it } from "vitest";
3
3
 
4
- import { defineToolcraft } from "../schema/define-toolcraft";
5
- import { CanvasShell } from "./canvas-shell";
6
- import { ControlsPanel } from "./controls-panel";
7
- import { ToolcraftApp } from "./toolcraft-app";
4
+ import { defineToolcraft } from "../../schema/define-toolcraft";
5
+ import { CanvasShell } from "../canvas/canvas-shell";
6
+ import { ControlsPanel } from "../controls-panel/controls-panel";
7
+ import {
8
+ ToolcraftApp,
9
+ type ToolcraftAppComposition,
10
+ } from "./toolcraft-app";
8
11
  import { ToolcraftRoot } from "./toolcraft-root";
9
- import { LayersPanel } from "./layers-panel";
10
- import { PanelContainer, PanelHost, PanelStage } from "./panel-host";
11
- import { TimelinePanel } from "./timeline-panel";
12
+ import { LayersPanel } from "../layers/layers-panel";
13
+ import { PanelContainer, PanelHost, PanelStage } from "../panel-host/panel-host";
14
+ import { TimelinePanel } from "../timeline/timeline-panel";
12
15
  import { ToolbarPanel } from "./toolbar-panel";
13
16
 
14
17
  const runtimePublicApiSchema = defineToolcraft({
@@ -18,6 +21,13 @@ const runtimePublicApiSchema = defineToolcraft({
18
21
 
19
22
  describe("Toolcraft template runtime public API", () => {
20
23
  it("keeps app assembly props narrow", () => {
24
+ expectTypeOf<keyof ToolcraftAppComposition>().toEqualTypeOf<
25
+ | "canvasContent"
26
+ | "controlRenderers"
27
+ | "onPanelAction"
28
+ | "renderDefaultCanvasMedia"
29
+ | "schema"
30
+ >();
21
31
  expectTypeOf<
22
32
  keyof React.ComponentProps<typeof ToolcraftApp>
23
33
  >().toEqualTypeOf<
@@ -106,6 +116,16 @@ describe("Toolcraft template runtime public API", () => {
106
116
  renderDefaultCanvasMedia: false,
107
117
  schema: runtimePublicApiSchema,
108
118
  };
119
+ const compositionWithClassName: ToolcraftAppComposition = {
120
+ schema: runtimePublicApiSchema,
121
+ // @ts-expect-error Host layout classes belong to the protected route.
122
+ className: "product-shell",
123
+ };
124
+ const compositionWithStyle: ToolcraftAppComposition = {
125
+ schema: runtimePublicApiSchema,
126
+ // @ts-expect-error Host layout styles belong to the protected route.
127
+ style: { minHeight: 0 },
128
+ };
109
129
  const canvasWithSlotProps: React.ComponentProps<typeof CanvasShell> = {
110
130
  children: <div />,
111
131
  renderDefaultMedia: false,
@@ -123,6 +143,8 @@ describe("Toolcraft template runtime public API", () => {
123
143
  expect(appWithChildrenProps).toBeTruthy();
124
144
  expect(appWithToolbarThemeToggleProps).toBeTruthy();
125
145
  expect(appWithCanvasSlotProps).toBeTruthy();
146
+ expect(compositionWithClassName).toBeTruthy();
147
+ expect(compositionWithStyle).toBeTruthy();
126
148
  expect(canvasWithSlotProps).toBeTruthy();
127
149
  expect(canvasWithUpload).toBeTruthy();
128
150
  expect(styledCanvas).toBeTruthy();