feat(time-log): 對既有議題重跑時補到當下,每一輪各記一筆

原本的終點一律是議題的建立時間,所以對既有議題重跑時相減為負,補登直接 no-op——
那一輪的規劃時間就這樣掉了,而那正是這顆議題要修的毛病,只是換個位置出現。

終點改成看議題是不是這一輪建立的:是就補到議題建立那一刻(第一次跑),不是就補到
補登的當下(重跑)。回報多出 `迄` 與 `依據` 兩個欄位,讓人一眼看出這一筆補的是哪一段。

「這顆議題上已經有工時就跳過」這條規則拿掉了,它與累計互斥。防重複只剩一條:錶已經
跑在這顆議題上——那一段已經有錶在記,補下去會與錶涵蓋的區間重疊。連帶把 lib 的
listIssueTimes 一起移除,沒有人再用它。

實跑驗過(議題 #57):補登 121 秒、起錶、停錶 7 秒,兩筆都進得了週報,驗完刪除。
議題 #57 的規格同步更正,另外兩處過期的敘述也一併改掉。

議題 #57

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-18 08:46:27 +08:00
co-authored by Claude Opus 5
parent 7ee050de2f
commit 46c6db8c70
4 changed files with 66 additions and 79 deletions
-27
View File
@@ -1041,33 +1041,6 @@ export async function stopStopwatch(login, repo, index) {
return false;
}
/**
* 這顆議題上已經記到的工時。
*
* 清單的範圍隨權限而異:不是 repo admin 時 Gitea 只回自己的那幾筆,是 admin 時連別人的
* 一起回。呼叫端(補登)問的是「這顆議題上已經有工時了嗎」,**兩種範圍都答得了那一問**:
* 剛建好的議題上一筆都不該有,有了就代表這個流程跑過一次。範圍寬一點只會讓它偏向不補,
* 而那是安全的方向——工時記重複比記不到更難在報表上被發現。
* @param {{base: string, token: string}} login
* @param {string} repo owner/name
* @param {number} index
* @returns {Promise<object[]>}
*/
export async function listIssueTimes(login, repo, index) {
const path = `/repos/${repo}/issues/${index}/times`;
const response = await giteaRequest(login, 'GET', path);
// 議題本身讀得到卻在這裡 404,代表的是 repo 的時間追蹤關著。訊息與前置檢查第四層
// 對齊:同一件事在試跑與實跑上要說同一句話,否則試跑看到的是一句看不懂的 404
if (response.status === 404) {
throw new ScriptError(
'TIME_TRACKER_OFF',
'repo 尚未開啟時間追蹤,工時記不進去;請到 Settings → Advanced Settings → Enable Time Tracker 開啟',
);
}
return expectOk(response, `GET ${path}`) ?? [];
}
// ── 標籤 ───────────────────────────────────────────────────────────
/**