fix/pr-head-after-merge/main #51

Merged
admin merged 1 commits from fix/pr-head-after-merge/main into master 2026-09-17 09:19:26 +00:00
Member

摘要

PR 合併之後,pr-watch 真的清得掉那棵工作樹了。

需求議題

#38 — 以 worktree 隔離平行工作包的實作與修正

工作包議題

#50 — 修正 pr-watch 在 PR 合併後推導錯工作樹路徑

變更內容

  • scripts/pr-watch.js:新增 headBranch(),分支名改從 head.label 取;
    head.ref 只在 label 缺席且它不是 refs/pull/… 時當備援;兩邊都取不到時以
    PULL_HEAD_MISSING 中止,並指出手動出口 worktree-remove 怎麼指名那一棵。
  • test/pr-watch.test.js:假的 PR 可以指定 head 的樣子,新增三條測試——
    已合併且來源分支已刪、fork 的 owner:branch label、兩邊都取不到。

設計重點

為什麼不能只看 head.ref。 Gitea 在 PR 合併而來源分支被刪掉之後,把 head.ref
換成 refs/pull/{編號}/head,分支名退到 head.label:

PR 狀態 head.ref head.label
#48 已合併、來源分支已刪 refs/pull/48/head feat/pr-watch-and-cleanup/main
#46 已合併、來源分支已刪 refs/pull/46/head feat/worktree-branch-prep/main

而合併正是唯一該清理工作樹的時機,所以這個 bug 的效果是自動清理在真實情況下從來
不會成立
:推導出一條不存在的路徑,然後回報 nothing-to-do,靜悄悄地什麼都沒做。

為什麼備援要擋掉 refs/pull/…。 那不是分支名,拿它推導只會得到另一條不存在的
路徑——寧可說「讀不到來源分支名」,並告訴使用者改用 worktree-remove --branch。
靜默地算出一條錯路徑,比明確中止難查得多。

測試先前為什麼沒抓到。 假的 PR 一律照「開著的 PR」寫,head.ref 永遠是分支名。
補的正是合併後那一種——這一顆 bug 是在真實環境用它清自己的工作樹時撞出來的。

解決的問題

/sdlc-feat 開出 PR、PR 被合併之後,使用者跑 pr-watch 會得到「工作樹不在、沒事要做」,
而那棵工作樹其實還在 ~/.tea-sdlc/worktrees/ 底下,永遠不會被清掉,也沒有任何訊息
提示他。集中目錄會無限長大,而那正是 #38 要它自動清理的理由。

影響的功能

只動 pr-watch 取分支名的那一段。回報欄位、四種 PR 狀態的處置、清理的守門規則都不變,
既有測試原封通過。worktree-remove 不受影響——它吃 --branch,本來就不做推導。

測試結果

npm test
ℹ tests 727
ℹ pass 727
ℹ fail 0

新增三條(先紅後綠):合併且來源分支已刪、fork 的 label、兩邊都取不到。

另外對真的 #48(已合併)跑過一次:

修正前 "branch":"refs/pull/48/head"  → 路徑 .../bb4f5127f641(不存在)
修正後 "branch":"feat/pr-watch-and-cleanup/main" → 路徑 .../bd457620184e(真正的那一棵)

🤖 Generated with Claude Code

