開發流程的每一段(規劃、分析、實作、修正、工時回報)目前都靠人工在 Gitea 網頁與終端之間來回搬運:需求寫成散文、工作包憑印象拆、分支與 commit 命名各憑喜好、PR 描述每次結構不同、工時靠記憶補登。結果是三種反覆出現的損耗:
同時,使用者同時使用多個 coding agent(Claude Code / Codex / Antigravity / Copilot / Kiro / oh-my-pi / OpenCode),流程若只寫給其中一家,換工具就得重寫。
一組六個顯式指令,把 SDLC 各階段固定成可重複的流程;所有對外部系統(Gitea、git)的呼叫下沉到零相依的 Node 腳本,統一 JSON 輸入輸出;所有產出(議題、PR、報表)套用固定模板。流程正本只寫一份平台中立 markdown,由安裝腳本產生各平台的薄轉接檔。
使用者的體驗是:/sdlc-plan 把一段口語需求變成結構化需求議題;/sdlc-analyze 逐題把可行性疑點問到共識後生出工作包;/sdlc-feat 領取工作包、開分支、逐項實作並開 PR;/sdlc-fix 處理 PR 留言;/sdlc-sync 把散落的留言決策收回議題描述;/sdlc-report 產出工時報表。
/sdlc-plan
/sdlc-analyze
/sdlc-feat
/sdlc-fix
/sdlc-sync
/sdlc-report
模組邊界
prompts/sdlc-{plan,analyze,feat,fix,sync,report}.md
scripts/*.js
fetch
child_process
fs
templates/*.md
overview-artifact.html
{{變數}}
references/*.md
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 或環境變數。
{ok, data, error:{code, message}}
lib.js
--dry-run
internal_tracker.enable_time_tracker
fileURLToPath(import.meta.url)
templates/
references/
腳本清單: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。
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。
install
prompt
status
schedule
pr-reply
pr-watch
worktree-remove
worktree-ensure
wp-list
issue-body.js
pr-threads.js
抽取契約(下游指令唯一的議題讀取管道,只讀 body 不讀留言)
{index, url, title, labels[], 總覽, 背景, 目標[], 非目標[], 名詞表[{term,def}], 流程圖, 驗收標準[], 影響範圍[], 未決事項[], 未處理留言數}
{index, url, title, 需求議題, 描述, 架構圖, 範圍邊界[], 介面契約[], 待辦[{text,done,raw,驗收[{text,done,raw}]}], 整體驗收[], repos[], 相依:{blocks[],depends[]}, assignee, 碼錶中, 未處理留言數}
{repo, 需求議題, 工作包[{index,title,url,state,assignee}], 數量}
--repo --requirement <需求議題編號>
--index
需求議題
issue-body
需求議題:#N
raw 欄位保留原始 markdown 行,供 issue-update 做精確字串替換式的 checkbox 勾選(PATCH 局部,不重寫整份 body)。
raw
Gitea 承載對應
POST /issues/{i}/dependencies
/blocks
Issue.time_estimate
進行中
+1
已知平台限制與因應
projects
/user/stopwatches
repo.code: write
repo.issues: write
permissions.push
跨平台佈署
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 轉接檔。轉接檔內容為一行指向正本,路徑於產生時替換為絕對路徑。
~/.claude/
~/.codex/
~/.config/opencode/
~/.omp/
~/.kiro/
~/.gemini/
.github/
--platform a,b
--uninstall
SKILL.md
所有 description 統一前綴 僅由 /sdlc-xxx 指令叫用。;在支援關閉自動觸發的平台設對應旗標。已接受的取捨:Antigravity、Copilot、Kiro 無法關閉自動觸發,靠窄化 description 降低誤觸。
僅由 /sdlc-xxx 指令叫用。
輸出模板
{動詞}{名詞}
flowchart
sequenceDiagram
stateDiagram-v2
graph TD
HTML artifact 總覽
/sdlc-plan 與 /sdlc-analyze 各產一份,網址寫回議題 body 並於重跑時原地更新(不產生新連結)。markdown 白話總覽仍保留於議題內。注意 artifact 預設私有,組織外無法開啟。
命名規則
{類型}/{英文-kebab-需求描述}/main
{類型}/{需求描述}/{功能描述}
{類型}({檔案|功能}): {繁中需求描述}
分層與註解規範(references/coding-standards.md)
references/coding-standards.md
分層判定以職責而非目錄:對外介面即控制層、所有邏輯在服務層、任何碰 DB/API/資料來源者為存取層。控制層寫功能註解;服務層寫邏輯註解並標註所有呼叫的方法;存取層寫資料源註解;所有屬性寫用途註解(屬性為類別時遞迴),並附真實資料範例——優先取自 MCP,無 MCP 則以邏輯推理並明確註明來源未經驗證。改檔前依專案檔(*.csproj/composer.json/package.json/go.mod/pom.xml/pyproject.toml)偵測語言,對照 references/comment-styles.md;偵測不到即停止並詢問。
*.csproj
composer.json
package.json
go.mod
pom.xml
pyproject.toml
references/comment-styles.md
互動協定
分析階段以 AskUserQuestion 一次一題,選項固定為「建議(含理由)」與「手動輸入」,依架構→邏輯→資料→時程順序清空,全部結束後輸出共識摘要。規劃與分析本身已含問題釐清,因此寫入 Gitea 前不再設額外確認點。/sdlc-feat 的逐項待辦完成不打斷,只印進度。
AskUserQuestion
報表期間定義
一週為週一至週日;該週的週五所屬月份即為歸屬月;W1–W5 為該週五是當月第幾個週五。--week(預設,本週一至今日)/--month YYYY-MM/--year YYYY,月報以 W1–W5 分段小計。
--week
--month YYYY-MM
--year YYYY
什麼是好的測試:只測外部行為,不測實作細節。對本專案而言,外部行為就是「給定一組 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 更可信,且成本低)。
測試對象優先序:
--dry-run 兼作測試工具:所有寫入型腳本在 --dry-run 下輸出「將發出的請求」而非執行,讓寫入路徑不需要真實 Gitea 也能被斷言。
Prior art:本 repo 為新建,無既有測試可依循。測試執行器採 Node 內建 node:test + node:assert,與「零外部套件」的既定約束一致。
node:test
node:assert
tea
tea api
jq
~/.claude/plugins/installed_plugins.json
~/.codex/prompts/
No dependencies set.
The note is not visible to the blocked user.
Problem Statement
開發流程的每一段(規劃、分析、實作、修正、工時回報)目前都靠人工在 Gitea 網頁與終端之間來回搬運:需求寫成散文、工作包憑印象拆、分支與 commit 命名各憑喜好、PR 描述每次結構不同、工時靠記憶補登。結果是三種反覆出現的損耗:
同時,使用者同時使用多個 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
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 承載對應
POST /issues/{i}/dependencies、/blocksIssue.time_estimate寫不進去:Gitea 1.27 的 API 沒有任何請求定義接受該欄位,它只出現在議題的回應裡。report的估算也改讀這一行)進行中標籤+1已知平台限制與因應
project-add掃最近 50 筆議題的projects欄位反查 id→名稱對照;全空時要求使用者貼專案網址(結尾即 id)。/user/stopwatches):領取鎖改用 assignee + 標籤,碼錶僅用於工時。repo.code: write不蘊含repo.issues: write。因此權限檢查必須針對 issues unit 實測(嘗試性讀寫或檢查 collaborator 身分),不能只看permissions.push。跨平台佈署
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 降低誤觸。輸出模板
{動詞}{名詞},禁止流水編號。flowchart;工作包依性質用sequenceDiagram/flowchart/stateDiagram-v2;全景用graph TD。節點上限 12、節點文字 ≤8 字,超過即拆圖或不畫。HTML artifact 總覽
/sdlc-plan與/sdlc-analyze各產一份,網址寫回議題 body 並於重跑時原地更新(不產生新連結)。markdown 白話總覽仍保留於議題內。注意 artifact 預設私有,組織外無法開啟。命名規則
{類型}/{英文-kebab-需求描述}/main;從功能分支{類型}/{需求描述}/{功能描述}。需求描述由議題標題翻譯,≤40 字元。{類型}({檔案|功能}): {繁中需求描述},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 更可信,且成本低)。測試對象優先序:
wp-extract/issue-extract— 模板解析是整條鏈的上游,解析錯則下游全錯。餵入各種模板變體(缺段落、巢狀驗收為空、checkbox 已勾、中英混排)驗證輸出契約。issue-update的 checkbox 精確替換 — 驗證只動目標行、重複文字不誤傷、raw不匹配時回錯誤而非盲改。commit-split的類型分類與branch-prep的分支命名 — 純字串規則,表格驅動測試成本最低、回歸價值最高。claim的領取鎖決策表 — 他人 assignee/自己碼錶跑在本議題/跑在別的議題/無鎖,四種狀態各一例。report的週次歸屬 — 跨月、跨年、當月有五個週五等邊界。install.js— 在臨時家目錄上驗證偵測、產生、--uninstall後無殘留。--dry-run兼作測試工具:所有寫入型腳本在--dry-run下輸出「將發出的請求」而非執行,讓寫入路徑不需要真實 Gitea 也能被斷言。Prior art:本 repo 為新建,無既有測試可依循。測試執行器採 Node 內建
node:test+node:assert,與「零外部套件」的既定約束一致。Out of Scope
references/。Further Notes
teaCLI 原生不支援 Projects、議題相依與碼錶,這三項一律透過tea api打 Gitea REST API;其餘(議題、標籤、Milestone、留言、工時列表)走 tea 原生子指令。jq不存在,因此腳本以 Node 實作而非 bash + jq。~/.claude/plugins/installed_plugins.json與其他平台目錄,理論上安裝 Claude Code 版即可被它看見;install.js仍為它產生原生轉接檔以確保指令命名一致。~/.codex/prompts/已被官方標示為棄用、Antigravity 的 workflows 於 2026-11-01 移除,這兩處的轉接策略需在該日期前重新評估。