Compare commits

...
Author SHA1 Message Date
jarvis-at-skic 1de7d16d09 docs: start roadmap with code and process assessment
Build and publish Eldorado documentation / build (pull_request) Successful in 40s
2026-10-05 18:50:28 +00:00
jarvis-at-skic b679e6b2b5 Merge pull request 'docs: make Skills Measurement an adoption collection plan' (#22) from docs/skills-measurement-plan into main
Build and publish Eldorado documentation / build (push) Successful in 40s
2026-10-05 11:36:20 -07:00
9 changed files with 243 additions and 124 deletions

No files matched your search

@@ -2,7 +2,7 @@
"schema_version": 1, "schema_version": 1,
"diagram_type": "architecture", "diagram_type": "architecture",
"meta": { "meta": {
"title": "TO-BE: Evidence-gated rollout", "title": "Recommended roadmap: assess before adoption",
"output": "static/diagrams/strategy-roadmap-mobile/index.html", "output": "static/diagrams/strategy-roadmap-mobile/index.html",
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
@@ -11,10 +11,10 @@
}, },
"components": [ "components": [
{ {
"id": "foundation", "id": "assessment",
"type": "backend", "type": "backend",
"label": "1 \u00b7 Foundation", "label": "1 · Assess current state",
"sublabel": "People + data + baseline", "sublabel": "Code quality + delivery flow",
"pos": [ "pos": [
20, 20,
20 20
@@ -25,10 +25,10 @@
] ]
}, },
{ {
"id": "pilot", "id": "readiness",
"type": "backend", "type": "backend",
"label": "2 \u00b7 Skills pilot", "label": "2 · Improve readiness",
"sublabel": "Qualified, useful work", "sublabel": "Critical gaps + safe scope",
"pos": [ "pos": [
20, 20,
140 140
@@ -39,10 +39,10 @@
] ]
}, },
{ {
"id": "distribution", "id": "pilot",
"type": "backend", "type": "backend",
"label": "3 \u00b7 Distribution", "label": "3 · Bounded pilot",
"sublabel": "Revocation + recovery", "sublabel": "Compare accepted outcomes",
"pos": [ "pos": [
20, 20,
260 260
@@ -53,10 +53,10 @@
] ]
}, },
{ {
"id": "coordination", "id": "expansion",
"type": "backend", "type": "backend",
"label": "4 \u00b7 Coordination", "label": "4 · Expand on evidence",
"sublabel": "Human takeover proven", "sublabel": "Controls + support proven",
"pos": [ "pos": [
20, 20,
380 380
@@ -67,10 +67,10 @@
] ]
}, },
{ {
"id": "expansion", "id": "sustain",
"type": "backend", "type": "backend",
"label": "5 \u00b7 Departments", "label": "5 · Sustain & improve",
"sublabel": "Outcomes + cost + risk", "sublabel": "Monitor + reassess",
"pos": [ "pos": [
20, 20,
500 500
@@ -84,27 +84,27 @@
"connections": [ "connections": [
{ {
"id": "flow-0", "id": "flow-0",
"from": "foundation", "from": "assessment",
"to": "pilot", "to": "readiness",
"label": "Charter" "label": "Gaps"
}, },
{ {
"id": "flow-1", "id": "flow-1",
"from": "pilot", "from": "readiness",
"to": "distribution", "to": "pilot",
"label": "quality + coverage" "label": "Ready"
}, },
{ {
"id": "flow-2", "id": "flow-2",
"from": "distribution", "from": "pilot",
"to": "coordination", "to": "expansion",
"label": "Controls" "label": "Evidence"
}, },
{ {
"id": "flow-3", "id": "flow-3",
"from": "coordination", "from": "expansion",
"to": "expansion", "to": "sustain",
"label": "authority drills pass" "label": "Review"
} }
] ]
} }
+49 -49
View File
@@ -2,7 +2,7 @@
"schema_version": 1, "schema_version": 1,
"diagram_type": "architecture", "diagram_type": "architecture",
"meta": { "meta": {
"title": "TO-BE: Evidence-gated rollout", "title": "Recommended roadmap: assess before adoption",
"output": "static/diagrams/strategy-roadmap/index.html", "output": "static/diagrams/strategy-roadmap/index.html",
"quality_profile": "showcase", "quality_profile": "showcase",
"legend": { "legend": {
@@ -11,10 +11,10 @@
}, },
"components": [ "components": [
{ {
"id": "foundation", "id": "assessment",
"type": "backend", "type": "backend",
"label": "1 \u00b7 Foundation", "label": "1 · Assess current state",
"sublabel": "People + data + baseline", "sublabel": "Code quality + delivery flow",
"pos": [ "pos": [
20, 20,
20 20
@@ -24,41 +24,27 @@
60 60
] ]
}, },
{
"id": "readiness",
"type": "backend",
"label": "2 · Improve readiness",
"sublabel": "Critical gaps + safe scope",
"pos": [
260,
20
],
"size": [
180,
60
]
},
{ {
"id": "pilot", "id": "pilot",
"type": "backend", "type": "backend",
"label": "2 \u00b7 Skills pilot", "label": "3 · Bounded pilot",
"sublabel": "Qualified, useful work", "sublabel": "Compare accepted outcomes",
"pos": [ "pos": [
260, 260,
20
],
"size": [
180,
60
]
},
{
"id": "distribution",
"type": "backend",
"label": "3 \u00b7 Distribution",
"sublabel": "Revocation + recovery",
"pos": [
260,
150
],
"size": [
180,
60
]
},
{
"id": "coordination",
"type": "backend",
"label": "4 \u00b7 Coordination",
"sublabel": "Human takeover proven",
"pos": [
20,
150 150
], ],
"size": [ "size": [
@@ -69,8 +55,22 @@
{ {
"id": "expansion", "id": "expansion",
"type": "backend", "type": "backend",
"label": "5 \u00b7 Departments", "label": "4 · Expand on evidence",
"sublabel": "Outcomes + cost + risk", "sublabel": "Controls + support proven",
"pos": [
20,
150
],
"size": [
180,
60
]
},
{
"id": "sustain",
"type": "backend",
"label": "5 · Sustain & improve",
"sublabel": "Monitor + reassess",
"pos": [ "pos": [
20, 20,
280 280
@@ -84,27 +84,27 @@
"connections": [ "connections": [
{ {
"id": "flow-0", "id": "flow-0",
"from": "foundation", "from": "assessment",
"to": "pilot", "to": "readiness",
"label": "Charter" "label": "Gaps"
}, },
{ {
"id": "flow-1", "id": "flow-1",
"from": "pilot", "from": "readiness",
"to": "distribution", "to": "pilot",
"label": "quality + coverage" "label": "Ready"
}, },
{ {
"id": "flow-2", "id": "flow-2",
"from": "distribution", "from": "pilot",
"to": "coordination", "to": "expansion",
"label": "Controls" "label": "Evidence"
}, },
{ {
"id": "flow-3", "id": "flow-3",
"from": "coordination", "from": "expansion",
"to": "expansion", "to": "sustain",
"label": "authority drills pass" "label": "Review"
} }
] ]
} }
+45 -41
View File
@@ -1,7 +1,7 @@
--- ---
id: roadmap id: roadmap
title: Roadmap title: Roadmap
description: Evidence-gated phases, no promised dates or budgets. description: Assess current code quality and delivery processes, close critical gaps, then pilot, expand and sustain AI adoption.
hide_table_of_contents: true hide_table_of_contents: true
--- ---
@@ -9,64 +9,68 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram';
<div className="strategy-content"> <div className="strategy-content">
**TO-BE · Target operating model — not installed controls or company results.** Understand today’s code and how work really reaches production before introducing AI into the workflow. Fix what would make a pilot unsafe or impossible to evaluate—not every item of technical debt.
## What must be true before widening the rollout? <ArchifyDiagram name="strategy-roadmap" title="Assess code and delivery, improve readiness, pilot, expand on evidence, then sustain" story />
Advance by exit evidence, not promised dates or usage volume. Each stage can hold, narrow or stop; changed client, data or authority boundaries reopen earlier gates. **Recommended sequence · Target operating model, not an approved schedule or deployed governance.**
<ArchifyDiagram name="strategy-roadmap" title="Foundation, pilot, reliable distribution, coordination and departmental expansion have exit gates" story /> ## 1. Understand code quality and delivery
- **Start bounded:** named people, lawful data handling and a reproducible baseline precede the pilot. Inspect representative repositories across important services and change types: tests and CI reliability, maintainability, technical debt and security findings. Trace recent changes through the actual SDLC with the people doing the work—from request to production and feedback. Check ownership, review and release practices, handoffs, rework and bottlenecks; do not assume the documented process is the real one.
- **Prove recovery before coordination:** verified versions, revocation and human takeover are prerequisites.
- **Expand by department:** accepted outcomes, guardrails, total cost and experience justify continuation; sensitive decisions remain human. **Output:** baseline findings, a process map and prioritized gaps. Use these to identify a low-risk, repeatable workflow with observable acceptance—not simply the easiest repository.
## 2. Fix critical readiness gaps
Resolve gaps that threaten safe execution or a trustworthy comparison: for example, exposed secrets, unclear approval authority or unreliable checks needed to accept the pilot’s changes. Establish accountable people, data boundaries and recovery for the selected scope. Broader refactoring and non-critical debt can run alongside the pilot with a separate improvement backlog.
**Output:** a readiness decision and bounded pilot charter. Proceed only when the critical gaps for that workflow are closed; otherwise narrow the scope or hold.
## 3. Run a bounded pilot
Try a small set of reviewed skills in the selected workflow, with human review and no new privileged autonomous actions. Compare equivalent work with the baseline: accepted outcomes, escaped defects, full cost and verification effort. [Skills Measurement](./measurement.mdx) explains what to collect, calculate and report; agree the comparison rules before starting.
**Output:** a pilot report and a continue, adjust or stop decision. Missing evidence is a reason to investigate, not proof of improvement.
## 4. Expand only on evidence
Extend to another workflow or team only when quality, usefulness, cost and support capacity justify it. Prove reliable skill distribution, revocation and recovery before expanding authority. Introduce autonomous SDLC execution progressively under human direction; new departmental workflows need their own data boundaries and acceptance evidence.
**Output:** an evidenced expansion decision with verified controls for the next scope—not organization-wide rollout by default.
## 5. Sustain and improve
Review outcomes, drift, incidents and maintenance effort. Retire ineffective skills, revisit process bottlenecks and repeat assessment when repositories, clients, data or authority change. Work toward [Target](./target-operating-model.mdx): an autonomous agent executes and governs the repeating SDLC while humans direct, guide and review.
**Output:** maintained skills, a refreshed improvement backlog and evidence for the next cycle. Keep human takeover available; narrow or stop workflows when evidence no longer supports them.
<details> <details>
<summary>Stage-by-stage entry evidence, work, exit gates and hold conditions</summary> <summary>Supporting gate evidence and hold conditions</summary>
**TO-BE · Target operating model.** Introduction depends on the [roadmap gates](./roadmap.mdx); these pages do not describe installed controls or measured company results. These are recommended implementation gates, not assigned human owners, approved thresholds or installed integrations. Agree acceptance criteria for each selected workflow before evaluating it.
### Foundation ### Assessment → readiness
**Entry evidence** — Strategy scope accepted for planning; existing teams identified. Retain the sampled repository revisions, test/CI results, debt and security findings, and traced changes behind the process map. Record coverage and unknowns. Distinguish critical pilot blockers from parallel improvements; hold selection if the sample cannot explain how the candidate workflow is delivered and accepted.
**Work** — Inventory actual client hosts/builds, provider/data terms, repositories, authority, owners and event availability; select low-risk workflows and metric definitions. ### Readiness → pilot
**Exit evidence and hold condition** — Named accountable people and independent reviewers, bounded pilot charter, forbidden actions, data/retention decision and reproducible baseline plan. Hold if accountability or lawful collection is unresolved. Inventory actual client hosts/builds, provider/data terms, authority and event availability. Confirm accountable people and independent reviewers, forbidden actions, data/retention decisions, recovery and a reproducible baseline. Hold if accountability, lawful collection or critical acceptance checks remain unresolved.
### Governed skills pilot ### Pilot → expansion
**Entry evidence** — Foundation evidence approved; no privileged autonomous effects. Use a small registry, immutable skill contracts, qualified client adapters, evaluations and coaching. Verify the measurement calculations with synthetic fixtures before interpreting real outcomes. Require mandatory safety checks, independent task acceptance, reconciled source coverage and user feedback. Hold or narrow scope if quality or coverage is inadequate; usage alone does not justify expansion.
**Work** — Build a small registry, immutable contract, client adapters, evaluations, coaching and synthetic measurement verification. ### Expansion → wider authority
**Exit evidence and hold condition** — Qualified client/skill tuples, mandatory safety checks, independent task acceptance, reconciled coverage and user feedback. Hold or narrow scope if quality or data coverage is inadequate. Prove canary updates, effective-version readback, version locking, exception expiry, stale/offline handling, rollback and revocation. Hold if effective versions or controls cannot be verified or the catalog cannot be supported.
### Reliable distribution For autonomous execution, begin with observation and evidence assembly, then proposing and routing work, before granting scoped execution authority. Recommended controls include exact-artifact approvals, idempotency, duplicate/outage recovery, separation of duties, audit and kill-switch drills. Prove human takeover; never infer permission from missing evidence. The agent ultimately executes and governs the cycle, not only routes tasks.
**Entry evidence** — Pilot quality and usefulness support continuing. ### Sustained operation
**Work** — Canary updates, effective-version readback, version locking, exception expiry, stale/offline handling and rollback. Operations, Marketing, Finance & Accounting and HR & Administration workflows each need a workflow owner, outcome, data boundary, capacity and domain-specific review; Product and Technology continue quality improvement. Keep sensitive decisions human. Use accepted outcomes, guardrails, total cost and experience to continue, narrow, stop or roll back. Changed client, provider, data or authority boundaries reopen the relevant gates.
**Exit evidence and hold condition** — Tested revocation and recovery, no bypass of central privileged gates, owners can support the catalog. Hold if effective versions or controls cannot be verified.
### Logical SDLC coordination
**Entry evidence** — Distribution, authority and measurement evidence stable.
**Work** — Observe and assemble evidence first, then propose and route work within scoped identities and budgets.
**Exit evidence and hold condition** — Exact-artifact approvals, idempotency, duplicate/outage recovery, separation of duties, audit and kill-switch drills pass; humans can take over. No authority expansion based on usage alone.
### Departmental expansion
**Entry evidence** — Each department supplies a workflow owner, outcome, data boundary and capacity.
**Work** — Add Operations, Marketing, Finance & Accounting and HR & Administration workflows with domain-specific review; Product and Technology continue quality improvement.
**Exit evidence and hold condition** — Departmental accepted outcomes, guardrails, total cost and experience justify continuation; sensitive decisions stay human. Stop or roll back workflows without adequate evidence.
There are no invented launch dates, budgets, staffing commitments or guaranteed gains. Phase gates permit narrowing or stopping. Re-evaluate earlier phases when the underlying client, provider, data scope or authority changes.
</details> </details>
+1 -1
View File
@@ -15,7 +15,7 @@
"verify:build": "node scripts/verify.mjs --build", "verify:build": "node scripts/verify.mjs --build",
"diagrams:build": "node scripts/build-diagrams.mjs", "diagrams:build": "node scripts/build-diagrams.mjs",
"test": "node --test scripts/*.test.mjs", "test": "node --test scripts/*.test.mjs",
"test:browser": "node scripts/browser/strategy-story.cjs && node scripts/browser/inline-controls.cjs && node scripts/browser/sdlc-cycle.cjs && node scripts/browser/skills-measurement.cjs", "test:browser": "node scripts/browser/strategy-story.cjs && node scripts/browser/inline-controls.cjs && node scripts/browser/sdlc-cycle.cjs && node scripts/browser/skills-measurement.cjs && node scripts/browser/roadmap.cjs",
"kpi:example": "node scripts/ai-kpi.mjs" "kpi:example": "node scripts/ai-kpi.mjs"
}, },
"dependencies": { "dependencies": {
+1 -1
View File
@@ -61,7 +61,7 @@
{ {
"id": "roadmap", "id": "roadmap",
"title": "Roadmap", "title": "Roadmap",
"purpose": "Evidence-gated phases, no promised dates or budgets." "purpose": "Assess current code quality and delivery processes, close critical gaps, then pilot, expand and sustain AI adoption."
} }
], ],
"diagram": { "diagram": {
+86
View File
@@ -0,0 +1,86 @@
const {chromium} = require('playwright');
const assert = require('node:assert/strict');
const fs = require('node:fs');
(async () => {
const base = process.argv[2] || 'http://127.0.0.1:4173';
const output = `.cache/roadmap-${process.argv[3] || 'local'}`;
fs.mkdirSync(output, {recursive:true});
const browser = await chromium.launch({headless:true, executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE, args:['--no-sandbox']});
const results = [];
try {
for (const width of [1440, 390, 320]) {
const context = await browser.newContext({viewport:{width,height:1000}, colorScheme:'light'});
const page = await context.newPage();
const errors = [];
page.on('pageerror', error => errors.push(error.message));
const response = await page.goto(`${base}/eldorado-v1/documentation/strategy/roadmap/`, {waitUntil:'networkidle'});
assert.equal(response.status(), 200);
assert.equal(await page.locator('h1').innerText(), 'Roadmap');
const headings = page.locator('.strategy-content > h2');
assert.deepEqual((await headings.allTextContents()).map(s => s.replace(/\u200b/g, '')), ['1. Understand code quality and delivery','2. Fix critical readiness gaps','3. Run a bounded pilot','4. Expand only on evidence','5. Sustain and improve']);
const text = await page.locator('.strategy-content').innerText();
for (const marker of ['baseline findings', 'process map', 'prioritized gaps', 'alongside the pilot', 'Recommended sequence']) assert(text.includes(marker), marker);
assert(!text.includes('Supporting gate evidence and hold conditions\n\nThese are'));
if (width < 700) await page.getByRole('button', {name:'Toggle navigation bar'}).click();
const menu = page.locator('.theme-doc-sidebar-menu .menu__link').filter({visible:true});
await menu.first().waitFor({state:'visible'});
assert.deepEqual((await menu.allTextContents()).slice(0,2), ['Target','Roadmap']);
if (width < 700) await page.getByRole('button', {name:'Close navigation bar'}).click();
const panel = page.locator('.archify-panel--story');
const iframe = panel.locator(width > 700 ? '.story-desktop' : '.story-mobile');
await iframe.scrollIntoViewIfNeeded();
const frame = await (await iframe.elementHandle()).contentFrame();
await frame.locator('svg[role="img"]').waitFor();
const geometry = await frame.locator('svg[role="img"]').evaluate(svg => ({
nodes:[...svg.querySelectorAll('[data-node-id]')].map(n => ({id:n.dataset.nodeId,...n.getBoundingClientRect().toJSON()})),
width:innerWidth, height:innerHeight,
minLabel:Math.min(...[...svg.querySelectorAll('text[data-node-label]')].map(n => parseFloat(getComputedStyle(n).fontSize)*n.getScreenCTM().a))
}));
assert.deepEqual(geometry.nodes.map(n => n.id), ['assessment','readiness','pilot','expansion','sustain']);
for (const n of geometry.nodes) assert(n.x >= 0 && n.y >= 0 && n.right <= geometry.width + 1 && n.bottom <= geometry.height + 1);
assert(geometry.minLabel >= 10, `readable node labels: ${geometry.minLabel}`);
await frame.locator('#btn-theme').click();
await page.waitForFunction(() => document.documentElement.dataset.theme === 'dark');
await frame.locator('#btn-theme').click();
await page.waitForFunction(() => document.documentElement.dataset.theme === 'light');
for (const preset of ['blueprint','classic']) {
await frame.locator('#btn-preset').click();
await frame.locator(`[data-preset-value="${preset}"]`).click();
assert.equal(await frame.locator('html').getAttribute('data-preset'), preset);
}
await frame.locator('#btn-export').click();
const [download] = await Promise.all([page.waitForEvent('download'), frame.locator('[data-format="svg"]').click()]);
assert.equal(await download.failure(), null);
await download.saveAs(`${output}/${width}.svg`);
assert(fs.readFileSync(`${output}/${width}.svg`, 'utf8').includes('Assess current state'));
const opener = panel.getByRole('button', {name:/^Expand /});
await opener.click();
const close = panel.getByRole('button', {name:'Close full-screen diagram', exact:true});
await close.waitFor({state:'visible'}); assert.equal(await close.innerText(), '×');
await close.click(); assert(await opener.evaluate(n => n === document.activeElement));
await opener.click(); await close.waitFor({state:'visible'}); await page.keyboard.press('Escape');
await page.waitForFunction(() => !document.querySelector('.archify-panel--story dialog').open);
assert(await opener.evaluate(n => n === document.activeElement));
assert(!await page.evaluate(() => document.documentElement.scrollWidth > innerWidth));
await page.evaluate(() => scrollTo({top:0, behavior:'instant'}));
await page.screenshot({path:`${output}/${width}-top.png`});
await headings.first().scrollIntoViewIfNeeded();
await page.screenshot({path:`${output}/${width}-assessment.png`});
await page.screenshot({path:`${output}/${width}-full.png`, fullPage:true});
await page.locator('.strategy-content summary').click();
assert(await page.locator('.strategy-content details').evaluate(n => n.open));
await page.locator('.strategy-content details p').last().waitFor({state:'visible'});
assert((await page.locator('.strategy-content details').innerText()).includes('exact-artifact approvals'));
const links = await page.locator('.strategy-content a').evaluateAll(nodes => nodes.filter(n => !n.classList.contains('hash-link')).map(n => n.href));
for (const href of [...new Set(links)]) {
const r = await page.goto(href, {waitUntil:'networkidle'}); assert.equal(r.status(), 200);
assert.equal(page.url(), href);
}
assert.deepEqual(errors, []);
results.push({width, geometry, links:links.length, controls:true, export:true, sidebar:true, visibleAssessment:true});
fs.writeFileSync(`${output}/results.json`, JSON.stringify(results,null,2));
await context.close();
}
console.log(`PASS ${results.length} Roadmap viewports: visible stages/outputs, sidebar, diagram geometry, controls, export and links`);
} finally {await browser.close();}
})().catch(error => {console.error(error); process.exitCode = 1;});
+1 -1
View File
@@ -22,7 +22,7 @@ const fs=require('node:fs');
assert(geometry.nodes.length>=5 && geometry.nodes.length<=(['index','target-operating-model'].includes(id)?18:7),id); assert(geometry.nodes.length>=5 && geometry.nodes.length<=(['index','target-operating-model'].includes(id)?18:7),id);
for(const n of geometry.nodes) assert(n.x>=0 && n.y>=0 && n.right<=geometry.width+1 && n.bottom<=geometry.height+1,`${id} ${width} clipped ${JSON.stringify(n)} / ${geometry.height}`); for(const n of geometry.nodes) assert(n.x>=0 && n.y>=0 && n.right<=geometry.width+1 && n.bottom<=geometry.height+1,`${id} ${width} clipped ${JSON.stringify(n)} / ${geometry.height}`);
const data=await page.locator('.strategy-content').evaluate(el=>({words:el.innerText.trim().split(/\s+/).length,overflow:document.documentElement.scrollWidth>innerWidth,openDetails:el.querySelectorAll('details[open]').length})); const data=await page.locator('.strategy-content').evaluate(el=>({words:el.innerText.trim().split(/\s+/).length,overflow:document.documentElement.scrollWidth>innerWidth,openDetails:el.querySelectorAll('details[open]').length}));
assert(data.words<=(id==='measurement'?1100:200),id);assert(!data.overflow,id);assert.equal(data.openDetails,0,id); assert(data.words<=(id==='measurement'?1100:id==='roadmap'?600:200),id);assert(!data.overflow,id);assert.equal(data.openDetails,0,id);
await page.evaluate(()=>scrollTo({top:0,behavior:'instant'}));await page.screenshot({path:`.cache/story-${label}/${width}-${id}.png`,fullPage:true}); await page.evaluate(()=>scrollTo({top:0,behavior:'instant'}));await page.screenshot({path:`.cache/story-${label}/${width}-${id}.png`,fullPage:true});
const opener=panel.getByRole('button',{name:/^Expand /});await opener.click(); const opener=panel.getByRole('button',{name:/^Expand /});await opener.click();
const close=panel.getByRole('button',{name:'Close full-screen diagram',exact:true});await close.waitFor({state:'visible'}); const close=panel.getByRole('button',{name:'Close full-screen diagram',exact:true});await close.waitFor({state:'visible'});
+29
View File
@@ -0,0 +1,29 @@
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {readFileSync} from 'node:fs';
const read = path => readFileSync(path, 'utf8');
test('Roadmap visibly assesses code and real delivery before adoption', () => {
const page = read('docs/strategy/roadmap.mdx');
const visible = page.split('<details>')[0];
const headings = [...visible.matchAll(/^## (.+)$/gm)].map(match => match[1]);
assert.deepEqual(headings, ['1. Understand code quality and delivery', '2. Fix critical readiness gaps', '3. Run a bounded pilot', '4. Expand only on evidence', '5. Sustain and improve']);
assert(visible.indexOf(' story />') < visible.indexOf('## 1.'));
for (const marker of ['representative repositories', 'tests and CI', 'maintainability', 'technical debt', 'security findings', 'actual SDLC', 'ownership', 'review and release', 'bottlenecks', 'baseline findings', 'process map', 'prioritized gaps', 'alongside the pilot', './measurement.mdx', './target-operating-model.mdx']) assert(visible.includes(marker), marker);
assert.equal((visible.match(/\*\*Output:/g) || []).length, 5);
assert.match(visible, /Recommended sequence/);
assert(!page.includes('### Foundation'));
for (const marker of ['revocation', 'exact-artifact approvals', 'idempotency', 'human takeover', 'sensitive decisions']) assert(page.includes(marker), marker);
});
test('both roadmap diagrams make assessment and readiness prerequisites to the pilot', () => {
const ids = ['assessment', 'readiness', 'pilot', 'expansion', 'sustain'];
for (const suffix of ['', '-mobile']) {
const diagram = JSON.parse(read(`diagrams/strategy-roadmap${suffix}.architecture.json`));
assert.deepEqual(diagram.components.map(n => n.id), ids);
assert.deepEqual(diagram.connections.map(e => [e.from,e.to]), ids.slice(1).map((id, i) => [ids[i],id]));
assert.match(diagram.components[0].sublabel, /Code quality \+ delivery flow/);
assert.match(diagram.components[1].sublabel, /Critical gaps/);
assert.match(diagram.components[4].label, /Sustain/);
}
});
+2 -2
View File
@@ -13,12 +13,12 @@ test('every strategy page leads with a compact diagram story and closes its refe
assert(!page.includes('<details>') || page.indexOf(' story />') < page.indexOf('<details>'), id); assert(!page.includes('<details>') || page.indexOf(' story />') < page.indexOf('<details>'), id);
assert(!/<details\s+open/.test(page), id); assert(!/<details\s+open/.test(page), id);
assert.equal((page.match(/<details>/g) || []).length, (page.match(/<\/details>/g) || []).length, id); assert.equal((page.match(/<details>/g) || []).length, (page.match(/<\/details>/g) || []).length, id);
assert.equal((narrative.match(/^## /gm) || []).length, id === 'measurement' ? 4 : 1, id); assert.equal((narrative.match(/^## /gm) || []).length, id === 'measurement' ? 4 : id === 'roadmap' ? 5 : 1, id);
assert((narrative.match(/^- /gm) || []).length <= 3, id); assert((narrative.match(/^- /gm) || []).length <= 3, id);
assert(narrative.includes('**Next:**'), id); assert(narrative.includes('**Next:**'), id);
assert(!narrative.includes('| ---'), id); assert(!narrative.includes('| ---'), id);
const words = narrative.replace(/<[^>]*>/g, '').trim().split(/\s+/).length; const words = narrative.replace(/<[^>]*>/g, '').trim().split(/\s+/).length;
assert(words <= (id === 'measurement' ? 1100 : 200), `${id}: ${words} default narrative words`); assert(words <= (id === 'measurement' ? 1100 : id === 'roadmap' ? 600 : 200), `${id}: ${words} default narrative words`);
} }
}); });