## 摘要 PR 合併之後,`pr-watch` 真的清得掉那棵工作樹了。 ## 需求議題 #38 — 以 worktree 隔離平行工作包的實作與修正 ## 工作包議題 #50 — 修正 pr-watch 在 PR 合併後推導錯工作樹路徑 ## 變更內容 - `scripts/pr-watch.js`:新增 `headBranch()`,分支名改從 `head.label` 取; `head.ref` 只在 label 缺席且它不是 `refs/pull/…` 時當備援;兩邊都取不到時以 `PULL_HEAD_MISSING` 中止,並指出手動出口 `worktree-remove` 怎麼指名那一棵。 - `test/pr-watch.test.js`:假的 PR 可以指定 `head` 的樣子,新增三條測試—— 已合併且來源分支已刪、fork 的 `owner:branch` label、兩邊都取不到。 ## 設計重點 **為什麼不能只看 `head.ref`。** Gitea 在 PR 合併而來源分支被刪掉之後,把 `head.ref` 換成 `refs/pull/{編號}/head`,分支名退到 `head.label`: | PR | 狀態 | `head.ref` | `head.label` | | --- | --- | --- | --- | | #48 | 已合併、來源分支已刪 | `refs/pull/48/head` | `feat/pr-watch-and-cleanup/main` | | #46 | 已合併、來源分支已刪 | `refs/pull/46/head` | `feat/worktree-branch-prep/main` | 而合併正是唯一該清理工作樹的時機,所以這個 bug 的效果是**自動清理在真實情況下從來 不會成立**:推導出一條不存在的路徑,然後回報 `nothing-to-do`,靜悄悄地什麼都沒做。 **為什麼備援要擋掉 `refs/pull/…`。** 那不是分支名,拿它推導只會得到另一條不存在的 路徑——寧可說「讀不到來源分支名」,並告訴使用者改用 `worktree-remove --branch`。 靜默地算出一條錯路徑,比明確中止難查得多。 **測試先前為什麼沒抓到。** 假的 PR 一律照「開著的 PR」寫,`head.ref` 永遠是分支名。 補的正是合併後那一種——這一顆 bug 是在真實環境用它清自己的工作樹時撞出來的。 ## 解決的問題 `/sdlc-feat` 開出 PR、PR 被合併之後,使用者跑 `pr-watch` 會得到「工作樹不在、沒事要做」, 而那棵工作樹其實還在 `~/.tea-sdlc/worktrees/` 底下,永遠不會被清掉,也沒有任何訊息 提示他。集中目錄會無限長大,而那正是 #38 要它自動清理的理由。 ## 影響的功能 只動 `pr-watch` 取分支名的那一段。回報欄位、四種 PR 狀態的處置、清理的守門規則都不變, 既有測試原封通過。`worktree-remove` 不受影響——它吃 `--branch`,本來就不做推導。 ## 測試結果 ``` npm test ℹ tests 727 ℹ pass 727 ℹ fail 0 ``` 新增三條(先紅後綠):合併且來源分支已刪、fork 的 label、兩邊都取不到。 另外對真的 #48(已合併)跑過一次: ``` 修正前 "branch":"refs/pull/48/head" → 路徑 .../bb4f5127f641(不存在) 修正後 "branch":"feat/pr-watch-and-cleanup/main" → 路徑 .../bd457620184e(真正的那一棵) ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jiantw83 added 1 commit 2026-09-17 09:18:17 +00:00
PR 合併而來源分支被刪掉之後,Gitea 把 head.ref 換成 refs/pull/{編號}/head,分支名
退到 head.label。pr-watch 用的是 head.ref,於是推導出一條根本不存在的工作樹路徑,
回報「工作樹不在、沒事要做」——而合併正是唯一該清理工作樹的時機,等於自動清理在真實
情況下從來不會成立,而且靜悄悄的,沒有人會發現。

實測 #48(合併後)推導出 bb4f5127f641,真正的那一棵在 bd457620184e。

fork 來的 PR 的 label 是 owner:branch,只取分支那一段。兩邊都取不到時明確中止
(PULL_HEAD_MISSING),並指出手動出口怎麼指名那一棵,不拿空字串去推導路徑。

測試先前沒抓到,是因為假的 PR 一律照「開著的 PR」寫,head.ref 永遠是分支名。
補上「已合併且來源分支已刪」與 fork 兩種 head 的樣子。

議題 #50

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
admin approved these changes 2026-09-17 09:19:13 +00:00
admin merged commit 3a435bf2d9 into master 2026-09-17 09:19:26 +00:00
admin deleted branch fix/pr-head-after-merge/main 2026-09-17 09:19:26 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: plugins/tea-sdlc#51