@pixel-point/toolcraft 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/package.json +1 -1
  2. package/src/generate-performance-iteration-execution.test.mjs +2 -2
  3. package/src/generate-test-demand-only-lifecycle.mjs +14 -3
  4. package/src/generate-test-dependency-sandbox.mjs +42 -5
  5. package/src/generate-test-doc-assertions.mjs +109 -69
  6. package/src/generate-test-doc-assertions.test.mjs +65 -0
  7. package/src/generate-test-doc-policy-assertions.mjs +92 -0
  8. package/src/generate-test-file-assertions.mjs +36 -118
  9. package/src/generate-test-output-assertions.mjs +95 -0
  10. package/src/generate-test-package-assertions.mjs +6 -0
  11. package/src/generate-test-performance-boundary-assertions.mjs +45 -0
  12. package/src/generate-test-product-fixture.mjs +1 -0
  13. package/src/generate-test-product-fixture.test.mjs +18 -0
  14. package/src/generate-test-product-iteration.mjs +1 -0
  15. package/src/generate-test-product-iteration.test.mjs +18 -0
  16. package/src/generate-test-runtime-boundary-assertions.mjs +158 -0
  17. package/src/generate-test-standalone-assertions.mjs +10 -0
  18. package/src/generate-test-standalone-delivery-stages.mjs +14 -6
  19. package/src/generate.test.mjs +14 -0
  20. package/templates/runtime/contracts/component-contracts.choices.test.ts +59 -12
  21. package/templates/runtime/contracts/component-contracts.choices.ts +58 -12
  22. package/templates/runtime/contracts/component-contracts.inputs.test.ts +6 -6
  23. package/templates/runtime/contracts/component-contracts.inputs.ts +6 -6
  24. package/templates/runtime/contracts/component-contracts.media-custom.test.ts +8 -2
  25. package/templates/runtime/contracts/component-contracts.media-custom.ts +8 -2
  26. package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +21 -6
  27. package/templates/runtime/contracts/component-contracts.runtime-labels.test.ts +7 -1
  28. package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +4 -1
  29. package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +4 -1
  30. package/templates/runtime/contracts/component-contracts.runtime.ts +15 -10
  31. package/templates/runtime/contracts/component-contracts.test.ts +2 -0
  32. package/templates/runtime/contracts/decision-contracts.test.ts +43 -4
  33. package/templates/runtime/contracts/decision-contracts.ts +10 -10
  34. package/templates/runtime/contracts/performance-verification-policy.test.ts +59 -6
  35. package/templates/runtime/contracts/performance-verification-policy.ts +5 -2
  36. package/templates/runtime/export/artifact-download.test.ts +71 -0
  37. package/templates/runtime/export/artifact-download.ts +80 -0
  38. package/templates/runtime/export/artifact-export-request.ts +23 -0
  39. package/templates/runtime/export/artifact-export-settings.test.ts +75 -0
  40. package/templates/runtime/export/artifact-export-settings.ts +96 -0
  41. package/templates/runtime/export/artifact-frame-renderer.test.ts +107 -0
  42. package/templates/runtime/export/artifact-frame-renderer.ts +96 -0
  43. package/templates/runtime/export/artifact-frame-state.test.ts +54 -0
  44. package/templates/runtime/export/artifact-frame-state.ts +44 -0
  45. package/templates/runtime/export/artifact-scene-frame.test.ts +84 -0
  46. package/templates/runtime/export/artifact-scene-frame.ts +118 -0
  47. package/templates/runtime/export/export-background.ts +46 -0
  48. package/templates/runtime/export/export-error.ts +43 -0
  49. package/templates/runtime/export/export.test.ts +49 -226
  50. package/templates/runtime/export/image-artifact-export.test.ts +111 -0
  51. package/templates/runtime/export/image-artifact-export.ts +145 -0
  52. package/templates/runtime/export/index.ts +44 -3
  53. package/templates/runtime/export/product-export-renderer.test.ts +77 -0
  54. package/templates/runtime/export/product-export-renderer.ts +63 -0
  55. package/templates/runtime/export/video-artifact-export.test.ts +166 -0
  56. package/templates/runtime/export/video-artifact-export.ts +164 -0
  57. package/templates/runtime/export/video-encoding-backend.ts +124 -0
  58. package/templates/runtime/export/video-encoding-policy.test.ts +68 -0
  59. package/templates/runtime/export/video-encoding-policy.ts +86 -0
  60. package/templates/runtime/export/video-frame-schedule.test.ts +58 -0
  61. package/templates/runtime/export/video-frame-schedule.ts +42 -0
  62. package/templates/runtime/index.ts +3 -0
  63. package/templates/runtime/model-import/model-import-limits.ts +15 -4
  64. package/templates/runtime/react/app-shell/runtime-public-api-runtime.test.tsx +291 -0
  65. package/templates/runtime/react/app-shell/runtime-public-api-test-support.ts +21 -0
  66. package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +15 -304
  67. package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +41 -27
  68. package/templates/runtime/react/app-shell/toolcraft-app.tsx +39 -11
  69. package/templates/runtime/react/app-shell/toolcraft-source-asset-context.test.tsx +16 -57
  70. package/templates/runtime/react/app-shell/toolcraft-source-asset-context.tsx +75 -434
  71. package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.test.ts +194 -0
  72. package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.ts +227 -0
  73. package/templates/runtime/react/app-shell/toolcraft-source-asset-provider-ownership.test.tsx +243 -0
  74. package/templates/runtime/react/app-shell/toolcraft-source-asset-test-support.ts +51 -0
  75. package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.test.ts +138 -0
  76. package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.ts +378 -0
  77. package/templates/runtime/react/canvas/canvas-shell-rendering.test.tsx +76 -0
  78. package/templates/runtime/react/canvas/canvas-shell-test-utils.tsx +13 -1
  79. package/templates/runtime/react/canvas/canvas-shell.tsx +16 -1
  80. package/templates/runtime/react/canvas/product-scene-surface.test.tsx +195 -0
  81. package/templates/runtime/react/canvas/product-scene-surface.tsx +155 -0
  82. package/templates/runtime/react/canvas/runtime-scene-export.ts +1 -1
  83. package/templates/runtime/react/controls-panel/__tests__/control-conditions.test.ts +61 -0
  84. package/templates/runtime/react/controls-panel/__tests__/controls-panel.collection-actions.test.tsx +89 -0
  85. package/templates/runtime/react/controls-panel/__tests__/controls-panel.control-visibility.test.tsx +40 -19
  86. package/templates/runtime/react/controls-panel/__tests__/controls-panel.footer-actions.test.tsx +7 -12
  87. package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +18 -84
  88. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-collection.test.tsx +62 -0
  89. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-color-bank.test.tsx +67 -0
  90. package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +43 -87
  91. package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +68 -0
  92. package/templates/runtime/react/controls-panel/conditions/control-conditions.ts +32 -119
  93. package/templates/runtime/react/controls-panel/layout/controls-panel-control-group.tsx +5 -2
  94. package/templates/runtime/react/controls-panel/layout/controls-panel-layout.tsx +10 -8
  95. package/templates/runtime/react/controls-panel/layout/controls-panel-section.tsx +3 -3
  96. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.test.tsx +63 -0
  97. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.tsx +138 -0
  98. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-items.tsx +104 -0
  99. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-renderer.tsx +115 -236
  100. package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.test.tsx +95 -0
  101. package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.tsx +82 -0
  102. package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.test.tsx +73 -1
  103. package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.tsx +50 -1
  104. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.test.ts +1 -1
  105. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.ts +2 -1
  106. package/templates/runtime/react/controls-panel/values/controls-panel-collection-values.ts +38 -6
  107. package/templates/runtime/react/controls-panel/values/controls-panel-value-labels.ts +1 -0
  108. package/templates/runtime/react/index.ts +4 -0
  109. package/templates/runtime/react/model-rendering/model-export.ts +1 -1
  110. package/templates/runtime/react/orientation-gizmo/orientation-gizmo-selection.ts +5 -5
  111. package/templates/runtime/react/orientation-gizmo/use-toolcraft-orientation-control-selection.ts +2 -2
  112. package/templates/runtime/react/panel-host/panel-host-runtime-placement.test.tsx +30 -0
  113. package/templates/runtime/react/panel-host/panel-host.tsx +4 -0
  114. package/templates/runtime/scene/scene-bounds.test.ts +23 -0
  115. package/templates/runtime/scene/scene-bounds.ts +32 -19
  116. package/templates/runtime/schema/app-capabilities.test.ts +4 -0
  117. package/templates/runtime/schema/canvas-render-scale.ts +62 -0
  118. package/templates/runtime/schema/collection-item-controls.ts +29 -0
  119. package/templates/runtime/schema/control-applicability.test.ts +127 -0
  120. package/templates/runtime/schema/control-applicability.ts +433 -0
  121. package/templates/runtime/schema/control-schema-normalization.ts +177 -11
  122. package/templates/runtime/schema/controls-panel-actions.ts +2 -2
  123. package/templates/runtime/schema/controls-panel-section-id.test.ts +1 -1
  124. package/templates/runtime/schema/controls-panel-section-layout.ts +14 -9
  125. package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +62 -3
  126. package/templates/runtime/schema/define-toolcraft.collection-actions-item-controls.test.ts +127 -0
  127. package/templates/runtime/schema/define-toolcraft.control-sections.test.ts +10 -4
  128. package/templates/runtime/schema/define-toolcraft.file-drop-item-controls.test.ts +98 -0
  129. package/templates/runtime/schema/define-toolcraft.file-drop-normalization.test.ts +27 -0
  130. package/templates/runtime/schema/define-toolcraft.segmented-control-fit.test.ts +20 -2
  131. package/templates/runtime/schema/define-toolcraft.setup-background.test.ts +1 -1
  132. package/templates/runtime/schema/define-toolcraft.setup-canvas.test.ts +16 -3
  133. package/templates/runtime/schema/define-toolcraft.setup-render-scale-timeline.test.ts +71 -3
  134. package/templates/runtime/schema/define-toolcraft.source-collection.test.ts +79 -0
  135. package/templates/runtime/schema/define-toolcraft.ts +1 -1
  136. package/templates/runtime/schema/runtime-setup-section.ts +24 -5
  137. package/templates/runtime/schema/schema-resolvers.ts +0 -56
  138. package/templates/runtime/schema/types.ts +72 -17
  139. package/templates/runtime/state/canvas-background-state.ts +6 -0
  140. package/templates/runtime/testing/performance-render-plan-integration.test.ts +64 -0
  141. package/templates/runtime/testing/performance-renderer-pipeline-validation.ts +18 -1
  142. package/templates/starter/AGENTS.md +18 -15
  143. package/templates/starter/NOTICE.md +6 -0
  144. package/templates/starter/docs/toolcraft/README.md +2 -1
  145. package/templates/starter/docs/toolcraft/acceptance-testing.md +23 -35
  146. package/templates/starter/docs/toolcraft/agent-worklog.md +18 -3
  147. package/templates/starter/docs/toolcraft/assembly-workflow.md +13 -5
  148. package/templates/starter/docs/toolcraft/component-rules.md +8 -6
  149. package/templates/starter/docs/toolcraft/core/control-selection.md +9 -3
  150. package/templates/starter/docs/toolcraft/core/layout.md +7 -7
  151. package/templates/starter/docs/toolcraft/core/media-upload.md +4 -2
  152. package/templates/starter/docs/toolcraft/core/performance.md +14 -3
  153. package/templates/starter/docs/toolcraft/core/runtime-boundary.md +16 -3
  154. package/templates/starter/docs/toolcraft/core/setup-export.md +49 -19
  155. package/templates/starter/docs/toolcraft/core/timeline-animation.md +4 -4
  156. package/templates/starter/docs/toolcraft/custom-controls.md +6 -4
  157. package/templates/starter/docs/toolcraft/decision-contract.md +3 -1
  158. package/templates/starter/docs/toolcraft/performance.md +20 -6
  159. package/templates/starter/docs/toolcraft/renderer-technique.md +5 -1
  160. package/templates/starter/docs/toolcraft/schema-reference.md +23 -25
  161. package/templates/starter/docs/toolcraft/workflow.md +7 -2
  162. package/templates/starter/e2e/app-browser-control-applicability-requirements.spec.ts +163 -0
  163. package/templates/starter/e2e/app-browser-control-coverage.spec.ts +33 -0
  164. package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +50 -3
  165. package/templates/starter/e2e/app-browser-orientation-evidence.spec.ts +174 -21
  166. package/templates/starter/e2e/app-browser-render-scale-evidence.spec.ts +60 -6
  167. package/templates/starter/e2e/app-browser-render-scale-requirements.spec.ts +77 -1
  168. package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +8 -0
  169. package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +35 -0
  170. package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +5 -34
  171. package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +61 -16
  172. package/templates/starter/e2e/app-browser-shell.spec.ts +13 -5
  173. package/templates/starter/e2e/app-performance-path-adapters.ts +8 -1
  174. package/templates/starter/e2e/app-performance.spec.ts +16 -9
  175. package/templates/starter/e2e/{browser-conditional-output-evidence-helpers.ts → browser-background-output-evidence.ts} +0 -68
  176. package/templates/starter/e2e/browser-control-applicability-evidence.ts +114 -0
  177. package/templates/starter/e2e/browser-infinity-canvas-evidence.ts +29 -341
  178. package/templates/starter/e2e/browser-infinity-canvas-unavailable-image-evidence.ts +370 -0
  179. package/templates/starter/e2e/browser-media-export-evidence.spec.ts +77 -0
  180. package/templates/starter/e2e/browser-media-export-evidence.ts +208 -0
  181. package/templates/starter/e2e/browser-orientation-gizmo-evidence-helpers.ts +4 -0
  182. package/templates/starter/e2e/browser-orientation-gizmo-live-preconditions.ts +86 -0
  183. package/templates/starter/e2e/browser-render-scale-evidence.ts +37 -29
  184. package/templates/starter/e2e/browser-runtime-applicability-requirements.ts +84 -0
  185. package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +13 -3
  186. package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +72 -35
  187. package/templates/starter/e2e/browser-semantic-evidence-test-helpers.ts +25 -0
  188. package/templates/starter/e2e/browser-standard-timeline-evidence.ts +106 -0
  189. package/templates/starter/e2e/decoded-pixel-observation.spec.ts +74 -0
  190. package/templates/starter/e2e/decoded-pixel-observation.ts +227 -0
  191. package/templates/starter/e2e/export-artifact-helpers.ts +206 -25
  192. package/templates/starter/e2e/image-artifact-inspection.spec.ts +41 -0
  193. package/templates/starter/e2e/image-artifact-inspection.ts +99 -0
  194. package/templates/starter/e2e/performance-canvas-helpers.ts +22 -21
  195. package/templates/starter/e2e/performance-canvas-quality-guard.spec.ts +312 -0
  196. package/templates/starter/e2e/performance-canvas-quality-guard.ts +196 -0
  197. package/templates/starter/e2e/performance-canvas-quality-observer.ts +351 -0
  198. package/templates/starter/e2e/performance-control-layout-helpers.ts +2 -2
  199. package/templates/starter/e2e/performance-path-adapter-contract.ts +4 -4
  200. package/templates/starter/e2e/performance-path-helpers.spec.ts +203 -70
  201. package/templates/starter/e2e/performance-path-helpers.ts +210 -91
  202. package/templates/starter/e2e/performance-pipeline-evidence-continuity.spec.ts +76 -0
  203. package/templates/starter/e2e/performance-pipeline-evidence-test-fixtures.ts +11 -2
  204. package/templates/starter/e2e/performance-pipeline-invariants.ts +47 -4
  205. package/templates/starter/e2e/performance-render-scale-runner.spec.ts +140 -38
  206. package/templates/starter/e2e/video-artifact-inspection.spec.ts +64 -0
  207. package/templates/starter/e2e/video-artifact-inspection.ts +281 -0
  208. package/templates/starter/gitignore +1 -0
  209. package/templates/starter/package.json +1 -0
  210. package/templates/starter/scripts/check-toolcraft-docs.mjs +17 -0
  211. package/templates/starter/scripts/toolcraft-contract-manifest.json +1 -0
  212. package/templates/starter/scripts/toolcraft-delivery-plan-authority.test.mjs +60 -0
  213. package/templates/starter/scripts/toolcraft-delivery-plan-errors.test.mjs +7 -2
  214. package/templates/starter/scripts/toolcraft-delivery-plan.mjs +7 -3
  215. package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +95 -103
  216. package/templates/starter/scripts/toolcraft-product-boundary-module-policy.mjs +101 -0
  217. package/templates/starter/scripts/toolcraft-product-boundary.mjs +12 -0
  218. package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +0 -26
  219. package/templates/starter/scripts/toolcraft-product-control-bindings.mjs +182 -0
  220. package/templates/starter/scripts/toolcraft-product-control-boundary.mjs +146 -0
  221. package/templates/starter/scripts/toolcraft-product-control-boundary.test.mjs +186 -0
  222. package/templates/starter/scripts/toolcraft-product-evidence-boundary.test.mjs +85 -20
  223. package/templates/starter/scripts/toolcraft-product-evidence-import-policy.mjs +43 -0
  224. package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +157 -0
  225. package/templates/starter/scripts/toolcraft-product-export-boundary.test.mjs +196 -0
  226. package/templates/starter/scripts/toolcraft-typescript-analysis.d.mts +73 -0
  227. package/templates/starter/scripts/toolcraft-typescript-source-evidence-structure.test.mjs +20 -0
  228. package/templates/starter/scripts/toolcraft-typescript-source-evidence.mjs +1 -0
  229. package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade-test-helpers.mjs +318 -0
  230. package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +157 -206
  231. package/templates/starter/scripts/toolcraft-verification-inventory.mjs +1 -0
  232. package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +51 -0
  233. package/templates/starter/scripts/toolcraft-vite-env-activation.test.mjs +128 -59
  234. package/templates/starter/src/app/acceptance/artifact-export-intent.ts +130 -0
  235. package/templates/starter/src/app/acceptance/conditions.ts +1 -1
  236. package/templates/starter/src/app/acceptance/control-acceptance-context.ts +2 -2
  237. package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +6 -20
  238. package/templates/starter/src/app/acceptance/control-acceptance-kind-rules.ts +24 -5
  239. package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +2 -13
  240. package/templates/starter/src/app/acceptance/control-applicability-cases.test.ts +321 -0
  241. package/templates/starter/src/app/acceptance/control-applicability-cases.ts +290 -0
  242. package/templates/starter/src/app/acceptance/control-applicability.ts +332 -0
  243. package/templates/starter/src/app/acceptance/control-layout-dependency-rules.ts +20 -9
  244. package/templates/starter/src/app/acceptance/control-layout-entity-rules.ts +4 -6
  245. package/templates/starter/src/app/acceptance/control-layout-model.ts +4 -4
  246. package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +3 -10
  247. package/templates/starter/src/app/acceptance/control-parts.ts +8 -0
  248. package/templates/starter/src/app/acceptance/control-section-entity-cohesion.test.ts +215 -0
  249. package/templates/starter/src/app/acceptance/control-section-entity-cohesion.ts +132 -0
  250. package/templates/starter/src/app/acceptance/control-section-inventory.test.ts +87 -0
  251. package/templates/starter/src/app/acceptance/control-section-inventory.ts +74 -44
  252. package/templates/starter/src/app/acceptance/custom-controls.ts +11 -3
  253. package/templates/starter/src/app/acceptance/export-artifact-coverage.ts +113 -0
  254. package/templates/starter/src/app/acceptance/inline-layout.ts +64 -9
  255. package/templates/starter/src/app/acceptance/media-upload.ts +5 -1
  256. package/templates/starter/src/app/acceptance/orientation-gizmo.ts +18 -11
  257. package/templates/starter/src/app/acceptance/output-background-rules.ts +2 -2
  258. package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +18 -10
  259. package/templates/starter/src/app/acceptance/output-export-model.ts +54 -11
  260. package/templates/starter/src/app/acceptance/output-export.ts +35 -12
  261. package/templates/starter/src/app/acceptance/output-video-export-rules.ts +99 -0
  262. package/templates/starter/src/app/acceptance/types.ts +30 -8
  263. package/templates/starter/src/app/acceptance/validate-coverage.ts +20 -2
  264. package/templates/starter/src/app/starter-acceptance.artifact-export-intent.test.ts +239 -0
  265. package/templates/starter/src/app/starter-acceptance.background-export.test.ts +33 -0
  266. package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +16 -1
  267. package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +65 -0
  268. package/templates/starter/src/app/starter-acceptance.contract-fixtures.test.ts +41 -0
  269. package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +112 -16
  270. package/templates/starter/src/app/starter-acceptance.control-applicability.test.ts +224 -0
  271. package/templates/starter/src/app/starter-acceptance.control-order.test.ts +58 -3
  272. package/templates/starter/src/app/starter-acceptance.control-state.test.ts +0 -111
  273. package/templates/starter/src/app/starter-acceptance.custom-control-collections.test.ts +3 -1
  274. package/templates/starter/src/app/starter-acceptance.custom-control-valid.test.ts +1 -1
  275. package/templates/starter/src/app/starter-acceptance.export-artifact.test.ts +131 -0
  276. package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +22 -0
  277. package/templates/starter/src/app/{starter-acceptance.image-video-export-settings.test.ts → starter-acceptance.image-export-settings.test.ts} +37 -9
  278. package/templates/starter/src/app/starter-acceptance.interaction-ownership.test.ts +12 -0
  279. package/templates/starter/src/app/starter-acceptance.keyframes.test.ts +14 -4
  280. package/templates/starter/src/app/starter-acceptance.media-upload.fixtures.ts +11 -1
  281. package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +28 -0
  282. package/templates/starter/src/app/starter-acceptance.output-export-intent.test.ts +384 -0
  283. package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +46 -1
  284. package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +112 -105
  285. package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +12 -0
  286. package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +1 -1
  287. package/templates/starter/src/app/starter-acceptance.section-dependencies.test.ts +35 -24
  288. package/templates/starter/src/app/starter-acceptance.section-size.test.ts +72 -0
  289. package/templates/starter/src/app/starter-acceptance.ts +13 -2
  290. package/templates/starter/src/app/starter-acceptance.video-export-settings.test.ts +336 -0
  291. package/templates/starter/src/app/starter-acceptance.view-interaction.test.ts +8 -0
  292. package/templates/starter/src/app/starter-performance-test-utils.ts +103 -0
  293. package/templates/starter/src/app/starter-performance.gates.test.ts +231 -278
  294. package/templates/starter/src/app/starter-performance.lifecycle.test.ts +261 -0
  295. package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +4 -2
  296. package/templates/starter/src/routes/index.tsx +2 -0
  297. package/templates/ui/components/composites/tabs.tsx +2 -2
  298. package/templates/ui/components/controls/collection-actions/collection-item-groups.test.tsx +38 -0
  299. package/templates/ui/components/controls/collection-actions/collection-item-groups.tsx +36 -0
  300. package/templates/ui/components/controls/collection-actions/index.ts +2 -0
  301. package/templates/ui/components/controls/file-drop/file-drop-collection-control.tsx +137 -0
  302. package/templates/ui/components/controls/file-drop/file-drop-control.test.tsx +189 -0
  303. package/templates/ui/components/controls/file-drop/file-drop-control.tsx +81 -88
  304. package/templates/ui/components/controls/file-drop/file-drop-presentation.tsx +131 -9
  305. package/templates/ui/components/controls/file-drop/file-drop-types.ts +36 -22
  306. package/templates/ui/components/controls/file-drop/index.ts +1 -0
  307. package/templates/ui/components/controls/index.ts +3 -0
  308. package/templates/ui/components/controls/range-slider/range-slider-control.tsx +1 -1
  309. package/templates/ui/components/controls/range-slider/range-slider-value.test.ts +14 -0
  310. package/templates/ui/components/controls/range-slider/range-slider-value.ts +3 -2
  311. package/templates/runtime/export/export.ts +0 -166
  312. package/templates/starter/src/app/acceptance/condition-exclusivity.test.ts +0 -60
  313. package/templates/starter/src/app/acceptance/condition-exclusivity.ts +0 -221
