37 KiB
Continuity Plugin MVP Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Extract the current approved-plan continuity hard-gate into an installable, configurable, testable OpenClaw plugin MVP with bilingual README guidance, example config, and smoke-test flow.
Architecture: Keep the MVP small and adapter-first. Move continuity logic out of the current hard-coded scripts into a plugin package with four clear seams: config schema, continuity evaluator, receipt validator/storage helper, and hook adapter. Preserve current behavior first, then wrap it in plugin packaging, plugin docs, and plugin-level tests so the same continuity gate can be installed and configured without patching core workflow logic.
Tech Stack: Node.js, ESM (.mjs/TypeScript where already present), file-backed JSON receipts, OpenClaw hook/plugin conventions, bilingual Markdown docs, script-level test runners.
Implementation Notes for the Engineer
- Current behavior already exists in these files and should be treated as the extraction source of truth for MVP parity:
scripts/approved_plan_continuity_gate.mjsscripts/approved_plan_dispatch_binding.mjsscripts/test_approved_plan_continuity_gate.mjshooks/force-recall/handler.tsdocs/runbooks/approved-plan-continuity.mdstate/approved-plan-continuity/README.md
- The workspace currently has an empty top-level
plugins/directory, so the plan assumes creating a dedicated plugin package there instead of mixing plugin code back intoscripts/. - Do not widen scope into a generalized workflow engine. MVP means: preserve today’s continuity decision model, make it pluggable/configurable, document installation, and prove it with tests and a smoke path.
- Prefer pure functions for evaluator/validator pieces so they can be tested without spawning hooks.
- Treat current hard-gate scripts as compatibility fixtures during migration. Only remove or thin them after plugin parity is verified.
Proposed MVP Package Layout
plugins/continuity/
README.md
README.zh-TW.md
package.json
HOOK.md
examples/
openclaw.continuity.example.json
approved-plan-receipt.example.json
src/
index.mjs
config/
schema.mjs
defaults.mjs
continuity/
evaluator.mjs
receipt-validator.mjs
receipt-store.mjs
types.md
adapters/
force-recall.mjs
script-bridge.mjs
test/
continuity.evaluator.test.mjs
continuity.receipt-validator.test.mjs
continuity.plugin.test.mjs
continuity.smoke.test.mjs
If the repo’s actual plugin loader requires a different manifest filename or entrypoint shape, adapt the filenames but keep the same responsibilities and test coverage.
Acceptance Target
The MVP is acceptable only when all of the following are true:
- Continuity rules are configurable through a plugin config schema instead of only hard-coded constants.
- The evaluator can be imported and tested as a standalone module.
- Receipt validation is separated from gate decision logic.
- A hook adapter can call the plugin and inject the same kind of hard-gate behavior now implemented in
hooks/force-recall/handler.ts. - The plugin ships with bilingual install/apply documentation.
- The repo contains example config and at least one repeatable smoke test command.
- Existing current-script behavior is either preserved through bridge wrappers or explicitly mapped in the README migration section.
Task 1: Capture current continuity behavior as extraction baseline
Files:
- Review:
scripts/approved_plan_continuity_gate.mjs - Review:
scripts/approved_plan_dispatch_binding.mjs - Review:
scripts/test_approved_plan_continuity_gate.mjs - Review:
hooks/force-recall/handler.ts - Review:
docs/runbooks/approved-plan-continuity.md
Step 1: Create a baseline notes section in the plan worklog
- Write down the exact current responsibilities:
- legal terminal states
- minimum dispatch receipt fields
- receipt filename convention
- how
force-recallcurrently invokes continuity - which behaviors are already covered by tests
Step 2: Verify nothing was guessed Run:
rg -n "waiting_user|blocked|pending_verification|dispatchReceipt|nextDerivedAction|approved_plan_continuity" \
scripts/approved_plan_continuity_gate.mjs \
scripts/approved_plan_dispatch_binding.mjs \
scripts/test_approved_plan_continuity_gate.mjs \
hooks/force-recall/handler.ts \
docs/runbooks/approved-plan-continuity.md
Expected: matching lines confirm all baseline rules come from checked-in files
Step 3: Commit baseline notes
git add docs/plans/2026-04-24-continuity-plugin-mvp.md
git commit -m "docs: capture continuity plugin extraction baseline"
Task 1 Baseline Worklog (captured 2026-04-24)
Reviewed source-of-truth files
scripts/approved_plan_continuity_gate.mjsscripts/approved_plan_dispatch_binding.mjsscripts/test_approved_plan_continuity_gate.mjsscripts/test_force_recall_long_task_preflight.mjshooks/force-recall/handler.tsdocs/runbooks/approved-plan-continuity.md
Current responsibilities baseline
-
scripts/approved_plan_continuity_gate.mjs- Reads JSON input from
--input <path>and emits one JSON envelope to stdout. - Evaluates approved-plan continuity only when:
taskState === 'complete'- a next action is known via
nextDerivedAction ?? derivedAction - no valid
dispatchReceiptis present replyClosureStateis not one of the legal terminal states.
- Hard-coded legal terminal states today are exactly:
waiting_userblockedpending_verification
- Current failure output is:
ok: falsestatus: 'continuity_failure'verdict: 'continuity_failure'reason: 'missing_dispatch_receipt'
- Current pass output is:
ok: truestatus: 'pass'verdict: 'pass'
- Always stamps
gate: 'approved_plan_continuity'in the response envelope. - Current receipt validation inside the gate is intentionally narrow: it only requires
planId,currentTask, object-shapednextDerivedAction, anddispatchedAtto treatdispatchReceiptas valid.
- Reads JSON input from
-
scripts/approved_plan_dispatch_binding.mjs- Reads JSON input from
--input <path>and optional--receipt-diroverride. - Default receipt dir is
state/approved-plan-continuityresolved fromprocess.cwd(). - Builds a receipt from:
planIdcurrentTasknextDerivedAction ?? derivedActiondispatchedAtdispatchRunIdchildSessionKeyreplyClosureState
- Validates presence of all seven fields above before writing.
- Adds filesystem-safety checks by slugifying
planIdanddispatchRunId; missing/unsafe values are reported asplanId_filesystem_safe/dispatchRunId_filesystem_safe. - On success writes
receipt-<planIdSafe>-<dispatchRunIdSafe>.jsonunder the receipt dir and returns:ok: truestatus: 'receipt_written'binding: 'approved_plan_dispatch'receiptPathreceipt
- On validation failure returns:
ok: falsestatus: 'missing_required_receipt_fields'binding: 'approved_plan_dispatch'missing: string[]receiptPath: null
- Reads JSON input from
-
hooks/force-recall/handler.ts- Runs continuity as a hook-time adapter, not a pure module yet.
- Continuity input is assembled by
buildApprovedPlanContinuityInput(wrapperResult, autoChainPlanResult). - Hook mapping behavior today:
- source next action =
wrapperResult.nextDerivedAction ?? wrapperResult.derivedAction ?? plannerDerivedAction plannerDerivedActionis synthesized from auto-chain planner output whenderivedAction !== 'none'- if no next action exists, continuity gate is skipped (
null) replyClosureStatedefaults to:wrapperResult.replyClosureState, else'waiting_user'whenwrapperResult.handoff?.mode === 'button_path', else'completed'
dispatchReceiptis passed through fromwrapperResult.dispatchReceipt ?? nulltaskStatedefaults towrapperResult.taskState ?? (plannerDerivedAction ? 'complete' : null)
- source next action =
- The hook executes
scripts/approved_plan_continuity_gate.mjsvia JSON-script indirection, then renders a prompt block.
Minimal receipt contract baseline
- Receipt fields documented/runbook + dispatch binding currently agree on the following MVP minimum shape:
planIdcurrentTasknextDerivedActiondispatchedAtdispatchRunIdchildSessionKeyreplyClosureState
- Important parity note: the gate currently enforces only a smaller subset for pass/fail (
planId,currentTask, objectnextDerivedAction,dispatchedAt), while dispatch binding enforces the full seven-field receipt contract before persisting. - Extraction must preserve this mismatch unless explicitly changed in a later task.
Receipt filename / storage convention baseline
- Receipt directory default:
state/approved-plan-continuity - Receipt filename pattern:
receipt-<planIdSafe>-<dispatchRunIdSafe>.json - Safe segments are produced by lowercasing, trimming, replacing non
[a-z0-9._-]runs with-, trimming edge dashes, and collapsing repeated dashes.
Hook block shape baseline
- The continuity block currently injected by
hooks/force-recall/handler.tsis:
[APPROVED_PLAN_CONTINUITY_GATE]
status=<status>
verdict=<verdict>
reason=<reason?>
- HARD_GATE: Do not close out this reply as normal completion.
- HARD_GATE: Route back to continuity failure until a real next dispatch receipt exists, unless closure state is waiting_user, blocked, or pending_verification.
[/APPROVED_PLAN_CONTINUITY_GATE]
reason=is only included when present.- The two
HARD_GATElines are only added whenresult.ok === false. - The block is omitted entirely when no continuity input can be constructed.
Current input / output envelopes
- Continuity gate script envelope:
- input: JSON file path via
--input; optional--compact - output keys:
ok,status,verdict,reason?,gate,compact,inputPath,input
- input: JSON file path via
- Dispatch binding script envelope:
- input: JSON file path via
--input; optional--receipt-dir; optional--compact - output keys on success:
ok,status,binding,compact,inputPath,receipt,receiptPath,input - output keys on failure: same envelope plus
missing, withreceiptPath: null
- input: JSON file path via
Test coverage baseline already present
scripts/test_approved_plan_continuity_gate.mjscovers:- JSON envelope skeleton / gate label
- fail when
taskState=complete+ known next action + no valid dispatch receipt + non-legal closure - fail when planner uses
derivedActionwithout bound receipt - fail when
dispatchReceiptis fake non-null object without minimum fields - pass when valid dispatch receipt exists
- pass when
derivedActionhas bound dispatch receipt - pass for legal closure states
waiting_user,blocked,pending_verification
scripts/test_force_recall_long_task_preflight.mjscovers continuity integration in hook preflight:- continuity block is emitted in pass-path plumbing
- dry-run auto-chain dispatch alone still yields
status=continuity_failure - hook block must surface
verdict=continuity_failureandreason=missing_dispatch_receipt - hook guidance must route back to continuity failure until a real receipt exists
Known limitations / extraction constraints
- Continuity rules are hard-coded in scripts and hook glue; there is no plugin config surface yet.
- Hook integration shells out through script execution instead of importing a shared evaluator.
- Receipt validation logic is split:
- gate pass/fail uses a smaller inline validator
- receipt persistence uses a fuller required-field validator
- Current gate treats any object-shaped
nextDerivedActionas sufficient inside a receipt; action schema is not validated further. - Current gate does not read receipts from disk by convention; it only validates the in-memory
dispatchReceiptpayload passed into it. - Hook-generated
plannerDerivedActionis dry-run planner intent, not proof of real dispatch; continuity intentionally still fails until a real receipt is attached.
Task 2: Create plugin package skeleton
Files:
- Create:
plugins/continuity/package.json - Create:
plugins/continuity/README.md - Create:
plugins/continuity/README.zh-TW.md - Create:
plugins/continuity/HOOK.md - Create:
plugins/continuity/src/index.mjs
Step 1: Create the directory tree only Run:
mkdir -p plugins/continuity/src plugins/continuity/src/config plugins/continuity/src/continuity plugins/continuity/src/adapters plugins/continuity/examples plugins/continuity/test
Expected: directories exist
Step 2: Add minimal package metadata and placeholder entrypoint
package.jsonshould declare the plugin name, version, ESM type, and test script.src/index.mjsshould export placeholders for:- config schema/defaults
- evaluator
- receipt validator
- hook adapter factory
Step 3: Verify files exist Run:
test -f plugins/continuity/package.json \
&& test -f plugins/continuity/src/index.mjs \
&& test -f plugins/continuity/README.md \
&& test -f plugins/continuity/README.zh-TW.md \
&& echo OK
Expected: OK
Step 4: Commit
git add plugins/continuity
git commit -m "chore: add continuity plugin package skeleton"
Task 3: Define plugin config schema contract
Files:
- Create:
plugins/continuity/src/config/schema.mjs - Create:
plugins/continuity/src/config/defaults.mjs - Create:
plugins/continuity/examples/openclaw.continuity.example.json - Modify:
plugins/continuity/README.md - Modify:
plugins/continuity/README.zh-TW.md
Step 1: Write the config keys before implementation code Define exact keys for MVP, for example:
enabledplanMatcherslegalTerminalStatesreceiptDirrequireRealDispatchReceiptallowReplyClosureWithoutDispatchdebugadapter.forceRecall.enabledadapter.forceRecall.injectBlockLabel
Step 2: Add schema/default exports
schema.mjsshould export the allowed key list, required types, and validation helper contract.defaults.mjsshould export a concrete defaults object aligned with today’s behavior.
Step 3: Add example config
- Put a fully populated example JSON under
plugins/continuity/examples/openclaw.continuity.example.json.
Step 4: Verify example config matches schema keys Run:
node -e "import('./plugins/continuity/src/config/defaults.mjs').then(m=>console.log(Object.keys(m.defaultConfig||m.defaults||{})))"
Expected: prints the default key list without runtime error
Step 5: Commit
git add plugins/continuity/src/config plugins/continuity/examples/openclaw.continuity.example.json plugins/continuity/README.md plugins/continuity/README.zh-TW.md
git commit -m "feat: define continuity plugin config schema and defaults"
Task 4: Write failing tests for config validation
Files:
- Create:
plugins/continuity/test/continuity.config.test.mjs - Test:
plugins/continuity/src/config/schema.mjs
Step 1: Write fail-first tests for valid config Cover:
- accepts default config
- accepts custom receipt directory
- accepts custom legal terminal states list
Step 2: Write fail-first tests for invalid config Cover:
- rejects non-array
legalTerminalStates - rejects empty
receiptDir - rejects unknown terminal state type entries
- rejects disabled adapter object shape if malformed
Step 3: Run tests to verify failure Run:
node plugins/continuity/test/continuity.config.test.mjs
Expected: FAIL because validator behavior is not fully implemented yet
Step 4: Commit
git add plugins/continuity/test/continuity.config.test.mjs
git commit -m "test: add fail-first continuity plugin config validation tests"
Task 5: Implement minimal config validator
Files:
- Modify:
plugins/continuity/src/config/schema.mjs - Modify:
plugins/continuity/src/config/defaults.mjs - Modify:
plugins/continuity/test/continuity.config.test.mjs
Step 1: Implement the smallest validator that passes the tests
- Normalize missing fields from defaults.
- Reject malformed fields with explicit error codes/messages.
- Preserve current terminal states:
waiting_user,blocked,pending_verification.
Step 2: Run tests Run:
node plugins/continuity/test/continuity.config.test.mjs
Expected: PASS
Step 3: Commit
git add plugins/continuity/src/config/schema.mjs plugins/continuity/src/config/defaults.mjs plugins/continuity/test/continuity.config.test.mjs
git commit -m "feat: validate continuity plugin config"
Task 6: Extract receipt validator contract
Files:
- Create:
plugins/continuity/src/continuity/receipt-validator.mjs - Create:
plugins/continuity/src/continuity/types.md - Modify:
plugins/continuity/README.md - Modify:
plugins/continuity/README.zh-TW.md
Step 1: Document the receipt shape in one place Define these fields as the MVP minimum:
planIdcurrentTasknextDerivedActiondispatchedAtdispatchRunIdchildSessionKeyreplyClosureState
Step 2: Export validator API shape
validateReceipt(receipt)returns{ ok, errors, normalizedReceipt }isValidReceipt(receipt)returns boolean
Step 3: Verify file exists and exports load Run:
node -e "import('./plugins/continuity/src/continuity/receipt-validator.mjs').then(m=>console.log(Object.keys(m).sort().join(',')))"
Expected: export list includes validator functions
Step 4: Commit
git add plugins/continuity/src/continuity/receipt-validator.mjs plugins/continuity/src/continuity/types.md plugins/continuity/README.md plugins/continuity/README.zh-TW.md
git commit -m "chore: define continuity receipt validator contract"
Task 7: Write failing tests for receipt validator
Files:
- Create:
plugins/continuity/test/continuity.receipt-validator.test.mjs - Test:
plugins/continuity/src/continuity/receipt-validator.mjs
Step 1: Write success-path tests Cover:
- valid receipt with all minimum fields passes
- filesystem-safe IDs are accepted
Step 2: Write failure-path tests Cover:
- missing
planId - missing
dispatchRunId - non-object
nextDerivedAction - empty
childSessionKey - fake non-null receipt object fails
Step 3: Run tests to verify failure Run:
node plugins/continuity/test/continuity.receipt-validator.test.mjs
Expected: FAIL
Step 4: Commit
git add plugins/continuity/test/continuity.receipt-validator.test.mjs
git commit -m "test: add fail-first continuity receipt validator tests"
Task 8: Implement receipt validator
Files:
- Modify:
plugins/continuity/src/continuity/receipt-validator.mjs - Modify:
plugins/continuity/test/continuity.receipt-validator.test.mjs
Step 1: Implement field validation and normalization
- Reuse current minimum field expectations from
scripts/approved_plan_dispatch_binding.mjsandscripts/approved_plan_continuity_gate.mjs. - Keep validation separate from file I/O.
Step 2: Run tests Run:
node plugins/continuity/test/continuity.receipt-validator.test.mjs
Expected: PASS
Step 3: Commit
git add plugins/continuity/src/continuity/receipt-validator.mjs plugins/continuity/test/continuity.receipt-validator.test.mjs
git commit -m "feat: implement continuity receipt validator"
Task 9: Extract receipt store helper
Files:
- Create:
plugins/continuity/src/continuity/receipt-store.mjs - Modify:
plugins/continuity/examples/approved-plan-receipt.example.json - Modify:
plugins/continuity/README.md - Modify:
plugins/continuity/README.zh-TW.md
Step 1: Create the example receipt JSON
- Add a real-looking valid receipt example matching the documented minimum shape.
Step 2: Implement file naming helpers only Export small functions for:
- slugifying
planId - slugifying
dispatchRunId - building
receipt-<planId>-<dispatchRunId>.json - resolving the receipt path from config
Step 3: Verify helper exports load Run:
node -e "import('./plugins/continuity/src/continuity/receipt-store.mjs').then(m=>console.log(Object.keys(m).sort().join(',')))"
Expected: helper export names print successfully
Step 4: Commit
git add plugins/continuity/src/continuity/receipt-store.mjs plugins/continuity/examples/approved-plan-receipt.example.json plugins/continuity/README.md plugins/continuity/README.zh-TW.md
git commit -m "chore: add continuity receipt store helpers and examples"
Task 10: Write failing tests for receipt store behavior
Files:
- Create:
plugins/continuity/test/continuity.receipt-store.test.mjs - Test:
plugins/continuity/src/continuity/receipt-store.mjs
Step 1: Write tests for path generation Cover:
- builds correct filename from safe IDs
- normalizes unsafe characters
- resolves receipt path inside configured receipt dir
Step 2: Write tests for write/read round-trip Cover:
- writes validated receipt JSON
- reads back same logical payload
- rejects invalid receipt before write
Step 3: Run tests to verify failure Run:
node plugins/continuity/test/continuity.receipt-store.test.mjs
Expected: FAIL until read/write helpers exist
Step 4: Commit
git add plugins/continuity/test/continuity.receipt-store.test.mjs
git commit -m "test: add fail-first continuity receipt store tests"
Task 11: Implement receipt store helpers
Files:
- Modify:
plugins/continuity/src/continuity/receipt-store.mjs - Modify:
plugins/continuity/test/continuity.receipt-store.test.mjs
Step 1: Implement the minimum store API Export functions for:
buildReceiptFilenameresolveReceiptPathwriteReceiptreadReceipt
Step 2: Run tests Run:
node plugins/continuity/test/continuity.receipt-store.test.mjs
Expected: PASS
Step 3: Commit
git add plugins/continuity/src/continuity/receipt-store.mjs plugins/continuity/test/continuity.receipt-store.test.mjs
git commit -m "feat: implement continuity receipt store helpers"
Task 12: Extract continuity evaluator contract
Files:
- Create:
plugins/continuity/src/continuity/evaluator.mjs - Modify:
plugins/continuity/src/index.mjs - Modify:
plugins/continuity/README.md - Modify:
plugins/continuity/README.zh-TW.md
Step 1: Define evaluator input/output shape Input should support:
taskStatenextDerivedActionderivedActionreplyClosureStatedispatchReceipt- config override for legal terminal states
Output should support:
okstatusverdictreasongate
Step 2: Stub the evaluator exports
evaluateContinuity(payload, config)buildContinuityGateBlock(result, config)
Step 3: Verify exports load Run:
node -e "import('./plugins/continuity/src/continuity/evaluator.mjs').then(m=>console.log(Object.keys(m).sort().join(',')))"
Expected: export list prints successfully
Step 4: Commit
git add plugins/continuity/src/continuity/evaluator.mjs plugins/continuity/src/index.mjs plugins/continuity/README.md plugins/continuity/README.zh-TW.md
git commit -m "chore: define continuity evaluator contract"
Task 13: Write failing tests for continuity evaluator parity
Files:
- Create:
plugins/continuity/test/continuity.evaluator.test.mjs - Test:
plugins/continuity/src/continuity/evaluator.mjs - Reference:
scripts/test_approved_plan_continuity_gate.mjs
Step 1: Port the current continuity gate cases into plugin tests Cover at least:
- fail when task complete + next action known + no dispatch receipt + closure not legal
- fail when planner returns
derivedActionwithout bound dispatch receipt - fail when fake non-null receipt object is supplied
- pass when valid dispatch receipt exists
- pass when closure is
waiting_user - pass when closure is
blocked - pass when closure is
pending_verification
Step 2: Add one plugin-specific config override case
- custom legal terminal states list works
Step 3: Run tests to verify failure Run:
node plugins/continuity/test/continuity.evaluator.test.mjs
Expected: FAIL
Step 4: Commit
git add plugins/continuity/test/continuity.evaluator.test.mjs
git commit -m "test: add fail-first continuity evaluator parity tests"
Task 14: Implement continuity evaluator
Files:
- Modify:
plugins/continuity/src/continuity/evaluator.mjs - Modify:
plugins/continuity/src/continuity/receipt-validator.mjs - Modify:
plugins/continuity/test/continuity.evaluator.test.mjs
Step 1: Implement the smallest evaluator that matches current behavior
- Reuse receipt validator instead of inline checks.
- Preserve current failure reason:
missing_dispatch_receipt. - Preserve current legal closure state behavior.
Step 2: Run tests Run:
node plugins/continuity/test/continuity.evaluator.test.mjs
Expected: PASS
Step 3: Commit
git add plugins/continuity/src/continuity/evaluator.mjs plugins/continuity/src/continuity/receipt-validator.mjs plugins/continuity/test/continuity.evaluator.test.mjs
git commit -m "feat: implement continuity evaluator"
Task 15: Add script bridge for backward compatibility
Files:
- Create:
plugins/continuity/src/adapters/script-bridge.mjs - Modify:
scripts/approved_plan_continuity_gate.mjs - Modify:
scripts/approved_plan_dispatch_binding.mjs
Step 1: Write failing bridge tests first
- The old scripts should still produce compatible JSON envelopes by delegating to plugin modules.
Step 2: Implement thin bridge wiring
- Keep CLI parsing in scripts if easiest.
- Move decision logic to plugin modules.
Step 3: Run existing script tests Run:
node scripts/test_approved_plan_continuity_gate.mjs
Expected: PASS with plugin-backed logic
Step 4: Commit
git add plugins/continuity/src/adapters/script-bridge.mjs scripts/approved_plan_continuity_gate.mjs scripts/approved_plan_dispatch_binding.mjs
git commit -m "refactor: bridge legacy continuity scripts to plugin modules"
Task 16: Extract hook adapter contract
Files:
- Create:
plugins/continuity/src/adapters/force-recall.mjs - Modify:
plugins/continuity/HOOK.md - Modify:
plugins/continuity/src/index.mjs
Step 1: Define hook adapter responsibilities The adapter should:
- accept hook context and plugin config
- build continuity input from hook state
- call the evaluator
- return a prompt block or structured gate result
- avoid duplicating evaluator rules
Step 2: Stub the factory export Export something like:
createForceRecallContinuityAdapter(config)runForceRecallContinuityAdapter(ctx, config)
Step 3: Verify exports load Run:
node -e "import('./plugins/continuity/src/adapters/force-recall.mjs').then(m=>console.log(Object.keys(m).sort().join(',')))"
Expected: export names print successfully
Step 4: Commit
git add plugins/continuity/src/adapters/force-recall.mjs plugins/continuity/HOOK.md plugins/continuity/src/index.mjs
git commit -m "chore: define force-recall continuity adapter contract"
Task 17: Write failing tests for hook adapter
Files:
- Create:
plugins/continuity/test/continuity.plugin.test.mjs - Test:
plugins/continuity/src/adapters/force-recall.mjs - Reference:
hooks/force-recall/handler.ts
Step 1: Write success-path adapter tests Cover:
- returns no block when no approved-plan continuity context exists
- returns pass block when receipt is valid
Step 2: Write fail-path adapter tests Cover:
- returns hard-gate block when continuity fails
- includes expected gate label and reason
- honors config override for block label/debug mode
Step 3: Run tests to verify failure Run:
node plugins/continuity/test/continuity.plugin.test.mjs
Expected: FAIL
Step 4: Commit
git add plugins/continuity/test/continuity.plugin.test.mjs
git commit -m "test: add fail-first continuity hook adapter tests"
Task 18: Implement hook adapter
Files:
- Modify:
plugins/continuity/src/adapters/force-recall.mjs - Modify:
plugins/continuity/src/continuity/evaluator.mjs - Modify:
plugins/continuity/test/continuity.plugin.test.mjs
Step 1: Implement adapter logic with minimal hook assumptions
- Build gate input from hook payload.
- Delegate decisions to evaluator.
- Build the hard-gate block string in one place.
Step 2: Run tests Run:
node plugins/continuity/test/continuity.plugin.test.mjs
Expected: PASS
Step 3: Commit
git add plugins/continuity/src/adapters/force-recall.mjs plugins/continuity/src/continuity/evaluator.mjs plugins/continuity/test/continuity.plugin.test.mjs
git commit -m "feat: implement continuity force-recall adapter"
Task 19: Wire force-recall hook to the plugin adapter
Files:
- Modify:
hooks/force-recall/handler.ts - Test:
scripts/test_force_recall_long_task_preflight.mjs - Reference:
plugins/continuity/src/adapters/force-recall.mjs
Step 1: Write the smallest integration change
- Replace inline continuity-specific logic in
handler.tswith plugin adapter invocation. - Keep unrelated long-task governor behavior unchanged.
Step 2: Run targeted verification Run:
node scripts/test_approved_plan_continuity_gate.mjs
node scripts/test_force_recall_long_task_preflight.mjs
node --check hooks/force-recall/handler.ts
Expected: PASS
Step 3: Commit
git add hooks/force-recall/handler.ts
git commit -m "refactor: route force-recall continuity gate through plugin adapter"
Task 20: Add plugin-level smoke test
Files:
- Create:
plugins/continuity/test/continuity.smoke.test.mjs - Modify:
plugins/continuity/package.json - Modify:
plugins/continuity/examples/openclaw.continuity.example.json
Step 1: Write a smoke test that exercises the public plugin path Smoke path should:
- load config
- validate config
- validate receipt
- evaluate a failing continuity payload
- evaluate a passing payload with valid receipt
Step 2: Run the smoke test Run:
node plugins/continuity/test/continuity.smoke.test.mjs
Expected: PASS
Step 3: Expose a package script Add package script, for example:
{
"scripts": {
"test": "node test/continuity.config.test.mjs && node test/continuity.receipt-validator.test.mjs && node test/continuity.receipt-store.test.mjs && node test/continuity.evaluator.test.mjs && node test/continuity.plugin.test.mjs && node test/continuity.smoke.test.mjs"
}
}
Step 4: Verify package test command Run:
cd plugins/continuity && npm test
Expected: PASS
Step 5: Commit
git add plugins/continuity/package.json plugins/continuity/test/continuity.smoke.test.mjs plugins/continuity/examples/openclaw.continuity.example.json
git commit -m "test: add continuity plugin smoke test and package test script"
Task 21: Write bilingual README installation/apply instructions
Files:
- Modify:
plugins/continuity/README.md - Modify:
plugins/continuity/README.zh-TW.md - Reference:
plugins/continuity/HOOK.md - Reference:
plugins/continuity/examples/openclaw.continuity.example.json
Step 1: Add English README sections Include:
- what problem the plugin solves
- MVP scope/non-goals
- install location and package layout
- config reference table/list
- example config snippet
- receipt format summary
- hook adapter usage
- smoke test command
- migration note from hard-coded scripts
Step 2: Add Traditional Chinese README sections with parity Include the same sections as the English README.
Step 3: Verify both READMEs mention the same critical commands Run:
rg -n "npm test|openclaw|receiptDir|waiting_user|pending_verification|blocked" plugins/continuity/README.md plugins/continuity/README.zh-TW.md
Expected: both files contain the same core operational terms
Step 4: Commit
git add plugins/continuity/README.md plugins/continuity/README.zh-TW.md plugins/continuity/HOOK.md
git commit -m "docs: add bilingual continuity plugin installation and usage guides"
Task 22: Add example application note for root workspace config
Files:
- Modify:
plugins/continuity/README.md - Modify:
plugins/continuity/README.zh-TW.md - Optional Create:
docs/runbooks/continuity-plugin-apply.md
Step 1: Document how to apply the plugin in a real OpenClaw workspace Show a concrete example of:
- where the plugin folder lives
- how config points at
state/approved-plan-continuity - how
force-recallshould load/use the adapter
Step 2: Add a do-not-do list Explicitly warn against:
- changing core continuity rules during extraction
- using fake dispatch receipts for pass-through
- removing current scripts before parity tests pass
Step 3: Verify paths are exact Run:
test -d plugins/continuity && test -d state/approved-plan-continuity && test -f hooks/force-recall/handler.ts && echo OK
Expected: OK
Step 4: Commit
git add plugins/continuity/README.md plugins/continuity/README.zh-TW.md docs/runbooks/continuity-plugin-apply.md
git commit -m "docs: add continuity plugin apply guidance for workspace integration"
Task 23: Run full verification suite
Files:
- Test:
plugins/continuity/test/*.mjs - Test:
scripts/test_approved_plan_continuity_gate.mjs - Test:
scripts/test_force_recall_long_task_preflight.mjs - Check:
hooks/force-recall/handler.ts
Step 1: Run plugin package tests Run:
cd plugins/continuity && npm test
Expected: PASS
Step 2: Run compatibility tests from repo root Run:
node scripts/test_approved_plan_continuity_gate.mjs
node scripts/test_force_recall_long_task_preflight.mjs
node --check hooks/force-recall/handler.ts
Expected: PASS
Step 3: Record exact verification results in the plan tail or PR notes
- Copy exact commands
- Copy PASS summary counts
- Note any skipped tests
Step 4: Commit
git add plugins/continuity hooks/force-recall/handler.ts scripts/approved_plan_continuity_gate.mjs scripts/approved_plan_dispatch_binding.mjs docs/plans/2026-04-24-continuity-plugin-mvp.md
git commit -m "chore: verify continuity plugin MVP end-to-end"
Task 24: Final acceptance checklist and handoff
Files:
- Modify:
docs/plans/2026-04-24-continuity-plugin-mvp.md - Review:
plugins/continuity/README.md - Review:
plugins/continuity/README.zh-TW.md
Step 1: Add a checked acceptance checklist to the bottom of the plan Include:
- config schema implemented
- evaluator extracted
- receipt validator extracted
- hook adapter wired
- plugin-level tests passing
- bilingual README complete
- example config present
- smoke test present
- compatibility path preserved
Step 2: Mark remaining risks explicitly List at least:
- plugin loader assumptions may differ from current repo conventions
- current repo lacks an existing continuity plugin precedent
- future non-
force-recalladapters are out of MVP scope
Step 3: Leave status as pending verification, not complete
- Follow the workspace rule that implementation is not “done” until verified by the owner flow.
Step 4: Commit
git add docs/plans/2026-04-24-continuity-plugin-mvp.md
git commit -m "docs: finalize continuity plugin MVP implementation plan"
MVP Validation Checklist
plugins/continuity/package exists with entrypoint, docs, examples, and tests- Config schema/defaults exist and are test-covered
- Receipt validator exists and is test-covered
- Receipt store helpers exist and are test-covered
- Continuity evaluator exists and matches current hard-gate behavior
- Legacy scripts bridge to plugin logic or are otherwise compatibility-covered
hooks/force-recall/handler.tsconsumes plugin adapter instead of continuity-specific inline logic- English README explains install/config/test/migration
- Traditional Chinese README explains install/config/test/migration
- Example config and example receipt are checked in
- Smoke test passes
- Existing continuity and force-recall tests still pass
Risks / Open Questions
- The repo currently has an empty
plugins/directory, so actual OpenClaw plugin manifest/loading conventions may need one discovery slice before implementation. hooks/force-recall/handler.tscurrently mixes several long-task concerns; extracting only continuity logic must avoid accidental behavior drift in unrelated gate-lock/auto-chain code.- Current script tests cover continuity decisions but not yet the full plugin install path, so smoke coverage is mandatory for MVP credibility.
- The bilingual README must stay behaviorally aligned with actual example config and commands; drift here would make the plugin “documented” but not really adoptable.
Plan complete and saved to docs/plans/2026-04-24-continuity-plugin-mvp.md. Two execution options:
1. Subagent-Driven (this session) - I dispatch fresh subagent per task, review between tasks, fast iteration
2. Parallel Session (separate) - Open new session with executing-plans, batch execution with checkpoints
Which approach?
If Subagent-Driven chosen:
- REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development
- Stay in this session
- Fresh subagent per task + code review
If Parallel Session chosen:
- Guide them to open new session in worktree
- REQUIRED SUB-SKILL: New session uses superpowers:executing-plans