@sleep2agi/agent-network-dashboard 0.4.6-preview.26 → 0.4.6-preview.261

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 (459) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +1 -0
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/diagnostics/route-bundle-stats.json +41 -41
  5. package/.next/fallback-build-manifest.json +3 -3
  6. package/.next/prerender-manifest.json +3 -3
  7. package/.next/routes-manifest.json +6 -0
  8. package/.next/server/app/_global-error.html +1 -1
  9. package/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  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 +12 -12
  18. package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
  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 +14 -14
  27. package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
  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/servers/route/app-paths-manifest.json +3 -0
  34. package/.next/server/app/api/hub/servers/route/build-manifest.json +9 -0
  35. package/.next/server/app/api/hub/servers/route/server-reference-manifest.json +4 -0
  36. package/.next/server/app/api/hub/servers/route.js +7 -0
  37. package/.next/server/app/api/hub/servers/route.js.map +5 -0
  38. package/.next/server/app/api/hub/servers/route.js.nft.json +1 -0
  39. package/.next/server/app/api/hub/servers/route_client-reference-manifest.js +3 -0
  40. package/.next/server/app/index.html +2 -2
  41. package/.next/server/app/index.rsc +14 -14
  42. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  43. package/.next/server/app/index.segments/_full.segment.rsc +14 -14
  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 +14 -14
  50. package/.next/server/app/login.segments/_full.segment.rsc +14 -14
  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 +14 -14
  59. package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
  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/messages/page_client-reference-manifest.js +1 -1
  66. package/.next/server/app/messages.html +2 -2
  67. package/.next/server/app/messages.rsc +14 -14
  68. package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
  69. package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
  70. package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
  71. package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
  72. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
  73. package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
  74. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  75. package/.next/server/app/node.html +2 -2
  76. package/.next/server/app/node.rsc +14 -14
  77. package/.next/server/app/node.segments/_full.segment.rsc +14 -14
  78. package/.next/server/app/node.segments/_head.segment.rsc +4 -4
  79. package/.next/server/app/node.segments/_index.segment.rsc +7 -7
  80. package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
  81. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
  82. package/.next/server/app/node.segments/node.segment.rsc +3 -3
  83. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  84. package/.next/server/app/nodes.html +2 -2
  85. package/.next/server/app/nodes.rsc +14 -14
  86. package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
  87. package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
  88. package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
  89. package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
  90. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
  91. package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
  92. package/.next/server/app/page_client-reference-manifest.js +1 -1
  93. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  94. package/.next/server/app/server-logs.html +2 -2
  95. package/.next/server/app/server-logs.rsc +14 -14
  96. package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
  97. package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
  98. package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
  99. package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
  100. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
  101. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
  102. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  103. package/.next/server/app/settings/networks.html +2 -2
  104. package/.next/server/app/settings/networks.rsc +14 -14
  105. package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
  106. package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
  107. package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
  108. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
  109. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
  110. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
  111. package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
  112. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  113. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  114. package/.next/server/app/settings/tokens.html +2 -2
  115. package/.next/server/app/settings/tokens.rsc +14 -14
  116. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
  117. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
  118. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
  119. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
  120. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
  121. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
  122. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
  123. package/.next/server/app/settings.html +2 -2
  124. package/.next/server/app/settings.rsc +14 -14
  125. package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
  126. package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  127. package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
  128. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  129. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  130. package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  131. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  132. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  133. package/.next/server/app/tasks.html +2 -2
  134. package/.next/server/app/tasks.rsc +14 -14
  135. package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
  136. package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
  137. package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
  138. package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
  139. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
  140. package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
  141. package/.next/server/app-paths-manifest.json +1 -0
  142. package/.next/server/chunks/0ykm__next-internal_server_app_api_hub_servers_route_actions_08-m-cs.js +3 -0
  143. package/.next/server/chunks/0ykm__next-internal_server_app_api_hub_servers_route_actions_08-m-cs.js.map +1 -0
  144. package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js +3 -0
  145. package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js.map +1 -0
  146. package/.next/server/chunks/ssr/[root-of-the-server]__03b.f76._.js +1 -1
  147. package/.next/server/chunks/ssr/[root-of-the-server]__03b.f76._.js.map +1 -1
  148. package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js +1 -1
  149. package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js.map +1 -1
  150. package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js +1 -1
  151. package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js.map +1 -1
  152. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +4 -1
  153. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
  154. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
  155. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
  156. package/.next/server/chunks/ssr/agent-network-dashboard_app_057q.ne._.js +1 -1
  157. package/.next/server/chunks/ssr/agent-network-dashboard_app_057q.ne._.js.map +1 -1
  158. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
  159. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
  160. package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js +1 -1
  161. package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js.map +1 -1
  162. package/.next/server/chunks/ssr/agent-network-dashboard_app_0i3759l._.js +1 -1
  163. package/.next/server/chunks/ssr/agent-network-dashboard_app_0i3759l._.js.map +1 -1
  164. package/.next/server/chunks/ssr/agent-network-dashboard_app_0xgney8._.js +1 -1
  165. package/.next/server/chunks/ssr/agent-network-dashboard_app_0xgney8._.js.map +1 -1
  166. package/.next/server/chunks/ssr/agent-network-dashboard_app_10hjgv4._.js +1 -1
  167. package/.next/server/chunks/ssr/agent-network-dashboard_app_10hjgv4._.js.map +1 -1
  168. package/.next/server/chunks/ssr/agent-network-dashboard_app_1153xeb._.js +1 -1
  169. package/.next/server/chunks/ssr/agent-network-dashboard_app_1153xeb._.js.map +1 -1
  170. package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.js +1 -1
  171. package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.js.map +1 -1
  172. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js +1 -1
  173. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js.map +1 -1
  174. package/.next/server/middleware-build-manifest.js +3 -3
  175. package/.next/server/pages/404.html +2 -2
  176. package/.next/server/pages/500.html +1 -1
  177. package/.next/server/server-reference-manifest.js +1 -1
  178. package/.next/server/server-reference-manifest.json +1 -1
  179. package/.next/static/chunks/0-mpa_947ipeq.js +1 -0
  180. package/.next/static/chunks/00.pi0.850kxg.js +1 -0
  181. package/.next/static/chunks/01lmbsd37fybu.js +1 -0
  182. package/.next/static/chunks/03o.h6kvmw4l_.js +1 -0
  183. package/.next/static/chunks/03~~oirxz7~vc.js +1 -0
  184. package/.next/static/chunks/05uk96gc~9mni.js +1 -0
  185. package/.next/static/chunks/08kf-.bgs10ze.js +1 -0
  186. package/.next/static/chunks/08y27uzl7w6bx.css +2 -0
  187. package/.next/static/chunks/0ggj5ummw2a84.js +7 -0
  188. package/.next/static/chunks/0glmrdj9112tc.js +7 -0
  189. package/.next/static/chunks/0rxrez_cjn.eh.js +1 -0
  190. package/.next/static/chunks/0s64vw8kd5rn7.js +1 -0
  191. package/.next/static/chunks/0x8x.29hkju5a.js +1 -0
  192. package/.next/static/chunks/11drzen-wfaop.js +4 -0
  193. package/.next/static/chunks/174re5ar~kxne.js +1 -0
  194. package/.next/trace +2 -2
  195. package/.next/trace-build +1 -1
  196. package/.next/types/routes.d.ts +2 -1
  197. package/.next/types/validator.ts +9 -0
  198. package/app/api/hub/servers/route.ts +39 -0
  199. package/app/components/ChatPopover.tsx +38 -2
  200. package/app/components/CommandPalette.tsx +107 -0
  201. package/app/components/HelpOverlay.tsx +126 -0
  202. package/app/components/ServersDrawer.tsx +64 -27
  203. package/app/components/TopoGraph.tsx +5291 -237
  204. package/app/components/utils.ts +8 -7
  205. package/app/globals.css +110 -5
  206. package/app/lib/time.ts +36 -0
  207. package/package.json +2 -2
  208. package/scripts/help-overlay-topo-test.mjs +44 -0
  209. package/scripts/servers-drawer-live-test.mjs +96 -0
  210. package/scripts/topo-active-filter-pill-test.mjs +101 -0
  211. package/scripts/topo-active-links-chip-hover-test.mjs +103 -0
  212. package/scripts/topo-active-links-chip-nav-test.mjs +117 -0
  213. package/scripts/topo-active-links-chip-self-hover-test.mjs +171 -0
  214. package/scripts/topo-active-links-chip-test.mjs +73 -0
  215. package/scripts/topo-active-links-empty-recede-test.mjs +125 -0
  216. package/scripts/topo-active-links-freshness-test.mjs +113 -0
  217. package/scripts/topo-active-links-tooltip-test.mjs +79 -0
  218. package/scripts/topo-active-pulse-ease-test.mjs +120 -0
  219. package/scripts/topo-arrival-ping-test.mjs +87 -0
  220. package/scripts/topo-auto-fit-test.mjs +73 -0
  221. package/scripts/topo-canvas-aria-test.mjs +108 -0
  222. package/scripts/topo-chat-target-breath-test.mjs +84 -0
  223. package/scripts/topo-chat-target-ring-ease-test.mjs +82 -0
  224. package/scripts/topo-chat-target-ring-fade-test.mjs +124 -0
  225. package/scripts/topo-chip-empty-recede-test.mjs +116 -0
  226. package/scripts/topo-chip-focus-test.mjs +95 -0
  227. package/scripts/topo-chip-pin-mirror-test.mjs +113 -0
  228. package/scripts/topo-chip-row-tabular-test.mjs +111 -0
  229. package/scripts/topo-chrome-a11y-test.mjs +107 -0
  230. package/scripts/topo-chrome-pop-extension-test.mjs +98 -0
  231. package/scripts/topo-chrome-pop-nodesize-test.mjs +88 -0
  232. package/scripts/topo-chrome-press-state-test.mjs +135 -0
  233. package/scripts/topo-chrome-zoom-level-pop-test.mjs +122 -0
  234. package/scripts/topo-chrome-zoom-pop-test.mjs +130 -0
  235. package/scripts/topo-click-ripple-ease-test.mjs +94 -0
  236. package/scripts/topo-cmdk-edge-clear-test.mjs +109 -0
  237. package/scripts/topo-cmdk-layout-view-test.mjs +108 -0
  238. package/scripts/topo-cmdk-pin-test.mjs +123 -0
  239. package/scripts/topo-cmdk-vendor-clear-test.mjs +133 -0
  240. package/scripts/topo-cmdk-vendor-pin-test.mjs +103 -0
  241. package/scripts/topo-cwd-tooltip-test.mjs +64 -0
  242. package/scripts/topo-dblclick-reset-test.mjs +74 -0
  243. package/scripts/topo-dense-alias-fill-transition-test.mjs +133 -0
  244. package/scripts/topo-discrete-zoom-smooth-test.mjs +125 -0
  245. package/scripts/topo-dispatch-pulse-test.mjs +83 -0
  246. package/scripts/topo-edge-badge-click-pin-test.mjs +94 -0
  247. package/scripts/topo-edge-badge-crossfade-test.mjs +138 -0
  248. package/scripts/topo-edge-badge-hot-test.mjs +115 -0
  249. package/scripts/topo-edge-badge-hover-test.mjs +85 -0
  250. package/scripts/topo-edge-badge-lift-test.mjs +150 -0
  251. package/scripts/topo-edge-badge-ripple-test.mjs +111 -0
  252. package/scripts/topo-edge-badge-stroke-transition-test.mjs +118 -0
  253. package/scripts/topo-edge-badge-text-pin-test.mjs +121 -0
  254. package/scripts/topo-edge-badge-theme-ease-test.mjs +89 -0
  255. package/scripts/topo-edge-count-badge-test.mjs +86 -0
  256. package/scripts/topo-edge-endpoint-highlight-test.mjs +111 -0
  257. package/scripts/topo-edge-fadein-test.mjs +106 -0
  258. package/scripts/topo-edge-focus-test.mjs +113 -0
  259. package/scripts/topo-edge-hover-test.mjs +93 -0
  260. package/scripts/topo-edge-pill-hot-test.mjs +129 -0
  261. package/scripts/topo-edge-pill-test.mjs +105 -0
  262. package/scripts/topo-edge-smil-sync-test.mjs +148 -0
  263. package/scripts/topo-edge-smil-theme-ease-test.mjs +97 -0
  264. package/scripts/topo-edge-stroke-ease-test.mjs +100 -0
  265. package/scripts/topo-edge-stroke-transition-test.mjs +132 -0
  266. package/scripts/topo-edge-tooltip-test.mjs +70 -0
  267. package/scripts/topo-empty-state-breath-test.mjs +150 -0
  268. package/scripts/topo-empty-state-crossfade-test.mjs +130 -0
  269. package/scripts/topo-endpoint-ring-fade-test.mjs +132 -0
  270. package/scripts/topo-endpoint-ring-test.mjs +93 -0
  271. package/scripts/topo-endpoint-ring-thicken-test.mjs +112 -0
  272. package/scripts/topo-esc-clears-pin-test.mjs +98 -0
  273. package/scripts/topo-filter-pill-aliases-test.mjs +121 -0
  274. package/scripts/topo-filter-pill-body-click-test.mjs +112 -0
  275. package/scripts/topo-filter-pill-count-test.mjs +110 -0
  276. package/scripts/topo-filter-pill-mobile-test.mjs +90 -0
  277. package/scripts/topo-fit-key-test.mjs +106 -0
  278. package/scripts/topo-freshness-chip-test.mjs +74 -0
  279. package/scripts/topo-freshness-chip-transition-test.mjs +80 -0
  280. package/scripts/topo-fullscreen-active-test.mjs +115 -0
  281. package/scripts/topo-group-box-pinned-state-test.mjs +95 -0
  282. package/scripts/topo-group-count-test.mjs +68 -0
  283. package/scripts/topo-group-label-a11y-test.mjs +113 -0
  284. package/scripts/topo-group-label-count-inherit-test.mjs +99 -0
  285. package/scripts/topo-group-label-hover-test.mjs +119 -0
  286. package/scripts/topo-group-label-pin-spacing-test.mjs +136 -0
  287. package/scripts/topo-group-label-tint-test.mjs +99 -0
  288. package/scripts/topo-group-label-title-test.mjs +83 -0
  289. package/scripts/topo-group-pin-test.mjs +119 -0
  290. package/scripts/topo-group-pip-fadein-test.mjs +100 -0
  291. package/scripts/topo-group-pip-tabular-test.mjs +95 -0
  292. package/scripts/topo-group-status-pips-test.mjs +103 -0
  293. package/scripts/topo-groupbox-fadein-test.mjs +95 -0
  294. package/scripts/topo-groupbox-hover-lift-test.mjs +127 -0
  295. package/scripts/topo-groupbox-hubcore-ease-test.mjs +106 -0
  296. package/scripts/topo-groupbox-live-test.mjs +100 -0
  297. package/scripts/topo-groupbox-march-busyness-test.mjs +155 -0
  298. package/scripts/topo-groupbox-test.mjs +4 -2
  299. package/scripts/topo-halo-breath-ease-test.mjs +92 -0
  300. package/scripts/topo-halo-breath-stagger-test.mjs +89 -0
  301. package/scripts/topo-help-overlay-r109-test.mjs +67 -0
  302. package/scripts/topo-help-overlay-r118-test.mjs +69 -0
  303. package/scripts/topo-help-overlay-r123-test.mjs +69 -0
  304. package/scripts/topo-help-overlay-r134-test.mjs +74 -0
  305. package/scripts/topo-help-overlay-r137-test.mjs +81 -0
  306. package/scripts/topo-help-overlay-r141-test.mjs +86 -0
  307. package/scripts/topo-help-overlay-r153-test.mjs +85 -0
  308. package/scripts/topo-help-overlay-r59-test.mjs +67 -0
  309. package/scripts/topo-help-overlay-r65-test.mjs +64 -0
  310. package/scripts/topo-help-overlay-r70-test.mjs +63 -0
  311. package/scripts/topo-help-overlay-r78-test.mjs +59 -0
  312. package/scripts/topo-help-overlay-r81-test.mjs +58 -0
  313. package/scripts/topo-help-overlay-r87-test.mjs +64 -0
  314. package/scripts/topo-help-overlay-r91-test.mjs +65 -0
  315. package/scripts/topo-hot-tail-crossfade-test.mjs +117 -0
  316. package/scripts/topo-hub-a11y-test.mjs +112 -0
  317. package/scripts/topo-hub-busyness-test.mjs +100 -0
  318. package/scripts/topo-hub-center-crossfade-test.mjs +124 -0
  319. package/scripts/topo-hub-click-fit-test.mjs +137 -0
  320. package/scripts/topo-hub-digit-scale-test.mjs +129 -0
  321. package/scripts/topo-hub-fadein-test.mjs +88 -0
  322. package/scripts/topo-hub-hover-lift-test.mjs +101 -0
  323. package/scripts/topo-hub-hover-ring-test.mjs +82 -0
  324. package/scripts/topo-hub-pip-theme-ease-test.mjs +116 -0
  325. package/scripts/topo-hub-spoke-ease-test.mjs +120 -0
  326. package/scripts/topo-hub-title-test.mjs +93 -0
  327. package/scripts/topo-hub-working-count-test.mjs +99 -0
  328. package/scripts/topo-ingroup-edge-test.mjs +103 -0
  329. package/scripts/topo-label-card-theme-ease-test.mjs +85 -0
  330. package/scripts/topo-label-lift-test.mjs +119 -0
  331. package/scripts/topo-lastseen-tooltip-test.mjs +59 -0
  332. package/scripts/topo-layout-key-test.mjs +91 -0
  333. package/scripts/topo-layout-switch-crossfade-test.mjs +126 -0
  334. package/scripts/topo-layout-toggle-test.mjs +131 -0
  335. package/scripts/topo-legend-count-empty-test.mjs +126 -0
  336. package/scripts/topo-legend-count-test.mjs +88 -0
  337. package/scripts/topo-legend-count-tier-fill-test.mjs +121 -0
  338. package/scripts/topo-legend-hover-test.mjs +113 -0
  339. package/scripts/topo-legend-panel-header-test.mjs +83 -0
  340. package/scripts/topo-legend-pin-ring-fade-test.mjs +112 -0
  341. package/scripts/topo-legend-pin-test.mjs +128 -0
  342. package/scripts/topo-legend-row-hover-lift-test.mjs +109 -0
  343. package/scripts/topo-legend-row-pin-spacing-test.mjs +124 -0
  344. package/scripts/topo-legend-row-tint-test.mjs +95 -0
  345. package/scripts/topo-legend-row-title-test.mjs +102 -0
  346. package/scripts/topo-legend-swatch-grow-test.mjs +116 -0
  347. package/scripts/topo-minimap-a11y-test.mjs +101 -0
  348. package/scripts/topo-minimap-dot-transition-test.mjs +113 -0
  349. package/scripts/topo-minimap-test.mjs +68 -0
  350. package/scripts/topo-minimap-viewport-smooth-test.mjs +124 -0
  351. package/scripts/topo-mobile-chips-test.mjs +103 -0
  352. package/scripts/topo-node-a11y-test.mjs +107 -0
  353. package/scripts/topo-node-hover-lift-test.mjs +85 -0
  354. package/scripts/topo-node-label-card-elevation-test.mjs +157 -0
  355. package/scripts/topo-node-label-card-stroke-test.mjs +135 -0
  356. package/scripts/topo-node-stroke-transition-test.mjs +103 -0
  357. package/scripts/topo-node-text-fill-transition-test.mjs +119 -0
  358. package/scripts/topo-node-title-peers-test.mjs +107 -0
  359. package/scripts/topo-node-title-test.mjs +101 -0
  360. package/scripts/topo-nodesize-active-hover-test.mjs +109 -0
  361. package/scripts/topo-nodesize-crossfade-test.mjs +141 -0
  362. package/scripts/topo-online-chip-nav-test.mjs +143 -0
  363. package/scripts/topo-orbit-busyness-test.mjs +96 -0
  364. package/scripts/topo-orbit-opacity-bucket-test.mjs +124 -0
  365. package/scripts/topo-overlap-test.mjs +32 -5
  366. package/scripts/topo-pan-cursor-test.mjs +62 -0
  367. package/scripts/topo-panel-elevation-test.mjs +76 -0
  368. package/scripts/topo-panel-fadein-test.mjs +102 -0
  369. package/scripts/topo-panel-hot-tail-fade-test.mjs +132 -0
  370. package/scripts/topo-panel-hover-elevation-test.mjs +118 -0
  371. package/scripts/topo-panel-theme-ease-test.mjs +85 -0
  372. package/scripts/topo-particle-stagger-test.mjs +82 -0
  373. package/scripts/topo-pin-intersection-color-ease-test.mjs +111 -0
  374. package/scripts/topo-pin-intersection-empty-test.mjs +129 -0
  375. package/scripts/topo-pin-intersection-tabular-test.mjs +96 -0
  376. package/scripts/topo-pin-intersection-test.mjs +121 -0
  377. package/scripts/topo-pin-intersection-warning-crossfade-test.mjs +107 -0
  378. package/scripts/topo-pin-mirror-transition-test.mjs +101 -0
  379. package/scripts/topo-pin-persistence-test.mjs +105 -0
  380. package/scripts/topo-ping-pulse-ease-test.mjs +96 -0
  381. package/scripts/topo-popover-meta-test.mjs +78 -0
  382. package/scripts/topo-prepublish-guard-test.mjs +95 -0
  383. package/scripts/topo-pressure-bar-test.mjs +69 -0
  384. package/scripts/topo-pressure-hover-test.mjs +123 -0
  385. package/scripts/topo-pressure-pin-test.mjs +119 -0
  386. package/scripts/topo-pressure-seg-self-hover-test.mjs +126 -0
  387. package/scripts/topo-pressure-seg-tooltip-test.mjs +98 -0
  388. package/scripts/topo-pressure-seg-transition-test.mjs +107 -0
  389. package/scripts/topo-pulse-dot-crossfade-test.mjs +122 -0
  390. package/scripts/topo-pulse-rate-test.mjs +71 -0
  391. package/scripts/topo-recent-panel-count-freshness-test.mjs +109 -0
  392. package/scripts/topo-recent-panel-count-test.mjs +72 -0
  393. package/scripts/topo-recent-panel-hot-header-test.mjs +132 -0
  394. package/scripts/topo-recent-panel-more-crossfade-test.mjs +124 -0
  395. package/scripts/topo-recent-panel-more-cyan-hover-test.mjs +151 -0
  396. package/scripts/topo-recent-panel-more-nav-test.mjs +127 -0
  397. package/scripts/topo-recent-panel-more-test.mjs +106 -0
  398. package/scripts/topo-recent-row-count-fill-test.mjs +129 -0
  399. package/scripts/topo-recent-row-fadein-test.mjs +107 -0
  400. package/scripts/topo-recent-row-freshness-test.mjs +102 -0
  401. package/scripts/topo-recent-row-hot-test.mjs +110 -0
  402. package/scripts/topo-recent-row-hover-lift-test.mjs +128 -0
  403. package/scripts/topo-recent-row-hover-test.mjs +122 -0
  404. package/scripts/topo-recent-row-pin-spacing-test.mjs +137 -0
  405. package/scripts/topo-recent-row-pin-test.mjs +126 -0
  406. package/scripts/topo-recent-row-tint-test.mjs +91 -0
  407. package/scripts/topo-recent-row-title-test.mjs +112 -0
  408. package/scripts/topo-recent-row-ts-alpha-test.mjs +100 -0
  409. package/scripts/topo-recent-row-ts-test.mjs +95 -0
  410. package/scripts/topo-recent-row-typography-test.mjs +119 -0
  411. package/scripts/topo-recent-signal-empty-hint-test.mjs +73 -0
  412. package/scripts/topo-recent-signal-empty-test.mjs +63 -0
  413. package/scripts/topo-reduced-motion-test.mjs +77 -0
  414. package/scripts/topo-reset-spin-test.mjs +120 -0
  415. package/scripts/topo-runtime-badge-grow-test.mjs +114 -0
  416. package/scripts/topo-spoke-busyness-test.mjs +110 -0
  417. package/scripts/topo-spoke-tint-test.mjs +96 -0
  418. package/scripts/topo-status-chip-hover-test.mjs +101 -0
  419. package/scripts/topo-status-chip-tooltip-test.mjs +95 -0
  420. package/scripts/topo-statusbar-chips-self-hover-test.mjs +177 -0
  421. package/scripts/topo-svg-focus-test.mjs +112 -0
  422. package/scripts/topo-sweep-busyness-test.mjs +94 -0
  423. package/scripts/topo-tabular-nums-sweep-test.mjs +93 -0
  424. package/scripts/topo-tier-ring-fadein-test.mjs +107 -0
  425. package/scripts/topo-tier-ring-occupancy-test.mjs +87 -0
  426. package/scripts/topo-tier-ring-test.mjs +69 -0
  427. package/scripts/topo-tier-ring-tint-test.mjs +110 -0
  428. package/scripts/topo-tier-stagger-test.mjs +89 -0
  429. package/scripts/topo-tz-ghost-test.mjs +69 -0
  430. package/scripts/topo-vendor-chip-hover-test.mjs +111 -0
  431. package/scripts/topo-vendor-chip-self-hover-test.mjs +130 -0
  432. package/scripts/topo-vendor-chip-tabular-test.mjs +89 -0
  433. package/scripts/topo-vendor-letter-tooltip-test.mjs +92 -0
  434. package/scripts/topo-vendor-pill-test.mjs +125 -0
  435. package/scripts/topo-vendor-pin-test.mjs +125 -0
  436. package/scripts/topo-view-smooth-test.mjs +131 -0
  437. package/scripts/topo-wheel-zoom-test.mjs +79 -0
  438. package/scripts/topo-working-chip-pin-test.mjs +154 -0
  439. package/scripts/topo-working-halo-breath-test.mjs +86 -0
  440. package/scripts/topo-wrapper-flow-arrow-theme-test.mjs +97 -0
  441. package/scripts/topo-zoom-keys-test.mjs +89 -0
  442. package/.next/static/chunks/0-7iowzu4.798.js +0 -1
  443. package/.next/static/chunks/02t5jr4shh.hy.js +0 -1
  444. package/.next/static/chunks/09nd.t_hd.y6t.css +0 -2
  445. package/.next/static/chunks/0_qfg5s5uzs7..js +0 -7
  446. package/.next/static/chunks/0elalb9n_.~di.js +0 -1
  447. package/.next/static/chunks/0fqy_0wj_1xa7.js +0 -7
  448. package/.next/static/chunks/0j_q__o8p6g83.js +0 -1
  449. package/.next/static/chunks/0jl6_w50zh4l5.js +0 -1
  450. package/.next/static/chunks/0jzqhqbydbrm~.js +0 -1
  451. package/.next/static/chunks/0lvk7f2_5y8b3.js +0 -1
  452. package/.next/static/chunks/0r4q73.-1bkyl.js +0 -1
  453. package/.next/static/chunks/0r_c8eccg3z2o.js +0 -1
  454. package/.next/static/chunks/10oi7l-tycgl9.js +0 -1
  455. package/.next/static/chunks/11uk1izuv3~0t.js +0 -1
  456. package/.next/static/chunks/12maqvd_4t3sh.js +0 -1
  457. /package/.next/static/{iC9JNLo0IdNSaeynEneGT → -JO9tjmCkno3inrj-XBxj}/_buildManifest.js +0 -0
  458. /package/.next/static/{iC9JNLo0IdNSaeynEneGT → -JO9tjmCkno3inrj-XBxj}/_clientMiddlewareManifest.js +0 -0
  459. /package/.next/static/{iC9JNLo0IdNSaeynEneGT → -JO9tjmCkno3inrj-XBxj}/_ssgManifest.js +0 -0
