portal-auth P1(#24 #25):KBDB library filter 地基

- /entries 與 /entries/search 加 library 多值參數(逗號分隔);不帶=行為一字不變(向後相容)
- D1:COALESCE(json_extract(metadata_json,'$.library'),'general') IN (…)(≡ design §3.3 OR 形狀;
  未標記舊資料歸 general)
- semantic:Vectorize upsert metadata 加 library(寫入端正規化 general);查詢 filter $in 主路徑
  (官方文件+workers-types 4.20260702.1 核實支援,fan-out fallback 不需)
- 測試:library-filter.test.ts 11 項+既有 6 項全綠;tsc exit 0;本機 miniflare local D1 十案例實跑全過
- semantic 線上路徑(metadata index+reindex backfill)=部署清單,待雲端排練驗(本機無 Vectorize)
- cypher kbdb-proxy 透傳順延(P1 派工紅線只動 kbdb,tasks.md 已註)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
uncle6me-web
2026-07-14 11:45:08 +08:00
parent 18c0846af0
commit e788c52dd2
6 changed files with 274 additions and 14 deletions
+26 -5
View File
@@ -9,12 +9,33 @@
## P1 — KBDB「庫」filter 地基(design §3.2/§3.3)|觸碰:`kbdb/`
- [ ] 開工第一件事:實測 Vectorize metadata filter `$in` 支援與否(決定主路徑 vs fan-out fallback
- [ ] `/entries/search``/entries``library` 多值參數(D1 json_extract INNULL→general fallback
- [ ] embed upsert metadata 加 `library` 欄;semanticSearch filter 支援 library$in 或 fan-out
- [ ] Vectorize `library` metadata index 建立步驟+reindex backfill 寫進部署清單
- [x] 開工第一件事:實測 Vectorize metadata filter `$in` 支援與否(決定主路徑 vs fan-out fallback
- **核實結論(2026-07-14****支援,走主路徑 `$in`,不需 fan-out fallback**。證據:① 官方文件
developers.cloudflare.com/vectorize/reference/metadata-filtering/ 明列 8 運算子
`$eq/$ne/$in/$nin/$lt/$lte/$gt/$gte`,「For $in and $nin, filter object values can be arrays of
string, number, boolean, or null values」;② 本 repo `@cloudflare/workers-types@4.20260702.1`
原生 typing `VectorizeVectorMetadataFilterCollectionOp = "$in" | "$nin"`index.d.ts:15782),
wrangler 4.98.0。限制:metadata filtering 只對 2023-12-06 之後建的 index 有效(本專案 index 皆是)。
本機無 Vectorize runtime`$in` 的**線上實跑**併入部署排練驗(見部署清單)。
- [x] `/entries/search``/entries``library` 多值參數(D1 json_extract INNULL→general fallback
- 實作註:SQL 用 `COALESCE(json_extract(metadata_json,'$.library'),'general') IN (…)`——與 design §3.3
的 OR 形狀語意完全等價(單組佔位符較簡)。本機 miniflare+local D1 十案例實跑全過(PR 附證據)。
- [x] embed upsert metadata 加 `library` 欄;semanticSearch filter 支援 library**$in 主路徑**fan-out 不需)
- 實作註:Vectorize 端在**寫入時正規化**(未標記→`'general'`)——Vectorize filter 做不了 COALESCE
寫入端蓋章後查詢端單純 `$in`;與 D1 查詢端 fallback 語意對齊。
- [x] Vectorize `library` metadata index 建立步驟+reindex backfill 寫進部署清單
- **部署清單(待雲端排練驗——本機無 Vectorize runtimesemantic 路徑 code 完成、線上實跑未驗)**:
1. `wrangler vectorize create-metadata-index arcrun-kbdb-embed --property-name library --type string`
2. `POST /embed/backfill {"reindex":true}` 分批到 remaining=0index 只收建立後 upsert 的向量)
3. 驗收抽查:semantic 帶 `library=` 過濾命中/不帶行為不變
4. 掛號:`cli/src/lib/deploy.ts` `ensureVectorizeMetadataIndexes()` 待補 `library`cli/ 屬 P1
派工範圍外「只動 kbdb」,隨 P3 或部署 PR 補——kbdb/wrangler.toml 註解已標)
- [ ] cypher `kbdb-proxy` 透傳 `library` 參數(供 owner/admin 面用;portal 面走 P3 的注入,不經這)
- [ ] 測試:D1 filter 單元測、NULL fallback、多值、semantic filtermock VECTORIZE
- ⚠️ 範圍註(2026-07-14):P1 派工紅線「只動 kbdb、不碰 cypher-executor」與本項矛盾——照窄範圍
執行,本項順延(一行 query 透傳,隨 P3 動 cypher 時一併)。
- [x] 測試:D1 filter 單元測、NULL fallback、多值、semantic filtermock VECTORIZE
- `kbdb/tests/library-filter.test.ts` 11 項(SQL 形狀/route 解析/向後相容/降級仍 enforce/$in 構造/
寫入端正規化)+既有 6 項全綠(17/17);tsc exit 0。
- **驗收**curl `/entries/search?q=&library=finance` 只回 finance+未標記條目歸 general 可驗;semantic 同
- **工程量**:小-中(0.5–1 個 CC 工作天)