@sleep2agi/agent-network-dashboard 0.5.3-preview.1 → 0.5.3-preview.100
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 +32 -32
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +2 -2
- package/.next/server/app/_not-found.rsc +12 -12
- package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- 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 +14 -14
- package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
- package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
- package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +14 -14
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +7 -7
- 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 +14 -14
- package/.next/server/app/login.segments/_full.segment.rsc +14 -14
- package/.next/server/app/login.segments/_head.segment.rsc +4 -4
- package/.next/server/app/login.segments/_index.segment.rsc +7 -7
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/login.segments/login.segment.rsc +3 -3
- 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 +14 -14
- package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
- package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
- 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 +14 -14
- package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
- package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
- package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
- 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 +14 -14
- package/.next/server/app/node.segments/_full.segment.rsc +14 -14
- package/.next/server/app/node.segments/_head.segment.rsc +4 -4
- package/.next/server/app/node.segments/_index.segment.rsc +7 -7
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/node.segments/node.segment.rsc +3 -3
- 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 +14 -14
- package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
- package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
- 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 +14 -14
- package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
- package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
- 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 +14 -14
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
- 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 +14 -14
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +14 -14
- package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- 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 +14 -14
- package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
- package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +4 -4
- 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/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +2 -2
- package/.next/server/pages/500.html +1 -1
- package/.next/static/chunks/0-c2b_r~s.a00.js +1 -0
- package/.next/static/chunks/{0ce~u5hn~wege.js → 0nvxj45vzw-1t.js} +1 -1
- package/.next/static/chunks/{03a4--7ncekmk.js → 0v4-5tng.uh.7.js} +2 -2
- package/.next/static/chunks/0v9i~z.k.2uji.js +1 -0
- package/.next/static/chunks/0w3dd-f9bl6xs.js +4 -0
- package/.next/static/chunks/13~aih56vx-cf.css +2 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/ServersDrawer.tsx +16 -3
- package/app/components/TopoGraph.tsx +2747 -140
- package/app/globals.css +142 -6
- package/package.json +4 -4
- package/scripts/p157-servers-copy-test.mjs +95 -0
- package/scripts/topo-active-chrome-hover-text-test.mjs +107 -0
- package/scripts/topo-alias-glow-test.mjs +121 -0
- package/scripts/topo-avatar-brightness-test.mjs +116 -0
- package/scripts/topo-avatar-fallback-hover-test.mjs +104 -0
- package/scripts/topo-brand-logo-breath-test.mjs +102 -0
- package/scripts/topo-brand-logo-hover-brightness-test.mjs +105 -0
- package/scripts/topo-brand-logo-hover-rotate-test.mjs +93 -0
- package/scripts/topo-brand-logo-hover-test.mjs +85 -0
- package/scripts/topo-chip-row-digit-ls-test.mjs +135 -0
- package/scripts/topo-chip-row-member-alias-lit-test.mjs +154 -0
- package/scripts/topo-chip-row-press-test.mjs +93 -0
- package/scripts/topo-chip-row-tier-glow-brightness-test.mjs +99 -0
- package/scripts/topo-chip-row-unit-hover-tracking-test.mjs +124 -0
- package/scripts/topo-chrome-press-fullstrip-test.mjs +105 -0
- package/scripts/topo-chrome-press-scale-test.mjs +100 -0
- package/scripts/topo-cluster-count-attr-test.mjs +80 -0
- package/scripts/topo-crescent-breath-test.mjs +104 -0
- package/scripts/topo-crescent-recede-test.mjs +111 -0
- package/scripts/topo-edge-badge-hover-glow-test.mjs +90 -0
- package/scripts/topo-edge-badge-text-brightness-test.mjs +83 -0
- package/scripts/topo-edge-particle-brightness-test.mjs +82 -0
- package/scripts/topo-edge-pill-glow-test.mjs +67 -0
- package/scripts/topo-edge-visible-brightness-test.mjs +84 -0
- package/scripts/topo-endpoint-ring-brightness-test.mjs +83 -0
- package/scripts/topo-filter-pill-glow-test.mjs +90 -0
- package/scripts/topo-filter-pills-press-test.mjs +96 -0
- package/scripts/topo-fleet-density-tier-test.mjs +84 -0
- package/scripts/topo-flow-rail-brightness-test.mjs +80 -0
- package/scripts/topo-focus-outline-transition-test.mjs +107 -0
- package/scripts/topo-freshness-chip-fade-test.mjs +105 -0
- package/scripts/topo-fullscreen-attr-test.mjs +73 -0
- package/scripts/topo-fullscreen-icon-rotate-test.mjs +93 -0
- package/scripts/topo-grid-content-bottom-attr-test.mjs +72 -0
- package/scripts/topo-group-label-brightness-test.mjs +84 -0
- package/scripts/topo-group-label-hover-glow-test.mjs +86 -0
- package/scripts/topo-group-label-member-alias-hover-test.mjs +125 -0
- package/scripts/topo-group-pill-glow-test.mjs +76 -0
- package/scripts/topo-hover-ring-duration-test.mjs +87 -0
- package/scripts/topo-hub-digit-brightness-test.mjs +79 -0
- package/scripts/topo-hub-digit-ls-test.mjs +119 -0
- package/scripts/topo-hub-halo-brightness-test.mjs +80 -0
- package/scripts/topo-hub-halo-glow-test.mjs +96 -0
- package/scripts/topo-hub-highlight-amplify-test.mjs +139 -0
- package/scripts/topo-hub-highlight-brightness-test.mjs +84 -0
- package/scripts/topo-hub-highlight-fill-transition-test.mjs +84 -0
- package/scripts/topo-hub-highlight-glow-test.mjs +99 -0
- package/scripts/topo-hub-highlight-r-test.mjs +112 -0
- package/scripts/topo-hub-highlight-recede-test.mjs +144 -0
- package/scripts/topo-hub-highlight-theme-fill-test.mjs +83 -0
- package/scripts/topo-hub-hover-ring-brightness-test.mjs +79 -0
- package/scripts/topo-hub-hover-ring-glow-test.mjs +97 -0
- package/scripts/topo-hub-idle-breath-test.mjs +109 -0
- package/scripts/topo-hub-recede-test.mjs +124 -0
- package/scripts/topo-hub-spoke-brightness-test.mjs +77 -0
- package/scripts/topo-hub-spoke-glow-test.mjs +112 -0
- package/scripts/topo-layout-hover-fw-test.mjs +98 -0
- package/scripts/topo-legend-count-letter-spacing-test.mjs +108 -0
- package/scripts/topo-legend-label-fw-test.mjs +107 -0
- package/scripts/topo-legend-row-label-glow-test.mjs +102 -0
- package/scripts/topo-legend-swatch-glow-test.mjs +109 -0
- package/scripts/topo-legend-swatch-member-alias-match-test.mjs +139 -0
- package/scripts/topo-minimap-hover-glow-test.mjs +109 -0
- package/scripts/topo-node-alias-brightness-test.mjs +84 -0
- package/scripts/topo-node-sub-text-brightness-test.mjs +88 -0
- package/scripts/topo-nodesize-hover-fw-test.mjs +99 -0
- package/scripts/topo-orphan-box-dash-test.mjs +89 -0
- package/scripts/topo-orphan-fill-opacity-test.mjs +91 -0
- package/scripts/topo-orphan-label-italic-test.mjs +90 -0
- package/scripts/topo-orphan-label-opacity-test.mjs +98 -0
- package/scripts/topo-panel-count-hover-ls-test.mjs +87 -0
- package/scripts/topo-panel-row-brightness-test.mjs +116 -0
- package/scripts/topo-panel-title-brightness-test.mjs +98 -0
- package/scripts/topo-panel-title-glow-test.mjs +111 -0
- package/scripts/topo-pill-x-rotate-test.mjs +96 -0
- package/scripts/topo-pinned-aspect-test.mjs +89 -0
- package/scripts/topo-pressure-seg-glow-test.mjs +92 -0
- package/scripts/topo-pressure-seg-member-alias-match-test.mjs +133 -0
- package/scripts/topo-pressure-seg-motion-test.mjs +101 -0
- package/scripts/topo-recent-hot-pulse-test.mjs +102 -0
- package/scripts/topo-recent-more-fw-test.mjs +126 -0
- package/scripts/topo-recent-row-fw-test.mjs +115 -0
- package/scripts/topo-recent-row-text-glow-test.mjs +86 -0
- package/scripts/topo-reduced-motion-attr-test.mjs +69 -0
- package/scripts/topo-reset-icon-hover-scale-test.mjs +102 -0
- package/scripts/topo-runtime-badge-brightness-test.mjs +78 -0
- package/scripts/topo-runtime-badge-glow-test.mjs +108 -0
- package/scripts/topo-starfield-hue-test.mjs +109 -0
- package/scripts/topo-status-ring-brightness-test.mjs +84 -0
- package/scripts/topo-svg-focus-transition-test.mjs +105 -0
- package/scripts/topo-titleblock-h2-hover-fw-test.mjs +109 -0
- package/scripts/topo-titleblock-h2-hover-tracking-test.mjs +128 -0
- package/scripts/topo-titleblock-kicker-hover-test.mjs +134 -0
- package/scripts/topo-vendor-activelinks-press-test.mjs +100 -0
- package/scripts/topo-vendor-chip-glow-test.mjs +97 -0
- package/scripts/topo-vendor-pill-glow-test.mjs +98 -0
- package/scripts/topo-watermark-breath-test.mjs +100 -0
- package/scripts/topo-watermark-recede-test.mjs +114 -0
- package/scripts/topo-zoom-level-color-test.mjs +105 -0
- package/.next/static/chunks/0a4hmfvj-81x5.css +0 -2
- package/.next/static/chunks/14m8prv3qgm45.js +0 -4
- package/.next/static/chunks/17fq.aa.hsdd..js +0 -1
- package/.next/static/chunks/17~las5t-t.kj.js +0 -1
- /package/.next/static/{cBZM18sgaGtUo-xccD_a3 → oBpu6kOuBIOwABE5kiB8V}/_buildManifest.js +0 -0
- /package/.next/static/{cBZM18sgaGtUo-xccD_a3 → oBpu6kOuBIOwABE5kiB8V}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{cBZM18sgaGtUo-xccD_a3 → oBpu6kOuBIOwABE5kiB8V}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/* Round 492 verification: chrome-strip Ring/Grid buttons gain
|
|
2
|
+
* `active:scale-95` press feedback alongside R196's `active:bg-cyan-
|
|
3
|
+
* 500/25` color-deepen. Adds haptic-like compression on click,
|
|
4
|
+
* synced with bg/color via inline `transform 150ms ease-out`.
|
|
5
|
+
*
|
|
6
|
+
* Verifies (per Ring + Grid button):
|
|
7
|
+
* 1. button DOM element present
|
|
8
|
+
* 2. className contains 'active:scale-95' and 'transform-gpu'
|
|
9
|
+
* 3. inline style transition string includes 'transform 150ms ease-out'
|
|
10
|
+
* 4. baseline transform resolves to none/matrix-identity (not pressed)
|
|
11
|
+
* 5. source-file regex confirms both buttons wired
|
|
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: 1200 } });
|
|
21
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
22
|
+
await ctx.addInitScript(() => {
|
|
23
|
+
try {
|
|
24
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
25
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
26
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
27
|
+
} catch {}
|
|
28
|
+
});
|
|
29
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
30
|
+
const r = await route.fetch();
|
|
31
|
+
const b = await r.json();
|
|
32
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
33
|
+
const mk = (alias, status) => ({
|
|
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
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1', 'working')] } });
|
|
39
|
+
});
|
|
40
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
41
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
42
|
+
const page = await ctx.newPage();
|
|
43
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
44
|
+
await page.waitForSelector('[data-topo-chrome-layout="ring"]', { timeout: 15000 });
|
|
45
|
+
await page.waitForTimeout(800);
|
|
46
|
+
|
|
47
|
+
const probe = async (selector) => {
|
|
48
|
+
const el = await page.$(selector);
|
|
49
|
+
if (!el) return null;
|
|
50
|
+
const data = await page.evaluate((selector) => {
|
|
51
|
+
const el = document.querySelector(selector);
|
|
52
|
+
if (!el) return null;
|
|
53
|
+
const cs = window.getComputedStyle(el);
|
|
54
|
+
return {
|
|
55
|
+
className: el.className || '',
|
|
56
|
+
transition_property: cs.transitionProperty,
|
|
57
|
+
transition_duration: cs.transitionDuration,
|
|
58
|
+
transition_timing_func: cs.transitionTimingFunction,
|
|
59
|
+
transform_baseline: cs.transform,
|
|
60
|
+
};
|
|
61
|
+
}, selector);
|
|
62
|
+
return data;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const ringInfo = await probe('[data-topo-chrome-layout="ring"]');
|
|
66
|
+
const gridInfo = await probe('[data-topo-chrome-layout="grid"]');
|
|
67
|
+
|
|
68
|
+
await browser.close();
|
|
69
|
+
|
|
70
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
71
|
+
const sourceRingActive = /data-topo-chrome-layout="ring"[\s\S]{0,8000}active:scale-95 transform-gpu/.test(src);
|
|
72
|
+
const sourceGridActive = /data-topo-chrome-layout="grid"[\s\S]{0,8000}active:scale-95 transform-gpu/.test(src);
|
|
73
|
+
const sourceRingTransform = /background-color 150ms ease, color 150ms ease, letter-spacing 200ms ease-out, transform 150ms ease-out/.test(src);
|
|
74
|
+
const sourceGridTransform = /border-color 200ms ease-out, letter-spacing 200ms ease-out, transform 150ms ease-out/.test(src);
|
|
75
|
+
|
|
76
|
+
const hasActiveScale = (cls) => /active:scale-95/.test(cls) && /transform-gpu/.test(cls);
|
|
77
|
+
const hasTransformInTransition = (info) =>
|
|
78
|
+
info && /transform/i.test(info.transition_property || '') && /\b0\.15s\b/.test(info.transition_duration || '');
|
|
79
|
+
const isBaselineIdentity = (info) =>
|
|
80
|
+
info && (info.transform_baseline === 'none' || info.transform_baseline === 'matrix(1, 0, 0, 1, 0, 0)');
|
|
81
|
+
|
|
82
|
+
const results = {
|
|
83
|
+
ring_dom_found: !!ringInfo,
|
|
84
|
+
ring_class_active: ringInfo && hasActiveScale(ringInfo.className),
|
|
85
|
+
ring_transform_tr: hasTransformInTransition(ringInfo),
|
|
86
|
+
ring_baseline_id: isBaselineIdentity(ringInfo),
|
|
87
|
+
grid_dom_found: !!gridInfo,
|
|
88
|
+
grid_class_active: gridInfo && hasActiveScale(gridInfo.className),
|
|
89
|
+
grid_transform_tr: hasTransformInTransition(gridInfo),
|
|
90
|
+
grid_baseline_id: isBaselineIdentity(gridInfo),
|
|
91
|
+
source_ring_active: sourceRingActive,
|
|
92
|
+
source_grid_active: sourceGridActive,
|
|
93
|
+
source_ring_tr: sourceRingTransform,
|
|
94
|
+
source_grid_tr: sourceGridTransform,
|
|
95
|
+
};
|
|
96
|
+
const ok = Object.values(results).every(Boolean);
|
|
97
|
+
console.log(`${ok ? '✅' : '❌'} chrome-strip Ring/Grid active:scale-95 (R492):`, JSON.stringify(results),
|
|
98
|
+
'\n ring:', ringInfo && { tp: ringInfo.transition_property, td: ringInfo.transition_duration, tx: ringInfo.transform_baseline },
|
|
99
|
+
'\n grid:', gridInfo && { tp: gridInfo.transition_property, td: gridInfo.transition_duration, tx: gridInfo.transform_baseline });
|
|
100
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* Round 512 verification: root svg surfaces `data-topo-cluster-count`
|
|
2
|
+
* (14th attr in canvas state surface set). Paired with R469 fleet
|
|
3
|
+
* numerics + R502 categorical density.
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - grid layout: data-topo-cluster-count = groupBoxes.length (≥ 1)
|
|
7
|
+
* - ring layout: data-topo-cluster-count = '0' (groupBoxes is empty)
|
|
8
|
+
* - orphan-band fixture: cluster count includes the orphan band
|
|
9
|
+
*
|
|
10
|
+
* Tests across 2 fixtures × 2 layouts.
|
|
11
|
+
*/
|
|
12
|
+
import { chromium } from 'playwright';
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
|
|
15
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
16
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
17
|
+
|
|
18
|
+
async function probe({ layout, sessions, label }) {
|
|
19
|
+
const browser = await chromium.launch({ headless: true });
|
|
20
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
21
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
22
|
+
await ctx.addInitScript((l) => {
|
|
23
|
+
try {
|
|
24
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
25
|
+
localStorage.setItem('anet-topo-layout', l);
|
|
26
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
27
|
+
} catch {}
|
|
28
|
+
}, layout);
|
|
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) => ({
|
|
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
|
+
await route.fulfill({ response: r, json: { ...b, sessions: sessions.map(s => mk(s.alias, s.status)) } });
|
|
39
|
+
});
|
|
40
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
41
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
42
|
+
const page = await ctx.newPage();
|
|
43
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
44
|
+
await page.waitForSelector('svg[data-topo-cluster-count]', { timeout: 15000 });
|
|
45
|
+
await page.waitForTimeout(1500);
|
|
46
|
+
const count = await page.evaluate(() =>
|
|
47
|
+
document.querySelector('svg[viewBox="0 0 1000 680"]')?.getAttribute('data-topo-cluster-count')
|
|
48
|
+
);
|
|
49
|
+
await browser.close();
|
|
50
|
+
return { label, count };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Fixture A: 2 prefix groups (alpha×3 + beta×2) + 3 orphans
|
|
54
|
+
const fixtureA = [
|
|
55
|
+
{ alias: 'alpha·1', status: 'working' },
|
|
56
|
+
{ alias: 'alpha·2', status: 'idle' },
|
|
57
|
+
{ alias: 'alpha·3', status: 'idle' },
|
|
58
|
+
{ alias: 'beta·1', status: 'working' },
|
|
59
|
+
{ alias: 'beta·2', status: 'idle' },
|
|
60
|
+
{ alias: 'zeta', status: 'idle' },
|
|
61
|
+
{ alias: 'omega', status: 'idle' },
|
|
62
|
+
{ alias: 'lonely', status: 'idle' },
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
const aGrid = await probe({ layout: 'grid', sessions: fixtureA, label: 'grid+2prefix+3orph' });
|
|
66
|
+
const aRing = await probe({ layout: 'ring', sessions: fixtureA, label: 'ring+same fixture' });
|
|
67
|
+
|
|
68
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
69
|
+
const sourceWired = /data-topo-cluster-count=\{groupBoxes\.length\}/.test(src);
|
|
70
|
+
|
|
71
|
+
const results = {
|
|
72
|
+
grid_returns_3: aGrid.count === '3', // 2 prefix groups + 1 orphan band
|
|
73
|
+
ring_returns_0: aRing.count === '0', // no group boxes in ring layout
|
|
74
|
+
source_wired: sourceWired,
|
|
75
|
+
};
|
|
76
|
+
const ok = Object.values(results).every(Boolean);
|
|
77
|
+
console.log(`${ok ? '✅' : '❌'} R512 cluster-count attr:`, JSON.stringify(results),
|
|
78
|
+
'\n grid:', JSON.stringify(aGrid),
|
|
79
|
+
'\n ring:', JSON.stringify(aRing));
|
|
80
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/* Round 528 verification: brand crescent gains ambient SMIL breath
|
|
2
|
+
* (0.8↔1.0 fill-opacity, 7s, repeat indefinite). 呼吸感 family 4th
|
|
3
|
+
* anchor — symmetric to R519 watermark breath but at 7s vs 6s cadence
|
|
4
|
+
* so the two ambient anchors don't beat together visibly.
|
|
5
|
+
*
|
|
6
|
+
* Test phases:
|
|
7
|
+
* 1. motion enabled: data-topo-brand-canvas-mark-breath='true'
|
|
8
|
+
* + <animate> child mounted on inner <rect>
|
|
9
|
+
* + values='0.8;1;0.8', dur='7s', repeatCount='indefinite'
|
|
10
|
+
* + attributeName='fill-opacity' (NOT 'opacity')
|
|
11
|
+
* 2. reduced-motion: breath attr='false', NO <animate> child
|
|
12
|
+
* 3. wrapper recede + visibility still works (regression check)
|
|
13
|
+
* 4. source-side regex confirms wiring
|
|
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
|
+
async function probe(reducedMotion) {
|
|
22
|
+
const browser = await chromium.launch({ headless: true });
|
|
23
|
+
const ctx = await browser.newContext({
|
|
24
|
+
viewport: { width: 1500, height: 1200 },
|
|
25
|
+
reducedMotion: reducedMotion ? 'reduce' : 'no-preference',
|
|
26
|
+
});
|
|
27
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
28
|
+
await ctx.addInitScript(() => {
|
|
29
|
+
try {
|
|
30
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
31
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
32
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
33
|
+
} catch {}
|
|
34
|
+
});
|
|
35
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
36
|
+
const r = await route.fetch();
|
|
37
|
+
const b = await r.json();
|
|
38
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
39
|
+
const mk = (alias) => ({
|
|
40
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
41
|
+
network_id: nid, project_dir: null,
|
|
42
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
43
|
+
});
|
|
44
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
45
|
+
mk('alpha·1'), mk('alpha·2'),
|
|
46
|
+
] } });
|
|
47
|
+
});
|
|
48
|
+
// NO messages → flowLinks=0 → crescent visible
|
|
49
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
50
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
51
|
+
const page = await ctx.newPage();
|
|
52
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
53
|
+
await page.waitForSelector('[data-topo-brand-canvas-mark]', { timeout: 15000 });
|
|
54
|
+
await page.waitForTimeout(800);
|
|
55
|
+
const data = await page.evaluate(() => {
|
|
56
|
+
const wrap = document.querySelector('[data-topo-brand-canvas-mark]');
|
|
57
|
+
const rect = wrap?.querySelector('rect[mask*="canvas-corner-mask"]');
|
|
58
|
+
const animate = rect?.querySelector('animate');
|
|
59
|
+
return {
|
|
60
|
+
breathAttr: wrap?.getAttribute('data-topo-brand-canvas-mark-breath'),
|
|
61
|
+
visibleAttr: wrap?.getAttribute('data-topo-brand-canvas-mark-visible'),
|
|
62
|
+
hasAnimate: !!animate,
|
|
63
|
+
attrName: animate?.getAttribute('attributeName') || null,
|
|
64
|
+
values: animate?.getAttribute('values') || null,
|
|
65
|
+
dur: animate?.getAttribute('dur') || null,
|
|
66
|
+
repeatCount: animate?.getAttribute('repeatCount') || null,
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
await browser.close();
|
|
70
|
+
return data;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const normal = await probe(false);
|
|
74
|
+
const reduced = await probe(true);
|
|
75
|
+
|
|
76
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
77
|
+
const sourceAnimateGated =
|
|
78
|
+
/\{!reducedMotion && \(\s*<animate attributeName="fill-opacity" values="0\.8;1;0\.8" dur="7s" repeatCount="indefinite" \/>\s*\)\}/.test(src);
|
|
79
|
+
const sourceAttrWired =
|
|
80
|
+
/data-topo-brand-canvas-mark-breath=\{reducedMotion \? 'false' : 'true'\}/.test(src);
|
|
81
|
+
|
|
82
|
+
const results = {
|
|
83
|
+
// motion enabled
|
|
84
|
+
normal_breath_true: normal?.breathAttr === 'true',
|
|
85
|
+
normal_visible_true: normal?.visibleAttr === 'true',
|
|
86
|
+
normal_has_animate: normal?.hasAnimate === true,
|
|
87
|
+
normal_attr_fill_op: normal?.attrName === 'fill-opacity',
|
|
88
|
+
normal_values_correct: normal?.values === '0.8;1;0.8',
|
|
89
|
+
normal_dur_7s: normal?.dur === '7s',
|
|
90
|
+
normal_repeat_indef: normal?.repeatCount === 'indefinite',
|
|
91
|
+
// prefers-reduced-motion
|
|
92
|
+
reduced_breath_false: reduced?.breathAttr === 'false',
|
|
93
|
+
reduced_no_animate: reduced?.hasAnimate === false,
|
|
94
|
+
reduced_visible_true: reduced?.visibleAttr === 'true', // crescent still visible, just no breath
|
|
95
|
+
// source
|
|
96
|
+
source_animate_gated: sourceAnimateGated,
|
|
97
|
+
source_attr_wired: sourceAttrWired,
|
|
98
|
+
};
|
|
99
|
+
const ok = Object.values(results).every(Boolean);
|
|
100
|
+
console.log(`${ok ? '✅' : '❌'} R528 crescent ambient breath:`,
|
|
101
|
+
JSON.stringify(results, null, 2),
|
|
102
|
+
'\n normal:', JSON.stringify(normal),
|
|
103
|
+
'\n reduced:', JSON.stringify(reduced));
|
|
104
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/* Round 526 verification: brand crescent at canvas top-left gains
|
|
2
|
+
* focal-recede (4th anchor in family). Multiplies visible opacity by
|
|
3
|
+
* 0.7 when non-hub canvas surface is hovered.
|
|
4
|
+
*
|
|
5
|
+
* Test phases (flowLinks=0 state — crescent visible):
|
|
6
|
+
* 1. rest: opacity=0.35, recede attr='false', visible='true'
|
|
7
|
+
* 2. hover legend `idle` row: opacity=0.245 (0.35 × 0.7),
|
|
8
|
+
* recede attr='true'
|
|
9
|
+
* 3. mouseleave: opacity returns to 0.35, recede='false'
|
|
10
|
+
* 4. source-side regex confirms multiplicative opacity + attr wired
|
|
11
|
+
*/
|
|
12
|
+
import { chromium } from 'playwright';
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
|
|
15
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
16
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
17
|
+
|
|
18
|
+
const browser = await chromium.launch({ headless: true });
|
|
19
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
20
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
21
|
+
await ctx.addInitScript(() => {
|
|
22
|
+
try {
|
|
23
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
24
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
25
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
26
|
+
} 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: [
|
|
38
|
+
mk('alpha·1'), mk('alpha·2'), mk('alpha·3'),
|
|
39
|
+
] } });
|
|
40
|
+
});
|
|
41
|
+
// NO messages → flowLinks.length === 0 → crescent visible at opacity 0.35
|
|
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
|
+
const page = await ctx.newPage();
|
|
45
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
46
|
+
await page.waitForSelector('[data-topo-brand-canvas-mark]', { timeout: 15000 });
|
|
47
|
+
await page.waitForTimeout(800);
|
|
48
|
+
|
|
49
|
+
// Phase 1: rest
|
|
50
|
+
const rest = await page.evaluate(() => {
|
|
51
|
+
const m = document.querySelector('[data-topo-brand-canvas-mark]');
|
|
52
|
+
return {
|
|
53
|
+
opacity: parseFloat(m?.getAttribute('opacity') || '0'),
|
|
54
|
+
visible: m?.getAttribute('data-topo-brand-canvas-mark-visible'),
|
|
55
|
+
recede: m?.getAttribute('data-topo-brand-canvas-mark-recede'),
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Phase 2: hover legend `idle` row (sets hoveredStatus → recede)
|
|
60
|
+
await page.hover('[data-legend-row-label="idle"]');
|
|
61
|
+
await page.waitForTimeout(400);
|
|
62
|
+
const hover = await page.evaluate(() => {
|
|
63
|
+
const m = document.querySelector('[data-topo-brand-canvas-mark]');
|
|
64
|
+
return {
|
|
65
|
+
opacity: parseFloat(m?.getAttribute('opacity') || '0'),
|
|
66
|
+
visible: m?.getAttribute('data-topo-brand-canvas-mark-visible'),
|
|
67
|
+
recede: m?.getAttribute('data-topo-brand-canvas-mark-recede'),
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Phase 3: mouseleave
|
|
72
|
+
await page.mouse.move(900, 50);
|
|
73
|
+
await page.waitForTimeout(400);
|
|
74
|
+
const leave = await page.evaluate(() => {
|
|
75
|
+
const m = document.querySelector('[data-topo-brand-canvas-mark]');
|
|
76
|
+
return {
|
|
77
|
+
opacity: parseFloat(m?.getAttribute('opacity') || '0'),
|
|
78
|
+
recede: m?.getAttribute('data-topo-brand-canvas-mark-recede'),
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await browser.close();
|
|
83
|
+
|
|
84
|
+
// Source regex
|
|
85
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
86
|
+
const sourceOpacityWired =
|
|
87
|
+
/opacity=\{\(flowLinks\.length === 0 \? 0\.35 : 0\) \* \(\s*\(hoveredAlias \|\| hoveredEdgeKey \|\| hoveredGroupLabel \|\|\s*hoveredStatus \|\| hoveredVendor\) && !hoveredHub \? 0\.7 : 1\s*\)\}/.test(src);
|
|
88
|
+
const sourceAttrWired =
|
|
89
|
+
/data-topo-brand-canvas-mark-recede=\{\s*\(hoveredAlias \|\| hoveredEdgeKey \|\| hoveredGroupLabel \|\|\s*hoveredStatus \|\| hoveredVendor\) && !hoveredHub \? 'true' : 'false'\s*\}/.test(src);
|
|
90
|
+
|
|
91
|
+
const approxEq = (a, b, tol = 0.001) => Math.abs(a - b) < tol;
|
|
92
|
+
|
|
93
|
+
const results = {
|
|
94
|
+
rest_opacity_035: approxEq(rest?.opacity, 0.35),
|
|
95
|
+
rest_visible_true: rest?.visible === 'true',
|
|
96
|
+
rest_recede_false: rest?.recede === 'false',
|
|
97
|
+
hover_opacity_0245: approxEq(hover?.opacity, 0.245),
|
|
98
|
+
hover_recede_true: hover?.recede === 'true',
|
|
99
|
+
hover_visible_still: hover?.visible === 'true', // crescent should still be visible
|
|
100
|
+
leave_opacity_035: approxEq(leave?.opacity, 0.35),
|
|
101
|
+
leave_recede_false: leave?.recede === 'false',
|
|
102
|
+
source_opacity_wired: sourceOpacityWired,
|
|
103
|
+
source_attr_wired: sourceAttrWired,
|
|
104
|
+
};
|
|
105
|
+
const ok = Object.values(results).every(Boolean);
|
|
106
|
+
console.log(`${ok ? '✅' : '❌'} R526 crescent focal-recede:`,
|
|
107
|
+
JSON.stringify(results, null, 2),
|
|
108
|
+
'\n rest:', JSON.stringify(rest),
|
|
109
|
+
'\n hover:', JSON.stringify(hover),
|
|
110
|
+
'\n leave:', JSON.stringify(leave));
|
|
111
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/* Round 534 verification: edge midpoint badge gains drop-shadow glow on
|
|
2
|
+
* hover/pin (cyan accent), with hover precedence over isHot (amber R480).
|
|
3
|
+
*
|
|
4
|
+
* Test strategy: source-side wiring is canonical because edge hover via
|
|
5
|
+
* Playwright is impractical (topo-panel rect intercepts at SVG root;
|
|
6
|
+
* R48 hitbox is the React handler target but isn't directly hoverable
|
|
7
|
+
* through the panel). Rest-state DOM probe + source regex covers the
|
|
8
|
+
* 4-axis hover-lift parity wiring.
|
|
9
|
+
*
|
|
10
|
+
* Test phases:
|
|
11
|
+
* 1. rest cold: glow attr='false', filter='none', lifted attr='false'
|
|
12
|
+
* (regression check — pre-R534 behavior unchanged at rest)
|
|
13
|
+
* 2. source-side regex confirms:
|
|
14
|
+
* - filter ternary precedence: (hovered||pinned) > isHot > undefined
|
|
15
|
+
* - cyan accent hue (pal.legendAccent) at 99 hex alpha
|
|
16
|
+
* - data-edge-badge-glow 3-value attr ('hover' | 'hot' | 'false')
|
|
17
|
+
* - transition list includes filter
|
|
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: 1200 } });
|
|
27
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
28
|
+
await ctx.addInitScript(() => {
|
|
29
|
+
try {
|
|
30
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
31
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
32
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
33
|
+
} catch {}
|
|
34
|
+
});
|
|
35
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
36
|
+
const r = await route.fetch();
|
|
37
|
+
const b = await r.json();
|
|
38
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
39
|
+
const mk = (alias) => ({
|
|
40
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
41
|
+
network_id: nid, project_dir: null,
|
|
42
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
43
|
+
});
|
|
44
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
45
|
+
});
|
|
46
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: {
|
|
47
|
+
messages: [{ id: 'm1', from_alias: 'a·1', to_alias: 'a·2', content: 'test', created_at: fresh }]
|
|
48
|
+
} }));
|
|
49
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
50
|
+
const page = await ctx.newPage();
|
|
51
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
52
|
+
await page.waitForSelector('[data-edge-badge-glow]', { timeout: 15000 });
|
|
53
|
+
await page.waitForTimeout(800);
|
|
54
|
+
|
|
55
|
+
const rest = await page.evaluate(() => {
|
|
56
|
+
const el = document.querySelector('[data-edge-badge-glow]');
|
|
57
|
+
if (!el) return null;
|
|
58
|
+
const cs = getComputedStyle(el);
|
|
59
|
+
return {
|
|
60
|
+
glowAttr: el.getAttribute('data-edge-badge-glow'),
|
|
61
|
+
liftedAttr: el.getAttribute('data-edge-badge-lifted'),
|
|
62
|
+
filter: cs.filter,
|
|
63
|
+
transition: cs.transition,
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
await browser.close();
|
|
68
|
+
|
|
69
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
70
|
+
const sourceFilterTernary =
|
|
71
|
+
/filter: \(isHoveredEdge \|\| isPinned\)\s+\? `drop-shadow\(0 0 3px \$\{pal\.legendAccent\}99\)`\s+: isHot\s+\? `drop-shadow\(0 0 3px \$\{hotStroke\}80\)`\s+: undefined,/.test(src);
|
|
72
|
+
const sourceAttrTernary =
|
|
73
|
+
/data-edge-badge-glow=\{\(isHoveredEdge \|\| isPinned\) \? 'hover' : isHot \? 'hot' : 'false'\}/.test(src);
|
|
74
|
+
const sourceTransitionFilter =
|
|
75
|
+
/transition: 'r 180ms ease-out, stroke 300ms ease-out, stroke-width 300ms ease-out, fill 200ms ease-out, opacity 200ms ease-out, filter 200ms ease-out'/.test(src);
|
|
76
|
+
|
|
77
|
+
const results = {
|
|
78
|
+
rest_glow_false: rest?.glowAttr === 'false',
|
|
79
|
+
rest_lifted_false: rest?.liftedAttr === 'false',
|
|
80
|
+
rest_filter_none: rest?.filter === 'none' || rest?.filter === '',
|
|
81
|
+
rest_transition_has_filter: /\bfilter\b/.test(rest?.transition || ''),
|
|
82
|
+
source_filter_ternary: sourceFilterTernary,
|
|
83
|
+
source_attr_ternary: sourceAttrTernary,
|
|
84
|
+
source_transition_filter: sourceTransitionFilter,
|
|
85
|
+
};
|
|
86
|
+
const ok = Object.values(results).every(Boolean);
|
|
87
|
+
console.log(`${ok ? '✅' : '❌'} R534 edge-badge hover-glow (source-canonical):`,
|
|
88
|
+
JSON.stringify(results, null, 2),
|
|
89
|
+
'\n rest:', JSON.stringify(rest));
|
|
90
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/* Round 570 verification: edge-badge digit gains filter brightness
|
|
2
|
+
* (1.15) on (isHoveredEdge || isPinned || isHot). Joins per-element
|
|
3
|
+
* brightness family at 7th anchor.
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. mock 1 message → 1 flowLink with edge-badge rendered
|
|
7
|
+
* 2. rest: filter='none', brightness-attr='1'
|
|
8
|
+
* 3. transition-property contains 'filter'
|
|
9
|
+
* 4. source-side regex confirms wiring
|
|
10
|
+
*
|
|
11
|
+
* Live hover/pin on SVG edge-badge is unreliable for Playwright
|
|
12
|
+
* (R525 banked); use source-canonical for gate + rest data-attrs.
|
|
13
|
+
*/
|
|
14
|
+
import { chromium } from 'playwright';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
|
|
17
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
18
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
19
|
+
|
|
20
|
+
const browser = await chromium.launch({ headless: true });
|
|
21
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
22
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
23
|
+
await ctx.addInitScript(() => {
|
|
24
|
+
try {
|
|
25
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
26
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
27
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
28
|
+
} catch {}
|
|
29
|
+
});
|
|
30
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
31
|
+
const r = await route.fetch();
|
|
32
|
+
const b = await r.json();
|
|
33
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
34
|
+
const mk = (alias) => ({
|
|
35
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
36
|
+
network_id: nid, project_dir: null,
|
|
37
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
38
|
+
});
|
|
39
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1'), mk('a·2')] } });
|
|
40
|
+
});
|
|
41
|
+
// 1 message so flowLinks > 0 → edge-badge renders
|
|
42
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
43
|
+
{ from_alias: 'a·1', to_alias: 'a·2', content: 'hi', created_at: fresh },
|
|
44
|
+
] } }));
|
|
45
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
46
|
+
const page = await ctx.newPage();
|
|
47
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
48
|
+
await page.waitForSelector('[data-edge-badge-text]', { timeout: 15000 });
|
|
49
|
+
await page.waitForTimeout(500);
|
|
50
|
+
|
|
51
|
+
const rest = await page.evaluate(() => {
|
|
52
|
+
const el = document.querySelector('[data-edge-badge-text]');
|
|
53
|
+
if (!el) return null;
|
|
54
|
+
const cs = getComputedStyle(el);
|
|
55
|
+
return {
|
|
56
|
+
filter: cs.filter,
|
|
57
|
+
transitionProperty: cs.transitionProperty,
|
|
58
|
+
brightnessAttr: el.getAttribute('data-edge-badge-text-brightness'),
|
|
59
|
+
pinAttr: el.getAttribute('data-edge-badge-text-pin'),
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
await browser.close();
|
|
64
|
+
|
|
65
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
66
|
+
const sourceFilter = /filter: \(isHoveredEdge \|\| isPinned \|\| isHot\)\s*\?\s*'brightness\(1\.15\)'\s*:\s*undefined/.test(src);
|
|
67
|
+
const sourceAttr = /data-edge-badge-text-brightness=\{\(isHoveredEdge \|\| isPinned \|\| isHot\) \? '1\.15' : '1'\}/.test(src);
|
|
68
|
+
const sourceTransition = /transition: 'letter-spacing 300ms ease-out, font-weight 300ms ease-out, filter 300ms ease-out'/.test(src);
|
|
69
|
+
|
|
70
|
+
const results = {
|
|
71
|
+
rest_filter_none: rest?.filter === 'none',
|
|
72
|
+
rest_brightness_1: rest?.brightnessAttr === '1',
|
|
73
|
+
rest_pin_false: rest?.pinAttr === 'false',
|
|
74
|
+
transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
|
|
75
|
+
source_filter: sourceFilter,
|
|
76
|
+
source_attr: sourceAttr,
|
|
77
|
+
source_transition: sourceTransition,
|
|
78
|
+
};
|
|
79
|
+
const ok = Object.values(results).every(Boolean);
|
|
80
|
+
console.log(`${ok ? '✅' : '❌'} R570 edge-badge text brightness(1.15) (per-element family 7th anchor):`,
|
|
81
|
+
JSON.stringify(results, null, 2),
|
|
82
|
+
`\n rest: ${JSON.stringify(rest)}`);
|
|
83
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/* Round 583 verification: edge flow particle gains filter
|
|
2
|
+
* brightness(1.15) on edge hover/endpoint hover. 22nd anchor in
|
|
3
|
+
* per-element brightness family.
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. mock 1 message → 1 flowLink → particle renders (SMIL-animated)
|
|
7
|
+
* 2. rest: filter='none', brightness-attr='1'
|
|
8
|
+
* 3. transition-property contains 'filter'
|
|
9
|
+
* 4. source: filter conditional + data-attr + transition extension
|
|
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: 1200 } });
|
|
19
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
20
|
+
await ctx.addInitScript(() => {
|
|
21
|
+
try {
|
|
22
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
23
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
24
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
25
|
+
} 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) => ({
|
|
32
|
+
alias, status: 'idle', 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: [mk('a·1'), mk('a·2')] } });
|
|
37
|
+
});
|
|
38
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
39
|
+
{ from_alias: 'a·1', to_alias: 'a·2', content: 'hi', created_at: fresh },
|
|
40
|
+
] } }));
|
|
41
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
42
|
+
const page = await ctx.newPage();
|
|
43
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
44
|
+
await page.waitForSelector('[data-edge-particle]', { timeout: 15000, state: 'attached' });
|
|
45
|
+
await page.waitForTimeout(500);
|
|
46
|
+
|
|
47
|
+
const rest = await page.evaluate(() => {
|
|
48
|
+
const el = document.querySelector('[data-edge-particle]');
|
|
49
|
+
if (!el) return null;
|
|
50
|
+
const cs = getComputedStyle(el);
|
|
51
|
+
return {
|
|
52
|
+
filter: cs.filter,
|
|
53
|
+
transitionProperty: cs.transitionProperty,
|
|
54
|
+
brightnessAttr: el.getAttribute('data-edge-particle-brightness'),
|
|
55
|
+
liftedAttr: el.getAttribute('data-edge-particle-lifted'),
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await browser.close();
|
|
60
|
+
|
|
61
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
62
|
+
const sourceFilter = /filter: \(isHoveredEdge \|\| isEndpointHoveredEdge\)\s*\?\s*\(isLight \? 'brightness\(1\.15\)' : 'url\(#topo-glow\) brightness\(1\.15\)'\)\s*:\s*undefined/.test(src);
|
|
63
|
+
const sourceAttr = /data-edge-particle-brightness=\{\(isHoveredEdge \|\| isEndpointHoveredEdge\) \? '1\.15' : '1'\}/.test(src);
|
|
64
|
+
const sourceTransition = /transition: 'fill 200ms ease-out, opacity 200ms ease-out, r 200ms ease-out, filter 200ms ease-out'/.test(src);
|
|
65
|
+
|
|
66
|
+
const results = {
|
|
67
|
+
particle_present: !!rest,
|
|
68
|
+
// On cyber theme at rest, particle inherits url(#topo-glow) via attribute
|
|
69
|
+
rest_filter_has_url_or_none: /url\(/.test(rest?.filter || '') || rest?.filter === 'none',
|
|
70
|
+
rest_filter_no_brightness: !/brightness\(/.test(rest?.filter || ''),
|
|
71
|
+
rest_brightness_1: rest?.brightnessAttr === '1',
|
|
72
|
+
rest_lifted_false: rest?.liftedAttr === 'false',
|
|
73
|
+
transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
|
|
74
|
+
source_filter: sourceFilter,
|
|
75
|
+
source_attr: sourceAttr,
|
|
76
|
+
source_transition: sourceTransition,
|
|
77
|
+
};
|
|
78
|
+
const ok = Object.values(results).every(Boolean);
|
|
79
|
+
console.log(`${ok ? '✅' : '❌'} R583 edge flow particle brightness (22nd anchor):`,
|
|
80
|
+
JSON.stringify(results, null, 2),
|
|
81
|
+
`\n rest: ${JSON.stringify(rest)}`);
|
|
82
|
+
process.exit(ok ? 0 : 1);
|