Files
settled-reach/docs/workshops/tile-derivation-contract/D-239-draft.md
T
jpmschweitzerandClaude Opus 4.8 fa8b6ebf08 docs(governance): file D-239 tile derivation contract, resolve Q-101
Resolves Q-101 — how a coarse Layer-1 cell + seed becomes coherent ~1m
voxel geometry across the scale jumps. The tile-derivation-contract
workshop output:

- three-carrier refinement chain RegionProfile -> ChunkContext -> VoxelColumn,
  pure deterministic, no authoring at the derivation layers
- district-temperature climate primitive (2x2 km, C, nullable) + separate
  moisture; everything climatic derives from temperature(+moisture)
- scattered, transient freeze/snow model (freshwater +5..-10, sea ice own
  band, snow moisture-gated; forms cold phase / melts warm phase)
- stateless f64-to-voxel domain warp (anti-squaring)
- 8 morphology families over a frozen 17-zone vocabulary, gated decision tree
- seams prevented at source (gate ordering + build-time matrix); valid
  geomorphic seams kept sharp + warped

Includes workshop brief, round-1 positions, and workshop-outcomes.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:14:55 +02:00

7.2 KiB
Raw Blame History

D-239 (REVISED post-verification): Tile derivation contract — coarse→fine refinement chain (Q-101)

domain: architecture · type: confirmed · date: 2026-06-07 · resolves: Q-101

Decision. The walkable tile is materialised by a three-carrier refinement chain, each stage a pure deterministic function of (seed, atlas, body-params, position) per D-227: RegionProfile (~1 km) → ChunkContext (64 m) → VoxelColumn (1 m). Each scale boundary is its own derivation with its own failure modes.

Determinism — no authoring at the derivation layers, ever

L1L5 derivation has zero per-body override hooks. All authorial control lives upstream at the body-parameter / atlas / system-specialization layer; the gating params (GlaciationGrade, precipitation_class, RIVER_THRESHOLD, tectonic_class) are derived from body params (stellar type / orbit / hydrosphere / lithology), never authored. RIVER_THRESHOLD specifically is a derived per-body-class value (hydrosphere, tectonic_activity, precipitation_class) → threshold, not the global constant 200. Lore-anchored bodies are honoured by setting params and stand as validation cases — if a body reads wrong, fix its params, never patch the derivation. Validation caveat: derived terrain can only honour a lore body if its params permit it — e.g. tidal flats require a moon param (the D-228 tidal term); confirm each validation body's params before treating its terrain as a contract (Velen's tidal-flat coast presumes Velen has a moon — verify).

Anti-"squaring" (warp)

