feat(simulation): WaterBody voxel family — oceans/lakes/tidal flats render wet (T-1082)

The water zones (OpenOcean/Lake/TidalFlat) fell through to the dry-land AlluvialPlain
fallback, so the sea rendered as dry forested land (the D-245 believability bug).

- voxel.rs: new MorphologyFamily::WaterBody (9th family) + generate_water_body,
  dispatched from zone_to_family. Deep open water with a Shallow shoal band on the
  district-anchored coast line (wider for shallower bodies); TidalFlat all-Shallow.
  Seabed Rock (steep) / Sand (gentle) / Wetland (tidal mud); Vegetation::Barren;
  water surface elevation_m = 0; seasonal Ice via derive_cover (frozen seas). Wetland
  stays AlluvialPlain (it is land — a marsh, not open water). Integer/D-010. + 4 tests.
- believability.rs: fix a sampling bias in the T-1083 enforcer found while verifying
  this — the metrics sampled the first 64 districts in BTreeMap order (a spatial corner,
  e.g. all-ocean), which reported a forested world as "0 vegetated". Now a deterministic
  seeded spread across the body (matches D-245's "randomly-sampled locations").
- D-239 amended (§5 8→9 families; §6 refined — the 3 water zones now dispatch to
  WaterBody). Believability golden regenerated.

Probe (Arbour @ yolo): water-renders-wet 4/64 FAIL → 42/44 PASS; terrain-material
variety 1 → 4 PASS; 3/7 → 5/7 criteria. (Remaining fails — moisture gradient,
vegetation-present — are T-1080.)

clippy --all-targets -D warnings clean; 1579 lib tests + the harness pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 15:30:25 +02:00
co-authored by Claude Opus 4.8
parent ed2c9853be
commit cdc55032df
6 changed files with 266 additions and 30 deletions
+15
View File
@@ -2702,3 +2702,18 @@ BASELINE @ believability-v1: Arbour 3/7, Edict 3/7. FAIL: moisture gradient (dis
DEFERRED (ticket item 3 — explicitly optional): per-layer PNG maps (the T-960 Atlas-viewer stopgap). The contrast+coherence metrics are the core enforcer; maps are a follow-up if the human-gate review wants them before T-960.
This is the D-245 enforcer; advisory now, ratchets to strict (BELIEVABILITY_STRICT) once Q-123 calibrates thresholds and T-1080/1081/1082 flip the criteria.', NULL, '2026-06-28 12:56:03', '2026-06-28 12:56:03.498', '2026-06-28 12:56:03.498', NULL, '73ed53bc02a79f3112f30dea16a82dd3', 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 ('06FGSJWWZNWYT3C4T828ZF1QCG', 'status', 'backlog', 'in_progress', NULL, '2026-06-28 13:00:26', '2026-06-28 13:00:26.933', '2026-06-28 13:00:26.933', NULL, 'e840ecc301d33695e4866a7acdace1ce', 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 ('06FGSJWWZNWYT3C4T828ZF1QCG', 'status', 'in_progress', 'in_progress', NULL, '2026-06-28 13:01:05', '2026-06-28 13:01:05.826', '2026-06-28 13:01:05.826', NULL, '2db838e8ab9ce3cf6385ea00f484e382', 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 ('06FGSJWWZNWYT3C4T828ZF1QCG', 'description', 'Probe evidence (Arbour @ yolo, an OCEAN world): OpenOcean districts derive water=Dry 100% with vegetation Forest 62% on Wetland substrate — i.e. the sea is painted as dry forested land. Root cause (voxel.rs zone_to_family): OpenOcean/Lake/TidalFlat/Wetland fall back to the AlluvialPlain (dry-land) generator; there is no water-body generator that lays Water::Deep/Shallow for water zones, sets a sea/lake surface elevation, or forms coastlines. On an ocean world this means the majority of the surface renders wrong. Known incompleteness (the fallback is documented), filed so it has a home. Direction to discuss: a water-body morphology family (ocean / lake / tidal-flat) that sets Deep/Shallow water + substrate + coast, and how sea level (heightmap sea_level threshold) feeds it.', 'Probe evidence (Arbour @ yolo, an OCEAN world): OpenOcean districts derive water=Dry 100% with vegetation Forest 62% on Wetland substrate — i.e. the sea is painted as dry forested land. Root cause (voxel.rs zone_to_family): OpenOcean/Lake/TidalFlat/Wetland fall back to the AlluvialPlain (dry-land) generator; there is no water-body generator that lays Water::Deep/Shallow for water zones, sets a sea/lake surface elevation, or forms coastlines. On an ocean world this means the majority of the surface renders wrong. Known incompleteness (the fallback is documented), filed so it has a home. Direction to discuss: a water-body morphology family (ocean / lake / tidal-flat) that sets Deep/Shallow water + substrate + coast, and how sea level (heightmap sea_level threshold) feeds it.
---
Refinement (Si pass + user ruling, 2026-06-28) — resolves the ''direction to discuss'':
- FAMILY: dedicated WaterBody family (9th D-239 family) for OpenOcean/Lake/TidalFlat, branching internally on morphology_zone (like IncisedGorge covers MountainPass/ValleyFloor/Alpine). Amend D-239 §5/§6 (8→9 families) + zone_to_family.
- FIDELITY: RICHER — a Shallow fringe along the district-anchored shoreline (ChunkContext.coast_anchor_m, as CliffCoast uses) + Deep toward the interior; TidalFlat = all Shallow (intertidal).
- SUBSTRATE: reuse existing TerrainMaterial (no new variant). Rock seabed/shore where slope_q is steep (Rock IS in the enum — rocky available both above and below water, per user), Sand where gentle; TidalFlat = Wetland (mud). Vegetation = Barren in all water voxels (fixes ''Forest on the sea'').
- SURFACE: water surface elevation_m = 0 (the sea-level convention the existing coastal families already use — raw heightmap sea_level does NOT reach the voxel tier; only ocean_fraction_q/elev_q do). Depth is conveyed by the Water axis (Deep/Shallow), not by elevation_m.
- COVER: reuse derive_cover so cold-body water gets Ice (frozen seas on Edict) — important for the frozen-world believability case.
- SCOPE: Wetland zone STAYS AlluvialPlain (it is land — a marsh, not open water; only the 3 named zones get WaterBody). Transient tidal wet/dry alternation deferred to Q-105.
- DETERMINISM: integer arithmetic only (D-010); warp before the integer voxel address, as the other families.
- VERIFICATION: the T-1083 believability harness must flip ''water renders wet'' toward green for Arbour + Edict; update the golden (UPDATE_GOLDEN) to capture the improvement.', NULL, '2026-06-28 13:10:56', '2026-06-28 13:10:56.408', '2026-06-28 13:10:56.408', NULL, 'f9737eab39f048ff84b8478ca11f5215', 2) ON CONFLICT(hash) DO NOTHING;
+15
View File
@@ -3635,3 +3635,18 @@ BASELINE @ believability-v1: Arbour 3/7, Edict 3/7. FAIL: moisture gradient (dis
DEFERRED (ticket item 3 — explicitly optional): per-layer PNG maps (the T-960 Atlas-viewer stopgap). The contrast+coherence metrics are the core enforcer; maps are a follow-up if the human-gate review wants them before T-960.
This is the D-245 enforcer; advisory now, ratchets to strict (BELIEVABILITY_STRICT) once Q-123 calibrates thresholds and T-1080/1081/1082 flip the criteria.', 'in_progress', 'high', NULL, 'server', 'D-239', '2026-06-28 05:55:19.712', '2026-06-28 12:56:03.498', NULL, 'e39a34b2d5f662cef1b8fee88a70c8f9', 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 ('06FGSJWWZNWYT3C4T828ZF1QCG', 'story', '06FGSJNP8YM537DJCC82ZD6544', 'No water-body voxel generator — OpenOcean/Lake/TidalFlat render as dry land', 'Probe evidence (Arbour @ yolo, an OCEAN world): OpenOcean districts derive water=Dry 100% with vegetation Forest 62% on Wetland substrate — i.e. the sea is painted as dry forested land. Root cause (voxel.rs zone_to_family): OpenOcean/Lake/TidalFlat/Wetland fall back to the AlluvialPlain (dry-land) generator; there is no water-body generator that lays Water::Deep/Shallow for water zones, sets a sea/lake surface elevation, or forms coastlines. On an ocean world this means the majority of the surface renders wrong. Known incompleteness (the fallback is documented), filed so it has a home. Direction to discuss: a water-body morphology family (ocean / lake / tidal-flat) that sets Deep/Shallow water + substrate + coast, and how sea level (heightmap sea_level threshold) feeds it.', 'in_progress', 'high', NULL, 'server', 'D-239', '2026-06-28 05:54:58.429', '2026-06-28 13:00:26.933', NULL, '12c4956809610e71cdf625d28fc48bdb', 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 ('06FGSJWWZNWYT3C4T828ZF1QCG', 'story', '06FGSJNP8YM537DJCC82ZD6544', 'No water-body voxel generator — OpenOcean/Lake/TidalFlat render as dry land', 'Probe evidence (Arbour @ yolo, an OCEAN world): OpenOcean districts derive water=Dry 100% with vegetation Forest 62% on Wetland substrate — i.e. the sea is painted as dry forested land. Root cause (voxel.rs zone_to_family): OpenOcean/Lake/TidalFlat/Wetland fall back to the AlluvialPlain (dry-land) generator; there is no water-body generator that lays Water::Deep/Shallow for water zones, sets a sea/lake surface elevation, or forms coastlines. On an ocean world this means the majority of the surface renders wrong. Known incompleteness (the fallback is documented), filed so it has a home. Direction to discuss: a water-body morphology family (ocean / lake / tidal-flat) that sets Deep/Shallow water + substrate + coast, and how sea level (heightmap sea_level threshold) feeds it.', 'in_progress', 'high', NULL, 'server', 'D-239', '2026-06-28 05:54:58.429', '2026-06-28 13:01:05.826', NULL, '330a98a5774e1be834fd8fef02e2f1ff', 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 ('06FGSJWWZNWYT3C4T828ZF1QCG', 'story', '06FGSJNP8YM537DJCC82ZD6544', 'No water-body voxel generator — OpenOcean/Lake/TidalFlat render as dry land', 'Probe evidence (Arbour @ yolo, an OCEAN world): OpenOcean districts derive water=Dry 100% with vegetation Forest 62% on Wetland substrate — i.e. the sea is painted as dry forested land. Root cause (voxel.rs zone_to_family): OpenOcean/Lake/TidalFlat/Wetland fall back to the AlluvialPlain (dry-land) generator; there is no water-body generator that lays Water::Deep/Shallow for water zones, sets a sea/lake surface elevation, or forms coastlines. On an ocean world this means the majority of the surface renders wrong. Known incompleteness (the fallback is documented), filed so it has a home. Direction to discuss: a water-body morphology family (ocean / lake / tidal-flat) that sets Deep/Shallow water + substrate + coast, and how sea level (heightmap sea_level threshold) feeds it.
---
Refinement (Si pass + user ruling, 2026-06-28) — resolves the ''direction to discuss'':
- FAMILY: dedicated WaterBody family (9th D-239 family) for OpenOcean/Lake/TidalFlat, branching internally on morphology_zone (like IncisedGorge covers MountainPass/ValleyFloor/Alpine). Amend D-239 §5/§6 (8→9 families) + zone_to_family.
- FIDELITY: RICHER — a Shallow fringe along the district-anchored shoreline (ChunkContext.coast_anchor_m, as CliffCoast uses) + Deep toward the interior; TidalFlat = all Shallow (intertidal).
- SUBSTRATE: reuse existing TerrainMaterial (no new variant). Rock seabed/shore where slope_q is steep (Rock IS in the enum — rocky available both above and below water, per user), Sand where gentle; TidalFlat = Wetland (mud). Vegetation = Barren in all water voxels (fixes ''Forest on the sea'').
- SURFACE: water surface elevation_m = 0 (the sea-level convention the existing coastal families already use — raw heightmap sea_level does NOT reach the voxel tier; only ocean_fraction_q/elev_q do). Depth is conveyed by the Water axis (Deep/Shallow), not by elevation_m.
- COVER: reuse derive_cover so cold-body water gets Ice (frozen seas on Edict) — important for the frozen-world believability case.
- SCOPE: Wetland zone STAYS AlluvialPlain (it is land — a marsh, not open water; only the 3 named zones get WaterBody). Transient tidal wet/dry alternation deferred to Q-105.
- DETERMINISM: integer arithmetic only (D-010); warp before the integer voxel address, as the other families.
- VERIFICATION: the T-1083 believability harness must flip ''water renders wet'' toward green for Arbour + Edict; update the golden (UPDATE_GOLDEN) to capture the improvement.', 'in_progress', 'high', NULL, 'server', 'D-239', '2026-06-28 05:54:58.429', '2026-06-28 13:10:56.408', NULL, '8f55fc31d54598d0756308b8e6ef645c', 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);