發佈 jsc-sdlc 0.0.7:交付工作包 WP-01、共識規則、marketplace 正本遷移 #9

Merged
admin merged 8 commits from develop into master 2026-08-24 10:20:06 +00:00
13 changed files with 306 additions and 44 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "jsc-sdlc",
"version": "0.0.5",
"version": "0.0.7",
"description": "開發生命週期:規劃/分析/實作/維護(wiki 追蹤)",
"skills": "./skills",
"author": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "jsc-sdlc",
"version": "0.0.5",
"version": "0.0.7",
"description": "開發生命週期:規劃/分析/實作/維護(wiki 追蹤)",
"skills": "./skills"
}
+16 -10
View File
@@ -1,21 +1,23 @@
# jsc-sdlc — 開發生命週期
jsc 技能組的 sdlc domain:規劃 → 分析 → 實作 → 維護四個階段,全程以 wiki 頁追蹤(`PLAN_CONTENTS`、`PLAN_{HASH}`、`ANALYZE_CONTENTS`、`ANALYZE_{HASH}`、`REPO_CONTENTS`、`REPO_{HASH}`、`MAINTAIN_CONTENTS`)。另有異常頁(`ERROR_CONTENTS`、`ERROR_{HASH}`)記錄 hook 或流程失敗。每次切換階段先過模型閘門:由 `jsc-hooks/hooks/sdlc-gate.sh lock {stage}` 從 transcript 讀出**實際**模型 id,比對該階段的必要能力標籤(plan、analyze 需 `reasoning-max`;implement 需 `coding`;maintain 任意),不符就拒絕上鎖、該階段不得執行。判定全在程式層,模型不得自評標籤。通過後鎖定到下一階段的閘門重新上鎖;同一階段內把模型換成不合格的,下一輪提示會被 hook 以 exit 2 擋下。分析前先與使用者確認來源分支,寫檔前先確認目標分支。
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 議題留言。另有異常頁(`ERROR_CONTENTS`、`ERROR_{HASH}`)記錄 hook 或流程失敗。每次切換階段先過模型閘門:由 `jsc-hooks/hooks/sdlc-gate.sh lock {stage}` 從 transcript 讀出**實際**模型 id,比對該階段的必要能力標籤(plan、analyze 需 `reasoning-max`;implement 需 `coding`;maintain 任意),不符就拒絕上鎖、該階段不得執行。判定全在程式層,模型不得自評標籤。通過後鎖定到下一階段的閘門重新上鎖;同一階段內把模型換成不合格的,下一輪提示會被 hook 以 exit 2 擋下。分析前先與使用者確認來源分支,寫檔前先確認目標分支。
## 安裝、更新、移除
Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/jsc.git),安裝 token 為 `jsc-sdlc@jsc`。每個指令一行:
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/jsc.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/jsc.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/jsc.git && copilot plugin install jsc-sdlc@jsc` | `copilot plugin marketplace update jsc && copilot plugin update jsc-sdlc@jsc` | `copilot plugin uninstall jsc-sdlc@jsc` |
| 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/jsc.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` |
| 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。
## Skills 目錄
呼叫方式:Claude / Antigravity `/jsc-sdlc:{name}`;Codex `${name}`;Copilot / Kiro 描述需求自動觸發。
@@ -24,15 +26,15 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/jsc.git),安
### `plan`
規劃:讀計畫目錄 → 補充或新建計畫 → 決策樹補全目標、範圍、可行性至共識 → 產生使用者故事 → 寫回 `PLAN_{HASH}`。純邏輯,禁止程式碼與修改檔案。
規劃:讀計畫目錄 → 補充或新建計畫 → 決策樹持續提問,補全目標、範圍、可行性到達成共識(判定規則見 `references/consensus.md`,一輪不算問完)→ 產生使用者故事 → 寫回 `PLAN_{HASH}`。純邏輯,禁止程式碼與修改檔案。
### `analyze`
分析:搭配現況(工作目錄與 `REPO_{HASH}` 盤點複用)分析使用者故事 → WBS 產生編號工作包 → CPM 估工時與天數 → TDD 拆待辦 → 寫回 `ANALYZE_{HASH}`。純邏輯,禁止程式碼與修改檔案。
分析:先確認來源分支 → 持續提問到達成共識(`references/consensus.md`)→ 搭配現況(工作目錄與 `REPO_{HASH}` 盤點複用)分析使用者故事 → WBS 產生編號工作包,`WP-01` 固定是獨立的交付/交接工作包、實作工作包相依於它 → CPM 估工時與天數 → TDD 拆待辦 → 寫回 `ANALYZE_{HASH}`。純邏輯,禁止程式碼與修改檔案。
### `implement`
實作:產生工作證鎖定「未完成、無相依、無工作證」的工作包 → 逐項 TDD 實作、每完成一項立即更新 wiki → 程式碼審查 → 詢問是否加入維護目錄。
實作:先確認目標分支 → 產生工作證鎖定「未完成、無相依、無工作證」的工作包(交付工作包優先)→ 交付工作包開工前先確認交付內容(API 文件/由使用者輸入,見 `references/deliver-formats.md`) → 逐項 TDD 實作、每完成一項立即更新 wiki → 程式碼審查 → 詢問交付文件格式(`DELIVER_{HASH}` wiki 頁或 Gitea 議題留言)並產出 → 詢問是否加入維護目錄。
### `maintain`
@@ -48,12 +50,16 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/jsc.git),安
| `templates/analyze-page.md`、`templates/analyze-contents.md` | 分析頁(WBS、CPM、TDD 待辦)與分析目錄 |
| `templates/repo-page.md`、`templates/repo-contents.md` | 存取庫盤點頁(功能與端點,附 commit sha)與盤點目錄 |
| `templates/error-page.md`、`templates/error-contents.md` | 異常頁與異常目錄 |
| `templates/deliver-page.md`、`templates/deliver-contents.md` | 交付頁(API 文件、新舊參數標示、驗證方式)與交付目錄 |
| `templates/maintain-contents.md` | 維護目錄(截止日 NULL = 永久維護) |
| `references/tdd.md` | 接縫、紅綠循環規則、反模式 |
| `references/branch.md` | 分支規則:分析前確認來源分支、寫檔前確認目標分支、判定遠端預設分支、不破壞未提交變更 |
| `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`;`MAINTAIN_CONTENTS` 只讀 `JSC_WIKI_REPO_MAINTAIN`,再退回 `JSC_WIKI_REPO`。不同類型不可互相代用;兩者都未設定才詢問(見 `jsc-gitea`)。
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 不重複實作演算法。
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "jsc-sdlc",
"version": "0.0.5",
"version": "0.0.7",
"description": "開發生命週期:規劃/分析/實作/維護(wiki 追蹤)",
"skills": "./skills/"
}
+44
View File
@@ -0,0 +1,44 @@
# 分支規則 — SDLC 各階段動工前的分支確認
分析要讀對分支的程式碼,實作要寫進對的分支。兩件事都不能從「目前 checkout 的分支」推定使用者的意圖。
## 先確認,再動工
| 階段 | 要確認的分支 | 確認時機 |
| --- | --- | --- |
| `analyze` | **來源分支**——哪條分支的程式碼算現況 | 讀任何程式碼之前 |
| `implement` | **目標分支**——這批工作要合併進哪條分支 | 寫任何檔案之前 |
確認方式:
1. 先把事實攤開:目前分支、工作區是否乾淨、遠端有哪些分支(`git branch -r`)、下節判定出的遠端預設分支。
2. 依 `jsc-ask:ask` 的決策樹詢問,每個選項都要標明影響範圍。分析錯分支會產出對不上程式碼的工作包;目標分支錯了則 PR 會開到錯的地方。
3. 把確認結果寫進產出(分析頁的來源分支欄、PR 的目標分支),後續步驟一律沿用同一個答案,不再自行改判。
4. 使用者沒回答就**不預設** `develop`/`master`;預設值只在使用者明確同意後才成立。
## 判定遠端預設分支
1. 先用 `git symbolic-ref --quiet refs/remotes/origin/HEAD`,結果形如 `refs/remotes/origin/<預設分支>`。
2. 取不到時退而用 `git remote show origin`,找輸出中的 `HEAD branch:` 那行。
3. 兩者都取不到 → 回報並停止,**不臆測** `master`/`main`。
需要基準或後備分支時(例如 PR 目標):`origin/develop` 存在就用 `develop`;否則 `origin/master` 存在就用 `master`;兩者皆無則回報並停止。
## 只讀階段不動工作區
`analyze` 是 logic-only 階段:
- 需要換分支才能讀到正確現況時,**停下來請使用者自己切換**。
- 不代為 `switch`、不 `stash`、不動工作區、不建分支。
## 實作階段的分支選擇
- **只有來源分支與目標分支同名時才開新的工作分支**:同名就不可在該分支上直接 commit,改從已更新到最新的目標分支建立新工作分支,後續操作都以新分支為準。不同名就在目前分支處理。
- 新分支名稱要可讀且不覆蓋既有分支;本地或遠端已存在同名分支時,換一個時間戳或短 hash。
- 切換或建立分支屬不可忽略的狀態變更,要在輸出中講清楚原因與結果分支名稱。
## 不破壞既有工作
- 工作區有未提交變更時,先提醒使用者 commit 或備份,**絕不**強制丟棄。
- 未提交變更導致切換分支或 pull 失敗 → 停止並回報,請使用者處理。
- **絕不** `reset --hard`/`checkout -f`/`clean`。
+38
View File
@@ -0,0 +1,38 @@
# 共識判定 — 規劃與分析階段的提問規則
`plan` 與 `analyze` 都靠提問把需求問清楚。兩個階段共用本規則,各自不再重寫一份。
## 一輪不算問完
- **每個回答都要生出下一個問題**:從使用者的答案往下推,找出它新暴露的未知,繼續問。答完一輪就收工是最常見的失敗。
- 問題一次只問一件事,選項一律標明影響範圍(依 `jsc-ask:ask`)。
- 問過的別再問:先查 wiki 的 `QUESTION_CONTENTS` 與 `QUESTION_{HASH}`,已答的直接沿用。
## 達成共識的兩個條件
同時滿足才算共識,缺一不可:
1. **沒有未知會改變產出**——任何還沒問清楚的細節,都不足以改變使用者故事、工作包切分或工時估算。
2. **使用者明確確認**——把整理過的結論讀回去,使用者明確表示同意。
## 每輪都要讓共識可見
提問前先攤開現況,不要讓使用者自己記:
| 區塊 | 內容 |
| --- | --- |
| 已達成共識 | 已確認的項目與結論 |
| 尚未釐清 | 還開著的項目,以及它會影響什麼 |
| 本輪要問 | 這一輪要解決哪一項 |
## 不可以做的事
- **不得用自己的假設補洞**。缺資訊就問,不能先寫下去再說。
- **不得把沉默或「都可以」當成答案**——只要該項會改變範圍或切分,就要追問到具體選項。
- **不得在還有開著的項目時往下走**(規劃不得產出使用者故事,分析不得開始 WBS)。
- 使用者確實不想決定時:把它當**未決項**寫進頁面,註明影響與預設處理方式,並問使用者要不要接受那個預設值。未決項不得靜默消失。
## 收尾
- 共識達成後,把「問了什麼、答了什麼」依 `jsc-ask:ask` 規則回存 wiki,讓下一階段不必重問。
- 頁面上的未決項要能追:誰要決定、什麼時候決定、不決定會怎樣。
+58
View File
@@ -0,0 +1,58 @@
# 交付內容型別
交付/交接工作包開工時,先跟使用者確認這份交付要產出什麼內容。預設選項固定兩個,其餘由使用者輸入。
| 選項 | 內容 |
| --- | --- |
| 1. API 文件 | 端點路徑、輸入參數(**全部**)、輸出參數(**全部**);見下節 |
| 2. 由使用者輸入 | 使用者自己講要什麼內容;照使用者說的做,不套 API 文件格式 |
選項一律依 `jsc-ask:ask` 規則呈現,並標明影響範圍。**不得自行預設,也不得跳過詢問。**
## API 文件
### 必備欄位
| 區塊 | 要求 |
| --- | --- |
| 端點路徑 | 方法與完整路徑(例 `GET /v1/members/{id}`),含版本前綴 |
| 輸入參數 | **列出全部**——路徑、查詢字串、標頭、請求主體逐層列,不可只列「主要的幾個」 |
| 輸出參數 | **列出全部**——回應主體逐層列,含錯誤回應的結構與狀態碼 |
每個參數都要有:名稱、型別、必填與否、範例、資料來源、新舊狀態。
### 參數範例:真實資料優先
1. 先找真實來源:資料庫欄位與實際資料列、實際 API 回應、既有設定檔或 fixture、日誌。標成 `真實:{來源}`。
2. 找不到來源才由邏輯推理,標成 `推論:無來源`,讓接手者知道那個值還沒被驗證。
3. **不得**編一個看起來合理的值當成真實資料。
4. 範例只保留**結構與格式**。個資一律遮蔽或改寫成格式描述,不把真實個資寫進交付文件。
### 既有端點:新舊參數必須明顯區分
改的是既有端點時,接手者最需要知道「哪些是這次動到的」。用兩種標示,兩者都要:
**一、參數表加狀態欄**
| 狀態 | 標示 | 意義 |
| --- | --- | --- |
| 新增 | 🆕 **新增** | 這次新增的參數 |
| 變更 | ⚠️ **變更** | 既有參數改了型別、必填性、預設值或語意 |
| 既有 | (留空) | 這次沒動 |
| 移除 | ❌ **移除** | 這次移除,含淘汰時程 |
**二、差異區塊用 `diff` 語法標色**
Gitea 與 GitHub 的 markdown 都會替 `diff` 程式碼區塊上色,`+` 綠、`-` 紅,是最可靠的「顏色」做法(HTML 的 `style` 屬性會被 wiki 過濾掉,不要用):
````markdown
```diff
GET /v1/members/{id}
id string 必填
+ include_tags boolean 選填 預設 false(本次新增)
- legacy_flag boolean 選填 (本次移除,2026-12-31 前相容)
! status string 必填 列舉值新增 suspended(本次變更)
```
````
新端點不需要狀態欄與差異區塊,但要註明「本次新增端點」。
+12 -10
View File
@@ -1,6 +1,6 @@
---
name: analyze
description: SDLC analysis stage. Gate on capability tags enforced in code by sdlc-gate (analyze requires reasoning-max, verified against the transcript's actual model id), confirm the source branch with the user, pick a plan from PLAN_CONTENTS, analyze user stories against the current state (working directory plus REPO_{HASH} inventory for reuse). Run WBS with handover work packages ranked first (spec before implementation), estimate them with CPM, split each into TDD todos, and write wiki page ANALYZE_{HASH} with real sample data. Logic only - never write code or modify files. Use after planning and before implementation.
description: SDLC analysis stage. Gate on capability tags enforced in code by sdlc-gate (analyze requires reasoning-max, verified against the transcript's actual model id), confirm the source branch with the user, pick a plan from PLAN_CONTENTS, analyze user stories against the current state (working directory plus REPO_{HASH} inventory for reuse). Keep questioning until consensus per references/consensus.md, run WBS with the delivery/handover package as a standalone WP-01 that implementation packages depend on, estimate them with CPM, split each into TDD todos, and write wiki page ANALYZE_{HASH} with real sample data. Logic only - never write code or modify files. Use after planning and before implementation.
---
# analyze
@@ -21,31 +21,32 @@ All wiki reads and writes go through `jsc-gitea:wiki`.
2. **Confirm the source branch** — the branch whose code counts as the current state:
1. Report the working directory's current branch, plus the remote branches available (`git branch -r`) and whether the working tree is clean.
2. Ask per `jsc-ask:ask` rules which branch the analysis reads from; state the impact scope on every option (analysing the wrong branch produces work packages for code that does not exist).
3. When the chosen branch is not the current one, **stop and ask the user to switch**. This stage never switches branches, never stashes, and never touches the working tree — see `/jsc-shared:spec-git-safety`.
3. When the chosen branch is not the current one, **stop and ask the user to switch**. This stage never switches branches, never stashes, and never touches the working tree — rules in `references/branch.md`.
4. Record the confirmed branch and its head sha on the analysis page. Completion condition: the user has confirmed the branch explicitly; never infer it from the current checkout alone.
3. Read `PLAN_CONTENTS` via `jsc-gitea:wiki` for plans whose status is the literal 「未分析」 (name and HASH), and read `ANALYZE_CONTENTS` for existing analyses.
4. Let the user choose per `jsc-ask:ask` rules: **extend an existing analysis** or **analyze a new plan**. State the impact scope on every option.
5. Analyze the plan page's user stories one by one against the **current state**, questioning via the `jsc-ask:ask` decision tree until no doubt remains; keep asking while consensus is missing. Current state means:
5. Analyze the plan page's user stories one by one against the **current state**, **questioning until consensus** per `references/consensus.md` (the single authority for both planning and analysis): every answer produces the next question, and consensus needs both no output-changing unknown **and** the user's explicit confirmation. Never assume a missing detail, and never start the WBS while any item is still open. Current state means:
1. Every file in the working directory, on the branch confirmed in step 2.
2. **Reuse existing methods and endpoints whenever possible**:
- Check the `REPO_{HASH}` inventory page first. Re-inventory when the feature or endpoint is missing, or when the recorded commit sha differs from the current one.
- Re-inventory **MUST run as a sub agent**: analyze the repository's features and endpoints, attach the current commit sha, write back to `REPO_{HASH}` with `templates/repo-page.md`, and update `REPO_CONTENTS` per `templates/repo-contents.md`.
- For each reuse candidate, confirm the file path and method name first, then analyze whether its logic fits the requirement.
6. Run a **Work Breakdown Structure (WBS)**: split the user stories into work packages, number them sequentially (`WP-01`, `WP-02`, ...) and mark dependencies.
7. **Rank handover work packages first** — see 「交接優先」 below. Spec-shaped packages ship before implementation-shaped ones.
7. **`WP-01` is always the delivery/handover work package** — see 「交付工作包最優先」 below. It stands alone, never merged into an implementation package, and every implementation package that consumes its spec depends on it.
8. Estimate every work package's effort in hours and days with the **Critical Path Method (CPM)**, and mark the critical path.
9. Split every work package into todos with **Test-Driven Development (TDD)**, formatted `[ ]` (open) / `[x]` (done). Each todo is one vertical slice: one seam, one test, one minimal implementation. Seams and anti-patterns: `references/tdd.md`.
10. Apply `templates/analyze-page.md` to create or update the analysis page and write it back via `jsc-gitea:wiki`. The page content is Traditional Chinese, exactly as the template dictates.
11. If the analysis page is new: add it to `ANALYZE_CONTENTS` per `templates/analyze-contents.md`, and flip the plan's status in `PLAN_CONTENTS` to the literal 「已分析」.
## 交接優先(handover first)
## 交付工作包最優先(delivery package is WP-01)
A work package is a **handover package** when someone else — another person, another CLI, another team — has to act on its output. Interfaces, schemas, spec documents, acceptance criteria and sample payloads are handover output; endpoint bodies and UI wiring are not.
A work package is a **delivery/handover package** when someone else — another person, another CLI, another team — has to act on its output. Interfaces, schemas, spec documents, acceptance criteria and sample payloads are delivery output; endpoint bodies and UI wiring are not.
- Mark every work package as 交接 `是` / `否` in the WBS table.
- **Order handover packages before implementation packages**, so the receiving side gets the spec while implementation is still open. Implementation packages are the backup queue (實作候補): they are still numbered, estimated and kept on the page, just ranked later.
- Dependencies still win: never place a package before one it depends on. Within the same dependency level, handover packages come first.
- Do not merge a spec and its implementation into one package — that removes the ability to hand the spec over early. Split them.
- **`WP-01` is the delivery/handover package, always first, always standalone.** Pull every spec-shaped item out of the implementation packages and put it here. Never merge a spec into the package that implements it — merging removes the ability to hand the spec over early, which is the whole point.
- **Implementation packages depend on `WP-01`** when they consume its spec, and they are the backup queue (實作候補): still numbered, still estimated, still on the page, just ranked after it.
- Mark every work package as 交付 `是` / `否` in the WBS table, and record `WP-01`'s intended content type in the 交付型別 column when the user has already decided it (options in `references/deliver-formats.md`; the type is confirmed for real when `implement` starts that package).
- Dependencies still win among the rest: never place a package before one it depends on. Within the same dependency level, delivery-shaped packages come first.
- **When nothing is genuinely deliverable** (say, an internal refactor with no interface change), do not invent an empty `WP-01`: confirm with the user per `jsc-ask:ask` that this analysis has no handover output, then note the reason on the page and number the implementation packages from `WP-01`.
## 範例資料(sample data)
@@ -55,6 +56,7 @@ Every sample value on the analysis page — request and response payloads, field
2. **Only when no source exists**, derive the value by reasoning from the surrounding logic — and label it as inferred (for example `推論:無來源`), so the receiving side knows it is unverified.
3. Never invent a plausible-looking value and present it as real, and never leave the origin of a sample unstated.
4. Real data goes on the page as **structure and format only**: field names, types, shapes. Never copy personal data onto the wiki — mask any personal identifier, and prefer describing the format over pasting the value.
5. When `WP-01`'s content type is an API document, the required fields and the new-versus-existing parameter marking are defined in `references/deliver-formats.md`; follow it rather than inventing a layout.
## Hard limits
+19 -7
View File
@@ -1,6 +1,6 @@
---
name: implement
description: SDLC implementation stage. Gate on capability tags enforced in code by sdlc-gate (implement requires coding, verified against the transcript's actual model id), confirm the target branch with the user before writing any file, then claim a ready work package from ANALYZE_CONTENTS with a work ticket and complete its TDD todos one by one, updating the wiki after every item. Ends with jsc-review code-review and an optional MAINTAIN_CONTENTS entry. Use when analysis is done and code must be written; not for planning or analysis.
description: SDLC implementation stage. Gate on capability tags enforced in code by sdlc-gate (implement requires coding), confirm the target branch before writing any file, then claim a ready work package from ANALYZE_CONTENTS with a work ticket and complete its TDD todos one by one, updating the wiki after every item. A delivery package confirms its content type (API document or user-defined) before its first todo. Ends with jsc-review code-review, then always asks which delivery-document format to produce (DELIVER_{HASH} wiki page or Gitea issue comment) before an optional MAINTAIN_CONTENTS entry. Use when analysis is done and code must be written; not for planning or analysis.
---
# implement
@@ -16,19 +16,31 @@ All wiki reads and writes go through `jsc-gitea:wiki`.
3. **Never claim a capability tag you have not verified with that script**, and never substitute your own judgement for its verdict. Non-zero exit = blocked: relay the script's message verbatim, stop the skill, do nothing else this turn. Do not run `unlock` to get past the gate; only the user may decide that.
4. Exit 0 means the stage is locked. From now until the next stage's gate runs, the sdlc-gate hook blocks every prompt whose model stops satisfying the tags.
2. **Confirm the target branch** — do this **before writing any file**:
1. Report the current branch, whether the working tree is clean, and which of `origin/develop` / `origin/master` exist, plus the remote default branch resolved per `/jsc-shared:spec-git-safety`.
1. Report the current branch, whether the working tree is clean, and which of `origin/develop` / `origin/master` exist, plus the remote default branch resolved per `references/branch.md`.
2. Ask per `jsc-ask:ask` rules which branch this work merges into; state the impact scope on every option (the answer decides the PR target and, when it collides with the current branch, forces a new working branch).
3. Uncommitted changes in the working tree → warn first and let the user commit or back them up; never discard them.
4. Apply `/jsc-shared:spec-git-safety` to the confirmed target: source branch and target branch sharing a name means creating a new working branch instead of committing on the target; report the resulting branch name.
4. Apply `references/branch.md` to the confirmed target: source branch and target branch sharing a name means creating a new working branch instead of committing on the target; report the resulting branch name.
5. Record the confirmed target branch on the analysis page next to the work ticket, and reuse it as the PR target in `jsc-git:pr`. Completion condition: the user has confirmed the target branch explicitly; never fall back to `develop` silently.
3. **Generate a work ticket**: format `TICKET_{yyyyMMdd}_{HHmmss}_{HASH}`. `{HASH}` = the shared wiki hash for `{owner}/{repo}`, computed by `jsc-gitea/tools/hash-id` (see `jsc-gitea:wiki`). Try to rename the current session to the ticket name (skip when the CLI does not support it).
4. Read `ANALYZE_CONTENTS` via `jsc-gitea:wiki` and list what is unfinished: plan name, HASH, work package number, count of open items. A selectable work package must satisfy all three: **unfinished, dependency-free (or all dependencies done), and not holding a work ticket**.
5. Let the user pick a work package per `jsc-ask:ask` rules (options state open-item count and estimated effort). **List handover packages (交接 `是`) first** — the analysis page ranks spec delivery ahead of implementation, so keep that order in the options. Write the ticket into that work package's ticket column (the zh-TW field 「工作證」) on the analysis page and save it back to the wiki. **Only after the ticket is saved successfully may you proceed.**
6. List every open item of the work package and implement them **one at a time**:
5. Let the user pick a work package per `jsc-ask:ask` rules (options state open-item count and estimated effort). **List delivery packages (交付 `是`) first** — the analysis page makes `WP-01` the standalone delivery package, so keep that order in the options. Write the ticket into that work package's ticket column (the zh-TW field 「工作證」) on the analysis page and save it back to the wiki. **Only after the ticket is saved successfully may you proceed.**
6. **When the package taken is a delivery/handover package, confirm its content before doing any of its todos**:
1. Ask per `jsc-ask:ask` rules what this delivery must contain. The default options are fixed: **1. API 文件** (endpoint path, **every** input parameter, **every** output parameter) and **2. 由使用者輸入** (the user states the content themselves). State the impact scope on each. **Never assume the type, and never skip this — the answer decides what the whole package produces.**
2. Chose API 文件 → follow `references/deliver-formats.md`: all parameters listed (not just the main ones), each with name, type, required flag, example, data source and new-versus-existing status; sample values take real sources first and are labelled `真實:{來源}` or `推論:無來源`; **an existing endpoint must mark new versus old parameters both ways** — the status column (🆕 新增 / ⚠️ 變更 / ❌ 移除 / blank for untouched) and a `diff` code block for colour. HTML `style` attributes get filtered by the wiki, so never rely on them.
3. Chose 由使用者輸入 → produce exactly what the user described; do not force the API document layout onto it.
4. Record the confirmed type in the analysis page's 交付型別 column and save it before starting the todos.
7. List every open item of the work package and implement them **one at a time**:
- Follow the TDD loop: red before green, one slice at a time; rules and anti-patterns in `references/tdd.md` (refactoring belongs to the review stage).
- After each item, flip its `[ ]` to `[x]` on the analysis page and save to the wiki before starting the next item.
7. When all items are done, call `jsc-review:code-review` and wait for the review; on failure, fix and re-review until it passes.
8. Ask per `jsc-ask:ask` rules whether to register this project for maintenance: append to `MAINTAIN_CONTENTS` with `templates/maintain-contents.md`. Required: repository `{owner}/{repo}`, maintenance method, start date. Optional: end date (NULL = maintain forever), last-maintained time.
8. When all items are done, call `jsc-review:code-review` and wait for the review; on failure, fix and re-review until it passes.
9. **Delivery document** — a finished work package is a delivery, so **always ask before producing it; never pick a format silently and never skip this step**:
1. Ask per `jsc-ask:ask` rules which format to produce. The options are fixed: **a `DELIVER_{HASH}` wiki page** or **a Gitea issue comment**. State the impact scope on each (the wiki page lives beside the plan and analysis pages; the issue comment reaches whoever follows that issue).
2. Both formats use the same structure — `templates/deliver-page.md`, in Traditional Chinese. Only the destination differs.
3. Wiki page: write `DELIVER_{HASH}` through `jsc-gitea:wiki`, where `{HASH}` comes from `jsc-gitea/tools/hash-id` over `{owner}/{repo}` plus the work package number (for example `plugins/sdlc#WP-01`), so each work package gets its own page instead of overwriting the previous one. A new page is added to `DELIVER_CONTENTS` per `templates/deliver-contents.md`.
4. Issue comment: confirm the issue number with the user (propose the one referenced by the work package or the PR; never guess), then post via `gitea/tools/gitea.sh api POST /repos/{owner}/{repo}/issues/{n}/comments` with the body passed in as a UTF-8 file — real newlines, never a literal `\n`.
5. Sample values follow the analysis page's 資料來源 column: `真實:{來源}` for real sources, `推論:無來源` for reasoned ones. Personal data never goes in — keep the field and format, drop the value.
6. Completion condition: the chosen format has actually been produced, and you have reported where it landed (wiki page name, or the comment URL).
10. Ask per `jsc-ask:ask` rules whether to register this project for maintenance: append to `MAINTAIN_CONTENTS` with `templates/maintain-contents.md`. Required: repository `{owner}/{repo}`, maintenance method, start date. Optional: end date (NULL = maintain forever), last-maintained time.
## Rules
+4 -1
View File
@@ -20,10 +20,12 @@ All wiki reads and writes go through `jsc-gitea:wiki`.
4. Exit 0 means the stage is locked. From now until the next stage's gate runs, the sdlc-gate hook blocks every prompt whose model stops satisfying the tags.
2. Read `PLAN_CONTENTS` via `jsc-gitea:wiki` and list the plans whose status is the literal 「未分析」 (not analyzed), with names and HASH.
3. Let the user choose per `jsc-ask:ask` rules: **extend an existing plan** (list the not-analyzed plans as options) or **create a new plan**. State the impact scope on every option.
4. Question via the `jsc-ask:ask` decision tree until no doubt remains on all three items; keep asking while consensus is missing:
4. **Keep questioning until consensus** — rules in `references/consensus.md`, which is the single authority for both planning and analysis. Cover all three items:
- Goal: the problem to solve and the criteria for success.
- Scope: what is included, what is excluded, which repositories are involved.
- Feasibility: whether the system architecture and data sources support the goal.
**One round is never enough**: every answer must produce the next question, derived from what that answer just exposed. Consensus needs both conditions from `references/consensus.md` — no remaining unknown that would change the output, **and** the user's explicit confirmation of the summary you read back. Never fill a gap with your own assumption, and never move on to user stories while any item is still open.
5. Turn the consensus into **user stories** (the zh-TW pattern 「身為⋯⋯我想要⋯⋯以便⋯⋯」), one per line.
6. Apply `templates/plan-page.md` to create or update the plan page, and write it back via `jsc-gitea:wiki`. The page content is Traditional Chinese, exactly as the template dictates.
7. If the plan page is new, add it to `PLAN_CONTENTS` using the entry format of `templates/plan-contents.md`, with status set to the literal 「未分析」.
@@ -33,3 +35,4 @@ All wiki reads and writes go through `jsc-gitea:wiki`.
- Never output a code snippet.
- Never modify any file in the working directory.
- Never skip the decision tree and assume requirements.
- Never stop questioning after one round; consensus is reached only under `references/consensus.md`, and the user says so.
+24 -13
View File
@@ -14,28 +14,39 @@
- 複用來源:[[REPO_{HASH}]](commit sha:`{sha}`)
- 複用決策:{複用哪些方法/端點、為什麼;不複用的原因}
## 未決項
<!-- 使用者尚未決定的項目;沒有就寫「無」。不得靜默消失。 -->
| 項目 | 影響 | 預設處理 | 待決定者 |
| --- | --- | --- | --- |
| {項目} | {不決定會怎樣} | {暫定做法} | {誰} |
## 工作分解結構(WBS)
交接工作包(規格、介面、驗收條件)排在實作工作包之前;實作為候補。相依關係優先於交接排序。
`WP-01` 固定是交付/交接工作包,獨立成一包,不與實作合併;用到它規格的實作工作包相依於它。
交付型別於實作階段開工時確認(API 文件/由使用者輸入)。
資料來源欄記錄範例資料的出處:`真實:{來源}` 或 `推論:無來源`。
| 編號 | 工作包名稱 | 交接 | 相依 | 工時(h) | 天數 | 資料來源 | 工作證 | 狀態 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| WP-01 | {規格類名稱} | 是 | - | {h} | {d} | 真實:{來源} | | 未完成 |
| WP-02 | {交接文件名稱} | 是 | WP-01 | {h} | {d} | 真實:{來源} | | 未完成 |
| WP-03 | {實作類名稱} | 否 | WP-01 | {h} | {d} | 推論:無來源 | | 未完成 |
| 編號 | 工作包名稱 | 交付 | 交付型別 | 相依 | 工時(h) | 天數 | 資料來源 | 工作證 | 狀態 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| WP-01 | {交付/交接:規格與介面定義} | 是 | API 文件 | - | {h} | {d} | 真實:{來源} | | 未完成 |
| WP-02 | {實作類名稱} | 否 | - | WP-01 | {h} | {d} | 真實:{來源} | | 未完成 |
| WP-03 | {實作類名稱} | 否 | - | WP-01 | {h} | {d} | 推論:無來源 | | 未完成 |
- 關鍵路徑:{WP-01 → WP-03 → ⋯⋯},總天數 {d}
- 交接批次:{WP-01、WP-02};實作候補:{WP-03、⋯⋯}
- 關鍵路徑:{WP-01 → WP-02 → ⋯⋯},總天數 {d}
- 實作候補:{WP-02、WP-03、⋯⋯}
## 待辦事項(TDD)
### WP-01 {工作包名稱}
### WP-01 {交付/交接工作包名稱}
- [ ] 盤點端點與參數:{對象}
- [ ] 產出規格與範例資料(標明真實/推論)
- [ ] 與使用者確認交付內容並產出交付文件
### WP-02 {工作包名稱}
- [ ] 撰寫 {對象} 的測試:{預期行為}
- [ ] 實作 {對象} 使測試通過
- [ ] 重構 {對象} 並保持測試綠燈
### WP-02 {工作包名稱}
- [ ] ⋯⋯
+7
View File
@@ -0,0 +1,7 @@
# 交付目錄
<!-- 交付欄:是 = 交付/交接工作包(WP-01),接手者要據此動工;否 = 實作類工作包。 -->
| 計畫名稱 | 工作包 | 交付 | 交付型別 | 交付頁 | HASH | 存取庫 | 交付時間 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| {計畫名稱} | WP-01 {工作包名稱} | 是 | API 文件 | [[DELIVER_{HASH}|{WP-01 工作包名稱}]] | {HASH} | {owner}/{repo} | {yyyy-MM-dd HH:mm:ss} |
+81
View File
@@ -0,0 +1,81 @@
# 交付:{計畫名稱} {WP-nn} {工作包名稱}
- 頁名:`DELIVER_{HASH}`
- HASH:`{HASH}`
- 對應分析:[[ANALYZE_{HASH}]]
- 存取庫:`{owner}/{repo}`
- 目標分支:`{使用者確認的目標分支}`
- 工作證:`TICKET_{yyyyMMdd}_{HHmmss}_{HASH}`
- 交付工作包:是 <!-- 是 | 否 -->
- 交付型別:API 文件 <!-- API 文件 | 由使用者輸入:{說明} -->
- 交付時間:{yyyy-MM-dd HH:mm:ss}
## 交付內容
| 項目 | 說明 |
| --- | --- |
| 這次交付什麼 | {一句話講清楚接手者拿到什麼} |
| 接手者需要做什麼 | {下一步動作;沒有就寫「無」} |
| 尚未交付的部分 | {留在候補的實作工作包,或寫「無」} |
## API 文件
<!-- 交付型別為「由使用者輸入」時,本節改成使用者指定的內容,不套下面的格式。 -->
### {方法} {端點路徑}
- 端點狀態:本次新增 <!-- 本次新增 | 既有端點 -->
- 說明:{這個端點做什麼}
標示規則:🆕 **新增**、⚠️ **變更**、❌ **移除**(含淘汰時程)、既有參數留空。
資料來源:`真實:{來源}` 或 `推論:無來源`。範例只留格式,個資不留值。
#### 輸入參數(全部)
| 參數 | 位置 | 型別 | 必填 | 範例 | 資料來源 | 狀態 |
| --- | --- | --- | --- | --- | --- | --- |
| {name} | path/query/header/body | {型別} | 是/否 | {值} | 真實:{來源} | 🆕 **新增** |
#### 輸出參數(全部)
| 參數 | 型別 | 說明 | 範例 | 資料來源 | 狀態 |
| --- | --- | --- | --- | --- | --- |
| {name} | {型別} | {說明} | {值} | 真實:{來源} | |
#### 錯誤回應
| 狀態碼 | 條件 | 回應結構 |
| --- | --- | --- |
| {400} | {條件} | {結構} |
#### 新舊差異
<!-- 既有端點必附;本次新增的端點可省略。diff 區塊會被 Gitea 上色,不要用 HTML style。 -->
```diff
{方法} {端點路徑}
{既有參數} {型別} {必填}
+ {新增參數} {型別} {必填} {預設值}(本次新增)
- {移除參數} {型別} {必填} (本次移除,{日期} 前相容)
! {變更參數} {型別} {必填} (本次變更:{變更內容})
```
### 驗收條件
- [ ] {可驗證的條件}
## 變更檔案
| 檔案 | 變更 |
| --- | --- |
| `{path}` | {做了什麼} |
## 驗證方式
| 項目 | 指令或步驟 | 結果 |
| --- | --- | --- |
| {測試} | `{指令}` | {通過/失敗} |
## 已知限制
- {限制或風險;沒有就寫「無」}