@sleep2agi/agent-network-dashboard 0.5.1-preview.8 → 0.5.1-preview.81
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 +6 -6
- 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/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/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/00-1ykc0vbxty.js +1 -0
- package/.next/static/chunks/017hq2-5l~_98.css +2 -0
- package/.next/static/chunks/06v9r0n6tmq02.js +4 -0
- package/.next/static/chunks/0bm3odi3zwrl_.js +1 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +1581 -89
- package/package.json +1 -1
- package/scripts/topo-active-links-chip-hover-lift-test.mjs +93 -0
- package/scripts/topo-chip-digit-fontweight-test.mjs +105 -0
- package/scripts/topo-chip-digit-hover-bold-test.mjs +94 -0
- package/scripts/topo-chip-row-group-hover-brighten-test.mjs +107 -0
- package/scripts/topo-chip-row-hover-lift-test.mjs +95 -0
- package/scripts/topo-chrome-button-hover-lift-test.mjs +94 -0
- package/scripts/topo-chrome-segmented-radius-test.mjs +100 -0
- package/scripts/topo-click-ripple-opacity-test.mjs +99 -0
- package/scripts/topo-edge-badge-fontsize-test.mjs +90 -0
- package/scripts/topo-edge-badge-hover-opacity-test.mjs +94 -0
- package/scripts/topo-edge-badge-hover-stroke-test.mjs +92 -0
- package/scripts/topo-edge-badge-opacity-test.mjs +80 -0
- package/scripts/topo-edge-badge-pin-opacity-test.mjs +86 -0
- package/scripts/topo-edge-badge-stroke-test.mjs +92 -0
- package/scripts/topo-edge-freshness-floor-test.mjs +99 -0
- package/scripts/topo-edge-visible-linecap-test.mjs +89 -0
- package/scripts/topo-filter-pill-hover-lift-test.mjs +101 -0
- package/scripts/topo-filter-pill-hover-opacity-test.mjs +110 -0
- package/scripts/topo-filter-pill-value-fw-test.mjs +88 -0
- package/scripts/topo-filter-pill-x-hover-scale-test.mjs +99 -0
- package/scripts/topo-flow-rail-linecap-test.mjs +79 -0
- package/scripts/topo-freshness-chip-hierarchy-test.mjs +93 -0
- package/scripts/topo-freshness-chip-tabular-test.mjs +41 -0
- package/scripts/topo-freshness-floor-lift-test.mjs +92 -0
- package/scripts/topo-freshness-suffix-tabular-test.mjs +88 -0
- package/scripts/topo-fullscreen-icon-hover-scale-test.mjs +91 -0
- package/scripts/topo-group-box-stroke-test.mjs +105 -0
- package/scripts/topo-group-label-count-fontweight-test.mjs +108 -0
- package/scripts/topo-hover-detail-body-fw-test.mjs +101 -0
- package/scripts/topo-hover-detail-model-fw-test.mjs +98 -0
- package/scripts/topo-hover-detail-opacity-test.mjs +98 -0
- package/scripts/topo-hover-detail-rx-test.mjs +81 -0
- package/scripts/topo-hub-digit-fontsize-test.mjs +86 -0
- package/scripts/topo-hub-halo-light-trough-test.mjs +88 -0
- package/scripts/topo-hub-halo-radius-test.mjs +86 -0
- package/scripts/topo-hub-halo-trough-test.mjs +83 -0
- package/scripts/topo-hub-highlight-opacity-test.mjs +88 -0
- package/scripts/topo-hub-highlight-radius-test.mjs +90 -0
- package/scripts/topo-hub-hover-ring-opacity-test.mjs +96 -0
- package/scripts/topo-hub-hover-ring-stroke-test.mjs +86 -0
- package/scripts/topo-hub-spoke-linecap-test.mjs +80 -0
- package/scripts/topo-layout-toggle-hover-tracking-test.mjs +109 -0
- package/scripts/topo-layout-toggle-radius-test.mjs +87 -0
- package/scripts/topo-legend-label-fontweight-test.mjs +94 -0
- package/scripts/topo-legend-pin-ring-stroke-test.mjs +101 -0
- package/scripts/topo-minimap-offline-opacity-test.mjs +90 -0
- package/scripts/topo-minimap-online-opacity-test.mjs +93 -0
- package/scripts/topo-minimap-online-radius-test.mjs +85 -0
- package/scripts/topo-minimap-viewport-linejoin-test.mjs +75 -0
- package/scripts/topo-minimap-viewport-rx-test.mjs +85 -0
- package/scripts/topo-more-flows-fontweight-test.mjs +103 -0
- package/scripts/topo-node-halo-offline-opacity-test.mjs +87 -0
- package/scripts/topo-node-label-card-rx-test.mjs +85 -0
- package/scripts/topo-node-pulse-peak-test.mjs +89 -0
- package/scripts/topo-node-pulse-trough-test.mjs +91 -0
- package/scripts/topo-panel-count-letterspacing-test.mjs +89 -0
- package/scripts/topo-panel-rect-opacity-hover-test.mjs +109 -0
- package/scripts/topo-pressure-bar-height-test.mjs +92 -0
- package/scripts/topo-pressure-kicker-fontweight-test.mjs +76 -0
- package/scripts/topo-recent-pip-radius-2-test.mjs +72 -0
- package/scripts/topo-recent-pip-radius-test.mjs +76 -0
- package/scripts/topo-recent-row-content-opacity-test.mjs +81 -0
- package/scripts/topo-recent-row-text-fontweight-test.mjs +90 -0
- package/scripts/topo-reset-hover-rotate-test.mjs +102 -0
- package/scripts/topo-spoke-active-opacity-test.mjs +104 -0
- package/scripts/topo-spoke-active-stroke-test.mjs +95 -0
- package/scripts/topo-spoke-idle-opacity-test.mjs +91 -0
- package/scripts/topo-vendor-chip-hover-lift-test.mjs +87 -0
- package/scripts/topo-vendor-glyph-fontweight-test.mjs +102 -0
- package/scripts/topo-vendor-letter-hover-scale-test.mjs +129 -0
- package/scripts/topo-vendor-suffix-hover-brighten-test.mjs +87 -0
- package/scripts/topo-zoom-icon-hover-scale-test.mjs +114 -0
- package/scripts/topo-zoom-level-hover-fw-test.mjs +95 -0
- package/.next/static/chunks/06132.qvlxn22.js +0 -4
- package/.next/static/chunks/0aauz~36q5n2a.css +0 -2
- package/.next/static/chunks/0vkj-grzc4zxy.js +0 -1
- package/.next/static/chunks/0x0kput204icg.js +0 -1
- /package/.next/static/{m-5OV2JFjgsIdYk1S2Lvx → 7M-H85_nP8uV0ksA_U7g_}/_buildManifest.js +0 -0
- /package/.next/static/{m-5OV2JFjgsIdYk1S2Lvx → 7M-H85_nP8uV0ksA_U7g_}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{m-5OV2JFjgsIdYk1S2Lvx → 7M-H85_nP8uV0ksA_U7g_}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* Round 360 verification: hub working-count digit fontSize 11 → 12.
|
|
2
|
+
* The hub is the canvas's focal point — its digit is the most-read
|
|
3
|
+
* scalar on the whole topology. R130 sized it at 11 inside the
|
|
4
|
+
* r=10 / 20-px core; R360 nudges to 12 (~13 px wide × 12 px tall,
|
|
5
|
+
* still well inside) for ~9 % more presence. Sibling visual-weight
|
|
6
|
+
* bump family with R287/R295/R359.
|
|
7
|
+
*
|
|
8
|
+
* Contract:
|
|
9
|
+
* - Hub digit font-size attr === '12'.
|
|
10
|
+
* - data-topo-hub-working-count-font-size === '12'.
|
|
11
|
+
* - data-topo-hub-working-count surfaces the count (>0 with mocked
|
|
12
|
+
* working sessions).
|
|
13
|
+
* - Pre-R360 invariants: R225 tabular-nums + R209 scale-on-hover
|
|
14
|
+
* transform-box still set, fontWeight=700, dy="0.36em" preserved.
|
|
15
|
+
* - Overlap-test stays green (digit is inside hub <g>, not a node
|
|
16
|
+
* the overlap probe scans).
|
|
17
|
+
*/
|
|
18
|
+
import { chromium } from 'playwright';
|
|
19
|
+
import { readFileSync } from 'node:fs';
|
|
20
|
+
|
|
21
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
22
|
+
const browser = await chromium.launch({ headless: true });
|
|
23
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
24
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
25
|
+
await ctx.addInitScript(() => {
|
|
26
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
27
|
+
});
|
|
28
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
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: 'working', 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
|
+
// 3 working sessions → workingCount=3 → digit visible.
|
|
39
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('a'), mk('b'), mk('c') ] } });
|
|
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
|
+
|
|
44
|
+
const page = await ctx.newPage();
|
|
45
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
46
|
+
await page.waitForSelector('[data-topo-hub-working-count]', { timeout: 15000 });
|
|
47
|
+
await page.waitForTimeout(300);
|
|
48
|
+
|
|
49
|
+
const probe = await page.evaluate(() => {
|
|
50
|
+
const t = document.querySelector('[data-topo-hub-working-count]');
|
|
51
|
+
const cs = t ? getComputedStyle(t) : null;
|
|
52
|
+
return {
|
|
53
|
+
fontSizeAttr: t?.getAttribute('font-size') ?? null,
|
|
54
|
+
fontSizeData: t?.getAttribute('data-topo-hub-working-count-font-size') ?? null,
|
|
55
|
+
countValue: t?.getAttribute('data-topo-hub-working-count') ?? null,
|
|
56
|
+
fontWeight: t?.getAttribute('font-weight') ?? null,
|
|
57
|
+
dy: t?.getAttribute('dy') ?? null,
|
|
58
|
+
fontVariant: cs?.fontVariantNumeric ?? null,
|
|
59
|
+
transformBox: cs?.transformBox ?? null,
|
|
60
|
+
transformOrigin: cs?.transformOrigin ?? null,
|
|
61
|
+
transition: cs?.transition ?? null,
|
|
62
|
+
opacity: t?.getAttribute('opacity') ?? null,
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await browser.close();
|
|
67
|
+
|
|
68
|
+
const hasTrans = (s, prop) =>
|
|
69
|
+
new RegExp(`${prop}\\s+\\d*\\.?\\d*s|${prop}\\s+\\d+ms`, 'i').test(s || '');
|
|
70
|
+
|
|
71
|
+
const results = {
|
|
72
|
+
font_size_attr_12: probe.fontSizeAttr === '12',
|
|
73
|
+
data_font_size_12: probe.fontSizeData === '12',
|
|
74
|
+
count_value_3: probe.countValue === '3', // 3 mocked working sessions
|
|
75
|
+
font_weight_700: probe.fontWeight === '700',
|
|
76
|
+
dy_0_36em: probe.dy === '0.36em',
|
|
77
|
+
tabular_nums: /tabular-nums/.test(probe.fontVariant || ''), // R225
|
|
78
|
+
transform_box_fill: probe.transformBox === 'fill-box', // R209
|
|
79
|
+
trans_has_transform: hasTrans(probe.transition, 'transform'), // R209
|
|
80
|
+
trans_has_fill: hasTrans(probe.transition, 'fill'), // R253
|
|
81
|
+
opacity_visible: probe.opacity === '1',
|
|
82
|
+
};
|
|
83
|
+
const ok = Object.values(results).every(Boolean);
|
|
84
|
+
console.log(`${ok ? '✅' : '❌'} hub digit fontSize 11 → 12:`, JSON.stringify(results),
|
|
85
|
+
'\n probe:', probe);
|
|
86
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/* Round 405 verification: hub-halo LIGHT trough 0.32 → 0.34 —
|
|
2
|
+
* symmetrizes R404 cyber treatment across both themes. Probes
|
|
3
|
+
* both cyber and light theme states via two browser contexts.
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - Idle fixture (workingCount=0, bucket=0):
|
|
7
|
+
* * cyber: data-topo-hub-halo-trough === '0.1' (R404 invariant)
|
|
8
|
+
* * light: data-topo-hub-halo-trough === '0.34' (R405 lift)
|
|
9
|
+
* * both: data-hub-busyness === '0'
|
|
10
|
+
* * both: data-topo-hub-halo-peak per-theme invariant
|
|
11
|
+
* (cyber 0.16, light 0.52)
|
|
12
|
+
* - Source-file verification:
|
|
13
|
+
* * const troughLight = 0.34;
|
|
14
|
+
* * const troughDark = 0.10;
|
|
15
|
+
*/
|
|
16
|
+
import { chromium } from 'playwright';
|
|
17
|
+
import { readFileSync } from 'node:fs';
|
|
18
|
+
|
|
19
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
20
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
21
|
+
|
|
22
|
+
async function probeTheme(theme) {
|
|
23
|
+
const browser = await chromium.launch({ headless: true });
|
|
24
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
25
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
26
|
+
await ctx.addInitScript((t) => {
|
|
27
|
+
try { localStorage.setItem('anet-theme', t); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
28
|
+
}, theme);
|
|
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('alpha'), mk('beta') ] } });
|
|
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: 'domcontentloaded' });
|
|
44
|
+
await page.waitForSelector('[data-hub-busyness]', { timeout: 15000 });
|
|
45
|
+
await page.waitForTimeout(400);
|
|
46
|
+
const probe = await page.evaluate(() => {
|
|
47
|
+
const halo = document.querySelector('[data-hub-busyness]');
|
|
48
|
+
if (!halo) return null;
|
|
49
|
+
return {
|
|
50
|
+
busyness: halo.getAttribute('data-hub-busyness'),
|
|
51
|
+
trough: halo.getAttribute('data-topo-hub-halo-trough'),
|
|
52
|
+
peak: halo.getAttribute('data-topo-hub-halo-peak'),
|
|
53
|
+
fill: halo.getAttribute('fill'),
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
await browser.close();
|
|
57
|
+
return probe;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const cyber = await probeTheme('cyber');
|
|
61
|
+
const light = await probeTheme('light');
|
|
62
|
+
|
|
63
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
64
|
+
const sourceLight034 = /const troughLight\s*=\s*0\.34;/.test(fileText);
|
|
65
|
+
const sourceDark010 = /const troughDark\s*=\s*0\.10;/.test(fileText);
|
|
66
|
+
const sourceLightPeak = /const peakLight\s*=\s*\[0\.52, 0\.58, 0\.65, 0\.72\]\[busy\];/.test(fileText);
|
|
67
|
+
|
|
68
|
+
const results = {
|
|
69
|
+
// Cyber R404 invariant
|
|
70
|
+
cyber_busy_0: cyber?.busyness === '0',
|
|
71
|
+
cyber_trough_0_1: cyber?.trough === '0.1',
|
|
72
|
+
cyber_peak_0_16: cyber?.peak === '0.16',
|
|
73
|
+
cyber_fill_dark: cyber?.fill === '#10b981',
|
|
74
|
+
// Light R405 lift
|
|
75
|
+
light_busy_0: light?.busyness === '0',
|
|
76
|
+
light_trough_0_34: light?.trough === '0.34',
|
|
77
|
+
light_peak_0_52: light?.peak === '0.52',
|
|
78
|
+
light_fill_light: light?.fill === '#d1fae5',
|
|
79
|
+
// Source-file canonical wire
|
|
80
|
+
source_light_034: sourceLight034,
|
|
81
|
+
source_dark_010: sourceDark010,
|
|
82
|
+
source_light_peak: sourceLightPeak,
|
|
83
|
+
};
|
|
84
|
+
const ok = Object.values(results).every(Boolean);
|
|
85
|
+
console.log(`${ok ? '✅' : '❌'} hub-halo light trough 0.32 → 0.34:`, JSON.stringify(results),
|
|
86
|
+
'\n cyber:', cyber,
|
|
87
|
+
'\n light:', light);
|
|
88
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* Round 408 verification: hub-halo radius 18 → 20. Visual-weight
|
|
2
|
+
* bump family 13th anchor — the canvas's signature breath element
|
|
3
|
+
* gets +2px radius (~23% area increase). Per-bucket opacity envelope
|
|
4
|
+
* and breath rhythm preserved exactly.
|
|
5
|
+
*
|
|
6
|
+
* Contract:
|
|
7
|
+
* - The hub-halo <circle> r attr === '20'
|
|
8
|
+
* - data-topo-hub-halo-radius === '20'
|
|
9
|
+
* - Pre-R408 invariants preserved:
|
|
10
|
+
* * R404 cyber trough '0.1'
|
|
11
|
+
* * R405 light trough '0.34'
|
|
12
|
+
* * idle bucket peakDark '0.16'
|
|
13
|
+
* * data-hub-busyness === '0' for all-idle fixture
|
|
14
|
+
* * fill remains theme-correct (#10b981 cyber / #d1fae5 light)
|
|
15
|
+
*
|
|
16
|
+
* Source-file verification of the radius change for redundancy.
|
|
17
|
+
*/
|
|
18
|
+
import { chromium } from 'playwright';
|
|
19
|
+
import { readFileSync } from 'node:fs';
|
|
20
|
+
|
|
21
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
22
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
23
|
+
|
|
24
|
+
const browser = await chromium.launch({ headless: true });
|
|
25
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
26
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
27
|
+
await ctx.addInitScript(() => {
|
|
28
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } 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('alpha'), mk('beta') ] } });
|
|
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
|
+
|
|
44
|
+
const page = await ctx.newPage();
|
|
45
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
46
|
+
await page.waitForSelector('[data-hub-busyness]', { timeout: 15000 });
|
|
47
|
+
await page.waitForTimeout(400);
|
|
48
|
+
|
|
49
|
+
const probe = await page.evaluate(() => {
|
|
50
|
+
const halo = document.querySelector('[data-hub-busyness]');
|
|
51
|
+
if (!halo) return null;
|
|
52
|
+
return {
|
|
53
|
+
busyness: halo.getAttribute('data-hub-busyness'),
|
|
54
|
+
rAttr: halo.getAttribute('r'),
|
|
55
|
+
rData: halo.getAttribute('data-topo-hub-halo-radius'),
|
|
56
|
+
trough: halo.getAttribute('data-topo-hub-halo-trough'),
|
|
57
|
+
peak: halo.getAttribute('data-topo-hub-halo-peak'),
|
|
58
|
+
fill: halo.getAttribute('fill'),
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
63
|
+
const sourceR20 = /cx=\{cx\} cy=\{cy\} r="20"/.test(fileText);
|
|
64
|
+
const sourceDataR20 = /data-topo-hub-halo-radius="20"/.test(fileText);
|
|
65
|
+
|
|
66
|
+
await browser.close();
|
|
67
|
+
|
|
68
|
+
const results = {
|
|
69
|
+
// R408 wire
|
|
70
|
+
r_attr_20: probe?.rAttr === '20',
|
|
71
|
+
r_data_20: probe?.rData === '20',
|
|
72
|
+
// R404/R405 trough invariants preserved
|
|
73
|
+
cyber_trough_0_1: probe?.trough === '0.1',
|
|
74
|
+
// R84 idle bucket peak invariant
|
|
75
|
+
cyber_peak_0_16: probe?.peak === '0.16',
|
|
76
|
+
// Pre-R408 base invariants
|
|
77
|
+
busyness_0: probe?.busyness === '0',
|
|
78
|
+
fill_cyber: probe?.fill === '#10b981',
|
|
79
|
+
// Source-file canonical wire
|
|
80
|
+
source_r_20: sourceR20,
|
|
81
|
+
source_data_r_20: sourceDataR20,
|
|
82
|
+
};
|
|
83
|
+
const ok = Object.values(results).every(Boolean);
|
|
84
|
+
console.log(`${ok ? '✅' : '❌'} hub-halo radius 18 → 20:`, JSON.stringify(results),
|
|
85
|
+
'\n probe:', probe);
|
|
86
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/* Round 404 verification: hub-halo SMIL trough opacity cyber 0.08
|
|
2
|
+
* → 0.10. Extends the stale-state legibility lift family (R317 /
|
|
3
|
+
* R358 / R372) to the canvas's signature breath low-point.
|
|
4
|
+
* Per-bucket peaks [0.16/0.20/0.26/0.32] unchanged so the R84
|
|
5
|
+
* breath tuning is preserved.
|
|
6
|
+
*
|
|
7
|
+
* Contract:
|
|
8
|
+
* - Idle fixture (no working sessions, bucket=0):
|
|
9
|
+
* * data-hub-busyness === '0'
|
|
10
|
+
* * data-topo-hub-halo-trough === '0.1' (cyber theme)
|
|
11
|
+
* * data-topo-hub-halo-peak === '0.16' (idle bucket peak invariant)
|
|
12
|
+
* - Source-file verification of:
|
|
13
|
+
* * `const troughDark = 0.10;`
|
|
14
|
+
* * peakDark array unchanged
|
|
15
|
+
*/
|
|
16
|
+
import { chromium } from 'playwright';
|
|
17
|
+
import { readFileSync } from 'node:fs';
|
|
18
|
+
|
|
19
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
20
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
21
|
+
|
|
22
|
+
const browser = await chromium.launch({ headless: true });
|
|
23
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
24
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
25
|
+
await ctx.addInitScript(() => {
|
|
26
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
27
|
+
});
|
|
28
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
29
|
+
const r = await route.fetch();
|
|
30
|
+
const b = await r.json();
|
|
31
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
32
|
+
// All idle so workingCount=0, busy bucket=0 (peak 0.16)
|
|
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('alpha'), mk('beta') ] } });
|
|
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
|
+
|
|
43
|
+
const page = await ctx.newPage();
|
|
44
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
45
|
+
await page.waitForSelector('[data-hub-busyness]', { timeout: 15000 });
|
|
46
|
+
await page.waitForTimeout(400);
|
|
47
|
+
|
|
48
|
+
const probe = await page.evaluate(() => {
|
|
49
|
+
const halo = document.querySelector('[data-hub-busyness]');
|
|
50
|
+
if (!halo) return null;
|
|
51
|
+
return {
|
|
52
|
+
busyness: halo.getAttribute('data-hub-busyness'),
|
|
53
|
+
trough: halo.getAttribute('data-topo-hub-halo-trough'),
|
|
54
|
+
peak: halo.getAttribute('data-topo-hub-halo-peak'),
|
|
55
|
+
radius: halo.getAttribute('r'),
|
|
56
|
+
fill: halo.getAttribute('fill'),
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
61
|
+
const sourceHasTrough010 = /const troughDark\s*=\s*0\.10;/.test(fileText);
|
|
62
|
+
const sourceHasPeakArray = /const peakDark\s*=\s*\[0\.16, 0\.20, 0\.26, 0\.32\]\[busy\];/.test(fileText);
|
|
63
|
+
|
|
64
|
+
await browser.close();
|
|
65
|
+
|
|
66
|
+
const results = {
|
|
67
|
+
// Idle fixture invariants
|
|
68
|
+
busyness_0: probe?.busyness === '0',
|
|
69
|
+
// R404: cyber trough lifted to 0.10
|
|
70
|
+
trough_cyber_0_1: probe?.trough === '0.1',
|
|
71
|
+
// R84 peak invariants (bucket=0 idle peak)
|
|
72
|
+
peak_idle_0_16: probe?.peak === '0.16',
|
|
73
|
+
// Pre-R404 base hub-halo invariants
|
|
74
|
+
radius_18: probe?.radius === '18',
|
|
75
|
+
fill_cyber: probe?.fill === '#10b981',
|
|
76
|
+
// Source-file canonical wire
|
|
77
|
+
source_trough_010: sourceHasTrough010,
|
|
78
|
+
source_peak_array: sourceHasPeakArray,
|
|
79
|
+
};
|
|
80
|
+
const ok = Object.values(results).every(Boolean);
|
|
81
|
+
console.log(`${ok ? '✅' : '❌'} hub-halo cyber trough 0.08 → 0.10:`, JSON.stringify(results),
|
|
82
|
+
'\n probe:', probe);
|
|
83
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/* Round 386 verification: hub-highlight idle opacity 0.9 → 0.95.
|
|
2
|
+
* Theme-consistency / canvas-presence polish family (4th anchor)
|
|
3
|
+
* after R370 hub-ring 0.7→0.8 cyber, R371 edge-badge 0.82→0.85
|
|
4
|
+
* cyber, R372 minimap offline 0.5→0.6. Lifts the focal point's
|
|
5
|
+
* idle "lamp lit but no work" core from a faded 0.9 to a present
|
|
6
|
+
* 0.95 (idle alpha gap halved).
|
|
7
|
+
*
|
|
8
|
+
* Contract:
|
|
9
|
+
* - When workingCount === 0 (all sessions idle / connected):
|
|
10
|
+
* * opacity attr === '0.95'
|
|
11
|
+
* * data-topo-hub-highlight-opacity === '0.95'
|
|
12
|
+
* * data-topo-hub-highlight-visible === 'true'
|
|
13
|
+
* - When workingCount > 0 (≥ 1 working session):
|
|
14
|
+
* * opacity attr === '0' (R130 takeover gate preserved)
|
|
15
|
+
* * data-topo-hub-highlight-visible === 'false'
|
|
16
|
+
* - Pre-R386 invariants preserved:
|
|
17
|
+
* * data-topo-hub-highlight-radius === '5.5' (R365)
|
|
18
|
+
* * fill === '#d1fae5'
|
|
19
|
+
*
|
|
20
|
+
* Test fixture supplies all-idle and all-working scenarios via
|
|
21
|
+
* /api/hub/status route fulfillment.
|
|
22
|
+
*/
|
|
23
|
+
import { chromium } from 'playwright';
|
|
24
|
+
import { readFileSync } from 'node:fs';
|
|
25
|
+
|
|
26
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
27
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
28
|
+
|
|
29
|
+
async function probeWith(sessionStatus) {
|
|
30
|
+
const browser = await chromium.launch({ headless: true });
|
|
31
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
32
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
33
|
+
await ctx.addInitScript(() => {
|
|
34
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
35
|
+
});
|
|
36
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
37
|
+
const r = await route.fetch();
|
|
38
|
+
const b = await r.json();
|
|
39
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
40
|
+
const mk = (alias) => ({
|
|
41
|
+
alias, status: sessionStatus, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
42
|
+
network_id: nid, project_dir: null,
|
|
43
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
44
|
+
});
|
|
45
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('a'), mk('b') ] } });
|
|
46
|
+
});
|
|
47
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
48
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
49
|
+
const page = await ctx.newPage();
|
|
50
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
51
|
+
await page.waitForSelector('[data-topo-hub-highlight]', { timeout: 15000 });
|
|
52
|
+
await page.waitForTimeout(350);
|
|
53
|
+
const probe = await page.evaluate(() => {
|
|
54
|
+
const e = document.querySelector('[data-topo-hub-highlight]');
|
|
55
|
+
return {
|
|
56
|
+
opacityAttr: e?.getAttribute('opacity') ?? null,
|
|
57
|
+
opacityData: e?.getAttribute('data-topo-hub-highlight-opacity') ?? null,
|
|
58
|
+
visible: e?.getAttribute('data-topo-hub-highlight-visible') ?? null,
|
|
59
|
+
radius: e?.getAttribute('data-topo-hub-highlight-radius') ?? null,
|
|
60
|
+
fill: e?.getAttribute('fill') ?? null,
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
await browser.close();
|
|
64
|
+
return probe;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const idle = await probeWith('idle');
|
|
68
|
+
const working = await probeWith('working');
|
|
69
|
+
|
|
70
|
+
const results = {
|
|
71
|
+
// Idle: lifted opacity 0.95 visible
|
|
72
|
+
idle_opacity_attr_0_95: idle.opacityAttr === '0.95',
|
|
73
|
+
idle_opacity_data_0_95: idle.opacityData === '0.95',
|
|
74
|
+
idle_visible_true: idle.visible === 'true',
|
|
75
|
+
// Working: R130 takeover, opacity 0
|
|
76
|
+
working_opacity_attr_0: working.opacityAttr === '0',
|
|
77
|
+
working_visible_false: working.visible === 'false',
|
|
78
|
+
// Cross-state invariants (R365 + fill)
|
|
79
|
+
radius_5_5_idle: idle.radius === '5.5',
|
|
80
|
+
radius_5_5_working: working.radius === '5.5',
|
|
81
|
+
fill_d1fae5_idle: idle.fill === '#d1fae5',
|
|
82
|
+
fill_d1fae5_working: working.fill === '#d1fae5',
|
|
83
|
+
};
|
|
84
|
+
const ok = Object.values(results).every(Boolean);
|
|
85
|
+
console.log(`${ok ? '✅' : '❌'} hub-highlight idle opacity 0.9 → 0.95:`, JSON.stringify(results),
|
|
86
|
+
'\n idle: ', idle,
|
|
87
|
+
'\n working:', working);
|
|
88
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/* Round 365 verification: hub-center 'lit-lamp' decorative highlight
|
|
2
|
+
* circle radius 5 → 5.5. Visible when workingCount === 0 (idle fleet
|
|
3
|
+
* decor per R130). Sibling visual-weight bump family — extends to
|
|
4
|
+
* 6 canvas anchors:
|
|
5
|
+
* R287 minimap viewport stroke 1 → 1.5
|
|
6
|
+
* R295 legend swatch base radius 5.5 → 6
|
|
7
|
+
* R359 recent-row pip base radius 1.6 → 1.8
|
|
8
|
+
* R360 hub digit fontSize 11 → 12
|
|
9
|
+
* R361 edge-badge digit fontSize 10 → 11
|
|
10
|
+
* R365 hub-highlight base radius 5 → 5.5 (this round)
|
|
11
|
+
*
|
|
12
|
+
* 21 % area bump (π·5.5² / π·5² = 1.21). Still well inside r=10 core.
|
|
13
|
+
*
|
|
14
|
+
* Test approach: feed an IDLE fleet (no working sessions) so the
|
|
15
|
+
* highlight is fully opaque.
|
|
16
|
+
*
|
|
17
|
+
* Contract:
|
|
18
|
+
* - data-topo-hub-highlight element r attr === '5.5'.
|
|
19
|
+
* - data-topo-hub-highlight-radius === '5.5'.
|
|
20
|
+
* - data-topo-hub-highlight-visible === 'true' (idle fleet).
|
|
21
|
+
* - opacity attr === '0.9' (workingCount === 0 branch).
|
|
22
|
+
* - Pre-R365 invariants:
|
|
23
|
+
* * cx + cy unchanged (visual center stable)
|
|
24
|
+
* * fill='#d1fae5' (R130 lamp color)
|
|
25
|
+
* * style.transition contains opacity (R213 always-mount gate)
|
|
26
|
+
* * pointerEvents: 'none' (R130)
|
|
27
|
+
*/
|
|
28
|
+
import { chromium } from 'playwright';
|
|
29
|
+
import { readFileSync } from 'node:fs';
|
|
30
|
+
|
|
31
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
32
|
+
const browser = await chromium.launch({ headless: true });
|
|
33
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
34
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
35
|
+
await ctx.addInitScript(() => {
|
|
36
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
37
|
+
});
|
|
38
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
39
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
40
|
+
const r = await route.fetch();
|
|
41
|
+
const b = await r.json();
|
|
42
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
43
|
+
// IDLE: status !== 'working' so workingCount=0 and the highlight is opaque.
|
|
44
|
+
const mk = (alias) => ({
|
|
45
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
46
|
+
network_id: nid, project_dir: null,
|
|
47
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
48
|
+
});
|
|
49
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('a'), mk('b'), mk('c') ] } });
|
|
50
|
+
});
|
|
51
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
52
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
53
|
+
|
|
54
|
+
const page = await ctx.newPage();
|
|
55
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
56
|
+
await page.waitForSelector('[data-topo-hub-highlight]', { timeout: 15000 });
|
|
57
|
+
await page.waitForTimeout(300);
|
|
58
|
+
|
|
59
|
+
const probe = await page.evaluate(() => {
|
|
60
|
+
const h = document.querySelector('[data-topo-hub-highlight]');
|
|
61
|
+
const cs = h ? getComputedStyle(h) : null;
|
|
62
|
+
return {
|
|
63
|
+
rAttr: h?.getAttribute('r') ?? null,
|
|
64
|
+
rData: h?.getAttribute('data-topo-hub-highlight-radius') ?? null,
|
|
65
|
+
visibleAttr: h?.getAttribute('data-topo-hub-highlight-visible') ?? null,
|
|
66
|
+
opacityAttr: h?.getAttribute('opacity') ?? null,
|
|
67
|
+
fill: h?.getAttribute('fill') ?? null,
|
|
68
|
+
transition: cs?.transition ?? null,
|
|
69
|
+
pointerEv: cs?.pointerEvents ?? null,
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
await browser.close();
|
|
74
|
+
|
|
75
|
+
const hasTrans = (s, prop) =>
|
|
76
|
+
new RegExp(`${prop}\\s+\\d*\\.?\\d*s|${prop}\\s+\\d+ms`, 'i').test(s || '');
|
|
77
|
+
|
|
78
|
+
const results = {
|
|
79
|
+
r_attr_5_5: probe.rAttr === '5.5',
|
|
80
|
+
r_data_5_5: probe.rData === '5.5',
|
|
81
|
+
visible_true: probe.visibleAttr === 'true',
|
|
82
|
+
opacity_0_9: probe.opacityAttr === '0.9',
|
|
83
|
+
fill_d1fae5: probe.fill === '#d1fae5',
|
|
84
|
+
trans_has_opacity: hasTrans(probe.transition, 'opacity'),
|
|
85
|
+
pointer_events_none: probe.pointerEv === 'none',
|
|
86
|
+
};
|
|
87
|
+
const ok = Object.values(results).every(Boolean);
|
|
88
|
+
console.log(`${ok ? '✅' : '❌'} hub-highlight radius 5 → 5.5:`, JSON.stringify(results),
|
|
89
|
+
'\n probe:', probe);
|
|
90
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/* Round 370 verification: hub hover-ring cyber opacity 0.7 → 0.8.
|
|
2
|
+
* R177 designed the hub hover-ring at opacity-0 → 0.85 (light) / 0 →
|
|
3
|
+
* 0.7 (cyber). The 15 % gap between themes meant cyber-theme users
|
|
4
|
+
* got a noticeably softer hover cue than light-theme users against
|
|
5
|
+
* backgrounds that should equalise (dark bg needs more luminance to
|
|
6
|
+
* read as 'on'). R370 bumps cyber 0.7 → 0.8, narrowing the theme
|
|
7
|
+
* gap to 5 % (light stays at 0.85).
|
|
8
|
+
*
|
|
9
|
+
* Contract (cyber theme):
|
|
10
|
+
* - Rest (hub NOT hovered): hub-hover-ring opacity attr === '0'.
|
|
11
|
+
* - Hover hub: opacity attr === '0.8'.
|
|
12
|
+
* - data-topo-hub-hover-ring-opacity === '0.8' on hover.
|
|
13
|
+
* - Pre-R370 invariants:
|
|
14
|
+
* * r=17 on hover (R177)
|
|
15
|
+
* * stroke=#10b981 (cyber, R253)
|
|
16
|
+
* * strokeWidth=1.5
|
|
17
|
+
* * pointerEvents:none
|
|
18
|
+
* * R177 r + opacity transitions preserved
|
|
19
|
+
*/
|
|
20
|
+
import { chromium } from 'playwright';
|
|
21
|
+
import { readFileSync } from 'node:fs';
|
|
22
|
+
|
|
23
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
24
|
+
const browser = await chromium.launch({ headless: true });
|
|
25
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
26
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
27
|
+
await ctx.addInitScript(() => {
|
|
28
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
29
|
+
});
|
|
30
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
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) => ({
|
|
36
|
+
alias, status: 'working', 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: [ mk('a'), mk('b'), mk('c') ] } });
|
|
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
|
+
|
|
45
|
+
const page = await ctx.newPage();
|
|
46
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
47
|
+
await page.waitForSelector('[data-topo-hub-hover-ring]', { timeout: 15000 });
|
|
48
|
+
await page.waitForTimeout(300);
|
|
49
|
+
|
|
50
|
+
const restProbe = await page.evaluate(() => {
|
|
51
|
+
const r = document.querySelector('[data-topo-hub-hover-ring]');
|
|
52
|
+
const cs = r ? getComputedStyle(r) : null;
|
|
53
|
+
return {
|
|
54
|
+
opacityAttr: r?.getAttribute('opacity') ?? null,
|
|
55
|
+
opacityData: r?.getAttribute('data-topo-hub-hover-ring-opacity') ?? null,
|
|
56
|
+
rAttr: r?.getAttribute('r') ?? null,
|
|
57
|
+
radiusData: r?.getAttribute('data-topo-hub-hover-ring-radius') ?? null,
|
|
58
|
+
strokeAttr: r?.getAttribute('stroke') ?? null,
|
|
59
|
+
strokeWidthAttr: r?.getAttribute('stroke-width') ?? null,
|
|
60
|
+
pointerEv: cs?.pointerEvents ?? null,
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Hover the hub group.
|
|
65
|
+
await page.hover('[data-topo-hub]');
|
|
66
|
+
await page.waitForTimeout(300);
|
|
67
|
+
const hoverProbe = await page.evaluate(() => {
|
|
68
|
+
const r = document.querySelector('[data-topo-hub-hover-ring]');
|
|
69
|
+
return {
|
|
70
|
+
opacityAttr: r?.getAttribute('opacity') ?? null,
|
|
71
|
+
opacityData: r?.getAttribute('data-topo-hub-hover-ring-opacity') ?? null,
|
|
72
|
+
rAttr: r?.getAttribute('r') ?? null,
|
|
73
|
+
radiusData: r?.getAttribute('data-topo-hub-hover-ring-radius') ?? null,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await browser.close();
|
|
78
|
+
|
|
79
|
+
const results = {
|
|
80
|
+
rest_opacity_0: restProbe.opacityAttr === '0',
|
|
81
|
+
rest_opacity_data_0: restProbe.opacityData === '0',
|
|
82
|
+
rest_r_14: restProbe.rAttr === '14', // R177 rest
|
|
83
|
+
rest_radius_data_14: restProbe.radiusData === '14',
|
|
84
|
+
rest_stroke_cyber: restProbe.strokeAttr === '#10b981', // R253 cyber
|
|
85
|
+
rest_stroke_width_1_5: restProbe.strokeWidthAttr === '1.5', // R51 sentinel reserved but R177
|
|
86
|
+
pointer_events_none: restProbe.pointerEv === 'none',
|
|
87
|
+
hover_opacity_0_8: hoverProbe.opacityAttr === '0.8', // R370 cyber bump
|
|
88
|
+
hover_opacity_data_0_8: hoverProbe.opacityData === '0.8',
|
|
89
|
+
hover_r_17: hoverProbe.rAttr === '17', // R177 hover lift
|
|
90
|
+
hover_radius_data_17: hoverProbe.radiusData === '17',
|
|
91
|
+
};
|
|
92
|
+
const ok = Object.values(results).every(Boolean);
|
|
93
|
+
console.log(`${ok ? '✅' : '❌'} hub hover-ring opacity 0.7 → 0.8 (cyber):`, JSON.stringify(results),
|
|
94
|
+
'\n rest: ', restProbe,
|
|
95
|
+
'\n hover:', hoverProbe);
|
|
96
|
+
process.exit(ok ? 0 : 1);
|