@sleep2agi/agent-network-dashboard 0.4.6-preview.27 → 0.4.6-preview.270

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 (468) 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/0.qg_sd3s8sj~.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/0ggj5ummw2a84.js +7 -0
  187. package/.next/static/chunks/0glmrdj9112tc.js +7 -0
  188. package/.next/static/chunks/0rxrez_cjn.eh.js +1 -0
  189. package/.next/static/chunks/0x8x.29hkju5a.js +1 -0
  190. package/.next/static/chunks/0y.7kwty.hl7h.css +2 -0
  191. package/.next/static/chunks/0zwpi6hqmzpqh.js +1 -0
  192. package/.next/static/chunks/149kodgion8f0.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 +5411 -240
  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-semantic-gap-test.mjs +97 -0
  229. package/scripts/topo-chip-row-tabular-test.mjs +111 -0
  230. package/scripts/topo-chrome-a11y-test.mjs +107 -0
  231. package/scripts/topo-chrome-pop-extension-test.mjs +98 -0
  232. package/scripts/topo-chrome-pop-nodesize-test.mjs +88 -0
  233. package/scripts/topo-chrome-press-state-test.mjs +135 -0
  234. package/scripts/topo-chrome-strip-semantic-gap-test.mjs +99 -0
  235. package/scripts/topo-chrome-zoom-level-pop-test.mjs +122 -0
  236. package/scripts/topo-chrome-zoom-pop-test.mjs +130 -0
  237. package/scripts/topo-click-ripple-ease-test.mjs +94 -0
  238. package/scripts/topo-cmdk-edge-clear-test.mjs +109 -0
  239. package/scripts/topo-cmdk-layout-view-test.mjs +108 -0
  240. package/scripts/topo-cmdk-pin-test.mjs +123 -0
  241. package/scripts/topo-cmdk-vendor-clear-test.mjs +133 -0
  242. package/scripts/topo-cmdk-vendor-pin-test.mjs +103 -0
  243. package/scripts/topo-corner-radius-unify-test.mjs +103 -0
  244. package/scripts/topo-cwd-tooltip-test.mjs +64 -0
  245. package/scripts/topo-dblclick-reset-test.mjs +74 -0
  246. package/scripts/topo-dense-alias-fill-transition-test.mjs +133 -0
  247. package/scripts/topo-discrete-zoom-smooth-test.mjs +125 -0
  248. package/scripts/topo-dispatch-pulse-test.mjs +83 -0
  249. package/scripts/topo-edge-badge-click-pin-test.mjs +94 -0
  250. package/scripts/topo-edge-badge-crossfade-test.mjs +138 -0
  251. package/scripts/topo-edge-badge-hot-test.mjs +115 -0
  252. package/scripts/topo-edge-badge-hover-test.mjs +85 -0
  253. package/scripts/topo-edge-badge-lift-test.mjs +150 -0
  254. package/scripts/topo-edge-badge-ripple-test.mjs +111 -0
  255. package/scripts/topo-edge-badge-stroke-transition-test.mjs +118 -0
  256. package/scripts/topo-edge-badge-text-pin-test.mjs +121 -0
  257. package/scripts/topo-edge-badge-theme-ease-test.mjs +89 -0
  258. package/scripts/topo-edge-count-badge-test.mjs +86 -0
  259. package/scripts/topo-edge-endpoint-highlight-test.mjs +111 -0
  260. package/scripts/topo-edge-fadein-test.mjs +106 -0
  261. package/scripts/topo-edge-focus-test.mjs +113 -0
  262. package/scripts/topo-edge-hover-test.mjs +93 -0
  263. package/scripts/topo-edge-pill-hot-test.mjs +129 -0
  264. package/scripts/topo-edge-pill-test.mjs +105 -0
  265. package/scripts/topo-edge-smil-sync-test.mjs +148 -0
  266. package/scripts/topo-edge-smil-theme-ease-test.mjs +97 -0
  267. package/scripts/topo-edge-stroke-ease-test.mjs +100 -0
  268. package/scripts/topo-edge-stroke-transition-test.mjs +132 -0
  269. package/scripts/topo-edge-tooltip-test.mjs +70 -0
  270. package/scripts/topo-empty-state-breath-test.mjs +150 -0
  271. package/scripts/topo-empty-state-crossfade-test.mjs +130 -0
  272. package/scripts/topo-empty-state-recenter-test.mjs +107 -0
  273. package/scripts/topo-endpoint-ring-fade-test.mjs +132 -0
  274. package/scripts/topo-endpoint-ring-test.mjs +93 -0
  275. package/scripts/topo-endpoint-ring-thicken-test.mjs +112 -0
  276. package/scripts/topo-esc-clears-pin-test.mjs +98 -0
  277. package/scripts/topo-filter-pill-aliases-test.mjs +121 -0
  278. package/scripts/topo-filter-pill-body-click-test.mjs +112 -0
  279. package/scripts/topo-filter-pill-count-test.mjs +110 -0
  280. package/scripts/topo-filter-pill-mobile-test.mjs +90 -0
  281. package/scripts/topo-fit-key-test.mjs +106 -0
  282. package/scripts/topo-freshness-chip-test.mjs +74 -0
  283. package/scripts/topo-freshness-chip-transition-test.mjs +80 -0
  284. package/scripts/topo-fullscreen-active-test.mjs +115 -0
  285. package/scripts/topo-group-box-pinned-state-test.mjs +95 -0
  286. package/scripts/topo-group-count-test.mjs +6 -1
  287. package/scripts/topo-group-label-a11y-test.mjs +113 -0
  288. package/scripts/topo-group-label-count-inherit-test.mjs +99 -0
  289. package/scripts/topo-group-label-hover-test.mjs +119 -0
  290. package/scripts/topo-group-label-pin-spacing-test.mjs +136 -0
  291. package/scripts/topo-group-label-tint-test.mjs +99 -0
  292. package/scripts/topo-group-label-title-test.mjs +83 -0
  293. package/scripts/topo-group-pin-test.mjs +119 -0
  294. package/scripts/topo-group-pip-fadein-test.mjs +100 -0
  295. package/scripts/topo-group-pip-tabular-test.mjs +95 -0
  296. package/scripts/topo-group-status-pips-test.mjs +103 -0
  297. package/scripts/topo-groupbox-fadein-test.mjs +95 -0
  298. package/scripts/topo-groupbox-hover-lift-test.mjs +127 -0
  299. package/scripts/topo-groupbox-hubcore-ease-test.mjs +106 -0
  300. package/scripts/topo-groupbox-live-test.mjs +100 -0
  301. package/scripts/topo-groupbox-march-busyness-test.mjs +155 -0
  302. package/scripts/topo-groupbox-test.mjs +4 -2
  303. package/scripts/topo-halo-breath-ease-test.mjs +92 -0
  304. package/scripts/topo-halo-breath-stagger-test.mjs +89 -0
  305. package/scripts/topo-help-overlay-r109-test.mjs +67 -0
  306. package/scripts/topo-help-overlay-r118-test.mjs +69 -0
  307. package/scripts/topo-help-overlay-r123-test.mjs +69 -0
  308. package/scripts/topo-help-overlay-r134-test.mjs +74 -0
  309. package/scripts/topo-help-overlay-r137-test.mjs +81 -0
  310. package/scripts/topo-help-overlay-r141-test.mjs +86 -0
  311. package/scripts/topo-help-overlay-r153-test.mjs +85 -0
  312. package/scripts/topo-help-overlay-r59-test.mjs +67 -0
  313. package/scripts/topo-help-overlay-r65-test.mjs +64 -0
  314. package/scripts/topo-help-overlay-r70-test.mjs +63 -0
  315. package/scripts/topo-help-overlay-r78-test.mjs +59 -0
  316. package/scripts/topo-help-overlay-r81-test.mjs +58 -0
  317. package/scripts/topo-help-overlay-r87-test.mjs +64 -0
  318. package/scripts/topo-help-overlay-r91-test.mjs +65 -0
  319. package/scripts/topo-hot-tail-crossfade-test.mjs +117 -0
  320. package/scripts/topo-html-overlay-padding-unify-test.mjs +120 -0
  321. package/scripts/topo-hub-a11y-test.mjs +112 -0
  322. package/scripts/topo-hub-busyness-test.mjs +100 -0
  323. package/scripts/topo-hub-center-crossfade-test.mjs +124 -0
  324. package/scripts/topo-hub-click-fit-test.mjs +137 -0
  325. package/scripts/topo-hub-digit-scale-test.mjs +129 -0
  326. package/scripts/topo-hub-fadein-test.mjs +88 -0
  327. package/scripts/topo-hub-hover-lift-test.mjs +101 -0
  328. package/scripts/topo-hub-hover-ring-test.mjs +82 -0
  329. package/scripts/topo-hub-pip-theme-ease-test.mjs +116 -0
  330. package/scripts/topo-hub-spoke-ease-test.mjs +120 -0
  331. package/scripts/topo-hub-title-test.mjs +93 -0
  332. package/scripts/topo-hub-working-count-test.mjs +99 -0
  333. package/scripts/topo-ingroup-edge-test.mjs +103 -0
  334. package/scripts/topo-label-card-theme-ease-test.mjs +85 -0
  335. package/scripts/topo-label-lift-test.mjs +119 -0
  336. package/scripts/topo-lastseen-tooltip-test.mjs +59 -0
  337. package/scripts/topo-layout-key-test.mjs +91 -0
  338. package/scripts/topo-layout-switch-crossfade-test.mjs +126 -0
  339. package/scripts/topo-layout-toggle-test.mjs +131 -0
  340. package/scripts/topo-legend-count-empty-test.mjs +126 -0
  341. package/scripts/topo-legend-count-test.mjs +88 -0
  342. package/scripts/topo-legend-count-tier-fill-test.mjs +121 -0
  343. package/scripts/topo-legend-header-symmetric-inset-test.mjs +112 -0
  344. package/scripts/topo-legend-hover-test.mjs +113 -0
  345. package/scripts/topo-legend-panel-header-test.mjs +83 -0
  346. package/scripts/topo-legend-pin-ring-fade-test.mjs +112 -0
  347. package/scripts/topo-legend-pin-test.mjs +128 -0
  348. package/scripts/topo-legend-row-hover-lift-test.mjs +109 -0
  349. package/scripts/topo-legend-row-pin-spacing-test.mjs +124 -0
  350. package/scripts/topo-legend-row-tint-test.mjs +95 -0
  351. package/scripts/topo-legend-row-title-test.mjs +102 -0
  352. package/scripts/topo-legend-swatch-grow-test.mjs +116 -0
  353. package/scripts/topo-minimap-a11y-test.mjs +101 -0
  354. package/scripts/topo-minimap-dot-transition-test.mjs +113 -0
  355. package/scripts/topo-minimap-test.mjs +68 -0
  356. package/scripts/topo-minimap-viewport-smooth-test.mjs +124 -0
  357. package/scripts/topo-mobile-chips-test.mjs +103 -0
  358. package/scripts/topo-node-a11y-test.mjs +107 -0
  359. package/scripts/topo-node-hover-lift-test.mjs +85 -0
  360. package/scripts/topo-node-label-card-elevation-test.mjs +157 -0
  361. package/scripts/topo-node-label-card-stroke-test.mjs +135 -0
  362. package/scripts/topo-node-stroke-transition-test.mjs +103 -0
  363. package/scripts/topo-node-text-fill-transition-test.mjs +119 -0
  364. package/scripts/topo-node-title-peers-test.mjs +107 -0
  365. package/scripts/topo-node-title-test.mjs +101 -0
  366. package/scripts/topo-nodesize-active-hover-test.mjs +109 -0
  367. package/scripts/topo-nodesize-crossfade-test.mjs +141 -0
  368. package/scripts/topo-online-chip-nav-test.mjs +143 -0
  369. package/scripts/topo-orbit-busyness-test.mjs +96 -0
  370. package/scripts/topo-orbit-opacity-bucket-test.mjs +124 -0
  371. package/scripts/topo-overlap-test.mjs +32 -5
  372. package/scripts/topo-pan-cursor-test.mjs +62 -0
  373. package/scripts/topo-panel-elevation-test.mjs +76 -0
  374. package/scripts/topo-panel-fadein-test.mjs +102 -0
  375. package/scripts/topo-panel-hot-tail-fade-test.mjs +132 -0
  376. package/scripts/topo-panel-hover-elevation-test.mjs +118 -0
  377. package/scripts/topo-panel-theme-ease-test.mjs +85 -0
  378. package/scripts/topo-particle-stagger-test.mjs +82 -0
  379. package/scripts/topo-pin-intersection-color-ease-test.mjs +111 -0
  380. package/scripts/topo-pin-intersection-empty-test.mjs +129 -0
  381. package/scripts/topo-pin-intersection-tabular-test.mjs +96 -0
  382. package/scripts/topo-pin-intersection-test.mjs +121 -0
  383. package/scripts/topo-pin-intersection-warning-crossfade-test.mjs +107 -0
  384. package/scripts/topo-pin-mirror-transition-test.mjs +101 -0
  385. package/scripts/topo-pin-persistence-test.mjs +105 -0
  386. package/scripts/topo-ping-pulse-ease-test.mjs +96 -0
  387. package/scripts/topo-popover-meta-test.mjs +78 -0
  388. package/scripts/topo-prepublish-guard-test.mjs +95 -0
  389. package/scripts/topo-pressure-bar-test.mjs +69 -0
  390. package/scripts/topo-pressure-hover-test.mjs +123 -0
  391. package/scripts/topo-pressure-pin-test.mjs +119 -0
  392. package/scripts/topo-pressure-seg-self-hover-test.mjs +126 -0
  393. package/scripts/topo-pressure-seg-tooltip-test.mjs +98 -0
  394. package/scripts/topo-pressure-seg-transition-test.mjs +107 -0
  395. package/scripts/topo-pulse-dot-crossfade-test.mjs +122 -0
  396. package/scripts/topo-pulse-rate-test.mjs +71 -0
  397. package/scripts/topo-recent-panel-count-freshness-test.mjs +109 -0
  398. package/scripts/topo-recent-panel-count-test.mjs +72 -0
  399. package/scripts/topo-recent-panel-footer-breath-test.mjs +142 -0
  400. package/scripts/topo-recent-panel-hot-header-test.mjs +132 -0
  401. package/scripts/topo-recent-panel-more-crossfade-test.mjs +124 -0
  402. package/scripts/topo-recent-panel-more-cyan-hover-test.mjs +151 -0
  403. package/scripts/topo-recent-panel-more-nav-test.mjs +127 -0
  404. package/scripts/topo-recent-panel-more-test.mjs +106 -0
  405. package/scripts/topo-recent-panel-readability-bump-test.mjs +151 -0
  406. package/scripts/topo-recent-row-count-fill-test.mjs +129 -0
  407. package/scripts/topo-recent-row-fadein-test.mjs +107 -0
  408. package/scripts/topo-recent-row-freshness-test.mjs +102 -0
  409. package/scripts/topo-recent-row-hot-test.mjs +110 -0
  410. package/scripts/topo-recent-row-hover-lift-test.mjs +128 -0
  411. package/scripts/topo-recent-row-hover-test.mjs +122 -0
  412. package/scripts/topo-recent-row-pin-spacing-test.mjs +137 -0
  413. package/scripts/topo-recent-row-pin-test.mjs +126 -0
  414. package/scripts/topo-recent-row-tint-test.mjs +91 -0
  415. package/scripts/topo-recent-row-title-test.mjs +112 -0
  416. package/scripts/topo-recent-row-ts-alpha-test.mjs +100 -0
  417. package/scripts/topo-recent-row-ts-test.mjs +95 -0
  418. package/scripts/topo-recent-row-typography-test.mjs +119 -0
  419. package/scripts/topo-recent-signal-empty-hint-test.mjs +73 -0
  420. package/scripts/topo-recent-signal-empty-test.mjs +63 -0
  421. package/scripts/topo-reduced-motion-test.mjs +77 -0
  422. package/scripts/topo-reset-spin-test.mjs +120 -0
  423. package/scripts/topo-runtime-badge-grow-test.mjs +114 -0
  424. package/scripts/topo-spoke-busyness-test.mjs +110 -0
  425. package/scripts/topo-spoke-tint-test.mjs +96 -0
  426. package/scripts/topo-status-chip-hover-test.mjs +101 -0
  427. package/scripts/topo-status-chip-tooltip-test.mjs +95 -0
  428. package/scripts/topo-statusbar-chips-self-hover-test.mjs +177 -0
  429. package/scripts/topo-svg-focus-test.mjs +112 -0
  430. package/scripts/topo-sweep-busyness-test.mjs +94 -0
  431. package/scripts/topo-tabular-nums-sweep-test.mjs +93 -0
  432. package/scripts/topo-tier-ring-fadein-test.mjs +107 -0
  433. package/scripts/topo-tier-ring-occupancy-test.mjs +87 -0
  434. package/scripts/topo-tier-ring-test.mjs +69 -0
  435. package/scripts/topo-tier-ring-tint-test.mjs +110 -0
  436. package/scripts/topo-tier-stagger-test.mjs +89 -0
  437. package/scripts/topo-tz-ghost-test.mjs +69 -0
  438. package/scripts/topo-vendor-chip-hover-test.mjs +111 -0
  439. package/scripts/topo-vendor-chip-self-hover-test.mjs +130 -0
  440. package/scripts/topo-vendor-chip-tabular-test.mjs +89 -0
  441. package/scripts/topo-vendor-letter-tooltip-test.mjs +92 -0
  442. package/scripts/topo-vendor-pill-test.mjs +125 -0
  443. package/scripts/topo-vendor-pin-test.mjs +125 -0
  444. package/scripts/topo-view-smooth-test.mjs +131 -0
  445. package/scripts/topo-wheel-zoom-test.mjs +79 -0
  446. package/scripts/topo-working-chip-pin-test.mjs +154 -0
  447. package/scripts/topo-working-halo-breath-test.mjs +86 -0
  448. package/scripts/topo-wrapper-flow-arrow-theme-test.mjs +97 -0
  449. package/scripts/topo-wrapper-shadow-theme-ease-test.mjs +89 -0
  450. package/scripts/topo-zoom-keys-test.mjs +89 -0
  451. package/.next/static/chunks/0-7iowzu4.798.js +0 -1
  452. package/.next/static/chunks/02t5jr4shh.hy.js +0 -1
  453. package/.next/static/chunks/04ppgi-mphhr6.js +0 -1
  454. package/.next/static/chunks/09nd.t_hd.y6t.css +0 -2
  455. package/.next/static/chunks/0_qfg5s5uzs7..js +0 -7
  456. package/.next/static/chunks/0elalb9n_.~di.js +0 -1
  457. package/.next/static/chunks/0fqy_0wj_1xa7.js +0 -7
  458. package/.next/static/chunks/0j_q__o8p6g83.js +0 -1
  459. package/.next/static/chunks/0jl6_w50zh4l5.js +0 -1
  460. package/.next/static/chunks/0r4q73.-1bkyl.js +0 -1
  461. package/.next/static/chunks/0r_c8eccg3z2o.js +0 -1
  462. package/.next/static/chunks/0zs511wcsq~0j.js +0 -1
  463. package/.next/static/chunks/10oi7l-tycgl9.js +0 -1
  464. package/.next/static/chunks/11uk1izuv3~0t.js +0 -1
  465. package/.next/static/chunks/15gj.t675_yw3.js +0 -1
  466. /package/.next/static/{kk1qr2sXSqVvoqBT7fk1x → zfTklPhuNFS7pf_LmLAvq}/_buildManifest.js +0 -0
  467. /package/.next/static/{kk1qr2sXSqVvoqBT7fk1x → zfTklPhuNFS7pf_LmLAvq}/_clientMiddlewareManifest.js +0 -0
  468. /package/.next/static/{kk1qr2sXSqVvoqBT7fk1x → zfTklPhuNFS7pf_LmLAvq}/_ssgManifest.js +0 -0
