sdd-guard 退役:讓「取消 Active SDD」這個裁決真的執行得下去(inkstone/ISEP#91)
leo 2026-08-16 在 inkstone/InkStoneCo#40 → comment 2942 裁定「取消 Active SDD」, 11 天沒被執行。原因不是有人偷懶,是**執行它的第一步會鎖死自己**: sdd-guard.sh 是 fail-closed 的 · 動 code 檔時 status: active 不是恰好 1 份 → 擋(0 份也擋) · 路徑所在的 repo 沒有 3-specs → 也擋 ⇒ 照裁決把最後那份 active 拿掉 → 變 0 份 → 任何人動任何 .ts/.py/.go 全被擋。 而 ISEP 這個 repo 自己就沒有 3-specs——本票開工第一件事實測到: $ echo '{"tool_name":"Edit","tool_input":{"file_path":".../hooks/lib/dispatch_parse.py"}}' \ | bash hooks/sdd-guard.sh 🚫 SDD 協議攔截:… 找不到任何 SDD exit 2 **它一直在誤攔 ISEP 自己,只是沒人回報。** ── 這一版做了什麼 ──────────────────────────────────── · hooks/sdd-guard.sh 刪除,hooks.json 取消註冊(85 → 84 條,只少這一條) · commands/sdd-check.md 改寫:SDD 只記「起初的樣子」,任務本體在 Gitea 票; 找不到 SDD 不再是停下來的理由,找不到票才是 · agents/inkstoneco-hand.md 拿掉「任何時刻只允許一份 status: active」那條紅線 · hooks/lib/path-resolve.sh 只加註解:它的唯一 caller 走了,但別順手刪 (#22 學到的東西住在裡面,十幾支閘還在用它要修的那個寫法) ── 迴歸測試:測的不是「檔案刪了沒」,是「那個擋還會不會發生」── hooks/tests/sdd-guard-retired.test.sh(通過 8/失敗 0,離線): 把「裁決執行完之後的世界」(沒有 3-specs 的 repo、兩份 status: active 的 repo) 丟給 hooks.json 上**整組** Write|Edit|MultiEdit 的閘——清單當場從 hooks.json 讀、 不寫死——不准有任何一支用 SDD/3-specs 當理由擋下來。 ⇒ 日後有人換個檔名把同一個形狀種回來,這支照樣紅。 🔴 判準刻意不是「一支閘都不准擋」:同組還住著跟 SDD 無關、且看 session 狀態 決定擋不擋的閘(history-first/subagent-first)。把它們算失敗,這支測試會在別人 改別的東西時無故變紅,紅久了就沒人看——誤攔比漏擋更該修,對測試一樣成立。 **紅的證明**:把 sdd-guard 暫時復原(檔案+註冊)重跑 → 通過 1/失敗 7, 四條行為格全部指名 sdd-guard.sh。已還原。 ── 自己跑過的 ────────────────────────────────────── · hooks/tests/sdd-guard-retired.test.sh 通過 8/失敗 0 · 逐支點名 hooks.json(README「裝什麼」那道指令) 84 條,對 main 做集合差: 少了 sdd-guard.sh × 1,多出 0 支,其餘一支不差 · 盤點數字全部在這棵樹上實數,不是加減推: ls hooks/*.sh|wc -l = 61(原 62) grep -c '"command":' hooks/hooks.json = 84(原 85) agents 7/commands 7/skills 2/scripts 48(皆未變動) · 盤點表對帳三格(hooks-inventory 自己寫死的那三道):三格皆無輸出 · scripts/check-version-consistency.sh ✅ 0.16.2 一致 · claude plugin validate . ✅ Validation passed · hooks/tests/ 全部離線測試 24 支重跑:本次改動 0 退步 (dispatch-format-guard 40/52、prod-write-guard 18/19-fail、 stage-before-prod-guard 9/7-fail、另 3 支需帶參數/建不起沙盒—— **六支在 gitea/main 上逐支重跑結果一模一樣,是既有狀態不是本次造成**) ── 沒做、也不該由這張票做的 ───────────────────────── · inkstone/InkStoneCo 那半(拿掉 active SDD + 刪 CLAUDE.md「單一活性鐵律」段) ——那是 inkstoneco-hand 的 repo;而且順序上本來就要等這一版出去、 兩邊 /plugin update 之後才動得,先拿掉就鎖死 · checkbox 分診(掛 inkstone/InkStoneCo#49,票上明寫不要另開票) · 版本號:待總管定版 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016ZBu4Sa1cGntKFRBYNZ6xs
This commit is contained in:
+57
-41
@@ -1,65 +1,81 @@
|
||||
---
|
||||
name: sdd-check
|
||||
description: |
|
||||
開始任何開發任務前確認有沒有對應的 SDD——要寫 code、開新功能、
|
||||
或不確定「這件事屬於哪份規格」時自動載入。
|
||||
依 D35 SDD 生命週期鐵律:任何時刻只允許一份 status: active 的 SDD,
|
||||
所有開發任務對應它的 tasks,找不到就停下來問(不得自行建 SDD);
|
||||
動手前把這件事的來歷讀齊——要寫 code、開新功能、
|
||||
或不確定「這件事當初為什麼長這樣」時自動載入。
|
||||
🔴 Active SDD 已於 2026-08-16 取消(inkstone/InkStoneCo#40):
|
||||
**任務本體在 Gitea 票,不在 SDD**;SDD 只記「起初的樣子」,
|
||||
沒有 status、沒有唯一活性、也不再養任務 checkbox。
|
||||
⇒ 找不到 SDD 不是停下來的理由,找不到票才是;也不要為了動手而現編一份 SDD。
|
||||
規格層變更改開 Gitea 票(Human+指派 Leo)後停止等 confirm——pending-changes.md 已於 2026-08-19 廢除,禁止寫入。
|
||||
---
|
||||
|
||||
# /sdd-check — 確認當前任務有沒有對應 SDD
|
||||
# /sdd-check — 動手前把這件事的來歷讀齊
|
||||
|
||||
動手前執行。確保 CC 有全局觀,不會在沒有設計文件的情況下猛衝。
|
||||
## 先講清楚它現在是什麼
|
||||
|
||||
leo 2026-08-16(`inkstone/InkStoneCo#40` → comment 2942):
|
||||
|
||||
> 「**取消 Active SDD**⋯⋯所有文件中都不帶有任務 checkbox,因為移動到 Gitea 來管理,
|
||||
> SDD 會脫節,它所做的是記錄起初的樣子⋯⋯實際情況靠 issues, PR, release 等機制來管理。」
|
||||
|
||||
所以三件事分家(`docs/governance/sdd-gitea-governance.md` §0 公理 1):
|
||||
|
||||
```
|
||||
意圖真相 → SDD(docs/3-specs/) 未來式:當初打算怎麼做
|
||||
狀態真相 → Gitea 票/PR/release 現在式:現在做到哪、誰在做
|
||||
知識真相 → wiki 過去式:撞過什麼、學到什麼
|
||||
```
|
||||
|
||||
🔴 **這支命令已經不是一道閘了。** 舊版靠 `sdd-guard.sh` 在動 code 前強制要有
|
||||
「恰好一份 status: active 的 SDD」,那支閘於 `inkstone/ISEP#91` 退役——
|
||||
它是 fail-closed 的,裁決一執行(active SDD 歸零)就會鎖死所有 code 寫入。
|
||||
|
||||
---
|
||||
|
||||
## 執行流程
|
||||
|
||||
### 第一步:理解任務
|
||||
### 第一步:這件事的**票**是哪一張
|
||||
|
||||
確認使用者要做什麼:
|
||||
- 涉及哪個子系統?
|
||||
- 是新功能還是修改現有功能?
|
||||
- 影響範圍?
|
||||
**這一步不能跳,也是唯一會讓你停下來的一步。**
|
||||
|
||||
### 第二步:尋找對應 SDD
|
||||
- 有票號 → 讀它(含整串留言:裁決、假設、前手交回的下一步都在那裡)
|
||||
- 沒票號 → **先問清楚是哪一張,或先把票開出來**,不要憑一句話開工
|
||||
(`commands/issue-handle.md`:Issue 是唯一任務介面)
|
||||
|
||||
在 `docs/3-specs/` 下尋找對應的子系統目錄,確認有沒有:
|
||||
- `design.md`(設計文件)
|
||||
- `tasks.md`(任務清單)
|
||||
### 第二步:這件事的**來歷**在哪份 SDD
|
||||
|
||||
### 第三步:根據結果回應
|
||||
在 `system-dev/docs/3-specs/` 下找對應子系統的 `design.md`。
|
||||
|
||||
- 找到 → 讀它,弄清楚「當初為什麼這樣設計、有哪些邊界不能動」
|
||||
- **找不到 → 照樣可以動手**。票才是任務本體;
|
||||
沒有 SDD 只代表這塊當初沒有寫下設計,不代表這件事沒被批准
|
||||
|
||||
🔴 **不要為了動手而現編一份 SDD**,也不要去改任何 `status:` frontmatter——
|
||||
那是已經取消的制度的殘留物。
|
||||
|
||||
🔴 **不要把任務 checkbox 寫進 SDD**。要追蹤進度就開票/改票的狀態標籤;
|
||||
寫進文件裡的 checkbox 沒有人會回來關掉它(`inkstone/InkStoneCo#49`
|
||||
清的就是這一批:378 條沒人維護的 checkbox)。
|
||||
|
||||
### 第三步:把讀到的東西講出來再動手
|
||||
|
||||
回覆開頭一行交代即可:
|
||||
|
||||
**情況 A:找到對應 SDD**
|
||||
```
|
||||
✅ 找到 SDD:docs/3-specs/[子系統]/
|
||||
📋 design.md:[確認]
|
||||
📋 tasks.md:[確認,列出相關 task]
|
||||
🎯 對應 task:[編號和描述]
|
||||
繼續嗎?
|
||||
📌 票:<owner/repo#N> —— <一句話它要解什麼>
|
||||
📋 來歷:<design.md 路徑,或「這塊沒有 SDD」>
|
||||
🚧 邊界:<這次不准動的東西>
|
||||
```
|
||||
|
||||
**情況 B:找不到 SDD,任務明確**
|
||||
```
|
||||
⚠️ 找不到對應 SDD
|
||||
任務:[描述]
|
||||
建議在 docs/3-specs/[建議子系統名]/ 建立 SDD
|
||||
---
|
||||
|
||||
要我幫你起草 design.md 嗎?(需要你確認後才動手)
|
||||
```
|
||||
## 什麼時候該停下來問
|
||||
|
||||
**情況 C:找不到 SDD,任務模糊**
|
||||
```
|
||||
⚠️ 找不到對應 SDD,而且任務範圍不夠清楚
|
||||
請先回答:
|
||||
1. 這個功能屬於哪個子系統?
|
||||
2. 完成的標準是什麼?
|
||||
3. 有沒有不能動的邊界?
|
||||
```
|
||||
只有這幾種,**都跟 SDD 在不在無關**:
|
||||
|
||||
### 注意
|
||||
- 找不到對應的票,也問不出是哪一張
|
||||
- 票上的要求跟現行規範互相衝突(貼出兩邊出處,給出你的推測,再問)
|
||||
- 命中四題公式:花錢/不可逆/跨專案結構/品味方向
|
||||
|
||||
- 找不到 SDD **不等於可以直接動手**
|
||||
- 小修改(修 bug、改文字)可以豁免,但要明確說「這是小修改,範圍是 X」
|
||||
- 新功能、架構變動、跨模組的修改 → 一定要有 SDD
|
||||
其餘情況做出最合理的假設、把假設寫進 commit message 或票的留言,繼續走。
|
||||
|
||||
Reference in New Issue
Block a user