From 8ede74e9e2253fd7a98934650b8dba71bf8f2ff6 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Thu, 27 Aug 2026 09:15:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(comment-scope):=20=E6=96=B0=E5=A2=9E=20swe?= =?UTF-8?q?ep=20=E6=A8=A1=E5=BC=8F=EF=BC=8C=E6=8E=83=E6=95=B4=E5=80=8B=20g?= =?UTF-8?q?it=20=E5=B7=A5=E4=BD=9C=E5=8D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What:`hooks/comment-scope.sh` 由兩種模式變三種,新增 `sweep [dir]`:掃整個 git 工作區這次改過的所有檔案,命中就把報告與最多三行證據送到 stderr 並 exit 2,找不到 git 就安靜 exit 0。`prompt` 與無參數單檔掃描兩個模式的判定邏輯一行不動。 Why:只有 claude 有 PostToolUse,拿得到「剛剛寫了哪個檔」。codex、copilot、antigravity、kiro 四個 CLI 都沒有 post-tool 事件,註解範圍檢查在那邊只剩規則提示,違規註解寫進去了不會有人叫。改掃整個工作區的 git diff,時機晚一點,涵蓋範圍一樣。 How:單檔判定抽成 `scan_file()`,兩種掃描模式共用同一份禁止樣式與白名單,不會各自漂移。`sweep` 以 `git rev-parse --show-toplevel` 找庫根,所以在子目錄跑也掃得到整個庫;逐檔報告累積在暫存檔再一次輸出,因為迴圈跑在管線的子行程裡,變數帶不回本 shell。 Who:`jsc-hooks` 的 hook 實作層,供 `tools/wire-cli.sh` 接線給 codex、copilot、antigravity、kiro 四個 CLI 使用。 --- hooks/comment-scope.sh | 166 ++++++++++++++++++++++++++--------------- 1 file changed, 106 insertions(+), 60 deletions(-) diff --git a/hooks/comment-scope.sh b/hooks/comment-scope.sh index 061b16c..d00d749 100755 --- a/hooks/comment-scope.sh +++ b/hooks/comment-scope.sh @@ -4,8 +4,13 @@ # 專案代號、客戶名稱這類無法用樣式判定的,交給 jsc-review:code-review 第 2 組人工審查。 # # 用法: -# comment-scope.sh prompt # UserPromptSubmit:注入規則摘要 -# comment-scope.sh # PostToolUse:掃描剛寫入的檔案,命中就發警告 +# comment-scope.sh prompt 注入規則摘要(UserPromptSubmit 或規則檔取文字用) +# comment-scope.sh 掃描剛寫入的單一檔案(PostToolUse) +# comment-scope.sh sweep [dir] 掃描整個工作區這次改過的所有檔案(沒有 post-tool hook 的 CLI 用) +# +# 為什麼要有 sweep:只有 claude 接得到 PostToolUse,逐檔精準掃得到。codex 只有每輪結束的 +# notify、kiro 只有 userPromptSubmit、copilot 與 antigravity 只有包裝別名,這四個都拿不到 +# 「剛剛寫了哪個檔」,只能改成掃整個工作區的 git diff。時機晚一點,涵蓋範圍一樣。 # # 輸入相容: # Claude: PostToolUse 的 stdin JSON,取 tool_input.file_path。 @@ -13,7 +18,7 @@ # 兩者都取不到就安靜降級(exit 0)。 # # 掃描範圍:檔案在 git 工作區內就只掃 `git diff HEAD` 的新增行,不翻舊帳; -# 不在 git 內或檔案尚未追蹤才整檔掃描。 +# 不在 git 內或檔案尚未追蹤才整檔掃描。sweep 一律只看 git diff。 # # 結束碼:0=沒命中或資料不足;2=命中,訊息走 stderr 交回模型自行修正(不擋寫入,檔案已經寫好了)。 # 逃生門:JSC_COMMENT_SCOPE=off。 @@ -29,43 +34,6 @@ if [ "${1:-}" = "prompt" ]; then exit 0 fi -read_stdin 2>/dev/null || STDIN_JSON="" -file=$(json_str file_path 2>/dev/null || true) -[ -n "$file" ] || file="${JSC_CHANGED_FILE:-}" -[ -n "$file" ] && [ -f "$file" ] || exit 0 - -# 非程式碼檔不受本規則限制:markdown、純文字、資料檔沒有「程式碼註解」。 -case "$file" in - *.md|*.markdown|*.txt|*.rst|*.json|*.csv|*.tsv|*.svg|*.lock|*.log|*COMMIT_EDITMSG) exit 0 ;; -esac -# 二進位檔跳過。只認 NUL 位元組——拿「非可列印字元」當判準會把所有含中文的檔案誤判成二進位。 -raw=$(head -c 1024 "$file" 2>/dev/null | wc -c) -txt=$(head -c 1024 "$file" 2>/dev/null | LC_ALL=C tr -d '\000' | wc -c) -[ "$raw" = "$txt" ] || exit 0 - -dir=$(dirname -- "$file") -if git -C "$dir" rev-parse --is-inside-work-tree >/dev/null 2>&1 && - git -C "$dir" ls-files --error-unmatch -- "$file" >/dev/null 2>&1; then - lines=$(git -C "$dir" diff HEAD -- "$file" 2>/dev/null | sed -n 's/^+[^+]/&/p' | cut -c2-) - [ -n "$lines" ] || exit 0 -else - lines=$(cat "$file" 2>/dev/null) -fi - -# 只留註解行:行首註解符號,或行中出現 // 與 # 的行尾註解。 -comments=$(printf '%s\n' "$lines" | grep -E '^[[:space:]]*(//|#|--|\*|/\*|