#!/usr/bin/env python3 """Validate an emitted RRC JSON artifact against source receipts. This is an I/O-only shim: it performs no admissibility decisions. It checks: - JSON parses - required top-level fields are present - every row has required fields - equation_ids are unique - promotion is 'not_promoted' everywhere - alignment_score matches alignment_status mapping """ from __future__ import annotations import argparse import json import sys from pathlib import Path from typing import Any SCORE_MAP = { "aligned_exact": 100, "aligned_proxy": 86, "compatible_structural_projection": 72, "alignment_warning": 35, "missing_prediction": 0, } REQUIRED_TOP = {"schema", "claim_boundary", "summary", "rows"} REQUIRED_ROW = { "equation_id", "name", "shape", "status", "alignment_status", "alignment_score", "promotion", "warnings", "receipt_valid", } def validate(data: dict[str, Any]) -> list[str]: errors: list[str] = [] missing_top = REQUIRED_TOP - data.keys() if missing_top: errors.append(f"missing top-level fields: {sorted(missing_top)}") return errors rows = data.get("rows", []) if not isinstance(rows, list): errors.append("'rows' must be a list") return errors ids = set() for idx, row in enumerate(rows): missing_row = REQUIRED_ROW - row.keys() if missing_row: errors.append(f"row {idx}: missing fields {sorted(missing_row)}") continue eq_id = row["equation_id"] if eq_id in ids: errors.append(f"duplicate equation_id: {eq_id}") ids.add(eq_id) if row["promotion"] != "not_promoted": errors.append( f"row {idx} ({eq_id}): promotion must be 'not_promoted', " f"got {row['promotion']!r}" ) expected_score = SCORE_MAP.get(row["alignment_status"]) if expected_score is None: errors.append( f"row {idx} ({eq_id}): unknown alignment_status " f"{row['alignment_status']!r}" ) elif row["alignment_score"] != expected_score: errors.append( f"row {idx} ({eq_id}): alignment_score {row['alignment_score']} " f"does not match status {row['alignment_status']!r} ({expected_score})" ) return errors def main() -> int: parser = argparse.ArgumentParser(description="Validate RRC emitted JSON") parser.add_argument("json_file", help="path to emitted JSON file") args = parser.parse_args() path = Path(args.json_file) if not path.exists(): print(f"ERROR: file not found: {path}", file=sys.stderr) return 1 try: data = json.loads(path.read_text(encoding="utf-8")) except json.JSONDecodeError as e: print(f"ERROR: invalid JSON: {e}", file=sys.stderr) return 1 errors = validate(data) if errors: print("VALIDATION FAILED", file=sys.stderr) for err in errors: print(f" - {err}", file=sys.stderr) return 1 rows = data.get("rows", []) print(f"OK: {len(rows)} rows, schema={data.get('schema')}") return 0 if __name__ == "__main__": raise SystemExit(main())