一次交貨留下兩樣東西:跨 repo 版本清單(inkstone/ISEP#84)+結案記帳(inkstone/ISEP#85) #103

Closed
claude-code wants to merge 1 commits from feat/release-manifest-and-milestone-account into main
Member

【工單】inkstone/ISEP#84inkstone/ISEP#85(同一條分支,兩張票都在「一次交貨結束時要留下什麼」這一格)

🔴 版本號待總管定版plugin.json 仍是 0.11.0,沒有自己動。
scripts/check-version-consistency.sh 現在是綠的:plugin.json=0.11.0、最新 tag=v0.11.0。)


#84 — 這一版由哪幾個 repo 的哪幾版組成

新增 scripts/release-manifest(freeze/verify/show/list/current/diff/rollback)。

三條硬規則長在工具裡,不是寫在文件裡靠人記得:

  • freeze 之前每一格都真的去 Gitea 抓一次,抓不到就不給凍結。
    「寫上去」跟「存在」是兩件事,而清單的用處完全建立在後者。
  • 凍結了就不准再加東西(同名清單已存在 ⇒ 拒絕覆寫)。新的需求進下一份。
  • 退版沒有「只退一個」這個選項rollback 一定吐出整份清單的每一格
    (含「已經在目標版本、不必動」的那幾格,列出來才證明沒有一格被漏掉);
    --only <某個 repo> 直接擋下——那正是票上那個病:
    剩下的還停在新版 ⇒ 一組從來沒測過的組合

清單與人看的 INDEX.md 寫在專案根的 releases/,不是 plugin 目錄
——ISEP 是 marketplace 裝的,claude plugin update 會把那個目錄整個換掉,
而清單的用處全部發生在「以後要退版的那一天」。

沒有新增 PreToolUse 閘是刻意的:這一層唯一能機械辨認的「退版動作」形狀很難跟
「讀取/談論」分開,而誤攔在本 repo 是第一級缺陷。所以閘做成工具本身就是唯一的門
(同 scripts/pr-verdict 的形狀),不去猜指令字串。

#85 — 估多久/花多久/差多少/為什麼差

新增 scripts/milestone-account(codes/list/audit/close/report)
hooks/milestone-account-guard.sh(PreToolUse/Bash,+1 支、+1 條註冊)。

  • 三個數字自己算,不用手填:取自 Gitea 的 created_atdue_onclosed_at
  • 差超過 ±25%(超時或提早都算)就要挑一個代號,挑不出來不准結案。
    提早太多不是好消息,是當初估太鬆——所以兩個方向同一條線。
  • 代號是七個的封閉集合(票上那張表,一個不多一個不少):
    idle 磨洋工/sidetrack 分心跳線/undispatched 忘了派工/cherry-pick 偏科/
    waiting 等答案/scope-creep 範圍變大/misestimate 純粹估錯。
    票上寫死的理由:能統計的前提是分類有限。
  • 代號要有 Gitea 時間軸撐得住audit 先從時間戳/指派欄位/標籤/票的歸屬
    算出哪幾個訊號成立,close 只接受訊號成立的那幾個;六個都不成立時唯一合法的
    就是 misestimate(=票上那句「以上都沒有,但還是差很多」)。
    不採信任何人的自述,這是票上寫死的。判準一句自然語言都不讀
  • 閘擋的是「直接 curl -X PATCH … state=closed 但還沒記帳」。
    純讀取/建里程碑/改期限/echo 那段指令/cat 這支閘/heredoc 內文/
    走正門 milestone-account close——全部放行
    真要手動關 ⇒ 指令裡加 milestone-account-ok(留痕)。
  • 帳本同樣寫在專案根的 system-dev/estimates/(理由同上:plugin 目錄會被換掉,
    而這張票的全部價值就在「累積」)。

milestone-account-guard 跟既有的 milestone-due-guard 是同一條線的兩端:
那支管里程碑要有真的期限(沒有期限就沒有「估多久」可言),這支管的時候要留下帳。


