tea-sdlc:以 tea 驅動 SDLC 全流程的跨平台指令組 #1

Closed
opened 2026-09-17 03:30:14 +00:00 by jiantw83 · 0 comments
Member

Problem Statement

開發流程的每一段(規劃、分析、實作、修正、工時回報)目前都靠人工在 Gitea 網頁與終端之間來回搬運:需求寫成散文、工作包憑印象拆、分支與 commit 命名各憑喜好、PR 描述每次結構不同、工時靠記憶補登。結果是三種反覆出現的損耗:

  1. 議題內容不可機讀 — 下游(分析、實作)無法從議題自動取得所需資訊,每次都要人重讀一遍並口述給 agent。
  2. 規則靠人記憶 — 註解規範、分支命名、commit 分類、PR 八段描述都寫在腦子裡,不同人與不同 agent 產出不一致。
  3. 額度浪費 — agent 每次都要吞下 tea 的表格輸出與整份議題全文,才能取出兩三個欄位。

同時,使用者同時使用多個 coding agent(Claude Code / Codex / Antigravity / Copilot / Kiro / oh-my-pi / OpenCode),流程若只寫給其中一家,換工具就得重寫。

Solution

一組六個顯式指令,把 SDLC 各階段固定成可重複的流程;所有對外部系統(Gitea、git)的呼叫下沉到零相依的 Node 腳本,統一 JSON 輸入輸出;所有產出(議題、PR、報表)套用固定模板。流程正本只寫一份平台中立 markdown,由安裝腳本產生各平台的薄轉接檔。

使用者的體驗是:/sdlc-plan 把一段口語需求變成結構化需求議題;/sdlc-analyze 逐題把可行性疑點問到共識後生出工作包;/sdlc-feat 領取工作包、開分支、逐項實作並開 PR;/sdlc-fix 處理 PR 留言;/sdlc-sync 把散落的留言決策收回議題描述;/sdlc-report 產出工時報表。

