@pixel-point/toolcraft 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/package.json +1 -1
  2. package/src/generate-performance-iteration-execution.test.mjs +2 -2
  3. package/src/generate-test-demand-only-lifecycle.mjs +14 -3
  4. package/src/generate-test-dependency-sandbox.mjs +42 -5
  5. package/src/generate-test-doc-assertions.mjs +109 -69
  6. package/src/generate-test-doc-assertions.test.mjs +65 -0
  7. package/src/generate-test-doc-policy-assertions.mjs +92 -0
  8. package/src/generate-test-file-assertions.mjs +36 -118
  9. package/src/generate-test-output-assertions.mjs +95 -0
  10. package/src/generate-test-package-assertions.mjs +6 -0
  11. package/src/generate-test-performance-boundary-assertions.mjs +45 -0
  12. package/src/generate-test-product-fixture.mjs +1 -0
  13. package/src/generate-test-product-fixture.test.mjs +18 -0
  14. package/src/generate-test-product-iteration.mjs +1 -0
  15. package/src/generate-test-product-iteration.test.mjs +18 -0
  16. package/src/generate-test-runtime-boundary-assertions.mjs +158 -0
  17. package/src/generate-test-standalone-assertions.mjs +10 -0
  18. package/src/generate-test-standalone-delivery-stages.mjs +14 -6
  19. package/src/generate.test.mjs +14 -0
  20. package/templates/runtime/contracts/component-contracts.choices.test.ts +59 -12
  21. package/templates/runtime/contracts/component-contracts.choices.ts +58 -12
  22. package/templates/runtime/contracts/component-contracts.inputs.test.ts +6 -6
  23. package/templates/runtime/contracts/component-contracts.inputs.ts +6 -6
  24. package/templates/runtime/contracts/component-contracts.media-custom.test.ts +8 -2
  25. package/templates/runtime/contracts/component-contracts.media-custom.ts +8 -2
  26. package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +21 -6
  27. package/templates/runtime/contracts/component-contracts.runtime-labels.test.ts +7 -1
  28. package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +4 -1
  29. package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +4 -1
  30. package/templates/runtime/contracts/component-contracts.runtime.ts +15 -10
  31. package/templates/runtime/contracts/component-contracts.test.ts +2 -0
  32. package/templates/runtime/contracts/decision-contracts.test.ts +43 -4
  33. package/templates/runtime/contracts/decision-contracts.ts +10 -10
  34. package/templates/runtime/contracts/performance-verification-policy.test.ts +59 -6
  35. package/templates/runtime/contracts/performance-verification-policy.ts +5 -2
  36. package/templates/runtime/export/artifact-download.test.ts +71 -0
  37. package/templates/runtime/export/artifact-download.ts +80 -0
  38. package/templates/runtime/export/artifact-export-request.ts +23 -0
  39. package/templates/runtime/export/artifact-export-settings.test.ts +75 -0
  40. package/templates/runtime/export/artifact-export-settings.ts +96 -0
  41. package/templates/runtime/export/artifact-frame-renderer.test.ts +107 -0
  42. package/templates/runtime/export/artifact-frame-renderer.ts +96 -0
  43. package/templates/runtime/export/artifact-frame-state.test.ts +54 -0
  44. package/templates/runtime/export/artifact-frame-state.ts +44 -0
  45. package/templates/runtime/export/artifact-scene-frame.test.ts +84 -0
  46. package/templates/runtime/export/artifact-scene-frame.ts +118 -0
  47. package/templates/runtime/export/export-background.ts +46 -0
  48. package/templates/runtime/export/export-error.ts +43 -0
  49. package/templates/runtime/export/export.test.ts +49 -226
  50. package/templates/runtime/export/image-artifact-export.test.ts +111 -0
  51. package/templates/runtime/export/image-artifact-export.ts +145 -0
  52. package/templates/runtime/export/index.ts +44 -3
  53. package/templates/runtime/export/product-export-renderer.test.ts +77 -0
  54. package/templates/runtime/export/product-export-renderer.ts +63 -0
  55. package/templates/runtime/export/video-artifact-export.test.ts +166 -0
  56. package/templates/runtime/export/video-artifact-export.ts +164 -0
  57. package/templates/runtime/export/video-encoding-backend.ts +124 -0
  58. package/templates/runtime/export/video-encoding-policy.test.ts +68 -0
  59. package/templates/runtime/export/video-encoding-policy.ts +86 -0
  60. package/templates/runtime/export/video-frame-schedule.test.ts +58 -0
  61. package/templates/runtime/export/video-frame-schedule.ts +42 -0
  62. package/templates/runtime/index.ts +3 -0
  63. package/templates/runtime/model-import/model-import-limits.ts +15 -4
  64. package/templates/runtime/react/app-shell/runtime-public-api-runtime.test.tsx +291 -0
  65. package/templates/runtime/react/app-shell/runtime-public-api-test-support.ts +21 -0
  66. package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +15 -304
  67. package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +41 -27
  68. package/templates/runtime/react/app-shell/toolcraft-app.tsx +39 -11
  69. package/templates/runtime/react/app-shell/toolcraft-source-asset-context.test.tsx +16 -57
  70. package/templates/runtime/react/app-shell/toolcraft-source-asset-context.tsx +75 -434
  71. package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.test.ts +194 -0
  72. package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.ts +227 -0
  73. package/templates/runtime/react/app-shell/toolcraft-source-asset-provider-ownership.test.tsx +243 -0
  74. package/templates/runtime/react/app-shell/toolcraft-source-asset-test-support.ts +51 -0
  75. package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.test.ts +138 -0
  76. package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.ts +378 -0
  77. package/templates/runtime/react/canvas/canvas-shell-rendering.test.tsx +76 -0
  78. package/templates/runtime/react/canvas/canvas-shell-test-utils.tsx +13 -1
  79. package/templates/runtime/react/canvas/canvas-shell.tsx +16 -1
  80. package/templates/runtime/react/canvas/product-scene-surface.test.tsx +195 -0
  81. package/templates/runtime/react/canvas/product-scene-surface.tsx +155 -0
  82. package/templates/runtime/react/canvas/runtime-scene-export.ts +1 -1
  83. package/templates/runtime/react/controls-panel/__tests__/control-conditions.test.ts +61 -0
  84. package/templates/runtime/react/controls-panel/__tests__/controls-panel.collection-actions.test.tsx +89 -0
  85. package/templates/runtime/react/controls-panel/__tests__/controls-panel.control-visibility.test.tsx +40 -19
  86. package/templates/runtime/react/controls-panel/__tests__/controls-panel.footer-actions.test.tsx +7 -12
  87. package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +18 -84
  88. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-collection.test.tsx +62 -0
  89. package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-color-bank.test.tsx +67 -0
  90. package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +43 -87
  91. package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +68 -0
  92. package/templates/runtime/react/controls-panel/conditions/control-conditions.ts +32 -119
  93. package/templates/runtime/react/controls-panel/layout/controls-panel-control-group.tsx +5 -2
  94. package/templates/runtime/react/controls-panel/layout/controls-panel-layout.tsx +10 -8
  95. package/templates/runtime/react/controls-panel/layout/controls-panel-section.tsx +3 -3
  96. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.test.tsx +63 -0
  97. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.tsx +138 -0
  98. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-items.tsx +104 -0
  99. package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-renderer.tsx +115 -236
  100. package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.test.tsx +95 -0
  101. package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.tsx +82 -0
  102. package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.test.tsx +73 -1
  103. package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.tsx +50 -1
  104. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.test.ts +1 -1
  105. package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.ts +2 -1
  106. package/templates/runtime/react/controls-panel/values/controls-panel-collection-values.ts +38 -6
  107. package/templates/runtime/react/controls-panel/values/controls-panel-value-labels.ts +1 -0
  108. package/templates/runtime/react/index.ts +4 -0
  109. package/templates/runtime/react/model-rendering/model-export.ts +1 -1
  110. package/templates/runtime/react/orientation-gizmo/orientation-gizmo-selection.ts +5 -5
  111. package/templates/runtime/react/orientation-gizmo/use-toolcraft-orientation-control-selection.ts +2 -2
  112. package/templates/runtime/react/panel-host/panel-host-runtime-placement.test.tsx +30 -0
  113. package/templates/runtime/react/panel-host/panel-host.tsx +4 -0
  114. package/templates/runtime/scene/scene-bounds.test.ts +23 -0
  115. package/templates/runtime/scene/scene-bounds.ts +32 -19
  116. package/templates/runtime/schema/app-capabilities.test.ts +4 -0
  117. package/templates/runtime/schema/canvas-render-scale.ts +62 -0
  118. package/templates/runtime/schema/collection-item-controls.ts +29 -0
  119. package/templates/runtime/schema/control-applicability.test.ts +127 -0
  120. package/templates/runtime/schema/control-applicability.ts +433 -0
  121. package/templates/runtime/schema/control-schema-normalization.ts +177 -11
  122. package/templates/runtime/schema/controls-panel-actions.ts +2 -2
  123. package/templates/runtime/schema/controls-panel-section-id.test.ts +1 -1
  124. package/templates/runtime/schema/controls-panel-section-layout.ts +14 -9
  125. package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +62 -3
  126. package/templates/runtime/schema/define-toolcraft.collection-actions-item-controls.test.ts +127 -0
  127. package/templates/runtime/schema/define-toolcraft.control-sections.test.ts +10 -4
  128. package/templates/runtime/schema/define-toolcraft.file-drop-item-controls.test.ts +98 -0
  129. package/templates/runtime/schema/define-toolcraft.file-drop-normalization.test.ts +27 -0
  130. package/templates/runtime/schema/define-toolcraft.segmented-control-fit.test.ts +20 -2
  131. package/templates/runtime/schema/define-toolcraft.setup-background.test.ts +1 -1
  132. package/templates/runtime/schema/define-toolcraft.setup-canvas.test.ts +16 -3
  133. package/templates/runtime/schema/define-toolcraft.setup-render-scale-timeline.test.ts +71 -3
  134. package/templates/runtime/schema/define-toolcraft.source-collection.test.ts +79 -0
  135. package/templates/runtime/schema/define-toolcraft.ts +1 -1
  136. package/templates/runtime/schema/runtime-setup-section.ts +24 -5
  137. package/templates/runtime/schema/schema-resolvers.ts +0 -56
  138. package/templates/runtime/schema/types.ts +72 -17
  139. package/templates/runtime/state/canvas-background-state.ts +6 -0
  140. package/templates/runtime/testing/performance-render-plan-integration.test.ts +64 -0
  141. package/templates/runtime/testing/performance-renderer-pipeline-validation.ts +18 -1
  142. package/templates/starter/AGENTS.md +18 -15
  143. package/templates/starter/NOTICE.md +6 -0
  144. package/templates/starter/docs/toolcraft/README.md +2 -1
  145. package/templates/starter/docs/toolcraft/acceptance-testing.md +23 -35
  146. package/templates/starter/docs/toolcraft/agent-worklog.md +18 -3
  147. package/templates/starter/docs/toolcraft/assembly-workflow.md +13 -5
  148. package/templates/starter/docs/toolcraft/component-rules.md +8 -6
  149. package/templates/starter/docs/toolcraft/core/control-selection.md +9 -3
  150. package/templates/starter/docs/toolcraft/core/layout.md +7 -7
  151. package/templates/starter/docs/toolcraft/core/media-upload.md +4 -2
  152. package/templates/starter/docs/toolcraft/core/performance.md +14 -3
  153. package/templates/starter/docs/toolcraft/core/runtime-boundary.md +16 -3
  154. package/templates/starter/docs/toolcraft/core/setup-export.md +49 -19
  155. package/templates/starter/docs/toolcraft/core/timeline-animation.md +4 -4
  156. package/templates/starter/docs/toolcraft/custom-controls.md +6 -4
  157. package/templates/starter/docs/toolcraft/decision-contract.md +3 -1
  158. package/templates/starter/docs/toolcraft/performance.md +20 -6
  159. package/templates/starter/docs/toolcraft/renderer-technique.md +5 -1
  160. package/templates/starter/docs/toolcraft/schema-reference.md +23 -25
  161. package/templates/starter/docs/toolcraft/workflow.md +7 -2
  162. package/templates/starter/e2e/app-browser-control-applicability-requirements.spec.ts +163 -0
  163. package/templates/starter/e2e/app-browser-control-coverage.spec.ts +33 -0
  164. package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +50 -3
  165. package/templates/starter/e2e/app-browser-orientation-evidence.spec.ts +174 -21
  166. package/templates/starter/e2e/app-browser-render-scale-evidence.spec.ts +60 -6
  167. package/templates/starter/e2e/app-browser-render-scale-requirements.spec.ts +77 -1
  168. package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +8 -0
  169. package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +35 -0
  170. package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +5 -34
  171. package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +61 -16
  172. package/templates/starter/e2e/app-browser-shell.spec.ts +13 -5
  173. package/templates/starter/e2e/app-performance-path-adapters.ts +8 -1
  174. package/templates/starter/e2e/app-performance.spec.ts +16 -9
  175. package/templates/starter/e2e/{browser-conditional-output-evidence-helpers.ts → browser-background-output-evidence.ts} +0 -68
  176. package/templates/starter/e2e/browser-control-applicability-evidence.ts +114 -0
  177. package/templates/starter/e2e/browser-infinity-canvas-evidence.ts +29 -341
  178. package/templates/starter/e2e/browser-infinity-canvas-unavailable-image-evidence.ts +370 -0
  179. package/templates/starter/e2e/browser-media-export-evidence.spec.ts +77 -0
  180. package/templates/starter/e2e/browser-media-export-evidence.ts +208 -0
  181. package/templates/starter/e2e/browser-orientation-gizmo-evidence-helpers.ts +4 -0
  182. package/templates/starter/e2e/browser-orientation-gizmo-live-preconditions.ts +86 -0
  183. package/templates/starter/e2e/browser-render-scale-evidence.ts +37 -29
  184. package/templates/starter/e2e/browser-runtime-applicability-requirements.ts +84 -0
  185. package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +13 -3
  186. package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +72 -35
  187. package/templates/starter/e2e/browser-semantic-evidence-test-helpers.ts +25 -0
  188. package/templates/starter/e2e/browser-standard-timeline-evidence.ts +106 -0
  189. package/templates/starter/e2e/decoded-pixel-observation.spec.ts +74 -0
  190. package/templates/starter/e2e/decoded-pixel-observation.ts +227 -0
  191. package/templates/starter/e2e/export-artifact-helpers.ts +206 -25
  192. package/templates/starter/e2e/image-artifact-inspection.spec.ts +41 -0
  193. package/templates/starter/e2e/image-artifact-inspection.ts +99 -0
  194. package/templates/starter/e2e/performance-canvas-helpers.ts +22 -21
  195. package/templates/starter/e2e/performance-canvas-quality-guard.spec.ts +312 -0
  196. package/templates/starter/e2e/performance-canvas-quality-guard.ts +196 -0
  197. package/templates/starter/e2e/performance-canvas-quality-observer.ts +351 -0
  198. package/templates/starter/e2e/performance-control-layout-helpers.ts +2 -2
  199. package/templates/starter/e2e/performance-path-adapter-contract.ts +4 -4
  200. package/templates/starter/e2e/performance-path-helpers.spec.ts +203 -70
  201. package/templates/starter/e2e/performance-path-helpers.ts +210 -91
  202. package/templates/starter/e2e/performance-pipeline-evidence-continuity.spec.ts +76 -0
  203. package/templates/starter/e2e/performance-pipeline-evidence-test-fixtures.ts +11 -2
  204. package/templates/starter/e2e/performance-pipeline-invariants.ts +47 -4
  205. package/templates/starter/e2e/performance-render-scale-runner.spec.ts +140 -38
  206. package/templates/starter/e2e/video-artifact-inspection.spec.ts +64 -0
  207. package/templates/starter/e2e/video-artifact-inspection.ts +281 -0
  208. package/templates/starter/gitignore +1 -0
  209. package/templates/starter/package.json +1 -0
  210. package/templates/starter/scripts/check-toolcraft-docs.mjs +17 -0
  211. package/templates/starter/scripts/toolcraft-contract-manifest.json +1 -0
  212. package/templates/starter/scripts/toolcraft-delivery-plan-authority.test.mjs +60 -0
  213. package/templates/starter/scripts/toolcraft-delivery-plan-errors.test.mjs +7 -2
  214. package/templates/starter/scripts/toolcraft-delivery-plan.mjs +7 -3
  215. package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +95 -103
  216. package/templates/starter/scripts/toolcraft-product-boundary-module-policy.mjs +101 -0
  217. package/templates/starter/scripts/toolcraft-product-boundary.mjs +12 -0
  218. package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +0 -26
  219. package/templates/starter/scripts/toolcraft-product-control-bindings.mjs +182 -0
  220. package/templates/starter/scripts/toolcraft-product-control-boundary.mjs +146 -0
  221. package/templates/starter/scripts/toolcraft-product-control-boundary.test.mjs +186 -0
  222. package/templates/starter/scripts/toolcraft-product-evidence-boundary.test.mjs +85 -20
  223. package/templates/starter/scripts/toolcraft-product-evidence-import-policy.mjs +43 -0
  224. package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +157 -0
  225. package/templates/starter/scripts/toolcraft-product-export-boundary.test.mjs +196 -0
  226. package/templates/starter/scripts/toolcraft-typescript-analysis.d.mts +73 -0
  227. package/templates/starter/scripts/toolcraft-typescript-source-evidence-structure.test.mjs +20 -0
  228. package/templates/starter/scripts/toolcraft-typescript-source-evidence.mjs +1 -0
  229. package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade-test-helpers.mjs +318 -0
  230. package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +157 -206
  231. package/templates/starter/scripts/toolcraft-verification-inventory.mjs +1 -0
  232. package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +51 -0
  233. package/templates/starter/scripts/toolcraft-vite-env-activation.test.mjs +128 -59
  234. package/templates/starter/src/app/acceptance/artifact-export-intent.ts +130 -0
  235. package/templates/starter/src/app/acceptance/conditions.ts +1 -1
  236. package/templates/starter/src/app/acceptance/control-acceptance-context.ts +2 -2
  237. package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +6 -20
  238. package/templates/starter/src/app/acceptance/control-acceptance-kind-rules.ts +24 -5
  239. package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +2 -13
  240. package/templates/starter/src/app/acceptance/control-applicability-cases.test.ts +321 -0
  241. package/templates/starter/src/app/acceptance/control-applicability-cases.ts +290 -0
  242. package/templates/starter/src/app/acceptance/control-applicability.ts +332 -0
  243. package/templates/starter/src/app/acceptance/control-layout-dependency-rules.ts +20 -9
  244. package/templates/starter/src/app/acceptance/control-layout-entity-rules.ts +4 -6
  245. package/templates/starter/src/app/acceptance/control-layout-model.ts +4 -4
  246. package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +3 -10
  247. package/templates/starter/src/app/acceptance/control-parts.ts +8 -0
  248. package/templates/starter/src/app/acceptance/control-section-entity-cohesion.test.ts +215 -0
  249. package/templates/starter/src/app/acceptance/control-section-entity-cohesion.ts +132 -0
  250. package/templates/starter/src/app/acceptance/control-section-inventory.test.ts +87 -0
  251. package/templates/starter/src/app/acceptance/control-section-inventory.ts +74 -44
  252. package/templates/starter/src/app/acceptance/custom-controls.ts +11 -3
  253. package/templates/starter/src/app/acceptance/export-artifact-coverage.ts +113 -0
  254. package/templates/starter/src/app/acceptance/inline-layout.ts +64 -9
  255. package/templates/starter/src/app/acceptance/media-upload.ts +5 -1
  256. package/templates/starter/src/app/acceptance/orientation-gizmo.ts +18 -11
  257. package/templates/starter/src/app/acceptance/output-background-rules.ts +2 -2
  258. package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +18 -10
  259. package/templates/starter/src/app/acceptance/output-export-model.ts +54 -11
  260. package/templates/starter/src/app/acceptance/output-export.ts +35 -12
  261. package/templates/starter/src/app/acceptance/output-video-export-rules.ts +99 -0
  262. package/templates/starter/src/app/acceptance/types.ts +30 -8
  263. package/templates/starter/src/app/acceptance/validate-coverage.ts +20 -2
  264. package/templates/starter/src/app/starter-acceptance.artifact-export-intent.test.ts +239 -0
  265. package/templates/starter/src/app/starter-acceptance.background-export.test.ts +33 -0
  266. package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +16 -1
  267. package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +65 -0
  268. package/templates/starter/src/app/starter-acceptance.contract-fixtures.test.ts +41 -0
  269. package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +112 -16
  270. package/templates/starter/src/app/starter-acceptance.control-applicability.test.ts +224 -0
  271. package/templates/starter/src/app/starter-acceptance.control-order.test.ts +58 -3
  272. package/templates/starter/src/app/starter-acceptance.control-state.test.ts +0 -111
  273. package/templates/starter/src/app/starter-acceptance.custom-control-collections.test.ts +3 -1
  274. package/templates/starter/src/app/starter-acceptance.custom-control-valid.test.ts +1 -1
  275. package/templates/starter/src/app/starter-acceptance.export-artifact.test.ts +131 -0
  276. package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +22 -0
  277. package/templates/starter/src/app/{starter-acceptance.image-video-export-settings.test.ts → starter-acceptance.image-export-settings.test.ts} +37 -9
  278. package/templates/starter/src/app/starter-acceptance.interaction-ownership.test.ts +12 -0
  279. package/templates/starter/src/app/starter-acceptance.keyframes.test.ts +14 -4
  280. package/templates/starter/src/app/starter-acceptance.media-upload.fixtures.ts +11 -1
  281. package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +28 -0
  282. package/templates/starter/src/app/starter-acceptance.output-export-intent.test.ts +384 -0
  283. package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +46 -1
  284. package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +112 -105
  285. package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +12 -0
  286. package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +1 -1
  287. package/templates/starter/src/app/starter-acceptance.section-dependencies.test.ts +35 -24
  288. package/templates/starter/src/app/starter-acceptance.section-size.test.ts +72 -0
  289. package/templates/starter/src/app/starter-acceptance.ts +13 -2
  290. package/templates/starter/src/app/starter-acceptance.video-export-settings.test.ts +336 -0
  291. package/templates/starter/src/app/starter-acceptance.view-interaction.test.ts +8 -0
  292. package/templates/starter/src/app/starter-performance-test-utils.ts +103 -0
  293. package/templates/starter/src/app/starter-performance.gates.test.ts +231 -278
  294. package/templates/starter/src/app/starter-performance.lifecycle.test.ts +261 -0
  295. package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +4 -2
  296. package/templates/starter/src/routes/index.tsx +2 -0
  297. package/templates/ui/components/composites/tabs.tsx +2 -2
  298. package/templates/ui/components/controls/collection-actions/collection-item-groups.test.tsx +38 -0
  299. package/templates/ui/components/controls/collection-actions/collection-item-groups.tsx +36 -0
  300. package/templates/ui/components/controls/collection-actions/index.ts +2 -0
  301. package/templates/ui/components/controls/file-drop/file-drop-collection-control.tsx +137 -0
  302. package/templates/ui/components/controls/file-drop/file-drop-control.test.tsx +189 -0
  303. package/templates/ui/components/controls/file-drop/file-drop-control.tsx +81 -88
  304. package/templates/ui/components/controls/file-drop/file-drop-presentation.tsx +131 -9
  305. package/templates/ui/components/controls/file-drop/file-drop-types.ts +36 -22
  306. package/templates/ui/components/controls/file-drop/index.ts +1 -0
  307. package/templates/ui/components/controls/index.ts +3 -0
  308. package/templates/ui/components/controls/range-slider/range-slider-control.tsx +1 -1
  309. package/templates/ui/components/controls/range-slider/range-slider-value.test.ts +14 -0
  310. package/templates/ui/components/controls/range-slider/range-slider-value.ts +3 -2
  311. package/templates/runtime/export/export.ts +0 -166
  312. package/templates/starter/src/app/acceptance/condition-exclusivity.test.ts +0 -60
  313. package/templates/starter/src/app/acceptance/condition-exclusivity.ts +0 -221
