fix: update.sh 不再覆蓋客製 pre-write-guard.sh(issue #3)+ bump 1.3.1

update.sh 原把 pre-write-guard.sh 列在無條件覆蓋區,會用模板空殼
無聲蓋掉下游已客製的 guardrail,且 update_file 無 .bak 備份。

改法(issue 方案 1):新增 keep_with_template()——原檔永不覆蓋,
最新模板版另存 pre-write-guard.template.sh 旁邊,結尾印 diff 指令供採納。
首次安裝(原檔不存在)才走 update_file 抓本體。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-25 20:47:46 +08:00
parent ba247428a8
commit c0a6b6a465
3 changed files with 51 additions and 2 deletions
+12
View File
@@ -10,6 +10,18 @@
--- ---
## 1.3.1 — 修:update.sh 不再覆蓋客製的 pre-write-guard.shissue #3
**修正**
- `scripts/update.sh` 原本把 `pre-write-guard.sh` 列在「覆蓋更新」區,**無條件**用模板空殼蓋掉。
但此檔的定位是「使用者手填的 guardrail 客製檔」(CHANGELOG 1.2.0),下游通常已塞滿自己的 enforcement
`update_file` 覆蓋**無 `.bak` 備份**——跑一次 update 等於無聲關掉整套 guardrail(如 Arcrun 的 KNOWN_SDDS 白名單、薄殼原則強制等數百行)。
- 改法(issue 建議方案 1):新增 `keep_with_template()`,把 `pre-write-guard.sh` 移出覆蓋區。
**原檔永不覆蓋**,改把最新模板版另存成 `pre-write-guard.template.sh` 旁邊,更新結尾印出 `diff` 指令供使用者自行採納。
首次安裝(原檔不存在)才會直接抓本體。`install.sh` 路徑本就用 `download_if_missing`(已存在即跳過),無此問題。
---
## 1.3.0 — vault 偵測(Logseq / Obsidian+ Cowork 整理 skill ## 1.3.0 — vault 偵測(Logseq / Obsidian+ Cowork 整理 skill
**新增** **新增**
+38 -1
View File
@@ -21,6 +21,7 @@ TEMPLATE_URL="$REPO_RAW/template"
UPDATED=() UPDATED=()
KEPT=() KEPT=()
NEW=() NEW=()
TEMPLATED=()
# ── 版本比對:先看本機 vs 遠端,給使用者「值不值得更新」的判斷 ── # ── 版本比對:先看本機 vs 遠端,給使用者「值不值得更新」的判斷 ──
LOCAL_VER="(未知)" LOCAL_VER="(未知)"
@@ -77,6 +78,29 @@ keep_file() {
[ -f "$1" ] && KEPT+=("$1") || true [ -f "$1" ] && KEPT+=("$1") || true
} }
# 客製檔:使用者一定會手填內容(如 pre-write-guard.sh)。
# - 已存在 → 絕不覆蓋,但把最新模板版抓到 <檔名>.template.sh 旁邊,供使用者自行 diff 採納。
# - 不存在 → 視同新檔,直接抓本體(第一次安裝才會走這條)。
keep_with_template() {
local dest="$1" src="$2"
if [ -f "$dest" ]; then
KEPT+=("$dest")
local tmpl="${dest%.sh}.template.sh"
if curl -sSL "$src" -o "$tmpl.tmp" 2>/dev/null && [ -s "$tmpl.tmp" ]; then
if [ -f "$tmpl" ] && cmp -s "$tmpl" "$tmpl.tmp"; then
rm -f "$tmpl.tmp" # 模板版沒變,不重複提示
else
mv "$tmpl.tmp" "$tmpl"
TEMPLATED+=("$tmpl")
fi
else
rm -f "$tmpl.tmp"
fi
else
update_file "$dest" "$src" # 還沒裝過 → 當新檔處理
fi
}
# ── 偵測已安裝哪些模組(依現有檔案判斷,更新只動已裝的)── # ── 偵測已安裝哪些模組(依現有檔案判斷,更新只動已裝的)──
HAS_WIKI=false HAS_WIKI=false
HAS_SDD=false HAS_SDD=false
@@ -89,9 +113,14 @@ $HAS_SDD && echo " • SDD"
{ $HAS_WIKI || $HAS_SDD; } || echo " (未偵測到任何模組——這裡可能還沒安裝,請改跑 install.sh" { $HAS_WIKI || $HAS_SDD; } || echo " (未偵測到任何模組——這裡可能還沒安裝,請改跑 install.sh"
echo "" echo ""
# ── 客製檔:使用者手填的 guardrail,永不覆蓋(issue #3)──
# pre-write-guard.sh 的定位是「空白客製模板,使用者沒配置前不提供保護」(CHANGELOG 1.2.0)。
# 下游通常已塞滿自己的 enforcement,直接覆蓋=無聲關掉整套 guardrail。
# 改為:保留原檔不動,新版範本另存 pre-write-guard.template.sh,由使用者自行 diff 採納。
keep_with_template ".claude/hooks/pre-write-guard.sh" "$TEMPLATE_URL/.claude/hooks/pre-write-guard.sh"
# ── 模板/邏輯檔:覆蓋更新 ────────────────────────── # ── 模板/邏輯檔:覆蓋更新 ──────────────────────────
# 共用 hook 與指引 # 共用 hook 與指引
update_file ".claude/hooks/pre-write-guard.sh" "$TEMPLATE_URL/.claude/hooks/pre-write-guard.sh"
update_file ".claude/commands/issue-handle.md" "$TEMPLATE_URL/.claude/commands/issue-handle.md" update_file ".claude/commands/issue-handle.md" "$TEMPLATE_URL/.claude/commands/issue-handle.md"
update_file ".claude/VERSION" "$TEMPLATE_URL/.claude/VERSION" update_file ".claude/VERSION" "$TEMPLATE_URL/.claude/VERSION"
@@ -154,6 +183,14 @@ if [ ${#KEPT[@]} -gt 0 ]; then
echo "🔒 完整保留(你的內容/設定,從未碰過):" echo "🔒 完整保留(你的內容/設定,從未碰過):"
for f in "${KEPT[@]}"; do echo " = $f"; done for f in "${KEPT[@]}"; do echo " = $f"; done
fi fi
if [ ${#TEMPLATED[@]} -gt 0 ]; then
echo ""
echo "📋 客製檔有新版範本(你的原檔沒動,新版另存旁邊,請自行 diff 採納):"
for f in "${TEMPLATED[@]}"; do
echo "$f"
echo " 比對:diff \"${f%.template.sh}.sh\" \"$f\""
done
fi
# ── settings.json 提醒:新模組 hook 可能要手動補 ── # ── settings.json 提醒:新模組 hook 可能要手動補 ──
if [ -f ".claude/settings.json" ]; then if [ -f ".claude/settings.json" ]; then
+1 -1
View File
@@ -1 +1 @@
1.3.0 1.3.1