Files
Arcrun/.agents/specs/arcrun/arcrun.md
T
uncle6me-web 922a57fe34 arcrun — AI workflow execution engine (clean history)
Self-hosted 開源:WASM 零件 + recipe + cypher-executor,跑在你自己的 Cloudflare。

此為重建的乾淨歷史起點(移除曾誤 commit 的 GCP SA 金鑰,舊歷史保留在
richblack/arcrun 與本地 backup 分支)。含:
- acr init --self-hosted installer(建 KV/R2 + codeload 拉預編譯 wasm + wrangler deploy + seed recipe)
- recipe push 把關(資料外流提醒 + 打通檢查)
- 19 個正當零件預編譯 wasm(claude_api/km_writer/kbdb_upsert_block 排除:違反 DECISIONS §1)
- CLI / cypher-executor / registry / 完整 SDD

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 15:52:38 +08:00

382 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# arcrun — 進度與待辦
> 設計細節見 `arcrun/README.md`(產品說明)和 `arcrun/BETA_TEST.md`(封測指南)。
> 這份文件只記錄:目前狀態、還差什麼、封測能不能啟動。
---
## 一、封測目標場景
封測者是工程師朋友,有自己的網頁,需要後端自動化。目標是他能在 AI 協助下,一次或很少次完成以下完整流程:
1. `acr init` 取得 api_key
2. `acr parts scaffold` 查零件格式,AI 幫寫 workflow YAML
3. 若內建零件不足,`acr recipe push` 增加打外部 API 的 recipe
4. `acr creds push` 上傳 OAuth tokengmail / google_sheets 等)
5. `acr push` 部署 workflow,取得 Webhook URL
6. 網頁 POST /webhooks/named/{name}/trigger,結果存 Google Sheets
---
## 二、場景各步驟驗證狀態
### Step 1acr init → api_key
- [x] `acr init` Standard 模式完成,api_key 存入 `~/.arcrun/config.yaml`
- [x] 已驗證:`mode: standard, api_key: ak_...` 正確
### Step 2acr parts scaffold → AI 看到零件格式
- [x] `acr parts` 列出 21 個零件,完全內建,不依賴 registry.arcrun.dev
- [x] `acr parts scaffold google_sheets` 輸出 spreadsheet_id / range / operation / values 格式與 credentials.yaml 範本
- [x] 已驗證:輸出可直接貼入 YAML
### Step 3acr recipe push → 打外部 API
- [x] `acr recipe push` 上傳成功,回傳 rec_hash
- [x] workflow 使用 `component: rec_xxxxxxxx`acr push 後 trigger 能正確呼叫外部 API
- [x] 已驗證(2026-04-18):httpbin_post recipe → trigger → httpbin.org/post 回傳正確 ✅
### Step 4acr creds push → 自動注入 token
- [x] `POST /credentials` API 完成,以 `{api_key}:cred:{name}` 存入 KV
- [x] Webhook trigger 時 injectCredentials 從 KV 取得 token 自動注入
- [x] `/register` 現在回傳 `encryption_key``acr init` 自動存入 config
- [x] `acr creds push` 從 config 讀 encryption_key,不再需要手動設定環境變數
- [x] 已驗證(2026-04-18):beta@arcrun.dev 帳號完整流程:init → creds push → trigger → credential 注入成功 ✅
### Step 5acr push → Webhook URL
- [x] `acr push workflow.yaml` 部署成功,顯示 Webhook URL 和完整 curl 範例
- [x] config 中的 `component` / 參數在 push 時套入 graph 節點
- [x] 已驗證(2026-04-18):sheet-test workflow push 成功 ✅
### Step 6:網頁 POST → 執行 → 結果到 Google Sheets
- [x] `POST /webhooks/named/{name}/trigger -H 'X-Arcrun-API-Key: ...'` 觸發執行正常
- [x] google_sheets 零件有實作(append row 到 Sheets API
- [x] 已驗證(2026-04-18):trigger sheet-test → 報「缺少 credential」(符合預期,credential 未上傳)✅
- [ ] **未驗證**:真實 google_oauth token + acr creds push → trigger → Google Sheets 實際寫入
- 需要真實 OAuth token 才能完整驗證
---
## 三、封測啟動阻擋項
P0 全部清除才啟動封測。
| # | 項目 | 狀態 | 說明 |
|---|------|------|------|
| 1 | acr parts scaffold 正確輸出 | ✅ 完成 | 21 個零件內建清單 |
| 2 | acr recipe push 端對端 | ✅ 完成 | httpbin_post 驗證通過 |
| 3 | acr creds push 代碼 | ✅ 完成 | 需 ARCRUN_ENCRYPTION_KEY |
| 4 | credential 注入端對端 | ✅ 完成 | 無 token 時錯誤訊息正確 |
| 5 | acr push + webhook trigger | ✅ 完成 | 端對端驗證通過 |
| 6 | acr creds push 實測 | ✅ 完成 | /register 回傳 encryption_keyacr init 自動存入 configCLI 1.0.9|
| 7 | Google Sheets 真實寫入 | ⚠️ 部分驗證 | credential 注入已驗證;實際 Sheets 寫入需真實 OAuth token |
| 8 | 第三方服務認證 recipe | ✅ 完成 | 20 個服務(Notion/Slack/GitHub/OpenAI 等),CLI 1.1.0 |
| **9** | **cypher-executor outbound HTTP fetch 全失效** | ✅ **已解決 2026-05-13**(CF 同 zone 自循環死鎖,改走 workers.dev)| 詳見下方專段 |
| **10** | **multi-node chain context propagation 漏失** | ✅ **已解決 2026-05-13**ON_SUCCESS/ON_FAIL/IF/ON_CLICK 沒 spread baseCtx| 詳見下方專段 |
**目前狀況**P0 全部解決。
- #9 修復方式:component worker URL 從 `*.arcrun.dev`(同 cypher zone)改走 `arcrun-{name}.{WORKER_SUBDOMAIN}.workers.dev`(避開同 zone 自循環)
- #10 修復方式:4 個 edge type 補 `{...baseCtx, ...result}`,跟 PIPE/FOREACH 一致
兩個 P0 解完 mira 7 節點 workflow 端對端通(含真 Claude 16 秒呼叫)。
---
### ✅ P0 #92026-05-13 已解決):cypher-executor outbound fetch 全失效
**完整事件報告(含誤判路徑)**[docs/incidents/2026-05-13-cypher-outbound-522.md](../../../docs/incidents/2026-05-13-cypher-outbound-522.md)
**修復方式**cypher-executor fetch component worker 從 `*.arcrun.dev`(同 zone)改走 `arcrun-{name}.{WORKER_SUBDOMAIN}.workers.dev`。對外 `cypher.arcrun.dev` 不變,用戶 0 感知。
**改動檔案**2026-05-13):
- `cypher-executor/src/lib/component-loader.ts``wasmWorkerUrl(canonicalId, subdomain)` 簽名加 subdomain 參數 + URL pattern 改 workers.dev
- `cypher-executor/src/actions/auth-dispatcher.ts`:同步新簽名
- `cypher-executor/src/types.ts``Bindings``WORKER_SUBDOMAIN: string`
- `cypher-executor/wrangler.toml``[vars]``WORKER_SUBDOMAIN = "uncle6-me"`
- 5 個 component worker 在 dashboard 啟用 workers.dev URLkbdb-get / kbdb-ingest / kbdb-create-block / kbdb-patch-block / claude-api**未來新 component 也都要開**
**驗證**cypher-executor → kbdb-get / claude-api 從 522 → 200。mira `acr run wiki_synthesis` 5 節點 workflow 跑通前 3 節點(kbdb_get chain)。
**Self-hosted fork 注意**:必須改 `wrangler.toml [vars] WORKER_SUBDOMAIN` 為自己的 CF 帳號 subdomain,並把所有 component worker 在 dashboard 啟用 workers.dev URL。
---
### ✅ P0 #102026-05-13 已解決):multi-node chain context propagation 漏失
**現象**cypher binding workflow 從第 2 個節點開始,原始 input contexttop-level `api_key` / `mira_token` 等)丟失,下游節點 `{{api_key}}` 模板原文未替換傳給零件 → 401 Unauthorized 或類似錯。
**測試重現**
```yaml
flow:
- "input >> ON_SUCCESS >> n1"
- "n1 >> ON_SUCCESS >> n2"
config:
n1: { component: kbdb_get, api_key: "{{api_key}}", block_id: "{{b1}}" }
n2: { component: kbdb_get, api_key: "{{api_key}}", block_id: "{{b2}}" }
context: { api_key: "ak_xxx", b1: "...", b2: "..." }
```
n1 收到 ctx 含 `api_key / b1 / b2` ✓ → 跑通。
n2 收到的 ctx 只有 `n1.output spread`blocks/count/success/block_id),**`api_key / b1 / b2` 不見**`{{api_key}}` 原文傳到零件回 401。
**根因**`graph-executor.ts` 在 PIPE / FOREACH 邊類型已修「baseCtx result」,但 **ON_SUCCESS / ON_FAIL / IF / ON_CLICK 四個 edge type 沒套同模式**,直接把 `result` 當下游 ctx 傳,丟掉原始 context。
**修法**`cypher-executor/src/graph-executor.ts` line 407 / 415 / 423 / 472):
```typescript
// 改前
result = await this.executeNode(nextNode, graph, result, ...);
// 改後(同 PIPE/FOREACH 模式)
const baseCtx = (typeof context === 'object' && context !== null) ? context as Record<string, unknown> : {};
const baseResult = (typeof result === 'object' && result !== null) ? result as Record<string, unknown> : {};
const mergedCtx = { ...baseCtx, ...baseResult };
result = await this.executeNode(nextNode, graph, mergedCtx, ...);
```
**驗證**mira `acr run wiki_synthesis` 7 節點 workflow 端對端跑通(16 秒,含真 Claude 呼叫)。每個節點都拿到正確 `api_key` 不再 401。
**歷史脈絡**:類似問題 2026-05-07 commit e8fca33 在 FOREACH edge 已修一次("FOREACH preserves outer context"),但當時沒同步處理另外 4 個 edge type。本次補完。
---
### ✅ P0 #10 補完三個衍生問題(2026-05-13 晚 ~ 2026-05-14
P0 #10 修完後 mira 嘗試做 wiki 多段結構,又踩出三個 cypher binding 設計缺陷。**都是同一天解掉**。
#### A. interpolateData() 不遞迴 nested object
**現象**`set` / `kbdb_create_block``values: { text: "{{classify.data.text}}" }``tags_json: ["facet:{{paragraph.facet}}"]` 等 nested config 內的 `{{x}}` 不被替換,原文傳給零件。
**根因**`interpolateData()` 只 iterate top-level,對非 string 值(object / array)直接 pass-through 不下沉。
**修法**:拆 `interpolateString` + `interpolateValue`(遞迴 object / array),`interpolateData` 改 call `interpolateValue`
**測試**`set values: { text: "hello {{name}}", arr: ["item {{name}}"] }``name=world` → 全展開。
#### B. ctx 沒存上游 output 的 node id namespace
**現象**`{{classify.data.text}}` 找不到上游 classify 的 output;只能用 `{{data.text}}`(直接 spread 取),但會被下個節點覆蓋,多節點 chain 用不了。
**根因**`propagateCtx` 只把上游 result spread 進 ctx,沒額外存 `[node.id]: result`
**修法**`propagateCtx` 改回傳 `{ ...baseCtx, ...baseResult, [upstreamNodeId]: upstreamResult }`。讓下游能用 `{{node_id.data.text}}` 從 namespace 取,永不被覆蓋。
**測試**5 節點 chain 用 `{{load_schema.blocks.0.content}}` / `{{classify.data.text}}` 全展開。
#### C. FOREACH 找 iterable 只看 result,不看 ctx + 不看 nested
**現象**mira wiki_synthesis 雙重 FOREACH(外層 `對每個 paragraph`、內層 `對每個 triplet`),外層 OK,內層跑 0 次。
**根因 (C1)**`getIterableFromContext(result, key)` 只看當前節點 output。`result``create_paragraph` output`{data, success}`),不含 paragraphs。但 `paragraphs` 早就在 ctx 從 classify spread 來。
**根因 (C2)**:當外層 FOREACH 把 `paragraph` item 注入 ctx,內層 FOREACH 要找 `paragraph.triplets``getIterableFromContext` 只看 top-level,看不到 `paragraph` 物件裡的 `triplets`
**修法**
- (C1) FOREACH `result` 找不到 iterable → fallback 找 `context`
- (C2) `getIterableFromContext` 加一輪「掃 ctx 內每個 object 找 nested key」
**測試**mira wiki_synthesis 3 層樹(wiki-page → paragraphs → triplets)端對端跑通,KBDB 內驗證 `物理 AI` wiki 有 2 段 paragraph + 4 個 tripletparent_id 正確接到對應 paragraph。
#### Edge type 一致化
`propagateCtx(context, result, upstreamNodeId)` helper5 個 edge typePIPE / ON_SUCCESS / ON_FAIL / IF / ON_CLICK / FOREACH)全部用同一 function 組下游 ctx。**未來新 edge type 必須用這 helper**,避免再漏。
#### CLI validator 同步
`cli/src/lib/yaml-parser.ts` validateRelations 加 regex 支援 `對每個 X` / `FOREACH X` 迭代器命名(之前 validator 字串完全比對擋住,但 graph-builder 執行端早已支援)。
---
### 三-A、P1 待改進(不擋封測,但 mira 已踩到)
#### ✅ P1 #3cypher-executor `scheduled()` handler2026-05-14 完成)
**原痛點**cron 零件只做 expression validationcypher-executor 沒 `scheduled()` handler。寫了 cron 首節點的 workflow 不會真的跑。
**之前的 workaround**(已撤):mira 寫了個 `/mira/wiki-from-raw` route 從前端 fire-and-forget 觸發 wiki_synthesis。但這違反「一律 arcrun-native」原則,也讓 arcrun 永遠補不齊缺失。**已刪 route,回 arcrun-native 路線**。
**落地**
1. `wrangler.toml``[triggers] crons = ["* * * * *"]`(每分鐘 tick
2. `src/lib/cron-match.ts`5 欄位 cron expression matcher(支援 `*` / `N` / `*/N` / `1-5` / `5,10` 組合)
3. `src/scheduled.ts`scheduled handler 掃 KV `cron-idx:` prefix,比對 controller.scheduledTime,匹配就 `executeWebhookGraph` 背景跑
4. `routes/webhooks-named.ts`acr push 偵測首節點是 cron 零件 → 抽 `cron_expr` 存進 record + 額外寫 `cron-idx:{api_key}:{name}` 輕量 index entry。DELETE 一併清理
5. `src/index.ts`export default 改 `{ fetch, scheduled }`
6. cypher-executor 自己加 `workers_dev = true` 給未來 self-trigger 用(fork 用 path-based 子 trigger 也走 workers.dev 避同 zone
**workflow YAML 慣例**
```yaml
flow:
- "my_cron >> ON_SUCCESS >> downstream_node"
config:
my_cron:
component: cron
cron_expr: "*/5 * * * *" # 每 5 分鐘
```
acr push 就會自動建立 cron-idx 並開始定時觸發。
**測試**`tests/arcrun-test/cron_heartbeat.yaml` — 每分鐘 fire 一次 + set 節點 log。
`wrangler tail arcrun-cypher-executor` 應看 `[scheduled] trigger cron_heartbeat ...`
**對應 use case**mira `mira_feed_watcher`(7B.3h,下一輪做)/ RSS 每日抓 / voice-stt 每小時掃 / 等所有 cron-driven source。
---
#### P1 #1workflow 缺 IF/branch 能力(2026-05-14 mira 7B.3f 提出)
**現象**mira 想做「找有則 PATCH 沒則 CREATE」(index-entry upsert),arcrun 目前只有 `ON_SUCCESS` + `對每個 X`FOREACH+ 已存在但壞掉的 `if_control`(見已知限制 #1),沒有 `>> ON_TRUE >>` / `>> ON_FALSE >>` 條件路由。
**短期 workaround**(已採用,2026-05-14):建 `kbdb_upsert_block` 零件,把分支邏輯封進零件內部(GET by page_name → 找到 PATCH 沒找到 POST)。caller 看到的是單純的 upsert 介面。
**長期解**:升 `if_control` false branch 路由 / 加 `>> ON_TRUE >>` edge type,讓 workflow 層可表達分支。對未來所有「找則改否則建」/「條件分流」場景都會撞到,不只 mira。
**位置**cypher-executor/src/graph-executor.ts edge type 處理(5 個 edge type 抽出 `propagateCtx` 後新增 IF 應該不難)+ cli/src/lib/yaml-parser.ts validator。
---
#### P0 #112026-05-14 已解決):interpolateString stringify array 撐爆下游
**現象**mira_feed_watcher 用 `items: "{{list_raws.blocks}}"` 把 kbdb_get 拿到的 blocks 陣列傳給 filter 零件。watcher 跑 264ms 完成、0 raw 處理。
**根因**`interpolateString` 看到模板就用 `String.replace`,非 string 值(陣列)一律 `JSON.stringify`。filter 零件收到字串 `"[{...},{...}]"` 不是 arrayitems 被忽略 → 0 matches → FOREACH 跑 0 次。
**修法**`interpolateString` 加 single-ref pass-through 規則:若整個值是純單一 `{{x}}` 引用,回 raw value(保留 array / object 型別)。多 ref / 混合文字仍 stringify 拼接字串。
**測試**mira_feed_watcher 推到 prod 後下一個 cron tick 觀察 wiki-processed tag 是否在 raws 上出現。
---
### 三-B、新零件加入紀錄
| 日期 | 零件 | 動機 | 對應 SDD |
|---|---|---|---|
| 2026-05-14 | `kbdb_upsert_block` | mira 7B.3f index-entry per-entity upsert,繞過 workflow 缺 IF/branch 能力(P1 #1)。內部 GET by page_name → 找到 PATCH 沒找到 POST。page_name 當 idempotency key。 | polaris/mira/.agents/specs/mira-app/design.md §3.5.12.4.1 |
**新零件 checklist(避免 P1 #1 重蹈 kbdb_upsert_block 漏白名單覆轍)**
每加一個 API/data 零件(不是 logic primitive),都要:
- [ ] `registry/components/{name}/main.go` + `component.contract.yaml` + `go.mod`
- [ ] `tinygo build -target=wasi`
- [ ] `.component-builds/{name}/` 完整 4 檔(`wrangler.toml``workers_dev = true` + `pnpm-lock.yaml` + `tsconfig.json` + `src/index.ts`
- [ ] **`cypher-executor/src/lib/component-loader.ts``WASM_HTTP_RUNNER_IDS` 加 canonical_id**(漏這條 cypher-executor 永遠拋「找不到零件」,端對端會死靜悄悄)
- [ ] `acr validate workflow.yaml`
- [ ] 直接 curl `https://{kebab}.arcrun.dev` + `https://arcrun-{kebab}.{WORKER_SUBDOMAIN}.workers.dev` 都 200
---
### 三-C、P1 #2workers_dev = true 全 component 自動化(2026-05-14 已收)
**原痛點**:每新部署一個 component worker,要去 CF Dashboard 手動 Enable workers.dev URL,否則 cypher-executor fetch 該 worker 會 404。
**解**32 個 `.component-builds/*/wrangler.toml` 全部加 `workers_dev = true`。CI 每次 deploy 自動啟用對應 workers.dev URL,零手動。
**未來新 component**:模板 (`component-worker-template/`) 應該預設帶 `workers_dev = true`,新人 fork 不會踩。已列入「新零件 checklist」第 3 條。
**為何不走 `*.acr-comp.uncle6.me` 自訂 zone**CF Universal SSL 只發一層子域,sub-sub `*.acr-comp.uncle6.me` 不蓋;要 ACM ($10/月) 才能簽。違反 arcrun「fork 後 self-host 用 free tier 跑得起來」核心目標。workers_dev=true 走 CF 默認的 workers.dev certfree tier OK,更乾淨。
---
### 原 P0 #9 調查紀錄(保留作歷史參考)
**現象**cypher-executor 的 `makeHttpRunner` (`cypher-executor/src/lib/component-loader.ts:142`) 對任何 outbound URL fetch 都回 CF **522 (origin timeout, ~1000ms)**
**測試矩陣**mira repo `polaris/mira/arcrun/wiki_synthesis.yaml` 端對端壓測時發現):
| 路徑 | 結果 | 證明 |
|---|---|---|
| 本機 curl → kbdb-get.arcrun.dev | 200 (22ms) | KBDB worker 本身健康 |
| cypher-executor → kbdb-get.arcrun.dev (HTTP) | **522** (1002ms) | outbound HTTP fetch 壞 |
| cypher-executor → claude-api.arcrun.dev (HTTP) | **522** | 同 zone 也壞 |
| cypher-executor → httpbin.org (外部) | **522** | 不只是 same-account loop |
| cypher-executor → string_ops (Service Binding) | 200 ✅ | SVC_* 路徑正常 |
| acr run hello (built-in via SB) | ✅ | hello.yaml 仍跑得通 |
**衍生小 bug**`set` 零件 input schema 變了(要 `assignments` 陣列或 `values` 物件,不是 `value`)。tests/arcrun-test/hello.yaml 跑 string_ops 沒踩到。
**影響範圍(封測啟動阻擋)**
- 任何用戶 workflow 含 outbound HTTP 都壞:
- 用戶 `acr recipe push` 後 trigger → 打外部 API 全 522(推翻 P0 #2 4/18 紀錄)
- 用戶要存資料進 arcrun 內建 KBDB → 522mira 7B.3c 卡這裡)
- 任何 auth primitive 走獨立 Worker URL 路徑 → 522
- Google Sheets 寫入 → 522(推翻 P0 #7「待真實 OAuth 驗證」評估,根本還沒到 OAuth 步驟就壞)
- 只有「全內建邏輯零件 + 純 service binding」workflow 還能跑
**根因(2026-05-13 確認):5/8-5/9 9 次 manual `wrangler deploy` 把含 WIP bug 的 cypher-executor 推上 prod**
調查路徑(按時序):
1. 一開始懷疑 free tier CPU cap10ms / invocation)→ 對照測試「5 節點 SB chain」跑了 2.2 秒卻通過,**推翻**
2. 換懷疑 CF zone 規則 / Bot Fight Mode → dashboard bindings 乾淨無攔截,**推翻**
3. 用戶補繳費恢復 Workers Paid → 重測仍全 522**徹底排除付費假設**
4. 看 dashboard Version History5/8 4 次 + 5/9 5 次 = **9 次 manual `wrangler deploy by uncle6.me`**
5. 對照 GitHub Actions4/24 後完全沒 deploy(最後是 commit e222116 `fix(wasi-shim)`
6. 對照 git:本機 main **領先 origin/main 3 commits 未 push**,含:
- `497f92a feat(arcrun): recipe system + resumable workflow + component registry canon`
- `e8fca33 feat(cypher): 3-node wiki workflow end-to-end (FOREACH + nested interp + unified parsing)`
- `519423c feat(arcrun): mira wiki page with tag filter + accumulated WIP`(自描含 `cypher-executor: auth-dispatcher / wasi-shim adjustments (WIP)`
**結論**:那 9 次 manual deploy 把上面 3 個 unpushed commit 的 cypher-executor 改動推上 prod,其中至少一個改動破壞了 outbound fetch(最可能是 519423c WIP 內的 wasi-shim / auth-dispatcher 改動)。GitHub Actions 因為沒 push 沒跑,CI 沒 catch4/18-4/24 那段 SDD「驗證通過」的紀錄是 truth,現在 prod 是壞的版本。
**為何 SB 路徑沒事 / HTTP 路徑全死**SB 走 cypher-executor 內部 service binding API`env.SVC_X.fetch()`),不經過 outbound HTTP code path。HTTP 路徑走 `makeHttpRunner` (component-loader.ts:142) 的 `fetch(url, ...)`,這條路被 WIP code 弄壞。具體壞在哪要 diff 那 3 個 commit 的 cypher-executor 改動才知道。
**驗證 wrangler tail 證據**trigger 任何 outbound HTTP 的 graphcypher-executor 自己 `wallTime: 497ms, cpuTime: 2ms, outcome: ok`、無 logs、無 exceptions。代表 cypher-executor 把「fetch 失敗的 522 response」當作 component 正常輸出包回 client,自己沒撞任何錯。
**解法(三選一)**
- **A. Rollback prod 到 4/24 的 e222116** — CF dashboard → arcrun-cypher-executor → Deployments → 找 4/24 那筆 → Rollback。5 分鐘恢復 outbound fetch,丟失 wiki workflow / recipe / resumable 等 cypher 端 WIP 改動(但前端、registry components、KBDB blocks 都不丟,因為它們是別的 worker / 別的儲存)。**richblack 操作。**
- **B. Diff 3 個 unpushed commit 找出壞掉的改動修掉** — 不丟功能,但要動 src code 走 SDD 協議,30min - 數小時。
- **C. 架構切換**mira 老闆 2026-05-13 提的):sub-workflow 自殺交棒模式,cypher-executor 不再做集中 graph executor。從根本繞開「cypher-executor 一個 invocation 跑長 graph」這條脆弱路徑。一勞永逸但是大改。
**衍生小 bug 仍要修**(跟付費無關):`set` 零件 input schema 變了(要 `assignments` 陣列或 `values` 物件,不是 `value`)。要嘛 update set 零件 contract 容錯,要嘛文件化新 schema。
**為什麼這直接擋封測**
封測場景 Step 6「網頁 POST → 結果存 Google Sheets」走 google_sheets 零件 (HTTP outbound to googleapis.com)。如果 cypher-executor outbound 全壞,**封測者跑任何含外部 API 的 workflow 都會 522**,不是「Google Sheets 實際寫入未驗證」級別的小事。
**也直接擋 mira**[polaris/mira/.agents/specs/mira-app/tasks.md] 7B.3c-fwiki 合成 workflow)卡這裡。
---
## 四、封測前 P3(啟動當天)
- [ ] 用封測者 email 呼叫 `/register`,取得 api_key
- [ ] 將 ARCRUN_ENCRYPTION_KEY 以安全方式提供給封測者
- [ ] 確認聯絡管道
---
## 五、已知限制(封測期間不修)
1. `if_control` false branch 不路由(條件 false 時後續節點不執行)→ 升級計畫見 P1 #12026-05-14 mira 用 `kbdb_upsert_block` workaround
2. 多節點 context 不自動解包(上游輸出 flat merge,下游需從 `data.result` 取值)
3. 用戶自製邏輯零件(Phase 5)封測後才實作
---
## 六、實作進度
| Phase | 內容 | 狀態 |
|-------|------|------|
| 0 | Workers 部署、CI/CD、DNS | ✅ |
| 1 | CLI 基礎(init / validate / run / parts | ✅ |
| 2 | /register、/cypher/execute、21 個零件 | ✅ |
| 3 | Service Binding 架構、{{variable}} 插值、ON_FAIL 修正 | ✅ |
| 4 | 動態 Recipe KVCRUD)、acr recipe 指令 | ✅ |
| 5 | 用戶自製邏輯零件(WASM push) | ⏸ 封測後 |
| 6 | Credential 多租戶({api_key}:cred:{name})、acr creds push | ✅ |
| 7 | acr parts 內建清單、acr parts scaffold | ✅ |
| 8 | /webhooks/named、acr push 改版、config 套入 graph | ✅ |
### CLI 版本
| 版本 | 變更 |
|------|------|
| 1.1.0 | auth recipe 系統:20 個服務預建(Notion/Slack/GitHub/OpenAI/Google SA 等);acr auth-recipe 指令 |
| 1.0.9 | /register 回傳 encryption_keyacr init 自動儲存;creds push 不需手動設環境變數 |
| 1.0.8 | acr push → webhooks/namedconfig 套入 graphacr parts 內建清單 |
| 1.0.7 | acr creds push → POST /credentials |
| 1.0.6 | acr recipe push / list / delete |
| 1.0.5 | hello.yaml 改 string_ops--version 修正 |
| 1.0.4 | config/context 分離 |
| 1.0.3 | 初始發布 |