@sleep2agi/agent-network-dashboard 0.5.3 → 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 (484) 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 +4 -4
  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/{0ph1in3421~o-.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 +6686 -248
  233. package/app/globals.css +897 -7
  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-chrome-hover-text-test.mjs +107 -0
  245. package/scripts/topo-active-links-chip-halo-layers-test.mjs +81 -0
  246. package/scripts/topo-alias-chat-brightness-test.mjs +79 -0
  247. package/scripts/topo-alias-text-halo-layers-test.mjs +98 -0
  248. package/scripts/topo-animation-temporal-modes-catalog-test.mjs +144 -0
  249. package/scripts/topo-avatar-chat-gate-test.mjs +77 -0
  250. package/scripts/topo-avatar-drop-shadow-test.mjs +86 -0
  251. package/scripts/topo-avatar-fallback-hover-test.mjs +104 -0
  252. package/scripts/topo-avatar-fallback-rotate-test.mjs +92 -0
  253. package/scripts/topo-avatar-rotate-test.mjs +85 -0
  254. package/scripts/topo-avatar-scale-test.mjs +89 -0
  255. package/scripts/topo-badge-chat-gate-test.mjs +74 -0
  256. package/scripts/topo-brand-drop-shadow-test.mjs +71 -0
  257. package/scripts/topo-brand-logo-breath-test.mjs +102 -0
  258. package/scripts/topo-brand-logo-halo-layers-test.mjs +85 -0
  259. package/scripts/topo-brand-logo-hover-brightness-test.mjs +105 -0
  260. package/scripts/topo-brand-logo-hover-rotate-test.mjs +93 -0
  261. package/scripts/topo-brand-logo-hover-test.mjs +85 -0
  262. package/scripts/topo-canvas-desc-a11y-test.mjs +87 -0
  263. package/scripts/topo-canvas-entrance-animation-test.mjs +117 -0
  264. package/scripts/topo-canvas-scan-beam-diagonal-test.mjs +148 -0
  265. package/scripts/topo-canvas-scan-beam-test.mjs +109 -0
  266. package/scripts/topo-canvas-scan-beam-vertical-test.mjs +123 -0
  267. package/scripts/topo-card-chat-brightness-test.mjs +86 -0
  268. package/scripts/topo-chat-ring-breath-curve-test.mjs +114 -0
  269. package/scripts/topo-chat-ring-brightness-test.mjs +80 -0
  270. package/scripts/topo-chat-ring-halo-layers-test.mjs +100 -0
  271. package/scripts/topo-chat-ring-r-breath-test.mjs +121 -0
  272. package/scripts/topo-chat-ring-status-halo-test.mjs +106 -0
  273. package/scripts/topo-chat-ring-sw-breath-test.mjs +123 -0
  274. package/scripts/topo-chip-pin-halo-test.mjs +85 -0
  275. package/scripts/topo-chip-row-digit-ls-test.mjs +135 -0
  276. package/scripts/topo-chip-row-member-alias-lit-test.mjs +154 -0
  277. package/scripts/topo-chip-row-tier-glow-brightness-test.mjs +99 -0
  278. package/scripts/topo-chip-row-unit-hover-tracking-test.mjs +124 -0
  279. package/scripts/topo-chrome-control-halo-layers-test.mjs +22 -0
  280. package/scripts/topo-chrome-fullscreen-breath-test.mjs +121 -0
  281. package/scripts/topo-chrome-layout-trailer-breath-test.mjs +86 -0
  282. package/scripts/topo-chrome-nodesize-trailer-breath-test.mjs +86 -0
  283. package/scripts/topo-chrome-reset-breath-test.mjs +115 -0
  284. package/scripts/topo-chrome-strip-entrance-animation-test.mjs +115 -0
  285. package/scripts/topo-chrome-wrapper-halo-test.mjs +83 -0
  286. package/scripts/topo-chrome-zoom-wrapper-breath-test.mjs +85 -0
  287. package/scripts/topo-click-ripple-glow-test.mjs +86 -0
  288. package/scripts/topo-click-ripple-halo-layers-test.mjs +79 -0
  289. package/scripts/topo-click-ripple-sw-test.mjs +110 -0
  290. package/scripts/topo-cluster-count-attr-test.mjs +80 -0
  291. package/scripts/topo-crescent-breath-test.mjs +104 -0
  292. package/scripts/topo-crescent-envelope-breath-test.mjs +103 -0
  293. package/scripts/topo-crescent-recede-test.mjs +111 -0
  294. package/scripts/topo-dense-alias-chat-halo-test.mjs +73 -0
  295. package/scripts/topo-dense-alias-halo-layers-test.mjs +80 -0
  296. package/scripts/topo-dual-axis-surfaces-catalog-test.mjs +94 -0
  297. package/scripts/topo-edge-badge-circle-brightness-test.mjs +82 -0
  298. package/scripts/topo-edge-badge-circle-hot-pulse-test.mjs +100 -0
  299. package/scripts/topo-edge-badge-digit-halo-layers-test.mjs +107 -0
  300. package/scripts/topo-edge-badge-endpoint-gate-test.mjs +94 -0
  301. package/scripts/topo-edge-badge-halo-layers-test.mjs +85 -0
  302. package/scripts/topo-edge-badge-hot-pulse-test.mjs +92 -0
  303. package/scripts/topo-edge-badge-hover-glow-test.mjs +90 -0
  304. package/scripts/topo-edge-badge-text-brightness-test.mjs +83 -0
  305. package/scripts/topo-edge-chat-gate-test.mjs +71 -0
  306. package/scripts/topo-edge-flow-rail-halo-layers-test.mjs +89 -0
  307. package/scripts/topo-edge-particle-brightness-test.mjs +82 -0
  308. package/scripts/topo-edge-particle-halo-layers-test.mjs +91 -0
  309. package/scripts/topo-edge-pill-glow-test.mjs +67 -0
  310. package/scripts/topo-edge-pin-halo-test.mjs +99 -0
  311. package/scripts/topo-edge-visible-brightness-test.mjs +84 -0
  312. package/scripts/topo-edge-visible-halo-layers-test.mjs +87 -0
  313. package/scripts/topo-endpoint-ring-brightness-test.mjs +83 -0
  314. package/scripts/topo-endpoint-ring-flow-halo-test.mjs +107 -0
  315. package/scripts/topo-endpoint-ring-halo-layers-test.mjs +100 -0
  316. package/scripts/topo-filter-pill-glow-test.mjs +90 -0
  317. package/scripts/topo-filter-pill-halo-layers-test.mjs +27 -0
  318. package/scripts/topo-flow-arrow-brightness-test.mjs +82 -0
  319. package/scripts/topo-flow-rail-brightness-test.mjs +80 -0
  320. package/scripts/topo-fullscreen-attr-test.mjs +73 -0
  321. package/scripts/topo-fullscreen-brightness-test.mjs +84 -0
  322. package/scripts/topo-fullscreen-icon-rotate-test.mjs +93 -0
  323. package/scripts/topo-grid-content-bottom-attr-test.mjs +72 -0
  324. package/scripts/topo-group-box-brightness-test.mjs +84 -0
  325. package/scripts/topo-group-box-halo-layers-test.mjs +91 -0
  326. package/scripts/topo-group-chat-gate-test.mjs +77 -0
  327. package/scripts/topo-group-label-brightness-test.mjs +84 -0
  328. package/scripts/topo-group-label-halo-layers-test.mjs +78 -0
  329. package/scripts/topo-group-label-hover-glow-test.mjs +86 -0
  330. package/scripts/topo-group-label-member-alias-hover-test.mjs +125 -0
  331. package/scripts/topo-group-pill-glow-test.mjs +76 -0
  332. package/scripts/topo-group-tint-brightness-test.mjs +82 -0
  333. package/scripts/topo-h2-dual-axis-breath-test.mjs +92 -0
  334. package/scripts/topo-h2-triple-axis-breath-test.mjs +142 -0
  335. package/scripts/topo-halo-chat-gate-test.mjs +72 -0
  336. package/scripts/topo-hover-detail-halo-test.mjs +76 -0
  337. package/scripts/topo-hub-a11y-title-test.mjs +95 -0
  338. package/scripts/topo-hub-core-brightness-test.mjs +82 -0
  339. package/scripts/topo-hub-core-halo-layers-test.mjs +81 -0
  340. package/scripts/topo-hub-digit-brightness-test.mjs +79 -0
  341. package/scripts/topo-hub-digit-halo-layers-test.mjs +76 -0
  342. package/scripts/topo-hub-digit-ls-test.mjs +119 -0
  343. package/scripts/topo-hub-halo-brightness-test.mjs +80 -0
  344. package/scripts/topo-hub-halo-glow-test.mjs +96 -0
  345. package/scripts/topo-hub-halo-halo-layers-test.mjs +76 -0
  346. package/scripts/topo-hub-highlight-brightness-test.mjs +84 -0
  347. package/scripts/topo-hub-highlight-glow-test.mjs +99 -0
  348. package/scripts/topo-hub-highlight-halo-layers-test.mjs +78 -0
  349. package/scripts/topo-hub-highlight-r-test.mjs +112 -0
  350. package/scripts/topo-hub-hover-ring-brightness-test.mjs +79 -0
  351. package/scripts/topo-hub-hover-ring-glow-test.mjs +97 -0
  352. package/scripts/topo-hub-hover-ring-halo-layers-test.mjs +71 -0
  353. package/scripts/topo-hub-spoke-brightness-test.mjs +77 -0
  354. package/scripts/topo-hub-spoke-glow-test.mjs +112 -0
  355. package/scripts/topo-hub-spoke-halo-layers-test.mjs +97 -0
  356. package/scripts/topo-hub-spoke-self-filter-test.mjs +119 -0
  357. package/scripts/topo-kicker-breath-test.mjs +100 -0
  358. package/scripts/topo-kicker-dual-axis-breath-test.mjs +81 -0
  359. package/scripts/topo-kicker-halo-layers-test.mjs +82 -0
  360. package/scripts/topo-kicker-triple-axis-breath-test.mjs +124 -0
  361. package/scripts/topo-label-card-brightness-test.mjs +81 -0
  362. package/scripts/topo-layout-hover-fw-test.mjs +98 -0
  363. package/scripts/topo-layout-toggle-brightness-test.mjs +94 -0
  364. package/scripts/topo-layout-toggle-halo-layers-test.mjs +95 -0
  365. package/scripts/topo-legend-count-brightness-test.mjs +80 -0
  366. package/scripts/topo-legend-count-halo-layers-test.mjs +79 -0
  367. package/scripts/topo-legend-count-letter-spacing-test.mjs +108 -0
  368. package/scripts/topo-legend-label-fw-test.mjs +107 -0
  369. package/scripts/topo-legend-panel-title-breath-test.mjs +86 -0
  370. package/scripts/topo-legend-pin-ring-brightness-test.mjs +82 -0
  371. package/scripts/topo-legend-pin-ring-halo-layers-test.mjs +71 -0
  372. package/scripts/topo-legend-row-count-brightness-test.mjs +85 -0
  373. package/scripts/topo-legend-row-label-glow-test.mjs +102 -0
  374. package/scripts/topo-legend-swatch-glow-test.mjs +109 -0
  375. package/scripts/topo-legend-swatch-member-alias-match-test.mjs +139 -0
  376. package/scripts/topo-legend-tint-brightness-test.mjs +83 -0
  377. package/scripts/topo-legend-trio-halo-layers-test.mjs +22 -0
  378. package/scripts/topo-live-lanes.mjs +48 -0
  379. package/scripts/topo-minimap-container-halo-test.mjs +82 -0
  380. package/scripts/topo-minimap-dot-chat-gate-test.mjs +81 -0
  381. package/scripts/topo-minimap-hover-glow-test.mjs +109 -0
  382. package/scripts/topo-minimap-viewport-brightness-test.mjs +84 -0
  383. package/scripts/topo-minimap-viewport-halo-layers-test.mjs +24 -0
  384. package/scripts/topo-more-footer-brightness-test.mjs +94 -0
  385. package/scripts/topo-node-alias-brightness-test.mjs +84 -0
  386. package/scripts/topo-node-avatar-halo-layers-test.mjs +25 -0
  387. package/scripts/topo-node-hover-ring-halo-layers-test.mjs +70 -0
  388. package/scripts/topo-node-label-card-halo-test.mjs +76 -0
  389. package/scripts/topo-node-sub-text-brightness-test.mjs +88 -0
  390. package/scripts/topo-nodesize-brightness-test.mjs +82 -0
  391. package/scripts/topo-nodesize-halo-layers-test.mjs +89 -0
  392. package/scripts/topo-nodesize-hover-fw-test.mjs +99 -0
  393. package/scripts/topo-orphan-label-opacity-test.mjs +98 -0
  394. package/scripts/topo-overlap-test.mjs +22 -8
  395. package/scripts/topo-panel-count-halo-layers-test.mjs +91 -0
  396. package/scripts/topo-panel-count-hover-ls-test.mjs +87 -0
  397. package/scripts/topo-panel-rect-halo-test.mjs +90 -0
  398. package/scripts/topo-panel-row-brightness-test.mjs +116 -0
  399. package/scripts/topo-panel-title-brightness-test.mjs +98 -0
  400. package/scripts/topo-panel-title-glow-test.mjs +111 -0
  401. package/scripts/topo-panel-titles-dual-axis-breath-test.mjs +94 -0
  402. package/scripts/topo-panel-titles-halo-layers-test.mjs +23 -0
  403. package/scripts/topo-panel-titles-triple-axis-breath-test.mjs +161 -0
  404. package/scripts/topo-pill-x-rotate-test.mjs +96 -0
  405. package/scripts/topo-pip-brightness-test.mjs +85 -0
  406. package/scripts/topo-pressure-bar-halo-layers-test.mjs +19 -0
  407. package/scripts/topo-pressure-seg-glow-test.mjs +92 -0
  408. package/scripts/topo-pressure-seg-member-alias-match-test.mjs +133 -0
  409. package/scripts/topo-pressure-seg-motion-test.mjs +101 -0
  410. package/scripts/topo-r717-scan-beam-pair-pattern-test.mjs +100 -0
  411. package/scripts/topo-r717-triple-axis-pair-pattern-test.mjs +113 -0
  412. package/scripts/topo-r717-triple-axis-tier-pattern-test.mjs +117 -0
  413. package/scripts/topo-recent-count-brightness-test.mjs +84 -0
  414. package/scripts/topo-recent-more-fw-test.mjs +126 -0
  415. package/scripts/topo-recent-more-halo-layers-test.mjs +90 -0
  416. package/scripts/topo-recent-panel-hot-pulse-test.mjs +105 -0
  417. package/scripts/topo-recent-panel-title-breath-test.mjs +91 -0
  418. package/scripts/topo-recent-pip-halo-layers-test.mjs +82 -0
  419. package/scripts/topo-recent-row-chat-gate-test.mjs +75 -0
  420. package/scripts/topo-recent-row-content-lift-test.mjs +140 -0
  421. package/scripts/topo-recent-row-fw-test.mjs +115 -0
  422. package/scripts/topo-recent-row-text-glow-test.mjs +86 -0
  423. package/scripts/topo-recent-row-text-halo-layers-test.mjs +67 -0
  424. package/scripts/topo-recent-tint-brightness-test.mjs +80 -0
  425. package/scripts/topo-recent-ts-brightness-test.mjs +86 -0
  426. package/scripts/topo-reduced-motion-attr-test.mjs +69 -0
  427. package/scripts/topo-reset-brightness-test.mjs +83 -0
  428. package/scripts/topo-reset-icon-hover-scale-test.mjs +102 -0
  429. package/scripts/topo-respiratory-axis-count-stats-test.mjs +154 -0
  430. package/scripts/topo-respiratory-patterns-catalog-test.mjs +112 -0
  431. package/scripts/topo-respiratory-rolodex-test.mjs +83 -0
  432. package/scripts/topo-respiratory-tiers-catalog-test.mjs +119 -0
  433. package/scripts/topo-respiratory-triple-axis-surfaces-catalog-test.mjs +127 -0
  434. package/scripts/topo-runtime-badge-brightness-test.mjs +78 -0
  435. package/scripts/topo-runtime-badge-glow-test.mjs +108 -0
  436. package/scripts/topo-runtime-badge-halo-layers-test.mjs +87 -0
  437. package/scripts/topo-runtime-badge-rotate-test.mjs +85 -0
  438. package/scripts/topo-section-title-breath-test.mjs +83 -0
  439. package/scripts/topo-section-title-halo-layers-test.mjs +88 -0
  440. package/scripts/topo-spoke-chat-gate-test.mjs +72 -0
  441. package/scripts/topo-starfield-hue-test.mjs +109 -0
  442. package/scripts/topo-status-pin-pill-halo-layers-test.mjs +17 -0
  443. package/scripts/topo-status-ring-brightness-test.mjs +84 -0
  444. package/scripts/topo-status-ring-chat-gate-test.mjs +72 -0
  445. package/scripts/topo-status-ring-halo-layers-test.mjs +105 -0
  446. package/scripts/topo-status-ring-status-halo-test.mjs +110 -0
  447. package/scripts/topo-sub-text-chat-brightness-test.mjs +81 -0
  448. package/scripts/topo-svg-title-a11y-r731-test.mjs +93 -0
  449. package/scripts/topo-svg-title-a11y-test.mjs +88 -0
  450. package/scripts/topo-title-block-entrance-animation-test.mjs +127 -0
  451. package/scripts/topo-title-block-envelope-breath-test.mjs +87 -0
  452. package/scripts/topo-titleblock-h2-hover-fw-test.mjs +109 -0
  453. package/scripts/topo-titleblock-h2-hover-tracking-test.mjs +128 -0
  454. package/scripts/topo-titleblock-kicker-hover-test.mjs +134 -0
  455. package/scripts/topo-tree-diag.mjs +95 -0
  456. package/scripts/topo-vendor-chip-glow-test.mjs +97 -0
  457. package/scripts/topo-vendor-chip-halo-layers-test.mjs +18 -0
  458. package/scripts/topo-vendor-chip-pin-halo-test.mjs +88 -0
  459. package/scripts/topo-vendor-count-suffix-halo-layers-test.mjs +79 -0
  460. package/scripts/topo-vendor-distribution-wrapper-halo-test.mjs +93 -0
  461. package/scripts/topo-vendor-letter-halo-layers-test.mjs +93 -0
  462. package/scripts/topo-vendor-pill-glow-test.mjs +98 -0
  463. package/scripts/topo-watermark-breath-test.mjs +100 -0
  464. package/scripts/topo-watermark-dual-axis-breath-test.mjs +88 -0
  465. package/scripts/topo-watermark-envelope-breath-test.mjs +88 -0
  466. package/scripts/topo-watermark-recede-test.mjs +114 -0
  467. package/scripts/topo-watermark-triple-axis-breath-test.mjs +129 -0
  468. package/scripts/topo-working-online-chip-halo-layers-test.mjs +94 -0
  469. package/scripts/topo-zoom-buttons-brightness-test.mjs +94 -0
  470. package/scripts/topo-zoom-in-out-halo-layers-test.mjs +97 -0
  471. package/scripts/topo-zoom-level-breath-test.mjs +87 -0
  472. package/scripts/topo-zoom-level-brightness-test.mjs +83 -0
  473. package/scripts/topo-zoom-level-color-test.mjs +105 -0
  474. package/scripts/topo-zoom-level-dual-axis-breath-test.mjs +83 -0
  475. package/scripts/topo-zoom-level-halo-layers-test.mjs +78 -0
  476. package/scripts/topo-zoom-level-triple-axis-breath-test.mjs +148 -0
  477. package/.next/static/chunks/0fuba20p57-zo.js +0 -1
  478. package/.next/static/chunks/0m.1mvl~t.avc.css +0 -2
  479. package/.next/static/chunks/10cj-86disers.js +0 -1
  480. package/.next/static/chunks/158h2g7f-nxbt.js +0 -4
  481. /package/.next/server/chunks/{[externals]__11vad82._.js.map → 0ykm__next-internal_server_app_api_hub_upload_route_actions_03_eqnf.js.map} +0 -0
  482. /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → xq88BMF7fMUHWh10yaKTn}/_buildManifest.js +0 -0
  483. /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → xq88BMF7fMUHWh10yaKTn}/_clientMiddlewareManifest.js +0 -0
  484. /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → xq88BMF7fMUHWh10yaKTn}/_ssgManifest.js +0 -0
