refactor(core): boundary policy as resolved capabilities, not generator-name tests (L42, step 6); R9

ResolvedLayoutSnapshotV3::finalize maps each strate's generator and interface once into capability
records (FI gradient air-gap, surface/FI landing support, passage-anchor columns, SW-to-TN floor);
ApplyResolvedStrateBoundaryBand and passage composition read those instead of generator kinds. Derived
records stay out of canonical JSON, so layout identity is unchanged. Owner hashes identical to L41;
fast/medium/full PASS on clean Clang and GCC builds; cost within noise.
Research R9 (read-only): player-visible roadmap refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-23 20:22:49 +02:00
1 parent 1abee91721
commit 2566f53734
8 files changed
+204 -15

No files matched your search

+21
View File
@@ -2215,6 +2215,27 @@ per-sample dispatch path; this migration adds no manager lookup to it. The Unrea
cannot be compiled in this Linux workspace, so their small source changes still need the Windows
Unreal build before integration.
### 8.52 Resolved boundary and landing capabilities — World Assembler M3 L42
`ResolvedLayoutSnapshotV3::finalize` materializes runtime capability records from the immutable
strate/interface fields before sampling begins. The upper interface records whether its Gradient FI
bedrock air gap remains open and whether a SurfaceWorld-to-TunnelNetwork passage gets the special
landing support profile. Per-strate passage records carry the existing SurfaceWorld landing profile,
FloatingIslands route-support behavior, and passage-anchor column center policy. Shared boundary and
passage composition reads these records; it no longer compares generator-kind strings.
The records are deterministic derivatives of `generator_kind`, `transition_mode`, and the resolved
adjacent strate, and are omitted from canonical JSON. Those source fields remain in the hashed layout,
so owner layout IDs and density hashes retain their L41 identity. The upper strate still controls
Hard/Gradient/Interleaved evaluation; each strate still composes ceiling, content, then breakable
bedrock. L29 transition samples and the passage-mouth fade arithmetic are unchanged.
`BindResolvedStratumFields` still tests the resolved generator kind once to bind the concrete
SurfaceWorld, FloatingIslands, or legacy evaluator. Passage planning in `ResolvedLayoutInternal.h`
also retains generator-specific anchor and default-mouth placement rules; those are outside the
shared composition boundary policy. No Unreal source changed. See the L42 report for hashes, tier
results and paired cost measurements.
## 9. Multiplayer model (listen-server first, dedicated-friendly)
> **Status: transport is DESIGN ONLY — nothing is networked in-tree yet** (no `Replicated`/`HasAuthority`/RPCs; a
+11
View File
@@ -1284,6 +1284,17 @@ ARCHITECTURE §8.47 and
Hash parity is unchanged from L37/L39; see ARCHITECTURE §8.50 and
[`Standalone/Research/WorldAssemblerM3/Linux40/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux40/REPORT.md).
### 3.34 Resolved boundary and landing capabilities — World Assembler M3 L42
| Symbol | Canonical file | Role |
|---|---|---|
| `ResolvedLayoutStratePassageCapabilitiesV1`, `ResolvedLayoutInterfaceCapabilitiesV1` | `Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h` | Runtime-only resolved records for surface/island landing, passage-column anchoring, the FI Gradient air gap, and SW-to-TunnelNetwork support. They are derived during layout finalization from fields already included in the canonical layout identity. |
| `ResolvedLayoutSnapshotV3::finalize` | `Standalone/Core/src/ResolvedLayoutInternal.h` | Resolves those capabilities once before sampling; canonical JSON and stable layout IDs stay unchanged. |
| `FStandaloneShapeWorld::ApplyResolvedStrateBoundaryBand`, `ApplyResolvedStratePassageCarves`, `BuildPassageVoidCrossingPlan`, `PassageBridgeSignedDistance` | `Standalone/Core/src/ShapeWorldInternal.h` | Consume resolved capability records. Generator-kind selection remains only in `BindResolvedStratumFields`, where it binds the concrete evaluator once. |
Owner hashes match L41; see ARCHITECTURE §8.52 and
[`Standalone/Research/WorldAssemblerM3/Linux42/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux42/REPORT.md).
## 4. The density pipeline (most-edited hot path)
### 4.1 `GetDensityWithParams` (TunnelNetwork) — VoxelGenerator.cpp:3749
@@ -729,6 +729,22 @@ namespace VoxelForgeCore
std::int64_t solidDensityQ16 = 1ll << 16;
};
// Runtime policy resolved once from the director's immutable strate/interface
// description. These derived capabilities are deliberately omitted from canonical
// JSON: their source fields are already hashed and the records preserve that identity.
struct ResolvedLayoutStratePassageCapabilitiesV1
{
bool hasSurfaceLanding = false;
bool hasFloatingIslandLanding = false;
bool usePassageAnchorForColumns = false;
};
struct ResolvedLayoutInterfaceCapabilitiesV1
{
bool preserveUpperBedrockAirGap = false;
bool surfaceToTunnelLandingSupport = false;
};
struct ResolvedLayoutStratumV2
{
std::string stableId;
@@ -758,6 +774,8 @@ namespace VoxelForgeCore
std::int64_t managerChunkWidthMicrometres = 0;
std::int64_t dispatchChunkWidthMicrometres = 0;
std::vector<ResolvedLayoutAnchorV2> anchors;
ResolvedLayoutStratePassageCapabilitiesV1 passageCapabilities;
ResolvedLayoutInterfaceCapabilitiesV1 lowerInterfaceCapabilities;
};
/** Per-column resolved bands for one adjacent bedrock/ceiling interface.
@@ -409,6 +409,26 @@ bool ResolvedLayoutSnapshotV3::finalize(std::string& error)
if(x.bedrock.kind.empty())x.bedrock.kind="bedrock";
if(x.interiorTopMicrometres<=x.interiorBottomMicrometres||x.voxelSizeMicrometres==0)
{error="resolved layout contains an invalid interior interval or voxel size";return false;}
// Materialize generator-specific composition policy at layout resolution. The
// sampling/composition path consumes these capabilities without examining names.
x.passageCapabilities={};
x.lowerInterfaceCapabilities={};
if(x.generatorKind=="SurfaceWorld")
x.passageCapabilities.hasSurfaceLanding=true;
else if(x.generatorKind=="FloatingIslands")
{
x.passageCapabilities.hasFloatingIslandLanding=true;
x.passageCapabilities.usePassageAnchorForColumns=true;
}
if(i+1<strates.size())
{
const auto& lower=strates[i+1];
x.lowerInterfaceCapabilities.preserveUpperBedrockAirGap=
x.generatorKind=="FloatingIslands"&&x.transitionMode=="Gradient";
x.lowerInterfaceCapabilities.surfaceToTunnelLandingSupport=
x.generatorKind=="SurfaceWorld"&&lower.generatorKind=="TunnelNetwork";
}
}
const std::int64_t playerCenterAboveFloorQ=static_cast<std::int64_t>(std::llround(
1.13*WorldAssemblySubvoxelsPerVoxel*1000000.0/coreVoxelSizeMicrometres));
+9 -11
View File
@@ -807,8 +807,7 @@ public:
solidTop-zMicrometres));
const std::int64_t seam=transitionUpper->bedrock.bottomMicrometres;
const bool floatingIslandAirGap=
transitionUpper->generatorKind=="FloatingIslands"
&&transitionUpper->transitionMode=="Gradient"
transitionUpper->lowerInterfaceCapabilities.preserveUpperBedrockAirGap
&&bands.upperBedrockTopMicrometres<seam
&&zMicrometres>=bands.upperBedrockTopMicrometres
&&zMicrometres<seam;
@@ -876,8 +875,8 @@ public:
:-static_cast<double>(std::min(zMicrometres-solidBottom,
solidTop-zMicrometres));
const std::int64_t seam=upper->bedrock.bottomMicrometres;
const bool floatingIslandAirGap=upper->generatorKind=="FloatingIslands"
&&upper->transitionMode=="Gradient"
const bool floatingIslandAirGap=
upper->lowerInterfaceCapabilities.preserveUpperBedrockAirGap
&&resolvedBands.upperBedrockTopMicrometres<seam
&&zMicrometres>=resolvedBands.upperBedrockTopMicrometres
&&zMicrometres<seam;
@@ -1015,10 +1014,9 @@ public:
const auto* supportUpper=supportStratum(passage.upperStrateIndex);
const auto* supportLower=supportStratum(passage.lowerStrateIndex);
const bool floatingIslandPassage=supportUpper
&&supportUpper->generatorKind=="FloatingIslands";
&&supportUpper->passageCapabilities.hasFloatingIslandLanding;
const bool surfaceToTunnelSupport=supportUpper&&supportLower
&&supportUpper->generatorKind=="SurfaceWorld"
&&supportLower->generatorKind=="TunnelNetwork";
&&supportUpper->lowerInterfaceCapabilities.surfaceToTunnelLandingSupport;
const double firstFloorQ=passage.controlPoints.front().positionSubvoxels[2]
-passage.controlPoints.front().radiusSubvoxels+playerCenterAboveFloorQ;
const double lastFloorQ=passage.controlPoints.back().positionSubvoxels[2]
@@ -3466,7 +3464,7 @@ private:
ResolvedLayout->strates.end(),[strate](const auto& value)
{return value.strateIndex==strate;});
surfaceWorldUpper=upper!=ResolvedLayout->strates.end()
&&upper->generatorKind=="SurfaceWorld";
&&upper->passageCapabilities.hasSurfaceLanding;
}
const std::size_t shortSpanPadding=!crossing.needsColumn
&&surfaceWorldUpper&&!flags.empty()?2:0;
@@ -3737,7 +3735,7 @@ private:
ResolvedLayout->strates.end(),[&passage](const auto& value)
{return value.strateIndex==passage.upperStrateIndex;});
const bool surfaceWorldUpper=upperStratum!=ResolvedLayout->strates.end()
&&upperStratum->generatorKind=="SurfaceWorld";
&&upperStratum->passageCapabilities.hasSurfaceLanding;
const double ax=static_cast<double>(a.positionSubvoxels[0]);
const double ay=static_cast<double>(a.positionSubvoxels[1]);
const double dx=static_cast<double>(b.positionSubvoxels[0])-ax;
@@ -3949,7 +3947,7 @@ private:
ResolvedLayout->strates.end(),[&passage](const auto& value)
{return value.strateIndex==passage.upperStrateIndex;});
const bool surfaceWorldUpper=upperStratum!=ResolvedLayout->strates.end()
&&upperStratum->generatorKind=="SurfaceWorld";
&&upperStratum->passageCapabilities.hasSurfaceLanding;
if(passage.controlPoints.size()<2)continue;
std::vector<FPathSample> samples;
samples.reserve(passage.controlPoints.size()*2);
@@ -4029,7 +4027,7 @@ private:
?static_cast<std::int64_t>(std::llround(static_cast<double>(sumY)/centerSamples)):0;
for(const auto& stratum:ResolvedLayout->strates)
if(stratum.strateIndex==passage.upperStrateIndex
&&stratum.generatorKind=="FloatingIslands")
&&stratum.passageCapabilities.usePassageAnchorForColumns)
for(const auto& anchor:stratum.anchors)
if(anchor.kind=="passage_anchor"&&anchor.values.size()>=2)
{
@@ -0,0 +1,56 @@
# Linux 42 — resolved boundary capabilities
Migration step 6 is a Core-only pure refactor. No Unreal source changed.
## Policy records
`ResolvedLayoutSnapshotV3::finalize` resolves the existing generator and interface fields once into
runtime capabilities. `ApplyResolvedStrateBoundaryBand` reads
`lowerInterfaceCapabilities.preserveUpperBedrockAirGap` for the FI Gradient gap. Passage composition
reads `passageCapabilities.hasSurfaceLanding` for the SW landing/bridge profile and crossing extent,
`hasFloatingIslandLanding` for the FI route support, and `usePassageAnchorForColumns` for its fixed
passage-column center. `surfaceToTunnelLandingSupport` records the SW-to-TunnelNetwork floor profile.
The derived records are omitted from canonical JSON, so the resolved layout identity is unchanged.
`BindResolvedStratumFields` still checks `generatorKind` once to bind SurfaceWorld, FloatingIslands,
or legacy evaluation. `finalize` maps that resolved kind to capabilities once. `PlanResolvedLayoutPassagesV1`
still names SurfaceWorld/FloatingIslands for existing default mouth and anchor placement; that passage
planning policy remains outside this boundary-composition step.
Ceiling → content → breakable bedrock order remains unchanged for every strate. The upper strate still
controls Hard/Gradient/Interleaved. L29 transition sample arithmetic and the passage-mouth fade are
unchanged.
## Hashes and cost
Source stamp: `a3a65e58a670399d9458aa2a9c99eddd7b541671f919a293f5b4086878e9eb78`.
FI layout ID `b7a7d9ecc48d8f26`; SW layout ID `8a52e84c26ed92d2`. All four 12-record FI/SW worker-1
and worker-12 hash signatures match L41 exactly: FI
`9820f4f38b189b3f7263810e7b3ff62aa502b21f476ffcfdbc7761a65cb07d58`; SW
`a1e9268a4bbcc77d2a1ac54095df6851a70bab65c43ae50b332ed75132617834`. Worker-1 and worker-12 match
each other for both recipes.
Full-tier five-pair whole-view-ready cost versus `HEAD` `1abee917215cd6f971e39dd3158cecf4c9992fbe`:
FI median 18.164 s → 18.189 s (**+0.14%**); SW 1.888 s → 1.877 s (**−0.58%**). No measured cost
regression.
## Verification
| Tier | Result |
|---|---|
| Fast | PASS, 163.2 s; owner hashes, worker parity, and ring gates pass. |
| Medium | PASS, 469.9 s; transition modes, hole controls, route proofs, owner passage matrix, ring and capture gates pass. |
| Full | PASS, 1,637.0 s; 107 runs and 539 checks, including Clang/GCC, 30-cell determinism and paired cost. |
Full used clean Clang 19 and GCC 14 builds from `Saved/Linux/l42/final-clean-build`, `-j12`, FP
contraction off. The final source stamp was embedded in both binaries. All processes used CPUs 0–11,
the 6 GiB address-space limit, and a 30-minute process timeout.
The first fast invocation stopped before running checks because the L42 binary had not yet been built;
fast passed after the build. The mislabelled-owner and all-black capture negative controls are expected
rejections and passed their verifier checks. No tier had an unexpected failed run.
## Orchestrator review (Claude)
Accepted. The current tree stamp equals both L42 binaries (`a3a65e58…`), so the fast/medium/full evidence is from this exact source. Owner hashes are identical to L41. Passage planning (`PlanResolvedLayoutPassagesV1`) still names generators; that is a later step.
@@ -0,0 +1,64 @@
I couldn’t write to the requested path because the standing instruction says read-only and “Don’t touch the tree.” Here is the report text for `Standalone/Research/WorldAssemblerM3/Research9/REPORT.md`. No scripts, builds, tests, probes, or binaries were run.
# Research R9 — What should the player see next?
## Done, partly done, obsolete
| Area | Status | Readout |
|---|---|---|
| Fable performance work and preview tools | **Done**, with one caveat | Instrumentation, most Tier 1–2 optimizations, preview, and determinism tools are marked complete. Tile classification was later turned off on the game path; don’t assume every “done” item is still active there. [fable-idea.md](</home/jahni/VoxelM/Plugins/VoxelForge/fable-idea.md:35>) |
| Biomes, materials, decorations | **Done in the legacy Unreal path; partly carried into Core** | F5/F6/F16 are marked done. The Core integration documents still identify gaps in water presentation, biome material palette, decoration, and atmosphere. [fable-idea.md](</home/jahni/VoxelM/Plugins/VoxelForge/fable-idea.md:118>) · [ARCHITECTURE.md §8.19](</home/jahni/VoxelM/Plugins/VoxelForge/ARCHITECTURE.md:1176>) |
| POIs, water, cave materials, terrain ops | **Partly done** | F7 has deterministic landmark placement, passage-mouth anchors, conditions, and companions; SDF carve/fill stamps remain open. The legacy water plane is strata-wide and visual; swimming is open, and Core does not yet present native water. F17’s cap/ground split exists, but cave material identity is not a general semantic channel. F20’s surface phases 1–2 are built; spikes/holes remain open. [fable-idea.md](</home/jahni/VoxelM/Plugins/VoxelForge/fable-idea.md:127>) · [ARCHITECTURE.md §8.5](</home/jahni/VoxelM/Plugins/VoxelForge/ARCHITECTURE.md:267>) |
| Save/load, ore, audio, HUD, weather, carve UX, transport gameplay, ambient life | **Open or parked** | The Core has edit and layout foundations, but these player-facing systems are not delivered by them. [fable-idea.md](</home/jahni/VoxelM/Plugins/VoxelForge/fable-idea.md:116>) · [fable-idea.md §Experience polish](</home/jahni/VoxelM/Plugins/VoxelForge/fable-idea.md:244>) |
| F18 far-field sheets | **Obsolete** | The owner removed the sheet path in the September cleanup. F20’s proposed `SurfaceOps[]` data shape was also replaced by fields on `FSurfaceGenerationParams`. [fable-idea.md](</home/jahni/VoxelM/Plugins/VoxelForge/fable-idea.md:138>) |
| Strata, passages, transitions | **Partly done** | The Core resolves physical strata bounds, boundary bands, inter-strate passages, walkable landings, and Hard/Gradient/Interleaved boundary transitions. These do not make every composed season satisfy the entrance-to-exit law. The transition blends boundary bands; it does not blend unrelated generator fields. [ARCHITECTURE.md §8.41](</home/jahni/VoxelM/Plugins/VoxelForge/ARCHITECTURE.md:1928>) · [ARCHITECTURE.md §8.46](</home/jahni/VoxelM/Plugins/VoxelForge/ARCHITECTURE.md:2056>) |
| Lateral within-strate regions | **Implemented, gated** | The region blend exists, but its passage-law audit is still 4/16; region-zero controls are also 4/16. It is not ready to promote as the route to tunnel/chamber mixing. [ARCHITECTURE.md §8.1a](</home/jahni/VoxelM/Plugins/VoxelForge/ARCHITECTURE.md:91>) |
| Composer and GDD game | **Partly done / mostly design** | Candidate rolling, measurement, selection, preview, and promotion exist. The season artifact does not yet carry generated passages or the full visual/content payload; tagged draws for materials, creatures, and audio remain open. City, economy, combat, death, housing, and multiplayer are game design, not delivered VoxelForge features. [COMPOSER-NOTES.md §4](</home/jahni/VoxelM/Plugins/VoxelForge/COMPOSER-NOTES.md:1125>) · [COMPOSER-NOTES.md §7](</home/jahni/VoxelM/Plugins/VoxelForge/COMPOSER-NOTES.md:1407>) · [GDD.md](</home/jahni/VoxelM/Plugins/VoxelForge/GDD.md:18>) |
The GDD’s geometry contract—bounded strata, passages, and transitions—has a substantial implementation base. The long-term loop, guaranteed resource progression, boss content, named discoveries, seasonal play, and the opening remain design goals, not a playable game loop. The first strate is explicitly meant to be hand-built and story-significant. [GDD.md §§6–8](</home/jahni/VoxelM/Plugins/VoxelForge/GDD.md:104>) · [GDD.md §§9–15](</home/jahni/VoxelM/Plugins/VoxelForge/GDD.md:197>)
## Ranked next player-visible features
Ranked for payoff against delivery cost and risk. Costs and risks are qualitative.
1. **Landmarks and set-pieces — very high payoff; medium cost/risk.** **Core:** add deterministic bounded SDF stamp records for carved or filled structures, with stable IDs and passage-safe placement. **Unreal:** connect those records to the existing landmark streamer and mesh/actor paths. **Owner:** author a few shrine, ruin, crystal-garden, and boss-entry kits with tags and loot hooks. Placement exists; stamps do not. [fable-idea.md F7](</home/jahni/VoxelM/Plugins/VoxelForge/fable-idea.md:127>)
2. **Cave lighting identity — high payoff; small-to-medium cost, low-to-medium risk.** **Core:** no field change for lights attached to existing ceiling or landmark placements; a real skylight opening needs a bounded geometry feature. **Unreal:** add cave atmosphere profiles, emissive HISM clusters, and a few local lights or artificial light wells. **Owner:** author gem-star, bioluminescent, and shaft-light kits plus color/exposure profiles. The existing atmosphere manager is strate/biome-oriented, but this needs an enclosed-cave profile.
3. **Depth, place names, and an explored-chunks map — high payoff; small cost/risk.** **Core:** expose resolved strate IDs, depth, passage endpoints, and stable landmark IDs; no density change. **Unreal:** UMG depth/name cards, route cues, and a lightweight explored-area map. **Owner:** provide name pools, map symbols, and discovery rules. This also improves orientation before a full quest system exists. [fable-idea.md F11](</home/jahni/VoxelM/Plugins/VoxelForge/fable-idea.md:247>) · [GDD.md §14](</home/jahni/VoxelM/Plugins/VoxelForge/GDD.md:383>)
4. **Ore veins and dig rewards — very high payoff; medium cost/risk.** **Core:** add a deterministic resource/material channel or bounded vein records, separate from rock density. **Unreal:** show vein identity through mesh attributes/materials and award resources through the carve path. **Owner:** author ore looks, rarity/yield, depth eligibility, and guarantees for recipe-critical materials. This directly supports the GDD’s gather-and-return loop. [fable-idea.md F8](</home/jahni/VoxelM/Plugins/VoxelForge/fable-idea.md:132>) · [GDD.md §9](</home/jahni/VoxelM/Plugins/VoxelForge/GDD.md:197>)
5. **Mixed-scale caves: tunnels opening into chambers — very high payoff; large cost/high risk.** **Core:** build a composite cavern-network recipe whose room graph and bounds are resolved before sampling; keep the strata’s entrance/exit and boundary posts shared. Prefer one evaluator with internal room/tunnel structure over promoting the currently gated lateral blend. **Unreal:** expose the recipe and a walkable preview, then support its materials, lighting, and collision. **Owner:** author chamber/tunnel motifs, size ranges, and rules for wide arenas versus narrow connectors.
6. **Local streams and pools — high payoff; large cost/high risk.** **Core:** add a bounded watercourse path, pool surface, and liquid-query output. Existing Core fields include water channels and a per-stratum water surface, but that is not a cave stream or pool. **Unreal:** render water surfaces, add swim/collision volumes, underwater post-process, sound, and effects. **Owner:** author water materials, flow/pool profiles, sound, and themed edge content. Start with deterministic static flow and local pools; leave fluid simulation for later. [VoxelForgeCore.h](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h:375>) · [ARCHITECTURE.md §8.5](</home/jahni/VoxelM/Plugins/VoxelForge/ARCHITECTURE.md:420>)
7. **Save/load for edits and homes — very high payoff; large cost/high risk.** **Core:** persist edits against the resolved world identity and generation version. **Unreal:** serialize diffs and house snapshots, with the game’s authority deciding what survives a season. **Owner:** settle the persistence boundary: GDD says housing survives wipes, while underground building is still open. [fable-idea.md F4](</home/jahni/VoxelM/Plugins/VoxelForge/fable-idea.md:116>) · [GDD.md §§11, 13](</home/jahni/VoxelM/Plugins/VoxelForge/GDD.md:285>)
8. **Full tagged-content composer — strategic payoff is very high; extra-large cost/very high risk.** **Core/build box:** expand from density recipes to reviewed passage, feature, and content records; preserve deterministic IDs and selection evidence. **Unreal:** author tags, import reviewed manifests, and spawn the selected content at runtime. **Owner:** tag raw meshes, materials, sounds, creatures, and structures with overlapping themes and veto composed seasons. This should follow a small authored content library and a proven mixed-cave recipe; otherwise it composes an empty world. [COMPOSER-NOTES.md §1](</home/jahni/VoxelM/Plugins/VoxelForge/COMPOSER-NOTES.md:18>) · [COMPOSER-NOTES.md §7](</home/jahni/VoxelM/Plugins/VoxelForge/COMPOSER-NOTES.md:1477>)
## Fit with Research6 §2 contract
R6’s scalar field contract is a good fit for **a new single composite cave generator**, provided its complete plan is immutable and bound before tile jobs. The contract still needs its broader migration: R6 identifies remaining dispatch, unit, policy, passage, and mesher leaks. Recent Core binding/layout work advances that migration, but does not make every generator a native field yet. [Research6/REPORT.md §2](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Research6/REPORT.md:22>) · [ARCHITECTURE.md §8.50](</home/jahni/VoxelM/Plugins/VoxelForge/ARCHITECTURE.md:2165>)
- **Fits without a generator/mesher extension:** Unreal-only lighting, actor/HISM landmarks, HUD/map, and edit persistence. A visual landmark can reuse the current content path.
- **Fits the evaluator contract, but needs data/implementation:** A composite cave generator can return one `densityAt` field. Its room graph and feature bounds must be in the resolved snapshot before sampling. Static SDF stamps need bounded feature records and conservative interval behavior.
- **Needs the contract extended:** Water needs a liquid surface/query payload separate from rock density. Visible ores need a material/resource semantic channel. A physically open skylight needs geometry and a light-opening descriptor.
- **Composer scope:** Offline composition can keep the runtime evaluator contract; the resolved season manifest must grow to carry passages and selected content/feature records. The current six-slot artifact is not the complete world manifest.
## Prior art: design principles
1. **Give the player a readable route rhythm.** Deep Rock Galactic connects curated rooms with narrow, winding tunnels; designers shape rooms to funnel players naturally toward exits and balance traversal with dramatic spaces. Spelunky 2 pairs a guaranteed safe route with optional layers and alternate routes. [DRG developer cave-generation article](https://store.steampowered.com/news/posts/?appgroupname=Deep+Rock+Galactic&appids=548430&enddate=1729500950&feed=steam_community_announcements), [Spelunky 2 interview](https://blog.playstation.com/archive/2018/08/29/first-look-at-spelunky-2-gameplay-plus-new-derek-yu-interview/)
2. **Alternate scale and local hazards.** Minecraft deliberately mixes huge “cheese” chambers, long “spaghetti” caves, narrow “noodle” passages, and local-level aquifers. This supports alternating tunnels, chambers, and occasional pools instead of filling a whole strate with water. [Minecraft Caves & Cliffs features](https://www.minecraft.net/de-de/article/caves---cliffs--part-ii-out-today-bedrock)
3. **Curate the structure; randomize inside it.** DRG uses designed room templates with internal randomizers. Astroneer uses artist-designed biomes and constrains randomization; Enshrouded’s world team describes handcrafted locations and procedural tools as support for meaningful discovery and lore. [DRG](https://store.steampowered.com/news/posts/?appgroupname=Deep+Rock+Galactic&appids=548430&enddate=1729500950&feed=steam_community_announcements), [Astroneer developer interview](https://www.unrealengine.com/developer-interviews/inspired-space-inside-the-development-of-astroneer?lang=en-US), [Keen Games on Enshrouded’s world](https://www.linkedin.com/posts/keen-games_creating-the-world-of-enshrouded-activity-7140369674289995777-SJ2t)
4. **Use lighting and vistas as orientation, not decoration alone.** DRG varies cave geometry, fog, and lighting by biome. Enshrouded’s 1.0 notes emphasize distinct biome lighting and atmosphere and improved distant vistas; No Man’s Sky’s update notes call out more navigable caves and underground ruins. [DRG](https://store.steampowered.com/news/posts/?appgroupname=Deep+Rock+Galactic&appids=548430&enddate=1729500950&feed=steam_community_announcements), [Enshrouded 1.0 notes](https://kg-www.keengames.com/en-US/news/release-trailer-changelog-everything-you-need-to-wait-for-tomorrow), [No Man’s Sky](https://www.nomanssky.com/en/next-update/)
5. **Make exploration teachable and reactive.** Spelunky 2 preserves a safe route while adding layers and liquids; Noita’s developers describe physical materials as a source of emergent encounters; Valheim’s official overview emphasizes biome-specific challenges, resources, secrets, and caves as optional exploration. [Spelunky 2](https://blog.playstation.com/archive/2018/08/29/first-look-at-spelunky-2-gameplay-plus-new-derek-yu-interview/), [Noita GDC talk](https://www.gdcvault.com/play/1025695/Exploring-the-), [Valheim FAQ](https://valheim.com/faq/)
## Owner questions
1. Should the first slice prioritize a **lit landmark chamber** or a **gather-and-return loop** with ore and persistence?
2. Is a static, bounded stream and pool acceptable for the water MVP, with simulation deferred?
+5 -4
View File
@@ -23,7 +23,7 @@ ROOT = Path(__file__).resolve().parents[3]
VERIFY_DIR = ROOT / "Standalone/Tools/verify"
LINUX37 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux37"
OWNER = ROOT / "Standalone/data/owner_world.json"
OUT_DEFAULT = ROOT / "Saved/Linux/l41"
OUT_DEFAULT = ROOT / "Saved/Linux/l42"
PARSER = argparse.ArgumentParser(description=__doc__)
PARSER.add_argument("tier", choices=("fast", "medium", "full"))
@@ -35,6 +35,7 @@ PARSER.add_argument("--overall-timeout", type=int, default=7200,
help="maximum tier wall time in seconds (default: 7200; each child is capped at 1800)")
ARGS = PARSER.parse_args()
OUT = ARGS.out.resolve()
ROUND_NAME = OUT.name
os.environ["VOXELFORGE_VERIFY_OUT"] = str(OUT)
os.environ["PYTHONDONTWRITEBYTECODE"] = "1"
sys.dont_write_bytecode = True
@@ -45,9 +46,9 @@ from runner import VerificationFailure, VerificationRunner, bounded_run
from source_stamp import source_stamp
CLANG = OUT / "bin/VoxelForgeCoreHeadless-l41-clang"
GCC = OUT / "bin/VoxelForgeCoreHeadless-l41-gcc"
RENDERER = OUT / "bin/VoxelForgeOffscreenCapture-l41-clang"
CLANG = OUT / "bin" / f"VoxelForgeCoreHeadless-{ROUND_NAME}-clang"
GCC = OUT / "bin" / f"VoxelForgeCoreHeadless-{ROUND_NAME}-gcc"
RENDERER = OUT / "bin" / f"VoxelForgeOffscreenCapture-{ROUND_NAME}-clang"
HASH_RE = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M)
RECIPE_RE = re.compile(
r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$", re.M)