docs(assembler): round L20 -- design for director / generators / mesher, layout in metres

Standalone/DESIGN_STRATA_UNITS_AND_LAYERS.md: maps today's code to the three layers, ranks 9
violations (top: no single physical stratum-bounds/interface record; SurfaceWorld 8 m vs
FloatingIslands 4 m per chunk), defines the director-resolved generator request/result contract,
moves seals/caps/voids/interfaces into shared composition, and proposes an explicit LOD-stable
interface surface for the L19 ledges. 6-step migration plan with "worlds don't move" checks;
owner decisions listed. No code or world change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-20 08:53:03 +02:00
1 parent 811c4b7b17
commit 6f9c7bd652
2 files changed
+344

No files matched your search

@@ -0,0 +1,263 @@
# VoxelForge strata, units, and generation layers
**Design round L20 — 2026-10-20**
## Summary
Author strate layout in metres and give each strate a voxel size. Keep Core's internal tile at 32³
voxels; its physical width follows that strate's voxel size and the tile's LOD. Use one director to
resolve the season, layout, seed, generator recipe, resolution, and interfaces before workers start.
Generators then evaluate an immutable, common field contract. A shared composition layer applies
strata boundaries, gaps, seals, edits, caches, and proofs. The mesher consumes that composed field
and generic surface hints; it should not branch on SurfaceWorld, FloatingIslands, or feature type IDs.
The code already has parts of this shape, but not the boundaries between them. In particular,
`FStandaloneShapeWorld` is both a dispatch layer and a collection of field adapters, while
`World::generateTile` contains generator-aware far-surface and feature refinement. The Unreal
adapter currently translates two different meanings of “chunk” into Core coordinates.
The L19 ledges are not explained by a different density recipe per LOD. The ring audit found
upward-facing terrain from the same lower SurfaceWorld field at different extracted heights on
adjacent LODs. At the default 25 cm Core voxel size, LOD1, LOD2, and LOD3 sample at 0.5 m, 1 m,
and 2 m. The maximum LOD1→2 ring difference is 1.49862 m; LOD2→3 reaches 7.73318 m, with 8
no-hit samples among 308. An explicit shared surface contract can give all LODs common boundary
geometry and a controlled transition band. A planar ceiling alone will not fix these ground ledges.
One conversion issue needs an explicit preservation target. The current Core path maps one
SurfaceWorld slot chunk to 32 Core voxels (8 m at 25 cm), but one FloatingIslands slot chunk to
32 owner voxels at 12.5 cm (4 m). Converting each current interpretation independently into metres
can preserve each field's current positions, but it does not make shared chunk indices one common
physical boundary. The converter must record the actual per-strate bounds and any resulting gap or
overlap before choosing a unified interface. Do not promise a no-movement migration from a single
global “metres per chunk” constant.
Metres are not a runtime cost concern. Resolution is. Halving voxel spacing in all three axes means
about eight times as many density samples for the same physical volume, plus more tiles, queue work,
and cache entries because each internal tile remains 32³ voxels. With 25 cm as the default for all
strates, the proposed starting resolution matches today's Core sampling resolution.
## 1. Current code mapped to the three layers
There is no single class called “director” today. The director work is split between Unreal's
season/layout code, the Core adapter, and Core's tile scheduler.
| Intended layer | Current location and symbols | Current responsibility and boundary issue |
|---|---|---|
| **Director / orchestrator** | `VoxelStrateComposer.cpp`; `VoxelSeasonManifest.cpp`; `VoxelStrateManager.cpp` (`Initialize`, `GetGeneratorTypeForChunk`, `GetGenerationParams`); `VoxelWorld.cpp` (`BuildDesiredTiles`, tile scheduling, epochs); `VoxelForgeCoreAdapter.cpp` (`BuildSurfaceStratumPlan`, `BuildFloatingIslandStratumPlan`, `AttachValidatedWorldAssembly`) | Composes season params and stacked slots, resolves generator kind and seed, and serializes the Core snapshot. `WorldAssemblyManifest`, `WorldAssemblyPlanV1`, and their `FromJson`/`finalize`/`validate` functions in `WorldAssemblerInternal.h` are the current plan/manifest format. Resolution and bounds are not fully resolved here: Core re-derives them using generator-specific conversions. `TopWorldZ`, `BottomWorldZ`, `HeightInChunks`, and `InterStrateGapChunks` remain chunk/voxel-coordinate based in owner-facing data. |
| **Generators** | SurfaceWorld: `Heightfield2D` in `VoxelForgeCore.h` and `WorldAssemblerInternal.h`; plan construction in `VoxelForgeCoreAdapter.cpp`. FloatingIslands: `FloatingIslandFieldV1` in `VoxelForgeCore.h` and `FloatingIslandsInternal.h`; plan construction in the adapter. Legacy: `UVoxelGenerator::GetDensityAt` in `VoxelGenerator.cpp`, `VoxelDensityOpStack.cpp`, and `VoxelCaveMorphology.cpp`. | SurfaceWorld and FloatingIslands have distinct plan and evaluator APIs. Legacy generation still asks the manager for the current chunk's params and generator type. In Core, the “generator” boundary is obscured by `FStandaloneShapeWorld`, which selects native fields or falls back to the copied owner generator. |
| **Shared field / composition library** | Noise and fixed-point evaluation: `WorldAssemblerInternal.h`, `FloatingIslandsInternal.h`. CPU/HLSL far-field math: `VoxelForgeFieldShared.h`. FP contract: `CoreNamespacePreamble.h`. Feature culling and caches: `BuildWorldAssemblyFeatureTileListV1`, `ScopedWorldAssemblyFeatureQueriesV1`, `SharedColumnCache.h`, `ThreadLocalStorage.h`. Field bounds/proofs: `Heightfield2D::interval`, FloatingIslands bounds, `FStandaloneShapeWorld::ClassifyBoxDetailed` and `BuildShapeDependencyProof`. Density seals: `VoxelDensityPrimitives.h`. | Useful shared pieces exist, but only for subsets of recipes. Noise is not one library used by every legacy and native generator. Bounds, density, and output identity still use subvoxels of a Core voxel. The canonical stratum bounds descriptor `FResolvedStratumBounds` is private to `ShapeWorldInternal.h`, not part of the plan contract. `AppendStratumBoundaryCeilings` is under far-shell/meshing code, even though the boundary meaning is shared composition policy. |
| **Mesher** | `UVoxelMarchingCubesMesher::GenerateMesh` in `VoxelMarchingCubesMesher.cpp`; dispatch and mesh assembly in `World::generateTile` in `VoxelForgeCore.cpp`; `FarShellsInternal.h`; hybrid sharp support in `VoxelHybridSharpMesher.h` and `VoxelMarchingCubesMesher.cpp`. | MC, skirts, far shells, connector repair panels, LOD refinement, and cap repair are spread across the production mesher and Core tile builder. `World::generateTile` scans recipe feature type IDs, refines type-4 shelves only at LOD0–2, selects a native SurfaceWorld horizon, and invokes separate ground/cap repair. `FStandaloneShapeWorld::BuildFarFieldTileInput` constructs FloatingIslands connector panels. These are recipe-aware mesh paths. |
### What crosses a boundary today that should not
- `FStandaloneShapeWorld` reads `UVoxelStrateManager`, `FStrateSlot`, `WorldAssemblyManifest`, legacy
generator params, and generator type. It selects a recipe, evaluates a field, resolves its bounds,
applies a seal, and builds GPU far-field input. That combines director, generator adapter, shared
field, and renderer responsibilities.
- `World::generateTile` knows `WorldAssemblyPlanV1`, SurfaceWorld heightfields, feature numeric IDs,
and FloatingIslands presence. The generic mesher should receive capabilities and surface data,
not know those recipe identities.
- The adapter exports one layout but encodes physical positions in `WorldAssemblySubvoxelsPerVoxel`.
That makes a physical length's fixed integer depend on the selected Core voxel size.
- Core `WorldAssemblyStratumPlanV1` carries `topChunkZ`/`bottomChunkZ`; validation in
`WorldAssemblerInternal.h` multiplies those values by `32`. FloatingIslands additionally stores
its own owner-to-Core size ratio and metric-equivalent bounds in Core-voxel units.
- The Core boundary path calls `GetResolvedStratumBounds` differently for SurfaceWorld and
FloatingIslands. The director should resolve a single physical boundary record once.
- Legacy density still reaches into manager-owned params and operations. It must become a generator
adapter that consumes the same resolved request as a native recipe, or remain explicitly marked as
a compatibility route until it can be ported.
## 2. Violations, ranked by risk
Rank 1 is the highest risk to correct physical layout and cross-LOD output.
| Rank | Risk | Violation and evidence | Why it matters |
|---:|---|---|---|
| 1 | **Critical** | **No single physical bounds/interface contract.** `FResolvedStratumBounds` in `ShapeWorldInternal.h` derives SurfaceWorld bounds from `Slot.*ChunkZ × 32`, but derives native FloatingIslands bounds from `layout*ZSubvoxels` and an owner/Core scale ratio. `GetResolvedStratumBounds` is then reused by field classification, far-field protection, and far ceiling generation. | A shared logical slot boundary can map to different metre positions depending on generator. This can make an apparent seam a gap, overlap, or misplaced terrain surface before the mesher samples it. It also makes “preserve the old heights” ambiguous unless the old per-field physical bounds are recorded. |
| 2 | **Critical** | **LOD extraction has no required shared surface representation.** `World::generateTile` uses normal MC sampling for LOD1–3; native SurfaceWorld ground refinement is only invoked at LOD4+. L19's strict ring probe excludes skirts and masked triangles and measured 149.862 cm max at LOD1→2 and 773.318 cm max at LOD2→3. | A coordinate-stable density function does not guarantee equal extracted surfaces when sample grids differ. Thin seals can be skipped, and a heightfield root can shift with coarse XY/Z samples. This is the measured ledge failure. |
| 3 | **High** | **Chunk, owner-voxel, Core-voxel, and fixed-point units are mixed.** `WorldAssemblyFixed` in the Unreal adapter serializes lengths as 1/256 Core voxel. SurfaceWorld plan bounds use `Slot.BottomChunkZ * 32` and `(TopChunkZ-BottomChunkZ+1)*32`. FloatingIslands uses `32 × ownerToCoreScaleNumerator / denominator`. `ShapeWorldInternal.h` reverses Core Z to legacy chunk coordinates with `/ GetCoreVoxelsPerOwnerChunk()`. | A parameter's physical interpretation depends on generator and runtime Core size. `/32`, `*32`, and scale-ratio logic are reasonable only in a single boundary adapter or for the internal fixed tile; they are incorrect as the authored layout contract. |
| 4 | **High** | **The Unreal adapter and manager both resolve the same layout.** `VoxelStrateManager.cpp` creates chunk slots and per-generator runtime params; `VoxelForgeCoreAdapter.cpp` re-reads those params and builds distinct native plans; `ShapeWorldInternal.h` maps Core samples back through the manager again. `WorldAssemblyStratumPlanV1::topChunkZ/bottomChunkZ` are checked against the manager in `AttachValidatedWorldAssembly`. | The runtime can validate matching integer slots without validating that the resulting physical bounds mean the same thing for both generators. The future adapter should serialize already-resolved metres and per-strate resolution. |
| 5 | **High** | **Generators read director state.** Legacy `UVoxelGenerator::GetDensityAt` asks the manager for type/params and builds/refetches operator stacks. Core native lookup also asks the manager which generator applies at a Core sample. | The generator cannot be a pure evaluator of a resolved recipe. It is hard to cache, audit, or replay independently, and unit conversion is repeated in worker code. |
| 6 | **High** | **Boundary behavior is split between recipe and shared paths.** FloatingIslands geometry v3 special-cases top seal evaluation in `NativeFloatingIslandDensityAt`; older geometry versions retain two-sided seals. `VF_ApplyBoundarySeal`/`VF_ApplyUpperBoundarySeal` provide shared density math, while `AppendStratumBoundaryCeilings` separately patches missing mesh coverage. SurfaceWorld also owns a heightfield cap. | Density closure, boundary ownership, and visible cap geometry can disagree. A shared operator alone does not guarantee a shared, LOD-stable surface. Preserve versioned historical fields during migration, then route new plans through one contract. |
| 7 | **Medium-high** | **Mesher contains recipe policy.** `World::generateTile` has SurfaceWorld native-horizon selection, a SurfaceWorld-only far skip condition, type-2 sharp boxes, type-4 shelf refinement, separate native ground/cap refinement, and a `farHorizonVersion` identity. `ShapeWorldInternal.h` creates connector panel repairs from FloatingIslands. | A new recipe requires mesher edits and generator details leak into extraction. The mesher should consume explicit surfaces, generic feature constraints, and a requested error/refinement hint. |
| 8 | **Medium-high** | **Legacy paths do not share the new generator format.** `UVoxelGenerator`, operator stacks, morphology caches, Core's native `Heightfield2D`, and `FloatingIslandFieldV1` have separate recipe/parameter routes. | “One generator format” is not yet true. A migration wrapper is needed so behavior can be ported in small, hash-checked steps instead of reimplementing all legacy archetypes at once. |
| 9 | **Medium** | **Shared helpers and numeric policies are partial.** Core's FP preamble/self-test applies to Core translation units; fixed-point noise is implemented in assembler code, island noise is in a separate implementation, and far CPU/HLSL math has its own shared header. Feature bounds/caches are more reusable than the field interfaces. | Keep the tested Core determinism contract, but promote the shared numeric/noise primitives only where their exact semantics can be versioned. “Shared” code is not automatically cross-platform identical if separate float evaluators remain. |
### Unit measurements relevant to migration
`CHUNK_SIZE` is 32 and `VOXEL_SIZE` is 12.5 cm, so the owner's legacy chunk is 4 m
([`VoxelTypes.h`](../Source/VoxelForge/Public/VoxelTypes.h), [`Round5`](Research/WorldAssemblerM3/Round5/REPORT.md)). The current default Core voxel is 25 cm. In the current native Core routes:
| Route | Current conversion | Physical chunk width at default | Evidence |
|---|---|---:|---|
| SurfaceWorld | `32` Core voxels per slot chunk | 8 m | `BuildSurfaceStratumPlan` uses chunk bounds directly in Core voxel units; L18 records the preserved `topChunkZ × 32` mapping. |
| FloatingIslands | `32 × 125000/250000 = 16` Core voxels per owner chunk | 4 m | `BuildFloatingIslandStratumPlan` serializes the ratio and applies it to layout bounds; `GetCoreVoxelsPerOwnerChunk` uses the same ratio. |
This confirms the claimed factor of two. It does **not** prove that this conversion alone caused
the L19 ring delta. L19 isolated the observed step to coarse extraction of lower SurfaceWorld
terrain, and the reported LOD4+ horizon refiner cannot affect those LOD1→2 and LOD2→3 values.
## 3. Generator contract and one-time interface handling
### What the director resolves before generation
The director should publish an immutable `ResolvedWorld` (exact type/schema is an implementation
choice) containing:
- a stable world/season identity and seed;
- an ordered list of strates with a stable ID, generator kind and recipe version;
- each strate's physical minimum and maximum bounds in metres, including height as their difference;
- a voxel size in metres per strate (25 cm default for every strate);
- route points, island anchors/connectors, and all top/bottom/ceiling positions in the same physical
coordinate space;
- one resolved interface record per adjacent pair, including any explicit void, bedrock gap,
sealed contact, upper cap, passage, or open boundary;
- any season-level values that affect world output, such as routes, islands, water datum, or biome
selection, already attached to their owning strate or interface;
- a canonical identity over the sorted resolved layout, seed, resolution map, recipes, and interface
records.
Do not make generators ask the director for the active `FStrateSlot`, chunk number, season, or
neighbour generator while evaluating a point.
### Request to every generator
A worker request should give the generator:
1. The immutable resolved recipe and stable stratum ID.
2. Physical query/tile bounds in metres, including the exact halo requested by the mesher.
3. The canonical sample coordinates or a clearly defined lattice origin and step. Voxel coordinates
are useful as an internal derived lattice, but metres/physical fixed units are the identity space.
4. The resolved per-strate voxel size and seed. LOD can be included as a sampling hint; the canonical
field value itself must not change just because the caller chose another LOD.
5. Read-only interface descriptors that touch the request bounds. Pass boundary records, not a
pointer back to the neighbour's manager or mutable generator.
### Result from every generator
The common result should provide a deterministic field evaluator and its declared capabilities:
- signed density using one documented solid/air sign convention;
- optional material or surface-class data;
- conservative interval/classification proofs and conservative feature/influence bounds, or an
explicit “unknown, evaluate” result;
- optional semantic 2D surfaces such as a ground heightfield or a cap, in physical coordinates;
- a detail envelope / maximum safe sample spacing hint. It is a hint to generic LOD/refinement
policy, not permission for a recipe to choose its own mesh path;
- generator/schema/evaluator versions for stable plan and output identity.
Keep the established fail-open behavior: an unknown interval or influence bound causes evaluation,
not a solid/air skip. Existing feature candidate lists and worker caches fit this contract as
optimizations beneath the evaluator.
### Interfaces, seals, caps, and voids belong to shared composition
The director resolves the meaning and exact physical location of each interface once. The shared
composition layer then combines generator fields and applies boundary semantics in a fixed order:
1. Evaluate each generator only for its declared physical domain, retaining its ordinary
field/feature behavior.
2. Apply the interface contract once: for example, a physically measured seal band, a cap surface,
open void, bedrock gap, or permitted passage. The contract declares ownership, sidedness, material
class, collision/support policy, and whether player edits may cut it. A gap is data, not an
accidental “no generator found” branch.
3. Apply world edits through the canonical composed field, so both sides see the same edit in
physical space.
4. Give the resulting field, proofs, and any explicit surfaces to the mesher.
This centralizes the semantics currently spread across generator density wrappers,
`FResolvedStratumBounds`, and `AppendStratumBoundaryCeilings`. Existing versioned manifests still
need compatibility adapters: do not silently reinterpret old `boundarySealSubvoxels` values.
For two different generator kinds that meet at a plane, both should reference the same stable
interface ID and exact physical boundary. Their density fields can remain independent; shared
composition owns the boundary rule. If the plan intentionally has open space between them, the
resolved layout records that metre-valued interval explicitly.
## 4. Why LOD changes thin features, and the interface surface contract
MC samples density at lattice corners. A thin seal or cap can be narrower than one coarse cell, so
the coarse grid may see no sign change at all. If it does see a crossing, interpolation uses the
coarse cell's endpoint values; its root can differ from the finer grid's root. A shared analytic
density function guarantees the same values at the same physical coordinates, not the same triangles
from different sample grids.
For a physical strate boundary, use an explicit surface descriptor with exact height/shape in metres
and a globally stable sample phase. Every LOD must use common anchors along tile and LOD transition
edges. The mesher can fill the interior at its chosen rate, then build a deterministic transition
band from those common anchors into its coarser interior. A seal/cap should not rely on a sub-cell
thin density strip surviving arbitrary MC sampling.
For the L19 lower-ground ledge, the same rule needs a SurfaceWorld ground profile available to the
mesher as semantic surface data. A shared planar boundary cap would only close the strate ceiling;
it would not align these upward-facing ground triangles. The surface can be band-limited by LOD, but
the adjacent LODs must share their transition samples and be checked against a physical error
tolerance. If that cannot be met with a transition band, refine only the affected boundary tiles.
The costs are extra boundary vertices/triangles and some CPU work to construct common transition
strips. Collision/support must consume the same interface representation where that surface is
collision-relevant. The owner would see caps and ledges hold one physical height as the camera moves
between LODs, instead of steps or holes appearing at the ring. Authoring remains in metres; internal
tile and transition details stay hidden.
This is not free geometry, but it is bounded to boundaries and LOD transition bands. L19 has already
shown why “add a thin density seal and sample it normally” is not a sufficient all-LOD guarantee.
## 5. Keep the per-strate resolution door open
Yes. A 25 cm per-strate default preserves the current Core sample spacing, and the common physical
field coordinate contract leaves room for later different sizes. Do not enable mixed resolutions
until the Round5 boundary contract is met:
1. Canonical physical-space field queries and explicit ownership at a shared boundary.
2. Deterministic transition meshes with common LOD ancestry on both resolutions.
3. Physical-space edit rasterization/replay that reaches both grids exactly once, with no holes or
double application.
4. A stable, canonically sorted strate-ID-to-size map included in plan/season identity and border
hashes.
5. Streaming and collision rules for tiles that touch or span two resolutions.
At today's one-size setting, the size map has one value (250,000 microns) for every strate. It adds
no mixed-resolution mesh, edit, or streaming cost. Tile width remains `32 × voxel size × 2^LOD`;
different future sizes change physical tile width and workload, but never change the 32³ internal
tile format.
## 6. Migration plan with “worlds don't move” checks
The checkpoints distinguish expected equality from a deliberately changed interface mesh. A plan
or schema identity can change even when field output remains equal; record both identities and mesh
hashes separately.
| Step | Work | Expected equality / check | Changes output? / Unreal PC? |
|---:|---|---|---|
| 0 | Freeze the L19 evidence as the baseline: W12, Clang with FP contraction off; retain the whole-view hashes, full-detail hashes, strict ceiling audit, captures, and FI/SW ring tables. | Baseline hashes recorded below; pin the protected SW LOD0–2 hashes too. Capture byte/pixel comparisons and ring samples must retain location, LOD, and skirt exclusion. | No. No new build needed for this design round. |
| 1 | Add a versioned resolved-metre layout representation and a read-only conversion/audit path. The audit reports, per strate, old input units, resolved old physical bounds, new metre bounds, voxel size, interfaces, and identity. Keep the old evaluator active. | Exact old-vs-new resolved positions at all authored top, bottom, height, route, island, and cap anchors. Old Core density/mesh/payload/topology hashes remain equal where the conversion is exactly representable; otherwise list the precise quantization delta before accepting a new baseline. | No. Core parser/audit can be Linux-only; adapter export needs Unreal BuildHost on the owner's PC. |
| 2 | Change owner-facing layout authoring and season serialization to metres. Convert each old slot using its **current resolved physical bounds**, not one global chunk multiplier. Represent any historical gap/overlap explicitly. Default each strate's voxel size to 25 cm. | Same physical top/bottom/height values and field anchors before/after. Run default W12 hashes and matched captures. The report must call out any interface whose two old generator bounds disagree instead of silently forcing them together. | Intended no. Touches `VoxelForgeCoreAdapter.cpp`, `VoxelStrateManager`, season manifest/composer and likely `VoxelWorld`; compile and actor validation require the owner's Unreal PC. |
| 3 | Add the common generator request/result contract and adapt `Heightfield2D` and `FloatingIslandFieldV1`; wrap the legacy `UVoxelGenerator` route without moving it yet. Move manager lookups out of evaluator calls in stages. | Per-strate exact density queries, proof classifications, full-detail hashes, whole-view hashes, W1/W8/W12 determinism, and generator-to-legacy route parity. Existing current output hashes remain equal for adapters that preserve their exact physical recipe. | No intended visual change. Unreal adapter/legacy wrappers need owner-PC UHT/build and actor validation; native Core pieces can be audited on Linux. |
| 4 | Resolve interface records once in the director; route new seal, cap, void, bedrock-gap, and passage behavior through shared composition. Keep old manifest versions on compatibility adapters. | Preserve density hashes where only a mesh closure was missing. Run the strict LOD0–8 ceiling interior/perimeter audit, edge pairing, same-LOD border hashes, matched captures, and field proofs. Any newly closed boundary is a named expected mesh/payload/topology delta. | Affected boundary mesh may change. Adapter serialization needs owner-PC validation; Core audit can run here. This step fixes thin seals/caps, not the L19 ground ledges. |
| 5 | Add the generic explicit-surface and LOD-transition contract. Feed SurfaceWorld ground-profile data into common transition bands; prototype on the measured FI/SW interface. | Produce before/after matched readable captures and full ring tables. Require zero no-hit interface samples and a chosen physical seam-error limit; retain L19 hash equality for unaffected tiles/LODs. For intended changes, list changed mesh/payload/topology hashes and keep density unchanged if the field itself is unchanged. | **This is the step that fixes the L19 ledges.** It changes protected SurfaceWorld LOD2 output, so implement only after the owner approves that specific output change. Unreal capture/collision review is on the owner's PC. |
| 6 | Enable a per-strate size map behind the already-resolved contract, initially set to 25 cm on all strates. Add one non-default diagnostic size case only after the default remains green. | At all-25-cm map, reproduce the approved default hashes and captures. Include sorted size-map identity in a negative control; boundary/transition hashes must change when one size changes. Re-run edit-across-boundary, collision, streaming, and W1/W8/W12 checks. | No default change; non-default diagnostic intentionally changes sampling. Touches Unreal reflected settings, snapshot adapter, and world identity; full compile/run requires the owner's PC. |
### L19 reference hashes
Representative W12 Clang `-ffp-contract=off`, density / mesh / payload / topology:
| Whole view | L19 hash |
|---|---|
| SurfaceWorld | `c10697a8f48380c7 / 4197fc1072f0ff58 / 7b3e616ec9459851 / c879e35592bf33e5` |
| FloatingIslands | `00bc3607a7839854 / 4baa66127c2b0892 / e11ef05e851a1517 / 1278bc4b1fffb869` |
Protected SurfaceWorld LOD0–2 hashes are in the L19 report and should be retained through steps
1–4 except for explicitly approved boundary geometry. The whole-view hash gate alone cannot prove
that a ring improved; step 5 needs the strict ring table and readable captures as well.
### Owner decisions this design needs
1. **Preservation target:** confirm that migration snapshots each current generator's resolved
physical bounds (including any current overlap or gap) before later tuning them into a single
authored metre layout. If instead the initial migration should force currently different bounds
to meet, that is a deliberate world change and needs its own baseline/capture review.
2. **Ledge output:** approve the specific SurfaceWorld LOD2/transition change before step 5
implementation, as required by the existing protected-output rule.