#!/usr/bin/env python3 """Generate/check the cross-runtime Outcome & Alliance measurement schema.""" from __future__ import annotations import argparse import json import sys from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] API_ROOT = REPO_ROOT / "apps" / "api" OUTPUT = API_ROOT / "app" / "contracts" / "measurement_contract.v1.json" sys.path.insert(0, str(API_ROOT)) from app.contracts.measurement import ( # noqa: E402 AI_VIEWS, ALLIANCE_CHECKPOINTS, ALLIANCE_DIMENSIONS, INSTRUMENT_KINDS, MEASUREMENT_CONSTRUCTS, MEASUREMENT_PERSPECTIVES, MEASUREMENT_STATUSES, MODEL_RUN_STATUSES, SOURCE_KINDS, SOURCE_PERSPECTIVE_COMPATIBILITY, AllianceAgentAssessment, AllianceScores, BenchmarkCase, MeasurementEvent, MeasurementInstrument, ModelRun, ) def build_contract() -> dict[str, object]: return { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://vignette.local/contracts/measurement_contract.v1.json", "title": "Vignette Outcome & Alliance Measurement Contract", "version": 1, "enums": { "sourceKinds": list(SOURCE_KINDS), "constructs": list(MEASUREMENT_CONSTRUCTS), "perspectives": list(MEASUREMENT_PERSPECTIVES), "measurementStatuses": list(MEASUREMENT_STATUSES), "instrumentKinds": list(INSTRUMENT_KINDS), "aiViews": list(AI_VIEWS), "modelRunStatuses": list(MODEL_RUN_STATUSES), "allianceDimensions": list(ALLIANCE_DIMENSIONS), "allianceCheckpoints": list(ALLIANCE_CHECKPOINTS), }, "sourcePerspectiveCompatibility": { source: sorted(perspectives) for source, perspectives in SOURCE_PERSPECTIVE_COMPATIBILITY.items() }, "$defs": { "MeasurementInstrument": MeasurementInstrument.model_json_schema(), "ModelRun": ModelRun.model_json_schema(), "MeasurementEvent": MeasurementEvent.model_json_schema(), "BenchmarkCase": BenchmarkCase.model_json_schema(), "AllianceScores": AllianceScores.model_json_schema(), "AllianceAgentAssessment": AllianceAgentAssessment.model_json_schema(), }, } def rendered_contract() -> str: return json.dumps(build_contract(), ensure_ascii=False, indent=2, sort_keys=True) + "\n" def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--check", action="store_true") args = parser.parse_args(argv) rendered = rendered_contract() if args.check: current = OUTPUT.read_text(encoding="utf-8") if OUTPUT.exists() else "" if current != rendered: print(f"measurement contract drift: regenerate {OUTPUT}", file=sys.stderr) return 1 print(f"measurement contract OK: {OUTPUT}") return 0 OUTPUT.write_text(rendered, encoding="utf-8") print(OUTPUT) return 0 if __name__ == "__main__": raise SystemExit(main())