review 抓到一個沉默的失效:rollback 最後那一手「git 清不乾淨時把目錄本身也清掉」呼叫 rmSync,但把這段從 branch-prep 搬進 lib 時,import 留在了原處。那一行落在自己的 try/catch 裡,所以 ReferenceError 被吞掉——註解承諾的事從來沒發生過,而且測試全綠。 下一次重跑會撞上 WORKTREE_PATH_TAKEN,人看到的是一句與真正原因無關的錯誤。 順手收掉兩支腳本各寫一次的 origin 檢查(只有「為什麼需要它」那一句不同,由呼叫端給), 並把 lib 檔頭「負責六件事」改成七件——工作樹的一生現在整個住在這裡。 正本三處跟著改: - 查現況那一行補上 --dry-run。pr-watch 在 PR 已終止時會順手清掉工作樹,而「我想看一下 留言」不該把清理順便做掉——清不清理是使用者的決定。 - 拿掉「使用者堅持要繼續就繼續」:它與同一份正本的邊界(已合併或關閉時不繼續處理留言) 直接矛盾,而在一棵該被清掉的工作樹上改東西,那些改動不會進到任何 PR 裡。 - worktree-ensure 的指令補上 --path:目標專案多半不是當前目錄,而「不必先手動 cd」 正是這一步要解決的問題。 議題 #42 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
152 lines
7.5 KiB
Markdown
152 lines
7.5 KiB
Markdown
name: sdlc-fix
|
||
description: 僅由 /sdlc-fix 指令叫用。定位工作包的工作樹,讀取 PR 上的三類留言,逐條處理並回覆,最後輸出修正摘要。
|
||
|
||
# sdlc-fix
|
||
|
||
reviewer 留完意見,跑這一段,意見被逐條處理並回覆,不漏掉任何一則。
|
||
|
||
這份檔案是流程正本。各平台的轉接檔只是指回這裡,不要把規則抄過去。
|
||
|
||
## 輸入
|
||
|
||
一個 PR 編號。
|
||
|
||
## 1. 看 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` 是
|
||
推導出的路徑上有別的東西,請使用者自己確認後移除——**不要自己刪**。
|
||
|
||
**後面每一步都在那棵工作樹裡做**,不要回到主工作區:它可能停在別的分支上,在那裡改
|
||
會把改動落到別顆工作包的分支去。
|
||
|
||
## 2. 讀留言
|
||
|
||
```
|
||
node scripts/pr-comments.js --repo <owner/name> --index <PR 編號>
|
||
```
|
||
|
||
三類留言一次讀齊:**一般留言**、**review 總評**、**行內留言**。每一則都帶 `id`、`作者`、
|
||
`內容`、`已處理`,行內的還帶 `檔案`/`行`/`diff`——那段 diff 是判斷「他在說哪裡」的依據,
|
||
不要略過不看。
|
||
|
||
**先看 `未處理數`。** 它是這一輪要處理的量;`已處理` 為 `true` 的那些是前一輪做過的,
|
||
跳過不再處理。
|
||
|
||
**三類都標記得了,機制不同**:一般留言與 review 總評用 `+1` reaction,行內留言用
|
||
resolve。`已處理` 認的是**自己打的** `+1`——reviewer 對留言按讚是「我同意」,不是
|
||
「這則處理過了」。
|
||
|
||
偶爾會遇到 `可標記` 是 `false` 的總評(在 timeline 上對不到它在 issue comment 表裡的
|
||
那一份)。那一則回覆照發,但沒有記號留得下來,**要在修正摘要裡單獨點出來**。
|
||
|
||
## 3. 分類:必改還是建議
|
||
|
||
逐則判斷,**reviewer 不必逐則說明**。判斷依據是內容本身:
|
||
|
||
- **必改** — 指出了錯誤、遺漏、會出事的寫法,或明確要求改動。
|
||
- **建議** — 提出另一種做法、風格偏好、「之後可以考慮」。
|
||
|
||
分類結果**先呈現給使用者**再動手:列出每一則的「類型/作者/一句話摘要/你的分類」。
|
||
分類錯的代價不對稱——把必改當成建議會漏掉真的問題,所以拿不準時歸到必改那一邊,
|
||
並在下一步問清楚。
|
||
|
||
## 4. 不確定就問
|
||
|
||
**一次問一題。** 下列情況不要自作主張:
|
||
|
||
- 分不出必改還是建議。
|
||
- 知道要改,但有兩種以上做法,而選擇會影響別處。
|
||
- 留言本身看不懂,或它指的位置與現在的程式碼對不上(PR 之後又推了新 commit 是常見原因)。
|
||
|
||
每一題給兩個選項,並附上你判斷的理由:
|
||
|
||
- **建議** — 你的答案,寫「為什麼是這個」。
|
||
- **手動輸入** — 讓使用者自己說。
|
||
|
||
**不確定卻硬改,比多問一題貴得多。** 改壞的地方 reviewer 下一輪才會看到。
|
||
|
||
## 5. 逐則處理並回覆
|
||
|
||
一則一則來:先改,改完立刻回覆那一則,再處理下一則。**不要全部改完才一起回**——
|
||
中途斷掉的話,沒有人知道哪幾則已經處理過。
|
||
|
||
```
|
||
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 以為被忽略了。
|
||
|
||
## 6. 修正摘要
|
||
|
||
全部處理完後印一則摘要,讓 reviewer 不必逐串點開:
|
||
|
||
- **必改幾則、建議幾則**,各自處理了幾則、不改幾則。
|
||
- **逐則一行**:作者/一句話原意/你的處置。
|
||
- **沒有留下記號的那幾則**(`可標記` 為 `false`,或腳本回報 `已標記: false`)要單獨
|
||
列出來,否則 reviewer 掃 reaction 與 resolve 時會以為它們被跳過了。
|
||
- **問過使用者的題目與答案**。
|
||
- 有沒有留言因為指向的程式碼已經變了而無法處理。
|
||
|
||
摘要只印在終端,**不自動張貼到 PR 上**。要不要貼由使用者決定。
|
||
|
||
## 邊界
|
||
|
||
- 不改與留言無關的程式碼。順手看到的問題記下來說出來,不要摸進這一輪。
|
||
- 不自行判斷不確定的事——寧可多問一題。
|
||
- 不跳過任何一則留言。決定不改的也要回覆並說明理由。
|
||
- 不在回覆沒成功時標記已處理。
|
||
- **不自動張貼修正摘要**,也不自動關閉或合併 PR。
|
||
- 不動 PR 的 review 狀態:回覆一則意見不該順手把整個 PR 標成通過或要求變更。
|
||
- **不在主工作區處理留言**,一律在 `worktree-ensure` 定位出來的那棵工作樹裡。
|
||
- PR 已經合併或關閉時不繼續處理留言,也不自己去刪推導路徑上的東西。
|