@cascade-flow/worker 0.2.17 → 0.2.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import type { Backend } from "@cascade-flow/backend-interface";
1
+ import type { Backend, StepEvent } from "@cascade-flow/backend-interface";
2
2
  import { type LoadedStep } from "@cascade-flow/runner";
3
3
  /**
4
4
  * Check if all dependencies for a step are satisfied
@@ -20,7 +20,7 @@ import { type LoadedStep } from "@cascade-flow/runner";
20
20
  * @param runId - Run identifier
21
21
  * @returns true if all dependencies are in terminal state and satisfy execution requirements
22
22
  */
23
- export declare function checkDependenciesSatisfied(step: LoadedStep, backend: Backend, workflowSlug: string, runId: string): Promise<boolean>;
23
+ export declare function checkDependenciesSatisfied(step: LoadedStep, backend: Backend, workflowSlug: string, runId: string, stepEventsByStepId?: Map<string, StepEvent[]>): Promise<boolean>;
24
24
  /**
25
25
  * Load outputs from all dependencies
26
26
  * Returns a map of dependency alias to output value
@@ -1 +1 @@
1
- {"version":3,"file":"dependency-resolver.d.ts","sourceRoot":"","sources":["../../src/execution/dependency-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAE/D,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAkClB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CA0C9B;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,UAAU,EAAE,EACtB,YAAY,GAAE,OAAe,GAC5B,UAAU,EAAE,CAed"}
1
+ {"version":3,"file":"dependency-resolver.d.ts","sourceRoot":"","sources":["../../src/execution/dependency-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAE1E,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,GAC5C,OAAO,CAAC,OAAO,CAAC,CAmClB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CA0C9B;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,UAAU,EAAE,EACtB,YAAY,GAAE,OAAe,GAC5B,UAAU,EAAE,CAed"}
package/dist/index.js CHANGED
@@ -80,9 +80,9 @@ import {
80
80
  // src/execution/dependency-resolver.ts
81
81
  import { projectStepState } from "@cascade-flow/backend-interface";
82
82
  import { isOptional } from "@cascade-flow/workflow";
83
- async function checkDependenciesSatisfied(step, backend, workflowSlug, runId) {
83
+ async function checkDependenciesSatisfied(step, backend, workflowSlug, runId, stepEventsByStepId) {
84
84
  for (const [depKey, dep] of Object.entries(step.dependencies)) {
85
- const depEvents = await backend.loadEvents(workflowSlug, runId, {
85
+ const depEvents = stepEventsByStepId?.get(dep.id) ?? await backend.loadEvents(workflowSlug, runId, {
86
86
  category: "step",
87
87
  stepId: dep.id
88
88
  });
@@ -205,10 +205,11 @@ async function scheduleStep(backend, workflowSlug, runId, stepId, reason, attemp
205
205
  availableAt: options?.availableAt ?? now,
206
206
  reason,
207
207
  attemptNumber,
208
- retryDelayMs: options?.retryDelayMs
208
+ retryDelayMs: options?.retryDelayMs,
209
+ priority: options?.priority
209
210
  });
210
211
  }
211
- async function scheduleDownstreamSteps(backend, workflowSlug, runId, completedStepId, allSteps) {
212
+ async function scheduleDownstreamSteps(backend, workflowSlug, runId, completedStepId, allSteps, options) {
212
213
  const scheduledSteps = [];
213
214
  const dependentSteps = findDependentSteps(completedStepId, allSteps, false);
214
215
  for (const dependentStep of dependentSteps) {
@@ -219,12 +220,12 @@ async function scheduleDownstreamSteps(backend, workflowSlug, runId, completedSt
219
220
  stepId: dependentStep.id
220
221
  });
221
222
  if (stepEvents.length === 0) {
222
- await scheduleStep(backend, workflowSlug, runId, dependentStep.id, "dependency-satisfied", 1);
223
+ await scheduleStep(backend, workflowSlug, runId, dependentStep.id, "dependency-satisfied", 1, { priority: options?.priority });
223
224
  scheduledSteps.push(dependentStep.name);
224
225
  } else {
225
226
  const state = projectStepState3(stepEvents, workflowSlug);
226
227
  if (state.status === "pending") {
227
- await scheduleStep(backend, workflowSlug, runId, dependentStep.id, "dependency-satisfied", 1);
228
+ await scheduleStep(backend, workflowSlug, runId, dependentStep.id, "dependency-satisfied", 1, { priority: options?.priority });
228
229
  scheduledSteps.push(dependentStep.name);
229
230
  }
230
231
  }
@@ -415,6 +416,7 @@ class StepWorker {
415
416
  activeSteps = new Map;
416
417
  stats;
417
418
  workflowCache = new Map;
419
+ freeSlots = new Set;
418
420
  constructor(backend, options = {}) {
419
421
  this.workerId = options.workerId || `step-worker-${hostname()}-${process.pid}-${getMicrosecondTimestamp5()}`;
420
422
  this.backend = backend || new FileSystemBackend(options.baseDir || "./.runs");
@@ -427,6 +429,7 @@ class StepWorker {
427
429
  staleThreshold: options.staleThreshold ?? 30000,
428
430
  staleCheckInterval: options.staleCheckInterval ?? 1e4,
429
431
  schedulerInterval: options.schedulerInterval ?? 5000,
432
+ schedulerRunBatchSize: options.schedulerRunBatchSize ?? 200,
430
433
  shutdownTimeout: options.shutdownTimeout ?? 30000,
431
434
  workflowsDir: options.workflowsDir || "./workflows",
432
435
  baseDir: options.baseDir || "./.runs"
@@ -440,6 +443,9 @@ class StepWorker {
440
443
  failedSteps: 0,
441
444
  reclaimedSteps: 0
442
445
  };
446
+ for (let i = 0;i < this.options.concurrency; i++) {
447
+ this.freeSlots.add(i);
448
+ }
443
449
  }
444
450
  getStats() {
445
451
  return { ...this.stats };
@@ -565,10 +571,6 @@ class StepWorker {
565
571
  if (this.activeSteps.size >= this.options.concurrency) {
566
572
  break;
567
573
  }
568
- const isClaimable = await this.backend.isStepClaimable(workflowSlug, runId, stepId);
569
- if (!isClaimable) {
570
- continue;
571
- }
572
574
  const workflowData = this.workflowCache.get(workflowSlug);
573
575
  const stepExists = workflowData?.steps.some((s) => s.id === stepId);
574
576
  if (!stepExists) {
@@ -595,13 +597,18 @@ class StepWorker {
595
597
  console.warn(`[StepWorker ${this.workerId}] Workflow ${workflowSlug} not in cache, skipping`);
596
598
  continue;
597
599
  }
598
- let runIds = [];
600
+ let activeRuns = [];
599
601
  try {
600
- runIds = await this.backend.listRunIds(workflowSlug);
602
+ const result = await this.backend.listRuns({
603
+ workflowSlug,
604
+ status: ["pending", "running"]
605
+ });
606
+ activeRuns = result.runs;
601
607
  } catch {
602
608
  continue;
603
609
  }
604
- for (const runId of runIds) {
610
+ for (const run of activeRuns) {
611
+ const runId = run.runId;
605
612
  try {
606
613
  const workflowEvents = await loadWorkflowEvents(this.backend, workflowSlug, runId);
607
614
  if (workflowEvents.length === 0)
@@ -639,23 +646,25 @@ class StepWorker {
639
646
  let allStepsCompleted = true;
640
647
  let anyStepFailed = false;
641
648
  let failedStepName;
649
+ const runSubmittedEventForPriority = getRunSubmittedEvent(workflowEvents);
650
+ const runPriority = runSubmittedEventForPriority?.priority;
642
651
  const allStepEvents = await this.backend.loadStepEventsForProjection(workflowSlug, runId);
643
652
  for (const step of workflowData.steps) {
644
653
  const stepEvents = allStepEvents.get(step.id) || [];
645
654
  if (stepEvents.length === 0) {
646
655
  allStepsCompleted = false;
647
- const canSchedule = await checkDependenciesSatisfied(step, this.backend, workflowSlug, runId);
656
+ const canSchedule = await checkDependenciesSatisfied(step, this.backend, workflowSlug, runId, allStepEvents);
648
657
  if (canSchedule) {
649
- await scheduleStep(this.backend, workflowSlug, runId, step.id, Object.keys(step.dependencies).length === 0 ? "initial" : "dependency-satisfied", 1);
658
+ await scheduleStep(this.backend, workflowSlug, runId, step.id, Object.keys(step.dependencies).length === 0 ? "initial" : "dependency-satisfied", 1, { priority: runPriority });
650
659
  console.log(`[StepWorker ${this.workerId}] Scheduled ${step.name} in ${workflowSlug}/${runId}`);
651
660
  }
652
661
  } else {
653
662
  const state = projectStepState6(stepEvents, workflowSlug);
654
663
  if (state.status === "pending") {
655
664
  allStepsCompleted = false;
656
- const canSchedule = await checkDependenciesSatisfied(step, this.backend, workflowSlug, runId);
665
+ const canSchedule = await checkDependenciesSatisfied(step, this.backend, workflowSlug, runId, allStepEvents);
657
666
  if (canSchedule) {
658
- await scheduleStep(this.backend, workflowSlug, runId, step.id, "dependency-satisfied", 1);
667
+ await scheduleStep(this.backend, workflowSlug, runId, step.id, "dependency-satisfied", 1, { priority: runPriority });
659
668
  console.log(`[StepWorker ${this.workerId}] Scheduled pending step ${step.name} in ${workflowSlug}/${runId}`);
660
669
  }
661
670
  } else if (state.status === "failed" && state.terminal) {
@@ -726,6 +735,7 @@ class StepWorker {
726
735
  let startTime = getMicrosecondTimestamp5();
727
736
  let attemptNumber = null;
728
737
  let heartbeatTimer = null;
738
+ let slotIndex = null;
729
739
  try {
730
740
  const workflowData = this.workflowCache.get(workflowSlug);
731
741
  if (!workflowData) {
@@ -735,21 +745,34 @@ class StepWorker {
735
745
  if (!step) {
736
746
  throw new Error(`Step ${stepId} not found in workflow ${workflowSlug}`);
737
747
  }
748
+ const slotIterator = this.freeSlots.values().next();
749
+ if (slotIterator.done) {
750
+ throw new Error(`No free slots available`);
751
+ }
752
+ slotIndex = slotIterator.value;
753
+ this.freeSlots.delete(slotIndex);
738
754
  const claimResult = await this.backend.claimScheduledStep(workflowSlug, runId, stepId, this.workerId, {
739
755
  dependencies: Object.keys(step.dependencies),
740
756
  timestamp: startTime,
741
- attemptNumber: 1
757
+ attemptNumber: 1,
758
+ slotIndex,
759
+ workerConcurrency: this.options.concurrency
742
760
  });
743
761
  if (!claimResult) {
744
762
  console.log(`[StepWorker ${this.workerId}] Skipped ${stepKey} (already claimed)`);
763
+ this.freeSlots.add(slotIndex);
745
764
  return;
746
765
  }
747
766
  attemptNumber = claimResult.attemptNumber;
748
767
  startTime = getMicrosecondTimestamp5();
768
+ const capturedSlotIndex = slotIndex;
749
769
  heartbeatTimer = setInterval(() => {
750
770
  if (attemptNumber === null)
751
771
  return;
752
- this.backend.saveStepHeartbeat(workflowSlug, runId, stepId, this.workerId, attemptNumber).catch((err) => {
772
+ this.backend.saveStepHeartbeat(workflowSlug, runId, stepId, this.workerId, attemptNumber, {
773
+ slotIndex: capturedSlotIndex,
774
+ workerConcurrency: this.options.concurrency
775
+ }).catch((err) => {
753
776
  console.error(`[StepWorker ${this.workerId}] Error sending heartbeat for ${stepKey}:`, err);
754
777
  });
755
778
  }, this.options.heartbeatInterval);
@@ -759,7 +782,8 @@ class StepWorker {
759
782
  runId,
760
783
  stepId,
761
784
  attemptNumber,
762
- heartbeatTimer: trackedTimer
785
+ heartbeatTimer: trackedTimer,
786
+ slotIndex: capturedSlotIndex
763
787
  });
764
788
  this.stats.currentlyRunning++;
765
789
  console.log(`[StepWorker ${this.workerId}] Executing ${step.name} (attempt ${attemptNumber})`);
@@ -861,13 +885,17 @@ class StepWorker {
861
885
  clearInterval(heartbeatTimer);
862
886
  heartbeatTimer = null;
863
887
  }
888
+ const completedStep = this.activeSteps.get(stepKey);
889
+ if (completedStep) {
890
+ this.freeSlots.add(completedStep.slotIndex);
891
+ }
864
892
  this.activeSteps.delete(stepKey);
865
893
  this.stats.currentlyRunning--;
866
894
  this.stats.totalStepsProcessed++;
867
895
  if (this.options.mode === "unified") {
868
896
  const workflowData2 = this.workflowCache.get(workflowSlug);
869
897
  if (workflowData2) {
870
- const scheduled = await scheduleDownstreamSteps(this.backend, workflowSlug, runId, stepId, workflowData2.steps);
898
+ const scheduled = await scheduleDownstreamSteps(this.backend, workflowSlug, runId, stepId, workflowData2.steps, { priority: runSubmittedEvent?.priority });
871
899
  if (scheduled.length > 0) {
872
900
  console.log(`[StepWorker ${this.workerId}] Scheduled downstream steps: ${scheduled.join(", ")}`);
873
901
  }
@@ -879,11 +907,15 @@ class StepWorker {
879
907
  const activeStep = this.activeSteps.get(stepKey);
880
908
  if (activeStep) {
881
909
  clearInterval(activeStep.heartbeatTimer);
910
+ this.freeSlots.add(activeStep.slotIndex);
882
911
  this.activeSteps.delete(stepKey);
883
912
  this.stats.currentlyRunning--;
884
913
  } else if (heartbeatTimer) {
885
914
  clearInterval(heartbeatTimer);
886
915
  heartbeatTimer = null;
916
+ if (slotIndex !== null) {
917
+ this.freeSlots.add(slotIndex);
918
+ }
887
919
  }
888
920
  if (attemptNumber === null) {
889
921
  return;
@@ -960,6 +992,8 @@ class StepWorker {
960
992
  retryDelayMs = error.delayMs;
961
993
  }
962
994
  const nextRetryAt = getMicrosecondTimestamp5() + retryDelayMs * MICROSECONDS_PER_MILLISECOND;
995
+ const retryWorkflowEvents = await loadWorkflowEvents(this.backend, workflowSlug, runId);
996
+ const retryRunSubmittedEvent = getRunSubmittedEvent(retryWorkflowEvents);
963
997
  await this.backend.saveStepFailedAndScheduleRetry(workflowSlug, runId, stepId2, stepError, {
964
998
  duration,
965
999
  attemptNumber: currentAttemptNumber,
@@ -973,7 +1007,8 @@ class StepWorker {
973
1007
  retryDelayMs,
974
1008
  totalPolicies: policies.length,
975
1009
  policyIndex: policyResult.policyIndex,
976
- attemptInPolicy: policyResult.attemptInPolicy
1010
+ attemptInPolicy: policyResult.attemptInPolicy,
1011
+ priority: retryRunSubmittedEvent?.priority
977
1012
  });
978
1013
  const totalAttempts = getTotalAttempts(policies);
979
1014
  console.log(`[StepWorker ${this.workerId}] Scheduled retry for ${step.name} (attempt ${nextAttemptNumber}/${totalAttempts}, policy ${policyResult.policyIndex + 1}/${policies.length}, delay ${retryDelayMs}ms)`);
@@ -1010,4 +1045,4 @@ export {
1010
1045
  StepWorker
1011
1046
  };
1012
1047
 
1013
- //# debugId=2EA382FEED348E2C64756E2164756E21
1048
+ //# debugId=2B02B1179FF8DE8264756E2164756E21
package/dist/index.js.map CHANGED
@@ -2,17 +2,17 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/step-worker.ts", "../src/retry/policy-resolver.ts", "../src/retry/index.ts", "../src/execution/dependency-resolver.ts", "../src/scheduling/skip-handler.ts", "../src/scheduling/step-scheduler.ts", "../src/utils/step-key.ts", "../src/scheduling/workflow-lifecycle.ts", "../src/utils/event-helpers.ts"],
4
4
  "sourcesContent": [
5
- "import { FileSystemBackend } from \"@cascade-flow/backend-filesystem\";\nimport type { Backend } from \"@cascade-flow/backend-interface\";\nimport { getMicrosecondTimestamp, MICROSECONDS_PER_MILLISECOND, convertZodToJSONSchema, projectStepState, serializeError } from \"@cascade-flow/backend-interface\";\nimport { hostname } from \"node:os\";\nimport { join } from \"node:path\";\nimport { discoverSteps, discoverWorkflows, executeStepInProcess, calculateWorkflowHash, getGitInfo, type LoadedStep, type CheckpointData, type CheckpointFailedData } from \"@cascade-flow/runner\";\nimport { Skip } from \"@cascade-flow/workflow\";\nimport {\n getCurrentPolicy,\n computeDelay,\n resolveRetryPolicies,\n getTotalAttempts,\n isRetryableError,\n isNonRetryableError,\n} from \"./retry\";\nimport type { ZodSchema } from \"zod\";\nimport { checkDependenciesSatisfied, loadDependencyOutputs } from \"./execution/dependency-resolver.ts\";\nimport { cascadeSkip, handleStepSkip } from \"./scheduling/skip-handler.ts\";\nimport { scheduleDownstreamSteps, scheduleStep } from \"./scheduling/step-scheduler.ts\";\nimport { createStepKey, extractStepId } from \"./utils/step-key.ts\";\nimport {\n handleWorkflowCompletion,\n handleWorkflowFailure,\n handleWorkflowStart,\n parseWorkflowInput,\n validateWorkflowInput,\n} from \"./scheduling/workflow-lifecycle.ts\";\nimport type { StepWorkerOptions, StepWorkerStats } from \"./types.ts\";\nimport {\n getRunSubmittedEvent,\n getWorkflowInputValidationEvent,\n getWorkflowTerminalState,\n hasWorkflowStarted,\n hasWorkflowSubmitted,\n hasWorkflowValidatedInput,\n loadWorkflowEvents\n} from \"./utils/event-helpers.ts\";\n\n/**\n * StepWorker - long-running process for step-level distributed workflow execution\n *\n * Architecture:\n * - Workers claim and execute individual steps (not entire workflows)\n * - Steps are scheduled when their dependencies complete\n * - Multiple workers can collaboratively execute steps from the same workflow\n * - Enables finer-grained parallelization and better resource utilization\n *\n * Features:\n * - Executor loop: Claims and executes scheduled steps\n * - Scheduler loop: Finds ready steps and schedules them\n * - Heartbeat loop: Sends heartbeats for running steps\n * - Reclamation loop: Detects and reclaims stale steps from crashed workers\n * - Retry support: Automatic retries with configurable delay\n * - Timeout enforcement: Abort-controlled cancellation of hung subprocesses\n * - Graceful shutdown: Waits for active steps to complete\n */\nexport class StepWorker {\n private workerId: string;\n private backend: Backend;\n private options: Required<StepWorkerOptions>;\n private running: boolean = false;\n private activeSteps: Map<string, {\n workflowSlug: string;\n runId: string;\n stepId: string;\n attemptNumber: number;\n heartbeatTimer: Timer;\n }> = new Map();\n private stats: StepWorkerStats;\n private workflowCache: Map<string, { metadata: any; steps: LoadedStep[]; inputSchema?: ZodSchema }> = new Map();\n\n constructor(backend?: Backend, options: StepWorkerOptions = {}) {\n // Generate worker ID if not provided (using microseconds for consistency)\n this.workerId = options.workerId || `step-worker-${hostname()}-${process.pid}-${getMicrosecondTimestamp()}`;\n\n // Use provided backend or create filesystem backend\n this.backend = backend || new FileSystemBackend(options.baseDir || \"./.runs\");\n\n // Set defaults for all options\n this.options = {\n workerId: this.workerId,\n mode: options.mode ?? \"unified\",\n concurrency: options.concurrency ?? 1,\n pollInterval: options.pollInterval ?? 1000,\n heartbeatInterval: options.heartbeatInterval ?? 5000,\n staleThreshold: options.staleThreshold ?? 30000,\n staleCheckInterval: options.staleCheckInterval ?? 10000,\n schedulerInterval: options.schedulerInterval ?? 5000,\n shutdownTimeout: options.shutdownTimeout ?? 30000,\n workflowsDir: options.workflowsDir || \"./workflows\",\n baseDir: options.baseDir || \"./.runs\",\n };\n\n this.stats = {\n workerId: this.workerId,\n mode: this.options.mode,\n startedAt: getMicrosecondTimestamp(), // Convert to microseconds\n totalStepsProcessed: 0,\n currentlyRunning: 0,\n failedSteps: 0,\n reclaimedSteps: 0,\n };\n }\n\n /**\n * Get current worker statistics\n */\n getStats(): StepWorkerStats {\n return { ...this.stats };\n }\n\n /**\n * Start the worker (blocking operation)\n *\n * Starts appropriate loops based on worker mode:\n * - unified: All 4 loops (executor, scheduler, heartbeat, reclamation)\n * - executor: Only executor + heartbeat loops\n * - scheduler: Only scheduler + reclamation loops\n */\n async start(): Promise<void> {\n if (this.running) {\n throw new Error(\"Worker is already running\");\n }\n\n this.running = true;\n console.log(`[StepWorker ${this.workerId}] Starting in ${this.options.mode} mode...`);\n\n // Set up signal handlers for graceful shutdown\n this.setupSignalHandlers();\n\n // Load workflow metadata and cache it\n console.log(`[StepWorker ${this.workerId}] Loading workflows from ${this.options.workflowsDir}...`);\n await this.loadWorkflows();\n\n // Register workflows with backend\n console.log(`[StepWorker ${this.workerId}] Registering workflows with backend...`);\n await this.registerWorkflows();\n\n // Start appropriate loops based on mode\n const loops: Promise<void>[] = [];\n\n if (this.options.mode === \"unified\" || this.options.mode === \"executor\") {\n // Executor loop: Claims and executes scheduled steps\n loops.push(this.executorLoop());\n console.log(`[StepWorker ${this.workerId}] Executor loop started (concurrency: ${this.options.concurrency})`);\n }\n\n if (this.options.mode === \"unified\" || this.options.mode === \"scheduler\") {\n // Scheduler loop: Finds ready steps and schedules them\n loops.push(this.schedulerLoop());\n console.log(`[StepWorker ${this.workerId}] Scheduler loop started (interval: ${this.options.schedulerInterval}ms)`);\n\n // Reclamation loop: Detects and reclaims stale steps\n loops.push(this.reclamationLoop());\n console.log(`[StepWorker ${this.workerId}] Reclamation loop started (threshold: ${this.options.staleThreshold}ms)`);\n }\n\n console.log(`[StepWorker ${this.workerId}] Started successfully`);\n\n // Wait for all loops to complete (on shutdown)\n try {\n await Promise.all(loops);\n } finally {\n clearInterval(this.heartbeatTimer as any);\n console.log(`[StepWorker ${this.workerId}] Stopped`);\n }\n }\n\n /**\n * Gracefully stop the worker\n * Waits for active steps to complete before shutting down\n */\n async stop(): Promise<void> {\n if (!this.running) {\n return;\n }\n\n console.log(`[StepWorker ${this.workerId}] Stopping... (${this.activeSteps.size} active steps)`);\n this.running = false;\n\n // Wait for active steps to complete (with timeout)\n const shutdownStart = Date.now();\n while (this.activeSteps.size > 0 && Date.now() - shutdownStart < this.options.shutdownTimeout) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n if (this.activeSteps.size > 0) {\n console.warn(`[StepWorker ${this.workerId}] Forced shutdown with ${this.activeSteps.size} active steps`);\n }\n\n console.log(`[StepWorker ${this.workerId}] Stopped`);\n }\n\n /**\n * Load and cache workflow metadata and steps\n */\n private async loadWorkflows(): Promise<void> {\n try {\n const workflows = await discoverWorkflows(this.options.workflowsDir);\n\n for (const workflow of workflows) {\n const steps = await discoverSteps(workflow.stepsDir);\n this.workflowCache.set(workflow.slug, {\n metadata: workflow,\n steps,\n inputSchema: workflow.inputSchema, // Cache Zod schema for validation\n });\n }\n\n console.log(`[StepWorker ${this.workerId}] Loaded ${workflows.length} workflows`);\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Failed to load workflows:`, error);\n throw error;\n }\n }\n\n /**\n * Register workflows with backend\n * Converts Zod schemas to JSON Schema and stores workflow metadata\n */\n private async registerWorkflows(): Promise<void> {\n try {\n for (const [slug, { metadata, steps, inputSchema }] of this.workflowCache) {\n // Convert Zod schema to JSON Schema if present\n let inputSchemaJSON = undefined;\n if (inputSchema) {\n try {\n inputSchemaJSON = convertZodToJSONSchema(inputSchema);\n } catch (error) {\n console.warn(\n `[StepWorker ${this.workerId}] Failed to convert schema for workflow ${slug}: ${error}`\n );\n }\n }\n\n // Build step definitions array\n const stepDefinitions = steps.map((step) => ({\n id: step.id, // Unique identifier (directory name)\n name: step.name, // Display name\n dependencies: Object.values(step.dependencies).map(dep => dep.id), // Use IDs for references\n exportOutput: step.exportOutput ?? false,\n }));\n\n // Register with backend\n await this.backend.registerWorkflow({\n slug,\n name: metadata.name,\n location: metadata.dir, // Filesystem directory path\n inputSchemaJSON,\n steps: stepDefinitions,\n });\n\n // Create workflow version\n const versionId = await calculateWorkflowHash(metadata);\n const git = await getGitInfo(metadata.dir);\n const stepManifest = steps.map((s) => s.id);\n\n await this.backend.createWorkflowVersion({\n workflowSlug: slug,\n versionId,\n createdAt: getMicrosecondTimestamp(),\n stepManifest,\n totalSteps: steps.length,\n git,\n });\n }\n\n console.log(`[StepWorker ${this.workerId}] Registered ${this.workflowCache.size} workflows`);\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Failed to register workflows:`, error);\n throw error;\n }\n }\n\n /**\n * Executor loop: Claims and executes scheduled steps\n */\n private async executorLoop(): Promise<void> {\n while (this.running) {\n try {\n // Check if we have capacity to execute more steps\n if (this.activeSteps.size >= this.options.concurrency) {\n await new Promise((resolve) => setTimeout(resolve, this.options.pollInterval));\n continue;\n }\n\n // List scheduled steps available for claiming\n const limit = this.options.concurrency - this.activeSteps.size;\n const scheduledSteps = await this.backend.listScheduledSteps({ limit });\n\n if (scheduledSteps.length === 0) {\n // No steps available, wait before polling again\n await new Promise((resolve) => setTimeout(resolve, this.options.pollInterval));\n continue;\n }\n\n // Try to claim and execute each step (up to concurrency limit)\n for (const { workflowSlug, runId, stepId } of scheduledSteps) {\n if (this.activeSteps.size >= this.options.concurrency) {\n break;\n }\n\n // Check if step is still claimable (might have been claimed by another worker)\n const isClaimable = await this.backend.isStepClaimable(workflowSlug, runId, stepId);\n\n if (!isClaimable) {\n continue; // Already claimed or no longer scheduled\n }\n\n // Check if step still exists in current workflow definition\n const workflowData = this.workflowCache.get(workflowSlug);\n const stepExists = workflowData?.steps.some((s) => s.id === stepId);\n if (!stepExists) {\n await this.handleOrphanStep(workflowSlug, runId, stepId);\n continue;\n }\n\n // Execute step (non-blocking - fires and forgets)\n this.executeStep(workflowSlug, runId, stepId).catch((err) => {\n console.error(`[StepWorker ${this.workerId}] Error executing ${createStepKey(workflowSlug, runId, stepId)}:`, err);\n });\n }\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Error in executor loop:`, error);\n await new Promise((resolve) => setTimeout(resolve, this.options.pollInterval));\n }\n }\n }\n\n /**\n * Scheduler loop: Finds ready steps and schedules them\n */\n private async schedulerLoop(): Promise<void> {\n while (this.running) {\n try {\n // List active workflows (workflows with incomplete runs)\n const activeWorkflows = await this.backend.listActiveWorkflows();\n\n for (const workflowSlug of activeWorkflows) {\n // Get workflow from cache\n const workflowData = this.workflowCache.get(workflowSlug);\n if (!workflowData) {\n console.warn(`[StepWorker ${this.workerId}] Workflow ${workflowSlug} not in cache, skipping`);\n continue;\n }\n\n // Get all runs for this workflow\n let runIds: string[] = [];\n try {\n runIds = await this.backend.listRunIds(workflowSlug);\n } catch {\n // Failed to list runs\n continue;\n }\n\n for (const runId of runIds) {\n try {\n // Load workflow events to check run state\n const workflowEvents = await loadWorkflowEvents(this.backend, workflowSlug, runId);\n if (workflowEvents.length === 0) continue;\n\n // Check if workflow is already in a terminal state\n const { hasCompleted, hasFailed, hasCancelled } = getWorkflowTerminalState(workflowEvents);\n\n if (hasCompleted || hasFailed || hasCancelled) {\n continue; // Skip terminal workflows\n }\n\n // Check if workflow has been submitted but not started yet\n const hasSubmitted = hasWorkflowSubmitted(workflowEvents);\n const hasStarted = hasWorkflowStarted(workflowEvents);\n\n if (!hasSubmitted) {\n continue; // Skip workflows without RunSubmitted (shouldn't happen)\n }\n\n // If submitted but not started, emit WorkflowStarted event\n if (!hasStarted) {\n const runSubmittedEvent = getRunSubmittedEvent(workflowEvents);\n if (!runSubmittedEvent) {\n throw new Error(`No RunSubmitted event found for ${workflowSlug}/${runId}`);\n }\n\n await handleWorkflowStart(this.backend, workflowSlug, runId, {\n versionId: runSubmittedEvent.versionId,\n hasInputSchema: workflowData.inputSchema !== undefined,\n hasInput: !!(runSubmittedEvent && runSubmittedEvent.input !== undefined),\n }, workflowEvents);\n\n console.log(`[StepWorker ${this.workerId}] Started workflow ${workflowSlug}/${runId}`);\n }\n\n // Validate input (if not already validated)\n const hasValidatedInput = hasWorkflowValidatedInput(workflowEvents);\n\n if (!hasValidatedInput) {\n const workflowInput = parseWorkflowInput(workflowEvents);\n const validationResult = await validateWorkflowInput(\n this.backend,\n workflowSlug,\n runId,\n workflowInput,\n workflowData.inputSchema,\n workflowEvents\n );\n\n if (!validationResult.success) {\n console.log(\n `[StepWorker ${this.workerId}] Workflow ${workflowSlug}/${runId} failed (input validation)`\n );\n continue; // Skip to next run, don't schedule any steps\n }\n }\n\n // Track completion state\n let allStepsCompleted = true;\n let anyStepFailed = false;\n let failedStepName: string | undefined;\n\n // Load step events for state projection in a single batch query (avoids N+1)\n const allStepEvents = await this.backend.loadStepEventsForProjection(workflowSlug, runId);\n\n // For each step in the workflow, check if it should be scheduled\n for (const step of workflowData.steps) {\n // Get step events from batch-loaded map\n const stepEvents = allStepEvents.get(step.id) || [];\n\n // If step has no events yet, it's pending\n if (stepEvents.length === 0) {\n allStepsCompleted = false;\n\n // Check if dependencies are satisfied\n const canSchedule = await checkDependenciesSatisfied(step, this.backend, workflowSlug, runId);\n\n // If no dependencies (initial step) or all deps completed, schedule it\n if (canSchedule) {\n await scheduleStep(\n this.backend,\n workflowSlug,\n runId,\n step.id,\n Object.keys(step.dependencies).length === 0 ? \"initial\" : \"dependency-satisfied\",\n 1\n );\n\n console.log(`[StepWorker ${this.workerId}] Scheduled ${step.name} in ${workflowSlug}/${runId}`);\n }\n } else {\n // Step has events, check its state\n const state = projectStepState(stepEvents, workflowSlug);\n\n if (state.status === \"pending\") {\n allStepsCompleted = false;\n\n // Check if dependencies are satisfied\n const canSchedule = await checkDependenciesSatisfied(step, this.backend, workflowSlug, runId);\n\n if (canSchedule) {\n await scheduleStep(this.backend, workflowSlug, runId, step.id, \"dependency-satisfied\", 1);\n\n console.log(\n `[StepWorker ${this.workerId}] Scheduled pending step ${step.name} in ${workflowSlug}/${runId}`\n );\n }\n } else if (state.status === \"failed\" && state.terminal) {\n anyStepFailed = true;\n failedStepName = step.name;\n allStepsCompleted = false;\n } else if (state.status !== \"completed\" && state.status !== \"skipped\") {\n allStepsCompleted = false;\n }\n }\n }\n\n // Check for workflow completion\n if (allStepsCompleted) {\n await handleWorkflowCompletion(\n this.backend,\n workflowSlug,\n runId,\n workflowData.steps,\n workflowEvents\n );\n\n console.log(`[StepWorker ${this.workerId}] Workflow ${workflowSlug}/${runId} completed`);\n } else if (anyStepFailed) {\n await handleWorkflowFailure(\n this.backend,\n workflowSlug,\n runId,\n workflowData.steps,\n workflowEvents,\n failedStepName\n );\n\n console.log(\n `[StepWorker ${this.workerId}] Workflow ${workflowSlug}/${runId} failed (step: ${failedStepName})`\n );\n }\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Error processing run ${runId}:`, error);\n }\n }\n }\n\n await new Promise((resolve) => setTimeout(resolve, this.options.schedulerInterval));\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Error in scheduler loop:`, error);\n await new Promise((resolve) => setTimeout(resolve, this.options.schedulerInterval));\n }\n }\n }\n\n /**\n * Reclamation loop: Detects and reclaims stale steps from crashed workers\n */\n private async reclamationLoop(): Promise<void> {\n while (this.running) {\n try {\n const reclaimed = await this.backend.reclaimStaleSteps(\n this.options.staleThreshold * 1000, // Convert to microseconds\n this.workerId\n );\n\n if (reclaimed.length > 0) {\n console.log(`[StepWorker ${this.workerId}] Reclaimed ${reclaimed.length} stale steps`);\n this.stats.reclaimedSteps += reclaimed.length;\n }\n\n await new Promise((resolve) => setTimeout(resolve, this.options.staleCheckInterval));\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Error in reclamation loop:`, error);\n await new Promise((resolve) => setTimeout(resolve, this.options.staleCheckInterval));\n }\n }\n }\n\n /**\n * Load existing checkpoints for a step from events\n *\n * Returns a Map from checkpoint name to array of data (by sequence number)\n */\n private async loadCheckpointsFromEvents(\n workflowSlug: string,\n runId: string,\n stepId: string\n ): Promise<Map<string, string[]>> {\n const events = await this.backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId,\n });\n\n const checkpoints = new Map<string, string[]>();\n for (const event of events) {\n if (event.type === \"StepCheckpoint\") {\n if (!checkpoints.has(event.name)) {\n checkpoints.set(event.name, []);\n }\n const arr = checkpoints.get(event.name)!;\n // Ensure array is large enough for sequence number\n while (arr.length <= event.sequenceNumber) {\n arr.push(\"\");\n }\n arr[event.sequenceNumber] = event.data;\n }\n }\n return checkpoints;\n }\n\n /**\n * Execute a single step\n */\n private async executeStep(workflowSlug: string, runId: string, stepId: string): Promise<void> {\n const stepKey = createStepKey(workflowSlug, runId, stepId);\n let startTime = getMicrosecondTimestamp(); // Microseconds - declare at function scope\n let attemptNumber: number | null = null;\n let heartbeatTimer: Timer | null = null;\n\n try {\n // Get workflow and step metadata\n const workflowData = this.workflowCache.get(workflowSlug);\n if (!workflowData) {\n throw new Error(`Workflow ${workflowSlug} not found in cache`);\n }\n\n const step = workflowData.steps.find((s) => s.id === stepId);\n if (!step) {\n throw new Error(`Step ${stepId} not found in workflow ${workflowSlug}`);\n }\n\n // Atomically claim the step (using stepId)\n // Note: attemptNumber in metadata is a placeholder - backend will determine actual attempt number from step state\n const claimResult = await this.backend.claimScheduledStep(workflowSlug, runId, stepId, this.workerId, {\n dependencies: Object.keys(step.dependencies),\n timestamp: startTime,\n attemptNumber: 1, // Placeholder - backend determines actual attempt from step events\n });\n\n if (!claimResult) {\n console.log(`[StepWorker ${this.workerId}] Skipped ${stepKey} (already claimed)`);\n return;\n }\n\n attemptNumber = claimResult.attemptNumber;\n startTime = getMicrosecondTimestamp(); // Update startTime closer to actual execution\n\n // Track active step and start heartbeat (using stepId)\n heartbeatTimer = setInterval(() => {\n if (attemptNumber === null) return;\n this.backend.saveStepHeartbeat(workflowSlug, runId, stepId, this.workerId, attemptNumber).catch((err) => {\n console.error(`[StepWorker ${this.workerId}] Error sending heartbeat for ${stepKey}:`, err);\n });\n }, this.options.heartbeatInterval);\n\n const trackedTimer = heartbeatTimer!;\n\n this.activeSteps.set(stepKey, {\n workflowSlug,\n runId,\n stepId,\n attemptNumber,\n heartbeatTimer: trackedTimer,\n });\n\n this.stats.currentlyRunning++;\n\n console.log(`[StepWorker ${this.workerId}] Executing ${step.name} (attempt ${attemptNumber})`);\n\n // Load dependency outputs\n const dependencyOutputs = await loadDependencyOutputs(step, this.backend, workflowSlug, runId);\n\n // Load workflow input from RunSubmitted event (pre-validated by scheduler)\n const workflowEvents = await loadWorkflowEvents(this.backend, workflowSlug, runId);\n const runSubmittedEvent = getRunSubmittedEvent(workflowEvents);\n let workflowInput: unknown = undefined;\n\n if (runSubmittedEvent && runSubmittedEvent.input !== undefined) {\n // Parse input from event\n workflowInput = JSON.parse(runSubmittedEvent.input);\n }\n\n // If workflow has schema and validation succeeded, apply defaults (even when no input provided)\n if (workflowData.inputSchema) {\n const validationEvent = getWorkflowInputValidationEvent(workflowEvents);\n if (validationEvent && validationEvent.success) {\n // Re-parse with schema to get defaults (validation already confirmed this will succeed)\n // Use {} as fallback when no input provided to trigger Zod's default values\n const parseResult = workflowData.inputSchema.safeParse(workflowInput ?? {});\n if (parseResult.success) {\n workflowInput = parseResult.data;\n }\n }\n }\n\n // Build context (use step.name for display name in logs)\n const ctx = {\n runId,\n workflow: {\n slug: workflowSlug,\n name: workflowData.metadata.name,\n },\n input: workflowInput,\n log: (...args: any[]) => {\n console.log(`[${step.name}]`, ...args);\n },\n };\n\n // Execute step in subprocess with timeout\n // Priority: step timeout (most specific) → submission timeout → default 5 minutes\n const stepFile = join(step.dir, \"step.ts\");\n const submissionTimeoutMs = runSubmittedEvent && runSubmittedEvent.timeoutUs\n ? Math.floor(runSubmittedEvent.timeoutUs / 1000)\n : undefined;\n const timeout = step.timeoutMs ?? submissionTimeoutMs ?? 300000;\n\n // Load existing checkpoints for replay (from any previous attempts)\n const existingCheckpoints = await this.loadCheckpointsFromEvents(\n workflowSlug,\n runId,\n stepId\n );\n\n const abortController = new AbortController();\n const executionPromise = executeStepInProcess(\n stepFile,\n step.id, // Pass step ID for stable file paths\n dependencyOutputs,\n ctx,\n attemptNumber!,\n this.backend,\n // Real-time log emission callback\n async (log) => {\n // Create LogEntry event - use log.timestamp to preserve exact ordering\n const logEvent: Omit<import(\"@cascade-flow/backend-interface\").LogEntryEvent, \"eventId\"> = {\n workflowSlug,\n runId,\n category: \"step\",\n type: \"LogEntry\",\n stepId,\n stream: log.stream,\n message: log.message,\n attemptNumber: attemptNumber!,\n timestampUs: log.timestamp, // Use the timestamp captured by subprocess executor\n };\n await this.backend.appendEvent(workflowSlug, runId, logEvent as any);\n },\n // Checkpoint persistence callback\n async (checkpoint: CheckpointData) => {\n // Extract metadata from data and strip from payload\n let parentCheckpoint:\n | { name: string; sequenceNumber: number }\n | undefined;\n let label: string | undefined;\n let cleanedData = checkpoint.data;\n try {\n const parsed = JSON.parse(checkpoint.data);\n if (parsed?._parentCheckpoint) {\n parentCheckpoint = parsed._parentCheckpoint;\n delete parsed._parentCheckpoint;\n }\n if (parsed?._label) {\n label = parsed._label;\n delete parsed._label;\n }\n // Re-serialize without metadata fields\n cleanedData = JSON.stringify(parsed);\n } catch {\n // Ignore parse errors - use original data\n }\n\n await this.backend.saveStepCheckpoint(workflowSlug, runId, stepId, {\n name: checkpoint.name,\n sequenceNumber: checkpoint.sequenceNumber,\n attemptNumber: attemptNumber!,\n data: cleanedData,\n label,\n parentCheckpoint,\n });\n },\n // Checkpoint failure callback\n async (failure: CheckpointFailedData) => {\n await this.backend.saveStepCheckpointFailed(workflowSlug, runId, stepId, {\n name: failure.name,\n sequenceNumber: failure.sequenceNumber,\n attemptNumber: attemptNumber!,\n error: JSON.parse(failure.error),\n });\n },\n existingCheckpoints,\n {\n signal: abortController.signal,\n }\n );\n\n const timeoutTimer = setTimeout(() => {\n abortController.abort(new Error(`Step timeout after ${timeout}ms`));\n }, timeout);\n\n const { result: output } = await executionPromise.finally(() => {\n clearTimeout(timeoutTimer);\n });\n\n const endTime = getMicrosecondTimestamp(); // Microseconds\n const duration = endTime - startTime;\n\n // Logs are already emitted in real-time via the onLog callback\n // No need to emit them again here\n\n // Emit StepCompleted event (using stepId)\n await this.backend.saveStepComplete(\n workflowSlug,\n runId,\n stepId,\n output,\n {\n timestamp: endTime,\n duration,\n attemptNumber: attemptNumber!,\n output,\n },\n step.exportOutput ?? false\n );\n\n console.log(`[StepWorker ${this.workerId}] Completed ${step.name}`);\n\n // Cleanup\n if (heartbeatTimer) {\n clearInterval(heartbeatTimer);\n heartbeatTimer = null;\n }\n this.activeSteps.delete(stepKey);\n this.stats.currentlyRunning--;\n this.stats.totalStepsProcessed++;\n\n // If in unified mode, schedule downstream steps (using stepId)\n if (this.options.mode === \"unified\") {\n const workflowData = this.workflowCache.get(workflowSlug);\n if (workflowData) {\n const scheduled = await scheduleDownstreamSteps(\n this.backend,\n workflowSlug,\n runId,\n stepId,\n workflowData.steps\n );\n if (scheduled.length > 0) {\n console.log(\n `[StepWorker ${this.workerId}] Scheduled downstream steps: ${scheduled.join(\", \")}`\n );\n }\n }\n }\n } catch (error) {\n const failureContext = attemptNumber === null ? \"Failed to claim\" : \"Failed\";\n console.error(`[StepWorker ${this.workerId}] ${failureContext} ${stepKey}:`, error);\n\n const activeStep = this.activeSteps.get(stepKey);\n if (activeStep) {\n clearInterval(activeStep.heartbeatTimer);\n this.activeSteps.delete(stepKey);\n this.stats.currentlyRunning--;\n } else if (heartbeatTimer) {\n clearInterval(heartbeatTimer);\n heartbeatTimer = null;\n }\n\n if (attemptNumber === null) {\n return;\n }\n\n this.stats.failedSteps++;\n\n // Get workflow and step metadata for retry logic\n const workflowData = this.workflowCache.get(workflowSlug);\n if (!workflowData) {\n console.error(`[StepWorker ${this.workerId}] Workflow ${workflowSlug} not found in cache`);\n return;\n }\n\n // Extract stepId from stepKey (handles nested steps with slashes)\n const stepId = extractStepId(stepKey);\n if (!stepId) {\n console.error(`[StepWorker ${this.workerId}] Invalid stepKey format: ${stepKey}`);\n return;\n }\n const step = workflowData.steps.find((s) => s.id === stepId);\n if (!step) {\n console.error(`[StepWorker ${this.workerId}] Step ${stepId} not found in workflow ${workflowSlug}`);\n return;\n }\n\n // Load step events to get current attempt number (using stepId)\n const events = await this.backend.loadEvents(workflowSlug, runId, { category: \"step\", stepId });\n const state = projectStepState(events, workflowSlug);\n const currentAttemptNumber = state.attemptNumber;\n\n const endTime = getMicrosecondTimestamp(); // Microseconds\n const duration = endTime - (state.startTime || startTime);\n\n // Prepare error object using centralized error serialization\n const stepError = serializeError(error);\n\n // SKIP DETECTION: Check if error is a Skip (don't retry, just mark as skipped)\n if (error instanceof Error && (error.name === \"Skip\" || error instanceof Skip)) {\n const skipError = error as Skip;\n\n await handleStepSkip(this.backend, workflowSlug, runId, stepId, skipError, duration, currentAttemptNumber);\n\n console.log(`[StepWorker ${this.workerId}] Skipped ${step.name}: ${skipError.reason || skipError.message}`);\n\n // If in unified mode, check for cascade skips\n if (this.options.mode === \"unified\") {\n const workflowData = this.workflowCache.get(workflowSlug);\n if (workflowData) {\n await cascadeSkip(this.backend, workflowSlug, runId, stepId, workflowData.steps, this.workerId);\n }\n }\n\n return; // Don't retry, don't mark as failed\n }\n\n // Check for NonRetryableError - immediate terminal failure\n if (isNonRetryableError(error)) {\n await this.backend.saveStepFailed(workflowSlug, runId, stepId, stepError, {\n duration,\n attemptNumber: currentAttemptNumber,\n terminal: true,\n failureReason: \"execution-error\",\n });\n\n console.log(`[StepWorker ${this.workerId}] Terminal failure for ${step.name} (non-retryable error)`);\n return;\n }\n\n // Resolve retry policies (new format or legacy conversion)\n const policies = resolveRetryPolicies(step);\n\n // No retry policies configured - terminal failure\n if (!policies || policies.length === 0) {\n await this.backend.saveStepFailed(workflowSlug, runId, stepId, stepError, {\n duration,\n attemptNumber: currentAttemptNumber,\n terminal: true,\n failureReason: \"execution-error\",\n });\n\n console.log(`[StepWorker ${this.workerId}] Terminal failure for ${step.name} (no retry policy)`);\n return;\n }\n\n // Check if we should retry based on current attempt\n const nextAttemptNumber = currentAttemptNumber + 1;\n const policyResult = getCurrentPolicy(nextAttemptNumber, policies);\n\n if (policyResult.exhausted) {\n // Terminal failure - all retry policies exhausted\n await this.backend.saveStepFailed(workflowSlug, runId, stepId, stepError, {\n duration,\n attemptNumber: currentAttemptNumber,\n terminal: true,\n failureReason: \"exhausted-retries\",\n });\n\n const totalAttempts = getTotalAttempts(policies);\n console.log(`[StepWorker ${this.workerId}] Terminal failure for ${step.name} (exhausted ${totalAttempts} attempts across ${policies.length} policies)`);\n } else {\n // Not terminal - schedule retry\n // Check if RetryableError provides a custom delay override\n let retryDelayMs = computeDelay(policyResult.policy.backoff, policyResult.attemptInPolicy);\n if (isRetryableError(error) && error.delayMs !== undefined) {\n retryDelayMs = error.delayMs;\n }\n\n const nextRetryAt = getMicrosecondTimestamp() + retryDelayMs * MICROSECONDS_PER_MILLISECOND;\n\n // Use atomic method to ensure both failure and schedule events are written together\n await this.backend.saveStepFailedAndScheduleRetry(\n workflowSlug,\n runId,\n stepId,\n stepError,\n {\n duration,\n attemptNumber: currentAttemptNumber,\n nextRetryAt,\n failureReason: \"execution-error\",\n policyIndex: policyResult.policyIndex,\n attemptInPolicy: policyResult.attemptInPolicy,\n },\n {\n availableAt: nextRetryAt,\n nextAttemptNumber,\n retryDelayMs,\n totalPolicies: policies.length,\n policyIndex: policyResult.policyIndex,\n attemptInPolicy: policyResult.attemptInPolicy,\n }\n );\n\n const totalAttempts = getTotalAttempts(policies);\n console.log(\n `[StepWorker ${this.workerId}] Scheduled retry for ${step.name} (attempt ${nextAttemptNumber}/${totalAttempts}, policy ${policyResult.policyIndex + 1}/${policies.length}, delay ${retryDelayMs}ms)`\n );\n }\n }\n }\n\n /**\n * Handle an orphan step that no longer exists in the workflow definition\n * Writes a terminal StepFailed event to prevent infinite retry loops\n */\n private async handleOrphanStep(\n workflowSlug: string,\n runId: string,\n stepId: string\n ): Promise<void> {\n const stepKey = createStepKey(workflowSlug, runId, stepId);\n console.warn(\n `[StepWorker ${this.workerId}] Orphan step detected: ${stepKey} (step removed from workflow)`\n );\n\n const error = {\n name: \"StepRemovedError\",\n message: `Step \"${stepId}\" no longer exists in workflow \"${workflowSlug}\". The workflow definition was modified after this run was submitted.`,\n };\n\n await this.backend.saveStepFailed(workflowSlug, runId, stepId, error, {\n duration: 0,\n attemptNumber: 1,\n terminal: true,\n failureReason: \"step-removed\",\n });\n\n this.stats.failedSteps++;\n }\n\n /**\n * Set up signal handlers for graceful shutdown\n */\n private setupSignalHandlers(): void {\n const shutdown = async (signal: string) => {\n console.log(`[StepWorker ${this.workerId}] Received ${signal}, shutting down gracefully...`);\n await this.stop();\n process.exit(0);\n };\n\n process.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\n process.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n }\n\n private heartbeatTimer?: Timer;\n}\n",
5
+ "import { FileSystemBackend } from \"@cascade-flow/backend-filesystem\";\nimport type { Backend } from \"@cascade-flow/backend-interface\";\nimport { getMicrosecondTimestamp, MICROSECONDS_PER_MILLISECOND, convertZodToJSONSchema, projectStepState, serializeError } from \"@cascade-flow/backend-interface\";\nimport { hostname } from \"node:os\";\nimport { join } from \"node:path\";\nimport { discoverSteps, discoverWorkflows, executeStepInProcess, calculateWorkflowHash, getGitInfo, type LoadedStep, type CheckpointData, type CheckpointFailedData } from \"@cascade-flow/runner\";\nimport { Skip } from \"@cascade-flow/workflow\";\nimport {\n getCurrentPolicy,\n computeDelay,\n resolveRetryPolicies,\n getTotalAttempts,\n isRetryableError,\n isNonRetryableError,\n} from \"./retry\";\nimport type { ZodSchema } from \"zod\";\nimport { checkDependenciesSatisfied, loadDependencyOutputs } from \"./execution/dependency-resolver.ts\";\nimport { cascadeSkip, handleStepSkip } from \"./scheduling/skip-handler.ts\";\nimport { scheduleDownstreamSteps, scheduleStep } from \"./scheduling/step-scheduler.ts\";\nimport { createStepKey, extractStepId } from \"./utils/step-key.ts\";\nimport {\n handleWorkflowCompletion,\n handleWorkflowFailure,\n handleWorkflowStart,\n parseWorkflowInput,\n validateWorkflowInput,\n} from \"./scheduling/workflow-lifecycle.ts\";\nimport type { StepWorkerOptions, StepWorkerStats } from \"./types.ts\";\nimport {\n getRunSubmittedEvent,\n getWorkflowInputValidationEvent,\n getWorkflowTerminalState,\n hasWorkflowStarted,\n hasWorkflowSubmitted,\n hasWorkflowValidatedInput,\n loadWorkflowEvents\n} from \"./utils/event-helpers.ts\";\n\n/**\n * StepWorker - long-running process for step-level distributed workflow execution\n *\n * Architecture:\n * - Workers claim and execute individual steps (not entire workflows)\n * - Steps are scheduled when their dependencies complete\n * - Multiple workers can collaboratively execute steps from the same workflow\n * - Enables finer-grained parallelization and better resource utilization\n *\n * Features:\n * - Executor loop: Claims and executes scheduled steps\n * - Scheduler loop: Finds ready steps and schedules them\n * - Heartbeat loop: Sends heartbeats for running steps\n * - Reclamation loop: Detects and reclaims stale steps from crashed workers\n * - Retry support: Automatic retries with configurable delay\n * - Timeout enforcement: Abort-controlled cancellation of hung subprocesses\n * - Graceful shutdown: Waits for active steps to complete\n */\nexport class StepWorker {\n private workerId: string;\n private backend: Backend;\n private options: Required<StepWorkerOptions>;\n private running: boolean = false;\n private activeSteps: Map<string, {\n workflowSlug: string;\n runId: string;\n stepId: string;\n attemptNumber: number;\n heartbeatTimer: Timer;\n slotIndex: number;\n }> = new Map();\n private stats: StepWorkerStats;\n private workflowCache: Map<string, { metadata: any; steps: LoadedStep[]; inputSchema?: ZodSchema }> = new Map();\n private freeSlots: Set<number> = new Set();\n\n constructor(backend?: Backend, options: StepWorkerOptions = {}) {\n // Generate worker ID if not provided (using microseconds for consistency)\n this.workerId = options.workerId || `step-worker-${hostname()}-${process.pid}-${getMicrosecondTimestamp()}`;\n\n // Use provided backend or create filesystem backend\n this.backend = backend || new FileSystemBackend(options.baseDir || \"./.runs\");\n\n // Set defaults for all options\n this.options = {\n workerId: this.workerId,\n mode: options.mode ?? \"unified\",\n concurrency: options.concurrency ?? 1,\n pollInterval: options.pollInterval ?? 1000,\n heartbeatInterval: options.heartbeatInterval ?? 5000,\n staleThreshold: options.staleThreshold ?? 30000,\n staleCheckInterval: options.staleCheckInterval ?? 10000,\n schedulerInterval: options.schedulerInterval ?? 5000,\n schedulerRunBatchSize: options.schedulerRunBatchSize ?? 200,\n shutdownTimeout: options.shutdownTimeout ?? 30000,\n workflowsDir: options.workflowsDir || \"./workflows\",\n baseDir: options.baseDir || \"./.runs\",\n };\n\n this.stats = {\n workerId: this.workerId,\n mode: this.options.mode,\n startedAt: getMicrosecondTimestamp(), // Convert to microseconds\n totalStepsProcessed: 0,\n currentlyRunning: 0,\n failedSteps: 0,\n reclaimedSteps: 0,\n };\n\n // Initialize free slots (0 to concurrency-1)\n for (let i = 0; i < this.options.concurrency; i++) {\n this.freeSlots.add(i);\n }\n }\n\n /**\n * Get current worker statistics\n */\n getStats(): StepWorkerStats {\n return { ...this.stats };\n }\n\n /**\n * Start the worker (blocking operation)\n *\n * Starts appropriate loops based on worker mode:\n * - unified: All 4 loops (executor, scheduler, heartbeat, reclamation)\n * - executor: Only executor + heartbeat loops\n * - scheduler: Only scheduler + reclamation loops\n */\n async start(): Promise<void> {\n if (this.running) {\n throw new Error(\"Worker is already running\");\n }\n\n this.running = true;\n console.log(`[StepWorker ${this.workerId}] Starting in ${this.options.mode} mode...`);\n\n // Set up signal handlers for graceful shutdown\n this.setupSignalHandlers();\n\n // Load workflow metadata and cache it\n console.log(`[StepWorker ${this.workerId}] Loading workflows from ${this.options.workflowsDir}...`);\n await this.loadWorkflows();\n\n // Register workflows with backend\n console.log(`[StepWorker ${this.workerId}] Registering workflows with backend...`);\n await this.registerWorkflows();\n\n // Start appropriate loops based on mode\n const loops: Promise<void>[] = [];\n\n if (this.options.mode === \"unified\" || this.options.mode === \"executor\") {\n // Executor loop: Claims and executes scheduled steps\n loops.push(this.executorLoop());\n console.log(`[StepWorker ${this.workerId}] Executor loop started (concurrency: ${this.options.concurrency})`);\n }\n\n if (this.options.mode === \"unified\" || this.options.mode === \"scheduler\") {\n // Scheduler loop: Finds ready steps and schedules them\n loops.push(this.schedulerLoop());\n console.log(`[StepWorker ${this.workerId}] Scheduler loop started (interval: ${this.options.schedulerInterval}ms)`);\n\n // Reclamation loop: Detects and reclaims stale steps\n loops.push(this.reclamationLoop());\n console.log(`[StepWorker ${this.workerId}] Reclamation loop started (threshold: ${this.options.staleThreshold}ms)`);\n }\n\n console.log(`[StepWorker ${this.workerId}] Started successfully`);\n\n // Wait for all loops to complete (on shutdown)\n try {\n await Promise.all(loops);\n } finally {\n clearInterval(this.heartbeatTimer as any);\n console.log(`[StepWorker ${this.workerId}] Stopped`);\n }\n }\n\n /**\n * Gracefully stop the worker\n * Waits for active steps to complete before shutting down\n */\n async stop(): Promise<void> {\n if (!this.running) {\n return;\n }\n\n console.log(`[StepWorker ${this.workerId}] Stopping... (${this.activeSteps.size} active steps)`);\n this.running = false;\n\n // Wait for active steps to complete (with timeout)\n const shutdownStart = Date.now();\n while (this.activeSteps.size > 0 && Date.now() - shutdownStart < this.options.shutdownTimeout) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n if (this.activeSteps.size > 0) {\n console.warn(`[StepWorker ${this.workerId}] Forced shutdown with ${this.activeSteps.size} active steps`);\n }\n\n console.log(`[StepWorker ${this.workerId}] Stopped`);\n }\n\n /**\n * Load and cache workflow metadata and steps\n */\n private async loadWorkflows(): Promise<void> {\n try {\n const workflows = await discoverWorkflows(this.options.workflowsDir);\n\n for (const workflow of workflows) {\n const steps = await discoverSteps(workflow.stepsDir);\n this.workflowCache.set(workflow.slug, {\n metadata: workflow,\n steps,\n inputSchema: workflow.inputSchema, // Cache Zod schema for validation\n });\n }\n\n console.log(`[StepWorker ${this.workerId}] Loaded ${workflows.length} workflows`);\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Failed to load workflows:`, error);\n throw error;\n }\n }\n\n /**\n * Register workflows with backend\n * Converts Zod schemas to JSON Schema and stores workflow metadata\n */\n private async registerWorkflows(): Promise<void> {\n try {\n for (const [slug, { metadata, steps, inputSchema }] of this.workflowCache) {\n // Convert Zod schema to JSON Schema if present\n let inputSchemaJSON = undefined;\n if (inputSchema) {\n try {\n inputSchemaJSON = convertZodToJSONSchema(inputSchema);\n } catch (error) {\n console.warn(\n `[StepWorker ${this.workerId}] Failed to convert schema for workflow ${slug}: ${error}`\n );\n }\n }\n\n // Build step definitions array\n const stepDefinitions = steps.map((step) => ({\n id: step.id, // Unique identifier (directory name)\n name: step.name, // Display name\n dependencies: Object.values(step.dependencies).map(dep => dep.id), // Use IDs for references\n exportOutput: step.exportOutput ?? false,\n }));\n\n // Register with backend\n await this.backend.registerWorkflow({\n slug,\n name: metadata.name,\n location: metadata.dir, // Filesystem directory path\n inputSchemaJSON,\n steps: stepDefinitions,\n });\n\n // Create workflow version\n const versionId = await calculateWorkflowHash(metadata);\n const git = await getGitInfo(metadata.dir);\n const stepManifest = steps.map((s) => s.id);\n\n await this.backend.createWorkflowVersion({\n workflowSlug: slug,\n versionId,\n createdAt: getMicrosecondTimestamp(),\n stepManifest,\n totalSteps: steps.length,\n git,\n });\n }\n\n console.log(`[StepWorker ${this.workerId}] Registered ${this.workflowCache.size} workflows`);\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Failed to register workflows:`, error);\n throw error;\n }\n }\n\n /**\n * Executor loop: Claims and executes scheduled steps\n */\n private async executorLoop(): Promise<void> {\n while (this.running) {\n try {\n // Check if we have capacity to execute more steps\n if (this.activeSteps.size >= this.options.concurrency) {\n await new Promise((resolve) => setTimeout(resolve, this.options.pollInterval));\n continue;\n }\n\n // List scheduled steps available for claiming\n const limit = this.options.concurrency - this.activeSteps.size;\n const scheduledSteps = await this.backend.listScheduledSteps({ limit });\n\n if (scheduledSteps.length === 0) {\n // No steps available, wait before polling again\n await new Promise((resolve) => setTimeout(resolve, this.options.pollInterval));\n continue;\n }\n\n // Try to claim and execute each step (up to concurrency limit)\n for (const { workflowSlug, runId, stepId } of scheduledSteps) {\n if (this.activeSteps.size >= this.options.concurrency) {\n break;\n }\n\n // Check if step still exists in current workflow definition\n const workflowData = this.workflowCache.get(workflowSlug);\n const stepExists = workflowData?.steps.some((s) => s.id === stepId);\n if (!stepExists) {\n await this.handleOrphanStep(workflowSlug, runId, stepId);\n continue;\n }\n\n // Execute step (non-blocking - fires and forgets)\n this.executeStep(workflowSlug, runId, stepId).catch((err) => {\n console.error(`[StepWorker ${this.workerId}] Error executing ${createStepKey(workflowSlug, runId, stepId)}:`, err);\n });\n }\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Error in executor loop:`, error);\n await new Promise((resolve) => setTimeout(resolve, this.options.pollInterval));\n }\n }\n }\n\n /**\n * Scheduler loop: Finds ready steps and schedules them\n */\n private async schedulerLoop(): Promise<void> {\n while (this.running) {\n try {\n // List active workflows (workflows with incomplete runs)\n const activeWorkflows = await this.backend.listActiveWorkflows();\n\n for (const workflowSlug of activeWorkflows) {\n // Get workflow from cache\n const workflowData = this.workflowCache.get(workflowSlug);\n if (!workflowData) {\n console.warn(`[StepWorker ${this.workerId}] Workflow ${workflowSlug} not in cache, skipping`);\n continue;\n }\n\n let activeRuns: Array<{ runId: string }> = [];\n try {\n const result = await this.backend.listRuns({\n workflowSlug,\n status: [\"pending\", \"running\"],\n });\n activeRuns = result.runs;\n } catch {\n // Failed to list runs for this workflow\n continue;\n }\n\n for (const run of activeRuns) {\n const runId = run.runId;\n try {\n // Load workflow events to check run state\n const workflowEvents = await loadWorkflowEvents(this.backend, workflowSlug, runId);\n if (workflowEvents.length === 0) continue;\n\n // Check if workflow is already in a terminal state\n const { hasCompleted, hasFailed, hasCancelled } = getWorkflowTerminalState(workflowEvents);\n\n if (hasCompleted || hasFailed || hasCancelled) {\n continue; // Skip terminal workflows\n }\n\n // Check if workflow has been submitted but not started yet\n const hasSubmitted = hasWorkflowSubmitted(workflowEvents);\n const hasStarted = hasWorkflowStarted(workflowEvents);\n\n if (!hasSubmitted) {\n continue; // Skip workflows without RunSubmitted (shouldn't happen)\n }\n\n // If submitted but not started, emit WorkflowStarted event\n if (!hasStarted) {\n const runSubmittedEvent = getRunSubmittedEvent(workflowEvents);\n if (!runSubmittedEvent) {\n throw new Error(`No RunSubmitted event found for ${workflowSlug}/${runId}`);\n }\n\n await handleWorkflowStart(this.backend, workflowSlug, runId, {\n versionId: runSubmittedEvent.versionId,\n hasInputSchema: workflowData.inputSchema !== undefined,\n hasInput: !!(runSubmittedEvent && runSubmittedEvent.input !== undefined),\n }, workflowEvents);\n\n console.log(`[StepWorker ${this.workerId}] Started workflow ${workflowSlug}/${runId}`);\n }\n\n // Validate input (if not already validated)\n const hasValidatedInput = hasWorkflowValidatedInput(workflowEvents);\n\n if (!hasValidatedInput) {\n const workflowInput = parseWorkflowInput(workflowEvents);\n const validationResult = await validateWorkflowInput(\n this.backend,\n workflowSlug,\n runId,\n workflowInput,\n workflowData.inputSchema,\n workflowEvents\n );\n\n if (!validationResult.success) {\n console.log(\n `[StepWorker ${this.workerId}] Workflow ${workflowSlug}/${runId} failed (input validation)`\n );\n continue; // Skip to next run, don't schedule any steps\n }\n }\n\n // Track completion state\n let allStepsCompleted = true;\n let anyStepFailed = false;\n let failedStepName: string | undefined;\n\n // Get run priority for step scheduling\n const runSubmittedEventForPriority = getRunSubmittedEvent(workflowEvents);\n const runPriority = runSubmittedEventForPriority?.priority;\n\n // Load step events for state projection in a single batch query (avoids N+1)\n const allStepEvents = await this.backend.loadStepEventsForProjection(workflowSlug, runId);\n\n // For each step in the workflow, check if it should be scheduled\n for (const step of workflowData.steps) {\n // Get step events from batch-loaded map\n const stepEvents = allStepEvents.get(step.id) || [];\n\n // If step has no events yet, it's pending\n if (stepEvents.length === 0) {\n allStepsCompleted = false;\n\n // Check if dependencies are satisfied\n const canSchedule = await checkDependenciesSatisfied(\n step,\n this.backend,\n workflowSlug,\n runId,\n allStepEvents\n );\n\n // If no dependencies (initial step) or all deps completed, schedule it\n if (canSchedule) {\n await scheduleStep(\n this.backend,\n workflowSlug,\n runId,\n step.id,\n Object.keys(step.dependencies).length === 0 ? \"initial\" : \"dependency-satisfied\",\n 1,\n { priority: runPriority }\n );\n\n console.log(`[StepWorker ${this.workerId}] Scheduled ${step.name} in ${workflowSlug}/${runId}`);\n }\n } else {\n // Step has events, check its state\n const state = projectStepState(stepEvents, workflowSlug);\n\n if (state.status === \"pending\") {\n allStepsCompleted = false;\n\n // Check if dependencies are satisfied\n const canSchedule = await checkDependenciesSatisfied(\n step,\n this.backend,\n workflowSlug,\n runId,\n allStepEvents\n );\n\n if (canSchedule) {\n await scheduleStep(\n this.backend,\n workflowSlug,\n runId,\n step.id,\n \"dependency-satisfied\",\n 1,\n { priority: runPriority }\n );\n\n console.log(\n `[StepWorker ${this.workerId}] Scheduled pending step ${step.name} in ${workflowSlug}/${runId}`\n );\n }\n } else if (state.status === \"failed\" && state.terminal) {\n anyStepFailed = true;\n failedStepName = step.name;\n allStepsCompleted = false;\n } else if (state.status !== \"completed\" && state.status !== \"skipped\") {\n allStepsCompleted = false;\n }\n }\n }\n\n // Check for workflow completion\n if (allStepsCompleted) {\n await handleWorkflowCompletion(\n this.backend,\n workflowSlug,\n runId,\n workflowData.steps,\n workflowEvents\n );\n\n console.log(`[StepWorker ${this.workerId}] Workflow ${workflowSlug}/${runId} completed`);\n } else if (anyStepFailed) {\n await handleWorkflowFailure(\n this.backend,\n workflowSlug,\n runId,\n workflowData.steps,\n workflowEvents,\n failedStepName\n );\n\n console.log(\n `[StepWorker ${this.workerId}] Workflow ${workflowSlug}/${runId} failed (step: ${failedStepName})`\n );\n }\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Error processing run ${runId}:`, error);\n }\n }\n }\n\n await new Promise((resolve) => setTimeout(resolve, this.options.schedulerInterval));\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Error in scheduler loop:`, error);\n await new Promise((resolve) => setTimeout(resolve, this.options.schedulerInterval));\n }\n }\n }\n\n /**\n * Reclamation loop: Detects and reclaims stale steps from crashed workers\n */\n private async reclamationLoop(): Promise<void> {\n while (this.running) {\n try {\n const reclaimed = await this.backend.reclaimStaleSteps(\n this.options.staleThreshold * 1000, // Convert to microseconds\n this.workerId\n );\n\n if (reclaimed.length > 0) {\n console.log(`[StepWorker ${this.workerId}] Reclaimed ${reclaimed.length} stale steps`);\n this.stats.reclaimedSteps += reclaimed.length;\n }\n\n await new Promise((resolve) => setTimeout(resolve, this.options.staleCheckInterval));\n } catch (error) {\n console.error(`[StepWorker ${this.workerId}] Error in reclamation loop:`, error);\n await new Promise((resolve) => setTimeout(resolve, this.options.staleCheckInterval));\n }\n }\n }\n\n /**\n * Load existing checkpoints for a step from events\n *\n * Returns a Map from checkpoint name to array of data (by sequence number)\n */\n private async loadCheckpointsFromEvents(\n workflowSlug: string,\n runId: string,\n stepId: string\n ): Promise<Map<string, string[]>> {\n const events = await this.backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId,\n });\n\n const checkpoints = new Map<string, string[]>();\n for (const event of events) {\n if (event.type === \"StepCheckpoint\") {\n if (!checkpoints.has(event.name)) {\n checkpoints.set(event.name, []);\n }\n const arr = checkpoints.get(event.name)!;\n // Ensure array is large enough for sequence number\n while (arr.length <= event.sequenceNumber) {\n arr.push(\"\");\n }\n arr[event.sequenceNumber] = event.data;\n }\n }\n return checkpoints;\n }\n\n /**\n * Execute a single step\n */\n private async executeStep(workflowSlug: string, runId: string, stepId: string): Promise<void> {\n const stepKey = createStepKey(workflowSlug, runId, stepId);\n let startTime = getMicrosecondTimestamp(); // Microseconds - declare at function scope\n let attemptNumber: number | null = null;\n let heartbeatTimer: Timer | null = null;\n let slotIndex: number | null = null;\n\n try {\n // Get workflow and step metadata\n const workflowData = this.workflowCache.get(workflowSlug);\n if (!workflowData) {\n throw new Error(`Workflow ${workflowSlug} not found in cache`);\n }\n\n const step = workflowData.steps.find((s) => s.id === stepId);\n if (!step) {\n throw new Error(`Step ${stepId} not found in workflow ${workflowSlug}`);\n }\n\n // Acquire a slot for this step\n const slotIterator = this.freeSlots.values().next();\n if (slotIterator.done) {\n throw new Error(`No free slots available`);\n }\n slotIndex = slotIterator.value;\n this.freeSlots.delete(slotIndex);\n\n // Atomically claim the step (using stepId)\n // Note: attemptNumber in metadata is a placeholder - backend will determine actual attempt number from step state\n const claimResult = await this.backend.claimScheduledStep(workflowSlug, runId, stepId, this.workerId, {\n dependencies: Object.keys(step.dependencies),\n timestamp: startTime,\n attemptNumber: 1, // Placeholder - backend determines actual attempt from step events\n slotIndex,\n workerConcurrency: this.options.concurrency,\n });\n\n if (!claimResult) {\n console.log(`[StepWorker ${this.workerId}] Skipped ${stepKey} (already claimed)`);\n // Release slot on failed claim\n this.freeSlots.add(slotIndex);\n return;\n }\n\n attemptNumber = claimResult.attemptNumber;\n startTime = getMicrosecondTimestamp(); // Update startTime closer to actual execution\n\n // Track active step and start heartbeat (using stepId)\n const capturedSlotIndex = slotIndex;\n heartbeatTimer = setInterval(() => {\n if (attemptNumber === null) return;\n this.backend.saveStepHeartbeat(workflowSlug, runId, stepId, this.workerId, attemptNumber, {\n slotIndex: capturedSlotIndex,\n workerConcurrency: this.options.concurrency,\n }).catch((err) => {\n console.error(`[StepWorker ${this.workerId}] Error sending heartbeat for ${stepKey}:`, err);\n });\n }, this.options.heartbeatInterval);\n\n const trackedTimer = heartbeatTimer!;\n\n this.activeSteps.set(stepKey, {\n workflowSlug,\n runId,\n stepId,\n attemptNumber,\n heartbeatTimer: trackedTimer,\n slotIndex: capturedSlotIndex,\n });\n\n this.stats.currentlyRunning++;\n\n console.log(`[StepWorker ${this.workerId}] Executing ${step.name} (attempt ${attemptNumber})`);\n\n // Load dependency outputs\n const dependencyOutputs = await loadDependencyOutputs(step, this.backend, workflowSlug, runId);\n\n // Load workflow input from RunSubmitted event (pre-validated by scheduler)\n const workflowEvents = await loadWorkflowEvents(this.backend, workflowSlug, runId);\n const runSubmittedEvent = getRunSubmittedEvent(workflowEvents);\n let workflowInput: unknown = undefined;\n\n if (runSubmittedEvent && runSubmittedEvent.input !== undefined) {\n // Parse input from event\n workflowInput = JSON.parse(runSubmittedEvent.input);\n }\n\n // If workflow has schema and validation succeeded, apply defaults (even when no input provided)\n if (workflowData.inputSchema) {\n const validationEvent = getWorkflowInputValidationEvent(workflowEvents);\n if (validationEvent && validationEvent.success) {\n // Re-parse with schema to get defaults (validation already confirmed this will succeed)\n // Use {} as fallback when no input provided to trigger Zod's default values\n const parseResult = workflowData.inputSchema.safeParse(workflowInput ?? {});\n if (parseResult.success) {\n workflowInput = parseResult.data;\n }\n }\n }\n\n // Build context (use step.name for display name in logs)\n const ctx = {\n runId,\n workflow: {\n slug: workflowSlug,\n name: workflowData.metadata.name,\n },\n input: workflowInput,\n log: (...args: any[]) => {\n console.log(`[${step.name}]`, ...args);\n },\n };\n\n // Execute step in subprocess with timeout\n // Priority: step timeout (most specific) → submission timeout → default 5 minutes\n const stepFile = join(step.dir, \"step.ts\");\n const submissionTimeoutMs = runSubmittedEvent && runSubmittedEvent.timeoutUs\n ? Math.floor(runSubmittedEvent.timeoutUs / 1000)\n : undefined;\n const timeout = step.timeoutMs ?? submissionTimeoutMs ?? 300000;\n\n // Load existing checkpoints for replay (from any previous attempts)\n const existingCheckpoints = await this.loadCheckpointsFromEvents(\n workflowSlug,\n runId,\n stepId\n );\n\n const abortController = new AbortController();\n const executionPromise = executeStepInProcess(\n stepFile,\n step.id, // Pass step ID for stable file paths\n dependencyOutputs,\n ctx,\n attemptNumber!,\n this.backend,\n // Real-time log emission callback\n async (log) => {\n // Create LogEntry event - use log.timestamp to preserve exact ordering\n const logEvent: Omit<import(\"@cascade-flow/backend-interface\").LogEntryEvent, \"eventId\"> = {\n workflowSlug,\n runId,\n category: \"step\",\n type: \"LogEntry\",\n stepId,\n stream: log.stream,\n message: log.message,\n attemptNumber: attemptNumber!,\n timestampUs: log.timestamp, // Use the timestamp captured by subprocess executor\n };\n await this.backend.appendEvent(workflowSlug, runId, logEvent as any);\n },\n // Checkpoint persistence callback\n async (checkpoint: CheckpointData) => {\n // Extract metadata from data and strip from payload\n let parentCheckpoint:\n | { name: string; sequenceNumber: number }\n | undefined;\n let label: string | undefined;\n let cleanedData = checkpoint.data;\n try {\n const parsed = JSON.parse(checkpoint.data);\n if (parsed?._parentCheckpoint) {\n parentCheckpoint = parsed._parentCheckpoint;\n delete parsed._parentCheckpoint;\n }\n if (parsed?._label) {\n label = parsed._label;\n delete parsed._label;\n }\n // Re-serialize without metadata fields\n cleanedData = JSON.stringify(parsed);\n } catch {\n // Ignore parse errors - use original data\n }\n\n await this.backend.saveStepCheckpoint(workflowSlug, runId, stepId, {\n name: checkpoint.name,\n sequenceNumber: checkpoint.sequenceNumber,\n attemptNumber: attemptNumber!,\n data: cleanedData,\n label,\n parentCheckpoint,\n });\n },\n // Checkpoint failure callback\n async (failure: CheckpointFailedData) => {\n await this.backend.saveStepCheckpointFailed(workflowSlug, runId, stepId, {\n name: failure.name,\n sequenceNumber: failure.sequenceNumber,\n attemptNumber: attemptNumber!,\n error: JSON.parse(failure.error),\n });\n },\n existingCheckpoints,\n {\n signal: abortController.signal,\n }\n );\n\n const timeoutTimer = setTimeout(() => {\n abortController.abort(new Error(`Step timeout after ${timeout}ms`));\n }, timeout);\n\n const { result: output } = await executionPromise.finally(() => {\n clearTimeout(timeoutTimer);\n });\n\n const endTime = getMicrosecondTimestamp(); // Microseconds\n const duration = endTime - startTime;\n\n // Logs are already emitted in real-time via the onLog callback\n // No need to emit them again here\n\n // Emit StepCompleted event (using stepId)\n await this.backend.saveStepComplete(\n workflowSlug,\n runId,\n stepId,\n output,\n {\n timestamp: endTime,\n duration,\n attemptNumber: attemptNumber!,\n output,\n },\n step.exportOutput ?? false\n );\n\n console.log(`[StepWorker ${this.workerId}] Completed ${step.name}`);\n\n // Cleanup\n if (heartbeatTimer) {\n clearInterval(heartbeatTimer);\n heartbeatTimer = null;\n }\n const completedStep = this.activeSteps.get(stepKey);\n if (completedStep) {\n this.freeSlots.add(completedStep.slotIndex);\n }\n this.activeSteps.delete(stepKey);\n this.stats.currentlyRunning--;\n this.stats.totalStepsProcessed++;\n\n // If in unified mode, schedule downstream steps (using stepId)\n if (this.options.mode === \"unified\") {\n const workflowData = this.workflowCache.get(workflowSlug);\n if (workflowData) {\n const scheduled = await scheduleDownstreamSteps(\n this.backend,\n workflowSlug,\n runId,\n stepId,\n workflowData.steps,\n { priority: runSubmittedEvent?.priority }\n );\n if (scheduled.length > 0) {\n console.log(\n `[StepWorker ${this.workerId}] Scheduled downstream steps: ${scheduled.join(\", \")}`\n );\n }\n }\n }\n } catch (error) {\n const failureContext = attemptNumber === null ? \"Failed to claim\" : \"Failed\";\n console.error(`[StepWorker ${this.workerId}] ${failureContext} ${stepKey}:`, error);\n\n const activeStep = this.activeSteps.get(stepKey);\n if (activeStep) {\n clearInterval(activeStep.heartbeatTimer);\n this.freeSlots.add(activeStep.slotIndex);\n this.activeSteps.delete(stepKey);\n this.stats.currentlyRunning--;\n } else if (heartbeatTimer) {\n clearInterval(heartbeatTimer);\n heartbeatTimer = null;\n // Release slot if it was acquired but claim failed after slot allocation\n if (slotIndex !== null) {\n this.freeSlots.add(slotIndex);\n }\n }\n\n if (attemptNumber === null) {\n return;\n }\n\n this.stats.failedSteps++;\n\n // Get workflow and step metadata for retry logic\n const workflowData = this.workflowCache.get(workflowSlug);\n if (!workflowData) {\n console.error(`[StepWorker ${this.workerId}] Workflow ${workflowSlug} not found in cache`);\n return;\n }\n\n // Extract stepId from stepKey (handles nested steps with slashes)\n const stepId = extractStepId(stepKey);\n if (!stepId) {\n console.error(`[StepWorker ${this.workerId}] Invalid stepKey format: ${stepKey}`);\n return;\n }\n const step = workflowData.steps.find((s) => s.id === stepId);\n if (!step) {\n console.error(`[StepWorker ${this.workerId}] Step ${stepId} not found in workflow ${workflowSlug}`);\n return;\n }\n\n // Load step events to get current attempt number (using stepId)\n const events = await this.backend.loadEvents(workflowSlug, runId, { category: \"step\", stepId });\n const state = projectStepState(events, workflowSlug);\n const currentAttemptNumber = state.attemptNumber;\n\n const endTime = getMicrosecondTimestamp(); // Microseconds\n const duration = endTime - (state.startTime || startTime);\n\n // Prepare error object using centralized error serialization\n const stepError = serializeError(error);\n\n // SKIP DETECTION: Check if error is a Skip (don't retry, just mark as skipped)\n if (error instanceof Error && (error.name === \"Skip\" || error instanceof Skip)) {\n const skipError = error as Skip;\n\n await handleStepSkip(this.backend, workflowSlug, runId, stepId, skipError, duration, currentAttemptNumber);\n\n console.log(`[StepWorker ${this.workerId}] Skipped ${step.name}: ${skipError.reason || skipError.message}`);\n\n // If in unified mode, check for cascade skips\n if (this.options.mode === \"unified\") {\n const workflowData = this.workflowCache.get(workflowSlug);\n if (workflowData) {\n await cascadeSkip(this.backend, workflowSlug, runId, stepId, workflowData.steps, this.workerId);\n }\n }\n\n return; // Don't retry, don't mark as failed\n }\n\n // Check for NonRetryableError - immediate terminal failure\n if (isNonRetryableError(error)) {\n await this.backend.saveStepFailed(workflowSlug, runId, stepId, stepError, {\n duration,\n attemptNumber: currentAttemptNumber,\n terminal: true,\n failureReason: \"execution-error\",\n });\n\n console.log(`[StepWorker ${this.workerId}] Terminal failure for ${step.name} (non-retryable error)`);\n return;\n }\n\n // Resolve retry policies (new format or legacy conversion)\n const policies = resolveRetryPolicies(step);\n\n // No retry policies configured - terminal failure\n if (!policies || policies.length === 0) {\n await this.backend.saveStepFailed(workflowSlug, runId, stepId, stepError, {\n duration,\n attemptNumber: currentAttemptNumber,\n terminal: true,\n failureReason: \"execution-error\",\n });\n\n console.log(`[StepWorker ${this.workerId}] Terminal failure for ${step.name} (no retry policy)`);\n return;\n }\n\n // Check if we should retry based on current attempt\n const nextAttemptNumber = currentAttemptNumber + 1;\n const policyResult = getCurrentPolicy(nextAttemptNumber, policies);\n\n if (policyResult.exhausted) {\n // Terminal failure - all retry policies exhausted\n await this.backend.saveStepFailed(workflowSlug, runId, stepId, stepError, {\n duration,\n attemptNumber: currentAttemptNumber,\n terminal: true,\n failureReason: \"exhausted-retries\",\n });\n\n const totalAttempts = getTotalAttempts(policies);\n console.log(`[StepWorker ${this.workerId}] Terminal failure for ${step.name} (exhausted ${totalAttempts} attempts across ${policies.length} policies)`);\n } else {\n // Not terminal - schedule retry\n // Check if RetryableError provides a custom delay override\n let retryDelayMs = computeDelay(policyResult.policy.backoff, policyResult.attemptInPolicy);\n if (isRetryableError(error) && error.delayMs !== undefined) {\n retryDelayMs = error.delayMs;\n }\n\n const nextRetryAt = getMicrosecondTimestamp() + retryDelayMs * MICROSECONDS_PER_MILLISECOND;\n\n // Get run priority for retry scheduling\n const retryWorkflowEvents = await loadWorkflowEvents(this.backend, workflowSlug, runId);\n const retryRunSubmittedEvent = getRunSubmittedEvent(retryWorkflowEvents);\n\n // Use atomic method to ensure both failure and schedule events are written together\n await this.backend.saveStepFailedAndScheduleRetry(\n workflowSlug,\n runId,\n stepId,\n stepError,\n {\n duration,\n attemptNumber: currentAttemptNumber,\n nextRetryAt,\n failureReason: \"execution-error\",\n policyIndex: policyResult.policyIndex,\n attemptInPolicy: policyResult.attemptInPolicy,\n },\n {\n availableAt: nextRetryAt,\n nextAttemptNumber,\n retryDelayMs,\n totalPolicies: policies.length,\n policyIndex: policyResult.policyIndex,\n attemptInPolicy: policyResult.attemptInPolicy,\n priority: retryRunSubmittedEvent?.priority,\n }\n );\n\n const totalAttempts = getTotalAttempts(policies);\n console.log(\n `[StepWorker ${this.workerId}] Scheduled retry for ${step.name} (attempt ${nextAttemptNumber}/${totalAttempts}, policy ${policyResult.policyIndex + 1}/${policies.length}, delay ${retryDelayMs}ms)`\n );\n }\n }\n }\n\n /**\n * Handle an orphan step that no longer exists in the workflow definition\n * Writes a terminal StepFailed event to prevent infinite retry loops\n */\n private async handleOrphanStep(\n workflowSlug: string,\n runId: string,\n stepId: string\n ): Promise<void> {\n const stepKey = createStepKey(workflowSlug, runId, stepId);\n console.warn(\n `[StepWorker ${this.workerId}] Orphan step detected: ${stepKey} (step removed from workflow)`\n );\n\n const error = {\n name: \"StepRemovedError\",\n message: `Step \"${stepId}\" no longer exists in workflow \"${workflowSlug}\". The workflow definition was modified after this run was submitted.`,\n };\n\n await this.backend.saveStepFailed(workflowSlug, runId, stepId, error, {\n duration: 0,\n attemptNumber: 1,\n terminal: true,\n failureReason: \"step-removed\",\n });\n\n this.stats.failedSteps++;\n }\n\n /**\n * Set up signal handlers for graceful shutdown\n */\n private setupSignalHandlers(): void {\n const shutdown = async (signal: string) => {\n console.log(`[StepWorker ${this.workerId}] Received ${signal}, shutting down gracefully...`);\n await this.stop();\n process.exit(0);\n };\n\n process.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\n process.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n }\n\n private heartbeatTimer?: Timer;\n}\n",
6
6
  "/**\n * Retry policy resolution and delay computation\n *\n * This module provides stateless functions for computing retry behavior\n * from attempt numbers and policy configurations.\n */\n\nimport type { RetryPolicy, BackoffConfig } from \"@cascade-flow/workflow\";\n\n/**\n * Result of policy resolution when a policy is found\n */\nexport type PolicyResolutionResult =\n | {\n exhausted: false;\n policy: RetryPolicy;\n policyIndex: number;\n attemptInPolicy: number; // 1-indexed within this policy\n }\n | {\n exhausted: true;\n };\n\n/**\n * Get the current policy for an attempt number\n *\n * @param attemptNumber - 1-indexed attempt number (the attempt we're about to make)\n * @param policies - Array of retry policies\n * @returns Policy resolution result\n *\n * @example\n * ```typescript\n * const policies = [\n * { maxAttempts: 10, backoff: { type: \"exponential\", ... } },\n * { maxAttempts: 10, backoff: { type: \"constant\", delayMs: 3600000 } },\n * ];\n *\n * getCurrentPolicy(1, policies) // → policy 0, attemptInPolicy 1\n * getCurrentPolicy(10, policies) // → policy 0, attemptInPolicy 10\n * getCurrentPolicy(11, policies) // → policy 1, attemptInPolicy 1\n * getCurrentPolicy(21, policies) // → exhausted\n * ```\n */\nexport function getCurrentPolicy(\n attemptNumber: number,\n policies: RetryPolicy[]\n): PolicyResolutionResult {\n if (policies.length === 0) {\n return { exhausted: true };\n }\n\n let accumulated = 0;\n\n for (let i = 0; i < policies.length; i++) {\n const policy = policies[i]!;\n if (attemptNumber <= accumulated + policy.maxAttempts) {\n return {\n exhausted: false,\n policy,\n policyIndex: i,\n attemptInPolicy: attemptNumber - accumulated,\n };\n }\n accumulated += policy.maxAttempts;\n }\n\n return { exhausted: true };\n}\n\n/**\n * Compute the delay for a given policy and attempt within that policy\n *\n * @param backoff - Backoff configuration\n * @param attemptInPolicy - 1-indexed attempt number within the policy\n * @returns Delay in milliseconds\n */\nexport function computeDelay(backoff: BackoffConfig, attemptInPolicy: number): number {\n switch (backoff.type) {\n case \"constant\":\n return backoff.delayMs;\n\n case \"exponential\": {\n const multiplier = backoff.multiplier ?? 2;\n // attemptInPolicy 1 → delay = initialDelayMs * multiplier^0 = initialDelayMs\n // attemptInPolicy 2 → delay = initialDelayMs * multiplier^1\n const delay = backoff.initialDelayMs * Math.pow(multiplier, attemptInPolicy - 1);\n return Math.min(delay, backoff.maxDelayMs);\n }\n\n case \"linear\": {\n // attemptInPolicy 1 → delay = initialDelayMs\n // attemptInPolicy 2 → delay = initialDelayMs + incrementMs\n const delay = backoff.initialDelayMs + (attemptInPolicy - 1) * backoff.incrementMs;\n return Math.min(delay, backoff.maxDelayMs);\n }\n\n default: {\n // Type guard for exhaustive check\n const _exhaustive: never = backoff;\n throw new Error(`Unknown backoff type: ${JSON.stringify(_exhaustive)}`);\n }\n }\n}\n\n/**\n * Convert legacy retry configuration to the new policy format\n *\n * @param maxRetries - Legacy maxRetries value (number of retries, not total attempts)\n * @param retryDelayMs - Legacy retryDelayMs value\n * @returns Array of retry policies, or undefined if no retry config\n *\n * @example\n * ```typescript\n * // maxRetries=3 means 4 total attempts (1 initial + 3 retries)\n * convertLegacyRetryConfig(3, 1000)\n * // → [{ maxAttempts: 4, backoff: { type: \"constant\", delayMs: 1000 } }]\n *\n * convertLegacyRetryConfig(0, 0)\n * // → undefined (no retries)\n * ```\n */\nexport function convertLegacyRetryConfig(\n maxRetries?: number,\n retryDelayMs?: number\n): RetryPolicy[] | undefined {\n // No retry if maxRetries is 0 or undefined\n if (!maxRetries || maxRetries <= 0) {\n return undefined;\n }\n\n // Legacy maxRetries means \"number of retries after initial attempt\"\n // So total attempts = maxRetries + 1\n return [\n {\n maxAttempts: maxRetries + 1,\n backoff: {\n type: \"constant\",\n delayMs: retryDelayMs ?? 0,\n },\n },\n ];\n}\n\n/**\n * Get the total number of attempts across all policies\n */\nexport function getTotalAttempts(policies: RetryPolicy[]): number {\n return policies.reduce((sum, p) => sum + p.maxAttempts, 0);\n}\n\n/**\n * Resolve effective retry policies from step configuration\n * Prefers new `retry` array over legacy `maxRetries`/`retryDelayMs`\n *\n * @param step - Step with retry configuration\n * @returns Resolved retry policies or undefined\n */\nexport function resolveRetryPolicies(step: {\n retry?: RetryPolicy[];\n maxRetries?: number;\n retryDelayMs?: number;\n}): RetryPolicy[] | undefined {\n // New format takes precedence\n if (step.retry && step.retry.length > 0) {\n return step.retry;\n }\n\n // Fall back to legacy format\n return convertLegacyRetryConfig(step.maxRetries, step.retryDelayMs);\n}\n",
7
7
  "/**\n * Retry utilities for the worker package\n */\n\n// Policy resolution and delay computation\nexport {\n getCurrentPolicy,\n computeDelay,\n convertLegacyRetryConfig,\n getTotalAttempts,\n resolveRetryPolicies,\n type PolicyResolutionResult,\n} from \"./policy-resolver\";\n\n// Re-export error classes from workflow package for convenience\nexport {\n RetryableError,\n NonRetryableError,\n isRetryableError,\n isNonRetryableError,\n} from \"@cascade-flow/workflow\";\n",
8
- "import type { Backend } from \"@cascade-flow/backend-interface\";\nimport { projectStepState } from \"@cascade-flow/backend-interface\";\nimport { type LoadedStep } from \"@cascade-flow/runner\";\nimport { isOptional } from \"@cascade-flow/workflow\";\n\n/**\n * Check if all dependencies for a step are satisfied\n * Returns true if the step can be scheduled\n *\n * IMPORTANT: Both required AND optional dependencies must reach a terminal state\n * (completed or skipped) before a step can be scheduled. The distinction between\n * required and optional only affects CASCADE SKIP behavior:\n *\n * - Required dependency skips → dependent step is cascade skipped\n * - Optional dependency skips → dependent step executes with undefined value\n *\n * This means optional dependencies still BLOCK scheduling until they either complete\n * or skip. They only differ in how the dependent step handles the skipped state.\n *\n * @param step - The step to check dependencies for\n * @param backend - Backend interface for loading events\n * @param workflowSlug - Workflow identifier\n * @param runId - Run identifier\n * @returns true if all dependencies are in terminal state and satisfy execution requirements\n */\nexport async function checkDependenciesSatisfied(\n step: LoadedStep,\n backend: Backend,\n workflowSlug: string,\n runId: string\n): Promise<boolean> {\n for (const [depKey, dep] of Object.entries(step.dependencies) as [string, LoadedStep][]) {\n const depEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: dep.id,\n });\n\n // If dependency has no events yet, we must wait regardless of optional status\n // Optional deps only skip blocking when they are in \"skipped\" terminal state\n if (depEvents.length === 0) {\n return false; // Dependency not ready - wait for it to complete or skip\n }\n\n const depState = projectStepState(depEvents as any, workflowSlug);\n const isOptionalDep = isOptional(step.dependencies[depKey]);\n\n // Check if dependency is in a terminal state we can accept\n if (depState.status === \"completed\") {\n continue; // Completed - always OK for both required and optional\n }\n\n if (depState.status === \"skipped\") {\n if (isOptionalDep) {\n continue; // Skipped optional dep - OK\n } else {\n return false; // Skipped required dep - blocks execution\n }\n }\n\n // Dependency is not in a terminal state (pending, scheduled, running, failed non-terminal)\n return false;\n }\n\n return true; // All dependencies satisfied\n}\n\n/**\n * Load outputs from all dependencies\n * Returns a map of dependency alias to output value\n *\n * This function should only be called after checkDependenciesSatisfied returns true,\n * ensuring all dependencies are in terminal state.\n *\n * Behavior by dependency state:\n * - Completed: Returns parsed JSON output\n * - Skipped + Optional: Returns undefined\n * - Skipped + Required: Throws error (should never happen - step should be cascade skipped)\n * - Any other state: Throws error (should never happen - checkDependenciesSatisfied should prevent scheduling)\n *\n * @param step - The step to load dependency outputs for\n * @param backend - Backend interface for loading events\n * @param workflowSlug - Workflow identifier\n * @param runId - Run identifier\n * @returns Map of dependency alias to output value (undefined for skipped optional deps)\n * @throws Error if dependency is not in a valid terminal state\n */\nexport async function loadDependencyOutputs(\n step: LoadedStep,\n backend: Backend,\n workflowSlug: string,\n runId: string\n): Promise<Record<string, any>> {\n const dependencyOutputs: Record<string, any> = {};\n\n for (const [depKey, depStep] of Object.entries(step.dependencies) as [string, LoadedStep][]) {\n const depEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: depStep.id,\n });\n\n if (depEvents.length === 0) {\n // This should never happen if checkDependenciesSatisfied was called first\n // Both required and optional deps must have events (completed or skipped)\n throw new Error(`Dependency ${depStep.name} has no events - step was scheduled prematurely`);\n }\n\n const depState = projectStepState(depEvents as any, workflowSlug);\n const isOptionalDep = isOptional(step.dependencies[depKey]);\n\n // Optional deps can be skipped\n if (depState.status === \"skipped\" && isOptionalDep) {\n dependencyOutputs[depKey] = undefined;\n continue;\n }\n\n // At this point, dependency must be completed (not skipped optional which was handled above)\n // Note: output field is guaranteed to exist for completed steps (StepCompletedEvent requires it)\n if (depState.status !== \"completed\") {\n throw new Error(\n `Dependency '${depStep.name}' is not ready (status: ${depState.status}). ` +\n `This should not happen - checkDependenciesSatisfied should have prevented scheduling.`\n );\n }\n\n if (!depState.output) {\n throw new Error(`Dependency '${depStep.name}' has no output despite being completed`);\n }\n\n // Parse dependency output\n dependencyOutputs[depKey] = JSON.parse(depState.output);\n }\n\n return dependencyOutputs;\n}\n\n/**\n * Find all steps that depend on a given step\n * @param targetStepId - The stepId (unique identifier) to find dependents for\n * @param allSteps - All steps in the workflow\n * @param requiredOnly - If true, only return steps with required dependencies\n */\nexport function findDependentSteps(\n targetStepId: string,\n allSteps: LoadedStep[],\n requiredOnly: boolean = false\n): LoadedStep[] {\n return allSteps.filter((step) => {\n const deps = Object.entries(step.dependencies) as [string, LoadedStep][];\n return deps.some(([alias, dep]) => {\n const dependsOnTarget = dep.id === targetStepId;\n if (!dependsOnTarget) return false;\n\n if (requiredOnly) {\n const isOptionalDep = isOptional(step.dependencies[alias]);\n return !isOptionalDep; // Only include if it's a required dependency\n }\n\n return true; // Include all dependencies\n });\n });\n}\n",
8
+ "import type { Backend, StepEvent } from \"@cascade-flow/backend-interface\";\nimport { projectStepState } from \"@cascade-flow/backend-interface\";\nimport { type LoadedStep } from \"@cascade-flow/runner\";\nimport { isOptional } from \"@cascade-flow/workflow\";\n\n/**\n * Check if all dependencies for a step are satisfied\n * Returns true if the step can be scheduled\n *\n * IMPORTANT: Both required AND optional dependencies must reach a terminal state\n * (completed or skipped) before a step can be scheduled. The distinction between\n * required and optional only affects CASCADE SKIP behavior:\n *\n * - Required dependency skips → dependent step is cascade skipped\n * - Optional dependency skips → dependent step executes with undefined value\n *\n * This means optional dependencies still BLOCK scheduling until they either complete\n * or skip. They only differ in how the dependent step handles the skipped state.\n *\n * @param step - The step to check dependencies for\n * @param backend - Backend interface for loading events\n * @param workflowSlug - Workflow identifier\n * @param runId - Run identifier\n * @returns true if all dependencies are in terminal state and satisfy execution requirements\n */\nexport async function checkDependenciesSatisfied(\n step: LoadedStep,\n backend: Backend,\n workflowSlug: string,\n runId: string,\n stepEventsByStepId?: Map<string, StepEvent[]>\n): Promise<boolean> {\n for (const [depKey, dep] of Object.entries(step.dependencies) as [string, LoadedStep][]) {\n const depEvents = stepEventsByStepId?.get(dep.id) ??\n await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: dep.id,\n });\n\n // If dependency has no events yet, we must wait regardless of optional status\n // Optional deps only skip blocking when they are in \"skipped\" terminal state\n if (depEvents.length === 0) {\n return false; // Dependency not ready - wait for it to complete or skip\n }\n\n const depState = projectStepState(depEvents as any, workflowSlug);\n const isOptionalDep = isOptional(step.dependencies[depKey]);\n\n // Check if dependency is in a terminal state we can accept\n if (depState.status === \"completed\") {\n continue; // Completed - always OK for both required and optional\n }\n\n if (depState.status === \"skipped\") {\n if (isOptionalDep) {\n continue; // Skipped optional dep - OK\n } else {\n return false; // Skipped required dep - blocks execution\n }\n }\n\n // Dependency is not in a terminal state (pending, scheduled, running, failed non-terminal)\n return false;\n }\n\n return true; // All dependencies satisfied\n}\n\n/**\n * Load outputs from all dependencies\n * Returns a map of dependency alias to output value\n *\n * This function should only be called after checkDependenciesSatisfied returns true,\n * ensuring all dependencies are in terminal state.\n *\n * Behavior by dependency state:\n * - Completed: Returns parsed JSON output\n * - Skipped + Optional: Returns undefined\n * - Skipped + Required: Throws error (should never happen - step should be cascade skipped)\n * - Any other state: Throws error (should never happen - checkDependenciesSatisfied should prevent scheduling)\n *\n * @param step - The step to load dependency outputs for\n * @param backend - Backend interface for loading events\n * @param workflowSlug - Workflow identifier\n * @param runId - Run identifier\n * @returns Map of dependency alias to output value (undefined for skipped optional deps)\n * @throws Error if dependency is not in a valid terminal state\n */\nexport async function loadDependencyOutputs(\n step: LoadedStep,\n backend: Backend,\n workflowSlug: string,\n runId: string\n): Promise<Record<string, any>> {\n const dependencyOutputs: Record<string, any> = {};\n\n for (const [depKey, depStep] of Object.entries(step.dependencies) as [string, LoadedStep][]) {\n const depEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: depStep.id,\n });\n\n if (depEvents.length === 0) {\n // This should never happen if checkDependenciesSatisfied was called first\n // Both required and optional deps must have events (completed or skipped)\n throw new Error(`Dependency ${depStep.name} has no events - step was scheduled prematurely`);\n }\n\n const depState = projectStepState(depEvents as any, workflowSlug);\n const isOptionalDep = isOptional(step.dependencies[depKey]);\n\n // Optional deps can be skipped\n if (depState.status === \"skipped\" && isOptionalDep) {\n dependencyOutputs[depKey] = undefined;\n continue;\n }\n\n // At this point, dependency must be completed (not skipped optional which was handled above)\n // Note: output field is guaranteed to exist for completed steps (StepCompletedEvent requires it)\n if (depState.status !== \"completed\") {\n throw new Error(\n `Dependency '${depStep.name}' is not ready (status: ${depState.status}). ` +\n `This should not happen - checkDependenciesSatisfied should have prevented scheduling.`\n );\n }\n\n if (!depState.output) {\n throw new Error(`Dependency '${depStep.name}' has no output despite being completed`);\n }\n\n // Parse dependency output\n dependencyOutputs[depKey] = JSON.parse(depState.output);\n }\n\n return dependencyOutputs;\n}\n\n/**\n * Find all steps that depend on a given step\n * @param targetStepId - The stepId (unique identifier) to find dependents for\n * @param allSteps - All steps in the workflow\n * @param requiredOnly - If true, only return steps with required dependencies\n */\nexport function findDependentSteps(\n targetStepId: string,\n allSteps: LoadedStep[],\n requiredOnly: boolean = false\n): LoadedStep[] {\n return allSteps.filter((step) => {\n const deps = Object.entries(step.dependencies) as [string, LoadedStep][];\n return deps.some(([alias, dep]) => {\n const dependsOnTarget = dep.id === targetStepId;\n if (!dependsOnTarget) return false;\n\n if (requiredOnly) {\n const isOptionalDep = isOptional(step.dependencies[alias]);\n return !isOptionalDep; // Only include if it's a required dependency\n }\n\n return true; // Include all dependencies\n });\n });\n}\n",
9
9
  "import type { Backend } from \"@cascade-flow/backend-interface\";\nimport { getMicrosecondTimestamp, projectStepState } from \"@cascade-flow/backend-interface\";\nimport type { LoadedStep } from \"@cascade-flow/runner\";\nimport { findDependentSteps } from \"../execution/dependency-resolver.ts\";\n\n/**\n * Handle a step skip - emit StepSkipped event\n */\nexport async function handleStepSkip(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n stepId: string,\n skipError: {\n reason?: string;\n message: string;\n metadata?: Record<string, unknown>;\n },\n duration: number,\n attemptNumber: number\n): Promise<void> {\n await backend.saveStepSkipped(workflowSlug, runId, stepId, {\n skipType: \"primary\",\n reason: skipError.reason || skipError.message.replace(\"Step skipped: \", \"\"),\n metadata: skipError.metadata,\n duration,\n attemptNumber,\n });\n}\n\n/**\n * Cascade skip to dependent steps that have the skipped step as a REQUIRED dependency\n * Recursively propagates skip to all dependent steps\n */\nexport async function cascadeSkip(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n skippedStepId: string,\n allSteps: LoadedStep[],\n workerId: string\n): Promise<void> {\n // Find steps that depend on the skipped step as a REQUIRED dependency (using stepId)\n const dependentSteps = findDependentSteps(skippedStepId, allSteps, true);\n\n for (const dependentStep of dependentSteps) {\n // Check current state to avoid double-skipping (using stepId)\n const stepEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: dependentStep.id,\n });\n const hasEvents = stepEvents.length > 0;\n\n // If step has no events yet or is not terminal (not completed/failed/skipped), cascade skip\n if (!hasEvents) {\n const now = getMicrosecondTimestamp(); // Microseconds\n\n // Emit StepStarted to mark as \"running\" briefly (for consistency) - using stepId\n await backend.saveStepStart(workflowSlug, runId, dependentStep.id, workerId, {\n dependencies: Object.keys(dependentStep.dependencies),\n timestamp: now,\n attemptNumber: 1,\n });\n\n // Immediately skip with cascade reason (using stepId)\n await backend.saveStepSkipped(workflowSlug, runId, dependentStep.id, {\n skipType: \"cascade\",\n reason: `Dependency '${skippedStepId}' was skipped`,\n duration: 0, // No actual execution time\n attemptNumber: 1,\n cascadedFrom: skippedStepId,\n });\n\n // Recursively cascade to further dependents (using stepId)\n await cascadeSkip(backend, workflowSlug, runId, dependentStep.id, allSteps, workerId);\n } else {\n const depState = projectStepState(stepEvents as any, workflowSlug);\n if (depState.status !== \"completed\" && depState.status !== \"failed\" && depState.status !== \"skipped\") {\n // Step is in progress or scheduled, still cascade skip (using stepId)\n await backend.saveStepSkipped(workflowSlug, runId, dependentStep.id, {\n skipType: \"cascade\",\n reason: `Dependency '${skippedStepId}' was skipped`,\n duration: getMicrosecondTimestamp() - (depState.startTime || getMicrosecondTimestamp()),\n attemptNumber: depState.attemptNumber,\n cascadedFrom: skippedStepId,\n });\n\n // Recursively cascade to further dependents (using stepId)\n await cascadeSkip(backend, workflowSlug, runId, dependentStep.id, allSteps, workerId);\n }\n }\n }\n}\n",
10
- "import type { Backend } from \"@cascade-flow/backend-interface\";\nimport { getMicrosecondTimestamp, projectStepState } from \"@cascade-flow/backend-interface\";\nimport type { LoadedStep } from \"@cascade-flow/runner\";\nimport { checkDependenciesSatisfied, findDependentSteps } from \"../execution/dependency-resolver.ts\";\n\n/**\n * Schedule a single step (emit StepScheduled event)\n */\nexport async function scheduleStep(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n stepId: string,\n reason: \"initial\" | \"dependency-satisfied\" | \"retry\",\n attemptNumber: number,\n options?: {\n availableAt?: number;\n retryDelayMs?: number;\n }\n): Promise<void> {\n const now = getMicrosecondTimestamp();\n await backend.saveStepScheduled(workflowSlug, runId, stepId, {\n availableAt: options?.availableAt ?? now,\n reason,\n attemptNumber,\n retryDelayMs: options?.retryDelayMs,\n });\n}\n\n/**\n * Schedule initial steps (steps with no dependencies or all optional dependencies)\n */\nexport async function scheduleInitialSteps(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n steps: LoadedStep[]\n): Promise<string[]> {\n const scheduledSteps: string[] = [];\n\n for (const step of steps) {\n // Check if step has no events yet (using stepId)\n const stepEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: step.id,\n });\n\n if (stepEvents.length === 0) {\n // Check if dependencies are satisfied\n const canSchedule = await checkDependenciesSatisfied(step, backend, workflowSlug, runId);\n\n if (canSchedule) {\n await scheduleStep(\n backend,\n workflowSlug,\n runId,\n step.id,\n Object.keys(step.dependencies).length === 0 ? \"initial\" : \"dependency-satisfied\",\n 1\n );\n scheduledSteps.push(step.name);\n }\n }\n }\n\n return scheduledSteps;\n}\n\n/**\n * Schedule ready steps (pending steps whose dependencies are now satisfied)\n */\nexport async function scheduleReadySteps(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n steps: LoadedStep[]\n): Promise<string[]> {\n const scheduledSteps: string[] = [];\n\n for (const step of steps) {\n const stepEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: step.id,\n });\n\n // Skip if no events yet (handled by scheduleInitialSteps)\n if (stepEvents.length === 0) continue;\n\n const state = projectStepState(stepEvents as any, workflowSlug);\n\n // Only schedule if step is pending\n if (state.status === \"pending\") {\n const canSchedule = await checkDependenciesSatisfied(step, backend, workflowSlug, runId);\n\n if (canSchedule) {\n await scheduleStep(backend, workflowSlug, runId, step.id, \"dependency-satisfied\", 1);\n scheduledSteps.push(step.name);\n }\n }\n }\n\n return scheduledSteps;\n}\n\n/**\n * Schedule downstream steps (steps that depend on a newly completed step)\n */\nexport async function scheduleDownstreamSteps(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n completedStepId: string,\n allSteps: LoadedStep[]\n): Promise<string[]> {\n const scheduledSteps: string[] = [];\n\n // Find steps that depend on the completed step (using stepId)\n const dependentSteps = findDependentSteps(completedStepId, allSteps, false);\n\n for (const dependentStep of dependentSteps) {\n // Check if all dependencies are completed\n const allDepsCompleted = await checkDependenciesSatisfied(dependentStep, backend, workflowSlug, runId);\n\n if (allDepsCompleted) {\n // Check current state to avoid double-scheduling (using stepId)\n const stepEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: dependentStep.id,\n });\n\n // If step has no events yet, or is still pending, schedule it\n if (stepEvents.length === 0) {\n await scheduleStep(backend, workflowSlug, runId, dependentStep.id, \"dependency-satisfied\", 1);\n scheduledSteps.push(dependentStep.name);\n } else {\n const state = projectStepState(stepEvents as any, workflowSlug);\n if (state.status === \"pending\") {\n await scheduleStep(backend, workflowSlug, runId, dependentStep.id, \"dependency-satisfied\", 1);\n scheduledSteps.push(dependentStep.name);\n }\n }\n }\n }\n\n return scheduledSteps;\n}\n",
10
+ "import type { Backend } from \"@cascade-flow/backend-interface\";\nimport { getMicrosecondTimestamp, projectStepState } from \"@cascade-flow/backend-interface\";\nimport type { LoadedStep } from \"@cascade-flow/runner\";\nimport { checkDependenciesSatisfied, findDependentSteps } from \"../execution/dependency-resolver.ts\";\n\n/**\n * Schedule a single step (emit StepScheduled event)\n */\nexport async function scheduleStep(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n stepId: string,\n reason: \"initial\" | \"dependency-satisfied\" | \"retry\",\n attemptNumber: number,\n options?: {\n availableAt?: number;\n retryDelayMs?: number;\n priority?: number;\n }\n): Promise<void> {\n const now = getMicrosecondTimestamp();\n await backend.saveStepScheduled(workflowSlug, runId, stepId, {\n availableAt: options?.availableAt ?? now,\n reason,\n attemptNumber,\n retryDelayMs: options?.retryDelayMs,\n priority: options?.priority,\n });\n}\n\n/**\n * Schedule initial steps (steps with no dependencies or all optional dependencies)\n */\nexport async function scheduleInitialSteps(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n steps: LoadedStep[]\n): Promise<string[]> {\n const scheduledSteps: string[] = [];\n\n for (const step of steps) {\n // Check if step has no events yet (using stepId)\n const stepEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: step.id,\n });\n\n if (stepEvents.length === 0) {\n // Check if dependencies are satisfied\n const canSchedule = await checkDependenciesSatisfied(step, backend, workflowSlug, runId);\n\n if (canSchedule) {\n await scheduleStep(\n backend,\n workflowSlug,\n runId,\n step.id,\n Object.keys(step.dependencies).length === 0 ? \"initial\" : \"dependency-satisfied\",\n 1\n );\n scheduledSteps.push(step.name);\n }\n }\n }\n\n return scheduledSteps;\n}\n\n/**\n * Schedule ready steps (pending steps whose dependencies are now satisfied)\n */\nexport async function scheduleReadySteps(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n steps: LoadedStep[]\n): Promise<string[]> {\n const scheduledSteps: string[] = [];\n\n for (const step of steps) {\n const stepEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: step.id,\n });\n\n // Skip if no events yet (handled by scheduleInitialSteps)\n if (stepEvents.length === 0) continue;\n\n const state = projectStepState(stepEvents as any, workflowSlug);\n\n // Only schedule if step is pending\n if (state.status === \"pending\") {\n const canSchedule = await checkDependenciesSatisfied(step, backend, workflowSlug, runId);\n\n if (canSchedule) {\n await scheduleStep(backend, workflowSlug, runId, step.id, \"dependency-satisfied\", 1);\n scheduledSteps.push(step.name);\n }\n }\n }\n\n return scheduledSteps;\n}\n\n/**\n * Schedule downstream steps (steps that depend on a newly completed step)\n */\nexport async function scheduleDownstreamSteps(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n completedStepId: string,\n allSteps: LoadedStep[],\n options?: {\n priority?: number;\n }\n): Promise<string[]> {\n const scheduledSteps: string[] = [];\n\n // Find steps that depend on the completed step (using stepId)\n const dependentSteps = findDependentSteps(completedStepId, allSteps, false);\n\n for (const dependentStep of dependentSteps) {\n // Check if all dependencies are completed\n const allDepsCompleted = await checkDependenciesSatisfied(dependentStep, backend, workflowSlug, runId);\n\n if (allDepsCompleted) {\n // Check current state to avoid double-scheduling (using stepId)\n const stepEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: dependentStep.id,\n });\n\n // If step has no events yet, or is still pending, schedule it\n if (stepEvents.length === 0) {\n await scheduleStep(backend, workflowSlug, runId, dependentStep.id, \"dependency-satisfied\", 1, { priority: options?.priority });\n scheduledSteps.push(dependentStep.name);\n } else {\n const state = projectStepState(stepEvents as any, workflowSlug);\n if (state.status === \"pending\") {\n await scheduleStep(backend, workflowSlug, runId, dependentStep.id, \"dependency-satisfied\", 1, { priority: options?.priority });\n scheduledSteps.push(dependentStep.name);\n }\n }\n }\n }\n\n return scheduledSteps;\n}\n",
11
11
  "/**\n * Step key utilities\n *\n * A step key is a unique identifier in the format: `workflowSlug/runId/stepId`\n * where stepId may contain slashes for nested steps (e.g., \"slp/cognitive/extract-discrepancy\")\n */\n\n/**\n * Create a step key from its components\n *\n * @param workflowSlug - The workflow identifier\n * @param runId - The run identifier\n * @param stepId - The step identifier (may contain slashes for nested steps)\n * @returns The step key in format: `workflowSlug/runId/stepId`\n *\n * @example\n * createStepKey(\"pdpm\", \"run_123\", \"step-1\")\n * // => \"pdpm/run_123/step-1\"\n *\n * @example\n * createStepKey(\"pdpm\", \"run_123\", \"slp/cognitive/extract-discrepancy\")\n * // => \"pdpm/run_123/slp/cognitive/extract-discrepancy\"\n */\nexport function createStepKey(workflowSlug: string, runId: string, stepId: string): string {\n return `${workflowSlug}/${runId}/${stepId}`;\n}\n\n/**\n * Extract the stepId component from a step key\n *\n * Handles nested steps that contain slashes in their stepId.\n *\n * @param stepKey - The step key in format: `workflowSlug/runId/stepId`\n * @returns The stepId portion (everything after the first two slashes)\n *\n * @example\n * extractStepId(\"pdpm/run_123/step-1\")\n * // => \"step-1\"\n *\n * @example\n * extractStepId(\"pdpm/run_123/slp/cognitive/extract-discrepancy\")\n * // => \"slp/cognitive/extract-discrepancy\"\n */\nexport function extractStepId(stepKey: string): string {\n const parts = stepKey.split('/');\n return parts.slice(2).join('/');\n}\n\n/**\n * Extract the workflowSlug component from a step key\n *\n * @param stepKey - The step key in format: `workflowSlug/runId/stepId`\n * @returns The workflowSlug portion (first component)\n *\n * @example\n * extractWorkflowSlug(\"pdpm/run_123/step-1\")\n * // => \"pdpm\"\n */\nexport function extractWorkflowSlug(stepKey: string): string {\n return stepKey.split('/')[0]!;\n}\n\n/**\n * Extract the runId component from a step key\n *\n * @param stepKey - The step key in format: `workflowSlug/runId/stepId`\n * @returns The runId portion (second component)\n *\n * @example\n * extractRunId(\"pdpm/run_123/step-1\")\n * // => \"run_123\"\n */\nexport function extractRunId(stepKey: string): string {\n return stepKey.split('/')[1]!;\n}\n",
12
12
  "import type { Backend } from \"@cascade-flow/backend-interface\";\nimport { getMicrosecondTimestamp, projectStepState } from \"@cascade-flow/backend-interface\";\nimport type { ZodIssue, ZodSchema } from \"zod\";\nimport type { LoadedStep } from \"@cascade-flow/runner\";\nimport {\n calculateWorkflowDuration,\n getRunSubmittedEvent,\n getCurrentWorkflowAttemptNumber,\n} from \"../utils/event-helpers.ts\";\nimport type { WorkflowEvent } from \"../utils/event-helpers.ts\";\n\n/**\n * Handle workflow start - emit WorkflowStarted event\n */\nexport async function handleWorkflowStart(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n metadata: {\n versionId: string;\n hasInputSchema: boolean;\n hasInput: boolean;\n },\n workflowEvents: WorkflowEvent[]\n): Promise<void> {\n const workflowAttemptNumber = getCurrentWorkflowAttemptNumber(workflowEvents);\n\n await backend.saveWorkflowStart(workflowSlug, runId, {\n versionId: metadata.versionId,\n workflowAttemptNumber,\n hasInputSchema: metadata.hasInputSchema,\n hasInput: metadata.hasInput,\n });\n}\n\n/**\n * Validate workflow input against schema\n * Returns validation result and emits WorkflowInputValidation event\n */\nexport async function validateWorkflowInput(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n workflowInput: unknown,\n inputSchema: ZodSchema | undefined,\n workflowEvents: WorkflowEvent[]\n): Promise<{\n success: boolean;\n error?: { name: string; message: string };\n validationErrors?: Array<{ path: string; message: string }>;\n}> {\n const workflowAttemptNumber = getCurrentWorkflowAttemptNumber(workflowEvents);\n\n if (!inputSchema) {\n // No schema to validate against - if input provided, mark as success\n if (workflowInput !== undefined) {\n await backend.saveWorkflowInputValidation(workflowSlug, runId, {\n workflowAttemptNumber,\n hasSchema: false,\n success: true,\n });\n }\n return { success: true };\n }\n\n // Validate with schema\n const parseResult = inputSchema.safeParse(workflowInput ?? {});\n\n if (!parseResult.success) {\n const validationErrors = parseResult.error.issues.map((e: ZodIssue) => ({\n path: e.path.join(\".\"),\n message: e.message,\n }));\n\n const errorMessage = validationErrors\n .map((e: { path: string; message: string }) => ` ${e.path}: ${e.message}`)\n .join(\"\\n\");\n\n const error = {\n name: \"ValidationError\",\n message: `Invalid workflow input:\\n${errorMessage}`,\n };\n\n // Emit validation FAILURE event\n await backend.saveWorkflowInputValidation(workflowSlug, runId, {\n workflowAttemptNumber,\n hasSchema: true,\n success: false,\n error,\n validationErrors,\n });\n\n // Emit WorkflowFailed event\n const duration = calculateWorkflowDuration(workflowEvents);\n\n await backend.saveWorkflowFailed(\n workflowSlug,\n runId,\n error,\n {\n workflowAttemptNumber,\n duration,\n completedSteps: 0,\n },\n \"step-failed\" // Using existing failure reason\n );\n\n return { success: false, error, validationErrors };\n }\n\n // Validation succeeded - emit validation SUCCESS event\n await backend.saveWorkflowInputValidation(workflowSlug, runId, {\n workflowAttemptNumber,\n hasSchema: true,\n success: true,\n });\n\n return { success: true };\n}\n\n/**\n * Handle workflow completion - collect exported outputs and emit WorkflowCompleted event\n */\nexport async function handleWorkflowCompletion(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n steps: LoadedStep[],\n workflowEvents: WorkflowEvent[]\n): Promise<void> {\n const workflowAttemptNumber = getCurrentWorkflowAttemptNumber(workflowEvents);\n const duration = calculateWorkflowDuration(workflowEvents);\n const now = getMicrosecondTimestamp();\n\n // Collect exported step outputs\n const output: Record<string, unknown> = {};\n for (const step of steps) {\n const stepEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: step.id,\n });\n const state = projectStepState(stepEvents, workflowSlug);\n\n if (state.exportOutput && state.output) {\n output[step.name] = JSON.parse(state.output);\n }\n }\n\n await backend.saveWorkflowComplete(workflowSlug, runId, output, {\n workflowAttemptNumber,\n timestamp: now,\n duration,\n totalSteps: steps.length,\n });\n}\n\n/**\n * Handle workflow failure - count completed steps and emit WorkflowFailed event\n */\nexport async function handleWorkflowFailure(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n steps: LoadedStep[],\n workflowEvents: WorkflowEvent[],\n failedStepName?: string\n): Promise<void> {\n const workflowAttemptNumber = getCurrentWorkflowAttemptNumber(workflowEvents);\n const duration = calculateWorkflowDuration(workflowEvents);\n\n // Count completed steps\n let completedCount = 0;\n for (const step of steps) {\n const stepEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId: step.id,\n });\n if (stepEvents.length > 0) {\n const state = projectStepState(stepEvents, workflowSlug);\n if (state.status === \"completed\") {\n completedCount++;\n }\n }\n }\n\n await backend.saveWorkflowFailed(\n workflowSlug,\n runId,\n {\n message: failedStepName ? `Step ${failedStepName} failed` : \"Workflow failed\",\n name: \"StepFailure\",\n },\n {\n workflowAttemptNumber,\n duration,\n completedSteps: completedCount,\n failedStep: failedStepName,\n },\n \"step-failed\"\n );\n}\n\n/**\n * Parse workflow input from RunSubmitted event\n */\nexport function parseWorkflowInput(workflowEvents: WorkflowEvent[]): unknown {\n const runSubmittedEvent = getRunSubmittedEvent(workflowEvents);\n if (runSubmittedEvent && runSubmittedEvent.input) {\n return JSON.parse(runSubmittedEvent.input);\n }\n return undefined;\n}\n",
13
13
  "import type { Backend, StepEvent, StepState, WorkflowEvent } from \"@cascade-flow/backend-interface\";\nimport { getMicrosecondTimestamp, projectStepState } from \"@cascade-flow/backend-interface\";\n\n// Re-export types for convenience\nexport type { WorkflowEvent, StepEvent, StepState };\n\n/**\n * Load step events and project to current state\n */\nexport async function loadStepState(\n backend: Backend,\n workflowSlug: string,\n runId: string,\n stepId: string\n): Promise<StepState> {\n const stepEvents = await backend.loadEvents(workflowSlug, runId, {\n category: \"step\",\n stepId,\n });\n\n return projectStepState(stepEvents, workflowSlug);\n}\n\n/**\n * Load all workflow events for a run\n */\nexport async function loadWorkflowEvents(\n backend: Backend,\n workflowSlug: string,\n runId: string\n): Promise<WorkflowEvent[]> {\n return backend.loadEvents(workflowSlug, runId, { category: \"workflow\" });\n}\n\n/**\n * Get the current workflow attempt number from events.\n * Returns 1 if no retry has occurred (initial attempt).\n * Returns the workflowAttemptNumber from the most recent WorkflowRetryStarted event.\n */\nexport function getCurrentWorkflowAttemptNumber(events: WorkflowEvent[]): number {\n const retryEvents = events.filter((e): e is Extract<WorkflowEvent, { type: \"WorkflowRetryStarted\" }> =>\n e.type === \"WorkflowRetryStarted\"\n );\n if (retryEvents.length === 0) return 1; // Initial attempt\n\n // Get the most recent retry (events are chronologically sorted)\n const mostRecentRetry = retryEvents[retryEvents.length - 1];\n if (!mostRecentRetry) return 1; // Extra safety check\n\n return mostRecentRetry.workflowAttemptNumber;\n}\n\n/**\n * Check if workflow is in a terminal state (completed, failed, or cancelled)\n * Only considers events from the current workflow attempt.\n */\nexport function isWorkflowTerminal(events: WorkflowEvent[]): boolean {\n const currentAttempt = getCurrentWorkflowAttemptNumber(events);\n return events.some((e) => {\n if (e.type === \"WorkflowCompleted\" || e.type === \"WorkflowFailed\" || e.type === \"WorkflowCancelled\") {\n return e.workflowAttemptNumber === currentAttempt;\n }\n return false;\n });\n}\n\n/**\n * Check specific terminal states\n * Only considers events from the current workflow attempt.\n */\nexport function getWorkflowTerminalState(events: WorkflowEvent[]): {\n hasCompleted: boolean;\n hasFailed: boolean;\n hasCancelled: boolean;\n} {\n const currentAttempt = getCurrentWorkflowAttemptNumber(events);\n\n return {\n hasCompleted: events.some((e) => e.type === \"WorkflowCompleted\" && e.workflowAttemptNumber === currentAttempt),\n hasFailed: events.some((e) => e.type === \"WorkflowFailed\" && e.workflowAttemptNumber === currentAttempt),\n hasCancelled: events.some((e) => e.type === \"WorkflowCancelled\" && e.workflowAttemptNumber === currentAttempt),\n };\n}\n\n/**\n * Calculate workflow duration from start event to now (in microseconds)\n * Uses the WorkflowStarted event from the current workflow attempt.\n */\nexport function calculateWorkflowDuration(events: WorkflowEvent[]): number {\n const currentAttempt = getCurrentWorkflowAttemptNumber(events);\n\n // Find WorkflowStarted event for current attempt\n const workflowStartEvent = events.find((e): e is Extract<WorkflowEvent, { type: \"WorkflowStarted\" }> =>\n e.type === \"WorkflowStarted\" && e.workflowAttemptNumber === currentAttempt\n );\n\n const startTime = workflowStartEvent ? workflowStartEvent.timestampUs : 0;\n const now = getMicrosecondTimestamp();\n return now - startTime;\n}\n\n/**\n * Check if workflow has been started\n * Only considers WorkflowStarted events from the current workflow attempt.\n */\nexport function hasWorkflowStarted(events: WorkflowEvent[]): boolean {\n const currentAttempt = getCurrentWorkflowAttemptNumber(events);\n return events.some((e) => e.type === \"WorkflowStarted\" && e.workflowAttemptNumber === currentAttempt);\n}\n\n/**\n * Check if workflow has been submitted\n */\nexport function hasWorkflowSubmitted(events: WorkflowEvent[]): boolean {\n return events.some((e) => e.type === \"RunSubmitted\");\n}\n\n/**\n * Check if workflow input has been validated\n * Only considers WorkflowInputValidation events from the current workflow attempt.\n */\nexport function hasWorkflowValidatedInput(events: WorkflowEvent[]): boolean {\n const currentAttempt = getCurrentWorkflowAttemptNumber(events);\n return events.some((e) => e.type === \"WorkflowInputValidation\" && e.workflowAttemptNumber === currentAttempt);\n}\n\n/**\n * Get the RunSubmitted event from workflow events\n */\nexport function getRunSubmittedEvent(events: WorkflowEvent[]): Extract<WorkflowEvent, { type: \"RunSubmitted\" }> | undefined {\n return events.find((e): e is Extract<WorkflowEvent, { type: \"RunSubmitted\" }> =>\n e.type === \"RunSubmitted\"\n );\n}\n\n/**\n * Get the WorkflowStarted event from workflow events\n * Returns the WorkflowStarted event from the current workflow attempt.\n */\nexport function getWorkflowStartedEvent(events: WorkflowEvent[]): Extract<WorkflowEvent, { type: \"WorkflowStarted\" }> | undefined {\n const currentAttempt = getCurrentWorkflowAttemptNumber(events);\n return events.find((e): e is Extract<WorkflowEvent, { type: \"WorkflowStarted\" }> =>\n e.type === \"WorkflowStarted\" && e.workflowAttemptNumber === currentAttempt\n );\n}\n\n/**\n * Get the WorkflowInputValidation event from workflow events\n * Returns the most recent WorkflowInputValidation event.\n *\n * Note: We return the most recent validation event regardless of attempt number because:\n * 1. Workflow input is immutable (stored once in RunSubmitted event)\n * 2. Input validation is idempotent - same input + schema = same result\n * 3. This prevents race conditions where executor claims steps before scheduler emits validation for new attempt\n * 4. Validation result from attempt 1 is valid for all subsequent retry attempts\n */\nexport function getWorkflowInputValidationEvent(events: WorkflowEvent[]): Extract<WorkflowEvent, { type: \"WorkflowInputValidation\" }> | undefined {\n // Get the most recent validation event (input doesn't change across attempts)\n const validationEvents = events.filter((e): e is Extract<WorkflowEvent, { type: \"WorkflowInputValidation\" }> =>\n e.type === \"WorkflowInputValidation\"\n );\n return validationEvents.length > 0 ? validationEvents[validationEvents.length - 1] : undefined;\n}\n"
14
14
  ],
15
- "mappings": "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",
16
- "debugId": "2EA382FEED348E2C64756E2164756E21",
15
+ "mappings": "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",
16
+ "debugId": "2B02B1179FF8DE8264756E2164756E21",
17
17
  "names": []
18
18
  }
