import { normalizeContinuityEngineInput, createContinuityEngineContract, } from '../continuity/engine.mjs'; import { evaluateContinuity, buildContinuityGateBlock } from '../continuity/evaluator.mjs'; function isNonEmptyString(value) { return typeof value === 'string' && value.trim().length > 0; } export function buildApprovedPlanContinuityInput(wrapperResult, autoChainPlanResult = null) { if (!wrapperResult || wrapperResult.classification !== 'long_task') return null; const wrapperNextAction = wrapperResult?.nextDerivedAction ?? wrapperResult?.derivedAction ?? null; const plannerDerivedAction = autoChainPlanResult?.derivedAction && autoChainPlanResult.derivedAction !== 'none' ? { type: autoChainPlanResult.dispatchMode ?? 'no_dispatch', action: autoChainPlanResult.derivedAction, } : null; const nextDerivedAction = wrapperNextAction ?? plannerDerivedAction; if (nextDerivedAction == null) return null; const replyClosureState = isNonEmptyString(wrapperResult?.replyClosureState) ? wrapperResult.replyClosureState : (wrapperResult?.handoff?.mode === 'button_path' ? 'waiting_user' : 'completed'); const dispatchReceipt = wrapperResult?.dispatchReceipt ?? null; const nextTaskKnown = wrapperResult?.nextTaskKnown === true || (plannerDerivedAction != null && isNonEmptyString(autoChainPlanResult?.derivedAction) && autoChainPlanResult.derivedAction !== 'none'); const sameApprovedPlan = wrapperResult?.sameApprovedPlan === true || plannerDerivedAction != null; const taskBoundaryStop = wrapperResult?.taskBoundaryStop === true || replyClosureState === 'completed'; const highRiskStop = wrapperResult?.highRiskStop === true; return normalizeContinuityEngineInput({ planId: wrapperResult?.planId ?? 'hook-preflight-approved-plan', currentTask: wrapperResult?.currentTask ?? wrapperResult?.requiredNextAction ?? 'hook-preflight-task', taskState: wrapperResult?.taskState ?? (plannerDerivedAction ? 'complete' : null), nextDerivedAction, replyClosureState, dispatchReceipt, nextTaskKnown, sameApprovedPlan, taskBoundaryStop, highRiskStop, metadata: { adapterSource: 'force-recall', classification: wrapperResult?.classification ?? null, }, }); } export function createForceRecallContinuityAdapter(config = {}) { const legalTerminalStates = config?.legalTerminalStates; const label = config?.adapter?.forceRecall?.injectBlockLabel ?? 'APPROVED_PLAN_CONTINUITY_GATE'; return { evaluate({ wrapperResult, autoChainPlanResult = null }) { const input = buildApprovedPlanContinuityInput(wrapperResult, autoChainPlanResult); if (!input) { return createContinuityEngineContract({ input: null, evaluation: null, block: '', options: { adapterName: 'force-recall', label }, }); } const evaluation = evaluateContinuity(input, { legalTerminalStates }); const block = buildContinuityGateBlock(evaluation, { legalTerminalStates, label }); return createContinuityEngineContract({ input, evaluation, block, options: { adapterName: 'force-recall', label }, }); }, }; } export function runForceRecallContinuityAdapter({ wrapperResult, autoChainPlanResult = null, config = {} } = {}) { return createForceRecallContinuityAdapter(config).evaluate({ wrapperResult, autoChainPlanResult }); }