Files
KArtSell.Aegis/docs/Design/kbx-foundation-v36/scripts/validate-template-navigation-v36.mjs
T

60 lines
4.7 KiB
JavaScript

import fs from 'node:fs'
import path from 'node:path'
const root=process.cwd();const failures=[]
const read=p=>fs.readFileSync(path.join(root,p),'utf8')
const json=p=>JSON.parse(read(p))
const must=(text,needles,scope)=>needles.forEach(needle=>{if(!text.includes(needle))failures.push(`${scope} missing ${needle}`)})
const recipes=json('contracts/screens/kbx.screen-recipes.json')
const verification=json('generated/screen-recipe-verification-manifest.json')
const scenarios=json('contracts/testing/kbx.test-scenarios.json').scenarios
const screens=json('generated/screen-manifest.json')
const screenById=new Map(screens.map(screen=>[screen.id,screen]))
const scenarioById=new Map(scenarios.map(scenario=>[scenario.id,scenario]))
if(recipes.recipes.length!==9)failures.push(`expected 9 recipes, found ${recipes.recipes.length}`)
if(verification.recipes.length!==9)failures.push(`expected 9 recipe verification rows, found ${verification.recipes.length}`)
for(const recipe of recipes.recipes){
const profile=recipe.testProfile
if(!profile) { failures.push(`${recipe.code} missing testProfile`); continue }
for(const key of ['requiredScenarioKinds','requiredTags','requiredEvidence','requiredChecks'])if(!(profile[key]?.length>0))failures.push(`${recipe.code} testProfile missing ${key}`)
if(!profile.requiredScenarioKinds.includes('e2e'))failures.push(`${recipe.code} must require at least one E2E scenario`)
const row=verification.recipes.find(item=>item.code===recipe.code)
if(!row?.complete)failures.push(`${recipe.code} recipe verification incomplete: ${JSON.stringify(row)}`)
const canonical=recipe.canonicalScenarioIds.flatMap(id=>scenarioById.has(id)?[scenarioById.get(id)]:[])
const representativeE2e=canonical.find(scenario=>scenario.kind==='e2e'&&screenById.get(scenario.screenId)?.templateCode===recipe.code)
if(!representativeE2e)failures.push(`${recipe.code} needs an E2E scenario on a screen that actually uses ${recipe.code}`)
}
const typeContract=read('packages/kbx-contracts/src/screen.ts')
must(typeContract,['KbxScreenRecipeTestProfile','requiredScenarioKinds','requiredTags','requiredEvidence','requiredChecks'],'recipe verification type contract')
const generator=read('scripts/generate-screen-recipe-contracts.mjs')
must(generator,['screen-recipe-verification-manifest.json','missingScenarioKinds','missingTags','missingEvidence','kbxScreenRecipeVerificationCatalog'],'recipe verification generator')
for(const [file,id] of [
['tests/e2e/erp-item-master.spec.ts','scenario.erp.item-master.keyboard-recovery'],
['tests/e2e/common-operations.spec.ts','scenario.common.operations.queue-recovery'],
['tests/e2e/common-reconcile.spec.ts','scenario.common.reconcile.mismatch-recovery'],
]) must(read(file),[id,'scenarioTitle','data-kbx-surface'],file)
const scaffolder=read('scripts/create-kbx-screen.mjs')
must(scaffolder,['KbxGeneratedScreenTestPlan','.test-plan.ts','recipe.testProfile.requiredChecks','recipe.testProfile.requiredEvidence'],'recipe-driven generated test plan')
const scaffoldValidator=read('scripts/validate-scaffolder.mjs')
must(scaffoldValidator,['generated recipe test plan','test plan missing required check','test plan missing evidence'],'scaffolder test-plan governance')
const navigation=read('packages/kbx-contracts/src/navigation.ts')
must(navigation,['occurredAt: string','KbxHomeAttentionQueue','overflowCount','sourceCounts'],'Home attention queue contract')
const homeNav=read('packages/kbx-ui/src/shell/homeNavigation.ts')
must(homeNav,['buildKbxHomeAttentionQueue','b.occurredAt.localeCompare(a.occurredAt)','overflowCount','sourceCounts','Backward-compatible item-only view'],'Home attention deterministic queue')
const home=read('packages/kbx-ui/src/shell/KbxHomePage.vue')
must(home,['buildKbxHomeAttentionQueue','exactAttentionCount','attentionOverflowCount','전체 {{exactAttentionCount}}개 · 상위 {{attentionItems.length}}개 표시'],'Home exact attention count UX')
const uiIndex=read('packages/kbx-ui/src/index.ts')
if(!uiIndex.includes('buildKbxHomeAttentionQueue'))failures.push('public UI API missing buildKbxHomeAttentionQueue')
const homeTest=read('tests/unit/kbx-home-attention.contract.spec.ts')
must(homeTest,['newest-first within priority','overflowCount','sourceCounts'], 'Home attention queue unit contract')
const releaseAnalyzer=read('scripts/analyze-kbx-release.mjs')
must(releaseAnalyzer,['screen-recipe','testProfile','canonicalScenarioIds'],'release analyzer recipe verification tracking')
if(failures.length){console.error(failures.join('\n'));process.exit(1)}
console.log(`v36 recipe/home validation passed: recipes=${recipes.recipes.length}, recipe verification=9/9, canonical E2E representative coverage enforced, and Home attention exact-count/newest-first queue is active.`)