@sleep2agi/agent-network-dashboard 0.5.3-preview.99 → 0.5.4

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 (410) 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 +35 -35
  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 +2 -2
  17. package/.next/server/app/_not-found.rsc +13 -13
  18. package/.next/server/app/_not-found.segments/_full.segment.rsc +13 -13
  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 +2 -2
  26. package/.next/server/app/admin.rsc +15 -15
  27. package/.next/server/app/admin.segments/_full.segment.rsc +15 -15
  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 +2 -2
  41. package/.next/server/app/index.rsc +15 -15
  42. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  43. package/.next/server/app/index.segments/_full.segment.rsc +15 -15
  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 +15 -15
  50. package/.next/server/app/login.segments/_full.segment.rsc +15 -15
  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 +2 -2
  58. package/.next/server/app/logs.rsc +15 -15
  59. package/.next/server/app/logs.segments/_full.segment.rsc +15 -15
  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 +2 -2
  76. package/.next/server/app/messages.rsc +15 -15
  77. package/.next/server/app/messages.segments/_full.segment.rsc +15 -15
  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 +2 -2
  85. package/.next/server/app/node.rsc +15 -15
  86. package/.next/server/app/node.segments/_full.segment.rsc +15 -15
  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 +2 -2
  94. package/.next/server/app/nodes.rsc +15 -15
  95. package/.next/server/app/nodes.segments/_full.segment.rsc +15 -15
  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 +2 -2
  104. package/.next/server/app/server-logs.rsc +15 -15
  105. package/.next/server/app/server-logs.segments/_full.segment.rsc +15 -15
  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 +2 -2
  113. package/.next/server/app/settings/networks.rsc +15 -15
  114. package/.next/server/app/settings/networks.segments/_full.segment.rsc +15 -15
  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 +2 -2
  124. package/.next/server/app/settings/tokens.rsc +15 -15
  125. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +15 -15
  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 +2 -2
  133. package/.next/server/app/settings.rsc +15 -15
  134. package/.next/server/app/settings.segments/_full.segment.rsc +15 -15
  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 +2 -2
  143. package/.next/server/app/tasks.rsc +15 -15
  144. package/.next/server/app/tasks.segments/_full.segment.rsc +15 -15
  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]__0sv~g.o._.js +1 -1
  199. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +1 -1
  200. package/.next/server/chunks/ssr/[root-of-the-server]__0u5aqkk._.js +1 -1
  201. package/.next/server/chunks/ssr/[root-of-the-server]__0u5aqkk._.js.map +1 -1
  202. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +3 -3
  203. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
  204. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
  205. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
  206. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
  207. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
  208. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js +1 -1
  209. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js.map +1 -1
  210. package/.next/server/middleware-build-manifest.js +3 -3
  211. package/.next/server/middleware.js +2 -2
  212. package/.next/server/middleware.js.nft.json +1 -1
  213. package/.next/server/pages/404.html +2 -2
  214. package/.next/server/pages/500.html +1 -1
  215. package/.next/static/chunks/{07~8sx3_5uiox.js → 04wjx7vbxusw5.js} +4 -1
  216. package/.next/static/chunks/089t1exs6apb8.js +4 -0
  217. package/.next/static/chunks/{084e1mr6acfta.js → 09e8kxo30n5cf.js} +1 -1
  218. package/.next/static/chunks/{0v4-5tng.uh.7.js → 0k-c1chkvf78s.js} +2 -2
  219. package/.next/static/chunks/0v2~nlpk-cx6v.css +2 -0
  220. package/.next/static/chunks/0xsye-9kffdi0.js +1 -0
  221. package/.next/static/chunks/0~rx_~akeylmq.js +1 -0
  222. package/.next/trace +2 -2
  223. package/.next/trace-build +1 -1
  224. package/.next/types/routes.d.ts +2 -1
  225. package/.next/types/validator.ts +9 -0
  226. package/app/api/hub/send/route.ts +11 -2
  227. package/app/api/hub/servers/route.ts +3 -29
  228. package/app/api/hub/upload/route.ts +83 -0
  229. package/app/components/AppShell.tsx +3 -1
  230. package/app/components/MobileNav.tsx +45 -0
  231. package/app/components/TaskChatPanel.tsx +130 -6
  232. package/app/components/TopoGraph.tsx +4591 -216
  233. package/app/globals.css +839 -0
  234. package/app/layout.tsx +6 -0
  235. package/app/lib/serverDedupe.ts +122 -0
  236. package/app/lib/vendorIdentity.ts +74 -56
  237. package/app/manifest.ts +23 -0
  238. package/package.json +4 -4
  239. package/public/vendors/claude.svg +7 -8
  240. package/public/vendors/minimax.svg +8 -9
  241. package/public/vendors/openai.svg +8 -10
  242. package/scripts/p157-rc2-dedup-test.mjs +110 -0
  243. package/scripts/topo-a11y-titles-catalog-test.mjs +132 -0
  244. package/scripts/topo-active-links-chip-halo-layers-test.mjs +81 -0
  245. package/scripts/topo-alias-chat-brightness-test.mjs +79 -0
  246. package/scripts/topo-alias-text-halo-layers-test.mjs +98 -0
  247. package/scripts/topo-animation-temporal-modes-catalog-test.mjs +144 -0
  248. package/scripts/topo-avatar-chat-gate-test.mjs +77 -0
  249. package/scripts/topo-avatar-drop-shadow-test.mjs +86 -0
  250. package/scripts/topo-avatar-fallback-rotate-test.mjs +92 -0
  251. package/scripts/topo-avatar-rotate-test.mjs +85 -0
  252. package/scripts/topo-avatar-scale-test.mjs +89 -0
  253. package/scripts/topo-badge-chat-gate-test.mjs +74 -0
  254. package/scripts/topo-brand-drop-shadow-test.mjs +71 -0
  255. package/scripts/topo-brand-logo-halo-layers-test.mjs +85 -0
  256. package/scripts/topo-canvas-desc-a11y-test.mjs +87 -0
  257. package/scripts/topo-canvas-entrance-animation-test.mjs +117 -0
  258. package/scripts/topo-canvas-scan-beam-diagonal-test.mjs +148 -0
  259. package/scripts/topo-canvas-scan-beam-test.mjs +109 -0
  260. package/scripts/topo-canvas-scan-beam-vertical-test.mjs +123 -0
  261. package/scripts/topo-card-chat-brightness-test.mjs +86 -0
  262. package/scripts/topo-chat-ring-breath-curve-test.mjs +114 -0
  263. package/scripts/topo-chat-ring-brightness-test.mjs +80 -0
  264. package/scripts/topo-chat-ring-halo-layers-test.mjs +100 -0
  265. package/scripts/topo-chat-ring-r-breath-test.mjs +121 -0
  266. package/scripts/topo-chat-ring-status-halo-test.mjs +106 -0
  267. package/scripts/topo-chat-ring-sw-breath-test.mjs +123 -0
  268. package/scripts/topo-chip-pin-halo-test.mjs +85 -0
  269. package/scripts/topo-chrome-control-halo-layers-test.mjs +22 -0
  270. package/scripts/topo-chrome-fullscreen-breath-test.mjs +121 -0
  271. package/scripts/topo-chrome-layout-trailer-breath-test.mjs +86 -0
  272. package/scripts/topo-chrome-nodesize-trailer-breath-test.mjs +86 -0
  273. package/scripts/topo-chrome-reset-breath-test.mjs +115 -0
  274. package/scripts/topo-chrome-strip-entrance-animation-test.mjs +115 -0
  275. package/scripts/topo-chrome-wrapper-halo-test.mjs +83 -0
  276. package/scripts/topo-chrome-zoom-wrapper-breath-test.mjs +85 -0
  277. package/scripts/topo-click-ripple-glow-test.mjs +86 -0
  278. package/scripts/topo-click-ripple-halo-layers-test.mjs +79 -0
  279. package/scripts/topo-click-ripple-sw-test.mjs +110 -0
  280. package/scripts/topo-crescent-envelope-breath-test.mjs +103 -0
  281. package/scripts/topo-dense-alias-chat-halo-test.mjs +73 -0
  282. package/scripts/topo-dense-alias-halo-layers-test.mjs +80 -0
  283. package/scripts/topo-dual-axis-surfaces-catalog-test.mjs +94 -0
  284. package/scripts/topo-edge-badge-circle-brightness-test.mjs +82 -0
  285. package/scripts/topo-edge-badge-circle-hot-pulse-test.mjs +100 -0
  286. package/scripts/topo-edge-badge-digit-halo-layers-test.mjs +107 -0
  287. package/scripts/topo-edge-badge-endpoint-gate-test.mjs +94 -0
  288. package/scripts/topo-edge-badge-halo-layers-test.mjs +85 -0
  289. package/scripts/topo-edge-badge-hot-pulse-test.mjs +92 -0
  290. package/scripts/topo-edge-chat-gate-test.mjs +71 -0
  291. package/scripts/topo-edge-flow-rail-halo-layers-test.mjs +89 -0
  292. package/scripts/topo-edge-particle-halo-layers-test.mjs +91 -0
  293. package/scripts/topo-edge-pin-halo-test.mjs +99 -0
  294. package/scripts/topo-edge-visible-halo-layers-test.mjs +87 -0
  295. package/scripts/topo-endpoint-ring-flow-halo-test.mjs +107 -0
  296. package/scripts/topo-endpoint-ring-halo-layers-test.mjs +100 -0
  297. package/scripts/topo-filter-pill-halo-layers-test.mjs +27 -0
  298. package/scripts/topo-flow-arrow-brightness-test.mjs +82 -0
  299. package/scripts/topo-fullscreen-brightness-test.mjs +84 -0
  300. package/scripts/topo-group-box-brightness-test.mjs +84 -0
  301. package/scripts/topo-group-box-halo-layers-test.mjs +91 -0
  302. package/scripts/topo-group-chat-gate-test.mjs +77 -0
  303. package/scripts/topo-group-label-halo-layers-test.mjs +78 -0
  304. package/scripts/topo-group-tint-brightness-test.mjs +82 -0
  305. package/scripts/topo-h2-dual-axis-breath-test.mjs +92 -0
  306. package/scripts/topo-h2-triple-axis-breath-test.mjs +142 -0
  307. package/scripts/topo-halo-chat-gate-test.mjs +72 -0
  308. package/scripts/topo-hover-detail-halo-test.mjs +76 -0
  309. package/scripts/topo-hub-a11y-title-test.mjs +95 -0
  310. package/scripts/topo-hub-core-brightness-test.mjs +82 -0
  311. package/scripts/topo-hub-core-halo-layers-test.mjs +81 -0
  312. package/scripts/topo-hub-digit-halo-layers-test.mjs +76 -0
  313. package/scripts/topo-hub-halo-halo-layers-test.mjs +76 -0
  314. package/scripts/topo-hub-highlight-halo-layers-test.mjs +78 -0
  315. package/scripts/topo-hub-hover-ring-halo-layers-test.mjs +71 -0
  316. package/scripts/topo-hub-spoke-halo-layers-test.mjs +97 -0
  317. package/scripts/topo-hub-spoke-self-filter-test.mjs +119 -0
  318. package/scripts/topo-kicker-breath-test.mjs +100 -0
  319. package/scripts/topo-kicker-dual-axis-breath-test.mjs +81 -0
  320. package/scripts/topo-kicker-halo-layers-test.mjs +82 -0
  321. package/scripts/topo-kicker-triple-axis-breath-test.mjs +124 -0
  322. package/scripts/topo-label-card-brightness-test.mjs +81 -0
  323. package/scripts/topo-layout-toggle-brightness-test.mjs +94 -0
  324. package/scripts/topo-layout-toggle-halo-layers-test.mjs +95 -0
  325. package/scripts/topo-legend-count-brightness-test.mjs +80 -0
  326. package/scripts/topo-legend-count-halo-layers-test.mjs +79 -0
  327. package/scripts/topo-legend-panel-title-breath-test.mjs +86 -0
  328. package/scripts/topo-legend-pin-ring-brightness-test.mjs +82 -0
  329. package/scripts/topo-legend-pin-ring-halo-layers-test.mjs +71 -0
  330. package/scripts/topo-legend-row-count-brightness-test.mjs +85 -0
  331. package/scripts/topo-legend-tint-brightness-test.mjs +83 -0
  332. package/scripts/topo-legend-trio-halo-layers-test.mjs +22 -0
  333. package/scripts/topo-live-lanes.mjs +48 -0
  334. package/scripts/topo-minimap-container-halo-test.mjs +82 -0
  335. package/scripts/topo-minimap-dot-chat-gate-test.mjs +81 -0
  336. package/scripts/topo-minimap-viewport-brightness-test.mjs +84 -0
  337. package/scripts/topo-minimap-viewport-halo-layers-test.mjs +24 -0
  338. package/scripts/topo-more-footer-brightness-test.mjs +94 -0
  339. package/scripts/topo-node-avatar-halo-layers-test.mjs +25 -0
  340. package/scripts/topo-node-hover-ring-halo-layers-test.mjs +70 -0
  341. package/scripts/topo-node-label-card-halo-test.mjs +76 -0
  342. package/scripts/topo-nodesize-brightness-test.mjs +82 -0
  343. package/scripts/topo-nodesize-halo-layers-test.mjs +89 -0
  344. package/scripts/topo-overlap-test.mjs +22 -8
  345. package/scripts/topo-panel-count-halo-layers-test.mjs +91 -0
  346. package/scripts/topo-panel-rect-halo-test.mjs +90 -0
  347. package/scripts/topo-panel-titles-dual-axis-breath-test.mjs +94 -0
  348. package/scripts/topo-panel-titles-halo-layers-test.mjs +23 -0
  349. package/scripts/topo-panel-titles-triple-axis-breath-test.mjs +161 -0
  350. package/scripts/topo-pip-brightness-test.mjs +85 -0
  351. package/scripts/topo-pressure-bar-halo-layers-test.mjs +19 -0
  352. package/scripts/topo-r717-scan-beam-pair-pattern-test.mjs +100 -0
  353. package/scripts/topo-r717-triple-axis-pair-pattern-test.mjs +113 -0
  354. package/scripts/topo-r717-triple-axis-tier-pattern-test.mjs +117 -0
  355. package/scripts/topo-recent-count-brightness-test.mjs +84 -0
  356. package/scripts/topo-recent-more-halo-layers-test.mjs +90 -0
  357. package/scripts/topo-recent-panel-hot-pulse-test.mjs +105 -0
  358. package/scripts/topo-recent-panel-title-breath-test.mjs +91 -0
  359. package/scripts/topo-recent-pip-halo-layers-test.mjs +82 -0
  360. package/scripts/topo-recent-row-chat-gate-test.mjs +75 -0
  361. package/scripts/topo-recent-row-content-lift-test.mjs +140 -0
  362. package/scripts/topo-recent-row-text-halo-layers-test.mjs +67 -0
  363. package/scripts/topo-recent-tint-brightness-test.mjs +80 -0
  364. package/scripts/topo-recent-ts-brightness-test.mjs +86 -0
  365. package/scripts/topo-reset-brightness-test.mjs +83 -0
  366. package/scripts/topo-respiratory-axis-count-stats-test.mjs +154 -0
  367. package/scripts/topo-respiratory-patterns-catalog-test.mjs +112 -0
  368. package/scripts/topo-respiratory-rolodex-test.mjs +83 -0
  369. package/scripts/topo-respiratory-tiers-catalog-test.mjs +119 -0
  370. package/scripts/topo-respiratory-triple-axis-surfaces-catalog-test.mjs +127 -0
  371. package/scripts/topo-runtime-badge-brightness-test.mjs +78 -0
  372. package/scripts/topo-runtime-badge-halo-layers-test.mjs +87 -0
  373. package/scripts/topo-runtime-badge-rotate-test.mjs +85 -0
  374. package/scripts/topo-section-title-breath-test.mjs +83 -0
  375. package/scripts/topo-section-title-halo-layers-test.mjs +88 -0
  376. package/scripts/topo-spoke-chat-gate-test.mjs +72 -0
  377. package/scripts/topo-status-pin-pill-halo-layers-test.mjs +17 -0
  378. package/scripts/topo-status-ring-chat-gate-test.mjs +72 -0
  379. package/scripts/topo-status-ring-halo-layers-test.mjs +105 -0
  380. package/scripts/topo-status-ring-status-halo-test.mjs +110 -0
  381. package/scripts/topo-sub-text-chat-brightness-test.mjs +81 -0
  382. package/scripts/topo-svg-title-a11y-r731-test.mjs +93 -0
  383. package/scripts/topo-svg-title-a11y-test.mjs +88 -0
  384. package/scripts/topo-title-block-entrance-animation-test.mjs +127 -0
  385. package/scripts/topo-title-block-envelope-breath-test.mjs +87 -0
  386. package/scripts/topo-tree-diag.mjs +95 -0
  387. package/scripts/topo-vendor-chip-halo-layers-test.mjs +18 -0
  388. package/scripts/topo-vendor-chip-pin-halo-test.mjs +88 -0
  389. package/scripts/topo-vendor-count-suffix-halo-layers-test.mjs +79 -0
  390. package/scripts/topo-vendor-distribution-wrapper-halo-test.mjs +93 -0
  391. package/scripts/topo-vendor-letter-halo-layers-test.mjs +93 -0
  392. package/scripts/topo-watermark-dual-axis-breath-test.mjs +88 -0
  393. package/scripts/topo-watermark-envelope-breath-test.mjs +88 -0
  394. package/scripts/topo-watermark-triple-axis-breath-test.mjs +129 -0
  395. package/scripts/topo-working-online-chip-halo-layers-test.mjs +94 -0
  396. package/scripts/topo-zoom-buttons-brightness-test.mjs +94 -0
  397. package/scripts/topo-zoom-in-out-halo-layers-test.mjs +97 -0
  398. package/scripts/topo-zoom-level-breath-test.mjs +87 -0
  399. package/scripts/topo-zoom-level-brightness-test.mjs +83 -0
  400. package/scripts/topo-zoom-level-dual-axis-breath-test.mjs +83 -0
  401. package/scripts/topo-zoom-level-halo-layers-test.mjs +78 -0
  402. package/scripts/topo-zoom-level-triple-axis-breath-test.mjs +148 -0
  403. package/.next/static/chunks/09oxd2mm27b_n.js +0 -1
  404. package/.next/static/chunks/0ots8-uksxz9p.js +0 -4
  405. package/.next/static/chunks/0voxs92keb6tg.js +0 -1
  406. package/.next/static/chunks/13~aih56vx-cf.css +0 -2
  407. /package/.next/server/chunks/{[externals]__11vad82._.js.map → 0ykm__next-internal_server_app_api_hub_upload_route_actions_03_eqnf.js.map} +0 -0
  408. /package/.next/static/{Ha31LjrNJgJIEydZivRlp → xq88BMF7fMUHWh10yaKTn}/_buildManifest.js +0 -0
  409. /package/.next/static/{Ha31LjrNJgJIEydZivRlp → xq88BMF7fMUHWh10yaKTn}/_clientMiddlewareManifest.js +0 -0
  410. /package/.next/static/{Ha31LjrNJgJIEydZivRlp → xq88BMF7fMUHWh10yaKTn}/_ssgManifest.js +0 -0
