@sleep2agi/agent-network-dashboard 0.5.1-preview.8 → 0.5.1-preview.80
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 +6 -6
- 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 +2 -2
- package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/server/app/admin.html +2 -2
- package/.next/server/app/admin.rsc +2 -2
- package/.next/server/app/admin.segments/_full.segment.rsc +2 -2
- package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_index.segment.rsc +2 -2
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/admin.segments/admin.segment.rsc +1 -1
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +3 -3
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +2 -2
- package/.next/server/app/login.rsc +3 -3
- package/.next/server/app/login.segments/_full.segment.rsc +3 -3
- package/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/server/app/login.segments/_index.segment.rsc +2 -2
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +2 -2
- package/.next/server/app/logs.rsc +2 -2
- package/.next/server/app/logs.segments/_full.segment.rsc +2 -2
- package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_index.segment.rsc +2 -2
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
- package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +2 -2
- package/.next/server/app/messages.rsc +2 -2
- package/.next/server/app/messages.segments/_full.segment.rsc +2 -2
- package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_index.segment.rsc +2 -2
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/messages.segments/messages.segment.rsc +1 -1
- package/.next/server/app/node/page_client-reference-manifest.js +1 -1
- package/.next/server/app/node.html +2 -2
- package/.next/server/app/node.rsc +2 -2
- package/.next/server/app/node.segments/_full.segment.rsc +2 -2
- package/.next/server/app/node.segments/_head.segment.rsc +1 -1
- package/.next/server/app/node.segments/_index.segment.rsc +2 -2
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/node.segments/node.segment.rsc +1 -1
- package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/nodes.html +2 -2
- package/.next/server/app/nodes.rsc +2 -2
- package/.next/server/app/nodes.segments/_full.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_index.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/nodes.segment.rsc +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +2 -2
- package/.next/server/app/server-logs.rsc +2 -2
- package/.next/server/app/server-logs.segments/_full.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_index.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +1 -1
- package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/networks.html +2 -2
- package/.next/server/app/settings/networks.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +2 -2
- package/.next/server/app/settings/tokens.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +1 -1
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +3 -3
- package/.next/server/app/settings.segments/_full.segment.rsc +3 -3
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks.html +2 -2
- package/.next/server/app/tasks.rsc +2 -2
- package/.next/server/app/tasks.segments/_full.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_index.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/tasks.segment.rsc +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +3 -3
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +2 -2
- package/.next/server/pages/500.html +1 -1
- package/.next/static/chunks/0.qqb9jjqlh...js +1 -0
- package/.next/static/chunks/017hq2-5l~_98.css +2 -0
- package/.next/static/chunks/03kbe~9.kta82.js +1 -0
- package/.next/static/chunks/14p~tt-bh1ooi.js +4 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +1562 -88
- package/package.json +1 -1
- package/scripts/topo-active-links-chip-hover-lift-test.mjs +93 -0
- package/scripts/topo-chip-digit-fontweight-test.mjs +105 -0
- package/scripts/topo-chip-digit-hover-bold-test.mjs +94 -0
- package/scripts/topo-chip-row-group-hover-brighten-test.mjs +107 -0
- package/scripts/topo-chip-row-hover-lift-test.mjs +95 -0
- package/scripts/topo-chrome-button-hover-lift-test.mjs +94 -0
- package/scripts/topo-chrome-segmented-radius-test.mjs +100 -0
- package/scripts/topo-click-ripple-opacity-test.mjs +99 -0
- package/scripts/topo-edge-badge-fontsize-test.mjs +90 -0
- package/scripts/topo-edge-badge-hover-opacity-test.mjs +94 -0
- package/scripts/topo-edge-badge-hover-stroke-test.mjs +92 -0
- package/scripts/topo-edge-badge-opacity-test.mjs +80 -0
- package/scripts/topo-edge-badge-pin-opacity-test.mjs +86 -0
- package/scripts/topo-edge-badge-stroke-test.mjs +92 -0
- package/scripts/topo-edge-freshness-floor-test.mjs +99 -0
- package/scripts/topo-edge-visible-linecap-test.mjs +89 -0
- package/scripts/topo-filter-pill-hover-lift-test.mjs +101 -0
- package/scripts/topo-filter-pill-hover-opacity-test.mjs +110 -0
- package/scripts/topo-filter-pill-value-fw-test.mjs +88 -0
- package/scripts/topo-filter-pill-x-hover-scale-test.mjs +99 -0
- package/scripts/topo-flow-rail-linecap-test.mjs +79 -0
- package/scripts/topo-freshness-chip-hierarchy-test.mjs +93 -0
- package/scripts/topo-freshness-chip-tabular-test.mjs +41 -0
- package/scripts/topo-freshness-floor-lift-test.mjs +92 -0
- package/scripts/topo-freshness-suffix-tabular-test.mjs +88 -0
- package/scripts/topo-fullscreen-icon-hover-scale-test.mjs +91 -0
- package/scripts/topo-group-box-stroke-test.mjs +105 -0
- package/scripts/topo-group-label-count-fontweight-test.mjs +108 -0
- package/scripts/topo-hover-detail-body-fw-test.mjs +101 -0
- package/scripts/topo-hover-detail-model-fw-test.mjs +98 -0
- package/scripts/topo-hover-detail-opacity-test.mjs +98 -0
- package/scripts/topo-hover-detail-rx-test.mjs +81 -0
- package/scripts/topo-hub-digit-fontsize-test.mjs +86 -0
- package/scripts/topo-hub-halo-light-trough-test.mjs +88 -0
- package/scripts/topo-hub-halo-radius-test.mjs +86 -0
- package/scripts/topo-hub-halo-trough-test.mjs +83 -0
- package/scripts/topo-hub-highlight-opacity-test.mjs +88 -0
- package/scripts/topo-hub-highlight-radius-test.mjs +90 -0
- package/scripts/topo-hub-hover-ring-opacity-test.mjs +96 -0
- package/scripts/topo-hub-hover-ring-stroke-test.mjs +86 -0
- package/scripts/topo-hub-spoke-linecap-test.mjs +80 -0
- package/scripts/topo-layout-toggle-hover-tracking-test.mjs +109 -0
- package/scripts/topo-layout-toggle-radius-test.mjs +87 -0
- package/scripts/topo-legend-label-fontweight-test.mjs +94 -0
- package/scripts/topo-legend-pin-ring-stroke-test.mjs +101 -0
- package/scripts/topo-minimap-offline-opacity-test.mjs +90 -0
- package/scripts/topo-minimap-online-opacity-test.mjs +93 -0
- package/scripts/topo-minimap-online-radius-test.mjs +85 -0
- package/scripts/topo-minimap-viewport-linejoin-test.mjs +75 -0
- package/scripts/topo-minimap-viewport-rx-test.mjs +85 -0
- package/scripts/topo-more-flows-fontweight-test.mjs +103 -0
- package/scripts/topo-node-halo-offline-opacity-test.mjs +87 -0
- package/scripts/topo-node-label-card-rx-test.mjs +85 -0
- package/scripts/topo-node-pulse-peak-test.mjs +89 -0
- package/scripts/topo-node-pulse-trough-test.mjs +91 -0
- package/scripts/topo-panel-count-letterspacing-test.mjs +89 -0
- package/scripts/topo-panel-rect-opacity-hover-test.mjs +109 -0
- package/scripts/topo-pressure-bar-height-test.mjs +92 -0
- package/scripts/topo-pressure-kicker-fontweight-test.mjs +76 -0
- package/scripts/topo-recent-pip-radius-2-test.mjs +72 -0
- package/scripts/topo-recent-pip-radius-test.mjs +76 -0
- package/scripts/topo-recent-row-content-opacity-test.mjs +81 -0
- package/scripts/topo-recent-row-text-fontweight-test.mjs +90 -0
- package/scripts/topo-reset-hover-rotate-test.mjs +102 -0
- package/scripts/topo-spoke-active-opacity-test.mjs +104 -0
- package/scripts/topo-spoke-active-stroke-test.mjs +95 -0
- package/scripts/topo-spoke-idle-opacity-test.mjs +91 -0
- package/scripts/topo-vendor-chip-hover-lift-test.mjs +87 -0
- package/scripts/topo-vendor-glyph-fontweight-test.mjs +102 -0
- package/scripts/topo-vendor-letter-hover-scale-test.mjs +129 -0
- package/scripts/topo-vendor-suffix-hover-brighten-test.mjs +87 -0
- package/scripts/topo-zoom-icon-hover-scale-test.mjs +114 -0
- package/.next/static/chunks/06132.qvlxn22.js +0 -4
- package/.next/static/chunks/0aauz~36q5n2a.css +0 -2
- package/.next/static/chunks/0vkj-grzc4zxy.js +0 -1
- package/.next/static/chunks/0x0kput204icg.js +0 -1
- /package/.next/static/{m-5OV2JFjgsIdYk1S2Lvx → PTRxTZopSjU0AslWqFq4c}/_buildManifest.js +0 -0
- /package/.next/static/{m-5OV2JFjgsIdYk1S2Lvx → PTRxTZopSjU0AslWqFq4c}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{m-5OV2JFjgsIdYk1S2Lvx → PTRxTZopSjU0AslWqFq4c}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/* Round 409 verification: active-node pulse SMIL peak opacity lift
|
|
2
|
+
* — cyber 0.18 → 0.20 / light 0.12 → 0.14. Active-state breath
|
|
3
|
+
* widens slightly at peak (+0.02 both themes) while trough stays.
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - Seed a flow link so a node becomes "active" (R243 isActive gate)
|
|
7
|
+
* - The active node's <g data-node-pulse> child has an <animate>
|
|
8
|
+
* opacity element with:
|
|
9
|
+
* * cyber: values='0.20;0.04;0.20' + data-node-pulse-peak='0.20'
|
|
10
|
+
* * light: values='0.14;0.02;0.14' + data-node-pulse-peak='0.14'
|
|
11
|
+
* - Pre-R409 invariants preserved:
|
|
12
|
+
* * dur='2.4s', calcMode='spline', repeatCount='indefinite'
|
|
13
|
+
* * keySplines='0.42 0 0.58 1;0.42 0 0.58 1'
|
|
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 probeTheme(theme) {
|
|
22
|
+
const browser = await chromium.launch({ headless: true });
|
|
23
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
24
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
25
|
+
await ctx.addInitScript((t) => {
|
|
26
|
+
try { localStorage.setItem('anet-theme', t); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
27
|
+
}, theme);
|
|
28
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
29
|
+
const r = await route.fetch();
|
|
30
|
+
const b = await r.json();
|
|
31
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
32
|
+
const mk = (alias) => ({
|
|
33
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
34
|
+
network_id: nid, project_dir: null,
|
|
35
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
36
|
+
});
|
|
37
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('alpha'), mk('beta'), mk('gamma') ] } });
|
|
38
|
+
});
|
|
39
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({
|
|
40
|
+
json: { messages: [
|
|
41
|
+
{ id: 'm1', from_alias: 'alpha', to_alias: 'beta', content: 'ping', created_at: fresh, network_id: 'default' },
|
|
42
|
+
] },
|
|
43
|
+
}));
|
|
44
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
45
|
+
const page = await ctx.newPage();
|
|
46
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
47
|
+
await page.waitForSelector('[data-node-pulse-active="true"]', { timeout: 15000 });
|
|
48
|
+
await page.waitForTimeout(500);
|
|
49
|
+
const probe = await page.evaluate(() => {
|
|
50
|
+
const pulseGroup = document.querySelector('[data-node-pulse-active="true"]');
|
|
51
|
+
if (!pulseGroup) return null;
|
|
52
|
+
const animates = pulseGroup.querySelectorAll('animate');
|
|
53
|
+
const opacityAnim = Array.from(animates).find(a => a.getAttribute('attributeName') === 'opacity');
|
|
54
|
+
return opacityAnim ? {
|
|
55
|
+
attributeName: opacityAnim.getAttribute('attributeName'),
|
|
56
|
+
values: opacityAnim.getAttribute('values'),
|
|
57
|
+
dur: opacityAnim.getAttribute('dur'),
|
|
58
|
+
calcMode: opacityAnim.getAttribute('calcMode'),
|
|
59
|
+
repeatCount: opacityAnim.getAttribute('repeatCount'),
|
|
60
|
+
keySplines: opacityAnim.getAttribute('keySplines'),
|
|
61
|
+
peakData: opacityAnim.getAttribute('data-node-pulse-peak'),
|
|
62
|
+
} : null;
|
|
63
|
+
});
|
|
64
|
+
await browser.close();
|
|
65
|
+
return probe;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const cyber = await probeTheme('cyber');
|
|
69
|
+
const light = await probeTheme('light');
|
|
70
|
+
|
|
71
|
+
const results = {
|
|
72
|
+
// R409: peak lifts to 0.20 cyber / 0.14 light
|
|
73
|
+
cyber_values_0_20: cyber?.values === '0.20;0.04;0.20',
|
|
74
|
+
cyber_peak_data_0_20: cyber?.peakData === '0.20',
|
|
75
|
+
light_values_0_14: light?.values === '0.14;0.02;0.14',
|
|
76
|
+
light_peak_data_0_14: light?.peakData === '0.14',
|
|
77
|
+
// Pre-R409 invariants
|
|
78
|
+
cyber_dur_2_4s: cyber?.dur === '2.4s',
|
|
79
|
+
cyber_spline: cyber?.calcMode === 'spline',
|
|
80
|
+
cyber_repeat_indefinite: cyber?.repeatCount === 'indefinite',
|
|
81
|
+
cyber_keySplines: cyber?.keySplines === '0.42 0 0.58 1;0.42 0 0.58 1',
|
|
82
|
+
light_dur_2_4s: light?.dur === '2.4s',
|
|
83
|
+
light_keySplines: light?.keySplines === '0.42 0 0.58 1;0.42 0 0.58 1',
|
|
84
|
+
};
|
|
85
|
+
const ok = Object.values(results).every(Boolean);
|
|
86
|
+
console.log(`${ok ? '✅' : '❌'} active-node pulse peak lift:`, JSON.stringify(results),
|
|
87
|
+
'\n cyber:', cyber,
|
|
88
|
+
'\n light:', light);
|
|
89
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/* Round 413 verification: active-node pulse SMIL trough opacity
|
|
2
|
+
* lift — cyber 0.04 → 0.05 / light 0.02 → 0.03. Extends the
|
|
3
|
+
* stale-state legibility lift family (8th anchor) and pairs with
|
|
4
|
+
* R409 peak lift so the per-node "active flow" breath reads
|
|
5
|
+
* confidently at both ends of its cycle.
|
|
6
|
+
*
|
|
7
|
+
* Contract:
|
|
8
|
+
* - Seed a flow link so a node becomes "active" (R243 isActive gate)
|
|
9
|
+
* - The active node's <animate> opacity element:
|
|
10
|
+
* * cyber: values='0.20;0.05;0.20' + data-node-pulse-trough='0.05'
|
|
11
|
+
* * light: values='0.14;0.03;0.14' + data-node-pulse-trough='0.03'
|
|
12
|
+
* - R409 peak invariant: data-node-pulse-peak='0.20' / '0.14'
|
|
13
|
+
* - Pre-R413 invariants preserved:
|
|
14
|
+
* * dur='2.4s', calcMode='spline', repeatCount='indefinite'
|
|
15
|
+
* * keySplines='0.42 0 0.58 1;0.42 0 0.58 1'
|
|
16
|
+
*/
|
|
17
|
+
import { chromium } from 'playwright';
|
|
18
|
+
import { readFileSync } from 'node:fs';
|
|
19
|
+
|
|
20
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
21
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
22
|
+
|
|
23
|
+
async function probeTheme(theme) {
|
|
24
|
+
const browser = await chromium.launch({ headless: true });
|
|
25
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
26
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
27
|
+
await ctx.addInitScript((t) => {
|
|
28
|
+
try { localStorage.setItem('anet-theme', t); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
29
|
+
}, theme);
|
|
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('alpha'), mk('beta'), mk('gamma') ] } });
|
|
40
|
+
});
|
|
41
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({
|
|
42
|
+
json: { messages: [
|
|
43
|
+
{ id: 'm1', from_alias: 'alpha', to_alias: 'beta', content: 'ping', created_at: fresh, network_id: 'default' },
|
|
44
|
+
] },
|
|
45
|
+
}));
|
|
46
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
47
|
+
const page = await ctx.newPage();
|
|
48
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
49
|
+
await page.waitForSelector('[data-node-pulse-active="true"]', { timeout: 15000 });
|
|
50
|
+
await page.waitForTimeout(500);
|
|
51
|
+
const probe = await page.evaluate(() => {
|
|
52
|
+
const pulseGroup = document.querySelector('[data-node-pulse-active="true"]');
|
|
53
|
+
if (!pulseGroup) return null;
|
|
54
|
+
const animates = pulseGroup.querySelectorAll('animate');
|
|
55
|
+
const opacityAnim = Array.from(animates).find(a => a.getAttribute('attributeName') === 'opacity');
|
|
56
|
+
return opacityAnim ? {
|
|
57
|
+
values: opacityAnim.getAttribute('values'),
|
|
58
|
+
peakData: opacityAnim.getAttribute('data-node-pulse-peak'),
|
|
59
|
+
troughData: opacityAnim.getAttribute('data-node-pulse-trough'),
|
|
60
|
+
dur: opacityAnim.getAttribute('dur'),
|
|
61
|
+
calcMode: opacityAnim.getAttribute('calcMode'),
|
|
62
|
+
keySplines: opacityAnim.getAttribute('keySplines'),
|
|
63
|
+
} : null;
|
|
64
|
+
});
|
|
65
|
+
await browser.close();
|
|
66
|
+
return probe;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const cyber = await probeTheme('cyber');
|
|
70
|
+
const light = await probeTheme('light');
|
|
71
|
+
|
|
72
|
+
const results = {
|
|
73
|
+
// R413: trough lifts to 0.05 cyber / 0.03 light
|
|
74
|
+
cyber_values_0_05: cyber?.values === '0.20;0.05;0.20',
|
|
75
|
+
cyber_trough_data_0_05: cyber?.troughData === '0.05',
|
|
76
|
+
light_values_0_03: light?.values === '0.14;0.03;0.14',
|
|
77
|
+
light_trough_data_0_03: light?.troughData === '0.03',
|
|
78
|
+
// R409 peak invariants
|
|
79
|
+
cyber_peak_data_0_20: cyber?.peakData === '0.20',
|
|
80
|
+
light_peak_data_0_14: light?.peakData === '0.14',
|
|
81
|
+
// Pre-R413 invariants preserved
|
|
82
|
+
cyber_dur_2_4s: cyber?.dur === '2.4s',
|
|
83
|
+
cyber_spline: cyber?.calcMode === 'spline',
|
|
84
|
+
cyber_keySplines: cyber?.keySplines === '0.42 0 0.58 1;0.42 0 0.58 1',
|
|
85
|
+
light_dur_2_4s: light?.dur === '2.4s',
|
|
86
|
+
};
|
|
87
|
+
const ok = Object.values(results).every(Boolean);
|
|
88
|
+
console.log(`${ok ? '✅' : '❌'} active-node pulse trough lift:`, JSON.stringify(results),
|
|
89
|
+
'\n cyber:', cyber,
|
|
90
|
+
'\n light:', light);
|
|
91
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/* Round 349 verification: panel header counts pick up editorial
|
|
2
|
+
* letter-spacing 0.2, one tier below the R301 panel title 0.3.
|
|
3
|
+
* Closes the panel-pair editorial symmetry — both top-corner panels
|
|
4
|
+
* now have a 2-step header hierarchy:
|
|
5
|
+
* title fontSize=12 fontWeight=700 letterSpacing=0.3 (R301)
|
|
6
|
+
* count fontSize=10 fontWeight=600 letterSpacing=0.2 (R349, this round)
|
|
7
|
+
* Joins the R285 / R289 / R301 / R302 / R304 / R325 editorial-
|
|
8
|
+
* letterspacing tier at the panel-summary scope. The R162 freshness
|
|
9
|
+
* fill, R225 tabular-nums, R311 fontWeight, R336 unit-tspan opacity-0.7
|
|
10
|
+
* split all preserved (SVG inheritance propagates the tier to descendant
|
|
11
|
+
* tspans).
|
|
12
|
+
*
|
|
13
|
+
* Contract:
|
|
14
|
+
* - Recent-signal panel header count <text> letter-spacing="0.2".
|
|
15
|
+
* - Legend panel header count <text> letter-spacing="0.2".
|
|
16
|
+
* - data-{recent,legend}-panel-count-letter-spacing="0.2" attrs present.
|
|
17
|
+
* - Pre-R349 invariants: R311 fontWeight=600, R225 tabular-nums,
|
|
18
|
+
* R336 unit-tspan opacity=0.7 all preserved.
|
|
19
|
+
*/
|
|
20
|
+
import { chromium } from 'playwright';
|
|
21
|
+
import { readFileSync } from 'node:fs';
|
|
22
|
+
|
|
23
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
24
|
+
const browser = await chromium.launch({ headless: true });
|
|
25
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
26
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
27
|
+
await ctx.addInitScript(() => {
|
|
28
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
29
|
+
});
|
|
30
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
31
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
32
|
+
const r = await route.fetch();
|
|
33
|
+
const b = await r.json();
|
|
34
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
35
|
+
const mk = (alias) => ({
|
|
36
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
37
|
+
network_id: nid, project_dir: null,
|
|
38
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
39
|
+
});
|
|
40
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('a'), mk('b'), mk('c') ] } });
|
|
41
|
+
});
|
|
42
|
+
// One message → recent panel mounts.
|
|
43
|
+
const now = Date.now();
|
|
44
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
45
|
+
{ id: 'm1', from_alias: 'a', to_alias: 'b', content: 'ping',
|
|
46
|
+
network_id: 'default', created_at: new Date(now - 5000).toISOString() },
|
|
47
|
+
] } }));
|
|
48
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
49
|
+
|
|
50
|
+
const page = await ctx.newPage();
|
|
51
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
52
|
+
await page.waitForSelector('[data-recent-panel-count]', { timeout: 15000 });
|
|
53
|
+
await page.waitForSelector('[data-legend-panel-count]', { timeout: 5000 });
|
|
54
|
+
await page.waitForTimeout(300);
|
|
55
|
+
|
|
56
|
+
const probe = await page.evaluate(() => {
|
|
57
|
+
const rTspan = document.querySelector('[data-recent-panel-count]');
|
|
58
|
+
const rText = rTspan?.closest('text');
|
|
59
|
+
const rUnit = document.querySelector('[data-recent-panel-count-unit]');
|
|
60
|
+
const lText = document.querySelector('[data-legend-panel-count]');
|
|
61
|
+
const lUnit = document.querySelector('[data-legend-panel-count-unit]');
|
|
62
|
+
return {
|
|
63
|
+
recentTextLs: rText?.getAttribute('letter-spacing') ?? null,
|
|
64
|
+
recentLsAttr: rText?.getAttribute('data-recent-panel-count-letter-spacing') ?? null,
|
|
65
|
+
recentFw: rTspan?.getAttribute('font-weight') ?? null,
|
|
66
|
+
recentUnitOp: rUnit?.getAttribute('opacity') ?? null,
|
|
67
|
+
legendTextLs: lText?.getAttribute('letter-spacing') ?? null,
|
|
68
|
+
legendLsAttr: lText?.getAttribute('data-legend-panel-count-letter-spacing') ?? null,
|
|
69
|
+
legendFw: lText?.getAttribute('font-weight') ?? null,
|
|
70
|
+
legendUnitOp: lUnit?.getAttribute('opacity') ?? null,
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await browser.close();
|
|
75
|
+
|
|
76
|
+
const results = {
|
|
77
|
+
recent_text_ls_0_2: probe.recentTextLs === '0.2',
|
|
78
|
+
recent_attr_0_2: probe.recentLsAttr === '0.2',
|
|
79
|
+
recent_fw_600: probe.recentFw === '600', // R311
|
|
80
|
+
recent_unit_op_0_7: probe.recentUnitOp === '0.7', // R336
|
|
81
|
+
legend_text_ls_0_2: probe.legendTextLs === '0.2',
|
|
82
|
+
legend_attr_0_2: probe.legendLsAttr === '0.2',
|
|
83
|
+
legend_fw_600: probe.legendFw === '600', // R310
|
|
84
|
+
legend_unit_op_0_7: probe.legendUnitOp === '0.7', // R336
|
|
85
|
+
};
|
|
86
|
+
const ok = Object.values(results).every(Boolean);
|
|
87
|
+
console.log(`${ok ? '✅' : '❌'} panel count letter-spacing 0.2:`, JSON.stringify(results),
|
|
88
|
+
'\n probe:', probe);
|
|
89
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/* Round 348 verification: panel rect opacity hover-state bump.
|
|
2
|
+
* Recent-signal + legend panels both lift their fill opacity when
|
|
3
|
+
* hoveredPanel === <self>. Cyber: 0.92 → 0.97. Light: 0.97 → 1.0.
|
|
4
|
+
* Joins the panel-hover cue stack:
|
|
5
|
+
* - R135 drop-shadow boost
|
|
6
|
+
* - R345 panel title letter-spacing tween 0.3 → 0.4
|
|
7
|
+
* - R266 fill theme-flip
|
|
8
|
+
* - R348 rect opacity bump (this round)
|
|
9
|
+
* Pure paint-level change — geometry-safe, bbox unchanged, so
|
|
10
|
+
* topo-overlap-test invariants hold. The R247 transition list already
|
|
11
|
+
* includes `opacity 200ms ease-out` so the value tween is automatic.
|
|
12
|
+
*
|
|
13
|
+
* Contract (cyber theme):
|
|
14
|
+
* - Rest: both panel rects opacity=0.92.
|
|
15
|
+
* - Hover recent: recent-panel rect opacity=0.97.
|
|
16
|
+
* - Hover legend: legend-panel rect opacity=0.97.
|
|
17
|
+
* - data-topo-panel-elevation selectors locate the rects (existing).
|
|
18
|
+
* - data-topo-panel-hovered toggles on parent <g> (existing R135).
|
|
19
|
+
* - Pre-R348 invariants: R331 rx=10 + R247 transition list intact.
|
|
20
|
+
*/
|
|
21
|
+
import { chromium } from 'playwright';
|
|
22
|
+
import { readFileSync } from 'node:fs';
|
|
23
|
+
|
|
24
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
25
|
+
const browser = await chromium.launch({ headless: true });
|
|
26
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
27
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
28
|
+
await ctx.addInitScript(() => {
|
|
29
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
30
|
+
});
|
|
31
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
32
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
33
|
+
const r = await route.fetch();
|
|
34
|
+
const b = await r.json();
|
|
35
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
36
|
+
const mk = (alias) => ({
|
|
37
|
+
alias, status: 'working', 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
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('alpha'), mk('beta'), mk('gamma') ] } });
|
|
42
|
+
});
|
|
43
|
+
// One message so the recent-signal panel mounts.
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
46
|
+
{ id: 'm1', from_alias: 'alpha', to_alias: 'beta', content: 'ping',
|
|
47
|
+
network_id: 'default', created_at: new Date(now - 5000).toISOString() },
|
|
48
|
+
] } }));
|
|
49
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
50
|
+
|
|
51
|
+
const page = await ctx.newPage();
|
|
52
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
53
|
+
await page.waitForSelector('[data-topo-panel-elevation="recent"]', { timeout: 15000 });
|
|
54
|
+
await page.waitForSelector('[data-topo-panel-elevation="legend"]', { timeout: 5000 });
|
|
55
|
+
await page.waitForTimeout(400);
|
|
56
|
+
|
|
57
|
+
// Rest probe (cyber theme).
|
|
58
|
+
const restProbe = await page.evaluate(() => {
|
|
59
|
+
const r = document.querySelector('[data-topo-panel-elevation="recent"]');
|
|
60
|
+
const l = document.querySelector('[data-topo-panel-elevation="legend"]');
|
|
61
|
+
return {
|
|
62
|
+
recentOpacity: r?.getAttribute('opacity') ?? null,
|
|
63
|
+
legendOpacity: l?.getAttribute('opacity') ?? null,
|
|
64
|
+
recentRx: r?.getAttribute('rx') ?? null,
|
|
65
|
+
legendRx: l?.getAttribute('rx') ?? null,
|
|
66
|
+
recentTrans: r ? getComputedStyle(r).transition : null,
|
|
67
|
+
legendTrans: l ? getComputedStyle(l).transition : null,
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Hover recent panel.
|
|
72
|
+
await page.hover('[data-topo-panel="recent"]');
|
|
73
|
+
await page.waitForTimeout(300);
|
|
74
|
+
const recentHoverProbe = await page.evaluate(() => {
|
|
75
|
+
const r = document.querySelector('[data-topo-panel-elevation="recent"]');
|
|
76
|
+
return { opacity: r?.getAttribute('opacity') ?? null };
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Hover legend panel.
|
|
80
|
+
await page.hover('[data-topo-panel="legend"]');
|
|
81
|
+
await page.waitForTimeout(300);
|
|
82
|
+
const legendHoverProbe = await page.evaluate(() => {
|
|
83
|
+
const l = document.querySelector('[data-topo-panel-elevation="legend"]');
|
|
84
|
+
return { opacity: l?.getAttribute('opacity') ?? null };
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
await browser.close();
|
|
88
|
+
|
|
89
|
+
const hasTrans = (s, prop) =>
|
|
90
|
+
new RegExp(`${prop}\\s+\\d*\\.?\\d*s|${prop}\\s+\\d+ms`, 'i').test(s || '');
|
|
91
|
+
|
|
92
|
+
const results = {
|
|
93
|
+
rest_recent_0_92: restProbe.recentOpacity === '0.92',
|
|
94
|
+
rest_legend_0_92: restProbe.legendOpacity === '0.92',
|
|
95
|
+
rest_recent_rx_10: restProbe.recentRx === '10',
|
|
96
|
+
rest_legend_rx_10: restProbe.legendRx === '10',
|
|
97
|
+
trans_recent_op: hasTrans(restProbe.recentTrans, 'opacity'),
|
|
98
|
+
trans_legend_op: hasTrans(restProbe.legendTrans, 'opacity'),
|
|
99
|
+
trans_recent_filter: hasTrans(restProbe.recentTrans, 'filter'),
|
|
100
|
+
trans_legend_filter: hasTrans(restProbe.legendTrans, 'filter'),
|
|
101
|
+
hover_recent_0_97: recentHoverProbe.opacity === '0.97',
|
|
102
|
+
hover_legend_0_97: legendHoverProbe.opacity === '0.97',
|
|
103
|
+
};
|
|
104
|
+
const ok = Object.values(results).every(Boolean);
|
|
105
|
+
console.log(`${ok ? '✅' : '❌'} panel rect opacity hover bump:`, JSON.stringify(results),
|
|
106
|
+
'\n rest: ', restProbe,
|
|
107
|
+
'\n hover recent:', recentHoverProbe,
|
|
108
|
+
'\n hover legend:', legendHoverProbe);
|
|
109
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/* Round 374 verification: pressure-bar height h-1.5 → h-2 (6 → 8 px).
|
|
2
|
+
* Sibling visual-weight bump (8th canvas/HTML anchor in the family).
|
|
3
|
+
* +33 % bar height gives working/idle/offline segments more visibility.
|
|
4
|
+
*
|
|
5
|
+
* Geometry-safe: items-center flex centers the bar inside the chip's
|
|
6
|
+
* py-1 — bar at 8 px stays comfortably inside the 10-px text-row.
|
|
7
|
+
*
|
|
8
|
+
* Contract (cyber, fixture with mix):
|
|
9
|
+
* - Pressure bar wrapper computed height === '8px' (h-2).
|
|
10
|
+
* - data-fleet-pressure-bar-height === 'h-2'.
|
|
11
|
+
* - Pre-R374 invariants:
|
|
12
|
+
* * width still w-16 (64 px)
|
|
13
|
+
* * inline-flex display + rounded-full + overflow-hidden
|
|
14
|
+
* * background rgb(75 85 99 / 0.25)
|
|
15
|
+
* * Parent [data-fleet-pressure] chip className unchanged
|
|
16
|
+
* (font-mono + chip structure)
|
|
17
|
+
*/
|
|
18
|
+
import { chromium } from 'playwright';
|
|
19
|
+
import { readFileSync } from 'node:fs';
|
|
20
|
+
|
|
21
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
22
|
+
const browser = await chromium.launch({ headless: true });
|
|
23
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
24
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
25
|
+
await ctx.addInitScript(() => {
|
|
26
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
27
|
+
});
|
|
28
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
29
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
30
|
+
const r = await route.fetch();
|
|
31
|
+
const b = await r.json();
|
|
32
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
33
|
+
const mk = (alias, status = 'working') => ({
|
|
34
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
35
|
+
network_id: nid, project_dir: null,
|
|
36
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
37
|
+
});
|
|
38
|
+
// Mix so all 3 segments render.
|
|
39
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
40
|
+
mk('w1'), mk('w2'),
|
|
41
|
+
mk('i1', 'idle'), mk('i2', 'idle'),
|
|
42
|
+
mk('o1', 'offline'),
|
|
43
|
+
] } });
|
|
44
|
+
});
|
|
45
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
46
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
47
|
+
|
|
48
|
+
const page = await ctx.newPage();
|
|
49
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
50
|
+
await page.waitForSelector('[data-fleet-pressure-bar-height]', { timeout: 15000 });
|
|
51
|
+
await page.waitForTimeout(300);
|
|
52
|
+
|
|
53
|
+
const probe = await page.evaluate(() => {
|
|
54
|
+
const bar = document.querySelector('[data-fleet-pressure-bar-height]');
|
|
55
|
+
const cs = bar ? getComputedStyle(bar) : null;
|
|
56
|
+
const parent = document.querySelector('[data-fleet-pressure]');
|
|
57
|
+
// Count visible segments inside the bar.
|
|
58
|
+
const segs = bar ? Array.from(bar.querySelectorAll('[data-pressure-seg]')) : [];
|
|
59
|
+
return {
|
|
60
|
+
height: cs?.height ?? null,
|
|
61
|
+
width: cs?.width ?? null,
|
|
62
|
+
barHeightData: bar?.getAttribute('data-fleet-pressure-bar-height') ?? null,
|
|
63
|
+
display: cs?.display ?? null,
|
|
64
|
+
borderRadius: cs?.borderRadius ?? null,
|
|
65
|
+
overflow: cs?.overflow ?? null,
|
|
66
|
+
bgColor: cs?.backgroundColor ?? null,
|
|
67
|
+
parentMono: /font-mono/.test(parent?.getAttribute('class') || ''),
|
|
68
|
+
segCount: segs.length,
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
await browser.close();
|
|
73
|
+
|
|
74
|
+
const results = {
|
|
75
|
+
height_8px: probe.height === '8px', // h-2
|
|
76
|
+
width_64px: probe.width === '64px', // w-16
|
|
77
|
+
data_height_h_2: probe.barHeightData === 'h-2',
|
|
78
|
+
// Flex items get display blockified: inline-flex → flex when nested
|
|
79
|
+
// in flex container. Accept either.
|
|
80
|
+
display_inline_flex: probe.display === 'inline-flex' || probe.display === 'flex',
|
|
81
|
+
// Tailwind rounded-full is border-radius: 9999px, which browsers
|
|
82
|
+
// sometimes render as 3.35544e+07px (huge approximation). Accept any
|
|
83
|
+
// value indicating fully-rounded.
|
|
84
|
+
has_rounded_full: /9999|3\.355|e\+/.test(probe.borderRadius || ''),
|
|
85
|
+
overflow_hidden: probe.overflow === 'hidden',
|
|
86
|
+
parent_font_mono: probe.parentMono,
|
|
87
|
+
three_segments: probe.segCount === 3,
|
|
88
|
+
};
|
|
89
|
+
const ok = Object.values(results).every(Boolean);
|
|
90
|
+
console.log(`${ok ? '✅' : '❌'} pressure-bar height 1.5 → 2:`, JSON.stringify(results),
|
|
91
|
+
'\n probe:', probe);
|
|
92
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/* Round 373 verification: pressure-bar kicker label fontWeight 400 →
|
|
2
|
+
* 500. Sibling small-text fw lift family with R363/R364/R366/R368 —
|
|
3
|
+
* 5th surface in the family.
|
|
4
|
+
*
|
|
5
|
+
* Family snapshot post-R373:
|
|
6
|
+
* recent-row alias fw 500 (R363)
|
|
7
|
+
* legend-row label fw 500 (R364)
|
|
8
|
+
* group-label count fw 500 (R366)
|
|
9
|
+
* +N more flows footer fw 500 (R368)
|
|
10
|
+
* pressure-bar kicker fw 500 (R373, this round)
|
|
11
|
+
*
|
|
12
|
+
* Contract (cyber, fixture with mix so pressure bar renders):
|
|
13
|
+
* - [data-fleet-pressure-kicker] computed fontWeight === '500'.
|
|
14
|
+
* - Pre-R373 invariants:
|
|
15
|
+
* * text-[10px] (fontSize 10) preserved
|
|
16
|
+
* * tracking-wide (letter-spacing 0.025em) preserved
|
|
17
|
+
* * Parent [data-fleet-pressure] still has font-mono + chip
|
|
18
|
+
* structure
|
|
19
|
+
*/
|
|
20
|
+
import { chromium } from 'playwright';
|
|
21
|
+
import { readFileSync } from 'node:fs';
|
|
22
|
+
|
|
23
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
24
|
+
const browser = await chromium.launch({ headless: true });
|
|
25
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
26
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
27
|
+
await ctx.addInitScript(() => {
|
|
28
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
29
|
+
});
|
|
30
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
31
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
32
|
+
const r = await route.fetch();
|
|
33
|
+
const b = await r.json();
|
|
34
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
35
|
+
const mk = (alias) => ({
|
|
36
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
37
|
+
network_id: nid, project_dir: null,
|
|
38
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
39
|
+
});
|
|
40
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('a'), mk('b'), mk('c') ] } });
|
|
41
|
+
});
|
|
42
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
43
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
44
|
+
|
|
45
|
+
const page = await ctx.newPage();
|
|
46
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
47
|
+
await page.waitForSelector('[data-fleet-pressure-kicker]', { timeout: 15000 });
|
|
48
|
+
await page.waitForTimeout(300);
|
|
49
|
+
|
|
50
|
+
const probe = await page.evaluate(() => {
|
|
51
|
+
const kicker = document.querySelector('[data-fleet-pressure-kicker]');
|
|
52
|
+
const parent = document.querySelector('[data-fleet-pressure]');
|
|
53
|
+
const cs = kicker ? getComputedStyle(kicker) : null;
|
|
54
|
+
return {
|
|
55
|
+
fontWeight: cs?.fontWeight ?? null,
|
|
56
|
+
fontSize: cs?.fontSize ?? null,
|
|
57
|
+
letterSpacing: cs?.letterSpacing ?? null,
|
|
58
|
+
text: kicker?.textContent ?? null,
|
|
59
|
+
parentCls: parent?.getAttribute('class') ?? null,
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
await browser.close();
|
|
64
|
+
|
|
65
|
+
const results = {
|
|
66
|
+
font_weight_500: probe.fontWeight === '500',
|
|
67
|
+
font_size_10px: probe.fontSize === '10px',
|
|
68
|
+
// tracking-wide = 0.025em → at 10px font that's 0.25px computed.
|
|
69
|
+
letter_spacing_tracking_wide: /0\.25px|0\.025em/.test(probe.letterSpacing || ''),
|
|
70
|
+
text_is_pressure: probe.text === 'pressure',
|
|
71
|
+
parent_font_mono: /font-mono/.test(probe.parentCls || ''),
|
|
72
|
+
};
|
|
73
|
+
const ok = Object.values(results).every(Boolean);
|
|
74
|
+
console.log(`${ok ? '✅' : '❌'} pressure-bar kicker fw 400 → 500:`, JSON.stringify(results),
|
|
75
|
+
'\n probe:', probe);
|
|
76
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/* Round 383 verification: recency pip base radius 1.8 → 2.0.
|
|
2
|
+
* Continues R359 lift trajectory; sibling visual-weight bump
|
|
3
|
+
* family (9th anchor).
|
|
4
|
+
*
|
|
5
|
+
* Contract:
|
|
6
|
+
* - Pip element computed r === '2.0' (rendered) or attribute equals 2.
|
|
7
|
+
* - data-recent-row-freshness-radius === '2.0'.
|
|
8
|
+
* - Pre-R383 invariants:
|
|
9
|
+
* * cx=10 (R160 left margin position unchanged)
|
|
10
|
+
* * fill=pal.legendAccent
|
|
11
|
+
* * opacity transition (R358) preserved
|
|
12
|
+
* * R358 stale-alpha floor 0.30 still applies
|
|
13
|
+
*/
|
|
14
|
+
import { chromium } from 'playwright';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
|
|
17
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
18
|
+
const browser = await chromium.launch({ headless: true });
|
|
19
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
20
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
21
|
+
await ctx.addInitScript(() => {
|
|
22
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
23
|
+
});
|
|
24
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
25
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
26
|
+
const r = await route.fetch();
|
|
27
|
+
const b = await r.json();
|
|
28
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
29
|
+
const mk = (alias) => ({
|
|
30
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
31
|
+
network_id: nid, project_dir: null,
|
|
32
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
33
|
+
});
|
|
34
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [ mk('a'), mk('b') ] } });
|
|
35
|
+
});
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [
|
|
38
|
+
{ id: 'm1', from_alias: 'a', to_alias: 'b', content: 'ping',
|
|
39
|
+
network_id: 'default', created_at: new Date(now - 5000).toISOString(),
|
|
40
|
+
last_at: new Date(now - 5000).toISOString() },
|
|
41
|
+
] } }));
|
|
42
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
43
|
+
|
|
44
|
+
const page = await ctx.newPage();
|
|
45
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
46
|
+
await page.waitForSelector('[data-recent-row-freshness]', { timeout: 15000 });
|
|
47
|
+
await page.waitForTimeout(300);
|
|
48
|
+
|
|
49
|
+
const probe = await page.evaluate(() => {
|
|
50
|
+
const pip = document.querySelector('[data-recent-row-freshness]');
|
|
51
|
+
return {
|
|
52
|
+
rAttr: pip?.getAttribute('r') ?? null,
|
|
53
|
+
radiusAttr: pip?.getAttribute('data-recent-row-freshness-radius') ?? null,
|
|
54
|
+
cxAttr: pip?.getAttribute('cx') ?? null,
|
|
55
|
+
linkKey: pip?.getAttribute('data-recent-row-freshness') ?? null,
|
|
56
|
+
opacityAttr: pip?.getAttribute('opacity') ?? null,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
await browser.close();
|
|
61
|
+
|
|
62
|
+
const results = {
|
|
63
|
+
r_attr_2: probe.rAttr === '2' || probe.rAttr === '2.0',
|
|
64
|
+
radius_attr_2_0: probe.radiusAttr === '2.0',
|
|
65
|
+
cx_unchanged_10: probe.cxAttr === '10', // R160 invariant
|
|
66
|
+
link_key_present: (probe.linkKey || '').length > 0,
|
|
67
|
+
opacity_above_zero: parseFloat(probe.opacityAttr || '0') > 0, // fresh, alpha > 0
|
|
68
|
+
};
|
|
69
|
+
const ok = Object.values(results).every(Boolean);
|
|
70
|
+
console.log(`${ok ? '✅' : '❌'} recent pip radius 1.8 → 2.0:`, JSON.stringify(results),
|
|
71
|
+
'\n probe:', probe);
|
|
72
|
+
process.exit(ok ? 0 : 1);
|