@sleep2agi/agent-network-dashboard 0.4.6-preview.281 → 0.4.6-preview.283
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 +4 -4
- 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.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- 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 +1 -1
- package/.next/server/app/admin.html +1 -1
- package/.next/server/app/admin.rsc +1 -1
- package/.next/server/app/admin.segments/_full.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_index.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/login.segments/_full.segment.rsc +2 -2
- package/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/server/app/login.segments/_index.segment.rsc +1 -1
- package/.next/server/app/login.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/logs.rsc +1 -1
- package/.next/server/app/logs.segments/_full.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_index.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/messages.rsc +1 -1
- package/.next/server/app/messages.segments/_full.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_index.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/node.rsc +1 -1
- package/.next/server/app/node.segments/_full.segment.rsc +1 -1
- package/.next/server/app/node.segments/_head.segment.rsc +1 -1
- package/.next/server/app/node.segments/_index.segment.rsc +1 -1
- package/.next/server/app/node.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/nodes.rsc +1 -1
- package/.next/server/app/nodes.segments/_full.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_index.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/server-logs.rsc +1 -1
- package/.next/server/app/server-logs.segments/_full.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_index.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/settings/networks.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/settings/tokens.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/settings.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- 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.html +1 -1
- package/.next/server/app/tasks.rsc +1 -1
- package/.next/server/app/tasks.segments/_full.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_index.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_tree.segment.rsc +1 -1
- 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 +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/static/chunks/{0c_eg6lxw~36i.js → 0770ctmo-jd~3.js} +3 -3
- package/.next/static/chunks/{0qnfuwkukbu01.js → 12ih-cxmgr09g.js} +1 -1
- package/.next/static/chunks/{11ilooy_9niy-.js → 13ku0uxsx2o6i.js} +1 -1
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +42 -2
- package/package.json +1 -1
- package/scripts/topo-freshness-conditional-render-test.mjs +92 -0
- package/scripts/topo-orbit-particles-retired-test.mjs +91 -0
- package/scripts/topo-freshness-text-color-coherence-test.mjs +0 -97
- package/scripts/topo-orbit-busyness-test.mjs +0 -96
- package/scripts/topo-orbit-opacity-bucket-test.mjs +0 -124
- /package/.next/static/{gjUOBeB2JqesZ_cSX14ph → gPw1YGsDb6psvirUWKGfQ}/_buildManifest.js +0 -0
- /package/.next/static/{gjUOBeB2JqesZ_cSX14ph → gPw1YGsDb6psvirUWKGfQ}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{gjUOBeB2JqesZ_cSX14ph → gPw1YGsDb6psvirUWKGfQ}/_ssgManifest.js +0 -0
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/* Round 272 verification: FreshnessChip text prefix matches color
|
|
2
|
-
* state (fresh="live", stale="lag").
|
|
3
|
-
*
|
|
4
|
-
* Pre-R272 the chip read "live · {sec}s" in both states:
|
|
5
|
-
* fresh: gray + "live · 3s" → color says fresh, text says fresh ✓
|
|
6
|
-
* stale: amber + "live · 15s" → color says stale, text says fresh ✗ (contradicts)
|
|
7
|
-
*
|
|
8
|
-
* Post-R272:
|
|
9
|
-
* fresh: gray + "live · 3s" → color and text both say fresh ✓
|
|
10
|
-
* stale: amber + "lag · 15s" → color and text both signal stale ✓
|
|
11
|
-
*
|
|
12
|
-
* The chip's `stale` flag fires when sec > 10. Hard to wait 11s in
|
|
13
|
-
* a test, so we test the fresh-state directly (default render is
|
|
14
|
-
* fresh since useRef captures Date.now() at mount and 0s has
|
|
15
|
-
* elapsed). For stale, we'd need to wait — instead, verify the
|
|
16
|
-
* code path by checking the chip exists with fresh text + correct
|
|
17
|
-
* `data-freshness-chip-stale='false'` attr.
|
|
18
|
-
*
|
|
19
|
-
* Test scope:
|
|
20
|
-
* 1. Chip exists with data-freshness-chip attribute.
|
|
21
|
-
* 2. At fresh state, data-freshness-chip-stale === 'false'.
|
|
22
|
-
* 3. At fresh state, text starts with "live · " (prefix word "live").
|
|
23
|
-
* 4. At fresh state, color is gray (computed color contains 156 or
|
|
24
|
-
* similar Tailwind gray RGB).
|
|
25
|
-
* 5. Source code regression: the new JSX uses {stale ? 'lag' : 'live'}
|
|
26
|
-
* ternary (verified by grep'ing the rendered HTML node structure
|
|
27
|
-
* — the ternary always renders ONE of the two words, so the chip
|
|
28
|
-
* text should contain a single 3-letter prefix word).
|
|
29
|
-
* 6. R271 regression: legend row hitbox y=21 (working row).
|
|
30
|
-
*/
|
|
31
|
-
import { chromium } from 'playwright';
|
|
32
|
-
import { readFileSync } from 'node:fs';
|
|
33
|
-
|
|
34
|
-
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
35
|
-
const browser = await chromium.launch({ headless: true });
|
|
36
|
-
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
37
|
-
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
38
|
-
await ctx.addInitScript(() => {
|
|
39
|
-
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
40
|
-
});
|
|
41
|
-
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
42
|
-
await ctx.route('**/api/hub/status*', async (route) => {
|
|
43
|
-
const r = await route.fetch();
|
|
44
|
-
const b = await r.json();
|
|
45
|
-
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
46
|
-
const mk = (alias) => ({
|
|
47
|
-
alias, status: 'working', model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
48
|
-
network_id: nid, project_dir: null,
|
|
49
|
-
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
50
|
-
});
|
|
51
|
-
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
52
|
-
mk('alpha'), mk('beta'), mk('gamma'), mk('delta'),
|
|
53
|
-
] } });
|
|
54
|
-
});
|
|
55
|
-
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
56
|
-
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
57
|
-
|
|
58
|
-
const page = await ctx.newPage();
|
|
59
|
-
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
60
|
-
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
|
|
61
|
-
await page.waitForSelector('[data-freshness-chip]', { timeout: 10000 });
|
|
62
|
-
await page.waitForSelector('[data-legend-status="working"] rect', { timeout: 10000 });
|
|
63
|
-
await page.waitForTimeout(300);
|
|
64
|
-
|
|
65
|
-
const probe = await page.evaluate(() => {
|
|
66
|
-
const chip = document.querySelector('[data-freshness-chip]');
|
|
67
|
-
const legendRect = document.querySelector('[data-legend-status="working"] rect');
|
|
68
|
-
return {
|
|
69
|
-
chipText: chip ? chip.textContent.trim() : null,
|
|
70
|
-
chipStale: chip ? chip.getAttribute('data-freshness-chip-stale') : null,
|
|
71
|
-
chipColor: chip ? window.getComputedStyle(chip).color : null,
|
|
72
|
-
legendRectY: legendRect ? +legendRect.getAttribute('y') : null,
|
|
73
|
-
};
|
|
74
|
-
});
|
|
75
|
-
await browser.close();
|
|
76
|
-
|
|
77
|
-
// Fresh state: text should start with "live · " and stale attr === 'false'.
|
|
78
|
-
// gray chip color: text-gray-400 in cyber theme = rgb(156, 163, 175) or oklab(...) → contains "156" or "rgb".
|
|
79
|
-
const results = {
|
|
80
|
-
chip_present: probe.chipText !== null,
|
|
81
|
-
chip_is_fresh: probe.chipStale === 'false',
|
|
82
|
-
chip_text_starts_with_live: probe.chipText != null && probe.chipText.startsWith('live · '),
|
|
83
|
-
chip_text_no_lag_when_fresh: probe.chipText != null && !probe.chipText.startsWith('lag · '),
|
|
84
|
-
// Fresh color in cyber is text-gray-400. Tailwind v4 renders modern
|
|
85
|
-
// browsers as oklab()/lab()/oklch(). Accept any computed-color
|
|
86
|
-
// function format that indicates a color was actually applied.
|
|
87
|
-
chip_color_set: probe.chipColor != null
|
|
88
|
-
&& /(rgb|oklab|lab|oklch|hsl)/.test(probe.chipColor),
|
|
89
|
-
r271_legend_rect_y_21: probe.legendRectY === 21,
|
|
90
|
-
};
|
|
91
|
-
const ok = Object.values(results).every(Boolean);
|
|
92
|
-
console.log(`${ok ? '✅' : '❌'} freshness text color coherence:`, JSON.stringify(results),
|
|
93
|
-
'\n chip text:', JSON.stringify(probe.chipText),
|
|
94
|
-
'\n chip stale attr:', probe.chipStale,
|
|
95
|
-
'\n chip color:', probe.chipColor,
|
|
96
|
-
'\n legend rect y:', probe.legendRectY);
|
|
97
|
-
process.exit(ok ? 0 : 1);
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/* Round 131 verification: outer-ring orbit period buckets on
|
|
2
|
-
* workingCount, mirroring R84's hub-breath cadence. Idle fleet
|
|
3
|
-
* keeps the original 16s "calm sweep"; as work piles up the
|
|
4
|
-
* orbit accelerates to 14 / 12 / 10s. Both motion layers now
|
|
5
|
-
* read the same underlying "is the network busy" signal.
|
|
6
|
-
*
|
|
7
|
-
* Bucket boundaries identical to R84 (line ~2702):
|
|
8
|
-
* workingCount === 0 → bucket 0, dur 16s
|
|
9
|
-
* workingCount in [1, 2] → bucket 1, dur 14s
|
|
10
|
-
* workingCount in [3, 5] → bucket 2, dur 12s
|
|
11
|
-
* workingCount >= 6 → bucket 3, dur 10s
|
|
12
|
-
*
|
|
13
|
-
* R50 only renders on cyber theme (light is skipped to keep the
|
|
14
|
-
* white surface clean). All probes use cyber.
|
|
15
|
-
*
|
|
16
|
-
* Probe fleet sizes pick one representative per bucket.
|
|
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
|
-
|
|
23
|
-
async function probe(workingCount, totalCount) {
|
|
24
|
-
const browser = await chromium.launch({ headless: true });
|
|
25
|
-
const ctx = await browser.newContext({ viewport: { width: 1400, 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 sessions = [];
|
|
36
|
-
for (let i = 0; i < totalCount; i++) {
|
|
37
|
-
sessions.push({
|
|
38
|
-
alias: `node${i}`,
|
|
39
|
-
status: i < workingCount ? 'working' : 'idle',
|
|
40
|
-
model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
41
|
-
network_id: nid, project_dir: null,
|
|
42
|
-
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
await route.fulfill({ response: r, json: { ...b, sessions } });
|
|
46
|
-
});
|
|
47
|
-
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
|
|
48
|
-
await ctx.route('**/api/hub/tasks*', (route) => route.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.waitForFunction((n) => document.querySelectorAll('g[data-node]').length === n, totalCount, { timeout: 30000 });
|
|
53
|
-
await page.waitForTimeout(400);
|
|
54
|
-
|
|
55
|
-
const out = await page.evaluate(() => {
|
|
56
|
-
const orbits = [...document.querySelectorAll('[data-topo-orbit-bucket]')];
|
|
57
|
-
return orbits.map(g => ({
|
|
58
|
-
bucket: g.getAttribute('data-topo-orbit-bucket'),
|
|
59
|
-
dur: g.getAttribute('data-topo-orbit-dur'),
|
|
60
|
-
animDur: g.querySelector('animateTransform')?.getAttribute('dur'),
|
|
61
|
-
}));
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
await browser.close();
|
|
65
|
-
return out;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Pick one from each bucket
|
|
69
|
-
const b0 = await probe(0, 4); // workingCount=0 → bucket 0, dur 16
|
|
70
|
-
const b1 = await probe(2, 4); // workingCount=2 → bucket 1, dur 14
|
|
71
|
-
const b2 = await probe(4, 5); // workingCount=4 → bucket 2, dur 12
|
|
72
|
-
const b3 = await probe(7, 8); // workingCount=7 → bucket 3, dur 10
|
|
73
|
-
|
|
74
|
-
const allConsistent = (orbits, bucket, dur) =>
|
|
75
|
-
orbits.length === 4 &&
|
|
76
|
-
orbits.every(o => o.bucket === String(bucket) && o.dur === String(dur) && o.animDur === `${dur}s`);
|
|
77
|
-
|
|
78
|
-
const results = {
|
|
79
|
-
b0_fourOrbits: b0.length === 4,
|
|
80
|
-
b0_bucket0_16s: allConsistent(b0, 0, 16),
|
|
81
|
-
b1_bucket1_14s: allConsistent(b1, 1, 14),
|
|
82
|
-
b2_bucket2_12s: allConsistent(b2, 2, 12),
|
|
83
|
-
b3_bucket3_10s: allConsistent(b3, 3, 10),
|
|
84
|
-
// dur strictly decreases as busy increases
|
|
85
|
-
dur_monotonic:
|
|
86
|
-
Number(b0[0]?.dur) > Number(b1[0]?.dur) &&
|
|
87
|
-
Number(b1[0]?.dur) > Number(b2[0]?.dur) &&
|
|
88
|
-
Number(b2[0]?.dur) > Number(b3[0]?.dur),
|
|
89
|
-
};
|
|
90
|
-
const ok = Object.values(results).every(Boolean);
|
|
91
|
-
console.log(`${ok ? '✅' : '❌'} orbit busyness:`, JSON.stringify(results),
|
|
92
|
-
`\n b0(0w/4)=`, b0,
|
|
93
|
-
`\n b1(2w/4)=`, b1,
|
|
94
|
-
`\n b2(4w/5)=`, b2,
|
|
95
|
-
`\n b3(7w/8)=`, b3);
|
|
96
|
-
process.exit(ok ? 0 : 1);
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
/* Round 216 verification: outer-ring orbit particle opacity scales
|
|
2
|
-
* with busy bucket alongside R131's speed scaling. Idle fleet → dim
|
|
3
|
-
* particles; busy fleet → bright. transitions on opacity 300ms.
|
|
4
|
-
*
|
|
5
|
-
* Bucket map: workingCount 0 → busy 0; 1-2 → 1; 3-5 → 2; 6+ → 3
|
|
6
|
-
* opacity [0.5, 0.7, 0.85, 1.0]
|
|
7
|
-
*
|
|
8
|
-
* Test scenarios (cyber dark, orbit particles only render in dark):
|
|
9
|
-
* A. 0 working sessions (4 idle): busy=0, opacity≈0.5
|
|
10
|
-
* B. 2 working sessions (2 working+2 idle): busy=1, opacity≈0.7
|
|
11
|
-
* C. 6 working sessions: busy=3, opacity≈1.0
|
|
12
|
-
* Every orbit particle has style.transition: 'opacity 300ms'
|
|
13
|
-
* Every orbit <g> exposes data-topo-orbit-opacity matching the
|
|
14
|
-
* bucket value (test verifies derivation + DOM agreement).
|
|
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 browser = await chromium.launch({ headless: true });
|
|
21
|
-
|
|
22
|
-
async function pageFor(workingN) {
|
|
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
|
-
const totalSessions = Math.max(workingN, 4);
|
|
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, status) => ({
|
|
35
|
-
alias, status, 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
|
-
const sessions = [];
|
|
40
|
-
for (let i = 0; i < totalSessions; i++) {
|
|
41
|
-
sessions.push(mk(`node-${(i + 1).toString().padStart(2, '0')}`, i < workingN ? 'working' : 'idle'));
|
|
42
|
-
}
|
|
43
|
-
await route.fulfill({ response: r, json: { ...b, sessions } });
|
|
44
|
-
});
|
|
45
|
-
await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: [] } }));
|
|
46
|
-
await ctx.route('**/api/hub/tasks*', (r2) => r2.fulfill({ json: { tasks: [] } }));
|
|
47
|
-
const page = await ctx.newPage();
|
|
48
|
-
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
49
|
-
await page.waitForFunction((n) => document.querySelectorAll('g[data-node]').length === n, totalSessions, { timeout: 30000 });
|
|
50
|
-
await page.waitForSelector('[data-topo-orbit-bucket]', { timeout: 10000, state: 'attached' });
|
|
51
|
-
await page.waitForTimeout(300);
|
|
52
|
-
return page;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const probe = async (page) => page.evaluate(() => {
|
|
56
|
-
return [...document.querySelectorAll('[data-topo-orbit-bucket]')].map(el => {
|
|
57
|
-
const inner = el.querySelector('circle');
|
|
58
|
-
return {
|
|
59
|
-
bucket: el.getAttribute('data-topo-orbit-bucket'),
|
|
60
|
-
bucketOpacity: el.getAttribute('data-topo-orbit-opacity'),
|
|
61
|
-
dur: el.getAttribute('data-topo-orbit-dur'),
|
|
62
|
-
circleOpacity: parseFloat(inner?.getAttribute('opacity') || ''),
|
|
63
|
-
transition: inner?.style.transition,
|
|
64
|
-
};
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// Scenario A: 0 working → busy=0, opacity=0.5
|
|
69
|
-
const pageA = await pageFor(0);
|
|
70
|
-
const probeA = await probe(pageA);
|
|
71
|
-
await pageA.close();
|
|
72
|
-
|
|
73
|
-
// Scenario B: 2 working → busy=1, opacity=0.7
|
|
74
|
-
const pageB = await pageFor(2);
|
|
75
|
-
const probeB = await probe(pageB);
|
|
76
|
-
await pageB.close();
|
|
77
|
-
|
|
78
|
-
// Scenario C: 6 working → busy=3, opacity=1.0
|
|
79
|
-
const pageC = await pageFor(6);
|
|
80
|
-
const probeC = await probe(pageC);
|
|
81
|
-
await pageC.close();
|
|
82
|
-
await browser.close();
|
|
83
|
-
|
|
84
|
-
const near = (got, want, tol = 0.05) => Math.abs(got - want) < tol;
|
|
85
|
-
const hasOpacityT = (s) => /opacity\s+(?:300ms|0\.3s)/.test(s || '');
|
|
86
|
-
|
|
87
|
-
const results = {
|
|
88
|
-
// 4 orbit particles in each scenario (R50 phase array of 4)
|
|
89
|
-
A_four_particles: probeA.length === 4,
|
|
90
|
-
B_four_particles: probeB.length === 4,
|
|
91
|
-
C_four_particles: probeC.length === 4,
|
|
92
|
-
|
|
93
|
-
// Scenario A — idle fleet (busy=0)
|
|
94
|
-
A_bucket_0: probeA.every(p => p.bucket === '0'),
|
|
95
|
-
A_opacity_half: probeA.every(p => near(p.circleOpacity, 0.5)),
|
|
96
|
-
A_data_attr_matches: probeA.every(p => parseFloat(p.bucketOpacity) === p.circleOpacity),
|
|
97
|
-
|
|
98
|
-
// Scenario B — light load (busy=1)
|
|
99
|
-
B_bucket_1: probeB.every(p => p.bucket === '1'),
|
|
100
|
-
B_opacity_0p7: probeB.every(p => near(p.circleOpacity, 0.7)),
|
|
101
|
-
|
|
102
|
-
// Scenario C — heavy load (busy=3)
|
|
103
|
-
C_bucket_3: probeC.every(p => p.bucket === '3'),
|
|
104
|
-
C_opacity_full: probeC.every(p => near(p.circleOpacity, 1.0)),
|
|
105
|
-
|
|
106
|
-
// Brightness actually grew across buckets
|
|
107
|
-
brightness_grew: probeA[0].circleOpacity < probeB[0].circleOpacity
|
|
108
|
-
&& probeB[0].circleOpacity < probeC[0].circleOpacity,
|
|
109
|
-
|
|
110
|
-
// Transitions present in every particle of every scenario
|
|
111
|
-
A_all_have_transition: probeA.every(p => hasOpacityT(p.transition)),
|
|
112
|
-
B_all_have_transition: probeB.every(p => hasOpacityT(p.transition)),
|
|
113
|
-
C_all_have_transition: probeC.every(p => hasOpacityT(p.transition)),
|
|
114
|
-
|
|
115
|
-
// R131's existing speed scaling still derives — dur shortens as
|
|
116
|
-
// bucket grows
|
|
117
|
-
speed_scales: parseFloat(probeA[0].dur || '0') > parseFloat(probeC[0].dur || '99'),
|
|
118
|
-
};
|
|
119
|
-
const ok = Object.values(results).every(Boolean);
|
|
120
|
-
console.log(`${ok ? '✅' : '❌'} orbit opacity bucket:`, JSON.stringify(results),
|
|
121
|
-
`\n probeA (0 working):`, probeA.slice(0, 1),
|
|
122
|
-
`\n probeB (2 working):`, probeB.slice(0, 1),
|
|
123
|
-
`\n probeC (6 working):`, probeC.slice(0, 1));
|
|
124
|
-
process.exit(ok ? 0 : 1);
|
|
File without changes
|
/package/.next/static/{gjUOBeB2JqesZ_cSX14ph → gPw1YGsDb6psvirUWKGfQ}/_clientMiddlewareManifest.js
RENAMED
|
File without changes
|
|
File without changes
|