e474b4cb6f
leo 2026-08-27:「子票相依是 gitea 原有機制,改 tag 和指定也是,這些全部都要」 08-26 掉的那一次(arcrun-rag#136 comment 4267「等雲端那半出貨才驗得了」躺了 14 小時)三格全缺:沒有子票、tag 沒動、沒有指派給任何人。根因不是誰忘了, 是那件事沒有落在任何一個「撈一次就看得到」的欄位上。 實測(Gitea 1.26.4):子票還開著時關母票 → HTTP 412 "cannot close this issue or pull request because it still has open dependencies" ⇒ 相依是平台保證的硬擋,不是提醒。跨 repo 也成立(201)。 - scripts/ticket 新增三個動詞:subtask(長子票+掛相依)/ handback(指派+改 tag+寫下一步,一個動作)/mine(撈一次看棒子在誰手上) - hooks/comment-carries-task-guard.sh:留言帶未完成的未來式卻沒開子票 → 擋一次 - hooks/baton-handback-guard.sh:一條線收工,三格缺哪一格當場說出來(提醒不擋) - docs/governance §16:三個維度/粒度(傾向多開票)/既有票只從今天起適用/ 與 s/* 的關係/實測輸出 - 測試 20+10 全綠,用 fixture 跑不打網路、不在票池留測試票 📌 踩到並記進閘的檔頭:hook 裡比對中文一律用 python3 的 re,不要用 grep 的字元類 (等[^。]{0,20}出貨 在真實 hook 呼叫路徑下對「等雲端那半出貨」不匹配,閘靜默失效) 票:inkstone/ISEP#30(comment 4334/4335/4346/4347) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
56 lines
2.7 KiB
Bash
Executable File
56 lines
2.7 KiB
Bash
Executable File
#!/bin/bash
|
||
# 交棒警察的測試——三格(指派/tag/下一步)各自缺漏時要被抓到
|
||
# 判準:5 種該報、5 種不該報
|
||
# 用 fixture 跑,不打網路、不在票池留下任何一張測試票。
|
||
cd "$(dirname "$0")/.." || exit 1
|
||
H=hooks/baton-handback-guard.sh
|
||
PASS=0; FAIL=0
|
||
FX=$(mktemp -d); trap 'rm -rf "$FX"' EXIT
|
||
|
||
mkfx(){ # $1=state $2=assignees(csv) $3=labels(csv) $4=有沒有交棒留言(y/n)
|
||
python3 - "$FX" "$1" "$2" "$3" "$4" <<'PY'
|
||
import json, sys, os
|
||
d, state, asg, labs, baton = sys.argv[1:6]
|
||
issue = {"state": state,
|
||
"assignees": [{"login": a} for a in asg.split(",") if a],
|
||
"labels": [{"name": l} for l in labs.split(",") if l]}
|
||
comments = [{"body": "一般進度留言"}]
|
||
if baton == "y":
|
||
comments.append({"body": "🏃 **棒子交回** → `claude-code`\n\n**下一步**:去驗那一格"})
|
||
json.dump(issue, open(os.path.join(d, "issue.json"), "w"))
|
||
json.dump(comments, open(os.path.join(d, "comments.json"), "w"))
|
||
PY
|
||
}
|
||
|
||
run(){ # $1=want $2=說明 (fixture 已備好)
|
||
printf '%s' '{"tool_name":"Agent","tool_input":{"prompt":"【工單】inkstone/arcrun-rag#136\n做點事"}}' \
|
||
| BATON_GUARD_FIXTURE="$FX" bash "$H" >/dev/null 2>&1
|
||
got=$?
|
||
if [ "$got" = "$1" ]; then PASS=$((PASS+1)); printf ' ✅ '; else FAIL=$((FAIL+1)); printf ' ❌ '; fi
|
||
printf 'want=%s got=%s %s\n' "$1" "$got" "$2"
|
||
}
|
||
|
||
echo "── 該報:三格有缺 ──"
|
||
mkfx open "" "s/doing" n ; run 2 "三格全缺(=08-26 那次掉棒的狀態)"
|
||
mkfx open "" "s/review" y ; run 2 "缺指派:撈 assignee 撈不到它"
|
||
mkfx open "claude-code" "" y ; run 2 "缺 tag:看不出它卡在哪一段"
|
||
mkfx open "claude-code" "s/review" n ; run 2 "缺下一步:收下的人得重讀整串"
|
||
mkfx open "claude-code" "s/doing" y ; run 2 "tag 還停在 s/doing,但這條線收工了"
|
||
|
||
echo "── 不該報 ──"
|
||
mkfx open "claude-code" "s/review" y ; run 0 "三格都齊(交回總管等 review)"
|
||
mkfx open "Leo" "s/stage,Human" y ; run 0 "三格都齊(交給 leo 驗收)"
|
||
mkfx open "claude-code" "s/pending,p/high" y ; run 0 "卡在依賴上,但三格都齊"
|
||
mkfx closed "" "" n ; run 0 "票已關=棒子到終點,沒有下一手"
|
||
|
||
echo "── 派工單裡沒有【工單】那行 ⇒ 不歸這支管 ──"
|
||
printf '%s' '{"tool_name":"Agent","tool_input":{"prompt":"隨便做點事"}}' \
|
||
| BATON_GUARD_FIXTURE="$FX" bash "$H" >/dev/null 2>&1
|
||
got=$?
|
||
if [ "$got" = 0 ]; then PASS=$((PASS+1)); printf ' ✅ '; else FAIL=$((FAIL+1)); printf ' ❌ '; fi
|
||
printf 'want=0 got=%s 沒有票號的派工單\n' "$got"
|
||
|
||
echo
|
||
echo "$PASS/$((PASS+FAIL)) 通過"
|
||
[ "$FAIL" = 0 ]
|