User Stories

  1. 身為需求提出者,我想把一段口語需求變成結構化議題,以便開發者不必再來問我細節。
  2. 身為需求提出者,我想在議題裡看到領域名詞表,以便團隊對同一個詞的理解一致。
  3. 身為需求提出者,我想用 Mermaid 流程圖取代長段文字描述,以便一眼看懂流程而不必逐字讀。
  4. 身為非技術的利害關係人,我想在議題最上方看到一句話總覽,以便不必讀完技術細節就知道這件事在做什麼。
  5. 身為非技術的利害關係人,我想有一個圖解版總覽網頁,以便在會議上直接投影討論。
  6. 身為需求提出者,我想混用自由文字、規格檔案與既有議題編號當輸入,以便不必先把資料整理成單一格式。
  7. 身為需求提出者,我想在關鍵資訊缺漏時被逐項詢問,以便 agent 不會替我編造我沒說過的目標。
  8. 身為需求提出者,我想讓議題自動貼上合適的標籤,以便看板篩選正確。
  9. 身為專案維護者,我不想讓 agent 自動新增標籤,以便標籤體系不會在多 repo 之間長出雜草。
  10. 身為架構師,我想對需求議題執行架構可行性檢查,以便及早發現它放錯 repo 或製造循環相依。
  11. 身為架構師,我想執行邏輯可行性檢查,以便發現既有功能已經做過同一件事。
  12. 身為資料負責人,我想執行資料可行性檢查,以便及早發現 schema 變更、遷移與交易邊界問題。
  13. 身為專案經理,我想執行時程可行性檢查,以便知道相依鏈最長路徑與未知數最大的一項。
  14. 身為使用者,我想在分析階段一次只被問一題,以便在看到前一題答案後再回答下一題。
  15. 身為使用者,我想每一題都附上 agent 的建議與理由,以便多數情況下只要點同意。
  16. 身為使用者,我想能對任何一題手動輸入答案,以便不被選項限制。
  17. 身為使用者,我想在所有問題結束後看到共識摘要,以便在產生工作包前做最後確認。
  18. 身為開發者,我想讓工作包的待辦與其驗收標準巢狀配對,以便知道每一項做到什麼程度算完成。
  19. 身為開發者,我想在工作包看到範圍邊界(明列不做什麼),以便抵抗範圍蔓延。
  20. 身為開發者,我想在工作包看到介面契約表格,以便知道我產出的介面誰會消費。
  21. 身為專案經理,我想讓工作包之間自動建立阻擋/先決相依,以便看板呈現真實順序。
  22. 身為專案經理,我想讓工作包的截止日依相依關係拓撲排序推算,以便不會出現前置工作比後續晚到期的矛盾。
  23. 身為專案經理,我想讓工作包歸入 Gitea 專案看板,以便在看板上追蹤。
  24. 身為專案經理,我想讓工作包掛在 Milestone 下,以便有進度條與時程。
  25. 身為專案經理,我想在工作包記錄人天估算,以便事後與實際工時比對。
  26. 身為開發者,我想看到工作包全景圖(相依與時程),以便理解自己這一項在整體中的位置。
  27. 身為開發者,我想指定工作包後自動開始計時,以便不必記得手動按。
  28. 身為開發者,我想在領取工作包時被阻擋(若已有他人領取),以便不會兩個人做同一件事。
  29. 身為開發者,我想在自己已有碼錶在跑時被阻擋,以便發現自己忘記停掉上一個工作包。
  30. 身為開發者,我想被詢問來源分支,以便正確地從功能分支或開發分支長出新分支。
  31. 身為開發者,我想讓遠端已存在的來源分支被 pull 而非重建,以便不覆蓋他人進度。
  32. 身為開發者,我想讓分支名稱依既定規則產生,以便 CI 與 URL 不會因中文出問題。
  33. 身為開發者,我想每完成一項待辦就自動勾選,以便議題頁的進度條隨時反映真實狀態。
  34. 身為開發者,我不想每完成一項就被問一次,以便二十項待辦不用按二十次同意。
  35. 身為 reviewer,我不想看到每項待辦都產生一則留言,以便議題不被洗版。
  36. 身為開發者,我想讓變更檔案依類型分批 commit,以便 git 歷史可讀。
  37. 身為開發者,我想讓 commit 訊息用繁體中文描述需求,以便日後回顧時看得懂。
  38. 身為 reviewer,我想看到固定八段結構的 PR 描述,以便每次都在同一個位置找到我要的資訊。
  39. 身為 reviewer,我想看到真實執行過的測試結果,以便不被「已測試通過」這種空話誤導。
  40. 身為 reviewer,我想在沒有自動化測試時看到手動驗證步驟,以便自己能重現。
  41. 身為開發者,我想在工作包全部完成後自動開 PR 並停止計時,以便工時統計準確。
  42. 身為開發者,我想在中斷後重跑指令時自動接續,以便不必手動記錄進度。
  43. 身為開發者,我不想有本地狀態檔,以便換機器或換 agent 都能接手。
  44. 身為 reviewer,我想讓 agent 讀取我在 PR 上的所有留言(一般留言、review 總評、行內留言),以便不漏掉任何意見。
  45. 身為 reviewer,我想讓 agent 分辨哪些留言是必改、哪些是建議,以便不必逐則說明。
  46. 身為 reviewer,我想在 agent 不確定時被詢問,以便它不自作主張改壞。
  47. 身為 reviewer,我想看到 agent 在我原本的留言串底下回覆,以便知道哪一則被處理了。
  48. 身為 reviewer,我想看到已處理留言被打上 reaction,以便快速掃過還剩哪些。
  49. 身為 reviewer,我想在最後看到一則修正摘要,以便不必逐串點開。
  50. 身為專案維護者,我想把議題留言裡的決策整併回議題描述,以便新加入的人不必爬完整串留言。
  51. 身為專案維護者,我想讓已整併的留言被標記,以便下次不重複處理。
  52. 身為專案維護者,我想在略過某則留言時它保持未標記,以便下次仍會被提出。
  53. 身為開發者,我想在分析或實作時被自動提示有未整併留言並先處理,以便不用未更新的描述做事。
  54. 身為開發者,我想在自動整併完成後流程自動接回,以便不必重打指令。
  55. 身為開發者,我想產出本週工時報表,以便週會直接使用。
  56. 身為開發者,我想產出月報與年報,以便做季度與年度回顧。
  57. 身為開發者,我想讓跨月那一週依「該週週五所屬月份」歸屬,以便不被重複計算。
  58. 身為開發者,我想在報表看到估算與實際工時的落差,以便改進下次估算。
  59. 身為開發者,我想讓報表只印在終端不自動張貼,以便自己決定給誰看。
  60. 身為開發者,我想讓 agent 在改檔前偵測語言與框架,以便註解格式符合該語言慣例。
  61. 身為 reviewer,我想讓控制層有功能註解,以便知道每個對外介面在做什麼。
  62. 身為 reviewer,我想讓服務層有邏輯註解並標註所有呼叫的方法,以便追蹤呼叫鏈。
  63. 身為 reviewer,我想讓存取層有資料源註解,以便知道資料從哪來。
  64. 身為 reviewer,我想讓所有屬性都有用途註解(類別屬性遞迴),以便不必猜欄位意義。
  65. 身為 reviewer,我想讓屬性註解附真實資料範例,以便理解實際格式。
  66. 身為 reviewer,我想在範例無法從 MCP 取得時看到「由邏輯推理」的註明,以便知道它未經驗證。
  67. 身為專案維護者,我不想在議題或程式碼看到無意義編號(如 WP-01),以便命名本身就說明用途。
  68. 身為使用者,我想所有 Gitea 呼叫都走腳本並回傳精簡 JSON,以便 agent 不吞下大量無用輸出而浪費額度。
  69. 身為使用者,我想用 --dry-run 先看將執行什麼,以便在真的寫入前檢查。
  70. 身為使用者,我想讓腳本冪等,以便中斷重跑不產生重複議題。
  71. 身為使用者,我想在任一前置條件缺失時得到明確錯誤碼,以便知道是哪一步壞了。
  72. 身為多工具使用者,我想同一套流程在七個 agent 平台都能用,以便換工具不必重寫。
  73. 身為多工具使用者,我想讓安裝腳本偵測我裝了哪些平台並讓我勾選,以便不在沒裝的機器上留下孤兒目錄。
  74. 身為多工具使用者,我想能用 --platform 指定安裝對象,以便在 CI 或腳本中非互動安裝。
  75. 身為多工具使用者,我想能一鍵解除安裝轉接檔而不動正本,以便乾淨移除。
  76. 身為維護者,我想流程正本只有一份,以便改規則不會出現各平台版本分歧。
  77. 身為使用者,我不想讓這些流程被模型自動觸發,以便只在我明確下指令時才執行。

Implementation Decisions

