Ctrl K
ComunidadGuías…

scripts/check-contracts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env python3
"""Check lightweight data-safety contract traceability.

Each contract is listed in docs/architecture.md, named by a production owner
comment with `CONTRACT: SOME_ID`, and covered by at least one `contract_` test
whose name includes the same ID in lower snake case.
"""

from __future__ import annotations

import re
import sys
from pathlib import Path

REPO = Path(__file__).resolve().parents[1]
ARCHITECTURE = REPO / "docs" / "architecture.md"
CONTRACT_RE = re.compile(r"\bCONTRACT:\s+([A-Z][A-Z0-9_]+)\b")
CATALOG_RE = re.compile(r"(?m)^\| `([A-Z][A-Z0-9_]*)` \|")
TEST_RE = re.compile(r"(?m)^\s*(?:async\s+)?fn\s+(contract_[a-zA-Z0-9_]+)\s*\(")
VALID_ID_RE = re.compile(r"^[A-Z][A-Z0-9_]*$")


def rust_files_under(*roots: str) -> list[Path]:
    files: list[Path] = []
    for root in roots:
        root_path = REPO / root
        if root_path.exists():
            files.extend(sorted(root_path.rglob("*.rs")))
    return files


def rel(path: Path) -> str:
    return str(path.relative_to(REPO))


def main() -> int:
    production_files = rust_files_under("src")
    test_files = rust_files_under("src", "tests")
    contract_locations: dict[str, list[str]] = {}
    contract_tests: dict[str, list[str]] = {}
    errors: list[str] = []

    architecture = ARCHITECTURE.read_text(encoding="utf-8")
    catalog_ids = CATALOG_RE.findall(architecture)
    catalog_set = set(catalog_ids)
    if len(catalog_ids) != len(catalog_set):
        errors.append("docs/architecture.md contains duplicate safety contract ids")

    for path in production_files:
        text = path.read_text(encoding="utf-8")
        for match in CONTRACT_RE.finditer(text):
            contract_id = match.group(1)
            if not VALID_ID_RE.match(contract_id):
                errors.append(f"{rel(path)}: invalid CONTRACT id {contract_id!r}")
                continue
            line = text.count("\n", 0, match.start()) + 1
            contract_locations.setdefault(contract_id, []).append(f"{rel(path)}:{line}")

    for path in test_files:
        text = path.read_text(encoding="utf-8")
        for match in TEST_RE.finditer(text):
            test_name = match.group(1)
            for contract_id in contract_locations:
                normalized_id = contract_id.lower()
                if normalized_id in test_name:
                    line = text.count("\n", 0, match.start()) + 1
                    contract_tests.setdefault(contract_id, []).append(f"{rel(path)}:{line}")

    for contract_id in sorted(catalog_set - contract_locations.keys()):
        errors.append(f"{contract_id}: documented contract has no production owner marker")

    for contract_id in sorted(contract_locations.keys() - catalog_set):
        locations = ", ".join(contract_locations[contract_id])
        errors.append(f"{contract_id}: production marker is not documented ({locations})")

    for contract_id, locations in sorted(contract_locations.items()):
        normalized_id = contract_id.lower()
        matched = contract_tests.get(contract_id, [])
        if not matched:
            joined = ", ".join(locations)
            errors.append(
                f"{contract_id}: missing contract_ test name containing "
                f"{normalized_id!r} (marker at {joined})"
            )

    if not catalog_ids:
        errors.append("no safety contracts found in docs/architecture.md")

    if errors:
        print("contract check failed:", file=sys.stderr)
        for error in errors:
            print(f"  - {error}", file=sys.stderr)
        return 1

    print(
        f"contract check passed: {len(catalog_set)} documented contract(s), "
        f"{sum(len(v) for v in contract_tests.values())} matching test(s)"
    )
    return 0


if __name__ == "__main__":
    raise SystemExit(main())