docs: clarify generic continuity adapter paths

This commit is contained in:
2026-04-24 19:49:45 +08:00
parent 981759c56a
commit d35fe70c21
8 changed files with 469 additions and 138 deletions

View File

@@ -1,12 +1,16 @@
# Continuity Plugin (MVP)
# Continuity Plugin (MVP → generalized checkpoint)
> 中文版:`README.zh-TW.md`
This package extracts the current approved-plan continuity hard gate into a small installable, testable OpenClaw plugin MVP.
This package extracts the current approved-plan continuity hard gate into a small installable, testable OpenClaw plugin.
The goal is not to reinvent workflow policy. The goal is to package the existing continuity evaluator, receipt contract, and force-recall adapter so other OpenClaw workspaces can reuse the same minimum integration.
The package still preserves the current approved-plan behavior, but it now moves one step closer to a more general **engine + adapter** structure:
## What this MVP currently provides
- a host-agnostic continuity engine input/output contract
- the existing `force-recall` parity adapter
- a new `generic-preflight` adapter and manual runner for non-`force-recall` integration
## What this package currently provides
- continuity config validation
- dispatch receipt contract validation
@@ -14,6 +18,8 @@ The goal is not to reinvent workflow policy. The goal is to package the existing
- approved-plan continuity gate evaluation
- prompt block generation for the continuity gate
- a `force-recall` adapter that maps hook wrapper/planner output into continuity input
- a `generic-preflight` adapter that accepts host-agnostic continuity input directly
- a manual preflight runner for workspaces that do not use `force-recall`
## Install location
@@ -23,7 +29,7 @@ Recommended location inside an OpenClaw workspace:
<workspace>/plugins/continuity
```
With the current MVP integration, the related files normally look like this:
Possible integration layouts now include both the original `force-recall` path and a more generic path:
```text
<workspace>/
@@ -59,10 +65,12 @@ plugins/continuity/
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
@@ -80,10 +88,12 @@ plugins/continuity/
- `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` currently re-exports:
@@ -91,11 +101,42 @@ plugins/continuity/
- `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
The generalized engine accepts a normalized continuity input with fields such as:
- `planId`
- `currentTask`
- `taskState`
- `nextDerivedAction`
- `replyClosureState`
- `dispatchReceipt`
- `nextTaskKnown`
- `sameApprovedPlan`
- `taskBoundaryStop`
- `highRiskStop`
Generalized adapters return a common contract:
- `input`
- `result`
- `evaluation`
- `block`
- `meta.adapterName`
- `meta.hostAgnostic`
See `src/continuity/types.md` for the concise contract notes.
## Example config
@@ -118,6 +159,10 @@ Start from `examples/openclaw.continuity.example.json`:
"forceRecall": {
"enabled": true,
"injectBlockLabel": "APPROVED_PLAN_CONTINUITY_GATE"
},
"genericPreflight": {
"enabled": true,
"injectBlockLabel": "APPROVED_PLAN_CONTINUITY_GATE"
}
}
}
@@ -125,23 +170,9 @@ Start from `examples/openclaw.continuity.example.json`:
Defaults are defined in `src/config/defaults.mjs`.
## Hook integration
## Integration path A: `force-recall`
The primary MVP integration point is `hooks/force-recall/handler.ts`.
The current hook path is:
1. run long-task preflight / gate lock / auto-chain planner
2. dynamically load `plugins/continuity/src/index.mjs`
3. call `runForceRecallContinuityAdapter({ wrapperResult, autoChainPlanResult, config })`
4. prepend the returned block into `bodyForAgent`
The handler already contains the plugin path integration points. The key symbols are:
- `runForceRecallContinuityAdapter`
- `[APPROVED_PLAN_CONTINUITY_GATE]`
Minimal integration example:
The original MVP integration point remains `hooks/force-recall/handler.ts`.
```js
import plugin from './plugins/continuity/src/index.mjs';
@@ -157,7 +188,48 @@ if (out?.block) {
}
```
If you want a custom injected block label, override `adapter.forceRecall.injectBlockLabel`.
## Integration path B: generic/manual preflight
If your workspace does **not** use `force-recall`, you can still install and use the plugin by calling the generalized adapter or the manual runner directly.
### 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',
});
```
If `out.block` is non-empty, prepend it into the prompt/body seen by the agent.
## Receipt contract
@@ -171,24 +243,6 @@ Minimum receipt shape:
- `childSessionKey`
- `replyClosureState`
Example from `examples/approved-plan-receipt.example.json`:
```json
{
"planId": "example-plan",
"currentTask": "task-01",
"nextDerivedAction": {
"kind": "delegate",
"target": "subagent",
"task": "placeholder"
},
"dispatchedAt": "2026-04-24T16:43:00+08:00",
"dispatchRunId": "example-run",
"childSessionKey": "session-placeholder",
"replyClosureState": "pending_verification"
}
```
To persist a receipt:
```js
@@ -202,51 +256,51 @@ await writeReceipt({
## Smoke test / verification
At minimum, run:
Required plugin verification:
```bash
cd plugins/continuity
npm test
node test/continuity.smoke.test.mjs
```
If your workspace uses `force-recall`, also run:
```bash
cd /path/to/workspace
node scripts/test_force_recall_long_task_preflight.mjs
node --check hooks/force-recall/handler.ts
```
For a minimal plugin-only check, you can also run:
```bash
cd plugins/continuity
node test/continuity.smoke.test.mjs
```
## Install and apply steps for another OpenClaw workspace
1. Copy `plugins/continuity` into your workspace.
2. Ensure `hooks/force-recall/handler.ts` loads `plugins/continuity/src/index.mjs`.
3. Adjust the continuity config as needed, especially:
2. Choose one integration path:
- `force-recall`: load `runForceRecallContinuityAdapter(...)`
- no `force-recall`: call `runGenericPreflightContinuityAdapter(...)` or `runManualContinuityPreflight(...)`
3. Adjust config as needed, especially:
- `planMatchers`
- `legalTerminalStates`
- `receiptDir`
- `adapter.forceRecall.injectBlockLabel`
- `adapter.genericPreflight.injectBlockLabel`
4. If your dispatch flow creates child runs/sessions, persist a real receipt.
5. Run the smoke test and the force-recall preflight test.
5. Run plugin tests and the relevant workspace smoke path.
6. Confirm the agent prompt contains the continuity gate block and that dry-run dispatch alone does not pass the gate.
## Current limitations
- This is an MVP extraction of the **approved-plan continuity hard gate**, not a general workflow engine.
- The main adapter is `force-recall`; the package is not yet generalized into a multi-hook / multi-event integration layer.
- Config is still passed as module defaults plus caller input; there is not yet a full OpenClaw plugin installer/registration guide.
- This is still centered on the approved-plan continuity hard gate, not a full general workflow engine.
- The generalized engine contract is intentionally minimal and conservative.
- `force-recall` remains the most battle-tested adapter.
- The receipt store only writes files; it does not manage retention, cleanup, or indexing.
- The receipt validator checks the minimum contract only; it does not deeply validate every `nextDerivedAction` subtype.
- The documented install path assumes the existing `force-recall` preflight chain; if your workspace does not use that chain, you still need your own glue code.
## Notes
- Default legal terminal states are `waiting_user`, `blocked`, and `pending_verification`
- The evaluator preserves current behavior, including `missing_dispatch_receipt` and `missing_auto_next_dispatch`
- The adapter mirrors the continuity input mapping used by `hooks/force-recall/handler.ts`
- The new generic path makes the plugin more reusable even without the `force-recall` hook
- `HOOK.md` describes the plugin/hook adapter contract boundary, not the full installation guide
## Chinese documentation