# Continuity Plugin MVP:Agent 安裝與操作手冊 > 目標讀者:OpenClaw agent / 實作者 > > 這份文件不是概念介紹,而是可直接照做的 runbook / checklist。 > 若你只想知道「要不要裝、怎麼接、怎麼驗證」,先看本文,不必先讀完整 README。 ## 0. 這個 plugin 什麼時候要裝 ### 應安裝的情況 如果你的 workspace 符合以下任一條件,建議安裝: - 你有 **approved-plan** 類型的長任務 / 多步驟任務。 - 你不希望 agent 在某個 task 做完後,直接把整件事當成「已完成」結案。 - 你需要 agent 在同一個 approved plan 內,判斷是否還有 **下一個要派發的 task**。 - 你需要用 **dispatch receipt** 證明「真的有派出下一步」,而不是只在回覆裡口頭說會繼續。 - 你已經在用 `hooks/force-recall/handler.ts`,希望把 approved-plan continuity gate 注入 agent prompt。 ### 可先不裝的情況 以下情況可先不裝,或只當參考: - 你的 workspace 沒有 approved-plan / auto-chain / dispatch 這類流程。 - 你只需要一般單回合聊天,不需要 continuity hard gate。 - 你沒有 `force-recall` hook,也暫時不打算自己補 glue code。 --- ## 1. 安裝目標與預期結果 安裝完成後,應達到這個最小結果: - `hooks/force-recall/handler.ts` 能載入 `plugins/continuity/src/index.mjs` - hook 在 preflight 時會呼叫 `runForceRecallContinuityAdapter(...)` - agent prompt 內可看到 `[APPROVED_PLAN_CONTINUITY_GATE] ... [/APPROVED_PLAN_CONTINUITY_GATE]` - 當 approved plan 任務完成,但沒有真實下一步 dispatch receipt 時,gate 會擋下錯誤結案 - plugin 自身測試與 hook smoke test 可通過 --- ## 2. 應放到哪裡 ### 標準位置 把 plugin 放在 workspace 內這個位置: ```text /plugins/continuity ``` 以目前 MVP 的預期 layout: ```text / hooks/ force-recall/ handler.ts HOOK.md plugins/ continuity/ AGENT_GUIDE.zh-TW.md README.zh-TW.md README.md HOOK.md package.json examples/ src/ test/ scripts/ test_force_recall_long_task_preflight.mjs ``` ### 本次文件對應的實際路徑 ```text /home/alice/.openclaw/workspace/plugins/continuity ``` --- ## 3. 安裝前 checklist 在開始前,先確認: - [ ] 你的 workspace 有 `hooks/force-recall/handler.ts` - [ ] 你的 workspace 有 `scripts/test_force_recall_long_task_preflight.mjs` - [ ] 你的 workspace 願意採用 approved-plan continuity hard gate - [ ] 你接受 MVP 目前只優先支援 `force-recall` adapter - [ ] 你知道 receipt 只是「最小 contract」,不是完整 workflow engine 可先用以下命令確認: ```bash cd ls hooks/force-recall/handler.ts ls scripts/test_force_recall_long_task_preflight.mjs ls plugins/continuity/package.json ``` --- ## 4. 需要哪些檔案 ### 必要檔案 至少要有以下檔案: ```text plugins/continuity/ package.json src/index.mjs src/adapters/force-recall.mjs src/config/defaults.mjs src/config/schema.mjs src/continuity/evaluator.mjs src/continuity/receipt-validator.mjs src/continuity/receipt-store.mjs examples/openclaw.continuity.example.json examples/approved-plan-receipt.example.json ``` ### 建議一起帶走的檔案 ```text plugins/continuity/ README.zh-TW.md README.md HOOK.md AGENT_GUIDE.zh-TW.md test/continuity.config.test.mjs test/continuity.receipt-validator.test.mjs test/continuity.receipt-store.test.mjs test/continuity.evaluator.test.mjs test/continuity.plugin.test.mjs test/continuity.smoke.test.mjs ``` ### 如果缺檔,先補哪些 優先順序: 1. `src/index.mjs` 2. `src/adapters/force-recall.mjs` 3. `src/continuity/evaluator.mjs` 4. `src/continuity/receipt-validator.mjs` 5. `src/continuity/receipt-store.mjs` 6. `examples/openclaw.continuity.example.json` 7. `test/continuity.smoke.test.mjs` --- ## 5. 直接安裝步驟 ### 路徑 A:你已經在同一個 repo / workspace 內 - [ ] 確認 `plugins/continuity` 目錄存在 - [ ] 確認 `package.json` 與 `src/index.mjs` 存在 - [ ] 確認 `hooks/force-recall/handler.ts` 存在 驗證命令: ```bash cd find plugins/continuity -maxdepth 3 -type f | sort ``` ### 路徑 B:你要複製到另一個 OpenClaw workspace 在來源 workspace: ```bash cd rsync -av plugins/continuity/ /plugins/continuity/ ``` 複製後在目標 workspace 驗證: ```bash cd find plugins/continuity -maxdepth 3 -type f | sort ``` --- ## 6. example config 怎麼套 ### Step 1:從 example 複製一份你的 continuity config 來源範例: ```text plugins/continuity/examples/openclaw.continuity.example.json ``` 範例內容: ```json { "enabled": true, "planMatchers": ["approved-plan"], "legalTerminalStates": [ "waiting_user", "blocked", "pending_verification" ], "receiptDir": "state/approved-plan-continuity", "requireRealDispatchReceipt": true, "allowReplyClosureWithoutDispatch": false, "debug": false, "adapter": { "forceRecall": { "enabled": true, "injectBlockLabel": "APPROVED_PLAN_CONTINUITY_GATE" } } } ``` ### Step 2:先只改最少必要欄位 通常只需要先確認這幾個欄位: - [ ] `enabled` - [ ] `planMatchers` - [ ] `legalTerminalStates` - [ ] `receiptDir` - [ ] `requireRealDispatchReceipt` - [ ] `allowReplyClosureWithoutDispatch` - [ ] `adapter.forceRecall.enabled` - [ ] `adapter.forceRecall.injectBlockLabel` ### Step 3:建議的最小套用策略 #### 情境 A:你就是要沿用目前 approved-plan MVP 行為 直接照 example 使用,通常不用改: - `planMatchers = ["approved-plan"]` - `legalTerminalStates = ["waiting_user", "blocked", "pending_verification"]` - `requireRealDispatchReceipt = true` - `allowReplyClosureWithoutDispatch = false` #### 情境 B:你有自己的 plan 名稱 如果你的 wrapper / planner 用的是別的 plan 名稱,調整: ```json { "planMatchers": ["your-approved-plan-name"] } ``` #### 情境 C:你想改 injected block label 如果你不想使用預設 label: ```json { "adapter": { "forceRecall": { "enabled": true, "injectBlockLabel": "YOUR_CONTINUITY_GATE" } } } ``` ### Step 4:receiptDir 先建起來 ```bash cd mkdir -p state/approved-plan-continuity ``` --- ## 7. 如何接 `force-recall` hook ## 7.1 你要確認的整合點 MVP 的主要整合點是: ```text hooks/force-recall/handler.ts ``` 目前 hook 端流程應該是: 1. 跑 long-task preflight / wrapper 2. 跑 gate lock 3. 跑 auto-chain planner 4. 載入 continuity plugin 5. 呼叫 `runForceRecallContinuityAdapter(...)` 6. 把 continuity block prepend 到 `bodyForAgent` ### 你至少要看到這些關鍵符號 - `plugins/continuity/src/index.mjs` - `runForceRecallContinuityAdapter` - `APPROVED_PLAN_CONTINUITY_GATE` 檢查命令: ```bash cd grep -n "runForceRecallContinuityAdapter" hooks/force-recall/handler.ts grep -n "APPROVED_PLAN_CONTINUITY_GATE" hooks/force-recall/handler.ts grep -n "plugins\", \"continuity\", \"src\", \"index.mjs" hooks/force-recall/handler.ts ``` ## 7.2 最小接法範例 如果你要自己補接,最小概念如下: ```js import plugin from './plugins/continuity/src/index.mjs'; const out = plugin.runForceRecallContinuityAdapter({ config: plugin.defaultConfig, wrapperResult, autoChainPlanResult, }); if (out?.block) { context.bodyForAgent = `${out.block}\n${context.bodyForAgent}`; } ``` ## 7.3 實作者要檢查的實際條件 - [ ] hook 能動態 import `plugins/continuity/src/index.mjs` - [ ] `runForceRecallContinuityAdapter` 是 function - [ ] 傳入 `wrapperResult` - [ ] 傳入 `autoChainPlanResult` - [ ] 有傳 `config`(至少先用 `defaultConfig`) - [ ] `out.block` 非空時有 prepend 到 `bodyForAgent` - [ ] agent prompt 最終可見 continuity gate block ## 7.4 receipt 與 continuity input 的關係 如果你的流程真的有派發下一步,請不要只在字串裡描述「已派發」,而要產出真實 `dispatchReceipt`。 最小 receipt shape: - `planId` - `currentTask` - `nextDerivedAction` - `dispatchedAt` - `dispatchRunId` - `childSessionKey` - `replyClosureState` 範例:`plugins/continuity/examples/approved-plan-receipt.example.json` --- ## 8. 實作時建議直接照抄的操作流程 ### Checklist:第一次把 plugin 接進現有 workspace - [ ] 建立 / 複製 `plugins/continuity` - [ ] 確認 `src/index.mjs` 可被 hook 載入 - [ ] 確認 continuity example config 可讀 - [ ] 建立 `state/approved-plan-continuity/` - [ ] 確認 `hooks/force-recall/handler.ts` 有 continuity adapter 接點 - [ ] 確認有 prepend continuity block 到 `bodyForAgent` - [ ] 若 dispatch 真的發生,補上 receipt 寫檔 - [ ] 跑 plugin test - [ ] 跑 force-recall smoke test - [ ] 檢查 injected prompt block 是否存在 ### Checklist:第一次加 receipt 落盤 - [ ] 準備合法 receipt object - [ ] 先用 `validateReceipt()` / `isValidReceipt()` 驗證 - [ ] 用 `writeReceipt({ receiptDir, receipt })` 落盤 - [ ] 確認 receipt 寫到 `state/approved-plan-continuity/` - [ ] 再跑 continuity smoke test,避免只是「看起來有 receipt」 --- ## 9. 安裝後怎麼跑 smoke test ### 最小 smoke test 先跑 plugin 自己的測試: ```bash cd /plugins/continuity npm test ``` 如果你只想快速驗證 plugin 主體: ```bash cd /plugins/continuity node test/continuity.smoke.test.mjs ``` ### Hook 整合 smoke test ```bash cd node scripts/test_force_recall_long_task_preflight.mjs node --check hooks/force-recall/handler.ts ``` ### 建議的完整 smoke test 順序 照這個順序最容易定位問題: 1. plugin 單體測試 ```bash cd /plugins/continuity npm test ``` 2. hook 檔案語法檢查 ```bash cd node --check hooks/force-recall/handler.ts ``` 3. hook preflight smoke test ```bash cd node scripts/test_force_recall_long_task_preflight.mjs ``` 4. 人工檢查 block 是否真的被 inject 建議檢查測試輸出或 debug prompt,確認有出現: ```text [APPROVED_PLAN_CONTINUITY_GATE] ``` --- ## 10. Smoke test 通過標準 以下條件都成立,才算最小安裝成功: - [ ] `npm test` 全通過 - [ ] `node --check hooks/force-recall/handler.ts` 通過 - [ ] `node scripts/test_force_recall_long_task_preflight.mjs` 通過 - [ ] 測試 / 輸出中可看到 continuity gate block - [ ] 沒有 receipt 時,gate 會對缺少 dispatch 的情境做 fail / hard-gate - [ ] 有合法 terminal state(例如 `waiting_user` / `blocked` / `pending_verification`)時,不會誤判 --- ## 11. 失敗時先檢查什麼 請依這個順序排查,不要一開始就到處改 code。 ### 第一層:路徑 / 檔案是否存在 - [ ] `plugins/continuity/src/index.mjs` 存在 - [ ] `hooks/force-recall/handler.ts` 存在 - [ ] `plugins/continuity/examples/openclaw.continuity.example.json` 存在 - [ ] `plugins/continuity/examples/approved-plan-receipt.example.json` 存在 命令: ```bash cd ls plugins/continuity/src/index.mjs ls hooks/force-recall/handler.ts ls plugins/continuity/examples/openclaw.continuity.example.json ls plugins/continuity/examples/approved-plan-receipt.example.json ``` ### 第二層:hook 是否真的有接到 plugin - [ ] `handler.ts` 有 import / dynamic import continuity plugin - [ ] `handler.ts` 有呼叫 `runForceRecallContinuityAdapter(...)` - [ ] `handler.ts` 有把 `out.block` prepend 到 `bodyForAgent` ### 第三層:config 是否合理 優先檢查: - [ ] `enabled` 是否為 `true` - [ ] `adapter.forceRecall.enabled` 是否為 `true` - [ ] `planMatchers` 是否對得上你的 approved plan 名稱 - [ ] `receiptDir` 是否可寫 - [ ] `requireRealDispatchReceipt` 是否符合你預期 - [ ] `allowReplyClosureWithoutDispatch` 是否不小心放寬了 gate ### 第四層:receipt 是否是真的、不是假資料 最常見問題: - 只有「打算 dispatch」但沒有真實 receipt - receipt shape 不完整 - `dispatchRunId` / `childSessionKey` 空字串 - `replyClosureState` 不在合法狀態 - 寫到了錯誤資料夾 ### 第五層:hook 前置資料是否足夠 因為 continuity adapter 會吃: - `wrapperResult` - `autoChainPlanResult` 所以要檢查: - [ ] wrapper 是否真的把 long-task / approved-plan 狀態帶進來 - [ ] planner 是否真的產出 `derivedAction` - [ ] `nextDerivedAction` 是否能被 continuity input 建出來 - [ ] closure state 是否被正確推導 --- ## 12. 快速除錯命令 ### 看 plugin 測試是否全過 ```bash cd /plugins/continuity npm test ``` ### 看 hook 語法有沒有壞 ```bash cd node --check hooks/force-recall/handler.ts ``` ### 看 handler 裡 continuity 關鍵字是否存在 ```bash cd grep -n "runForceRecallContinuityAdapter" hooks/force-recall/handler.ts grep -n "APPROVED_PLAN_CONTINUITY_GATE" hooks/force-recall/handler.ts ``` ### 看 receipt 資料夾有沒有東西 ```bash cd find state/approved-plan-continuity -maxdepth 2 -type f | sort ``` --- ## 13. 目前限制 這個 MVP 目前有以下限制,安裝前要先接受: - 它是 **approved-plan continuity hard gate** 的抽離版,不是通用 workflow engine。 - 主要 adapter 目前只有 `force-recall`。 - 文件描述的是「接在既有 force-recall preflight 鏈上」的路徑;若你的 workspace 沒這條鏈,仍要自己補 glue code。 - config 目前是模組預設值 + 呼叫端傳入,不是完整 plugin installer / registry 流程。 - receipt store 目前只負責寫檔,不管 retention、cleanup、indexing。 - receipt validator 目前只驗證最小 contract,不會深入驗證每種 `nextDerivedAction` 的完整語意。 - 若你只做 dry-run planning、沒有真實 dispatch receipt,gate 仍可能視為未通過;這是設計目標,不是 bug。 --- ## 14. 建議的交付標準:什麼叫「agent 可照做」 若你要把這個 plugin 交給另一位 agent / 實作者,至少應滿足: - [ ] 他不需要回頭爬整段對話,也知道 plugin 的用途 - [ ] 他知道檔案應放在哪裡 - [ ] 他知道要帶哪些檔案 - [ ] 他知道怎麼接 `force-recall` hook - [ ] 他知道 example config 先改哪些欄位 - [ ] 他知道怎麼跑 smoke test - [ ] 他知道失敗先查哪幾層 - [ ] 他知道目前限制,不會誤以為這是完整 workflow framework 如果以上 8 點都回答得出來,才算達到「agent 可照做」。 --- ## 15. 一頁版執行摘要(超短版) 如果你趕時間,只做下面這些: 1. 把 plugin 放到: ```text /plugins/continuity ``` 2. 確認 hook 有接: - `plugins/continuity/src/index.mjs` - `runForceRecallContinuityAdapter(...)` - prepend `out.block` 到 `bodyForAgent` 3. 套 example config: ```text plugins/continuity/examples/openclaw.continuity.example.json ``` 4. 建 receipt 目錄: ```bash mkdir -p /state/approved-plan-continuity ``` 5. 跑測試: ```bash cd /plugins/continuity && npm test cd && node --check hooks/force-recall/handler.ts cd && node scripts/test_force_recall_long_task_preflight.mjs ``` 6. 確認 prompt 裡有: ```text [APPROVED_PLAN_CONTINUITY_GATE] ``` 7. 確認沒有真實 dispatch receipt 時,不會被錯誤判定為已完成。 --- ## 16. 參考文件 - `plugins/continuity/README.zh-TW.md` - `plugins/continuity/README.md` - `plugins/continuity/HOOK.md` - `plugins/continuity/examples/openclaw.continuity.example.json` - `plugins/continuity/examples/approved-plan-receipt.example.json` - `hooks/force-recall/handler.ts` - `scripts/test_force_recall_long_task_preflight.mjs` 如需英文版,可再從本文翻成 `AGENT_GUIDE.md`;MVP 階段中文版優先即可。