@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
@@ -64,6 +64,12 @@ export function getToolcraftInfiniteCanvasBackgroundColor(
64
64
  return undefined;
65
65
  }
66
66
 
67
+ return getToolcraftRuntimeBackgroundColor(state);
68
+ }
69
+
70
+ export function getToolcraftRuntimeBackgroundColor(
71
+ state: ToolcraftState,
72
+ ): string | undefined {
67
73
  const background = getToolcraftRuntimeSetupBackgroundControls(state.schema);
68
74
  const value = background
69
75
  ? state.values[background.color.target] ?? background.color.defaultValue
@@ -34,6 +34,70 @@ describe("Toolcraft render plan integration", () => {
34
34
  );
35
35
  });
36
36
 
37
+ it("allows off-main retina rasterization to preserve exact backing during viewport zoom", () => {
38
+ const pass = createPass({
39
+ cacheKey: undefined,
40
+ cost: {
41
+ dimensions: ["output-units"],
42
+ frequency: "interaction",
43
+ relationship: "linear",
44
+ },
45
+ id: "viewport-raster",
46
+ inputs: ["canvas.viewport.zoom"],
47
+ invalidatedBy: ["canvas.viewport.zoom"],
48
+ kind: "rasterize",
49
+ lifecycle: { cache: "none", resourceScope: "interaction" },
50
+ quality: "retina",
51
+ runsOn: "worker",
52
+ });
53
+ const baseConfig = createEnvelopeConfig({ pass });
54
+ const rendererPipeline = {
55
+ ...baseConfig.rendererPipeline!,
56
+ interactionInvalidation: [
57
+ {
58
+ interaction: "viewport-zoom" as const,
59
+ invalidates: [pass.id],
60
+ targets: ["canvas.viewport.zoom"],
61
+ },
62
+ ],
63
+ };
64
+ const renderScaleSchema = {
65
+ ...testSchema,
66
+ canvas: {
67
+ ...testSchema.canvas,
68
+ renderScale: { ...testSchema.canvas.renderScale, enabled: true },
69
+ },
70
+ };
71
+ const errors = validateToolcraftPerformanceCoverage(
72
+ renderScaleSchema,
73
+ { ...baseConfig, rendererPipeline },
74
+ TOOLCRAFT_FUNCTIONAL_PERFORMANCE_COVERAGE_POLICY,
75
+ );
76
+
77
+ expect(errors).not.toContainEqual(
78
+ expect.stringContaining(
79
+ 'viewport-zoom must not invalidate expensive pass "viewport-raster"',
80
+ ),
81
+ );
82
+ expect(
83
+ validateToolcraftPerformanceCoverage(
84
+ renderScaleSchema,
85
+ {
86
+ ...baseConfig,
87
+ rendererPipeline: {
88
+ ...rendererPipeline,
89
+ passes: [{ ...pass, quality: "full" }],
90
+ },
91
+ },
92
+ TOOLCRAFT_FUNCTIONAL_PERFORMANCE_COVERAGE_POLICY,
93
+ ),
94
+ ).toContainEqual(
95
+ expect.stringContaining(
96
+ 'viewport-zoom must not invalidate expensive pass "viewport-raster"',
97
+ ),
98
+ );
99
+ });
100
+
37
101
  it.each(["memoized", "retained-resource"] as const)(
38
102
  "requires cacheKey for a composite pass with %s cache",
39
103
  (cache) => {
@@ -106,6 +106,22 @@ function hasPipelineReference(value: string): boolean {
106
106
  return value.trim().length > 0 && !vaguePipelineReferencePattern.test(value.trim());
107
107
  }
108
108
 
109
+ function isRetinaViewportZoomRaster(
110
+ schema: ResolvedToolcraftAppSchema,
111
+ interaction: ToolcraftPipelineInteraction,
112
+ pass: ToolcraftRenderPass,
113
+ ): boolean {
114
+ return (
115
+ interaction === "viewport-zoom" &&
116
+ schema.canvas.renderScale.enabled &&
117
+ pass.kind === "rasterize" &&
118
+ pass.quality === "retina" &&
119
+ (pass.runsOn === "worker" ||
120
+ pass.runsOn === "gpu" ||
121
+ pass.runsOn === "worker-or-gpu")
122
+ );
123
+ }
124
+
109
125
  function getPipelineReferenceErrors(
110
126
  passId: string,
111
127
  field: string,
@@ -317,7 +333,8 @@ function getRendererPipelineErrorsFromParsedPipeline(
317
333
 
318
334
  if (
319
335
  highFrequencyViewportInteractions.has(invalidation.interaction) &&
320
- expensiveRenderPassKinds.has(pass.kind)
336
+ expensiveRenderPassKinds.has(pass.kind) &&
337
+ !isRetinaViewportZoomRaster(schema, invalidation.interaction, pass)
321
338
  ) {
322
339
  errors.push(
323
340
  `rendererPipeline ${invalidation.interaction} must not invalidate expensive pass "${passId}" (${pass.kind}). Move viewport work to transforms/uniforms or explain it through a cheaper pass.`,
@@ -20,10 +20,10 @@ Process matching routes sequentially within the current phase and skip repeated
20
20
 
21
21
  1. Build through `defineToolcraft` and `ToolcraftApp`.
22
22
  2. Keep app state in Toolcraft runtime schema and commands.
23
- 3. Keep product output in `canvasContent`; never render app UI there. The signed host owns `ToolcraftApp`, bootstrap, routes, and global runtime styles; product code supplies only `ToolcraftAppComposition`. Model upload preserves supported authored appearance from standalone files, folders, and bounded ZIP packages; declare typed `modelPresentation`, using runtime presentation by default and checked consumers for custom presentation. `renderDefaultCanvasMedia={false}` never hides runtime model layers. If upload/import is part of the source-material flow, do not invent canvas placeholder artwork, CTA copy, helper text, fake sample output, or preset source designs before real content exists.
24
- 4. Use built-in Toolcraft controls before custom controls. Before controls or canvas interactions, declare typed `interactionOwnership`: user request, inspected reference, or product usability selects one primary surface for each operation; complementary operations may share related state, but canvas and panel must not mirror the same operation. Every product also declares typed `viewInteraction` before renderer code; a visible editable spatial scene defaults to `orbit` and uses schema `orientationGizmo` plus runtime model-orbit interaction. Fixed or timeline-owned cameras require an explicit user request or inspected-reference evidence.
25
- 5. Do not hand-compose runtime surfaces or render built-in control components directly in app code; use `ToolcraftApp`, schema controls, `canvasContent`, `controlRenderers`, `onPanelAction`, and runtime commands.
26
- 6. Before writing controls, make and export `starterControlSectionInventory`: each product controls section declares its title, product entity or workflow stage, targets, and grouping reason. Group by product meaning, not UI component type.
23
+ 3. Keep product output in `canvasContent`; never render app UI there. The signed host owns `ToolcraftApp`, bootstrap, routes, global runtime styles, and the finite/infinite product scene surface; product code supplies only `ToolcraftAppComposition`. Infinite custom raster/WebGL output declares `sceneBoundsProvider` and consumes `useToolcraftProductSceneFrame` instead of dormant finite `canvas.size`. A preview-only environment that must fill the complete Infinity viewport uses `infiniteCanvasContent`; it remains pointer-transparent and outside world transforms, scene bounds, and export. Model upload preserves supported authored appearance from standalone files, folders, and bounded ZIP packages; declare typed `modelPresentation`, using runtime presentation by default and checked consumers for custom presentation. `renderDefaultCanvasMedia={false}` never hides runtime model layers. If upload/import is part of the source-material flow, do not invent canvas placeholder artwork, CTA copy, helper text, fake sample output, or preset source designs before real content exists.
24
+ 4. Use built-in Toolcraft controls before custom controls. Use `sourceCollection` when a source/runtime workflow owns array cardinality and users edit existing built-in item values; use `collectionActions` when users own add/remove cardinality. Before controls or canvas interactions, declare typed `interactionOwnership`: user request, inspected reference, or product usability selects one primary surface for each operation; complementary operations may share related state, but canvas and panel must not mirror the same operation. Every product also declares typed `viewInteraction` before renderer code; a visible editable spatial scene defaults to `orbit` and uses schema `orientationGizmo` plus runtime model-orbit interaction. Fixed or timeline-owned cameras require an explicit user request or inspected-reference evidence.
25
+ 5. Do not hand-compose runtime surfaces or render built-in control components directly in app code; use `ToolcraftApp`, schema controls, `canvasContent`, `controlRenderers`, `onPanelAction`, and runtime commands. Product code never imports modules below `src/toolcraft/ui/components/controls/**` or substitutes native `color`, `range`, `file`, `checkbox`, `radio`, `select`, or `textarea` value models for schema controls. Product artifact surfaces must correspond exactly to required `productReadiness.exportIntent`; use `docs/toolcraft/core/setup-export.md` for the canonical export decision sequence.
26
+ 6. Before writing controls, export `starterControlSectionInventory`. Every product section declares stable `entityId`, human-readable `entity`, exact targets, and `groupingReason`. Every product control explicitly declares `applicability` as `always` or `conditional`; inactive branches are absent, and every visible finite sibling branch must prove the control's accepted product outcome. Keep one entity in one section through ten controls; sections with eight to ten controls declare `semanticGroup` on every control. Entities above ten controls split into balanced two-to-ten-control workflow stages that keep the same entity identity and declare unique `workflowStage` plus `splitReason`. Group by product meaning, never by UI component type or target namespace.
27
27
  7. Keep control `label` short but semantically sufficient with the nearest visible section/group context, and put product-specific behavior help in schema `description`; runtime renders the label help tooltip only when that description adds meaning beyond the label.
28
28
  8. Enable layers and timeline only when product behavior requires them, then test the real UI. Product animation loops are seamless forward-only by default: first and last frames stitch, direction does not reverse, and mirror/yoyo/ping-pong behavior requires explicit user intent.
29
29
  9. Animated preview renderers suspend or coalesce non-essential animation work during canvas drag, pan, pinch, zoom, and radar/center interactions, then resume without changing user playback state.
@@ -33,7 +33,7 @@ Process matching routes sequentially within the current phase and skip repeated
33
33
  13. Generated apps follow the mandatory runtime Setup, Infinity canvas/finite canvas sizing, render scale, Timeline switch, Background, Image Export, Video Export, and sticky action rules in `docs/toolcraft/core/setup-export.md`. Do not duplicate or reinterpret those controls in app-authored sections.
34
34
  14. Media uploads, image/file mode, source images, multi-upload sorting, default assets, and image transform actions follow `docs/toolcraft/core/media-upload.md`.
35
35
  15. Keep `docs/toolcraft/agent-worklog.md` current with a decision trail, product decisions, explicit reference inputs, evidence, verification, and risks. Reference-runtime-clone apps also declare `referenceStudy` plus `referenceFeatureInventory` so every inspected reference feature has feature-level behavior evidence and maps to Toolcraft implementation and acceptance coverage.
36
- 16. Prove every visible entity through acceptance, browser, and performance coverage. Browser acceptance and performance pass only when protected helpers emit matching runtime evidence after successful assertions; source-code spelling and acceptance prose are not outcome authority. Declare typed conditional-visibility and background-output coverage, then use their fixed protected browser recipes. Raster products with `canvas.renderScale` declare `renderScaleCoverage` for interaction and steady state, plus playback when timeline is enabled, and prove real backing pixels with `canvas-render-scale-backing`; clamping quality is a functional failure without measured performance. Generic acceptance outcomes prove command side effects only; use the fixed media, persistence, viewport, compound-control, layer, and timeline semantic recipes for specialized evidence.
36
+ 16. Prove every visible entity through acceptance, browser, and performance coverage. Browser acceptance and performance pass only when protected helpers emit matching runtime evidence after successful assertions; source-code spelling and acceptance prose are not outcome authority. Control applicability derives case-scoped presence/absence and product-outcome evidence from semantic section peers; background output keeps its fixed typed recipe. Raster products with `canvas.renderScale` declare `renderScaleCoverage` for interaction and steady state, plus playback when timeline is enabled, and prove real backing pixels with `canvas-render-scale-backing`; clamping quality is a functional failure without measured performance. Every measured path in a render-scale-enabled raster product proves actual CSS × devicePixelRatio × 2 backing after each measured phase. Generic acceptance outcomes prove command side effects only; use the fixed media, persistence, viewport, compound-control, layer, and timeline semantic recipes for specialized evidence.
37
37
  17. Performance planning follows one sequence: reachable controls and inputs; workload dimensions and enforced boundaries; pass cost, frequency, lifecycle, and invalidation; render-plan assessment and protected kernel benchmark when required; derived paths and combined fixtures; targeted functional/browser development checks; lifecycle-appropriate delivery proof. Keep `src/app/app-verification-impact.json` complete so later functional changes derive exact verification scope. Only exact request authority may create a measured targeted performance iteration. Details live in `docs/toolcraft/core/performance.md` and `docs/toolcraft/performance.md`.
38
38
  18. Custom renderer apps compile one canonical `rendererPipelineRegistration`, supply it through `ToolcraftAppComposition`, reuse that registration as `rendererPipeline` in performance assessment, and derive paths and fixtures from it. The neutral starter has no registration, runtime provider, or fixture adapters.
39
39
  19. Classify each coherent user-visible delivery batch with a verification tier before editing. Steering and fixes inside the same request stay in that batch. Use targeted checks for development feedback, then run the protected delivery gate once when the batch is ready.
@@ -42,7 +42,7 @@ Process matching routes sequentially within the current phase and skip repeated
42
42
 
43
43
  The generated folder starts as a neutral Toolcraft shell: canvas upload plus toolbar. It intentionally does not include demo controls, prompt fields, layers, or timeline. Do not treat test fixtures or documentation examples as product requirements. Add controls, timeline, layers, sticky actions, and custom renderers only after the requested product or reference app requires them; base workspace persistence already exists.
44
44
 
45
- When the folder becomes a real product, update `src/app/app-acceptance-data.ts` from `appProductReadiness.mode: "starter"` to `mode: "product"` and fill `productName`, `productSummary`, `requestedBehavior`, typed `interactionOwnership`, and typed `viewInteraction`. Compare canvas and panel for each operation that could plausibly live on either surface. A visible editable 3D scene uses `orbit`; `fixed-camera` and `timeline-camera` require explicit request/reference evidence. Renamed product folders are not allowed to keep neutral starter readiness.
45
+ When the folder becomes a real product, update `src/app/app-acceptance-data.ts` from `appProductReadiness.mode: "starter"` to `mode: "product"` and fill `productName`, `productSummary`, `requestedBehavior`, required typed `exportIntent`, typed `interactionOwnership`, and typed `viewInteraction`. Compare canvas and panel for each operation that could plausibly live on either surface. A visible editable 3D scene uses `orbit`; `fixed-camera` and `timeline-camera` require explicit request/reference evidence. Renamed product folders are not allowed to keep neutral starter readiness.
46
46
 
47
47
  ## License
48
48
 
@@ -119,11 +119,13 @@ These ids mirror `TOOLCRAFT_DECISION_CONTRACT` in `@/toolcraft/runtime`. Keep th
119
119
 
120
120
  - Use `defineToolcraft` from `@/toolcraft/runtime`.
121
121
  - Export an `appComposition` satisfying `ToolcraftAppComposition` from `src/app/app-composition.tsx`.
122
- - Keep product composition limited to `schema`, `canvasContent`, `controlRenderers`, `modelPresentation`, `onPanelAction`, `renderDefaultCanvasMedia`, and optional `rendererPipelineRegistration`; host `className` and `style` are not product extension points.
122
+ - Keep product composition limited to `schema`, `canvasContent`, `infiniteCanvasContent`, `controlRenderers`, `exportRenderer`, `sceneBoundsProvider`, `modelPresentation`, `onPanelAction`, `renderDefaultCanvasMedia`, and optional `rendererPipelineRegistration`; host `className` and `style` are not product extension points.
123
+ - Infinite product output fills the runtime-owned scene surface derived from `sceneBoundsProvider`. Raster/WebGL renderers call `useToolcraftProductSceneFrame` for backing size and coordinate translation; they never position a second bounds wrapper or use dormant finite `canvas.size` while infinite.
123
124
  - Custom renderers use one compiled `rendererPipelineRegistration` as the canonical declaration for runtime execution and new-envelope performance assessment. Product code receives only the disposal-free pipeline client through hooks and panel action context.
124
- - Do not import `ToolcraftApp`, low-level runtime surfaces, or built-in controls into product modules. The signed host renders the shell; product modules use schema controls and supported composition fields.
125
+ - Do not import `ToolcraftApp`, low-level runtime surfaces, built-in controls, or modules below `src/toolcraft/ui/components/controls/**` into product modules. Do not recreate schema control value models with native form elements. The signed host renders the shell; product modules use schema controls and supported composition fields.
125
126
  - Use `renderDefaultCanvasMedia={false}` when a custom renderer replaces generic image/file preview. This flag does not suppress runtime model layers; use typed `modelPresentation` custom mode with checked consumers for declared model targets.
126
- - Use `ToolcraftApp onPanelAction` for sticky footer product actions such as Generate, Apply, Export, Copy, or Download.
127
+ - Use `ToolcraftApp onPanelAction` for non-export sticky footer product actions such as Generate, Apply, Copy, or Download. Typed `export-image` and `export-video` actions are executed by the runtime from the shared `ToolcraftAppComposition.exportRenderer`.
128
+ - Product export renderers draw one deterministic scene-coordinate frame and return/await their real work. Product modules never allocate export canvases, choose encoders, encode blobs, create download URLs, or duplicate image/video composition.
127
129
  - Keep final app behavior in the schema and runtime command bus, not in isolated local control state.
128
130
  - For animated products, write an Animation Intent Inventory before coding: use top playback timeline for product transport, keyframes timeline for editable property animation, and no timeline only for explicitly autonomous decorative output with no video export. Any app with `Export Video` must enable the top Toolcraft timeline.
129
131
  - For keyframes timeline apps, renderers read keyframed settings through Toolcraft evaluated-value helpers/hooks. Do not parse timeline `valueLabel` strings or read raw `state.values` for keyframed targets.
@@ -172,7 +174,7 @@ Do not rerun `pnpm install` after every edit. Run it after fresh export, depende
172
174
 
173
175
  Do not run the full browser performance suite for Tier 0-2 edits.
174
176
 
175
- The automatic lifecycle is sequential. First product delivery uses bare `pnpm verify:delivery` for complete product contracts, one production build, full functional acceptance, and zero measured performance. Later delivery is functional-targeted: it compares the immediately previous and current semantic functional proof models and derives exact direct-owner, domain, and affected-unit-graph proof. A performance complaint may authorize one targeted iteration; a full audit remains explicit-only. The canonical selection and evidence rules live in `docs/toolcraft/workflow.md`, `docs/toolcraft/acceptance-testing.md`, and `docs/toolcraft/performance.md`; do not duplicate their algorithm here.
177
+ The automatic lifecycle is sequential. First product delivery uses bare `pnpm verify:delivery` for complete product contracts, one production build, full functional acceptance, and zero measured performance. Later delivery is functional-targeted: it compares the immediately previous and current semantic functional proof models and derives exact direct-owner, domain, and affected-unit-graph proof. Classifier output establishes complaint authority only, never path localization. For a localized performance complaint, select affected canonical paths and run one targeted iteration without clarification. When localization remains unresolved, regardless of whether classification is high-confidence `performance-iteration` or `needs-agent-judgment`, ask one user-facing question naming visible operations and offering targeted diagnosis or a complete review; unresolved localization creates neither performance-iteration intent nor canonical path authority, and internal path IDs are never user choices. A broad or unlocalizable problem may justify recommending the complete review in that single choice, but the user still chooses; an explicit complete-review request runs `pnpm verify:perf` directly. The canonical selection and evidence rules live in `docs/toolcraft/workflow.md`, `docs/toolcraft/acceptance-testing.md`, and `docs/toolcraft/performance.md`; do not duplicate their algorithm here.
176
178
 
177
179
  Feature loops after the first working version run only the smallest focused functional and browser checks while implementation is changing, then one bare `verify:delivery` at the coherent boundary. Do not rerun aggregate, export, or performance matrices after every edit. An unchanged `sourceHash` uses the protected fast path and does not recollect semantic proof inputs.
178
180
 
@@ -187,7 +189,7 @@ pnpm verify:delivery
187
189
  pnpm dev
188
190
  ```
189
191
 
190
- The protected runner selects first-delivery functional proof, later `functional-targeted` ownership-derived proof, or one complaint-authorized targeted performance iteration from protected state. `pnpm verify:perf` is the separate operator/CI full-audit command; run it only after an explicit user request or accepted agent offer, never as an inferred continuation of a complaint.
192
+ The protected runner selects first-delivery functional proof, later `functional-targeted` ownership-derived proof, or one localized-or-clarified targeted performance iteration from protected state. Classifier output alone never supplies path localization; unresolved localization creates neither performance-iteration intent nor canonical path authority regardless of classifier result. `pnpm verify:perf` is the separate operator/CI full-audit command; run it only after an explicit user request or accepted agent offer, never as an inferred continuation of a complaint.
191
193
 
192
194
  Use `pnpm install` before this final gate when the folder is fresh or dependencies changed.
193
195
 
@@ -202,14 +204,15 @@ The app is complete only when:
202
204
  - the Toolcraft runtime shell is present;
203
205
  - `canvasContent` contains product output only;
204
206
  - the runtime canvas backing remains visible behind product output;
205
- - every visible control affects runtime state and product output or a command side effect;
207
+ - infinite product output uses the runtime-owned product scene surface, exact provider bounds, and real edge-pixel proof without clipping to dormant finite `canvas.size`;
208
+ - every product control declares explicit applicability, every non-matching finite branch hides it, and every visible finite branch proves product output or the accepted command side effect;
206
209
  - reset returns schema controls to `defaultValue`;
207
210
  - sticky footer export actions operate on final product output at `state.canvas.size`;
208
- - every product exposes Export PNG; products whose requested delivery includes animation also expose Export Video;
211
+ - artifact actions and settings correspond exactly to `productReadiness.exportIntent`; image export is the product default, video requires explicit user-request evidence, and image removal requires explicit user-removal evidence;
209
212
  - PNG export uses the background controls normalized into runtime Setup: `Background` beside `Infinity canvas`, then `Background color`; live preview hides product background when Background is off, and video keeps background;
210
- - every PNG export includes `Image Export` format/resolution `select` controls, and passes `export.image.resolution` into `createToolcraftPngExportCanvas`;
213
+ - every PNG export includes `Image Export` format/resolution `select` controls; runtime resolves the selected settings and exact output size;
211
214
  - products with both PNG and video export place `Image Export` immediately before `Video Export`;
212
- - export paths use the standard export helpers: PNG uses selected image resolution or retina fallback, while video uses current canvas/output size or the selected 4K target;
215
+ - one shared `exportRenderer` draws product pixels for both image and video; runtime owns selected settings, scene crop, background, runtime media/model compositing, canvas allocation, encoding, download, progress, and typed errors;
213
216
  - layers are absent for single-layer apps and fully working when enabled;
214
217
  - timeline is absent, playback, keyframes, or custom reference timeline according to product behavior;
215
218
  - performance checks cover workload and responsiveness for all relevant controls;
@@ -6,3 +6,9 @@ starter, UI component, documentation, and template source code.
6
6
  Use of that Toolcraft code is governed by the MIT License in `LICENSE.md`.
7
7
  Product-specific design, content, configuration, and application code that you
8
8
  create remain yours.
9
+
10
+ ## Mediabunny
11
+
12
+ Video export uses Mediabunny 1.52.2, Copyright © 2026 Vanilagy,
13
+ licensed under the Mozilla Public License 2.0 (MPL-2.0).
14
+ Source: https://github.com/Vanilagy/mediabunny
@@ -40,7 +40,8 @@ Use focused tests while a coherent user-visible delivery batch is changing. Stee
40
40
 
41
41
  - **First product delivery:** bare `pnpm verify:delivery` proves complete product contracts, performs one production build, runs full functional acceptance, and runs no measured performance. It preserves any independent performance baseline.
42
42
  - **Later functional delivery:** the same bare command compares with the immediately previous successful delivery and derives exact ownership-required proof.
43
- - **Performance complaint:** record an exact request quote and canonical affected path IDs in the worklog, then run one bare delivery for one targeted iteration and return the verified app for evaluation.
43
+ - **Localized or clarified targeted work:** classifier output establishes complaint authority only and never path localization. Only a localized complaint or a post-clarification targeted choice records an exact request quote and canonical affected path IDs in the worklog, then one bare delivery runs one targeted iteration and returns the verified app for evaluation. Unresolved localization creates neither performance-iteration intent nor canonical path authority regardless of classifier result.
44
+ - **Adaptive complaint route:** a localized complaint lets the agent choose affected paths without a question; an ambiguous complaint gets one visible-operation choice between targeted diagnosis and a complete performance review; a broad problem may receive the same recommendation, while only an explicit request or accepted offer authorizes the full review.
44
45
  - **Full audit:** only an explicit operator request or accepted offer authorizes `pnpm verify:perf`, which performs one fresh build and the complete maximum-fixture performance matrix.
45
46
 
46
47
  Use the current AI agent's controlled browser for targeted diagnosis and visual checks.
@@ -26,9 +26,12 @@ The exported starter may keep `appProductReadiness.mode: "starter"` only while i
26
26
 
27
27
  - `productName`;
28
28
  - `productSummary`;
29
- - `requestedBehavior`.
29
+ - `requestedBehavior`;
30
+ - required `exportIntent`;
30
31
  - `viewInteraction`.
31
32
 
33
+ `productReadiness.exportIntent` is the typed authority for artifact delivery. Acceptance, schema actions, and export settings must correspond exactly to its resolved image and video capabilities. The evidence-bearing modes and decision sequence live in `core/setup-export.md`; do not infer export intent from animation or timeline state.
34
+
32
35
  `viewInteraction` classifies the product as `non-spatial`, `orbit`,
33
36
  `fixed-camera`, or `timeline-camera`. Editable spatial scenes default to orbit;
34
37
  fixed/timeline modes require explicit request/reference evidence.
@@ -82,6 +85,8 @@ The `e2e/app-browser-*` prefix is reserved for signed framework specs.
82
85
 
83
86
  Every runtime production module/resource has a direct owner in `src/app/app-verification-impact.json`; proof and test paths cannot own them. Each browser file owns one acceptance domain (the first ID segment). Later delivery compares semantic models and selects changed contracts, owners/domains, and product-unit tests—not filenames or reverse imports. Additive owner deltas select only new IDs; other deltas retain affected IDs.
84
87
 
88
+ Classifier output establishes complaint authority only; unresolved localization creates no intent/path regardless of result. Only localized/clarified work starts an iteration.
89
+
85
90
  Contract docs are signed except product-owned `agent-worklog.md` and optional `workflow-observation.md`; only the observation stays outside `sourceHash`.
86
91
 
87
92
  Framework meta-tests are product-invariant: their synthetic validator cases use protected neutral contract fixtures, never the editable app schema, product acceptance rows, transfer intent, or section inventory. Put exact product targets, defaults, option values, and product-specific expectations in separate app-owned tests. The product gates still read `app-schema.ts`, `app-acceptance-data.ts`, product test names, worklog evidence, and browser scenarios dynamically.
@@ -94,13 +99,13 @@ Slider and range slider rows must prove live behavior. Browser tests should drag
94
99
 
95
100
  ## Infinity Canvas Coverage
96
101
 
97
- Every editable-output product app proves `infinityCanvasCoverage` mode/restoration. When the standard Background pair exists, the fixed proof also changes Background color, verifies that the complete infinite viewport uses it, turns Background off to prove finite fallback plus a disabled Infinity switch, and turns Background back on to prove availability returns without enabling Infinity. PNG/video apps also prove decoded scene-bounds output (video uses one `timeRange` envelope) from `ToolcraftAppComposition.sceneBoundsProvider`; fixed recipes cover hidden/editor exclusion and exact empty, unavailable, and oversized failure codes. Full recipes live in `core/setup-export.md`.
102
+ Every editable-output app proves `infinityCanvasCoverage`. Background proof covers color, viewport, disable/restore, and finite size. Preview checks the runtime scene against its exact `sceneBoundsProvider` union and real edge pixels; app selectors fail. Raster backing follows `useToolcraftProductSceneFrame`, not dormant finite size. Image/video decode the same bounds; video unions scheduled states. Fixed recipes cover excluded, empty, unavailable, and oversized scenes. See `core/setup-export.md`.
98
103
 
99
104
  ## Render Scale Coverage
100
105
 
101
- With `canvas.renderScale: true`, add one browser row on `canvas.renderScale`: `renderScaleCoverage: { kind: "selected-backing-pixels", states: ["interaction", "steady"] }`; timeline uses `["interaction", "playback", "steady"]`.
106
+ For a raster product with render scale, add one `canvas.renderScale` browser row: `renderScaleCoverage: { kind: "selected-backing-pixels", states: ["interaction", "steady"] }`; timeline adds `"playback"`.
102
107
 
103
- Call `expectToolcraftCanvasRenderScaleEvidence` with transitions. It keeps CSS size, asserts backing `CSS × DPR × scale`, then emits `canvas-render-scale-backing`. A clamp is a functional failure without measured performance.
108
+ Run `expectToolcraftCanvasRenderScaleEvidence` per state. CSS size stays fixed and backing must equal `CSS × devicePixelRatio × selected scale` within one pixel before `canvas-render-scale-backing`; mismatch fails. Every measured path in that product proves exact `CSS × devicePixelRatio × 2` after each phase.
104
109
 
105
110
  Default local persistence requires one runtime row with `evidence: "persistence-state"`, `persistenceCoverage: "reload"`, and `persistenceSlices` equal to the resolved plan. Browser proof changes each slice, waits for status `success`, reloads, then verifies restored state and real output before evidence. Settings import/export is not reload proof.
106
111
 
@@ -115,6 +120,7 @@ Required parts:
115
120
  | `anchorGrid` | `anchorGrid.position` |
116
121
  | `channelMixer` | `channelMixer.activeChannel`, `channelMixer.values`; only for RGB channel matrix behavior |
117
122
  | `collectionActions` | `collectionActions.add`, `collectionActions.remove`, `collectionActions.items` |
123
+ | `sourceCollection` | `sourceCollection.items` |
118
124
  | `colorOpacity` | `colorOpacity.hex`, `colorOpacity.opacity` |
119
125
  | `curves` | RGB variant: `curves.activeChannel`, `curves.points`; `variant: "single"`: `curves.points` |
120
126
  | `fontPicker` | `fontPicker.fontId`, `fontPicker.fontWeight`, `fontPicker.fontSize`, `fontPicker.letterSpacing`, `fontPicker.lineHeight`, `fontPicker.textCase`, `fontPicker.color`, `fontPicker.opacity` |
@@ -147,6 +153,8 @@ choosing a fixed camera and thereby escaping gizmo acceptance.
147
153
 
148
154
  Use protected `expectToolcraftOrientationAxisDrag`/`AxisSnap`/`ModelDrag`/`CanvasMissPan`/`UndoReset` recipes. Axis drag finds blank circular background and performs the pointer drag; axis snap projects and clicks the requested endpoint from canonical pose. Evidence follows pose/output/ownership/history assertions. Arbitrary mutations, endpoint-only or generic drag, source spelling, and value changes do not qualify. Use `expectExportExcludesCanvasHandles` for export-clean proof.
149
155
 
156
+ `expectToolcraftOrientationAxisDrag` validates paused playback and maximum `canvas.renderScale` when those standard controls are present. Product tests prepare those states through real UI before capturing their baseline; the protected helper does not toggle playback or quality, so one drag remains one history transaction. This is functional browser proof, not measured performance evidence.
157
+
150
158
  ## Control Selection Gates
151
159
 
152
160
  Acceptance must catch wrong-substitution failures. If the prompt, spec, or app behavior needs a value model owned by a built-in control, the schema must use that built-in or include a documented built-in fit check.
@@ -157,7 +165,7 @@ High-confidence wrong-substitution cases:
157
165
  - typography without `fontPicker`;
158
166
  - sibling typography controls that split case, color, opacity, size, weight, letter spacing, or line height away from `fontPicker`;
159
167
  - color plus opacity without `colorOpacity`;
160
- - repeatable user-editable item sets without `collectionActions` or another justified collection owner;
168
+ - source-sized repeated item sets without `sourceCollection`, or user-editable cardinality without `collectionActions`;
161
169
  - from/to range without `rangeSlider` or `rangeInput`;
162
170
  - curve, remap, easing, or response without `curves`;
163
171
  - manual stable two-axis position, direction, focus, anchor, light, or vector parameters without `vector`;
@@ -179,34 +187,14 @@ A model `fileDrop` row declares `modelImportCoverage: "all-required-model-import
179
187
 
180
188
  Protected browser evidence imports every format plus folder/ZIP; proves first-root choice, runtime/custom readiness, nontransparent RGBA, and authored signatures versus fallback. Metadata, changed pose, or a canvas node is not proof. Fatal input keeps the prior commit. `Fix model` requires a deterministic topology plan and verified result; appearance warnings never expose it. Processing preview is `40%`; committed preview/export is `100%`. Both share document, appearance key, pose pixels, and omit gizmo chrome. Reload proves repository-backed appearance; corrupt refs become `unavailable`. History/reset proves removal, enabled undo/redo, and default restore through import.
181
189
 
182
- Rows that use custom controls must include `customControlCoverage` and typed `builtInFitCheck`.
183
-
184
- ```ts
185
- builtInFitCheck: {
186
- capabilities: [
187
- "collection",
188
- "reorder",
189
- "selection",
190
- "commands",
191
- "custom-value-model",
192
- ],
193
- checkedBuiltIns: ["fileDrop", "collectionActions", "imagePicker"],
194
- closestBuiltIn: "fileDrop",
195
- whyInsufficient:
196
- "FileDrop imports, previews, orders, and removes source files, but this product also needs per-glyph density thresholds stored with each item.",
197
- productObservable:
198
- "Changing a glyph density threshold changes which uploaded glyph renders for the same depth-map tone.",
199
- }
200
- ```
201
-
202
- The fit check declares broad typed capabilities, names real checked built-ins, the closest built-in or `"none"`, why it is insufficient, and the product-observable evidence that proves the custom control works. At least one of `custom-interaction`, `custom-value-model`, or `custom-visualization` is required; collection/command chrome alone does not justify custom UI.
190
+ Custom-control rows require `customControlCoverage` and typed `builtInFitCheck`; see `custom-controls.md` for the canonical shape. The fit check records capabilities, checked controls, the closest control (or `"none"`), the missing interaction, and observable proof. One `custom-*` capability is required; collection/command chrome alone is insufficient.
203
191
 
204
192
  A fit check containing `custom-interaction` also requires `interactionId` and a
205
193
  panel ownership entry. The fit check compares built-in controls; ownership
206
194
  separately proves why the operation belongs in the panel instead of directly on
207
195
  the canvas. Passing one gate never bypasses the other.
208
196
 
209
- For collection-like custom controls, the fit check must include `collectionActions` and `actions`. Collection-like is decided from the runtime value model and workflow: arrays, `{ items: [...] }` objects, selected-item state, grow/shrink item sets, ordering, add, remove, delete, or reorder behavior. Acceptance should fail if the row compares only unrelated built-ins such as `vector` or `select` while the actual value model is a collection.
197
+ Collection-like custom controls must check `sourceCollection` and `collectionActions`, plus `actions` when commands exist. Arrays, `{ items: [...] }`, selection, cardinality, ordering, or item commands establish collection behavior; product nouns and unrelated controls do not.
210
198
 
211
199
  Custom controls cannot be justified by icons, layout, styling, compactness, or custom buttons alone. `whyInsufficient` must name the product interaction or value model that built-ins cannot express.
212
200
 
@@ -224,25 +212,25 @@ Valid acceptance evidence includes:
224
212
  - changed timeline playback state plus rendered frame.
225
213
  - restored persisted value or product output after browser reload.
226
214
 
227
- Product apps must include output delivery acceptance. Every product needs `Export PNG` evidence. Apps whose requested delivery includes animation also need `Export Video` evidence; timeline playback or keyframes alone do not invent video delivery. Clipboard copy can be tested as an additional behavior, but it cannot replace export coverage.
215
+ Product apps include artifact acceptance only for the delivery enabled by `productReadiness.exportIntent`. Image-only products prove complete image coverage; image-plus-video products prove both; video-only products prove complete video coverage; explicit no-export products have no image/video artifact rows. Timeline playback, keyframes, or animation never add video acceptance. Clipboard copy can be tested as an additional behavior, but it cannot substitute for the recorded artifact intent.
228
216
 
229
217
  Export-content proof is distinct from export mechanics: content inspects selected artifact semantics; mechanics proves lifecycle, format, dimensions, transport, and errors. Neither substitutes.
230
218
 
231
- Every app with `Export PNG` must exercise the separate `Image Export` section: choose at least two `export.image.format` values, choose at least two `export.image.resolution` values, export the image, and decode the result to prove file type and actual pixel dimensions changed. Animated apps with both `Export PNG` and `Export Video` still need this image-export coverage; `Video Export` does not replace it.
219
+ Every app with `Export PNG` must exercise the separate `Image Export` section: choose at least two `export.image.format` values, choose at least two `export.image.resolution` values, export the image, and decode the result to prove file type and actual pixel dimensions changed. Apps with both `Export PNG` and explicitly requested `Export Video` still need this image-export coverage; `Video Export` does not replace it.
232
220
 
233
- Async Export, Download, Copy, Generate, or Apply acceptance must prove the sticky footer top accent indicator is visible while the returned `onPanelAction` Promise is pending, advances when `reportProgress(0..1)` is called, and hides after it settles. Video export acceptance must prove frame-based progress updates during render/encode instead of only toggling a pending state.
221
+ Runtime Export acceptance must prove the sticky footer top accent indicator advances through real render/encode/download work and hides only after the artifact settles. Async non-export Download, Copy, Generate, or Apply acceptance must prove the indicator is visible while the returned `onPanelAction` Promise is pending, advances when `reportProgress(0..1)` is called, and hides after it settles.
234
222
 
235
- Animated app acceptance must also exercise the separate `Video Export` section: choose at least two `export.video.format` values, choose at least two `export.video.resolution` values, verify unsupported MIME/container choices fall back safely, and assert exported video bytes, dimensions, MIME/container, and duration match runtime timeline state. `current` video export must use the current canvas/output size with even encoder-safe rounding. `4k` video export must use `getToolcraftVideoExportSize`, fit inside 3840x2160, preserve aspect ratio, and produce even dimensions; do not accept PNG-style 4096px long-edge video sizing. Recorder/encoder errors must reject instead of resolving corrupt blobs. The duration assertion must load the exported blob as a video, wait for metadata, and compare `video.duration` with the edited timeline duration; `blobSize > 0`, `blobType`, WebM parser fallback, or assigning the expected duration when metadata is missing are not enough.
223
+ Every video-enabled app exercises two video formats and resolutions. It proves real bytes, dimensions, actual MIME/container or typed capability failure, timeline duration, 30 FPS timestamps/durations from actual encoded packet metadata, decoded product motion, current even-safe sizing, and aspect-preserving 4K inside 3840x2160. Renderer/encoder/muxer errors reject; `blobSize`, metadata alone, assumed FPS, synthetic frame counts, or substituted expectations are invalid. Animated output requires distinct decoded frame hashes.
236
224
 
237
225
  Footer action acceptance must not include Reset. Reset is already available in the controls panel header and uses schema `defaultValue`; duplicating it in sticky `panelActions` fails acceptance.
238
226
 
239
227
  Local `actions` acceptance must click every visible action and prove the nearby entity changed through runtime state or product output. A section-level `Randomize palette` must change palette output, `Normalize weights` must change weights/output, and `Clear selection` must clear only the scoped selection. Do not accept a test that only proves the button rendered. A single-button `actions` control fails validation when the control label duplicates the button label; the label must add concise context. Visual acceptance rejects side-label actions; labels sit above a two-column button grid where each button cell is 50% width.
240
228
 
241
- `collectionActions` acceptance must click plus and minus in the real panel, prove the runtime target array length changes, prove `minItems` prevents invalid removal, prove `recommendedMaxItems` is not a hidden hard limit, and prove preview/export consumes the changed item list.
229
+ `collectionActions` keeps parts `collectionActions.add`, `collectionActions.remove`, `collectionActions.items`. Prove limits, full-default add, sibling-preserving edit, preview/export, and whole-record removal. `sourceCollection` proves source count, item edit, output, and no add/remove.
242
230
 
243
- PNG export tests must prove runtime background behavior: changing the background color affects preview/export and the complete infinite viewport, turning `export.includeBackground` off through the Setup `Background` switch exits infinite mode, disables Infinity, hides the live preview product background, and creates transparent PNG output; video export still keeps the background, turning Background on restores Infinity availability without enabling it and includes the current background color in PNG, and exported pixel dimensions are retina size, at least `state.canvas.size * 2`.
231
+ Image export proves background changes in preview/artifact/infinite viewport; Background off restores finite mode, disables Infinity, hides bounded preview background, and makes PNG transparent while JPEG/video stay opaque. Restoring it enables Infinity availability without entering that mode. Protected proof decodes real type, selected dimensions, product bounds/pixels, and pixel hash; bytes or dimensions alone are insufficient.
244
232
 
245
- Hard acceptance semantics are typed, not inferred from English prose. Every `visibleWhen` acceptance row declares `visibilityCoverage` for both `hidden` and `visible`; the protected conditional-visibility recipe must remove the dependent target from the rendered panel and restore it through the same target-scoped gating control. The `export.includeBackground` row declares `backgroundOutputCoverage` for preview exclusion and transparent image alpha, plus preserved video background when the schema exposes video export. Its protected recipe verifies the preview transition, decodes a non-empty image artifact and checks background alpha, and inspects video background behavior when applicable. `expectedObservable` and `userAction` remain human-readable context and may use any language; matching words such as “hidden”, “PNG”, or “video” never satisfy these requirements by themselves.
233
+ Hard acceptance semantics are typed, not inferred from English prose. Control applicability derives exact pairwise cases from the control's section-inventory peers for both `always` and `conditional` controls. Each non-matching case requires target absence. Each matching case requires target presence plus every existing product outcome on that acceptance row, under a canonical case-suffixed requirement ID. A missing predicate therefore cannot hide behind a passing default branch. The `export.includeBackground` row separately declares `backgroundOutputCoverage` for preview exclusion and transparent image alpha, plus preserved video background when the schema exposes video export. Its protected recipe verifies the preview transition, decodes a non-empty image artifact and checks background alpha, and inspects video background behavior when applicable. `expectedObservable` and `userAction` remain human-readable context and may use any language; matching words such as “hidden”, “PNG”, or “video” never satisfy these requirements by themselves.
246
234
 
247
235
  Invalid final acceptance evidence:
248
236
 
@@ -330,6 +318,6 @@ Performance browser tests use the derived path matrix. Each path has one browser
330
318
 
331
319
  ## Fixtures
332
320
 
333
- Use fixtures that make each behavior visible. For example, background character-size controls need visible background characters, transparency needs alpha-sensitive pixels, selected-layer controls need multiple layers, timeline controls need deterministic playback or keyframe fixtures, and mode-specific controls need fixtures for every mode branch. Conditional coverage must prove visible controls, inactive controls hidden with `visibleWhen`, preserved values after switching away and back, and renderer output for the active branch. Count-controlled control banks must test both the low-count UI state and the expanded-count UI state; the test fails if inactive controls remain visible while the renderer ignores them.
321
+ Use fixtures that make each behavior visible. For example, background character-size controls need visible background characters, transparency needs alpha-sensitive pixels, selected-layer controls need multiple layers, timeline controls need deterministic playback or keyframe fixtures, and mode-specific controls need fixtures for every mode branch. Applicability coverage proves matching controls visible, non-matching controls absent, values preserved after switching away and back, and the accepted renderer/export outcome in every visible finite sibling branch. Count-controlled control banks prove the numeric boundary states; the test fails if inactive controls remain visible or a visible control is ignored by the renderer.
334
322
 
335
323
  Generic hash differences are not enough for semantic controls. If a control promises a direction, test that direction.
@@ -12,13 +12,13 @@ The neutral starter has no product renderer, timeline, layers, export behavior,
12
12
 
13
13
  Keep this worklog human-shaped. For the first product delivery, record the request, decisions, state/output mapping, reference evidence, rejected alternatives, and known risks; one bare `pnpm verify:delivery` derives complete contract proof, one build, full functional acceptance, and no measured performance. For later `functional-targeted` delivery, record only the new intent and decisions; the same bare command derives exact ownership-required proof from protected state.
14
14
 
15
- A performance complaint adds only the domain authority below, then one bare `pnpm verify:delivery` runs one targeted iteration. A full audit remains separate and requires an explicit operator request or accepted offer before `pnpm verify:perf` may run. Protected receipts own changed files, plans, checks, reports, measurements, and pass/fail evidence.
15
+ Classifier output establishes complaint authority only and never path localization. A localized performance complaint adds the domain authority below, then one bare `pnpm verify:delivery` runs one targeted iteration. If localization remains unresolved regardless of classifier result, ask one user-facing question naming visible operations and offering targeted diagnosis or a complete review; record neither `performance-iteration` intent nor canonical path authority until the answer supplies exact localization evidence. Never ask the user to choose internal path IDs. A broad or honestly unlocalizable problem may present that single choice with a recommendation for complete review, but the user still chooses. A direct complete-review request needs no further clarification. The full audit remains separate and requires an explicit operator request or accepted offer before `pnpm verify:perf` may run. Protected receipts own changed files, plans, checks, reports, measurements, and pass/fail evidence.
16
16
 
17
17
  When `canvas.renderScale` is enabled, record the renderer decision to preserve selected backing quality and map it to functional `renderScaleCoverage` for interaction and steady state, plus playback when timeline is enabled. The worklog may name the protected `canvas-render-scale-backing` recipe, but it cannot claim its evidence or turn a quality failure into performance authority.
18
18
 
19
19
  ## Performance Iteration Entry Contract
20
20
 
21
- For high-confidence ordinary work, record `Performance intent: ordinary-product-work`. For a performance complaint or optimization request, record exactly these domain fields in the latest iteration:
21
+ For high-confidence ordinary work, record `Performance intent: ordinary-product-work`. For unresolved localization, whether classification returned high-confidence `performance-iteration` or `needs-agent-judgment`, record the unresolved visible operation but no `Performance intent: performance-iteration` field or `Performance paths` until the user's one clarification provides exact localization. For a localized performance complaint or post-clarification targeted choice, record exactly these domain fields in the latest iteration:
22
22
 
23
23
  ```md
24
24
  - Performance intent: performance-iteration
@@ -27,7 +27,7 @@ For high-confidence ordinary work, record `Performance intent: ordinary-product-
27
27
  - Verification: One bare `pnpm verify:delivery` will derive and run the protected proof.
28
28
  ```
29
29
 
30
- The quoted evidence must be an exact nontrivial raw substring of `Request` with identical whitespace and Unicode code units. `Performance paths` must be a non-empty unique JSON array of canonical path IDs. Do not record command arguments, changed-file inventory, executed checks, reports, or measurements; the protected planner and receipt own that machine evidence. One complaint authorizes one bounded iteration; after it passes, return the app and wait for user evaluation. For `needs-agent-judgment`, read the full request and record the chosen intent. Complaint evidence never authorizes full certification. The separate operator command is permitted only after the user explicitly requests a complete audit or explicitly accepts the agent's offer; the user does not need to name the command.
30
+ The quoted evidence must be an exact nontrivial raw substring of `Request` with identical whitespace and Unicode code units. `Performance paths` must be a non-empty unique JSON array of canonical path IDs. Do not record command arguments, changed-file inventory, executed checks, reports, or measurements; the protected planner and receipt own that machine evidence. Each localized complaint or post-clarification targeted choice authorizes one bounded iteration; after it passes, return the app and wait for user evaluation. Classifier output or complaint evidence alone never supplies path localization or authorizes full certification. The separate operator command is permitted only after the user explicitly requests a complete audit or explicitly accepts the agent's offer; the user does not need to name the command.
31
31
 
32
32
  ## Decision Trail
33
33
 
@@ -116,6 +116,21 @@ The quoted evidence must be an exact nontrivial raw substring of `Request` with
116
116
  - Verification: One bare `pnpm verify:delivery` will derive and run the protected proof.
117
117
  - Risks: Already-exported applications retain their copied runtime until regenerated. Browser proof relies on the runtime gizmo's canonical pose/target attributes and intentionally fails closed if the real handle is absent or ambiguous.
118
118
 
119
+ ### Iteration 6 — Executable product-control applicability
120
+
121
+ - Request: Fix starter contracts so generated products show only settings that apply to the selected type and cannot pass delivery with a visible control that the renderer ignores.
122
+ - Task type: Shared runtime schema, controls-panel visibility, starter acceptance, protected browser evidence, generated fixtures, CLI, and documentation.
123
+ - User-visible result: Every generated product control explicitly declares `always` or `conditional` applicability. Non-matching controls disappear without losing their values, while every visible finite sibling branch must prove the control's real accepted product outcome.
124
+ - Source/reference checked: Badge behavior was used only as failure evidence; implementation scope remained the Toolcraft runtime and starter contracts. The legacy `visibleWhen` runtime path, control-section inventory, acceptance requirement derivation, reporter, and generated image/video/material fixtures were inspected.
125
+ - Contract rules applied: `controls-product-coverage`, `controls-section-inventory-required`, `controls-component-layout-invariants`, `acceptance-product-observable`, and `workflow-required`.
126
+ - Interaction ownership: The runtime owns applicability normalization and panel presence. Product schemas own explicit applicability claims. Existing product acceptance owns actions and outcomes; the applicability layer only derives the branch cases in which those outcomes must be reproved.
127
+ - Decision: Normalize explicit applicability, legacy `visibleWhen`, and omitted low-level input into one resolved model with origin metadata; reject legacy/implicit origins for product controls; combine conditional predicates with AND; derive pairwise cases from semantic section peers; preserve the authored `Background` inventory ownership after runtime relocates its product controls into `Setup`; attach case-scoped evidence only after exact presence/absence and real outcome assertions pass.
128
+ - Alternatives rejected: Extending optional `visibleWhen`, selector-owned target lists, renderer dependency inference, acceptance prose heuristics, Cartesian branch enumeration, and Badge-specific logic.
129
+ - State/output mapping: Applicability reads canonical runtime target values and changes only panel presence. Hidden values remain in runtime state, persistence, transfer, and history. Matching cases reuse the control's existing preview, rendered-pixel, artifact, command, or semantic proof.
130
+ - Performance intent: ordinary-product-work
131
+ - Verification: One bare `pnpm verify:delivery` remains the generated-app delivery authority; this runtime/template contract delivery also runs the monorepo checks required by the repository entry contract.
132
+ - Risks: Pairwise proof depends on truthful Control Section Inventory grouping; unsupported selector domains fail acceptance instead of silently skipping cases. Legacy low-level consumers remain readable but cannot satisfy generated product acceptance.
133
+
119
134
  ## Decisions
120
135
 
121
136
  ### Renderer
@@ -25,7 +25,7 @@ export const appComposition = {
25
25
  } satisfies ToolcraftAppComposition;
26
26
  ```
27
27
 
28
- Edit `src/app/app-composition.tsx`, not the signed route. Product composition may provide only `schema`, `canvasContent`, `controlRenderers`, `modelPresentation`, `onPanelAction`, `renderDefaultCanvasMedia`, and optional `rendererPipelineRegistration`; the protected route owns `className` and other host layout. Model products default to `modelPresentation: { mode: "runtime" }`. Custom presentation declares checked consumers and suppresses only their model targets; `renderDefaultCanvasMedia={false}` affects generic image/file preview, not runtime models. Do not compose `ToolcraftRoot`, `CanvasShell`, `ControlsPanel`, `LayersPanel`, `TimelinePanel`, or `ToolbarPanel` by hand. If a runtime surface has a performance or behavior issue, fix the shared runtime instead of replacing the surface locally.
28
+ Edit `src/app/app-composition.tsx`, not the signed route. Product composition may provide only `schema`, `canvasContent`, `infiniteCanvasContent`, `controlRenderers`, `exportRenderer`, `modelPresentation`, `onPanelAction`, `renderDefaultCanvasMedia`, `sceneBoundsProvider`, and optional `rendererPipelineRegistration`; the protected route owns `className` and other host layout. `infiniteCanvasContent` is editor-only product output for a full Infinity viewport backdrop; it does not inherit world transforms or participate in scene bounds/export. Model products default to `modelPresentation: { mode: "runtime" }`. Custom presentation declares checked consumers and suppresses only their model targets; `renderDefaultCanvasMedia={false}` affects generic image/file preview, not runtime models. Do not compose `ToolcraftRoot`, `CanvasShell`, `ControlsPanel`, `LayersPanel`, `TimelinePanel`, or `ToolbarPanel` by hand. If a runtime surface has a performance or behavior issue, fix the shared runtime instead of replacing the surface locally.
29
29
 
30
30
  Supporting product modules may be organized anywhere under `src`; there is no folder allowlist. The product boundary follows all product production files and rejects host/runtime surface imports, built-in control imports/re-exports, dynamic bypasses, and production dependencies on test/spec modules.
31
31
 
@@ -35,8 +35,10 @@ Allowed app extension points:
35
35
  | --- | --- |
36
36
  | Schema controls | Built-in controls, targets, defaults, visibility, panel actions. |
37
37
  | `canvasContent` | Product output only. |
38
+ | `infiniteCanvasContent` | Editor-only full-viewport product environment under the Infinity world; never app UI or export content. |
38
39
  | `controlRenderers` | True custom controls only after the built-in fit check. |
39
- | `onPanelAction` | Sticky footer product actions. |
40
+ | `exportRenderer` | One deterministic scene-coordinate product frame shared by runtime image and video export. |
41
+ | `onPanelAction` | Non-export sticky footer product actions. |
40
42
  | `rendererPipelineRegistration` | One compiled executable pipeline shared by render work, actions, evidence, and new-envelope assessment. |
41
43
  | Runtime commands/hooks | History, media, canvas, timeline, layers, and controlled app behavior. |
42
44
 
@@ -50,6 +52,10 @@ Once the folder is a real product, switch `src/app/app-acceptance-data.ts` from
50
52
 
51
53
  ```ts
52
54
  export const appProductReadiness = {
55
+ exportIntent: {
56
+ image: { mode: "toolcraft-default" },
57
+ video: { mode: "not-requested" },
58
+ },
53
59
  interactionOwnership: [],
54
60
  mode: "product",
55
61
  productName: "Product name",
@@ -62,6 +68,8 @@ export const appProductReadiness = {
62
68
  } as const;
63
69
  ```
64
70
 
71
+ Every product declaration requires `productReadiness.exportIntent`. It is the authority for exact image/video schema actions, settings sections, and artifact acceptance. Use `core/setup-export.md` for the single export-intent decision sequence; animation and timeline choices do not supply delivery intent.
72
+
65
73
  Populate `interactionOwnership` before adding canvas handles or custom
66
74
  interactions. One operation has one primary `canvas` or `panel` surface chosen
67
75
  from user request, inspected reference, or product usability evidence. Different
@@ -74,7 +82,7 @@ the prompt did not separately request rotation.
74
82
 
75
83
  ## Controls
76
84
 
77
- Before writing product sections, export `starterControlSectionInventory`. Each product section declares its title, targets, product entity or workflow stage, and grouping reason.
85
+ Before choosing component layout, export `starterControlSectionInventory` and make the entity-first grouping decision. Every product section declares stable `entityId`, human-readable `entity`, exact targets, and `groupingReason`; one entity stays in one section through ten controls, while larger entities split only into explicit balanced workflow stages.
78
86
 
79
87
  Use `core/layout.md` for section grouping, dependency cohesion, headers, reset, collapse, spacing, dividers, labels, and inline rows. Use `core/control-selection.md` and `component-rules.md` before choosing concrete controls. Built-in compound controls stay compound; extend the kit instead of splitting owned fields into neighboring controls.
80
88
 
@@ -98,7 +106,7 @@ When porting an existing app, use `transferMode: "reference-runtime-clone"` unle
98
106
 
99
107
  ## Timeline And Animation
100
108
 
101
- Before adding animation controls, write an Animation Intent Inventory. Product animation, keyframes, playback, and video export use the top Toolcraft timeline. Autonomous no-timeline animation is allowed only for non-product decorative motion with no user-facing transport and no video export.
109
+ Before adding animation controls, write an Animation Intent Inventory. Product animation, keyframes, and playback use the top Toolcraft timeline. Explicitly requested video export also requires that timeline, but the timeline never authorizes video delivery. Autonomous no-timeline animation is allowed only for non-product decorative motion with no user-facing transport and no video export.
102
110
 
103
111
  Use `core/timeline-animation.md` for timeline mode, compact/extended timeline, seamless forward loops, duration changes, keyframes, viewport interaction performance, and video export timing.
104
112
 
@@ -116,7 +124,7 @@ Use one normal sequence: assemble or change the product, gather focused function
116
124
 
117
125
  1. First product delivery uses bare `pnpm verify:delivery` for complete product contracts, one production build, full functional acceptance, and no measured performance.
118
126
  2. Later `functional-targeted` delivery uses the same bare command for exact ownership-derived functional proof relative to the immediately previous successful delivery.
119
- 3. A performance complaint records its exact request quote and canonical affected path IDs in the worklog, then one bare delivery runs one targeted iteration and returns the app for evaluation.
127
+ 3. Classifier output establishes complaint authority only and never path localization. Only a localized complaint or a post-clarification targeted choice records an exact request quote and canonical affected path IDs in the worklog, then one bare delivery runs one targeted iteration and returns the app for evaluation. Unresolved localization creates neither performance-iteration intent nor canonical path authority regardless of classifier result.
120
128
  4. A full audit requires an explicit operator request or accepted offer; only then run `pnpm verify:perf` for one fresh build and the complete maximum-fixture performance matrix.
121
129
 
122
130
  Protected receipts own changed files, the derived plan, executed checks, reports, measurements, and pass/fail evidence. The worklog keeps product intent and decisions.