@sleep2agi/agent-network-dashboard 0.5.3-preview.20 → 0.5.3-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/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/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/{0bh3bd_k4cou9.js → 08.p955zvm-z-.js} +1 -1
- package/.next/static/chunks/0a3myvz04olik.js +1 -0
- package/.next/static/chunks/0mdrwmj6j8tr9.js +1 -0
- package/.next/static/chunks/0xxjzk4uj.8js.js +4 -0
- package/.next/static/chunks/17if82x7mcn4j.css +2 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +4990 -178
- package/app/globals.css +144 -7
- package/package.json +4 -4
- 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-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-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-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-click-ripple-glow-test.mjs +86 -0
- package/scripts/topo-click-ripple-halo-layers-test.mjs +79 -0
- package/scripts/topo-click-ripple-sw-test.mjs +110 -0
- package/scripts/topo-cluster-count-attr-test.mjs +80 -0
- package/scripts/topo-crescent-breath-test.mjs +104 -0
- package/scripts/topo-crescent-recede-test.mjs +111 -0
- package/scripts/topo-dense-alias-halo-layers-test.mjs +80 -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-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-halo-chat-gate-test.mjs +72 -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-amplify-test.mjs +139 -0
- package/scripts/topo-hub-highlight-brightness-test.mjs +84 -0
- package/scripts/topo-hub-highlight-fill-transition-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-highlight-recede-test.mjs +144 -0
- package/scripts/topo-hub-highlight-theme-fill-test.mjs +83 -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-idle-breath-test.mjs +7 -2
- package/scripts/topo-hub-recede-test.mjs +124 -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-halo-layers-test.mjs +82 -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-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-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-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-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-halo-layers-test.mjs +23 -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-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-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-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-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-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-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-recede-test.mjs +114 -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-brightness-test.mjs +83 -0
- package/scripts/topo-zoom-level-color-test.mjs +105 -0
- package/scripts/topo-zoom-level-halo-layers-test.mjs +78 -0
- package/.next/static/chunks/0.s1q59.w46yn.js +0 -4
- package/.next/static/chunks/06f643qjk~ayp.js +0 -1
- package/.next/static/chunks/0m-5_1vuw.lxb.js +0 -1
- package/.next/static/chunks/0m.1mvl~t.avc.css +0 -2
- /package/.next/static/{D60rGoeOKUed7uGrc-7wS → IANqjY6wNx4TFsHE-0g9m}/_buildManifest.js +0 -0
- /package/.next/static/{D60rGoeOKUed7uGrc-7wS → IANqjY6wNx4TFsHE-0g9m}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{D60rGoeOKUed7uGrc-7wS → IANqjY6wNx4TFsHE-0g9m}/_ssgManifest.js +0 -0
|
@@ -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,80 @@
|
|
|
1
|
+
/* Round 512 verification: root svg surfaces `data-topo-cluster-count`
|
|
2
|
+
* (14th attr in canvas state surface set). Paired with R469 fleet
|
|
3
|
+
* numerics + R502 categorical density.
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - grid layout: data-topo-cluster-count = groupBoxes.length (≥ 1)
|
|
7
|
+
* - ring layout: data-topo-cluster-count = '0' (groupBoxes is empty)
|
|
8
|
+
* - orphan-band fixture: cluster count includes the orphan band
|
|
9
|
+
*
|
|
10
|
+
* Tests across 2 fixtures × 2 layouts.
|
|
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
|
+
async function probe({ layout, sessions, label }) {
|
|
19
|
+
const browser = await chromium.launch({ headless: true });
|
|
20
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
21
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
22
|
+
await ctx.addInitScript((l) => {
|
|
23
|
+
try {
|
|
24
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
25
|
+
localStorage.setItem('anet-topo-layout', l);
|
|
26
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
27
|
+
} catch {}
|
|
28
|
+
}, layout);
|
|
29
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
30
|
+
const r = await route.fetch();
|
|
31
|
+
const b = await r.json();
|
|
32
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
33
|
+
const mk = (alias, status) => ({
|
|
34
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
35
|
+
network_id: nid, project_dir: null,
|
|
36
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
37
|
+
});
|
|
38
|
+
await route.fulfill({ response: r, json: { ...b, sessions: sessions.map(s => mk(s.alias, s.status)) } });
|
|
39
|
+
});
|
|
40
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
41
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
42
|
+
const page = await ctx.newPage();
|
|
43
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
44
|
+
await page.waitForSelector('svg[data-topo-cluster-count]', { timeout: 15000 });
|
|
45
|
+
await page.waitForTimeout(1500);
|
|
46
|
+
const count = await page.evaluate(() =>
|
|
47
|
+
document.querySelector('svg[viewBox="0 0 1000 680"]')?.getAttribute('data-topo-cluster-count')
|
|
48
|
+
);
|
|
49
|
+
await browser.close();
|
|
50
|
+
return { label, count };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Fixture A: 2 prefix groups (alpha×3 + beta×2) + 3 orphans
|
|
54
|
+
const fixtureA = [
|
|
55
|
+
{ alias: 'alpha·1', status: 'working' },
|
|
56
|
+
{ alias: 'alpha·2', status: 'idle' },
|
|
57
|
+
{ alias: 'alpha·3', status: 'idle' },
|
|
58
|
+
{ alias: 'beta·1', status: 'working' },
|
|
59
|
+
{ alias: 'beta·2', status: 'idle' },
|
|
60
|
+
{ alias: 'zeta', status: 'idle' },
|
|
61
|
+
{ alias: 'omega', status: 'idle' },
|
|
62
|
+
{ alias: 'lonely', status: 'idle' },
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
const aGrid = await probe({ layout: 'grid', sessions: fixtureA, label: 'grid+2prefix+3orph' });
|
|
66
|
+
const aRing = await probe({ layout: 'ring', sessions: fixtureA, label: 'ring+same fixture' });
|
|
67
|
+
|
|
68
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
69
|
+
const sourceWired = /data-topo-cluster-count=\{groupBoxes\.length\}/.test(src);
|
|
70
|
+
|
|
71
|
+
const results = {
|
|
72
|
+
grid_returns_3: aGrid.count === '3', // 2 prefix groups + 1 orphan band
|
|
73
|
+
ring_returns_0: aRing.count === '0', // no group boxes in ring layout
|
|
74
|
+
source_wired: sourceWired,
|
|
75
|
+
};
|
|
76
|
+
const ok = Object.values(results).every(Boolean);
|
|
77
|
+
console.log(`${ok ? '✅' : '❌'} R512 cluster-count attr:`, JSON.stringify(results),
|
|
78
|
+
'\n grid:', JSON.stringify(aGrid),
|
|
79
|
+
'\n ring:', JSON.stringify(aRing));
|
|
80
|
+
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);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/* Round 526 verification: brand crescent at canvas top-left gains
|
|
2
|
+
* focal-recede (4th anchor in family). Multiplies visible opacity by
|
|
3
|
+
* 0.7 when non-hub canvas surface is hovered.
|
|
4
|
+
*
|
|
5
|
+
* Test phases (flowLinks=0 state — crescent visible):
|
|
6
|
+
* 1. rest: opacity=0.35, recede attr='false', visible='true'
|
|
7
|
+
* 2. hover legend `idle` row: opacity=0.245 (0.35 × 0.7),
|
|
8
|
+
* recede attr='true'
|
|
9
|
+
* 3. mouseleave: opacity returns to 0.35, recede='false'
|
|
10
|
+
* 4. source-side regex confirms multiplicative opacity + attr wired
|
|
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: [
|
|
38
|
+
mk('alpha·1'), mk('alpha·2'), mk('alpha·3'),
|
|
39
|
+
] } });
|
|
40
|
+
});
|
|
41
|
+
// NO messages → flowLinks.length === 0 → crescent visible at opacity 0.35
|
|
42
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
43
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
44
|
+
const page = await ctx.newPage();
|
|
45
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
46
|
+
await page.waitForSelector('[data-topo-brand-canvas-mark]', { timeout: 15000 });
|
|
47
|
+
await page.waitForTimeout(800);
|
|
48
|
+
|
|
49
|
+
// Phase 1: rest
|
|
50
|
+
const rest = await page.evaluate(() => {
|
|
51
|
+
const m = document.querySelector('[data-topo-brand-canvas-mark]');
|
|
52
|
+
return {
|
|
53
|
+
opacity: parseFloat(m?.getAttribute('opacity') || '0'),
|
|
54
|
+
visible: m?.getAttribute('data-topo-brand-canvas-mark-visible'),
|
|
55
|
+
recede: m?.getAttribute('data-topo-brand-canvas-mark-recede'),
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Phase 2: hover legend `idle` row (sets hoveredStatus → recede)
|
|
60
|
+
await page.hover('[data-legend-row-label="idle"]');
|
|
61
|
+
await page.waitForTimeout(400);
|
|
62
|
+
const hover = await page.evaluate(() => {
|
|
63
|
+
const m = document.querySelector('[data-topo-brand-canvas-mark]');
|
|
64
|
+
return {
|
|
65
|
+
opacity: parseFloat(m?.getAttribute('opacity') || '0'),
|
|
66
|
+
visible: m?.getAttribute('data-topo-brand-canvas-mark-visible'),
|
|
67
|
+
recede: m?.getAttribute('data-topo-brand-canvas-mark-recede'),
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Phase 3: mouseleave
|
|
72
|
+
await page.mouse.move(900, 50);
|
|
73
|
+
await page.waitForTimeout(400);
|
|
74
|
+
const leave = await page.evaluate(() => {
|
|
75
|
+
const m = document.querySelector('[data-topo-brand-canvas-mark]');
|
|
76
|
+
return {
|
|
77
|
+
opacity: parseFloat(m?.getAttribute('opacity') || '0'),
|
|
78
|
+
recede: m?.getAttribute('data-topo-brand-canvas-mark-recede'),
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await browser.close();
|
|
83
|
+
|
|
84
|
+
// Source regex
|
|
85
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
86
|
+
const sourceOpacityWired =
|
|
87
|
+
/opacity=\{\(flowLinks\.length === 0 \? 0\.35 : 0\) \* \(\s*\(hoveredAlias \|\| hoveredEdgeKey \|\| hoveredGroupLabel \|\|\s*hoveredStatus \|\| hoveredVendor\) && !hoveredHub \? 0\.7 : 1\s*\)\}/.test(src);
|
|
88
|
+
const sourceAttrWired =
|
|
89
|
+
/data-topo-brand-canvas-mark-recede=\{\s*\(hoveredAlias \|\| hoveredEdgeKey \|\| hoveredGroupLabel \|\|\s*hoveredStatus \|\| hoveredVendor\) && !hoveredHub \? 'true' : 'false'\s*\}/.test(src);
|
|
90
|
+
|
|
91
|
+
const approxEq = (a, b, tol = 0.001) => Math.abs(a - b) < tol;
|
|
92
|
+
|
|
93
|
+
const results = {
|
|
94
|
+
rest_opacity_035: approxEq(rest?.opacity, 0.35),
|
|
95
|
+
rest_visible_true: rest?.visible === 'true',
|
|
96
|
+
rest_recede_false: rest?.recede === 'false',
|
|
97
|
+
hover_opacity_0245: approxEq(hover?.opacity, 0.245),
|
|
98
|
+
hover_recede_true: hover?.recede === 'true',
|
|
99
|
+
hover_visible_still: hover?.visible === 'true', // crescent should still be visible
|
|
100
|
+
leave_opacity_035: approxEq(leave?.opacity, 0.35),
|
|
101
|
+
leave_recede_false: leave?.recede === 'false',
|
|
102
|
+
source_opacity_wired: sourceOpacityWired,
|
|
103
|
+
source_attr_wired: sourceAttrWired,
|
|
104
|
+
};
|
|
105
|
+
const ok = Object.values(results).every(Boolean);
|
|
106
|
+
console.log(`${ok ? '✅' : '❌'} R526 crescent focal-recede:`,
|
|
107
|
+
JSON.stringify(results, null, 2),
|
|
108
|
+
'\n rest:', JSON.stringify(rest),
|
|
109
|
+
'\n hover:', JSON.stringify(hover),
|
|
110
|
+
'\n leave:', JSON.stringify(leave));
|
|
111
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* Round 680 — dense plain-text alias (the >16-node fallback label)
|
|
2
|
+
* extends from group-hover:-translate-y geometry-only to 2-layer
|
|
3
|
+
* drop-shadow at status.primary tint with 2+4 stride, alpha 80/40.
|
|
4
|
+
* Closes the dense-mode alias hover signature parity with normal-
|
|
5
|
+
* mode card label (R645). 39th anchor in family — first dense-mode
|
|
6
|
+
* anchor.
|
|
7
|
+
*
|
|
8
|
+
* Source assertions:
|
|
9
|
+
* - filter uses status.primary at 0x80 + 0x40 with 2+4 stride,
|
|
10
|
+
* gated on hoveredAlias === session.alias
|
|
11
|
+
* - data-node-dense-alias-text-halo-layers attr toggles '2' ↔ '0'
|
|
12
|
+
* - transition extends with 'filter 200ms ease-out'
|
|
13
|
+
*
|
|
14
|
+
* Runtime assertions:
|
|
15
|
+
* - dense alias labels present (>16 nodes)
|
|
16
|
+
* - all rest: halo-layers='0'
|
|
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
|
+
// 18 nodes triggers dense fallback (>16 nodes)
|
|
44
|
+
await route.fulfill({ response: r, json: { ...b, sessions: Array.from({ length: 18 }, (_, i) => mk(`a·${i + 1}`)) } });
|
|
45
|
+
});
|
|
46
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
47
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
48
|
+
const page = await ctx.newPage();
|
|
49
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
50
|
+
await page.waitForSelector('[data-node-dense-alias-text-halo-layers]', { timeout: 15000, state: 'attached' });
|
|
51
|
+
await page.waitForTimeout(500);
|
|
52
|
+
|
|
53
|
+
const restState = await page.evaluate(() => {
|
|
54
|
+
return Array.from(document.querySelectorAll('[data-node-dense-alias-text]')).map(el => ({
|
|
55
|
+
alias: el.getAttribute('data-node-dense-alias-text'),
|
|
56
|
+
layers: el.getAttribute('data-node-dense-alias-text-halo-layers'),
|
|
57
|
+
}));
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
await browser.close();
|
|
61
|
+
|
|
62
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
63
|
+
const sourceFilter = /filter: hoveredAlias === session\.alias\s*\?\s*`drop-shadow\(0 0 2px \$\{status\.primary\}80\) drop-shadow\(0 0 4px \$\{status\.primary\}40\)`/.test(src);
|
|
64
|
+
const sourceLayersAttr = /data-node-dense-alias-text-halo-layers=\{hoveredAlias === session\.alias \? '2' : '0'\}/.test(src);
|
|
65
|
+
const sourceTransition = /transition: 'transform 200ms ease-out, fill 300ms ease-out, filter 200ms ease-out'/.test(src);
|
|
66
|
+
|
|
67
|
+
const restAllZero = restState.every(e => e.layers === '0');
|
|
68
|
+
|
|
69
|
+
const results = {
|
|
70
|
+
dense_aliases_present: restState.length >= 10, // 18 nodes should yield ~18 dense labels
|
|
71
|
+
rest_all_layers_zero: restAllZero,
|
|
72
|
+
source_filter: sourceFilter,
|
|
73
|
+
source_layers_attr: sourceLayersAttr,
|
|
74
|
+
source_transition: sourceTransition,
|
|
75
|
+
};
|
|
76
|
+
const ok = Object.values(results).every(Boolean);
|
|
77
|
+
console.log(`${ok ? '✅' : '❌'} R680 dense plain-text alias multi-layer halo (first dense-mode anchor):`,
|
|
78
|
+
JSON.stringify(results, null, 2),
|
|
79
|
+
`\n count: ${restState.length}, sample: ${JSON.stringify(restState.slice(0, 3))}`);
|
|
80
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/* Round 603 — edge-badge CIRCLE stacks brightness(1.15) onto
|
|
2
|
+
* R534/R480 drop-shadow on hover/pin/hot. 5th hover axis on
|
|
3
|
+
* the badge ring; brings circle brightness to parity with the
|
|
4
|
+
* R570 digit brightness within the same edge-badge unit.
|
|
5
|
+
*
|
|
6
|
+
* Test phases:
|
|
7
|
+
* 1. mock 1 message → 1 flowLink → edge-badge renders
|
|
8
|
+
* 2. rest: filter='none', brightness-attr='1'
|
|
9
|
+
* 3. computed transition-property contains 'filter'
|
|
10
|
+
* 4. source: stacked filter conditional includes brightness +
|
|
11
|
+
* data-attr extension
|
|
12
|
+
*/
|
|
13
|
+
import { chromium } from 'playwright';
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
|
|
16
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
17
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
18
|
+
|
|
19
|
+
const browser = await chromium.launch({ headless: true });
|
|
20
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
21
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
22
|
+
await ctx.addInitScript(() => {
|
|
23
|
+
try {
|
|
24
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
25
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
26
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
27
|
+
} catch {}
|
|
28
|
+
});
|
|
29
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
30
|
+
const r = await route.fetch();
|
|
31
|
+
const b = await r.json();
|
|
32
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
33
|
+
const mk = (alias) => ({
|
|
34
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
35
|
+
network_id: nid, project_dir: null,
|
|
36
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
37
|
+
});
|
|
38
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
39
|
+
});
|
|
40
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
41
|
+
{ from_alias: 'a·1', to_alias: 'a·2', content: 'hi', created_at: fresh },
|
|
42
|
+
] } }));
|
|
43
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
44
|
+
const page = await ctx.newPage();
|
|
45
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
46
|
+
await page.waitForSelector('[data-edge-badge-brightness]', { timeout: 15000, state: 'attached' });
|
|
47
|
+
await page.waitForTimeout(500);
|
|
48
|
+
|
|
49
|
+
const rest = await page.evaluate(() => {
|
|
50
|
+
const el = document.querySelector('[data-edge-badge-brightness]');
|
|
51
|
+
if (!el) return null;
|
|
52
|
+
const cs = getComputedStyle(el);
|
|
53
|
+
return {
|
|
54
|
+
filter: cs.filter,
|
|
55
|
+
transitionProperty: cs.transitionProperty,
|
|
56
|
+
brightnessAttr: el.getAttribute('data-edge-badge-brightness'),
|
|
57
|
+
glowAttr: el.getAttribute('data-edge-badge-glow'),
|
|
58
|
+
liftedAttr: el.getAttribute('data-edge-badge-lifted'),
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
await browser.close();
|
|
63
|
+
|
|
64
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
65
|
+
const sourceFilter = /filter: \(isHoveredEdge \|\| isPinned\)\s*\?\s*`drop-shadow\(0 0 3px \$\{pal\.legendAccent\}99\) brightness\(1\.15\)`\s*:\s*isHot\s*\?\s*`drop-shadow\(0 0 3px \$\{hotStroke\}80\) brightness\(1\.15\)`\s*:\s*undefined/.test(src);
|
|
66
|
+
const sourceAttr = /data-edge-badge-brightness=\{\(isHoveredEdge \|\| isPinned \|\| isHot\) \? '1\.15' : '1'\}/.test(src);
|
|
67
|
+
|
|
68
|
+
const results = {
|
|
69
|
+
badge_present: !!rest,
|
|
70
|
+
rest_filter_none: rest?.filter === 'none',
|
|
71
|
+
rest_brightness_1: rest?.brightnessAttr === '1',
|
|
72
|
+
rest_glow_false: rest?.glowAttr === 'false',
|
|
73
|
+
rest_lifted_false: rest?.liftedAttr === 'false',
|
|
74
|
+
transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
|
|
75
|
+
source_filter: sourceFilter,
|
|
76
|
+
source_attr: sourceAttr,
|
|
77
|
+
};
|
|
78
|
+
const ok = Object.values(results).every(Boolean);
|
|
79
|
+
console.log(`${ok ? '✅' : '❌'} R603 edge-badge circle brightness (5th axis, ring↔digit parity):`,
|
|
80
|
+
JSON.stringify(results, null, 2),
|
|
81
|
+
`\n rest: ${JSON.stringify(rest)}`);
|
|
82
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/* Round 633 — edge-badge CIRCLE joins the hot-pulse family at the
|
|
2
|
+
* geometric axis. SMIL stroke-width 2 ↔ 2.5 over 3s ease-in-out,
|
|
3
|
+
* gated `isHot && !reducedMotion`. In lockstep with R632 digit
|
|
4
|
+
* opacity pulse. 3rd anchor in hot-pulse family.
|
|
5
|
+
*
|
|
6
|
+
* Test phases:
|
|
7
|
+
* 1. cold edge (mock 3 messages) → no hot-pulse, sw=1.25 attr
|
|
8
|
+
* doesn't exist as SMIL animate child
|
|
9
|
+
* 2. hot edge (mock 12 messages) → SMIL animate child present
|
|
10
|
+
* with attributeName='stroke-width', values='2;2.5;2',
|
|
11
|
+
* dur='3s', calcMode='spline'
|
|
12
|
+
* 3. hot-pulse attr === 'on' on hot edge
|
|
13
|
+
* 4. source: SMIL animate gated on `isHot && !reducedMotion`,
|
|
14
|
+
* stroke-width values='2;2.5;2' explicit
|
|
15
|
+
*/
|
|
16
|
+
import { chromium } from 'playwright';
|
|
17
|
+
import { readFileSync } from 'node:fs';
|
|
18
|
+
|
|
19
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
20
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
21
|
+
|
|
22
|
+
const browser = await chromium.launch({ headless: true });
|
|
23
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
24
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
25
|
+
await ctx.addInitScript(() => {
|
|
26
|
+
try {
|
|
27
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
28
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
29
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
30
|
+
} catch {}
|
|
31
|
+
});
|
|
32
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
33
|
+
const r = await route.fetch();
|
|
34
|
+
const b = await r.json();
|
|
35
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
36
|
+
const mk = (alias) => ({
|
|
37
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
38
|
+
network_id: nid, project_dir: null,
|
|
39
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
40
|
+
});
|
|
41
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
42
|
+
});
|
|
43
|
+
// 12 messages → isHot (count ≥ 10 threshold)
|
|
44
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages:
|
|
45
|
+
Array.from({ length: 12 }, (_, i) => ({
|
|
46
|
+
from_alias: 'a·1', to_alias: 'a·2', content: `msg-${i}`, created_at: fresh,
|
|
47
|
+
}))
|
|
48
|
+
} }));
|
|
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-edge-badge-hot-pulse]', { timeout: 15000, state: 'attached' });
|
|
53
|
+
await page.waitForTimeout(500);
|
|
54
|
+
|
|
55
|
+
const hot = await page.evaluate(() => {
|
|
56
|
+
const el = document.querySelector('[data-edge-badge-hot-pulse="on"]');
|
|
57
|
+
if (!el) return null;
|
|
58
|
+
const animates = Array.from(el.querySelectorAll('animate'));
|
|
59
|
+
return {
|
|
60
|
+
hotPulseAttr: el.getAttribute('data-edge-badge-hot-pulse'),
|
|
61
|
+
glowAttr: el.getAttribute('data-edge-badge-glow'),
|
|
62
|
+
strokeWidthAttr: el.getAttribute('stroke-width'),
|
|
63
|
+
animateCount: animates.length,
|
|
64
|
+
animateAttrs: animates.map(a => ({
|
|
65
|
+
attr: a.getAttribute('attributeName'),
|
|
66
|
+
dur: a.getAttribute('dur'),
|
|
67
|
+
vals: a.getAttribute('values'),
|
|
68
|
+
calc: a.getAttribute('calcMode'),
|
|
69
|
+
spl: a.getAttribute('keySplines'),
|
|
70
|
+
rep: a.getAttribute('repeatCount'),
|
|
71
|
+
})),
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
await browser.close();
|
|
76
|
+
|
|
77
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
78
|
+
const sourceAnimate = /\{isHot && !reducedMotion && \(\s*<animate\s+attributeName="stroke-width"\s+values="2;2\.5;2"\s+dur="3s"\s+calcMode="spline"\s+keyTimes="0;0\.5;1"\s+keySplines="0\.42 0 0\.58 1;0\.42 0 0\.58 1"\s+repeatCount="indefinite"\s*\/>\s*\)\}/.test(src);
|
|
79
|
+
const sourceAttr = /data-edge-badge-hot-pulse=\{isHot && !reducedMotion \? 'on' : 'off'\}/.test(src);
|
|
80
|
+
|
|
81
|
+
const swAnimate = hot?.animateAttrs?.find(a => a.attr === 'stroke-width');
|
|
82
|
+
const results = {
|
|
83
|
+
hot_circle_present: !!hot,
|
|
84
|
+
hot_pulse_attr_on: hot?.hotPulseAttr === 'on',
|
|
85
|
+
hot_glow_amber: hot?.glowAttr === 'hot',
|
|
86
|
+
hot_has_smil_sw: swAnimate != null,
|
|
87
|
+
hot_sw_values: swAnimate?.vals === '2;2.5;2',
|
|
88
|
+
hot_sw_dur_3s: swAnimate?.dur === '3s',
|
|
89
|
+
hot_sw_calc_spline: swAnimate?.calc === 'spline',
|
|
90
|
+
hot_sw_spline_ease: swAnimate?.spl === '0.42 0 0.58 1;0.42 0 0.58 1',
|
|
91
|
+
hot_sw_rep_indef: swAnimate?.rep === 'indefinite',
|
|
92
|
+
hot_attr_sw_2: hot?.strokeWidthAttr === '2',
|
|
93
|
+
source_smil_gated: sourceAnimate,
|
|
94
|
+
source_attr_gated: sourceAttr,
|
|
95
|
+
};
|
|
96
|
+
const ok = Object.values(results).every(Boolean);
|
|
97
|
+
console.log(`${ok ? '✅' : '❌'} R633 edge-badge CIRCLE hot-pulse stroke-width breath (3rd hot-pulse anchor):`,
|
|
98
|
+
JSON.stringify(results, null, 2),
|
|
99
|
+
`\n hot: ${JSON.stringify(hot)}`);
|
|
100
|
+
process.exit(ok ? 0 : 1);
|