@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
@@ -1,80 +1,18 @@
1
- import type {
2
- ToolcraftFunctionalProofOwner,
3
- } from "./toolcraft-functional-proof-model.mjs";
4
1
  import {
5
2
  createToolcraftFunctionalProofModel,
6
3
  } from "./toolcraft-functional-proof-model.mjs";
7
4
  import type {
8
5
  ToolcraftDeliveryCatalog,
9
- ToolcraftVerificationImpactOwner,
10
- } from "./toolcraft-verification-impact.mjs";
6
+ } from "./playwright-test-title-selection.mjs";
11
7
 
12
- const functionalOwner: ToolcraftFunctionalProofOwner = {
13
- acceptanceIds: ["material.shape"],
14
- kind: "functional",
15
- path: "src/material.ts",
16
- };
17
- const presentationOwner: ToolcraftFunctionalProofOwner = {
18
- acceptanceIds: ["appearance.background"],
19
- kind: "presentation",
20
- path: "public/background.png",
21
- };
22
- const performanceOwner: ToolcraftFunctionalProofOwner = {
23
- acceptanceIds: ["material.shape"],
24
- kind: "performance",
25
- passIds: ["preview-composite"],
26
- path: "src/output.ts",
27
- };
28
- const invalidFunctional: ToolcraftFunctionalProofOwner = {
29
- acceptanceIds: ["material.shape"],
30
- kind: "functional",
31
- // @ts-expect-error Functional owners cannot carry renderer passes.
32
- passIds: ["preview-composite"],
33
- path: "src/material.ts",
34
- };
35
- const invalidPresentation: ToolcraftFunctionalProofOwner = {
36
- acceptanceIds: ["appearance.background"],
37
- kind: "presentation",
38
- // @ts-expect-error Presentation owners cannot carry renderer passes.
39
- passIds: ["preview-composite"],
40
- path: "public/background.png",
41
- };
42
- // @ts-expect-error Performance owners require renderer passes.
43
- const invalidPerformance: ToolcraftFunctionalProofOwner = {
44
- acceptanceIds: ["material.shape"],
45
- kind: "performance",
46
- path: "src/output.ts",
47
- };
48
- const publicFunctionalOwner: ToolcraftVerificationImpactOwner = {
49
- acceptanceIds: ["material.shape"],
50
- kind: "functional",
51
- path: "src/material.ts",
52
- };
53
- const invalidPublicFunctionalOwner: ToolcraftVerificationImpactOwner = {
54
- acceptanceIds: ["material.shape"],
55
- kind: "functional",
56
- // @ts-expect-error Functional impact owners cannot carry passIds.
57
- passIds: ["preview-composite"],
58
- path: "src/material.ts",
59
- };
60
- // @ts-expect-error Performance impact owners require passIds.
61
- const invalidPublicPerformanceOwner: ToolcraftVerificationImpactOwner = {
62
- acceptanceIds: ["material.shape"],
63
- kind: "performance",
64
- path: "src/output.ts",
65
- };
66
- const sharedCurrentCatalog: ToolcraftDeliveryCatalog = {
8
+ const catalog: ToolcraftDeliveryCatalog = {
67
9
  acceptance: [],
68
10
  performance: [],
69
11
  version: 2,
70
12
  };
71
- const validCurrentModel = createToolcraftFunctionalProofModel({
72
- catalog: sharedCurrentCatalog,
73
- inventory: {
74
- owners: [],
75
- version: 3,
76
- },
77
- });
13
+
14
+ const model = createToolcraftFunctionalProofModel({ catalog });
15
+
78
16
  createToolcraftFunctionalProofModel({
79
17
  catalog: {
80
18
  acceptance: [],
@@ -82,21 +20,6 @@ createToolcraftFunctionalProofModel({
82
20
  // @ts-expect-error Delivery catalog is current-only v2.
83
21
  version: 3,
84
22
  },
85
- inventory: {
86
- owners: [],
87
- version: 3,
88
- },
89
23
  });
90
24
 
91
- void [
92
- functionalOwner,
93
- presentationOwner,
94
- performanceOwner,
95
- invalidFunctional,
96
- invalidPresentation,
97
- invalidPerformance,
98
- publicFunctionalOwner,
99
- invalidPublicFunctionalOwner,
100
- invalidPublicPerformanceOwner,
101
- validCurrentModel,
102
- ];
25
+ void model;
@@ -1,5 +1,16 @@
1
1
  export function serializeToolcraftCanonicalJson(value: unknown): string;
2
2
  export function createToolcraftCanonicalJsonHash(value: unknown): string;
3
+ export function hasToolcraftExactRecordKeys(
4
+ value: unknown,
5
+ keys: readonly string[],
6
+ ): boolean;
7
+ export function isToolcraftCanonicalTargetArray(
8
+ value: unknown,
9
+ options?: Readonly<{ empty?: boolean; paths?: boolean }>,
10
+ ): boolean;
11
+ export function isToolcraftDenseExactArray(value: unknown): value is unknown[];
12
+ export function deepFreezeToolcraftValue<T>(value: T): T;
13
+ export function isToolcraftDeeplyFrozen(value: unknown): boolean;
3
14
  export function deriveToolcraftAcceptanceDomainId(acceptanceId: string): string;
4
15
  export function createToolcraftAcceptanceContractHash(
5
16
  acceptanceEntry: unknown,
@@ -4,6 +4,67 @@ const compareCodeUnits = (left, right) => left < right ? -1 : left > right ? 1 :
4
4
  const isTrimmedString = (value) =>
5
5
  typeof value === "string" && value.length > 0 && value.trim() === value;
6
6
 
7
+ export function hasToolcraftExactRecordKeys(value, keys) {
8
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
9
+ return false;
10
+ }
11
+ const prototype = Object.getPrototypeOf(value);
12
+ if (prototype !== Object.prototype && prototype !== null) return false;
13
+ const ownKeys = Reflect.ownKeys(value);
14
+ return ownKeys.length === keys.length && ownKeys.every((key) =>
15
+ typeof key === "string" &&
16
+ keys.includes(key) &&
17
+ Object.prototype.propertyIsEnumerable.call(value, key)
18
+ );
19
+ }
20
+
21
+ export function isToolcraftCanonicalTargetArray(
22
+ value,
23
+ { empty = false, paths = false } = {},
24
+ ) {
25
+ const dense = isToolcraftDenseExactArray(value);
26
+ const valid = (item) =>
27
+ typeof item === "string" &&
28
+ item.length > 0 &&
29
+ item.trim() === item &&
30
+ (!paths || (
31
+ !item.includes("\\") &&
32
+ !item.startsWith("/") &&
33
+ !/^[A-Za-z]:\//u.test(item) &&
34
+ item.split("/").every((part) => part && part !== "." && part !== "..")
35
+ ));
36
+ return dense && (empty || value.length > 0) && value.every(valid) &&
37
+ value.every((item, index) =>
38
+ index === 0 || compareCodeUnits(value[index - 1], item) < 0
39
+ );
40
+ }
41
+
42
+ export function isToolcraftDenseExactArray(value) {
43
+ return (
44
+ Array.isArray(value) &&
45
+ Reflect.ownKeys(value).length === value.length + 1 &&
46
+ Array.from(
47
+ { length: value.length },
48
+ (_, index) => Object.hasOwn(value, index),
49
+ ).every(Boolean)
50
+ );
51
+ }
52
+
53
+ export function deepFreezeToolcraftValue(value) {
54
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
55
+ Object.values(value).forEach(deepFreezeToolcraftValue);
56
+ Object.freeze(value);
57
+ }
58
+ return value;
59
+ }
60
+
61
+ export function isToolcraftDeeplyFrozen(value) {
62
+ return !(value && typeof value === "object") || (
63
+ Object.isFrozen(value) &&
64
+ Object.values(value).every(isToolcraftDeeplyFrozen)
65
+ );
66
+ }
67
+
7
68
  export function serializeToolcraftCanonicalJson(value, ancestors = new Set()) {
8
69
  if (value === null || typeof value === "boolean" || typeof value === "string") {
9
70
  return JSON.stringify(value);
@@ -5,7 +5,12 @@ import test from "node:test";
5
5
  import {
6
6
  createToolcraftAcceptanceContractHash,
7
7
  createToolcraftCanonicalJsonHash,
8
+ deepFreezeToolcraftValue,
8
9
  deriveToolcraftAcceptanceDomainId,
10
+ hasToolcraftExactRecordKeys,
11
+ isToolcraftCanonicalTargetArray,
12
+ isToolcraftDeeplyFrozen,
13
+ isToolcraftDenseExactArray,
9
14
  serializeToolcraftCanonicalJson,
10
15
  } from "./toolcraft-functional-proof-primitives.mjs";
11
16
 
@@ -24,6 +29,44 @@ test("one primitive boundary owns canonical serialization and semantic hashes",
24
29
  assert.equal(deriveToolcraftAcceptanceDomainId("material.shape"), "material");
25
30
  });
26
31
 
32
+ test("canonical structural primitives reject ambiguous proof shapes", () => {
33
+ assert.equal(
34
+ hasToolcraftExactRecordKeys({ files: [], kind: "product-tests" }, [
35
+ "files",
36
+ "kind",
37
+ ]),
38
+ true,
39
+ );
40
+ assert.equal(
41
+ hasToolcraftExactRecordKeys({ files: [], kind: "product-tests", extra: true }, [
42
+ "files",
43
+ "kind",
44
+ ]),
45
+ false,
46
+ );
47
+ assert.equal(isToolcraftDenseExactArray(["a"]), true);
48
+ assert.equal(isToolcraftDenseExactArray(Array(1)), false);
49
+ assert.equal(
50
+ isToolcraftCanonicalTargetArray(["src/app/a.ts", "src/app/b.ts"], {
51
+ paths: true,
52
+ }),
53
+ true,
54
+ );
55
+ assert.equal(
56
+ isToolcraftCanonicalTargetArray(["src/app/b.ts", "../a.ts"], {
57
+ paths: true,
58
+ }),
59
+ false,
60
+ );
61
+ });
62
+
63
+ test("canonical deep freeze preserves identity and proves nested immutability", () => {
64
+ const value = { nested: { acceptanceIds: ["output.updates"] } };
65
+
66
+ assert.equal(deepFreezeToolcraftValue(value), value);
67
+ assert.equal(isToolcraftDeeplyFrozen(value), true);
68
+ });
69
+
27
70
  test("canonical primitives reject symbol keys at every object depth", () => {
28
71
  const topLevel = { value: true, [Symbol("top")]: true };
29
72
  const nested = { nested: { value: true, [Symbol("nested")]: true } };
@@ -8,8 +8,10 @@ export const requiredPackageScriptNames = [
8
8
  "docs:check",
9
9
  "preview",
10
10
  "preview:restart",
11
+ "reference:study",
11
12
  "test",
12
13
  "test:browser",
14
+ "test:feature",
13
15
  "typecheck",
14
16
  "verify:delivery",
15
17
  "verify:kernel",
@@ -17,6 +19,12 @@ export const requiredPackageScriptNames = [
17
19
  "verify:receipt",
18
20
  ];
19
21
 
22
+ const requiredMotionReferenceTrustRootFilePaths = [
23
+ "scripts/create-toolcraft-motion-reference-study.mjs",
24
+ "src/app/acceptance/motion-reference-evidence.d.mts",
25
+ "src/app/acceptance/motion-reference-evidence.mjs",
26
+ ];
27
+
20
28
  export const reservedGeneratedVerificationConfigPatterns = [
21
29
  /^playwright\.config\.[cm]?[jt]s$/u,
22
30
  /^vite\.config\.[cm]?[jt]s$/u,
@@ -32,6 +40,7 @@ export const requiredProtectedTrustRootFilePaths = [
32
40
  "e2e/browser-performance-report.ts",
33
41
  "e2e/browser-runtime-evidence-reporter.ts",
34
42
  "e2e/browser-runtime-evidence-requirements.ts",
43
+ "e2e/toolcraft-feature-verification-reporter.ts",
35
44
  "e2e/performance-pipeline-evidence.ts",
36
45
  "e2e/toolcraft-product-test.ts",
37
46
  "playwright.config.ts",
@@ -40,6 +49,8 @@ export const requiredProtectedTrustRootFilePaths = [
40
49
  "scripts/run-browser-performance.mjs",
41
50
  "scripts/run-delivery-verification.mjs",
42
51
  "scripts/run-kernel-benchmarks.mjs",
52
+ "scripts/run-feature-verification.mjs",
53
+ "scripts/toolcraft-feature-verification-plan.mjs",
43
54
  "scripts/toolcraft-integrity-manifest.mjs",
44
55
  "scripts/toolcraft-integrity-policy.mjs",
45
56
  "scripts/toolcraft-product-boundary.mjs",
@@ -51,8 +62,10 @@ export const requiredProtectedTrustRootFilePaths = [
51
62
  "scripts/toolcraft-vitest-runtime-evidence-reporter.mjs",
52
63
  "scripts/toolcraft-workflow-routes.mjs",
53
64
  "src/app/acceptance/validation-pipeline.ts",
65
+ "src/app/acceptance/feature-verification-selection.ts",
54
66
  "src/app/app-automated-runtime-evidence.test.ts",
55
67
  "vite.config.ts",
68
+ ...requiredMotionReferenceTrustRootFilePaths,
56
69
  ];
57
70
 
58
71
  export const runtimeSurfaceComponentNames = Object.freeze([
@@ -9,7 +9,7 @@ import {
9
9
  } from "./toolcraft-integrity-policy.mjs";
10
10
 
11
11
  const fixtureManifestSignature =
12
- "qU2Tc5z8NqfzbGr7ZdcGhKtt6eLBkw+kJMvmTNq5cE3andSTf/tF3SUdwpNJ4nNSiSHn/x6FcP0/iKW98nEWDg==";
12
+ "KwSG36fxNC20k9czN8i/613IjmdGNj7SJXOdWjSXRlWIQwddFrC6lWf9moWCAjDP4bxke6j6pBLkdPt/xjopDw==";
13
13
  const runtimeSource = "export const runtime = true;\n";
14
14
 
15
15
  const sha256 = (value) =>
@@ -26,7 +26,11 @@ async function loadLayerEvidenceFacade(context) {
26
26
  '"./transition.mjs"',
27
27
  )
28
28
  .replaceAll('"./browser-runtime-evidence"', '"./evidence.mjs"')
29
- .replaceAll('"./browser-proof-session"', '"./proof-session.mjs"');
29
+ .replaceAll('"./browser-proof-session"', '"./proof-session.mjs"')
30
+ .replaceAll(
31
+ '"./browser-selection-scope-evidence"',
32
+ '"./selection-scope.mjs"',
33
+ );
30
34
  const { outputText } = ts.transpileModule(source, {
31
35
  compilerOptions: {
32
36
  module: ts.ModuleKind.ESNext,
@@ -88,6 +92,24 @@ async function loadLayerEvidenceFacade(context) {
88
92
  }
89
93
  `,
90
94
  ),
95
+ fs.writeFile(
96
+ path.join(outputDir, "selection-scope.mjs"),
97
+ `
98
+ export async function expectToolcraftSelectionScopedControl(options) {
99
+ globalThis.__toolcraftLayerSelectionScopeCalls.push(options);
100
+ globalThis.__toolcraftLayerEvidenceAttachments.push({
101
+ evidenceType: "product-observable-change",
102
+ requirementId: options.requirementId,
103
+ target: options.propertyTarget,
104
+ });
105
+ globalThis.__toolcraftLayerEvidenceAttachments.push({
106
+ evidenceType: "selection-scoped-control",
107
+ requirementId: options.requirementId,
108
+ target: options.propertyTarget,
109
+ });
110
+ }
111
+ `,
112
+ ),
91
113
  ]);
92
114
 
93
115
  return import(`${pathToFileURL(outputPath).href}?test=${Date.now()}`);
@@ -100,6 +122,7 @@ function setTransition(before, after) {
100
122
  test("layer recipes attach exact-target base and specialized evidence", async (context) => {
101
123
  const facade = await loadLayerEvidenceFacade(context);
102
124
  globalThis.__toolcraftLayerEvidenceAttachments = [];
125
+ globalThis.__toolcraftLayerSelectionScopeCalls = [];
103
126
  globalThis.__toolcraftLayerEvidenceTransitionCalls = 0;
104
127
  const action = { target: "layers.semantic-target" };
105
128
  const observation = {};
@@ -168,24 +191,11 @@ test("layer recipes attach exact-target base and specialized evidence", async (c
168
191
  options,
169
192
  );
170
193
 
171
- setTransition(
172
- {
173
- controlValue: 0,
174
- outputSignature: "before",
175
- selectedLayerId: "layer-a",
176
- },
177
- {
178
- controlValue: 1,
179
- outputSignature: "after",
180
- selectedLayerId: "layer-a",
181
- },
182
- );
183
- await facade.expectToolcraftSelectedLayerControl(
184
- observation,
185
- action,
186
- globalThis.__toolcraftLayerEvidenceTransition.after,
187
- options,
188
- );
194
+ const selectedLayerOptions = {
195
+ propertyTarget: action.target,
196
+ requirementId: options.requirementId,
197
+ };
198
+ await facade.expectToolcraftSelectedLayerControl(selectedLayerOptions);
189
199
 
190
200
  setTransition(
191
201
  { layerIds: ["layer-a"], outputSignature: "before" },
@@ -211,8 +221,6 @@ test("layer recipes attach exact-target base and specialized evidence", async (c
211
221
  ["product-observable-change", "layer-visibility"],
212
222
  ["product-observable-change", "layer-reorder"],
213
223
  ["product-observable-change", "layer-grouping"],
214
- ["media-lifecycle", "layer-selected-layer-controls"],
215
- ["media-lifecycle", "layer-media-lifecycle"],
216
224
  ].flatMap(([baseEvidenceType, specializedEvidenceType]) => [
217
225
  {
218
226
  evidenceType: baseEvidenceType,
@@ -225,12 +233,40 @@ test("layer recipes attach exact-target base and specialized evidence", async (c
225
233
  target: action.target,
226
234
  },
227
235
  ]),
236
+ {
237
+ evidenceType: "product-observable-change",
238
+ requirementId: options.requirementId,
239
+ target: action.target,
240
+ },
241
+ {
242
+ evidenceType: "selection-scoped-control",
243
+ requirementId: options.requirementId,
244
+ target: action.target,
245
+ },
246
+ {
247
+ evidenceType: "layer-selected-layer-controls",
248
+ requirementId: options.requirementId,
249
+ target: action.target,
250
+ },
251
+ {
252
+ evidenceType: "media-lifecycle",
253
+ requirementId: options.requirementId,
254
+ target: action.target,
255
+ },
256
+ {
257
+ evidenceType: "layer-media-lifecycle",
258
+ requirementId: options.requirementId,
259
+ target: action.target,
260
+ },
228
261
  ];
229
262
  assert.deepEqual(
230
263
  globalThis.__toolcraftLayerEvidenceAttachments,
231
264
  expectedEvidence,
232
265
  );
233
- assert.equal(globalThis.__toolcraftLayerEvidenceTransitionCalls, 6);
266
+ assert.equal(globalThis.__toolcraftLayerEvidenceTransitionCalls, 5);
267
+ assert.deepEqual(globalThis.__toolcraftLayerSelectionScopeCalls, [
268
+ selectedLayerOptions,
269
+ ]);
234
270
  });
235
271
 
236
272
  test("layer recipes fail before assertions or evidence when action has no target", async (context) => {
@@ -0,0 +1,111 @@
1
+ export const TOOLCRAFT_MOTION_ANALYSIS_COMPONENT_MAX = 255;
2
+ export const TOOLCRAFT_MOTION_CHANGE_METRIC = "max-yuva-diff-v1";
3
+ export const TOOLCRAFT_MOTION_FFMPEG_TIMESTAMP_TOLERANCE_SECONDS = 1e-6;
4
+
5
+ const PROBE_SHOW_ENTRIES =
6
+ "program_version=version:stream=codec_type,width,height,pix_fmt," +
7
+ "avg_frame_rate,r_frame_rate,nb_frames,duration,start_time:" +
8
+ "format=duration,start_time:" +
9
+ "frame=best_effort_timestamp_time,pts_time:pixel_format=name,nb_components:" +
10
+ "pixel_format_flags=alpha:pixel_format_components=index,bit_depth";
11
+
12
+ function fail(message) {
13
+ throw new TypeError(`Invalid Toolcraft motion analysis protocol: ${message}`);
14
+ }
15
+
16
+ export function createToolcraftMotionProbeArguments(inputPath) {
17
+ if (typeof inputPath !== "string" || inputPath.length === 0) {
18
+ fail("an input path is required for probing");
19
+ }
20
+ return [
21
+ "-v", "error", "-select_streams", "v:0",
22
+ "-show_program_version", "-show_pixel_formats",
23
+ "-show_streams", "-show_format", "-show_frames",
24
+ "-show_entries", PROBE_SHOW_ENTRIES,
25
+ "-of", "json", inputPath,
26
+ ];
27
+ }
28
+
29
+ export function createToolcraftMotionAnalysisGraph(inputLabel, hasAlpha) {
30
+ if (typeof inputLabel !== "string" || inputLabel.length === 0 ||
31
+ typeof hasAlpha !== "boolean") {
32
+ fail("an input label and alpha decision are required");
33
+ }
34
+ const color = "format=yuv444p,signalstats," +
35
+ "metadata=mode=add:key=toolcraft.channel:value=color," +
36
+ "metadata=print:file=-";
37
+ if (!hasAlpha) return `${inputLabel}${color}[colorout]`;
38
+ const alpha = "alphaextract,format=gray,signalstats," +
39
+ "metadata=mode=add:key=toolcraft.channel:value=alpha," +
40
+ "metadata=print:file=-";
41
+ return `${inputLabel}split=2[colorSource][alphaSource];` +
42
+ `[colorSource]${color}[colorout];[alphaSource]${alpha}[alphaout]`;
43
+ }
44
+
45
+ export function createToolcraftMotionAnalysisOutputArguments(hasAlpha) {
46
+ if (typeof hasAlpha !== "boolean") fail("an alpha decision is required");
47
+ return [
48
+ "-map", "[colorout]",
49
+ ...(hasAlpha ? ["-map", "[alphaout]"] : []),
50
+ "-f", "null", "-",
51
+ ];
52
+ }
53
+
54
+ export function toolcraftMotionTimestampsAgree(left, right) {
55
+ return typeof left === "number" && Number.isFinite(left) &&
56
+ typeof right === "number" && Number.isFinite(right) &&
57
+ Math.abs(left - right) <= TOOLCRAFT_MOTION_FFMPEG_TIMESTAMP_TOLERANCE_SECONDS;
58
+ }
59
+
60
+ export function toolcraftMotionAnalysisChangeScore(record) {
61
+ const values = [record?.yDifference, record?.uDifference, record?.vDifference,
62
+ ...(record?.alphaDifference === undefined ? [] : [record.alphaDifference])];
63
+ if (values.length < 3 || values.some((value) =>
64
+ typeof value !== "number" || !Number.isFinite(value) || value < 0 ||
65
+ value > TOOLCRAFT_MOTION_ANALYSIS_COMPONENT_MAX)) {
66
+ fail(`change components must be finite values between 0 and ${TOOLCRAFT_MOTION_ANALYSIS_COMPONENT_MAX}`);
67
+ }
68
+ return Math.max(...values) / TOOLCRAFT_MOTION_ANALYSIS_COMPONENT_MAX;
69
+ }
70
+
71
+ export function validateToolcraftMotionScanRecordAgreement(records, expectedTimes) {
72
+ if (!Array.isArray(records) || !Array.isArray(expectedTimes) ||
73
+ records.length !== expectedTimes.length || records.length === 0 ||
74
+ records.some((record, index) => record?.frameIndex !== index ||
75
+ !toolcraftMotionTimestampsAgree(record?.timeSeconds, expectedTimes[index]))) {
76
+ fail("decoded frame count, index, timestamp, and score agreement is required");
77
+ }
78
+ }
79
+
80
+ export function createToolcraftMotionLoopSeamScore(decodedFrameCount, records) {
81
+ if (!Number.isInteger(decodedFrameCount) || decodedFrameCount <= 0) {
82
+ fail("a positive decoded frame count is required");
83
+ }
84
+ if (decodedFrameCount === 1) {
85
+ if (records !== undefined) fail("single-frame sources cannot include seam records");
86
+ return 0;
87
+ }
88
+ if (!Array.isArray(records) || records.length !== 2) {
89
+ fail("loop seam requires exactly two frame records");
90
+ }
91
+ if (records[0]?.frameIndex !== 0 || records[1]?.frameIndex !== 1 ||
92
+ !(records[1]?.timeSeconds > records[0]?.timeSeconds)) {
93
+ fail("loop seam frame indices must be 0 then 1 with increasing timestamps");
94
+ }
95
+ return toolcraftMotionAnalysisChangeScore(records[1]);
96
+ }
97
+
98
+ export function createToolcraftMotionScanResult(records, loopSeamScore) {
99
+ if (!Array.isArray(records) || records.length === 0 ||
100
+ typeof loopSeamScore !== "number" || !Number.isFinite(loopSeamScore) ||
101
+ loopSeamScore < 0 || loopSeamScore > 1) {
102
+ fail("scan records and a normalized loop seam score are required");
103
+ }
104
+ return {
105
+ changeMetric: TOOLCRAFT_MOTION_CHANGE_METRIC,
106
+ changeScores: records.map(toolcraftMotionAnalysisChangeScore),
107
+ componentDifferences: records,
108
+ loopSeamScore,
109
+ scannedFrameCount: records.length,
110
+ };
111
+ }
@@ -0,0 +1,116 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import {
5
+ createToolcraftMotionAnalysisGraph,
6
+ createToolcraftMotionAnalysisOutputArguments,
7
+ createToolcraftMotionLoopSeamScore,
8
+ createToolcraftMotionProbeArguments,
9
+ createToolcraftMotionScanResult,
10
+ TOOLCRAFT_MOTION_ANALYSIS_COMPONENT_MAX,
11
+ TOOLCRAFT_MOTION_CHANGE_METRIC,
12
+ toolcraftMotionAnalysisChangeScore,
13
+ toolcraftMotionTimestampsAgree,
14
+ validateToolcraftMotionScanRecordAgreement,
15
+ } from "./toolcraft-motion-reference-analysis-protocol.mjs";
16
+
17
+ function record(frameIndex, timeSeconds, {
18
+ alphaDifference,
19
+ uDifference = 0,
20
+ vDifference = 0,
21
+ yDifference = 0,
22
+ } = {}) {
23
+ return {
24
+ ...(alphaDifference === undefined ? {} : { alphaDifference }),
25
+ frameIndex,
26
+ timeSeconds,
27
+ uDifference,
28
+ vDifference,
29
+ yDifference,
30
+ };
31
+ }
32
+
33
+ test("owns the exact ffprobe visual metadata and descriptor request", () => {
34
+ assert.deepEqual(createToolcraftMotionProbeArguments("/refs/input.mov"), [
35
+ "-v", "error", "-select_streams", "v:0",
36
+ "-show_program_version", "-show_pixel_formats",
37
+ "-show_streams", "-show_format", "-show_frames",
38
+ "-show_entries",
39
+ "program_version=version:stream=codec_type,width,height,pix_fmt,avg_frame_rate,r_frame_rate,nb_frames,duration,start_time:format=duration,start_time:frame=best_effort_timestamp_time,pts_time:pixel_format=name,nb_components:pixel_format_flags=alpha:pixel_format_components=index,bit_depth",
40
+ "-of", "json", "/refs/input.mov",
41
+ ]);
42
+ });
43
+
44
+ test("owns exact 8-bit color and conditional alpha stdout analysis graphs", () => {
45
+ assert.equal(createToolcraftMotionAnalysisGraph("[decoded]", false),
46
+ "[decoded]format=yuv444p,signalstats," +
47
+ "metadata=mode=add:key=toolcraft.channel:value=color," +
48
+ "metadata=print:file=-[colorout]");
49
+ assert.equal(createToolcraftMotionAnalysisGraph("[decoded]", true),
50
+ "[decoded]split=2[colorSource][alphaSource];" +
51
+ "[colorSource]format=yuv444p,signalstats," +
52
+ "metadata=mode=add:key=toolcraft.channel:value=color," +
53
+ "metadata=print:file=-[colorout];" +
54
+ "[alphaSource]alphaextract,format=gray,signalstats," +
55
+ "metadata=mode=add:key=toolcraft.channel:value=alpha," +
56
+ "metadata=print:file=-[alphaout]");
57
+ assert.deepEqual(createToolcraftMotionAnalysisOutputArguments(false), [
58
+ "-map", "[colorout]", "-f", "null", "-",
59
+ ]);
60
+ assert.deepEqual(createToolcraftMotionAnalysisOutputArguments(true), [
61
+ "-map", "[colorout]", "-map", "[alphaout]", "-f", "null", "-",
62
+ ]);
63
+ });
64
+
65
+ test("owns the single 8-bit component normalization authority", () => {
66
+ assert.equal(TOOLCRAFT_MOTION_ANALYSIS_COMPONENT_MAX, 255);
67
+ assert.equal(toolcraftMotionAnalysisChangeScore(record(0, 0, {
68
+ alphaDifference: 102,
69
+ uDifference: 51,
70
+ vDifference: 12,
71
+ })), 102 / TOOLCRAFT_MOTION_ANALYSIS_COMPONENT_MAX);
72
+ assert.throws(() => toolcraftMotionAnalysisChangeScore(record(0, 0, {
73
+ yDifference: 256,
74
+ })), /between 0 and 255/iu);
75
+ });
76
+
77
+ test("validates scan count, indices, and authoritative timestamps with one tolerance", () => {
78
+ const records = [record(0, 0), record(1, 0.1250004), record(2, 0.5)];
79
+ assert.equal(toolcraftMotionTimestampsAgree(0.1250004, 0.125), true);
80
+ assert.doesNotThrow(() => validateToolcraftMotionScanRecordAgreement(
81
+ records, [0, 0.125, 0.5],
82
+ ));
83
+ assert.throws(() => validateToolcraftMotionScanRecordAgreement(
84
+ records.slice(0, 2), [0, 0.125, 0.5],
85
+ ), /agreement/iu);
86
+ assert.throws(() => validateToolcraftMotionScanRecordAgreement(
87
+ [records[0], { ...records[1], frameIndex: 2 }, records[2]], [0, 0.125, 0.5],
88
+ ), /agreement/iu);
89
+ assert.throws(() => validateToolcraftMotionScanRecordAgreement(
90
+ [records[0], { ...records[1], timeSeconds: 0.13 }, records[2]], [0, 0.125, 0.5],
91
+ ), /agreement/iu);
92
+ });
93
+
94
+ test("owns single-frame zero and exact last-to-first seam cardinality", () => {
95
+ assert.equal(createToolcraftMotionLoopSeamScore(1), 0);
96
+ const seam = [record(0, 0), record(1, 1, { vDifference: 51 })];
97
+ assert.equal(createToolcraftMotionLoopSeamScore(3, seam), 51 / 255);
98
+ assert.throws(() => createToolcraftMotionLoopSeamScore(3, seam.slice(0, 1)),
99
+ /exactly two/iu);
100
+ assert.throws(() => createToolcraftMotionLoopSeamScore(3, [...seam, record(2, 2)]),
101
+ /exactly two/iu);
102
+ assert.throws(() => createToolcraftMotionLoopSeamScore(3, [seam[1], seam[0]]),
103
+ /indices|increasing/iu);
104
+ });
105
+
106
+ test("assembles one canonical scan result", () => {
107
+ const records = [record(0, 0), record(1, 1, { uDifference: 51 })];
108
+ assert.deepEqual(createToolcraftMotionScanResult(records, 0.25), {
109
+ changeMetric: TOOLCRAFT_MOTION_CHANGE_METRIC,
110
+ changeScores: [0, 51 / 255],
111
+ componentDifferences: records,
112
+ loopSeamScore: 0.25,
113
+ scannedFrameCount: 2,
114
+ });
115
+ assert.equal(TOOLCRAFT_MOTION_CHANGE_METRIC, "max-yuva-diff-v1");
116
+ });