@sleep2agi/agent-network-dashboard 0.5.3 → 0.5.5-preview.0

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 (496) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +2 -0
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/diagnostics/route-bundle-stats.json +37 -37
  5. package/.next/fallback-build-manifest.json +3 -3
  6. package/.next/prerender-manifest.json +29 -0
  7. package/.next/routes-manifest.json +12 -0
  8. package/.next/server/app/_global-error.html +1 -1
  9. package/.next/server/app/_global-error.rsc +2 -2
  10. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
  12. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/server/app/_not-found.html +3 -3
  17. package/.next/server/app/_not-found.rsc +14 -14
  18. package/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  19. package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  20. package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
  21. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  22. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  23. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  24. package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  25. package/.next/server/app/admin.html +3 -3
  26. package/.next/server/app/admin.rsc +16 -16
  27. package/.next/server/app/admin.segments/_full.segment.rsc +16 -16
  28. package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
  29. package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
  30. package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
  31. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
  32. package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
  33. package/.next/server/app/api/hub/upload/route/app-paths-manifest.json +3 -0
  34. package/.next/server/app/api/hub/upload/route/build-manifest.json +9 -0
  35. package/.next/server/app/api/hub/upload/route/server-reference-manifest.json +4 -0
  36. package/.next/server/app/api/hub/upload/route.js +7 -0
  37. package/.next/server/app/api/hub/upload/route.js.map +5 -0
  38. package/.next/server/app/api/hub/upload/route.js.nft.json +1 -0
  39. package/.next/server/app/api/hub/upload/route_client-reference-manifest.js +3 -0
  40. package/.next/server/app/index.html +3 -3
  41. package/.next/server/app/index.rsc +16 -16
  42. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  43. package/.next/server/app/index.segments/_full.segment.rsc +16 -16
  44. package/.next/server/app/index.segments/_head.segment.rsc +4 -4
  45. package/.next/server/app/index.segments/_index.segment.rsc +7 -7
  46. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  47. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  48. package/.next/server/app/login.html +2 -2
  49. package/.next/server/app/login.rsc +16 -16
  50. package/.next/server/app/login.segments/_full.segment.rsc +16 -16
  51. package/.next/server/app/login.segments/_head.segment.rsc +4 -4
  52. package/.next/server/app/login.segments/_index.segment.rsc +7 -7
  53. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  54. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
  55. package/.next/server/app/login.segments/login.segment.rsc +3 -3
  56. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  57. package/.next/server/app/logs.html +3 -3
  58. package/.next/server/app/logs.rsc +16 -16
  59. package/.next/server/app/logs.segments/_full.segment.rsc +16 -16
  60. package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
  61. package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
  62. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  63. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
  64. package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
  65. package/.next/server/app/manifest.webmanifest/route/app-paths-manifest.json +3 -0
  66. package/.next/server/app/manifest.webmanifest/route/build-manifest.json +9 -0
  67. package/.next/server/app/manifest.webmanifest/route/server-reference-manifest.json +4 -0
  68. package/.next/server/app/manifest.webmanifest/route.js +8 -0
  69. package/.next/server/app/manifest.webmanifest/route.js.map +5 -0
  70. package/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -0
  71. package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +3 -0
  72. package/.next/server/app/manifest.webmanifest.body +1 -0
  73. package/.next/server/app/manifest.webmanifest.meta +1 -0
  74. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  75. package/.next/server/app/messages.html +3 -3
  76. package/.next/server/app/messages.rsc +16 -16
  77. package/.next/server/app/messages.segments/_full.segment.rsc +16 -16
  78. package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
  79. package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
  80. package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
  81. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
  82. package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
  83. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  84. package/.next/server/app/node.html +3 -3
  85. package/.next/server/app/node.rsc +16 -16
  86. package/.next/server/app/node.segments/_full.segment.rsc +16 -16
  87. package/.next/server/app/node.segments/_head.segment.rsc +4 -4
  88. package/.next/server/app/node.segments/_index.segment.rsc +7 -7
  89. package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
  90. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
  91. package/.next/server/app/node.segments/node.segment.rsc +3 -3
  92. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  93. package/.next/server/app/nodes.html +3 -3
  94. package/.next/server/app/nodes.rsc +16 -16
  95. package/.next/server/app/nodes.segments/_full.segment.rsc +16 -16
  96. package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
  97. package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
  98. package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
  99. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
  100. package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
  101. package/.next/server/app/page_client-reference-manifest.js +1 -1
  102. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  103. package/.next/server/app/server-logs.html +3 -3
  104. package/.next/server/app/server-logs.rsc +16 -16
  105. package/.next/server/app/server-logs.segments/_full.segment.rsc +16 -16
  106. package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
  107. package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
  108. package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
  109. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
  110. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
  111. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  112. package/.next/server/app/settings/networks.html +3 -3
  113. package/.next/server/app/settings/networks.rsc +16 -16
  114. package/.next/server/app/settings/networks.segments/_full.segment.rsc +16 -16
  115. package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
  116. package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
  117. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
  118. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
  119. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
  120. package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
  121. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  122. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  123. package/.next/server/app/settings/tokens.html +3 -3
  124. package/.next/server/app/settings/tokens.rsc +16 -16
  125. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +16 -16
  126. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
  127. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
  128. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
  129. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
  130. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
  131. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
  132. package/.next/server/app/settings.html +3 -3
  133. package/.next/server/app/settings.rsc +16 -16
  134. package/.next/server/app/settings.segments/_full.segment.rsc +16 -16
  135. package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  136. package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
  137. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  138. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  139. package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  140. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  141. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  142. package/.next/server/app/tasks.html +3 -3
  143. package/.next/server/app/tasks.rsc +16 -16
  144. package/.next/server/app/tasks.segments/_full.segment.rsc +16 -16
  145. package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
  146. package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
  147. package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
  148. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
  149. package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
  150. package/.next/server/app-paths-manifest.json +2 -0
  151. package/.next/server/chunks/00jm_next_dist_0ju_ux9._.js +18 -0
  152. package/.next/server/chunks/00jm_next_dist_0ju_ux9._.js.map +1 -0
  153. package/.next/server/chunks/0ykm__next-internal_server_app_api_hub_upload_route_actions_03_eqnf.js +3 -0
  154. package/.next/server/chunks/0ykm__next-internal_server_app_manifest_webmanifest_route_actions_0m16rb8.js +3 -0
  155. package/.next/server/chunks/0ykm__next-internal_server_app_manifest_webmanifest_route_actions_0m16rb8.js.map +1 -0
  156. package/.next/server/chunks/{[externals]__11vad82._.js → [externals]__036g1.i._.js} +2 -2
  157. package/.next/server/chunks/[externals]__036g1.i._.js.map +1 -0
  158. package/.next/server/chunks/[root-of-the-server]__0-8_f0o._.js +3 -0
  159. package/.next/server/chunks/[root-of-the-server]__0-8_f0o._.js.map +1 -0
  160. package/.next/server/chunks/{[root-of-the-server]__08uyvdq._.js → [root-of-the-server]__0jndzts._.js} +2 -2
  161. package/.next/server/chunks/{[root-of-the-server]__08uyvdq._.js.map → [root-of-the-server]__0jndzts._.js.map} +1 -1
  162. package/.next/server/chunks/[root-of-the-server]__0mxw4vb._.js +1 -1
  163. package/.next/server/chunks/[root-of-the-server]__0mxw4vb._.js.map +1 -1
  164. package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js +1 -1
  165. package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js.map +1 -1
  166. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0..ddwm.js +1 -1
  167. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0..ddwm.js.map +1 -1
  168. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_02bxi6j.js +1 -1
  169. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_02bxi6j.js.map +1 -1
  170. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05oassd.js +1 -1
  171. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05oassd.js.map +1 -1
  172. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05vxtby.js +1 -1
  173. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05vxtby.js.map +1 -1
  174. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05~eml4.js +1 -1
  175. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05~eml4.js.map +1 -1
  176. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_-g_q2.js +1 -1
  177. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_-g_q2.js.map +1 -1
  178. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_ec0xu.js +1 -1
  179. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_ec0xu.js.map +1 -1
  180. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0czb6wz.js +1 -1
  181. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0czb6wz.js.map +1 -1
  182. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0e-cn.p.js +1 -1
  183. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0e-cn.p.js.map +1 -1
  184. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0k8_sr8.js +1 -1
  185. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0k8_sr8.js.map +1 -1
  186. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0lt_3bw.js +1 -1
  187. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0lt_3bw.js.map +1 -1
  188. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0uyh3yt.js +1 -1
  189. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0uyh3yt.js.map +1 -1
  190. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0v-a2ps.js +1 -1
  191. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0v-a2ps.js.map +1 -1
  192. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_12.4r9~.js +1 -1
  193. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_12.4r9~.js.map +1 -1
  194. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_13mqkay.js +1 -1
  195. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_13mqkay.js.map +1 -1
  196. package/.next/server/chunks/ssr/[root-of-the-server]__030vg4n._.js +4 -1
  197. package/.next/server/chunks/ssr/[root-of-the-server]__030vg4n._.js.map +1 -1
  198. package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js +1 -1
  199. package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js.map +1 -1
  200. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js +1 -1
  201. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +1 -1
  202. package/.next/server/chunks/ssr/[root-of-the-server]__0u5aqkk._.js +1 -1
  203. package/.next/server/chunks/ssr/[root-of-the-server]__0u5aqkk._.js.map +1 -1
  204. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +4 -4
  205. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
  206. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
  207. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
  208. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
  209. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
  210. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js +1 -1
  211. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js.map +1 -1
  212. package/.next/server/chunks/ssr/agent-network-dashboard_app_tasks_page_tsx_0mwxy4z._.js +1 -1
  213. package/.next/server/chunks/ssr/agent-network-dashboard_app_tasks_page_tsx_0mwxy4z._.js.map +1 -1
  214. package/.next/server/middleware-build-manifest.js +3 -3
  215. package/.next/server/middleware.js +2 -2
  216. package/.next/server/middleware.js.nft.json +1 -1
  217. package/.next/server/pages/404.html +3 -3
  218. package/.next/server/pages/500.html +1 -1
  219. package/.next/static/chunks/{07~8sx3_5uiox.js → 0csnc6nlttr5s.js} +4 -1
  220. package/.next/static/chunks/0grmy4z.ylqtd.css +2 -0
  221. package/.next/static/chunks/0k68tvhf0o-sb.js +1 -0
  222. package/.next/static/chunks/{0v4-5tng.uh.7.js → 0lc4e9o91uv.n.js} +2 -2
  223. package/.next/static/chunks/0prdn66k~zu45.js +1 -0
  224. package/.next/static/chunks/{0ph1in3421~o-.js → 0qvb.hq86qp2g.js} +1 -1
  225. package/.next/static/chunks/0wyjrc0bekhiz.js +1 -0
  226. package/.next/static/chunks/0~ykmap37nw9d.js +1 -0
  227. package/.next/static/chunks/17r9h6cx1w6q-.js +4 -0
  228. package/.next/trace +2 -2
  229. package/.next/trace-build +1 -1
  230. package/.next/types/routes.d.ts +2 -1
  231. package/.next/types/validator.ts +9 -0
  232. package/app/api/hub/send/route.ts +11 -2
  233. package/app/api/hub/servers/route.ts +3 -29
  234. package/app/api/hub/upload/route.ts +83 -0
  235. package/app/components/AppShell.tsx +4 -2
  236. package/app/components/CommandCenter.tsx +1 -1
  237. package/app/components/DispatchPanel.tsx +1 -1
  238. package/app/components/MobileNav.tsx +58 -0
  239. package/app/components/TaskChatPanel.tsx +209 -30
  240. package/app/components/TaskDrawer.tsx +1 -1
  241. package/app/components/TopoGraph.tsx +6686 -248
  242. package/app/globals.css +897 -7
  243. package/app/layout.tsx +8 -2
  244. package/app/lib/serverDedupe.ts +122 -0
  245. package/app/lib/vendorIdentity.ts +74 -56
  246. package/app/manifest.ts +23 -0
  247. package/app/nodes/page.tsx +21 -151
  248. package/package.json +4 -4
  249. package/public/vendors/claude.svg +7 -8
  250. package/public/vendors/minimax.svg +8 -9
  251. package/public/vendors/openai.svg +8 -10
  252. package/scripts/p157-rc2-dedup-test.mjs +110 -0
  253. package/scripts/topo-a11y-titles-catalog-test.mjs +132 -0
  254. package/scripts/topo-active-chrome-hover-text-test.mjs +107 -0
  255. package/scripts/topo-active-links-chip-halo-layers-test.mjs +81 -0
  256. package/scripts/topo-alias-chat-brightness-test.mjs +79 -0
  257. package/scripts/topo-alias-text-halo-layers-test.mjs +98 -0
  258. package/scripts/topo-animation-temporal-modes-catalog-test.mjs +144 -0
  259. package/scripts/topo-avatar-chat-gate-test.mjs +77 -0
  260. package/scripts/topo-avatar-drop-shadow-test.mjs +86 -0
  261. package/scripts/topo-avatar-fallback-hover-test.mjs +104 -0
  262. package/scripts/topo-avatar-fallback-rotate-test.mjs +92 -0
  263. package/scripts/topo-avatar-rotate-test.mjs +85 -0
  264. package/scripts/topo-avatar-scale-test.mjs +89 -0
  265. package/scripts/topo-badge-chat-gate-test.mjs +74 -0
  266. package/scripts/topo-brand-drop-shadow-test.mjs +71 -0
  267. package/scripts/topo-brand-logo-breath-test.mjs +102 -0
  268. package/scripts/topo-brand-logo-halo-layers-test.mjs +85 -0
  269. package/scripts/topo-brand-logo-hover-brightness-test.mjs +105 -0
  270. package/scripts/topo-brand-logo-hover-rotate-test.mjs +93 -0
  271. package/scripts/topo-brand-logo-hover-test.mjs +85 -0
  272. package/scripts/topo-canvas-desc-a11y-test.mjs +87 -0
  273. package/scripts/topo-canvas-entrance-animation-test.mjs +117 -0
  274. package/scripts/topo-canvas-scan-beam-diagonal-test.mjs +148 -0
  275. package/scripts/topo-canvas-scan-beam-test.mjs +109 -0
  276. package/scripts/topo-canvas-scan-beam-vertical-test.mjs +123 -0
  277. package/scripts/topo-card-chat-brightness-test.mjs +86 -0
  278. package/scripts/topo-chat-ring-breath-curve-test.mjs +114 -0
  279. package/scripts/topo-chat-ring-brightness-test.mjs +80 -0
  280. package/scripts/topo-chat-ring-halo-layers-test.mjs +100 -0
  281. package/scripts/topo-chat-ring-r-breath-test.mjs +121 -0
  282. package/scripts/topo-chat-ring-status-halo-test.mjs +106 -0
  283. package/scripts/topo-chat-ring-sw-breath-test.mjs +123 -0
  284. package/scripts/topo-chip-pin-halo-test.mjs +85 -0
  285. package/scripts/topo-chip-row-digit-ls-test.mjs +135 -0
  286. package/scripts/topo-chip-row-member-alias-lit-test.mjs +154 -0
  287. package/scripts/topo-chip-row-tier-glow-brightness-test.mjs +99 -0
  288. package/scripts/topo-chip-row-unit-hover-tracking-test.mjs +124 -0
  289. package/scripts/topo-chrome-control-halo-layers-test.mjs +22 -0
  290. package/scripts/topo-chrome-fullscreen-breath-test.mjs +121 -0
  291. package/scripts/topo-chrome-layout-trailer-breath-test.mjs +86 -0
  292. package/scripts/topo-chrome-nodesize-trailer-breath-test.mjs +86 -0
  293. package/scripts/topo-chrome-reset-breath-test.mjs +115 -0
  294. package/scripts/topo-chrome-strip-entrance-animation-test.mjs +115 -0
  295. package/scripts/topo-chrome-wrapper-halo-test.mjs +83 -0
  296. package/scripts/topo-chrome-zoom-wrapper-breath-test.mjs +85 -0
  297. package/scripts/topo-click-ripple-glow-test.mjs +86 -0
  298. package/scripts/topo-click-ripple-halo-layers-test.mjs +79 -0
  299. package/scripts/topo-click-ripple-sw-test.mjs +110 -0
  300. package/scripts/topo-cluster-count-attr-test.mjs +80 -0
  301. package/scripts/topo-crescent-breath-test.mjs +104 -0
  302. package/scripts/topo-crescent-envelope-breath-test.mjs +103 -0
  303. package/scripts/topo-crescent-recede-test.mjs +111 -0
  304. package/scripts/topo-dense-alias-chat-halo-test.mjs +73 -0
  305. package/scripts/topo-dense-alias-halo-layers-test.mjs +80 -0
  306. package/scripts/topo-dual-axis-surfaces-catalog-test.mjs +94 -0
  307. package/scripts/topo-edge-badge-circle-brightness-test.mjs +82 -0
  308. package/scripts/topo-edge-badge-circle-hot-pulse-test.mjs +100 -0
  309. package/scripts/topo-edge-badge-digit-halo-layers-test.mjs +107 -0
  310. package/scripts/topo-edge-badge-endpoint-gate-test.mjs +94 -0
  311. package/scripts/topo-edge-badge-halo-layers-test.mjs +85 -0
  312. package/scripts/topo-edge-badge-hot-pulse-test.mjs +92 -0
  313. package/scripts/topo-edge-badge-hover-glow-test.mjs +90 -0
  314. package/scripts/topo-edge-badge-text-brightness-test.mjs +83 -0
  315. package/scripts/topo-edge-chat-gate-test.mjs +71 -0
  316. package/scripts/topo-edge-flow-rail-halo-layers-test.mjs +89 -0
  317. package/scripts/topo-edge-particle-brightness-test.mjs +82 -0
  318. package/scripts/topo-edge-particle-halo-layers-test.mjs +91 -0
  319. package/scripts/topo-edge-pill-glow-test.mjs +67 -0
  320. package/scripts/topo-edge-pin-halo-test.mjs +99 -0
  321. package/scripts/topo-edge-visible-brightness-test.mjs +84 -0
  322. package/scripts/topo-edge-visible-halo-layers-test.mjs +87 -0
  323. package/scripts/topo-endpoint-ring-brightness-test.mjs +83 -0
  324. package/scripts/topo-endpoint-ring-flow-halo-test.mjs +107 -0
  325. package/scripts/topo-endpoint-ring-halo-layers-test.mjs +100 -0
  326. package/scripts/topo-filter-pill-glow-test.mjs +90 -0
  327. package/scripts/topo-filter-pill-halo-layers-test.mjs +27 -0
  328. package/scripts/topo-flow-arrow-brightness-test.mjs +82 -0
  329. package/scripts/topo-flow-rail-brightness-test.mjs +80 -0
  330. package/scripts/topo-fullscreen-attr-test.mjs +73 -0
  331. package/scripts/topo-fullscreen-brightness-test.mjs +84 -0
  332. package/scripts/topo-fullscreen-icon-rotate-test.mjs +93 -0
  333. package/scripts/topo-grid-content-bottom-attr-test.mjs +72 -0
  334. package/scripts/topo-group-box-brightness-test.mjs +84 -0
  335. package/scripts/topo-group-box-halo-layers-test.mjs +91 -0
  336. package/scripts/topo-group-chat-gate-test.mjs +77 -0
  337. package/scripts/topo-group-label-brightness-test.mjs +84 -0
  338. package/scripts/topo-group-label-halo-layers-test.mjs +78 -0
  339. package/scripts/topo-group-label-hover-glow-test.mjs +86 -0
  340. package/scripts/topo-group-label-member-alias-hover-test.mjs +125 -0
  341. package/scripts/topo-group-pill-glow-test.mjs +76 -0
  342. package/scripts/topo-group-tint-brightness-test.mjs +82 -0
  343. package/scripts/topo-h2-dual-axis-breath-test.mjs +92 -0
  344. package/scripts/topo-h2-triple-axis-breath-test.mjs +142 -0
  345. package/scripts/topo-halo-chat-gate-test.mjs +72 -0
  346. package/scripts/topo-hover-detail-halo-test.mjs +76 -0
  347. package/scripts/topo-hub-a11y-title-test.mjs +95 -0
  348. package/scripts/topo-hub-core-brightness-test.mjs +82 -0
  349. package/scripts/topo-hub-core-halo-layers-test.mjs +81 -0
  350. package/scripts/topo-hub-digit-brightness-test.mjs +79 -0
  351. package/scripts/topo-hub-digit-halo-layers-test.mjs +76 -0
  352. package/scripts/topo-hub-digit-ls-test.mjs +119 -0
  353. package/scripts/topo-hub-halo-brightness-test.mjs +80 -0
  354. package/scripts/topo-hub-halo-glow-test.mjs +96 -0
  355. package/scripts/topo-hub-halo-halo-layers-test.mjs +76 -0
  356. package/scripts/topo-hub-highlight-brightness-test.mjs +84 -0
  357. package/scripts/topo-hub-highlight-glow-test.mjs +99 -0
  358. package/scripts/topo-hub-highlight-halo-layers-test.mjs +78 -0
  359. package/scripts/topo-hub-highlight-r-test.mjs +112 -0
  360. package/scripts/topo-hub-hover-ring-brightness-test.mjs +79 -0
  361. package/scripts/topo-hub-hover-ring-glow-test.mjs +97 -0
  362. package/scripts/topo-hub-hover-ring-halo-layers-test.mjs +71 -0
  363. package/scripts/topo-hub-spoke-brightness-test.mjs +77 -0
  364. package/scripts/topo-hub-spoke-glow-test.mjs +112 -0
  365. package/scripts/topo-hub-spoke-halo-layers-test.mjs +97 -0
  366. package/scripts/topo-hub-spoke-self-filter-test.mjs +119 -0
  367. package/scripts/topo-kicker-breath-test.mjs +100 -0
  368. package/scripts/topo-kicker-dual-axis-breath-test.mjs +81 -0
  369. package/scripts/topo-kicker-halo-layers-test.mjs +82 -0
  370. package/scripts/topo-kicker-triple-axis-breath-test.mjs +124 -0
  371. package/scripts/topo-label-card-brightness-test.mjs +81 -0
  372. package/scripts/topo-layout-hover-fw-test.mjs +98 -0
  373. package/scripts/topo-layout-toggle-brightness-test.mjs +94 -0
  374. package/scripts/topo-layout-toggle-halo-layers-test.mjs +95 -0
  375. package/scripts/topo-legend-count-brightness-test.mjs +80 -0
  376. package/scripts/topo-legend-count-halo-layers-test.mjs +79 -0
  377. package/scripts/topo-legend-count-letter-spacing-test.mjs +108 -0
  378. package/scripts/topo-legend-label-fw-test.mjs +107 -0
  379. package/scripts/topo-legend-panel-title-breath-test.mjs +86 -0
  380. package/scripts/topo-legend-pin-ring-brightness-test.mjs +82 -0
  381. package/scripts/topo-legend-pin-ring-halo-layers-test.mjs +71 -0
  382. package/scripts/topo-legend-row-count-brightness-test.mjs +85 -0
  383. package/scripts/topo-legend-row-label-glow-test.mjs +102 -0
  384. package/scripts/topo-legend-swatch-glow-test.mjs +109 -0
  385. package/scripts/topo-legend-swatch-member-alias-match-test.mjs +139 -0
  386. package/scripts/topo-legend-tint-brightness-test.mjs +83 -0
  387. package/scripts/topo-legend-trio-halo-layers-test.mjs +22 -0
  388. package/scripts/topo-live-lanes.mjs +48 -0
  389. package/scripts/topo-minimap-container-halo-test.mjs +82 -0
  390. package/scripts/topo-minimap-dot-chat-gate-test.mjs +81 -0
  391. package/scripts/topo-minimap-hover-glow-test.mjs +109 -0
  392. package/scripts/topo-minimap-viewport-brightness-test.mjs +84 -0
  393. package/scripts/topo-minimap-viewport-halo-layers-test.mjs +24 -0
  394. package/scripts/topo-more-footer-brightness-test.mjs +94 -0
  395. package/scripts/topo-node-alias-brightness-test.mjs +84 -0
  396. package/scripts/topo-node-avatar-halo-layers-test.mjs +25 -0
  397. package/scripts/topo-node-hover-ring-halo-layers-test.mjs +70 -0
  398. package/scripts/topo-node-label-card-halo-test.mjs +76 -0
  399. package/scripts/topo-node-sub-text-brightness-test.mjs +88 -0
  400. package/scripts/topo-nodesize-brightness-test.mjs +82 -0
  401. package/scripts/topo-nodesize-halo-layers-test.mjs +89 -0
  402. package/scripts/topo-nodesize-hover-fw-test.mjs +99 -0
  403. package/scripts/topo-orphan-label-opacity-test.mjs +98 -0
  404. package/scripts/topo-overlap-test.mjs +22 -8
  405. package/scripts/topo-panel-count-halo-layers-test.mjs +91 -0
  406. package/scripts/topo-panel-count-hover-ls-test.mjs +87 -0
  407. package/scripts/topo-panel-rect-halo-test.mjs +90 -0
  408. package/scripts/topo-panel-row-brightness-test.mjs +116 -0
  409. package/scripts/topo-panel-title-brightness-test.mjs +98 -0
  410. package/scripts/topo-panel-title-glow-test.mjs +111 -0
  411. package/scripts/topo-panel-titles-dual-axis-breath-test.mjs +94 -0
  412. package/scripts/topo-panel-titles-halo-layers-test.mjs +23 -0
  413. package/scripts/topo-panel-titles-triple-axis-breath-test.mjs +161 -0
  414. package/scripts/topo-pill-x-rotate-test.mjs +96 -0
  415. package/scripts/topo-pip-brightness-test.mjs +85 -0
  416. package/scripts/topo-pressure-bar-halo-layers-test.mjs +19 -0
  417. package/scripts/topo-pressure-seg-glow-test.mjs +92 -0
  418. package/scripts/topo-pressure-seg-member-alias-match-test.mjs +133 -0
  419. package/scripts/topo-pressure-seg-motion-test.mjs +101 -0
  420. package/scripts/topo-r717-scan-beam-pair-pattern-test.mjs +100 -0
  421. package/scripts/topo-r717-triple-axis-pair-pattern-test.mjs +113 -0
  422. package/scripts/topo-r717-triple-axis-tier-pattern-test.mjs +117 -0
  423. package/scripts/topo-recent-count-brightness-test.mjs +84 -0
  424. package/scripts/topo-recent-more-fw-test.mjs +126 -0
  425. package/scripts/topo-recent-more-halo-layers-test.mjs +90 -0
  426. package/scripts/topo-recent-panel-hot-pulse-test.mjs +105 -0
  427. package/scripts/topo-recent-panel-title-breath-test.mjs +91 -0
  428. package/scripts/topo-recent-pip-halo-layers-test.mjs +82 -0
  429. package/scripts/topo-recent-row-chat-gate-test.mjs +75 -0
  430. package/scripts/topo-recent-row-content-lift-test.mjs +140 -0
  431. package/scripts/topo-recent-row-fw-test.mjs +115 -0
  432. package/scripts/topo-recent-row-text-glow-test.mjs +86 -0
  433. package/scripts/topo-recent-row-text-halo-layers-test.mjs +67 -0
  434. package/scripts/topo-recent-tint-brightness-test.mjs +80 -0
  435. package/scripts/topo-recent-ts-brightness-test.mjs +86 -0
  436. package/scripts/topo-reduced-motion-attr-test.mjs +69 -0
  437. package/scripts/topo-reset-brightness-test.mjs +83 -0
  438. package/scripts/topo-reset-icon-hover-scale-test.mjs +102 -0
  439. package/scripts/topo-respiratory-axis-count-stats-test.mjs +154 -0
  440. package/scripts/topo-respiratory-patterns-catalog-test.mjs +112 -0
  441. package/scripts/topo-respiratory-rolodex-test.mjs +83 -0
  442. package/scripts/topo-respiratory-tiers-catalog-test.mjs +119 -0
  443. package/scripts/topo-respiratory-triple-axis-surfaces-catalog-test.mjs +127 -0
  444. package/scripts/topo-runtime-badge-brightness-test.mjs +78 -0
  445. package/scripts/topo-runtime-badge-glow-test.mjs +108 -0
  446. package/scripts/topo-runtime-badge-halo-layers-test.mjs +87 -0
  447. package/scripts/topo-runtime-badge-rotate-test.mjs +85 -0
  448. package/scripts/topo-section-title-breath-test.mjs +83 -0
  449. package/scripts/topo-section-title-halo-layers-test.mjs +88 -0
  450. package/scripts/topo-spoke-chat-gate-test.mjs +72 -0
  451. package/scripts/topo-starfield-hue-test.mjs +109 -0
  452. package/scripts/topo-status-pin-pill-halo-layers-test.mjs +17 -0
  453. package/scripts/topo-status-ring-brightness-test.mjs +84 -0
  454. package/scripts/topo-status-ring-chat-gate-test.mjs +72 -0
  455. package/scripts/topo-status-ring-halo-layers-test.mjs +105 -0
  456. package/scripts/topo-status-ring-status-halo-test.mjs +110 -0
  457. package/scripts/topo-sub-text-chat-brightness-test.mjs +81 -0
  458. package/scripts/topo-svg-title-a11y-r731-test.mjs +93 -0
  459. package/scripts/topo-svg-title-a11y-test.mjs +88 -0
  460. package/scripts/topo-title-block-entrance-animation-test.mjs +127 -0
  461. package/scripts/topo-title-block-envelope-breath-test.mjs +87 -0
  462. package/scripts/topo-titleblock-h2-hover-fw-test.mjs +109 -0
  463. package/scripts/topo-titleblock-h2-hover-tracking-test.mjs +128 -0
  464. package/scripts/topo-titleblock-kicker-hover-test.mjs +134 -0
  465. package/scripts/topo-tree-diag.mjs +95 -0
  466. package/scripts/topo-vendor-chip-glow-test.mjs +97 -0
  467. package/scripts/topo-vendor-chip-halo-layers-test.mjs +18 -0
  468. package/scripts/topo-vendor-chip-pin-halo-test.mjs +88 -0
  469. package/scripts/topo-vendor-count-suffix-halo-layers-test.mjs +79 -0
  470. package/scripts/topo-vendor-distribution-wrapper-halo-test.mjs +93 -0
  471. package/scripts/topo-vendor-letter-halo-layers-test.mjs +93 -0
  472. package/scripts/topo-vendor-pill-glow-test.mjs +98 -0
  473. package/scripts/topo-watermark-breath-test.mjs +100 -0
  474. package/scripts/topo-watermark-dual-axis-breath-test.mjs +88 -0
  475. package/scripts/topo-watermark-envelope-breath-test.mjs +88 -0
  476. package/scripts/topo-watermark-recede-test.mjs +114 -0
  477. package/scripts/topo-watermark-triple-axis-breath-test.mjs +129 -0
  478. package/scripts/topo-working-online-chip-halo-layers-test.mjs +94 -0
  479. package/scripts/topo-zoom-buttons-brightness-test.mjs +94 -0
  480. package/scripts/topo-zoom-in-out-halo-layers-test.mjs +97 -0
  481. package/scripts/topo-zoom-level-breath-test.mjs +87 -0
  482. package/scripts/topo-zoom-level-brightness-test.mjs +83 -0
  483. package/scripts/topo-zoom-level-color-test.mjs +105 -0
  484. package/scripts/topo-zoom-level-dual-axis-breath-test.mjs +83 -0
  485. package/scripts/topo-zoom-level-halo-layers-test.mjs +78 -0
  486. package/scripts/topo-zoom-level-triple-axis-breath-test.mjs +148 -0
  487. package/.next/static/chunks/01lmbsd37fybu.js +0 -1
  488. package/.next/static/chunks/03o.h6kvmw4l_.js +0 -1
  489. package/.next/static/chunks/0fuba20p57-zo.js +0 -1
  490. package/.next/static/chunks/0m.1mvl~t.avc.css +0 -2
  491. package/.next/static/chunks/10cj-86disers.js +0 -1
  492. package/.next/static/chunks/158h2g7f-nxbt.js +0 -4
  493. /package/.next/server/chunks/{[externals]__11vad82._.js.map → 0ykm__next-internal_server_app_api_hub_upload_route_actions_03_eqnf.js.map} +0 -0
  494. /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → 7CjN6e7QM2eogH8RhsM1k}/_buildManifest.js +0 -0
  495. /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → 7CjN6e7QM2eogH8RhsM1k}/_clientMiddlewareManifest.js +0 -0
  496. /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → 7CjN6e7QM2eogH8RhsM1k}/_ssgManifest.js +0 -0
