Files
documentation/scripts/sdlc-cycle.test.mjs
T
jarvis-at-skic 20e6f4899c
Build and publish Eldorado documentation / build (pull_request) Successful in 50s
docs: rename Target contributors to AI Agent
2026-10-05 19:51:04 +00:00

63 lines
3.4 KiB
JavaScript

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {readFileSync} from 'node:fs';
const read = p => readFileSync(p, 'utf8');
const stages = ['Scope', 'Architecture', 'UI/UX', 'Planning', 'Delivery', 'UAT', 'Security', 'Releases'];
test('Strategy opens at the canonical autonomous lifecycle', () => {
assert.match(read('sidebars/strategy.ts'), /strategySidebar: \['target-operating-model', 'roadmap'/);
assert.match(read('docs/strategy/target-operating-model.mdx'), /^sidebar_label: Target$/m);
for (const id of ['target-operating-model']) {
const page = read(`docs/strategy/${id}.mdx`);
const primary = page.split('<details>')[0];
assert(primary.includes('name="strategy-target"'));
assert(primary.includes('autonomous agent'));
assert(primary.includes('direct, guide and review'));
assert(primary.includes('Scope → Architecture → UI/UX → Planning → Delivery → UAT → Security → Releases → Scope'));
assert(primary.includes('human-controlled AI Agent'));
assert(!/code[ -]agent/i.test(page));
assert(primary.includes('TO-BE'));
assert(!/only routes|People authorize|independent gates protect release/.test(primary));
}
});
test('both target diagrams have eight stages, eight governed phases and eight human-controlled contributors', () => {
for (const suffix of ['', '-mobile']) {
const d = JSON.parse(read(`diagrams/strategy-target${suffix}.architecture.json`));
const ids = stages.map(label => d.components.find(n => n.label === label)?.id);
assert(ids.every(Boolean));
assert.equal(new Set(ids).size, 8);
const flow = d.connections.filter(e => ids.includes(e.from) && ids.includes(e.to));
assert.deepEqual(flow.map(e => [e.from, e.to]), ids.map((id, i) => [id, ids[(i + 1) % ids.length]]));
assert.match(flow.at(-1).label, /Repeat/);
assert(d.components.some(n => n.id === 'agent' && n.label === 'Autonomous agent' && n.sublabel === 'Human Controlled'));
assert(!d.components.some(n => n.id === 'humans' || n.label === 'Humans'));
assert(!d.connections.some(e => e.id === 'human-direction' || e.from === 'humans' || e.to === 'humans'));
assert.equal(d.connections.length, 24);
assert.deepEqual(d.connections.filter(e => e.from === 'agent').map(e => e.to), ids);
const contributors = d.components.filter(n => n.id.startsWith('code-'));
assert.equal(contributors.length, 8);
assert(contributors.every(n => n.label === 'AI Agent' && n.sublabel === 'Human-controlled'));
for (const id of ids) {
assert(d.connections.some(e => e.from === `code-${id}` && e.to === id && e.variant === 'dashed'));
assert(d.connections.some(e => e.from === 'agent' && e.to === id && e.variant === 'security'));
}
assert.equal(d.components.length, 17);
if (!suffix) {
const center = n => n.pos.map((v, i) => v + n.size[i] / 2);
const agent = center(d.components.find(n => n.id === 'agent'));
const phaseCenters = ids.map(id => center(d.components.find(n => n.id === id)));
for (const axis of [0, 1]) {
const values = phaseCenters.map(c => c[axis]);
assert.equal(agent[axis], (Math.min(...values) + Math.max(...values)) / 2);
}
for (const code of contributors) {
const phase = d.components.find(n => n.id === code.id.slice(5));
const distance = n => Math.hypot(...center(n).map((v, i) => v - agent[i]));
assert(distance(code) > distance(phase), `${code.id} is exterior`);
}
}
}
});