feat/plan-analyze-timing/main
master
規劃與分析的時間不再憑空消失。/sdlc-report 的數字裡從此規劃、分析、實作三段都在, 估算的落差看得出來源——在此之前碼錶只在領取工作包時起動,報表上規劃永遠是零。
/sdlc-report
#56
#57
四顆 commit:
5638593
81d02bf
7ee050d
46c6db8
新增:
scripts/time-log.js
test/time-log.test.js
test/helpers/prompt-doc.js
promptStep
修改:
scripts/timer.js
--stop
scripts/lib.js
stopStopwatch
pr-create.js
(login, repo, index)
scripts/pr-create.js
prompts/sdlc-plan.md
prompts/sdlc-analyze.md
prompts/sdlc-feat.md
test/timer.test.js
test/sdlc-plan-assets.test.js
test/sdlc-analyze-assets.test.js
test/sdlc-feat-assets.test.js
test/overview-artifact.test.js
test/wp-schedule-assets.test.js
補登的長度由腳本算,不由 agent 做減法。 交給 agent 等於讓兩邊的時鐘與時區各算一次, 而算錯了報表上看不出來。--since 收指令開始的時刻,終點由腳本自己判斷。
--since
終點看議題是不是這一輪建立的。 是就補到議題建立那一刻;對既有議題重跑就補到補登的 當下——拿舊的建立時間當終點會算出負數,等於把那一輪的工夫丟掉,而那正是這顆議題要修的 毛病,只是換個位置出現。重跑是累計不是覆蓋,每一輪各記一筆。
防重複只留一條:錶已經跑在這顆議題上。 補登排在起錶之前,錶在跑代表這一輪已經走到 起錶那一步,補下去會與錶涵蓋的區間重疊。曾經用過的「議題上已經有工時就跳過」與累計互斥, 拿掉了。
--stop 只停 --index 指的那一顆。 別顆議題上的錶一律不碰:Gitea 在別顆議題上起新錶 會靜默地停掉並記錄前一顆,那種靜默結算正是領取鎖那條規則當初要擋的,不能在這裡反過來 製造它。claim.js 一個字都沒動。
--index
claim.js
analyze 的錶起在第一段開頭。 分析最耗時的正是共識之前那一段(四類疑點逐題問到收斂), 從第二段才起的話那段時間永遠是零。因此該正本的邊界由「共識摘要之前不對 Gitea 產生任何 寫入」改寫成「不寫入任何內容」,並把碼錶明文除外、寫上理由:它記的是工時,不是內容。 這一條事前與 repo 擁有者確認過。
plan 與 analyze 各記各的。 plan 在自己的回報那一步就停錶,所以同一顆需求議題上會有 兩筆工時。「每個階段停掉自己起的錶」與「兩段合成一筆」無法同時成立,而錶跨階段跑的代價 (跑完就去開會,錶跑一整天)比多一筆紀錄大得多。議題 #57 的規格已就此更正。
正本之間改以步驟名稱互指。 編號會整批位移,名字不會;promptStep 讓測試用同一套規則 框出某一步,別人插一步時不會無聲地框到另一段內容上。
--dry-run
/sdlc-plan
/sdlc-analyze
/sdlc-feat
pr-create
scripts/report.js
/user/times
npm test(含新增的 23 條):
npm test
ℹ tests 823 ℹ suites 0 ℹ pass 823 ℹ fail 0 ℹ cancelled 0 ℹ skipped 0 ℹ todo 0 ℹ duration_ms 11168.6262
另在議題 #57 上實跑過真實路徑(該 repo 的 enable_time_tracker 是 true):
enable_time_tracker
true
--- 1. 補登 --- {"ok":true,"data":{...,"since":"2026-09-18T00:42:47.207Z","迄":"2026-09-18T00:44:48.469Z","依據":"補登當下","秒數":121,"補登":true}} --- 2. 起錶 --- {"ok":true,"data":{...,"碼錶中":true,"已在計時":false}} --- 3. 錶在跑時補登應跳過 --- {"ok":true,"data":{...,"秒數":296,"補登":false,"note":"碼錶已經跑在這顆議題上。補登排在起錶之前,錶在跑就代表這一輪補過了,補下去會與錶重疊。"}} --- 4. 停錶 --- {"ok":true,"data":{...,"碼錶已停":true}} --- 5. 再停一次(錶已經沒在跑) --- {"ok":true,"data":{...,"碼錶已停":false,"note":"碼錶本來就沒在這顆議題上運轉,這一步略過;別顆議題上的錶不由這裡代停。"}} --- 6. report --week --- "總計": {"實際秒": 128, "實際工時": "0h 02m"} "議題": [{"index": 57, "實際秒": 128, "實際工時": "0h 02m"}]
驗證用的那兩筆工時(121 秒與 7 秒)驗完已刪除,議題 #57 上目前一筆工時都沒有。
reviewer 可自行重現:git diff origin/master 後 npm test;真實路徑以 --dry-run 觀察即可,不必真的寫入。
git diff origin/master
停錶原本只長在 pr-create 裡,而規劃與分析接下來也要停自己的錶(議題 #57)。 那段容錯邏輯——「錶沒在跑」的狀態碼隨站台版本而異,認的是狀態碼在 409/500 這一組**且**訊息說的是碼錶——各寫一份遲早會在某一邊漏掉一種狀態碼,而它漏掉的 症狀正是「事情做完了卻回報失敗」。 順手把簽章改成與同伴一致的 (login, repo, index):fetchIssue、listIssueTimes、 stopwatchOnIssue 都這樣收,只有它收一條手組的路徑字串。 新增 listIssueTimes 供補登判斷「這顆議題上已經有工時了嗎」。它在議題讀得到卻 404 時報 TIME_TRACKER_OFF,與四層前置檢查第四層說同一句話——試跑不跑前置檢查, 那句話得由它自己說,否則試跑看到的是一句看不懂的 404。 議題 #57 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
碼錶只在領取工作包時起動,所以工時報表上規劃與分析永遠是零。久了會讓人以為 規劃不花時間,而那正是估算失準最常見的來源。 timer 加上 --stop,而且**只停 --index 指的那一顆**。每個階段停掉自己起的那一支, 錶就不會跨階段跑——跑完就去開會而錶跑一整天,報表當場失真。反過來,別顆議題上的錶 一律不碰:Gitea 在別顆議題上起新錶會靜默地停掉並記錄前一顆,那種靜默結算正是領取鎖 那條規則當初要擋的,不能在這裡反過來製造它。錶本來就沒在跑不算失敗,這一步多半排在 回報之前,報成失敗只會讓人以為前面那件事沒做成而重跑一次。 time-log 補登議題建立之前那一段——讀齊輸入、逐項詢問、組出議題內容,往往是整個 plan 最耗時的部分,而那時候議題還不存在,沒有標的可起錶。長度由腳本自己算(議題的建立時間 減掉 --since),交給 agent 做減法等於讓兩邊的時鐘各算一次,而算錯了報表上看不出來。 **不設時間上限、照實補登**:中途去開會的兩小時會一起算進去,換來這個流程不必為此 多長一題出來問使用者。 補登不是冪等的動作,所以兩種情況跳過不補:錶已經跑在這顆議題上(補登排在起錶之前, 錶在跑就代表這一段補過了),以及這顆議題上已經有工時(整個流程跑完過一次)。工時記 重複比記不到更難在報表上被發現,所以判斷偏向不補。 時間追蹤在現有環境下可能是關著的,真實路徑跑不起來;兩支都靠 --dry-run 與 stub server 測,共 27 條。 議題 #57 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
起錶與停錶寫在同一份正本裡成對出現,讀的人一眼看得出這段計時涵蓋到哪;兩份各加一節 「計時範圍」把兩端指出來。 sdlc-plan 記兩段:議題建立之前那段在第一步記下開始時間、議題建立之後以補登記上去; 之後起錶,回報那一步停錶。補登排在議題建立之後、起錶之前,順序反過來的話補登會被 time-log 當成「這一步做過了」而跳過。 sdlc-analyze 在它分析的那顆需求議題上起錶,起點放在第一段開頭——分析最耗時的正是 共識之前那一段,從第二段才起的話那段時間永遠是零。因此「共識摘要之前不對 Gitea 產生任何寫入」改寫成「不寫入任何**內容**」,並把碼錶明文除外、寫上理由:它記的是 工時,不是內容。這一條與 repo 擁有者確認過。 sdlc-feat 的「碼錶一律由使用者自己停」收斂成「**別顆議題上的**錶一律由使用者自己停」 ——它原本讀起來像全域規則,而現在每道指令都會停自己起的那一支。 正本之間改以步驟**名稱**互指,不用編號:編號會整批位移,名字不會。測試跟著改用新的 promptStep 輔助函式,以名字框出某一步的內容,別人插一步時不會無聲地框到另一段上。 議題 #57 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
原本的終點一律是議題的建立時間,所以對既有議題重跑時相減為負,補登直接 no-op—— 那一輪的規劃時間就這樣掉了,而那正是這顆議題要修的毛病,只是換個位置出現。 終點改成看議題是不是這一輪建立的:是就補到議題建立那一刻(第一次跑),不是就補到 補登的當下(重跑)。回報多出 `迄` 與 `依據` 兩個欄位,讓人一眼看出這一筆補的是哪一段。 「這顆議題上已經有工時就跳過」這條規則拿掉了,它與累計互斥。防重複只剩一條:錶已經 跑在這顆議題上——那一段已經有錶在記,補下去會與錶涵蓋的區間重疊。連帶把 lib 的 listIssueTimes 一起移除,沒有人再用它。 實跑驗過(議題 #57):補登 121 秒、起錶、停錶 7 秒,兩筆都進得了週報,驗完刪除。 議題 #57 的規格同步更正,另外兩處過期的敘述也一併改掉。 議題 #57 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
No dependencies set.
The note is not visible to the blocked user.
摘要
規劃與分析的時間不再憑空消失。
/sdlc-report的數字裡從此規劃、分析、實作三段都在,估算的落差看得出來源——在此之前碼錶只在領取工作包時起動,報表上規劃永遠是零。
需求議題
#56
工作包議題
#57
變更內容
四顆 commit:
5638593refactor(lib): 停錶與議題工時清單下沉到 lib81d02bffeat(timer,time-log): 起錶配上停錶,並補登議題建立之前的時間7ee050ddocs(sdlc-plan,sdlc-analyze): 兩份正本各自起停自己的錶46c6db8feat(time-log): 對既有議題重跑時補到當下,每一輪各記一筆新增:
scripts/time-log.js— 補登一段沒有錶記到的工時test/time-log.test.js— 12 條test/helpers/prompt-doc.js的promptStep— 以步驟名稱(不是編號)框出正本裡的某一步修改:
scripts/timer.js— 加上--stopscripts/lib.js—stopStopwatch由pr-create.js下沉,簽章改成與同伴一致的(login, repo, index)scripts/pr-create.js— 改用下沉後的stopStopwatchprompts/sdlc-plan.md、prompts/sdlc-analyze.md— 各加一節「計時範圍」與起停步驟prompts/sdlc-feat.md— 「碼錶一律由使用者自己停」收斂成只講別顆議題test/timer.test.js(+6 條)、test/sdlc-plan-assets.test.js(+6 條)、test/sdlc-analyze-assets.test.js(+5 條)、test/sdlc-feat-assets.test.js、test/overview-artifact.test.js、test/wp-schedule-assets.test.js設計重點
補登的長度由腳本算,不由 agent 做減法。 交給 agent 等於讓兩邊的時鐘與時區各算一次,
而算錯了報表上看不出來。
--since收指令開始的時刻,終點由腳本自己判斷。終點看議題是不是這一輪建立的。 是就補到議題建立那一刻;對既有議題重跑就補到補登的
當下——拿舊的建立時間當終點會算出負數,等於把那一輪的工夫丟掉,而那正是這顆議題要修的
毛病,只是換個位置出現。重跑是累計不是覆蓋,每一輪各記一筆。
防重複只留一條:錶已經跑在這顆議題上。 補登排在起錶之前,錶在跑代表這一輪已經走到
起錶那一步,補下去會與錶涵蓋的區間重疊。曾經用過的「議題上已經有工時就跳過」與累計互斥,
拿掉了。
--stop只停--index指的那一顆。 別顆議題上的錶一律不碰:Gitea 在別顆議題上起新錶會靜默地停掉並記錄前一顆,那種靜默結算正是領取鎖那條規則當初要擋的,不能在這裡反過來
製造它。
claim.js一個字都沒動。analyze 的錶起在第一段開頭。 分析最耗時的正是共識之前那一段(四類疑點逐題問到收斂),
從第二段才起的話那段時間永遠是零。因此該正本的邊界由「共識摘要之前不對 Gitea 產生任何
寫入」改寫成「不寫入任何內容」,並把碼錶明文除外、寫上理由:它記的是工時,不是內容。
這一條事前與 repo 擁有者確認過。
plan 與 analyze 各記各的。 plan 在自己的回報那一步就停錶,所以同一顆需求議題上會有
兩筆工時。「每個階段停掉自己起的錶」與「兩段合成一筆」無法同時成立,而錶跨階段跑的代價
(跑完就去開會,錶跑一整天)比多一筆紀錄大得多。議題 #57 的規格已就此更正。
正本之間改以步驟名稱互指。 編號會整批位移,名字不會;
promptStep讓測試用同一套規則框出某一步,別人插一步時不會無聲地框到另一段內容上。
解決的問題
--dry-run下看不出「這一步會不會真的做」:兩支都先讀現況再印出將發出的請求。影響的功能
/sdlc-plan、/sdlc-analyze各多兩步(起錶/停錶)與一節「計時範圍」;plan 另多一步「記下開始時間」與一次補登。
/sdlc-report的數字會變大——規劃與分析從此有工時。這是本次要的結果。/sdlc-feat只改一句措辭(「碼錶一律由使用者自己停」→ 只講別顆議題的錶),行為不變。pr-create的停錶行為不變,只是改叫 lib 的共用實作。claim.js(領取鎖)未改動。scripts/report.js未改動:它讀/user/times,補登的工時本來就進得去。測試結果
npm test(含新增的 23 條):另在議題 #57 上實跑過真實路徑(該 repo 的
enable_time_tracker是true):驗證用的那兩筆工時(121 秒與 7 秒)驗完已刪除,議題 #57 上目前一筆工時都沒有。
其他
reviewer 可自行重現:
git diff origin/master後npm test;真實路徑以--dry-run觀察即可,不必真的寫入。