48 lines
3.2 KiB
JavaScript
48 lines
3.2 KiB
JavaScript
import { mkdtempSync, rmSync, writeFileSync, readFileSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { execFileSync } from 'node:child_process';
|
|
import { Store } from '../src/store.mjs';
|
|
import { Broker } from '../src/broker.mjs';
|
|
import { initProject, readSpec, writeRecord, listProjectFiles, readProjectFile, writeHumanFile, ProjectError } from '../../project/src/index.mjs';
|
|
export const git = (repo, ...args) => execFileSync('git', ['-c', 'core.hooksPath=/dev/null', '-c', 'maintenance.auto=false', '-c', 'gc.auto=0', '-C', repo, ...args], { encoding: 'utf8' }).trim();
|
|
const options = [{ key: 'yes', text: 'Yes' }, { key: 'no', text: 'No' }];
|
|
export async function fixture(t, { adapter = true, roles = {}, arbiters = { technical: 'chief', delivery: 'chief' }, access = null, autonomyHost = null } = {}) {
|
|
const root = mkdtempSync(join(tmpdir(), 'bus-spec-'));
|
|
const store = new Store(root);
|
|
t.after(() => { store.close(); rmSync(root, { recursive: true, force: true }); });
|
|
const authority = grants => ({ withinRole: grants, crossRole: [] });
|
|
const business = { id: 'demo', human: 'jason', arbiters,
|
|
projects: { stack: { root: join(root, 'code'), repo: join(root, 'records') } }, roles: {
|
|
coder: { definition: 'coder', authority: authority(['message.send', 'record.write']) },
|
|
reviewer: { definition: 'reviewer', authority: authority(['message.send']) },
|
|
chief: { definition: 'chief-of-staff', authority: authority(['message.send', 'decision.resolve.technical', 'decision.resolve.delivery']) },
|
|
...roles,
|
|
} };
|
|
const { repo, commit } = await initProject({ business, project: 'stack', dataRoot: root });
|
|
const broker = new Broker({ store, businesses: { demo: business }, access, autonomy: autonomyHost, project: adapter ? {
|
|
readSpec: context => readSpec({ ...context, dataRoot: root }),
|
|
writeRecord: context => writeRecord({ ...context, dataRoot: root }),
|
|
listFiles: context => listProjectFiles({ ...context, dataRoot: root }),
|
|
readFile: context => readProjectFile({ ...context, dataRoot: root }),
|
|
writeFile: context => writeHumanFile({ ...context, dataRoot: root }),
|
|
ProjectError,
|
|
} : null });
|
|
const agent = role => {
|
|
const cap = broker.bindLaunch({ business: 'demo', role, run: role + '-run', harness: 'pi', address: role });
|
|
broker.request(cap, { verb: 'role.claim' }); return cap;
|
|
};
|
|
const coder = agent('coder'), reviewer = agent('reviewer'), chief = agent('chief');
|
|
const human = broker.bindHuman({ business: 'demo', human: 'jason', via: 'cli', outsideAgent: true });
|
|
const call = (cap, verb, args = {}) => broker.request(cap, { verb, args });
|
|
const raise = args => call(coder, 'decision.raise', { action: 'deploy', question: 'Ship?', options,
|
|
recommendation: 'yes', blocking: false, ...args });
|
|
const save = (content, author = 'jason') => {
|
|
writeFileSync(join(repo, 'spec/north-star.md'), content);
|
|
git(repo, 'add', '--', 'spec/north-star.md');
|
|
git(repo, '-c', `user.name=${author}`, '-c', '[email protected]', 'commit', '-m', 'Spec');
|
|
return git(repo, 'rev-parse', 'HEAD');
|
|
};
|
|
return { root, store, business, broker, repo, commit, agent, coder, reviewer, chief, human, call, raise, save };
|
|
}
|