@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
@@ -36,13 +36,15 @@ Range slider value editing accepts common range separators such as `20/80`, `20-
36
36
 
37
37
  Discrete sliders must still drag smoothly. Heavy preview work may be coalesced, cached, or split into lightweight live feedback plus heavier refinement, but the canvas/product output must not stay unchanged until pointer release.
38
38
 
39
- Use `visibleWhen` when a slider or range slider is meaningful only in some mode, type, source, include, variant, or count state. Inactive branches disappear so the panel shows only controls that can be used in the current state.
39
+ Every product slider and range slider declares `applicability`. Use `mode: "conditional"` when it is meaningful only in some mode, type, source, include, variant, or count state. Every predicate in `all` must match; inactive branches disappear while their values remain preserved.
40
40
 
41
- Do not use schema `disabled: true` or `disabledWhen` for product sliders and range sliders. Product panels should show only controls usable in the current state. Use `visibleWhen` for unavailable product states instead of rendering disabled controls.
41
+ Do not use schema `disabled: true` or `disabledWhen` for product sliders and range sliders. Product panels show only controls usable in the current state.
42
42
 
43
- For mode/type/source/include/count branches, hide with `visibleWhen` instead of disabling. Example: when Texture is `Off`, hide texture pattern, upload, blend, and opacity. When Texture is `Image`, show the image uploader and shared texture settings. When `Shades` is `2`, `Shade 3`, `Shade 4`, and `Shade 5` are not visible. Do not keep inactive controls visible while making the renderer ignore them.
43
+ For mode/type/source/include/count branches, declare conditional applicability instead of disabling. Example: when Texture is `Off`, texture pattern, upload, blend, and opacity predicates do not match. When Texture is `Image`, the uploader and shared texture settings match. When `Shades` is `2`, `Shade 3`, `Shade 4`, and `Shade 5` do not match. Do not keep inactive controls visible while making the renderer ignore them.
44
44
 
45
- If `visibleWhen` points to a selector for the same target entity or selected branch, keep the selector and the dependent controls in the same semantic section. A section that exists only because one selector option is active is not a separate product section just because the branch uses a standalone control. Use one section with conditional controls; split only when the dependent branch is a separate product entity with its own workflow and acceptance evidence.
45
+ If applicability points to a selector for the same target entity or selected branch, keep the selector and dependent controls in the same semantic section. A section that exists only because one selector option is active is not a separate product section just because the branch uses a standalone control. Use one section with conditional controls; split only when the dependent branch is a separate product entity with its own workflow and acceptance evidence.
46
+
47
+ An `always` declaration is testable, not a shortcut: protected acceptance varies every supported finite sibling selector from the same Control Section Inventory and proves the control's existing product outcome in each branch. Conditional controls use the same pairwise cases; a non-matching case proves absence, and every matching case reproves the real output. This catches both missing predicates and incorrect always-visible declarations.
46
48
 
47
49
  ## Palette
48
50
 
@@ -86,7 +88,7 @@ Use `core/layout.md` for section grouping, dependency cohesion, headers, reset,
86
88
 
87
89
  ## Colors
88
90
 
89
- Use `core/layout.md` for semantic color grouping, color labels, row fit, and color/opacity layout. Use `core/setup-export.md` for the authored background source pair, its runtime Setup placement, and export background behavior.
91
+ Use `core/layout.md` for semantic color grouping, color labels, row fit, and color/opacity layout. Use `core/setup-export.md` for the authored background source pair, its runtime Setup placement, and export background behavior. For repeated built-in controls, use `sourceCollection` for a source-owned array and `collectionActions` for a user-growable array; both support `checkbox`, `color`, `colorOpacity`, `fontPicker`, `rangeInput`, `rangeSlider`, `segmented`, `select`, `slider`, `switch`, `text`, and `vector` items, while unknown item types fail schema validation. Use scalar `itemControl` for one homogeneous repeated value. A `collectionActions` control may instead use `itemControls` only when two or more built-in fields form one logical target-array record that is added or removed atomically. Runtime places a line only between adjacent compound records and leaves standalone color grids unchanged. A multiple file-kind `fileDrop` with `variant: "collection-actions"` may declare `itemControls` to render built-in settings directly below each attached file and persist per-file values keyed by `mediaId`; its upload row and settings are one logical group under the same divider rule.
90
92
 
91
93
  ## File Upload
92
94
 
@@ -179,7 +181,7 @@ Use `useToolcraftModelOrbitInteraction` on the product renderer and provide a hi
179
181
 
180
182
  Multiple `orientationGizmo` declarations are allowed only for model modes whose combined section/control visibility conditions are statically provable as mutually exclusive. Runtime renders at most one active canvas handle and rejects an ambiguous state instead of selecting the first declaration.
181
183
 
182
- Click a signed axis endpoint to return to that view. Drag anywhere inside the circular gizmo to orbit with Blender-style Turntable behavior: horizontal movement rotates around world up, vertical movement rotates around the screen-horizontal axis, and sensitivity is 0.4 degrees per CSS pixel. Direct model drag uses the same rotation kernel. Axis snaps use angle-scaled Blender Smooth View timing with a 200ms maximum. Gizmo drag, snap, and direct model drag share target-scoped ownership, so a newer gesture, reset, undo/redo, or external target write cancels stale work. A background click is inert; pointer cancel and lost capture end the gesture. The runtime handle is fixed under canvas pan/zoom, uses one history group per completed gesture, and is excluded from export. Product code selects it through schema and must not import or render the visual gizmo directly.
184
+ Click a signed axis endpoint to return to that view. Drag anywhere inside the circular gizmo to orbit with Blender-style Turntable behavior: horizontal movement rotates around world up, vertical movement rotates around the screen-horizontal axis, and sensitivity is 0.4 degrees per CSS pixel. Direct model drag uses the same rotation kernel. Axis snaps use angle-scaled Blender Smooth View timing with a 200ms maximum. Gizmo drag, snap, and direct model drag share target-scoped ownership, so a newer gesture, reset, undo/redo, or external target write cancels stale work. A background click is inert; pointer cancel and lost capture end the gesture. The runtime handle is fixed under canvas pan/zoom, uses one history group per completed gesture, and is excluded from export. Product code selects it through schema and must not import or render the visual gizmo directly. When the product also enables the Toolcraft timeline or `canvas.renderScale`, orientation axis-drag proof runs with playback paused and render scale at its declared maximum. The shared pose and visible product pixels must update before pointer release in that state. Cooperative rendering may coalesce work, but it must publish a changed high-quality frame during the gesture; pointer release is not the first allowed visible commit.
183
185
 
184
186
  ## Curves
185
187
 
@@ -84,6 +84,7 @@ renamed copy of the same capability is still duplication.
84
84
  - Use `tabs` for finite choices that replace the content or workflow view below the control; the runtime changes overflowing tabs to Select without changing the value.
85
85
  - Use `segmented` for compact finite mode settings that leave the surrounding view unchanged.
86
86
  - Use `actions` for local section commands that affect only the nearby entity.
87
+ - Use `sourceCollection` when source analysis or another runtime workflow owns the array length and users edit only existing built-in item values.
87
88
  - Use `collectionActions` for repeatable product entities whose actual item list can grow or shrink.
88
89
  - Use `panelActions` for sticky final product actions such as export, copy, generate, apply, or download.
89
90
 
@@ -91,18 +92,22 @@ renamed copy of the same capability is still duplication.
91
92
 
92
93
  - `fontPicker` owns font family, weight, size, text case, text color/opacity, letter spacing, and line height.
93
94
  - `gradient` owns gradient type, angle, draggable stop track, and Stops list.
94
- - RGB `curves`, `channelMixer`, `palette`, and `collectionActions` are also compound controls.
95
+ - RGB `curves`, `channelMixer`, `palette`, `sourceCollection`, and `collectionActions` are also compound controls.
95
96
  - Do not split owned fields into neighboring schema controls.
96
97
  - If a needed owned field is missing from a built-in, extend the kit instead of composing a parallel control.
97
98
 
98
- ## Collection Actions
99
+ ## Collection Cardinality
99
100
 
101
+ - Use `sourceCollection` when a loaded, derived, detected, or otherwise external source owns the exact array length. It renders the declared built-in `itemControl` for every current item and never exposes add/remove commands.
100
102
  - Use `collectionActions` when users edit the actual growable/shrinkable set: colors, glyphs, symbols, points, rules, variants, objects, style entries, or similar repeatable entities.
103
+ - Both controls use the same runtime-owned built-in item renderer. Product code must not copy a child control implementation to support a dynamic list.
104
+ - Source workflows replace the complete `sourceCollection` target array; panel edits change item values only.
105
+
101
106
  - Adding/removing items must update runtime state and product preview/export.
102
107
  - Do not use a count slider plus hidden fixed item controls when the user needs to add or remove actual entities.
103
108
  - The collection control shows the collection label on the left and remove/add icon buttons on the right.
104
109
  - Homogeneous repeated items do not show visible per-item labels when the collection label already names the group.
105
- - Plain color items may use equal 50% columns; color+opacity items stay stacked.
110
+ - Plain color items may use equal 50% columns; color+opacity items stay stacked. Use `itemControl` for one homogeneous value. Use `itemControls` only when two or more built-in fields form one logical target-array record and affect that entity's outcome: `+` appends all field defaults, `−` removes the final record, and runtime places a content-width line only between records without `Item N` headings. Standalone color `itemControl` stays a divider-free two-column grid; color may still be a legitimate compound field.
106
111
 
107
112
  ## Actions
108
113
 
@@ -156,4 +161,5 @@ typed evidence-backed `fixed-camera` escape hatch.
156
161
  - Remove file names, helper text, and captions that do not help distinguish items or explain state.
157
162
  - Do not make tiny item-level action buttons below kit comfort sizes.
158
163
  - Do not recreate built-in controls, panels, toolbar, timeline, layers, canvas shell, or runtime surfaces.
164
+ - Do not import deep Toolcraft control implementation modules or substitute native form controls for a schema-owned value model.
159
165
  - A custom control with `custom-interaction` must reference its typed interaction owner. Its built-in fit check does not justify panel UI when the same operation is already owned by a canvas interaction.
@@ -4,11 +4,10 @@ Read this module before changing sections, labels, helper icons, inline rows, di
4
4
 
5
5
  ## Sections
6
6
 
7
- - Build controls-panel sections from product entities and workflow stages, not component types.
8
- - Before writing controls, export `starterControlSectionInventory`. Each product section declares title, product entity or workflow stage, targets, and grouping reason.
9
- - Keep sections discrete. Two to seven product controls is the normal size.
10
- - Split sections that grow past seven controls or mix several meanings.
11
- - In a section larger than seven controls, every control declares `semanticGroup`. One tightly scoped product sub-entity/workflow shares one group; mixed groups are structural evidence that the section should split. Do not infer this from labels.
7
+ - Build controls-panel sections from logical product entities, not component types, visual control size, or target namespaces. Before writing controls, export `starterControlSectionInventory`; every section declares stable `entityId`, human-readable `entity`, exact targets, and `groupingReason`.
8
+ - One to seven controls is the normal section size. Eight to ten controls are allowed for one cohesive entity and require `semanticGroup` on every control. Ten controls is the hard maximum.
9
+ - One entity with ten or fewer controls stays in one section. Different source, settings, placement, or presentation roles do not create sections by themselves.
10
+ - An entity above ten controls splits into balanced workflow sections containing two to ten controls. Every split section keeps the same `entityId` and `entity` and declares a unique `workflowStage` plus concrete `splitReason`; it may not leave a one-control tail. A one-control section is valid only when that control is the entity's complete editable surface.
12
11
  - Do not reuse the same section title for multiple sections.
13
12
  - Bad titles: `Controls`, `Settings`, `Options`, `Sliders`, `Inputs`, `Buttons`, `Color`, `Colors`.
14
13
  - Good titles name the edited thing: `Background`, `Object`, `Token Pattern`, `Motion`, `Tone Mapping`, `Export`.
@@ -17,8 +16,9 @@ Read this module before changing sections, labels, helper icons, inline rows, di
17
16
 
18
17
  ## Dependency Cohesion
19
18
 
19
+ - Typed `entityId` is the primary authority for section cohesion. Target-prefix checks are secondary diagnostics and never redefine an inventory entity.
20
20
  - A selector that controls mode, type, source, variant, or include state stays with the controls it gates when they share the same product entity.
21
- - Use `visibleWhen` for inactive product branches so the panel shows only usable controls.
21
+ - Declare conditional control applicability for inactive product branches so the panel shows only usable controls while preserving hidden values.
22
22
  - Do not create a separate section that merely mirrors one selector option unless that branch is a genuinely separate product entity with its own workflow evidence.
23
23
  - A section with no visible controls is hidden automatically.
24
24
  - Do not use `disabled: true` or `disabledWhen` for generated product controls.
@@ -50,7 +50,7 @@ Read this module before changing sections, labels, helper icons, inline rows, di
50
50
  - If a section contains exactly one control, simple or compound, render only the parent section dividers.
51
51
  - Do not add full-width borders inside a compound control.
52
52
  - Do not put dividers only around an internal subsection such as Gradient Stops.
53
- - Small compound fields such as `colorOpacity` and `rangeInput` stay inline fields without section dividers.
53
+ - Small compound fields such as `colorOpacity` and `rangeInput` stay inline fields without section dividers. Repeated `collectionActions` records built from `itemControls` use one content-width line only between adjacent logical records, with 18px spacing on each side and no generated item heading. A FileDrop collection slot and its per-file settings use the same group boundary. Standalone color `itemControl` grids have no item dividers.
54
54
 
55
55
  ## Labels And Help
56
56
 
@@ -51,6 +51,7 @@ Read this module before changing image upload, file upload, source material impo
51
51
  - Multiple image uploads render as a sortable four-column thumbnail grid.
52
52
  - The add-more tile is last.
53
53
  - Per-image removal stays inside the file control.
54
+ - When the product explicitly requires the compact cardinality pattern used by `collectionActions`, set `variant: "collection-actions"` on an `assetKind: "file"` control with `multiple: true`. Its header `+` adds one empty FileDrop slot and `−` removes the final slot or its attached file; the wide add row and per-item remove actions are omitted so cardinality has one owner. When every attached file owns settings, declare built-in `itemControls` with a `defaultValue` for every entry: attached files render those settings directly below their upload row, empty pending slots render no settings, the parent target stores value records keyed by `mediaId`, and runtime media keeps ownership of file bytes and lifecycle. The upload row and its per-file settings form one logical group; runtime renders one content-width line only between adjacent groups and never adds `Item N` headings. Product renderers join both slices by `mediaId`; do not collapse per-file settings into a global sibling section.
54
55
  - Dragging thumbnails updates runtime media order.
55
56
  - Product renderers and exports consume runtime media order instead of keeping a separate product-only order.
56
57
 
@@ -60,6 +61,7 @@ Read this module before changing image upload, file upload, source material impo
60
61
  - Long filenames fade/truncate at the end instead of hard-clipping.
61
62
  - The last item has no bottom separator.
62
63
  - The add row is part of the file control and uses the same width and hover behavior as list rows.
64
+ - The `variant: "collection-actions"` opt-in replaces that add row and the per-row remove buttons with the compact header `− / +` controls while preserving runtime media order.
63
65
  - When an app contains both image and file uploaders, canvas drops route by asset kind:
64
66
  - image files prefer visible image uploaders;
65
67
  - non-image files prefer visible file uploaders;
@@ -92,8 +94,8 @@ Read this module before changing image upload, file upload, source material impo
92
94
  - A structurally valid staged draft may preview during analysis without replacing committed state.
93
95
  - Analyzing and repairing preview opacity is `40%`; committed preview and export opacity is `100%`.
94
96
  - Rotatable model products use `orientationGizmo`. Direct drag on model geometry and the gizmo write the same orientation target against the same presentation lease; a canvas miss remains viewport pan. Preview, undo/reset, and export read that shared pose, canonical document reference, and appearance cache key.
95
- - Product image export creates its normal target canvas, renders product-owned pixels, then awaits `renderModelsToCanvas(exportCanvas)` from `onPanelAction` before encoding or downloading. This composites visible committed model layers at the current canvas size, target pixel ratio, and shared orientation. Do not enumerate model assets or call Three loaders in product export code.
96
- - Video export must render the same visible models and shared pose through the runtime model binding for every exported frame; it cannot substitute the panel preview or omit model layers.
97
+ - Runtime image/video export composites visible committed model layers at the exact scene frame, output size, pixel ratio, and shared orientation before awaiting the product's shared `exportRenderer` frame. Product code does not enumerate model assets, call Three loaders, invoke model compositors, encode canvases, or download artifacts.
98
+ - Every scheduled video frame uses the same runtime model binding and shared pose; it cannot substitute the panel preview or omit model layers.
97
99
 
98
100
  ### Persistence And Proof
99
101
 
@@ -3,6 +3,7 @@
3
3
  <!-- toolcraft-performance-lifecycle: first-delivery=functional; later-delivery=functional-targeted; complaint=one-authority-targeted-performance-iteration; full-audit=explicit-only -->
4
4
  <!-- toolcraft-performance-iteration: authority=exact-request-evidence+canonical-path-ids; fixture=reachable-development; after-pass=return-app-to-user+stop -->
5
5
  <!-- toolcraft-performance-full-authority: automatic=forbidden; recommendation=two-compatible-iterations-or-broad-unlocalizable-problem; command=pnpm verify:perf; authority=explicit-user-request-or-accepted-offer -->
6
+ <!-- toolcraft-performance-routing: localized=agent-targeted; ambiguous=one-user-facing-choice; broad=offer-targeted-or-full; full=explicit-only -->
6
7
 
7
8
  Read this module before changing renderer technique, animation, canvas, media, export, render scale, workload controls, or performance tests.
8
9
 
@@ -60,10 +61,18 @@ Include `initial-render` and every reachable interaction that executes or intent
60
61
 
61
62
  Browser checks apply compiled values through the real UI, observe every dimension, exercise the real preview or export path, assert the product result, and then check the budget. Export scenarios keep exact `actionValue`, visible `controlLabel`, and `completionEvidence` proof.
62
63
 
64
+ Selected image/video dimensions, decoded output quality, video duration, and exact 30 FPS packet cadence are functional correctness and never require measured performance authority. Export completion latency and UI responsiveness are measured only for a user-authorized targeted iteration or explicit full audit.
65
+
63
66
  ## Verification Triggers
64
67
 
65
68
  Keep `src/app/app-verification-impact.json` complete: every product production module is `presentation`, `functional`, or `performance`, every owner names its nearest acceptance ids, and performance owners name their exact renderer pass ids. `performance` means the module can change a named pass's execution, invalidation, workload, resource lifecycle, or measured output. Shared modules name only the acceptance and pass coverage they can actually change; blanket every-module ownership is invalid. The protected delivery runner compares the inventory with the immediately previous successful delivery and requires ownership-derived functional proof for changed implementation. Performance ownership constrains which passes and paths an exact request may authorize; it does not authorize measurements by itself. A durable full-performance baseline, when one exists, remains historical evidence rather than the functional change anchor. Missing modules, stale paths, unknown acceptance or pass ids, and blanket ownership fail before a receipt can be written.
66
69
 
70
+ Design product module boundaries for this exact later-delivery ownership. Keep frequently changed defaults and domain logic outside the public `app-schema.ts` assembly module when their acceptance coverage is narrower; otherwise a valid edit to that broad owner must select all of its acceptance ids. For raster zoom, prefer viewport transforms, but when exact render-scale backing requires rerasterization, declare one off-main `rasterize` pass with `quality: "retina"` owned by `viewport-zoom`. No other expensive viewport invalidation is accepted.
71
+
72
+ Performance adapters measure one primary user operation per phase; do not include an inverse cleanup action inside the measured operation. Non-animation interaction probes retain at least 20 post-action frames so nearest-rank p95 is statistically distinct from the maximum frame without weakening either threshold.
73
+
74
+ Performance-adapter-only changes remain functional delivery work: run code health and directly affected unit proof, but do not infer measurement. Their path candidates become executable only through exact complaint authority or an explicit full audit.
75
+
67
76
  Run targeted functional and browser checks during development. Only exact request authority can create a measured targeted performance iteration; a changed pipeline, workload boundary, adapter, interaction, measured output, owner, pass, path, filename, tier, or subsystem cannot. During an authorized iteration, the targeted Playwright reporter binds passed test names, pass ids, canonical path ids, nonce, and current source hash; product code and prose cannot mint that evidence.
68
77
 
69
78
  Functional performance coverage uses the runtime-owned deferred validation policy: all structural envelope, renderer pipeline, path, fixture, and adapter errors still fail, while unresolved kernel benchmark decisions remain visible as pending assessment requirements and require no kernel receipt. Strict/default validation and every authorized performance run continue to require the decision and protected current-source evidence.
@@ -74,9 +83,11 @@ The protected conversational lifecycle is automatic:
74
83
 
75
84
  - **First product delivery:** bare `pnpm verify:delivery` runs complete product contracts, one production build, and full functional acceptance with no measured performance. It preserves any independent full-performance baseline and cannot claim targeted or full performance evidence.
76
85
  - **Later functional-targeted delivery:** the same bare command runs exact ownership-derived functional checks for the changed implementation. It preserves any existing baseline and cannot silently invoke measured performance.
77
- - **Performance complaint:** record only domain authority in the latest Decision Trail—an exact request quote and canonical affected path IDs—then one bare `pnpm verify:delivery` runs one targeted iteration against the reachable development fixture. The same authority cannot produce a second successful iteration. Deliver the verified app, then stop and wait for user evaluation. A later complaint creates a new Decision Trail authority and starts another bounded iteration from the immediately previous successful delivery.
86
+ - **Localized or clarified targeted work:** only a localized complaint or a post-clarification targeted choice records domain authority in the latest Decision Trail—an exact request quote and canonical affected path IDs—then one bare `pnpm verify:delivery` runs one targeted iteration against the reachable development fixture. Classifier output establishes complaint authority only and never path localization. Any unresolved localization creates neither performance-iteration intent nor canonical path authority, whether classification returned high-confidence `performance-iteration` or `needs-agent-judgment`. The same authority cannot produce a second successful iteration. Deliver the verified app, then stop and wait for user evaluation. Each later localized request may create one new bounded iteration from the immediately previous successful delivery.
87
+
88
+ Request classification is tri-state. High-confidence performance language returns `performance-iteration`; high-confidence ordinary product work remains ordinary; ambiguous or unrecognized language becomes `needs-agent-judgment`, and the AI decides from the complete request. Classifier output establishes complaint authority only and never path localization. A localized complaint lets the agent select affected canonical paths and run one targeted iteration without asking the user. For an ambiguous complaint, ask one user-facing question naming visible operations and offering targeted diagnosis or a complete performance review; never ask the user for internal path IDs, and create neither performance-iteration intent nor canonical path authority before the answer. A broad or honestly unlocalizable problem may lead to that single targeted/full choice with a recommendation for complete performance review, but the user still chooses. An explicit complete-performance-review request runs `pnpm verify:perf` directly. Local negation and product commands are interpreted in their own clause rather than through a global phrase list. Before a performance iteration, the worklog must contain a nontrivial exact raw substring of Request as evidence. Whitespace and Unicode code units must match exactly; invented, whitespace-collapsed, NFKC-equivalent, or otherwise mismatched text is rejected. Complaint wording, repetition, filename, diagnostic classification, and touched subsystem never launch the complete matrix automatically.
78
89
 
79
- Request classification is tri-state. High-confidence performance language selects `performance-iteration`; high-confidence ordinary product work remains ordinary; ambiguous or unrecognized language becomes `needs-agent-judgment`, and the AI decides from the complete request. Local negation and product commands are interpreted in their own clause rather than through a global phrase list. Before a performance iteration, the worklog must contain a nontrivial exact raw substring of Request as evidence. Whitespace and Unicode code units must match exactly; invented, whitespace-collapsed, NFKC-equivalent, or otherwise mismatched text is rejected. Complaint wording, repetition, filename, diagnostic classification, and touched subsystem never launch the complete matrix automatically.
90
+ Store agent-produced browser diagnostics under `.toolcraft/browser-artifacts/`, or use external tool-owned storage when the browser integration owns the artifact. Diagnostics never become product source or performance authority.
80
91
 
81
92
  Every protected targeted performance report stores the independently validated `cold`, `warm`, and `sustained` numeric observations for each selected canonical path. When the immediately previous successful delivery contains compatible targeted measurements, the next complaint records metric deltas against that report; otherwise it records an explicit non-comparable result. Deltas are diagnostic evidence, not a noisy strict-improvement gate: the current iteration must pass its absolute profile budgets, then return to the user without launching another optimization pass.
82
93
 
@@ -92,7 +103,7 @@ Completion wording must name the evidence level. Functional delivery reports fun
92
103
 
93
104
  Render Scale preserves selected backing resolution and visible quality. A raster product with `canvas.renderScale` declares typed `renderScaleCoverage: { kind: "selected-backing-pixels", states }` on one browser runtime row targeting `canvas.renderScale`. Exact sorted states are `["interaction", "steady"]`, plus `"playback"` when timeline is enabled.
94
105
 
95
- The product browser scenario supplies real state transitions to `expectToolcraftCanvasRenderScaleEvidence`. The protected helper keeps CSS size stable, checks actual canvas backing pixels against `css size × devicePixelRatio × selected scale` in every state, and only then emits `canvas-render-scale-backing` for each `<acceptance-id>#<state>`. A clamp or downsample is a functional failure without measured performance. In an explicitly authorized render-scale performance path, `performance-render-scale` may be emitted only after the same real backing assertion passes.
106
+ The product browser scenario supplies real state transitions to `expectToolcraftCanvasRenderScaleEvidence`. The protected helper keeps CSS size stable, checks actual canvas backing pixels against `css size × devicePixelRatio × selected scale` in every state, and only then emits `canvas-render-scale-backing` for each `<acceptance-id>#<state>`. A clamp or downsample is a functional failure without measured performance. Every measured path in a render-scale-enabled raster product proves actual `CSS size × devicePixelRatio × 2` backing after each measured phase before `performance-render-scale` evidence may be emitted.
96
107
 
