Hold the gap table to the split it publishes
Last tick the map and the exported gap table bucketed the same 1,845 groups differently — 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 told different stories, which is worse than one being plainly wrong: a reader comparing them cannot tell which to believe. I fixed it by hand, which fixes today only. Clause O holds three things a reader depends on: every tier-0 group appears in the table exactly once, every row carries a kind, and a sign language is ALWAYS labelled as one rather than 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. Checked against the real defect, not a synthetic one: putting the precedence back the wrong way round makes it fail with "47 sign-language row(s) are not labelled as sign languages (e.g. qcd, qiq, qns) — the Deaf share of the gap will read low". Poison is 15/15.
This commit is contained in:
parent
2046f2febd
commit
9d1a0acd9e
1 changed files with 36 additions and 1 deletions
|
|
@ -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')
|
||||
|
|
|
|||
Loading…
Reference in a new issue