docs/physicalization-roadmap.md
Physicalization Roadmap
Status: specification frozen. The Constitution, ontology, representation model and metric-layer principles are treated as given. No new framework is proposed below. Where the existing implementation is insufficient, that insufficiency is measured and named, not designed around.
Required invariant, both directions:
Facts → Properties → Metrics → Geometry → Rendering
Rendered Property → Geometry → Metric → Properties → Facts
0. Findings that constrain the roadmap
Three results from measurement. Each changes task ordering; none is optional.
0.1 plots.ts is a fact table stored as source code — FALSIFIED
Superseded by measurement. The section below is preserved as written because the negative result is the finding. P1 was run as an experiment and failed on both halves, for two independent reasons, each with an executable witness in
tests/plot-register-necessity.test.ts.
There is no seniority to record.
git log -Sover every product and agent id returns exactly one distinct timestamp: the whole population entered in a single commit. Arrival order was never observed. It is not a fact missing from the vocabulary — it is information that does not exist. Asincefield would not derive the order, it would invent it, and hand-entered dates are the same manual arrangement in a fact's costume.The register holds what no function of the present set can reproduce. Product plot 1 was allocated to
emp, an entity since removed. Any allocator over a total order on the present entities yields a dense0..n-1; this register has a gap, so no such function produces it. The gap is what keepsplatformat plot 4 instead of sliding to 3 — densifying it moves four incumbents, which Article III.4 forbids.Correct reclassification, stated conditionally:
plots.tsis currently justified as an append-only allocation ledger, because the evidence required to derive its contents is absent from the observable object space. Not "cannot ever be derived": the criterion is universal, the verdict contingent. Deleting it today destroys the record rather than simplifying the code.The predicted milestone — a manually maintained representation eliminated because an executable derivation became sufficient — was not achieved, and is not achievable here. The derivation is provably insufficient. What the experiment established instead is a criterion for when such a replacement is possible at all: only where the discarded structure carries no history, and where the ordering it encodes was actually observed rather than assumed.
The governing principle is "nothing may be manually arranged." Position today
comes from src/lib/world/plots.ts — a hand-maintained register. By the literal
reading, position is the single largest violation in the system.
It was proved earlier that position cannot be a pure function of the present entity set without violating Article III.4: seniority is not recoverable from the ids that exist now, and any order-sensitive allocator moves incumbents when a newcomer sorts earlier.
Both are true, and they are not in conflict. The proof constrains pure functions of the entity set. It says nothing about functions of facts. If first-observation is recorded as a fact, then
plot = allocate(entities ordered by first-recorded-at)
is derived, stable under growth, and manually arranged nowhere. plots.ts is
not evidence that geometry must be chosen; it is evidence that a fact family
is missing. The repair is to move it into the fact vocabulary — not to compute
it away, which is impossible, and not to keep it, which is manual arrangement.
This is the roadmap's spine. Every other geometric property depends on position, and position is not derivable until entity existence is a fact.
0.2 The fact substrate for the primary objective already exists
The primary objective names position, distance, clustering, hierarchy,
movement, visibility, topology. All seven are graph properties. ExchangeFact
{ fromId, toId, kind, weight, at, evidence }
is a weighted, directed, timestamped graph over subjects. It is ratified, it is populated, and it is consumed today by exactly two components for line drawing.
No new ontology is required for the metric layer. That is a measured result, and it discharges the brief's condition for proposing one: the current implementation is sufficient at the fact layer.
Asymmetry is not a defect to normalize away. A directed exchange graph induces a quasi-metric, which is the one point where the closed mathematical programme touches implementation — as a constraint on what the metric may assume (no symmetry, no triangle equality), not as new theory.
0.3 Reconstruction from geometry alone is impossible, by counting
The brief requires that where reconstruction is impossible, the impossibility be proved precisely. For layout it is provable and needs no appeal to implementation:
Let n subjects carry a weighted directed exchange relation. The fact content is up to n(n−1) independent weights. A planar layout is 2n numbers. For n ≥ 4, 2n < n(n−1). No injective map from exchange-weight space to planar position space exists. Therefore no layout algorithm whatsoever permits recovery of the exchange facts from rendered positions alone.
At n = 5 the system carries up to 20 weights in 10 coordinates. The loss is structural, not a property of any particular algorithm, and it cannot be engineered away.
Consequence. The reverse chain Rendered → … → Facts cannot close by
inversion at the geometry stage. It can only close if geometry ships with the
residual required to invert it. Reconstruction is therefore an artifact the
renderer must emit, not a property the geometry can possess. Every task below
carries a reconstruction criterion in that form.
This is the honest reading of "the renderer must never invent information": the renderer may not invent, and it also may not silently destroy — where it must destroy, it must record what it destroyed.
1. What is blocked, and by what
| Blocked | By | Why |
|---|---|---|
| Any new visible property | needs its own Article X amendment | a visible property needs a Legend row, and the Legend is constitutional. AMD-0003 was vetoed 2026-08-03, so nothing is pending — but nothing is thereby permitted: amending a constitutional file requires proposing and deciding an amendment |
| Height quantisation (II.2, II.3 / tripwire W5) | floor/tier units undecided | the band edges are the decision |
Retiring repo-todos legacy identity |
Gap surfacing design | F6b |
Nothing else is blocked. The roadmap is sequenced so that P0–P3 complete entirely inside non-constitutional files, and the constitutional dependency lands only at P4 — by which point the amendment will have been resolved or the work will stop at a provably complete metric layer with no visible binding.
That ordering is deliberate: it front-loads everything that can be falsified without a ratification decision.
2. Tasks
P0 — Renderer-observing test harness
Validation question 6 — can the rendered property be traced completely back to facts? — is currently unanswerable, because zero tests import any renderer component. Every success criterion below is unmeasurable until this exists. It is therefore first, ahead of any metric.
| Constitutional dependency | none |
| Implementation dependency | none |
| Measurable success criteria | a test renders WorldScene and CityMap to static markup, parses the result, and returns every attribute-value pair actually emitted. The count of enumerated attributes is asserted against the count the grammar predicts, and the two are equal by construction |
| Reconstruction criteria | none — this task builds the observation surface, it does not transform information |
| Validation strategy | mutation: change one literal in one component; the harness must report exactly one changed attribute. If it reports zero, the harness is not observing the rendered surface and the task has failed |
Measured, and P0 as first written is falsified. The probe was run. Two results, the second more serious than the risk I had recorded:
- Importing
WorldSceneunder--conditions=react-serverthrowsTypeError: o.createContext is not a function. Client components need a second test condition, as anticipated. - The two renderers do not share an output surface.
CityMapemits SVG — 20 markup elements, parseable attributes.WorldSceneis@react-three/fiber— 16 scene elements,three,useFrame. Its geometry goes to the GPU. It has no DOM attributes to enumerate, sorenderToStaticMarkupyields a canvas element and nothing about what was drawn.
This is Attack 1 from verification-theory.md arriving in the repository: the
object space "attribute bindings in markup" does not merely miss positions in
WorldScene, it fails to range over it at all.
It matters because of where the known defects are. Of the eight measured
violations, six are in the renderer with no markup surface — all three
Article VI undeclared bands (:174, :239, :282) and three of the five Article
I.3 classifications (:280, :389, :390). Only CityMap:436 and :704 sit on
the observable surface.
P0 therefore splits:
- P0a — SVG surface (
CityMap). Unblocked, no new dependency. Closes two violations with proof. - P0b — scene-graph surface (
WorldScene). Requires observing the r3f scene graph, which needs@react-three/test-rendereror equivalent. That is a dependency decision, and it is the ratifying authority's, not mine.
Extracting the geometry into a pure function and testing that is available
without any dependency, and must be recorded as what it is: verification against
an intermediate representation, which verification-theory.md §5 identifies as
the failure mode where the test passes and the rule is violated with no signal.
It is already the exact mistake made once at CityMap.tsx:436. It would close
no violation with proof, and should not be counted as if it had.
This task also closes the §5 coverage violation recorded in
verification-theory.md: today rules about rendered output are verified against
composeWorld, an intermediate object. That is the failure mode where the test
passes and the rule is violated with no signal — already observed once, at
CityMap.tsx:436.
P1 — Existence as a fact
| Constitutional dependency | Article III.1–III.4 (position permanent, stable under growth) |
| Implementation dependency | P0 not required; independent |
| Measurable success criteria | a fact family records first-observation per subject. plots.ts is deleted. assignSlots consumes the fact. Adding an entity moves zero incumbents; removing one moves zero survivors; both asserted over a generated population, not a fixture of five |
| Reconstruction criteria | complete and invertible. Plot ↔ seniority rank is a bijection given the entity set. From rendered plot indices plus the entity set, the seniority order is recoverable exactly. This is the one stage in the whole chain that loses nothing |
| Validation strategy | the existing spatial-stability suite must be observed failing against a re-derivation that ignores the seniority fact, then pass. Property test: for every permutation of arrival order, incumbent plots are invariant under subsequent arrivals |
P1 is the only task that makes an existing hand-maintained file disappear. Its
success is binary and externally visible: plots.ts exists, or it does not.
P2 — The coupling quasi-metric
The first derived metric. Full seven-question validation in §3, including one answer of "no."
| Constitutional dependency | Article VI (declared normalisation) — the weight→distance transform is a band and must be declared. This is the first point of contact with a constitutional file and it is deferred to P4; P2 declares the transform in the metric module and marks it undeclared-at-Legend |
| Implementation dependency | ExchangeFact (exists, ratified, populated) |
| Measurable success criteria | d(a,b) computed from exchange weights alone. Asserted: non-negativity; d(a,a) = 0; d(a,b) = ∞ where no path exists; asymmetry preserved — a test asserts d(a,b) ≠ d(b,a) for a directed fixture, so that a future "fix" symmetrizing the metric fails loudly. Zero reads of any identifier outside facts.exchanges |
| Reconstruction criteria | partial, with the loss characterised. Direction survives; individual edge weights do not survive path composition. Sufficient reconstruction structure: the exchange list. Metric + exchange list → facts, exactly. Metric alone → facts, not recoverable |
| Validation strategy | mutation: symmetrize the metric; the asymmetry test must fail and no other test may fail (precision). Second mutation: substitute a hand-tuned constant for a fact-derived weight; a provenance test asserting the metric module reads no literal numeric outside its declared band must fail |
P3 — Layout as the solution to a metric, with residual
Positions computed by minimizing disagreement between planar distance and the P2 quasi-metric. No designer input, no hand-placed anchor.
| Constitutional dependency | Article III (III.4 stability is the hard constraint on any iterative layout) |
| Implementation dependency | P1 (seniority anchors the solution), P2 (the metric being solved) |
| Measurable success criteria | position is a deterministic function of facts — same facts, same coordinates, across processes. Stability under growth is asserted, not hoped: adding a subject perturbs incumbent coordinates by zero, or by a bounded amount that is itself declared. An unconstrained force layout will fail this, and that failure is the point of the criterion |
| Reconstruction criteria | impossible by §0.3, proved by dimension count. The renderer must therefore emit a residual: for each rendered position, the metric value it solved and the edge set that determined it. Success is that positions + residual → metric → facts closes, and that the residual is emitted by the renderer rather than recomputed by the verifier |
| Validation strategy | the reverse chain is executed as a test: parse rendered coordinates via P0, read the emitted residual, reconstruct the exchange facts, assert equality with the input facts. This test is the roadmap's terminal acceptance criterion — it is the invariant, executed |
MEASURED: III.4 and metric-faithful layout are incompatible. Adding one subject to a four-subject fixture moved 4 of 4 incumbents, by up to 6.57 units. This was recorded as the way P3 fails, and it is how P3 failed.
The result is not a defect in the layout. It follows from what MDS solves: every
coordinate is a function of every distance, so any new edge perturbs the whole
configuration. No stability-preserving metric-faithful layout exists, for the
same reason plots.ts could not be derived — the allocation event is
information that the present metric does not contain.
That closes the loop with P1. Position stays historical in the Justification
Ledger, and the metric's proper role is to inform new allocations, not to
replace the register. Derived geometry is a solver for where a newcomer should
go; it is not the authority for where incumbents already are.
Pre-registered prediction for P4
Recorded before implementation, so it can fail. Evidence: P0a, P2 and P3 ran end to end with zero new foundational concepts.
- The existing justification categories will remain sufficient.
- The existing projection vocabulary will remain sufficient.
- The existing residual model will remain sufficient.
- Remaining work will primarily extend observable objects and rendering instrumentation.
Falsification: if P4 requires a new foundational concept, the prediction has failed and the reason must come from measurement, not intuition. If it requires only carrying the existing residual through to rendered output, the architecture has survived its first complete implementation cycle.
The specific pressure point to watch: the residual is currently emitted by
layoutFrom, at the fact-set object. Carrying it to rendered-dom means a
rendered property must be traceable back through a residual that the renderer
did not compute. Nothing in the vocabulary forbids that — but nothing has
demonstrated it either.
P4 — Legend binding (requires its own amendment)
| Constitutional dependency | Article X — requires proposing an amendment to the Legend. AMD-0003 vetoed 2026-08-03; the block is no longer a pending decision but an unproposed one. Article VI (declared bands), Article I.3 |
| Implementation dependency | P0, P2, P3 |
| Measurable success criteria | every visible property has a Legend row naming its metric, its transform and its unit. The three undeclared Article VI bands (WorldScene:174, :239, :282) and the five Article I.3 renderer classifications (CityMap:436, :704; WorldScene:280, :389, :390) are closed. Enumerated and asserted via P0, over rendered output |
| Reconstruction criteria | Legend row → metric → facts, for every visible property, with no property lacking a row |
| Validation strategy | a test enumerating rendered attributes (P0) and cross-referencing the Legend, failing on any attribute with no row. This is the total-and-functional classification requirement, executed against the rendered surface rather than the source text |
P5 — Quantisation (blocked: floor/tier units)
| Constitutional dependency | Article II.2, II.3; Article III.6 |
| Implementation dependency | P4 |
| Measurable success criteria | tripwire W5 closes — 2001 distinct inputs produce a bounded, declared number of distinct heights |
| Reconstruction criteria | deliberately lossy, and the loss is the feature. Height → band, not height → value. The band is recoverable; the value is not. This must be stated in the Legend rather than discovered by a reader |
| Validation strategy | the existing W5 measurement, observed failing now and passing after |
3. Seven-question validation — the coupling quasi-metric (P2)
| # | Question | Answer |
|---|---|---|
| 1 | Why does this metric exist? | Subjects that exchange must render as near. Without it, proximity is chosen by a designer, which the brief forbids |
| 2 | Which constitutional facts define it? | ExchangeFact{fromId, toId, kind, weight}. No other input |
| 3 | Which mathematical properties? | Non-negative; d(x,x)=0; triangle inequality under path composition; asymmetric. A quasi-metric, not a metric |
| 4 | Which geometric property? | Planar separation |
| 5 | Which rendered property? | Building x/y |
| 6 | Traceable back to facts? | Yes, once P0 exists. Not yet — no test observes rendered output, so this cannot currently be answered at all |
| 7 | Reconstructable from the rendered property plus sufficient structure? | No, from the rendered property alone — proved impossible in §0.3 by dimension counting. Yes, with the exchange list as the sufficient reconstruction structure |
By the brief's own rule — "if any answer is no, the metric is incomplete" — this metric is incomplete, and provably cannot be completed. Question 7 has no positive answer for any layout metric whatsoever, at n ≥ 4.
That is not a reason to abandon the metric. It is a reason to fix the architecture: geometry must emit its residual. The rule as stated admits no layout at all; the rule as repaired admits exactly the layouts that record what they discarded. P3's reconstruction criterion is written to that repair, and P3's terminal test is what makes it true rather than asserted.
4. Ordering, and what would falsify the roadmap
P0 → P1 → P2 → P3 are unblocked and strictly ordered by dependency. P4 → P5 are blocked on decisions that are the ratifying authority's, not mine.
Three ways this roadmap fails, each detectable by a task it already contains:
- P0 cannot render client components under
react-server. Then the observation surface requires a second test condition. Detected by running it. - P3 cannot satisfy III.4. Metric-faithful layout and never-move may be incompatible. Detected by P3's stability criterion, which is written to fail in that case rather than to accommodate it.
- The residual is larger than the facts. If emitting sufficient reconstruction structure means shipping the fact set, geometry adds no compression and the reverse chain is trivially satisfied. Detected by measuring residual size against fact size in P3.
The third is the one I would bet on. It is not yet measured, and it is stated here as a hypothesis, not a finding.