Files
Arcrun/registry/examples/km-wiki-ingest/drainer
kbdb-cc c6932b0088 feat(km-wiki-ingest): 重做成跑在 cypher 上的 workflow(走 cypher binding,汰換 service-binding drainer,D28)
把知識庫 ingest 從 standalone drainer(誤用 Service Bindings)重表達為 cypher workflow:

- workflow.yaml(Phase 0 cron drain):watch_cron→load_cursor→list_cards→pick_card(code)
  →fetch_card→parse_card(code)→upsert_entry→save_cursor→post_envelopes→post_one_envelope。
  線性 pipe,跨-worker 全走 cypher binding(零件節點),零 service binding。
- workflow.delta.yaml(Gitea webhook 穩態):collect_changed(code)→foreach card→fetch/parse/upsert/foreach envelope。
- code/kbdb/graph 接法:code=canonical `code` 零件(arcrun-code);kbdb/graph=http_request 零件打
  /entries/ingest、/triplets/ingest(server 端冪等);Gitea=http_request。
- 平台端最小補丁(各需 gated 部署):
  1) cypher-executor component-loader:WASM_HTTP_RUNNER_IDS 加 'code'(canonical→arcrun-code,cypher binding 正解)。
  2) kbdb base:POST /entries/ingest(page_name+content_hash 冪等 upsert,對稱 graph /triplets/ingest;
     因 flow DSL 無資料條件分支,把 create/patch/skip 冪等推到 server 端)。
- drainer/DEPRECATED.md:標舊 standalone worker 退役計畫(新版穩定後 wrangler delete)。
- DEPLOY.md:部署順序、cron/webhook 掛法、subdomain 對齊、驗收與退役。

本輪不部署(待總管/leo 審架構)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJiLCRUU2o3aSpPEzVCt2o
2026-07-06 12:59:13 +00:00
..

arcrun-km-wiki-drainer —— km_wiki_ingest_drain 的無人值守 runtime

workflow.yaml 是宣告式 spec本 Worker 是它可真部署、有游標/觸發的執行體。 復用已 live 的零件與服務,不改 cypher-executor

Gitea 抓卡 md → arcrun-code 零件(sandbox inline JS 解析)→ /entries 冪等 upsertembed:true
             → graph /triplets/ingestserver 側 per-source 冪等)
  • Livehttps://arcrun-km-wiki-drainer.leo21c.workers.dev
  • 解析 JSsrc/usercode.ts(由 workflow.yamlparse_card.code 抽出,單一真相源 lib/card-to-envelope.mjs)。

兩觸發模式(共用同一 processCard 核心)

模式 觸發 行為
Phase 0 cron drain cron tick(見「開自走」) drainBatch(BATCH_SIZE)Gitea tree 列卡 → 游標之後取一小批 → 逐卡 processCard → 進游標(到底回捲重掃)。壓 CF subrequest 下、撐得住 5,083 檔(每 tick 小批)。
穩態 webhook Gitea push webhook → POST /webhook 只處理本次 commit 動到的 system-dev/wiki/cards/**.mddelta),不重掃全庫。Gitea→Cloudflare,非 GitHub Actions(不觸 D20

冪等:未改卡的 entrypage_name+content_hash)與 tripletsource.uri+content_hash)皆 skip;只有新/改卡真寫。游標存 KBDB 一個 ingest_cursor entry(走 API、零建表)。

HTTP 路由

方法 路徑 用途
GET / 健康
GET /cursor 看游標狀態
POST /drain?batch=N 手動觸發一批 drain= 一個 cron tick;驗收/補跑用)
POST /webhook Gitea push webhook 入口(delta
POST /cursor/reset 游標歸零(重新全 drain

⚠️ 非-auto(預設)

wrangler.toml[triggers] crons 預設註解掉——不自走排程、不無人值守亂寫。 drain 以 POST /drain 手動觸發(與 cron scheduled handler 同核心)。 要開自走 Phase 0 backfillleo 過閘後取消 wrangler.toml 那兩行註解再 deploy。

部署(wrangler 直推 leo21c,禁 acr update

cd registry/examples/km-wiki-ingest/drainer
npm install
npx wrangler deploy
# ★ 必須:設 Gitea 讀取權(Leo/notes 為 private repo)——此步需 leo 在互動模式跑(secret 寫入)
printf '%s' "$GITEA_TOKEN" | npx wrangler secret put GITEA_TOKEN
# 選填:webhook 簽章驗證
# printf '%s' "$WEBHOOK_SECRET" | npx wrangler secret put GITEA_WEBHOOK_SECRET

Gitea webhook 設定(穩態 delta

Leo/notes → Settings → Webhooks → Add Webhook → Gitea

  • Target URLhttps://arcrun-km-wiki-drainer.leo21c.workers.dev/webhook
  • HTTP MethodPOSTContent-Typeapplication/json
  • TriggerPush events(可只限 main
  • Secret:若設,同步 GITEA_WEBHOOK_SECRET secret(本 Worker 驗 X-Gitea-Signature HMAC-SHA256
  • Gitea 的 ping event → Worker 回 {ok:true,pong:true}(測連通)

config

  • varsREPO=Leo/notes REF=main OWNER=leo CARDS_ROOT=system-dev/wiki/cards GRAPH_KEY=leo BATCH_SIZE=2
  • Service Bindings[[services]]SVC_CODE→arcrun-codeSVC_KBDB→arcrun-kbdbSVC_GRAPH→kbdb-graph-plugin⚠️ 同帳號 worker-to-worker 必須走 Service Bindingenv.SVC_X.fetch())——直接 fetch("https://arcrun-*.leo21c.workers.dev") 會撞 CF 1042(同帳號 worker 互打限制)。Giteagit.uncle6.me,非 CF)才用 plain fetch。 註:wrangler dev 本地 miniflare 不強制 1042,故本地測會假綠 → 一律對部署後真端點驗收。

規模備註(5,083 檔)

  • 列卡走 Gitea git/trees?recursive=true(一次全樹);若 truncated,回應標記 truncated:true, 屆時換 tree 分頁列法(現況 notes 卡數小、不截斷)。
  • 每 tick 只 BATCH_SIZE 張,游標續傳;到底回捲 → 全庫變更靠冪等於下一輪捕捉; 即時變更走 webhook。