Imports the v0.9.2 documentation baseline and the bootstrap files required by docs/governance/repository-bootstrap-plan.md v0.1.0 §3, minus the justfile (added in the next commit). This commit establishes the git history for the project. All previous work lived only as filesystem state with no version control.
91 lines
2.8 KiB
Python
91 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
DOCS = ROOT / "docs"
|
|
|
|
ID_FILES = {
|
|
"SysRS": DOCS / "requirements" / "sysrs.md",
|
|
"SysDes": DOCS / "architecture" / "sysdes.md",
|
|
"SRS": DOCS / "requirements" / "srs.md",
|
|
"SAD": DOCS / "architecture" / "sad.md",
|
|
"SDD": DOCS / "architecture" / "sdd.md",
|
|
}
|
|
|
|
def read(path: Path) -> str:
|
|
if not path.exists():
|
|
return ""
|
|
return path.read_text(encoding="utf-8")
|
|
|
|
def defined_ids(prefix: str, text: str) -> set[str]:
|
|
return set(re.findall(rf"\*\*({prefix}-\d{{3}})\*\*:", text))
|
|
|
|
def all_refs(prefix: str, text: str) -> set[str]:
|
|
return set(re.findall(rf"{prefix}-\d{{3}}", text))
|
|
|
|
def main() -> int:
|
|
if not DOCS.exists():
|
|
print("docs/ does not exist; skipping documentation validation.")
|
|
return 0
|
|
|
|
all_text = "\n".join(p.read_text(encoding="utf-8") for p in DOCS.rglob("*.md"))
|
|
|
|
defined = {
|
|
prefix: defined_ids(prefix, read(path))
|
|
for prefix, path in ID_FILES.items()
|
|
}
|
|
|
|
failed = False
|
|
|
|
for prefix, ids in defined.items():
|
|
refs = all_refs(prefix, all_text)
|
|
undefined = sorted(refs - ids)
|
|
if undefined:
|
|
failed = True
|
|
print(f"[FAIL] Undefined {prefix} references: {', '.join(undefined)}")
|
|
else:
|
|
print(f"[OK] {prefix}: {len(ids)} defined, 0 undefined references")
|
|
|
|
srs = read(DOCS / "requirements" / "srs.md")
|
|
sad = read(DOCS / "architecture" / "sad.md")
|
|
sdd = read(DOCS / "architecture" / "sdd.md")
|
|
|
|
checks = [
|
|
("SRS direct SysRS references", re.findall(r"SysRS-\d{3}", srs)),
|
|
("SAD direct SysRS references", re.findall(r"SysRS-\d{3}", sad)),
|
|
("SAD direct SysDes references", re.findall(r"SysDes-\d{3}", sad)),
|
|
("SDD direct SysRS references", re.findall(r"SysRS-\d{3}", sdd)),
|
|
("SDD direct SysDes references", re.findall(r"SysDes-\d{3}", sdd)),
|
|
("SDD direct SRS references", re.findall(r"SRS-\d{3}", sdd)),
|
|
]
|
|
|
|
for name, matches in checks:
|
|
if matches:
|
|
failed = True
|
|
print(f"[FAIL] {name}: {len(matches)}")
|
|
else:
|
|
print(f"[OK] {name}: 0")
|
|
|
|
old_names = re.findall(r"CHANORA_[A-Za-z0-9_]+_v\d+\.\d+(?:\.\d+)?\.md", all_text)
|
|
if old_names:
|
|
failed = True
|
|
print(f"[FAIL] Old package-style filenames found: {len(set(old_names))}")
|
|
else:
|
|
print("[OK] No old package-style filenames found")
|
|
|
|
cjk = re.findall(r"[\u4e00-\u9fff]", all_text)
|
|
if cjk:
|
|
failed = True
|
|
print(f"[FAIL] CJK characters found: {len(cjk)}")
|
|
else:
|
|
print("[OK] English-only CJK check passed")
|
|
|
|
return 1 if failed else 0
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|