Commit Graph
11 Commits
Author SHA1 Message Date
jiantw83andClaude Opus 5 7ee050de2f docs(sdlc-plan,sdlc-analyze): 兩份正本各自起停自己的錶
起錶與停錶寫在同一份正本裡成對出現,讀的人一眼看得出這段計時涵蓋到哪;兩份各加一節
「計時範圍」把兩端指出來。

sdlc-plan 記兩段:議題建立之前那段在第一步記下開始時間、議題建立之後以補登記上去;
之後起錶,回報那一步停錶。補登排在議題建立之後、起錶之前,順序反過來的話補登會被
time-log 當成「這一步做過了」而跳過。

sdlc-analyze 在它分析的那顆需求議題上起錶,起點放在第一段開頭——分析最耗時的正是
共識之前那一段,從第二段才起的話那段時間永遠是零。因此「共識摘要之前不對 Gitea
產生任何寫入」改寫成「不寫入任何**內容**」,並把碼錶明文除外、寫上理由:它記的是
工時,不是內容。這一條與 repo 擁有者確認過。

sdlc-feat 的「碼錶一律由使用者自己停」收斂成「**別顆議題上的**錶一律由使用者自己停」
——它原本讀起來像全域規則,而現在每道指令都會停自己起的那一支。

正本之間改以步驟**名稱**互指,不用編號:編號會整批位移,名字不會。測試跟著改用新的
promptStep 輔助函式,以名字框出某一步的內容,別人插一步時不會無聲地框到另一段上。

議題 #57

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 19:32:37 +08:00
jiantw83 d6b44e0ba8 test(分批提交): 把變更依類型分批 commit
一個 commit 只裝一種類型:程式碼、測試、文件、雜項各自成批,reviewer 一次只看一件事,
日後 git log 也讀得懂。全部混成一顆「完成工作包」的巨大 commit,等於沒有歷史。

類型多半看得出來——測試檔就是 test、README 就是 docs——但 scripts/ 底下的改動是新功能
還是修 bug,只有做的人知道,所以那一批由 --type 指定。這張對照表是純字串規則,表格驅動。

scope 單檔用檔名(claim.test.js 的 scope 是 claim,不是 claim.test),多檔用 --scope 的
功能名。描述要有中文:日後回顧時看得懂的是中文,而夾雜英文的專有名詞本來就該保留原文。

--files 讓一次變更橫跨兩個功能時能分兩次跑;--body 讓工具產出的歷史與本 repo 既有的
commit 一樣說明得出「為什麼」。

列變更檔案刻意不用 git status --porcelain:它的前兩欄是狀態碼,而 runGit 會 trim 掉
輸出的前導空白,未 staged 的修改會少掉檔名的第一個字元。
2026-09-17 08:23:21 +00:00
jiantw83andClaude Opus 5 8ea6a2a8b3 test(逐項實作): 覆蓋勾選的五種危險、兩份規則正本與正本第二段
勾選的測試全部繞著「會不會改錯行」打轉,五種都是 code review 抓出來的實際缺陷:
圍欄裡長得像 checkbox 的那一行不會被改到、不同段落的同一句話靠 --section 分得開、
大寫 [X] 重跑是 no-op、方框後沒有空白照樣勾得到、沒有方框的項目給的是指路的錯誤
而不是謊報已勾過。

另外釘住抽取端與勾選端的一致性:wp-extract 交得出來的每一種 raw,--tick 都要收得下。

patchOf 收進 helpers——它先前在三個測試檔裡各有一份一模一樣的定義。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 07:39:54 +00:00
jiantw83andClaude Opus 5 e1897f2d33 test(helpers): 加上「有遠端」的臨時 repo,並收掉三份重複的 git 執行器
branch-prep 的重點行為都繞著遠端打轉——來源分支在遠端已存在時要 pull 而不是重建、
目標分支已存在時不能覆蓋他人進度。這些事沒有遠端就驗不出來,所以補一個 bare origin
加工作用 clone,並附 pushFromElsewhere 模擬「別人推了東西上去」。

順手把 makeTempRepo 與新 helper 各自重寫一次的 git 執行器與 seed 收成共用的兩支。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 07:07:01 +00:00
jiantw83andClaude Opus 5 17178f0c4d feat(佈署): 以 npm 裝出 tea-sdlc 指令並產生各平台轉接檔
單一入口 bin/tea-sdlc.js 認四個子指令。第一個位置參數是子指令,其餘 argv 原樣
交出去——既有的 flag 解析拒絕位置參數,所以子指令必須在那之前就被取走。

轉接檔裡沒有路徑,只有一句 tea-sdlc prompt --name <指令名>。正本在哪由 PATH 上
的 tea-sdlc 自己回推:fnm 把 Node 版號寫進全域安裝路徑,寫死路徑的話升一次
Node,七個平台的轉接檔會同時指向不存在的檔案,而且不會有任何錯誤訊息。

