@sleep2agi/agent-network-dashboard 0.5.1-preview.13 → 0.5.1-preview.130
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +7 -7
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-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.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +2 -2
- package/.next/server/app/server-logs.rsc +2 -2
- package/.next/server/app/server-logs.segments/_full.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_index.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +1 -1
- package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/networks.html +2 -2
- package/.next/server/app/settings/networks.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +2 -2
- package/.next/server/app/settings/tokens.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +1 -1
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +3 -3
- package/.next/server/app/settings.segments/_full.segment.rsc +3 -3
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks.html +2 -2
- package/.next/server/app/tasks.rsc +2 -2
- package/.next/server/app/tasks.segments/_full.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_index.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/tasks.segment.rsc +1 -1
- package/.next/server/chunks/ssr/{[root-of-the-server]__03b.f76._.js → [root-of-the-server]__0sv~g.o._.js} +2 -2
- package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +1 -0
- 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/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/0-at-u3ty_q5z.js +1 -0
- package/.next/static/chunks/0a4hmfvj-81x5.css +2 -0
- package/.next/static/chunks/0kz7356-vy97a.js +1 -0
- package/.next/static/chunks/{03~~oirxz7~vc.js → 0phbmewz8hp6a.js} +1 -1
- package/.next/static/chunks/11xegdodzgys0.js +4 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +2528 -186
- package/package.json +1 -1
- package/screenshots/v0.11.0-147/after.png +0 -0
- package/scripts/p0-147-screenshot.mjs +53 -0
- 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-fullscreen-icon-sw-test.mjs +92 -0
- package/scripts/topo-chrome-reset-icon-sw-test.mjs +80 -0
- package/scripts/topo-chrome-segmented-radius-test.mjs +100 -0
- package/scripts/topo-chrome-zoom-icon-sw-test.mjs +90 -0
- package/scripts/topo-click-ripple-opacity-test.mjs +99 -0
- package/scripts/topo-dashboard-version-attr-test.mjs +69 -0
- package/scripts/topo-dense-alias-opacity-test.mjs +68 -0
- package/scripts/topo-edge-badge-digit-fw-test.mjs +103 -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-letter-spacing-test.mjs +86 -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-endpoint-hover-sw-test.mjs +127 -0
- package/scripts/topo-edge-freshness-floor-test.mjs +99 -0
- package/scripts/topo-edge-particle-hover-r-test.mjs +113 -0
- package/scripts/topo-edge-particle-radius-test.mjs +76 -0
- package/scripts/topo-edge-visible-linecap-test.mjs +89 -0
- package/scripts/topo-endpoint-ring-r-hover-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-hover-sw-test.mjs +113 -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-geom-transition-test.mjs +110 -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-group-label-count-fw-test.mjs +100 -0
- package/scripts/topo-group-label-fw-pin-test.mjs +99 -0
- package/scripts/topo-group-label-letter-spacing-test.mjs +113 -0
- package/scripts/topo-group-label-tint-geom-test.mjs +94 -0
- package/scripts/topo-group-label-tint-transition-test.mjs +97 -0
- package/scripts/topo-group-pip-fontsize-test.mjs +106 -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-core-fill-hover-test.mjs +85 -0
- package/scripts/topo-hub-digit-fontsize-test.mjs +86 -0
- package/scripts/topo-hub-digit-fw-hover-test.mjs +102 -0
- package/scripts/topo-hub-halo-light-trough-test.mjs +88 -0
- package/scripts/topo-hub-halo-r-hover-test.mjs +82 -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-hover-opacity-test.mjs +119 -0
- package/scripts/topo-hub-spoke-hover-sw-test.mjs +121 -0
- package/scripts/topo-hub-spoke-linecap-test.mjs +80 -0
- package/scripts/topo-label-card-opacity-hover-test.mjs +99 -0
- package/scripts/topo-layout-toggle-radius-test.mjs +87 -0
- package/scripts/topo-legend-count-active-opacity-test.mjs +102 -0
- package/scripts/topo-legend-count-pin-fw-test.mjs +90 -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-legend-row-letter-spacing-test.mjs +101 -0
- package/scripts/topo-minimap-offline-opacity-test.mjs +90 -0
- package/scripts/topo-minimap-online-hover-opacity-test.mjs +92 -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-opacity-test.mjs +96 -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-alias-letter-spacing-test.mjs +112 -0
- package/scripts/topo-node-halo-hover-opacity-test.mjs +104 -0
- package/scripts/topo-node-halo-light-offline-test.mjs +80 -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-node-sub-text-fw-test.mjs +75 -0
- package/scripts/topo-node-sub-text-letter-spacing-test.mjs +115 -0
- package/scripts/topo-panel-count-fw-hover-test.mjs +105 -0
- package/scripts/topo-panel-stroke-hover-test.mjs +110 -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-count-pin-fw-test.mjs +106 -0
- package/scripts/topo-recent-row-letter-spacing-test.mjs +109 -0
- package/scripts/topo-recent-row-pip-hover-r-test.mjs +104 -0
- package/scripts/topo-recent-row-text-fontweight-test.mjs +90 -0
- package/scripts/topo-runtime-icon-hover-test.mjs +96 -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-status-ring-hover-sw-test.mjs +105 -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-level-hover-fw-test.mjs +95 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__03b.f76._.js.map +0 -1
- package/.next/static/chunks/0is7s1ik8dy24.js +0 -4
- package/.next/static/chunks/0kt7qs66ra2.2.css +0 -2
- package/.next/static/chunks/0yl__lz0pv5_7.js +0 -1
- package/.next/static/chunks/1090s4vyw-jrc.js +0 -1
- /package/.next/static/{Fa8EZgmgYGwvcoaGKpSmo → ZPH3qUPz78tGunqc1tq8i}/_buildManifest.js +0 -0
- /package/.next/static/{Fa8EZgmgYGwvcoaGKpSmo → ZPH3qUPz78tGunqc1tq8i}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{Fa8EZgmgYGwvcoaGKpSmo → ZPH3qUPz78tGunqc1tq8i}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/* Round 433 verification: legend-row text 3-tier letter-spacing —
|
|
2
|
+
* rest 0 / hover 0.25 / pinned 0.5. Mirror of R432 group-label pattern
|
|
3
|
+
* at legend-row scope. Hover-letter-spacing family extension (9 anchors).
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - 3 legend rows mount (working / idle / offline)
|
|
7
|
+
* - rest: every legend-row-label reports letter-spacing '0px' +
|
|
8
|
+
* hovered='false' + pinned='false'
|
|
9
|
+
* - hover one legend-status group: that row's label letter-spacing
|
|
10
|
+
* '0.25px' + hovered='true'
|
|
11
|
+
* - siblings stay rest
|
|
12
|
+
* - source-file probe confirms 3-tier conditional + transition kept
|
|
13
|
+
*/
|
|
14
|
+
import { chromium } from 'playwright';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
|
|
17
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
18
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
19
|
+
|
|
20
|
+
const browser = await chromium.launch({ headless: true });
|
|
21
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
22
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
23
|
+
await ctx.addInitScript(() => {
|
|
24
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
25
|
+
});
|
|
26
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
27
|
+
const r = await route.fetch();
|
|
28
|
+
const b = await r.json();
|
|
29
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
30
|
+
const mk = (alias, status) => ({
|
|
31
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
32
|
+
network_id: nid, project_dir: null,
|
|
33
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
34
|
+
});
|
|
35
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
36
|
+
mk('alpha', 'working'),
|
|
37
|
+
mk('beta', 'working'),
|
|
38
|
+
mk('gamma', 'idle'),
|
|
39
|
+
] } });
|
|
40
|
+
});
|
|
41
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
42
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
43
|
+
|
|
44
|
+
const page = await ctx.newPage();
|
|
45
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
46
|
+
await page.waitForSelector('[data-legend-row-label]', { timeout: 15000 });
|
|
47
|
+
await page.waitForTimeout(400);
|
|
48
|
+
|
|
49
|
+
const readAll = () => page.evaluate(() => {
|
|
50
|
+
const ts = [...document.querySelectorAll('[data-legend-row-label]')];
|
|
51
|
+
return ts.map(t => ({
|
|
52
|
+
key: t.getAttribute('data-legend-row-label'),
|
|
53
|
+
ls: t.style.letterSpacing,
|
|
54
|
+
pinned: t.getAttribute('data-legend-row-label-pinned'),
|
|
55
|
+
hovered: t.getAttribute('data-legend-row-label-hovered'),
|
|
56
|
+
}));
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const rest = await readAll();
|
|
60
|
+
|
|
61
|
+
// Hover the 'working' legend-status group wrapper (its onMouseEnter
|
|
62
|
+
// triggers setHoveredStatus('working') which flips the label tween).
|
|
63
|
+
let hover = null;
|
|
64
|
+
const box = await page.evaluate(() => {
|
|
65
|
+
const g = document.querySelector('[data-legend-status="working"]');
|
|
66
|
+
if (!g) return null;
|
|
67
|
+
const b = g.getBoundingClientRect();
|
|
68
|
+
return { x: b.x + b.width / 2, y: b.y + b.height / 2 };
|
|
69
|
+
});
|
|
70
|
+
if (box) {
|
|
71
|
+
await page.mouse.move(box.x, box.y);
|
|
72
|
+
await page.waitForTimeout(300);
|
|
73
|
+
hover = await readAll();
|
|
74
|
+
await page.mouse.move(0, 0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
78
|
+
const sourceWired = /letterSpacing:\s*isPinned\s*\?\s*'0\.5px'\s*:\s*\n?\s*hoveredStatus\s*===\s*row\.key\s*\?\s*'0\.25px'\s*:\s*'0px'/.test(fileText);
|
|
79
|
+
|
|
80
|
+
await browser.close();
|
|
81
|
+
|
|
82
|
+
const isRest = (ls) => ls === '0px' || ls === '' || ls === 'normal';
|
|
83
|
+
|
|
84
|
+
const hoveredEntry = hover?.find(r => r.key === 'working');
|
|
85
|
+
const othersStayRest = hover ? hover.filter(r => r.key !== 'working').every(r => isRest(r.ls) && r.hovered === 'false') : false;
|
|
86
|
+
|
|
87
|
+
const results = {
|
|
88
|
+
rest_three_rows: rest.length === 3,
|
|
89
|
+
rest_all_zero: rest.every(r => isRest(r.ls)),
|
|
90
|
+
rest_all_pinned_false: rest.every(r => r.pinned === 'false'),
|
|
91
|
+
rest_all_hovered_false: rest.every(r => r.hovered === 'false'),
|
|
92
|
+
hover_target_ls_0_25: hoveredEntry?.ls === '0.25px',
|
|
93
|
+
hover_target_hovered_true: hoveredEntry?.hovered === 'true',
|
|
94
|
+
hover_others_stay_rest: othersStayRest,
|
|
95
|
+
source_three_tier_wired: sourceWired,
|
|
96
|
+
};
|
|
97
|
+
const ok = Object.values(results).every(Boolean);
|
|
98
|
+
console.log(`${ok ? '✅' : '❌'} legend-row 3-tier letter-spacing:`, JSON.stringify(results),
|
|
99
|
+
'\n rest:', JSON.stringify(rest),
|
|
100
|
+
'\n hover target:', JSON.stringify(hoveredEntry));
|
|
101
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/* Round 372 verification: minimap offline-dot opacity 0.5 → 0.6.
|
|
2
|
+
* Sibling stale-state legibility lift to R358 (freshness ramp floor
|
|
3
|
+
* 0.25 → 0.30). Pre-R372 R198 drew offline dots at α=0.5; R372 lifts
|
|
4
|
+
* to 0.6 (+20 % relative) for better readability while keeping a
|
|
5
|
+
* clear two-tier distinction vs online α=0.9.
|
|
6
|
+
*
|
|
7
|
+
* The minimap only renders when view is non-default (zoom !== 1 ||
|
|
8
|
+
* pan). Test triggers zoom-in to mount it, then probes the offline
|
|
9
|
+
* dot's opacity attr.
|
|
10
|
+
*
|
|
11
|
+
* Contract:
|
|
12
|
+
* - data-topo-minimap-dot-online="false" element opacity === '0.6'.
|
|
13
|
+
* - data-topo-minimap-dot-opacity === '0.6' for offline dot.
|
|
14
|
+
* - Online dot still at opacity '0.9' (R198 invariant).
|
|
15
|
+
* - Pre-R372 invariants:
|
|
16
|
+
* * R198 offline r=1.2, online r=1.7 preserved
|
|
17
|
+
* * R198 transition list (opacity + fill + r) preserved
|
|
18
|
+
*/
|
|
19
|
+
import { chromium } from 'playwright';
|
|
20
|
+
import { readFileSync } from 'node:fs';
|
|
21
|
+
|
|
22
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
23
|
+
const 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(() => {
|
|
27
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
28
|
+
});
|
|
29
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
30
|
+
const stale = new Date(Date.now() - 600 * 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
|
+
// Mix of online (working) + offline sessions.
|
|
36
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
37
|
+
{ alias: 'on-a', status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
38
|
+
network_id: nid, project_dir: null, created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
39
|
+
{ alias: 'on-b', status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
40
|
+
network_id: nid, project_dir: null, created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
41
|
+
{ alias: 'off-c', status: 'offline', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
42
|
+
network_id: nid, project_dir: null, created_at: stale, updated_at: stale, last_seen_at: stale },
|
|
43
|
+
] } });
|
|
44
|
+
});
|
|
45
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
46
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
47
|
+
|
|
48
|
+
const page = await ctx.newPage();
|
|
49
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
50
|
+
// Minimap only mounts when view is non-default — zoom in twice.
|
|
51
|
+
await page.waitForSelector('[data-topo-chrome-zoom-in]', { timeout: 15000 });
|
|
52
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
53
|
+
await page.waitForTimeout(200);
|
|
54
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
55
|
+
await page.waitForSelector('[data-topo-minimap-dot]', { timeout: 5000 });
|
|
56
|
+
await page.waitForTimeout(400);
|
|
57
|
+
|
|
58
|
+
const probe = await page.evaluate(() => {
|
|
59
|
+
const offline = document.querySelector('[data-topo-minimap-dot-online="false"]');
|
|
60
|
+
const online = document.querySelector('[data-topo-minimap-dot-online="true"]');
|
|
61
|
+
const cs = offline ? getComputedStyle(offline) : null;
|
|
62
|
+
return {
|
|
63
|
+
offlineOpacity: offline?.getAttribute('opacity') ?? null,
|
|
64
|
+
offlineData: offline?.getAttribute('data-topo-minimap-dot-opacity') ?? null,
|
|
65
|
+
offlineR: offline?.getAttribute('r') ?? null,
|
|
66
|
+
offlineTrans: cs?.transition ?? null,
|
|
67
|
+
onlineOpacity: online?.getAttribute('opacity') ?? null,
|
|
68
|
+
onlineR: online?.getAttribute('r') ?? null,
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
await browser.close();
|
|
73
|
+
|
|
74
|
+
const hasTrans = (s, prop) =>
|
|
75
|
+
new RegExp(`${prop}\\s+\\d*\\.?\\d*s|${prop}\\s+\\d+ms`, 'i').test(s || '');
|
|
76
|
+
|
|
77
|
+
const results = {
|
|
78
|
+
offline_opacity_0_6: probe.offlineOpacity === '0.6',
|
|
79
|
+
offline_data_0_6: probe.offlineData === '0.6',
|
|
80
|
+
offline_r_1_2: probe.offlineR === '1.2', // R198 invariant
|
|
81
|
+
online_opacity_0_9: probe.onlineOpacity === '0.9', // R198 invariant
|
|
82
|
+
online_r_1_7: probe.onlineR === '1.7', // R198 invariant
|
|
83
|
+
trans_has_opacity: hasTrans(probe.offlineTrans, 'opacity'), // R198
|
|
84
|
+
trans_has_fill: hasTrans(probe.offlineTrans, 'fill'), // R198
|
|
85
|
+
trans_has_r: hasTrans(probe.offlineTrans, 'r'), // R198
|
|
86
|
+
};
|
|
87
|
+
const ok = Object.values(results).every(Boolean);
|
|
88
|
+
console.log(`${ok ? '✅' : '❌'} minimap offline opacity 0.5 → 0.6:`, JSON.stringify(results),
|
|
89
|
+
'\n probe:', probe);
|
|
90
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/* Round 421 verification: minimap online dot opacity 0.95 → 1.0 on
|
|
2
|
+
* minimap container hover. Sibling to R346 viewport rect tween.
|
|
3
|
+
* Live-fleet anchors brighten when user hovers the minimap.
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - Minimap mounts on non-default view → zoom-in twice
|
|
7
|
+
* - Rest state: online dot opacity '0.95' (R392 invariant)
|
|
8
|
+
* - Hover state (page.hover on minimap container):
|
|
9
|
+
* * online dot opacity '1' + data '1'
|
|
10
|
+
* * R346 viewport strokeWidth '1.75'
|
|
11
|
+
* - Offline dot stays at R372 '0.6' in both states
|
|
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
|
+
const stale = new Date(Date.now() - 30 * 60 * 1000).toISOString();
|
|
19
|
+
|
|
20
|
+
const browser = await chromium.launch({ headless: true });
|
|
21
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
22
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
23
|
+
await ctx.addInitScript(() => {
|
|
24
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
25
|
+
});
|
|
26
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
27
|
+
const r = await route.fetch();
|
|
28
|
+
const b = await r.json();
|
|
29
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
30
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
31
|
+
{ alias: 'alpha', status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli', network_id: nid, project_dir: null, created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
32
|
+
{ alias: 'ghost', status: 'offline', model: 'claude-opus-4', runtime: 'claude-code-cli', network_id: nid, project_dir: null, created_at: stale, updated_at: stale, last_seen_at: stale },
|
|
33
|
+
] } });
|
|
34
|
+
});
|
|
35
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
36
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
37
|
+
|
|
38
|
+
const page = await ctx.newPage();
|
|
39
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
40
|
+
await page.waitForSelector('g[data-node]', { timeout: 15000 });
|
|
41
|
+
await page.waitForTimeout(300);
|
|
42
|
+
|
|
43
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
44
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
45
|
+
await page.waitForSelector('[data-topo-minimap-dot]', { timeout: 5000 });
|
|
46
|
+
await page.waitForTimeout(400);
|
|
47
|
+
|
|
48
|
+
const restProbe = await page.evaluate(() => {
|
|
49
|
+
const dots = Array.from(document.querySelectorAll('[data-topo-minimap-dot]'));
|
|
50
|
+
const on = dots.find((d) => d.getAttribute('data-topo-minimap-dot-online') === 'true');
|
|
51
|
+
const off = dots.find((d) => d.getAttribute('data-topo-minimap-dot-online') === 'false');
|
|
52
|
+
return {
|
|
53
|
+
online: on ? { opacity: on.getAttribute('opacity'), data: on.getAttribute('data-topo-minimap-dot-opacity') } : null,
|
|
54
|
+
offline: off ? { opacity: off.getAttribute('opacity'), data: off.getAttribute('data-topo-minimap-dot-opacity') } : null,
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
await page.hover('[data-topo-minimap]');
|
|
59
|
+
await page.waitForTimeout(400);
|
|
60
|
+
|
|
61
|
+
const hoverProbe = await page.evaluate(() => {
|
|
62
|
+
const dots = Array.from(document.querySelectorAll('[data-topo-minimap-dot]'));
|
|
63
|
+
const on = dots.find((d) => d.getAttribute('data-topo-minimap-dot-online') === 'true');
|
|
64
|
+
const off = dots.find((d) => d.getAttribute('data-topo-minimap-dot-online') === 'false');
|
|
65
|
+
const view = document.querySelector('[data-topo-minimap-viewport]');
|
|
66
|
+
return {
|
|
67
|
+
online: on ? { opacity: on.getAttribute('opacity'), data: on.getAttribute('data-topo-minimap-dot-opacity') } : null,
|
|
68
|
+
offline: off ? { opacity: off.getAttribute('opacity'), data: off.getAttribute('data-topo-minimap-dot-opacity') } : null,
|
|
69
|
+
viewportSw: view?.getAttribute('stroke-width') ?? null,
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
await browser.close();
|
|
74
|
+
|
|
75
|
+
const results = {
|
|
76
|
+
// Rest state (R392 baseline)
|
|
77
|
+
rest_online_0_95: restProbe.online?.opacity === '0.95',
|
|
78
|
+
rest_online_data_0_95: restProbe.online?.data === '0.95',
|
|
79
|
+
rest_offline_0_6: restProbe.offline?.opacity === '0.6',
|
|
80
|
+
// Hover state (R421 lift)
|
|
81
|
+
hover_online_1: hoverProbe.online?.opacity === '1',
|
|
82
|
+
hover_online_data_1: hoverProbe.online?.data === '1',
|
|
83
|
+
// R372 offline invariant: stays at 0.6 in both states
|
|
84
|
+
hover_offline_0_6: hoverProbe.offline?.opacity === '0.6',
|
|
85
|
+
// R346 viewport lift on hover (invariant)
|
|
86
|
+
hover_viewport_sw_1_75: hoverProbe.viewportSw === '1.75',
|
|
87
|
+
};
|
|
88
|
+
const ok = Object.values(results).every(Boolean);
|
|
89
|
+
console.log(`${ok ? '✅' : '❌'} minimap online dot hover opacity 0.95 → 1.0:`, JSON.stringify(results),
|
|
90
|
+
'\n rest: ', restProbe,
|
|
91
|
+
'\n hover:', hoverProbe);
|
|
92
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/* Round 392 verification: minimap online dot opacity 0.9 → 0.95.
|
|
2
|
+
* Theme-consistency / canvas-presence polish family (7th anchor)
|
|
3
|
+
* after R370 hub-ring, R371 edge-badge, R372 minimap offline,
|
|
4
|
+
* R386 hub-highlight idle, R387 hover-detail panel, R391 hub-spoke
|
|
5
|
+
* active. Halves the online dot's idle alpha gap (0.10 → 0.05).
|
|
6
|
+
* Mirrors R386's hub-highlight idle 0.9 → 0.95 on the minimap.
|
|
7
|
+
*
|
|
8
|
+
* Contract:
|
|
9
|
+
* - Minimap only mounts when view is non-default — test clicks
|
|
10
|
+
* zoom-in twice to mount it before probing.
|
|
11
|
+
* - Online dots: opacity attr === '0.95', data-opacity === '0.95',
|
|
12
|
+
* R384 r=1.9 invariant, data-online='true'
|
|
13
|
+
* - Offline dot (one ghost session): opacity attr === '0.6'
|
|
14
|
+
* (R372 invariant), r=1.2 invariant, data-online='false'
|
|
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
|
+
const stale = new Date(Date.now() - 30 * 60 * 1000).toISOString(); // 30 min ago → offline
|
|
22
|
+
|
|
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(() => {
|
|
27
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } 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
|
+
await route.fulfill({ response: r, json: {
|
|
34
|
+
...b,
|
|
35
|
+
sessions: [
|
|
36
|
+
{ alias: 'alpha', status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli', network_id: nid, project_dir: null, created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
37
|
+
{ alias: 'beta', status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli', network_id: nid, project_dir: null, created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
38
|
+
{ alias: 'ghost', status: 'offline', model: 'claude-opus-4', runtime: 'claude-code-cli', network_id: nid, project_dir: null, created_at: stale, updated_at: stale, last_seen_at: stale },
|
|
39
|
+
],
|
|
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
|
+
|
|
45
|
+
const page = await ctx.newPage();
|
|
46
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
47
|
+
await page.waitForSelector('g[data-node]', { timeout: 15000 });
|
|
48
|
+
await page.waitForTimeout(300);
|
|
49
|
+
|
|
50
|
+
// Minimap mounts only on non-default view — click zoom-in twice
|
|
51
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
52
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
53
|
+
await page.waitForSelector('[data-topo-minimap-dot]', { timeout: 5000 });
|
|
54
|
+
await page.waitForTimeout(400);
|
|
55
|
+
|
|
56
|
+
const probe = await page.evaluate(() => {
|
|
57
|
+
const dots = Array.from(document.querySelectorAll('[data-topo-minimap-dot]'));
|
|
58
|
+
const online = dots.filter((d) => d.getAttribute('data-topo-minimap-dot-online') === 'true');
|
|
59
|
+
const offline = dots.filter((d) => d.getAttribute('data-topo-minimap-dot-online') === 'false');
|
|
60
|
+
const read = (el) => el ? ({
|
|
61
|
+
opacityAttr: el.getAttribute('opacity'),
|
|
62
|
+
opacityData: el.getAttribute('data-topo-minimap-dot-opacity'),
|
|
63
|
+
radiusAttr: el.getAttribute('r'),
|
|
64
|
+
}) : null;
|
|
65
|
+
return {
|
|
66
|
+
total: dots.length,
|
|
67
|
+
onlineCount: online.length,
|
|
68
|
+
offlineCount: offline.length,
|
|
69
|
+
onlineSample: read(online[0]),
|
|
70
|
+
offlineSample: read(offline[0]),
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await browser.close();
|
|
75
|
+
|
|
76
|
+
const results = {
|
|
77
|
+
// Setup: 2 online + 1 offline
|
|
78
|
+
total_3_dots: probe.total === 3,
|
|
79
|
+
online_2_dots: probe.onlineCount === 2,
|
|
80
|
+
offline_1_dot: probe.offlineCount === 1,
|
|
81
|
+
// R392: online opacity 0.9 → 0.95
|
|
82
|
+
online_opacity_0_95: probe.onlineSample?.opacityAttr === '0.95',
|
|
83
|
+
online_data_0_95: probe.onlineSample?.opacityData === '0.95',
|
|
84
|
+
online_r_1_9: probe.onlineSample?.radiusAttr === '1.9', // R384 invariant
|
|
85
|
+
// R372 invariant: offline opacity 0.6
|
|
86
|
+
offline_opacity_0_6: probe.offlineSample?.opacityAttr === '0.6',
|
|
87
|
+
offline_data_0_6: probe.offlineSample?.opacityData === '0.6',
|
|
88
|
+
offline_r_1_2: probe.offlineSample?.radiusAttr === '1.2',
|
|
89
|
+
};
|
|
90
|
+
const ok = Object.values(results).every(Boolean);
|
|
91
|
+
console.log(`${ok ? '✅' : '❌'} minimap online dot opacity 0.9 → 0.95:`, JSON.stringify(results),
|
|
92
|
+
'\n probe:', JSON.stringify(probe, null, 2));
|
|
93
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/* Round 384 verification: minimap online dot radius 1.7 → 1.9.
|
|
2
|
+
* Sibling visual-weight bump (10th anchor) to R383 recent-row pip
|
|
3
|
+
* 1.8 → 2.0. Widens online vs offline tier contrast (1.42× → 1.58×).
|
|
4
|
+
* R372 already lifted offline opacity 0.5 → 0.6; R384 lifts online
|
|
5
|
+
* radius — pair completes minimap-dot legibility polish across both
|
|
6
|
+
* states.
|
|
7
|
+
*
|
|
8
|
+
* The minimap only renders when view is non-default (zoom !== 1 ||
|
|
9
|
+
* pan), so test triggers zoom-in twice to mount it.
|
|
10
|
+
*
|
|
11
|
+
* Contract:
|
|
12
|
+
* - Online dot computed r === '1.9'.
|
|
13
|
+
* - Online dot data-topo-minimap-dot-radius === '1.9'.
|
|
14
|
+
* - Offline dot r === '1.2' (R198 invariant, untouched).
|
|
15
|
+
* - Offline dot data-radius === '1.2'.
|
|
16
|
+
* - Pre-R384 invariants:
|
|
17
|
+
* * R198 opacity (online 0.9 / offline 0.6 from R372)
|
|
18
|
+
* * R198 transition list (opacity + fill + r 200ms) 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
|
+
const stale = new Date(Date.now() - 600 * 1000).toISOString();
|
|
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
|
+
// Mix of online (working) + offline.
|
|
37
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
38
|
+
{ alias: 'on-a', status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
39
|
+
network_id: nid, project_dir: null, created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
40
|
+
{ alias: 'on-b', status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
41
|
+
network_id: nid, project_dir: null, created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
42
|
+
{ alias: 'off-c', status: 'offline', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
43
|
+
network_id: nid, project_dir: null, created_at: stale, updated_at: stale, last_seen_at: stale },
|
|
44
|
+
] } });
|
|
45
|
+
});
|
|
46
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
47
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
48
|
+
|
|
49
|
+
const page = await ctx.newPage();
|
|
50
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
51
|
+
// Trigger zoom-in to mount minimap (R30 gate).
|
|
52
|
+
await page.waitForSelector('[data-topo-chrome-zoom-in]', { timeout: 15000 });
|
|
53
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
54
|
+
await page.waitForTimeout(200);
|
|
55
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
56
|
+
await page.waitForSelector('[data-topo-minimap-dot]', { timeout: 5000 });
|
|
57
|
+
await page.waitForTimeout(400);
|
|
58
|
+
|
|
59
|
+
const probe = await page.evaluate(() => {
|
|
60
|
+
const online = document.querySelector('[data-topo-minimap-dot-online="true"]');
|
|
61
|
+
const offline = document.querySelector('[data-topo-minimap-dot-online="false"]');
|
|
62
|
+
return {
|
|
63
|
+
onlineR: online?.getAttribute('r') ?? null,
|
|
64
|
+
onlineRData: online?.getAttribute('data-topo-minimap-dot-radius') ?? null,
|
|
65
|
+
onlineOpacity: online?.getAttribute('opacity') ?? null,
|
|
66
|
+
offlineR: offline?.getAttribute('r') ?? null,
|
|
67
|
+
offlineRData: offline?.getAttribute('data-topo-minimap-dot-radius') ?? null,
|
|
68
|
+
offlineOpacity: offline?.getAttribute('opacity') ?? null,
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
await browser.close();
|
|
73
|
+
|
|
74
|
+
const results = {
|
|
75
|
+
online_r_1_9: probe.onlineR === '1.9',
|
|
76
|
+
online_r_data_1_9: probe.onlineRData === '1.9',
|
|
77
|
+
online_opacity_0_9: probe.onlineOpacity === '0.9', // R198 invariant
|
|
78
|
+
offline_r_1_2: probe.offlineR === '1.2', // R198 invariant
|
|
79
|
+
offline_r_data_1_2: probe.offlineRData === '1.2',
|
|
80
|
+
offline_opacity_0_6: probe.offlineOpacity === '0.6', // R372 lift
|
|
81
|
+
};
|
|
82
|
+
const ok = Object.values(results).every(Boolean);
|
|
83
|
+
console.log(`${ok ? '✅' : '❌'} minimap online dot radius 1.7 → 1.9:`, JSON.stringify(results),
|
|
84
|
+
'\n probe:', probe);
|
|
85
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* Round 379 verification: minimap viewport rect picks up
|
|
2
|
+
* strokeLinejoin='round'. Sibling SVG stroke-softening polish to
|
|
3
|
+
* R378 flow-rail linecap + R288 chrome icon linecap family.
|
|
4
|
+
*
|
|
5
|
+
* The minimap only mounts when view is non-default (zoom !== 1 ||
|
|
6
|
+
* pan), so test triggers zoom-in to mount it.
|
|
7
|
+
*
|
|
8
|
+
* Contract:
|
|
9
|
+
* - [data-topo-minimap-viewport] element stroke-linejoin attr === 'round'.
|
|
10
|
+
* - data-topo-minimap-viewport-linejoin === 'round'.
|
|
11
|
+
* - Pre-R379 invariants:
|
|
12
|
+
* * R287 strokeWidth=1.5 (cold rest)
|
|
13
|
+
* * R287 stroke=pal.legendAccent
|
|
14
|
+
* * R346 opacity=0.9 (cold rest)
|
|
15
|
+
* * R199 smoothView + R346 transition list still tween correctly
|
|
16
|
+
*/
|
|
17
|
+
import { chromium } from 'playwright';
|
|
18
|
+
import { readFileSync } from 'node:fs';
|
|
19
|
+
|
|
20
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
21
|
+
const browser = await chromium.launch({ headless: true });
|
|
22
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
23
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
24
|
+
await ctx.addInitScript(() => {
|
|
25
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
26
|
+
});
|
|
27
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
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
|
+
const mk = (alias) => ({
|
|
33
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
34
|
+
network_id: nid, project_dir: null,
|
|
35
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
36
|
+
});
|
|
37
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('a'), mk('b'), mk('c') ] } });
|
|
38
|
+
});
|
|
39
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
40
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
41
|
+
|
|
42
|
+
const page = await ctx.newPage();
|
|
43
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
44
|
+
// Trigger zoom-in to mount minimap (R30 gate).
|
|
45
|
+
await page.waitForSelector('[data-topo-chrome-zoom-in]', { timeout: 15000 });
|
|
46
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
47
|
+
await page.waitForTimeout(200);
|
|
48
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
49
|
+
await page.waitForSelector('[data-topo-minimap-viewport]', { timeout: 5000 });
|
|
50
|
+
await page.waitForTimeout(400);
|
|
51
|
+
|
|
52
|
+
const probe = await page.evaluate(() => {
|
|
53
|
+
const r = document.querySelector('[data-topo-minimap-viewport]');
|
|
54
|
+
return {
|
|
55
|
+
linejoinAttr: r?.getAttribute('stroke-linejoin') ?? null,
|
|
56
|
+
linejoinData: r?.getAttribute('data-topo-minimap-viewport-linejoin') ?? null,
|
|
57
|
+
strokeWidthAttr: r?.getAttribute('stroke-width') ?? null,
|
|
58
|
+
opacityAttr: r?.getAttribute('opacity') ?? null,
|
|
59
|
+
fillAttr: r?.getAttribute('fill') ?? null,
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
await browser.close();
|
|
64
|
+
|
|
65
|
+
const results = {
|
|
66
|
+
linejoin_round: probe.linejoinAttr === 'round',
|
|
67
|
+
data_linejoin_round: probe.linejoinData === 'round',
|
|
68
|
+
stroke_width_1_5_rest: probe.strokeWidthAttr === '1.5', // R287 cold rest
|
|
69
|
+
opacity_0_9_rest: probe.opacityAttr === '0.9', // R346 cold rest
|
|
70
|
+
fill_none: probe.fillAttr === 'none', // viewport rect is stroke-only
|
|
71
|
+
};
|
|
72
|
+
const ok = Object.values(results).every(Boolean);
|
|
73
|
+
console.log(`${ok ? '✅' : '❌'} minimap viewport linejoin='round':`, JSON.stringify(results),
|
|
74
|
+
'\n probe:', probe);
|
|
75
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/* Round 450 verification: minimap viewport rect rest opacity 0.9 →
|
|
2
|
+
* 0.95. Closes half the alpha gap on the wayfinding indicator.
|
|
3
|
+
*
|
|
4
|
+
* Contract:
|
|
5
|
+
* - rest: viewport rect opacity '0.95'
|
|
6
|
+
* - hover the minimap container: viewport opacity '1' (R346 preserved)
|
|
7
|
+
* - strokeWidth invariants preserved (rest=1.5, hover=1.75)
|
|
8
|
+
*/
|
|
9
|
+
import { chromium } from 'playwright';
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
|
|
12
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
13
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
14
|
+
|
|
15
|
+
const browser = await chromium.launch({ headless: true });
|
|
16
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
17
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
18
|
+
await ctx.addInitScript(() => {
|
|
19
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
20
|
+
});
|
|
21
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
22
|
+
const r = await route.fetch();
|
|
23
|
+
const b = await r.json();
|
|
24
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
25
|
+
const mk = (alias, status) => ({
|
|
26
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
27
|
+
network_id: nid, project_dir: null,
|
|
28
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
29
|
+
});
|
|
30
|
+
// Need enough nodes for minimap to render — and a non-default view
|
|
31
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
32
|
+
mk('alpha', 'working'),
|
|
33
|
+
mk('beta', 'idle'),
|
|
34
|
+
mk('gamma', 'working'),
|
|
35
|
+
mk('delta', 'idle'),
|
|
36
|
+
] } });
|
|
37
|
+
});
|
|
38
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
39
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
40
|
+
|
|
41
|
+
const page = await ctx.newPage();
|
|
42
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
43
|
+
|
|
44
|
+
// Trigger a zoom to mount the minimap (R30 gate: minimap only renders on non-default view)
|
|
45
|
+
await page.waitForSelector('[data-topo-chrome-zoom-in]', { timeout: 15000 });
|
|
46
|
+
await page.click('[data-topo-chrome-zoom-in]');
|
|
47
|
+
await page.waitForTimeout(300);
|
|
48
|
+
|
|
49
|
+
await page.waitForSelector('[data-topo-minimap-viewport]', { timeout: 5000 });
|
|
50
|
+
await page.waitForTimeout(300);
|
|
51
|
+
|
|
52
|
+
const rest = await page.evaluate(() => {
|
|
53
|
+
const v = document.querySelector('[data-topo-minimap-viewport]');
|
|
54
|
+
return v ? {
|
|
55
|
+
opacity: v.getAttribute('opacity'),
|
|
56
|
+
sw: v.getAttribute('stroke-width'),
|
|
57
|
+
hover: v.getAttribute('data-topo-minimap-viewport-hover'),
|
|
58
|
+
} : null;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Hover the minimap container
|
|
62
|
+
let hover = null;
|
|
63
|
+
const minimap = await page.$('[data-topo-minimap]');
|
|
64
|
+
if (minimap) {
|
|
65
|
+
await minimap.hover({ force: true });
|
|
66
|
+
await page.waitForTimeout(250);
|
|
67
|
+
hover = await page.evaluate(() => {
|
|
68
|
+
const v = document.querySelector('[data-topo-minimap-viewport]');
|
|
69
|
+
return v ? {
|
|
70
|
+
opacity: v.getAttribute('opacity'),
|
|
71
|
+
sw: v.getAttribute('stroke-width'),
|
|
72
|
+
hover: v.getAttribute('data-topo-minimap-viewport-hover'),
|
|
73
|
+
} : null;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
78
|
+
const sourceWired = /opacity=\{hoveredMinimap \? '1' : '0\.95'\}/.test(fileText);
|
|
79
|
+
|
|
80
|
+
await browser.close();
|
|
81
|
+
|
|
82
|
+
const results = {
|
|
83
|
+
rest_mounted: !!rest,
|
|
84
|
+
rest_opacity_0_95: rest?.opacity === '0.95',
|
|
85
|
+
rest_sw_1_5: rest?.sw === '1.5',
|
|
86
|
+
rest_hover_false: rest?.hover === 'false',
|
|
87
|
+
hover_opacity_1: hover?.opacity === '1',
|
|
88
|
+
hover_sw_1_75: hover?.sw === '1.75',
|
|
89
|
+
hover_hover_true: hover?.hover === 'true',
|
|
90
|
+
source_wired: sourceWired,
|
|
91
|
+
};
|
|
92
|
+
const ok = Object.values(results).every(Boolean);
|
|
93
|
+
console.log(`${ok ? '✅' : '❌'} minimap viewport rest opacity:`, JSON.stringify(results),
|
|
94
|
+
'\n rest:', JSON.stringify(rest),
|
|
95
|
+
'\n hover:', JSON.stringify(hover));
|
|
96
|
+
process.exit(ok ? 0 : 1);
|