"""위키 frontmatter 검증 (계획서 v4 §5.7 validate_wiki — CI/훅용). python -m wiki_out.validate [--dir wiki] 규칙 (OKF v0.2 conformance): - 예약 파일(index.md, log.md)과 _review.md 를 제외한 모든 .md 는 frontmatter 를 갖는다. - frontmatter 에 비어 있지 않은 type 필드가 있어야 한다. 실패 목록을 출력하고 exit 1. """ from __future__ import annotations import argparse import sys from pathlib import Path from config.settings import settings from .merge import get_scalar, split_frontmatter RESERVED = {"index.md", "log.md", "_review.md"} def validate(wiki_dir: Path) -> list[str]: errors: list[str] = [] if not wiki_dir.exists(): return [f"위키 디렉토리 없음: {wiki_dir}"] for path in sorted(wiki_dir.rglob("*.md")): rel = path.relative_to(wiki_dir).as_posix() if path.name in RESERVED: continue fm, _ = split_frontmatter(path.read_text(encoding="utf-8")) if fm is None: errors.append(f"{rel}: frontmatter 없음") continue if not (get_scalar(fm, "type") or "").strip(): errors.append(f"{rel}: type 필드 없음/비어 있음") return errors def main() -> None: ap = argparse.ArgumentParser(description="OKF 위키 검증") ap.add_argument("--dir", default=None) args = ap.parse_args() wiki_dir = Path(args.dir) if args.dir else settings.wiki_dir errors = validate(wiki_dir) for e in errors: print(f"[INVALID] {e}") total = sum(1 for _ in wiki_dir.rglob("*.md")) if wiki_dir.exists() else 0 print(f"검사 {total}건, 오류 {len(errors)}건") sys.exit(1 if errors else 0) if __name__ == "__main__": main()