我跑過的(每一格都自己跑過,不是宣稱)

離線,不打 Gitea、不留測試票、不關任何真的 milestone、不建任何真的 release:

bash scripts/test-release-manifest.sh              → 通過 21 條,失敗 0 條
bash scripts/test-milestone-account.sh             → 通過 23 條,失敗 0 條
bash hooks/tests/milestone-account-guard.test.sh   → 通過 22 條,失敗 0 條

三支都在 CLAUDE_CODE_CHILD_SESSION 清掉之後重跑過一次(這台機器上它原本是 1)。

真實 Gitea 唯讀重演(只有 GET/--dry-run,一通寫入都沒送出):

  • milestone-account list --org inkstone --overdue 撈到的正是票上點名的那五個,而且每一個都算得出數字:
🔴 inkstone/arcrun-rag#47   估 0.5天/已 3.5天/+592%
🔴 inkstone/Arcrun#46       估 0.5天/已 3.6天/+592%
🔴 inkstone/Arcrun#50       估 0.8天/已 1.8天/+131%
🔴 inkstone/Arcrun#51       估 0.6天/已 1.6天/+178%
🔴 inkstone/ISEP#43         估 4.6天/已 7.6天/+66%
  • milestone-account audit inkstone/ISEP#43 從真的時間軸算出:
    最長空白 2.8 天(佔整段 37%)/29 個動作在別的票上(37%)/5 張票整段沒有人被指派/
    開跑之後才補進來 9/15 張票 ⇒ 可以挑的代號 idle / sidetrack / undispatched / cherry-pick / scope-creep
  • release-manifest freeze … --dry-runinkstone/ISEP@v0.11.0inkstone/arcrun-rag@1.4.60
    兩格都抓到真的 release;換成 v99.0.0 當場被擋下。

既有測試沒被我弄壞(同樣清掉 CLAUDE_CODE_CHILD_SESSION 跑):
release-tag 8/8、ticket-api-bypass 24/24、ticket-where-seen 17/17、comment-carries-task 22/22、
baton-handback 10/10、main-and-prod-push 13/13、stage-before-prod 13/13、github-contact 14/14、
kbdb-api-wall 10/10、dispatch-format 33/33、sdd 8/8、search-is-not-proof 31/31、
factory-idle 33/33、mainline-idle 61/61、reply-identity 11/11、ask-user-question 14/14、
gitea-arm-check 16/16、pr-verdict 52/52、countdown 20/20、prod-write 37/37、
版本三處一致

🔴 一格我沒有交乾淨,明講hooks/tests/main-and-prod-push-guard-cross-repo.test.sh
通過 14/失敗 5這是本來就紅的——我把改動 git stash 掉、在乾淨的 main 上重跑,
一模一樣是 14/5。不是這個 PR 造成的,也不在這兩張票的範圍內。

盤點數字

在我自己的樹上實數出來的,不是拿上一版加減推
system-dev/wiki/mistakes.md:那個數字是 leo 的驗收介面,多報就是假綠):

