docs(meta): D-255 — the ladder floor is one subtile per pixel (T-1213)

Measured during T-1213, through the production canvas builder on Ferrath: at
Quarter and below, morphology collapses to ONE zone and vegetation to ONE
class. The uniform frames in the 2026-08-06 descent ladder were those rungs
drawing exactly what they contain.

The cause is arithmetic, not a missing feature. At the uniform 2x2 px display
ratio a 3440x1440 window gives 540 gridunits on the short axis, so:

  Quarter  512 m  ->  0.948 m/gridunit  ->  0.474 m/px   ~1 subtile per pixel
  Block    128 m  ->  0.237 m/gridunit                    4 gridunits per voxel
  Chunk     64 m  ->  0.119 m/gridunit                    8 gridunits per voxel

Block and Chunk magnify beneath the finest datum that can exist, so they can
only ever draw one voxel larger. Quarter lands within 5% of one subtile per
pixel and becomes the floor.

Stated as a rule so it survives the constants moving: the deepest Atlas rung
is the one at which a screen pixel shows one subtile. It is derived from the
data model rather than chosen, and it moves automatically if the subtile does.

WHAT THIS IS NOT. Chunk remains the 64 m stream/derive unit of D-243 and stays
vital — it is what Phase 5 derives first-person walkable content on, and
D-012's load-around-the-player is expressed in chunks. Block remains the 128 m
generator planning unit. Only Atlas VIEWABILITY is retired; the containment
ladder is untouched. This record governs what the map draws, not what the
generator builds.

The justification is the Atlas's purpose (Jeroen): it exists to give the player
information, and a rung earns its place by answering a question the rung above
cannot. Once a pixel is a subtile there is no finer datum to answer with.

The resulting Global -> Region -> District -> Quarter steps at ~93x -> 100x ->
4x. That unevenness is NOT from this change — the rungs removed were 4x and 2x
steps carrying no information — it is D-243's one non-power-of-2 rung, and
T-1218 already exists to re-balance it. A compensating rung above Region was
considered and declined here; it belongs with that ticket.

