feat: export continuity plugin MVP packaging
This commit is contained in:
254
plugins/continuity/README.md
Normal file
254
plugins/continuity/README.md
Normal file
@@ -0,0 +1,254 @@
|
||||
# Continuity Plugin (MVP)
|
||||
|
||||
> 中文版:`README.zh-TW.md`
|
||||
|
||||
This package extracts the current approved-plan continuity hard gate into a small installable, testable OpenClaw plugin MVP.
|
||||
|
||||
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.
|
||||
|
||||
## What this MVP currently provides
|
||||
|
||||
- continuity config validation
|
||||
- dispatch receipt contract validation
|
||||
- receipt file writing
|
||||
- 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
|
||||
|
||||
## Install location
|
||||
|
||||
Recommended location inside an OpenClaw workspace:
|
||||
|
||||
```text
|
||||
<workspace>/plugins/continuity
|
||||
```
|
||||
|
||||
With the current MVP integration, the related files normally look like this:
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
## Directory structure
|
||||
|
||||
```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
|
||||
config/
|
||||
defaults.mjs
|
||||
schema.mjs
|
||||
continuity/
|
||||
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
|
||||
```
|
||||
|
||||
## Public surface
|
||||
|
||||
- `src/config/schema.mjs`
|
||||
- `src/config/defaults.mjs`
|
||||
- `src/continuity/evaluator.mjs`
|
||||
- `src/continuity/receipt-validator.mjs`
|
||||
- `src/continuity/receipt-store.mjs`
|
||||
- `src/adapters/force-recall.mjs`
|
||||
- `src/index.mjs`
|
||||
|
||||
`src/index.mjs` currently re-exports:
|
||||
|
||||
- `defaultConfig`
|
||||
- `cloneDefaultConfig()`
|
||||
- `validateContinuityConfig()` / `normalizeContinuityConfig()`
|
||||
- `evaluateContinuity()` / `buildContinuityGateBlock()`
|
||||
- `validateReceipt()` / `isValidReceipt()`
|
||||
- `slugifyReceiptSegment()` / `buildReceiptFilename()` / `writeReceipt()`
|
||||
- `buildApprovedPlanContinuityInput()`
|
||||
- `createForceRecallContinuityAdapter()` / `runForceRecallContinuityAdapter()`
|
||||
|
||||
## Example config
|
||||
|
||||
Start from `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"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Defaults are defined in `src/config/defaults.mjs`.
|
||||
|
||||
## Hook integration
|
||||
|
||||
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:
|
||||
|
||||
```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}`;
|
||||
}
|
||||
```
|
||||
|
||||
If you want a custom injected block label, override `adapter.forceRecall.injectBlockLabel`.
|
||||
|
||||
## Receipt contract
|
||||
|
||||
Minimum receipt shape:
|
||||
|
||||
- `planId`
|
||||
- `currentTask`
|
||||
- `nextDerivedAction`
|
||||
- `dispatchedAt`
|
||||
- `dispatchRunId`
|
||||
- `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
|
||||
import { writeReceipt } from './src/index.mjs';
|
||||
|
||||
await writeReceipt({
|
||||
receiptDir: 'state/approved-plan-continuity',
|
||||
receipt,
|
||||
});
|
||||
```
|
||||
|
||||
## Smoke test / verification
|
||||
|
||||
At minimum, run:
|
||||
|
||||
```bash
|
||||
cd plugins/continuity
|
||||
npm test
|
||||
|
||||
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:
|
||||
- `planMatchers`
|
||||
- `legalTerminalStates`
|
||||
- `receiptDir`
|
||||
- `adapter.forceRecall.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.
|
||||
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.
|
||||
- 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`
|
||||
- `HOOK.md` describes the plugin/hook adapter contract boundary, not the full installation guide
|
||||
|
||||
## Chinese documentation
|
||||
|
||||
See `README.zh-TW.md` for the Traditional Chinese version.
|
||||
Reference in New Issue
Block a user