@sleep2agi/agent-network-dashboard 0.5.3-preview.26 → 0.5.3-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 (399) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +3 -3
  3. package/.next/diagnostics/route-bundle-stats.json +7 -7
  4. package/.next/fallback-build-manifest.json +3 -3
  5. package/.next/server/app/_global-error.html +1 -1
  6. package/.next/server/app/_global-error.rsc +1 -1
  7. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  13. package/.next/server/app/_not-found.html +2 -2
  14. package/.next/server/app/_not-found.rsc +2 -2
  15. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  16. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  18. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  22. package/.next/server/app/admin.html +2 -2
  23. package/.next/server/app/admin.rsc +2 -2
  24. package/.next/server/app/admin.segments/_full.segment.rsc +2 -2
  25. package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
  26. package/.next/server/app/admin.segments/_index.segment.rsc +2 -2
  27. package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
  28. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +1 -1
  29. package/.next/server/app/admin.segments/admin.segment.rsc +1 -1
  30. package/.next/server/app/index.html +2 -2
  31. package/.next/server/app/index.rsc +3 -3
  32. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  33. package/.next/server/app/index.segments/_full.segment.rsc +3 -3
  34. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  35. package/.next/server/app/index.segments/_index.segment.rsc +2 -2
  36. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  37. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  38. package/.next/server/app/login.html +2 -2
  39. package/.next/server/app/login.rsc +3 -3
  40. package/.next/server/app/login.segments/_full.segment.rsc +3 -3
  41. package/.next/server/app/login.segments/_head.segment.rsc +1 -1
  42. package/.next/server/app/login.segments/_index.segment.rsc +2 -2
  43. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  44. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  45. package/.next/server/app/login.segments/login.segment.rsc +1 -1
  46. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  47. package/.next/server/app/logs.html +2 -2
  48. package/.next/server/app/logs.rsc +2 -2
  49. package/.next/server/app/logs.segments/_full.segment.rsc +2 -2
  50. package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
  51. package/.next/server/app/logs.segments/_index.segment.rsc +2 -2
  52. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  53. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +1 -1
  54. package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
  55. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  56. package/.next/server/app/messages.html +2 -2
  57. package/.next/server/app/messages.rsc +2 -2
  58. package/.next/server/app/messages.segments/_full.segment.rsc +2 -2
  59. package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
  60. package/.next/server/app/messages.segments/_index.segment.rsc +2 -2
  61. package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
  62. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +1 -1
  63. package/.next/server/app/messages.segments/messages.segment.rsc +1 -1
  64. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  65. package/.next/server/app/node.html +2 -2
  66. package/.next/server/app/node.rsc +2 -2
  67. package/.next/server/app/node.segments/_full.segment.rsc +2 -2
  68. package/.next/server/app/node.segments/_head.segment.rsc +1 -1
  69. package/.next/server/app/node.segments/_index.segment.rsc +2 -2
  70. package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
  71. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +1 -1
  72. package/.next/server/app/node.segments/node.segment.rsc +1 -1
  73. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  74. package/.next/server/app/nodes.html +2 -2
  75. package/.next/server/app/nodes.rsc +2 -2
  76. package/.next/server/app/nodes.segments/_full.segment.rsc +2 -2
  77. package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
  78. package/.next/server/app/nodes.segments/_index.segment.rsc +2 -2
  79. package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
  80. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +1 -1
  81. package/.next/server/app/nodes.segments/nodes.segment.rsc +1 -1
  82. package/.next/server/app/page_client-reference-manifest.js +1 -1
  83. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  84. package/.next/server/app/server-logs.html +2 -2
  85. package/.next/server/app/server-logs.rsc +2 -2
  86. package/.next/server/app/server-logs.segments/_full.segment.rsc +2 -2
  87. package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
  88. package/.next/server/app/server-logs.segments/_index.segment.rsc +2 -2
  89. package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
  90. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +1 -1
  91. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +1 -1
  92. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  93. package/.next/server/app/settings/networks.html +2 -2
  94. package/.next/server/app/settings/networks.rsc +2 -2
  95. package/.next/server/app/settings/networks.segments/_full.segment.rsc +2 -2
  96. package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
  97. package/.next/server/app/settings/networks.segments/_index.segment.rsc +2 -2
  98. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
  99. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +1 -1
  100. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +1 -1
  101. package/.next/server/app/settings/networks.segments/settings.segment.rsc +1 -1
  102. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  103. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  104. package/.next/server/app/settings/tokens.html +2 -2
  105. package/.next/server/app/settings/tokens.rsc +2 -2
  106. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +2 -2
  107. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
  108. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +2 -2
  109. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
  110. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +1 -1
  111. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +1 -1
  112. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +1 -1
  113. package/.next/server/app/settings.html +2 -2
  114. package/.next/server/app/settings.rsc +3 -3
  115. package/.next/server/app/settings.segments/_full.segment.rsc +3 -3
  116. package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  117. package/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  118. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  119. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
  120. package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  121. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  122. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  123. package/.next/server/app/tasks.html +2 -2
  124. package/.next/server/app/tasks.rsc +2 -2
  125. package/.next/server/app/tasks.segments/_full.segment.rsc +2 -2
  126. package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
  127. package/.next/server/app/tasks.segments/_index.segment.rsc +2 -2
  128. package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
  129. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +1 -1
  130. package/.next/server/app/tasks.segments/tasks.segment.rsc +1 -1
  131. package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js +1 -1
  132. package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js.map +1 -1
  133. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js +1 -1
  134. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +1 -1
  135. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +4 -4
  136. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
  137. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
  138. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
  139. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
  140. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
  141. package/.next/server/middleware-build-manifest.js +3 -3
  142. package/.next/server/pages/404.html +2 -2
  143. package/.next/server/pages/500.html +1 -1
  144. package/.next/static/chunks/{05uydm8okqgqe.js → 0-vlr8~b0f-cx.js} +1 -1
  145. package/.next/static/chunks/08.pwokcpknmp.js +1 -0
  146. package/.next/static/chunks/0nd-y~i5proep.js +1 -0
  147. package/.next/static/chunks/0ztakmtfxkgya.js +4 -0
  148. package/.next/static/chunks/16-7qr7qx9zrz.css +2 -0
  149. package/.next/trace +2 -2
  150. package/.next/trace-build +1 -1
  151. package/app/api/hub/servers/route.ts +3 -29
  152. package/app/components/TopoGraph.tsx +6588 -201
  153. package/app/globals.css +897 -7
  154. package/app/lib/serverDedupe.ts +122 -0
  155. package/app/lib/vendorIdentity.ts +74 -56
  156. package/package.json +4 -4
  157. package/public/vendors/claude.svg +7 -8
  158. package/public/vendors/minimax.svg +8 -9
  159. package/public/vendors/openai.svg +8 -10
  160. package/scripts/p157-rc2-dedup-test.mjs +110 -0
  161. package/scripts/topo-a11y-titles-catalog-test.mjs +132 -0
  162. package/scripts/topo-active-chrome-hover-text-test.mjs +107 -0
  163. package/scripts/topo-active-links-chip-halo-layers-test.mjs +81 -0
  164. package/scripts/topo-alias-chat-brightness-test.mjs +79 -0
  165. package/scripts/topo-alias-text-halo-layers-test.mjs +98 -0
  166. package/scripts/topo-animation-temporal-modes-catalog-test.mjs +144 -0
  167. package/scripts/topo-avatar-chat-gate-test.mjs +77 -0
  168. package/scripts/topo-avatar-drop-shadow-test.mjs +86 -0
  169. package/scripts/topo-avatar-fallback-hover-test.mjs +104 -0
  170. package/scripts/topo-avatar-fallback-rotate-test.mjs +92 -0
  171. package/scripts/topo-avatar-rotate-test.mjs +85 -0
  172. package/scripts/topo-avatar-scale-test.mjs +89 -0
  173. package/scripts/topo-badge-chat-gate-test.mjs +74 -0
  174. package/scripts/topo-brand-drop-shadow-test.mjs +71 -0
  175. package/scripts/topo-brand-logo-breath-test.mjs +102 -0
  176. package/scripts/topo-brand-logo-halo-layers-test.mjs +85 -0
  177. package/scripts/topo-brand-logo-hover-brightness-test.mjs +105 -0
  178. package/scripts/topo-brand-logo-hover-rotate-test.mjs +93 -0
  179. package/scripts/topo-brand-logo-hover-test.mjs +85 -0
  180. package/scripts/topo-canvas-desc-a11y-test.mjs +87 -0
  181. package/scripts/topo-canvas-entrance-animation-test.mjs +117 -0
  182. package/scripts/topo-canvas-scan-beam-diagonal-test.mjs +148 -0
  183. package/scripts/topo-canvas-scan-beam-test.mjs +109 -0
  184. package/scripts/topo-canvas-scan-beam-vertical-test.mjs +123 -0
  185. package/scripts/topo-card-chat-brightness-test.mjs +86 -0
  186. package/scripts/topo-chat-ring-breath-curve-test.mjs +114 -0
  187. package/scripts/topo-chat-ring-brightness-test.mjs +80 -0
  188. package/scripts/topo-chat-ring-halo-layers-test.mjs +100 -0
  189. package/scripts/topo-chat-ring-r-breath-test.mjs +121 -0
  190. package/scripts/topo-chat-ring-status-halo-test.mjs +106 -0
  191. package/scripts/topo-chat-ring-sw-breath-test.mjs +123 -0
  192. package/scripts/topo-chip-pin-halo-test.mjs +85 -0
  193. package/scripts/topo-chip-row-digit-ls-test.mjs +135 -0
  194. package/scripts/topo-chip-row-member-alias-lit-test.mjs +154 -0
  195. package/scripts/topo-chip-row-tier-glow-brightness-test.mjs +99 -0
  196. package/scripts/topo-chip-row-unit-hover-tracking-test.mjs +124 -0
  197. package/scripts/topo-chrome-control-halo-layers-test.mjs +22 -0
  198. package/scripts/topo-chrome-fullscreen-breath-test.mjs +121 -0
  199. package/scripts/topo-chrome-layout-trailer-breath-test.mjs +86 -0
  200. package/scripts/topo-chrome-nodesize-trailer-breath-test.mjs +86 -0
  201. package/scripts/topo-chrome-reset-breath-test.mjs +115 -0
  202. package/scripts/topo-chrome-strip-entrance-animation-test.mjs +115 -0
  203. package/scripts/topo-chrome-wrapper-halo-test.mjs +83 -0
  204. package/scripts/topo-chrome-zoom-wrapper-breath-test.mjs +85 -0
  205. package/scripts/topo-click-ripple-glow-test.mjs +86 -0
  206. package/scripts/topo-click-ripple-halo-layers-test.mjs +79 -0
  207. package/scripts/topo-click-ripple-sw-test.mjs +110 -0
  208. package/scripts/topo-crescent-breath-test.mjs +104 -0
  209. package/scripts/topo-crescent-envelope-breath-test.mjs +103 -0
  210. package/scripts/topo-crescent-recede-test.mjs +111 -0
  211. package/scripts/topo-dense-alias-chat-halo-test.mjs +73 -0
  212. package/scripts/topo-dense-alias-halo-layers-test.mjs +80 -0
  213. package/scripts/topo-dual-axis-surfaces-catalog-test.mjs +94 -0
  214. package/scripts/topo-edge-badge-circle-brightness-test.mjs +82 -0
  215. package/scripts/topo-edge-badge-circle-hot-pulse-test.mjs +100 -0
  216. package/scripts/topo-edge-badge-digit-halo-layers-test.mjs +107 -0
  217. package/scripts/topo-edge-badge-endpoint-gate-test.mjs +94 -0
  218. package/scripts/topo-edge-badge-halo-layers-test.mjs +85 -0
  219. package/scripts/topo-edge-badge-hot-pulse-test.mjs +92 -0
  220. package/scripts/topo-edge-badge-hover-glow-test.mjs +90 -0
  221. package/scripts/topo-edge-badge-text-brightness-test.mjs +83 -0
  222. package/scripts/topo-edge-chat-gate-test.mjs +71 -0
  223. package/scripts/topo-edge-flow-rail-halo-layers-test.mjs +89 -0
  224. package/scripts/topo-edge-particle-brightness-test.mjs +82 -0
  225. package/scripts/topo-edge-particle-halo-layers-test.mjs +91 -0
  226. package/scripts/topo-edge-pill-glow-test.mjs +67 -0
  227. package/scripts/topo-edge-pin-halo-test.mjs +99 -0
  228. package/scripts/topo-edge-visible-brightness-test.mjs +84 -0
  229. package/scripts/topo-edge-visible-halo-layers-test.mjs +87 -0
  230. package/scripts/topo-endpoint-ring-brightness-test.mjs +83 -0
  231. package/scripts/topo-endpoint-ring-flow-halo-test.mjs +107 -0
  232. package/scripts/topo-endpoint-ring-halo-layers-test.mjs +100 -0
  233. package/scripts/topo-filter-pill-glow-test.mjs +90 -0
  234. package/scripts/topo-filter-pill-halo-layers-test.mjs +27 -0
  235. package/scripts/topo-flow-arrow-brightness-test.mjs +82 -0
  236. package/scripts/topo-flow-rail-brightness-test.mjs +80 -0
  237. package/scripts/topo-fullscreen-attr-test.mjs +73 -0
  238. package/scripts/topo-fullscreen-brightness-test.mjs +84 -0
  239. package/scripts/topo-fullscreen-icon-rotate-test.mjs +93 -0
  240. package/scripts/topo-grid-content-bottom-attr-test.mjs +72 -0
  241. package/scripts/topo-group-box-brightness-test.mjs +84 -0
  242. package/scripts/topo-group-box-halo-layers-test.mjs +91 -0
  243. package/scripts/topo-group-chat-gate-test.mjs +77 -0
  244. package/scripts/topo-group-label-brightness-test.mjs +84 -0
  245. package/scripts/topo-group-label-halo-layers-test.mjs +78 -0
  246. package/scripts/topo-group-label-hover-glow-test.mjs +86 -0
  247. package/scripts/topo-group-label-member-alias-hover-test.mjs +125 -0
  248. package/scripts/topo-group-pill-glow-test.mjs +76 -0
  249. package/scripts/topo-group-tint-brightness-test.mjs +82 -0
  250. package/scripts/topo-h2-dual-axis-breath-test.mjs +92 -0
  251. package/scripts/topo-h2-triple-axis-breath-test.mjs +142 -0
  252. package/scripts/topo-halo-chat-gate-test.mjs +72 -0
  253. package/scripts/topo-hover-detail-halo-test.mjs +76 -0
  254. package/scripts/topo-hub-a11y-title-test.mjs +95 -0
  255. package/scripts/topo-hub-core-brightness-test.mjs +82 -0
  256. package/scripts/topo-hub-core-halo-layers-test.mjs +81 -0
  257. package/scripts/topo-hub-digit-brightness-test.mjs +79 -0
  258. package/scripts/topo-hub-digit-halo-layers-test.mjs +76 -0
  259. package/scripts/topo-hub-digit-ls-test.mjs +119 -0
  260. package/scripts/topo-hub-halo-brightness-test.mjs +80 -0
  261. package/scripts/topo-hub-halo-glow-test.mjs +96 -0
  262. package/scripts/topo-hub-halo-halo-layers-test.mjs +76 -0
  263. package/scripts/topo-hub-highlight-brightness-test.mjs +84 -0
  264. package/scripts/topo-hub-highlight-glow-test.mjs +99 -0
  265. package/scripts/topo-hub-highlight-halo-layers-test.mjs +78 -0
  266. package/scripts/topo-hub-highlight-r-test.mjs +112 -0
  267. package/scripts/topo-hub-hover-ring-brightness-test.mjs +79 -0
  268. package/scripts/topo-hub-hover-ring-glow-test.mjs +97 -0
  269. package/scripts/topo-hub-hover-ring-halo-layers-test.mjs +71 -0
  270. package/scripts/topo-hub-spoke-brightness-test.mjs +77 -0
  271. package/scripts/topo-hub-spoke-glow-test.mjs +112 -0
  272. package/scripts/topo-hub-spoke-halo-layers-test.mjs +97 -0
  273. package/scripts/topo-hub-spoke-self-filter-test.mjs +119 -0
  274. package/scripts/topo-kicker-breath-test.mjs +100 -0
  275. package/scripts/topo-kicker-dual-axis-breath-test.mjs +81 -0
  276. package/scripts/topo-kicker-halo-layers-test.mjs +82 -0
  277. package/scripts/topo-kicker-triple-axis-breath-test.mjs +124 -0
  278. package/scripts/topo-label-card-brightness-test.mjs +81 -0
  279. package/scripts/topo-layout-hover-fw-test.mjs +98 -0
  280. package/scripts/topo-layout-toggle-brightness-test.mjs +94 -0
  281. package/scripts/topo-layout-toggle-halo-layers-test.mjs +95 -0
  282. package/scripts/topo-legend-count-brightness-test.mjs +80 -0
  283. package/scripts/topo-legend-count-halo-layers-test.mjs +79 -0
  284. package/scripts/topo-legend-count-letter-spacing-test.mjs +108 -0
  285. package/scripts/topo-legend-label-fw-test.mjs +107 -0
  286. package/scripts/topo-legend-panel-title-breath-test.mjs +86 -0
  287. package/scripts/topo-legend-pin-ring-brightness-test.mjs +82 -0
  288. package/scripts/topo-legend-pin-ring-halo-layers-test.mjs +71 -0
  289. package/scripts/topo-legend-row-count-brightness-test.mjs +85 -0
  290. package/scripts/topo-legend-row-label-glow-test.mjs +102 -0
  291. package/scripts/topo-legend-swatch-glow-test.mjs +109 -0
  292. package/scripts/topo-legend-swatch-member-alias-match-test.mjs +139 -0
  293. package/scripts/topo-legend-tint-brightness-test.mjs +83 -0
  294. package/scripts/topo-legend-trio-halo-layers-test.mjs +22 -0
  295. package/scripts/topo-minimap-container-halo-test.mjs +82 -0
  296. package/scripts/topo-minimap-dot-chat-gate-test.mjs +81 -0
  297. package/scripts/topo-minimap-hover-glow-test.mjs +109 -0
  298. package/scripts/topo-minimap-viewport-brightness-test.mjs +84 -0
  299. package/scripts/topo-minimap-viewport-halo-layers-test.mjs +24 -0
  300. package/scripts/topo-more-footer-brightness-test.mjs +94 -0
  301. package/scripts/topo-node-alias-brightness-test.mjs +84 -0
  302. package/scripts/topo-node-avatar-halo-layers-test.mjs +25 -0
  303. package/scripts/topo-node-hover-ring-halo-layers-test.mjs +70 -0
  304. package/scripts/topo-node-label-card-halo-test.mjs +76 -0
  305. package/scripts/topo-node-sub-text-brightness-test.mjs +88 -0
  306. package/scripts/topo-nodesize-brightness-test.mjs +82 -0
  307. package/scripts/topo-nodesize-halo-layers-test.mjs +89 -0
  308. package/scripts/topo-nodesize-hover-fw-test.mjs +99 -0
  309. package/scripts/topo-orphan-label-opacity-test.mjs +98 -0
  310. package/scripts/topo-overlap-test.mjs +22 -8
  311. package/scripts/topo-panel-count-halo-layers-test.mjs +91 -0
  312. package/scripts/topo-panel-count-hover-ls-test.mjs +87 -0
  313. package/scripts/topo-panel-rect-halo-test.mjs +90 -0
  314. package/scripts/topo-panel-row-brightness-test.mjs +116 -0
  315. package/scripts/topo-panel-title-brightness-test.mjs +98 -0
  316. package/scripts/topo-panel-title-glow-test.mjs +111 -0
  317. package/scripts/topo-panel-titles-dual-axis-breath-test.mjs +94 -0
  318. package/scripts/topo-panel-titles-halo-layers-test.mjs +23 -0
  319. package/scripts/topo-panel-titles-triple-axis-breath-test.mjs +161 -0
  320. package/scripts/topo-pill-x-rotate-test.mjs +96 -0
  321. package/scripts/topo-pip-brightness-test.mjs +85 -0
  322. package/scripts/topo-pressure-bar-halo-layers-test.mjs +19 -0
  323. package/scripts/topo-pressure-seg-glow-test.mjs +92 -0
  324. package/scripts/topo-pressure-seg-member-alias-match-test.mjs +133 -0
  325. package/scripts/topo-pressure-seg-motion-test.mjs +101 -0
  326. package/scripts/topo-r717-scan-beam-pair-pattern-test.mjs +100 -0
  327. package/scripts/topo-r717-triple-axis-pair-pattern-test.mjs +113 -0
  328. package/scripts/topo-r717-triple-axis-tier-pattern-test.mjs +117 -0
  329. package/scripts/topo-recent-count-brightness-test.mjs +84 -0
  330. package/scripts/topo-recent-more-fw-test.mjs +126 -0
  331. package/scripts/topo-recent-more-halo-layers-test.mjs +90 -0
  332. package/scripts/topo-recent-panel-hot-pulse-test.mjs +105 -0
  333. package/scripts/topo-recent-panel-title-breath-test.mjs +91 -0
  334. package/scripts/topo-recent-pip-halo-layers-test.mjs +82 -0
  335. package/scripts/topo-recent-row-chat-gate-test.mjs +75 -0
  336. package/scripts/topo-recent-row-content-lift-test.mjs +140 -0
  337. package/scripts/topo-recent-row-fw-test.mjs +115 -0
  338. package/scripts/topo-recent-row-text-glow-test.mjs +86 -0
  339. package/scripts/topo-recent-row-text-halo-layers-test.mjs +67 -0
  340. package/scripts/topo-recent-tint-brightness-test.mjs +80 -0
  341. package/scripts/topo-recent-ts-brightness-test.mjs +86 -0
  342. package/scripts/topo-reduced-motion-attr-test.mjs +69 -0
  343. package/scripts/topo-reset-brightness-test.mjs +83 -0
  344. package/scripts/topo-reset-icon-hover-scale-test.mjs +102 -0
  345. package/scripts/topo-respiratory-axis-count-stats-test.mjs +154 -0
  346. package/scripts/topo-respiratory-patterns-catalog-test.mjs +112 -0
  347. package/scripts/topo-respiratory-rolodex-test.mjs +83 -0
  348. package/scripts/topo-respiratory-tiers-catalog-test.mjs +119 -0
  349. package/scripts/topo-respiratory-triple-axis-surfaces-catalog-test.mjs +127 -0
  350. package/scripts/topo-runtime-badge-brightness-test.mjs +78 -0
  351. package/scripts/topo-runtime-badge-glow-test.mjs +108 -0
  352. package/scripts/topo-runtime-badge-halo-layers-test.mjs +87 -0
  353. package/scripts/topo-runtime-badge-rotate-test.mjs +85 -0
  354. package/scripts/topo-section-title-breath-test.mjs +83 -0
  355. package/scripts/topo-section-title-halo-layers-test.mjs +88 -0
  356. package/scripts/topo-spoke-chat-gate-test.mjs +72 -0
  357. package/scripts/topo-starfield-hue-test.mjs +109 -0
  358. package/scripts/topo-status-pin-pill-halo-layers-test.mjs +17 -0
  359. package/scripts/topo-status-ring-brightness-test.mjs +84 -0
  360. package/scripts/topo-status-ring-chat-gate-test.mjs +72 -0
  361. package/scripts/topo-status-ring-halo-layers-test.mjs +105 -0
  362. package/scripts/topo-status-ring-status-halo-test.mjs +110 -0
  363. package/scripts/topo-sub-text-chat-brightness-test.mjs +81 -0
  364. package/scripts/topo-svg-title-a11y-r731-test.mjs +93 -0
  365. package/scripts/topo-svg-title-a11y-test.mjs +88 -0
  366. package/scripts/topo-title-block-entrance-animation-test.mjs +127 -0
  367. package/scripts/topo-title-block-envelope-breath-test.mjs +87 -0
  368. package/scripts/topo-titleblock-h2-hover-fw-test.mjs +109 -0
  369. package/scripts/topo-titleblock-h2-hover-tracking-test.mjs +128 -0
  370. package/scripts/topo-titleblock-kicker-hover-test.mjs +134 -0
  371. package/scripts/topo-tree-diag.mjs +95 -0
  372. package/scripts/topo-vendor-chip-glow-test.mjs +97 -0
  373. package/scripts/topo-vendor-chip-halo-layers-test.mjs +18 -0
  374. package/scripts/topo-vendor-chip-pin-halo-test.mjs +88 -0
  375. package/scripts/topo-vendor-count-suffix-halo-layers-test.mjs +79 -0
  376. package/scripts/topo-vendor-distribution-wrapper-halo-test.mjs +93 -0
  377. package/scripts/topo-vendor-letter-halo-layers-test.mjs +93 -0
  378. package/scripts/topo-vendor-pill-glow-test.mjs +98 -0
  379. package/scripts/topo-watermark-breath-test.mjs +100 -0
  380. package/scripts/topo-watermark-dual-axis-breath-test.mjs +88 -0
  381. package/scripts/topo-watermark-envelope-breath-test.mjs +88 -0
  382. package/scripts/topo-watermark-recede-test.mjs +114 -0
  383. package/scripts/topo-watermark-triple-axis-breath-test.mjs +129 -0
  384. package/scripts/topo-working-online-chip-halo-layers-test.mjs +94 -0
  385. package/scripts/topo-zoom-buttons-brightness-test.mjs +94 -0
  386. package/scripts/topo-zoom-in-out-halo-layers-test.mjs +97 -0
  387. package/scripts/topo-zoom-level-breath-test.mjs +87 -0
  388. package/scripts/topo-zoom-level-brightness-test.mjs +83 -0
  389. package/scripts/topo-zoom-level-color-test.mjs +105 -0
  390. package/scripts/topo-zoom-level-dual-axis-breath-test.mjs +83 -0
  391. package/scripts/topo-zoom-level-halo-layers-test.mjs +78 -0
  392. package/scripts/topo-zoom-level-triple-axis-breath-test.mjs +148 -0
  393. package/.next/static/chunks/0b57cx-~yee9s.js +0 -1
  394. package/.next/static/chunks/0c5ux9rrl-j.a.js +0 -4
  395. package/.next/static/chunks/0ixrbcha76lse.js +0 -1
  396. package/.next/static/chunks/0m.1mvl~t.avc.css +0 -2
  397. /package/.next/static/{fAHTff4Obp5vYwjZIWEvA → CLsgsYpGMRUiIcJJK3xkR}/_buildManifest.js +0 -0
  398. /package/.next/static/{fAHTff4Obp5vYwjZIWEvA → CLsgsYpGMRUiIcJJK3xkR}/_clientMiddlewareManifest.js +0 -0
  399. /package/.next/static/{fAHTff4Obp5vYwjZIWEvA → CLsgsYpGMRUiIcJJK3xkR}/_ssgManifest.js +0 -0
