passages: smooth 12 m lower-mouth radius taper; all four-strate passages pass (L68, v213)

The FI->TN wall beat (4.77 cm at 7.06 m) was the lower-mouth flare: the full mouth radius
was assigned to the penultimate control point, a one-segment radius jump. The shared route
builder now blends to the mouth radius over 12 m with a smoothstep. Wall ripple 1-2:
7.27 -> 1.62 cm. All three passages pass support/blocked/grade/ripple/naturalness; controls
detected. Fast tier 269/269 incl. the new-plan stage; W1/W8/W12 equal, Clang and GCC.
Hash pins: FI style 2 re-pinned at v213.

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-27 03:17:27 +01:00
1 parent 087333bf8a
commit bd7bba994c
10 files changed
+677 -12

No files matched your search

@@ -403,7 +403,7 @@ namespace VoxelForgeCore
// Version 210 keeps bulk native-cave sampling on the scalar field path at strata edges.
// Version 211 makes coordinate biasing in the shared cell hash unsigned, removing signed-overflow UB.
// Version 212 balances generated entry routes against existing walk lanes and preserves their shared treads.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 212;
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 213;
enum class FieldChannel : std::uint32_t
{
+19 -1
View File
@@ -3188,7 +3188,7 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
for(std::size_t i=0;i<xy.size();++i)
{
std::int64_t radius=(i<=1||i==lowerMouthIndex
||i+1>=xy.size()-1)?mouthRadius:midRadius;
||(i>lowerMouthIndex&&i+1>=xy.size()-1))?mouthRadius:midRadius;
if(surfaceGroundDeparture&&i<lowerMouthIndex)
{
const double t=std::clamp(static_cast<double>(cumulative[i])
@@ -3197,6 +3197,24 @@ bool PlanResolvedLayoutPassagesV1(ResolvedLayoutSnapshotV3& layout,std::int32_t
radius=surfacePortalRadius+static_cast<std::int64_t>(std::llround(
(midRadius-surfacePortalRadius)*smooth));
}
// Grow the lower bore into its mouth over fixed route distance. Assigning
// the full mouth radius to the penultimate point creates a segment-length
// flare whose cubic-detrended profile can read as a short-period wall beat.
if(i<=lowerMouthIndex)
{
constexpr std::int64_t LowerMouthRadiusBlendLengthMetres=12;
const std::uint64_t blendLength=static_cast<std::uint64_t>(
std::max<std::int64_t>(LowerMouthRadiusBlendLengthMetres*qPerMetre,
2*mouthRadius));
const std::uint64_t distanceToLowerMouth=mouthHorizontal-cumulative[i];
if(distanceToLowerMouth<blendLength)
{
const double t=static_cast<double>(distanceToLowerMouth)/blendLength;
const double smooth=t*t*(3.0-2.0*t);
radius=midRadius+static_cast<std::int64_t>(std::llround(
(mouthRadius-midRadius)*(1.0-smooth)));
}
}
std::int64_t playerZ=0;
if(i>lowerMouthIndex)
playerZ=lowerLandingPoints[i-lowerMouthIndex-1][2];
@@ -0,0 +1,395 @@
#!/usr/bin/env python3
"""Render arrival, departure, and mid-tunnel views for the four-strate owner plan."""
import json
import importlib.util
import argparse
import math
import os
import re
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l68/captures-run"
BIN = ROOT / "Saved/Linux/l68/bin-final-clang"
CAPTURES = Path(__file__).resolve().parent / "captures"
HEADLESS = BIN / "VoxelForgeCoreHeadless-l68-final-clang"
RENDERER = BIN / "VoxelForgeOffscreenCapture-l68-final-clang"
PNG_DIR = OUT / "capture-png"
RECIPE_INPUTS = (
("passage-0-1", ROOT / "Standalone/data/owner_world.json",
"surface-world", "SurfaceWorld", "upper"),
("passage-1-2", ROOT / "Standalone/data/owner_world.json",
"surface-world", "FloatingIslands", "upper"),
("passage-2-3", ROOT / "Standalone/data/owner_world.json",
"surface-world", "TunnelNetwork", "upper"),
)
SUBVOXELS_PER_VOXEL = 256.0
RING_AUDIT = ROOT / "Standalone/Research/WorldAssemblerM3/Linux32/AuditRingTerraceL32.py"
spec = importlib.util.spec_from_file_location("ring_profile_l32", RING_AUDIT)
ring_profile = importlib.util.module_from_spec(spec)
spec.loader.exec_module(ring_profile)
for directory in (OUT, BIN, PNG_DIR, CAPTURES):
directory.mkdir(parents=True, exist_ok=True)
ENV = os.environ.copy()
ENV["LP_NUM_THREADS"] = "12"
ENV["XDG_CACHE_HOME"] = str(OUT / "xdg-cache")
PARSER = argparse.ArgumentParser(description=__doc__)
PARSER.add_argument("--scene", choices=[value[0] for value in RECIPE_INPUTS])
PARSER.add_argument("--view", choices=("arrival-mouth", "departure-mouth", "mid-tunnel"))
OPTIONS = PARSER.parse_args()
def run(name, command):
log = OUT / f"capture-{name}.log"
wrapped = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
"timeout", "1800s", *map(str, command)]
started = time.monotonic()
with log.open("w", encoding="utf-8") as stream:
result = subprocess.run(wrapped, cwd=ROOT, env=ENV, stdout=stream,
stderr=subprocess.STDOUT, timeout=1800, check=False)
elapsed = time.monotonic() - started
print(f"[L68CaptureRun] step={name} elapsed={elapsed:.1f}s exit={result.returncode} log={log}",
flush=True)
if result.returncode != 0:
raise SystemExit(f"{name} failed; see {log}")
return log
def add(a, b):
return tuple(x + y for x, y in zip(a, b))
def sub(a, b):
return tuple(x - y for x, y in zip(a, b))
def mul(a, scale):
return tuple(x * scale for x in a)
def norm(a):
length = math.sqrt(sum(x * x for x in a))
if length <= 1.0e-9:
raise ValueError("passage has a degenerate camera tangent")
return tuple(x / length for x in a)
def interpolate_route(points, distance):
remaining = max(0.0, distance)
for a, b in zip(points, points[1:]):
delta = sub(b[0], a[0])
length = math.sqrt(sum(x * x for x in delta))
if length <= 1.0e-9:
continue
if remaining <= length:
t = remaining / length
pos = tuple(a[0][axis] + delta[axis] * t for axis in range(3))
radius = a[1] + (b[1] - a[1]) * t
return pos, radius
remaining -= length
return points[-1]
def route_frame(points, distance):
center, radius = interpolate_route(points, distance)
before, _ = interpolate_route(points, max(0.0, distance - 0.25))
after, _ = interpolate_route(points, distance + 0.25)
tangent = norm(sub(after, before))
horizontal = norm((tangent[0], tangent[1], 0.0))
side = (-horizontal[1], horizontal[0], 0.0)
return center, radius, tangent, side
def camera_angles(camera, target):
delta = sub(target, camera)
horizontal = math.hypot(delta[0], delta[1])
yaw = math.degrees(math.atan2(delta[0], delta[1]))
pitch = math.degrees(math.atan2(delta[2], horizontal))
return yaw, pitch
def fmt(values):
return ",".join(f"{value:.6f}" for value in values)
def load_reference_cameras():
log = ROOT / "Saved/Linux/l34/run-capture-standard-set-final-radius3.log"
pattern = re.compile(
r"^\[L34CaptureCamera\] view=(\S+).*?camera_m=\(([^)]*)\) "
r"target_m=\(([^)]*)\) clip=(\S+)", re.M)
values = {}
for name, camera, target, clip in pattern.findall(
log.read_text(encoding="utf-8", errors="replace")):
parse = lambda value: tuple(float(part) for part in value.split(","))
values[name] = (parse(camera), parse(target), None if clip == "none" else parse(clip))
return values
REFERENCE_CAMERAS = {}
def terrain_surface_near(mesh, x, y, expected_height):
bounds = (x - 2.0, x + 2.0, y - 2.0, y + 2.0)
_, triangles, _ = ring_profile.read_scene(
str(mesh), None, -1.0e9, 1.0e9, bounds)
buckets = ring_profile.build_buckets(triangles, True, bounds, cell_size=1.0)
hits = []
for dy in range(-4, 5):
for dx in range(-4, 5):
sample_x, sample_y = x + dx * 0.5, y + dy * 0.5
hit = ring_profile.sample_surface(buckets, sample_x, sample_y, True, 1.0,
preferred_height=expected_height)
if hit is not None:
hits.append((math.hypot(dx * 0.5, dy * 0.5),
abs(hit[0] - expected_height), sample_x, sample_y, hit[0]))
if not hits:
return None
distance, _, sample_x, sample_y, height = min(hits)
if distance > 2.0 or abs(height - expected_height) > 8.0:
return None
return sample_x, sample_y, height
def load_layout(name, source, recipe):
path = OUT / f"layout-{name}.json"
run(f"layout-{name}", [HEADLESS, source, "--workers=12", "--world-assembler-prototype",
"--stream-benchmark", "--stream-pipeline", "--force-generate", "--clip-radius=2",
"--max-clip-level=0", "--max-level=0", f"--recipe={recipe}",
f"--resolved-layout-output={path}", "--resolved-layout-only"])
return json.loads(path.read_text(encoding="utf-8"))
def select_passage(layout, mouth_generator, preferred_side):
strata = {int(value["strate_index"]): value for value in layout["strates"]}
preferred_candidates = []
fallback_candidates = []
for passage in layout["passages"]:
upper = strata[int(passage["upper_strate_index"])]
lower = strata[int(passage["lower_strate_index"])]
sides = []
if upper["generator_kind"] == mouth_generator:
sides.append("upper")
if lower["generator_kind"] == mouth_generator:
sides.append("lower")
if preferred_side in sides:
preferred_candidates.append((passage, preferred_side == "lower"))
elif sides:
fallback_candidates.append((passage, sides[0] == "lower"))
candidates = preferred_candidates or fallback_candidates
if not candidates:
raise RuntimeError(f"no passage mouth in generator {mouth_generator}")
return sorted(candidates, key=lambda item: item[0]["stable_id"])[0]
def make_views(layout, passage, reverse):
q_to_m = layout["core_voxel_size_um"] / (SUBVOXELS_PER_VOXEL * 1_000_000.0)
controls = [
(tuple(value * q_to_m for value in point["position_q"]),
point["radius_q"] * q_to_m)
for point in passage["control_points"]
]
lower_mouth = tuple(value * q_to_m for value in passage["lower_mouth_q"])
lower_index = min(range(len(controls)), key=lambda i: sum(
(controls[i][0][axis] - lower_mouth[axis]) ** 2 for axis in range(3)))
path = controls[:lower_index + 1]
if len(path) < 2:
raise RuntimeError(f"{passage['stable_id']} has no mouth-to-mouth route")
if reverse:
path.reverse()
lengths = [math.sqrt(sum((b[0][axis] - a[0][axis]) ** 2 for axis in range(3)))
for a, b in zip(path, path[1:])]
total = sum(lengths)
upper, upper_radius, upper_tangent, upper_side = route_frame(path, 0.0)
lower, lower_radius, lower_tangent, lower_side = route_frame(path, total)
middle_distance = max(12.0, min(total - 12.0, total * 0.4)) if total > 24.0 else total * 0.4
if (int(passage["upper_strate_index"],) == 1
and int(passage["lower_strate_index"]) == 2 and not reverse):
# The old 7 m authored-radius beat sat near the middle of this audit window.
middle_distance = min(total - 12.0, 90.8)
entry_distance = min(6.0, total * 0.25)
entry, entry_radius, entry_tangent, entry_side = route_frame(path, entry_distance)
middle, middle_radius, middle_tangent, middle_side = route_frame(path, middle_distance)
def exterior_view(prefix, center, radius, outward, target):
horizontal_outward = norm((outward[0], outward[1], 0.0))
eye_height = center[2] - radius + 1.6
eye = (center[0] + horizontal_outward[0] * 5.5,
center[1] + horizontal_outward[1] * 5.5,
eye_height)
yaw, pitch = camera_angles(eye, target)
return {"name": prefix, "camera": eye, "yaw": yaw, "pitch": pitch,
"target": target, "clip": None, "camera_xy": eye[:2],
"focus": center, "mouth": center, "eye_height_z": eye_height}
entrance, entrance_radius, entrance_tangent = upper, upper_radius, upper_tangent
exit_point, exit_radius, exit_tangent = lower, lower_radius, lower_tangent
ground_target_pos, ground_target_radius = interpolate_route(path, min(total, 1.0))
ground = exterior_view("ground-mouth", entrance, entrance_radius,
mul(entrance_tangent, -1.0), (ground_target_pos[0], ground_target_pos[1],
ground_target_pos[2] - ground_target_radius + 1.0))
ground["focus"] = entrance
ground["outside_camera"] = True
def cutaway_view(prefix, center, radius, tangent, side, distance, target_distance):
camera = (center[0] - side[0] * 7.0, center[1] - side[1] * 7.0,
center[2] - radius + 1.6)
target_pos, target_radius = interpolate_route(path, target_distance)
target = (target_pos[0], target_pos[1],
target_pos[2] - target_radius + 1.6)
yaw, pitch = camera_angles(camera, target)
plane = (side[0], side[1], 0.0,
-(side[0] * center[0] + side[1] * center[1]))
return {"name": prefix, "camera": camera, "yaw": yaw, "pitch": pitch,
"target": target, "clip": plane, "camera_xy": camera[:2],
"focus": center, "mouth": center}
def inside_mouth_view(prefix, at_start):
endpoint_distance = 0.0 if at_start else total
mouth, _, tangent, mouth_side = route_frame(path, endpoint_distance)
camera_distance = min(total, 7.4) if at_start else max(0.0, total - 5.5)
center, _, _, side = route_frame(path, camera_distance)
camera = (center[0] + side[0] * 2.5,
center[1] + side[1] * 2.5, center[2])
outward = mul(tangent, -1.0) if at_start else tangent
target = (mouth[0] + outward[0] * 8.0 + mouth_side[0] * 2.5,
mouth[1] + outward[1] * 8.0 + mouth_side[1] * 2.5,
mouth[2])
yaw, pitch = camera_angles(camera, target)
return {"name": prefix, "camera": camera, "yaw": yaw, "pitch": pitch,
"target": target, "clip": None, "camera_xy": camera[:2],
"focus": mouth, "mouth": mouth, "outside_camera": False,
"camera_location": "passage-air", "focus_radius": 30.0,
"eye_height_z": camera[2], "fov_deg": 80.0}
# Place each interface view at its true route endpoint. The endpoint camera
# is a side cutaway so the solid terrain in front of an underground mouth
# cannot hide the floor-to-tunnel connection.
arrival_distance = 0.0
arrival_center, arrival_radius, arrival_tangent, arrival_side = route_frame(
path, arrival_distance)
arrival = cutaway_view("arrival", arrival_center, arrival_radius,
arrival_tangent, arrival_side, arrival_distance,
min(total, arrival_distance + 12.0))
arrival["camera_location"] = "passage-air"
arrival["focus_radius"] = 20.0
arrival["yaw"], arrival["pitch"] = camera_angles(
arrival["camera"], arrival["target"])
entry_camera_distance = min(8.0, total * 0.1)
entry_center, entry_radius, entry_tangent, entry_side = route_frame(
path, entry_camera_distance)
# Player-height view from just inside the passage, aimed through its actual
# interface mouth so the floor, bore, and opening share one frame.
entry_camera = (entry_center[0], entry_center[1],
entry_center[2] - entry_radius + 1.6)
entry_target_pos, entry_target_radius = interpolate_route(
path, min(total, entry_distance + 14.0))
entry_target = (entry_target_pos[0], entry_target_pos[1],
entry_camera[2] - 2.5)
entry_yaw, entry_pitch = camera_angles(entry_camera, entry_target)
entry_view = {"name": "rock-entry", "camera": entry_camera,
"yaw": entry_yaw, "pitch": entry_pitch, "target": entry_target,
"clip": None, "camera_xy": entry_camera[:2],
"focus": entry_center, "mouth": entrance, "outside_camera": False,
"camera_location": "passage-air", "focus_radius": 20.0,
"eye_height_z": entry_camera[2]}
middle_view = cutaway_view("mid-tunnel", middle, middle_radius, middle_tangent,
middle_side, middle_distance, min(total, middle_distance + 2.0))
ground["focus_radius"] = 20.0
middle_view["focus_radius"] = 20.0
middle_camera_center, _ = interpolate_route(path, middle_distance)
middle_view["camera"] = (middle_camera_center[0] + middle_side[0] * 0.75,
middle_camera_center[1] + middle_side[1] * 0.75,
middle[2] - middle_radius + 1.6)
middle_target_pos, middle_target_radius = interpolate_route(
path, min(total, middle_distance + 14.0))
middle_view["target"] = (middle_target_pos[0] + middle_side[0] * 2.35,
middle_target_pos[1] + middle_side[1] * 2.35,
middle_target_pos[2] - middle_target_radius + 1.8)
# Keep the camera inside the bore, close to one wall, and look down the
# route so the old beat location is visible at player height.
middle_view["clip"] = None
middle_view["camera_location"] = "passage-air"
middle_view["yaw"], middle_view["pitch"] = camera_angles(
middle_view["camera"], middle_view["target"])
return (ground, entry_view, middle_view, arrival,
inside_mouth_view("inside-mouth-start", True),
inside_mouth_view("inside-mouth-end", False)), total, lower_index
def export_capture(scene_name, source, recipe, passage, endpoint, view):
stem = f"{passage['stable_id'].replace('/', '-')}-{endpoint}"
view["name"] = stem
mesh = OUT / f"{stem}.vfmesh"
png = PNG_DIR / f"{stem}.png"
jpg = CAPTURES / f"{stem}.jpg"
yaw, pitch = view["yaw"], view["pitch"]
camera = view["camera"]
export_camera = view.get("focus", camera)
run(f"{stem}-export", [HEADLESS, source, "--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", f"--recipe={recipe}",
f"--camera={fmt((*export_camera, yaw, pitch))}", f"--mesh-export={mesh}"])
render_clip = view["clip"]
surface = None
if view.get("outside_camera", False):
surface = terrain_surface_near(mesh, *view["camera_xy"], view["target"][2])
if surface is None:
camera = (view["camera_xy"][0], view["camera_xy"][1], view["eye_height_z"])
else:
camera = (surface[0], surface[1], surface[2] + 1.6)
elif render_clip is not None:
camera = view["camera"]
yaw, pitch = camera_angles(camera, view["target"])
fov_deg = view.get("fov_deg", 80.0)
print(f"[L68CaptureCamera] view={stem} camera_m=({fmt(camera)}) "
f"target_m=({fmt(view['target'])}) "
f"clip={fmt(render_clip) if render_clip is not None else 'none'} fov_deg={fov_deg:.1f}",
flush=True)
render = [RENDERER, mesh, png, "--size=1600x900", f"--fov-deg={fov_deg:.1f}",
f"--camera-m={fmt(camera)}", f"--yaw-deg={yaw:.6f}", f"--pitch-deg={pitch:.6f}",
"--tile-skirts=off", "--shade=readable", "--headlamp=on", "--height-tint=on",
f"--height-center-m={view['target'][2]:.6f}", "--height-range-m=8", "--tile-edges=off"]
if view.get("focus_radius", 24.0) is not None:
render.append(f"--focus-region={fmt((*view['focus'], view.get('focus_radius', 24.0)))}")
if render_clip is not None:
render.append(f"--clip-plane={fmt(render_clip)}")
run(f"{stem}-render", render)
run(f"{stem}-jpeg", ["ffmpeg", "-nostdin", "-hide_banner", "-loglevel", "error",
"-y", "-i", png, "-frames:v", "1", "-q:v", "4", jpg])
size = jpg.stat().st_size if jpg.exists() else 0
print(f"[L68CaptureJPEG] file={jpg.relative_to(ROOT)} bytes={size} "
f"status={'PASS' if 0 < size <= 300_000 else 'FAIL'}", flush=True)
if not 0 < size <= 300_000:
raise SystemExit(f"{jpg.name} is missing or exceeds 300 KB")
for scene_name, source, recipe, mouth_generator, preferred_side in RECIPE_INPUTS:
if OPTIONS.scene and scene_name != OPTIONS.scene:
continue
layout = load_layout(scene_name, source, recipe)
passage, _ = select_passage(layout, mouth_generator, preferred_side)
forward_views, route_length, lower_index = make_views(layout, passage, False)
reverse_views, _, _ = make_views(layout, passage, True)
print(f"[L68CapturePassage] interface={scene_name.removeprefix('passage-')} "
f"id={passage['stable_id']} route_m={route_length:.3f} "
f"control_points={lower_index + 1}", flush=True)
if scene_name == "passage-2-3":
endpoint_views = (("arrival-mouth", forward_views[4]),
("departure-mouth", forward_views[5]))
else:
endpoint_views = (
("arrival-mouth", forward_views[0] if scene_name == "passage-0-1" else forward_views[1]),
("departure-mouth", reverse_views[3]),
)
for endpoint, view in endpoint_views:
if OPTIONS.view and endpoint != OPTIONS.view:
continue
export_capture(scene_name, source, recipe, passage, endpoint, view)
if scene_name == "passage-1-2" and (OPTIONS.view is None or OPTIONS.view == "mid-tunnel"):
export_capture(scene_name, source, recipe, passage, "mid-tunnel", forward_views[2])
@@ -0,0 +1,48 @@
# Linux68 — FI→TN 7 m wall beat
## Cause and fix
The 7.06 m beat came from the authored-radius profile. In the failing 32 m window, a radius-only diagnostic reproduces 4.77 cm at 7.0625 m. The route’s interior controls are generally 5.6–6.3 m apart; the last 3.0→4.5 m radius change spans 5.803 m, followed by an 8.8 m constant-radius span. The measured beat does not repeat at either spacing. Removing relief left 7.46 cm, and restoring the earlier carve cutoff left 7.55 cm. The shorter 114.23 m route moved the lower-mouth flare into the failing window; the L67 split rose from 6.78 to 14.52 cm.
The shared route builder now blends the lower-mouth radius over 12 m with a smooth distance-based taper, replacing the single-segment radius jump. Evaluator version is **v213**. L67 support changes remain in place.
## Passage audits
Clang and GCC produced identical results under the authored-radius gauge with cubic detrending per 32 m window. Limits are unchanged: wall ≤3.5 cm, floor ≤2.5 cm.
| Interface | Wall ripple | Period | Floor ripple | Blocked / unsupported / grade | Result |
|---|---:|---:|---:|---:|---|
| FI 0–1 | 1.45 cm | 4.562 m | 0.06 cm | 0 / 0 / 0 | PASS |
| FI 1–2 | 1.62 cm | 7.250 m | 1.33 cm | 0 / 0 / 0 | PASS |
| TN 2–3 | 0.92 cm | 7.375 m | 0.32 cm | 0 / 0 / 0 | PASS |
Naturalness, mouth profile, and ripple audits passed 3/3. Synthetic sphere, floor bead, floor step, L23 smooth-wall, and L23 terrace controls were detected. Blocked controls were detected 3/3. The new-plan generator/style maps, 3/3 interfaces, and three transition audits passed; width and thickness negative controls were rejected.
Clang and GCC builds passed with source stamp `33a8215f36abc00fadcdde5d6f3ff2d7054454fc2158e32470fb059e68bbd12e`. W1/W8/W12 hashes matched for all four strata on both compilers (8 compiler/stratum rows, 12 hash rows per worker count). The final fast tier passed **269/269** checks in 265.1 s. Its new-plan stage passed. The first fast attempt exposed the expected v213 floating-islands hash change against the old L52 pin; the current W1/W12 hashes match, and the v213 pin is [here](hash-baselines/owner-hash-floating-islands-style2-v213.log).
## Captures
All files are below 300 KB. The 1–2 camera is at the old ripple window. The 2–3 cameras are inside the passage and aimed through the mouths. The upper 2–3 exterior is sparse in the capture mesh, so that view reads as a dark opening.
| View | File | Bytes | SHA-256 |
|---|---|---:|---|
| 1–2 mid-tunnel | [JPEG](captures/passage-1-2-0-mid-tunnel.jpg) | 29,282 | `39381b01ae4d1674800391c6d8c65383e0d6866abf3cd70a8330062c677d06fa` |
| 2–3 arrival mouth | [JPEG](captures/passage-2-3-0-arrival-mouth.jpg) | 20,123 | `f73ce987932a5e2ba165a3272b18d8786fcce3f815d0c2a1edcf13c99cc3f7b4` |
| 2–3 departure mouth | [JPEG](captures/passage-2-3-0-departure-mouth.jpg) | 26,024 | `7665166f8f2e78b86774931e53af32243a5f40d2fc95e1b7ad4bf8cd6d310bd5` |
## Whole-view cost
Three interleaved L67/L68 pairs per stratum; all 24 runs exited 0 with 12 hash rows.
| Stratum | L67 median | L68 median | Change |
|---:|---:|---:|---:|
| 0 | 1.011 s | 1.074 s | +6.23% |
| 1 | 1.494 s | 1.503 s | +0.60% |
| 2 | 0.581 s | 0.577 s | −0.69% |
| 3 | 0.210 s | 0.210 s | 0.00% |
## Failed runs and discarded diagnostics
The first fast attempt failed only on the stale L52 floating-islands hash expectation; the updated v213 pin and final fast run passed. Relief-off and old-cutoff experiments still failed the wall limit. A generic control-point refinement reduced ripple but introduced one unsupported sample; a post-route refinement retained 7.23 cm ripple. Those experiments were reverted. One early audit used the landmark-demo flag on an incompatible passage fixture and exited during route setup; the corrected audit passed.
Evidence is under `Saved/Linux/l68`: `build-clang.log`, `build-gcc.log`, `logs/final-{clang,gcc}-owner.log`, `logs/transition-clang.log`, `verify/owner-w1-w8-w12-determinism.json`, `cost/cost-summary.json`, and `verify/fast-tier-final.log`.
@@ -0,0 +1,105 @@
#!/usr/bin/env python3
"""Measure three interleaved L67/L68 whole-view pairs per owner strate."""
import json
import os
import re
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l68/cost"
DATA = ROOT / "Standalone/data/owner_world.json"
BINARIES = {
"l67": ROOT / "Saved/Linux/l67/bin-final/VoxelForgeCoreHeadless-l67-final-clang",
"l68": ROOT / "Saved/Linux/l68/bin-final-clang/VoxelForgeCoreHeadless-l68-final-clang",
}
CAMERAS = {
0: "0.000000,0.000000,-374.939453,0.000000,0.000000",
1: "25.836914,3.199219,-737.000000,0.000000,0.000000",
2: "19.166016,-14.200195,-753.374023,0.000000,0.000000",
3: "-20.062500,-5.068359,-900.353516,0.000000,0.000000",
}
ORDER = ("l67", "l68", "l68", "l67", "l67", "l68")
PREFIXES = (
"[PipelineFullDetailHash]", "[PipelineWholeViewHash]",
"[PipelineLODHash]", "[PipelineExactQueryHash]",
)
ELAPSED_RE = re.compile(r"\belapsed_ms=([0-9.]+)")
WHOLE_VIEW_RE = re.compile(r"^\[StreamPipeline\].*?whole_view_ready=([0-9.]+)s", re.M)
ENV = os.environ.copy()
def run(strate, repetition, variant):
name = f"strate{strate}-pair{repetition // 2 + 1}-{variant}"
log_path = OUT / f"{name}.log"
layout_path = OUT / f"{name}.json"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
"timeout", "1740s", str(BINARIES[variant]), str(DATA), "--workers=1",
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
"--force-generate", "--clip-radius=1", "--max-clip-level=8", "--max-level=0",
"--recipe=surface-world", "--stream-hash", "--max-clip-level=0",
"--render-distance-chunks=0", f"--camera={CAMERAS[strate]}",
f"--resolved-layout-output={layout_path}",
]
start = time.monotonic()
with log_path.open("w", encoding="utf-8") as stream:
result = subprocess.run(command, cwd=ROOT, env=ENV, stdout=stream,
stderr=subprocess.STDOUT, timeout=1740, check=False)
elapsed = time.monotonic() - start
lines = log_path.read_text(encoding="utf-8", errors="replace").splitlines()
hashes = [line for line in lines if line.startswith(PREFIXES)]
pipeline_elapsed = [float(value) for line in lines
if line.startswith("[PipelineWholeViewHash]")
for value in ELAPSED_RE.findall(line)]
whole_view_match = WHOLE_VIEW_RE.search("\n".join(lines))
record = {
"strate": strate, "pair_order": repetition, "variant": variant,
"elapsed_seconds": elapsed, "pipeline_elapsed_ms": pipeline_elapsed,
"whole_view_seconds": float(whole_view_match.group(1))
if whole_view_match else None,
"exit_code": result.returncode, "hash_rows": len(hashes),
"log": str(log_path.relative_to(ROOT)),
}
print(json.dumps(record, sort_keys=True), flush=True)
return record
def main():
OUT.mkdir(parents=True, exist_ok=True)
results = []
for strate in range(4):
for repetition, variant in enumerate(ORDER):
record = run(strate, repetition, variant)
results.append(record)
if record["exit_code"] != 0 or record["hash_rows"] != 12:
break
else:
continue
break
strata = {}
for strate in range(4):
values = {variant: [row["whole_view_seconds"] for row in results
if row["strate"] == strate and row["variant"] == variant
and row["whole_view_seconds"] is not None]
for variant in ("l67", "l68")}
if all(len(values[variant]) == 3 for variant in ("l67", "l68")):
l67 = sorted(values["l67"])[1]
l68 = sorted(values["l68"])[1]
strata[str(strate)] = {"l67_seconds": values["l67"],
"l68_seconds": values["l68"], "l67_median_seconds": l67,
"l68_median_seconds": l68,
"change_percent": (l68 / l67 - 1.0) * 100.0}
summary = {"pairs_per_strate": 3, "order": ORDER, "strata": strata,
"runs": results, "complete": len(results) == 24
and all(x["exit_code"] == 0 and x["hash_rows"] == 12 for x in results)}
(OUT / "cost-summary.json").write_text(json.dumps(summary, indent=2) + "\n",
encoding="utf-8")
print(f"[L68CostSummary] complete={summary['complete']} runs={len(results)}", flush=True)
return 0 if summary["complete"] else 1
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,94 @@
#!/usr/bin/env python3
"""Compare owner four-strata hashes at W1/W8/W12 with both compilers."""
import json
import re
import subprocess
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l68"
DATA = ROOT / "Standalone/data/owner_world.json"
LAYOUT = OUT / "layouts/final-clang-owner.json"
BINARIES = {
"clang": OUT / "bin-final-clang/VoxelForgeCoreHeadless-l68-final-clang",
"gcc": OUT / "bin-final-gcc/VoxelForgeCoreHeadless-l68-final-gcc",
}
HASH_RE = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M)
RESULTS = []
def hashes(path):
return HASH_RE.findall(path.read_text(encoding="utf-8", errors="replace"))
def cameras_by_strate():
layout = json.loads(LAYOUT.read_text(encoding="utf-8"))
scale = float(layout["core_voxel_size_um"]) / 256_000_000.0
cameras = {}
for passage in layout["passages"]:
upper = str(int(passage["upper_strate_index"]))
lower = str(int(passage["lower_strate_index"]))
cameras.setdefault(upper, tuple(float(v) * scale for v in passage["upper_mouth_q"]))
cameras[lower] = tuple(float(v) * scale for v in passage["lower_mouth_q"])
if set(cameras) != {"0", "1", "2", "3"}:
raise RuntimeError(f"expected a camera for all four strata; found {sorted(cameras)}")
return cameras
def main():
(OUT / "verify").mkdir(parents=True, exist_ok=True)
logs = OUT / "logs/determinism"
layouts = OUT / "layouts/determinism"
logs.mkdir(parents=True, exist_ok=True)
layouts.mkdir(parents=True, exist_ok=True)
cameras = cameras_by_strate()
for compiler, binary in BINARIES.items():
for strate in range(4):
camera = ",".join(f"{value:.6f}" for value in (*cameras[str(strate)], 0.0, 0.0))
outputs = {}
codes = {}
for workers in (1, 8, 12):
name = f"owner-new-plan-{compiler}-strate{strate}-w{workers}"
log_path = logs / f"{name}.log"
layout_path = layouts / f"{name}.json"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
"timeout", "1740s", str(binary), str(DATA), f"--workers={workers}",
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
"--force-generate", "--clip-radius=1", "--max-clip-level=8",
"--max-level=0", "--recipe=surface-world", "--stream-hash",
"--max-clip-level=0", "--render-distance-chunks=0", f"--camera={camera}",
f"--resolved-layout-output={layout_path}",
]
with log_path.open("w", encoding="utf-8") as stream:
result = subprocess.run(command, cwd=ROOT, stdout=stream,
stderr=subprocess.STDOUT, timeout=1740, check=False)
outputs[workers] = hashes(log_path)
codes[workers] = result.returncode
print(json.dumps({"compiler": compiler, "strate": strate,
"workers": workers, "exit_code": result.returncode,
"hash_rows": len(outputs[workers]), "log": str(log_path.relative_to(ROOT))},
sort_keys=True), flush=True)
if result.returncode != 0 or len(outputs[workers]) != 12:
break
passed = (set(codes) == {1, 8, 12} and all(code == 0 for code in codes.values())
and outputs[1] == outputs[8] == outputs[12])
RESULTS.append({"compiler": compiler, "strate": strate,
"workers": {str(k): len(v) for k, v in outputs.items()},
"exit_codes": {str(k): v for k, v in codes.items()},
"w1_w8_w12_equal": passed})
if not passed:
break
if RESULTS[-1]["compiler"] != compiler or not RESULTS[-1]["w1_w8_w12_equal"]:
break
passed = len(RESULTS) == 8 and all(row["w1_w8_w12_equal"] for row in RESULTS)
summary = {"status": "PASS" if passed else "FAIL", "strata": RESULTS}
(OUT / "verify/owner-w1-w8-w12-determinism.json").write_text(
json.dumps(summary, indent=2) + "\n", encoding="utf-8")
print(f"[L68OwnerW1W8W12] status={summary['status']} rows={len(RESULTS)}", flush=True)
return 0 if passed else 1
if __name__ == "__main__":
raise SystemExit(main())
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

