// E7: exercise startBroker's real live readRaw adapter, rather than replacing the library adapter. import test from 'node:test'; import assert from 'node:assert/strict'; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { startBroker } from '../src/runtime.mjs'; import { validateBusinessDocument } from '../../organization/src/organization-config.mjs'; import { businessDoc, rolesCopy, systemFor, writeJson } from '../../organization/tests/helpers.mjs'; import { mappingEntry } from '../../library/tests/helpers.mjs'; test('C2-06 runtime reads changed and unreadable reply limits without restarting', async t => { const root = mkdtempSync(join(tmpdir(), 'citation-runtime-')); t.after(() => rmSync(root, { recursive: true, force: true })); const doc = businessDoc(root), rolesDir = rolesCopy(root), dir = join(root, 'config'), dataRoot = join(root, 'data'); doc.projects.books = mappingEntry(); doc.roles.chief.credentials = { gitea: { ...doc.roles.coder.credentials.gitea } }; doc.replyLimits = { requireCitation: false, citationsPerReply: 3 }; const file = writeJson(join(dir, 'businesses/acme.json'), doc); const checked = validateBusinessDocument(doc, file, { rolesDir }); mkdirSync(dataRoot, { mode: 0o700 }); // Runtime takes the host's broker projection, not the business validator's unresolved role entries. // No agent action is needed here: use the same empty-authority shape as limits-runtime.test.mjs. const business = { id: 'acme', human: 'jason', projects: checked.projects, arbiters: { technical: 'chief', delivery: 'chief' }, roles: {chief: { definition: 'chief-of-staff', authority: { withinRole: ['decision.resolve.technical', 'decision.resolve.delivery'], crossRole: [] } }, coder: { definition: 'coder', authority: { withinRole: [], crossRole: [] } } } }; const runtime = await startBroker({ dataRoot, businesses: { acme: business }, organization: { dir, rolesDir, system: systemFor(root) } }); t.after(() => runtime.close()); const human = runtime.broker.bindHuman({ business: 'acme', human: 'jason', via: 'cli', outsideAgent: true }); const status = () => runtime.broker.request(human, { verb: 'library.status', args: { project: 'books' } }); assert.deepEqual((await status()).replyLimits, { requireCitation: false, citationsPerReply: 3, fallback: [], problem: null }); doc.replyLimits = { requireCitation: true, citationsPerReply: 7 }; writeJson(file, doc); assert.deepEqual((await status()).replyLimits, { requireCitation: true, citationsPerReply: 7, fallback: [], problem: null }); writeFileSync(file, '{broken'); assert.deepEqual((await status()).replyLimits, { requireCitation: true, citationsPerReply: 20, fallback: [], problem: 'reply-limits-unreadable' }); rmSync(file); assert.equal((await status()).replyLimits.problem, 'reply-limits-unreadable'); });