wip(assembler): round L33 -- SurfaceWorld can be an upper strate; FloorProfileBlend measures seams
Route planning for an upper SurfaceWorld failed on long candidate chords over steep relief; chords are now capped to the arrival/departure radii on an 8 m centre grid with an origin-proximity cost (21.5 m walk, about 4 deg). The departure passage starts at the SW ground and tunnels down through rock. FI -> SW -> TN fixture: all 4 styles pass every passage audit on both compilers. FloorProfileBlend now checks endpoint height/tangent seams (step and tangent-step negative controls detected). Owner world hashes unchanged; 30/30 determinism; cost within noise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
1 parent
d0158c6019
commit
b7a47bef95
17 files changed
+1116
-32
No files matched your search
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run owner L25 hashes, 24 m crossings, and upper-SurfaceWorld fixture determinism."""
|
||||
import re
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[4]
|
||||
OUT = ROOT / "Saved/Linux/l33"
|
||||
L32 = ROOT / "Saved/Linux/l32"
|
||||
FIXTURE = OUT / "fixtures/sw-upper-tunnel-network-style0.json"
|
||||
BINARIES = {
|
||||
"clang": OUT / "bin/VoxelForgeCoreHeadless-clang-l33-final",
|
||||
"gcc": OUT / "bin/VoxelForgeCoreHeadless-gcc-l33-final",
|
||||
}
|
||||
HASH_PATTERN = re.compile(
|
||||
r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M)
|
||||
LAYOUT_PATTERN = re.compile(
|
||||
r"^\[ResolvedLayoutSnapshot\] schema=\d+ stable_identity=([^ ]+) strata=\d+ bytes=\d+ round_trip=PASS$",
|
||||
re.M)
|
||||
PLAN_PATTERN = re.compile(
|
||||
r"^\[WorldAssemblerPlanSerialization\].*canonical_round_trip=true .*"
|
||||
r"plan_hash=([0-9a-f]+) manifest_hash=([0-9a-f]+) status=PASS$", re.M)
|
||||
ROUTE_PATTERN = re.compile(
|
||||
r"^\[WorldAssemblerRouteAccepted\] arrival_xy_m=\([^)]*\) "
|
||||
r"departure_xy_m=\([^)]*\) endpoint_proximity_cost=\d+ average_grade_q16=\d+$", re.M)
|
||||
rows = []
|
||||
failed = False
|
||||
owner_reference = {}
|
||||
fixture_reference = None
|
||||
|
||||
|
||||
def run(command, logfile):
|
||||
started = time.monotonic()
|
||||
try:
|
||||
with logfile.open("w", encoding="utf-8") as stream:
|
||||
result = subprocess.run(command, stdout=stream, stderr=subprocess.STDOUT,
|
||||
timeout=1800, check=False)
|
||||
except subprocess.TimeoutExpired:
|
||||
result = None
|
||||
return result, time.monotonic() - started, logfile.read_text(
|
||||
encoding="utf-8", errors="replace")
|
||||
|
||||
|
||||
for kind in ("l25", "crossing24"):
|
||||
for recipe in ("surface-world", "floating-islands"):
|
||||
for compiler, binary in BINARIES.items():
|
||||
for workers in (1, 8, 12):
|
||||
name = f"{kind}-{compiler}-{recipe}-w{workers}"
|
||||
logfile = OUT / f"determinism-{name}.log"
|
||||
command = [
|
||||
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
||||
str(binary), str(ROOT / "Standalone/data/owner_world.json"),
|
||||
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
|
||||
"--stream-hash", "--force-generate", "--clip-radius=3",
|
||||
"--max-clip-level=8", "--far-horizon-lod8-step=0",
|
||||
f"--workers={workers}", f"--recipe={recipe}",
|
||||
]
|
||||
if kind == "crossing24":
|
||||
command.extend(("--camera-step=24,0,0", "--region-crossing"))
|
||||
result, elapsed, text = run(command, logfile)
|
||||
hashes = HASH_PATTERN.findall(text)
|
||||
stamps = re.findall(
|
||||
r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$",
|
||||
text, re.M)
|
||||
ref = L32 / f"{kind}-settled-final-{compiler}-{recipe}-w{workers}.log"
|
||||
reference_hashes = HASH_PATTERN.findall(ref.read_text(
|
||||
encoding="utf-8", errors="replace")) if ref.exists() else []
|
||||
stable_key = (kind, recipe)
|
||||
stable = stable_key not in owner_reference or hashes == owner_reference[stable_key]
|
||||
if stable_key not in owner_reference and hashes:
|
||||
owner_reference[stable_key] = hashes
|
||||
equal_l32 = len(hashes) == 12 and hashes == reference_hashes
|
||||
ok = (result is not None and result.returncode == 0
|
||||
and stamps == [(recipe, recipe, "PASS")]
|
||||
and "hash=on" in text and len(hashes) == 12 and stable and equal_l32)
|
||||
rows.append((kind, recipe, compiler, workers, elapsed,
|
||||
result.returncode if result else "TIMEOUT", ok))
|
||||
print(f"{name} elapsed={elapsed:.1f}s hashes={len(hashes)}/12 "
|
||||
f"same_across_matrix={'yes' if stable else 'no'} "
|
||||
f"same_as_l32={'yes' if equal_l32 else 'no'} {'PASS' if ok else 'FAIL'}",
|
||||
flush=True)
|
||||
failed |= not ok
|
||||
|
||||
|
||||
for compiler, binary in BINARIES.items():
|
||||
for workers in (1, 8, 12):
|
||||
name = f"upper-fixture-{compiler}-w{workers}"
|
||||
logfile = OUT / f"determinism-{name}.log"
|
||||
command = [
|
||||
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
||||
str(binary), str(FIXTURE), "--workers=" + str(workers),
|
||||
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
|
||||
"--force-generate", "--clip-radius=3", "--max-clip-level=8",
|
||||
"--max-level=-1", "--recipe=floating-islands", "--audit-resolved-layout-passages",
|
||||
]
|
||||
result, elapsed, text = run(command, logfile)
|
||||
layouts = LAYOUT_PATTERN.findall(text)
|
||||
plans = PLAN_PATTERN.findall(text)
|
||||
routes = ROUTE_PATTERN.findall(text)
|
||||
stamps = re.findall(
|
||||
r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$",
|
||||
text, re.M)
|
||||
passage_summary = re.search(r"^\[ResolvedPassageAuditSummary\].*status=PASS$", text, re.M)
|
||||
signature = (tuple(layouts), tuple(plans), tuple(routes))
|
||||
stable = fixture_reference is None or signature == fixture_reference
|
||||
if fixture_reference is None and layouts and plans and routes:
|
||||
fixture_reference = signature
|
||||
ok = (result is not None and result.returncode == 0 and len(layouts) == 1
|
||||
and len(plans) == 1 and len(routes) == 1
|
||||
and stamps == [("floating-islands", "floating-islands", "PASS")]
|
||||
and passage_summary is not None and stable)
|
||||
rows.append(("upper-fixture", "floating-islands", compiler, workers, elapsed,
|
||||
result.returncode if result else "TIMEOUT", ok))
|
||||
print(f"{name} elapsed={elapsed:.1f}s layout={layouts[0] if layouts else 'MISSING'} "
|
||||
f"stable_across_matrix={'yes' if stable else 'no'} {'PASS' if ok else 'FAIL'}",
|
||||
flush=True)
|
||||
failed |= not ok
|
||||
|
||||
|
||||
summary = OUT / "determinism-l33.csv"
|
||||
summary.write_text(
|
||||
"kind,recipe,compiler,workers,elapsed_seconds,exit_code,status\n" +
|
||||
"".join(f"{kind},{recipe},{compiler},{workers},{elapsed:.3f},{code},"
|
||||
f"{'PASS' if ok else 'FAIL'}\n"
|
||||
for kind, recipe, compiler, workers, elapsed, code, ok in rows),
|
||||
encoding="utf-8")
|
||||
print(f"[L33Determinism] runs={len(rows)} pass={sum(row[-1] for row in rows)} "
|
||||
f"fail={sum(not row[-1] for row in rows)} summary={summary}", flush=True)
|
||||
raise SystemExit(1 if failed or len(rows) != 30 else 0)
|
||||
Reference in new issue
Block a user