A global position-keyed domain-warp field suppresses grid/seam artifacts. The warp is a stateless, hash-based pure function of (seed, body_id, position) — no lookup table, no thread-local cache (so it's order-independent across threads/platforms). It keeps f64 sub-metre precision through to the final voxel coordinate, then quantises by truncation to the integer voxel address — a cast, not a comparison, so IEEE-754-deterministic across targets. The ±8 m warp range makes FMA-contraction ULP variance (~1e-15 m) unable to shift the rounded voxel, so no platform guards are needed. The warp is position math, not a structural decision — D-010 integer discipline on all material/morphology decisions is preserved.

Morphology — 8 families

Selected by a strict decision tree over integer RegionProfile inputs: LavaField · FjordWall · CliffCoast · BraidedDelta · DuneStrand · IncisedGorge · MeanderReach · AlluvialPlain (fallback). Requires adding tectonic_class to RegionProfile. MountainPass is a zone label sharing IncisedGorge geometry. Hard gates (boolean, applied pre-selection in tree order): fjord requires GlaciationGrade ≥ 2; LavaField requires tectonic_class = Volcanic; lithology bounds slope/form (see laws below).

Frozen 17-zone MorphologyZone display vocabulary

Derived labels per D-228, enum→label map frozen at authoring time. The canonical freeze point is the Rust MorphologyZone enum; adding/renaming a zone requires a D-record amendment (a code reviewer enforces this). The 17: open ocean, lake, tidal flat, dune strand, cliff coast, fjord, delta, estuarine, alluvial plain, river bank, meander reach, braided plain, valley floor, mountain pass, alpine, volcanic, wetland. Note — zones ≠ families: four zones (tidal flat, estuarine, alpine, wetland) have no distinct generator family; they are derived sub-classifications from family + elevation/water-height conditions (e.g. tidal flat = BraidedDelta at the tidal margin; alpine = AlluvialPlain/IncisedGorge above the treeline-elevation threshold).

Zone seams — prevent incompatible, allow valid (don't patch)

The boolean gates are discontinuities on continuous inputs, so "continuous→continuous" is NOT the mechanism. The mechanism is the decision-tree gate ordering + a build-time compatibility matrix: incompatible family pairs (e.g. MeanderReach↔Volcanic — geomorphically incoherent) cannot be adjacent classifier outputs; the matrix is a build-time invariant test, never a runtime override. Valid geomorphic seams (cliff↔fjord at the glaciation threshold, lithology faults) are permitted sharp transitions — kept sharp (real geology is sharp), made non-grid/organic by the warp; no modulation feathering. The warp also guarantees seams don't produce degenerate slivers at chunk scale (preserving the per-chunk tactical-content rule below).

Believability laws (binding — inline, not just titles)

  • Drainage monotonicity: channels descend; respect the D8 thalweg (D-208); tributaries join from upstream; river mouths sit at sea level.
  • Lithology → landform: Rock → vertical faces/cliffs; Sand → ≤ angle of repose (~32°), dunes not cliffs; Gravel → braided channels/fans, not single-thread meander; Soil → rolling/floodplain; Wetland → ≤5° flats; Lava → sheets/shield slopes + lava tubes, immature drainage.
  • Glaciation → form: fjord requires GlaciationGrade ≥ 2; U-valleys ≥ 1; moraine ridges ≥ 1; cirques ≥ 2. GlaciationGrade 0 high-relief is V-ridges (fluvial), never glacial U-profiles.
  • Climate → vegetation: treeline transitions Forest → Scrub → Barren (no Forest→Barren skip); riparian Thicket/Scrub band 13 tiles along every perennial waterway; boundaries follow contours/moisture, not chunk edges.

Game-feel constraints

Every chunk carries ≥1 tactical decision point; cover ≠ concealment (mechanically distinct); high-ground asymmetric-but-not-dominant; chokepoints narrow enough to matter (river crossings 315 m, gorge floors 28 m); seasonal/tidal state must produce real passability changes, not cosmetic ones — BraidedDelta/MeanderReach ElevationDelta calibrated so channels fall below the Q-105 high-water threshold and levees stay above it (flood = genuinely impassable, not recoloured).

Mechanics

  • No per-tile flow_direction[64×64] in ChunkContext (D8 ≈ 152 m/cell — coarser than a chunk) → one basin-direction + global meander-curve params. Features with wavelength > 64 m (meanders, dunes, cliff continuations) seed from Region-or-higher, not the chunk seed.
  • Caching: RegionProfile is stored in BodyWorldState (D-203) (~6k/body, populated in the D-206 background pass) so the Atlas reads zone labels without triggering voxel derivation; voxel derivation is on-demand + cached, never persisted (D-227). Budget ~2.24.2 ms/chunk (validate per-family in Phase 4 — FjordWall/IncisedGorge are far costlier than the AlluvialPlain fallback).

Resolves: Q-101. Touches: Q-102 (cohesion = the warp). Leaves open: Q-103 (mutator op schema), Q-105 (region seasonal/clock state — the ElevationDelta calibration above is a forward contract to it). Cross-refs: D-227, D-228, D-203, D-206, D-208/209/210, D-010, D-234, D-142, D-217. Raised by: tile-derivation-contract workshop (Tyre, Gestalt, Troblum, Miri) + lead-interviewed decisions, 2026-06-07; verified by an adversarial pass from the same four. Dissent: Tyre's initial cross-family elevation-blend was resolved against (prevent-at-source). Early-integer-truncation of the warp (raised against Gestalt's ElevationDelta ranges and by Tyre) was resolved against in favour of f64-to-voxel.