@@ -0,0 +1,114 @@
1
+ /* Round 641 — chat-target ring 3-axis breath SMIL animates gain
2
+ * canonical CSS ease-in-out keySplines (0.42 0 0.58 1, twice for
3
+ * both halves). All three animates (opacity, stroke-width, r)
4
+ * share the same curve so the breath settles at endpoints
5
+ * and accelerates through midpoints — heart-rest organic feel.
6
+ *
7
+ * Test phases:
8
+ * 1. mock 2 idle nodes, no chat → ring at rest, breath-curve='none'
9
+ * 2. click a·1 → 3 animates concurrently with:
10
+ * - calcMode='spline'
11
+ * - keyTimes='0;0.5;1'
12
+ * - keySplines='0.42 0 0.58 1;0.42 0 0.58 1'
13
+ * 3. breath-curve attr === 'ease-in-out'
14
+ * 4. source: all 3 animates carry the new attrs
15
+ */
16
+ import { chromium } from 'playwright';
17
+ import { readFileSync } from 'node:fs';
18
+
19
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
20
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
21
+
22
+ const browser = await chromium.launch({ headless: true });
23
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
24
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
25
+ await ctx.addInitScript(() => {
26
+ try {
27
+ localStorage.setItem('anet-theme', 'cyber');
28
+ localStorage.setItem('anet-topo-layout', 'ring');
29
+ sessionStorage.setItem('anet_v3_auth', '1');
30
+ } catch {}
31
+ });
32
+ await ctx.route('**/api/hub/status*', async (route) => {
33
+ const r = await route.fetch();
34
+ const b = await r.json();
35
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
36
+ const mk = (alias) => ({
37
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
38
+ network_id: nid, project_dir: null,
39
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
40
+ });
41
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
42
+ });
43
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
44
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
45
+ const page = await ctx.newPage();
46
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
47
+ await page.waitForSelector('[data-chat-target-ring]', { timeout: 15000, state: 'attached' });
48
+ await page.waitForTimeout(500);
49
+
50
+ const rest = await page.evaluate(() => {
51
+ const el = document.querySelector('[data-chat-target-ring]');
52
+ if (!el) return null;
53
+ return {
54
+ curve: el.getAttribute('data-chat-target-ring-breath-curve'),
55
+ active: el.getAttribute('data-chat-target-active'),
56
+ };
57
+ });
58
+
59
+ await page.click('[data-node="a·1"]', { force: true });
60
+ await page.waitForTimeout(400);
61
+
62
+ const active = await page.evaluate(() => {
63
+ const node = document.querySelector('[data-node="a·1"]');
64
+ if (!node) return null;
65
+ const ring = node.querySelector('[data-chat-target-ring]');
66
+ if (!ring) return null;
67
+ const animates = Array.from(ring.querySelectorAll('animate'));
68
+ return {
69
+ curve: ring.getAttribute('data-chat-target-ring-breath-curve'),
70
+ active: ring.getAttribute('data-chat-target-active'),
71
+ animateAttrs: animates.map(a => ({
72
+ attr: a.getAttribute('attributeName'),
73
+ calc: a.getAttribute('calcMode'),
74
+ kt: a.getAttribute('keyTimes'),
75
+ ks: a.getAttribute('keySplines'),
76
+ })),
77
+ };
78
+ });
79
+
80
+ await browser.close();
81
+
82
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
83
+ // Each of the 3 animates should carry the same spline attrs
84
+ const splineAttrPattern = /calcMode="spline"\s+keyTimes="0;0\.5;1"\s+keySplines="0\.42 0 0\.58 1;0\.42 0 0\.58 1"/g;
85
+ const splineMatches = (src.match(splineAttrPattern) || []).length;
86
+ const sourceCurveAttr = /data-chat-target-ring-breath-curve=\{!reducedMotion && isChat \? 'ease-in-out' : 'none'\}/.test(src);
87
+
88
+ const allHaveSpline = active?.animateAttrs?.length === 3 && active.animateAttrs.every(a =>
89
+ a.calc === 'spline' &&
90
+ a.kt === '0;0.5;1' &&
91
+ a.ks === '0.42 0 0.58 1;0.42 0 0.58 1'
92
+ );
93
+
94
+ const results = {
95
+ rest_curve_none: rest?.curve === 'none',
96
+ active_curve_ease: active?.curve === 'ease-in-out',
97
+ active_animate_count_3: active?.animateAttrs?.length === 3,
98
+ active_all_have_spline: allHaveSpline,
99
+ active_has_opacity: active?.animateAttrs?.some(a => a.attr === 'opacity'),
100
+ active_has_sw: active?.animateAttrs?.some(a => a.attr === 'stroke-width'),
101
+ active_has_r: active?.animateAttrs?.some(a => a.attr === 'r'),
102
+ // Multiple SMIL ease-in-out splines exist across the file (R243 active-
103
+ // pulse, R244 hub-halo, plus 3 new chat-target ring animates). Assert
104
+ // count >= 3 — runtime block already verifies the 3 chat-target ring
105
+ // animates carry the exact attrs.
106
+ source_at_least_3_splines: splineMatches >= 3,
107
+ source_curve_attr: sourceCurveAttr,
108
+ };
109
+ const ok = Object.values(results).every(Boolean);
110
+ console.log(`${ok ? '✅' : '❌'} R641 chat-target ring 3-axis breath ease-in-out keySplines:`,
111
+ JSON.stringify(results, null, 2),
112
+ `\n rest: ${JSON.stringify(rest)}`,
113
+ `\n active: ${JSON.stringify(active)}`);
114
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,80 @@
1
+ /* 🎯 Round 615 — 100th consecutive visible-polish round milestone.
2
+ * Chat-target ring stacks brightness(1.15) onto url(#topo-glow)
3
+ * on isChat=true. Introduces a NEW 4th brightness gate type:
4
+ * chat-target-gated.
5
+ *
6
+ * Test phases:
7
+ * 1. mock 2 idle nodes → chat ring renders (opacity 0 at rest)
8
+ * 2. rest (no chat target): filter='none', brightness-attr='1',
9
+ * active='false'
10
+ * 3. computed transition-property contains 'filter'
11
+ * 4. source: stacked filter conditional + data-attr
12
+ */
13
+ import { chromium } from 'playwright';
14
+ import { readFileSync } from 'node:fs';
15
+
16
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
17
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
18
+
19
+ const browser = await chromium.launch({ headless: true });
20
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
21
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
22
+ await ctx.addInitScript(() => {
23
+ try {
24
+ localStorage.setItem('anet-theme', 'cyber');
25
+ localStorage.setItem('anet-topo-layout', 'ring');
26
+ sessionStorage.setItem('anet_v3_auth', '1');
27
+ } catch {}
28
+ });
29
+ await ctx.route('**/api/hub/status*', async (route) => {
30
+ const r = await route.fetch();
31
+ const b = await r.json();
32
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
33
+ const mk = (alias) => ({
34
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
35
+ network_id: nid, project_dir: null,
36
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
37
+ });
38
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
39
+ });
40
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
41
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
42
+ const page = await ctx.newPage();
43
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
44
+ await page.waitForSelector('[data-chat-target-ring]', { timeout: 15000, state: 'attached' });
45
+ await page.waitForTimeout(500);
46
+
47
+ const rest = await page.evaluate(() => {
48
+ const el = document.querySelector('[data-chat-target-ring]');
49
+ if (!el) return null;
50
+ const cs = getComputedStyle(el);
51
+ return {
52
+ filter: cs.filter,
53
+ opacity: cs.opacity,
54
+ transitionProperty: cs.transitionProperty,
55
+ brightnessAttr: el.getAttribute('data-node-chat-ring-brightness'),
56
+ activeAttr: el.getAttribute('data-chat-target-active'),
57
+ };
58
+ });
59
+
60
+ await browser.close();
61
+
62
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
63
+ const sourceFilter = /filter: isChat\s*\?\s*\(isLight\s*\?\s*'brightness\(1\.15\)'\s*:\s*'url\(#topo-glow\) brightness\(1\.15\)'\)\s*:\s*undefined/.test(src);
64
+ const sourceAttr = /data-node-chat-ring-brightness=\{isChat \? '1\.15' : '1'\}/.test(src);
65
+
66
+ const results = {
67
+ ring_present: !!rest,
68
+ rest_filter_none: rest?.filter === 'none',
69
+ rest_opacity_zero: parseFloat(rest?.opacity || '1') === 0,
70
+ rest_brightness_1: rest?.brightnessAttr === '1',
71
+ rest_active_false: rest?.activeAttr === 'false',
72
+ transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
73
+ source_filter: sourceFilter,
74
+ source_attr: sourceAttr,
75
+ };
76
+ const ok = Object.values(results).every(Boolean);
77
+ console.log(`${ok ? '✅' : '❌'} 🎯 R615 chat-target ring brightness (NEW chat-target-gated brightness, 100 rounds milestone):`,
78
+ JSON.stringify(results, null, 2),
79
+ `\n rest: ${JSON.stringify(rest)}`);
80
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,100 @@
1
+ /* Round 642 — chat-target ring gains a SECOND drop-shadow layer
2
+ * at 6px blur + 20% alpha, layered with R637's 3px+40% halo. The
3
+ * chat partner now radiates a "near + far" layered glow vocabulary.
4
+ *
5
+ * Test phases:
6
+ * 1. rest: no chat, halo-layers='0', filter='none'
7
+ * 2. click a·1 → halo-layers='2', filter contains TWO drop-shadow
8
+ * substrings with the same status.primary tint at different
9
+ * blur radii (3px + 6px) and different alpha (~40% + ~20%)
10
+ * 3. source: both light + cyber filter expressions stack the
11
+ * two drop-shadows ahead of url(#topo-glow) + brightness
12
+ */
13
+ import { chromium } from 'playwright';
14
+ import { readFileSync } from 'node:fs';
15
+
16
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
17
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
18
+
19
+ const browser = await chromium.launch({ headless: true });
20
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
21
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
22
+ await ctx.addInitScript(() => {
23
+ try {
24
+ localStorage.setItem('anet-theme', 'cyber');
25
+ localStorage.setItem('anet-topo-layout', 'ring');
26
+ sessionStorage.setItem('anet_v3_auth', '1');
27
+ } catch {}
28
+ });
29
+ await ctx.route('**/api/hub/status*', async (route) => {
30
+ const r = await route.fetch();
31
+ const b = await r.json();
32
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
33
+ const mk = (alias) => ({
34
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
35
+ network_id: nid, project_dir: null,
36
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
37
+ });
38
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
39
+ });
40
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
41
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
42
+ const page = await ctx.newPage();
43
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
44
+ await page.waitForSelector('[data-chat-target-ring]', { timeout: 15000, state: 'attached' });
45
+ await page.waitForTimeout(500);
46
+
47
+ const rest = await page.evaluate(() => {
48
+ const el = document.querySelector('[data-chat-target-ring]');
49
+ if (!el) return null;
50
+ return {
51
+ layers: el.getAttribute('data-chat-target-ring-halo-layers'),
52
+ active: el.getAttribute('data-chat-target-active'),
53
+ };
54
+ });
55
+
56
+ await page.click('[data-node="a·1"]', { force: true });
57
+ await page.waitForTimeout(400);
58
+
59
+ const active = await page.evaluate(() => {
60
+ const node = document.querySelector('[data-node="a·1"]');
61
+ if (!node) return null;
62
+ const ring = node.querySelector('[data-chat-target-ring]');
63
+ if (!ring) return null;
64
+ const cs = getComputedStyle(ring);
65
+ return {
66
+ layers: ring.getAttribute('data-chat-target-ring-halo-layers'),
67
+ active: ring.getAttribute('data-chat-target-active'),
68
+ haloColor: ring.getAttribute('data-chat-target-ring-halo-color'),
69
+ filter: cs.filter,
70
+ };
71
+ });
72
+
73
+ await browser.close();
74
+
75
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
76
+ const sourceLightFilter = /`drop-shadow\(0 0 3px \$\{status\.primary\}40\) drop-shadow\(0 0 6px \$\{status\.primary\}20\) brightness\(1\.15\)`/.test(src);
77
+ const sourceCyberFilter = /`drop-shadow\(0 0 3px \$\{status\.primary\}40\) drop-shadow\(0 0 6px \$\{status\.primary\}20\) url\(#topo-glow\) brightness\(1\.15\)`/.test(src);
78
+ const sourceLayersAttr = /data-chat-target-ring-halo-layers=\{isChat \? '2' : '0'\}/.test(src);
79
+
80
+ const dropShadowMatches = (active?.filter || '').match(/drop-shadow/g) || [];
81
+
82
+ const results = {
83
+ rest_layers_0: rest?.layers === '0',
84
+ rest_active_false: rest?.active === 'false',
85
+ active_layers_2: active?.layers === '2',
86
+ active_active_true: active?.active === 'true',
87
+ active_halo_color: /^#[0-9a-f]{6,8}$/i.test(active?.haloColor || ''),
88
+ active_two_dropshadows: dropShadowMatches.length === 2,
89
+ active_has_brightness: /brightness/.test(active?.filter || ''),
90
+ active_has_glow_filter: /url\("#topo-glow"\)/.test(active?.filter || ''),
91
+ source_light_filter: sourceLightFilter,
92
+ source_cyber_filter: sourceCyberFilter,
93
+ source_layers_attr: sourceLayersAttr,
94
+ };
95
+ const ok = Object.values(results).every(Boolean);
96
+ console.log(`${ok ? '✅' : '❌'} R642 chat-target ring multi-layer halo (near + far):`,
97
+ JSON.stringify(results, null, 2),
98
+ `\n rest: ${JSON.stringify(rest)}`,
99
+ `\n active: ${JSON.stringify(active)}`);
100
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,121 @@
1
+ /* Round 640 — chat-target ring gains a THIRD breath axis: radius.
2
+ * r=radius+14 ↔ radius+14.5 over 3s, in lockstep with R120 opacity
3
+ * + R630 stroke-width breaths. Three concurrent SMIL animates run
4
+ * through the same fragment gate.
5
+ *
6
+ * Test phases:
7
+ * 1. mock 2 idle nodes
8
+ * 2. rest (no chat): chat-target ring exists, no <animate>
9
+ * children; r-breath attr 'off'
10
+ * 3. click a node to open chat → ring becomes chat target →
11
+ * 3 <animate> children: opacity, stroke-width, r — all
12
+ * dur='3s', repeatCount='indefinite'
13
+ * 4. r animate values = `${radius+14};${radius+14.5};${radius+14}`
14
+ * 5. source: new <animate attributeName="r"> sibling inside the
15
+ * same fragment gate
16
+ */
17
+ import { chromium } from 'playwright';
18
+ import { readFileSync } from 'node:fs';
19
+
20
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
21
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
22
+
23
+ const browser = await chromium.launch({ headless: true });
24
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
25
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
26
+ await ctx.addInitScript(() => {
27
+ try {
28
+ localStorage.setItem('anet-theme', 'cyber');
29
+ localStorage.setItem('anet-topo-layout', 'ring');
30
+ sessionStorage.setItem('anet_v3_auth', '1');
31
+ } catch {}
32
+ });
33
+ await ctx.route('**/api/hub/status*', async (route) => {
34
+ const r = await route.fetch();
35
+ const b = await r.json();
36
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
37
+ const mk = (alias) => ({
38
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
39
+ network_id: nid, project_dir: null,
40
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
41
+ });
42
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
43
+ });
44
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
45
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
46
+ const page = await ctx.newPage();
47
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
48
+ await page.waitForSelector('[data-chat-target-ring]', { timeout: 15000, state: 'attached' });
49
+ await page.waitForTimeout(500);
50
+
51
+ const rest = await page.evaluate(() => {
52
+ const el = document.querySelector('[data-chat-target-ring]');
53
+ if (!el) return null;
54
+ return {
55
+ rBreath: el.getAttribute('data-chat-target-ring-r-breath'),
56
+ active: el.getAttribute('data-chat-target-active'),
57
+ animateCount: el.querySelectorAll('animate').length,
58
+ };
59
+ });
60
+
61
+ // Open chat with a·1
62
+ await page.click('[data-node="a·1"]', { force: true });
63
+ await page.waitForTimeout(400);
64
+
65
+ const active = await page.evaluate(() => {
66
+ const node = document.querySelector('[data-node="a·1"]');
67
+ if (!node) return null;
68
+ const ring = node.querySelector('[data-chat-target-ring]');
69
+ if (!ring) return null;
70
+ const animates = Array.from(ring.querySelectorAll('animate'));
71
+ return {
72
+ rBreath: ring.getAttribute('data-chat-target-ring-r-breath'),
73
+ swBreath: ring.getAttribute('data-chat-target-ring-sw-breath'),
74
+ breath: ring.getAttribute('data-chat-target-breath'),
75
+ active: ring.getAttribute('data-chat-target-active'),
76
+ rAttr: ring.getAttribute('r'),
77
+ animateCount: animates.length,
78
+ animateAttrs: animates.map(a => ({
79
+ attr: a.getAttribute('attributeName'),
80
+ dur: a.getAttribute('dur'),
81
+ vals: a.getAttribute('values'),
82
+ rep: a.getAttribute('repeatCount'),
83
+ })),
84
+ };
85
+ });
86
+
87
+ await browser.close();
88
+
89
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
90
+ const sourceRAnimate = /<animate\s+attributeName="r"\s+values=\{`\$\{radius \+ 14\};\$\{radius \+ 14\.5\};\$\{radius \+ 14\}`\}\s+dur="3s"\s+repeatCount="indefinite"\s*\/>/.test(src);
91
+ const sourceRBreathAttr = /data-chat-target-ring-r-breath=\{!reducedMotion && isChat \? 'on' : 'off'\}/.test(src);
92
+
93
+ const rAnimate = active?.animateAttrs?.find(a => a.attr === 'r');
94
+ const opAnimate = active?.animateAttrs?.find(a => a.attr === 'opacity');
95
+ const swAnimate = active?.animateAttrs?.find(a => a.attr === 'stroke-width');
96
+
97
+ const results = {
98
+ rest_ring_present: !!rest,
99
+ rest_r_breath_off: rest?.rBreath === 'off',
100
+ rest_no_animate: rest?.animateCount === 0,
101
+ active_ring_present: !!active,
102
+ active_r_breath_on: active?.rBreath === 'on',
103
+ active_sw_breath_on: active?.swBreath === 'on',
104
+ active_breath_on: active?.breath === 'on',
105
+ active_animate_count_3: active?.animateCount === 3,
106
+ active_has_r: rAnimate != null,
107
+ active_has_opacity: opAnimate != null,
108
+ active_has_stroke_width: swAnimate != null,
109
+ active_r_dur_3s: rAnimate?.dur === '3s',
110
+ active_r_rep_indef: rAnimate?.rep === 'indefinite',
111
+ // r animate values include radius+14 + radius+14.5 (radius is per-node-tier-dependent)
112
+ active_r_values_format: /^[\d.]+;[\d.]+;[\d.]+$/.test(rAnimate?.vals || ''),
113
+ source_r_animate: sourceRAnimate,
114
+ source_r_breath_attr: sourceRBreathAttr,
115
+ };
116
+ const ok = Object.values(results).every(Boolean);
117
+ console.log(`${ok ? '✅' : '❌'} R640 chat-target ring radius breath (3-axis 呼吸感: opacity + sw + r):`,
118
+ JSON.stringify(results, null, 2),
119
+ `\n rest: ${JSON.stringify(rest)}`,
120
+ `\n active: ${JSON.stringify(active)}`);
121
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,106 @@
1
+ /* Round 637 — chat-target ring filter gains a status-tinted
2
+ * drop-shadow halo. The halo colour now matches the ring's stroke
3
+ * (status.primary): green for working, teal for idle, slate for
4
+ * offline. Chromatic identity of the chat partner reinforced
5
+ * across stroke + halo.
6
+ *
7
+ * Test phases:
8
+ * 1. mock idle node → click to open chat → ring filter contains
9
+ * drop-shadow with idle teal #14b8a6 + brightness(1.15) +
10
+ * url(#topo-glow) on cyber
11
+ * 2. data-chat-target-ring-halo-color === status.primary hex
12
+ * 3. transition still includes 'filter'
13
+ * 4. source: filter expression uses status.primary in drop-shadow
14
+ */
15
+ import { chromium } from 'playwright';
16
+ import { readFileSync } from 'node:fs';
17
+
18
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
19
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
20
+
21
+ const browser = await chromium.launch({ headless: true });
22
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
23
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
24
+ await ctx.addInitScript(() => {
25
+ try {
26
+ localStorage.setItem('anet-theme', 'cyber');
27
+ localStorage.setItem('anet-topo-layout', 'ring');
28
+ sessionStorage.setItem('anet_v3_auth', '1');
29
+ } catch {}
30
+ });
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, status) => ({
36
+ alias, status, 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('a·1', 'idle'),
42
+ mk('a·2', 'working'),
43
+ ] } });
44
+ });
45
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
46
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
47
+ const page = await ctx.newPage();
48
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
49
+ await page.waitForSelector('[data-chat-target-ring]', { timeout: 15000, state: 'attached' });
50
+ await page.waitForTimeout(500);
51
+
52
+ // rest: no chat — halo color attr should be 'none'
53
+ const restAttrs = await page.evaluate(() => {
54
+ const el = document.querySelector('[data-chat-target-ring]');
55
+ if (!el) return null;
56
+ return {
57
+ haloColor: el.getAttribute('data-chat-target-ring-halo-color'),
58
+ active: el.getAttribute('data-chat-target-active'),
59
+ };
60
+ });
61
+
62
+ // open chat with a·1 (idle)
63
+ await page.click('[data-node="a·1"]', { force: true });
64
+ await page.waitForTimeout(400);
65
+
66
+ const chatState = await page.evaluate(() => {
67
+ const node = document.querySelector('[data-node="a·1"]');
68
+ if (!node) return null;
69
+ const ring = node.querySelector('[data-chat-target-ring]');
70
+ if (!ring) return null;
71
+ const cs = getComputedStyle(ring);
72
+ return {
73
+ haloColor: ring.getAttribute('data-chat-target-ring-halo-color'),
74
+ active: ring.getAttribute('data-chat-target-active'),
75
+ stroke: ring.getAttribute('stroke') || cs.stroke,
76
+ filter: cs.filter,
77
+ transition:cs.transitionProperty,
78
+ };
79
+ });
80
+
81
+ await browser.close();
82
+
83
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
84
+ const sourceLightFilter = /`drop-shadow\(0 0 3px \$\{status\.primary\}40\) brightness\(1\.15\)`/.test(src);
85
+ const sourceCyberFilter = /`drop-shadow\(0 0 3px \$\{status\.primary\}40\) url\(#topo-glow\) brightness\(1\.15\)`/.test(src);
86
+ const sourceHaloAttr = /data-chat-target-ring-halo-color=\{isChat \? status\.primary : 'none'\}/.test(src);
87
+
88
+ const results = {
89
+ rest_halo_color_none: restAttrs?.haloColor === 'none',
90
+ rest_active_false: restAttrs?.active === 'false',
91
+ chat_present: !!chatState,
92
+ chat_active_true: chatState?.active === 'true',
93
+ chat_halo_color_set: /^#[0-9a-f]{6,8}$/i.test(chatState?.haloColor || ''),
94
+ chat_filter_has_dropshadow: /drop-shadow/.test(chatState?.filter || ''),
95
+ chat_filter_has_brightness: /brightness/.test(chatState?.filter || ''),
96
+ chat_transition_has_filter: /filter/.test(chatState?.transition || ''),
97
+ source_light_filter: sourceLightFilter,
98
+ source_cyber_filter: sourceCyberFilter,
99
+ source_halo_attr: sourceHaloAttr,
100
+ };
101
+ const ok = Object.values(results).every(Boolean);
102
+ console.log(`${ok ? '✅' : '❌'} R637 chat-target ring status-tinted halo (chromatic identity completion):`,
103
+ JSON.stringify(results, null, 2),
104
+ `\n rest: ${JSON.stringify(restAttrs)}`,
105
+ `\n chat: ${JSON.stringify(chatState)}`);
106
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,123 @@
1
+ /* Round 630 — chat-target ring gains a SECOND breath axis:
2
+ * stroke-width 2.5↔2.75 over 3s, in lockstep with the existing
3
+ * R120 opacity breath (0.72↔0.95 / 0.82↔1.0). Doubles the 呼吸感
4
+ * — the ring "swells" as it brightens, then settles as it dims.
5
+ * Gated `!reducedMotion && isChat`. R51 sentinel-safe (sw range
6
+ * [2.5, 2.75] stays clear of reserved {1.5, 3}).
7
+ *
8
+ * Test phases:
9
+ * 1. mock 2 nodes → no chat: chat-target ring opacity=0,
10
+ * sw-breath attr 'off', NO <animate> children
11
+ * 2. click a node → opens ChatPopover for that alias →
12
+ * chat-target ring becomes isChat → sw-breath attr 'on',
13
+ * TWO <animate> children present (one opacity + one
14
+ * stroke-width, both dur='3s' repeatCount='indefinite')
15
+ * 3. source: stroke-width animate uses values '2.5;2.75;2.5'
16
+ * and sits inside the same `!reducedMotion && isChat`
17
+ * gate as the opacity animate
18
+ */
19
+ import { chromium } from 'playwright';
20
+ import { readFileSync } from 'node:fs';
21
+
22
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
23
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
24
+
25
+ const browser = await chromium.launch({ headless: true });
26
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
27
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
28
+ await ctx.addInitScript(() => {
29
+ try {
30
+ localStorage.setItem('anet-theme', 'cyber');
31
+ localStorage.setItem('anet-topo-layout', 'ring');
32
+ sessionStorage.setItem('anet_v3_auth', '1');
33
+ } catch {}
34
+ });
35
+ await ctx.route('**/api/hub/status*', async (route) => {
36
+ const r = await route.fetch();
37
+ const b = await r.json();
38
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
39
+ const mk = (alias) => ({
40
+ alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
41
+ network_id: nid, project_dir: null,
42
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
43
+ });
44
+ await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
45
+ });
46
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
47
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
48
+ const page = await ctx.newPage();
49
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
50
+ await page.waitForSelector('[data-chat-target-ring]', { timeout: 15000, state: 'attached' });
51
+ await page.waitForTimeout(500);
52
+
53
+ const restState = await page.evaluate(() => {
54
+ const el = document.querySelector('[data-chat-target-ring]');
55
+ if (!el) return null;
56
+ return {
57
+ active: el.getAttribute('data-chat-target-active'),
58
+ breath: el.getAttribute('data-chat-target-breath'),
59
+ swBreath: el.getAttribute('data-chat-target-ring-sw-breath'),
60
+ animateCount: el.querySelectorAll('animate').length,
61
+ };
62
+ });
63
+
64
+ // Click a node to open chat → that node's chat-target ring activates
65
+ await page.click('[data-node="a·1"]', { force: true });
66
+ await page.waitForTimeout(400);
67
+
68
+ const activeState = await page.evaluate(() => {
69
+ // Find the chat-target ring of node a·1 — it's inside g[data-node="a·1"]
70
+ const node = document.querySelector('[data-node="a·1"]');
71
+ if (!node) return null;
72
+ const ring = node.querySelector('[data-chat-target-ring]');
73
+ if (!ring) return null;
74
+ const animates = Array.from(ring.querySelectorAll('animate'));
75
+ return {
76
+ active: ring.getAttribute('data-chat-target-active'),
77
+ breath: ring.getAttribute('data-chat-target-breath'),
78
+ swBreath: ring.getAttribute('data-chat-target-ring-sw-breath'),
79
+ animateCount: animates.length,
80
+ animateAttrs: animates.map(a => ({
81
+ attr: a.getAttribute('attributeName'),
82
+ dur: a.getAttribute('dur'),
83
+ vals: a.getAttribute('values'),
84
+ rep: a.getAttribute('repeatCount'),
85
+ })),
86
+ };
87
+ });
88
+
89
+ await browser.close();
90
+
91
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
92
+ const sourceSwAnimate = /<animate\s+attributeName="stroke-width"\s+values="2\.5;2\.75;2\.5"\s+dur="3s"\s+repeatCount="indefinite"\s*\/>/.test(src);
93
+ const sourceSwAttr = /data-chat-target-ring-sw-breath=\{!reducedMotion && isChat \? 'on' : 'off'\}/.test(src);
94
+ // Ensure both animates sit inside the same `!reducedMotion && isChat &&` gate
95
+ const sourceFragmentGate = /\{!reducedMotion && isChat && \(\s*<>\s*<animate\s+attributeName="opacity"[\s\S]*?<animate\s+attributeName="stroke-width"/.test(src);
96
+
97
+ const swAnimate = activeState?.animateAttrs?.find(a => a.attr === 'stroke-width');
98
+ const opAnimate = activeState?.animateAttrs?.find(a => a.attr === 'opacity');
99
+
100
+ const results = {
101
+ rest_ring_present: !!restState,
102
+ rest_active_false: restState?.active === 'false',
103
+ rest_breath_off: restState?.breath === 'off',
104
+ rest_sw_breath_off: restState?.swBreath === 'off',
105
+ rest_no_animate: restState?.animateCount === 0,
106
+ active_active_true: activeState?.active === 'true',
107
+ active_breath_on: activeState?.breath === 'on',
108
+ active_sw_breath_on: activeState?.swBreath === 'on',
109
+ active_animate_count_2: activeState?.animateCount === 2,
110
+ active_sw_dur_3s: swAnimate?.dur === '3s',
111
+ active_sw_values: swAnimate?.vals === '2.5;2.75;2.5',
112
+ active_sw_rep_indef: swAnimate?.rep === 'indefinite',
113
+ active_op_dur_3s: opAnimate?.dur === '3s', // existing R120 still present
114
+ source_sw_animate: sourceSwAnimate,
115
+ source_sw_attr: sourceSwAttr,
116
+ source_fragment_gate: sourceFragmentGate,
117
+ };
118
+ const ok = Object.values(results).every(Boolean);
119
+ console.log(`${ok ? '✅' : '❌'} R630 chat-target ring stroke-width breath (呼吸感 2nd axis):`,
120
+ JSON.stringify(results, null, 2),
121
+ `\n rest: ${JSON.stringify(restState)}`,
122
+ `\n active: ${JSON.stringify(activeState)}`);
123
+ process.exit(ok ? 0 : 1);