wip(assembler): round L21 -- resolved strate layout snapshot + validator (no world change)

Core ResolvedLayoutSnapshotV1 (canonical JSON, stable identity): per strate stable ID, generator,
recipe, interior bounds in metres, ceiling/bedrock bands as Core really applies them, transition
mode/width, dispatch provenance. Validator: compat mode reports today's deviations; strict mode
enforces ceiling -> content -> bedrock -> next ceiling (owner rule), two separate bands, nominal
contiguity, interpenetration only within the declared EVoxelStrateTransition width; 7 negative
controls rejected. Findings: SW built at -120..-632 m although the params say -60 m; a 60 m unowned
gap filled by analytic FI fallback; no active bedrock bands; transitions ignored by Core.
All L19 hashes unchanged (28 + 14 crossing runs). The Unreal adapter exports resolved_layout
(uncompiled here).

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 10:22:00 +02:00
1 parent 5d5447dc32
commit 8753f6dbe4
12 files changed
+1347 -3

No files matched your search

@@ -563,6 +563,96 @@ namespace VoxelForgeCore
std::string ToJson() const;
};
// Read-only, versioned account of the physical layout resolved by the director and the
// Core adapter. Coordinates are half-open micrometre intervals; recipe anchors retain their
// source fixed-point units so this record never rounds the recipe itself.
inline constexpr std::uint32_t ResolvedLayoutSchemaVersionV1 = 1;
enum class ResolvedLayoutValidationModeV1 : std::uint8_t { compatibility, strict };
struct ResolvedLayoutAnchorV1
{
std::string kind;
std::string stableId;
std::string units;
std::vector<std::int64_t> values;
};
struct ResolvedLayoutBandV1
{
std::string kind; // ceiling, content, bedrock
std::int64_t bottomMicrometres = 0;
std::int64_t topMicrometres = 0;
bool presentInCurrentField = false;
bool diggable = true;
bool protectedBand = false;
std::string behaviour;
std::string densitySide;
std::string capPath;
};
struct ResolvedLayoutStratumV1
{
std::string stableId;
std::int32_t order = 0;
std::int32_t strateIndex = -1;
std::string generatorKind;
std::string recipeId;
std::uint32_t recipeVersion = 0;
std::int64_t interiorBottomMicrometres = 0;
std::int64_t interiorTopMicrometres = 0;
std::uint32_t voxelSizeMicrometres = 0;
std::array<std::int64_t, 3> latticeOriginMicrometres{};
ResolvedLayoutBandV1 ceiling;
ResolvedLayoutBandV1 content;
ResolvedLayoutBandV1 bedrock;
std::string transitionMode; // mode at this strate's lower interface
std::int32_t transitionBlendChunks = 0;
std::int64_t transitionWidthMicrometres = 0;
std::int64_t transitionWarpAmplitudeMicrometres = 0;
std::int64_t transitionInterpenetrationMicrometres = 0;
bool transitionHonouredInCore = false;
std::string transitionDispatchPath;
std::string boundDispatchPath;
std::string queryDispatchPath;
std::string managerLookup;
std::int64_t managerChunkWidthMicrometres = 0;
std::int64_t dispatchChunkWidthMicrometres = 0;
std::vector<ResolvedLayoutAnchorV1> anchors;
};
struct ResolvedLayoutIssueV1
{
std::string code;
std::string detail;
};
struct VFCORE_API ResolvedLayoutSnapshotV1
{
std::uint32_t schemaVersion = ResolvedLayoutSchemaVersionV1;
std::string worldIdentity;
std::uint32_t ownerVoxelSizeMicrometres = 0;
std::uint32_t coreVoxelSizeMicrometres = 0;
std::vector<ResolvedLayoutStratumV1> strates;
std::string stableIdentity;
bool finalize(std::string& error);
bool validate(ResolvedLayoutValidationModeV1 mode,
std::vector<ResolvedLayoutIssueV1>& issues,
std::string& error) const;
std::string ToJson() const;
static std::optional<ResolvedLayoutSnapshotV1> FromJson(
std::string_view json, std::string& error);
};
struct ResolvedLayoutValidatorAuditV1
{
std::uint32_t controlsRun = 0;
std::uint32_t controlsRejectedAsExpected = 0;
bool passed = false;
std::vector<ResolvedLayoutIssueV1> failures;
};
VFCORE_API ResolvedLayoutValidatorAuditV1 AuditResolvedLayoutValidatorV1();
struct FloatingIslandBoundsAuditResult
{
std::uint64_t boxesTested = 0;
@@ -1154,6 +1244,8 @@ namespace VoxelForgeCore
ShapeBuildStats buildStats() const;
float densityAt(Vec3d voxelPosition) const;
// Audit-only selector provenance for the same point evaluator; never used by meshing.
std::string densityDispatchPathAt(Vec3d voxelPosition) const;
// Analytic source distance without the occupancy-preserving near-zero clamp or packed proxy.
float unclampedDensityAt(Vec3d voxelPosition) const;
DetailFieldSample detailSampleAt(Vec3d voxelPosition) const;
@@ -0,0 +1,330 @@
#pragma once
#include "Json.h"
#include "VoxelForgeCore/VoxelForgeCore.h"
#include <algorithm>
#include <iomanip>
#include <sstream>
namespace VoxelForgeCore
{
namespace
{
std::string LayoutEscape(std::string_view value)
{
std::string out="\"";
for(unsigned char c:value)
{
switch(c)
{
case '"':out+="\\\"";break;
case '\\':out+="\\\\";break;
case '\b':out+="\\b";break;
case '\f':out+="\\f";break;
case '\n':out+="\\n";break;
case '\r':out+="\\r";break;
case '\t':out+="\\t";break;
default:if(c<0x20){char b[7];std::snprintf(b,sizeof(b),"\\u%04x",c);out+=b;}
else out+=static_cast<char>(c);
}
}
out+='"';return out;
}
std::uint64_t LayoutHash(std::string_view value)
{
std::uint64_t hash=14695981039346656037ull;
for(unsigned char c:value){hash^=c;hash*=1099511628211ull;}
return hash;
}
std::string LayoutHex(std::uint64_t value)
{std::ostringstream out;out<<std::hex<<std::setfill('0')<<std::setw(16)<<value;return out.str();}
std::int64_t LayoutTransitionLimit(const ResolvedLayoutStratumV1& stratum)
{
if(stratum.transitionMode=="Hard")return 0;
return stratum.transitionWidthMicrometres
+(stratum.transitionMode=="Interleaved"?stratum.transitionWarpAmplitudeMicrometres:0);
}
std::string LayoutBandJson(const ResolvedLayoutBandV1& band)
{
std::ostringstream out;out<<"{\"kind\":"<<LayoutEscape(band.kind)
<<",\"bottom_um\":"<<band.bottomMicrometres<<",\"top_um\":"<<band.topMicrometres
<<",\"present\":"<<(band.presentInCurrentField?"true":"false")
<<",\"diggable\":"<<(band.diggable?"true":"false")
<<",\"protected\":"<<(band.protectedBand?"true":"false")
<<",\"behaviour\":"<<LayoutEscape(band.behaviour)
<<",\"density_side\":"<<LayoutEscape(band.densitySide)
<<",\"cap_path\":"<<LayoutEscape(band.capPath)<<'}';return out.str();
}
ResolvedLayoutBandV1 ParseLayoutBand(const VFJson::Value& value)
{
ResolvedLayoutBandV1 b;b.kind=value.Get("kind").String();
b.bottomMicrometres=value.Get("bottom_um").Integer();b.topMicrometres=value.Get("top_um").Integer();
b.presentInCurrentField=value.Get("present").Boolean();b.diggable=value.Get("diggable").Boolean(true);
b.protectedBand=value.Get("protected").Boolean();b.behaviour=value.Get("behaviour").String();
b.densitySide=value.Get("density_side").String();b.capPath=value.Get("cap_path").String();return b;
}
std::string LayoutBodyJson(const ResolvedLayoutSnapshotV1& s)
{
std::ostringstream out;out<<"{\"schema_version\":"<<s.schemaVersion
<<",\"world_identity\":"<<LayoutEscape(s.worldIdentity)
<<",\"owner_voxel_size_um\":"<<s.ownerVoxelSizeMicrometres
<<",\"core_voxel_size_um\":"<<s.coreVoxelSizeMicrometres<<",\"strates\":[";
for(std::size_t i=0;i<s.strates.size();++i)
{
if(i)out<<',';const auto& x=s.strates[i];
out<<"{\"stable_id\":"<<LayoutEscape(x.stableId)<<",\"order\":"<<x.order
<<",\"strate_index\":"<<x.strateIndex<<",\"generator_kind\":"<<LayoutEscape(x.generatorKind)
<<",\"recipe_id\":"<<LayoutEscape(x.recipeId)<<",\"recipe_version\":"<<x.recipeVersion
<<",\"interior_bottom_um\":"<<x.interiorBottomMicrometres
<<",\"interior_top_um\":"<<x.interiorTopMicrometres
<<",\"voxel_size_um\":"<<x.voxelSizeMicrometres
<<",\"lattice_origin_um\":["<<x.latticeOriginMicrometres[0]<<','
<<x.latticeOriginMicrometres[1]<<','<<x.latticeOriginMicrometres[2]<<']'
<<",\"ceiling\":"<<LayoutBandJson(x.ceiling)
<<",\"content\":"<<LayoutBandJson(x.content)
<<",\"bedrock\":"<<LayoutBandJson(x.bedrock)
<<",\"transition_mode\":"<<LayoutEscape(x.transitionMode)
<<",\"transition_blend_chunks\":"<<x.transitionBlendChunks
<<",\"transition_width_um\":"<<x.transitionWidthMicrometres
<<",\"transition_warp_amplitude_um\":"<<x.transitionWarpAmplitudeMicrometres
<<",\"transition_interpenetration_um\":"<<x.transitionInterpenetrationMicrometres
<<",\"transition_honoured_in_core\":"<<(x.transitionHonouredInCore?"true":"false")
<<",\"transition_dispatch_path\":"<<LayoutEscape(x.transitionDispatchPath)
<<",\"bound_dispatch_path\":"<<LayoutEscape(x.boundDispatchPath)
<<",\"query_dispatch_path\":"<<LayoutEscape(x.queryDispatchPath)
<<",\"manager_lookup\":"<<LayoutEscape(x.managerLookup)
<<",\"manager_chunk_width_um\":"<<x.managerChunkWidthMicrometres
<<",\"dispatch_chunk_width_um\":"<<x.dispatchChunkWidthMicrometres
<<",\"anchors\":[";
for(std::size_t a=0;a<x.anchors.size();++a)
{
if(a)out<<',';const auto& anchor=x.anchors[a];
out<<"{\"kind\":"<<LayoutEscape(anchor.kind)<<",\"stable_id\":"
<<LayoutEscape(anchor.stableId)<<",\"units\":"<<LayoutEscape(anchor.units)<<",\"values\":[";
for(std::size_t v=0;v<anchor.values.size();++v){if(v)out<<',';out<<anchor.values[v];}
out<<"]}";
}
out<<"]}";
}
out<<"]}";return out.str();
}
std::int64_t LayoutInt(const VFJson::Value& obj,std::string_view key)
{return obj.Get(key).Integer();}
std::string LayoutString(const VFJson::Value& obj,std::string_view key)
{return obj.Get(key).String();}
bool LayoutBool(const VFJson::Value& obj,std::string_view key,bool fallback=false)
{return obj.Get(key).Boolean(fallback);}
}
std::string ResolvedLayoutSnapshotV1::ToJson() const
{
const std::string body=LayoutBodyJson(*this);
return body.substr(0,body.size()-1)+",\"stable_identity\":"
+LayoutEscape(stableIdentity.empty()?"resolved-layout-v1-fnv64:"+LayoutHex(LayoutHash(body)):stableIdentity)+"}";
}
bool ResolvedLayoutSnapshotV1::finalize(std::string& error)
{
error.clear();
if(schemaVersion!=ResolvedLayoutSchemaVersionV1||worldIdentity.empty()||strates.empty())
{error="resolved layout has an unsupported version, empty world identity, or no strates";return false;}
std::stable_sort(strates.begin(),strates.end(),[](const auto& a,const auto& b)
{return a.interiorTopMicrometres!=b.interiorTopMicrometres
?a.interiorTopMicrometres>b.interiorTopMicrometres:a.order<b.order;});
for(std::size_t i=0;i<strates.size();++i)
{
auto& x=strates[i];x.order=static_cast<std::int32_t>(i);
if(x.stableId.empty())x.stableId=worldIdentity+"/strate/"+std::to_string(x.strateIndex);
if(x.content.kind.empty())x.content.kind="content";
if(x.ceiling.kind.empty())x.ceiling.kind="ceiling";
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;}
}
stableIdentity.clear();const std::string body=LayoutBodyJson(*this);
stableIdentity="resolved-layout-v1-fnv64:"+LayoutHex(LayoutHash(body));
std::vector<ResolvedLayoutIssueV1> issues;
return validate(ResolvedLayoutValidationModeV1::compatibility,issues,error);
}
bool ResolvedLayoutSnapshotV1::validate(ResolvedLayoutValidationModeV1 mode,
std::vector<ResolvedLayoutIssueV1>& issues,std::string& error) const
{
issues.clear();error.clear();
if(schemaVersion!=ResolvedLayoutSchemaVersionV1||worldIdentity.empty()||strates.empty())
{error="resolved layout schema/world/strata header is invalid";return false;}
const auto add=[&](std::string code,std::string detail)
{issues.push_back({std::move(code),std::move(detail)});};
const bool strict=mode==ResolvedLayoutValidationModeV1::strict;
for(std::size_t i=0;i<strates.size();++i)
{
const auto& s=strates[i];
const std::int64_t effectiveTransitionWidth=LayoutTransitionLimit(s);
if(s.interiorTopMicrometres<=s.interiorBottomMicrometres)
add("invalid_interior",s.stableId+" has non-positive content height");
if(s.transitionInterpenetrationMicrometres>effectiveTransitionWidth
||s.transitionInterpenetrationMicrometres<0)
add("transition_overlap_exceeds_width",s.stableId+" transition interpenetration exceeds its declared width");
if(s.managerChunkWidthMicrometres>0&&s.dispatchChunkWidthMicrometres>0
&&s.managerChunkWidthMicrometres!=s.dispatchChunkWidthMicrometres)
add("ambiguous_dispatch_units",s.stableId+" manager chunk width differs from Core dispatch chunk width");
if(i+1<strates.size()&&s.transitionMode!="Hard"&&!s.transitionHonouredInCore)
add("transition_not_honoured",s.stableId+" declares a blend/interleave that Core does not apply on this interface");
if(!s.ceiling.presentInCurrentField)add("missing_ceiling",s.stableId+" has no explicit ceiling band in today's field");
if(!s.bedrock.presentInCurrentField)add("missing_bedrock",s.stableId+" has no explicit bedrock floor in today's field");
if(strict)
{
if(s.order!=static_cast<std::int32_t>(i))add("wrong_order",s.stableId+" order is not top-to-bottom");
if(!s.ceiling.presentInCurrentField||!s.bedrock.presentInCurrentField)
add(!s.ceiling.presentInCurrentField?"missing_ceiling":"missing_bedrock",s.stableId+" lacks a required boundary band");
if(!s.content.presentInCurrentField)
add("missing_content",s.stableId+" has no content generator band");
const auto bandShape=[&](const ResolvedLayoutBandV1& b,std::string_view expected)
{
if(b.kind!=expected||b.topMicrometres<=b.bottomMicrometres)
add("wrong_order",s.stableId+" has an invalid "+std::string(expected)+" band");
if(b.protectedBand&&b.diggable)
add("invalid_protection",s.stableId+" band is both protected and diggable");
};
bandShape(s.ceiling,"ceiling");bandShape(s.content,"content");bandShape(s.bedrock,"bedrock");
if(s.ceiling.bottomMicrometres!=s.content.topMicrometres
||s.content.bottomMicrometres!=s.bedrock.topMicrometres)
add("wrong_order",s.stableId+" bands do not follow ceiling -> content -> bedrock");
if(i+1<strates.size()
&&s.bedrock.bottomMicrometres!=strates[i+1].ceiling.topMicrometres)
add(s.bedrock.bottomMicrometres>strates[i+1].ceiling.topMicrometres?"gap":"overlap",
s.stableId+" bedrock and next strate ceiling are not nominally contiguous");
if(s.transitionInterpenetrationMicrometres>effectiveTransitionWidth)
add("transition_overlap_exceeds_width",s.stableId+" interpenetration is wider than the declared transition zone");
}
}
if(!strict)
{
for(const auto& s:strates)
{
if(s.content.presentInCurrentField&&s.ceiling.presentInCurrentField)
{
if(s.ceiling.bottomMicrometres<s.content.topMicrometres)
add("band_overlap",s.stableId+" ceiling overlaps content by "+std::to_string(
s.content.topMicrometres-s.ceiling.bottomMicrometres)+" um");
else if(s.ceiling.bottomMicrometres>s.content.topMicrometres)
add("uncovered_interval",s.stableId+" has a "+std::to_string(
s.ceiling.bottomMicrometres-s.content.topMicrometres)+" um gap below its ceiling");
}
if(s.content.presentInCurrentField&&s.bedrock.presentInCurrentField)
{
if(s.bedrock.topMicrometres>s.content.bottomMicrometres)
add("band_overlap",s.stableId+" bedrock overlaps content by "+std::to_string(
s.bedrock.topMicrometres-s.content.bottomMicrometres)+" um");
else if(s.bedrock.topMicrometres<s.content.bottomMicrometres)
add("uncovered_interval",s.stableId+" has a "+std::to_string(
s.content.bottomMicrometres-s.bedrock.topMicrometres)+" um gap above its bedrock");
}
}
for(std::size_t i=0;i+1<strates.size();++i)
{
const auto& a=strates[i];const auto& b=strates[i+1];
const std::int64_t effectiveTransitionWidth=LayoutTransitionLimit(a);
if(a.interiorBottomMicrometres>b.interiorTopMicrometres)
add("uncovered_interval",a.stableId+" to "+b.stableId+" leaves "+std::to_string(
a.interiorBottomMicrometres-b.interiorTopMicrometres)+" um uncovered");
else if(a.interiorBottomMicrometres<b.interiorTopMicrometres)
{
const std::int64_t overlap=b.interiorTopMicrometres-a.interiorBottomMicrometres;
if(overlap>effectiveTransitionWidth)
add("overlap",a.stableId+" and "+b.stableId+" interiors overlap by "+std::to_string(overlap)+" um");
else add("transition_interpenetration",a.stableId+" and "+b.stableId+" overlap inside the declared transition zone");
}
if(a.bedrock.presentInCurrentField&&b.ceiling.presentInCurrentField)
{
if(a.bedrock.bottomMicrometres>b.ceiling.topMicrometres)
add("uncovered_interval",a.stableId+" bedrock and "+b.stableId+" ceiling leave "+std::to_string(
a.bedrock.bottomMicrometres-b.ceiling.topMicrometres)+" um uncovered");
else if(a.bedrock.bottomMicrometres<b.ceiling.topMicrometres)
{
const std::int64_t overlap=b.ceiling.topMicrometres-a.bedrock.bottomMicrometres;
if(overlap>effectiveTransitionWidth)
add("overlap",a.stableId+" bedrock and "+b.stableId+" ceiling overlap by "+std::to_string(overlap)+" um");
else add("transition_interpenetration",a.stableId+" bedrock and "+b.stableId+" ceiling interpenetrate by "+std::to_string(overlap)+" um inside the declared transition zone");
}
}
}
}
if(strict&&!issues.empty()){error="strict resolved-layout validation rejected "+issues.front().code;return false;}
return true;
}
std::optional<ResolvedLayoutSnapshotV1> ResolvedLayoutSnapshotV1::FromJson(
std::string_view json,std::string& error)
{
VFJson::Value root;if(!VFJson::Parser(std::string(json)).Parse(root,error))return std::nullopt;
if(!root.IsObject()){error="resolved layout JSON root must be an object";return std::nullopt;}
ResolvedLayoutSnapshotV1 s;s.schemaVersion=static_cast<std::uint32_t>(LayoutInt(root,"schema_version"));
s.worldIdentity=LayoutString(root,"world_identity");
s.ownerVoxelSizeMicrometres=static_cast<std::uint32_t>(LayoutInt(root,"owner_voxel_size_um"));
s.coreVoxelSizeMicrometres=static_cast<std::uint32_t>(LayoutInt(root,"core_voxel_size_um"));
for(const auto& v:root.Get("strates").AsArray())
{
ResolvedLayoutStratumV1 x;x.stableId=LayoutString(v,"stable_id");
x.order=static_cast<std::int32_t>(LayoutInt(v,"order"));x.strateIndex=static_cast<std::int32_t>(LayoutInt(v,"strate_index"));
x.generatorKind=LayoutString(v,"generator_kind");x.recipeId=LayoutString(v,"recipe_id");
x.recipeVersion=static_cast<std::uint32_t>(LayoutInt(v,"recipe_version"));
x.interiorBottomMicrometres=LayoutInt(v,"interior_bottom_um");x.interiorTopMicrometres=LayoutInt(v,"interior_top_um");
x.voxelSizeMicrometres=static_cast<std::uint32_t>(LayoutInt(v,"voxel_size_um"));
const auto& origin=v.Get("lattice_origin_um").AsArray();for(std::size_t i=0;i<3&&i<origin.size();++i)x.latticeOriginMicrometres[i]=origin[i].Integer();
x.ceiling=ParseLayoutBand(v.Get("ceiling"));x.content=ParseLayoutBand(v.Get("content"));x.bedrock=ParseLayoutBand(v.Get("bedrock"));
x.transitionMode=LayoutString(v,"transition_mode");x.transitionBlendChunks=static_cast<std::int32_t>(LayoutInt(v,"transition_blend_chunks"));
x.transitionWidthMicrometres=LayoutInt(v,"transition_width_um");
x.transitionWarpAmplitudeMicrometres=LayoutInt(v,"transition_warp_amplitude_um");
x.transitionInterpenetrationMicrometres=LayoutInt(v,"transition_interpenetration_um");
x.transitionHonouredInCore=LayoutBool(v,"transition_honoured_in_core");x.transitionDispatchPath=LayoutString(v,"transition_dispatch_path");
x.boundDispatchPath=LayoutString(v,"bound_dispatch_path");x.queryDispatchPath=LayoutString(v,"query_dispatch_path");
x.managerLookup=LayoutString(v,"manager_lookup");x.managerChunkWidthMicrometres=LayoutInt(v,"manager_chunk_width_um");
x.dispatchChunkWidthMicrometres=LayoutInt(v,"dispatch_chunk_width_um");
for(const auto& a:v.Get("anchors").AsArray())
{ResolvedLayoutAnchorV1 p;p.kind=LayoutString(a,"kind");p.stableId=LayoutString(a,"stable_id");p.units=LayoutString(a,"units");
for(const auto& value:a.Get("values").AsArray())p.values.push_back(value.Integer());x.anchors.push_back(std::move(p));}
s.strates.push_back(std::move(x));
}
const std::string serializedIdentity=LayoutString(root,"stable_identity");
if(!s.finalize(error))return std::nullopt;
if(s.stableIdentity!=serializedIdentity){error="resolved layout stable identity does not match its canonical payload";return std::nullopt;}
return s;
}
ResolvedLayoutValidatorAuditV1 AuditResolvedLayoutValidatorV1()
{
ResolvedLayoutValidatorAuditV1 result;
auto make=[](std::string id,std::int32_t order,std::int64_t top,std::int64_t bottom)
{
ResolvedLayoutStratumV1 s;s.stableId=std::move(id);s.order=order;s.strateIndex=order;s.generatorKind="synthetic";
s.interiorTopMicrometres=top;s.interiorBottomMicrometres=bottom;s.voxelSizeMicrometres=250000;
s.transitionMode="Gradient";s.transitionWidthMicrometres=4000000;
s.transitionHonouredInCore=true;
s.ceiling={"ceiling",top,top+1000000,true,true,false,"closed ceiling band","upper face","synthetic"};
s.content={"content",bottom,top,true,true,false,"generator content","none","none"};
s.bedrock={"bedrock",bottom-1000000,bottom,true,true,false,"breakable bedrock","lower face","none"};
return s;
};
const auto expectReject=[&](std::string name,ResolvedLayoutSnapshotV1 candidate)
{
++result.controlsRun;std::vector<ResolvedLayoutIssueV1> issues;std::string error;
if(!candidate.validate(ResolvedLayoutValidationModeV1::strict,issues,error))++result.controlsRejectedAsExpected;
else result.failures.push_back({"negative_control_accepted",std::move(name)+" was accepted by strict validator"});
};
auto base=ResolvedLayoutSnapshotV1{};base.worldIdentity="synthetic";base.strates={make("a",0,10000000,0),make("b",1,-2000000,-12000000)};
{std::vector<ResolvedLayoutIssueV1> issues;std::string error;
if(!base.validate(ResolvedLayoutValidationModeV1::strict,issues,error))
result.failures.push_back({"positive_control_rejected","valid ceiling/content/bedrock layout was rejected"});}
auto boundaryGap=base;boundaryGap.strates[1].ceiling.topMicrometres-=1;
expectReject("bedrock/next-ceiling gap",boundaryGap);
auto missingBedrock=base;missingBedrock.strates[0].bedrock.presentInCurrentField=false;expectReject("missing bedrock",missingBedrock);
auto missingCeiling=base;missingCeiling.strates[0].ceiling.presentInCurrentField=false;expectReject("missing ceiling",missingCeiling);
auto wrongOrder=base;wrongOrder.strates[0].content.kind="bedrock";expectReject("wrong band order",wrongOrder);
auto largeOverlap=base;largeOverlap.strates[0].transitionInterpenetrationMicrometres=4000001;expectReject("interpenetration exceeds transition width",largeOverlap);
auto genericOverlap=base;genericOverlap.strates[0].bedrock.bottomMicrometres-=1;expectReject("nominal band overlap",genericOverlap);
auto genericGap=base;genericGap.strates[0].bedrock.bottomMicrometres+=1;expectReject("nominal band gap",genericGap);
result.passed=result.controlsRun==result.controlsRejectedAsExpected&&result.failures.empty();return result;
}
}
+26
View File
@@ -1095,6 +1095,32 @@ public:
return AnalyticDensityAt(X,Y,Z);
}
std::string DensityDispatchPathAt(float X,float Y,float Z) const
{
if(SharedDensitySource)return SharedDensitySource->DensityDispatchPathAt(X,Y,Z);
float Density=0.0f;
if(NativeFloatingIslandDensityAt(X,Y,Z,Density))return "FloatingIslands-native";
if(NativeSurfaceDensityAt(X,Y,Z,Density))return "SurfaceWorld-native";
if(UsesLegacySurfaceField(X,Y,Z))return "SurfaceWorld-legacy";
if(Owner&&Owner->Manager)
{
const int32 ChunkZ=FMath::FloorToInt(Z/static_cast<float>(CHUNK_SIZE));
const ECaveGeneratorType Type=Owner->Manager->GetGeneratorTypeForChunk(FIntVector(0,0,ChunkZ));
switch(Type)
{
case ECaveGeneratorType::TunnelNetwork:return "compiled-analytic/TunnelNetwork";
case ECaveGeneratorType::FlatPlain:return "compiled-analytic/FlatPlain";
case ECaveGeneratorType::CrystalChamber:return "compiled-analytic/CrystalChamber";
case ECaveGeneratorType::Maze:return "compiled-analytic/Maze";
case ECaveGeneratorType::SurfaceWorld:return "compiled-analytic/SurfaceWorld";
case ECaveGeneratorType::VerticalShafts:return "compiled-analytic/VerticalShafts";
case ECaveGeneratorType::FloatingIslands:return "compiled-analytic/FloatingIslands";
case ECaveGeneratorType::Underwater:return "compiled-analytic/Underwater";
}
}
return "compiled-analytic/fallback";
}
float DensityAtLattice(int32 X,int32 Y,int32 Z) const
{
if(SharedDensitySource)return SharedDensitySource->DensityAtLattice(X,Y,Z);
+5
View File
@@ -2,6 +2,7 @@
#include "StandaloneSnapshotAdapter.h"
#include "VoxelForgeCore/VoxelForgeCore.h"
#include "WorldAssemblerInternal.h"
#include "ResolvedLayoutInternal.h"
#include "FloatingIslandsInternal.h"
#include <shared_mutex>
@@ -1457,6 +1458,10 @@ namespace VoxelForgeCore
float World::densityAt(Vec3d position) const
{ return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape?impl_->shape->DensityAt(static_cast<float>(position.x),static_cast<float>(position.y),static_cast<float>(position.z)):0.0f; }
std::string World::densityDispatchPathAt(Vec3d position) const
{ return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape
?impl_->shape->DensityDispatchPathAt(static_cast<float>(position.x),static_cast<float>(position.y),static_cast<float>(position.z))
:"uncompiled"; }
float World::unclampedDensityAt(Vec3d position) const
{ return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape?impl_->shape->DensityAtUnclamped(static_cast<float>(position.x),static_cast<float>(position.y),static_cast<float>(position.z)):0.0f; }
DetailFieldSample World::detailSampleAt(Vec3d position) const
@@ -0,0 +1,203 @@
# World Assembler L21 — resolved strate layout
This round adds a read-only layout snapshot and validator. It does not change density or mesh
evaluation.
## Snapshot and current stack
World identity is `owner-world/seed/0`; Core voxel size is 0.25 m, owner voxel size is 0.125 m, and
all lattice origins are `(0,0,0)`. Intervals below are half-open `[bottom, top)` metres. Stable strate
IDs are `owner-world/seed/0/strate/<index>/generator/<kind>`. The shared Core record uses canonical
JSON schema v1 and an FNV-1a payload identity.
The required structure, top to bottom, is:
```text
strate N ceiling band
content
bedrock band
strate N+1 ceiling band
content
bedrock band
```
Ceiling and bedrock remain distinct bands owned by their own strate. Their nominal edges touch; a
separate `EVoxelStrateTransition` declaration describes possible interpenetration.
| Prototype | Order / stable suffix | Generator; recipe version | Interior/content (m) | Current ceiling | Current bedrock | Transition at lower interface |
|---|---|---|---|---|---|---|
| SurfaceWorld | 0 / `TunnelNetwork` | TunnelNetwork; `legacy.TunnelNetwork` v0 | `[-120, 8)` | No Core density band. Manager configures a 1 m upper `VF_ApplyBoundarySeal` at `[8,9)`, but the compiled analytic Core path does not apply it. | No Core density band. Manager configures a 1 m lower `VF_ApplyBoundarySeal` at `[-121,-120)`, but the compiled analytic Core path does not apply it. | Gradient, 2 chunks = 8 m by the 4 m manager chunk. Core does not apply it; manager/dispatch chunk widths are 4/8 m. |
| SurfaceWorld | 1 / `SurfaceWorld` | SurfaceWorld; `SurfaceWorld.Heightfield2D` v1 | `[-632,-120)` | No separate volumetric band; cap profile is in content, with `AppendStratumBoundaryCeilings` mesh fallback. | None. | Gradient, 1 chunk = 4 m by manager units; no lower strate in this plan. Manager/dispatch widths are 4/8 m. |
| FloatingIslands | 0 / `FloatingIslands` | FloatingIslands; `FloatingIslands.ClusterField` geometry v3 | `[-60,4)` | Active one-sided upper seal `[3.5,4)` = 0.5 m. It overlaps the content range by 0.5 m. | None in geometry v3. | Gradient, 2 chunks = 8 m. Core does not apply it; manager/dispatch widths are both 4 m. |
| FloatingIslands | 1 / `SurfaceWorld` | SurfaceWorld; `SurfaceWorld.Heightfield2D` v1 | `[-632,-120)` | No separate volumetric band; cap profile is in content, with mesh fallback. | None. | Gradient, 1 chunk = 4 m; no lower strate in this plan. Manager/dispatch widths are 4/8 m. |
Dispatch provenance is recorded per stratum in the JSON snapshot:
- SurfaceWorld bounds come from `BuildSurfaceStratumPlan`, which converts each chunk with 32 Core
voxels = 8 m. `NativeSurfaceDensityAt` selects with `floor(CoreZ/32)`, then calls
`GetGeneratorTypeForChunk` / `GetStrateIndex`. The manager's owner chunk is 4 m.
- FI bounds come from `BuildFloatingIslandStratumPlan`, which converts each 32-voxel owner chunk
through the 12.5/25 cm owner/Core ratio = 16 Core voxels = 4 m. `NativeFloatingIslandDensityAt`
uses the same conversion before the manager lookup.
- Legacy TunnelNetwork selection uses the Core 32-voxel chunk lookup. The manager helper assigns
the upper strate's transition to its lower interface.
SurfaceWorld strata carry four cap profiles, 33 route points and their attached passages. The FI
strate carries four island anchors and its attached passages. The snapshot preserves these recipe
anchors in their source fixed-point units.
The owner configuration’s non-Hard transitions are currently not honored by Core at these interfaces.
`UVoxelStrateManager::GetGenerationParams` contains legacy vector blending, but Core’s compiled
dispatcher selects the resolved/native per-strate fields without applying that blend. FI v3 calls
`VF_ApplyUpperBoundarySeal` for its ceiling; player edit brushes are applied after the native field,
so that seal remains diggable. Bands default to `diggable=true`, `protected=false`; protection is an
explicit option.
```text
Current SurfaceWorld plan, top → bottom
TunnelNetwork ceiling [8,9) (configured; inactive in Core density)
TunnelNetwork content [-120,8)
TunnelNetwork bedrock [-121,-120) (configured; inactive in Core)
SurfaceWorld ceiling: none
SurfaceWorld content [-632,-120)
SurfaceWorld bedrock: none
Current FI prototype, top → bottom
FI ceiling [3.5,4) active, inset into FI content by 0.5 m
FI content [-60,4)
FI bedrock: missing
Unassigned interval [-120,-60) = 60 m
SurfaceWorld ceiling: none
SurfaceWorld content [-632,-120)
SurfaceWorld bedrock: none
```
The SurfaceWorld and FI content interiors therefore do not overlap: the FI prototype has a 60 m gap.
The owner manager slots meet at −60 m when both use 4 m owner chunks, but SurfaceWorld plan/query
dispatch converts chunks at 8 m while FI converts at 4 m. In the gap, Core answers through the
compiled analytic FloatingIslands fallback, not either planned recipe; probes at −68 m returned
solid density −4.125. SurfaceWorld and TunnelNetwork content interiors touch at −120 m in the
SurfaceWorld prototype, but Core does not apply the declared Gradient there.
## Compatibility validation and boundary probes
Compatibility mode accepted both layouts with seven reported issues apiece. SurfaceWorld reports
unhonored transition, 4/8 m dispatch-unit ambiguity on both strates, and missing current-field
ceiling and bedrock bands on both. FI reports its unhonored transition, missing FI bedrock, the
0.5 m ceiling/content overlap, the 60 m uncovered interval, and missing SurfaceWorld ceiling and
bedrock. These are recorded as compatibility deviations, not world changes.
Strict mode accepted a valid synthetic two-strate fixture. Its seven negative controls rejected:
| Control | Strict check that rejects it |
|---|---|
| Nominal band overlap | Bedrock(N) bottom must equal ceiling(N+1) top. |
| Nominal band gap | The same exact nominal contiguity check. |
| Missing bedrock | `bedrock.present` is required. |
| Missing ceiling | `ceiling.present` is required. |
| Wrong band order | Each band kind and the ceiling → content → bedrock edges must match. |
| Gap between bedrock(N) and ceiling(N+1) | Their nominal endpoints must be equal. |
| Interpenetration wider than transition | Explicit overlap must be at most the mode’s limit; this control uses 4,000,001 µm against a 4,000,000 µm Gradient zone. |
Hard has a 0 m limit. Gradient uses `TransitionBlendChunks × 4 m`; Interleaved adds its recorded
two-manager-chunk warp amplitude to the blend width. The nominal bands still touch exactly; the
separate interpenetration field records any permitted physical crossing. Current Core
interpenetration is 0 m because it does not apply the declared blends.
Each plan audited 21 points: one Core voxel (0.25 m) below, at, and above every distinct content,
active-band, configured-band, and transition-zone endpoint. The remaining points agreed with the
snapshot. Every disagreement was an uncovered snapshot point answered by a named compiled analytic
fallback:
| Prototype | Probe Z (m) | Actual Core dispatch | Density / occupancy |
|---|---|---|---|
| SurfaceWorld | −632.250 | `compiled-analytic/TunnelNetwork` | `+1`, air |
| SurfaceWorld | 8.000, 8.250, 8.750, 9.000, 9.250 | `compiled-analytic/TunnelNetwork` | `+9.648438`, `+10.64844`, `+12.64844`, `+13.64844`, `+14.64844`; all air |
| FI | −632.250 | `compiled-analytic/TunnelNetwork` | `+1`, air |
| FI | −120.000, −119.750 | `compiled-analytic/FloatingIslands` | `−108.4793`, `−107.4969`; solid |
| FI | −68.250, −68.000, −67.750, −60.250 | `compiled-analytic/FloatingIslands` | `−4.125`; solid at each point |
| FI | 4.000, 4.250 | `compiled-analytic/FloatingIslands` | `+0.671875`, `+2.253906`; air |
Probe summaries: SurfaceWorld 6/21 disagreements; FI 9/21. Full per-point records are in
`Saved/Linux/linux21/boundary-probes-{surface-world,floating-islands}.log`.
## Identity, output parity and cost
Snapshots round-tripped through canonical JSON. At W1/W8/W12 their bytes were identical per recipe:
| Recipe | Stable identity | Canonical JSON SHA-256 |
|---|---|---|
| SurfaceWorld | `resolved-layout-v1-fnv64:63cf4d2661149fcd` | `267586b3da9bc5c08c654c097559b205222f53c594c4c4332cb4929fd3d75c05` |
| FloatingIslands | `resolved-layout-v1-fnv64:1d90167f37ef9323` | `7bb9e9d745de3a2edf4276f507a5e4c082ff86aa73d9c1ad7e77c1b4d8b8bea8` |
The 28 hash runs (both recipes, Clang `fp-contract=off` and GCC default, W1/W8/W12 and W12×5)
matched all 12 L19 rows per run. The 14 dedicated 24 m crossing runs also matched all 12 L19
crossing rows. The table gives the final Clang W12×5 rows, in density/mesh/payload/topology order;
each equals its L19 reference.
| Scope | SurfaceWorld | FloatingIslands |
|---|---|---|
| Full detail | `0ee0579bd15cbbe4 / 32e5d4964d610fee / 1932b96ee4b1d910 / 69743c6bad3447dc` | `43034299d33f2536 / a41e8353ec4bbe9c / cd0e3e15eef827b0 / 0b3c3f13cc1d6f8a` |
| Whole view | `c10697a8f48380c7 / 4197fc1072f0ff58 / 7b3e616ec9459851 / c879e35592bf33e5` | `00bc3607a7839854 / 4baa66127c2b0892 / e11ef05e851a1517 / 1278bc4b1fffb869` |
| LOD 0 | `769f2a706d585a72 / 33eeeb39fa443816 / 645621a1d968983f / c2457ed905036c9d` | `ccf97d8e95163a35 / 3333fa0ddebdece2 / d1906bffc2b9d6f2 / a261f3d965e15c12` |
| LOD 1 | `69cc5a5c0a2c60af / b48335f5410c57d5 / d15c5480162ab8ba / feca1bd025823604` | `25fa2f0fa7fbb6e6 / c549c519707ac1d7 / 66f797cde4ebdecf / 2383982a12a27ee5` |
| LOD 2 | `85deed5683a77202 / 53469895987aeea2 / e55f8ae7e1532033 / d5feb12a0e85c09b` | `c0577decd8a02cab / 3ccf08b7be6edc5b / 0abcbbda5a06c110 / 11c77b71b606fe75` |
| LOD 3 | `6518caefb3be7e7f / ec513c90b853a614 / f62fa1137ff17f82 / ccf1dcf681965816` | `386e0c0ef2d7c920 / 1ee2c82d34ad9918 / 000a6514ba018406 / 1b4523b19e90f305` |
| LOD 4 | `62d4be96021992f4 / 42706847cb9c744a / eab76f9634e4b9bd / 207ffbb6ef184397` | `e8117a3a803be9f8 / 8a6c36cae1fe0e30 / c839f1b1629eff8c / 0ce9d7ea77b4f62b` |
| LOD 5 | `5e4a8c38b8cea6fc / 76adc9ae86988e27 / 938975bf7cc6d94d / 42e135856abdbcac` | `ca6d1df453c6b600 / 02c90d834d9a3fb6 / 4364c37d526f4104 / 1b1cf40d25e50ddf` |
| LOD 6 | `e036e95b9006945b / a880cc101a4ed957 / bd82f1aefad6dd89 / 5e9f3408345d95b3` | `6764e347b08603a0 / 46c6ed9a1f029b94 / 5b8dc9d5b7cb0d3d / a10a4a69a93eac4d` |
| LOD 7 | `8ee358af56a30d8d / 5cbd8e5965a2cc3f / d4a7fe5d9e4bde30 / 4dd52cd090a9af78` | `c7cd1b483c598595 / a545eb567dc4a0df / b0a1fb225437e05a / 301d1b884c509550` |
| LOD 8 | `c3458e1cbdb9c471 / fba3698d21dd1be0 / 77dfb814eac3a24c / c9514f1580c42449` | `7b6e9279b4993109 / cc63440d9867a18d / 12f5cec78b38fa1b / eed919db6db6b2a7` |
Exact-query rows (density/unclamped, detail, collision): SurfaceWorld `e4d4a8eb95b35933 / e4d4a8eb95b35933`,
`efcba20c0c70c415`, `e604823a249029bf`; FloatingIslands `87e5c0dbf9ee9ee2 / 87e5c0dbf9ee9ee2`,
`efcba20c0c70c415`, `e604823a249029bf`. The representative 24 m crossing W12×5 whole-view row is the
SurfaceWorld row above; all crossing full-detail, LOD and exact-query rows matched the L19 crossing
reference.
Five interleaved hashing-off W12 pairs against L19 measured SurfaceWorld medians 1.510 s old / 1.512 s
new (+0.14%) and FI 13.487 s old / 13.381 s new (−0.79%). The opt-in snapshot is constructed once
at plan time, outside tile workers; ordinary standalone evaluation does not request it. No hash rows
were produced during these pairs.
Clang and GCC builds passed at 12 jobs. Final build peak process-tree/single-process RSS was
2,697,676/450,248 KiB (Clang) and 4,570,704/897,024 KiB (GCC). The final evidence runner's maximum
single-process RSS was 583,736 KiB. All runs used CPUs 0–11 and stayed below the per-run limit; no
governor or system changes were made.
## Failed and retried runs
- An initial snapshot invocation omitted `--stream-benchmark --stream-pipeline` and exited 2; adding
the required flags passed.
- Early Clang builds caught a `strates` member typo, then an audit initializer/type error. Both were
fixed; the final Clang builds passed.
- The first complete evidence pass exited 1 at boundary probing because the audit read the host
manager after the harness had released it. Dispatch provenance was moved to Core's live selector;
the final audits passed.
- One GCC build wrapper was interrupted (exit 130) while diagnosing an empty progress log, then
rerun successfully. No runtime/hash run timed out or exceeded 15 minutes, and no L19 hash mismatch
remained.
## Owner note
This records the present strata and confirms the selected ceiling → content → bedrock model. FI still
has no floor in v3; SurfaceWorld has no volumetric floor or separate ceiling; the 8 m / 4 m dispatch
conversions leave a 60 m FI-prototype gap answered by analytic fallback. Core currently ignores the
configured transition blend at these interfaces. Bedrock and ceiling protection remain explicit
options with diggable defaults. This round changes no world output.
The Unreal adapter adds only a separate `resolved_layout` JSON field beside `world_assembly`; that
small edit could not be compiled on this Linux machine. No async path, density evaluator, hash input,
or recipe version changed. No commit, push, or stash was made.
## Orchestrator review (Claude)
- Merged: read-only snapshot + validator, no world change (28 hash runs and 14 crossing runs equal L19;
cost within noise). The Unreal adapter gains a 193-line `resolved_layout` export beside
`world_assembly`. It is export-only, but UNCOMPILED here; it must be built on the owner PC.
- Key facts for the owner: the authored params put the SW top at −60 m (4 m owner chunks), Core
builds SW at −120…−632 m (8 m conversion); the 60 m between FI and SW is unowned and answered by
the analytic FloatingIslands fallback as solid. No strate has an active bedrock band; SW has no
ceiling band (mesh fallback only); configured Gradient transitions are ignored by Core.
- To check next: whether the "ledges" ground seen under the islands is this fallback solid in the
unowned gap rather than SW terrain (L19 attributed them to SW at about −60…−73 m).
@@ -0,0 +1,165 @@
#!/usr/bin/env python3
"""Constrained L21 snapshot, output-parity, crossing, and off-cost evidence."""
import os
import re
import signal
import statistics
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/linux21"
OUT.mkdir(parents=True, exist_ok=True)
if not os.sched_getaffinity(0).issubset(set(range(12))):
raise SystemExit("run under taskset -c 0-11")
BIN = {
"clang-off": ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-linux21-clang",
"gcc-default": ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-linux21-gcc",
}
OLD_CLANG = ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-linux19-clang"
OLD_GCC = ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-linux19-gcc"
DATA = ROOT / "Standalone/data/owner_world.json"
HASH_ROW = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M)
LODS = [(1, 1), (8, 1), (12, 1), (12, 2), (12, 3), (12, 4), (12, 5)]
RECIPES = {
"surface-world": "0,-35,-487.94,0,-22",
"floating-islands": "-22,-19,-22.8,0,-4",
}
results = []
def launch(name, argv, timeout=900):
logfile = OUT / f"{name}.log"
command = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", *map(str, argv)]
started = time.monotonic()
peak_tree = 0
peak_process = 0
timed_out = False
with logfile.open("w", encoding="utf-8") as stream:
process = subprocess.Popen(command, stdout=stream, stderr=subprocess.STDOUT,
start_new_session=True)
while process.poll() is None:
pending, seen, total = [process.pid], set(), 0
while pending:
pid = pending.pop()
if pid in seen:
continue
seen.add(pid)
try:
pending.extend(int(x) for x in Path(f"/proc/{pid}/task/{pid}/children").read_text().split())
values = {}
for line in Path(f"/proc/{pid}/status").read_text().splitlines():
if line.startswith(("VmRSS:", "VmHWM:")):
key, amount, *_ = line.split()
values[key] = int(amount)
total += values.get("VmRSS:", 0)
peak_process = max(peak_process, values.get("VmRSS:", 0), values.get("VmHWM:", 0))
except (FileNotFoundError, PermissionError, ProcessLookupError, ValueError):
pass
peak_tree = max(peak_tree, total)
if time.monotonic() - started > timeout:
os.killpg(process.pid, signal.SIGTERM)
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
os.killpg(process.pid, signal.SIGKILL)
process.wait()
timed_out = True
break
time.sleep(0.1)
code = process.wait()
elapsed = time.monotonic() - started
rows = HASH_ROW.findall(logfile.read_text(encoding="utf-8", errors="replace"))
results.append((name, code, elapsed, peak_process, peak_tree, timed_out, len(rows)))
print(f"[L21Run] {name} exit={code} seconds={elapsed:.3f} peak_process_rss_kib={peak_process} "
f"peak_tree_rss_kib={peak_tree} hash_rows={len(rows)} timed_out={str(timed_out).lower()}", flush=True)
return logfile
def base_args(binary, recipe, workers, hash_output=False, crossing=False):
args = [binary, DATA, "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
"--force-generate", "--clip-radius=3", "--max-clip-level=8", f"--workers={workers}",
f"--camera={RECIPES[recipe]}", f"--recipe={recipe}"]
if hash_output:
args.append("--stream-hash")
if crossing:
args += ["--camera-step=24,0,0", "--region-crossing"]
return args
# Plan-time identities and canonical serialization at W1/W8/W12, both field recipes.
snapshots = {}
for recipe in RECIPES:
for workers, repeat in [(1, 1), (8, 1), (12, 1)]:
path = OUT / f"snapshot-{recipe}-w{workers}-r{repeat}.json"
args = [BIN["clang-off"], DATA, "--world-assembler-prototype", "--stream-benchmark",
"--stream-pipeline", f"--recipe={recipe}", f"--workers={workers}",
f"--resolved-layout-output={path}", "--resolved-layout-only"]
log = launch(f"snapshot-{recipe}-w{workers}-r{repeat}", args)
if results[-1][1] != 0:
raise SystemExit(f"snapshot plan failed: {log}")
snapshots[(recipe, workers)] = path.read_bytes()
if len({snapshots[(recipe, workers)] for workers in (1, 8, 12)}) != 1:
raise SystemExit(f"snapshot serialization changed with worker count: {recipe}")
print(f"[L21SnapshotIdentity] recipe={recipe} worker_counts=1,8,12 canonical_bytes=identical status=PASS", flush=True)
# Full matrix. Every row is compared against the L19 W12x5 reference.
for recipe in RECIPES:
for compiler, binary in BIN.items():
for workers, repeat in LODS:
name = f"matrix-{recipe}-{compiler}-w{workers}-r{repeat}"
log = launch(name, base_args(binary, recipe, workers, hash_output=True))
rows = HASH_ROW.findall(log.read_text(encoding="utf-8", errors="replace"))
reference_name = f"{recipe}-{compiler}-w12-r5.log"
reference = ROOT / "Saved/Linux/l19-matrix" / reference_name
expected = HASH_ROW.findall(reference.read_text(encoding="utf-8", errors="replace"))
if results[-1][1] != 0 or len(rows) != 12 or rows != expected:
print(f"[L21HashMismatch] {name} expected_rows={len(expected)} actual_rows={len(rows)}", flush=True)
raise SystemExit(1)
# The crossing matrix retains the 24 m two-view query proof on both compilers.
for compiler, binary in BIN.items():
for workers, repeat in LODS:
name = f"crossing-{compiler}-w{workers}-r{repeat}"
log = launch(name, base_args(binary, "surface-world", workers, hash_output=True, crossing=True))
rows = HASH_ROW.findall(log.read_text(encoding="utf-8", errors="replace"))
reference = ROOT / "Saved/Linux/l19-crossing" / f"{compiler}-w12-r5.log"
expected = HASH_ROW.findall(reference.read_text(encoding="utf-8", errors="replace"))
if results[-1][1] != 0 or len(rows) != 12 or rows != expected:
print(f"[L21CrossingHashMismatch] {name} expected_rows={len(expected)} actual_rows={len(rows)}", flush=True)
raise SystemExit(1)
# Five interleaved W12 pairs per recipe, hashing disabled. Alternate order by pair to reduce drift.
off_pairs = {recipe: {"old": [], "new": []} for recipe in RECIPES}
for recipe in RECIPES:
for pair in range(1, 6):
order = [("old", OLD_CLANG), ("new", BIN["clang-off"])] if pair % 2 else [("new", BIN["clang-off"]), ("old", OLD_CLANG)]
for label, binary in order:
name = f"offcost-{recipe}-pair{pair}-{label}"
log = launch(name, base_args(binary, recipe, 12, hash_output=False), timeout=900)
if results[-1][1] != 0:
raise SystemExit(f"hashing-off cost run failed: {log}")
off_pairs[recipe][label].append(results[-1][2])
print(f"[L21OffCostPair] recipe={recipe} pair={pair} old_seconds={off_pairs[recipe]['old'][-1]:.3f} "
f"new_seconds={off_pairs[recipe]['new'][-1]:.3f}", flush=True)
for recipe, pair in off_pairs.items():
old = statistics.median(pair["old"])
new = statistics.median(pair["new"])
print(f"[L21OffCostSummary] recipe={recipe} pairs=5 median_old_seconds={old:.3f} "
f"median_new_seconds={new:.3f} delta_percent={(new-old)/old*100.0:.2f}", flush=True)
# Query the real compiled Core field at every distinct recorded stratum/band endpoint.
for recipe in RECIPES:
name = f"boundary-probes-{recipe}"
args = base_args(BIN["clang-off"], recipe, 12, hash_output=False)
args += ["--audit-resolved-layout-boundaries"]
log = launch(name, args)
if results[-1][1] != 0:
raise SystemExit(f"Core boundary probes failed: {log}")
print(f"[L21EvidenceSummary] snapshots=6 matrix=28 crossing=14 off_cost_pairs=10 boundary_audits=2 status=PASS", flush=True)
for name, code, elapsed, rss, tree, timed_out, rows in results:
print(f"[L21RunDetail] {name} exit={code} seconds={elapsed:.3f} peak_process_rss_kib={rss} "
f"peak_tree_rss_kib={tree} hash_rows={rows} timed_out={str(timed_out).lower()}", flush=True)
+58 -1
View File
@@ -63,6 +63,9 @@ namespace
float CameraYawDegrees=0.0f;
float CameraPitchDegrees=0.0f;
std::filesystem::path MeshExportPath;
std::filesystem::path ResolvedLayoutOutputPath;
bool ResolvedLayoutOnly=false;
bool AuditResolvedLayoutBoundaries=false;
};
bool ParseInteger(std::string_view text,int& output)
@@ -117,6 +120,9 @@ namespace
" --mesh-export=FILE (write the exact generated tile meshes for offline rendering)\n"
" --profile-column-overlap --far-horizon-lod8-step=N --force-generate\n"
" --seed=N --recipe=surface-world|floating-islands\n"
" --resolved-layout-output=FILE (canonical plan-time layout snapshot)\n"
" --resolved-layout-only (exit after plan and snapshot validation)\n"
" --audit-resolved-layout-boundaries (query Core at each recorded endpoint)\n"
" --auto-surface-camera (place the 27-tile cube on this seed's surface)\n"
" --mesh-coverage (report non-empty tiles and indexed triangles)\n"
" --screen-space-gate (measure display error and historical negative controls)\n"
@@ -134,6 +140,8 @@ namespace
return false;
}
if(arg=="--world-assembler-prototype")options.WorldAssemblerPrototype=true;
else if(arg=="--resolved-layout-only")options.ResolvedLayoutOnly=true;
else if(arg=="--audit-resolved-layout-boundaries")options.AuditResolvedLayoutBoundaries=true;
else if(arg=="--stream-benchmark")options.StreamBenchmark=true;
else if(arg=="--stream-pipeline")options.StreamPipeline=true;
else if(arg=="--stream-hash")options.StreamHash=true;
@@ -155,6 +163,8 @@ namespace
else if(recipe=="floating-islands")options.FloatingIslandsRecipe=true;
else {std::fprintf(stderr,"Invalid --recipe value: %.*s\n",static_cast<int>(recipe.size()),recipe.data());return false;}
}
else if(arg.starts_with("--resolved-layout-output="))
options.ResolvedLayoutOutputPath=std::string(arg.substr(std::string_view("--resolved-layout-output=").size()));
else if(arg.starts_with("--seed="))
{if(!readInt("--seed=",options.SeedOverride))return false;options.HasSeedOverride=true;}
else if(arg.starts_with("--render-distance-chunks="))
@@ -314,6 +324,52 @@ int main(int argc,char** argv)
&&!StandaloneWorldAssemblyPrototype::AttachFloatingIslandWorldAssembly(
*ownerWorld,ownerJsonRoot,worldAssembly,error))
{std::fprintf(stderr,"Floating-island assembly setup failed: %s\n",error.c_str());return 2;}
VoxelForgeCore::ResolvedLayoutSnapshotV1 resolvedLayout;
const bool buildResolvedLayout=!options.ResolvedLayoutOutputPath.empty()
||options.AuditResolvedLayoutBoundaries||options.ResolvedLayoutOnly;
if(buildResolvedLayout)
{
const std::string_view variant=options.FloatingIslandsRecipe?"floating-islands":"surface-world";
if(!StandaloneWorldAssemblyPrototype::BuildResolvedLayoutSnapshot(
*ownerWorld,worldAssembly,variant,resolvedLayout,error))
{std::fprintf(stderr,"Resolved-layout snapshot failed: %s\n",error.c_str());return 2;}
const std::string layoutJson=resolvedLayout.ToJson();
if(!options.ResolvedLayoutOutputPath.empty())
{
const auto roundTrip=VoxelForgeCore::ResolvedLayoutSnapshotV1::FromJson(layoutJson,error);
if(!roundTrip||roundTrip->ToJson()!=layoutJson||roundTrip->stableIdentity!=resolvedLayout.stableIdentity)
{if(error.empty())error="resolved-layout canonical serialization did not round-trip";
std::fprintf(stderr,"Resolved-layout round trip failed: %s\n",error.c_str());return 2;}
if(!options.ResolvedLayoutOutputPath.parent_path().empty())
std::filesystem::create_directories(options.ResolvedLayoutOutputPath.parent_path());
std::ofstream output(options.ResolvedLayoutOutputPath,std::ios::binary);
if(!output){std::fprintf(stderr,"Could not write resolved-layout snapshot: %s\n",options.ResolvedLayoutOutputPath.c_str());return 2;}
output.write(layoutJson.data(),static_cast<std::streamsize>(layoutJson.size()));
if(!output){std::fprintf(stderr,"Resolved-layout snapshot write failed: %s\n",options.ResolvedLayoutOutputPath.c_str());return 2;}
}
const auto controls=VoxelForgeCore::AuditResolvedLayoutValidatorV1();
std::vector<VoxelForgeCore::ResolvedLayoutIssueV1> compatibilityIssues;
std::string compatibilityError;
const bool compatibilityAccepted=resolvedLayout.validate(
VoxelForgeCore::ResolvedLayoutValidationModeV1::compatibility,
compatibilityIssues,compatibilityError);
std::printf("[ResolvedLayoutSnapshot] schema=%u stable_identity=%s strata=%zu bytes=%zu round_trip=PASS\n",
resolvedLayout.schemaVersion,resolvedLayout.stableIdentity.c_str(),resolvedLayout.strates.size(),layoutJson.size());
std::printf("[ResolvedLayoutCompatibility] accepted=%s issues=%zu error=%s\n",
compatibilityAccepted?"true":"false",compatibilityIssues.size(),compatibilityError.c_str());
for(const auto& issue:compatibilityIssues)
std::printf("[ResolvedLayoutCompatibilityIssue] code=%s detail=%s\n",
issue.code.c_str(),issue.detail.c_str());
if(!compatibilityAccepted)
{std::fprintf(stderr,"Resolved-layout compatibility validation failed: %s\n",compatibilityError.c_str());return 2;}
std::printf("[ResolvedLayoutValidatorControls] rejected=%u/%u status=%s\n",
controls.controlsRejectedAsExpected,controls.controlsRun,controls.passed?"PASS":"FAIL");
if(!controls.passed)
{for(const auto& failure:controls.failures)std::printf("[ResolvedLayoutValidatorControlFailure] %s %s\n",failure.code.c_str(),failure.detail.c_str());return 2;}
if(!options.ResolvedLayoutOutputPath.empty())
std::printf("[ResolvedLayoutSnapshotOutput] path=%s\n",options.ResolvedLayoutOutputPath.c_str());
if(options.ResolvedLayoutOnly)return 0;
}
if(options.AutoSurfaceCamera)
{
constexpr std::int64_t UnitsPerVoxel=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
@@ -377,5 +433,6 @@ int main(int argc,char** argv)
cameraStepVoxels,options.AuditUniformBlockProofs,options.ProfileLodWork,
options.RegionCrossing,options.AuditTileShapeReadiness,
options.DiagnosticSlowShapeCompileMs,options.AuditBasePageEquivalence,
options.AuditRouteParity);
options.AuditRouteParity,options.AuditResolvedLayoutBoundaries,
buildResolvedLayout?&resolvedLayout:nullptr);
}
+86 -1
View File
@@ -253,7 +253,9 @@ namespace StandaloneStreamBenchmark
bool bAuditUniformBlockProofs=false,bool bReportLodWorkProfile=false,
bool bRegionCrossing=false,
bool bAuditTileShapeReadiness=false,int DiagnosticSlowShapeCompileMs=0,
bool bAuditBasePageEquivalence=false,bool bAuditRouteParity=false)
bool bAuditBasePageEquivalence=false,bool bAuditRouteParity=false,
bool bAuditResolvedLayoutBoundaries=false,
const VoxelForgeCore::ResolvedLayoutSnapshotV1* ResolvedLayout=nullptr)
{
using Clock=std::chrono::steady_clock;
FStandaloneOwnerWorld& World=*OwnerWorld;
@@ -438,6 +440,89 @@ namespace StandaloneStreamBenchmark
Streamer.Stop();
std::fprintf(stderr,"[StreamPipeline] full shape build failed: %s\n",BuildError.c_str());return 2;
}
if(bAuditResolvedLayoutBoundaries)
{
if(ResolvedLayout==nullptr)
{Streamer.Stop();std::fprintf(stderr,"[ResolvedLayoutProbe] missing plan-time snapshot\n");return 2;}
std::vector<std::int64_t> endpoints;
for(const auto& Stratum:ResolvedLayout->strates)
{
endpoints.push_back(Stratum.interiorBottomMicrometres);
endpoints.push_back(Stratum.interiorTopMicrometres);
endpoints.push_back(Stratum.ceiling.bottomMicrometres);
endpoints.push_back(Stratum.ceiling.topMicrometres);
endpoints.push_back(Stratum.bedrock.bottomMicrometres);
endpoints.push_back(Stratum.bedrock.topMicrometres);
}
for(std::size_t StratumIndex=0;StratumIndex+1<ResolvedLayout->strates.size();++StratumIndex)
{
const auto& Upper=ResolvedLayout->strates[StratumIndex];
if(Upper.transitionMode=="Hard"||Upper.transitionWidthMicrometres<=0)continue;
endpoints.push_back(Upper.interiorBottomMicrometres-Upper.transitionWidthMicrometres);
endpoints.push_back(Upper.interiorBottomMicrometres+Upper.transitionWidthMicrometres);
}
std::sort(endpoints.begin(),endpoints.end());
endpoints.erase(std::unique(endpoints.begin(),endpoints.end()),endpoints.end());
std::uint64_t probes=0,disagreements=0;
const double CoreVoxelMicrometres=std::max<std::uint32_t>(1,World.CoreVoxelSizeMicrons);
const auto expectedAt=[&](std::int64_t zMicrometres)
{
std::vector<std::string> candidates;
for(const auto& Stratum:ResolvedLayout->strates)
{
const auto contains=[zMicrometres](const VoxelForgeCore::ResolvedLayoutBandV1& Band)
{return Band.presentInCurrentField&&zMicrometres>=Band.bottomMicrometres
&&zMicrometres<Band.topMicrometres;};
if(contains(Stratum.ceiling))candidates.push_back(Stratum.generatorKind+"/ceiling");
if(contains(Stratum.content))candidates.push_back(Stratum.generatorKind+"/content");
if(contains(Stratum.bedrock))candidates.push_back(Stratum.generatorKind+"/bedrock");
}
return candidates;
};
const std::array<std::int64_t,3> offsets{{
-static_cast<std::int64_t>(World.CoreVoxelSizeMicrons),0,
static_cast<std::int64_t>(World.CoreVoxelSizeMicrons)}};
for(const std::int64_t Endpoint:endpoints)
for(const std::int64_t Offset:offsets)
{
const std::int64_t zMicrometres=Endpoint+Offset;
const double zVoxel=static_cast<double>(zMicrometres)/CoreVoxelMicrometres;
const VoxelForgeCore::Vec3d position{0.0,0.0,zVoxel};
const std::string actual=Shape.densityDispatchPathAt(position);
const auto expected=expectedAt(zMicrometres);
std::string expectedLabel;
std::vector<std::string> expectedGenerators;
for(const auto& Candidate:expected)
{
if(!expectedLabel.empty())expectedLabel+=',';
expectedLabel+=Candidate;
const auto Separator=Candidate.find('/');
const std::string Kind=Candidate.substr(0,Separator);
if(std::find(expectedGenerators.begin(),expectedGenerators.end(),Kind)==expectedGenerators.end())
expectedGenerators.push_back(Kind);
}
if(expected.empty())expectedLabel="uncovered";
std::string actualGenerator;
if(actual=="SurfaceWorld-native"||actual=="SurfaceWorld-legacy")actualGenerator="SurfaceWorld";
else if(actual=="FloatingIslands-native")actualGenerator="FloatingIslands";
else if(actual.rfind("compiled-analytic/",0)==0)actualGenerator=actual.substr(18);
const bool mismatch=expected.empty()
?actual!="compiled-analytic/fallback"
:std::find(expectedGenerators.begin(),expectedGenerators.end(),actualGenerator)==expectedGenerators.end();
const float density=Shape.densityAt(position);
const bool solid=density<0.0f;
++probes;disagreements+=mismatch?1u:0u;
std::printf("[ResolvedLayoutProbe] endpoint_um=%lld offset_um=%lld z_m=%.3f expected=%s actual=%s density=%.7g occupancy=%s disagreement=%s\n",
static_cast<long long>(Endpoint),static_cast<long long>(Offset),
static_cast<double>(zMicrometres)/1000000.0,expectedLabel.c_str(),actual.c_str(),density,
solid?"solid":"air",mismatch?"YES":"no");
}
std::printf("[ResolvedLayoutProbeSummary] probes=%llu disagreements=%llu status=%s\n",
static_cast<unsigned long long>(probes),static_cast<unsigned long long>(disagreements),
disagreements==0?"PASS":"DEVIATIONS_RECORDED");
Streamer.Stop();
return 0;
}
const auto ShapeReady=Clock::now();
const double ShapeSeconds=std::chrono::duration<double>(ShapeReady-ShapeBuildStart).count();
if(bAuditTileShapeReadiness)
+157
View File
@@ -525,4 +525,161 @@ namespace StandaloneWorldAssemblyPrototype
return true;
}
inline const char* GeneratorKind(ECaveGeneratorType type)
{
switch(type)
{
case ECaveGeneratorType::TunnelNetwork:return "TunnelNetwork";
case ECaveGeneratorType::FlatPlain:return "FlatPlain";
case ECaveGeneratorType::CrystalChamber:return "CrystalChamber";
case ECaveGeneratorType::Maze:return "Maze";
case ECaveGeneratorType::SurfaceWorld:return "SurfaceWorld";
case ECaveGeneratorType::VerticalShafts:return "VerticalShafts";
case ECaveGeneratorType::FloatingIslands:return "FloatingIslands";
case ECaveGeneratorType::Underwater:return "Underwater";
}
return "Unknown";
}
inline const char* TransitionKind(EVoxelStrateTransition type)
{
switch(type)
{
case EVoxelStrateTransition::Gradient:return "Gradient";
case EVoxelStrateTransition::Hard:return "Hard";
case EVoxelStrateTransition::Interleaved:return "Interleaved";
}
return "Unknown";
}
inline bool BuildResolvedLayoutSnapshot(const FStandaloneOwnerWorld& owner,
const VoxelForgeCore::WorldAssemblyManifest& assembly,std::string_view recipeVariant,
VoxelForgeCore::ResolvedLayoutSnapshotV1& out,std::string& error)
{
using namespace VoxelForgeCore;
if(!owner.Manager){error="resolved layout builder requires the initialized director";return false;}
(void)recipeVariant;
out={};out.worldIdentity="owner-world/seed/"+std::to_string(owner.Seed);
out.ownerVoxelSizeMicrometres=owner.OwnerVoxelSizeMicrons;
out.coreVoxelSizeMicrometres=owner.CoreVoxelSizeMicrons;
const std::int64_t coreMicrons=std::max<std::uint32_t>(1,owner.CoreVoxelSizeMicrons);
const std::int64_t managerChunkMicrons=CHUNK_SIZE*static_cast<std::int64_t>(owner.OwnerVoxelSizeMicrons);
const auto fixedToMicrons=[&](std::int64_t fixed)
{return static_cast<std::int64_t>(std::llround(static_cast<double>(fixed)
*static_cast<double>(coreMicrons)/(WorldAssemblySubvoxelsPerVoxel)));};
for(const FStrateSlot& slot:owner.Manager->GetLayout())
{
if(!slot.Definition)continue;
const auto type=owner.Manager->GetGeneratorTypeForChunk(FIntVector(0,0,slot.TopChunkZ));
ResolvedLayoutStratumV1 s;s.strateIndex=slot.StrateIndex;s.generatorKind=GeneratorKind(type);
s.stableId=out.worldIdentity+"/strate/"+std::to_string(slot.StrateIndex)
+"/generator/"+GeneratorKind(type);
s.recipeId=type==ECaveGeneratorType::SurfaceWorld?"SurfaceWorld.Heightfield2D"
:type==ECaveGeneratorType::FloatingIslands?"FloatingIslands.ClusterField":"legacy."+std::string(GeneratorKind(type));
s.recipeVersion=type==ECaveGeneratorType::SurfaceWorld?assembly.recipe.schemaVersion
:type==ECaveGeneratorType::FloatingIslands&&!assembly.floatingIslands.empty()
?assembly.floatingIslands.front().manifest.recipe.geometryVersion:0;
s.voxelSizeMicrometres=owner.CoreVoxelSizeMicrons;
s.latticeOriginMicrometres={0,0,0};
std::int64_t bottom=static_cast<std::int64_t>(slot.BottomChunkZ)*CHUNK_SIZE*coreMicrons;
std::int64_t top=static_cast<std::int64_t>(slot.TopChunkZ+1)*CHUNK_SIZE*coreMicrons;
if(type==ECaveGeneratorType::FloatingIslands)
{
const auto it=std::find_if(assembly.floatingIslands.begin(),assembly.floatingIslands.end(),
[&](const auto& p){return p.strateIndex==slot.StrateIndex;});
if(it!=assembly.floatingIslands.end())
{bottom=fixedToMicrons(it->manifest.recipe.layoutMinimumZSubvoxels);
top=fixedToMicrons(it->manifest.recipe.layoutMaximumZSubvoxels);}
}
s.interiorBottomMicrometres=bottom;s.interiorTopMicrometres=top;
s.content={"content",bottom,top,true,true,false,"current generator interior","none","none"};
s.transitionMode=TransitionKind(slot.Definition->TransitionType);
s.transitionBlendChunks=slot.Definition->TransitionBlendChunks;
s.transitionWidthMicrometres=static_cast<std::int64_t>(s.transitionBlendChunks)*managerChunkMicrons;
s.transitionWarpAmplitudeMicrometres=s.transitionMode=="Interleaved"
?2*managerChunkMicrons:0;
s.transitionInterpenetrationMicrometres=0;
s.transitionHonouredInCore=false;
s.transitionDispatchPath="upper strate owns lower interface; UVoxelStrateManager::GetGenerationParams can blend legacy vectors, but Core's compiled field selects per-strate/native recipe fields without transition blending";
s.managerLookup="UVoxelStrateManager::GetGeneratorTypeForChunk; upper strate TransitionType owns lower interface";
s.managerChunkWidthMicrometres=managerChunkMicrons;
s.dispatchChunkWidthMicrometres=type==ECaveGeneratorType::FloatingIslands
?static_cast<std::int64_t>(CHUNK_SIZE)*owner.OwnerVoxelSizeMicrons
:static_cast<std::int64_t>(CHUNK_SIZE)*coreMicrons;
if(type==ECaveGeneratorType::SurfaceWorld)
{s.boundDispatchPath="BuildSurfaceStratumPlan: (chunkZ*CHUNK_SIZE) Core voxels; 32 Core voxels per chunk";
s.queryDispatchPath="FStandaloneShapeWorld::NativeSurfaceDensityAt: floor(Z/CHUNK_SIZE), manager lookup; 32 Core voxels per chunk";}
else if(type==ECaveGeneratorType::FloatingIslands)
{s.boundDispatchPath="BuildFloatingIslandStratumPlan: owner chunk * 32 * owner/Core voxel ratio";
s.queryDispatchPath="FStandaloneShapeWorld::NativeFloatingIslandDensityAt: floor(Z/(32*owner/Core ratio)), manager lookup";}
else
{s.boundDispatchPath="legacy strata slot bounds scaled by Core chunk width";
s.queryDispatchPath="legacy Core field; manager lookup uses floor(Z/CHUNK_SIZE)";}
const std::int64_t legacySealMicrons=static_cast<std::int64_t>(std::llround(
std::max(0.0f,slot.Definition->GenerationParams.BoundarySealThickness)
*owner.OwnerVoxelSizeMicrons));
if(type==ECaveGeneratorType::FloatingIslands)
{
const auto it=std::find_if(assembly.floatingIslands.begin(),assembly.floatingIslands.end(),
[&](const auto& p){return p.strateIndex==slot.StrateIndex;});
const std::int64_t seal=it==assembly.floatingIslands.end()?0:fixedToMicrons(
it->manifest.recipe.boundarySealSubvoxels);
s.ceiling={"ceiling",top-seal,top,seal>0,true,false,
"v3 shared upper boundary density seal; one sided; inset from upper edge","upper/interior side","VF_ApplyUpperBoundarySeal"};
s.bedrock={"bedrock",bottom,bottom,false,true,false,
"no lower boundary seal in geometryVersion 3","none","none"};
if(it!=assembly.floatingIslands.end())
{
for(std::size_t n=0;n<it->manifest.plan.islands.size();++n)
{const auto& a=it->manifest.plan.islands[n];ResolvedLayoutAnchorV1 anchor;
anchor.kind="island_anchor";anchor.stableId="island/"+std::to_string(n);anchor.units="1/256 Core voxel";
anchor.values={a.centerSubvoxels[0],a.centerSubvoxels[1],a.centerSubvoxels[2],a.radiusSubvoxels,a.topHalfSubvoxels};
s.anchors.push_back(std::move(anchor));}
}
}
else if(type==ECaveGeneratorType::SurfaceWorld)
{
s.ceiling={"ceiling",top,top,false,true,false,
"no separate volumetric ceiling band; cap profile is internal to content","none",
"Heightfield2D cap profile + AppendStratumBoundaryCeilings fallback mesh"};
s.bedrock={"bedrock",bottom,bottom,false,true,false,"no lower bedrock band","none","none"};
for(const auto& p:assembly.recipe.biomes)
if(p.hasCapProfile)
{ResolvedLayoutAnchorV1 a;a.kind="cap_profile";a.stableId="biome/"+std::to_string(p.stableId);
a.units="1/256 Core voxel";a.values={p.capHeightSubvoxels,p.capUndulationSubvoxels,
p.capWavelengthSubvoxels,p.capDetailAmplitudeSubvoxels,p.capRidgeAmplitudeSubvoxels};s.anchors.push_back(std::move(a));}
const auto plan=std::find_if(assembly.plan.strates.begin(),assembly.plan.strates.end(),
[&](const auto& p){return p.strateIndex==slot.StrateIndex;});
if(plan!=assembly.plan.strates.end())
{
for(std::size_t n=0;n<plan->route.size();++n)
{const auto& p=plan->route[n];ResolvedLayoutAnchorV1 a;a.kind="route_point";a.stableId="route/"+std::to_string(n);
a.units="1/256 Core voxel";a.values={p.positionSubvoxels[0],p.positionSubvoxels[1],p.positionSubvoxels[2],p.radiusSubvoxels};
s.anchors.push_back(std::move(a));}
}
}
else
{
s.ceiling={"ceiling",top,top+legacySealMicrons,false,true,false,
"manager configures a two-sided legacy seal, but Core's compiled analytic field does not apply this density band",
"configured upper side","legacy VF_ApplyBoundarySeal; absent from current Core density path"};
s.bedrock={"bedrock",bottom-legacySealMicrons,bottom,false,true,false,
"manager configures a two-sided legacy seal, but Core's compiled analytic field does not apply this density band; breakable by default",
"configured lower side","legacy VF_ApplyBoundarySeal; absent from current Core density path"};
}
for(std::size_t n=0;n<owner.Manager->GetPassages().Num();++n)
{
const auto& passage=owner.Manager->GetPassages()[static_cast<int32>(n)];
if(passage.UpperStrateIndex!=slot.StrateIndex&&passage.LowerStrateIndex!=slot.StrateIndex)continue;
ResolvedLayoutAnchorV1 a;a.kind="passage";a.stableId="passage/"+std::to_string(n);
a.units="milli owner voxels";a.values={std::llround(passage.UpperPoint.X*1000.0),
std::llround(passage.UpperPoint.Y*1000.0),std::llround(passage.UpperPoint.Z*1000.0),
std::llround(passage.LowerPoint.X*1000.0),std::llround(passage.LowerPoint.Y*1000.0),
std::llround(passage.LowerPoint.Z*1000.0)};s.anchors.push_back(std::move(a));
}
out.strates.push_back(std::move(s));
}
return out.finalize(error);
}
} // namespace StandaloneWorldAssemblyPrototype