feat(W2 Phase 2-3): JDD 文件範本+八條封路 hook+還清兩件舊債
SDD: docs/3-specs/jdd-dual-profile(active)。編號 task 26/33 完成,Phase 4-5 未開工。 ■ Phase 2 JDD 文件範本(orchestrator profile) 範本形狀對齊「實際跑出來的那兩份」(總管已寫的 root.md 15 卡、journeys.md J-1 九站), 不是照規格憑空造: - 卡片是巢狀 bullet(`- **P1** 🟢 …` + 子項放來源/對帳),非規格畫的平行文字行 - 站點索引**巢狀 bullet 不用表格**(表格會把層級壓平,看不出從屬) - 兩份都保留「這卷還缺什麼(誠實記)」收尾段——規格沒有,但那是防假綠的地方 新增:root.md / journeys.md / sprint.md / triage-map.md 四範本(add-if-missing, 填了就永不覆蓋)+ plugin-load-order.md(W3 插槽,框架不發明平行外掛格式) ■ Phase 3 封路 hook(八條規則落六支檔) - role-guard(J1+J2+J3)★命門:考生不能改考卷。六組實測含「考題藏在別的 md 裡」也擋 - jdd-format-guard(J4+J5+J8):紅卡缺對帳日/任務缺站號/PM 文件混技術名詞 - station-done-guard(J6):收工判準是站的考題全綠,不是任務全關 - regression-scope(J7):動實作 → 列出要重考哪幾題(只提醒不擋) - install-artifact-guard(S1):實例不改機制 - orchestrator-scope-guard(S4):總管不進成員 repo 動實作(從實例上收進框架, 路徑清單改由實例自填,範本零專名) 掛載鏈依「範圍大的擋在前」:改機制 → 角色 → 位置 → 格式 → 既有三支 ■ 還清兩件舊債 - update.sh 檔案清單改讀 manifest(舊硬編降為抓不到來源時的 fallback) ——install/update 兩份手抄清單漂移的根因全修 - CLAUDE.md 界標補植:舊實例全文原封包進本地區、框架區重鋪、原檔備份、冪等 ——解開「沒界標⇒不敢覆蓋⇒框架改的憲法永遠送不到既有實例」這個死結 ■ 修掉三個自己造的問題(實測抓出來的,不是想出來的) - jdd-format-guard 誤擋真實 journeys.md 的「這卷還缺什麼」自述段 → 排除法改**正面圈定**(只掃卡片本體與站內文),說明區/自述段/索引自然不在範圍 - install-artifact-guard 把 pre-write-guard.sh 也擋了——而它的錯誤訊息正叫人去改那支 → 使用者自訂插槽列為最優先放行 - check-legacy-paths 用 HEAD 當基準會**自我弱化**:改成清單驅動後保護範圍 35→29 條 → 基準改指最後一次真正發佈的版本 ■ 實測(全部貼過輸出) - G2 考生改考卷:6/6,含 orchestrator 寫 code/engineer 改考題/考題藏別處 - G4 憲法分流:兩環境重裝,總管版技術軌關鍵字 0、成員版上游指針 8,界標 4/4 - G6 實例改機制:4/4,含框架開發標記放行與自訂插槽放行 - G7 CI 擋實例名:注入違規 → 指出檔案行號 exit 1 - G3 進度以站計量:起牀推「J-1 已點亮 2/9 站」、收工列未亮站並禁用任務數當理由 - 回歸考、界標補植冪等、orchestrator-scope-guard 四組:全通 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,14 @@ set -euo pipefail
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
BASE="${BASE:-HEAD}"
|
||||
# ⚠️ 基準**不能**用 HEAD——這是實測踩到的:
|
||||
# 把 install.sh 改成清單驅動之後,HEAD 裡的硬編路徑從 35 條掉到 29 條,
|
||||
# **閘保護的範圍就跟著縮水 6 條**——而那 6 條正是還沒更新的舊實例仍然會去抓的。
|
||||
# 用 HEAD 當基準,閘會隨著每次提交自我弱化,最後變成「只保護今天的自己」。
|
||||
# ⇒ 基準必須是「**外面實際在跑的那一版**」=最後一次真的發佈出去的 commit。
|
||||
# 發新版、且確認真的送出去之後,才把下面這行往前挪。
|
||||
LAST_RELEASED_DEFAULT="dc4fe67" # 1.18.0
|
||||
BASE="${BASE:-$LAST_RELEASED_DEFAULT}"
|
||||
|
||||
# ── 取出基準版本的兩支腳本 ────────────────────────────
|
||||
TMP="$(mktemp -d)"
|
||||
|
||||
+15
-2
@@ -414,9 +414,18 @@ build_hooks_json() {
|
||||
fi
|
||||
|
||||
# PreToolUse 依模組疊加。
|
||||
# 順序原則:**範圍大的擋在前**——這樣錯誤訊息會指向最根本的那條規則,
|
||||
# 順序原則:**範圍大的擋在前**——錯誤訊息才會指向最根本的那條規則,
|
||||
# 而不是讓人先修一個表層問題、修完才發現底下還有一條。
|
||||
# ① 改機制 這個檔你根本不該動(最外層)
|
||||
# ② 角色 你這個身分不該寫這種檔
|
||||
# ③ 位置 總管不該進成員 repo 動實作(僅總管實例)
|
||||
# ④ 格式 檔可以寫,但寫進去的內容格式不對
|
||||
# ⑤ 既有的 SDD/自訂禁令/機敏掃描
|
||||
local pt=()
|
||||
pt+=('{ "type": "command", "command": ".claude/hooks/install-artifact-guard.sh" }')
|
||||
pt+=('{ "type": "command", "command": ".claude/hooks/role-guard.sh" }')
|
||||
[ "$PROFILE" = "orchestrator" ] && pt+=('{ "type": "command", "command": ".claude/hooks/orchestrator-scope-guard.sh" }')
|
||||
pt+=('{ "type": "command", "command": ".claude/hooks/jdd-format-guard.sh" }')
|
||||
$WANT_SDD && pt+=('{ "type": "command", "command": ".claude/hooks/sdd-guard.sh" }')
|
||||
pt+=('{ "type": "command", "command": ".claude/hooks/pre-write-guard.sh" }')
|
||||
$WANT_WIKI && pt+=('{ "type": "command", "command": ".claude/hooks/wiki-secret-scan.sh" }')
|
||||
@@ -435,7 +444,11 @@ build_hooks_json() {
|
||||
if [ -n "$session_hooks" ]; then
|
||||
printf ' "SessionStart": [\n { "matcher": "startup|resume|clear",\n "hooks": [ %s ] }\n ],\n' "$session_hooks"
|
||||
fi
|
||||
printf ' "PreToolUse": [\n { "matcher": "Write|Edit",\n "hooks": [ %s ] }\n ]\n' "$pretool_hooks"
|
||||
printf ' "PreToolUse": [\n { "matcher": "Write|Edit|MultiEdit",\n "hooks": [ %s ] }\n ],\n' "$pretool_hooks"
|
||||
# 回歸考:動了實作之後才有意義 → PostToolUse(只提醒不擋)
|
||||
printf ' "PostToolUse": [\n { "matcher": "Write|Edit|MultiEdit",\n "hooks": [ { "type": "command", "command": ".claude/hooks/regression-scope.sh" } ] }\n ],\n'
|
||||
# 收工判準:站的考題全綠才算收,不是任務全關 → Stop
|
||||
printf ' "Stop": [\n { "hooks": [ { "type": "command", "command": ".claude/hooks/station-done-guard.sh" } ] }\n ]\n'
|
||||
printf ' }\n}\n'
|
||||
}
|
||||
|
||||
|
||||
+177
-56
@@ -298,67 +298,148 @@ echo ""
|
||||
# 改為:保留原檔不動,新版範本另存 pre-write-guard.template.sh,由使用者自行 diff 採納。
|
||||
keep_with_template ".claude/hooks/pre-write-guard.sh" "$TEMPLATE_URL/.claude/hooks/pre-write-guard.sh"
|
||||
|
||||
# ── 舊版硬編清單(僅在抓不到 manifest 時使用的退路)──────────
|
||||
# 保留它的唯一理由:來源不可達時,更新不該整個停擺。
|
||||
# ⚠️ 新增產物請改 template/manifest/*.tsv,**不要**再往這裡加——
|
||||
# 這份清單就是當初漂移的來源。
|
||||
legacy_update_list() {
|
||||
# ── 模板/邏輯檔:覆蓋更新 ──────────────────────────
|
||||
# 共用 hook 與指引
|
||||
update_file ".claude/commands/issue-handle.md" "$TEMPLATE_URL/.claude/commands/issue-handle.md"
|
||||
update_file "system-dev/VERSION" "$TEMPLATE_URL/system-dev/VERSION"
|
||||
update_file ".claude/commands/issue-handle.md" "$TEMPLATE_URL/.claude/commands/issue-handle.md"
|
||||
update_file "system-dev/VERSION" "$TEMPLATE_URL/system-dev/VERSION"
|
||||
|
||||
# Logseq 任務 marker 解析(單一真相源):vault 萃取(/wiki-extract)與 tasks→Project
|
||||
# 投影共用同一套;任一模組在用就補/更新(邏輯檔,可覆蓋)。
|
||||
if $HAS_WIKI || $HAS_SDD; then
|
||||
update_file "system-dev/docs/4-guides/logseq-markers.md" "$TEMPLATE_URL/system-dev/docs/4-guides/logseq-markers.md"
|
||||
if $HAS_WIKI || $HAS_SDD; then
|
||||
update_file "system-dev/docs/4-guides/logseq-markers.md" "$TEMPLATE_URL/system-dev/docs/4-guides/logseq-markers.md"
|
||||
fi
|
||||
|
||||
if $HAS_WIKI; then
|
||||
# wiki 的「邏輯檔」:導航與 hooks,可覆蓋。wiki 資料在 system-dev/,hooks/commands 留 .claude/。
|
||||
update_file "system-dev/wiki/INDEX.md" "$TEMPLATE_URL/system-dev/wiki/INDEX.md"
|
||||
update_file ".claude/hooks/session-start-recall.sh" "$TEMPLATE_URL/.claude/hooks/session-start-recall.sh"
|
||||
update_file ".claude/hooks/wiki-secret-scan.sh" "$TEMPLATE_URL/.claude/hooks/wiki-secret-scan.sh"
|
||||
# 1.16.0:讓 wiki 真的被讀到的兩支(開場 push 全文解決不了「只讀開頭」,見 CHANGELOG)
|
||||
update_file ".claude/hooks/wiki-first-search.sh" "$TEMPLATE_URL/.claude/hooks/wiki-first-search.sh"
|
||||
update_file ".claude/hooks/subagent-wiki-guard.sh" "$TEMPLATE_URL/.claude/hooks/subagent-wiki-guard.sh"
|
||||
# 1.18.0:公開 mirror 落後偵測(手動同步的靜默失敗只有外部用戶會撞到)
|
||||
update_file ".claude/hooks/publish-lag-check.sh" "$TEMPLATE_URL/.claude/hooks/publish-lag-check.sh"
|
||||
update_file ".claude/commands/wiki-init.md" "$TEMPLATE_URL/.claude/commands/wiki-init.md"
|
||||
update_file ".claude/commands/wiki-capture.md" "$TEMPLATE_URL/.claude/commands/wiki-capture.md"
|
||||
update_file ".claude/commands/wiki-update.md" "$TEMPLATE_URL/.claude/commands/wiki-update.md"
|
||||
update_file ".claude/commands/wiki-recall.md" "$TEMPLATE_URL/.claude/commands/wiki-recall.md"
|
||||
# vault 增量萃取(Logseq/Obsidian → system-dev/wiki,冪等):邏輯檔,可覆蓋。舊版沒有 → 當新檔補。
|
||||
update_file ".claude/commands/wiki-extract.md" "$TEMPLATE_URL/.claude/commands/wiki-extract.md"
|
||||
# Cowork(claude.ai)的 wiki 整理 skill:規則檔,可覆蓋
|
||||
update_file "system-dev/docs/SKILL.md" "$TEMPLATE_URL/system-dev/docs/SKILL.md"
|
||||
|
||||
# wiki 的「使用者資料」:絕不碰
|
||||
keep_file "system-dev/wiki/status.md"
|
||||
keep_file "system-dev/wiki/mistakes.md"
|
||||
# principles.md(1.10):舊版沒有 → 補範本;已有 → 當用戶資料保留
|
||||
add_if_missing "system-dev/wiki/principles.md" "$TEMPLATE_URL/system-dev/wiki/principles.md"
|
||||
keep_file "system-dev/wiki/decisions-summary.md"
|
||||
keep_file "system-dev/wiki/TAXONOMY.md"
|
||||
keep_file "system-dev/wiki/.wikiignore"
|
||||
fi
|
||||
|
||||
if $HAS_SDD; then
|
||||
# SDD 範本與 hook:可覆蓋
|
||||
update_file "system-dev/docs/3-specs/TEMPLATE-sdd/design.md" "$TEMPLATE_URL/system-dev/docs/3-specs/TEMPLATE-sdd/design.md"
|
||||
update_file "system-dev/docs/3-specs/TEMPLATE-sdd/tasks.md" "$TEMPLATE_URL/system-dev/docs/3-specs/TEMPLATE-sdd/tasks.md"
|
||||
update_file "system-dev/docs/2-architecture/decisions/TEMPLATE-adr.md" "$TEMPLATE_URL/system-dev/docs/2-architecture/decisions/TEMPLATE-adr.md"
|
||||
update_file ".claude/commands/sdd-check.md" "$TEMPLATE_URL/.claude/commands/sdd-check.md"
|
||||
update_file ".claude/hooks/sdd-guard.sh" "$TEMPLATE_URL/.claude/hooks/sdd-guard.sh"
|
||||
|
||||
# SDD 生命週期鐵律(1.14,issue #6):規則檔+獨立檢查腳本=邏輯檔可覆蓋;
|
||||
# pending-changes.md 裝著用戶的 proposal=用戶資料,只補不覆蓋。
|
||||
# (issue #13 教訓:update 不補新檔會造成結構斷層,新檔必須在這裡鋪。)
|
||||
update_file "system-dev/docs/3-specs/SDD-LIFECYCLE.md" "$TEMPLATE_URL/system-dev/docs/3-specs/SDD-LIFECYCLE.md"
|
||||
add_if_missing "system-dev/docs/3-specs/pending-changes.md" "$TEMPLATE_URL/system-dev/docs/3-specs/pending-changes.md"
|
||||
update_file "system-dev/scripts/sdd-active-check.sh" "$TEMPLATE_URL/scripts/sdd-active-check.sh"
|
||||
|
||||
# tasks⇄Project 投影(issue #16):邏輯檔,可覆蓋。舊版沒有 → add_if_missing 補。
|
||||
# 啟用狀態存遠端(acr push),不在這些檔裡,覆蓋不會關掉誰的同步。
|
||||
add_if_missing "system-dev/workflows/tasks-project-sync.yaml" "$TEMPLATE_URL/system-dev/workflows/tasks-project-sync.yaml"
|
||||
add_if_missing "system-dev/workflows/tasks-project-sync.local.sh" "$TEMPLATE_URL/system-dev/workflows/tasks-project-sync.local.sh"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# ── Manifest 驅動的更新(1.19.0:兩支腳本讀同一份清單)────────
|
||||
# 在這之前,這裡是一份**手抄的**檔案清單,install.sh 另有一份。兩份手抄必然漂移,
|
||||
# 而且已經漂了:wiki-first-search / subagent-wiki-guard / publish-lag-check /
|
||||
# decisions-summary 這四個,update 會處理但 install 從來不裝
|
||||
# ⇒ 乾淨安裝的人反而拿不到最新三版的招牌功能。
|
||||
# 現在兩支都讀 template/manifest/*.tsv,這類漂移在結構上不可能再發生。
|
||||
#
|
||||
# 讀不到 manifest(來源太舊/網路問題)→ 退回舊的硬編清單(見下方 legacy_update_list),
|
||||
# 不讓更新整個停擺。
|
||||
|
||||
MANIFEST_DIR="system-dev/.template-manifest.d"
|
||||
mkdir -p "$MANIFEST_DIR"
|
||||
|
||||
SDT_PROFILE="repo"
|
||||
[ -f "system-dev/.profile" ] && SDT_PROFILE="$(tr -d '[:space:]' < system-dev/.profile 2>/dev/null || echo repo)"
|
||||
|
||||
fetch_manifest() { # $1=名稱
|
||||
local out="$MANIFEST_DIR/$1.tsv"
|
||||
if curl -sSL "$TEMPLATE_URL/manifest/$1.tsv" -o "$out" 2>/dev/null \
|
||||
&& [ -s "$out" ] && ! looks_like_error_page "$out"; then
|
||||
return 0
|
||||
fi
|
||||
rm -f "$out"; return 1
|
||||
}
|
||||
|
||||
resolve_src() {
|
||||
case "$1" in
|
||||
T:*) printf '%s/%s' "$TEMPLATE_URL" "${1#T:}" ;;
|
||||
S:*) printf '%s/%s' "$REPO_RAW/scripts" "${1#S:}" ;;
|
||||
*) printf '' ;;
|
||||
esac
|
||||
}
|
||||
|
||||
want_module() {
|
||||
case "$1" in
|
||||
core) return 0 ;;
|
||||
wiki) $HAS_WIKI && return 0 || return 1 ;;
|
||||
sdd) $HAS_SDD && return 0 || return 1 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
apply_manifest() { # $1=manifest 檔
|
||||
local f="$1" src dest class module profile url
|
||||
[ -f "$f" ] || return 0
|
||||
while IFS=$'\t' read -r src dest class module profile; do
|
||||
case "$src" in ''|'#'*) continue ;; esac
|
||||
[ -z "${dest:-}" ] && continue
|
||||
want_module "$module" || continue
|
||||
url="$(resolve_src "$src")"
|
||||
case "$class" in
|
||||
dir) mkdir -p "$dest" 2>/dev/null || true ;;
|
||||
overwrite) [ -n "$url" ] && update_file "$dest" "$url" ;;
|
||||
add-if-missing) [ -n "$url" ] && add_if_missing "$dest" "$url" ;;
|
||||
keep-with-template) [ -n "$url" ] && keep_with_template "$dest" "$url" ;;
|
||||
keep) keep_file "$dest" ;;
|
||||
claude-md) CLAUDE_MD_SRC="$url" ;; # 憲法走界標補植,見下方專段
|
||||
*) : ;;
|
||||
esac
|
||||
done < "$f"
|
||||
}
|
||||
|
||||
CLAUDE_MD_SRC=""
|
||||
USED_MANIFEST=false
|
||||
if fetch_manifest common; then
|
||||
USED_MANIFEST=true
|
||||
fetch_manifest "$SDT_PROFILE" || true
|
||||
apply_manifest "$MANIFEST_DIR/common.tsv"
|
||||
apply_manifest "$MANIFEST_DIR/$SDT_PROFILE.tsv"
|
||||
else
|
||||
t "⚠️ 抓不到安裝清單,退回舊版硬編清單(功能較少但不會壞)" \
|
||||
"⚠️ Manifest unavailable; falling back to the legacy hardcoded list"
|
||||
legacy_update_list
|
||||
fi
|
||||
|
||||
if $HAS_WIKI; then
|
||||
# wiki 的「邏輯檔」:導航與 hooks,可覆蓋。wiki 資料在 system-dev/,hooks/commands 留 .claude/。
|
||||
update_file "system-dev/wiki/INDEX.md" "$TEMPLATE_URL/system-dev/wiki/INDEX.md"
|
||||
update_file ".claude/hooks/session-start-recall.sh" "$TEMPLATE_URL/.claude/hooks/session-start-recall.sh"
|
||||
update_file ".claude/hooks/wiki-secret-scan.sh" "$TEMPLATE_URL/.claude/hooks/wiki-secret-scan.sh"
|
||||
# 1.16.0:讓 wiki 真的被讀到的兩支(開場 push 全文解決不了「只讀開頭」,見 CHANGELOG)
|
||||
update_file ".claude/hooks/wiki-first-search.sh" "$TEMPLATE_URL/.claude/hooks/wiki-first-search.sh"
|
||||
update_file ".claude/hooks/subagent-wiki-guard.sh" "$TEMPLATE_URL/.claude/hooks/subagent-wiki-guard.sh"
|
||||
# 1.18.0:公開 mirror 落後偵測(手動同步的靜默失敗只有外部用戶會撞到)
|
||||
update_file ".claude/hooks/publish-lag-check.sh" "$TEMPLATE_URL/.claude/hooks/publish-lag-check.sh"
|
||||
update_file ".claude/commands/wiki-init.md" "$TEMPLATE_URL/.claude/commands/wiki-init.md"
|
||||
update_file ".claude/commands/wiki-capture.md" "$TEMPLATE_URL/.claude/commands/wiki-capture.md"
|
||||
update_file ".claude/commands/wiki-update.md" "$TEMPLATE_URL/.claude/commands/wiki-update.md"
|
||||
update_file ".claude/commands/wiki-recall.md" "$TEMPLATE_URL/.claude/commands/wiki-recall.md"
|
||||
# vault 增量萃取(Logseq/Obsidian → system-dev/wiki,冪等):邏輯檔,可覆蓋。舊版沒有 → 當新檔補。
|
||||
update_file ".claude/commands/wiki-extract.md" "$TEMPLATE_URL/.claude/commands/wiki-extract.md"
|
||||
# Cowork(claude.ai)的 wiki 整理 skill:規則檔,可覆蓋
|
||||
update_file "system-dev/docs/SKILL.md" "$TEMPLATE_URL/system-dev/docs/SKILL.md"
|
||||
|
||||
# wiki 的「使用者資料」:絕不碰
|
||||
keep_file "system-dev/wiki/status.md"
|
||||
keep_file "system-dev/wiki/mistakes.md"
|
||||
# principles.md(1.10):舊版沒有 → 補範本;已有 → 當用戶資料保留
|
||||
add_if_missing "system-dev/wiki/principles.md" "$TEMPLATE_URL/system-dev/wiki/principles.md"
|
||||
keep_file "system-dev/wiki/decisions-summary.md"
|
||||
keep_file "system-dev/wiki/TAXONOMY.md"
|
||||
keep_file "system-dev/wiki/.wikiignore"
|
||||
fi
|
||||
|
||||
if $HAS_SDD; then
|
||||
# SDD 範本與 hook:可覆蓋
|
||||
update_file "system-dev/docs/3-specs/TEMPLATE-sdd/design.md" "$TEMPLATE_URL/system-dev/docs/3-specs/TEMPLATE-sdd/design.md"
|
||||
update_file "system-dev/docs/3-specs/TEMPLATE-sdd/tasks.md" "$TEMPLATE_URL/system-dev/docs/3-specs/TEMPLATE-sdd/tasks.md"
|
||||
update_file "system-dev/docs/2-architecture/decisions/TEMPLATE-adr.md" "$TEMPLATE_URL/system-dev/docs/2-architecture/decisions/TEMPLATE-adr.md"
|
||||
update_file ".claude/commands/sdd-check.md" "$TEMPLATE_URL/.claude/commands/sdd-check.md"
|
||||
update_file ".claude/hooks/sdd-guard.sh" "$TEMPLATE_URL/.claude/hooks/sdd-guard.sh"
|
||||
|
||||
# SDD 生命週期鐵律(1.14,issue #6):規則檔+獨立檢查腳本=邏輯檔可覆蓋;
|
||||
# pending-changes.md 裝著用戶的 proposal=用戶資料,只補不覆蓋。
|
||||
# (issue #13 教訓:update 不補新檔會造成結構斷層,新檔必須在這裡鋪。)
|
||||
update_file "system-dev/docs/3-specs/SDD-LIFECYCLE.md" "$TEMPLATE_URL/system-dev/docs/3-specs/SDD-LIFECYCLE.md"
|
||||
add_if_missing "system-dev/docs/3-specs/pending-changes.md" "$TEMPLATE_URL/system-dev/docs/3-specs/pending-changes.md"
|
||||
update_file "system-dev/scripts/sdd-active-check.sh" "$TEMPLATE_URL/scripts/sdd-active-check.sh"
|
||||
|
||||
# tasks⇄Project 投影(issue #16):邏輯檔,可覆蓋。舊版沒有 → add_if_missing 補。
|
||||
# 啟用狀態存遠端(acr push),不在這些檔裡,覆蓋不會關掉誰的同步。
|
||||
add_if_missing "system-dev/workflows/tasks-project-sync.yaml" "$TEMPLATE_URL/system-dev/workflows/tasks-project-sync.yaml"
|
||||
add_if_missing "system-dev/workflows/tasks-project-sync.local.sh" "$TEMPLATE_URL/system-dev/workflows/tasks-project-sync.local.sh"
|
||||
fi
|
||||
|
||||
# ── 自我更新:把最新的 update.sh / install.sh 抓到 system-dev/scripts/ ──
|
||||
# 這兩支在 main/scripts/ 下(不在 template/);落地位置新版收進 system-dev/scripts/。
|
||||
update_file "system-dev/scripts/update.sh" "$REPO_RAW/scripts/update.sh"
|
||||
@@ -368,7 +449,47 @@ chmod +x .claude/hooks/*.sh system-dev/scripts/*.sh system-dev/workflows/*.sh 2>
|
||||
|
||||
# ── 使用者資料檔:絕不碰,但提醒「設定可能有新欄位要手動補」──
|
||||
keep_file ".claude/settings.json"
|
||||
keep_file "CLAUDE.md"
|
||||
|
||||
# ── CLAUDE.md 界標補植(1.19.0)────────────────────────
|
||||
# 1.18.x 以前的 CLAUDE.md 是「整份下載 + 往後 append」,**沒有任何區段界標**。
|
||||
# 沒界標 ⇒ update 分不出「哪段是框架的、哪段是你寫的」⇒ 只能永遠不敢碰
|
||||
# ⇒ 框架後來改的憲法**永遠送不到既有實例**。這一段就是來解這個死結。
|
||||
#
|
||||
# 保守到底,寧可什麼都不做也不弄丟一個字:
|
||||
# · 已有界標 → 什麼都不做(冪等)
|
||||
# · 沒有界標 → 現有全文**原封不動**包進本地補充區,框架區重鋪在它上面
|
||||
# · 抓不到憲法範本 → 放棄補植、保留原檔(不留半殘的檔)
|
||||
# 最壞情況是同一段內容在兩區各一份,由人自己刪——我們不代刪。
|
||||
if [ -f "CLAUDE.md" ]; then
|
||||
if grep -q 'sdt:framework begin' CLAUDE.md 2>/dev/null; then
|
||||
keep_file "CLAUDE.md"
|
||||
elif [ -n "${CLAUDE_MD_SRC:-}" ]; then
|
||||
FW_TMP="$(mktemp)"
|
||||
if curl -sSL "$CLAUDE_MD_SRC" -o "$FW_TMP" 2>/dev/null && ! looks_like_error_page "$FW_TMP"; then
|
||||
cp CLAUDE.md "CLAUDE.md.before-markers"
|
||||
{
|
||||
printf '<!-- sdt:framework begin profile=%s version=%s sha256=%s -->\n' \
|
||||
"$SDT_PROFILE" "$REMOTE_VER" "$(sdt_sha256 "$FW_TMP" | cut -c1-12)"
|
||||
cat "$FW_TMP"
|
||||
printf '<!-- sdt:framework end -->\n\n'
|
||||
printf '<!-- sdt:local begin — 這一區是你的,update 永遠不會動它 -->\n'
|
||||
printf '\n<!-- ⬇️ 以下是你原本的 CLAUDE.md,一字未動地搬進來。\n'
|
||||
printf ' 上面的框架區從現在起由 template 維護;兩邊若有重複的段落,\n'
|
||||
printf ' 請自己刪掉這裡的舊版本(我們不敢代你刪)。\n'
|
||||
printf ' 原檔備份:CLAUDE.md.before-markers -->\n\n'
|
||||
cat "CLAUDE.md.before-markers"
|
||||
printf '\n<!-- sdt:local end -->\n'
|
||||
} > CLAUDE.md
|
||||
rm -f "$FW_TMP"
|
||||
MIGRATED+=("CLAUDE.md → 補上界標(原檔備份 CLAUDE.md.before-markers)")
|
||||
else
|
||||
rm -f "$FW_TMP"
|
||||
keep_file "CLAUDE.md"
|
||||
fi
|
||||
else
|
||||
keep_file "CLAUDE.md"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── 結果輸出 ───────────────────────────────────────
|
||||
echo ""
|
||||
|
||||
Reference in New Issue
Block a user