Files
ISEP/system-dev/wiki/mistakes.md
T
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

80 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 已知誤解 / 踩過的坑
> 這是 ISEP 自己的坑,不是 InkStoneCo 的(不轉抄,複製即 fork,fork 即漂移)。
> 撞到新坑就 append 一條;session 開場只推最近幾條標題(見 `hooks/session-start-recall.sh` push 5/5),全文在這裡。
⚠️ MISTAKE: 「環境設定」曾經拆成兩份,各自會漂
症狀: 本機在跑 `InkStoneCo/.claude/`(真身),雲端跑的是 `generate-shell-payload.py`
另外產生塞進 GitHub 私 repo 的一份(薄殼)。`inkstone/InkStoneCo#57` 實測:薄殼比真身
少 7 支閘,其中兩支是前一天才立的;`#14` 更早查到雲端 33 支 guard 一支都沒生效。
正確做法: 只留一份——ISEP 這個 repo 本身就是唯一真相源,本機與雲端裝同一個 plugin。
改動一律只改這裡,然後兩邊各自 `/plugin update`。不要再改
`InkStoneCo/.claude/hooks/`(退場中,早晚會刪)。
原因: 「一份東西兩個副本」在沒有機制強制同步的情況下必然漂移——差異不是誰疏忽,
是結構本身允許漂移發生。
日期: 2026-08-20ISEP `c263866` 建立時就是為了解這個病)
⚠️ MISTAKE: hook 路徑寫死會在雲端斷
症狀: 舊版 hook 若用 `$CLAUDE_PROJECT_DIR/.claude/hooks/...` 或寫死的絕對路徑指向 hook
腳本自己,雲端執行時的 cwd 不是本機那個真身目錄,路徑就對不到、hook 直接失效
(正是上一條「雲端 33 支 guard 一支都沒生效」的根因)。
正確做法: hook 指自己(找到自己在哪、要 source 的其他 hook 檔)一律用官方
`${CLAUDE_PLUGIN_ROOT}`。腳本內部要指**專案裡的檔案**(如 `system-dev/wiki/`
`system-dev/docs/`)才用 `$CLAUDE_PROJECT_DIR`——那些檔案本來就该住在被操作的
那個 repo 裡,跟 hook 自己的路徑是两回事,别混。
原因: 兩種路徑指的是完全不同的東西(「plugin 安裝到哪」vs「正在操作哪個專案」),
混用就是這條坑的直接原因。
日期: 2026-08-20README「路徑規約」段記錄,ISEP 0.1.0 把 51 條 hook 路徑全部改過一輪)
## ⚠️ MISTAKE: 「裝好了」不等於「它在跑」
2026-08-20 實查:ISEP repo 建好、README 寫著 0.1.0、41 支閘都在裡面——
`claude plugin list` 裡**根本沒有 ISEP**。本機仍然在跑 `InkStoneCo/.claude/`
Gitea 上**一個 release tag 都沒有**。
⇒ 「東西做出來了」與「有人在用它」是兩件事,而只有後者算交付。
⇒ 判準:**去執行環境查它有沒有被載入**(`claude plugin list` / `claude plugin details`),
不要從 repo 裡有什麼檔案去推論。
## ⚠️ MISTAKE: 判準寫在閘裡了,但那個閘掛在**做完之後**才跑的時機上
票: `inkstone/InkStoneCo#55`
日期: 2026-08-26
症狀: leo 一天內好幾次被丟純技術路徑選擇,當場問「**今天已經好幾次問我,
為什麼 hooks 沒有攔下來?**」,其中一次他直接說「這種問題不要問我,
我要的是你解決了以後給我 prod」。
實查: 總管問 leo 走的動作是 `AskUserQuestion` 這個工具,而
`hooks.json``AskUserQuestion` 出現 **0 次**——沒有任何 matcher,它是裸的。
判準其實早就寫好了(`self-drive-police.sh` / `self-drive-judge.sh` 用的就是四題公式),
但那兩支只掛在 `Stop``SubagentStop`
原因: **判準對了,時機錯了。** `Stop` 是回合結束後才跑——問題早就送到 leo 眼前、
他早就被打斷了,這時再反問 AI「你查過了嗎」,成本已經轉嫁出去了。
正確做法: 攔截點要長在**那個動作發生的那一刻**(`PreToolUse` / `AskUserQuestion`)。
新增 `hooks/ask-user-question-guard.sh`
🔴 **推廣**:以後看到「規則寫了卻沒被攔下來」,先問的不是「判準對不對」,
而是「**這支閘掛在哪個事件上、那個事件發生時傷害造成了沒有**」。
## ⚠️ MISTAKE: hook 訊息用沒加引號的 heredoc,反引號會被當成命令執行
票: `inkstone/InkStoneCo#55`
日期: 2026-08-26
症狀: `ask-user-question-guard.sh` 擋下之後,stderr 冒出
`line 218: system-dev/wiki/: is a directory`,而訊息裡
「去查 `system-dev/wiki/`」和「`touch /tmp/.ask-ok-<session_id>`」兩行
**變成空白**。閘照擋 exit 2,所以測試若只看離開碼**完全看不出來**。
原因: 寫成 `cat >&2 <<EOF`(heredoc 標記沒加引號)⇒ shell 會對內容做展開,
而本 repo 的 hook 訊息**慣例上大量使用反引號**標路徑與指令
⇒ 每一組反引號都被當成命令替換真的去執行。
正確做法: hook 的訊息一律用 `cat <<'EOF'`(標記加單引號)。
需要塞變數就留 `__PLACEHOLDER__`,事後用 python 換掉——
**不要用 sed**,正體中文加上訊息裡的 `/``&``\` 讓跳脫非常脆。
迴歸測試要**檢查訊息內容**,不能只檢查離開碼
`hooks/tests/ask-user-question-guard.test.sh` 的 ⑩b 就是這一條)。