#!/usr/bin/env python3 """Extract the validated recipe-stamped passage matrix into a compact table.""" import csv import re from pathlib import Path ROOT = Path(__file__).resolve().parents[4] OUT = ROOT / "Saved/Linux/l31" rows = [] for recipe in ("surface-world", "floating-islands"): for style in range(4): for compiler in ("clang", "gcc"): name = f"passage-{recipe}-style{style}-{compiler}" path = OUT / f"{name}.log" text = path.read_text(encoding="utf-8", errors="replace") def match(pattern): found = re.search(pattern, text, re.M) if not found: raise SystemExit(f"{path}: missing metric {pattern}") return found stamp = match( r"^\[WorldAssemblerRecipeAudit\] requested=([^ ]+) actual=([^ ]+).*status=(PASS|FAIL)$") capsule = match( r"^\[ResolvedPassageAudit\].*capsule_samples=(\d+) blocked=(\d+) " r"support_samples=(\d+) unsupported=(\d+) grade_failures=(\d+) " r"mouth_content=([^ ]+) mouth_radius=([^ ]+) .*$") air = match(r"^\[PassageOpenAirAuditSummary\].*violations=(\d+).*status=(PASS|FAIL)$") natural = match(r"^\[PassageNaturalnessSummary\] passed=(\d+)/(\d+).*$") bridge = match( r"^\[PassageNoLongBridgeAudit\].*longest_uncolumned_m=([0-9.]+) " r"threshold_m=([0-9.]+).*$") column = match( r"^\[PassageRockColumnAuditSummary\] columns=(\d+) connected_ends=([^ ]+) " r"short_spans=(\d+) wall_or_support_failures=(\d+).*status=(PASS|FAIL)$") binding = match( r"^\[ResolvedPassageAuditSummary\].*route_bindings=(\d+) " r"route_binding_failures=(\d+).*status=(PASS|FAIL)$") walk = match(r"^\[Walkability\] PASS (\d+)/(\d+) passage centerline samples") rows.append({ "requested": stamp.group(1), "actual": stamp.group(2), "stamp": stamp.group(3), "style": style, "compiler": compiler, "capsule_samples": int(capsule.group(1)), "blocked": int(capsule.group(2)), "support_samples": int(capsule.group(3)), "unsupported": int(capsule.group(4)), "grade_failures": int(capsule.group(5)), "mouth_content": capsule.group(6), "mouth_radius": capsule.group(7), "air_violations": int(air.group(1)), "air_status": air.group(2), "natural_passed": natural.group(1), "natural_total": natural.group(2), "longest_uncolumned_m": bridge.group(1), "bridge_threshold_m": bridge.group(2), "column_count": int(column.group(1)), "connected_ends": column.group(2), "short_spans": int(column.group(3)), "column_failures": int(column.group(4)), "route_bindings": int(binding.group(1)), "binding_failures": int(binding.group(2)), "walk_samples": int(walk.group(1)), "walk_total": int(walk.group(2)), "log": path.name, }) with (OUT / "passage-audit-metrics.csv").open("w", newline="", encoding="utf-8") as stream: writer = csv.DictWriter(stream, fieldnames=list(rows[0])) writer.writeheader() writer.writerows(rows) lines = [ "| Requested → actual | Style | Compiler | Capsule | Open air | Natural | Long bridge | Column ends | Bindings | Walkability |", "|---|---:|---|---|---:|---:|---:|---:|---:|---:|", ] for row in rows: ok = (row["requested"] == row["actual"] and row["stamp"] == "PASS" and row["blocked"] == row["unsupported"] == row["grade_failures"] == 0 and row["mouth_content"] == row["mouth_radius"] == "2/2" and row["air_violations"] == 0 and row["air_status"] == "PASS" and row["natural_passed"] == row["natural_total"] == "1" and float(row["longest_uncolumned_m"]) <= float(row["bridge_threshold_m"]) and row["connected_ends"] == f"{2 * row['column_count']}/{2 * row['column_count']}" and row["column_failures"] == 0 and row["binding_failures"] == 0 and row["route_bindings"] > 0 and row["walk_samples"] == row["walk_total"]) if not ok: raise SystemExit(f"{row['log']}: metric audit failed") cells = ( f"{row['blocked']}/{row['unsupported']} blocked/unsupported; mouth 2/2", f"{row['air_violations']} violations", f"{row['natural_passed']}/{row['natural_total']}", f"{float(row['longest_uncolumned_m']):.3f}/{row['bridge_threshold_m']} m", row["connected_ends"], f"{row['route_bindings']} (0 failures)", f"{row['walk_samples']}/{row['walk_total']}", ) lines.append(f"| {row['requested']} → {row['actual']} | {row['style']} | {row['compiler']} | " + " | ".join(cells) + " |") table = OUT / "passage-audit-table.md" table.write_text("\n".join(lines) + "\n", encoding="utf-8") print(f"[L31PassageAuditTable] rows={len(rows)} pass={len(rows)} " f"csv={OUT / 'passage-audit-metrics.csv'} markdown={table}")