@sleep2agi/agent-network-dashboard 0.5.3-preview.6 → 0.5.3-preview.60
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 +32 -32
- 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 +12 -12
- package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/server/app/admin.html +2 -2
- package/.next/server/app/admin.rsc +14 -14
- package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
- package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
- package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +14 -14
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +7 -7
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +2 -2
- package/.next/server/app/login.rsc +14 -14
- package/.next/server/app/login.segments/_full.segment.rsc +14 -14
- package/.next/server/app/login.segments/_head.segment.rsc +4 -4
- package/.next/server/app/login.segments/_index.segment.rsc +7 -7
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/login.segments/login.segment.rsc +3 -3
- package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +2 -2
- package/.next/server/app/logs.rsc +14 -14
- package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
- package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
- package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +2 -2
- package/.next/server/app/messages.rsc +14 -14
- package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
- package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
- package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
- package/.next/server/app/node/page_client-reference-manifest.js +1 -1
- package/.next/server/app/node.html +2 -2
- package/.next/server/app/node.rsc +14 -14
- package/.next/server/app/node.segments/_full.segment.rsc +14 -14
- package/.next/server/app/node.segments/_head.segment.rsc +4 -4
- package/.next/server/app/node.segments/_index.segment.rsc +7 -7
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/node.segments/node.segment.rsc +3 -3
- package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/nodes.html +2 -2
- package/.next/server/app/nodes.rsc +14 -14
- package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
- package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +2 -2
- package/.next/server/app/server-logs.rsc +14 -14
- package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
- package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
- package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/networks.html +2 -2
- package/.next/server/app/settings/networks.rsc +14 -14
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +2 -2
- package/.next/server/app/settings/tokens.rsc +14 -14
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +14 -14
- package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks.html +2 -2
- package/.next/server/app/tasks.rsc +14 -14
- package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
- package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
- package/.next/server/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 +3 -3
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js.map +1 -1
- package/.next/server/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/058_sxgdyfzl7.js +4 -0
- package/.next/static/chunks/0b1q0~gt32zw-.css +2 -0
- package/.next/static/chunks/0q~p0u0ysa9nd.js +1 -0
- package/.next/static/chunks/{03a4--7ncekmk.js → 0v4-5tng.uh.7.js} +2 -2
- package/.next/static/chunks/0y2cak1ot-feb.js +1 -0
- package/.next/static/chunks/{16qx24lc72~7v.js → 17idlq8so6dmm.js} +1 -1
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/ServersDrawer.tsx +16 -3
- package/app/components/TopoGraph.tsx +1549 -76
- package/app/globals.css +55 -7
- package/package.json +4 -4
- package/scripts/p157-servers-copy-test.mjs +95 -0
- package/scripts/topo-alias-glow-test.mjs +121 -0
- package/scripts/topo-avatar-brightness-test.mjs +116 -0
- package/scripts/topo-chip-row-digit-ls-test.mjs +135 -0
- package/scripts/topo-chip-row-press-test.mjs +93 -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-hover-glow-test.mjs +90 -0
- package/scripts/topo-edge-pill-glow-test.mjs +67 -0
- package/scripts/topo-filter-pill-glow-test.mjs +90 -0
- package/scripts/topo-filter-pills-press-test.mjs +96 -0
- package/scripts/topo-fleet-density-tier-test.mjs +84 -0
- package/scripts/topo-freshness-chip-fade-test.mjs +105 -0
- package/scripts/topo-fullscreen-attr-test.mjs +73 -0
- package/scripts/topo-grid-content-bottom-attr-test.mjs +72 -0
- package/scripts/topo-group-label-hover-glow-test.mjs +86 -0
- package/scripts/topo-group-pill-glow-test.mjs +76 -0
- package/scripts/topo-hub-digit-ls-test.mjs +119 -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-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-glow-test.mjs +97 -0
- package/scripts/topo-hub-idle-breath-test.mjs +109 -0
- package/scripts/topo-hub-recede-test.mjs +124 -0
- package/scripts/topo-hub-spoke-glow-test.mjs +112 -0
- package/scripts/topo-layout-hover-fw-test.mjs +98 -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-swatch-glow-test.mjs +109 -0
- package/scripts/topo-minimap-hover-glow-test.mjs +109 -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-italic-test.mjs +90 -0
- package/scripts/topo-pinned-aspect-test.mjs +89 -0
- package/scripts/topo-pressure-seg-glow-test.mjs +92 -0
- package/scripts/topo-pressure-seg-motion-test.mjs +101 -0
- package/scripts/topo-recent-hot-pulse-test.mjs +102 -0
- package/scripts/topo-recent-more-fw-test.mjs +126 -0
- package/scripts/topo-recent-row-fw-test.mjs +115 -0
- package/scripts/topo-reduced-motion-attr-test.mjs +69 -0
- package/scripts/topo-reset-icon-hover-scale-test.mjs +102 -0
- package/scripts/topo-starfield-hue-test.mjs +109 -0
- package/scripts/topo-vendor-activelinks-press-test.mjs +100 -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-level-color-test.mjs +105 -0
- package/.next/static/chunks/018~fceya_6uk.css +0 -2
- package/.next/static/chunks/0ic678xqvd4ys.js +0 -4
- package/.next/static/chunks/0swbhc-5l4rz9.js +0 -1
- package/.next/static/chunks/17v63m4g4.i5h.js +0 -1
- /package/.next/static/{FpDDygQl1AAn4qwXBn3mt → lzP2ZpRRhiAhFxTKHfcxY}/_buildManifest.js +0 -0
- /package/.next/static/{FpDDygQl1AAn4qwXBn3mt → lzP2ZpRRhiAhFxTKHfcxY}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{FpDDygQl1AAn4qwXBn3mt → lzP2ZpRRhiAhFxTKHfcxY}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/* Round 522 verification: chrome Ring/Grid layout toggle's inactive
|
|
2
|
+
* variant gains `hover:font-medium` typography preview. Closes chrome
|
|
3
|
+
* toggle group typography hover-fw family at the last remaining toggle.
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. default (layout=ring): Ring active fw=500, Grid inactive fw=400
|
|
7
|
+
* + Grid data-attr = '500' (preview target)
|
|
8
|
+
* + Ring data-attr = null
|
|
9
|
+
* 2. hover Grid (inactive): fontWeight → 500 (preview lands)
|
|
10
|
+
* 3. source-side regex confirms hover:font-medium + transition wired
|
|
11
|
+
* for both buttons
|
|
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')] } });
|
|
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-topo-chrome-layout]', { timeout: 15000 });
|
|
45
|
+
await page.waitForTimeout(800);
|
|
46
|
+
|
|
47
|
+
const buttons = await page.evaluate(() => {
|
|
48
|
+
const els = Array.from(document.querySelectorAll('[data-topo-chrome-layout]'));
|
|
49
|
+
return els.map((el) => ({
|
|
50
|
+
label: el.getAttribute('data-topo-chrome-layout'),
|
|
51
|
+
active: el.getAttribute('data-topo-chrome-layout-active'),
|
|
52
|
+
previewAttr: el.getAttribute('data-topo-chrome-layout-hover-preview-fw'),
|
|
53
|
+
fw: getComputedStyle(el).fontWeight,
|
|
54
|
+
}));
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Phase 2: hover the inactive (Grid since layout=ring default)
|
|
58
|
+
await page.hover('[data-topo-chrome-layout="grid"]');
|
|
59
|
+
await page.waitForTimeout(350);
|
|
60
|
+
const gridHoverFw = await page.evaluate(() =>
|
|
61
|
+
getComputedStyle(document.querySelector('[data-topo-chrome-layout="grid"]')).fontWeight
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
await browser.close();
|
|
65
|
+
|
|
66
|
+
// Source regex
|
|
67
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
68
|
+
const sourceWiredClassRing = /'ring' \? '.*font-medium.*' : '.*hover:font-medium'.*\$\{chromePopping === 'layout-ring'/.test(src);
|
|
69
|
+
const sourceWiredClassGrid = /'grid' \? '.*font-medium.*' : '.*hover:font-medium'.*\$\{chromePopping === 'layout-grid'/.test(src);
|
|
70
|
+
const sourceWiredAttrRing = /data-topo-chrome-layout-hover-preview-fw=\{layout === 'ring' \? null : '500'\}/.test(src);
|
|
71
|
+
const sourceWiredAttrGrid = /data-topo-chrome-layout-hover-preview-fw=\{layout === 'grid' \? null : '500'\}/.test(src);
|
|
72
|
+
const sourceWiredTransRing = /transition: '.*font-weight 150ms ease'.*\n.*Ring/.test(src) ||
|
|
73
|
+
/font-weight 150ms ease'\s*\}\}\s*>\s*\n\s*Ring/.test(src);
|
|
74
|
+
const sourceWiredTransGrid = /borderColor:.*containerBorder.*font-weight 150ms ease/.test(src);
|
|
75
|
+
|
|
76
|
+
const ring = buttons.find(b => b.label === 'ring');
|
|
77
|
+
const grid = buttons.find(b => b.label === 'grid');
|
|
78
|
+
|
|
79
|
+
const results = {
|
|
80
|
+
ring_active_true: ring?.active === 'true',
|
|
81
|
+
ring_active_fw_500: ring?.fw === '500',
|
|
82
|
+
ring_no_preview_attr: ring?.previewAttr === null,
|
|
83
|
+
grid_active_false: grid?.active === 'false',
|
|
84
|
+
grid_inactive_fw_400: grid?.fw === '400',
|
|
85
|
+
grid_preview_attr_500: grid?.previewAttr === '500',
|
|
86
|
+
grid_hover_fw_500: gridHoverFw === '500',
|
|
87
|
+
source_class_ring: sourceWiredClassRing,
|
|
88
|
+
source_class_grid: sourceWiredClassGrid,
|
|
89
|
+
source_attr_ring: sourceWiredAttrRing,
|
|
90
|
+
source_attr_grid: sourceWiredAttrGrid,
|
|
91
|
+
source_trans_grid: sourceWiredTransGrid,
|
|
92
|
+
};
|
|
93
|
+
const ok = Object.values(results).every(Boolean);
|
|
94
|
+
console.log(`${ok ? '✅' : '❌'} R522 layout hover-fw preview:`,
|
|
95
|
+
JSON.stringify(results, null, 2),
|
|
96
|
+
'\n buttons:', JSON.stringify(buttons),
|
|
97
|
+
'\n grid hover fw:', gridHoverFw);
|
|
98
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/* Round 518 verification: legend-row COUNT digit gains the same 3-tier
|
|
2
|
+
* hover-letter-spacing tween R433 added to the LABEL — symmetric row
|
|
3
|
+
* hover gesture. Also lifts transition list 150 → 200ms closing R475
|
|
4
|
+
* panel-row cadence at the count surface.
|
|
5
|
+
*
|
|
6
|
+
* Test phases:
|
|
7
|
+
* 1. rest: letter-spacing 0px, attr='0px', transition includes '200ms'
|
|
8
|
+
* 2. hover: letter-spacing 0.25px, attr='0.25px'
|
|
9
|
+
* 3. source-side regex confirms 3-tier wiring + 200ms cadence
|
|
10
|
+
*
|
|
11
|
+
* Pin tier (0.5px) requires real click + filter-pin localStorage —
|
|
12
|
+
* skip and rely on source-regex for the pinned tier.
|
|
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, status) => ({
|
|
35
|
+
alias, status, 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: [
|
|
40
|
+
mk('a·1', 'idle'),
|
|
41
|
+
mk('a·2', 'idle'),
|
|
42
|
+
mk('b·1', '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-legend-count]', { timeout: 15000 });
|
|
50
|
+
await page.waitForTimeout(800);
|
|
51
|
+
|
|
52
|
+
// Pick the 'online' row's count (it'll have count > 0 so we see typography)
|
|
53
|
+
const targetSel = '[data-legend-count="idle"]';
|
|
54
|
+
|
|
55
|
+
// Phase 1: rest
|
|
56
|
+
const rest = await page.evaluate((sel) => {
|
|
57
|
+
const el = document.querySelector(sel);
|
|
58
|
+
if (!el) return null;
|
|
59
|
+
const cs = getComputedStyle(el);
|
|
60
|
+
return {
|
|
61
|
+
attrLS: el.getAttribute('data-legend-count-letter-spacing'),
|
|
62
|
+
attrTrans: el.getAttribute('data-legend-count-transition'),
|
|
63
|
+
letterSpacing: cs.letterSpacing,
|
|
64
|
+
transition: cs.transition,
|
|
65
|
+
};
|
|
66
|
+
}, targetSel);
|
|
67
|
+
|
|
68
|
+
// Phase 2: hover the row's hitbox (the parent g — but row hover is keyed
|
|
69
|
+
// on hoveredStatus which is set by mouseEnter on the row-hitbox rect.
|
|
70
|
+
// Easier: hover the LABEL text (also part of the row) and observe count.
|
|
71
|
+
await page.hover('[data-legend-row-label="idle"]');
|
|
72
|
+
await page.waitForTimeout(350);
|
|
73
|
+
const hover = await page.evaluate((sel) => {
|
|
74
|
+
const el = document.querySelector(sel);
|
|
75
|
+
if (!el) return null;
|
|
76
|
+
const cs = getComputedStyle(el);
|
|
77
|
+
return {
|
|
78
|
+
attrLS: el.getAttribute('data-legend-count-letter-spacing'),
|
|
79
|
+
letterSpacing: cs.letterSpacing,
|
|
80
|
+
};
|
|
81
|
+
}, targetSel);
|
|
82
|
+
|
|
83
|
+
await browser.close();
|
|
84
|
+
|
|
85
|
+
// Phase 3: source regex — verifies all 3 tiers + 200ms cadence
|
|
86
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
87
|
+
const sourceWiredLS =
|
|
88
|
+
/letterSpacing: isPinned \? '0\.5px' :\s*hoveredStatus === row\.key \? '0\.25px' : '0px',/.test(src);
|
|
89
|
+
const sourceWiredAttr =
|
|
90
|
+
/data-legend-count-letter-spacing=\{isPinned \? '0\.5px' : hoveredStatus === row\.key \? '0\.25px' : '0px'\}/.test(src);
|
|
91
|
+
const sourceWiredCadence =
|
|
92
|
+
/transition: 'opacity 200ms ease-out, fill 200ms ease-out, font-weight 200ms ease-out, letter-spacing 200ms ease-out',/.test(src);
|
|
93
|
+
|
|
94
|
+
const results = {
|
|
95
|
+
rest_attr_0: rest?.attrLS === '0px',
|
|
96
|
+
rest_attr_transition_200: rest?.attrTrans === '200ms',
|
|
97
|
+
rest_letter_spacing_0: rest?.letterSpacing === '0px' || rest?.letterSpacing === 'normal',
|
|
98
|
+
rest_transition_200ms: /(200ms|0\.2s)/.test(rest?.transition || ''),
|
|
99
|
+
hover_attr_025: hover?.attrLS === '0.25px',
|
|
100
|
+
hover_letter_spacing_025: hover?.letterSpacing === '0.25px',
|
|
101
|
+
source_3_tier_ls: sourceWiredLS,
|
|
102
|
+
source_attr_3_tier: sourceWiredAttr,
|
|
103
|
+
source_200ms_cadence: sourceWiredCadence,
|
|
104
|
+
};
|
|
105
|
+
const ok = Object.values(results).every(Boolean);
|
|
106
|
+
console.log(`${ok ? '✅' : '❌'} R518 legend-count 3-tier letter-spacing + 200ms:`, JSON.stringify(results, null, 2),
|
|
107
|
+
'\n rest:', JSON.stringify(rest), '\n hover:', JSON.stringify(hover));
|
|
108
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/* Round 531 verification: legend-row label gains fontWeight 500 → 600 on
|
|
2
|
+
* hover OR pin. Hover-fw family 8th anchor; symmetric to R530 recent-row.
|
|
3
|
+
*
|
|
4
|
+
* Test phases:
|
|
5
|
+
* 1. rest: attr='500', fw=500, hovered/pinned='false'
|
|
6
|
+
* 2. hover legend `idle` row label:
|
|
7
|
+
* attr='600', fw=600, hovered='true'
|
|
8
|
+
* 3. mouseleave: attr returns to '500'
|
|
9
|
+
* 4. source-side regex confirms ternary + transition list extension
|
|
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
|
+
// 3 idle, 1 working — legend rows have counts
|
|
37
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
38
|
+
mk('a·1', 'idle'), mk('a·2', 'idle'), mk('a·3', 'idle'), mk('a·4', 'working'),
|
|
39
|
+
] } });
|
|
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-legend-row-label="idle"]', { timeout: 15000 });
|
|
46
|
+
await page.waitForTimeout(800);
|
|
47
|
+
|
|
48
|
+
const sel = '[data-legend-row-label="idle"]';
|
|
49
|
+
|
|
50
|
+
const restRead = async () => page.evaluate((sel) => {
|
|
51
|
+
const el = document.querySelector(sel);
|
|
52
|
+
if (!el) return null;
|
|
53
|
+
const cs = getComputedStyle(el);
|
|
54
|
+
return {
|
|
55
|
+
attrFw: el.getAttribute('data-legend-row-label-font-weight'),
|
|
56
|
+
attrPinned: el.getAttribute('data-legend-row-label-pinned'),
|
|
57
|
+
attrHovered: el.getAttribute('data-legend-row-label-hovered'),
|
|
58
|
+
fontWeight: cs.fontWeight,
|
|
59
|
+
transition: cs.transition,
|
|
60
|
+
};
|
|
61
|
+
}, sel);
|
|
62
|
+
|
|
63
|
+
// Phase 1: rest
|
|
64
|
+
const rest = await restRead();
|
|
65
|
+
|
|
66
|
+
// Phase 2: hover the row label
|
|
67
|
+
await page.hover(sel);
|
|
68
|
+
await page.waitForTimeout(400);
|
|
69
|
+
const hover = await restRead();
|
|
70
|
+
|
|
71
|
+
// Phase 3: mouseleave
|
|
72
|
+
await page.mouse.move(50, 50);
|
|
73
|
+
await page.waitForTimeout(400);
|
|
74
|
+
const leave = await restRead();
|
|
75
|
+
|
|
76
|
+
await browser.close();
|
|
77
|
+
|
|
78
|
+
// Source regex
|
|
79
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
80
|
+
const sourceFwTernary =
|
|
81
|
+
/fontWeight=\{\(hoveredStatus === row\.key \|\| isPinned\) \? '600' : '500'\}/.test(src);
|
|
82
|
+
const sourceAttrWired =
|
|
83
|
+
/data-legend-row-label-font-weight=\{\(hoveredStatus === row\.key \|\| isPinned\) \? '600' : '500'\}/.test(src);
|
|
84
|
+
const sourceTransitionExt =
|
|
85
|
+
/transition: 'fill 200ms ease-out, letter-spacing 200ms ease-out, font-weight 200ms ease-out'/.test(src);
|
|
86
|
+
|
|
87
|
+
const results = {
|
|
88
|
+
rest_attr_500: rest?.attrFw === '500',
|
|
89
|
+
rest_fw_500: rest?.fontWeight === '500',
|
|
90
|
+
rest_hovered_false: rest?.attrHovered === 'false',
|
|
91
|
+
rest_pinned_false: rest?.attrPinned === 'false',
|
|
92
|
+
hover_attr_600: hover?.attrFw === '600',
|
|
93
|
+
hover_fw_600: hover?.fontWeight === '600',
|
|
94
|
+
hover_hovered_true: hover?.attrHovered === 'true',
|
|
95
|
+
leave_attr_500: leave?.attrFw === '500',
|
|
96
|
+
leave_fw_500: leave?.fontWeight === '500',
|
|
97
|
+
source_fw_ternary: sourceFwTernary,
|
|
98
|
+
source_attr_wired: sourceAttrWired,
|
|
99
|
+
source_transition_ext: sourceTransitionExt,
|
|
100
|
+
};
|
|
101
|
+
const ok = Object.values(results).every(Boolean);
|
|
102
|
+
console.log(`${ok ? '✅' : '❌'} R531 legend-label hover-fw:`,
|
|
103
|
+
JSON.stringify(results, null, 2),
|
|
104
|
+
'\n rest:', JSON.stringify(rest),
|
|
105
|
+
'\n hover:', JSON.stringify(hover),
|
|
106
|
+
'\n leave:', JSON.stringify(leave));
|
|
107
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/* Round 537 verification: legend swatch gains drop-shadow glow on
|
|
2
|
+
* hover/pin using its own row.fill color — drop-shadow family 13th
|
|
3
|
+
* anchor.
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. rest: data-legend-swatch-glow='false', filter='none'
|
|
7
|
+
* 2. hover legend 'idle' row label (banked R518 path): swatch's glow
|
|
8
|
+
* attr='true', filter matches drop-shadow with the idle row fill
|
|
9
|
+
* (cyber #2dd4bf teal-400)
|
|
10
|
+
* 3. mouseleave: returns to 'false'/'none'
|
|
11
|
+
* 4. source-side regex confirms filter ternary + transition wiring
|
|
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, 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: [
|
|
39
|
+
mk('a·1', 'idle'), mk('a·2', 'idle'), mk('a·3', 'working'),
|
|
40
|
+
] } });
|
|
41
|
+
});
|
|
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-legend-swatch="idle"]', { timeout: 15000 });
|
|
47
|
+
await page.waitForTimeout(800);
|
|
48
|
+
|
|
49
|
+
const sel = '[data-legend-swatch="idle"]';
|
|
50
|
+
|
|
51
|
+
const restRead = async () => page.evaluate((sel) => {
|
|
52
|
+
const el = document.querySelector(sel);
|
|
53
|
+
if (!el) return null;
|
|
54
|
+
const cs = getComputedStyle(el);
|
|
55
|
+
return {
|
|
56
|
+
glowAttr: el.getAttribute('data-legend-swatch-glow'),
|
|
57
|
+
state: el.getAttribute('data-legend-swatch-state'),
|
|
58
|
+
filter: cs.filter,
|
|
59
|
+
transition: cs.transition,
|
|
60
|
+
};
|
|
61
|
+
}, sel);
|
|
62
|
+
|
|
63
|
+
// Phase 1: rest
|
|
64
|
+
const rest = await restRead();
|
|
65
|
+
|
|
66
|
+
// Phase 2: hover the legend 'idle' row label — sibling row hover sets
|
|
67
|
+
// hoveredStatus='idle' which is the same gate as the swatch's hover.
|
|
68
|
+
await page.hover('[data-legend-row-label="idle"]');
|
|
69
|
+
await page.waitForTimeout(400);
|
|
70
|
+
const hover = await restRead();
|
|
71
|
+
|
|
72
|
+
// Phase 3: mouseleave
|
|
73
|
+
await page.mouse.move(50, 50);
|
|
74
|
+
await page.waitForTimeout(400);
|
|
75
|
+
const leave = await restRead();
|
|
76
|
+
|
|
77
|
+
await browser.close();
|
|
78
|
+
|
|
79
|
+
// Source regex
|
|
80
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
81
|
+
const sourceFilterTernary =
|
|
82
|
+
/filter: \(isRowHovered \|\| isPinned\)\s+\? `drop-shadow\(0 0 3px \$\{row\.fill\}99\)`\s+: undefined,/.test(src);
|
|
83
|
+
const sourceAttrWired =
|
|
84
|
+
/data-legend-swatch-glow=\{\(isRowHovered \|\| isPinned\) \? 'true' : 'false'\}/.test(src);
|
|
85
|
+
const sourceTransitionExt =
|
|
86
|
+
/transition: 'r 150ms ease-out, filter 150ms ease-out',/.test(src);
|
|
87
|
+
|
|
88
|
+
const results = {
|
|
89
|
+
rest_glow_false: rest?.glowAttr === 'false',
|
|
90
|
+
rest_state_idle: rest?.state === 'idle',
|
|
91
|
+
rest_filter_none: rest?.filter === 'none' || rest?.filter === '',
|
|
92
|
+
rest_transition_has_filter: /\bfilter\b/.test(rest?.transition || ''),
|
|
93
|
+
hover_glow_true: hover?.glowAttr === 'true',
|
|
94
|
+
hover_state_hover: hover?.state === 'hover',
|
|
95
|
+
hover_filter_drop_shadow: /drop-shadow/.test(hover?.filter || ''),
|
|
96
|
+
hover_filter_has_teal: /rgba?\(45,?\s*212,?\s*191/.test(hover?.filter || ''), // cyber idle teal-400 #2dd4bf (computed as rgba(...))
|
|
97
|
+
leave_glow_false: leave?.glowAttr === 'false',
|
|
98
|
+
leave_filter_none: leave?.filter === 'none' || leave?.filter === '',
|
|
99
|
+
source_filter_ternary: sourceFilterTernary,
|
|
100
|
+
source_attr_wired: sourceAttrWired,
|
|
101
|
+
source_transition_ext: sourceTransitionExt,
|
|
102
|
+
};
|
|
103
|
+
const ok = Object.values(results).every(Boolean);
|
|
104
|
+
console.log(`${ok ? '✅' : '❌'} R537 legend-swatch glow:`,
|
|
105
|
+
JSON.stringify(results, null, 2),
|
|
106
|
+
'\n rest:', JSON.stringify(rest),
|
|
107
|
+
'\n hover:', JSON.stringify(hover),
|
|
108
|
+
'\n leave:', JSON.stringify(leave));
|
|
109
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/* Round 540 verification: minimap viewport gains drop-shadow glow on
|
|
2
|
+
* hover, with hover precedence over R481 zoom-state glow. 2-tier alpha
|
|
3
|
+
* ladder (hover 99 / zoom 80).
|
|
4
|
+
*
|
|
5
|
+
* Test strategy: minimap is only visible when canvas is zoomed or
|
|
6
|
+
* panned (default view returns null). Trigger zoom via the chrome
|
|
7
|
+
* zoom-in button, verify zoom-state glow renders, then hover the
|
|
8
|
+
* minimap container and verify hover precedence + alpha distinction
|
|
9
|
+
* via the data-attr. Source regex covers the ternary wiring.
|
|
10
|
+
*
|
|
11
|
+
* Test phases:
|
|
12
|
+
* 1. trigger zoom > 1.5 via chrome zoom-in clicks
|
|
13
|
+
* 2. minimap visible, viewport glow attr = 'zoom'
|
|
14
|
+
* 3. hover minimap container: viewport glow = 'hover'
|
|
15
|
+
* 4. source-side regex confirms 3-value attr + filter ternary
|
|
16
|
+
*/
|
|
17
|
+
import { chromium } from 'playwright';
|
|
18
|
+
import { readFileSync } from 'node:fs';
|
|
19
|
+
|
|
20
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
21
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
22
|
+
|
|
23
|
+
const browser = await chromium.launch({ headless: true });
|
|
24
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
25
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
26
|
+
await ctx.addInitScript(() => {
|
|
27
|
+
try {
|
|
28
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
29
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
30
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
31
|
+
} catch {}
|
|
32
|
+
});
|
|
33
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
34
|
+
const r = await route.fetch();
|
|
35
|
+
const b = await r.json();
|
|
36
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
37
|
+
const mk = (alias) => ({
|
|
38
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
39
|
+
network_id: nid, project_dir: null,
|
|
40
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
41
|
+
});
|
|
42
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
43
|
+
mk('a·1'), mk('a·2'), mk('a·3'),
|
|
44
|
+
] } });
|
|
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-topo-chrome-zoom-in]', { timeout: 15000 });
|
|
51
|
+
await page.waitForTimeout(500);
|
|
52
|
+
|
|
53
|
+
// Phase 1: click zoom-in until zoom > 1.5 (1.2^3 = 1.728)
|
|
54
|
+
for (let i = 0; i < 3; i++) {
|
|
55
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
56
|
+
await page.waitForTimeout(150);
|
|
57
|
+
}
|
|
58
|
+
await page.waitForTimeout(500);
|
|
59
|
+
|
|
60
|
+
// Minimap should now be visible
|
|
61
|
+
await page.waitForSelector('[data-topo-minimap-viewport]', { timeout: 5000 });
|
|
62
|
+
|
|
63
|
+
// Phase 2: zoom-state read
|
|
64
|
+
const zoomState = await page.evaluate(() => {
|
|
65
|
+
const el = document.querySelector('[data-topo-minimap-viewport]');
|
|
66
|
+
if (!el) return null;
|
|
67
|
+
const cs = getComputedStyle(el);
|
|
68
|
+
return {
|
|
69
|
+
glow: el.getAttribute('data-topo-minimap-viewport-glow'),
|
|
70
|
+
filter: cs.filter,
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Phase 3: hover minimap container
|
|
75
|
+
await page.hover('[data-topo-minimap]');
|
|
76
|
+
await page.waitForTimeout(400);
|
|
77
|
+
const hoverState = await page.evaluate(() => {
|
|
78
|
+
const el = document.querySelector('[data-topo-minimap-viewport]');
|
|
79
|
+
if (!el) return null;
|
|
80
|
+
const cs = getComputedStyle(el);
|
|
81
|
+
return {
|
|
82
|
+
glow: el.getAttribute('data-topo-minimap-viewport-glow'),
|
|
83
|
+
filter: cs.filter,
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
await browser.close();
|
|
88
|
+
|
|
89
|
+
// Source regex
|
|
90
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
91
|
+
const sourceFilterTernary =
|
|
92
|
+
/filter: hoveredMinimap\s+\? `drop-shadow\(0 0 2px \$\{pal\.legendAccent\}99\)`\s+: view\.zoom > 1\.5\s+\? `drop-shadow\(0 0 2px \$\{pal\.legendAccent\}80\)`\s+: undefined,/.test(src);
|
|
93
|
+
const sourceAttrTernary =
|
|
94
|
+
/data-topo-minimap-viewport-glow=\{hoveredMinimap \? 'hover' : view\.zoom > 1\.5 \? 'zoom' : 'false'\}/.test(src);
|
|
95
|
+
|
|
96
|
+
const results = {
|
|
97
|
+
zoom_glow_zoom: zoomState?.glow === 'zoom',
|
|
98
|
+
zoom_filter_drop_shadow: /drop-shadow/.test(zoomState?.filter || ''),
|
|
99
|
+
hover_glow_hover: hoverState?.glow === 'hover',
|
|
100
|
+
hover_filter_drop_shadow: /drop-shadow/.test(hoverState?.filter || ''),
|
|
101
|
+
source_filter_ternary: sourceFilterTernary,
|
|
102
|
+
source_attr_ternary: sourceAttrTernary,
|
|
103
|
+
};
|
|
104
|
+
const ok = Object.values(results).every(Boolean);
|
|
105
|
+
console.log(`${ok ? '✅' : '❌'} R540 minimap viewport hover-glow:`,
|
|
106
|
+
JSON.stringify(results, null, 2),
|
|
107
|
+
'\n zoom:', JSON.stringify(zoomState),
|
|
108
|
+
'\n hover:', JSON.stringify(hoverState));
|
|
109
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* Round 521 verification: chrome nodeSize S/M/L inactive variant gains
|
|
2
|
+
* hover-fw preview — fw 400 (default) → 500 (font-medium, matches active
|
|
3
|
+
* variant). Extends R270 hover-preview idiom to the typography axis.
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. inactive rest: fontWeight = 400, data-attr = '500' (preview target)
|
|
7
|
+
* 2. inactive hover: fontWeight = 500 (preview lands at active fw)
|
|
8
|
+
* 3. active rest: fontWeight = 500 (existing font-medium class)
|
|
9
|
+
* 4. source-side regex confirms hover:font-medium class + attr wiring
|
|
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) => ({
|
|
32
|
+
alias, status: 'idle', 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: [mk('a·1')] } });
|
|
37
|
+
});
|
|
38
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
39
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
40
|
+
const page = await ctx.newPage();
|
|
41
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
42
|
+
await page.waitForSelector('[data-topo-chrome-nodesize]', { timeout: 15000 });
|
|
43
|
+
await page.waitForTimeout(800);
|
|
44
|
+
|
|
45
|
+
// Find the inactive + active buttons via attrs
|
|
46
|
+
const buttons = await page.evaluate(() => {
|
|
47
|
+
const els = Array.from(document.querySelectorAll('[data-topo-chrome-nodesize]'));
|
|
48
|
+
return els.map((el) => ({
|
|
49
|
+
label: el.getAttribute('data-topo-chrome-nodesize'),
|
|
50
|
+
active: el.getAttribute('data-topo-chrome-nodesize-active'),
|
|
51
|
+
previewAttr: el.getAttribute('data-topo-chrome-nodesize-hover-preview-fw'),
|
|
52
|
+
fw: getComputedStyle(el).fontWeight,
|
|
53
|
+
}));
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Find an inactive one. Default nodeScale is M (1) so S + L should be inactive.
|
|
57
|
+
const inactiveLabel = buttons.find(b => b.active === 'false')?.label;
|
|
58
|
+
if (!inactiveLabel) {
|
|
59
|
+
console.log('❌ R521 — no inactive nodeSize button found');
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
const inactiveSel = `[data-topo-chrome-nodesize="${inactiveLabel}"]`;
|
|
63
|
+
|
|
64
|
+
// Phase 2: hover the inactive button
|
|
65
|
+
await page.hover(inactiveSel);
|
|
66
|
+
await page.waitForTimeout(350);
|
|
67
|
+
const hoverFw = await page.evaluate((sel) => getComputedStyle(document.querySelector(sel)).fontWeight, inactiveSel);
|
|
68
|
+
|
|
69
|
+
// Phase 3: find active button
|
|
70
|
+
const active = buttons.find(b => b.active === 'true');
|
|
71
|
+
|
|
72
|
+
await browser.close();
|
|
73
|
+
|
|
74
|
+
// Phase 4: source regex
|
|
75
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
76
|
+
const sourceWiredClass = /hover:bg-cyan-500\/5 active:bg-cyan-500\/15 hover:font-medium/.test(src);
|
|
77
|
+
const sourceWiredAttr =
|
|
78
|
+
/data-topo-chrome-nodesize-hover-preview-fw=\{nodeScale === v \? null : '500'\}/.test(src);
|
|
79
|
+
const sourceWiredTransition = /transition-\[font-weight\]/.test(src);
|
|
80
|
+
|
|
81
|
+
const inactiveRest = buttons.find(b => b.label === inactiveLabel);
|
|
82
|
+
|
|
83
|
+
const results = {
|
|
84
|
+
inactive_rest_fw_400: inactiveRest?.fw === '400',
|
|
85
|
+
inactive_rest_attr_500: inactiveRest?.previewAttr === '500',
|
|
86
|
+
inactive_active_attr_false: inactiveRest?.active === 'false',
|
|
87
|
+
inactive_hover_fw_500: hoverFw === '500',
|
|
88
|
+
active_rest_fw_500: active?.fw === '500',
|
|
89
|
+
active_no_preview_attr: active?.previewAttr === null || active?.previewAttr === undefined,
|
|
90
|
+
source_class_wired: sourceWiredClass,
|
|
91
|
+
source_attr_wired: sourceWiredAttr,
|
|
92
|
+
source_transition_wired: sourceWiredTransition,
|
|
93
|
+
};
|
|
94
|
+
const ok = Object.values(results).every(Boolean);
|
|
95
|
+
console.log(`${ok ? '✅' : '❌'} R521 nodeSize hover-fw preview:`,
|
|
96
|
+
JSON.stringify(results, null, 2),
|
|
97
|
+
'\n buttons:', JSON.stringify(buttons),
|
|
98
|
+
'\n inactive(', inactiveLabel, ')hover fw:', hoverFw);
|
|
99
|
+
process.exit(ok ? 0 : 1);
|