The plateau was the tell. Roughness changed the component COUNT (it
manufactures noise pockets) but the giant component sat at ~0.22 in every
variant, and widening connectors past the proven roughness bound barely
moved it. That is a random graph below its percolation threshold: 0.6
sites, 0.35 bonds, and a 1.6-cell pair cutoff that drops many neighbour
pairs once jitter spreads them 1.7 (orthogonal) to 2.4 (diagonal) cells
apart.
So the lever was topology. Every shaft now emits a deterministic connector
to the nearest shaft STRICTLY closer to the origin, so chains drain inward
and terminate at the spine. The probabilistic connectors stay as texture
and loops -- the tree guarantees you can get out, the noise keeps it from
reading as a diagram.
Deliberately NOT tuned: raising CrossConnectChance/ShaftDensity/the cutoff
toward the percolation threshold buys a world connected at one seed and
shattered at the next, which is exactly the 1-in-16 behaviour we had. A
phase transition is not a knob.
seed 1337 components 30 -> 17, largest share .220 -> .975
16 seeds spine is the largest component in 16/16 (was 8/16)
largest share .58 - .9999
Seam safety, because a parent computed from a 3x3 window would differ
between chunks and the connector would exist in one and not the other:
collect over 7x7, emit only for the inner 3x3, whose 5x5 candidate windows
are then fully contained. 154 seam probes per path, 0 mismatches.
Box verdicts re-checked against the new air: 27 proved, 33 mixed,
0 violations. Stack mirror bit-identical over 20,000 samples.
Perf: 1.634 us forced rebuild, 0.100 us hot call -- the 49 rolls happen
only on cache rebuild, never per voxel.
⚠️ ACCEPTANCE STILL FAILS: arrival->departure 4/16 (was 1/16). Reported,
not tuned. With 97% of the air in one component, two mouths that both land
IN the field would essentially always connect -- so the remaining failure
is placement, not topology. Next.
Build clean, 20 succeeded / 0 warnings / 0 failed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bp7FxoQcSoiuhxjuLr6aBM
Jahni chose: make the (0,0) column join the shafts it passes, so
VerticalShafts behaves like the other seven archetypes. Built, and it
works as far as it goes -- the spine is now the LARGEST air component in
13 of 16 seeds (share up to 0.81, was 0.096 and never largest).
⚠️ IT DOES NOT MEET THE ACCEPTANCE CRITERION. arrival->departure is still
1/16. Reported as a failure rather than dressed up, because the criterion
was the measured law, not "the code was written". The test now prints
ACCEPTANCE arrival->departure: FAIL (1/16 seeds pass) so it cannot be
quietly forgotten.
Why it is insufficient, and it is structural: the spine only joins its own
3x3 cell neighbourhood, while passage mouths land 60-200 voxels from
(0,0). The departure network is unreachable from the spine in all 16
seeds. Joining the hub to its neighbours does not help if the rest of the
graph never reaches the hub.
Part A diagnosis (seed 1337, margin 0, step 2, radius 192):
baseline 30 components, largest .220
roughness 0 17 components, largest .226
connector radius 8 29 components, largest .229
H1 is real but partial: roughness fragments the space (13 of the 30
components are noise pockets), yet widening connectors past the proven
roughness bound barely moves it. So roughness is NOT what severs the
network -- the largest component sits at ~0.22 in every variant, which is
the signature of a graph below its percolation threshold. The lever is
topology, not radius. H2 (the hardcoded 1.6 pair cutoff) went untested.
Implementation notes: the spine is added ONLY as a connector endpoint, not
as a carving shaft -- VF_ApplyOriginSpine remains sole owner -- and is
excluded from ledge placement. Spine connectors use radius 6.625, above
the proven roughness supremum of 5.625 (sup|FBM| = 1.5, not 1.0).
SpineRadius is threaded through BuildVerticalShaftStack, not hardcoded.
Op-stack mirror bit-identical over 20,000 samples, 0 box-verdict
violations. LayoutOrderIndependence green.
Build clean, 19 succeeded / 0 warnings / 0 failed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bp7FxoQcSoiuhxjuLr6aBM
Commit 1ab8c0c reported Tier 1 working on the strength of a green suite and a
fixture reading 48/48. A million-seed sweep then showed the room query put the
landing point outside the selected room 92.795% of the time. Seven sampled
passages cannot see a systemic defect; the 48/48 was luck.
The cause was my instruction. I specced MaxLateralSnap = 0 for rooms and slabs
to "preserve existing placement", so the query found the nearest room and then
returned the CALLER's XY with that room's Z -- it located a room and aimed
beside it. Precisely the defect I had identified for Maze, VerticalShafts and
FloatingIslands, then exempted rooms from.
The function already computed the room's XY and threw it away. It now returns
it. A room's centre is inside its own room by construction, so this needs no
SDF evaluation and no warp handling -- and the centre also holds the largest
margin against the production warp, which displaces the field about 1.5 voxels:
decisive at a room's edge, irrelevant at its centre. Simpler and more robust
than the warped-SDF inside-proof I had been asking for.
Caves get a real RoomSpacing budget, because a room is an XY-sparse target just
like a maze corridor. Slabs correctly keep zero: their void band is
XY-continuous, so the requested XY is already inside it.
Room/slab rings go 38/48 to 32/32. But TunnelNetwork and Underwater now decline
entirely at the fixture seed -- with RoomDensity below 1 the nearest room is
often past one spacing, so they fall back to random reach. Honest, not landing.
Roughly 2x spacing would restore them at the cost of passages drifting from the
(0,0) spine, which is what makes them findable. Left untuned deliberately;
raising a number until coverage looks better is the move I twice told Codex not
to make.
One guard softened: the test asserted all four room/slab archetypes must answer
within seven sampled passages. That asserts a property of the sample, not the
code, and it failed on this fix, since a supported query is allowed to decline
on budget. Now reported rather than asserted. Vacuity, per-mouth ring and
footing checks, endpoint matching and the SurfaceWorld refusal all remain hard
failures.
Built clean; 17 succeeded, 0 warnings, 0 failed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DPUuCtn5zTLui6WybLbkNb
Tier 1. GeneratePassages placed every passage at a random angle, distance and
reach, never consulting the destination strate. The carved tube is air by
construction, so nothing looked wrong -- but whether the lower mouth joined the
destination's connected cave space was luck. A player could descend and arrive
in a sealed pocket. The primordial law was a hope.
VF_SuggestOpenPointZ is a pure free function of (archetype, params, seed, XY):
no operator stack, no StrateManager, no cache. That is deliberate. This runs
inside Initialize, where the layout is half-built and LayoutVersion is in
flight, so anything holding a manager pointer there is a re-entrancy trap.
Coverage is four archetypes of eight, and the number is the deliverable:
7 passages, 3 aimed at generator-confirmed open space with 48/48 ring samples
air, 4 falling back. The hole is not closed. It is measured, where this morning
it was invisible.
Two corrections from Codex, both mine and both would have shipped confident
nonsense: room placement is seeded by MakeStrateSeed, not the passage salt, so
my version would have queried a cave graph that does not exist; and slabs need
the world seed because that is what GetSlabDensity uses.
And one of mine caught in review: the first test sampled GetDensityAt at the
mouth and asserted air, which is true by construction because the passage carve
is a structural-post invariant. It could not fail. Replaced with a 16-point
ring outside the carve radius requiring 8/16 air -- a proxy for connectivity,
not a proof. The proof is a flood fill, which is Tier 2.
Logging: my first spec asked for a per-passage warning on fallback. It fired
572 times and turned 14 clean tests yellow, which is precisely the anti-pattern
OPSTACK-HANDOFF.md warns about -- a warning that always means "this is fine"
teaches people to ignore warnings. Now one sorted Log line per layout build.
Built clean, suite green: 17 succeeded, 0 with warnings, 0 failed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DPUuCtn5zTLui6WybLbkNb
Tier 0. Reordering Settings->StratePool in the editor used to change every
world in the game, because Initialize Fisher-Yates shuffled the array in
editor order. The pool is now sorted by stable soft-asset path before the
shuffle, so the layout is a pure function of (seed, pool contents as a SET).
The selection algorithm itself is untouched -- same Fisher-Yates, same cycling,
same FixedStrates handling, same Z ranges. Sorting by pointer would have looked
right and been load-order dependent, which is the trap here.
GeneratePassages walked one sequential FRandomStream across every strate, so
changing an early connection count shifted every later passage. Each draw is
now a salted VoxelHash of (seed, boundary index, connection index), with the
distributions preserved exactly -- ToFloat01 returns [0,1), so Lerp(Min,Max,t)
reproduces FRandRange precisely.
Codex implemented it and caught a real flaw in my spec: I asked for a test that
permutes the pool and asserts the passages match, but once the layout is
order-independent that test cannot fail whether or not the passage fix works --
the layout comes out identical, so even the old sequential stream would agree.
It added the perturbation that actually bites: change an early connection count
and verify every later boundary keeps its own values. It also contradicted me
on passage type being randomly drawn. It isn't, and it preserved that.
Built VoxelMEditor clean, then ran the suite headless: 16 succeeded, 0 failed,
0 not run. That also closes the thread OPSTACK-HANDOFF.md left open -- 4d33321
and 91585ea were built but never re-verified, and both acceptance conditions
are now met: violations 0 everywhere (12 of 40 TunnelNetwork tiles proved over
15972 brute-forced voxels), all equivalences green. No revert needed.
Expected: every seed now lays out differently than before. Accepted,
pre-content-lock.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DPUuCtn5zTLui6WybLbkNb
Function-static thread_local CP state previously trusted only chunk coordinates and each manager's locally-reused layout version, allowing a worker to carry params, biome context, CP_UseOpStack, and the built stack into another world. Allocate each generator a monotonic owner ID and add one uint64 comparison to the hot key. This intentionally fixes only the proved CP_* path; other TLS caches remain outside this change.
6 of 8 archetypes ported. This one starts from VOID and FILLS where the
other four start from ROCK and CARVE, which is what it was worth doing:
neither end of the pile needed a new operator, only the opposite sign.
FConstantRockSource -> FConstantFieldSource(+/-Base) AllSolid <-> AllAir
FSdfCarveOp -> FSdfConvertOp(Sign = +/-1) carve <-> fill
FSdfRoughnessMod 4th archetype, unchanged
Only the island blob source is new. Multiplying by +/-1 is exact in
IEEE-754, so the three already-green ports are bit-for-bit untouched.
ClassifyBox can return AllAir for the first time in the plugin, and an
island strate is by construction mostly empty — the test counts AllSolid
and AllAir separately so an aggregate cannot hide whether that fired.
Two bounds that would have been holes if assumed rather than derived:
the island bound is one-sided (a hairline thread of matter hangs below
each island down its axis, so only the TOP may reject), and the domain
warp displaces X and Y independently, so the pad needs WarpAmp*sqrt(2).
Also: AUDIT C1 was NOT closed. The 2026-07-27 sweep matched `SeedF * K`
and this archetype's warp spells it `(float)S * K`, so one site survived
— at seed 2e9 the warp flattens and every island snaps back to a perfect
circle. Fixed in both paths in one pass so the equivalence test stays a
valid oracle. Expect island silhouettes to change at large seeds.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Q3: fable-idea F20 phases 1/2 and F18, REVIEW_FINDINGS perf pass 2 and batch 3,
and ARCHITECTURE's biome full-param redesign were all still carrying
"CODE-COMPLETE, PENDING BUILD" markers dated 07-04/-06/-08. Jahni confirmed on
2026-07-26 that everything is built and working (AUDIT-2026-07.md §0), so the
documents were misreporting project state. Ticked with the date they were
ticked, not just the date they were built.
Deliberately NOT ticked: ARCHITECTURE's F6 master material graph. Its C++ half
is built, but the material graph itself is editor-side work that is genuinely
still open, and ticking it would recreate the problem this queue item fixes.
CODEMAP discipline for this batch: new §3.2b (the VoxelDensityOp contract), new
§3.12 (Private/Tests), the EVoxelTileClass move into §3.2, and
FChunkBiomeCache::Invalidate under the biome types row.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AUDIT P1: every markdown design doc except CODEMAP.md was untracked, so
ARCHITECTURE / AUDIT / OPSTACK-PLAN / fable-idea / REVIEW_FINDINGS lived
only on disk. Replaces the single !CODEMAP.md exception with !*.md.
Also makes OPSTACK-PROGRESS.md commits actually record something, which
the unattended crash-safety discipline depends on.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>