prompt 是全專案唯一輸出非 JSON 的路徑,理由只有一個:它的輸出要餵給模型讀。
失敗仍走 envelope——成功是內容,失敗才需要結構。

status 的 ok 不兼差表達環境好壞,健康與否放在 data.healthy:呼叫端要分得出
「status 掛了」與「status 成功查到你環境有問題」。

install 只寫進偵測得到的平台;缺 git/tea 只警告不中止,因為那兩個完全不影響
轉接檔產生,硬擋等於逼使用者為了裝 plugin 先去裝 tea。uninstall 只刪帶產生標記
的檔案,使用者自己寫的同名檔案一律留著並在輸出裡交代。裝哪些指令以 prompts/ 裡
實際存在的正本為準,不是寫死的六個名字——裝出指向不存在正本的轉接檔,使用者只會
看到 PROMPT_NOT_FOUND。

流程正本的 description 前綴在抄進轉接檔之前就檢查:有三個平台關不掉自動觸發,
全靠那句話把 description 窄到不會被誤判,不能等使用者發現誤觸才知道漏了。

議題 #26 #27 #28 #29 #17

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 06:59:37 +00:00
jiantw83andClaude Opus 5 0aa0439061 test(總覽網頁): 釘住模板結構與兩份正本的規則
模板的檢查重點是「樣式與內容分離」與「全景段落能整段消失」,兩者壞掉時規劃版會
留下空標題或行內樣式散落各處,肉眼不容易發現。

順帶把 work-package 測試的 phase2 切法收斂到第三段之前——原本切到檔尾,第三段
新增的編號清單會混進段落順序的斷言裡。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 06:22:29 +00:00
jiantw83andClaude Opus 5 6457d68874 refactor(測試): 模板結構的三項檢查抽到共用斷言
段落順序、正本的編號清單、圖表段落不寫死圍欄——這三件事需求議題與工作包議題
都要驗,第二份模板出現時就該抽出來。兩份測試原本各抄一份,其中佔位數的斷言
還悄悄長成不同寫法(一邊 >=、一邊 ==);抽出來之後這種分歧會被逼著講清楚。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 05:43:26 +00:00
jiantw83andClaude Opus 5 930270f545 refactor(測試): 正本的共用檢查抽到 helpers
description 前綴、沒有 frontmatter、不出現平台專屬字樣——這三件事每一份流程
正本都要驗,第二份正本出現時就該抽出來,而不是再抄一次。順帶把讀正本、讀規則
正本、讀模板三個路徑組合也收在同一處。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 05:11:06 +00:00
jiantw83andClaude Opus 5 b0bd061852 refactor(測試): 共用假 Gitea 的啟動與環境變數
每支測試各自寫一次「啟動 stub、登記 close、組環境變數」已經重複三次,抽到
helpers 之後新增測試檔只要一行。各檔仍保留自己的預設路由,因為那是該檔的
情境設定,不該共用。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 04:44:45 +00:00
jiantw83andClaude Opus 5 4ae097f1e1 fix(腳本契約): 長輸出不再被截斷,查重翻頁加上上限
process.stdout.write 之後立刻 process.exit 會截斷輸出——stdout 接到 pipe 時
寫入是非同步的。改為等 write 的 callback 回來再退出。實測舊寫法在約 83KB 處
被切斷,新增的回歸測試以 8000 筆標籤覆蓋這條路徑。

findIssueByTitle 的翻頁原本沒有上限,Gitea 若持續回滿一頁就會無限打下去。
加上 200 頁上限,超過即以 DEDUPE_LIMIT 報錯而非無聲回 null——無聲回 null 會
讓呼叫端把既有議題再建一次,正好是冪等查重要防的事。

parseFlags 取值時不再於三元運算式內遞增迴圈變數,改為獨立敘述。

測試工具的 maxBuffer 調高到 64MB:預設 1MB 會在長輸出時砍掉子行程,那是測試
工具的限制而非腳本的問題。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 04:26:51 +00:00
jiantw83andClaude Opus 5 28dec83498 test(腳本契約): 以子行程與 stub server 驗證契約與四層前置檢查
測試一律以子行程執行腳本、比對 stdout 的單行 JSON 與 exit code,因為那正是
七個平台共用的實際呼叫方式,不會因內部重構而破碎。

Gitea 以本機 stub server 替身並錄下每一筆請求,藉此斷言「腳本到底發了哪些
請求」——包含 --dry-run 不得發出任何請求、前一層檢查沒過就不再往下打、
寫入權探針不得挾帶任何要寫入的欄位。git 則在 .tmp/ 下的臨時 repo 跑真實
指令,比 mock 可信且成本低。

lib-exports.test.js 是唯一直接 import lib 的例外:冪等查重與 git 執行點在
CLI 邊界上還沒有消費者,檔頭已註明等 #4 與 #10 落地後即可縮小或移除。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 04:26:51 +00:00