@pixel-point/toolcraft 0.0.18 → 0.0.19

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 (384) hide show
  1. package/package.json +1 -1
  2. package/src/generate-demand-only-lifecycle.test.mjs +9 -1
  3. package/src/generate-performance-iteration-execution.test.mjs +3 -3
  4. package/src/generate-test-delivery-architecture-assertions.mjs +11 -73
  5. package/src/generate-test-demand-only-lifecycle.mjs +34 -36
  6. package/src/generate-test-dependency-sandbox.mjs +4 -1
  7. package/src/generate-test-doc-assertions.mjs +55 -53
  8. package/src/generate-test-doc-assertions.test.mjs +1 -1
  9. package/src/generate-test-doc-policy-assertions.mjs +1 -1
  10. package/src/generate-test-export-doc-assertions.mjs +53 -0
  11. package/src/generate-test-file-assertions.mjs +51 -8
  12. package/src/generate-test-integrity-assertions.mjs +5 -2
  13. package/src/generate-test-integrity-manifest-assertions.mjs +16 -5
  14. package/src/generate-test-integrity-ownership-assertions.mjs +36 -4
  15. package/src/generate-test-package-assertions.mjs +4 -0
  16. package/src/generate-test-product-fixture.mjs +1 -1
  17. package/src/generate-test-product-fixture.test.mjs +35 -38
  18. package/src/generate-test-product-iteration.mjs +0 -1
  19. package/src/generate-test-product-iteration.test.mjs +0 -1
  20. package/src/generate-test-runtime-boundary-assertions.mjs +20 -0
  21. package/src/generate-test-standalone-assertions.mjs +0 -16
  22. package/src/generate-test-standalone-delivery-stages.mjs +2 -86
  23. package/src/generate.test.mjs +4 -0
  24. package/src/generated-integrity-manifest.test.mjs +5 -2
  25. package/src/generated-source-policy.test.mjs +0 -4
  26. package/src/package-json.mjs +5 -0
  27. package/src/package-json.test.mjs +21 -0
  28. package/src/package-manager.mjs +2 -0
  29. package/src/package-manager.test.mjs +8 -0
  30. package/src/packaged-template-fallback-helpers.mjs +254 -0
  31. package/src/packaged-template-fallback.test.mjs +121 -46
  32. package/src/packaged-template-runtime-assertions.mjs +150 -0
  33. package/templates/runtime/contracts/component-contracts.choices.test.ts +18 -3
  34. package/templates/runtime/contracts/component-contracts.choices.ts +8 -3
  35. package/templates/runtime/contracts/component-contracts.inputs.ts +2 -1
  36. package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +18 -4
  37. package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +1 -1
  38. package/templates/runtime/contracts/component-contracts.runtime.ts +7 -4
  39. package/templates/runtime/contracts/component-contracts.visual.test.ts +20 -0
  40. package/templates/runtime/contracts/component-contracts.visual.ts +4 -0
  41. package/templates/runtime/contracts/decision-contracts.test.ts +18 -12
  42. package/templates/runtime/contracts/decision-contracts.ts +4 -4
  43. package/templates/runtime/contracts/performance-verification-policy.test.ts +12 -12
  44. package/templates/runtime/contracts/performance-verification-policy.ts +8 -8
  45. package/templates/runtime/export/artifact-download.ts +1 -0
  46. package/templates/runtime/export/artifact-frame-renderer.ts +2 -15
  47. package/templates/runtime/export/artifact-frame-state.ts +16 -0
  48. package/templates/runtime/export/artifact-scene-frame.test.ts +3 -3
  49. package/templates/runtime/export/artifact-scene-frame.ts +3 -3
  50. package/templates/runtime/export/export-error.ts +5 -0
  51. package/templates/runtime/export/export-renderer-coverage.ts +54 -0
  52. package/templates/runtime/export/image-artifact-export.ts +2 -2
  53. package/templates/runtime/export/index.ts +13 -0
  54. package/templates/runtime/export/product-export-renderer.test.ts +38 -4
  55. package/templates/runtime/export/product-export-renderer.ts +0 -41
  56. package/templates/runtime/export/product-svg-export-renderer.ts +21 -0
  57. package/templates/runtime/export/svg-artifact-export.test.ts +98 -0
  58. package/templates/runtime/export/svg-artifact-export.ts +120 -0
  59. package/templates/runtime/export/svg-document.test.ts +221 -0
  60. package/templates/runtime/export/svg-document.ts +400 -0
  61. package/templates/runtime/export/svg-policy.ts +47 -0
  62. package/templates/runtime/index.ts +1 -0
  63. package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +10 -0
  64. package/templates/runtime/react/app-shell/settings-transfer.test.ts +21 -0
  65. package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +46 -1
  66. package/templates/runtime/react/app-shell/toolcraft-app.tsx +7 -2
  67. package/templates/runtime/react/canvas/canvas-shell-interactions.test.tsx +30 -0
  68. package/templates/runtime/react/canvas/canvas-shell-pinch-interactions.test.tsx +155 -0
  69. package/templates/runtime/react/canvas/canvas-shell-rendering.test.tsx +1 -1
  70. package/templates/runtime/react/canvas/canvas-shell.tsx +16 -5
  71. package/templates/runtime/react/canvas/canvas-viewport-geometry.ts +133 -0
  72. package/templates/runtime/react/canvas/use-canvas-viewport-interactions.ts +285 -36
  73. package/templates/runtime/react/controls-panel/__tests__/controls-panel.color-applicability-layout.test.tsx +134 -0
  74. package/templates/runtime/react/controls-panel/__tests__/controls-panel.color-layout.test.tsx +16 -1
  75. package/templates/runtime/react/controls-panel/__tests__/controls-panel.render-isolation.test.tsx +2 -0
  76. package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +39 -0
  77. package/templates/runtime/react/controls-panel/__tests__/controls-panel.setup-controls.test.tsx +3 -3
  78. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-collection.test.tsx +1 -4
  79. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-color-bank.test.tsx +2 -2
  80. package/templates/runtime/react/controls-panel/__tests__/controls-panel.vector-interaction.test.tsx +6 -6
  81. package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +2 -2
  82. package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +40 -11
  83. package/templates/runtime/react/controls-panel/layout/controls-panel-layout.tsx +31 -2
  84. package/templates/runtime/react/controls-panel/layout/controls-panel-section.tsx +4 -1
  85. package/templates/runtime/react/controls-panel/renderers/controls-panel-action-renderer.tsx +2 -1
  86. package/templates/runtime/react/controls-panel/renderers/controls-panel-basic-renderers.tsx +2 -52
  87. package/templates/runtime/react/controls-panel/values/controls-panel-color-values.ts +1 -9
  88. package/templates/runtime/react/controls-panel/values/controls-panel-spatial-values.ts +7 -2
  89. package/templates/runtime/react/orientation-gizmo/orientation-gizmo-math.ts +9 -69
  90. package/templates/runtime/schema/artifact-export-actions.test.ts +47 -0
  91. package/templates/runtime/schema/artifact-export-actions.ts +49 -0
  92. package/templates/runtime/schema/types.ts +1 -0
  93. package/templates/runtime/state/canvas-background-state.ts +1 -16
  94. package/templates/runtime/state/canvas-state.ts +32 -20
  95. package/templates/runtime/state/control-value-codecs.test.ts +98 -0
  96. package/templates/runtime/state/control-value-codecs.ts +700 -0
  97. package/templates/runtime/state/control-value-normalization.test.ts +1 -1
  98. package/templates/runtime/state/control-value-normalization.ts +127 -135
  99. package/templates/runtime/state/controls-reducer.ts +26 -3
  100. package/templates/runtime/state/create-template-state.test.ts +30 -0
  101. package/templates/runtime/state/create-template-state.ts +52 -31
  102. package/templates/runtime/state/orientation-pose.ts +80 -0
  103. package/templates/runtime/state/persistence-control-values.test.ts +59 -0
  104. package/templates/runtime/state/reducer-controls.test.ts +45 -0
  105. package/templates/runtime/state/reducer-media-reset.test.ts +1 -1
  106. package/templates/runtime/state/reducer-timeline.test.ts +70 -0
  107. package/templates/runtime/state/timeline-reducer.ts +40 -2
  108. package/templates/runtime/testing/performance-schema-queries.ts +2 -2
  109. package/templates/starter/AGENTS.md +21 -22
  110. package/templates/starter/docs/toolcraft/README.md +6 -6
  111. package/templates/starter/docs/toolcraft/acceptance-testing.md +20 -20
  112. package/templates/starter/docs/toolcraft/agent-worklog.md +88 -1
  113. package/templates/starter/docs/toolcraft/assembly-workflow.md +7 -6
  114. package/templates/starter/docs/toolcraft/component-rules.md +2 -2
  115. package/templates/starter/docs/toolcraft/core/layout.md +6 -1
  116. package/templates/starter/docs/toolcraft/core/media-upload.md +1 -1
  117. package/templates/starter/docs/toolcraft/core/performance.md +8 -10
  118. package/templates/starter/docs/toolcraft/core/reference-study.md +80 -19
  119. package/templates/starter/docs/toolcraft/core/runtime-boundary.md +2 -1
  120. package/templates/starter/docs/toolcraft/core/setup-export.md +43 -13
  121. package/templates/starter/docs/toolcraft/decision-contract.md +2 -2
  122. package/templates/starter/docs/toolcraft/performance.md +8 -10
  123. package/templates/starter/docs/toolcraft/renderer-technique.md +2 -2
  124. package/templates/starter/docs/toolcraft/schema-reference.md +8 -8
  125. package/templates/starter/docs/toolcraft/workflow.md +14 -14
  126. package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +38 -0
  127. package/templates/starter/e2e/app-browser-motion-reference-requirements.spec.ts +411 -0
  128. package/templates/starter/e2e/app-browser-proof-session.spec.ts +85 -0
  129. package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +62 -0
  130. package/templates/starter/e2e/app-browser-selection-scope-evidence.spec.ts +137 -0
  131. package/templates/starter/e2e/browser-infinity-canvas-svg-evidence.ts +42 -0
  132. package/templates/starter/e2e/browser-layer-evidence-helpers.ts +15 -36
  133. package/templates/starter/e2e/browser-product-raster-snapshot.ts +213 -0
  134. package/templates/starter/e2e/browser-proof-session.ts +43 -15
  135. package/templates/starter/e2e/browser-proof-surface-action.ts +79 -0
  136. package/templates/starter/e2e/browser-proof-types.ts +15 -0
  137. package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +22 -6
  138. package/templates/starter/e2e/browser-selection-scope-evidence.ts +269 -0
  139. package/templates/starter/e2e/browser-semantic-evidence-test-helpers.ts +97 -0
  140. package/templates/starter/e2e/browser-svg-export-evidence.spec.ts +79 -0
  141. package/templates/starter/e2e/browser-svg-export-evidence.ts +152 -0
  142. package/templates/starter/e2e/export-artifact-helpers.ts +70 -0
  143. package/templates/starter/e2e/product-observable-helpers.ts +8 -129
  144. package/templates/starter/e2e/svg-artifact-inspection.spec.ts +136 -0
  145. package/templates/starter/e2e/svg-artifact-inspection.ts +331 -0
  146. package/templates/starter/e2e/svg-download-test-fixtures.ts +34 -0
  147. package/templates/starter/e2e/toolcraft-delivery-catalog-reporter.ts +198 -15
  148. package/templates/starter/e2e/toolcraft-feature-verification-reporter.spec.ts +149 -0
  149. package/templates/starter/e2e/toolcraft-feature-verification-reporter.ts +223 -0
  150. package/templates/starter/package.json +2 -0
  151. package/templates/starter/scripts/check-toolcraft-docs.mjs +1 -0
  152. package/templates/starter/scripts/create-toolcraft-motion-reference-study.mjs +233 -0
  153. package/templates/starter/scripts/create-toolcraft-motion-reference-study.test.mjs +459 -0
  154. package/templates/starter/scripts/playwright-test-title-selection.d.mts +45 -0
  155. package/templates/starter/scripts/run-browser-performance-test-helpers.mjs +0 -27
  156. package/templates/starter/scripts/run-browser-performance.mjs +0 -6
  157. package/templates/starter/scripts/run-browser-performance.test.mjs +5 -13
  158. package/templates/starter/scripts/run-delivery-verification-test-helpers.mjs +0 -34
  159. package/templates/starter/scripts/run-delivery-verification.test.mjs +135 -31
  160. package/templates/starter/scripts/run-feature-verification.mjs +212 -0
  161. package/templates/starter/scripts/run-feature-verification.test.mjs +226 -0
  162. package/templates/starter/scripts/toolcraft-checkpoint-delivery-state.mjs +21 -8
  163. package/templates/starter/scripts/toolcraft-checkpoint-delivery-state.test.mjs +32 -92
  164. package/templates/starter/scripts/toolcraft-checkpoint-transaction.mjs +28 -6
  165. package/templates/starter/scripts/toolcraft-checkpoint-transaction.test.mjs +8 -63
  166. package/templates/starter/scripts/toolcraft-delivery-anchor.mjs +28 -8
  167. package/templates/starter/scripts/toolcraft-delivery-anchor.test.mjs +50 -61
  168. package/templates/starter/scripts/toolcraft-delivery-architecture-inventory.mjs +0 -4
  169. package/templates/starter/scripts/toolcraft-delivery-architecture-policy.mjs +0 -1
  170. package/templates/starter/scripts/toolcraft-delivery-evidence.test.mjs +2 -3
  171. package/templates/starter/scripts/toolcraft-delivery-executor.mjs +5 -1
  172. package/templates/starter/scripts/toolcraft-delivery-executor.test.mjs +5 -12
  173. package/templates/starter/scripts/toolcraft-delivery-functional-context.d.mts +1 -48
  174. package/templates/starter/scripts/toolcraft-delivery-functional-context.mjs +2 -30
  175. package/templates/starter/scripts/toolcraft-delivery-functional-context.test.mjs +4 -166
  176. package/templates/starter/scripts/toolcraft-delivery-functional-initial.test.mjs +4 -20
  177. package/templates/starter/scripts/toolcraft-delivery-lifecycle.mjs +43 -192
  178. package/templates/starter/scripts/toolcraft-delivery-performance-iteration-lifecycle.test.mjs +79 -440
  179. package/templates/starter/scripts/toolcraft-delivery-plan-authority.test.mjs +102 -297
  180. package/templates/starter/scripts/toolcraft-delivery-plan-construction.mjs +46 -97
  181. package/templates/starter/scripts/toolcraft-delivery-plan-test-helpers.mjs +125 -0
  182. package/templates/starter/scripts/toolcraft-delivery-plan-validation.test.mjs +58 -0
  183. package/templates/starter/scripts/toolcraft-delivery-plan.d.mts +19 -31
  184. package/templates/starter/scripts/toolcraft-delivery-plan.mjs +254 -252
  185. package/templates/starter/scripts/toolcraft-delivery-plan.test.mjs +29 -457
  186. package/templates/starter/scripts/toolcraft-delivery-receipt-performance.test.mjs +1 -1
  187. package/templates/starter/scripts/toolcraft-delivery-receipt-strictness.test.mjs +3 -72
  188. package/templates/starter/scripts/toolcraft-delivery-receipt-test-helpers.mjs +7 -36
  189. package/templates/starter/scripts/toolcraft-delivery-receipt.d.mts +3 -5
  190. package/templates/starter/scripts/toolcraft-delivery-receipt.mjs +15 -31
  191. package/templates/starter/scripts/toolcraft-delivery-receipt.test.mjs +28 -20
  192. package/templates/starter/scripts/toolcraft-delivery-receipt.types.test.mts +22 -30
  193. package/templates/starter/scripts/toolcraft-feature-verification-plan.d.mts +20 -0
  194. package/templates/starter/scripts/toolcraft-feature-verification-plan.mjs +146 -0
  195. package/templates/starter/scripts/toolcraft-feature-verification-plan.test.mjs +96 -0
  196. package/templates/starter/scripts/toolcraft-functional-proof-model.d.mts +3 -18
  197. package/templates/starter/scripts/toolcraft-functional-proof-model.mjs +39 -127
  198. package/templates/starter/scripts/toolcraft-functional-proof-model.test.mjs +25 -362
  199. package/templates/starter/scripts/toolcraft-functional-proof-model.types.test.mts +6 -83
  200. package/templates/starter/scripts/toolcraft-functional-proof-primitives.d.mts +11 -0
  201. package/templates/starter/scripts/toolcraft-functional-proof-primitives.mjs +61 -0
  202. package/templates/starter/scripts/toolcraft-functional-proof-primitives.test.mjs +43 -0
  203. package/templates/starter/scripts/toolcraft-integrity-policy.mjs +13 -0
  204. package/templates/starter/scripts/toolcraft-integrity-test-utils.mjs +1 -1
  205. package/templates/starter/scripts/toolcraft-layer-evidence-facade.test.mjs +58 -22
  206. package/templates/starter/scripts/toolcraft-motion-reference-analysis-protocol.mjs +111 -0
  207. package/templates/starter/scripts/toolcraft-motion-reference-analysis-protocol.test.mjs +116 -0
  208. package/templates/starter/scripts/toolcraft-motion-reference-artifacts.d.mts +37 -0
  209. package/templates/starter/scripts/toolcraft-motion-reference-artifacts.mjs +308 -0
  210. package/templates/starter/scripts/toolcraft-motion-reference-artifacts.test.mjs +420 -0
  211. package/templates/starter/scripts/toolcraft-motion-reference-artifacts.types.test.mts +50 -0
  212. package/templates/starter/scripts/toolcraft-motion-reference-command-options.mjs +195 -0
  213. package/templates/starter/scripts/toolcraft-motion-reference-command-options.test.mjs +224 -0
  214. package/templates/starter/scripts/toolcraft-motion-reference-contact-sheet.mjs +122 -0
  215. package/templates/starter/scripts/toolcraft-motion-reference-contact-sheet.test.mjs +153 -0
  216. package/templates/starter/scripts/toolcraft-motion-reference-evidence-assembly.mjs +270 -0
  217. package/templates/starter/scripts/toolcraft-motion-reference-evidence.test.mjs +432 -0
  218. package/templates/starter/scripts/toolcraft-motion-reference-ffmpeg-output.mjs +275 -0
  219. package/templates/starter/scripts/toolcraft-motion-reference-ffmpeg-output.test.mjs +294 -0
  220. package/templates/starter/scripts/toolcraft-motion-reference-group-inventory.mjs +148 -0
  221. package/templates/starter/scripts/toolcraft-motion-reference-image-filter-graph.mjs +101 -0
  222. package/templates/starter/scripts/toolcraft-motion-reference-image-filter-graph.test.mjs +124 -0
  223. package/templates/starter/scripts/toolcraft-motion-reference-image-source.mjs +259 -0
  224. package/templates/starter/scripts/toolcraft-motion-reference-image-source.test.mjs +338 -0
  225. package/templates/starter/scripts/toolcraft-motion-reference-image-timing.mjs +96 -0
  226. package/templates/starter/scripts/toolcraft-motion-reference-image-timing.test.mjs +81 -0
  227. package/templates/starter/scripts/toolcraft-motion-reference-lock-recovery.test.mjs +144 -0
  228. package/templates/starter/scripts/toolcraft-motion-reference-media-source.mjs +165 -0
  229. package/templates/starter/scripts/toolcraft-motion-reference-media-source.test.mjs +299 -0
  230. package/templates/starter/scripts/toolcraft-motion-reference-publication-discovery.test.mjs +142 -0
  231. package/templates/starter/scripts/toolcraft-motion-reference-publication-isolation.test.mjs +234 -0
  232. package/templates/starter/scripts/toolcraft-motion-reference-publication-journal-schema.mjs +122 -0
  233. package/templates/starter/scripts/toolcraft-motion-reference-publication-journal-store.mjs +89 -0
  234. package/templates/starter/scripts/toolcraft-motion-reference-publication-journal-store.test.mjs +74 -0
  235. package/templates/starter/scripts/toolcraft-motion-reference-publication-journal.mjs +264 -0
  236. package/templates/starter/scripts/toolcraft-motion-reference-publication-journal.test.mjs +377 -0
  237. package/templates/starter/scripts/toolcraft-motion-reference-publication-lease.mjs +254 -0
  238. package/templates/starter/scripts/toolcraft-motion-reference-publication-lease.test.mjs +130 -0
  239. package/templates/starter/scripts/toolcraft-motion-reference-publication-staging.mjs +128 -0
  240. package/templates/starter/scripts/toolcraft-motion-reference-publication-staging.test.mjs +209 -0
  241. package/templates/starter/scripts/toolcraft-motion-reference-publication.fixtures.mjs +88 -0
  242. package/templates/starter/scripts/toolcraft-motion-reference-publication.mjs +249 -0
  243. package/templates/starter/scripts/toolcraft-motion-reference-publication.test.mjs +433 -0
  244. package/templates/starter/scripts/toolcraft-motion-reference-review-output.mjs +38 -0
  245. package/templates/starter/scripts/toolcraft-motion-reference-review-output.test.mjs +29 -0
  246. package/templates/starter/scripts/toolcraft-motion-reference-root-safety.test.mjs +84 -0
  247. package/templates/starter/scripts/toolcraft-motion-reference-roots.mjs +83 -0
  248. package/templates/starter/scripts/toolcraft-motion-reference-sampling.mjs +283 -0
  249. package/templates/starter/scripts/toolcraft-motion-reference-sampling.test.mjs +480 -0
  250. package/templates/starter/scripts/toolcraft-motion-reference-stage-registry.mjs +39 -0
  251. package/templates/starter/scripts/toolcraft-motion-reference-stage-registry.test.mjs +59 -0
  252. package/templates/starter/scripts/toolcraft-motion-reference-stage.mjs +71 -0
  253. package/templates/starter/scripts/toolcraft-motion-reference-stage.test.mjs +61 -0
  254. package/templates/starter/scripts/toolcraft-motion-review-numeric.mjs +74 -0
  255. package/templates/starter/scripts/toolcraft-motion-review-numeric.test.mjs +65 -0
  256. package/templates/starter/scripts/toolcraft-motion-review-partitioning.mjs +268 -0
  257. package/templates/starter/scripts/toolcraft-motion-review-partitioning.test.mjs +329 -0
  258. package/templates/starter/scripts/toolcraft-motion-review-protected-units.mjs +120 -0
  259. package/templates/starter/scripts/toolcraft-motion-review-protected-units.test.mjs +111 -0
  260. package/templates/starter/scripts/toolcraft-performance-escalation-policy.test.mjs +77 -345
  261. package/templates/starter/scripts/toolcraft-performance-receipt-validation.test.mjs +19 -21
  262. package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +1 -1
  263. package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +10 -1
  264. package/templates/starter/scripts/toolcraft-product-export-boundary.test.mjs +5 -1
  265. package/templates/starter/scripts/toolcraft-product-observable-facade.test.mjs +46 -1
  266. package/templates/starter/scripts/toolcraft-receipt-boundary.test.mjs +0 -1
  267. package/templates/starter/scripts/toolcraft-source-inventory.d.mts +5 -0
  268. package/templates/starter/scripts/toolcraft-source-inventory.mjs +25 -14
  269. package/templates/starter/scripts/toolcraft-source-inventory.test.mjs +48 -0
  270. package/templates/starter/scripts/toolcraft-source-ownership.mjs +0 -1
  271. package/templates/starter/scripts/toolcraft-source-ownership.test.mjs +30 -5
  272. package/templates/starter/scripts/toolcraft-verification-receipt-test-helpers.mjs +5 -26
  273. package/templates/starter/scripts/toolcraft-verification-receipt.d.mts +0 -7
  274. package/templates/starter/scripts/toolcraft-verification-receipt.mjs +3 -47
  275. package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +6 -87
  276. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.d.mts +19 -0
  277. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.mjs +107 -0
  278. package/templates/starter/scripts/toolcraft-vitest-runtime-contract.test.mjs +114 -0
  279. package/templates/starter/scripts/toolcraft-vitest-runtime-evidence-reporter.mjs +13 -2
  280. package/templates/starter/scripts/toolcraft-vitest-runtime-evidence-reporter.test.mjs +110 -0
  281. package/templates/starter/src/app/acceptance/artifact-export-intent.ts +51 -20
  282. package/templates/starter/src/app/acceptance/canvas-coverage.ts +1 -0
  283. package/templates/starter/src/app/acceptance/color-bank-labels.ts +11 -15
  284. package/templates/starter/src/app/acceptance/color-row-grouping.ts +33 -0
  285. package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +0 -11
  286. package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +2 -3
  287. package/templates/starter/src/app/acceptance/control-component-rules.ts +0 -10
  288. package/templates/starter/src/app/acceptance/control-labels.ts +30 -1
  289. package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +18 -0
  290. package/templates/starter/src/app/acceptance/export-artifact-coverage.ts +25 -17
  291. package/templates/starter/src/app/acceptance/feature-verification-selection.test.ts +295 -0
  292. package/templates/starter/src/app/acceptance/feature-verification-selection.ts +161 -0
  293. package/templates/starter/src/app/acceptance/infinity-canvas.ts +10 -0
  294. package/templates/starter/src/app/acceptance/interaction-ownership-intent.ts +19 -1
  295. package/templates/starter/src/app/acceptance/interaction-ownership.ts +18 -2
  296. package/templates/starter/src/app/acceptance/motion-reference-evidence-validation.mjs +65 -0
  297. package/templates/starter/src/app/acceptance/motion-reference-evidence-windows.mjs +301 -0
  298. package/templates/starter/src/app/acceptance/motion-reference-evidence.d.mts +11 -0
  299. package/templates/starter/src/app/acceptance/motion-reference-evidence.mjs +145 -0
  300. package/templates/starter/src/app/acceptance/motion-reference-study-behaviors.ts +162 -0
  301. package/templates/starter/src/app/acceptance/motion-reference-study-coverage.ts +206 -0
  302. package/templates/starter/src/app/acceptance/motion-reference-study-identity.ts +129 -0
  303. package/templates/starter/src/app/acceptance/motion-reference-study-partitions.ts +186 -0
  304. package/templates/starter/src/app/acceptance/motion-reference-study.ts +90 -0
  305. package/templates/starter/src/app/acceptance/output-export-actions.test.ts +9 -1
  306. package/templates/starter/src/app/acceptance/output-export-actions.ts +14 -22
  307. package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +5 -1
  308. package/templates/starter/src/app/acceptance/output-export-model.ts +4 -0
  309. package/templates/starter/src/app/acceptance/output-export.ts +4 -1
  310. package/templates/starter/src/app/acceptance/reference-study-types.ts +167 -17
  311. package/templates/starter/src/app/acceptance/runtime-coverage.ts +6 -1
  312. package/templates/starter/src/app/acceptance/selection-scope.test.ts +200 -0
  313. package/templates/starter/src/app/acceptance/selection-scope.ts +151 -0
  314. package/templates/starter/src/app/acceptance/transfer-mode-types.ts +114 -0
  315. package/templates/starter/src/app/acceptance/types.ts +43 -118
  316. package/templates/starter/src/app/acceptance/validate-coverage.ts +14 -3
  317. package/templates/starter/src/app/starter-acceptance-data.ts +1 -0
  318. package/templates/starter/src/app/starter-acceptance.animation-intent.test.ts +3 -0
  319. package/templates/starter/src/app/starter-acceptance.artifact-export-intent.test.ts +81 -8
  320. package/templates/starter/src/app/starter-acceptance.background-export.test.ts +2 -0
  321. package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +2 -0
  322. package/templates/starter/src/app/starter-acceptance.color-row-grouping.test.ts +118 -0
  323. package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +1 -1
  324. package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +1 -0
  325. package/templates/starter/src/app/starter-acceptance.control-applicability.test.ts +1 -0
  326. package/templates/starter/src/app/starter-acceptance.control-label-context.test.ts +1 -0
  327. package/templates/starter/src/app/starter-acceptance.control-labels.test.ts +78 -3
  328. package/templates/starter/src/app/starter-acceptance.control-naming-rules.test.ts +77 -1
  329. package/templates/starter/src/app/starter-acceptance.custom-control-fit-check.test.ts +1 -1
  330. package/templates/starter/src/app/starter-acceptance.export-artifact.test.ts +74 -3
  331. package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +5 -1
  332. package/templates/starter/src/app/starter-acceptance.image-export-settings.test.ts +2 -0
  333. package/templates/starter/src/app/starter-acceptance.interaction-ownership.test.ts +19 -3
  334. package/templates/starter/src/app/starter-acceptance.layers.test.ts +2 -1
  335. package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +28 -0
  336. package/templates/starter/src/app/starter-acceptance.motion-reference-evidence.test.ts +17 -0
  337. package/templates/starter/src/app/starter-acceptance.motion-reference-identity.test.ts +163 -0
  338. package/templates/starter/src/app/starter-acceptance.motion-reference-mapping.test.ts +133 -0
  339. package/templates/starter/src/app/starter-acceptance.motion-reference-ownership.test.ts +121 -0
  340. package/templates/starter/src/app/starter-acceptance.motion-reference-partitions.test.ts +210 -0
  341. package/templates/starter/src/app/starter-acceptance.motion-reference-test-utils.ts +313 -0
  342. package/templates/starter/src/app/starter-acceptance.output-export-intent.test.ts +78 -4
  343. package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +6 -1
  344. package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +18 -1
  345. package/templates/starter/src/app/starter-acceptance.product-worklog.test.ts +123 -2
  346. package/templates/starter/src/app/starter-acceptance.reference-custom-timeline.test.ts +2 -0
  347. package/templates/starter/src/app/starter-acceptance.reference-foundation.test.ts +8 -0
  348. package/templates/starter/src/app/starter-acceptance.reference-timeline.test.ts +7 -0
  349. package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +2 -0
  350. package/templates/starter/src/app/starter-acceptance.timeline-playback.test.ts +5 -0
  351. package/templates/starter/src/app/starter-acceptance.ts +34 -8
  352. package/templates/starter/src/app/starter-acceptance.video-export-settings.test.ts +2 -0
  353. package/templates/starter/src/app/starter-acceptance.video-reference-study.test.ts +34 -236
  354. package/templates/starter/src/app/starter-acceptance.view-interaction.test.ts +4 -0
  355. package/templates/starter/src/app/starter-acceptance.worklog-test-utils.ts +122 -6
  356. package/templates/starter/src/app/starter-acceptance.worklog.test.ts +152 -16
  357. package/templates/starter/src/app/starter-performance.gates.test.ts +20 -18
  358. package/templates/starter/src/app/starter-performance.lifecycle.test.ts +22 -6
  359. package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +3 -0
  360. package/templates/starter/tsconfig.json +1 -0
  361. package/templates/starter/scripts/toolcraft-browser-impact-selection.mjs +0 -26
  362. package/templates/starter/scripts/toolcraft-delivery-framework-refresh.test.mjs +0 -141
  363. package/templates/starter/scripts/toolcraft-delivery-functional-changed.test.mjs +0 -468
  364. package/templates/starter/scripts/toolcraft-delivery-functional-model-lifecycle.test.mjs +0 -254
  365. package/templates/starter/scripts/toolcraft-delivery-functional-semantic-regression.test.mjs +0 -135
  366. package/templates/starter/scripts/toolcraft-delivery-performance-iteration-durability.test.mjs +0 -329
  367. package/templates/starter/scripts/toolcraft-delivery-plan-errors.test.mjs +0 -430
  368. package/templates/starter/scripts/toolcraft-delivery-plan-functional-model.test.mjs +0 -358
  369. package/templates/starter/scripts/toolcraft-functional-proof-regression-fixtures.mjs +0 -298
  370. package/templates/starter/scripts/toolcraft-verification-impact-inventory.d.mts +0 -62
  371. package/templates/starter/scripts/toolcraft-verification-impact-inventory.mjs +0 -344
  372. package/templates/starter/scripts/toolcraft-verification-impact-inventory.test.mjs +0 -204
  373. package/templates/starter/scripts/toolcraft-verification-impact-performance-candidates.test.mjs +0 -210
  374. package/templates/starter/scripts/toolcraft-verification-impact-resolution.mjs +0 -344
  375. package/templates/starter/scripts/toolcraft-verification-impact-resolution.test.mjs +0 -270
  376. package/templates/starter/scripts/toolcraft-verification-impact-semantic-resolution.test.mjs +0 -449
  377. package/templates/starter/scripts/toolcraft-verification-impact-support-resolution.test.mjs +0 -195
  378. package/templates/starter/scripts/toolcraft-verification-impact.d.mts +0 -132
  379. package/templates/starter/scripts/toolcraft-verification-impact.mjs +0 -169
  380. package/templates/starter/scripts/toolcraft-verification-impact.test.mjs +0 -300
  381. package/templates/starter/scripts/toolcraft-verification-input-roles.mjs +0 -197
  382. package/templates/starter/scripts/toolcraft-verification-input-roles.test.mjs +0 -225
  383. package/templates/starter/src/app/acceptance/video-reference-study.ts +0 -217
  384. package/templates/starter/src/app/starter-verification-impact.json +0 -15
