Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-1/work
Some checks are pending
build-gate / build (push) Waiting to run

This commit is contained in:
doxa-maps-88655c70 2026-09-24 13:49:10 +00:00
commit 0a2fd134ec

View file

@ -163,9 +163,33 @@ const r = await page.evaluate(() => {
// Whole-map property, NOT one sampled element — see header note 2.
const mapFaults = (() => {
const svg = document.querySelector('.sheet svg')
if (!svg) return ['no map svg found']
// ⚠ SCOPE TO PAGE 1. This was `document.querySelector('.sheet svg')` — "the first svg
// ANYWHERE" — which is a FALLBACK SELECTOR, and a fallback selector turns an absence
// into a pass. Measured 2026-09-24: deleting the map svg from page 1 entirely left this
// gate reporting "map: palette resolves, not black — PASS, map painted", because the
// query silently retargeted to the PRAYER WHEEL's svg two sheets later. The wheel has no
// CSS variables to leave unresolved and no black fills, so both checks passed vacuously
// while page 1 — "the map one-pager", the first line of the Driver's packet spec — was
// blank. The sheet count stayed 8 because the empty sheet still exists.
// The packet's page order is the product spec and does not vary: sheet 0 IS the map page.
const sheet0 = document.querySelector('.sheet')
const svg = sheet0 ? sheet0.querySelector('svg') : null
if (!svg) return ['no map svg on page 1 — the map one-pager rendered without its map']
const faults = []
// ⚠ AND ASSERT IT PAINTS GEOGRAPHY. Palette-resolves + not-black are both properties a
// map with ZERO country shapes satisfies perfectly. Geography is counted as paths whose
// `d` is long enough to be a coastline rather than an icon or a chart tick. MEASURED
// across zones: laos 13, brazil 18, middle-east-core 55 — it varies with how many
// countries a zone spans, so the floor is well under the smallest rather than an exact
// count. Zones whose groups do not resolve are SKIPPED by the generator and never reach
// this gate ("europe: no groups resolved — skipped"), so a zero here is a real fault.
const geoPaths = [...svg.querySelectorAll('path')]
.filter((e) => (e.getAttribute('d') || '').length > 200).length
if (geoPaths < 5) {
faults.push(`only ${geoPaths} geography path(s) on the map page — the map one-pager is `
+ 'blank or drew nothing but furniture (a correct palette and no black fills are both '
+ 'satisfied by a map with no countries on it)')
}
const names = [...new Set((svg.outerHTML.match(/var\((--[a-z0-9-]+)/g) || []).map((v) => v.slice(4)))]
const cs = getComputedStyle(svg)
for (const n of names) if (!cs.getPropertyValue(n).trim()) faults.push(`unresolved ${n}`)
@ -235,6 +259,14 @@ const r = await page.evaluate(() => {
})(),
metacamp: (body.match(/metacamp\.org/g) || []).length,
mapFaults,
// Printed beside the verdict: a reader should see the number the assertion rests on,
// not just the word "painted".
mapGeoPaths: (() => {
const sheet0 = document.querySelector('.sheet')
const svg = sheet0 ? sheet0.querySelector('svg') : null
if (!svg) return -1
return [...svg.querySelectorAll('path')].filter((e) => (e.getAttribute('d') || '').length > 200).length
})(),
// The per-page "{from}-{to} of {count}" headers, as DIGIT TRIPLES rather than text.
// Read from the rendered DOM (not the source template) so what is checked is what a
// reader would see. Locale digits are normalised to ASCII first: several catalogs
@ -329,7 +361,24 @@ if (r.points !== POINTS_EXPECT) {
+ 'carries its "12 Prayer Points" heading')
}
if (r.metacamp !== 2) fails.push(`${r.metacamp} metacamp.org attributions, expected exactly 2`)
if (r.mapFaults.length) fails.push(`map: ${r.mapFaults.join('; ')}`)
// THE MAP PAGE IS OPT-OUT-ABLE, THE SAME WAY THE PHOTOS ARE — and for the same reason.
// packet.mjs lifts the map from out/posters/<zone>.html and, when that file is absent,
// deliberately "still builds (cover page without the map) rather than failing". That soft
// fail is intentional, but it is also INVISIBLE: measured 2026-09-24, a packet built with
// no poster sources has 8 sheets and an <svg> present (the prayer wheel's) and carries no
// marker at all, so it is structurally indistinguishable from a good one while page 1
// promises a map one-pager and delivers an empty sheet. doxa-maps-plugin-studio ships 0
// poster html files against wt-packet's 28, so every packet generated there is degraded
// this way and nothing said so.
// Default to FAILING, so the degradation has to be DECLARED rather than discovered.
const expectMap = process.env.PACKET_EXPECT_MAP !== '0'
if (r.mapFaults.length && expectMap) {
fails.push(`map: ${r.mapFaults.join('; ')}`
+ (r.mapGeoPaths === -1
? ' — build the poster sources first (node library/scripts/posters/generate.mjs), or set '
+ 'PACKET_EXPECT_MAP=0 to declare this a deliberately map-less packet'
: ''))
}
if (fontStatus.declared && fontStatus.loaded !== fontStatus.declared) {
fails.push(`a declared @font-face did not load (${fontStatus.names.join(', ')}) — `
+ 'text in that script will print as empty boxes')
@ -478,7 +527,9 @@ console.log(` wheel segments : ${r.wheelSegs} (${r.wheelLabels}/${WHEEL_LABE
console.log(` Mark 5 in full : ${r.mark5Len} chars`
+ `${scriptureIsEnglish ? ' ⚠ UNTRANSLATED (English fallback)' : ''}`)
console.log(` metacamp.org : ${r.metacamp}`)
console.log(` map : ${r.mapFaults.length ? r.mapFaults.join('; ') : 'palette resolves, not black'}`)
console.log(` map (page 1) : ${r.mapFaults.length
? `${r.mapFaults.join('; ')}${expectMap ? '' : ' [declared deliberate: PACKET_EXPECT_MAP=0]'}`
: `${r.mapGeoPaths} geography paths, palette resolves, not black`}`)
console.log(` page size : ${boxes[0] ? boxes[0].join(' x ') : '?'} pt`
+ `${boxes.length ? ` (all ${boxes.length} pages, asserted US Letter)` : ''}`)
console.log(` layout : ${r.cards} cards / ${PER_PAGE} per page `
@ -494,4 +545,8 @@ if (fails.length) {
for (const f of fails) console.error(` - ${f}`)
process.exit(1)
}
console.log(`\nPACKET-RENDER: PASS — ${r.sheets} sheets, ${r.sheets} pages, portrait, map painted, content intact.`)
// ⚠ THE VERDICT MUST NOT CLAIM MORE THAN WAS CHECKED. It read "map painted" unconditionally,
// so a packet passing under PACKET_EXPECT_MAP=0 — one with NO map on page 1 — was summarised
// as having a painted map. The summary line is the part a reader actually quotes.
console.log(`\nPACKET-RENDER: PASS — ${r.sheets} sheets, ${r.sheets} pages, portrait, `
+ `${r.mapFaults.length ? 'NO map (declared)' : 'map painted'}, content intact.`)