Files
ISEP/docs/governance/DIVERGENCE-v0.5.0-to-v0.6.0.md
Leo e16d21435f v0.9.0:全面 PR-only(leo 裁定)+跨 repo 群票載體入規範
leo 2026-08-20:「所有 subagent 都是 PR only,在雲端地端總管所做的都是 PR-only。」
⇒ 推翻總管原提案(只有 ISEP 走 PR-only,其他 repo 總管自裁)。
   DIVERGENCE §E1 已加註被推翻,原文保留作歷史。
⇒ main-and-prod-push-guard.sh 現行判準只擋 subagent、放行總管,與本條不符,
   要改成不分角色一律擋;/tmp/.main-push-ok 戳記隨之作廢(PR review 就是那道確認)。排群 4。

另 §15.5:六個群在 ISEP 各有一張 hub 票(#30-#35),別的 repo 的舊票用 Gitea 原生
dependency 指過去(跨 repo dependency 已實測 201 可用)——milestone 管不到跨 repo,這是載體。
2026-08-20 17:55:35 +08:00

221 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 我改了 claude.ai 那版的哪些地方,為什麼
> leo 2026-08-20 交辦:「你查看是否合理,提出意見,因為這個是計劃,
> 有些已經有、有些還沒有、有些有了不符合⋯⋯則你要改一版你的版本。」
>
> 本檔是**我的意見書**。原稿存檔在 `_draft-claude-ai-v0.5.0.md`
> 修訂後的現行規範是 `sdd-gitea-governance.md`v0.6.0)。
---
## 先講結論
- **骨架是對的,照單全收**
- 物件模型(SDD → tracking → leaf → PR → releasemilestone 橫切當 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. E1E16 的 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. 排程 jobE5E8E16staledigest)需要 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,通知丟不影響一切)——沿用