97
108
  Do not pass budgets by silently reducing selected quality, backing resolution, product range, source fidelity, export fidelity, or live interaction semantics. Diagnose pass cost, invalidation, cache lifetime, scheduling, and execution location first.
98
109
 
@@ -18,28 +18,41 @@ Use only these app-specific extension points. Shared runtime changes happen upst
18
18
  - schema controls;
19
19
  - schema `canvas`, `panels`, `toolbar`, `panelActions`, `persistence`, `media`, `assembly`, and transfer-mode metadata;
20
20
  - `canvasContent` for product output only;
21
+ - `infiniteCanvasContent` for editor-only product output that must fill the
22
+ complete Infinity viewport without inheriting world pan, zoom, product scene
23
+ bounds, or export bounds;
21
24
  - `renderDefaultCanvasMedia={false}` only when a product renderer replaces generic image/file preview; it does not suppress runtime model layers;
22
25
  - typed `modelPresentation`, with `{ mode: "runtime" }` as the default standard preview/export owner or `{ mode: "custom", consumers }` for declared model targets with checked consumers;
23
26
  - `controlRenderers` only for true custom controls that pass the built-in fit check;
24
- - `onPanelAction` for sticky product actions;
27
+ - one `exportRenderer` that draws a deterministic product frame for runtime-owned image/video export;
28
+ - one `sceneBoundsProvider` that returns exact-state product world-space rectangles for infinite preview and runtime-owned export;
29
+ - `onPanelAction` for non-export sticky product actions;
25
30
  - optional `rendererPipelineRegistration` for one compiled executable custom-renderer pipeline shared by product work, runtime evidence, and performance assessment;
