Files
Arcrun/system-dev/docs/3-specs/resumable-workflow/tasks.md
T
uncle6me-web 5d00e71275 chore: D22 落地——docs/SDD/wiki/CLAUDE.md 進 repo(Gitea private 預設全 push)
頂層 D22 決策(leo 2026-07-03 拍板):推什麼由開發環境歸屬決定,
Gitea private=除機敏值/build 產物/.github 外全 push。
解 T1.5 卡點:雲端工人 clone 拿得到 credential-store-migration.md,可就地改寫 SDD。
機敏掃描兩輪通過(新增 189 檔約 2.1MB,node_modules/dist/wasm 照舊排除)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 07:13:33 +08:00

4.1 KiB
Raw Blame History

Tasks — Resumable Workflow

對應 SDDdesign.md 上次更新:2026-05-07

狀態 legend[ ] 待辦 / [🔄] 進行中 / [x] 完成


Phase 1Mira daemon 端 callback 支援

  • 1.1 改 /opt/mira/mira-daemon.jsHetzner mira container/execute 接受 params.callback_url
  • 1.2 fireCallback functiontask done/failed 時 POST callback_urlbody = {task_id, success, data?, error?}
  • 1.3 callback retry4 次(立即 + 1s/5s/30s backoff),全失敗 log
  • 1.4 patch script 寫好 /tmp/patch-mira-daemon.pydocker cp 進 container(注意:rebuild image 會丟失,需重 patch 或正式 commit 進 Dockerfile/git repo
  • 1.5 真實端對端驗證:daemon log 顯示 [Mira callback] task=task_2_... POST https://cypher.arcrun.dev/workflows/resume OK 2002026-05-07 07:24:04 + task_3 短測試)

Phase 2cypher-executor resumable runtime

  • 2.1 寫 paused-runs.ts81 行):persistPausedRun / loadPausedRun / consumePausedRun + isResumablePending 偵測器,24h TTL
  • 2.2 改 graph-executor.ts Component case:偵測 pending → 寫 KV + throw WorkflowPaused
  • 2.3 改 cypher-handlers.tscatch WorkflowPaused → 回 {success:true, paused:true, task_id, run_id, paused_node_id, trace, graph}
  • 2.4 callback_url 自動注入:componentId==='claude_api' 時 mergedContext.callback_url = PUBLIC_BASE_URL 或預設 cypher.arcrun.dev/workflows/resume

Phase 3resume endpoint

  • 3.1 寫 routes/resume.tsPOST /workflows/resumeconsumePausedRun → resumeFromPaused
  • 3.2 graph-executor 加 resumeFromPaused() 方法:把 callback_result 當 paused_node 輸出 + spread 進 ctx + 從下游節點繼續
  • 3.3 idempotent 驗證:第二次 callback 回 {noop:true, reason:"state 不存在或過期"}
  • 3.4 cypher-executor 部署 v0580980b
  • 3.5 mount /workflows/resume 進 index.ts

Phase 4claude_api 容器透傳 callback_url

  • 4.1 改 claude_api/main.goInput 加 CallbackURLtimeout 預設改 120s
  • 4.2 重 build wasm + redeploy claude-api.arcrun.dev (v f926e3dd)
  • 4.3 真實端對端驗證:daemon 收到 callback_url → task done 後 POST cypher-executor/workflows/resume → 200 OK

Phase 5:端對端整合測試

  • 5.1 用 MCP u6u_execute_workflow 跑 wiki 合成 + 5KB+ 草稿
  • 5.2 第一次回應應為 {paused, task_id, run_id}
  • 5.3 等 daemon callback 進來(log 看到 /workflows/resume 命中)
  • 5.4 觀察 wiki page 真的寫進 KBDB(即使原 MCP call 已斷線)
  • 5.5 trace 含完整節點紀錄(paused → resumed

Phase 6Trigger 端背景執行(?async=1)(2026-05-24 新增,對應 design.md §5

根因:project_detector daemon 同步回 done(不切非同步)→ webhook 同步阻塞 31s → 前端 1.5s 斷線殺掉 workflow → tag 沒寫成。對照實驗已證(全程等 31s 成功 / 2s 斷線失敗)。

  • 6.1 routes/webhooks-named.ts trigger handler:偵測 ?async=1c.executionCtx.waitUntil(executeWebhookGraph(...)) 立回 202 {accepted:true};不帶則維持原同步(向後相容)
  • 6.2 背景 run 的 telemetry / execution verdict 照寫(waitUntil 內)
  • 6.3 部署 cypher-executor,驗證:curl ?async=1 立即回 202<2s
  • 6.4 e2e?async=1 觸發 + 2s 強制斷線 → 等 ~35s 後 raw tag 有寫入(對照本次失敗實驗 caf8b827)
  • 6.5 mira 前端 feed/page.tsxtriggerProjectDetector + triggerWikiSynthesis 觸發 URL 加 ?async=1

風險追蹤

  • 風險 1daemon callback 進來時,cypher.arcrun.dev 還沒醒(CF Worker cold start)→ 第一次 retry 接住(daemon retry policy 涵蓋)
  • 風險 2v1 沒 final_callback 給原 client → 用戶要主動查狀態
    • 接受:mira 河道 UI 可定期 refetch wiki page,或用既有 KBDB 觸發機制
    • v2 加 final_callback 統一處理

v2 已記錄

  • nested pending(一個 run 多個 paused 節點)
  • foreach 內 pendingitem-level resume
  • final_callback 給原 clienttrigger 時帶 final_callback_url
  • poll_task 零件(外部 API 沒 webhook 時用)