CLAUDE.md's cascade line updated in the same commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-07 14:05:41 +02:00
co-authored by Claude Opus 5
parent 6beb4bbea1
commit b429f633e6
4 changed files with 95 additions and 1 deletions
@@ -98,3 +98,5 @@ Note the ladder currently also reports courses=0 at every rung below Global —
rivers vanish on descent. That is tracked separately as T-1239 and is NOT this rivers vanish on descent. That is tracked separately as T-1239 and is NOT this
ticket''s scope, but it will be visible in the same captures, so do not mistake it ticket''s scope, but it will be visible in the same captures, so do not mistake it
for a failure of the un-summarisation work.', NULL, '2026-08-06 15:59:39', '2026-08-06 15:59:39.623', '2026-08-06 15:59:39.623', NULL, 'fff0549b0da56272e5c13e9de4374f76', 2) ON CONFLICT(hash) DO NOTHING; for a failure of the un-summarisation work.', NULL, '2026-08-06 15:59:39', '2026-08-06 15:59:39.623', '2026-08-06 15:59:39.623', NULL, 'fff0549b0da56272e5c13e9de4374f76', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FT0TZC9MJV6KZTSRVRYQ327M', 'status', 'backlog', 'in_progress', NULL, '2026-08-07 11:36:05', '2026-08-07 11:36:05.551', '2026-08-07 11:36:05.551', NULL, '56946f83904827105a9ae52d64a91a1d', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FT0TZC9MJV6KZTSRVRYQ327M', 'status', 'in_progress', 'in_progress', NULL, '2026-08-07 11:36:20', '2026-08-07 11:36:20.465', '2026-08-07 11:36:20.465', NULL, 'd57ff6176db9e02ac1e97fb8cb8e609b', 2) ON CONFLICT(hash) DO NOTHING;
+70
View File
@@ -95,3 +95,73 @@ Note the ladder currently also reports courses=0 at every rung below Global —
rivers vanish on descent. That is tracked separately as T-1239 and is NOT this rivers vanish on descent. That is tracked separately as T-1239 and is NOT this
ticket''s scope, but it will be visible in the same captures, so do not mistake it ticket''s scope, but it will be visible in the same captures, so do not mistake it
for a failure of the un-summarisation work.', 'backlog', 'high', NULL, NULL, 'D-258', '2026-07-26 21:54:15.245', '2026-08-06 15:59:39.623', NULL, 'd9bfabaf6b4f1751a9261995f84c0b7b', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); for a failure of the un-summarisation work.', 'backlog', 'high', NULL, NULL, 'D-258', '2026-07-26 21:54:15.245', '2026-08-06 15:59:39.623', NULL, 'd9bfabaf6b4f1751a9261995f84c0b7b', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FT0TZC9MJV6KZTSRVRYQ327M', 'story', '06FT0TX2W0BA10PRR7NMJ2362M', 'Rung-0.5 expanded-layer generator (deterministic un-summarisation of rung 0)', 'Build the deterministic expansion from rung 0 (heightmap.png 1024x512 16-bit elevation + reliefmap.png 1024x512 colour biome) to rung 0.5, sized per D-258''s 2-px-per-gridunit-at-large-display rule. Same body + same seed must produce the same layer every time (byte-identical, per D-227''s determinism discipline extended by this carve-out). The reliefmap is a PLURALITY, not ground truth: each reliefmap cell already voted-and-discarded the dominant biome across ~38 km of ground, so this generator un-summarises it -- it does not upscale/interpolate it. Three binding invariants from D-258: (1) biome edges are gradients, never lines -- transitions blend so no boundary falls on a rung-0 cell edge (the D-243 climate edge-fuzz rule applied to biome); (2) descending the ladder reveals COMPOSITION not sharpness -- a cell reading ''forest'' globally must be able to contain clearings/marsh/rock/scrub the vote suppressed, emerging deterministically as the ladder descends; (3) CONSERVATIVE invention is the binding acceptance gate -- downsampling rung 0.5 must reproduce the rung-0 summary it came from (a forest cell may gain marsh pockets but must still read as forest from orbit). Blocked on T-1212 (cost/size measurement) landing first. Depends on: nothing else in this epic to start scaffolding, but hydrology (sibling ticket) and this generator are tightly coupled -- coordinate sequencing with whoever picks up hydrology. See governance/decisions/architecture.md#d-258.
---
UNBLOCKED 2026-08-06 (T-1211 re-scope, Jeroen''s call). The T-1212 blocker edge is
removed: that measurement priced a hydrology move that is not happening, and the
descent ladder showed there is no expansion artefact to measure yet anyway.
BUILD IT AS A PURE FUNCTION FIRST, not as a stored layer. The stored-layer half of
D-258 was materially weakened by its own 2026-07-27 amendment (the "not locally
computable" argument for the D-227 carve-out does not hold, because the whole-body
solve it cited already runs once per body in layer1.rs and is sampled at every
rung). So follow the mechanism that exists — D-255(f) mechanism B,
compute-once-sample-everywhere — measure it, and only argue for storage on those
numbers. Do NOT open with a cache.
WHAT "FLAT" MEANS CONCRETELY, so the fix has a target. Ferrath''s heightmap is
1024x512 over a 38,089 km circumference: 37.2 km per source pixel. Global draws at
35.267 km/gridunit, roughly 1:1 with the source, and reads as a real map. Region
draws at 0.379 km/gridunit — 98x finer than any stored datum — and is a single
uniform colour with dither. District is 0.0038 km/gridunit, ~9,800x finer, also
uniform. So the acceptance bar is not subtle: at Region, ~98 gridunits across a
single source pixel must carry visible, deterministic, non-repeating composition
that still downsamples back to that pixel''s summary (D-258''s conservation
invariant, the binding gate).
VERIFY BY CAPTURE, NOT BY REASONING. The scenarios exist: atlas_GJ820Bc_land_*
(Region/District/Quarter/Block/Chunk, one land-anchored world point, no overlays)
in tests/visual.json. Captures run offscreen under gamescope at native 3440x1440
via tests/run-visual --screenshot <name> — they do not steal the desktop. Re-shoot
the ladder and look at it; a green unit test proves nothing here.
Note the ladder currently also reports courses=0 at every rung below Global —
rivers vanish on descent. That is tracked separately as T-1239 and is NOT this
ticket''s scope, but it will be visible in the same captures, so do not mistake it
for a failure of the un-summarisation work.', 'in_progress', 'high', NULL, NULL, 'D-258', '2026-07-26 21:54:15.245', '2026-08-07 11:36:05.551', NULL, 'a3edd5306633b6247c1cd67bf700db69', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FT0TZC9MJV6KZTSRVRYQ327M', 'story', '06FT0TX2W0BA10PRR7NMJ2362M', 'Rung-0.5 expanded-layer generator (deterministic un-summarisation of rung 0)', 'Build the deterministic expansion from rung 0 (heightmap.png 1024x512 16-bit elevation + reliefmap.png 1024x512 colour biome) to rung 0.5, sized per D-258''s 2-px-per-gridunit-at-large-display rule. Same body + same seed must produce the same layer every time (byte-identical, per D-227''s determinism discipline extended by this carve-out). The reliefmap is a PLURALITY, not ground truth: each reliefmap cell already voted-and-discarded the dominant biome across ~38 km of ground, so this generator un-summarises it -- it does not upscale/interpolate it. Three binding invariants from D-258: (1) biome edges are gradients, never lines -- transitions blend so no boundary falls on a rung-0 cell edge (the D-243 climate edge-fuzz rule applied to biome); (2) descending the ladder reveals COMPOSITION not sharpness -- a cell reading ''forest'' globally must be able to contain clearings/marsh/rock/scrub the vote suppressed, emerging deterministically as the ladder descends; (3) CONSERVATIVE invention is the binding acceptance gate -- downsampling rung 0.5 must reproduce the rung-0 summary it came from (a forest cell may gain marsh pockets but must still read as forest from orbit). Blocked on T-1212 (cost/size measurement) landing first. Depends on: nothing else in this epic to start scaffolding, but hydrology (sibling ticket) and this generator are tightly coupled -- coordinate sequencing with whoever picks up hydrology. See governance/decisions/architecture.md#d-258.
---
UNBLOCKED 2026-08-06 (T-1211 re-scope, Jeroen''s call). The T-1212 blocker edge is
removed: that measurement priced a hydrology move that is not happening, and the
descent ladder showed there is no expansion artefact to measure yet anyway.
BUILD IT AS A PURE FUNCTION FIRST, not as a stored layer. The stored-layer half of
D-258 was materially weakened by its own 2026-07-27 amendment (the "not locally
computable" argument for the D-227 carve-out does not hold, because the whole-body
solve it cited already runs once per body in layer1.rs and is sampled at every
rung). So follow the mechanism that exists — D-255(f) mechanism B,
compute-once-sample-everywhere — measure it, and only argue for storage on those
numbers. Do NOT open with a cache.
WHAT "FLAT" MEANS CONCRETELY, so the fix has a target. Ferrath''s heightmap is
1024x512 over a 38,089 km circumference: 37.2 km per source pixel. Global draws at
35.267 km/gridunit, roughly 1:1 with the source, and reads as a real map. Region
draws at 0.379 km/gridunit — 98x finer than any stored datum — and is a single
uniform colour with dither. District is 0.0038 km/gridunit, ~9,800x finer, also
uniform. So the acceptance bar is not subtle: at Region, ~98 gridunits across a
single source pixel must carry visible, deterministic, non-repeating composition
that still downsamples back to that pixel''s summary (D-258''s conservation
invariant, the binding gate).
VERIFY BY CAPTURE, NOT BY REASONING. The scenarios exist: atlas_GJ820Bc_land_*
(Region/District/Quarter/Block/Chunk, one land-anchored world point, no overlays)
in tests/visual.json. Captures run offscreen under gamescope at native 3440x1440
via tests/run-visual --screenshot <name> — they do not steal the desktop. Re-shoot
the ladder and look at it; a green unit test proves nothing here.
Note the ladder currently also reports courses=0 at every rung below Global —
rivers vanish on descent. That is tracked separately as T-1239 and is NOT this
ticket''s scope, but it will be visible in the same captures, so do not mistake it
for a failure of the un-summarisation work.', 'in_progress', 'high', NULL, NULL, 'D-258', '2026-07-26 21:54:15.245', '2026-08-07 11:36:20.464', NULL, '94ccf78431914ea836ba5d59170a3395', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
+1 -1
View File
@@ -41,7 +41,7 @@ Development follows a strict cascade. Each phase has a concrete deliverable. **D
| 1 | Wiki content complete — all planets, moons, stations, heightmaps, artwork | Implant-ready Godot map of the Reach with click-throughs + wiki/GTTR popups | | 1 | Wiki content complete — all planets, moons, stations, heightmaps, artwork | Implant-ready Godot map of the Reach with click-throughs + wiki/GTTR popups |
| 2 | Economics layer — supply/demand, transport, political/social pressure, corporations, supply chains | Economics spreadsheets/graphs with runtime-tweakable simulation | | 2 | Economics layer — supply/demand, transport, political/social pressure, corporations, supply chains | Economics spreadsheets/graphs with runtime-tweakable simulation |
| 3 | Planetary/moon maps & station layouts — cities, rivers, mountains, roads, biomes, rail | Atlas of the Reach (implant app) | | 3 | Planetary/moon maps & station layouts — cities, rivers, mountains, roads, biomes, rail | Atlas of the Reach (implant app) |
| 4 | World generation (tile/chunk/block) — deterministic multilayer seed→tile cascade; each layer above the tile fill viewed as a **map in the implant Atlas** (no in-world rendering; tile/voxel output is harness-verified, never Atlas-mapped; **chunk (64 m) is the deepest Atlas rung** — D-255, narrowing the D-226 amendment 2026-07-13) | Deterministic walkable-world data + per-layer Atlas maps + asset catalog + the **stepped Atlas ladder** (D-255, amended 2026-07-26 — the extent inversion: six levels — the Global body-surface opener (rung 0, viewport-sized, always kept) + five fixed rungs Region→District→Quarter→Block→Chunk; **a rung fixes the canvas EXTENT and spacing falls out of it** — the shorter viewport axis spans exactly one cell of the rung's level, so canvas cost is constant at every rung — drawn texel-exact by the client map-art function at a uniform 2×2 display ratio; heightmap PNGs remain invisible derivation input, never displayed. Rung 0.5, an expanded whole-body layer where hydrology resolves once and every rung below sources from it, is RULED (D-258) but not yet implemented — see D-258) | | 4 | World generation (tile/chunk/block) — deterministic multilayer seed→tile cascade; each layer above the tile fill viewed as a **map in the implant Atlas** (no in-world rendering; tile/voxel output is harness-verified, never Atlas-mapped; **quarter (512 m) is the deepest Atlas rung** — D-255 amended 2026-08-07, superseding the chunk floor: the deepest rung is the one where a screen **pixel shows one subtile**, and below that a rung magnifies rather than informs. **Chunk stays the 64 m stream/derive unit and is vital for Phase-5 first-person content — only its Atlas *viewability* was retired**) | Deterministic walkable-world data + per-layer Atlas maps + asset catalog + the **stepped Atlas ladder** (D-255, amended 2026-07-26 and 2026-08-07 — the extent inversion: four levels — the Global body-surface opener (rung 0, viewport-sized, always kept) + three fixed rungs Region→District→Quarter; **a rung fixes the canvas EXTENT and spacing falls out of it** — the shorter viewport axis spans exactly one cell of the rung's level, so canvas cost is constant at every rung — drawn texel-exact by the client map-art function at a uniform 2×2 display ratio; heightmap PNGs remain invisible derivation input, never displayed. Rung 0.5, an expanded whole-body layer where hydrology resolves once and every rung below sources from it, is RULED (D-258) but not yet implemented — see D-258) |
| 5 | Player control & in-world rendering — character, walls/stairs/doors, lighting, drawn on **generated** tiles (no test map) | Player viewport with final-version assets on the generated world | | 5 | Player control & in-world rendering — character, walls/stairs/doors, lighting, drawn on **generated** tiles (no test map) | Player viewport with final-version assets on the generated world |
| 6 | Detail coloring — room-level NPC population, cultural room grammar | Only when the world is walkable | | 6 | Detail coloring — room-level NPC population, cultural room grammar | Only when the world is walkable |
+22
View File
@@ -2298,6 +2298,28 @@ Technical foundation decisions that constrain implementation: engine, client-ser
**Status, honestly:** Region is confirmed working. **Global still reads wrong and this amendment does not fix it** — it is correctly *sized* now but still rides the orbital derive, so it carries no hydrology. Its repair is [D-258](#d-258)'s rung 0.5, not further work on this record. **Status, honestly:** Region is confirmed working. **Global still reads wrong and this amendment does not fix it** — it is correctly *sized* now but still rides the orbital derive, so it carries no hydrology. Its repair is [D-258](#d-258)'s rung 0.5, not further work on this record.
- **Amendment (2026-08-07, Jeroen's ruling — THE LADDER FLOOR: the deepest rung is one subtile per pixel; Block and Chunk stop being viewable rungs):** The rung set narrows from five fixed rungs to **three** — Region → District → **Quarter** — beneath the Global opener. Ruled on measurement, during T-1213.
**The rule, stated once:** *the Atlas's deepest rung is the one at which a screen pixel shows one subtile.* Below that a rung is not showing more, only bigger. This replaces "chunk (64 m) is the deepest Atlas rung" from the 2026-07-13 D-226 narrowing.
**The arithmetic.** The uniform display ratio is 2×2 px per gridunit (item 4 above), and a 3440×1440 window yields 540 gridunits on the short axis. With `VOXEL_M = 1` and the subtile at 2⁻¹ = 0.5 m:
| Rung | Extent | m/gridunit | m/pixel | Against the finest datum |
|------|--------|-----------|---------|--------------------------|
| **Quarter** | 512 m | **0.948** | **0.474** | ≈1 voxel per gridunit, **≈1 subtile per pixel** |
| Block | 128 m | 0.237 | 0.119 | 4 gridunits per voxel |
| Chunk | 64 m | 0.119 | 0.059 | 8 gridunits per voxel |
Quarter lands within 5% of the rule. Block and Chunk magnify *beneath the finest thing that can exist*, so they can only ever draw one voxel larger. Measured on Ferrath through the production canvas builder (`t1213_ladder_field_variance`): at Quarter and below, morphology collapses to **1 zone** and vegetation to **1 class** — the uniform frames in the 2026-08-06 descent ladder were those two rungs rendering exactly what they contain, which is nothing new.
**What this is NOT.** **Chunk remains the 64 m stream/derive unit of [D-243](#d-243), untouched, and stays vital** — it is the unit Phase 5 derives first-person walkable content on, and [D-012](#d-012)'s load/unload-around-the-player is expressed in chunks. Only its *viewability as an Atlas map rung* is retired. Block likewise remains the generator's 128 m planning unit. Nothing in the containment ladder changes; this record governs what the **map** draws, not what the **generator** builds.
**Why the floor is principled rather than a tuning choice.** The Atlas exists to give the player **information** about a body (Jeroen: *"the goal here is to provide the user information, while implementing the cascaded generators to make that possible in the first place"*). A rung earns its place by answering a question the rung above cannot — continents, provinces, a district's terrain, a quarter's ground. Once a pixel is a subtile, every further step answers nothing new, because no finer datum exists to answer with. The floor is therefore derived from the data model, not from taste, and it moves automatically if the subtile ever does.
**On the resulting ladder shape.** Global → Region → District → Quarter steps at roughly 93× → 100× → 4×. The unevenness is **not** caused by this amendment (the rungs removed were 4× and 2× steps carrying no information); it is [D-243](#d-243)'s single non-power-of-2 rung, and [T-1218](../../.pql) already exists to re-balance it (region → 262,144, district → 4,096, making that step 64×). A compensating rung above Region was considered and **declined here** — it belongs with that ticket's re-balancing, not as an ad-hoc addition.
**Consequential edits:** CLAUDE.md's Phase-4 cascade line (which named chunk as the deepest Atlas rung) is updated with this record. [D-226](#d-226)(d)'s prohibition is unaffected and now has margin — it caps Atlas granularity at settlement/quarter, and Quarter is exactly that cap.
--- ---
### D-256: Canonical sampling convention — one absolute-metre derive core; the batch layer is a survey raster ### D-256: Canonical sampling convention — one absolute-metre derive core; the batch layer is a survey raster