# 我改了 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 個 - 現有:`Human` `duplicate` `p/high` `p/low` `s/backlog` `s/doing` `s/pending` `s/stage` `s/todo` `s/triage` - 原稿要的 `gate/human` `s/review` `close/*` `hub` `type/*`——**一個都不存在** - 為什麼會這樣: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. ~~PR-only 要不要套到所有 repo?~~ 🔴 **已被 leo 2026-08-20 推翻:全部 repo、全部角色一律 PR-only(見規範 §8.1)。下面是當時的提案,保留作歷史。** #### 原提案 - **衝突點**:你的 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,通知丟不影響一切)——沿用