Files

8.1 KiB
Raw Permalink Blame History

Continuity PluginMVP → 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-recall parity adapter
  • 新增 generic-preflight adapter 與 manual runner讓未使用 force-recall 的 workspace 也能接

目前能做什麼

  • 驗證 continuity config
  • 驗證 dispatch receipt contract
  • 寫出 receipt 檔案
  • 評估 approved-plan continuity gate
  • 產生可注入 prompt 的 continuity gate block
  • 透過 force-recall adapter把 hook 端的 wrapper/planner 結果轉成 continuity input
  • 透過 generic-preflight adapter直接吃 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.mjs
  • src/config/defaults.mjs
  • src/continuity/engine.mjs
  • src/continuity/evaluator.mjs
  • src/continuity/receipt-validator.mjs
  • src/continuity/receipt-store.mjs
  • src/adapters/force-recall.mjs
  • src/adapters/generic-preflight.mjs
  • src/index.mjs

src/index.mjs 目前會 re-export

  • defaultConfig
  • cloneDefaultConfig()
  • 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常用欄位包括

  • planId
  • currentTask
  • taskState
  • nextDerivedAction
  • replyClosureState
  • dispatchReceipt
  • nextTaskKnown
  • sameApprovedPlan
  • taskBoundaryStop
  • highRiskStop

generalized adapter 會回傳共同 contract

  • input
  • result
  • evaluation
  • block
  • meta.adapterName
  • meta.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

整合路徑 Aforce-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}`;
}

整合路徑 Bgeneric / 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 如下:

  • planId
  • currentTask
  • nextDerivedAction
  • dispatchedAt
  • dispatchRunId
  • childSessionKey
  • replyClosureState

若要把 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 使用者)

  1. plugins/continuity 複製到你的 workspace。
  2. 選一條整合路徑:
    • force-recall:載入 runForceRecallContinuityAdapter(...)
    • 沒有 force-recall:呼叫 runGenericPreflightContinuityAdapter(...)runManualContinuityPreflight(...)
  3. 視需要調整 continuity config至少確認
    • planMatchers
    • legalTerminalStates
    • receiptDir
    • adapter.forceRecall.injectBlockLabel
    • adapter.genericPreflight.injectBlockLabel
  4. 若你的 dispatch 流程會產生 child run/session請同步寫出 receipt。
  5. 跑 plugin 測試與對應 workspace smoke path。
  6. 確認 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 stateswaiting_userblockedpending_verification
  • evaluator 保留既有行為,包括 missing_dispatch_receiptmissing_auto_next_dispatch
  • 新增 generic path 後,即使沒有 force-recall hook也比較能重用這個 plugin
  • HOOK.md 說明的是 plugin/hook adapter 契約定位,不是完整安裝說明

英文文件

英文版請見 README.md