feat(core): cavern graph v1, one continuous floor-capped tunnel into the landmark chamber (L46); R13

The flagged SW demo's ramp (57 carves + 107 support pillars, visibly ribbed) becomes one cubic-Bezier
sweep: closest point by 17-point seed plus 5 Newton steps, a cubic floor profile, a rounded 2.6 m bore,
and a hard floor cap applied after unions and relief that only adds support where the field is air.
Optional resolved cavern-graph records (one room, one edge) enter canonical identity only when present;
their bounds extend World::isTileShapeFree. Reachability passes (L43 control fails), headroom 2.8 m,
floor ripple 1.8 mm (L45 ramp control fails at 17.9 mm), shape limits met; demo off: owner hashes
identical to L45. fast/medium/full PASS. Research R13 (read-only): continuous SDF sweeps along curves.

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-24 09:53:06 +02:00
1 parent f13b145f23
commit e016f6a20f
14 files changed
+1753 -48

No files matched your search

@@ -0,0 +1,384 @@
#!/usr/bin/env python3
"""Capture the L46 cavern graph views and audit player-scale built-shape limits."""
from __future__ import annotations
import argparse
import importlib.util
import json
import math
import os
from pathlib import Path
import subprocess
import sys
import time
ROOT = Path(__file__).resolve().parents[4]
VERIFY = ROOT / "Standalone/Tools/verify"
LINUX37 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux37"
sys.path.insert(0, str(VERIFY))
from runner import bounded_run, current_stamp, first_stamp
def load_module(name: str, path: Path):
spec = importlib.util.spec_from_file_location(name, path)
if spec is None or spec.loader is None:
raise RuntimeError(f"cannot import {path}")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
PROFILE = load_module("l45_ring_profile", ROOT /
"Standalone/Research/WorldAssemblerM3/Linux32/AuditRingTerraceL32.py")
SHAPE = load_module("l45_shape_audit", LINUX37 / "AuditMouthShapeL37.py")
PARSER = argparse.ArgumentParser(description=__doc__)
PARSER.add_argument("--layout", type=Path, required=True)
PARSER.add_argument("--artifact-dir", type=Path, required=True)
PARSER.add_argument("--capture-dir", type=Path, required=True)
PARSER.add_argument("--data", type=Path, default=ROOT / "Standalone/data/owner_world.json")
OPTIONS = PARSER.parse_args()
ARTIFACT_DIR = OPTIONS.artifact_dir.resolve()
CAPTURE_DIR = OPTIONS.capture_dir.resolve()
LAYOUT_PATH = OPTIONS.layout.resolve()
ARTIFACT_DIR.mkdir(parents=True, exist_ok=True)
CAPTURE_DIR.mkdir(parents=True, exist_ok=True)
PNG_DIR = ARTIFACT_DIR / "capture-png"
PNG_DIR.mkdir(parents=True, exist_ok=True)
HEADLESS = Path(os.environ["VOXELFORGE_L37_HEADLESS"])
RENDERER = Path(os.environ["VOXELFORGE_L37_RENDERER"])
EXPECTED_STAMP = current_stamp()
def run_logged(name: str, command: list[str], *, capture: bool = False) -> str:
log = ARTIFACT_DIR / f"{name}.log"
started = time.monotonic()
with log.open("w", encoding="utf-8") as stream:
result = bounded_run(command, timeout=1800, stdout=stream)
elapsed = time.monotonic() - started
output = log.read_text(encoding="utf-8", errors="replace")
if result is None:
raise RuntimeError(f"{name} timed out; see {log}")
print(f"[L45CaptureRun] step={name} elapsed={elapsed:.1f}s "
f"exit={result.returncode} log={log}", flush=True)
if result.returncode != 0:
raise RuntimeError(f"{name} failed; see {log}")
if capture and (first_stamp(output) != EXPECTED_STAMP
or first_stamp(bounded_run(
[str(command[0]), "--print-source-stamp"], timeout=15).stdout or "")
!= EXPECTED_STAMP):
raise RuntimeError(f"{name} executable source stamp mismatch")
return output
def stamp_by_id(layout: dict, stable_id: str) -> dict:
for stamp in layout.get("stamps", []):
if stamp.get("stable_id") == stable_id:
return stamp
raise RuntimeError(f"missing stamp {stable_id}")
def metres(stamp: dict, key: str = "position_um") -> tuple[float, float, float]:
return tuple(value / 1_000_000.0 for value in stamp[key])
def camera_angles(camera, target):
dx, dy, dz = (target[index] - camera[index] for index in range(3))
return (math.degrees(math.atan2(dx, dy)),
math.degrees(math.atan2(dz, math.hypot(dx, dy))))
def fmt(values) -> str:
return ",".join(f"{value:.6f}" for value in values)
def camera_spec(camera, target):
yaw, pitch = camera_angles(camera, target)
return (*camera, yaw, pitch)
def edge_point(edge: dict, t: float) -> tuple[float, float, float]:
points = edge["control_points_um"]
one = 1.0 - t
weights = (one ** 3, 3 * one ** 2 * t, 3 * one * t ** 2, t ** 3)
return tuple(sum(weights[index] * points[index][axis]
for index in range(4)) / 1_000_000.0
for axis in range(3))
def cavern_features(layout: dict):
if (layout.get("cavern_graph_vocabulary_version") != 1
or len(layout.get("cavern_rooms", [])) != 1
or len(layout.get("cavern_edges", [])) != 1):
raise RuntimeError("L46 capture needs one resolved cavern room and edge")
room = layout["cavern_rooms"][0]
edge = layout["cavern_edges"][0]
return room, edge
layout = json.loads(LAYOUT_PATH.read_text(encoding="utf-8"))
room, edge = cavern_features(layout)
portal_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-mouth-approach-v1")
floor_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-v1-floor")
dais_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-v1-dais")
entrance = edge_point(edge, 0.0)
next_ramp = edge_point(edge, 0.08)
portal = metres(portal_stamp)
chamber = metres(room, "center_um")
floor = metres(floor_stamp)
floor_top = floor[2] + floor_stamp["half_extents_um"][2] / 1_000_000.0
dais = metres(dais_stamp)
dais_top = dais[2] + dais_stamp["half_extents_um"][2] / 1_000_000.0
ground_z = entrance[2]
direction_length = math.hypot(next_ramp[0] - entrance[0], next_ramp[1] - entrance[1])
direction = ((next_ramp[0] - entrance[0]) / direction_length,
(next_ramp[1] - entrance[1]) / direction_length)
outward_length = math.hypot(entrance[0] - chamber[0], entrance[1] - chamber[1])
outward = ((entrance[0] - chamber[0]) / outward_length,
(entrance[1] - chamber[1]) / outward_length)
mouth_normal = (-direction[1], direction[0])
mesh = ARTIFACT_DIR / "landmark-l46.vfmesh"
export_camera = ((entrance[0] + chamber[0]) * 0.5,
(entrance[1] + chamber[1]) * 0.5,
(ground_z + floor_top) * 0.5)
export_target = (chamber[0], chamber[1], floor_top)
run_logged("landmark-export", [str(HEADLESS), str(OPTIONS.data), "--workers=12",
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
"--force-generate", "--clip-radius=3", "--max-clip-level=0", "--max-level=0",
"--render-distance-chunks=0", "--recipe=surface-world", "--landmark-chamber-demo",
f"--camera={fmt(camera_spec(export_camera, export_target))}",
f"--mesh-export={mesh}", f"--resolved-layout-output={LAYOUT_PATH}"], capture=True)
layout = json.loads(LAYOUT_PATH.read_text(encoding="utf-8"))
room, edge = cavern_features(layout)
portal_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-mouth-approach-v1")
floor_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-v1-floor")
dais_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-v1-dais")
entrance = edge_point(edge, 0.0)
next_ramp = edge_point(edge, 0.08)
portal = metres(portal_stamp)
chamber = metres(room, "center_um")
floor = metres(floor_stamp)
floor_top = floor[2] + floor_stamp["half_extents_um"][2] / 1_000_000.0
dais = metres(dais_stamp)
dais_top = dais[2] + dais_stamp["half_extents_um"][2] / 1_000_000.0
ground_z = entrance[2]
direction_length = math.hypot(next_ramp[0] - entrance[0], next_ramp[1] - entrance[1])
direction = ((next_ramp[0] - entrance[0]) / direction_length,
(next_ramp[1] - entrance[1]) / direction_length)
outward_length = math.hypot(entrance[0] - chamber[0], entrance[1] - chamber[1])
outward = ((entrance[0] - chamber[0]) / outward_length,
(entrance[1] - chamber[1]) / outward_length)
if not mesh.is_file() or mesh.stat().st_size == 0:
raise RuntimeError(f"missing mesh export {mesh}")
voxel_um, triangles, tile_count = PROFILE.read_scene(str(mesh), 0,
floor_top - 8.0, entrance[2] + 9.0,
(min(entrance[0], chamber[0]) - 20.0, max(entrance[0], chamber[0]) + 20.0,
min(entrance[1], chamber[1]) - 20.0, max(entrance[1], chamber[1]) + 20.0))
bounds = (min(entrance[0], chamber[0]) - 20.0, max(entrance[0], chamber[0]) + 20.0,
min(entrance[1], chamber[1]) - 20.0, max(entrance[1], chamber[1]) + 20.0)
buckets = PROFILE.build_buckets(triangles, True, bounds, cell_size=1.0)
ground_candidates = []
for ix in range(-20, 21):
for iy in range(-20, 21):
x, y = portal[0] + ix * 0.5, portal[1] + iy * 0.5
dx, dy = x - portal[0], y - portal[1]
distance = math.hypot(dx, dy)
if not 6.0 <= distance <= 10.0:
continue
hit = PROFILE.sample_surface(buckets, x, y, True, 1.0,
preferred_height=ground_z)
if hit is None or abs(hit[0] - ground_z) > 3.0 or hit[1][2] < 0.85:
continue
alignment = max(-1.0, min(1.0,
(dx * mouth_normal[0] + dy * mouth_normal[1]) / distance))
angle = math.acos(alignment)
score = abs(distance - 7.0) + angle * 4.0
ground_candidates.append((score, x, y, hit[0]))
if not ground_candidates:
raise RuntimeError("no walkable mesh ground lies 6 to 10 m from the cave mouth")
_, ground_x, ground_y, outside_ground = min(ground_candidates)
inside_floor = PROFILE.sample_surface(buckets, chamber[0], chamber[1], True, 1.0,
preferred_height=floor_top)
if inside_floor is None or abs(inside_floor[0] - floor_top) > 1.5:
raise RuntimeError(f"chamber floor mesh hit {inside_floor} does not match designed floor {floor_top:.3f} m")
floor_top = inside_floor[0]
ground_camera = (ground_x, ground_y, outside_ground + 1.6)
entry_ground = PROFILE.sample_surface(buckets, entrance[0], entrance[1], True, 1.0,
preferred_height=ground_z)
if entry_ground is None:
raise RuntimeError("cave mouth has no walkable ground surface in the exported mesh")
entry_camera = (entrance[0] + mouth_normal[0] * 3.8,
entrance[1] + mouth_normal[1] * 3.8, ground_z + 1.6)
entry_target_floor = edge_point(edge, 0.30)
entry_target = (entry_target_floor[0], entry_target_floor[1], entry_target_floor[2] + 1.4)
to_dais = (dais[0] - chamber[0], dais[1] - chamber[1])
to_dais_length = math.hypot(*to_dais)
opposite_dais = (-to_dais[0] / to_dais_length, -to_dais[1] / to_dais_length)
inside_x = chamber[0]
inside_y = chamber[1]
inside_floor = PROFILE.sample_surface(buckets, inside_x, inside_y, True, 1.0,
preferred_height=floor_top)
inside_eye_z = inside_floor[0] + 1.6
chamber_camera = (chamber[0] + opposite_dais[0] * 5.5,
chamber[1] + opposite_dais[1] * 5.5, inside_eye_z)
chamber_target = (dais[0], dais[1], dais_top - 0.25)
overview_camera = (entrance[0] + outward[0] * 18.0,
entrance[1] + outward[1] * 18.0, outside_ground + 15.0)
overview_target = ((entrance[0] + chamber[0]) * 0.5,
(entrance[1] + chamber[1]) * 0.5,
(ground_z + floor_top) * 0.5)
inward = (-outward[0], -outward[1])
clip_point = (entrance[0] + outward[0] * 0.5,
entrance[1] + outward[1] * 0.5)
overview_clip = (inward[0], inward[1], 0.0,
-(inward[0] * clip_point[0] + inward[1] * clip_point[1]))
views = (
("ground-entrance", ground_camera, (portal[0], portal[1], portal[2]),
(portal[0], portal[1], ground_z, 20.0), -509.0),
("entrance-looking-in", entry_camera, entry_target, (entrance[0], entrance[1], entrance[2], 16.0), -507.0),
("inside-to-dais", chamber_camera, chamber_target,
(chamber[0], chamber[1], chamber[2], 15.0), chamber[2]),
("overview-entrance-and-chamber", overview_camera, overview_target,
((entrance[0] + chamber[0]) * 0.5,
(entrance[1] + chamber[1]) * 0.5,
(ground_z + floor_top) * 0.5, 34.0), -509.0),
)
for name, camera, target, focus, height_center in views:
png = PNG_DIR / f"{name}.png"
jpg = CAPTURE_DIR / f"{name}.jpg"
yaw, pitch = camera_angles(camera, target)
fov = (80.0 if name == "overview-entrance-and-chamber" else
70.0 if name in ("inside-to-dais", "entrance-looking-in") else 65.0
if name == "ground-entrance" else 60.0)
if name == "ground-entrance":
fov = 55.0
print(f"[L46CaptureCamera] view={name} camera_m=({fmt(camera)}) "
f"target_m=({fmt(target)}) yaw_deg={yaw:.3f} pitch_deg={pitch:.3f} "
f"fov_deg={fov:.1f} entrance_distance_m={math.dist(camera, portal):.3f}", flush=True)
render = [str(RENDERER), str(mesh), str(png), "--size=1600x900", f"--fov-deg={fov:.1f}",
f"--camera-m={fmt(camera)}", f"--yaw-deg={yaw:.6f}", f"--pitch-deg={pitch:.6f}",
"--shade=readable", "--headlamp=on", "--height-tint=on",
"--light-direction=0.3,-0.4,0.85",
f"--height-center-m={(floor_top if name == 'inside-to-dais' else height_center):.6f}",
f"--height-range-m={4 if name == 'inside-to-dais' else 16}",
"--tile-skirts=off", "--tile-edges=off",
f"--focus-region={fmt(focus)}"]
if name == "overview-entrance-and-chamber":
render.append(f"--clip-plane={fmt(overview_clip)}")
run_logged(f"{name}-render", render, capture=True)
for quality in (4, 6, 8):
run_logged(f"{name}-jpeg-q{quality}", ["ffmpeg", "-nostdin", "-hide_banner",
"-loglevel", "error", "-y", "-i", str(png), "-frames:v", "1",
"-q:v", str(quality), str(jpg)])
if jpg.is_file() and 0 < jpg.stat().st_size <= 300_000:
break
if not jpg.is_file() or not 0 < jpg.stat().st_size <= 300_000:
raise RuntimeError(f"{jpg.name} exceeds the 300 KB capture limit")
quality_log = run_logged(f"{name}-quality", [sys.executable,
str(VERIFY / "capture_quality.py"), str(jpg)])
print(f"[L46CaptureJPEG] file={jpg} bytes={jpg.stat().st_size} "
f"quality_log={quality_log.strip().replace(chr(10), ' ')} status=PASS", flush=True)
def region_triangles(center, radius_xy, z_min, z_max):
selected = []
for triangle in triangles:
points = tuple(vertex[0] for vertex in triangle[2])
centroid = tuple(sum(point[axis] for point in points) / 3.0 for axis in range(3))
if (math.hypot(centroid[0] - center[0], centroid[1] - center[1]) <= radius_xy
and z_min <= centroid[2] <= z_max):
selected.append(triangle)
return selected
def tunnel_wall_triangles(edge, t, height_above_floor):
center = edge_point(edge, t)
before = edge_point(edge, max(0.0, t - 0.01))
after = edge_point(edge, min(1.0, t + 0.01))
tx, ty = after[0] - before[0], after[1] - before[1]
tangent_length = math.hypot(tx, ty)
tx, ty = tx / tangent_length, ty / tangent_length
expected_radius = edge["bore_radius_um"] / 1_000_000.0 * math.sqrt(
1.0 - (height_above_floor / (edge["bore_height_um"] / 1_000_000.0)) ** 2)
selected = []
for triangle in triangles:
points = tuple(vertex[0] for vertex in triangle[2])
centroid = tuple(sum(point[axis] for point in points) / 3.0 for axis in range(3))
dx, dy = centroid[0] - center[0], centroid[1] - center[1]
longitudinal = dx * tx + dy * ty
lateral = abs(-dy * tx + dx * ty)
vertical = centroid[2] - center[2]
if (abs(longitudinal) <= 1.5
and abs(lateral - expected_radius) <= 0.7
and abs(vertical - height_above_floor) <= 0.75):
selected.append(triangle)
print(f"[L46TunnelWallWindow] t={t:.3f} center_m=({center[0]:.3f},"
f"{center[1]:.3f},{center[2]:.3f}) expected_radius_m={expected_radius:.3f} "
f"longitudinal_half_width_m=1.500 vertical_half_width_m=0.750 "
f"triangles={len(selected)}", flush=True)
return selected
def audit_shape(name, region, center):
metrics = SHAPE.analyze_triangles(region, center[:2], center[2],
crop_to_center=False, include_sides=True)
passed = (metrics["triangles"] > 0
and metrics["planar_area"] < SHAPE.PLANE_LIMIT_M2
and metrics["straight"] <= SHAPE.STRAIGHT_LIMIT_M
and metrics["corners"] == 0)
print(f"[LandmarkBuiltShape] region={name} triangles={metrics['triangles']} "
f"planar_patch_m2={metrics['planar_area']:.4f} "
f"straight_run_m={metrics['straight']:.4f} sharp_corners={metrics['corners']} "
f"corner_turn_max_deg={metrics['corner_turn_max']:.2f} "
f"thresholds=({SHAPE.PLANE_LIMIT_M2:.2f}m2,{SHAPE.STRAIGHT_LIMIT_M:.2f}m,"
f"{SHAPE.CORNER_TURN_LIMIT_DEG:.0f}deg) status={'PASS' if passed else 'FAIL'}",
flush=True)
if not passed:
raise RuntimeError(f"L37 built-shape thresholds failed in {name}")
return metrics
entrance_metrics = audit_shape("cave-mouth", region_triangles(
portal, 5.0, ground_z + 0.8, ground_z + 4.5),
(portal[0], portal[1], ground_z))
tunnel_mid = edge_point(edge, 0.58)
tunnel_metrics = audit_shape("tunnel-wall-edge", tunnel_wall_triangles(
edge, 0.58, 1.2),
(tunnel_mid[0], tunnel_mid[1], tunnel_mid[2] + 1.2))
dais_surface = PROFILE.sample_surface(buckets, dais[0], dais[1], True, 1.0,
preferred_height=dais_top - 0.4)
if dais_surface is None:
raise RuntimeError("dais stamp has no upward-facing surface in the exported mesh")
dais_rise = dais_surface[0] - floor_top
print(f"[LandmarkDaisSurface] center_m=({dais[0]:.3f},{dais[1]:.3f}) "
f"floor_z_m={floor_top:.3f} top_z_m={dais_surface[0]:.3f} "
f"rise_m={dais_rise:.3f} minimum_m=1.000 "
f"status={'PASS' if dais_rise >= 1.0 else 'FAIL'}", flush=True)
if dais_rise < 1.0:
raise RuntimeError(f"dais rises only {dais_rise:.3f} m above the chamber floor")
dais_metrics = audit_shape("dais-platform", region_triangles(
dais, 1.7, floor_top + 0.6, dais_top + 0.4),
(dais[0], dais[1], dais_surface[0]))
metrics_path = ARTIFACT_DIR / "landmark-shape-metrics.json"
metrics_path.write_text(json.dumps({
"graph_vocabulary_version": layout["cavern_graph_vocabulary_version"],
"entry_m": entrance, "portal_m": portal, "entry_ground_m": ground_z,
"chamber_center_m": chamber, "chamber_floor_m": floor_top,
"tunnel_midpoint_m": tunnel_mid,
"dais_center_m": dais, "dais_top_m": dais_top,
"dais_surface_m": dais_surface[0], "dais_rise_m": dais_rise,
"l37_thresholds": {"planar_patch_m2_lt": SHAPE.PLANE_LIMIT_M2,
"straight_run_m_lte": SHAPE.STRAIGHT_LIMIT_M,
"corner_turn_deg_lt": SHAPE.CORNER_TURN_LIMIT_DEG},
"entrance_arch": entrance_metrics, "tunnel_wall": tunnel_metrics,
"dais_platform": dais_metrics,
"mesh_tiles": tile_count, "mesh_voxel_um": voxel_um,
}, indent=2) + "\n", encoding="utf-8")
print(f"[L46CaptureShapeMetrics] file={metrics_path} status=PASS", flush=True)
@@ -0,0 +1,36 @@
# Linux 46 — cavern graph slice 1
## Sweep and resolved graph
The ramp is one cubic-Bezier sweep. Each field query finds the closest XY point with a 17-point seed and five Newton refinements; the curve's Z coordinates define the cubic floor profile. A continuous rounded bore uses a 2.6 m radius, 4.8 m height and 0.3 m smooth blend. The 20 mm relief is applied to the bore. A separate hard floor cap runs after smooth unions, relief, passages and stamps. It preserves native negative density and adds at most 0.45 m of support only where the field is air. The room and edge conservative bounds feed `World::isTileShapeFree`.
Resolved snapshots can carry optional cavern graph vocabulary version 1 records: room `landmark/sw-arrival-chamber-v1` and edge `landmark/sw-arrival-chamber-tunnel-v1`, anchored from the surface-ground approach to that room. Graph fields are serialized and included in canonical identity only when records exist. With the demo off, the graph is absent and the L45 identities remain unchanged.
The 57 ramp carves and 107 support pillars are gone. The room is one graph node and the tunnel one edge. Four resolved stamps remain for the two mouth carves, room floor and dais.
## Audits
- Reachability: pass from walkable ground to the chamber floor; 58 path samples, 5,974 capsule samples, no blocked or unsupported samples, maximum grade 14.179°. Buried L43 control: expected fail.
- Headroom: 2.800 m minimum above the capsule, against 0.300 m required.
- Ripple: tunnel floor peak 0.0018 m over 202 samples (0.015 m limit); wall peak 0.0232 m over 138 samples (0.035 m limit, 0.25–1.0 m band). L45 segmented-ramp control: expected floor-ripple fail at 0.0179 m against 0.015 m.
- Built shape (L37 limits: planar patch <0.50 m², straight run ≤0.75 m, no sharp corners): entrance 0.4902 m² / 0.5470 m / 0; tunnel wall 0.3042 m² / 0.6225 m / 0; dais 0.2816 m² / 0.7500 m / 0.
- Inside-tunnel and near-tunnel camera hashes match at W1/W8/W12. Random-camera determinism also passed.
## Hashes, cost and tiers
The clean Clang and GCC builds share source stamp `20d1ae654440b22c6fdf9c91dd39c809b3063b54da6f2f4f44acf78894b7cf3b`. Owner JSON SHA-256 remains `7b095f9bcc6b90133d5a463f99f0b571133b2c549ce1ecf2d64fe9175e41e183`. Demo-off FI/SW layout IDs are `b7a7d9ecc48d8f26` / `8a52e84c26ed92d2`; their 12-hash signatures match L45: FI `9820f4f38b189b3f7263810e7b3ff62aa502b21f476ffcfdbc7761a65cb07d58`, SW `a1e9268a4bbcc77d2a1ac54095df6851a70bab65c43ae50b332ed75132617834`.
Five demo-off cost pairs against committed L45: FI median 16.315 → 16.401 s (+0.53%); SW 1.720 → 1.730 s (+0.58%). Fast passed in 202.7 s, medium in 571.9 s, and final full in 1605.2 s. Four captures are in `captures/`: `ground-entrance.jpg` (39,430 B), `entrance-looking-in.jpg` (45,070 B), `inside-to-dais.jpg` (28,310 B), `overview-entrance-and-chamber.jpg` (62,735 B). Each is below 300 KB. Fourteen of fifteen fast trials were used.
## Failed runs
The first medium capture audit sampled a broad tunnel volume and failed the built-shape limit; the final wall annulus at curve parameter 0.58 passed. The first full attempt passed its 30 determinism cells but failed extracting an 806 MB historical archive and filled `/tmp`. The final full run used a temporary Git wrapper to export only the build inputs (Core, Source, Compat and build scripts); its historical build, cost pairs and all full checks passed. No tracked verifier change was needed.
## Orchestrator review (Claude)
Accepted. The stamp matches the final Clang and GCC builds (`20d1ae65…`); demo-off owner hashes are identical to L45.
The segmented ramp (57 carves plus 107 pillars) is replaced by one continuous Bezier sweep with a hard floor cap;
headroom rose from 0.085 m to 2.8 m. Both controls fail as they should: the L45 ramp on floor ripple, and the buried
L43 layout on reachability. Follow-up for the verifier: the full tier's baseline export copies the whole HEAD tree
(about 785 MB) into `/tmp`, which is RAM-backed on this machine, and never deletes it. About 6 GB had accumulated.
It must export only the build inputs, into `Saved/Linux/`, and clean up after itself.
Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

