/** * Orchestrate Handoff Operations * * orchestrateHandoff and HandoffStep types migrated from * packages/cleo/src/dispatch/engines/orchestrate-engine.ts. * * Session operations (sessionStatus, sessionEnd, sessionContextInject) are * injected via DI to avoid a core→cleo import cycle. The domain layer * (orchestrate.ts) passes the actual session engine functions. * * @task T1570 * @task T4478 */ import type { Session, TaskWorkState } from '@cleocode/contracts'; import type { OrchestrateHandoffParams } from '@cleocode/contracts/operations/orchestrate'; import { type EngineResult } from '../engine-result.js'; export type { EngineResult }; /** Status of a single handoff step. */ export type HandoffStepStatus = 'pending' | 'completed' | 'failed' | 'skipped'; /** State of a single handoff step. */ export interface HandoffStepState { /** Step completion status. */ status: HandoffStepStatus; /** Operation name for this step. */ operation: string; /** Optional diagnostic message. */ message?: string; } /** Aggregate state of all three handoff steps. */ export interface HandoffState { contextInject: HandoffStepState; sessionEnd: HandoffStepState; spawn: HandoffStepState; } /** Detailed failure information for partial handoff. */ export interface HandoffFailureDetails { failedStep: 'session.context.inject' | 'session.end' | 'orchestrate.spawn'; activeSessionId: string | null; endedSessionId: string | null; idempotency: { key: string | null; policy: 'non-idempotent'; safeRetryFrom: 'start' | 'orchestrate.spawn'; reason: string; }; steps: HandoffState; } /** * Session status result shape (subset used by handoff). * * Typed as a minimal interface so core does not import from cleo's * session-engine.ts. The domain call-site passes the actual function. */ interface SessionStatusResult { hasActiveSession: boolean; session?: Session | null; taskWork?: TaskWorkState | null; overrideCount: number; } /** Context injection data returned by sessionContextInject (opaque to core). */ type ContextInjectionData = unknown; /** * Session operations injected into orchestrateHandoff to avoid a core→cleo import cycle. * * The actual functions come from `packages/cleo/src/dispatch/engines/session-engine.ts`. * Core only knows the shape, not the implementation. */ export interface HandoffSessionOps { /** Check whether an active session exists and return its state. */ sessionStatus: (projectRoot: string) => Promise>; /** End the active session and return the ended session id. */ sessionEnd: (projectRoot: string, note?: string) => Promise>; /** Inject handoff context into the session record. */ sessionContextInject: (protocolType: string, params?: { taskId?: string; variant?: string; }, projectRoot?: string) => EngineResult; } /** * orchestrate.handoff - Composite session handoff + successor spawn * * Step order is explicit and fixed: * 1) session.context.inject * 2) session.end * 3) orchestrate.spawn * * Idempotency policy: * - Non-idempotent overall. A retry after step 2 can duplicate spawn output. * - Failures include exact step state and a safe retry entry point. * * Session operations are injected via `sessionOps` to avoid a core→cleo * import cycle. The domain layer passes the actual cleo session engine functions. * * @param params - Handoff parameters including taskId, protocolType, etc. * @param sessionOps - Injected session operations (from cleo session-engine.ts). * @param projectRoot - Optional project root path. * @returns Engine result with handoff data or structured failure. * @task T4478 */ export declare function orchestrateHandoff(params: OrchestrateHandoffParams, sessionOps: HandoffSessionOps, projectRoot?: string): Promise; //# sourceMappingURL=handoff-ops.d.ts.map