@sleep2agi/agent-network-dashboard 0.5.3-preview.26 → 0.5.3-preview.260
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/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +7 -7
- package/.next/fallback-build-manifest.json +3 -3
- 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 +2 -2
- package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/admin.segments/_full.segment.rsc +2 -2
- package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_index.segment.rsc +2 -2
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/admin.segments/admin.segment.rsc +1 -1
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +3 -3
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +2 -2
- 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 +3 -3
- package/.next/server/app/login.segments/_full.segment.rsc +3 -3
- package/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/server/app/login.segments/_index.segment.rsc +2 -2
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/login.segments/login.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/logs.segments/_full.segment.rsc +2 -2
- package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_index.segment.rsc +2 -2
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/messages.segments/_full.segment.rsc +2 -2
- package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_index.segment.rsc +2 -2
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/messages.segments/messages.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/node.segments/_full.segment.rsc +2 -2
- package/.next/server/app/node.segments/_head.segment.rsc +1 -1
- package/.next/server/app/node.segments/_index.segment.rsc +2 -2
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/node.segments/node.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/nodes.segments/_full.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_index.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/nodes.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/server-logs.segments/_full.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_index.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +1 -1
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +3 -3
- package/.next/server/app/settings.segments/_full.segment.rsc +3 -3
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/tasks.segments/_full.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_index.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/tasks.segment.rsc +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/[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/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/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +2 -2
- package/.next/server/pages/500.html +1 -1
- package/.next/static/chunks/083elibefsefi.js +4 -0
- package/.next/static/chunks/{05uydm8okqgqe.js → 0p142v5va508~.js} +1 -1
- package/.next/static/chunks/0u8v68gl7g6j1.js +1 -0
- package/.next/static/chunks/11sahbo6ikg8g.js +1 -0
- package/.next/static/chunks/16-7qr7qx9zrz.css +2 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/api/hub/servers/route.ts +3 -29
- package/app/components/TopoGraph.tsx +6143 -180
- package/app/globals.css +897 -7
- package/app/lib/serverDedupe.ts +122 -0
- package/package.json +1 -1
- 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-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-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-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-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/0b57cx-~yee9s.js +0 -1
- package/.next/static/chunks/0c5ux9rrl-j.a.js +0 -4
- package/.next/static/chunks/0ixrbcha76lse.js +0 -1
- package/.next/static/chunks/0m.1mvl~t.avc.css +0 -2
- /package/.next/static/{fAHTff4Obp5vYwjZIWEvA → wz1T-LhLDalz691PpN3E7}/_buildManifest.js +0 -0
- /package/.next/static/{fAHTff4Obp5vYwjZIWEvA → wz1T-LhLDalz691PpN3E7}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{fAHTff4Obp5vYwjZIWEvA → wz1T-LhLDalz691PpN3E7}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* Round 743 — chrome strip entrance animation. 3rd member of the
|
|
2
|
+
* entrance family, completing the entrance trio. Three-stage cascade:
|
|
3
|
+
* R740 canvas 0 → 600 ms scale 0.99→1, opacity 0.8→1
|
|
4
|
+
* R742 title-block 200 → 700 ms translateY -4→0, opacity 0.7→1
|
|
5
|
+
* R743 chrome strip 400 → 900 ms translateX 8→0, opacity 0.7→1
|
|
6
|
+
*
|
|
7
|
+
* Assertions:
|
|
8
|
+
* - .anet-topo-chrome-strip-entrance class on [data-topo-chrome]
|
|
9
|
+
* - data-topo-chrome-entrance="true"
|
|
10
|
+
* - CSS @keyframes 0% translateX(8px) opacity 0.7 → 100% translateX(0) opacity 1
|
|
11
|
+
* - .anet-topo-chrome-strip-entrance binds 500ms ease-out 400ms delay
|
|
12
|
+
* - one-shot (runtime iteration count === '1')
|
|
13
|
+
* - prefers-reduced-motion guard present
|
|
14
|
+
* - Animation done within ~1.1s (400ms delay + 500ms + buffer);
|
|
15
|
+
* after 1100ms computed transform is identity & opacity = 1
|
|
16
|
+
* - chrome strip wrapper has NO compound animation (single anim) —
|
|
17
|
+
* anim_name is exactly the entrance keyframe (not comma-joined)
|
|
18
|
+
* - R741 catalog one-shot-mount.members === 3, includes chrome strip
|
|
19
|
+
* - R740 + R742 entrance siblings still present (regression)
|
|
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
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
26
|
+
|
|
27
|
+
const browser = await chromium.launch({ headless: true });
|
|
28
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
29
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
30
|
+
await ctx.addInitScript(() => {
|
|
31
|
+
try {
|
|
32
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
33
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
34
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
35
|
+
} catch {}
|
|
36
|
+
});
|
|
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: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
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: [mk('a·1'), mk('a·2')] } });
|
|
47
|
+
});
|
|
48
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
49
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
50
|
+
const page = await ctx.newPage();
|
|
51
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
52
|
+
await page.waitForSelector('[data-topo-chrome]', { timeout: 15000, state: 'attached' });
|
|
53
|
+
/* Wait past the 400ms delay + 500ms duration + buffer. */
|
|
54
|
+
await page.waitForTimeout(1100);
|
|
55
|
+
|
|
56
|
+
const state = await page.evaluate(() => {
|
|
57
|
+
const chrome = document.querySelector('[data-topo-chrome]');
|
|
58
|
+
const svg = document.querySelector('[data-topo-canvas-aria]');
|
|
59
|
+
const titleBlock = document.querySelector('[data-topo-section-titleblock-group]');
|
|
60
|
+
if (!chrome) return null;
|
|
61
|
+
const cs = getComputedStyle(chrome);
|
|
62
|
+
return {
|
|
63
|
+
has_entrance_class: chrome.classList.contains('anet-topo-chrome-strip-entrance'),
|
|
64
|
+
entrance_attr: chrome.getAttribute('data-topo-chrome-entrance'),
|
|
65
|
+
anim_name: cs.animationName,
|
|
66
|
+
anim_duration: cs.animationDuration,
|
|
67
|
+
anim_delay: cs.animationDelay,
|
|
68
|
+
anim_iteration: cs.animationIterationCount,
|
|
69
|
+
computed_transform: cs.transform,
|
|
70
|
+
computed_opacity: cs.opacity,
|
|
71
|
+
canvas_entrance: svg?.classList.contains('anet-topo-canvas-entrance') ?? null,
|
|
72
|
+
title_block_entrance: titleBlock?.classList.contains('anet-topo-title-block-entrance') ?? null,
|
|
73
|
+
temporal_modes: svg?.getAttribute('data-topo-animation-temporal-modes') ?? null,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await browser.close();
|
|
78
|
+
|
|
79
|
+
const cssSrc = readFileSync('/home/vansin/agent-network-dashboard/app/globals.css', 'utf8');
|
|
80
|
+
const cssKfStart = /@keyframes anet-topo-chrome-strip-entrance-kf\s*\{[\s\S]*?0%\s*\{[\s\S]*?transform:\s*translateX\(8px\)[\s\S]*?opacity:\s*0\.7/.test(cssSrc);
|
|
81
|
+
const cssKfEnd = /@keyframes anet-topo-chrome-strip-entrance-kf\s*\{[\s\S]*?100%\s*\{[\s\S]*?transform:\s*translateX\(0\)[\s\S]*?opacity:\s*1/.test(cssSrc);
|
|
82
|
+
const cssClassBound = /\.anet-topo-chrome-strip-entrance\s*\{[\s\S]*?animation:\s*anet-topo-chrome-strip-entrance-kf\s+500ms\s+ease-out\s+400ms\s+backwards/.test(cssSrc);
|
|
83
|
+
const cssReducedMotion = /@media\s*\(prefers-reduced-motion:\s*reduce\)\s*\{[\s\S]*?\.anet-topo-chrome-strip-entrance\s*\{\s*animation:\s*none/.test(cssSrc);
|
|
84
|
+
|
|
85
|
+
const transformSettled = state?.computed_transform === 'none'
|
|
86
|
+
|| state?.computed_transform === 'matrix(1, 0, 0, 1, 0, 0)';
|
|
87
|
+
const opacitySettled = parseFloat(state?.computed_opacity ?? '0') > 0.99;
|
|
88
|
+
const singleAnimation = state?.anim_name === 'anet-topo-chrome-strip-entrance-kf';
|
|
89
|
+
|
|
90
|
+
let modes = null;
|
|
91
|
+
try { modes = JSON.parse(state?.temporal_modes ?? ''); } catch {}
|
|
92
|
+
const oneShot = Array.isArray(modes) ? modes.find(m => m.mode === 'one-shot-mount') : null;
|
|
93
|
+
const oneShotHas3 = oneShot?.members === 3 && Array.isArray(oneShot?.examples) && oneShot.examples.includes('chrome strip');
|
|
94
|
+
|
|
95
|
+
const results = {
|
|
96
|
+
has_entrance_class: state?.has_entrance_class === true,
|
|
97
|
+
entrance_attr_true: state?.entrance_attr === 'true',
|
|
98
|
+
css_keyframe_start: cssKfStart,
|
|
99
|
+
css_keyframe_end: cssKfEnd,
|
|
100
|
+
css_class_binds_500ms_delay_400: cssClassBound,
|
|
101
|
+
css_reduced_motion_guard: cssReducedMotion,
|
|
102
|
+
runtime_animation_one_shot: state?.anim_iteration === '1',
|
|
103
|
+
single_animation_no_compound: singleAnimation,
|
|
104
|
+
transform_settled: transformSettled,
|
|
105
|
+
opacity_settled_to_1: opacitySettled,
|
|
106
|
+
r740_canvas_entrance_kept: state?.canvas_entrance === true,
|
|
107
|
+
r742_title_block_entrance_kept: state?.title_block_entrance === true,
|
|
108
|
+
r741_one_shot_members_now_3: oneShotHas3,
|
|
109
|
+
};
|
|
110
|
+
const ok = Object.values(results).every(Boolean);
|
|
111
|
+
console.log(`${ok ? '✅' : '❌'} R743 chrome strip entrance animation (3rd one-shot member, entrance trio complete):`,
|
|
112
|
+
JSON.stringify(results, null, 2),
|
|
113
|
+
`\n state: ${JSON.stringify(state)}`,
|
|
114
|
+
`\n one-shot entry: ${JSON.stringify(oneShot)}`);
|
|
115
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/* Round 697 — chrome strip segmented-control wrappers (Layout /
|
|
2
|
+
* nodeSize / zoom containers) gain wrapper-level multi-layer halo
|
|
3
|
+
* via CSS :has(button:hover) on the 3 wrappers' data-attrs. Pre-R697
|
|
4
|
+
* only individual inner buttons halo'd (R667-R675 per-button); the
|
|
5
|
+
* parent wrappers stayed flat. R697 closes the chrome-strip "active
|
|
6
|
+
* control group" signal at the parent scope.
|
|
7
|
+
*
|
|
8
|
+
* Source assertions:
|
|
9
|
+
* - globals.css :has(button:hover) rule covers all 3 wrappers
|
|
10
|
+
* - globals.css transition rule for the 3 wrappers includes filter
|
|
11
|
+
* - TopoGraph.tsx Layout wrapper has data-topo-chrome-wrapper-halo-family="layout"
|
|
12
|
+
* - TopoGraph.tsx nodeSize wrapper has data-topo-chrome-wrapper-halo-family="nodesize"
|
|
13
|
+
* - TopoGraph.tsx zoom wrapper has data-topo-chrome-wrapper-halo-family="zoom"
|
|
14
|
+
*
|
|
15
|
+
* Runtime assertions:
|
|
16
|
+
* - all 3 wrappers present in DOM with halo-family data-attrs
|
|
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
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
23
|
+
|
|
24
|
+
const browser = await chromium.launch({ headless: true });
|
|
25
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
26
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
27
|
+
await ctx.addInitScript(() => {
|
|
28
|
+
try {
|
|
29
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
30
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
31
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
32
|
+
} catch {}
|
|
33
|
+
});
|
|
34
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
35
|
+
const r = await route.fetch();
|
|
36
|
+
const b = await r.json();
|
|
37
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
38
|
+
const mk = (alias) => ({
|
|
39
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
40
|
+
network_id: nid, project_dir: null,
|
|
41
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
42
|
+
});
|
|
43
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
44
|
+
});
|
|
45
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
46
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
47
|
+
const page = await ctx.newPage();
|
|
48
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
49
|
+
await page.waitForSelector('[data-topo-chrome-wrapper-halo-family]', { timeout: 15000, state: 'attached' });
|
|
50
|
+
await page.waitForTimeout(300);
|
|
51
|
+
|
|
52
|
+
const runtimeState = await page.evaluate(() => {
|
|
53
|
+
const wrappers = Array.from(document.querySelectorAll('[data-topo-chrome-wrapper-halo-family]'));
|
|
54
|
+
return wrappers.map(w => w.getAttribute('data-topo-chrome-wrapper-halo-family')).sort();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
await browser.close();
|
|
58
|
+
|
|
59
|
+
const cssSrc = readFileSync('/home/vansin/agent-network-dashboard/app/globals.css', 'utf8');
|
|
60
|
+
const tsxSrc = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
61
|
+
|
|
62
|
+
const cssHoverRule = /\[data-topo-chrome-layout-trailer\]:has\(button:hover\),[\s\S]*?\[data-topo-chrome-fleet-group-trailer\]:has\(button:hover\),[\s\S]*?\[data-topo-chrome-zoom-wrapper\]:has\(button:hover\)\s*\{[\s\S]*?drop-shadow\(0 0 2px rgba\(103, 232, 249, 0\.5\)\)[\s\S]*?drop-shadow\(0 0 4px rgba\(103, 232, 249, 0\.25\)\)/.test(cssSrc);
|
|
63
|
+
const cssTransition = /\[data-topo-chrome-layout-trailer\],[\s\S]*?\[data-topo-chrome-fleet-group-trailer\],[\s\S]*?\[data-topo-chrome-zoom-wrapper\]\s*\{[\s\S]*?transition:[\s\S]*?filter 200ms/.test(cssSrc);
|
|
64
|
+
const tsxLayoutAttr = /data-topo-chrome-wrapper-halo-family="layout"/.test(tsxSrc);
|
|
65
|
+
const tsxNodesizeAttr = /data-topo-chrome-wrapper-halo-family="nodesize"/.test(tsxSrc);
|
|
66
|
+
const tsxZoomAttr = /data-topo-chrome-wrapper-halo-family="zoom"/.test(tsxSrc);
|
|
67
|
+
|
|
68
|
+
const expectedFamilies = ['layout', 'nodesize', 'zoom'];
|
|
69
|
+
|
|
70
|
+
const results = {
|
|
71
|
+
wrappers_count: runtimeState.length === 3,
|
|
72
|
+
wrappers_families: JSON.stringify(runtimeState) === JSON.stringify(expectedFamilies),
|
|
73
|
+
css_hover_rule: cssHoverRule,
|
|
74
|
+
css_transition: cssTransition,
|
|
75
|
+
tsx_layout_attr: tsxLayoutAttr,
|
|
76
|
+
tsx_nodesize_attr: tsxNodesizeAttr,
|
|
77
|
+
tsx_zoom_attr: tsxZoomAttr,
|
|
78
|
+
};
|
|
79
|
+
const ok = Object.values(results).every(Boolean);
|
|
80
|
+
console.log(`${ok ? '✅' : '❌'} R697 chrome wrapper :has() multi-layer halo (53rd anchor — 3 wrappers via CSS rule):`,
|
|
81
|
+
JSON.stringify(results, null, 2),
|
|
82
|
+
`\n runtime families: ${JSON.stringify(runtimeState)}`);
|
|
83
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/* Round 709 — chrome zoom wrapper at-rest breath at 23s. Closes chrome
|
|
2
|
+
* control trio (R707 17s + R708 19s + R709 23s adjacent-prime coprime
|
|
3
|
+
* cadences). 23s slowest = "calm anchor for the viewport-control cluster".
|
|
4
|
+
* Same alpha (6%) + :has(button:hover) gate as R707/R708.
|
|
5
|
+
*/
|
|
6
|
+
import { chromium } from 'playwright';
|
|
7
|
+
import { readFileSync } from 'node:fs';
|
|
8
|
+
|
|
9
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
10
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
11
|
+
|
|
12
|
+
const browser = await chromium.launch({ headless: true });
|
|
13
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
14
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
15
|
+
await ctx.addInitScript(() => {
|
|
16
|
+
try {
|
|
17
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
18
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
19
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
20
|
+
} catch {}
|
|
21
|
+
});
|
|
22
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
23
|
+
const r = await route.fetch();
|
|
24
|
+
const b = await r.json();
|
|
25
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
26
|
+
const mk = (alias) => ({
|
|
27
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
28
|
+
network_id: nid, project_dir: null,
|
|
29
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
30
|
+
});
|
|
31
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
32
|
+
});
|
|
33
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
34
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
35
|
+
const page = await ctx.newPage();
|
|
36
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
37
|
+
await page.waitForSelector('[data-topo-chrome-zoom-wrapper]', { timeout: 15000, state: 'attached' });
|
|
38
|
+
await page.waitForTimeout(300);
|
|
39
|
+
|
|
40
|
+
const runtimeState = await page.evaluate(() => {
|
|
41
|
+
const wrap = document.querySelector('[data-topo-chrome-zoom-wrapper]');
|
|
42
|
+
if (!wrap) return null;
|
|
43
|
+
const cs = getComputedStyle(wrap);
|
|
44
|
+
return {
|
|
45
|
+
has_class: wrap.classList.contains('anet-topo-chrome-zoom-wrapper-breath'),
|
|
46
|
+
breath_attr: wrap.getAttribute('data-topo-chrome-zoom-wrapper-breath'),
|
|
47
|
+
anim_name: cs.animationName,
|
|
48
|
+
anim_duration: cs.animationDuration,
|
|
49
|
+
anim_iter: cs.animationIterationCount,
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
await browser.close();
|
|
54
|
+
|
|
55
|
+
const cssSrc = readFileSync('/home/vansin/agent-network-dashboard/app/globals.css', 'utf8');
|
|
56
|
+
const tsxSrc = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
57
|
+
|
|
58
|
+
const cssKeyframes = /@keyframes anet-topo-chrome-zoom-wrapper-breath-kf\s*\{[\s\S]*?0%, 100%\s*\{\s*opacity:\s*1;\s*\}[\s\S]*?50%\s*\{\s*opacity:\s*0\.94;/.test(cssSrc);
|
|
59
|
+
const cssRule = /\.anet-topo-chrome-zoom-wrapper-breath\s*\{[\s\S]*?animation:\s*anet-topo-chrome-zoom-wrapper-breath-kf\s+23s\s+ease-in-out\s+infinite/.test(cssSrc);
|
|
60
|
+
const cssHoverGate = /\.anet-topo-chrome-zoom-wrapper-breath:has\(button:hover\)\s*\{\s*animation:\s*none/.test(cssSrc);
|
|
61
|
+
const cssReducedMotion = /prefers-reduced-motion:\s*reduce\s*\)\s*\{\s*\.anet-topo-chrome-zoom-wrapper-breath\s*\{\s*animation:\s*none/.test(cssSrc);
|
|
62
|
+
const tsxClass = /anet-topo-chrome-zoom-wrapper-breath ml-1\.5/.test(tsxSrc);
|
|
63
|
+
const tsxAttr = /data-topo-chrome-zoom-wrapper-breath="23s"/.test(tsxSrc);
|
|
64
|
+
|
|
65
|
+
const runtimeAnim = runtimeState?.anim_name === 'anet-topo-chrome-zoom-wrapper-breath-kf' || runtimeState?.anim_name === 'none';
|
|
66
|
+
const runtimeDuration = runtimeState?.anim_duration === '23s' || runtimeState?.anim_name === 'none';
|
|
67
|
+
|
|
68
|
+
const results = {
|
|
69
|
+
wrapper_present: !!runtimeState,
|
|
70
|
+
has_breath_class: runtimeState?.has_class === true,
|
|
71
|
+
breath_attr_23s: runtimeState?.breath_attr === '23s',
|
|
72
|
+
runtime_anim_ok: runtimeAnim,
|
|
73
|
+
runtime_duration_ok: runtimeDuration,
|
|
74
|
+
css_keyframes: cssKeyframes,
|
|
75
|
+
css_rule: cssRule,
|
|
76
|
+
css_hover_gate: cssHoverGate,
|
|
77
|
+
css_reduced_motion: cssReducedMotion,
|
|
78
|
+
tsx_class: tsxClass,
|
|
79
|
+
tsx_breath_attr: tsxAttr,
|
|
80
|
+
};
|
|
81
|
+
const ok = Object.values(results).every(Boolean);
|
|
82
|
+
console.log(`${ok ? '✅' : '❌'} R709 chrome zoom wrapper at-rest breath (23s prime, chrome control trio CLOSED — 17/19/23 adjacent primes):`,
|
|
83
|
+
JSON.stringify(results, null, 2),
|
|
84
|
+
`\n runtime: ${JSON.stringify(runtimeState)}`);
|
|
85
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* Round 608 — click-ripple gains drop-shadow glow that matches
|
|
2
|
+
* the ripple's stroke color. Expanding feedback ring now reads
|
|
3
|
+
* as a "lit pulse" rather than a plain stroke line.
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. mock 2 idle nodes → click first node → ripple renders
|
|
7
|
+
* 2. ripple element present with data-click-ripple attr
|
|
8
|
+
* 3. computed filter contains 'drop-shadow'
|
|
9
|
+
* 4. data-click-ripple-glow attr present with valid format
|
|
10
|
+
* 5. source: filter inline + data-attr extension
|
|
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
|
+
// Click hub group (role=button aria-label="Network hub...") to fire setClickRipple
|
|
44
|
+
await page.waitForSelector('[data-topo-hub-fade-delay]', { timeout: 15000, state: 'attached' });
|
|
45
|
+
const hubBox = await page.evaluate(() => {
|
|
46
|
+
const el = document.querySelector('[data-topo-hub-fade-delay]');
|
|
47
|
+
if (!el) return null;
|
|
48
|
+
const r = el.getBoundingClientRect();
|
|
49
|
+
return { x: r.left + r.width / 2, y: r.top + r.height / 2 };
|
|
50
|
+
});
|
|
51
|
+
if (!hubBox) throw new Error('hub not found');
|
|
52
|
+
await page.mouse.click(hubBox.x, hubBox.y);
|
|
53
|
+
// Wait briefly so the ripple mounts but doesn't fully fade
|
|
54
|
+
await page.waitForSelector('[data-click-ripple]', { timeout: 5000, state: 'attached' });
|
|
55
|
+
await page.waitForTimeout(100);
|
|
56
|
+
|
|
57
|
+
const rippleState = await page.evaluate(() => {
|
|
58
|
+
const el = document.querySelector('[data-click-ripple]');
|
|
59
|
+
if (!el) return null;
|
|
60
|
+
const cs = getComputedStyle(el);
|
|
61
|
+
return {
|
|
62
|
+
filter: cs.filter,
|
|
63
|
+
glowAttr: el.getAttribute('data-click-ripple-glow'),
|
|
64
|
+
stroke: el.getAttribute('stroke'),
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await browser.close();
|
|
69
|
+
|
|
70
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
71
|
+
const sourceFilter = /filter: `drop-shadow\(0 0 4px \$\{clickRipple\.color\}99\)`/.test(src);
|
|
72
|
+
const sourceAttr = /data-click-ripple-glow=\{`0 0 4px \$\{clickRipple\.color\}99`\}/.test(src);
|
|
73
|
+
|
|
74
|
+
const results = {
|
|
75
|
+
ripple_present: !!rippleState,
|
|
76
|
+
has_drop_shadow: /drop-shadow/.test(rippleState?.filter || ''),
|
|
77
|
+
glow_attr_format: /^0 0 4px /.test(rippleState?.glowAttr || ''),
|
|
78
|
+
has_stroke: !!rippleState?.stroke,
|
|
79
|
+
source_filter: sourceFilter,
|
|
80
|
+
source_attr: sourceAttr,
|
|
81
|
+
};
|
|
82
|
+
const ok = Object.values(results).every(Boolean);
|
|
83
|
+
console.log(`${ok ? '✅' : '❌'} R608 click-ripple drop-shadow glow (click feedback enhancement):`,
|
|
84
|
+
JSON.stringify(results, null, 2),
|
|
85
|
+
`\n ripple: ${JSON.stringify(rippleState)}`);
|
|
86
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/* Round 657 — click-ripple drop-shadow gains a SECOND outer layer
|
|
2
|
+
* at 8px + 0x4c alpha (half R608 inner 0x99). 16th anchor in
|
|
3
|
+
* multi-layer halo family (1st click-feedback anchor).
|
|
4
|
+
*/
|
|
5
|
+
import { chromium } from 'playwright';
|
|
6
|
+
import { readFileSync } from 'node:fs';
|
|
7
|
+
|
|
8
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
9
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
10
|
+
|
|
11
|
+
const browser = await chromium.launch({ headless: true });
|
|
12
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
13
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
14
|
+
await ctx.addInitScript(() => {
|
|
15
|
+
try {
|
|
16
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
17
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
18
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
19
|
+
} catch {}
|
|
20
|
+
});
|
|
21
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
22
|
+
const r = await route.fetch();
|
|
23
|
+
const b = await r.json();
|
|
24
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
25
|
+
const mk = (alias) => ({
|
|
26
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
27
|
+
network_id: nid, project_dir: null,
|
|
28
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
29
|
+
});
|
|
30
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
31
|
+
});
|
|
32
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
33
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
34
|
+
const page = await ctx.newPage();
|
|
35
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
36
|
+
await page.waitForSelector('[data-node="a·1"]', { timeout: 15000 });
|
|
37
|
+
await page.waitForTimeout(500);
|
|
38
|
+
|
|
39
|
+
// rest: no ripple
|
|
40
|
+
const restRipple = await page.evaluate(() => !!document.querySelector('[data-click-ripple]'));
|
|
41
|
+
|
|
42
|
+
// click node → ripple mounts; poll to catch it before it self-cleans
|
|
43
|
+
await page.click('[data-node="a·1"]', { force: true });
|
|
44
|
+
let activeState = null;
|
|
45
|
+
for (let i = 0; i < 12; i++) {
|
|
46
|
+
await page.waitForTimeout(40);
|
|
47
|
+
const s = await page.evaluate(() => {
|
|
48
|
+
const el = document.querySelector('[data-click-ripple]');
|
|
49
|
+
if (!el) return null;
|
|
50
|
+
const cs = getComputedStyle(el);
|
|
51
|
+
return {
|
|
52
|
+
layers: el.getAttribute('data-click-ripple-halo-layers'),
|
|
53
|
+
filter: cs.filter,
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
if (s) { activeState = s; break; }
|
|
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: `drop-shadow\(0 0 4px \$\{clickRipple\.color\}99\) drop-shadow\(0 0 8px \$\{clickRipple\.color\}4c\)`/.test(src);
|
|
63
|
+
const sourceLayersAttr = /data-click-ripple-halo-layers="2"/.test(src);
|
|
64
|
+
|
|
65
|
+
const dropShadowCount = (activeState?.filter?.match(/drop-shadow/g) || []).length;
|
|
66
|
+
|
|
67
|
+
const results = {
|
|
68
|
+
rest_no_ripple: restRipple === false,
|
|
69
|
+
active_present: !!activeState,
|
|
70
|
+
active_layers_2: activeState?.layers === '2',
|
|
71
|
+
active_two_dropshadows: dropShadowCount === 2,
|
|
72
|
+
source_filter: sourceFilter,
|
|
73
|
+
source_layers_attr: sourceLayersAttr,
|
|
74
|
+
};
|
|
75
|
+
const ok = Object.values(results).every(Boolean);
|
|
76
|
+
console.log(`${ok ? '✅' : '❌'} R657 click-ripple multi-layer halo (1st click-feedback anchor):`,
|
|
77
|
+
JSON.stringify(results, null, 2),
|
|
78
|
+
`\n active: ${JSON.stringify(activeState)}`);
|
|
79
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/* Round 631 — click-ripple gains a THIRD animate axis:
|
|
2
|
+
* stroke-width 2 → 0.5 over 500ms with the same R227 ease-out
|
|
3
|
+
* keySplines as r + opacity. Reads as a real-water-ripple thinning
|
|
4
|
+
* wavefront instead of a constant-thickness expanding line.
|
|
5
|
+
*
|
|
6
|
+
* Test phases:
|
|
7
|
+
* 1. mock 2 nodes → no ripple at rest, no [data-click-ripple]
|
|
8
|
+
* 2. click a node → ripple mounts with 3 <animate> children:
|
|
9
|
+
* - r (R14/R227)
|
|
10
|
+
* - opacity (R227/R403)
|
|
11
|
+
* - stroke-width (R631 — this round)
|
|
12
|
+
* all dur=0.5s, calcMode=spline, keySplines='0.25 0.1 0.25 1',
|
|
13
|
+
* fill=freeze
|
|
14
|
+
* 3. ripple disappears after ~600ms (setClickRipple→null timeout)
|
|
15
|
+
* 4. source: stroke-width animate sits as a sibling of the opacity
|
|
16
|
+
* animate inside the [data-click-ripple] <circle>
|
|
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
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
23
|
+
|
|
24
|
+
const browser = await chromium.launch({ headless: true });
|
|
25
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
26
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
27
|
+
await ctx.addInitScript(() => {
|
|
28
|
+
try {
|
|
29
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
30
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
31
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
32
|
+
} catch {}
|
|
33
|
+
});
|
|
34
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
35
|
+
const r = await route.fetch();
|
|
36
|
+
const b = await r.json();
|
|
37
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
38
|
+
const mk = (alias) => ({
|
|
39
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
40
|
+
network_id: nid, project_dir: null,
|
|
41
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
42
|
+
});
|
|
43
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
44
|
+
});
|
|
45
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
46
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
47
|
+
const page = await ctx.newPage();
|
|
48
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
49
|
+
await page.waitForSelector('[data-node="a·1"]', { timeout: 15000 });
|
|
50
|
+
await page.waitForTimeout(500);
|
|
51
|
+
|
|
52
|
+
// 1. rest: no ripple
|
|
53
|
+
const restRipple = await page.evaluate(() => !!document.querySelector('[data-click-ripple]'));
|
|
54
|
+
|
|
55
|
+
// 2. click node — ripple mounts
|
|
56
|
+
await page.click('[data-node="a·1"]', { force: true });
|
|
57
|
+
// poll quickly to catch the ripple before it self-cleans
|
|
58
|
+
let activeState = null;
|
|
59
|
+
for (let i = 0; i < 12; i++) {
|
|
60
|
+
await page.waitForTimeout(40);
|
|
61
|
+
const s = await page.evaluate(() => {
|
|
62
|
+
const el = document.querySelector('[data-click-ripple]');
|
|
63
|
+
if (!el) return null;
|
|
64
|
+
const animates = Array.from(el.querySelectorAll('animate'));
|
|
65
|
+
return {
|
|
66
|
+
strokeWidth: el.getAttribute('stroke-width'),
|
|
67
|
+
animateCount: animates.length,
|
|
68
|
+
animateAttrs: animates.map(a => ({
|
|
69
|
+
attr: a.getAttribute('attributeName'),
|
|
70
|
+
dur: a.getAttribute('dur'),
|
|
71
|
+
vals: a.getAttribute('values'),
|
|
72
|
+
calc: a.getAttribute('calcMode'),
|
|
73
|
+
spl: a.getAttribute('keySplines'),
|
|
74
|
+
fill: a.getAttribute('fill'),
|
|
75
|
+
})),
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
if (s) { activeState = s; break; }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
await browser.close();
|
|
82
|
+
|
|
83
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
84
|
+
const sourceSwAnimate = /<animate\s+attributeName="stroke-width"\s+values="2;0\.5"\s+dur="0\.5s"\s+calcMode="spline"\s+keyTimes="0;1"\s+keySplines="0\.25 0\.1 0\.25 1"\s+fill="freeze"/.test(src);
|
|
85
|
+
const sourceSwAttrs = /data-click-ripple-stroke-width-start="2"\s+data-click-ripple-stroke-width-end="0\.5"/.test(src);
|
|
86
|
+
|
|
87
|
+
const swAnimate = activeState?.animateAttrs?.find(a => a.attr === 'stroke-width');
|
|
88
|
+
const rAnimate = activeState?.animateAttrs?.find(a => a.attr === 'r');
|
|
89
|
+
const opAnimate = activeState?.animateAttrs?.find(a => a.attr === 'opacity');
|
|
90
|
+
|
|
91
|
+
const results = {
|
|
92
|
+
rest_no_ripple: restRipple === false,
|
|
93
|
+
active_ripple_present: activeState != null,
|
|
94
|
+
active_3_animates: activeState?.animateCount === 3,
|
|
95
|
+
active_has_r: rAnimate != null,
|
|
96
|
+
active_has_opacity: opAnimate != null,
|
|
97
|
+
active_has_sw: swAnimate != null,
|
|
98
|
+
active_sw_values: swAnimate?.vals === '2;0.5',
|
|
99
|
+
active_sw_dur: swAnimate?.dur === '0.5s',
|
|
100
|
+
active_sw_spline_easeout: swAnimate?.spl === '0.25 0.1 0.25 1',
|
|
101
|
+
active_sw_calc_spline: swAnimate?.calc === 'spline',
|
|
102
|
+
active_sw_fill_freeze: swAnimate?.fill === 'freeze',
|
|
103
|
+
source_sw_animate: sourceSwAnimate,
|
|
104
|
+
source_sw_attrs: sourceSwAttrs,
|
|
105
|
+
};
|
|
106
|
+
const ok = Object.values(results).every(Boolean);
|
|
107
|
+
console.log(`${ok ? '✅' : '❌'} R631 click-ripple stroke-width thinning (3-axis ripple):`,
|
|
108
|
+
JSON.stringify(results, null, 2),
|
|
109
|
+
`\n active: ${JSON.stringify(activeState)}`);
|
|
110
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/* Round 528 verification: brand crescent gains ambient SMIL breath
|
|
2
|
+
* (0.8↔1.0 fill-opacity, 7s, repeat indefinite). 呼吸感 family 4th
|
|
3
|
+
* anchor — symmetric to R519 watermark breath but at 7s vs 6s cadence
|
|
4
|
+
* so the two ambient anchors don't beat together visibly.
|
|
5
|
+
*
|
|
6
|
+
* Test phases:
|
|
7
|
+
* 1. motion enabled: data-topo-brand-canvas-mark-breath='true'
|
|
8
|
+
* + <animate> child mounted on inner <rect>
|
|
9
|
+
* + values='0.8;1;0.8', dur='7s', repeatCount='indefinite'
|
|
10
|
+
* + attributeName='fill-opacity' (NOT 'opacity')
|
|
11
|
+
* 2. reduced-motion: breath attr='false', NO <animate> child
|
|
12
|
+
* 3. wrapper recede + visibility still works (regression check)
|
|
13
|
+
* 4. source-side regex confirms wiring
|
|
14
|
+
*/
|
|
15
|
+
import { chromium } from 'playwright';
|
|
16
|
+
import { readFileSync } from 'node:fs';
|
|
17
|
+
|
|
18
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
19
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
20
|
+
|
|
21
|
+
async function probe(reducedMotion) {
|
|
22
|
+
const browser = await chromium.launch({ headless: true });
|
|
23
|
+
const ctx = await browser.newContext({
|
|
24
|
+
viewport: { width: 1500, height: 1200 },
|
|
25
|
+
reducedMotion: reducedMotion ? 'reduce' : 'no-preference',
|
|
26
|
+
});
|
|
27
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
28
|
+
await ctx.addInitScript(() => {
|
|
29
|
+
try {
|
|
30
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
31
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
32
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
33
|
+
} catch {}
|
|
34
|
+
});
|
|
35
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
36
|
+
const r = await route.fetch();
|
|
37
|
+
const b = await r.json();
|
|
38
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
39
|
+
const mk = (alias) => ({
|
|
40
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
41
|
+
network_id: nid, project_dir: null,
|
|
42
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
43
|
+
});
|
|
44
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
45
|
+
mk('alpha·1'), mk('alpha·2'),
|
|
46
|
+
] } });
|
|
47
|
+
});
|
|
48
|
+
// NO messages → flowLinks=0 → crescent visible
|
|
49
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
50
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
51
|
+
const page = await ctx.newPage();
|
|
52
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
53
|
+
await page.waitForSelector('[data-topo-brand-canvas-mark]', { timeout: 15000 });
|
|
54
|
+
await page.waitForTimeout(800);
|
|
55
|
+
const data = await page.evaluate(() => {
|
|
56
|
+
const wrap = document.querySelector('[data-topo-brand-canvas-mark]');
|
|
57
|
+
const rect = wrap?.querySelector('rect[mask*="canvas-corner-mask"]');
|
|
58
|
+
const animate = rect?.querySelector('animate');
|
|
59
|
+
return {
|
|
60
|
+
breathAttr: wrap?.getAttribute('data-topo-brand-canvas-mark-breath'),
|
|
61
|
+
visibleAttr: wrap?.getAttribute('data-topo-brand-canvas-mark-visible'),
|
|
62
|
+
hasAnimate: !!animate,
|
|
63
|
+
attrName: animate?.getAttribute('attributeName') || null,
|
|
64
|
+
values: animate?.getAttribute('values') || null,
|
|
65
|
+
dur: animate?.getAttribute('dur') || null,
|
|
66
|
+
repeatCount: animate?.getAttribute('repeatCount') || null,
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
await browser.close();
|
|
70
|
+
return data;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const normal = await probe(false);
|
|
74
|
+
const reduced = await probe(true);
|
|
75
|
+
|
|
76
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
77
|
+
const sourceAnimateGated =
|
|
78
|
+
/\{!reducedMotion && \(\s*<animate attributeName="fill-opacity" values="0\.8;1;0\.8" dur="7s" repeatCount="indefinite" \/>\s*\)\}/.test(src);
|
|
79
|
+
const sourceAttrWired =
|
|
80
|
+
/data-topo-brand-canvas-mark-breath=\{reducedMotion \? 'false' : 'true'\}/.test(src);
|
|
81
|
+
|
|
82
|
+
const results = {
|
|
83
|
+
// motion enabled
|
|
84
|
+
normal_breath_true: normal?.breathAttr === 'true',
|
|
85
|
+
normal_visible_true: normal?.visibleAttr === 'true',
|
|
86
|
+
normal_has_animate: normal?.hasAnimate === true,
|
|
87
|
+
normal_attr_fill_op: normal?.attrName === 'fill-opacity',
|
|
88
|
+
normal_values_correct: normal?.values === '0.8;1;0.8',
|
|
89
|
+
normal_dur_7s: normal?.dur === '7s',
|
|
90
|
+
normal_repeat_indef: normal?.repeatCount === 'indefinite',
|
|
91
|
+
// prefers-reduced-motion
|
|
92
|
+
reduced_breath_false: reduced?.breathAttr === 'false',
|
|
93
|
+
reduced_no_animate: reduced?.hasAnimate === false,
|
|
94
|
+
reduced_visible_true: reduced?.visibleAttr === 'true', // crescent still visible, just no breath
|
|
95
|
+
// source
|
|
96
|
+
source_animate_gated: sourceAnimateGated,
|
|
97
|
+
source_attr_wired: sourceAttrWired,
|
|
98
|
+
};
|
|
99
|
+
const ok = Object.values(results).every(Boolean);
|
|
100
|
+
console.log(`${ok ? '✅' : '❌'} R528 crescent ambient breath:`,
|
|
101
|
+
JSON.stringify(results, null, 2),
|
|
102
|
+
'\n normal:', JSON.stringify(normal),
|
|
103
|
+
'\n reduced:', JSON.stringify(reduced));
|
|
104
|
+
process.exit(ok ? 0 : 1);
|