diff --git a/Standalone/Research/WorldAssemblerM3/Linux20/SOL_REVIEW.md b/Standalone/Research/WorldAssemblerM3/Linux20/SOL_REVIEW.md new file mode 100644 index 0000000..3bfcfd7 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux20/SOL_REVIEW.md @@ -0,0 +1,233 @@ +# Sol 6.1 (medium) read-only review of the L20 design — 2026-10-20 + +Requested by the owner. Prompt: `Saved/Linux/claude/sol-l20-review.md` (copied below the answer). Session `01a1582c-547a-7701-9d9e-35239b7f0a26`, 68,458 tokens, sandbox read-only. + +**The direction is right. Preserve today’s world during conversion, but treat inconsistent bounds as compatibility data, not valid new layout. Allow the SurfaceWorld LOD2 boundary fix, with a precisely defined affected region and unchanged density.** + +L20 needs a stronger bedrock model and an earlier ownership contract. Adding floor bedrock everywhere is also a deliberate geometry change: current FloatingIslands v3 explicitly omits its lower seal. + +I only read files; I did not build, run, or modify anything. + +**1. The two decisions** + +**Decision 1: preserve first, repair separately.** L17 demonstrates why: unifying the chunk scale removed the approved SurfaceWorld ground and moved the world ([Linux17/REPORT.md:168](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux17/REPORT.md:168)). + +The mismatch is real. SurfaceWorld uses slot chunks directly as 32 Core voxels; FloatingIslands applies the owner/Core ratio ([VoxelForgeCoreAdapter.cpp:290](/home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:290), [VoxelForgeCoreAdapter.cpp:464](/home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:464)). + +However, preserve **effective behavior**, not just converted endpoints. Dispatch itself uses different conversions: SurfaceWorld divides Z by 32, while FloatingIslands uses the owner/Core scale ([ShapeWorldInternal.h:2130](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:2130), [ShapeWorldInternal.h:2158](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:2158)). An apparent interval between bounds therefore does not prove that interval currently generates air. + +Keep historical overlaps and ambiguities in a versioned compatibility snapshot. **Reject overlaps in newly authored layouts.** Otherwise preservation becomes permanent acceptance of the bug. + +**Decision 2: approve the change in principle.** L19 measured actual lower-ground extraction differences, not ceiling triangles: up to 1.50 m and 7.73 m ([Linux19/REPORT.md:9](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux19/REPORT.md:9)). An explicit ceiling cannot fix these. + +Define the affected tiles from the observed surface and transition support, including halos—not merely distance from a nominal strate plane. Preserve exact queries and unaffected near-player geometry. Validate against the same physical surface so the audit cannot “improve” by pairing different surfaces or hiding terrain. + +Metre authoring and default 25 cm voxels are sound. Fixed 32³ tiles mean physical tile width still follows voxel size; if Jahni wants fixed physical streaming regions, introduce those separately from internal tiles. + +**2. A concrete strate structure** + +Use one immutable, versioned director output. Distinguish a strate’s **generator interior** from the bedrock separating interiors. This makes thickness and ownership unambiguous. + +```text +ResolvedWorld + schemaVersion, evaluatorVersion, seed, worldIdentity + physicalUnit = fixed integer unit independent of voxel size + strates[] // ordered downward + verticalSegments[] // exact partition of declared world extent + interfaces[] + passages[] + +Strate + stableId // persisted; independent of array position + order + bottomM, topM // generator interior: [bottomM, topM) + voxelSizeM = 0.25 + latticeOriginM + generatorKind + recipeId, recipeVersion, resolvedRecipe, seedKey + floorBandId, ceilingBandId + interfaceAboveId, interfaceBelowId + +VerticalSegment + stableId, bottomM, topM + kind = StrateInterior | Bedrock | VoidGap + ownerId + +BedrockBand + stableId, bottomM, topM + thicknessM = topM - bottomM + volumeMaterialId + upperFaceMaterialId, lowerFaceMaterialId + digPolicy = Diggable | Protected | Restricted + allowedPassageIds[] + surfaceDescriptorIds[] + +Interface + stableId, upperStrateId, lowerStrateId + orderedSegmentIds[] // bedrock, optional void, further bedrock + passagePlacementRecipe + resolvedPassageIds[] + +Passage + stableId, interfaceId + physical tunnel shape, aperture boundaries + upper/lower endpoints, landing/support geometry + crossedBandIds[], clearance, carvePermission +``` + +Author in metres; serialize canonical fixed physical units with explicit rounding. The resolved fields above are produced once, not independently editable copies. + +For a shared slab, the upper strate’s floor and lower strate’s ceiling reference **the same band**. Its thickness and digging policy cannot disagree between sides. Separate skins with a void between them require three explicit segments. + +I recommend ordinary inter-strate bedrock remain diggable, preserving the established player-dug descent behavior ([ARCHITECTURE.md:472](/home/jahni/VoxelM/Plugins/VoxelForge/ARCHITECTURE.md:472)). Protection should be an explicit band policy. + +The invariants are: + +- Unique stable IDs; explicit order; finite bounds; positive interior height and bedrock thickness. +- Every physical height within the declared stack belongs to exactly one segment. No overlaps or implicit gaps. +- Every strate has floor and ceiling bedrock, including terminal strates. +- Interiors remain closed except through registered passages or authorized player-created apertures. +- A void gap lies between closed skins. A freely open connection requires an explicit aperture, potentially covering the whole interface. +- Passages cross every intervening band and provide usable entrances, exits, and support. +- All generators, proofs, streaming, meshing, collision, and material queries consume this snapshot. None reconstruct boundaries from chunk indices. + +Keep legacy recipe seed keys frozen during migration. Switching randomness from strate index to stable ID must be versioned separately to avoid changing the world. + +**3. Bedrock should be both volume and explicit geometry** + +Use an authoritative solid volume for density, digging, collision queries, and conservative proofs, plus explicit boundary surfaces for reliable extraction. Both representations derive from the same band and aperture descriptors. + +Density alone cannot guarantee a thin band survives coarse sampling. Conversely, a visual plane alone supplies no solid interior and can disagree with collision or digging. + +Current code illustrates the mismatch: the upper seal fills inward over its thickness, while fallback ceiling vertices are placed at `Bounds.TopZ` ([VoxelDensityPrimitives.h:44](/home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelDensityPrimitives.h:44), [FarShellsInternal.h:1238](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/FarShellsInternal.h:1238)). The new contract must distinguish the band’s outer boundary from its room-facing surface. + +For a ceiling above an interior, its lower face is at `topM`; for a floor below an interior, its upper face is at `bottomM`. Thickness extends away from the interior. + +The mesher should own each exposed face once, suppress overlapping ordinary extraction, and use shared edge anchors across LODs. Passage mouths need explicit clipping and wall geometry; corner sampling alone can miss a small aperture. + +Authorized edits must modify both density and surface extraction. Protected bands require explicit edit masking. Generated passages carve after bedrock composition, consistent with today’s passage ordering ([VoxelDensityPrimitives.h:86](/home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelDensityPrimitives.h:86)). + +Collision uses the same geometry semantics at a gameplay resolution independent of camera LOD. Peers reproduce bands and generated passages from the versioned plan; only player edits need synchronization. + +Cost stays local: cheap band queries and flat faces generally, extra refinement around openings and edited areas. + +**4. What I would change in L20** + +My top three risks are: + +1. **Migrating bounds without migrating dispatch.** Today’s “resolved” bounds still consult the manager and branch by generator ([ShapeWorldInternal.h:67](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:67)). Snapshot ownership, fallback behavior, and recipe anchors together. +2. **Changing gameplay under structural cleanup.** FloatingIslands v3 applies only an upper seal ([ShapeWorldInternal.h:2192](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:2192)). Restoring a floor changes visibility and descent. Require a new layout version; do not silently reintroduce the removed floor. +3. **Maintaining conflicting density, mesh, and collision boundaries.** Explicit surfaces must be authoritative constraints derived from bands, rather than another repair overlay. + +Reorder the migration to: compatibility snapshot → canonical ownership and bedrock schema → minimal shared boundary composition → targeted LOD transition prototype → metre authoring and generator adapters. Keep the broad generator/helper refactor incremental. Mixed resolutions remain last. + +**5. Smallest first implementation** + +Implement a **versioned resolved-layout snapshot and validator**, populated by the existing director/adapter. Record actual physical bounds, recipe/cap anchors, voxel sizes, current floor/ceiling behavior, and dispatch provenance. Flag incompatible intervals explicitly. Leave evaluation unchanged. + +Its acceptance test should require: + +- Exact preservation of existing resolved anchors and recipe values, including routes and cap profiles. +- Boundary probes immediately below, at, and above every endpoint, comparing actual old dispatch with the snapshot’s recorded behavior. +- Deterministic identity across worker counts and serialization round trips. +- Rejection of overlapping or uncovered new layouts. +- Existing SurfaceWorld density and geometry hashes unchanged; L19 ceiling coverage unchanged. + +This delivers inspectable strate structure first. Enforcing new floors and repairing ledges then become separate, measurable world changes. +--- + +## Prompt + +# VoxelForge — design review (Sol, read-only): strate structure, bedrock and the L20 decisions + +You are reviewing a design for VoxelForge, a voxel terrain plugin for a multiplayer Unreal Engine +game, with its generation done in a C++ Core library. The game is underground: the world is a +vertical stack of **strates** (layers). Each strate has its own generator type: +- SurfaceWorld: an enclosed surface-like heightfield world; +- FloatingIslands; +- caves, and future types. + +Players travel between strates through passages. Every machine generates the same terrain from a +seed. Only player edits cross the network. + +**This is a read-only review.** Read files, but don't build, run, edit or create anything. The +owner pays for this review, so be efficient: read what you need, and keep the answer focused and +concrete. + +## Read first + +- `/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/DESIGN_STRATA_UNITS_AND_LAYERS.md`: the design + under review (round L20). +- `/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux20/REPORT.md` +- For the bugs that motivated it: `.../Linux17/REPORT.md`, `.../Linux18/REPORT.md` and + `.../Linux19/REPORT.md`, in the same folder. Each has an "Orchestrator review" section at the end. +- Code, as needed: + - `Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp` (plan building: SurfaceWorld vs + FloatingIslands chunk conversion); + - `Source/VoxelForge/Private/VoxelStrateManager.cpp` and `Source/VoxelForge/Public/VoxelStrateTypes.h` + (strate slots and params); + - `Standalone/Core/src/ShapeWorldInternal.h` (`FResolvedStratumBounds`, `GetResolvedStratumBounds`); + - `Standalone/Core/src/FarShellsInternal.h` (`AppendStratumBoundaryCeilings`); + - `Source/VoxelForge/Public/VoxelDensityPrimitives.h` (boundary seals); + - `CLAUDE.md`, and `ARCHITECTURE.md` (§8) for the hard rules. + +## The owner's direction + +The owner is Jahni. Quotes: +- "Everything should use a parameter like on the strate, saying which voxel size it is, by default + 25 for everyone, same for island." +- "Our system should be in different categories: the director/orchestrator, the generators (all + using the same kind of format, helper functions … from a shared library like noise functions) and + the mesher; the generators are dictated by our current strate parameters." +- "The voxel size shouldn't dictate the size of a chunk … wouldn't it be better to have like Unreal + unit distance, and have x voxels fill it?" +- "Any strate should have a ceiling, since we're underground." +- "The ceiling height is decided by the strate parameter, it's not something unique to sky island." +- Now: **"we need proper strate structure, knowing where each starts etc."**, including the strate + **bedrocks (ceiling and floor)**. + +## What I (the orchestrator) recommended, which he wants judged + +1. **Layout is authored in metres;** each strate has a voxel size (default 25 cm); internal tiles + stay 32³ voxels. Units cost nothing at run time, while the voxel count does. +2. **Decision 1 (preservation):** when converting today's chunk-based strate parameters to metres, + keep every strate exactly where it currently is in the generated world, including any gap or + overlap that the current 8 m (SurfaceWorld) vs 4 m (FloatingIslands) per-chunk mismatch creates. + Report those gaps and overlaps, then tune in metres. The alternative is to force them to meet + during the migration. +3. **Decision 2:** allow step 5 of the migration (an explicit, LOD-stable interface surface) to + change SurfaceWorld LOD2 output near strate boundaries, to fix the owner's "ledges" (cross-LOD + ring steps of up to 1.5 m and 7.7 m at the FloatingIslands/SurfaceWorld interface). Near-player + terrain away from boundaries must stay identical. + +## Questions (answer each) + +1. **Are the two decisions and the direction right?** Say where you'd decide differently, and why. + Is preserving today's possibly-inconsistent bounds the right first step, or does it entrench a + bug? Is there a better migration order? +2. **Propose a proper strate structure.** A concrete data model the director owns. For each strate: + - its stable ID and order; + - top and bottom in metres; + - **floor bedrock and ceiling bedrock:** thickness in metres, material, whether players can dig + through, and how passages pierce them; + - its voxel size; + - its generator and recipe; + - its interfaces to the strate above and below: solid bedrock band, open void, passage + placement. + + Define the invariants: no overlaps; every metre owned by exactly one strate or one explicit + bedrock/gap band; ceiling and floor always closed, except at passages; contiguous or explicit + gaps. Show how "where each strate starts and ends" becomes a single source of truth that every + generator and the mesher read, never re-derive. +3. **Bedrock as geometry.** Should a ceiling or floor be a density band (a seal), an explicit + surface the mesher knows about, or both? Weigh LOD stability (the ledge problem: thin seals + extract at different heights per LOD), collision, player digging, multiplayer determinism, and + cost. Give a recommendation. +4. **What in the L20 design would you change, cut, or reorder?** Name the top 3 risks. +5. **The smallest first implementation step** that delivers the strate structure without moving the + approved SurfaceWorld world, and its acceptance test. + +## Answer format + +Plain English. The owner reads it, so lead with your verdicts in a few lines, then the details. +Around 1,500 words at most, plus the data-model sketch. Cite file:line where you rely on code.