Commit Graph

9 Commits

Author SHA1 Message Date
uncle6me-web c2897ba68b fix(mcp): AI 一連上就知道「這裡有主人的知識庫」+「讀不到」不再講成「不存在」
leo 2026-08-13:「它應該是**你的知識來源**⋯⋯**沒有它你是瞎的**,
從你對 Arcrun 的認知就知道你的內建 Memory 是沒用的。」

## 病灶一:指路的話被綁在一個會無聲消失的段落上

instructions 裡唯一提到「這裡有知識可查」的,是 buildLibraryMapInstructions
拼上去的【藏書地圖】——而那段是**選配的**(1500ms 逾時、catch 回 null、失敗無聲)。
必定出現的那段靜態文字(startHere)從頭到尾只講工作流、零件、recipe、邊的語法,
`kbdb_search`/`kbdb_get_map` 一個字都沒有。

實害:同一天,一條 portal 連線的 session 為了回答「Arcrun 是什麼」去讀了 682 行
原始碼——而 `kbdb_search(q="Arcrun 是什麼")` 當下回得出 33 筆真答案。

修法:
- 新增 `KNOWLEDGE_FIRST` 靜態段(與 startHere 同級,KBDB 掛了照樣出現),
  排在最前面:這條連線後面有主人的知識庫、第一個動作是 kbdb_search、
  工具怎麼呼叫、以及「沒查到/沒查/地圖沒取到」三件事不可以講成同一句。