26
- - runtime commands and hooks.
31
+ - runtime commands and hooks, including `useToolcraftProductSceneFrame` inside `canvasContent` when a raster/WebGL renderer needs the active finite or infinite frame.
27
32
 
28
33
  ## Forbidden Rebuilds
29
34
 
30
35
  - Do not hand-compose `ToolcraftRoot`, `CanvasShell`, `ControlsPanel`, `LayersPanel`, `TimelinePanel`, `ToolbarPanel`, or panel containers in product routes.
31
36
  - Do not render built-in control components such as `SliderControl`, `SelectControl`, `ColorControl`, `GradientControl`, `FontPickerControl`, `FileDropControl`, or `PanelActionsControl` directly in app code.
37
+ - Do not import anything below `src/toolcraft/ui/components/controls/**` (or the equivalent workspace package path), even when the private symbol name is not a public control. Private popovers, parsers, inputs, and state helpers are implementation details.
38
+ - Do not substitute native or primitive `input` types `color`, `range`, `file`, `checkbox`, or `radio`, or native `select`/`textarea`, for schema controls. Generic text inputs and product-specific primitives remain available inside a justified custom interaction.
32
39
  - Do not recreate controls, panels, toolbar, timeline, layers, canvas shell, drag handles, section headers, section reset, history, or runtime surfaces by hand.
