Assert that no ring value makes a group vanish

The bounded half already asserts that its total is conserved; the centered half
did not. It pins the three states as separate, and separateness is not
completeness: a group with a ring nobody anticipated could fall out of placed,
centre and unplaced alike and simply not exist on the page.

That is the failure that looks like a smaller dataset rather than an error. An
empty chart gets noticed; a chart quietly missing eleven groups does not, and
eleven is exactly how many carry ring -1 today.

Checked with the awkward values rather than the tidy ones: out of range high and
low, missing, fractional, and a numeric string. All seven are accounted for, the
out-of-range pair land in unplaced rather than being clamped to ring 1 or 10,
and a fractional ring is unplaced rather than rounded onto a neighbour it does
not belong to.

Falsified before trusting it: a filter that silently drops non-integer rings
turns the arm red at 5 of 7. The negative control also pins that the count moves
with the input, so it is not counting a constant.
This commit is contained in:
Doxa Maps 2026-09-28 16:04:08 +00:00
parent 00e505404c
commit 288bbf278a

View file

@ -139,6 +139,31 @@ ok('centered: a placed group with no recorded neighbour yields NO arrow',
noNb.placed.length === 1 && inwardArrow(noNb.placed[0], {}) === null)
// ★ CENTERED CONSERVATION, which the bounded half already asserts and this half did not.
// The three states are pinned as SEPARATE above, but separateness is not completeness: a group with
// a ring nobody anticipated could fall out of all three and simply not exist on the page. That is
// the failure that looks like a smaller dataset rather than an error — an empty chart gets noticed,
// a chart quietly missing eleven groups does not. Checked with the awkward values on purpose:
// out-of-range high and low, missing, fractional, and a numeric STRING.
const odd = [
{ id: 'hi', ring: 99 }, { id: 'lo', ring: -5 }, { id: 'centre', ring: 0 },
{ id: 'norel', ring: -1 }, { id: 'none' }, { id: 'str', ring: '3' }, { id: 'frac', ring: 3.5 },
]
const oddL = layoutCenteredSet(odd, {})
const accounted = oddL.placed.length + oddL.centre.length + oddL.unplaced.length
ok('centered: total is conserved — no ring value makes a group vanish',
accounted === odd.length, `${accounted} of ${odd.length}`)
ok('centered: an out-of-range ring is UNPLACED, never clamped into ring 1 or 10',
oddL.unplaced.some((p) => p.id === 'hi') && oddL.unplaced.some((p) => p.id === 'lo') &&
!oddL.placed.some((p) => p.id === 'hi' || p.id === 'lo'))
ok('centered: a fractional ring is unplaced rather than rounded onto a neighbour',
oddL.unplaced.some((p) => p.id === 'frac'))
// NEG CONTROL: the conservation arm can fail, so it is not counting a constant.
ok('NEG CONTROL: dropping one group from the input drops the accounted total',
(() => { const l = layoutCenteredSet(odd.slice(1), {}); return l.placed.length + l.centre.length + l.unplaced.length === odd.length - 1 })())
if (fail.length) {
console.log(`\nGOSPEL-SET-CHARTS: FAIL — ${fail.length}: ${fail.join(', ')}`)
process.exit(1)