- 地圖失敗**不再靜默**:拿不到就印【藏書地圖:這次沒取到】,
  stale token 另印身分版(要使用者重新連線)——「沒取到」與「這裡沒有知識」
  不可以長得一樣(Arcrun#109 同族)。鐵律不變:失敗仍然不擋連線。
- 抽出 `buildServerInstructions(env, identity)` 供測試印出完整字串。

## 病灶二:一個 401 被逐字翻譯成「不存在」

`arcrun_get_skill('write_intent_workflow')` 回「skill ... 不存在」,
但 `kbdb_search` 撈得到 `page_name: "skill-write_intent_workflow"`
(entry_type: agent-skill、source: installer-seed)——**與本工具查的鍵逐字相符**。
真兇是 `kbdbGetByPageName` 的 `if (!resp.ok) return null;`。
而 401 的來源是該實例的 arcrun-mcp 沒有 KBDB_INTERNAL_TOKEN
(kbdb-client 沒 token 就匿名送出)=部署面的事,但這支 code 把它講成了假話。

修法:
- 非 2xx 一律拋 KbdbAccessError(帶真 status)→ kbdb_unauthorized/kbdb_unreachable,
  訊息明說「這是讀不到,不是不存在」,並交出還走得通的那條路(kbdb_search)。
- `not_found` 只留給「KBDB 正常回應但真的沒這張卡」,並說明是「這台實例沒 seed」。
- 五支工具吃 identity:stale → identity_missing;portal 撞 401 時額外說明
  「是這批工具還走服務憑據,不是你的帳號讀不到」。
- instructions 步驟 4 不再指名 `arcrun_get_skill('INDEX')`(leo21c 實測根本沒 seed
  這支)——改成先 `arcrun_list_skills()` 看這台實例真的有哪幾支。

## 驗

- `mcp` 測試 130 passed(新增 mcp-instructions 7 項+skills-examples-honesty 10 項),tsc exit 0。
- 三種情境(地圖抓得到/抓不到/舊 token)各印一份完整 instructions 實測,
  三份的開場都指向 kbdb_search。

⚠️ 未部署(部署是 leo 的手動閘)。上線後才會到用戶手上。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 14:09:35 +08:00
uncle6me-web 10d150ac2b fix(mcp): MCP 用登入者的身分查詢,不再去找一把服務內部金鑰
leo 2026-08-12:「人類進 Portal 輸入帳密表示你是主人,可以查到你權限所有東西;
AI 透過輸入帳密的 MCP 查詢表示是授權的 AI,可以查到主人允許查的任何東西。」
「掛上 MCP 並輸入帳密,那個動作本身就是授權」⇒ 下游不得再要求第二次認證。

病根(不是金鑰沒同步,是身分沒接住):
  oauth/routes.ts 驗完 Portal 帳密只留下 `loginOk = res.ok` 一個布林值,身分當場丟棄,
  namespace 改從 `MCP_OWNER_NAMESPACE || "leo"` 拿。於是查詢時手上沒有身分可帶,
  只好用 KBDB_INTERNAL_TOKEN 直打 KBDB——那條路繞過 portal 所有庫過濾,
  而且不管誰登入都看到同一格、看到全部。CLI 也從不注入 MCP_OWNER_NAMESPACE,
  所以那個 "leo" 預設值是每台實例的實際行為,不是理論上的邊角。

修法(走既有那條路,不發明新的):
1. 接住身分:/authorize 解析 /portal/login 回應,把 portal session token +
   display_name/role/libraries 存進 authorization code → access token。
   /portal/login 補回 session_expires_in,access_token TTL 夾成
   min(自己的 TTL, portal session TTL)——不讓「MCP 還連著、底下 session 早死」。
   cypher 回 200 但沒給 session_token(舊版)→ 不發碼,不簽一張沒有身分的 token。
2. 攜帶身分:kbdb_* 全部改走 cypher `/portal/data/*`,Authorization 帶登入者的
   session。庫過濾/租戶注入/停用即時生效全在 server 側,與人類走 portal 網頁同一道閘。
   kbdb_graph_neighbors 因此不再需要 kbdb_base(server 自己知道查哪個庫)。
   藏書地圖(含連線時注入 instructions 的那份)同樣只回有權限的庫,快取改 per-session
   分格——地圖本身就是情報,不能讓先連上的人把視野留給下一個。
3. fail-closed:舊 token 沒有身分 → 誠實要求重新連線,不偷偷退回服務金鑰那條老路。
   服務級憑據(static token / partner key)維持既有 KBDB 直連,arcrun_* 零回歸。

新增 cypher portal 資料面端點(能力長在 API,MCP 只暴露;rule 07):
  GET  /portal/data/map、/portal/data/map/:library
  GET  /portal/data/templates、POST /portal/data/templates
  GET  /portal/data/records/by-template/:t、GET /portal/data/records/:id
  POST /portal/data/records
全部:呼叫端自帶 owner_id 一律不生效;越權與不存在同回 404;寫入 owner_id 由 server 定死。

KBDB base:`GET /records/:id` 與 by-template 補回 owner_id 欄位——原本不回,
呼叫端無從判斷「這筆是不是我的」,按 id 直讀等於沒有租戶邊界。

沒動:KBDB fail-closed 閘、任何金鑰、租戶字串仍不下發給呼叫端。

驗證:
  mcp        tsc 綠;vitest 113/113 綠(改前 48 綠 29 紅)
  cypher     vitest 400 綠 / 14 紅,14 紅與 base commit a24f291 逐條相同(既有)
  kbdb       vitest 208 綠 / 5 紅,5 紅同為既有(migrations/*.sql 被 gitignore)
  端到端     ◐ 未驗:需部署到 leo21c,那道閘要 leo 親手解(見 PR)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 19:33:12 +08:00
uncle6me-web c735b911a0 🔴 修教材反向教壞:skill §7 自打臉+補「分支怎麼算成功」+刪 publish 死代碼
端到端 haiku 考 0/3、1/3,**斷點在教材不在引擎**(另一 agent 取證,別重查):
探針零 code 實測 n=10→TRUE、n=1→FALSE 兩次 success;**考生的作品其實會動**
(amount=5000→true、amount=100→false 條件求值全對),但它以為跑不通而放棄改寫 code;
考生第二次自己指認「MCP 說明聲稱不支援 ON_TRUE/ON_FALSE,與實際系統行為不符」。

① skill `write_intent_workflow` **同一份前後打架**(我 08-01 只改了 §2 沒掃全篇):
   §2.1 教用 ON_TRUE,§7 第 1 條卻把 ON_TRUE 列為「不存在的邊」⇒ 教材自我否定。
   改:§7 只留 ON_FAILURE(真的沒有),並明寫「ON_TRUE/ON_FALSE/ON_BRANCH 是存在的,
   見 §2.1,本行舊世代已更正」。全篇 grep 過確認無其他矛盾。

② **補 §2.2「怎麼確認分支真的走對」**——這是「看到對的結果卻以為失敗」的直接解:
   看 verdict,且**走 true 路時 false 路節點不出現=正確行為不是失敗**;
   附 08-01 實撞案例,明講「只有一條路有輸出」不該判定壞掉。
   MCP instructions 同步加這段(比 skill 更前置,AI 一連上就讀到)。

③ #23 殘留清除(leo 08-01:「已經沒有 publish 了,零件等級一律走 PR,這條路封了」):
   `git rm mcp/src/tools/arcrun_publish_component.ts`+拔掉 registry.ts 的 import
   (註冊呼叫本來就已註解掉=純死代碼配活 import)。刪前 grep 全 repo 呼叫方:
   除本檔與 registry.ts 外,其餘命中全是 md/SDD 的歷史記載(不需動)。tsc 綠。
   替代路徑=`Leo/arcrun-components` fork→PR→人審,已寫進 registry.ts 註解。

SDD: workflow-discovery 3.11|CP: arcrun-usable 步驟 5
2026-07-31 18:37:48 +08:00
uncle6me-web a9a47b7c37 🔴 步驟5 補斷點:教材說「引擎不支援條件分支」+意圖語法收不到分支標籤
備考 haiku 真考時自查發現的兩個斷點——**若不補,考試必掛,且掛的是我自己的教材**。
形狀=步驟1 那個「世代脫節」的翻版:能力做好了,但教 AI 的地方還停在舊世代。

斷點①:三處教材主動說「沒有條件分支」,還教了正好造成腹語術的替代法
  - mcp/src/mcp-handler.ts:44「**沒有** ON_TRUE/ON_FALSE——引擎目前不支援條件分支」
  - registry/skills/write_intent_workflow.md:39「不要寫 ON_TRUE/ON_FALSE…
    需要判斷時**寫成一個獨立節點**再接 ON_SUCCESS」← 這正是「判斷退回 code」的入口
  - registry/skills/INDEX.md:44「已知的坑:引擎沒有條件分支」
  ⇒ 三處全部更新成現況(三顆零件都輸出 data.branch、引擎依標籤選路、
    查零件回應附 branch_hint 照著接即可),並保留「不要寫 ON_FAILURE」(那個真的沒有)。

斷點②(更隱蔽,靜默失效):`graph-builder` 只認得 `對每個 X` 的參數化 label,
  `ON_BRANCH(branch_active)` 帶括號會落到 toEdgeType 預設值 **PIPE**
  ⇒ 我在 skill 教的寫法,編圖收不到,而且**不報錯**——AI 以為分支了、實際全走同一條。
  「教了語法但引擎不收」比沒做更糟,故與文件同批補上:比照 FOREACH 抽 iterator 的作法
  抽 branch 標籤(半形/全形括號都收),寫進 edge.branch。

新增 tests/intent-branch-syntax.test.ts(7 項綠):守「文件教的寫法,編圖真的收得到」
——ON_TRUE/ON_FALSE 不退化成 PIPE、中文「成立時/否則」、ON_BRANCH(標籤) 抽得出 branch、
全形括號、try/catch 標籤;零變化:ON_SUCCESS 仍是 ON_SUCCESS、對每個 X 的 iterator 不受干擾。

全套 234 passed(前 227 +7),失敗數維持既有 9 筆;tsc 綠。

SDD: workflow-discovery 3.11|CP: arcrun-usable 步驟 5

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 16:51:19 +08:00
Leo cda1c7b261 instructions 補「你配備了 Arcrun、別上網搜」+新增 skills/INDEX(LLM wiki 式導航)
leo 兩個洞察:
① 「整個 arcrun instruction 很像 LLM wiki…它會拿到一個 index 把所有文件說明都塞給它,
   它不會就可以查,範本全部寫在裡面」
   ⇒ 對照 wiki 的 push/pull 分法:我原本只做了 push(instructions 開場),
     漏了 pull(INDEX 導航)。補 registry/skills/INDEX.md:
     什麼症狀查哪支 skill/查現成零件recipe workflow 的九支工具/四個已知的坑/腹語術紅線
② 「它不去查就不知道…如果它去上網搜因為它不知道自己有配備呢?」
   ⇒ 實測確認 instructions 是 **push**(本 session system prompt 內就有藏書地圖那段)
     ⇒ AI 不會去上網搜,但原本的 instructions 沒說「你配備了什麼」
     ⇒ 開場補:Arcrun 是什麼/你現在就有完整能力/不要上網搜(網路上沒有)

驗:tsc 零錯誤。⚠️ 未部署——實測總管 token 只有 account(read),無法部署任何 CF worker。
2026-07-30 22:38:37 +08:00
Leo fac7d6c9bb AI 一連上 MCP 就知道從哪開始(leo 追問揪出的最後一哩)
leo:「arcrun_get_skill 放在 MCP 裡,現在人類說『幫我用 arcrun 寫 xxx』,
Haiku 會說『arcrun 是什麼?我看看』然後發現有個 arcrun mcp 就去執行?
如果不會,要寫什麼在外面讓它一聽到就知道要用這些資源?」

實測答案:**不會**。
① 總管寫的指引沒有任何入口指向它(真實 AI 找不到)
② MCP 五個 skill 沒有「怎麼寫意圖工作流」這支
③ AI 只看到 41 個工具名 → 自己猜 → 很可能直接 push_workflow 瞎編,
   或去讀 registry/examples 那 8/13 引用不存在零件的壞範例

兩件修法:
1. registry/skills/write_intent_workflow.md — 把指引變成 AI 拿得到的 skill
   (範本全取自實跑 verdict=success 的四支 workflow;含「查詢現在回假 found」的已知限制警告)
2. mcp-handler.ts instructions 開場指路 — instructions 是唯一「AI 一連上就必看」的欄位
   ⇒ 開場就寫明五步順序(先讀 write_intent_workflow → whoami → 查零件 → list_skills → 缺件怎麼補)
   +邊只有兩種、第一個節點是 input、不要因查不到就改寫 code
   ⚠️ 靜態常數:KBDB 掛了也必出現(守「不擋連線」鐵律)

驗:tsc 零錯誤。 待部署後由 leo 真的問 haiku「幫我用 arcrun 做 X」驗證它會不會自己讀 skill。
2026-07-30 22:29:28 +08:00
Claude 343572bf5d feat(mcp): library-map M4 — kbdb_get_map tool + instructions 注入全館地圖
library-map SDD M4(design §4,源頭 #39)。兩件:

1. kbdb_get_map(tools/kbdb_map.ts,與 #68 kbdb_graph_neighbors 同族薄殼):
   - 無參數=全館地圖(每庫一行:library+narrative+top 3 entities+triplet_count)
   - 帶 library=該庫詳圖;top_entities/relation_profile/bridges 若為 JSON 字串形
     容錯 parse 成物件(parse 失敗當空陣列,不 crash)
   - 404/空庫誠實回報+POST /map/recompute backfill 指引
   - 走既有 KBDB service binding(kbdbFetch),不碰 D1、不新增 binding

2. instructions 注入(lib/library-map.ts+mcp-handler.ts):
   - 連線時拉 GET /map,渲染成緊湊文字({library}:{narrative}|核心:{top3}|{n} triplets)
     嵌 server instructions(design §6:session 啟動 push 零查詢)
   - 快取選型:isolate 內 TTL 快取(成功 5min/失敗 1min)——stateless StreamableHTTP
     每個 HTTP request 重建 McpServer,「每次現拉」實際是每個 tool call 都多打一次 /map
   - timeout 1.5s;任何失敗(超時/HTTP錯/空庫/壞JSON)回 null 靜默略過,絕不擋 MCP 連線(鐵律)

測試:假 KBDB binding(比照 kbdb-graph.test.ts)17 新測,pnpm vitest run 76/76 過、tsc --noEmit 乾淨。
merge 後需 gated redeploy arcrun-mcp(leo 閘)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUmjwkHLVBHM3ydhT1WSW3
2026-07-19 09:11:46 +00:00
Claude 5fc7277c3c refactor(mcp): u6u_* tool 全面 rename 為 arcrun_* + 前綴收斂單一來源
零 u6u 洩漏(leo 要求 1):connector tool 清單只剩 arcrun_*,並移除壞掉/
重複的 u6u_ workflow tool(deploy/execute/get/list_workflows 由 arcrun_
push/run/get/list_workflows 取代);MCP server name 也由 u6u-mcp-server
改 arcrun-mcp-server。

前綴單一真相源(leo 要求 2):新增 mcp/src/brand.ts(TOOL_PREFIX + toolName()
helper),所有 server.tool() 註冊一律走 toolName("suffix"),前綴不再明碼散寫。
未來 rebrand 只改 brand.ts 一行。

- 12 個獨有能力 tool rename(component/tag/gui/search_workflows)
- 4 個重複/壞掉 tool 移除
- inter-tool hint、描述字串、註解內 u6u_ 名字全數更新
- tsc exit 0;vitest 19/19 綠

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015d5jDbuqT5Htwv3Q88XXKk
2026-07-07 05:21:34 +00:00
uncle6me-web 3e65e22775 feat: 薄殼原則落地 + seed 下沉 API + MCP 進主庫 + 部署一致性
壓測四橫向問題修正(docs 壓測報告):

① 薄殼原則成鐵律:能力長在 API,CLI/MCP/lib 只暴露
   - seed 下沉成 API 行為:cypher-executor POST /init/seed(一次灌 API+auth recipe),
     種子資料移到 server src/lib/api-recipe-seeds.ts,CLI 改薄殼一次呼叫
   - 解除 deployFullyOk 連坐 + init 補 seed auth recipe + update 補 seed/全 KV
   - registry SUBMISSIONS_KV 補進 REQUIRED_KV_NAMESPACES(修 20/21)

② MCP 統一帳號來源(單一 remote MCP + .env 切 MCP URL)
   - MCP 從 sibling repo 搬進 arcrun/mcp/(remote Worker,route 改 mcp.arcrun.dev)
   - config 加 mcp_url 三層解析 + getMcpUrl + DEFAULT_MCP_URL
   - 新增 acr mcp-setup:依 config 寫專案 .mcp.json(接案切資料夾自動切 MCP)
   - acr --version 改動態讀 package.json(根治漂移)

③ Deploy 一致性
   - tests/release.feature + scripts/check-release.sh
   - local-deploy.sh:CLI npm publish + auto patch bump + CHANGELOG
   - local-deploy.sh bash 3.2 相容修正(mapfile / 空陣列 set -u)
   - builtins/pnpm-lock.yaml

④ README self-hosted 同步現況(移除 R2 殘留、加 flag/env、多帳號)

CLI bump → 1.3.0

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 15:45:35 +08:00