593defceb1
SDD: docs/3-specs/jdd-dual-profile — 33/33 編號 task 全數完成。 ■ Phase 4 把閘掛上去 - scripts/check-all.sh:三道閘+腳本語法的總入口(一個習慣,不是三個要記得的步驟) - .githooks/pre-commit + core.hooksPath:跑在人的機器上、commit 那一刻 不掛雲端 workflow——本組織禁止 repo 掛自動化(歷史上那正是帳號被停權的原因) ■ Phase 5 出貨 - VERSION 1.18.0 → 1.19.0(兩處:template/.claude/ 與 template/system-dev/) - CHANGELOG 1.19.0:用「你會多出什麼」的語言寫,不列檔名 - 🐛 順手補回 **1.18.0 完全沒有 changelog 紀錄**這件事—— 那一版發佈了、功能也出貨了,但更新跑完最後一行正是叫使用者「改了什麼看 CHANGELOG」, 版號動了卻查不到動了什麼=等於沒交代。依實際 commit 內容補寫。 ■ 七題驗收(全部附實測輸出) - ✅ G2 考生改考卷被攔(命門):engineer 改 journeys.md → exit 2; 連「把考題藏進 status.md」也擋,6/6 - ✅ G3 進度以站計量:起牀推「J-1 已點亮 n/m 站」,收工列未亮站並禁用任務數當理由 - ✅ G4 憲法分流:總管版技術軌關鍵字 0、成員版上游指針 8,界標各 4/4 - ✅ G6 實例改機制被攔:4/4(框架開發放行、使用者自訂插槽放行) - ✅ G7 框架混入實例名:指名 sdd-check.md:77,exit 1 - ◐ G1 PM 優先補接縫:機制齊了,但這是行為題,腳本證明不了 → 不標綠 - ◐ G5 政策包即插即用:插槽就位,政策包本體在 W3 ■ 安裝實測:兩個乾淨環境各 1 秒、48/54 檔、版本 1.19.0、profile 正確 (預測①「各 < 10 分鐘」達標;誠實註記:來源走本機檔案,比真實網路快) 🔴 狀態=**等發佈**,不是 ✅:更新來源是公開 GitHub raw, 只推 Gitea 的話外部實例抓不到 1.19.0。開閘由 leo 決定。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
290 lines
15 KiB
Markdown
290 lines
15 KiB
Markdown
# jdd-dual-profile — Tasks
|
||
|
||
> 權威來源:此檔案是進度真相,不是 CLAUDE.md 或對話。
|
||
> 規則:動手前標 [🔄],完成立刻標 [x],不批次更新。
|
||
> **每一項都標「服務哪條 Gherkin」**(G1–G7 定義見 `requirements.md` §四)。
|
||
> 🟢 **status: active(2026-08-05 leo 回「開工」)**。
|
||
> 進度:**33/33 編號 task 全數完成**(2026-08-06)。版本 1.18.0 → **1.19.0**。
|
||
> 七題驗收:**✅ 5 題(G2/G3/G4/G6/G7,皆附實測輸出)/◐ 2 題**——
|
||
> G1 是行為題(要真的派一次工才驗得到)、G5 的政策包本體在 W3。
|
||
> 🔴 **狀態=等發佈**:更新來源是公開 GitHub raw,需 leo 開閘才送得到外部實例。
|
||
|
||
---
|
||
|
||
## Gherkin 對照速查
|
||
|
||
| 號 | 一句話 | 來源 |
|
||
|---|---|---|
|
||
| G1 | PM 總管優先補接縫而非做新功能 | JDD §七 |
|
||
| G2 | 考生改考卷被攔截 | JDD §七 |
|
||
| G3 | 進度以站計量 | JDD §七 |
|
||
| G4 | 憲法分流不靠判斷 | 分離 §七 |
|
||
| G5 | 政策包即插即用(本波只到 ◐ 半通) | 分離 §七 |
|
||
| G6 | 實例改機制被攔 | 分離 §七 |
|
||
| G7 | 框架混入實例名被 CI 擋 | 分離 §七 |
|
||
|
||
---
|
||
|
||
## Phase 0:地基(manifest + 兩軸判定)
|
||
|
||
### 前置條件
|
||
- [ ] leo confirm 本 SDD,frontmatter 由 `draft` 改 `active`
|
||
|
||
### Tasks
|
||
|
||
- [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,不搬檔)
|
||
|
||
- [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)
|
||
- 驗收:以四組身分(orchestrator×orchestrator、orchestrator×engineer、
|
||
repo×engineer、repo×orchestrator)跑單元測試,最後一組回 exit 2;貼四組輸出
|
||
- 注意:不得用 `CLAUDE_PROJECT_DIR`(雲端可跑);bash 3.2 相容
|
||
|
||
- [x] 0.3 立 marker 檔約定:`system-dev/.profile`、`system-dev/.template-manifest`、`.sdt-framework-dev`
|
||
- 服務:**G4**、**G6**
|
||
- 驗收:三個檔的格式各寫一段規格進 design 的附錄,並在框架 repo 自己放一份
|
||
`.sdt-framework-dev`(commit)
|
||
- 注意:`--framework-dev` 不是官方 CLI flag(決策 D9),別去找那個參數
|
||
|
||
---
|
||
|
||
## Phase 1:雙 profile 與 CLAUDE.md 生成
|
||
|
||
> 前置條件:Phase 0 全部完成
|
||
|
||
- [x] 1.1 建 `template/profiles/repo/CLAUDE.md`(repo 憲法範本)
|
||
- 服務:**G4**
|
||
- 來源:現行 `template/CLAUDE.md` 演進;加「上游指針」一行、「站號怎麼標在 task 上」一段、
|
||
W3 must-read 注入點一段
|
||
- 驗收:`grep -c "上游" ≥ 1`;全文不含任何實例專名
|
||
|
||
- [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 的內容要抽象化,專案名留給實例填)
|
||
|
||
- [x] 1.3 `install.sh` 加 `--profile=repo|orchestrator` + 自動偵測 + 一次性人確認
|
||
- 服務:**G4**
|
||
- 偵測規則:目前目錄下存在多個各自帶 `.git` 的子目錄 → 建議 orchestrator
|
||
- 驗收:三種呼叫(明示 repo/明示 orchestrator/不指定走偵測)各跑一次乾淨環境,
|
||
貼出各自產生的 `system-dev/.profile` 內容
|
||
- 注意:**確認在寫入任何檔案之前**問,別裝了一半才問
|
||
|
||
- [x] 1.4 `install.sh` 改讀 manifest 鋪設產物 + 產 `.template-manifest`
|
||
- 服務:**G4**、G6
|
||
- 驗收:repo profile 裝出的檔案集合 = `common.tsv ∪ repo.tsv`,
|
||
且**不含** orchestrator 專屬檔(`ls` 對照貼出)
|
||
|
||
- [x] 1.5 CLAUDE.md 三段組裝(框架區界標 + 本地補充區界標 + sha256)
|
||
- 服務:**G4**
|
||
- 驗收:裝完的 CLAUDE.md 含 `sdt:framework begin/end` 與 `sdt:local begin/end` 四個界標,
|
||
且 `sha256` 值與框架區實際內容相符(重算比對貼出)
|
||
|
||
- [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`
|
||
|
||
- [x] 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 一眼看得懂該做什麼)
|
||
- 2026-08-06 還清:update.sh 檔案清單已改讀 manifest(舊硬編清單降為抓不到來源時的 fallback),根因全修
|
||
|
||
- [x] 1.8 `update.sh` 舊實例遷移:無 manifest → 一次性補植 + CLAUDE.md 界標補植
|
||
- 服務:**G4**、G6
|
||
- 驗收:拿一份 1.18.0 的實例副本跑兩次 update,第二次為 no-op(冪等,貼兩次輸出對照)
|
||
- 注意:舊 CLAUDE.md 整份包進 `sdt:local` 區,一個字都不能掉
|
||
- 2026-08-06 還清:界標補植已實作並實測(舊全文原封包進本地區、原檔備份、冪等)
|
||
|
||
- [x] 1.9 `template/CLAUDE.md` 原路徑保留轉址說明(向下相容)
|
||
- 服務:**G4**
|
||
- 驗收:舊版 update.sh 對該路徑的 curl 仍回 200(決策 D3)
|
||
|
||
---
|
||
|
||
## Phase 2:JDD 文件範本(orchestrator profile)
|
||
|
||
> 前置條件:Phase 1 完成(範本要靠 manifest 才鋪得下去)
|
||
|
||
- [x] 2.1 `docs/root.md.template`(白話根文件範本)
|
||
- 服務:**G1**
|
||
- 內容:JDD §3.1 格式原樣 + 三條規則(來源標記必附、禁技術名詞、🔴 卡必附對帳日)
|
||
- 驗收:範本自身通得過 task 3.2 的 J4/J8 檢查(自己吃自己狗糧)
|
||
|
||
- [x] 2.2 `docs/journeys.md.template`(PM 驗收文件範本)
|
||
- 服務:**G1**、**G3**
|
||
- 內容:JDD §3.2 三層巢狀 +「附:站點索引表」段 + 站全域編號/引用不重抄的註記
|
||
- 驗收:範本含站點索引表且欄位為「站|被哪些 Journey 經過|改動時重考範圍」
|
||
|
||
- [x] 2.3 `docs/sprint.md.template`(站號 sprint)+ tasks.md 站號欄位約定
|
||
- 服務:**G3**
|
||
- 內容:JDD §五 四步流程、順序鐵律「先認領 → 認領不足才新增 → 新增必掛站」、
|
||
起訖日與到期結算欄
|
||
- 驗收:範本能被 task 3.4 的 J6 判準讀出「本 sprint 指定站」與「未點亮站」
|
||
|
||
- [x] 2.4 `docs/triage-map.md.template`(分診表格式,內容留實例)
|
||
- 服務:**G1**
|
||
- 驗收:只有欄位與規則,**零實例內容**(通得過 task 4.1 的專名檢查)
|
||
|
||
- [x] 2.5 `docs/plugin-load-order.md`(W3 插槽文件)+ 兩份憲法的 must-read 注入點
|
||
- 服務:**G5(半通的那一半)**
|
||
- 內容:分離 §五 四步載入順序原文 +「政策包=官方 plugin,框架不發明平行格式」的約定
|
||
- 驗收:兩份 profile CLAUDE.md 各含一段可被 plugin SessionStart hook 填入的注入點標題
|
||
|
||
- [x] 2.6 JDD 術語表寫進 orchestrator 憲法(Journey 取代 CP,禁用舊詞)
|
||
- 服務:**G3**
|
||
- 驗收:術語表七詞(Journey/Station/通關/點亮/對帳/完備/輪子卡·賭注卡)齊全,
|
||
且標明 `CP.yaml`/`CPDO.md` 屬技術軌內圈保留原名
|
||
|
||
---
|
||
|
||
## Phase 3:封路 hook
|
||
|
||
> 前置條件:Phase 0(role-lib)+ Phase 2(有檔可擋)
|
||
|
||
- [x] 3.1 `role-guard.sh`(J1+J2+J3,common)
|
||
- 服務:**G2**(命門)
|
||
- 內容:orchestrator 禁寫 code 路徑/禁寫 tasks·requirements·design;
|
||
engineer 禁寫 journeys·root·`*.feature`·md 內 Gherkin 區塊;矩陣空格 exit 2
|
||
- 驗收:**六組實測**各貼 stdout/exit code——
|
||
① orchestrator 寫 `.py` → 擋 ② orchestrator 寫 `tasks.md` → 擋
|
||
③ engineer 改 `journeys.md` 的 Gherkin → 擋(**這條就是 G2**)
|
||
④ engineer 寫 `.py` → 放行 ⑤ orchestrator 寫 `journeys.md` → 放行
|
||
⑥ repo profile × `AGENT_ROLE=orchestrator` → 擋並要求修正環境
|
||
- 注意:Gherkin 區塊偵測要涵蓋 md 內的 ```gherkin fence 與 `- **G-x.y** Given` 行式
|
||
|
||
- [x] 3.2 `jdd-format-guard.sh`(J4+J5+J8,common)
|
||
- 服務:**G1**、G3
|
||
- J4:`root.md` 🔴 卡缺【要驗證+對帳日】→ 擋並指行號
|
||
- J5:`tasks.md` **新增**行缺站號 → 擋(Edit 看 `new_string`,Write 比對現檔差異)
|
||
- J8:`root.md`/`journeys.md` 技術名詞黑名單命中 → 擋並列詞+行號
|
||
- 驗收:三條各一組正例一組反例,共六次實測貼輸出
|
||
- 注意:J5 只判**新增**行,改既有行不擋(否則格式修正都做不了);誠實限制寫進註解
|
||
|
||
- [x] 3.3 `station-done-guard.sh`(J6,common,掛 Stop/TaskCompleted)
|
||
- 服務:**G3**
|
||
- 判準:本 sprint 指定站的 Gherkin 全綠才算收工;「tasks 全關」不算
|
||
- 驗收:造一個「tasks 全關但站 Gherkin 未綠」的情境 → 被退回(貼 exit 2 輸出)
|
||
- 注意:框架內**沒有**既有的 sprint 收尾 hook(`delivery-police.sh` 只在 InkStoneCo 實例),
|
||
這是新增不是修改;W4 時實例那支要退役,別兩處維護
|
||
|
||
- [x] 3.4 `regression-scope.sh`(J7,common)
|
||
- 服務:**G3**
|
||
- 行為:偵測站相關實作變動 → 讀 journeys.md 站點索引表 → 列需重考的 Journey/Gherkin
|
||
- 驗收:改動某站的實作檔後,輸出正確列出該站被哪些 Journey 經過(貼輸出)
|
||
- 注意:**提醒不阻擋**(exit 0)
|
||
|
||
- [x] 3.5 `install-artifact-guard.sh`(S1,common)
|
||
- 服務:**G6**
|
||
- 行為:寫入 `.claude/hooks/`/`system-dev/` 範本區/plugin 安裝目錄 → 擋,
|
||
提示「機制變更走框架/政策包 repo 提案」;`.sdt-framework-dev` 或 `SDT_FRAMEWORK_DEV=1` 放行
|
||
- 驗收:① 實例 session 編輯 `.claude/hooks/` 任一檔 → 擋(**這條就是 G6**)
|
||
② 框架 repo(有 marker)編輯同路徑 → 放行。兩組都貼輸出
|
||
- 注意:「範本區」的定義來自 manifest(class=overwrite 者),不要另寫一份路徑表
|
||
|
||
- [x] 3.6 `orchestrator-scope-guard.sh`(S4,orchestrator profile 專屬)
|
||
- 服務:**G6**
|
||
- 來源:改寫自 InkStoneCo 實例的 `guard-cross-project.sh`(上收進框架,決策 D6)
|
||
- 抽象化重點:子 repo 目錄清單、autodispatch 白名單**由實例設定檔提供**,
|
||
範本內**零實例專名**(通得過 task 4.1)
|
||
- 驗收:以假造的成員目錄結構跑三組——寫子 repo 的 `.py` → 擋/寫子 repo 的 `.md` → 放行/
|
||
`CHILD_SESSION=1` 且在白名單內 → 放行
|
||
- 注意:職責與 3.1 不重疊——3.1 管「角色能寫什麼**類型**」,本支管「總管能進哪個**位置**」
|
||
|
||
- [x] 3.7 改 `session-start-recall.sh`:依 profile 分流注入【改既有】
|
||
- 服務:**G3**、G4
|
||
- orchestrator:root/journeys 摘要 + 本 sprint **未點亮**站(治「起牀沒事做」)
|
||
- repo:維持現行 principles/status/mistakes
|
||
- 驗收:兩 profile 各開一次 session,貼注入內容對照(orchestrator 那份要出現站號)
|
||
|
||
- [x] 3.8 hook 全鏈掛載順序實測(design §4.4)
|
||
- 服務:**G2**、G6
|
||
- 驗收:故意觸發多條規則的一次寫入,確認錯誤訊息來自**最外層**那條(範圍大的先擋)
|
||
|
||
---
|
||
|
||
## Phase 4:框架側 CI 與清潔
|
||
|
||
> 前置條件:Phase 1(manifest 定義了「範本區」)
|
||
|
||
- [x] 4.1 `scripts/check-no-instance-names.sh` + `scripts/instance-names.txt`
|
||
- 服務:**G7**
|
||
- 行為:掃 `template/`,命中黑名單 → exit 1 並印「檔案:行號:命中詞」;
|
||
支援逐行豁免標記(行尾 `# sdt-instance-name-ok`);policy pack 路徑不受檢
|
||
- 驗收:在範本檔新增一行含 "arcrun" → 檢查 fail 並指出檔案與行號(**這條就是 G7**),貼輸出
|
||
|
||
- [x] 4.2 現況 20 行命中的分診處置(design §0.5)
|
||
- 服務:**G7**
|
||
- (a) 6 行註解/舉例 → 改寫成通用敘述
|
||
- (b) 3 行政策內容 + (c) 13 行 L2 產物 → 標 `# sdt-instance-name-ok` + 一行「W3 搬遷」註記
|
||
- 驗收:處置後 `check-no-instance-names.sh` 回 exit 0,且豁免行數 = 16(貼清單)
|
||
- 注意:**禁止假性清理**(把 arcrun 改寫成「某工作流引擎」=資訊消失、問題還在)
|
||
|
||
- [x] 4.3 掛 pre-commit / CI
|
||
- 服務:**G7**
|
||
- 驗收:`bash scripts/check-no-instance-names.sh` 在 CI 步驟中被呼叫,故意違規的 commit 被擋
|
||
|
||
---
|
||
|
||
## Phase 5:出貨(ship-check)
|
||
|
||
> 前置條件:Phase 0–4 全部完成
|
||
|
||
- [x] 5.1 CHANGELOG + VERSION bump(**兩處**:`template/.claude/VERSION` + `template/system-dev/VERSION`)
|
||
- 服務:全部
|
||
- 版號:1.18.0 → **1.19.0**(新功能、向下相容)
|
||
- 驗收:兩個 VERSION 檔內容一致;CHANGELOG 用用戶語言寫「這一版你會多出什麼」
|
||
- 注意:版本號是 leo 唯一的驗收介面——沒動=等於沒交付
|
||
|
||
- [x] 5.2 乾淨環境雙 profile 安裝實測(含計時)
|
||
- 服務:**G4**
|
||
- 驗收:兩個全新空目錄各裝一次,**各記錄實際耗時**(分離 §八 預測①:各 < 10 分鐘),
|
||
貼安裝輸出 + `ls -R` 檔案清單對照
|
||
|
||
- [x] 5.3 七題 Gherkin 逐條實測並記錄三態
|
||
- 服務:**G1–G7**
|
||
- 驗收:每題貼實測輸出並標 `✅ 通 / ◐ 半通(缺什麼)/ ❌ 斷`
|
||
- 注意:**G5 本波上限 `◐`**(插槽就位、政策包在 W3),標 ✅ 就是假綠;
|
||
G1 需要 root/journeys 有實內容才驗得到端到端 → 若實例尚未落地(W4),
|
||
以框架附的示範 fixture 驗,並在報告標明「以 fixture 驗,實例端到端待 W4」
|
||
|
||
- [x] 5.4 回報總管:交付物、三態表、與規格假設不符的清單
|
||
- 服務:全部
|
||
- 驗收:報告含 design §0 全部實查發現 + 本波實際落地的 hook 數(改既有 vs 新增)
|
||
|
||
---
|
||
|
||
## 完成定義
|
||
|
||
整個 SDD 完成 = 以下全部達成:
|
||
- [ ] 所有 tasks 標 [x]
|
||
- [ ] G1–G7 逐題有實測證據,且無任何一題為 `❌ 斷`(G5 可為 `◐`)
|
||
- [ ] `bash scripts/check-no-instance-names.sh` 回 exit 0
|
||
- [ ] `bash scripts/sdd-active-check.sh docs/3-specs` 回 exit 0
|
||
- [ ] 兩處 VERSION = 1.19.0,CHANGELOG 已寫
|
||
- [ ] design.md 與實作一致(如有出入需更新 design,不是默默改 code)
|
||
|
||
---
|
||
|
||
## 狀態說明
|
||
|
||
| 標記 | 意義 |
|
||
|------|------|
|
||
| `[ ]` | 未開始 |
|
||
| `[🔄]` | 進行中(當前 session)|
|
||
| `[x]` | 完成(有驗收證據)|
|
||
| `[~]` | 暫緩(說明原因)|
|
||
| `[!]` | 阻擋中(說明阻擋原因)|
|