From a45b61f326bc0fb689e2523a5f6cd32987991bea Mon Sep 17 00:00:00 2001 From: ogt Date: Wed, 22 Apr 2026 01:23:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(review):=20=E6=96=B0=E5=A2=9E=20/review=20?= =?UTF-8?q?pre-commit=20code=20review=20slash=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - .claude/commands/review.md: 整合 12 Agent 的 pre-commit review 指令 + 依 diff 類型路由:critic / db-expert / migration-engineer / tool-expert + Phase B 條件觸發 vuln-verifier(critic 發現 🔴 時) + ≥10 Python 檔案改派 refactor-specialist 主審 + 最終判決:BLOCKED / CAUTION / APPROVED - scripts/tg_notify.sh: Telegram 告警工具 + 7 個流程節點全部發送告警(啟動/每個 Agent 完成/最終判決) + 支援 info/warn/error 三級別 + jq/bash 雙備案解析 + token 未設定時 exit 0,不阻斷 review 流程 Co-Authored-By: Claude Sonnet 4.6 --- .claude/commands/review.md | 185 +++++++++++++++++++++++++++++++++++++ scripts/tg_notify.sh | 45 +++++++++ 2 files changed, 230 insertions(+) create mode 100644 .claude/commands/review.md create mode 100755 scripts/tg_notify.sh diff --git a/.claude/commands/review.md b/.claude/commands/review.md new file mode 100644 index 0000000..6d7c4fe --- /dev/null +++ b/.claude/commands/review.md @@ -0,0 +1,185 @@ +# /review — Pre-Commit Code Review + +你是 Code Review 協調員。使用者完成需求實作後、commit 前手動執行此指令,請依以下流程完整執行。**禁止跳過任何節點。** + +--- + +## 階段 0:準備與分析 + +執行以下指令: +```bash +git diff --staged --name-only +git diff --staged --stat +git branch --show-current +``` + +若 staged 無任何變更,輸出「⚠️ 無 staged 變更,請先 git add 後再執行 /review」並停止。 + +依變更檔案決定本次審查的 Agent 集合(路由規則見下方)。 + +--- + +## Telegram 節點 0:審查啟動 + +執行: +```bash +bash scripts/tg_notify.sh info "🔍 Code Review 啟動 + +📋 分支:$(git branch --show-current) +📁 Staged 變更: 個檔案 +🤖 派出 Agent:, , ... + +⏳ 審查進行中,請稍候..." +``` + +(將 替換為實際數值) + +--- + +## 階段 1:Agent 路由規則 + +依 staged 檔案清單,決定派出哪些 Agent: + +| 條件 | 觸發 Agent | +|------|-----------| +| 任何 `.py` / `.html` / `.js` 變更 | **critic**(必跑) | +| `migrations/*.sql` 或 `database/` 變更 | **db-expert** | +| `requirements.txt` / `Dockerfile` / `docker-compose.yml` 變更 | **migration-engineer** | +| `.claude/hooks/` / `settings.json` / `.claude/` 變更 | **tool-expert** | +| Python 檔案變更 ≥ 10 個 | 改派 **refactor-specialist**(取代 critic 為主審) | +| critic 報告含任何 🔴 Critical | 追加 **vuln-verifier**(Phase B,序列執行) | + +最多同時跑 4 個獨立 Agent(Phase A),vuln-verifier 為條件觸發的 Phase B。 + +--- + +## 階段 2:Phase A — 平行派出 Agent + +將所有 Phase A Agent **在同一訊息中並行呼叫**(多個 Agent tool call)。 + +每個 Agent 的 prompt 必須包含: +1. 完整的 `git diff --staged` 輸出(或相關部分) +2. 明確的輸出格式要求: + - 問題清單附 `file:line` + - 嚴重度分級:🔴 Critical / 🟠 High / 🟡 Medium / 🟢 Low + - 最後一行輸出 `VERDICT: BLOCKED` 或 `VERDICT: CAUTION` 或 `VERDICT: APPROVED` + +**critic prompt 範本**: +「審查以下 diff,找出安全漏洞、品質問題、反模式。每個問題附 file:line + 嚴重度。最後一行輸出 VERDICT: [BLOCKED/CAUTION/APPROVED]。 +diff 內容:[貼入 git diff --staged 輸出]」 + +**db-expert prompt 範本**: +「審查以下 migration/DB 相關 diff,找出 schema 問題、危險操作、缺失索引、N+1。最後一行輸出 VERDICT: [BLOCKED/CAUTION/APPROVED]。 +diff 內容:[貼入相關 diff]」 + +**migration-engineer prompt 範本**: +「審查以下依賴/Docker 變更,找出破壞性升級、版本衝突、危險設定。最後一行輸出 VERDICT: [BLOCKED/CAUTION/APPROVED]。 +diff 內容:[貼入相關 diff]」 + +**tool-expert prompt 範本**: +「審查以下 hook/settings 變更,確認安全設定未被削弱、hook 邏輯正確。最後一行輸出 VERDICT: [BLOCKED/CAUTION/APPROVED]。 +diff 內容:[貼入相關 diff]」 + +--- + +## 階段 2.5:每個 Agent 完成後立即發 Telegram + +每個 Agent 完成後,**立即**(不等其他 Agent)發送節點通知: + +```bash +bash scripts/tg_notify.sh "[ 完成] + +判決: +問題:🔴 | 🟠 | 🟡 | 🟢 +摘要:<1 句最嚴重問題,若無則「已查,無異狀」>" +``` + +level 對應:BLOCKED → error;CAUTION → warn;APPROVED → info + +--- + +## 階段 3:Phase B — vuln-verifier(條件觸發) + +**只有** critic 報告含 🔴 Critical 才執行此階段。 + +先發 Telegram: +```bash +bash scripts/tg_notify.sh warn "🔬 VULN-VERIFIER 啟動 +觸發原因:critic 發現 個 Critical 問題 +正在驗證漏洞可利用性..." +``` + +派出 vuln-verifier Agent,傳入 critic 完整報告 + 相關 diff,要求輸出: +- 每個 🔴 問題是否為真實可利用漏洞(confirmed / false-positive) +- PoC 描述(若 confirmed) +- 最後一行 `VERDICT: BLOCKED` 或 `VERDICT: APPROVED` + +完成後同樣發節點 Telegram 通知。 + +--- + +## 階段 4:最終判決聚合 + +依以下規則計算最終判決: + +| 判決 | 條件 | +|------|------| +| 🔴 **BLOCKED** | 任一 Agent 輸出 `VERDICT: BLOCKED`,或 vuln-verifier 確認漏洞可利用 | +| 🟡 **CAUTION** | 無 BLOCKED,但有任一 Agent 輸出 `VERDICT: CAUTION` | +| 🟢 **APPROVED** | 所有 Agent 輸出 `VERDICT: APPROVED` | + +--- + +## Telegram 節點 FINAL:最終判決 + +```bash +bash scripts/tg_notify.sh "📊 Code Review 完成 + +最終判決:<🔴 BLOCKED / 🟡 CAUTION / 🟢 APPROVED> +━━━━━━━━━━━━━━━━━━━━ +審查 Agent: +耗時:~ 分鐘 + +<若 BLOCKED 或 CAUTION:> +🔴 必修項目: + • <問題> @ + +<若 APPROVED:> +✅ 可安全 commit" +``` + +level 對應:BLOCKED → error;CAUTION → warn;APPROVED → info + +--- + +## 終端輸出格式 + +最後在 terminal 顯示完整報告: + +``` +## /review 審查報告 +### 變更範圍 +[staged 檔案清單] + +### Agent 判決摘要 +- critic: APPROVED / CAUTION / BLOCKED +- db-expert: APPROVED(若有執行) +- ... + +### 最終判決:🔴 BLOCKED / 🟡 CAUTION / 🟢 APPROVED + +### 必修清單(BLOCKED/CAUTION 時顯示) +- [ ] file:line — 問題描述 + +### 選修建議(APPROVED 時顯示) +- [ ] file:line — 建議描述 +``` + +--- + +## 注意事項 + +- Telegram 發送失敗**不阻斷** review 流程(`tg_notify.sh` 內部已處理) +- Agent prompt 必須包含實際 diff 內容,不可只說「請 review 最近的 diff」 +- 每個 Agent 完成後立即發 Telegram,不等全部完成再批量發送 +- `scripts/tg_notify.sh` 路徑相對於專案根目錄,確認存在後才呼叫 diff --git a/scripts/tg_notify.sh b/scripts/tg_notify.sh new file mode 100755 index 0000000..2c7e3c2 --- /dev/null +++ b/scripts/tg_notify.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# scripts/tg_notify.sh — Code Review Telegram 告警工具 +# 用法:bash scripts/tg_notify.sh "" +set -euo pipefail + +LEVEL="${1:-info}" +MESSAGE="${2:-}" + +TOKEN="${TELEGRAM_BOT_TOKEN:-}" +CHAT_IDS_RAW="${TELEGRAM_CHAT_IDS:-}" + +if [[ -z "$TOKEN" ]]; then + echo "[tg_notify] TELEGRAM_BOT_TOKEN 未設定,跳過通知" >&2 + exit 0 +fi +if [[ -z "$CHAT_IDS_RAW" ]]; then + echo "[tg_notify] TELEGRAM_CHAT_IDS 未設定,跳過通知" >&2 + exit 0 +fi + +case "$LEVEL" in + info) PREFIX="ℹ️" ;; + warn) PREFIX="⚠️" ;; + error) PREFIX="🚨" ;; + *) PREFIX="📌" ;; +esac + +FULL_MSG="${PREFIX} ${MESSAGE}" + +# 解析 CHAT_IDS JSON 陣列 +if command -v jq &>/dev/null; then + CHAT_IDS=$(echo "$CHAT_IDS_RAW" | jq -r '.[]' 2>/dev/null) +else + CHAT_IDS=$(echo "$CHAT_IDS_RAW" | tr -d '[]" ' | tr ',' '\n') +fi + +while IFS= read -r CHAT_ID; do + [[ -z "$CHAT_ID" ]] && continue + curl -s --max-time 10 -X POST \ + "https://api.telegram.org/bot${TOKEN}/sendMessage" \ + -d "chat_id=${CHAT_ID}" \ + --data-urlencode "text=${FULL_MSG}" \ + -d "parse_mode=HTML" > /dev/null || \ + echo "[tg_notify] 發送到 ${CHAT_ID} 失敗(不阻斷流程)" >&2 +done <<< "$CHAT_IDS"