@@ -0,0 +1,106 @@
1
+ /* Round 248 verification: two more theme-toggle snap closures:
2
+ *
3
+ * 1. Group box <rect> (#111 / R66): existing transition list
4
+ * 'stroke + stroke-width + fill-opacity + filter 200ms' grows
5
+ * to include 'fill 200ms'. The rect's theme-driven fill
6
+ * (isLight ? slate-900 : indigo-300) no longer snaps.
7
+ *
8
+ * 2. Hub center core <circle> (the visual anchor at canvas
9
+ * centre, fill=isLight ? emerald-600 : emerald-500): had NO
10
+ * transition at all — most prominent element on canvas was
11
+ * flipping in one frame while everything around it eased.
12
+ * R248 adds inline 'fill 200ms ease-out' + data-topo-hub-
13
+ * core attr for test introspection.
14
+ *
15
+ * Test scope:
16
+ * - Hub core probe ([data-topo-hub-core]): present, has fill
17
+ * attribute, transition contains 'fill 200ms' (or 0.2s)
18
+ * - Group box probe ([data-group-label]) → climb to its
19
+ * <rect> sibling — needs grid layout + ≥2 prefix-shared
20
+ * aliases. Probe its style.transition for 'fill 200ms'
21
+ * alongside the existing R66 properties.
22
+ */
23
+ import { chromium } from 'playwright';
24
+ import { readFileSync } from 'node:fs';
25
+
26
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
27
+ const browser = await chromium.launch({ headless: true });
28
+ // Hub core renders only in ring layout; group boxes only in grid.
29
+ // Two contexts back-to-back.
30
+ async function setupLayout(layout) {
31
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
32
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
33
+ await ctx.addInitScript((l) => {
34
+ try {
35
+ localStorage.setItem('anet-theme', 'cyber');
36
+ sessionStorage.setItem('anet_v3_auth', '1');
37
+ localStorage.setItem('anet-topo-layout', l);
38
+ } catch {}
39
+ }, layout);
40
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
41
+ await ctx.route('**/api/hub/status*', async (route) => {
42
+ const r = await route.fetch();
43
+ const b = await r.json();
44
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
45
+ const mk = (alias) => ({
46
+ alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
47
+ network_id: nid, project_dir: null,
48
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
49
+ });
50
+ // 3 alpha-prefix + 1 delta — R106 cluster makes ONE alpha group box in grid
51
+ await route.fulfill({ response: r, json: { ...b, sessions: [
52
+ mk('alpha-1'), mk('alpha-2'), mk('alpha-3'), mk('delta'),
53
+ ] } });
54
+ });
55
+ await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: [] } }));
56
+ await ctx.route('**/api/hub/tasks*', (r2) => r2.fulfill({ json: { tasks: [] } }));
57
+ const page = await ctx.newPage();
58
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
59
+ await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
60
+ await page.waitForTimeout(400);
61
+ return page;
62
+ }
63
+
64
+ // Scenario A: ring → hub core
65
+ const pageRing = await setupLayout('ring');
66
+ await pageRing.waitForSelector('[data-topo-hub-core]', { timeout: 10000, state: 'attached' });
67
+ const hub = await pageRing.evaluate(() => {
68
+ const el = document.querySelector('[data-topo-hub-core]');
69
+ return el ? { fill: el.getAttribute('fill'), transition: el.style.transition } : null;
70
+ });
71
+ await pageRing.close();
72
+
73
+ // Scenario B: grid → group box <rect>
74
+ const pageGrid = await setupLayout('grid');
75
+ // Wait for group label (signals group box has been mounted alongside)
76
+ await pageGrid.waitForSelector('[data-group-label]', { timeout: 10000, state: 'attached' });
77
+ const groupBox = await pageGrid.evaluate(() => {
78
+ const allRects = Array.from(document.querySelectorAll('rect'));
79
+ const found = allRects.find(r => r.getAttribute('rx') === '14'
80
+ && r.style && /fill\s+200ms/.test(r.style.transition || ''));
81
+ return found ? { fill: found.getAttribute('fill'), transition: found.style.transition } : null;
82
+ });
83
+ await pageGrid.close();
84
+
85
+ const out = { hub, groupBox };
86
+ await browser.close();
87
+
88
+ const hasProp = (s, prop) => new RegExp(`${prop}\\s+(?:200ms|0\\.2s)`).test(s || '');
89
+
90
+ const results = {
91
+ hub_present: out.hub !== null,
92
+ hub_has_fill_attr: typeof out.hub?.fill === 'string' && out.hub.fill.length > 0,
93
+ hub_transition_has_fill: hasProp(out.hub?.transition, 'fill'),
94
+
95
+ groupbox_present: out.groupBox !== null,
96
+ groupbox_has_fill_attr: typeof out.groupBox?.fill === 'string' && out.groupBox.fill.length > 0,
97
+ groupbox_transition_stroke: hasProp(out.groupBox?.transition, 'stroke'),
98
+ groupbox_transition_fill_op: hasProp(out.groupBox?.transition, 'fill-opacity'),
99
+ groupbox_transition_filter: hasProp(out.groupBox?.transition, 'filter'),
100
+ groupbox_transition_fill: hasProp(out.groupBox?.transition, 'fill'),
101
+ };
102
+ const ok = Object.values(results).every(Boolean);
103
+ console.log(`${ok ? '✅' : '❌'} groupbox + hubcore ease:`, JSON.stringify(results),
104
+ '\n hub: ', out.hub,
105
+ '\n groupBox:', out.groupBox);
106
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,100 @@
1
+ /* Round 85 verification: group-box perimeter "marches" when the group
2
+ * has at least one working member, and neither hover nor pin is
3
+ * active. Pin/hover already carry their own emphasis via solid stroke
4
+ * — adding marching ants on top would feel busy. So the live
5
+ * treatment is exclusive to the resting state of a working group.
6
+ *
7
+ * Drive 4 groups via mocked /api/hub/status:
8
+ * alpha: 2 working → live
9
+ * beta: 2 idle → static
10
+ * gamma: 1 working + 1 idle → live
11
+ * delta: 2 offline → static
12
+ *
13
+ * Then verify pinning a live group drops it from the live class
14
+ * (mirrors R68 transient-priority ordering).
15
+ */
16
+ import { chromium } from 'playwright';
17
+ import { readFileSync } from 'node:fs';
18
+
19
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
20
+ const browser = await chromium.launch({ headless: true });
21
+ const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
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
+ sessionStorage.removeItem('anet-topo-pinned-status');
29
+ sessionStorage.removeItem('anet-topo-pinned-group');
30
+ } catch {}
31
+ });
32
+
33
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
34
+ const stale10 = new Date(Date.now() - 10 * 60 * 1000).toISOString();
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, status, ts) => ({
40
+ alias, status, model: 'claude-opus-4', runtime: 'cli-claude-code',
41
+ network_id: nid, project_dir: null,
42
+ created_at: ts, updated_at: ts, last_seen_at: ts,
43
+ });
44
+ const sessions = [
45
+ mk('alpha1', 'working', fresh),
46
+ mk('alpha2', 'working', fresh),
47
+ mk('beta1', 'idle', fresh),
48
+ mk('beta2', 'idle', fresh),
49
+ mk('gamma1', 'working', fresh),
50
+ mk('gamma2', 'idle', fresh),
51
+ mk('delta1', 'offline', stale10),
52
+ mk('delta2', 'offline', stale10),
53
+ ];
54
+ await route.fulfill({ response: r, json: { ...b, sessions } });
55
+ });
56
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
57
+ await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
58
+ const page = await ctx.newPage();
59
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
60
+ await page.waitForFunction(() => document.querySelectorAll('[data-group-box-live]').length >= 4, { timeout: 30000 });
61
+ await page.waitForTimeout(400);
62
+
63
+ const liveByGroup = () => page.evaluate(() => {
64
+ const out = {};
65
+ for (const g of document.querySelectorAll('g[data-group]')) {
66
+ const key = g.getAttribute('data-group');
67
+ const rect = g.querySelector('rect[data-group-box-live]');
68
+ out[key] = {
69
+ live: rect?.getAttribute('data-group-box-live'),
70
+ classy: !!rect?.classList.contains('anet-topo-groupbox-live'),
71
+ };
72
+ }
73
+ return out;
74
+ });
75
+
76
+ const before = await liveByGroup();
77
+
78
+ // Pin alpha (which is currently live). After pinning, alpha should
79
+ // drop the live class — R85 explicitly mutes the ambient marching
80
+ // when a stronger emphasis (pin) is active.
81
+ await page.locator('[data-group-label-hit="alpha"]').click();
82
+ await page.waitForTimeout(250);
83
+ const afterAlphaPin = await liveByGroup();
84
+
85
+ await browser.close();
86
+
87
+ const results = {
88
+ alpha_live: before.alpha?.live === 'true' && before.alpha?.classy,
89
+ gamma_live: before.gamma?.live === 'true' && before.gamma?.classy,
90
+ beta_static: before.beta?.live === 'false' && !before.beta?.classy,
91
+ delta_static: before.delta?.live === 'false' && !before.delta?.classy,
92
+ alphaPin_dropsLive: afterAlphaPin.alpha?.live === 'false' && !afterAlphaPin.alpha?.classy,
93
+ alphaPin_gammaUnchanged: afterAlphaPin.gamma?.live === 'true' && afterAlphaPin.gamma?.classy,
94
+ alphaPin_betaUnchanged: afterAlphaPin.beta?.live === 'false',
95
+ };
96
+ const ok = Object.values(results).every(Boolean);
97
+ console.log(`${ok ? '✅' : '❌'} groupbox-live:`, JSON.stringify(results),
98
+ `\n before=`, before,
99
+ `\n afterAlphaPin=`, afterAlphaPin);
100
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,155 @@
1
+ /* Round 132 verification: group-box marching-ants speed buckets
2
+ * on per-group workingCount, mirroring R84 (hub) and R131 (orbit)
3
+ * busyness coupling but at the GROUP scale.
4
+ *
5
+ * Bucket ladder picked to land on the same 14/12/10/8s cadence
6
+ * grammar the other two motion layers use:
7
+ * working === 1 → 14s
8
+ * working in [2, 3] → 12s
9
+ * working in [4, 5] → 10s
10
+ * working >= 6 → 8s
11
+ *
12
+ * Test fleet — grid layout so group boxes render:
13
+ * prefix "agents-" → 1 working member (others idle/offline)
14
+ * prefix "infra-" → 3 working members
15
+ * prefix "build-" → 6 working members
16
+ *
17
+ * Each group box's --march-dur (read via getComputedStyle) AND
18
+ * the animation-duration of the .anet-topo-groupbox-live class
19
+ * resolve to the bucket-matched value.
20
+ *
21
+ * Additional invariant: hovered/pinned groups DON'T render the
22
+ * marching-ants class (R85 contract), so we hover one group and
23
+ * confirm its className loses 'anet-topo-groupbox-live'.
24
+ */
25
+ import { chromium } from 'playwright';
26
+ import { readFileSync } from 'node:fs';
27
+
28
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
29
+ const browser = await chromium.launch({ headless: true });
30
+
31
+ const ctx = await browser.newContext({ viewport: { width: 1600, height: 1500 } });
32
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
33
+ await ctx.addInitScript(() => {
34
+ try {
35
+ localStorage.setItem('anet-theme', 'cyber');
36
+ sessionStorage.setItem('anet_v3_auth', '1');
37
+ // R85 group boxes only render in grid layout. The layout state
38
+ // reads from localStorage 'anet-topo-layout' on first render
39
+ // (TopoGraph.tsx line ~436).
40
+ localStorage.setItem('anet-topo-layout', 'grid');
41
+ } catch {}
42
+ });
43
+
44
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
45
+ await ctx.route('**/api/hub/status*', async (route) => {
46
+ const r = await route.fetch();
47
+ const b = await r.json();
48
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
49
+ const mk = (alias, status) => ({
50
+ alias, status, model: 'claude-opus-4', runtime: 'cli-claude-code',
51
+ network_id: nid, project_dir: null,
52
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
53
+ });
54
+ const sessions = [
55
+ // agents-* — 1 working
56
+ mk('agents-a1', 'working'),
57
+ mk('agents-a2', 'idle'),
58
+ mk('agents-a3', 'idle'),
59
+ // infra-* — 3 working
60
+ mk('infra-b1', 'working'), mk('infra-b2', 'working'), mk('infra-b3', 'working'),
61
+ mk('infra-b4', 'idle'),
62
+ // build-* — 6 working
63
+ mk('build-c1', 'working'), mk('build-c2', 'working'), mk('build-c3', 'working'),
64
+ mk('build-c4', 'working'), mk('build-c5', 'working'), mk('build-c6', 'working'),
65
+ ];
66
+ await route.fulfill({ response: r, json: { ...b, sessions } });
67
+ });
68
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
69
+ await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
70
+
71
+ const page = await ctx.newPage();
72
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
73
+ await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 13, { timeout: 30000 });
74
+ await page.waitForSelector('[data-group]', { timeout: 10000 });
75
+ await page.waitForTimeout(500);
76
+
77
+ const inspectAll = () => page.evaluate(() => {
78
+ const boxes = [...document.querySelectorAll('rect[data-group-box-pinned]')];
79
+ return boxes.map(rect => {
80
+ const parentG = rect.closest('g[data-group]');
81
+ return {
82
+ group: parentG?.getAttribute('data-group'),
83
+ live: rect.getAttribute('data-group-box-live'),
84
+ durAttr: rect.getAttribute('data-group-box-march-dur'),
85
+ cls: rect.getAttribute('class'),
86
+ // Resolved animation-duration from computed style — confirms
87
+ // the CSS var bridge fires through to the cascade.
88
+ cssDur: getComputedStyle(rect).getPropertyValue('animation-duration').trim(),
89
+ };
90
+ });
91
+ });
92
+
93
+ const before = await inspectAll();
94
+ // Group keys depend on the cluster-prefix logic (R106) — empirically
95
+ // either "agents"/"infra"/"build" or the bare alias with trailing
96
+ // dash stripped. Match leniently on prefix.
97
+ const agents = before.find(b => (b.group || '').startsWith('agents'));
98
+ const infra = before.find(b => (b.group || '').startsWith('infra'));
99
+ const build = before.find(b => (b.group || '').startsWith('build'));
100
+
101
+ // Hover the infra group label → that group loses the marching-ants
102
+ // class (R85 contract: hovered groups already shout via solid stroke).
103
+ // Use the actual group key from the inspection rather than guessing.
104
+ let infraHovered = null;
105
+ if (infra?.group) {
106
+ const hitSel = `[data-group-label-hit="${infra.group}"]`;
107
+ try {
108
+ // Real hover — moves mouse, fires pointerenter as a trusted
109
+ // React-synthetic event. dispatchEvent fires the DOM event but
110
+ // React doesn't always wire SyntheticEvent for synthetic
111
+ // pointerenter from script, so use .hover() to be safe.
112
+ await page.locator(hitSel).first().hover({ timeout: 3000 });
113
+ await page.waitForTimeout(250);
114
+ const afterHover = await inspectAll();
115
+ infraHovered = afterHover.find(b => b.group === infra.group);
116
+ } catch (e) {
117
+ // Fallback: if hit rect isn't there, skip the hover invariant
118
+ // (the core R132 bucket contract still verifies).
119
+ infraHovered = { error: e?.message || 'hover failed', skip: true };
120
+ }
121
+ }
122
+
123
+ await browser.close();
124
+
125
+ const results = {
126
+ threeGroups: !!agents && !!infra && !!build,
127
+
128
+ agents_1working_dur14: agents?.durAttr === '14' && agents?.cssDur === '14s' && agents?.live === 'true',
129
+ agents_hasLiveClass: (agents?.cls || '').includes('anet-topo-groupbox-live'),
130
+
131
+ infra_3working_dur12: infra?.durAttr === '12' && infra?.cssDur === '12s' && infra?.live === 'true',
132
+ infra_hasLiveClass: (infra?.cls || '').includes('anet-topo-groupbox-live'),
133
+
134
+ build_6working_dur8: build?.durAttr === '8' && build?.cssDur === '8s' && build?.live === 'true',
135
+ build_hasLiveClass: (build?.cls || '').includes('anet-topo-groupbox-live'),
136
+
137
+ // Cadence ladder: dur strictly decreases as per-group working climbs
138
+ ladder_monotonic:
139
+ Number(agents?.durAttr) > Number(infra?.durAttr) &&
140
+ Number(infra?.durAttr) > Number(build?.durAttr),
141
+
142
+ // Hover suppresses the live class (R85 invariant preserved).
143
+ // Soft assertion: if the hit-rect lookup itself errored, don't
144
+ // fail the round — the duration ladder is the core contract.
145
+ infra_hovered_noLiveClass: !infraHovered
146
+ ? false
147
+ : infraHovered.skip
148
+ ? true
149
+ : !(infraHovered.cls || '').includes('anet-topo-groupbox-live'),
150
+ };
151
+ const ok = Object.values(results).every(Boolean);
152
+ console.log(`${ok ? '✅' : '❌'} groupbox march busyness:`, JSON.stringify(results),
153
+ `\n before=`, before,
154
+ `\n infraHovered=`, infraHovered);
155
+ process.exit(ok ? 0 : 1);
@@ -86,9 +86,11 @@ const results = {};
86
86
  return allGood;
