#!/usr/bin/env python3 """Local consistency checks for the Spine V1 scaffold. This script does not implement full JSON Schema validation. It validates the spec bundle at the repository-contract level using only the Python stdlib. """ from __future__ import annotations import json import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent SCHEMAS = ROOT / "schemas" REGISTRY = ROOT / "registry" EXAMPLES = ROOT / "examples" / "run_lifecycle" REQUIRED_SCHEMAS = { "OperatorContext": "operator_context.schema.json", "TaskRequest": "task_request.schema.json", "RoutingDecision": "routing_decision.schema.json", "RunRecord": "run_record.schema.json", "ExecutionRequest": "execution_request.schema.json", "ExecutionStatus": "execution_status.schema.json", "RouteTrace": "route_trace.schema.json", "ArtifactManifest": "artifact_manifest.schema.json", "EvalRecord": "eval_record.schema.json", "SpineEvent": "spine_event.schema.json", "SystemManifest": "system_manifest.schema.json", "HarnessManifest": "harness_manifest.schema.json", "AdapterManifest": "adapter_manifest.schema.json", } def load_json(path: Path): with path.open("r", encoding="utf-8") as handle: return json.load(handle) def require(condition: bool, message: str) -> None: if not condition: raise SystemExit(f"VALIDATION FAILED: {message}") def check_schema_inventory() -> None: for schema_name, filename in REQUIRED_SCHEMAS.items(): path = SCHEMAS / filename require(path.exists(), f"missing schema file: {filename}") data = load_json(path) require(data["title"] == schema_name, f"{filename} has unexpected title") def check_registry() -> None: system_manifest = load_json(REGISTRY / "system_manifest.json") require(system_manifest["schema_name"] == "SystemManifest", "system manifest schema name mismatch") require( sorted(system_manifest["schema_inventory"]) == sorted(REQUIRED_SCHEMAS.keys()), "system manifest schema inventory is incomplete", ) harness_ids = set() for path in sorted((REGISTRY / "harnesses").glob("*.json")): data = load_json(path) require(data["schema_name"] == "HarnessManifest", f"{path.name} is not a harness manifest") require(data["harness_id"] not in harness_ids, f"duplicate harness id: {data['harness_id']}") harness_ids.add(data["harness_id"]) adapter_ids = set() for path in sorted((REGISTRY / "adapters").glob("*.json")): data = load_json(path) require(data["schema_name"] == "AdapterManifest", f"{path.name} is not an adapter manifest") require(data["adapter_id"] not in adapter_ids, f"duplicate adapter id: {data['adapter_id']}") adapter_ids.add(data["adapter_id"]) def check_examples() -> None: task = load_json(EXAMPLES / "task_request.json") decision = load_json(EXAMPLES / "routing_decision.json") run = load_json(EXAMPLES / "run_record.json") execution = load_json(EXAMPLES / "execution_request.json") status = load_json(EXAMPLES / "execution_status.json") trace = load_json(EXAMPLES / "route_trace.json") artifact = load_json(EXAMPLES / "artifact_manifest.json") eval_record = load_json(EXAMPLES / "eval_record.json") events = load_json(EXAMPLES / "events.json") require(task["schema_name"] == "TaskRequest", "task example schema mismatch") require(decision["task_id"] == task["task_id"], "decision does not reference task") require(run["task_id"] == task["task_id"], "run does not reference task") require(execution["decision_id"] == decision["decision_id"], "execution does not reference decision") require(execution["run_id"] == run["run_id"], "execution does not reference run") require(status["execution_id"] == execution["execution_id"], "status does not reference execution") require(status["run_id"] == run["run_id"], "status does not reference run") require(trace["execution_id"] == execution["execution_id"], "trace does not reference execution") require(artifact["run_id"] == run["run_id"], "artifact does not reference run") require(eval_record["run_id"] == run["run_id"], "eval does not reference run") require(eval_record["task_id"] == task["task_id"], "eval does not reference task") require(run["decision_ids"] == [decision["decision_id"]], "run decision ids mismatch") require(run["execution_ids"] == [execution["execution_id"]], "run execution ids mismatch") require(run["artifact_ids"] == [artifact["artifact_id"]], "run artifact ids mismatch") require(run["eval_ids"] == [eval_record["eval_id"]], "run eval ids mismatch") sequences = [event["sequence"] for event in events] require(sequences == list(range(1, len(events) + 1)), "event sequence must be contiguous starting at 1") for event in events: require(event["schema_name"] == "SpineEvent", f"event {event['event_id']} schema mismatch") require(event["run_id"] == run["run_id"], f"event {event['event_id']} run id mismatch") event_ids = [event["event_id"] for event in events] require(run["event_ids"] == event_ids, "run event ids do not match event log") def main() -> None: check_schema_inventory() check_registry() check_examples() print("Spine validation OK") print(f"Schemas: {len(REQUIRED_SCHEMAS)}") print(f"Harness manifests: {len(list((REGISTRY / 'harnesses').glob('*.json')))}") print(f"Adapter manifests: {len(list((REGISTRY / 'adapters').glob('*.json')))}") print(f"Example files: {len(list(EXAMPLES.glob('*.json')))}") if __name__ == "__main__": try: main() except SystemExit: raise except Exception as exc: # pragma: no cover - defensive catch for local use raise SystemExit(f"VALIDATION FAILED: unexpected error: {exc}") from exc