@sleep2agi/agent-network-dashboard 0.5.3 → 0.5.5-preview.0
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.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +2 -0
- package/.next/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +37 -37
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +29 -0
- package/.next/routes-manifest.json +12 -0
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +2 -2
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +3 -3
- package/.next/server/app/_not-found.rsc +14 -14
- package/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/server/app/admin.html +3 -3
- package/.next/server/app/admin.rsc +16 -16
- package/.next/server/app/admin.segments/_full.segment.rsc +16 -16
- package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
- package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
- package/.next/server/app/api/hub/upload/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/hub/upload/route/build-manifest.json +9 -0
- package/.next/server/app/api/hub/upload/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/hub/upload/route.js +7 -0
- package/.next/server/app/api/hub/upload/route.js.map +5 -0
- package/.next/server/app/api/hub/upload/route.js.nft.json +1 -0
- package/.next/server/app/api/hub/upload/route_client-reference-manifest.js +3 -0
- package/.next/server/app/index.html +3 -3
- package/.next/server/app/index.rsc +16 -16
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +16 -16
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +7 -7
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +2 -2
- package/.next/server/app/login.rsc +16 -16
- package/.next/server/app/login.segments/_full.segment.rsc +16 -16
- package/.next/server/app/login.segments/_head.segment.rsc +4 -4
- package/.next/server/app/login.segments/_index.segment.rsc +7 -7
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/login.segments/login.segment.rsc +3 -3
- package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +3 -3
- package/.next/server/app/logs.rsc +16 -16
- package/.next/server/app/logs.segments/_full.segment.rsc +16 -16
- package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
- package/.next/server/app/manifest.webmanifest/route/app-paths-manifest.json +3 -0
- package/.next/server/app/manifest.webmanifest/route/build-manifest.json +9 -0
- package/.next/server/app/manifest.webmanifest/route/server-reference-manifest.json +4 -0
- package/.next/server/app/manifest.webmanifest/route.js +8 -0
- package/.next/server/app/manifest.webmanifest/route.js.map +5 -0
- package/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -0
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +3 -0
- package/.next/server/app/manifest.webmanifest.body +1 -0
- package/.next/server/app/manifest.webmanifest.meta +1 -0
- package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +3 -3
- package/.next/server/app/messages.rsc +16 -16
- package/.next/server/app/messages.segments/_full.segment.rsc +16 -16
- package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
- package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
- package/.next/server/app/node/page_client-reference-manifest.js +1 -1
- package/.next/server/app/node.html +3 -3
- package/.next/server/app/node.rsc +16 -16
- package/.next/server/app/node.segments/_full.segment.rsc +16 -16
- package/.next/server/app/node.segments/_head.segment.rsc +4 -4
- package/.next/server/app/node.segments/_index.segment.rsc +7 -7
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/node.segments/node.segment.rsc +3 -3
- package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/nodes.html +3 -3
- package/.next/server/app/nodes.rsc +16 -16
- package/.next/server/app/nodes.segments/_full.segment.rsc +16 -16
- package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +3 -3
- package/.next/server/app/server-logs.rsc +16 -16
- package/.next/server/app/server-logs.segments/_full.segment.rsc +16 -16
- package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
- package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/networks.html +3 -3
- package/.next/server/app/settings/networks.rsc +16 -16
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +16 -16
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +3 -3
- package/.next/server/app/settings/tokens.rsc +16 -16
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +16 -16
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings.html +3 -3
- package/.next/server/app/settings.rsc +16 -16
- package/.next/server/app/settings.segments/_full.segment.rsc +16 -16
- package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks.html +3 -3
- package/.next/server/app/tasks.rsc +16 -16
- package/.next/server/app/tasks.segments/_full.segment.rsc +16 -16
- package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
- package/.next/server/app-paths-manifest.json +2 -0
- package/.next/server/chunks/00jm_next_dist_0ju_ux9._.js +18 -0
- package/.next/server/chunks/00jm_next_dist_0ju_ux9._.js.map +1 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_hub_upload_route_actions_03_eqnf.js +3 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_manifest_webmanifest_route_actions_0m16rb8.js +3 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_manifest_webmanifest_route_actions_0m16rb8.js.map +1 -0
- package/.next/server/chunks/{[externals]__11vad82._.js → [externals]__036g1.i._.js} +2 -2
- package/.next/server/chunks/[externals]__036g1.i._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0-8_f0o._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0-8_f0o._.js.map +1 -0
- package/.next/server/chunks/{[root-of-the-server]__08uyvdq._.js → [root-of-the-server]__0jndzts._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__08uyvdq._.js.map → [root-of-the-server]__0jndzts._.js.map} +1 -1
- package/.next/server/chunks/[root-of-the-server]__0mxw4vb._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0mxw4vb._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0..ddwm.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0..ddwm.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_02bxi6j.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_02bxi6j.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05oassd.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05oassd.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05vxtby.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05vxtby.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05~eml4.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_05~eml4.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_-g_q2.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_-g_q2.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_ec0xu.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0_ec0xu.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0czb6wz.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0czb6wz.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0e-cn.p.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0e-cn.p.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0k8_sr8.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0k8_sr8.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0lt_3bw.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0lt_3bw.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0uyh3yt.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0uyh3yt.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0v-a2ps.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_0v-a2ps.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_12.4r9~.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_12.4r9~.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_13mqkay.js +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_13mqkay.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__030vg4n._.js +4 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__030vg4n._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0u5aqkk._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0u5aqkk._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +4 -4
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_tasks_page_tsx_0mwxy4z._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_tasks_page_tsx_0mwxy4z._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/middleware.js +2 -2
- package/.next/server/middleware.js.nft.json +1 -1
- package/.next/server/pages/404.html +3 -3
- package/.next/server/pages/500.html +1 -1
- package/.next/static/chunks/{07~8sx3_5uiox.js → 0csnc6nlttr5s.js} +4 -1
- package/.next/static/chunks/0grmy4z.ylqtd.css +2 -0
- package/.next/static/chunks/0k68tvhf0o-sb.js +1 -0
- package/.next/static/chunks/{0v4-5tng.uh.7.js → 0lc4e9o91uv.n.js} +2 -2
- package/.next/static/chunks/0prdn66k~zu45.js +1 -0
- package/.next/static/chunks/{0ph1in3421~o-.js → 0qvb.hq86qp2g.js} +1 -1
- package/.next/static/chunks/0wyjrc0bekhiz.js +1 -0
- package/.next/static/chunks/0~ykmap37nw9d.js +1 -0
- package/.next/static/chunks/17r9h6cx1w6q-.js +4 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/.next/types/routes.d.ts +2 -1
- package/.next/types/validator.ts +9 -0
- package/app/api/hub/send/route.ts +11 -2
- package/app/api/hub/servers/route.ts +3 -29
- package/app/api/hub/upload/route.ts +83 -0
- package/app/components/AppShell.tsx +4 -2
- package/app/components/CommandCenter.tsx +1 -1
- package/app/components/DispatchPanel.tsx +1 -1
- package/app/components/MobileNav.tsx +58 -0
- package/app/components/TaskChatPanel.tsx +209 -30
- package/app/components/TaskDrawer.tsx +1 -1
- package/app/components/TopoGraph.tsx +6686 -248
- package/app/globals.css +897 -7
- package/app/layout.tsx +8 -2
- package/app/lib/serverDedupe.ts +122 -0
- package/app/lib/vendorIdentity.ts +74 -56
- package/app/manifest.ts +23 -0
- package/app/nodes/page.tsx +21 -151
- package/package.json +4 -4
- package/public/vendors/claude.svg +7 -8
- package/public/vendors/minimax.svg +8 -9
- package/public/vendors/openai.svg +8 -10
- package/scripts/p157-rc2-dedup-test.mjs +110 -0
- package/scripts/topo-a11y-titles-catalog-test.mjs +132 -0
- package/scripts/topo-active-chrome-hover-text-test.mjs +107 -0
- package/scripts/topo-active-links-chip-halo-layers-test.mjs +81 -0
- package/scripts/topo-alias-chat-brightness-test.mjs +79 -0
- package/scripts/topo-alias-text-halo-layers-test.mjs +98 -0
- package/scripts/topo-animation-temporal-modes-catalog-test.mjs +144 -0
- package/scripts/topo-avatar-chat-gate-test.mjs +77 -0
- package/scripts/topo-avatar-drop-shadow-test.mjs +86 -0
- package/scripts/topo-avatar-fallback-hover-test.mjs +104 -0
- package/scripts/topo-avatar-fallback-rotate-test.mjs +92 -0
- package/scripts/topo-avatar-rotate-test.mjs +85 -0
- package/scripts/topo-avatar-scale-test.mjs +89 -0
- package/scripts/topo-badge-chat-gate-test.mjs +74 -0
- package/scripts/topo-brand-drop-shadow-test.mjs +71 -0
- package/scripts/topo-brand-logo-breath-test.mjs +102 -0
- package/scripts/topo-brand-logo-halo-layers-test.mjs +85 -0
- package/scripts/topo-brand-logo-hover-brightness-test.mjs +105 -0
- package/scripts/topo-brand-logo-hover-rotate-test.mjs +93 -0
- package/scripts/topo-brand-logo-hover-test.mjs +85 -0
- package/scripts/topo-canvas-desc-a11y-test.mjs +87 -0
- package/scripts/topo-canvas-entrance-animation-test.mjs +117 -0
- package/scripts/topo-canvas-scan-beam-diagonal-test.mjs +148 -0
- package/scripts/topo-canvas-scan-beam-test.mjs +109 -0
- package/scripts/topo-canvas-scan-beam-vertical-test.mjs +123 -0
- package/scripts/topo-card-chat-brightness-test.mjs +86 -0
- package/scripts/topo-chat-ring-breath-curve-test.mjs +114 -0
- package/scripts/topo-chat-ring-brightness-test.mjs +80 -0
- package/scripts/topo-chat-ring-halo-layers-test.mjs +100 -0
- package/scripts/topo-chat-ring-r-breath-test.mjs +121 -0
- package/scripts/topo-chat-ring-status-halo-test.mjs +106 -0
- package/scripts/topo-chat-ring-sw-breath-test.mjs +123 -0
- package/scripts/topo-chip-pin-halo-test.mjs +85 -0
- package/scripts/topo-chip-row-digit-ls-test.mjs +135 -0
- package/scripts/topo-chip-row-member-alias-lit-test.mjs +154 -0
- package/scripts/topo-chip-row-tier-glow-brightness-test.mjs +99 -0
- package/scripts/topo-chip-row-unit-hover-tracking-test.mjs +124 -0
- package/scripts/topo-chrome-control-halo-layers-test.mjs +22 -0
- package/scripts/topo-chrome-fullscreen-breath-test.mjs +121 -0
- package/scripts/topo-chrome-layout-trailer-breath-test.mjs +86 -0
- package/scripts/topo-chrome-nodesize-trailer-breath-test.mjs +86 -0
- package/scripts/topo-chrome-reset-breath-test.mjs +115 -0
- package/scripts/topo-chrome-strip-entrance-animation-test.mjs +115 -0
- package/scripts/topo-chrome-wrapper-halo-test.mjs +83 -0
- package/scripts/topo-chrome-zoom-wrapper-breath-test.mjs +85 -0
- package/scripts/topo-click-ripple-glow-test.mjs +86 -0
- package/scripts/topo-click-ripple-halo-layers-test.mjs +79 -0
- package/scripts/topo-click-ripple-sw-test.mjs +110 -0
- package/scripts/topo-cluster-count-attr-test.mjs +80 -0
- package/scripts/topo-crescent-breath-test.mjs +104 -0
- package/scripts/topo-crescent-envelope-breath-test.mjs +103 -0
- package/scripts/topo-crescent-recede-test.mjs +111 -0
- package/scripts/topo-dense-alias-chat-halo-test.mjs +73 -0
- package/scripts/topo-dense-alias-halo-layers-test.mjs +80 -0
- package/scripts/topo-dual-axis-surfaces-catalog-test.mjs +94 -0
- package/scripts/topo-edge-badge-circle-brightness-test.mjs +82 -0
- package/scripts/topo-edge-badge-circle-hot-pulse-test.mjs +100 -0
- package/scripts/topo-edge-badge-digit-halo-layers-test.mjs +107 -0
- package/scripts/topo-edge-badge-endpoint-gate-test.mjs +94 -0
- package/scripts/topo-edge-badge-halo-layers-test.mjs +85 -0
- package/scripts/topo-edge-badge-hot-pulse-test.mjs +92 -0
- package/scripts/topo-edge-badge-hover-glow-test.mjs +90 -0
- package/scripts/topo-edge-badge-text-brightness-test.mjs +83 -0
- package/scripts/topo-edge-chat-gate-test.mjs +71 -0
- package/scripts/topo-edge-flow-rail-halo-layers-test.mjs +89 -0
- package/scripts/topo-edge-particle-brightness-test.mjs +82 -0
- package/scripts/topo-edge-particle-halo-layers-test.mjs +91 -0
- package/scripts/topo-edge-pill-glow-test.mjs +67 -0
- package/scripts/topo-edge-pin-halo-test.mjs +99 -0
- package/scripts/topo-edge-visible-brightness-test.mjs +84 -0
- package/scripts/topo-edge-visible-halo-layers-test.mjs +87 -0
- package/scripts/topo-endpoint-ring-brightness-test.mjs +83 -0
- package/scripts/topo-endpoint-ring-flow-halo-test.mjs +107 -0
- package/scripts/topo-endpoint-ring-halo-layers-test.mjs +100 -0
- package/scripts/topo-filter-pill-glow-test.mjs +90 -0
- package/scripts/topo-filter-pill-halo-layers-test.mjs +27 -0
- package/scripts/topo-flow-arrow-brightness-test.mjs +82 -0
- package/scripts/topo-flow-rail-brightness-test.mjs +80 -0
- package/scripts/topo-fullscreen-attr-test.mjs +73 -0
- package/scripts/topo-fullscreen-brightness-test.mjs +84 -0
- package/scripts/topo-fullscreen-icon-rotate-test.mjs +93 -0
- package/scripts/topo-grid-content-bottom-attr-test.mjs +72 -0
- package/scripts/topo-group-box-brightness-test.mjs +84 -0
- package/scripts/topo-group-box-halo-layers-test.mjs +91 -0
- package/scripts/topo-group-chat-gate-test.mjs +77 -0
- package/scripts/topo-group-label-brightness-test.mjs +84 -0
- package/scripts/topo-group-label-halo-layers-test.mjs +78 -0
- package/scripts/topo-group-label-hover-glow-test.mjs +86 -0
- package/scripts/topo-group-label-member-alias-hover-test.mjs +125 -0
- package/scripts/topo-group-pill-glow-test.mjs +76 -0
- package/scripts/topo-group-tint-brightness-test.mjs +82 -0
- package/scripts/topo-h2-dual-axis-breath-test.mjs +92 -0
- package/scripts/topo-h2-triple-axis-breath-test.mjs +142 -0
- package/scripts/topo-halo-chat-gate-test.mjs +72 -0
- package/scripts/topo-hover-detail-halo-test.mjs +76 -0
- package/scripts/topo-hub-a11y-title-test.mjs +95 -0
- package/scripts/topo-hub-core-brightness-test.mjs +82 -0
- package/scripts/topo-hub-core-halo-layers-test.mjs +81 -0
- package/scripts/topo-hub-digit-brightness-test.mjs +79 -0
- package/scripts/topo-hub-digit-halo-layers-test.mjs +76 -0
- package/scripts/topo-hub-digit-ls-test.mjs +119 -0
- package/scripts/topo-hub-halo-brightness-test.mjs +80 -0
- package/scripts/topo-hub-halo-glow-test.mjs +96 -0
- package/scripts/topo-hub-halo-halo-layers-test.mjs +76 -0
- package/scripts/topo-hub-highlight-brightness-test.mjs +84 -0
- package/scripts/topo-hub-highlight-glow-test.mjs +99 -0
- package/scripts/topo-hub-highlight-halo-layers-test.mjs +78 -0
- package/scripts/topo-hub-highlight-r-test.mjs +112 -0
- package/scripts/topo-hub-hover-ring-brightness-test.mjs +79 -0
- package/scripts/topo-hub-hover-ring-glow-test.mjs +97 -0
- package/scripts/topo-hub-hover-ring-halo-layers-test.mjs +71 -0
- package/scripts/topo-hub-spoke-brightness-test.mjs +77 -0
- package/scripts/topo-hub-spoke-glow-test.mjs +112 -0
- package/scripts/topo-hub-spoke-halo-layers-test.mjs +97 -0
- package/scripts/topo-hub-spoke-self-filter-test.mjs +119 -0
- package/scripts/topo-kicker-breath-test.mjs +100 -0
- package/scripts/topo-kicker-dual-axis-breath-test.mjs +81 -0
- package/scripts/topo-kicker-halo-layers-test.mjs +82 -0
- package/scripts/topo-kicker-triple-axis-breath-test.mjs +124 -0
- package/scripts/topo-label-card-brightness-test.mjs +81 -0
- package/scripts/topo-layout-hover-fw-test.mjs +98 -0
- package/scripts/topo-layout-toggle-brightness-test.mjs +94 -0
- package/scripts/topo-layout-toggle-halo-layers-test.mjs +95 -0
- package/scripts/topo-legend-count-brightness-test.mjs +80 -0
- package/scripts/topo-legend-count-halo-layers-test.mjs +79 -0
- package/scripts/topo-legend-count-letter-spacing-test.mjs +108 -0
- package/scripts/topo-legend-label-fw-test.mjs +107 -0
- package/scripts/topo-legend-panel-title-breath-test.mjs +86 -0
- package/scripts/topo-legend-pin-ring-brightness-test.mjs +82 -0
- package/scripts/topo-legend-pin-ring-halo-layers-test.mjs +71 -0
- package/scripts/topo-legend-row-count-brightness-test.mjs +85 -0
- package/scripts/topo-legend-row-label-glow-test.mjs +102 -0
- package/scripts/topo-legend-swatch-glow-test.mjs +109 -0
- package/scripts/topo-legend-swatch-member-alias-match-test.mjs +139 -0
- package/scripts/topo-legend-tint-brightness-test.mjs +83 -0
- package/scripts/topo-legend-trio-halo-layers-test.mjs +22 -0
- package/scripts/topo-live-lanes.mjs +48 -0
- package/scripts/topo-minimap-container-halo-test.mjs +82 -0
- package/scripts/topo-minimap-dot-chat-gate-test.mjs +81 -0
- package/scripts/topo-minimap-hover-glow-test.mjs +109 -0
- package/scripts/topo-minimap-viewport-brightness-test.mjs +84 -0
- package/scripts/topo-minimap-viewport-halo-layers-test.mjs +24 -0
- package/scripts/topo-more-footer-brightness-test.mjs +94 -0
- package/scripts/topo-node-alias-brightness-test.mjs +84 -0
- package/scripts/topo-node-avatar-halo-layers-test.mjs +25 -0
- package/scripts/topo-node-hover-ring-halo-layers-test.mjs +70 -0
- package/scripts/topo-node-label-card-halo-test.mjs +76 -0
- package/scripts/topo-node-sub-text-brightness-test.mjs +88 -0
- package/scripts/topo-nodesize-brightness-test.mjs +82 -0
- package/scripts/topo-nodesize-halo-layers-test.mjs +89 -0
- package/scripts/topo-nodesize-hover-fw-test.mjs +99 -0
- package/scripts/topo-orphan-label-opacity-test.mjs +98 -0
- package/scripts/topo-overlap-test.mjs +22 -8
- package/scripts/topo-panel-count-halo-layers-test.mjs +91 -0
- package/scripts/topo-panel-count-hover-ls-test.mjs +87 -0
- package/scripts/topo-panel-rect-halo-test.mjs +90 -0
- package/scripts/topo-panel-row-brightness-test.mjs +116 -0
- package/scripts/topo-panel-title-brightness-test.mjs +98 -0
- package/scripts/topo-panel-title-glow-test.mjs +111 -0
- package/scripts/topo-panel-titles-dual-axis-breath-test.mjs +94 -0
- package/scripts/topo-panel-titles-halo-layers-test.mjs +23 -0
- package/scripts/topo-panel-titles-triple-axis-breath-test.mjs +161 -0
- package/scripts/topo-pill-x-rotate-test.mjs +96 -0
- package/scripts/topo-pip-brightness-test.mjs +85 -0
- package/scripts/topo-pressure-bar-halo-layers-test.mjs +19 -0
- package/scripts/topo-pressure-seg-glow-test.mjs +92 -0
- package/scripts/topo-pressure-seg-member-alias-match-test.mjs +133 -0
- package/scripts/topo-pressure-seg-motion-test.mjs +101 -0
- package/scripts/topo-r717-scan-beam-pair-pattern-test.mjs +100 -0
- package/scripts/topo-r717-triple-axis-pair-pattern-test.mjs +113 -0
- package/scripts/topo-r717-triple-axis-tier-pattern-test.mjs +117 -0
- package/scripts/topo-recent-count-brightness-test.mjs +84 -0
- package/scripts/topo-recent-more-fw-test.mjs +126 -0
- package/scripts/topo-recent-more-halo-layers-test.mjs +90 -0
- package/scripts/topo-recent-panel-hot-pulse-test.mjs +105 -0
- package/scripts/topo-recent-panel-title-breath-test.mjs +91 -0
- package/scripts/topo-recent-pip-halo-layers-test.mjs +82 -0
- package/scripts/topo-recent-row-chat-gate-test.mjs +75 -0
- package/scripts/topo-recent-row-content-lift-test.mjs +140 -0
- package/scripts/topo-recent-row-fw-test.mjs +115 -0
- package/scripts/topo-recent-row-text-glow-test.mjs +86 -0
- package/scripts/topo-recent-row-text-halo-layers-test.mjs +67 -0
- package/scripts/topo-recent-tint-brightness-test.mjs +80 -0
- package/scripts/topo-recent-ts-brightness-test.mjs +86 -0
- package/scripts/topo-reduced-motion-attr-test.mjs +69 -0
- package/scripts/topo-reset-brightness-test.mjs +83 -0
- package/scripts/topo-reset-icon-hover-scale-test.mjs +102 -0
- package/scripts/topo-respiratory-axis-count-stats-test.mjs +154 -0
- package/scripts/topo-respiratory-patterns-catalog-test.mjs +112 -0
- package/scripts/topo-respiratory-rolodex-test.mjs +83 -0
- package/scripts/topo-respiratory-tiers-catalog-test.mjs +119 -0
- package/scripts/topo-respiratory-triple-axis-surfaces-catalog-test.mjs +127 -0
- package/scripts/topo-runtime-badge-brightness-test.mjs +78 -0
- package/scripts/topo-runtime-badge-glow-test.mjs +108 -0
- package/scripts/topo-runtime-badge-halo-layers-test.mjs +87 -0
- package/scripts/topo-runtime-badge-rotate-test.mjs +85 -0
- package/scripts/topo-section-title-breath-test.mjs +83 -0
- package/scripts/topo-section-title-halo-layers-test.mjs +88 -0
- package/scripts/topo-spoke-chat-gate-test.mjs +72 -0
- package/scripts/topo-starfield-hue-test.mjs +109 -0
- package/scripts/topo-status-pin-pill-halo-layers-test.mjs +17 -0
- package/scripts/topo-status-ring-brightness-test.mjs +84 -0
- package/scripts/topo-status-ring-chat-gate-test.mjs +72 -0
- package/scripts/topo-status-ring-halo-layers-test.mjs +105 -0
- package/scripts/topo-status-ring-status-halo-test.mjs +110 -0
- package/scripts/topo-sub-text-chat-brightness-test.mjs +81 -0
- package/scripts/topo-svg-title-a11y-r731-test.mjs +93 -0
- package/scripts/topo-svg-title-a11y-test.mjs +88 -0
- package/scripts/topo-title-block-entrance-animation-test.mjs +127 -0
- package/scripts/topo-title-block-envelope-breath-test.mjs +87 -0
- package/scripts/topo-titleblock-h2-hover-fw-test.mjs +109 -0
- package/scripts/topo-titleblock-h2-hover-tracking-test.mjs +128 -0
- package/scripts/topo-titleblock-kicker-hover-test.mjs +134 -0
- package/scripts/topo-tree-diag.mjs +95 -0
- package/scripts/topo-vendor-chip-glow-test.mjs +97 -0
- package/scripts/topo-vendor-chip-halo-layers-test.mjs +18 -0
- package/scripts/topo-vendor-chip-pin-halo-test.mjs +88 -0
- package/scripts/topo-vendor-count-suffix-halo-layers-test.mjs +79 -0
- package/scripts/topo-vendor-distribution-wrapper-halo-test.mjs +93 -0
- package/scripts/topo-vendor-letter-halo-layers-test.mjs +93 -0
- package/scripts/topo-vendor-pill-glow-test.mjs +98 -0
- package/scripts/topo-watermark-breath-test.mjs +100 -0
- package/scripts/topo-watermark-dual-axis-breath-test.mjs +88 -0
- package/scripts/topo-watermark-envelope-breath-test.mjs +88 -0
- package/scripts/topo-watermark-recede-test.mjs +114 -0
- package/scripts/topo-watermark-triple-axis-breath-test.mjs +129 -0
- package/scripts/topo-working-online-chip-halo-layers-test.mjs +94 -0
- package/scripts/topo-zoom-buttons-brightness-test.mjs +94 -0
- package/scripts/topo-zoom-in-out-halo-layers-test.mjs +97 -0
- package/scripts/topo-zoom-level-breath-test.mjs +87 -0
- package/scripts/topo-zoom-level-brightness-test.mjs +83 -0
- package/scripts/topo-zoom-level-color-test.mjs +105 -0
- package/scripts/topo-zoom-level-dual-axis-breath-test.mjs +83 -0
- package/scripts/topo-zoom-level-halo-layers-test.mjs +78 -0
- package/scripts/topo-zoom-level-triple-axis-breath-test.mjs +148 -0
- package/.next/static/chunks/01lmbsd37fybu.js +0 -1
- package/.next/static/chunks/03o.h6kvmw4l_.js +0 -1
- package/.next/static/chunks/0fuba20p57-zo.js +0 -1
- package/.next/static/chunks/0m.1mvl~t.avc.css +0 -2
- package/.next/static/chunks/10cj-86disers.js +0 -1
- package/.next/static/chunks/158h2g7f-nxbt.js +0 -4
- /package/.next/server/chunks/{[externals]__11vad82._.js.map → 0ykm__next-internal_server_app_api_hub_upload_route_actions_03_eqnf.js.map} +0 -0
- /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → 7CjN6e7QM2eogH8RhsM1k}/_buildManifest.js +0 -0
- /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → 7CjN6e7QM2eogH8RhsM1k}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{tQ1EtcEiS7ikgAoAyZWm7 → 7CjN6e7QM2eogH8RhsM1k}/_ssgManifest.js +0 -0
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
-
<!-- MiniMax vendor mark
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<circle cx="32" cy="32" r="
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
stroke-linecap="round" stroke-linejoin="round" />
|
|
2
|
+
<!-- MiniMax vendor mark — official MiniMax logo (simple-icons set, CC0).
|
|
3
|
+
Vincent-authorized 2026-05-21 to use real vendor marks. Tinted circular
|
|
4
|
+
badge frames the official mark for the dashboard node-avatar context. -->
|
|
5
|
+
<circle cx="32" cy="32" r="32" fill="hsl(18 50% 22%)"/>
|
|
6
|
+
<circle cx="32" cy="32" r="30" fill="none" stroke="hsl(18 65% 52%)" stroke-width="2"/>
|
|
7
|
+
<g transform="translate(16 16) scale(1.333)" fill="hsl(20 80% 84%)">
|
|
8
|
+
<path d="M11.43 3.92a.86.86 0 1 0-1.718 0v14.236a1.999 1.999 0 0 1-3.997 0V9.022a.86.86 0 1 0-1.718 0v3.87a1.999 1.999 0 0 1-3.997 0V11.49a.57.57 0 0 1 1.139 0v1.404a.86.86 0 0 0 1.719 0V9.022a1.999 1.999 0 0 1 3.997 0v9.134a.86.86 0 0 0 1.719 0V3.92a1.998 1.998 0 1 1 3.996 0v11.788a.57.57 0 1 1-1.139 0zm10.572 3.105a2 2 0 0 0-1.999 1.997v7.63a.86.86 0 0 1-1.718 0V3.923a1.999 1.999 0 0 0-3.997 0v16.16a.86.86 0 0 1-1.719 0V18.08a.57.57 0 1 0-1.138 0v2a1.998 1.998 0 0 0 3.996 0V3.92a.86.86 0 0 1 1.719 0v12.73a1.999 1.999 0 0 0 3.996 0V9.023a.86.86 0 1 1 1.72 0v6.686a.57.57 0 0 0 1.138 0V9.022a2 2 0 0 0-1.998-1.997"/>
|
|
9
|
+
</g>
|
|
11
10
|
</svg>
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
-
<!-- OpenAI
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
fill="none" stroke="hsl(165 50% 78%)" stroke-width="3" stroke-linejoin="round" />
|
|
11
|
-
<circle cx="32" cy="32" r="4" fill="hsl(165 50% 78%)" />
|
|
2
|
+
<!-- OpenAI vendor mark — official OpenAI logo (simple-icons set, CC0).
|
|
3
|
+
Vincent-authorized 2026-05-21 to use real vendor marks. Tinted circular
|
|
4
|
+
badge frames the official mark for the dashboard node-avatar context. -->
|
|
5
|
+
<circle cx="32" cy="32" r="32" fill="hsl(165 26% 20%)"/>
|
|
6
|
+
<circle cx="32" cy="32" r="30" fill="none" stroke="hsl(165 40% 44%)" stroke-width="2"/>
|
|
7
|
+
<g transform="translate(16 16) scale(1.333)" fill="hsl(165 50% 82%)">
|
|
8
|
+
<path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"/>
|
|
9
|
+
</g>
|
|
12
10
|
</svg>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/* #157 RC#2 verification — Servers panel hostname dedup.
|
|
2
|
+
*
|
|
3
|
+
* Bug (Vincent 5560 + live re-probe 2026-05-20): the hub /api/servers
|
|
4
|
+
* endpoint keys host telemetry by (hostname, ip), so a machine whose
|
|
5
|
+
* agents report over more than one interface surfaces as multiple
|
|
6
|
+
* rows. `iZrj93pr2rcf5r2y9uo1oyZ` appeared twice — Docker-bridge IP
|
|
7
|
+
* (telemetry-bearing) + loopback (telemetry null) — splitting its
|
|
8
|
+
* agent count across two cards.
|
|
9
|
+
*
|
|
10
|
+
* Fix: `dedupeByHostname` in app/lib/serverDedupe.ts, applied in the
|
|
11
|
+
* /api/hub/servers proxy before normalizeServer.
|
|
12
|
+
*
|
|
13
|
+
* Two legs:
|
|
14
|
+
* A. mock fixture — compile serverDedupe.ts, run a crafted payload
|
|
15
|
+
* that exercises every branch (multi-row merge, telemetry
|
|
16
|
+
* coalesce, NAT-shared IP NOT merged, `unknown` passthrough,
|
|
17
|
+
* agents[] union).
|
|
18
|
+
* B. real payload — GET the running dashboard proxy and assert no
|
|
19
|
+
* hostname appears twice + counts are summed.
|
|
20
|
+
*/
|
|
21
|
+
import { execSync } from 'node:child_process';
|
|
22
|
+
import { readFileSync, renameSync, mkdirSync } from 'node:fs';
|
|
23
|
+
import { pathToFileURL } from 'node:url';
|
|
24
|
+
|
|
25
|
+
let failed = 0;
|
|
26
|
+
const ok = (name, cond, detail = '') => {
|
|
27
|
+
if (cond) { console.log(` ✅ ${name}`); }
|
|
28
|
+
else { console.log(` ❌ ${name}${detail ? ' — ' + detail : ''}`); failed++; }
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// ── Leg A: mock fixture against the real dedup module ──────────────
|
|
32
|
+
console.log('Leg A — mock fixture (compiled serverDedupe.ts):');
|
|
33
|
+
const OUT = '/tmp/p157-rc2-dedupe';
|
|
34
|
+
mkdirSync(OUT, { recursive: true });
|
|
35
|
+
execSync(
|
|
36
|
+
`npx tsc app/lib/serverDedupe.ts --outDir ${OUT} --module es2022 --target es2022 --moduleResolution bundler --skipLibCheck`,
|
|
37
|
+
{ stdio: 'inherit' },
|
|
38
|
+
);
|
|
39
|
+
renameSync(`${OUT}/serverDedupe.js`, `${OUT}/serverDedupe.mjs`);
|
|
40
|
+
const { dedupeByHostname } = await import(pathToFileURL(`${OUT}/serverDedupe.mjs`).href);
|
|
41
|
+
|
|
42
|
+
const fixture = [
|
|
43
|
+
// same hostname, two interfaces — bridge row fresh + telemetried,
|
|
44
|
+
// loopback row staler + telemetry null
|
|
45
|
+
{ hostname: 'host-A', ip: '172.17.0.2', agent_count: 29, last_seen: '2026-05-20 04:41:46',
|
|
46
|
+
cpu_load_1min: 1.49, cpu_cores: 8, mem_used_gb: 22.6, mem_total_gb: 32,
|
|
47
|
+
agents: [{ alias: 'a1' }, { alias: 'a2' }] },
|
|
48
|
+
{ hostname: 'host-A', ip: '127.0.0.1', agent_count: 38, last_seen: '2026-05-20 04:41:43',
|
|
49
|
+
cpu_load_1min: null, mem_used_gb: null,
|
|
50
|
+
agents: [{ alias: 'a2' }, { alias: 'a3' }] },
|
|
51
|
+
// NAT-shared public IP, distinct hostnames — must NOT merge
|
|
52
|
+
{ hostname: 'host-B', ip: '223.167.142.73', agent_count: 5, last_seen: '2026-05-18 02:34:16' },
|
|
53
|
+
{ hostname: 'host-C', ip: '223.167.142.73', agent_count: 2, last_seen: '2026-05-13 16:44:41' },
|
|
54
|
+
// sentinel hostname — two distinct unknown machines, pass through both
|
|
55
|
+
{ hostname: 'unknown', ip: '127.0.0.1', agent_count: 2, last_seen: '2026-05-16 08:40:14' },
|
|
56
|
+
{ hostname: 'unknown', ip: '10.0.0.9', agent_count: 1, last_seen: '2026-05-16 09:00:00' },
|
|
57
|
+
];
|
|
58
|
+
const out = dedupeByHostname(fixture);
|
|
59
|
+
const byHost = (h) => out.filter(r => r.hostname === h);
|
|
60
|
+
const hostA = byHost('host-A')[0];
|
|
61
|
+
|
|
62
|
+
ok('host-A collapses 2 rows → 1', byHost('host-A').length === 1, `got ${byHost('host-A').length}`);
|
|
63
|
+
ok('host-A agent_count summed 29+38=67', hostA?.agent_count === 67, `got ${hostA?.agent_count}`);
|
|
64
|
+
ok('host-A telemetry coalesced from bridge row (cpu 1.49)', hostA?.cpu_load_1min === 1.49, `got ${hostA?.cpu_load_1min}`);
|
|
65
|
+
ok('host-A mem coalesced (22.6)', hostA?.mem_used_gb === 22.6, `got ${hostA?.mem_used_gb}`);
|
|
66
|
+
ok('host-A last_seen = freshest (04:41:46)', hostA?.last_seen === '2026-05-20 04:41:46', `got ${hostA?.last_seen}`);
|
|
67
|
+
ok('host-A agents[] unioned + dedup by alias (a1,a2,a3)',
|
|
68
|
+
hostA?.agents?.length === 3 &&
|
|
69
|
+
new Set(hostA.agents.map(a => a.alias)).size === 3,
|
|
70
|
+
`got ${JSON.stringify(hostA?.agents)}`);
|
|
71
|
+
ok('host-B + host-C NOT merged despite shared IP', byHost('host-B').length === 1 && byHost('host-C').length === 1);
|
|
72
|
+
ok('two `unknown` rows both pass through (not merged)', byHost('unknown').length === 2, `got ${byHost('unknown').length}`);
|
|
73
|
+
ok('total rows: 1 (A) + 1 (B) + 1 (C) + 2 (unknown) = 5', out.length === 5, `got ${out.length}`);
|
|
74
|
+
|
|
75
|
+
// idempotency — running dedup on already-deduped output is a no-op
|
|
76
|
+
const twice = dedupeByHostname(out);
|
|
77
|
+
ok('idempotent — dedup(dedup(x)) === dedup(x)', twice.length === out.length);
|
|
78
|
+
|
|
79
|
+
// ── Leg B: real payload through the running dashboard proxy ─────────
|
|
80
|
+
console.log('\nLeg B — real payload (live /api/hub/servers proxy):');
|
|
81
|
+
let TOKEN;
|
|
82
|
+
try {
|
|
83
|
+
TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
84
|
+
} catch {
|
|
85
|
+
console.log(' ⚠️ no anet config — skipping live leg');
|
|
86
|
+
}
|
|
87
|
+
if (TOKEN) {
|
|
88
|
+
const res = await fetch('http://127.0.0.1:3000/api/hub/servers', {
|
|
89
|
+
headers: { cookie: `anet_dashboard_session=v3:${TOKEN}` },
|
|
90
|
+
});
|
|
91
|
+
ok('proxy returns 200', res.status === 200, `status ${res.status}`);
|
|
92
|
+
const body = await res.json();
|
|
93
|
+
const servers = body.servers ?? [];
|
|
94
|
+
ok('proxy returns servers[]', Array.isArray(servers) && servers.length > 0, `got ${servers.length}`);
|
|
95
|
+
const counts = {};
|
|
96
|
+
for (const s of servers) counts[s.hostname] = (counts[s.hostname] ?? 0) + 1;
|
|
97
|
+
const dups = Object.entries(counts).filter(([h, n]) => n > 1 && h !== 'unknown' && h !== '');
|
|
98
|
+
ok('no real hostname appears twice', dups.length === 0, `dups: ${JSON.stringify(dups)}`);
|
|
99
|
+
const izrj = servers.find(s => s.hostname?.startsWith('iZrj93pr'));
|
|
100
|
+
if (izrj) {
|
|
101
|
+
ok('iZrj93pr… host present as single card', true);
|
|
102
|
+
ok('iZrj93pr… has telemetry after coalesce (cpu non-null)', izrj.cpu_load_1min != null, `cpu ${izrj.cpu_load_1min}`);
|
|
103
|
+
console.log(` ℹ️ iZrj93pr… merged: agent_count=${izrj.agent_count}, cpu=${izrj.cpu_load_1min}, ip=${izrj.ip}`);
|
|
104
|
+
} else {
|
|
105
|
+
console.log(' ℹ️ iZrj93pr… not in current live payload (hub state changed) — structural dup check still authoritative');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
console.log(`\n${failed === 0 ? '✅ ALL GREEN' : `❌ ${failed} FAILED`}`);
|
|
110
|
+
process.exit(failed === 0 ? 0 : 1);
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/* Round 732 — a11y titles catalog on canvas root. 7TH orthogonal
|
|
2
|
+
* meta-doc axis. The introspection layer crosses families:
|
|
3
|
+
*
|
|
4
|
+
* Breath family (6 meta-docs):
|
|
5
|
+
* R710 data-topo-respiratory-rolodex (cadences)
|
|
6
|
+
* R716 data-topo-respiratory-dual-axis-surfaces (axes)
|
|
7
|
+
* R717 data-topo-respiratory-patterns (patterns)
|
|
8
|
+
* R720 data-topo-respiratory-tiers (tiers)
|
|
9
|
+
* R723 data-topo-respiratory-triple-axis-surfaces (triple-axis)
|
|
10
|
+
* R729 data-topo-respiratory-axis-count-stats (stats)
|
|
11
|
+
*
|
|
12
|
+
* A11y sub-family (1 meta-doc):
|
|
13
|
+
* R732 data-topo-a11y-titles (accessible names) ← this round
|
|
14
|
+
*
|
|
15
|
+
* Each entry maps surface → DOM selector → accessible name. The test
|
|
16
|
+
* resolves each selector at runtime and verifies the element's direct
|
|
17
|
+
* <title> child textContent matches the catalog's accessible_name.
|
|
18
|
+
*
|
|
19
|
+
* Assertions:
|
|
20
|
+
* - attr present on root <svg>
|
|
21
|
+
* - JSON parses to Array of 5 entries (R730: 3, R731: 2)
|
|
22
|
+
* - Each entry has {surface, selector, accessible_name} shape with
|
|
23
|
+
* non-empty string values
|
|
24
|
+
* - Each accessible_name follows canonical "<name> · <role>" format
|
|
25
|
+
* - Each selector resolves at runtime to an element (or null IF
|
|
26
|
+
* conditionally rendered, treated as pass for the cross-check)
|
|
27
|
+
* - When element exists, its direct <title> child's textContent
|
|
28
|
+
* equals catalog's accessible_name (STRICT cross-check)
|
|
29
|
+
* - All 5 surfaces are present in the expected anchor set
|
|
30
|
+
*/
|
|
31
|
+
import { chromium } from 'playwright';
|
|
32
|
+
import { readFileSync } from 'node:fs';
|
|
33
|
+
|
|
34
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
35
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
36
|
+
|
|
37
|
+
const browser = await chromium.launch({ headless: true });
|
|
38
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
39
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
40
|
+
await ctx.addInitScript(() => {
|
|
41
|
+
try {
|
|
42
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
43
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
44
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
45
|
+
} catch {}
|
|
46
|
+
});
|
|
47
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
48
|
+
const r = await route.fetch();
|
|
49
|
+
const b = await r.json();
|
|
50
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
51
|
+
const mk = (alias) => ({
|
|
52
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
53
|
+
network_id: nid, project_dir: null,
|
|
54
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
55
|
+
});
|
|
56
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
57
|
+
});
|
|
58
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
59
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
60
|
+
const page = await ctx.newPage();
|
|
61
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
62
|
+
await page.waitForSelector('[data-topo-canvas-aria]', { timeout: 15000, state: 'attached' });
|
|
63
|
+
await page.waitForTimeout(300);
|
|
64
|
+
|
|
65
|
+
const result = await page.evaluate(() => {
|
|
66
|
+
const svg = document.querySelector('[data-topo-canvas-aria]');
|
|
67
|
+
const catalogAttr = svg?.getAttribute('data-topo-a11y-titles') ?? null;
|
|
68
|
+
let catalog = null;
|
|
69
|
+
try { catalog = JSON.parse(catalogAttr ?? ''); } catch {}
|
|
70
|
+
|
|
71
|
+
/* Direct child <title> only — skip nested titles in mask defs etc. */
|
|
72
|
+
const directTitleText = (el) => {
|
|
73
|
+
if (!el) return null;
|
|
74
|
+
for (const child of el.children) {
|
|
75
|
+
if (child.tagName.toLowerCase() === 'title') return child.textContent;
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const crossChecks = Array.isArray(catalog)
|
|
81
|
+
? catalog.map(entry => {
|
|
82
|
+
const el = document.querySelector(entry.selector);
|
|
83
|
+
return {
|
|
84
|
+
surface: entry.surface,
|
|
85
|
+
element_present: !!el,
|
|
86
|
+
actual_title: directTitleText(el),
|
|
87
|
+
matches: !el || directTitleText(el) === entry.accessible_name,
|
|
88
|
+
};
|
|
89
|
+
})
|
|
90
|
+
: [];
|
|
91
|
+
|
|
92
|
+
return { catalogAttr, catalog, crossChecks };
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
await browser.close();
|
|
96
|
+
|
|
97
|
+
const { catalog, crossChecks } = result;
|
|
98
|
+
|
|
99
|
+
const validShape = Array.isArray(catalog) && catalog.every(e =>
|
|
100
|
+
typeof e?.surface === 'string' && e.surface.length > 0
|
|
101
|
+
&& typeof e?.selector === 'string' && e.selector.length > 0
|
|
102
|
+
&& typeof e?.accessible_name === 'string' && e.accessible_name.length > 0
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
/* R733 relaxed canonical-format from "exactly 2 parts" to ">=2 parts"
|
|
106
|
+
* to admit the new hub-highlight entry's 3-part name ("hub · network
|
|
107
|
+
* center · idle indicator"). All earlier entries still match. */
|
|
108
|
+
const canonicalFormat = (s) => typeof s === 'string' && /^[^·]+( · [^·]+)+$/.test(s);
|
|
109
|
+
const allCanonical = Array.isArray(catalog) && catalog.every(e => canonicalFormat(e.accessible_name));
|
|
110
|
+
|
|
111
|
+
const expectedSurfaces = ['canvas scan beam', 'canvas scan beam diagonal', 'canvas scan beam vertical', 'canvas-corner crescent', 'hub-highlight disc', 'legend panel title', 'recent panel title', 'title-block brand logo', 'watermark text'];
|
|
112
|
+
const actualSurfaces = Array.isArray(catalog) ? catalog.map(e => e.surface).sort() : [];
|
|
113
|
+
const surfacesMatch = JSON.stringify(actualSurfaces) === JSON.stringify(expectedSurfaces);
|
|
114
|
+
|
|
115
|
+
const allCrossChecks = crossChecks.every(c => c.matches);
|
|
116
|
+
|
|
117
|
+
const results = {
|
|
118
|
+
attr_present: !!result.catalogAttr,
|
|
119
|
+
json_parses: catalog !== null,
|
|
120
|
+
is_array: Array.isArray(catalog),
|
|
121
|
+
has_9_entries: Array.isArray(catalog) && catalog.length === 9,
|
|
122
|
+
shape_valid: validShape,
|
|
123
|
+
all_accessible_names_canonical: allCanonical,
|
|
124
|
+
surfaces_match_expected_set: surfacesMatch,
|
|
125
|
+
all_cross_checks_pass: allCrossChecks,
|
|
126
|
+
};
|
|
127
|
+
const ok = Object.values(results).every(Boolean);
|
|
128
|
+
console.log(`${ok ? '✅' : '❌'} R732 a11y titles catalog (7th meta-doc — pentagon→hexagon→HEPTAGON, cross-family):`,
|
|
129
|
+
JSON.stringify(results, null, 2),
|
|
130
|
+
`\n catalog: ${JSON.stringify(catalog)}`,
|
|
131
|
+
`\n cross-checks: ${JSON.stringify(crossChecks)}`);
|
|
132
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/* Round 552 verification: chrome active-variant buttons gain
|
|
2
|
+
* hover:text-cyan-200 lift. Coordinated 4-anchor edit:
|
|
3
|
+
* Ring | Grid | S/M/L | Fullscreen
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. Pick an active button (Ring is active by default in ring layout)
|
|
7
|
+
* 2. Read rest text color (cyan-300 = rgb(103, 232, 249))
|
|
8
|
+
* 3. Hover → text color = cyan-200 (rgb(165, 243, 252))
|
|
9
|
+
* 4. Verify bg also deepened (cyan-500/20)
|
|
10
|
+
* 5. Source-side regex: 4 occurrences of the new className substring
|
|
11
|
+
*/
|
|
12
|
+
import { chromium } from 'playwright';
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
|
|
15
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
16
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
17
|
+
|
|
18
|
+
const browser = await chromium.launch({ headless: true });
|
|
19
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
20
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
21
|
+
await ctx.addInitScript(() => {
|
|
22
|
+
try {
|
|
23
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
24
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
25
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
26
|
+
} catch {}
|
|
27
|
+
});
|
|
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: 'idle', 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: [mk('a·1')] } });
|
|
38
|
+
});
|
|
39
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
40
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
41
|
+
const page = await ctx.newPage();
|
|
42
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
43
|
+
await page.waitForSelector('[data-topo-chrome-layout="ring"]', { timeout: 15000 });
|
|
44
|
+
await page.waitForTimeout(500);
|
|
45
|
+
|
|
46
|
+
// Ring is active in ring layout
|
|
47
|
+
const sel = '[data-topo-chrome-layout="ring"]';
|
|
48
|
+
const rest = await page.evaluate((s) => {
|
|
49
|
+
const el = document.querySelector(s);
|
|
50
|
+
if (!el) return null;
|
|
51
|
+
const cs = getComputedStyle(el);
|
|
52
|
+
return {
|
|
53
|
+
color: cs.color,
|
|
54
|
+
bg: cs.backgroundColor,
|
|
55
|
+
activeAttr: el.getAttribute('data-topo-chrome-layout-active'),
|
|
56
|
+
};
|
|
57
|
+
}, sel);
|
|
58
|
+
|
|
59
|
+
await page.hover(sel);
|
|
60
|
+
await page.waitForTimeout(400);
|
|
61
|
+
const hover = await page.evaluate((s) => {
|
|
62
|
+
const el = document.querySelector(s);
|
|
63
|
+
if (!el) return null;
|
|
64
|
+
const cs = getComputedStyle(el);
|
|
65
|
+
return { color: cs.color, bg: cs.backgroundColor };
|
|
66
|
+
}, sel);
|
|
67
|
+
|
|
68
|
+
await browser.close();
|
|
69
|
+
|
|
70
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
71
|
+
// New active-variant substring must appear 4× (Ring, Grid, S/M/L, Fullscreen)
|
|
72
|
+
const occurrences = (src.match(/bg-cyan-500\/15 text-cyan-300 font-medium hover:bg-cyan-500\/20 hover:text-cyan-200 active:bg-cyan-500\/25/g) || []).length;
|
|
73
|
+
|
|
74
|
+
// Tailwind v4 emits cyan-300 / cyan-200 in lab() / oklab() color
|
|
75
|
+
// space, not legacy rgb(). Parse the L (lightness) component and
|
|
76
|
+
// verify hover L > rest L (cyan-200 is lighter than cyan-300).
|
|
77
|
+
// Bg uses oklab with alpha; rest alpha = 0.15 (cyan-500/15), hover
|
|
78
|
+
// alpha = 0.2 (cyan-500/20).
|
|
79
|
+
const parseLab = (s) => {
|
|
80
|
+
const m = (s || '').match(/lab\(([0-9.]+)\s/) || (s || '').match(/oklab\(([0-9.]+)\s/);
|
|
81
|
+
return m ? parseFloat(m[1]) : NaN;
|
|
82
|
+
};
|
|
83
|
+
const parseAlpha = (s) => {
|
|
84
|
+
const m = (s || '').match(/\/\s*([0-9.]+)\)/);
|
|
85
|
+
return m ? parseFloat(m[1]) : NaN;
|
|
86
|
+
};
|
|
87
|
+
const restL = parseLab(rest?.color);
|
|
88
|
+
const hoverL = parseLab(hover?.color);
|
|
89
|
+
const restBgA = parseAlpha(rest?.bg);
|
|
90
|
+
const hoverBgA = parseAlpha(hover?.bg);
|
|
91
|
+
|
|
92
|
+
const results = {
|
|
93
|
+
active_attr: rest?.activeAttr === 'true',
|
|
94
|
+
rest_text_parsed: !Number.isNaN(restL),
|
|
95
|
+
hover_text_parsed: !Number.isNaN(hoverL),
|
|
96
|
+
hover_text_lighter_than_rest: hoverL > restL + 3, // cyan-200 L≈91 > cyan-300 L≈85
|
|
97
|
+
rest_bg_alpha_0_15: Math.abs(restBgA - 0.15) < 0.01,
|
|
98
|
+
hover_bg_alpha_0_20: Math.abs(hoverBgA - 0.20) < 0.01,
|
|
99
|
+
source_4_occurrences: occurrences === 4,
|
|
100
|
+
};
|
|
101
|
+
const ok = Object.values(results).every(Boolean);
|
|
102
|
+
console.log(`${ok ? '✅' : '❌'} R552 chrome active-variant hover:text-cyan-200 (4 anchors):`,
|
|
103
|
+
JSON.stringify(results, null, 2),
|
|
104
|
+
'\n rest:', JSON.stringify(rest),
|
|
105
|
+
'\n hover:', JSON.stringify(hover),
|
|
106
|
+
'\n source occurrences:', occurrences);
|
|
107
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* Round 686 — active-links chip extends from 4+ hover axes (bg/text/
|
|
2
|
+
* border swap + translate-y) to add multi-layer halo paint axis.
|
|
3
|
+
* Inline filter conditional on hoveredActiveLinks state (existing,
|
|
4
|
+
* line 1098) gates 2-layer drop-shadow at pal.legendAccent tint with
|
|
5
|
+
* 2+4 stride, alpha 80/40. 45th anchor — first active-links anchor.
|
|
6
|
+
*
|
|
7
|
+
* Source assertions:
|
|
8
|
+
* - filter chain uses pal.legendAccent at 80/40 with 2+4 stride,
|
|
9
|
+
* gated on hoveredActiveLinks && isInteractive
|
|
10
|
+
* - data-active-links-chip-halo-layers attr toggles '2' ↔ '0'
|
|
11
|
+
*
|
|
12
|
+
* Runtime assertions:
|
|
13
|
+
* - active-links chip present (renders when sessions exist)
|
|
14
|
+
* - rest halo-layers='0'
|
|
15
|
+
* - chip is interactive when flowLinks > 0 (mock messages create flows)
|
|
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'), mk('a·3')] } });
|
|
43
|
+
});
|
|
44
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
45
|
+
{ id: 'm1', from_alias: 'a·1', to_alias: 'a·2', kind: 'message', content: 'p', network_id: 'default', created_at: fresh },
|
|
46
|
+
{ id: 'm2', from_alias: 'a·2', to_alias: 'a·3', kind: 'task', content: 'p2', network_id: 'default', created_at: fresh },
|
|
47
|
+
] } }));
|
|
48
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
49
|
+
const page = await ctx.newPage();
|
|
50
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
51
|
+
await page.waitForSelector('[data-active-links-chip]', { timeout: 15000, state: 'attached' });
|
|
52
|
+
await page.waitForTimeout(300);
|
|
53
|
+
|
|
54
|
+
const runtimeState = await page.evaluate(() => {
|
|
55
|
+
const chip = document.querySelector('[data-active-links-chip]');
|
|
56
|
+
return chip ? {
|
|
57
|
+
halo_layers: chip.getAttribute('data-active-links-chip-halo-layers'),
|
|
58
|
+
interactive: chip.getAttribute('data-active-links-clickable'),
|
|
59
|
+
flow_count: chip.getAttribute('data-active-links-flow-count'),
|
|
60
|
+
} : null;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
await browser.close();
|
|
64
|
+
|
|
65
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
66
|
+
const sourceFilter = /filter: hoveredActiveLinks && isInteractive\s*\?\s*`drop-shadow\(0 0 2px \$\{pal\.legendAccent\}80\) drop-shadow\(0 0 4px \$\{pal\.legendAccent\}40\)`\s*: undefined/.test(src);
|
|
67
|
+
const sourceAttr = /data-active-links-chip-halo-layers=\{hoveredActiveLinks && isInteractive \? '2' : '0'\}/.test(src);
|
|
68
|
+
|
|
69
|
+
const results = {
|
|
70
|
+
chip_present: !!runtimeState,
|
|
71
|
+
rest_layers_zero: runtimeState?.halo_layers === '0',
|
|
72
|
+
is_interactive: runtimeState?.interactive === 'true',
|
|
73
|
+
has_flows: runtimeState && parseInt(runtimeState.flow_count, 10) >= 1,
|
|
74
|
+
source_filter: sourceFilter,
|
|
75
|
+
source_layers_attr: sourceAttr,
|
|
76
|
+
};
|
|
77
|
+
const ok = Object.values(results).every(Boolean);
|
|
78
|
+
console.log(`${ok ? '✅' : '❌'} R686 active-links chip multi-layer halo (first active-links anchor):`,
|
|
79
|
+
JSON.stringify(results, null, 2),
|
|
80
|
+
`\n runtime: ${JSON.stringify(runtimeState)}`);
|
|
81
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/* Round 616 — alias text brightness gate extends from hover-only
|
|
2
|
+
* to (hover || chat-target). 2nd anchor in chat-target-gated
|
|
3
|
+
* brightness family (sibling to R615 chat ring).
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. mock 2 idle nodes → alias text renders
|
|
7
|
+
* 2. rest (no hover, no chat): filter='none', brightness-attr='1'
|
|
8
|
+
* 3. computed transition-property contains 'filter'
|
|
9
|
+
* 4. source: filter conditional includes BOTH hover AND chat
|
|
10
|
+
* gates, joined by `||`
|
|
11
|
+
*/
|
|
12
|
+
import { chromium } from 'playwright';
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
|
|
15
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
16
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
17
|
+
|
|
18
|
+
const browser = await chromium.launch({ headless: true });
|
|
19
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
20
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
21
|
+
await ctx.addInitScript(() => {
|
|
22
|
+
try {
|
|
23
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
24
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
25
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
26
|
+
} catch {}
|
|
27
|
+
});
|
|
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: 'idle', 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: [mk('a·1'), mk('a·2')] } });
|
|
38
|
+
});
|
|
39
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
40
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
41
|
+
const page = await ctx.newPage();
|
|
42
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
43
|
+
await page.waitForSelector('[data-node-alias-text]', { timeout: 15000, state: 'attached' });
|
|
44
|
+
await page.waitForTimeout(500);
|
|
45
|
+
|
|
46
|
+
const rest = await page.evaluate(() => {
|
|
47
|
+
const el = document.querySelector('[data-node-alias-text]');
|
|
48
|
+
if (!el) return null;
|
|
49
|
+
const cs = getComputedStyle(el);
|
|
50
|
+
return {
|
|
51
|
+
filter: cs.filter,
|
|
52
|
+
transitionProperty: cs.transitionProperty,
|
|
53
|
+
brightnessAttr: el.getAttribute('data-node-alias-brightness'),
|
|
54
|
+
hoveredAttr: el.getAttribute('data-node-alias-hovered'),
|
|
55
|
+
chatTargetAttr: el.getAttribute('data-node-alias-chat-target'),
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await browser.close();
|
|
60
|
+
|
|
61
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
62
|
+
const sourceFilter = /filter: !reducedMotion && \(hoveredAlias === session\.alias \|\| chatAlias === session\.alias\)\s*\?\s*`drop-shadow\(0 0 2px \$\{status\.text\}80\) brightness\(1\.15\)`\s*:\s*undefined/.test(src);
|
|
63
|
+
const sourceAttr = /data-node-alias-brightness=\{!reducedMotion && \(hoveredAlias === session\.alias \|\| chatAlias === session\.alias\) \? '1\.15' : '1'\}/.test(src);
|
|
64
|
+
|
|
65
|
+
const results = {
|
|
66
|
+
alias_present: !!rest,
|
|
67
|
+
rest_filter_none: rest?.filter === 'none',
|
|
68
|
+
rest_brightness_1: rest?.brightnessAttr === '1',
|
|
69
|
+
rest_hovered_false: rest?.hoveredAttr === 'false',
|
|
70
|
+
rest_chat_target_false: rest?.chatTargetAttr === 'false',
|
|
71
|
+
transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
|
|
72
|
+
source_filter_or_gate: sourceFilter,
|
|
73
|
+
source_attr_or_gate: sourceAttr,
|
|
74
|
+
};
|
|
75
|
+
const ok = Object.values(results).every(Boolean);
|
|
76
|
+
console.log(`${ok ? '✅' : '❌'} R616 alias chat-target brightness (chat-gated family 2/N):`,
|
|
77
|
+
JSON.stringify(results, null, 2),
|
|
78
|
+
`\n rest: ${JSON.stringify(rest)}`);
|
|
79
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/* Round 645 — node alias text gains a SECOND drop-shadow layer at
|
|
2
|
+
* 4px blur + 0x40 alpha. Extends the chromatic-identity 2-layer
|
|
3
|
+
* halo family from rings (R642/R643/R644) to TEXT — first text-
|
|
4
|
+
* scope multi-layer halo anchor.
|
|
5
|
+
*
|
|
6
|
+
* Test phases:
|
|
7
|
+
* 1. rest: alias text halo-layers='0', no filter
|
|
8
|
+
* 2. click a·1 → chat-target gate fires → alias text halo-layers='2',
|
|
9
|
+
* computed filter has EXACTLY 2 drop-shadow substrings with
|
|
10
|
+
* status.text tint at different alphas
|
|
11
|
+
* 3. source: filter expression stacks 2 drop-shadows
|
|
12
|
+
*/
|
|
13
|
+
import { chromium } from 'playwright';
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
|
|
16
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
17
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
18
|
+
|
|
19
|
+
const browser = await chromium.launch({ headless: true });
|
|
20
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
21
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
22
|
+
await ctx.addInitScript(() => {
|
|
23
|
+
try {
|
|
24
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
25
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
26
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
27
|
+
} catch {}
|
|
28
|
+
});
|
|
29
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
30
|
+
const r = await route.fetch();
|
|
31
|
+
const b = await r.json();
|
|
32
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
33
|
+
const mk = (alias) => ({
|
|
34
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
35
|
+
network_id: nid, project_dir: null,
|
|
36
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
37
|
+
});
|
|
38
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
39
|
+
});
|
|
40
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
41
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
42
|
+
const page = await ctx.newPage();
|
|
43
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
44
|
+
await page.waitForSelector('[data-node-alias-text]', { timeout: 15000, state: 'attached' });
|
|
45
|
+
await page.waitForTimeout(500);
|
|
46
|
+
|
|
47
|
+
const restTexts = await page.evaluate(() => {
|
|
48
|
+
return Array.from(document.querySelectorAll('[data-node-alias-text]')).map(el => ({
|
|
49
|
+
layers: el.getAttribute('data-node-alias-halo-layers'),
|
|
50
|
+
glow: el.getAttribute('data-node-alias-glow'),
|
|
51
|
+
chatTarget: el.getAttribute('data-node-alias-chat-target'),
|
|
52
|
+
}));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
await page.click('[data-node="a·1"]', { force: true });
|
|
56
|
+
await page.waitForTimeout(400);
|
|
57
|
+
|
|
58
|
+
const chatState = await page.evaluate(() => {
|
|
59
|
+
return Array.from(document.querySelectorAll('[data-node-alias-text]')).map(el => {
|
|
60
|
+
const cs = getComputedStyle(el);
|
|
61
|
+
return {
|
|
62
|
+
alias: el.getAttribute('data-node-alias-text'),
|
|
63
|
+
layers: el.getAttribute('data-node-alias-halo-layers'),
|
|
64
|
+
chatTarget: el.getAttribute('data-node-alias-chat-target'),
|
|
65
|
+
filter: cs.filter,
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
await browser.close();
|
|
71
|
+
|
|
72
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
73
|
+
const sourceFilter = /`drop-shadow\(0 0 2px \$\{status\.text\}80\) drop-shadow\(0 0 4px \$\{status\.text\}40\) brightness\(1\.15\)`/.test(src);
|
|
74
|
+
const sourceLayersAttr = /data-node-alias-halo-layers=\{!reducedMotion && \(hoveredAlias === session\.alias \|\| chatAlias === session\.alias\) \? '2' : '0'\}/.test(src);
|
|
75
|
+
|
|
76
|
+
const restAllZero = restTexts.every(t => t.layers === '0');
|
|
77
|
+
const chatActive = chatState.find(c => c.alias === 'a·1');
|
|
78
|
+
const chatActiveDropShadowCount = (chatActive?.filter?.match(/drop-shadow/g) || []).length;
|
|
79
|
+
const chatIdle = chatState.find(c => c.alias === 'a·2');
|
|
80
|
+
|
|
81
|
+
const results = {
|
|
82
|
+
texts_present: restTexts.length >= 2,
|
|
83
|
+
rest_all_zero: restAllZero,
|
|
84
|
+
chat_a1_present: !!chatActive,
|
|
85
|
+
chat_a1_layers_2: chatActive?.layers === '2',
|
|
86
|
+
chat_a1_chat_target_true:chatActive?.chatTarget === 'true',
|
|
87
|
+
chat_a1_two_dropshadows: chatActiveDropShadowCount === 2,
|
|
88
|
+
chat_a1_brightness: /brightness/.test(chatActive?.filter || ''),
|
|
89
|
+
chat_a2_layers_0: chatIdle?.layers === '0',
|
|
90
|
+
source_filter: sourceFilter,
|
|
91
|
+
source_layers_attr: sourceLayersAttr,
|
|
92
|
+
};
|
|
93
|
+
const ok = Object.values(results).every(Boolean);
|
|
94
|
+
console.log(`${ok ? '✅' : '❌'} R645 node alias text multi-layer halo (text-scope chromatic identity):`,
|
|
95
|
+
JSON.stringify(results, null, 2),
|
|
96
|
+
`\n rest: ${JSON.stringify(restTexts)}`,
|
|
97
|
+
`\n chat: ${JSON.stringify(chatState)}`);
|
|
98
|
+
process.exit(ok ? 0 : 1);
|