@@ -6,6 +6,7 @@ import type { LoadedStep } from "@cascade-flow/runner";
6
6
  export declare function scheduleStep(backend: Backend, workflowSlug: string, runId: string, stepId: string, reason: "initial" | "dependency-satisfied" | "retry", attemptNumber: number, options?: {
7
7
  availableAt?: number;
8
8
  retryDelayMs?: number;
9
+ priority?: number;
9
10
  }): Promise<void>;
10
11
  /**
11
12
  * Schedule initial steps (steps with no dependencies or all optional dependencies)
@@ -18,5 +19,7 @@ export declare function scheduleReadySteps(backend: Backend, workflowSlug: strin
18
19
  /**
19
20
  * Schedule downstream steps (steps that depend on a newly completed step)
20
21
  */
21
- export declare function scheduleDownstreamSteps(backend: Backend, workflowSlug: string, runId: string, completedStepId: string, allSteps: LoadedStep[]): Promise<string[]>;
22
+ export declare function scheduleDownstreamSteps(backend: Backend, workflowSlug: string, runId: string, completedStepId: string, allSteps: LoadedStep[], options?: {
23
+ priority?: number;
24
+ }): Promise<string[]>;
22
25
  //# sourceMappingURL=step-scheduler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"step-scheduler.d.ts","sourceRoot":"","sources":["../../src/scheduling/step-scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,GAAG,sBAAsB,GAAG,OAAO,EACpD,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;IACR,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GACA,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,EAAE,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC,CA6BnB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,EAAE,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC,CA0BnB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,UAAU,EAAE,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CAgCnB"}