@@ -1,7 +1,7 @@
1
1
  import type {
2
2
  ToolcraftBuiltInControlType as RuntimeToolcraftBuiltInControlType,
3
3
  ToolcraftControlOrderRole,
4
- ToolcraftControlSchema,
4
+ ResolvedToolcraftControlSchema,
5
5
  ToolcraftPersistableStateSlice,
6
6
  } from "@repo/toolcraft-runtime";
7
7
  import { TOOLCRAFT_BUILT_IN_CONTROL_TYPES } from "@repo/toolcraft-runtime";
@@ -58,6 +58,10 @@ export type ToolcraftAcceptanceEvidence =
58
58
  | "timeline-output"
59
59
  | "viewport-side-effect";
60
60
 
61
+ export type ToolcraftExportArtifactCoverage =
62
+ | "all-required-image-export-behavior"
63
+ | "all-required-video-export-behavior";
64
+
61
65
  export type ToolcraftReferenceCoverage =
62
66
  | "canvas-sizing"
63
67
  | "control-mapping"
@@ -98,8 +102,6 @@ export type ToolcraftPersistenceCoverage = "reload";
98
102
 
99
103
  export type ToolcraftSettingsTransferCoverage = "opt-out";
100
104
 
101
- export type ToolcraftConditionalVisibilityCoverage = "hidden" | "visible";
102
-
103
105
  export type ToolcraftOrientationGizmoCoverage =