@@ -0,0 +1,44 @@
## Key recommendations
1. **Add one shared curve sweep evaluator** for passage bores, the L45 ramp and R12 graph edges. Evaluate a smooth spline over global arc length, rather than taking a minimum over piecewise-linear capsules or discrete ramp stamps.
2. **Accelerate the global search with a conservative BVH.** Seed each surviving spline span from its chord projection, refine with a safeguarded solver, and compare all candidates whose bounds could beat the current best. One Newton solve from one seed is not a global closest-point solve.
3. **Keep the floor cap separate from tube ownership.** Use an explicit floor profile and R3’s floor-near candidate rule for overlapping bends and coils; keep relief and smooth unions away from the floor zero set.
4. **Use a sphere sweep as the fast, bounded field.** A general framed cross-section sweep is not guaranteed to be a true distance field on tight curves. Use rotation-minimising frames for its orientation, but validate curvature and retain conservative bounds for culling.
## Math and exactness
Represent the spine as a C1 or preferably C2 cubic spline \(C(s)\), parameterised by arc length \(s\). Interpolate radius \(r(s)\) and floor height \(h(s)\) as explicit route attributes. The round sweep is:
\[
\phi_{\text{tube}}(p)=\min_{s\in[0,L]} \left(\|p-C(s)\|-r(s)\right)
\]
This gives a continuous field with the correct zero set for the union of swept balls. It is exact distance outside that union; inside overlapping spheres it is only a distance bound, as the swept-volume literature cautions. The exact nearest-point equation for a cubic Bezier has degree five; Iñigo Quílez’s compact Bezier distance function is for a quadratic curve, so it is a useful small-case reference, not a complete cubic-tube solution. [IQ’s 2D distance functions](https://iquilezles.org/articles/distfunctions2d/), [point-to-NURBS distance paper](https://doi.org/10.1016/j.cad.2008.06.008), [swept-volume SDF analysis](https://doi.org/10.1145/3610548.3618196)
For the floor, define a separate cap from the selected route branch. For a single-valued floor graph \(h(x,y)\), a useful field is \((h(x,y)-z)/\sqrt{1+\lambda^2}\), where \(\lambda\) bounds the floor slope. Its zero set is the authored floor; it is exact distance for a planar floor and a conservative bound otherwise. Combine the tube and cap as an intersection, then carve using Core’s positive-air convention. Do not smooth-blend the floor edge or apply wall relief at the floor: either can shift the walk surface. The cave-network paper uses this slope-bounded height-field form and notes that arbitrary cross-section sweeps along high-curvature curves do not generally yield a continuous SDF. [Paris et al., *Synthesizing Geologically Coherent Cave Networks*](https://diglib.eg.org/items/a4e7985c-af52-4b55-bd1a-eeeff6c47422)
A circular sweep needs no frame. For an asymmetric cross-section, precompute a rotation-minimising frame along the arc-length table; the double-reflection method is a practical low-cost choice and avoids the Frenet frame’s flips at inflections. [Wang et al., *Computation of Rotation Minimizing Frames*](https://doi.org/10.1145/1330511.1330513)
## Cost and culling
Build an arc-length lookup table, spline-span bounds and optional frames once when resolving the layout. At sample time, traverse a BVH ordered by the conservative lower bound `distance(point, spanBounds) - maxRadius`. The current passage BVH already uses the analogous `AABB distance - maximum radius` bound; spline bounds must include each cubic span’s control hull, not just its endpoints.
Use the chord projection to seed a bracketed Newton or similar local solve on each promising span, include span endpoints, and retain the lowest result globally. A single seed can converge to the wrong local minimum near a bend or helix. For exact refinement, isolate all roots of the quintic stationary equation on the few surviving spans; variable radius adds a derivative term and makes the solve more costly. [The NURBS distance method](https://doi.org/10.1016/j.cad.2008.06.008) is a relevant example of clipping candidate regions before numerical refinement.
The exact minimum of 1-Lipschitz sphere fields is itself 1-Lipschitz. An *approximate* solver’s sampled value is not automatically a safe culling bound: it may overestimate the minimum. Keep a certified lower bound from the BVH/subdivision search for skip decisions, or stop with a known error gap and subtract that error. Report node visits, candidate spans, refinements and bound gaps per sample; a 256-span curve has about eight BVH levels before pruning, but tight overlapping coils may leave many candidates alive. Unreal’s spline API exposes closest-key queries, distance-along-spline queries and a reparameterisation table, matching the useful precomputed lookup pattern for game workloads. [Epic’s `USplineComponent` API](https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/Engine/USplineComponent)
## Floor ownership and code fit
For overlapping coils, do **not** use the closest 3D centerline to choose the floor. R3 recommends considering only floor candidates within half a voxel (0.125 m) vertically and inside the bore radius, then choosing the nearest floor point with a stable ID tie-break. Its synthetic helix showed roughly 3.37 m peak-to-peak error for closest-centerline ownership versus 0.029 m for floor-near ownership; it did not prove the rule fixes the real L38 ripple, so the real FI Style 2 route still needs measurement. [R3 floor ownership](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Research3/REPORT.md:5>) · [R12 graph-field recommendation](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Research12/REPORT.md:13>)
Put a shared evaluator in a Core internal sweep helper, with a resolved curve record carrying stable ID, cubic controls, arc-length attributes, floor/radius profiles and conservative bounds.
- **Passages:** adapt [`ApplyResolvedStratePassageCarves`](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:906>) to call it; retain bridge, mouth and support policy around the shared geometry query. Update [`BuildPassageNearestNode`](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:3349>) and its lower bounds for spline hulls.
- **L45 ramp:** replace the repeated ramp carve/support requests in [`MakeLandmarkChamberDemoRequests`](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Source/StreamBenchmarkHeadless.cpp:113>) with one floor-capped curve record. Route its evaluation through the shared composition/stamp path in [`ShapeWorldInternal.h`](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:1781>).
- **R12 graph edges:** store the same curve/floor data on each resolved edge and evaluate it from [`BindResolvedStratumFields`](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:286>); include blend, relief and floor-support reach in tile and shape-free bounds.
## Failure modes and suggested checks
The main risks are missed local minima, spline overshoot, curvature causing a swept cross-section to fold or overlap, variable radius changing the floor, frame flips, and hard floor-owner changes across nearby branches. Validate radius slope and curvature; use monotone floor interpolation where route height must not overshoot. Sphere-swept canal surfaces also become degenerate when radius changes as fast as the spine advances. [Canal surface conditions](https://mathworld.wolfram.com/CanalSurface.html)
For a zero-relief tight S-bend with nonuniform knot spacing, sample the floor crossing every 0.125 m of arc length against its analytic \(h(s)\): the analytic ripple should be 0, with measured error only from the solver/voxel tolerance and no peak at the knot spacing. Then run an overlapping helix with floor-near ownership, and the real L35/L36/L45 controls. Track floor peak-to-peak error, the 0.5–8 m ripple spectrum, culling false negatives, solver gaps and candidate counts. L35 and L36 documented the passage wall/floor beats, while L45 records the 57-carve/107-support ramp ribs. [L35](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux35/REPORT.md>) · [L36](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux36/REPORT.md>) · [L45](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux45/REPORT.md>)