Files

309 lines
8.1 KiB
Markdown
Raw Permalink 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.
# 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 內:
```text
<workspace>/plugins/continuity
```
現在可支援兩類整合路徑:原本的 `force-recall` 路徑,以及較通用的 generic path。
```text
<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
```
## 目錄結構
```text
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` 開始:
```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`
```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}`;
}
```
## 整合路徑 Bgeneric / manual preflight
如果你的 workspace **沒有** 使用 `force-recall`,現在也可以安裝這個 plugin直接呼叫 generalized adapter 或 manual runner。
### Generic preflight adapter
```js
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
```js
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 落盤,可用:
```js
import { writeReceipt } from './src/index.mjs';
await writeReceipt({
receiptDir: 'state/approved-plan-continuity',
receipt,
});
```
## Smoke test / 驗證
plugin 本體必要驗證:
```bash
cd plugins/continuity
npm test
node test/continuity.smoke.test.mjs
```
若你的 workspace 有使用 `force-recall`,再補跑:
```bash
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 states`waiting_user``blocked``pending_verification`
- evaluator 保留既有行為,包括 `missing_dispatch_receipt``missing_auto_next_dispatch`
- 新增 generic path 後,即使沒有 `force-recall` hook也比較能重用這個 plugin
- `HOOK.md` 說明的是 plugin/hook adapter 契約定位,不是完整安裝說明
## 英文文件
英文版請見 `README.md`