104
106
  | "axis-drag"
105
107
  | "axis-snap"
@@ -195,6 +197,9 @@ export type ToolcraftControlPartCoverage =
195
197
  | "anchorGrid.position"
196
198
  | "channelMixer.activeChannel"
197
199
  | "channelMixer.values"
200
+ | "collectionActions.add"
201
+ | "collectionActions.items"
202
+ | "collectionActions.remove"
198
203
  | "curves.activeChannel"
199
204
  | "curves.points"
200
205
  | "colorOpacity.hex"
@@ -218,6 +223,7 @@ export type ToolcraftControlPartCoverage =
218
223
  | "rangeInput.start"
219
224
  | "rangeSlider.lower"
220
225
  | "rangeSlider.upper"
226
+ | "sourceCollection.items"
221
227
  | "vector.x"
222
228
  | "vector.y";
223
229
 
@@ -268,12 +274,27 @@ export type ToolcraftTransferMode =
268
274
  videoReferenceStudy?: ToolcraftVideoReferenceStudyEvidence;
269
275
  };
270
276
 
277
+ export type ToolcraftImageExportIntent =
278
+ | Readonly<{ mode: "toolcraft-default" }>
279
+ | Readonly<{ evidence: string; mode: "user-requested" }>
280
+ | Readonly<{ evidence: string; mode: "user-removed" }>;
281
+
282
+ export type ToolcraftVideoExportIntent =
283
+ | Readonly<{ mode: "not-requested" }>
284
+ | Readonly<{ evidence: string; mode: "user-requested" }>;
285
+
286
+ export type ToolcraftArtifactExportIntent = Readonly<{
287
+ image: ToolcraftImageExportIntent;
288
+ video: ToolcraftVideoExportIntent;
289
+ }>;
290
+
271
291
  export type ToolcraftProductReadiness =
