reconcile the 5-caps representatives against the manifest; cap-1 was sampling a cap-2 bundle
This commit is contained in:
parent
a456a0fcd2
commit
97085f05cd
1 changed files with 51 additions and 2 deletions
|
|
@ -10,7 +10,9 @@
|
|||
* ★ THE MODEL, grounded not remembered: capability = 5 - PROFILE_TIER, where PROFILE_TIER lives in
|
||||
* internal/plugin-gallery/discover.mjs:
|
||||
* nested-mfe-spa 0 · nested-elements-mfe 1 · monolithic 2 · parameterized 3 · single 4
|
||||
* One representative bundle per level. If a bundle's declared type changes, update REPS here.
|
||||
* One representative bundle per level. REPS is reconciled against manifest.json at startup, so a
|
||||
* bundle whose declared type changes makes this gate FAIL LOUDLY rather than silently certify a
|
||||
* level it is no longer sampling — you no longer have to remember to update it by hand.
|
||||
*
|
||||
* ★ TWO MEASUREMENT TRAPS THIS ENCODES (both cost real debugging time):
|
||||
* - SHADOW DOM DOES NOT PIERCE. A cap-4/cap-5 composite mounts CHILD elements with their OWN shadow
|
||||
|
|
@ -34,12 +36,59 @@ const GL=['--use-gl=swiftshader','--enable-unsafe-swiftshader','--ignore-gpu-blo
|
|||
const B=(process.env.BASE || 'https://nuxtbase.app/plugin-assets/doxa-maps/').replace(/\/?$/,'/')
|
||||
// capability = 5 - PROFILE_TIER (discover.mjs). One representative per level.
|
||||
const REPS=[
|
||||
['cap-1 single', 'doxa-vision-card/doxa-vision-card/index.html', 'single'],
|
||||
// ★ CORRECTED 2026-09-20 by the manifest reconciliation added below, on its FIRST RUN.
|
||||
// This slot used to be doxa-vision-card — which ships doxa-vision-card.instances.json with 2
|
||||
// instances, so discover.mjs types it PARAMETERIZED (cap-2), not single. The gate has therefore
|
||||
// been reporting '5/5 capability levels' while sampling cap-2 TWICE and cap-1 NEVER. Exactly the
|
||||
// drift the reconciliation exists to catch, found the moment it was switched on.
|
||||
['cap-1 single', 'all-people-groups/all-people-groups/index.html', 'single'],
|
||||
['cap-2 parameterized', 'people-groups-grid/people-groups-grid/index.html', 'preset-element'],
|
||||
['cap-3 monolithic', 'doxa-research-map/research-map/index.html', 'monolithic'],
|
||||
['cap-4 nested-elements', 'dashboard-plus-grid/dashboard-plus-grid/index.html','nested-elements-mfe'],
|
||||
['cap-5 nested-mfe-spa', 'doxa-maps-spa/doxa-maps-spa/index.html', 'nested-mfe-spa'],
|
||||
]
|
||||
// ★ RECONCILE THE HARDCODED REPS AGAINST THE MANIFEST BEFORE TRUSTING THEM.
|
||||
// The REPS table above asserts each representative's declared type as a STRING LITERAL, and the
|
||||
// header says "if a bundle's declared type changes, update REPS here" — i.e. it relies on a human
|
||||
// remembering. That makes the EXPECTATION and the thing it describes corruptible by the same event:
|
||||
// change a bundle's meta.json and this gate keeps claiming the old tier while still passing, so it
|
||||
// would certify a matrix it is no longer actually sampling. (Live risk, not hypothetical: on
|
||||
// 2026-09-20 research-dashboard moved single -> monolithic. It is not a REP, so nothing desynced —
|
||||
// but only by luck.) Read the manifest and FAIL LOUDLY on any drift.
|
||||
// Local-tree runs only: the manifest sits next to the leaves at the same BASE.
|
||||
try {
|
||||
const mfUrl = B + 'manifest.json'
|
||||
const res = await fetch(mfUrl, { signal: AbortSignal.timeout(10000) })
|
||||
if (res.ok) {
|
||||
const mf = await res.json()
|
||||
const byProfile = new Map()
|
||||
for (const bundle of (mf.bundles || [])) {
|
||||
for (const p of (bundle.profiles || [])) byProfile.set(`${bundle.bundle}/${p.profile}`, p.type)
|
||||
}
|
||||
const ALIAS = { 'preset-element': 'parameterized', 'composite-element': 'nested-elements-mfe',
|
||||
'multi-view-element': 'monolithic', 'app-shell': 'nested-mfe-spa', 'single-element': 'single' }
|
||||
const drift = []
|
||||
for (const [name, path, claimed] of REPS) {
|
||||
const key = path.split('/').slice(0, 2).join('/')
|
||||
const actual = byProfile.get(key)
|
||||
const want = ALIAS[claimed] || claimed
|
||||
if (actual && actual !== want) drift.push(`${name}: REPS says "${claimed}" (=${want}) but the manifest says "${actual}" for ${key}`)
|
||||
}
|
||||
if (drift.length) {
|
||||
console.error('5-CAPS: FAIL — the REPS table has DRIFTED from the manifest:')
|
||||
drift.forEach((d) => console.error(' ' + d))
|
||||
console.error(' Update REPS in internal/verify-5-capabilities.mjs. Until then this gate is')
|
||||
console.error(' certifying capability levels it is no longer actually sampling.')
|
||||
process.exit(1)
|
||||
}
|
||||
console.log(`5-CAPS: REPS reconciled against ${mfUrl} — all ${REPS.length} declared types match.`)
|
||||
} else {
|
||||
console.log(`5-CAPS: NOTE — manifest not readable at ${mfUrl} (${res.status}); REPS types UNVERIFIED this run.`)
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`5-CAPS: NOTE — manifest check skipped (${String(e.message || e).slice(0, 60)}); REPS types UNVERIFIED this run.`)
|
||||
}
|
||||
|
||||
const b=await chromium.launch({headless:true,args:GL})
|
||||
let bad=0
|
||||
for(const [name,path,type] of REPS){
|
||||
|
|
|
|||
Loading…
Reference in a new issue