Files
VoxelForge/Standalone/Research/WorldAssemblerM3/Linux110/VerifyL110Captures.py
T
Fr0zkaandClaude Opus 5.5 bf39712792 passages: smoothed open-air shell joins (L110, v257) - partial, not merged
Bands = end profiles of per-control-span shell capsules (~9.35 m pitch = span spacing).
Shell now smooth-unions adjacent spans over 6 m and reuses the interior chord distance; a 0.60 m
clearance fades in 5-20 m from each mouth. Close-ups: bands reduced but still visible on part of
the exposed shell. Cost vs L109: near-ready +8..+12% (FI 0.88 -> 1.00, TN 0.92 -> 1.01 s @W12).
Audits, Clang/GCC determinism, fast tier and Linux UE build pass. Kept on its own branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
2026-10-29 16:07:52 +01:00

89 lines
3.8 KiB
Python

#!/usr/bin/env python3
"""Check the paired L109/L110 capture set and 4 m shell close-ups."""
from __future__ import annotations
import hashlib
import json
from collections import Counter
from pathlib import Path
import struct
ROOT = Path(__file__).resolve().parents[4]
CAPTURE_ROOT = Path(__file__).resolve().parent / "captures"
RESEARCH_ROOT = CAPTURE_ROOT.parent
INDEX = CAPTURE_ROOT / "capture-index.json"
OUTPUT = CAPTURE_ROOT / "capture-verification.json"
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 png_size(path: Path) -> tuple[int, int]:
with path.open("rb") as stream:
header = stream.read(24)
if len(header) != 24 or header[:8] != b"\x89PNG\r\n\x1a\n" or header[12:16] != b"IHDR":
raise RuntimeError(f"invalid PNG: {path}")
return struct.unpack(">II", header[16:24])
def main() -> int:
captures = json.loads(INDEX.read_text(encoding="utf-8"))["captures"]
counts = {variant: Counter(row["kind"] for row in captures
if row["variant"] == variant)
for variant in ("before", "after")}
by_variant = {variant: {row["name"]: row for row in captures
if row["variant"] == variant}
for variant in ("before", "after")}
errors: list[str] = []
for variant in ("before", "after"):
rows = [row for row in captures if row["variant"] == variant]
if len(rows) != 53:
errors.append(f"{variant}: expected 53 captures, got {len(rows)}")
for row in rows:
image = RESEARCH_ROOT / row["capture"]
if not row.get("verified") or row.get("render_tile_skirts") != "off":
errors.append(f"{variant}/{row['name']}: render verification flags failed")
if row.get("drawn_triangles", 0) <= 0 or not image.is_file():
errors.append(f"{variant}/{row['name']}: missing geometry or image")
elif png_size(image) != (1920, 1080):
errors.append(f"{variant}/{row['name']}: unexpected image size {png_size(image)}")
closeups = [row for row in rows if row["kind"] == "open-air-closeup"]
if len(closeups) != 11:
errors.append(f"{variant}: expected 11 close-ups, got {len(closeups)}")
for row in closeups:
distance = row.get("shell_standoff_actual_m")
if distance is None or not 3.0 <= distance <= 5.0:
errors.append(f"{variant}/{row['name']}: close-up standoff {distance}")
names_before, names_after = set(by_variant["before"]), set(by_variant["after"])
if names_before != names_after:
errors.append("before/after capture names do not match")
pair_counts = Counter()
for name in sorted(names_before & names_after):
left, right = by_variant["before"][name], by_variant["after"][name]
same = sha256(RESEARCH_ROOT / left["capture"]) == sha256(
RESEARCH_ROOT / right["capture"])
pair_counts[f"{left['kind']}_{'identical' if same else 'changed'}"] += 1
summary = {
"status": "PASS" if not errors else "FAIL",
"capture_count": len(captures),
"open_air_sections": len(json.loads(INDEX.read_text(encoding="utf-8"))[
"open_air_sections"]),
"per_variant_kind_counts": {variant: dict(sorted(counts[variant].items()))
for variant in counts},
"paired_image_bytes": dict(sorted(pair_counts.items())),
"errors": errors,
}
OUTPUT.write_text(json.dumps(summary, indent=2) + "\n", encoding="utf-8")
print(json.dumps(summary, sort_keys=True))
return 0 if not errors else 1
if __name__ == "__main__":
raise SystemExit(main())