109 行
3.2 KiB
Python
可执行文件
109 行
3.2 KiB
Python
可执行文件
#!/usr/bin/env python3
|
|
"""Validate the lightweight DCL7 document status baseline.
|
|
|
|
DCL7 removed the old full feature matrix from the current docs tree. Historical
|
|
details remain recoverable from git history and issue CSVs. This check now
|
|
guards the current lightweight status docs and the latest issue CSV contract
|
|
shape instead of requiring a large duplicated feature table.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import csv
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
MATRIX_PATH = ROOT / "docs" / "历史功能状态矩阵.md"
|
|
STATE_MATRIX_PATH = ROOT / "docs" / "文档事实源状态矩阵.md"
|
|
INDEX_PATH = ROOT / "docs" / "文档索引.md"
|
|
ISSUES_DIR = ROOT / "issues"
|
|
|
|
REQUIRED_COLUMNS = {
|
|
"ID",
|
|
"Title",
|
|
"Description",
|
|
"Acceptance",
|
|
"Test_Method",
|
|
"Tools",
|
|
"Dev_Status",
|
|
"Review1_Status",
|
|
"Regression_Status",
|
|
"Files",
|
|
"Dependencies",
|
|
"Notes",
|
|
}
|
|
|
|
|
|
def read_text(path: Path) -> str:
|
|
return path.read_text(encoding="utf-8")
|
|
|
|
|
|
def validate_latest_issue_csv() -> list[str]:
|
|
errors: list[str] = []
|
|
csv_files = sorted(ISSUES_DIR.glob("*.csv"))
|
|
if not csv_files:
|
|
return ["No issue CSV files found"]
|
|
|
|
latest = csv_files[-1]
|
|
with latest.open(encoding="utf-8", newline="") as fp:
|
|
reader = csv.DictReader(fp)
|
|
columns = set(reader.fieldnames or [])
|
|
missing = sorted(REQUIRED_COLUMNS - columns)
|
|
if missing:
|
|
errors.append(f"{latest.name} missing columns: {missing}")
|
|
|
|
rows = list(reader)
|
|
if not rows:
|
|
errors.append(f"{latest.name} has no issue rows")
|
|
|
|
for row in rows:
|
|
for key in ("Dev_Status", "Review1_Status", "Regression_Status"):
|
|
value = (row.get(key) or "").strip()
|
|
if value not in {"TODO", "DOING", "DONE"}:
|
|
errors.append(f"{latest.name}:{row.get('ID')} invalid {key}={value!r}")
|
|
|
|
return errors
|
|
|
|
|
|
def main() -> int:
|
|
errors: list[str] = []
|
|
|
|
for path in (MATRIX_PATH, STATE_MATRIX_PATH, INDEX_PATH):
|
|
if not path.exists():
|
|
errors.append(f"Missing required doc: {path.relative_to(ROOT)}")
|
|
|
|
if not errors:
|
|
matrix = read_text(MATRIX_PATH)
|
|
state = read_text(STATE_MATRIX_PATH)
|
|
index = read_text(INDEX_PATH)
|
|
|
|
required_matrix_markers = [
|
|
"历史功能状态矩阵",
|
|
"git show 5da05eb:docs/feature-matrix.md",
|
|
"MIF7",
|
|
"ME6-3",
|
|
]
|
|
for marker in required_matrix_markers:
|
|
if marker not in matrix:
|
|
errors.append(f"{MATRIX_PATH.relative_to(ROOT)} missing marker: {marker}")
|
|
|
|
for marker in ("中文优先", "已从当前树移除", "MIF7", "ME6-3"):
|
|
if marker not in state and marker not in index:
|
|
errors.append(f"status/index docs missing marker: {marker}")
|
|
|
|
errors.extend(validate_latest_issue_csv())
|
|
|
|
if errors:
|
|
print("[ERR] lightweight document status validation failed")
|
|
for err in errors:
|
|
print(f" - {err}")
|
|
return 1
|
|
|
|
print("[OK] lightweight document status baseline is valid")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|