cto/tools/check_s91_cto_dotpath.py
2026-05-31 21:44:51 -04:00

56 lines
1.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""Check S91 CTO SOT dotpath migration state."""
from __future__ import annotations
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
REQUIRED_FILES = [
".sot/00-START/CTO-WORKSPACE-INTENT.md",
".sot/03-PROTOCOLS/CTO-CASE-BACKEND-BRIEF.md",
".sot/03-PROTOCOLS/CTO-CASE-PROVIDER-DECISION-RECORD.md",
]
SCAN_FILES = [
"AGENTS.md",
"README.md",
"WORKBOARD.yaml",
"tools/validate_cto_child.py",
]
def fail(message: str) -> None:
raise SystemExit(f"S91 cto dotpath check failed: {message}")
def main() -> int:
if not (ROOT / ".sot").is_dir():
fail("missing canonical .sot directory")
legacy = ROOT / "sot"
if legacy.exists() or legacy.is_symlink():
fail("legacy sot path must be absent after compatibility retirement")
for relative in REQUIRED_FILES:
if not (ROOT / relative).is_file():
fail(f"missing required canonical file: {relative}")
for relative in SCAN_FILES:
text = (ROOT / relative).read_text(encoding="utf-8")
if re.search(r"(?<!\.)sot/", text):
fail(f"legacy sot reference remains in {relative}")
if ".sot/" not in text:
fail(f"missing canonical .sot reference in {relative}")
for path in (ROOT / ".sot").rglob("*.md"):
text = path.read_text(encoding="utf-8")
if re.search(r"source:\s+sot/", text):
fail(f"legacy source frontmatter remains in {path.relative_to(ROOT)}")
print("S91 cto dotpath check passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())