docs(sdlc-feat): 第三段收尾指向 pr-watch 與手動清理

PR 開出去之後流程就斷在那裡,使用者不會知道有東西可以查現況、也不會知道工作樹會被
自動清掉。收尾補一步,把兩支腳本講給使用者聽,並明講「多久跑一次由他自己排」。

邊界同時擋住兩件事:agent 不自己反覆跑 pr-watch,也不因為它建議了 run-sdlc-fix 就
自己去跑 /sdlc-fix——流程只由使用者明確叫用。

議題 #41

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-17 16:59:30 +08:00
co-authored by Claude Opus 5
parent d331bef1ed
commit 32edd65962
2 changed files with 36 additions and 0 deletions
+23
View File
@@ -306,6 +306,27 @@ repo**(錶停在那裡)。兩者常常不是同一個——議題在需求
- 碼錶是否已停;沒停的話把腳本回的那句說明一起帶出來 - 碼錶是否已停;沒停的話把腳本回的那句說明一起帶出來
- 議題上還有沒有沒勾完的待辦(理論上應該沒有;有的話要說出來) - 議題上還有沒有沒勾完的待辦(理論上應該沒有;有的話要說出來)
### 17. 告訴使用者之後怎麼查
PR 開出去之後就交給 reviewer 了。**把下面這件事講給使用者聽,不要自己反覆跑**:
```
node scripts/pr-watch.js --repo <owner/name> --index <PR 編號>
```
問一次答一次:PR 狀態、還有幾則留言沒處理、工作樹在哪、裡面有沒有沒提交的東西,
以及固定列舉值的 `suggestedAction`(`run-sdlc-fix`/`cleanup`/`nothing-to-do`/
`blocked-dirty`)。多久跑一次由使用者自己排(cron 或他自己的循環機制),
本工具不長出排程器。
PR 合併或關閉時它會順手清掉那棵工作樹,**本機分支與遠端分支都留著**;工作樹裡還有
沒提交的東西就會擋下來(`blocked-dirty`),由使用者自己處理。永遠不會被合併也不會被
關閉的那些 PR,用手動出口清:
```
node scripts/worktree-remove.js --repo <owner/name> --branch <分支名>
```
## 邊界 ## 邊界
- 第一段**不改任何一行程式碼**、不勾待辦、不提交、不開 PR——那些是後面幾段的事。 - 第一段**不改任何一行程式碼**、不勾待辦、不提交、不開 PR——那些是後面幾段的事。
@@ -321,6 +342,8 @@ repo**(錶停在那裡)。兩者常常不是同一個——議題在需求
- 不把實作規範或註解格式寫進目標專案的任何檔案。 - 不把實作規範或註解格式寫進目標專案的任何檔案。
- 不改與待辦無關的程式碼;順手想修的東西記下來說出來,不要摸進這次的變更裡。 - 不改與待辦無關的程式碼;順手想修的東西記下來說出來,不要摸進這次的變更裡。
- 不為了勾選在議題上留留言。 - 不為了勾選在議題上留留言。
- **不自動反覆執行 `pr-watch`**,也不因為它建議了 `run-sdlc-fix` 就自己去跑 `/sdlc-fix`——
流程只由使用者明確叫用。
- 不自行建立標籤。缺「進行中」標籤時中止並請使用者建立。 - 不自行建立標籤。缺「進行中」標籤時中止並請使用者建立。
- 不代替使用者停錶,也不在被鎖擋下時繞過去。 - 不代替使用者停錶,也不在被鎖擋下時繞過去。
- 不替使用者決定來源分支。 - 不替使用者決定來源分支。
+13
View File
@@ -133,6 +133,19 @@ test('邊界把第一段不做的事分開列,且明講不寫本機狀態檔',
assert.match(boundary, /換一台機器或換一個 agent/, '要說明為什麼不留狀態檔'); assert.match(boundary, /換一台機器或換一個 agent/, '要說明為什麼不留狀態檔');
}); });
test('第三段收尾時告訴使用者之後怎麼查 PR,但不自己反覆跑', () => {
assert.match(phase3, /pr-watch\.js/);
assert.match(phase3, /worktree-remove\.js/, '手動清理的出口也要講,否則沒人知道它在');
assert.match(phase3, /不要自己反覆跑/);
assert.match(phase3, /suggestedAction/, '建議動作是列舉值,要讓使用者知道有這個東西可以判斷');
});
test('邊界擋住「監看報了就自己去跑 sdlc-fix」', () => {
const boundary = prompt.slice(prompt.indexOf('## 邊界'));
assert.match(boundary, /不自動反覆執行 `pr-watch`/);
assert.match(boundary, /只由使用者明確叫用/);
});
// ── 第二段:逐項實作 ─────────────────────────────────────────────── // ── 第二段:逐項實作 ───────────────────────────────────────────────
test('第二段明講改的是工作樹裡的檔案,不是主工作區', () => { test('第二段明講改的是工作樹裡的檔案,不是主工作區', () => {