@@ -0,0 +1,90 @@
1
+ import { validateBehaviorCoverage } from "./motion-reference-study-behaviors";
2
+ import { validateStudyCoverage } from "./motion-reference-study-coverage";
3
+ import {
4
+ getMotionReferenceSourceSha256,
5
+ validateStudyIdentity,
6
+ } from "./motion-reference-study-identity";
7
+ import { validatePartitionCoverage } from "./motion-reference-study-partitions";
8
+ import type {
9
+ ToolcraftComponentAcceptance,
10
+ ToolcraftTransferMode,
11
+ } from "./types";
12
+
13
+ export function getToolcraftMotionReferenceStudyErrors({
14
+ acceptance,
15
+ transferMode,
16
+ }: {
17
+ acceptance: readonly ToolcraftComponentAcceptance[];
18
+ transferMode: ToolcraftTransferMode;
19
+ }): string[] {
20
+ const errors: string[] = [];
21
+ const acceptanceRowsById = new Map<string, ToolcraftComponentAcceptance[]>();
22
+ for (const entry of acceptance) {
23
+ acceptanceRowsById.set(entry.id, [
24
+ ...(acceptanceRowsById.get(entry.id) ?? []),
25
+ entry,
26
+ ]);
27
+ }
28
+ const referenceIds = new Set<string>();
29
+ const sourceOwners = new Map<string, string>();
30
+ const behaviorCountsByReferenceId = new Map<string, Map<string, number>>();
31
+
32
+ for (const input of transferMode.referenceInputs) {
33
+ if (referenceIds.has(input.referenceId)) {
34
+ errors.push(`motion reference id "${input.referenceId}" is duplicated.`);
35
+ }
36
+ referenceIds.add(input.referenceId);
37
+
38
+ errors.push(
39
+ ...validateStudyIdentity(input),
40
+ ...validateStudyCoverage(input),
41
+ ...validatePartitionCoverage(input),
42
+ ...validateBehaviorCoverage(input, acceptanceRowsById),
43
+ );
44
+
45
+ const sourceSha256 = getMotionReferenceSourceSha256(input);
46
+ if (sourceSha256) {
47
+ const existingOwner = sourceOwners.get(sourceSha256);
48
+ if (existingOwner) {
49
+ errors.push(
50
+ `motion reference sourceSha256 "${sourceSha256}" is declared by multiple reference inputs; merge their studies under one input.`,
51
+ );
52
+ } else {
53
+ sourceOwners.set(sourceSha256, input.referenceId);
54
+ }
55
+ }
56
+
57
+ const behaviorCounts =
58
+ behaviorCountsByReferenceId.get(input.referenceId) ??
59
+ new Map<string, number>();
60
+ for (const behavior of input.behaviors) {
61
+ behaviorCounts.set(
62
+ behavior.id,
63
+ (behaviorCounts.get(behavior.id) ?? 0) + 1,
64
+ );
65
+ }
66
+ behaviorCountsByReferenceId.set(input.referenceId, behaviorCounts);
67
+ }
68
+
69
+ for (const acceptanceEntry of acceptance) {
70
+ for (const coverage of acceptanceEntry.motionReferenceCoverage ?? []) {
71
+ const behaviorCount =
72
+ behaviorCountsByReferenceId
73
+ .get(coverage.referenceId)
74
+ ?.get(coverage.behaviorId) ?? 0;
75
+ if (behaviorCount === 0) {
76
+ errors.push(
77
+ `acceptance "${acceptanceEntry.id}" has dangling motion reference coverage for "${coverage.referenceId}" behavior "${coverage.behaviorId}".`,
78
+ );
79
+ } else if (behaviorCount > 1) {
80
+ errors.push(
81
+ `acceptance "${acceptanceEntry.id}" motion reference coverage for "${coverage.referenceId}" behavior "${coverage.behaviorId}" resolves to ${behaviorCount} behavior definitions; expected exactly one.`,
82
+ );
83
+ }
84
+ }
85
+ }
86
+
87
+ return [...new Set(errors)].sort((left, right) =>
88
+ left.localeCompare(right, "en"),
89
+ );
90
+ }
@@ -3,6 +3,7 @@ import { defineToolcraft } from "@repo/toolcraft-runtime";
3
3
 
