Files
ISEP/hooks/session-start-recall.sh
T
Leo c2638668e3 ISEP 0.1.0:環境設定收成一個 plugin,本機與雲端共用一份
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>
2026-08-20 11:41:46 +08:00

153 lines
9.4 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# SessionStart hook — 開 session 就把「全局」推到眼前(InkStoneCo#17 / D69 / D70 / D71
#
# 掛在 settings.json 的 SessionStartmatcher: startup|resume|clear)。stdout 會被當成 context 注入。
#
# ── 這支在整個機制裡的位置(leo 2026-08-11 拍板)─────────────────────────────
# 算 雲端的 Arcrun 工作流 `global_index`(讀 Gitea 五個 repo 的票 + 讀 KBDB 藏書地圖)
# 存 = 雲端(總圖住雲端,不推回地端;沒有東西需要同步,所以沒有漂移源)
# 拿 = 本檔。**由機制保證取一次**,不靠 AI 記得去打 MCP
# openhuman SuperContext 的教訓:靠模型自己選擇要不要查,就是會漏)
#
# ⚠️ 例外=下面 push 2/5 的「各 repo wiki 全景」:那段**算在地端**。
# 不是不想放雲端,是雲端拿不到 repo 樹(只有 API 列檔一條路,撞 principles 紅線)。
#
# ── 為什麼不再 cat status.md ────────────────────────────────────────────────
# 2026-08-11 實測:舊版這支吐 235,880 bytes(因為它 cat 整份 216 KB 的落帳流水),
# 真正進到 context 的只有 2 KB 預覽 + 一個要自己去 Read 的檔名。
# ⇒ 「開場就知道」等於沒發生。**注入通道的預算是有限的,落帳流水不該佔著它。**
# 進度/狀態一律去 Gitea(D52 + D72),不在地端養第二份會漂的快照。
#
# 順序=重要性:全局總圖最前面(它最可能被截斷保護到),其次原則,最後踩坑標題。
set -euo pipefail
GLOBAL_INDEX_URL="https://arcrun-cypher-executor.leo21c.workers.dev/webhooks/named/leo/global_index/query"
PANORAMA_FILE="system-dev/wiki/PANORAMA.md"
PRINCIPLES_FILE="system-dev/wiki/principles.md"
MISTAKES_FILE="system-dev/wiki/mistakes.md"
MISTAKES_TAIL=20 # 只推最近 N 條標題(全份 96 條/11 KB 會吃掉總圖的預算)
# ── push 1/5:全局總圖(雲端現算)────────────────────────────────────────────
# 降級規格(D71,票與知識不對稱):
# 算得出來 → 注入
# 算不出來/破損/空 → **完全不注入內容**,只誠實說一句「這次沒有」
# (寧可冷啟動,不要注入垃圾;票尤其不能給一份看起來像現況的舊東西)
GLOBAL_MD=""
GLOBAL_ERR=""
if RESP=$(curl -sS -m 45 -X POST "$GLOBAL_INDEX_URL" \
-H 'Content-Type: application/json' -d '{}' 2>/dev/null); then
GLOBAL_MD=$(printf '%s' "$RESP" | python3 -c '
import sys, json
try:
d = json.load(sys.stdin)
except Exception:
sys.exit(0)
def find_md(x, depth=0):
# 工作流的最終輸出可能被包一層 data(code 零件的回應信封),兩種形狀都收
if depth > 3 or not isinstance(x, dict):
return None
if x.get("success") is True and isinstance(x.get("md"), str) and x["md"].strip():
return x["md"]
return find_md(x.get("data"), depth + 1)
md = find_md(d)
if md:
sys.stdout.write(md)
' 2>/dev/null || true)
if [ -z "$GLOBAL_MD" ]; then
GLOBAL_ERR=$(printf '%s' "$RESP" | python3 -c '
import sys, json
try:
d = json.load(sys.stdin)
except Exception:
sys.stdout.write("回應不是 JSON"); sys.exit(0)
sys.stdout.write(str((d or {}).get("error") or "工作流沒有交出 md")[:200])
' 2>/dev/null || echo "回應解析失敗")
fi
else
GLOBAL_ERR="連不上雲端(curl 失敗或逾時 45 秒)"
fi
echo "════════════════════════════════════════════════"
if [ -n "$GLOBAL_MD" ]; then
printf '%s\n' "$GLOBAL_MD"
else
echo "⚠️ 這次拿不到全局總圖:${GLOBAL_ERR}"
echo " 刻意不給你一份舊的——票的狀態放舊的比沒有更危險(會去重做已經做完的事)。"
echo " ⇒ 你現在**不知道有哪些票、庫裡有哪些知識**。動手前先自己撈:"
echo " GiteaGET https://git.uncle6.me/api/v1/repos/Leo/<repo>/issues?state=open"
echo " (五個 repoInkStoneCo / Arcrun / arcrun-rag / mira / system-dev-template"
echo " 知識:kbdb_get_map()"
echo " 修這條管路:工作流 leo:wf:global_index(雲端),本 hook 只負責取來印。"
fi
echo "════════════════════════════════════════════════"
echo ""
# ── push 2/5:各 repo 的 wiki 全景(leo 2026-08-12「一次看到全景」的另一半)──
# 上面那段是**票**(雲端現算)+ KBDB 藏書地圖;這段是**各 repo 真正的 wiki**。
# 為什麼不塞進雲端那支工作流:工作流跑在 Cloudflare 上,要拿 repo 樹只有
# 「Gitea contents API 列檔」一條路,而 principles 紅線寫死
# 「讀 repo 走 git clone/fetch,不走 API 列檔」。
# ⇒ 在有 git 的地方算好(`scripts/wiki-panorama.sh`,人發起、不輪詢),
# 存成 repo 裡的一份 md,本檔只負責印。
# 只印到 `panorama:inject-end` 為止——標記以下是給 grep 的完整卡片清單,
# 全倒進來會撐爆 context(全檔 ~28 KB,注入段 ~6 KB)。
if [ -f "$PANORAMA_FILE" ]; then
echo "════════════════════════════════════════════════"
awk '/panorama:inject-end/{exit} {print}' "$PANORAMA_FILE"
# 過期就講出來(不自動重算:重算要連網 clone 十幾個 repo,不該卡在開場)
P_GEN=$(grep -m1 -oE '[0-9]{4}-[0-9]{2}-[0-9]{2} 產生' "$PANORAMA_FILE" | cut -d' ' -f1 || true)
W_LAST=$(git log -1 --format=%ad --date=short -- system-dev/wiki 2>/dev/null || true)
if [ -n "$P_GEN" ] && [ -n "$W_LAST" ] && [ "$W_LAST" \> "$P_GEN" ]; then
echo ""
echo "⚠️ 這張全景圖是 ${P_GEN} 算的,但 wiki 在 ${W_LAST} 又被改過 ⇒ 它已經不準了。"
echo " 重算:bash scripts/wiki-panorama.sh --write"
fi
echo "════════════════════════════════════════════════"
echo ""
else
echo "────────────────────────────────────────────────"
echo "⚠️ 沒有各 repo 的 wiki 全景圖($PANORAMA_FILE)⇒ 你**不知道哪些知識記在哪個 repo**。"
echo " 產生(約一分鐘,git clone 各 repo 的 wiki 目錄,不走 API):"
echo " bash scripts/wiki-panorama.sh --write"
echo ""
fi
# ── push 3/5:進度不在地端(D72)────────────────────────────────────────────
echo "────────────────────────────────────────────────"
echo "📍 進度/狀態一律去 Gitea 撈,不要在任何檔案裡找(D52 + D72)"
echo " 等 leo labels=s/stage 可開工 s/todo 進行中 s/doing"
echo " 知識庫(system-dev/wiki/)只放**事實**:踩過的坑、決策、憑證在哪。**不放進度**。"
echo " 🔴 不要在對話或任何檔案裡另養一份「等 leo 的清單」——它一定會漂。"
echo ""
# ── push 4/5principles(全文,行動前必服從)────────────────────────────────
if [ -f "$PRINCIPLES_FILE" ] && grep -q '^- ' "$PRINCIPLES_FILE" 2>/dev/null; then
echo "════════════════════════════════════════════════"
echo "📐 設計原則(行動前必服從,來自 principles.md"
echo "════════════════════════════════════════════════"
grep '^- ' "$PRINCIPLES_FILE"
P_COUNT=$(grep -c '^- ' "$PRINCIPLES_FILE")
if [ "$P_COUNT" -gt 15 ]; then
echo ""
echo "(⚠️ principles 已 ${P_COUNT} 條 > 15:請考慮合併相近原則、或把較細的下放成 card)"
fi
echo ""
fi
# ── push 5/5mistakes(只推最近 N 條標題)──────────────────────────────────
if [ -f "$MISTAKES_FILE" ] && grep -q 'MISTAKE' "$MISTAKES_FILE" 2>/dev/null; then
M_TOTAL=$(grep -cE 'MISTAKE' "$MISTAKES_FILE")
echo "────────────────────────────────────────────────"
echo "⚠️ 已知踩坑:最近 ${MISTAKES_TAIL} 條(全部 ${M_TOTAL} 條在 $MISTAKES_FILE,撞到就 grep 全文)"
grep -E 'MISTAKE' "$MISTAKES_FILE" | tail -n "$MISTAKES_TAIL" | sed 's/^/ /'
echo ""
fi
echo "────────────────────────────────────────────────"
echo "以上是 index,不是內容——它只讓你知道「有這件事、去哪裡找」。"
echo "要完整脈絡(decisions / mistakes / SDD)→ 執行 /wiki-recall"
echo "════════════════════════════════════════════════"
exit 0