docs: [verified] separate Measurement registry and workflow Baseline
Build and publish Eldorado documentation / build (pull_request) Successful in 46s
Build and publish Eldorado documentation / build (pull_request) Successful in 46s
This commit is contained in:
1 parent
c4b4c38e62
commit
abe00994a1
30 files changed
+961
-548
No files matched your search
@@ -0,0 +1,34 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {readFileSync} from 'node:fs';
|
||||
const read = path => readFileSync(path, 'utf8');
|
||||
|
||||
test('Baseline is workflow-scoped, evidence-bound and distinct from the optional registry', () => {
|
||||
const page = read('docs/strategy/baseline.mdx');
|
||||
for (const heading of ['Understand the current workflow','Select relevant metrics, with reasons','Agree feasible evidence','Record the starting position','Keep later evaluation comparable']) assert(page.includes(`## ${heading}`));
|
||||
for (const text of ['not a mandatory company-wide baseline','no actual baseline values or approved thresholds','lawful basis','privacy','retention','source coverage','**Available:**','**Unavailable:**','not causal ROI','selected-but-unavailable']) assert(page.includes(text), text);
|
||||
assert(page.indexOf('<ArchifyDiagram') < page.indexOf('## Understand'));
|
||||
assert(!page.includes('25%'));
|
||||
for (const doc of ['measurement/index','measurement/collection-and-safeguards','skills-adoption','skills-maintenance','skills-governance']) assert(page.includes(`./${doc}.mdx`));
|
||||
const registry = read('docs/strategy/measurement/index.mdx');
|
||||
assert(registry.includes('pagination_next: baseline'));
|
||||
assert(page.includes('pagination_prev: measurement/index'));
|
||||
assert(page.includes('pagination_next: skills-governance'));
|
||||
});
|
||||
|
||||
test('workflow application has one home and shared safety remains explicit', () => {
|
||||
const registry = read('docs/strategy/measurement/index.mdx');
|
||||
const shared = read('docs/strategy/measurement/collection-and-safeguards.mdx');
|
||||
const adoption = read('docs/strategy/skills-adoption.mdx');
|
||||
const maintenance = read('docs/strategy/skills-maintenance.mdx');
|
||||
assert(!registry.includes('Measure the pilot'));
|
||||
assert(!shared.includes('Track all five'));
|
||||
assert(!shared.includes('Before a pilot, freeze'));
|
||||
assert(shared.includes('id') && shared.includes('{#baseline-and-interpretation}')); // Existing inbound anchor survives relocation.
|
||||
for (const marker of ['transport retries','quarantined','Late arrivals','Unknown version stays null','30 days','12 months','below five people','No raw prompts','Consent is not presumed']) assert(shared.includes(marker),marker);
|
||||
assert(adoption.includes('not a mandatory pilot bundle'));
|
||||
assert(adoption.includes('What a pilot report looks like'));
|
||||
assert(maintenance.includes('Keep selected evidence useful'));
|
||||
assert(maintenance.includes('versioned corrections'));
|
||||
assert(adoption.includes('**Next:** [Maintain skills using the agreed evidence →](./skills-maintenance.mdx)'));
|
||||
});
|
||||
@@ -7,7 +7,7 @@ const assert=require('node:assert/strict');
|
||||
const browser=await chromium.launch({executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,args:['--no-sandbox']});
|
||||
const results=[];
|
||||
try {
|
||||
for(const topic of ['governance','quality','adoption','measurement','maintenance']) for(const width of [1440,1024,390,320]){
|
||||
for(const topic of ['measurement','baseline','governance','quality','adoption','maintenance']) for(const width of [1440,1024,390,320]){
|
||||
const spec=JSON.parse(fs.readFileSync(`diagrams/strategy-${topic}${width<=1100?'-mobile':''}.architecture.json`));
|
||||
const page=await browser.newPage({viewport:{width:1200,height:1000}});
|
||||
await page.goto('file://'+path.resolve(`${dir}/${topic}-${width}.svg`));
|
||||
@@ -33,7 +33,10 @@ const assert=require('node:assert/strict');
|
||||
assert.deepEqual(measured.labelOverlaps,[],`${topic}-${width}: rendered edge labels overlap`);
|
||||
for(const n of spec.components){assert(measured.text.includes(n.label));assert(measured.text.includes(n.tag));for(const line of n.sublabel.split('\n'))assert(measured.text.includes(line));}
|
||||
for(const e of spec.connections)if(e.label)assert(measured.text.includes(e.label));
|
||||
if(width===1440)await page.screenshot({path:`${dir}/${topic}-standalone-export.png`});
|
||||
if(width===1440){
|
||||
await page.setViewportSize({width:spec.meta.viewBox[0],height:spec.meta.viewBox[1]});
|
||||
await page.screenshot({path:`${dir}/${topic}-standalone-export.png`});
|
||||
}
|
||||
results.push({topic,width,nodes:measured.nodes.length,edges:measured.edges.length,complete:true});await page.close();
|
||||
}
|
||||
fs.writeFileSync(`${dir}/export-results.json`,JSON.stringify(results,null,2));
|
||||
|
||||
@@ -18,12 +18,12 @@ const fs = require('node:fs');
|
||||
assert.equal(await page.locator('h1').innerText(), 'Skills Measurement');
|
||||
assert((await page.title()).startsWith('Skills Measurement |'));
|
||||
assert.equal(await page.locator('.strategy-content details').count(), 0);
|
||||
assert.equal(await page.locator('.strategy-content h2').count(), 5);
|
||||
assert.equal(await page.locator('.strategy-content h2').count(), 2);
|
||||
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'});
|
||||
const metrics = JSON.parse(fs.readFileSync('research/ai-adoption/measurement-migration.json','utf8')).metrics;
|
||||
assert.deepEqual(await menu.allTextContents(), ['Target','Roadmap','Stage - 01 - Skills Adoption','Governance','Quality','Adoption','Measurement',...metrics.map(m => m.title),'Collection and safeguards','Run the synthetic measurement example','Maintenance','Stage - 02 - Autonomous Agent']);
|
||||
assert.deepEqual(await menu.allTextContents(), ['Target','Roadmap','Stage - 01 - Skills Adoption','Measurement',...metrics.map(m => m.title),'Collection and safeguards','Run the synthetic measurement example','Baseline','Governance','Quality','Adoption','Maintenance','Stage - 02 - Autonomous Agent']);
|
||||
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');
|
||||
@@ -51,7 +51,7 @@ const fs = require('node:fs');
|
||||
assert.equal(await download.failure(), null);
|
||||
const path = `${output}/${width}.svg`; await download.saveAs(path);
|
||||
const svg = fs.readFileSync(path, 'utf8');
|
||||
assert(svg.includes('Compare with baseline') && svg.includes('Zero denominator = N/A'));
|
||||
assert(svg.includes('Available choices') && svg.includes('No mandatory collection'));
|
||||
const opener = panel.getByRole('button', {name:/^Expand /});
|
||||
await opener.click();
|
||||
const close = panel.getByRole('button', {name:'Close full-screen diagram', exact:true});
|
||||
@@ -80,6 +80,6 @@ const fs = require('node:fs');
|
||||
fs.writeFileSync(`${output}/results.json`, JSON.stringify(results,null,2));
|
||||
await context.close();
|
||||
}
|
||||
console.log(`PASS ${results.length} Skills Measurement viewports: title/sidebar, open plan, diagram geometry/controls/export, all reference links and no page errors`);
|
||||
console.log(`PASS ${results.length} Skills Measurement viewports: title/sidebar, optional registry, diagram geometry/controls/export, all reference links and no page errors`);
|
||||
} finally {await browser.close();}
|
||||
})().catch(error => {console.error(error); process.exitCode = 1;});
|
||||
@@ -6,13 +6,23 @@ const assert=require('node:assert/strict');
|
||||
const out=`.cache/skills-${process.argv[3]||'candidate'}`;fs.mkdirSync(out,{recursive:true});
|
||||
const browser=await chromium.launch({executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE,args:['--no-sandbox']}); const results=[];
|
||||
try {
|
||||
for(const topic of ['governance','quality','adoption','measurement','maintenance']) for(const width of [1440,1024,390,320]) {
|
||||
for(const topic of ['measurement','baseline','governance','quality','adoption','maintenance']) for(const width of [1440,1024,390,320]) {
|
||||
console.log(`Checking ${topic} at ${width}px`);
|
||||
const page=await browser.newPage({viewport:{width,height:900},colorScheme:'light'});const errors=[];page.on('pageerror',e=>errors.push(e.message));
|
||||
const route=topic==='measurement'?topic:`skills-${topic}`;
|
||||
const route=['measurement','baseline'].includes(topic)?topic:`skills-${topic}`;
|
||||
assert.equal((await page.goto(`${base}/eldorado-v1/documentation/strategy/${route}/`,{waitUntil:'networkidle'})).status(),200);
|
||||
const panel=page.locator('.archify-panel--skills');assert.equal(await panel.count(),1);
|
||||
const iframe=panel.locator(width>1100?'.story-desktop':'.story-mobile');await iframe.scrollIntoViewIfNeeded();
|
||||
const frame=await(await iframe.elementHandle()).contentFrame();await frame.locator('svg[role="img"]').waitFor();
|
||||
// Keep iframe controls below the fixed portal header. Frame-local click
|
||||
// actionability cannot detect an overlay in the parent document.
|
||||
const showControls=async()=>{
|
||||
await panel.locator('dialog iframe').waitFor({state:'detached'});
|
||||
await panel.evaluate(n=>{
|
||||
scrollTo({top:n.getBoundingClientRect().top+scrollY-100,behavior:'instant'});
|
||||
return new Promise(resolve=>requestAnimationFrame(()=>requestAnimationFrame(resolve)));
|
||||
});
|
||||
};
|
||||
const geometry=await frame.locator('svg[role="img"]').evaluate(svg=>{
|
||||
const nodes=[...svg.querySelectorAll('g[data-node-id]')];const issues=[];let min=Infinity;
|
||||
for(const n of nodes){const rect=n.querySelector('rect').getBBox();for(const t of n.querySelectorAll('text')){
|
||||
@@ -24,8 +34,9 @@ const assert=require('node:assert/strict');
|
||||
const source=JSON.parse(fs.readFileSync(`diagrams/strategy-${topic}.architecture.json`));
|
||||
assert.equal(geometry.nodes,source.components.length);assert.deepEqual(geometry.issues,[]);assert(geometry.min>=10,JSON.stringify(geometry));
|
||||
for(const theme of ['light','dark']){
|
||||
await showControls();
|
||||
if(await frame.locator('html').getAttribute('data-theme')!==theme)await frame.locator('#btn-theme').click();
|
||||
await page.waitForFunction(t=>document.documentElement.dataset.theme===t,theme);
|
||||
await page.waitForFunction(t=>document.documentElement.dataset.theme===t,theme).catch(error=>{throw new Error(`${topic}/${width}/${theme}: theme synchronization failed`,{cause:error});});
|
||||
await panel.scrollIntoViewIfNeeded();await page.screenshot({path:`${out}/${topic}-${width}-${theme}-inline.png`});
|
||||
const open=panel.getByRole('button',{name:/^Expand /});await open.click();const close=panel.getByRole('button',{name:'Close full-screen diagram',exact:true});await close.waitFor({state:'visible'});
|
||||
const expanded=await(await panel.locator('dialog iframe').elementHandle()).contentFrame();await expanded.locator('svg[role="img"]').waitFor();
|
||||
@@ -34,6 +45,7 @@ const assert=require('node:assert/strict');
|
||||
if(width<=700){await page.setViewportSize({width,height:480});assert(await panel.locator('dialog').evaluate(n=>n.scrollHeight>n.clientHeight));await panel.locator('dialog').evaluate(n=>n.scrollTop=n.scrollHeight);await page.screenshot({path:`${out}/${topic}-${width}-${theme}-short-bottom.png`});await page.setViewportSize({width,height:900});}
|
||||
await close.focus();await page.keyboard.press('Escape');assert(await open.evaluate(n=>n===document.activeElement));
|
||||
}
|
||||
await showControls();
|
||||
await frame.locator('#btn-preset').click();await frame.locator('[data-preset-value="blueprint"]').click();
|
||||
await frame.locator('#btn-preset').click();await frame.locator('[data-preset-value="classic"]').click();
|
||||
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);
|
||||
|
||||
@@ -8,12 +8,12 @@ const fs = require('node:fs');
|
||||
const prefix = '/eldorado-v1/documentation/strategy/';
|
||||
const first = 'Stage - 01 - Skills Adoption';
|
||||
const second = 'Stage - 02 - Autonomous Agent';
|
||||
const topics = ['Governance','Quality','Adoption','Measurement','Maintenance'];
|
||||
const topics = ['Measurement','Baseline','Governance','Quality','Adoption','Maintenance'];
|
||||
const metrics = JSON.parse(fs.readFileSync('research/ai-adoption/measurement-migration.json','utf8')).metrics;
|
||||
const childIds = [...metrics.map(m => m.docId),'measurement/collection-and-safeguards','measurement/synthetic-example'];
|
||||
const childTitles = [...metrics.map(m => m.title),'Collection and safeguards','Run the synthetic measurement example'];
|
||||
const ids = ['target-operating-model','roadmap','stage-01-skills-adoption','skills-governance','skills-quality','skills-adoption','measurement',...childIds,'skills-maintenance','stage-02-autonomous-agent'];
|
||||
const titles = ['Target','Roadmap',first,'Skills governance','Skills quality','Skills adoption','Skills Measurement',...childTitles,'Skills maintenance',second];
|
||||
const ids = ['target-operating-model','roadmap','stage-01-skills-adoption','measurement',...childIds,'baseline','skills-governance','skills-quality','skills-adoption','skills-maintenance','stage-02-autonomous-agent'];
|
||||
const titles = ['Target','Roadmap',first,'Skills Measurement',...childTitles,'Baseline','Skills governance','Skills quality','Skills adoption','Skills maintenance',second];
|
||||
const browser = await chromium.launch({headless:true, executablePath:process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE, args:['--no-sandbox']});
|
||||
const results = [];
|
||||
try {
|
||||
@@ -47,7 +47,7 @@ const fs = require('node:fs');
|
||||
await reference.focus();
|
||||
await page.keyboard.press('Enter');
|
||||
await category.getByRole('link', {name:'Validated task success', exact:true}).waitFor({state:'visible'});
|
||||
assert.deepEqual(await visibleLabels(), ['Target','Roadmap',first,...topics.slice(0,4),...childTitles,'Maintenance',second]);
|
||||
assert.deepEqual(await visibleLabels(), ['Target','Roadmap',first,topics[0],...childTitles,...topics.slice(1),second]);
|
||||
await reference.click();
|
||||
await page.screenshot({path:`${output}/${width}-expanded.png`, animations:'disabled'});
|
||||
await caret.click();
|
||||
@@ -68,14 +68,14 @@ const fs = require('node:fs');
|
||||
else assert((await page.locator('h1').innerText()).includes('Target'));
|
||||
const prev = page.locator('.pagination-nav__link--prev');
|
||||
const next = page.locator('.pagination-nav__link--next');
|
||||
if (index) assert.equal(await prev.getAttribute('href'), `${prefix}${ids[index-1]}/`);
|
||||
if (index) assert.equal(await prev.getAttribute('href'), `${prefix}${id === 'baseline' ? 'measurement' : ids[index-1]}/`);
|
||||
else assert.equal(await prev.count(), 0);
|
||||
if (index < ids.length-1) assert.equal(await next.getAttribute('href'), `${prefix}${ids[index+1]}/`);
|
||||
if (index < ids.length-1) assert.equal(await next.getAttribute('href'), `${prefix}${id === 'measurement' ? 'baseline' : ids[index+1]}/`);
|
||||
else assert.equal(await next.count(), 0);
|
||||
if (index >= 3 && index < ids.length - 1) {
|
||||
assert.equal(await page.locator('.breadcrumbs a').filter({hasText:first}).getAttribute('href'), `${prefix}stage-01-skills-adoption/`);
|
||||
menu = await openMenu();
|
||||
const expectedTopics = id === 'measurement' || id.startsWith('measurement/') ? [...topics.slice(0,4),...childTitles,'Maintenance'] : topics;
|
||||
const expectedTopics = id === 'measurement' || id.startsWith('measurement/') ? [topics[0],...childTitles,...topics.slice(1)] : topics;
|
||||
assert.deepEqual(await visibleLabels(), ['Target','Roadmap',first,...expectedTopics,second]);
|
||||
if (id.startsWith('measurement/')) assert.equal(await page.locator('.breadcrumbs a').filter({hasText:'Measurement'}).getAttribute('href'), `${prefix}measurement/`);
|
||||
await closeMenu();
|
||||
|
||||
@@ -4,14 +4,16 @@ import {readFileSync} from 'node:fs';
|
||||
import {calculate} from './ai-kpi.mjs';
|
||||
const read = path => readFileSync(path, 'utf8');
|
||||
|
||||
test('Skills Measurement is an open adoption collection plan, not a hidden catalogue', () => {
|
||||
test('Skills Measurement is a visible optional registry, separate from workflow application', () => {
|
||||
const page = read('docs/strategy/measurement/index.mdx');
|
||||
assert.match(page, /title: Skills Measurement\nsidebar_label: Measurement/);
|
||||
for (const heading of ['Establish the baseline', 'Measure the pilot', 'Extend collection as adoption grows', 'Keep the collection running']) assert(page.includes(heading), heading);
|
||||
for (const heading of ['Establish the baseline', 'Measure the pilot', 'Extend collection as adoption grows', 'Keep the collection running']) assert(!page.includes(heading), heading);
|
||||
assert(page.includes('Registry inclusion does not require a metric to be used, collected or baselined'));
|
||||
assert(page.includes('../baseline.mdx'));
|
||||
assert(!page.includes('<details>'));
|
||||
assert(page.includes('./collection-and-safeguards.mdx'));
|
||||
assert(!page.includes('Is AI-assisted work worth continuing?'));
|
||||
for (const word of ['Recommended', 'not installed', 'unknown', 'review', 'CI', 'revision', 'Monthly', 'Weekly']) assert(page.includes(word), word);
|
||||
for (const word of ['candidate', 'not installed', 'applicability', 'calculation', 'inputs', 'limitations', 'implementation status']) assert(page.includes(word), word);
|
||||
});
|
||||
|
||||
test('all sixteen metric definitions remain in the reference with explicit implementation limits', () => {
|
||||
@@ -27,7 +29,7 @@ test('all sixteen metric definitions remain in the reference with explicit imple
|
||||
});
|
||||
|
||||
test('published pilot arithmetic matches the executable fixture, including partial cost', () => {
|
||||
const page = read('docs/strategy/measurement/index.mdx');
|
||||
const page = read('docs/strategy/skills-adoption.mdx');
|
||||
const fixture = JSON.parse(read('scripts/fixtures/ai-kpi-synthetic.json'));
|
||||
const report = calculate(fixture);
|
||||
const success = report.kpis['validated-task-success'];
|
||||
|
||||
@@ -6,15 +6,15 @@ import {join} from 'node:path';
|
||||
import {execFileSync} from 'node:child_process';
|
||||
import {skillsViewer,isSkillsStory} from './skills-viewer.mjs';
|
||||
const read = p => readFileSync(p,'utf8');
|
||||
const topics = ['governance','quality','adoption','measurement','maintenance'];
|
||||
test('all six Skills Adoption pages account for exactly five diagrams and ten sources',()=>{
|
||||
const topics = ['measurement','baseline','governance','quality','adoption','maintenance'];
|
||||
test('all seven Skills Adoption pages account for six diagrams and twelve sources',()=>{
|
||||
let count=0;
|
||||
for(const route of ['stage-01-skills-adoption',...topics.map(t=>t==='measurement'?t:`skills-${t}`)]){
|
||||
for(const route of ['stage-01-skills-adoption',...topics.map(t=>['measurement','baseline'].includes(t)?t:`skills-${t}`)]){
|
||||
const diagrams=[...read(`docs/strategy/${route === 'measurement' ? 'measurement/index' : route}.mdx`).matchAll(/<ArchifyDiagram name="([^"]+)"/g)];
|
||||
assert.equal(diagrams.length,route.startsWith('stage-')?0:1);
|
||||
for(const [,name] of diagrams){assert(isSkillsStory(name));for(const suffix of ['','-mobile'])JSON.parse(read(`diagrams/${name}${suffix}.architecture.json`));count++;}
|
||||
}
|
||||
assert.equal(count,5);assert(!isSkillsStory('strategy-target'));assert(!isSkillsStory('strategy-roadmap'));
|
||||
assert.equal(count,6);assert(!isSkillsStory('strategy-target'));assert(!isSkillsStory('strategy-roadmap'));
|
||||
});
|
||||
for(const topic of topics) test(`${topic}: rich native source, wide desktop, mobile parity and checked adapter`,()=>{
|
||||
const name=`strategy-${topic}`;const desktop=JSON.parse(read(`diagrams/${name}.architecture.json`));
|
||||
@@ -43,7 +43,7 @@ test('domain contracts retain human authority, honest measures and Delivery-firs
|
||||
assert(text('quality').includes('Critical effect blocks'));
|
||||
assert(text('adoption').includes('Delivery first')&&text('adoption').includes('Later order undecided'));
|
||||
assert(text('adoption').includes('No quotas or rankings'));
|
||||
for(const marker of ['Tracker + acceptance','Invoices + review minutes','Changes + defects','Anonymous 1–5 survey','Missing buckets = partial','Zero denominator = N/A'])assert(text('measurement').includes(marker),marker);
|
||||
for(const marker of ['Available choices','16 candidate contracts','No mandatory collection','Meaning + applicability','9 prototype / 7 unimplemented'])assert(text('measurement').includes(marker),marker);
|
||||
assert(text('maintenance').includes('No automatic reinstatement'));
|
||||
});
|
||||
test('topic compositions explain distinct relationships rather than a fixed card count',()=>{
|
||||
@@ -55,6 +55,7 @@ test('topic compositions explain distinct relationships rather than a fixed card
|
||||
has(g,'approve','owner');has(g,'distribute','withdraw');
|
||||
const q=spec('quality');for(const id of ['selection','safety','artifact','outcome'])has(q,id,'gate');has(q,'gate','accept');has(q,'gate','rework');
|
||||
const a=spec('adoption');for(const [x,y] of [['human','agent'],['agent','human'],['agent','learn'],['learn','delivery'],['learn','expand'],['human','expand']])has(a,x,y);
|
||||
const m=spec('measurement');for(const id of ['success','quality','cost','confidence']){has(m,id+'-source',id);has(m,id,'interpret');}
|
||||
const m=spec('measurement');for(const id of ['qualification','outcomes','experience','health']){has(m,'registry',id);has(m,id,'contract');}
|
||||
const b=spec('baseline');for(const [x,y] of [['workflow','selection'],['selection','evidence'],['evidence','position'],['position','comparison']])has(b,x,y);
|
||||
const c=spec('maintenance');for(const [x,y] of [['observe','triage'],['triage','change'],['change','validate'],['validate','release'],['release','observe'],['triage','safe'],['safe','observe'],['triage','retire'],['triage','contain'],['contain','change']])has(c,x,y);
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
// Native editable geometry and edges; scoped editorial typography for Stage 01.
|
||||
export const isSkillsStory = name => /^strategy-(governance|quality|adoption|measurement|maintenance)(-mobile)?$/.test(name);
|
||||
export const isSkillsStory = name => /^strategy-(governance|quality|adoption|measurement|baseline|maintenance)(-mobile)?$/.test(name);
|
||||
const escape = text => text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"');
|
||||
export function skillsViewer(html, spec) {
|
||||
if (spec.diagram_type !== 'architecture' || !spec.components.length) throw new Error('Skills story contract drift');
|
||||
|
||||
@@ -14,13 +14,14 @@ test('Strategy has Target, Roadmap, a linked Skills Adoption category and Autono
|
||||
type:'category', label:'Stage - 01 - Skills Adoption',
|
||||
link:{type:'doc', id:'stage-01-skills-adoption'}, collapsed:true,
|
||||
items:[
|
||||
{type:'doc', id:'skills-governance', label:'Governance'},
|
||||
{type:'doc', id:'skills-quality', label:'Quality'},
|
||||
{type:'doc', id:'skills-adoption', label:'Adoption'},
|
||||
{type:'category', label:'Measurement', collapsed:true, link:{type:'doc', id:'measurement/index'}, items:[
|
||||
...JSON.parse(read('research/ai-adoption/measurement-migration.json')).metrics.map(m => m.docId),
|
||||
'measurement/collection-and-safeguards','measurement/synthetic-example',
|
||||
]},
|
||||
{type:'doc', id:'baseline', label:'Baseline'},
|
||||
{type:'doc', id:'skills-governance', label:'Governance'},
|
||||
{type:'doc', id:'skills-quality', label:'Quality'},
|
||||
{type:'doc', id:'skills-adoption', label:'Adoption'},
|
||||
{type:'doc', id:'skills-maintenance', label:'Maintenance'},
|
||||
|
||||
],
|
||||
@@ -39,7 +40,7 @@ test('stage overviews explain the foundation and future without replacing topic
|
||||
assert(page.includes(`id: ${id}\ntitle: ${title}`));
|
||||
for (const link of ['./roadmap.mdx', './target-operating-model.mdx']) assert(page.includes(link));
|
||||
}
|
||||
for (const id of ['skills-governance','skills-quality','skills-adoption','measurement/index','skills-maintenance']) assert(first.includes(`./${id}.mdx`));
|
||||
for (const id of ['measurement/index','baseline','skills-governance','skills-quality','skills-adoption','skills-maintenance']) assert(first.includes(`./${id}.mdx`));
|
||||
for (const marker of ['human + AI Agent','Delivery first','order is not yet decided','KPIs','baseline','topology','feedback','new current situation']) assert(first.includes(marker), marker);
|
||||
for (const marker of ['future','proven skills','measurements','working practices','direction and review','not deployed autonomy','approved KPI thresholds']) assert(second.includes(marker), marker);
|
||||
assert.match(read('docs/strategy/measurement/index.mdx'), /^title: Skills Measurement\nsidebar_label: Measurement$/m);
|
||||
|
||||
@@ -13,7 +13,7 @@ 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(!/<details\s+open/.test(page), id);
|
||||
assert.equal((page.match(/<details>/g) || []).length, (page.match(/<\/details>/g) || []).length, id);
|
||||
assert.equal((narrative.match(/^## /gm) || []).length, id === 'measurement' ? 5 : id === 'roadmap' ? 4 : 1, id);
|
||||
assert.equal((narrative.match(/^## /gm) || []).length, id === 'measurement' ? 2 : id === 'roadmap' ? 4 : 1, id);
|
||||
assert((narrative.match(/^- /gm) || []).length <= 3, id);
|
||||
assert(narrative.includes('**Next:**'), id);
|
||||
assert(!narrative.includes('| ---'), id);
|
||||
|
||||
@@ -6,7 +6,7 @@ const model = JSON.parse(read('research/ai-adoption/strategy-model.json'));
|
||||
test('seven existing strategy pages and two stage overviews preserve canonical routes', () => {
|
||||
assert.equal(model.pages.length, 7);
|
||||
assert.deepEqual(readdirSync('docs/strategy').filter(p => p.endsWith('.mdx')).sort(),
|
||||
[...model.pages.filter(p => p.id !== 'measurement').map(({id}) => `${id}.mdx`), 'stage-01-skills-adoption.mdx', 'stage-02-autonomous-agent.mdx'].sort());
|
||||
[...model.pages.filter(p => p.id !== 'measurement').map(({id}) => `${id}.mdx`), 'stage-01-skills-adoption.mdx', 'stage-02-autonomous-agent.mdx', 'baseline.mdx'].sort());
|
||||
for (const {id} of model.pages) {
|
||||
const page = read(`docs/strategy/${id === 'measurement' ? 'measurement/index' : id}.mdx`);
|
||||
assert(page.includes(`id: ${id === 'measurement' ? 'index' : id}`));
|
||||
|
||||
@@ -22,11 +22,13 @@ if (process.argv.includes('--build')) {
|
||||
verifyMeasurementPages();
|
||||
const model = JSON.parse(read('research/ai-adoption/strategy-model.json'));
|
||||
const indexes = readdirSync('build').filter(f => /^search-index.*\.json$/.test(f)).map(f => read(join('build',f))).join('\n');
|
||||
assert(indexes.includes('/eldorado-v1/documentation/strategy/baseline/'), 'Missing indexed Baseline route');
|
||||
const redirect = read('build/strategy/index.html');
|
||||
assert(redirect.includes('/eldorado-v1/documentation/strategy/target-operating-model/'));
|
||||
assert(redirect.includes('window.location.href') && redirect.includes('http-equiv="refresh"') && !redirect.includes('archify-panel'), 'Landing must redirect, not duplicate Target');
|
||||
const strategyPages = [...model.pages,
|
||||
{id:'stage-01-skills-adoption', title:'Stage - 01 - Skills Adoption'},
|
||||
{id:'baseline', title:'Baseline'},
|
||||
{id:'stage-02-autonomous-agent', title:'Stage - 02 - Autonomous Agent'},
|
||||
];
|
||||
for (const {id, title} of strategyPages) {
|
||||
|
||||
Reference in new issue
Block a user