身為看頂層票的人,我要下游做完時頂層跟著關,我才不會看到一堆其實早就做完的票 #92

Closed
opened 2026-08-27 14:34:23 +00:00 by claude-code · 3 comments
Member

問題

一件事從別的地方進來(leo 講的、外面回報的、做到一半發現的),現在沒有一條固定的路去處理它。

結果是三種掉法:

① 開在頂層的票,下游做完了卻沒人回來關
SOP 自己的違規對照表就列著這一條:「下游 repo 完工但頂層票一直未關」。頂層票會永遠掛著,而 leo 是看頂層的。

② 兩邊沒有互相指
頂層票寫了「轉去某個 repo」,但那邊的票沒有指回來。從下游那張票看不出它從哪來,脈絡就斷了。

③ 這件事服務哪個使用者旅程,沒有記錄
所以後面要把相關的票聚成一包時,只能靠人重新讀一遍每張票在講什麼。

目標

讓「新事情進來」變成一條固定的路,走完會留下四樣東西:

  • 這件事屬於哪個 repo
  • 它要不要進現在的主線(判斷基準是主線的目標宣告,不是拿它跟一段散文比對)
  • 它服務哪條使用者旅程(對不上就不貼,不硬湊)
  • 兩邊互相指得到,而且下游關掉時頂層跟著關

驗收條件

  1. 從頂層開一張票、轉到下游 → 兩張票要互相看得到對方
  2. 把下游那張關掉 → 頂層那張要跟著被處理,不能默默留著
  3. 撈一次「已經沒有 open 下游票、但自己還開著的頂層票」→ 要撈得出來(現在撈不出來)
  4. 拿現有的頂層票跑一次 → 要能指出哪幾張是這種情況

deliverable 類型

code(→ PR)


細節

這條在 SOP 裡的位置:S1(分診,SOP 稱之為「萬用指令」——所有新事項不分來源都走這條路)。

已經有的、不要重造

  • ticket where 戳記 + ticket-api-bypass-guard.sh:已經強制「新增任何 Gitea 東西之前要先搜」,S1 的第一步(查票防重複)已經有了
  • comment-carries-task-guard.sh:已經在管「留言裡藏著沒做完的事要長成子票」,S1 的一個出口已經有了
  • Gitea 原生 issue dependency:跨 repo 關聯的載體已經有了,且 v0.6.0 §8 E4 標記為「平台原生,已驗證可用」

所以本票真正缺的只有三格:journey 標籤、雙向連結的強制、完工回寫。第三格是最痛的。

不要做的:不要為每種來源另設流程(SOP 明講「來源不同,分診流程相同」)。也不要做成 Gitea Actions/webhook 自動觸發——CLAUDE.md 的 flag 紅線與 issue-handle skill 的「有事才讀,禁止自動輪詢」都擋著,Gitea 也不放寬。

與 ISEP#83 的分工:#83 是「每天把舊票撈出來排序領取」(消化面),本票是「新事情進來時怎麼安置」(入口面)。#83 的聚類要靠本票貼的 journey 標籤,所以本票是它的上游。


🔎 為什麼另開一張票而不是貼進既有的(開票時聲明):#83 是消化面(每天撈舊票排序領取),本票是入口面(新事情進來怎麼安置),且 #83 的聚類要靠本票貼的 journey 標籤,是它的上游。comment-carries-task-guard 只管留言藏任務那一個出口,不管完工回寫。
當時搜尋:分診 頂層票 回寫 雙向連結 journey → 命中 45 張。

