Move the pinned gap, and assert the filing that closed it
upg100 filed asia-india-madhya-pradesh and this check went red, which is the arm working. They reported it instead of deleting my expectation to make their own change green, and they were right that doing so is how a guard gets hollowed out. dx-shepherd ruled the two land together, which is the only ordering where neither of us is red in between. THIS COMMIT IS RED ON MAIN BY ITSELF. It expects three unfiled zones and today's data has four. It goes green with upg100's data change and not before, so the two must land in the same landing. The gap pin drops to guizhou, xinjiang and bihar. Filing is the good direction but it is exactly as revertible as any other data edit, so the three newly filed India zones now get an arm of their own: drop a key from zone-regions and those groups quietly leave the region tree again, with the bucket the only thing still carrying them. Two of the three were never visible to the gap arms at all, so without this they could be unfiled with nothing to say so. Also recorded what the gap number actually counts. It is admin-to-list's values, which is not every printable zone, so it is a lower bound rather than a census. upg100 proved that costs something: checking the property instead of the four names they were handed, they found four more unfiled zones, none of them an admin-to-list value, so none of them ever appeared in this number. A count that is quietly a lower bound reads exactly like a complete one. And the fixture arm no longer hardcodes the number four. The gap changes; a literal there turns every legitimate data fix into a confusing red in an arm that is not even about the data. It counts the pin instead.
This commit is contained in:
parent
493bbf45b8
commit
f3c050aed1
1 changed files with 33 additions and 4 deletions
|
|
@ -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')
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue