# HANDOFF: arcrun config 寫入端 + 讓 AI 看懂 scope + KBDB Vectorize 開關

> 來源：InkStoneCo 頂層總管，2026-06-15。mira self-hosted dogfood 踩出的兩條框架缺口。
> 兩條都是 `change`，走 SDD 協議（先讀對應 SDD、宣告、改 tasks.md）。
> 觸發實證：mira（一個 AI）被交代遷移時**沒看懂 scope 存在**，差點誤部官方帳號。

---

## 缺口 1：config 讀分層完整、寫只能全域 + AI 看不懂 scope

### C.1 補 `acr init` 專案層寫入端

`cli/src/lib/config.ts` 讀取分層完整（`findProjectConfig()` env > 專案層 > 全域，8/8 測試），但**寫入只有 `saveConfig()`（config.ts:208）寫死全域** `~/.arcrun/config.yaml`（config.ts:38）。`acr init` 4 處呼叫（init.ts:93/142/278）全寫全域。
- → `acr init` 無法寫專案層。leo 意圖 project scope 卻被迫污染全域 → 怕誤打官方 uncle6me。

**修法**：
- `saveConfig()` 加 scope 參數（`'global' | 'project'`）；project 寫 `./.arcrun.yaml`（`process.cwd()`）。
- `acr init` / `acr config set` 加 `--project` flag。
- 預設是否翻轉（init 預設寫專案層）由 richblack 定（影響既有使用者）。
- 參考既有範式：`mcp-setup.ts` §7.8 已有 project scope 寫 `.mcp.json` 概念，比照。

### C.2 ★ 改 `cli/harness/CLAUDE.block.md` 讓操作 AI 看懂 scope（最重要）

**病根**：arcrun 是 AI 操作的工具（mindset §2），但 harness block（全文 41 行）對 scope / 帳號歸屬 / 誤部風險 **0 字提及**。AI 讀完完全不知道有 scope 這層 → mira 把「資料遷移」跟「在哪 scope 部署」混為一談。

在 harness block 加「部署落點與帳號安全」段：
1. **scope 模型**：分層 `env > 專案層 .arcrun.yaml > 全域 ~/.arcrun/config.yaml`。**部到哪個 CF 帳號取決於當前資料夾解析到哪份設定**。動手前先 `acr config --where`。
2. **多帳號警示**：同機可能多個 CF 帳號（dogfood / prod）；`.env` 可能並存多組 `CLOUDFLARE_*`（含 `*_UNCLE6` 後綴）。部署/遷移前必須明確目標 account_id，挑錯＝打到正式環境（不可逆）。
3. **遷移 ≠ scope**：搬資料（A 帳號→B 帳號）和「我用哪個帳號」是兩件獨立的事。
4. **fallback 陷阱**：任一層都沒 `mode` → `acr` 靜默當 `local`（config.ts:176），不報錯。看到「成功」但無雲端 trace 先查 `acr config --where`。
5. **無設定就停手**：`--where` 顯示無設定 / fallback local 而意圖 self-hosted → 停下問人。

> harness block 是 AI 的 mindset 入口，比 CLI `--help` 重要（AI 偏好讀 harness）。scope 安全屬「動手前世界觀」，必在這層。

**對應 SDD**：`docs/3-specs/arcrun/sdk-and-website/config-layering.md`。

---

## 缺口 2（任務 D）：KBDB Vectorize（embed）無環境開關

### 病根

KBDB 分 `base`（D1 only，免費）+ `embed` module（Vectorize+AI binding，語意搜尋）。但 `acr init/update` 完全沒處理 embed（grep `vectorize|embed` 在 `cli/src/` = 0 命中）；只活在 `kbdb/src/index.ts:5` 註解。→ **沒有 config 欄位 / 指令讓使用者或 AI 表達「要不要開 Vectorize」**。

### 設計哲學（leo 2026-06-15）：降級要優雅，但「完整體驗」要有門

> 「最好是我自己這套可以語義搜尋；不開就降級；**但想完整體驗卻沒有門**。」

- **預設降級且能跑**：沒開 embed → base 仍可關鍵字搜尋（不是壞掉）。
- **降級要明示不能無聲**：跑 base 時要讓人知道「語意搜尋未開」。無聲降級＝用戶以為這就是全部＝bug。
- **★ 升級要有門**：config 欄位 + `acr` 提示「想語意搜尋？這樣開」。現在連「有更完整版本可選」都不可見。

### 修法（config 欄位 + 部署條件注入，比照 MULTI_TENANT）

