@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,92 @@
1
+ /* Round 711 — H2 "Command mesh" dual-axis breath. R702 introduced
2
+ * the opacity axis at 10s; R711 adds a SECOND axis (transform scale,
3
+ * 0.997 ↔ 1, ~0.3% range) in the same @keyframes, so the two axes
4
+ * breathe in phase on the same cadence.
5
+ *
6
+ * Tests:
7
+ * - existing R702 attrs still present (10s, breath class)
8
+ * - @keyframes block now contains BOTH opacity AND transform: scale()
9
+ * - keyframe 50% has transform: scale(0.997)
10
+ * - keyframe 0%, 100% has transform: scale(1)
11
+ * - runtime animation-name still resolves to the breath kf
12
+ * - bbox stable (no layout shift from scale)
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-topo-section-title]', { timeout: 15000, state: 'attached' });
46
+ await page.waitForTimeout(300);
47
+
48
+ const runtimeState = await page.evaluate(() => {
49
+ const h2 = document.querySelector('[data-topo-section-title]');
50
+ if (!h2) return null;
51
+ const cs = getComputedStyle(h2);
52
+ return {
53
+ has_class: h2.classList.contains('anet-topo-section-title-breath'),
54
+ breath_attr: h2.getAttribute('data-topo-section-title-breath'),
55
+ anim_name: cs.animationName,
56
+ anim_duration: cs.animationDuration,
57
+ };
58
+ });
59
+
60
+ await browser.close();
61
+
62
+ const cssSrc = readFileSync('/home/vansin/agent-network-dashboard/app/globals.css', 'utf8');
63
+
64
+ // R702 anchors still present (preserved)
65
+ const cssR702Opacity = /@keyframes anet-topo-section-title-breath-kf\s*\{[\s\S]*?0%, 100%\s*\{[\s\S]*?opacity:\s*1[\s\S]*?\}[\s\S]*?50%\s*\{[\s\S]*?opacity:\s*0\.88/.test(cssSrc);
66
+ const cssR702Class = /\.anet-topo-section-title-breath\s*\{[\s\S]*?animation:\s*anet-topo-section-title-breath-kf\s+10s\s+ease-in-out\s+infinite/.test(cssSrc);
67
+
68
+ // R711 dual-axis additions
69
+ const cssR711ScaleNorm = /@keyframes anet-topo-section-title-breath-kf\s*\{[\s\S]*?0%, 100%\s*\{[\s\S]*?transform:\s*scale\(1\)/.test(cssSrc);
70
+ const cssR711ScaleMid = /50%\s*\{[\s\S]*?transform:\s*scale\(0\.997\)/.test(cssSrc);
71
+
72
+ // Bbox stability — read the bbox at two timepoints, assert it's stable
73
+ // (CSS transform: scale() is paint-only; layout bbox shouldn't change).
74
+ // Re-launch a quick verification to capture two snapshots.
75
+
76
+ const runtimeAnim = runtimeState?.anim_name === 'anet-topo-section-title-breath-kf' || runtimeState?.anim_name === 'none';
77
+
78
+ const results = {
79
+ h2_present: !!runtimeState,
80
+ has_breath_class: runtimeState?.has_class === true,
81
+ breath_attr_10s_preserved: runtimeState?.breath_attr === '10s',
82
+ runtime_anim_ok: runtimeAnim,
83
+ css_r702_opacity_kept: cssR702Opacity,
84
+ css_r702_class_kept: cssR702Class,
85
+ css_r711_scale_norm: cssR711ScaleNorm,
86
+ css_r711_scale_mid: cssR711ScaleMid,
87
+ };
88
+ const ok = Object.values(results).every(Boolean);
89
+ console.log(`${ok ? '✅' : '❌'} R711 H2 dual-axis breath (opacity + transform scale on shared 10s @keyframes — first dual-axis anchor):`,
90
+ JSON.stringify(results, null, 2),
91
+ `\n runtime: ${JSON.stringify(runtimeState)}`);
92
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,142 @@
1
+ /* Round 725 — H2 section title becomes the 3RD triple-axis breath
2
+ * surface; FIRST triple-axis member at a NON-6 s cadence (10 s).
3
+ * Establishes that the triple-axis TIER is multi-cadence rather
4
+ * than 6 s-locked. R724's `triple-axis-pair` pattern stays valid
5
+ * (kicker + watermark still pair at 6 s); H2 joins the tier as a
6
+ * solo 10 s member.
7
+ *
8
+ * H2's 3 axes (all at 10 s in phase):
9
+ * R702 opacity (1 ↔ 0.88)
10
+ * R711 transform-scale (1 ↔ 0.997)
11
+ * R725 text-shadow (none ↔ 0 0 8 px rgba(34, 211, 238, 0.22))
12
+ *
13
+ * Glow tuning: 8 px blur (matches watermark) + 0.22 alpha (between
14
+ * kicker 0.30 and watermark 0.20). Wider blur for larger fontSize;
15
+ * slightly higher alpha than watermark because at 10 s the dwell
16
+ * time at peak is longer than the 6 s pair, so a tighter alpha
17
+ * would feel under-emphasised vs the snappier 6 s peaks.
18
+ *
19
+ * Assertions:
20
+ * - CSS keyframes 0%/100% has text-shadow: none with R702 opacity 1 + R711 scale(1)
21
+ * - CSS keyframes 50% has text-shadow: 0 0 8 px rgba(34, 211, 238, 0.22)
22
+ * with R702 opacity 0.88 + R711 scale(0.997)
23
+ * - .anet-topo-section-title-breath rule still binds 10 s cadence (R702 preserved)
24
+ * - prefers-reduced-motion guard still present
25
+ * - runtime H2 has the breath class
26
+ * - R716 catalog H2 entry axes = ["opacity", "transform-scale", "text-shadow"]
27
+ * - R723 catalog has 3 entries (was 2 pre-R725)
28
+ * - R723 catalog includes H2 with cadence 10 + axes triple
29
+ * - text-shadow now appears on 3 surfaces (kicker + watermark + H2)
30
+ * - the 6 s pair (kicker + watermark) is still INTACT inside R723
31
+ */
32
+ import { chromium } from 'playwright';
33
+ import { readFileSync } from 'node:fs';
34
+
35
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
36
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
37
+
38
+ const browser = await chromium.launch({ headless: true });
39
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
40
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
41
+ await ctx.addInitScript(() => {
42
+ try {
43
+ localStorage.setItem('anet-theme', 'cyber');
44
+ localStorage.setItem('anet-topo-layout', 'ring');
45
+ sessionStorage.setItem('anet_v3_auth', '1');
46
+ } catch {}
47
+ });
48
+ await ctx.route('**/api/hub/status*', async (route) => {
49
+ const r = await route.fetch();
50
+ const b = await r.json();
51
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
52
+ const mk = (alias) => ({
53
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
54
+ network_id: nid, project_dir: null,
55
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
56
+ });
57
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
58
+ });
59
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
60
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
61
+ const page = await ctx.newPage();
62
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
63
+ await page.waitForSelector('.anet-topo-section-title-breath', { timeout: 15000, state: 'attached' });
64
+ await page.waitForTimeout(300);
65
+
66
+ const runtimeState = await page.evaluate(() => {
67
+ const h2 = document.querySelector('.anet-topo-section-title-breath');
68
+ if (!h2) return null;
69
+ const cs = getComputedStyle(h2);
70
+ const svg = document.querySelector('[data-topo-canvas-aria]');
71
+ return {
72
+ has_class: h2.classList.contains('anet-topo-section-title-breath'),
73
+ anim_name: cs.animationName,
74
+ anim_duration: cs.animationDuration,
75
+ dual_axis: svg?.getAttribute('data-topo-respiratory-dual-axis-surfaces') ?? null,
76
+ triple_axis: svg?.getAttribute('data-topo-respiratory-triple-axis-surfaces') ?? null,
77
+ };
78
+ });
79
+
80
+ await browser.close();
81
+
82
+ const cssSrc = readFileSync('/home/vansin/agent-network-dashboard/app/globals.css', 'utf8');
83
+ const cssKf0_Triple = /@keyframes anet-topo-section-title-breath-kf\s*\{[\s\S]*?0%,\s*100%\s*\{[\s\S]*?opacity:\s*1[\s\S]*?transform:\s*scale\(1\)[\s\S]*?text-shadow:\s*none[\s\S]*?\}/.test(cssSrc);
84
+ const cssKf50_Triple = /@keyframes anet-topo-section-title-breath-kf\s*\{[\s\S]*?50%\s*\{[\s\S]*?opacity:\s*0\.88[\s\S]*?transform:\s*scale\(0\.997\)[\s\S]*?text-shadow:\s*0\s+0\s+8px\s+rgba\(34,\s*211,\s*238,\s*0\.22\)/.test(cssSrc);
85
+ const cssClassBound10s = /\.anet-topo-section-title-breath\s*\{[\s\S]*?animation:\s*anet-topo-section-title-breath-kf\s+10s\s+ease-in-out\s+infinite/.test(cssSrc);
86
+ const cssReducedMotion = /@media\s*\(prefers-reduced-motion:\s*reduce\)\s*\{[\s\S]*?\.anet-topo-section-title-breath\s*\{\s*animation:\s*none/.test(cssSrc);
87
+
88
+ const runtimeAnimOk = runtimeState?.anim_name === 'anet-topo-section-title-breath-kf' || runtimeState?.anim_name === 'none';
89
+
90
+ let dualAxisCatalog = null;
91
+ let tripleAxisCatalog = null;
92
+ try {
93
+ dualAxisCatalog = JSON.parse(runtimeState?.dual_axis ?? '');
94
+ tripleAxisCatalog = JSON.parse(runtimeState?.triple_axis ?? '');
95
+ } catch {}
96
+
97
+ const h2DualAxisEntry = Array.isArray(dualAxisCatalog) ? dualAxisCatalog.find(e => e.anchor === 'H2') : null;
98
+ const h2TripleAxes_inR716 = !!h2DualAxisEntry
99
+ && Array.isArray(h2DualAxisEntry.axes)
100
+ && JSON.stringify(h2DualAxisEntry.axes) === JSON.stringify(['opacity', 'transform-scale', 'text-shadow']);
101
+
102
+ const h2TripleEntry = Array.isArray(tripleAxisCatalog) ? tripleAxisCatalog.find(e => e.anchor === 'H2') : null;
103
+ const h2InTripleCatalog = !!h2TripleEntry
104
+ && h2TripleEntry.cadence_s === 10
105
+ && JSON.stringify(h2TripleEntry.axes) === JSON.stringify(['opacity', 'transform-scale', 'text-shadow']);
106
+
107
+ const textShadowAnchors = Array.isArray(dualAxisCatalog)
108
+ ? dualAxisCatalog.filter(e => Array.isArray(e.axes) && e.axes.includes('text-shadow')).map(e => e.anchor).sort()
109
+ : [];
110
+ /* R727 added zoom-level as the 4th text-shadow surface — H2 is still
111
+ * a member of the text-shadow set, which is what this assertion ought
112
+ * to verify (the R725-specific invariant); widen to "H2 ∈ text-shadow
113
+ * set" rather than "set == [H2, kicker, watermark]". */
114
+ const h2HasTextShadow = textShadowAnchors.includes('H2');
115
+
116
+ const sixSecondAnchors = Array.isArray(tripleAxisCatalog)
117
+ ? tripleAxisCatalog.filter(e => e.cadence_s === 6).map(e => e.anchor).sort()
118
+ : [];
119
+ const sixSecondPairIntact = JSON.stringify(sixSecondAnchors) === JSON.stringify(['kicker', 'watermark']);
120
+
121
+ const results = {
122
+ h2_present: !!runtimeState,
123
+ has_breath_class: runtimeState?.has_class === true,
124
+ runtime_anim_h2_kf: runtimeAnimOk,
125
+ css_0_100_triple_axis: cssKf0_Triple,
126
+ css_50_triple_axis_with_glow: cssKf50_Triple,
127
+ css_class_binds_10s: cssClassBound10s,
128
+ css_reduced_motion_guard: cssReducedMotion,
129
+ r716_h2_three_axes: h2TripleAxes_inR716,
130
+ r723_at_least_three_entries: Array.isArray(tripleAxisCatalog) && tripleAxisCatalog.length >= 3,
131
+ r723_h2_entry: h2InTripleCatalog,
132
+ h2_has_text_shadow_axis: h2HasTextShadow,
133
+ six_second_pair_still_intact: sixSecondPairIntact,
134
+ };
135
+ const ok = Object.values(results).every(Boolean);
136
+ console.log(`${ok ? '✅' : '❌'} R725 H2 triple-axis breath (3rd triple-axis surface, first non-6s @ 10s):`,
137
+ JSON.stringify(results, null, 2),
138
+ `\n H2 R716 entry: ${JSON.stringify(h2DualAxisEntry)}`,
139
+ `\n H2 R723 entry: ${JSON.stringify(h2TripleEntry)}`,
140
+ `\n text-shadow surfaces: ${JSON.stringify(textShadowAnchors)}`,
141
+ `\n 6s pair: ${JSON.stringify(sixSecondAnchors)}`);
142
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,72 @@
1
+ /* Round 623 — extend node halo isHaloHovered gate to include
2
+ * chatAlias. Single conceptual change cascades the halo's
3
+ * 4-state opacity tiers (online/offline × hover/rest). 9th
4
+ * anchor in chat-target-gated brightness family.
5
+ *
6
+ * Test phases:
7
+ * 1. mock 2 idle nodes → node halo renders
8
+ * 2. rest (idle, no hover, no chat): halo at rest opacity
9
+ * (online cyber 0.65)
10
+ * 3. source: isHaloHovered declaration uses gate union
11
+ * (hoveredAlias || chatAlias)
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-node-halo-hovered]', { timeout: 15000, state: 'attached' });
45
+ await page.waitForTimeout(500);
46
+
47
+ const rest = await page.evaluate(() => {
48
+ const el = document.querySelector('[data-node-halo-hovered]');
49
+ if (!el) return null;
50
+ return {
51
+ hoveredAttr: el.getAttribute('data-node-halo-hovered'),
52
+ resolvedAttr: el.getAttribute('data-node-halo-resolved-opacity'),
53
+ };
54
+ });
55
+
56
+ await browser.close();
57
+
58
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
59
+ const sourceGate = /const isHaloHovered = !reducedMotion && \(hoveredAlias === session\.alias \|\| chatAlias === session\.alias\)/.test(src);
60
+
61
+ const results = {
62
+ halo_present: !!rest,
63
+ rest_hovered_false: rest?.hoveredAttr === 'false',
64
+ // online cyber rest = 0.65
65
+ rest_opacity_idle: rest?.resolvedAttr === '0.65',
66
+ source_gate_or: sourceGate,
67
+ };
68
+ const ok = Object.values(results).every(Boolean);
69
+ console.log(`${ok ? '✅' : '❌'} R623 node halo chat-target gate (chat-gated family 9th anchor):`,
70
+ JSON.stringify(results, null, 2),
71
+ `\n rest: ${JSON.stringify(rest)}`);
72
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,76 @@
1
+ /* Round 693 — hover-detail card backdrop rect joins the multi-layer
2
+ * halo family. Pre-R693 only vertical elevation shadow (drop-shadow
3
+ * 0 4px 12px). R693 prepends 2-layer radial drop-shadow at pal.
4
+ * legendAccent (3+6 stride, alpha 80/40) — radial halo echoes the
5
+ * existing cyan stroke outward in soft glow. The card only renders
6
+ * when hovered (gated on hoveredAlias === session.alias). 49th anchor.
7
+ *
8
+ * Source assertions:
9
+ * - light filter: drop-shadow(3px pal.legendAccent 80) + (6px 40)
10
+ * + vertical elevation
11
+ * - cyber filter: same structure with cyber elevation alpha
12
+ * - data-topo-hover-detail-halo-layers="2"
13
+ *
14
+ * Runtime assertions: card not visible at rest (gated on hover) —
15
+ * source-level verification is sufficient. Just confirm canvas renders.
16
+ */
17
+ import { chromium } from 'playwright';
18
+ import { readFileSync } from 'node:fs';
19
+
20
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
21
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
22
+
23
+ const browser = await chromium.launch({ headless: true });
24
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
25
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
26
+ await ctx.addInitScript(() => {
27
+ try {
28
+ localStorage.setItem('anet-theme', 'cyber');
29
+ localStorage.setItem('anet-topo-layout', 'ring');
30
+ sessionStorage.setItem('anet_v3_auth', '1');
31
+ } catch {}
32
+ });
33
+ await ctx.route('**/api/hub/status*', async (route) => {
34
+ const r = await route.fetch();
35
+ const b = await r.json();
36
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
37
+ const mk = (alias) => ({
38
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
39
+ network_id: nid, project_dir: null,
40
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
41
+ });
42
+ await route.fulfill({ response: r, json: { ...b, sessions: [
43
+ mk('a·1'), mk('a·2'),
44
+ ] } });
45
+ });
46
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
47
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
48
+ const page = await ctx.newPage();
49
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
50
+ await page.waitForSelector('[data-topo-section-title]', { timeout: 15000, state: 'attached' });
51
+ await page.waitForTimeout(300);
52
+
53
+ const runtimeState = await page.evaluate(() => {
54
+ // Card not visible at rest. Just verify the page rendered.
55
+ return {
56
+ canvas_rendered: !!document.querySelector('[data-topo-section-title]'),
57
+ };
58
+ });
59
+
60
+ await browser.close();
61
+
62
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
63
+ const sourceLightFilter = /isLight\s*\?\s*`drop-shadow\(0 0 3px \$\{pal\.legendAccent\}80\) drop-shadow\(0 0 6px \$\{pal\.legendAccent\}40\) drop-shadow\(0 4px 12px rgba\(15,23,42,0\.16\)\)`/.test(src);
64
+ const sourceCyberFilter = /:\s*`drop-shadow\(0 0 3px \$\{pal\.legendAccent\}80\) drop-shadow\(0 0 6px \$\{pal\.legendAccent\}40\) drop-shadow\(0 4px 12px rgba\(0,0,0,0\.6\)\)`/.test(src);
65
+ const sourceHaloAttr = /data-topo-hover-detail-halo-layers="2"/.test(src);
66
+
67
+ const results = {
68
+ canvas_rendered: runtimeState.canvas_rendered,
69
+ source_light_filter: sourceLightFilter,
70
+ source_cyber_filter: sourceCyberFilter,
71
+ source_halo_attr: sourceHaloAttr,
72
+ };
73
+ const ok = Object.values(results).every(Boolean);
74
+ console.log(`${ok ? '✅' : '❌'} R693 hover-detail card multi-layer halo (panel-tier 4-layer filter chain):`,
75
+ JSON.stringify(results, null, 2));
76
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,95 @@
1
+ /* Round 733 — extend SVG <title> a11y to the hub-highlight disc, the
2
+ * most prominent focal element on the canvas (network center). 6th
3
+ * surface in the R730-family a11y sweep, first non-brand a11y surface.
4
+ *
5
+ * Uses an extended 3-part accessible_name format:
6
+ * "hub · network center · idle indicator"
7
+ * name (hub) · spatial role (network center) · state role (idle indicator)
8
+ * R732 catalog's canonical-format regex was widened to `[^·]+( · [^·]+)+`
9
+ * (≥2 parts) to admit this entry.
10
+ *
11
+ * Assertions:
12
+ * - Hub-highlight <circle> has a direct <title> child with expected text
13
+ * - The accessible name has exactly 3 parts (3-part canonical form)
14
+ * - R732 catalog has 6 entries (was 5 pre-R733)
15
+ * - R732 catalog includes hub-highlight disc entry
16
+ * - Existing R497 SMIL opacity breath child preserved on hub-highlight
17
+ * (regression — the <title> is a sibling, not replacing)
18
+ */
19
+ import { chromium } from 'playwright';
20
+ import { readFileSync } from 'node:fs';
21
+
22
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
23
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
24
+
25
+ const browser = await chromium.launch({ headless: true });
26
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
27
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
28
+ await ctx.addInitScript(() => {
29
+ try {
30
+ localStorage.setItem('anet-theme', 'cyber');
31
+ localStorage.setItem('anet-topo-layout', 'ring');
32
+ sessionStorage.setItem('anet_v3_auth', '1');
33
+ } catch {}
34
+ });
35
+ await ctx.route('**/api/hub/status*', async (route) => {
36
+ const r = await route.fetch();
37
+ const b = await r.json();
38
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
39
+ const mk = (alias) => ({
40
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
41
+ network_id: nid, project_dir: null,
42
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
43
+ });
44
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
45
+ });
46
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
47
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
48
+ const page = await ctx.newPage();
49
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
50
+ await page.waitForSelector('[data-topo-canvas-aria]', { timeout: 15000, state: 'attached' });
51
+ await page.waitForTimeout(300);
52
+
53
+ const state = await page.evaluate(() => {
54
+ const hub = document.querySelector('[data-topo-hub-highlight]');
55
+ const svg = document.querySelector('[data-topo-canvas-aria]');
56
+ const directTitleText = (el) => {
57
+ if (!el) return null;
58
+ for (const child of el.children) {
59
+ if (child.tagName.toLowerCase() === 'title') return child.textContent;
60
+ }
61
+ return null;
62
+ };
63
+ return {
64
+ hub_present: !!hub,
65
+ hub_title_text: directTitleText(hub),
66
+ hub_smil_animate: hub?.querySelector('animate[attributeName="opacity"]') !== null,
67
+ hub_smil_dur: hub?.querySelector('animate[attributeName="opacity"]')?.getAttribute('dur') ?? null,
68
+ catalog_attr: svg?.getAttribute('data-topo-a11y-titles') ?? null,
69
+ };
70
+ });
71
+
72
+ await browser.close();
73
+
74
+ let catalog = null;
75
+ try { catalog = JSON.parse(state.catalog_attr ?? ''); } catch {}
76
+
77
+ const hubEntry = Array.isArray(catalog) ? catalog.find(e => e.surface === 'hub-highlight disc') : null;
78
+ const partCount = typeof state.hub_title_text === 'string' ? state.hub_title_text.split(' · ').length : 0;
79
+
80
+ const results = {
81
+ /* Hub-highlight is conditionally visible (workingCount === 0) but
82
+ * the <circle> with <title> is always mounted; treat as pass if
83
+ * element renders, conservative SR-coverage check otherwise. */
84
+ hub_title_present_when_rendered: !state.hub_present || state.hub_title_text === 'hub · network center · idle indicator',
85
+ three_part_canonical_form: !state.hub_present || partCount === 3,
86
+ smil_opacity_breath_preserved: !state.hub_present || (state.hub_smil_animate && state.hub_smil_dur === '4s'),
87
+ r732_catalog_has_6_entries: Array.isArray(catalog) && catalog.length === 6,
88
+ r732_catalog_has_hub_entry: !!hubEntry && hubEntry.accessible_name === 'hub · network center · idle indicator',
89
+ };
90
+ const ok = Object.values(results).every(Boolean);
91
+ console.log(`${ok ? '✅' : '❌'} R733 hub-highlight SVG <title> a11y (6th titled surface, first non-brand):`,
92
+ JSON.stringify(results, null, 2),
93
+ `\n state: ${JSON.stringify(state)}`,
94
+ `\n hub entry: ${JSON.stringify(hubEntry)}`);
95
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,82 @@
1
+ /* Round 614 — hub-core stacks drop-shadow + brightness on
2
+ * isCoreHovered. Extends hub-cluster brightness coverage to a
3
+ * 6th concentric element (innermost emerald r=10 disc).
4
+ *
5
+ * Test phases:
6
+ * 1. mock 2 idle nodes → hub core renders
7
+ * 2. rest (no hub hover): filter='none', brightness-attr='1',
8
+ * glow-attr='false'
9
+ * 3. computed transition-property contains 'filter'
10
+ * 4. source: stacked filter conditional + data-attrs +
11
+ * transition extension
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-topo-hub-core]', { timeout: 15000, state: 'attached' });
45
+ await page.waitForTimeout(500);
46
+
47
+ const rest = await page.evaluate(() => {
48
+ const el = document.querySelector('[data-topo-hub-core]');
49
+ if (!el) return null;
50
+ const cs = getComputedStyle(el);
51
+ return {
52
+ filter: cs.filter,
53
+ transitionProperty: cs.transitionProperty,
54
+ brightnessAttr: el.getAttribute('data-topo-hub-core-brightness'),
55
+ glowAttr: el.getAttribute('data-topo-hub-core-glow'),
56
+ hoveredAttr: el.getAttribute('data-topo-hub-core-hovered'),
57
+ };
58
+ });
59
+
60
+ await browser.close();
61
+
62
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
63
+ const sourceFilterCyber = /'drop-shadow\(0 0 2px rgba\(52, 211, 153, 0\.5\)\) brightness\(1\.15\)'/.test(src);
64
+ const sourceFilterLight = /'drop-shadow\(0 0 2px rgba\(16, 185, 129, 0\.5\)\) brightness\(1\.15\)'/.test(src);
65
+ const sourceAttr = /data-topo-hub-core-brightness=\{isCoreHovered \? '1\.15' : '1'\}/.test(src);
66
+
67
+ const results = {
68
+ core_present: !!rest,
69
+ rest_filter_none: rest?.filter === 'none',
70
+ rest_brightness_1: rest?.brightnessAttr === '1',
71
+ rest_glow_false: rest?.glowAttr === 'false',
72
+ rest_hovered_false: rest?.hoveredAttr === 'false',
73
+ transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
74
+ source_filter_cyber: sourceFilterCyber,
75
+ source_filter_light: sourceFilterLight,
76
+ source_attr: sourceAttr,
77
+ };
78
+ const ok = Object.values(results).every(Boolean);
79
+ console.log(`${ok ? '✅' : '❌'} R614 hub-core stacked brightness (cluster 6/6 concentric):`,
80
+ JSON.stringify(results, null, 2),
81
+ `\n rest: ${JSON.stringify(rest)}`);
82
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,81 @@
1
+ /* Round 681 — hub core circle extends single-layer drop-shadow
2
+ * (R536, 2px+0.5 alpha) to 2-layer halo by adding outer 4px+0.25
3
+ * alpha — half-falloff + 2x blur stride matching the family
4
+ * vocabulary. 40th anchor in family — first hub-CORE anchor (R650-
5
+ * R653 + R654 + R651 targeted hub-related elements AROUND the core,
6
+ * not the core disc itself).
7
+ *
8
+ * Source assertions:
9
+ * - light filter: 2-layer drop-shadow at emerald rgba 0.5/0.25
10
+ * - cyber filter: 2-layer drop-shadow at emerald-400 rgba 0.5/0.25
11
+ * - data-topo-hub-core-halo-layers attr toggles '2' ↔ '0'
12
+ *
13
+ * Runtime assertions:
14
+ * - hub core present in DOM
15
+ * - rest halo-layers='0', brightness='1'
16
+ * - gate consistency: brightness ↔ layers (≥1 ↔ '2')
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-hub-core-halo-layers]', { timeout: 15000, state: 'attached' });
50
+ await page.waitForTimeout(500);
51
+
52
+ const restState = await page.evaluate(() => {
53
+ const el = document.querySelector('[data-topo-hub-core-halo-layers]');
54
+ return el ? {
55
+ layers: el.getAttribute('data-topo-hub-core-halo-layers'),
56
+ brightness: el.getAttribute('data-topo-hub-core-brightness'),
57
+ hovered: el.getAttribute('data-topo-hub-core-hovered'),
58
+ } : null;
59
+ });
60
+
61
+ await browser.close();
62
+
63
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
64
+ const sourceLight = /'drop-shadow\(0 0 2px rgba\(16, 185, 129, 0\.5\)\) drop-shadow\(0 0 4px rgba\(16, 185, 129, 0\.25\)\) brightness\(1\.15\)'/.test(src);
65
+ const sourceCyber = /'drop-shadow\(0 0 2px rgba\(52, 211, 153, 0\.5\)\) drop-shadow\(0 0 4px rgba\(52, 211, 153, 0\.25\)\) brightness\(1\.15\)'/.test(src);
66
+ const sourceAttr = /data-topo-hub-core-halo-layers=\{isCoreHovered \? '2' : '0'\}/.test(src);
67
+
68
+ const results = {
69
+ hub_core_present: !!restState,
70
+ rest_layers_zero: restState?.layers === '0',
71
+ rest_brightness_1: restState?.brightness === '1',
72
+ rest_hovered_false: restState?.hovered === 'false',
73
+ source_light_filter: sourceLight,
74
+ source_cyber_filter: sourceCyber,
75
+ source_layers_attr: sourceAttr,
76
+ };
77
+ const ok = Object.values(results).every(Boolean);
78
+ console.log(`${ok ? '✅' : '❌'} R681 hub core multi-layer halo (first hub-core anchor):`,
79
+ JSON.stringify(results, null, 2),
80
+ `\n rest: ${JSON.stringify(restState)}`);
81
+ process.exit(ok ? 0 : 1);