Files
tea-sdlc/prompts/sdlc-feat.md
T
jiantw83andClaude Opus 5 ba714b0a00 docs(sdlc-feat): 第一段改成領取、備妥工作樹、最後起錶
正本跟著實作走:分支那一步改成工作樹,新增起錶那一步排在它後面,
並把三處「不要自己決定」寫明——來源分支不存在時不自己換一支、路徑被佔住時
不自己刪、工作樹建不起來時不退回原地切分支。工作區不乾淨的處置整段拿掉:
工作樹本來就是為了讓未提交的變更不再擋路。

AGENTS.md 補上兩條邊界。git worktree add 一定會在目標 repo 的 .git/worktrees/
底下寫中繼資料,這是 git 的機制,無法避免——「不改目標專案」指的是專案的內容檔,
把這件事明說,免得下一個人以為實作違規。

議題 #40

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

7.9 KiB
Raw Blame History

name: sdlc-feat description: 僅由 /sdlc-feat 指令叫用。領取一顆工作包、起錶、備妥分支,逐項實作並勾選待辦,最後分批提交並開立 PR。

sdlc-feat

拿一顆工作包,從領取到開出 PR。

第一段領取與開工準備:把工作包安全地認領下來,備妥一棵屬於它的工作樹,然後開始計時。 這一段不改任何一行程式碼——它只負責讓後面的實作有個乾淨的起點。

這份檔案是流程正本。各平台的轉接檔只是指回這裡,不要把規則抄過去。

輸入

一個工作包議題編號。

第一段:領取與開工準備

1. 讀工作包

node scripts/wp-extract.js --repo <owner/name> --index <編號>

拿到的是結構化欄位:待辦與它自己的驗收、範圍邊界、介面契約、相依、repo 列表。 不必再讀整份議題全文。

先看 未處理留言數。 只要不是 0,就代表議題描述可能是過期的——留言裡有決策還沒被 整併回描述。這時先停下來告訴使用者有幾則未整併的留言,建議先執行 /sdlc-sync 把它們整併回描述,再回來實作。使用者堅持要繼續就繼續,但要記下這件事, 並在最後的 PR 描述裡註明「實作基於未整併留言前的描述」。

再看 相依.depends。 裡面還有沒關閉的議題,代表這顆的前置還沒做完。照樣先說出來, 讓使用者決定要不要現在做。

2. 領取工作包

先試跑,看清楚會做什麼:

node scripts/claim.js --repo <owner/name> --index <編號> --dry-run

確認無誤後拿掉旗標再跑一次。放行時它會設 assignee、貼「進行中」標籤——這兩件事一起 構成領取鎖。錶不在這一步起:它等工作樹建好之後才起(第 6 步)。工作樹建立失敗會 中止整個領取,錶要是先起了,使用者就被計了一段什麼都沒做的時間。

領取鎖有四種狀態,三種擋、一種放行。被擋下來時不要繞過去,照著錯誤碼告訴使用者 發生什麼事、下一步是什麼:

狀態 錯誤碼 下一步
別人已經認領這顆 CLAIMED_BY_OTHER 改領別顆,或先跟對方確認
你的錶已經跑在這顆上 STOPWATCH_ON_THIS_ISSUE 這顆你正在做;要重新計時請先手動停錶
你的錶跑在別的議題上 STOPWATCH_ON_OTHER_ISSUE 多半是忘了停上一顆;先去停掉再回來
沒有鎖 —— 放行。自己已認領但沒起錶也算沒有鎖,那正是中斷後重跑的情形

碼錶一律由使用者自己停。哪一段時間該記在哪顆議題上只有他知道,代勞會把工時記錯地方。

鎖以外還有一個前置條件:repo 上要有「進行中」標籤。缺了會得到 LABEL_NOT_FOUND, 請使用者自己去建立——不要自己建,標籤體系不該在多個 repo 之間長出雜草。

3. 問來源分支

一次問一題。 新分支要從哪裡長出來,只有使用者知道,不要替他決定。 給兩個選項,並附上你判斷的理由:

  • 建議 — 你的答案。多數情況是開發分支(master/main/develop); 但若這顆工作包明顯是某個既有功能分支的一部分,就建議那一支,並說明為什麼。
  • 手動輸入 — 讓使用者自己填分支名。

不論哪一種,來源分支都必須已經在遠端上:工作樹的起點一律取自 origin/{來源分支}。

4. 把議題標題翻成英文

