mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-07-30 17:16:16 +00:00
- Move canonical FixedPoint to Core/SilverSight/FixedPoint.lean - Add SilverSightRRC library: RRC logogram gates, receipt bridge, AVM ISA - Add AVMIsa.Emit as the sole top-level JSON output boundary - Add rrc-emit-fixture executable and Python I/O shims - Update AGENTS.md, glossary, project map, and build baseline Build: 2981 jobs, 0 errors (lake build)
118 lines
3.2 KiB
Python
118 lines
3.2 KiB
Python
#!/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())
|