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

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 (469) 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/01lmbsd37fybu.js +1 -0
  181. package/.next/static/chunks/03o.h6kvmw4l_.js +1 -0
  182. package/.next/static/chunks/03~~oirxz7~vc.js +1 -0
  183. package/.next/static/chunks/05uk96gc~9mni.js +1 -0
  184. package/.next/static/chunks/08kf-.bgs10ze.js +1 -0
  185. package/.next/static/chunks/0ggj5ummw2a84.js +7 -0
  186. package/.next/static/chunks/0glmrdj9112tc.js +7 -0
  187. package/.next/static/chunks/0iqr11y9s-xgx.js +1 -0
  188. package/.next/static/chunks/0krph-mr~j~-i.js +1 -0
  189. package/.next/static/chunks/0rxrez_cjn.eh.js +1 -0
  190. package/.next/static/chunks/0x8x.29hkju5a.js +1 -0
  191. package/.next/static/chunks/0y.7kwty.hl7h.css +2 -0
  192. package/.next/static/chunks/10irw4noos.9c.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 +5440 -242
  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-strip-theme-ease-test.mjs +99 -0
  236. package/scripts/topo-chrome-zoom-level-pop-test.mjs +122 -0
  237. package/scripts/topo-chrome-zoom-pop-test.mjs +130 -0
  238. package/scripts/topo-click-ripple-ease-test.mjs +94 -0
  239. package/scripts/topo-cmdk-edge-clear-test.mjs +109 -0
  240. package/scripts/topo-cmdk-layout-view-test.mjs +108 -0
  241. package/scripts/topo-cmdk-pin-test.mjs +123 -0
  242. package/scripts/topo-cmdk-vendor-clear-test.mjs +133 -0
  243. package/scripts/topo-cmdk-vendor-pin-test.mjs +103 -0
  244. package/scripts/topo-corner-radius-unify-test.mjs +103 -0
  245. package/scripts/topo-cwd-tooltip-test.mjs +64 -0
  246. package/scripts/topo-dblclick-reset-test.mjs +74 -0
  247. package/scripts/topo-dense-alias-fill-transition-test.mjs +133 -0
  248. package/scripts/topo-discrete-zoom-smooth-test.mjs +125 -0
  249. package/scripts/topo-dispatch-pulse-test.mjs +83 -0
  250. package/scripts/topo-edge-badge-click-pin-test.mjs +94 -0
  251. package/scripts/topo-edge-badge-crossfade-test.mjs +138 -0
  252. package/scripts/topo-edge-badge-hot-test.mjs +115 -0
  253. package/scripts/topo-edge-badge-hover-test.mjs +85 -0
  254. package/scripts/topo-edge-badge-lift-test.mjs +150 -0
  255. package/scripts/topo-edge-badge-ripple-test.mjs +111 -0
  256. package/scripts/topo-edge-badge-stroke-transition-test.mjs +118 -0
  257. package/scripts/topo-edge-badge-text-pin-test.mjs +121 -0
  258. package/scripts/topo-edge-badge-theme-ease-test.mjs +89 -0
  259. package/scripts/topo-edge-count-badge-test.mjs +86 -0
  260. package/scripts/topo-edge-endpoint-highlight-test.mjs +111 -0
  261. package/scripts/topo-edge-fadein-test.mjs +106 -0
  262. package/scripts/topo-edge-focus-test.mjs +113 -0
  263. package/scripts/topo-edge-hover-test.mjs +93 -0
  264. package/scripts/topo-edge-pill-hot-test.mjs +129 -0
  265. package/scripts/topo-edge-pill-test.mjs +105 -0
  266. package/scripts/topo-edge-smil-sync-test.mjs +148 -0
  267. package/scripts/topo-edge-smil-theme-ease-test.mjs +97 -0
  268. package/scripts/topo-edge-stroke-ease-test.mjs +100 -0
  269. package/scripts/topo-edge-stroke-transition-test.mjs +132 -0
  270. package/scripts/topo-edge-tooltip-test.mjs +70 -0
  271. package/scripts/topo-empty-state-breath-test.mjs +150 -0
  272. package/scripts/topo-empty-state-crossfade-test.mjs +130 -0
  273. package/scripts/topo-empty-state-recenter-test.mjs +107 -0
  274. package/scripts/topo-endpoint-ring-fade-test.mjs +132 -0
  275. package/scripts/topo-endpoint-ring-test.mjs +93 -0
  276. package/scripts/topo-endpoint-ring-thicken-test.mjs +112 -0
  277. package/scripts/topo-esc-clears-pin-test.mjs +98 -0
  278. package/scripts/topo-filter-pill-aliases-test.mjs +121 -0
  279. package/scripts/topo-filter-pill-body-click-test.mjs +112 -0
  280. package/scripts/topo-filter-pill-count-test.mjs +110 -0
  281. package/scripts/topo-filter-pill-mobile-test.mjs +90 -0
  282. package/scripts/topo-fit-key-test.mjs +106 -0
  283. package/scripts/topo-freshness-chip-test.mjs +74 -0
  284. package/scripts/topo-freshness-chip-transition-test.mjs +80 -0
  285. package/scripts/topo-fullscreen-active-test.mjs +115 -0
  286. package/scripts/topo-group-box-pinned-state-test.mjs +95 -0
  287. package/scripts/topo-group-count-test.mjs +6 -1
  288. package/scripts/topo-group-label-a11y-test.mjs +113 -0
  289. package/scripts/topo-group-label-count-inherit-test.mjs +99 -0
  290. package/scripts/topo-group-label-hover-test.mjs +119 -0
  291. package/scripts/topo-group-label-pin-spacing-test.mjs +136 -0
  292. package/scripts/topo-group-label-tint-test.mjs +99 -0
  293. package/scripts/topo-group-label-title-test.mjs +83 -0
  294. package/scripts/topo-group-pin-test.mjs +119 -0
  295. package/scripts/topo-group-pip-fadein-test.mjs +100 -0
  296. package/scripts/topo-group-pip-tabular-test.mjs +95 -0
  297. package/scripts/topo-group-status-pips-test.mjs +103 -0
  298. package/scripts/topo-groupbox-fadein-test.mjs +95 -0
  299. package/scripts/topo-groupbox-hover-lift-test.mjs +127 -0
  300. package/scripts/topo-groupbox-hubcore-ease-test.mjs +106 -0
  301. package/scripts/topo-groupbox-live-test.mjs +100 -0
  302. package/scripts/topo-groupbox-march-busyness-test.mjs +155 -0
  303. package/scripts/topo-groupbox-test.mjs +4 -2
  304. package/scripts/topo-halo-breath-ease-test.mjs +92 -0
  305. package/scripts/topo-halo-breath-stagger-test.mjs +89 -0
  306. package/scripts/topo-help-overlay-r109-test.mjs +67 -0
  307. package/scripts/topo-help-overlay-r118-test.mjs +69 -0
  308. package/scripts/topo-help-overlay-r123-test.mjs +69 -0
  309. package/scripts/topo-help-overlay-r134-test.mjs +74 -0
  310. package/scripts/topo-help-overlay-r137-test.mjs +81 -0
  311. package/scripts/topo-help-overlay-r141-test.mjs +86 -0
  312. package/scripts/topo-help-overlay-r153-test.mjs +85 -0
  313. package/scripts/topo-help-overlay-r59-test.mjs +67 -0
  314. package/scripts/topo-help-overlay-r65-test.mjs +64 -0
  315. package/scripts/topo-help-overlay-r70-test.mjs +63 -0
  316. package/scripts/topo-help-overlay-r78-test.mjs +59 -0
  317. package/scripts/topo-help-overlay-r81-test.mjs +58 -0
  318. package/scripts/topo-help-overlay-r87-test.mjs +64 -0
  319. package/scripts/topo-help-overlay-r91-test.mjs +65 -0
  320. package/scripts/topo-hot-tail-crossfade-test.mjs +117 -0
  321. package/scripts/topo-html-overlay-padding-unify-test.mjs +120 -0
  322. package/scripts/topo-hub-a11y-test.mjs +112 -0
  323. package/scripts/topo-hub-busyness-test.mjs +100 -0
  324. package/scripts/topo-hub-center-crossfade-test.mjs +124 -0
  325. package/scripts/topo-hub-click-fit-test.mjs +137 -0
  326. package/scripts/topo-hub-digit-scale-test.mjs +129 -0
  327. package/scripts/topo-hub-fadein-test.mjs +88 -0
  328. package/scripts/topo-hub-hover-lift-test.mjs +101 -0
  329. package/scripts/topo-hub-hover-ring-test.mjs +82 -0
  330. package/scripts/topo-hub-pip-theme-ease-test.mjs +116 -0
  331. package/scripts/topo-hub-spoke-ease-test.mjs +120 -0
  332. package/scripts/topo-hub-title-test.mjs +93 -0
  333. package/scripts/topo-hub-working-count-test.mjs +99 -0
  334. package/scripts/topo-ingroup-edge-test.mjs +103 -0
  335. package/scripts/topo-label-card-theme-ease-test.mjs +85 -0
  336. package/scripts/topo-label-lift-test.mjs +119 -0
  337. package/scripts/topo-lastseen-tooltip-test.mjs +59 -0
  338. package/scripts/topo-layout-key-test.mjs +91 -0
  339. package/scripts/topo-layout-switch-crossfade-test.mjs +126 -0
  340. package/scripts/topo-layout-toggle-test.mjs +131 -0
  341. package/scripts/topo-legend-count-empty-test.mjs +126 -0
  342. package/scripts/topo-legend-count-test.mjs +88 -0
  343. package/scripts/topo-legend-count-tier-fill-test.mjs +121 -0
  344. package/scripts/topo-legend-header-symmetric-inset-test.mjs +112 -0
  345. package/scripts/topo-legend-hover-test.mjs +113 -0
  346. package/scripts/topo-legend-panel-header-test.mjs +83 -0
  347. package/scripts/topo-legend-pin-ring-fade-test.mjs +112 -0
  348. package/scripts/topo-legend-pin-test.mjs +128 -0
  349. package/scripts/topo-legend-row-hover-lift-test.mjs +109 -0
  350. package/scripts/topo-legend-row-pin-spacing-test.mjs +124 -0
  351. package/scripts/topo-legend-row-tint-test.mjs +95 -0
  352. package/scripts/topo-legend-row-title-test.mjs +102 -0
  353. package/scripts/topo-legend-swatch-grow-test.mjs +116 -0
  354. package/scripts/topo-minimap-a11y-test.mjs +101 -0
  355. package/scripts/topo-minimap-dot-transition-test.mjs +113 -0
  356. package/scripts/topo-minimap-test.mjs +68 -0
  357. package/scripts/topo-minimap-viewport-smooth-test.mjs +124 -0
  358. package/scripts/topo-mobile-chips-test.mjs +103 -0
  359. package/scripts/topo-node-a11y-test.mjs +107 -0
  360. package/scripts/topo-node-hover-lift-test.mjs +85 -0
  361. package/scripts/topo-node-label-card-elevation-test.mjs +157 -0
  362. package/scripts/topo-node-label-card-stroke-test.mjs +135 -0
  363. package/scripts/topo-node-stroke-transition-test.mjs +103 -0
  364. package/scripts/topo-node-text-fill-transition-test.mjs +119 -0
  365. package/scripts/topo-node-title-peers-test.mjs +107 -0
  366. package/scripts/topo-node-title-test.mjs +101 -0
  367. package/scripts/topo-nodesize-active-hover-test.mjs +109 -0
  368. package/scripts/topo-nodesize-crossfade-test.mjs +141 -0
  369. package/scripts/topo-online-chip-nav-test.mjs +143 -0
  370. package/scripts/topo-orbit-busyness-test.mjs +96 -0
  371. package/scripts/topo-orbit-opacity-bucket-test.mjs +124 -0
  372. package/scripts/topo-overlap-test.mjs +32 -5
  373. package/scripts/topo-pan-cursor-test.mjs +62 -0
  374. package/scripts/topo-panel-elevation-test.mjs +76 -0
  375. package/scripts/topo-panel-fadein-test.mjs +102 -0
  376. package/scripts/topo-panel-hot-tail-fade-test.mjs +132 -0
  377. package/scripts/topo-panel-hover-elevation-test.mjs +118 -0
  378. package/scripts/topo-panel-theme-ease-test.mjs +85 -0
  379. package/scripts/topo-particle-stagger-test.mjs +82 -0
  380. package/scripts/topo-pin-intersection-color-ease-test.mjs +111 -0
  381. package/scripts/topo-pin-intersection-empty-test.mjs +129 -0
  382. package/scripts/topo-pin-intersection-tabular-test.mjs +96 -0
  383. package/scripts/topo-pin-intersection-test.mjs +121 -0
  384. package/scripts/topo-pin-intersection-warning-crossfade-test.mjs +107 -0
  385. package/scripts/topo-pin-mirror-transition-test.mjs +101 -0
  386. package/scripts/topo-pin-persistence-test.mjs +105 -0
  387. package/scripts/topo-ping-pulse-ease-test.mjs +96 -0
  388. package/scripts/topo-popover-meta-test.mjs +78 -0
  389. package/scripts/topo-prepublish-guard-test.mjs +95 -0
  390. package/scripts/topo-pressure-bar-test.mjs +69 -0
  391. package/scripts/topo-pressure-hover-test.mjs +123 -0
  392. package/scripts/topo-pressure-pin-test.mjs +119 -0
  393. package/scripts/topo-pressure-seg-self-hover-test.mjs +126 -0
  394. package/scripts/topo-pressure-seg-tooltip-test.mjs +98 -0
  395. package/scripts/topo-pressure-seg-transition-test.mjs +107 -0
  396. package/scripts/topo-pulse-dot-crossfade-test.mjs +122 -0
  397. package/scripts/topo-pulse-rate-test.mjs +71 -0
  398. package/scripts/topo-recent-panel-count-freshness-test.mjs +109 -0
  399. package/scripts/topo-recent-panel-count-test.mjs +72 -0
  400. package/scripts/topo-recent-panel-footer-breath-test.mjs +142 -0
  401. package/scripts/topo-recent-panel-hot-header-test.mjs +132 -0
  402. package/scripts/topo-recent-panel-more-crossfade-test.mjs +124 -0
  403. package/scripts/topo-recent-panel-more-cyan-hover-test.mjs +151 -0
  404. package/scripts/topo-recent-panel-more-nav-test.mjs +127 -0
  405. package/scripts/topo-recent-panel-more-test.mjs +106 -0
  406. package/scripts/topo-recent-panel-readability-bump-test.mjs +151 -0
  407. package/scripts/topo-recent-row-count-fill-test.mjs +129 -0
  408. package/scripts/topo-recent-row-fadein-test.mjs +107 -0
  409. package/scripts/topo-recent-row-freshness-test.mjs +102 -0
  410. package/scripts/topo-recent-row-hot-test.mjs +110 -0
  411. package/scripts/topo-recent-row-hover-lift-test.mjs +128 -0
  412. package/scripts/topo-recent-row-hover-test.mjs +122 -0
  413. package/scripts/topo-recent-row-pin-spacing-test.mjs +137 -0
  414. package/scripts/topo-recent-row-pin-test.mjs +126 -0
  415. package/scripts/topo-recent-row-tint-test.mjs +91 -0
  416. package/scripts/topo-recent-row-title-test.mjs +112 -0
  417. package/scripts/topo-recent-row-ts-alpha-test.mjs +100 -0
  418. package/scripts/topo-recent-row-ts-test.mjs +95 -0
  419. package/scripts/topo-recent-row-typography-test.mjs +119 -0
  420. package/scripts/topo-recent-signal-empty-hint-test.mjs +73 -0
  421. package/scripts/topo-recent-signal-empty-test.mjs +63 -0
  422. package/scripts/topo-reduced-motion-test.mjs +77 -0
  423. package/scripts/topo-reset-spin-test.mjs +120 -0
  424. package/scripts/topo-runtime-badge-grow-test.mjs +114 -0
  425. package/scripts/topo-spoke-busyness-test.mjs +110 -0
  426. package/scripts/topo-spoke-tint-test.mjs +96 -0
  427. package/scripts/topo-status-chip-hover-test.mjs +101 -0
  428. package/scripts/topo-status-chip-tooltip-test.mjs +95 -0
  429. package/scripts/topo-statusbar-chips-self-hover-test.mjs +177 -0
  430. package/scripts/topo-svg-focus-test.mjs +112 -0
  431. package/scripts/topo-sweep-busyness-test.mjs +94 -0
  432. package/scripts/topo-tabular-nums-sweep-test.mjs +93 -0
  433. package/scripts/topo-tier-ring-fadein-test.mjs +107 -0
  434. package/scripts/topo-tier-ring-occupancy-test.mjs +87 -0
  435. package/scripts/topo-tier-ring-test.mjs +69 -0
  436. package/scripts/topo-tier-ring-tint-test.mjs +110 -0
  437. package/scripts/topo-tier-stagger-test.mjs +89 -0
  438. package/scripts/topo-tz-ghost-test.mjs +69 -0
  439. package/scripts/topo-vendor-chip-hover-test.mjs +111 -0
  440. package/scripts/topo-vendor-chip-self-hover-test.mjs +130 -0
  441. package/scripts/topo-vendor-chip-tabular-test.mjs +89 -0
  442. package/scripts/topo-vendor-letter-tooltip-test.mjs +92 -0
  443. package/scripts/topo-vendor-pill-test.mjs +125 -0
  444. package/scripts/topo-vendor-pin-test.mjs +125 -0
  445. package/scripts/topo-view-smooth-test.mjs +131 -0
  446. package/scripts/topo-wheel-zoom-test.mjs +79 -0
  447. package/scripts/topo-working-chip-pin-test.mjs +154 -0
  448. package/scripts/topo-working-halo-breath-test.mjs +86 -0
  449. package/scripts/topo-wrapper-flow-arrow-theme-test.mjs +97 -0
  450. package/scripts/topo-wrapper-shadow-theme-ease-test.mjs +89 -0
  451. package/scripts/topo-zoom-keys-test.mjs +89 -0
  452. package/.next/static/chunks/0-7iowzu4.798.js +0 -1
  453. package/.next/static/chunks/02t5jr4shh.hy.js +0 -1
  454. package/.next/static/chunks/04ppgi-mphhr6.js +0 -1
  455. package/.next/static/chunks/09nd.t_hd.y6t.css +0 -2
  456. package/.next/static/chunks/0_qfg5s5uzs7..js +0 -7
  457. package/.next/static/chunks/0elalb9n_.~di.js +0 -1
  458. package/.next/static/chunks/0fqy_0wj_1xa7.js +0 -7
  459. package/.next/static/chunks/0j_q__o8p6g83.js +0 -1
  460. package/.next/static/chunks/0jl6_w50zh4l5.js +0 -1
  461. package/.next/static/chunks/0r4q73.-1bkyl.js +0 -1
  462. package/.next/static/chunks/0r_c8eccg3z2o.js +0 -1
  463. package/.next/static/chunks/0zs511wcsq~0j.js +0 -1
  464. package/.next/static/chunks/10oi7l-tycgl9.js +0 -1
  465. package/.next/static/chunks/11uk1izuv3~0t.js +0 -1
  466. package/.next/static/chunks/15gj.t675_yw3.js +0 -1
  467. /package/.next/static/{kk1qr2sXSqVvoqBT7fk1x → 1RSKMzmY8kvB-f37IJbmE}/_buildManifest.js +0 -0
  468. /package/.next/static/{kk1qr2sXSqVvoqBT7fk1x → 1RSKMzmY8kvB-f37IJbmE}/_clientMiddlewareManifest.js +0 -0
  469. /package/.next/static/{kk1qr2sXSqVvoqBT7fk1x → 1RSKMzmY8kvB-f37IJbmE}/_ssgManifest.js +0 -0
