From 27c207c3e9d1845c3798acbab3b4cf84fa0bbf54 Mon Sep 17 00:00:00 2001 From: richblack Date: Tue, 21 Jul 2026 11:59:21 +0800 Subject: [PATCH] =?UTF-8?q?feat(1.17.0):=20=E6=9F=A5=E8=A9=A2=E4=B8=80?= =?UTF-8?q?=E5=BE=8B=E5=BE=9E=E6=9C=80=E5=BC=B7=E6=9F=A5=E6=B3=95=E9=96=8B?= =?UTF-8?q?=E5=A7=8B=EF=BC=88=E8=AA=9E=E6=84=8F=E2=86=92=E9=97=9C=E9=8D=B5?= =?UTF-8?q?=E5=AD=97=E2=86=92grep=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit leo:「它一定是用最好的搜尋,如果沒有才 fallback,但那不是你要指定的。」 事故:查 CF git 託管只用 grep→零命中→結論「沒查過/申請表沒送」=指控 leo 沒做他早就做過的事。同一問題跑語意搜尋第一筆就命中(0.858), 帶出三元組「Artifacts >> 若提供 git 倉庫則可取代 >> Gitea」,leo 15 天前就記了。 根因不是關鍵字選錯,是用了三種查詢裡最弱的那種。 grep 要求先猜對詞;語意搜尋不需要。 - subagent 注入改分級查法(語意/關鍵字/grep) - wiki-first-search:grep 零命中不再靜默退出(那正是最該用語意的時刻); 有命中也明說「最弱查法、搜尋詞是猜的,請補語意搜尋」 Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 24 ++++++++++++++++ template/.claude/VERSION | 2 +- template/.claude/hooks/subagent-wiki-guard.sh | 28 +++++++++++++++++-- template/.claude/hooks/wiki-first-search.sh | 26 ++++++++++++++++- template/system-dev/VERSION | 2 +- 5 files changed, 77 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fae318b..ccfcb62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,30 @@ --- +## 1.17.0 — 查詢一律從最強的查法開始(語意 → 關鍵字 → grep) + +**leo 2026-07-21**:「它一定是用最好的搜尋,如果沒有才 fallback, +**但那不是你要指定的**——對搜尋者來說,我就是要去搜尋,如果你沒這個機制才降。」 + +**事故**:查「CF 上的 git 託管」時只用 grep,搜 Gitea/freeze 等字面詞 → 零命中, +結論寫成「這件事沒查過、申請表沒送」=指控負責人沒做他早就做過的事。 +事後用**同一個問題**跑語意搜尋,**第一筆就命中**(score 0.858): +「Cloudflare Artifacts:假設內建 git 倉庫機制的 CF 功能,成立則可全 CF 化」, +還帶出三元組「Artifacts >> 若提供 git 倉庫則可取代 >> Gitea」——負責人 15 天前就記了。 + +**根因不是「關鍵字選錯」,是「用了三種查詢裡最弱的那種」**—— +grep 只認字面,**要求你先猜對那個詞**;語意搜尋不需要你猜對。 + +修正: +- `subagent-wiki-guard`:注入的指示改為**分級查法**—— + ①語意搜尋(`kbdb_search mode=semantic`,用自然語言問句)②關鍵字 ③grep(最後手段) +- `wiki-first-search`:① **grep 零命中不再靜默退出**(那正是最該改用語意搜尋的時刻, + 查不到 ≠ 沒記載,只代表沒猜中用詞)② 有命中時明說「這是最弱的查法、 + 搜尋詞是猜的,重要判斷請補語意搜尋」 +- 兩處都附真實案例,讓讀到的人知道代價 + +--- + ## 1.16.1 — 補破口:wiki-first-search 漏掉 Bash(隔天就被自己繞過) **1.16.0 上線隔天即實證失效**:hook 只掛 `Grep|Glob|Read`,但「用 curl/wrangler diff --git a/template/.claude/VERSION b/template/.claude/VERSION index 41c11ff..092afa1 100644 --- a/template/.claude/VERSION +++ b/template/.claude/VERSION @@ -1 +1 @@ -1.16.1 +1.17.0 diff --git a/template/.claude/hooks/subagent-wiki-guard.sh b/template/.claude/hooks/subagent-wiki-guard.sh index 6819fb6..ac1360d 100755 --- a/template/.claude/hooks/subagent-wiki-guard.sh +++ b/template/.claude/hooks/subagent-wiki-guard.sh @@ -46,14 +46,38 @@ guidance = """【自動注入:查任何東西之前,先查 wiki】 你所在的 repo 有維護自己的 wiki(通常在 `system-dev/wiki/`,舊結構在 `.claude/wiki/`)。 **接到「查/盤點/核實/實作」類任務時,第一個動作是搜尋 wiki,不是翻程式碼。** -做法(30 秒,省下大量白工): - grep -rin "<本題關鍵字>" system-dev/wiki/ 2>/dev/null || grep -rin "<關鍵字>" .claude/wiki/ +🔴 **查法有強弱之分,一律從最強的開始——沒有那個能力才降級。** +(leo 2026-07-21:「它一定是用最好的搜尋,如果沒有才 fallback, + 但那不是你要指定的,對搜尋者來說,我就是要去搜尋,如果你沒這個機制才降。」) + + **① 語意搜尋(最強,優先)**——有 Arcrun RAG MCP 就用它,用**自然語言問句**,不是關鍵字: + kbdb_search(q="<用一句話描述你要找什麼>", mode="semantic") + 不確定該查哪個庫 → 先 kbdb_get_map() 看藏書地圖 + 要沿關係展開 → kbdb_graph_neighbors() + **② 關鍵字搜尋**——語意不可用時:kbdb_search(q="...", mode="keyword") + **③ grep(最弱,最後手段)**——連 MCP 都沒有時: + grep -rin "<關鍵字>" system-dev/wiki/ 2>/dev/null || grep -rin "<關鍵字>" .claude/wiki/ + +🔴 **為什麼順序是硬規定(2026-07-21 實際事故)**: + 查「CF 上的 git 託管」時只用了 grep,搜 Gitea/freeze/D43 等字面詞 → **零命中**, + 結論寫成「這件事沒查過、申請表沒送」。 + 事後用**同一個問題**跑語意搜尋,**第一筆就命中**(score 0.858): + 「Cloudflare Artifacts:假設內建 git 倉庫機制的 CF 功能,成立則可全 CF 化」, + 還帶出三元組「Cloudflare Artifacts >> 若提供 git 倉庫則可取代 >> Gitea」—— + **負責人 15 天前就記在筆記裡了。** + → **grep 只認字面,要求你先猜對那個詞;語意搜尋不需要你猜對。** + 用 grep 查不到 ≠ wiki 沒記載,只代表你沒猜中用詞。 + +🔴 **凡結論涉及「某人沒做某事」,回報前必須先用語意搜尋查該事的記載**—— + 這種結論錯了會變成**指控**,成本遠高於技術判斷錯誤。 為什麼這是划算的: • wiki 是前人已經查過、驗證過、被負責人糾正過的結論——**判準**。 • 程式碼與歷史文件是**稿子**:它反映「還沒清乾淨」,不等於「還在用」。 從稿子推論會系統性得出過時結論。 • wiki 沒記載,才值得花力氣翻原文。 + • **凡結論涉及「某人沒做某事」,回報前必須先 grep 該事在 wiki 的記載**—— + 這種結論錯了會變成指控,成本遠高於技術判斷錯誤。 三條硬規則: 1. **wiki 與程式碼衝突 → 以 wiki 為準**,並在回報中明確指出衝突, diff --git a/template/.claude/hooks/wiki-first-search.sh b/template/.claude/hooks/wiki-first-search.sh index 6d75785..8ba441b 100755 --- a/template/.claude/hooks/wiki-first-search.sh +++ b/template/.claude/hooks/wiki-first-search.sh @@ -69,7 +69,24 @@ esac # grep wiki(不分大小寫、含行號),最多 12 行避免洗版 HITS=$(grep -rin --include="*.md" -- "$QUERY" "$WIKI_DIR" 2>/dev/null | head -12 || true) -[ -z "$HITS" ] && exit 0 + +# 🔴 grep 零命中時**不能靜默退出**——那正是今天失敗的模式(2026-07-21): +# grep 查不到 → 以為 wiki 沒記載 → 結論「這件事沒查過」。 +# 但 grep 只認字面,查不到往往只代表「沒猜中用詞」。 +# → 零命中反而是**最該改用語意搜尋**的時刻,必須出聲。 +if [ -z "$HITS" ]; then + echo "════════════════════════════════════════════════" + printf '🔍 grep 在 wiki 找不到「%s」——但這**不代表沒記載**\n' "$QUERY" + echo "════════════════════════════════════════════════" + echo "grep 只認字面,查不到通常只是「沒猜中用詞」。**改用語意搜尋再確認一次**:" + echo " kbdb_search(q=\"<用一句話描述你要找什麼>\", mode=\"semantic\")" + echo " 不知道該查哪個庫 → kbdb_get_map()|要沿關係展開 → kbdb_graph_neighbors()" + echo "" + echo "實例:查「CF 上的 git 託管」時 grep 全零命中,語意搜尋第一筆就命中" + echo "(Cloudflare Artifacts >> 若提供 git 倉庫則可取代 >> Gitea,負責人 15 天前就記了)。" + echo "" + exit 0 +fi COUNT=$(printf '%s\n' "$HITS" | wc -l | tr -d ' ') @@ -84,5 +101,12 @@ echo " • 看到「不可動/待廢除/進行中」→ 先讀它的**解 echo " 那是當時狀態不是永久禁令;條件已滿足就是可動。" echo " • wiki 沒答案才值得翻原文——翻完若得到新結論,**回頭更新 wiki**。" echo "" +echo "🔎 以上是 **grep(最弱的查法)** 的結果,只認字面,且搜尋詞是從你的指令**猜**出來的" +echo " (很可能太籠統而命中一堆無關的,同時漏掉真正的主題詞)。" +echo " **重要判斷一律補一次語意搜尋**——它不需要你猜對用詞:" +echo " kbdb_search(q=\"<一句話描述你要找什麼>\", mode=\"semantic\")" +echo " 實例:查「CF 的 git 託管」時 grep 猜到的詞是 cloudflare → 命中 12 處全無關、" +echo " 真正的答案(Artifacts)一筆沒撈到;語意搜尋第一筆就命中。" +echo "" exit 0 diff --git a/template/system-dev/VERSION b/template/system-dev/VERSION index 41c11ff..092afa1 100644 --- a/template/system-dev/VERSION +++ b/template/system-dev/VERSION @@ -1 +1 @@ -1.16.1 +1.17.0