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>
111 lines
5.5 KiB
Bash
Executable File
111 lines
5.5 KiB
Bash
Executable File
#!/bin/bash
|
||
# PreToolUse hook — 影子表警察:抓 D91 的指紋(宣告 schema 在一邊,資料倒進 JSON 團在另一邊)
|
||
#
|
||
# 🚫 **本檔目前是死的:沒有註冊進 .claude/settings.json,不會被執行。**
|
||
# leo 2026-08-15:「**我是要你提案封鎖方式,不是要你就去做,急着做造成太多疊牀架屋了。**」
|
||
# ⇒ 總管在討論「疊牀架屋是病」的同時去疊了這一層。已測過(該擋兩條擋、六條不該擋全放),
|
||
# 但**要不要掛由 leo 裁**——它只在「過渡期止血」這一個用途上值得存在。
|
||
# ⇒ 真正的封鎖方式是**刪掉 metadata_json 與 entry_type 兩個欄位**(減,不是加),
|
||
# 提案見 matrix/arcrun 的 pending-changes.md。
|
||
#
|
||
# ⚠️ 這支是**過渡期的止血帶,不是答案**(leo 2026-08-15 定調)。
|
||
# 真正的解是「**刪掉那兩個欄位,讓儲存層沒有位置放壞東西**」——提案在 matrix/arcrun 的 pending-changes.md。
|
||
# 偵測永遠落後一步:D91 就是從「多開一張表」變異成「JSON 團」的。
|
||
# 在收窄的 API 出來之前,這支至少擋得住已知的那個形狀。**別因為有閘就以為安全。**
|
||
#
|
||
# 【為什麼 kbdb-api-wall-guard 抓不到】
|
||
# 那支守著 D38「三張表打天下,永不加表」,而 D91 **完全沒有違反它**——一張表都沒加。
|
||
# 它做的是:seed 一張宣告 6 個欄位的 template,然後把資料倒進 metadata_json。
|
||
# ⇒ **一張沒人管得到的影子表,而表數是三。現有的閘數表,而病不在表數上。**
|
||
#
|
||
# 【病徵】kbdb/migrations/0004_execution_log_template.sql 自己的註解就寫著
|
||
# 「template 這裡只負責 schema 文件化⋯⋯結構化欄位打包進 metadata_json」
|
||
# ⇒ 那張宣告了 6 個欄位的 template,沒有任何東西讀它。
|
||
# 【擴散】同註解:「recipe_stat 早已示範這個模式合法」
|
||
# ⇒ 活著的 7 種 entry_type 裡有 6 種是這形狀——不是角落,是多數。
|
||
#
|
||
# 攔的是**形狀不是關鍵字**:型別標籤與 JSON 團打包必須**同時**出現才命中
|
||
# (今天已有四次閘因為比對指令形狀而誤攔,不再犯)。註解、測試、文件一律放行。
|
||
# 豁免:該行尾加 `shadow-table-ok`(留痕,commit 說明理由)。
|
||
#
|
||
# 全文:頂層 system-dev/wiki/decisions-summary.md D91、D92。
|
||
|
||
exec python3 -c '
|
||
import json, re, sys
|
||
|
||
try:
|
||
d = json.load(sys.stdin)
|
||
except Exception:
|
||
sys.exit(0)
|
||
if d.get("tool_name") not in ("Write", "Edit", "MultiEdit"):
|
||
sys.exit(0)
|
||
|
||
i = d.get("tool_input") or {}
|
||
path = i.get("file_path") or ""
|
||
if not path:
|
||
sys.exit(0)
|
||
|
||
parts = [i.get("content") or "", i.get("new_string") or ""]
|
||
for e in (i.get("edits") or []):
|
||
parts.append(e.get("new_string") or "")
|
||
body = "\n".join(p for p in parts if p)
|
||
if not body:
|
||
sys.exit(0)
|
||
|
||
low = path.lower()
|
||
if re.search(r"\.(md|txt|json|yaml|yml)$", low): sys.exit(0)
|
||
if re.search(r"(^|/)(wiki|docs|tests?)/", low): sys.exit(0)
|
||
if re.search(r"(test|spec)\.[a-z]+$|_test\.go$", low): sys.exit(0)
|
||
if not re.search(r"\.(ts|js|mjs|sql|go)$", low): sys.exit(0)
|
||
|
||
live = []
|
||
for line in body.splitlines():
|
||
if "shadow-table-ok" in line:
|
||
continue
|
||
s = re.sub(r"--.*$", "", line)
|
||
s = re.sub(r"//.*$", "", s)
|
||
if re.match(r"\s*[*#]", s):
|
||
continue
|
||
live.append(s)
|
||
live = "\n".join(live)
|
||
|
||
# A:把型別標籤釘在 entries 上
|
||
a = len(re.findall(r"""entry_type\s*[:=]\s*[\x27"][a-z_]+[\x27"]""", live))
|
||
# B:結構化欄位被打包進 JSON 團
|
||
b = len(re.findall(r"""metadata_json[^\n]{0,80}(JSON\.stringify|json_object|\{)|(JSON\.stringify|json_object)\([^\n]{0,80}metadata_json""", live))
|
||
# C:seed 一張宣告了欄位的 template
|
||
c = len(re.findall(r"""INSERT\s+(OR\s+IGNORE\s+)?INTO\s+templates\b[^;]{0,200}slots_json|slots_json\s*[:=]""", live, re.I | re.S))
|
||
|
||
if not ((a and b) or (c and b)):
|
||
sys.exit(0)
|
||
|
||
sys.stderr.write(f"""❌ BLOCKED — 影子表警察(D91 的指紋)
|
||
|
||
檔案:{path}
|
||
命中:型別標籤 {a} 處/JSON 團打包 {b} 處/template 宣告 {c} 處
|
||
|
||
你正在寫的形狀是:**宣告一個 schema,然後把資料倒進 metadata_json**。
|
||
那會做出一張**沒人管得到的影子表**——表數還是三,但欄位從此改不動:
|
||
要加一欄,得同時改「一個沒人讀的宣告」和「一段打包程式」,
|
||
而**沒有任何機制會告訴你它們已經對不上了**。
|
||
|
||
leo 2026-08-15:「這每個都是一個 template⋯⋯**以後你不能修改 fields,因為表禁止動**,
|
||
如果要多一欄,要不就是說要改表,**要不就是全塞在能塞的格子裡**。」
|
||
|
||
先回答這三題,答不出來就不是這樣寫:
|
||
① 這些被打包的欄位,**誰會讀 schema 宣告**?沒有人讀 ⇒ 那個宣告是裝飾品
|
||
② 要加第八個欄位時,**有什麼東西會擋住「只改了一半」**?
|
||
③ 這批資料的形狀是**我們決定**的,還是**使用者的想法**決定的?
|
||
使用者決定 ⇒ 不准有 schema,走 v-table
|
||
(Arcrun#133 的判準:這張表要改的時候,誰付 migration 的代價?)
|
||
|
||
真的有理由這樣寫(例:那條路徑的寫入放大有實測數字,且已在票上記錄)
|
||
⇒ 該行尾加 `shadow-table-ok`,並在 commit 說明理由。
|
||
|
||
⚠️ 本閘是過渡期止血帶。真正的解是刪掉 metadata_json 與 entry_type(減,不是加)。
|
||
|
||
參考:system-dev/wiki/decisions-summary.md **D91**(病徵與擴散)、**D92**(同族形狀)
|
||
""")
|
||
sys.exit(2)
|
||
'
|