Band faces now use signed distance to the displaced solid intervals, continuous across bands, so MC interpolates the interface instead of terracing at density levels. The Gradient amplitude is restored to width/8 (about 4 m peak-to-peak at 16 m). Ring/terrace audit at LOD0-8 on the FI floor and SW ceiling passes; negative controls: L30 (rings) and L31 (flat) both fail. Hole/interface audits, 16 passage rows and 24/24 determinism pass. Evaluator 20. Cost vs L31 SW +1.9%, FI +1.5%. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
99 lines
4.3 KiB
Python
99 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Check the L25 hash command and 24 m crossing across compilers and workers."""
|
|
import os
|
|
import re
|
|
import subprocess
|
|
import time
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[4]
|
|
OUT = ROOT / "Saved/Linux/l32"
|
|
OUT.mkdir(parents=True, exist_ok=True)
|
|
RUN_TAG = os.environ.get("VOXELFORGE_DETERMINISM_TAG", "").strip()
|
|
RUN_RESUME = os.environ.get("VOXELFORGE_DETERMINISM_RESUME", "0") == "1"
|
|
BINARIES = {
|
|
"clang": Path(os.environ.get("VOXELFORGE_L32_CLANG_BINARY",
|
|
str(OUT / "bin/VoxelForgeCoreHeadless-l32-clang-v20"))),
|
|
"gcc": Path(os.environ.get("VOXELFORGE_L32_GCC_BINARY",
|
|
str(OUT / "bin/VoxelForgeCoreHeadless-l32-gcc-v20"))),
|
|
}
|
|
HASH_PATTERN = re.compile(
|
|
r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M)
|
|
candidate_reference = {}
|
|
rows = []
|
|
failed = False
|
|
prior_elapsed = {}
|
|
if RUN_RESUME and RUN_TAG:
|
|
prior_log = OUT / f"determinism-{RUN_TAG}-runner.log"
|
|
if prior_log.exists():
|
|
for line in prior_log.read_text(encoding="utf-8", errors="replace").splitlines():
|
|
match = re.match(r"^(\S+) elapsed=([0-9.]+)s .* PASS$", line)
|
|
if match:
|
|
prior_elapsed[match.group(1)] = float(match.group(2))
|
|
|
|
|
|
def run(kind, compiler, recipe, workers):
|
|
global failed
|
|
tag = f"-{RUN_TAG}" if RUN_TAG else ""
|
|
name = f"{kind}{tag}-{compiler}-{recipe}-w{workers}"
|
|
logfile = OUT / f"{name}.log"
|
|
command = [
|
|
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
|
str(BINARIES[compiler]), 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"))
|
|
if RUN_RESUME and name in prior_elapsed and logfile.exists():
|
|
result = subprocess.CompletedProcess(command, 0)
|
|
elapsed = prior_elapsed[name]
|
|
else:
|
|
started = time.monotonic()
|
|
try:
|
|
with logfile.open("w", encoding="utf-8") as stream:
|
|
result = subprocess.run(command, stdout=stream, stderr=subprocess.STDOUT,
|
|
timeout=900, check=False)
|
|
except subprocess.TimeoutExpired:
|
|
result = None
|
|
elapsed = time.monotonic() - started
|
|
text = logfile.read_text(encoding="utf-8", errors="replace")
|
|
stamps = re.findall(
|
|
r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=([^ ]+)$",
|
|
text, re.M)
|
|
hashes = HASH_PATTERN.findall(text)
|
|
key = (kind, recipe)
|
|
reference = candidate_reference.get(key)
|
|
stable = reference is None or hashes == reference
|
|
if reference is None and hashes:
|
|
candidate_reference[key] = 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)
|
|
rows.append((kind, recipe, compiler, workers, elapsed,
|
|
result.returncode if result else "TIMEOUT", len(hashes), ok))
|
|
print(f"{name} elapsed={elapsed:.1f}s recipe={stamps[0][1] if stamps else 'MISSING'} "
|
|
f"hashes={len(hashes)} stable_across_matrix={'yes' if stable else 'no'} "
|
|
f"{'PASS' if ok else 'FAIL'}", flush=True)
|
|
failed |= not ok
|
|
|
|
|
|
for kind in ("l25", "crossing24"):
|
|
for recipe in ("surface-world", "floating-islands"):
|
|
for compiler in ("clang", "gcc"):
|
|
for workers in (1, 8, 12):
|
|
run(kind, compiler, recipe, workers)
|
|
|
|
summary = OUT / (f"determinism-{RUN_TAG}.csv" if RUN_TAG else "determinism.csv")
|
|
summary.write_text(
|
|
"kind,recipe,compiler,workers,elapsed_seconds,exit_code,hash_rows,status\n" +
|
|
"".join(f"{kind},{recipe},{compiler},{workers},{elapsed:.3f},{code},{count},"
|
|
f"{'PASS' if ok else 'FAIL'}\n"
|
|
for kind, recipe, compiler, workers, elapsed, code, count, ok in rows),
|
|
encoding="utf-8")
|
|
print(f"[L32Determinism] 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) != 24 else 0)
|