8.1 KiB
Continuity Plugin(MVP → generalized checkpoint)
English version:
README.md
這個套件把目前 approved-plan continuity hard gate 抽離成一個可安裝、可測試、可在 hook 內重用的 OpenClaw plugin。
它仍保留既有 approved-plan 行為,但現在往比較通用的 engine + adapter 結構前進了一步:
- 有 host-agnostic 的 continuity engine input/output contract
- 保留既有
force-recallparity adapter - 新增
generic-preflightadapter 與 manual runner,讓未使用force-recall的 workspace 也能接
目前能做什麼
- 驗證 continuity config
- 驗證 dispatch receipt contract
- 寫出 receipt 檔案
- 評估 approved-plan continuity gate
- 產生可注入 prompt 的 continuity gate block
- 透過
force-recalladapter,把 hook 端的 wrapper/planner 結果轉成 continuity input - 透過
generic-preflightadapter,直接吃 host-agnostic continuity input - 透過 manual preflight runner,在沒有
force-recall的情況下也能直接呼叫
安裝位置
建議直接放在 OpenClaw workspace 內:
<workspace>/plugins/continuity
現在可支援兩類整合路徑:原本的 force-recall 路徑,以及較通用的 generic path。
<workspace>/
hooks/
force-recall/
handler.ts
HOOK.md
plugins/
continuity/
README.zh-TW.md
README.md
HOOK.md
package.json
examples/
src/
test/
scripts/
test_force_recall_long_task_preflight.mjs
目錄結構
plugins/continuity/
README.zh-TW.md
README.md
HOOK.md
package.json
examples/
approved-plan-receipt.example.json
openclaw.continuity.example.json
src/
index.mjs
adapters/
force-recall.mjs
generic-preflight.mjs
config/
defaults.mjs
schema.mjs
continuity/
engine.mjs
evaluator.mjs
receipt-store.mjs
receipt-validator.mjs
types.md
test/
continuity.config.test.mjs
continuity.evaluator.test.mjs
continuity.plugin.test.mjs
continuity.receipt-store.test.mjs
continuity.receipt-validator.test.mjs
continuity.smoke.test.mjs
公開介面
src/config/schema.mjssrc/config/defaults.mjssrc/continuity/engine.mjssrc/continuity/evaluator.mjssrc/continuity/receipt-validator.mjssrc/continuity/receipt-store.mjssrc/adapters/force-recall.mjssrc/adapters/generic-preflight.mjssrc/index.mjs
src/index.mjs 目前會 re-export:
defaultConfigcloneDefaultConfig()validateContinuityConfig()/normalizeContinuityConfig()normalizeContinuityEngineInput()createContinuityEngineResult()/createContinuityEngineContract()evaluateContinuity()/buildContinuityGateBlock()validateReceipt()/isValidReceipt()slugifyReceiptSegment()/buildReceiptFilename()/writeReceipt()buildApprovedPlanContinuityInput()createForceRecallContinuityAdapter()/runForceRecallContinuityAdapter()buildGenericContinuityInput()createGenericPreflightContinuityAdapter()/runGenericPreflightContinuityAdapter()runManualContinuityPreflight()
Host-agnostic engine contract
generalized engine 會吃一個正規化後的 continuity input,常用欄位包括:
planIdcurrentTasktaskStatenextDerivedActionreplyClosureStatedispatchReceiptnextTaskKnownsameApprovedPlantaskBoundaryStophighRiskStop
generalized adapter 會回傳共同 contract:
inputresultevaluationblockmeta.adapterNamemeta.hostAgnostic
精簡契約請見 src/continuity/types.md。
Example config
請從 examples/openclaw.continuity.example.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"
},
"genericPreflight": {
"enabled": true,
"injectBlockLabel": "APPROVED_PLAN_CONTINUITY_GATE"
}
}
}
預設值定義在 src/config/defaults.mjs。
整合路徑 A:force-recall
原本的 MVP 整合點仍是 hooks/force-recall/handler.ts。
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}`;
}
整合路徑 B:generic / manual preflight
如果你的 workspace 沒有 使用 force-recall,現在也可以安裝這個 plugin,直接呼叫 generalized adapter 或 manual runner。
Generic preflight adapter
import plugin from './plugins/continuity/src/index.mjs';
const out = plugin.runGenericPreflightContinuityAdapter({
config: plugin.defaultConfig,
source: {
planId: 'approved-plan-1',
currentTask: 'task-3',
taskState: 'complete',
nextTaskKnown: true,
sameApprovedPlan: true,
taskBoundaryStop: true,
nextTaskId: 'task-4',
nextDerivedAction: { type: 'message_subagent', task: 'continue' },
replyClosureState: 'completed',
dispatchReceipt: null,
},
});
Manual runner
import plugin from './plugins/continuity/src/index.mjs';
const out = plugin.runManualContinuityPreflight({
config: plugin.defaultConfig,
planId: 'approved-plan-1',
currentTask: 'task-3',
taskState: 'complete',
nextDerivedAction: { type: 'message_subagent', task: 'continue' },
replyClosureState: 'waiting_user',
});
若 out.block 非空,就把它 prepend 到 agent 會看到的 prompt/body。
Receipt contract
最小 receipt shape 如下:
planIdcurrentTasknextDerivedActiondispatchedAtdispatchRunIdchildSessionKeyreplyClosureState
若要把 receipt 落盤,可用:
import { writeReceipt } from './src/index.mjs';
await writeReceipt({
receiptDir: 'state/approved-plan-continuity',
receipt,
});
Smoke test / 驗證
plugin 本體必要驗證:
cd plugins/continuity
npm test
node test/continuity.smoke.test.mjs
若你的 workspace 有使用 force-recall,再補跑:
cd /path/to/workspace
node scripts/test_force_recall_long_task_preflight.mjs
node --check hooks/force-recall/handler.ts
安裝與套用步驟(給其他 OpenClaw 使用者)
- 把
plugins/continuity複製到你的 workspace。 - 選一條整合路徑:
force-recall:載入runForceRecallContinuityAdapter(...)- 沒有
force-recall:呼叫runGenericPreflightContinuityAdapter(...)或runManualContinuityPreflight(...)
- 視需要調整 continuity config,至少確認:
planMatcherslegalTerminalStatesreceiptDiradapter.forceRecall.injectBlockLabeladapter.genericPreflight.injectBlockLabel
- 若你的 dispatch 流程會產生 child run/session,請同步寫出 receipt。
- 跑 plugin 測試與對應 workspace smoke path。
- 確認 agent prompt 內可見 continuity gate block,且 dry-run dispatch 不會被誤判為 pass。
目前限制
- 它仍以 approved-plan continuity hard gate 為中心,不是完整通用 workflow engine。
- generalized engine contract 目前刻意保持最小且保守。
force-recall仍是目前最成熟的 adapter。- receipt store 只負責寫檔,不含 retention、cleanup、indexing。
- receipt validator 目前只檢查最小 contract,不驗證每個
nextDerivedAction子欄位語意。
備註
- 預設 legal terminal states:
waiting_user、blocked、pending_verification - evaluator 保留既有行為,包括
missing_dispatch_receipt與missing_auto_next_dispatch - 新增 generic path 後,即使沒有
force-recallhook,也比較能重用這個 plugin HOOK.md說明的是 plugin/hook adapter 契約定位,不是完整安裝說明
英文文件
英文版請見 README.md。