passages: continuous floor h(s) along the dense route; shell-probe oracle fix (L115, v223)

Floor height from the planner profile h(s) by horizontal projection + arc-length interpolation;
adjacent fine segments share endpoint values. Floor zero-crossing offsets max 7.8 mm (L114: up
to 73 mm); rock-floor close-ups show no ribs. The 2 L114 shell misses were oracle false positives
(points inside an overlapping bore); the oracle now checks every overlapping span; no gate relaxed.
Fast tier PASS; Clang/GCC W1/W8/W12 deterministic. Speed regression grows: near-ready +17..+31% vs
L109 (fine-segment/sample pairs 49.0M vs 19.8M). Not merged.

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-30 01:48:29 +01:00
1 parent 5e875ae504
commit f403af1fc1
37 files changed
+2741 -183

No files matched your search

@@ -0,0 +1,46 @@
# Linux115 report
Source version 223. Floor height now comes from the planner profile `h(s)` on the dense route, using horizontal projection and arc-length interpolation. In-range projections interpolate on their fine segment; out-of-range projections use the global profile lookup. Adjacent fine segments share the same endpoint value. The plan-time grade audit remains enabled: maximum sampled grade was 10.687° (limit 15°).
## Floor zero crossings
Each station has 51 density samples. Offsets below are in millimetres.
| Passage | Station | Max absolute | Median absolute | P95 absolute |
|---|---:|---:|---:|---:|
| 0–1 | 25% | 0.088 | 0.009 | 0.066 |
| 0–1 | 50% | 0.079 | 0.016 | 0.064 |
| 0–1 | 75% | 0.225 | 0.016 | 0.161 |
| 1–2 | 25% | 7.475 | 7.259 | 7.459 |
| 1–2 | 50% | 7.272 | 7.215 | 7.265 |
| 1–2 | 75% | 7.272 | 7.121 | 7.245 |
| 2–3 | 25% | 7.849 | 7.712 | 7.844 |
| 2–3 | 50% | 7.712 | 7.351 | 7.694 |
| 2–3 | 75% | 7.573 | 7.506 | 7.566 |
Maximum offset is 7.849 mm, below the 10 mm target. Full data: [CSV](../../../../Saved/Linux/l115/density-probe/zero-crossing-offsets.csv) and [summary](../../../../Saved/Linux/l115/density-probe/zero-crossing-summary.json).
## Shell probes and captures
The two L114 southwest wall misses were probe-oracle false positives. Both positions were inside an intentionally carved overlapping passage bore, where host air is correct; the audit had only considered the nearest route span when classifying bore interior. The oracle now recognizes interior air on any overlapping route span. No wall gate was relaxed. The final two-strata audit reports 0 wall violations in 31,361 probes (8,848 overlap-interior skips), 0 floor violations, and 0 interior violations.
The final capture set has 23/23 programmatically verified images: 9 rock-floor close-ups and 14 open-air outside/interior close-ups across 7 sections. Quality labels are 18 `pass` and 5 `low_contrast_geometry_visible`; all five still passed visibility verification. [Capture index](captures/capture-index.json).
## Speed
Coarse candidate totals are L109 3,132, L114 14,384, and L115 3,720 (74.1% fewer than L114). The inner sweep still visits 48.95M fine-segment/sample pairs for both L114 and L115, versus 19.81M for L109, so fewer coarse candidates did not reduce fine traversal enough to improve readiness.
Five interleaved measured runs per version followed warm-ups at W8/W12 for all four strata. The host was quiet before timing (1-minute load 1.30; `top` 99% idle). Values below are L115 near-ready median deltas.
| Stratum | W8 vs L109 / L114 | W12 vs L109 / L114 |
|---|---:|---:|
| 0 | +16.8% / +8.7% | +16.8% / +9.2% |
| 1 | +30.4% / +13.0% | +31.1% / +14.5% |
| 2 | +25.2% / +12.4% | +25.9% / +12.0% |
| 3 | +23.8% / +8.6% | +18.1% / +2.9% |
Across the eight strata/worker combinations, median whole-view deltas were +10.7% versus L109 and +4.9% versus L114. Full run data: [timing summary](../../../../Saved/Linux/l115/timing/summary.json).
## Verification
Fast tier passed in 341.1 s, including walkability, passage shell, camera sweeps, native field, and motif capsule reachability. Clang/GCC hashes matched at W1/W8/W12 for all four owner strata groups. The final source stamp is `7eb1fa49f91954c0690173aba4ed832b3594e50531bd4b20690d122970943274`; no Unreal-compiled source changed, so no Unreal build was needed.
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""Compare per-tile passage candidate-list sizes for L109, L114, and L115."""
from __future__ import annotations
import json
import math
import re
import statistics
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l115/candidate-lists"
DATA = ROOT / "Standalone/data/owner_world.json"
BINARIES = {
"L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang",
"L114": ROOT / "Saved/Linux/l114/bin/VoxelForgeCoreHeadless-l114-clang",
"L115": ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-clang",
}
CAMERAS = {
0: (8.0, 16.0, -372.2626953125),
1: (25.8369140625, 3.19921875, -737.0),
2: (19.166015625, -14.2001953125, -753.3740234375),
3: (-20.0625, -5.068359375, -900.353515625),
}
LIST = re.compile(r"^\[PassageComposerTile\].*?features=(\d+) route_candidates=(\d+)", re.M)
def percentile(values: list[int], fraction: float) -> int:
ordered = sorted(values)
if not ordered:
return 0
return ordered[min(len(ordered) - 1,
max(0, math.ceil(fraction * len(ordered)) - 1))]
def run(strate: int, version: str) -> dict:
OUT.mkdir(parents=True, exist_ok=True)
log = OUT / f"{version}-s{strate}.log"
camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
"timeout", "1740s", str(BINARIES[version]), str(DATA),
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
"--workers=12", "--clip-radius=3", "--max-clip-level=8", "--max-level=8",
f"--camera={camera}", "--profile-passage-composer", "--stream-scheduler-policy=3",
]
started = time.monotonic()
with log.open("w", encoding="utf-8") as stream:
result = subprocess.run(command, cwd=ROOT, stdout=stream,
stderr=subprocess.STDOUT, check=False, timeout=1740)
output = log.read_text(encoding="utf-8", errors="replace")
features = [int(row[0]) for row in LIST.findall(output)]
routes = [int(row[1]) for row in LIST.findall(output)]
if result.returncode or not features:
raise SystemExit(f"candidate-list profile missing: {log}; exit={result.returncode}")
row = {
"strate": strate, "version": version, "profiled_tiles": len(features),
"feature_candidates": {"sum": sum(features), "min": min(features),
"median": statistics.median(features), "p95": percentile(features, .95),
"max": max(features)},
"route_segment_candidates": {"sum": sum(routes), "min": min(routes),
"median": statistics.median(routes), "p95": percentile(routes, .95),
"max": max(routes)},
"elapsed_s": round(time.monotonic() - started, 3),
"log": str(log.relative_to(ROOT)),
}
print("[L115CandidateLists] " + json.dumps(row, sort_keys=True), flush=True)
return row
def main() -> int:
if any(not path.is_file() for path in (*BINARIES.values(), DATA)):
raise SystemExit("missing L109/L114/L115 candidate-list input")
rows = [run(strate, version) for strate in range(4)
for version in ("L109", "L114", "L115")]
(OUT / "summary.json").write_text(json.dumps(rows, indent=2) + "\n",
encoding="utf-8")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,260 @@
#!/usr/bin/env python3
"""Capture L115 rock floors at three rock stations per passage and open-air walls."""
from __future__ import annotations
import importlib.util
import json
import math
import re
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
RESEARCH = Path(__file__).resolve().parent
CAPTURES = RESEARCH / "captures"
SAVED = ROOT / "Saved/Linux/l115/captures"
L113_RESEARCH = ROOT / "Standalone/Research/WorldAssemblerM3/Linux113"
L115_SAVED = ROOT / "Saved/Linux/l115"
BINARIES = {
"L115": L115_SAVED / "bin/VoxelForgeCoreHeadless-l115-clang",
}
RENDERERS = {
"L115": L115_SAVED / "bin/VoxelForgeOffscreenCapture-l115-clang",
}
SECTION = re.compile(
r"^\[PassageOpenAirSection\] id=(\S+) section=(\d+) start_m=([\d.]+) "
r"end_m=([\d.]+) samples=(\d+) midpoint_xyz_m=\(([^)]*)\) "
r"midpoint_radius_m=([\d.]+)", re.M)
sys.dont_write_bytecode = True
SPEC = importlib.util.spec_from_file_location(
"l113_capture_helpers", L113_RESEARCH / "RunL113Captures.py")
if SPEC is None or SPEC.loader is None:
raise SystemExit("cannot load the verified L113 capture helpers")
HELPERS = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(HELPERS)
HELPERS.RESEARCH = RESEARCH
HELPERS.CAPTURES = CAPTURES / "L115"
HELPERS.SAVED = SAVED / "L115"
HELPERS.BINARIES = BINARIES
HELPERS.RENDERERS = RENDERERS
def parse_sections(log: Path) -> list[dict]:
sections = []
text = log.read_text(encoding="utf-8", errors="replace")
for passage, section, start, end, samples, midpoint, radius in SECTION.findall(text):
sections.append({"passage": passage, "section": int(section),
"start_m": float(start), "end_m": float(end),
"samples": int(samples), "midpoint": HELPERS.vector(midpoint),
"radius_m": float(radius)})
return sections
def rocky_spans(total: float, sections: list[dict]) -> list[tuple[float, float]]:
spans = []
cursor = 0.0
for section in sorted(sections, key=lambda item: item["start_m"]):
start = max(0.0, min(total, section["start_m"]))
end = max(start, min(total, section["end_m"]))
if start - cursor > 2.0:
spans.append((cursor + 1.0, start - 1.0))
cursor = max(cursor, end)
if total - cursor > 2.0:
spans.append((cursor + 1.0, total - 1.0))
return [(start, end) for start, end in spans if end - start >= 1.0]
def rock_station_candidates(spans: list[tuple[float, float]]) -> list[float]:
total = sum(end - start for start, end in spans)
if total < 3.0:
raise RuntimeError("passage has less than 3 m of rock route outside open-air spans")
stations = []
for fraction in (0.25, 0.50, 0.75, 0.10, 0.90, 0.35, 0.65, 0.20, 0.80,
0.40, 0.60):
remaining = total * fraction
for start, end in spans:
span = end - start
if remaining <= span:
stations.append(start + remaining)
break
remaining -= span
return stations
def rock_floor_view(layout: dict, passage: dict, station: float, index: int) -> dict:
raw_route = HELPERS.smooth_route(layout, passage)
route, body_depth = HELPERS.derived_smooth_route(raw_route, passage, layout)
lengths, prefix = HELPERS.route_lengths(route)
center, radius = HELPERS.at_distance(route, lengths, prefix, station)
floor_depth = min(body_depth, max(0.0, radius - 0.23))
planned_floor = (center[0], center[1], center[2] - floor_depth)
tangent = HELPERS.tangent_at(route, lengths, prefix, station)
grade = math.degrees(math.atan2(abs(tangent[2]),
math.hypot(tangent[0], tangent[1])))
camera = tuple(planned_floor[axis] - 2.5 * tangent[axis]
+ (1.25 if axis == 2 else 0.0) for axis in range(3))
yaw, pitch = HELPERS.angles(camera, planned_floor)
safe_id = HELPERS.sanitize(passage["stable_id"])
return {"name": f"{safe_id}-rock-floor-station-{index}",
"passage": passage["stable_id"], "kind": "rock-floor-close",
"station": f"rock-floor/{station:.1f}m", "camera": camera,
"target": planned_floor, "yaw": yaw, "pitch": pitch,
"focus": planned_floor, "center_z": planned_floor[2],
"route_distance_m": station, "requested_route_distance_m": station,
"route_length_m": prefix[-1], "planned_floor_m": planned_floor[2],
"planned_grade_deg": grade}
def capture_rock_floor(layout: dict, passage: dict, station: float, index: int) -> dict:
view = rock_floor_view(layout, passage, station, index)
row = HELPERS.capture("L115", view, layout)
scene = ROOT / row["scene"]
anchor = HELPERS.nearest_surface_anchor(scene, view["target"], margin_m=5.0,
preferred_normal=(0.0, 0.0, 1.0), minimum_alignment=0.85)
alignment = HELPERS.dot(anchor["normal"], (0.0, 0.0, 1.0))
camera_distance = math.dist(row["camera_actual_m"], anchor["position_m"])
row.update({"variant": "L115", "kind": "rock-floor-close",
"planned_floor_m": view["planned_floor_m"],
"planned_grade_deg": view["planned_grade_deg"],
"floor_anchor_position_m": anchor["position_m"],
"floor_anchor_normal": anchor["normal"],
"closeup_camera_to_floor_distance_m": camera_distance,
"closeup_target_surface_distance_m": anchor["distance_m"],
"closeup_floor_normal_alignment": alignment,
"verified_upward_floor_normal": alignment >= 0.85})
if (not row["verified"] or not 2.0 <= camera_distance <= 3.2
or anchor["distance_m"] > 0.25 or alignment < 0.85
or view["planned_grade_deg"] < 2.0 or row["drawn_triangles"] <= 0
or row["pixel_quality_status"] not in
("pass", "low_contrast_geometry_visible")):
raise RuntimeError(f"rock-floor close-up failed at {passage['stable_id']} s={station:.2f}")
return row
def main() -> int:
layout_path = L115_SAVED / "audit-layout-candidate.json"
audit_log = L115_SAVED / "audit-owner-clang.log"
if any(not path.is_file() for path in (*BINARIES.values(), *RENDERERS.values(),
layout_path, audit_log)):
raise SystemExit("missing L115 binaries, layout, or passage audit log")
layout = json.loads(layout_path.read_text(encoding="utf-8"))
sections = parse_sections(audit_log)
if not sections:
raise SystemExit("no L115 open-air sections found")
CAPTURES.mkdir(parents=True, exist_ok=True)
HELPERS.CAPTURES = CAPTURES / "L115"
HELPERS.SAVED = SAVED / "L115"
HELPERS.CAPTURES.mkdir(parents=True, exist_ok=True)
HELPERS.SAVED.mkdir(parents=True, exist_ok=True)
rows = []
for passage in sorted(layout["passages"], key=lambda item: item["stable_id"]):
passage_sections = [item for item in sections
if item["passage"] == passage["stable_id"]]
raw_route = HELPERS.smooth_route(layout, passage)
route, _body_depth = HELPERS.derived_smooth_route(raw_route, passage, layout)
_lengths, prefix = HELPERS.route_lengths(route)
spans = rocky_spans(prefix[-1], passage_sections)
candidates = rock_station_candidates(spans)
accepted_stations = []
total_rock_length = sum(end - start for start, end in spans)
minimum_spacing = max(1.0, total_rock_length * 0.02)
for station in candidates:
if any(abs(station - prior) < minimum_spacing for prior in accepted_stations):
continue
index = len(accepted_stations) + 1
try:
row = capture_rock_floor(layout, passage, station, index)
except RuntimeError as error:
message = str(error)
if not (message.startswith("no nearby surface vertices in mesh scene:")
or message.startswith("rock-floor close-up failed at ")):
raise
print(f"[L115CaptureSkip] passage={passage['stable_id']} "
f"station_m={station:.3f} reason=surface-or-anchor-check", flush=True)
continue
accepted_stations.append(station)
rows.append(row)
if len(accepted_stations) == 3:
break
if len(accepted_stations) < 3:
for base_station in tuple(accepted_stations):
for offset in (-10.0, 10.0, -15.0, 15.0, -20.0, 20.0,
-25.0, 25.0, -30.0, 30.0):
station = base_station + offset
if not any(start < station < end for start, end in spans):
continue
if any(abs(station - prior) < minimum_spacing
for prior in accepted_stations):
continue
index = len(accepted_stations) + 1
try:
row = capture_rock_floor(layout, passage, station, index)
except RuntimeError as error:
message = str(error)
if not (message.startswith(
"no nearby surface vertices in mesh scene:")
or message.startswith("rock-floor close-up failed at ")):
raise
print(f"[L115CaptureSkip] passage={passage['stable_id']} "
f"station_m={station:.3f} reason=nearby-station-check",
flush=True)
continue
accepted_stations.append(station)
rows.append(row)
if len(accepted_stations) == 3:
break
if len(accepted_stations) == 3:
break
if len(accepted_stations) != 3:
raise RuntimeError(f"only {len(accepted_stations)} verified rock-floor views for "
f"{passage['stable_id']}: {accepted_stations}")
open_air_views = HELPERS.make_views(layout, sections, use_derived_shape=True,
use_spline=True, include_open_air=True)
open_air_views = [view for view in open_air_views
if view["kind"] == "open-air-close"]
if len(open_air_views) != 2 * len(sections):
raise RuntimeError("L115 open-air close-up count is not two per section")
for view in open_air_views:
row = HELPERS.capture("L115", view, layout)
if (not row["verified"]
or abs(row["closeup_camera_target_distance_m"] - 4.0) > 0.02
or row["closeup_target_surface_distance_m"] > 5.0
or row["closeup_wall_normal_alignment"] < 0.25
or row["drawn_triangles"] <= 0
or row["pixel_quality_status"] not in
("pass", "low_contrast_geometry_visible")):
raise RuntimeError(f"open-air close-up failed: {view['name']}")
row["variant"] = "L115"
rows.append(row)
(CAPTURES / "capture-index.json").write_text(
json.dumps({"captures": rows}, indent=2) + "\n", encoding="utf-8")
floor_rows = [row for row in rows if row["kind"] == "rock-floor-close"]
wall_rows = [row for row in rows if row["kind"] == "open-air-close"]
passage_ids = {item["stable_id"] for item in layout["passages"]}
if (len(floor_rows) != 3 * len(passage_ids)
or any(sum(row["passage"] == passage for row in floor_rows) != 3
for passage in passage_ids)
or len(wall_rows) != 2 * len(sections)):
raise RuntimeError("L115 capture count mismatch")
lines = ["# L115 captures", "",
"Each passage has three floor close-ups sampled outside the audited open-air spans. "
"Floor anchors require an upward normal alignment of at least 0.85, a target-to-floor "
"distance of at most 0.25 m, and a camera-to-floor distance between 2.0 and 3.2 m. "
"Each open-air section has verified outside and interior wall close-ups at 4 m.", ""]
for row in rows:
lines.append(f"- [{row['passage']} {row['station']}]({row['capture']}) — "
f"{row['kind']}; {row.get('drawn_triangles', 0)} triangles; "
f"{row['pixel_quality_status']}")
(CAPTURES / "INDEX.md").write_text("\n".join(lines) + "\n", encoding="utf-8")
print(f"[L115CaptureSummary] captures={len(rows)} rock_floors={len(floor_rows)} "
f"open_air_closeups={len(wall_rows)} sections={len(sections)} status=PASS",
flush=True)
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,79 @@
#!/usr/bin/env python3
"""Measure L115 floor zero crossings at three route stations per passage."""
from __future__ import annotations
import csv
import json
import math
import os
import re
import statistics
import subprocess
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l115/density-probe"
BINARY = ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-clang"
DATA = ROOT / "Standalone/data/owner_world.json"
SLOPE = re.compile(
r"^\[L115DensitySlopeSample\] passage=(\S+) station=(\S+) s_m=([\d.]+) "
r".*?planned_floor_m=(-?[\d.]+) root_floor_m=(-?[\d.]+|nan) "
r"residual_m=(-?[\d.]+|nan)", re.M)
def main() -> int:
OUT.mkdir(parents=True, exist_ok=True)
log = OUT / "owner4-clang.log"
layout = OUT / "layout.json"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
"timeout", "1740s", str(BINARY), str(DATA), "--world-assembler-prototype",
"--stream-benchmark", "--stream-pipeline", "--workers=12", "--clip-radius=3",
"--max-clip-level=8", "--max-level=8", "--camera=8,16,-372.2626953125,0,0",
"--audit-resolved-layout-passages", f"--resolved-layout-output={layout}",
]
with log.open("w", encoding="utf-8") as stream:
result = subprocess.run(command, cwd=ROOT,
env={**os.environ,
"VOXELFORGE_L115_DENSITY_PROFILE": "1"},
stdout=stream, stderr=subprocess.STDOUT,
check=False, timeout=1740)
if result.returncode:
raise SystemExit(f"L115 density probe failed: {log}")
text = log.read_text(encoding="utf-8", errors="replace")
groups: dict[tuple[str, str], list[dict]] = {}
for passage, station, distance, planned, root, residual in SLOPE.findall(text):
root_value = float(root) if root != "nan" else math.nan
residual_value = float(residual) if residual != "nan" else math.nan
groups.setdefault((passage, station), []).append({
"route_s_m": float(distance), "planned_floor_m": float(planned),
"root_floor_m": root_value, "offset_m": residual_value})
summary = []
with (OUT / "zero-crossing-offsets.csv").open("w", newline="", encoding="utf-8") as stream:
writer = csv.DictWriter(stream, fieldnames=("passage", "station", "route_s_m",
"planned_floor_m", "root_floor_m", "offset_m"))
writer.writeheader()
for (passage, station), samples in sorted(groups.items()):
for sample in samples:
writer.writerow({"passage": passage, "station": station, **sample})
finite = [sample["offset_m"] for sample in samples
if math.isfinite(sample["offset_m"])]
summary.append({"passage": passage, "station": station,
"samples": len(samples), "finite_roots": len(finite),
"max_abs_offset_m": max(map(abs, finite)) if finite else None,
"median_abs_offset_m": statistics.median(map(abs, finite))
if finite else None,
"p95_abs_offset_m": sorted(map(abs, finite))[
min(len(finite)-1, math.ceil(0.95*len(finite))-1)]
if finite else None})
if not summary or any(item["samples"] != 51 for item in summary):
raise RuntimeError("L115 density profile is missing 51-sample route stations")
(OUT / "zero-crossing-summary.json").write_text(
json.dumps(summary, indent=2) + "\n", encoding="utf-8")
print(f"[L115DensityProbe] exit={result.returncode} stations={len(summary)} "
f"log={log.relative_to(ROOT)}", flush=True)
return result.returncode
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,103 @@
#!/usr/bin/env python3
"""Check Clang/GCC hash identity at W1/W8/W12 and pin v223 owner hashes."""
from __future__ import annotations
import json
import re
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l115/hashes"
DATASETS = {
"owner4": ROOT / "Standalone/data/owner_world.json",
"owner2": ROOT / "Standalone/data/regression/owner_world_2strate_l61.json",
}
BINARIES = {
"clang": ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-clang",
"gcc": ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-gcc",
}
HASH = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M)
STAMP = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=(\S+)$", re.M)
def run(dataset: str, recipe: str, workers: int, compiler: str) -> dict:
OUT.mkdir(parents=True, exist_ok=True)
label = f"{dataset}-{recipe}-w{workers}-{compiler}"
log = OUT / f"{label}.log"
layout = OUT / f"{label}.layout.json"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
"timeout", "1740s", str(BINARIES[compiler]), str(DATASETS[dataset]),
f"--workers={workers}", "--world-assembler-prototype", "--stream-benchmark",
"--stream-pipeline", "--force-generate", "--clip-radius=3",
"--max-clip-level=8", "--max-level=8", f"--recipe={recipe}",
"--stream-hash", f"--resolved-layout-output={layout}",
]
started = time.monotonic()
with log.open("w", encoding="utf-8") as stream:
result = subprocess.run(command, cwd=ROOT, stdout=stream,
stderr=subprocess.STDOUT, check=False, timeout=1740)
output = log.read_text(encoding="utf-8", errors="replace")
hashes = HASH.findall(output)
if result.returncode or len(hashes) != 12:
raise SystemExit(f"hash run failed or incomplete: {label}; exit={result.returncode} "
f"hashes={len(hashes)} log={log}")
row = {"dataset": dataset, "recipe": recipe, "workers": workers,
"compiler": compiler, "exit_code": result.returncode,
"hashes": hashes, "source_stamp": (STAMP.search(output).group(1)
if STAMP.search(output) else None),
"elapsed_s": round(time.monotonic() - started, 3),
"log": str(log.relative_to(ROOT))}
print("[L115HashRun] " + json.dumps(row, sort_keys=True), flush=True)
return row
def main() -> int:
if any(not path.is_file() for path in (*DATASETS.values(), *BINARIES.values())):
raise SystemExit("missing L115 hash input")
rows = []
recipes = {"owner4": ("surface-world",),
"owner2": ("surface-world", "floating-islands")}
for dataset, dataset_recipes in recipes.items():
for recipe in dataset_recipes:
for workers in (1, 8, 12):
for compiler in ("clang", "gcc"):
rows.append(run(dataset, recipe, workers, compiler))
(OUT / "runs-partial.json").write_text(
json.dumps(rows, indent=2) + "\n", encoding="utf-8")
groups = {}
for dataset, dataset_recipes in recipes.items():
for recipe in dataset_recipes:
key = f"{dataset}/{recipe}"
group = [row for row in rows if row["dataset"] == dataset
and row["recipe"] == recipe]
reference = group[0]["hashes"]
groups[key] = {"all_worker_compiler_hashes_match": all(
row["hashes"] == reference for row in group),
"source_stamps": sorted({row["source_stamp"] for row in group}),
"runs": [{"workers": row["workers"], "compiler": row["compiler"],
"log": row["log"]} for row in group]}
if not groups[key]["all_worker_compiler_hashes_match"]:
raise SystemExit(f"determinism mismatch: {key}")
if dataset == "owner2":
canonical = next(row for row in group if row["workers"] == 12
and row["compiler"] == "clang")
recipe_name = "floating-islands" if recipe == "floating-islands" else "surface-world"
style = 1 if recipe_name == "surface-world" else 2
baseline = (ROOT / "Standalone/Tools/verify/baselines/owner-hash/canonical"
/ f"owner-hash-{recipe_name}-style{style}-v223.baseline")
baseline.write_text("\n".join(canonical["hashes"]) + "\n",
encoding="utf-8")
summary = {"runs": rows, "groups": groups,
"owner4_all_four_strata": "owner4/surface-world",
"owner2_canonical_pins": ["owner2/surface-world",
"owner2/floating-islands"]}
(OUT / "summary.json").write_text(json.dumps(summary, indent=2) + "\n",
encoding="utf-8")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,124 @@
#!/usr/bin/env python3
"""Five interleaved L80 readiness runs for L109, L114, and L115."""
from __future__ import annotations
import json
import os
import re
import statistics
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l115/timing"
DATA = ROOT / "Standalone/data/owner_world.json"
BINARIES = {
"L109": ROOT / "Saved/Linux/l109/bin-final/VoxelForgeCoreHeadless-l109-clang",
"L114": ROOT / "Saved/Linux/l114/bin/VoxelForgeCoreHeadless-l114-clang",
"L115": ROOT / "Saved/Linux/l115/bin/VoxelForgeCoreHeadless-l115-clang",
}
CAMERAS = {
0: (8.0, 16.0, -372.2626953125),
1: (25.8369140625, 3.19921875, -737.0),
2: (19.166015625, -14.2001953125, -753.3740234375),
3: (-20.0625, -5.068359375, -900.353515625),
}
PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M)
FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)")
NEAR = re.compile(
r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$",
re.M,
)
def run(strate: int, workers: int, version: str, phase: str, replicate: int) -> dict:
OUT.mkdir(parents=True, exist_ok=True)
label = f"s{strate}-w{workers}-{version}-{phase}{replicate}"
log = OUT / f"{label}.log"
camera = ",".join(f"{v:.12f}" for v in CAMERAS[strate]) + ",0,0"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
"timeout", "1740s", str(BINARIES[version]), str(DATA),
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8", "--max-level=8",
f"--camera={camera}", "--profile-lod-work", "--stream-scheduler-policy=3",
]
start = time.monotonic()
with log.open("w", encoding="utf-8") as output:
result = subprocess.run(command, cwd=ROOT, stdout=output,
stderr=subprocess.STDOUT, check=False, timeout=1740)
content = log.read_text(encoding="utf-8", errors="replace")
pipeline_match = PIPELINE.search(content)
near_match = NEAR.search(content)
if result.returncode or pipeline_match is None or near_match is None:
raise SystemExit(f"readiness run failed or trace missing: {log}; exit={result.returncode}")
pipeline = dict(FIELDS.findall(pipeline_match.group(1)))
row = {
"strate": strate, "workers": workers, "version": version,
"phase": phase, "replicate": replicate, "exit_code": result.returncode,
"wall_s": round(time.monotonic() - start, 3),
"lod02_ready_s": float(near_match.group(3)),
"whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")),
"whole_tiles": int(pipeline["whole_tiles"].split("/")[0]),
"log": str(log.relative_to(ROOT)),
}
print("[L115TimingRun] " + json.dumps(row, sort_keys=True), flush=True)
return row
def main() -> int:
if not DATA.is_file() or any(not binary.is_file() for binary in BINARIES.values()):
raise SystemExit("missing L109/L114/L115 data or timing binary")
OUT.mkdir(parents=True, exist_ok=True)
load_1m = os.getloadavg()[0]
uptime = subprocess.run(["uptime"], cwd=ROOT, text=True, capture_output=True,
check=True).stdout.strip()
top = subprocess.run(["ps", "-eo", "pid,pcpu,comm", "--sort=-pcpu"], cwd=ROOT,
text=True, capture_output=True, check=True).stdout
(OUT / "machine-load-before.txt").write_text(
f"uptime: {uptime}\n1-minute load: {load_1m:.2f}\ntop CPU users:\n{top}",
encoding="utf-8")
print(f"[L115TimingGate] load_1m={load_1m:.2f} uptime={uptime}", flush=True)
if load_1m >= 1.5:
raise SystemExit(f"timing refused: 1-minute load {load_1m:.2f} is not below 1.5")
rows = []
versions = ("L109", "L114", "L115")
for strate in range(4):
for workers in (8, 12):
for version in versions:
run(strate, workers, version, "warmup", 0)
for replicate in range(1, 6):
offset = (replicate - 1) % len(versions)
order = versions[offset:] + versions[:offset]
for version in order:
rows.append(run(strate, workers, version, "measured", replicate))
(OUT / "runs-partial.json").write_text(
json.dumps(rows, indent=2) + "\n", encoding="utf-8")
summary = []
for strate in range(4):
for workers in (8, 12):
item = {"strate": strate, "workers": workers, "replicates": 5}
medians = {}
for version in versions:
group = [row for row in rows if row["strate"] == strate
and row["workers"] == workers and row["version"] == version]
medians[version] = {}
for key in ("lod02_ready_s", "whole_view_ready_s"):
values = [row[key] for row in group]
medians[version][key] = statistics.median(values)
item[f"{version}_{key}_values"] = values
item[f"{version}_{key}_median"] = medians[version][key]
for comparison in ("L109", "L114"):
for key in ("lod02_ready_s", "whole_view_ready_s"):
item[f"L115_vs_{comparison}_{key}_delta_pct"] = round(
100.0 * (medians["L115"][key] / medians[comparison][key] - 1.0), 2)
summary.append(item)
(OUT / "summary.json").write_text(
json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n",
encoding="utf-8")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,27 @@
# L115 captures
Each passage has three floor close-ups sampled outside the audited open-air spans. Floor anchors require an upward normal alignment of at least 0.85, a target-to-floor distance of at most 0.25 m, and a camera-to-floor distance between 2.0 and 3.2 m. Each open-air section has verified outside and interior wall close-ups at 4 m.
- [passage/0-1/0 rock-floor/401.7m](captures/L115/L115/passage-0-1-0-rock-floor-station-1.png) — rock-floor-close; 122256 triangles; pass
- [passage/0-1/0 rock-floor/792.8m](captures/L115/L115/passage-0-1-0-rock-floor-station-2.png) — rock-floor-close; 585992 triangles; pass
- [passage/0-1/0 rock-floor/1634.5m](captures/L115/L115/passage-0-1-0-rock-floor-station-3.png) — rock-floor-close; 137252 triangles; pass
- [passage/1-2/0 rock-floor/27.0m](captures/L115/L115/passage-1-2-0-rock-floor-station-1.png) — rock-floor-close; 652088 triangles; pass
- [passage/1-2/0 rock-floor/52.9m](captures/L115/L115/passage-1-2-0-rock-floor-station-2.png) — rock-floor-close; 636128 triangles; pass
- [passage/1-2/0 rock-floor/78.9m](captures/L115/L115/passage-1-2-0-rock-floor-station-3.png) — rock-floor-close; 580512 triangles; pass
- [passage/2-3/0 rock-floor/323.4m](captures/L115/L115/passage-2-3-0-rock-floor-station-1.png) — rock-floor-close; 474896 triangles; low_contrast_geometry_visible
- [passage/2-3/0 rock-floor/333.4m](captures/L115/L115/passage-2-3-0-rock-floor-station-2.png) — rock-floor-close; 494436 triangles; pass
- [passage/2-3/0 rock-floor/343.4m](captures/L115/L115/passage-2-3-0-rock-floor-station-3.png) — rock-floor-close; 485332 triangles; pass
- [passage/0-1/0 section-1/4m-outside](captures/L115/L115/passage-0-1-0-openair-1-4m-outside.png) — open-air-close; 275313 triangles; pass
- [passage/0-1/0 section-1/4m-interior-wall](captures/L115/L115/passage-0-1-0-openair-1-4m-interior-wall.png) — open-air-close; 307964 triangles; low_contrast_geometry_visible
- [passage/0-1/0 section-2/4m-outside](captures/L115/L115/passage-0-1-0-openair-2-4m-outside.png) — open-air-close; 275313 triangles; pass
- [passage/0-1/0 section-2/4m-interior-wall](captures/L115/L115/passage-0-1-0-openair-2-4m-interior-wall.png) — open-air-close; 345024 triangles; pass
- [passage/0-1/0 section-3/4m-outside](captures/L115/L115/passage-0-1-0-openair-3-4m-outside.png) — open-air-close; 148970 triangles; pass
- [passage/0-1/0 section-3/4m-interior-wall](captures/L115/L115/passage-0-1-0-openair-3-4m-interior-wall.png) — open-air-close; 148032 triangles; pass
- [passage/1-2/0 section-1/4m-outside](captures/L115/L115/passage-1-2-0-openair-1-4m-outside.png) — open-air-close; 620866 triangles; low_contrast_geometry_visible
- [passage/1-2/0 section-1/4m-interior-wall](captures/L115/L115/passage-1-2-0-openair-1-4m-interior-wall.png) — open-air-close; 609733 triangles; pass
- [passage/1-2/0 section-2/4m-outside](captures/L115/L115/passage-1-2-0-openair-2-4m-outside.png) — open-air-close; 584622 triangles; pass
- [passage/1-2/0 section-2/4m-interior-wall](captures/L115/L115/passage-1-2-0-openair-2-4m-interior-wall.png) — open-air-close; 572238 triangles; pass
- [passage/2-3/0 section-1/4m-outside](captures/L115/L115/passage-2-3-0-openair-1-4m-outside.png) — open-air-close; 104612 triangles; low_contrast_geometry_visible
- [passage/2-3/0 section-1/4m-interior-wall](captures/L115/L115/passage-2-3-0-openair-1-4m-interior-wall.png) — open-air-close; 94962 triangles; low_contrast_geometry_visible
- [passage/2-3/0 section-2/4m-outside](captures/L115/L115/passage-2-3-0-openair-2-4m-outside.png) — open-air-close; 475838 triangles; pass
- [passage/2-3/0 section-2/4m-interior-wall](captures/L115/L115/passage-2-3-0-openair-2-4m-interior-wall.png) — open-air-close; 486512 triangles; pass
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

File diff suppressed because it is too large. Load diff