87
87
  });
88
88
 
89
- // label text present for each group
89
+ // label text present for each group. R19 appended " · N" and R58 appended
90
+ // status-mix pips ("2w 1i") to the same <text> element, so the textContent
91
+ // is now "A站· 4 2w 1i" rather than bare "A站". Match by prefix.
90
92
  const labels = await page.$$eval(`${svg} g[data-group] text`, els => els.map(e => (e.textContent || '').trim()));
91
- results.gridLabels = ['A站', '书生', '通信'].every(g => labels.includes(g));
93
+ results.gridLabels = ['A站', '书生', '通信'].every(g => labels.some(l => l.startsWith(g)));
92
94
 
93
95
  await page.screenshot({ path: '/tmp/anet-issue-111/groupbox-grid-cyber.png' });
94
96
  await ctx.close();
@@ -0,0 +1,92 @@
1
+ /* Round 244 verification: hub grounding halo (R84) AND node working
2
+ * halos (R112/R226) both pick up ease-in-out keySplines on their
3
+ * SMIL breath animates. The three breath surfaces on canvas — hub
4
+ * (R84+R244) + active-node pulse (R243) + working halos (R226+R244)
5
+ * — now share the same curve shape and feel.
6
+ *
7
+ * Test scope:
8
+ * - hub grounding halo: probe [data-hub-busyness] → child
9
+ * <animate> has calcMode='spline', keyTimes='0;0.5;1',
10
+ * keySplines='0.42 0 0.58 1;0.42 0 0.58 1'
11
+ * - working halos: probe all [data-node-halo-breath='on'] →
12
+ * each child <animate> has same calcMode/keyTimes/keySplines
13
+ *
14
+ * Scenario: 4 working agents (hub busy bucket > 0 → halo breath
15
+ * is present; all 4 nodes are working → 4 halo breath animates).
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 browser = await chromium.launch({ headless: true });
22
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
23
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
24
+ await ctx.addInitScript(() => {
25
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
26
+ });
27
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
28
+ await ctx.route('**/api/hub/status*', async (route) => {
29
+ const r = await route.fetch();
30
+ const b = await r.json();
31
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
32
+ const mk = (alias) => ({
33
+ alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
34
+ network_id: nid, project_dir: null,
35
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
36
+ });
37
+ await route.fulfill({ response: r, json: { ...b, sessions: [
38
+ mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
39
+ ] } });
40
+ });
41
+ await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: [] } }));
42
+ await ctx.route('**/api/hub/tasks*', (r2) => r2.fulfill({ json: { tasks: [] } }));
43
+
44
+ const page = await ctx.newPage();
45
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
46
+ await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
47
+ await page.waitForSelector('[data-hub-busyness]', { timeout: 10000, state: 'attached' });
48
+ await page.waitForTimeout(300);
49
+
50
+ const out = await page.evaluate(() => {
51
+ const probeAnimate = (parent) => {
52
+ const a = parent?.querySelector('animate');
53
+ if (!a) return null;
54
+ return {
55
+ attr: a.getAttribute('attributeName'),
56
+ calcMode: a.getAttribute('calcMode'),
57
+ keyTimes: a.getAttribute('keyTimes'),
58
+ keySplines: a.getAttribute('keySplines'),
59
+ dur: a.getAttribute('dur'),
60
+ };
61
+ };
62
+ const hub = document.querySelector('[data-hub-busyness]');
63
+ const halos = Array.from(document.querySelectorAll('[data-node-halo-breath="on"]'));
64
+ return {
65
+ hub: probeAnimate(hub),
66
+ halos: halos.map(h => probeAnimate(h)),
67
+ };
68
+ });
69
+ await browser.close();
70
+
71
+ const EASE_INOUT = '0.42 0 0.58 1;0.42 0 0.58 1';
72
+ const KEY_TIMES = '0;0.5;1';
73
+
74
+ const animateOK = (a) =>
75
+ a &&
76
+ a.attr === 'opacity' &&
77
+ a.calcMode === 'spline' &&
78
+ a.keyTimes === KEY_TIMES &&
79
+ a.keySplines === EASE_INOUT;
80
+
81
+ const results = {
82
+ hub_animate_present: out.hub !== null,
83
+ hub_ease_in_out: animateOK(out.hub),
84
+ halos_count_4: out.halos.length === 4,
85
+ halos_all_present: out.halos.every(h => h !== null),
86
+ halos_all_ease_in_out: out.halos.every(animateOK),
87
+ };
88
+ const ok = Object.values(results).every(Boolean);
89
+ console.log(`${ok ? '✅' : '❌'} halo breath ease:`, JSON.stringify(results),
90
+ '\n hub: ', out.hub,
91
+ '\n halos:', out.halos);
92
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,89 @@
1
+ /* Round 226 verification: working-halo breath gets per-node phase
2
+ * stagger via SMIL `begin="-{nodeIdx * 0.37 % 3}s"`. Pre-R226 all
3
+ * working halos pulsed in lockstep at the same instant; R226 desyncs
4
+ * them organically.
5
+ *
6
+ * Test: 4 working agents → probe each [data-node-halo-breath='on']
7
+ * circle for its `<animate>` child's `begin` attribute. Expect:
8
+ * - Each animate has a `begin` matching '-N.NNNs'
9
+ * - All four offsets are distinct (no two halos start at the
10
+ * same phase)
11
+ * - The data-node-halo-breath-offset attribute matches the
12
+ * `begin` magnitude (post-strip of '-' and 's')
13
+ * - The dur stays '3s' (period unchanged, only phase shifts)
14
+ * - Reduced-motion test scope unchanged (gate still keeps SMIL
15
+ * out for prefers-reduced-motion users)
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 browser = await chromium.launch({ headless: true });
22
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
23
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
24
+ await ctx.addInitScript(() => {
25
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
26
+ });
27
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
28
+ await ctx.route('**/api/hub/status*', async (route) => {
29
+ const r = await route.fetch();
30
+ const b = await r.json();
31
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
32
+ const mk = (alias) => ({
33
+ alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
34
+ network_id: nid, project_dir: null,
35
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
36
+ });
37
+ await route.fulfill({ response: r, json: { ...b, sessions: [
38
+ mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
39
+ ] } });
40
+ });
41
+ await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: [] } }));
42
+ await ctx.route('**/api/hub/tasks*', (r2) => r2.fulfill({ json: { tasks: [] } }));
43
+
44
+ const page = await ctx.newPage();
45
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
46
+ await page.waitForFunction(() => document.querySelectorAll('[data-node-halo-breath="on"]').length === 4, { timeout: 30000 });
47
+ await page.waitForTimeout(400);
48
+
49
+ const out = await page.evaluate(() => {
50
+ const halos = Array.from(document.querySelectorAll('[data-node-halo-breath="on"]'));
51
+ return halos.map((h) => {
52
+ const anim = h.querySelector('animate');
53
+ return {
54
+ offsetAttr: h.getAttribute('data-node-halo-breath-offset'),
55
+ begin: anim?.getAttribute('begin') || null,
56
+ dur: anim?.getAttribute('dur') || null,
57
+ attrName: anim?.getAttribute('attributeName') || null,
58
+ };
59
+ });
60
+ });
61
+ await browser.close();
62
+
63
+ const beginRe = /^-(\d+\.\d{3})s$/;
64
+ const parsed = out.map((h) => {
65
+ const m = (h.begin || '').match(beginRe);
66
+ return {
67
+ ...h,
68
+ beginNum: m ? parseFloat(m[1]) : NaN,
69
+ };
70
+ });
71
+
72
+ // Expected: 4 halos, offsets (0 * 0.37) % 3, (1 * 0.37) % 3, etc.
73
+ // = 0.000, 0.370, 0.740, 1.110 (each .toFixed(3))
74
+ const expected = [0, 0.37, 0.74, 1.11];
75
+ const close = (a, b) => Math.abs(a - b) < 0.005;
76
+
77
+ const results = {
78
+ four_halos: parsed.length === 4,
79
+ all_have_begin: parsed.every(p => !Number.isNaN(p.beginNum)),
80
+ all_have_dur_3s: parsed.every(p => p.dur === '3s'),
81
+ all_attr_opacity: parsed.every(p => p.attrName === 'opacity'),
82
+ all_offsets_distinct: new Set(parsed.map(p => p.beginNum)).size === 4,
83
+ offsets_match_golden: parsed.every((p, i) => close(p.beginNum, expected[i])),
84
+ attr_matches_begin: parsed.every((p) => p.offsetAttr === p.beginNum.toFixed(3)),
85
+ };
86
+ const ok = Object.values(results).every(Boolean);
87
+ console.log(`${ok ? '✅' : '❌'} halo breath stagger:`, JSON.stringify(results),
88
+ '\n parsed:', parsed);
89
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,67 @@
1
+ /* Round 109 verification: HelpOverlay catches up on R108 — palette
2
+ * gained pin-vendor commands (Anthropic/OpenAI/书生). Continues the
3
+ * R59/R62/R65/R70/R78/R81/R87/R91 docs-catch-up cadence.
4
+ *
5
+ * Stacks eight generations of help-overlay assertions — any future
6
+ * regression that drops an entry will be caught by one of:
7
+ * R109 (this) → R91 → R87 → R81 → R78 → R74 → R70 → R65 → R59
8
+ */
9
+ import { chromium } from 'playwright';
10
+ import { readFileSync } from 'node:fs';
11
+
12
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
13
+ const browser = await chromium.launch({ headless: true });
14
+
15
+ const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } });
16
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
17
+ await ctx.addInitScript(() => {
18
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
19
+ });
20
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
21
+ await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
22
+ const page = await ctx.newPage();
23
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
24
+ await page.waitForTimeout(800);
25
+
26
+ await page.keyboard.press('?');
27
+ await page.waitForSelector('[role="dialog"][aria-label="Keyboard shortcuts"]', { timeout: 5000 });
28
+
29
+ const items = await page.evaluate(() => {
30
+ const dialog = document.querySelector('[role="dialog"][aria-label="Keyboard shortcuts"]');
31
+ const groups = [...(dialog?.querySelectorAll('div') || [])];
32
+ let active = null;
33
+ for (const g of groups) {
34
+ if (g.textContent && /^Topology canvas$/i.test(g.textContent.trim())) {
35
+ active = g.parentElement;
36
+ break;
37
+ }
38
+ }
39
+ return active ? [...active.querySelectorAll('li')].map(li => (li.textContent || '').trim()) : [];
40
+ });
41
+
42
+ await browser.close();
43
+
44
+ const has = (s) => items.some(t => t.includes(s));
45
+ const results = {
46
+ r109_pinVendor: has('Pin vendor: Anthropic/OpenAI/书生 via palette → "Pin topology filter…" (R108)'),
47
+ // R91 priors
48
+ r91_clickVendor: has('Pin a vendor filter — click A/O/书/? in the chip row (R88)'),
49
+ r91_clearVendor: has('Clear vendor pin only via palette → "Clear topology vendor filter" (R90)'),
50
+ // R87 priors
51
+ r87_segHover: has('Preview a status filter — hover a pressure-bar segment (R83)'),
52
+ r87_groupLabelHover: has('Preview a team focus — hover a group label (R86)'),
53
+ // R81 priors
54
+ r81_workingChip: has('Highlight working nodes — chip-row sibling of legend (R79)'),
55
+ r81_vendorChip: has('Highlight one vendor — hover A/O/书/? in the chip row (R80)'),
56
+ // R78 / R74 / R70 / R65 / R59 priors — 8 generations now
57
+ r78_pillBodyClick: has('Clear filter — click anywhere on the pill body (R73)'),
58
+ r74_cmdkLayout: has('Toggle layout / Fit canvas via palette (R74)'),
59
+ r70_cmdkPin: has('(R69)'),
60
+ r65_groupClick: has('Pin a team focus (R63)'),
61
+ r62_pinChip: has('Pin a status filter (R60/R61)'),
62
+ r59_clickHub: has('Fit topology to canvas (R52)'),
63
+ };
64
+ const ok = Object.values(results).every(Boolean);
65
+ console.log(`${ok ? '✅' : '❌'} help overlay R109:`, JSON.stringify(results),
66
+ `\n items=`, items);
67
+ process.exit(ok ? 0 : 1);