+15 -10
View File
@@ -30,6 +30,7 @@ LINUX56 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux56"
LINUX58 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux58"
LINUX60 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux60"
LINUX67 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux67"
LINUX68 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux68"
OWNER = ROOT / "Standalone/data/regression/owner_world_2strate_l61.json"
OWNER_NEW = ROOT / "Standalone/data/owner_world.json"
OWNER_2STRATE_SHA256 = "7b095f9bcc6b90133d5a463f99f0b571133b2c549ce1ecf2d64fe9175e41e183"
@@ -101,6 +102,16 @@ RECIPE_RE = re.compile(
r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$", re.M)
def owner_hash_baseline(recipe: str, style: int) -> tuple[Path, str]:
if recipe == "surface-world" and style == 1:
return (LINUX67 / "hash-baselines" / "owner-hash-surface-world-style1-v212.log",
"L67-v212")
if recipe == "floating-islands" and style == 2:
return (LINUX68 / "hash-baselines" / "owner-hash-floating-islands-style2-v213.log",
"L68-v213")
raise VerificationFailure(f"no pinned owner hash baseline for {recipe} style {style}")
def compiler_name(binary: Path) -> str:
return "gcc" if "gcc" in binary.name else "clang"
@@ -624,13 +635,7 @@ def run_hash_pairs(runner: VerificationRunner,
l52_baseline = ROOT / "Saved/Linux/l52" / f"owner-hash-{recipe}-style{style}-w12.log"
l52_hashes = tuple(HASH_RE.findall(l52_baseline.read_text(
encoding="utf-8", errors="replace")))
if recipe == "surface-world":
expected_baseline = LINUX67 / "hash-baselines" / (
"owner-hash-surface-world-style1-v212.log")
expected_label = "L67-v212"
else:
expected_baseline = l52_baseline
expected_label = "L52"
expected_baseline, expected_label = owner_hash_baseline(recipe, style)
expected_hashes = tuple(HASH_RE.findall(expected_baseline.read_text(
encoding="utf-8", errors="replace")))
same_expected = hashes[12] == expected_hashes and len(expected_hashes) == 12
@@ -674,11 +679,11 @@ def run_default_profile_identity(runner: VerificationRunner, binary: Path) -> No
expected_style=2, expected_strate_styles={"0": 2, "1": 1}, workers=12,
layout_path=OUT / "layouts" / f"{name}.json")
values = tuple(HASH_RE.findall(output))
baseline = ROOT / "Saved/Linux/l52" / f"owner-hash-{recipe}-style{style}-w12.log"
baseline, label = owner_hash_baseline(recipe, style)
expected = tuple(HASH_RE.findall(baseline.read_text(
encoding="utf-8", errors="replace")))
runner.require(f"{name}:matches-L52", len(values) == 12 and values == expected,
f"current={len(values)} L52={len(expected)} exact canonical hash rows")
runner.require(f"{name}:matches-{label}", len(values) == 12 and values == expected,
f"current={len(values)} {label}={len(expected)} exact canonical hash rows")
class _SplitMix64: