#!/bin/bash # 討論串裡的任務要長成子票——這道閘的測試 # 判準:6 種該擋(留言裡真的藏著待辦)、10 種不該擋 # 🔴 「不該擋」比「該擋」重要:branch-holds.md 檔頭那句—— # 永遠在響的警報,等於訓練人忽略這個警報。 cd "$(dirname "$0")/.." || exit 1 H=hooks/comment-carries-task-guard.sh PASS=0; FAIL=0 SID=test-cctg-$$ run(){ # $1=want $2=cmd rm -f "/tmp/.comment-task-guard-warned-$SID" printf '%s' "{\"session_id\":\"$SID\",\"tool_name\":\"Bash\",\"tool_input\":{\"command\":$(python3 -c 'import json,sys;print(json.dumps(sys.argv[1]))' "$2")}}" \ | 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 %.62s\n' "$1" "$got" "$2" } echo "── 該擋:留言裡藏著一件還沒做完的事 ──" # 這一條就是 2026-08-26 真的掉了的那則的形狀 run 2 'req("POST", f"{API}/repos/inkstone/arcrun-rag/issues/136/comments", {"body":"Phase 1 的驗收在雲端那半出貨之前驗不了"})' run 2 'curl -X POST "$API/repos/inkstone/Arcrun/issues/12/comments" -d "{\"body\":\"要等 leo 開閘才能部署\"}"' run 2 'req("POST", f"{API}/repos/x/y/issues/3/comments", {"body":"[blocker] 收端還沒上線"})' run 2 'req("POST", f"{API}/repos/x/y/issues/3/comments", {"body":"這條路徑還沒測,先擱著"})' run 2 'req("POST", f"{API}/repos/x/y/issues/3/comments", {"body":"TODO: 補一條端到端測試"})' run 2 'req("POST", f"{API}/repos/x/y/issues/3/comments", {"body":"等雲端出貨之後要回頭重驗一次"})' echo "── 不該擋 ──" run 0 'curl -s "$API/repos/inkstone/ISEP/issues/30/comments"' # 純讀 run 0 'req("POST", f"{API}/repos/x/y/issues/3/comments", {"body":"已驗過,8/8 全綠"})' # 沒有待辦形狀 run 0 'scripts/ticket subtask inkstone/arcrun-rag#136 --title "身為x,我要y,我才z" -F /tmp/c.md' run 0 'scripts/ticket handback inkstone/arcrun-rag#136 --to claude-code --next "還沒驗的那格去驗"' run 0 'scripts/ticket mine' run 0 'scripts/ticket close inkstone/x#1 --deliverable https://example.invalid/pr/1' run 0 'grep -n "驗不了" hooks/comment-carries-task-guard.sh' # 只是讀這支閘 run 0 'echo "這則留言等雲端出貨才驗得了 —— no-subtask: 它已經有子票 #143 了"' # 逃生口 run 0 'curl -X POST "$API/repos/x/y/issues" -d "{\"title\":\"等出貨\"}"' # 開新票不歸這支管 run 0 'req("POST", f"{API}/repos/x/y/issues/3/comments", {"body":"🏃 **棒子交回** → claude-code\n\n**下一步**:等 #143"})' echo "── 交棒標記只認第一行(2026-08-27 dogfood 抓到的漏)──" # 真的交棒留言:🏃 在第一行 ⇒ 放行 run 0 'req("POST", f"{API}/repos/x/y/issues/3/comments", {"body":"🏃 **棒子交回** → claude-code\n\n**下一步**:等 #143"})' # 交件報告**引用**了一段有 🏃 的輸出,而報告本身帶著待辦 ⇒ 不准被豁免 TMPR=$(mktemp) printf '交件報告\n\n```\n🏃 在總管手上的棒子:2 根\n```\n\n還有一格等雲端那半出貨才驗得了\n' > "$TMPR" run 2 "scripts/ticket say inkstone/ISEP#30 -F $TMPR" rm -f "$TMPR" echo "── 同一 session 只擋一次(不鬼打牆)──" rm -f "/tmp/.comment-task-guard-warned-$SID" C='req("POST", f"{API}/repos/x/y/issues/3/comments", {"body":"驗不了"})' for want in 2 0; do printf '%s' "{\"session_id\":\"$SID\",\"tool_name\":\"Bash\",\"tool_input\":{\"command\":$(python3 -c 'import json,sys;print(json.dumps(sys.argv[1]))' "$C")}}" \ | bash "$H" >/dev/null 2>&1 got=$? if [ "$got" = "$want" ]; then PASS=$((PASS+1)); printf ' ✅ '; else FAIL=$((FAIL+1)); printf ' ❌ '; fi printf 'want=%s got=%s 第 %s 次同樣的指令\n' "$want" "$got" "$([ "$want" = 2 ] && echo 1 || echo 2)" done echo "── -F <檔>:內文在檔案裡也要看得到 ──" TMPF=$(mktemp); printf '這件事等雲端那半出貨才驗得了\n' > "$TMPF" run 2 "scripts/ticket say inkstone/arcrun-rag#136 -F $TMPF" printf '已驗完,全部綠燈\n' > "$TMPF" run 0 "scripts/ticket say inkstone/arcrun-rag#136 -F $TMPF" rm -f "$TMPF" "/tmp/.comment-task-guard-warned-$SID" echo echo "$PASS/$((PASS+FAIL)) 通過" [ "$FAIL" = 0 ]