40
+ - Do not create product-owned export canvases, encoders, object-URL downloads, or direct Mediabunny integrations; runtime owns typed image/video actions end to end.
33
41
  - If a shared behavior is wrong, fix the shared runtime/template source and regenerate or sync the copied Toolcraft source instead of patching one exported app.
34
42
 
35
43
  ## Canvas Boundary
36
44
 
37
45
  - `canvasContent` contains product output only: WebGL, Canvas 2D, SVG, DOM product text, shaders, generated previews, export previews, or product editing handles.
46
+ - `infiniteCanvasContent` follows the same product-output-only rule. Runtime
47
+ mounts it only in Infinity mode as a pointer-transparent viewport layer below
48
+ the transformed world. It is not a scene-bounds or export extension point.
38
49
  - App UI, CTAs, upload prompts, helper copy, placeholder instructions, buttons, menus, forms, and settings do not belong in `canvasContent`.
39
50
  - If upload/import is part of the source-material flow, the pre-content canvas stays neutral and runtime-backed. Upload affordance belongs in `fileDrop`.
40
51
  - DOM product text rendered inside `canvasContent` must be marked with `data-toolcraft-product-output` or `data-toolcraft-product-text` so tests and performance fixtures can target product output instead of app chrome.
41
52
  - Product editing handles must be textless overlays, write to runtime state, and stay out of export/copy output.
42
53
  - Preserve the runtime canvas backing. Product renderers may draw their own product background, but must not hide, replace, or make the Toolcraft canvas shell/backing transparent.
54
+ - Runtime owns the product scene surface. In infinite mode it resolves `sceneBoundsProvider` for the exact committed state and applies that frame before mounting product output. Product code does not position another scene wrapper from `canvas.size` or DOM measurement.
55
+ - Canvas 2D, WebGL, and WebGPU product output reads `useToolcraftProductSceneFrame()` for backing size and world-to-local translation. Finite frames are `{ x: 0, y: 0, width: canvas.size.width, height: canvas.size.height }`; infinite frames use the provider union. `empty` and `unavailable` are explicit states and never fall back to dormant finite dimensions.
43
56
 
44
57
  ## Model Presentation Boundary
45
58
 
@@ -63,7 +76,7 @@ Use only these app-specific extension points. Shared runtime changes happen upst
63
76
  - Generated applications keep their public entry surface in `src/app/app-composition.tsx` and `src/app/app-schema.ts`. Supporting product modules may live anywhere under `src`; every product production module is discovered by the same source inventory and checked by the same AST boundary.
64
77
  - The signed framework bootstrap includes `index.html`, `src/main.tsx`, `src/router.tsx`, `src/routes/index.tsx`, `src/routes/root.tsx`, and `src/styles.css`. Do not edit or replace those host files in a generated app.
65
78
  - Product styling is local by construction: use locally imported `*.module.css` files only. Every selector starts with a compound containing a local class. A first-compound `:is()` or `:where()` remains local only when every branch is locally anchored; `:not()` and `:has()` do not create a local anchor. Descendants may style product-owned children, but `:global`, bare/root selectors, host-attribute selectors, sibling escapes, CSS `@import`, package CSS imports, and product-created global `<style>`/`CSSStyleSheet` injection are rejected because they cross the product/runtime boundary.
66
- - Product `import()` and `require()` specifiers must be statically resolvable from literals, same-file constants, templates, or string concatenation. Production and test source share this rule, so computed module loading cannot hide a runtime/control import or a protected evidence channel.
79
+ - Product `import()` and `require()` specifiers must be statically resolvable from literals, same-file constants, templates, or string concatenation. Production and test source share this rule, so computed module loading cannot hide a runtime/control import or a protected evidence channel. Every deep control implementation import is rejected regardless of imported symbol name, and JSX control-substitute checks follow public `Input` aliases.
67
80
  - Product production modules must not import product tests, test-support modules, or protected browser-evidence internals, directly or through a product bridge. Runtime evidence is emitted only by the protected public acceptance/performance helpers after their assertions pass; product-owned source must not import, re-export, assemble, or forge the reserved evidence module names and payload identifiers.
