From df42fe74387773f84dbae9f72531078b07b7a971 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Mon, 28 Sep 2026 15:19:13 +0000 Subject: [PATCH] Fold the zone-tree assertions in, and stop the check dying before it reports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One file for one plugin's zone data: the join and the tree over the same zones were two scripts only because the first was already queued for landing. The tree section pins the id namespaces. The legend emits one bare string on one channel, and the zone and region id spaces share exactly one name, so un-namespaced that string cannot say which row was clicked. The fixture gives that region two zones on purpose — today's data gives it one, so both readings return the same set and a check built on the real table would pass without ever exercising the difference. It would be measuring the data rather than the code. Poisoning the namespace exposed a worse problem than the one being guarded. An unguarded lookup threw when the region id stopped existing, so the file died at the third assertion and the seven after it never ran — including the one the section exists for. The crash still exited 1, so it read exactly like the check catching the bug. Guarded, five arms now go red by name instead of one stack trace. A check that dies reports less than a check that fails. The summary arm is labelled as the weakest rather than the strongest. Under the poison the two readings still differ, both wrong, so it stays green while the specific lengths go red. It states the property; it does not guard it. --- internal/check-upg-zone-joins.mjs | 48 ++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/internal/check-upg-zone-joins.mjs b/internal/check-upg-zone-joins.mjs index 62329351f..e58828b31 100644 --- a/internal/check-upg-zone-joins.mjs +++ b/internal/check-upg-zone-joins.mjs @@ -18,6 +18,13 @@ * a plain string, while the source shape is `{ value, label }` before normalize.js * flattens it. Passing the object form matches nothing and returns an empty Set * for EVERY zone, which reads as "these zones have no groups". + * + 3. THE ZONE AND REGION ID SPACES OVERLAP. The legend emits ONE BARE STRING on one + * channel — a leaf emits its zone id, a region row emits the region's — and of 33 zone + * ids and 7 region ids exactly one name is shared, whose region is itself. Un-namespaced + * that string cannot say which row was clicked. It is harmless today ONLY because that + * region currently holds one zone, which is a fact about the data rather than a property + * of the design. * * EACH ARM IS CHECKED IN BOTH DIRECTIONS. The negative arms are the point: they record * what the fold and the flattening are BUYING, so a later reader asking "is this still @@ -28,6 +35,8 @@ import { readFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' import { dirname, join } from 'node:path' import evaluate from '../plugin-designs/my-upg-100-list/data/selector-evaluator.js' +import { buildZoneTree, zonesForSelection, isRegionId, regionOf, humanize, REGION_PREFIX } + from '../plugin-designs/gospel-internet/src/zoneTree.js' import { zonesByGroup, zonesBySelector, toSelectorRecord } from '../plugin-designs/gospel-internet/src/upgZones.js' const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..') @@ -77,8 +86,45 @@ const obj = zonesBySelector(zoneLists, objShaped, evaluate) ok('selector join, OBJECT-shaped — zones with members (must be 0)', [...obj.members.values()].filter((s) => s.size).length, 0) +// ── 3. the zone/region id namespaces ──────────────────────────────────────── +// The fixture gives the colliding region TWO zones ON PURPOSE. Today's data gives it one, +// so both readings of the bare id return the same set and a check built on the real table +// would pass without ever exercising the difference — it would be measuring the data, not +// the code. regions' check watches the shipped tables and fails if the colliding set moves; +// this pins the behaviour that makes a collision harmless when it arrives. +const ZR = { + europe: 'europe', // the colliding name: a zone AND a region + 'europe-balkans': 'europe', // the second zone today's data does not yet have + 'asia-india-gujarat': 'asia', + brazil: 'latam', +} +// ?. and ?? -1 below are NOT defensive noise. Poisoning the namespace makes `region:asia` +// stop existing, and an unguarded `.count` THREW — the file died at the third assertion and +// the seven after it, including the one this section exists for, never ran. The crash still +// exited 1, so it read like the check catching the bug. A check that dies reports less than +// one that fails by name: guard the lookups so every arm runs and says what it saw. +const tree = buildZoneTree(ZR, { counts: { 'asia-india-gujarat': 7 } }) +ok('tree: every region row is namespaced', tree.every((n) => n.id.startsWith(REGION_PREFIX)) ? 1 : 0, 1) +ok('tree: leaves stay bare', tree.flatMap((n) => n.children).every((c) => !isRegionId(c.id)) ? 1 : 0, 1) +ok('tree: a region rolls up its children counts', tree.find((n) => n.id === 'region:asia')?.count ?? -1, 7) +const asLeaf = zonesForSelection('europe', ZR) +const asRegion = zonesForSelection('region:europe', ZR) +ok('tree: the bare id means that ZONE only', asLeaf?.length ?? -1, 1) +ok('tree: the namespaced id expands to the REGION\'s zones', asRegion?.length ?? -1, 2) +// A SUMMARY ARM, AND THE WEAKEST ONE — kept for what it says, not for what it catches. +// Under a poisoned namespace the two readings still DIFFER (2 vs 0), both wrong, so this +// arm stays green while the two above it go red. The specific lengths are the guards; this +// line only states the property they add up to. Labelled honestly so nobody trusts it alone. +ok('tree: the two readings of the colliding name are not the same set (summary)', + JSON.stringify(asLeaf) !== JSON.stringify(asRegion) ? 1 : 0, 1) +ok('tree: a bare id never reads as a region', (!isRegionId('europe') && regionOf('europe') === null) ? 1 : 0, 1) +const sweep = new Set(tree.flatMap((n) => zonesForSelection(n.id, ZR))) +ok('tree: sweeping every region reaches every FILED zone and no more', sweep.size, Object.keys(ZR).length) +ok('tree: there is no region-based "all" to misuse', zonesForSelection(null, ZR) === null ? 1 : 0, 1) +ok('tree: humanize is only a fallback label', humanize('asia-india-gujarat') === 'Asia India Gujarat' ? 1 : 0, 1) + if (fail.length) { console.log(`\nUPG-ZONE-JOINS: FAIL — ${fail.length} assertion(s): ${fail.join(', ')}`) process.exit(1) } -console.log('\nUPG-ZONE-JOINS: PASS — both joins pinned in both directions') +console.log('\nUPG-ZONE-JOINS: PASS — both joins pinned in both directions, and the id namespaces cannot collapse')