把 main(v0.15.0,派工紀律三件 #105)併進來,逐支點名複驗過 hooks.json
## hooks.json:這次 git 自動合成功了,而那正是最危險的情況
`hooks.json` 是 JSON——**合錯了語法照樣合法、閘卻不見了,不會有任何東西喊一聲。**
所以「沒有衝突」不等於「沒掉東西」,一律再做兩件事:
① 逐支點名(指令已寫進 README「裝什麼」那段)→ 82 條,60 支各自幾條全部列出
② 跟**兩個父節點**做集合對照:
merged 82 = main 79 + 我的 3
從 main 掉了:0 條
從我這邊掉了:0 條
兩邊都沒有卻冒出來的:0 條
`#105` 三支與我的兩支同時在,位置也對:
roster-guard.sh PreToolUse Agent / Task
diagnosis-evidence-guard.sh PreToolUse Bash
investigate-first-stamp.sh PostToolUse Agent|Task / SendMessage
overdue-nag-guard.sh SessionStart
wiki-size-guard.sh SessionStart / PreToolUse Write|Edit|MultiEdit
(總管提醒的 `roster-guard` vs `mainline-focus-guard` 那種「同一陣列位置兩邊各一支」
這次沒有再發生衝突,但兩支都在,各 2 條。)
## 三處文字衝突:兩邊都留,數字重數
- plugin.json 版本吃 main 的 **0.15.0**(總管已定版,**我沒有動它**);
描述欄補上 main 新增的「7 位有名字的工人」,三個數字重數
- README.md 吃 main 的新表格結構(多了 agents/commands/skills/scripts 四列),
數字重數;並把累積成**四列**的 `hooks/` 收成一列
- hooks-inventory 標頭被貼成兩份、「一句話結論」被貼成**三份**(數字還互相打架),
各收成一份;版本註記兩邊都留
## 盤點(全部在合併後的樹上實數,不是加減推的)
ls hooks/*.sh | wc -l 58 → 60
grep -c '"command":' hooks/hooks.json 79 → 82
ls agents/*.md | wc -l 7
ls -p scripts | grep -v / | wc -l 48
未掛進 hooks.json 的 .sh 3(與本頁原本寫的一致,重數過)
📌 抓到的漂移(每次併都有一個,這次三個):
① hooks-inventory 的標頭 ×2、一句話結論 ×3
② README 的 `hooks/` 列 ×4,其中兩列是舊數字
③ plugin.json 描述欄寫「49 支腳本」,而用本頁寫死的那道指令實數是 48
## 測試(合併後全部重跑,帶對參數)
hooks/tests 23 支全綠:ask-user-question 14、countdown 20、diagnosis-evidence 26、
dispatch-format 52、factory-idle 33、gate-ok 17、gitea-arm-check 16、
presence-beacon 14、cross-repo 19、main-and-prod-push 10、mainline-focus 24、
mainline-idle 61、milestone-account 22、**overdue-nag 36**、pr-verdict 52、
prod-write 37、reply-identity 11、roster 24、sdd 8、search-is-not-proof 31、
stage-before-prod 16、unpushed-police 10、**wiki-compress 25**
scripts/test-* 13 支全綠。
claude plugin validate . ✔ passed;check-version-consistency ✅ 0.15.0 = v0.15.0。
兩支新 SessionStart hook 併完實跑過,閘判定探針對 v0.15.0 的 prod-write-guard 回 pass。
🔴 跑之前清 `CLAUDE_CODE_CHILD_SESSION`;四支要帶參數
(三支帶 hook 絕對路徑、cross-repo 帶 hook 絕對路徑、gitea-arm-check 帶 repo 根目錄)
——不帶會紅,而那是假紅。
This commit is contained in:
+59
-2
@@ -504,11 +504,12 @@ bash hooks/tests/ask-user-question-guard.live.test.sh
|
||||
- 📌 這支會隨模型版本漂移,**是量尺不是一次性驗收**。改完判準要連跑三次都全綠才算數
|
||||
(2026-08-26 實測:第一版判準連兩次都在同一題漏擋,收緊 ③④ 定義後三次全綠)
|
||||
|
||||
### A11 — 派工單只剩票號:擋得住,也放得過,而且會注入共通規定
|
||||
### A11 — 派工單只剩票號(含**回覆那條路**):擋得住,也放得過,而且會注入共通規定
|
||||
```
|
||||
bash hooks/tests/dispatch-format-guard.test.sh
|
||||
```
|
||||
**該看到**:`19/19 通過`。**離線、不打網路、不花錢**——這支閘是純結構判斷,沒有語意判官,
|
||||
**該看到**:`52/52 通過`(`inkstone/ISEP#88` 之前是 33 條;本頁一度寫 19,那是更早的數字,
|
||||
**沒有人回頭改** —— 同一個病,只是換一欄)。**離線、不打網路、不花錢**——這支閘是純結構判斷,沒有語意判官,
|
||||
所以它不需要像 A10 那樣另開一支 live 測試量準度,**每次結果都一樣**。
|
||||
**失敗**:
|
||||
- A 群任何一條紅 ⇒ **誤攔**。合規的派工只有一行票號,擋掉它等於整台機器派不了工
|
||||
@@ -517,6 +518,58 @@ bash hooks/tests/dispatch-format-guard.test.sh
|
||||
它壞了不會有人立刻發現——派工照樣送出去,只是收工方**不知道要貼回原票**
|
||||
- ⑨ 紅 ⇒ 真跡放行了。那份測資是**真的發生過的那一次派工**(見 `hooks/tests/fixtures/README.md`)
|
||||
- ⑰ 紅 ⇒ 訊息被 shell 展開了(同 A9 ⑩b 那個病:閘照擋,但它教人怎麼解的那兩行變成空白)
|
||||
- **D 群⑲⑳㉑㉒ 紅 ⇒ `inkstone/ISEP#88` 的驗收條件沒過**:回覆一個正在跑的 subagent
|
||||
時夾帶指令沒被擋(⑲)、或擋了卻沒把那段內容原文印出來(㉑,出路是「貼上票」,
|
||||
找不到原文就得回頭自己翻)
|
||||
- **E 群㉔–㉙ 任一紅 ⇒ 有一條通往 subagent 的路又漏了**。那六條是雲端 session/trigger/
|
||||
`claude -p`——`ticket-api-bypass-guard.sh` 檔頭記過這一族的通病:「認動作的方式漏了一條路」
|
||||
- **F 群㉚–㉟ 任一紅 ⇒ 誤攔**。㉚特別重要:subagent 往上回報(`to: "main"`)是**交件**,
|
||||
擋它等於擋掉交件本身;㉟反過來,子 session 自己往下派工時規矩要照樣管它,不然是逃逸艙口
|
||||
|
||||
### A16 — 工人有名字:指名派工、沒有這個人、注入它的檔案:24 條
|
||||
```
|
||||
bash hooks/tests/roster-guard.test.sh
|
||||
```
|
||||
**該看到**:`24 通過 / 0 失敗`。**離線、不打網路、不花錢**——純結構判斷(名字在不在名單裡),
|
||||
沒有語意判官,每次結果一樣。
|
||||
|
||||
**它在守什麼**(`inkstone/ISEP#86`):「身為派工的人,我要工人有名字,
|
||||
我才知道票上這件事到底是誰做的。」開票當日實查:`/root/.claude/agents/` 不存在,
|
||||
派工派給的是**沒有名字的臨時工**——票上只看得到「有個 agent 做了」。
|
||||
|
||||
**失敗**:
|
||||
- ①②③ 紅 ⇒ 驗收 1 沒過:`scripts/roster` 列不出名單、或列了卻看不出各自管什麼
|
||||
- ④⑤ 任一紅 ⇒ **誤攔**,名單上的人被擋掉 = 整台機器派不了工。這比漏擋嚴重
|
||||
- ⑥⑦⑧ 紅 ⇒ 驗收 4 沒過:派一個不存在的名字時講不出「沒有這個人」
|
||||
- ⑨ 紅 ⇒ 擋了卻沒印名單,人不知道有誰可以派(閘的訊息要講得出出路)
|
||||
- ⑬ 紅 ⇒ 名單讀不到時**沒有 fail-open**。一份讀不到的名單不該讓整台機器停擺
|
||||
- ⑯⑰ 紅 ⇒ 注入壞了。那是「你是誰/先讀什麼/你的紅線」唯一的送達方式——
|
||||
它壞了不會有人立刻發現,派工照樣送出去,只是工人不知道自己是誰
|
||||
- ⑱ 紅 ⇒ 驗收 3 沒過:票上的【身份】欄吃不下工人名字(或把原本三個角色弄壞了)
|
||||
|
||||
### A17 — 未經調查不寫診斷:26 條
|
||||
```
|
||||
bash hooks/tests/diagnosis-evidence-guard.test.sh
|
||||
```
|
||||
**該看到**:`26 通過 / 0 失敗`。**全程離線**:不打 Gitea、不開任何測試票,
|
||||
戳記走 `ISEP_STAMP_DIR`(不碰 `/tmp` 的正式戳記)。
|
||||
|
||||
**它在守什麼**(`inkstone/ISEP#87`):「先派人查 → 拿到查的結果 → 才可以寫診斷。」
|
||||
未經調查的診斷寫在票上會長得像事實,**工人會照著它去驗證,而不是去查**。
|
||||
|
||||
**失敗**:
|
||||
- ①–⑦ 任一紅 ⇒ 驗收 1 沒過。⑥⑦特別看:那是**側門**(直接打 Gitea API),
|
||||
只封正門等於沒封
|
||||
- ② 紅 ⇒ 驗收 3 沒過:訊息說不出「你還沒派人查這件事」,變成籠統的「格式不對」
|
||||
- ⑧⑨ 紅 ⇒ 驗收 2 沒過(派過人查卻還在擋),或戳記從「按票分」滑成「按 session 分」
|
||||
——後者等於派過一次就永久解鎖
|
||||
- **⑩–⑫ 任一紅 ⇒ 驗收 4 沒過,這是誤攔**:轉述別人查到的東西(有出處)被擋,
|
||||
那會逼人把真的有出處的話也吞回去
|
||||
- ⑬ 紅 ⇒ 判準從結構滑回措辭。那一條**故意用一段連「根因/因為/應該是」都沒有的內容**,
|
||||
它一旦放行,代表閘開始靠關鍵字判斷了(leo 2026-08-17 已證偽那條路)
|
||||
- ⑭–⑲ 任一紅 ⇒ 誤攔(短回覆、唯讀、搜尋、關票被擋)
|
||||
- ㉑ 紅 ⇒ 鬼打牆:同一張票擋不只一次,人會學會忽略它
|
||||
- ㉓㉔ 紅 ⇒ payload 壞掉時擋住了。這支是 PreToolUse,fail-closed 會讓人做不了事
|
||||
|
||||
### A12 — 票上的每一則留言都認得出是誰寫的(兩道門)
|
||||
```
|
||||
@@ -677,6 +730,10 @@ B2(信標那行)/B3(setup 輸出)/B4(閘的訊息)三個畫面
|
||||
| A6 標籤對齊+冪等 | 總管 | ✅ 14 repo,第二次 0/0 |
|
||||
| **A9 人閘警察管路** | 總管 | ✅ 14/14(2026-08-26) |
|
||||
| **A10 人閘警察準度** | 總管 | ✅ 9/9,連跑三次(2026-08-26),A 群誤攔 0 |
|
||||
| **A11 派工單只剩票號+回覆那條路(ISEP#88)** | 總管 | ✅ 52/52(2026-08-28) |
|
||||
| **A12 留言身份欄(兩道門)** | 總管 | ✅ 11/11(2026-08-28 複跑) |
|
||||
| **A16 工人有名字(ISEP#86)** | 總管 | ✅ 24/24(2026-08-28) |
|
||||
| **A17 未經調查不寫診斷(ISEP#87)** | 總管 | ✅ 26/26(2026-08-28) |
|
||||
| **A11 派工單只剩票號** | 總管 | ✅ 19/19(2026-08-27) |
|
||||
| **A12 留言身份欄(兩道門)** | 總管 | ✅ 11/11(2026-08-27) |
|
||||
| **A16 放行的門真的打得開** | 總管 | ✅ 17/17(2026-08-28,inkstone/ISEP#90) |
|
||||
|
||||
@@ -44,6 +44,58 @@
|
||||
|
||||
---
|
||||
|
||||
## 1.5 派給誰:從名單裡挑一個**有名字的工人**(inkstone/ISEP#86)
|
||||
|
||||
派工單只有票號,那「這是誰的活」寫在哪?——**不寫在派工單裡,寫在 `subagent_type`。**
|
||||
|
||||
```
|
||||
Task(subagent_type="isep-hand", prompt="【工單】inkstone/ISEP#86")
|
||||
▲ 名單上的名字 ▲ 派工單仍然只有這一行
|
||||
```
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| 名單在哪 | `agents/`,一個檔案一位工人(規約:`docs/governance/worker-roster.md`) |
|
||||
| 怎麼看 | `python3 scripts/roster list`/`show <名字>`/`which <owner/repo>` |
|
||||
| 機械閘 | `hooks/roster-guard.sh`——沒指名或名單上沒有這個名字就擋,並印出整份名單 |
|
||||
|
||||
**為什麼「你是誰」不能收進 §2 的共通規定**:共通規定是「每次都一樣」的東西,
|
||||
而「你是誰、你該讀哪些、你的紅線」**每個工人都不一樣**。所以它有自己的家(名單),
|
||||
由 `roster-guard.sh` 在派工當下注入——同樣不必有人記得寫。
|
||||
|
||||
---
|
||||
|
||||
## 1.6 回覆也是派工:**同一套規矩,同一支閘**(inkstone/ISEP#88)
|
||||
|
||||
派工單被壓成只剩票號之後,**回覆一個正在跑的 subagent 這條路沒有被管到**——
|
||||
那支閘掛在 `PreToolUse(Task|Agent)`,而回覆走的是別的工具,根本不經過那個攔截點。
|
||||
|
||||
實況(2026-08-27):第一次派工乾乾淨淨只有票號,中途回覆時又把一長串修改要求丟過去。
|
||||
**那些話票上一個字都沒有**,那條線被停掉或換人接手就消失。
|
||||
|
||||
⇒ **不另造一支平行的閘**:同一支 `dispatch-format-guard.sh`、同一個判斷函式,
|
||||
只是把所有通往 subagent 的路一次列全(表在 `hooks/lib/dispatch_parse.py` 的 `tool_channel()`):
|
||||
|
||||
| 路 | 裝話的欄位 |
|
||||
|---|---|
|
||||
| `Task`/`Agent` | `prompt` |
|
||||
| `SendMessage` | `message` |
|
||||
| 雲端 `create_session` | `prompt` |
|
||||
| 雲端 `send_message` | `text`/`message` |
|
||||
| 雲端 `create_trigger`/`update_trigger` | `prompt` |
|
||||
| 雲端 `fire_trigger` | `text` |
|
||||
| 雲端 `send_later` | `message` |
|
||||
| Bash `claude -p <prompt>` | 指令裡那段 prompt |
|
||||
|
||||
🔴 **新增一條路要加在那張表裡,不要再開一支閘。**
|
||||
「認動作的方式漏了一條路」是這一族的通病——`ticket-api-bypass-guard.sh` 的檔頭
|
||||
記過同一課(第一版只認大寫裸字 `POST`,`requests.post()` 與隱式 POST 全部漏掉)。
|
||||
|
||||
**刻意不管的方向**:subagent 往上回報(`SendMessage to: "main"`)=**交件不是派工**。
|
||||
擋它等於擋掉交件本身。
|
||||
|
||||
---
|
||||
|
||||
## 2. 共通規定(每一次派工由機器自動注入給收工方)
|
||||
|
||||
<!-- INJECT:BEGIN 這段之間的內容會被 dispatch-format-guard.sh 原文注入,改這裡=改所有派工 -->
|
||||
@@ -55,8 +107,10 @@
|
||||
3. **交件=貼回那張票**(`scripts/ticket say <owner/repo#N> -F <檔>`),
|
||||
不是只在對話裡回報。回覆第一行必須是身份欄,見下。
|
||||
4. **回覆第一行一律是**:
|
||||
`【身份】subagent/<owner/repo>/<你的分支>`
|
||||
角色三選一:`總管`/`subagent`/`leo`。
|
||||
`【身份】<你的名字>/<owner/repo>/<你的分支>`
|
||||
名字用機器注入給你的那個(`isep-hand`、`scout`…);沒有名字時才退回
|
||||
`總管`/`subagent`/`leo` 三選一。**票上要看得出是哪個工人做的**,
|
||||
而三條線並行時「subagent」這個字回答不了「是誰」。
|
||||
5. **不准 push 到 `main`/`master`**,也不准部署 prod。做在自己的分支上,交回分支名。
|
||||
6. **Gitea 的 org 是 `inkstone`**(不是 `Leo`);`gh` 打不到 Gitea;
|
||||
標籤是 `s/*` 不是 `status/*`。
|
||||
@@ -80,9 +134,13 @@
|
||||
【身份】subagent/inkstone/ISEP/feat/ticket-carries-the-task
|
||||
```
|
||||
|
||||
- 角色是**三選一的允許清單**:`總管`/`subagent`/`leo`
|
||||
- 角色是**允許清單**:`總管`/`subagent`/`leo`,**再加上 `agents/` 名單上的每一個工人名字**
|
||||
(`isep-hand`/`arcrun-hand`/`scout`…,inkstone/ISEP#86)。清單以外的名字一律擋。
|
||||
- 第二格是你動的 repo,第三格是分支(沒有就寫 `-`)
|
||||
|
||||
🔴 **有名字就用名字。** 三條線並行時三則「【身份】subagent/…」長得一模一樣,
|
||||
等於沒有身份——這正是 ISEP#86 要解的那件事。
|
||||
|
||||
### 為什麼
|
||||
|
||||
2026-08-27 實害:多條線並行時票上的留言看不出身份,
|
||||
@@ -106,8 +164,30 @@
|
||||
## 4. 這份規範自己怎麼被驗
|
||||
|
||||
```
|
||||
bash hooks/tests/dispatch-format-guard.test.sh 派工單閘:該擋的與不該擋的
|
||||
bash hooks/tests/reply-identity.test.sh 身份欄:正門與側門兩道
|
||||
bash hooks/tests/dispatch-format-guard.test.sh 派工單閘+**回覆那條路**:該擋的與不該擋的
|
||||
bash hooks/tests/reply-identity.test.sh 身份欄:正門與側門兩道
|
||||
bash hooks/tests/roster-guard.test.sh 工人名單:指名、沒有這個人、注入
|
||||
bash hooks/tests/diagnosis-evidence-guard.test.sh 未經調查不寫診斷
|
||||
```
|
||||
|
||||
測資裡放的是**真的發生過的那幾份違規派工單**,不是想像出來的例子。
|
||||
|
||||
---
|
||||
|
||||
## 5. 寫上票之前:**未經調查不寫診斷**(inkstone/ISEP#87)
|
||||
|
||||
順序只有一個方向:**先派人查 → 拿到查的結果 → 才可以寫診斷。**
|
||||
|
||||
> 「診斷寫完了,工人就不知道自己要做什麼——它會照著我的結論去驗證,而不是去查。
|
||||
> 而我不是那個 repo 的專家,它才是。」
|
||||
|
||||
機械閘 `hooks/diagnosis-evidence-guard.sh` 看三個**結構**訊號(一個關鍵字都沒有):
|
||||
|
||||
1. 這個 session 有沒有**派人查過那張票**(`investigate-first-stamp.sh` 的戳記)
|
||||
2. 這段話裡有沒有**走得過去的出處**(檔案:行號/commit/comment 號/票號/網址/實測輸出)
|
||||
3. 這段話**有沒有份量**(一句「收到」不可能是診斷)
|
||||
|
||||
①有 ⇒ 放行。①無+②有 ⇒ 放行(**轉述有出處不能被誤擋**)。三者皆缺 ⇒ 擋一次。
|
||||
|
||||
🔴 **「根因」「因為」「應該是」這類詞一律不准當判準**——leo 2026-08-17 已證偽文字層封路:
|
||||
當日 8 次誤攔、0 次正確攔截,而且**紅線寫得越細,命中關鍵字的機率越高 ⇒ 那些閘在懲罰謹慎**。
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# `agents/` — 工人名單(inkstone/ISEP#86)
|
||||
|
||||
> leo 派工時派給的不能是「一個 agent」,要派給**有名字的人**。
|
||||
> 「票上看不出來這件事是誰做的」是這張票的來由。
|
||||
|
||||
**一個檔案 = 一個工人。** 每個檔案只回答四件事:
|
||||
|
||||
| 段 | 問題 | 為什麼一定要有 |
|
||||
|---|---|---|
|
||||
| `**負責 repo**` | 它管哪一個 repo | 派工時挑人的唯一判準;也是【身份】欄第二格 |
|
||||
| `## 開工前先讀` | 它要先讀什麼 | 這是**每個工人各自不同**的部分——共通規定補不了 |
|
||||
| `## 紅線` | 它不准做什麼 | 全機共通的紅線在共通規定裡;這裡只寫這個 repo 特有的 |
|
||||
| frontmatter `description` | 一句話它是誰 | `scripts/roster list` 印的就是這一行 |
|
||||
|
||||
## 為什麼是這個形狀,不是自己造一套
|
||||
|
||||
`agents/` 是 Claude Code plugin **原生**的 subagent 目錄,檔名(frontmatter 的 `name`)
|
||||
就是 `Task` 工具的 `subagent_type`。⇒ 「指名派給誰」不必發明新欄位、不必改派工單格式
|
||||
(派工單仍然只有 `【工單】` 一行,`dispatch-format-guard.sh` 的行為一個字都沒變)。
|
||||
|
||||
## 怎麼用
|
||||
|
||||
```
|
||||
python3 scripts/roster list # 名單:有哪幾個工人、各自管什麼
|
||||
python3 scripts/roster show isep-hand # 一個工人的全文(它開工前會讀到的東西)
|
||||
python3 scripts/roster names # 只印名字,給腳本用
|
||||
```
|
||||
|
||||
派工時把名字放進 `Task` 的 `subagent_type`;名字不在名單上,
|
||||
`hooks/roster-guard.sh` 會擋下來並說「**沒有這個人**」,同時把名單印出來。
|
||||
|
||||
## 加一個工人
|
||||
|
||||
在這個目錄新增一個 `.md`(照既有檔案的四段),然後:
|
||||
|
||||
```
|
||||
python3 scripts/roster list # 新的名字要出現
|
||||
bash hooks/tests/roster-guard.test.sh # 全綠
|
||||
```
|
||||
|
||||
**不必改任何 hook**——名單是資料,閘讀的是這個目錄。
|
||||
+37
-12
@@ -1,4 +1,4 @@
|
||||
# 57 支閘,白話盤點表
|
||||
# 60 支閘,白話盤點表
|
||||
|
||||
> 回應 `inkstone/InkStoneCo#40`:「如果加入了,我應該可以白話文看到 hooks 的內容?」
|
||||
> 這份表就是那個「白話文」——不用點開任何 `.sh` 檔,一行看懂一支閘在管什麼。
|
||||
@@ -7,14 +7,14 @@
|
||||
|
||||
## 一句話結論
|
||||
|
||||
`hooks/` 底下有 **57 個 `.sh` 檔**,`hooks.json` 實際掛上 **75 條註冊**(同一支閘常被多種情境同時掛上);
|
||||
`hooks/` 底下有 **60 個 `.sh` 檔**,`hooks.json` 實際掛上 **82 條註冊**(同一支閘常被多種情境同時掛上);
|
||||
其中 **3 支檔案存在但沒被掛上**(2 支是待人填的空範本、1 支是刻意留著沒開的止血帶,見下面「未生效」表)。
|
||||
下面按「你會在什麼時候撞到它」分組,一支一行。
|
||||
|
||||
> 🔴 **這兩個數字上一版是錯的(2026-08-26 實際數過才發現)**:本頁原本寫「43 個檔、53 條註冊」,
|
||||
> 而當時真實是 **45 個檔、55 條註冊**——中間有兩支閘進來時沒有回頭改這裡。
|
||||
> 現在的寫法是實際數出來的:
|
||||
> `ls hooks/*.sh | wc -l` = 57;`grep -c '"command":' hooks/hooks.json` = 75。
|
||||
> `ls hooks/*.sh | wc -l` = 60;`grep -c '"command":' hooks/hooks.json` = 82。
|
||||
> ⚠️ **冒號不能省**:`grep -c '"command"'`(沒冒號)會連 `"type": "command"` 一起數到,回 **120**。
|
||||
> 本頁 2026-08-27 之前寫的是沒冒號那版——**照著它跑會拿到一個跟本頁不符的數字**。
|
||||
> **一份會偷偷過期的盤點表,跟沒有盤點表差不多**——見本頁最後「怎麼跟實況對帳」那段。
|
||||
@@ -46,14 +46,37 @@
|
||||
> 📌 **`0.7.0`(`inkstone/ISEP#30`,2026-08-27)進來一支**:`mainline-idle-guard.sh`(F 組,Stop)。
|
||||
> 48→**49** 支、59→**60** 條,兩個數字都是加完之後當場數出來的(指令同上)。
|
||||
>
|
||||
> 📌 **`inkstone/ISEP#93` + `#89`(2026-08-28)進來兩支**:
|
||||
> 📌 **`inkstone/ISEP#86`/`#87`/`#88`(2026-08-28)進來三支、+7 條**:
|
||||
> `roster-guard.sh`(D 組,`Task`+`Agent` 各一條)、
|
||||
> `diagnosis-evidence-guard.sh`(A 組,Bash)、
|
||||
> `investigate-first-stamp.sh`(H 組,`Agent|Task` 與 `SendMessage` 各一條),
|
||||
> 外加 `dispatch-format-guard.sh` 多掛兩處——Bash(接 `claude -p` 這條路)與
|
||||
> **新的「回覆 subagent」matcher**(`SendMessage` 與雲端 session/trigger 那幾支)。
|
||||
> 53→**56** 支、68→**75** 條,兩個數字都是**在這棵樹上當場數出來的**
|
||||
> (`ls hooks/*.sh | wc -l`/`grep -c '"command":' hooks/hooks.json`),
|
||||
> 不是拿上一版加減推的。順手改掉兩個過期的數字:`README.md` 的「48 支/59 條註冊/23 支腳本」
|
||||
> ——實數是 53/68/35(那是**併之前** main 上的實況),本版之後是 56/75/36。
|
||||
> **同一個病,只是換一個檔案。**
|
||||
>
|
||||
> 📌 **`inkstone/ISEP#93` + `#89`(2026-08-28)進來兩支、+3 條**:
|
||||
> `overdue-nag-guard.sh`(E 組,SessionStart)與 `wiki-size-guard.sh`(E 組 + B 組,兩個事件)。
|
||||
> 55→**57** 支、72→**75** 條——**兩個數字都是在「把 main 併進來之後」的樹上當場數出來的**,
|
||||
> 58→**60** 支、79→**82** 條——**兩個數字都是在「把 main 併進來之後」的樹上當場數出來的**,
|
||||
> 不是拿上一版加減推的(本頁自己上面就記著「不能靠加減推算、只能實數」)。
|
||||
> 順手拿掉一組重複貼上的行(那條 `grep` 指令被貼了兩次)。
|
||||
> 📌 **併回來時抓到的一個漂移**:`plugin.json` 描述欄寫「48 支腳本」,
|
||||
> 而用本頁寫死的那道指令(`ls -p scripts | grep -v / | wc -l`,只數檔案)
|
||||
> 在合併後的樹上實數是 **47**——**同一個病,第 N 次,只是換一欄。**
|
||||
>
|
||||
> 🔴 **這次併 `hooks.json` 學到一件比數字更重要的事**:它是 JSON,
|
||||
> **合錯了語法照樣合法、閘卻不見了,不會有任何東西喊一聲。**
|
||||
> 「同一個陣列位置兩邊各有一支」時(本次是 `roster-guard` vs `mainline-focus-guard`),
|
||||
> 正解是**展開成兩個項目**,不是二選一——選一邊就會讓一支真的閘靜靜消失。
|
||||
> ⇒ 合完一律再跑一次**逐支點名**(指令寫在 `README.md`「裝什麼」那段),
|
||||
> 並跟兩個父節點做集合對照:**從 main 掉了幾條、從自己這邊掉了幾條、冒出幾條**。
|
||||
> 本次三個答案都是 0。
|
||||
>
|
||||
> 📌 **順手抓到的漂移(每次併都抓到一個,這次是三個)**:
|
||||
> ① 本頁的「一句話結論」被貼成**三份**、標頭被貼成**兩份**(數字還互相打架);
|
||||
> ② `README.md` 的 `hooks/` 那列累積成**四列**,其中兩列是舊數字;
|
||||
> ③ `plugin.json` 描述欄寫「49 支腳本」,而用本頁寫死的那道指令
|
||||
> (`ls -p scripts | grep -v / | wc -l`,只數檔案)在合併後的樹上實數是 **48**。
|
||||
> **同一個病,第 N 次,只是換一欄。**
|
||||
|
||||
> 📌 **`0.10.0`(`inkstone/ISEP#81`,2026-08-28)進來一支**:`pr-verdict-guard.sh`(F 組,Stop)。
|
||||
> 51→**52** 支、64→**65** 條,兩個數字都是加完之後當場數出來的(指令同上)。
|
||||
@@ -101,7 +124,7 @@
|
||||
| `reply-identity-guard.sh` | 直接打 Gitea API 貼留言到票上時,內文第一行沒有 `【身份】`(`總管`/`subagent`/`leo`)就擋下——票上多條線並行時,看不出哪一則是誰寫的。純讀取、走 `scripts/ticket` 正門、指令裡加 `reply-identity-ok` 都放行。 | 🛑 擋 |
|
||||
| `comment-carries-task-guard.sh` | AI 要在票裡留一則「等某某上線才驗得了」這種**還沒做完的事**,卻沒有把它開成一張子票時,擋一次。留言沒人會回頭讀,票的 open/closed 撈一次就看得到。 | 🛑 擋(同一輪只擋一次) |
|
||||
| `search-is-not-proof-guard.sh` | AI 用知識庫的**搜尋**找到一筆東西,然後把那筆東西的原始編號直接貼進票裡或派工單裡,當成「某個功能壞了」的證據——而它從沒用正規的檢索路徑去查過那筆——擋一次。你關心的是:不會再有人拿錯的方法量出一個錯的結論,然後退回一張其實已經做完的票。 | 🛑 擋(同一輪只擋一次) |
|
||||
|
||||
| `diagnosis-evidence-guard.sh` | 你想把一段有份量的東西寫上票,而這個 session **沒派人去查過那張票**、那段話裡也**沒有任何走得過去的出處**(檔案:行號/commit/comment 號/票號/網址/貼出來的實測輸出)就擋一次——未經調查的診斷寫在票上會長得像事實,工人會照著它去驗證而不是去查。派過人查、或把出處帶上,都放行;一句短回覆不管。 | 🛑 擋 |
|
||||
## B. AI 想寫檔案/改程式碼的當下(PreToolUse / Write·Edit·MultiEdit)
|
||||
|
||||
| 閘名 | 對你意味著什麼 | 動作 |
|
||||
@@ -134,6 +157,8 @@
|
||||
| `micromanage-guard.sh` | 派工單寫得太細(指名檔案函式、編號步驟、要求每做一項回報一次…)就擋下——subagent 該被當成有能力的同事,不是照抄劇本的工具。 | 🛑 擋 |
|
||||
| `irreversible-dispatch-guard.sh` | 派工單裡出現「刪分支」「drop table」「rm -rf」這類不可逆動作,卻沒寫「先停下來等回覆才執行」就擋下。 | 🛑 擋 |
|
||||
| `no-ticket-no-dispatch.sh` | 派工單裡沒有寫工單號(`【工單】owner/repo#N`),或那張票已經關閉/根本不存在,就擋下——沒有票號的工作沒有人追得到進度。 | 🛑 擋 |
|
||||
| `dispatch-format-guard.sh` | **派工單 = 票號,就這樣。** 票號以外還寫了別的東西(背景、驗收條件、紅線、交件方式、「這個 session 才知道的事」)就擋下,並告訴你那些內容該搬去哪:每次都一樣的 → 共通規定;這次才知道的 → **寫進那張票**。反過來,合規的派工它會**自動把共通規定注入**給收工方(交件方式、不准 push main、org 是 `inkstone`…),所以你不寫也不會漏。判準是「這一行是不是【工單】欄位」——**在不在**,不是寫了什麼,所以講得再謹慎也不會被多罰。純禮貌收尾(「謝謝」)不算違規;`(→ comment M)` 不論全形或半形括號都認得(ISEP#65 修過一次:CLAUDE.md 自己規定的合格寫法曾經被這支閘自己擋下)。**`ISEP#88` 起同一支閘也掛在「回覆 subagent」那條路上**(`SendMessage`、雲端 session/trigger、以及 Bash 的 `claude -p`)——回覆也是派工,同一套規矩;擋下來時會把那段內容**原文印出來**方便直接貼上票。subagent 往上回報(`to: "main"`)不管,那是交件不是派工。 | 🛑 擋(+注入) |
|
||||
| `roster-guard.sh` | 派工要**指名派給誰**:`Task` 的 `subagent_type` 得是 `agents/` 名單上的名字(`isep-hand`/`arcrun-hand`/`scout`…),沒指名或指了不存在的名字就擋下,並把整份名單印出來。指對了它會**自動把那位工人的檔案原文注入**給它——你是誰、負責哪個 repo、開工前先讀什麼、你的紅線是什麼(這些每個工人都不一樣,共通規定補不了)。名單是資料:加一個工人=在 `agents/` 加一個 `.md`,不必改任何 hook。 | 🛑 擋(+注入) |
|
||||
| `mainline-focus-guard.sh` | 派出去的票**不在「現在的主線」上**,就擋一次,並問你是「補收」(它本來就該掛在主線上)還是「跳線」(真的插件事)。背景:2026-08-27 實查有 **14 個 milestone 同時開著**,其中「Mira 現代化」同名活在 5 個 repo ⇒ SOP 說的「只做該 milestone 的事」在現場**沒有指涉對象**,等於不存在。現在主線是一個查得到的事實(`scripts/mainline`,答案唯一),這支就是那個事實的用處。🔴 **沒有標主線 ⇒ 一律放行**;多張票只要有一張在主線上就放行;查不到那張票掛在哪也放行(**讀不到 ≠ 不屬於**);**同一張票只擋一次**,重送就過。跳線會留一筆紀錄——不留痕的話,跳線與專注在機器上長得一模一樣。 | 🛑 擋(同一張票至多一次) |
|
||||
| `dispatch-format-guard.sh` | **派工單 = 票號,就這樣。** 票號以外還寫了別的東西(背景、驗收條件、紅線、交件方式、「這個 session 才知道的事」)就擋下,並告訴你那些內容該搬去哪:每次都一樣的 → 共通規定;這次才知道的 → **寫進那張票**。反過來,合規的派工它會**自動把共通規定注入**給收工方(交件方式、不准 push main、org 是 `inkstone`…),所以你不寫也不會漏。判準是「這一行是不是【工單】欄位」——**在不在**,不是寫了什麼,所以講得再謹慎也不會被多罰。純禮貌收尾(「謝謝」)不算違規;`(→ comment M)` 不論全形或半形括號都認得(ISEP#65 修過一次:CLAUDE.md 自己規定的合格寫法曾經被這支閘自己擋下)。 | 🛑 擋(+注入) |
|
||||
|
||||
@@ -197,7 +222,7 @@
|
||||
| `issue-status-autoflip.sh` | AI 一派工出去,就自動把對應的 Gitea 票改成「進行中(s/doing)」,不必等人手動改標籤。 | 📝 記錄(自動改票) |
|
||||
| `baton-handback-guard.sh` | 一條派工線做完了,就去看它那張票有沒有**指派給人/標籤有沒有說它卡在哪/有沒有寫下一步**,缺哪一格就當場說出來。你關心的是:不會再有票做完了卻沒人接手,躺在那裡沒人發現。 | 📝 記錄(提醒,不擋) |
|
||||
| `kbdb-evidence-stamp.sh` | AI 每次去知識庫拿資料,就記一筆「這是**搜尋**搜到的,還是**走正規檢索路徑**拿到的」。你關心的是:它等一下要拿這筆資料下結論時,有東西可以對照它走的是哪條路。 | 📝 記錄 |
|
||||
|
||||
| `investigate-first-stamp.sh` | 你真的**派人去查某張票**之後,按「session + 票號」留一個時間戳——給 `diagnosis-evidence-guard.sh` 判斷「這件事有沒有人查過」用。按票分而不是按 session 分:早上派人查了 A 票,不該等於解鎖了 B 票的診斷。 | 📝 記錄 |
|
||||
## I. 你會撞到但跟「派工/收工」無關的一支(Edit·MultiEdit)
|
||||
|
||||
| 閘名 | 對你意味著什麼 | 動作 |
|
||||
@@ -297,7 +322,7 @@ A1 缺人話、A2 表格有幽靈、C 全頁有幽靈。
|
||||
|
||||
**這次順便抓到的另一個落差**(🕐 **這一段是 2026-08-20 的快照,裡面每個數字都是那天的,不是現況**——
|
||||
留著是因為它是「兩份文件的數字不會自己跟上」這個病的第一個案例;現況數字看本頁標頭):
|
||||
`.claude-plugin/plugin.json` 的說明文字寫「55 支機械閘(52 條註冊)」,
|
||||
`.claude-plugin/plugin.json` 的說明文字寫「58 支機械閘(52 條註冊)」,
|
||||
`README.md` 也寫「42 支 + `hooks.json`」「共 52 條註冊」——但實測是 **43 支檔案、53 條註冊**。
|
||||
差 1 支、差 1 條,猜測是今天(2026-08-20)新增的 `leo21c-write-guard.sh`/`release-tag-guard.sh`/
|
||||
`ticket-api-bypass-guard.sh` 這批(檔頭日期都是今天)加了之後,兩份文件的數字沒有跟著更新。
|
||||
|
||||
Reference in New Issue
Block a user