#!/usr/bin/env python3 """Guard ADR numbering under docs/decisions/. Fails when two ADRs share a ``NNNN`` prefix — the exact accident of two ``0006-*`` records landing from separate PRs cut off main at different times. Runs in CI via pre-commit, so a duplicate number can't merge silently. The scan is deliberately loose about *what* counts as an ADR file: it matches any file whose name starts with four digits and a separator (``-`` or ``_``), in any subdirectory and with any extension. A number collision must be caught even if a file is named slightly off-convention (uppercase slug, ``.rst``) or tucked into an archive subfolder — a strict ``NNNN-slug.md`` match would let those slip past and give false confidence. """ import re import sys from pathlib import Path ADR_FILE_RE = re.compile(r"^(\d{4})[-_]") def main() -> int: decisions_dir = Path(__file__).parent.parent / "docs" / "decisions" if not decisions_dir.is_dir(): return 0 seen: dict[str, str] = {} errors: list[str] = [] for path in sorted(decisions_dir.rglob("*")): if not path.is_file(): continue match = ADR_FILE_RE.match(path.name) if not match: continue number = match.group(1) rel = str(path.relative_to(decisions_dir)) if number in seen: errors.append( f"Duplicate ADR number {number}: {rel} collides with " f"{seen[number]}. Renumber one of them." ) else: seen[number] = rel if errors: print("ADR numbering check failed:\n") for err in errors: print(f" - {err}") return 1 return 0 if __name__ == "__main__": sys.exit(main())