Files
sdlc/README.md
T
jiantw83 77e7504982 docs(sdlc): 參考文件與 README 同步階梯、工作包隔離與日誌粒度
What:`references/branch.md` 新增「分支階梯與 base 推導」一節(只寫拿到 `jsc-git/tools/base-branch.sh --derive` 回應之後要做什麼)與「工作包隔離」一節(歸屬依據、狀態檔欄位、誰寫誰讀、查無歸屬放行、逃生門),閘門分工那一表補上 `claim`、`lock`、`owns`。`references/stage-report.md` 改寫暫存那一節,講明本節只適用於「還沒完成任何任務就停下」的階段。README 的工具表、`implement` 與 `maintain` 兩段說明、參考文件表與相依技能清單同步更新。

Why:階梯表與歸屬狀態檔的正本各有其處——階梯在 `jsc-meta` 的 `references/guidelines.md`,狀態檔格式在 `jsc-hooks`。抄第二份就會有兩份互相打架的規則,但完全不提又會讓實作階段不知道拿到 `7` 或「已建立功能主幹」時該做什麼。

How:兩節都只寫本階段要做的事,並把唯一來源用連結指出去。`branch.md` 的階梯那一節寫成一張「腳本回應 → 這個階段要做的事」對照表,`7` 明寫成「中止並問使用者,不退回 `develop`」。`stage-report.md` 補一句「暫存不等於已寫入」,因為日誌改成一個任務一筆之後,做完事情的階段本來就有日誌可連。

Who:讀 `jsc-sdlc` 參考文件與 README 的人,以及跑實作與維護兩階段的工作階段。
2026-08-27 11:20:30 +08:00

