from __future__ import annotations import json from pathlib import Path from typing import Any from jsonschema import Draft202012Validator BASE_DIR = Path(__file__).resolve().parent SCHEMA_DIR = BASE_DIR / "schemas" def load_schema(name: str) -> dict[str, Any]: path = SCHEMA_DIR / name with path.open("r", encoding="utf-8") as handle: return json.load(handle) REPORT_SCHEMA = load_schema("report-payload.schema.json") CLAUDE_SCHEMA = load_schema("claude-output.schema.json") REPORT_VALIDATOR = Draft202012Validator(REPORT_SCHEMA) CLAUDE_VALIDATOR = Draft202012Validator(CLAUDE_SCHEMA) def _format_path(path_parts) -> str: path = "$" for part in path_parts: if isinstance(part, int): path += f"[{part}]" else: path += f".{part}" return path def collect_errors(payload: Any, validator: Draft202012Validator) -> list[dict[str, str]]: errors = [] for error in sorted(validator.iter_errors(payload), key=lambda item: list(item.path)): errors.append({ "path": _format_path(error.absolute_path), "message": error.message, }) return errors def validate_report(payload: Any) -> list[dict[str, str]]: return collect_errors(payload, REPORT_VALIDATOR) def validate_claude_output(payload: Any) -> list[dict[str, str]]: return collect_errors(payload, CLAUDE_VALIDATOR)