Files
Arcrun/.agents/specs/arcrun-platform-evolution/tasks.md
T
Leo 180cef26c7 docs: rename SDD folders u6u-* → arcrun-* + update cross-refs
對應 SDD arcrun/.agents/specs/llm-interface/ M5.6(之前列為 backlog 連動)。
leo 2026-05-16 拍板 u6u 整體退場後,順手把兩個 SDD 也改名。

- .agents/specs/u6u-core-mvp/ → arcrun-core-mvp/
- .agents/specs/u6u-platform-evolution/ → arcrun-platform-evolution/
- CLAUDE.md / .claude/rules/00-sdd-protocol.md / 04-current-progress.md /
  llm-interface SDD 內所有跨 SDD 引用同步更新

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 15:24:22 +08:00

22 KiB
Raw Blame History

Implementation Plan: u6u Platform Evolution

Overview

依照 Bootstrap 順序分四個 Phase 實作,每個 Phase 都是下一個 Phase 的基礎。 技術棧:TypeScript、Hono、Zod、Vitest、fast-check,部署於 Cloudflare Workers。


Phase 0:最小 WASM 執行核心

  • 1. 建立 Component Registry 基礎架構(u6u-core/registry/

    • 1.1 建立 tpl-component Template Block(透過 KBDB HTTP API

      • 呼叫 KBDB /templates 建立 tpl-component template(若不存在)
      • 定義所有 slot keyscanonical_id、display_name、category、version、wasi_target、stability、runtime_compat、constraints、input_schema、output_schema、gherkin_tests、wasm_r2_key、cypher_binding_url、service_binding_key、description、tags、success_rate、avg_duration_ms、call_count、status、deprecated_at
      • Requirements: 12.1
    • 1.2 實作 POST /components/validate-contract 端點

      • 以 Zod schema 驗證 component.contract.yaml 所有必填欄位
      • 回傳缺失欄位清單(missing_fields: string[]
      • Requirements: 1.1, 1.2, 11.5
    • * 1.3 寫 property test for 合約格式完整性

      • Property 1: 合約格式完整性
      • Validates: Requirements 1.1, 1.2, 1.4
      • 用 fast-check 生成隨機缺少任意必填欄位的合約物件,驗證 validator 必定拒絕並回傳該欄位名稱
      • 用 fast-check 生成包含所有必填欄位的合約物件,驗證 validator 必定通過
    • 1.4 實作 GET /components/guide 端點

      • 回傳 Markdown 格式開發指引(TinyGo 白名單、禁止行為、contract YAML 範例、wasmtime 測試指令)
      • Requirements: 11.1, 11.2, 11.3
    • 1.5 實作 POST /components 零件提交端點(沙盒驗收流程)

      • 依序執行五個驗收步驟:(a) 體積檢查、(b) 冷啟動時間測量、(c) syscall 掃描、(d) Gherkin 測試執行、(e) runtime 相容測試
      • 任一步驟失敗立即停止,回傳 { success: false, failed_step, reason, guide_anchor, component_id, version }
      • 通過後以 KBDB HTTP API 寫入 Blockblock_id = comp-{id}-{version}
      • 同時上傳 .wasm 至 R2slot wasm_r2_key 記錄 R2 key
      • Requirements: 2.1, 2.2, 2.3
    • * 1.6 寫 property test for 沙盒驗收流程正確性

      • Property 2: 沙盒驗收流程正確性
      • Validates: Requirements 2.1, 2.2
      • 用 fast-check 生成在步驟 N 失敗的零件,驗證回應包含步驟 N 名稱與原因,且不執行步驟 N+1
    • * 1.7 寫 property test for 零件提交冪等性與持久性

      • Property 3: 零件提交冪等性與持久性
      • Validates: Requirements 2.3, 2.4
      • 用 fast-check 生成通過驗收的零件,提交後讀取合約驗證所有欄位 round-trip 一致
      • 對相同 (id, version) 重複提交 N 次,驗證 KBDB 只存在一個 Block
  • 2. 實作 WASI preview1 shim 與 WASM 執行核心(cypher-executor/src/lib/

    • 2.1 實作輕量 WASI preview1 shimwasi-shim.ts

      • 實作 fd_read(從 stdin buffer 讀取)、fd_write(寫入 stdout/stderr buffer)、proc_exit(拋出 Error)、random_getcrypto.getRandomValues
      • 其餘 syscall 一律回傳 ENOSYS76
      • 不引入任何外部依賴(不使用 @cloudflare/workers-wasi
      • Requirements: 3.1, 3.3
    • * 2.2 寫單元測試 for WASI shim

      • 測試 fd_read 正確讀取 stdin buffer(含多次讀取、邊界條件)
      • 測試 fd_write 正確寫入 stdout bufferfd=1)與 stderr bufferfd=2
      • 測試 proc_exit 拋出 Error
    • 2.3 實作 Tier 1 WASM 執行器(wasm-executor.ts

      • 從 R2 fetch .wasm ArrayBuffer
      • WebAssembly.compile 後快取 WebAssembly.ModuleWorker 記憶體,跨請求共享)
      • 建立 WASI shim,注入 stdin = JSON.stringify(input)
      • WebAssembly.instantiate(module, imports) → 呼叫 _start()main()
      • 從 stdout buffer 讀取輸出,JSON.parse 後回傳
      • 套用 max_cold_start_ms 逾時(Promise.race
      • Requirements: 3.1, 3.3, 6.6
    • * 2.4 寫 property test for Component Dispatcher 路由正確性

      • Property 4: Component Dispatcher 路由正確性
      • Validates: Requirements 3.1, 3.5, 3.6
      • 用 fast-check 生成合法 JSON input,驗證 WASM 執行路徑輸出與預期語意等效
  • 3. 建立 validate_json.wasm 第一個真實零件(TinyGo

    • 3.1 撰寫 validate_json TinyGo 原始碼(u6u-core/registry/components/validate_json/main.go

      • 只使用白名單 importosioencoding/json
      • 讀取 stdin JSON,解析 json_string 欄位,嘗試 json.Unmarshal
      • 成功輸出 {"valid":true},失敗輸出 {"valid":false,"error":"..."}
      • Requirements: 3.1, 11.6
    • 3.2 撰寫 validate_json component.contract.yaml

      • 包含所有必填欄位、gherkin_testshappy path + error path
      • runtime_compat: ["cf-workers","workerd","wazero"]
      • Requirements: 1.1, 1.2, 1.4
    • * 3.3 寫單元測試 for validate_jsonGherkin 場景驗證)

      • 測試合法 JSON 輸入回傳 {"valid":true}
      • 測試非法 JSON 輸入回傳 {"valid":false,"error":...}
  • 4. Checkpoint — Phase 0 驗收

    • 確認 validate_json.wasm 能在 CF Workers 環境中透過 WASM 執行器執行
    • 確認 Component Registry /guide/validate-contract/components 端點可用
    • 確認所有 Phase 0 測試通過,向使用者確認是否繼續 Phase 1

Phase 1:遷移現有零件(20 個 HTTP → WASM

  • 5. 升級 Component Dispatcher 支援雙模式(cypher-executor/src/lib/component-loader.ts

    • 5.1 重構 ComponentDescriptor 型別(移除舊 http_endpoint,新增 component_type

      • 定義 ComponentType = 'wasm' | 'cypher_binding' | 'service_binding'
      • 新版 ComponentDescriptor 欄位:component_typewasm_r2_keyruntime_compatmax_cold_start_msurlcypher_binding)、methodbindingservice_binding)、path
      • Requirements: 3.5
    • 5.2 實作路由決策邏輯(component-dispatcher.ts

      • 查 Component Registry 取得合約
      • component_type 分流:wasm → WASM 執行器;cypher_binding → HTTP POST 到外部 URLservice_binding → CF Service Binding
      • 檢查 runtime_compat 是否包含當前 Tier,不包含則回傳 RUNTIME_INCOMPATIBLE 錯誤
      • Requirements: 3.4, 6.1, 6.2
    • * 5.3 寫 property test for Dispatcher 錯誤結構完整性

      • Property 5: Dispatcher 錯誤結構完整性
      • Validates: Requirements 3.4, 6.4
      • 用 fast-check 生成 (component_id, tier) 組合,當 runtime_compat 不含當前 tier,驗證錯誤回應同時包含 component_id、tier、attempted_paths 三個欄位
  • 6. 遷移 20 個內建零件(u6u-core/builtins/u6u-core/registry/components/

    • 6.1 為每個零件撰寫 TinyGo 原始碼與 component.contract.yaml(批次作業)

      • 每個零件:只用白名單 import、stdin/stdout JSON I/O、附帶 gherkin_tests
      • 需要外部 API 的零件(如 gsheets):改用 cypher_binding 模式,contract 中記錄 cypher_binding_url
      • Requirements: 3.6, 11.6
    • 6.2 透過 POST /components 批次提交 20 個零件至 Component Registry

      • 每個零件通過沙盒驗收後自動寫入 KBDB
      • 驗證 20 個零件的 Gherkin 測試全部通過
      • Requirements: 2.1, 3.6
    • * 6.3 寫 property test for 歷史版本永久保留不變量

      • Property 8: 歷史版本永久保留不變量
      • Validates: Requirements 4.5, 10.5
      • 用 fast-check 生成已上架零件,標記為 deprecated 後,驗證 .wasm 仍可從 R2 讀取,pinned 引用仍可執行
  • 7. 實作 Component Registry 查詢端點

    • 7.1 實作 GET /components/:idGET /components/:id/versions

      • 透過 KBDB HTTP API 查詢 tpl-component blocks
      • /versions 回傳按「成功率 × 速度評分 × 被調用次數」排序的版本清單(最多 10 個)
      • Requirements: 12.3
    • 7.2 實作 GET /components/search?q=... 語意搜尋

      • 呼叫 KBDB Vectorize API,以 description + tags 欄位做語意搜尋
      • Requirements: 12.2
    • * 7.3 寫單元測試 for 查詢冪等性

      • 驗證相同查詢參數在 KBDB 資料不變時回傳相同結果
  • 8. Checkpoint — Phase 1 驗收

    • 確認 20 個零件全部通過沙盒驗收並存入 KBDB
    • 確認 Component Dispatcher 雙模式路由正確(WASM + cypher_binding
    • 確認所有 Phase 1 測試通過,向使用者確認是否繼續 Phase 2

Phase 2Cypher 語意擴展 + Multi-Tier Dispatcher

  • 9. 擴展 Cypher Triplet Parsercypher-executor/src/actions/triplet-parser.ts

    • 9.1 新增 EdgeType 定義

      • 在現有 PIPE | IF | FOREACH | CONTINUE 基礎上新增:IS_A | ON_SUCCESS | ON_FAIL | ON_CLICK | CALLS_SUBFLOW | CONTAINS | HAS_STYLE | HAS_BEHAVIOR
      • Requirements: 5.1
    • 9.2 實作 URI 協議解析函數(resolveComponentId

      • 解析 component://idcomponent://id@stablecomponent://id@pinned:vNworkflow://idui://idstyle://id
      • 回傳 { type, canonicalId, stability, pinnedVersion? }
      • Requirements: 4.1, 5.6
    • * 9.3 寫 property test for 零件 URI 解析 Round-Trip

      • Property 6: 零件 URI 解析 Round-Trip
      • Validates: Requirements 4.1
      • 用 fast-check 生成合法 URI 字串,解析後再序列化,驗證語意等效;驗證解析出的 id、stability、pinnedVersion 與原始 URI 完全一致
    • * 9.4 寫 property test for Cypher 三元組解析 Confluence

      • Property 9: Cypher 三元組解析 Confluence(順序無關性)
      • Validates: Requirements 5.7
      • 用 fast-check 生成合法三元組集合,用 fc.shuffledSubarray 打亂順序,驗證 parseTriplets 產生相同節點集合與邊集合
  • 10. 擴展 GraphExecutor 執行語意(cypher-executor/src/graph-executor.ts

    • 10.1 實作 IS_A 關係處理

      • 從 Component Registry 載入零件合約,以 input_schema 驗證節點輸入 context
      • Requirements: 5.2
    • 10.2 實作 ON_SUCCESS / ON_FAIL 分支執行

      • executeNode 的 try/catch 中,成功走 ON_SUCCESS 邊,失敗走 ON_FAIL 邊(傳遞 error context
      • Requirements: 5.3
    • 10.3 實作 CALLS_SUBFLOW 子流程呼叫

      • 從 KBDB 載入子 Workflow 定義,建立子 GraphExecutor 執行,將輸出合併回主流程 context
      • Requirements: 5.4
    • 10.4 實作 ON_CLICK 前端觸發處理

      • 接受來自前端 Smart Container 打包的 payload,作為 Workflow initialContext
      • Requirements: 5.5
    • 10.5 實作 CONTAINS / HAS_STYLE / HAS_BEHAVIOR 結構語意解析(不執行,僅記錄圖結構)

      • Requirements: 5.1
  • 11. 實作版本選擇策略(Component Dispatcher 升級)

    • 11.1 實作 floating 版本選擇算法

      • 從 KBDB 查詢該 id 下所有版本,計算「成功率 × 速度評分 × 被調用次數」,選取最高分版本
      • Requirements: 4.2
    • 11.2 實作 stable / pinned 版本選擇

      • stable:使用當前標記為 stable 的版本,有更優版本時記錄提示至 KBDB 但不切換
      • pinned:vN:永遠使用版本 vN,即使已 deprecated
      • Requirements: 4.3, 4.4
    • * 11.3 寫 property test for 版本選擇策略正確性

      • Property 7: 版本選擇策略正確性
      • Validates: Requirements 4.2, 4.4
      • 用 fast-check 生成版本集合(各有不同 success_rate、avg_duration_ms、call_count),驗證 floating 選最高分;驗證 pinned:vN 無論其他版本評分如何永遠選 vN
  • 12. 實作 Evaluator Agent 與評價迴圈(cypher-executor/src/actions/

    • 12.1 實作 execution-evaluator.ts(擴展現有 execution-logger.ts

      • Workflow 執行完畢後非同步寫入 KBDB Evaluation Blocktpl-evaluation
      • 記錄:run_id、workflow_id、component_id、verdict、duration_ms、error_message、evaluated_at
      • 冪等處理:相同 run_id 不重複建立 Block
      • Requirements: 10.1, 10.6
    • 12.2 實作 Pitfall Block 建立邏輯

      • 偵測某零件連續 5 次執行錯誤率 > 50%,建立 tpl-pitfall Block
      • 版本選擇時降低有 Pitfall 記錄的版本評分權重
      • Requirements: 10.2, 10.3
    • 12.3 實作零件自動 Deprecated / Tombstone 狀態轉換

      • 連續 30 天無引用 → 標記 deprecated,從預設搜尋移除
      • 再 90 天無引用 → 標記 tombstone,從所有搜尋移除(pinned .wasm 永久保留)
      • Requirements: 10.4, 10.5
    • * 12.4 寫 property test for 系統操作冪等性

      • Property 11: 系統操作冪等性
      • Validates: Requirements 10.6, 12.5
      • 用 fast-check 生成 run_id,對相同 run_id 呼叫 Evaluator N 次,驗證 KBDB 只存在一個 Evaluation Block
      • 驗證相同查詢參數在資料不變時回傳相同結果
  • 13. Checkpoint — Phase 2 驗收

    • 確認新 EdgeType 全部可解析執行(IS_A、ON_SUCCESS、ON_FAIL、CALLS_SUBFLOW、ON_CLICK
    • 確認版本選擇策略(floating / stable / pinned)行為正確
    • 確認 Evaluator Agent 冪等寫入 KBDB
    • 確認所有 Phase 2 測試通過,向使用者確認是否繼續 Phase 3

Phase 3:前端畫布(Web Components + 雙面翻轉)

  • 14. 建立 Web Components 零件庫(u6u-core/web-components/

    • 14.1 實作 <u6u-btn> Custom Element

      • 支援 attributeslabelcolortooltipworkflowdisabled
      • workflow 設定且點擊時發出 u6u:trigger CustomEvent{ workflowId, payload }
      • workflow 未設定時點擊不發出事件,console 輸出警告
      • Requirements: 8.2, 8.3
    • 14.2 實作 <u6u-text-input><u6u-text-field> Custom Elements

      • 支援 nameplaceholdervalue attributes
      • value property 可被 <u6u-card> 讀取
      • Requirements: 8.1
    • 14.3 實作 <u6u-card> Smart Container

      • 攔截子元件的 u6u:trigger 事件(stopPropagation
      • 收集同容器內所有 <u6u-text-input> / <u6u-text-field> 的 name-value 對
      • 合併至 payload 後重新發出 u6u:triggerbubbles: true, composed: true
      • Requirements: 8.4
    • 14.4 實作 <u6u-chart> Custom Element(基礎版)

      • 支援 data attributeJSON 字串)、基本折線圖渲染
      • Requirements: 8.1
    • * 14.5 寫 property test for Web Components 事件與渲染冪等性

      • Property 10: Web Components 事件與渲染冪等性
      • Validates: Requirements 8.3, 8.4, 8.5
      • 用 fast-check 生成 workflow URI,驗證點擊後 u6u:trigger detail.workflowId 與 URI id 完全一致
      • 用 fast-check 生成具名 input 集合置於 u6u-card,驗證收集到的 payload 包含所有 name-value 對
      • 用 fast-check 生成 attribute 值,對同一元件設定相同值 N 次,驗證渲染結果冪等
  • 15. 建立雙面翻轉畫布(inkstone-admin/frontend/web/

    • 15.1 實作翻轉狀態機(Canvas.tsx

      • 狀態:UIViewLogicView(點擊翻面按鈕切換)
      • LogicViewEditing(修改三元組)→ Saving(確認儲存)→ LogicView
      • Requirements: 9.1
    • 15.2 實作邏輯視圖(Cypher 三元組視覺化)

      • 顯示零件關聯的 Cypher 三元組(節點連線方式)
      • 修改三元組後即時更新 KBDB Workflow Block(透過 KBDB HTTP API
      • Requirements: 9.2
    • 15.3 實作 Workflow URI 選擇器

      • 列出 KBDB 中所有可用 Workflow,下拉選單完成 ON_CLICK >> workflow://id 綁定
      • Requirements: 9.3
    • 15.4 實作 Smart Container 拖放與自動打包關係顯示

      • 拖入同一 <u6u-card> 時,邏輯視圖自動顯示 CONTAINS 關係與自動打包說明
      • Requirements: 9.4
    • 15.5 實作零件替換過濾器

      • 替換已綁定 Workflow 的 UI 零件時,只顯示具備 u6u:trigger 能力的候選零件
      • Requirements: 9.5
    • 15.6 在畫布中整合 u6u Web ComponentsDogfooding

      • 畫布 UI 本身使用 <u6u-btn><u6u-card><u6u-text-input> 組裝
      • 驗證 Web Components 在 React 19 環境中正確運作
      • Requirements: 8.1, 9.1
    • * 15.7 寫整合測試 for 畫布翻轉流程

      • 測試 UIView → LogicView → Editing → Saving → LogicView 完整狀態轉換
      • 測試 KBDB 寫入成功與失敗兩種情境
  • 16. Final Checkpoint — 全平台驗收

    • 確認四個 Phase 的所有測試通過(pnpm test in each service
    • 確認 Dogfooding:畫布本身用 u6u Web Components 組裝,每一層都是下一層的第一個用戶
    • 確認 KBDB 不變量:仍只有三張表(blocks / templates / slots
    • 確認 API-First 鐵律:所有跨服務通訊只透過 HTTP API
    • 向使用者確認所有任務完成

Phase 4:邊緣基礎設施(Tier 3 支援)

這個 Phase 不在零件遷移範圍內,是獨立的基礎設施工作。

  • 17. Credentials 邊緣支援評估與改寫(u6u-core/credentials/

    • 17.1 評估 Tier 3 是否需要 Credentials

      • 場景:無人機在有網路時呼叫外部 API(如取得感測器資料),需要 access_token
      • 結論:Tier 3 需要在連網時從 Tier 2 取得 Credential,離線時使用本地快取的加密 token
      • Requirements: 7.1, 7.2
    • 17.2 實作 Credential 本地快取機制(Tier 3 用)

      • Tier 3 Go 排程引擎在連網時從 Tier 2 Credentials Worker 取得加密 token
      • 存入本地 SQLiteAES-GCM 加密,key 存於設備安全儲存)
      • 離線時從本地快取讀取,過期時加入 DTN 佇列等待更新
      • Requirements: 7.1, 7.3
  • 18. Go Cypher ExecutorTier 3 邊緣執行引擎)(u6u-core/executor/

    • 18.1 用 Go 實作 Cypher 三元組解析器

      • 解析 "A >> 關係 >> B" 格式,建立執行圖(nodes + edges
      • 支援 IS_A、ON_SUCCESS、ON_FAIL、CALLS_SUBFLOW、ON_CLICK 語意關係
      • 對應 cypher-executor/src/actions/triplet-parser.ts 的 Go 版本
      • Requirements: 5.1, 5.7
    • 18.2 用 Go + Wazero 實作 WASM 零件執行器

      • 載入本地 .wasm 檔案,透過 Wazero 原生 WASI preview1 執行
      • 注入 u6u host modulehttp_request host function,透過 DTN 或直接 HTTP
      • stdin/stdout JSON I/O,與 Tier 1/2 的 wasm-executor.ts 語意等效
      • Requirements: 7.1, 7.4
    • 18.3 實作 DTN 佇列(離線請求緩衝)

      • 零件需要網路但當前離線時,寫入本地 SQLite DTN 佇列
      • 連網時 Burst 傳輸:批次送出佇列中的請求,接收回應後繼續執行
      • Requirements: 7.2, 7.5
    • * 18.4 整合測試:validate_json.wasm 在 Wazero 執行

      • 確認同一個 .wasm 在 Tier 1wasi-shim.ts)和 Tier 3Wazero)執行結果一致

Notes

  • 標記 * 的子任務為選填,可跳過以加速 MVP 交付
  • 每個任務都引用具體的 Requirements 條款以確保可追溯性
  • Checkpoint 任務確保每個 Phase 完成後有明確的驗收點
  • Property tests 使用 fast-check,每個屬性最少執行 100 次迭代
  • 所有跨服務呼叫只透過 KBDB HTTP API,不直接操作 D1 SQL
  • TinyGo 零件只使用白名單 importosioencoding/json

Phase 5u6u-mcp 對齊新 Registry + u6u-gui 前端

壓測前必須完成,讓 AIu6u-mcp)和人類(u6u-gui)都能操作新的 WASM 零件架構。

  • 19. 更新 u6u-mcp 對齊新 Component Registryu6u-mcp/src/tools/

    • 19.1 更新 u6u_publish_component

      • 舊:呼叫 /components/publishpayload 為 { component_id, gherkin, api_config }
      • 新:呼叫 POST /componentspayload 為 { contract: ComponentContract, wasm_base64: string }
      • 新增 contractwasm_base64 參數,更新工具描述說明 TinyGo 零件提交流程
    • 19.2 更新 u6u_search_components

      • 舊:呼叫 /components/match(不存在的端點)
      • 新:呼叫 GET /components/search?q={query}(新 Registry 語意搜尋端點)
      • 更新工具描述:AI 可用自然語言搜尋零件(如「查詢 Google Sheets 資料」)
    • 19.3 更新 u6u_get_component

      • 舊:讀舊格式 slotscomponent_idnamepublished_at
      • 新:對齊 tpl-component slot 欄位(canonical_iddisplay_namecategoryversionstabilitywasm_r2_key 等)
      • 呼叫新 Registry GET /components/:id 端點
    • 19.4 新增 u6u_get_component_guide 工具

      • 呼叫 GET /components/guide,回傳開發指引給 AI
      • AI 在開發新零件前可先讀取指引,確保生成符合規範的 TinyGo 程式碼
  • 20. 建立 u6u-gui 前端(u6u-gui/

    • 20.1 建立 Cloudflare Pages 專案結構

      • React 19 + Vite + Tailwind CSS v4
      • 整合 @u6u/web-componentsalias 指向 u6u-core/web-components/src
      • wrangler.toml 設定 Pages 部署
    • 20.2 建立主畫布頁面(/canvas

      • 整合 Canvas.tsx(從 inkstone-admin 移植)
      • 連接 Cypher Executor APIPOST /cypher/execute
      • 連接 Component Registry API(搜尋、查詢零件)
      • AI 操作後(透過 u6u-mcp 修改 KBDB)畫布即時反映變更
    • 20.3 建立零件庫頁面(/components

      • 列出所有已上架零件(呼叫 GET /components/search
      • 顯示零件合約、評分、版本歷史
      • 提供「提交新零件」入口(連結到開發指引)
    • 20.4 建立 Workflow 管理頁面(/workflows

      • 列出所有 Workflow(從 KBDB 查詢 tpl-workflow
      • 點擊進入畫布編輯
      • 顯示執行歷史(Evaluation Block
    • 20.5 部署至 Cloudflare Pages

      • pnpm build && npx wrangler pages deploy dist
      • 設定環境變數(KBDB_URL、CYPHER_URL、REGISTRY_URL