68
81
  - Product production modules must form an acyclic dependency graph. The code-health gate resolves relative imports, directory `index.*` modules, configured TypeScript path aliases, and local package exports. Type-only imports, external packages, tests, and copied Toolcraft framework internals do not create product dependency edges. When a cycle exists, the gate prints the complete shortest cycle so the ownership boundary can be corrected directly.
69
82
  - Imported product source remains under `src`. Code health and product-boundary analysis consume the same canonical source-inventory semantics instead of maintaining independent recursive walkers. The signed Vitest reporter uses the canonical framework-ownership policy to distinguish product-owned runner results, while acceptance and performance requirements derive from typed app configuration.
@@ -31,22 +31,31 @@ Read this module before changing Setup, canvas sizing, background, image export,
31
31
  - `Infinity canvas` is the one runtime-owned mode switch for an unbounded workspace. Product code does not mirror it in `state.values` or create another canvas-mode control.
32
32
  - Turning it on removes the finite artboard boundary and clipping. `Aspect ratio`, `Canvas width`, and `Canvas height` disappear because they do not constrain the workspace.
33
33
  - Infinity canvas suppresses the bounded product-rendered preview background so the dormant finite output does not appear as a second canvas. While Background is on, `CanvasShell` fills the complete infinite viewport with the selected `Background color`; product code must not draw a synthetic workspace rectangle.
34
+ - Product output that semantically represents an editor environment rather than
35
+ bounded scene geometry may use `ToolcraftAppComposition.infiniteCanvasContent`.
36
+ Runtime mounts it only in Infinity mode, below the transformed product world,
37
+ across the full viewport, with pointer input disabled. It does not pan, zoom,
38
+ contribute to `sceneBoundsProvider`, or enter image/video export.
34
39
  - The last finite `canvas.size` remains dormant and immutable while Infinity canvas is on. Turning it off restores that exact size and centers the finite artboard; reset, undo/redo, persistence, and settings transfer preserve the same canonical `canvas.mode` behavior. Fixed proof compares exact artboard pixels and width/height control values before Infinity, after restoration, and after redo.
35
40
  - Runtime image and model assets keep explicit center-anchored world frames. Zoom, pan, radar, and model orientation change presentation, not scene geometry or export bounds.
36
- - Product `canvasContent` and custom renderer output declare one direct `ToolcraftAppComposition.sceneBoundsProvider`. It returns product world-space rectangles and receives `{ state, timeRange? }`; do not use a registry or DOM measurement.
41
+ - Product `canvasContent` and custom renderer output declare one direct `ToolcraftAppComposition.sceneBoundsProvider`. It returns product world-space rectangles for the supplied exact frame state; do not use a registry, DOM measurement, or app-authored time-range envelope.
42
+ - Runtime resolves that provider for the live committed state and positions one product scene surface at the exact union. Product output fills that surface; it does not create another absolute wrapper or reuse dormant finite `canvas.size` in infinite mode.
43
+ - Canvas 2D, WebGL, and WebGPU renderers call `useToolcraftProductSceneFrame()` inside `canvasContent` and use its rect for backing dimensions plus world-to-local translation. The hook reports finite, infinite, empty, or unavailable explicitly; empty/unavailable infinite frames do not silently render through finite fallback geometry.
37
44
  - Infinite PNG export crops to the outward-rounded union of visible product, image, and model frames. Hidden or unavailable layers, runtime media suppressed by the composition, and editor-only handles or gizmos are excluded.
38
45
  - Prove unavailable-image exclusion with `createToolcraftUnavailableImageResourceFixture` and `expectToolcraftInfinityCanvasUnavailableImageExportEvidence`; product tests never mutate storage/state or call the reserved bridge, and evidence publishes only after deterministic cleanup restores the ready resource.
39
- - Infinite video export resolves one bounds envelope for the requested `timeRange` and uses it for every frame, preventing frame-to-frame output size changes.
46
+ - Infinite video export asks the provider for every state in the runtime-owned frame schedule, unions those bounds once, and uses the result for every encoded frame, preventing frame-to-frame output size changes.
40
47
  - Finite-mode export remains the full finite canvas and does not call the product bounds provider.
41
48
  - Empty scenes, missing/invalid product bounds, and artifacts above `8192px` per edge or `67,108,864` pixels fail before canvas allocation with visible typed feedback: `empty-scene`, `scene-bounds-unavailable`, or `scene-export-too-large`.
42
49
 
43
50
  ## Resolution Scale
44
51
 
45
- - Non-vector raster, Canvas 2D, WebGL, and WebGPU previews set `canvas.renderScale: true`.
52
+ - Non-vector raster, Canvas 2D, WebGL, and WebGPU previews author `canvas.renderScale` as `true` or `{ step }`. For this control, product code may customize only the slider step; it cannot author `enabled`, `min`, `defaultValue`, or `max`.
53
+ - Runtime resolves the enabled slider to canonical `min: 1`, `defaultValue: 2`, and `max: 2`; the default step is `0.25`.
54
+ - A custom step must be finite, between `0.01` and `1`, and evenly partition the canonical `1..2` range so the `2` maximum remains reachable. Invalid or non-partitioning steps fail schema resolution instead of being clamped.
46
55
  - Runtime then appends `Resolution scale` after canvas sizing.
47
56
  - `Resolution scale` changes backing pixels from `1` to `2` without changing visible CSS size or product output dimensions.
48
57
  - The product acceptance matrix adds exactly one browser runtime row targeting `canvas.renderScale` with `renderScaleCoverage: { kind: "selected-backing-pixels", states: ["interaction", "steady"] }`; insert `"playback"` in sorted order when timeline is enabled.
49
- - The product browser scenario uses `expectToolcraftCanvasRenderScaleEvidence` for every declared state. Only after CSS size remains stable and actual backing dimensions honor `css size × devicePixelRatio × selected scale` does the protected reporter emit `canvas-render-scale-backing`.
58
+ - The product browser scenario uses `expectToolcraftCanvasRenderScaleEvidence` for every declared state. Only after CSS size remains stable and actual backing dimensions equal `css size × devicePixelRatio × selected scale` within the one-physical-pixel tolerance does the protected reporter emit `canvas-render-scale-backing`.
50
59
  - Any quality clamp or lower-resolution stretch is a functional failure without measured performance.
51
60
  - DOM/SVG/vector-native previews should not use render scale.
52
61
  - Performance fixes must preserve the user's selected render scale. Do not pass budgets by silently downsampling, stretching a lower-resolution backing canvas, blurring output, or clamping render scale below the chosen value.
@@ -70,8 +79,29 @@ Read this module before changing Setup, canvas sizing, background, image export,
70
79
  - Use a schema `color` target such as `appearance.background` or `scene.background`.
71
80
  - Do not hardcode a configurable background in CSS, Canvas `fillStyle`, or WebGL clear color.
72
81
  - Live preview calls `shouldIncludeToolcraftPreviewBackground(state)` and hides only the bounded product-rendered background when Background is off or Infinity canvas is on. In Infinity mode, the runtime viewport—not the product renderer—uses the selected Background color.
73
- - PNG export passes the Background value to the standard PNG export helper.
74
- - Video export keeps the background even when Background is off.
82
+ - Runtime image export reads Background directly: PNG can be transparent, while JPG remains opaque.
83
+ - Runtime video export keeps the selected background even when Background is off.
84
+
85
+ ## Artifact Export Intent
86
+
87
+ Use this sequence as the single authority for choosing product artifact delivery:
88
+
89
+ 1. Start every product with image export.
90
+ 2. Add video export only when the user explicitly requests video delivery.
91
+ 3. Do not infer video from animation, playback, keyframes, or timeline.
92
+ 4. Keep image with video unless the user explicitly requests removal.
93
+ 5. Record in `productReadiness.exportIntent`.
94
+
95
+ Product-mode readiness requires both discriminated decisions. Image uses `toolcraft-default`, `user-requested`, or `user-removed`: `user-requested` requires non-empty user-request evidence, and `user-removed` requires non-empty explicit user-removal evidence. Video uses `not-requested` or `user-requested`; `user-requested` requires non-empty explicit user-request evidence. Do not add optional modes, legacy fallbacks, or schema-derived inference. Resolved intent must correspond exactly to runtime-owned schema actions, settings sections, and artifact acceptance:
96
+
97
+ | Resolved delivery | Settings layout | Sticky export actions | Artifact acceptance |
98
+ | --- | --- | --- | --- |
99
+ | Image only | `Image Export` directly above sticky actions | `Export PNG` primary | Complete image coverage only |
100
+ | Image and video | `Image Export` immediately before `Video Export`; `Video Export` directly above sticky actions | `Export PNG` secondary, `Export Video` primary | Complete image and video coverage |
101
+ | Video only | `Video Export` directly above sticky actions | `Export Video` primary | Complete video coverage only |
102
+ | Explicit no-export | No image or video settings section | No image or video export action | No image or video artifact row |
103
+
104
+ Video-only requires non-empty evidence for both the explicit video request and explicit image removal. Explicit no-export requires non-empty image-removal evidence and video `not-requested`.
75
105
 
