from __future__ import annotations import argparse import json import os import sys from pathlib import Path from src.hackathon.validation import ( MODEL_REGISTRY_ENV, STIMULI_CATALOG_ENV, load_model_registry, load_stimuli_catalog, validate_blue_submission, validate_red_submission, ) def _load_payload(path: str) -> dict: if path == "-": raw = sys.stdin.read() source = "stdin" else: source = path try: raw = Path(path).read_text() except FileNotFoundError as exc: raise ValueError(f"File not found: {path}") from exc try: data = json.loads(raw) except json.JSONDecodeError as exc: raise ValueError(f"Invalid JSON in {source}: {exc}") from exc if not isinstance(data, dict): raise ValueError("Submission JSON must be an object.") return data def main() -> int: parser = argparse.ArgumentParser(description="Validate blue/red submission JSON against the contract.") parser.add_argument("payload", help="Path to submission JSON or '-' for stdin.") parser.add_argument("--team", choices=["blue", "red"], required=True, help="Submission team to validate.") parser.add_argument( "--model-registry", default=os.environ.get(MODEL_REGISTRY_ENV, ""), help=f"Model registry JSON path (defaults to ${MODEL_REGISTRY_ENV}).", ) parser.add_argument( "--stimuli-catalog", default=os.environ.get(STIMULI_CATALOG_ENV, ""), help=f"Stimuli catalog JSON/JSONL path (defaults to ${STIMULI_CATALOG_ENV}).", ) args = parser.parse_args() payload = _load_payload(args.payload) if args.team == "blue": registry = load_model_registry(args.model_registry or None) models = validate_blue_submission(payload, model_registry=registry) print(f"OK: blue submission validated ({len(models)} models).") else: catalog = load_stimuli_catalog(args.stimuli_catalog or None) stimuli = validate_red_submission(payload, stimuli_catalog=catalog) print(f"OK: red submission validated ({len(stimuli)} stimuli).") return 0 if __name__ == "__main__": raise SystemExit(main())