Oregami
Repositories/oxedyne/daimond

oxedyne/daimond/dev/verify_governor_ui.mjs

3.4 KiB, 1 run

created by r2519314175:441, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1// verify_governor_ui.mjs — the spend governor, wired into the real page.
2//
3// The pure decision core is covered by verify_governor.mjs under Node. This
4// drives the actual app (governor.js loaded in index.html, alongside the real
5// ledger) to prove the wiring: the module is present, its live decision runs,
6// its state escalates to amber after a burst, and no console error is thrown.
7//
8// Needs dev/serve.mjs (DAIMOND_PORT, default 8777) and dev/mockllm.mjs
9// (DAIMOND_MOCK_PORT, default 9099). The gateway is NOT needed — the governor never
10// touches it.
11import { open, shot } from './harness.mjs';
12
13const ok = [], bad = [];
14const check = (name, pass, detail) => {
15 (pass ? ok : bad).push(name);
16 console.log((pass ? ' ok ' : ' FAIL ') + name + (detail ? ' — ' + detail : ''));
17};
18
19const s = await open({ name: 'governor', signIn: true, connect: true });
20const { page } = s;
21
22// 1. The module and the ledger getter it depends on are both present.
23const present = await page.evaluate(() => ({
24 gov: !!window.DaimondGovernor,
25 samples: !!(window.DaimondLedger && typeof window.DaimondLedger.samples === 'function'),
26 assess: !!(window.DaimondGovernor && typeof window.DaimondGovernor.assessDispatch === 'function'),
27}));
28check('DaimondGovernor is loaded', present.gov);
29check('DaimondLedger.samples exists', present.samples);
30check('assessDispatch is exposed', present.assess);
31
32// 2. The live decision: a normal fan-out clears, a big one asks. This runs the
33// real module against the real (empty) ledger, so it exercises the fallback
34// baseline and the auto budget as they ship.
35const decision = await page.evaluate(() => ({
36 few: window.DaimondGovernor.assessDispatch(3),
37 many: window.DaimondGovernor.assessDispatch(60),
38}));
39check('a few agents clear silently in-page', decision.few && decision.few.needsConfirm === false,
40 'predicted ' + (decision.few && decision.few.predicted));
41check('a big fan-out needs confirming in-page', decision.many && decision.many.needsConfirm === true,
42 'predicted ' + (decision.many && decision.many.predicted));
43
44// 3. State escalates to amber after a synthetic burst. Feeding the real module
45// a run of costly turns at "now" should push the live rate well past the
46// fallback baseline.
47const level = await page.evaluate(() => {
48 const now = Date.now();
49 for (let i = 0; i < 8; i++) window.DaimondGovernor.observe({ t: now - i * 2000, u: 0.60 });
50 return window.DaimondGovernor.status().level;
51});
52check('a costly burst reads as amber (or tripped)', level === 'amber' || level === 'tripped', 'level ' + level);
53
54// 4. Setting a budget is honoured by the next decision.
55const budgeted = await page.evaluate(() => {
56 window.DaimondGovernor.setBudget(0.05); // a tiny pace budget
57 const a = window.DaimondGovernor.assessDispatch(1);
58 window.DaimondGovernor.setBudget(null); // back to auto
59 return a.needsConfirm;
60});
61check('a tiny user budget makes even one agent ask', budgeted === true);
62
63// 5. No console errors from the governor. The gateway is deliberately not run
64// in this minimal stack, so its proxied /api/ calls answer 502 — that noise
65// is expected and filtered; anything else is a real fault.
66const real = s.errs.filter(e => !/502|Bad Gateway|Failed to load resource/i.test(e));
67check('no governor-related console errors', real.length === 0, real.slice(0, 3).join(' | '));
68
69await shot(s, 'governor');
70await s.close();
71
72console.log('\n' + ok.length + ' ok, ' + bad.length + ' failed');
73process.exit(bad.length ? 1 : 0);