fix/pr-head-after-merge/main
master
PR 合併之後,pr-watch 真的清得掉那棵工作樹了。
pr-watch
#38 — 以 worktree 隔離平行工作包的實作與修正
#50 — 修正 pr-watch 在 PR 合併後推導錯工作樹路徑
scripts/pr-watch.js
headBranch()
head.label
head.ref
refs/pull/…
PULL_HEAD_MISSING
worktree-remove
test/pr-watch.test.js
head
owner:branch
為什麼不能只看 head.ref。 Gitea 在 PR 合併而來源分支被刪掉之後,把 head.ref 換成 refs/pull/{編號}/head,分支名退到 head.label:
refs/pull/{編號}/head
refs/pull/48/head
feat/pr-watch-and-cleanup/main
refs/pull/46/head
feat/worktree-branch-prep/main
而合併正是唯一該清理工作樹的時機,所以這個 bug 的效果是自動清理在真實情況下從來 不會成立:推導出一條不存在的路徑,然後回報 nothing-to-do,靜悄悄地什麼都沒做。
nothing-to-do
為什麼備援要擋掉 refs/pull/…。 那不是分支名,拿它推導只會得到另一條不存在的 路徑——寧可說「讀不到來源分支名」,並告訴使用者改用 worktree-remove --branch。 靜默地算出一條錯路徑,比明確中止難查得多。
worktree-remove --branch
測試先前為什麼沒抓到。 假的 PR 一律照「開著的 PR」寫,head.ref 永遠是分支名。 補的正是合併後那一種——這一顆 bug 是在真實環境用它清自己的工作樹時撞出來的。
/sdlc-feat 開出 PR、PR 被合併之後,使用者跑 pr-watch 會得到「工作樹不在、沒事要做」, 而那棵工作樹其實還在 ~/.tea-sdlc/worktrees/ 底下,永遠不會被清掉,也沒有任何訊息 提示他。集中目錄會無限長大,而那正是 #38 要它自動清理的理由。
/sdlc-feat
~/.tea-sdlc/worktrees/
只動 pr-watch 取分支名的那一段。回報欄位、四種 PR 狀態的處置、清理的守門規則都不變, 既有測試原封通過。worktree-remove 不受影響——它吃 --branch,本來就不做推導。
--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 合併而來源分支被刪掉之後,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>
No dependencies set.
The note is not visible to the blocked user.
摘要
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:branchlabel、兩邊都取不到。設計重點
為什麼不能只看
head.ref。 Gitea 在 PR 合併而來源分支被刪掉之後,把head.ref換成
refs/pull/{編號}/head,分支名退到head.label:head.refhead.labelrefs/pull/48/headfeat/pr-watch-and-cleanup/mainrefs/pull/46/headfeat/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,本來就不做推導。測試結果
新增三條(先紅後綠):合併且來源分支已刪、fork 的 label、兩邊都取不到。
另外對真的 #48(已合併)跑過一次:
🤖 Generated with Claude Code
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>