## 問題 一件事從別的地方進來(leo 講的、外面回報的、做到一半發現的),現在**沒有一條固定的路**去處理它。 結果是三種掉法: **① 開在頂層的票,下游做完了卻沒人回來關** SOP 自己的違規對照表就列著這一條:「下游 repo 完工但頂層票一直未關」。頂層票會永遠掛著,而 leo 是看頂層的。 **② 兩邊沒有互相指** 頂層票寫了「轉去某個 repo」,但那邊的票沒有指回來。從下游那張票看不出它從哪來,脈絡就斷了。 **③ 這件事服務哪個使用者旅程,沒有記錄** 所以後面要把相關的票聚成一包時,只能靠人重新讀一遍每張票在講什麼。 ## 目標 讓「新事情進來」變成一條固定的路,走完會留下四樣東西: - 這件事屬於哪個 repo - 它要不要進現在的主線(判斷基準是主線的目標宣告,不是拿它跟一段散文比對) - 它服務哪條使用者旅程(對不上就不貼,不硬湊) - **兩邊互相指得到,而且下游關掉時頂層跟著關** ## 驗收條件 1. 從頂層開一張票、轉到下游 → **兩張票要互相看得到對方** 2. 把下游那張關掉 → **頂層那張要跟著被處理**,不能默默留著 3. 撈一次「已經沒有 open 下游票、但自己還開著的頂層票」→ **要撈得出來**(現在撈不出來) 4. 拿現有的頂層票跑一次 → 要能指出哪幾張是這種情況 ## deliverable 類型 code(→ PR) --- <details><summary>細節</summary> **這條在 SOP 裡的位置**:S1(分診,SOP 稱之為「萬用指令」——所有新事項不分來源都走這條路)。 **已經有的、不要重造**: - `ticket where` 戳記 + `ticket-api-bypass-guard.sh`:已經強制「新增任何 Gitea 東西之前要先搜」,S1 的第一步(查票防重複)**已經有了** - `comment-carries-task-guard.sh`:已經在管「留言裡藏著沒做完的事要長成子票」,S1 的一個出口**已經有了** - Gitea 原生 issue dependency:跨 repo 關聯的載體**已經有了**,且 v0.6.0 §8 E4 標記為「平台原生,已驗證可用」 **所以本票真正缺的只有三格**:journey 標籤、雙向連結的強制、**完工回寫**。第三格是最痛的。 **不要做的**:不要為每種來源另設流程(SOP 明講「來源不同,分診流程相同」)。也不要做成 Gitea Actions/webhook 自動觸發——`CLAUDE.md` 的 flag 紅線與 `issue-handle` skill 的「有事才讀,禁止自動輪詢」都擋著,Gitea 也不放寬。 **與 ISEP#83 的分工**:#83 是「每天把舊票撈出來排序領取」(消化面),本票是「新事情進來時怎麼安置」(入口面)。#83 的聚類要靠本票貼的 journey 標籤,所以本票是它的上游。 </details> --- > 🔎 **為什麼另開一張票而不是貼進既有的**(開票時聲明):#83 是消化面(每天撈舊票排序領取),本票是入口面(新事情進來怎麼安置),且 #83 的聚類要靠本票貼的 journey 標籤,是它的上游。comment-carries-task-guard 只管留言藏任務那一個出口,不管完工回寫。 > 當時搜尋:`分診 頂層票 回寫 雙向連結 journey` → 命中 45 張。
claude-code added this to the SOP 變成閘 milestone 2026-08-27 14:34:31 +00:00
claude-code added the
p
high
s
todo
type
governance
labels 2026-08-27 14:34:32 +00:00
Author
Member

【身份】subagent/inkstone/ISEP/feat/handoff-writeback-loose

PR:#98(可合併,沒撞到今天其他線)

四條驗收條件,逐條對

① 從頂層開一張票、轉到下游 → 兩張票要互相看得到對方
ticket subtask(新別名 ticket handoff)現在是一個動作三件事:掛 Gitea 原生相依 + 子票內文寫 Parent:
在頂層票的時間軸貼一則指回下游的留言。原本只有前兩件——相依邊只長在側欄,
頂層票的時間軸上什麼都沒有,跨 repo 時尤其看不出來。

② 把下游那張關掉 → 頂層那張要跟著被處理
ticket close 關完子票立刻問 /blocks(誰在等我),對每張還開著的頂層票貼回寫留言;
下游全關的那一張再指派回總管+改 s/review
🔴 刻意不自動關母票:關票要有交付物、要有人看過——默默關掉跟默默留著是同一個病的兩面。

③ 撈「已經沒有 open 下游票、但自己還開著的頂層票」
新動詞 ticket loose。它是 ② 的補網:關票的側門(直接 PATCH state=closed)是
ticket-api-bypass-guard.sh 刻意放行的,走側門漏掉的由這張網撈回來。不是輪詢,開場/收工跑一次。

④ 拿現有的頂層票跑一次 → 指出哪幾張是這種情況
實跑了(唯讀,沒動任何票):245 張 open 票裡 17 張有下游相依,其中 2 張是這種情況——

  • inkstone/arcrun-rag#136 s/review、指派給 claude-code正在被處理
    (這正是回寫會把票放到的那個狀態,所以它出現在表上是對的)
  • inkstone/Arcrun#100 沒標籤、沒指派 ⇒ 就是票上講的那種「永遠掛著、沒人回來關」

沒有重造票上列的那三樣

ticket where 戳記+側門閘、comment-carries-task-guard、Gitea 原生 dependency ——
這一版整個長在它們上面,一樣都沒有重做。

scripts/test-ticket-handoff-writeback.sh 49 條全綠。全程離線:會打 API 的兩段
_writebackcmd_subtask)把 api() 換成錄音機,驗它到底打了哪些端點、送了什麼
——不打真實 Gitea、不開票、不關票、不留測試票。/blocks 的回應形狀是實查 inkstone/ISEP#75 拿到的,不是猜的。
回歸 A13 17/17、A4 24/24、A12 11/11 全綠。docs/TESTING.md 新增 A16。

判準全部是機械事實(相依邊在不在、state 是什麼),沒有一格在猜文字——
journey 走的是「要求那個標籤在 labels.yaml」,不是「猜哪些名字合法」。

🔴 一格沒有資料(機制驗過了,但還不能真的用)

labels.yamlj/刻意留空:旅程怎麼切、叫什麼名字是方向題(四題公式第 4 題),
不由工具或 subagent 代決;隨手造名字會讓同一條旅程長出三個拼法。
在有人加第一條旅程之前,--journey 只會擋、不會貼。
第一條旅程名加進 labels.yaml → 跑 gitea-labels-sync.sh 就能用。
(票上明講「對不上就不貼,不硬湊」,所以我沒有替它編一條。)

順帶回報兩件不屬於本票的事

  1. README.md 的盤點數字已經對不上(我沒有改它,避免跟今天其他線撞):
    實數 hooks/*.sh 52hooks.json 註冊 67 條、commands/ 7skills/ 2
    scripts/ 頂層 35 個檔(含本 PR 新增的 1 支);README 寫的是 48/59/7/2/23。
  2. github-contact-guard.sh 在 subagent 環境會誤攔 Gitea 的 push:它用 tool input 的 cwd
    解 remote 名稱,而 agent thread 的 cwd 每次被重設回 session 根目錄(那個 repo 的 origin 指向 GitHub)
    ⇒ 在別的 clone 裡 cd … && git push -u origin <branch> 被判成推 GitHub。
    我沒有碰 .github-armed(那是 leo 的保險),改用名字誠實的 gitea remote 推就正確放行了。

版本號待總管定版——本 PR 沒有動 plugin.json

【身份】subagent/inkstone/ISEP/feat/handoff-writeback-loose **PR:https://git.uncle6.me/inkstone/ISEP/pulls/98**(可合併,沒撞到今天其他線) ## 四條驗收條件,逐條對 **① 從頂層開一張票、轉到下游 → 兩張票要互相看得到對方** `ticket subtask`(新別名 `ticket handoff`)現在是一個動作三件事:掛 Gitea 原生相依 + 子票內文寫 `Parent:` + **在頂層票的時間軸貼一則指回下游的留言**。原本只有前兩件——相依邊只長在側欄, 頂層票的時間軸上什麼都沒有,跨 repo 時尤其看不出來。 **② 把下游那張關掉 → 頂層那張要跟著被處理** `ticket close` 關完子票立刻問 `/blocks`(誰在等我),對每張還開著的頂層票貼回寫留言; **下游全關的那一張再指派回總管+改 `s/review`**。 🔴 **刻意不自動關母票**:關票要有交付物、要有人看過——默默關掉跟默默留著是同一個病的兩面。 **③ 撈「已經沒有 open 下游票、但自己還開著的頂層票」** 新動詞 `ticket loose`。它是 ② 的補網:關票的側門(直接 `PATCH state=closed`)是 `ticket-api-bypass-guard.sh` 刻意放行的,走側門漏掉的由這張網撈回來。不是輪詢,開場/收工跑一次。 **④ 拿現有的頂層票跑一次 → 指出哪幾張是這種情況** 實跑了(唯讀,沒動任何票):**245 張 open 票裡 17 張有下游相依,其中 2 張是這種情況**—— - `inkstone/arcrun-rag#136` `s/review`、指派給 `claude-code` ⇒ **正在被處理** (這正是回寫會把票放到的那個狀態,所以它出現在表上是對的) - `inkstone/Arcrun#100` **沒標籤、沒指派** ⇒ 就是票上講的那種「永遠掛著、沒人回來關」 ## 沒有重造票上列的那三樣 `ticket where` 戳記+側門閘、`comment-carries-task-guard`、Gitea 原生 dependency —— 這一版整個長在它們上面,一樣都沒有重做。 ## 驗 `scripts/test-ticket-handoff-writeback.sh` **49 條全綠**。全程離線:會打 API 的兩段 (`_writeback`/`cmd_subtask`)把 `api()` 換成錄音機,驗它到底打了哪些端點、送了什麼 ——不打真實 Gitea、不開票、不關票、不留測試票。`/blocks` 的回應形狀是實查 `inkstone/ISEP#75` 拿到的,不是猜的。 回歸 A13 17/17、A4 24/24、A12 11/11 全綠。`docs/TESTING.md` 新增 A16。 判準全部是機械事實(相依邊在不在、`state` 是什麼),沒有一格在猜文字—— journey 走的是「**要求那個標籤在 `labels.yaml` 裡**」,不是「猜哪些名字合法」。 ## 🔴 一格沒有資料(機制驗過了,但還不能真的用) `labels.yaml` 的 `j/` 段**刻意留空**:旅程怎麼切、叫什麼名字是方向題(四題公式第 4 題), 不由工具或 subagent 代決;隨手造名字會讓同一條旅程長出三個拼法。 ⇒ **在有人加第一條旅程之前,`--journey` 只會擋、不會貼。** 第一條旅程名加進 `labels.yaml` → 跑 `gitea-labels-sync.sh` 就能用。 (票上明講「對不上就不貼,不硬湊」,所以我沒有替它編一條。) ## 順帶回報兩件不屬於本票的事 1. `README.md` 的盤點數字已經對不上(**我沒有改它**,避免跟今天其他線撞): 實數 `hooks/*.sh` **52**、`hooks.json` 註冊 **67** 條、`commands/` **7**、`skills/` **2**、 `scripts/` 頂層 **35** 個檔(含本 PR 新增的 1 支);README 寫的是 48/59/7/2/23。 2. `github-contact-guard.sh` 在 subagent 環境會**誤攔 Gitea 的 push**:它用 tool input 的 `cwd` 解 remote 名稱,而 agent thread 的 cwd 每次被重設回 session 根目錄(那個 repo 的 `origin` 指向 GitHub) ⇒ 在別的 clone 裡 `cd … && git push -u origin <branch>` 被判成推 GitHub。 **我沒有碰 `.github-armed`**(那是 leo 的保險),改用名字誠實的 `gitea` remote 推就正確放行了。 **版本號待總管定版**——本 PR 沒有動 `plugin.json`。
Author
Member

🏃 棒子交回 → claude-code

下一步:review 並合併 #98,然後定版(本 PR 沒動 plugin.json)。合併後這張票就可以關;j/ 旅程名要不要加是另一個決定。

證據:scripts/test-ticket-handoff-writeback.sh 49/49;實跑 ticket loose 撈出 2 張(arcrun-rag#136、Arcrun#100)

🏃 **棒子交回** → `claude-code` **下一步**:review 並合併 https://git.uncle6.me/inkstone/ISEP/pulls/98,然後定版(本 PR 沒動 plugin.json)。合併後這張票就可以關;j/ 旅程名要不要加是另一個決定。 **證據**:scripts/test-ticket-handoff-writeback.sh 49/49;實跑 ticket loose 撈出 2 張(arcrun-rag#136、Arcrun#100)
claude-code self-assigned this 2026-08-28 00:34:35 +00:00
claude-code added
s
review
and removed
s
todo
labels 2026-08-28 00:34:36 +00:00
Author
Member

【身份】subagent/inkstone/ISEP/feat/handoff-writeback-loose

已併回 main、解完衝突、重推。PR #98 現在 mergeable=True(head 07cb5e4,base 87678a8)。

衝突只有一個:docs/TESTING.md,兩條線各自加了一節、都叫 A16

兩邊內容都留。我這一節改成 A19(main 已經用掉 A16/A17/A18),
「目前狀態」表那一列跟著搬到 A18 後面。

🔴 main 側原本就有的 A11/A12/A14/A15 重號我沒有動——那是它兩條線各自編的,
不是這次造成的,動它會把 diff 炸開。但那份編號已經不唯一了
下一個要加 A-小節的人會再撞一次。要不要整理由總管決定。

其餘三個預期會撞的檔(hooks/hooks.json.claude-plugin/plugin.jsondocs/hooks-inventory.md
本線一個字都沒改,自動合併拿到的就是 main 那份。
版本號沒動,維持 main 的 v0.12.0(推完之後 main 又出了 v0.13.0
只動 plugin.json,跟本線不衝突,Gitea 算出來仍是 mergeable)。

盤點數字:在合併後的樹上自己重數

hooks/*.sh 54 hooks.json 註冊 71 commands 7 skills 2 scripts 頂層 38
  • docs/hooks-inventory.md 寫的 54/71 是對的(沒動它)
  • README.md 寫的 48/59/23 三個都錯,已改成實數,
    並把「怎麼重數」的五行指令直接寫進 README——
    這種數字會漂是因為沒人知道它怎麼來的,只改數字下次還會漂

全部測試重跑(不只我那支):28 支全綠

✅ 23 支一次就綠(含 pr-verdict 52/52、mainline-idle 61/61、mainline-focus 24/24、
   isep-presence-beacon 14/14、gate-ok 17/17、unpushed-police 10/10 這些今天新進來的)
✅ 另外 5 支:main-and-prod-push 10/10、cross-repo 19/19、prod-write 37/37、
   stage-before-prod 16/16、gitea-arm-check 16/16
⏭️ ask-user-question-guard.live.test.sh 跳過(會真的叫 haiku、要花錢)

🔴 那 5 支我第一輪跑出紅的,是我自己的跑法錯,不是回歸。
它們要吃一個參數(bash hooks/tests/prod-write-guard.test.sh hooks/prod-write-guard.sh
TESTING.md A15 本來就這樣寫),我的批次迴圈沒帶參數。
我沒有直接回報「壞了」——先把 gitea/main 開一個 worktree 跑同樣五支,
拿到一模一樣的失敗數(18/19、9/7)確認「在 main 上也一樣」,才去看根因。

帶對參數之後五支全綠。

📌 順帶一提:這件事本身就是本票在治的病的同款——
我差一點把「我用錯方法」講成「別人的東西壞了」

工作目錄:/home/user/inkstoneco/ISEP-92(remote gitea 指向 Gitea,push 正常,沒有再撞閘)

【身份】subagent/inkstone/ISEP/feat/handoff-writeback-loose **已併回 main、解完衝突、重推。`PR #98` 現在 `mergeable=True`**(head `07cb5e4`,base `87678a8`)。 ## 衝突只有一個:`docs/TESTING.md`,兩條線各自加了一節、**都叫 A16** 兩邊內容都留。**我這一節改成 A19**(main 已經用掉 A16/A17/A18), 「目前狀態」表那一列跟著搬到 A18 後面。 🔴 **main 側原本就有的 A11/A12/A14/A15 重號我沒有動**——那是它兩條線各自編的, 不是這次造成的,動它會把 diff 炸開。**但那份編號已經不唯一了**, 下一個要加 A-小節的人會再撞一次。要不要整理由總管決定。 其餘三個預期會撞的檔(`hooks/hooks.json`/`.claude-plugin/plugin.json`/`docs/hooks-inventory.md`) **本線一個字都沒改**,自動合併拿到的就是 main 那份。 **版本號沒動**,維持 main 的 `v0.12.0`(推完之後 main 又出了 `v0.13.0`, 只動 `plugin.json`,跟本線不衝突,Gitea 算出來仍是 mergeable)。 ## 盤點數字:在合併後的樹上自己重數 ``` hooks/*.sh 54 hooks.json 註冊 71 commands 7 skills 2 scripts 頂層 38 ``` - `docs/hooks-inventory.md` 寫的 **54/71 是對的**(沒動它) - `README.md` 寫的 **48/59/23 三個都錯**,已改成實數, 並把「怎麼重數」的五行指令直接寫進 README—— **這種數字會漂是因為沒人知道它怎麼來的**,只改數字下次還會漂 ## 全部測試重跑(不只我那支):**28 支全綠** ``` ✅ 23 支一次就綠(含 pr-verdict 52/52、mainline-idle 61/61、mainline-focus 24/24、 isep-presence-beacon 14/14、gate-ok 17/17、unpushed-police 10/10 這些今天新進來的) ✅ 另外 5 支:main-and-prod-push 10/10、cross-repo 19/19、prod-write 37/37、 stage-before-prod 16/16、gitea-arm-check 16/16 ⏭️ ask-user-question-guard.live.test.sh 跳過(會真的叫 haiku、要花錢) ``` 🔴 **那 5 支我第一輪跑出紅的,是我自己的跑法錯,不是回歸。** 它們要吃一個參數(`bash hooks/tests/prod-write-guard.test.sh hooks/prod-write-guard.sh`, `TESTING.md` A15 本來就這樣寫),我的批次迴圈沒帶參數。 **我沒有直接回報「壞了」——先把 `gitea/main` 開一個 worktree 跑同樣五支, 拿到一模一樣的失敗數(18/19、9/7)確認「在 main 上也一樣」,才去看根因。** 帶對參數之後五支全綠。 📌 順帶一提:這件事本身就是本票在治的病的同款—— **我差一點把「我用錯方法」講成「別人的東西壞了」**。 工作目錄:`/home/user/inkstoneco/ISEP-92`(remote `gitea` 指向 Gitea,push 正常,沒有再撞閘)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: inkstone/ISEP#92