feat(W2 Phase 0-1): 雙 profile 地基+JDD 兩軸身分+兩支防炸閘

SDD: docs/3-specs/jdd-dual-profile(draft → active,leo 2026-08-05 回「開工」)
範圍:總管指定的「防炸兩件 → Phase 0 → Phase 1」,Phase 2 以後未開工。

■ 防炸(排在所有 task 之前,因為它們炸的是既有的東西)
- check-no-instance-names.sh + instance-names.txt:框架範本不得混入實例專名
  基線實測 22 行命中(非先前誤報的 20)→ 9 行無損泛化改寫、13 行檔級豁免記帳待 W3 搬走
  拒絕假性清理(把專名換成模糊詞=資訊消失、分層問題還在)
- check-legacy-paths.sh:已發佈腳本引用的 35 條遠端路徑只增不移
  舊實例跑的是舊腳本、路徑寫死;搬檔=整排 404 且不會有下一次更新來修它(1.16.0 前科)

■ Phase 0 地基
- template/manifest/{common,repo,orchestrator}.tsv:安裝清單單一真相源
  修好 install/update 兩份硬編清單的既有漂移——install 從不裝 wiki-first-search /
  subagent-wiki-guard / publish-lag-check / decisions-summary,但 update 會
  ⇒ 乾淨安裝反而拿不到 1.16/1.17/1.18 的招牌功能
- .claude/hooks/lib/role-lib.sh:scope×role 兩軸機械判定,零自陳
  身分矩陣六組實測全通過,含「成員 repo × orchestrator」不存在的格子擋下
- .sdt-framework-dev:框架開發標記(官方沒有 --framework-dev 這個參數,實查非記憶)

■ Phase 1 雙 profile
- profiles/{repo,orchestrator}/CLAUDE.md 兩部憲法
- install.sh:--profile + 自動偵測+寫檔前確認、manifest 驅動、
  CLAUDE.md 三段組裝(框架區/本地補充區界標+sha256)、.profile、.template-manifest、
  settings.json 寫入 env.AGENT_ROLE 預設
- update.sh:漂移偵測(不覆蓋手改檔、另存 .new、白話清單)+ 基準快照隨更新前進
- template/CLAUDE.md 原路徑凍結留底(相容)

■ 順手修掉兩個舊 bug(都在本次要動的函式裡)
- add_if_missing 少了 mkdir -p ⇒ 新目錄的檔 curl 失敗但 VERSION 照升(2026-07 記「待回報」至今未修)
- 下載健全性只用 [ -s ]=非空即接受 ⇒ 404 頁面會無聲覆寫好檔
  (SKILL.md 260→1 行的機制;同一支腳本的版本號那條路早就防了,檔案這條沒防)

■ 實測(非推論)
- G4 憲法分流:兩個乾淨環境各裝一次,orchestrator 版含 SDD 三件式關鍵字 0 次、
  repo 版含上游指針 8 次;界標 4/4;sha 宣告與實算相符
