@tryvitris/website-harness 0.1.0-beta.6 → 0.1.0-beta.7

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 (458) hide show
  1. package/README.md +4 -4
  2. package/agent/graph.yaml +0 -2
  3. package/agent/refs/components.md +5 -41
  4. package/agent/refs/compose.md +1 -1
  5. package/agent/refs/implement.md +2 -2
  6. package/agent/refs/jev.md +1 -1
  7. package/agent/refs/layout.md +1 -1
  8. package/agent/refs/storyboard.md +1 -1
  9. package/agent/refs/template-adaptation.md +1 -1
  10. package/bin/api/agent/evaluate.js +10 -15
  11. package/bin/api/agent/grade.js +10 -15
  12. package/bin/api/cli/api.js +18 -23
  13. package/bin/api/cli.js +20 -25
  14. package/bin/api/engine.js +11 -16
  15. package/bin/api/hosting.js +12 -17
  16. package/bin/api/index.js +2 -3
  17. package/bin/api/references.js +1 -2
  18. package/bin/api/render.js +2 -4
  19. package/bin/chunks/{chunk-4GZCAWWK.js → chunk-4MFPATAB.js} +2 -4
  20. package/bin/chunks/{chunk-5OOPJNGN.js → chunk-5JTBC6UK.js} +1 -4
  21. package/bin/chunks/{chunk-Z2UNY47A.js → chunk-5YSPWKFF.js} +1 -1
  22. package/bin/chunks/{chunk-FYN4T4SV.js → chunk-7V3OKLKH.js} +15 -26
  23. package/bin/chunks/{chunk-3CTBXY5K.js → chunk-FRABKM65.js} +1936 -1899
  24. package/bin/chunks/{chunk-4DM5TTLG.js → chunk-H7Y72HXC.js} +5 -5
  25. package/bin/chunks/{chunk-R7YELY3C.js → chunk-HL6JVA4A.js} +100 -81
  26. package/bin/chunks/{chunk-54JC5L35.js → chunk-O55LAQ2C.js} +3 -5
  27. package/bin/chunks/{chunk-VH7PM7KJ.js → chunk-P56ZDMX7.js} +4 -6
  28. package/bin/chunks/{chunk-7VLBEAFW.js → chunk-PGFFKPK6.js} +2 -2
  29. package/bin/chunks/{chunk-YQYHROLZ.js → chunk-QRWGFLUU.js} +2 -2
  30. package/bin/chunks/{chunk-CBEJZO4L.js → chunk-TTAUU3AZ.js} +2 -2
  31. package/bin/chunks/{chunk-E5Y46VBX.js → chunk-VTI32UGJ.js} +200 -103
  32. package/bin/chunks/{chunk-DRJQ4OOU.js → chunk-WOORR67N.js} +0 -45
  33. package/bin/chunks/{chunk-B5I45LFD.js → chunk-YZWEXHT4.js} +11 -13
  34. package/bin/chunks/{chunk-YCVGD2CG.js → chunk-ZIROO2U4.js} +1204 -1176
  35. package/bin/chunks/{chunk-42IXFXUD.js → chunk-ZWFG4GPG.js} +11 -15
  36. package/bin/chunks/{design-context-store-IAT2P2OC.js → design-context-store-DCZOAK56.js} +10 -15
  37. package/bin/chunks/{packets-VBMY4SQJ.js → packets-QOLWPRNV.js} +10 -15
  38. package/bin/chunks/{policy-2I37JUU3.js → policy-MP2JZXI3.js} +1 -1
  39. package/bin/chunks/{preparation-S4MG3RPL.js → preparation-T2IOD5SJ.js} +10 -15
  40. package/bin/chunks/{questions-HKELBDFL.js → questions-XK545GCX.js} +1 -11
  41. package/bin/types/src/agent/composition-authoring.d.ts +2 -2
  42. package/bin/types/src/agent/jev/calibration.d.ts +2 -2
  43. package/bin/types/src/agent/jev/config.d.ts +1 -1
  44. package/bin/types/src/agent/jev/questions.d.ts +0 -10
  45. package/bin/types/src/agent/jev/types.d.ts +0 -2
  46. package/bin/types/src/agent/site-inputs.d.ts +9 -1
  47. package/bin/types/src/agent/template-catalog.d.ts +20 -0
  48. package/bin/types/src/agent/theme-selection.d.ts +4 -2
  49. package/bin/types/src/build/archives.d.ts +2 -0
  50. package/bin/vitris-art.js +10 -15
  51. package/bin/vitris-build.js +3 -5
  52. package/bin/vitris-create-site.js +12 -17
  53. package/bin/vitris-cursor-hook.js +10 -15
  54. package/bin/vitris-eval.js +12 -17
  55. package/bin/vitris-go.js +14 -19
  56. package/bin/vitris-harvest.js +11 -16
  57. package/bin/vitris-knowledge.js +11 -16
  58. package/bin/vitris-launch-preflight.js +11 -17
  59. package/bin/vitris-motion-view.js +13 -19
  60. package/bin/vitris-references.js +4 -7
  61. package/bin/vitris-refresh.js +11 -16
  62. package/bin/vitris-stock.js +1 -1
  63. package/bin/vitris-themes.js +10 -15
  64. package/bin/vitris-upgrade.js +11 -16
  65. package/bin/vitris-verify-browser.js +43 -8
  66. package/bin/vitris-verify-performance.js +3 -5
  67. package/bin/vitris.js +20 -25
  68. package/design-system/MASTER.md +2 -2
  69. package/docs/CLI.md +2 -1
  70. package/docs/DISTRIBUTION.md +1 -1
  71. package/package.json +2 -7
  72. package/templates/site/README.md +2 -0
  73. package/templates/site/gitignore +1 -0
  74. package/bin/chunks/chunk-6H3T46F5.js +0 -25
  75. package/bin/chunks/chunk-ANMJRJQ5.js +0 -31
  76. package/bin/chunks/chunk-FOXUQXTV.js +0 -278
  77. package/bin/chunks/chunk-HNORQ74T.js +0 -40
  78. package/bin/chunks/chunk-T7DGRVTP.js +0 -458
  79. package/bin/types/src/agent/jev/block-catalog.d.ts +0 -95
  80. package/bin/types/src/agent/jev/component-select.d.ts +0 -102
  81. package/bin/types/src/blocks/library-profile.d.ts +0 -9
  82. package/bin/types/src/blocks/metadata.d.ts +0 -65
  83. package/bin/vitris-blocks.js +0 -238
  84. package/blocks/CONVENTIONS.md +0 -121
  85. package/blocks/INDEX.md +0 -130
  86. package/blocks/about/about-awards/README.md +0 -36
  87. package/blocks/about/about-awards/styles.css +0 -13
  88. package/blocks/about/about-awards/template.html +0 -1
  89. package/blocks/about/about-credentials/README.md +0 -33
  90. package/blocks/about/about-credentials/block.meta.json +0 -85
  91. package/blocks/about/about-credentials/styles.css +0 -4
  92. package/blocks/about/about-credentials/template.html +0 -1
  93. package/blocks/about/about-founder/README.md +0 -35
  94. package/blocks/about/about-founder/styles.css +0 -9
  95. package/blocks/about/about-founder/template.html +0 -1
  96. package/blocks/about/about-mission/README.md +0 -31
  97. package/blocks/about/about-mission/styles.css +0 -5
  98. package/blocks/about/about-mission/template.html +0 -1
  99. package/blocks/about/about-statement/README.md +0 -28
  100. package/blocks/about/about-statement/styles.css +0 -7
  101. package/blocks/about/about-statement/template.html +0 -1
  102. package/blocks/about/about-story/README.md +0 -35
  103. package/blocks/about/about-story/styles.css +0 -5
  104. package/blocks/about/about-story/template.html +0 -1
  105. package/blocks/about/about-timeline/README.md +0 -33
  106. package/blocks/about/about-timeline/styles.css +0 -8
  107. package/blocks/about/about-timeline/template.html +0 -1
  108. package/blocks/about/about-values/README.md +0 -31
  109. package/blocks/about/about-values/styles.css +0 -3
  110. package/blocks/about/about-values/template.html +0 -1
  111. package/blocks/blog/blog-featured/README.md +0 -39
  112. package/blocks/blog/blog-featured/styles.css +0 -12
  113. package/blocks/blog/blog-featured/template.html +0 -1
  114. package/blocks/blog/blog-index/README.md +0 -34
  115. package/blocks/blog/blog-index/styles.css +0 -6
  116. package/blocks/blog/blog-index/template.html +0 -1
  117. package/blocks/blog/blog-post-header/README.md +0 -31
  118. package/blocks/blog/blog-post-header/styles.css +0 -8
  119. package/blocks/blog/blog-post-header/template.html +0 -1
  120. package/blocks/contact/contact-cards/README.md +0 -32
  121. package/blocks/contact/contact-cards/styles.css +0 -7
  122. package/blocks/contact/contact-cards/template.html +0 -1
  123. package/blocks/contact/contact-chips/README.md +0 -41
  124. package/blocks/contact/contact-chips/styles.css +0 -13
  125. package/blocks/contact/contact-chips/template.html +0 -1
  126. package/blocks/contact/contact-hours/README.md +0 -41
  127. package/blocks/contact/contact-hours/block.meta.json +0 -87
  128. package/blocks/contact/contact-hours/styles.css +0 -8
  129. package/blocks/contact/contact-hours/template.html +0 -1
  130. package/blocks/contact/contact-map/README.md +0 -39
  131. package/blocks/contact/contact-map/styles.css +0 -10
  132. package/blocks/contact/contact-map/template.html +0 -1
  133. package/blocks/contact/contact-offices/README.md +0 -32
  134. package/blocks/contact/contact-offices/styles.css +0 -8
  135. package/blocks/contact/contact-offices/template.html +0 -1
  136. package/blocks/contact/contact-phone-first/README.md +0 -33
  137. package/blocks/contact/contact-phone-first/block.meta.json +0 -86
  138. package/blocks/contact/contact-phone-first/styles.css +0 -11
  139. package/blocks/contact/contact-phone-first/template.html +0 -1
  140. package/blocks/contact/contact-split/README.md +0 -43
  141. package/blocks/contact/contact-split/styles.css +0 -12
  142. package/blocks/contact/contact-split/template.html +0 -1
  143. package/blocks/contact/contact-visit/README.md +0 -36
  144. package/blocks/contact/contact-visit/block.meta.json +0 -88
  145. package/blocks/contact/contact-visit/styles.css +0 -13
  146. package/blocks/contact/contact-visit/template.html +0 -1
  147. package/blocks/contact/service-areas/README.md +0 -32
  148. package/blocks/contact/service-areas/styles.css +0 -9
  149. package/blocks/contact/service-areas/template.html +0 -1
  150. package/blocks/content/glossary/README.md +0 -35
  151. package/blocks/content/glossary/styles.css +0 -6
  152. package/blocks/content/glossary/template.html +0 -1
  153. package/blocks/content/list-split/README.md +0 -33
  154. package/blocks/content/list-split/styles.css +0 -13
  155. package/blocks/content/list-split/template.html +0 -1
  156. package/blocks/content/prose-split/README.md +0 -32
  157. package/blocks/content/prose-split/styles.css +0 -12
  158. package/blocks/content/prose-split/template.html +0 -1
  159. package/blocks/content/specification-ledger/README.md +0 -32
  160. package/blocks/content/specification-ledger/block.meta.json +0 -85
  161. package/blocks/content/specification-ledger/styles.css +0 -10
  162. package/blocks/content/specification-ledger/template.html +0 -1
  163. package/blocks/cta/cta-band/README.md +0 -33
  164. package/blocks/cta/cta-band/styles.css +0 -11
  165. package/blocks/cta/cta-band/template.html +0 -1
  166. package/blocks/cta/cta-card/README.md +0 -35
  167. package/blocks/cta/cta-card/styles.css +0 -8
  168. package/blocks/cta/cta-card/template.html +0 -1
  169. package/blocks/cta/cta-floating-bar/README.md +0 -28
  170. package/blocks/cta/cta-floating-bar/styles.css +0 -8
  171. package/blocks/cta/cta-floating-bar/template.html +0 -1
  172. package/blocks/cta/cta-inline/README.md +0 -30
  173. package/blocks/cta/cta-inline/styles.css +0 -9
  174. package/blocks/cta/cta-inline/template.html +0 -1
  175. package/blocks/cta/cta-newsletter/README.md +0 -34
  176. package/blocks/cta/cta-newsletter/styles.css +0 -8
  177. package/blocks/cta/cta-newsletter/template.html +0 -1
  178. package/blocks/cta/cta-photo-fan/README.md +0 -36
  179. package/blocks/cta/cta-photo-fan/styles.css +0 -14
  180. package/blocks/cta/cta-photo-fan/template.html +0 -1
  181. package/blocks/cta/cta-split/README.md +0 -38
  182. package/blocks/cta/cta-split/styles.css +0 -10
  183. package/blocks/cta/cta-split/template.html +0 -1
  184. package/blocks/faq/faq-accordion/README.md +0 -36
  185. package/blocks/faq/faq-accordion/styles.css +0 -6
  186. package/blocks/faq/faq-accordion/template.html +0 -1
  187. package/blocks/faq/faq-grouped/README.md +0 -40
  188. package/blocks/faq/faq-grouped/styles.css +0 -20
  189. package/blocks/faq/faq-grouped/template.html +0 -1
  190. package/blocks/faq/faq-split/README.md +0 -37
  191. package/blocks/faq/faq-split/styles.css +0 -5
  192. package/blocks/faq/faq-split/template.html +0 -1
  193. package/blocks/faq/faq-tabs/README.md +0 -36
  194. package/blocks/faq/faq-tabs/styles.css +0 -3
  195. package/blocks/faq/faq-tabs/template.html +0 -1
  196. package/blocks/feature/feature-bento/README.md +0 -33
  197. package/blocks/feature/feature-bento/styles.css +0 -7
  198. package/blocks/feature/feature-bento/template.html +0 -1
  199. package/blocks/feature/feature-compare-table/README.md +0 -44
  200. package/blocks/feature/feature-compare-table/styles.css +0 -15
  201. package/blocks/feature/feature-compare-table/template.html +0 -1
  202. package/blocks/feature/feature-comparison/README.md +0 -34
  203. package/blocks/feature/feature-comparison/styles.css +0 -6
  204. package/blocks/feature/feature-comparison/template.html +0 -1
  205. package/blocks/feature/feature-grid-3/README.md +0 -34
  206. package/blocks/feature/feature-grid-3/styles.css +0 -8
  207. package/blocks/feature/feature-grid-3/template.html +0 -1
  208. package/blocks/feature/feature-icon-list/README.md +0 -39
  209. package/blocks/feature/feature-icon-list/styles.css +0 -9
  210. package/blocks/feature/feature-icon-list/template.html +0 -1
  211. package/blocks/feature/feature-spotlight/README.md +0 -39
  212. package/blocks/feature/feature-spotlight/styles.css +0 -5
  213. package/blocks/feature/feature-spotlight/template.html +0 -1
  214. package/blocks/feature/feature-stats-band/README.md +0 -33
  215. package/blocks/feature/feature-stats-band/styles.css +0 -8
  216. package/blocks/feature/feature-stats-band/template.html +0 -1
  217. package/blocks/feature/feature-tabs/README.md +0 -38
  218. package/blocks/feature/feature-tabs/styles.css +0 -7
  219. package/blocks/feature/feature-tabs/template.html +0 -1
  220. package/blocks/feature/feature-thumb-list/README.md +0 -38
  221. package/blocks/feature/feature-thumb-list/styles.css +0 -13
  222. package/blocks/feature/feature-thumb-list/template.html +0 -1
  223. package/blocks/feature/feature-zigzag/README.md +0 -31
  224. package/blocks/feature/feature-zigzag/styles.css +0 -6
  225. package/blocks/feature/feature-zigzag/template.html +0 -1
  226. package/blocks/footer/footer-columns/README.md +0 -39
  227. package/blocks/footer/footer-columns/styles.css +0 -16
  228. package/blocks/footer/footer-columns/template.html +0 -1
  229. package/blocks/footer/footer-compact/README.md +0 -33
  230. package/blocks/footer/footer-compact/styles.css +0 -12
  231. package/blocks/footer/footer-compact/template.html +0 -1
  232. package/blocks/footer/footer-cta/README.md +0 -37
  233. package/blocks/footer/footer-cta/styles.css +0 -18
  234. package/blocks/footer/footer-cta/template.html +0 -1
  235. package/blocks/footer/footer-social/README.md +0 -37
  236. package/blocks/footer/footer-social/styles.css +0 -17
  237. package/blocks/footer/footer-social/template.html +0 -1
  238. package/blocks/footer/footer-wordmark/README.md +0 -40
  239. package/blocks/footer/footer-wordmark/styles.css +0 -19
  240. package/blocks/footer/footer-wordmark/template.html +0 -1
  241. package/blocks/gallery/gallery-before-after/README.md +0 -31
  242. package/blocks/gallery/gallery-before-after/styles.css +0 -6
  243. package/blocks/gallery/gallery-before-after/template.html +0 -1
  244. package/blocks/gallery/gallery-carousel/README.md +0 -32
  245. package/blocks/gallery/gallery-carousel/styles.css +0 -7
  246. package/blocks/gallery/gallery-carousel/template.html +0 -1
  247. package/blocks/gallery/gallery-grid/README.md +0 -39
  248. package/blocks/gallery/gallery-grid/styles.css +0 -13
  249. package/blocks/gallery/gallery-grid/template.html +0 -1
  250. package/blocks/gallery/gallery-masonry/README.md +0 -33
  251. package/blocks/gallery/gallery-masonry/styles.css +0 -4
  252. package/blocks/gallery/gallery-masonry/template.html +0 -1
  253. package/blocks/gallery/gallery-mosaic-split/README.md +0 -40
  254. package/blocks/gallery/gallery-mosaic-split/styles.css +0 -15
  255. package/blocks/gallery/gallery-mosaic-split/template.html +0 -1
  256. package/blocks/hero/hero-asymmetric/README.md +0 -34
  257. package/blocks/hero/hero-asymmetric/styles.css +0 -13
  258. package/blocks/hero/hero-asymmetric/template.html +0 -10
  259. package/blocks/hero/hero-before-after/README.md +0 -38
  260. package/blocks/hero/hero-before-after/styles.css +0 -8
  261. package/blocks/hero/hero-before-after/template.html +0 -19
  262. package/blocks/hero/hero-editorial/README.md +0 -34
  263. package/blocks/hero/hero-editorial/block.meta.json +0 -85
  264. package/blocks/hero/hero-editorial/styles.css +0 -6
  265. package/blocks/hero/hero-editorial/template.html +0 -10
  266. package/blocks/hero/hero-evidence/README.md +0 -32
  267. package/blocks/hero/hero-evidence/block.meta.json +0 -85
  268. package/blocks/hero/hero-evidence/styles.css +0 -13
  269. package/blocks/hero/hero-evidence/template.html +0 -1
  270. package/blocks/hero/hero-form/README.md +0 -46
  271. package/blocks/hero/hero-form/styles.css +0 -11
  272. package/blocks/hero/hero-form/template.html +0 -15
  273. package/blocks/hero/hero-menu/README.md +0 -36
  274. package/blocks/hero/hero-menu/styles.css +0 -7
  275. package/blocks/hero/hero-menu/template.html +0 -10
  276. package/blocks/hero/hero-overlay/README.md +0 -35
  277. package/blocks/hero/hero-overlay/styles.css +0 -14
  278. package/blocks/hero/hero-overlay/template.html +0 -10
  279. package/blocks/hero/hero-page/README.md +0 -35
  280. package/blocks/hero/hero-page/styles.css +0 -19
  281. package/blocks/hero/hero-page/template.html +0 -1
  282. package/blocks/hero/hero-product/README.md +0 -41
  283. package/blocks/hero/hero-product/styles.css +0 -11
  284. package/blocks/hero/hero-product/template.html +0 -14
  285. package/blocks/hero/hero-service/README.md +0 -37
  286. package/blocks/hero/hero-service/block.meta.json +0 -85
  287. package/blocks/hero/hero-service/styles.css +0 -17
  288. package/blocks/hero/hero-service/template.html +0 -1
  289. package/blocks/hero/hero-split/README.md +0 -36
  290. package/blocks/hero/hero-split/styles.css +0 -7
  291. package/blocks/hero/hero-split/template.html +0 -11
  292. package/blocks/hero/hero-statement/README.md +0 -33
  293. package/blocks/hero/hero-statement/styles.css +0 -8
  294. package/blocks/hero/hero-statement/template.html +0 -1
  295. package/blocks/hero/hero-stats/README.md +0 -37
  296. package/blocks/hero/hero-stats/styles.css +0 -10
  297. package/blocks/hero/hero-stats/template.html +0 -10
  298. package/blocks/hero/hero-video-still/README.md +0 -36
  299. package/blocks/hero/hero-video-still/styles.css +0 -9
  300. package/blocks/hero/hero-video-still/template.html +0 -13
  301. package/blocks/icons.md +0 -44
  302. package/blocks/incentives/incentive-banner/README.md +0 -28
  303. package/blocks/incentives/incentive-banner/styles.css +0 -7
  304. package/blocks/incentives/incentive-banner/template.html +0 -1
  305. package/blocks/incentives/incentive-cards/README.md +0 -31
  306. package/blocks/incentives/incentive-cards/styles.css +0 -4
  307. package/blocks/incentives/incentive-cards/template.html +0 -1
  308. package/blocks/navbar/nav-announcement/README.md +0 -35
  309. package/blocks/navbar/nav-announcement/styles.css +0 -10
  310. package/blocks/navbar/nav-announcement/template.html +0 -14
  311. package/blocks/navbar/nav-centered/README.md +0 -35
  312. package/blocks/navbar/nav-centered/styles.css +0 -11
  313. package/blocks/navbar/nav-centered/template.html +0 -12
  314. package/blocks/navbar/nav-minimal/README.md +0 -29
  315. package/blocks/navbar/nav-minimal/styles.css +0 -5
  316. package/blocks/navbar/nav-minimal/template.html +0 -6
  317. package/blocks/navbar/nav-split/README.md +0 -34
  318. package/blocks/navbar/nav-split/styles.css +0 -11
  319. package/blocks/navbar/nav-split/template.html +0 -11
  320. package/blocks/navbar/nav-utility/README.md +0 -37
  321. package/blocks/navbar/nav-utility/styles.css +0 -17
  322. package/blocks/navbar/nav-utility/template.html +0 -12
  323. package/blocks/pricing/menu-featured/README.md +0 -34
  324. package/blocks/pricing/menu-featured/styles.css +0 -4
  325. package/blocks/pricing/menu-featured/template.html +0 -1
  326. package/blocks/pricing/menu-sections/README.md +0 -33
  327. package/blocks/pricing/menu-sections/styles.css +0 -9
  328. package/blocks/pricing/menu-sections/template.html +0 -1
  329. package/blocks/pricing/pricing-table/README.md +0 -40
  330. package/blocks/pricing/pricing-table/styles.css +0 -9
  331. package/blocks/pricing/pricing-table/template.html +0 -1
  332. package/blocks/pricing/pricing-tiers/README.md +0 -34
  333. package/blocks/pricing/pricing-tiers/styles.css +0 -7
  334. package/blocks/pricing/pricing-tiers/template.html +0 -1
  335. package/blocks/pricing/pricing-toggle/README.md +0 -34
  336. package/blocks/pricing/pricing-toggle/styles.css +0 -10
  337. package/blocks/pricing/pricing-toggle/template.html +0 -1
  338. package/blocks/process/process-carousel/README.md +0 -33
  339. package/blocks/process/process-carousel/styles.css +0 -5
  340. package/blocks/process/process-carousel/template.html +0 -1
  341. package/blocks/process/process-split/README.md +0 -35
  342. package/blocks/process/process-split/styles.css +0 -6
  343. package/blocks/process/process-split/template.html +0 -1
  344. package/blocks/process/process-stepper/README.md +0 -40
  345. package/blocks/process/process-stepper/styles.css +0 -11
  346. package/blocks/process/process-stepper/template.html +0 -1
  347. package/blocks/process/process-steps/README.md +0 -35
  348. package/blocks/process/process-steps/styles.css +0 -6
  349. package/blocks/process/process-steps/template.html +0 -1
  350. package/blocks/process/process-sticky/README.md +0 -38
  351. package/blocks/process/process-sticky/styles.css +0 -12
  352. package/blocks/process/process-sticky/template.html +0 -1
  353. package/blocks/process/process-timeline/README.md +0 -35
  354. package/blocks/process/process-timeline/styles.css +0 -10
  355. package/blocks/process/process-timeline/template.html +0 -1
  356. package/blocks/services/services-cards/README.md +0 -34
  357. package/blocks/services/services-cards/styles.css +0 -3
  358. package/blocks/services/services-cards/template.html +0 -1
  359. package/blocks/services/services-carousel/README.md +0 -34
  360. package/blocks/services/services-carousel/styles.css +0 -6
  361. package/blocks/services/services-carousel/template.html +0 -1
  362. package/blocks/services/services-list/README.md +0 -32
  363. package/blocks/services/services-list/block.meta.json +0 -85
  364. package/blocks/services/services-list/styles.css +0 -10
  365. package/blocks/services/services-list/template.html +0 -1
  366. package/blocks/services/services-menu/README.md +0 -39
  367. package/blocks/services/services-menu/styles.css +0 -6
  368. package/blocks/services/services-menu/template.html +0 -1
  369. package/blocks/services/services-packages/README.md +0 -34
  370. package/blocks/services/services-packages/styles.css +0 -6
  371. package/blocks/services/services-packages/template.html +0 -1
  372. package/blocks/services/services-panels/README.md +0 -36
  373. package/blocks/services/services-panels/styles.css +0 -15
  374. package/blocks/services/services-panels/template.html +0 -1
  375. package/blocks/services/services-photo-grid/README.md +0 -39
  376. package/blocks/services/services-photo-grid/styles.css +0 -10
  377. package/blocks/services/services-photo-grid/template.html +0 -1
  378. package/blocks/services/services-priority/README.md +0 -33
  379. package/blocks/services/services-priority/block.meta.json +0 -86
  380. package/blocks/services/services-priority/styles.css +0 -16
  381. package/blocks/services/services-priority/template.html +0 -1
  382. package/blocks/stats/stats-cards/README.md +0 -31
  383. package/blocks/stats/stats-cards/styles.css +0 -4
  384. package/blocks/stats/stats-cards/template.html +0 -1
  385. package/blocks/stats/stats-mosaic/README.md +0 -27
  386. package/blocks/stats/stats-mosaic/styles.css +0 -9
  387. package/blocks/stats/stats-mosaic/template.html +0 -1
  388. package/blocks/stats/stats-row/README.md +0 -29
  389. package/blocks/stats/stats-row/styles.css +0 -8
  390. package/blocks/stats/stats-row/template.html +0 -1
  391. package/blocks/stats/stats-split/README.md +0 -35
  392. package/blocks/stats/stats-split/styles.css +0 -3
  393. package/blocks/stats/stats-split/template.html +0 -1
  394. package/blocks/team/team-featured/README.md +0 -42
  395. package/blocks/team/team-featured/styles.css +0 -9
  396. package/blocks/team/team-featured/template.html +0 -1
  397. package/blocks/team/team-grid/README.md +0 -35
  398. package/blocks/team/team-grid/styles.css +0 -8
  399. package/blocks/team/team-grid/template.html +0 -1
  400. package/blocks/team/team-list/README.md +0 -32
  401. package/blocks/team/team-list/styles.css +0 -7
  402. package/blocks/team/team-list/template.html +0 -1
  403. package/blocks/testimonial/testimonial-carousel/README.md +0 -32
  404. package/blocks/testimonial/testimonial-carousel/styles.css +0 -7
  405. package/blocks/testimonial/testimonial-carousel/template.html +0 -1
  406. package/blocks/testimonial/testimonial-grid/README.md +0 -32
  407. package/blocks/testimonial/testimonial-grid/styles.css +0 -5
  408. package/blocks/testimonial/testimonial-grid/template.html +0 -1
  409. package/blocks/testimonial/testimonial-mosaic/README.md +0 -38
  410. package/blocks/testimonial/testimonial-mosaic/styles.css +0 -14
  411. package/blocks/testimonial/testimonial-mosaic/template.html +0 -1
  412. package/blocks/testimonial/testimonial-platform/README.md +0 -34
  413. package/blocks/testimonial/testimonial-platform/styles.css +0 -17
  414. package/blocks/testimonial/testimonial-platform/template.html +0 -1
  415. package/blocks/testimonial/testimonial-rating/README.md +0 -28
  416. package/blocks/testimonial/testimonial-rating/styles.css +0 -6
  417. package/blocks/testimonial/testimonial-rating/template.html +0 -1
  418. package/blocks/testimonial/testimonial-spotlight/README.md +0 -31
  419. package/blocks/testimonial/testimonial-spotlight/styles.css +0 -9
  420. package/blocks/testimonial/testimonial-spotlight/template.html +0 -1
  421. package/blocks/testimonial/testimonial-switcher/README.md +0 -39
  422. package/blocks/testimonial/testimonial-switcher/styles.css +0 -23
  423. package/blocks/testimonial/testimonial-switcher/template.html +0 -1
  424. package/blocks/testimonial/testimonial-wall/README.md +0 -34
  425. package/blocks/testimonial/testimonial-wall/styles.css +0 -7
  426. package/blocks/testimonial/testimonial-wall/template.html +0 -1
  427. package/blocks/trust-strip/trust-badges/README.md +0 -30
  428. package/blocks/trust-strip/trust-badges/styles.css +0 -5
  429. package/blocks/trust-strip/trust-badges/template.html +0 -1
  430. package/blocks/trust-strip/trust-certs/README.md +0 -31
  431. package/blocks/trust-strip/trust-certs/styles.css +0 -12
  432. package/blocks/trust-strip/trust-certs/template.html +0 -1
  433. package/blocks/trust-strip/trust-logos/README.md +0 -32
  434. package/blocks/trust-strip/trust-logos/styles.css +0 -5
  435. package/blocks/trust-strip/trust-logos/template.html +0 -1
  436. package/blocks/trust-strip/trust-quote/README.md +0 -29
  437. package/blocks/trust-strip/trust-quote/styles.css +0 -5
  438. package/blocks/trust-strip/trust-quote/template.html +0 -1
  439. package/blocks/trust-strip/trust-reviews/README.md +0 -35
  440. package/blocks/trust-strip/trust-reviews/styles.css +0 -9
  441. package/blocks/trust-strip/trust-reviews/template.html +0 -1
  442. package/blocks/work/case-alternating/README.md +0 -34
  443. package/blocks/work/case-alternating/block.meta.json +0 -86
  444. package/blocks/work/case-alternating/styles.css +0 -7
  445. package/blocks/work/case-alternating/template.html +0 -1
  446. package/blocks/work/case-carousel/README.md +0 -26
  447. package/blocks/work/case-carousel/styles.css +0 -7
  448. package/blocks/work/case-carousel/template.html +0 -1
  449. package/blocks/work/case-header/README.md +0 -38
  450. package/blocks/work/case-header/styles.css +0 -18
  451. package/blocks/work/case-header/template.html +0 -1
  452. package/blocks/work/project-evidence/README.md +0 -35
  453. package/blocks/work/project-evidence/block.meta.json +0 -87
  454. package/blocks/work/project-evidence/styles.css +0 -12
  455. package/blocks/work/project-evidence/template.html +0 -1
  456. package/blocks/work/project-grid/README.md +0 -38
  457. package/blocks/work/project-grid/styles.css +0 -9
  458. package/blocks/work/project-grid/template.html +0 -1
