packet gate: a prayer wheel with no words on it is not a prayer wheel
Some checks are pending
build-gate / build (push) Waiting to run
Some checks are pending
build-gate / build (push) Waiting to run
Blanking every wheel segment label and regenerating left check:packet-render reporting "12 segments, 11/11 rhythms, content intact — PASS" on a wheel that was a twelve-colour pie chart. Both printed numbers stayed true, which is why nothing caught it. The twelve segments are <path> elements and survive their labels being removed. And the rhythm assertion searched document.body.innerText, where the SAME twelve rhythm words are rendered TWICE in every packet — once per wheel segment, once as a prayer-point heading. So "every rhythm word appears in the document" was satisfied by the points page alone and said nothing about the wheel. That is the self-consistency-vs-completeness family again, with a new twist: when two surfaces share one vocabulary, a document-wide string search cannot attribute a hit to the surface being asserted. The fix is scoping the query to the surface, not a better word list. wheelLabels counts the non-numeric <text> runs inside the .wheel-title sheet's own svg, excluding the twelve "5" pips and the "5 minutes x 12" footer. It counts ELEMENTS, NOT DISTINCT WORDS, deliberately: `praise` and `praise_end` collapse to one word in English — which is exactly why the existing line reads 11/11 and not 12/12 — and that collision is locale-dependent, so a distinct-word count would be a different number per language. The Driver's spec names the wheel as one of the packet's four sections, so 12 labels is a contract. Mutated packet reports 0/12 and fails; restored reports 12/12. i18n verified at the rendered layer with a partial locale block (4 of 12 rhythms translated): the wheel painted four XX- labels with the other eight falling back to English and zero blank — and the split pair is visible, segment 1 English PRAISE beside segment 12 XX-PRAISE_END, which is what per-key resolution looks like. All 11 locales regenerated with 95 photos each: check:packets-all 11/11, every one 12/12 labelled, including RTL ar and Devanagari hi. Wave 34/34.
This commit is contained in:
parent
a177f98aff
commit
53fea6ee38
1 changed files with 38 additions and 1 deletions
|
|
@ -186,6 +186,32 @@ const r = await page.evaluate(() => {
|
||||||
rhythms: RHYTHMS.filter((w) => body.includes(w)).length,
|
rhythms: RHYTHMS.filter((w) => body.includes(w)).length,
|
||||||
rhythmsTotal: RHYTHMS.length,
|
rhythmsTotal: RHYTHMS.length,
|
||||||
wheelSegs: document.querySelectorAll('svg path[fill^="hsl"]').length,
|
wheelSegs: document.querySelectorAll('svg path[fill^="hsl"]').length,
|
||||||
|
// ⚠ COUNT THE WHEEL'S OWN LABELS, SCOPED TO THE WHEEL SHEET. `rhythms` below
|
||||||
|
// searches document.body.innerText, and the SAME rhythm vocabulary is rendered
|
||||||
|
// TWICE — once per wheel segment, and once per prayer point (each point prints
|
||||||
|
// tr(p.rhythm) as its heading). So "every rhythm word appears in the document" is
|
||||||
|
// satisfied by the POINTS page alone and says nothing about the wheel.
|
||||||
|
// Measured 2026-09-24: blanking every wheel segment label left the gate reporting
|
||||||
|
// "12 segments, 11/11 rhythms, content intact — PASS" on a prayer wheel that was a
|
||||||
|
// twelve-colour pie chart with no words on it. Both numbers stayed true: the
|
||||||
|
// segments are <path> elements and survive, and the words were still on the points
|
||||||
|
// page. The Driver's spec names the wheel as one of the packet's four sections.
|
||||||
|
//
|
||||||
|
// COUNT ELEMENTS, NOT DISTINCT WORDS. `order` renders 12 segments from 12 keys, but
|
||||||
|
// `praise` and `praise_end` collapse to the same word in English (which is why the
|
||||||
|
// line below prints 11/11, not 12/12) — and that collision is LOCALE-DEPENDENT. A
|
||||||
|
// distinct-word count would be a different number per language.
|
||||||
|
wheelLabels: (() => {
|
||||||
|
const title = document.querySelector('.wheel-title')
|
||||||
|
const sheet = title ? title.closest('.sheet') : null
|
||||||
|
const svg = sheet ? sheet.querySelector('svg') : null
|
||||||
|
if (!svg) return -1
|
||||||
|
// The segment labels are the non-numeric <text> runs: the pips are all "5" and
|
||||||
|
// the footer reads "5 <minutes> x 12".
|
||||||
|
return [...svg.querySelectorAll('text')]
|
||||||
|
.map((t) => (t.textContent || '').trim())
|
||||||
|
.filter((s) => s && !/^\d+$/.test(s) && !/^\d[\s\S]*×\s*12$/.test(s)).length
|
||||||
|
})(),
|
||||||
// ⚠ NOT body.includes('Gadarenes'). That was an ENGLISH proper noun, so this
|
// ⚠ NOT body.includes('Gadarenes'). That was an ENGLISH proper noun, so this
|
||||||
// assertion would go RED on a correctly-translated packet and stays green today
|
// assertion would go RED on a correctly-translated packet and stays green today
|
||||||
// only because every locale falls back to English for this key. The check and the
|
// only because every locale falls back to English for this key. The check and the
|
||||||
|
|
@ -268,6 +294,17 @@ if (r.cards && expectPhotos && r.imgs === 0) {
|
||||||
+ 'PACKET_EXPECT_PHOTOS=0 to declare this a deliberately photo-less packet.')
|
+ 'PACKET_EXPECT_PHOTOS=0 to declare this a deliberately photo-less packet.')
|
||||||
}
|
}
|
||||||
if (r.wheelSegs !== 12) fails.push(`prayer wheel has ${r.wheelSegs} segments, expected 12`)
|
if (r.wheelSegs !== 12) fails.push(`prayer wheel has ${r.wheelSegs} segments, expected 12`)
|
||||||
|
// A SEGMENT WITHOUT ITS WORD IS A COLOUR. 12 labels, one per segment, on the wheel
|
||||||
|
// sheet itself — not merely somewhere in the document.
|
||||||
|
const WHEEL_LABELS = 12
|
||||||
|
if (r.wheelLabels !== WHEEL_LABELS) {
|
||||||
|
fails.push(r.wheelLabels === -1
|
||||||
|
? 'no prayer-wheel svg found (no .wheel-title sheet) — the wheel page did not render'
|
||||||
|
: `the prayer wheel paints ${r.wheelLabels} segment label(s), expected ${WHEEL_LABELS} — `
|
||||||
|
+ 'the rhythm words are rendered TWICE in this packet (wheel segments and prayer-point '
|
||||||
|
+ 'headings), so the document-wide rhythm check below passes on the points page alone '
|
||||||
|
+ 'and cannot see an unlabelled wheel')
|
||||||
|
}
|
||||||
if (r.rhythms !== r.rhythmsTotal) fails.push(`only ${r.rhythms}/${r.rhythmsTotal} prayer rhythms present`)
|
if (r.rhythms !== r.rhythmsTotal) fails.push(`only ${r.rhythms}/${r.rhythmsTotal} prayer rhythms present`)
|
||||||
// Mark 5:1-20 in full is a Driver requirement for point 4: "it actually lists out the
|
// Mark 5:1-20 in full is a Driver requirement for point 4: "it actually lists out the
|
||||||
// full scripture, because prayer point number four is actually read the word." The
|
// full scripture, because prayer point number four is actually read the word." The
|
||||||
|
|
@ -437,7 +474,7 @@ if (r.ranges.length) {
|
||||||
console.log(` sheets/PDF pages : ${r.sheets} / ${pages}`)
|
console.log(` sheets/PDF pages : ${r.sheets} / ${pages}`)
|
||||||
console.log(` people cards : ${r.cards} (${r.imgs} photos, ${r.nophoto} typographic)`)
|
console.log(` people cards : ${r.cards} (${r.imgs} photos, ${r.nophoto} typographic)`)
|
||||||
console.log(` prayer points : ${r.points} / ${POINTS_EXPECT}`)
|
console.log(` prayer points : ${r.points} / ${POINTS_EXPECT}`)
|
||||||
console.log(` wheel segments : ${r.wheelSegs}`)
|
console.log(` wheel segments : ${r.wheelSegs} (${r.wheelLabels}/${WHEEL_LABELS} labelled)`)
|
||||||
console.log(` Mark 5 in full : ${r.mark5Len} chars`
|
console.log(` Mark 5 in full : ${r.mark5Len} chars`
|
||||||
+ `${scriptureIsEnglish ? ' ⚠ UNTRANSLATED (English fallback)' : ''}`)
|
+ `${scriptureIsEnglish ? ' ⚠ UNTRANSLATED (English fallback)' : ''}`)
|
||||||
console.log(` metacamp.org : ${r.metacamp}`)
|
console.log(` metacamp.org : ${r.metacamp}`)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue