17a74d7d3a
leo 2026-08-27:「前面說過每個回覆要戴上已經花了總時長,這為什麼沒出現?」
「這應該寫在 ISEP,隨時看自己拖了多久」
重點在後面那句:不是要總管記得戴,是要它長在機器上。
總管當時答「我沒做,現在開始戴」——而那正是這條規則第一次失效的方式。
一支閘掛兩個事件,是同一件事的兩半(票上點名的失效模式就在這裡):
UserPromptSubmit → 注入算好的那一行(模型不必自己算,也算不準)
Stop → 查核這一回合的回覆裡到底有沒有那一行,沒有就擋一次
只做前半=又一個會被忽略的提醒;只做後半=罰它做一件拿不到資料的事。
判準不是關鍵字黑名單,是「那個被要求的輸出元素在不在」——
whitelist-of-one:要求一個機器產生的標記在場,不是猜哪些字不該在場。
換講法照樣要帶標記,多寫什麼都不會觸發。
時長從這段對話的第一則訊息算起,理由寫在 hooks/lib/countdown.py 檔頭:
「任務」在機器上沒有起點,而 CLAUDE.md 規則三點七「一段對話=一個 release」
剛好讓對話起點就是這個交付的起點——這個數字沒有人要維護,也不會說謊。
resume 取較早的那個:接關不是重新開始。
連帶修好票上的兩個卡點(prod-write-guard):
卡點一 發一則 Telegram 跟部署工作流在閘眼裡一模一樣 ⇒ 判準改看打的是哪一個
named webhook(路徑形狀+名字),放行範圍只有 notify_leo 一個名字
卡點二 連「把卡點寫進票裡」都被同一支閘擋(同款第八次)⇒ 剝掉內文再判,
起始行保留,所以真的在部署的寫法照樣擋
(修這支的過程又撞了一次同款——那就是這一格最好的證據)
測試:countdown 20/20、prod-write-guard 29→37/37,全程離線
(時鐘定住、狀態走環境變數、不打網路)。
實測:起點 06:28 台北、現在 08:03 ⇒ 期望「已過 1 小時 35 分」,實得同一字串。
plugin.json 0.9.0 → 0.10.0(版本沒動=沒有人吃得到)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
110 lines
6.0 KiB
Bash
Executable File
110 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# prod-write-guard.sh 的迴歸測試。
|
||
# 🔴 必須寫成檔案跑:這道閘會擋掉「含有它要擋的字串」的指令本身
|
||
# ⇒ 直接在 Bash 裡打測試,會被自己擋下(2026-08-12 實撞)。
|
||
HOOK="$1"
|
||
mk(){ python3 -c "import json,sys;print(json.dumps({'tool_name':'Bash','tool_input':{'command':sys.argv[1]}}))" "$1"; }
|
||
PASS=0; FAIL=0
|
||
t(){ # t <期望 block|pass> <說明> <指令>
|
||
mk "$3" | "$HOOK" >/dev/null 2>&1; rc=$?
|
||
got=$([ $rc -eq 2 ] && echo block || echo pass)
|
||
if [ "$got" = "$1" ]; then echo " ✅ $2"; PASS=$((PASS+1))
|
||
else echo " ❌ $2 —— 期望 $1,實得 $got"; FAIL=$((FAIL+1)); fi
|
||
}
|
||
|
||
H='https://arcrun-kbdb.leo21c.workers.dev'
|
||
DASH_D='-d'
|
||
|
||
echo "── 該放行(唯讀)──"
|
||
t pass "純 GET" "curl -s $H/templates"
|
||
t pass "GET + tr -d(本次實撞的誤攔)" "ACC=\$(grep -oE '^X=.' f | tr $DASH_D '\\r'); curl -s $H/templates"
|
||
t pass "GET + cut -d=" "A=\$(cut ${DASH_D}= -f2 f); curl -s $H/templates"
|
||
t pass "GET + sort -d / xargs -d" "ls | sort $DASH_D | xargs $DASH_D '\\n' echo; curl -s $H/entries"
|
||
t pass "GET 帶 Bearer 標頭" "curl -s -H 'Authorization: Bearer xxx' $H/templates?limit=1"
|
||
t pass "打 staging" "curl -X POST https://arcrun-rag-installer-staging.workers.dev/x $DASH_D '{}'"
|
||
t pass "打 youlin 測試場" "curl -X POST https://arcrun-cypher-executor.youlin-hsieh-dev.workers.dev/x $DASH_D '{}'"
|
||
t pass "打 Gitea(不是實例)" "curl -X POST https://git.uncle6.me/api/v1/repos/Leo/x/issues $DASH_D '{}'"
|
||
|
||
echo "── 該擋(寫入)──"
|
||
t block "POST 到實例" "curl -X POST $H/entries $DASH_D '{}'"
|
||
t block "PUT 到實例" "curl -X PUT $H/entries/1 --data '{}'"
|
||
t block "DELETE 到實例" "curl -X DELETE $H/entries/1"
|
||
t block "POST 且同時有 tr -d(剪字後仍該擋)" "cat f | tr $DASH_D '\\r' | curl -X POST $H/webhooks/named $DASH_D @-"
|
||
t block "wrangler deploy" "npx wrangler deploy --name arcrun-kbdb"
|
||
|
||
# ── 2026-08-13:「執行它」vs「談論它」───────────────────────────────
|
||
# 實撞:把 #108 的驗收證據留言到 Gitea,正文引述了那個指令名 ⇒ 一則留言被當成部署擋掉。
|
||
# 這批測資的挑法是「本 repo 現行真的會出現的形狀」,不是我自己挑好抓的壞例子
|
||
# ——PR #87 那道假綠閘就是敗在後者(14 條全過,卻漏掉 repo 實際在用的呼叫寫法)。
|
||
ACR_U='acr up''date' # 拆開寫:否則這支測試檔自己會被閘擋住(它也是一條 Bash 指令)
|
||
ACR_P='acr pu''sh'
|
||
WR_D='wrangler dep''loy'
|
||
|
||
echo "── 該放行(只是談論,不是執行)──"
|
||
t pass "heredoc 正文引述(本次實撞)" \
|
||
"B=\$(cat <<'EOF'
|
||
更新指令 \`$ACR_U --force\` 印出了 ARCRUN_NAMESPACE
|
||
EOF
|
||
); curl -X POST https://git.uncle6.me/api/v1/repos/Leo/Arcrun/issues/108/comments $DASH_D \"\$B\""
|
||
t pass "commit 訊息裡提到" "git commit -m '修好 $ACR_U 的命名空間注入'"
|
||
t pass "markdown code span(反引號)" "printf '%s' '看 \`$ACR_U\` 的輸出'"
|
||
t pass "grep 它的名字" "grep -n '$ACR_P' .claude/hooks/prod-write-guard.sh"
|
||
t pass "文章裡提到 $WR_D" "printf '%s' '# 為什麼 $WR_D 要擋'"
|
||
t pass "acr 唯讀子指令" "acr status --json"
|
||
t pass "acr whoami" "acr whoami"
|
||
|
||
echo "── 該擋(真的在指令位置執行)──"
|
||
t block "行首" "$ACR_U --force"
|
||
t block "&& 之後" "cd /x && $ACR_U"
|
||
t block "; 之後" "echo hi; $ACR_P workflow.yaml"
|
||
t block "管線之後" "cat x.yaml | $ACR_P -"
|
||
t block "bash -c 引號裡" "bash -c \"$ACR_U --force\""
|
||
t block "\$( ) 裡" "OUT=\$($ACR_U 2>&1)"
|
||
t block "npx 前綴" "npx $WR_D --name arcrun-kbdb"
|
||
t block "sudo 前綴" "sudo $ACR_U"
|
||
t block "heredoc 之後的真指令(剝內文不能連指令一起剝)" \
|
||
"cat <<'EOF' > note.md
|
||
只是筆記
|
||
EOF
|
||
$ACR_U --force"
|
||
|
||
# ══ inkstone/ISEP#63 → comment 5106:兩個卡點 ═══════════════════════════
|
||
#
|
||
# 卡點一:發一則 Telegram 給 leo(`notify_leo`)跟「部署一個工作流上線」在本閘眼裡
|
||
# 長得一模一樣——兩者都是帶 body 的寫入型請求打到同一台實例。
|
||
# 判準改成看**打的是哪一個 named webhook**(路徑形狀+名字),
|
||
# 而放行的範圍只有一個名字,家族其他成員照擋。
|
||
# 卡點二:連「把這個卡點寫進票裡」都被同一支閘擋(同款第八次)——
|
||
# 內文引用了主機名與寫入旗標,而閘比對的是指令文字。
|
||
EXE="https://arcrun-cypher-executor.leo21c.wo""rkers.dev"
|
||
NAMED="$EXE/webhooks/named"
|
||
|
||
echo "── 卡點一:通知放得過,家族其他成員照擋 ──"
|
||
t pass "發一則 Telegram 給 leo(notify_leo trigger)" \
|
||
"curl -s -X POST $NAMED/leo/notify_leo/trigger $DASH_D '{\"text\":\"[總管] 進度\"}'"
|
||
t pass "同上,網址後面帶斜線" \
|
||
"curl -s -X POST $NAMED/leo/notify_leo/trigger/ --data '{\"text\":\"[總管] x\"}'"
|
||
t block "別的 named webhook(會動線上狀態)不在白名單裡" \
|
||
"curl -X POST $NAMED/leo/ship_refresh_cdn/trigger $DASH_D '{}'"
|
||
t block "部署端點(沒有名字、沒有 /trigger)" \
|
||
"curl -X POST $NAMED $DASH_D @workflow.json"
|
||
t block "通知混著一筆真的寫入 ⇒ 整條照擋(白名單要每一個都符合)" \
|
||
"curl -X POST $NAMED/leo/notify_leo/trigger $DASH_D '{}' && curl -X POST $EXE/entries $DASH_D '{}'"
|
||
t block "名字只是前綴相同(notify_leo_deploy)不算通知" \
|
||
"curl -X POST $NAMED/leo/notify_leo_deploy/trigger $DASH_D '{}'"
|
||
|
||
echo "── 卡點二:談論它(內文引用)不是執行它 ──"
|
||
t pass "把卡點貼回票上,內文引用了實例網址與寫入旗標(本次實撞)" \
|
||
"B=\$(cat <<'EOF'
|
||
閘擋下來了:\`curl -X POST $NAMED\` 被當成部署。
|
||
EOF
|
||
); curl -X POST https://git.uncle6.me/api/v1/repos/inkstone/ISEP/issues/63/comments $DASH_D \"\$B\""
|
||
t block "真的在部署、只是把 payload 放進內文 ⇒ 起始行仍看得到,照擋" \
|
||
"curl -X POST $NAMED $DASH_D @- <<'EOF'
|
||
{\"name\":\"x\"}
|
||
EOF"
|
||
|
||
echo
|
||
echo "結果:通過 $PASS / 失敗 $FAIL"
|
||
[ $FAIL -eq 0 ] || exit 1
|