76
106
  ## Image Export
77
107
 
@@ -79,32 +109,32 @@ Read this module before changing Setup, canvas sizing, background, image export,
79
109
  - `Image Export` uses two `select` controls in one compact two-column inline row:
80
110
  - `export.image.format`, default `png`, with baseline `PNG` and `JPG` options;
81
111
  - `export.image.resolution`, default `4k`, with baseline `2K`, `4K`, and `8K` options.
82
- - Still-output apps place `Image Export` directly above sticky footer actions.
112
+ - Image-only apps place `Image Export` directly above sticky footer actions.
83
113
  - Apps with both image and video export place `Image Export` immediately before `Video Export`.
84
- - PNG export resolves the concrete scene frame through the panel action context, then calls `createToolcraftPngExportCanvas({ frame, includeBackground, resolution, state, render })` and `renderRuntimeSceneToCanvas(canvas, frame)` before drawing product pixels.
114
+ - Typed `export-image` actions are handled by the runtime. It resolves the current scene frame, selected format and resolution, allocates the exact backing, composites background plus visible runtime media/models, awaits `ToolcraftAppComposition.exportRenderer`, encodes the selected artifact, downloads it, and reports typed progress/failures.
115
+ - Product code supplies only the shared deterministic `exportRenderer.renderFrame` callback in scene coordinates. It must not allocate an export canvas, call `toBlob`/`toDataURL`, create object URLs, or download the artifact.
85
116
  - The selected `export.image.resolution` must produce real 2048/4096/8192px long-edge PNG output for 2K/4K/8K. Retina sizing is only the fallback for current/omitted resolution.
86
117
 
87
118
  ## Video Export
88
119
 
89
- - Product apps whose requested delivery includes animation expose `Export Video` and `Export PNG`; timeline playback alone does not require video delivery.
120
+ - Only products with video `user-requested` intent and non-empty explicit user-request evidence expose `Export Video`; animation and timeline behavior do not authorize it.
90
121
  - Any app with `Export Video` must enable the top Toolcraft timeline.
91
- - Apps with `Export Video` expose a separate `Video Export` section directly above sticky footer export buttons, after `Image Export`.
122
+ - Apps with `Export Video` expose a separate `Video Export` section directly above sticky footer actions. When image export is also enabled, `Image Export` sits immediately before it.
92
123
  - `Video Export` uses two `select` controls in one compact two-column inline row by default:
93
124
  - `export.video.format`, default `mp4`, with baseline `MP4` and `WebM` options;
94
125
  - `export.video.resolution`, default `current`, with baseline `Current` and `4K` options.
95
126
  - Stack the pair only when labels or selected values would clip, and record that fit reason in the worklog.
96
- - Use `MediaRecorder.isTypeSupported(...)` or an explicit encoder/transcoder capability check before choosing the actual MIME/container.
127
+ - Runtime uses the pinned Mediabunny timestamped encoder to select an actually supported container and codec. It reports the real MIME/extension or a typed visible failure.
97
128
  - `MOV` and `ProRes` are not baseline browser outputs; use them only with a custom encoder/transcoder plus acceptance and performance coverage.
98
129
  - Use `getToolcraftVideoExportSize` for video dimensions. `current` uses current canvas/output size with even encoder-safe rounding; `4k` fits inside 3840x2160, preserves aspect ratio, and returns even dimensions.
99
- - Offline rendered-frame video export must write timeline-based timestamps. `canvas.captureStream()` plus `MediaRecorder` records wall-clock time and cannot be the only duration mechanism for heavy renderers.
100
- - Browser acceptance must load the exported blob as a video, wait for metadata, and compare `video.duration` with the runtime timeline duration.
130
+ - Runtime renders the same shared product frame callback at a fixed 30 FPS offline schedule, evaluates each immutable frame state at its timeline timestamp, and writes explicit packet timestamps/durations. Renderer wall-clock cost changes export latency only, never media cadence or duration.
131
+ - Product code must not instantiate `MediaRecorder` or `VideoEncoder`, call `canvas.captureStream()`, import `mediabunny`, or provide a wall-clock fallback.
132
+ - Protected browser acceptance decodes representative video frames, enumerates actual encoded packet timings, and proves dimensions, duration, cadence, background, and changing product pixels before publishing evidence.
101
133
 
102
134
  ## Sticky Product Actions
103
135
 
104
- - Product apps always expose export in sticky `panelActions`.
105
- - Every product exposes `Export PNG`.
106
- - Products whose requested delivery includes animation also expose `Export Video`.
107
- - Clipboard copy is optional and never replaces export.
136
+ - Export actions in sticky `panelActions` match the resolved artifact intent exactly. Explicit no-export products have no image or video export action.
137
+ - Clipboard copy may be an additional product action, but it never changes or substitutes for the recorded artifact intent.
108
138
  - Export PNG and Export Video use `icon: "upload-simple"` to match the runtime `Export Settings` action.
109
- - Async export/download/copy/generate/apply handlers return the real Promise from `onPanelAction`. The runtime shows the sticky footer top accent indicator while the Promise is pending.
110
- - Use `reportProgress(0..1)` for determinate progress when available.
139
+ - Runtime export actions own their real Promise and report render/encode/download progress through the sticky footer indicator.
140
+ - Async non-export download/copy/generate/apply handlers return the real Promise from `onPanelAction` and use `reportProgress(0..1)` when determinate progress is available.
@@ -63,7 +63,7 @@ Use no timeline only when the motion is explicitly autonomous decoration with no
63
63
 
64
64
  ## Video Export Timing
65
65
 
66
- - Video export uses runtime timeline time.
67
- - Offline rendered-frame video export must encode frame timestamps from timeline time.
68
- - Real-time `canvas.captureStream()` plus `MediaRecorder` is not enough when renderer work can be slower than playback.
69
- - Browser acceptance verifies exported video metadata duration against edited timeline duration.
66
+ - Runtime video export creates a fixed 30 FPS schedule from runtime timeline duration and evaluates one immutable frame state at every scheduled timeline time.
67
+ - The timestamped Mediabunny backend encodes each completed frame with its explicit schedule timestamp and duration; render wall-clock cost does not affect artifact cadence.
68
+ - Product code must not use `canvas.captureStream()`, `MediaRecorder`, `VideoEncoder`, or its own encoder/download fallback.
69
+ - Protected browser acceptance proves edited timeline duration, actual encoded packet count/timings, and distinct decoded product frames.
@@ -4,11 +4,13 @@
4
4
 
5
5
  Use a custom control only when no built-in Toolcraft control represents the product interaction.
6
6
 
7
- Built-ins come first: `slider`, `rangeSlider`, `select`, `segmented`, `switch`, `checkbox`, `color`, `colorOpacity`, `vector`, `gradient`, `curves`, `fontPicker`, `imagePicker`, `fileDrop`, `text`, `code`, `rangeInput`, `palette`, `actions`, `collectionActions`, and `panelActions`.
7
+ Built-ins come first: `slider`, `rangeSlider`, `select`, `segmented`, `switch`, `checkbox`, `color`, `colorOpacity`, `vector`, `gradient`, `curves`, `fontPicker`, `imagePicker`, `fileDrop`, `text`, `code`, `rangeInput`, `palette`, `actions`, `sourceCollection`, `collectionActions`, and `panelActions`.
8
8
 
9
9
  Register custom renderers through `ToolcraftApp controlRenderers`.
10
10
 
