feat(core): reachable SW landmark chamber demo with a reachability audit (L45); research R12
Stamp vocabulary v2; the flagged SW demo opens through a side-facing portal and a bent ramp (max 14 deg, two landings) into a 17 x 15 m chamber with a rock dais. New reachability audit: a capsule surface search from walkable ground near the arrival mouth to the chamber floor (66 samples, 0 blocked/unsupported); the buried L43 layout fails it. Demo off: owner hashes identical to L44. fast/medium/full PASS (Clang+GCC). Research R12 (read-only): composite cavern-graph generator design and slices. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
036bd530fc
commit
f13b145f23
14 files changed
+1404
-45
No files matched your search
@@ -0,0 +1,345 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Capture the L45 landmark 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)
|
||||
|
||||
|
||||
layout = json.loads(LAYOUT_PATH.read_text(encoding="utf-8"))
|
||||
if layout.get("stamp_vocabulary_version") not in (1, 2):
|
||||
raise RuntimeError("L45 capture needs a prior resolved L45 stamp layout")
|
||||
entrance_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-ramp-000")
|
||||
next_ramp_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-ramp-001")
|
||||
portal_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-mouth-approach-v1")
|
||||
chamber_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-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 = metres(entrance_stamp)
|
||||
next_ramp = metres(next_ramp_stamp)
|
||||
portal = metres(portal_stamp)
|
||||
chamber = metres(chamber_stamp)
|
||||
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] - 1.6
|
||||
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-l45.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"))
|
||||
if layout.get("stamp_vocabulary_version") != 2:
|
||||
raise RuntimeError("L45 export did not resolve ellipsoidal-dais stamp vocabulary v2")
|
||||
entrance_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-ramp-000")
|
||||
next_ramp_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-ramp-001")
|
||||
portal_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-mouth-approach-v1")
|
||||
chamber_stamp = stamp_by_id(layout, "landmark/sw-arrival-chamber-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 = metres(entrance_stamp)
|
||||
next_ramp = metres(next_ramp_stamp)
|
||||
portal = metres(portal_stamp)
|
||||
chamber = metres(chamber_stamp)
|
||||
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] - 1.6
|
||||
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_ramp_stamps = sorted((stamp for stamp in layout.get("stamps", [])
|
||||
if stamp.get("stable_id", "").startswith("landmark/sw-arrival-chamber-ramp-")),
|
||||
key=lambda stamp: stamp["stable_id"])
|
||||
if not entry_ramp_stamps:
|
||||
raise RuntimeError("resolved layout has no chamber ramp stamps")
|
||||
entry_target_stamp = entry_ramp_stamps[min(8, len(entry_ramp_stamps) - 1)]
|
||||
entry_target_center = metres(entry_target_stamp)
|
||||
entry_target = (entry_target_center[0],entry_target_center[1],entry_target_center[2]-1.2)
|
||||
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"[L45CaptureCamera] 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"[L45CaptureJPEG] 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 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))
|
||||
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({
|
||||
"vocabulary_version": layout["stamp_vocabulary_version"],
|
||||
"entry_m": entrance, "portal_m": portal, "entry_ground_m": ground_z,
|
||||
"chamber_center_m": chamber, "chamber_floor_m": floor_top,
|
||||
"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, "dais_platform": dais_metrics,
|
||||
"mesh_tiles": tile_count, "mesh_voxel_um": voxel_um,
|
||||
}, indent=2) + "\n", encoding="utf-8")
|
||||
print(f"[L45CaptureShapeMetrics] file={metrics_path} status=PASS", flush=True)
|
||||
@@ -0,0 +1,48 @@
|
||||
# L45 — reachable landmark chamber
|
||||
|
||||
## Design and stamps
|
||||
|
||||
The SW demo opens through a rounded, side-facing ellipsoid portal, then follows a bent rock ramp with two level landings into the 17 × 15 m chamber. The sloped section drops 5.85 m; the maximum measured grade is 14.039°. An ellipsoidal rock dais rises 1.138 m above the chamber floor.
|
||||
|
||||
The demo layout resolves 166 version-2 stamps: 57 ellipsoid carves, 107 support pillars, and two filled ellipsoids for the floor and dais. The side portal and supported arrival landing are runtime-only under the demo flag. `owner_world.json` is unchanged.
|
||||
|
||||
## Reachability and shape audits
|
||||
|
||||
The surface search joins walkable ground near the arrival mouth to the chamber floor. The capsule route passed 66 samples and 6,798 clearance checks: zero blocked samples, zero unsupported samples across 330 support checks, and zero grade failures. Minimum clearance is 0.085 m. The exact buried L43 layout fails the same reachability audit as required.
|
||||
|
||||
L37 thresholds (planar patch <0.50 m², straight run ≤0.75 m, no sharp corners): the portal measured 0.417 m² / 0.522 m / 0 corners; the dais measured 0.282 m² / 0.750 m / 0 corners.
|
||||
|
||||
## Hashes and cost
|
||||
|
||||
- Source stamp: `0ec9177748faff6ef4813af0c418057edfcacf95c7c39c1292288a29c7775015` (GCC and Clang).
|
||||
- Owner JSON SHA-256: `7b095f9bcc6b90133d5a463f99f0b571133b2c549ce1ecf2d64fe9175e41e183`.
|
||||
- Demo-off layout IDs: FI `b7a7d9ecc48d8f26`; SW `8a52e84c26ed92d2`. The 12-hash W1/W12 owner signatures match L44: FI `9820f4f38b189b3f7263810e7b3ff62aa502b21f476ffcfdbc7761a65cb07d58`; SW `a1e9268a4bbcc77d2a1ac54095df6851a70bab65c43ae50b332ed75132617834`.
|
||||
- Five-pair demo-off cost vs L44: FI median 16.476 → 16.677 s (+1.22%); SW 1.733 → 1.731 s (−0.12%).
|
||||
|
||||
## Verification and captures
|
||||
|
||||
`verify.py fast`, `medium`, and `full` passed in 189.5 s, 561.8 s, and 1,609.1 s. Passage, interface/hole, seeded random-camera, W1/W8/W12 determinism, and 30-cell checks passed.
|
||||
|
||||
All four JPEGs pass `capture_quality.py` and are under 300 KB:
|
||||
|
||||
- [Ground entrance, eye height at 7.03 m](captures/ground-entrance.jpg) — 36,041 B
|
||||
- [Entrance looking in](captures/entrance-looking-in.jpg) — 41,507 B
|
||||
- [Inside toward the dais](captures/inside-to-dais.jpg) — 36,590 B
|
||||
- [Overview of entrance and chamber](captures/overview-entrance-and-chamber.jpg) — 58,255 B
|
||||
|
||||
## Failed runs
|
||||
|
||||
Six geometry trial exports were used, within the 15-trial budget. The boxy arch exceeded the shape limits; early ramp/support variants blocked the path or exceeded the grade limit; a deeper mouth cut broke the surface connection and was reverted. Early eye-level camera angles were wall-blocked or poorly framed. The first final fast invocation rejected a stale GCC stamp; GCC was rebuilt to match and fast passed. The buried L43 and deliberate verifier negative controls fail as expected.
|
||||
|
||||
## Orchestrator review (Claude)
|
||||
|
||||
Accepted as the flagged demo. The stamp matches the final Clang and GCC builds (`0ec91777…`); demo-off owner
|
||||
hashes are identical to L44; the buried L43 layout fails the new reachability audit. The overview reads as a real
|
||||
place: a sinkhole and curved path cut into the ground, leading down into a chamber with a rock dais. Not yet natural:
|
||||
- **The ramp is visibly segmented.** Evenly spaced ribs run along it in the overview and the entrance view, the same
|
||||
per-segment seam family as the L35 ribs and L36 washboard. It is built from 57 carves plus 107 support pillars.
|
||||
- **The ramp's raised edge has straight vertical walls,** so in `entrance-looking-in.jpg` it reads as a built walkway.
|
||||
- **Headroom along the path is tight:** 0.085 m minimum clearance.
|
||||
- The dais is a smooth dome, readable but plain.
|
||||
|
||||
Next (L46): replace the stamped ramp with one continuous floor-capped tunnel edge, following R12's first slice.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
Reference in new issue
Block a user