arcrun — AI workflow execution engine (clean history)
Self-hosted 開源:WASM 零件 + recipe + cypher-executor,跑在你自己的 Cloudflare。 此為重建的乾淨歷史起點(移除曾誤 commit 的 GCP SA 金鑰,舊歷史保留在 richblack/arcrun 與本地 backup 分支)。含: - acr init --self-hosted installer(建 KV/R2 + codeload 拉預編譯 wasm + wrangler deploy + seed recipe) - recipe push 把關(資料外流提醒 + 打通檢查) - 19 個正當零件預編譯 wasm(claude_api/km_writer/kbdb_upsert_block 排除:違反 DECISIONS §1) - CLI / cypher-executor / registry / 完整 SDD Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
# .claude/hooks/post-edit-remind-tasks.sh
|
||||
# arcrun PostToolUse hook for Write / Edit / MultiEdit
|
||||
#
|
||||
# 職責:改完 code 後立刻提醒 CC 更新對應 tasks.md,避免批次更新
|
||||
# 退出 code:不 block,只提醒(exit 0)
|
||||
|
||||
set -o pipefail
|
||||
|
||||
INPUT=$(cat)
|
||||
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
|
||||
|
||||
# 只針對程式碼檔案提醒(不含 tasks.md / CLAUDE.md / rules/*.md 本身)
|
||||
if [[ "$FILE_PATH" =~ \.(go|ts|tsx|js|jsx|py|rs|wasm)$ ]] && [[ "$FILE_PATH" != *"tasks.md"* ]]; then
|
||||
cat >&2 <<EOF
|
||||
|
||||
📌 PostEdit 提醒(by arcrun hook)
|
||||
剛修改了:${FILE_PATH}
|
||||
|
||||
下一步動作:
|
||||
1. 找到對應的 .agents/specs/*/tasks.md
|
||||
2. 如果這個 task 已完成 → 立刻把 [ ] 改成 [x](或把進行中的 [🔄] 改成 [x])
|
||||
3. 如果發現新的 sub-task → 立刻加入 tasks.md
|
||||
4. 不要等到 session 結束才批次更新
|
||||
|
||||
違反 SDD 協議會在 Stop hook 被提醒,建議現在就處理。
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Executable
+106
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
# .claude/hooks/pre-bash-guard.sh
|
||||
# arcrun PreToolUse guard for Bash
|
||||
#
|
||||
# 職責:擋下會違反 CLAUDE rules 的 shell 指令
|
||||
# 退出 code:
|
||||
# 0 = 允許
|
||||
# 2 = 擋下(stderr 訊息會回傳給 CC)
|
||||
|
||||
set -o pipefail
|
||||
|
||||
INPUT=$(cat)
|
||||
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
|
||||
|
||||
block() {
|
||||
local rule="$1"
|
||||
local reason="$2"
|
||||
local fix="$3"
|
||||
cat >&2 <<EOF
|
||||
❌ BLOCKED by arcrun CLAUDE rules
|
||||
違反項:${rule}
|
||||
指令:${CMD}
|
||||
原因:${reason}
|
||||
正確做法:${fix}
|
||||
參考:.claude/rules/02-forbidden.md
|
||||
EOF
|
||||
exit 2
|
||||
}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 規則 1.2 / 3.3:禁止用 mkdir 建立違規的 auth/credential worker 目錄
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
if echo "$CMD" | grep -qE "mkdir.*((auth|credential|jwt|oauth)[-_]worker|new[-_](auth|credential|jwt|oauth))"; then
|
||||
block "1.2/3.3" \
|
||||
"偵測到嘗試建立新的 auth/credential/jwt/oauth Worker 目錄" \
|
||||
"auth primitive 放在 registry/components/auth_*/;不需要另建 worker 目錄"
|
||||
fi
|
||||
|
||||
# 禁止建立同名零件的平行目錄
|
||||
if echo "$CMD" | grep -qE "mkdir.*/(gmail|telegram|google[-_]sheets|line[-_]notify|http[-_]request)[-_](v2|v3|new|worker|backup)"; then
|
||||
block "3.3" \
|
||||
"禁止為既有零件建立平行目錄(v2/new/worker/backup)" \
|
||||
"直接改 registry/components/<n>/main.go"
|
||||
fi
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 規則 1.3:禁止 wrangler init / generate auth-* credential-* jwt-*
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
if echo "$CMD" | grep -qE "wrangler[[:space:]]+(init|generate).*[[:space:]](auth|credential|jwt|oauth)[-_]"; then
|
||||
block "1.3" \
|
||||
"禁止用 wrangler init/generate 建立 auth/credential/jwt Worker" \
|
||||
"auth primitive 透過 component-worker-template/ 搭配 WASM binary 部署,不要 wrangler init"
|
||||
fi
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 規則 3.1:Service Binding 新增警示
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 偵測在 wrangler.toml 新增 [[services]] 的 echo/cat/sed 操作(非 100% 準確,但夠用)
|
||||
if echo "$CMD" | grep -qE "echo.*\[\[services\]\].*>>"; then
|
||||
block "3.1" \
|
||||
"偵測到要在 wrangler.toml 新增 [[services]] binding" \
|
||||
"零件串接一律走 HTTP URL(cypher binding),不新增 service binding。若有特殊需求,先與 richblack 確認"
|
||||
fi
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 一般性危險指令
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
if echo "$CMD" | grep -qE "rm[[:space:]]+-rf[[:space:]]+(/|/\*|~|\\\$HOME|\.)"; then
|
||||
block "general" \
|
||||
"偵測到危險的 rm -rf 指令" \
|
||||
"明確指定要刪的目錄,不要對根目錄 / home / 當前目錄遞迴刪除"
|
||||
fi
|
||||
|
||||
# 禁止 force push 到 main
|
||||
if echo "$CMD" | grep -qE "git[[:space:]]+push.*--force.*(main|master)"; then
|
||||
block "general" \
|
||||
"禁止 force push 到 main/master" \
|
||||
"用 feature branch,或和 richblack 確認後手動操作"
|
||||
fi
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 資料外流警示(data-exfil-warning SDD R2):AI 動手把資料變成可被外部呼叫前先擋
|
||||
# `acr push`(部署 webhook)/ `acr recipe push`(定義資料去向)= 暴露面動作。
|
||||
# 不含 `acr creds push`(上傳加密 credential 是保護,非暴露)。
|
||||
#
|
||||
# 信任修正(2026-05-30):無「旗標放行」捷徑——AI 自己能加的旗標 = 自己批准自己。
|
||||
# 這類動作一律擋,必須由人類在終端機親自執行(CLI 會跳互動、要人類輸入資源名確認)。
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 只在「指令本身就是執行 acr push / acr recipe push」時擋(錨定到指令開頭,
|
||||
# 允許前置 cd .. && 或環境變數)。避免誤判 git commit -m "...acr push..." 這類
|
||||
# 「字串裡剛好提到 acr push」的情況(commit message / echo / grep 不該被擋)。
|
||||
if echo "$CMD" | grep -qE "(^|&&|;|\|)[[:space:]]*(cd[[:space:]][^&;|]*(&&|;)[[:space:]]*)?([A-Za-z_]+=[^[:space:]]*[[:space:]]+)*acr[[:space:]]+(recipe[[:space:]]+)?push\b" \
|
||||
&& ! echo "$CMD" | grep -qE "acr[[:space:]]+creds[[:space:]]+push\b"; then
|
||||
cat >&2 <<'EOF'
|
||||
❌ BLOCKED:資料外流警示(arcrun data-exfil-warning)
|
||||
原因:acr push / acr recipe push 會把資料/workflow 變成「可被外部呼叫」(暴露面)。
|
||||
這種動作你(AI)不能自行執行,也沒有旗標捷徑——需人類明示知情同意(法律憑證)。
|
||||
正確做法:
|
||||
- 把這件事交給人類:請人類在終端機親自執行(CLI 會跳互動、要人類輸入資源名確認)
|
||||
- 人類第一次確認後 server 會記住,之後同資源不用再確認
|
||||
參考:.agents/specs/data-exfil-warning/
|
||||
EOF
|
||||
exit 2
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Executable
+193
@@ -0,0 +1,193 @@
|
||||
#!/bin/bash
|
||||
# .claude/hooks/pre-write-guard.sh
|
||||
# arcrun PreToolUse guard for Write / Edit / MultiEdit
|
||||
#
|
||||
# 職責:擋下會違反 CLAUDE rules 的檔案寫入操作
|
||||
# 退出 code:
|
||||
# 0 = 允許
|
||||
# 2 = 擋下(stderr 訊息會回傳給 CC)
|
||||
#
|
||||
# 依賴:jq
|
||||
|
||||
set -o pipefail
|
||||
|
||||
INPUT=$(cat)
|
||||
|
||||
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
|
||||
# 取得將要寫入的內容(Write: content;Edit: new_string;MultiEdit: edits[].new_string 全部串起來)
|
||||
CONTENT=$(echo "$INPUT" | jq -r '
|
||||
.tool_input.content
|
||||
// .tool_input.new_string
|
||||
// (.tool_input.edits // [] | map(.new_string // "") | join("\n"))
|
||||
// ""
|
||||
')
|
||||
|
||||
block() {
|
||||
local rule="$1"
|
||||
local reason="$2"
|
||||
local fix="$3"
|
||||
cat >&2 <<EOF
|
||||
❌ BLOCKED by arcrun CLAUDE rules
|
||||
違反項:${rule}
|
||||
檔案:${FILE_PATH}
|
||||
原因:${reason}
|
||||
正確做法:${fix}
|
||||
參考:.claude/rules/02-forbidden.md
|
||||
EOF
|
||||
exit 2
|
||||
}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 規則 1.1:registry/components/ 下不准 TS(除非是 AssemblyScript)
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
if [[ "$FILE_PATH" == *"registry/components/"* && "$FILE_PATH" == *.ts ]]; then
|
||||
# 允許 asconfig.json 同目錄的 AssemblyScript
|
||||
COMP_DIR=$(dirname "$FILE_PATH")
|
||||
if [[ ! -f "$COMP_DIR/asconfig.json" ]]; then
|
||||
block "1.1" \
|
||||
"registry/components/ 下禁止 TypeScript(除非是 AssemblyScript 且同目錄有 asconfig.json)" \
|
||||
"零件必須用 TinyGo (main.go) 或 AssemblyScript 實作並編譯成 .wasm"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 規則 1.2:禁止在非法位置新增 auth/credential 實作
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 合法位置:registry/components/auth_static_key | auth_oauth2 | auth_service_account | auth_mtls
|
||||
if [[ "$FILE_PATH" =~ auth[-_](static[-_]key|oauth2|service[-_]account|mtls) ]]; then
|
||||
if [[ "$FILE_PATH" != *"registry/components/auth_"* ]]; then
|
||||
block "1.2" \
|
||||
"auth primitive 實作只能放在 registry/components/auth_<type>/" \
|
||||
"改去 registry/components/auth_static_key/ 等目錄,用 TinyGo 實作 main.go"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 規則 2.1:禁止新增含特定關鍵字的 TS 檔案(credential-injector / jwt-signer 等)
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
if [[ "$FILE_PATH" == *.ts ]]; then
|
||||
BASE=$(basename "$FILE_PATH")
|
||||
# 既有的 credential-injector.ts / jwt-signer.ts 允許修改(為了刪除),但不准新增同名
|
||||
if [[ "$BASE" =~ ^(credential[-_]injector|jwt[-_]signer)\.ts$ ]]; then
|
||||
if [[ ! -f "$FILE_PATH" ]]; then
|
||||
block "2.1" \
|
||||
"禁止新增 ${BASE}(Phase 1-3 的目標是刪除此類檔案,不是重建)" \
|
||||
"credential 注入 / JWT signing 屬於 WASM 零件職責,改去 registry/components/auth_*/"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 規則 2.2:cypher-executor TS 裡不准實作業務邏輯(只准 wasi-shim.ts 做 crypto)
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
if [[ "$FILE_PATH" == *"cypher-executor/src/"* && "$FILE_PATH" == *.ts ]]; then
|
||||
BASE=$(basename "$FILE_PATH")
|
||||
|
||||
# crypto.subtle.decrypt:只准在 wasi-shim.ts
|
||||
if echo "$CONTENT" | grep -qE "crypto\.subtle\.decrypt"; then
|
||||
if [[ "$BASE" != "wasi-shim.ts" ]]; then
|
||||
block "2.2" \
|
||||
"AES-GCM 解密(crypto.subtle.decrypt)只准出現在 wasi-shim.ts 的 crypto_decrypt host function" \
|
||||
"把解密邏輯移到 wasi-shim.ts 的 host function;或讓 WASM 零件透過 u6u.crypto_decrypt 呼叫"
|
||||
fi
|
||||
fi
|
||||
|
||||
# crypto.subtle.sign with RSASSA:只准在 wasi-shim.ts
|
||||
if echo "$CONTENT" | grep -qE "crypto\.subtle\.sign.*RSASSA"; then
|
||||
if [[ "$BASE" != "wasi-shim.ts" ]]; then
|
||||
block "2.2" \
|
||||
"RS256 簽章只准出現在 wasi-shim.ts 的 crypto_sign_rs256 host function" \
|
||||
"把簽章移到 wasi-shim.ts;或讓 auth_service_account WASM 透過 u6u.crypto_sign_rs256 呼叫"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Template 展開:{{secret.X}} 或 {{runtime.X}} 屬於 WASM 職責
|
||||
# 例外:auth-recipe-seeds.ts 是 recipe 資料定義(會被序列化寫進 RECIPES KV),
|
||||
# 其中的 {{secret.X}} / {{runtime.X}} 是「資料字面值」而非 TS 展開邏輯,
|
||||
# 真正的展開仍在 WASM auth primitive 內完成。
|
||||
if [[ "$BASE" != "auth-recipe-seeds.ts" ]] && echo "$CONTENT" | grep -qE "\{\{(secret|runtime)\." ; then
|
||||
block "2.2" \
|
||||
"Template 展開({{secret.X}} / {{runtime.X}})屬於 WASM auth primitive 職責" \
|
||||
"把這段邏輯改寫到 registry/components/auth_static_key/main.go(TinyGo)"
|
||||
fi
|
||||
|
||||
# Hard-code 的 BUILTIN_API_RECIPES / BUILTIN_CREDENTIALS_MAP 新增
|
||||
if echo "$CONTENT" | grep -qE "(BUILTIN_API_RECIPES|BUILTIN_CREDENTIALS_MAP)\s*[:=]"; then
|
||||
# 允許「把它設成空物件」或「刪除」,但不准新增實作
|
||||
if echo "$CONTENT" | grep -qE "BUILTIN_API_RECIPES.*=.*\{\s*[a-zA-Z]"; then
|
||||
block "2.2" \
|
||||
"禁止在 TS 裡新增 BUILTIN_API_RECIPES / BUILTIN_CREDENTIALS_MAP 實作" \
|
||||
"API 呼叫邏輯屬於各自的 WASM 零件(gmail.wasm / telegram.wasm 等),cypher-executor 只做 routing"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Hard-code API endpoint 實作
|
||||
HARDCODED_APIS=(
|
||||
"gmail\.googleapis\.com/gmail/v1/users/me/messages/send"
|
||||
"api\.telegram\.org/bot.*sendMessage"
|
||||
"sheets\.googleapis\.com/v4/spreadsheets"
|
||||
"notify-api\.line\.me/api/notify"
|
||||
)
|
||||
for PATTERN in "${HARDCODED_APIS[@]}"; do
|
||||
if echo "$CONTENT" | grep -qE "$PATTERN"; then
|
||||
# 允許 wasi-shim.ts 裡的 http_request host function(它只是 proxy)
|
||||
if [[ "$BASE" != "wasi-shim.ts" ]]; then
|
||||
block "2.2" \
|
||||
"禁止在 cypher-executor TS 裡 hard-code API endpoint(偵測到: $PATTERN)" \
|
||||
"把 API 呼叫移到對應的 WASM 零件(registry/components/gmail/main.go 等)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# exchangeGoogleJwt / 類似 token exchange function
|
||||
if echo "$CONTENT" | grep -qE "(exchangeGoogleJwt|exchangeServiceAccountJwt|signGoogleJwt)"; then
|
||||
if [[ "$BASE" != "wasi-shim.ts" ]]; then
|
||||
block "2.2" \
|
||||
"Token exchange 邏輯屬於 auth_service_account WASM 零件" \
|
||||
"改到 registry/components/auth_service_account/main.go"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 規則 3.3:禁止建立 *-v2 / new-* / *-worker 類複製貼上目錄
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
if [[ "$FILE_PATH" =~ /(auth|credential|jwt|oauth|gmail|telegram|google-sheets|line-notify|http-request)[-_](v2|v3|new|worker|backup|temp)/ ]]; then
|
||||
block "3.3" \
|
||||
"禁止為同一零件建立平行目錄(v2/new/worker/backup 等)" \
|
||||
"直接修改 registry/components/<name>/main.go 即可;需要版本管理請用 git branch"
|
||||
fi
|
||||
if [[ "$FILE_PATH" =~ /new-(auth|credential|jwt|oauth|gmail|telegram)/ ]]; then
|
||||
block "3.3" \
|
||||
"禁止為同一零件建立 new-<name>/ 平行目錄" \
|
||||
"直接修改 registry/components/<name>/main.go"
|
||||
fi
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 規則 4.3:禁止自行在 .agents/specs/ 下建新 SDD 目錄
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
if [[ "$FILE_PATH" == *".agents/specs/"* ]]; then
|
||||
# 檢查是否在已知 SDD 目錄內
|
||||
KNOWN_SDDS=(
|
||||
".agents/specs/arcrun"
|
||||
".agents/specs/u6u-core-mvp"
|
||||
".agents/specs/u6u-platform-evolution"
|
||||
".agents/specs/component-registry-canon"
|
||||
".agents/specs/component-gatekeeping" # 2026-05-29 richblack 確認新建(Phase 3 把關)
|
||||
".agents/specs/data-exfil-warning" # 2026-05-30 richblack 確認新建(資料外流警示)
|
||||
)
|
||||
IN_KNOWN=false
|
||||
for K in "${KNOWN_SDDS[@]}"; do
|
||||
if [[ "$FILE_PATH" == *"$K/"* ]]; then
|
||||
IN_KNOWN=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "$IN_KNOWN" == "false" ]]; then
|
||||
block "4.3" \
|
||||
"禁止自行在 .agents/specs/ 下建立新的頂層 SDD 目錄" \
|
||||
"先與 richblack 確認 SDD 範圍。若是現有 SDD 的補充檔案,請放到已知 SDD 目錄下"
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Executable
+73
@@ -0,0 +1,73 @@
|
||||
#!/bin/bash
|
||||
# .claude/hooks/session-start-load-sdd.sh
|
||||
# arcrun SessionStart hook
|
||||
#
|
||||
# 職責:session 啟動時注入當前進度、絕對禁令、SDD 位置,避免 CC 靠記憶猜測
|
||||
# 輸出走 stdout,會注入到 CC 的 context
|
||||
|
||||
set -o pipefail
|
||||
|
||||
cat <<'EOF'
|
||||
============================================================
|
||||
🚨 arcrun 工作規範(SessionStart 注入)
|
||||
============================================================
|
||||
|
||||
📌 絕對禁令(違反會被 pre-write / pre-bash hook 直接 block):
|
||||
|
||||
1. registry/components/ 下禁止 TypeScript 實作零件
|
||||
→ 只能 TinyGo (main.go) 或 AssemblyScript,編譯成 .wasm
|
||||
|
||||
2. cypher-executor TS 裡禁止實作 credential/auth/JWT 業務邏輯
|
||||
→ crypto.subtle.decrypt / sign 只准出現在 wasi-shim.ts 的 host function
|
||||
→ {{secret.X}} template 展開屬於 WASM 零件職責
|
||||
→ 禁止 hard-code gmail/telegram/sheets API endpoint
|
||||
|
||||
3. 禁止新增 Service Binding 綁零件
|
||||
→ 零件串接走 HTTP URL(cypher binding = YAML 裡的 URL 清單)
|
||||
→ Cypher binding 不是 Cloudflare 的 binding 機制
|
||||
|
||||
4. 每個 WASM 零件 = 獨立 Worker = 公開 URL
|
||||
→ 不是從 R2 動態讀(平台零件已 bundle 進各自 Worker)
|
||||
→ R2 只用於 Phase 5 的用戶自製零件(未啟用)
|
||||
|
||||
📋 任何 code 變動前,必須:
|
||||
|
||||
1. 讀 .agents/specs/arcrun/arcrun.md(總進度)
|
||||
2. 讀對應 task 的 SDD(design.md + tasks.md)
|
||||
3. 在回覆開頭宣告(格式見 .claude/rules/00-sdd-protocol.md):
|
||||
📋 已讀 SDD:<檔案清單>
|
||||
🎯 本次對應 task:<task 編號>
|
||||
📐 本次 task 的 SDD 規範摘要:<重點>
|
||||
🚧 執行範圍:修改/建立/刪除 <檔案>
|
||||
4. 每完成一個 task,立刻更新 tasks.md 的 [x],不批次
|
||||
|
||||
🔥 當前進行中 Phase:Credential Primitives TS → WASM
|
||||
|
||||
SDD:.agents/specs/arcrun/credential-primitives-wasm/
|
||||
已完成:Phase 0.1-0.5(核心合併 + u6u-core 刪除)
|
||||
未完成硬前置:
|
||||
- Phase 0.6 wasi-shim 加 host functions(kv_get / crypto_decrypt / crypto_sign_rs256)
|
||||
- Phase 0.7 component-loader WASM runner 路徑
|
||||
未完成主要任務:
|
||||
- Phase 1 auth_static_key WASM 零件(TinyGo)
|
||||
- Phase 2 auth_service_account WASM 零件
|
||||
- Phase 3 刪除 cypher-executor 的三套違規 TS:
|
||||
* src/actions/credential-injector.ts(整檔刪)
|
||||
* src/lib/jwt-signer.ts(整檔刪)
|
||||
* src/lib/component-loader.ts 的 BUILTIN_API_RECIPES + BUILTIN_CREDENTIALS_MAP(整段刪)
|
||||
|
||||
⛔ 封測狀態:推遲(richblack 2026-04-19 決定)
|
||||
原因:違規 TS 未清,不封測。
|
||||
|
||||
📚 詳細規範:
|
||||
.claude/rules/00-sdd-protocol.md — SDD 協議
|
||||
.claude/rules/01-tech-stack.md — 技術棧硬限制
|
||||
.claude/rules/02-forbidden.md — 禁止清單(hook 強制)
|
||||
.claude/rules/03-component-architecture.md — 零件架構(R2/cypher binding/service binding 的正確定義)
|
||||
.claude/rules/04-current-progress.md — 當前進度 + SDD 索引
|
||||
.claude/rules/06-mindset.md — mindset(為什麼層):工作流是default/零件稀有/AI→工具/誠實不假綠
|
||||
|
||||
============================================================
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
# .claude/hooks/stop-check-sync.sh
|
||||
# arcrun Stop hook
|
||||
#
|
||||
# 職責:session 結束前檢查 code 變動是否有對應的 SDD / tasks.md 更新
|
||||
# 退出 code:不 block,只警告
|
||||
|
||||
set -o pipefail
|
||||
|
||||
# 檢查 .agents/specs 下本次 session 是否有變動
|
||||
SPECS_DIFF=$(git -C "$(pwd)" status --porcelain -- '.agents/specs/' 2>/dev/null | head -20)
|
||||
CODE_DIFF=$(git -C "$(pwd)" status --porcelain -- '*.go' '*.ts' '*.tsx' '*.py' 'cypher-executor/' 'registry/' 'cli/' 2>/dev/null | head -20)
|
||||
|
||||
if [[ -n "$CODE_DIFF" && -z "$SPECS_DIFF" ]]; then
|
||||
cat >&2 <<EOF
|
||||
|
||||
⚠️ Stop hook 警告(by arcrun hook)
|
||||
|
||||
偵測到本 session 有程式碼變動,但 .agents/specs/ 下的 SDD 文件沒有任何變動。
|
||||
|
||||
未 commit 的程式碼變動:
|
||||
$(echo "$CODE_DIFF" | head -10)
|
||||
|
||||
請在結束前確認:
|
||||
1. 對應的 tasks.md 是否已更新 [x]?
|
||||
2. 是否有架構變動需要更新 design.md?
|
||||
3. 是否有 SDD 範圍外的 change 未標記?
|
||||
|
||||
SDD 協議要求:code 和 SDD 必須同步更新。
|
||||
參考:.claude/rules/00-sdd-protocol.md
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
# 若有暫存的 tasks.md 變動,提醒 commit
|
||||
TASKS_DIFF=$(git -C "$(pwd)" status --porcelain -- '.agents/specs/**/tasks.md' 2>/dev/null | head -5)
|
||||
if [[ -n "$TASKS_DIFF" ]]; then
|
||||
cat >&2 <<EOF
|
||||
|
||||
📝 提醒:tasks.md 有未 commit 的變動
|
||||
$(echo "$TASKS_DIFF")
|
||||
記得在結束前 commit。
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user