Unclaimed files left in the canonical checkout. Inventory: canonical-cleanup-inventory.md (commit-as-evidence groups). detect-secrets scan clean on 2026-11-02: hits are sha256 pins, git object ids, test sentinels already in tracked tests and unit-file lines.
62 lines
3.7 KiB
JavaScript
62 lines
3.7 KiB
JavaScript
// Row 149 probe (a), for sage-0650: when a merge-gate or security-reviewer turn ends and the runner's
|
|
// automatic RESULT reply is refused, what does the store gain, and does any of it reach the human's
|
|
// inbox or decision lists? Scratch store only, under TMPDIR. Mirrors runner.mjs:386-391.
|
|
import { mkdtempSync, rmSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
const R = '/home/jwoltje/dewey-scratch/r149/packages';
|
|
const { Store } = await import(`${R}/bus/src/store.mjs`);
|
|
const { Broker } = await import(`${R}/bus/src/broker.mjs`);
|
|
const { busBusiness } = await import(`${R}/bus/src/business.mjs`);
|
|
const { resolveInstance, validateBusinessDocument } = await import(`${R}/business/src/index.mjs`);
|
|
const { businessDoc, REPO_ROLES, systemFor } = await import(`${R}/business/tests/helpers.mjs`);
|
|
|
|
const root = mkdtempSync(join(tmpdir(), 'probe-149a-'));
|
|
const doc = businessDoc(root, 'demo');
|
|
doc.roles['merge-gate'] = { definition: 'merge-gate' };
|
|
doc.roles['security-reviewer'] = { definition: 'security-reviewer' };
|
|
const business = validateBusinessDocument(doc, join(root, 'businesses', 'demo.json'), { rolesDir: REPO_ROLES });
|
|
const resolved = {};
|
|
for (const i of Object.keys(business.roles)) resolved[i] = resolveInstance({ system: systemFor(root), business, instance: i });
|
|
const store = new Store(root);
|
|
const b = new Broker({ store, businesses: { demo: busBusiness(business, resolved) } });
|
|
const caps = {};
|
|
for (const role of ['merge-gate', 'security-reviewer', 'cto']) {
|
|
caps[role] = b.bindLaunch({ business: 'demo', role, run: `${role}-run`, harness: 'pi' });
|
|
b.request(caps[role], { verb: 'role.claim', args: {} });
|
|
}
|
|
const human = b.bindHuman({ business: 'demo', human: 'jason', via: 'cli', outsideAgent: true });
|
|
const tables = store.all("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").map((r) => r.name);
|
|
const counts = () => Object.fromEntries(tables.map((t) => [t, store.get(`SELECT count(*) n FROM "${t}"`).n]));
|
|
const humanViews = () => ({
|
|
inbox: b.request(human, { verb: 'inbox', args: {} }).length,
|
|
roles: b.request(human, { verb: 'decisions', args: { list: 'roles' } }).length,
|
|
recent: b.request(human, { verb: 'decisions', args: { list: 'recent' } }).length,
|
|
});
|
|
|
|
const out = { cases: [] };
|
|
for (const role of ['merge-gate', 'security-reviewer']) {
|
|
for (const [label, cap] of [['from cto', caps.cto], ['from human', human]]) {
|
|
b.request(cap, { verb: 'message.send', args: { to: role, body: `probe to ${role}` } });
|
|
const [m] = b.request(caps[role], { verb: 'message.receive', args: {} });
|
|
const before = counts(), seqBefore = store.get('SELECT max(seq) s FROM events').s ?? 0;
|
|
const viewsBefore = humanViews();
|
|
// The runner's try block: the reply, then message.read; the reply's refusal skips the read.
|
|
let reply = 'sent', read = 'not-run';
|
|
try {
|
|
b.request(caps[role], { verb: 'message.send', args: { to: m.from_role, body: 'turn answer', class: 'RESULT', in_reply_to: m.id } });
|
|
b.request(caps[role], { verb: 'message.read', args: { id: m.id } });
|
|
read = 'done';
|
|
} catch (e) { reply = e.code; }
|
|
const after = counts();
|
|
const grew = Object.fromEntries(tables.filter((t) => after[t] !== before[t]).map((t) => [t, after[t] - before[t]]));
|
|
const events = store.all('SELECT kind, actor_role, subject, body FROM events WHERE seq>?', seqBefore);
|
|
const again = b.request(caps[role], { verb: 'message.receive', args: {} }).length;
|
|
out.cases.push({ role, message: label, reply, read, grew, events, humanBefore: viewsBefore, humanAfter: humanViews(), redelivered: again });
|
|
}
|
|
}
|
|
out.decisionsTotal = store.get('SELECT count(*) n FROM decisions').n;
|
|
console.log(JSON.stringify(out, null, 1));
|
|
store.close();
|
|
rmSync(root, { recursive: true, force: true });
|