docs(meta): D-227 T-1125 invention-character amendment + D-239 T-1126 Marine amendment

D-227: records the two-tier driver model (body envelope from authored
params only, D-240 tilt exclusion upheld; position tier with fjord/
latitude/wetness/heterogeneity), the shared invent_primitives path,
the scatter floor-vs-ceiling reading, shoreline carving, and the
one-step-stale circularity ruling. D-239: Marine appended at
discriminant 6, morphology-derived verdict, airless precedence,
non-semantic Ord position.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-17 08:22:20 +02:00
co-authored by Claude Fable 5
parent aa1471069b
commit a86dab3756
+2
View File
@@ -1618,6 +1618,7 @@ Technical foundation decisions that constrain implementation: engine, client-ser
- **Rationale:** A world that stores its tiles cannot scale to body-sized 3-D volumes and bloats saves; a pure-function world with a transient cache + a sparse mutator log scales to any size, makes saves trivially small, and is the only model under which "dig anywhere, to any depth" is free (the subsurface was always computable — digging just reveals it). It also forces the determinism discipline the whole cascade needs anyway. The downward floor cap fell because it was solving a problem — per-layer storage cost — that derive-don't-store eliminates.
- **Open sub-questions:** the geology-model fidelity (simple depth-horizon stack vs tectonic-grade folding/faults) and how far `FloorMaterial` is derived now vs deferred to the city layers (both tracked in D-228 / Q-101); the mutator op schema (Q-103).
- **Implementation:** Phase 4+ (epic T-750). The caching substrate exists at the atlas level (`BodyWorldStateCache`, D-203/D-225); the tile/voxel cache, mutator overlay, and geology derivation land as the cascade reaches the tile layers. No migration needed pre-save (D-202 `schema_version` lineage covers future drift once saves exist).
- **Amended 2026-07-17 (T-1125 — the invention carries geographic content into district classification; two-tier driver model):** the "invented deterministically (interpolation + domain warp + detail-scatter)" clause is now implemented *with character* at the district tier, closing the T-1123 finding that classification consumed only the raw bilinear envelope (pixel-smooth coasts; scatter amplitude slaved to coarse heightmap slope ≈ 0 exactly on low-relief coasts). Mechanism (`atlas/coast_invention.rs` + `district_profile::invent_primitives`, shared by the on-demand `derive_district` AND batch `derive_district_profile` paths so they can never silently diverge): **(a) coastline domain-warp** — every envelope field (elevation, slope, ocean mask) is bilinearly sampled at the same warp-displaced position (C¹ multi-octave value noise, ≈16262 km band, sub-pixel amplitude cap 0.75 px, distinct salted hash stream — never correlated with the terrain scatter or climate edge-fuzz), inventing bays/capes/fjord inlets while the heightmap stays the truth at its own scale; **(b) slope-independent scatter floor** — the detail-scatter envelope gains a character-driven floor (invention no longer collapses on flat coasts; the old "flat envelope → zero invention" reading is superseded — the envelope rule survives as a *ceiling*: gentle bounded relief, never mountains on an authored plain); **(c) shoreline carving** — ridged character contributes real slope in shoreline patches so the steep coastal families (Fjord/CliffCoast) can fire where glacially/tectonically justified. **Crinkle varies (Jeroen's ruling): two driver tiers, zero new authored data.** Tier 1 (body personality envelope): `planet_class` (via `TectonicClass`) + `hydrosphere` + `atmosphere` + `body_radius_km` (via the pixel⇄metre seam) only — **D-240 stands: no orbital/tilt inputs**; erosion-proneness is *derived* (more ocean → wetter/rainier → higher erosion → smoother mature coasts; dry/thin-atmosphere → sharp young coasts). Tier 2 (position): latitude, driver-tier `GlaciationGrade` (fjordy high-latitude glaciated coasts), local wetness, and a seeded ~100400 km heterogeneity field so stretches of the same coast differ; longitude participates via absolute world-metre noise keying. **Circularity ruling:** the driver-tier climate (glaciation/moisture) reads the *unwarped* raw-bilinear primitives — one-step-stale by design, documented at the call site. All pure `(seed, body, position)` (D-010); character never steps on a district/region line (D-243 edge-fuzz discipline).
- **Raised by:** Jeroen (derive-don't-store, volumetric, drop-the-floor-cap directives) + Claude, atlas-derivation workshop, 2026-05-25.
- **Cross-reference:** [D-010](#d-010) (determinism — now save-critical), [D-222](#d-222) (subtile/tile/chunk hierarchy), [D-110](#d-110) (signed z-levels), [D-225](#d-225) (layer-stream proxy + cache pattern), [D-203](#d-203) (LRU cache tier), [D-224](#d-224) (SeedChain — feeds `derive`), [D-228](#d-228) (composite tile schema — the derived value type), [Q-101](../questions/architecture.md#q-101) (refinement contract), [Q-103](../questions/architecture.md#q-103) (mutator op schema), [Q-104](../questions/architecture.md#q-104) (floor↔voxel-z mapping)
- **Dissent:** None
@@ -1830,6 +1831,7 @@ Technical foundation decisions that constrain implementation: engine, client-ser
- **Implementation note (T-1025/T-1027, 2026-06-08):** §6's frozen 17-zone `MorphologyZone` enum is realised in `server/src/simulation/generator.rs` (`repr(u8)`, discriminant-pinned). The §5 8-family gated classifier + §7 compatibility-matrix invariants live in `derive_morphology_zone` (`region_profile.rs`). **16 of the 17 zones are reachable at RegionProfile scale; `BraidedPlain` is the exception** — distinguishing it from `Delta` needs a lithology signal (§8 Gravel→braided) that `RegionProfile` does not carry, so `BraidedPlain` is **deferred to ChunkContext** sub-classification. The §7 compatibility invariant is enforced as a **classifier-gate-ordering** property (a build-time test that a single region cannot yield a forbidden pair), per §7's "build-time test" language; genuine cross-region sharp seams (cliff↔fjord, lithology faults) remain permitted. §2 climate-derived fields (`precipitation_class`, `glaciation_grade`, `vegetation_class`) all derive from the temperature(+moisture) primitive (T-1025).
- **Amendment (T-1082, 2026-06-28):** §5's family set grows from **8 to 9** — a `WaterBody` generator family is added for the water zones **OpenOcean / Lake / TidalFlat**, which previously fell through to the dry-land `AlluvialPlain` fallback (the D-245 believability bug: oceans rendered as dry forested land — `water=Dry` + `Forest` on the sea). `WaterBody` lays `Water::Deep`/`Shallow` (a Shallow shoal band on the district-anchored coast line `coast_anchor_m`, Deep beyond; TidalFlat is all-Shallow), a seabed `TerrainMaterial` (`Rock` on steep districts / `Sand` on gentle / `Wetland` for tidal mud), `Vegetation::Barren`, the water surface at `elevation_m = 0` (the §8 mouths-at-sea-level convention), and seasonal `Ice` via `derive_cover` (frozen seas). This **refines §6**: open ocean / lake / tidal flat are still derived zone *labels*, but their *generator* is now `WaterBody`, not `AlluvialPlain` — so §6's "tidal flat … not [a] distinct generator famil[y]" is superseded for the dispatch of those three zones. `Wetland` stays a land zone on `AlluvialPlain` (a marsh — saturated ground, not open water). Lives in `server/src/atlas/voxel.rs` (`MorphologyFamily::WaterBody` + `generate_water_body`, dispatched by `zone_to_family`); verified by the T-1083 believability harness (water-renders-wet flips PASS for Arbour + Edict). The §5 8-family decision-tree classifier (`derive_morphology_zone`) is unchanged — this is a voxel-tier *generator* family, selected by zone, not a new RegionProfile classifier branch.
- **Amendment (T-1080, 2026-06-28):** §2's **moisture** primitive is now a **body ceiling × per-district spatial gradient**, not a single body constant. The hydrosphere+atmosphere value (`derive_moisture_q`) is the *wettest* a district on the body can be; per-district **latitude** (equator wet → pole dry), **elevation** (orographic / rain-shadow), and **continentality** (`100 ocean_fraction_q`, coast wet → interior dry) subtract from it. Integer (D-010); coefficients in `ClimateConstants` / `climate_constants.toml` `[moisture_gradient]` (provisional, Q-123 calibrates). This mirrors D-240's latitude-graded *temperature* model and fixes the T-1080 believability bug (`moisture_q = 80` for all 2 048 districts → uniform vegetation/terrain — "nothing to fuzz"). It **propagates**: `precipitation_class`, `vegetation_class`, and the `morphology_zone` Wetland gate all read `moisture_q`, so those diversify for free. Lives in `district_profile.rs::derive_moisture_q`; verified by the T-1083 believability harness (moisture-gradient flips PASS, `distinct` 1 → ~49 on Arbour). The body-scale ceiling keeps each world's character; the gradient varies it within.
- **Amendment (T-1126, 2026-07-17):** §8's climate→vegetation law predates a water class — `derive_vegetation` was ocean-blind, so district-resolution maps painted Forest across open ocean (T-1123 finding; the voxel tier masked it in-world via the T-1082 `WaterBody` generator, but the district carrier itself disagreed with its own morphology). `VegetationClass` gains **`Marine`, appended at discriminant 6** (after `RiparianThicket = 5`; the load-bearing discriminant-pin test is extended). The verdict is **morphology-derived**: `build_district_profile` derives `morphology_zone` first and passes `open_water = (OpenOcean | Lake)` into the vegetation call — vegetation and morphology can never disagree by construction, and **no fourth ocean threshold exists**. Precedence: airless (`temperature_c == None`) still wins — an airless body has no climate/vegetation branch at all (§2), so its seas read `Absent`, not `Marine`. The `Ord` position of `Marine` is **non-semantic**: the §8 Forest→Scrub→Barren density-ladder reading does not extend to it (discriminants are append-only serialisation order). `near_perennial_water` (the riparian river-proximity signal) is unrelated and unchanged.
- **Amendment (T-1081, 2026-06-28):** the voxel tier now carries **mid-scale relief** (D-243 §2's invented terrain). Before, the family generators set `elevation_m` from `elev_q` at a compressed scale plus only ±4 m per-voxel micro-scatter — the walkable surface read flat (the D-245 "03 m, no hills to navigate by" bug). A `voxel_relief` pass (`detail_scatter.rs`, the `terrain_detail` fBm at a **0.131 km sub-district octave band** — all finer than the 2 km district, so it never competes with `elev_q`'s district-scale role — rather than the district 440 km band; body-global `SeedDomain::VoxelRelief` seed, position-keyed; the `f64` perturbation truncated to integer metres before assignment — D-010) is added post-dispatch in `derive_voxel_column`. Two load-bearing choices: **(a) the relief envelope is `slope_q·3 + elev_q`, not slope alone** — the coarse heightmap (~4078 km/px) yields `slope_q ≈ 0` even on high ground (observed max 13 on Arbour), so gating on slope would invent nothing; folding elevation in makes high terrain read rugged and coastal flats stay gentle. **(b) Only the flat families** (AlluvialPlain / LavaField / BraidedDelta / DuneStrand / MeanderReach) take it — CliffCoast / FjordWall / IncisedGorge already generate strong internal relief and a position-varying field would warp those features (e.g. drown a gorge's wall-to-floor drop); WaterBody stays at sea level. The relief **span** (`VOXEL_RELIEF_SPAN_M = 100`) and the believability voxel-relief threshold (≥ 8 m) are provisional (Q-123 calibrates, like the moisture coefficients). The span is held modest deliberately: relief sits on the compressed `elev_q/N` base (max ~50 m) and `elevation_m` clamps at 0 (sea level), so an oversized span clamps away on low ground (drowning the relief, biasing it positive) — a bigger span belongs with the deferred absolute-elevation model. Verified by the T-1083 harness — a new `voxel_relief` contrast metric (mean within-district elevation range across a district-spanning transect, since a single 64 m sample chunk is narrower than the relief band) flips PASS (≈22 m on Arbour + Edict). **Deferred:** the *absolute* elevation span is still the compressed `elev_q/N` base — a per-body hypsometric relief model (so a body's true max relief sets the ceiling AND gives the relief headroom to grow without clamping) is a later refinement; the mid-scale relief gives navigable hills now without it.
- **Cross-reference:** [D-227](#d-227) (derive-don't-store voxel model), [D-228](#d-228) (composite tile axes / cohesion / seasonal state), [D-210](#d-210) (temperature proxy — formalised), [D-203](#d-203) (BodyWorldState cache), [D-206](#d-206) (background analysis pass), [D-208](#d-208) (drainage / D8), [D-010](#d-010) (determinism), [D-234](#d-234) (street/footprint geometry — consumes morphology), [D-142](content.md#d-142) (zone types), [D-217](#d-217) (tile condition), [Q-102](../questions/architecture.md#q-102) (cohesion = the warp), [Q-103](../questions/architecture.md#q-103) (mutator schema — open), [Q-105](../questions/architecture.md#q-105) (seasonal/clock state — temperature/ElevationDelta forward contract)