@sleep2agi/agent-network-dashboard 0.5.3-preview.5 → 0.5.3-preview.51
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/08i3yp3wnkvdd.js +4 -0
- package/.next/static/chunks/0ib0ojh9.ofrs.js +1 -0
- package/.next/static/chunks/0sht0y-y7x71m.css +2 -0
- package/.next/static/chunks/{03a4--7ncekmk.js → 0v4-5tng.uh.7.js} +2 -2
- package/.next/static/chunks/12rya_znu46dn.js +1 -0
- package/.next/static/chunks/{031p2u1xb1~uk.js → 142gisyxu_fy5.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 +1324 -68
- 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-press-test.mjs +93 -0
- package/scripts/topo-chrome-press-fullstrip-test.mjs +105 -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-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-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-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-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-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/024l23a_mex8..js +0 -4
- package/.next/static/chunks/09q4enn24qy1u.js +0 -1
- package/.next/static/chunks/0iwmx1skjhecc.js +0 -1
- package/.next/static/chunks/0yj_zl0p6_4ws.css +0 -2
- /package/.next/static/{3Apg3z__jP_I-Dl6oqXnF → -N6yPJbjnHbgai9z-vmKs}/_buildManifest.js +0 -0
- /package/.next/static/{3Apg3z__jP_I-Dl6oqXnF → -N6yPJbjnHbgai9z-vmKs}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{3Apg3z__jP_I-Dl6oqXnF → -N6yPJbjnHbgai9z-vmKs}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/* Round 523 verification: starfield gains 3-hue deterministic color
|
|
2
|
+
* rotation (indigo / cyan / slate) instead of flat #a5b4fc. 配色 family
|
|
3
|
+
* 3rd anchor (cyber theme; light theme unaffected per starfield gate).
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. cyber: 14 dots present, each carries data-topo-starfield-dot-hue
|
|
7
|
+
* with one of: indigo / cyan / slate
|
|
8
|
+
* 2. distribution: dots at i % 3 === 0 → indigo (#a5b4fc),
|
|
9
|
+
* i % 3 === 1 → cyan (#67e8f9), i % 3 === 2 → slate (#cbd5e1)
|
|
10
|
+
* → 14 dots → 5 indigo + 5 cyan + 4 slate (indices 0..13)
|
|
11
|
+
* 3. all three hues present
|
|
12
|
+
* 4. light theme: starfield not rendered at all (existing gate)
|
|
13
|
+
* 5. source-side regex confirms hues array + dot-hue attr wired
|
|
14
|
+
*/
|
|
15
|
+
import { chromium } from 'playwright';
|
|
16
|
+
import { readFileSync } from 'node:fs';
|
|
17
|
+
|
|
18
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
19
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
20
|
+
|
|
21
|
+
async function probe(theme) {
|
|
22
|
+
const browser = await chromium.launch({ headless: true });
|
|
23
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
24
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
25
|
+
await ctx.addInitScript((t) => {
|
|
26
|
+
try {
|
|
27
|
+
localStorage.setItem('anet-theme', t);
|
|
28
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
29
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
30
|
+
} catch {}
|
|
31
|
+
}, theme);
|
|
32
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
33
|
+
const r = await route.fetch();
|
|
34
|
+
const b = await r.json();
|
|
35
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
36
|
+
const mk = (alias) => ({
|
|
37
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
38
|
+
network_id: nid, project_dir: null,
|
|
39
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
40
|
+
});
|
|
41
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1')] } });
|
|
42
|
+
});
|
|
43
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
44
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
45
|
+
const page = await ctx.newPage();
|
|
46
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
47
|
+
await page.waitForSelector('svg[data-topo-layout]', { timeout: 15000 });
|
|
48
|
+
await page.waitForTimeout(800);
|
|
49
|
+
const data = await page.evaluate(() => {
|
|
50
|
+
const dots = Array.from(document.querySelectorAll('[data-topo-starfield-dot]'));
|
|
51
|
+
return dots.map((el) => ({
|
|
52
|
+
idx: el.getAttribute('data-topo-starfield-dot'),
|
|
53
|
+
hue: el.getAttribute('data-topo-starfield-dot-hue'),
|
|
54
|
+
fill: el.getAttribute('fill'),
|
|
55
|
+
}));
|
|
56
|
+
});
|
|
57
|
+
await browser.close();
|
|
58
|
+
return data;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const cyber = await probe('cyber');
|
|
62
|
+
const light = await probe('light');
|
|
63
|
+
|
|
64
|
+
// Source regex
|
|
65
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
66
|
+
const sourceHuesArr =
|
|
67
|
+
/const hues = \['#a5b4fc', '#67e8f9', '#cbd5e1'\] as const;/.test(src);
|
|
68
|
+
const sourceNamesArr =
|
|
69
|
+
/const hueNames = \['indigo', 'cyan', 'slate'\] as const;/.test(src);
|
|
70
|
+
const sourceAttrWired =
|
|
71
|
+
/data-topo-starfield-dot-hue=\{hueNames\[hueIdx\]\}/.test(src);
|
|
72
|
+
|
|
73
|
+
// Cyber: 14 dots, distribution by i % 3
|
|
74
|
+
const cyberHueCounts = { indigo: 0, cyan: 0, slate: 0 };
|
|
75
|
+
for (const d of cyber) {
|
|
76
|
+
if (d.hue && cyberHueCounts[d.hue] !== undefined) cyberHueCounts[d.hue]++;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Verify each idx has the right hue per i % 3
|
|
80
|
+
const cyberIdxMatch = cyber.every((d) => {
|
|
81
|
+
const i = parseInt(d.idx, 10);
|
|
82
|
+
const expected = ['indigo', 'cyan', 'slate'][i % 3];
|
|
83
|
+
return d.hue === expected;
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Verify fill matches the hue
|
|
87
|
+
const cyberFillMatch = cyber.every((d) => {
|
|
88
|
+
const expectedFill = { indigo: '#a5b4fc', cyan: '#67e8f9', slate: '#cbd5e1' }[d.hue];
|
|
89
|
+
return d.fill === expectedFill;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const results = {
|
|
93
|
+
cyber_dot_count_14: cyber.length === 14,
|
|
94
|
+
cyber_indigo_count_5: cyberHueCounts.indigo === 5, // i=0,3,6,9,12 → 5
|
|
95
|
+
cyber_cyan_count_5: cyberHueCounts.cyan === 5, // i=1,4,7,10,13 → 5
|
|
96
|
+
cyber_slate_count_4: cyberHueCounts.slate === 4, // i=2,5,8,11 → 4
|
|
97
|
+
cyber_idx_to_hue_match: cyberIdxMatch,
|
|
98
|
+
cyber_hue_to_fill_match: cyberFillMatch,
|
|
99
|
+
light_starfield_empty: light.length === 0,
|
|
100
|
+
source_hues_array: sourceHuesArr,
|
|
101
|
+
source_names_array: sourceNamesArr,
|
|
102
|
+
source_attr_wired: sourceAttrWired,
|
|
103
|
+
};
|
|
104
|
+
const ok = Object.values(results).every(Boolean);
|
|
105
|
+
console.log(`${ok ? '✅' : '❌'} R523 starfield 3-hue rotation:`,
|
|
106
|
+
JSON.stringify(results, null, 2),
|
|
107
|
+
'\n cyber distribution:', JSON.stringify(cyberHueCounts),
|
|
108
|
+
'\n light count:', light.length);
|
|
109
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/* Round 496 verification: vendor letter chip (data-vendor-letter-
|
|
2
|
+
* hover-lift="true") + active-links chip (data-active-links-chip)
|
|
3
|
+
* join active:scale-95 press family. Brings press family from 13
|
|
4
|
+
* surfaces (R495) to 15.
|
|
5
|
+
*
|
|
6
|
+
* Active-links chip is gated on isInteractive (flowLinks.length > 0)
|
|
7
|
+
* — fixture provides at least 1 active edge via working session.
|
|
8
|
+
* Vendor letter chip renders 1× per distinct vendor (cli runtime: 1 +
|
|
9
|
+
* any others). Test uses fixture with claude-code-cli only.
|
|
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('alpha·a1', 'working'),
|
|
38
|
+
mk('alpha·a2', 'idle'),
|
|
39
|
+
] } });
|
|
40
|
+
});
|
|
41
|
+
// Provide messages so flowLinks isInteractive activates (R206 gate)
|
|
42
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
43
|
+
{ id: 'm1', from_alias: 'alpha·a1', to_alias: 'alpha·a2', content: 'test', created_at: fresh },
|
|
44
|
+
] } }));
|
|
45
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
46
|
+
const page = await ctx.newPage();
|
|
47
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
48
|
+
await page.waitForTimeout(1500);
|
|
49
|
+
|
|
50
|
+
const vendor = await page.evaluate(() => {
|
|
51
|
+
const els = Array.from(document.querySelectorAll('[data-vendor-letter-hover-lift="true"]'));
|
|
52
|
+
return els.map((el) => {
|
|
53
|
+
const cs = window.getComputedStyle(el);
|
|
54
|
+
return {
|
|
55
|
+
cls_has_scale95: /active:scale-95/.test(el.className || ''),
|
|
56
|
+
cls_has_lift: /hover:-translate-y-px/.test(el.className || ''),
|
|
57
|
+
tp_has_transform:/transform/i.test(cs.transitionProperty || ''),
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const active = await page.evaluate(() => {
|
|
63
|
+
const el = document.querySelector('[data-active-links-chip]');
|
|
64
|
+
if (!el) return null;
|
|
65
|
+
const cs = window.getComputedStyle(el);
|
|
66
|
+
return {
|
|
67
|
+
cls_has_scale95: /active:scale-95/.test(el.className || ''),
|
|
68
|
+
cls_has_lift: /hover:-translate-y-px/.test(el.className || ''),
|
|
69
|
+
clickable: el.getAttribute('data-active-links-clickable'),
|
|
70
|
+
tp_has_transform:/transform/i.test(cs.transitionProperty || ''),
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await browser.close();
|
|
75
|
+
|
|
76
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
77
|
+
const sVendor = /transition-transform duration-200 ease-out transform-gpu hover:-translate-y-px active:scale-95"/.test(src);
|
|
78
|
+
const sActive = /hover:bg-cyan-500\/10 hover:text-cyan-200 hover:border-cyan-500\/30 hover:-translate-y-px active:scale-95'/.test(src);
|
|
79
|
+
|
|
80
|
+
const allVendorsScale = vendor.length === 0 || vendor.every((v) => v.cls_has_scale95);
|
|
81
|
+
const allVendorsLift = vendor.length === 0 || vendor.every((v) => v.cls_has_lift);
|
|
82
|
+
const allVendorsTp = vendor.length === 0 || vendor.every((v) => v.tp_has_transform);
|
|
83
|
+
|
|
84
|
+
const results = {
|
|
85
|
+
source_vendor_wired: sVendor,
|
|
86
|
+
source_active_wired: sActive,
|
|
87
|
+
vendor_rendered_or_zero: vendor.length >= 0, // tautology — gate signal only
|
|
88
|
+
vendor_all_have_scale: allVendorsScale,
|
|
89
|
+
vendor_all_have_lift: allVendorsLift,
|
|
90
|
+
vendor_all_tp_transform: allVendorsTp,
|
|
91
|
+
active_dom_found: !!active,
|
|
92
|
+
// active-links only carries scale-95 when isInteractive=clickable=true
|
|
93
|
+
active_class_correct: !active || (active.clickable === 'true' ? active.cls_has_scale95 : true),
|
|
94
|
+
active_lift_correct: !active || (active.clickable === 'true' ? active.cls_has_lift : true),
|
|
95
|
+
active_tp_transform: !active || active.tp_has_transform,
|
|
96
|
+
};
|
|
97
|
+
const ok = Object.values(results).every(Boolean);
|
|
98
|
+
console.log(`${ok ? '✅' : '❌'} R496 vendor+active-links press:`, JSON.stringify(results),
|
|
99
|
+
'\n vendor count:', vendor.length, ' active clickable:', active && active.clickable);
|
|
100
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/* Round 519 verification: brand watermark gains ambient SMIL breath
|
|
2
|
+
* animation — 呼吸感 family 3rd anchor.
|
|
3
|
+
*
|
|
4
|
+
* Test phases:
|
|
5
|
+
* 1. default (motion enabled): data-topo-brand-watermark-breath='true'
|
|
6
|
+
* + <animate> child mounted inside the <text>
|
|
7
|
+
* + animate values='0.32;0.48;0.32', dur='6s', repeatCount='indefinite'
|
|
8
|
+
* 2. prefers-reduced-motion: data-topo-brand-watermark-breath='false'
|
|
9
|
+
* + NO <animate> child (gated out at JSX level)
|
|
10
|
+
* 3. source-side regex confirms SMIL gate + values + duration
|
|
11
|
+
* 4. zero-overlap is gated separately by topo-overlap-test.mjs
|
|
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
|
+
async function probe(reducedMotion) {
|
|
20
|
+
const browser = await chromium.launch({ headless: true });
|
|
21
|
+
const ctx = await browser.newContext({
|
|
22
|
+
viewport: { width: 1500, height: 1200 },
|
|
23
|
+
reducedMotion: reducedMotion ? 'reduce' : 'no-preference',
|
|
24
|
+
});
|
|
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: [mk('a·1')] } });
|
|
43
|
+
});
|
|
44
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
45
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
46
|
+
const page = await ctx.newPage();
|
|
47
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
48
|
+
await page.waitForSelector('[data-topo-brand-watermark]', { timeout: 15000 });
|
|
49
|
+
await page.waitForTimeout(800);
|
|
50
|
+
const probe = await page.evaluate(() => {
|
|
51
|
+
const el = document.querySelector('[data-topo-brand-watermark]');
|
|
52
|
+
if (!el) return null;
|
|
53
|
+
const animate = el.querySelector('animate');
|
|
54
|
+
return {
|
|
55
|
+
attrBreath: el.getAttribute('data-topo-brand-watermark-breath'),
|
|
56
|
+
hasAnimate: !!animate,
|
|
57
|
+
attrName: animate?.getAttribute('attributeName') || null,
|
|
58
|
+
values: animate?.getAttribute('values') || null,
|
|
59
|
+
dur: animate?.getAttribute('dur') || null,
|
|
60
|
+
repeatCount: animate?.getAttribute('repeatCount') || null,
|
|
61
|
+
textContent: el.textContent?.trim() || null,
|
|
62
|
+
opacity: el.getAttribute('opacity'),
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
await browser.close();
|
|
66
|
+
return probe;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const normal = await probe(false);
|
|
70
|
+
const reduced = await probe(true);
|
|
71
|
+
|
|
72
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
73
|
+
const sourceWiredGate =
|
|
74
|
+
/\{!reducedMotion && \(\s*<animate attributeName="opacity" values="0\.32;0\.48;0\.32" dur="6s" repeatCount="indefinite" \/>\s*\)\}/.test(src);
|
|
75
|
+
const sourceWiredAttr =
|
|
76
|
+
/data-topo-brand-watermark-breath=\{reducedMotion \? 'false' : 'true'\}/.test(src);
|
|
77
|
+
|
|
78
|
+
const results = {
|
|
79
|
+
// Phase 1: motion enabled
|
|
80
|
+
normal_attr_true: normal?.attrBreath === 'true',
|
|
81
|
+
normal_has_animate: normal?.hasAnimate === true,
|
|
82
|
+
normal_attr_name_opacity: normal?.attrName === 'opacity',
|
|
83
|
+
normal_values_correct: normal?.values === '0.32;0.48;0.32',
|
|
84
|
+
normal_dur_6s: normal?.dur === '6s',
|
|
85
|
+
normal_repeat_indefinite: normal?.repeatCount === 'indefinite',
|
|
86
|
+
normal_text_content: normal?.textContent === 'sleep2agi',
|
|
87
|
+
normal_static_opacity_04: normal?.opacity === '0.4',
|
|
88
|
+
// Phase 2: prefers-reduced-motion
|
|
89
|
+
reduced_attr_false: reduced?.attrBreath === 'false',
|
|
90
|
+
reduced_no_animate: reduced?.hasAnimate === false,
|
|
91
|
+
reduced_text_content: reduced?.textContent === 'sleep2agi',
|
|
92
|
+
// Phase 3: source regex
|
|
93
|
+
source_animate_gated: sourceWiredGate,
|
|
94
|
+
source_attr_wired: sourceWiredAttr,
|
|
95
|
+
};
|
|
96
|
+
const ok = Object.values(results).every(Boolean);
|
|
97
|
+
console.log(`${ok ? '✅' : '❌'} R519 watermark breath:`, JSON.stringify(results, null, 2),
|
|
98
|
+
'\n normal:', JSON.stringify(normal),
|
|
99
|
+
'\n reduced:', JSON.stringify(reduced));
|
|
100
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/* Round 525 verification: brand watermark gains focal-recede on
|
|
2
|
+
* non-hub canvas hover — extends R507/R508 focal-recede pattern to
|
|
3
|
+
* 3rd anchor.
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. rest: wrapper opacity=1, recede attr='false'
|
|
7
|
+
* 2. hover an alias (non-hub canvas surface): wrapper opacity=0.7,
|
|
8
|
+
* recede attr='true'
|
|
9
|
+
* 3. mouseleave: wrapper opacity returns to 1
|
|
10
|
+
* 4. SMIL <animate> still mounted on inner text (R519 preserved)
|
|
11
|
+
* 5. source-side regex confirms wrapper opacity ternary + 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: [
|
|
39
|
+
mk('alpha·1'), mk('alpha·2'), mk('alpha·3'),
|
|
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-topo-brand-watermark-wrapper]', { timeout: 15000 });
|
|
47
|
+
await page.waitForTimeout(800);
|
|
48
|
+
|
|
49
|
+
// Phase 1: rest
|
|
50
|
+
const rest = await page.evaluate(() => {
|
|
51
|
+
const w = document.querySelector('[data-topo-brand-watermark-wrapper]');
|
|
52
|
+
const t = document.querySelector('[data-topo-brand-watermark]');
|
|
53
|
+
const animate = t?.querySelector('animate');
|
|
54
|
+
return {
|
|
55
|
+
wOpacity: w?.getAttribute('opacity'),
|
|
56
|
+
wRecede: w?.getAttribute('data-topo-brand-watermark-recede'),
|
|
57
|
+
hasAnimate: !!animate,
|
|
58
|
+
textContent: t?.textContent?.trim() || null,
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Phase 2: trigger focal-recede via hoveredStatus by hovering the
|
|
63
|
+
// legend `idle` row's label. setHoveredStatus is one of the recede
|
|
64
|
+
// gate vars; the label is a stable hover target (HTML+SVG safe per
|
|
65
|
+
// R518 test path).
|
|
66
|
+
await page.hover('[data-legend-row-label="idle"]');
|
|
67
|
+
await page.waitForTimeout(400);
|
|
68
|
+
const hover = await page.evaluate(() => {
|
|
69
|
+
const w = document.querySelector('[data-topo-brand-watermark-wrapper]');
|
|
70
|
+
return {
|
|
71
|
+
wOpacity: w?.getAttribute('opacity'),
|
|
72
|
+
wRecede: w?.getAttribute('data-topo-brand-watermark-recede'),
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Phase 3: physical mouse move far away from any hover target
|
|
77
|
+
await page.mouse.move(900, 50);
|
|
78
|
+
await page.waitForTimeout(400);
|
|
79
|
+
const leave = await page.evaluate(() => {
|
|
80
|
+
const w = document.querySelector('[data-topo-brand-watermark-wrapper]');
|
|
81
|
+
return {
|
|
82
|
+
wOpacity: w?.getAttribute('opacity'),
|
|
83
|
+
wRecede: w?.getAttribute('data-topo-brand-watermark-recede'),
|
|
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 sourceWiredOpacity =
|
|
92
|
+
/opacity=\{\(hoveredAlias \|\| hoveredEdgeKey \|\| hoveredGroupLabel \|\|\s*hoveredStatus \|\| hoveredVendor\) && !hoveredHub \? 0\.7 : 1\}/.test(src);
|
|
93
|
+
const sourceWiredAttr =
|
|
94
|
+
/data-topo-brand-watermark-recede=\{\s*\(hoveredAlias \|\| hoveredEdgeKey \|\| hoveredGroupLabel \|\|\s*hoveredStatus \|\| hoveredVendor\) && !hoveredHub \? 'true' : 'false'\s*\}/.test(src);
|
|
95
|
+
|
|
96
|
+
const results = {
|
|
97
|
+
rest_wrapper_opacity_1: rest?.wOpacity === '1',
|
|
98
|
+
rest_recede_false: rest?.wRecede === 'false',
|
|
99
|
+
rest_has_animate: rest?.hasAnimate === true, // R519 SMIL preserved
|
|
100
|
+
rest_text_content: rest?.textContent === 'sleep2agi',
|
|
101
|
+
hover_wrapper_opacity_07: hover?.wOpacity === '0.7',
|
|
102
|
+
hover_recede_true: hover?.wRecede === 'true',
|
|
103
|
+
leave_wrapper_opacity_1: leave?.wOpacity === '1',
|
|
104
|
+
leave_recede_false: leave?.wRecede === 'false',
|
|
105
|
+
source_opacity_wired: sourceWiredOpacity,
|
|
106
|
+
source_attr_wired: sourceWiredAttr,
|
|
107
|
+
};
|
|
108
|
+
const ok = Object.values(results).every(Boolean);
|
|
109
|
+
console.log(`${ok ? '✅' : '❌'} R525 watermark focal-recede:`,
|
|
110
|
+
JSON.stringify(results, null, 2),
|
|
111
|
+
'\n rest:', JSON.stringify(rest),
|
|
112
|
+
'\n hover:', JSON.stringify(hover),
|
|
113
|
+
'\n leave:', JSON.stringify(leave));
|
|
114
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/* Round 517 verification: chrome zoom-level readout gains a 3rd hover
|
|
2
|
+
* axis — color brighten from pal.legendText → pal.legendHeadline.
|
|
3
|
+
*
|
|
4
|
+
* Test phases:
|
|
5
|
+
* 1. rest: data-topo-chrome-zoom-level-color = 'text'
|
|
6
|
+
* + computed color matches pal.legendText (cyber: #94a3b8)
|
|
7
|
+
* 2. hover: data-topo-chrome-zoom-level-color = 'headline'
|
|
8
|
+
* + computed color matches pal.legendHeadline (cyber: #e5e7eb)
|
|
9
|
+
* + R347 letterSpacing still spreads (0.5px)
|
|
10
|
+
* + R420 fontWeight still lifts (600)
|
|
11
|
+
* 3. source-side regex confirms the color ternary 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) => ({
|
|
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-zoom-level]', { timeout: 15000 });
|
|
45
|
+
await page.waitForTimeout(800);
|
|
46
|
+
|
|
47
|
+
// Phase 1: rest
|
|
48
|
+
const rest = await page.evaluate(() => {
|
|
49
|
+
const el = document.querySelector('[data-topo-chrome-zoom-level]');
|
|
50
|
+
if (!el) return null;
|
|
51
|
+
const cs = getComputedStyle(el);
|
|
52
|
+
return {
|
|
53
|
+
attrColor: el.getAttribute('data-topo-chrome-zoom-level-color'),
|
|
54
|
+
attrHover: el.getAttribute('data-topo-chrome-zoom-level-hover'),
|
|
55
|
+
color: cs.color,
|
|
56
|
+
letterSpacing: cs.letterSpacing,
|
|
57
|
+
fontWeight: cs.fontWeight,
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Phase 2: hover
|
|
62
|
+
await page.hover('[data-topo-chrome-zoom-level]');
|
|
63
|
+
await page.waitForTimeout(350); // 200ms transition + slack
|
|
64
|
+
const hover = await page.evaluate(() => {
|
|
65
|
+
const el = document.querySelector('[data-topo-chrome-zoom-level]');
|
|
66
|
+
if (!el) return null;
|
|
67
|
+
const cs = getComputedStyle(el);
|
|
68
|
+
return {
|
|
69
|
+
attrColor: el.getAttribute('data-topo-chrome-zoom-level-color'),
|
|
70
|
+
attrHover: el.getAttribute('data-topo-chrome-zoom-level-hover'),
|
|
71
|
+
color: cs.color,
|
|
72
|
+
letterSpacing: cs.letterSpacing,
|
|
73
|
+
fontWeight: cs.fontWeight,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Phase 3: source regex
|
|
78
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
79
|
+
const sourceWired =
|
|
80
|
+
/color: hoveredZoomLevel \? pal\.legendHeadline : pal\.legendText,/.test(src) &&
|
|
81
|
+
/data-topo-chrome-zoom-level-color=\{hoveredZoomLevel \? 'headline' : 'text'\}/.test(src);
|
|
82
|
+
|
|
83
|
+
await browser.close();
|
|
84
|
+
|
|
85
|
+
// pal.legendText cyber = #94a3b8 → rgb(148, 163, 184)
|
|
86
|
+
// pal.legendHeadline cyber = #e5e7eb → rgb(229, 231, 235)
|
|
87
|
+
const restColor = 'rgb(148, 163, 184)';
|
|
88
|
+
const hoverColor = 'rgb(229, 231, 235)';
|
|
89
|
+
|
|
90
|
+
const results = {
|
|
91
|
+
rest_attr_text: rest?.attrColor === 'text',
|
|
92
|
+
rest_attr_hover_false: rest?.attrHover === 'false',
|
|
93
|
+
rest_color_legendText: rest?.color === restColor,
|
|
94
|
+
rest_letter_spacing_0: rest?.letterSpacing === '0px' || rest?.letterSpacing === 'normal',
|
|
95
|
+
hover_attr_headline: hover?.attrColor === 'headline',
|
|
96
|
+
hover_attr_hover_true: hover?.attrHover === 'true',
|
|
97
|
+
hover_color_legendHead: hover?.color === hoverColor,
|
|
98
|
+
hover_letter_spacing_5: hover?.letterSpacing === '0.5px',
|
|
99
|
+
hover_font_weight_600: hover?.fontWeight === '600',
|
|
100
|
+
source_wired: sourceWired,
|
|
101
|
+
};
|
|
102
|
+
const ok = Object.values(results).every(Boolean);
|
|
103
|
+
console.log(`${ok ? '✅' : '❌'} R517 zoom-level 3-axis hover:`, JSON.stringify(results, null, 2),
|
|
104
|
+
'\n rest:', JSON.stringify(rest), '\n hover:', JSON.stringify(hover));
|
|
105
|
+
process.exit(ok ? 0 : 1);
|