@@ -1,7 +1,7 @@
# SDD × Gitea 治理規範
```
version: 0.8 .0
version: 0.10 .0
status: 現行(本檔的修改依 §9 走 issue)
scope: 所有安裝 ISEP 的環境(本機 CC 與雲端 CC)
distribution: 隨 ISEP 發佈,ISEP repo 是唯一編輯點(§11)
@@ -11,6 +11,10 @@ lineage: v0.5.0 draft by claude.ai(存檔 _draft-claude-ai-v0.5.0.md)
依 leo 指正:規劃不另立文件,修正本檔就是新版
→ v0.8.0 三源整合定案(§15):claude.ai 兩份規劃 × 舊票需求 × 既有機制,
逐領域對照、三處矛盾解法、動工順序——leo 2026-08-20 核准
→ v0.9.0 leo 裁定全面 PR-only(§8.1):所有 subagent、地端與雲端總管一律走 PR,
推翻總管原本「只有 ISEP 走 PR-only」的提案
→ v0.10.0 M4.0 補上「里程碑怎麼組成」(目標→遍歷票池→缺口才補票→定下不改);
M4.3 改寫成「定下就不改,尤其不准因為做不完而打折」——leo 2026-08-20 訂正
```
---
@@ -123,12 +127,34 @@ s/triage ──驗傷通過──▶ s/backlog ──排進 milestone──▶ s
## 4. Milestone 規則(= sprint = 可測試版本)
- **M4.1** 命名 `vX.Y` ,必設 due date。
- **M4.0(怎麼組成一個 milestone) ** 🔴 **順序是:leo 給目標 → 遍歷票池找出「達成它需要哪些票」→
池裡沒有的才補開 → 定下,之後不改。**
```
leo 說要達成什麼
↓
總管遍歷 issues 池(跨 repo),找出達成這個目標需要關掉哪些票
↓
某一塊沒有票承接 ⇒ 那才是真缺口 ⇒ 補開一張(不是在里程碑裡編任務)
↓
組成定下 ← 從這裡開始,內容不再變動
` ``
- **不是**「總管想做什麼就放什麼」,也**不是**「先訂五件事再看做得完幾件」。
- 里程碑的名字寫**這個里程碑在做什麼事**,不是版本號(leo 2026-08-20)。
- **M4.1** 必設 due date。
- **M4.2** Deliverable = **一個可測的新版本號**。所有掛入 leaf 關閉後,可從預設分支打出通過驗收的版本。
- **M4.3** **Timebox 到期:不自動關、不自動打 tag、也不把票移出。 ** 到期只做一件事:通知 leo。
🔴 **里程碑的內容一經確定就不增不減 ** ( leo 2026-08-20:「milestone 確定後怎麼可以再把東西移除?
定下工作自己刪掉是什麼意思?根本就沒有什麼降」)。增減都是 leo 的裁決,不是總管的操作。
自動打 tag 會製造假交付——tag 永遠只在「驗過了」之後發生。
- **M4.3(定下就不改,尤其不准打折)** 🔴 **組成一經定下,不因為做不完而縮減。**
> leo 2026-08-20:「**milestone 確定後怎麼可以再把東西移除?定下工作自己刪掉是什麼意思?
> 根本就沒有什麼降**⋯⋯而不是要做 5 件事,做不到就改成 2 件,**自己打折**。」
- **Timebox 到期:不自動關、不自動打 tag、不把票移出。** 到期只做一件事:通知 leo。
- 做不完就是**還沒完成**,里程碑保持開著,百分比就顯示真實的完成度——
那個數字本來就是要拿來看「還差多少」的。把分母改小只是讓它說謊。
- 自動打 tag 會製造假交付——tag 永遠只在「驗過了」之後發生。
- ⚠️ 唯一的例外是**目標本身變了**(leo 改了要達成什麼)⇒ 那是重新走一次 M4.0,不是打折。
- **M4.4** Milestone 關閉 = release tag,一對一。「已交付」唯一合法形式是 **tag 存在且裝得起來**;打 tag 前置 open issues = 0(§8 E12)。
- **M4.5** Description 只寫版本目標一句 + tracking 連結。討論回 tracking issue。
- **M4.6** 🔴 **release note 寫在 Gitea Releases 裡,不寫在 README。**( leo 2026-08-20:「release 不是寫在 readme,要放在 release 裡」)
@@ -237,7 +263,7 @@ s/triage ──驗傷通過──▶ s/backlog ──排進 milestone──▶ s
| # | 封什麼路 | 用什麼封 | 現況 |
|---|---|---|---|
| E1 | 直接 push 預設分支 | branch protection: PR-only | ◐ 現有 `main-and-prod-push-guard.sh` 語意相反( 擋 subagent、放行總管)。**本版只對 ISEP 開 PR-only**,見 §8.1 |
| E1 | 直接 push 預設分支 | branch protection: PR-only,**全部 repo、全部角色**(§8.1) | ◐ 現有 ` main-and-prod-push-guard.sh` 只 擋 subagent、放行總管 ⇒ **與本條不符,要改**:總管與雲端一律同擋 |
| E2 | PR 不關聯 issue | PR 模板必含 ` closes #`,缺漏即 fail | ❌ 待建 |
| E3 | 手動關 leaf | hook 攔截;只放行 ` close/*` 與 §6.2 人執路徑 | ❌ 待建 |
| E4 | 被 block 的票先關 | Gitea issue dependency | ✅ 平台原生,已驗證可用 |
@@ -254,13 +280,24 @@ s/triage ──驗傷通過──▶ s/backlog ──排進 milestone──▶ s
| E15 | 代理硬做只有人能做的事 | 代理端無對應 tool 或 token;唯一出口是開 ` human/exec` 票 | ◐ 部分(credential 機制已擋一部分,D36) |
| E16 | 標籤漂移 | 走 Gitea labels API 依 ` labels.yaml` 校正:缺的補、改的還原、多的**只告警不刪** | ❌ 待建(` ISEP#4 `) |
### 8.1 E1 的適用範圍(裁決記錄 )
### 8.1 E1 的適用範圍:**全部 repo、全部角色,一律 PR-only**( leo 2026-08-20 裁定 )
**只 有 ISEP 走 PR- only;其他 repo 維持現行「總管推 main 自己裁」。 **
> leo 原話:「 **所 有 subagent 都是 PR only,在雲端地端總管所做的都是 PR-only。**」
- 理由:ISEP 壞掉 = **所有 session 一起壞 ** ,值得多一道摩擦;其他 repo 壞掉只影響自己。
- 一刀切到 14 個 repo 會在 leo 最忙的時候把整條線卡在「等總管開 PR」。
- 這條命中四題公式的「跨專案結構」⇒ 已記為裁決題(`DIVERGENCE` §E1),leo 可打回。
` ``
subagent(地端/雲端) → 只能推自己的分支,開 PR ← 擋
總管 (地端/雲端) → 只能推自己的分支,開 PR ← 擋
leo → 他自己的操作不在此限
` ``
🔴 **沒有例外,不分 repo。** 這條推翻了總管原本的判斷(原提案:只有 ISEP 走 PR-only,
其他 repo 維持「總管推 main 自己裁」,理由是怕卡住 leo)。
leo 直接裁定全面適用——**歷史紀錄留在 ` DIVERGENCE-v0.5.0-to-v0.6.0.md` §E1,該段已被本條推翻。**
**因此要改的**: ` main-and-prod-push-guard.sh` 目前的判準是
「` CLAUDE_CODE_CHILD_SESSION=1` 才擋」⇒ 只擋 subagent、放行總管,**與本條不符**。
改成不分角色一律擋推預設分支;` /tmp/.main-push-ok` 那套「總管看過」的戳記機制隨之作廢
(PR 的 review 就是那道確認,不需要第二套)。排在群 4「派工與交付紀律」。
### 8.2 所有 job 第一版都不依賴 Gitea Actions runner
@@ -589,7 +626,7 @@ leo 08-17 診斷見公理 3; 08-17 實測:文字層的閘 **8 次誤攔、0
### 15.2 工作順序(六個里程碑,各 repo 同名,內容一經確定不增不減)
| 順 | 里程碑 | 來源票 |
| 順 | 里程碑 | 來源票(由目標遍歷票池而來,M4.0) |
|---|---|---|
| 0 | 讓閘擋對東西 | ` InkStoneCo#56 #23 #22 #36 #55 #1 ` |
| 1 | 讓規則的效果看得見 | ` InkStoneCo#48 #17 #20 #18 `、` Arcrun#86 #142 #81 ` |
@@ -598,6 +635,8 @@ leo 08-17 診斷見公理 3; 08-17 實測:文字層的閘 **8 次誤攔、0
| 4 | 派工與交付紀律 | ` InkStoneCo#12 #28 `、` arcrun-rag#47 #124 `、` Arcrun#93 #143 #131 `、` system-dev-template#7 ` |
| 5 | 票與文件歸位 | ` InkStoneCo#9 #49 #10 #8 #5 `、` system-dev-template#1 #4 ` |
這六群的組成是照 M4.0 走出來的:leo 給的目標是「把管理這條線做對」,
總管遍歷 14 repo/ 156 張 open 票,挑出 44 張達成它需要關掉的,**沒有補開任何新任務票**。
排序判準=「什麼擋住什麼」:閘不修好,其他群的成果會被誤攔咬到;沒有留痕,修了也量不出變好。
` #40 ` 是憲法,貫穿全部;` #48 ` 是 ` #40 ` warn 校準的資料前提,所以排群 1 之首。
@@ -614,6 +653,15 @@ leo 08-17 診斷見公理 3; 08-17 實測:文字層的閘 **8 次誤攔、0
` #37 ` 兩份 repo 哪份為準(建議 ` inkstone/*`)/` #5 ` ` #8 ` 轉 hub 或作廢/
08-20 兩支未經 warn 期的 block 閘,隨盤點表(` docs/hooks-inventory.md`)一起審。
**已裁**: PR-only 全面適用(§8.1, 2026-08-20)。
### 15.5 跨 repo 的載體:ISEP 的六張群票
Gitea 的 milestone 只管得到同一個 repo,所以六個群在 ` inkstone/ISEP` 各有一張 ` hub` 票
( ` ISEP#30 `– ` #35 `),別的 repo 的舊票用 **Gitea 原生 dependency** 指到它
( leo 2026-08-20;跨 repo dependency 已實測可用)。
⇒ **群票的相依全關,群票才關得掉**;六張群票的狀態就是六群的進度。
---
## 附:Label 全集(快照;唯一真相為 ` labels.yaml`)