@sleep2agi/agent-network-dashboard 0.4.6-preview.20 → 0.4.6-preview.201
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 +1 -0
- package/.next/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +41 -41
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/routes-manifest.json +6 -0
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/_not-found.rsc +12 -12
- package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
- 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 +2 -2
- package/.next/server/app/admin.rsc +14 -14
- package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
- 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/servers/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/hub/servers/route/build-manifest.json +9 -0
- package/.next/server/app/api/hub/servers/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/hub/servers/route.js +7 -0
- package/.next/server/app/api/hub/servers/route.js.map +5 -0
- package/.next/server/app/api/hub/servers/route.js.nft.json +1 -0
- package/.next/server/app/api/hub/servers/route_client-reference-manifest.js +3 -0
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +14 -14
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +14 -14
- 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 +14 -14
- package/.next/server/app/login.segments/_full.segment.rsc +14 -14
- 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 +2 -2
- package/.next/server/app/logs.rsc +14 -14
- package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
- 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/messages/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +2 -2
- package/.next/server/app/messages.rsc +14 -14
- package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
- 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 +2 -2
- package/.next/server/app/node.rsc +14 -14
- package/.next/server/app/node.segments/_full.segment.rsc +14 -14
- 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 +2 -2
- package/.next/server/app/nodes.rsc +14 -14
- package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
- 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 +2 -2
- package/.next/server/app/server-logs.rsc +14 -14
- package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
- 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 +2 -2
- package/.next/server/app/settings/networks.rsc +14 -14
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
- 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 +2 -2
- package/.next/server/app/settings/tokens.rsc +14 -14
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
- 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 +2 -2
- package/.next/server/app/settings.rsc +14 -14
- package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
- 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 +2 -2
- package/.next/server/app/tasks.rsc +14 -14
- package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
- 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 +1 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_hub_servers_route_actions_08-m-cs.js +3 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_hub_servers_route_actions_08-m-cs.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__03b.f76._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__03b.f76._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.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/agent-network-dashboard_09kk21a._.js +4 -1
- 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_057q.ne._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_057q.ne._.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_0_d45-d._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0i3759l._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0i3759l._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0xgney8._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0xgney8._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_10hjgv4._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_10hjgv4._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_1153xeb._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_1153xeb._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.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/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +2 -2
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/0-mpa_947ipeq.js +1 -0
- package/.next/static/chunks/01b6zl3rabau1.js +1 -0
- package/.next/static/chunks/01lmbsd37fybu.js +1 -0
- package/.next/static/chunks/03o.h6kvmw4l_.js +1 -0
- package/.next/static/chunks/03~~oirxz7~vc.js +1 -0
- package/.next/static/chunks/05uk96gc~9mni.js +1 -0
- package/.next/static/chunks/08kf-.bgs10ze.js +1 -0
- package/.next/static/chunks/0fzk-axksemic.css +2 -0
- package/.next/static/chunks/0ggj5ummw2a84.js +7 -0
- package/.next/static/chunks/0glmrdj9112tc.js +7 -0
- package/.next/static/chunks/0n7ow3nu-_bsk.js +4 -0
- package/.next/static/chunks/0rxrez_cjn.eh.js +1 -0
- package/.next/static/chunks/0x8x.29hkju5a.js +1 -0
- package/.next/static/chunks/0zx.24yobat5o.js +1 -0
- package/.next/static/chunks/174re5ar~kxne.js +1 -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/servers/route.ts +39 -0
- package/app/components/ChatPopover.tsx +38 -2
- package/app/components/CommandPalette.tsx +107 -0
- package/app/components/HelpOverlay.tsx +126 -0
- package/app/components/ServersDrawer.tsx +64 -27
- package/app/components/TopoGraph.tsx +3984 -264
- package/app/components/utils.ts +8 -7
- package/app/globals.css +110 -5
- package/app/lib/time.ts +36 -0
- package/package.json +1 -1
- package/scripts/help-overlay-topo-test.mjs +44 -0
- package/scripts/servers-drawer-live-test.mjs +96 -0
- package/scripts/topo-active-filter-pill-test.mjs +101 -0
- package/scripts/topo-active-links-chip-hover-test.mjs +103 -0
- package/scripts/topo-active-links-chip-nav-test.mjs +117 -0
- package/scripts/topo-active-links-chip-self-hover-test.mjs +171 -0
- package/scripts/topo-active-links-chip-test.mjs +73 -0
- package/scripts/topo-active-links-freshness-test.mjs +113 -0
- package/scripts/topo-active-links-tooltip-test.mjs +79 -0
- package/scripts/topo-arrival-ping-test.mjs +87 -0
- package/scripts/topo-arrow-tier-test.mjs +61 -0
- package/scripts/topo-auto-fit-test.mjs +73 -0
- package/scripts/topo-canvas-aria-test.mjs +108 -0
- package/scripts/topo-chat-target-breath-test.mjs +84 -0
- package/scripts/topo-chat-target-ring-fade-test.mjs +124 -0
- package/scripts/topo-chip-focus-test.mjs +95 -0
- package/scripts/topo-chip-pin-mirror-test.mjs +113 -0
- package/scripts/topo-chrome-a11y-test.mjs +107 -0
- package/scripts/topo-chrome-zoom-level-pop-test.mjs +122 -0
- package/scripts/topo-chrome-zoom-pop-test.mjs +130 -0
- package/scripts/topo-click-ripple-test.mjs +66 -0
- package/scripts/topo-cmdk-edge-clear-test.mjs +109 -0
- package/scripts/topo-cmdk-layout-view-test.mjs +108 -0
- package/scripts/topo-cmdk-pin-test.mjs +123 -0
- package/scripts/topo-cmdk-vendor-clear-test.mjs +133 -0
- package/scripts/topo-cmdk-vendor-pin-test.mjs +103 -0
- package/scripts/topo-cwd-tooltip-test.mjs +64 -0
- package/scripts/topo-dblclick-reset-test.mjs +74 -0
- package/scripts/topo-discrete-zoom-smooth-test.mjs +125 -0
- package/scripts/topo-dispatch-pulse-test.mjs +83 -0
- package/scripts/topo-edge-badge-click-pin-test.mjs +94 -0
- package/scripts/topo-edge-badge-hot-test.mjs +115 -0
- package/scripts/topo-edge-badge-hover-test.mjs +85 -0
- package/scripts/topo-edge-badge-lift-test.mjs +150 -0
- package/scripts/topo-edge-badge-ripple-test.mjs +111 -0
- package/scripts/topo-edge-badge-stroke-transition-test.mjs +118 -0
- package/scripts/topo-edge-count-badge-test.mjs +86 -0
- package/scripts/topo-edge-endpoint-highlight-test.mjs +111 -0
- package/scripts/topo-edge-fadein-test.mjs +106 -0
- package/scripts/topo-edge-focus-test.mjs +113 -0
- package/scripts/topo-edge-hover-test.mjs +93 -0
- package/scripts/topo-edge-pill-hot-test.mjs +129 -0
- package/scripts/topo-edge-pill-test.mjs +105 -0
- package/scripts/topo-edge-stroke-transition-test.mjs +132 -0
- package/scripts/topo-edge-tooltip-test.mjs +70 -0
- package/scripts/topo-endpoint-ring-fade-test.mjs +132 -0
- package/scripts/topo-endpoint-ring-test.mjs +93 -0
- package/scripts/topo-esc-clears-pin-test.mjs +98 -0
- package/scripts/topo-filter-pill-aliases-test.mjs +121 -0
- package/scripts/topo-filter-pill-body-click-test.mjs +112 -0
- package/scripts/topo-filter-pill-count-test.mjs +110 -0
- package/scripts/topo-filter-pill-mobile-test.mjs +90 -0
- package/scripts/topo-fit-key-test.mjs +106 -0
- package/scripts/topo-freshness-chip-test.mjs +74 -0
- package/scripts/topo-freshness-chip-transition-test.mjs +80 -0
- package/scripts/topo-fullscreen-active-test.mjs +115 -0
- package/scripts/topo-group-box-pinned-state-test.mjs +95 -0
- package/scripts/topo-group-count-test.mjs +68 -0
- package/scripts/topo-group-hover-test.mjs +82 -0
- package/scripts/topo-group-label-a11y-test.mjs +113 -0
- package/scripts/topo-group-label-hover-test.mjs +119 -0
- package/scripts/topo-group-label-tint-test.mjs +99 -0
- package/scripts/topo-group-label-title-test.mjs +83 -0
- package/scripts/topo-group-pin-test.mjs +119 -0
- package/scripts/topo-group-status-pips-test.mjs +103 -0
- package/scripts/topo-groupbox-fadein-test.mjs +95 -0
- package/scripts/topo-groupbox-hover-lift-test.mjs +127 -0
- package/scripts/topo-groupbox-live-test.mjs +100 -0
- package/scripts/topo-groupbox-march-busyness-test.mjs +155 -0
- package/scripts/topo-groupbox-test.mjs +4 -2
- package/scripts/topo-help-overlay-r109-test.mjs +67 -0
- package/scripts/topo-help-overlay-r118-test.mjs +69 -0
- package/scripts/topo-help-overlay-r123-test.mjs +69 -0
- package/scripts/topo-help-overlay-r134-test.mjs +74 -0
- package/scripts/topo-help-overlay-r137-test.mjs +81 -0
- package/scripts/topo-help-overlay-r141-test.mjs +86 -0
- package/scripts/topo-help-overlay-r153-test.mjs +85 -0
- package/scripts/topo-help-overlay-r59-test.mjs +67 -0
- package/scripts/topo-help-overlay-r65-test.mjs +64 -0
- package/scripts/topo-help-overlay-r70-test.mjs +63 -0
- package/scripts/topo-help-overlay-r78-test.mjs +59 -0
- package/scripts/topo-help-overlay-r81-test.mjs +58 -0
- package/scripts/topo-help-overlay-r87-test.mjs +64 -0
- package/scripts/topo-help-overlay-r91-test.mjs +65 -0
- package/scripts/topo-hub-a11y-test.mjs +112 -0
- package/scripts/topo-hub-busyness-test.mjs +100 -0
- package/scripts/topo-hub-click-fit-test.mjs +137 -0
- package/scripts/topo-hub-fadein-test.mjs +88 -0
- package/scripts/topo-hub-hover-lift-test.mjs +101 -0
- package/scripts/topo-hub-hover-ring-test.mjs +82 -0
- package/scripts/topo-hub-title-test.mjs +93 -0
- package/scripts/topo-hub-working-count-test.mjs +99 -0
- package/scripts/topo-ingroup-edge-test.mjs +103 -0
- package/scripts/topo-label-lift-test.mjs +119 -0
- package/scripts/topo-label-scale-test.mjs +78 -0
- package/scripts/topo-lastseen-tooltip-test.mjs +59 -0
- package/scripts/topo-layout-key-test.mjs +91 -0
- package/scripts/topo-layout-switch-crossfade-test.mjs +126 -0
- package/scripts/topo-layout-toggle-test.mjs +131 -0
- package/scripts/topo-legend-count-test.mjs +88 -0
- package/scripts/topo-legend-hover-test.mjs +113 -0
- package/scripts/topo-legend-panel-header-test.mjs +83 -0
- package/scripts/topo-legend-pin-ring-fade-test.mjs +112 -0
- package/scripts/topo-legend-pin-test.mjs +128 -0
- package/scripts/topo-legend-row-hover-lift-test.mjs +109 -0
- package/scripts/topo-legend-row-tint-test.mjs +95 -0
- package/scripts/topo-legend-row-title-test.mjs +102 -0
- package/scripts/topo-minimap-a11y-test.mjs +101 -0
- package/scripts/topo-minimap-test.mjs +68 -0
- package/scripts/topo-mobile-chips-test.mjs +103 -0
- package/scripts/topo-node-a11y-test.mjs +107 -0
- package/scripts/topo-node-hover-lift-test.mjs +85 -0
- package/scripts/topo-node-label-card-elevation-test.mjs +157 -0
- package/scripts/topo-node-stroke-transition-test.mjs +103 -0
- package/scripts/topo-node-title-peers-test.mjs +107 -0
- package/scripts/topo-node-title-test.mjs +101 -0
- package/scripts/topo-nodesize-active-hover-test.mjs +109 -0
- package/scripts/topo-nodesize-crossfade-test.mjs +141 -0
- package/scripts/topo-offline-dim-test.mjs +70 -0
- package/scripts/topo-online-chip-nav-test.mjs +143 -0
- package/scripts/topo-orbit-busyness-test.mjs +96 -0
- package/scripts/topo-overlap-test.mjs +32 -5
- package/scripts/topo-pan-cursor-test.mjs +62 -0
- package/scripts/topo-panel-elevation-test.mjs +76 -0
- package/scripts/topo-panel-fadein-test.mjs +102 -0
- package/scripts/topo-panel-hot-tail-fade-test.mjs +124 -0
- package/scripts/topo-panel-hover-elevation-test.mjs +118 -0
- package/scripts/topo-particle-stagger-test.mjs +82 -0
- package/scripts/topo-pin-intersection-empty-test.mjs +129 -0
- package/scripts/topo-pin-intersection-test.mjs +121 -0
- package/scripts/topo-pin-mirror-transition-test.mjs +101 -0
- package/scripts/topo-pin-persistence-test.mjs +105 -0
- package/scripts/topo-popover-meta-test.mjs +78 -0
- package/scripts/topo-pressure-bar-test.mjs +69 -0
- package/scripts/topo-pressure-hover-test.mjs +123 -0
- package/scripts/topo-pressure-pin-test.mjs +119 -0
- package/scripts/topo-pressure-seg-tooltip-test.mjs +98 -0
- package/scripts/topo-pressure-seg-transition-test.mjs +107 -0
- package/scripts/topo-pulse-rate-test.mjs +71 -0
- package/scripts/topo-recent-panel-count-freshness-test.mjs +109 -0
- package/scripts/topo-recent-panel-count-test.mjs +72 -0
- package/scripts/topo-recent-panel-hot-header-test.mjs +132 -0
- package/scripts/topo-recent-panel-more-nav-test.mjs +127 -0
- package/scripts/topo-recent-panel-more-test.mjs +106 -0
- package/scripts/topo-recent-row-count-fill-test.mjs +129 -0
- package/scripts/topo-recent-row-freshness-test.mjs +102 -0
- package/scripts/topo-recent-row-hot-test.mjs +110 -0
- package/scripts/topo-recent-row-hover-lift-test.mjs +128 -0
- package/scripts/topo-recent-row-hover-test.mjs +122 -0
- package/scripts/topo-recent-row-pin-test.mjs +126 -0
- package/scripts/topo-recent-row-tint-test.mjs +91 -0
- package/scripts/topo-recent-row-title-test.mjs +112 -0
- package/scripts/topo-recent-row-ts-alpha-test.mjs +100 -0
- package/scripts/topo-recent-row-ts-test.mjs +95 -0
- package/scripts/topo-recent-row-typography-test.mjs +119 -0
- package/scripts/topo-recent-signal-empty-hint-test.mjs +73 -0
- package/scripts/topo-recent-signal-empty-test.mjs +63 -0
- package/scripts/topo-reduced-motion-test.mjs +77 -0
- package/scripts/topo-reset-spin-test.mjs +120 -0
- package/scripts/topo-spoke-busyness-test.mjs +110 -0
- package/scripts/topo-status-chip-hover-test.mjs +101 -0
- package/scripts/topo-status-chip-tooltip-test.mjs +95 -0
- package/scripts/topo-svg-focus-test.mjs +112 -0
- package/scripts/topo-sweep-busyness-test.mjs +94 -0
- package/scripts/topo-tier-ring-fadein-test.mjs +107 -0
- package/scripts/topo-tier-ring-occupancy-test.mjs +87 -0
- package/scripts/topo-tier-ring-test.mjs +69 -0
- package/scripts/topo-tier-ring-tint-test.mjs +110 -0
- package/scripts/topo-tier-stagger-test.mjs +89 -0
- package/scripts/topo-tz-ghost-test.mjs +69 -0
- package/scripts/topo-vendor-chip-hover-test.mjs +111 -0
- package/scripts/topo-vendor-letter-tooltip-test.mjs +92 -0
- package/scripts/topo-vendor-pill-test.mjs +125 -0
- package/scripts/topo-vendor-pin-test.mjs +125 -0
- package/scripts/topo-view-smooth-test.mjs +131 -0
- package/scripts/topo-wheel-zoom-test.mjs +79 -0
- package/scripts/topo-working-chip-pin-test.mjs +154 -0
- package/scripts/topo-working-halo-breath-test.mjs +86 -0
- package/scripts/topo-zoom-keys-test.mjs +89 -0
- package/.next/static/chunks/0-7iowzu4.798.js +0 -1
- package/.next/static/chunks/02t5jr4shh.hy.js +0 -1
- package/.next/static/chunks/076u9wjiilxzg.js +0 -1
- package/.next/static/chunks/07hlou5cndq1b.js +0 -1
- package/.next/static/chunks/09nd.t_hd.y6t.css +0 -2
- package/.next/static/chunks/0_qfg5s5uzs7..js +0 -7
- package/.next/static/chunks/0elalb9n_.~di.js +0 -1
- package/.next/static/chunks/0fqy_0wj_1xa7.js +0 -7
- package/.next/static/chunks/0j_q__o8p6g83.js +0 -1
- package/.next/static/chunks/0jl6_w50zh4l5.js +0 -1
- package/.next/static/chunks/0lw~4lr23sl-r.js +0 -1
- package/.next/static/chunks/0r4q73.-1bkyl.js +0 -1
- package/.next/static/chunks/0r_c8eccg3z2o.js +0 -1
- package/.next/static/chunks/10oi7l-tycgl9.js +0 -1
- package/.next/static/chunks/11uk1izuv3~0t.js +0 -1
- /package/.next/static/{kZOwEPGbIfBUUE4MFGvHz → IZ83xXmRRznWkvPwyxx-z}/_buildManifest.js +0 -0
- /package/.next/static/{kZOwEPGbIfBUUE4MFGvHz → IZ83xXmRRznWkvPwyxx-z}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{kZOwEPGbIfBUUE4MFGvHz → IZ83xXmRRznWkvPwyxx-z}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/* Round 162 verification: recent-signal panel header "N flows"
|
|
2
|
+
* tspan picks up the R160/R161 freshness vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* R10 fades canvas edge by freshness (per-edge stroke opacity)
|
|
5
|
+
* R160 brought it to the recent-signal panel rows (per-flow pip)
|
|
6
|
+
* R161 brought it to the chip-row "active links" chip bullet
|
|
7
|
+
* (fleet aggregate in the chip-row above the SVG)
|
|
8
|
+
* R162 brings it to the recent-signal panel HEADER count
|
|
9
|
+
* (fleet aggregate inside the SVG corner)
|
|
10
|
+
*
|
|
11
|
+
* The chip-row "N active links · last 5s" and the panel-header
|
|
12
|
+
* "N flows" show the same metric at two scopes. R161 tinted the
|
|
13
|
+
* chip-row side; R162 tints the panel-side mirror so both
|
|
14
|
+
* scopes speak the same freshness vocabulary side-by-side.
|
|
15
|
+
*
|
|
16
|
+
* Same alpha ramp as R160/R161:
|
|
17
|
+
* ageSec ≤ 30 → 1.0 (fully fresh)
|
|
18
|
+
* 30-300s → smooth decay 1.0 → 0.25
|
|
19
|
+
* > 300s → 0.25 stale floor
|
|
20
|
+
*
|
|
21
|
+
* Hot tail (R129 amber " · N hot") is volume-tinted and stays
|
|
22
|
+
* unchanged — recency tints the head; volume colors the tail.
|
|
23
|
+
*
|
|
24
|
+
* Test: 3 page loads, 5s / 90s / 360s ago.
|
|
25
|
+
*/
|
|
26
|
+
import { chromium } from 'playwright';
|
|
27
|
+
import { readFileSync } from 'node:fs';
|
|
28
|
+
|
|
29
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
30
|
+
const browser = await chromium.launch({ headless: true });
|
|
31
|
+
|
|
32
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
33
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
34
|
+
await ctx.addInitScript(() => {
|
|
35
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
async function probe(msgAgeSec) {
|
|
39
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
40
|
+
await ctx.unroute('**/api/hub/status*').catch(() => {});
|
|
41
|
+
await ctx.unroute('**/api/hub/messages*').catch(() => {});
|
|
42
|
+
await ctx.unroute('**/api/hub/tasks*').catch(() => {});
|
|
43
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
44
|
+
const r = await route.fetch();
|
|
45
|
+
const b = await r.json();
|
|
46
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
47
|
+
const mk = (alias) => ({
|
|
48
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
49
|
+
network_id: nid, project_dir: null,
|
|
50
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
51
|
+
});
|
|
52
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('alpha'), mk('beta')] } });
|
|
53
|
+
});
|
|
54
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [
|
|
55
|
+
{ id: 'x', from_alias: 'alpha', to_alias: 'beta', content: 'hi',
|
|
56
|
+
network_id: 'default', created_at: new Date(Date.now() - msgAgeSec * 1000).toISOString() },
|
|
57
|
+
] } }));
|
|
58
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
59
|
+
|
|
60
|
+
const page = await ctx.newPage();
|
|
61
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
62
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 2, { timeout: 30000 });
|
|
63
|
+
await page.waitForSelector('[data-recent-panel-count]', { timeout: 10000 });
|
|
64
|
+
await page.waitForTimeout(400);
|
|
65
|
+
const out = await page.evaluate(() => {
|
|
66
|
+
const el = document.querySelector('[data-recent-panel-count]');
|
|
67
|
+
if (!el) return null;
|
|
68
|
+
// SVG tspan fill attribute is the source of truth — getComputedStyle on
|
|
69
|
+
// tspan returns nothing useful on some browsers.
|
|
70
|
+
return {
|
|
71
|
+
alpha: parseFloat(el.getAttribute('data-recent-panel-count-freshness-alpha') || ''),
|
|
72
|
+
fill: el.getAttribute('fill') || '',
|
|
73
|
+
text: el.textContent,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
await page.close();
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const A = await probe(5); // fresh
|
|
81
|
+
const B = await probe(90); // mid
|
|
82
|
+
const C = await probe(360); // stale
|
|
83
|
+
|
|
84
|
+
await browser.close();
|
|
85
|
+
|
|
86
|
+
const cyanRgb = (str) => {
|
|
87
|
+
const m = /rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(str);
|
|
88
|
+
if (!m) return null;
|
|
89
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const results = {
|
|
93
|
+
fresh_dot_found: A !== null,
|
|
94
|
+
mid_dot_found: B !== null,
|
|
95
|
+
stale_dot_found: C !== null,
|
|
96
|
+
fresh_alpha_1: A && Math.abs(A.alpha - 1.0) < 0.05,
|
|
97
|
+
mid_alpha_window: B && B.alpha > 0.7 && B.alpha < 0.95,
|
|
98
|
+
stale_alpha_floor: C && Math.abs(C.alpha - 0.25) < 0.05,
|
|
99
|
+
fresh_color_cyan: A && JSON.stringify(cyanRgb(A.fill)) === '[34,211,238]',
|
|
100
|
+
stale_alpha_in_fill: C && /0\.25/.test(C.fill),
|
|
101
|
+
ladder_descends: A && B && C && A.alpha > B.alpha && B.alpha > C.alpha,
|
|
102
|
+
text_says_1_flow: A && /1 flow/.test(A.text || ''),
|
|
103
|
+
};
|
|
104
|
+
const ok = Object.values(results).every(Boolean);
|
|
105
|
+
console.log(`${ok ? '✅' : '❌'} panel-header count freshness:`, JSON.stringify(results),
|
|
106
|
+
`\n fresh =`, A,
|
|
107
|
+
`\n mid =`, B,
|
|
108
|
+
`\n stale =`, C);
|
|
109
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/* Round 96 verification: the recent-signal panel header count now
|
|
2
|
+
* reads "X flows" off flowLinks.length (matching the deduped rows
|
|
3
|
+
* below), not "X msgs" off the raw messages.length. Pre-R96 a
|
|
4
|
+
* fleet with 10 messages aggregating to 3 unique pairs read
|
|
5
|
+
* "10 msgs" above only 3 rendered rows — read as broken.
|
|
6
|
+
*
|
|
7
|
+
* Mock 5 messages between 2 distinct pairs: alpha↔beta gets 4
|
|
8
|
+
* msgs (4 separate exchanges, dedupes to 1 flow), gamma→delta
|
|
9
|
+
* gets 1 msg (1 flow). Total = 5 msgs, 2 flows. Header should
|
|
10
|
+
* show "2 flows", panel renders 2 rows.
|
|
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 browser = await chromium.launch({ headless: true });
|
|
17
|
+
|
|
18
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
19
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
20
|
+
await ctx.addInitScript(() => {
|
|
21
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
25
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
26
|
+
const r = await route.fetch();
|
|
27
|
+
const b = await r.json();
|
|
28
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
29
|
+
const mk = (alias) => ({
|
|
30
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
31
|
+
network_id: nid, project_dir: null,
|
|
32
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
33
|
+
});
|
|
34
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('alpha'), mk('beta'), mk('gamma'), mk('delta')] } });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const now = Date.now();
|
|
38
|
+
const mkMsg = (id, from_alias, to_alias, content, ageMs) => ({
|
|
39
|
+
id, from_alias, to_alias, content, network_id: 'default',
|
|
40
|
+
created_at: new Date(now - ageMs).toISOString(),
|
|
41
|
+
});
|
|
42
|
+
// 5 messages → 2 flow pairs (alpha→beta × 4, gamma→delta × 1).
|
|
43
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [
|
|
44
|
+
mkMsg('m1', 'alpha', 'beta', 'ping-1', 60 * 1000),
|
|
45
|
+
mkMsg('m2', 'alpha', 'beta', 'ping-2', 50 * 1000),
|
|
46
|
+
mkMsg('m3', 'alpha', 'beta', 'ping-3', 40 * 1000),
|
|
47
|
+
mkMsg('m4', 'alpha', 'beta', 'ping-4', 30 * 1000),
|
|
48
|
+
mkMsg('m5', 'gamma', 'delta', 'hello', 20 * 1000),
|
|
49
|
+
] } }));
|
|
50
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
51
|
+
const page = await ctx.newPage();
|
|
52
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
53
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
|
|
54
|
+
await page.waitForSelector('[data-recent-panel-count]', { timeout: 10000 });
|
|
55
|
+
await page.waitForTimeout(400);
|
|
56
|
+
|
|
57
|
+
const headerCount = await page.locator('[data-recent-panel-count]').textContent();
|
|
58
|
+
const renderedRows = await page.locator('[data-recent-row]').count();
|
|
59
|
+
|
|
60
|
+
await browser.close();
|
|
61
|
+
|
|
62
|
+
const results = {
|
|
63
|
+
header_saysFlowsNotMsgs: /\bflows\b/.test(headerCount || ''),
|
|
64
|
+
header_count2: /^2 flows/.test(headerCount || ''),
|
|
65
|
+
rows_match_header: renderedRows === 2,
|
|
66
|
+
no_msgs_word: !/\bmsgs?\b/.test(headerCount || ''),
|
|
67
|
+
};
|
|
68
|
+
const ok = Object.values(results).every(Boolean);
|
|
69
|
+
console.log(`${ok ? '✅' : '❌'} recent-panel count:`, JSON.stringify(results),
|
|
70
|
+
`\n header=`, JSON.stringify(headerCount),
|
|
71
|
+
`\n rows=`, renderedRows);
|
|
72
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/* Round 129 verification: recent-signal panel header gains a
|
|
2
|
+
* " · N hot" amber tail when ≥ 1 flowLink has count ≥ 10.
|
|
3
|
+
*
|
|
4
|
+
* The hot-lane convention's surfaces:
|
|
5
|
+
* R126: canvas midpoint count badge → amber stroke
|
|
6
|
+
* R127: recent-signal row count digit → amber + bold
|
|
7
|
+
* R129: recent-signal panel HEADER → " · N hot" amber suffix
|
|
8
|
+
*
|
|
9
|
+
* Vertical scan path now reads: header → rows → canvas. Each layer
|
|
10
|
+
* answers a different scope: header = "how many hot?", rows =
|
|
11
|
+
* "which ones?", canvas = "where on the topology?".
|
|
12
|
+
*
|
|
13
|
+
* Three states:
|
|
14
|
+
* A. 3 pairs, all count < 10 → header "3 flows", no hot tail
|
|
15
|
+
* B. 5 pairs, 2 of them count ≥ 10 → header "5 flows · 2 hot", amber tail
|
|
16
|
+
* C. 5 pairs, 5 of them count ≥ 10 → header "5 flows · 5 hot"
|
|
17
|
+
*/
|
|
18
|
+
import { chromium } from 'playwright';
|
|
19
|
+
import { readFileSync } from 'node:fs';
|
|
20
|
+
|
|
21
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
22
|
+
|
|
23
|
+
async function probe(seedPairs) {
|
|
24
|
+
// seedPairs is an array of [from, to, count] tuples — each pair gets
|
|
25
|
+
// `count` msgs to make link.count == count after dedup.
|
|
26
|
+
const browser = await chromium.launch({ headless: true });
|
|
27
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
28
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
29
|
+
await ctx.addInitScript(() => {
|
|
30
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
34
|
+
const aliasSet = new Set();
|
|
35
|
+
for (const [a, b] of seedPairs) { aliasSet.add(a); aliasSet.add(b); }
|
|
36
|
+
const aliases = [...aliasSet];
|
|
37
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
38
|
+
const r = await route.fetch();
|
|
39
|
+
const b = await r.json();
|
|
40
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
41
|
+
const mk = (alias) => ({
|
|
42
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
43
|
+
network_id: nid, project_dir: null,
|
|
44
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
45
|
+
});
|
|
46
|
+
await route.fulfill({ response: r, json: { ...b, sessions: aliases.map(mk) } });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const now = Date.now();
|
|
50
|
+
const msgs = [];
|
|
51
|
+
let id = 0;
|
|
52
|
+
for (const [from, to, count] of seedPairs) {
|
|
53
|
+
for (let i = 0; i < count; i++) {
|
|
54
|
+
msgs.push({
|
|
55
|
+
id: `m${id++}`,
|
|
56
|
+
from_alias: from,
|
|
57
|
+
to_alias: to,
|
|
58
|
+
content: 'hi',
|
|
59
|
+
network_id: 'default',
|
|
60
|
+
created_at: new Date(now - (20000 + i * 500 + id * 13)).toISOString(),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: msgs } }));
|
|
65
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
66
|
+
|
|
67
|
+
const page = await ctx.newPage();
|
|
68
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
69
|
+
await page.waitForFunction((n) => document.querySelectorAll('g[data-node]').length === n, aliases.length, { timeout: 30000 });
|
|
70
|
+
await page.waitForTimeout(500);
|
|
71
|
+
|
|
72
|
+
const out = await page.evaluate(() => {
|
|
73
|
+
const count = document.querySelector('[data-recent-panel-count]');
|
|
74
|
+
const hot = document.querySelector('[data-recent-panel-hot-count]');
|
|
75
|
+
return {
|
|
76
|
+
countText: count?.textContent,
|
|
77
|
+
hotText: hot?.textContent,
|
|
78
|
+
hotAttr: hot?.getAttribute('data-recent-panel-hot-count'),
|
|
79
|
+
hotFill: hot?.getAttribute('fill'),
|
|
80
|
+
hotWeight: hot?.getAttribute('font-weight'),
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
await browser.close();
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// State A: all warm
|
|
89
|
+
const a = await probe([
|
|
90
|
+
['alpha', 'beta', 4],
|
|
91
|
+
['gamma', 'delta', 5],
|
|
92
|
+
['epsilon', 'zeta', 3],
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
// State B: 5 pairs, 2 hot (≥ 10)
|
|
96
|
+
const b = await probe([
|
|
97
|
+
['alpha', 'beta', 12], // hot
|
|
98
|
+
['gamma', 'delta', 15], // hot
|
|
99
|
+
['epsilon', 'zeta', 4],
|
|
100
|
+
['eta', 'theta', 6],
|
|
101
|
+
['iota', 'kappa', 8],
|
|
102
|
+
]);
|
|
103
|
+
|
|
104
|
+
// State C: 5 pairs, all 5 hot
|
|
105
|
+
const c = await probe([
|
|
106
|
+
['alpha', 'beta', 12],
|
|
107
|
+
['gamma', 'delta', 11],
|
|
108
|
+
['epsilon', 'zeta', 14],
|
|
109
|
+
['eta', 'theta', 13],
|
|
110
|
+
['iota', 'kappa', 25],
|
|
111
|
+
]);
|
|
112
|
+
|
|
113
|
+
const amber = '#fbbf24';
|
|
114
|
+
|
|
115
|
+
const results = {
|
|
116
|
+
a_count_3flows: a.countText === '3 flows',
|
|
117
|
+
a_noHotTspan: a.hotText === undefined,
|
|
118
|
+
|
|
119
|
+
b_count_5flows: b.countText === '5 flows',
|
|
120
|
+
b_hot_text: b.hotText === ' · 2 hot',
|
|
121
|
+
b_hot_attr: b.hotAttr === '2',
|
|
122
|
+
b_hot_amberFill: (b.hotFill || '').toLowerCase() === amber,
|
|
123
|
+
b_hot_boldWeight: b.hotWeight === '700',
|
|
124
|
+
|
|
125
|
+
c_count_5flows: c.countText === '5 flows',
|
|
126
|
+
c_hot_text: c.hotText === ' · 5 hot',
|
|
127
|
+
c_hot_attr: c.hotAttr === '5',
|
|
128
|
+
};
|
|
129
|
+
const ok = Object.values(results).every(Boolean);
|
|
130
|
+
console.log(`${ok ? '✅' : '❌'} recent-panel hot header:`, JSON.stringify(results),
|
|
131
|
+
`\n A=`, a, `\n B=`, b, `\n C=`, c);
|
|
132
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/* Round 133 verification: R128's "+N more flows" footer becomes a
|
|
2
|
+
* clickable nav to /messages. R128 introduced the truncation hint
|
|
3
|
+
* as pure metadata; R133 lets the user act on it.
|
|
4
|
+
*
|
|
5
|
+
* Three states tested:
|
|
6
|
+
* A. Click footer → navigation lands on /messages
|
|
7
|
+
* B. Hover footer → opacity rises 0.55 → 0.85, underline appears
|
|
8
|
+
* C. Leave hover → opacity drops back, underline gone
|
|
9
|
+
*
|
|
10
|
+
* Plus: footer carries role="link" + cursor:pointer + a tooltip
|
|
11
|
+
* referencing /messages, all for discoverability and a11y.
|
|
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 browser = await chromium.launch({ headless: true });
|
|
18
|
+
|
|
19
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
20
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
21
|
+
await ctx.addInitScript(() => {
|
|
22
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
26
|
+
const aliases = ['alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta'];
|
|
27
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
28
|
+
const r = await route.fetch();
|
|
29
|
+
const b = await r.json();
|
|
30
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
31
|
+
const mk = (alias) => ({
|
|
32
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
33
|
+
network_id: nid, project_dir: null,
|
|
34
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
35
|
+
});
|
|
36
|
+
await route.fulfill({ response: r, json: { ...b, sessions: aliases.map(mk) } });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
const msgs = [];
|
|
41
|
+
// 5 distinct pairs → forces R128 footer with "+ 2 more flows"
|
|
42
|
+
for (let i = 0; i < 5; i++) {
|
|
43
|
+
msgs.push({
|
|
44
|
+
id: `m${i}`,
|
|
45
|
+
from_alias: aliases[i],
|
|
46
|
+
to_alias: aliases[(i + 1) % aliases.length],
|
|
47
|
+
content: 'hi',
|
|
48
|
+
network_id: 'default',
|
|
49
|
+
created_at: new Date(now - (20000 + i * 1000)).toISOString(),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: msgs } }));
|
|
53
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
54
|
+
|
|
55
|
+
const page = await ctx.newPage();
|
|
56
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
57
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 6, { timeout: 30000 });
|
|
58
|
+
await page.waitForSelector('[data-recent-panel-more-nav]', { timeout: 10000 });
|
|
59
|
+
await page.waitForTimeout(400);
|
|
60
|
+
|
|
61
|
+
const beforeHover = await page.evaluate(() => {
|
|
62
|
+
const wrap = document.querySelector('[data-recent-panel-more-nav]');
|
|
63
|
+
const text = wrap?.querySelector('text[data-recent-panel-more]');
|
|
64
|
+
return {
|
|
65
|
+
role: wrap?.getAttribute('role'),
|
|
66
|
+
tabindex: wrap?.getAttribute('tabindex'),
|
|
67
|
+
cursor: (wrap?.getAttribute('style') || '').includes('pointer'),
|
|
68
|
+
title: wrap?.querySelector('title')?.textContent,
|
|
69
|
+
opacity: text?.getAttribute('opacity'),
|
|
70
|
+
underline: text?.getAttribute('text-decoration'),
|
|
71
|
+
moreCount: text?.getAttribute('data-recent-panel-more'),
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Hover the footer
|
|
76
|
+
await page.locator('[data-recent-panel-more-nav]').hover();
|
|
77
|
+
await page.waitForTimeout(250);
|
|
78
|
+
const onHover = await page.evaluate(() => {
|
|
79
|
+
const text = document.querySelector('[data-recent-panel-more-nav] text');
|
|
80
|
+
return {
|
|
81
|
+
opacity: text?.getAttribute('opacity'),
|
|
82
|
+
underline: text?.getAttribute('text-decoration'),
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Move away → restore
|
|
87
|
+
await page.mouse.move(10, 10);
|
|
88
|
+
await page.waitForTimeout(250);
|
|
89
|
+
const afterLeave = await page.evaluate(() => {
|
|
90
|
+
const text = document.querySelector('[data-recent-panel-more-nav] text');
|
|
91
|
+
return {
|
|
92
|
+
opacity: text?.getAttribute('opacity'),
|
|
93
|
+
underline: text?.getAttribute('text-decoration'),
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Click → expect /messages navigation
|
|
98
|
+
await page.locator('[data-recent-panel-more-nav]').click();
|
|
99
|
+
await page.waitForURL('**/messages', { timeout: 10000 });
|
|
100
|
+
const finalUrl = page.url();
|
|
101
|
+
|
|
102
|
+
await browser.close();
|
|
103
|
+
|
|
104
|
+
const results = {
|
|
105
|
+
before_roleLink: beforeHover.role === 'link',
|
|
106
|
+
before_tabIndex0: beforeHover.tabindex === '0',
|
|
107
|
+
before_cursorPointer: beforeHover.cursor,
|
|
108
|
+
before_titleMentionsMessages: (beforeHover.title || '').includes('/messages'),
|
|
109
|
+
before_moreCount2: beforeHover.moreCount === '2',
|
|
110
|
+
before_opacity55: beforeHover.opacity === '0.55',
|
|
111
|
+
before_noUnderline: beforeHover.underline === 'none' || !beforeHover.underline,
|
|
112
|
+
|
|
113
|
+
hover_opacity85: onHover.opacity === '0.85',
|
|
114
|
+
hover_underline: onHover.underline === 'underline',
|
|
115
|
+
|
|
116
|
+
leave_opacityRestored: afterLeave.opacity === '0.55',
|
|
117
|
+
leave_underlineGone: afterLeave.underline === 'none' || !afterLeave.underline,
|
|
118
|
+
|
|
119
|
+
click_navigatedToMessages: /\/messages$/.test(finalUrl),
|
|
120
|
+
};
|
|
121
|
+
const ok = Object.values(results).every(Boolean);
|
|
122
|
+
console.log(`${ok ? '✅' : '❌'} recent-panel more nav:`, JSON.stringify(results),
|
|
123
|
+
`\n before=`, beforeHover,
|
|
124
|
+
`\n onHover=`, onHover,
|
|
125
|
+
`\n afterLeave=`, afterLeave,
|
|
126
|
+
`\n finalUrl=`, finalUrl);
|
|
127
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/* Round 128 verification: "+N more flows" overflow hint in the
|
|
2
|
+
* recent-signal panel.
|
|
3
|
+
*
|
|
4
|
+
* The panel renders top 3 flowLinks via .slice(0, 3). When the
|
|
5
|
+
* fleet has > 3 active flows, the rest silently disappear — the
|
|
6
|
+
* R96 "X flows" header reports the total but doesn't make
|
|
7
|
+
* truncation explicit. R128 adds a muted italic footer
|
|
8
|
+
* "+ N more flow(s)"
|
|
9
|
+
* inside the existing panel (y=82, between row-3 baseline and the
|
|
10
|
+
* panel bottom at y=84), only when flowLinks.length > 3.
|
|
11
|
+
*
|
|
12
|
+
* Three states tested:
|
|
13
|
+
* - 5 distinct flow pairs → footer shows "+ 2 more flows"
|
|
14
|
+
* - exactly 3 flow pairs → footer absent
|
|
15
|
+
* - 0 flows (empty panel) → footer absent (R45 placeholder wins)
|
|
16
|
+
*
|
|
17
|
+
* Note: the test seeds (count) messages per pair so each unique
|
|
18
|
+
* (from→to) pair becomes ONE flowLink (deduped). Pairs > 3 force
|
|
19
|
+
* the hint; pairs ≤ 3 don't.
|
|
20
|
+
*/
|
|
21
|
+
import { chromium } from 'playwright';
|
|
22
|
+
import { readFileSync } from 'node:fs';
|
|
23
|
+
|
|
24
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
25
|
+
|
|
26
|
+
async function probe(pairCount) {
|
|
27
|
+
const browser = await chromium.launch({ headless: true });
|
|
28
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
29
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
30
|
+
await ctx.addInitScript(() => {
|
|
31
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
35
|
+
const aliases = ['alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta'];
|
|
36
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
37
|
+
const r = await route.fetch();
|
|
38
|
+
const b = await r.json();
|
|
39
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
40
|
+
const mk = (alias) => ({
|
|
41
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
42
|
+
network_id: nid, project_dir: null,
|
|
43
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
44
|
+
});
|
|
45
|
+
await route.fulfill({ response: r, json: { ...b, sessions: aliases.map(mk) } });
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const now = Date.now();
|
|
49
|
+
const msgs = [];
|
|
50
|
+
// Make pairCount distinct (from→to) pairs, 1 msg each, ascending age
|
|
51
|
+
for (let i = 0; i < pairCount; i++) {
|
|
52
|
+
msgs.push({
|
|
53
|
+
id: `m${i}`,
|
|
54
|
+
from_alias: aliases[i],
|
|
55
|
+
to_alias: aliases[(i + 1) % aliases.length],
|
|
56
|
+
content: 'hi',
|
|
57
|
+
network_id: 'default',
|
|
58
|
+
created_at: new Date(now - (20000 + i * 1000)).toISOString(),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: msgs } }));
|
|
62
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
63
|
+
|
|
64
|
+
const page = await ctx.newPage();
|
|
65
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
66
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 6, { timeout: 30000 });
|
|
67
|
+
await page.waitForTimeout(500);
|
|
68
|
+
|
|
69
|
+
const out = await page.evaluate(() => {
|
|
70
|
+
const el = document.querySelector('[data-recent-panel-more]');
|
|
71
|
+
const rows = document.querySelectorAll('[data-recent-row]').length;
|
|
72
|
+
const headerCount = document.querySelector('[data-recent-panel-count]')?.textContent;
|
|
73
|
+
return {
|
|
74
|
+
footerPresent: !!el,
|
|
75
|
+
footerText: el?.textContent?.trim(),
|
|
76
|
+
footerAttr: el?.getAttribute('data-recent-panel-more'),
|
|
77
|
+
rows,
|
|
78
|
+
headerCount,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await browser.close();
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const five = await probe(5);
|
|
87
|
+
const three = await probe(3);
|
|
88
|
+
const zero = await probe(0);
|
|
89
|
+
|
|
90
|
+
const results = {
|
|
91
|
+
five_footerPresent: five.footerPresent,
|
|
92
|
+
five_footerText: five.footerText === '+ 2 more flows',
|
|
93
|
+
five_footerAttr: five.footerAttr === '2',
|
|
94
|
+
five_rowsCapped3: five.rows === 3,
|
|
95
|
+
five_headerSaysFive: five.headerCount?.startsWith('5'),
|
|
96
|
+
|
|
97
|
+
three_footerAbsent: !three.footerPresent,
|
|
98
|
+
three_rowsExactly3: three.rows === 3,
|
|
99
|
+
|
|
100
|
+
zero_footerAbsent: !zero.footerPresent,
|
|
101
|
+
zero_rowsZero: zero.rows === 0,
|
|
102
|
+
};
|
|
103
|
+
const ok = Object.values(results).every(Boolean);
|
|
104
|
+
console.log(`${ok ? '✅' : '❌'} recent-panel more:`, JSON.stringify(results),
|
|
105
|
+
`\n five=`, five, `\n three=`, three, `\n zero=`, zero);
|
|
106
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/* Round 189 verification: recent-signal row count tspan unified
|
|
2
|
+
* into one always-mounted element with fill/fontWeight gated by
|
|
3
|
+
* isHot. transition: fill 300ms ease-out makes the R127 hot
|
|
4
|
+
* threshold crossing (count >= 10) ease smoothly through the
|
|
5
|
+
* colour shift instead of snapping.
|
|
6
|
+
*
|
|
7
|
+
* Pre-R189 two tspans branched on isHot — different
|
|
8
|
+
* data-recent-row-count and data-recent-row-count-hot
|
|
9
|
+
* attributes; mount/unmount made fill+fontWeight snap.
|
|
10
|
+
*
|
|
11
|
+
* Test:
|
|
12
|
+
* Mock 3 flows side by side:
|
|
13
|
+
* alpha→beta: count=4 (cold) → fill unset, weight unset,
|
|
14
|
+
* no hot attr
|
|
15
|
+
* alpha→gamma: count=12 (hot) → fill=amber, weight=700,
|
|
16
|
+
* hot attr 'true'
|
|
17
|
+
* alpha→delta: count=20 (hot) → fill=amber, weight=700
|
|
18
|
+
* All three tspans:
|
|
19
|
+
* - have data-recent-row-count
|
|
20
|
+
* - have style.transition includes 'fill 300ms'
|
|
21
|
+
*/
|
|
22
|
+
import { chromium } from 'playwright';
|
|
23
|
+
import { readFileSync } from 'node:fs';
|
|
24
|
+
|
|
25
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
26
|
+
const browser = await chromium.launch({ headless: true });
|
|
27
|
+
|
|
28
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
29
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
30
|
+
await ctx.addInitScript(() => {
|
|
31
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
35
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
36
|
+
const r = await route.fetch();
|
|
37
|
+
const b = await r.json();
|
|
38
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
39
|
+
const mk = (alias) => ({
|
|
40
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
41
|
+
network_id: nid, project_dir: null,
|
|
42
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
43
|
+
});
|
|
44
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
45
|
+
mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
|
|
46
|
+
] } });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const now = Date.now();
|
|
50
|
+
const msgs = [];
|
|
51
|
+
// alpha→beta: 4 (cold)
|
|
52
|
+
for (let i = 0; i < 4; i++) {
|
|
53
|
+
msgs.push({ id: `cold${i}`, from_alias: 'alpha', to_alias: 'beta', content: 'hi',
|
|
54
|
+
network_id: 'default', created_at: new Date(now - (5000 + i * 50)).toISOString() });
|
|
55
|
+
}
|
|
56
|
+
// alpha→gamma: 12 (hot)
|
|
57
|
+
for (let i = 0; i < 12; i++) {
|
|
58
|
+
msgs.push({ id: `h1${i}`, from_alias: 'alpha', to_alias: 'gamma', content: 'hi',
|
|
59
|
+
network_id: 'default', created_at: new Date(now - (10000 + i * 50)).toISOString() });
|
|
60
|
+
}
|
|
61
|
+
// alpha→delta: 20 (hot)
|
|
62
|
+
for (let i = 0; i < 20; i++) {
|
|
63
|
+
msgs.push({ id: `h2${i}`, from_alias: 'alpha', to_alias: 'delta', content: 'hi',
|
|
64
|
+
network_id: 'default', created_at: new Date(now - (15000 + i * 50)).toISOString() });
|
|
65
|
+
}
|
|
66
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: msgs } }));
|
|
67
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
68
|
+
|
|
69
|
+
const page = await ctx.newPage();
|
|
70
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
71
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
|
|
72
|
+
await page.waitForSelector('[data-recent-row-count]', { timeout: 10000 });
|
|
73
|
+
await page.waitForTimeout(400);
|
|
74
|
+
|
|
75
|
+
const probe = await page.evaluate(() => {
|
|
76
|
+
const tspans = [...document.querySelectorAll('[data-recent-row-count]')];
|
|
77
|
+
return tspans.map(t => {
|
|
78
|
+
const row = t.closest('[data-recent-row]');
|
|
79
|
+
return {
|
|
80
|
+
rowKey: row?.getAttribute('data-recent-row'),
|
|
81
|
+
text: t.textContent,
|
|
82
|
+
fill: t.getAttribute('fill'),
|
|
83
|
+
fontWeight: t.getAttribute('font-weight'),
|
|
84
|
+
hotAttr: t.getAttribute('data-recent-row-count-hot'),
|
|
85
|
+
transition: t.style.transition || getComputedStyle(t).transition,
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
await browser.close();
|
|
91
|
+
|
|
92
|
+
const findByKey = (key) => probe.find(p => p.rowKey === key);
|
|
93
|
+
const cold = findByKey('alpha->beta');
|
|
94
|
+
const hot1 = findByKey('alpha->gamma');
|
|
95
|
+
const hot2 = findByKey('alpha->delta');
|
|
96
|
+
|
|
97
|
+
const hasFillTransition = (s) =>
|
|
98
|
+
(s?.transition || '').includes('fill 300ms') ||
|
|
99
|
+
/fill\s+0\.3s|fill\s+300ms/.test(s?.transition || '');
|
|
100
|
+
|
|
101
|
+
const results = {
|
|
102
|
+
three_tspans_present: probe.length === 3,
|
|
103
|
+
cold_found: cold !== undefined,
|
|
104
|
+
hot1_found: hot1 !== undefined,
|
|
105
|
+
hot2_found: hot2 !== undefined,
|
|
106
|
+
|
|
107
|
+
cold_no_fill: cold?.fill === null || cold?.fill === undefined,
|
|
108
|
+
cold_no_fontWeight: cold?.fontWeight === null || cold?.fontWeight === undefined,
|
|
109
|
+
cold_no_hot_attr: cold?.hotAttr === null,
|
|
110
|
+
cold_text_4: cold?.text === '4',
|
|
111
|
+
|
|
112
|
+
hot1_fill_amber: hot1?.fill === '#fbbf24',
|
|
113
|
+
hot1_fontWeight_700: hot1?.fontWeight === '700',
|
|
114
|
+
hot1_hot_attr: hot1?.hotAttr === 'true',
|
|
115
|
+
hot1_text_12: hot1?.text === '12',
|
|
116
|
+
|
|
117
|
+
hot2_fill_amber: hot2?.fill === '#fbbf24',
|
|
118
|
+
hot2_fontWeight_700: hot2?.fontWeight === '700',
|
|
119
|
+
hot2_hot_attr: hot2?.hotAttr === 'true',
|
|
120
|
+
hot2_text_20: hot2?.text === '20',
|
|
121
|
+
|
|
122
|
+
all_have_fill_transition: probe.every(p => hasFillTransition(p)),
|
|
123
|
+
};
|
|
124
|
+
const ok = Object.values(results).every(Boolean);
|
|
125
|
+
console.log(`${ok ? '✅' : '❌'} recent-row count fill:`, JSON.stringify(results),
|
|
126
|
+
`\n cold:`, cold,
|
|
127
|
+
`\n hot1:`, hot1,
|
|
128
|
+
`\n hot2:`, hot2);
|
|
129
|
+
process.exit(ok ? 0 : 1);
|