Commit Graph
7 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 4.8 0263b68df9 feat(simulation): cache TerrainAnalysis + derive basin_direction from the D8 thalweg (T-1044, T-1047)
T-1044: run_layer1 now returns TerrainAnalysis (carried transiently on
CascadeSnapshot, dropped after the district + road-graph passes), eliminating the
redundant per-body drainage::analyze + TerrainAnalysis::analyze re-run flagged by
PERF/TODO(T-1044). Not persisted on the LRU-cached state (D-203/T-1048 size concern).

T-1047: basin_direction is now derived from the real D8 thalweg. run_layer1
aggregates a per-district dominant D8 direction from the live fdir grid (carried
transiently on DrainageResult), threaded via Layer1Output.district_basin_dirs ->
derive_all_districts -> DistrictProfile.basin_direction; derive_chunk_context reads
it directly. Removed the false derive_basin_direction (it branched on ocean_fraction_q
then read seed bits despite a doc comment claiming an elev_q/slope_q D8 proxy) +
corrected the module contract. D-239 §8 (D8 thalweg) now actually honoured.

1559 tests pass; golden byte-identical (district_basin_dirs is #[serde(skip)], transient).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 09:46:42 +02:00
jpmschweitzerandClaude Opus 4.8 ff5e7ee944 fix(simulation): VoxelCache precondition doc + sec_phase decontamination + cache blend test (T-1042)
Addresses PR #167 review (Hoshe H1/H2/H3, Tyre T2).

H1 — the VoxelCache 'same (seed, body_id, tile_pos) -> same column' invariant
is no longer unconditional after the T-1042 blend (the key omits blend_weight/
secondary). Replaced with an explicit precondition on the struct + get_or_derive:
the caller must pass the ChunkContext of the chunk that contains the tile.

H2/T2 — sec_phase claimed to be 'position-independent' but mixed in
primary_meander_phase/2 (the primary's per-position seed), making the secondary
phase proxy asymmetric and primary-contaminated. Dropped that term; sec_phase is
now the secondary's own morphology scalars (slope_q + moisture_q), with a comment
honestly naming it a bounded cosmetic approximation and where to thread the real
secondary seed if needed.

H3 — added cache_boundary_tile_blend_is_stable: derives a boundary ChunkContext
(blend_weight=128, secondary=Some), calls get_or_derive twice, asserts a cache
hit + identical blended elevation + that the Cow::Owned blend path actually ran.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 17:30:46 +02:00
jpmschweitzerandClaude Opus 4.8 32010cc498 feat(simulation): cross-district parameter blending at chunk/voxel scale (T-1042)
Replaces the single-DistrictProfile walking-skeleton restriction so
continuous terrain parameters no longer step at the 2 km district pitch
(D-239 §4/§7/§8). ChunkContext gains secondary: Option<DistrictProfile> +
blend_weight: u8; derive_chunk_context detects a chunk within one chunk of
a district border, looks up the adjacent profile, and integer-blends
meander/channel params on the context. derive_voxel_column integer-blends
elev_q/moisture_q before material selection, reusing the same warp offset so
the seam cannot align with the chunk edge (Cow fast-path keeps interior
chunks bit-identical — golden seed unchanged).

Morphology FAMILY selection is never blended — stays sharp per D-239 §7
(family dispatch reads the primary district only). Climate feathering is the
separate T-1078 path. Adds cross_district_elevation_blend_reduces_seam_step
and cross_district_morphology_family_seams_stay_sharp to the derivation
harness.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 14:05:48 +02:00
jpmschweitzerandClaude Opus 4.8 b3b5bfc2e3 refactor(simulation): rename carrier RegionProfile->DistrictProfile + re-scale to the D-243 ladder (T-1077)
Phase 2 of the D-243 re-scale. The ~1km carrier is renamed and re-scaled to
the 2km district, and every consumer reads scale from the canonical scale.rs
instead of a local literal.

- region_profile.rs -> district_profile.rs; RegionProfile -> DistrictProfile,
  RegionPos -> DistrictPos (re-exported from scale::DistrictPos), derive_*_regions
  -> derive_*_districts, across all 10 consumers + the derivation harness.
- chunk_context now references scale:: for the carrier cell: district 1024m -> 2048m,
  shift 4 -> 5 (CHUNK_DISTRICT_SHIFT). This caught a real latent bug: the seed-district
  index used a literal '>> 4' while the anchor used the constant, so same-district
  chunks could derive different anchors — now both use scale::CHUNK_DISTRICT_SHIFT.
- derivation_harness scale literals ('>> 4', '* 1024', '0..16') converted to
  scale:: constants (the same drift the canonical source eliminates). Believability
  tests pass at 2km; the voxel determinism golden re-pinned (anchors moved with the
  re-scale — deterministic, intended).

Full suite + clippy --all-targets -D warnings green. The district DERIVATION still
tiles the heightmap at 8 cells (the old coarse path); replacing it with on-demand
heightmap interpolation + detail-scatter is phase 3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 22:53:18 +02:00
jpmschweitzerandClaude Fable 5 993333facc style(engine): rustfmt — wrap long lines in bridge_tcp test + chunk_context gate (gate fixup)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 13:48:53 +02:00
jpmschweitzerandClaude Fable 5 408bd39e63 fix(simulation): region-anchor channels and linear landforms (T-1040, T-1041)
derive_chunk_context now derives channel_anchor_m and coast_anchor_m from
the Region-or-higher seed path (D-239 §10); all five voxel placement sites
measure distance to these anchors in continuous world coordinates:

- T-1040: compute_channel_state / compute_meander_reach_channel /
  in_levee_band subtract the region anchor instead of measuring from the
  world origin axis — active channels now exist in their chunks anywhere
  on the body, continuous across chunk boundaries. has_active_channel is
  honest in both directions (band-crossing gate; floor covers the
  BraidedDelta belt at short wavelengths).
- T-1041: fjord/cliff/gorge/delta drop their rem_euclid(64) chunk-frame
  folds — one valley/coastline/fan per region instead of one per chunk.
  D-239 §9 chokepoint widths preserved; two i32 wall-rise overflows on
  region-scale distances fixed by clamping before multiply.

Harness: 6 new believability tests (channel presence + gate honesty at
chunk (1000,-750), cross-boundary continuity, one-landform-per-region,
braid-belt confinement); drainage sweeps strengthened with anchor-band
chunks. Voxel golden regenerated deliberately: case A now pins a genuinely
in-channel Shallow voxel on the anchor, case C a Deep trough voxel
matching its label; case B byte-identical and L0/L1 cascade golden
untouched (no upstream leak). Review: approved, three minors addressed
(truncation-convention docs, delta gate floor, case C relocation).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 13:46:38 +02:00
jpmschweitzerandClaude Opus 4.8 cd8bfec64b feat(simulation): VoxelColumn walking skeleton (T-1028)
D-239 §1/§7/§10 — the lower derivation chain end-to-end with the AlluvialPlain
fallback only (specialized families are T-1029).

- chunk_context.rs: ChunkContext (64m) — basin_direction + meander phase/wavelength
  + active-channel params. NO per-tile flow_direction[64x64] (D8 ~152m coarser than
  a chunk, D-239 §10); features >64m seed from Region-or-higher. SeedDomain::ChunkContext=8.
- voxel.rs: VoxelColumn (1m) composing the D-228 tile axes (TerrainMaterial /
  FloorMaterial=None / Vegetation / Water / elevation_m). Derive-on-demand + VoxelCache
  (LRU BTreeMap, never persisted per D-227). Domain warp (T-1026) wired through:
  f64 warp -> as-i32 truncation to the voxel address; all material/morphology gates
  integer (D-010 — the meander wavelength f64 is truncated before the Water decision).
- AlluvialPlain generator: Soil/Wetland terrain, climate vegetation, integer-meander
  channel (Shallow/Deep) from ChunkContext. The other 7 families are dispatch stubs
  (canonical terrain material, fall back to AlluvialPlain geometry) — no panic.

29 new tests incl end-to-end determinism (same seed/pos -> identical column),
cache hit/miss/eviction/re-derivation, warp-applied. cargo test 1563 pass,
clippy -D warnings clean, fmt clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 13:53:47 +02:00