1. **config 加欄位**：`ArcrunConfig`（config.ts:11）加 `kbdb_embed?: boolean`（預設 false＝base 免費）。leo dogfood 設 true。
2. **部署條件注入**：`acr update` 部 KBDB worker 時 `kbdb_embed: true` → 注入 Vectorize+AI binding + 部 embed module；false 只部 base。比照 `deploy.ts:395` MULTI_TENANT 注入、`deploy.ts:380` WORKER_SUBDOMAIN 注入。
3. **降級可見**：`acr config --where` / 部署摘要顯示「KBDB: base（語意搜尋未開）」或「embed（Vectorize 啟用）」；base 時提示升級門。
4. **AI 認知**：harness block（C.2 那段）一併說「KBDB 預設 base（D1 免費僅關鍵字）；語意搜尋需 `kbdb_embed: true`（Vectorize 計費）。功能需語意搜尋但這套是 base → 別假裝有，明示降級指出升級門」。呼應 mindset §7 誠實。

**對應 SDD**：KBDB 模組化屬 `docs/3-specs/` kbdb spec；部署注入屬 `sdk-and-website/self-hosted-init.md`。

---

## 任務 E（★ 急，擋 mira 14-E load）：給 mira「leo21c kbdb worker 實際綁的 D1 id」

> 總管裁定（2026-06-15）：mira 14-E load 撞 Workers 每日 10萬 request 牆（逐筆 API 病根）→ 改走 `wrangler d1 import`（資料層搬遷＝用戶 CF 權限，繞 API）。**但 mira 需要 D1 id 才能灌對庫。**

**為什麼 mira 自己查不到**：
- cypher-executor **無** D1 binding，轉發給 **kbdb worker**。
- kbdb worker 的 D1 id 是 **deploy.ts 部署時動態注入**（`kbdb/wrangler.toml` 靜態值 `0c580910…` 是官方 prod，self-hosted 部署會覆蓋）。
- → leo21c 上 kbdb worker 實際綁的 D1 id ≠ mira `wrangler` 直連的 `arcrun-kbdb`（`1099d0f3…`）。這是「wrangler 查 0 筆、cypher 有 11 萬筆」的真相（兩個同名不同 id 的 D1）。

**你要做**：用 leo21c CF token 查 leo21c 上 **kbdb worker 部署時實際注入的 D1 database_id**（看 deploy.ts 注入邏輯 / 查 leo21c worker runtime binding），告訴 mira。mira 拿到才能 `wrangler d1 import <該 id>` 灌對庫。

## 任務 F（B，框架缺口，非急）：cypher `/kbdb/entries` 補批次端點

> 總管裁定 B：應用層大批寫入該有批次 API。**未來每個 self-hosted 用戶大批匯入都撞 10萬 request 牆**（不只 mira）——逐筆 POST 每筆 1 request，~5萬筆燒光免費 worker 當日配額。

- `POST /kbdb/entries` 收陣列（`[{...},{...}]` 或 `{entries:[...]}`），1 request 寫 N 筆 → 45.8萬筆只要 ~900 requests。
- 守鐵律（只轉發 API、不開 SQL/建表；owner_id 仍自動注入每筆）。
- 對應 SDD：kbdb-proxy 屬既有範圍。

## 任務 G（雜項，mira 14-E 踩出的 cypher 框架特性，記著）

mira load 踩出，記給框架修（非急）：
1. CF WAF 1010：Python urllib 預設 UA 被擋 → 文件提醒帶 UA。
2. 重複 id → 500（非 409）：UNIQUE 衝突宜回 409 友善處理。
3. 零星單筆 500：某些 block 穩定 500、同 content 換 id 卻 200＝邊緣 bug（疑 metadata_json/refs_json 某字元觸發，未定位）。
4. `?id=` query 被忽略（回前 100 筆不過濾）；查單筆只能 `/entries/:id` 路徑——文件宜明示。
5. **DELETE `/kbdb/entries/:id` route 缺**（OPTIONS 卻宣告支援 DELETE，CORS 宣告與實作不一致）。
6. cypher 綁的 D1 與同名 `arcrun-kbdb` database_id 不一致（見任務 E）——self-hosted 文件宜說明「wrangler 直連 ≠ cypher 綁的庫」。

## 共通教訓

任務 C、D 同類：**把「該是環境設定的選擇」從 code 註解提升到 AI/使用者可表達的層級**。arcrun 是 AI 操作的工具，凡影響「部到哪、開什麼功能」的選擇都必須在 config + harness 可見，不能只活在實作裡。
任務 E/F 同類：**資料層搬遷（用戶 CF 權限 d1 import）vs 應用層大批寫入（cypher 批次 API）是不同層級，都該存在**——逐筆 API 推大批資料是把「資料遷移」做成「應用層寫入」，撞 worker 請求上限。

## 依賴

mira 側（建專案層 .arcrun.yaml + 移全域）先行，見 mira repo `docs/HANDOFF-arcrun-config-project-scope.md`。本框架補強讓「未來不再污染全域 / AI 不再看不懂 scope」，是根治，非阻擋 mira 當前解耦。