82 lines
14 KiB
Markdown
Raw 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.
# jsc-sdlc — 開發生命週期
jsc 技能組的 sdlc domain:規劃 → 分析 → 實作 → 維護四個階段,全程以 wiki 頁追蹤(`PLAN_CONTENTS`、`PLAN_{HASH}`、`ANALYZE_CONTENTS`、`ANALYZE_{HASH}`、`REPO_CONTENTS`、`REPO_{HASH}`、`DELIVER_CONTENTS`、`DELIVER_{HASH}`、`MAINTAIN_CONTENTS`)。工作包完成即交付:實作階段會詢問交付文件要產生成 `DELIVER_{HASH}` wiki 頁或 Gitea 議題留言。hook 或流程失敗記在異常頁(`ERROR_CONTENTS`、`ERROR_{HASH}`),那組頁面與範本由 `jsc-hooks` 擁有,本 domain 不放副本。每次切換階段先過模型閘門,判定全在程式層,由 `jsc-hooks/hooks/sdlc-gate.sh lock {stage}` 執行;各階段必要標籤、阻擋與回報的鐵則見 `references/model-gate.md`。分析前先與使用者確認來源分支;實作沿用同一條來源分支作為 worktree 基準與 PR 目標。**所有參考與來源分支一律取遠端的 `origin/{branch}`,動作前先 `git fetch --prune origin`;本地分支不可作為基準,本地與遠端不一致就停下回報。**
## 安裝、更新、移除
Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安裝 token 為 `jsc-sdlc@jsc`。每個指令一行:
| CLI | 安裝 | 更新 | 移除 |
| --- | --- | --- | --- |
| claude | `claude plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && claude plugin install jsc-sdlc@jsc` | `claude plugin marketplace update jsc && claude plugin update jsc-sdlc@jsc` | `claude plugin uninstall jsc-sdlc@jsc` |
| codex | `codex plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && codex plugin add jsc-sdlc@jsc` | `codex plugin marketplace upgrade jsc` | `codex plugin remove jsc-sdlc@jsc` |
| copilot | `copilot plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && copilot plugin install jsc-sdlc@jsc` | `copilot plugin marketplace update jsc && copilot plugin update jsc-sdlc@jsc` | `copilot plugin uninstall jsc-sdlc@jsc` |
| antigravity | `git clone https://gitea.jsc.idv.tw/plugins/sdlc.git ~/plugins/sdlc && agy plugin install ~/plugins/sdlc` | `git -C ~/plugins/sdlc pull && agy plugin uninstall jsc-sdlc && agy plugin install ~/plugins/sdlc` | `agy plugin uninstall jsc-sdlc` |
| kiro | `kiro-cli plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && kiro-cli plugin install jsc-sdlc@jsc` | `kiro-cli plugin marketplace update jsc && kiro-cli plugin update jsc-sdlc@jsc` | `kiro-cli plugin uninstall jsc-sdlc@jsc` |
> antigravity 不支援 gitea URL 安裝,改用本地 clone 路徑。批次操作五個 CLI:使用 `/jsc-cli:deploy`。
> 舊入口 `plugins/jsc` 已移除,marketplace 正本移到 `plugins/meta`。marketplace 名稱仍是 `jsc`(取自 marketplace.json 的 `name` 欄位,與存取庫名無關),安裝 token 不變;已從舊入口安裝過的人先執行 `claude plugin marketplace remove jsc`,再依上表重新 add。
## 工具
| 腳本 | 用途 |
| --- | --- |
| `tools/wp-gate.sh` | 工作包 PR 閘門,把「一個工作包的 PR 沒合併,擋的是相依於它的工作包,不是整份分析」從內文敘述變成程式判定,共三個用法。`check {owner}/{repo} {index} [--since {ISO 時間}]` 查一支 PR:已合併就呼叫 `jsc-hooks` 的 `sdlc-gate.sh wp-unlock` 解鎖並印 `status=merged`;沒合併就印 `status=open` 或 `status=closed-unmerged`(被關掉但沒合併不算完成),接著把 issue 留言、審查評語、行內留言全部逐行印出(`--since` 只印更新的,值取上一輪的 `latest=`),最後一行印 `latest={最新一筆留言的時間戳}` 供寫回分析頁。`check-deps {owner}/{repo} {wp-number}` 查某個候選工作包能不能挑:活抓分析頁 WBS 表的相依欄,逐一核對每個相依工作包的狀態與 PR 是否已合併,只認同一張分析頁上的 `WP-NN` 編號,指到別份計畫的文字項目查不了就列出來要求人工確認,不當成擋人的理由。`claim {owner}/{repo} {wp-number} [--analyze {分析頁頁名}]` 在領包當下轉呼叫 `sdlc-gate.sh wp-claim` 登錄歸屬。`lock {owner}/{repo} {index} [--wp {wp-number}]` 在 PR 開好後轉呼叫 `sdlc-gate.sh wp-lock` 記下未結清,`--wp` 把 PR 掛到該工作包名下。`owns {owner}/{repo} {index} [--wp {wp-number}]` 比對這支 PR 是不是自己這一包的:`owned` 放行、`foreign` 擋住並指出它掛在哪一包名下、查無歸屬(沒有領取紀錄、工作包還沒掛上 PR)一律 `unowned` 放行只提醒。第一行固定 `status=...` 供程式判讀,其後為繁中說明;結束碼 `0`=已合併或無阻擋(含 `check-deps` 的 `ready`、`claim` 的 `claimed`、`owns` 的 `owned` 與 `unowned`)、`1`=未合併、`check-deps` 判定 `blocked` 或 `owns` 判定 `foreign`、`2`=用法錯誤、`3`=相依工具或 PR/分析頁查不到(**查不到就擋,不放行**),或歸屬登錄不了。狀態檔由 `jsc-hooks` 產生(領取檔 `$JSC_HOME/wp/{owner}-{repo}.claim`、鎖檔 `$JSC_HOME/wp/{owner}-{repo}-{index}.pr`,純文字 key=value 一行一欄),不綁 session,開新對話照樣擋;本檔只讀不寫,寫入一律走 `sdlc-gate.sh` 的子命令 |
| `tools/stage-report.sh` | 階段收尾回報,四個階段共用。`stage-report.sh {plan\|analyze\|implement\|maintain}` 加 `--page TYPE:PAGE`(本階段寫過的每一頁,可重複)產出繁中回報:模型閘門判定(轉述 `sdlc-gate.sh report`,不自評)、工作日誌連結(`--worklog`、`--worklog-heading` 組出導向條目標題的錨點)、所有寫入的 wiki 絕對網址。實作階段再加 `--worktree`、`--source-branch`、`--work-branch`、`--target-branch`、`--pr`,來源分支在不在遠端、工作分支幾個 commit、推送了沒,都由腳本現查。沒有工作日誌時警告使用者檢查,並用 `--pending-file`、`--log-hash` 把內容交給 `jsc-log/tools/worklog-pending.sh` 暫存,下次寫日誌一併寫入。結束碼 `0`=完整、`1`=有警告(**警告不是阻擋**)、`2`=用法錯誤、`3`=相依工具找不到 |
## Skills 目錄
呼叫方式:Claude / Antigravity `/jsc-sdlc:{name}`;Codex `${name}`;Copilot / Kiro 描述需求自動觸發。
<!-- JSC-SKILLS:START -->
### `plan`
規劃:讀計畫目錄 → 補充或新建計畫 → 決策樹持續提問,補全目標、範圍、可行性到達成共識(判定規則見 `references/consensus.md`,一輪不算問完)→ 產生使用者故事 → 寫回 `PLAN_{HASH}` → 階段回報(`tools/stage-report.sh`)。純邏輯,禁止程式碼與修改檔案。
### `analyze`
分析:先確認來源分支 → 持續提問到達成共識(`references/consensus.md`)→ 搭配現況(工作目錄與 `REPO_{HASH}` 盤點複用)分析使用者故事 → WBS 產生編號工作包,`WP-01` 固定是獨立的交付、交接工作包,實作工作包相依於它 → CPM 估工時與天數 → TDD 拆待辦 → 寫回 `ANALYZE_{HASH}` → 階段回報(`tools/stage-report.sh`)。純邏輯,禁止程式碼與修改檔案。
### `implement`
實作:先確認來源分支(同時是 PR 目標)→ 領包前先跑 `tools/wp-gate.sh check` 把每個已開 PR 但沒合併的工作包留言逐筆印出,動手前先跑 `tools/wp-gate.sh owns` 確認那支 PR 是自己這一包的,再依 `jsc-ask:ask` 決策樹與使用者對每一則留言達成共識才修(以 sub agent 回原 worktree、推同一條工作分支,不開第二個 PR),**這一步只結清舊 PR 的留言,不擋別的工作包**——修不動或純討論的留言忽略但要在回報裡列出,處理過的時間戳寫回分析頁**既有**的 PR 欄位當下一輪的 `--since` → 產生工作證鎖定「未完成、無工作證」的候選工作包(交付工作包優先),**每個候選都跑 `tools/wp-gate.sh check-deps` 判斷能不能挑**:活查它在分析頁上的相依工作包是否都已合併,只有相依於它的包才會被一支未合併的 PR 擋住,跟它無關的工作包可以平行進行 → 領到包立刻跑 `tools/wp-gate.sh claim` 記下歸屬 → 交付工作包開工前先確認交付內容(API 文件、由使用者輸入,見 `references/deliver-formats.md`)→ **動程式碼前先從 `origin/{source-branch}` 建立 worktree**(`.worktree/{analysis-HASH}/{wp-number}/{repo}`,一個工作包一個 worktree,分支處理依決策樹詢問)→ 在 worktree 內逐項 TDD 實作、每完成一項立即更新 wiki → 程式碼審查 → **每完成一個工作包就 commit、push、PR 回來源分支**(一包一 PR),接著 `tools/wp-gate.sh lock --wp` 上鎖並登記 PR 歸屬 → **用 `jsc-gitea/tools/pr-watch.sh` 盯到合併**(預設 60 秒輪詢、不自動退場;退出碼 `0` 已合併或關閉、`10` 有新留言就回頭跑同一套留言修正、`3` 查不到該 PR、`2` 參數或環境有問題),合併後解鎖並移除 worktree → 詢問交付文件格式(`DELIVER_{HASH}` wiki 頁或 Gitea 議題留言)並產出 → 詢問是否加入維護目錄 → 階段回報(`tools/stage-report.sh`,多報工作目錄與來源、工作、目標三條分支)。**每完成一個任務就寫一筆工作日誌**(`jsc-log:worklog`):一個工作包、一輪 PR 留言修正、一個獨立的修正提交各算一個任務,不等到階段結束才補一次;`stage-report.sh --pending-file` 暫存的內容併進同一次寫入,寫入成功才清除。寫程式碼時註解只寫「為什麼這樣寫」,工作包編號、分析頁編號、待辦編號、分支名、PR 編號一律不寫進註解,完整清單與白名單見 `jsc-review` 的 `references/comment-scope.md`。
### `maintain`
維護:讀取維護期內的專案,每個專案一個 sub agent:fetch 後切 develop、master 並對齊 `origin/{branch}` → 提出至少五種維護方法,依決策樹讓使用者挑要做哪些 → commit / push / PR → **PR 開好立刻寫一筆工作日誌**(`jsc-log:worklog`,一個專案一筆,下一個專案開工前要先寫完)→ 更新前次維護時間 → 階段回報(`tools/stage-report.sh`)。sub agent 改程式碼時註解只寫「為什麼這樣寫」,議題編號、commit hash、分支名、人名與 `@` 提及一律不寫進註解,完整清單與白名單見 `jsc-review` 的 `references/comment-scope.md`。僅適用於維護期內已交付的專案;尚在實作中或未登記於 `MAINTAIN_CONTENTS` 的專案不適用。
<!-- JSC-SKILLS:END -->
## 範本與參考
| 檔案 | 用途 |
| --- | --- |
| `templates/plan-page.md`、`templates/plan-contents.md` | 計畫頁與計畫目錄 |
| `templates/analyze-page.md`、`templates/analyze-contents.md` | 分析頁(WBS、CPM、TDD 待辦)與分析目錄 |
| `templates/repo-page.md`、`templates/repo-contents.md` | 存取庫盤點頁(功能與端點,附 commit sha)與盤點目錄 |
| `templates/deliver-page.md`、`templates/deliver-contents.md` | 交付頁(API 文件、新舊參數標示、驗證方式)與交付目錄 |
| `templates/maintain-contents.md` | 維護目錄(截止日 NULL = 永久維護) |
| `references/stage-report.md` | 階段回報:四階段都要交的三項(模型能力標籤、工作日誌連結、所有寫入的 wiki 連結)、實作階段多交的四項、沒寫日誌時的暫存規則、提前停止也要回報 |
| `references/model-gate.md` | 模型閘門:執行順序、各階段必要標籤、阻擋與回報的鐵則 |
| `references/tdd.md` | 接縫、紅綠循環規則、反模式 |
| `references/branch.md` | 分支規則:**一律以遠端 `origin/{branch}` 為準、動作前先 fetch**、分析前確認來源分支、實作沿用同一條來源分支作為 PR 目標(一包一 PR,一個工作包的 PR 沒合併只擋相依於它的工作包,不擋整份分析,閘門分工與工作包隔離的狀態檔格式見該檔)、分支階梯(表本身在 `jsc-meta` 的 `references/guidelines.md`「PR 分支階梯」,該檔只寫 sdlc 拿到 `jsc-git/tools/base-branch.sh --derive` 的回應之後要做什麼、推不出就中止問使用者)、實作一律在 `.worktree/{HASH}/{wp-number}/{repo}` 內進行——一個工作包一個 worktree,讓互不相依的工作包能平行進行不互相搶路徑(建立前問分支、PR 合併後才移除)、判定遠端預設分支、不破壞未提交變更 |
| `references/consensus.md` | 規劃與分析的提問規則:一輪不算問完、共識的兩個判定條件、未決項處理 |
| `references/deliver-formats.md` | 交付內容型別:API 文件必備欄位、範例資料優先序、既有端點的新舊參數標示 |
## 環境變數
Wiki 位置:`PLAN_{HASH}` / `PLAN_CONTENTS` 只讀 `JSC_WIKI_REPO_PLAN`,再退回 `JSC_WIKI_REPO`;`ANALYZE_{HASH}` / `ANALYZE_CONTENTS` 只讀 `JSC_WIKI_REPO_ANALYZE`,再退回 `JSC_WIKI_REPO`;`REPO_{HASH}` / `REPO_CONTENTS` 只讀 `JSC_WIKI_REPO_REPO`,再退回 `JSC_WIKI_REPO`;`DELIVER_{HASH}` / `DELIVER_CONTENTS` 只讀 `JSC_WIKI_REPO_DELIVER`,再退回 `JSC_WIKI_REPO`;`MAINTAIN_CONTENTS` 只讀 `JSC_WIKI_REPO_MAINTAIN`,再退回 `JSC_WIKI_REPO`。不同類型不可互相代用;兩者都未設定才詢問(見 `jsc-gitea`)。
HASH 規則:`{owner}/{repo}` 的共用 wiki hash 一律由 `jsc-gitea/tools/hash-id` 計算(見 `jsc-gitea:wiki`),此 domain 不重複實作演算法。
## 相關 domain
- [`jsc-cli`](https://gitea.jsc.idv.tw/plugins/cli):模型能力標籤與階段閘門判定(`tools/model-tags.sh`、`references/model-tags.md`、`jsc-cli:models`)、偏好模型鏈(`tools/model-config.sh`)
- [`jsc-hooks`](https://gitea.jsc.idv.tw/plugins/hooks):sdlc-gate 階段模型鎖定
- [`jsc-gitea`](https://gitea.jsc.idv.tw/plugins/gitea):wiki 讀寫、實作階段等 PR 合併的輪詢(`tools/pr-watch.sh`)
- [`jsc-review`](https://gitea.jsc.idv.tw/plugins/review):實作完成後的程式碼審查
- [`jsc-git`](https://gitea.jsc.idv.tw/plugins/git) / [`jsc-pkg`](https://gitea.jsc.idv.tw/plugins/pkg):維護階段的 commit / PR 與套件更新
- [`jsc-log`](https://gitea.jsc.idv.tw/plugins/log):工作日誌,每完成一個任務就寫一筆