fix(shafts): the primordial law holds -- 0 trusted negatives across 16 seeds

Closes the VerticalShafts bug. Two remaining failures were investigated
and neither was a broken world.

PART A -- my measurement window was binding, not the world.
The window was a square centred on (0,0) with a radius, while mouths sit
up to ~200 voxels out in arbitrary directions, so a box holding both was
mostly empty space paid for at full price. Seed 6 at step 1 needed
16,515,072 cells and blew the cap; fitted to the two mouths it needs
6,553,344 and measures fine.

  seed  6  step 2  NOT_CONNECTED -> CONNECTED at doubled margin
  seed  6  step 1  NOT_CONNECTED -> CONNECTED at doubled margin
  seed 14  step 2  CONNECTED
  seed 14  step 1  CONNECTED

A fitted box can cut off a route that detours outside it, so every
negative is re-run at doubled margin. 5 of 16 were binding negatives and
all 5 flipped. TRUSTED NEGATIVES: 0. There is no evidence of a single
unescapable strate in 16 seeds.

PART B -- the drainage tree has no orphans, and a third cause existed.
  0 / 10,372 unreachable shaft paths (0% orphan rate)
  16 strict local minima, all caught by the direct-spine fallback
  neighbour fallback fired 0 times; emergency fallback 0
  91.8% of non-largest components are smaller than one shaft volume --
    they are roughness bubbles, not geometry

So a mouth could land in a noise bubble that is open but unreachable --
worse than useless, exactly the trap the law forbids.
VF_SuggestLandingPoint now returns the selected shaft AXIS, which is on
the drainage tree by construction.

⚠️ Codex found a third cause neither of us listed: tree capsules could
cross ledge bands, so a guaranteed connector could be blocked by a ledge.
Connector Z is now drawn from a deterministic ledge-free interval,
mirrored in the op stack.

⚠️ And an 8th error in my spec: "connect to any neighbour shaft" as a
fallback can create CYCLES -- a loop of shafts that drains nowhere and is
disconnected from the spine. The fallback must preserve strictly
decreasing origin-distance. Implemented that way.

  per-archetype law 6/6 · box-verdict violations 0 · stack equivalence
  bit-identical over 20,000 samples · sweep 45.3 -> 20.4 s
  cache 7.970 us rebuild, 0.073 us hot call (225-cell rolls on rebuild only)

Build clean, 21 succeeded / 0 failed, verified by me in VoxelM.log.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU
This commit is contained in:
Fr0zkaandClaude Opus 5 committed 2026-09-04 03:57:30 +02:00
1 parent 9d2324879d
commit 4f11ce81a4
10 files changed
+1813 -174

No files matched your search

@@ -672,8 +672,8 @@ namespace
(MaxLateralSnap + FMath::Max(Params.ShaftMaxRadius, 1.0f)) / Spacing) + 2;
float BestDistSq = FLT_MAX;
float BestX = 0.0f;
float BestY = 0.0f;
float BestAxisX = 0.0f;
float BestAxisY = 0.0f;
bool bFound = false;
int32 BestCellX = INT32_MAX;
int32 BestCellY = INT32_MAX;
@@ -711,17 +711,12 @@ namespace
continue;
}
if (Distance <= SafeRadius || Distance <= KINDA_SMALL_NUMBER)
{
BestX = WorldX;
BestY = WorldY;
}
else
{
const float Scale = SafeRadius / Distance;
BestX = ShaftX + DXWorld * Scale;
BestY = ShaftY + DYWorld * Scale;
}
// A VerticalShafts landing must identify the topology, not merely an open point
// inside its radius. The safe-radius distance still chooses the nearest confident
// site under the existing snap budget, but the returned XY is the selected shaft's
// exact axis so it is on the deterministic drainage tree by construction.
BestAxisX = ShaftX;
BestAxisY = ShaftY;
BestDistSq = DistSq;
BestCellX = CellX;
BestCellY = CellY;
@@ -729,13 +724,13 @@ namespace
}
}
if (!bFound || BestDistSq > MaxSnapSq || !FMath::IsFinite(BestX)
|| !FMath::IsFinite(BestY))
if (!bFound || BestDistSq > MaxSnapSq || !FMath::IsFinite(BestAxisX)
|| !FMath::IsFinite(BestAxisY))
{
return false;
}
OutPoint = FVector(BestX, BestY, LandingZ);
OutPoint = FVector(BestAxisX, BestAxisY, LandingZ);
return !OutPoint.ContainsNaN() && FMath::IsFinite(OutPoint.X)
&& FMath::IsFinite(OutPoint.Y) && FMath::IsFinite(OutPoint.Z);
}