@@ -0,0 +1,125 @@
1
+ /* Round 561 verification: group-label opacity lifts to 1.0 when
2
+ * operator hovers a NODE ALIAS that's a member of this group.
3
+ * 4th anchor in the inspection-overrides-encoding family.
4
+ *
5
+ * Mock: 3 'alpha-' prefix sessions (1 group) + 3 standalone
6
+ * (orphan band). Hover the alpha-1 node → group 'alpha·' label
7
+ * should lift opacity 0.55 → 1.0.
8
+ *
9
+ * Test phases:
10
+ * 1. confirm grid layout active
11
+ * 2. rest: group 'alpha·' opacity = 0.55
12
+ * 3. hover a node from alpha group → 'alpha·' opacity = 1.0,
13
+ * member-alias-hovered attr = 'true'
14
+ * 4. orphan group should NOT lift (its members aren't hovered)
15
+ * 5. source-side regex confirms wiring
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', 'grid');
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, status = 'idle') => ({
38
+ alias, status, 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
+ // alpha-group has WORKING members → ants run at rest. Hovering a
43
+ // member alias should keep ants running (R561 refined gate).
44
+ await route.fulfill({ response: r, json: { ...b, sessions: [
45
+ mk('alpha·1', 'working'), mk('alpha·2', 'working'), mk('alpha·3'),
46
+ mk('foo'), mk('bar'), mk('baz'),
47
+ ] } });
48
+ });
49
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
50
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
51
+ const page = await ctx.newPage();
52
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
53
+ await page.waitForSelector('[data-group-label]', { timeout: 15000 });
54
+ await page.waitForTimeout(500);
55
+
56
+ const probeGroups = async () => {
57
+ return page.evaluate(() => {
58
+ const els = Array.from(document.querySelectorAll('[data-group-label]'));
59
+ return els.map(el => {
60
+ // Find the matching outer <g> with data-group-box-live to read the
61
+ // ants-gate refinement. The box rect sits within the same parent
62
+ // group as the label — both nest under the per-band <g> in the
63
+ // groupBoxes.map() loop.
64
+ const parent = el.closest('g')?.parentElement || null;
65
+ const boxRect = parent?.querySelector('[data-group-box-live]') || null;
66
+ return {
67
+ key: el.getAttribute('data-group-label'),
68
+ orphan: el.getAttribute('data-group-label-orphan') === 'true',
69
+ opacityAttr: el.getAttribute('data-group-label-opacity'),
70
+ computedOpacity: getComputedStyle(el).opacity,
71
+ memberAliasHovered: el.getAttribute('data-group-label-member-alias-hovered') === 'true',
72
+ boxLive: boxRect?.getAttribute('data-group-box-live'),
73
+ };
74
+ });
75
+ });
76
+ };
77
+
78
+ const restGroups = await probeGroups();
79
+
80
+ // Hover a node from the alpha group.
81
+ await page.hover('g[data-node="alpha·1"]');
82
+ await page.waitForTimeout(400);
83
+ const hoverGroups = await probeGroups();
84
+
85
+ await browser.close();
86
+
87
+ const restAlpha = restGroups.find(g => g.key === 'alpha·');
88
+ const restOrphan = restGroups.find(g => g.orphan);
89
+ const hoverAlpha = hoverGroups.find(g => g.key === 'alpha·');
90
+ const hoverOrphan = hoverGroups.find(g => g.orphan);
91
+
92
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
93
+ const sourceFlag = /const isMemberAliasHovered = !!hoveredAlias && groupKeys\[hoveredAlias\] === box\.key;/.test(src);
94
+ const sourceOpacity = /opacity=\{isPinned \|\| isHovered \|\| isMemberAliasHovered \? 1 : box\.isOrphan \? 0\.4 : 0\.55\}/.test(src);
95
+ const sourceAttr = /data-group-label-member-alias-hovered=/.test(src);
96
+
97
+ const results = {
98
+ alpha_present: !!restAlpha,
99
+ orphan_present: !!restOrphan,
100
+ rest_alpha_opacity_0_55: restAlpha?.computedOpacity === '0.55',
101
+ rest_alpha_attr_not_hovered: restAlpha?.memberAliasHovered === false,
102
+ rest_orphan_opacity_0_4: restOrphan?.computedOpacity === '0.4',
103
+ hover_alpha_opacity_1: hoverAlpha?.computedOpacity === '1',
104
+ hover_alpha_attr_hovered: hoverAlpha?.memberAliasHovered === true,
105
+ hover_orphan_opacity_unchanged: hoverOrphan?.computedOpacity === '0.4',
106
+ hover_orphan_attr_not_hovered: hoverOrphan?.memberAliasHovered === false,
107
+ // R561 ants-gate refinement: alpha group has working members.
108
+ // Rest: ants run ('true'). Pre-R561 hovering a member alias
109
+ // halted ants ('false'); R561 keeps them running on member-alias
110
+ // hover ('true'). Direct label hover would still halt — not
111
+ // exercised here.
112
+ rest_alpha_ants_running: restAlpha?.boxLive === 'true',
113
+ hover_alpha_ants_keep_running: hoverAlpha?.boxLive === 'true',
114
+ source_flag: sourceFlag,
115
+ source_opacity: sourceOpacity,
116
+ source_attr: sourceAttr,
117
+ };
118
+ const ok = Object.values(results).every(Boolean);
119
+ console.log(`${ok ? '✅' : '❌'} R561 group-label member-alias-hover opacity lift (4th anchor in inspection-overrides-encoding):`,
120
+ JSON.stringify(results, null, 2),
121
+ '\n rest alpha:', JSON.stringify(restAlpha),
122
+ '\n rest orphan:', JSON.stringify(restOrphan),
123
+ '\n hover alpha:', JSON.stringify(hoverAlpha),
124
+ '\n hover orphan:', JSON.stringify(hoverOrphan));
125
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,76 @@
1
+ /* Round 544 verification: group filter pill gains cyan-accent drop-
2
+ * shadow when rendered (pin-active visual). Sibling to R543 status pill.
3
+ *
4
+ * Test strategy: source-canonical because group-label click via Playwright
5
+ * is impractical (banked R538/R544 lesson — SVG hit-test intercept).
6
+ * Source regex confirms the wiring; rest-state DOM probe confirms pill
7
+ * is absent when unpinned (baseline behavior unchanged).
8
+ *
9
+ * Test phases:
10
+ * 1. unpinned (default): no [data-active-filter="group"] element
11
+ * 2. source-side regex confirms filter wired with pal.legendAccent
12
+ * via color-mix 60% syntax
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', 'grid');
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, status) => ({
35
+ alias, status, 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: [
40
+ mk('alpha·1', 'working'), mk('alpha·2', 'working'),
41
+ mk('beta·1', 'idle'), mk('beta·2', 'idle'),
42
+ ] } });
43
+ });
44
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
45
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
46
+ const page = await ctx.newPage();
47
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
48
+ await page.waitForSelector('[data-group-label]', { timeout: 15000 });
49
+ await page.waitForTimeout(500);
50
+
51
+ const unpinned = await page.evaluate(() =>
52
+ document.querySelector('[data-active-filter="group"]') !== null
53
+ );
54
+
55
+ await browser.close();
56
+
57
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
58
+ const sourceFilterWired =
59
+ /filter: `drop-shadow\(0 0 3px color-mix\(in srgb, \$\{pal\.legendAccent\} 60%, transparent\)\)`,/.test(src);
60
+
61
+ // Confirm we edited the GROUP pill specifically (data-active-filter="group")
62
+ // — look for the filter wiring within the group-pill scope by matching
63
+ // the surrounding setPinnedGroup handler.
64
+ const groupPillScope = src.match(/onClick=\{\(\) => setPinnedGroup\(null\)\}[\s\S]{0,2500}/)?.[0] || '';
65
+ const groupPillHasFilter = /filter: `drop-shadow\(0 0 3px color-mix\(in srgb, \$\{pal\.legendAccent\} 60%, transparent\)\)`,/.test(groupPillScope);
66
+
67
+ const results = {
68
+ unpinned_pill_absent: unpinned === false,
69
+ source_filter_wired: sourceFilterWired,
70
+ source_group_pill_scope: groupPillHasFilter,
71
+ };
72
+ const ok = Object.values(results).every(Boolean);
73
+ console.log(`${ok ? '✅' : '❌'} R544 group filter pill glow (source-canonical):`,
74
+ JSON.stringify(results, null, 2),
75
+ '\n unpinned absent:', unpinned);
76
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,82 @@
1
+ /* Round 610 — group label tint rect gains filter brightness(1.15)
2
+ * on (pinnedGroup === box.key || hoveredGroupLabel === box.key).
3
+ * Same gate as the existing fill swap.
4
+ *
5
+ * Test phases:
6
+ * 1. mock 2 prefix-group nodes → grid layout renders tint rects
7
+ * 2. rest: filter='none', brightness-attr='1', tinted='none'
8
+ * 3. computed transition-property contains 'filter'
9
+ * 4. source: filter conditional + data-attr + transition extension
10
+ */
11
+ import { chromium } from 'playwright';
12
+ import { readFileSync } from 'node:fs';
13
+
14
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
15
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
16
+
17
+ const browser = await chromium.launch({ headless: true });
18
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
19
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
20
+ await ctx.addInitScript(() => {
21
+ try {
22
+ localStorage.setItem('anet-theme', 'cyber');
23
+ localStorage.setItem('anet-topo-layout', 'grid');
24
+ sessionStorage.setItem('anet_v3_auth', '1');
25
+ } catch {}
26
+ });
27
+ await ctx.route('**/api/hub/status*', async (route) => {
28
+ const r = await route.fetch();
29
+ const b = await r.json();
30
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
31
+ const mk = (alias) => ({
32
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
33
+ network_id: nid, project_dir: null,
34
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
35
+ });
36
+ await route.fulfill({ response: r, json: { ...b, sessions: [
37
+ mk('alpha·1'), mk('alpha·2'), mk('beta·1'), mk('beta·2'),
38
+ ] } });
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-group-label-tint-brightness]', { timeout: 15000, state: 'attached' });
45
+ await page.waitForTimeout(500);
46
+
47
+ const rest = await page.evaluate(() => {
48
+ const el = document.querySelector('[data-group-label-tint-brightness]');
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-group-label-tint-brightness'),
55
+ tintedAttr: el.getAttribute('data-group-label-tinted'),
56
+ transitionAttr: el.getAttribute('data-group-label-tint-transition'),
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: \(pinnedGroup === box\.key \|\| hoveredGroupLabel === box\.key\)\s*\?\s*'brightness\(1\.15\)'\s*:\s*undefined/.test(src);
64
+ const sourceAttr = /data-group-label-tint-brightness=\{\(pinnedGroup === box\.key \|\| hoveredGroupLabel === box\.key\) \? '1\.15' : '1'\}/.test(src);
65
+ const sourceTransition = /transition: 'fill 200ms ease-out, opacity 200ms ease-out, x 200ms ease-out, width 200ms ease-out, rx 200ms ease-out, filter 200ms ease-out'/.test(src);
66
+
67
+ const results = {
68
+ tint_present: !!rest,
69
+ rest_filter_none: rest?.filter === 'none',
70
+ rest_brightness_1: rest?.brightnessAttr === '1',
71
+ rest_tinted_none: rest?.tintedAttr === 'none',
72
+ transition_attr: rest?.transitionAttr === '200ms',
73
+ transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
74
+ source_filter: sourceFilter,
75
+ source_attr: sourceAttr,
76
+ source_transition: sourceTransition,
77
+ };
78
+ const ok = Object.values(results).every(Boolean);
79
+ console.log(`${ok ? '✅' : '❌'} R610 group-label tint rect brightness (pin/hover panel tier):`,
80
+ JSON.stringify(results, null, 2),
81
+ `\n rest: ${JSON.stringify(rest)}`);
82
+ process.exit(ok ? 0 : 1);
@@ -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);