@@ -1,458 +0,0 @@
1
- import {
2
- digest
3
- } from "./chunk-AUO5I56E.js";
4
- import {
5
- fingerprint,
6
- sourceHash,
7
- within
8
- } from "./chunk-T6PE4KN4.js";
9
-
10
- // src/agent/playwright-runtime.ts
11
- async function loadPlaywrightChromium() {
12
- let imported;
13
- try {
14
- imported = await import("playwright");
15
- } catch (error) {
16
- const message = error instanceof Error ? error.message : String(error);
17
- const missing = error.code === "ERR_MODULE_NOT_FOUND" || /Cannot find package ['"]playwright['"]/.test(message);
18
- if (missing) {
19
- throw new Error("The playwright npm package is not installed. @tryvitris/website-harness depends on it for browser capture. Reinstall the package so its dependencies are installed. Browser binaries are separate: after the package is present, run `npx playwright install chromium`.");
20
- }
21
- throw error;
22
- }
23
- const chromium = imported.chromium || imported.default?.chromium;
24
- if (!chromium?.launch) {
25
- throw new Error("The installed playwright package did not export chromium. Reinstall playwright, then run `npx playwright install chromium`.");
26
- }
27
- return chromium;
28
- }
29
- function explainBrowserLaunchFailure(error) {
30
- const message = error instanceof Error ? error.message : String(error);
31
- if (/executable doesn't exist|browserType\.launch|npx playwright install|Failed to launch/i.test(message)) {
32
- return `Playwright is installed, but the Chromium browser binary is not provisioned. Run: npx playwright install chromium
33
- ${message}`;
34
- }
35
- return message;
36
- }
37
-
38
- // src/agent/template-motion.ts
39
- import { existsSync, readFileSync } from "node:fs";
40
- import { join } from "node:path";
41
- var TEMPLATE_MOTION_PATH = "agent/decisions/template-motion.json";
42
- var templateMotionHash = (plan) => digest(plan);
43
- function validateTemplateMotionPlan(plan) {
44
- const failures = [];
45
- if (plan?.version !== 1 || !plan.selectionHash || !/^https:\/\//.test(plan.referenceUrl || "") || !Array.isArray(plan.moments) || !plan.moments.length) return ["Template motion needs a versioned plan, selection and pinned HTTPS reference"];
46
- if (new Set(plan.moments.map((m) => m.id)).size !== plan.moments.length) failures.push("Duplicate template motion moment IDs");
47
- if (!plan.moments.some((m) => m.kind === "load")) failures.push("Fresh-session load comparison required: inspect the opening from navigation start");
48
- for (const m of plan.moments) {
49
- if (!/^[\w-]+$/.test(m.id) || !["load", "marquee", "pointer-follow", "magnetic", "scroll", "route", "drawer", "sequence"].includes(m.kind) || !m.intent?.trim() || !Number.isInteger(m.width) || m.width < 320 || m.width > 2560 || [m.reference, m.implementation].some((s) => !s?.path?.startsWith("/") || !s.target?.trim() || !s.observe?.trim())) failures.push("Invalid located motion moment: " + m.id);
50
- }
51
- for (const m of plan.moments) for (const side of [m.reference, m.implementation]) if (side?.requiredPhases !== void 0 && (!Array.isArray(side.requiredPhases) || side.requiredPhases.some((p) => typeof p !== "string" || !p.trim()))) failures.push("Invalid required transition phases: " + m.id);
52
- return failures;
53
- }
54
- function templateMotionReviewFailures(root, selectionHash, node) {
55
- const path = join(root, TEMPLATE_MOTION_PATH);
56
- if (!existsSync(path)) return [];
57
- const plan = JSON.parse(readFileSync(path, "utf8"));
58
- const errors = validateTemplateMotionPlan(plan);
59
- if (plan.selectionHash !== selectionHash) errors.push("Template motion plan belongs to a different selection");
60
- if (!["representative-review", "visual-review"].includes(node)) return errors;
61
- const reportPath = join(root, "agent/reviews/" + (node === "representative-review" ? "representative-browser" : "browser") + ".json");
62
- const evidence = existsSync(reportPath) ? JSON.parse(readFileSync(reportPath, "utf8")).templateMotion : void 0;
63
- if (!evidence || evidence.version !== 1 || evidence.planHash !== templateMotionHash(plan) || evidence.selectionHash !== selectionHash || evidence.distHash !== fingerprint(root, ["dist"])) return [...errors, "Current recorded template motion comparison missing or stale"];
64
- const files = new Map((evidence.files || []).map((f) => [f.path, f.hash]));
65
- for (const m of plan.moments) for (const side of ["reference", "implementation"]) {
66
- const c = evidence.captures?.find((c2) => c2.momentId === m.id && c2.side === side && c2.width === m.width);
67
- if (!c || !Array.isArray(c.failures) || c.failures.length || !Array.isArray(c.frames) || c.frames.length < 3 || !Array.isArray(c.samples) || c.samples.length < 3 || !c.video) {
68
- errors.push("Incomplete temporal comparison: " + m.id + " / " + side);
69
- continue;
70
- }
71
- for (const phase of Array.isArray(m[side].requiredPhases) ? m[side].requiredPhases : []) if (!Array.isArray(c.phaseStates) || !c.phaseStates.some((s) => s.phase === phase)) errors.push("Missing recorded transition phase: " + m.id + " / " + side + " / " + phase);
72
- for (const path2 of [...c.frames, c.video]) {
73
- try {
74
- if (!files.get(path2) || !existsSync(within(root, path2)) || files.get(path2) !== fingerprint(root, [path2])) errors.push("Changed or missing template motion capture: " + path2);
75
- } catch {
76
- errors.push("Unsafe template motion capture: " + path2);
77
- }
78
- }
79
- if (new Set(c.samples.map((s) => s.state)).size < 2 && !m.departure?.trim()) errors.push("No observed temporal change or explained departure: " + m.id + " / " + side);
80
- }
81
- const reviewPath = join(root, "agent/reviews/" + node + ".json");
82
- const fidelity = existsSync(reviewPath) ? JSON.parse(readFileSync(reviewPath, "utf8")).templateMotion : void 0;
83
- if (!fidelity || fidelity.planHash !== templateMotionHash(plan) || fidelity.distHash !== evidence.distHash) errors.push("Temporal fidelity review missing or stale");
84
- else for (const m of plan.moments) {
85
- const comparison = fidelity.moments?.find((r) => r.id === m.id);
86
- if (!comparison || comparison.verdict !== "pass" || ["timing", "easing", "continuity", "inputAlternatives"].some((k) => !comparison[k]?.trim())) errors.push("Located temporal assessment missing: " + m.id);
87
- }
88
- return errors;
89
- }
90
-
91
- // src/agent/motion-composition.ts
92
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
93
- import { join as join2 } from "node:path";
94
- import { parseFragment } from "parse5";
95
- function motionCompositionPolicy(root, routes) {
96
- const site = existsSync2(join2(root, "site.json")) ? JSON.parse(readFileSync2(join2(root, "site.json"), "utf8")) : {};
97
- const policy = site.motionComposition;
98
- const requestPath = join2(root, "agent/change-request.json"), request = existsSync2(requestPath) ? JSON.parse(readFileSync2(requestPath, "utf8")) : {};
99
- const reauthored = [request.scope, ...request.scopes || []].some((s) => ["pages", "direction"].includes(s)) ? (request.affectedPages || []).filter((p) => routes.includes(p)) : [];
100
- return { operatorOff: site.scrollMotion?.policy === "off", requiredRoutes: [.../* @__PURE__ */ new Set([...policy?.version === 2 ? policy.routes === "all-authored" ? routes : Array.isArray(policy.routes) ? policy.routes : [] : [], ...reauthored])] };
101
- }
102
- function validateRouteComposition(plan, routes, options = {}) {
103
- const errors = [];
104
- if (options.requiredRoutes?.length && plan?.version !== 2) return ["Required motionPlan v2 missing: compose every authored route, including expansion; a legacy scene list is insufficient"];
105
- if (plan?.version !== 2) return errors;
106
- if (!Array.isArray(plan.routes)) return ["motionPlan v2 requires route compositions"];
107
- const required = options.requiredRoutes?.length ? options.requiredRoutes : routes || plan.routes.map((r) => r.route);
108
- for (const route of required) if (!plan.routes.some((r) => r.route === route)) errors.push(`Missing motion composition for authored route: ${route}`);
109
- if (new Set(plan.routes.map((r) => r.route)).size !== plan.routes.length) errors.push("Duplicate route motion composition");
110
- for (const r of plan.routes) {
111
- if (!r.route?.startsWith("/") || routes && !routes.includes(r.route) || ["task", "character", "normal", "mobile", "reduced", "ending"].some((k) => !r[k]?.trim()) || !Array.isArray(r.available) || !r.available.length || !Array.isArray(r.beats) || !r.beats.length) {
112
- errors.push(`Incomplete route composition: ${r.route}`);
113
- continue;
114
- }
115
- const routeScenes = plan.scenes.filter((s) => s.route === r.route), expected = options.sections?.[r.route];
116
- if (expected && expected.join("|") !== r.beats.map((b) => b.sectionId).join("|")) errors.push(`Content beats missing/out of document order: ${r.route}; expected ${expected.join(", ")}`);
117
- if (new Set(r.beats.map((b) => b.sectionId)).size !== r.beats.length) errors.push(`Duplicate content beat: ${r.route}`);
118
- for (const [i, b] of r.beats.entries()) {
119
- const role = r.beats.length === 1 ? "whole" : i === 0 ? "opening" : i === r.beats.length - 1 ? "closing" : "development";
120
- if (!/^[A-Za-z][\w-]*$/.test(b.sectionId || "") || !b.change?.trim() || !b.transition?.trim() || !Array.isArray(b.scenes) || b.role !== role) errors.push(`Incomplete/incorrectly ordered motion beat: ${r.route}#${b.sectionId}`);
121
- for (const id of b.scenes || []) if (!routeScenes.some((s) => s.targetId === id)) errors.push(`Unbound beat scene: ${r.route}#${b.sectionId}/${id}`);
122
- if (!options.operatorOff && !b.scenes?.length) {
123
- const a = b.connects?.map((id) => r.beats.findIndex((x) => x.scenes?.includes(id)));
124
- if (!a || a.length !== 2 || (a[0] ?? -1) < 0 || (a[0] ?? -1) >= i || (a[1] ?? -1) <= i) errors.push(`Quiet interval needs located active moments on both sides: ${r.route}#${b.sectionId}`);
125
- }
126
- }
127
- for (const s of routeScenes) if (!r.beats.some((b) => b.scenes?.includes(s.targetId))) errors.push(`Scene omitted from journey: ${r.route}#${s.targetId}`);
128
- if (!options.operatorOff) {
129
- if (!r.beats[0]?.scenes?.length || !r.beats.at(-1)?.scenes?.length) errors.push(`Opening/closing not composed: ${r.route}; one isolated region cannot stand for the whole route`);
130
- if (!routeScenes.some((s) => s.mobile === "same")) errors.push(`Mobile route has no active treatment: ${r.route}`);
131
- }
132
- }
133
- return errors;
134
- }
135
- function compositionBindingFailures(plan, route, html) {
136
- if (plan?.version !== 2) return [];
137
- const r = plan.routes?.find((r2) => r2.route === route);
138
- if (!r) return [];
139
- const elements = [], walk = (n) => {
140
- if (n.attrs) elements.push(n);
141
- for (const c of n.childNodes || []) walk(c);
142
- };
143
- walk(parseFragment(html));
144
- const get = (n, k) => n?.attrs?.find((a) => a.name === k)?.value, byId = (id) => elements.filter((n) => get(n, "id") === id), contains = (root, n) => root === n || (root?.childNodes || []).some((c) => contains(c, n));
145
- const errors = [];
146
- let last = -1;
147
- for (const beat of r.beats) {
148
- const nodes = byId(beat.sectionId), section = nodes[0], position = elements.indexOf(section);
149
- if (nodes.length !== 1 || position <= last) errors.push(`Missing/out-of-order page beat: ${route}#${beat.sectionId}`);
150
- last = position;
151
- for (const id of beat.scenes) if (!byId(id)[0] || !contains(section, byId(id)[0])) errors.push(`Scene lies outside planned content beat: ${route}#${beat.sectionId}/${id}`);
152
- }
153
- for (const id of r.available) {
154
- const nodes = byId(id);
155
- if (nodes.length !== 1) errors.push(`Continuously available target missing: ${route}#${id}`);
156
- else if (elements.some((n) => ["text", "entrance", "stagger", "sequence", "count"].includes(get(n, "data-motion")) && contains(n, nodes[0]))) errors.push(`Essential reading/action inside active target: ${route}#${id}`);
157
- }
158
- return errors;
159
- }
160
- function concentrationFailures(route, sections, scenes, viewport) {
161
- const active = scenes.filter((s) => s.active), regions = new Set(active.map((s) => s.sectionId).filter(Boolean));
162
- if (sections.length > 1 && regions.size === 1) {
163
- const region = sections.find((s) => regions.has(s.id));
164
- if (region && sections.some((s) => s.id !== region.id && (s.bottom <= region.top || s.top >= region.bottom) && s.bottom - s.top >= viewport * 0.5)) return [`Concentrated motion: ${route} all active scenes lie in #${region.id} while other substantial content is uncomposed; repair the opening/development/closing relationships, not an effect quota`];
165
- }
166
- return [];
167
- }
168
-
169
- // src/agent/browser-motion-journey.ts
170
- import { createHash } from "node:crypto";
171
- import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3 } from "node:fs";
172
- import { join as join3, relative } from "node:path";
173
- var JOURNEY_SCENARIO = { version: 6, fontSettlementMs: 5e3, arrivalSettlementMs: 5e3, openingObservationMs: 6e3, openingMs: 600, stepPx: 180, readingMs: 600, firstSampleMs: 120, settleMs: 1600, maxHeight: 6e4, modes: ["normal", "reduce", "static"], traversal: "early opening render-state sampling, real arrival settlement, then continuous forward native wheel through the final scroll pixel, overlapping viewport checkpoints including quiet intervals and closing; no target jumps" };
174
- var JOURNEY_SCENARIO_HASH = createHash("sha256").update(JSON.stringify(JOURNEY_SCENARIO)).digest("hex");
175
- async function captureMotionJourney(browser, root, url, route, width, mode, directory, plan, operatorOff = false) {
176
- const folder = join3(root, directory);
177
- mkdirSync(folder, { recursive: true });
178
- const context = await browser.newContext({ viewport: { width, height: 900 }, reducedMotion: mode === "reduce" ? "reduce" : "no-preference", javaScriptEnabled: mode !== "static", ...mode === "normal" ? { recordVideo: { dir: folder, size: { width, height: 900 } } } : {} });
179
- const page = await context.newPage(), composition = plan.routes?.find((r) => r.route === route), declared = plan.scenes.filter((s) => s.route === route), html = readFileSync3(join3(root, `dist${route === "/" ? "" : route}/index.html`), "utf8"), asset = html.match(/src=["'](\/motion-[^"']+\.js)["']/)?.[1];
180
- const result = { path: route, width, mode, sourceHash: sourceHash(root), outputHash: fingerprint(root, ["dist"]), planHash: fingerprint(root, ["onboarding/storyboard.json"]), scenarioHash: JOURNEY_SCENARIO_HASH, engineAssetHash: asset ? fingerprint(root, [`dist${asset}`]) : "", sections: [], scenes: [], checkpoints: [], failures: [] };
181
- const started = Date.now();
182
- try {
183
- page.on("pageerror", (e) => result.failures.push(e.message));
184
- await page.route("**/api/**", (r) => r.fulfill({ status: 204, body: "" }));
185
- if (mode === "normal") await page.addInitScript(({ ids, started: started2, limit }) => {
186
- const buffer = window.__vitrisJourneyOpening = { stopped: false, checkpoints: [] }, previous2 = /* @__PURE__ */ new Map();
187
- const tick = () => {
188
- if (buffer.stopped || Date.now() - started2 > limit) return;
189
- const states = ids.flatMap((id) => {
190
- const e = document.getElementById(id), state = window.VitrisMotion?.inspect(id);
191
- if (!e || state?.static !== false) return [];
192
- const nodes = [e, ...e.querySelectorAll("[data-motion-word],[data-motion-child],[data-motion-path],[data-motion-visual]")];
193
- return [{ id, signature: JSON.stringify(nodes.map((n) => {
194
- const s = getComputedStyle(n);
195
- return [s.opacity, s.transform, s.clipPath, s.strokeDashoffset, n.hasAttribute("data-motion-visual") ? n.textContent : ""];
196
- })), phase: state.phase || null, static: false }];
197
- });
198
- const changed = states.some((s) => previous2.get(s.id) !== s.signature);
199
- states.forEach((s) => previous2.set(s.id, s.signature));
200
- if (changed && buffer.checkpoints.length < 128) buffer.checkpoints.push({ y: scrollY, timeMs: Date.now() - started2, states });
201
- window.requestAnimationFrame(tick);
202
- };
203
- window.requestAnimationFrame(tick);
204
- }, { ids: declared.map((s) => s.targetId), started, limit: JOURNEY_SCENARIO.openingObservationMs });
205
- await page.goto(url, { waitUntil: "domcontentloaded" });
206
- const fontsSettled = await page.evaluate(async (ms) => await Promise.race([document.fonts.ready.then(() => true), new Promise((resolve) => setTimeout(() => resolve(false), ms))]), JOURNEY_SCENARIO.fontSettlementMs);
207
- if (!fontsSettled) throw Error("Fonts did not settle before full-journey geometry capture");
208
- if (mode !== "static") await page.waitForFunction(() => !document.documentElement.dataset.experienceArrival, {}, { timeout: JOURNEY_SCENARIO.arrivalSettlementMs });
209
- const reject = page.locator("[data-cookie-reject]");
210
- if (mode !== "static" && await reject.isVisible()) await reject.click();
211
- await page.waitForTimeout(50);
212
- const geometry = await page.evaluate(({ ids, beatIds }) => {
213
- const sections = [.../* @__PURE__ */ new Set([...beatIds.map((id) => document.getElementById(id)), ...document.querySelectorAll("main section[id],main article[id]")])].filter(Boolean).map((e) => ({ id: e.id, top: e.getBoundingClientRect().top + scrollY, bottom: e.getBoundingClientRect().bottom + scrollY })).sort((a, b) => a.top - b.top);
214
- const scenes = ids.map((id) => {
215
- const e = document.getElementById(id), s = e?.closest("section[id],article[id],[data-section-id]");
216
- return { id, sectionId: s?.id || beatIds.find((id2) => document.getElementById(id2)?.contains(e)) || null, top: e ? e.getBoundingClientRect().top + scrollY : 0, bottom: e ? e.getBoundingClientRect().bottom + scrollY : 0, active: false };
217
- });
218
- return { sections, scenes, height: document.documentElement.scrollHeight };
219
- }, { ids: declared.map((s) => s.targetId), beatIds: composition?.beats.map((b) => b.sectionId) || [] });
220
- result.sections = geometry.sections;
221
- result.scenes = geometry.scenes;
222
- if (geometry.height > JOURNEY_SCENARIO.maxHeight) throw Error("Route exceeds bounded full-journey capture height; no partial journey may pass");
223
- const sample = async (index2, final = false) => {
224
- const snapshot = await page.evaluate(({ ids, available, readable }) => ({ y: scrollY, states: ids.map((id) => {
225
- const e = document.getElementById(id), state = window.VitrisMotion?.inspect(id);
226
- const nodes = e ? [e, ...e.querySelectorAll("[data-motion-word],[data-motion-child],[data-motion-path],[data-motion-visual]")] : [];
227
- return { id, signature: JSON.stringify(nodes.map((n) => {
228
- const s = getComputedStyle(n);
229
- return [s.opacity, s.transform, s.clipPath, s.strokeDashoffset, n.hasAttribute("data-motion-visual") ? n.textContent : ""];
230
- })), phase: state?.phase || null, static: state?.static ?? null, stickyTop: e?.getAttribute("data-motion") === "story" ? [e, ...e.querySelectorAll("*")].find((n) => getComputedStyle(n).position === "sticky")?.getBoundingClientRect().top ?? null : null };
231
- }), unavailable: available.filter((id) => {
232
- const e = document.getElementById(id);
233
- return !e || getComputedStyle(e).visibility === "hidden" || Number(getComputedStyle(e).opacity) < 0.99 || !e.getClientRects().length;
234
- }), unreadable: readable ? ids.filter((id) => {
235
- const e = document.getElementById(id);
236
- return !e || [e, ...e.querySelectorAll("[data-motion-word],[data-motion-child]")].some((n) => Number(getComputedStyle(n).opacity) < 0.99 || getComputedStyle(n).visibility === "hidden");
237
- }) : [] }), { ids: declared.map((s) => s.targetId), available: composition?.available || [], readable: mode !== "normal" || final });
238
- for (const id of snapshot.unavailable) result.failures.push(`Essential content/action unavailable in journey: ${route}#${id}`);
239
- for (const id of snapshot.unreadable) result.failures.push(`Final/reduced/static content unreadable: ${route}#${id}`);
240
- const checkpoint = { y: snapshot.y, timeMs: Date.now() - started, states: snapshot.states };
241
- if (index2 % 3 === 0 || final) {
242
- const path = `${directory}/${route.replace(/[^a-z0-9]/gi, "-")}-${width}-${mode}-${index2}.png`;
243
- await page.screenshot({ path: join3(root, path), animations: "allow" });
244
- checkpoint.screenshot = path;
245
- checkpoint.screenshotHash = fingerprint(root, [path]);
246
- }
247
- result.checkpoints.push(checkpoint);
248
- };
249
- if (mode === "normal") result.checkpoints.push(...await page.evaluate(() => {
250
- const buffer = window.__vitrisJourneyOpening;
251
- if (!buffer) return [];
252
- buffer.stopped = true;
253
- return buffer.checkpoints;
254
- }));
255
- let index = 0;
256
- await sample(index++);
257
- await page.waitForTimeout(JOURNEY_SCENARIO.openingMs);
258
- let previous = -1;
259
- while (true) {
260
- const position = await page.evaluate(() => ({ y: scrollY, max: document.documentElement.scrollHeight - innerHeight }));
261
- if (position.y >= position.max - 0.5) break;
262
- if (position.y === previous && index > 2) throw Error("Native traversal did not advance");
263
- previous = position.y;
264
- await page.mouse.wheel(0, Math.min(JOURNEY_SCENARIO.stepPx, position.max - position.y));
265
- await page.waitForTimeout(JOURNEY_SCENARIO.firstSampleMs);
266
- await sample(index++);
267
- await page.waitForTimeout(JOURNEY_SCENARIO.readingMs - JOURNEY_SCENARIO.firstSampleMs);
268
- }
269
- await page.waitForTimeout(JOURNEY_SCENARIO.settleMs);
270
- await sample(index, true);
271
- for (const scene of result.scenes) {
272
- const states = result.checkpoints.flatMap((c) => c.states.filter((s) => s.id === scene.id)), intent = declared.find((s) => s.targetId === scene.id);
273
- scene.active = scenePlayed(result.checkpoints, scene.id, intent.effect);
274
- if (mode === "normal" && !operatorOff && !(width < 600 && intent.mobile === "static") && !scene.active) result.failures.push(`Planned scene inert in full journey: ${route}#${scene.id}; inspect initial-visible/nested/large-target safeguards and choose a supporting target`);
275
- }
276
- if (mode === "normal" && !operatorOff) result.failures.push(...concentrationFailures(route, result.sections, result.scenes, 900));
277
- } catch (error) {
278
- result.failures.push(String(error));
279
- } finally {
280
- const video = page.video();
281
- await context.close();
282
- if (video) {
283
- result.video = relative(root, await video.path()).replaceAll("\\", "/");
284
- result.videoHash = fingerprint(root, [result.video]);
285
- }
286
- }
287
- result.failures = [...new Set(result.failures)];
288
- return result;
289
- }
290
- function scenePlayed(checkpoints, id, effect) {
291
- const states = checkpoints.flatMap((c) => c.states.filter((s) => s.id === id));
292
- if (effect !== "story") return new Set(states.map((s) => s.signature)).size > 1 && states.some((s) => s.static === false);
293
- return checkpoints.some((c, i) => {
294
- const previous = checkpoints[i - 1], a = previous?.states.find((s) => s.id === id), b = c.states.find((s) => s.id === id);
295
- return previous && c.y > previous.y + 20 && typeof a?.stickyTop === "number" && typeof b?.stickyTop === "number" && Math.abs(a.stickyTop - b.stickyTop) < 2 && b.stickyTop >= 0 && b.stickyTop < 900;
296
- });
297
- }
298
- function journeyEvidenceFailures(root, evidence, plan) {
299
- const errors = [...evidence.failures];
300
- const html = readFileSync3(join3(root, `dist${evidence.path === "/" ? "" : evidence.path}/index.html`), "utf8"), asset = html.match(/src=["'](\/motion-[^"']+\.js)["']/)?.[1];
301
- if (evidence.sourceHash !== sourceHash(root) || evidence.outputHash !== fingerprint(root, ["dist"]) || evidence.planHash !== fingerprint(root, ["onboarding/storyboard.json"]) || evidence.scenarioHash !== JOURNEY_SCENARIO_HASH || evidence.engineAssetHash !== (asset ? fingerprint(root, [`dist${asset}`]) : "")) errors.push(`Route journey source/output/plan/scenario bytes stale: ${evidence.path}`);
302
- if (!evidence.checkpoints.length || evidence.checkpoints[0].y > 2 || evidence.checkpoints.some((c, i) => i > 0 && (c.y < evidence.checkpoints[i - 1].y || c.y - evidence.checkpoints[i - 1].y > 900))) errors.push(`Route journey skipped content: ${evidence.path}`);
303
- if ((evidence.checkpoints.at(-1)?.y || 0) + 900 < Math.max(0, ...evidence.sections.map((s) => s.bottom)) - 2) errors.push(`Route journey did not reach closing content: ${evidence.path}`);
304
- for (const c of evidence.checkpoints) if (c.screenshot) {
305
- try {
306
- const bytes = readFileSync3(join3(root, c.screenshot));
307
- if (!c.screenshotHash || fingerprint(root, [c.screenshot]) !== c.screenshotHash || ![137, 80, 78, 71, 13, 10, 26, 10].every((v, i) => bytes[i] === v)) errors.push(`Journey checkpoint corrupt/changed: ${c.screenshot}`);
308
- } catch {
309
- errors.push(`Journey checkpoint missing: ${c.screenshot}`);
310
- }
311
- }
312
- if (evidence.mode === "normal" && (!evidence.video || !existsSync3(join3(root, evidence.video)) || fingerprint(root, [evidence.video]) !== evidence.videoHash)) errors.push(`Normal full-route recording missing/changed: ${evidence.path}`);
313
- for (const s of plan.scenes.filter((s2) => s2.route === evidence.path)) if (!evidence.scenes.some((e) => e.id === s.targetId)) errors.push(`Scene omitted from full journey: ${evidence.path}#${s.targetId}`);
314
- const off = motionCompositionPolicy(root, [evidence.path]).operatorOff;
315
- for (const scene of plan.scenes.filter((s) => s.route === evidence.path)) {
316
- const states = evidence.checkpoints.flatMap((c) => c.states.filter((s) => s.id === scene.targetId));
317
- const played = scenePlayed(evidence.checkpoints, scene.targetId, scene.effect);
318
- if (evidence.mode === "normal" && !off && !(evidence.width < 600 && scene.mobile === "static") && !played) errors.push(`Planned scene has no bound playback evidence: ${evidence.path}#${scene.targetId}`);
319
- }
320
- if (evidence.mode === "normal" && !off) errors.push(...concentrationFailures(evidence.path, evidence.sections, evidence.scenes, 900));
321
- return [...new Set(errors)];
322
- }
323
- var MOTION_CRITIQUE_CRITERIA = ["whole-journey", "distribution-connections", "business-rhythm", "competition-stillness", "route-differences", "immediate-use"];
324
- function motionCritiqueFailures(root, review, routes, report) {
325
- const errors = [];
326
- for (const route of routes) {
327
- const row = review.motionJourneys?.find((r) => r.route === route);
328
- if (!row) {
329
- errors.push(`Located whole-route motion critique missing: ${route}`);
330
- continue;
331
- }
332
- for (const criterion of MOTION_CRITIQUE_CRITERIA) {
333
- const check = row.checks?.find((c) => c.criterion === criterion);
334
- if (!check || check.verdict !== "pass" || typeof check.evidence !== "string" || check.evidence.trim().length < 24 || !Array.isArray(check.checkpoints) || !check.checkpoints.length) {
335
- errors.push(`Motion critique needs located judgment: ${route}/${criterion}`);
336
- continue;
337
- }
338
- for (const path of check.checkpoints) {
339
- const checkpoint = report.routeJourneys?.filter((j) => j.path === route).flatMap((j) => j.checkpoints).find((c) => c.screenshot === path);
340
- if (!checkpoint || !existsSync3(join3(root, path)) || fingerprint(root, [path]) !== checkpoint.screenshotHash) errors.push(`Motion critique checkpoint stale/missing: ${route}/${path}`);
341
- }
342
- }
343
- }
344
- return errors;
345
- }
346
-
347
- // src/agent/browser-motion.ts
348
- import { createHash as createHash2 } from "node:crypto";
349
- import { readFileSync as readFileSync4 } from "node:fs";
350
- import { join as join4 } from "node:path";
351
- var MOTION_SCENARIO = { version: 2, states: ["before", "during", "after"], triggerViewport: 0.78, duringMs: 120, settleMs: 1550, progress: [0, 0.5, 1], modes: ["normal", "reduce"], scrolling: "ordinary document flow, target checkpoints, forward and reverse", expressive: "canonical text, visual counter, authored phrase opacity, SVG stroke" };
352
- var MOTION_SCENARIO_HASH = createHash2("sha256").update(JSON.stringify(MOTION_SCENARIO)).digest("hex");
353
- async function observeMotion(page, root, route, width, mode, directory) {
354
- const scripts = page.locator('script[src*="/motion-"]');
355
- const asset = await scripts.count() ? await scripts.first().getAttribute("src") : null;
356
- const evidence = { path: route, width, motion: mode, scenarioHash: MOTION_SCENARIO_HASH, engineAssetHash: asset ? fingerprint(root, [`dist/${asset.replace(/^\//, "")}`]) : "", targets: [], failures: [] };
357
- if (!asset) return evidence;
358
- await page.waitForTimeout(50);
359
- const targets = await page.locator("[data-motion-target],[data-reveal]").evaluateAll((es) => es.map((e, i) => ({ id: e.id || `legacy-${i}`, effect: e.getAttribute("data-motion") || (e.hasAttribute("data-count-to") ? "count" : e.hasAttribute("data-reveal-stagger") ? "stagger" : "entrance"), index: i })));
360
- for (const [index, declared] of targets.entries()) {
361
- if (declared.id.startsWith("legacy-")) continue;
362
- if (await page.locator(`[id="${declared.id}"]`).count() !== 1) {
363
- evidence.failures.push(`Motion target not unique: ${declared.id}`);
364
- continue;
365
- }
366
- const target = page.locator(`[id="${declared.id}"]`);
367
- await page.evaluate(() => {
368
- scrollTo(0, 0);
369
- window.VitrisMotion?.init();
370
- });
371
- await page.waitForTimeout(50);
372
- const samples = [];
373
- const capture = async (state) => {
374
- const value = await target.evaluate((e) => ({ opacity: Math.min(...[e, ...e.querySelectorAll("[data-motion-child],[data-reveal-child],[data-motion-word]")].map((n) => Number(getComputedStyle(n).opacity))), transform: getComputedStyle(e).transform, progress: window.VitrisMotion?.inspect(e.id)?.progress ?? null, canonical: e.querySelector("[data-motion-visual]") ? e.firstElementChild?.textContent || "" : e.textContent || "", visual: e.querySelector("[data-motion-visual]")?.textContent ?? null, stroke: e.querySelector("[data-motion-path]") ? getComputedStyle(e.querySelector("[data-motion-path]")).strokeDashoffset : "" }));
375
- const path = `${directory}/motion-${route.replace(/[^a-z0-9]/gi, "-")}-${width}-${mode}-${index}-${state}.png`;
376
- await page.screenshot({ path: join4(root, path), animations: "allow" });
377
- samples.push({ state, ...value, screenshot: path, screenshotHash: fingerprint(root, [path]) });
378
- };
379
- await capture("before");
380
- const top = await target.evaluate((e) => e.getBoundingClientRect().top + scrollY);
381
- await page.evaluate((y) => scrollTo(0, Math.max(0, y - innerHeight * 0.78)), top);
382
- await page.waitForTimeout(MOTION_SCENARIO.duringMs);
383
- await capture("during");
384
- await page.waitForTimeout(MOTION_SCENARIO.settleMs);
385
- await capture("after");
386
- if (["entrance", "stagger", "text", "sequence"].includes(declared.effect)) {
387
- const unreadable = await target.evaluate((e) => [e, ...e.querySelectorAll("[data-motion-child],[data-reveal-child],[data-motion-word]")].some((n) => Number(getComputedStyle(n).opacity) < 0.99 || getComputedStyle(n).visibility === "hidden"));
388
- if (unreadable) evidence.failures.push(`Motion content not readable after settling: ${declared.id}`);
389
- }
390
- if (mode === "reduce" && samples.some((s) => s.opacity < 0.99)) evidence.failures.push(`Reduced motion hid content: ${declared.id}`);
391
- const runtimeState = await target.evaluate((e) => window.VitrisMotion?.inspect(e.id));
392
- if (!runtimeState) evidence.failures.push(`Motion runtime did not initialize: ${declared.id}`);
393
- if (mode === "normal" && !runtimeState?.static && ["entrance", "stagger", "text", "sequence"].includes(declared.effect) && samples.every((s) => s.opacity >= 0.99)) evidence.failures.push(`Declared entrance did not animate in the temporal scenario: ${declared.id}`);
394
- if (declared.effect === "count") {
395
- if (samples.some((s) => s.canonical !== samples[0].canonical) || samples.at(-1).visual !== null) evidence.failures.push(`Count canonical/final text changed: ${declared.id}`);
396
- if (mode === "normal" && !runtimeState?.static && !samples.some((s) => s.visual !== null && s.visual !== s.canonical)) evidence.failures.push(`Count never changed its visual value: ${declared.id}`);
397
- if (mode === "reduce" && samples.some((s) => s.visual !== null)) evidence.failures.push(`Reduced count animated: ${declared.id}`);
398
- }
399
- if (declared.effect === "draw" && mode === "normal" && !runtimeState?.static && new Set(samples.map((s) => s.stroke)).size < 2) evidence.failures.push(`Decorative path did not draw: ${declared.id}`);
400
- if (["progress", "drift"].includes(declared.effect) && mode === "normal" && !runtimeState?.static) {
401
- const states = [];
402
- for (const progress of MOTION_SCENARIO.progress) {
403
- const geometry = await target.evaluate((e) => {
404
- const t = document.getElementById(e.getAttribute("data-motion-trigger") || "");
405
- return { top: t.getBoundingClientRect().top + scrollY, height: t.getBoundingClientRect().height, start: Number(e.getAttribute("data-motion-range-start") || 0), end: Number(e.getAttribute("data-motion-range-end") || 1) };
406
- });
407
- const y = geometry.top - 900 + (900 + geometry.height) * (geometry.start + progress * (geometry.end - geometry.start));
408
- const clamped = await page.evaluate((y2) => {
409
- const max = document.documentElement.scrollHeight - innerHeight;
410
- scrollTo(0, y2);
411
- return y2 < 0 || y2 > max;
412
- }, y);
413
- await page.waitForTimeout(100);
414
- await capture(`progress-${progress}`);
415
- const actual = samples.at(-1).progress;
416
- if (actual !== null) states.push(actual);
417
- else evidence.failures.push(`Progress target did not provide current state: ${declared.id}`);
418
- if (!clamped && actual !== null && Math.abs(actual - progress) > 0.04) evidence.failures.push(`Progress checkpoint mismatch ${declared.id}: expected ${progress}, saw ${actual}`);
419
- }
420
- if (states.length && states[0] > states.at(-1) + 0.01) evidence.failures.push(`Progress reversed unexpectedly: ${declared.id}`);
421
- if (states.length > 1 && Math.max(...states) - Math.min(...states) > 0.1 && new Set(samples.filter((s) => s.state.startsWith("progress-")).map((s) => s.transform)).size < 2) evidence.failures.push(`Linked effect stayed static despite changing progress: ${declared.id}`);
422
- }
423
- evidence.targets.push({ id: declared.id, effect: declared.effect, samples });
424
- }
425
- await page.evaluate(() => scrollTo(0, 0));
426
- return evidence;
427
- }
428
- function temporalMotionFailures(root, evidence, expectedAssetHash) {
429
- const failures = [...evidence.failures];
430
- if (evidence.scenarioHash !== MOTION_SCENARIO_HASH || evidence.engineAssetHash !== expectedAssetHash) failures.push("Temporal motion evidence uses stale scenarios or engine bytes");
431
- for (const target of evidence.targets) for (const sample of target.samples) {
432
- try {
433
- const bytes = readFileSync4(join4(root, sample.screenshot));
434
- if (![137, 80, 78, 71, 13, 10, 26, 10].every((value, i) => bytes[i] === value) || fingerprint(root, [sample.screenshot]) !== sample.screenshotHash) failures.push(`Motion capture corrupt or changed: ${sample.screenshot}`);
435
- } catch {
436
- failures.push(`Motion capture missing: ${sample.screenshot}`);
437
- }
438
- }
439
- return failures;
440
- }
441
-
442
- export {
443
- loadPlaywrightChromium,
444
- explainBrowserLaunchFailure,
445
- TEMPLATE_MOTION_PATH,
446
- templateMotionHash,
447
- validateTemplateMotionPlan,
448
- templateMotionReviewFailures,
449
- motionCompositionPolicy,
450
- validateRouteComposition,
451
- compositionBindingFailures,
452
- captureMotionJourney,
453
- journeyEvidenceFailures,
454
- motionCritiqueFailures,
455
- MOTION_SCENARIO_HASH,
456
- observeMotion,
457
- temporalMotionFailures
458
- };
@@ -1,95 +0,0 @@
1
- import { blockPreviewEvidence, type BlockMeta } from "../../blocks/metadata.ts";
2
- export type FitLabel = "good-start" | "needs-adaptation" | "no-fit";
3
- export interface BlockSlot {
4
- name: string;
5
- required: boolean;
6
- description: string;
7
- }
8
- export interface BlockRecord {
9
- id: string;
10
- category: string;
11
- name: string;
12
- look: string;
13
- media: string;
14
- mediaRequired: boolean;
15
- registers: string[];
16
- variants: string[];
17
- slots: BlockSlot[];
18
- interaction: "static" | "island";
19
- mobile: {
20
- hasMediaQuery: boolean;
21
- notes: string;
22
- };
23
- geometry: string[];
24
- example: string;
25
- examplePath: string;
26
- previewPath?: string;
27
- previewHash?: string;
28
- seesImages: false;
29
- dir: string;
30
- meta?: BlockMeta;
31
- metadataSource?: "block.meta.json" | "legacy-readme";
32
- previewEvidence?: ReturnType<typeof blockPreviewEvidence>;
33
- }
34
- export interface BlockLibrary {
35
- generatedFrom: "readme+index+template";
36
- blocks: BlockRecord[];
37
- }
38
- export declare function loadBlockLibrary(kernel?: string): BlockLibrary;
39
- export declare function validateBlockLibrary(lib: BlockLibrary, kernel?: string): string[];
40
- export interface StoryboardSectionCase {
41
- id: string;
42
- siteType: string;
43
- role: string;
44
- visitorJob: string;
45
- mediaCount: number;
46
- mediaAspect?: string;
47
- interaction?: string;
48
- textLength: number;
49
- expectedFit: Record<string, FitLabel>;
50
- missingJob?: string;
51
- }
52
- export declare const BLOCK_COVERAGE_CASES: StoryboardSectionCase[];
53
- export declare function auditBlockCoverage(lib: BlockLibrary, cases?: StoryboardSectionCase[]): {
54
- gaps: Array<{
55
- caseId: string;
56
- missingJob?: string;
57
- noFit: boolean;
58
- }>;
59
- labeled: Array<{
60
- caseId: string;
61
- blockId: string;
62
- fit: FitLabel;
63
- }>;
64
- };
65
- export interface SectionState {
66
- sectionId: string;
67
- pagePath: string;
68
- visitorJob: string;
69
- requiredActions: string[];
70
- textLength: number;
71
- textContentIdentity?: string;
72
- mediaCount: number;
73
- mediaAspect?: string;
74
- mediaIds?: string[];
75
- mediaDescriptors?: string[];
76
- emphasis?: string;
77
- pageRole?: string;
78
- pageVisitorOutcome?: string;
79
- sectionRole?: string;
80
- sectionPurpose?: string;
81
- decisionIds?: string[];
82
- constraints?: string[];
83
- contentShape?: string;
84
- interaction?: string;
85
- adjacentRoles?: string[];
86
- adjacentSectionIds?: string[];
87
- neighborPurposes?: string[];
88
- repetitionRationale?: string;
89
- layoutFamily?: string;
90
- sourceIds?: string[];
91
- sourceHashes?: string[];
92
- }
93
- export declare function libraryContentHash(lib: BlockLibrary): string;
94
- export declare function hardFilterBlocks(lib: BlockLibrary, state: SectionState): BlockRecord[];
95
- export declare function lexicalShortlist(lib: BlockLibrary, state: SectionState, limit?: number): BlockRecord[];