@@ -0,0 +1,85 @@
1
+ /* Round 548 verification: title-block brand logo gains hover:scale-105
2
+ * delight gesture. Banked R547 Tailwind 4 pattern — probe cs.scale not
3
+ * cs.transform.
4
+ *
5
+ * Test phases:
6
+ * 1. rest: scale='none'
7
+ * 2. hover: scale='1.05'
8
+ * 3. source-side regex confirms className + data-attr wired
9
+ */
10
+ import { chromium } from 'playwright';
11
+ import { readFileSync } from 'node:fs';
12
+
13
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
14
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
15
+
16
+ const browser = await chromium.launch({ headless: true });
17
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
18
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
19
+ await ctx.addInitScript(() => {
20
+ try {
21
+ localStorage.setItem('anet-theme', 'cyber');
22
+ localStorage.setItem('anet-topo-layout', 'ring');
23
+ sessionStorage.setItem('anet_v3_auth', '1');
24
+ } catch {}
25
+ });
26
+ await ctx.route('**/api/hub/status*', async (route) => {
27
+ const r = await route.fetch();
28
+ const b = await r.json();
29
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
30
+ const mk = (alias) => ({
31
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
32
+ network_id: nid, project_dir: null,
33
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
34
+ });
35
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1')] } });
36
+ });
37
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
38
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
39
+ const page = await ctx.newPage();
40
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
41
+ await page.waitForSelector('[data-topo-brand-logo]', { timeout: 15000 });
42
+ await page.waitForTimeout(500);
43
+
44
+ const sel = '[data-topo-brand-logo]';
45
+ const rest = await page.evaluate((s) => {
46
+ const el = document.querySelector(s);
47
+ if (!el) return null;
48
+ const cs = getComputedStyle(el);
49
+ return {
50
+ attrScale: el.getAttribute('data-topo-brand-logo-hover-scale'),
51
+ scale: cs.scale,
52
+ rotate: cs.rotate,
53
+ };
54
+ }, sel);
55
+
56
+ await page.hover(sel);
57
+ await page.waitForTimeout(400);
58
+ const hover = await page.evaluate((s) => {
59
+ const el = document.querySelector(s);
60
+ if (!el) return null;
61
+ const cs = getComputedStyle(el);
62
+ return { scale: cs.scale };
63
+ }, sel);
64
+
65
+ await browser.close();
66
+
67
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
68
+ const sourceClassNameWired =
69
+ /className="shrink-0 transition-transform duration-200 ease-out hover:scale-105 transform-gpu"/.test(src);
70
+ const sourceAttrWired =
71
+ /data-topo-brand-logo-hover-scale="1\.05"/.test(src);
72
+
73
+ const results = {
74
+ rest_scale_none: rest?.scale === 'none' || rest?.scale === '1',
75
+ rest_attr_scale_105: rest?.attrScale === '1.05',
76
+ hover_scale_105: hover?.scale === '1.05',
77
+ source_classname: sourceClassNameWired,
78
+ source_attr: sourceAttrWired,
79
+ };
80
+ const ok = Object.values(results).every(Boolean);
81
+ console.log(`${ok ? '✅' : '❌'} R548 brand-logo hover-scale:`,
82
+ JSON.stringify(results, null, 2),
83
+ '\n rest:', JSON.stringify(rest),
84
+ '\n hover:', JSON.stringify(hover));
85
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,87 @@
1
+ /* Round 734 — SVG <desc> stable structural description on root canvas
2
+ * + aria-describedby linkage. Different a11y mechanism from R730-R733:
3
+ * R730-R733 add <title> children as accessible NAMES on individual
4
+ * decorative elements (watermark, brand logo, hub, etc.)
5
+ * R734 adds <desc> as a stable DESCRIPTION on the canvas root,
6
+ * complementing the existing dynamic aria-label (R7/R469).
7
+ *
8
+ * WAI-ARIA name + description pair: SR announces the accessible name
9
+ * (label) first, then optionally reads the description on follow-up.
10
+ *
11
+ * Assertions:
12
+ * - Root <svg> has aria-describedby="anet-topo-canvas-desc"
13
+ * - <desc id="anet-topo-canvas-desc"> exists as a child of root <svg>
14
+ * - desc content mentions key structural surfaces: hub, ring/grid,
15
+ * recent-signal, legend, chrome strip
16
+ * - desc content mentions key interactions: Tab, double-click, l-key
17
+ * - aria-label (R7/R469 dynamic) still present and not replaced
18
+ * - aria-roledescription (R-original) still present
19
+ */
20
+ import { chromium } from 'playwright';
21
+ import { readFileSync } from 'node:fs';
22
+
23
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
24
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
25
+
26
+ const browser = await chromium.launch({ headless: true });
27
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
28
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
29
+ await ctx.addInitScript(() => {
30
+ try {
31
+ localStorage.setItem('anet-theme', 'cyber');
32
+ localStorage.setItem('anet-topo-layout', 'ring');
33
+ sessionStorage.setItem('anet_v3_auth', '1');
34
+ } catch {}
35
+ });
36
+ await ctx.route('**/api/hub/status*', async (route) => {
37
+ const r = await route.fetch();
38
+ const b = await r.json();
39
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
40
+ const mk = (alias) => ({
41
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
42
+ network_id: nid, project_dir: null,
43
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
44
+ });
45
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
46
+ });
47
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
48
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
49
+ const page = await ctx.newPage();
50
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
51
+ await page.waitForSelector('[data-topo-canvas-aria]', { timeout: 15000, state: 'attached' });
52
+ await page.waitForTimeout(300);
53
+
54
+ const state = await page.evaluate(() => {
55
+ const svg = document.querySelector('[data-topo-canvas-aria]');
56
+ const desc = document.getElementById('anet-topo-canvas-desc');
57
+ return {
58
+ aria_describedby: svg?.getAttribute('aria-describedby') ?? null,
59
+ aria_label: svg?.getAttribute('aria-label') ?? null,
60
+ aria_roledescr: svg?.getAttribute('aria-roledescription') ?? null,
61
+ desc_present: !!desc,
62
+ desc_text: desc?.textContent ?? null,
63
+ desc_is_child_of_svg: desc?.parentElement === svg,
64
+ };
65
+ });
66
+
67
+ await browser.close();
68
+
69
+ const text = state.desc_text ?? '';
70
+ const textLower = text.toLowerCase();
71
+ const mentionsStructural = ['hub', 'ring', 'grid', 'recent-signal', 'legend', 'chrome strip'].every(k => textLower.includes(k));
72
+ const mentionsInteractions = ['Tab', 'double-click', 'l '].every(k => text.includes(k));
73
+
74
+ const results = {
75
+ aria_describedby_correct: state.aria_describedby === 'anet-topo-canvas-desc',
76
+ desc_element_present: state.desc_present === true,
77
+ desc_is_direct_child: state.desc_is_child_of_svg === true,
78
+ desc_mentions_structural: mentionsStructural,
79
+ desc_mentions_interactions: mentionsInteractions,
80
+ aria_label_preserved: typeof state.aria_label === 'string' && state.aria_label.includes('Agent network topology'),
81
+ aria_roledescription_kept: state.aria_roledescr === 'agent network topology',
82
+ };
83
+ const ok = Object.values(results).every(Boolean);
84
+ console.log(`${ok ? '✅' : '❌'} R734 SVG <desc> + aria-describedby on root canvas (WAI-ARIA name + description pair):`,
85
+ JSON.stringify(results, null, 2),
86
+ `\n state: ${JSON.stringify(state)}`);
87
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,117 @@
1
+ /* Round 740 — one-time canvas entrance animation. Plays on first
2
+ * paint, then the canvas sits at scale(1) opacity(1) for the rest of
3
+ * the session. Distinct from breath (infinite rest-axis) and ambient
4
+ * (infinite sweep-axis) — R740 is ONE-SHOT.
5
+ *
6
+ * Assertions:
7
+ * - .anet-topo-canvas-entrance class on root <svg> (reducedMotion off)
8
+ * - data-topo-canvas-entrance="true" attribute
9
+ * - CSS @keyframes 0% scale(0.99) opacity 0.8 → 100% scale(1) opacity 1
10
+ * - .anet-topo-canvas-entrance binds 600ms ease-out animation
11
+ * - CSS animation NOT infinite (no `infinite` keyword) — one-shot
12
+ * - transform-origin: 50% 50%
13
+ * - prefers-reduced-motion guard present
14
+ * - Animation completes within ~1s (test waits 1.2s after mount,
15
+ * then verifies computed transform is identity matrix)
16
+ * - Existing canvas className tokens (w-full h-auto block) preserved
17
+ */
18
+ import { chromium } from 'playwright';
19
+ import { readFileSync } from 'node:fs';
20
+
21
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
22
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
23
+
24
+ const browser = await chromium.launch({ headless: true });
25
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
26
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
27
+ await ctx.addInitScript(() => {
28
+ try {
29
+ localStorage.setItem('anet-theme', 'cyber');
30
+ localStorage.setItem('anet-topo-layout', 'ring');
31
+ sessionStorage.setItem('anet_v3_auth', '1');
32
+ } catch {}
33
+ });
34
+ await ctx.route('**/api/hub/status*', async (route) => {
35
+ const r = await route.fetch();
36
+ const b = await r.json();
37
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
38
+ const mk = (alias) => ({
39
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
40
+ network_id: nid, project_dir: null,
41
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
42
+ });
43
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
44
+ });
45
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
46
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
47
+ const page = await ctx.newPage();
48
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
49
+ await page.waitForSelector('[data-topo-canvas-aria]', { timeout: 15000, state: 'attached' });
50
+
51
+ /* Wait past the 600ms animation duration so computed transform settles
52
+ * to the final state (scale(1)). */
53
+ await page.waitForTimeout(1200);
54
+
55
+ const state = await page.evaluate(() => {
56
+ const svg = document.querySelector('[data-topo-canvas-aria]');
57
+ if (!svg) return null;
58
+ const cs = getComputedStyle(svg);
59
+ return {
60
+ has_entrance_class: svg.classList.contains('anet-topo-canvas-entrance'),
61
+ entrance_attr: svg.getAttribute('data-topo-canvas-entrance'),
62
+ class_attr: svg.getAttribute('class'),
63
+ anim_name: cs.animationName,
64
+ anim_duration: cs.animationDuration,
65
+ anim_iteration: cs.animationIterationCount,
66
+ transform_origin: cs.transformOrigin,
67
+ computed_transform: cs.transform,
68
+ computed_opacity: cs.opacity,
69
+ };
70
+ });
71
+
72
+ await browser.close();
73
+
74
+ const cssSrc = readFileSync('/home/vansin/agent-network-dashboard/app/globals.css', 'utf8');
75
+ const cssKfStart = /@keyframes anet-topo-canvas-entrance-kf\s*\{[\s\S]*?0%\s*\{[\s\S]*?transform:\s*scale\(0\.99\)[\s\S]*?opacity:\s*0\.8/.test(cssSrc);
76
+ const cssKfEnd = /@keyframes anet-topo-canvas-entrance-kf\s*\{[\s\S]*?100%\s*\{[\s\S]*?transform:\s*scale\(1\)[\s\S]*?opacity:\s*1/.test(cssSrc);
77
+ const cssClassBound = /\.anet-topo-canvas-entrance\s*\{[\s\S]*?animation:\s*anet-topo-canvas-entrance-kf\s+600ms\s+ease-out/.test(cssSrc);
78
+ /* The CSS source regex was too broad (matched `infinite` in OTHER
79
+ * class blocks past this one). Verify one-shot directly via the
80
+ * runtime computed animation-iteration-count — this is the property
81
+ * that actually determines whether the animation replays. */
82
+ const runtimeOneShot = state?.anim_iteration === '1';
83
+ const cssTransformOrigin = /\.anet-topo-canvas-entrance\s*\{[\s\S]*?transform-origin:\s*50%\s+50%/.test(cssSrc);
84
+ const cssReducedMotion = /@media\s*\(prefers-reduced-motion:\s*reduce\)\s*\{[\s\S]*?\.anet-topo-canvas-entrance\s*\{\s*animation:\s*none/.test(cssSrc);
85
+
86
+ /* After 1.2s the animation should have completed; computed transform
87
+ * should be identity-matrix (scale 1). matrix(1, 0, 0, 1, 0, 0) === 'none'
88
+ * in some browsers; accept either. */
89
+ const transformSettled = state?.computed_transform === 'none'
90
+ || state?.computed_transform === 'matrix(1, 0, 0, 1, 0, 0)';
91
+
92
+ const opacitySettled = parseFloat(state?.computed_opacity ?? '0') > 0.99;
93
+
94
+ const classKept = typeof state?.class_attr === 'string'
95
+ && state.class_attr.includes('w-full')
96
+ && state.class_attr.includes('h-auto')
97
+ && state.class_attr.includes('block')
98
+ && state.class_attr.includes('anet-topo-canvas-entrance');
99
+
100
+ const results = {
101
+ has_entrance_class: state?.has_entrance_class === true,
102
+ entrance_attr_true: state?.entrance_attr === 'true',
103
+ original_classes_preserved: classKept,
104
+ css_keyframe_start: cssKfStart,
105
+ css_keyframe_end: cssKfEnd,
106
+ css_class_binds_600ms_ease_out: cssClassBound,
107
+ runtime_animation_one_shot: runtimeOneShot,
108
+ css_transform_origin_center: cssTransformOrigin,
109
+ css_reduced_motion_guard: cssReducedMotion,
110
+ transform_settled_to_identity: transformSettled,
111
+ opacity_settled_to_1: opacitySettled,
112
+ };
113
+ const ok = Object.values(results).every(Boolean);
114
+ console.log(`${ok ? '✅' : '❌'} R740 one-time canvas entrance animation (scale 0.99→1 + opacity 0.8→1 @ 600ms ease-out, one-shot):`,
115
+ JSON.stringify(results, null, 2),
116
+ `\n state: ${JSON.stringify(state)}`);
117
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,148 @@
1
+ /* Round 739 — diagonal scan beam (3rd member of ambient scan beam
2
+ * family). Completes the trio from pair:
3
+ * R735 horizontal beam 30 s (top → bottom)
4
+ * R736 vertical beam 23 s (left → right)
5
+ * R739 diagonal beam 19 s (NW → SE) ← this round
6
+ *
7
+ * Coprime invariants:
8
+ * gcd(19, 23) = 1
9
+ * gcd(19, 30) = 1
10
+ * gcd(23, 30) = 1
11
+ * → 3 cadences pairwise coprime → never phase-lock as a trio.
12
+ *
13
+ * Assertions:
14
+ * - <line data-topo-canvas-scan-beam-diagonal> exists with 4 SMIL
15
+ * <animate> children on x1/y1/x2/y2 (all 19s, all repeatCount=indefinite)
16
+ * - opacity animate 0 → 0.06 → 0 at keyTimes 0/0.05/0.95/1, dur 19s
17
+ * - SVG <title>: "canvas scan beam diagonal · ambient sweep · 19s cycle"
18
+ * - data-topo-canvas-scan-beam-diagonal-active="true"
19
+ * - diagonal beam in background layer (rendered before nodes)
20
+ * - diagonal beam rendered AFTER vertical beam (trio document order)
21
+ * - all 3 beams alive (R735 + R736 regressions)
22
+ * - all 3 cadences pairwise coprime (Euclid check)
23
+ * - R717 patterns has 10 entries (was 9)
24
+ * - R717 includes new `scan-beam-trio` with shape "coprime-trio"
25
+ * and cadences [19, 23, 30]
26
+ * - R729 stats: patterns_count 10, ambient_patterns 2, ambient_cadences 3
27
+ * - R732 a11y catalog: 9 entries incl. diagonal beam
28
+ */
29
+ import { chromium } from 'playwright';
30
+ import { readFileSync } from 'node:fs';
31
+
32
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
33
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
34
+
35
+ const browser = await chromium.launch({ headless: true });
36
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
37
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
38
+ await ctx.addInitScript(() => {
39
+ try {
40
+ localStorage.setItem('anet-theme', 'cyber');
41
+ localStorage.setItem('anet-topo-layout', 'ring');
42
+ sessionStorage.setItem('anet_v3_auth', '1');
43
+ } catch {}
44
+ });
45
+ await ctx.route('**/api/hub/status*', async (route) => {
46
+ const r = await route.fetch();
47
+ const b = await r.json();
48
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
49
+ const mk = (alias) => ({
50
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
51
+ network_id: nid, project_dir: null,
52
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
53
+ });
54
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
55
+ });
56
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
57
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
58
+ const page = await ctx.newPage();
59
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
60
+ await page.waitForSelector('[data-topo-canvas-scan-beam-diagonal]', { timeout: 15000, state: 'attached' });
61
+ await page.waitForTimeout(300);
62
+
63
+ const state = await page.evaluate(() => {
64
+ const dbeam = document.querySelector('[data-topo-canvas-scan-beam-diagonal]');
65
+ const vbeam = document.querySelector('[data-topo-canvas-scan-beam-vertical]');
66
+ const hbeam = document.querySelector('[data-topo-canvas-scan-beam]');
67
+ if (!dbeam) return null;
68
+ const getAnim = (el, attr) => el?.querySelector(`animate[attributeName="${attr}"]`);
69
+ const x1A = getAnim(dbeam, 'x1');
70
+ const y1A = getAnim(dbeam, 'y1');
71
+ const x2A = getAnim(dbeam, 'x2');
72
+ const y2A = getAnim(dbeam, 'y2');
73
+ const opA = getAnim(dbeam, 'opacity');
74
+ const dtitle = dbeam.querySelector(':scope > title');
75
+ const svg = document.querySelector('[data-topo-canvas-aria]');
76
+ const firstNode = svg?.querySelector('g[data-node]');
77
+ const dbeamBeforeNodes = dbeam && firstNode
78
+ ? (dbeam.compareDocumentPosition(firstNode) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0
79
+ : null;
80
+ const dbeamAfterVbeam = vbeam && dbeam
81
+ ? (vbeam.compareDocumentPosition(dbeam) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0
82
+ : null;
83
+ return {
84
+ dbeam_present: !!dbeam,
85
+ dbeam_active_attr: dbeam?.getAttribute('data-topo-canvas-scan-beam-diagonal-active') ?? null,
86
+ x1_dur: x1A?.getAttribute('dur'), x1_vals: x1A?.getAttribute('values'),
87
+ y1_dur: y1A?.getAttribute('dur'), y1_vals: y1A?.getAttribute('values'),
88
+ x2_dur: x2A?.getAttribute('dur'), x2_vals: x2A?.getAttribute('values'),
89
+ y2_dur: y2A?.getAttribute('dur'), y2_vals: y2A?.getAttribute('values'),
90
+ op_dur: opA?.getAttribute('dur'), op_vals: opA?.getAttribute('values'), op_kt: opA?.getAttribute('keyTimes'),
91
+ dtitle_text: dtitle?.textContent ?? null,
92
+ dbeam_before_nodes: dbeamBeforeNodes,
93
+ dbeam_after_vbeam: dbeamAfterVbeam,
94
+ hbeam_present: !!hbeam,
95
+ vbeam_present: !!vbeam,
96
+ patterns: svg?.getAttribute('data-topo-respiratory-patterns') ?? null,
97
+ stats: svg?.getAttribute('data-topo-respiratory-axis-count-stats') ?? null,
98
+ a11y: svg?.getAttribute('data-topo-a11y-titles') ?? null,
99
+ };
100
+ });
101
+
102
+ await browser.close();
103
+
104
+ const gcd = (a, b) => (b === 0 ? a : gcd(b, a % b));
105
+ const coprime_trio = gcd(19, 23) === 1 && gcd(19, 30) === 1 && gcd(23, 30) === 1;
106
+
107
+ let patterns = null;
108
+ let stats = null;
109
+ let a11y = null;
110
+ try {
111
+ patterns = JSON.parse(state?.patterns ?? '');
112
+ stats = JSON.parse(state?.stats ?? '');
113
+ a11y = JSON.parse(state?.a11y ?? '');
114
+ } catch {}
115
+
116
+ const trioEntry = Array.isArray(patterns) ? patterns.find(p => p.name === 'scan-beam-trio') : null;
117
+ const trioCorrect = !!trioEntry
118
+ && JSON.stringify(trioEntry.cadences) === JSON.stringify([19, 23, 30])
119
+ && trioEntry.shape === 'coprime-trio'
120
+ && Array.isArray(trioEntry.anchors) && trioEntry.anchors.length === 3
121
+ && trioEntry.anchors.includes('scan beam diagonal');
122
+
123
+ const results = {
124
+ dbeam_line_present: state?.dbeam_present === true,
125
+ dbeam_active_true: state?.dbeam_active_attr === 'true',
126
+ x1_anim_full: state?.x1_dur === '19s' && state?.x1_vals === '-100;1100;-100',
127
+ y1_anim_full: state?.y1_dur === '19s' && state?.y1_vals === '-100;780;-100',
128
+ x2_anim_full: state?.x2_dur === '19s' && state?.x2_vals === '-30;1170;-30',
129
+ y2_anim_full: state?.y2_dur === '19s' && state?.y2_vals === '-30;850;-30',
130
+ op_anim_ramped: state?.op_dur === '19s' && state?.op_vals === '0;0.06;0.06;0' && state?.op_kt === '0;0.05;0.95;1',
131
+ dbeam_a11y_title: state?.dtitle_text === 'canvas scan beam diagonal · ambient sweep · 19s cycle',
132
+ dbeam_background_layer: state?.dbeam_before_nodes === true,
133
+ dbeam_after_vertical: state?.dbeam_after_vbeam === true,
134
+ all_three_beams_present: state?.dbeam_present && state?.vbeam_present && state?.hbeam_present,
135
+ coprime_trio_pairwise: coprime_trio,
136
+ r717_has_10_entries: Array.isArray(patterns) && patterns.length === 10,
137
+ r717_trio_entry_correct: trioCorrect,
138
+ r729_patterns_count_10: stats?.patterns_count === 10,
139
+ r729_ambient_patterns_2: stats?.ambient_patterns === 2,
140
+ r729_ambient_cadences_3: stats?.ambient_cadences === 3,
141
+ r732_a11y_has_9_entries: Array.isArray(a11y) && a11y.length === 9,
142
+ };
143
+ const ok = Object.values(results).every(Boolean);
144
+ console.log(`${ok ? '✅' : '❌'} R739 diagonal scan beam (3rd ambient member, completes scan-beam-trio with pairwise-coprime cadences):`,
145
+ JSON.stringify(results, null, 2),
146
+ `\n trio entry: ${JSON.stringify(trioEntry)}`,
147
+ `\n gcd: 19-23=${gcd(19,23)} 19-30=${gcd(19,30)} 23-30=${gcd(23,30)}`);
148
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,109 @@
1
+ /* Round 735 — SVG scan beam: ambient living-system sweep across the
2
+ * canvas every 30 s. Pivot round: first genuinely new VISIBLE
3
+ * animation outside the breath / a11y / meta-doc threads since R720.
4
+ *
5
+ * Spec:
6
+ * - 1 px tall horizontal cyan stripe (pal.legendAccent)
7
+ * - y animates -2 → 680 → -2 over 30 s repeatCount=indefinite
8
+ * - opacity animates 0 → 0.08 → 0.08 → 0 at keyTimes 0/0.05/0.95/1
9
+ * - pointer-events: none, no business logic
10
+ * - rendered AFTER panel backdrop, BEFORE all other canvas content
11
+ * (background layer; nodes paint over it)
12
+ * - gated by !reducedMotion at JSX level
13
+ * - SVG <title> child for a11y ("canvas scan beam · ambient sweep · 30s cycle")
14
+ *
15
+ * Assertions:
16
+ * - <rect data-topo-canvas-scan-beam> exists
17
+ * - Two <animate> children: attributeName="y" and attributeName="opacity"
18
+ * - y animate has values "-2;680;-2" and dur "30s"
19
+ * - opacity animate has values "0;0.08;0.08;0" and dur "30s"
20
+ * - <title> child has the expected accessible name
21
+ * - data-topo-canvas-scan-beam-active="true" (reducedMotion off in test)
22
+ * - Beam is rendered BEFORE nodes (background-layer z-order)
23
+ * - R732 a11y-titles catalog has the scan-beam entry (7 total)
24
+ * - Overlap-test selectors don't match the rect (no data-node /
25
+ * data-group, no matching translate prefix) — verified indirectly
26
+ * by overlap test still passing
27
+ */
28
+ import { chromium } from 'playwright';
29
+ import { readFileSync } from 'node:fs';
30
+
31
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
32
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
33
+
34
+ const browser = await chromium.launch({ headless: true });
35
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
36
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
37
+ await ctx.addInitScript(() => {
38
+ try {
39
+ localStorage.setItem('anet-theme', 'cyber');
40
+ localStorage.setItem('anet-topo-layout', 'ring');
41
+ sessionStorage.setItem('anet_v3_auth', '1');
42
+ } catch {}
43
+ });
44
+ await ctx.route('**/api/hub/status*', async (route) => {
45
+ const r = await route.fetch();
46
+ const b = await r.json();
47
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
48
+ const mk = (alias) => ({
49
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
50
+ network_id: nid, project_dir: null,
51
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
52
+ });
53
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
54
+ });
55
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
56
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
57
+ const page = await ctx.newPage();
58
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
59
+ await page.waitForSelector('[data-topo-canvas-scan-beam]', { timeout: 15000, state: 'attached' });
60
+ await page.waitForTimeout(300);
61
+
62
+ const state = await page.evaluate(() => {
63
+ const beam = document.querySelector('[data-topo-canvas-scan-beam]');
64
+ if (!beam) return null;
65
+ const yAnim = beam.querySelector('animate[attributeName="y"]');
66
+ const opAnim = beam.querySelector('animate[attributeName="opacity"]');
67
+ const titleEl = beam.querySelector(':scope > title');
68
+ const svg = document.querySelector('[data-topo-canvas-aria]');
69
+ const firstNode = svg?.querySelector('g[data-node]');
70
+ const beamBeforeNodes = beam && firstNode
71
+ ? (beam.compareDocumentPosition(firstNode) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0
72
+ : null;
73
+ const catalogAttr = svg?.getAttribute('data-topo-a11y-titles') ?? null;
74
+ return {
75
+ beam_present: !!beam,
76
+ beam_active_attr: beam?.getAttribute('data-topo-canvas-scan-beam-active') ?? null,
77
+ beam_width: beam?.getAttribute('width') ?? null,
78
+ beam_height: beam?.getAttribute('height') ?? null,
79
+ y_anim_present: !!yAnim,
80
+ y_anim_values: yAnim?.getAttribute('values') ?? null,
81
+ y_anim_dur: yAnim?.getAttribute('dur') ?? null,
82
+ y_anim_repeat: yAnim?.getAttribute('repeatCount') ?? null,
83
+ op_anim_present: !!opAnim,
84
+ op_anim_values: opAnim?.getAttribute('values') ?? null,
85
+ op_anim_dur: opAnim?.getAttribute('dur') ?? null,
86
+ op_anim_keytimes: opAnim?.getAttribute('keyTimes') ?? null,
87
+ title_text: titleEl?.textContent ?? null,
88
+ beam_before_nodes: beamBeforeNodes,
89
+ catalog_has_entry: typeof catalogAttr === 'string' && catalogAttr.includes('canvas scan beam'),
90
+ };
91
+ });
92
+
93
+ await browser.close();
94
+
95
+ const results = {
96
+ beam_rect_present: state?.beam_present === true,
97
+ beam_active_true: state?.beam_active_attr === 'true',
98
+ beam_full_width_1px: state?.beam_width === '1000' && state?.beam_height === '1',
99
+ y_anim_full_sweep: state?.y_anim_present === true && state?.y_anim_values === '-2;680;-2' && state?.y_anim_dur === '30s' && state?.y_anim_repeat === 'indefinite',
100
+ opacity_anim_ramped: state?.op_anim_present === true && state?.op_anim_values === '0;0.08;0.08;0' && state?.op_anim_dur === '30s' && state?.op_anim_keytimes === '0;0.05;0.95;1',
101
+ a11y_title_present: state?.title_text === 'canvas scan beam · ambient sweep · 30s cycle',
102
+ beam_in_background_layer: state?.beam_before_nodes === true,
103
+ r732_catalog_includes_beam: state?.catalog_has_entry === true,
104
+ };
105
+ const ok = Object.values(results).every(Boolean);
106
+ console.log(`${ok ? '✅' : '❌'} R735 SVG canvas scan beam (ambient 30s sweep, first non-introspection visible animation since R720):`,
107
+ JSON.stringify(results, null, 2),
108
+ `\n state: ${JSON.stringify(state)}`);
109
+ process.exit(ok ? 0 : 1);