Files
wehub-resource-sync f3d80b4628
Auto Release / auto-release (push) Failing after 1s
CI / lint (push) Failing after 0s
CI / screenshot-quality (push) Failing after 3s
CI / pr-policy (push) Has been skipped
CI / test (3.11) (push) Failing after 0s
CI / test (3.12) (push) Failing after 0s
CI / test (3.13) (push) Failing after 3s
CI / coverage (push) Failing after 1s
Legibility / legibility (push) Failing after 3s
chore: import upstream snapshot with attribution
2026-07-13 12:31:48 +08:00

298 lines
9.7 KiB
Python

#!/usr/bin/env python3
"""Deterministic legibility checks for maintainer standards, plans, and architecture manifest."""
from __future__ import annotations
import argparse
import datetime as dt
import re
import sys
from dataclasses import dataclass
from pathlib import Path
ISO_DATE_RE = re.compile(r"^\d{4}-\d{2}-\d{2}$")
REQUIRED_STANDARDS_KEYS = ("owner", "last_reviewed", "source_of_truth")
ALLOWED_PLAN_STATUS = {"active", "completed", "cancelled"}
AGENT_DOCS_DIR = Path(".agents") / "docs"
STANDARDS_DIR = AGENT_DOCS_DIR / "standards"
PLANS_DIR = AGENT_DOCS_DIR / "plans"
ARCHITECTURE_MANIFEST = AGENT_DOCS_DIR / "architecture" / "manifest.yaml"
PUBLIC_DOCS_DIR = Path("docs")
README_DOC_PAIRS = ((Path("README.md"), Path("README_zh.md")),)
@dataclass
class CheckResult:
failures: list[str]
warnings: list[str]
def parse_frontmatter(markdown_text: str) -> dict[str, str]:
lines = markdown_text.splitlines()
if len(lines) < 3 or lines[0].strip() != "---":
return {}
frontmatter_lines: list[str] = []
for line in lines[1:]:
if line.strip() == "---":
break
frontmatter_lines.append(line)
else:
return {}
fields: dict[str, str] = {}
for line in frontmatter_lines:
if ":" not in line:
continue
key, value = line.split(":", 1)
fields[key.strip()] = value.strip()
return fields
def parse_expected_paths(manifest_text: str) -> list[str]:
lines = manifest_text.splitlines()
in_expected_paths = False
expected_paths: list[str] = []
for line in lines:
stripped = line.strip()
if not stripped or stripped.startswith("#"):
continue
if stripped == "expected_paths:":
in_expected_paths = True
continue
if in_expected_paths:
if not stripped.startswith("- "):
break
value = stripped[2:].strip().strip("'\"")
if value:
expected_paths.append(value)
return expected_paths
def parse_iso_date(date_str: str) -> dt.date | None:
if not ISO_DATE_RE.match(date_str):
return None
try:
return dt.date.fromisoformat(date_str)
except ValueError:
return None
def _is_within_repo_root(repo_root: Path, candidate_path: Path) -> bool:
try:
candidate_path.relative_to(repo_root)
return True
except ValueError:
return False
def _strip_fenced_code_blocks(markdown_text: str) -> str:
kept_lines: list[str] = []
in_fence = False
fence_char = ""
fence_len = 0
for line in markdown_text.splitlines():
stripped = line.lstrip()
if not in_fence and (stripped.startswith("```") or stripped.startswith("~~~")):
in_fence = True
fence_char = stripped[0]
fence_len = len(stripped) - len(stripped.lstrip(fence_char))
continue
if in_fence:
if stripped.startswith(fence_char * fence_len):
in_fence = False
continue
kept_lines.append(line)
return "\n".join(kept_lines)
def check_standards_freshness(
repo_root: Path, *, freshness_days: int, strict_freshness: bool, today: dt.date
) -> CheckResult:
failures: list[str] = []
warnings: list[str] = []
standards_dir = repo_root / STANDARDS_DIR
for file_path in sorted(standards_dir.glob("*.md")):
frontmatter = parse_frontmatter(file_path.read_text(encoding="utf-8"))
for key in REQUIRED_STANDARDS_KEYS:
if not frontmatter.get(key):
failures.append(f"{file_path}: missing frontmatter key '{key}'")
last_reviewed_raw = frontmatter.get("last_reviewed")
if not last_reviewed_raw:
continue
reviewed_date = parse_iso_date(last_reviewed_raw)
if reviewed_date is None:
failures.append(f"{file_path}: last_reviewed must be ISO date YYYY-MM-DD")
continue
age_days = (today - reviewed_date).days
if age_days > freshness_days:
msg = (
f"{file_path}: last_reviewed {last_reviewed_raw} is stale "
f"({age_days} days old, threshold={freshness_days})"
)
if strict_freshness:
failures.append(msg)
else:
warnings.append(msg)
return CheckResult(failures=failures, warnings=warnings)
def check_architecture_manifest(repo_root: Path) -> CheckResult:
failures: list[str] = []
resolved_repo_root = repo_root.resolve()
manifest_path = repo_root / ARCHITECTURE_MANIFEST
if not manifest_path.exists():
return CheckResult(failures=[f"{manifest_path}: missing manifest file"], warnings=[])
expected_paths = parse_expected_paths(manifest_path.read_text(encoding="utf-8"))
if not expected_paths:
failures.append(f"{manifest_path}: expected_paths list is empty or missing")
return CheckResult(failures=failures, warnings=[])
for relative_path in expected_paths:
candidate_path = Path(relative_path)
if candidate_path.is_absolute():
failures.append(f"{manifest_path}: expected path must be relative: {relative_path}")
continue
absolute_path = (repo_root / candidate_path).resolve()
if not _is_within_repo_root(resolved_repo_root, absolute_path):
failures.append(f"{manifest_path}: expected path resolves outside repo root: {relative_path}")
continue
if not absolute_path.exists():
failures.append(f"{manifest_path}: expected path missing: {relative_path}")
return CheckResult(failures=failures, warnings=[])
def check_plan_state_drift(repo_root: Path) -> CheckResult:
failures: list[str] = []
plans_dir = repo_root / PLANS_DIR
for file_path in sorted(plans_dir.glob("**/*.md")):
text = file_path.read_text(encoding="utf-8")
frontmatter = parse_frontmatter(text)
status = frontmatter.get("status")
if status not in ALLOWED_PLAN_STATUS:
failures.append(f"{file_path}: status must be one of {sorted(ALLOWED_PLAN_STATUS)}")
continue
if status == "completed" and "- [ ]" in _strip_fenced_code_blocks(text):
failures.append(f"{file_path}: completed plan still contains unchecked TODO checkboxes")
return CheckResult(failures=failures, warnings=[])
def _public_doc_counterpart(path: Path) -> Path:
if path.name.endswith(".zh.md"):
return path.with_name(f"{path.name.removesuffix('.zh.md')}.md")
return path.with_name(f"{path.stem}.zh.md")
def check_public_docs_bilingual(repo_root: Path) -> CheckResult:
failures: list[str] = []
for english_path, chinese_path in README_DOC_PAIRS:
absolute_english = repo_root / english_path
absolute_chinese = repo_root / chinese_path
if absolute_english.exists() and not absolute_chinese.exists():
failures.append(f"{absolute_english}: missing Simplified Chinese counterpart: {chinese_path}")
if absolute_chinese.exists() and not absolute_english.exists():
failures.append(f"{absolute_chinese}: missing English counterpart: {english_path}")
public_docs_dir = repo_root / PUBLIC_DOCS_DIR
if not public_docs_dir.exists():
return CheckResult(failures=failures, warnings=[])
for file_path in sorted(public_docs_dir.glob("**/*.md")):
counterpart = _public_doc_counterpart(file_path)
if not counterpart.exists():
counterpart_relative = counterpart.relative_to(repo_root)
if file_path.name.endswith(".zh.md"):
failures.append(f"{file_path}: missing English counterpart: {counterpart_relative}")
else:
failures.append(f"{file_path}: missing Simplified Chinese counterpart: {counterpart_relative}")
return CheckResult(failures=failures, warnings=[])
def run_checks(repo_root: Path, *, freshness_days: int, strict_freshness: bool, today: dt.date) -> CheckResult:
failures: list[str] = []
warnings: list[str] = []
for result in (
check_standards_freshness(
repo_root,
freshness_days=freshness_days,
strict_freshness=strict_freshness,
today=today,
),
check_architecture_manifest(repo_root),
check_plan_state_drift(repo_root),
check_public_docs_bilingual(repo_root),
):
failures.extend(result.failures)
warnings.extend(result.warnings)
return CheckResult(failures=failures, warnings=warnings)
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--repo-root", type=Path, default=Path.cwd(), help="Repository root path (default: current dir)"
)
parser.add_argument(
"--freshness-days",
type=int,
default=60,
help="Warn when standards last_reviewed is older than this many days (default: 60)",
)
parser.add_argument(
"--strict-freshness",
action="store_true",
help="Promote stale standards freshness warnings to failures",
)
return parser
def main(argv: list[str] | None = None) -> int:
args = build_parser().parse_args(argv)
result = run_checks(
args.repo_root,
freshness_days=args.freshness_days,
strict_freshness=args.strict_freshness,
today=dt.date.today(),
)
for warning in result.warnings:
print(f"WARNING: {warning}")
for failure in result.failures:
print(f"ERROR: {failure}")
if result.warnings:
print(f"Legibility check warnings: {len(result.warnings)}")
if result.failures:
print(f"Legibility check failures: {len(result.failures)}")
return 1
print("Legibility checks passed")
return 0
if __name__ == "__main__":
sys.exit(main())