@@ -0,0 +1,148 @@
1
+ /* Round 231 verification: edge SMIL trio (R103 particle motion +
2
+ * R76 dispatch pulse + R75 arrival ping) now share a single per-edge
3
+ * stagger so all three fire phase-coherently with the particle:
4
+ *
5
+ * particle.animateMotion.begin = -stagger
6
+ * dispatch.animate.begin = -stagger (= particle's)
7
+ * arrival.animate.begin = -(stagger + 0.92*dur) mod dur
8
+ *
9
+ * where stagger = (edgeIndex * 0.37) % duration,
10
+ * duration = max(0.9, 2.6 / sqrt(link.count)).
11
+ *
12
+ * Scenario: 4 working agents + 2 flows (alpha→beta count=5, gamma→
13
+ * delta count=4) — both flows have count ≥ 3 so dispatch pulse
14
+ * fires on both, and fresh > 0.5 so arrival ping fires on both.
15
+ *
16
+ * Per edge:
17
+ * - probe particle's animateMotion.begin
18
+ * - probe dispatch's two <animate>.begin (r + opacity, must match)
19
+ * - probe arrival's two <animate>.begin (r + opacity, must match)
20
+ * - verify all three follow the formula given index + duration
21
+ */
22
+ import { chromium } from 'playwright';
23
+ import { readFileSync } from 'node:fs';
24
+
25
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
26
+ const browser = await chromium.launch({ headless: true });
27
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
28
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
29
+ await ctx.addInitScript(() => {
30
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
31
+ });
32
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
33
+ await ctx.route('**/api/hub/status*', async (route) => {
34
+ const r = await route.fetch();
35
+ const b = await r.json();
36
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
37
+ const mk = (alias) => ({
38
+ alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
39
+ network_id: nid, project_dir: null,
40
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
41
+ });
42
+ await route.fulfill({ response: r, json: { ...b, sessions: [
43
+ mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
44
+ ] } });
45
+ });
46
+ const now = Date.now();
47
+ const msgs = [];
48
+ // flow 0: alpha→beta count=5 — sorted by recent activity, this will be
49
+ // the more-recent flow; edge index depends on flowLinks.sort by last_at desc.
50
+ for (let i = 0; i < 5; i++) {
51
+ msgs.push({
52
+ id: `ab${i}`, from_alias: 'alpha', to_alias: 'beta', content: 'hi',
53
+ network_id: 'default', created_at: new Date(now - (500 + i * 50)).toISOString(),
54
+ });
55
+ }
56
+ // flow 1: gamma→delta count=4 — older
57
+ for (let i = 0; i < 4; i++) {
58
+ msgs.push({
59
+ id: `gd${i}`, from_alias: 'gamma', to_alias: 'delta', content: 'hi',
60
+ network_id: 'default', created_at: new Date(now - (5000 + i * 50)).toISOString(),
61
+ });
62
+ }
63
+ await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: msgs } }));
64
+ await ctx.route('**/api/hub/tasks*', (r2) => r2.fulfill({ json: { tasks: [] } }));
65
+
66
+ const page = await ctx.newPage();
67
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
68
+ await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
69
+ await page.waitForSelector('[data-arrival-ping]', { timeout: 10000, state: 'attached' });
70
+ await page.waitForSelector('[data-dispatch-pulse]', { timeout: 10000, state: 'attached' });
71
+ await page.waitForTimeout(400);
72
+
73
+ const probe = await page.evaluate(() => {
74
+ // Edges keyed by link.key ("from→to"). We grab pairs of (arrival, dispatch)
75
+ // by data attr, plus particle's animateMotion inside the edge <g>.
76
+ const pings = Array.from(document.querySelectorAll('[data-arrival-ping]'));
77
+ const pulses = Array.from(document.querySelectorAll('[data-dispatch-pulse]'));
78
+ // Each ping/pulse lives inside an edge <g> that also contains the animateMotion
79
+ // for the particle. We walk up to find the shared parent.
80
+ return pings.map((ping) => {
81
+ const key = ping.getAttribute('data-arrival-ping');
82
+ const pulse = pulses.find(p => p.getAttribute('data-dispatch-pulse') === key);
83
+ // animateMotion lives in a sibling <circle> within the same parent <g>
84
+ const edgeG = ping.closest('g[data-edge-visible-parent]') || ping.parentElement;
85
+ const motion = edgeG?.querySelector('animateMotion');
86
+ const pingAnims = Array.from(ping.querySelectorAll('animate'));
87
+ const pulseAnims = pulse ? Array.from(pulse.querySelectorAll('animate')) : [];
88
+ return {
89
+ key,
90
+ pingBeginR: pingAnims.find(a => a.getAttribute('attributeName') === 'r')?.getAttribute('begin') || null,
91
+ pingBeginOpacity: pingAnims.find(a => a.getAttribute('attributeName') === 'opacity')?.getAttribute('begin') || null,
92
+ pulseBeginR: pulseAnims.find(a => a.getAttribute('attributeName') === 'r')?.getAttribute('begin') || null,
93
+ pulseBeginOpacity: pulseAnims.find(a => a.getAttribute('attributeName') === 'opacity')?.getAttribute('begin') || null,
94
+ motionBegin: motion?.getAttribute('begin') || null,
95
+ motionDur: motion?.getAttribute('dur') || null,
96
+ };
97
+ });
98
+ });
99
+ await browser.close();
100
+
101
+ const parseS = (s) => {
102
+ if (!s) return null;
103
+ const m = String(s).match(/^-?(\d+(?:\.\d+)?)s$/);
104
+ if (!m) return null;
105
+ return s.startsWith('-') ? -parseFloat(m[1]) : parseFloat(m[1]);
106
+ };
107
+
108
+ const close = (a, b, eps = 0.005) => Math.abs(a - b) < eps;
109
+
110
+ const validate = (edge) => {
111
+ const dur = parseS(edge.motionDur);
112
+ const motionBegin = parseS(edge.motionBegin); // -stagger
113
+ const pingR = parseS(edge.pingBeginR);
114
+ const pingOp = parseS(edge.pingBeginOpacity);
115
+ const pulseR = parseS(edge.pulseBeginR);
116
+ const pulseOp = parseS(edge.pulseBeginOpacity);
117
+ if (dur === null || motionBegin === null || motionBegin > 0) return null;
118
+ const stagger = -motionBegin; // positive
119
+ // Expected ping begin = -(stagger + 0.92*dur) mod dur → in [-dur, 0]
120
+ const wrapped = (stagger + 0.92 * dur) % dur;
121
+ const expectedPing = -wrapped;
122
+ return {
123
+ dur,
124
+ motionBegin,
125
+ stagger,
126
+ expectedPing,
127
+ pulseR,
128
+ pulseOp,
129
+ pingR,
130
+ pingOp,
131
+ dispatch_matches_particle: close(pulseR, motionBegin) && close(pulseOp, motionBegin),
132
+ arrival_matches_formula: close(pingR, expectedPing) && close(pingOp, expectedPing),
133
+ };
134
+ };
135
+
136
+ const edges = probe.map(validate).filter(e => e !== null);
137
+
138
+ const results = {
139
+ at_least_one_edge: edges.length >= 1,
140
+ all_dispatch_match_particle: edges.every(e => e.dispatch_matches_particle),
141
+ all_arrival_match_formula: edges.every(e => e.arrival_matches_formula),
142
+ pulse_r_op_consistent: edges.every(e => Math.abs(e.pulseR - e.pulseOp) < 0.005),
143
+ ping_r_op_consistent: edges.every(e => Math.abs(e.pingR - e.pingOp) < 0.005),
144
+ };
145
+ const ok = Object.values(results).every(Boolean);
146
+ console.log(`${ok ? '✅' : '❌'} edge SMIL sync:`, JSON.stringify(results),
147
+ '\n edges:', edges);
148
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,97 @@
1
+ /* Round 252 verification: three SMIL edge elements (particle,
2
+ * arrival ping, dispatch pulse) pick up theme-toggle transitions
3
+ * on their static color attributes, closing the last per-edge
4
+ * theme-toggle snaps.
5
+ *
6
+ * Pre-R252 each element had inline style with only pointerEvents
7
+ * (or no style for particle). Theme-driven fill/stroke snapped:
8
+ * · particle: fill=pal.flowParticle (cyber yellow ↔ light amber)
9
+ * · arrival ping: stroke=pal.flowEdge (cyber cyan ↔ light emerald)
10
+ * · dispatch pulse: stroke=pal.flowEdge (same as ping)
11
+ *
12
+ * R252 adds 200ms transitions:
13
+ * · particle: transition: fill 200ms, opacity 200ms
14
+ * · arrival ping: transition: stroke 200ms
15
+ * · dispatch pulse: transition: stroke 200ms
16
+ *
17
+ * The SMIL animateMotion (particle path) + R228 spline-eased animates
18
+ * (ping/pulse r + opacity) run independently of these CSS transitions
19
+ * — no conflict; CSS handles static-color theme transitions, SMIL
20
+ * handles animation values.
21
+ *
22
+ * Scenario: 4 working agents + 5-msg alpha→beta (count≥3, fresh>0.5)
23
+ * → particle + arrival ping + dispatch pulse all rendered.
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
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
31
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
32
+ await ctx.addInitScript(() => {
33
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
34
+ });
35
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
36
+ await ctx.route('**/api/hub/status*', async (route) => {
37
+ const r = await route.fetch();
38
+ const b = await r.json();
39
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
40
+ const mk = (alias) => ({
41
+ alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
42
+ network_id: nid, project_dir: null,
43
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
44
+ });
45
+ await route.fulfill({ response: r, json: { ...b, sessions: [
46
+ mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
47
+ ] } });
48
+ });
49
+ const now = Date.now();
50
+ const msgs = [];
51
+ for (let i = 0; i < 5; i++) {
52
+ msgs.push({
53
+ id: `m${i}`, from_alias: 'alpha', to_alias: 'beta', content: 'hi',
54
+ network_id: 'default', created_at: new Date(now - (1000 + i * 50)).toISOString(),
55
+ });
56
+ }
57
+ await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: msgs } }));
58
+ await ctx.route('**/api/hub/tasks*', (r2) => r2.fulfill({ json: { tasks: [] } }));
59
+
60
+ const page = await ctx.newPage();
61
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
62
+ await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
63
+ await page.waitForSelector('[data-edge-particle]', { timeout: 10000, state: 'attached' });
64
+ await page.waitForSelector('[data-arrival-ping]', { timeout: 10000, state: 'attached' });
65
+ await page.waitForSelector('[data-dispatch-pulse]', { timeout: 10000, state: 'attached' });
66
+ await page.waitForTimeout(300);
67
+
68
+ const probe = await page.evaluate(() => {
69
+ const grab = (sel) => {
70
+ const el = document.querySelector(sel);
71
+ return el ? { transition: el.style.transition, fill: el.getAttribute('fill'), stroke: el.getAttribute('stroke') } : null;
72
+ };
73
+ return {
74
+ particle: grab('[data-edge-particle]'),
75
+ arrivalPing: grab('[data-arrival-ping]'),
76
+ dispatchPulse: grab('[data-dispatch-pulse]'),
77
+ };
78
+ });
79
+ await browser.close();
80
+
81
+ const has = (s, prop) => new RegExp(`${prop}\\s+(?:200ms|0\\.2s)`).test(s || '');
82
+
83
+ const results = {
84
+ particle_present: probe.particle !== null,
85
+ particle_has_fill_200: has(probe.particle?.transition, 'fill'),
86
+ particle_has_opacity_200: has(probe.particle?.transition, 'opacity'),
87
+
88
+ arrival_ping_present: probe.arrivalPing !== null,
89
+ arrival_ping_has_stroke_200: has(probe.arrivalPing?.transition, 'stroke'),
90
+
91
+ dispatch_pulse_present: probe.dispatchPulse !== null,
92
+ dispatch_pulse_has_stroke_200: has(probe.dispatchPulse?.transition, 'stroke'),
93
+ };
94
+ const ok = Object.values(results).every(Boolean);
95
+ console.log(`${ok ? '✅' : '❌'} edge SMIL theme ease:`, JSON.stringify(results),
96
+ '\n probe:', probe);
97
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,100 @@
1
+ /* Round 245 verification: edge surface (visible flow path + flow
2
+ * rail dashed underline) picks up stroke-color transitions so
3
+ * theme toggle eases instead of snapping.
4
+ *
5
+ * Pre-R245:
6
+ * - [data-edge-visible]: transition = 'opacity 300ms ease-out,
7
+ * stroke-width 300ms ease-out' (R166)
8
+ * - [data-edge-flow-rail]: Tailwind className 'transition-opacity
9
+ * duration-300' (opacity only, no stroke)
10
+ *
11
+ * Post-R245:
12
+ * - [data-edge-visible]: transition list adds 'stroke 300ms ease-
13
+ * out' alongside the existing two
14
+ * - [data-edge-flow-rail]: inline style with both 'opacity' and
15
+ * 'stroke' at 300ms ease-out; Tailwind className dropped
16
+ *
17
+ * Scenario: 4 working agents + 5-msg alpha→beta flow → at least
18
+ * one visible flow + flow-rail pair.
19
+ */
20
+ import { chromium } from 'playwright';
21
+ import { readFileSync } from 'node:fs';
22
+
23
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
24
+ const browser = await chromium.launch({ headless: true });
25
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
26
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
27
+ await ctx.addInitScript(() => {
28
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
29
+ });
30
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
31
+ await ctx.route('**/api/hub/status*', async (route) => {
32
+ const r = await route.fetch();
33
+ const b = await r.json();
34
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
35
+ const mk = (alias) => ({
36
+ alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
37
+ network_id: nid, project_dir: null,
38
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
39
+ });
40
+ await route.fulfill({ response: r, json: { ...b, sessions: [
41
+ mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
42
+ ] } });
43
+ });
44
+ const now = Date.now();
45
+ const msgs = [];
46
+ for (let i = 0; i < 5; i++) {
47
+ msgs.push({
48
+ id: `m${i}`, from_alias: 'alpha', to_alias: 'beta', content: 'hi',
49
+ network_id: 'default', created_at: new Date(now - (1000 + i * 50)).toISOString(),
50
+ });
51
+ }
52
+ await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: msgs } }));
53
+ await ctx.route('**/api/hub/tasks*', (r2) => r2.fulfill({ json: { tasks: [] } }));
54
+
55
+ const page = await ctx.newPage();
56
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
57
+ await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
58
+ await page.waitForSelector('[data-edge-visible]', { timeout: 10000, state: 'attached' });
59
+ await page.waitForSelector('[data-edge-flow-rail]', { timeout: 10000, state: 'attached' });
60
+ await page.waitForTimeout(300);
61
+
62
+ const out = await page.evaluate(() => {
63
+ const probe = (sel) => {
64
+ const el = document.querySelector(sel);
65
+ if (!el) return null;
66
+ return {
67
+ transition: getComputedStyle(el).transition,
68
+ className: el.getAttribute('class') || '',
69
+ stroke: el.getAttribute('stroke'),
70
+ };
71
+ };
72
+ return {
73
+ visible: probe('[data-edge-visible]'),
74
+ rail: probe('[data-edge-flow-rail]'),
75
+ };
76
+ });
77
+ await browser.close();
78
+
79
+ const hasProp = (s, prop) => new RegExp(`${prop}\\s+(?:300ms|0\\.3s)`).test(s || '');
80
+
81
+ const results = {
82
+ visible_present: out.visible !== null,
83
+ visible_has_opacity_300ms: hasProp(out.visible?.transition, 'opacity'),
84
+ visible_has_stroke_width_300ms: hasProp(out.visible?.transition, 'stroke-width'),
85
+ visible_has_stroke_300ms: hasProp(out.visible?.transition, 'stroke'),
86
+
87
+ rail_present: out.rail !== null,
88
+ rail_has_opacity_300ms: hasProp(out.rail?.transition, 'opacity'),
89
+ rail_has_stroke_300ms: hasProp(out.rail?.transition, 'stroke'),
90
+ // Tailwind 'transition-opacity duration-300' className dropped
91
+ // (the inline transition list replaces it; Tailwind would
92
+ // otherwise OVERRIDE the inline stroke transition with its
93
+ // opacity-only declaration)
94
+ rail_no_tailwind_class: !/transition-opacity/.test(out.rail?.className || ''),
95
+ };
96
+ const ok = Object.values(results).every(Boolean);
97
+ console.log(`${ok ? '✅' : '❌'} edge stroke ease:`, JSON.stringify(results),
98
+ '\n visible:', out.visible,
99
+ '\n rail: ', out.rail);
100
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,132 @@
1
+ /* Round 166 verification: visible flow edge path picks up
2
+ * stroke-width transition.
3
+ *
4
+ * R50 thickens hovered edges to 1.4× (renderWidth = width * 1.4)
5
+ * but pre-R166 only opacity transitioned — width snapped. R166
6
+ * adds stroke-width to the transition list so the edge thickens
7
+ * smoothly on hover, pairing with R164 edge-badge r-lift for
8
+ * coordinated 300ms ease-out across the edge surface.
9
+ *
10
+ * Test:
11
+ * 1. Mock 4 sessions + 1 flow alpha→beta
12
+ * 2. Probe visible path before hover → strokeWidth=base
13
+ * 3. Probe transition string includes both opacity and
14
+ * stroke-width
15
+ * 4. Hover edge hitbox → wait 350ms (past transition)
16
+ * 5. Probe strokeWidth → should be ≈ base * 1.4
17
+ * 6. mouse away → strokeWidth back to base
18
+ */
19
+ import { chromium } from 'playwright';
20
+ import { readFileSync } from 'node:fs';
21
+
22
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
23
+ const browser = await chromium.launch({ headless: true });
24
+
25
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
26
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
27
+ await ctx.addInitScript(() => {
28
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
29
+ });
30
+
31
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
32
+ await ctx.route('**/api/hub/status*', async (route) => {
33
+ const r = await route.fetch();
34
+ const b = await r.json();
35
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
36
+ const mk = (alias) => ({
37
+ alias, status: 'working', model: 'claude-opus-4', runtime: 'cli-claude-code',
38
+ network_id: nid, project_dir: null,
39
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
40
+ });
41
+ // 4 sessions so alpha + beta are 90° apart (not 180° — that
42
+ // would put their edge midpoint on the hub, where the hub
43
+ // <g> intercepts pointer events). gamma + delta are filler.
44
+ await route.fulfill({ response: r, json: { ...b, sessions: [
45
+ mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
46
+ ] } });
47
+ });
48
+
49
+ const now = Date.now();
50
+ // 4 msgs so:
51
+ // - width = Math.min(2+4, 7) = 6
52
+ // - hover renderWidth = Math.min(6*1.4, 10) = 8.4
53
+ // AND the edge midpoint count badge renders (R100 threshold
54
+ // count >= 3) so we can use it as the hover surface. The
55
+ // visible path has pointerEvents:none; the R48 hitbox is a
56
+ // thin stroke that Playwright's .hover() can't reliably land
57
+ // on. The badge is a r=9 circle with pointerEvents:all and
58
+ // propagates hover to hoveredEdgeKey (R122) — most reliable
59
+ // target for triggering the visible-path transition.
60
+ const msgs = [];
61
+ for (let i = 0; i < 4; i++) {
62
+ msgs.push({ id: `m${i}`, from_alias: 'alpha', to_alias: 'beta', content: 'hi',
63
+ network_id: 'default', created_at: new Date(now - (10000 + i * 500)).toISOString() });
64
+ }
65
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: msgs } }));
66
+ await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
67
+
68
+ const page = await ctx.newPage();
69
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
70
+ await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
71
+ await page.waitForSelector('[data-edge-visible]', { timeout: 10000 });
72
+ await page.waitForTimeout(400);
73
+
74
+ const idle = await page.evaluate(() => {
75
+ const el = document.querySelector('[data-edge-visible]');
76
+ if (!el) return null;
77
+ return {
78
+ strokeWidth: parseFloat(el.getAttribute('stroke-width')),
79
+ inlineTransition: el.style.transition || '',
80
+ computedTransition: getComputedStyle(el).transition || '',
81
+ };
82
+ });
83
+
84
+ // Hover the edge midpoint badge (R164 r=9 circle, pointerEvents:all,
85
+ // propagates to hoveredEdgeKey via R122). The visible path has
86
+ // pointerEvents:none; the R48 hitbox is a thin stroke that
87
+ // Playwright .hover() can't reliably land on.
88
+ await page.locator('[data-edge-count-badge]').hover();
89
+ // Wait for transition to settle.
90
+ await page.waitForTimeout(400);
91
+ const hovered = await page.evaluate(() => {
92
+ const el = document.querySelector('[data-edge-visible]');
93
+ if (!el) return null;
94
+ return {
95
+ strokeWidth: parseFloat(el.getAttribute('stroke-width')),
96
+ };
97
+ });
98
+
99
+ // Move cursor away
100
+ await page.mouse.move(10, 10);
101
+ await page.waitForTimeout(400);
102
+ const idleAgain = await page.evaluate(() => {
103
+ const el = document.querySelector('[data-edge-visible]');
104
+ if (!el) return null;
105
+ return {
106
+ strokeWidth: parseFloat(el.getAttribute('stroke-width')),
107
+ };
108
+ });
109
+
110
+ await browser.close();
111
+
112
+ const hasOpacity = (idle?.inlineTransition || '').includes('opacity 300ms') ||
113
+ /opacity\s+0\.3s|opacity\s+300ms/.test(idle?.computedTransition || '');
114
+ const hasStrokeWidth = (idle?.inlineTransition || '').includes('stroke-width 300ms') ||
115
+ /stroke-width\s+0\.3s|stroke-width\s+300ms/.test(idle?.computedTransition || '');
116
+
117
+ // Expected: width=Math.min(2+4, 7)=6. Hover renderWidth=Math.min(6*1.4, 10)=8.4.
118
+ const results = {
119
+ edge_found: idle !== null,
120
+ has_opacity_transition: hasOpacity,
121
+ has_stroke_width_transition: hasStrokeWidth,
122
+ idle_width_6: idle && Math.abs(idle.strokeWidth - 6) < 0.05,
123
+ hover_width_8p4: hovered && Math.abs(hovered.strokeWidth - 8.4) < 0.1,
124
+ hover_width_thicker: hovered && idle && hovered.strokeWidth > idle.strokeWidth,
125
+ idle_again_width_6: idleAgain && Math.abs(idleAgain.strokeWidth - 6) < 0.05,
126
+ };
127
+ const ok = Object.values(results).every(Boolean);
128
+ console.log(`${ok ? '✅' : '❌'} edge stroke transition:`, JSON.stringify(results),
129
+ `\n idle =`, idle,
130
+ `\n hovered =`, hovered,
131
+ `\n idleAgain =`, idleAgain);
132
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,70 @@
1
+ /* Round 39 verification: each flow-link path carries a `<title>` with
2
+ * "from → to\nN messages · last <relative>". Tests:
3
+ * - tooltip text shape (route + count + relative time)
4
+ * - singular vs. plural ("1 message" vs "5 messages")
5
+ * - missing last_at falls through cleanly */
6
+ import { chromium } from 'playwright';
7
+ import { readFileSync } from 'node:fs';
8
+
9
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
10
+ const browser = await chromium.launch({ headless: true });
11
+
12
+ const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } });
13
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
14
+ await ctx.addInitScript(() => {
15
+ try {
16
+ localStorage.setItem('anet-theme', 'cyber');
17
+ localStorage.setItem('anet-topo-layout', 'grid');
18
+ sessionStorage.setItem('anet_v3_auth', '1');
19
+ } catch {}
20
+ });
21
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
22
+ await ctx.route('**/api/hub/status*', async (route) => {
23
+ const r = await route.fetch();
24
+ const b = await r.json();
25
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
26
+ const sessions = ['alpha', 'beta', 'gamma'].map(a => ({
27
+ alias: a, status: 'idle', network_id: nid, project_dir: null,
28
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
29
+ }));
30
+ await route.fulfill({ response: r, json: { ...b, sessions } });
31
+ });
32
+ // Inject messages: 1 between alpha→beta (singular), 5 between alpha→gamma (plural).
33
+ const old = new Date(Date.now() - 8 * 60 * 1000).toISOString();
34
+ const recent = new Date(Date.now() - 30 * 1000).toISOString();
35
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [
36
+ { from_alias: 'alpha', to_alias: 'beta', content: 'hello', created_at: old },
37
+ { from_alias: 'alpha', to_alias: 'gamma', content: 'm1', created_at: recent },
38
+ { from_alias: 'alpha', to_alias: 'gamma', content: 'm2', created_at: recent },
39
+ { from_alias: 'alpha', to_alias: 'gamma', content: 'm3', created_at: recent },
40
+ { from_alias: 'alpha', to_alias: 'gamma', content: 'm4', created_at: recent },
41
+ { from_alias: 'alpha', to_alias: 'gamma', content: 'm5', created_at: recent },
42
+ ] } }));
43
+ await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
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 === 3, { timeout: 30000 });
47
+ await page.waitForTimeout(600);
48
+
49
+ // Collect every flow-link tooltip (each base path with a child <title>).
50
+ const tooltips = await page.evaluate(() => {
51
+ const svg = document.querySelector('svg[viewBox="0 0 1000 680"]');
52
+ // Two paths per flow link — the base one carries the <title>.
53
+ const titled = [...svg.querySelectorAll('path > title')];
54
+ return titled.map(t => t.textContent);
55
+ });
56
+
57
+ await browser.close();
58
+ const has = (route, count, plural) => tooltips.some(t =>
59
+ t.includes(route) &&
60
+ (plural ? t.includes(`${count} messages`) : t.includes(`${count} message`)) &&
61
+ /last \w+ ago/.test(t)
62
+ );
63
+ const results = {
64
+ singularAlphaToBeta: has('alpha → beta', 1, false),
65
+ pluralAlphaToGamma: has('alpha → gamma', 5, true),
66
+ tooltipCount: tooltips.length === 2,
67
+ };
68
+ const ok = Object.values(results).every(Boolean);
69
+ console.log(`${ok ? '✅' : '❌'} edge tooltip:`, JSON.stringify(results), '\n tooltips=', tooltips);
70
+ process.exit(ok ? 0 : 1);