9136f5f0e76f4c9395cefaeffdc99d35964dd76c
21
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bc0f9ee791 |
wip(step3): 12.5 cm voxels, fall-through fixed, brick evaluator in game, organic tunnels -- speed gate FAILS
Stopped by the owner's decision (in-game lit captures were eating the round); he judges the look in game instead. 1. Fall-through with the research field: fixed. Deep drop, gate on: 2 holds (0.50 s), min foot clearance +43 cm; gate off: penetrates (-278 cm). Stress fixture offsets converted to metres. 2. VOXEL_SIZE 25 -> 12.5 cm. Physical sizes kept in metres (player, steps, gate, insets, research field sizes, dig radii, test thresholds); class defaults that count chunks/voxels doubled (ClipRadius 6, RenderDistanceChunks 1536, ViewDistance*, StrateViewMargin 6, PawnCollisionRadius 2, SkirtCells 4, EdgeSealThickness 128, decoration spacings, density volume res 256). Asset values override these defaults: the owner must double his own. Ring scale, six workers, idle, step-2f field before the look changes: 64 m cube (519^3) 4.55 s; 32 m cube (259^3) 0.95 s. 3. In game: tiles go through the brick evaluator (proved by a log marker); profile switch rebuilds the loaded world (~5,800 tiles); full-detail fill 12.4 s after spawn in the visible-window test. 4. Look: round winding tunnels, per-column ellipsoid/lattice caches. All step-2f geometry gates pass at 12.5 cm (0 crumbs, 1 solid component per profile, solid share 69-87%). 259^3 ring, six workers: 1.08-2.02 s (worst HyperComplex) -- the 600 ms gate FAILS. Lit captures failed (hidden/off-screen window, then blank frames); not pursued. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ |
||
|
|
26984d38d8 |
docs(comments): drop history narration, keep the why
Rewrite comments that told the story of past rounds instead of the current code: dated "fixed on / tried on / reverted on" notes, "this used to...", "stale paragraph removed", "Phase 1/2" progress labels, and the "ClassifyTile still does not use ClassifyBox" claim (it does now, via VF_ClassifyBoxWithWarpRetry). Every invariant, unit, sign convention, trap and measurement that justified the design is kept, rephrased in the present tense and in its original language (French or English). Also fix comments that named symbols removed in the dead-code commit (EvaluateSDF wrapper, FTunnelCoreWorldEvaluation support-floor fields, BlendChunks -> TransitionBlendChunks) and the stale function name in the VF_RollStrateParamsDetailed determinism checkf message. Comment and message text only; no code token changed. Tests untouched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01URDGLsu7c4nunqNFPJEFPU |
||
|
|
3f629f407a |
refactor(dead-code): remove functions, members and types with no caller
Each symbol below had zero references in Source/ (tests included), Tools/, Config/ and the build files after comment/string stripping. Functions: EvaluateTunnelCoreSDF, EvaluateSDF (uncached wrapper), IsTunnelSupportFloorWorldPoint, BuildTunnelSupportFloorColumn, IsTunnelSupportFloorColumnZ, GetTunnelSupportFloorColumnBand, VF_TunnelFloorAtSegment, VF_ProjectSweptTunnelFloor, FVoxelWormField EvaluateExact, ApplyPassageLandingAirMC, ApplyPassageTunnelAirMC, GetGenerationParamsFingerprint, FVoxelStrateCorpus::LoadFromSettings, GetSkippedDefinitions, VF_RollStrateParams, VF_ArePlayerFitConnectedWithSampler, VF_GetVoxelSeasonSelectionReasonName, UVoxelSeasonAsset::GetManifestContentHash, FVoxelStackSampler::IsRunning, CompareSkippedPostValue, MakeSurfaceColumnSource, WriteObjTile, ExploreEffectName, ExploreTileClassName, and the VoxelTypes.h chunk-local helpers (WorldToLocalCoord, ChunkToWorldPos, LocalToIndex, IndexToLocal, IsValidLocalCoord, GetFaceDirection, GetFaceNormal, CHUNK_SIZE_SQUARED, CHUNK_VOLUME). Members/types: write-only floor flags (FVoxelOpSample:: bProtectedStructuralFloor, StructuralFloorMinimumDensity, bTunnelCoreSupportFloor; bSupportFloor on the tunnel evaluations; FTunnelFloorSegmentProfile::NumSteps), UVoxelStrateManager::BlendChunks, unused FSummary counters in the stack sampler, two unused FVoxelSeasonCompositionSettings aliases, and a few unused locals/constants. No UPROPERTY, UFUNCTION, reflected type or enum was touched. Behaviour is unchanged: removed code was unreachable or only written, never read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01URDGLsu7c4nunqNFPJEFPU |
||
|
|
7af8d0e870 |
fix(correctness): false AllAir certificates and a stale shaft cache key; 44/44 tests green
The harness's first full suite run showed 16 of 44 tests failing. Two were real defects in the owner's world: 1. ParameterRoll: the tile classifier could certify a box AllAir while the final field is solid there (3 false proofs found, e.g. density -2.092319 at (-192,16,-224)). Cause: the box diagnostic narrowed 'tail reach' to 'air reach', so the swept tunnel FLOOR -- which writes solid -- did not count as reaching the box. A false AllAir skips meshing, i.e. missing floor in game. The classifier now uses the same reach predicate as the final writer (swept chain, floor band, relief, room-mouth envelope) and propagates it through Mixed refinement nodes. Re-run: 1,288,143 lattice samples, 0 violations. 2. VerticalShaftEquivalence: LedgeSpacing and LedgeDepth were missing from the production TLS cache key, so a shaft could reuse stale ledge parameters. Both are now in the key. The other 14: broken fixtures (missing staged corpus assets, a sampler leaking the shaft TLS marker between queries, stale candidate IDs, a window entirely inside the common tail) or stale expectations after this week's owner decisions (no authored tunnel floor, slope in degrees, rooms owning their interior). No test was deleted or weakened into vacuity; retired legacy comparisons stay as telemetry and the current stack is asserted instead. PassageLandsInOpenSpace now requires a real player-capsule fit in the final density at each authored landing (14/14, worst gradient 0.115723). Suite: 42 tests green in one run, the two long op-stack sweeps green in serialized filtered runs (the 1800 s launch guard); a harness timeout-recording bug was fixed. Bounded probe exports unchanged (canonical 94B47A1C, owner 44E7C813). ⚠️ Harness perf scenario moved 50.74 s -> 53.58 s worker (+5.6%): the wider reach predicate skips fewer boxes. Measure on the game path and decide before merging. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ |
||
|
|
4fa3931176 |
fix(tunnels): ribs removed at the cause; authored tunnel floor removed; slope acts on the route
The owner proved in game that the tunnel core caused the ribs (voxel.TunnelAblateTunnelCore=1 removes them). Root cause: the core's final reassertion replaced any sufficiently interior sample with a fixed +16 air density, destroying the distance gradient, so marching cubes snapped the surface to the voxel grid (all 385 centre samples saturated). The core now reasserts the continuous -Core.SDF, with bottom polarity from the swept shape. The Catmull-Rom sweep from |
||
|
|
0231072cc4 |
wip(tunnels): continuous world-core sweep, slope in degrees, bounded winding -- NOT MERGED: +18-30% worker CPU, visuals unconfirmed
Tunnel round from the owner's playtest. Luna's ablations traced the ribs to the world-space tunnel-core stage: disabling it removes them, while terracing, detail ops, roughness, the support floor, lateral warp, radius jitter, winding and LOD do not. The per-span capsule union is replaced by a deterministic Catmull-Rom sweep. Winding and graph expansion are now gated on bTunnelFloorEnabled (they ran even with the floor off). TunnelFloorGentleSlopeThreshold is authored in degrees (0-90, min 1 deg, DetSinCos conversion, legacy tangent values migrated: 0.3 -> 16.7 deg). The route length is capped at 6 waves x 640 = 3840 voxels, so 0.1 deg loads instead of freezing (2048 collapsed canonical reach; 24576 used ~2 GB). Room-wall trimming is behind voxel.TunnelMouthTrim (default OFF): with it on, a 36 m gap disconnects the walk. Canonical walk: 20,907 / 10,981, connected (was 20,830 / 10,909); exports identical with -voxel.CrtFma3=0; TilePostReachProof, DetSinCos and strate crossing pass. NOT merged because: one S/M pair vs the tip DLL shows worker CPU +17.8% static / +30.3% moving and worse p95; and the orchestrator's look at the before/after renders is inconclusive (camera not matched; regular grooves still visible in the after interior). Next: owner checks the look in game; if smooth, make the sweep cheap before merging; if not, drop the sweep and keep the degrees/bound/wind-gate parts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ |
||
|
|
e91f1c44bb |
wip(tunnels): checkpoint -- floor parameters exposed, round cut short by Codex credit limit
⚠️ THIS IS A CHECKPOINT, NOT A FINISHED CHANGE. The agent hit its usage limit
mid-round (locked out until 2026-09-15) after compacting its context, and never
filed a report or capability numbers. Committing so 1,344 lines are not left
uncommitted for five days. Verified by me only to the extent stated below.
WHAT LANDED
The tunnel floor controls are now real strate parameters under
"Cave Morphology|Tunnels|Floor", which is what the owner asked for -- hand-made
assets can tune them and the composer can roll them later:
bTunnelFloorEnabled true
bTunnelFloorTerracingEnabled true
TunnelFloorTerraceStepHeight 1.71 voxels (the existing 42.75 cm riser)
TunnelFloorMaxLedgeHeight 12.0 voxels (3 m -- climbable, not walkable)
TunnelFloorGentleSlopeThreshold tan(44 deg)
TunnelFloorLedgeCountPreference 0 (0 = old per-segment staircase;
>0 = whole-chain ledge policy)
TunnelFloorMaxLedges 4096
⭐ So the staircase-vs-ledges question the owner raised is now answerable IN THE
EDITOR without a rebuild: set LedgeCountPreference to 2-3 and the whole-chain
policy takes over from the per-segment one.
VERIFIED BY ME
build 0 errors
export, 2 runs 1.321 / 1.357 s (
|
||
|
|
2eaceb5984 |
feat(maze): a spanning tree -- it is a maze now, not a grid
Jahni: "mostly a cube full of straight pathway along the edges... basically
just a repeating pattern of tunnel connecting to each other, definitely
unwanted". And the measurement: the arrival mouth in a 30-cell pocket while
the network held 1,217. SAME CAUSE -- edge selection was independent hash
gating per +X/+Y/+Z edge, i.e. a random subgraph of the cubic lattice.
Every junction identical, and connectivity left to chance.
Fixed the way VerticalShafts was fixed in
|
||
|
|
fc43a86709 |
feat(scale): size the world to a human body -- and it is NOT enough
Jahni: "can't you try and make the world to scale?" Every length parameter is now derived from the body and annotated with its metre value, so nobody has to do the arithmetic to notice something is absurd. CorridorRadius 4 -> 8 1 m -> 2 m radius (4 m bore) CellSize 40 -> 64 keeps a real wall between wider corridors TunnelMinRadius 3 -> 6 0.75 m -> 1.5 m ShaftMinRadius 5 -> 8 1.25 m -> 2 m IslandMinRadius 18 -> 24 4.5 m -> 6 m MouthRadius 6 -> 8 passage mouths 4 m plus passage reach, spiral, cascade, bridges, ridges, chasms The reasoning that motivated it still looks right: a 2 m circular bore for a 1.76 m player clears the head only along the exact centreline, so almost no cell has a floor with 7.04 voxels of clear air above it. A 4 m bore is genuinely walkable. ⚠️ BUT IT DID NOT FIX TRAVERSABILITY, and this time it is not the instrument. The player-fit law is measured at STEP 1 on a mouth-fitted window -- full resolution, both mouths inside the box -- and across the eight showcase archetypes it reports: 6 NotConnectedAtThisResolution (real negatives at full resolution) 2 OutOfWindow (unmeasurable, not passing) 1 StartCellNotPlayerFit (the arrival mouth itself is too small) 0 CONNECTED And every archetype reports hard-gate survivors=0, so the showcase is displaying the least-bad of an entirely failing set. ⛔ DO NOT READ player_fit_fraction / player_clearance FROM THE SHOWCASE LINE. Those come from the COARSE step-4 measurement in the same log line, where the 1.36-voxel player is sub-cell and fit is unmeasurable -- player_clearance reads a uniform "1.00 voxels" for all eight archetypes, which is one cell, not one voxel. Only restricted_law is at step 1 and only it is trustworthy. Fixing that mixed-resolution reporting is next. So scale was necessary and insufficient. My hypothesis was that bore diameter versus body height was the binding constraint; doubling it moved nothing measurable. Something else is preventing player-sized volume from existing at all -- worth finding before tuning any further. Codex applied these edits and then died mid-poll without validating them (third time a killed agent left a clean-looking unbuilt diff). Build and suite run by me: build clean, 30 succeeded / 0 failed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K8V9my1PL68pmQb2gutZZV |
||
|
|
eb47efdec9 |
feat(measure): a player does not fit. The law was passing impossible routes.
Jahni walked composed strates for the first time: "'maze' is way too tight tunnel radius wise, i can't enter nor anything". The candidates he could not enter were the ones our metrics ranked BEST -- Maze had the highest walkable fraction (.285) and highest connected surface (.99) of all eight. ⭐ THE HEADLINE, AND IT IS BAD NEWS WORTH HAVING: old arrival->departure law passing on 7 of 8 candidates player-fit-restricted law CONNECTED ON 0 OF 8 **The primordial law has been passing on routes no player fits through.** Every "the world is traversable" claim in this project measured air, not passage. Player-fit fraction across the eight showcase candidates ranges .0000 (FloatingIslands -- literally zero) to .0117. The season composer now returns 0 survivors for 6 required slots, and the showcase gate rejects 8 of 8. That is the correct outcome. The gate is not tuned to a threshold; it requires a resolved player-fit volume and a connected player-fit route. Capsule confirmed by Jahni as the base ACharacter: 34 cm radius, 88 cm half-height = 1.36 voxels radius, 7.04 tall. Named constant with the derivation beside it. Two traps avoided, both of which would have produced confident nonsense: - THE COARSE GRID CANNOT RESOLVE A PLAYER. SampleStep 4 makes a cell 4 voxels, ~3x the player's radius, so fit is below the resolution of every metric built so far -- which is exactly why nothing flagged an impassable maze. Fit runs on step 1 and REFUSES (bPlayerFitResolved=false + reason) when the step is too coarse. - Manhattan distance >= Euclidean, so reusing the existing transform for clearance would OVERESTIMATE free space and report fits that do not exist. Clearance uses a separate Chebyshev transform; Manhattan stays only on the legacy feature-scale metric. ⚠️ MY ROUGHNESS HYPOTHESIS WAS WRONG, and Codex disproved it rather than confirming it. Forcing SurfaceRoughness=0 on the Maze moved PlayerFit .0105 -> .0138 and the restricted law stayed NotConnected. Minimum corridor clearance is 1.00 voxel (25 cm) with or without roughness -- the corridors are simply too tight for a 34 cm capsule, full stop. Roughness IS still a real pinch risk where reach exceeds corridor radius: Underwater 2.21x, FlatPlain 2.31x, CrystalChamber 1.81x, TunnelNetwork 1.44x on corridors, VerticalShafts 1.30x on connectors. The 5.625-voxel default bound stays dangerous. Islands measured, not changed (feel is Jahni's call): 0/2 touch either seal, median clear gap 47.8 above / 9.0 below -- but effective radius spans 27-258 voxels at H=128 with ThicknessRatio .546, so the worst case has zero guaranteed separation. Recommendation recorded: radius back to 18-42, StrateHeightInChunks 4 -> 6, ThicknessRatio <= .40. Build clean, 30 succeeded / 0 failed, verified in the namespace log. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU |
||
|
|
faa62d419e |
feat(runtime): the composed world can BE the game world
Jahni: "can you not implement those settings? as in, have them be live in
game?" This is that. The composer stops being a lab tool.
THE ARCHITECTURAL LINE, which is the whole design (COMPOSER-NOTES §3.1):
COMPOSITION stays editor-only, EVALUATION becomes runtime. Rolling,
measuring, preview, selection, promotion, the corpus -- none of it reaches
a player's machine. What crosses into the runtime is exactly two things:
reading a season manifest, and materialising a recipe into an op stack.
UVoxelSeasonAsset a cookable UPrimaryDataAsset holding the manifest,
so a season ships in a packaged game. The JSON
stays the reviewable, git-diffable artefact.
UVoxelSettings::Season optional. Unset => behaviour is exactly as today.
GetEffective*() season seed / spine radius / world radius / season
number override the authored values when assigned.
The test deliberately sets DIFFERENT authored
values, so "the season is authoritative" is proved
rather than coincidental.
⭐ MULTIPLAYER DETERMINISM, PROVED: two independent runtime managers built
the same season and compared 393,216 density samples BIT-IDENTICALLY. This
is the property the whole multiplayer model rests on -- replicate seed +
layout + diff, never geometry.
⭐ AND A STALE SEASON IS DETECTABLE, NOT SILENT. Initialize() now returns
bool and an assigned-but-invalid season NEVER falls back to the authored
pool. Falling back would hand a client a world that looks fine and is not
the season -- silent divergence, the worst failure mode in a shared world.
GetCurrentSeasonContentHash() is exposed BlueprintPure to compare at join.
HasComposerRecipeOverride() is gone. It force-classified every custom recipe
as Mixed, which was correct while box verdicts were only proved for
hand-written stacks -- but
|
||
|
|
088b40216d |
feat(composer): showcase of all 8 archetypes -- and "not navigable" answered
Jahni asked for one strate per archetype to look at, and said the previews looked "not navigable nor anything except maybe the mazes". Both delivered. ⭐ PART A -- HIS EYE WAS RIGHT, AND SO WAS THE METRIC. BOTH EXPLANATIONS WERE TRUE, and they split by archetype: archetype walkable FLOOR AREA largest connected surface CrystalChamber .059 .9999 1.00 FlatPlain .048 .9985 .9998 SurfaceWorld .064 .9374 .9936 Maze .285 .2629 .9905 Underwater .229 .2061 .3312 TunnelNetwork .155 .2084 .4640 VerticalShafts .108 .1138 .1449 FloatingIslands .004 .1016 .4992 1. THE METRIC WAS WRONG FOR CHAMBERS. Walkable fraction is volumetric: an air cell with solid one step below and headroom above. In a cathedral almost no air cell is near a floor, so a huge open room scores ~.06 while a tight maze scores ~.29. It was measuring CORRIDOR-NESS, not navigability -- and mazes win that by construction, which is exactly the pattern he spotted. Slab families actually have 94-100% walkable FLOOR AREA, fully connected. They were never the problem. 2. AND FOUR ARCHETYPES ARE GENUINELY FRAGMENTED, which is a real content finding, not an artifact. Largest connected walkable surface: VerticalShafts .14, Underwater .33, TunnelNetwork .46, FloatingIslands .50. In VerticalShafts, 86% of the floor is unreachable from the biggest patch. The primordial law still passes -- you CAN get from arrival to departure -- but most of the floor is not part of that. That is precisely "not navigable" and it needed a new metric to see. New metrics: WalkableFloorAreaFraction, NumWalkableSurfaceComponents, LargestWalkableSurfaceShare. A floor you cannot cross is not a floor. Web references checked, per his suggestion -- we invented every metric in this project without once testing them against reality: NPS solution-cave and Mammoth Cave morphology, Lehman Cave dimensions (Talus Room 90x376 ft, 21,511 sq ft floor, 113 ft ceiling), Deep Rock Galactic cave-design notes, Team Cherry on Metroidvania maps. They support heterogeneous room+passage space with branches and shafts -- NOT a universal floor-to-volume target. So there is no single number to optimise, which is itself worth knowing. PART B -- Saved/VoxelForge/Showcase/index.html, 8 cards, 64 PNGs, fine renders (step 1, radius 64, centred on LargestComponentPoint), 0 blanks. Each card carries the exact PIE values to type in, because navigability is judged by walking: CrystalChamber seed 7331 idx 34 slot 1 Maze seed 0 idx 58 slot 1 FlatPlain seed 0 idx 4 slot 1 SurfaceWorld seed 0 idx 11 slot 2 FloatingIslands seed 0 idx 34 slot 1 TunnelNetwork seed 0 idx 61 slot 1 Underwater seed 0 idx 46 slot 1 VerticalShafts seed 0 idx 15 slot 1 All bComposerRollStructure = false. Selection searched seeds 0/7331 x indices 0-63, applied the three hard gates, then scored floor_area + .25*clearance + .10*largest_surface. Caveats kept honest: floor area is a sampled XY proxy, projected connectivity is not a 3D traversal proof, "best" means best within the searched range. Build clean, 30 succeeded / 0 failed, verified by me. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU |
||
|
|
dd38832bb6 |
feat(composer): lateral REGIONS -- built, measured, and gated OFF
Jahni's own idea: "archetype could even mix within the same strate at some
point, tunnel network leading to a big chamber". An archetype becomes a
spatial REGION inside a strate, not a label on it.
Built by extending the mechanism that already exists rather than inventing
one: the stack blends VERTICALLY between strates, so regions blend the same
way LATERALLY. Deterministic jittered Voronoi sites on a 256-voxel lattice,
1-3 regions per strate from (seed, strateIndex), 24-voxel symmetric blend
band, per-chunk lookup cache. Parameters are never blended -- a shaft's
ShaftSpacing means nothing to a slab -- only the resulting DENSITY is.
Structural posts stay global and unconditional, so an invented region
cannot switch off the primordial law.
single-region path BIT-IDENTICAL to legacy, 256 probes, native + recipe
cross-boundary boxes 20 of 40, 199,800 voxels brute-forced, 0 VIOLATIONS
(every seam-spanning box correctly returned Mixed)
blend-band cost 663 ns vs 338 ns per voxel, over 16.0% of voxels
~1.15x field-weighted
survival 16/16 valid, non-vacuous, largest share >= .50
⛔ AND IT IS GATED OFF, because the seam breaks the one law that matters:
arrival -> departure across a region boundary passes 9/16 seeds, against
11/16 same-region controls in the same harness. Density blending alone does
not guarantee a player can cross a seam. A strate that mixes archetypes and
strands you at the boundary is strictly worse than one that does not mix.
VF_LateralRegionsAreShippable() returns false and the test ASSERTS THE GATE
IS SHUT while the rate is imperfect -- so flipping it without fixing
connectivity turns the suite red by design. The rate is a warning, not an
assertion: it is the measured state of an off-by-default feature, not a
regression in a live world, and a permanently red suite stops being read,
which is how real failures get missed.
Everything that ships is still hard-guarded: single-region bit-identity,
zero cross-boundary box violations, and every shipping-path law test
untouched.
The fix is an explicit CROSS-SEAM CORRIDOR CONTRACT -- a design decision,
recorded rather than made unilaterally. Codex diagnosed this correctly and
declined to tune the threshold, which was the right call.
Build clean, 29 succeeded / 0 failed, run and verified by me.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU
|
||
|
|
0b3ec18b43 |
feat(composer): PROMOTION -- the corpus grows itself, and it did not collapse
Tier 5. §3.3's answer to Jahni's "I'd like the system to not rely at all on
the handmade ones": promotion does not REMOVE the authored seed, it dilutes
it. Every invented strate that measures well rejoins the corpus.
Five simulated seasons, 24 candidates each:
season corpus project/default/promoted survival spread
1 15 4/8/3 20.8% 0.869
2 20 4/8/8 54.2% 0.849
3 20 4/8/8 54.2% 0.849
4 21 4/8/9 45.8% 0.916
5 21 4/8/9 50.0% 0.916
Corpus 12 -> 21, of which 9 are discovered. Survival roughly doubles.
⭐ AND THE COLLAPSE RISK DID NOT MATERIALISE, which was the thing worth
measuring rather than assuming. Promotion selects survivors, and blending
survivors repeatedly can converge the corpus onto a narrow safe region --
the composer would get better at passing and worse at surprising. Spread
went 0.869 -> 0.916. It dipped and plateaued mid-run, but did not narrow.
Recorded honestly: seasons 3 and 5 promoted ZERO. The near-duplicate gate
(normalised metric distance < 0.20 over air, largest share, walkable,
feature scale, clearance) is doing its job, but it also means the corpus
saturates at this scale. Five seasons of 24 demonstrates the MECHANISM, not
§3.3's "season 5 blends 200 discovered ones" -- that needs the overnight
budget, not a test.
Safety: a promoted record is RE-MEASURED on load, never trusted. Verified by
corrupting a stored metric -- the loader discarded it and re-derived the
geometry. A stale or tampered record therefore cannot introduce an
unescapable strate into a future season, which is the one failure that would
matter. Provenance (project/default/promoted) is tracked and logged.
Codex's recommendation, and I agree: keep a small explicit OUTLIER QUOTA
among candidates that pass every hard gate. This run showed no collapse, but
survivor-only promotion keeps the long-term risk, and a quota costs nothing.
PART A: the fine ROI now centres on LargestComponentPoint instead of (0,0).
Blank fine renders 6/42 -> 3/42. The label now reads "largest open space",
not "strate centre" -- the image moved, so the caption had to.
Build clean, 27 succeeded / 0 failed, verified by me. WorldRadiusVoxels=0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU
|
||
|
|
43eaf1ef0e |
test(composer): the handmade corpus is load-bearing for QUALITY, not validity
Answers Jahni's standing wish directly: "in the best of both worlds, i'd like the system to not rely at all on the handmade ones." Three arms, same size, same measurement, same criteria: approach survival walkable mean feature-scale mean corpus blend (today) 13/16 81% 0.0661 92.3 naive uniform 7/16 44% 0.0126 64.6 constraint-sampled 7/16 44% 0.0129 31.4 ⭐ THE ANSWER IS NOT THE SURVIVAL RATE, IT IS THE QUALITY GAP. Constraint sampling produces VALID worlds -- it passes the primordial law more often than naive rolling (1 law failure vs 3) -- but the survivors are materially worse: ~5x lower walkable fraction and ~3x lower feature scale. A composer that emits technically-passing but uniformly mediocre places has not solved the problem. So the corpus carries something the declared constraints do not. §3.3 said independent rolling destroys the CORRELATIONS; stating those correlations explicitly recovers validity but not the tacit quality that authored vectors encode. That is worth knowing and it was not knowable by argument. ⇒ VERDICT: keep the corpus in production. Constraint sampling is a corpus-free BOOTSTRAP (it can seed a corpus from nothing), and PROMOTION (Tier 5) is the real route off handmade content -- dilution, not removal. Naive rolling is rejected outright. ⚠️ UNDER-POWERED, stated plainly: 16 candidates per arm, not the 256 the spec asked for -- the fixed 8M-cell box/law workload made 256x3 too slow to finish. The 5x walkable gap is large enough to be believable at n=16, but the survival rates (44% vs 44%) are not separable at that sample size. Do not quote these as precise. Authored-corpus audit, and Codex read it correctly: 3 of 12 vectors violate the proposed relations (DA_Strate3 room coverage 2.68 vs bound 0.35; Default_SurfaceWorld ground bound; Default_VerticalShafts shaft radius 5 vs roughness margin 5.875). That does NOT mean those assets are broken -- it means the new relations are conservative HYPOTHESES, not universal corpus invariants. Recorded as such. Box law held across all three arms: 768 proved, 673,486 voxels brute-forced, 0 violations. §6.2 did not reopen under corpus-free parameters. Also noted: "uniform within clamps" was underspecified in my spec -- many fields have no finite upper clamp. Both corpus-free arms use the same declared H-relative envelopes so the comparison stays honest. Build clean, CorpusFree green, WorldRadiusVoxels=0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU |
||
|
|
d717bc74ff |
feat(editor): walk a composed candidate in PIE + why rooms read angular
PART B -- the thing Jahni asked for: "any way to test those in game?" A candidate existed only as measurements and PNGs. Now he can stand in one. Select the VoxelWorld actor in PIE -> Live Edit|Composer -> ComposerSeed / ComposerCandidateIndex / ComposerTargetStrateIndex / bComposerRollStructure -> click Apply Composer Candidate. The button and the automation tests call the SAME roll wrapper, which was the load-bearing requirement: a second roll path could drift, and then he would be judging a different world than the contact sheet describes. A determinism sample is logged on apply (seed, index, recipe, archetype, metrics, epoch, eight-point density verdict) so drift is caught the day it happens rather than in a month. Hazards handled, since this is the first composer code to touch the live runtime path: preflight materialisation before any live mutation, generation and decoration tasks drained, PassagesVersion bumped to invalidate thread_local caches, reuse of the existing RegenerateAllChunks / Epoch invalidation rather than a new path, no Initialize() or GeneratePassages() during apply (the re-entrancy trap), DiffLayer locks untouched, and custom recipes conservatively force ClassifyTile to Mixed. Scope is deliberate: a DENSITY-ONLY overlay. Layout height, authored passages, content, water and biome metadata stay from the existing slot; RebuildStrates() clears it. A full composed layout replacement needs a safe rebuild path that does not exist yet. Editor-only, verified: a Shipping build succeeds with the bridge excluded (96/96 actions), so §3.1's "offline only, never on a player's machine" still holds. ⚠️ UNVERIFIED BY DESIGN: a button cannot be tested headlessly and Codex was told not to claim it works. Jahni presses it and confirms the visual plus the "determinism=PASS" log line. PART A -- why rooms read angular, measured not guessed. One of three room shapes is VoxelSDF::RoundedBox: ShapeA = (.8 Rxy, .8 Rxy, .8 Rz) ShapeR = .25 Rxy so rounding is 31% of the horizontal half-extent but 78% of the vertical. Corners are rounded; the broad planar FACES survive. SmoothMin (blend 4) softens room/tunnel junctions not isolated corners; the cave warp bends geometry but preserves flat regions; roughness is surface-scale only. The name is accurate -- "rounded box" is not "blob". NOT ACTED ON. Jahni corrected his own read: the angular archetype is Maze (lattice source, rectilinear BY DESIGN and correct), and TunnelNetwork is "alright-ish". Codex's recommendation is recorded for if he ever wants it: ~5-10% boxes, 10-20% capsules, rest ellipsoids, or a larger ShapeR. Also closed REVIEW_FINDINGS EVoxelPassageType/Style as WONTFIX, enacting a 2026-08-16 judgement that recommended closure and was left open. Build clean (Editor + Shipping), 25 succeeded / 0 failed, run by me. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU |
||
|
|
993512f0bc |
feat(composer): F1 -- the candidates are VISIBLE, and detail is invisible
PART B: the preview. Jahni, asked what "good" means for ranking a season: "good is hard to describe, i believe it'll be easier once i'm able to see the strates candidates." So the ranking policy was blocked on this, not on more metrics. COMPOSER-NOTES §3.4 promised the preview comes nearly free once the measurement exists; collected. Per candidate, rendered from the grid the measurement ALREADY built (no second sampling of the world): a vertical XZ section and a plan XY slice, solid dark, air light, walkable cells highlighted, with a chunk scale bar so a corridor is distinguishable from a cathedral. Plus a self-contained index.html contact sheet of all 64 -- survivors first, outliers first within them, recipes, metrics, and every rejected candidate labelled with WHY (vacuous 3, fragmented 2, law failed 19). Saved/ComposerPreview/<runid>/index.html 64 candidates, 128 PNGs Two honesty rules are on the page itself, not buried in a comment: every number states the window that produced it (margin/step/Z span), and a 2D slice CANNOT show connectivity -- two regions that look joined in one slice may not be. Plan-Z is chosen by highest solid/air boundary-transition count, not hardcoded mid-height; a slab strate would otherwise render as a blank sheet. Codex flagged the ambiguity in my spec and picked correctly. PART A: bootstrap jitter for zero-spread fields. ±25% of a field's own magnitude when corpus spread is ~0, ±15% of measured spread otherwise, clamps last. Marked in code as a BOOTSTRAP for a starved corpus that promotion (Tier 5) should retire. 1,422 applications over 168 fields in the parameter roll; 6,848 over 107 in the structure roll. ⚠️ AND IT DID NOT BROADEN THE DISTRIBUTIONS. Feature scale 0-376 either way; walkable actually NARROWED (.389 -> .287). Codex's conclusion, and I agree: the measurement is INSENSITIVE to these fields, not merely corpus-starved. The reason is now obvious and worth writing down: the grid samples every 4 voxels, and cave DETAIL -- terraces, scallops, ribbing -- lives at 1-3 voxels. It is below the sampling resolution. A step-4 grid structurally cannot see feel; it sees size. So "vary the detail" and "score the detail" need different instruments, and the preview images inherit the same limit. Box proofs stayed sound under wider jitter: parameter roll 1,204 proved / 1,602,524 voxels / 0 violations; structure roll 659 proved / 877,129 / 0 violations. §6.2 did not reopen. fable-idea.md F1 ticked (measurement + preview). Build clean, 25 succeeded / 0 failed, verified by me. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU |
||
|
|
f088c19f88 |
feat(composer): cave FEEL is rollable -- 23 of 34 fields were live all along
Jahni: "we need to be able to have everything tuned, so feeling can be
quite different." So the 34 excluded terrain-detail fields had to be
settled -- they are the difference between varying how BIG a cave is and
varying how it FEELS.
Settled by EXPERIMENT, not by reading, because the exclusion rested on the
same kind of structural claim that produced the withdrawn fuse assertion
and the "99.95% void" reading. Sample GetDensityAt over a lattice, change
ONLY those fields, re-sample, per operation group:
LIVE (23 fields) terrace, layer-line, ribbing, overhang, cliff,
scallop, arch, dome, pinch -> now rolled
DEAD (11 fields) column, pit, chimney -> pre-baked into the chunk cache
from Definition->TerrainOperations, so the values in
FStrateGenerationParams are transport, not tunables
The call chain for the dead ones: BuildParamsFromDefinition returns only
the base params (VoxelStrateManager.cpp:1399); VoxelGenerator separately
reads Definition->TerrainOperations (VoxelGenerator.cpp:1099);
BuildChunkCache calls RoomOp->ApplyTo and pre-bakes pits/chimneys/columns
(VoxelCaveMorphology.cpp:1741).
⚠️ AND THE TRAP FIRED, exactly as specced against: these are native
unreflected fields, so REMOVING THEM FROM THE EXCLUSION LIST WOULD HAVE
ROLLED NOTHING. A knob that looks like it works and does not is worse than
an honest exclusion. An explicit jitter path was needed. This is why the
task was specced as an experiment with a liveness assertion (24 group/path
rows, 0 mismatches) rather than as a list edit.
⚠️ HONEST NEGATIVE: rolling detail did NOT materially broaden the measured
distributions. Feature scale 4-376 -> 0-376; walkable unchanged. All 17/17
TunnelNetwork/Underwater candidates activated live detail and every one of
the nine live groups appeared, so it is not that the fields are inert --
it is that most of them have ZERO CORPUS SPREAD, because the four authored
assets leave them at header defaults. Jitter is a fraction of measured
spread, and a fraction of zero is zero.
⇒ Real limitation, recorded not patched: "ranges come from corpus spread"
(§3.3) is right in principle and DEGENERATES on a homogeneous corpus. The
composer needs a bootstrap for zero-spread fields. Next.
Box verdicts with detail rolled: 1,228 proved, 1,634,468 voxels
brute-forced, 0 violations. Survival 59/64.
Recommendation recorded for later: roll terrain-operation parameter
STRUCTS directly into a transient candidate pool rather than corpus-ing
over assets -- there is exactly one such asset in the project, so an asset
corpus would starve like the strate corpus did.
Build clean, 25 succeeded / 0 failed, verified by me.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU
|
||
|
|
859a9b25c1 |
feat(composer): the structure roll -- 64 distinct stacks nobody wrote
Tier 4b. Until now the composer varied PARAMETERS within an archetype:
differently-sized caves. This rolls STRUCTURE, which is what makes a strate
a different KIND of place.
Per COMPOSER-NOTES §3.2: roll root polarity (rock+carve or void+fill) ->
a shape source legal for that polarity -> the conversion FOLLOWS from
polarity rather than being rolled -> k modifiers drawn from what the
CHANNEL DECLARATIONS say is legal, not from a hand-written list ->
structural posts appended automatically and not omittable.
64 distinct recipes of 64 (perfect structural diversity)
invalid recipes emitted: 0 (the roller cannot produce an
order the DAG validator rejects)
survival 46/64 (71.9%) non-vacuous 62, largest-share 60,
law pass 48
⭐ AND THEY ARE REAL PLACES NOBODY DESIGNED. Root polarity as a one-bit
identity lever, exactly as §3.2 predicted:
VF|r=vd/T|s=rg/T|x=fl/T TunnelNetwork's ROOM GRAPH rooted in void with
a FILL -- rooms become solid blobs hanging in
open space. air .978, feature scale 64.
VF|r=vd/M|s=lt/M|x=fl/M Maze's lattice corridors filled instead of
carved. air .938, feature scale 16.
RC|r=rk/V|s=sh/V|x=cv/V shafts carved from rock with a Maze modifier
set they never ship with.
Same parts, different worlds. That is the whole thesis of the op stack,
finally exercised.
⭐⭐ AND THE VERDICTS HOLD ON STACKS NOBODY VERIFIED:
489 proved (213 AllSolid, 276 AllAir), 2,071 mixed
650,859 voxels brute-forced
0 VIOLATIONS
This is what
|
||
|
|
190ff381c0 |
feat(composer): it invents strates that work -- 59/64, and §6.2 is CLOSED
The corpus was starved: the loader followed the active settings pool and
found ONE vector, so all 64 candidates were bit-identical and every number
was a placeholder. It now loads every UVoxelStrateDefinition via the Asset
Registry (Saved/Autosaves and Saved/Cooked excluded -- including them would
silently weight the corpus toward whatever was autosaved last) plus the
per-archetype defaults from VoxelStrateTypes.h, which are themselves
hand-tuned known-good vectors. Blending stays WITHIN an archetype;
different archetypes read different subsets of the 73 fields.
⭐ THE COMPOSER WORKS. 64 candidates blended from real parents, every one
measured:
survival 59/64 (92.2%)
non-vacuous 60 · largest-share >= .50 60 · primordial law 63 · roll
failures 0
and they are genuinely different worlds, not one world 64 times:
air fraction .0137 -> 1.000
walkable .000 -> .389
feature scale 4 -> 376 voxels
archetypes TunnelNetwork, VerticalShafts, FlatPlain, CrystalChamber,
SurfaceWorld, Underwater, FloatingIslands, Maze
⭐⭐ §6.2 IS CLOSED, and it was the real risk. Box-verdict bounds were only
ever proved against the parameters Jahni typed; the whole worry was that
invented parameters would violate a bound nobody had checked -- silently,
leaving no geometry and no collision. Against ROLLED parameters:
1,224 boxes proved (549 AllSolid, 675 AllAir), 1,336 Mixed
1,629,144 voxels brute-forced
0 VIOLATIONS
The bounds hold across the rolled range, not just at authored points. The
isolation work in
|
||
|
|
358bd415a9 |
feat(composer): the parameter roll -- infrastructure real, corpus starved
Tier 4a. The first piece of the composer that INVENTS rather than fixes. The design, from COMPOSER-NOTES §3.3: do NOT roll 73 parameters independently. The coherent region of a 73-dimensional space is a vanishingly thin sheet and uniform sampling never lands on it -- and independent rolling destroys the CORRELATIONS (room spacing <-> room radius <-> tunnel length) that make a vector coherent. So blend known-good vectors through the existing FStrateGenerationParams::Lerp instead: constraint satisfaction is free, because a convex combination preserves every relation holding in both parents. Min <= Max stays true because it was never broken. Built: FVoxelStrateCorpus (loads authored vectors, computes per-field spread), VF_RollStrateParams (2-3 weighted parents, convex blend, jitter by +-15% of each field's MEASURED corpus range -- not by the clamps, which are "don't type nonsense" limits, not "this makes a good world" limits), and VoxelForge.Composer.ParameterRoll. Determinism asserted by rolling twice and comparing every field. Exclusion list found by reflection, not assumption: StrateTopWorldZ and StrateBottomWorldZ (manager-owned runtime bounds) plus 34 terrain-op transport fields (TerraceStepHeight..PinchLength) that are copied in from room operators rather than being strate tunables. Bools inherit from the dominant parent; ints/enums use Lerp's existing snap. ⚠️ THE RESULT IS VACUOUS AND SAYS SO. 64/64 candidates "survived" -- but the corpus loaded ONE vector (DA_Strate3), so all 64 are bit-identical. 100% survival of a single point is not evidence of anything. The box- verdict check is vacuous too: 2,560 boxes, 0 proved, 0 voxels brute-forced, so §6.2 is NOT closed. The test emits a warning saying exactly this rather than reporting a clean pass, and no workaround was added to hide it. Four strate assets exist (DA_Strate1..4); the loader found one. Fixing the corpus is the next task -- with one parent there is nothing to blend, and every number above is a placeholder. Also owed: clamp metadata is editor-only, so the safety net needs a cook-time baked table before this ships. Nothing calls the composer from any runtime path (§3.1: offline, once per season, on a build box). Build clean, 23 tests / 0 failed (1 carries the deliberate vacuity warning), verified in VoxelM.log. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU |