Files
ISEP/hooks/component-guard.sh
T
Leo c2638668e3 ISEP 0.1.0:環境設定收成一個 plugin,本機與雲端共用一份
leo 2026-08-20:「同一個 plugin 你用,薄殼也用,保證兩邊同步」
              「我要你幫雲端做薄殼,永遠都有問題,你要做的就是這組設定
                你自己可以 dogfooding」

搬進來:41 支 hook(51 條註冊)/7 支 command/2 支 skill/23 支腳本。
不搬 .env、wiki、docs——那些是知識不是環境。

51 條 hook 路徑全部從 $CLAUDE_PROJECT_DIR/.claude/hooks/ 改成 ${CLAUDE_PLUGIN_ROOT}/hooks/,
零漏網。那正是薄殼一直壞掉的根:雲端 cwd 不是真身,寫死路徑就斷。

尚未驗證:Claude Code 能不能從私有 Gitea repo 裝 marketplace(要憑證)。
下一步就是在本機實際裝一次,通了才動雲端 bootstrap.sh。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 11:41:46 +08:00

48 lines
2.8 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# component-guard.sh — 零件/service-binding 建立保險(D27/D282026-07-06
# 背景:AI 一再自建 domain 零件(km_wiki_card_parse)、錯用 service bindingdrainer 修 1042)。
# 靠 wiki 規則防不住(leo:「這規定說幾次都沒用」)→ 仿 D20 github-contact-guard 做硬閘:
# 把「建零件 / 加 service binding」當武器,平時機械擋(exit 2),要人類跑 scripts/component-arm.sh
# 顯式解保險(限時,且解時該過 docs/component-pr-review-standard.md)才放行。
# n8n 哲學(leo):現成零件 + 通用 code 零件 + cypher workflow 就夠了 → 預設根本不碰「建零件」那條路,就不會亂想。
# 誠實限制(同 github-guard mindset §7):AI 技術上可繞過;本 hook 價值=擋手滑 + 留審計軌跡 + 逼你回頭用積木,
# 絕不聲稱「不可能繞過」。最後一段靠 D27/D28 鐵律與自律。
INPUT=$(cat)
read_field() { printf '%s' "$INPUT" | python3 -c "import json,sys
try:
d=json.load(sys.stdin);ti=d.get('tool_input',{})
print(ti.get('$1',''))
except: print('')" 2>/dev/null; }
FP=$(read_field file_path)
[ -z "$FP" ] && exit 0
BODY="$(read_field content)$(read_field new_string)"
PROJ="${CLAUDE_PROJECT_DIR:-$(pwd)}"
ARM="$PROJ/.component-armed"
# 解保險窗口(限時,仿 github-arm):arm 檔內時間戳,30 分鐘內放行
if [ -f "$ARM" ]; then
ARMED=$(tr -dc '0-9' < "$ARM" 2>/dev/null); NOW=$(date +%s)
if [ -n "$ARMED" ] && [ $(( NOW - ARMED )) -lt 1800 ] 2>/dev/null; then exit 0; fi
fi
HIT=""
if printf '%s' "$FP" | grep -qiE 'wrangler\.(toml|jsonc?)$' && printf '%s' "$BODY" | grep -qE '\[\[services\]\]|(^|[^_a-zA-Z])services[[:space:]]*='; then
HIT="service binding[[services]])— D28 禁令:跨-worker 編排走 cypher binding,不走 service binding"
elif printf '%s' "$FP" | grep -qE 'registry/components/[^/]+/(component\.contract\.ya?ml|main\.(go|ts|mjs))$'; then
HIT="建/改命名零件(registry/components/…)— D27:一次性邏輯用通用 code 零件,別鑄 domain 零件"
fi
[ -z "$HIT" ] && exit 0
{
echo "❌ BLOCKED by component-guard$HIT"
echo ""
echo "預設就用「我給你的積木」:現有零件 + 通用 code 零件(inline JS + cypher workflowcypher binding 串多 worker/零件)。"
echo "這些對絕大多數需求已足夠。碰到這道閘,先回頭問:現成積木真的拼不出來嗎?(多半可以)"
echo "真的需要新零件 / service binding(罕見)→ 要能過 docs/component-pr-review-standard.md,且人類顯式跑 scripts/component-arm.sh 解保險。"
} >&2
LOG="$PROJ/system-dev/docs/3-specs/autonomy-dispatch/component-guard-log.md"
printf '| %s | 擋(%s) | `%s` |\n' "$(date '+%F %T')" "${HIT%%—*}" "$(printf '%s' "$FP" | head -c 120)" >> "$LOG" 2>/dev/null
exit 2