Sweep every browser gate for English-text matchers; fix the fifth and last
Some checks are pending
build-gate / build (push) Waiting to run

The same defect had surfaced in FOUR gates across previous ticks — a gate keyed on
English prose silently excludes every translated surface, or goes red on a
correctly translated one. Finding a fifth by accident would mean the pattern was
still being discovered rather than eliminated, so this sweeps all 25 gates that
drive a browser instead of waiting for the next one.

9 flagged, 8 benign: CSS class names (.vtl-fab, .stl-panel) and CSS property VALUES
(/paint|layout|strict|content/) are locale-independent by definition.

ONE REAL HIT — check-poster-prints.mjs:131, `/Gadarenes/.test(...)`. That is the
World English Bible's proper noun, so the assertion and the bug were locked
together: it passes today ONLY because point4_passage is still English in all ten
non-English blocks. The day a licensed translation lands it would have gone red on
a CORRECT packet. Now asserts the .p4-passage block by length, the same structural
fix already applied in check-packet-render and check-packet-browser.

Proved on the case the old matcher got wrong: renaming Gadarenes -> gadarenos, as
any translation would, now PASSES where /Gadarenes/ would have failed.
MUTATION-TESTED both directions — a passage truncated to 180 chars FAILS ("looks
truncated: 259 chars"), and the .p4-passage block renamed in the MARKUP FAILS
("no .p4-passage block").

★ ONE MUTATION SILENTLY DID NOT LAND, and it is worth recording. My first attempt
at the second mutation used a count=1 replace, which hit the explanatory COMMENT
rather than the markup — "p4-passage" appears twice in packet-render.js. The gate
"passed" and I nearly recorded a hole in the assertion. The assertion was sound;
the mutation was not. The sweep made the same class of error in the other
direction, flagging check-packet-render for a "Gadarenes" that lives only in a
comment explaining why it was removed.

Five instances found and fixed across five ticks; none remain in live code. The
rule for any new gate: if it matches on user-visible text, resolve the expected
string from the catalog for the page language, or assert on STRUCTURE — a class
hook, a length — instead.
This commit is contained in:
doxa-maps-88655c70 2026-09-24 11:00:29 +00:00
parent 9c802b556f
commit 96d7902a95

View file

@ -128,7 +128,14 @@ const r = await pg.evaluate(async ({ src, frame, packetRender, cardRender, qr, s
out.packetSheets = pdoc.querySelectorAll('.sheet').length
out.packetCards = pdoc.querySelectorAll('.card').length
out.packetWheel = pdoc.querySelectorAll('svg path[fill^="hsl"]').length
out.packetMark5 = /Gadarenes/.test(pdoc.body.innerText)
// ⚠ NOT /Gadarenes/. That is an ENGLISH proper noun from the World English Bible
// text, so this assertion would go RED on a CORRECTLY TRANSLATED packet and passes
// today only because point4_passage is still English in all ten non-English blocks
// (DECIDE-MARK5-SCRIPTURE-IS-ENGLISH-IN-EVERY-TRANSLATED-PACKET). The check and the
// bug were locked together — the same fix already applied in check-packet-render
// and check-packet-browser. Assert the passage BLOCK and its length, which holds in
// any language.
out.packetMark5Len = (pdoc.querySelector('.p4-passage') || { textContent: '' }).textContent.trim().length
// ── without a provider: must FAIL HONESTLY, not throw ────────────────────
const noProv = usePosterPrints({ label: (i) => i.label })
@ -155,13 +162,19 @@ if (!/no records provider/i.test(r.noProvMsg)) {
if (r.packetSheets !== 4) fails.push(`the packet printed ${r.packetSheets} sheets, expected 4`)
if (r.packetCards !== 2) fails.push(`the packet printed ${r.packetCards} people cards, expected 2`)
if (r.packetWheel !== 12) fails.push(`the prayer wheel has ${r.packetWheel} segments, expected 12`)
if (!r.packetMark5) fails.push('the packet is missing Mark 5:1-20 in full')
// The English passage is 2,141 chars; 1,200 is a floor no truncation or placeholder
// survives, with room for languages that render the same text more compactly.
if (r.packetMark5Len < 1200) {
fails.push(r.packetMark5Len === 0
? 'the packet is missing Mark 5:1-20 in full (no .p4-passage block)'
: `Mark 5:1-20 looks truncated: ${r.packetMark5Len} chars`)
}
if (errs.length) fails.push(`${errs.length} page error(s): ${errs[0]}`)
console.log(` list print : ${r.listRows} rows, checkbox=${r.listHasCheckbox}`)
console.log(` without provider : phase=${r.noProvPhase} "${r.noProvMsg.slice(0, 60)}"`)
console.log(` packet : ${r.packetSheets} sheets, ${r.packetCards} cards, `
+ `${r.packetWheel} wheel segments, Mark5=${r.packetMark5}`)
+ `${r.packetWheel} wheel segments, Mark5=${r.packetMark5Len} chars`)
console.log(` page errors : ${errs.length}`)
if (fails.length) {