diff --git a/internal/check-gospel-coverage-consistent.mjs b/internal/check-gospel-coverage-consistent.mjs index d8a1c08d3..8bf6a4977 100644 --- a/internal/check-gospel-coverage-consistent.mjs +++ b/internal/check-gospel-coverage-consistent.mjs @@ -55,6 +55,7 @@ const REPO = resolve(dirname(fileURLToPath(import.meta.url)), '..') const POISON = process.argv.includes('--poison') let poisonStale = false let poisonTable = false +let poisonGapKind = false const read = (p) => JSON.parse(readFileSync(resolve(REPO, p), 'utf8')) let pins, table, verif @@ -93,6 +94,7 @@ if (POISON) { poisonStale = true // L codes.zzm = { l: 'Claims a pool nobody swept for it', ck: 'ebible, grn', s: 'https://ebible.org/zzm/' } // M poisonTable = true // N + poisonGapKind = true // O } const SPECIAL = (c) => c === 'und' || c === 'mul' || c === 'mis' || c === 'zxx' || (c >= 'qaa' && c <= 'qtz') @@ -336,13 +338,45 @@ if (verif && verif.links) { } } +/* ── O: every gap row is classified, and the classification means what it says ─────────── + "1,845 groups have nothing" is four situations wearing one number, and the map and the + exported table each state the split. They did not agree: the table tested sign language + first, the map tested private-use first, so 47 Deaf groups landed in different buckets and + the Deaf share read 136 in one place and 183 in the other. Both were internally consistent + and they told different stories, which is worse than one of them simply being wrong. + + This holds the table to three things a reader depends on: every tier-0 group appears + exactly once, every row carries a kind, and a sign language is ALWAYS labelled as one — + never as an unindexable code — because being Deaf is the actionable fact and every + private-use code in this gap belongs to a sign language anyway. */ +{ + let t + try { t = read('data/tables/gospel-gaps.json') } catch { t = null } + if (t) { + const tier0 = rows.filter((r) => r[6] === 0).length + const gapRows = (t.rows || []).length + if (tier0 !== gapRows) { + add('O', `the gap table has ${gapRows} row(s) but ${tier0} pin(s) are tier 0 — one of them is stale`) + } + const unclassified = (t.rows || []).filter((r) => (poisonGapKind ? true : !r.gap_kind)).length + if (unclassified) add('O', `${unclassified} gap row(s) carry no gap_kind`) + const mislabelled = (t.rows || []).filter((r) => { + const c = codes[r.iso639_3] + return c && c.sg === 1 && !/sign language/.test(r.gap_kind || '') + }) + if (mislabelled.length) { + add('O', `${mislabelled.length} sign-language row(s) are not labelled as sign languages (e.g. ${mislabelled.slice(0, 3).map((r) => r.iso639_3).join(', ')}) — the Deaf share of the gap will read low`) + } + } +} + const clauses = new Set(fails.map((f) => f.slice(3, 4))) if (POISON) { // D is included deliberately: it is the clause that would have caught the 506 // resources dropped from a table titled "every link", and the most valuable clause is // the worst one to leave unproven. The injected codes above (und, zzq) are absent from // the table, so they poison D as well as A and B. - const want = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N'] + const want = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'] const caught = want.filter((c) => clauses.has(c)) console.log(`COVERAGE-CONSISTENT --poison: ${caught.length}/${want.length} clause(s) caught their injected defect (${caught.join(',')})`) if (caught.length !== want.length) { @@ -370,3 +404,4 @@ console.log(' K every shipped link is verified, and none known-broken ships') console.log(' L the verification record is current, not merely consistent') console.log(' M a pool named as checked was really searched for that code') console.log(' N a table\'s has-anything column agrees with the pin tier') +console.log(' O every gap row is classified, and a sign language says so')