@@ -0,0 +1,92 @@
1
+ /* Round 244 verification: hub grounding halo (R84) AND node working
2
+ * halos (R112/R226) both pick up ease-in-out keySplines on their
3
+ * SMIL breath animates. The three breath surfaces on canvas — hub
4
+ * (R84+R244) + active-node pulse (R243) + working halos (R226+R244)
5
+ * — now share the same curve shape and feel.
6
+ *
7
+ * Test scope:
8
+ * - hub grounding halo: probe [data-hub-busyness] → child
9
+ * <animate> has calcMode='spline', keyTimes='0;0.5;1',
10
+ * keySplines='0.42 0 0.58 1;0.42 0 0.58 1'
11
+ * - working halos: probe all [data-node-halo-breath='on'] →
12
+ * each child <animate> has same calcMode/keyTimes/keySplines
13
+ *
14
+ * Scenario: 4 working agents (hub busy bucket > 0 → halo breath
15
+ * is present; all 4 nodes are working → 4 halo breath animates).
16
+ */
17
+ import { chromium } from 'playwright';
18
+ import { readFileSync } from 'node:fs';
19
+
20
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
21
+ const browser = await chromium.launch({ headless: true });
22
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
23
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
24
+ await ctx.addInitScript(() => {
25
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
26
+ });
27
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
28
+ await ctx.route('**/api/hub/status*', async (route) => {
29
+ const r = await route.fetch();
30
+ const b = await r.json();
31
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
32
+ const mk = (alias) => ({
33
+ alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
34
+ network_id: nid, project_dir: null,
35
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
36
+ });
37
+ await route.fulfill({ response: r, json: { ...b, sessions: [
38
+ mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
39
+ ] } });
40
+ });
41
+ await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: [] } }));
42
+ await ctx.route('**/api/hub/tasks*', (r2) => r2.fulfill({ json: { tasks: [] } }));
43
+
44
+ const page = await ctx.newPage();
45
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
46
+ await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
47
+ await page.waitForSelector('[data-hub-busyness]', { timeout: 10000, state: 'attached' });
48
+ await page.waitForTimeout(300);
49
+
50
+ const out = await page.evaluate(() => {
51
+ const probeAnimate = (parent) => {
52
+ const a = parent?.querySelector('animate');
53
+ if (!a) return null;
54
+ return {
55
+ attr: a.getAttribute('attributeName'),
56
+ calcMode: a.getAttribute('calcMode'),
57
+ keyTimes: a.getAttribute('keyTimes'),
58
+ keySplines: a.getAttribute('keySplines'),
59
+ dur: a.getAttribute('dur'),
60
+ };
61
+ };
62
+ const hub = document.querySelector('[data-hub-busyness]');
63
+ const halos = Array.from(document.querySelectorAll('[data-node-halo-breath="on"]'));
64
+ return {
65
+ hub: probeAnimate(hub),
66
+ halos: halos.map(h => probeAnimate(h)),
67
+ };
68
+ });
69
+ await browser.close();
70
+
71
+ const EASE_INOUT = '0.42 0 0.58 1;0.42 0 0.58 1';
72
+ const KEY_TIMES = '0;0.5;1';
73
+
74
+ const animateOK = (a) =>
75
+ a &&
76
+ a.attr === 'opacity' &&
77
+ a.calcMode === 'spline' &&
78
+ a.keyTimes === KEY_TIMES &&
79
+ a.keySplines === EASE_INOUT;
80
+
81
+ const results = {
82
+ hub_animate_present: out.hub !== null,
83
+ hub_ease_in_out: animateOK(out.hub),
84
+ halos_count_4: out.halos.length === 4,
85
+ halos_all_present: out.halos.every(h => h !== null),
86
+ halos_all_ease_in_out: out.halos.every(animateOK),
87
+ };
88
+ const ok = Object.values(results).every(Boolean);
89
+ console.log(`${ok ? '✅' : '❌'} halo breath ease:`, JSON.stringify(results),
90
+ '\n hub: ', out.hub,
91
+ '\n halos:', out.halos);
92
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,89 @@
1
+ /* Round 226 verification: working-halo breath gets per-node phase
2
+ * stagger via SMIL `begin="-{nodeIdx * 0.37 % 3}s"`. Pre-R226 all
3
+ * working halos pulsed in lockstep at the same instant; R226 desyncs
4
+ * them organically.
5
+ *
6
+ * Test: 4 working agents → probe each [data-node-halo-breath='on']
7
+ * circle for its `<animate>` child's `begin` attribute. Expect:
8
+ * - Each animate has a `begin` matching '-N.NNNs'
9
+ * - All four offsets are distinct (no two halos start at the
10
+ * same phase)
11
+ * - The data-node-halo-breath-offset attribute matches the
12
+ * `begin` magnitude (post-strip of '-' and 's')
13
+ * - The dur stays '3s' (period unchanged, only phase shifts)
14
+ * - Reduced-motion test scope unchanged (gate still keeps SMIL
15
+ * out for prefers-reduced-motion users)
16
+ */
17
+ import { chromium } from 'playwright';
18
+ import { readFileSync } from 'node:fs';
19
+
20
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
21
+ const browser = await chromium.launch({ headless: true });
22
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
23
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
24
+ await ctx.addInitScript(() => {
25
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
26
+ });
27
+ const fresh = new Date(Date.now() - 60 * 1000).toISOString();
28
+ await ctx.route('**/api/hub/status*', async (route) => {
29
+ const r = await route.fetch();
30
+ const b = await r.json();
31
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
32
+ const mk = (alias) => ({
33
+ alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
34
+ network_id: nid, project_dir: null,
35
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
36
+ });
37
+ await route.fulfill({ response: r, json: { ...b, sessions: [
38
+ mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
39
+ ] } });
40
+ });
41
+ await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: [] } }));
42
+ await ctx.route('**/api/hub/tasks*', (r2) => r2.fulfill({ json: { tasks: [] } }));
43
+
44
+ const page = await ctx.newPage();
45
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
46
+ await page.waitForFunction(() => document.querySelectorAll('[data-node-halo-breath="on"]').length === 4, { timeout: 30000 });
47
+ await page.waitForTimeout(400);
48
+
49
+ const out = await page.evaluate(() => {
50
+ const halos = Array.from(document.querySelectorAll('[data-node-halo-breath="on"]'));
51
+ return halos.map((h) => {
52
+ const anim = h.querySelector('animate');
53
+ return {
54
+ offsetAttr: h.getAttribute('data-node-halo-breath-offset'),
55
+ begin: anim?.getAttribute('begin') || null,
56
+ dur: anim?.getAttribute('dur') || null,
57
+ attrName: anim?.getAttribute('attributeName') || null,
58
+ };
59
+ });
60
+ });
61
+ await browser.close();
62
+
63
+ const beginRe = /^-(\d+\.\d{3})s$/;
64
+ const parsed = out.map((h) => {
65
+ const m = (h.begin || '').match(beginRe);
66
+ return {
67
+ ...h,
68
+ beginNum: m ? parseFloat(m[1]) : NaN,
69
+ };
70
+ });
71
+
72
+ // Expected: 4 halos, offsets (0 * 0.37) % 3, (1 * 0.37) % 3, etc.
73
+ // = 0.000, 0.370, 0.740, 1.110 (each .toFixed(3))
74
+ const expected = [0, 0.37, 0.74, 1.11];
75
+ const close = (a, b) => Math.abs(a - b) < 0.005;
76
+
77
+ const results = {
78
+ four_halos: parsed.length === 4,
79
+ all_have_begin: parsed.every(p => !Number.isNaN(p.beginNum)),
80
+ all_have_dur_3s: parsed.every(p => p.dur === '3s'),
81
+ all_attr_opacity: parsed.every(p => p.attrName === 'opacity'),
82
+ all_offsets_distinct: new Set(parsed.map(p => p.beginNum)).size === 4,
83
+ offsets_match_golden: parsed.every((p, i) => close(p.beginNum, expected[i])),
84
+ attr_matches_begin: parsed.every((p) => p.offsetAttr === p.beginNum.toFixed(3)),
85
+ };
86
+ const ok = Object.values(results).every(Boolean);
87
+ console.log(`${ok ? '✅' : '❌'} halo breath stagger:`, JSON.stringify(results),
88
+ '\n parsed:', parsed);
89
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,67 @@
1
+ /* Round 109 verification: HelpOverlay catches up on R108 — palette
2
+ * gained pin-vendor commands (Anthropic/OpenAI/书生). Continues the
3
+ * R59/R62/R65/R70/R78/R81/R87/R91 docs-catch-up cadence.
4
+ *
5
+ * Stacks eight generations of help-overlay assertions — any future
6
+ * regression that drops an entry will be caught by one of:
7
+ * R109 (this) → R91 → R87 → R81 → R78 → R74 → R70 → R65 → R59
8
+ */
9
+ import { chromium } from 'playwright';
10
+ import { readFileSync } from 'node:fs';
11
+
12
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
13
+ const browser = await chromium.launch({ headless: true });
14
+
15
+ const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } });
16
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
17
+ await ctx.addInitScript(() => {
18
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
19
+ });
20
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
21
+ await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
22
+ const page = await ctx.newPage();
23
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
24
+ await page.waitForTimeout(800);
25
+
26
+ await page.keyboard.press('?');
27
+ await page.waitForSelector('[role="dialog"][aria-label="Keyboard shortcuts"]', { timeout: 5000 });
28
+
29
+ const items = await page.evaluate(() => {
30
+ const dialog = document.querySelector('[role="dialog"][aria-label="Keyboard shortcuts"]');
31
+ const groups = [...(dialog?.querySelectorAll('div') || [])];
32
+ let active = null;
33
+ for (const g of groups) {
34
+ if (g.textContent && /^Topology canvas$/i.test(g.textContent.trim())) {
35
+ active = g.parentElement;
36
+ break;
37
+ }
38
+ }
39
+ return active ? [...active.querySelectorAll('li')].map(li => (li.textContent || '').trim()) : [];
40
+ });
41
+
42
+ await browser.close();
43
+
44
+ const has = (s) => items.some(t => t.includes(s));
45
+ const results = {
46
+ r109_pinVendor: has('Pin vendor: Anthropic/OpenAI/书生 via palette → "Pin topology filter…" (R108)'),
47
+ // R91 priors
48
+ r91_clickVendor: has('Pin a vendor filter — click A/O/书/? in the chip row (R88)'),
49
+ r91_clearVendor: has('Clear vendor pin only via palette → "Clear topology vendor filter" (R90)'),
50
+ // R87 priors
51
+ r87_segHover: has('Preview a status filter — hover a pressure-bar segment (R83)'),
52
+ r87_groupLabelHover: has('Preview a team focus — hover a group label (R86)'),
53
+ // R81 priors
54
+ r81_workingChip: has('Highlight working nodes — chip-row sibling of legend (R79)'),
55
+ r81_vendorChip: has('Highlight one vendor — hover A/O/书/? in the chip row (R80)'),
56
+ // R78 / R74 / R70 / R65 / R59 priors — 8 generations now
57
+ r78_pillBodyClick: has('Clear filter — click anywhere on the pill body (R73)'),
58
+ r74_cmdkLayout: has('Toggle layout / Fit canvas via palette (R74)'),
59
+ r70_cmdkPin: has('(R69)'),
60
+ r65_groupClick: has('Pin a team focus (R63)'),
61
+ r62_pinChip: has('Pin a status filter (R60/R61)'),
62
+ r59_clickHub: has('Fit topology to canvas (R52)'),
63
+ };
64
+ const ok = Object.values(results).every(Boolean);
65
+ console.log(`${ok ? '✅' : '❌'} help overlay R109:`, JSON.stringify(results),
66
+ `\n items=`, items);
67
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,69 @@
1
+ /* Round 118 verification: HelpOverlay catches up on R116 (recent-
2
+ * signal row click pins the edge) + R117 (Cmd+K clear-edge command).
3
+ * Continues the R59/R62/R65/R70/R78/R81/R87/R91/R109 cadence (~5-8
4
+ * rounds between syncs).
5
+ *
6
+ * Nine generations of help-overlay assertions stacked here — any
7
+ * future regression that drops an entry is caught by one of:
8
+ * R118 → R109 → R91 → R87 → R81 → R78 → R74 → R70 → R65 → R59
9
+ */
10
+ import { chromium } from 'playwright';
11
+ import { readFileSync } from 'node:fs';
12
+
13
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
14
+ const browser = await chromium.launch({ headless: true });
15
+
16
+ const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } });
17
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
18
+ await ctx.addInitScript(() => {
19
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
20
+ });
21
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
22
+ await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
23
+ const page = await ctx.newPage();
24
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
25
+ await page.waitForTimeout(800);
26
+
27
+ await page.keyboard.press('?');
28
+ await page.waitForSelector('[role="dialog"][aria-label="Keyboard shortcuts"]', { timeout: 5000 });
29
+
30
+ const items = await page.evaluate(() => {
31
+ const dialog = document.querySelector('[role="dialog"][aria-label="Keyboard shortcuts"]');
32
+ const groups = [...(dialog?.querySelectorAll('div') || [])];
33
+ let active = null;
34
+ for (const g of groups) {
35
+ if (g.textContent && /^Topology canvas$/i.test(g.textContent.trim())) {
36
+ active = g.parentElement;
37
+ break;
38
+ }
39
+ }
40
+ return active ? [...active.querySelectorAll('li')].map(li => (li.textContent || '').trim()) : [];
41
+ });
42
+
43
+ await browser.close();
44
+
45
+ const has = (s) => items.some(t => t.includes(s));
46
+ const results = {
47
+ r118_rowClickPin: has('Pin a flow filter — click a recent-signal row to lock the edge (R116)'),
48
+ r118_cmdkClearEdge: has('Clear edge pin only via palette → "Clear topology edge pin" (R117)'),
49
+ // R109 priors
50
+ r109_pinVendor: has('Pin vendor: Anthropic/OpenAI/书生 via palette → "Pin topology filter…" (R108)'),
51
+ // R91 priors
52
+ r91_clickVendor: has('Pin a vendor filter — click A/O/书/? in the chip row (R88)'),
53
+ r91_clearVendor: has('Clear vendor pin only via palette → "Clear topology vendor filter" (R90)'),
54
+ // R87 priors
55
+ r87_segHover: has('Preview a status filter — hover a pressure-bar segment (R83)'),
56
+ // R81 priors
57
+ r81_vendorChip: has('Highlight one vendor — hover A/O/书/? in the chip row (R80)'),
58
+ // R78 / R74 / R70 / R65 / R59 priors — 10 generations
59
+ r78_pillBodyClick: has('Clear filter — click anywhere on the pill body (R73)'),
60
+ r74_cmdkLayout: has('Toggle layout / Fit canvas via palette (R74)'),
61
+ r70_cmdkPin: has('(R69)'),
62
+ r65_groupClick: has('Pin a team focus (R63)'),
63
+ r62_pinChip: has('Pin a status filter (R60/R61)'),
64
+ r59_clickHub: has('Fit topology to canvas (R52)'),
65
+ };
66
+ const ok = Object.values(results).every(Boolean);
67
+ console.log(`${ok ? '✅' : '❌'} help overlay R118:`, JSON.stringify(results),
68
+ `\n items=`, items);
69
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,69 @@
1
+ /* Round 123 verification: HelpOverlay catches up on R121 — edge
2
+ * midpoint count badge became click-to-pin. R122's badge hover
3
+ * is the natural partner of R121 click; doesn't need its own
4
+ * entry. Continues the R59/R62/R65/R70/R78/R81/R87/R91/R109/R118
5
+ * cadence.
6
+ *
7
+ * Ten generations of help-overlay assertions stacked here — any
8
+ * future regression that drops an entry is caught by one of:
9
+ * R123 → R118 → R109 → R91 → R87 → R81 → R78 → R74 → R70 → R65 → R59
10
+ */
11
+ import { chromium } from 'playwright';
12
+ import { readFileSync } from 'node:fs';
13
+
14
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
15
+ const browser = await chromium.launch({ headless: true });
16
+
17
+ const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } });
18
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
19
+ await ctx.addInitScript(() => {
20
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
21
+ });
22
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
23
+ await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
24
+ const page = await ctx.newPage();
25
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
26
+ await page.waitForTimeout(800);
27
+
28
+ await page.keyboard.press('?');
29
+ await page.waitForSelector('[role="dialog"][aria-label="Keyboard shortcuts"]', { timeout: 5000 });
30
+
31
+ const items = await page.evaluate(() => {
32
+ const dialog = document.querySelector('[role="dialog"][aria-label="Keyboard shortcuts"]');
33
+ const groups = [...(dialog?.querySelectorAll('div') || [])];
34
+ let active = null;
35
+ for (const g of groups) {
36
+ if (g.textContent && /^Topology canvas$/i.test(g.textContent.trim())) {
37
+ active = g.parentElement;
38
+ break;
39
+ }
40
+ }
41
+ return active ? [...active.querySelectorAll('li')].map(li => (li.textContent || '').trim()) : [];
42
+ });
43
+
44
+ await browser.close();
45
+
46
+ const has = (s) => items.some(t => t.includes(s));
47
+ const results = {
48
+ r123_clickBadge: has('Pin a flow filter from the canvas — click an edge midpoint count badge (R121)'),
49
+ // R118 priors
50
+ r118_rowClickPin: has('Pin a flow filter — click a recent-signal row to lock the edge (R116)'),
51
+ r118_cmdkClearEdge: has('Clear edge pin only via palette → "Clear topology edge pin" (R117)'),
52
+ // R109 priors
53
+ r109_pinVendor: has('Pin vendor: Anthropic/OpenAI/书生 via palette → "Pin topology filter…" (R108)'),
54
+ // R91 priors
55
+ r91_clickVendor: has('Pin a vendor filter — click A/O/书/? in the chip row (R88)'),
56
+ // R87 / R81 / R78 / R74 / R70 / R65 / R59 priors — 11 generations
57
+ r87_segHover: has('Preview a status filter — hover a pressure-bar segment (R83)'),
58
+ r81_vendorChip: has('Highlight one vendor — hover A/O/书/? in the chip row (R80)'),
59
+ r78_pillBodyClick: has('Clear filter — click anywhere on the pill body (R73)'),
60
+ r74_cmdkLayout: has('Toggle layout / Fit canvas via palette (R74)'),
61
+ r70_cmdkPin: has('(R69)'),
62
+ r65_groupClick: has('Pin a team focus (R63)'),
63
+ r62_pinChip: has('Pin a status filter (R60/R61)'),
64
+ r59_clickHub: has('Fit topology to canvas (R52)'),
65
+ };
66
+ const ok = Object.values(results).every(Boolean);
67
+ console.log(`${ok ? '✅' : '❌'} help overlay R123:`, JSON.stringify(results),
68
+ `\n items=`, items);
69
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,74 @@
1
+ /* Round 134 verification: HelpOverlay catches up on R133 — the
2
+ * recent-signal panel's "+ N more flows" truncation footer (R128)
3
+ * became a clickable navigation to /messages. First TopoGraph
4
+ * affordance that reaches OUT of the canvas, so it gets its own
5
+ * Help-overlay entry.
6
+ *
7
+ * R124-R132 were all passive visuals / motion / readouts with no
8
+ * new gestures, so R133 is the only entry since R123.
9
+ *
10
+ * Stacks 12 docs generations to catch any future regression that
11
+ * drops an entry: R134 → R123 → R118 → R109 → R91 → R87 → R81 →
12
+ * R78 → R74 → R70 → R65 → R59.
13
+ */
14
+ import { chromium } from 'playwright';
15
+ import { readFileSync } from 'node:fs';
16
+
17
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
18
+ const browser = await chromium.launch({ headless: true });
19
+
20
+ const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } });
21
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
22
+ await ctx.addInitScript(() => {
23
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
24
+ });
25
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
26
+ await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
27
+ const page = await ctx.newPage();
28
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
29
+ await page.waitForTimeout(800);
30
+
31
+ await page.keyboard.press('?');
32
+ await page.waitForSelector('[role="dialog"][aria-label="Keyboard shortcuts"]', { timeout: 5000 });
33
+
34
+ const items = await page.evaluate(() => {
35
+ const dialog = document.querySelector('[role="dialog"][aria-label="Keyboard shortcuts"]');
36
+ const groups = [...(dialog?.querySelectorAll('div') || [])];
37
+ let active = null;
38
+ for (const g of groups) {
39
+ if (g.textContent && /^Topology canvas$/i.test(g.textContent.trim())) {
40
+ active = g.parentElement;
41
+ break;
42
+ }
43
+ }
44
+ return active ? [...active.querySelectorAll('li')].map(li => (li.textContent || '').trim()) : [];
45
+ });
46
+
47
+ await browser.close();
48
+
49
+ const has = (s) => items.some(t => t.includes(s));
50
+ const results = {
51
+ r134_clickFooter: has('See all flows — click "+ N more flows" in the recent-signal panel (R133)'),
52
+ // R123 prior
53
+ r123_clickBadge: has('Pin a flow filter from the canvas — click an edge midpoint count badge (R121)'),
54
+ // R118 priors
55
+ r118_rowClickPin: has('Pin a flow filter — click a recent-signal row to lock the edge (R116)'),
56
+ r118_cmdkClearEdge: has('Clear edge pin only via palette → "Clear topology edge pin" (R117)'),
57
+ // R109 prior
58
+ r109_pinVendor: has('Pin vendor: Anthropic/OpenAI/书生 via palette → "Pin topology filter…" (R108)'),
59
+ // R91 prior
60
+ r91_clickVendor: has('Pin a vendor filter — click A/O/书/? in the chip row (R88)'),
61
+ // R87 / R81 / R78 / R74 / R70 / R65 / R59 priors
62
+ r87_segHover: has('Preview a status filter — hover a pressure-bar segment (R83)'),
63
+ r81_vendorChip: has('Highlight one vendor — hover A/O/书/? in the chip row (R80)'),
64
+ r78_pillBodyClick: has('Clear filter — click anywhere on the pill body (R73)'),
65
+ r74_cmdkLayout: has('Toggle layout / Fit canvas via palette (R74)'),
66
+ r70_cmdkPin: has('(R69)'),
67
+ r65_groupClick: has('Pin a team focus (R63)'),
68
+ r62_pinChip: has('Pin a status filter (R60/R61)'),
69
+ r59_clickHub: has('Fit topology to canvas (R52)'),
70
+ };
71
+ const ok = Object.values(results).every(Boolean);
72
+ console.log(`${ok ? '✅' : '❌'} help overlay R134:`, JSON.stringify(results),
73
+ `\n items=`, items);
74
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,81 @@
1
+ /* Round 137 verification: HelpOverlay catches up on R136 — the
2
+ * "N active links" chip in the chip row got a real onClick →
3
+ * /messages navigation (R136 fixed the cursor-pointer-lying bug:
4
+ * cursor:pointer existed since R77, but no click handler).
5
+ *
6
+ * Pairs with R134's footer-nav entry at a different surface:
7
+ * R133 footer-nav: canvas-side panel, only when flowLinks > 3
8
+ * R136 chip-nav: chip row, whenever flowLinks > 0 (broader)
9
+ *
10
+ * Stacks 13 docs generations now: R137 → R134 → R123 → R118 →
11
+ * R109 → R91 → R87 → R81 → R78 → R74 → R70 → R65 → R59. Any
12
+ * regression that drops an entry is caught by one of these.
13
+ */
14
+ import { chromium } from 'playwright';
15
+ import { readFileSync } from 'node:fs';
16
+
17
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
18
+ const browser = await chromium.launch({ headless: true });
19
+
20
+ const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } });
21
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
22
+ await ctx.addInitScript(() => {
23
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
24
+ });
25
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
26
+ await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
27
+ const page = await ctx.newPage();
28
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
29
+ await page.waitForTimeout(800);
30
+
31
+ await page.keyboard.press('?');
32
+ await page.waitForSelector('[role="dialog"][aria-label="Keyboard shortcuts"]', { timeout: 5000 });
33
+
34
+ const items = await page.evaluate(() => {
35
+ const dialog = document.querySelector('[role="dialog"][aria-label="Keyboard shortcuts"]');
36
+ const groups = [...(dialog?.querySelectorAll('div') || [])];
37
+ let active = null;
38
+ for (const g of groups) {
39
+ if (g.textContent && /^Topology canvas$/i.test(g.textContent.trim())) {
40
+ active = g.parentElement;
41
+ break;
42
+ }
43
+ }
44
+ return active ? [...active.querySelectorAll('li')].map(li => (li.textContent || '').trim()) : [];
45
+ });
46
+
47
+ await browser.close();
48
+
49
+ const has = (s) => items.some(t => t.includes(s));
50
+ const results = {
51
+ r137_clickChip: has('See all flows — click the "N active links" chip in the chip row (R136)'),
52
+ // R134 prior
53
+ r134_clickFooter: has('See all flows — click "+ N more flows" in the recent-signal panel (R133)'),
54
+ // R123 prior
55
+ r123_clickBadge: has('Pin a flow filter from the canvas — click an edge midpoint count badge (R121)'),
56
+ // R118 priors
57
+ r118_rowClickPin: has('Pin a flow filter — click a recent-signal row to lock the edge (R116)'),
58
+ r118_cmdkClearEdge: has('Clear edge pin only via palette → "Clear topology edge pin" (R117)'),
59
+ // R109 prior
60
+ r109_pinVendor: has('Pin vendor: Anthropic/OpenAI/书生 via palette → "Pin topology filter…" (R108)'),
61
+ // R91 prior
62
+ r91_clickVendor: has('Pin a vendor filter — click A/O/书/? in the chip row (R88)'),
63
+ // R87 prior
64
+ r87_segHover: has('Preview a status filter — hover a pressure-bar segment (R83)'),
65
+ // R81 prior
66
+ r81_vendorChip: has('Highlight one vendor — hover A/O/书/? in the chip row (R80)'),
67
+ // R78 prior
68
+ r78_pillBodyClick: has('Clear filter — click anywhere on the pill body (R73)'),
69
+ // R74 prior
70
+ r74_cmdkLayout: has('Toggle layout / Fit canvas via palette (R74)'),
71
+ // R70 prior
72
+ r70_cmdkPin: has('(R69)'),
73
+ // R65 prior
74
+ r65_groupClick: has('Pin a team focus (R63)'),
75
+ // R59 prior
76
+ r59_clickHub: has('Fit topology to canvas (R52)'),
77
+ };
78
+ const ok = Object.values(results).every(Boolean);
79
+ console.log(`${ok ? '✅' : '❌'} help overlay R137:`, JSON.stringify(results),
80
+ `\n items=`, items);
81
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,86 @@
1
+ /* Round 141 verification: HelpOverlay catches up on R139 + R140 —
2
+ * two new chip-row gestures landed since R137's last docs update.
3
+ *
4
+ * R139: click "N working" chip → pin pinnedStatus='working'
5
+ * (composes with R60 pressure-bar + R61 legend)
6
+ * R140: click "N online" chip → /nodes
7
+ * (pin 'idle' would misrepresent the chip semantically)
8
+ *
9
+ * Two entries added this round — usually one, but two gestures
10
+ * landed in consecutive rounds R139/R140.
11
+ *
12
+ * Stacks 14 docs generations now: R141 (×2) → R137 → R134 → R123
13
+ * → R118 → R109 → R91 → R87 → R81 → R78 → R74 → R70 → R65 → R59.
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 browser = await chromium.launch({ headless: true });
20
+
21
+ const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } });
22
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
23
+ await ctx.addInitScript(() => {
24
+ try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
25
+ });
26
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
27
+ await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
28
+ const page = await ctx.newPage();
29
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
30
+ await page.waitForTimeout(800);
31
+
32
+ await page.keyboard.press('?');
33
+ await page.waitForSelector('[role="dialog"][aria-label="Keyboard shortcuts"]', { timeout: 5000 });
34
+
35
+ const items = await page.evaluate(() => {
36
+ const dialog = document.querySelector('[role="dialog"][aria-label="Keyboard shortcuts"]');
37
+ const groups = [...(dialog?.querySelectorAll('div') || [])];
38
+ let active = null;
39
+ for (const g of groups) {
40
+ if (g.textContent && /^Topology canvas$/i.test(g.textContent.trim())) {
41
+ active = g.parentElement;
42
+ break;
43
+ }
44
+ }
45
+ return active ? [...active.querySelectorAll('li')].map(li => (li.textContent || '').trim()) : [];
46
+ });
47
+
48
+ await browser.close();
49
+
50
+ const has = (s) => items.some(t => t.includes(s));
51
+ const results = {
52
+ // R141 NEW
53
+ r141_workingPin: has('Pin "working" status — click "N working" in the chip row (R139)'),
54
+ r141_onlineNav: has('Open the agent list — click "N online" in the chip row (R140)'),
55
+ // R137 prior
56
+ r137_clickChip: has('See all flows — click the "N active links" chip in the chip row (R136)'),
57
+ // R134 prior
58
+ r134_clickFooter: has('See all flows — click "+ N more flows" in the recent-signal panel (R133)'),
59
+ // R123 prior
60
+ r123_clickBadge: has('Pin a flow filter from the canvas — click an edge midpoint count badge (R121)'),
61
+ // R118 priors
62
+ r118_rowClickPin: has('Pin a flow filter — click a recent-signal row to lock the edge (R116)'),
63
+ r118_cmdkClearEdge: has('Clear edge pin only via palette → "Clear topology edge pin" (R117)'),
64
+ // R109 prior
65
+ r109_pinVendor: has('Pin vendor: Anthropic/OpenAI/书生 via palette → "Pin topology filter…" (R108)'),
66
+ // R91 prior
67
+ r91_clickVendor: has('Pin a vendor filter — click A/O/书/? in the chip row (R88)'),
68
+ // R87 prior
69
+ r87_segHover: has('Preview a status filter — hover a pressure-bar segment (R83)'),
70
+ // R81 prior
71
+ r81_vendorChip: has('Highlight one vendor — hover A/O/书/? in the chip row (R80)'),
72
+ // R78 prior
73
+ r78_pillBodyClick: has('Clear filter — click anywhere on the pill body (R73)'),
74
+ // R74 prior
75
+ r74_cmdkLayout: has('Toggle layout / Fit canvas via palette (R74)'),
76
+ // R70 prior
77
+ r70_cmdkPin: has('(R69)'),
78
+ // R65 prior
79
+ r65_groupClick: has('Pin a team focus (R63)'),
80
+ // R59 prior
81
+ r59_clickHub: has('Fit topology to canvas (R52)'),
82
+ };
83
+ const ok = Object.values(results).every(Boolean);
84
+ console.log(`${ok ? '✅' : '❌'} help overlay R141:`, JSON.stringify(results),
85
+ `\n items=`, items);
86
+ process.exit(ok ? 0 : 1);