併進 main(#96 雲端接線/#100 v0.12.0/#99 主線唯一),解 TESTING.md 撞號(inkstone/ISEP#92)
唯一衝突在 docs/TESTING.md:兩條線各自加了一節、**都叫 A16**。 兩邊內容都留,我這一節改成 A19(main 已用掉 A16/A17/A18), 「目前狀態」表的那一列跟著搬到 A18 後面。 main 側本來就有的 A11/A12/A14/A15 重號**沒有動**——那是它兩條線各自編的, 不是這次造成的,動它會把 diff 炸開。 沒有碰的:.claude-plugin/plugin.json(維持 main 的 v0.12.0,版本由總管統一定)、 hooks/hooks.json、docs/hooks-inventory.md——這三個檔本線一個字都沒改, 自動合併拿到的就是 main 那份。 盤點數字在合併後的樹上重數(不是相加、不是抄別人的): hooks/*.sh 54 hooks.json 註冊 71 commands 7 skills 2 scripts 頂層 38 docs/hooks-inventory.md 寫的 54/71 **是對的**;README 寫的 48/59/23 **三個都錯**,已改成實數,並把「怎麼重數」的指令寫進去—— 這種數字會漂是因為沒人知道它怎麼來的。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016ZBu4Sa1cGntKFRBYNZ6xs
This commit is contained in:
+145
-2
@@ -91,6 +91,40 @@ bash scripts/test-baton-handback-guard.sh
|
||||
- 「不該報」4 條任一紅 ⇒ 每條線收工都被念一次,警報會被學會忽略
|
||||
- 「票已關」那條紅 ⇒ 棒子已經到終點還在催,那是最典型的假警報
|
||||
|
||||
### A14 — PR 一定要有結論:52 條
|
||||
```
|
||||
bash hooks/tests/pr-verdict-guard.test.sh
|
||||
```
|
||||
**該看到**:`52 通過 / 0 失敗`。全程離線(走 `PR_VERDICT_FIXTURE`),
|
||||
**不打 Gitea、不開測試 PR、不留任何測試票**;狀態檔走 `PR_VERDICT_STATE_DIR`。
|
||||
|
||||
**它在守什麼**(`inkstone/ISEP#81`,2026-08-27 實查):最久的三個 open PR 躺了兩星期
|
||||
(`inkstone/arcrun-rag#91` 14 天、`inkstone/Arcrun#116` 14 天、`inkstone/Arcrun#104` 15 天),
|
||||
而 v0.9.0 的 46 支閘**一支都沒有在管 PR**。票看起來是「已交付」,
|
||||
東西卻沒進 main ⇒ 沒進版本 ⇒ **leo 手上永遠不會出現它**。
|
||||
|
||||
**失敗**:
|
||||
- B 群(⑨⑩⑪,票上那三個真跡)任一紅 ⇒ 今天這個形狀會再發生一次
|
||||
- C 群 ⑭⑰ 紅 ⇒ 驗收條件 1/3 沒過:「放著不管」抓不到,或「merge 了分支還在」放行
|
||||
- **A 群任何一條紅 ⇒ 誤攔,這比漏擋嚴重**。②③特別重要:
|
||||
指派給人/掛 Human 之後還在點名,就是 ISEP v0.6.0 divergence §B4 記過的那個坑
|
||||
(「`s/review` 佇列非空即 block」⇒ 佇列本來就不會空 ⇒ **總管永遠停不下來**)
|
||||
- E 群 ㉙ 紅 ⇒ 閘訊息裡承諾的出路(「把它指派給那個人,本閘立刻不再點名它」)是假的
|
||||
- D 群 ㉓ 紅 ⇒ 判準從「識別碼比對」滑成「只要提到票號就放行」,閘會被任何一句話關掉
|
||||
|
||||
> 📌 **真跡不只在 fixture 裡跑過**:同一支閘打真實 Gitea 也驗過,
|
||||
> 一次點名 7 個沒有結論的 PR,含票上那三個(15/14/14 天)。
|
||||
> 指令:`printf '{"session_id":"x","transcript_path":"/nonexistent"}' | bash hooks/pr-verdict-guard.sh`
|
||||
> ——**唯讀,不改動任何 PR**。
|
||||
|
||||
### A15 — 給結論的那支工具自己說得出要打哪幾通 API
|
||||
```
|
||||
python3 scripts/pr-verdict list
|
||||
python3 scripts/pr-verdict merge inkstone/ISEP#71 --dry-run
|
||||
```
|
||||
**該看到**:`list` 印出 open PR 與「有沒有人被指派」;`merge --dry-run` 印出
|
||||
`[dry-run] POST …/pulls/71/merge` 與 `[dry-run] DELETE …/branches/<分支>`,**一通都不真的送出**。
|
||||
**失敗**:`--dry-run` 底下出現真實的寫入結果 ⇒ 這支工具沒辦法在按下去之前被檢查。
|
||||
### A14 — 每一則回覆都自己說出拖了多久:20 條
|
||||
```
|
||||
bash hooks/tests/countdown-guard.test.sh
|
||||
@@ -120,6 +154,49 @@ bash hooks/tests/countdown-guard.test.sh
|
||||
(subagent 的回覆不是給 leo 看的),所以在一條 subagent 裡跑,B 群會**全綠而且是假綠**。
|
||||
測試檔自己會把它清掉——2026-08-28 第一次跑就撞到這個,才補上去的。
|
||||
|
||||
### A16 — 現在的主線是哪一個:24 條
|
||||
```
|
||||
bash hooks/tests/mainline-focus-guard.test.sh
|
||||
```
|
||||
**該看到**:`通過 24 條,失敗 0 條`。**全程離線**:狀態走 `ISEP_COUNTDOWN_STATE_DIR`、
|
||||
時鐘走 `ISEP_COUNTDOWN_NOW`、「那張票掛在哪」走 `ISEP_MAINLINE_FIXTURE`,
|
||||
並把 `TICKET_HOST` 指到一個連不上的位址——**任何一條真的走到網路,會在那裡當場失敗,
|
||||
不會靜靜地變成假綠**。
|
||||
|
||||
**它在守什麼**(`inkstone/ISEP#82`,leo 2026-08-27):
|
||||
「**14 個里程碑同時亮著卻不知道該看哪個**」。當天實查 14 個 open milestone,
|
||||
其中「Mira 現代化」這個名字同時活在 5 個 repo,5 個已經逾期
|
||||
⇒ SOP 說的「只做**該** milestone 的事」**沒有指涉對象,等於不存在**。
|
||||
|
||||
**判準**:問「現在的主線是哪一個」,`scripts/mainline` 回一個答案,而且只有一個。
|
||||
|
||||
**失敗**:
|
||||
- A 群任一條紅 ⇒ 答案不唯一,或標了新的舊的還在——那就回到 14 個一起亮的狀態
|
||||
- ⑧ 紅 ⇒ **目標宣告沒有自己出現**(票上驗收第 2 條),leo 又要自己去翻
|
||||
- ⑨ 紅 ⇒ 主線的名字沒掛在被查核的 ⏱ 那一行上 ⇒ 它到不了 leo 眼前
|
||||
(本票刻意不另立第二道會擋人的閘,就是靠這一格成立)
|
||||
- ⑩ 紅 ⇒ 用「期限最近的那個」蓋過了被指定的主線。**猜的不准蓋過指定的**
|
||||
- ⑬⑭ 紅 ⇒ 派了不在主線上的票沒被問一次,或問了卻沒給補收/跳線兩條路
|
||||
- ⑯ 紅 ⇒ **鬼打牆**:同一張票被擋第二次。至多擋一次是硬要求
|
||||
- **⑲–㉔(不該擋)任一條紅 ⇒ 誤攔,這比漏擋嚴重**。特別是 ⑲(沒有主線就一律放行,
|
||||
票上驗收第 4 條)與 ㉒(問不到那張票掛在哪 ⇒ 放行)——
|
||||
**「讀不到」不等於「不屬於」,把這兩件事講成同一句是最貴的錯**
|
||||
|
||||
📌 這一條線的另一半是**指令**,不是閘:`scripts/mainline`(`show`/`list`/`set`/
|
||||
`clear`/`refresh`/`adopt`/`has`)。要打網路的那幾個(list/set/adopt)不在測試裡跑,
|
||||
因為它們**只有真的 Gitea 才驗得了**——驗法見 A17。
|
||||
|
||||
### A17 — 主線那支指令真的問得到 Gitea(要網路)
|
||||
```
|
||||
python3 scripts/mainline list
|
||||
```
|
||||
**該看到**:一份 open milestone 清單,**跨多個 repo**(`ISEP` / `Arcrun` / `arcrun-rag` / `mira`…),
|
||||
每一行左邊是可以直接貼給 `set` 的 `owner/repo#<milestone id>`。
|
||||
**失敗**:
|
||||
- `一個 open milestone 都沒讀到` ⇒ 這台機器拿不到 Gitea。**那是讀不到,不是沒有**
|
||||
——不要因此標一個猜的主線
|
||||
- 只有單一 repo ⇒ 沒有跨 repo,等於沒看到全局
|
||||
|
||||
### A15 — 發通知不等於部署:37 條
|
||||
```
|
||||
bash hooks/tests/prod-write-guard.test.sh hooks/prod-write-guard.sh
|
||||
@@ -131,7 +208,68 @@ bash hooks/tests/prod-write-guard.test.sh hooks/prod-write-guard.sh
|
||||
- 「卡點二」2 條任一紅 ⇒ 「談論它」又被當成「執行它」(同款第八次),
|
||||
或是剝了內文之後連真的部署都放行了
|
||||
|
||||
### A16 — 下游做完時頂層跟著關:49 條
|
||||
### A16 — 「總管可以放行」那道門真的打得開:17 條
|
||||
```
|
||||
bash hooks/tests/gate-ok.test.sh
|
||||
```
|
||||
**該看到**:`通過 17 條,失敗 0 條`。
|
||||
|
||||
**它在守什麼**(inkstone/ISEP#90 ④,2026-08-28 實查):三支閘
|
||||
(`prod-write-guard`/`main-and-prod-push-guard`/`stage-before-prod-guard`)
|
||||
都是「擋下來、但**總管看過就能放行**」的設計,而**既有測試只驗了擋得住,
|
||||
一條都沒驗過放得開**。於是這個 bug 活了很久:`stat -f %m` 在 GNU coreutils 上
|
||||
是「檔案系統資訊」,它一邊回非零一邊吐一整段文字 ⇒ 秒數被污染 ⇒
|
||||
**在 Linux(=每一個雲端 session)上戳記永遠不被接受** ⇒ 那三支閘在雲端等於純擋,
|
||||
而閘不會告訴你門是壞的。
|
||||
|
||||
**失敗**:
|
||||
- ②⑤(門打得開)紅 ⇒ 逃生口又焊死了,那三支閘在雲端變回純擋
|
||||
- ⑥⑦⑧(門沒變寬)任一紅 ⇒ **更嚴重**:綁 repo/有效期/空戳記那三條性質是
|
||||
08-11、08-12 兩次真的被穿透之後才補上的,不准為了「好放行」而鬆掉
|
||||
- ⑫ 紅 ⇒ `gate-ok` 在解不出 repo 時留下了一枚註定打不開的空戳記,
|
||||
那會讓人以為門開了(而空戳記本身就是 08-12 那把萬用鑰匙的形狀)
|
||||
- ⑰ 紅 ⇒ 判準又變回「行為取決於 cwd 裡有沒有一個叫 `%m` 的檔」。
|
||||
這條是這個 bug 的最後一層:**GNU 的 `-f` 是布林旗標,`%m` 被當成另一個檔名運算元**
|
||||
⇒ 有那個檔就 `exit 0`、`||` 連跑都不跑。所以修法不能只是「把順序反過來」,
|
||||
**每一步都要驗它是不是純數字**
|
||||
|
||||
⚠️ 這支會真的寫 `/tmp` 的戳記檔(那是閘寫死的路徑)。**不要在「已經蓋好戳記正要推東西」
|
||||
的當下跑它**——它會把那枚戳記洗掉。
|
||||
|
||||
### A17 — 未推警察不會對雲端的工作分支亂叫:10 條
|
||||
```
|
||||
bash hooks/tests/unpushed-police.test.sh
|
||||
```
|
||||
**該看到**:`通過 10 條,失敗 0 條`。全離線(用本機 bare repo 當「遠端」)。
|
||||
|
||||
**它在守什麼**(inkstone/ISEP#90 ①):雲端 session 開出來的工作分支天生沒有 upstream,
|
||||
內容卻等於遠端 main ⇒ 舊判準「沒 upstream=從沒推過」讓**每個雲端 session、每次收工
|
||||
都被攔一次**(08-27 一個 session 五次全是誤報)。
|
||||
|
||||
**失敗**:
|
||||
- A 群(①—⑥,不該報)任一紅 ⇒ **誤攔**,比漏擋嚴重:永遠在響的警報=訓練人忽略它,
|
||||
下一條真的失蹤的分支會混在雜訊裡
|
||||
- B 群(⑦—⑩,該報)任一紅 ⇒ 為了不吵而改成放行了,那是把閘關掉不是修好
|
||||
- 特別看 ④:問不到遠端(離線)**不准當成「你沒推」**
|
||||
|
||||
### A18 — 信標會講出雲端會壞掉的那三件事:14 條
|
||||
```
|
||||
bash hooks/tests/isep-presence-beacon.test.sh
|
||||
```
|
||||
**該看到**:`通過 14 條,失敗 0 條`。全離線。
|
||||
|
||||
**它在守什麼**(inkstone/ISEP#90 ②③):信標原本只證明「有一份 plugin 載入了」,
|
||||
不證明「載入的是哪一份」——08-27 雲端載 0.3.9、main 0.9.0,差 7 個 release,
|
||||
而它照樣是綠的。
|
||||
|
||||
**失敗**:
|
||||
- ⑫⑬⑭(信標永遠在)任一紅 ⇒ **最嚴重**:那一行消失=leo 會判定這個 session 零閘
|
||||
- ③ 紅 ⇒ 版本落差報不出來,`ISEP#67` 那個病又變回看不見
|
||||
- ⑤⑦ 紅 ⇒ 舊複本遮蔽正門抓不到(`InkStoneCo/scripts/ticket` 那件)
|
||||
- ⑥ 紅 ⇒ **誤攔**:同步過的複本被念,人就學會忽略它
|
||||
- ⑪ 紅 ⇒ 內層迴圈變數撞名的回歸(同一個 `.claude` 下第二個殘骸會被靜靜跳過)
|
||||
|
||||
### A19 — 下游做完時頂層跟著關:49 條
|
||||
```
|
||||
bash scripts/test-ticket-handoff-writeback.sh
|
||||
```
|
||||
@@ -360,15 +498,20 @@ B2(信標那行)/B3(setup 輸出)/B4(閘的訊息)三個畫面
|
||||
| A3 打 tag 閘 | 總管 | ✅ 3/3 |
|
||||
| **A4 新增 Gitea 東西側門閘** | 總管 | ✅ 24/24(2026-08-27,inkstone/ISEP#72) |
|
||||
| **A13 戳記證明看過不是跑過** | 總管 | ✅ 17/17(2026-08-27,inkstone/ISEP#72→4873) |
|
||||
| **A14 PR 一定要有結論** | 總管 | ✅ 52/52(2026-08-28,inkstone/ISEP#81)+真實 Gitea 唯讀重演 |
|
||||
| **A15 pr-verdict --dry-run** | 總管 | ✅(2026-08-28) |
|
||||
| **A14 回覆自己說出拖了多久** | 總管 | ✅ 20/20(2026-08-28,inkstone/ISEP#63) |
|
||||
| **A15 發通知不等於部署** | 總管 | ✅ 37/37(2026-08-28,inkstone/ISEP#63) |
|
||||
| **A16 下游做完頂層跟著關** | 總管 | ✅ 49/49(2026-08-28,inkstone/ISEP#92) |
|
||||
| A5 搜尋跨 repo | 總管 | ✅ |
|
||||
| A6 標籤對齊+冪等 | 總管 | ✅ 14 repo,第二次 0/0 |
|
||||
| **A9 人閘警察管路** | 總管 | ✅ 14/14(2026-08-26) |
|
||||
| **A10 人閘警察準度** | 總管 | ✅ 9/9,連跑三次(2026-08-26),A 群誤攔 0 |
|
||||
| **A11 派工單只剩票號** | 總管 | ✅ 19/19(2026-08-27) |
|
||||
| **A12 留言身份欄(兩道門)** | 總管 | ✅ 11/11(2026-08-27) |
|
||||
| **A16 放行的門真的打得開** | 總管 | ✅ 17/17(2026-08-28,inkstone/ISEP#90) |
|
||||
| **A17 未推警察不誤攔雲端分支** | 總管 | ✅ 10/10(2026-08-28,inkstone/ISEP#90) |
|
||||
| **A18 信標會報雲端接線缺陷** | 總管 | ✅ 14/14(2026-08-28,inkstone/ISEP#90) |
|
||||
| **A19 下游做完頂層跟著關** | 總管 | ✅ 49/49(2026-08-28,inkstone/ISEP#92) |
|
||||
| A7 plugin 裝得起來 | 總管 | ✅ |
|
||||
| **A8 新 session 閘會觸發** | 總管 | 見本版 release note |
|
||||
| **B1–B5 雲端** | **leo** | 還沒跑(機器碰不到 Cloud environment) |
|
||||
|
||||
Reference in New Issue
Block a user