#!/bin/bash # PreToolUse hook — 動 code 前檢查有沒有對應 SDD # wishlist §2:把 /sdd-check 從「命令要人打」升級成「hook 自動攔」。 # # 掛在 settings.json 的 PreToolUse(matcher: Write|Edit)。 # stdin 收到 JSON:{ tool_name, tool_input: { file_path, ... } } # 行為:動到 code 檔(.ts/.go/...)但 system-dev/docs/3-specs/ 下沒有任何 SDD → 警告(exit 2 擋)。 # # 誠實限制(抄 arcrun):只擋語法層明顯違規(直接寫 code 檔)。 # 藏在 helper 裡、用 bash 繞道的改動擋不到。 # 價值是「想跳過會被抓到 + 留痕可審」,不是技術防偽。絕不聲稱「不可能繞過」。 set -euo pipefail INPUT=$(cat) # 解析 file_path。優先用 jq,沒有 jq 退回 grep(容錯)。 if command -v jq >/dev/null 2>&1; then FILE_PATH=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // empty') else FILE_PATH=$(printf '%s' "$INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"file_path"[[:space:]]*:[[:space:]]*"//;s/"$//') fi # 拿不到路徑 → 不擋(容錯,寧可放過也不誤殺) [ -z "$FILE_PATH" ] && exit 0 # 只管 code 檔。docs/markdown/設定檔等放行。 case "$FILE_PATH" in *.ts|*.tsx|*.js|*.jsx|*.go|*.py|*.rs|*.java|*.rb|*.php|*.c|*.cpp|*.h|*.hpp|*.swift|*.kt) ;; *) exit 0 ;; esac # 改 SDD 自己 / 測試檔 → 放行 case "$FILE_PATH" in *system-dev/docs/3-specs/*) exit 0 ;; *_test.*|*.test.*|*.spec.*|*/tests/*|*/test/*) exit 0 ;; esac # system-dev/docs/3-specs/ 下完全沒有 design.md → 攔 SDD_COUNT=0 if [ -d "system-dev/docs/3-specs" ]; then SDD_COUNT=$(find system-dev/docs/3-specs -name 'design.md' -not -path '*TEMPLATE*' 2>/dev/null | wc -l | tr -d ' ') fi if [ "$SDD_COUNT" -eq 0 ]; then cat >&2 <&2 exit 0