@@ -1,180 +1,25 @@
1
1
  import assert from "node:assert/strict";
2
- import fs from "node:fs/promises";
3
- import os from "node:os";
4
- import path from "node:path";
5
2
  import test from "node:test";
6
- import { pathToFileURL } from "node:url";
7
3
 
8
- import ts from "typescript";
4
+ import {
5
+ createArtifactAction,
6
+ createSession,
7
+ executeClosurelessObservation,
8
+ getHarnessState,
9
+ loadUnavailableResourceFacade,
10
+ resetHarness,
11
+ setActivationError,
12
+ setCleanupFailure,
13
+ setMalformedActivation,
14
+ } from "./toolcraft-unavailable-resource-evidence-facade-test-helpers.mjs";
9
15
 
10
- const starterRoot = path.resolve(import.meta.dirname, "..");
11
- const helperPath = path.join(
12
- starterRoot,
13
- "e2e/browser-infinity-canvas-evidence.ts",
14
- );
15
-
16
- async function loadUnavailableResourceFacade(context) {
17
- const outputDir = await fs.mkdtemp(
18
- path.join(os.tmpdir(), "toolcraft-unavailable-resource-evidence-"),
16
+ test("closureless observation harness rejects browser callbacks with outer references", () => {
17
+ const readAttribute = (root) => root.getAttribute("data-value");
18
+ assert.throws(
19
+ () => executeClosurelessObservation((root) => readAttribute(root), {}),
20
+ /readAttribute is not defined/u,
19
21
  );
20
- context.after(() => fs.rm(outputDir, { force: true, recursive: true }));
21
- const outputPath = path.join(outputDir, "browser-infinity-canvas-evidence.mjs");
22
- const source = (await fs.readFile(helperPath, "utf8"))
23
- .replaceAll('"@playwright/test"', '"./playwright.mjs"')
24
- .replaceAll('"./browser-runtime-evidence"', '"./evidence.mjs"')
25
- .replaceAll('"./browser-proof-session"', '"./proof-session.mjs"')
26
- .replaceAll('"./export-artifact-helpers"', '"./artifact.mjs"');
27
- const { outputText } = ts.transpileModule(source, {
28
- compilerOptions: {
29
- module: ts.ModuleKind.ESNext,
30
- target: ts.ScriptTarget.ES2022,
31
- },
32
- fileName: helperPath,
33
- });
34
-
35
- await Promise.all([
36
- fs.writeFile(outputPath, outputText),
37
- fs.writeFile(
38
- path.join(outputDir, "playwright.mjs"),
39
- `
40
- import assert from "node:assert/strict";
41
- function partial(actual, expected, message) {
42
- for (const [key, value] of Object.entries(expected)) {
43
- assert.deepEqual(actual?.[key], value, message);
44
- }
45
- }
46
- export function expect(actual, message = "Expectation failed") {
47
- return {
48
- not: {
49
- toBe(expected) {
50
- assert.notEqual(actual, expected, message);
51
- },
52
- toEqual(expected) {
53
- assert.notDeepEqual(actual, expected, message);
54
- },
55
- },
56
- toBe(expected) {
57
- assert.equal(actual, expected, message);
58
- },
59
- toBeTruthy() {
60
- assert.ok(actual, message);
61
- },
62
- toEqual(expected) {
63
- assert.deepEqual(actual, expected, message);
64
- },
65
- toMatchObject(expected) {
66
- if (expected?.status === "cleaned") {
67
- globalThis.__toolcraftUnavailableEvidenceTrace.push(
68
- "assert:cleaned",
69
- );
70
- }
71
- partial(actual, expected, message);
72
- },
73
- };
74
- }
75
- `,
76
- ),
77
- fs.writeFile(
78
- path.join(outputDir, "evidence.mjs"),
79
- `
80
- export async function attachToolcraftBrowserRuntimeEvidence(evidence) {
81
- globalThis.__toolcraftUnavailableEvidenceTrace.push(
82
- "evidence:" + evidence.evidenceType,
83
- );
84
- globalThis.__toolcraftUnavailableEvidenceAttachments.push(evidence);
85
- }
86
- `,
87
- ),
88
- fs.writeFile(
89
- path.join(outputDir, "proof-session.mjs"),
90
- `
91
- export function assertToolcraftBrowserProofSession() {
92
- globalThis.__toolcraftUnavailableEvidenceSessionAssertions += 1;
93
- }
94
- export function getToolcraftBrowserActionTarget(action) {
95
- return action.target;
96
- }
97
- export async function readToolcraftBrowserObservation() {
98
- return globalThis.__toolcraftUnavailableEvidenceObservation;
99
- }
100
- export async function runToolcraftBrowserAction() {
101
- globalThis.__toolcraftUnavailableEvidenceActionCalls += 1;
102
- const actionName =
103
- globalThis.__toolcraftUnavailableEvidenceActionCalls === 1
104
- ? "activate"
105
- : "cleanup";
106
- globalThis.__toolcraftUnavailableEvidenceTrace.push(
107
- "action:" + actionName,
108
- );
109
- if (
110
- actionName === "cleanup" &&
111
- globalThis.__toolcraftUnavailableEvidenceCleanupFailure
112
- ) {
113
- throw new Error("cleanup failed");
114
- }
115
- globalThis.__toolcraftUnavailableEvidenceObservation =
116
- globalThis.__toolcraftUnavailableEvidenceActionCalls === 1
117
- ? {
118
- assetId: "image-2",
119
- fileName: "unavailable.png",
120
- lifecycle: "unavailable",
121
- requestId: "unavailable-image-1",
122
- resolverAvailable: false,
123
- status: "active",
124
- }
125
- : {
126
- assetId: "image-2",
127
- fileName: "unavailable.png",
128
- lifecycle: "ready",
129
- requestId: "unavailable-image-1",
130
- resolverAvailable: true,
131
- status: "cleaned",
132
- };
133
- }
134
- export async function runToolcraftBrowserValueAction(action) {
135
- globalThis.__toolcraftUnavailableEvidenceTrace.push("artifact");
136
- return action.result;
137
- }
138
- `,
139
- ),
140
- fs.writeFile(
141
- path.join(outputDir, "artifact.mjs"),
142
- `
143
- export function assertToolcraftProducedArtifact(artifact) {
144
- if (!artifact) throw new Error("missing artifact");
145
- }
146
- export function validateToolcraftExportArtifactInspection(inspection) {
147
- globalThis.__toolcraftUnavailableEvidenceArtifactValidations += 1;
148
- if (!inspection?.byteLength) throw new Error("invalid inspection");
149
- return inspection;
150
- }
151
- `,
152
- ),
153
- ]);
154
-
155
- return import(`${pathToFileURL(outputPath).href}?test=${Date.now()}`);
156
- }
157
-
158
- function createSession() {
159
- return {
160
- observe(read) {
161
- return { read };
162
- },
163
- targetAction(target, run) {
164
- return { run, target };
165
- },
166
- };
167
- }
168
-
169
- function resetHarness() {
170
- globalThis.__toolcraftUnavailableEvidenceActionCalls = 0;
171
- globalThis.__toolcraftUnavailableEvidenceArtifactValidations = 0;
172
- globalThis.__toolcraftUnavailableEvidenceAttachments = [];
173
- globalThis.__toolcraftUnavailableEvidenceCleanupFailure = false;
174
- globalThis.__toolcraftUnavailableEvidenceObservation = { status: "missing" };
175
- globalThis.__toolcraftUnavailableEvidenceSessionAssertions = 0;
176
- globalThis.__toolcraftUnavailableEvidenceTrace = [];
177
- }
22
+ });
178
23
 
179
24
  function createFiniteObservation(width, height) {
180
25
  return {
@@ -184,6 +29,7 @@ function createFiniteObservation(width, height) {
184
29
  finiteControlSize: { height, width },
185
30
  finiteControlsPresent: true,
186
31
  overflow: "hidden",
32
+ productSceneStatus: null,
187
33
  sceneRect: null,
188
34
  viewportOffset: { x: 0, y: 0 },
189
35
  };
@@ -197,6 +43,7 @@ function createInfiniteObservation() {
197
43
  finiteControlSize: null,
198
44
  finiteControlsPresent: false,
199
45
  overflow: "visible",
46
+ productSceneStatus: "ready",
200
47
  sceneRect: { height: 400, width: 640, x: -320, y: -200 },
201
48
  viewportOffset: { x: 0, y: 0 },
202
49
  };
@@ -230,7 +77,7 @@ test("Infinity mode recipe rejects a wrong restored dormant finite size", async
230
77
  },
231
78
  ),
232
79
  );
233
- assert.deepEqual(globalThis.__toolcraftUnavailableEvidenceAttachments, []);
80
+ assert.deepEqual(getHarnessState().attachments, []);
234
81
  });
