import test from 'node:test'; import assert from 'node:assert/strict'; import {readFileSync, existsSync, readdirSync} from 'node:fs'; import {createHash} from 'node:crypto'; import {calculate} from './ai-kpi.mjs'; const read = p => readFileSync(p, 'utf8'); test('each original metric survives exactly once on its own canonical Measurement page', () => { const manifest = JSON.parse(read('research/ai-adoption/measurement-migration.json')); const model = JSON.parse(read('research/ai-adoption/strategy-model.json')); const report = calculate(JSON.parse(read('scripts/fixtures/ai-kpi-synthetic.json'))); assert.equal(manifest.metrics.length, 16); assert.deepEqual(manifest.metrics.map(m => m.title), model.kpis.map(k => k.name)); assert.equal(new Set(manifest.metrics.map(m => m.docId)).size, 16); assert.equal(manifest.metrics.filter(m => m.status === 'prototype').length, 9); assert.equal(manifest.metrics.filter(m => m.status === 'unimplemented').length, 7); const overview = read('docs/strategy/measurement/index.mdx'); for (const metric of manifest.metrics) { const page = read(`docs/strategy/${metric.docId}.mdx`); assert.equal(metric.url, `/strategy/${metric.docId}/`); assert.equal(metric.oldAnchor, metric.docId.split('/').at(-1)); assert(page.includes(`slug: /${metric.docId}`)); assert(overview.includes(`./${metric.oldAnchor}.mdx`)); assert(page.includes('./collection-and-safeguards.mdx')); assert(page.includes('not installed collection')); assert(page.includes(metric.status === 'prototype' ? 'Prototype calculation' : 'Unimplemented metric')); assert.equal(Object.hasOwn(report.kpis, metric.calculationId), metric.status === 'prototype'); const contract = page.split('{/* contract:start */}\n')[1]?.split('\n{/* contract:end */}')[0]; assert(contract, metric.title); assert.equal(createHash('sha256').update(contract).digest('hex'), metric.contractSha256, metric.title); for (const field of ['Numerator','Denominator','Expression','Aggregation','Unit','Eligible population','Exclusions','Events and source','Owner / cadence','Missing evidence','Gaming and limits']) assert.equal(contract.split(`| ${field} |`).length, 2, `${metric.title}: ${field}`); } assert.equal(readdirSync('docs/strategy/measurement').filter(p => p.endsWith('.mdx')).length, 19); assert(!existsSync('docs/strategy/reference/measurement-contracts.mdx')); for (const part of manifest.shared) { const page = read(`docs/strategy/measurement/${part.slug}.mdx`); const body = page.split('{/* preserved:start */}\n')[1]?.split('\n{/* preserved:end */}')[0]; // Only the cross-page navigation wording changes; hash all original substance. const original = body.replace('Use the [metric definitions](./index.mdx#metric-definitions)', 'Use the metric contracts below') // The old navigation named nonexistent roadmap gates. Restore only that // historical sentence for the migration hash; metric substance stays exact. .replace('Use these safeguards throughout the [Stage 01 journey](../stage-01-skills-adoption.mdx)', 'Introduction depends on the [roadmap gates](../roadmap.mdx)'); assert.equal(createHash('sha256').update(original).digest('hex'), part.sha256); } });