docs/coherence-classification.md
Agreement classification — and a live constitutional divergence
Refined invariant under test:
No projection should reconstruct semantics that already exist structurally upstream.
Agreement alone is not evidence of coherence. Every agreement is classified:
| Class | Meaning |
|---|---|
| Structural | projections read the same upstream fact |
| Derived | transformed from the same upstream fact |
| Accidental | independently reconstructed; agreement is a coincidence |
| Unknown | relationship not established |
Classification of every audited agreement
| Finding | Quantity | Class | Basis |
|---|---|---|---|
| — | "which agent is busiest" across panel / 3D / API | Structural | all read World.load |
| 3.2 | Article VI compliance | Accidental | verifier greps prose the composer wrote |
| 3.3 | operational status | Accidental | same ternary written twice |
| 3.4 | workload | Accidental → BROKEN | see below |
| 3.5 | entity kind | Accidental | id-string shape vs Building.kind |
No agreement in this system is Derived. Every one is either Structural (one source) or Accidental (duplicated logic). There is no middle case.
3.4 resolved — the accident has already broken, on a constitutional fix
The duplication
The weight formula is byte-for-byte identical in two places:
// build.ts:176 // state.ts:407
priority = p1?3:p2?2:1 p = p1?3:p2?2:1
weight += priority * sum + p *
(blocked ? 2 : 1) (blocked ? 2 : 1)
Different variable names, identical semantics. Classic accidental coherence.
Where it broke
The normalisation diverged, and it diverged because of a constitutional repair that landed in one projection only:
| Projection | Normalisation | Status |
|---|---|---|
build.ts → World.load |
min(1, log1p(w) / log1p(peak)) |
repaired for Article IV.4 |
state.ts:462 → CityNode.workload |
min(1, w / peak) |
original linear formula |
build.ts:200 records why the repair happened: "Linear scaling against the peak
erased the field: one agent with 40 blocked items drove another with genuine work
to 0.0042, which renders as empty."
That defect is still live in CityMap.
Measured divergence
Same organization, same agent with 3 open items, two projections:
| peak | World.load (log) |
CityMap.workload (linear) |
IV.4 breach in CityMap? |
|---|---|---|---|
| 160 | 0.3829 | 0.0375 | no |
| 300 | 0.3410 | 0.0200 | no |
| 600 | 0.3041 | 0.0100 | yes — renders as empty |
| 1200 | 0.2744 | 0.0050 | yes — renders as empty |
A 10× divergence at ordinary scale, and beyond peak ≈ 600 an agent with real work is invisible in the SVG city while reading 30% in the 3D world.
Peak 600 is one agent holding 150 blocked normal-priority items — large, but not hypothetical for an estate that accumulates.
The enforcement blind spot
constitution.ts:178 verifies Article IV.4 against world.agents[].load — the
repaired value. It never inspects CityNode.workload.
A constitutional invariant is enforced on one projection, violated in another, and the enforcement mechanism is structurally incapable of seeing the violation.
That is not a gap in the verifier's rules. It is a consequence of accidental coherence: the verifier checks the canonical world, and the second projection is not derived from it.
Why this vindicates the classification
Under agreement-only auditing, 3.4 looked fine — the two projections rank agents identically, because the weight formula matches. Ranking agreement concealed a value divergence of an order of magnitude, and a live constitutional violation.
Accidental agreement is not merely fragile in principle. Here it has already failed, silently, and the failure is a constitutional one.
The fix, stated but not applied
The only repair consistent with the invariant is to delete the reconstruction,
not to copy the logarithm into state.ts:
CityNode.workloadshould readWorld.agents[].load.CityNode.statusshould readWorld.agents[].status(finding 3.3, same shape).
Copying the corrected formula would restore agreement while leaving the coherence class Accidental — two implementations that happen to match again, awaiting the next one-sided repair. Reading the World makes it Structural, and structurally coherent projections cannot diverge.
The change touches page.tsx's CityView construction, lib/hq/view.ts, and
removes the parallel derivation in state.ts. It is larger than the incident
repair and is recorded, not applied.
Not attempted: finding 3.2, per standing instruction.