272
292
  | {
273
293
  mode: "starter";
274
294
  reason: string;
275
295
  }
276
296
  | {
297
+ exportIntent: ToolcraftArtifactExportIntent;
277
298
  mode: "product";
278
299
  interactionOwnership: readonly ToolcraftInteractionOwnershipEntry[];
279
300
  productName: string;
@@ -290,6 +311,9 @@ export type ToolcraftComponentAcceptance = {
290
311
  browserTestName: string;
291
312
  componentType: string;
292
313
  evidence: ToolcraftAcceptanceEvidence;
314
+ exportArtifactCoverage?:
315
+ | ToolcraftExportArtifactCoverage
316
+ | readonly ToolcraftExportArtifactCoverage[];
293
317
  expectedObservable: string;
294
318
  fixture: string;
295
319
  id: string;
@@ -335,13 +359,10 @@ export type ToolcraftComponentAcceptance = {
335
359
  | "all-required-background-output"
336
360
  | readonly ToolcraftBackgroundOutputCoverage[];
337
361
  userAction: string;
338
- visibilityCoverage?:
339
- | "all-conditional-visibility"
340
- | readonly ToolcraftConditionalVisibilityCoverage[];
341
362
  };
342
363
 
343
364
  export type ToolcraftVisibleControl = {
344
- control: ToolcraftControlSchema;
365
+ control: ResolvedToolcraftControlSchema;
345
366
  controlId: string;
346
367
  sectionTitle?: string;
347
368
  };
@@ -356,7 +377,8 @@ export type ToolcraftControlOrderItem = {
356
377
  };
357
378
 
358
379
  export type ToolcraftControlSectionInventoryEntry = {
359
- entity?: string;
380
+ entity: string;
381
+ entityId: string;
360
382
  groupingReason: string;
361
383
  id: string;
362
384
  splitReason?: string;
@@ -5,11 +5,13 @@ import {
5
5
  getToolcraftAnimationModeChoiceErrors,
6
6
  } from "./animation-intent";
7
7
  import { getToolcraftControlAcceptanceErrors } from "./control-acceptance";
8
+ import { getToolcraftControlApplicabilityErrors } from "./control-applicability";
8
9
  import {
9
10
  getToolcraftControlSectionHeuristicErrors,
10
11
  getToolcraftControlSectionInvariantErrors,
11
12
  } from "./control-layout";
12
13
  import { getToolcraftControlOrderErrors } from "./control-order";
14
+ import { getToolcraftControlSectionEntityCohesionErrors } from "./control-section-entity-cohesion";
13
15
  import { getToolcraftControlSectionInventoryErrors } from "./control-section-inventory";
14
16
  import { isToolcraftVisibleAcceptanceControl } from "./controls";
15
17
  import { getToolcraftInlineLayoutErrors } from "./inline-layout";
@@ -146,12 +148,27 @@ const toolcraftAcceptanceValidators: readonly ToolcraftAcceptanceValidator[] = [
146
148
  ruleId: "controls-product-coverage",
147
149
  validate: ({ schema }) => getToolcraftOrientationGizmoErrors(schema),
148
150
  },
151
+ {
152
+ path: "schema.panels.controls.sections[].controls[].applicability",
153
+ ruleId: "controls-product-coverage",
154
+ validate: ({ controls, productReadiness }) =>
155
+ getToolcraftControlApplicabilityErrors({
156
+ controls,
157
+ productReadiness,
158
+ }),
159
+ },
149
160
  {
150
161
  path: "starterControlSectionInventory",
151
162
  ruleId: "controls-section-inventory-required",
152
163
  validate: ({ schema, sectionInventory }) =>
153
164
  getToolcraftControlSectionInventoryErrors(schema, sectionInventory),
154
165
  },
166
+ {
167
+ path: "starterControlSectionInventory",
168
+ ruleId: "controls-section-inventory-required",
169
+ validate: ({ sectionInventory }) =>
170
+ getToolcraftControlSectionEntityCohesionErrors(sectionInventory),
171
+ },
155
172
  {
156
173
  path: "schema.panels.controls.sections[].layoutGroups",
157
174
  ruleId: "controls-component-layout-invariants",
@@ -160,10 +177,11 @@ const toolcraftAcceptanceValidators: readonly ToolcraftAcceptanceValidator[] = [
160
177
  {
161
178
  path: "schema.export",
162
179
  ruleId: "output-export-required",
163
- validate: ({ controls, hasVideoExportAction, schema }) =>
180
+ validate: ({ acceptance, controls, productReadiness, schema }) =>
164
181
  getToolcraftOutputExportErrors({
182
+ acceptance,
165
183
  controls,
166
- hasVideoExportAction,
184
+ productReadiness,
167
185
  schema,
168
186
  }),
169
187
  },
@@ -0,0 +1,239 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import {
4
+ getToolcraftArtifactExportIntentEvidenceErrors,
5
+ resolveToolcraftArtifactExportIntent,
6
+ validateToolcraftArtifactExportIntentCorrespondence,
7
+ } from "./acceptance/artifact-export-intent";
8
+ import type { ToolcraftArtifactExportIntent } from "./acceptance/types";
9
+
10
+ const deliveryCases: readonly Readonly<{
11
+ expected: Readonly<{
12
+ imageEnabled: boolean;
13
+ videoEnabled: boolean;
14
+ }>;
15
+ intent: ToolcraftArtifactExportIntent;
16
+ name: string;
17
+ }>[] = [
18
+ {
19
+ expected: { imageEnabled: true, videoEnabled: false },
20
+ intent: {
21
+ image: { mode: "toolcraft-default" },
22
+ video: { mode: "not-requested" },
23
+ },
24
+ name: "enables default image export without unrequested video export",
25
+ },
26
+ {
27
+ expected: { imageEnabled: true, videoEnabled: false },
28
+ intent: {
29
+ image: {
30
+ evidence: "The user explicitly requested PNG delivery.",
31
+ mode: "user-requested",
32
+ },
33
+ video: { mode: "not-requested" },
34
+ },
35
+ name: "enables explicitly requested image export",
36
+ },
37
+ {
38
+ expected: { imageEnabled: false, videoEnabled: false },
39
+ intent: {
40
+ image: {
41
+ evidence: "The user explicitly requested no image export.",
42
+ mode: "user-removed",
43
+ },
44
+ video: { mode: "not-requested" },
45
+ },
46
+ name: "disables explicitly removed image export",
47
+ },
48
+ {
49
+ expected: { imageEnabled: true, videoEnabled: true },
50
+ intent: {
51
+ image: { mode: "toolcraft-default" },
52
+ video: {
53
+ evidence: "The user explicitly requested MP4 delivery.",
54
+ mode: "user-requested",
55
+ },
56
+ },
57
+ name: "enables explicitly requested video export",
58
+ },
59
+ {
60
+ expected: { imageEnabled: true, videoEnabled: true },
61
+ intent: {
62
+ image: {
63
+ evidence: "The user explicitly requested PNG delivery.",
64
+ mode: "user-requested",
65
+ },
66
+ video: {
67
+ evidence: "The user explicitly requested MP4 delivery.",
68
+ mode: "user-requested",
69
+ },
70
+ },
71
+ name: "enables explicitly requested image and video export",
72
+ },
73
+ {
74
+ expected: { imageEnabled: false, videoEnabled: true },
75
+ intent: {
76
+ image: {
77
+ evidence: "The user explicitly requested no image export.",
78
+ mode: "user-removed",
79
+ },
80
+ video: {
81
+ evidence: "The user explicitly requested MP4 delivery.",
82
+ mode: "user-requested",
83
+ },
84
+ },
85
+ name: "keeps requested video export when image export is removed",
86
+ },
87
+ ];
88
+
89
+ const evidenceCases: readonly Readonly<{
90
+ expected: readonly string[];
91
+ intent: ToolcraftArtifactExportIntent;
92
+ name: string;
93
+ }>[] = [
94
+ {
95
+ expected: [],
96
+ intent: {
97
+ image: { mode: "toolcraft-default" },
98
+ video: { mode: "not-requested" },
99
+ },
100
+ name: "accepts default image and not-requested video modes",
101
+ },
102
+ {
103
+ expected: [],
104
+ intent: {
105
+ image: {
106
+ evidence: "The user explicitly requested PNG delivery.",
107
+ mode: "user-requested",
108
+ },
109
+ video: { mode: "not-requested" },
110
+ },
111
+ name: "accepts nonblank requested image evidence",
112
+ },
113
+ {
114
+ expected: [],
115
+ intent: {
116
+ image: {
117
+ evidence: "The user explicitly requested no image export.",
118
+ mode: "user-removed",
119
+ },
120
+ video: { mode: "not-requested" },
121
+ },
122
+ name: "accepts nonblank image removal evidence",
123
+ },
124
+ {
125
+ expected: [],
126
+ intent: {
127
+ image: { mode: "toolcraft-default" },
128
+ video: {
129
+ evidence: "The user explicitly requested MP4 delivery.",
130
+ mode: "user-requested",
131
+ },
132
+ },
133
+ name: "accepts nonblank requested video evidence",
134
+ },
135
+ {
136
+ expected: [
137
+ "Image export user-removed intent requires non-empty evidence.",
138
+ ],
139
+ intent: {
140
+ image: { evidence: " \n\t ", mode: "user-removed" },
141
+ video: { mode: "not-requested" },
142
+ },
143
+ name: "rejects blank image removal evidence",
144
+ },
145
+ {
146
+ expected: [
147
+ "Image export user-requested intent requires non-empty evidence.",
148
+ ],
149
+ intent: {
150
+ image: { evidence: " ", mode: "user-requested" },
151
+ video: { mode: "not-requested" },
152
+ },
153
+ name: "rejects blank requested image evidence",
154
+ },
155
+ {
156
+ expected: [
157
+ "Video export user-requested intent requires non-empty evidence.",
158
+ ],
159
+ intent: {
160
+ image: { mode: "toolcraft-default" },
161
+ video: { evidence: "\t", mode: "user-requested" },
162
+ },
163
+ name: "rejects blank requested video evidence",
164
+ },
165
+ {
166
+ expected: [
167
+ "Image export user-removed intent requires non-empty evidence.",
168
+ "Video export user-requested intent requires non-empty evidence.",
169
+ ],
170
+ intent: {
171
+ image: { evidence: " ", mode: "user-removed" },
172
+ video: { evidence: "\n", mode: "user-requested" },
173
+ },
174
+ name: "aggregates blank image and video evidence errors",
175
+ },
176
+ ];
177
+
178
+ describe("Toolcraft artifact export intent", () => {
179
+ it.each(deliveryCases)("$name", ({ expected, intent }) => {
180
+ const delivery = resolveToolcraftArtifactExportIntent(intent);
181
+
182
+ expect(delivery).toEqual(expected);
183
+ expect(Object.isFrozen(delivery)).toBe(true);
184
+ });
185
+
186
+ it.each(evidenceCases)("$name", ({ expected, intent }) => {
187
+ expect(getToolcraftArtifactExportIntentEvidenceErrors(intent)).toEqual(
188
+ expected,
189
+ );
190
+ });
191
+
192
+ it("validates enabled and disabled delivery against typed schema facts", () => {
193
+ expect(
194
+ validateToolcraftArtifactExportIntentCorrespondence({
195
+ hasImageExportAction: false,
196
+ hasImageExportSection: false,
197
+ hasVideoExportAction: true,
198
+ hasVideoExportSection: true,
199
+ intent: {
200
+ image: { mode: "toolcraft-default" },
201
+ video: { mode: "not-requested" },
202
+ },
203
+ }),
204
+ ).toEqual({
205
+ delivery: { imageEnabled: true, videoEnabled: false },
206
+ errors: [
207
+ 'Image export intent "toolcraft-default" requires an export-image panel action.',
208
+ 'Image export intent "toolcraft-default" requires an "Image Export" section.',
209
+ 'Video export intent "not-requested" must not have an export-video panel action.',
210
+ 'Video export intent "not-requested" must not have a "Video Export" section.',
211
+ ],
212
+ });
213
+ });
214
+
215
+ it("aggregates evidence and correspondence errors without prose inference", () => {
216
+ expect(
217
+ validateToolcraftArtifactExportIntentCorrespondence({
218
+ hasImageExportAction: true,
219
+ hasImageExportSection: true,
220
+ hasVideoExportAction: false,
221
+ hasVideoExportSection: false,
222
+ intent: {
223
+ image: { evidence: " ", mode: "user-removed" },
224
+ video: { evidence: "\t", mode: "user-requested" },
225
+ },
226
+ }),
227
+ ).toEqual({
228
+ delivery: { imageEnabled: false, videoEnabled: true },
229
+ errors: [
230
+ "Image export user-removed intent requires non-empty evidence.",
231
+ "Video export user-requested intent requires non-empty evidence.",
232
+ 'Image export intent "user-removed" must not have an export-image panel action.',
233
+ 'Image export intent "user-removed" must not have an "Image Export" section.',
234
+ 'Video export intent "user-requested" requires an export-video panel action.',
235
+ 'Video export intent "user-requested" requires a "Video Export" section.',
236
+ ],
237
+ });
238
+ });
239
+ });
@@ -1,5 +1,6 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
 
3
+ import type { ToolcraftProductReadiness } from "./acceptance/types";
3
4
  import { defineContractSchemaFixture, validateContractAcceptance } from "./starter-acceptance.contract-fixtures";
4
5
  import {
5
6
  makeBackgroundSection,
@@ -7,6 +8,33 @@ import {
7
8
  } from "./starter-acceptance.export-test-utils";
8
9
  import { makeControlAcceptance } from "./starter-acceptance.test-utils";
9
10
 
11
+ const imageExportProductReadiness: ToolcraftProductReadiness = {
12
+ exportIntent: {
13
+ image: { mode: "toolcraft-default" },
14
+ video: { mode: "not-requested" },
15
+ },
16
+ interactionOwnership: [],
17
+ mode: "product",
18
+ productName: "Background image export fixture",
19
+ productSummary: "A static image fixture for background export validation.",
20
+ requestedBehavior: "Export the image with configurable background output.",
21
+ viewInteraction: {
22
+ mode: "non-spatial",
23
+ reason: "The fixture renders a static two-dimensional image.",
24
+ },
25
+ };
26
+
27
+ const videoExportProductReadiness: ToolcraftProductReadiness = {
28
+ ...imageExportProductReadiness,
29
+ exportIntent: {
30
+ image: { mode: "toolcraft-default" },
31
+ video: {
32
+ evidence: "The background fixture explicitly exercises video background export.",
33
+ mode: "user-requested",
34
+ },
35
+ },
36
+ };
37
+
10
38
  describe("Toolcraft background export acceptance contract", () => {
11
39
  it("requires png export apps to expose background color and png background toggle controls", () => {
12
40
  const schemaWithoutBackgroundControls = defineContractSchemaFixture({
@@ -43,6 +71,7 @@ describe("Toolcraft background export acceptance contract", () => {
43
71
  expect(
44
72
  validateContractAcceptance({
45
73
  schema: schemaWithoutBackgroundControls,
74
+ productReadiness: imageExportProductReadiness,
46
75
  acceptance: [
47
76
  {
48
77
  actionCoverage: ["export.png"],
@@ -118,6 +147,7 @@ describe("Toolcraft background export acceptance contract", () => {
118
147
  expect(
119
148
  validateContractAcceptance({
120
149
  schema: schemaWithLegacyBackgroundControls,
150
+ productReadiness: imageExportProductReadiness,
121
151
  acceptance: [
122
152
  makeControlAcceptance("appearance.background", "color"),
123
153
  makeControlAcceptance("export.includeBackground", "switch"),
@@ -185,6 +215,7 @@ describe("Toolcraft background export acceptance contract", () => {
185
215
  });
186
216
  const errors = validateContractAcceptance({
187
217
  schema: schemaWithBackgroundControls,
218
+ productReadiness: imageExportProductReadiness,
188
219
  acceptance: [
189
220
  makeControlAcceptance("appearance.background", "color"),
190
221
  {
@@ -262,6 +293,7 @@ describe("Toolcraft background export acceptance contract", () => {
262
293
  expect(
263
294
  validateContractAcceptance({
264
295
  schema: schemaWithBackgroundControls,
296
+ productReadiness: imageExportProductReadiness,
265
297
  acceptance: [
266
298
  makeControlAcceptance("appearance.background", "color"),
267
299
  makeControlAcceptance("export.includeBackground", "switch"),
@@ -332,6 +364,7 @@ describe("Toolcraft background export acceptance contract", () => {
332
364
  expect(
333
365
  validateContractAcceptance({
334
366
  schema: schemaWithVideoExport,
367
+ productReadiness: videoExportProductReadiness,
335
368
  acceptance: [
336
369
  makeControlAcceptance("appearance.background", "color"),
337
370
  {
@@ -9,6 +9,10 @@ import { makeControlAcceptance } from "./starter-acceptance.test-utils";
9
9
  import type { ToolcraftProductReadiness } from "./acceptance/types";
10
10
 
11
11
  const infinityProductReadiness: ToolcraftProductReadiness = {
12
+ exportIntent: {
13
+ image: { mode: "toolcraft-default" },
14
+ video: { mode: "not-requested" },
15
+ },
12
16
  interactionOwnership: [],
13
17
  mode: "product",
14
18
  productName: "Infinity contract fixture",
@@ -20,6 +24,17 @@ const infinityProductReadiness: ToolcraftProductReadiness = {
20
24
  },
21
25
  };
22
26
 
27
+ const infinityVideoProductReadiness: ToolcraftProductReadiness = {
28
+ ...infinityProductReadiness,
29
+ exportIntent: {
30
+ image: { mode: "toolcraft-default" },
31
+ video: {
32
+ evidence: "The Infinity canvas fixture explicitly exercises video export bounds.",
33
+ mode: "user-requested",
34
+ },
35
+ },
36
+ };
37
+
23
38
  function createFixedOutputSchema({
24
39
  height = 1080,
25
40
  width = 1920,
@@ -167,7 +182,7 @@ describe("Toolcraft canvas sizing acceptance coverage", () => {
167
182
  validateContractAcceptance({
168
183
  schema: createEditableOutputSchema("export-video"),
169
184
  acceptance: [makeInfinityCanvasAcceptance("mode-and-restoration")],
170
- productReadiness: infinityProductReadiness,
185
+ productReadiness: infinityVideoProductReadiness,
171
186
  }),
172
187
  ).toEqual(
173
188
  expect.arrayContaining([
@@ -7,6 +7,71 @@ import {
7
7
  import { makeControlAcceptance } from "./starter-acceptance.test-utils";
8
8
 
9
9
  describe("starter acceptance compound control part coverage contract", () => {
10
+ it("distinguishes user-owned and source-owned collection parts", () => {
11
+ const collectionSchema = defineContractSchemaFixture({
12
+ canvas: { enabled: true },
13
+ panels: {
14
+ controls: {
15
+ sections: [
16
+ {
17
+ controls: {
18
+ editableColors: {
19
+ defaultValue: [{ hex: "#DFFF1A" }],
20
+ itemControl: { label: false, type: "color" },
21
+ target: "colors.editable",
22
+ type: "collectionActions",
23
+ },
24
+ editableLayers: {
25
+ defaultValue: [{ enabled: true, strength: 0.5 }],
26
+ itemControls: {
27
+ enabled: {
28
+ defaultValue: true,
29
+ label: "Enabled",
30
+ type: "switch",
31
+ },
32
+ strength: {
33
+ defaultValue: 0.5,
34
+ label: "Strength",
35
+ max: 1,
36
+ min: 0,
37
+ type: "slider",
38
+ },
39
+ },
40
+ itemLabel: "Layer",
41
+ target: "layers.editable",
42
+ type: "collectionActions",
43
+ },
44
+ sourceColors: {
45
+ defaultValue: [{ hex: "#8CFF3A" }],
46
+ itemControl: { label: false, type: "color" },
47
+ target: "colors.source",
48
+ type: "sourceCollection",
49
+ },
50
+ },
51
+ title: "Fill Sections",
52
+ },
53
+ ],
54
+ title: "Controls",
55
+ },
56
+ },
57
+ });
58
+ const acceptance = [
59
+ makeControlAcceptance("colors.editable", "collectionActions"),
60
+ makeControlAcceptance("layers.editable", "collectionActions"),
61
+ makeControlAcceptance("colors.source", "sourceCollection"),
62
+ ];
63
+
64
+ expect(
65
+ validateContractAcceptance({ schema: collectionSchema, acceptance }),
66
+ ).toEqual(
67
+ expect.arrayContaining([
68
+ "Fill Sections / editableColors (colors.editable) must declare controlPartCoverage for every semantic value part: collectionActions.add, collectionActions.remove, collectionActions.items.",
69
+ "Fill Sections / editableLayers (layers.editable) must declare controlPartCoverage for every semantic value part: collectionActions.add, collectionActions.remove, collectionActions.items.",
70
+ "Fill Sections / sourceColors (colors.source) must declare controlPartCoverage for every semantic value part: sourceCollection.items.",
71
+ ]),
72
+ );
73
+ });
74
+
10
75
  it("requires compound controls to cover every semantic value part", () => {
11
76
  const compoundSchema = defineContractSchemaFixture({
12
77
  canvas: { enabled: true },
@@ -20,6 +20,47 @@ const schema = {
20
20
  } satisfies ToolcraftAppSchema;
21
21
 
22
22
  describe("Toolcraft acceptance contract schema fixtures", () => {
23
+ it("authors neutral fixture controls explicitly without masking legacy input", () => {
24
+ const fixture = defineContractSchemaFixture({
25
+ canvas: { enabled: true },
26
+ panels: {
27
+ controls: {
28
+ sections: [
29
+ {
30
+ controls: {
31
+ legacy: {
32
+ target: "shape.legacy",
33
+ type: "slider",
34
+ visibleWhen: { equals: true, target: "shape.enabled" },
35
+ },
36
+ neutral: {
37
+ target: "shape.enabled",
38
+ type: "switch",
39
+ },
40
+ },
41
+ id: "shape",
42
+ title: "Shape",
43
+ },
44
+ ],
45
+ title: "Controls",
46
+ },
47
+ },
48
+ });
49
+ const controls = fixture.panels.controls?.sections.find(
50
+ (section) => section.id === "shape",
51
+ )?.controls;
52
+
53
+ expect(controls?.neutral?.applicability).toEqual({
54
+ mode: "always",
55
+ origin: "explicit",
56
+ });
57
+ expect(controls?.legacy?.applicability).toEqual({
58
+ all: [{ equals: true, target: "shape.enabled" }],
59
+ mode: "conditional",
60
+ origin: "legacy",
61
+ });
62
+ });
63
+
23
64
  it("opts unrelated unit fixtures out without changing the production default", () => {
24
65
  const productionDefault = defineToolcraft(schema);
25
66
  const contractFixture = defineContractSchemaFixture(schema);