模組邊界

  • prompts/sdlc-{plan,analyze,feat,fix,sync,report}.md — 流程正本,平台中立 markdown,唯一的事實來源。不含任何平台專屬語法。
  • scripts/*.js — 所有副作用(Gitea API、git、檔案系統)的唯一出口。Node,零外部套件,僅用內建 fetch / child_process / fs。
  • templates/*.md + overview-artifact.html — 所有產出格式,{{變數}} 佔位。
  • references/*.md — 規則正本(實作規範、註解格式對照表、可行性檢查清單),由正本 markdown 指名讀取。
  • install.js — 平台偵測與轉接檔產生,唯一知道各平台目錄結構的地方。

腳本介面契約

所有腳本一律具名 flag 輸入、單行 JSON 輸出 {ok, data, error:{code, message}}。共用邏輯在 lib.js:Gitea API 呼叫、前置檢查、--dry-run、冪等查重、JSON 輸出。前置檢查涵蓋四層:執行環境(node/git/tea 存在)、Gitea 登入有效、帳號對目標 repo 的 issues unit 具寫入權、repo 已開啟 internal_tracker.enable_time_tracker。任一層不通過即中止並指出應修改的設定位置,不讓後續步驟散落地失敗。腳本以 fileURLToPath(import.meta.url) 回推 plugin 根定位 templates/ 與 references/,不依賴 cwd 或環境變數。

腳本清單:issue-create、issue-update、issue-extract、wp-extract、issue-link、labels-list、project-add、timer、claim、branch-prep、commit-split、pr-create、pr-comments、comments-merge、report。

實作過程中由各工作包追加(以工作包為準):install、prompt、status(指令入口的三個子指令)、schedule(依相依推算截止日)、pr-reply(#14)、pr-watch 與 worktree-remove(#38)、worktree-ensure(#42)、wp-list(#60)。另有三支不是 CLI 的共用模組:lib.js、issue-body.js、pr-threads.js。

抽取契約(下游指令唯一的議題讀取管道,只讀 body 不讀留言)

  • issue-extract → {index, url, title, labels[], 總覽, 背景, 目標[], 非目標[], 名詞表[{term,def}], 流程圖, 驗收標準[], 影響範圍[], 未決事項[], 未處理留言數}
  • wp-extract → {index, url, title, 需求議題, 描述, 架構圖, 範圍邊界[], 介面契約[], 待辦[{text,done,raw,驗收[{text,done,raw}]}], 整體驗收[], repos[], 相依:{blocks[],depends[]}, assignee, 碼錶中, 未處理留言數}
  • wp-list → {repo, 需求議題, 工作包[{index,title,url,state,assignee}], 數量}。flag 為 --repo --requirement <需求議題編號>;--index 留給「這支腳本作用在哪一顆議題上」,這裡要的是母議題,兩者不混用。歸屬判準與 wp-extract 的 需求議題 欄位共用 issue-body 的同一個函式(關聯段落的 需求議題:#N),不另發明判準;PR 的描述也有那一行,所以 PR 不列入。找不到任何工作包時回空陣列而非錯誤。

raw 欄位保留原始 markdown 行,供 issue-update 做精確字串替換式的 checkbox 勾選(PATCH 局部,不重寫整份 body)。

Gitea 承載對應

概念 承載
需求 / 工作包 Issue
時程 Milestone(deadline + 進度條)
看板位置 Issue.projects(id 陣列)
相依 POST /issues/{i}/dependencies、/blocks
人天估算 body 的「估算人天」一行(Issue.time_estimate 寫不進去:Gitea 1.27 的 API 沒有任何請求定義接受該欄位,它只出現在議題的回應裡。report 的估算也改讀這一行)
領取鎖 assignee + 進行中 標籤
工時 stopwatch(`/issues/{i}/stopwatch/start
留言已處理 comment reaction +1

已知平台限制與因應

  • Gitea 無「列出專案」endpoint:project-add 掃最近 50 筆議題的 projects 欄位反查 id→名稱對照;全空時要求使用者貼專案網址(結尾即 id)。
  • 碼錶只能讀自己的(/user/stopwatches):領取鎖改用 assignee + 標籤,碼錶僅用於工時。
  • 領取規則:他人 assignee 擋;自己碼錶跑在任何議題(含本議題)一律擋,需手動停錶後再領。
  • Gitea 的 team unit 權限可獨立於 repo 的 push 權限:repo.code: write 不蘊含 repo.issues: write。因此權限檢查必須針對 issues unit 實測(嘗試性讀寫或檢查 collaborator 身分),不能只看 permissions.push。
  • repo 的時間追蹤預設關閉且需 repo admin 才能開啟;本工具偵測到關閉時中止並指示開啟路徑(Settings → Advanced Settings → Enable Time Tracker)。

跨平台佈署

install.js 偵測 ~/.claude/、~/.codex/、~/.config/opencode/、~/.omp/、~/.kiro/、~/.gemini/、.github/ 後列出勾選(預設全勾),可 --platform a,b 指定、--uninstall 移除轉接檔(正本不動)。四個支援 command 的平台(Claude Code、Codex、OpenCode、oh-my-pi)產生 command 轉接檔;三個不支援 command 的平台(Antigravity、Copilot、Kiro)產生 SKILL.md 轉接檔。轉接檔內容為一行指向正本,路徑於產生時替換為絕對路徑。

所有 description 統一前綴 僅由 /sdlc-xxx 指令叫用。;在支援關閉自動觸發的平台設對應旗標。已接受的取捨:Antigravity、Copilot、Kiro 無法關閉自動觸發,靠窄化 description 降低誤觸。

輸出模板

  • 需求議題:一句話總覽(含 artifact 連結)/背景(≤3 行)/目標(可量測)/非目標/領域名詞表/流程圖/驗收標準/影響範圍/未決事項
  • 工作包議題:這個工作包在做什麼/描述/架構圖/範圍邊界/介面契約/待辦(巢狀驗收)/整體驗收/repo 列表/關聯(需求議題、阻擋、先決、估算人天)。標題為 {動詞}{名詞},禁止流水編號。
  • PR:標題等同分支名;描述八段為摘要/需求議題/工作包議題/變更內容/設計重點/解決的問題/影響的功能/測試結果。
  • Mermaid 對照:需求用 flowchart;工作包依性質用 sequenceDiagram/flowchart/stateDiagram-v2;全景用 graph TD。節點上限 12、節點文字 ≤8 字,超過即拆圖或不畫。

HTML artifact 總覽

/sdlc-plan 與 /sdlc-analyze 各產一份,網址寫回議題 body 並於重跑時原地更新(不產生新連結)。markdown 白話總覽仍保留於議題內。注意 artifact 預設私有,組織外無法開啟。

命名規則

  • 分支:從開發分支 {類型}/{英文-kebab-需求描述}/main;從功能分支 {類型}/{需求描述}/{功能描述}。需求描述由議題標題翻譯,≤40 字元。
  • Commit:以「類型 × 功能」為一個 commit,訊息 {類型}({檔案|功能}): {繁中需求描述},scope 單檔用檔名、多檔用功能名。

分層與註解規範(references/coding-standards.md)

分層判定以職責而非目錄:對外介面即控制層、所有邏輯在服務層、任何碰 DB/API/資料來源者為存取層。控制層寫功能註解;服務層寫邏輯註解並標註所有呼叫的方法;存取層寫資料源註解;所有屬性寫用途註解(屬性為類別時遞迴),並附真實資料範例——優先取自 MCP,無 MCP 則以邏輯推理並明確註明來源未經驗證。改檔前依專案檔(*.csproj/composer.json/package.json/go.mod/pom.xml/pyproject.toml)偵測語言,對照 references/comment-styles.md;偵測不到即停止並詢問。

互動協定

分析階段以 AskUserQuestion 一次一題,選項固定為「建議(含理由)」與「手動輸入」,依架構→邏輯→資料→時程順序清空,全部結束後輸出共識摘要。規劃與分析本身已含問題釐清,因此寫入 Gitea 前不再設額外確認點。/sdlc-feat 的逐項待辦完成不打斷,只印進度。

報表期間定義

一週為週一至週日;該週的週五所屬月份即為歸屬月;W1–W5 為該週五是當月第幾個週五。--week(預設,本週一至今日)/--month YYYY-MM/--year YYYY,月報以 W1–W5 分段小計。

Testing Decisions

什麼是好的測試:只測外部行為,不測實作細節。對本專案而言,外部行為就是「給定一組 flag 與一份 Gitea 回應,腳本印出什麼 JSON、以及對 Gitea 發出哪些請求」。不測私有函式、不測 JSON 內部的建構過程。

唯一接縫:scripts/*.js 的 CLI 邊界。 每支腳本都是一個獨立行程,輸入是具名 flag,輸出是單行 JSON。測試以子行程執行腳本、比對 stdout 的 JSON 與 exit code。之所以選這個接縫而非函式層,是因為它同時是七個平台共用的實際呼叫方式——測到的東西就是使用者真正會執行的東西,且不會因內部重構而破碎。

外部相依的隔離:lib.js 的 Gitea 呼叫集中於單一函式,測試時以環境變數指向本機 stub server(或注入 fetch 替身),錄下請求並回放固定回應。git 操作同理集中於 lib.js 的單一執行點,測試在臨時 git repo 上跑真實 git(比 mock git 更可信,且成本低)。

測試對象優先序:

  1. wp-extract / issue-extract — 模板解析是整條鏈的上游,解析錯則下游全錯。餵入各種模板變體(缺段落、巢狀驗收為空、checkbox 已勾、中英混排)驗證輸出契約。
  2. issue-update 的 checkbox 精確替換 — 驗證只動目標行、重複文字不誤傷、raw 不匹配時回錯誤而非盲改。
  3. commit-split 的類型分類與 branch-prep 的分支命名 — 純字串規則,表格驅動測試成本最低、回歸價值最高。
  4. claim 的領取鎖決策表 — 他人 assignee/自己碼錶跑在本議題/跑在別的議題/無鎖,四種狀態各一例。
  5. report 的週次歸屬 — 跨月、跨年、當月有五個週五等邊界。
  6. install.js — 在臨時家目錄上驗證偵測、產生、--uninstall 後無殘留。

--dry-run 兼作測試工具:所有寫入型腳本在 --dry-run 下輸出「將發出的請求」而非執行,讓寫入路徑不需要真實 Gitea 也能被斷言。

Prior art:本 repo 為新建,無既有測試可依循。測試執行器採 Node 內建 node:test + node:assert,與「零外部套件」的既定約束一致。

Out of Scope

  • 不修改任何目標專案的檔案(含不寫入目標專案的 CLAUDE.md);實作規範只存在於本 plugin 的 references/。
  • 不自動建立 Gitea 標籤、不自動建立 Gitea 專案。
  • 不自動修改 repo 或 org 的權限設定,亦不自動開啟 repo 的時間追蹤開關。
  • 不自動張貼工時報表到任何管道。
  • 不支援 GitHub/GitLab 等 Gitea 以外的議題系統。
  • 不自動安裝 Node、tea 或任何執行環境,僅在缺失時印出安裝指引並中止。
  • 不處理 Windows 的 symlink 議題(本次採產生轉接檔而非 symlink,因此不受影響)。
  • 不提供議題的刪除或關閉流程。
  • 不做多人協作的衝突合併(領取鎖只做阻擋,不做排隊)。

Further Notes

  • tea CLI 原生不支援 Projects、議題相依與碼錶,這三項一律透過 tea api 打 Gitea REST API;其餘(議題、標籤、Milestone、留言、工時列表)走 tea 原生子指令。
  • 環境中 jq 不存在,因此腳本以 Node 實作而非 bash + jq。
  • oh-my-pi 會自動讀取 ~/.claude/plugins/installed_plugins.json 與其他平台目錄,理論上安裝 Claude Code 版即可被它看見;install.js 仍為它產生原生轉接檔以確保指令命名一致。
  • Codex 的 ~/.codex/prompts/ 已被官方標示為棄用、Antigravity 的 workflows 於 2026-11-01 移除,這兩處的轉接策略需在該日期前重新評估。
## Problem Statement 開發流程的每一段(規劃、分析、實作、修正、工時回報)目前都靠人工在 Gitea 網頁與終端之間來回搬運:需求寫成散文、工作包憑印象拆、分支與 commit 命名各憑喜好、PR 描述每次結構不同、工時靠記憶補登。結果是三種反覆出現的損耗: 1. **議題內容不可機讀** — 下游(分析、實作)無法從議題自動取得所需資訊,每次都要人重讀一遍並口述給 agent。 2. **規則靠人記憶** — 註解規範、分支命名、commit 分類、PR 八段描述都寫在腦子裡,不同人與不同 agent 產出不一致。 3. **額度浪費** — agent 每次都要吞下 tea 的表格輸出與整份議題全文,才能取出兩三個欄位。 同時,使用者同時使用多個 coding agent(Claude Code / Codex / Antigravity / Copilot / Kiro / oh-my-pi / OpenCode),流程若只寫給其中一家,換工具就得重寫。 ## Solution 一組六個顯式指令,把 SDLC 各階段固定成可重複的流程;所有對外部系統(Gitea、git)的呼叫下沉到零相依的 Node 腳本,統一 JSON 輸入輸出;所有產出(議題、PR、報表)套用固定模板。流程正本只寫一份平台中立 markdown,由安裝腳本產生各平台的薄轉接檔。 使用者的體驗是:`/sdlc-plan` 把一段口語需求變成結構化需求議題;`/sdlc-analyze` 逐題把可行性疑點問到共識後生出工作包;`/sdlc-feat` 領取工作包、開分支、逐項實作並開 PR;`/sdlc-fix` 處理 PR 留言;`/sdlc-sync` 把散落的留言決策收回議題描述;`/sdlc-report` 產出工時報表。 ## User Stories 1. 身為需求提出者,我想把一段口語需求變成結構化議題,以便開發者不必再來問我細節。 2. 身為需求提出者,我想在議題裡看到領域名詞表,以便團隊對同一個詞的理解一致。 3. 身為需求提出者,我想用 Mermaid 流程圖取代長段文字描述,以便一眼看懂流程而不必逐字讀。 4. 身為非技術的利害關係人,我想在議題最上方看到一句話總覽,以便不必讀完技術細節就知道這件事在做什麼。 5. 身為非技術的利害關係人,我想有一個圖解版總覽網頁,以便在會議上直接投影討論。 6. 身為需求提出者,我想混用自由文字、規格檔案與既有議題編號當輸入,以便不必先把資料整理成單一格式。 7. 身為需求提出者,我想在關鍵資訊缺漏時被逐項詢問,以便 agent 不會替我編造我沒說過的目標。 8. 身為需求提出者,我想讓議題自動貼上合適的標籤,以便看板篩選正確。 9. 身為專案維護者,我不想讓 agent 自動新增標籤,以便標籤體系不會在多 repo 之間長出雜草。 10. 身為架構師,我想對需求議題執行架構可行性檢查,以便及早發現它放錯 repo 或製造循環相依。 11. 身為架構師,我想執行邏輯可行性檢查,以便發現既有功能已經做過同一件事。 12. 身為資料負責人,我想執行資料可行性檢查,以便及早發現 schema 變更、遷移與交易邊界問題。 13. 身為專案經理,我想執行時程可行性檢查,以便知道相依鏈最長路徑與未知數最大的一項。 14. 身為使用者,我想在分析階段一次只被問一題,以便在看到前一題答案後再回答下一題。 15. 身為使用者,我想每一題都附上 agent 的建議與理由,以便多數情況下只要點同意。 16. 身為使用者,我想能對任何一題手動輸入答案,以便不被選項限制。 17. 身為使用者,我想在所有問題結束後看到共識摘要,以便在產生工作包前做最後確認。 18. 身為開發者,我想讓工作包的待辦與其驗收標準巢狀配對,以便知道每一項做到什麼程度算完成。 19. 身為開發者,我想在工作包看到範圍邊界(明列不做什麼),以便抵抗範圍蔓延。 20. 身為開發者,我想在工作包看到介面契約表格,以便知道我產出的介面誰會消費。 21. 身為專案經理,我想讓工作包之間自動建立阻擋/先決相依,以便看板呈現真實順序。 22. 身為專案經理,我想讓工作包的截止日依相依關係拓撲排序推算,以便不會出現前置工作比後續晚到期的矛盾。 23. 身為專案經理,我想讓工作包歸入 Gitea 專案看板,以便在看板上追蹤。 24. 身為專案經理,我想讓工作包掛在 Milestone 下,以便有進度條與時程。 25. 身為專案經理,我想在工作包記錄人天估算,以便事後與實際工時比對。 26. 身為開發者,我想看到工作包全景圖(相依與時程),以便理解自己這一項在整體中的位置。 27. 身為開發者,我想指定工作包後自動開始計時,以便不必記得手動按。 28. 身為開發者,我想在領取工作包時被阻擋(若已有他人領取),以便不會兩個人做同一件事。 29. 身為開發者,我想在自己已有碼錶在跑時被阻擋,以便發現自己忘記停掉上一個工作包。 30. 身為開發者,我想被詢問來源分支,以便正確地從功能分支或開發分支長出新分支。 31. 身為開發者,我想讓遠端已存在的來源分支被 pull 而非重建,以便不覆蓋他人進度。 32. 身為開發者,我想讓分支名稱依既定規則產生,以便 CI 與 URL 不會因中文出問題。 33. 身為開發者,我想每完成一項待辦就自動勾選,以便議題頁的進度條隨時反映真實狀態。 34. 身為開發者,我不想每完成一項就被問一次,以便二十項待辦不用按二十次同意。 35. 身為 reviewer,我不想看到每項待辦都產生一則留言,以便議題不被洗版。 36. 身為開發者,我想讓變更檔案依類型分批 commit,以便 git 歷史可讀。 37. 身為開發者,我想讓 commit 訊息用繁體中文描述需求,以便日後回顧時看得懂。 38. 身為 reviewer,我想看到固定八段結構的 PR 描述,以便每次都在同一個位置找到我要的資訊。 39. 身為 reviewer,我想看到真實執行過的測試結果,以便不被「已測試通過」這種空話誤導。 40. 身為 reviewer,我想在沒有自動化測試時看到手動驗證步驟,以便自己能重現。 41. 身為開發者,我想在工作包全部完成後自動開 PR 並停止計時,以便工時統計準確。 42. 身為開發者,我想在中斷後重跑指令時自動接續,以便不必手動記錄進度。 43. 身為開發者,我不想有本地狀態檔,以便換機器或換 agent 都能接手。 44. 身為 reviewer,我想讓 agent 讀取我在 PR 上的所有留言(一般留言、review 總評、行內留言),以便不漏掉任何意見。 45. 身為 reviewer,我想讓 agent 分辨哪些留言是必改、哪些是建議,以便不必逐則說明。 46. 身為 reviewer,我想在 agent 不確定時被詢問,以便它不自作主張改壞。 47. 身為 reviewer,我想看到 agent 在我原本的留言串底下回覆,以便知道哪一則被處理了。 48. 身為 reviewer,我想看到已處理留言被打上 reaction,以便快速掃過還剩哪些。 49. 身為 reviewer,我想在最後看到一則修正摘要,以便不必逐串點開。 50. 身為專案維護者,我想把議題留言裡的決策整併回議題描述,以便新加入的人不必爬完整串留言。 51. 身為專案維護者,我想讓已整併的留言被標記,以便下次不重複處理。 52. 身為專案維護者,我想在略過某則留言時它保持未標記,以便下次仍會被提出。 53. 身為開發者,我想在分析或實作時被自動提示有未整併留言並先處理,以便不用未更新的描述做事。 54. 身為開發者,我想在自動整併完成後流程自動接回,以便不必重打指令。 55. 身為開發者,我想產出本週工時報表,以便週會直接使用。 56. 身為開發者,我想產出月報與年報,以便做季度與年度回顧。 57. 身為開發者,我想讓跨月那一週依「該週週五所屬月份」歸屬,以便不被重複計算。 58. 身為開發者,我想在報表看到估算與實際工時的落差,以便改進下次估算。 59. 身為開發者,我想讓報表只印在終端不自動張貼,以便自己決定給誰看。 60. 身為開發者,我想讓 agent 在改檔前偵測語言與框架,以便註解格式符合該語言慣例。 61. 身為 reviewer,我想讓控制層有功能註解,以便知道每個對外介面在做什麼。 62. 身為 reviewer,我想讓服務層有邏輯註解並標註所有呼叫的方法,以便追蹤呼叫鏈。 63. 身為 reviewer,我想讓存取層有資料源註解,以便知道資料從哪來。 64. 身為 reviewer,我想讓所有屬性都有用途註解(類別屬性遞迴),以便不必猜欄位意義。 65. 身為 reviewer,我想讓屬性註解附真實資料範例,以便理解實際格式。 66. 身為 reviewer,我想在範例無法從 MCP 取得時看到「由邏輯推理」的註明,以便知道它未經驗證。 67. 身為專案維護者,我不想在議題或程式碼看到無意義編號(如 WP-01),以便命名本身就說明用途。 68. 身為使用者,我想所有 Gitea 呼叫都走腳本並回傳精簡 JSON,以便 agent 不吞下大量無用輸出而浪費額度。 69. 身為使用者,我想用 --dry-run 先看將執行什麼,以便在真的寫入前檢查。 70. 身為使用者,我想讓腳本冪等,以便中斷重跑不產生重複議題。 71. 身為使用者,我想在任一前置條件缺失時得到明確錯誤碼,以便知道是哪一步壞了。 72. 身為多工具使用者,我想同一套流程在七個 agent 平台都能用,以便換工具不必重寫。 73. 身為多工具使用者,我想讓安裝腳本偵測我裝了哪些平台並讓我勾選,以便不在沒裝的機器上留下孤兒目錄。 74. 身為多工具使用者,我想能用 --platform 指定安裝對象,以便在 CI 或腳本中非互動安裝。 75. 身為多工具使用者,我想能一鍵解除安裝轉接檔而不動正本,以便乾淨移除。 76. 身為維護者,我想流程正本只有一份,以便改規則不會出現各平台版本分歧。 77. 身為使用者,我不想讓這些流程被模型自動觸發,以便只在我明確下指令時才執行。 ## Implementation Decisions **模組邊界** - `prompts/sdlc-{plan,analyze,feat,fix,sync,report}.md` — 流程正本,平台中立 markdown,唯一的事實來源。不含任何平台專屬語法。 - `scripts/*.js` — 所有副作用(Gitea API、git、檔案系統)的唯一出口。Node,零外部套件,僅用內建 `fetch` / `child_process` / `fs`。 - `templates/*.md` + `overview-artifact.html` — 所有產出格式,`{{變數}}` 佔位。 - `references/*.md` — 規則正本(實作規範、註解格式對照表、可行性檢查清單),由正本 markdown 指名讀取。 - `install.js` — 平台偵測與轉接檔產生,唯一知道各平台目錄結構的地方。 **腳本介面契約** 所有腳本一律具名 flag 輸入、單行 JSON 輸出 `{ok, data, error:{code, message}}`。共用邏輯在 `lib.js`:Gitea API 呼叫、前置檢查、`--dry-run`、冪等查重、JSON 輸出。前置檢查涵蓋四層:執行環境(node/git/tea 存在)、Gitea 登入有效、帳號對目標 repo 的 issues unit 具寫入權、repo 已開啟 `internal_tracker.enable_time_tracker`。任一層不通過即中止並指出應修改的設定位置,不讓後續步驟散落地失敗。腳本以 `fileURLToPath(import.meta.url)` 回推 plugin 根定位 `templates/` 與 `references/`,不依賴 cwd 或環境變數。 腳本清單:`issue-create`、`issue-update`、`issue-extract`、`wp-extract`、`issue-link`、`labels-list`、`project-add`、`timer`、`claim`、`branch-prep`、`commit-split`、`pr-create`、`pr-comments`、`comments-merge`、`report`。 實作過程中由各工作包追加(以工作包為準):`install`、`prompt`、`status`(指令入口的三個子指令)、`schedule`(依相依推算截止日)、`pr-reply`(#14)、`pr-watch` 與 `worktree-remove`(#38)、`worktree-ensure`(#42)、`wp-list`(#60)。另有三支不是 CLI 的共用模組:`lib.js`、`issue-body.js`、`pr-threads.js`。 **抽取契約**(下游指令唯一的議題讀取管道,只讀 body 不讀留言) - `issue-extract` → `{index, url, title, labels[], 總覽, 背景, 目標[], 非目標[], 名詞表[{term,def}], 流程圖, 驗收標準[], 影響範圍[], 未決事項[], 未處理留言數}` - `wp-extract` → `{index, url, title, 需求議題, 描述, 架構圖, 範圍邊界[], 介面契約[], 待辦[{text,done,raw,驗收[{text,done,raw}]}], 整體驗收[], repos[], 相依:{blocks[],depends[]}, assignee, 碼錶中, 未處理留言數}` - `wp-list` → `{repo, 需求議題, 工作包[{index,title,url,state,assignee}], 數量}`。flag 為 `--repo --requirement <需求議題編號>`;`--index` 留給「這支腳本作用在哪一顆議題上」,這裡要的是母議題,兩者不混用。歸屬判準與 `wp-extract` 的 `需求議題` 欄位共用 `issue-body` 的同一個函式(關聯段落的 `需求議題:#N`),不另發明判準;PR 的描述也有那一行,所以 PR 不列入。找不到任何工作包時回空陣列而非錯誤。 `raw` 欄位保留原始 markdown 行,供 `issue-update` 做精確字串替換式的 checkbox 勾選(PATCH 局部,不重寫整份 body)。 **Gitea 承載對應** | 概念 | 承載 | |---|---| | 需求 / 工作包 | Issue | | 時程 | Milestone(deadline + 進度條) | | 看板位置 | Issue.projects(id 陣列) | | 相依 | `POST /issues/{i}/dependencies`、`/blocks` | | 人天估算 | body 的「估算人天」一行(`Issue.time_estimate` 寫不進去:Gitea 1.27 的 API 沒有任何請求定義接受該欄位,它只出現在議題的回應裡。`report` 的估算也改讀這一行) | | 領取鎖 | assignee + `進行中` 標籤 | | 工時 | stopwatch(`/issues/{i}/stopwatch/start|stop`)、`/user/times` | | 留言已處理 | comment reaction `+1` | **已知平台限制與因應** - Gitea 無「列出專案」endpoint:`project-add` 掃最近 50 筆議題的 `projects` 欄位反查 id→名稱對照;全空時要求使用者貼專案網址(結尾即 id)。 - 碼錶只能讀自己的(`/user/stopwatches`):領取鎖改用 assignee + 標籤,碼錶僅用於工時。 - 領取規則:他人 assignee 擋;自己碼錶跑在任何議題(含本議題)一律擋,需手動停錶後再領。 - Gitea 的 team unit 權限可獨立於 repo 的 push 權限:`repo.code: write` 不蘊含 `repo.issues: write`。因此權限檢查必須針對 issues unit 實測(嘗試性讀寫或檢查 collaborator 身分),不能只看 `permissions.push`。 - repo 的時間追蹤預設關閉且需 repo admin 才能開啟;本工具偵測到關閉時中止並指示開啟路徑(Settings → Advanced Settings → Enable Time Tracker)。 **跨平台佈署** `install.js` 偵測 `~/.claude/`、`~/.codex/`、`~/.config/opencode/`、`~/.omp/`、`~/.kiro/`、`~/.gemini/`、`.github/` 後列出勾選(預設全勾),可 `--platform a,b` 指定、`--uninstall` 移除轉接檔(正本不動)。四個支援 command 的平台(Claude Code、Codex、OpenCode、oh-my-pi)產生 command 轉接檔;三個不支援 command 的平台(Antigravity、Copilot、Kiro)產生 `SKILL.md` 轉接檔。轉接檔內容為一行指向正本,路徑於產生時替換為絕對路徑。 所有 description 統一前綴 `僅由 /sdlc-xxx 指令叫用。`;在支援關閉自動觸發的平台設對應旗標。**已接受的取捨**:Antigravity、Copilot、Kiro 無法關閉自動觸發,靠窄化 description 降低誤觸。 **輸出模板** - 需求議題:一句話總覽(含 artifact 連結)/背景(≤3 行)/目標(可量測)/非目標/領域名詞表/流程圖/驗收標準/影響範圍/未決事項 - 工作包議題:這個工作包在做什麼/描述/架構圖/範圍邊界/介面契約/待辦(巢狀驗收)/整體驗收/repo 列表/關聯(需求議題、阻擋、先決、估算人天)。標題為 `{動詞}{名詞}`,禁止流水編號。 - PR:標題等同分支名;描述八段為摘要/需求議題/工作包議題/變更內容/設計重點/解決的問題/影響的功能/測試結果。 - Mermaid 對照:需求用 `flowchart`;工作包依性質用 `sequenceDiagram`/`flowchart`/`stateDiagram-v2`;全景用 `graph TD`。節點上限 12、節點文字 ≤8 字,超過即拆圖或不畫。 **HTML artifact 總覽** `/sdlc-plan` 與 `/sdlc-analyze` 各產一份,網址寫回議題 body 並於重跑時原地更新(不產生新連結)。markdown 白話總覽仍保留於議題內。注意 artifact 預設私有,組織外無法開啟。 **命名規則** - 分支:從開發分支 `{類型}/{英文-kebab-需求描述}/main`;從功能分支 `{類型}/{需求描述}/{功能描述}`。需求描述由議題標題翻譯,≤40 字元。 - Commit:以「類型 × 功能」為一個 commit,訊息 `{類型}({檔案|功能}): {繁中需求描述}`,scope 單檔用檔名、多檔用功能名。 **分層與註解規範**(`references/coding-standards.md`) 分層判定以職責而非目錄:對外介面即控制層、所有邏輯在服務層、任何碰 DB/API/資料來源者為存取層。控制層寫功能註解;服務層寫邏輯註解並標註所有呼叫的方法;存取層寫資料源註解;所有屬性寫用途註解(屬性為類別時遞迴),並附真實資料範例——優先取自 MCP,無 MCP 則以邏輯推理並明確註明來源未經驗證。改檔前依專案檔(`*.csproj`/`composer.json`/`package.json`/`go.mod`/`pom.xml`/`pyproject.toml`)偵測語言,對照 `references/comment-styles.md`;偵測不到即停止並詢問。 **互動協定** 分析階段以 `AskUserQuestion` 一次一題,選項固定為「建議(含理由)」與「手動輸入」,依架構→邏輯→資料→時程順序清空,全部結束後輸出共識摘要。規劃與分析本身已含問題釐清,因此寫入 Gitea 前不再設額外確認點。`/sdlc-feat` 的逐項待辦完成不打斷,只印進度。 **報表期間定義** 一週為週一至週日;該週的週五所屬月份即為歸屬月;W1–W5 為該週五是當月第幾個週五。`--week`(預設,本週一至今日)/`--month YYYY-MM`/`--year YYYY`,月報以 W1–W5 分段小計。 ## Testing Decisions **什麼是好的測試**:只測外部行為,不測實作細節。對本專案而言,外部行為就是「給定一組 flag 與一份 Gitea 回應,腳本印出什麼 JSON、以及對 Gitea 發出哪些請求」。不測私有函式、不測 JSON 內部的建構過程。 **唯一接縫:`scripts/*.js` 的 CLI 邊界。** 每支腳本都是一個獨立行程,輸入是具名 flag,輸出是單行 JSON。測試以子行程執行腳本、比對 stdout 的 JSON 與 exit code。之所以選這個接縫而非函式層,是因為它同時是七個平台共用的實際呼叫方式——測到的東西就是使用者真正會執行的東西,且不會因內部重構而破碎。 **外部相依的隔離**:`lib.js` 的 Gitea 呼叫集中於單一函式,測試時以環境變數指向本機 stub server(或注入 `fetch` 替身),錄下請求並回放固定回應。git 操作同理集中於 `lib.js` 的單一執行點,測試在臨時 git repo 上跑真實 git(比 mock git 更可信,且成本低)。 **測試對象優先序**: 1. `wp-extract` / `issue-extract` — 模板解析是整條鏈的上游,解析錯則下游全錯。餵入各種模板變體(缺段落、巢狀驗收為空、checkbox 已勾、中英混排)驗證輸出契約。 2. `issue-update` 的 checkbox 精確替換 — 驗證只動目標行、重複文字不誤傷、`raw` 不匹配時回錯誤而非盲改。 3. `commit-split` 的類型分類與 `branch-prep` 的分支命名 — 純字串規則,表格驅動測試成本最低、回歸價值最高。 4. `claim` 的領取鎖決策表 — 他人 assignee/自己碼錶跑在本議題/跑在別的議題/無鎖,四種狀態各一例。 5. `report` 的週次歸屬 — 跨月、跨年、當月有五個週五等邊界。 6. `install.js` — 在臨時家目錄上驗證偵測、產生、`--uninstall` 後無殘留。 **`--dry-run` 兼作測試工具**:所有寫入型腳本在 `--dry-run` 下輸出「將發出的請求」而非執行,讓寫入路徑不需要真實 Gitea 也能被斷言。 **Prior art**:本 repo 為新建,無既有測試可依循。測試執行器採 Node 內建 `node:test` + `node:assert`,與「零外部套件」的既定約束一致。 ## Out of Scope - 不修改任何目標專案的檔案(含不寫入目標專案的 CLAUDE.md);實作規範只存在於本 plugin 的 `references/`。 - 不自動建立 Gitea 標籤、不自動建立 Gitea 專案。 - 不自動修改 repo 或 org 的權限設定,亦不自動開啟 repo 的時間追蹤開關。 - 不自動張貼工時報表到任何管道。 - 不支援 GitHub/GitLab 等 Gitea 以外的議題系統。 - 不自動安裝 Node、tea 或任何執行環境,僅在缺失時印出安裝指引並中止。 - 不處理 Windows 的 symlink 議題(本次採產生轉接檔而非 symlink,因此不受影響)。 - 不提供議題的刪除或關閉流程。 - 不做多人協作的衝突合併(領取鎖只做阻擋,不做排隊)。 ## Further Notes - `tea` CLI 原生不支援 Projects、議題相依與碼錶,這三項一律透過 `tea api` 打 Gitea REST API;其餘(議題、標籤、Milestone、留言、工時列表)走 tea 原生子指令。 - 環境中 `jq` 不存在,因此腳本以 Node 實作而非 bash + jq。 - oh-my-pi 會自動讀取 `~/.claude/plugins/installed_plugins.json` 與其他平台目錄,理論上安裝 Claude Code 版即可被它看見;`install.js` 仍為它產生原生轉接檔以確保指令命名一致。 - Codex 的 `~/.codex/prompts/` 已被官方標示為棄用、Antigravity 的 workflows 於 2026-11-01 移除,這兩處的轉接策略需在該日期前重新評估。
admin added the ready-for-agent label 2026-09-17 03:35:39 +00:00
admin removed the ready-for-agent label 2026-09-17 03:36:46 +00:00
jiantw83 added the ready-for-agent label 2026-09-17 03:37:16 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: plugins/tea-sdlc#1