Files
PolyGateway/.claude/scripts/hooks/post-edit-quality.sh
T
iomgaa 0df4d365a5 fix: hook scripts misread ruff success banner as a lint issue
ruff check prints 'All checks passed!' on success, which the non-empty
output test counted as one problem and blocked every commit. Use
--quiet --output-format concise so success is silent and each
diagnostic is exactly one line.
2026-07-20 01:26:23 -04:00

85 lines
2.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# ============================================================
# post-edit-quality.sh
# Claude Code PostToolUse hook — 每次编辑 .py 文件后自动检查
#
# 触发时机: Claude 每次执行 Write/Edit 后
# 作用: 对被修改的文件执行复杂度和风格检查(确定性质量守卫)
# 退出码: 0 = 通过, 非0 = 报告问题(Claude 会看到 stderr 反馈)
#
# 注册: 见 .claude/settings.json → hooks.PostToolUse
# ============================================================
set -euo pipefail
# PolyGateway conda 环境(存在则优先其工具链)
PROJ_ENV="$HOME/miniconda3/envs/PolyGateway/bin"
[[ -d "$PROJ_ENV" ]] && export PATH="$PROJ_ENV:$PATH"
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
# 只检查 .py 文件
if [[ ! "$FILE_PATH" == *.py ]]; then
exit 0
fi
# reference/ 只读区、外部路径不检查(写入本身由 pre-tool-guard 拦截)
case "$FILE_PATH" in
*/reference/*|reference/*) exit 0 ;;
esac
# 只检查存在的文件
if [[ ! -f "$FILE_PATH" ]]; then
exit 0
fi
ERRORS=""
WARNINGS=""
# ── 1. Ruff 格式 + lint 检查 ──
if command -v ruff &> /dev/null; then
# --quiet: 成功时零输出(避免把 "All checks passed!" 误判为问题),失败时只打印诊断行
RUFF_OUTPUT=$(ruff check --quiet --output-format concise "$FILE_PATH" 2>&1 || true)
if [[ -n "$RUFF_OUTPUT" ]]; then
ERRORS+="[ruff] 风格/lint 问题:\n$RUFF_OUTPUT\n\n"
fi
fi
# ── 2. Radon 圈复杂度(只报告 C 级及以下) ──
if command -v radon &> /dev/null; then
RADON_OUTPUT=$(radon cc "$FILE_PATH" -n C -s 2>&1 || true)
if echo "$RADON_OUTPUT" | grep -qE '^\s+[FMC]\s'; then
ERRORS+="[radon] 圈复杂度过高(≥C):\n$RADON_OUTPUT\n\n"
fi
fi
# ── 3. 文件行数检查(warning,不阻塞)──
LINE_COUNT=$(wc -l < "$FILE_PATH")
if [[ "$LINE_COUNT" -gt 200 ]]; then
WARNINGS+="[行数] $FILE_PATH${LINE_COUNT} 行,超过 200 行建议上限。\n\n"
fi
# ── 4. 禁止裸 except ──
if grep -nE '^\s*except\s*:\s*$|^\s*except\s+Exception\s*:\s*pass' "$FILE_PATH" 2>/dev/null; then
ERRORS+="[安全] 检测到裸 except 或 except Exception: pass,请捕获具体异常类型(CLAUDE.md P5)。\n\n"
fi
# ── 5. 禁止硬编码敏感信息 ──
if grep -nEi "(api_key|secret|password|token)\s*=\s*[\"'][^\"']+[\"']" "$FILE_PATH" 2>/dev/null; then
ERRORS+="[安全] 疑似硬编码敏感信息,请使用环境变量或 .env 文件。\n\n"
fi
# ── 输出结果 ──
if [[ -n "$WARNINGS" ]]; then
echo -e "⚠️ Warnings$FILE_PATH,不阻塞):\n" >&2
echo -e "$WARNINGS" >&2
fi
if [[ -n "$ERRORS" ]]; then
echo -e "❌ 代码质量检查发现问题($FILE_PATH):\n" >&2
echo -e "$ERRORS" >&2
exit 1
fi
exit 0