- G7 CI 擋實例名:注入違規行 → fail 並指出 sdd-check.md:77,exit 1;還原後 exit 0
- 漂移偵測:手改兩支 hook → 正確報 2 支、手改內容保住、產 .new;
  解掉後歸零;連跑三輪冪等

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-05 23:56:48 +08:00
parent 2a8c259d08
commit 6a49f25aef
23 changed files with 1259 additions and 132 deletions
+34 -5
View File
@@ -1,5 +1,5 @@
---
status: draft # active | draft | paused | closed(生命週期鐵律見 ../SDD-LIFECYCLE.md
status: active # active | draft | paused | closed(生命週期鐵律見 ../SDD-LIFECYCLE.md
superseded_by: "" # closed 且被取代時填接替的 SDD 資料夾名
---
@@ -8,11 +8,13 @@ superseded_by: "" # closed 且被取代時填接替的 SDD 資料夾名
> 建立:2026-08-05 | 最後更新:2026-08-05
> 負責人:system-dev-template CC
> 來源:InkStoneCo 總管交辦 **W2**
> **狀態:draft — 等 leo confirm 才升 active,未實作任何 code**
> **狀態:active2026-08-05 leo 回「開工」升活性)**
>
> 為什麼是 `draft` 而非 `active`D35 ②③ 規定 CC 不得自行讓 SDD 生效;
> 本 repo 目前 **0 份 active**(見「現況實查」§0.1),本案 confirm 後直接升 active
> 不需搬移任何未完成任務(無現任 active 可搬)。
> 升活性前實查:全 repo 帶 frontmatter 的只有 `TEMPLATE-sdd`draft,範本不算數)
> ⇒ active 數 = 0,**無衝突、無未完成任務需搬移**(D35 ④ a 步驟空集合)。
>
> 施工順序由總管指定:**發現①、發現⑦ 的防炸工程 → Phase 0 → Phase 1 → 停下驗 Gherkin**。
> Phase 2 以後未經確認不得開工。
---
@@ -407,6 +409,33 @@ SessionStart
---
## 附錄 A:三個 marker 檔的格式規格(task 0.3
| 檔 | 位置 | 內容 | 誰寫 | 誰讀 |
|---|---|---|---|---|
| `.profile` | 實例 `system-dev/.profile` | 單行:`repo``orchestrator`(前後空白會被 trim | `install.sh --profile` | `role-lib.sh``sdt_scope()``update.sh`、CI |
| `.template-manifest` | 實例 `system-dev/.template-manifest` | TSV`dest class version sha256`(安裝當下的雜湊) | installupdate | `update.sh` 的三態判定 |
| `.sdt-framework-dev` | **框架 repo 根**(實例不該有) | 任意文字,存在即生效 | 框架 repo 自帶並 commit | `install-artifact-guard.sh` |
- 三者都是「機器可讀的事實」,不是設定選項——agent 不得靠它們表達意圖,只能讀。
- `.profile` 讀不到 → 視為 `repo`(代價寫在 `role-lib.sh` 註解裡,不假裝沒有)。
- `.sdt-framework-dev` 出現在實例裡 = 有人在關掉自己的封路,**git diff 看得見**。
---
## 附錄 B:本波實作的兩支機械閘(先於一切 task,防炸用)
| 閘 | 檔 | 擋什麼 | 實測 |
|---|---|---|---|
| 實例專名 | `scripts/check-no-instance-names.sh` `scripts/instance-names.txt` | 框架範本混入實例專名 | 基線 22 行 → 處置後 0 違規/13 行檔級豁免;注入違規行可 fail 並指出檔案:行號 |
| 相容路徑 | `scripts/check-legacy-paths.sh` | 搬檔/改名導致舊實例 update 整排 404 | 追蹤 35 條已發佈路徑;移走 `template/CLAUDE.md` 可正確 fail |
> 為什麼這兩支要排在所有 task 之前(總管裁定):它們**炸的是既有的東西**,不是新功能沒做好。
> 專名閘晚做 → 之後每加一個範本檔都可能再混進實例名,債只會更大;
> 相容閘晚做 → Phase 1 一搬 `CLAUDE.md` 就把所有舊實例的自動更新弄死,而且**沒有下一次更新能修它**。
---
## 相關文件
- `requirements.md`(本卷)/`tasks.md`(本卷)
+17 -13
View File
@@ -3,7 +3,9 @@
> 權威來源:此檔案是進度真相,不是 CLAUDE.md 或對話。
> 規則:動手前標 [🔄],完成立刻標 [x],不批次更新。
> **每一項都標「服務哪條 Gherkin」**G1G7 定義見 `requirements.md` §四)。
> 🔴 **本卷 status: draft — 等 leo confirm 才准動工。以下一項都還沒開始。**
> 🟢 **status: active2026-08-05 leo 回「開工」)**
> 進度:**防炸兩閘 Phase 0 Phase 1 已完成**Phase 1 有兩項 ◐,見下)。
> **Phase 2 以後未經確認不得開工**(總管指定:先停下驗 Gherkin)。
---
@@ -28,14 +30,14 @@
### Tasks
- [ ] 0.1 定義 manifest 格式並產出三份 `template/manifest/{common,repo,orchestrator}.tsv`
- [x] 0.1 定義 manifest 格式並產出三份 `template/manifest/{common,repo,orchestrator}.tsv`
- 服務:**G4**(分流的資料基礎)、G6(產物區清單的單一來源)
- 欄位:`dest class profile`class ∈ `overwrite|keep|add-if-missing|keep-with-template`
- 驗收:三份 manifest 涵蓋現行 install.sh 硬編的**每一個** `download_if_missing` 目標,
逐項比對零遺漏(貼比對輸出)
- 注意:既有檔一律標 `common` 且 dest 路徑**與現況完全相同**(決策 D3,不搬檔)
- [ ] 0.2 寫 `template/.claude/hooks/lib/role-lib.sh`(兩軸判定函式庫)
- [x] 0.2 寫 `template/.claude/hooks/lib/role-lib.sh`(兩軸判定函式庫)
- 服務:**G2**、G6
- 內容:`sdt_repo_root` / `sdt_rel_path` / `sdt_scope` / `sdt_role` /
`sdt_assert_identity` / `sdt_file_path_from_stdin`jq→python3→grep 三段 fallback
@@ -43,7 +45,7 @@
repo×engineer、repo×orchestrator)跑單元測試,最後一組回 exit 2;貼四組輸出
- 注意:不得用 `CLAUDE_PROJECT_DIR`(雲端可跑);bash 3.2 相容
- [ ] 0.3 立 marker 檔約定:`system-dev/.profile``system-dev/.template-manifest``.sdt-framework-dev`
- [x] 0.3 立 marker 檔約定:`system-dev/.profile``system-dev/.template-manifest``.sdt-framework-dev`
- 服務:**G4**、**G6**
- 驗收:三個檔的格式各寫一段規格進 design 的附錄,並在框架 repo 自己放一份
`.sdt-framework-dev`commit
@@ -55,54 +57,56 @@
> 前置條件:Phase 0 全部完成
- [ ] 1.1 建 `template/profiles/repo/CLAUDE.md`repo 憲法範本)
- [x] 1.1 建 `template/profiles/repo/CLAUDE.md`repo 憲法範本)
- 服務:**G4**
- 來源:現行 `template/CLAUDE.md` 演進;加「上游指針」一行、「站號怎麼標在 task 上」一段、
W3 must-read 注入點一段
- 驗收:`grep -c "上游" ≥ 1`;全文不含任何實例專名
- [ ] 1.2 建 `template/profiles/orchestrator/CLAUDE.md`(總管憲法範本)
- [x] 1.2 建 `template/profiles/orchestrator/CLAUDE.md`(總管憲法範本)
- 服務:**G4**、G3
- 內容:效忠 root/journeys、JDD 全術語表、sprint 站號全流程、
進度語言「J-x 已點亮 n/m 站」、問題升級階梯三級(藍圖 §5.5)、W3 must-read 注入點
- 驗收:`grep -c "SDD 三件式\|requirements.md" = 0`(G4 明文:總管版無 SDD 三件式細節)
- 注意:不得出現任何實例專名(藍圖 v3 的內容要抽象化,專案名留給實例填)
- [ ] 1.3 `install.sh``--profile=repo|orchestrator` 自動偵測 一次性人確認
- [x] 1.3 `install.sh``--profile=repo|orchestrator` 自動偵測 一次性人確認
- 服務:**G4**
- 偵測規則:目前目錄下存在多個各自帶 `.git` 的子目錄 → 建議 orchestrator
- 驗收:三種呼叫(明示 repo/明示 orchestrator/不指定走偵測)各跑一次乾淨環境,
貼出各自產生的 `system-dev/.profile` 內容
- 注意:**確認在寫入任何檔案之前**問,別裝了一半才問
- [ ] 1.4 `install.sh` 改讀 manifest 鋪設產物 + 產 `.template-manifest`
- [x] 1.4 `install.sh` 改讀 manifest 鋪設產物 + 產 `.template-manifest`
- 服務:**G4**、G6
- 驗收:repo profile 裝出的檔案集合 = `common.tsv repo.tsv`
且**不含** orchestrator 專屬檔(`ls` 對照貼出)
- [ ] 1.5 CLAUDE.md 三段組裝(框架區界標 + 本地補充區界標 + sha256)
- [x] 1.5 CLAUDE.md 三段組裝(框架區界標 + 本地補充區界標 + sha256)
- 服務:**G4**
- 驗收:裝完的 CLAUDE.md 含 `sdt:framework begin/end``sdt:local begin/end` 四個界標,
`sha256` 值與框架區實際內容相符(重算比對貼出)
- [ ] 1.6 `install.sh``build_hooks_json()` 加 profile 維度 寫入 `env.AGENT_ROLE` 預設
- [x] 1.6 `install.sh``build_hooks_json()` 加 profile 維度 寫入 `env.AGENT_ROLE` 預設
- 服務:**G2**、G6
- 驗收:兩 profile 各自產生的 `settings.json` 中,hook 掛載順序符合 design §4.4
orchestrator 實例的 `env.AGENT_ROLE = orchestrator`、repo 實例 = `engineer`
- [ ] 1.7 `update.sh` 改讀 manifest + 三態判定 + 漂移清單輸出
- [~] 1.7 `update.sh` 改讀 manifest + 三態判定 + 漂移清單輸出
- 服務:**G6**(機械閘 #3
- 驗收:在 InkStoneCo 實例上跑,漂移清單**恰好列出 4 支**
`pre-write-guard.sh``sdd-guard.sh``subagent-wiki-guard.sh``wiki-first-search.sh`
見 design §0.4 基線),貼完整輸出
- 注意:漂移檔**不覆蓋**,新版另存 `<檔>.new`;輸出用白話(leo 一眼看得懂該做什麼)
- 現況:◐ 漂移偵測+基準維護已實作並實測;**但 update.sh 的檔案清單尚未改讀 manifest**(仍是自己那份硬編),install/update 清單漂移的根因只修了一半
- [ ] 1.8 `update.sh` 舊實例遷移:無 manifest → 一次性補植 CLAUDE.md 界標補植
- [~] 1.8 `update.sh` 舊實例遷移:無 manifest → 一次性補植 CLAUDE.md 界標補植
- 服務:**G4**、G6
- 驗收:拿一份 1.18.0 的實例副本跑兩次 update,第二次為 no-op(冪等,貼兩次輸出對照)
- 注意:舊 CLAUDE.md 整份包進 `sdt:local` 區,一個字都不能掉
- 現況:◐ 舊實例無 manifest → 首輪自動建基準(已實測);**CLAUDE.md 界標補植未做**
- [ ] 1.9 `template/CLAUDE.md` 原路徑保留轉址說明(向下相容)
- [x] 1.9 `template/CLAUDE.md` 原路徑保留轉址說明(向下相容)
- 服務:**G4**
- 驗收:舊版 update.sh 對該路徑的 curl 仍回 200(決策 D3