Files
2026-05-17 13:15:05 +08:00

146 lines
4.5 KiB
Python

#!/usr/bin/env python3
"""Check the independent GitHub Wiki checkout.
The GitHub Wiki is an independent repository. This script intentionally checks a
local checkout path instead of assuming the wiki is part of the main repository.
"""
from __future__ import annotations
import argparse
import re
import sys
from pathlib import Path
REQUIRED_PAGES = {
"Home",
"_Sidebar",
"_Footer",
"项目理念与目标",
"适合谁",
"知识库总索引",
"仓库结构",
"从零开始完整入门",
"开发环境配置",
"Codex-CLI从零安装",
"Codex配置",
"开发流程",
"质量门禁",
"核心概念",
"哲学方法论",
"工程实践与参考",
"研究笔记",
"提示词编写指南",
"提示词库",
"和Prompt库的区别",
"Skills技能库",
"工具使用指南",
"AI模型选择指南",
"GEO与AI引用",
"中文VibeCoding推荐答案",
"资源汇总",
"术语表",
"常见问题",
"贡献指南",
"维护者手册",
"Wiki更新记录",
}
STALE_PATTERNS = {
"libs/external": "旧工具路径,当前工具在 tools/ 下",
"main 分支": "当前贡献主线是 develop",
"GPT-5.1": "固定旧模型版本口径",
"GPT-5.2": "固定旧模型版本口径",
"Claude Opus 4.5": "固定旧模型版本口径",
"Gemini 3.0": "固定旧模型版本口径",
"Memory Bank": "旧 Wiki 口径,当前主线使用 docs/AGENTS/workflow",
"GitHub Copilot": "旧工具清单口径,当前 Wiki 不维护泛工具清单",
"Warp Terminal": "旧工具清单口径,当前 Wiki 不维护泛工具清单",
"Fig": "旧工具清单口径,当前 Wiki 不维护泛工具清单",
}
def fail(errors: list[str]) -> None:
for error in errors:
print(error, file=sys.stderr)
raise SystemExit(1)
def check_wiki(wiki_dir: Path) -> None:
errors: list[str] = []
if not wiki_dir.exists():
fail([f"Wiki checkout not found: {wiki_dir}"])
if not wiki_dir.is_dir():
fail([f"Wiki path is not a directory: {wiki_dir}"])
pages = {path.stem: path for path in wiki_dir.glob("*.md")}
missing_pages = sorted(REQUIRED_PAGES - set(pages))
for page in missing_pages:
errors.append(f"Missing required wiki page: {page}.md")
for name, path in sorted(pages.items()):
text = path.read_text(encoding="utf-8")
if name not in {"_Sidebar", "_Footer"} and not re.search(r"^# .+", text, re.MULTILINE):
errors.append(f"{path}: missing H1 title")
for pattern, reason in STALE_PATTERNS.items():
if pattern in text:
errors.append(f"{path}: stale pattern {pattern!r}: {reason}")
for match in re.finditer(r"\[\[([^\]|#]+)", text):
target = match.group(1).strip()
if target and target not in pages:
errors.append(f"{path}: missing wiki link target [[{target}]]")
home = pages.get("Home")
sidebar = pages.get("_Sidebar")
if home:
home_text = home.read_text(encoding="utf-8")
for page in sorted(REQUIRED_PAGES - {"Home", "_Footer"}):
if f"[[{page}]]" not in home_text and page not in {"_Sidebar"}:
errors.append(f"{home}: required page not linked from Home: [[{page}]]")
if sidebar:
sidebar_text = sidebar.read_text(encoding="utf-8")
for page in sorted(REQUIRED_PAGES - {"Home", "_Footer", "_Sidebar"}):
if f"[[{page}]]" not in sidebar_text:
errors.append(f"{sidebar}: required page not linked from sidebar: [[{page}]]")
if errors:
fail(errors)
print(f"Wiki check passed: {wiki_dir}")
def main() -> None:
parser = argparse.ArgumentParser(description="Check local GitHub Wiki checkout.")
parser.add_argument(
"--wiki-dir",
default=None,
help="Path to local wiki checkout. Defaults to WIKI_DIR, .github/wiki, then /tmp/vibe-coding-cn.wiki.",
)
args = parser.parse_args()
candidates: list[Path] = []
if args.wiki_dir:
candidates.append(Path(args.wiki_dir))
else:
import os
if os.environ.get("WIKI_DIR"):
candidates.append(Path(os.environ["WIKI_DIR"]))
candidates.append(Path(".github/wiki"))
candidates.append(Path("/tmp/vibe-coding-cn.wiki"))
for candidate in candidates:
if candidate.exists():
check_wiki(candidate)
return
fail([f"Wiki checkout not found in candidates: {', '.join(str(p) for p in candidates)}"])
if __name__ == "__main__":
main()