4
4
  import {
5
5
  schemaHasPngExportPanelAction,
6
+ schemaHasSvgExportPanelAction,
6
7
  schemaHasVideoExportPanelAction,
7
8
  } from "./output-export-actions";
8
9
 
@@ -16,6 +17,11 @@ function createOutputSchema() {
16
17
  controls: {
17
18
  output: {
18
19
  actions: [
20
+ {
21
+ label: "Guardar vector",
22
+ role: "export-svg",
23
+ value: "salida.vector",
24
+ },
19
25
  {
20
26
  label: "Guardar imagen",
21
27
  role: "export-image",
@@ -41,10 +47,11 @@ function createOutputSchema() {
41
47
  }
42
48
 
43
49
  describe("Toolcraft typed output action roles", () => {
44
- it("detects image and video export without parsing labels or values", () => {
50
+ it("detects image, SVG, and video export without parsing labels or values", () => {
45
51
  const schema = createOutputSchema();
46
52
 
47
53
  expect(schemaHasPngExportPanelAction(schema)).toBe(true);
54
+ expect(schemaHasSvgExportPanelAction(schema)).toBe(true);
48
55
  expect(schemaHasVideoExportPanelAction(schema)).toBe(true);
49
56
  });
50
57
 
@@ -71,6 +78,7 @@ describe("Toolcraft typed output action roles", () => {
71
78
  });
72
79
 
73
80
  expect(schemaHasPngExportPanelAction(schema)).toBe(false);
81
+ expect(schemaHasSvgExportPanelAction(schema)).toBe(false);
74
82
  expect(schemaHasVideoExportPanelAction(schema)).toBe(false);
75
83
  });
76
84
  });
@@ -1,34 +1,26 @@
1
1
  import type {
2
2
  ResolvedToolcraftAppSchema,
3
- ToolcraftActionSchema,
3
+ ToolcraftArtifactExportActionRole,
4
4
  } from "@repo/toolcraft-runtime";
5
+ import { getToolcraftArtifactExportActions } from "@repo/toolcraft-runtime";
5
6
 
6
- import { getControlActions } from "./actions";
7
-
8
- function actionLooksLikePngExport(action: ToolcraftActionSchema | string): boolean {
9
- return typeof action !== "string" && action.role === "export-image";
7
+ function schemaHasExportPanelAction(
8
+ schema: ResolvedToolcraftAppSchema,
9
+ role: ToolcraftArtifactExportActionRole,
10
+ ): boolean {
11
+ return getToolcraftArtifactExportActions(schema).some(
12
+ (action) => action.role === role,
13
+ );
10
14
  }
11
15
 
12
- function actionLooksLikeVideoExport(action: ToolcraftActionSchema | string): boolean {
13
- return typeof action !== "string" && action.role === "export-video";
16
+ export function schemaHasPngExportPanelAction(schema: ResolvedToolcraftAppSchema): boolean {
17
+ return schemaHasExportPanelAction(schema, "export-image");
14
18
  }
15
19
 
16
- export function schemaHasPngExportPanelAction(schema: ResolvedToolcraftAppSchema): boolean {
17
- return (schema.panels.controls?.sections ?? []).some((section) =>
18
- Object.values(section.controls).some(
19
- (control) =>
20
- control.type === "panelActions" &&
21
- getControlActions(control).some(actionLooksLikePngExport),
22
- ),
23
- );
20
+ export function schemaHasSvgExportPanelAction(schema: ResolvedToolcraftAppSchema): boolean {
21
+ return schemaHasExportPanelAction(schema, "export-svg");
24
22
  }
25
23
 
26
24
  export function schemaHasVideoExportPanelAction(schema: ResolvedToolcraftAppSchema): boolean {
27
- return (schema.panels.controls?.sections ?? []).some((section) =>
28
- Object.values(section.controls).some(
29
- (control) =>
30
- control.type === "panelActions" &&
31
- getControlActions(control).some(actionLooksLikeVideoExport),
32
- ),
33
- );
25
+ return schemaHasExportPanelAction(schema, "export-video");
34
26
  }
@@ -8,7 +8,11 @@ export function getToolcraftOutputExportLayoutErrors({
8
8
  delivery: ToolcraftArtifactExportDelivery;
9
9
  facts: ToolcraftOutputExportFacts;
10
10
  }): string[] {
11
- if (!delivery.imageEnabled && !delivery.videoEnabled) {
11
+ if (
12
+ !delivery.imageEnabled &&
13
+ !delivery.svgEnabled &&
14
+ !delivery.videoEnabled
15
+ ) {
12
16
  return [];
13
17
  }
14
18
 
@@ -6,6 +6,7 @@ import type {
6
6
  import { getControlLabelText } from "./controls";
7
7
  import {
8
8
  schemaHasPngExportPanelAction,
9
+ schemaHasSvgExportPanelAction,
9
10
  schemaHasVideoExportPanelAction,
10
11
  } from "./output-export-actions";
11
12
  import { normalizeToolcraftSemanticText } from "./semantic";
@@ -19,6 +20,7 @@ export type ToolcraftOutputExportFacts = {
19
20
  backgroundSection: ToolcraftControlsSection | undefined;
20
21
  finalExportSettingsIndex: number;
21
22
  hasImageExportAction: boolean;
23
+ hasSvgExportAction: boolean;
22
24
  hasVideoExportAction: boolean;
23
25
  imageExportSection: ToolcraftControlsSection | undefined;
24
26
  imageExportSectionIndex: number;
@@ -148,6 +150,7 @@ export function buildToolcraftOutputExportFacts({
148
150
  "Video Export",
149
151
  );
150
152
  const hasImageExportAction = schemaHasPngExportPanelAction(schema);
153
+ const hasSvgExportAction = schemaHasSvgExportPanelAction(schema);
151
154
  const hasVideoExportAction = schemaHasVideoExportPanelAction(schema);
152
155
 
153
156
  return {
@@ -159,6 +162,7 @@ export function buildToolcraftOutputExportFacts({
159
162
  ? imageExportSectionIndex
160
163
  : -1,
161
164
  hasImageExportAction,
165
+ hasSvgExportAction,
162
166
  hasVideoExportAction,
163
167
  imageExportSection,
164
168
  imageExportSectionIndex,
@@ -7,6 +7,7 @@ import {
7
7
  } from "./output-background-rules";
8
8
  import {
9
9
  schemaHasPngExportPanelAction,
10
+ schemaHasSvgExportPanelAction,
10
11
  schemaHasVideoExportPanelAction,
11
12
  } from "./output-export-actions";
12
13
  import { getToolcraftOutputExportLayoutErrors } from "./output-export-layout-rules";
@@ -23,6 +24,7 @@ import type {
23
24
  export {
24
25
  isOutputBackgroundToggleControl,
25
26
  schemaHasPngExportPanelAction,
27
+ schemaHasSvgExportPanelAction,
26
28
  schemaHasVideoExportPanelAction,
27
29
  };
28
30
 
@@ -50,6 +52,7 @@ export function getToolcraftOutputExportErrors({
50
52
  validateToolcraftArtifactExportIntentCorrespondence({
51
53
  hasImageExportAction: facts.hasImageExportAction,
52
54
  hasImageExportSection: facts.imageExportSection !== undefined,
55
+ hasSvgExportAction: facts.hasSvgExportAction,
53
56
  hasVideoExportAction: facts.hasVideoExportAction,
54
57
  hasVideoExportSection: facts.videoExportSection !== undefined,
55
58
  intent: productReadiness.exportIntent,
@@ -59,7 +62,7 @@ export function getToolcraftOutputExportErrors({
59
62
  ...intentErrors,
60
63
  ...(delivery.imageEnabled ? getToolcraftImageExportErrors(facts) : []),
61
64
  ...(delivery.videoEnabled ? getToolcraftVideoExportErrors(facts) : []),
62
- ...(delivery.imageEnabled || delivery.videoEnabled
65
+ ...(delivery.imageEnabled || delivery.svgEnabled || delivery.videoEnabled
63
66
  ? getToolcraftOutputBackgroundErrors({ controls, facts })
64
67
  : []),
65
68
  ...getToolcraftOutputExportLayoutErrors({ delivery, facts }),
@@ -12,36 +12,186 @@ export type ToolcraftReferenceStudyEvidence = {
12
12
  status: ToolcraftReferenceStudyStatus;
13
13
  };
14
14
 
15
- export type ToolcraftVideoReferenceStoryboardFrame = {
16
- behaviorObservation: string;
15
+ export type ToolcraftMotionReferenceTimingMode = "ordinal" | "seconds";
16
+
17
+ export type ToolcraftMotionReferenceSourceKind =
18
+ | "contact-sheet"
19
+ | "frame-sequence"
20
+ | "gif"
21
+ | "screen-recording"
22
+ | "video";
23
+
24
+ type ToolcraftMotionReferenceFrameBase = {
25
+ cell: Readonly<{ column: number; row: number }>;
17
26
  frameId: string;
18
- frameSource: string;
19
- timeSeconds: number;
20
- visualObservation: string;
27
+ sourceFrameIndex: number;
28
+ sourceLocator: string;
29
+ sourceSha256: string;
21
30
  };
22
31
 
23
- export type ToolcraftVideoReferenceTransition = {
24
- behaviorDelta: string;
32
+ export type ToolcraftMotionReferenceOrdinalFrame =
33
+ ToolcraftMotionReferenceFrameBase & { timeSeconds?: never };
34
+
35
+ export type ToolcraftMotionReferenceTimedFrame =
36
+ ToolcraftMotionReferenceFrameBase & { timeSeconds: number };
37
+
38
+ export type ToolcraftMotionReferenceEvidenceEvent = {
39
+ afterFrameId: string;
40
+ beforeFrameId: string;
41
+ eventId: string;
42
+ kind: "change" | "loop-seam";
43
+ peakFrameId: string;
44
+ score: number;
45
+ windowFrameIds: readonly string[];
46
+ };
47
+
48
+ type ToolcraftMotionReferenceEvidenceBase = {
49
+ changeMetric: "max-yuva-diff-v1";
50
+ contactSheet: Readonly<{
51
+ columns: number;
52
+ height: number;
53
+ path: `src/app/reference-studies/${string}/contact-sheet.png`;
54
+ rows: number;
55
+ sha256: string;
56
+ width: number;
57
+ }>;
58
+ decodedFrameCount: number;
59
+ detectedEvents: readonly ToolcraftMotionReferenceEvidenceEvent[];
60
+ evidenceVersion: 1;
61
+ ffmpegVersion: string;
62
+ ffprobeVersion: string;
63
+ height: number;
64
+ scannedFrameCount: number;
65
+ sourceBasename: string;
66
+ sourceSha256: string;
67
+ studyId: string;
68
+ width: number;
69
+ };
70
+
71
+ export type ToolcraftMotionReferenceEvidence =
72
+ ToolcraftMotionReferenceEvidenceBase &
73
+ (
74
+ | {
75
+ sourceGrid: Readonly<{ columns: number; rows: number }>;
76
+ sourceKind: "contact-sheet";
77
+ }
78
+ | {
79
+ sourceGrid?: never;
80
+ sourceKind: Exclude<
81
+ ToolcraftMotionReferenceSourceKind,
82
+ "contact-sheet"
83
+ >;
84
+ }
85
+ ) &
86
+ (
87
+ | {
88
+ focusWindows: readonly [];
89
+ overviewFrameIds: readonly string[];
90
+ reviewedFrames: readonly ToolcraftMotionReferenceOrdinalFrame[];
91
+ timingMode: "ordinal";
92
+ }
93
+ | {
94
+ durationSeconds: number;
95
+ focusWindows: readonly Readonly<{
96
+ endSeconds: number;
97
+ frameIds: readonly string[];
98
+ sourceFrameEndIndex: number;
99
+ sourceFrameStartIndex: number;
100
+ startSeconds: number;
101
+ }>[];
102
+ maximumSourceFrameGapSeconds: number;
103
+ nominalFrameRate?: number;
104
+ overviewFrameIds: readonly string[];
105
+ overviewTargetFps: number;
106
+ reviewPartition?: Readonly<{
107
+ count: number;
108
+ groupId: `motion-group-v1-${string}`;
109
+ index: number;
110
+ planSha256: string;
111
+ scope: Readonly<{ endSeconds: number; startSeconds: number }>;
112
+ }>;
113
+ reviewedFrames: readonly ToolcraftMotionReferenceTimedFrame[];
114
+ segment?: Readonly<{ endSeconds: number; startSeconds: number }>;
115
+ timing: Readonly<
116
+ | { authority: "decoded-timestamps" }
117
+ | { authority: "declared-fps"; framesPerSecond: number }
118
+ | {
119
+ authority: "declared-timestamps";
120
+ timestampsSha256: string;
121
+ }
122
+ >;
123
+ timingMode: "seconds";
124
+ }
125
+ );
126
+
127
+ export type ToolcraftMotionReferencePhase = {
128
+ behaviorIds: readonly string[];
25
129
  fromFrameId: string;
26
130
  id: string;
27
131
  toFrameId: string;
132
+ visualState: string;
28
133
  };
29
134
 
30
- export type ToolcraftVideoReferenceAcceptanceMapping = {
135
+ export type ToolcraftMotionReferenceEvent = {
136
+ evidenceEventId: string;
137
+ id: string;
138
+ } &
139
+ (
140
+ | {
141
+ behaviorIds: readonly string[];
142
+ classification: "product-behavior";
143
+ reason?: never;
144
+ }
145
+ | {
146
+ behaviorIds: readonly [];
147
+ classification:
148
+ | "edit-boundary"
149
+ | "encoding-artifact"
150
+ | "irrelevant-change";
151
+ reason: string;
152
+ }
153
+ );
154
+
155
+ export type ToolcraftMotionReferenceTimingClaim =
156
+ | "cadence"
157
+ | "duration"
158
+ | "easing"
159
+ | "loop-seam"
160
+ | "speed";
161
+
162
+ export type ToolcraftMotionReferenceBehavior = {
31
163
  acceptanceId: string;
32
- behavior: string;
33
- frameIds: readonly string[];
164
+ description: string;
165
+ id: string;
166
+ implementationIntent: string;
167
+ timingClaims: readonly Readonly<{
168
+ claim: ToolcraftMotionReferenceTimingClaim;
169
+ studyId: string;
170
+ }>[];
34
171
  };
35
172
 
36
- export type ToolcraftVideoReferenceStudyEvidence = {
37
- acceptanceMapping: readonly ToolcraftVideoReferenceAcceptanceMapping[];
38
- behaviorDecomposition: string;
39
- extractionEvidence: string;
40
- referenceLocation: string;
41
- storyboard: readonly ToolcraftVideoReferenceStoryboardFrame[];
42
- transitionAnalysis: readonly ToolcraftVideoReferenceTransition[];
173
+ export type ToolcraftMotionReferenceStudy = {
174
+ evidence: ToolcraftMotionReferenceEvidence;
175
+ evidencePath: `src/app/reference-studies/${string}/evidence.json`;
176
+ events: readonly ToolcraftMotionReferenceEvent[];
177
+ phases: readonly ToolcraftMotionReferencePhase[];
178
+ studyId: string;
43
179
  };
44
180
 
181
+ export type ToolcraftMotionReferenceInput = {
182
+ behaviors: readonly ToolcraftMotionReferenceBehavior[];
183
+ kind: "motion-reference";
184
+ referenceId: `motion-reference-v1-${string}`;
185
+ studies: readonly ToolcraftMotionReferenceStudy[];
186
+ };
187
+
188
+ export type ToolcraftReferenceInput = ToolcraftMotionReferenceInput;
189
+
190
+ export type ToolcraftMotionReferenceCoverage = Readonly<{
191
+ behaviorId: string;
192
+ referenceId: ToolcraftMotionReferenceInput["referenceId"];
193
+ }>;
194
+
45
195
  export type ToolcraftReferenceFeatureStatus =
46
196
  | "intentionally-changed"
47
197
  | "ported"
@@ -9,6 +9,7 @@ import {
9
9
  } from "./coverage";
10
10
  import {
11
11
  schemaHasPngExportPanelAction,
12
+ schemaHasSvgExportPanelAction,
12
13
  schemaHasVideoExportPanelAction,
13
14
  } from "./output-export";
14
15
  import type {
@@ -178,7 +179,11 @@ export function getToolcraftCanvasSizingCoverageErrors({
178
179
  const errors: string[] = [];
179
180
 
180
181
  if (schema.canvas.sizing.mode === "fixed-output") {
181
- if (schemaHasPngExportPanelAction(schema) || schemaHasVideoExportPanelAction(schema)) {
182
+ if (
183
+ schemaHasPngExportPanelAction(schema) ||
184
+ schemaHasSvgExportPanelAction(schema) ||
185
+ schemaHasVideoExportPanelAction(schema)
186
+ ) {
182
187
  errors.push(
183
188
  'Product/output apps with export actions must use canvas.sizing mode "editable-output" so Aspect ratio, Canvas width, and Canvas height are always available. Put reference, fixed-format, or user-requested dimensions in canvas.size as the initial value instead of hiding size controls with "fixed-output".',
184
189
  );
@@ -0,0 +1,200 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import type {
4
+ ToolcraftComponentAcceptance,
5
+ ToolcraftInteractionOwnershipEntry,
6
+ ToolcraftProductReadiness,
7
+ } from "./types";
8
+ import { getToolcraftSelectionScopeErrors } from "./selection-scope";
9
+
10
+ const selectionAcceptance: ToolcraftComponentAcceptance = {
11
+ automated: true,
12
+ automatedTestName: "selection updates the active shape",
13
+ browser: true,
14
+ browserTestName: "browser: selection updates the active shape",
15
+ componentType: "canvas selection",
16
+ evidence: "command-side-effect",
17
+ expectedObservable: "Selecting either shape updates the active shape.",
18
+ fixture: "two separated visible shapes",
19
+ id: "shape.selection",
20
+ interactionId: "shape-selection",
21
+ kind: "runtime",
22
+ target: "selection.activeShape",
23
+ userAction: "Select each shape.",
24
+ };
25
+
26
+ const fillAcceptance: ToolcraftComponentAcceptance = {
27
+ automated: true,
28
+ automatedTestName: "selected fill changes only the active shape",
29
+ browser: true,
30
+ browserTestName: "browser: selected fill changes only the active shape",
31
+ componentType: "color",
32
+ evidence: "product-output",
33
+ expectedObservable: "Only the selected shape changes fill.",
34
+ fixture: "two separated visible shapes",
35
+ id: "shape.selected-fill",
36
+ interactionId: "shape-fill",
37
+ kind: "control",
38
+ selectionScopeCoverage: "two-entity-isolation",
39
+ target: "selectedShape.fill",
40
+ userAction: "Select each shape and edit Fill.",
41
+ };
42
+
43
+ function readiness(
44
+ interactionOwnership: readonly ToolcraftInteractionOwnershipEntry[],
45
+ ): ToolcraftProductReadiness {
46
+ return {
47
+ exportIntent: {
48
+ image: { mode: "toolcraft-default" },
49
+ svg: { mode: "not-requested" },
50
+ video: { mode: "not-requested" },
51
+ },
52
+ interactionOwnership,
53
+ mode: "product",
54
+ productName: "Selection fixture",
55
+ productSummary: "Two shapes with selected-entity property editing.",
56
+ requestedBehavior: "Select either shape and edit only that shape.",
57
+ viewInteraction: {
58
+ mode: "non-spatial",
59
+ reason: "The fixture uses a fixed two-dimensional editing view.",
60
+ },
61
+ };
62
+ }
63
+
64
+ const validOwnership = [
65
+ {
66
+ alternative: {
67
+ reason: "A panel selector would separate selection from visible shapes.",
68
+ surface: "panel",
69
+ },
70
+ capability: "spatial-selection",
71
+ evidence: {
72
+ detail: "The user requested direct selection on the visible canvas.",
73
+ source: "user-request",
74
+ },
75
+ id: "shape-selection",
76
+ reason: "Canvas selection provides immediate spatial target feedback.",
77
+ surface: "canvas",
78
+ target: "selection.activeShape",
79
+ },
80
+ {
81
+ alternative: {
82
+ reason: "A canvas color editor would duplicate panel property editing.",
83
+ surface: "canvas",
84
+ },
85
+ capability: "property-edit",
86
+ evidence: {
87
+ detail: "The user requested built-in panel controls for shape properties.",
88
+ source: "user-request",
89
+ },
90
+ id: "shape-fill",
91
+ reason: "The panel keeps exact color entry accessible and discoverable.",
92
+ selectionScope: {
93
+ mode: "selected-entity",
94
+ selectionInteractionId: "shape-selection",
95
+ },
96
+ surface: "panel",
97
+ target: "selectedShape.fill",
98
+ },
99
+ ] as const;
100
+
101
+ describe("Toolcraft selection scope", () => {
102
+ it("accepts a linked two-entity selected-property proof", () => {
103
+ expect(
104
+ getToolcraftSelectionScopeErrors({
105
+ acceptance: [selectionAcceptance, fillAcceptance],
106
+ layersEnabled: false,
107
+ productReadiness: readiness(validOwnership),
108
+ }),
109
+ ).toEqual([]);
110
+ });
111
+
112
+ it("allows an explicitly global property without isolation coverage", () => {
113
+ const globalOwnership = [
114
+ {
115
+ ...validOwnership[1],
116
+ id: "scene-background",
117
+ selectionScope: { mode: "global" },
118
+ target: "scene.background",
119
+ },
120
+ ] as const;
121
+ const globalAcceptance = {
122
+ ...fillAcceptance,
123
+ id: "scene.background",
124
+ interactionId: "scene-background",
125
+ selectionScopeCoverage: undefined,
126
+ target: "scene.background",
127
+ };
128
+
129
+ expect(
130
+ getToolcraftSelectionScopeErrors({
131
+ acceptance: [globalAcceptance],
132
+ layersEnabled: false,
133
+ productReadiness: readiness(globalOwnership),
134
+ }),
135
+ ).toEqual([]);
136
+ });
137
+
138
+ it("rejects omitted scope, invalid selection links, and missing isolation", () => {
139
+ const malformed = [
140
+ {
141
+ ...validOwnership[1],
142
+ selectionScope: undefined,
143
+ },
144
+ {
145
+ ...validOwnership[1],
146
+ id: "wrong-link",
147
+ selectionScope: {
148
+ mode: "selected-entity",
149
+ selectionInteractionId: "shape-fill",
150
+ },
151
+ },
152
+ ] as never;
153
+
154
+ expect(
155
+ getToolcraftSelectionScopeErrors({
156
+ acceptance: [
157
+ selectionAcceptance,
158
+ { ...fillAcceptance, selectionScopeCoverage: undefined },
159
+ ],
160
+ layersEnabled: false,
161
+ productReadiness: readiness(malformed),
162
+ }),
163
+ ).toEqual(
164
+ expect.arrayContaining([
165
+ expect.stringContaining("must declare selectionScope"),
166
+ expect.stringContaining(
167
+ "must reference spatial-selection or structured-selection",
168
+ ),
169
+ expect.stringContaining("two-entity-isolation"),
170
+ ]),
171
+ );
172
+ });
173
+
174
+ it("rejects meaningless isolation metadata", () => {
175
+ expect(
176
+ getToolcraftSelectionScopeErrors({
177
+ acceptance: [
178
+ {
179
+ ...fillAcceptance,
180
+ interactionId: "scene-background",
181
+ target: "scene.background",
182
+ },
183
+ ],
184
+ layersEnabled: false,
185
+ productReadiness: readiness([
186
+ {
187
+ ...validOwnership[1],
188
+ id: "scene-background",
189
+ selectionScope: { mode: "global" },
190
+ target: "scene.background",
191
+ },
192
+ ]),
193
+ }),
194
+ ).toEqual([
195
+ expect.stringContaining(
196
+ "without selected-entity ownership or a selectedLayer.* target",
197
+ ),
198
+ ]);
199
+ });
200
+ });