chore: bootstrap project scaffolding
Add architecture doc (research-wiki/ARCHITECTURE.md), CLAUDE.md with tiered SOP for Fable 5, adapted .claude skills/hooks/settings, package skeleton (src/polygateway), pyproject with import-linter contracts, Makefile, .env.example and smoke test.
This commit is contained in:
Executable
+81
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# pre-commit-guard.sh
|
||||
# Claude Code PreToolUse hook — 拦截 git commit,执行全量检查
|
||||
#
|
||||
# 触发时机: Claude 尝试执行 git commit 之前
|
||||
# 作用: 阻塞提交直到质量门通过(确定性质量守卫)
|
||||
# 退出码: 0 = 放行, 2 = 阻塞(Claude 必须先修复问题)
|
||||
#
|
||||
# 注册: 见 .claude/settings.json → hooks.PreToolUse (matcher: Bash)
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
# PolyGateway conda 环境(存在则优先其工具链)
|
||||
PROJ_ENV="$HOME/miniconda3/envs/PolyGateway/bin"
|
||||
[[ -d "$PROJ_ENV" ]] && export PATH="$PROJ_ENV:$PATH"
|
||||
|
||||
INPUT=$(cat)
|
||||
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
|
||||
|
||||
# 只拦截 git commit 命令
|
||||
if ! echo "$COMMAND" | grep -qE '(^|\s|&&|;)\s*git\s+commit'; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ERRORS=""
|
||||
WARNINGS=""
|
||||
|
||||
CODE_DIRS=("src")
|
||||
|
||||
for CODE_DIR in "${CODE_DIRS[@]}"; do
|
||||
[[ -d "$CODE_DIR" ]] || continue
|
||||
|
||||
# ── 1. 全量代码质量检查 ──
|
||||
if command -v ruff &> /dev/null; then
|
||||
RUFF_OUTPUT=$(ruff check "$CODE_DIR" 2>&1 || true)
|
||||
if [[ -n "$RUFF_OUTPUT" ]]; then
|
||||
ERROR_COUNT=$(echo "$RUFF_OUTPUT" | wc -l)
|
||||
ERRORS+="[ruff] $CODE_DIR/ 中有 ${ERROR_COUNT} 个问题。运行 ruff check $CODE_DIR/ 查看详情。\n"
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v radon &> /dev/null; then
|
||||
RADON_OUTPUT=$(radon cc "$CODE_DIR" -n C -s 2>&1 || true)
|
||||
if echo "$RADON_OUTPUT" | grep -qE '^\s+[FMC]\s'; then
|
||||
ERRORS+="[radon] 存在圈复杂度 ≥ C 的函数:\n$RADON_OUTPUT\n"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── 2. 文件行数检查 ──
|
||||
while IFS= read -r pyfile; do
|
||||
lines=$(wc -l < "$pyfile")
|
||||
if [[ "$lines" -gt 200 ]]; then
|
||||
WARNINGS+="[行数] $pyfile 有 ${lines} 行,超过 200 行建议上限。\n"
|
||||
fi
|
||||
done < <(find "$CODE_DIR" -name "*.py" 2>/dev/null || true)
|
||||
done
|
||||
|
||||
# ── 3. 测试检查 ──
|
||||
if [[ -d tests ]] && command -v pytest &> /dev/null; then
|
||||
if ! TEST_OUTPUT=$(pytest tests/ --tb=line -q 2>&1); then
|
||||
FAILED=$(echo "$TEST_OUTPUT" | tail -3)
|
||||
ERRORS+="[测试] 有测试未通过:\n$FAILED\n"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── 判定结果 ──
|
||||
if [[ -n "$WARNINGS" ]]; then
|
||||
echo -e "⚠️ Warnings(不阻塞):\n" >&2
|
||||
echo -e "$WARNINGS" >&2
|
||||
fi
|
||||
|
||||
if [[ -n "$ERRORS" ]]; then
|
||||
echo -e "❌ 提交被阻塞 — 请先修复以下问题:\n" >&2
|
||||
echo -e "$ERRORS" >&2
|
||||
echo -e "修复完成后重新执行 git commit。" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "✅ 所有检查通过,允许提交。"
|
||||
exit 0
|
||||
Reference in New Issue
Block a user