Files
tea-sdlc/prompts/sdlc-fix.md
T
jiantw83andClaude Opus 5 a5f36ed14c feat(sdlc-fix): 輸入放寬為 PR 編號或議題編號
議題不自己重做一遍實作流程,而是交棒給 /sdlc-feat:工作包議題直接交棒,
需求議題先讓 /sdlc-sync 整併決策留言,剩下確實要改碼的才列出底下的工作包
讓使用者挑一顆。交棒複用 sdlc-sync 已經定好的接回機制,使用者不必重打指令。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 18:16:23 +08:00

235 lines
12 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.
name: sdlc-fix
description: 僅由 /sdlc-fix 指令叫用。收 PR 或議題編號:PR 就定位工作樹、逐條處理三類留言並回覆;議題則交棒給 /sdlc-feat。
# sdlc-fix
reviewer 留完意見,跑這一段,意見被逐條處理並回覆,不漏掉任何一則。
**意見不一定發在 PR 上。** 常常是發在工作包議題或需求議題的留言裡:使用者手上只有一個
議題編號,看得到有人說「這裡要改」。所以輸入收得下三種東西,但只有 PR 在這裡處理完——
議題交棒給 `/sdlc-feat`,不在這裡重做一遍它的流程。
這份檔案是流程正本。各平台的轉接檔只是指回這裡,不要把規則抄過去。
## 輸入
一個 PR 編號或議題編號。
## 1. 判定輸入是哪一種
三種輸入走三條不同的路,先問清楚是哪一種再動手。**判定沿用既有契約,不另發明判準**——
標籤、標題前綴、編號區間都猜得出來,但猜錯的代價是整條路走錯。
先讀一次留言。它議題與 PR 都收得下,`類型` 欄位就是 PR 與議題的分界:
```
node scripts/pr-comments.js --repo <owner/name> --index <編號>
```
**每個 PR 都是議題,反過來不成立**,所以這個問題只能從議題那一端問:先打 PR 的端點,
遇到純議題會 404,在讀到第一則留言之前就斷了。
`類型` 是 `議題` 時再問一次它是哪一種議題:
```
node scripts/wp-extract.js --repo <owner/name> --index <編號>
```
**`需求議題` 欄位(工作包的母議題)解析得出編號的就是工作包議題,解析不出來的就當需求
議題。** 這是工作包抽取契約本來就有的欄位,`/sdlc-sync` 分這兩種議題用的也是同一份抽取。
| 判定 | 下一步 |
| --- | --- |
| `類型` 為 `PR` | 第 3 步起,這份正本後面每一步都是 PR 的路 |
| `類型` 為 `議題`,抽得出 `需求議題` | 第 2 步的「工作包議題」 |
| `類型` 為 `議題`,抽不出 `需求議題` | 第 2 步的「需求議題」 |
## 2. 議題:交棒給 /sdlc-feat
### 工作包議題
那一顆工作包該怎麼做,`/sdlc-feat`(`prompts/sdlc-feat.md`)已經從領取、備妥工作樹、
逐項實作一路定到開出 PR。**照那份正本走,把這個編號當成它的輸入。**
**不要把它的步驟搬過來重講一遍**:那會製造第二份正本,兩邊遲早分岔——而使用者不會知道
自己讀到的是哪一份。
交棒沿用 `/sdlc-sync` 那一套接回機制,只是方向相反:**直接接下去做,不要求使用者重打
指令**。他已經給過這個編號了。
留言的整併不必在這裡先做——`/sdlc-feat` 的第一步就會看 `未處理留言數`,該整併時它自己
會轉去 `/sdlc-sync`。在這裡先做一次,等於把那一步也抄了過來。
### 需求議題
需求議題上的留言**絕大多數是決策討論**,不是「這一行要改」。所以先整併,再談改碼:
1. 第 1 步的 `未處理數` 大於 0 就**走 `/sdlc-sync` 的流程**(`prompts/sdlc-sync.md`),
做完**自動接回這裡**——重新讀一次留言,拿到的才是剛整併過的狀態。同樣不要求使用者重打指令。
2. 整併(與使用者選擇略過)之後還剩下的留言裡,挑出**確實要求改程式碼**的那幾則。判斷
依據與第 5 步的「必改/建議」同一套:指出了錯誤、遺漏、會出事的寫法,或明確要求改動。
3. **一則都沒有就到此為止。** 把整併了幾則、略過幾則講清楚,說明沒有要改碼的意見,
然後停下來。先 sync 一次通常就清空了,選工作包那一步根本不會觸發。
確實有要改的,就列出這顆需求底下的工作包,讓使用者挑一顆:
```
node scripts/wp-list.js --repo <owner/name> --requirement <需求議題編號>
```
**不要因為「輸入不是工作包」就報錯。** 挑哪一顆他無論如何都要挑,報錯只是把這件事推回去
讓他自己在 Gitea 網頁上翻。
一次問一題,選項是清單上的工作包(帶編號、標題、狀態、領取人),外加**手動輸入**——
清單以「關聯」段落認歸屬,漏掉的那一顆他自己給得出編號。附上你的判斷:哪一顆的範圍
涵蓋得到那幾則留言說的地方,以及為什麼。
清單是空的就照實說:這顆需求底下還沒有工作包,該跑的是 `/sdlc-analyze`,不是這一支。
挑定之後**交棒給 `/sdlc-feat`**,與上一小節同一條路。**把那幾則要求改碼的留言一起帶過去**,
它們是這一輪要做的事;留言本身留在需求議題上不動,交棒不搬走任何人說過的話。
## 3. 看 PR 現況,並定位工作樹
先問一次現況,再決定要不要動手:
```
node scripts/pr-watch.js --repo <owner/name> --index <PR 編號> --dry-run
```
**這裡要帶 `--dry-run`**:`pr-watch` 在 PR 已終止時會順手清掉工作樹,而這一步只是要
知道現況——清不清理是使用者的決定,不該由「我想看一下留言」這個動作順便做掉。
**`terminal` 為 `true`(PR 已合併或已關閉)時就停下來,不要繼續處理留言。** 那顆工作包
已經結束,在一棵該被清掉的工作樹上改東西是白做工,而且那些改動不會進到任何 PR 裡。
把 `suggestedAction` 的意思講給使用者聽,讓他決定下一步:
| 值 | 意思 |
| --- | --- |
| `nothing-to-do` | 沒事了;工作樹不在或已經清掉 |
| `cleanup` | 工作樹還在,可以用 `worktree-remove` 清掉 |
| `blocked-dirty` | 那棵工作樹裡還有沒提交的東西,要他自己處理 |
PR 還開著就定位工作樹。輸入是 `pr-watch` 給的 `branch`——路徑由「哪顆工作包」推導,
不必也不該由使用者自己去記那串雜湊目錄名:
```
node scripts/worktree-ensure.js --repo <owner/name> --path <目標專案路徑> \
--branch <pr-watch 給的 branch> --dry-run
```
`--path` 是目標專案在本機的位置(工作包 `repos` 列的那一顆),不給就用當前目錄——
而當前目錄多半不是它,這正是這一步要解決的問題。
試跑會印出推導出的路徑與將執行的 git 指令;確認無誤後拿掉旗標再跑一次。
**推導出的路徑不存在時它會重建,那是常態不是例外**:進度完全不寫在本機,換一台機器
或換一個 agent 接手時工作樹本來就不在,重建的成本就是一次 `git worktree add`。
重建走的是與開工時同一套建立方式,分支上已經有的進度會被接上,不是長一棵空的。
兩種會被擋下來的情況照實說,不要繞過去:`BRANCH_NOT_FOUND` 是那一支分支在本機與遠端
都不見了(多半是 PR 已經合併而分支被刪,回頭確認 PR 狀態);`WORKTREE_PATH_TAKEN` 是
推導出的路徑上有別的東西,請使用者自己確認後移除——**不要自己刪**。
**後面每一步都在那棵工作樹裡做**,不要回到主工作區:它可能停在別的分支上,在那裡改
會把改動落到別顆工作包的分支去。
## 4. 讀留言
```
node scripts/pr-comments.js --repo <owner/name> --index <PR 編號>
```
第 1 步判定型別時讀的就是這一份,**手上那一份還在就直接用,不必再讀一次**。
三類留言一次讀齊:**一般留言**、**review 總評**、**行內留言**。每一則都帶 `id`、`作者`、
`內容`、`已處理`,行內的還帶 `檔案`/`行`/`diff`——那段 diff 是判斷「他在說哪裡」的依據,
不要略過不看。
**先看 `未處理數`。** 它是這一輪要處理的量;`已處理` 為 `true` 的那些是前一輪做過的,
跳過不再處理。
**三類都標記得了,機制不同**:一般留言與 review 總評用 `+1` reaction,行內留言用
resolve。`已處理` 認的是**自己打的** `+1`——reviewer 對留言按讚是「我同意」,不是
「這則處理過了」。
偶爾會遇到 `可標記` 是 `false` 的總評(在 timeline 上對不到它在 issue comment 表裡的
那一份)。那一則回覆照發,但沒有記號留得下來,**要在修正摘要裡單獨點出來**。
## 5. 分類:必改還是建議
逐則判斷,**reviewer 不必逐則說明**。判斷依據是內容本身:
- **必改** — 指出了錯誤、遺漏、會出事的寫法,或明確要求改動。
- **建議** — 提出另一種做法、風格偏好、「之後可以考慮」。
分類結果**先呈現給使用者**再動手:列出每一則的「類型/作者/一句話摘要/你的分類」。
分類錯的代價不對稱——把必改當成建議會漏掉真的問題,所以拿不準時歸到必改那一邊,
並在下一步問清楚。
## 6. 不確定就問
**一次問一題。** 下列情況不要自作主張:
- 分不出必改還是建議。
- 知道要改,但有兩種以上做法,而選擇會影響別處。
- 留言本身看不懂,或它指的位置與現在的程式碼對不上(PR 之後又推了新 commit 是常見原因)。
每一題給兩個選項,並附上你判斷的理由:
- **建議** — 你的答案,寫「為什麼是這個」。
- **手動輸入** — 讓使用者自己說。
**不確定卻硬改,比多問一題貴得多。** 改壞的地方 reviewer 下一輪才會看到。
## 7. 逐則處理並回覆
一則一則來:先改,改完立刻回覆那一則,再處理下一則。**不要全部改完才一起回**——
中途斷掉的話,沒有人知道哪幾則已經處理過。
```
node scripts/pr-reply.js --repo <owner/name> --index <PR 編號> \
--comment <留言 id> --kind inline|general|review --body '<回覆>' --dry-run
```
`--kind` 對應 `pr-comments` 給的 `類型`:`行內` → `inline`、`一般` → `general`、
`總評` → `review`。**三類留言的 id 各自獨立**,`--kind` 給錯會找不到那一則。
腳本自己會去查行內留言的位置(含它在新檔還是被刪掉的那一側)與它所屬的 commit,
把回覆放回同一串;也會在回覆成功之後才標記(行內用 resolve,一般與總評用 `+1`)。
回覆失敗就不標記——沒回卻標記等於謊稱處理過。
**留言指向的程式碼已經被改掉時**,回覆可能會被 Gitea 拒絕(位置對不上)。那時不要硬試,
把那一則列進摘要的「無法處理」,讓使用者自己去 PR 上回。
**回覆要說出做了什麼**,不是「已修正」。reviewer 看回覆就要知道改法對不對,
不必自己去翻 diff。決定不改的也要回,並說明理由——建議類的留言常常合理地不採納,
但沉默會讓 reviewer 以為被忽略了。
## 8. 修正摘要
全部處理完後印一則摘要,讓 reviewer 不必逐串點開:
- **必改幾則、建議幾則**,各自處理了幾則、不改幾則。
- **逐則一行**:作者/一句話原意/你的處置。
- **沒有留下記號的那幾則**(`可標記` 為 `false`,或腳本回報 `已標記: false`)要單獨
列出來,否則 reviewer 掃 reaction 與 resolve 時會以為它們被跳過了。
- **問過使用者的題目與答案**。
- 有沒有留言因為指向的程式碼已經變了而無法處理。
摘要只印在終端,**不自動張貼到 PR 上**。要不要貼由使用者決定。
## 邊界
- 不改與留言無關的程式碼。順手看到的問題記下來說出來,不要摸進這一輪。
- 不自行判斷不確定的事——寧可多問一題。
- 不跳過任何一則留言。決定不改的也要回覆並說明理由。
- 不在回覆沒成功時標記已處理。
- **不自動張貼修正摘要**,也不自動關閉或合併 PR。
- 不動 PR 的 review 狀態:回覆一則意見不該順手把整個 PR 標成通過或要求變更。
- **不在主工作區處理留言**,一律在 `worktree-ensure` 定位出來的那棵工作樹裡。
- PR 已經合併或關閉時不繼續處理留言,也不自己去刪推導路徑上的東西。
- **不重做 `/sdlc-feat` 的步驟,也不把它的步驟抄進這份正本**:議題一律交棒過去。
- 不因為輸入是議題就報錯要使用者改打別的指令,也不要求他把交棒過的指令重打一次。
- 不替使用者決定要在哪一顆工作包上改:列出清單,讓他挑。