from __future__ import annotations import re from pathlib import Path from typing import Any import yaml ROOT = Path(__file__).resolve().parent.parent CAPABILITIES_DIR = ROOT / "registry" / "capabilities" INDEX_PATH = ROOT / "registry" / "indexes" / "capabilities.yaml" SCHEMA_PATH = ROOT / "schemas" / "capability.schema.yaml" LEVEL_ORDERS = { "discovery": ["D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7"], "availability": ["A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7"], "completeness": ["C0", "C1", "C2", "C3", "C4", "C5", "C6"], "reliability": ["R0", "R1", "R2", "R3", "R4", "R5", "R6"], } def load_schema() -> dict[str, Any]: with SCHEMA_PATH.open(encoding="utf-8") as handle: return yaml.safe_load(handle) def parse_front_matter(path: Path) -> dict[str, Any]: text = path.read_text(encoding="utf-8") match = re.match(r"^---\n(.*?)\n---", text, re.DOTALL) if not match: raise ValueError(f"{path}: missing YAML front matter") data = yaml.safe_load(match.group(1)) if not isinstance(data, dict): raise ValueError(f"{path}: front matter must be a mapping") return data def capability_paths(target: Path | None = None) -> list[Path]: if target is not None: return [target] return sorted(CAPABILITIES_DIR.glob("*.md")) def load_index() -> dict[str, Any]: with INDEX_PATH.open(encoding="utf-8") as handle: return yaml.safe_load(handle) def parse_vector(vector: str) -> dict[str, str]: parts = [part.strip() for part in vector.split("/")] if len(parts) != 4: raise ValueError(f"invalid vector: {vector}") return { "discovery": parts[0], "availability": parts[1], "completeness": parts[2], "reliability": parts[3], } def level_at_least(dimension: str, current: str, minimum: str) -> bool: order = LEVEL_ORDERS[dimension] return order.index(current) >= order.index(minimum) def registry_paths(repo_root: Path) -> dict[str, Path]: registry = repo_root / "registry" return { "registry": registry, "capabilities": registry / "capabilities", "index": registry / "indexes" / "capabilities.yaml", "sources": registry / "federation" / "sources.yaml", } def load_index_at(path: Path) -> dict[str, Any]: with path.open(encoding="utf-8") as handle: return yaml.safe_load(handle) def entry_vector(front_matter: dict[str, Any]) -> str: discovery = front_matter["maturity"]["discovery"]["current"] availability = front_matter["maturity"]["availability"]["current"] completeness = front_matter["external_evidence"]["completeness"]["level"] reliability = front_matter["external_evidence"]["reliability"]["level"] return f"{discovery} / {availability} / {completeness} / {reliability}" def vectors_match(index_vector: str, front_matter: dict[str, Any]) -> bool: return index_vector.replace(" ", "") == entry_vector(front_matter).replace(" ", "")