235
82
 
236
83
  test("Infinity mode recipe accepts exact restored dormant finite dimensions", async (context) => {
@@ -259,7 +106,7 @@ test("Infinity mode recipe accepts exact restored dormant finite dimensions", as
259
106
  target: "canvas.infinity",
260
107
  },
261
108
  );
262
- assert.deepEqual(globalThis.__toolcraftUnavailableEvidenceAttachments, [
109
+ assert.deepEqual(getHarnessState().attachments, [
263
110
  {
264
111
  evidenceType: "viewport-side-effect",
265
112
  requirementId: "canvas.infinity.mode",
@@ -276,18 +123,20 @@ test("Infinity mode recipe accepts exact restored dormant finite dimensions", as
276
123
  test("unavailable-image export recipe proves typed fault before evidence and cleans up", async (context) => {
277
124
  const facade = await loadUnavailableResourceFacade(context);
278
125
  resetHarness();
126
+ const session = createSession();
279
127
  const fixture = facade.createToolcraftUnavailableImageResourceFixture(
280
- createSession(),
128
+ session,
281
129
  {
282
130
  fileName: "unavailable.png",
283
131
  sourceTarget: "source.images",
284
132
  target: "canvas.infinity",
285
133
  },
286
134
  );
287
- const exportAction = {
288
- result: new Uint8Array([1, 2, 3]),
289
- target: "canvas.infinity",
290
- };
135
+ const exportAction = createArtifactAction(
136
+ session,
137
+ "canvas.infinity",
138
+ new Uint8Array([1, 2, 3]),
139
+ );
291
140
  const inspection =
292
141
  await facade.expectToolcraftInfinityCanvasUnavailableImageExportEvidence(
293
142
  fixture,
@@ -304,10 +153,12 @@ test("unavailable-image export recipe proves typed fault before evidence and cle
304
153
  height: 2004,
305
154
  width: 2048,
306
155
  });
307
- assert.equal(globalThis.__toolcraftUnavailableEvidenceActionCalls, 2);
308
- assert.equal(globalThis.__toolcraftUnavailableEvidenceArtifactValidations, 1);
309
- assert.equal(globalThis.__toolcraftUnavailableEvidenceSessionAssertions, 1);
310
- assert.deepEqual(globalThis.__toolcraftUnavailableEvidenceAttachments, [
156
+ const state = getHarnessState();
157
+ assert.equal(state.actionCalls, 2);
158
+ assert.equal(state.artifactValidations, 1);
159
+ assert.equal(state.closurelessObservationCalls, 4);
160
+ assert.equal(state.sessionAssertions, 1);
161
+ assert.deepEqual(state.attachments, [
311
162
  {
312
163
  evidenceType: "exported-artifact",
313
164
  requirementId: "canvas.infinity.image-export",
@@ -319,21 +170,40 @@ test("unavailable-image export recipe proves typed fault before evidence and cle
319
170
  target: "canvas.infinity",
320
171
  },
321
172
  ]);
322
- assert.deepEqual(globalThis.__toolcraftUnavailableEvidenceTrace, [
173
+ assert.deepEqual(state.trace, [
323
174
  "action:activate",
175
+ "assert:active",
324
176
  "artifact",
177
+ "assert:active",
325
178
  "action:cleanup",
326
179
  "assert:cleaned",
327
180
  "evidence:exported-artifact",
328
181
  "evidence:infinity-scene-bounds-image-export",
329
182
  ]);
183
+ assert.deepEqual(state.bridgeActions, ["activate", "cleanup"]);
184
+ assert.deepEqual(state.eventNames, [
185
+ "toolcraft.browser-proof.unavailable-resource-request",
186
+ "toolcraft.browser-proof.unavailable-resource-request",
187
+ ]);
188
+ assert.deepEqual(state.selectorNames, [
189
+ '[data-slot="toolcraft-runtime-app"]',
190
+ '[data-slot="toolcraft-runtime-app"]',
191
+ ]);
192
+ assert.ok(
193
+ state.attributeNames.length > 0 &&
194
+ state.attributeNames.every(
195
+ (name) => name === "data-toolcraft-unavailable-resource-evidence",
196
+ ),
197
+ );
198
+ assert.equal(state.pollCalls, 2);
330
199
  });
331
200
 
332
201
  test("unavailable-image export recipe cleans up and emits no evidence when decoded bounds fail", async (context) => {
333
202
  const facade = await loadUnavailableResourceFacade(context);
334
203
  resetHarness();
204
+ const session = createSession();
335
205
  const fixture = facade.createToolcraftUnavailableImageResourceFixture(
336
- createSession(),
206
+ session,
337
207
  {
338
208
  fileName: "unavailable.png",
339
209
  target: "canvas.infinity",
@@ -343,10 +213,11 @@ test("unavailable-image export recipe cleans up and emits no evidence when decod
343
213
  await assert.rejects(
344
214
  facade.expectToolcraftInfinityCanvasUnavailableImageExportEvidence(
345
215
  fixture,
346
- {
347
- result: new Uint8Array([1, 2, 3]),
348
- target: "canvas.infinity",
349
- },
216
+ createArtifactAction(
217
+ session,
218
+ "canvas.infinity",
219
+ new Uint8Array([1, 2, 3]),
220
+ ),
350
221
  async () => ({ byteLength: 3, height: 100, width: 100 }),
351
222
  {
352
223
  expectedSize: { height: 2004, width: 2048 },
@@ -355,20 +226,18 @@ test("unavailable-image export recipe cleans up and emits no evidence when decod
355
226
  ),
356
227
  );
357
228
 
358
- assert.equal(globalThis.__toolcraftUnavailableEvidenceActionCalls, 2);
359
- assert.deepEqual(globalThis.__toolcraftUnavailableEvidenceAttachments, []);
360
- assert.equal(
361
- globalThis.__toolcraftUnavailableEvidenceObservation.status,
362
- "cleaned",
363
- );
229
+ assert.equal(getHarnessState().actionCalls, 2);
230
+ assert.deepEqual(getHarnessState().attachments, []);
231
+ assert.equal(getHarnessState().observation.status, "cleaned");
364
232
  });
365
233
 
366
234
  test("unavailable-image export recipe emits no evidence when cleanup fails", async (context) => {
367
235
  const facade = await loadUnavailableResourceFacade(context);
368
236
  resetHarness();
369
- globalThis.__toolcraftUnavailableEvidenceCleanupFailure = true;
237
+ setCleanupFailure();
238
+ const session = createSession();
370
239
  const fixture = facade.createToolcraftUnavailableImageResourceFixture(
371
- createSession(),
240
+ session,
372
241
  {
373
242
  fileName: "unavailable.png",
374
243
  target: "canvas.infinity",
@@ -378,10 +247,11 @@ test("unavailable-image export recipe emits no evidence when cleanup fails", asy
378
247
  await assert.rejects(
379
248
  facade.expectToolcraftInfinityCanvasUnavailableImageExportEvidence(
380
249
  fixture,
381
- {
382
- result: new Uint8Array([1, 2, 3]),
383
- target: "canvas.infinity",
384
- },
250
+ createArtifactAction(
251
+ session,
252
+ "canvas.infinity",
253
+ new Uint8Array([1, 2, 3]),
254
+ ),
385
255
  async () => ({ byteLength: 3, height: 2004, width: 2048 }),
386
256
  {
387
257
  expectedSize: { height: 2004, width: 2048 },
@@ -391,14 +261,75 @@ test("unavailable-image export recipe emits no evidence when cleanup fails", asy
391
261
  /cleanup failed/u,
392
262
  );
393
263
 
394
- assert.deepEqual(globalThis.__toolcraftUnavailableEvidenceAttachments, []);
395
- assert.deepEqual(globalThis.__toolcraftUnavailableEvidenceTrace, [
264
+ assert.deepEqual(getHarnessState().attachments, []);
265
+ assert.deepEqual(getHarnessState().trace, [
396
266
  "action:activate",
267
+ "assert:active",
397
268
  "artifact",
269
+ "assert:active",
398
270
  "action:cleanup",
399
271
  ]);
400
272
  });
401
273
 
274
+ test("unavailable-image export recipe surfaces bridge errors before artifact work", async (context) => {
275
+ const facade = await loadUnavailableResourceFacade(context);
276
+ resetHarness();
277
+ setActivationError("activation failed");
278
+ const session = createSession();
279
+ const fixture = facade.createToolcraftUnavailableImageResourceFixture(
280
+ session,
281
+ { fileName: "unavailable.png", target: "canvas.infinity" },
282
+ );
283
+
284
+ await assert.rejects(
285
+ facade.expectToolcraftInfinityCanvasUnavailableImageExportEvidence(
286
+ fixture,
287
+ createArtifactAction(
288
+ session,
289
+ "canvas.infinity",
290
+ new Uint8Array([1]),
291
+ ),
292
+ async () => ({ byteLength: 1, height: 1, width: 1 }),
293
+ {
294
+ expectedSize: { height: 1, width: 1 },
295
+ requirementId: "canvas.infinity.image-export",
296
+ },
297
+ ),
298
+ /activation failed/u,
299
+ );
300
+ assert.deepEqual(getHarnessState().trace, ["action:activate"]);
301
+ assert.deepEqual(getHarnessState().attachments, []);
302
+ });
303
+
304
+ test("unavailable-image export recipe rejects malformed bridge observations", async (context) => {
305
+ const facade = await loadUnavailableResourceFacade(context);
306
+ resetHarness();
307
+ setMalformedActivation();
308
+ const session = createSession();
309
+ const fixture = facade.createToolcraftUnavailableImageResourceFixture(
310
+ session,
311
+ { fileName: "unavailable.png", target: "canvas.infinity" },
312
+ );
313
+
314
+ await assert.rejects(
315
+ facade.expectToolcraftInfinityCanvasUnavailableImageExportEvidence(
316
+ fixture,
317
+ createArtifactAction(
318
+ session,
319
+ "canvas.infinity",
320
+ new Uint8Array([1]),
321
+ ),
322
+ async () => ({ byteLength: 1, height: 1, width: 1 }),
323
+ {
324
+ expectedSize: { height: 1, width: 1 },
325
+ requirementId: "canvas.infinity.image-export",
326
+ },
327
+ ),
328
+ /published malformed state/u,
329
+ );
330
+ assert.deepEqual(getHarnessState().attachments, []);
331
+ });
332
+
402
333
  test("unavailable-image export recipe rejects forged fixtures and target mismatch", async (context) => {
403
334
  const facade = await loadUnavailableResourceFacade(context);
404
335
  resetHarness();
@@ -426,14 +357,34 @@ test("unavailable-image export recipe rejects forged fixtures and target mismatc
426
357
  await assert.rejects(
427
358
  facade.expectToolcraftInfinityCanvasUnavailableImageExportEvidence(
428
359
  fixture,
429
- { result: new Uint8Array([1]), target: "actions.output" },
360
+ createArtifactAction(
361
+ session,
362
+ "actions.output",
363
+ new Uint8Array([1]),
364
+ ),
365
+ async () => ({ byteLength: 1, height: 1, width: 1 }),
366
+ {
367
+ expectedSize: { height: 1, width: 1 },
368
+ requirementId: "canvas.infinity.image-export",
369
+ },
370
+ ),
371
+ );
372
+ await assert.rejects(
373
+ facade.expectToolcraftInfinityCanvasUnavailableImageExportEvidence(
374
+ fixture,
375
+ createArtifactAction(
376
+ createSession(),
377
+ "canvas.infinity",
378
+ new Uint8Array([1]),
379
+ ),
430
380
  async () => ({ byteLength: 1, height: 1, width: 1 }),
431
381
  {
432
382
  expectedSize: { height: 1, width: 1 },
433
383
  requirementId: "canvas.infinity.image-export",
434
384
  },
435
385
  ),
386
+ /same browser proof session/u,
436
387
  );
437
- assert.equal(globalThis.__toolcraftUnavailableEvidenceActionCalls, 0);
438
- assert.deepEqual(globalThis.__toolcraftUnavailableEvidenceAttachments, []);
388
+ assert.equal(getHarnessState().actionCalls, 0);
389
+ assert.deepEqual(getHarnessState().attachments, []);
439
390
  });
@@ -5,6 +5,7 @@ import path from "node:path";
5
5
  const ignoredDirectoryNames = new Set([
6
6
  ".agents",
7
7
  ".git",
8
+ ".playwright-mcp",
8
9
  ".toolcraft",
9
10
  ".vite",
10
11
  "coverage",
@@ -193,6 +193,57 @@ test("ignores workflow skills, generated output, and checkpoint directories thro
193
193
  );
194
194
  });
195
195
 
196
+ test("ignores browser-tool artifact create change and delete", async (t) => {
197
+ const rootDir = await createRootWideInventoryFixture();
198
+ t.after(() => fs.rm(rootDir, { force: true, recursive: true }));
199
+ const baseline = await collectToolcraftVerificationInputs(rootDir);
200
+ const browserArtifact = path.join(
201
+ rootDir,
202
+ ".playwright-mcp",
203
+ "nested",
204
+ "page.yml",
205
+ );
206
+
207
+ for (const content of ["page: initial\n", "page: updated\n"]) {
208
+ await fs.mkdir(path.dirname(browserArtifact), { recursive: true });
209
+ await fs.writeFile(browserArtifact, content);
210
+ const current = await collectToolcraftVerificationInputs(rootDir);
211
+
212
+ assert.equal(current.sourceHash, baseline.sourceHash);
213
+ assert.deepEqual(
214
+ getToolcraftChangedVerificationFiles(baseline.entries, current.entries),
215
+ [],
216
+ );
217
+ }
218
+
219
+ await fs.rm(path.join(rootDir, ".playwright-mcp"), {
220
+ force: true,
221
+ recursive: true,
222
+ });
223
+ const current = await collectToolcraftVerificationInputs(rootDir);
224
+
225
+ assert.equal(current.sourceHash, baseline.sourceHash);
226
+ assert.deepEqual(
227
+ getToolcraftChangedVerificationFiles(baseline.entries, current.entries),
228
+ [],
229
+ );
230
+ });
231
+
232
+ test("continues to hash real product raster assets", async (t) => {
233
+ const rootDir = await createRootWideInventoryFixture();
234
+ t.after(() => fs.rm(rootDir, { force: true, recursive: true }));
235
+ const baseline = await collectToolcraftVerificationInputs(rootDir);
236
+
237
+ await fs.writeFile(path.join(rootDir, "public", "source.png"), "updated-source-image");
238
+ const current = await collectToolcraftVerificationInputs(rootDir);
239
+
240
+ assert.notEqual(current.sourceHash, baseline.sourceHash);
241
+ assert.deepEqual(
242
+ getToolcraftChangedVerificationFiles(baseline.entries, current.entries),
243
+ ["public/source.png"],
244
+ );
245
+ });
246
+
196
247
  test("does not report legacy workflow-skill receipt entries as product changes", async (t) => {
197
248
  const rootDir = await createRootWideInventoryFixture();
198
249
  t.after(() => fs.rm(rootDir, { force: true, recursive: true }));