Files
gplan-2/tools/hook_gdd_lint.py
T
2026-09-14 18:18:49 +08:00

53 lines
1.7 KiB
Python

#!/usr/bin/env python3
"""PostToolUse hook: after Write/Edit on a design document, run gdd_lint and
feed failures back to the writing agent. Never crashes; best-effort."""
import json
import re
import subprocess
import sys
from pathlib import Path
try:
payload = json.load(sys.stdin)
except Exception:
sys.exit(0)
path = ""
try:
tool_input = payload.get("tool_input") or {}
path = tool_input.get("file_path") or ""
except Exception:
sys.exit(0)
if not path or not re.search(r"design[\\/].*\.md$", path.replace("\\", "/")):
sys.exit(0)
if re.search(r"review|report|legacy-", Path(path).name, re.I):
sys.exit(0)
# 与 gdd_lint.DEFAULT_EXCLUDE 同源:索引/概念层文档不在门禁默认范围,钩子同样跳过
if Path(path).name in {"game-concept.md", "game-pillars.md", "systems-index.md"}:
sys.exit(0)
# 设计推演件(analysis 两件套的另一半):以散文推演为主,不适用 GDD 格式门禁
norm = path.replace("\\", "/")
if Path(path).name == "analysis.md" or "/analysis/" in norm:
sys.exit(0)
if not Path("tools/gdd_lint.py").exists():
sys.exit(0)
try:
result = subprocess.run(
[sys.executable, "tools/gdd_lint.py", path, "--json"],
capture_output=True, text=True, timeout=30,
)
data = json.loads(result.stdout or "[]")
failures = [r for r in data if r.get("issues")]
if failures:
lines = ["[gdd_lint] 刚写入的文档未过格式门禁,请修复后再结束:"]
for r in failures:
for issue in r.get("issues", []):
lines.append(f" ! {issue}")
print("\n".join(lines), file=sys.stderr)
sys.exit(2)
except Exception:
pass
sys.exit(0)