# Implementation Plan: u6u Platform Evolution ## Overview 依照 Bootstrap 順序分四個 Phase 實作,每個 Phase 都是下一個 Phase 的基礎。 技術棧:TypeScript、Hono、Zod、Vitest、fast-check,部署於 Cloudflare Workers。 --- ## Phase 0:最小 WASM 執行核心 - [x] 1. 建立 Component Registry 基礎架構(`u6u-core/registry/`) - [x] 1.1 建立 `tpl-component` Template Block(透過 KBDB HTTP API) - 呼叫 KBDB `/templates` 建立 `tpl-component` template(若不存在) - 定義所有 slot keys(canonical_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_ - [x] 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 必定通過 - [x] 1.4 實作 `GET /components/guide` 端點 - 回傳 Markdown 格式開發指引(TinyGo 白名單、禁止行為、contract YAML 範例、wasmtime 測試指令) - _Requirements: 11.1, 11.2, 11.3_ - [x] 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 寫入 Block(`block_id = comp-{id}-{version}`) - 同時上傳 `.wasm` 至 R2,slot `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 - [x] 2. 實作 WASI preview1 shim 與 WASM 執行核心(`cypher-executor/src/lib/`) - [x] 2.1 實作輕量 WASI preview1 shim(`wasi-shim.ts`) - 實作 `fd_read`(從 stdin buffer 讀取)、`fd_write`(寫入 stdout/stderr buffer)、`proc_exit`(拋出 Error)、`random_get`(`crypto.getRandomValues`) - 其餘 syscall 一律回傳 ENOSYS(76) - 不引入任何外部依賴(不使用 `@cloudflare/workers-wasi`) - _Requirements: 3.1, 3.3_ - [x]* 2.2 寫單元測試 for WASI shim - 測試 `fd_read` 正確讀取 stdin buffer(含多次讀取、邊界條件) - 測試 `fd_write` 正確寫入 stdout buffer(fd=1)與 stderr buffer(fd=2) - 測試 `proc_exit` 拋出 Error - [x] 2.3 實作 Tier 1 WASM 執行器(`wasm-executor.ts`) - 從 R2 fetch `.wasm` ArrayBuffer - `WebAssembly.compile` 後快取 `WebAssembly.Module`(Worker 記憶體,跨請求共享) - 建立 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 執行路徑輸出與預期語意等效 - [x] 3. 建立 `validate_json.wasm` 第一個真實零件(TinyGo) - [x] 3.1 撰寫 `validate_json` TinyGo 原始碼(`u6u-core/registry/components/validate_json/main.go`) - 只使用白名單 import:`os`、`io`、`encoding/json` - 讀取 stdin JSON,解析 `json_string` 欄位,嘗試 `json.Unmarshal` - 成功輸出 `{"valid":true}`,失敗輸出 `{"valid":false,"error":"..."}` - _Requirements: 3.1, 11.6_ - [x] 3.2 撰寫 `validate_json` component.contract.yaml - 包含所有必填欄位、gherkin_tests(happy path + error path) - `runtime_compat: ["cf-workers","workerd","wazero"]` - _Requirements: 1.1, 1.2, 1.4_ - [ ]* 3.3 寫單元測試 for validate_json(Gherkin 場景驗證) - 測試合法 JSON 輸入回傳 `{"valid":true}` - 測試非法 JSON 輸入回傳 `{"valid":false,"error":...}` - [x] 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) - [x] 5. 升級 Component Dispatcher 支援雙模式(`cypher-executor/src/lib/component-loader.ts`) - [x] 5.1 重構 `ComponentDescriptor` 型別(移除舊 `http_endpoint`,新增 `component_type`) - 定義 `ComponentType = 'wasm' | 'cypher_binding' | 'service_binding'` - 新版 `ComponentDescriptor` 欄位:`component_type`、`wasm_r2_key`、`runtime_compat`、`max_cold_start_ms`、`url`(cypher_binding)、`method`、`binding`(service_binding)、`path` - _Requirements: 3.5_ - [x] 5.2 實作路由決策邏輯(`component-dispatcher.ts`) - 查 Component Registry 取得合約 - 依 `component_type` 分流:`wasm` → WASM 執行器;`cypher_binding` → HTTP POST 到外部 URL;`service_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 三個欄位 - [x] 6. 遷移 20 個內建零件(`u6u-core/builtins/` → `u6u-core/registry/components/`) - [x] 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_ - [x] 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 引用仍可執行 - [x] 7. 實作 Component Registry 查詢端點 - [x] 7.1 實作 `GET /components/:id` 與 `GET /components/:id/versions` - 透過 KBDB HTTP API 查詢 `tpl-component` blocks - `/versions` 回傳按「成功率 × 速度評分 × 被調用次數」排序的版本清單(最多 10 個) - _Requirements: 12.3_ - [x] 7.2 實作 `GET /components/search?q=...` 語意搜尋 - 呼叫 KBDB Vectorize API,以 `description` + `tags` 欄位做語意搜尋 - _Requirements: 12.2_ - [ ]* 7.3 寫單元測試 for 查詢冪等性 - 驗證相同查詢參數在 KBDB 資料不變時回傳相同結果 - [x] 8. Checkpoint — Phase 1 驗收 - 確認 20 個零件全部通過沙盒驗收並存入 KBDB - 確認 Component Dispatcher 雙模式路由正確(WASM + cypher_binding) - 確認所有 Phase 1 測試通過,向使用者確認是否繼續 Phase 2 --- ## Phase 2:Cypher 語意擴展 + Multi-Tier Dispatcher - [x] 9. 擴展 Cypher Triplet Parser(`cypher-executor/src/actions/triplet-parser.ts`) - [x] 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_ - [x] 9.2 實作 URI 協議解析函數(`resolveComponentId`) - 解析 `component://id`、`component://id@stable`、`component://id@pinned:vN`、`workflow://id`、`ui://id`、`style://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` 產生相同節點集合與邊集合 - [x] 10. 擴展 GraphExecutor 執行語意(`cypher-executor/src/graph-executor.ts`) - [x] 10.1 實作 `IS_A` 關係處理 - 從 Component Registry 載入零件合約,以 `input_schema` 驗證節點輸入 context - _Requirements: 5.2_ - [x] 10.2 實作 `ON_SUCCESS` / `ON_FAIL` 分支執行 - 在 `executeNode` 的 try/catch 中,成功走 `ON_SUCCESS` 邊,失敗走 `ON_FAIL` 邊(傳遞 error context) - _Requirements: 5.3_ - [x] 10.3 實作 `CALLS_SUBFLOW` 子流程呼叫 - 從 KBDB 載入子 Workflow 定義,建立子 GraphExecutor 執行,將輸出合併回主流程 context - _Requirements: 5.4_ - [x] 10.4 實作 `ON_CLICK` 前端觸發處理 - 接受來自前端 Smart Container 打包的 payload,作為 Workflow initialContext - _Requirements: 5.5_ - [x] 10.5 實作 `CONTAINS` / `HAS_STYLE` / `HAS_BEHAVIOR` 結構語意解析(不執行,僅記錄圖結構) - _Requirements: 5.1_ - [x] 11. 實作版本選擇策略(Component Dispatcher 升級) - [x] 11.1 實作 floating 版本選擇算法 - 從 KBDB 查詢該 id 下所有版本,計算「成功率 × 速度評分 × 被調用次數」,選取最高分版本 - _Requirements: 4.2_ - [x] 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 - [x] 12. 實作 Evaluator Agent 與評價迴圈(`cypher-executor/src/actions/`) - [x] 12.1 實作 `execution-evaluator.ts`(擴展現有 `execution-logger.ts`) - Workflow 執行完畢後非同步寫入 KBDB Evaluation Block(`tpl-evaluation`) - 記錄:run_id、workflow_id、component_id、verdict、duration_ms、error_message、evaluated_at - 冪等處理:相同 run_id 不重複建立 Block - _Requirements: 10.1, 10.6_ - [x] 12.2 實作 Pitfall Block 建立邏輯 - 偵測某零件連續 5 次執行錯誤率 > 50%,建立 `tpl-pitfall` Block - 版本選擇時降低有 Pitfall 記錄的版本評分權重 - _Requirements: 10.2, 10.3_ - [x] 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 - 驗證相同查詢參數在資料不變時回傳相同結果 - [x] 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 + 雙面翻轉) - [x] 14. 建立 Web Components 零件庫(`u6u-core/web-components/`) - [x] 14.1 實作 `` Custom Element - 支援 attributes:`label`、`color`、`tooltip`、`workflow`、`disabled` - `workflow` 設定且點擊時發出 `u6u:trigger` CustomEvent(`{ workflowId, payload }`) - `workflow` 未設定時點擊不發出事件,console 輸出警告 - _Requirements: 8.2, 8.3_ - [x] 14.2 實作 `` 與 `` Custom Elements - 支援 `name`、`placeholder`、`value` attributes - `value` property 可被 `` 讀取 - _Requirements: 8.1_ - [x] 14.3 實作 `` Smart Container - 攔截子元件的 `u6u:trigger` 事件(`stopPropagation`) - 收集同容器內所有 `` / `` 的 name-value 對 - 合併至 payload 後重新發出 `u6u:trigger`(`bubbles: true, composed: true`) - _Requirements: 8.4_ - [x] 14.4 實作 `` Custom Element(基礎版) - 支援 `data` attribute(JSON 字串)、基本折線圖渲染 - _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 次,驗證渲染結果冪等 - [x] 15. 建立雙面翻轉畫布(`inkstone-admin/frontend/web/`) - [x] 15.1 實作翻轉狀態機(`Canvas.tsx`) - 狀態:`UIView` ↔ `LogicView`(點擊翻面按鈕切換) - `LogicView` → `Editing`(修改三元組)→ `Saving`(確認儲存)→ `LogicView` - _Requirements: 9.1_ - [x] 15.2 實作邏輯視圖(Cypher 三元組視覺化) - 顯示零件關聯的 Cypher 三元組(節點連線方式) - 修改三元組後即時更新 KBDB Workflow Block(透過 KBDB HTTP API) - _Requirements: 9.2_ - [x] 15.3 實作 Workflow URI 選擇器 - 列出 KBDB 中所有可用 Workflow,下拉選單完成 `ON_CLICK >> workflow://id` 綁定 - _Requirements: 9.3_ - [x] 15.4 實作 Smart Container 拖放與自動打包關係顯示 - 拖入同一 `` 時,邏輯視圖自動顯示 CONTAINS 關係與自動打包說明 - _Requirements: 9.4_ - [x] 15.5 實作零件替換過濾器 - 替換已綁定 Workflow 的 UI 零件時,只顯示具備 `u6u:trigger` 能力的候選零件 - _Requirements: 9.5_ - [x] 15.6 在畫布中整合 u6u Web Components(Dogfooding) - 畫布 UI 本身使用 ``、``、`` 組裝 - 驗證 Web Components 在 React 19 環境中正確運作 - _Requirements: 8.1, 9.1_ - [ ]* 15.7 寫整合測試 for 畫布翻轉流程 - 測試 UIView → LogicView → Editing → Saving → LogicView 完整狀態轉換 - 測試 KBDB 寫入成功與失敗兩種情境 - [x] 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 - 存入本地 SQLite(AES-GCM 加密,key 存於設備安全儲存) - 離線時從本地快取讀取,過期時加入 DTN 佇列等待更新 - _Requirements: 7.1, 7.3_ - [ ] 18. Go Cypher Executor(Tier 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 module(`http_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 1(wasi-shim.ts)和 Tier 3(Wazero)執行結果一致 --- ## Notes - 標記 `*` 的子任務為選填,可跳過以加速 MVP 交付 - 每個任務都引用具體的 Requirements 條款以確保可追溯性 - Checkpoint 任務確保每個 Phase 完成後有明確的驗收點 - Property tests 使用 fast-check,每個屬性最少執行 100 次迭代 - 所有跨服務呼叫只透過 KBDB HTTP API,不直接操作 D1 SQL - TinyGo 零件只使用白名單 import(`os`、`io`、`encoding/json`) ## Phase 5:u6u-mcp 對齊新 Registry + u6u-gui 前端 > 壓測前必須完成,讓 AI(u6u-mcp)和人類(u6u-gui)都能操作新的 WASM 零件架構。 - [x] 19. 更新 u6u-mcp 對齊新 Component Registry(`u6u-mcp/src/tools/`) - [x] 19.1 更新 `u6u_publish_component` - 舊:呼叫 `/components/publish`,payload 為 `{ component_id, gherkin, api_config }` - 新:呼叫 `POST /components`,payload 為 `{ contract: ComponentContract, wasm_base64: string }` - 新增 `contract` 和 `wasm_base64` 參數,更新工具描述說明 TinyGo 零件提交流程 - [x] 19.2 更新 `u6u_search_components` - 舊:呼叫 `/components/match`(不存在的端點) - 新:呼叫 `GET /components/search?q={query}`(新 Registry 語意搜尋端點) - 更新工具描述:AI 可用自然語言搜尋零件(如「查詢 Google Sheets 資料」) - [x] 19.3 更新 `u6u_get_component` - 舊:讀舊格式 slots(`component_id`、`name`、`published_at`) - 新:對齊 `tpl-component` slot 欄位(`canonical_id`、`display_name`、`category`、`version`、`stability`、`wasm_r2_key` 等) - 呼叫新 Registry `GET /components/:id` 端點 - [x] 19.4 新增 `u6u_get_component_guide` 工具 - 呼叫 `GET /components/guide`,回傳開發指引給 AI - AI 在開發新零件前可先讀取指引,確保生成符合規範的 TinyGo 程式碼 - [x] 20. 建立 u6u-gui 前端(`u6u-gui/`) - [x] 20.1 建立 Cloudflare Pages 專案結構 - React 19 + Vite + Tailwind CSS v4 - 整合 `@u6u/web-components`(alias 指向 `u6u-core/web-components/src`) - wrangler.toml 設定 Pages 部署 - [x] 20.2 建立主畫布頁面(`/canvas`) - 整合 `Canvas.tsx`(從 inkstone-admin 移植) - 連接 Cypher Executor API(`POST /cypher/execute`) - 連接 Component Registry API(搜尋、查詢零件) - AI 操作後(透過 u6u-mcp 修改 KBDB)畫布即時反映變更 - [x] 20.3 建立零件庫頁面(`/components`) - 列出所有已上架零件(呼叫 `GET /components/search`) - 顯示零件合約、評分、版本歷史 - 提供「提交新零件」入口(連結到開發指引) - [x] 20.4 建立 Workflow 管理頁面(`/workflows`) - 列出所有 Workflow(從 KBDB 查詢 `tpl-workflow`) - 點擊進入畫布編輯 - 顯示執行歷史(Evaluation Block) - [x] 20.5 部署至 Cloudflare Pages - `pnpm build && npx wrangler pages deploy dist` - 設定環境變數(KBDB_URL、CYPHER_URL、REGISTRY_URL)