11
- Do not use `controlRenderers` to recreate a built-in control. If the product needs a slider, select, segmented mode picker, color input, gradient editor, font picker, image upload, arbitrary file upload, textarea, local action group, repeatable item add/remove, or footer action, declare the matching schema control instead of rendering the component manually.
11
+ Do not use `controlRenderers` to recreate a built-in control. If the product needs a slider, select, segmented mode picker, color input, gradient editor, font picker, image upload, arbitrary file upload, textarea, local action group, source-sized repeated item editor, repeatable item add/remove, or footer action, declare the matching schema control instead of rendering the component manually.
12
+
13
+ Product modules never import deep paths below `src/toolcraft/ui/components/controls/**` and never replace schema value models with native `color`, `range`, `file`, `checkbox`, `radio`, `select`, or `textarea` controls. If a built-in lacks a required variant, improve the shared runtime instead of copying its private popover, parser, history, or state mechanics.
12
14
 
13
15
  Do not edit `ControlsPanel`, copied `src/toolcraft`, or Toolcraft internals inside a generated app.
14
16
 
@@ -40,7 +42,7 @@ builtInFitCheck: {
40
42
  "commands",
41
43
  "custom-value-model",
42
44
  ],
43
- checkedBuiltIns: ["fileDrop", "collectionActions", "imagePicker"],
45
+ checkedBuiltIns: ["fileDrop", "sourceCollection", "collectionActions", "imagePicker"],
44
46
  closestBuiltIn: "fileDrop",
45
47
  whyInsufficient:
46
48
  "FileDrop imports, previews, orders, and removes source files, but this product also needs per-glyph density thresholds stored with each item.",
