閘掛在「收工後」,而 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,壞掉等於它不存在 版本 0.3.9 → 0.4.0。這不是儀式,是傳輸機制本身:產物按版本號分資料夾 (~/.claude/plugins/cache/inkstone/isep/<版本>/),版本沒動就不會長出新資料夾, 這支閘一個 session 都載入不到。docs/TESTING.md 開頭那段講的就是這件事, 而第一版我漏了——總管複驗時量出來的。 假設(沒有前例可循,先裁再記):跳 0.4.0 而不是 0.3.10。理由是這一版第一次 掛上 AskUserQuestion 這個事件面,是新能力不是修補;而且 0.3.10 在 plugin 快取目錄的 ls 裡會排到 0.3.1 旁邊,肉眼不好認。錯了打回,改號很便宜。 順手修掉自己寫出來的一個坑:訊息原本用沒加引號的 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 支測試與改動前逐條對照,結果完全相同(沒有被我弄壞) 順手對帳:plugin.json 與 marketplace.json 的描述寫「43 支機械閘、53 條註冊」, 實際數過是 46/56(含本次新增這支)。docs/hooks-inventory.md 一併更正。 【工單】inkstone/InkStoneCo#55
This commit is contained in:
@@ -60,6 +60,30 @@ python3 scripts/ticket where 標籤 模組化
|
||||
ISEP 的叫 `origin`,於是這道閘在新 repo 等於不存在)
|
||||
- 結果只有單一 repo ⇒ 搜尋沒有跨 repo,等於沒搜
|
||||
|
||||
### A9 — 人閘警察的管路:該擋的擋、壞掉不會卡住 session
|
||||
```
|
||||
bash hooks/tests/ask-user-question-guard.test.sh
|
||||
```
|
||||
**該看到**:`14/14 通過`。**不打網路、不花錢**(判官用替身)。
|
||||
**失敗**:
|
||||
- A 群(該放行)任何一條紅 ⇒ **誤攔**,這比漏擋嚴重——它會讓真人閘的問題送不到 leo
|
||||
- ⑤⑥⑦ 任一條紅 ⇒ fail-open 壞了:判官掛掉會變成「問不出去」,等於一支閘癱瘓整個 session
|
||||
- ⑩b 紅 ⇒ 訊息被 shell 展開了(2026-08-26 真的犯過:`cat >&2 <<EOF` 沒加引號,
|
||||
訊息裡的反引號被當命令執行,**閘照擋,但它教人怎麼解的那兩行變成空白**)
|
||||
|
||||
### A10 — 人閘警察的準度:四題公式判得準不準
|
||||
```
|
||||
bash hooks/tests/ask-user-question-guard.live.test.sh
|
||||
```
|
||||
🔴 **這支真的會叫 haiku**(9 題、每題一次呼叫,整支約 2 分鐘)。
|
||||
**該看到**:`9/9 通過`,且結尾的「A 群誤攔」計數是 **0**。
|
||||
**失敗**:
|
||||
- **A 群紅(誤攔真人閘)=最嚴重**:等於讓總管替 leo 決定他的品味。看到就停下來改判準,不要放著
|
||||
- B 群紅 = 漏擋,判官把純技術題當成人閘。改 `ask-user-question-guard.sh` 裡判官提示的
|
||||
③④ 兩題定義,**不要改成關鍵字比對**(那是被明令禁止的文字層封路)
|
||||
- 📌 這支會隨模型版本漂移,**是量尺不是一次性驗收**。改完判準要連跑三次都全綠才算數
|
||||
(2026-08-26 實測:第一版判準連兩次都在同一題漏擋,收緊 ③④ 定義後三次全綠)
|
||||
|
||||
### A6 — 標籤對齊且冪等
|
||||
```
|
||||
bash scripts/gitea-labels-sync.sh
|
||||
@@ -196,6 +220,8 @@ B2(信標那行)/B3(setup 輸出)/B4(閘的訊息)三個畫面
|
||||
| A4 開票側門閘 | 總管 | ✅ 13/13 |
|
||||
| A5 搜尋跨 repo | 總管 | ✅ |
|
||||
| A6 標籤對齊+冪等 | 總管 | ✅ 14 repo,第二次 0/0 |
|
||||
| **A9 人閘警察管路** | 總管 | ✅ 14/14(2026-08-26) |
|
||||
| **A10 人閘警察準度** | 總管 | ✅ 9/9,連跑三次(2026-08-26),A 群誤攔 0 |
|
||||
| A7 plugin 裝得起來 | 總管 | ✅ |
|
||||
| **A8 新 session 閘會觸發** | 總管 | 見本版 release note |
|
||||
| **B1–B5 雲端** | **leo** | 還沒跑(機器碰不到 Cloud environment) |
|
||||
|
||||
+20
-2
@@ -1,4 +1,4 @@
|
||||
# 43 支閘,白話盤點表
|
||||
# 46 支閘,白話盤點表
|
||||
|
||||
> 回應 `inkstone/InkStoneCo#40`:「如果加入了,我應該可以白話文看到 hooks 的內容?」
|
||||
> 這份表就是那個「白話文」——不用點開任何 `.sh` 檔,一行看懂一支閘在管什麼。
|
||||
@@ -7,10 +7,16 @@
|
||||
|
||||
## 一句話結論
|
||||
|
||||
`hooks/` 底下有 **43 個 `.sh` 檔**,`hooks.json` 實際掛上 **53 條註冊**(同一支閘常被多種情境同時掛上);
|
||||
`hooks/` 底下有 **46 個 `.sh` 檔**,`hooks.json` 實際掛上 **56 條註冊**(同一支閘常被多種情境同時掛上);
|
||||
其中 **3 支檔案存在但沒被掛上**(2 支是待人填的空範本、1 支是刻意留著沒開的止血帶,見下面「未生效」表)。
|
||||
下面按「你會在什麼時候撞到它」分組,一支一行。
|
||||
|
||||
> 🔴 **這兩個數字上一版是錯的(2026-08-26 實際數過才發現)**:本頁原本寫「43 個檔、53 條註冊」,
|
||||
> 而當時真實是 **45 個檔、55 條註冊**——中間有兩支閘進來時沒有回頭改這裡。
|
||||
> 現在的寫法是實際數出來的:
|
||||
> `ls hooks/*.sh | wc -l` = 46;`hooks.json` 展開後的 command 條目 = 56。
|
||||
> **一份會偷偷過期的盤點表,跟沒有盤點表差不多**——見本頁最後「怎麼跟實況對帳」那段。
|
||||
|
||||
---
|
||||
|
||||
## 怎麼讀這張表
|
||||
@@ -71,6 +77,18 @@
|
||||
| `irreversible-dispatch-guard.sh` | 派工單裡出現「刪分支」「drop table」「rm -rf」這類不可逆動作,卻沒寫「先停下來等回覆才執行」就擋下。 | 🛑 擋 |
|
||||
| `no-ticket-no-dispatch.sh` | 派工單裡沒有寫工單號(`【工單】owner/repo#N`),或那張票已經關閉/根本不存在,就擋下——沒有票號的工作沒有人追得到進度。 | 🛑 擋 |
|
||||
|
||||
## D2. AI 想開口問你問題的當下(PreToolUse / AskUserQuestion)
|
||||
|
||||
| 閘名 | 對你意味著什麼 | 動作 |
|
||||
|---|---|---|
|
||||
| `ask-user-question-guard.sh` | AI 要跳出來問你一個問題的**那一刻**先攔一下,用小模型(haiku)照「四題公式」判這題該不該打擾你:**花錢/不可逆/跨專案結構/品味方向/只有你做得到**——命中任何一題就放行(那本來就該問你),四題全否(純技術實作選擇、問「要不要開始」)就擋回去要它自己裁。**同一個問題只擋一次**,它重送就過得去,所以判錯不會害你收不到問題;判官掛掉/沒網路也一律放行。 | 🛑 擋(同一題至多一次) |
|
||||
|
||||
> **為什麼要有這一組**(leo 2026-08-26:「今天已經好幾次問我,**為什麼 hooks 沒有攔下來?**」):
|
||||
> 在這之前 `AskUserQuestion` 在 `hooks.json` 裡出現 **0 次**,一支閘都沒掛。
|
||||
> F 組那兩支自走警察(`self-drive-police` / `self-drive-judge`)判準一樣,
|
||||
> 但它們掛在「收工」那一刻——**問題早就送到你眼前了**,事後再問 AI「你查過了嗎」已經來不及。
|
||||
> 這一組補的是**時機**,不是判準。
|
||||
|
||||
## E. 每個對話一開始(SessionStart)
|
||||
|
||||
| 閘名 | 對你意味著什麼 | 動作 |
|
||||
|
||||
Reference in New Issue
Block a user