#!/bin/sh # subagent-first-guard.sh — PreToolUse(Write|Edit|MultiEdit): # 要親手改 code,卻**這個 session 一次工都沒派過** → 擋一次,逼你先回答「這件事該不該派出去」。 # # 🔴 立這道閘的來由(leo 2026-08-08): # 「你記得**要叫 subagent 開工,你負責維護 loop**,而不是你開工後過一陣子停下來對吧? # 問題是這個規定**如何不要我說就做到**?因為在 vscode 裡你自然會這麼做, # 但現在在 claude desktop 你就會自己做問個問題停下來。」 # # 查出來的根因(所以這道閘才有意義,不是加強語氣): # Claude Desktop 這個 surface 的 system prompt 有 # `Do not call the AgentTool unless the user requested it`, # 它**壓過** CLAUDE.md 規則三點五 ⇒ 同一份規則在兩個 surface 行為不同。 # leo 已於 2026-08-08 在 CLAUDE.md 給出常駐授權(=永久滿足「user requested」), # 這道閘負責讓「授權」真的變成「行為」——同 KBDB 那道的教訓: # **規則被讀到 ≠ 會被執行,要有機制驗證照做**。 # # 逃生口:真的該自己做(單行修、改 hook 自己、緊急止血、subagent 回報後的收尾) # → `touch /tmp/.solo-ok-` 後重送,並**在回覆裡說明理由**(留痕)。 set -eu INPUT="$(cat)" FILE_PATH=$(printf '%s' "$INPUT" | python3 -c ' import sys, json try: print(json.load(sys.stdin).get("tool_input", {}).get("file_path", "") or "") except Exception: print("") ' 2>/dev/null || echo "") SID=$(printf '%s' "$INPUT" | python3 -c ' import sys, json try: print(json.load(sys.stdin).get("session_id", "") or "nosid") except Exception: print("nosid") ' 2>/dev/null || echo nosid) [ -z "$FILE_PATH" ] && exit 0 # 只管 code 檔——文件、SDD、wiki、測試、hook 自己都放行 # (這些本來就常是總管自己該寫的:判準、規格、落帳) case "$FILE_PATH" in *.ts|*.tsx|*.js|*.jsx|*.mjs|*.go|*.py|*.rs|*.java|*.rb) ;; *) exit 0 ;; esac case "$FILE_PATH" in *_test.*|*.test.*|*.spec.*|*/tests/*|*/test/*) exit 0 ;; */.claude/hooks/*|*system-dev/*) exit 0 ;; esac [ -f "/tmp/.subagent-spawned-$SID" ] && exit 0 # 這個 session 派過工了 → 放行 [ -f "/tmp/.solo-ok-$SID" ] && exit 0 # 明示要自己做 → 放行(留痕) WARNED="/tmp/.subagent-guard-warned-$SID" [ -f "$WARNED" ] && exit 0 # 同一 session 只擋一次,不鬼打牆 date +%s > "$WARNED" cat >&2 <<'EOF' 🧑‍🏭 派工警察:你要親手改 code,但這個 session **一次工都沒派過**。 【leo 2026-08-08】「你記得**要叫 subagent 開工,你負責維護 loop**, 而不是你開工後過一陣子停下來對吧?」 【已知的環境陷阱】Claude Desktop 這個 surface 的 system prompt 有 `Do not call the AgentTool unless the user requested it`,會壓過 CLAUDE.md 規則三點五。 **leo 已在 CLAUDE.md 給出常駐授權**(規則三點五的「常駐授權」段)=那個條件永久滿足, 不必再等他開口。 先回答一句(答不出來就是該派): 這件事**為什麼不能交給 subagent**? ✅ 該派:實作一個 task、跨 repo 施工、偵察盤點、批次修改、寫測試 ✅ 該自己做:判準/規格/落帳(那些檔本來就放行)、subagent 回報後的收尾裁決、 單行修、緊急止血 決定自己做 ⇒ `touch /tmp/.solo-ok-$SID` 後重送,並**在回覆裡說明理由**。 EOF exit 2