67f5f0fa5e
leo 2026-08-27:「現在每天都在追新的,所以要用 Routine 去消化舊的,可以有多個條件」
兩條線各用各的判準(他當場訂正的那件事):
緊急線=掛 open milestone 的,用「距離目標的遠近」排
還債線=沒掛的那 188 張,用多條件排(事故/擋人/承諾/票齡/估工)← 本次做的
新增 scripts/debt-worklist(list/claim/forget):
· 撈全 org 15 個 repo 的 open issue + open PR,逐一列出當作「我查了哪些」的證明
· 扣掉掛 open milestone 的(緊急線在管)、等 leo 的(Human/human-exec/s/stage,
那些要催不是要領,催辦是 inkstone/ISEP#93)、已領走的
· 每張票旁邊印出「為什麼排這裡」的分項,排錯可以指著某一項說它給太多
· 成包只認強訊號:互相指著、或 Gitea 原生相依(母子票)。
第一版用單向引用成包,190 張裡 121 張黏成一坨——一包沒有人領得動
· 空清單會明講「查詢跑過了,結果是零」,不默默結束
· claim 之後那些票不再出現在清單上,並在隔天的清單頂端交代它們關了沒
hooks/session-start-recall.sh 加一段(不打網路,只看狀態檔日期):
今天還沒撈過就說一句,並給出要跑的那一行。開 session 自動去撈=輪詢,紅線擋著。
測試 scripts/test-debt-worklist.sh:40 條全離線,票上四條驗收條件各一組。
真實資料唯讀實跑過:229 張 → 可領 188 張/185 包,領走兩張後隔天清單少掉它們。
180 lines
11 KiB
Bash
Executable File
180 lines
11 KiB
Bash
Executable File
#!/bin/bash
|
||
# SessionStart hook — 開 session 就把「全局」推到眼前(InkStoneCo#17 / D69 / D70 / D71)
|
||
#
|
||
# 掛在 settings.json 的 SessionStart(matcher: 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 " Gitea:GET https://git.uncle6.me/api/v1/repos/Leo/<repo>/issues?state=open"
|
||
echo " (五個 repo:InkStoneCo / 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/5:principles(全文,行動前必服從)────────────────────────────────
|
||
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/5:mistakes(只推最近 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
|
||
|
||
# ── push 6:還債線今天撈過了沒(inkstone/ISEP#83)──────────────────────────
|
||
# 🔴 **這裡不打網路、不撈票**——只看狀態檔的日期,講一句話。
|
||
# 要真的撈是人(或這個 session)自己跑那一行;SessionStart 只負責讓它被想起來。
|
||
# 「每天都在追新的,所以要用 Routine 去消化舊的」(leo 2026-08-27)——
|
||
# 沒有這一句,沒掛 milestone 的那 170 多張永遠不會被任何人拿起來。
|
||
DEBT_STATE="${ISEP_DEBT_STATE_DIR:-$HOME/.claude/isep-debt}/claimed.json"
|
||
DEBT_LINE=$(python3 - "$DEBT_STATE" <<'PY' 2>/dev/null || true
|
||
import json, sys, datetime
|
||
try:
|
||
d = json.load(open(sys.argv[1]))
|
||
except Exception:
|
||
d = {}
|
||
last = (d.get("last_run") or "")[:10]
|
||
today = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d")
|
||
n = len(d.get("claims") or {})
|
||
if last == today:
|
||
print(f"✅ 今天撈過了(手上領著 {n} 張)")
|
||
else:
|
||
print("🔴 今天還沒撈過還債清單" + (f"(手上還領著 {n} 張沒關)" if n else ""))
|
||
PY
|
||
)
|
||
echo "────────────────────────────────────────────────"
|
||
echo "🧾 還債線(inkstone/ISEP#83):${DEBT_LINE:-🔴 今天還沒撈過還債清單}"
|
||
echo " 撈一次 = python3 ${CLAUDE_PLUGIN_ROOT:-.}/scripts/debt-worklist list"
|
||
echo " 它排的是「沒掛 milestone 的舊票」——掛著的歸緊急線(milestone)管,兩條線不互搶。"
|
||
echo ""
|
||
|
||
echo "────────────────────────────────────────────────"
|
||
echo "以上是 index,不是內容——它只讓你知道「有這件事、去哪裡找」。"
|
||
echo "要完整脈絡(decisions / mistakes / SDD)→ 執行 /wiki-recall"
|
||
echo "════════════════════════════════════════════════"
|
||
|
||
exit 0
|