分支名的中段要用英文,中文會讓 CI 與 URL 出問題。把工作包議題的標題翻成 小寫英文 kebab、40 字元以內,例如「建立工作包的抽取契約」→ wp-extract-contract。

翻譯要保留原意而不是逐字直譯,寧可用一個更短的說法,也不要把長句截斷成看不懂的字串。

5. 備妥工作樹

工作樹開在工作包的 repos 列出的那些 repo 上,不是開在本 plugin 的目錄裡。 repos 只有一顆就用那一顆;有多顆時逐一確認要在哪幾個開分支, 再對每一個各跑一次 branch-prep,分支名在每個 repo 都相同。

node scripts/branch-prep.js --repo <owner/name> --path <目標專案路徑> \
  --source <來源分支> --slug <英文-kebab> [--type feat] --dry-run

--type 只在來源是開發分支時要給(feat/fix/chore…);從功能分支長出時, 類型與需求描述沿用來源,不必也不能再指定。

試跑會印出將執行的 git 指令、算出來的分支名與工作樹路徑。確認無誤後拿掉旗標再跑一次。

不在原地切換分支,一律開一棵獨立的工作樹。 每顆工作包有自己的目錄、自己的建置 產物、自己的未提交變更,彼此看不見對方。這件事對 agent 特別重要:它是非同步的, 可能在分支已經被切走之後才去讀檔,而它不會察覺自己讀到的是別顆工作包的內容—— 產出看起來完全合理,只是接錯了上下文。

工作樹一律建立,沒有例外。 建不起來就照實中止,不要改成在原地切分支: 使用者會以為自己在隔離環境裡,其實在原地改。

工作樹路徑由 owner/repo/分支名 推導而得,印在輸出的 worktree 欄位。 後面幾段的實作、測試與提交都在那棵工作樹裡做,不要回到主工作區動手。

它保證三件事:

  • 起點一律是遠端的來源分支(origin/{來源分支}),不是本機同名分支——後者可能 落後好幾天。遠端沒有那一支時得到 SOURCE_NOT_FOUND,把訊息念給使用者,讓他決定 是先把來源分支推上去,還是改指定一個別的來源——不要自己換一個。
  • 目標分支已經存在時接上去而不是蓋掉;工作樹已經在了就沿用,不動裡面還沒提交的東西。
  • 失敗時不留半成品:不會出現有分支沒工作樹、或有工作樹沒分支的狀態。

推導出的路徑被別的東西佔住時(WORKTREE_PATH_TAKEN,多半是別的 clone 留下的), 把路徑念給使用者,請他確認裡面沒有還沒保存的東西再移除——不要自己刪。

工作樹是乾淨的:沒有安裝依賴,也沒有任何建置產物,.env 這類機密檔案更不會被 複製過去。把輸出的 提示.安裝指令 念給使用者,機密檔案請他自己放一份。

6. 起錶

工作樹建好之後才起錶:

node scripts/timer.js --repo <owner/name> --index <編號> --dry-run

確認無誤後拿掉旗標再跑一次。錶已經跑在這顆議題上時它什麼都不做——那正是中斷後重跑 的情形,重新起錶會把已經累積的時間切成兩段。

7. 回報

印出一份開工前的現況,不寫回議題:

  • 工作包標題與網址、這一顆有幾項待辦
  • 認領結果(是否本來就是自己的)、碼錶已起
  • 來源分支、新分支名、分支是新建還是接上既有
  • 工作樹路徑,以及它是乾淨的、要先跑哪一行安裝指令
  • 未處理留言數與未關閉的先決議題(若有)

邊界

  • 第一段不改任何一行程式碼、不勾待辦、不提交、不開 PR——那些是後面幾段的事。
  • 不在主工作區動手。 實作一律在 branch-prep 建出來的那棵工作樹裡進行。
  • 不把依賴、建置產物或 .env 這類機密檔案複製到工作樹裡,也不做連結—— 兩棵工作樹共用同一份依賴,正好把工作樹要隔離的東西又接回去。
  • 工作樹建不起來時中止,不退回原地切分支。
  • 不自行建立標籤。缺「進行中」標籤時中止並請使用者建立。
  • 不代替使用者停錶,也不在被鎖擋下時繞過去。
  • 不替使用者決定來源分支。
  • 不寫任何本機狀態檔。 進度完全由 Gitea 上的 assignee、標籤、碼錶與 git 本身推導, 換一台機器或換一個 agent 都要能直接接手。