import assert from 'node:assert/strict'; import plugin, { createForceRecallContinuityAdapter, defaultConfig, evaluateContinuity, } from '../src/index.mjs'; function test(name, fn) { try { fn(); console.log(`ok - ${name}`); } catch (error) { console.error(`not ok - ${name}`); throw error; } } test('index exports plugin surface', () => { assert.equal(plugin.name, '@openclaw/plugin-continuity'); assert.equal(typeof evaluateContinuity, 'function'); assert.equal(defaultConfig.adapter.forceRecall.enabled, true); }); test('adapter preserves current hook parity for plain wrapper next-action mapping', () => { const adapter = createForceRecallContinuityAdapter(defaultConfig); const out = adapter.evaluate({ wrapperResult: { classification: 'long_task', planId: 'plan-1', currentTask: 'task-7', taskState: 'complete', nextDerivedAction: { type: 'message_subagent', task: 'continue' }, replyClosureState: 'completed', dispatchReceipt: null, }, }); assert.equal(out.result.ok, true); assert.match(out.block, /status=pass/); }); test('adapter fails when planner-derived auto-next boundary exists without dispatch receipt', () => { const adapter = createForceRecallContinuityAdapter(defaultConfig); const out = adapter.evaluate({ wrapperResult: { classification: 'long_task', planId: 'plan-2', currentTask: 'task-8', replyClosureState: 'completed', dispatchReceipt: null, }, autoChainPlanResult: { derivedAction: 'continue_task_9', dispatchMode: 'message_subagent', }, }); assert.equal(out.result.ok, false); assert.equal(out.result.reason, 'missing_auto_next_dispatch'); assert.match(out.block, /continuity_failure/); }); console.log('continuity.plugin.test.mjs PASS');