Skip to content
← Documentation

docs/worldscene-audit.md


WorldScene against the grammar

The grammar run against the actual renderer. Executable: tests/worldscene-audit.test.ts.

Outcome: one illegal visual claim, and it is position. The repair class is representation — the canonical source already exists and the renderer does not consume it. Two other candidates were investigated and withdrawn as unreachable, which is recorded because withdrawing them was the harder call.


The finding

Visual claim. Two buildings drawn near each other are near each other.

Violated rule. R2 proximity-invented — a categorical space placed on a spatial channel with no declared metric.

Missing canonical source. None is missing. slots.ts:98 places every unrecorded subject at hash32(id) % capacity. Rendered position is a hash of the subject's name.

Repair class: representation gap. Not an observation gap and not a semantic ownership gap.

Why it is a representation gap and not the others

layout.ts:118 exports layoutFrom(exchanges), which derives placement from couplingMatrix — proximity computed from exchange facts, exactly what R2 requires. It is consumed by CouplingField.tsx and by nothing else.

Two placement systems exist. The metric-derived one renders a different component; the ring-slot one renders the city.

So the facts are observed, the semantics are canonical and singly-owned, and the metric is derived. Only the renderer's input is wrong.

Corroboration

In the scale-10 fixture, over all 4,950 building pairs:

mean rendered distance   linked = 500.0   unlinked = 333.3   ratio = 1.500

Buildings that exchange are drawn 1.5× farther apart than buildings that do not. Position is not merely uninformative about coupling — in this fixture it is anti-correlated with it.

The mechanism is topological, and I should not overstate it: every fixture link is hub-to-spoke, and a radius is longer than an average chord. So the 1.5× is a property of this fixture, not a law. The finding does not rest on it. The finding rests on hash32(id), which is in the source and needs no fixture.

What was already declared, and what was not

projection.ts:131 already carries an ids→plots entry declaring that assignSlots loses which plots came from the register and which were allocated by hash.

That is an honest declaration about assignSlots's own output. It does not cover this finding. The declared loss is internal to the function; the finding is that the rendered spatial channel asserts a relation to a viewer that no fact licenses. The Information Ledger tracks what a function discards. It does not track what a projection claims.

That is a gap in the ledger's scope, not a failure of its honesty — and it is worth stating plainly, because the ledger's existence made it easy to assume this had been covered.


Channels audited

Six, read from source with line references, all in the test.

Channel Licensed by Canonical? Meanings Verdict
ring hue (171) district accent identity 1
ring opacity (174) district.activity yes 1
emissiveIntensity (292) building.activity yes 1
box height (336) a declared measure yes 1
link dash (240) link.kind yes 1
position (275) hash32(id) no R2

Two channels carry activity — ring opacity and emissive intensity. That is sufficiency, not overload: one channel still carries one meaning, and the closure/sufficiency distinction says a fact with two carriers survives losing one. R6 is not triggered and should not be.

period = 9 - min(1, flow) * 6.5 (line 217). Travel time is derived from flow, so the motion channel is a real readout, not decoration. This is the one place a temporal channel carries an ordered state honestly, and it passes.


Two candidates investigated and withdrawn

Both looked like findings, and reporting them would have been wrong. Recorded because the withdrawal is the substantive part.

1. Building opacity carries isLot and unobserved (line 299). opacity={isLot ? 0.35 : unobserved ? 0.5 : 1} — the lot branch wins, so a lot that is also unobserved renders identically to an observed lot.

Measured: atScale(1) produces 0 lots. The state is not reachable in any fixture available to me, and this project's own rule — never vary fields independently unless the generator can emit that state — applies to findings as much as to fixtures. Withdrawn as unreachable, not as false. It may be reachable against the live substrate, which I cannot exercise here.

2. Link opacity carries handoff and flow (line 239). opacity={handoff ? 0.75 : 0.1 + link.flow * 0.45} — when handoff is true, flow is unrepresentable, and handoff already has its own channel (colour, line 236). That would be R3 with no compensating gain.

Measured at scale 10: only road links exist; no handoff link is produced. Withdrawn as unreachable.

Both would have been plausible findings supported by a source read. Neither survived a reachability check. That is three times in this investigation that a reachability check has overturned a reading of the source, and it is the reason the check is not optional.


Standing

Question Answer
Are all visual claims licensed? no — one is not
Which? position, on R2
Missing canonical source? nonelayoutFrom exists and is unconsumed by the scene
Repair class representation gap
Does the ontology need extending? no — nothing was added to make anything pass
Purity unchanged; no canonical logic was duplicated into the renderer

Not repaired. The directive was the smallest falsifiable finding, not a refactor. The audit test asserts the exact violation set, so wiring layoutFrom into placement will fail this test and retire the finding — the same mechanism the blocker tests use, where a change in reality breaks the expectation rather than waiting for someone to remember.

What is still not established

  • The audit covers six channels. WorldScene.tsx is 457 lines and carries more — beacons, agent elevation (busy ? 3.2 : 2.2), labels, wireframes. The table is a start, not a census, and busy-as-elevation is the next candidate.
  • Reachability was tested against fixtures only. The two withdrawn findings need a live substrate to settle.
  • Whether the ring layout is deliberately non-semantic — a stable civic map that never claimed to encode coupling — is a design question the grammar cannot answer. The grammar says the channel makes a claim; whether the claim was intended is not a measurement.

165 tests → 168, tsc clean.