@sleep2agi/agent-network-dashboard 0.5.3-preview.15 → 0.5.3-preview.151
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/0-0xscbvi_1df.js +1 -0
- package/.next/static/chunks/0-8bxlg9uqt.w.css +2 -0
- package/.next/static/chunks/0.g6l5qrv8vb0.js +1 -0
- package/.next/static/chunks/{0g21xro04lbjk.js → 04_da~p.dz9um.js} +1 -1
- package/.next/static/chunks/15~12t12e_bh-.js +4 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +4088 -174
- package/app/globals.css +58 -7
- package/package.json +4 -4
- package/scripts/topo-active-chrome-hover-text-test.mjs +107 -0
- package/scripts/topo-alias-chat-brightness-test.mjs +79 -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-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-brightness-test.mjs +80 -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-click-ripple-glow-test.mjs +86 -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-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-endpoint-gate-test.mjs +94 -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-particle-brightness-test.mjs +82 -0
- package/scripts/topo-edge-pill-glow-test.mjs +67 -0
- package/scripts/topo-edge-visible-brightness-test.mjs +84 -0
- package/scripts/topo-endpoint-ring-brightness-test.mjs +83 -0
- package/scripts/topo-filter-pill-glow-test.mjs +90 -0
- package/scripts/topo-fleet-density-tier-test.mjs +84 -0
- package/scripts/topo-flow-arrow-brightness-test.mjs +82 -0
- package/scripts/topo-flow-rail-brightness-test.mjs +80 -0
- package/scripts/topo-freshness-chip-fade-test.mjs +105 -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-chat-gate-test.mjs +77 -0
- package/scripts/topo-group-label-brightness-test.mjs +84 -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-digit-brightness-test.mjs +79 -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-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-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-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-self-filter-test.mjs +119 -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-legend-count-brightness-test.mjs +80 -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-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-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-more-footer-brightness-test.mjs +94 -0
- package/scripts/topo-node-alias-brightness-test.mjs +84 -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-hover-fw-test.mjs +99 -0
- package/scripts/topo-orphan-box-dash-test.mjs +89 -0
- package/scripts/topo-orphan-fill-opacity-test.mjs +91 -0
- package/scripts/topo-orphan-label-opacity-test.mjs +98 -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-pill-x-rotate-test.mjs +96 -0
- package/scripts/topo-pinned-aspect-test.mjs +89 -0
- package/scripts/topo-pip-brightness-test.mjs +85 -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-panel-hot-pulse-test.mjs +105 -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-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-rotate-test.mjs +85 -0
- package/scripts/topo-spoke-chat-gate-test.mjs +72 -0
- package/scripts/topo-starfield-hue-test.mjs +109 -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-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-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-zoom-buttons-brightness-test.mjs +94 -0
- package/scripts/topo-zoom-level-brightness-test.mjs +83 -0
- package/scripts/topo-zoom-level-color-test.mjs +105 -0
- package/.next/static/chunks/056n7oz45zp01.js +0 -1
- package/.next/static/chunks/0bud6.ic~l84v.js +0 -1
- package/.next/static/chunks/0m.1mvl~t.avc.css +0 -2
- package/.next/static/chunks/0qf8ynb6zk1~~.js +0 -4
- /package/.next/static/{gEFJytjHWAA9KfebCcNdi → E9jD1f6-mjQO7VWb-fwWh}/_buildManifest.js +0 -0
- /package/.next/static/{gEFJytjHWAA9KfebCcNdi → E9jD1f6-mjQO7VWb-fwWh}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{gEFJytjHWAA9KfebCcNdi → E9jD1f6-mjQO7VWb-fwWh}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/* Round 548 verification: title-block brand logo gains hover:scale-105
|
|
2
|
+
* delight gesture. Banked R547 Tailwind 4 pattern — probe cs.scale not
|
|
3
|
+
* cs.transform.
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. rest: scale='none'
|
|
7
|
+
* 2. hover: scale='1.05'
|
|
8
|
+
* 3. source-side regex confirms className + data-attr wired
|
|
9
|
+
*/
|
|
10
|
+
import { chromium } from 'playwright';
|
|
11
|
+
import { readFileSync } from 'node:fs';
|
|
12
|
+
|
|
13
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
14
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
15
|
+
|
|
16
|
+
const browser = await chromium.launch({ headless: true });
|
|
17
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
18
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
19
|
+
await ctx.addInitScript(() => {
|
|
20
|
+
try {
|
|
21
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
22
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
23
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
24
|
+
} catch {}
|
|
25
|
+
});
|
|
26
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
27
|
+
const r = await route.fetch();
|
|
28
|
+
const b = await r.json();
|
|
29
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
30
|
+
const mk = (alias) => ({
|
|
31
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
32
|
+
network_id: nid, project_dir: null,
|
|
33
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
34
|
+
});
|
|
35
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1')] } });
|
|
36
|
+
});
|
|
37
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
38
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
39
|
+
const page = await ctx.newPage();
|
|
40
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
41
|
+
await page.waitForSelector('[data-topo-brand-logo]', { timeout: 15000 });
|
|
42
|
+
await page.waitForTimeout(500);
|
|
43
|
+
|
|
44
|
+
const sel = '[data-topo-brand-logo]';
|
|
45
|
+
const rest = await page.evaluate((s) => {
|
|
46
|
+
const el = document.querySelector(s);
|
|
47
|
+
if (!el) return null;
|
|
48
|
+
const cs = getComputedStyle(el);
|
|
49
|
+
return {
|
|
50
|
+
attrScale: el.getAttribute('data-topo-brand-logo-hover-scale'),
|
|
51
|
+
scale: cs.scale,
|
|
52
|
+
rotate: cs.rotate,
|
|
53
|
+
};
|
|
54
|
+
}, sel);
|
|
55
|
+
|
|
56
|
+
await page.hover(sel);
|
|
57
|
+
await page.waitForTimeout(400);
|
|
58
|
+
const hover = await page.evaluate((s) => {
|
|
59
|
+
const el = document.querySelector(s);
|
|
60
|
+
if (!el) return null;
|
|
61
|
+
const cs = getComputedStyle(el);
|
|
62
|
+
return { scale: cs.scale };
|
|
63
|
+
}, sel);
|
|
64
|
+
|
|
65
|
+
await browser.close();
|
|
66
|
+
|
|
67
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
68
|
+
const sourceClassNameWired =
|
|
69
|
+
/className="shrink-0 transition-transform duration-200 ease-out hover:scale-105 transform-gpu"/.test(src);
|
|
70
|
+
const sourceAttrWired =
|
|
71
|
+
/data-topo-brand-logo-hover-scale="1\.05"/.test(src);
|
|
72
|
+
|
|
73
|
+
const results = {
|
|
74
|
+
rest_scale_none: rest?.scale === 'none' || rest?.scale === '1',
|
|
75
|
+
rest_attr_scale_105: rest?.attrScale === '1.05',
|
|
76
|
+
hover_scale_105: hover?.scale === '1.05',
|
|
77
|
+
source_classname: sourceClassNameWired,
|
|
78
|
+
source_attr: sourceAttrWired,
|
|
79
|
+
};
|
|
80
|
+
const ok = Object.values(results).every(Boolean);
|
|
81
|
+
console.log(`${ok ? '✅' : '❌'} R548 brand-logo hover-scale:`,
|
|
82
|
+
JSON.stringify(results, null, 2),
|
|
83
|
+
'\n rest:', JSON.stringify(rest),
|
|
84
|
+
'\n hover:', JSON.stringify(hover));
|
|
85
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* Round 618 — extend label card hover treatments (stroke +
|
|
2
|
+
* filter brightness) gate from hover-only to (hover || chat-
|
|
3
|
+
* target). 4th anchor in chat-target-gated brightness family.
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. mock 2 idle nodes → label cards render
|
|
7
|
+
* 2. rest (no hover, no chat): rest filter (shallow DS, NO
|
|
8
|
+
* brightness), brightness-attr='1', elevation='idle',
|
|
9
|
+
* chat-target='false'
|
|
10
|
+
* 3. computed transition-property contains 'filter'
|
|
11
|
+
* 4. source: stroke + filter conditionals include BOTH hover
|
|
12
|
+
* AND chat gates joined by `||`
|
|
13
|
+
*/
|
|
14
|
+
import { chromium } from 'playwright';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
|
|
17
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
18
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
19
|
+
|
|
20
|
+
const browser = await chromium.launch({ headless: true });
|
|
21
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
22
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
23
|
+
await ctx.addInitScript(() => {
|
|
24
|
+
try {
|
|
25
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
26
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
27
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
28
|
+
} catch {}
|
|
29
|
+
});
|
|
30
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
31
|
+
const r = await route.fetch();
|
|
32
|
+
const b = await r.json();
|
|
33
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
34
|
+
const mk = (alias) => ({
|
|
35
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
36
|
+
network_id: nid, project_dir: null,
|
|
37
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
38
|
+
});
|
|
39
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
40
|
+
});
|
|
41
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
42
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
43
|
+
const page = await ctx.newPage();
|
|
44
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
45
|
+
await page.waitForSelector('[data-node-label-card-chat-target]', { timeout: 15000, state: 'attached' });
|
|
46
|
+
await page.waitForTimeout(500);
|
|
47
|
+
|
|
48
|
+
const rest = await page.evaluate(() => {
|
|
49
|
+
const el = document.querySelector('[data-node-label-card-chat-target]');
|
|
50
|
+
if (!el) return null;
|
|
51
|
+
const cs = getComputedStyle(el);
|
|
52
|
+
return {
|
|
53
|
+
filter: cs.filter,
|
|
54
|
+
transitionProperty: cs.transitionProperty,
|
|
55
|
+
brightnessAttr: el.getAttribute('data-node-label-card-brightness'),
|
|
56
|
+
elevationAttr: el.getAttribute('data-node-label-card-elevation'),
|
|
57
|
+
chatTargetAttr: el.getAttribute('data-node-label-card-chat-target'),
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
await browser.close();
|
|
62
|
+
|
|
63
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
64
|
+
const sourceFilterOr = /filter: !reducedMotion && \(hoveredAlias === session\.alias \|\| chatAlias === session\.alias\)\s*\?\s*\(isLight/.test(src);
|
|
65
|
+
const sourceStrokeOr = /stroke=\{!reducedMotion && \(hoveredAlias === session\.alias \|\| chatAlias === session\.alias\)/.test(src);
|
|
66
|
+
const sourceAttrOr = /data-node-label-card-brightness=\{!reducedMotion && \(hoveredAlias === session\.alias \|\| chatAlias === session\.alias\) \? '1\.15' : '1'\}/.test(src);
|
|
67
|
+
const sourceChatAttr = /data-node-label-card-chat-target=\{chatAlias === session\.alias \? 'true' : 'false'\}/.test(src);
|
|
68
|
+
|
|
69
|
+
const results = {
|
|
70
|
+
card_present: !!rest,
|
|
71
|
+
rest_has_drop_shadow: /drop-shadow/.test(rest?.filter || ''),
|
|
72
|
+
rest_no_brightness: !/brightness/.test(rest?.filter || ''),
|
|
73
|
+
rest_brightness_1: rest?.brightnessAttr === '1',
|
|
74
|
+
rest_elevation_idle: rest?.elevationAttr === 'idle',
|
|
75
|
+
rest_chat_target_false: rest?.chatTargetAttr === 'false',
|
|
76
|
+
transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
|
|
77
|
+
source_filter_or: sourceFilterOr,
|
|
78
|
+
source_stroke_or: sourceStrokeOr,
|
|
79
|
+
source_attr_or: sourceAttrOr,
|
|
80
|
+
source_chat_attr: sourceChatAttr,
|
|
81
|
+
};
|
|
82
|
+
const ok = Object.values(results).every(Boolean);
|
|
83
|
+
console.log(`${ok ? '✅' : '❌'} R618 card chat-target brightness (chat-gated family 4th anchor):`,
|
|
84
|
+
JSON.stringify(results, null, 2),
|
|
85
|
+
`\n rest: ${JSON.stringify(rest)}`);
|
|
86
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* 🎯 Round 615 — 100th consecutive visible-polish round milestone.
|
|
2
|
+
* Chat-target ring stacks brightness(1.15) onto url(#topo-glow)
|
|
3
|
+
* on isChat=true. Introduces a NEW 4th brightness gate type:
|
|
4
|
+
* chat-target-gated.
|
|
5
|
+
*
|
|
6
|
+
* Test phases:
|
|
7
|
+
* 1. mock 2 idle nodes → chat ring renders (opacity 0 at rest)
|
|
8
|
+
* 2. rest (no chat target): filter='none', brightness-attr='1',
|
|
9
|
+
* active='false'
|
|
10
|
+
* 3. computed transition-property contains 'filter'
|
|
11
|
+
* 4. source: stacked filter conditional + data-attr
|
|
12
|
+
*/
|
|
13
|
+
import { chromium } from 'playwright';
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
|
|
16
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
17
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
18
|
+
|
|
19
|
+
const browser = await chromium.launch({ headless: true });
|
|
20
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
21
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
22
|
+
await ctx.addInitScript(() => {
|
|
23
|
+
try {
|
|
24
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
25
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
26
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
27
|
+
} catch {}
|
|
28
|
+
});
|
|
29
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
30
|
+
const r = await route.fetch();
|
|
31
|
+
const b = await r.json();
|
|
32
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
33
|
+
const mk = (alias) => ({
|
|
34
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
35
|
+
network_id: nid, project_dir: null,
|
|
36
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
37
|
+
});
|
|
38
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
39
|
+
});
|
|
40
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
41
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
42
|
+
const page = await ctx.newPage();
|
|
43
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
44
|
+
await page.waitForSelector('[data-chat-target-ring]', { timeout: 15000, state: 'attached' });
|
|
45
|
+
await page.waitForTimeout(500);
|
|
46
|
+
|
|
47
|
+
const rest = await page.evaluate(() => {
|
|
48
|
+
const el = document.querySelector('[data-chat-target-ring]');
|
|
49
|
+
if (!el) return null;
|
|
50
|
+
const cs = getComputedStyle(el);
|
|
51
|
+
return {
|
|
52
|
+
filter: cs.filter,
|
|
53
|
+
opacity: cs.opacity,
|
|
54
|
+
transitionProperty: cs.transitionProperty,
|
|
55
|
+
brightnessAttr: el.getAttribute('data-node-chat-ring-brightness'),
|
|
56
|
+
activeAttr: el.getAttribute('data-chat-target-active'),
|
|
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: isChat\s*\?\s*\(isLight\s*\?\s*'brightness\(1\.15\)'\s*:\s*'url\(#topo-glow\) brightness\(1\.15\)'\)\s*:\s*undefined/.test(src);
|
|
64
|
+
const sourceAttr = /data-node-chat-ring-brightness=\{isChat \? '1\.15' : '1'\}/.test(src);
|
|
65
|
+
|
|
66
|
+
const results = {
|
|
67
|
+
ring_present: !!rest,
|
|
68
|
+
rest_filter_none: rest?.filter === 'none',
|
|
69
|
+
rest_opacity_zero: parseFloat(rest?.opacity || '1') === 0,
|
|
70
|
+
rest_brightness_1: rest?.brightnessAttr === '1',
|
|
71
|
+
rest_active_false: rest?.activeAttr === 'false',
|
|
72
|
+
transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
|
|
73
|
+
source_filter: sourceFilter,
|
|
74
|
+
source_attr: sourceAttr,
|
|
75
|
+
};
|
|
76
|
+
const ok = Object.values(results).every(Boolean);
|
|
77
|
+
console.log(`${ok ? '✅' : '❌'} 🎯 R615 chat-target ring brightness (NEW chat-target-gated brightness, 100 rounds milestone):`,
|
|
78
|
+
JSON.stringify(results, null, 2),
|
|
79
|
+
`\n rest: ${JSON.stringify(rest)}`);
|
|
80
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/* Round 637 — chat-target ring filter gains a status-tinted
|
|
2
|
+
* drop-shadow halo. The halo colour now matches the ring's stroke
|
|
3
|
+
* (status.primary): green for working, teal for idle, slate for
|
|
4
|
+
* offline. Chromatic identity of the chat partner reinforced
|
|
5
|
+
* across stroke + halo.
|
|
6
|
+
*
|
|
7
|
+
* Test phases:
|
|
8
|
+
* 1. mock idle node → click to open chat → ring filter contains
|
|
9
|
+
* drop-shadow with idle teal #14b8a6 + brightness(1.15) +
|
|
10
|
+
* url(#topo-glow) on cyber
|
|
11
|
+
* 2. data-chat-target-ring-halo-color === status.primary hex
|
|
12
|
+
* 3. transition still includes 'filter'
|
|
13
|
+
* 4. source: filter expression uses status.primary in drop-shadow
|
|
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
|
+
const browser = await chromium.launch({ headless: true });
|
|
22
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
23
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
24
|
+
await ctx.addInitScript(() => {
|
|
25
|
+
try {
|
|
26
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
27
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
28
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
29
|
+
} catch {}
|
|
30
|
+
});
|
|
31
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
32
|
+
const r = await route.fetch();
|
|
33
|
+
const b = await r.json();
|
|
34
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
35
|
+
const mk = (alias, status) => ({
|
|
36
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
37
|
+
network_id: nid, project_dir: null,
|
|
38
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
39
|
+
});
|
|
40
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
41
|
+
mk('a·1', 'idle'),
|
|
42
|
+
mk('a·2', 'working'),
|
|
43
|
+
] } });
|
|
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-chat-target-ring]', { timeout: 15000, state: 'attached' });
|
|
50
|
+
await page.waitForTimeout(500);
|
|
51
|
+
|
|
52
|
+
// rest: no chat — halo color attr should be 'none'
|
|
53
|
+
const restAttrs = await page.evaluate(() => {
|
|
54
|
+
const el = document.querySelector('[data-chat-target-ring]');
|
|
55
|
+
if (!el) return null;
|
|
56
|
+
return {
|
|
57
|
+
haloColor: el.getAttribute('data-chat-target-ring-halo-color'),
|
|
58
|
+
active: el.getAttribute('data-chat-target-active'),
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// open chat with a·1 (idle)
|
|
63
|
+
await page.click('[data-node="a·1"]', { force: true });
|
|
64
|
+
await page.waitForTimeout(400);
|
|
65
|
+
|
|
66
|
+
const chatState = await page.evaluate(() => {
|
|
67
|
+
const node = document.querySelector('[data-node="a·1"]');
|
|
68
|
+
if (!node) return null;
|
|
69
|
+
const ring = node.querySelector('[data-chat-target-ring]');
|
|
70
|
+
if (!ring) return null;
|
|
71
|
+
const cs = getComputedStyle(ring);
|
|
72
|
+
return {
|
|
73
|
+
haloColor: ring.getAttribute('data-chat-target-ring-halo-color'),
|
|
74
|
+
active: ring.getAttribute('data-chat-target-active'),
|
|
75
|
+
stroke: ring.getAttribute('stroke') || cs.stroke,
|
|
76
|
+
filter: cs.filter,
|
|
77
|
+
transition:cs.transitionProperty,
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
await browser.close();
|
|
82
|
+
|
|
83
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
84
|
+
const sourceLightFilter = /`drop-shadow\(0 0 3px \$\{status\.primary\}40\) brightness\(1\.15\)`/.test(src);
|
|
85
|
+
const sourceCyberFilter = /`drop-shadow\(0 0 3px \$\{status\.primary\}40\) url\(#topo-glow\) brightness\(1\.15\)`/.test(src);
|
|
86
|
+
const sourceHaloAttr = /data-chat-target-ring-halo-color=\{isChat \? status\.primary : 'none'\}/.test(src);
|
|
87
|
+
|
|
88
|
+
const results = {
|
|
89
|
+
rest_halo_color_none: restAttrs?.haloColor === 'none',
|
|
90
|
+
rest_active_false: restAttrs?.active === 'false',
|
|
91
|
+
chat_present: !!chatState,
|
|
92
|
+
chat_active_true: chatState?.active === 'true',
|
|
93
|
+
chat_halo_color_set: /^#[0-9a-f]{6,8}$/i.test(chatState?.haloColor || ''),
|
|
94
|
+
chat_filter_has_dropshadow: /drop-shadow/.test(chatState?.filter || ''),
|
|
95
|
+
chat_filter_has_brightness: /brightness/.test(chatState?.filter || ''),
|
|
96
|
+
chat_transition_has_filter: /filter/.test(chatState?.transition || ''),
|
|
97
|
+
source_light_filter: sourceLightFilter,
|
|
98
|
+
source_cyber_filter: sourceCyberFilter,
|
|
99
|
+
source_halo_attr: sourceHaloAttr,
|
|
100
|
+
};
|
|
101
|
+
const ok = Object.values(results).every(Boolean);
|
|
102
|
+
console.log(`${ok ? '✅' : '❌'} R637 chat-target ring status-tinted halo (chromatic identity completion):`,
|
|
103
|
+
JSON.stringify(results, null, 2),
|
|
104
|
+
`\n rest: ${JSON.stringify(restAttrs)}`,
|
|
105
|
+
`\n chat: ${JSON.stringify(chatState)}`);
|
|
106
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/* Round 630 — chat-target ring gains a SECOND breath axis:
|
|
2
|
+
* stroke-width 2.5↔2.75 over 3s, in lockstep with the existing
|
|
3
|
+
* R120 opacity breath (0.72↔0.95 / 0.82↔1.0). Doubles the 呼吸感
|
|
4
|
+
* — the ring "swells" as it brightens, then settles as it dims.
|
|
5
|
+
* Gated `!reducedMotion && isChat`. R51 sentinel-safe (sw range
|
|
6
|
+
* [2.5, 2.75] stays clear of reserved {1.5, 3}).
|
|
7
|
+
*
|
|
8
|
+
* Test phases:
|
|
9
|
+
* 1. mock 2 nodes → no chat: chat-target ring opacity=0,
|
|
10
|
+
* sw-breath attr 'off', NO <animate> children
|
|
11
|
+
* 2. click a node → opens ChatPopover for that alias →
|
|
12
|
+
* chat-target ring becomes isChat → sw-breath attr 'on',
|
|
13
|
+
* TWO <animate> children present (one opacity + one
|
|
14
|
+
* stroke-width, both dur='3s' repeatCount='indefinite')
|
|
15
|
+
* 3. source: stroke-width animate uses values '2.5;2.75;2.5'
|
|
16
|
+
* and sits inside the same `!reducedMotion && isChat`
|
|
17
|
+
* gate as the opacity animate
|
|
18
|
+
*/
|
|
19
|
+
import { chromium } from 'playwright';
|
|
20
|
+
import { readFileSync } from 'node:fs';
|
|
21
|
+
|
|
22
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
23
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
24
|
+
|
|
25
|
+
const browser = await chromium.launch({ headless: true });
|
|
26
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
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: [mk('a·1'), mk('a·2')] } });
|
|
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-chat-target-ring]', { timeout: 15000, state: 'attached' });
|
|
51
|
+
await page.waitForTimeout(500);
|
|
52
|
+
|
|
53
|
+
const restState = await page.evaluate(() => {
|
|
54
|
+
const el = document.querySelector('[data-chat-target-ring]');
|
|
55
|
+
if (!el) return null;
|
|
56
|
+
return {
|
|
57
|
+
active: el.getAttribute('data-chat-target-active'),
|
|
58
|
+
breath: el.getAttribute('data-chat-target-breath'),
|
|
59
|
+
swBreath: el.getAttribute('data-chat-target-ring-sw-breath'),
|
|
60
|
+
animateCount: el.querySelectorAll('animate').length,
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Click a node to open chat → that node's chat-target ring activates
|
|
65
|
+
await page.click('[data-node="a·1"]', { force: true });
|
|
66
|
+
await page.waitForTimeout(400);
|
|
67
|
+
|
|
68
|
+
const activeState = await page.evaluate(() => {
|
|
69
|
+
// Find the chat-target ring of node a·1 — it's inside g[data-node="a·1"]
|
|
70
|
+
const node = document.querySelector('[data-node="a·1"]');
|
|
71
|
+
if (!node) return null;
|
|
72
|
+
const ring = node.querySelector('[data-chat-target-ring]');
|
|
73
|
+
if (!ring) return null;
|
|
74
|
+
const animates = Array.from(ring.querySelectorAll('animate'));
|
|
75
|
+
return {
|
|
76
|
+
active: ring.getAttribute('data-chat-target-active'),
|
|
77
|
+
breath: ring.getAttribute('data-chat-target-breath'),
|
|
78
|
+
swBreath: ring.getAttribute('data-chat-target-ring-sw-breath'),
|
|
79
|
+
animateCount: animates.length,
|
|
80
|
+
animateAttrs: animates.map(a => ({
|
|
81
|
+
attr: a.getAttribute('attributeName'),
|
|
82
|
+
dur: a.getAttribute('dur'),
|
|
83
|
+
vals: a.getAttribute('values'),
|
|
84
|
+
rep: a.getAttribute('repeatCount'),
|
|
85
|
+
})),
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
await browser.close();
|
|
90
|
+
|
|
91
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
92
|
+
const sourceSwAnimate = /<animate\s+attributeName="stroke-width"\s+values="2\.5;2\.75;2\.5"\s+dur="3s"\s+repeatCount="indefinite"\s*\/>/.test(src);
|
|
93
|
+
const sourceSwAttr = /data-chat-target-ring-sw-breath=\{!reducedMotion && isChat \? 'on' : 'off'\}/.test(src);
|
|
94
|
+
// Ensure both animates sit inside the same `!reducedMotion && isChat &&` gate
|
|
95
|
+
const sourceFragmentGate = /\{!reducedMotion && isChat && \(\s*<>\s*<animate\s+attributeName="opacity"[\s\S]*?<animate\s+attributeName="stroke-width"/.test(src);
|
|
96
|
+
|
|
97
|
+
const swAnimate = activeState?.animateAttrs?.find(a => a.attr === 'stroke-width');
|
|
98
|
+
const opAnimate = activeState?.animateAttrs?.find(a => a.attr === 'opacity');
|
|
99
|
+
|
|
100
|
+
const results = {
|
|
101
|
+
rest_ring_present: !!restState,
|
|
102
|
+
rest_active_false: restState?.active === 'false',
|
|
103
|
+
rest_breath_off: restState?.breath === 'off',
|
|
104
|
+
rest_sw_breath_off: restState?.swBreath === 'off',
|
|
105
|
+
rest_no_animate: restState?.animateCount === 0,
|
|
106
|
+
active_active_true: activeState?.active === 'true',
|
|
107
|
+
active_breath_on: activeState?.breath === 'on',
|
|
108
|
+
active_sw_breath_on: activeState?.swBreath === 'on',
|
|
109
|
+
active_animate_count_2: activeState?.animateCount === 2,
|
|
110
|
+
active_sw_dur_3s: swAnimate?.dur === '3s',
|
|
111
|
+
active_sw_values: swAnimate?.vals === '2.5;2.75;2.5',
|
|
112
|
+
active_sw_rep_indef: swAnimate?.rep === 'indefinite',
|
|
113
|
+
active_op_dur_3s: opAnimate?.dur === '3s', // existing R120 still present
|
|
114
|
+
source_sw_animate: sourceSwAnimate,
|
|
115
|
+
source_sw_attr: sourceSwAttr,
|
|
116
|
+
source_fragment_gate: sourceFragmentGate,
|
|
117
|
+
};
|
|
118
|
+
const ok = Object.values(results).every(Boolean);
|
|
119
|
+
console.log(`${ok ? '✅' : '❌'} R630 chat-target ring stroke-width breath (呼吸感 2nd axis):`,
|
|
120
|
+
JSON.stringify(results, null, 2),
|
|
121
|
+
`\n rest: ${JSON.stringify(restState)}`,
|
|
122
|
+
`\n active: ${JSON.stringify(activeState)}`);
|
|
123
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/* Round 539 verification: chip-row digit (working/online/active-links)
|
|
2
|
+
* gains group-hover:tracking-wide alongside existing R362 group-hover:
|
|
3
|
+
* font-bold. Hover-letter-spacing family 12th anchor across 3 siblings.
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. rest each chip-digit: computed letterSpacing='normal' (=0)
|
|
7
|
+
* 2. hover the chip's parent (has `group` class — sets group-hover):
|
|
8
|
+
* digit's letterSpacing = ~0.025em
|
|
9
|
+
* 3. source-side regex confirms all 3 digits have the new class
|
|
10
|
+
*/
|
|
11
|
+
import { chromium } from 'playwright';
|
|
12
|
+
import { readFileSync } from 'node:fs';
|
|
13
|
+
|
|
14
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
15
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
16
|
+
|
|
17
|
+
const browser = await chromium.launch({ headless: true });
|
|
18
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
19
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
20
|
+
await ctx.addInitScript(() => {
|
|
21
|
+
try {
|
|
22
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
23
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
24
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
25
|
+
} catch {}
|
|
26
|
+
});
|
|
27
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
28
|
+
const r = await route.fetch();
|
|
29
|
+
const b = await r.json();
|
|
30
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
31
|
+
const mk = (alias, status) => ({
|
|
32
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
33
|
+
network_id: nid, project_dir: null,
|
|
34
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
35
|
+
});
|
|
36
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
37
|
+
mk('a·1', 'working'), mk('a·2', 'idle'),
|
|
38
|
+
] } });
|
|
39
|
+
});
|
|
40
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: {
|
|
41
|
+
messages: [{ id: 'm1', from_alias: 'a·1', to_alias: 'a·2', content: 't', 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-working-chip-digit]', { timeout: 15000 });
|
|
47
|
+
await page.waitForTimeout(800);
|
|
48
|
+
|
|
49
|
+
async function probe(digitSel, chipParentSel) {
|
|
50
|
+
const rest = await page.evaluate((s) => {
|
|
51
|
+
const el = document.querySelector(s);
|
|
52
|
+
if (!el) return null;
|
|
53
|
+
return { ls: getComputedStyle(el).letterSpacing };
|
|
54
|
+
}, digitSel);
|
|
55
|
+
await page.hover(chipParentSel);
|
|
56
|
+
await page.waitForTimeout(350);
|
|
57
|
+
const hover = await page.evaluate((s) => {
|
|
58
|
+
const el = document.querySelector(s);
|
|
59
|
+
if (!el) return null;
|
|
60
|
+
return { ls: getComputedStyle(el).letterSpacing };
|
|
61
|
+
}, digitSel);
|
|
62
|
+
// move pointer away for next probe
|
|
63
|
+
await page.mouse.move(50, 50);
|
|
64
|
+
await page.waitForTimeout(200);
|
|
65
|
+
return { rest, hover };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// The chip-row chip <span class="group ...">; each has parent with `group`.
|
|
69
|
+
// Hover the chip's parent span — its child digit gets group-hover effects.
|
|
70
|
+
// The chip parent is the closest ancestor with `group` class. Easier: find
|
|
71
|
+
// the digit and walk up to nearest `.group` element via JS.
|
|
72
|
+
async function hoverChipDigit(sel) {
|
|
73
|
+
const handle = await page.evaluateHandle((s) => {
|
|
74
|
+
const el = document.querySelector(s);
|
|
75
|
+
if (!el) return null;
|
|
76
|
+
let p = el.parentElement;
|
|
77
|
+
while (p && !p.classList.contains('group')) p = p.parentElement;
|
|
78
|
+
return p;
|
|
79
|
+
}, sel);
|
|
80
|
+
return handle;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function probeChip(digitSel) {
|
|
84
|
+
const rest = await page.evaluate((s) => {
|
|
85
|
+
const el = document.querySelector(s);
|
|
86
|
+
if (!el) return null;
|
|
87
|
+
return { ls: getComputedStyle(el).letterSpacing };
|
|
88
|
+
}, digitSel);
|
|
89
|
+
const groupHandle = await hoverChipDigit(digitSel);
|
|
90
|
+
await groupHandle.asElement()?.hover();
|
|
91
|
+
await page.waitForTimeout(350);
|
|
92
|
+
const hover = await page.evaluate((s) => {
|
|
93
|
+
const el = document.querySelector(s);
|
|
94
|
+
if (!el) return null;
|
|
95
|
+
return { ls: getComputedStyle(el).letterSpacing };
|
|
96
|
+
}, digitSel);
|
|
97
|
+
await page.mouse.move(50, 50);
|
|
98
|
+
await page.waitForTimeout(200);
|
|
99
|
+
return { rest, hover };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const working = await probeChip('[data-working-chip-digit]');
|
|
103
|
+
const online = await probeChip('[data-online-chip-digit]');
|
|
104
|
+
const activeLinks = await probeChip('[data-active-links-chip-digit]');
|
|
105
|
+
|
|
106
|
+
await browser.close();
|
|
107
|
+
|
|
108
|
+
// Source regex — all 3 chip digits should carry the new class string
|
|
109
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
110
|
+
const sourceWorking = /class[Nn]ame="font-semibold transition-\[font-weight,letter-spacing\] duration-200 group-hover:font-bold group-hover:tracking-wide" data-working-chip-digit/.test(src);
|
|
111
|
+
const sourceOnline = /class[Nn]ame="font-semibold transition-\[font-weight,letter-spacing\] duration-200 group-hover:font-bold group-hover:tracking-wide" data-online-chip-digit/.test(src);
|
|
112
|
+
const sourceAL = /class[Nn]ame="font-semibold transition-\[font-weight,letter-spacing\] duration-200 group-hover:font-bold group-hover:tracking-wide" data-active-links-chip-digit/.test(src);
|
|
113
|
+
|
|
114
|
+
const isRestLS = (r) => r?.ls === 'normal' || r?.ls === '0px';
|
|
115
|
+
// tracking-wide = 0.025em; on text-xs (12px) digit ≈ 0.3px (varies with computed font-size)
|
|
116
|
+
const isHoverLS = (r) => r?.ls && r.ls !== 'normal' && r.ls !== '0px' && parseFloat(r.ls) > 0.1;
|
|
117
|
+
|
|
118
|
+
const results = {
|
|
119
|
+
working_rest_normal: isRestLS(working?.rest),
|
|
120
|
+
working_hover_wide: isHoverLS(working?.hover),
|
|
121
|
+
online_rest_normal: isRestLS(online?.rest),
|
|
122
|
+
online_hover_wide: isHoverLS(online?.hover),
|
|
123
|
+
active_rest_normal: isRestLS(activeLinks?.rest),
|
|
124
|
+
active_hover_wide: isHoverLS(activeLinks?.hover),
|
|
125
|
+
source_working: sourceWorking,
|
|
126
|
+
source_online: sourceOnline,
|
|
127
|
+
source_active_links: sourceAL,
|
|
128
|
+
};
|
|
129
|
+
const ok = Object.values(results).every(Boolean);
|
|
130
|
+
console.log(`${ok ? '✅' : '❌'} R539 chip-row digit hover-tracking:`,
|
|
131
|
+
JSON.stringify(results, null, 2),
|
|
132
|
+
'\n working:', JSON.stringify(working),
|
|
133
|
+
'\n online:', JSON.stringify(online),
|
|
134
|
+
'\n active-links:', JSON.stringify(activeLinks));
|
|
135
|
+
process.exit(ok ? 0 : 1);
|