Compare commits

..

1 Commits

Author SHA1 Message Date
claude-code 17c72ec789 閘掛在「收工後」,而 leo 是在「被問到」的當下被打擾——補上那一刻的攔截
leo 2026-08-26:「今天已經好幾次問我,為什麼 hooks 沒有攔下來?」

實查:總管問 leo 走的動作是 AskUserQuestion,而 hooks.json 裡它出現 0 次,
沒有任何 matcher。判準其實早就寫好了——self-drive-police / self-drive-judge
用的就是同一套四題公式——但那兩支只掛在 Stop 與 SubagentStop,
是回合結束後才跑的。問題早就送到他眼前了,事後再反問「你查過了嗎」,
成本已經轉嫁出去。判準對了,時機錯了。

新增 hooks/ask-user-question-guard.sh(PreToolUse / AskUserQuestion):
- 觸發條件是那個動作本身,不是任何句型或關鍵字——全檔零個判擋用的正則,
  換句話說閃不過去,講得謹慎也不會被多罰(leo 2026-08-17 文字層封路的檢驗)
- 進來之後用四題公式的 haiku 判官分「該問 / 不該問」,命中任一題一律放行
- 同一個問題只擋一次(雜湊戳記):判官誤判時重送即過,
  leo 該收到的問題不會因為一支閘而永遠送不到
- 判官掛掉/沒網路/claude 不在 PATH 一律 fail-open,壞掉等於它不存在

順手修掉自己寫出來的一個坑:訊息原本用沒加引號的 heredoc,
反引號被當命令執行,wiki 路徑與豁免指令兩行變成空白(閘照擋,只看離開碼看不出來)。
已收成 mistakes.md 一條,並由 ⑩b 這條測試守著。

實測:
- hooks/tests/ask-user-question-guard.test.sh      14/14(離線,不花錢)
- hooks/tests/ask-user-question-guard.live.test.sh 9/9 連跑三次(真的叫 haiku)
  A 群 5 條真人閘(花錢/不可逆/跨專案結構/品味方向/物理人閘)全部放行,誤攔 0
  B 群 4 條純技術路徑選擇全部擋下
- 既有 7 支測試與改動前逐條對照,結果完全相同(沒有被我弄壞)

順手對帳:docs/hooks-inventory.md 的「43 個檔、53 條註冊」上一版就是錯的,
實際數過是 45/55(本次之後 46/56),plugin.json 與 marketplace.json 一併更正。

【工單】inkstone/InkStoneCo#55
2026-08-26 22:26:51 +08:00
2 changed files with 2 additions and 15 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "isep",
"description": "InkStone Environment Plugin —— leo 的 Claude Code 環境唯一真相源:46 支機械閘(56 條註冊,白話盤點見 docs/hooks-inventory.md)、7 支 slash command、2 支 skill、27 支腳本,外加治理規範與標籤真相源。本機與雲端裝同一份,沒有子集。",
"version": "0.4.0",
"version": "0.3.8",
"keywords": [
"inkstone",
"guardrails",
+1 -14
View File
@@ -29,20 +29,7 @@ case "$GATES" in
GATES="$(ls "$ROOT"/hooks/*.sh 2>/dev/null | grep -cv '\.template\.sh$' | tr -d ' ')" ;;
esac
# 🔴 講清楚「這一份是誰」(leo 2026-08-23 的雲端驗收卡在這裡整整一輪):
# 同一台機器上 ISEP 可能有兩份——marketplace 裝的 plugin 快取,
# 與 repo 裡 vendor 進去的複製本。**兩份都會印這一行**,而版本號一樣時分不出誰在說話。
# 「閘到底從哪一份走」正是決定「另一份能不能拆」的唯一判準
# ⇒ 讓路徑自己講:快取在 plugins/cache/ 底下,vendor 的在 repo 的 .claude/ 底下。
# (查過歷史:本檔只有 daa1674 建立、b1f399f 改閘數兩輪,沒有人試過標示來源,也沒有被否決的方案。
# KBDB 語意搜尋這段開發史:0 命中,該餵。)
case "$ROOT" in
*/plugins/cache/*) SRC="pluginmarketplace 裝的)" ;;
*/.claude/isep*) SRC="vendorrepo 裡的複製本)" ;;
*) SRC="來源不明" ;;
esac
MSG="🟢 ISEP v${VER} 已載入(${GATES} 支閘|來源:${SRC}${ROOT}"
MSG="🟢 ISEP v${VER} 已載入(${GATES} 支閘在 ${ROOT}"
printf '%s\n' "{
\"systemMessage\": \"${MSG}\",