#!/bin/bash # arcrun-guard.sh — 用戶專案的 arcrun PreToolUse guard(由 acr install-harness 裝進 .claude/hooks/) # # 對象:在「用 arcrun 開發」的專案裡工作的 CC。擋它走歪(退回自寫 Python / 不用 recipe / 未經同意暴露)。 # 與 arcrun repo 開發版 hook 完全不同(那個擋的是開發 arcrun 本身)。 # # 鐵則(user-cc-harness design §0.5):每次擋下/提醒都要給「具體怎麼做才對」的正路,不只說「不行」。 # # 退出碼:0=允許(可附 stderr 提醒);2=硬擋(stderr 回給 CC)。 # 分級(design §4):多數用「提醒不硬擋」(避免誤殺正常 python);硬擋只留給「未經同意暴露資料」。 set -o pipefail INPUT=$(cat) TOOL=$(echo "$INPUT" | jq -r '.tool_name // ""') CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""') remind() { # 提醒但放行(exit 0)。CC 看到 stderr,自己判斷是否真要繼續。 echo "💡 arcrun 提醒:$1" >&2 echo " 正路:$2" >&2 exit 0 } block() { echo "❌ arcrun guard 擋下:$1" >&2 echo " 正路:$2" >&2 exit 2 } # ── 硬擋:未經人類同意的暴露動作(明確越界,mindset §5)────────────── # 非互動環境下 CC 自己跑「部署對外 webhook / push recipe」= 替人類決定公開。 if echo "$CMD" | grep -qE "acr (push|recipe push)\b"; then if [ ! -t 0 ] && [ "${ARCRUN_HUMAN_CONFIRMED:-}" != "1" ]; then block "在非互動環境自動執行暴露動作(acr push / recipe push 會讓東西可被外部呼叫)" \ "把這動作交給人類在終端機執行,或先讓使用者明示同意。不要替使用者決定公開。" fi fi # ── 提醒(不硬擋):退回自寫 Python/Node 一次性自動化 ────────────────── # 「我先用 Python 測試」這類退回熟悉工具的傾向。python 不絕對錯(可能跑測試),故提醒不擋。 if echo "$CMD" | grep -qE "(^|[;&| ])(python3?|node)[ ]+[^ ]+\.(py|js|mjs|ts)\b"; then # 排除明顯的測試 / 既有工具呼叫(pytest / npm test / jest 等)降低誤判 if ! echo "$CMD" | grep -qE "(pytest|jest|vitest|npm (run )?test|mocha|\btest_)"; then remind "偵測到用 python/node 跑腳本。這專案用 arcrun,串服務/自動化不要自刻一次性腳本。" \ "先跑 \`acr parts\` 看有哪些零件,把需求寫成 workflow.yaml 用 \`acr run\`。若這確實不是自動化(例如跑測試/別的工具),忽略本提醒。" fi fi # ── 提醒(不硬擋):自寫打固定 API 的 script,而非 recipe ────────────── if echo "$CMD" | grep -qE "(curl|fetch|requests\.(get|post)|axios).*https?://"; then remind "偵測到自己打外部 API。arcrun 裡「打固定 endpoint」應寫成 recipe,不自刻 HTTP 呼叫。" \ "用 \`acr recipe push\` 把這個 API 包成 recipe,workflow 裡用 component 引用它。見 arcrun-mindset Skill。" fi exit 0