c2638668e3
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>
82 lines
3.8 KiB
Bash
Executable File
82 lines
3.8 KiB
Bash
Executable File
#!/bin/sh
|
||
# not-my-branch-guard.sh — PreToolUse(Bash):**不准 commit 到別人正在施工的分支。**
|
||
#
|
||
# 🔴 為什麼是硬擋(2026-08-16,總管一小時內犯兩次):
|
||
# 第一次:把 branch-hold 的落帳 commit 打在 `feat/gitea-arm-per-issue` 上(agent 的分支)
|
||
# 第二次:把 `ticket decide` 的 commit 打在**同一條**分支上
|
||
# ——而且第一次之後,總管在回覆裡寫了「這正是共用工作區那條教訓咬到我自己」。
|
||
# **寫下教訓沒有讓他不再犯。** 一小時後同一個錯又來一次。
|
||
#
|
||
# 為什麼會犯:總管的 shell 與 agent 共用同一個工作區,**分支是誰上一次切的就是誰的**。
|
||
# `git commit` 不會問「你確定要打在這條上嗎」,它只是照做。
|
||
# 而 `git push gitea main` 在那種狀態下會回 **`Everything up-to-date`**
|
||
# ——**假成功**,因為本機 `main` 確實沒動過。真訊號是「本機 HEAD 與遠端對不上」。
|
||
#
|
||
# 判準:**當前分支出現在 `.claude/branch-holds.md` 裡** ⇒ 那是有人(agent)正在上面施工的
|
||
# 分支,或刻意保留的分支。兩種都不該由總管順手 commit 進去。
|
||
#
|
||
# 刻意不擋的:
|
||
# · 在 `main` 上 commit(那是總管的地盤,另有 main-and-prod-push-guard 管推送)
|
||
# · 不在 branch-holds 名單上的分支(總管自己開的工作分支)
|
||
# · 非 commit 的 git 動作(status/log/diff/checkout…)
|
||
#
|
||
# 真的要在那條分支上 commit(例如接手一條被放棄的分支):
|
||
# 把它從 `branch-holds.md` 移除(那本來就是「它不再是別人的」的正確表示法),
|
||
# 或 `NOT_MY_BRANCH_OK=1 git commit ...`(留痕,commit 說明寫理由)。
|
||
set -eu
|
||
|
||
[ "${NOT_MY_BRANCH_OK:-}" = "1" ] && exit 0
|
||
|
||
PAYLOAD=$(cat 2>/dev/null || echo '{}')
|
||
CMD=$(printf '%s' "$PAYLOAD" | python3 -c '
|
||
import sys, json
|
||
try: d = json.load(sys.stdin)
|
||
except Exception: sys.exit(0)
|
||
print((d.get("tool_input") or {}).get("command") or "")
|
||
' 2>/dev/null || true)
|
||
|
||
# 只看 commit(含 -m/-F/--amend)
|
||
case "$CMD" in
|
||
*"git commit"*) ;;
|
||
*) exit 0 ;;
|
||
esac
|
||
|
||
PROJ="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
||
HOLDS="$PROJ/.claude/branch-holds.md"
|
||
[ -f "$HOLDS" ] || exit 0
|
||
|
||
BR=$(git -C "$PROJ" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
|
||
[ -n "$BR" ] || exit 0
|
||
case "$BR" in main|master|HEAD) exit 0 ;; esac
|
||
|
||
# 分支名有沒有出現在 branch-holds 的條目裡(格式:- `分支名`(repo):理由)
|
||
grep -q "^- \`${BR}\`" "$HOLDS" 2>/dev/null || exit 0
|
||
|
||
REASON=$(grep -A1 "^- \`${BR}\`" "$HOLDS" | head -2 | tr '\n' ' ' | cut -c1-160)
|
||
|
||
cat >&2 <<EOF
|
||
🚫 這條分支不是你的——它列在 branch-holds 上(別人正在施工,或刻意保留)
|
||
|
||
當前分支:$BR
|
||
它的條目:${REASON}
|
||
|
||
🔴 **2026-08-16 總管一小時內在同一條分支上犯了兩次**,而且第一次之後
|
||
還在回覆裡寫了「這正是共用工作區那條教訓咬到我自己」——**寫下教訓沒有讓他不再犯。**
|
||
|
||
【為什麼這個錯特別難發現】
|
||
打錯分支之後跑 \`git push gitea main\` 會回 **\`Everything up-to-date\`**——
|
||
**那是假成功**,因為本機 \`main\` 確實沒動過。
|
||
真訊號是「**本機 HEAD 與遠端對不上**」,而那句話不會自己跳出來。
|
||
|
||
【現在怎麼做(擇一)】
|
||
① **切回 main 再 commit**(絕大多數情況的正解):
|
||
git checkout main && <你的 git commit ...>
|
||
② **已經打錯了要救**:
|
||
git checkout main && git cherry-pick <那顆 sha>
|
||
git branch -f $BR gitea/$BR # 把別人的分支還原成遠端狀態
|
||
③ **你真的要接手這條分支**:先把它從 \`.claude/branch-holds.md\` 移除
|
||
(那本來就是「它不再是別人的」的正確表示法),再 commit
|
||
④ 真有例外:\`NOT_MY_BRANCH_OK=1 git commit ...\`,並在 commit 說明寫理由
|
||
EOF
|
||
exit 2
|