docs/change-channels.md
Which visual channels can truthfully carry change
src/lib/world/changeset.ts, tests/changeset.test.ts
Position was settled first: trustworthy as identity, not as a change channel (embedding-stability). This asks the question one level up — of every channel, measured the same way.
First result — on Enterprise XI alone
Superseded by the falsification below. Kept because the retraction is only legible beside what it retracts.
1247 common subject-pairs over 8 adjacent revisions of this repository; 23 genuinely changed. Ground truth is computed from the facts — a subject changed iff its own measurements or couplings differ — never from what a channel reported, which would be circular.
| channel | kind | fires | FP% | FN% | AUC |
|---|---|---|---|---|---|
| box emissive intensity | world-normalised | 24 | 0.0 | 0.0 | — |
| box height | world-normalised | 15 | 0.0 | 37.5 | — |
| co-change position | solved | 139 | 90.6 | 43.5 | 0.739 |
| identity hue | direct | 0 | — | 100.0 | — |
| box footprint | constant | 0 | — | 100.0 | — |
| alert beacon and label colour | direct | 0 | — | 100.0 | — |
| capacity readout | direct | 0 | — | 100.0 | — |
AUC is blank for height and brightness because nothing false ever fired. That is not a missing result; it is the strongest possible one — there is no false distribution to separate from.
The height miss rate here read 0.0% when first published. That was an
instrument fault: box height was declared as unit 0–1 with floor 0.01
while HEIGHT_RULE emits 0.4–28, making the floor 26× more sensitive than the
stated convention. Corrected, height misses 37.5% of real byte changes even
on this repository (docs/reference-mechanisms.md). The clean case was never
clean.
Three groups, apparently separated by kind:
- Height and brightness fired on exactly the 23 changed subjects and never once otherwise. This was read as "subject-scoped scalars carry change perfectly." That reading does not survive — see below.
- The solved channel is the worst. Position fired 139 times for 13 real changes: 90.6% false, and it still missed 43.5% of what did change.
- Four of seven channels are dead. In a generated world hue derives from the
directory, footprint is constant, health is
unknownand capacity isnull. They carry no temporal information at all.
The channel that is best for identity is worst for change, and the reverse. Position is stable enough to make a city recognisable between revisions precisely because it responds to everything at once and therefore to nothing in particular. That is the same property, read twice. (This part stands.)
FALSIFIED: the law is about the reference, not the channel
The result above was read as "subject-scoped channels communicate subject change cleanly." That reading is wrong, and Enterprise XI is not representative.
Four repositories were generated to attack it — 11 revisions each, 33 files, deterministic seed. Instrument guard: the control has 1 distinct peak value across its history and each adversary has 11, so the adversaries really do move the reference.
Scored per channel against the metric that channel actually projects — height
against repo/bytes, brightness against repo/commits-touching, position
against couplings. (Subject-level truth, "did this subject change in any way",
is the wrong question: a file whose commit count moved but whose bytes did not
should leave height alone, and scoring that as a miss punishes the channel for
being right. Third instrument correction of this study.)
| scenario | height FP% | brightness FP% | position FP% |
|---|---|---|---|
stable-peak (control, mirrors Enterprise XI) |
0.0 | 83.3 | 66.7 |
moving-peak — the largest file is edited every revision |
94.6 | 96.9 | 74.4 |
monorepo — dominance rotates between components |
92.0 | 91.7 | 80.1 |
rotating-max — a different file is the maximum each revision |
90.2 | 88.9 | — |
Height goes from 0% to 95% false firings. Under a moving reference it is worse than position, the channel this investigation had already condemned.
Brightness is 83.3% false even in the control, because the churn reference moves whenever any commit lands. Its perfect score on Enterprise XI was a property of that repository's commit distribution, nothing more.
So the corrected law is:
A channel is clean iff the reference it is normalised against is stable. The channel's scope is irrelevant; the reference's scope is everything.
Characterised as a class in reference-mechanisms:
spurious change comes from a moving reference, invisible change comes from the
cap, and observed-peak — what ships — is the only mechanism that pays both.
Height and brightness are not subject-scoped at all — they are world-normalised
and always were. They looked subject-scoped because their divisor happened not to
move.
What survived falsification: the model
| every scenario | |
|---|---|
| false firings the model correctly disclaimed | 100% |
| real changes the model mislabelled | 0 |
In all four repositories, across every channel, the ChangeSet never once called
a spurious firing fact, and never once disclaimed a real one. The channels
degrade catastrophically; the attribution does not degrade at all.
That is the useful split. The renderer cannot trust a world-normalised channel,
and it does not have to — the model already knows, per mark, which firings are
about the repository. The repair is not a new channel or a new fact. It is that
the display must stop presenting normalisation firings as changes.
The blind spot on the other side
The same defect, seen from the reverse direction: the largest subject's height
can never change, because it is the reference and is pinned at 1.0.
Quadrupling the biggest file in the repository is invisible. Asserted in
tests/changeset.test.ts rather than worked around, so it fails if it moves.
The conditional that qualified the Enterprise XI scores
Height and brightness are world-normalised: they divide by the largest value
currently observed. A perfect score means the reference did not move, not that
it cannot.
Measured over the last 60 adjacent revisions: the peak source file was
src/lib/ledger/claims.ts at 35,540 bytes in every one of them, while the
file count grew 115 → 170. Sub-floor drift on unchanged subjects: 0 of 1224.
The reference is empirically immovable here.
But tests/changeset.test.ts shows what happens when it does move: adding one
500 KB file re-scales every building at once, and every one of those changes
is correctly attributed to normalisation rather than to the subject. So the
failure mode is not gradual — it is all-or-nothing, and it depends entirely
on whether the largest file happens to be under active edit.
Measured zero is not the same as structurally impossible — and the section
above proves it, by building the repositories where it does fire. The design
defect is observed-peak where rule.ts already has the vocabulary for a
declared-ceiling or stale-peak reference. It is unfixed.
What this rules out and rules in
Ruled out: motion as a change channel. Settled by measurement twice over — alignment cuts false motion 78.4% but leaves distributions that interpenetrate, and constraining the embedding drives false motion to zero without improving discrimination at all (AUC plateau 0.675 vs 0.831).
Ruled in: nothing yet. No channel currently in the system is unconditionally truthful about change. The two that scored perfectly did so because one repository's references happened to sit still, and both collapse past 95% false firings when they do not.
What is ruled in is the model: attribution survived every adversarial
repository at 100% soundness. Any channel can be made honest by consulting it —
which requires no new ontology, only that the display stop treating
normalisation as change.
Four channels are dormant, and that is not a mandate. Hue, footprint, beacon and capacity never fire, because a generated world has nothing to put in them. An earlier draft called this "available capacity" on the grounds that they are subject-scoped — the same reasoning the falsification destroyed. A dormant channel is evidence about the channel, not evidence that the ontology is missing a fact.
Before anything is invented to fill one: does the fact already exist in the canonical world? If not, is it canonical, or merely convenient because a channel is empty? Only a fact surviving the same reduction discipline as everything else may be introduced.
So the next question is not which channel, but which facts deserve a channel — the inverse of the question this investigation started with. And a dormant channel is not evidence that the ontology is incomplete: before any fact is invented to fill one, it must already exist in the canonical world, or survive the same reduction discipline as everything else.
The lesson that outlives MDS
False motion can be reduced to zero without making motion informative.
Every anchor weight from λ=0.3 upward drove false motion down — to literally zero at λ=10 — and left discrimination flat at AUC 0.675. The noise went away and the signal went with it.
Less visual noise is not the same as more information. A channel is not improved by being made quieter; it is improved by being made discriminative, and those are independent properties. Every quietening change must therefore be measured against a discrimination metric, or it will look like progress while being none.