import test from 'node:test'; import assert from 'node:assert/strict'; import {readFileSync} from 'node:fs'; import {createHash} from 'node:crypto'; import {execFileSync} from 'node:child_process'; import {slides} from '../presentations/less-prompting-more-shipping/slides.mjs'; const read=p=>readFileSync(p,'utf8'); test('deck preserves assignment coverage, 35+15 timing and traceable notes',()=>{ assert.equal(slides.length,23); assert.equal(new Set(slides.map(s=>s.id)).size,23); assert.equal(slides.filter(s=>s.track==='main').reduce((n,s)=>n+s.minutes,0),35); assert.equal(slides.find(s=>s.track==='discussion').minutes,15); assert.equal(slides.find(s=>s.track==='appendix').minutes,0); for(const s of slides){assert(s.sources.length);assert(s.notes.length>250);assert(s.body.length);} for(const id of ['months-one-two','months-three-four','months-five-six','measures','month-six','beyond']) assert(slides.some(s=>s.id===id)); for(const id of ['experiment']) assert.match(slides.find(s=>s.id===id).body,/fictional/i); assert.match(slides.find(s=>s.id==='qualification').notes,/separately authorizes/); }); test('starting point keeps content without the two removed headings',()=>{ const body=slides.find(s=>s.id==='starting-point').body; assert.doesNotMatch(body,/Assignment facts|Unknown until discovery/); for(const text of ['Solo architect → CTO','No formal authority over teams','Stack, tools, process, baselines','Capacity and actual bottlenecks'])assert(body.includes(text)); assert.doesNotMatch(body,/


/); }); test('contributors explains human-controlled AI tools below the diagram',()=>{ const body=slides.find(s=>s.id==='contributors').body; const definition='AI Agent = Claude, Cline, ChatGPT or a similar tool, used under human control.'; assert(body.includes(definition)); assert(body.indexOf(definition)>body.indexOf('contribution-grid')); assert(body.includes('Dashed ⇢ contribution from outside the cycle.')); }); test('capacity visibly frames the days as an example weekly allocation',()=>{ const slide=slides.find(s=>s.id==='capacity'); assert.equal(slide.title,'One architect. One active live pilot.'); assert(slide.body.startsWith('

Example weekly allocation for the AI architect

{ const body=slides.find(s=>s.id==='learning-loop').body; const loop=body.split('
')[0]; assert.deepEqual([...loop.matchAll(/(.*?)<\/span>/g)].map(m=>m[1]),['Understand work','Measure + baseline','Engineer topology','Use in real work','Collect results','Reassess']); assert.deepEqual([...loop.matchAll(/(.*?)<\/i>/g)].map(m=>m[1]),['→','↓','→','↓','→']); assert(body.includes('↻ Repeat within each phase.')); }); test('build emits local pinned Reveal assets, stable IDs and no production CDN',()=>{ execFileSync(process.execPath,['scripts/build-presentations.mjs']); const dir='static/presentations/less-prompting-more-shipping'; const html=read(`${dir}/index.html`); assert.equal((html.match(/
s.id===id)); for(const doc of map.diagramSources)assert.equal(doc.sha256,createHash('sha256').update(read(doc.path)).digest('hex')); assert.match(map.strategyRevision,/same-build/); for(const doc of map.sourceDocuments) assert.equal(doc.sha256,createHash('sha256').update(read(doc.path)).digest('hex'),doc.path); for(const id of ['target-operating-model','roadmap','six-months-target','six-months-roadmap','stage-02-autonomous-agent']) assert(map.sourceDocuments.some(d=>d.id===id),id); assert(slides.find(s=>s.id==='beyond').notes.includes('long-term destination remains human-directed')); for(const id of ['months-one-two','months-three-four','months-five-six','capacity','experiment']) assert(slides.find(s=>s.id===id).sources.includes('six-months-roadmap'),id); }); test('visible strategy narrative preserves five-page order and short experiment',()=>{ const index=id=>slides.findIndex(s=>s.id===id); const sequence=['starting-point','target','contributors','roadmap','learning-loop','six-month-target','months-one-two','months-three-four','months-five-six','experiment','month-six','beyond','authority','discussion']; for(let i=1;iindex(sequence[i-1]),sequence[i]); assert.match(slides[index('target')].body,/Autonomous agent/); assert.match(slides[index('roadmap')].body,/Order undecided/); assert.match(slides[index('roadmap')].body,/Delivery keeps improving/); assert.match(slides[index('learning-loop')].body,/Triggers → skills → handoffs → acceptance/); assert(!slides.some(s=>s.id==='inconclusive'||s.id==='stop')); assert(!slides[index('experiment')].body.includes('')); assert.match(slides[index('experiment')].notes,/40-minute median against 30 baseline/); assert.equal(slides[index('experiment')].minutes,2); assert.equal(slides.filter(s=>s.track==='appendix').reduce((a,s)=>a+s.minutes,0),0); }); test('presentation topology preserves all original relationships across two readable views',async()=>{ const {topology,cycleFigure,contributionsFigure}=await import('../presentations/less-prompting-more-shipping/target-figure.mjs'); const original=JSON.parse(read('diagrams/strategy-target.architecture.json')); const pairs=prefix=>original.connections.filter(c=>c.id.startsWith(prefix)).map(c=>[c.from,c.to]).sort(); assert.deepEqual([...topology.lifecycle].sort(),pairs('stage-')); assert.deepEqual([...topology.governance].sort(),pairs('govern-')); assert.deepEqual([...topology.contributions].sort(),pairs('contribute-')); for(const [from,to] of [...topology.lifecycle,...topology.governance])assert(cycleFigure.includes(`data-from="${from}" data-to="${to}"`)); for(const [from,to] of topology.contributions)assert(contributionsFigure.includes(`data-from="${from}" data-to="${to}"`)); assert.equal((cycleFigure.match(/data-node="agent"/g)||[]).length,2); // desktop + recomposed phone });