50876ffa4f
leo 交辦:把 claude.ai 寫的治理規範整理進 ISEP,並且「查看是否合理,提出意見⋯⋯ 改一版你的版本」。原稿作者看不到 codebase,標籤名/hook 名/既有鐵律有實錯。 三份文件: - _draft-claude-ai-v0.5.0.md 原稿,一字未改,加存檔標頭 - sdd-gitea-governance.md v0.6.0 現行版 - DIVERGENCE-v0.5.0-to-v0.6.0.md 我改了哪 14 處、為什麼 修訂重點(實查 2026-08-20 的現場,不是推測): - 標籤名幾乎全是憑空的:gate/human・s/review・close/*・hub・type/* 現場一個都不存在。 Human 不改名(leo 08-17 才改過,改名會廢掉他的看板習慣),另加 human/exec 當第二維度。 - 狀態機三態擴成七態:原稿會擠掉 s/triage・s/backlog・s/pending・s/stage, 而那四個態上掛著 179 張 open 票。s/review 與 s/stage 是兩件事,不可互相取代。 - E1–E16 的 hook 全是憑空命名,改成標註「已有 <實際檔名> / 待建」—— E14 其實已經有了(subagent-claim-worksheet.sh),重造就是第 42 支互相打架的閘。 - 刪掉「薄殼只裝 shell-safe 子集」:那是舊薄殼模型的殘留,正是 InkStoneCo#57 的成因, 而且與原稿自己的 P11.2.1/P11.2.4 自相矛盾。 - 排程 job 第一版一律不依賴 Gitea Actions runner(有沒有 runner 未經查證, 依賴不確定存在的東西,壞掉的形式是「以為有人在跑」)。 - 補上原稿整份沒有的「載入契約」一節——那正是 leo 需求 3 的核心,也是 InkStoneCo#14 的根因。 - 補上 M4.6:release note 寫在 release 裡不寫 README(leo 2026-08-20 當場指正)。 - 補上 §3.4 總管收工義務:審核通過的當下就關票(leo 2026-08-20 指出上次 milestone 0% 的病)。 兩個裁決題已按判斷先做、理由寫在 DIVERGENCE §E,leo 可打回: PR-only 只套 ISEP 不套全部 repo;舊的 duplicate 標籤封存不刪。
13 KiB
13 KiB
我改了 claude.ai 那版的哪些地方,為什麼
leo 2026-08-20 交辦:「你查看是否合理,提出意見,因為這個是計劃, 有些已經有、有些還沒有、有些有了不符合⋯⋯則你要改一版你的版本。」
本檔是我的意見書。原稿存檔在
_draft-claude-ai-v0.5.0.md, 修訂後的現行規範是sdd-gitea-governance.md(v0.6.0)。
先講結論
- 骨架是對的,照單全收
- 物件模型(SDD → tracking → leaf → PR → release,milestone 橫切當 time 軸)
- 「封路優於守規」這條公理——它跟你 08-17 那句「封的是動作,不是文字」是同一件事
- 「人是特殊 executor」把
gate/human(審核者)與exec/human(執行者)拆開- 🔴 這是原稿最有價值的一條。現行的
Human標籤把兩件事混在一起: 「你來按放行」跟「這件事只有你的手能做」——前者你可以晚點按, 後者你不按整條線就停在那。混在一起你看不出哪張真的在擋路。
- 🔴 這是原稿最有價值的一條。現行的
- 時態分工(SDD 未來式/Gitea 現在式/Wiki 過去式)
- 有 14 處對不上現場,我改了。下面逐條。
- 有 2 處是你的裁決題,我先按我的判斷做了,理由寫在票上,你覺得不對就打回。
A. 事實錯誤(原稿寫的東西,現場不存在或不長那樣)
A1. 標籤名幾乎全是憑空的
- 我實查(2026-08-20):
inkstone/ISEP當時 0 個標籤;inkstone/InkStoneCo有 10 個- 現有:
Humanduplicatep/highp/lows/backlogs/doings/pendings/stages/todos/triage - 原稿要的
gate/humans/reviewclose/*hubtype/*——一個都不存在
- 現有:
- 為什麼會這樣:claude.ai 看不到 codebase 也連不上 Gitea,標籤名只能用猜的。這不是它的錯,是那個 surface 的限制。
- 我怎麼改:把標籤集寫成
labels.yaml當唯一真相源,並且先建出來再說——ISEP 已經實建 23 個並驗證存在。名字取捨見 A2–A4。
A2. gate/human → 不改名,維持 Human
- 你 08-17 才把
s/leo改名成Human,而且明講它是正交維度不是流程狀態, 你自己是靠 Gitea 原生「指派給您的」+這個標籤在看跨 repo 的待辦。 - 改名成
gate/human會做兩件壞事:既有票全部要重貼標籤;你現在的看板習慣當場失效。 - 我怎麼改:
Human原封不動(語意=你是審核者)。另外新增human/exec表示「這張票的執行者是人」。兩者可以疊,也可以只有其一。
A3. 狀態機只有三態,會把現場四個態擠掉
- 原稿:
s/todo → s/doing → s/review → closed。 - 現場正在用的還有
s/triage(還沒驗傷)、s/backlog(要做但沒排 sprint)、s/pending(卡在外部)、s/stage(已上 stage 等你驗)。 三個 repo 加起來 179 張 open 票掛在這些態上。 - 我怎麼改:狀態機擴成七態,原稿的三態是其中的主幹道。
A4. s/review 和 s/stage 是兩件事,原稿把它們當成一件
s/review= PR 開了,等總管 merge(程式碼還沒進 main)s/stage= 已經部署到 stage,等 leo 實際打開來驗(程式碼早進 main 了)- 原稿只有前者,等於把「等你驗收」這個態砍掉——那正是你唯一會看的那個態。
- 我怎麼改:兩個都留,並在狀態機裡標明先後。
A5. E1–E16 的 hook 全是憑空命名,現場有 41 支真的
- 原稿的封路清單只寫「用什麼封」,沒有一個對得上真檔名。
- 實際對照(我逐支比對過檔名,不是猜的):
| 原稿 | 現場有沒有 | 對應到哪支 |
|---|---|---|
| E1 直接 push 預設分支 | ◐ 有但語意相反 | main-and-prod-push-guard.sh(擋 subagent,放行總管) |
| E6 代理越過人閘 | ◐ 部分 | irreversible-dispatch-guard.sh/prod-write-guard.sh |
| E11 地端雲端漂移 | ◐ 管的是別的 | skill-deploy-drift-guard.sh(管 skill,不管 manifest) |
| E12 宣稱交付但票未關 | ◐ 部分 | delivery-police.sh/claim-verify-police.sh |
| E14 subagent 空口宣稱 | ✅ 已經有了 | subagent-claim-worksheet.sh+empty-handed-stop-guard.sh |
| E2 E3 E4 E5 E7 E8 E9 E10 E13 E15 E16 | ❌ 沒有 | — |
- 我怎麼改:修訂版的封路清單一律標「現況:已有
<檔名>/ 待建」, 已有的不重造(重造就是第 42 支互相打架的閘)。
A6. §11.1 的目錄結構與實際 repo 不符
- 原稿畫的是
governance-plugin/,實際 repo 叫ISEP。 - 原稿沒提到的、實際存在的:
commands/(7 支)、skills/(2 支)、scripts/(23 支)。 - 原稿列的、實際不存在的:
labels.yaml、templates/、jobs/、manifest.json。 - 🔴 順手抓到的髒東西:
scripts/install.sh其實是 system-dev-template 的安裝器 (內容在裝 wiki/SDD,跟 plugin 無關),搬家時混進來的。修訂版標明它是待清理項。
A7. §11.4.4 叫 install.sh 去 systemctl restart gitea
- 我沒有查證 Gitea 跑在哪台、是不是 docker、我有沒有那台的 shell。所以我不知道這行能不能跑。
- 但更根本的問題:原稿自己在 §11.4.3 說「模板通道壞掉不影響治理正確性」—— 既然如此,就不該為它在安裝腳本裡放一個會失敗、會嚇人、還可能重啟到別人東西的動作。
- 我怎麼改:模板通道降級成 optional 的獨立腳本,不掛在 install 流程上。
A8. Telegram「小六 bot 通道」
- 原稿直接寫了通道名。我沒有核實過那是不是現役通道名,所以修訂版不寫死通道名,
改成指向
wiki/agent-memory.md的通知通道段(真相源在那裡,這裡只放指針)。
B. 與你既有鐵律直接打架的(照原稿走,第一天就會違規)
B1. §11.2.5「薄殼只裝 manifest 標記 shell-safe 的子集」— 🔴 這條我整條刪掉
- 這是舊薄殼模型的殘留,而且它會把你剛拆掉的病裝回去。
- 你 08-20 的原話是「同一個 plugin 你用,薄殼也用,保證兩邊同步」。
「只裝子集」= 兩邊不一樣 = 就是
InkStoneCo#57(薄殼少 7 支閘)那張票的成因本身。 - 原稿其他地方(P11.2.1「安裝同一個 release」、P11.2.4「整包替換禁止 cherry-pick」) 跟這條自相矛盾——它自己也知道不該有子集。
- 我怎麼改:刪除,並在修訂版明文寫「沒有子集,只有同一份」。
B2. §12.1 說 SDD 的寫入者是「人」、代理僅提案
- 現況相反:SDD 幾乎都是 AI 寫的,你是審的那個。照字面走,第一天就全面違規。
- 我怎麼改:改成「代理可寫,但範圍/驗收/非目標的變更必經人閘」—— 管的是哪些欄位需要你點頭,不是誰握筆。
B3. E9 留言 ≤600 字元、同票同 session >3 則就 reject
- 這條的方向是對的(推理進 wiki,留言只帶指標),但數字太緊,而且它懲罰誠實。
- 你 08-17 自己的診斷:文字層的閘那天 8 次誤攔、0 次正確攔截, 而且「紅線寫得越細,命中關鍵字的機率越高 ⇒ 那些閘在懲罰謹慎」。
- 我怎麼改:超長不 reject,改成擋下來並要求把長內容移去 wiki 再留指標; 則數上限拿掉(改用「同一張票同一 session 第 4 則起要先讀前 3 則」的提示,不是硬擋)。
B4. E13「s/review 佇列非空即 block 總管 stop」
- 這條會讓總管永遠停不下來:你在上課、沒人 merge,佇列就一直非空。
- 而且它跟現有的
empty-handed-stop-guard.sh(判準是「這回合有沒有 tool call」)疊在一起,兩支會互相踩。 - 我怎麼改:判準改成「有我自己開的
s/review,而這一回合我完全沒碰它」才擋—— 擋的是遺忘,不是擋等待。
B5. M4.3「Timebox 不可延長,到期強制關 milestone、搬票、打 tag」
- 對你的作息(上課日只有中午晚上各看一眼)這條會製造假交付: scope 縮到剩一張票也照樣打 tag,那個 tag 打開來沒東西。
- 而且它依賴排程 job,而我不確定有沒有 runner(見 C1)。
- 我怎麼改:到期不自動關、不自動打 tag,改成強制做一次「降 scope 對帳」並通知你; 打 tag 永遠是「驗過了」才發生的動作。
C. 技術可行性我實查過的
C1. 排程 job(E5/E8/E16/stale/digest)需要 Gitea Actions runner — 我還沒查有沒有
- 誠實標記:這格我沒驗。 我不知道這台 Gitea 有沒有掛 runner。
- 另外你的 D20 紅線「禁排程輪詢」管的是 GitHub(自架 Gitea 不受 flag 影響), 所以規則上不衝突,但能不能跑是另一回事。
- 我怎麼改:第一版所有 job 都做成
scripts/底下可手動跑、也可由 SessionStart hook 順手跑的東西, 不依賴 runner。等確認有 runner 再升級成排程。這樣壞掉的成本是「沒人跑」,不是「以為有人跑」。
C2. Gitea 1.26.4 支援 label exclusive — ✅ 查證過,可用
- 所以原稿 P11.4.5「
s/*與close/*一律 exclusive,非法狀態不可表示」成立,我照做了。 - 現有 10 個標籤全部
exclusive: false,這次會被改成 true。
C3. Gitea 有 issue dependency API — ✅ 查證過(/issues/{index}/dependencies)
- 所以 R2.5「順序關係用原生 dependency」可行。
C4. Gitea 沒有跨 repo 搬 issue 的 API — ❌ 查證過
- 只有 repo transfer,沒有 issue transfer。
- 影響:
InkStoneCo#40(forge-discipline 母規格)、#57、#14搬不到 ISEP。 - 我怎麼改:不搬,用互鏈。ISEP 的 hub 票
#1指回那三張。
D. 原稿沒寫、但非有不可的(你的需求 1–3 的核心)
D1. plugin 到底怎麼被載入 — 原稿整份沒提
- 你的需求是「雲端每次執行拉
github.com/youlinhsieh/inkstoneco, CC plugin 要把 loading 需要的放進去」。 - 原稿 §11 講的是「分發」(release、manifest、checksum), 完全沒講 Claude Code 這個 host 怎麼發現並掛載這個 plugin。
- 而這正是
InkStoneCo#14那張票的病根:Claude Code 只在 session 啟動當下讀一次 cwd 的.claude/。 - 我怎麼改:修訂版加一節「載入契約」,並且這件事另立
ISEP#5專票去做實測。
D2. 版本號的一致性沒有任何機制
- 原稿 §9 說「plugin 版本 = 規範版本」,但沒說怎麼保證。
- 而今天就出事了:README 宣稱 0.1.0、
plugin.json寫 0.1.0、Gitea 上 release 數 = 0。 - 我怎麼改:修訂版把 E12 改寫成「版本三處一致」的閘(
plugin.json/ tag / release 存在), 並把「release note 寫在 release 裡、不寫 README」寫進規範(你 08-20 的原話)。另立ISEP#6。
D3. ISEP 是 private repo,雲端拿不到就什麼都不用談
- 原稿沒提憑證。這是整條線最可能默默失敗的一格。
- 修訂版寫進「載入契約」,實作走既有 credential 機制(D36:只拿名字不碰值)。
E. 兩個裁決題(我先按自己的判斷做了,你打回我就改)
E1. E1「PR-only,禁止直接 push 預設分支」要不要套到所有 repo?
- 衝突點:你的 CLAUDE.md 明寫「總管推 main 自己裁(但要逐筆看過那些 commit)」, 原稿要求全部走 PR。兩者不能同時成立。
- 我的判斷:只有 ISEP 這個 repo 走 PR-only,其他 repo 維持現行。
- 理由:ISEP 是所有環境的唯一真相源,它壞掉是所有 session 一起壞—— 這個 repo 值得多一道摩擦。其他 repo 壞掉只影響自己。
- 一刀切到 14 個 repo 會在你最忙的時候把整條線卡在「等總管開 PR」。
- 這題命中四題公式的「跨專案結構」,所以我標成裁決題寫在這裡; 但照你 08-17 的規矩(不確定 → 假設 → 記錄 → 繼續走),我不停下來等。
E2. 現有 duplicate 標籤要不要被 close/duplicate 取代?
- 我的判斷:新的照建,舊的不刪只封存(
is_archived)。 - 理由:刪標籤會把它從所有歷史票上摘掉——那是不可逆的,而且會讓舊票的關閉理由憑空消失。
附:我沒動的東西(原稿寫得比我好的)
- §1 物件模型的那張圖與職責表——直接沿用
- §5 關閉分類 taxonomy(七種
close/*)——名稱與語意全部沿用 - §7 討論路由的那棵決策樹——沿用
- §10.1「OP 是票的唯一狀態容器,留言是 append-only 的 delta」——沿用,這條解掉了「一張票要讀 40 則留言才知道現況」
- §12.4 單向依賴(Wiki 壞不影響 Gitea,Gitea 壞不影響 SDD,通知丟不影響一切)——沿用