@@ -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);
@@ -0,0 +1,123 @@
1
+ /* Round 736 — vertical scan beam companion to R735's horizontal beam.
2
+ * Forms the "scan beam" ambient family — coprime cadences mean the
3
+ * beams never phase-lock; over time the visual rhythm reads as
4
+ * "ambient crosshair drift".
5
+ *
6
+ * R735 horizontal beam 30 s (top → bottom)
7
+ * R736 vertical beam 23 s (left → right) ← this round
8
+ * gcd(23, 30) = 1
9
+ *
10
+ * Assertions:
11
+ * - <rect data-topo-canvas-scan-beam-vertical> exists with 1×680 box
12
+ * - x animates -2 → 1000 → -2 over 23s repeatCount=indefinite
13
+ * - opacity animates 0 → 0.08 → 0.08 → 0 at keyTimes 0/0.05/0.95/1, dur 23s
14
+ * - SVG <title> child = "canvas scan beam vertical · ambient sweep · 23s cycle"
15
+ * - data-topo-canvas-scan-beam-vertical-active="true" (reducedMotion off)
16
+ * - vertical beam in background layer (rendered before nodes)
17
+ * - vertical beam rendered AFTER horizontal beam (pair grouping)
18
+ * - R735 horizontal beam still intact (regression — y, dur, title preserved)
19
+ * - coprime cadences: gcd(23, 30) === 1 — verified by checking the
20
+ * two beams' durs are 23s/30s and Math.gcd-equivalent reduces to 1
21
+ * - R732 a11y-titles catalog has 8 entries incl. vertical beam
22
+ */
23
+ import { chromium } from 'playwright';
24
+ import { readFileSync } from 'node:fs';
25
+
26
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
27
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
28
+
29
+ const browser = await chromium.launch({ headless: true });
30
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
31
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
32
+ await ctx.addInitScript(() => {
33
+ try {
34
+ localStorage.setItem('anet-theme', 'cyber');
35
+ localStorage.setItem('anet-topo-layout', 'ring');
36
+ sessionStorage.setItem('anet_v3_auth', '1');
37
+ } catch {}
38
+ });
39
+ await ctx.route('**/api/hub/status*', async (route) => {
40
+ const r = await route.fetch();
41
+ const b = await r.json();
42
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
43
+ const mk = (alias) => ({
44
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
45
+ network_id: nid, project_dir: null,
46
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
47
+ });
48
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
49
+ });
50
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
51
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
52
+ const page = await ctx.newPage();
53
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
54
+ await page.waitForSelector('[data-topo-canvas-scan-beam-vertical]', { timeout: 15000, state: 'attached' });
55
+ await page.waitForTimeout(300);
56
+
57
+ const state = await page.evaluate(() => {
58
+ const vbeam = document.querySelector('[data-topo-canvas-scan-beam-vertical]');
59
+ const hbeam = document.querySelector('[data-topo-canvas-scan-beam]');
60
+ if (!vbeam || !hbeam) return null;
61
+ const xAnim = vbeam.querySelector('animate[attributeName="x"]');
62
+ const opAnim = vbeam.querySelector('animate[attributeName="opacity"]');
63
+ const vtitle = vbeam.querySelector(':scope > title');
64
+ const yAnim = hbeam.querySelector('animate[attributeName="y"]');
65
+ const htitle = hbeam.querySelector(':scope > title');
66
+ const svg = document.querySelector('[data-topo-canvas-aria]');
67
+ const firstNode = svg?.querySelector('g[data-node]');
68
+ const vbeamBeforeNodes = vbeam && firstNode
69
+ ? (vbeam.compareDocumentPosition(firstNode) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0
70
+ : null;
71
+ const vbeamAfterHbeam = hbeam && vbeam
72
+ ? (hbeam.compareDocumentPosition(vbeam) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0
73
+ : null;
74
+ const catalogAttr = svg?.getAttribute('data-topo-a11y-titles') ?? null;
75
+ return {
76
+ vbeam_present: !!vbeam,
77
+ vbeam_active_attr: vbeam?.getAttribute('data-topo-canvas-scan-beam-vertical-active') ?? null,
78
+ vbeam_width: vbeam?.getAttribute('width') ?? null,
79
+ vbeam_height: vbeam?.getAttribute('height') ?? null,
80
+ x_anim_present: !!xAnim,
81
+ x_anim_values: xAnim?.getAttribute('values') ?? null,
82
+ x_anim_dur: xAnim?.getAttribute('dur') ?? null,
83
+ x_anim_repeat: xAnim?.getAttribute('repeatCount') ?? null,
84
+ op_anim_present: !!opAnim,
85
+ op_anim_values: opAnim?.getAttribute('values') ?? null,
86
+ op_anim_dur: opAnim?.getAttribute('dur') ?? null,
87
+ op_anim_keytimes: opAnim?.getAttribute('keyTimes') ?? null,
88
+ vtitle_text: vtitle?.textContent ?? null,
89
+ hbeam_present: !!hbeam,
90
+ hbeam_y_dur: yAnim?.getAttribute('dur') ?? null,
91
+ hbeam_y_values: yAnim?.getAttribute('values') ?? null,
92
+ htitle_text: htitle?.textContent ?? null,
93
+ vbeam_before_nodes: vbeamBeforeNodes,
94
+ vbeam_after_hbeam: vbeamAfterHbeam,
95
+ catalog_includes_vbeam: typeof catalogAttr === 'string' && catalogAttr.includes('canvas scan beam vertical'),
96
+ };
97
+ });
98
+
99
+ await browser.close();
100
+
101
+ const gcd = (a, b) => (b === 0 ? a : gcd(b, a % b));
102
+ const coprime_23_30 = gcd(23, 30) === 1;
103
+
104
+ const results = {
105
+ vbeam_rect_present: state?.vbeam_present === true,
106
+ vbeam_active_true: state?.vbeam_active_attr === 'true',
107
+ vbeam_1px_full_height: state?.vbeam_width === '1' && state?.vbeam_height === '680',
108
+ x_anim_full_sweep: state?.x_anim_present === true && state?.x_anim_values === '-2;1000;-2' && state?.x_anim_dur === '23s' && state?.x_anim_repeat === 'indefinite',
109
+ vbeam_opacity_anim_ramped: state?.op_anim_present === true && state?.op_anim_values === '0;0.08;0.08;0' && state?.op_anim_dur === '23s' && state?.op_anim_keytimes === '0;0.05;0.95;1',
110
+ vbeam_a11y_title_present: state?.vtitle_text === 'canvas scan beam vertical · ambient sweep · 23s cycle',
111
+ vbeam_in_background_layer: state?.vbeam_before_nodes === true,
112
+ vbeam_after_horizontal_beam: state?.vbeam_after_hbeam === true,
113
+ hbeam_y_30s_preserved: state?.hbeam_y_dur === '30s' && state?.hbeam_y_values === '-2;680;-2',
114
+ hbeam_title_preserved: state?.htitle_text === 'canvas scan beam · ambient sweep · 30s cycle',
115
+ coprime_cadences_23_30: coprime_23_30,
116
+ r732_catalog_includes_vbeam: state?.catalog_includes_vbeam === true,
117
+ };
118
+ const ok = Object.values(results).every(Boolean);
119
+ console.log(`${ok ? '✅' : '❌'} R736 vertical scan beam (companion to R735, coprime cadences form ambient crosshair pair):`,
120
+ JSON.stringify(results, null, 2),
121
+ `\n state: ${JSON.stringify(state)}`,
122
+ `\n gcd(23, 30) = ${gcd(23, 30)}`);
123
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,86 @@
1
+ /* Round 618 — extend label card hover treatments (stroke +
2
+ * filter brightness) gate from hover-only to (hover || chat-
3
+ * target). 4th anchor in chat-target-gated brightness family.
4
+ *
5
+ * Test phases:
6
+ * 1. mock 2 idle nodes → label cards render
7
+ * 2. rest (no hover, no chat): rest filter (shallow DS, NO
8
+ * brightness), brightness-attr='1', elevation='idle',
9
+ * chat-target='false'
10
+ * 3. computed transition-property contains 'filter'
11
+ * 4. source: stroke + filter conditionals include BOTH hover
12
+ * AND chat gates joined by `||`
13
+ */
14
+ import { chromium } from 'playwright';
15
+ import { readFileSync } from 'node:fs';
16
+
17
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
18
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
19
+
20
+ const browser = await chromium.launch({ headless: true });
21
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
22
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
23
+ await ctx.addInitScript(() => {
24
+ try {
25
+ localStorage.setItem('anet-theme', 'cyber');
26
+ localStorage.setItem('anet-topo-layout', 'ring');
27
+ sessionStorage.setItem('anet_v3_auth', '1');
28
+ } catch {}
29
+ });
30
+ await ctx.route('**/api/hub/status*', async (route) => {
31
+ const r = await route.fetch();
32
+ const b = await r.json();
33
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
34
+ const mk = (alias) => ({
35
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
36
+ network_id: nid, project_dir: null,
37
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
38
+ });
39
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
40
+ });
41
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
42
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
43
+ const page = await ctx.newPage();
44
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
45
+ await page.waitForSelector('[data-node-label-card-chat-target]', { timeout: 15000, state: 'attached' });
46
+ await page.waitForTimeout(500);
47
+
48
+ const rest = await page.evaluate(() => {
49
+ const el = document.querySelector('[data-node-label-card-chat-target]');
50
+ if (!el) return null;
51
+ const cs = getComputedStyle(el);
52
+ return {
53
+ filter: cs.filter,
54
+ transitionProperty: cs.transitionProperty,
55
+ brightnessAttr: el.getAttribute('data-node-label-card-brightness'),
56
+ elevationAttr: el.getAttribute('data-node-label-card-elevation'),
57
+ chatTargetAttr: el.getAttribute('data-node-label-card-chat-target'),
58
+ };
59
+ });
60
+
61
+ await browser.close();
62
+
63
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
64
+ const sourceFilterOr = /filter: !reducedMotion && \(hoveredAlias === session\.alias \|\| chatAlias === session\.alias\)\s*\?\s*\(isLight/.test(src);
65
+ const sourceStrokeOr = /stroke=\{!reducedMotion && \(hoveredAlias === session\.alias \|\| chatAlias === session\.alias\)/.test(src);
66
+ const sourceAttrOr = /data-node-label-card-brightness=\{!reducedMotion && \(hoveredAlias === session\.alias \|\| chatAlias === session\.alias\) \? '1\.15' : '1'\}/.test(src);
67
+ const sourceChatAttr = /data-node-label-card-chat-target=\{chatAlias === session\.alias \? 'true' : 'false'\}/.test(src);
68
+
69
+ const results = {
70
+ card_present: !!rest,
71
+ rest_has_drop_shadow: /drop-shadow/.test(rest?.filter || ''),
72
+ rest_no_brightness: !/brightness/.test(rest?.filter || ''),
73
+ rest_brightness_1: rest?.brightnessAttr === '1',
74
+ rest_elevation_idle: rest?.elevationAttr === 'idle',
75
+ rest_chat_target_false: rest?.chatTargetAttr === 'false',
76
+ transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
77
+ source_filter_or: sourceFilterOr,
78
+ source_stroke_or: sourceStrokeOr,
79
+ source_attr_or: sourceAttrOr,
80
+ source_chat_attr: sourceChatAttr,
81
+ };
82
+ const ok = Object.values(results).every(Boolean);
83
+ console.log(`${ok ? '✅' : '❌'} R618 card chat-target brightness (chat-gated family 4th anchor):`,
84
+ JSON.stringify(results, null, 2),
85
+ `\n rest: ${JSON.stringify(rest)}`);
86
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,114 @@
1
+ /* Round 641 — chat-target ring 3-axis breath SMIL animates gain
2
+ * canonical CSS ease-in-out keySplines (0.42 0 0.58 1, twice for
3
+ * both halves). All three animates (opacity, stroke-width, r)
4
+ * share the same curve so the breath settles at endpoints
5
+ * and accelerates through midpoints — heart-rest organic feel.
6
+ *
7
+ * Test phases:
8
+ * 1. mock 2 idle nodes, no chat → ring at rest, breath-curve='none'
9
+ * 2. click a·1 → 3 animates concurrently with:
10
+ * - calcMode='spline'
11
+ * - keyTimes='0;0.5;1'
12
+ * - keySplines='0.42 0 0.58 1;0.42 0 0.58 1'
13
+ * 3. breath-curve attr === 'ease-in-out'
14
+ * 4. source: all 3 animates carry the new attrs
15
+ */
16
+ import { chromium } from 'playwright';
17
+ import { readFileSync } from 'node:fs';
18
+
19
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
20
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
21
+
22
+ const browser = await chromium.launch({ headless: true });
23
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
24
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
25
+ await ctx.addInitScript(() => {
26
+ try {
27
+ localStorage.setItem('anet-theme', 'cyber');
28
+ localStorage.setItem('anet-topo-layout', 'ring');
29
+ sessionStorage.setItem('anet_v3_auth', '1');
30
+ } catch {}
31
+ });
32
+ await ctx.route('**/api/hub/status*', async (route) => {
33
+ const r = await route.fetch();
34
+ const b = await r.json();
35
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
36
+ const mk = (alias) => ({
37
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
38
+ network_id: nid, project_dir: null,
39
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
40
+ });
41
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
42
+ });
43
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
44
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
45
+ const page = await ctx.newPage();
46
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
47
+ await page.waitForSelector('[data-chat-target-ring]', { timeout: 15000, state: 'attached' });
48
+ await page.waitForTimeout(500);
49
+
50
+ const rest = await page.evaluate(() => {
51
+ const el = document.querySelector('[data-chat-target-ring]');
52
+ if (!el) return null;
53
+ return {
54
+ curve: el.getAttribute('data-chat-target-ring-breath-curve'),
55
+ active: el.getAttribute('data-chat-target-active'),
56
+ };
57
+ });
58
+
59
+ await page.click('[data-node="a·1"]', { force: true });
60
+ await page.waitForTimeout(400);
61
+
62
+ const active = await page.evaluate(() => {
63
+ const node = document.querySelector('[data-node="a·1"]');
64
+ if (!node) return null;
65
+ const ring = node.querySelector('[data-chat-target-ring]');
66
+ if (!ring) return null;
67
+ const animates = Array.from(ring.querySelectorAll('animate'));
68
+ return {
69
+ curve: ring.getAttribute('data-chat-target-ring-breath-curve'),
70
+ active: ring.getAttribute('data-chat-target-active'),
71
+ animateAttrs: animates.map(a => ({
72
+ attr: a.getAttribute('attributeName'),
73
+ calc: a.getAttribute('calcMode'),
74
+ kt: a.getAttribute('keyTimes'),
75
+ ks: a.getAttribute('keySplines'),
76
+ })),
77
+ };
78
+ });
79
+
80
+ await browser.close();
81
+
82
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
83
+ // Each of the 3 animates should carry the same spline attrs
84
+ const splineAttrPattern = /calcMode="spline"\s+keyTimes="0;0\.5;1"\s+keySplines="0\.42 0 0\.58 1;0\.42 0 0\.58 1"/g;
85
+ const splineMatches = (src.match(splineAttrPattern) || []).length;
86
+ const sourceCurveAttr = /data-chat-target-ring-breath-curve=\{!reducedMotion && isChat \? 'ease-in-out' : 'none'\}/.test(src);
87
+
88
+ const allHaveSpline = active?.animateAttrs?.length === 3 && active.animateAttrs.every(a =>
89
+ a.calc === 'spline' &&
90
+ a.kt === '0;0.5;1' &&
91
+ a.ks === '0.42 0 0.58 1;0.42 0 0.58 1'
92
+ );
93
+
94
+ const results = {
95
+ rest_curve_none: rest?.curve === 'none',
96
+ active_curve_ease: active?.curve === 'ease-in-out',
97
+ active_animate_count_3: active?.animateAttrs?.length === 3,
98
+ active_all_have_spline: allHaveSpline,
99
+ active_has_opacity: active?.animateAttrs?.some(a => a.attr === 'opacity'),
100
+ active_has_sw: active?.animateAttrs?.some(a => a.attr === 'stroke-width'),
101
+ active_has_r: active?.animateAttrs?.some(a => a.attr === 'r'),
102
+ // Multiple SMIL ease-in-out splines exist across the file (R243 active-
103
+ // pulse, R244 hub-halo, plus 3 new chat-target ring animates). Assert
104
+ // count >= 3 — runtime block already verifies the 3 chat-target ring
105
+ // animates carry the exact attrs.
106
+ source_at_least_3_splines: splineMatches >= 3,
107
+ source_curve_attr: sourceCurveAttr,
108
+ };
109
+ const ok = Object.values(results).every(Boolean);
110
+ console.log(`${ok ? '✅' : '❌'} R641 chat-target ring 3-axis breath ease-in-out keySplines:`,
111
+ JSON.stringify(results, null, 2),
112
+ `\n rest: ${JSON.stringify(rest)}`,
113
+ `\n active: ${JSON.stringify(active)}`);
114
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,80 @@
1
+ /* 🎯 Round 615 — 100th consecutive visible-polish round milestone.
2
+ * Chat-target ring stacks brightness(1.15) onto url(#topo-glow)
3
+ * on isChat=true. Introduces a NEW 4th brightness gate type:
4
+ * chat-target-gated.
5
+ *
6
+ * Test phases:
7
+ * 1. mock 2 idle nodes → chat ring renders (opacity 0 at rest)
8
+ * 2. rest (no chat target): filter='none', brightness-attr='1',
9
+ * active='false'
10
+ * 3. computed transition-property contains 'filter'
11
+ * 4. source: stacked filter conditional + data-attr
12
+ */
13
+ import { chromium } from 'playwright';
14
+ import { readFileSync } from 'node:fs';
15
+
16
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
17
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
18
+
19
+ const browser = await chromium.launch({ headless: true });
20
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
21
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
22
+ await ctx.addInitScript(() => {
23
+ try {
24
+ localStorage.setItem('anet-theme', 'cyber');
25
+ localStorage.setItem('anet-topo-layout', 'ring');
26
+ sessionStorage.setItem('anet_v3_auth', '1');
27
+ } catch {}
28
+ });
29
+ await ctx.route('**/api/hub/status*', async (route) => {
30
+ const r = await route.fetch();
31
+ const b = await r.json();
32
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
33
+ const mk = (alias) => ({
34
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
35
+ network_id: nid, project_dir: null,
36
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
37
+ });
38
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
39
+ });
40
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
41
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
42
+ const page = await ctx.newPage();
43
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
44
+ await page.waitForSelector('[data-chat-target-ring]', { timeout: 15000, state: 'attached' });
45
+ await page.waitForTimeout(500);
46
+
47
+ const rest = await page.evaluate(() => {
48
+ const el = document.querySelector('[data-chat-target-ring]');
49
+ if (!el) return null;
50
+ const cs = getComputedStyle(el);
51
+ return {
52
+ filter: cs.filter,
53
+ opacity: cs.opacity,
54
+ transitionProperty: cs.transitionProperty,
55
+ brightnessAttr: el.getAttribute('data-node-chat-ring-brightness'),
56
+ activeAttr: el.getAttribute('data-chat-target-active'),
57
+ };
58
+ });
59
+
60
+ await browser.close();
61
+
62
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
63
+ const sourceFilter = /filter: isChat\s*\?\s*\(isLight\s*\?\s*'brightness\(1\.15\)'\s*:\s*'url\(#topo-glow\) brightness\(1\.15\)'\)\s*:\s*undefined/.test(src);
64
+ const sourceAttr = /data-node-chat-ring-brightness=\{isChat \? '1\.15' : '1'\}/.test(src);
65
+
66
+ const results = {
67
+ ring_present: !!rest,
68
+ rest_filter_none: rest?.filter === 'none',
69
+ rest_opacity_zero: parseFloat(rest?.opacity || '1') === 0,
70
+ rest_brightness_1: rest?.brightnessAttr === '1',
71
+ rest_active_false: rest?.activeAttr === 'false',
72
+ transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
73
+ source_filter: sourceFilter,
74
+ source_attr: sourceAttr,
75
+ };
76
+ const ok = Object.values(results).every(Boolean);
77
+ console.log(`${ok ? '✅' : '❌'} 🎯 R615 chat-target ring brightness (NEW chat-target-gated brightness, 100 rounds milestone):`,
78
+ JSON.stringify(results, null, 2),
79
+ `\n rest: ${JSON.stringify(rest)}`);
80
+ process.exit(ok ? 0 : 1);