#!/usr/bin/env python3 from __future__ import annotations import argparse import re from pathlib import Path import yaml ROOT = Path(__file__).resolve().parents[1] def _extract_refs(text: str) -> set[str]: refs: set[str] = set() for match in re.finditer(r"(?P(?:spec|tools|prompts|governance)/[A-Za-z0-9_./-]+\.(?:yaml|md|py|json))", text): refs.add(match.group("path")) return refs def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("--index", default="governance/adr_index.yaml") args = ap.parse_args() index = yaml.safe_load((ROOT / args.index).read_text(encoding="utf-8")) entries = index.get("entries") if isinstance(index, dict) else [] errors: list[str] = [] for entry in entries: if not isinstance(entry, dict): continue path = ROOT / str(entry.get("path") or "") if not path.exists(): errors.append(f"missing adr: {path}") continue text = path.read_text(encoding="utf-8") refs = _extract_refs(text) if not refs: errors.append(f"no spec/tool refs in adr: {path}") if "## Context" not in text or "## Decision" not in text or "## Rollback" not in text: errors.append(f"adr sections incomplete: {path}") print("ADR_SPEC_LINKS_OK" if not errors else "ADR_SPEC_LINKS_FAIL") for err in errors[:20]: print(err) return 0 if not errors else 1 if __name__ == "__main__": raise SystemExit(main())