feat(core): deterministic bounded SDF landmark stamps, off by default (L43); research R10

Stamp vocabulary v1 (carve ellipsoid/arch, fill pillar/dais) with smooth CSG and seeded relief; the
director resolves records (stable ID, strate, micrometre position, conservative bounds) from
hash(seed, strate, ID) with up to 512 candidates and rejects any that touch a passage mouth, walk corridor,
content face or ceiling/bedrock band; a stamp BVH skips tiles outside all bounds. No requests: canonical
JSON and owner hashes unchanged. --landmark-chamber-demo adds a SW chamber (buried; see review).
fast/medium/full PASS on clean builds. Research R10 (read-only): ore/resource channel design.
Review also records a pre-existing W1/W12 determinism mismatch at a non-spawn camera (L37+, not S14).

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 21:50:56 +02:00
1 parent 497e974178
commit 422dd7761a
12 files changed
+1138 -2

No files matched your search

+397 -1
View File
@@ -144,6 +144,145 @@ namespace
for(unsigned char c:value){hash^=c;hash*=1099511628211ull;}
return hash;
}
std::uint64_t LayoutStampMix(std::uint64_t value)
{
value^=value>>30;value*=0xbf58476d1ce4e5b9ull;
value^=value>>27;value*=0x94d049bb133111ebull;
return value^(value>>31);
}
std::uint64_t LayoutStampSeed(std::int32_t seed,std::int32_t strate,
std::string_view stableId)
{
std::uint64_t hash=14695981039346656037ull;
TransitionHashWord(hash,static_cast<std::uint32_t>(seed));
TransitionHashWord(hash,static_cast<std::uint32_t>(strate));
for(unsigned char c:stableId){hash^=c;hash*=1099511628211ull;}
return LayoutStampMix(hash);
}
std::uint64_t LayoutStampNext(std::uint64_t& state)
{state=LayoutStampMix(state+0x9e3779b97f4a7c15ull);return state;}
bool LayoutStampKindValid(ResolvedSdfStampKindV1 kind)
{
const auto value=static_cast<std::uint8_t>(kind);
return value>=static_cast<std::uint8_t>(ResolvedSdfStampKindV1::carveEllipsoid)
&&value<=static_cast<std::uint8_t>(ResolvedSdfStampKindV1::fillDais);
}
double LayoutStampPointSegmentDistance(const std::array<std::int64_t,3>& point,
const std::array<std::int64_t,3>& a,const std::array<std::int64_t,3>& b)
{
double lengthSquared=0.0,dot=0.0;
for(std::size_t axis=0;axis<3;++axis)
{
const double delta=static_cast<double>(b[axis])-a[axis];
lengthSquared+=delta*delta;
dot+=(static_cast<double>(point[axis])-a[axis])*delta;
}
const double t=lengthSquared>0.0?std::clamp(dot/lengthSquared,0.0,1.0):0.0;
double distanceSquared=0.0;
for(std::size_t axis=0;axis<3;++axis)
{
const double nearest=static_cast<double>(a[axis])
+t*(static_cast<double>(b[axis])-a[axis]);
const double delta=static_cast<double>(point[axis])-nearest;
distanceSquared+=delta*delta;
}
return std::sqrt(distanceSquared);
}
double LayoutStampBoundRadius(const ResolvedLayoutStampV1& stamp)
{
double radiusSquared=0.0;
for(std::size_t axis=0;axis<3;++axis)
{
const double extent=(static_cast<double>(stamp.boundsMaximumMicrometres[axis])
-stamp.boundsMinimumMicrometres[axis])*0.5;
radiusSquared+=extent*extent;
}
return std::sqrt(radiusSquared);
}
bool LayoutStampSafe(const ResolvedLayoutSnapshotV3& layout,
const ResolvedLayoutStampV1& stamp,std::string* reason=nullptr)
{
const auto strate=std::find_if(layout.strates.begin(),layout.strates.end(),
[&](const auto& value){return value.strateIndex==stamp.strateIndex;});
if(strate==layout.strates.end()||!strate->content.presentInCurrentField)
{if(reason)*reason="stamp strate has no current content band";return false;}
if(stamp.boundsMinimumMicrometres[2]<=strate->content.bottomMicrometres
||stamp.boundsMaximumMicrometres[2]>=strate->content.topMicrometres)
{if(reason)*reason="stamp bounds touch or cross the ceiling/bedrock content faces";return false;}
for(const auto* band:{&strate->ceiling,&strate->bedrock})
if(band->presentInCurrentField
&&stamp.boundsMinimumMicrometres[2]<band->topMicrometres
&&stamp.boundsMaximumMicrometres[2]>band->bottomMicrometres)
{if(reason)*reason="stamp bounds overlap a ceiling or bedrock band";return false;}
const double boundRadius=LayoutStampBoundRadius(stamp);
const double coreMicrometres=std::max<std::uint32_t>(1,layout.coreVoxelSizeMicrometres);
constexpr double RouteClearanceMicrometres=1000000.0;
const auto routeSafe=[&](const std::array<std::int64_t,3>& a,
const std::array<std::int64_t,3>& b,double radiusSubvoxels)
{
const double radius=radiusSubvoxels*coreMicrometres
/WorldAssemblySubvoxelsPerVoxel;
return LayoutStampPointSegmentDistance(stamp.positionMicrometres,a,b)
>boundRadius+radius+RouteClearanceMicrometres;
};
const auto qToMicrometres=[&](const std::array<std::int64_t,3>& q)
{
std::array<std::int64_t,3> result{};
for(std::size_t axis=0;axis<3;++axis)
result[axis]=static_cast<std::int64_t>(std::llround(
static_cast<double>(q[axis])*coreMicrometres
/WorldAssemblySubvoxelsPerVoxel));
return result;
};
for(const auto& passage:layout.passages)
{
if(passage.upperStrateIndex!=stamp.strateIndex
&&passage.lowerStrateIndex!=stamp.strateIndex)continue;
const auto upper=qToMicrometres(passage.upperMouthSubvoxels);
const auto lower=qToMicrometres(passage.lowerMouthSubvoxels);
const double mouthRadius=static_cast<double>(passage.mouthRadiusSubvoxels)
*coreMicrometres/WorldAssemblySubvoxelsPerVoxel;
if(LayoutStampPointSegmentDistance(stamp.positionMicrometres,upper,upper)
<=boundRadius+mouthRadius+RouteClearanceMicrometres
||LayoutStampPointSegmentDistance(stamp.positionMicrometres,lower,lower)
<=boundRadius+mouthRadius+RouteClearanceMicrometres)
{if(reason)*reason="stamp is inside a passage mouth safety volume";return false;}
for(std::size_t i=0;i+1<passage.controlPoints.size();++i)
{
const auto a=qToMicrometres(passage.controlPoints[i].positionSubvoxels);
const auto b=qToMicrometres(passage.controlPoints[i+1].positionSubvoxels);
const double radius=std::max(passage.controlPoints[i].radiusSubvoxels,
passage.controlPoints[i+1].radiusSubvoxels);
if(!routeSafe(a,b,radius))
{if(reason)*reason="stamp overlaps a resolved passage walk corridor";return false;}
}
}
std::vector<const ResolvedLayoutAnchorV2*> route;
for(const auto& anchor:strate->anchors)
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
route.push_back(&anchor);
for(std::size_t i=0;i<route.size();++i)
{
const auto makePoint=[&](const ResolvedLayoutAnchorV2& anchor)
{return std::array<std::int64_t,3>{
static_cast<std::int64_t>(std::llround(static_cast<double>(anchor.values[0])
*coreMicrometres/WorldAssemblySubvoxelsPerVoxel)),
static_cast<std::int64_t>(std::llround(static_cast<double>(anchor.values[1])
*coreMicrometres/WorldAssemblySubvoxelsPerVoxel)),
static_cast<std::int64_t>(std::llround(static_cast<double>(anchor.values[2])
*coreMicrometres/WorldAssemblySubvoxelsPerVoxel))};};
const auto a=makePoint(*route[i]);
const auto b=i+1<route.size()?makePoint(*route[i+1]):a;
const double radius=i+1<route.size()
?std::max(route[i]->values.size()>=4?route[i]->values[3]:0,
route[i+1]->values.size()>=4?route[i+1]->values[3]:0)
:route[i]->values.size()>=4?route[i]->values[3]:0;
if(!routeSafe(a,b,radius))
{if(reason)*reason="stamp overlaps a resolved strate walk route";return false;}
}
return true;
}
std::string LayoutHex(std::uint64_t value)
{std::ostringstream out;out<<std::hex<<std::setfill('0')<<std::setw(16)<<value;return out.str();}
std::string LayoutBandJson(const ResolvedLayoutBandV2& band)
@@ -238,7 +377,34 @@ namespace
}
out<<"]}";
}
out<<"]}";return out.str();
out<<']';
if(!s.stamps.empty())
{
out<<",\"stamp_vocabulary_version\":"<<s.stampVocabularyVersion
<<",\"stamps\":[";
for(std::size_t i=0;i<s.stamps.size();++i)
{
if(i)out<<',';const auto& stamp=s.stamps[i];
out<<"{\"stable_id\":"<<LayoutEscape(stamp.stableId)
<<",\"strate_index\":"<<stamp.strateIndex
<<",\"kind\":"<<static_cast<unsigned>(stamp.kind)
<<",\"position_um\":["<<stamp.positionMicrometres[0]<<','
<<stamp.positionMicrometres[1]<<','<<stamp.positionMicrometres[2]
<<"],\"bounds_min_um\":["<<stamp.boundsMinimumMicrometres[0]<<','
<<stamp.boundsMinimumMicrometres[1]<<','<<stamp.boundsMinimumMicrometres[2]
<<"],\"bounds_max_um\":["<<stamp.boundsMaximumMicrometres[0]<<','
<<stamp.boundsMaximumMicrometres[1]<<','<<stamp.boundsMaximumMicrometres[2]
<<"],\"half_extents_um\":["<<stamp.halfExtentsMicrometres[0]<<','
<<stamp.halfExtentsMicrometres[1]<<','<<stamp.halfExtentsMicrometres[2]
<<"],\"smooth_width_um\":"<<stamp.smoothWidthMicrometres
<<",\"irregularity_amplitude_um\":"<<stamp.irregularityAmplitudeMicrometres
<<",\"irregularity_wavelength_um\":"<<stamp.irregularityWavelengthMicrometres
<<",\"irregularity_seed\":"<<stamp.irregularitySeed
<<",\"yaw_quarter_turns\":"<<static_cast<unsigned>(stamp.yawQuarterTurns)<<'}';
}
out<<']';
}
out<<'}';return out.str();
}
std::int64_t LayoutInt(const VFJson::Value& obj,std::string_view key)
{return obj.Get(key).Integer();}
@@ -659,6 +825,50 @@ bool ResolvedLayoutSnapshotV3::validate(ResolvedLayoutValidationModeV3 mode,
add("passage_grade",passage.stableId+" is not strictly descending or exceeds the 15 degree grade limit");
}
}
if(stamps.empty())
{
if(stampVocabularyVersion!=0)
add("stamp_vocabulary_version","stamp vocabulary version is set without any stamp records");
}
else if(stampVocabularyVersion!=ResolvedLayoutStampVocabularyVersionV1)
add("stamp_vocabulary_version","resolved stamps require vocabulary version 1");
std::vector<std::string> stampIds;
for(const auto& stamp:stamps)
{
if(stamp.stableId.empty()
||std::find(stampIds.begin(),stampIds.end(),stamp.stableId)!=stampIds.end())
add("stamp_identity","stamp has an empty or duplicate stable identity");
else stampIds.push_back(stamp.stableId);
if(!LayoutStampKindValid(stamp.kind)||stamp.yawQuarterTurns>3)
add("stamp_kind","stamp has an unsupported kind or orientation");
bool validExtents=true;
for(const auto extent:stamp.halfExtentsMicrometres)
validExtents=validExtents&&extent>=500000&&extent<=100000000;
if(!validExtents||stamp.smoothWidthMicrometres<0
||stamp.smoothWidthMicrometres>10000000
||stamp.irregularityAmplitudeMicrometres<0
||stamp.irregularityAmplitudeMicrometres>10000000
||stamp.irregularityWavelengthMicrometres<0
||stamp.irregularityWavelengthMicrometres>100000000
||(stamp.irregularityAmplitudeMicrometres>0
&&stamp.irregularityWavelengthMicrometres<=0))
add("stamp_parameters",stamp.stableId+" has invalid or unbounded geometry parameters");
const std::int64_t pad=stamp.smoothWidthMicrometres
+stamp.irregularityAmplitudeMicrometres;
const std::array<std::int64_t,3> extents={
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad,
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad,
stamp.halfExtentsMicrometres[2]+pad};
for(std::size_t axis=0;axis<3;++axis)
if(stamp.boundsMinimumMicrometres[axis]
!=stamp.positionMicrometres[axis]-extents[axis]
||stamp.boundsMaximumMicrometres[axis]
!=stamp.positionMicrometres[axis]+extents[axis])
add("stamp_bounds",stamp.stableId+" conservative bounds do not match its parameters");
std::string safetyReason;
if(!LayoutStampSafe(*this,stamp,&safetyReason))
add("stamp_placement",stamp.stableId+" is unsafe: "+safetyReason);
}
if(strict&&!issues.empty()){error="strict resolved-layout validation rejected "+issues.front().code;return false;}
return true;
}
@@ -674,6 +884,7 @@ std::optional<ResolvedLayoutSnapshotV3> ResolvedLayoutSnapshotV3::FromJson(
s.coreVoxelSizeMicrometres=static_cast<std::uint32_t>(LayoutInt(root,"core_voxel_size_um"));
s.strateLayoutChunkSizeMicrometres=static_cast<std::uint32_t>(LayoutInt(root,"strate_layout_chunk_size_um"));
s.strateLayoutChunkWidthSubvoxels=LayoutInt(root,"strate_layout_chunk_width_subvoxels");
s.stampVocabularyVersion=static_cast<std::uint32_t>(LayoutInt(root,"stamp_vocabulary_version"));
for(const auto& v:root.Get("strates").AsArray())
{
ResolvedLayoutStratumV2 x;x.stableId=LayoutString(v,"stable_id");
@@ -721,12 +932,197 @@ std::optional<ResolvedLayoutSnapshotV3> ResolvedLayoutSnapshotV3::FromJson(
}
s.passages.push_back(std::move(p));
}
for(const auto& v:root.Get("stamps").AsArray())
{
ResolvedLayoutStampV1 stamp;stamp.stableId=LayoutString(v,"stable_id");
stamp.strateIndex=static_cast<std::int32_t>(LayoutInt(v,"strate_index"));
stamp.kind=static_cast<ResolvedSdfStampKindV1>(LayoutInt(v,"kind"));
const auto readTriplet=[&](std::string_view key,std::array<std::int64_t,3>& target)
{
const auto& values=v.Get(key).AsArray();
for(std::size_t axis=0;axis<3&&axis<values.size();++axis)
target[axis]=values[axis].Integer();
};
readTriplet("position_um",stamp.positionMicrometres);
readTriplet("bounds_min_um",stamp.boundsMinimumMicrometres);
readTriplet("bounds_max_um",stamp.boundsMaximumMicrometres);
readTriplet("half_extents_um",stamp.halfExtentsMicrometres);
stamp.smoothWidthMicrometres=LayoutInt(v,"smooth_width_um");
stamp.irregularityAmplitudeMicrometres=LayoutInt(v,"irregularity_amplitude_um");
stamp.irregularityWavelengthMicrometres=LayoutInt(v,"irregularity_wavelength_um");
stamp.irregularitySeed=static_cast<std::uint64_t>(LayoutInt(v,"irregularity_seed"));
stamp.yawQuarterTurns=static_cast<std::uint8_t>(LayoutInt(v,"yaw_quarter_turns"));
s.stamps.push_back(std::move(stamp));
}
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;
}
bool ResolveResolvedLayoutStampsV1(ResolvedLayoutSnapshotV3& layout,std::int32_t seed,
std::span<const ResolvedLayoutStampRequestV1> requests,std::string& error)
{
error.clear();
if(requests.empty())
{
ResolvedLayoutSnapshotV3 candidate=layout;
candidate.stampVocabularyVersion=0;candidate.stamps.clear();
if(!candidate.finalize(error))return false;
layout=std::move(candidate);return true;
}
std::vector<ResolvedLayoutStampRequestV1> ordered(requests.begin(),requests.end());
std::sort(ordered.begin(),ordered.end(),[](const auto& a,const auto& b)
{return a.stableId<b.stableId;});
ResolvedLayoutSnapshotV3 candidate=layout;
candidate.stampVocabularyVersion=ResolvedLayoutStampVocabularyVersionV1;
candidate.stamps.clear();candidate.stamps.reserve(ordered.size());
for(std::size_t requestIndex=0;requestIndex<ordered.size();++requestIndex)
{
const auto& request=ordered[requestIndex];
if(request.stableId.empty()||(requestIndex>0
&&ordered[requestIndex-1].stableId==request.stableId))
{error="stamp requests require non-empty unique stable IDs";return false;}
if(!LayoutStampKindValid(request.kind)||request.yawQuarterTurns>3
||request.placementRadiusMicrometres<0
||request.placementRadiusMicrometres>100000000
||request.smoothWidthMicrometres<0||request.smoothWidthMicrometres>10000000
||request.irregularityAmplitudeMicrometres<0
||request.irregularityAmplitudeMicrometres>10000000
||request.irregularityWavelengthMicrometres<0
||request.irregularityWavelengthMicrometres>100000000
||(request.irregularityAmplitudeMicrometres>0
&&request.irregularityWavelengthMicrometres<=0))
{error="stamp request "+request.stableId+" has invalid or unbounded parameters";return false;}
if(std::any_of(request.halfExtentsMicrometres.begin(),request.halfExtentsMicrometres.end(),
[](std::int64_t extent){return extent<500000||extent>100000000;}))
{error="stamp request "+request.stableId+" has an extent outside 0.5..100 m";return false;}
const auto stratum=std::find_if(candidate.strates.begin(),candidate.strates.end(),
[&](const auto& value){return value.strateIndex==request.strateIndex;});
if(stratum==candidate.strates.end())
{error="stamp request "+request.stableId+" names an unknown strate";return false;}
for(const auto coordinate:request.anchorPositionMicrometres)
if(coordinate<-1000000000000ll||coordinate>1000000000000ll)
{error="stamp request "+request.stableId+" has an unbounded anchor";return false;}
// The shared JSON value type stores numbers as IEEE-754 doubles; keep the
// serialized seed in its exact integer range so the canonical round trip holds.
const std::uint64_t baseSeed=LayoutStampSeed(seed,request.strateIndex,request.stableId)
&0x001fffffffffffffull;
std::uint64_t state=baseSeed;
const auto randomOffset=[&](std::uint64_t bits)
{
const std::int64_t radius=request.placementRadiusMicrometres;
if(radius==0)return std::int64_t{0};
const std::uint64_t span=static_cast<std::uint64_t>(radius)*2+1;
return static_cast<std::int64_t>(bits%span)-radius;
};
bool placed=false;
for(std::uint32_t attempt=0;attempt<(request.placementRadiusMicrometres==0?1u:512u);++attempt)
{
ResolvedLayoutStampV1 stamp;stamp.stableId=request.stableId;
stamp.strateIndex=request.strateIndex;stamp.kind=request.kind;
stamp.halfExtentsMicrometres=request.halfExtentsMicrometres;
stamp.smoothWidthMicrometres=request.smoothWidthMicrometres;
stamp.irregularityAmplitudeMicrometres=request.irregularityAmplitudeMicrometres;
stamp.irregularityWavelengthMicrometres=request.irregularityWavelengthMicrometres;
stamp.irregularitySeed=baseSeed;stamp.yawQuarterTurns=request.yawQuarterTurns;
std::array<std::int64_t,3> offset{};
if(request.placementRadiusMicrometres>0)
{
offset={randomOffset(LayoutStampNext(state)),
randomOffset(LayoutStampNext(state)),
randomOffset(LayoutStampNext(state))/3};
const long double radius=static_cast<long double>(request.placementRadiusMicrometres);
const long double distanceSquared=static_cast<long double>(offset[0])*offset[0]
+static_cast<long double>(offset[1])*offset[1]
+static_cast<long double>(offset[2])*offset[2];
if(distanceSquared>radius*radius)continue;
}
for(std::size_t axis=0;axis<3;++axis)
stamp.positionMicrometres[axis]=request.anchorPositionMicrometres[axis]+offset[axis];
const std::int64_t pad=stamp.smoothWidthMicrometres
+stamp.irregularityAmplitudeMicrometres;
const std::array<std::int64_t,3> extents={
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?1:0]+pad,
stamp.halfExtentsMicrometres[stamp.yawQuarterTurns%2?0:1]+pad,
stamp.halfExtentsMicrometres[2]+pad};
for(std::size_t axis=0;axis<3;++axis)
{
stamp.boundsMinimumMicrometres[axis]=stamp.positionMicrometres[axis]-extents[axis];
stamp.boundsMaximumMicrometres[axis]=stamp.positionMicrometres[axis]+extents[axis];
}
if(!LayoutStampSafe(candidate,stamp))continue;
candidate.stamps.push_back(std::move(stamp));placed=true;break;
}
if(!placed)
{error="stamp request "+request.stableId+" has no deterministic passage-safe content placement";return false;}
}
if(!candidate.finalize(error))return false;
std::vector<ResolvedLayoutIssueV2> issues;std::string strictError;
if(!candidate.validate(ResolvedLayoutValidationModeV3::strict,issues,strictError))
{error="strict stamp placement validation failed: "+strictError;return false;}
layout=std::move(candidate);return true;
}
ResolvedLayoutStampPlacementAuditV1 AuditResolvedLayoutStampPlacementV1(
const ResolvedLayoutSnapshotV3& layout)
{
ResolvedLayoutStampPlacementAuditV1 result;
const auto makeControl=[&](const std::array<std::int64_t,3>& position,
std::int32_t strateIndex,std::array<std::int64_t,3> minimum,
std::array<std::int64_t,3> maximum,std::string id,
std::string_view expectedReason)
{
ResolvedLayoutSnapshotV3 candidate=layout;
ResolvedLayoutStampV1 stamp;stamp.stableId=std::move(id);
stamp.strateIndex=strateIndex;stamp.kind=ResolvedSdfStampKindV1::carveEllipsoid;
stamp.positionMicrometres=position;stamp.boundsMinimumMicrometres=minimum;
stamp.boundsMaximumMicrometres=maximum;
stamp.halfExtentsMicrometres={250000,250000,250000};
stamp.irregularitySeed=1;
candidate.stampVocabularyVersion=ResolvedLayoutStampVocabularyVersionV1;
candidate.stamps={stamp};
std::vector<ResolvedLayoutIssueV2> issues;std::string error;
++result.negativeControlsRun;
if(!candidate.validate(ResolvedLayoutValidationModeV3::strict,issues,error)
&&std::any_of(issues.begin(),issues.end(),[&](const auto& issue)
{return issue.code=="stamp_placement"
&&issue.detail.find(expectedReason)!=std::string::npos;}))
++result.negativeControlsRejected;
};
const auto passage=std::find_if(layout.passages.begin(),layout.passages.end(),
[](const auto& value){return value.controlPoints.size()>=2;});
if(passage!=layout.passages.end())
{
const double scale=static_cast<double>(layout.coreVoxelSizeMicrometres)
/WorldAssemblySubvoxelsPerVoxel;
const std::size_t routeControlIndex=passage->lowerMouthControlIndex>4
?passage->lowerMouthControlIndex-4:0;
std::array<std::int64_t,3> position{};
for(std::size_t axis=0;axis<3;++axis)
position[axis]=static_cast<std::int64_t>(std::llround(
passage->controlPoints[routeControlIndex].positionSubvoxels[axis]*scale));
makeControl(position,passage->lowerStrateIndex,
{position[0]-250000,position[1]-250000,position[2]-250000},
{position[0]+250000,position[1]+250000,position[2]+250000},
"negative-control/forced-on-route","resolved passage walk corridor");
}
const auto stratum=std::find_if(layout.strates.begin(),layout.strates.end(),
[](const auto& value){return value.content.presentInCurrentField;});
if(stratum!=layout.strates.end())
{
const std::array<std::int64_t,3> position={0,0,stratum->content.topMicrometres};
makeControl(position,stratum->strateIndex,
{position[0]-250000,position[1]-250000,position[2]-250000},
{position[0]+250000,position[1]+250000,position[2]+250000},
"negative-control/forced-into-ceiling-band","touch or cross the ceiling/bedrock");
}
result.passed=result.negativeControlsRun==2
&&result.negativeControlsRejected==result.negativeControlsRun;
return result;
}
bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t seed,
const std::vector<ResolvedLayoutPassageConfigV1>& configs,std::string& error)
{