docs(governance): D-253 region transient state model + Q-102/103/105/109 triage (T-1057)
D-253 (resolves Q-105): the region owns transient clock-bound surface state — four phase terms (diurnal/tidal/weather/seasonal), memoized-by- bucket absolute-clock evaluation, edge-fuzzed per-tile inheritance, integer-deterministic (D-010), state-model-only (no gameplay/rendering). Discharges the T-1030/T-1078/T-1082 forward-contracts. Diurnal promoted to a first-class term (user-confirmed). Q-102 resolved-in-practice (D-246 voxel_mosaic + D-228 override stack); Q-103 + Q-109 deferred to Phase 5+ with dated triage notes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1966,4 +1966,34 @@ Technical foundation decisions that constrain implementation: engine, client-ser
|
||||
|
||||
---
|
||||
|
||||
*106 decisions (D-001 through D-252, excluding gaps). Last updated: 2026-07-06 (D-252 — Facing is view-only: movement no longer writes Facing, NPC gaze becomes AI intent, bump-to-turn retired; resolves the Q-084 walk-vs-aim split with T-1088 play evidence).*
|
||||
### D-253: Region transient state model — seasonal/tidal/weather/snow phase functions (resolves Q-105)
|
||||
|
||||
- **Date:** 2026-07-08
|
||||
- **Resolves:** [Q-105](../questions/architecture.md#q-105).
|
||||
- **Decision:** The region ([D-243](#d-243)) is the single scale at which **transient (clock-bound) surface state** is resolved — "computed once per region per phase, inherited by every district and tile inside" ([D-243](#d-243) §3, the cheap-dynamism source). This record pins that model: **what** transient state a region carries, **how** its clock advances and recomputes, **how** tiles inherit it, and its **determinism** — but explicitly **not** the gameplay/rendering that later consumes it.
|
||||
|
||||
**(a) The transient bundle — four phase terms + their derived surface scalars.** A region carries a memoized `RegionPhase` (proposed carrier name) built from **four clock terms, one per natural clock rate** (fastest → slowest), each a pure function of the in-game clock ([D-031](#d-031)) and the region's static params:
|
||||
- **Diurnal** — day/night, from the [D-031](#d-031) day-phase clock; amplitude = the atmosphere heat-retention already defined in [D-239](#d-239) §2 (thick air → small swing). *This term is the one [D-239](#d-239) §2 already owns for temperature; D-253 folds it into the same region phase model as the other three, rather than leaving it a separate mechanism.*
|
||||
- **Tidal** — from the lunar/day clock; amplitude from the body's satellite config; **absent (zero) when the body has no moon**. Drives the tidal component of water-height.
|
||||
- **Weather** — a coarse, seeded, deterministic precipitation/condition term (a bounded pseudo-sequence keyed on `(region, weather-bucket)` — **not** a simulated advecting weather system; deliberately minimal to stay "nearly free"). Drives puddles + general conditions.
|
||||
- **Seasonal** — from the year clock, **phased continuously by latitude** (amplitude → 0 at the equator and sign inverting across it — a continuous function of latitude, not a binary hemisphere flag, so the equatorial seam never steps). The slow temperature term + the seasonal component of water-height + the snow/crop drivers.
|
||||
- From these terms the region derives its **transient surface scalars** (region-level, not per-tile): **temperature(time)** = the T-1078 / [D-240](#d-240) static baseline **+** seasonal offset **+** diurnal offset (this makes [D-239](#d-239) §2's "temperature(time)" concrete — the static baseline T-1078 ships is the mean-phase value); **water-height(time)** = mean water level **+** seasonal term **+** tidal term; **snow/ice depth** = `f(temperature(time), moisture)` feeding the **existing T-1030 scattered band** ([D-239](#d-239) §3) — D-253 supplies only the *depth over time*, T-1030 owns *where* the band scatters; **weather intensity/category**; and the **crop-cycle phase** (sown → growing → ripe → harvested → fallow) = `f(seasonal)`, the cadence clock for [D-228](#d-228)'s managed-`Vegetation` farmland override (D-253 owns the *cadence*; the settlement/economic layer owns crop *type* and farmland *placement*).
|
||||
|
||||
**(b) Phase-stepping — recompute on bucket rollover, never per tick, never integrated.** Each term declares a **clock-bucket size** (diurnal ≈ day-phase; tidal ≈ day-phase; weather ≈ a multi-phase block; seasonal ≈ a season step). `RegionPhase` is **memoized with the clock-buckets it was computed for**; a query recomputes a term **only when its bucket rolls over** — the "nearly free" requirement, and [D-226](#d-226)'s dynamic-state path. Crucially, every scalar is evaluated from the **absolute clock value** (`state = f(clock)`), **never integrated step-by-step** (`state += Δ`): absolute evaluation is drift-free, reproducible, and hands [D-226](#d-226) its **frozen-phase inspection** for free (freeze the clock → the whole world's transient state is stable and re-derivable). Default bucket sizes are source-canonical + tunable (the `climate_constants.toml` precedent), provisional pending calibration.
|
||||
|
||||
**(c) Inheritance — region computes the scalar, the tile realizes it locally, edge-fuzzed.** Districts and tiles **never compute their own phase** — they read the region scalars, blended across region neighbours by the **same [D-243](#d-243) §4 edge-fuzz** the static climate baseline uses (warp-perturbed bilinear across region centres), so a weather front / seasonal gradient / thaw line never steps on the ~205 km grid (and the equatorial seasonal seam is continuous by construction, per (a)). The **per-tile realization is a local comparison**, not an inherited value: a tile is **flooded** iff `region-water-height(time) > tile.elevation`; **snowed** to a depth capped by the region snow-depth, scattered by the T-1030 band and gated on its own material/moisture; **puddled** iff the weather term is wet and the tile sits in a micro-relief low (the T-1081 `voxel_relief` hollows) that diurnal evaporation has not burned off; its farmland shows the crop stage the region phase dictates. So floodplain / tidal-flat / seasonal-river **emerge** ([D-228](#d-228)) — the static world stays static; only the region scalars carry the clock. This directly discharges T-1082's deferred TidalFlat wet/dry alternation (`Shallow`/`Dry` = tidal water-height vs local elevation).
|
||||
|
||||
**(d) Determinism ([D-010](#d-010)).** Every term and scalar is **integer fixed-point** (phase positions as basis-points of their cycle; depths/heights in integer mm/cm; temperature offsets on the existing integer scale) and a **seeded pure function** of `(absolute clock, region params, body seed)`. **No per-tick float accumulation exists anywhere in the model** — see (b). Weather's pseudo-sequence is a seeded hash of `(region, weather-bucket)`, so it replays identically. Frozen clock → byte-identical state on every platform and every reload; this is what lets the transient overlay live in the [D-227](#d-227) derive-don't-store tier (the memo is **not persisted** — a save records only the clock and the state re-derives).
|
||||
|
||||
**(e) Scope boundary — this is the STATE MODEL, not its consumers.** D-253 defines *derivable transient state and the functions that produce it* — Phase-4-appropriate, viewable as an Atlas layer like every other cascade output, and completing the forward-contracts left open by T-1030 / T-1078 / T-1082. It does **NOT** build: weather/flood/snow **gameplay** (movement, perception, passability effects — [D-239](#d-239) §9 names the passability hook but its wiring is later), the **farming/crop simulation**, snow/water **rendering** (Phase 5), or any **verb** that reads this state. Those are later phases and inherit a fixed contract here. Adding a fifth term or a consumer is a future amendment, not a reinterpretation of this record.
|
||||
|
||||
- **Rationale:** The model is cheap *because* the four transient terms line up with the four natural clock rates and reuse the existing temperature primitive — temperature(time) and water-height(time) are just a static baseline plus the same seasonal/diurnal/tidal offsets, so **one clock model drives temperature, flooding, tides, snow, puddles, weather, and crops** with no per-system simulation. The single load-bearing choice — **absolute-clock evaluation rather than step integration** — satisfies three requirements at once: determinism ([D-010](#d-010), no drift), cheapness (recompute only on bucket rollover, and per-region not per-tile → O(regions)), and inspectability ([D-226](#d-226) frozen phase). Computing at the region and realizing per-tile by comparison is what keeps the dynamism O(regions) while still producing per-tile flood/snow/puddle/crop extent — the "computed once, inherited" contract [D-243](#d-243) §3 promised.
|
||||
- **Raised by:** Jeroen (Q-105 model constraints — clock + hemisphere bound, moon-gated tides, computed-once-per-region, "nearly free", 2026-05-25) + Tyre (T-1057 triage — the four-term phase-function model, the absolute-clock / memoized-by-bucket / edge-fuzzed-inheritance pins, 2026-07-08). **Authored as a proposed design for PR review** — the flagged judgment calls (below) are open for the lead/user to adjust.
|
||||
- **Design choices flagged for review:** (1) **diurnal promoted to a first-class term** — Q-105 enumerated three terms (seasonal/tidal/weather); D-253 adds diurnal as the fourth, since [D-239](#d-239) §2 already owns it for temperature and T-1030's dawn-frost already depends on it (a coherence unification, but it extends Q-105's framing). (2) **weather kept deliberately minimal** (a seeded coarse precipitation/condition term, no advecting fronts) — the depth is a taste call. (3) **recompute-bucket granularities** (diurnal/tidal ≈ day-phase, weather ≈ multi-phase, seasonal ≈ season-step) are provisional/tunable, not hard-pinned. (4) **memoized-not-persisted** reconciles D-228's "region property computed once per phase" with [D-227](#d-227) derive-don't-store (the region *caches* the bundle keyed by bucket; it is never durable state). (5) **"phased by hemisphere" read as continuous-in-latitude** (amplitude→0 at equator) rather than a north/south sign flag, so the seam edge-fuzzes cleanly.
|
||||
- **Implementation:** Phase 4+ (epic [T-750](../../.pql)), the forward contract from T-1030 (transient freeze/snow depth), T-1078 (region climate stack — shipped the static baseline + region-clock *structure*; D-253 adds the transient terms), and T-1082 (tidal-flat wet/dry). Proposed home: a `RegionPhase` carrier alongside `RegionProfile` in `BodyWorldState` ([D-203](#d-203) / [D-239](#d-239) §10 region storage), memoized by clock-bucket; proposed derivations `derive_region_phase(clock, region)` + per-tile realization helpers (flood / snow / puddle / crop) — names non-binding, the impl ticket fixes them. Constants in a source-canonical TOML (`climate_constants.toml` precedent). A new implementation ticket lands under T-750.
|
||||
- **Cross-reference:** [D-243](#d-243) (region = climate/weather/season lockdown scale; §3 computed-once-inherited; §4 edge-fuzz — the inheritance contract), [D-228](#d-228) (the seasonal water-height / snow-cover overlay / crop cycle this model drives — its open water-height sub-question resolved here), [D-239](#d-239) §2 (temperature(time) primitive — made concrete) / §3 (T-1030 scattered freeze-snow — given its clock) / §9 (seasonal passability — a later consumer), [D-240](#d-240) (`planet_class` temperature envelope — the baseline the seasonal/diurnal terms offset), [D-226](#d-226) (dynamic-state frozen-phase inspection), [D-031](#d-031) (game clock / day phases — the clock source), [D-010](#d-010) (determinism), [D-203](#d-203) (BodyWorldState region cache — the memo home), [D-227](#d-227) (derive-don't-store — the memo is not persisted). Tickets: [T-1057](../../.pql) (this triage), T-1030 / T-1078 / T-1082 (the discharged forward-contracts), T-1081 (`voxel_relief` micro-lows — puddle/flood sites).
|
||||
- **Dissent:** None
|
||||
|
||||
---
|
||||
|
||||
*107 decisions (D-001 through D-253, excluding gaps). Last updated: 2026-07-08 (D-253 — region transient state model: four clock-terms (diurnal/tidal/weather/seasonal), memoized-by-bucket absolute-clock evaluation, edge-fuzzed per-tile realization; resolves Q-105).*
|
||||
|
||||
Reference in New Issue
Block a user