@sleep2agi/agent-network-dashboard 0.5.1-preview.46 → 0.5.1-preview.48
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 +4 -4
- 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.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- 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 +1 -1
- package/.next/server/app/admin.html +1 -1
- package/.next/server/app/admin.rsc +1 -1
- package/.next/server/app/admin.segments/_full.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_index.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/login.segments/_full.segment.rsc +2 -2
- package/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/server/app/login.segments/_index.segment.rsc +1 -1
- package/.next/server/app/login.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/logs.rsc +1 -1
- package/.next/server/app/logs.segments/_full.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_index.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/messages.rsc +1 -1
- package/.next/server/app/messages.segments/_full.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_index.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/node.rsc +1 -1
- package/.next/server/app/node.segments/_full.segment.rsc +1 -1
- package/.next/server/app/node.segments/_head.segment.rsc +1 -1
- package/.next/server/app/node.segments/_index.segment.rsc +1 -1
- package/.next/server/app/node.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/nodes.rsc +1 -1
- package/.next/server/app/nodes.segments/_full.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_index.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/server-logs.rsc +1 -1
- package/.next/server/app/server-logs.segments/_full.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_index.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/settings/networks.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/settings/tokens.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/settings.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/tasks.rsc +1 -1
- package/.next/server/app/tasks.segments/_full.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_index.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_tree.segment.rsc +1 -1
- 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 +1 -1
- 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 +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/static/chunks/{0cwp~el0uaicb.js → 0-a2d3-.76~dq.js} +1 -1
- package/.next/static/chunks/{0bems3b8ts-r5.js → 0bvg-md8ec_k1.js} +1 -1
- package/.next/static/chunks/13uef5ssg5y_p.js +4 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +49 -2
- package/package.json +1 -1
- package/scripts/topo-hover-detail-opacity-test.mjs +98 -0
- package/scripts/topo-hub-highlight-opacity-test.mjs +88 -0
- package/.next/static/chunks/0-x11plautja~.js +0 -4
- /package/.next/static/{H68VhNauRFb-uJX6AO32c → vFF2_rh1XLC2PSSUSj53a}/_buildManifest.js +0 -0
- /package/.next/static/{H68VhNauRFb-uJX6AO32c → vFF2_rh1XLC2PSSUSj53a}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{H68VhNauRFb-uJX6AO32c → vFF2_rh1XLC2PSSUSj53a}/_ssgManifest.js +0 -0
|
@@ -5383,13 +5383,33 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
5383
5383
|
+ 300ms opacity transition + pointerEvents:none all
|
|
5384
5384
|
preserved. data-topo-hub-highlight-radius attr exposes
|
|
5385
5385
|
the value for tests. */}
|
|
5386
|
+
{/* Round 386 / Loop: hub-highlight idle opacity 0.9 → 0.95.
|
|
5387
|
+
When workingCount===0 the highlight paints as the visible
|
|
5388
|
+
idle "lamp lit but no work" core (R130 takeover gate).
|
|
5389
|
+
Pre-R386 idle opacity was 0.9 — a ~6 % fade against full
|
|
5390
|
+
paint that read as slightly-dimmed-ghost on the focal
|
|
5391
|
+
point. R386 lifts to 0.95 (idle alpha gap halved 0.10
|
|
5392
|
+
→ 0.05) so the canvas anchor reads more confidently
|
|
5393
|
+
as a present-but-idle state rather than a faded ghost.
|
|
5394
|
+
Theme-consistency / canvas-presence polish family (4th
|
|
5395
|
+
anchor):
|
|
5396
|
+
R370 hub hover-ring opacity 0.7 → 0.8 cyber
|
|
5397
|
+
R371 edge-badge rest opacity 0.82 → 0.85 cyber
|
|
5398
|
+
R372 minimap offline-dot opacity 0.5 → 0.6
|
|
5399
|
+
R386 hub-highlight idle opacity 0.9 → 0.95 (this round)
|
|
5400
|
+
opacity=0 when working preserved so the hub-digit's
|
|
5401
|
+
R130 takeover stays seamless. 300ms opacity transition
|
|
5402
|
+
+ R213 always-mount opacity-gate + pointerEvents:none
|
|
5403
|
+
+ R365 r=5.5 all preserved. data-topo-hub-highlight-
|
|
5404
|
+
opacity attr exposes the resolved value for tests. */}
|
|
5386
5405
|
<circle
|
|
5387
5406
|
cx={cx} cy={cy} r="5.5"
|
|
5388
5407
|
fill="#d1fae5"
|
|
5389
|
-
opacity={workingCount > 0 ? 0 : 0.
|
|
5408
|
+
opacity={workingCount > 0 ? 0 : 0.95}
|
|
5390
5409
|
data-topo-hub-highlight
|
|
5391
5410
|
data-topo-hub-highlight-visible={workingCount > 0 ? 'false' : 'true'}
|
|
5392
5411
|
data-topo-hub-highlight-radius="5.5"
|
|
5412
|
+
data-topo-hub-highlight-opacity={workingCount > 0 ? 0 : 0.95}
|
|
5393
5413
|
style={{
|
|
5394
5414
|
pointerEvents: 'none',
|
|
5395
5415
|
transition: 'opacity 300ms ease-out',
|
|
@@ -6576,11 +6596,38 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
6576
6596
|
const detailY = pos.y - detailH / 2;
|
|
6577
6597
|
return (
|
|
6578
6598
|
<g transform={`translate(${detailX}, ${detailY})`} data-topo-hover-detail={session.alias} style={{ pointerEvents: 'none' }}>
|
|
6599
|
+
{/* Round 387 / Loop: hover-detail panel cyber backdrop
|
|
6600
|
+
opacity 0.94 → 0.97. The hover-detail card is
|
|
6601
|
+
ALWAYS rendered in active-hover context (it IS
|
|
6602
|
+
the hover product), so it should carry the
|
|
6603
|
+
same backdrop weight as the R348 recent-signal /
|
|
6604
|
+
legend panel HOVER state (which lifts 0.92 →
|
|
6605
|
+
0.97 cyber). Pre-R387 the card sat at 0.94
|
|
6606
|
+
cyber, leaving a 0.03 alpha gap against the
|
|
6607
|
+
R348 panel-hover state — small but visible
|
|
6608
|
+
when the hover-detail floats next to a hovered
|
|
6609
|
+
recent-signal panel. R387 unifies them at 0.97
|
|
6610
|
+
so all active-hover panels paint with the same
|
|
6611
|
+
confident backdrop opacity in cyber. Light
|
|
6612
|
+
stays at 0.98 (already at the strong end —
|
|
6613
|
+
R348 light also stays at 0.97/0.98 max).
|
|
6614
|
+
Theme-consistency / canvas-presence polish
|
|
6615
|
+
family (5th anchor):
|
|
6616
|
+
R370 hub hover-ring opacity 0.7 → 0.8 cyber
|
|
6617
|
+
R371 edge-badge rest opacity 0.82 → 0.85 cyber
|
|
6618
|
+
R372 minimap offline-dot opacity 0.5 → 0.6
|
|
6619
|
+
R386 hub-highlight idle opacity 0.9 → 0.95
|
|
6620
|
+
R387 hover-detail panel opacity 0.94 → 0.97 cyber (this round)
|
|
6621
|
+
data-topo-hover-detail-opacity attr exposes
|
|
6622
|
+
the resolved value for tests. R348 drop-shadow
|
|
6623
|
+
+ rx=8 + stroke=pal.legendAccent + fill=pal.
|
|
6624
|
+
labelBox.fill all preserved. */}
|
|
6579
6625
|
<rect
|
|
6580
6626
|
x="0" y="0" width={detailW} height={detailH} rx="8"
|
|
6581
6627
|
fill={pal.labelBox.fill}
|
|
6582
6628
|
stroke={pal.legendAccent}
|
|
6583
|
-
opacity={isLight ? 0.98 : 0.
|
|
6629
|
+
opacity={isLight ? 0.98 : 0.97}
|
|
6630
|
+
data-topo-hover-detail-opacity={isLight ? 0.98 : 0.97}
|
|
6584
6631
|
style={{ filter: isLight ? 'drop-shadow(0 4px 12px rgba(15,23,42,0.16))' : 'drop-shadow(0 4px 12px rgba(0,0,0,0.6))' }}
|
|
6585
6632
|
/>
|
|
6586
6633
|
<text x="10" y="16" fontSize="9" fontFamily="monospace" fill={pal.legendAccent} fontWeight="700">
|
package/package.json
CHANGED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/* Round 387 verification: hover-detail panel cyber rest opacity
|
|
2
|
+
* 0.94 → 0.97. Theme-consistency / canvas-presence polish family
|
|
3
|
+
* (5th anchor) after R370 hub-ring 0.7→0.8 cyber, R371 edge-badge
|
|
4
|
+
* 0.82→0.85 cyber, R372 minimap offline 0.5→0.6, R386 hub-highlight
|
|
5
|
+
* idle 0.9→0.95. Unifies the active-hover product card's cyber
|
|
6
|
+
* backdrop with the R348 recent-signal/legend panel HOVER state
|
|
7
|
+
* (0.97 cyber) so all active-hover panels paint with the same
|
|
8
|
+
* confident backdrop.
|
|
9
|
+
*
|
|
10
|
+
* Contract:
|
|
11
|
+
* - On hover, the hover-detail panel mounts and:
|
|
12
|
+
* * <rect> opacity attr === '0.97' (cyber theme)
|
|
13
|
+
* * data-topo-hover-detail-opacity === '0.97' (cyber theme)
|
|
14
|
+
* - Pre-R387 invariants preserved:
|
|
15
|
+
* * <rect> rx === '8'
|
|
16
|
+
* * <rect> stroke is non-empty (pal.legendAccent)
|
|
17
|
+
* * data-topo-hover-detail is present (alias-keyed)
|
|
18
|
+
* * R348 drop-shadow filter is present
|
|
19
|
+
* - Light theme stays at opacity 0.98 (separately tested below).
|
|
20
|
+
*
|
|
21
|
+
* Fixture: 2 idle sessions so hover-detail mounts cleanly without
|
|
22
|
+
* the dense-layout >16-node gate (R387 inherits the same gate).
|
|
23
|
+
*/
|
|
24
|
+
import { chromium } from 'playwright';
|
|
25
|
+
import { readFileSync } from 'node:fs';
|
|
26
|
+
|
|
27
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
28
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
29
|
+
|
|
30
|
+
async function probeWith(theme) {
|
|
31
|
+
const browser = await chromium.launch({ headless: true });
|
|
32
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
33
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
34
|
+
await ctx.addInitScript((t) => {
|
|
35
|
+
try { localStorage.setItem('anet-theme', t); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
36
|
+
}, theme);
|
|
37
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
38
|
+
const r = await route.fetch();
|
|
39
|
+
const b = await r.json();
|
|
40
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
41
|
+
const mk = (alias) => ({
|
|
42
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
43
|
+
network_id: nid, project_dir: null,
|
|
44
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
45
|
+
});
|
|
46
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('alpha'), mk('beta') ] } });
|
|
47
|
+
});
|
|
48
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
49
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
50
|
+
const page = await ctx.newPage();
|
|
51
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
52
|
+
await page.waitForSelector('g[data-node]', { timeout: 15000 });
|
|
53
|
+
await page.waitForTimeout(300);
|
|
54
|
+
// Hover the first node to mount hover-detail
|
|
55
|
+
await page.hover('g[data-node]');
|
|
56
|
+
await page.waitForSelector('[data-topo-hover-detail]', { timeout: 5000 });
|
|
57
|
+
await page.waitForTimeout(300);
|
|
58
|
+
const probe = await page.evaluate(() => {
|
|
59
|
+
const card = document.querySelector('[data-topo-hover-detail]');
|
|
60
|
+
if (!card) return null;
|
|
61
|
+
const rect = card.querySelector('rect');
|
|
62
|
+
return {
|
|
63
|
+
alias: card.getAttribute('data-topo-hover-detail'),
|
|
64
|
+
opacityAttr: rect?.getAttribute('opacity') ?? null,
|
|
65
|
+
opacityData: rect?.getAttribute('data-topo-hover-detail-opacity') ?? null,
|
|
66
|
+
rxAttr: rect?.getAttribute('rx') ?? null,
|
|
67
|
+
strokeAttr: rect?.getAttribute('stroke') ?? null,
|
|
68
|
+
filterStyle: rect?.getAttribute('style') ?? '',
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
await browser.close();
|
|
72
|
+
return probe;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const cyber = await probeWith('cyber');
|
|
76
|
+
const light = await probeWith('light');
|
|
77
|
+
|
|
78
|
+
const results = {
|
|
79
|
+
// Cyber: lifted from 0.94 → 0.97
|
|
80
|
+
cyber_opacity_attr_0_97: cyber?.opacityAttr === '0.97',
|
|
81
|
+
cyber_opacity_data_0_97: cyber?.opacityData === '0.97',
|
|
82
|
+
// Light: stays at 0.98 (R387 doesn't touch light)
|
|
83
|
+
light_opacity_attr_0_98: light?.opacityAttr === '0.98',
|
|
84
|
+
light_opacity_data_0_98: light?.opacityData === '0.98',
|
|
85
|
+
// Pre-R387 invariants on both themes
|
|
86
|
+
cyber_rx_8: cyber?.rxAttr === '8',
|
|
87
|
+
light_rx_8: light?.rxAttr === '8',
|
|
88
|
+
cyber_stroke_present: !!cyber?.strokeAttr && cyber.strokeAttr !== 'none',
|
|
89
|
+
light_stroke_present: !!light?.strokeAttr && light.strokeAttr !== 'none',
|
|
90
|
+
cyber_drop_shadow: cyber?.filterStyle.includes('drop-shadow'),
|
|
91
|
+
light_drop_shadow: light?.filterStyle.includes('drop-shadow'),
|
|
92
|
+
cyber_alias_present: !!cyber?.alias && cyber.alias.length > 0,
|
|
93
|
+
};
|
|
94
|
+
const ok = Object.values(results).every(Boolean);
|
|
95
|
+
console.log(`${ok ? '✅' : '❌'} hover-detail panel cyber opacity 0.94 → 0.97:`, JSON.stringify(results),
|
|
96
|
+
'\n cyber:', cyber,
|
|
97
|
+
'\n light:', light);
|
|
98
|
+
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);
|