@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,92 @@
|
|
|
1
|
+
/* Round 374 verification: pressure-bar height h-1.5 → h-2 (6 → 8 px).
|
|
2
|
+
* Sibling visual-weight bump (8th canvas/HTML anchor in the family).
|
|
3
|
+
* +33 % bar height gives working/idle/offline segments more visibility.
|
|
4
|
+
*
|
|
5
|
+
* Geometry-safe: items-center flex centers the bar inside the chip's
|
|
6
|
+
* py-1 — bar at 8 px stays comfortably inside the 10-px text-row.
|
|
7
|
+
*
|
|
8
|
+
* Contract (cyber, fixture with mix):
|
|
9
|
+
* - Pressure bar wrapper computed height === '8px' (h-2).
|
|
10
|
+
* - data-fleet-pressure-bar-height === 'h-2'.
|
|
11
|
+
* - Pre-R374 invariants:
|
|
12
|
+
* * width still w-16 (64 px)
|
|
13
|
+
* * inline-flex display + rounded-full + overflow-hidden
|
|
14
|
+
* * background rgb(75 85 99 / 0.25)
|
|
15
|
+
* * Parent [data-fleet-pressure] chip className unchanged
|
|
16
|
+
* (font-mono + chip structure)
|
|
17
|
+
*/
|
|
18
|
+
import { chromium } from 'playwright';
|
|
19
|
+
import { readFileSync } from 'node:fs';
|
|
20
|
+
|
|
21
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
22
|
+
const browser = await chromium.launch({ headless: true });
|
|
23
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
24
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
25
|
+
await ctx.addInitScript(() => {
|
|
26
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
27
|
+
});
|
|
28
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
29
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
30
|
+
const r = await route.fetch();
|
|
31
|
+
const b = await r.json();
|
|
32
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
33
|
+
const mk = (alias, status = 'working') => ({
|
|
34
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
35
|
+
network_id: nid, project_dir: null,
|
|
36
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
37
|
+
});
|
|
38
|
+
// Mix so all 3 segments render.
|
|
39
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
40
|
+
mk('w1'), mk('w2'),
|
|
41
|
+
mk('i1', 'idle'), mk('i2', 'idle'),
|
|
42
|
+
mk('o1', 'offline'),
|
|
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-fleet-pressure-bar-height]', { timeout: 15000 });
|
|
51
|
+
await page.waitForTimeout(300);
|
|
52
|
+
|
|
53
|
+
const probe = await page.evaluate(() => {
|
|
54
|
+
const bar = document.querySelector('[data-fleet-pressure-bar-height]');
|
|
55
|
+
const cs = bar ? getComputedStyle(bar) : null;
|
|
56
|
+
const parent = document.querySelector('[data-fleet-pressure]');
|
|
57
|
+
// Count visible segments inside the bar.
|
|
58
|
+
const segs = bar ? Array.from(bar.querySelectorAll('[data-pressure-seg]')) : [];
|
|
59
|
+
return {
|
|
60
|
+
height: cs?.height ?? null,
|
|
61
|
+
width: cs?.width ?? null,
|
|
62
|
+
barHeightData: bar?.getAttribute('data-fleet-pressure-bar-height') ?? null,
|
|
63
|
+
display: cs?.display ?? null,
|
|
64
|
+
borderRadius: cs?.borderRadius ?? null,
|
|
65
|
+
overflow: cs?.overflow ?? null,
|
|
66
|
+
bgColor: cs?.backgroundColor ?? null,
|
|
67
|
+
parentMono: /font-mono/.test(parent?.getAttribute('class') || ''),
|
|
68
|
+
segCount: segs.length,
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
await browser.close();
|
|
73
|
+
|
|
74
|
+
const results = {
|
|
75
|
+
height_8px: probe.height === '8px', // h-2
|
|
76
|
+
width_64px: probe.width === '64px', // w-16
|
|
77
|
+
data_height_h_2: probe.barHeightData === 'h-2',
|
|
78
|
+
// Flex items get display blockified: inline-flex → flex when nested
|
|
79
|
+
// in flex container. Accept either.
|
|
80
|
+
display_inline_flex: probe.display === 'inline-flex' || probe.display === 'flex',
|
|
81
|
+
// Tailwind rounded-full is border-radius: 9999px, which browsers
|
|
82
|
+
// sometimes render as 3.35544e+07px (huge approximation). Accept any
|
|
83
|
+
// value indicating fully-rounded.
|
|
84
|
+
has_rounded_full: /9999|3\.355|e\+/.test(probe.borderRadius || ''),
|
|
85
|
+
overflow_hidden: probe.overflow === 'hidden',
|
|
86
|
+
parent_font_mono: probe.parentMono,
|
|
87
|
+
three_segments: probe.segCount === 3,
|
|
88
|
+
};
|
|
89
|
+
const ok = Object.values(results).every(Boolean);
|
|
90
|
+
console.log(`${ok ? '✅' : '❌'} pressure-bar height 1.5 → 2:`, JSON.stringify(results),
|
|
91
|
+
'\n probe:', probe);
|
|
92
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/* Round 373 verification: pressure-bar kicker label fontWeight 400 →
|
|
2
|
+
* 500. Sibling small-text fw lift family with R363/R364/R366/R368 —
|
|
3
|
+
* 5th surface in the family.
|
|
4
|
+
*
|
|
5
|
+
* Family snapshot post-R373:
|
|
6
|
+
* recent-row alias fw 500 (R363)
|
|
7
|
+
* legend-row label fw 500 (R364)
|
|
8
|
+
* group-label count fw 500 (R366)
|
|
9
|
+
* +N more flows footer fw 500 (R368)
|
|
10
|
+
* pressure-bar kicker fw 500 (R373, this round)
|
|
11
|
+
*
|
|
12
|
+
* Contract (cyber, fixture with mix so pressure bar renders):
|
|
13
|
+
* - [data-fleet-pressure-kicker] computed fontWeight === '500'.
|
|
14
|
+
* - Pre-R373 invariants:
|
|
15
|
+
* * text-[10px] (fontSize 10) preserved
|
|
16
|
+
* * tracking-wide (letter-spacing 0.025em) preserved
|
|
17
|
+
* * Parent [data-fleet-pressure] still has font-mono + chip
|
|
18
|
+
* structure
|
|
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-fleet-pressure-kicker]', { timeout: 15000 });
|
|
48
|
+
await page.waitForTimeout(300);
|
|
49
|
+
|
|
50
|
+
const probe = await page.evaluate(() => {
|
|
51
|
+
const kicker = document.querySelector('[data-fleet-pressure-kicker]');
|
|
52
|
+
const parent = document.querySelector('[data-fleet-pressure]');
|
|
53
|
+
const cs = kicker ? getComputedStyle(kicker) : null;
|
|
54
|
+
return {
|
|
55
|
+
fontWeight: cs?.fontWeight ?? null,
|
|
56
|
+
fontSize: cs?.fontSize ?? null,
|
|
57
|
+
letterSpacing: cs?.letterSpacing ?? null,
|
|
58
|
+
text: kicker?.textContent ?? null,
|
|
59
|
+
parentCls: parent?.getAttribute('class') ?? null,
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
await browser.close();
|
|
64
|
+
|
|
65
|
+
const results = {
|
|
66
|
+
font_weight_500: probe.fontWeight === '500',
|
|
67
|
+
font_size_10px: probe.fontSize === '10px',
|
|
68
|
+
// tracking-wide = 0.025em → at 10px font that's 0.25px computed.
|
|
69
|
+
letter_spacing_tracking_wide: /0\.25px|0\.025em/.test(probe.letterSpacing || ''),
|
|
70
|
+
text_is_pressure: probe.text === 'pressure',
|
|
71
|
+
parent_font_mono: /font-mono/.test(probe.parentCls || ''),
|
|
72
|
+
};
|
|
73
|
+
const ok = Object.values(results).every(Boolean);
|
|
74
|
+
console.log(`${ok ? '✅' : '❌'} pressure-bar kicker fw 400 → 500:`, JSON.stringify(results),
|
|
75
|
+
'\n probe:', probe);
|
|
76
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/* Round 383 verification: recency pip base radius 1.8 → 2.0.
|
|
2
|
+
* Continues R359 lift trajectory; sibling visual-weight bump
|
|
3
|
+
* family (9th anchor).
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - Pip element computed r === '2.0' (rendered) or attribute equals 2.
|
|
7
|
+
* - data-recent-row-freshness-radius === '2.0'.
|
|
8
|
+
* - Pre-R383 invariants:
|
|
9
|
+
* * cx=10 (R160 left margin position unchanged)
|
|
10
|
+
* * fill=pal.legendAccent
|
|
11
|
+
* * opacity transition (R358) preserved
|
|
12
|
+
* * R358 stale-alpha floor 0.30 still applies
|
|
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 browser = await chromium.launch({ headless: true });
|
|
19
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
20
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
21
|
+
await ctx.addInitScript(() => {
|
|
22
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
23
|
+
});
|
|
24
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
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) => ({
|
|
30
|
+
alias, status: 'working', 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: [ mk('a'), mk('b') ] } });
|
|
35
|
+
});
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
38
|
+
{ id: 'm1', from_alias: 'a', to_alias: 'b', content: 'ping',
|
|
39
|
+
network_id: 'default', created_at: new Date(now - 5000).toISOString(),
|
|
40
|
+
last_at: new Date(now - 5000).toISOString() },
|
|
41
|
+
] } }));
|
|
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-recent-row-freshness]', { timeout: 15000 });
|
|
47
|
+
await page.waitForTimeout(300);
|
|
48
|
+
|
|
49
|
+
const probe = await page.evaluate(() => {
|
|
50
|
+
const pip = document.querySelector('[data-recent-row-freshness]');
|
|
51
|
+
return {
|
|
52
|
+
rAttr: pip?.getAttribute('r') ?? null,
|
|
53
|
+
radiusAttr: pip?.getAttribute('data-recent-row-freshness-radius') ?? null,
|
|
54
|
+
cxAttr: pip?.getAttribute('cx') ?? null,
|
|
55
|
+
linkKey: pip?.getAttribute('data-recent-row-freshness') ?? null,
|
|
56
|
+
opacityAttr: pip?.getAttribute('opacity') ?? null,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
await browser.close();
|
|
61
|
+
|
|
62
|
+
const results = {
|
|
63
|
+
r_attr_2: probe.rAttr === '2' || probe.rAttr === '2.0',
|
|
64
|
+
radius_attr_2_0: probe.radiusAttr === '2.0',
|
|
65
|
+
cx_unchanged_10: probe.cxAttr === '10', // R160 invariant
|
|
66
|
+
link_key_present: (probe.linkKey || '').length > 0,
|
|
67
|
+
opacity_above_zero: parseFloat(probe.opacityAttr || '0') > 0, // fresh, alpha > 0
|
|
68
|
+
};
|
|
69
|
+
const ok = Object.values(results).every(Boolean);
|
|
70
|
+
console.log(`${ok ? '✅' : '❌'} recent pip radius 1.8 → 2.0:`, JSON.stringify(results),
|
|
71
|
+
'\n probe:', probe);
|
|
72
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/* Round 359 verification: recency pip base radius 1.6 → 1.8. Sibling
|
|
2
|
+
* to R358 freshness floor lift (alpha 0.25 → 0.30) — together the
|
|
3
|
+
* stale pip stays distinguishable as it ages.
|
|
4
|
+
* pre-R358/R359: stale pip painted at r=1.6 + α=0.25 (near-invisible)
|
|
5
|
+
* post-R358: stale pip α=0.30
|
|
6
|
+
* post-R359: stale pip r=1.8 (1.8² / 1.6² ≈ 1.27, ~27% more glyph)
|
|
7
|
+
*
|
|
8
|
+
* Same visual-weight family as R287 minimap stroke 1 → 1.5 and R295
|
|
9
|
+
* legend swatch base radius 5.5 → 6.
|
|
10
|
+
*
|
|
11
|
+
* Contract:
|
|
12
|
+
* - Pip element computed r === '1.8' (or rendered SVG r attr).
|
|
13
|
+
* - data-recent-row-freshness-radius === '1.8'.
|
|
14
|
+
* - Pre-R359 invariants preserved:
|
|
15
|
+
* * R358 stale-alpha floor 0.30 still applies (visible on > 300s)
|
|
16
|
+
* * data-recent-row-freshness attr still surfaces the link key
|
|
17
|
+
* * Pip stays inside the 7-px left margin (cx=10 unchanged)
|
|
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
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
31
|
+
const r = await route.fetch();
|
|
32
|
+
const b = await r.json();
|
|
33
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
34
|
+
const mk = (alias) => ({
|
|
35
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
36
|
+
network_id: nid, project_dir: null,
|
|
37
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
38
|
+
});
|
|
39
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('a'), mk('b') ] } });
|
|
40
|
+
});
|
|
41
|
+
const now = Date.now();
|
|
42
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
43
|
+
// Fresh message → row with pip mounts.
|
|
44
|
+
{ id: 'm1', from_alias: 'a', to_alias: 'b', content: 'ping',
|
|
45
|
+
network_id: 'default', created_at: new Date(now - 5000).toISOString(),
|
|
46
|
+
last_at: new Date(now - 5000).toISOString() },
|
|
47
|
+
] } }));
|
|
48
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
49
|
+
|
|
50
|
+
const page = await ctx.newPage();
|
|
51
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
52
|
+
await page.waitForSelector('[data-recent-row-freshness]', { timeout: 15000 });
|
|
53
|
+
await page.waitForTimeout(300);
|
|
54
|
+
|
|
55
|
+
const probe = await page.evaluate(() => {
|
|
56
|
+
const pip = document.querySelector('[data-recent-row-freshness]');
|
|
57
|
+
return {
|
|
58
|
+
rAttr: pip?.getAttribute('r') ?? null,
|
|
59
|
+
radiusAttr: pip?.getAttribute('data-recent-row-freshness-radius') ?? null,
|
|
60
|
+
cxAttr: pip?.getAttribute('cx') ?? null,
|
|
61
|
+
linkKey: pip?.getAttribute('data-recent-row-freshness') ?? null,
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
await browser.close();
|
|
66
|
+
|
|
67
|
+
const results = {
|
|
68
|
+
r_attr_1_8: probe.rAttr === '1.8',
|
|
69
|
+
radius_attr_1_8: probe.radiusAttr === '1.8',
|
|
70
|
+
cx_unchanged_10: probe.cxAttr === '10', // R160 margin invariant
|
|
71
|
+
link_key_present: (probe.linkKey || '').length > 0,
|
|
72
|
+
};
|
|
73
|
+
const ok = Object.values(results).every(Boolean);
|
|
74
|
+
console.log(`${ok ? '✅' : '❌'} recent pip radius 1.6 → 1.8:`, JSON.stringify(results),
|
|
75
|
+
'\n probe:', probe);
|
|
76
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* Round 418 verification: recent-row content preview gets
|
|
2
|
+
* opacity=0.7 tspan wrapper. Subordinate-text tier at the SVG-
|
|
3
|
+
* text scope — sibling to chip-internal-hierarchy label-tier
|
|
4
|
+
* (opacity-70) at HTML scope.
|
|
5
|
+
*
|
|
6
|
+
* Contract:
|
|
7
|
+
* - Seed a flow with content so recent-signal panel mounts a row
|
|
8
|
+
* - The row text contains a <tspan opacity="0.7"
|
|
9
|
+
* data-recent-row-content-tspan> wrapping the preview text
|
|
10
|
+
* - tspan textContent matches the truncated content
|
|
11
|
+
* - Pre-R418 invariants on the row preserved:
|
|
12
|
+
* * R320 count tspan fw=600 cold / 700 hot
|
|
13
|
+
* * R363 row text fw=500
|
|
14
|
+
* * R220 letter-spacing pin signature
|
|
15
|
+
*/
|
|
16
|
+
import { chromium } from 'playwright';
|
|
17
|
+
import { readFileSync } from 'node:fs';
|
|
18
|
+
|
|
19
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
20
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
21
|
+
|
|
22
|
+
const browser = await chromium.launch({ headless: true });
|
|
23
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
24
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
25
|
+
await ctx.addInitScript(() => {
|
|
26
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
27
|
+
});
|
|
28
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
29
|
+
const r = await route.fetch();
|
|
30
|
+
const b = await r.json();
|
|
31
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
32
|
+
const mk = (alias) => ({
|
|
33
|
+
alias, status: 'idle', 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('alpha'), mk('beta') ] } });
|
|
38
|
+
});
|
|
39
|
+
// Seed a flow with content text so the row preview renders
|
|
40
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({
|
|
41
|
+
json: { messages: [
|
|
42
|
+
{ id: 'm1', from_alias: 'alpha', to_alias: 'beta', content: 'hi there!', created_at: fresh, network_id: 'default' },
|
|
43
|
+
] },
|
|
44
|
+
}));
|
|
45
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
46
|
+
|
|
47
|
+
const page = await ctx.newPage();
|
|
48
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
49
|
+
await page.waitForSelector('[data-recent-row-content-tspan]', { timeout: 15000 });
|
|
50
|
+
await page.waitForTimeout(400);
|
|
51
|
+
|
|
52
|
+
const probe = await page.evaluate(() => {
|
|
53
|
+
const tspans = Array.from(document.querySelectorAll('[data-recent-row-content-tspan]'));
|
|
54
|
+
if (tspans.length === 0) return null;
|
|
55
|
+
const sample = tspans[0];
|
|
56
|
+
return {
|
|
57
|
+
count: tspans.length,
|
|
58
|
+
opacityAttr: sample.getAttribute('opacity'),
|
|
59
|
+
textContent: sample.textContent,
|
|
60
|
+
parentTag: sample.parentElement?.tagName,
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
await browser.close();
|
|
65
|
+
|
|
66
|
+
const results = {
|
|
67
|
+
// At least one content tspan mounted
|
|
68
|
+
tspan_mounted: (probe?.count || 0) >= 1,
|
|
69
|
+
// R418 wire: opacity 0.7
|
|
70
|
+
opacity_0_7: probe?.opacityAttr === '0.7',
|
|
71
|
+
// textContent is the truncated preview (R0 truncate appends '...' suffix when
|
|
72
|
+
// input exceeds the 8-char limit, so total can exceed 8 — assert non-empty
|
|
73
|
+
// and matches the seeded content prefix).
|
|
74
|
+
text_truncated: !!probe?.textContent && probe.textContent.startsWith('hi '),
|
|
75
|
+
// Parent is a <text> element (SVG context)
|
|
76
|
+
parent_text: probe?.parentTag === 'text',
|
|
77
|
+
};
|
|
78
|
+
const ok = Object.values(results).every(Boolean);
|
|
79
|
+
console.log(`${ok ? '✅' : '❌'} recent-row content preview tspan opacity=0.7:`, JSON.stringify(results),
|
|
80
|
+
'\n probe:', probe);
|
|
81
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/* Round 445 verification: recent-row count tspan fontWeight lift on
|
|
2
|
+
* isRowPinned. Extends R320 cold/hot fw binary (600/700) to also fire
|
|
3
|
+
* on pin. cold+pinned → 700; cold+un-pinned → 600.
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - rest: every recent-row-count reports font-weight '600' +
|
|
7
|
+
* pinned='false'
|
|
8
|
+
* - click a recent-row: that row's count flips to '700' +
|
|
9
|
+
* pinned='true'; siblings stay rest
|
|
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', 'idle'),
|
|
35
|
+
mk('gamma', 'idle'),
|
|
36
|
+
] } });
|
|
37
|
+
});
|
|
38
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({
|
|
39
|
+
json: { messages: [
|
|
40
|
+
// Use only 1 message each so neither row crosses the hot threshold (≥10)
|
|
41
|
+
{ id: 'm1', from_alias: 'alpha', to_alias: 'beta', content: 'ping', created_at: fresh, network_id: 'default' },
|
|
42
|
+
{ id: 'm2', from_alias: 'alpha', to_alias: 'gamma', content: 'pong', created_at: fresh, network_id: 'default' },
|
|
43
|
+
] },
|
|
44
|
+
}));
|
|
45
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
46
|
+
|
|
47
|
+
const page = await ctx.newPage();
|
|
48
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
49
|
+
await page.waitForSelector('[data-recent-row-count]', { timeout: 15000 });
|
|
50
|
+
await page.waitForTimeout(400);
|
|
51
|
+
|
|
52
|
+
const readAll = () => page.evaluate(() => {
|
|
53
|
+
const ts = [...document.querySelectorAll('[data-recent-row-count]')];
|
|
54
|
+
return ts.map(t => {
|
|
55
|
+
const row = t.closest('[data-recent-row]');
|
|
56
|
+
return {
|
|
57
|
+
rowKey: row?.getAttribute('data-recent-row') || null,
|
|
58
|
+
fw: t.getAttribute('font-weight'),
|
|
59
|
+
pinned: t.getAttribute('data-recent-row-count-pinned'),
|
|
60
|
+
hot: t.getAttribute('data-recent-row-count-hot'),
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const rest = await readAll();
|
|
66
|
+
const firstRow = rest[0]?.rowKey;
|
|
67
|
+
|
|
68
|
+
// Pin the first row via click on its <g data-recent-row>
|
|
69
|
+
let pinned = null;
|
|
70
|
+
if (firstRow) {
|
|
71
|
+
const row = await page.$(`[data-recent-row="${firstRow}"]`);
|
|
72
|
+
if (row) {
|
|
73
|
+
await row.click();
|
|
74
|
+
await page.waitForTimeout(250);
|
|
75
|
+
pinned = await readAll();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
80
|
+
const sourceWired = /fontWeight=\{\(isHot \|\| isRowPinned\) \? '700' : '600'\}/.test(fileText);
|
|
81
|
+
|
|
82
|
+
await browser.close();
|
|
83
|
+
|
|
84
|
+
const restAll600 = rest.every(r => r.fw === '600');
|
|
85
|
+
const restNoPin = rest.every(r => r.pinned === 'false');
|
|
86
|
+
const restNoHot = rest.every(r => !r.hot || r.hot !== 'true');
|
|
87
|
+
const pinnedEntry = pinned?.find(r => r.rowKey === firstRow);
|
|
88
|
+
const pinFw_700 = pinnedEntry?.fw === '700';
|
|
89
|
+
const pinFlag = pinnedEntry?.pinned === 'true';
|
|
90
|
+
const othersRest = pinned ? pinned.filter(r => r.rowKey !== firstRow).every(r => r.fw === '600' && r.pinned === 'false') : false;
|
|
91
|
+
|
|
92
|
+
const results = {
|
|
93
|
+
rest_count_ge_2: rest.length >= 2,
|
|
94
|
+
rest_all_fw_600: restAll600,
|
|
95
|
+
rest_no_pin: restNoPin,
|
|
96
|
+
rest_no_hot: restNoHot,
|
|
97
|
+
pinned_target_fw_700: pinFw_700,
|
|
98
|
+
pinned_target_flag: pinFlag,
|
|
99
|
+
pinned_others_stay: othersRest,
|
|
100
|
+
source_wired: sourceWired,
|
|
101
|
+
};
|
|
102
|
+
const ok = Object.values(results).every(Boolean);
|
|
103
|
+
console.log(`${ok ? '✅' : '❌'} recent-row count fw pin:`, JSON.stringify(results),
|
|
104
|
+
'\n rest:', JSON.stringify(rest),
|
|
105
|
+
'\n pinned target:', JSON.stringify(pinnedEntry));
|
|
106
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/* Round 434 verification: recent-signal row text 3-tier letter-spacing —
|
|
2
|
+
* rest 0 / hover 0.25 / pinned 0.5. Mirror of R433 legend-row pattern
|
|
3
|
+
* at recent-signal scope. Hover-letter-spacing family becomes 10 anchors.
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - need flow messages to populate recent rows — fixture seeds
|
|
7
|
+
* alpha↔beta + alpha↔gamma so ≥2 rows mount
|
|
8
|
+
* - rest: every recent-row-text reports letter-spacing '0px' +
|
|
9
|
+
* hovered='false' + pinned='false'
|
|
10
|
+
* - hover one data-recent-row wrapper: that row's text reports
|
|
11
|
+
* letter-spacing '0.25px' + hovered='true' (R434 mid tier)
|
|
12
|
+
* - siblings stay rest
|
|
13
|
+
* - source-file probe confirms 3-tier conditional
|
|
14
|
+
*/
|
|
15
|
+
import { chromium } from 'playwright';
|
|
16
|
+
import { readFileSync } from 'node:fs';
|
|
17
|
+
|
|
18
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
19
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
20
|
+
|
|
21
|
+
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
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
28
|
+
const r = await route.fetch();
|
|
29
|
+
const b = await r.json();
|
|
30
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
31
|
+
const mk = (alias, status) => ({
|
|
32
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
33
|
+
network_id: nid, project_dir: null,
|
|
34
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
35
|
+
});
|
|
36
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
37
|
+
mk('alpha', 'working'),
|
|
38
|
+
mk('beta', 'idle'),
|
|
39
|
+
mk('gamma', 'idle'),
|
|
40
|
+
] } });
|
|
41
|
+
});
|
|
42
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({
|
|
43
|
+
json: { messages: [
|
|
44
|
+
{ id: 'm1', from_alias: 'alpha', to_alias: 'beta', content: 'ping1', created_at: fresh, network_id: 'default' },
|
|
45
|
+
{ id: 'm2', from_alias: 'alpha', to_alias: 'gamma', content: 'ping2', created_at: fresh, network_id: 'default' },
|
|
46
|
+
] },
|
|
47
|
+
}));
|
|
48
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
49
|
+
|
|
50
|
+
const page = await ctx.newPage();
|
|
51
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
52
|
+
await page.waitForSelector('[data-recent-row-text]', { timeout: 15000 });
|
|
53
|
+
await page.waitForTimeout(400);
|
|
54
|
+
|
|
55
|
+
const readAll = () => page.evaluate(() => {
|
|
56
|
+
const ts = [...document.querySelectorAll('[data-recent-row-text]')];
|
|
57
|
+
return ts.map(t => ({
|
|
58
|
+
key: t.getAttribute('data-recent-row-text'),
|
|
59
|
+
ls: t.style.letterSpacing,
|
|
60
|
+
pinned: t.getAttribute('data-recent-row-text-pinned'),
|
|
61
|
+
hovered: t.getAttribute('data-recent-row-text-hovered'),
|
|
62
|
+
}));
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const rest = await readAll();
|
|
66
|
+
const firstKey = rest[0]?.key;
|
|
67
|
+
|
|
68
|
+
// Hover the data-recent-row <g> wrapper for the first row.
|
|
69
|
+
let hover = null;
|
|
70
|
+
if (firstKey) {
|
|
71
|
+
const box = await page.evaluate((key) => {
|
|
72
|
+
const g = document.querySelector(`[data-recent-row="${key}"]`);
|
|
73
|
+
if (!g) return null;
|
|
74
|
+
const b = g.getBoundingClientRect();
|
|
75
|
+
return { x: b.x + b.width / 2, y: b.y + b.height / 2 };
|
|
76
|
+
}, firstKey);
|
|
77
|
+
if (box) {
|
|
78
|
+
await page.mouse.move(box.x, box.y);
|
|
79
|
+
await page.waitForTimeout(300);
|
|
80
|
+
hover = await readAll();
|
|
81
|
+
await page.mouse.move(0, 0);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
86
|
+
const sourceWired = /letterSpacing:\s*isRowPinned\s*\?\s*'0\.5px'\s*:\s*\n?\s*isRowHovered\s*\?\s*'0\.25px'\s*:\s*'0px'/.test(fileText);
|
|
87
|
+
|
|
88
|
+
await browser.close();
|
|
89
|
+
|
|
90
|
+
const isRest = (ls) => ls === '0px' || ls === '' || ls === 'normal';
|
|
91
|
+
|
|
92
|
+
const hoveredEntry = hover?.find(r => r.key === firstKey);
|
|
93
|
+
const othersStayRest = hover ? hover.filter(r => r.key !== firstKey).every(r => isRest(r.ls) && r.hovered === 'false') : false;
|
|
94
|
+
|
|
95
|
+
const results = {
|
|
96
|
+
rest_count_gte_2: rest.length >= 2,
|
|
97
|
+
rest_all_zero: rest.every(r => isRest(r.ls)),
|
|
98
|
+
rest_all_pinned_false: rest.every(r => r.pinned === 'false'),
|
|
99
|
+
rest_all_hovered_false: rest.every(r => r.hovered === 'false'),
|
|
100
|
+
hover_target_ls_0_25: hoveredEntry?.ls === '0.25px',
|
|
101
|
+
hover_target_hovered_true: hoveredEntry?.hovered === 'true',
|
|
102
|
+
hover_others_stay_rest: othersStayRest,
|
|
103
|
+
source_three_tier_wired: sourceWired,
|
|
104
|
+
};
|
|
105
|
+
const ok = Object.values(results).every(Boolean);
|
|
106
|
+
console.log(`${ok ? '✅' : '❌'} recent-row 3-tier letter-spacing:`, JSON.stringify(results),
|
|
107
|
+
'\n rest count:', rest.length,
|
|
108
|
+
'\n hover target:', JSON.stringify(hoveredEntry));
|
|
109
|
+
process.exit(ok ? 0 : 1);
|