@@ -51,7 +53,7 @@ builtInFitCheck: {
51
53
 
52
54
  `capabilities` is required and uses broad behavior facts: `collection`, `reorder`, `selection`, `commands`, `custom-interaction`, `custom-value-model`, or `custom-visualization`. At least one of the three `custom-*` capabilities must explain why built-ins cannot own the interaction. `checkedBuiltIns` must name real Toolcraft built-in controls. `closestBuiltIn` must be one of those checked controls or `"none"` when no built-in is meaningfully close. `whyInsufficient` explains the missing interaction. `productObservable` names the output or side effect that proves the custom control is necessary.
53
55
 
54
- If the custom control owns a growable, removable, selectable, or reorderable runtime item set, `checkedBuiltIns` must include both `collectionActions` and `actions`. Decide this from the value model and workflow, such as arrays, `{ items: [...] }` objects, selected-item state, or add/remove/reorder behavior, not from entity names like masks or glyphs. This applies even when the empty state visually looks like a few icon buttons: the fit check must prove why `collectionActions` cannot own the runtime list and why `actions` alone cannot represent the collection state.
56
+ If the custom control owns a repeated runtime item set, `checkedBuiltIns` must include `sourceCollection` and `collectionActions` so the fit check distinguishes source-owned from user-owned cardinality. Include `actions` when the custom interaction also exposes commands. Decide this from the value model and workflow, such as arrays, `{ items: [...] }` objects, selected-item state, or add/remove/reorder behavior, not from entity names like masks or glyphs. This applies even when the empty state visually looks like a few icon buttons: the fit check must prove why neither built-in collection owner can represent the state and why command UI is necessary when commands exist.
55
57
 
56
58
  Do not justify a custom control with icons, layout, styling, compactness, or custom buttons alone. If the built-in control has the right value model and mechanics, use it or improve that built-in instead.
57
59
 
@@ -21,7 +21,7 @@ Use this before writing a schema, spec, or implementation plan. It separates har
21
21
  | Panels | Mixed | Panel mechanics are hard; panel presence is product-dependent |
22
22
  | Layers | Heuristic, then invariant | Enable only for real layer behavior; fully test when enabled |
23
23
  | Timeline | Heuristic, then invariant | Choose from Animation Intent Inventory and transport behavior |
24
- | Controls | Mixed | Bind every visible control, choose one evidence-backed surface per operation, and prove product output behavior |
24
+ | Controls | Mixed | Bind every visible control, choose one evidence-backed surface per operation, and make artifact UI match required export intent |
25
25
  | Renderer | Default plus invariant | Choose technique from fidelity/workload and declare spatial view interaction before renderer code |
26
26
  | Reference analysis | Invariant | Study video references as frame-to-frame behavior before implementation |
27
27
  | Reference clone | Invariant | Preserve reference behavior unless redesign is explicit |
@@ -36,6 +36,8 @@ The runtime shell invariant means product code exports the typed composition and
36
36
 
37
37
  This catalog mirrors `TOOLCRAFT_DECISION_CONTRACT`. If runtime adds or renames a rule id, this page and `AGENTS.md` must list the same id.
38
38
 
39
+ `output-export-required` keeps artifact intent and implementation in exact correspondence. Product-mode readiness records `productReadiness.exportIntent`; schema actions, settings sections, and artifact acceptance expose exactly the enabled image/video capabilities. The authoritative decision sequence and evidence requirements live in `core/setup-export.md`.
40
+
39
41
  [//]: # (toolcraft-contract:decision-rule-table:start)
40
42
  | Rule ID | Level | Area |
41
43
  | --- | --- | --- |
@@ -3,6 +3,7 @@
3
3
  <!-- toolcraft-performance-lifecycle: first-delivery=functional; later-delivery=functional-targeted; complaint=one-authority-targeted-performance-iteration; full-audit=explicit-only -->
4
4
  <!-- toolcraft-performance-iteration: authority=exact-request-evidence+canonical-path-ids; fixture=reachable-development; after-pass=return-app-to-user+stop -->
5
5
  <!-- toolcraft-performance-full-authority: automatic=forbidden; recommendation=two-compatible-iterations-or-broad-unlocalizable-problem; command=pnpm verify:perf; authority=explicit-user-request-or-accepted-offer -->
6
+ <!-- toolcraft-performance-routing: localized=agent-targeted; ambiguous=one-user-facing-choice; broad=offer-targeted-or-full; full=explicit-only -->
6
7
 
7
8
  Use this document while authoring `src/app/app-performance.ts`, performance acceptance, and browser evidence. Read `core/performance.md` first. Functional selection and proof ownership are canonical in `workflow.md` and `acceptance-testing.md`; performance metadata does not redefine them.
8
9
 
@@ -95,6 +96,14 @@ Scenario interaction is the canonical pipeline interaction from its derived path
95
96
 
96
97
  `src/app/app-verification-impact.json` maps every current product production module to `presentation`, `functional`, or `performance` impact and names its nearest acceptance ids. A performance entry is reserved for a module that can change a named pass's execution, invalidation, workload, resource lifecycle, or measured output, and names only those exact pass ids. The inventory contains no stale or missing module paths; blanket every-module acceptance or pass ownership is invalid. This mapping is the authority for verification scope after first delivery.
97
98
 
99
+ Keep frequently edited product defaults and domain behavior in focused product modules whose ownership entries name only their nearest acceptance ids. `app-schema.ts` remains the public assembly boundary, but it should import those domain definitions instead of accumulating every mutable product decision in one file. A change made directly in a blanket schema owner correctly selects every acceptance id owned by that file; module boundaries are therefore part of later-delivery feedback speed, not cosmetic organization.
100
+
101
+ Viewport drag and zoom normally stay in transforms or uniforms and must not invalidate expensive passes. A render-scale-enabled raster product may rerasterize on `viewport-zoom` only through an off-main `rasterize` pass with `quality: "retina"`; this is the narrow exception that preserves exact CSS × DPR × selected-scale backing as the visible zoom size changes. Main-thread, non-retina, drag-time, and unrelated expensive invalidations remain invalid.
102
+
103
+ Each measured interaction phase performs one primary user operation. State-restoring inverse actions belong in a later phase or outside the measurement, never in the same action. Non-animation interaction probes collect at least 20 post-action frames so nearest-rank p95 remains a percentile rather than collapsing to the single maximum frame; animation keeps its dedicated 120-frame sample and export keeps completion-owned timing.
104
+
105
+ A change isolated to product performance adapters or performance test support selects code-health and any directly affected unit proof for ordinary delivery, but it never infers a measured path. Exact request authority may consume the adapter's performance candidates in one targeted iteration, while explicit `pnpm verify:perf` remains the only full-audit route.
106
+
98
107
  ## 6. Fixture Adapters And Plans
99
108
 
100
109
  `fixtureAdapters.dimensions` contains exactly one adapter per workload dimension. An adapter:
@@ -125,6 +134,8 @@ Mutating measurements prove a stable baseline, record the first persistent chang
125
134
 
126
135
  `export` scenarios declare exact `actionValue`, visible `controlLabel`, and `completionEvidence`. They may declare a `completionDeadlineMs` only when the product needs a stricter deadline than the central batch profile; scenarios do not author responsiveness budgets. The protected helper owns the click and completion event. Export evidence still inspects the delivered artifact and verifies that it is non-empty and matches selected output semantics.
127
136
 
137
+ Artifact dimensions, decoded quality, video duration, and exact 30 FPS packet cadence are functional proof. Export latency and UI responsiveness become measured performance only through an authorized targeted iteration or explicit full audit.
138
+
128
139
  ## 8. Demand-Only Performance Lifecycle
129
140
 
130
141
  During implementation, run targeted unit and functional browser checks for feedback without minting delivery evidence. At the coherent delivery boundary, the protected delivery runner diffs current sources against the immediately previous successful delivery and resolves changed modules through `app-verification-impact.json`. Every functional delivery requires only its ownership-derived functional proof, including changes to performance-owned modules. Performance ownership constrains an exact request-authorized iteration; it does not authorize measurements. A durable full-performance baseline, when one exists, remains historical evidence and is not reused as the functional-delivery diff anchor. Reports remain bound to their executed plan, nonce, and current source hash; product-authored JSON is not evidence.
@@ -139,17 +150,20 @@ The conversational lifecycle is automatic:
139
150
 
140
151
  1. **First product delivery.** Bare `pnpm verify:delivery` proves complete product contracts, performs one production build, and runs full functional acceptance with no measured performance. The receipt preserves any independent full-performance baseline and cannot claim targeted or full performance evidence.
141
152
  2. **Later functional-targeted delivery.** The same bare command derives exact ownership-required functional checks from the current inputs and immediately previous successful delivery. It preserves a baseline when present and cannot silently run measured performance or create one.
142
- 3. **Performance complaint.** The latest Decision Trail records only an exact request quote and canonical affected path IDs. One bare `pnpm verify:delivery` then runs one targeted iteration against the reachable development fixture. The protected report stores independently validated `cold`, `warm`, and `sustained` measurements; compatible prior evidence produces diagnostic deltas, while absent or incompatible evidence records a non-comparable result. Current absolute budgets remain the pass/fail authority. Deliver the verified app, then stop and wait for user evaluation. A later complaint creates a new Decision Trail authority for another bounded iteration.
153
+ 3. **Localized or clarified targeted work.** Only a localized complaint or a post-clarification targeted choice records an exact request quote and canonical affected path IDs in the latest Decision Trail. Classifier output establishes complaint authority only and never path localization. Any unresolved localization creates neither performance-iteration intent nor canonical path authority, whether classification returned high-confidence `performance-iteration` or `needs-agent-judgment`. One bare `pnpm verify:delivery` then runs one targeted iteration against the reachable development fixture. The protected report stores independently validated `cold`, `warm`, and `sustained` measurements; compatible prior evidence produces diagnostic deltas, while absent or incompatible evidence records a non-comparable result. Current absolute budgets remain the pass/fail authority. Deliver the verified app, then stop and wait for user evaluation. Each later localized request may create one new bounded iteration.
143
154
  4. **Full audit.** Only an explicit operator request or accepted offer authorizes `pnpm verify:perf`. It performs one fresh production build and the complete maximum-fixture performance matrix, updates only the performance checkpoints, and preserves the delivery anchor.
144
155
 
145
- Use the runtime request classifier as a guard, not as a substitute for understanding the user. It returns high-confidence `performance-iteration`, high-confidence ordinary product work, or `needs-agent-judgment`. High-confidence ordinary product instructions stay ordinary. For ambiguous language, the AI reads the actual request and decides. Iteration mode requires `Performance intent: performance-iteration — Request evidence: "<verbatim exact Request quote>"` in the worklog before the command runs. The quote must be a nontrivial exact raw substring of the current Request, including identical whitespace and Unicode code units; invented, whitespace-collapsed, or NFKC-equivalent evidence is invalid.
156
+ Use the runtime request classifier as a guard, not as a substitute for understanding the user. It returns high-confidence `performance-iteration`, high-confidence ordinary product work, or `needs-agent-judgment`. High-confidence ordinary product instructions stay ordinary. Classifier output establishes complaint authority only and never path localization. A localized complaint lets the agent select the affected canonical paths and run one targeted iteration without asking the user. For an ambiguous complaint, ask one user-facing question naming the visible operation and offering targeted diagnosis or a complete performance review; never ask the user to choose internal path IDs, and create neither performance-iteration intent nor canonical path authority before the answer. A broad or honestly unlocalizable problem may lead to that single targeted/full choice with a recommendation for complete performance review, but only the user's choice authorizes it. A direct complete-performance-review request runs `pnpm verify:perf` without another clarification. Iteration mode requires `Performance intent: performance-iteration — Request evidence: "<verbatim exact Request quote>"` in the worklog before the command runs. The quote must be a nontrivial exact raw substring of the current Request, including identical whitespace and Unicode code units; invented, whitespace-collapsed, or NFKC-equivalent evidence is invalid.
157
+
158
+ Store agent-produced browser diagnostics under `.toolcraft/browser-artifacts/`, or leave them in external tool-owned storage when the browser integration owns them. Diagnostics are not product source and must not affect verification inventory.
146
159
 
147
160
  Canonical classification examples:
148
161
 
149
- - direct reports that the app lags, the editor is slow, dragging has latency, frames stutter, or CPU/GPU/memory use is excessive select one performance iteration;
162
+ - reports that the app lags, the editor is slow, frames stutter, or CPU/GPU/memory use is excessive may establish high-confidence complaint authority, but without a visible operation they remain unlocalized and do not select an iteration;
163
+ - “dragging has latency” is localized to a visible operation, so the agent selects its affected canonical paths and runs one targeted iteration without clarification;
150
164
  - product commands such as increasing animation speed, freezing a camera at a frame, renaming a mode to “Performance”, or stating that the app does not lag are high-confidence ordinary product work;
151
- - wording such as “the controls feel sticky” or “something feels off” needs agent judgment from the full request;
152
- - classification is clause-local: an independent complaint still selects an iteration even when another clause negates a different complaint or requests a product speed change.
165
+ - wording such as “the controls feel sticky” or “something feels off” needs agent judgment from the full request; if localization remains unresolved, ask the one visible-operation targeted/full question and record no iteration or path authority before the answer;
166
+ - classification is clause-local: an independent complaint may establish complaint authority even when another clause negates a different complaint or requests a product speed change, while localization is still resolved separately.
153
167
 
154
168
  Use bare `pnpm verify:delivery` once for the coherent delivery batch. Complaint wording, repetition, filename, diagnostic classification, and touched subsystem never launch the complete matrix automatically. A targeted failure triggers targeted diagnosis, not an automatic full-suite run, and a passing iteration stops after returning the verified app for user evaluation.
155
169
 
@@ -165,7 +179,7 @@ User-facing completion text must distinguish the levels. Functional delivery rep
165
179
 
166
180
  ## Performance Quality
167
181
 
168
- Preserve selected output quality, preview fidelity, backing resolution, source fidelity, product boundaries, and live interaction behavior. Raster products with Resolution scale declare functional `renderScaleCoverage` using `kind: "selected-backing-pixels"` and exact `interaction`/`steady` states, plus `playback` when timeline is enabled. Their product browser scenario uses `expectToolcraftCanvasRenderScaleEvidence`; `canvas-render-scale-backing` is emitted only after real backing dimensions satisfy the selected scale without changing visible CSS size.
182
+ Preserve selected output quality, preview fidelity, backing resolution, source fidelity, product boundaries, and live interaction behavior. Raster products with Resolution scale declare functional `renderScaleCoverage` using `kind: "selected-backing-pixels"` and exact `interaction`/`steady` states, plus `playback` when timeline is enabled. Their product browser scenario uses `expectToolcraftCanvasRenderScaleEvidence`; `canvas-render-scale-backing` is emitted only after real backing dimensions satisfy the selected scale without changing visible CSS size. Every measured path in a render-scale-enabled raster product must prove actual `CSS size × devicePixelRatio × 2` backing after each measured phase.
169
183
 
170
184
  A renderer that caps 2x output during interaction, playback, or steady state fails functional acceptance without measured performance. `performance-render-scale` remains limited to an explicitly authorized performance path and follows the same backing-pixel assertion; path metadata alone is not evidence. When a budget fails, inspect assessed pass cost, invalidation, resource lifecycle, scheduling, cancellation, and execution location before changing product scope.
171
185