fix(simulation): address PR #172 review — C1 over-vegetation + H1 biosphere gate (T-1084/T-1085)
Hoshe + Tyre review of the micro-habitat-mosaic branch requested changes on two data-confirmed correctness bugs plus follow-through. All addressed. Blocking: - C1 (voxel.rs): the mosaic re-granted vegetation the climate withheld — a frozen ice world (Edict) read 61% vegetated tundra. The Grassland apply-gate now fires only where the climate already grants cover (!Barren); a climatically-barren district (frozen < -50C = surface ice/geology D-239 §2, or hyper-arid moisture<5, both resolved to VegetationClass::Barren upstream) is skipped. Genuine tundra (cold + moisture>=15) is Scrub upstream and still reaches the tundra palette via the same !Barren path. believability.json regenerated: Edict vegetated_districts 39->0, Arbour 20->8 (its real cold-pole/arid districts revert to barren); intra-class variety preserved (Arbour vegetation_classes 3, micro_habitat_distinct 2). - H1 (bodies.py): biosphere Gate 0 keyed on `inhabited`, conflating settlement with biosphere and force-Airless'ing uninhabited-but-alive worlds (D-247: worlds were alive before humans). Gate 0 is now settlement-independent — keyed on atmosphere/hydrosphere/planet_class. 24 uninhabited-alive worlds now classified (was 0); GJ0g-1 (dense atm + rivers) -> NativeMirror. Split 122 Compatible : 121 Mirror; all 9 canon exemplars hold. Follow-through: - C2 (bodies.py + D-247): Gate 0 now reads planet_class (barren -> Airless) as D-247's "+ planet_class" phrasing names. D-247 amended to record the actual two-gate signal set (atm/hydro/planet_class habitability; economic_base_primary chirality; settlement-independence). - C3 (believability.rs): micro_habitat_distinct criterion relaxed to `== 0 || >= 2` — the min-over-patches estimator makes K=3 unreachable against a dominant-entry palette; K=2 provisional, Q-123 calibrates. - C4 + H2 (D-246): amended to record the v1 scope cut — only the Soil-derived vegetated/wet classes take the mosaic; material-driven families are `_ => false` so Hardpan/Scree are authored but unreachable in v1; no elevation change in v1; the mosaic OWNS the §8 climate->vegetation law for the classes it touches. - H3 (voxel.rs): three dedicated mosaic-pass regression tests — C1 barren-respect, §8 material-untouched + forest-textured, T-1040 no-water-without-channel. - H4 (voxel.rs): relief_signal comment corrected to ~[-1,+1]. - H5 (bodies.py): frontmatter override now strips quotes + validates against the 4-value enum (warn-and-skip on typo). systems.db regenerated + stamped (H1). believability golden regenerated (C1). Full cargo test green; clippy -D warnings + ruff clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1924,6 +1924,10 @@ Technical foundation decisions that constrain implementation: engine, client-ser
|
||||
- **New D-228 axis values** (append-only discriminants, [D-010](#d-010)): `Vegetation::Meadow = 7` (forb-rich flowering herbaceous — the wetland *meadow* and grassland *wildflower*), `Vegetation::Deadfall = 8` (dead woody debris — obstruction + fire fuel, no canopy concealment), `Vegetation::Lichen = 9` (crustose/pioneer biological crust — the rock *lichen* and lava *weathered crust*), `TerrainMaterial::Hardpan = 6` (compacted flat crust — hard fast footing, does not slump like sand), `TerrainMaterial::Scree = 7` (loose angular rock debris — unstable footing; *scree*/*talus* differ only by derived name). `Water` is unchanged (Dry/Shallow/Deep suffice). Adding these lights up exhaustive `match` arms across `voxel.rs`, `from_vegetation_class`, the renderer, and any serializer — an intentional compile-time checklist.
|
||||
- **Rationale:** T-1084's finding was that a class can pass every binding law ([D-239](#d-239) §8) and still render as one uniform material ("Wetland 100%"); [D-245](#d-245) makes *believability* the gate, and intra-class variety is one of its five necessary conditions. Reusing the T-1081 `detail_scatter` machinery (same enveloped-fBm core, one more octave band, one more `SeedDomain`) keeps the mechanism inside the derive-don't-store tier with no new architecture. Front-loading the whole vocabulary — rather than growing it as needs appear — is forced by determinism: the palette is a *weighted selection* the seed indexes, so every added value shifts the realization of already-generated worlds. Expressing micro-habitats as combinations of orthogonal axes (plus derived name/relief) rather than a flat `MicroHabitat` enum is the same anti-combinatorial-explosion logic as D-228 itself.
|
||||
- **Implementation:** [T-1084](../../.pql) (story under epic [T-1079](../../.pql)). Touchpoints: `detail_scatter.rs` (`voxel_mosaic()` + the `[64,32,16,8]` m band); `seed.rs` (`SeedDomain::VoxelMosaic = 12` + the pinned-discriminant guard); `voxel.rs` (new per-family-gated mosaic pass after the relief block ~`:495`; **replaces** `scatter_vegetation()` ~`:1907`; new axis-value `match` arms); `believability.rs` (`micro_habitat_distinct` + criterion); new `server/data/mosaic_constants.toml`. Budget verified in the T-1081 harness.
|
||||
- **Amendment (T-1084, 2026-07-05 — v1 implementation scope, PR #172 H2/C4):** the first implementation lands a **narrower pass than item 5 specifies**, recorded here so the record and code agree (the [D-239](#d-239) T-1080/81/82 postscript pattern):
|
||||
- **Only the Soil-derived vegetated/wet classes take the mosaic** in v1 — Wetland, Forest, Grassland (the `apply` gate in `voxel.rs`). The **material-driven** families (Sand, Rock, Gravel, Lava) are gated `_ => false`, so the material-variant rows of the table above — dune crest/**hardpan**, **scree**/talus, dry-wash Gravel, and every Lava row — are **authored but not yet constructed on any reachable path**, and the two new `TerrainMaterial::{Hardpan, Scree}` values are consequently unreachable in v1. A material change on those families must respect the family's own lithology and carved geometry (shape-aware §8 reconciliation), so they are the deferred follow-up. Item 5's promise that the flat families take the *full* (material + micro-relief) mosaic is **deferred, not delivered** at v1.
|
||||
- **No elevation change in v1.** The item-5 micro-relief nudge (dune crest/slack, bog lows) and the non-structural dramatic-family pass are both deferred — v1 modulates **vegetation + water only**, never `elevation_m`. The D-239 §8 **lithology** law therefore holds trivially: material and shape are left exactly as the family generator set them.
|
||||
- **For the three classes it does touch, the mosaic OWNS the §8 climate→vegetation law** (C4), not merely stays inside it. The **no-skip** half holds — no palette emits `Barren` in a Forest / Wetland / Grassland zone. The **climate-appropriateness** half is enforced by the Grassland apply-gate `!Barren`: a climatically-barren district (frozen `< -50 °C` = surface ice / geology per D-239 §2, or hyper-arid `moisture_q < 5` — both resolved to `VegetationClass::Barren` upstream by `derive_vegetation`) is **skipped**, so the mosaic never re-grants cover the climate withheld (the C1 fix: Edict, a frozen ice world, must not read as vegetated tundra — [D-245](#d-245) §5). The trade: the family generators' *guaranteed* riparian Thicket band is softened to a **probabilistic** wet-habitat clustered near `has_active_channel` chunks (T-1040-gated) — acceptable at v1.
|
||||
- **Cross-reference:** [D-228](#d-228) (the axes this modulates — amended 2026-07-02 to add the five values), [D-227](#d-227) (derive-don't-store — the tier the mosaic lives in), [D-245](#d-245) (believability gate — this is condition 3, intra-class variety), [D-239](#d-239) §8 (binding laws — the mosaic stays inside them) / §10 (sub-chunk budget), [D-243](#d-243) §2 (the detail-scatter tier T-1081 and this extend), [D-247](content.md#d-247) (native-mirror vs introduced-Earth **biosphere register** — palette-key input 3; the mosaic is chirality-blind, but its register labels each niche native or introduced), [D-210](#d-210) / [T-948](../../.pql) (SubBiomeVariant — now **palette-key input 2**: the macro biome realized as the finer intra-class distribution, not a single tag). Tickets: T-1084 (this), T-1079 (epic), T-1081 (relief — a conditioning input + the reused machinery), T-1083 (enforcer — measures the mosaic), [Q-123](../questions/architecture.md#q-123) item 3 (calibrates K).
|
||||
- **Dissent:** None
|
||||
|
||||
|
||||
@@ -634,6 +634,10 @@ How narrative, NPCs, and world content are created: content tiers, NPC generatio
|
||||
- **Colonization is ecological *war*, not terraforming.** Two centuries can't build an atmosphere, but they are ample to **burn back native ecology and hold an Earth-crop perimeter.** So the Earth-chirality footprint is a **spatial field that grows outward from settlements over wave-time**: `P(introduced Earth ecology) ≈ f(distance-to-settlement, settlement_age, economic_tier, arability)`. Wave-1 capitals → broad established farmland; Wave-5 frontier → a thin beachhead in native wilds. Three policy states per locale: **converted** (Earth-managed core), **contested** (naturalized front — escapees vs native reclaiming; abandoned land reverting), **preserved** (native biosphere protected — either *from exploitation* because it is edible/valuable (Keid, GJ-166A, the Cadwal archetype) or *for study* because it is inert (the Solandar xenobotany economy, GJ-827)). Mirror worlds show *sharp two-biosphere fronts*; Compatible worlds show *blended, competing* ecology.
|
||||
- **Code hooks (bounded, verified derivation-safe).** A new body attribute `biosphere_class ∈ {NativeCompatible, NativeMirror, TerraformedSterile, Airless}`, read *once per body*, consumed downstream (food/economy/perception), touching **nothing** in voxel geometry. It is an **authored input, not a derivation** — chirality follows a world's authored economic/cultural identity (Arbour's estate families *grow their own food*; a coin flip could wrongly declare that biology inedible), so it is authored data, never seeded entropy. Home: wiki body frontmatter (where `substrate:` already lives) → a nullable `bodies.biosphere_class` column → the `BodyParams` read set (D-240). Canon-silent bodies take a **principled default inferred from `economic_base_primary` + `planet_class`** (still authored-data logic, not entropy), with explicit per-world overrides where canon speaks (Solandar=Mirror, Keid=Compatible, Oshima=`TerraformedSterile`, Arbour=Compatible). That frontmatter + schema + importer bundle **lands with the Miri continuity pass** (asset-pipeline: schema ships with its source + consumer) — **no column is needed for D-246**, whose native mosaic is chirality-agnostic. Provenance at the tile is a new **orthogonal overlay field** `VoxelColumn.biosphere ∈ {Native, Introduced}` (defaulted `Native`, `#[serde(default)]`), sitting beside `cover` — set `Native` by the wild/natural derivation (all of Phase 4) and `Introduced` by the future managed override, i.e. it is exactly D-228's **wild → economic/managed** precedence read as a label. Every voxel still resolves to a complete D-228 tuple; the bit adds no unset state and no new RNG.
|
||||
- **Scope.** The *biochemistry* is phase-independent canon. The *tile register* is Phase 4 — but only its **native** half exists now (the managed Earth-conversion layer is drawn later by the settlement/economic pass, D-166 outside-in). Food-supply economics is a Phase-2 consumer (already latent — agriculture-as-leverage, frontier net food importers). Foraging futility, predators that gore-but-don't-eat, absent native medicine, and Earth-blight-not-native-plague are **parked gameplay** (T-1036) — flagged, not designed here.
|
||||
- **Amendment (T-1085, 2026-07-05 — implemented default signal set, PR #172 H1/C2):** the shipped `populate_biosphere_class` default (`tooling/economy-db/economy_import/bodies.py`) is a **two-gate** function, and its signal set is the "`economic_base_primary` + `planet_class`" phrasing above **honored and widened** so the record matches the code:
|
||||
- **Gate 0 — habitability, settlement-independent** — reads `atmosphere` + `hydrosphere` + `planet_class` (not `economic_base_primary`, not `inhabited`). No real atmosphere (`""/none/trace`) or a `barren` `planet_class` → `Airless`; a *thin* atmosphere → `TerraformedSterile` if inhabited else `Airless` (the Oshima case — a held atmosphere is settlement infrastructure); a real atmosphere but no liquid hydrosphere → `Airless`. This gate is deliberately **independent of settlement**: an uninhabited world with a real atmosphere + liquid water was alive before humans and stays alive (the H1 fix — the earlier `not inhabited → Airless` pre-gate conflated *settlement* with *biosphere* and mis-classified ~24 uninhabited-but-alive worlds, e.g. `GJ0g-1`, collapsing the Compatible/Mirror population).
|
||||
- **Gate 1 — chirality** — reached only for a habitable world, reads `economic_base_primary`: agriculture / service → `NativeCompatible`; penal / extractive / manufacturing → `NativeMirror`; the neutral remainder → a **stable per-body SHA-1 hash split** (~50/50, deterministic, no entropy). Authored frontmatter overrides still win over the whole function.
|
||||
- So `planet_class` **is** a default input (Gate 0, alongside atmosphere + hydrosphere), and `economic_base_primary` is the Gate-1 input — the two named signals now map to the two gates, with the habitability signals (atmosphere/hydrosphere) that the original phrasing left implicit made explicit.
|
||||
- **Rationale:** "Implemented" is a false summit for a setting the same way it is for the cascade (cf. [D-245](../decisions/architecture.md#d-245)). The Reach's habitability was scattered across a dozen wiki entries as unexplained flavor ("alien biochemistries, incompatible, inedible, non-infectious — *almost always*"); this record supplies the single mechanism that predicts all of it *and* its exceptions, and turns "can I eat here?" into a legible, generatable world property. The 50/50 chirality boolean (vs a fuzzy "usually incompatible") is chosen because it makes both world-classes common enough to matter and gives the storyteller a hard axis. Native-life-not-terraforming is forced by the timeline math the setting already committed to. Touchstones: Mass Effect (levo/dextro food chirality), Vance's *Cadwal Chronicles* (the Conservancy world → Keid), the Bobiverse (convergent-but-alien niches), Hamilton's Commonwealth (non-animal/mega clades, the Primes), Card's descolada/Lusitania (a biosphere as one linked genetic system).
|
||||
- **Affects:** **Wiki continuity pass** (Miri) over the entries that already gesture at this, each assigned a chirality bit consistent with its authored identity — GJ-338B (Arbour — Compatible; estate-food garden), GJ-827 (Solandar — Mirror-inert research preserve), GJ-166A (Keid — Compatible; preserved *because* its edible native biology is an exploitation target — conservation against capital), GJ-524 (Mirror), GJ-684A (native + introduced coexisting), GJ-197 (Earth introductions thrive), GJ-79 (Oshima — `TerraformedSterile`), GJ-124 (Hạ Long — resolve whether its "protein" is native-Compatible harvest or Earth aquaculture). **Schema/code:** authored `bodies.biosphere_class` column + wiki frontmatter (nullable; principled default from `economic_base_primary`+`planet_class`, explicit overrides) — an **input, not a seed derivation** — landing with the continuity pass; `VoxelColumn.biosphere` overlay field. **Economy** (Burnelli): food-supply demand primitive keyed on `biosphere_class`. **[D-246](../decisions/architecture.md#d-246):** its palette register is now grounded as native-mirror-wild vs introduced-Earth-managed.
|
||||
- **Cross-reference:** [D-246](../decisions/architecture.md#d-246) (the mosaic register that consumes this — native vs introduced), [D-228](../decisions/architecture.md#d-228) (the wild→managed override stack this labels), [D-227](../decisions/architecture.md#d-227) (derive-don't-store — `biosphere` is a derived overlay), [D-166](../decisions/scope.md#d-166) (outside-in — the settlement pass draws the Earth-conversion layer), [D-188](../decisions/architecture.md#d-188) (`planet_class` — the sibling body attribute), [D-240](../decisions/architecture.md#d-240) (BodyParams read set `biosphere_class` joins), [D-245](../decisions/architecture.md#d-245) (believability — the conversion gradient supplies coherence + non-stationarity for free). Tickets: T-1084 (D-246 mosaic register), T-1079 (epic); a Miri continuity/vocabulary ticket to be filed.
|
||||
|
||||
Reference in New Issue
Block a user