1
+ {"version":3,"file":"step-scheduler.d.ts","sourceRoot":"","sources":["../../src/scheduling/step-scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,GAAG,sBAAsB,GAAG,OAAO,EACpD,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;IACR,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,EAAE,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC,CA6BnB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,EAAE,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC,CA0BnB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,UAAU,EAAE,EACtB,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,OAAO,CAAC,MAAM,EAAE,CAAC,CAgCnB"}
@@ -26,6 +26,7 @@ export declare class StepWorker {
26
26
  private activeSteps;
27
27
  private stats;
28
28
  private workflowCache;
29
+ private freeSlots;
29
30
  constructor(backend?: Backend, options?: StepWorkerOptions);
30
31
  /**
31
32
  * Get current worker statistics
@@ -1 +1 @@
1
- {"version":3,"file":"step-worker.d.ts","sourceRoot":"","sources":["../src/step-worker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AA0B/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAWrE;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,WAAW,CAMJ;IACf,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,aAAa,CAA2F;gBAEpG,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB;IAiC9D;;OAEG;IACH,QAAQ,IAAI,eAAe;IAI3B;;;;;;;OAOG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiD5B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB3B;;OAEG;YACW,aAAa;IAoB3B;;;OAGG;YACW,iBAAiB;IAsD/B;;OAEG;YACW,YAAY;IAoD1B;;OAEG;YACW,aAAa;IAqL3B;;OAEG;YACW,eAAe;IAqB7B;;;;OAIG;YACW,yBAAyB;IA2BvC;;OAEG;YACW,WAAW;IA2YzB;;;OAGG;YACW,gBAAgB;IAyB9B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,cAAc,CAAC,CAAQ;CAChC"}
1
+ {"version":3,"file":"step-worker.d.ts","sourceRoot":"","sources":["../src/step-worker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AA0B/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAWrE;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,WAAW,CAOJ;IACf,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,aAAa,CAA2F;IAChH,OAAO,CAAC,SAAS,CAA0B;gBAE/B,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB;IAuC9D;;OAEG;IACH,QAAQ,IAAI,eAAe;IAI3B;;;;;;;OAOG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiD5B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB3B;;OAEG;YACW,aAAa;IAoB3B;;;OAGG;YACW,iBAAiB;IAsD/B;;OAEG;YACW,YAAY;IA6C1B;;OAEG;YACW,aAAa;IAkN3B;;OAEG;YACW,eAAe;IAqB7B;;;;OAIG;YACW,yBAAyB;IA2BvC;;OAEG;YACW,WAAW;IA4azB;;;OAGG;YACW,gBAAgB;IAyB9B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,cAAc,CAAC,CAAQ;CAChC"}
package/dist/types.d.ts CHANGED
@@ -22,6 +22,8 @@ export type StepWorkerOptions = {
22
22
  staleCheckInterval?: number;
23
23
  /** How often to run scheduler sweep (ms, default: 5000) */
24
24
  schedulerInterval?: number;
25
+ /** Number of active runs to fetch per scheduler batch (default: 200) */
26
+ schedulerRunBatchSize?: number;
25
27
  /** Graceful shutdown timeout (ms, default: 30000) */
26
28
  shutdownTimeout?: number;
27
29
  /** Path to workflows directory (default: "./workflows") */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,2FAA2F;IAC3F,IAAI,CAAC,EAAE,UAAU,CAAC;IAElB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,2FAA2F;IAC3F,IAAI,CAAC,EAAE,UAAU,CAAC;IAElB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,wEAAwE;IACxE,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cascade-flow/worker",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -18,8 +18,8 @@
18
18
  "test": "bun test"
19
19
  },
20
20
  "dependencies": {
21
- "@cascade-flow/backend-interface": "0.2.8",
22
- "@cascade-flow/backend-filesystem": "0.2.17",
21
+ "@cascade-flow/backend-interface": "0.2.9",
22
+ "@cascade-flow/backend-filesystem": "0.2.18",
23
23
  "@cascade-flow/runner": "0.2.17",
24
24
  "@cascade-flow/workflow": "0.3.5"
25
25
  },