@sleep2agi/agent-network-dashboard 0.5.1-preview.13 → 0.5.1-preview.131
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/{03~~oirxz7~vc.js → 09dd~tmai-uvf.js} +1 -1
- package/.next/static/chunks/0a4hmfvj-81x5.css +2 -0
- package/.next/static/chunks/0d3qvaags566q.js +1 -0
- package/.next/static/chunks/0y6xhu~ffpycg.js +1 -0
- 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-overlap-stale-build-guard-test.mjs +66 -0
- package/scripts/topo-overlap-test.mjs +42 -1
- 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 → aNROJZBaF0IgNbCcEynAI}/_buildManifest.js +0 -0
- /package/.next/static/{Fa8EZgmgYGwvcoaGKpSmo → aNROJZBaF0IgNbCcEynAI}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{Fa8EZgmgYGwvcoaGKpSmo → aNROJZBaF0IgNbCcEynAI}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* Round 429 verification: node label-card body opacity 0.94 → 1.0 on
|
|
2
|
+
* hover (cyber theme). Sibling to R348 panel rect opacity lift at
|
|
3
|
+
* panel scope. Adds a solidity axis to node hover signature alongside
|
|
4
|
+
* R217 stroke tint + R142 drop-shadow + R26 lift + R427/R428 ls.
|
|
5
|
+
*
|
|
6
|
+
* Contract:
|
|
7
|
+
* - rest (cyber): every label-card reports opacity '0.94'
|
|
8
|
+
* - rest elevation attr 'idle' on all cards
|
|
9
|
+
* - hover one node: that card opacity '1' + elevation 'hover'
|
|
10
|
+
* - siblings stay at 0.94 / 'idle'
|
|
11
|
+
* - source-file probe confirms conditional + R246 transition intact
|
|
12
|
+
*/
|
|
13
|
+
import { chromium } from 'playwright';
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
|
|
16
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
17
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
18
|
+
|
|
19
|
+
const browser = await chromium.launch({ headless: true });
|
|
20
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
21
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
22
|
+
await ctx.addInitScript(() => {
|
|
23
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
24
|
+
});
|
|
25
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
26
|
+
const r = await route.fetch();
|
|
27
|
+
const b = await r.json();
|
|
28
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
29
|
+
const mk = (alias, status) => ({
|
|
30
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
31
|
+
network_id: nid, project_dir: null,
|
|
32
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
33
|
+
});
|
|
34
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
35
|
+
mk('alpha', 'working'),
|
|
36
|
+
mk('beta', 'idle'),
|
|
37
|
+
mk('gamma', 'working'),
|
|
38
|
+
] } });
|
|
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-node-label-card]', { timeout: 15000 });
|
|
46
|
+
await page.waitForTimeout(400);
|
|
47
|
+
|
|
48
|
+
const readAll = () => page.evaluate(() => {
|
|
49
|
+
const rects = [...document.querySelectorAll('[data-node-label-card]')];
|
|
50
|
+
return rects.map(t => ({
|
|
51
|
+
alias: t.getAttribute('data-node-label-card'),
|
|
52
|
+
opacity: t.getAttribute('opacity'),
|
|
53
|
+
elevation: t.getAttribute('data-node-label-card-elevation'),
|
|
54
|
+
}));
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const rest = await readAll();
|
|
58
|
+
const firstAlias = rest[0]?.alias;
|
|
59
|
+
let hover = null;
|
|
60
|
+
if (firstAlias) {
|
|
61
|
+
const box = await page.evaluate((alias) => {
|
|
62
|
+
const t = document.querySelector(`[data-node-label-card="${alias}"]`);
|
|
63
|
+
if (!t) return null;
|
|
64
|
+
const node = t.closest('[data-node]');
|
|
65
|
+
const target = node || t;
|
|
66
|
+
const b = target.getBoundingClientRect();
|
|
67
|
+
return { x: b.x + b.width / 2, y: b.y + b.height / 2 };
|
|
68
|
+
}, firstAlias);
|
|
69
|
+
if (box) {
|
|
70
|
+
await page.mouse.move(box.x, box.y);
|
|
71
|
+
await page.waitForTimeout(300);
|
|
72
|
+
hover = await readAll();
|
|
73
|
+
await page.mouse.move(0, 0);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
78
|
+
const sourceWired = /opacity=\{\s*\n?\s*!reducedMotion && hoveredAlias === session\.alias\s*\n?\s*\?\s*1\s*\n?\s*:\s*\(isLight \? 1 : 0\.94\)\s*\n?\s*\}/.test(fileText);
|
|
79
|
+
const sourceTransition = /transition: 'filter 220ms ease-out, stroke 220ms ease-out, fill 220ms ease-out, opacity 220ms ease-out'/.test(fileText);
|
|
80
|
+
|
|
81
|
+
await browser.close();
|
|
82
|
+
|
|
83
|
+
const hoveredEntry = hover?.find(r => r.alias === firstAlias);
|
|
84
|
+
const othersRest = hover ? hover.filter(r => r.alias !== firstAlias).every(r => r.opacity === '0.94' && r.elevation === 'idle') : false;
|
|
85
|
+
|
|
86
|
+
const results = {
|
|
87
|
+
rest_card_count_gte_3: rest.length >= 3,
|
|
88
|
+
rest_all_opacity_0_94: rest.every(r => r.opacity === '0.94'),
|
|
89
|
+
rest_all_elevation_idle: rest.every(r => r.elevation === 'idle'),
|
|
90
|
+
hover_target_opacity_1: hoveredEntry?.opacity === '1',
|
|
91
|
+
hover_target_elevation: hoveredEntry?.elevation === 'hover',
|
|
92
|
+
hover_others_stay_idle: othersRest,
|
|
93
|
+
source_conditional_wired: sourceWired,
|
|
94
|
+
source_transition_intact: sourceTransition,
|
|
95
|
+
};
|
|
96
|
+
const ok = Object.values(results).every(Boolean);
|
|
97
|
+
console.log(`${ok ? '✅' : '❌'} label card opacity hover:`, JSON.stringify(results),
|
|
98
|
+
'\n hover target:', JSON.stringify(hoveredEntry));
|
|
99
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/* Round 375 verification: Layout-toggle wrapper rounded-md → rounded-
|
|
2
|
+
* lg (6 → 8 px). Extends the R330/R331/R332 corner-radius cascade to
|
|
3
|
+
* the chrome-strip layout-toggle wrapper. Pre-R375 the wrapper at
|
|
4
|
+
* rounded-md (6 px) was the only chrome-strip container still using
|
|
5
|
+
* the smaller corner radius — both R330 outer wrapper and R332
|
|
6
|
+
* minimap sit at ≥ 8 px; R375 brings the toggle into the rounded-lg
|
|
7
|
+
* tier where minimap already lives.
|
|
8
|
+
*
|
|
9
|
+
* Contract:
|
|
10
|
+
* - data-topo-chrome-layout-trailer element computed border-radius
|
|
11
|
+
* === '8px' (rounded-lg).
|
|
12
|
+
* - data-topo-chrome-layout-radius === 'rounded-lg'.
|
|
13
|
+
* - Pre-R375 invariants:
|
|
14
|
+
* * border still present (1 px default Tailwind)
|
|
15
|
+
* * R268 inline borderColor + 200ms border-color transition
|
|
16
|
+
* * R329 mr-0.5 spacing preserved
|
|
17
|
+
* * inline-flex + overflow-hidden preserved
|
|
18
|
+
* * Inner buttons (Ring + Grid) still mounted as flex children
|
|
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-chrome-layout-trailer]', { timeout: 15000 });
|
|
48
|
+
await page.waitForTimeout(300);
|
|
49
|
+
|
|
50
|
+
const probe = await page.evaluate(() => {
|
|
51
|
+
const w = document.querySelector('[data-topo-chrome-layout-trailer]');
|
|
52
|
+
const cs = w ? getComputedStyle(w) : null;
|
|
53
|
+
const ring = w?.querySelector('[data-topo-chrome-layout="ring"]');
|
|
54
|
+
const grid = w?.querySelector('[data-topo-chrome-layout="grid"]');
|
|
55
|
+
return {
|
|
56
|
+
borderRadius: cs?.borderRadius ?? null,
|
|
57
|
+
radiusData: w?.getAttribute('data-topo-chrome-layout-radius') ?? null,
|
|
58
|
+
borderWidth: cs?.borderWidth ?? null,
|
|
59
|
+
display: cs?.display ?? null,
|
|
60
|
+
overflow: cs?.overflow ?? null,
|
|
61
|
+
transition: cs?.transition ?? null,
|
|
62
|
+
cls: w?.getAttribute('class') ?? null,
|
|
63
|
+
ringPresent: !!ring,
|
|
64
|
+
gridPresent: !!grid,
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await browser.close();
|
|
69
|
+
|
|
70
|
+
const hasTrans = (s, prop) =>
|
|
71
|
+
new RegExp(`${prop}\\s+\\d*\\.?\\d*s|${prop}\\s+\\d+ms`, 'i').test(s || '');
|
|
72
|
+
|
|
73
|
+
const results = {
|
|
74
|
+
border_radius_8px: probe.borderRadius === '8px', // rounded-lg
|
|
75
|
+
data_radius_lg: probe.radiusData === 'rounded-lg',
|
|
76
|
+
border_width_1px: probe.borderWidth === '1px',
|
|
77
|
+
display_inline_flex: probe.display === 'inline-flex' || probe.display === 'flex',
|
|
78
|
+
overflow_hidden: probe.overflow === 'hidden',
|
|
79
|
+
trans_has_border_color: hasTrans(probe.transition, 'border-color'), // R268
|
|
80
|
+
cls_has_mr_0_5: /mr-0\.5/.test(probe.cls || ''), // R329
|
|
81
|
+
ring_button_present: probe.ringPresent,
|
|
82
|
+
grid_button_present: probe.gridPresent,
|
|
83
|
+
};
|
|
84
|
+
const ok = Object.values(results).every(Boolean);
|
|
85
|
+
console.log(`${ok ? '✅' : '❌'} Layout-toggle wrapper rounded-md → rounded-lg:`, JSON.stringify(results),
|
|
86
|
+
'\n probe:', probe);
|
|
87
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/* Round 449 verification: legend-row count active-state opacity
|
|
2
|
+
* 0.95 → 1.0 on (hoveredStatus===row.key || isPinned). Closes the 5%
|
|
3
|
+
* alpha gap on populated active rows.
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - rest: every populated legend-count reports opacity '0.65' (R204)
|
|
7
|
+
* - click 'working' status: that count opacity '1'
|
|
8
|
+
* - empty (0-count) rows stay at R204 dim (0.28/0.30) unaffected
|
|
9
|
+
* - siblings stay at rest 0.65
|
|
10
|
+
*/
|
|
11
|
+
import { chromium } from 'playwright';
|
|
12
|
+
import { readFileSync } from 'node:fs';
|
|
13
|
+
|
|
14
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
15
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
16
|
+
|
|
17
|
+
const browser = await chromium.launch({ headless: true });
|
|
18
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
19
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
20
|
+
await ctx.addInitScript(() => {
|
|
21
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
22
|
+
});
|
|
23
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
24
|
+
const r = await route.fetch();
|
|
25
|
+
const b = await r.json();
|
|
26
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
27
|
+
const mk = (alias, status) => ({
|
|
28
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
29
|
+
network_id: nid, project_dir: null,
|
|
30
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
31
|
+
});
|
|
32
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
33
|
+
mk('alpha', 'working'),
|
|
34
|
+
mk('beta', 'working'),
|
|
35
|
+
mk('gamma', '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
|
+
await page.waitForSelector('[data-legend-count]', { timeout: 15000 });
|
|
44
|
+
await page.waitForTimeout(400);
|
|
45
|
+
|
|
46
|
+
const readAll = () => page.evaluate(() => {
|
|
47
|
+
const ts = [...document.querySelectorAll('[data-legend-count]')];
|
|
48
|
+
return ts.map(t => ({
|
|
49
|
+
key: t.getAttribute('data-legend-count'),
|
|
50
|
+
opacity: t.getAttribute('opacity'),
|
|
51
|
+
empty: t.getAttribute('data-legend-count-empty'),
|
|
52
|
+
}));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const rest = await readAll();
|
|
56
|
+
|
|
57
|
+
// Click 'working' status row to pin
|
|
58
|
+
let pinned = null;
|
|
59
|
+
const workingGroup = await page.$(`[data-legend-status="working"]`);
|
|
60
|
+
if (workingGroup) {
|
|
61
|
+
await workingGroup.click();
|
|
62
|
+
await page.waitForTimeout(250);
|
|
63
|
+
pinned = await readAll();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
67
|
+
const sourceWired = /:\s*\(hoveredStatus === row\.key \|\| isPinned \? 1 : 0\.65\)/.test(fileText);
|
|
68
|
+
|
|
69
|
+
await browser.close();
|
|
70
|
+
|
|
71
|
+
// rest: populated rows (working=2, idle=1) should be 0.65; offline (count=0) should be 0.28/0.30
|
|
72
|
+
const workingRest = rest.find(r => r.key === 'working');
|
|
73
|
+
const idleRest = rest.find(r => r.key === 'idle');
|
|
74
|
+
const offlineRest = rest.find(r => r.key === 'offline');
|
|
75
|
+
|
|
76
|
+
const restWorking_065 = workingRest?.opacity === '0.65';
|
|
77
|
+
const restIdle_065 = idleRest?.opacity === '0.65';
|
|
78
|
+
const restOfflineEmpty = offlineRest?.empty === 'true' && (offlineRest?.opacity === '0.3' || offlineRest?.opacity === '0.28');
|
|
79
|
+
|
|
80
|
+
// pinned: working should be 1
|
|
81
|
+
const pinnedWorking = pinned?.find(r => r.key === 'working');
|
|
82
|
+
const pinnedIdle = pinned?.find(r => r.key === 'idle');
|
|
83
|
+
const pinnedOffline = pinned?.find(r => r.key === 'offline');
|
|
84
|
+
|
|
85
|
+
const pinWorking_1 = pinnedWorking?.opacity === '1';
|
|
86
|
+
const pinIdleRest = pinnedIdle?.opacity === '0.65';
|
|
87
|
+
const pinOfflineEmpty = pinnedOffline?.empty === 'true';
|
|
88
|
+
|
|
89
|
+
const results = {
|
|
90
|
+
rest_working_065: restWorking_065,
|
|
91
|
+
rest_idle_065: restIdle_065,
|
|
92
|
+
rest_offline_empty_dim: restOfflineEmpty,
|
|
93
|
+
pin_working_opacity_1: pinWorking_1,
|
|
94
|
+
pin_idle_stays_rest_065: pinIdleRest,
|
|
95
|
+
pin_offline_stays_empty: pinOfflineEmpty,
|
|
96
|
+
source_wired: sourceWired,
|
|
97
|
+
};
|
|
98
|
+
const ok = Object.values(results).every(Boolean);
|
|
99
|
+
console.log(`${ok ? '✅' : '❌'} legend count active opacity:`, JSON.stringify(results),
|
|
100
|
+
'\n rest:', JSON.stringify(rest),
|
|
101
|
+
'\n pinned:', JSON.stringify(pinned));
|
|
102
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/* Round 446 verification: legend-row count fontWeight lift on isPinned.
|
|
2
|
+
* 600 → 700 when the status tier is pinned. Mirror of R444/R445 at
|
|
3
|
+
* legend-row scope.
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - rest: every legend-count reports font-weight '600' + pinned='false'
|
|
7
|
+
* - click a legend-status group: that row's count flips to '700' +
|
|
8
|
+
* pinned='true'; siblings stay rest
|
|
9
|
+
*/
|
|
10
|
+
import { chromium } from 'playwright';
|
|
11
|
+
import { readFileSync } from 'node:fs';
|
|
12
|
+
|
|
13
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
14
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
15
|
+
|
|
16
|
+
const browser = await chromium.launch({ headless: true });
|
|
17
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
18
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
19
|
+
await ctx.addInitScript(() => {
|
|
20
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
21
|
+
});
|
|
22
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
23
|
+
const r = await route.fetch();
|
|
24
|
+
const b = await r.json();
|
|
25
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
26
|
+
const mk = (alias, status) => ({
|
|
27
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
28
|
+
network_id: nid, project_dir: null,
|
|
29
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
30
|
+
});
|
|
31
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
32
|
+
mk('alpha', 'working'),
|
|
33
|
+
mk('beta', 'working'),
|
|
34
|
+
mk('gamma', 'idle'),
|
|
35
|
+
] } });
|
|
36
|
+
});
|
|
37
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
38
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
39
|
+
|
|
40
|
+
const page = await ctx.newPage();
|
|
41
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
42
|
+
await page.waitForSelector('[data-legend-count]', { timeout: 15000 });
|
|
43
|
+
await page.waitForTimeout(400);
|
|
44
|
+
|
|
45
|
+
const readAll = () => page.evaluate(() => {
|
|
46
|
+
const ts = [...document.querySelectorAll('[data-legend-count]')];
|
|
47
|
+
return ts.map(t => ({
|
|
48
|
+
key: t.getAttribute('data-legend-count'),
|
|
49
|
+
fw: t.getAttribute('font-weight'),
|
|
50
|
+
pinned: t.getAttribute('data-legend-count-pinned'),
|
|
51
|
+
}));
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const rest = await readAll();
|
|
55
|
+
|
|
56
|
+
// Click the 'working' status row to pin it
|
|
57
|
+
let pinned = null;
|
|
58
|
+
const workingGroup = await page.$(`[data-legend-status="working"]`);
|
|
59
|
+
if (workingGroup) {
|
|
60
|
+
await workingGroup.click();
|
|
61
|
+
await page.waitForTimeout(250);
|
|
62
|
+
pinned = await readAll();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
66
|
+
const sourceWired = /fontWeight=\{isPinned \? '700' : '600'\}/.test(fileText);
|
|
67
|
+
|
|
68
|
+
await browser.close();
|
|
69
|
+
|
|
70
|
+
const restAll600 = rest.every(r => r.fw === '600');
|
|
71
|
+
const restNoPin = rest.every(r => r.pinned === 'false');
|
|
72
|
+
const pinnedEntry = pinned?.find(r => r.key === 'working');
|
|
73
|
+
const pinFw_700 = pinnedEntry?.fw === '700';
|
|
74
|
+
const pinFlag = pinnedEntry?.pinned === 'true';
|
|
75
|
+
const othersStayRest = pinned ? pinned.filter(r => r.key !== 'working').every(r => r.fw === '600' && r.pinned === 'false') : false;
|
|
76
|
+
|
|
77
|
+
const results = {
|
|
78
|
+
rest_three_rows: rest.length === 3,
|
|
79
|
+
rest_all_fw_600: restAll600,
|
|
80
|
+
rest_no_pin: restNoPin,
|
|
81
|
+
pinned_target_fw_700: pinFw_700,
|
|
82
|
+
pinned_target_flag: pinFlag,
|
|
83
|
+
pinned_others_stay: othersStayRest,
|
|
84
|
+
source_wired: sourceWired,
|
|
85
|
+
};
|
|
86
|
+
const ok = Object.values(results).every(Boolean);
|
|
87
|
+
console.log(`${ok ? '✅' : '❌'} legend count fw pin:`, JSON.stringify(results),
|
|
88
|
+
'\n rest:', JSON.stringify(rest),
|
|
89
|
+
'\n pinned target:', JSON.stringify(pinnedEntry));
|
|
90
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/* Round 364 verification: legend-row label fontWeight 400 → 500.
|
|
2
|
+
* Sibling typography lift to R363 recent-row text fw 400 → 500.
|
|
3
|
+
* Both surfaces render small monospace text against panel chrome
|
|
4
|
+
* at fontSize 9-11 where SVG-default fw 400 sits at the legibility
|
|
5
|
+
* floor.
|
|
6
|
+
*
|
|
7
|
+
* Family snapshot post-R364:
|
|
8
|
+
* legend label fw 500 (R364, this round)
|
|
9
|
+
* legend count fw 600 (R309)
|
|
10
|
+
* recent alias fw 500 (R363)
|
|
11
|
+
* recent count fw 600/700 (R320)
|
|
12
|
+
*
|
|
13
|
+
* Contract (cyber, fixture with active rows):
|
|
14
|
+
* - Each rendered [data-legend-row-label] has font-weight === '500'.
|
|
15
|
+
* - Each has data-legend-row-label-font-weight === '500'.
|
|
16
|
+
* - Pre-R364 invariants:
|
|
17
|
+
* * fontSize=11 + fontFamily=monospace
|
|
18
|
+
* * R219 letter-spacing 0 → 0.5px on pin (style.transition still
|
|
19
|
+
* lists letter-spacing)
|
|
20
|
+
* * R55 fill transition retained
|
|
21
|
+
* * data-legend-row-label key surfaces (working / idle / offline)
|
|
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 browser = await chromium.launch({ headless: true });
|
|
28
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
29
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
30
|
+
await ctx.addInitScript(() => {
|
|
31
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
32
|
+
});
|
|
33
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
34
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
35
|
+
const r = await route.fetch();
|
|
36
|
+
const b = await r.json();
|
|
37
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
38
|
+
const mk = (alias) => ({
|
|
39
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
40
|
+
network_id: nid, project_dir: null,
|
|
41
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
42
|
+
});
|
|
43
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('a'), mk('b'), mk('c') ] } });
|
|
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
|
+
await page.waitForSelector('[data-legend-row-label]', { timeout: 15000 });
|
|
51
|
+
await page.waitForTimeout(300);
|
|
52
|
+
|
|
53
|
+
const probe = await page.evaluate(() => {
|
|
54
|
+
const labels = Array.from(document.querySelectorAll('[data-legend-row-label]'));
|
|
55
|
+
return labels.map(el => {
|
|
56
|
+
const cs = getComputedStyle(el);
|
|
57
|
+
return {
|
|
58
|
+
key: el.getAttribute('data-legend-row-label'),
|
|
59
|
+
fontWeightAttr: el.getAttribute('font-weight'),
|
|
60
|
+
fontWeightData: el.getAttribute('data-legend-row-label-font-weight'),
|
|
61
|
+
fontSizeAttr: el.getAttribute('font-size'),
|
|
62
|
+
fontFamily: el.getAttribute('font-family'),
|
|
63
|
+
transition: cs.transition,
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await browser.close();
|
|
69
|
+
|
|
70
|
+
const hasTrans = (s, prop) =>
|
|
71
|
+
new RegExp(`${prop}\\s+\\d*\\.?\\d*s|${prop}\\s+\\d+ms`, 'i').test(s || '');
|
|
72
|
+
|
|
73
|
+
const allRowsOk = probe.length > 0 && probe.every(r =>
|
|
74
|
+
r.fontWeightAttr === '500'
|
|
75
|
+
&& r.fontWeightData === '500'
|
|
76
|
+
&& r.fontSizeAttr === '11'
|
|
77
|
+
&& /monospace/i.test(r.fontFamily || '')
|
|
78
|
+
&& hasTrans(r.transition, 'letter-spacing')
|
|
79
|
+
&& hasTrans(r.transition, 'fill')
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const results = {
|
|
83
|
+
rows_rendered: probe.length >= 1,
|
|
84
|
+
all_rows_fw_500: probe.every(r => r.fontWeightAttr === '500'),
|
|
85
|
+
all_rows_data_500: probe.every(r => r.fontWeightData === '500'),
|
|
86
|
+
all_rows_fontsize_11: probe.every(r => r.fontSizeAttr === '11'),
|
|
87
|
+
all_rows_monospace: probe.every(r => /monospace/i.test(r.fontFamily || '')),
|
|
88
|
+
all_rows_have_ls_trans: probe.every(r => hasTrans(r.transition, 'letter-spacing')),
|
|
89
|
+
all_rows_have_fill_trans: probe.every(r => hasTrans(r.transition, 'fill')),
|
|
90
|
+
};
|
|
91
|
+
const ok = allRowsOk && Object.values(results).every(Boolean);
|
|
92
|
+
console.log(`${ok ? '✅' : '❌'} legend-row label fw 400 → 500:`, JSON.stringify(results),
|
|
93
|
+
'\n rows: ', probe.map(r => ({ key: r.key, fw: r.fontWeightAttr })));
|
|
94
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/* Round 402 verification: legend pin-ring strokeWidth 1.5 → 1.75.
|
|
2
|
+
* Sibling visual-weight bump (12th anchor) to R385 hub hover-ring
|
|
3
|
+
* — both are stroke-only pin/hover indicators painted as r=8 / r=14
|
|
4
|
+
* circles outside their target. R51 sentinel concern: 1.5 reserved
|
|
5
|
+
* for offline-node detection, but selector gated to g[data-node]
|
|
6
|
+
* ancestors so this legend-internal circle is invisible to probe.
|
|
7
|
+
*
|
|
8
|
+
* Contract:
|
|
9
|
+
* - data-legend-pin-ring-stroke-width === '1.75' (idle state too,
|
|
10
|
+
* since the attr surfaces the resolved value regardless of pin)
|
|
11
|
+
* - <circle> stroke-width attr === '1.75'
|
|
12
|
+
* - Pre-R402 invariants preserved:
|
|
13
|
+
* * r='8', fill='none', cx='16'
|
|
14
|
+
* * opacity reflects isPinned state (0 idle, 1 pinned)
|
|
15
|
+
* * data-legend-pin-ring-pinned attr present
|
|
16
|
+
* - Idle ring: opacity='0' (R181 always-mount + transition)
|
|
17
|
+
* - Pinned ring (after click): opacity='1'
|
|
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 fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
24
|
+
|
|
25
|
+
const browser = await chromium.launch({ headless: true });
|
|
26
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
27
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
28
|
+
await ctx.addInitScript(() => {
|
|
29
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
30
|
+
});
|
|
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, status) => ({
|
|
36
|
+
alias, status, 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: [
|
|
41
|
+
mk('alpha', 'working'),
|
|
42
|
+
mk('beta', 'idle'),
|
|
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
|
+
await page.waitForSelector('[data-legend-pin-ring]', { timeout: 15000 });
|
|
51
|
+
await page.waitForTimeout(400);
|
|
52
|
+
|
|
53
|
+
const restProbe = await page.evaluate(() => {
|
|
54
|
+
const ring = document.querySelector('[data-legend-pin-ring]');
|
|
55
|
+
return ring ? {
|
|
56
|
+
strokeWidthAttr: ring.getAttribute('stroke-width'),
|
|
57
|
+
strokeWidthData: ring.getAttribute('data-legend-pin-ring-stroke-width'),
|
|
58
|
+
rAttr: ring.getAttribute('r'),
|
|
59
|
+
fillAttr: ring.getAttribute('fill'),
|
|
60
|
+
cxAttr: ring.getAttribute('cx'),
|
|
61
|
+
opacityAttr: ring.getAttribute('opacity'),
|
|
62
|
+
pinned: ring.getAttribute('data-legend-pin-ring-pinned'),
|
|
63
|
+
} : null;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Click a legend row to pin it
|
|
67
|
+
await page.click('[data-legend-status="working"]');
|
|
68
|
+
await page.waitForTimeout(300);
|
|
69
|
+
|
|
70
|
+
const pinnedProbe = await page.evaluate(() => {
|
|
71
|
+
const rings = Array.from(document.querySelectorAll('[data-legend-pin-ring]'));
|
|
72
|
+
const pinned = rings.find((r) => r.getAttribute('data-legend-pin-ring-pinned') === 'true');
|
|
73
|
+
return pinned ? {
|
|
74
|
+
strokeWidthAttr: pinned.getAttribute('stroke-width'),
|
|
75
|
+
opacityAttr: pinned.getAttribute('opacity'),
|
|
76
|
+
rAttr: pinned.getAttribute('r'),
|
|
77
|
+
} : null;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await browser.close();
|
|
81
|
+
|
|
82
|
+
const results = {
|
|
83
|
+
// R402 wire: stroke-width attr + data both 1.75
|
|
84
|
+
rest_strokeWidth_1_75: restProbe?.strokeWidthAttr === '1.75',
|
|
85
|
+
rest_data_1_75: restProbe?.strokeWidthData === '1.75',
|
|
86
|
+
// Pre-R402 invariants (R181 + base geometry)
|
|
87
|
+
rest_r_8: restProbe?.rAttr === '8',
|
|
88
|
+
rest_fill_none: restProbe?.fillAttr === 'none',
|
|
89
|
+
rest_cx_16: restProbe?.cxAttr === '16',
|
|
90
|
+
rest_opacity_0: restProbe?.opacityAttr === '0', // R181 idle invariant
|
|
91
|
+
rest_pinned_false: restProbe?.pinned === 'false',
|
|
92
|
+
// Pinned state preserves the bumped stroke
|
|
93
|
+
pinned_strokeWidth_1_75: pinnedProbe?.strokeWidthAttr === '1.75',
|
|
94
|
+
pinned_opacity_1: pinnedProbe?.opacityAttr === '1', // R181 pinned alpha
|
|
95
|
+
pinned_r_8: pinnedProbe?.rAttr === '8', // geometry preserved
|
|
96
|
+
};
|
|
97
|
+
const ok = Object.values(results).every(Boolean);
|
|
98
|
+
console.log(`${ok ? '✅' : '❌'} legend pin-ring strokeWidth 1.5 → 1.75:`, JSON.stringify(results),
|
|
99
|
+
'\n rest: ', restProbe,
|
|
100
|
+
'\n pinned: ', pinnedProbe);
|
|
101
|
+
process.exit(ok ? 0 : 1);
|