mirror of
https://github.com/tradecatlabs/vibe-coding-cn.git
synced 2026-07-27 18:57:50 +00:00
146 lines
4.5 KiB
Python
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()
|