feat(core): native lattice generator, slice 1 -- helix-ramp spine + small maze (L58); research R27

Core.Lattice.PrimitiveField v1, opt-in per strate (legacy Maze/VerticalShaft stay legacy): resolves the real
arrival and departure mouths first, plans a mandatory spine, then maze cells and two dead ends (9 rooms,
9 edges, stable IDs). The spine descends 20 m through four helix turns (6 m radius, 3 m clear width, 5 m
pitch, 2.6 m clearance; max grade 10.0 deg); each feature is one filleted void (0.57 m measured). Final-field
reachability passes at 883 stations; an orphaned shaft control is rejected; exact intervals (0 misses) and
a whole-surface audit with 0 flags. Whole view 1.69 s (above the 1 s target). fast/medium/full PASS.
Research R27 (self-checked): static stream-to-pool water design.

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-25 15:45:32 +01:00
1 parent 1e3e04bbac
commit 6c6cc37e1d
25 files changed
+280497 -117

No files matched your search

@@ -0,0 +1,249 @@
#!/usr/bin/env python3
"""Run L54's triangle audit over L58's explicit lattice polylines and controls."""
from __future__ import annotations
import argparse
import importlib.util
import json
import math
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
AUDIT54 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux54/AuditWholeSurfaceL54.py"
spec = importlib.util.spec_from_file_location("whole_surface_l54", AUDIT54)
audit54 = importlib.util.module_from_spec(spec)
assert spec and spec.loader
spec.loader.exec_module(audit54)
original_make_route = audit54.make_route
def build_segment_bvh(segments: list[tuple]) -> dict:
def build(indices: list[int]) -> dict:
minimum = tuple(min(min(segments[index][0][axis], segments[index][1][axis])
for index in indices) for axis in range(3))
maximum = tuple(max(max(segments[index][0][axis], segments[index][1][axis])
for index in indices) for axis in range(3))
if len(indices) <= 8:
return {"minimum": minimum, "maximum": maximum,
"segments": tuple(sorted(indices)), "left": None, "right": None}
axis = max(range(3), key=lambda value: maximum[value] - minimum[value])
indices.sort(key=lambda index: (segments[index][0][axis]
+ segments[index][1][axis]) * 0.5)
middle = len(indices) // 2
return {"minimum": minimum, "maximum": maximum, "segments": None,
"left": build(indices[:middle]), "right": build(indices[middle:])}
if not segments:
raise ValueError("lattice audit route has no measurable segments")
return build(list(range(len(segments))))
def make_lattice_route(layout: dict, phase_m: float = 0.0) -> dict:
edges = sorted((edge for edge in layout.get("cavern_edges", [])
if edge["stable_id"] in ("lattice/spine/00-arrival-portal-v1",
"lattice/spine/01-helix-ramp-v1", "lattice/spine/99-departure-portal-v1")
or edge["stable_id"].startswith("lattice/spine/maze-edge-")),
key=lambda edge: (0 if edge["stable_id"].startswith("lattice/spine/00-") else
1 if edge["stable_id"].startswith("lattice/spine/01-") else
2 if edge["stable_id"].startswith("lattice/spine/maze-edge-") else 3,
edge["stable_id"]))
if not edges:
raise ValueError("lattice audit needs its resolved mandatory spine edges")
segments = []
routes = []
for edge_index, edge in enumerate(edges):
points = [[value / 1_000_000.0 for value in row]
for row in edge.get("polyline_um", [])]
if len(points) < 2:
raise ValueError(f"{edge['stable_id']}: explicit path is missing")
radius = edge["bore_radius_um"] / 1_000_000.0
height = edge["bore_height_um"] / 1_000_000.0
horizontal_s = [0.0]
for a, b in zip(points, points[1:]):
horizontal_s.append(horizontal_s[-1] + ((b[0] - a[0]) ** 2
+ (b[1] - a[1]) ** 2) ** 0.5)
first = points[1]
first_dx, first_dy = first[0] - points[0][0], first[1] - points[0][1]
first_length = max(1.0e-9, (first_dx * first_dx + first_dy * first_dy) ** 0.5)
extension = (points[0][0] - first_dx / first_length * audit54.OPEN_GROUND_EXTENSION_M,
points[0][1] - first_dy / first_length * audit54.OPEN_GROUND_EXTENSION_M,
points[0][2] - (first[2] - points[0][2]) / first_length
* audit54.OPEN_GROUND_EXTENSION_M)
route_points = [extension, *points]
route_s = [-audit54.OPEN_GROUND_EXTENSION_M, *horizontal_s]
for index, (a, b) in enumerate(zip(route_points, route_points[1:])):
segments.append((a, b, route_s[index], route_s[index + 1],
radius, height, edge_index))
routes.append({"edge": edge, "points": points, "radius": radius,
"height": height, "length": horizontal_s[-1], "index": edge_index})
rooms = [{"room": room,
"center": tuple(value / 1_000_000.0 for value in room["center_um"]),
"half": tuple(value / 1_000_000.0 for value in room["half_extents_um"]),
"floor": room["floor_um"] / 1_000_000.0}
for room in sorted(layout.get("cavern_rooms", []), key=lambda row: row["stable_id"])]
return {"segments": segments, "edges": routes, "rooms": rooms, "phase_m": phase_m,
"segment_bvh": build_segment_bvh(segments)}
def make_route(layout: dict, phase_m: float = 0.0) -> dict:
if any(edge.get("stable_id", "").startswith("lattice/")
for edge in layout.get("cavern_edges", [])):
return make_lattice_route(layout, phase_m)
return original_make_route(layout, phase_m)
def lattice_route_nearest(point: tuple[float, float, float], route: dict):
"""Resolve stacked helix turns in 3D, then measure corridor radius in XY."""
best = None
def consider(segment_index: int) -> None:
nonlocal best
a, b, s0, s1, radius, height, edge_index = route["segments"][segment_index]
dx, dy, dz = (b[axis] - a[axis] for axis in range(3))
length_squared = dx * dx + dy * dy + dz * dz
t = 0.0 if length_squared <= 1.0e-12 else max(0.0, min(1.0,
((point[0] - a[0]) * dx + (point[1] - a[1]) * dy
+ (point[2] - a[2]) * dz) / length_squared))
x, y, z = (a[axis] + (b[axis] - a[axis]) * t for axis in range(3))
distance3d_squared = ((point[0] - x) ** 2 + (point[1] - y) ** 2
+ (point[2] - z) ** 2)
if (best is None or distance3d_squared < best[0]
or (distance3d_squared == best[0] and segment_index < best[1])):
horizontal_length = math.hypot(dx, dy)
lateral = ((dx * (point[1] - y) - dy * (point[0] - x))
/ horizontal_length if horizontal_length > 1.0e-9 else 0.0)
best = (distance3d_squared, segment_index,
math.hypot(point[0] - x, point[1] - y),
s0 + (s1 - s0) * t, z, lateral, radius, height, edge_index,
route["edges"][edge_index]["length"])
def lower_bound_squared(node: dict) -> float:
distance_squared = 0.0
for axis in range(3):
gap = (node["minimum"][axis] - point[axis]
if point[axis] < node["minimum"][axis]
else point[axis] - node["maximum"][axis]
if point[axis] > node["maximum"][axis] else 0.0)
distance_squared += gap * gap
return distance_squared
def visit(node: dict) -> None:
if best is not None and lower_bound_squared(node) > best[0]:
return
if node["segments"] is not None:
for segment_index in node["segments"]:
consider(segment_index)
return
left, right = node["left"], node["right"]
left_bound, right_bound = lower_bound_squared(left), lower_bound_squared(right)
if left_bound <= right_bound:
visit(left)
visit(right)
else:
visit(right)
visit(left)
visit(route["segment_bvh"])
if best is None:
raise ValueError("lattice audit route has no measurable segments")
return best[2:]
def mark_lattice_region(triangles: list, route: dict) -> None:
margin = audit54.CORRIDOR_MARGIN_M
extension = audit54.OPEN_GROUND_EXTENSION_M
bounds = []
for edge in route["edges"]:
points = edge["points"]
radius, height = edge["radius"], edge["height"]
bounds.append((
min(point[0] for point in points) - radius - margin,
max(point[0] for point in points) + radius + margin,
min(point[1] for point in points) - radius - margin,
max(point[1] for point in points) + radius + margin,
min(point[2] for point in points) - margin,
max(point[2] for point in points) + height + margin))
for room in route["rooms"]:
center, half, floor = room["center"], room["half"], room["floor"]
bounds.append((center[0] - half[0] - margin, center[0] + half[0] + margin,
center[1] - half[1] - margin, center[1] + half[1] + margin,
floor - margin, floor + 2.0 * half[2] + margin))
for triangle in triangles:
x, y, z = triangle.center
if not any(low_x <= x <= high_x and low_y <= y <= high_y
and low_z <= z <= high_z
for low_x, high_x, low_y, high_y, low_z, high_z in bounds):
triangle.in_region = False
triangle.reference = False
continue
nearest = lattice_route_nearest(triangle.center, route)
distance, distance_s, floor_z, lateral, radius, height, edge_index, edge_length = nearest
corridor = (-extension <= distance_s <= edge_length
and distance <= radius + margin
and floor_z - margin <= z <= floor_z + height + margin)
room_box = any(abs(x - room["center"][0]) <= room["half"][0] + margin
and abs(y - room["center"][1]) <= room["half"][1] + margin
and room["floor"] - margin <= z
<= room["floor"] + 2.0 * room["half"][2] + margin
for room in route["rooms"])
triangle.in_region = corridor or room_box
inside_room = any(abs(x - room["center"][0]) <= room["half"][0] + 0.45
and abs(y - room["center"][1]) <= room["half"][1] + 0.45
for room in route["rooms"])
outside_bore = distance > radius + 0.45 and not inside_room
triangle.reference = (triangle.in_region and outside_bore
and triangle.smooth[2] >= 0.45)
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--case", nargs=5, action="append", required=True,
metavar=("LABEL", "MESH", "LAYOUT_OR_DASH", "EXPECT", "FOCUS"))
parser.add_argument("--json", type=Path, required=True)
parser.add_argument("--svg-dir", type=Path)
parser.add_argument("--phase", type=float, choices=(-0.5, 0.0, 0.5), default=0.0)
args = parser.parse_args()
audit54.make_route = make_route
results = []
for label, mesh, layout, expect, focus in args.case:
if expect not in ("pass", "fail", "measure") or focus not in ("whole", "floor"):
parser.error("EXPECT must be pass/fail/measure and FOCUS must be whole/floor")
native_lattice = layout != "-" and any(
edge.get("stable_id", "").startswith("lattice/")
for edge in json.loads(Path(layout).read_text(encoding="utf-8")).get(
"cavern_edges", []))
original_margin = audit54.CORRIDOR_MARGIN_M
original_extension = audit54.OPEN_GROUND_EXTENSION_M
original_nearest = audit54.route_nearest
original_mark_region = audit54.mark_region
if native_lattice:
# Keep the whole-surface test on native records: one core voxel of
# tolerance captures their meshed walls while excluding the separate
# legacy transition above the resolved mouth.
audit54.CORRIDOR_MARGIN_M = 0.25
audit54.OPEN_GROUND_EXTENSION_M = 0.0
audit54.route_nearest = lattice_route_nearest
audit54.mark_region = mark_lattice_region
try:
results.append(audit54.audit_case(label, Path(mesh), Path(layout), expect,
focus, args.svg_dir, args.phase))
finally:
audit54.CORRIDOR_MARGIN_M = original_margin
audit54.OPEN_GROUND_EXTENSION_M = original_extension
audit54.route_nearest = original_nearest
audit54.mark_region = original_mark_region
if native_lattice:
print("[L58LatticeAuditScope] margin_m=0.250 outside_mouth_extension_m=0.000 "
"nearest_centerline=3D radius_measure=horizontal status=PASS")
args.json.parent.mkdir(parents=True, exist_ok=True)
args.json.write_text(json.dumps({"audit": "whole-surface-lattice-l58-v1",
"cases": results}, indent=2) + "\n", encoding="utf-8")
failures = [result for result in results if result["status"] != "PASS"]
print(f"[L58WholeSurfaceAuditSummary] cases={len(results)} failed={len(failures)} "
f"json={args.json} status={'FAIL' if failures else 'PASS'}")
return 1 if failures else 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,83 @@
#!/usr/bin/env python3
"""Split the owner surface strate around a small, opt-in native maze strate."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
def sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for block in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(block)
return digest.hexdigest()
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--owner", type=Path, required=True)
parser.add_argument("--out", type=Path, required=True)
args = parser.parse_args()
root = json.loads(args.owner.read_text(encoding="utf-8"))
strates = root.get("strates")
if not isinstance(strates, list):
raise ValueError("owner input has no strates array")
by_index = {int(row.get("index", -1)): row for row in strates if isinstance(row, dict)}
if set(by_index) != {0, 1} or len(strates) != 2:
raise ValueError("fixture requires the reviewed two-strate owner input")
upper, surface = by_index[0], by_index[1]
if (int(upper.get("asset", {}).get("GeneratorType", -1)) != 0
or int(surface.get("asset", {}).get("GeneratorType", -1)) != 4):
raise ValueError("fixture requires TunnelNetwork over SurfaceWorld")
if int(upper.get("passage_config", {}).get("Connections", -1)) != 1:
raise ValueError("owner arrival passage count differs from the reviewed input")
# Keep both resolved mouths in the small synthetic Maze layer. The authored
# owner reach ranges are intentionally broad and can place a synthetic mouth
# hundreds of metres beyond a four-chunk prototype layer.
upper["passage_config"].update({"ReachMin": 32, "ReachMax": 32})
upper["asset"]["PassageConfig"].update({"ReachMin": 32, "ReachMax": 32})
maze = json.loads(json.dumps(surface))
maze.update({"index": 1, "top_chunk_z": -16, "bottom_chunk_z": -19,
"height_chunks": 4})
maze["asset"].update({"StrateName": "L58 Native Lattice Maze",
"GeneratorType": 3, "StrateHeightInChunks": 4})
maze["asset"].setdefault("MazeParams", {})["BoundarySealThickness"] = 8
maze["passage_config"]["Connections"] = 1
maze["passage_config"].update({"ReachMin": 32, "ReachMax": 32})
maze["asset"]["PassageConfig"].update({"Connections": 1, "ReachMin": 32, "ReachMax": 32})
lower = json.loads(json.dumps(surface))
lower.update({"index": 2, "top_chunk_z": -20, "bottom_chunk_z": -23,
"height_chunks": 4})
lower["asset"].update({"StrateName": "L58 Lower Surface", "GeneratorType": 4,
"StrateHeightInChunks": 4})
lower["passage_config"]["Connections"] = 1
lower["asset"]["PassageConfig"]["Connections"] = 1
root["total_strates"] = 3
root["strates"] = [upper, maze, lower]
# Keep the legacy passage portals proportional to this compact native
# prototype; the owner world remains at its authored scale.
root.update({"owner_voxel_size_cm": 6.25,
"owner_voxel_size_microns": 62500,
"core_voxel_size_cm": 25,
"core_voxel_size_microns": 250000,
"owner_to_core_length_scale": 0.25})
args.out.parent.mkdir(parents=True, exist_ok=True)
args.out.write_text(json.dumps(root, indent=2, sort_keys=True) + "\n",
encoding="utf-8")
print(f"[LatticeFixtureBuild] source={args.owner} source_sha256={sha256(args.owner)} "
f"fixture={args.out} fixture_sha256={sha256(args.out)} "
"strates=0:TunnelNetwork,1:Maze[4 chunks],2:SurfaceWorld[60 chunks] "
"owner_input_untouched=true status=PASS")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,164 @@
#!/usr/bin/env python3
"""Export the L58 native lattice view and render four reviewed viewpoints."""
from __future__ import annotations
import argparse
import hashlib
import importlib.util
import json
import math
import os
from pathlib import Path
import subprocess
import sys
ROOT = Path(__file__).resolve().parents[4]
CAPTURE54 = ROOT / "Standalone/Research/WorldAssemblerM3/Linux54/CaptureNativeCavesL54.py"
spec = importlib.util.spec_from_file_location("capture_native_caves_l54", CAPTURE54)
capture54 = importlib.util.module_from_spec(spec)
assert spec and spec.loader
spec.loader.exec_module(capture54)
run_step = capture54.run_step
camera_angles = capture54.camera_angles
filter_mesh_y_leq = capture54.filter_mesh_y_leq
fmt = capture54.fmt
def sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for block in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(block)
return digest.hexdigest()
def midpoint(points: list[list[float]]) -> tuple[float, float, float]:
return tuple(sum(point[axis] for point in points) / len(points) for axis in range(3))
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--out", type=Path, required=True)
parser.add_argument("--fixture", type=Path, required=True)
parser.add_argument("--layout", type=Path, required=True)
parser.add_argument("--headless", type=Path, required=True)
parser.add_argument("--renderer", type=Path, required=True)
parser.add_argument("--artifact-dir", type=Path, required=True)
args = parser.parse_args()
out = args.out.resolve()
artifact_dir = args.artifact_dir.resolve()
capture_dir = out / "lattice-capture-png"
mesh_dir = out / "lattice-meshes"
for directory in (capture_dir, mesh_dir, artifact_dir):
directory.mkdir(parents=True, exist_ok=True)
layout = json.loads(args.layout.read_text(encoding="utf-8"))
edges = sorted(layout.get("cavern_edges", []), key=lambda row: row["stable_id"])
helix = next((edge for edge in edges
if edge["stable_id"] == "lattice/spine/01-helix-ramp-v1"), None)
maze_edges = [edge for edge in edges
if edge["stable_id"].startswith("lattice/spine/maze-edge-")]
if helix is None or len(maze_edges) < 4:
raise ValueError("layout is missing the resolved helix or small maze spine")
helix_points = [[value / 1_000_000.0 for value in point]
for point in helix["polyline_um"]]
maze_points = [[value / 1_000_000.0 for value in point]
for point in maze_edges[0]["polyline_um"]]
shaft_center = midpoint(helix_points)
top = helix_points[0]
bottom = helix_points[-1]
whole_mesh = mesh_dir / "lattice-whole-view.vfmesh"
export_layout = out / "layouts" / "lattice-capture-layout.json"
env = os.environ.copy()
env["LP_NUM_THREADS"] = "12"
env["XDG_CACHE_HOME"] = str(out / "xdg-cache")
export_camera = (top[0], top[1], top[2] + 1.5, 0.0, -8.0)
run_step("lattice-whole-view-export", [args.headless, args.fixture,
"--workers=12", "--world-assembler-prototype", "--stream-benchmark",
"--stream-pipeline", "--force-generate", "--clip-radius=4",
"--max-clip-level=0", "--max-level=0", "--render-distance-chunks=0",
"--recipe=lattice", "--lattice-strate=1",
f"--camera={fmt(export_camera)}", f"--resolved-layout-output={export_layout}",
f"--mesh-export={whole_mesh}"], out / "capture-lattice-export.log",
env=env, stamped=True)
if not whole_mesh.is_file() or whole_mesh.stat().st_size == 0:
raise RuntimeError("whole-lattice export produced no mesh")
cutaway_mesh = mesh_dir / "lattice-cutaway-y-center.vfmesh"
cutaway_triangles = filter_mesh_y_leq(whole_mesh, cutaway_mesh, shaft_center[1])
print(f"[L58LatticeCutaway] plane_y_m={shaft_center[1]:.3f} "
f"retained_triangles={cutaway_triangles} mesh={cutaway_mesh}", flush=True)
# Stand over the clear central opening so the top tread does not occlude
# the view down the shaft.
top_camera = (shaft_center[0], shaft_center[1] - 0.8, top[2] + 2.0)
top_target = (shaft_center[0] + 0.2, shaft_center[1], bottom[2] + 1.3)
eye_index = len(helix_points) // 2
eye_floor = helix_points[eye_index]
eye_tangent = tuple(helix_points[eye_index + 1][axis]
- helix_points[eye_index - 1][axis] for axis in range(3))
eye_len = max(1.0e-9, math.hypot(eye_tangent[0], eye_tangent[1]))
eye_camera = (eye_floor[0], eye_floor[1], eye_floor[2] + 1.45)
# Look across the shaft center from the ramp so the adjacent higher turn
# reads in the same frame. The view clips the near half of the shaft wall.
eye_target = (shaft_center[0], shaft_center[1], eye_camera[2] + 4.2)
maze_a, maze_b = maze_points[0], maze_points[-1]
maze_camera = ((maze_a[0] + maze_b[0]) * 0.5,
(maze_a[1] + maze_b[1]) * 0.5,
(maze_a[2] + maze_b[2]) * 0.5 + 1.45)
maze_target = (maze_camera[0] + (maze_b[0] - maze_a[0]) * 0.65,
maze_camera[1] + (maze_b[1] - maze_a[1]) * 0.65,
maze_camera[2] + (maze_b[2] - maze_a[2]) * 0.65)
overview_camera = (shaft_center[0], shaft_center[1] - 28.0,
(top[2] + bottom[2]) * 0.5)
overview_target = (shaft_center[0], shaft_center[1], (top[2] + bottom[2]) * 0.5)
views = (
("helix-top-down", whole_mesh, top_camera, top_target, 22.0, 70.0, None),
("ramp-eye-next-turn", whole_mesh, eye_camera, eye_target, 12.0, 76.0,
(0.0, 1.0, 0.0, -shaft_center[1])),
("maze-eye-level", whole_mesh, maze_camera, maze_target, 14.0, 82.0, None),
("cutaway-overview", cutaway_mesh, overview_camera, overview_target, 40.0, 80.0, None),
)
quality = ROOT / "Standalone/Tools/verify/capture_quality.py"
for name, render_mesh, camera, target, focus_radius, fov, clip_plane in views:
yaw, pitch = camera_angles(camera, target)
if name == "ramp-eye-next-turn":
yaw, pitch = 45.0, 10.0
png = capture_dir / f"lattice-{name}.png"
image = artifact_dir / f"lattice-{name}.jpg"
render_args = [args.renderer, render_mesh, png,
"--size=1280x720", f"--fov-deg={fov:.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={(top[2] + bottom[2]) * 0.5:.6f}",
"--height-range-m=24", "--tile-edges=off",
f"--focus-region={fmt((*target, focus_radius))}"]
if clip_plane is not None:
render_args.append(f"--clip-plane={fmt(clip_plane)}")
run_step(f"{name}-render", render_args,
out / f"capture-{name}-render.log", env=env, stamped=True)
run_step(f"{name}-jpeg", ["ffmpeg", "-nostdin", "-hide_banner", "-loglevel",
"error", "-y", "-i", png, "-frames:v", "1", "-q:v", "5", image],
out / f"capture-{name}-jpeg.log", env=env)
quality_output = run_step(f"{name}-quality", [sys.executable, quality, image],
out / f"capture-{name}-quality.log", env=env)
quality_lines = [line for line in quality_output.splitlines()
if line.startswith("[CaptureQuality]")]
if not quality_lines or not quality_lines[-1].endswith("status=PASS"):
raise RuntimeError(f"capture quality gate failed for {name}")
size = image.stat().st_size
if size > 300_000:
raise RuntimeError(f"capture exceeds 300 KB: {image} ({size} bytes)")
print(f"[L58LatticeCapture] view={name} file={image} bytes={size} "
f"sha256={sha256(image)} status=PASS", flush=True)
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except Exception as error:
print(f"[L58LatticeCapture] status=FAIL error={error}", file=sys.stderr, flush=True)
raise SystemExit(1)
@@ -0,0 +1,51 @@
# Linux58 — Native lattice, slice 1
## Records and geometry
The fixture uses seed `0`, strate `1`, and recipe `Core.Lattice.PrimitiveField` version `1`. Room and edge IDs are stable and keyed by `(seed, strate, recipe_version, stable_id)`. The resolved arrival is `passage/0-1/0` lower at `(9.142, -2.073, -122.500) m`; departure is `passage/1-2/0` upper at `(12.271, -3.565, -149.500) m`. The plan resolves 9 rooms and 9 edges before branches: arrival/departure rooms, maze cells `00`–`04`, two dead-end rooms; arrival portal, helix ramp, maze edges `00`–`03`, departure portal, and two dead-end edges. The canonical record digest is `639d8b975024c9824c944f8244fae88d796350da5f4168b85d5ec7b501c5a842`.
The mandatory spine descends 20 m through four helix turns: 6 m centreline radius, 3 m clear width, 5 m pitch, and 2.6 m finished floor-to-soffit. Measured grades are 7.555° at the centreline and 10.028° at the inner edge. The cubic smooth-max fillet measures `0.570778 m` (required `>=0.500 m`). The prototype’s accepted outer shaft envelope is 21 m. The maze has five cells and two dead ends. This recipe is opt-in; legacy Maze and VerticalShaft assets remain legacy.
## Reachability, intervals, and surface
On the final field, arrival-to-departure reachability passed all 883 stations: 44,150 capsule samples, 4,415 support samples, and 4,415 headroom samples had zero failures. Maximum grade was 10.028° and minimum headroom was 2.200 m. The deliberately disconnected shaft control was rejected (`reachable=no`; zero connected route stations).
The interval oracle checked 4 boxes against 1,372 brute-force samples with zero misses. It rejected both false all-air and false all-solid proofs; `isTileShapeFree` blocked the occupied wall-foot tile. The whole-surface audit covered 89,577 LOD0 triangles across the helix edges and maze wall feet: zero flagged triangles and zero clusters. The L45 ramp, L46 entrance, and L47 wall-foot controls failed as expected; the plain-native control passed.
## Peers and timing
Clang and GCC builds used FP contraction off. W1/W8/W12 matched for four randomized cameras, including one inside the helix, with matching tile hashes and the canonical record digest above.
Clang measured first tile `0.201 s`, near ring `0.345 s`, whole view `1.694 s`, and moving p50/p95 `485.536/977.128 ms`. The whole view is above the 0.7–1.0 s target; moving p95 is just under 1 s.
## Captures and hashes
All four JPEGs passed the capture gate, were visually reviewed, and are below 300 KB.
| View | Bytes | SHA-256 |
|---|---:|---|
| `captures/lattice-helix-top-down.jpg` | 19,616 | `0ab87ee1e799ce96752dc3bf9d6803928e4d6aaad8a87400d899ff3f3be06149` |
| `captures/lattice-ramp-eye-next-turn.jpg` | 22,540 | `d16b0ad577f5ec0e676e18ba62a5de64c71385cd93b53b225ac25f109b184265` |
| `captures/lattice-maze-eye-level.jpg` | 12,361 | `463ee13e962ecc36de1778abcd09f34f5bd375db5537395e7b1e0e0df3d72331` |
| `captures/lattice-cutaway-overview.jpg` | 28,673 | `10204ac2b120ad360e31ac589351c31d0c0e9603feb22841860bd4e145613194` |
Source stamp: `7d181a5b606879ae7277db296e43df11f3fdef41eefa127f5c86d8a431fc4a10`. The owner input remains unchanged at SHA-256 `7b095f9bcc6b90133d5a463f99f0b571133b2c549ce1ecf2d64fe9175e41e183`.
## Tiers, trials, and failed runs
`verify.py fast` passed in 176.4 s; `medium` passed in 1,170.0 s. The single full run on the clean build reached 1,700 s and timed out during the later GCC motif matrix. Before timeout, its L58 GCC field, orphan control, W1/W8/W12 peers, inside-helix camera, and Clang comparisons had passed. No second full run was made.
The run ledger records 10 verification-tier invocations against the 15-trial limit: 3 fast, 6 medium, and 1 full. Earlier failures were a stale style assertion; capture framing/quality; the initial broad transition ROI and boundary seam; and a floor-profile ripple (`0.0887 m`, adjacent step `0.1791 m`) before blend tuning. One direct surface audit initially had a missing `math` import, and one diagnostic parse had a syntax error; both were corrected. A post-tuning fast assertion also used stale blend values. The final fast and medium tiers passed. The only final-tier failure was the full-run timeout above.
## Orchestrator review (Claude)
Accepted. The stamp matches the final Clang and GCC builds (`7d181a5b…`). The full tier had timed out at the builder's
1,740 s process wrapper (the tier itself now runs about 38 min). I re-ran it with the tier's own 7,200 s limit:
**PASS, 2,307 s.** Reachability passes at all 883 stations, the orphan control is rejected, and the surface audit is
clean. Two items for the next lattice slice:
- **Whole view 1.69 s** is above the about-1 s target.
- **It reads as a corkscrew tunnel bored through rock** (separate stacked turns with rock between them). It doesn't
read as an open vertical shaft with a ramp around its wall, which is what "vertical shaft world" implies. Open the
shaft core in slice 2.
Removed the duplicate control SVGs (already in Linux48).
File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 3.1 MiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 2.7 MiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 3.1 MiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 4.8 MiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB