/** * Copyright (c) 2025 Elara AI Pty Ltd * Licensed under BSL 1.1. See LICENSE for details. */ import type { VersionVector, Structure } from '@elaraai/e3-types'; import type { StorageBackend } from '../storage/interfaces.js'; import type { DataflowExecutionState, InitializeResult, PrepareTaskResult, TaskCompletedResult, TaskFailedResult, FinalizeResult, TreeUpdateResult, ExecutionEvent } from './types.js'; /** * Options for initializing a dataflow execution. */ export interface StepInitializeOptions { /** Maximum concurrent task executions (default: 4) */ concurrency?: number; /** Force re-execution even if cached (default: false) */ force?: boolean; /** Filter to run only specific task(s) by exact name */ filter?: string; } /** * Initialize a new dataflow execution. * * Builds the dependency graph, snapshots root input versions, initializes * version vectors, and creates the initial execution state. * * @param storage - Storage backend * @param repo - Repository identifier * @param workspace - Workspace name * @param executionId - Unique execution ID * @param options - Execution options * @returns Initial state and ready tasks * * @throws {WorkspaceNotFoundError} If workspace doesn't exist * @throws {WorkspaceNotDeployedError} If workspace has no package deployed * @throws {TaskNotFoundError} If filter specifies a task that doesn't exist */ export declare function stepInitialize(storage: StorageBackend, repo: string, workspace: string, executionId: string, options?: StepInitializeOptions): Promise; /** * Resolve the set of tasks a run is permitted to schedule. * * With no `--filter`, every task may run (returns null — "no restriction"). A * `--filter ` scopes the run to that task's dependency closure — the * target plus its transitive producers — so the target's (usually cached) * upstream can run and make it ready. Restricting to the bare target instead * would strand it `pending` on dependencies that never get scheduled. * * @param state - Current execution state * @returns Set of task names permitted to run, or null if unrestricted */ export declare function stepGetRunSet(state: DataflowExecutionState): Set | null; /** * Decide whether a task's cache should be bypassed (force re-execution). * * `--force` on its own re-executes every task. Combined with `--filter ` * it applies to the explicitly named target only — the target's dependencies * run from cache — so "re-run just this task" does not re-execute the whole * upstream tree. Keeping this scope in one place keeps the cache-bypass * decision in {@link stepPrepareTask} and the runner's force flag in agreement. * * @param state - Current execution state * @param taskName - Name of the task being prepared or executed * @returns True if the task must re-execute regardless of a cached result */ export declare function stepTaskForced(state: DataflowExecutionState, taskName: string): boolean; /** * Get tasks that are ready to execute. * * A task is ready when: * 1. All tasks it depends on have completed (not just started) * 2. It passes the filter (if any) * 3. It is not already completed, in-progress, failed, skipped, or deferred * * This is a pure function - it only reads state. * * @param state - Current execution state * @returns Array of task names that are ready to execute */ export declare function stepGetReady(state: DataflowExecutionState): string[]; /** * Check if the execution is complete. * * An execution is complete when all tasks are in a terminal state * (completed, failed, skipped) or have permanently unresolvable * dependencies. Returns false if any non-terminal tasks remain. * * This is a pure function - it only reads state. * * @param state - Current execution state * @returns True if execution is complete */ export declare function stepIsComplete(state: DataflowExecutionState): boolean; /** * Detect input changes since the last snapshot. * * Reads current root input dataset hashes from storage and compares * against the snapshot stored in state. For each change, updates the * input snapshot and version vectors, and emits input_changed events. * * @param storage - Storage backend * @param state - Execution state to mutate (inputSnapshot, versionVectors) * @returns Changes detected and events emitted */ export declare function stepDetectInputChanges(storage: StorageBackend, state: DataflowExecutionState, cachedStructure?: Structure | null): Promise<{ changes: Array<{ path: string; previousHash: string | null; newHash: string; }>; events: ExecutionEvent[]; }>; /** * Invalidate tasks affected by input changes. * * For each affected task that is not currently in_progress: * - completed: reset to pending, decrement executed/cached counter, emit task_invalidated * - deferred: reset to pending * - pending/ready: leave as-is (will pick up new inputs naturally) * - skipped: leave as-is (upstream failure still applies) * - failed: leave as-is (task already failed; orchestrator is winding down) * * @param state - Execution state to mutate * @param changes - Input changes from stepDetectInputChanges * @returns Invalidated task names and events */ export declare function stepInvalidateTasks(state: DataflowExecutionState, changes: Array<{ path: string; }>): { invalidated: string[]; events: ExecutionEvent[]; }; /** * Check version vector consistency for a task's inputs. * * All input version vectors must agree on shared keys (same root input path * must have the same hash in every vector that contains it). * * @param state - Execution state * @param taskName - Task to check * @returns Consistency result with merged VV or conflict path */ export declare function stepCheckVersionConsistency(state: DataflowExecutionState, taskName: string): { consistent: true; mergedVV: VersionVector; } | { consistent: false; conflictPath: string; }; /** * Prepare a task for execution by resolving inputs and checking cache. * * This async operation: * 1. Resolves input hashes from current workspace state * 2. Checks if there's a valid cached execution * * @param storage - Storage backend * @param state - Current execution state * @param taskName - Name of the task to prepare * @returns Preparation result with input hashes and cache status */ export declare function stepPrepareTask(storage: StorageBackend, state: DataflowExecutionState, taskName: string): Promise; /** * Mark a task as started (in-progress). * * Mutates the execution state to record that a task has begun execution. * * @param state - Execution state to mutate * @param taskName - Name of the task * @returns Event to record */ export declare function stepTaskStarted(state: DataflowExecutionState, taskName: string): ExecutionEvent; /** * Mark a task as completed successfully. * * Mutates the execution state, computes the merged version vector for the * task's output, and returns the newly ready tasks. * * @param state - Execution state to mutate * @param taskName - Name of the task * @param outputHash - Hash of the output dataset * @param cached - Whether the result was from cache * @param duration - Execution duration in milliseconds * @returns Result with newly ready tasks and event */ export declare function stepTaskCompleted(state: DataflowExecutionState, taskName: string, outputHash: string, cached: boolean, duration: number): { result: TaskCompletedResult; event: ExecutionEvent; }; /** * Mark a task as failed. * * Mutates the execution state and returns tasks that should be skipped. * * @param state - Execution state to mutate * @param taskName - Name of the failed task * @param error - Error message (optional) * @param exitCode - Exit code if process failed (optional) * @param duration - Execution duration in milliseconds * @returns Result with tasks to skip and event */ export declare function stepTaskFailed(state: DataflowExecutionState, taskName: string, error: string | undefined, exitCode: number | undefined, duration: number): { result: TaskFailedResult; event: ExecutionEvent; }; /** * Mark tasks as skipped due to upstream failure. * * @param state - Execution state to mutate * @param taskNames - Names of tasks to skip * @param cause - Name of the task that caused the skip * @returns Array of events to record */ export declare function stepTasksSkipped(state: DataflowExecutionState, taskNames: string[], cause: string): ExecutionEvent[]; /** * Finalize the execution and return the result. * * Mutates the execution state to mark it as completed or failed. * * @param state - Execution state to mutate * @param runId - Dataflow run ID (UUIDv7) from the orchestrator * @returns Final result */ export declare function stepFinalize(state: DataflowExecutionState, runId: string): { result: FinalizeResult; event: ExecutionEvent; }; /** * Cancel the execution. * * @param state - Execution state to mutate * @param reason - Reason for cancellation * @returns Event to record */ export declare function stepCancel(state: DataflowExecutionState, reason?: string): ExecutionEvent; /** * Prepare the execution state for a yield checkpoint (or crash recovery). * * Resets all `in_progress` tasks to `pending` so the persisted state is * resumable: a resumed loop re-launches them via stepGetReady, and tasks * that actually finished in the meantime are served from the execution * cache. `deferred` tasks are also reset — deferral is a launch-time * decision and the version-vector conflict may have resolved since; the * consistency check at re-launch re-defers if it genuinely persists. * The execution status stays 'running' — yield is a pause, not a * terminal state. * * @param state - Execution state to mutate * @returns Names of tasks that were reset to pending */ export declare function stepYield(state: DataflowExecutionState): { reset: string[]; }; /** * Apply a task's output to the workspace tree with version vector. * * Writes the output ref file with the merged version vector from the task's * inputs. Per-dataset ref writes are atomic and independent, so no * serialization is needed for concurrent writes to different paths. * * @param storage - Storage backend * @param repo - Repository identifier * @param workspace - Workspace name * @param outputPathStr - Output path as a keypath string (e.g., ".results.data") * @param outputHash - Hash of the output dataset to write * @param versions - Merged version vector for provenance tracking * @returns Result indicating success */ export declare function stepApplyTreeUpdate(storage: StorageBackend, repo: string, workspace: string, outputPathStr: string, outputHash: string, versions: VersionVector): Promise; //# sourceMappingURL=steps.d.ts.map