diff --git a/internal/check-list-selection.mjs b/internal/check-list-selection.mjs index c64ea78c8..4d90bc7e0 100644 --- a/internal/check-list-selection.mjs +++ b/internal/check-list-selection.mjs @@ -35,8 +35,13 @@ const MISSING = [ 'asia-china-guizhou-province', 'asia-china-xinjiang-uyghur-autonomous-region', 'asia-india-bihar', - 'asia-india-madhya-pradesh', ] +// asia-india-madhya-pradesh WAS here and is now FILED. upg100 hit this arm while filing it, and +// did the right thing with it: they reported the red instead of editing my expectation to make +// their change green — "editing someone else's pinned expectation to make my own change green is +// precisely the move that hollows out a guard". dx-shepherd then ruled that their data and this +// fixture land TOGETHER, which is the only ordering where neither of us is red in between. + ok(leavesOf(TREE[0]).map((l) => l.id).join(',') === 'z1,z2,z3', 'leavesOf walks NESTED children, not one level') ok([...zoneIdsIn(TREE)].sort().join(',') === 'z1,z2,z3', 'zoneIdsIn collects every leaf id in the tree') @@ -53,11 +58,15 @@ const all = ['z1', 'z2', 'z3', ...MISSING] const withBucket = withUnassigned(TREE, all, 'Unassigned') ok(withBucket.length === TREE.length + 1, 'zones absent from the tree get an explicit bucket') const bucket = withBucket[withBucket.length - 1] -ok(bucket.id === UNASSIGNED_ID && bucket.children.length === 4, 'and all four missing zones are in it') +// Counted from MISSING, never written as a literal: the gap CHANGES (upg100 filed one while I was +// writing this), and a hardcoded 4 here turns every legitimate data fix into a puzzling red in an +// arm that is not even about the data. +ok(bucket.id === UNASSIGNED_ID && bucket.children.length === MISSING.length, + `and all ${MISSING.length} missing zones are in it`) ok(bucket.children.map((c) => c.id).includes('asia-china-xinjiang-uyghur-autonomous-region'), 'including xinjiang — the consumer\'s largest zone at 100 groups, which a region tree loses silently') ok(bucket.children.every((c) => c.id && c.zoneKey), - 'each is a SELECTABLE leaf, not a lump — a reader wants xinjiang, not "the four nobody filed"') + 'each is a SELECTABLE leaf, not a lump — a reader wants xinjiang, not "the ones nobody filed"') ok(withUnassigned(TREE, ['z1', 'z2', 'z3']).length === TREE.length, 'CONTROL: no bucket appears when nothing is missing') ok(withUnassigned(TREE, null).length === TREE.length && withUnassigned(TREE, []).length === TREE.length, @@ -70,7 +79,7 @@ ok(!zoneIdsIn(naive).has('asia-china-xinjiang-uyghur-autonomous-region'), // ── a region sweep is NOT a zone sweep (gospel, END-GOS-VLG2) ─────────────────────────────────── // ★ The consequence of the bucket that neither of us should leave implicit: ticking every REGION -// still does not select every ZONE, because the four unfiled zones have no region BY DEFINITION. +// still does not select every ZONE, because the unfiled zones have no region BY DEFINITION. // Nothing on screen would say so — the reader just gets a smaller total, which is the exact // silent-wrong-answer shape the bucket exists to end. So if a "select all" is ever added it must // sweep ZONES, not regions, or it inherits the bug. Pinned here so the wrong one cannot ship @@ -114,6 +123,14 @@ const adminToList = readJson('admin-to-list.json') // admin name -> zone id const filed = new Set(Object.keys(regionOf)) const joinable = new Set(Object.values(adminToList).map(String)) const realGap = [...joinable].filter((id) => !filed.has(id)).sort() +// ★ WHAT THIS GAP COUNTS, AND WHAT IT DOES NOT. `joinable` is admin-to-list's VALUES — zones +// reachable by an admin-area join. That is NOT the same as every printable zone, so this arm can +// only ever report a LOWER BOUND on unfiled zones. upg100 proved the difference costs something: +// checking the property rather than the four names they were handed, they found deaf-old-world, +// deaf-new-world-asia-pacific, asia-india-uttarakhand and asia-india-west-bengal also unfiled, +// and none of the four is an admin-to-list value, so none of them appears in realGap. Two were +// then filed; the deaf pair look deliberate (there is a "deaf": "exempt" umbrella key). Stated +// here because a gap number that is quietly a lower bound reads exactly like a complete one. ok(realGap.length > 0, realGap.length > 0 @@ -123,6 +140,18 @@ ok(realGap.join(',') === MISSING.join(','), realGap.join(',') === MISSING.join(',') ? 'and it is exactly the four this check names, so the fixture above models the shipped data rather than a story about it' : `THE GAP MOVED — re-derive. shipped now: [${realGap.join(', ')}] but this check asserts: [${MISSING.join(', ')}]. A zone ADDED here is groups that just became unreachable; a zone REMOVED got filed and the fixture is stale. Either way the numbers in the commit body are no longer true.`) +// ── the zones that got FILED stay filed (dx-shepherd RG12) ───────────────────────────────────── +// The gap arms watch the BAD direction. Filing is the good one, and it is exactly as revertible: +// drop a key from zone-regions and those groups leave the region tree again, silently, with the +// bucket the only thing still carrying them. Two of these three were never visible to the gap arms +// at all (see the coverage note below), so without this they could be unfiled with nothing to say so. +const FILED = ['asia-india-madhya-pradesh', 'asia-india-uttarakhand', 'asia-india-west-bengal'] +for (const z of FILED) { + ok(filed.has(z), filed.has(z) + ? `${z} is filed under a region, so it reaches readers through the tree and not only the bucket` + : `${z} IS NO LONGER FILED — it was given a region and has lost it, so its groups are back to being reachable only through the unassigned bucket. That is the silent direction: no error, just a shorter region tree.`) +} + ok(joinable.has('asia-china-xinjiang-uyghur-autonomous-region') && !filed.has('asia-china-xinjiang-uyghur-autonomous-region'), 'xinjiang specifically: joinable in admin-to-list, absent from zone-regions — its 100 groups are reachable ONLY through the bucket')