ls hooks/*.sh | wc -l                 →  53 → 54
grep -c '"command":' hooks/hooks.json →  68 → 69
ls -p scripts | grep -v / | wc -l     →  39

hooks-inventory.md 的落差偵測兩組 comm 都是空的(沒有閘漏列人話、沒有列了卻不存在的閘)。

順手修掉兩個真的漂移(不是改風格):

  • docs/hooks-inventory.md 的「一句話結論」同一行被貼了兩次,而標頭寫 52、內文寫 53
    ——同一頁裡三個數字互相矛盾,正是那一頁自己警告過的病。
  • 描述欄的「38 支腳本」是把 kbdb-live-exam/lib/patches/ 三個目錄也數進去了;
    用那一頁寫死的指令(只數檔案)實數是 39

我判斷的、寫下來讓你打回

  • #85 的訊號門檻是第一版,會需要調。 上面 ISEP#43 那次七個訊號命中了五個,
    偏寬。但這正是票上要的「把測得到變成可以統計、可以迭代」——
    資料累積起來之後調門檻,而不是現在憑感覺先調。
    🔴 調法只有一條:改 audit 的偵測器,不是在 close 開後門讓人繞過去。
  • #84 沒有配一支 PreToolUse 閘,理由寫在上面(誤攔風險 > 漏擋代價)。
    如果你認為需要,那是另一張票。
  • 兩份資料(清單、帳本)都落在專案根而不是 plugin 目錄。這是我自己裁的,
    理由是 plugin update 會把 plugin 目錄整個換掉。若你要它們住別的地方,
    兩支工具都吃 RELEASE_MANIFEST_DIRMILESTONE_ACCOUNT_DIR 環境變數,改一行就好。
【工單】`inkstone/ISEP#84`、`inkstone/ISEP#85`(同一條分支,兩張票都在「一次交貨結束時要留下什麼」這一格) 🔴 **版本號待總管定版**:`plugin.json` 仍是 `0.11.0`,沒有自己動。 (`scripts/check-version-consistency.sh` 現在是綠的:plugin.json=0.11.0、最新 tag=v0.11.0。) --- ## `#84` — 這一版由哪幾個 repo 的哪幾版組成 新增 `scripts/release-manifest`(freeze/verify/show/list/current/diff/rollback)。 三條硬規則**長在工具裡**,不是寫在文件裡靠人記得: - **freeze 之前每一格都真的去 Gitea 抓一次**,抓不到就不給凍結。 「寫上去」跟「存在」是兩件事,而清單的用處完全建立在後者。 - **凍結了就不准再加東西**(同名清單已存在 ⇒ 拒絕覆寫)。新的需求進下一份。 - **退版沒有「只退一個」這個選項**:`rollback` 一定吐出整份清單的每一格 (含「已經在目標版本、不必動」的那幾格,列出來才證明沒有一格被漏掉); `--only <某個 repo>` 直接擋下——那正是票上那個病: 剩下的還停在新版 ⇒ **一組從來沒測過的組合**。 清單與人看的 `INDEX.md` 寫在**專案根的 `releases/`**,不是 plugin 目錄 ——ISEP 是 marketplace 裝的,`claude plugin update` 會把那個目錄整個換掉, 而清單的用處全部發生在「以後要退版的那一天」。 **沒有新增 PreToolUse 閘是刻意的**:這一層唯一能機械辨認的「退版動作」形狀很難跟 「讀取/談論」分開,而誤攔在本 repo 是第一級缺陷。所以閘做成**工具本身就是唯一的門** (同 `scripts/pr-verdict` 的形狀),不去猜指令字串。 ## `#85` — 估多久/花多久/差多少/為什麼差 新增 `scripts/milestone-account`(codes/list/audit/close/report) + `hooks/milestone-account-guard.sh`(PreToolUse/Bash,+1 支、+1 條註冊)。 - **三個數字自己算**,不用手填:取自 Gitea 的 `created_at`/`due_on`/`closed_at`。 - **差超過 ±25%(超時或提早都算)就要挑一個代號,挑不出來不准結案。** 提早太多不是好消息,是當初估太鬆——所以兩個方向同一條線。 - **代號是七個的封閉集合**(票上那張表,一個不多一個不少): `idle` 磨洋工/`sidetrack` 分心跳線/`undispatched` 忘了派工/`cherry-pick` 偏科/ `waiting` 等答案/`scope-creep` 範圍變大/`misestimate` 純粹估錯。 票上寫死的理由:**能統計的前提是分類有限。** - **代號要有 Gitea 時間軸撐得住**:`audit` 先從時間戳/指派欄位/標籤/票的歸屬 算出哪幾個訊號成立,`close` **只接受訊號成立的那幾個**;六個都不成立時唯一合法的 就是 `misestimate`(=票上那句「以上都沒有,但還是差很多」)。 ⇒ **不採信任何人的自述**,這是票上寫死的。判準**一句自然語言都不讀**。 - 閘擋的是「直接 `curl -X PATCH … state=closed` 但還沒記帳」。 純讀取/建里程碑/改期限/`echo` 那段指令/`cat` 這支閘/heredoc 內文/ 走正門 `milestone-account close`——**全部放行**。 真要手動關 ⇒ 指令裡加 `milestone-account-ok`(留痕)。 - 帳本同樣寫在**專案根的 `system-dev/estimates/`**(理由同上:plugin 目錄會被換掉, 而這張票的全部價值就在「累積」)。 `milestone-account-guard` 跟既有的 `milestone-due-guard` 是同一條線的兩端: 那支管**開**里程碑要有真的期限(沒有期限就沒有「估多久」可言),這支管**關**的時候要留下帳。 --- ## 我跑過的(每一格都自己跑過,不是宣稱) 離線,不打 Gitea、不留測試票、不關任何真的 milestone、不建任何真的 release: ``` bash scripts/test-release-manifest.sh → 通過 21 條,失敗 0 條 bash scripts/test-milestone-account.sh → 通過 23 條,失敗 0 條 bash hooks/tests/milestone-account-guard.test.sh → 通過 22 條,失敗 0 條 ``` 三支都在 `CLAUDE_CODE_CHILD_SESSION` **清掉之後**重跑過一次(這台機器上它原本是 `1`)。 **真實 Gitea 唯讀重演**(只有 GET/`--dry-run`,一通寫入都沒送出): - `milestone-account list --org inkstone --overdue` 撈到的正是票上點名的那五個,而且每一個都算得出數字: ``` 🔴 inkstone/arcrun-rag#47 估 0.5天/已 3.5天/+592% 🔴 inkstone/Arcrun#46 估 0.5天/已 3.6天/+592% 🔴 inkstone/Arcrun#50 估 0.8天/已 1.8天/+131% 🔴 inkstone/Arcrun#51 估 0.6天/已 1.6天/+178% 🔴 inkstone/ISEP#43 估 4.6天/已 7.6天/+66% ``` - `milestone-account audit inkstone/ISEP#43` 從真的時間軸算出: 最長空白 2.8 天(佔整段 37%)/29 個動作在別的票上(37%)/5 張票整段沒有人被指派/ 開跑之後才補進來 9/15 張票 ⇒ 可以挑的代號 `idle / sidetrack / undispatched / cherry-pick / scope-creep`。 - `release-manifest freeze … --dry-run` 對 `inkstone/ISEP@v0.11.0` + `inkstone/arcrun-rag@1.4.60` 兩格都抓到真的 release;換成 `v99.0.0` 當場被擋下。 **既有測試沒被我弄壞**(同樣清掉 `CLAUDE_CODE_CHILD_SESSION` 跑): release-tag 8/8、ticket-api-bypass 24/24、ticket-where-seen 17/17、comment-carries-task 22/22、 baton-handback 10/10、main-and-prod-push 13/13、stage-before-prod 13/13、github-contact 14/14、 kbdb-api-wall 10/10、dispatch-format 33/33、sdd 8/8、search-is-not-proof 31/31、 factory-idle 33/33、mainline-idle 61/61、reply-identity 11/11、ask-user-question 14/14、 gitea-arm-check 16/16、pr-verdict 52/52、countdown 20/20、prod-write 37/37、 版本三處一致 ✅。 🔴 **一格我沒有交乾淨,明講**:`hooks/tests/main-and-prod-push-guard-cross-repo.test.sh` 是 `通過 14/失敗 5`。**這是本來就紅的**——我把改動 `git stash` 掉、在乾淨的 `main` 上重跑, 一模一樣是 14/5。不是這個 PR 造成的,也不在這兩張票的範圍內。 ## 盤點數字 **在我自己的樹上實數出來的**,不是拿上一版加減推 (`system-dev/wiki/mistakes.md`:那個數字是 leo 的驗收介面,多報就是假綠): ``` ls hooks/*.sh | wc -l → 53 → 54 grep -c '"command":' hooks/hooks.json → 68 → 69 ls -p scripts | grep -v / | wc -l → 39 ``` `hooks-inventory.md` 的落差偵測兩組 `comm` 都是空的(沒有閘漏列人話、沒有列了卻不存在的閘)。 順手修掉兩個真的漂移(不是改風格): - `docs/hooks-inventory.md` 的「一句話結論」**同一行被貼了兩次**,而標頭寫 52、內文寫 53 ——同一頁裡三個數字互相矛盾,正是那一頁自己警告過的病。 - 描述欄的「38 支腳本」是把 `kbdb-live-exam/`/`lib/`/`patches/` 三個**目錄**也數進去了; 用那一頁寫死的指令(只數檔案)實數是 **39**。 ## 我判斷的、寫下來讓你打回 - **`#85` 的訊號門檻是第一版,會需要調。** 上面 `ISEP#43` 那次七個訊號命中了五個, 偏寬。但這正是票上要的「把測得到變成可以統計、**可以迭代**」—— 資料累積起來之後調門檻,而不是現在憑感覺先調。 🔴 **調法只有一條**:改 `audit` 的偵測器,不是在 `close` 開後門讓人繞過去。 - **`#84` 沒有配一支 PreToolUse 閘**,理由寫在上面(誤攔風險 > 漏擋代價)。 如果你認為需要,那是另一張票。 - **兩份資料(清單、帳本)都落在專案根而不是 plugin 目錄**。這是我自己裁的, 理由是 `plugin update` 會把 plugin 目錄整個換掉。若你要它們住別的地方, 兩支工具都吃 `RELEASE_MANIFEST_DIR`/`MILESTONE_ACCOUNT_DIR` 環境變數,改一行就好。
claude-code added 1 commit 2026-08-28 00:56:17 +00:00
+ 每次結案都留下估多久/花多久/差多少(inkstone/ISEP#85)

#84:scripts/release-manifest
  freeze 前每一格都真的去 Gitea 抓過(抓不到不給凍結);凍結後不准再加東西;
  rollback 一定吐出整份清單的每一格,--only 指名單一 repo 會被擋下
  ——那正是票上那個病:剩下的還停在新版 ⇒ 一組從來沒測過的組合。
  清單與 INDEX.md 寫在專案根的 releases/(不是 plugin 目錄,plugin update 會清掉)。

#85:scripts/milestone-account + hooks/milestone-account-guard.sh
  三個數字自己算(取自 Gitea 的 created_at/due_on/closed_at,不用手填);
  差超過 ±25%(超時或提早都算)就要從七個固定代號裡挑一個,挑不出來不准結案;
  代號要有 Gitea 時間軸撐得住——訊號不成立的代號直接拒收(不採信自述)。
  閘擋的是「直接 curl PATCH state=closed 但還沒記帳」,正門走 milestone-account close。

盤點數字在本樹實數(ls hooks/*.sh|grep -c '"command":'):
  hooks 53→54 支、註冊 68→69 條、scripts 39 支(描述欄舊的 38 把三個目錄也數進去了)。
順手修掉 docs/hooks-inventory.md「一句話結論」被貼兩次、且標頭 52/內文 53 互相矛盾。

測試(全部離線,不打 Gitea、不留測試票/不關真的 milestone):
  scripts/test-release-manifest.sh            21/21
  scripts/test-milestone-account.sh           23/23
  hooks/tests/milestone-account-guard.test.sh 22/22

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ZBu4Sa1cGntKFRBYNZ6xs
claude-code closed this pull request 2026-08-28 01:04:57 +00:00

Pull request closed

Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: inkstone/ISEP#103