@sleep2agi/agent-network-dashboard 0.5.3-preview.13 → 0.5.3-preview.131
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +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/05-~ezd16iskp.css +2 -0
- package/.next/static/chunks/0f2vrzslznn_e.js +1 -0
- package/.next/static/chunks/{11iqwh145jvo5.js → 0j0mqmu927775.js} +1 -1
- package/.next/static/chunks/0l2trp87vwy6a.js +1 -0
- package/.next/static/chunks/0r6phtc3s-m6f.js +4 -0
- package/.next/static/chunks/{03a4--7ncekmk.js → 0v4-5tng.uh.7.js} +2 -2
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/ServersDrawer.tsx +16 -3
- package/app/components/TopoGraph.tsx +3508 -148
- package/app/globals.css +58 -7
- 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-chat-brightness-test.mjs +79 -0
- package/scripts/topo-avatar-brightness-test.mjs +116 -0
- package/scripts/topo-avatar-drop-shadow-test.mjs +86 -0
- package/scripts/topo-avatar-fallback-hover-test.mjs +104 -0
- package/scripts/topo-avatar-fallback-rotate-test.mjs +92 -0
- package/scripts/topo-avatar-rotate-test.mjs +85 -0
- package/scripts/topo-avatar-scale-test.mjs +89 -0
- package/scripts/topo-brand-drop-shadow-test.mjs +71 -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-chat-ring-brightness-test.mjs +80 -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-tier-glow-brightness-test.mjs +99 -0
- package/scripts/topo-chip-row-unit-hover-tracking-test.mjs +124 -0
- package/scripts/topo-click-ripple-glow-test.mjs +86 -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-circle-brightness-test.mjs +82 -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-fleet-density-tier-test.mjs +84 -0
- package/scripts/topo-flow-arrow-brightness-test.mjs +82 -0
- package/scripts/topo-flow-rail-brightness-test.mjs +80 -0
- package/scripts/topo-freshness-chip-fade-test.mjs +105 -0
- package/scripts/topo-fullscreen-attr-test.mjs +73 -0
- package/scripts/topo-fullscreen-brightness-test.mjs +84 -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-box-brightness-test.mjs +84 -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-group-tint-brightness-test.mjs +82 -0
- package/scripts/topo-hub-core-brightness-test.mjs +82 -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 +7 -2
- 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-label-card-brightness-test.mjs +81 -0
- package/scripts/topo-layout-hover-fw-test.mjs +98 -0
- package/scripts/topo-layout-toggle-brightness-test.mjs +94 -0
- package/scripts/topo-legend-count-brightness-test.mjs +80 -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-pin-ring-brightness-test.mjs +82 -0
- package/scripts/topo-legend-row-count-brightness-test.mjs +85 -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-legend-tint-brightness-test.mjs +83 -0
- package/scripts/topo-minimap-hover-glow-test.mjs +109 -0
- package/scripts/topo-more-footer-brightness-test.mjs +94 -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-brightness-test.mjs +82 -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-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-pip-brightness-test.mjs +85 -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-count-brightness-test.mjs +84 -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-recent-tint-brightness-test.mjs +80 -0
- package/scripts/topo-recent-ts-brightness-test.mjs +86 -0
- package/scripts/topo-reduced-motion-attr-test.mjs +69 -0
- package/scripts/topo-reset-brightness-test.mjs +83 -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-runtime-badge-rotate-test.mjs +85 -0
- package/scripts/topo-starfield-hue-test.mjs +109 -0
- package/scripts/topo-status-ring-brightness-test.mjs +84 -0
- package/scripts/topo-sub-text-chat-brightness-test.mjs +81 -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-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-buttons-brightness-test.mjs +94 -0
- package/scripts/topo-zoom-level-brightness-test.mjs +83 -0
- package/scripts/topo-zoom-level-color-test.mjs +105 -0
- package/.next/static/chunks/0-eqn.ga3bcnl.js +0 -1
- package/.next/static/chunks/0m.1mvl~t.avc.css +0 -2
- package/.next/static/chunks/0tl3h11hxa7oe.js +0 -4
- package/.next/static/chunks/0zwxl-vr5q45i.js +0 -1
- /package/.next/static/{U6pY8Ja-T2ME4lRhun26w → skBswyT45Rn83Ku6lBH0M}/_buildManifest.js +0 -0
- /package/.next/static/{U6pY8Ja-T2ME4lRhun26w → skBswyT45Rn83Ku6lBH0M}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{U6pY8Ja-T2ME4lRhun26w → skBswyT45Rn83Ku6lBH0M}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/* Round 560 verification: chip-row chip UNIT spans + filter-pill
|
|
2
|
+
* prefix/count + vendor-letter count suffix gain group-hover:
|
|
3
|
+
* tracking-wide. Coordinated 7-occurrence replace_all swap
|
|
4
|
+
* extends the hover-letter-spacing family across the small
|
|
5
|
+
* data-label-spans-with-opacity-70 cohort.
|
|
6
|
+
*
|
|
7
|
+
* Test phases:
|
|
8
|
+
* 1. rest: letter-spacing ≈ 'normal' (0px) on working-chip-unit
|
|
9
|
+
* 2. hover the chip wrapper (group) → unit letter-spacing lifts
|
|
10
|
+
* to ≈ 0.025em ≈ 0.3px on a 12px font
|
|
11
|
+
* 3. transition-property contains BOTH 'opacity' and
|
|
12
|
+
* 'letter-spacing'
|
|
13
|
+
* 4. source-side regex confirms the new className substring
|
|
14
|
+
* appears 7 times (replace_all touched all sites)
|
|
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: 1200 } });
|
|
24
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
25
|
+
await ctx.addInitScript(() => {
|
|
26
|
+
try {
|
|
27
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
28
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
29
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
30
|
+
} catch {}
|
|
31
|
+
});
|
|
32
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
33
|
+
const r = await route.fetch();
|
|
34
|
+
const b = await r.json();
|
|
35
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
36
|
+
const mk = (alias, status = 'working') => ({
|
|
37
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
38
|
+
network_id: nid, project_dir: null,
|
|
39
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
40
|
+
});
|
|
41
|
+
// Working sessions so the working chip is clickable / hoverable.
|
|
42
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
43
|
+
mk('a·1', 'working'), mk('a·2', 'working'), mk('a·3', 'idle'),
|
|
44
|
+
] } });
|
|
45
|
+
});
|
|
46
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
47
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
48
|
+
const page = await ctx.newPage();
|
|
49
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
50
|
+
await page.waitForSelector('[data-working-chip-unit]', { timeout: 15000 });
|
|
51
|
+
await page.waitForTimeout(500);
|
|
52
|
+
|
|
53
|
+
const unitSel = '[data-working-chip-unit]';
|
|
54
|
+
// Hover the parent chip (the <span> wrapping digit+unit) — group-hover.
|
|
55
|
+
// Walk up until we find the role='button' chip wrapper.
|
|
56
|
+
const chipWrapperHandle = await page.evaluateHandle((s) => {
|
|
57
|
+
let el = document.querySelector(s);
|
|
58
|
+
while (el && el.parentElement) {
|
|
59
|
+
el = el.parentElement;
|
|
60
|
+
if (el.getAttribute('role') === 'button' || el.getAttribute('aria-pressed') !== null) {
|
|
61
|
+
return el;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return el;
|
|
65
|
+
}, unitSel);
|
|
66
|
+
|
|
67
|
+
const parsePx = (s) => parseFloat((s || '').replace(/px$/, ''));
|
|
68
|
+
|
|
69
|
+
const rest = await page.evaluate((s) => {
|
|
70
|
+
const el = document.querySelector(s);
|
|
71
|
+
if (!el) return null;
|
|
72
|
+
const cs = getComputedStyle(el);
|
|
73
|
+
return {
|
|
74
|
+
letterSpacing: cs.letterSpacing,
|
|
75
|
+
transitionProperty: cs.transitionProperty,
|
|
76
|
+
transitionDuration: cs.transitionDuration,
|
|
77
|
+
fontSize: cs.fontSize,
|
|
78
|
+
opacity: cs.opacity,
|
|
79
|
+
};
|
|
80
|
+
}, unitSel);
|
|
81
|
+
|
|
82
|
+
// Hover the chip wrapper
|
|
83
|
+
await chipWrapperHandle.hover();
|
|
84
|
+
await page.waitForTimeout(400);
|
|
85
|
+
const hover = await page.evaluate((s) => {
|
|
86
|
+
const el = document.querySelector(s);
|
|
87
|
+
if (!el) return null;
|
|
88
|
+
const cs = getComputedStyle(el);
|
|
89
|
+
return {
|
|
90
|
+
letterSpacing: cs.letterSpacing,
|
|
91
|
+
opacity: cs.opacity,
|
|
92
|
+
};
|
|
93
|
+
}, unitSel);
|
|
94
|
+
|
|
95
|
+
await browser.close();
|
|
96
|
+
|
|
97
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
98
|
+
// Count occurrences of the new className
|
|
99
|
+
const occurrences = (src.match(/opacity-70 transition-\[opacity,letter-spacing\] duration-200 group-hover:opacity-100 group-hover:tracking-wide/g) || []).length;
|
|
100
|
+
|
|
101
|
+
// At text-xs (12px in chip-row context), tracking-wide = 0.025em = 0.3px
|
|
102
|
+
// At rest, letter-spacing = 'normal' which most browsers report as '0px'
|
|
103
|
+
// or 'normal'.
|
|
104
|
+
const restPx = parsePx(rest?.letterSpacing) || 0;
|
|
105
|
+
const hoverPx = parsePx(hover?.letterSpacing);
|
|
106
|
+
|
|
107
|
+
const results = {
|
|
108
|
+
rest_letter_spacing_zero: rest?.letterSpacing === 'normal' || Math.abs(restPx) < 0.01,
|
|
109
|
+
hover_letter_spacing_wide: Math.abs(hoverPx - 0.3) < 0.1, // tracking-wide @ 12px ≈ 0.3px
|
|
110
|
+
hover_ls_greater_than_rest: hoverPx > restPx + 0.1,
|
|
111
|
+
rest_opacity_0_7: Math.abs(parseFloat(rest?.opacity || '0') - 0.7) < 0.01,
|
|
112
|
+
hover_opacity_1: Math.abs(parseFloat(hover?.opacity || '0') - 1.0) < 0.01,
|
|
113
|
+
transition_has_opacity: /opacity/.test(rest?.transitionProperty || ''),
|
|
114
|
+
transition_has_ls: /letter-spacing/.test(rest?.transitionProperty || ''),
|
|
115
|
+
transition_duration: rest?.transitionDuration === '0.2s' || /^0\.2s/.test(rest?.transitionDuration || ''),
|
|
116
|
+
source_7_occurrences: occurrences === 7,
|
|
117
|
+
};
|
|
118
|
+
const ok = Object.values(results).every(Boolean);
|
|
119
|
+
console.log(`${ok ? '✅' : '❌'} R560 chip-row unit + filter-pill spans hover-tracking (7 anchors via replace_all):`,
|
|
120
|
+
JSON.stringify(results, null, 2),
|
|
121
|
+
`\n rest: ${JSON.stringify(rest)}`,
|
|
122
|
+
`\n hover: ${JSON.stringify(hover)}`,
|
|
123
|
+
`\n source replace_all occurrences: ${occurrences}`);
|
|
124
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* Round 608 — click-ripple gains drop-shadow glow that matches
|
|
2
|
+
* the ripple's stroke color. Expanding feedback ring now reads
|
|
3
|
+
* as a "lit pulse" rather than a plain stroke line.
|
|
4
|
+
*
|
|
5
|
+
* Test phases:
|
|
6
|
+
* 1. mock 2 idle nodes → click first node → ripple renders
|
|
7
|
+
* 2. ripple element present with data-click-ripple attr
|
|
8
|
+
* 3. computed filter contains 'drop-shadow'
|
|
9
|
+
* 4. data-click-ripple-glow attr present with valid format
|
|
10
|
+
* 5. source: filter inline + data-attr extension
|
|
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: [mk('a·1'), mk('a·2')] } });
|
|
38
|
+
});
|
|
39
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
40
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
41
|
+
const page = await ctx.newPage();
|
|
42
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
43
|
+
// Click hub group (role=button aria-label="Network hub...") to fire setClickRipple
|
|
44
|
+
await page.waitForSelector('[data-topo-hub-fade-delay]', { timeout: 15000, state: 'attached' });
|
|
45
|
+
const hubBox = await page.evaluate(() => {
|
|
46
|
+
const el = document.querySelector('[data-topo-hub-fade-delay]');
|
|
47
|
+
if (!el) return null;
|
|
48
|
+
const r = el.getBoundingClientRect();
|
|
49
|
+
return { x: r.left + r.width / 2, y: r.top + r.height / 2 };
|
|
50
|
+
});
|
|
51
|
+
if (!hubBox) throw new Error('hub not found');
|
|
52
|
+
await page.mouse.click(hubBox.x, hubBox.y);
|
|
53
|
+
// Wait briefly so the ripple mounts but doesn't fully fade
|
|
54
|
+
await page.waitForSelector('[data-click-ripple]', { timeout: 5000, state: 'attached' });
|
|
55
|
+
await page.waitForTimeout(100);
|
|
56
|
+
|
|
57
|
+
const rippleState = await page.evaluate(() => {
|
|
58
|
+
const el = document.querySelector('[data-click-ripple]');
|
|
59
|
+
if (!el) return null;
|
|
60
|
+
const cs = getComputedStyle(el);
|
|
61
|
+
return {
|
|
62
|
+
filter: cs.filter,
|
|
63
|
+
glowAttr: el.getAttribute('data-click-ripple-glow'),
|
|
64
|
+
stroke: el.getAttribute('stroke'),
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await browser.close();
|
|
69
|
+
|
|
70
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
71
|
+
const sourceFilter = /filter: `drop-shadow\(0 0 4px \$\{clickRipple\.color\}99\)`/.test(src);
|
|
72
|
+
const sourceAttr = /data-click-ripple-glow=\{`0 0 4px \$\{clickRipple\.color\}99`\}/.test(src);
|
|
73
|
+
|
|
74
|
+
const results = {
|
|
75
|
+
ripple_present: !!rippleState,
|
|
76
|
+
has_drop_shadow: /drop-shadow/.test(rippleState?.filter || ''),
|
|
77
|
+
glow_attr_format: /^0 0 4px /.test(rippleState?.glowAttr || ''),
|
|
78
|
+
has_stroke: !!rippleState?.stroke,
|
|
79
|
+
source_filter: sourceFilter,
|
|
80
|
+
source_attr: sourceAttr,
|
|
81
|
+
};
|
|
82
|
+
const ok = Object.values(results).every(Boolean);
|
|
83
|
+
console.log(`${ok ? '✅' : '❌'} R608 click-ripple drop-shadow glow (click feedback enhancement):`,
|
|
84
|
+
JSON.stringify(results, null, 2),
|
|
85
|
+
`\n ripple: ${JSON.stringify(rippleState)}`);
|
|
86
|
+
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,82 @@
|
|
|
1
|
+
/* Round 603 — edge-badge CIRCLE stacks brightness(1.15) onto
|
|
2
|
+
* R534/R480 drop-shadow on hover/pin/hot. 5th hover axis on
|
|
3
|
+
* the badge ring; brings circle brightness to parity with the
|
|
4
|
+
* R570 digit brightness within the same edge-badge unit.
|
|
5
|
+
*
|
|
6
|
+
* Test phases:
|
|
7
|
+
* 1. mock 1 message → 1 flowLink → edge-badge renders
|
|
8
|
+
* 2. rest: filter='none', brightness-attr='1'
|
|
9
|
+
* 3. computed transition-property contains 'filter'
|
|
10
|
+
* 4. source: stacked filter conditional includes brightness +
|
|
11
|
+
* data-attr extension
|
|
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) => ({
|
|
34
|
+
alias, status: 'idle', 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'), mk('a·2')] } });
|
|
39
|
+
});
|
|
40
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
41
|
+
{ from_alias: 'a·1', to_alias: 'a·2', content: 'hi', created_at: fresh },
|
|
42
|
+
] } }));
|
|
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-edge-badge-brightness]', { timeout: 15000, state: 'attached' });
|
|
47
|
+
await page.waitForTimeout(500);
|
|
48
|
+
|
|
49
|
+
const rest = await page.evaluate(() => {
|
|
50
|
+
const el = document.querySelector('[data-edge-badge-brightness]');
|
|
51
|
+
if (!el) return null;
|
|
52
|
+
const cs = getComputedStyle(el);
|
|
53
|
+
return {
|
|
54
|
+
filter: cs.filter,
|
|
55
|
+
transitionProperty: cs.transitionProperty,
|
|
56
|
+
brightnessAttr: el.getAttribute('data-edge-badge-brightness'),
|
|
57
|
+
glowAttr: el.getAttribute('data-edge-badge-glow'),
|
|
58
|
+
liftedAttr: el.getAttribute('data-edge-badge-lifted'),
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
await browser.close();
|
|
63
|
+
|
|
64
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
65
|
+
const sourceFilter = /filter: \(isHoveredEdge \|\| isPinned\)\s*\?\s*`drop-shadow\(0 0 3px \$\{pal\.legendAccent\}99\) brightness\(1\.15\)`\s*:\s*isHot\s*\?\s*`drop-shadow\(0 0 3px \$\{hotStroke\}80\) brightness\(1\.15\)`\s*:\s*undefined/.test(src);
|
|
66
|
+
const sourceAttr = /data-edge-badge-brightness=\{\(isHoveredEdge \|\| isPinned \|\| isHot\) \? '1\.15' : '1'\}/.test(src);
|
|
67
|
+
|
|
68
|
+
const results = {
|
|
69
|
+
badge_present: !!rest,
|
|
70
|
+
rest_filter_none: rest?.filter === 'none',
|
|
71
|
+
rest_brightness_1: rest?.brightnessAttr === '1',
|
|
72
|
+
rest_glow_false: rest?.glowAttr === 'false',
|
|
73
|
+
rest_lifted_false: rest?.liftedAttr === 'false',
|
|
74
|
+
transition_has_filter: /filter/.test(rest?.transitionProperty || ''),
|
|
75
|
+
source_filter: sourceFilter,
|
|
76
|
+
source_attr: sourceAttr,
|
|
77
|
+
};
|
|
78
|
+
const ok = Object.values(results).every(Boolean);
|
|
79
|
+
console.log(`${ok ? '✅' : '❌'} R603 edge-badge circle brightness (5th axis, ring↔digit parity):`,
|
|
80
|
+
JSON.stringify(results, null, 2),
|
|
81
|
+
`\n rest: ${JSON.stringify(rest)}`);
|
|
82
|
+
process.exit(ok ? 0 : 1);
|