@calmo/task-runner 3.4.0 → 3.4.1

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.
Files changed (87) hide show
  1. package/.github/dependabot.yml +7 -7
  2. package/.github/workflows/ci.yml +4 -4
  3. package/.jules/backlog_maniac.md +1 -0
  4. package/.jules/nexus.md +1 -0
  5. package/.jules/sentinel.md +1 -0
  6. package/.releaserc.json +2 -7
  7. package/AGENTS.md +8 -2
  8. package/CHANGELOG.md +178 -174
  9. package/README.md +23 -23
  10. package/coverage/coverage-final.json +8 -8
  11. package/coverage/index.html +7 -7
  12. package/coverage/lcov-report/index.html +7 -7
  13. package/coverage/lcov-report/src/EventBus.ts.html +27 -21
  14. package/coverage/lcov-report/src/TaskGraphValidationError.ts.html +12 -3
  15. package/coverage/lcov-report/src/TaskGraphValidator.ts.html +152 -137
  16. package/coverage/lcov-report/src/TaskRunner.ts.html +48 -45
  17. package/coverage/lcov-report/src/TaskRunnerBuilder.ts.html +29 -5
  18. package/coverage/lcov-report/src/TaskRunnerExecutionConfig.ts.html +1 -1
  19. package/coverage/lcov-report/src/TaskStateManager.ts.html +1 -1
  20. package/coverage/lcov-report/src/WorkflowExecutor.ts.html +21 -12
  21. package/coverage/lcov-report/src/contracts/RunnerEvents.ts.html +1 -1
  22. package/coverage/lcov-report/src/contracts/index.html +1 -1
  23. package/coverage/lcov-report/src/index.html +8 -8
  24. package/coverage/lcov-report/src/strategies/DryRunExecutionStrategy.ts.html +4 -4
  25. package/coverage/lcov-report/src/strategies/RetryingExecutionStrategy.ts.html +29 -11
  26. package/coverage/lcov-report/src/strategies/StandardExecutionStrategy.ts.html +5 -5
  27. package/coverage/lcov-report/src/strategies/index.html +1 -1
  28. package/coverage/lcov.info +266 -262
  29. package/coverage/src/EventBus.ts.html +27 -21
  30. package/coverage/src/TaskGraphValidationError.ts.html +12 -3
  31. package/coverage/src/TaskGraphValidator.ts.html +152 -137
  32. package/coverage/src/TaskRunner.ts.html +48 -45
  33. package/coverage/src/TaskRunnerBuilder.ts.html +29 -5
  34. package/coverage/src/TaskRunnerExecutionConfig.ts.html +1 -1
  35. package/coverage/src/TaskStateManager.ts.html +1 -1
  36. package/coverage/src/WorkflowExecutor.ts.html +21 -12
  37. package/coverage/src/contracts/RunnerEvents.ts.html +1 -1
  38. package/coverage/src/contracts/index.html +1 -1
  39. package/coverage/src/index.html +8 -8
  40. package/coverage/src/strategies/DryRunExecutionStrategy.ts.html +4 -4
  41. package/coverage/src/strategies/RetryingExecutionStrategy.ts.html +29 -11
  42. package/coverage/src/strategies/StandardExecutionStrategy.ts.html +5 -5
  43. package/coverage/src/strategies/index.html +1 -1
  44. package/dist/EventBus.js +13 -11
  45. package/dist/EventBus.js.map +1 -1
  46. package/dist/TaskGraphValidationError.js.map +1 -1
  47. package/dist/TaskGraphValidator.js +9 -9
  48. package/dist/TaskGraphValidator.js.map +1 -1
  49. package/dist/TaskRunner.js.map +1 -1
  50. package/dist/TaskRunnerBuilder.js.map +1 -1
  51. package/dist/WorkflowExecutor.js +2 -1
  52. package/dist/WorkflowExecutor.js.map +1 -1
  53. package/dist/strategies/RetryingExecutionStrategy.js +3 -1
  54. package/dist/strategies/RetryingExecutionStrategy.js.map +1 -1
  55. package/dist/strategies/StandardExecutionStrategy.js +1 -1
  56. package/dist/strategies/StandardExecutionStrategy.js.map +1 -1
  57. package/openspec/AGENTS.md +81 -15
  58. package/openspec/changes/archive/2026-01-18-add-concurrency-control/proposal.md +7 -4
  59. package/openspec/changes/archive/2026-01-18-add-concurrency-control/tasks.md +1 -0
  60. package/openspec/changes/archive/2026-01-18-add-external-task-cancellation/proposal.md +4 -1
  61. package/openspec/changes/archive/2026-01-18-add-external-task-cancellation/tasks.md +2 -1
  62. package/openspec/changes/archive/2026-01-18-add-integration-tests/proposal.md +3 -0
  63. package/openspec/changes/archive/2026-01-18-add-integration-tests/tasks.md +1 -0
  64. package/openspec/changes/archive/2026-01-18-add-task-retry-policy/proposal.md +3 -0
  65. package/openspec/changes/archive/2026-01-18-add-task-retry-policy/tasks.md +1 -0
  66. package/openspec/changes/archive/2026-01-18-add-workflow-preview/proposal.md +3 -0
  67. package/openspec/changes/archive/2026-01-18-add-workflow-preview/tasks.md +1 -0
  68. package/openspec/changes/archive/2026-01-18-refactor-core-architecture/proposal.md +3 -0
  69. package/openspec/changes/archive/2026-01-18-refactor-core-architecture/tasks.md +1 -0
  70. package/openspec/changes/feat-per-task-timeout/proposal.md +11 -6
  71. package/openspec/changes/feat-per-task-timeout/tasks.md +1 -1
  72. package/openspec/project.md +21 -15
  73. package/package.json +1 -1
  74. package/src/EventBus.ts +18 -16
  75. package/src/TaskGraph.ts +8 -8
  76. package/src/TaskGraphValidationError.ts +4 -1
  77. package/src/TaskGraphValidator.ts +148 -143
  78. package/src/TaskRunner.ts +42 -41
  79. package/src/TaskRunnerBuilder.ts +11 -3
  80. package/src/WorkflowExecutor.ts +13 -10
  81. package/src/contracts/ITaskGraphValidator.ts +12 -12
  82. package/src/contracts/ValidationError.ts +6 -6
  83. package/src/contracts/ValidationResult.ts +4 -4
  84. package/src/strategies/DryRunExecutionStrategy.ts +3 -3
  85. package/src/strategies/RetryingExecutionStrategy.ts +15 -9
  86. package/src/strategies/StandardExecutionStrategy.ts +4 -4
  87. package/test-report.xml +108 -108
@@ -264,7 +264,11 @@
264
264
  <a name='L199'></a><a href='#L199'>199</a>
265
265
  <a name='L200'></a><a href='#L200'>200</a>
266
266
  <a name='L201'></a><a href='#L201'>201</a>
267
- <a name='L202'></a><a href='#L202'>202</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
269
+ <span class="cline-any cline-neutral">&nbsp;</span>
270
+ <span class="cline-any cline-neutral">&nbsp;</span>
271
+ <span class="cline-any cline-neutral">&nbsp;</span>
268
272
  <span class="cline-any cline-neutral">&nbsp;</span>
269
273
  <span class="cline-any cline-neutral">&nbsp;</span>
270
274
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -288,11 +292,10 @@
288
292
  <span class="cline-any cline-neutral">&nbsp;</span>
289
293
  <span class="cline-any cline-neutral">&nbsp;</span>
290
294
  <span class="cline-any cline-neutral">&nbsp;</span>
291
- <span class="cline-any cline-yes">57x</span>
292
295
  <span class="cline-any cline-yes">57x</span>
293
296
  <span class="cline-any cline-yes">57x</span>
294
297
  <span class="cline-any cline-neutral">&nbsp;</span>
295
- <span class="cline-any cline-neutral">&nbsp;</span>
298
+ <span class="cline-any cline-yes">57x</span>
296
299
  <span class="cline-any cline-neutral">&nbsp;</span>
297
300
  <span class="cline-any cline-neutral">&nbsp;</span>
298
301
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -352,7 +355,6 @@
352
355
  <span class="cline-any cline-yes">24x</span>
353
356
  <span class="cline-any cline-neutral">&nbsp;</span>
354
357
  <span class="cline-any cline-neutral">&nbsp;</span>
355
- <span class="cline-any cline-neutral">&nbsp;</span>
356
358
  <span class="cline-any cline-yes">4x</span>
357
359
  <span class="cline-any cline-neutral">&nbsp;</span>
358
360
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -369,8 +371,6 @@
369
371
  <span class="cline-any cline-neutral">&nbsp;</span>
370
372
  <span class="cline-any cline-neutral">&nbsp;</span>
371
373
  <span class="cline-any cline-neutral">&nbsp;</span>
372
- <span class="cline-any cline-neutral">&nbsp;</span>
373
- <span class="cline-any cline-neutral">&nbsp;</span>
374
374
  <span class="cline-any cline-yes">4x</span>
375
375
  <span class="cline-any cline-neutral">&nbsp;</span>
376
376
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -433,6 +433,8 @@
433
433
  <span class="cline-any cline-yes">3x</span>
434
434
  <span class="cline-any cline-neutral">&nbsp;</span>
435
435
  <span class="cline-any cline-neutral">&nbsp;</span>
436
+ <span class="cline-any cline-neutral">&nbsp;</span>
437
+ <span class="cline-any cline-neutral">&nbsp;</span>
436
438
  <span class="cline-any cline-yes">5x</span>
437
439
  <span class="cline-any cline-neutral">&nbsp;</span>
438
440
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -469,7 +471,10 @@
469
471
  import { TaskResult } from "./TaskResult.js";
470
472
  import { TaskGraphValidator } from "./TaskGraphValidator.js";
471
473
  import { TaskGraph } from "./TaskGraph.js";
472
- import { RunnerEventPayloads, RunnerEventListener } from "./contracts/RunnerEvents.js";
474
+ import {
475
+ RunnerEventPayloads,
476
+ RunnerEventListener,
477
+ } from "./contracts/RunnerEvents.js";
473
478
  import { EventBus } from "./EventBus.js";
474
479
  import { WorkflowExecutor } from "./WorkflowExecutor.js";
475
480
  import { TaskRunnerExecutionConfig } from "./TaskRunnerExecutionConfig.js";
@@ -491,9 +496,8 @@ export { RunnerEventPayloads, RunnerEventListener, TaskRunnerExecutionConfig };
491
496
  export class TaskRunner&lt;TContext&gt; {
492
497
  private eventBus = new EventBus&lt;TContext&gt;();
493
498
  private validator = new TaskGraphValidator();
494
- private executionStrategy: IExecutionStrategy&lt;TContext&gt; = new RetryingExecutionStrategy(
495
- new StandardExecutionStrategy()
496
- );
499
+ private executionStrategy: IExecutionStrategy&lt;TContext&gt; =
500
+ new RetryingExecutionStrategy(new StandardExecutionStrategy());
497
501
  &nbsp;
498
502
  /**
499
503
  * @param context The shared context object to be passed to each task.
@@ -551,7 +555,6 @@ export class TaskRunner&lt;TContext&gt; {
551
555
  // Actually, Mermaid ID cannot have spaces without quotes.
552
556
  const safeId = (name: string) =&gt; JSON.stringify(name);
553
557
  const sanitize = (name: string) =&gt; this.sanitizeMermaidId(name);
554
- &nbsp;
555
558
  &nbsp;
556
559
  // Add all nodes first to ensure they exist
557
560
  for (const step of steps) {
@@ -565,9 +568,7 @@ export class TaskRunner&lt;TContext&gt; {
565
568
  for (const step of steps) {
566
569
  if (step.dependencies) {
567
570
  for (const dep of step.dependencies) {
568
- graphLines.push(
569
- ` ${sanitize(dep)} --&gt; ${sanitize(step.name)}`
570
- );
571
+ graphLines.push(` ${sanitize(dep)} --&gt; ${sanitize(step.name)}`);
571
572
  }
572
573
  }
573
574
  }
@@ -629,40 +630,42 @@ export class TaskRunner&lt;TContext&gt; {
629
630
  &nbsp;
630
631
  // We need to handle the timeout cleanup properly.
631
632
  if (config?.timeout !== undefined) {
632
- const controller = new AbortController();
633
- const timeoutId = setTimeout(() =&gt; {
634
- controller.abort(new Error(`Workflow timed out after ${config.timeout}ms`));
635
- }, config.timeout);
633
+ const controller = new AbortController();
634
+ const timeoutId = setTimeout(() =&gt; {
635
+ controller.abort(
636
+ new Error(`Workflow timed out after ${config.timeout}ms`)
637
+ );
638
+ }, config.timeout);
636
639
  &nbsp;
637
- let effectiveSignal = controller.signal;
638
- let onAbort: (() =&gt; void) | undefined;
640
+ let effectiveSignal = controller.signal;
641
+ let onAbort: (() =&gt; void) | undefined;
639
642
  &nbsp;
640
- // Handle combination of signals if user provided one
641
- if (config.signal) {
642
- if (config.signal.aborted) {
643
- // If already aborted, use it directly (WorkflowExecutor handles early abort)
644
- // We can cancel timeout immediately
645
- clearTimeout(timeoutId);
646
- effectiveSignal = config.signal;
647
- } else {
648
- // Listen to user signal to abort our controller
649
- onAbort = () =&gt; {
650
- controller.abort(config.signal?.reason);
651
- };
652
- config.signal.addEventListener("abort", onAbort);
653
- }
654
- }
643
+ // Handle combination of signals if user provided one
644
+ if (config.signal) {
645
+ if (config.signal.aborted) {
646
+ // If already aborted, use it directly (WorkflowExecutor handles early abort)
647
+ // We can cancel timeout immediately
648
+ clearTimeout(timeoutId);
649
+ effectiveSignal = config.signal;
650
+ } else {
651
+ // Listen to user signal to abort our controller
652
+ onAbort = () =&gt; {
653
+ controller.abort(config.signal?.reason);
654
+ };
655
+ config.signal.addEventListener("abort", onAbort);
656
+ }
657
+ }
655
658
  &nbsp;
656
- try {
657
- return await executor.execute(steps, effectiveSignal);
658
- } finally {
659
- clearTimeout(timeoutId);
660
- if (config.signal &amp;&amp; onAbort) {
661
- config.signal.removeEventListener("abort", onAbort);
662
- }
663
- }
659
+ try {
660
+ return await executor.execute(steps, effectiveSignal);
661
+ } finally {
662
+ clearTimeout(timeoutId);
663
+ if (config.signal &amp;&amp; onAbort) {
664
+ config.signal.removeEventListener("abort", onAbort);
665
+ }
666
+ }
664
667
  } else {
665
- return executor.execute(steps, config?.signal);
668
+ return executor.execute(steps, config?.signal);
666
669
  }
667
670
  }
668
671
  }
@@ -673,7 +676,7 @@ export class TaskRunner&lt;TContext&gt; {
673
676
  <div class='footer quiet pad2 space-top1 center small'>
674
677
  Code coverage generated by
675
678
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
676
- at 2026-01-18T20:19:46.886Z
679
+ at 2026-01-18T21:02:31.387Z
677
680
  </div>
678
681
  <script src="../prettify.js"></script>
679
682
  <script>
@@ -139,7 +139,21 @@
139
139
  <a name='L74'></a><a href='#L74'>74</a>
140
140
  <a name='L75'></a><a href='#L75'>75</a>
141
141
  <a name='L76'></a><a href='#L76'>76</a>
142
- <a name='L77'></a><a href='#L77'>77</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
151
+ <span class="cline-any cline-neutral">&nbsp;</span>
152
+ <span class="cline-any cline-neutral">&nbsp;</span>
153
+ <span class="cline-any cline-neutral">&nbsp;</span>
154
+ <span class="cline-any cline-neutral">&nbsp;</span>
155
+ <span class="cline-any cline-neutral">&nbsp;</span>
156
+ <span class="cline-any cline-neutral">&nbsp;</span>
143
157
  <span class="cline-any cline-neutral">&nbsp;</span>
144
158
  <span class="cline-any cline-neutral">&nbsp;</span>
145
159
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -198,7 +212,9 @@
198
212
  <span class="cline-any cline-yes">1x</span>
199
213
  <span class="cline-any cline-neutral">&nbsp;</span>
200
214
  <span class="cline-any cline-neutral">&nbsp;</span>
215
+ <span class="cline-any cline-neutral">&nbsp;</span>
201
216
  <span class="cline-any cline-yes">2x</span>
217
+ <span class="cline-any cline-neutral">&nbsp;</span>
202
218
  <span class="cline-any cline-yes">1x</span>
203
219
  <span class="cline-any cline-neutral">&nbsp;</span>
204
220
  <span class="cline-any cline-yes">1x</span>
@@ -216,7 +232,10 @@
216
232
  <span class="cline-any cline-neutral">&nbsp;</span>
217
233
  <span class="cline-any cline-neutral">&nbsp;</span>
218
234
  <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { TaskRunner } from "./TaskRunner.js";
219
- import { RunnerEventPayloads, RunnerEventListener } from "./contracts/RunnerEvents.js";
235
+ import {
236
+ RunnerEventPayloads,
237
+ RunnerEventListener,
238
+ } from "./contracts/RunnerEvents.js";
220
239
  import { IExecutionStrategy } from "./strategies/IExecutionStrategy.js";
221
240
  &nbsp;
222
241
  /**
@@ -226,7 +245,10 @@ export class TaskRunnerBuilder&lt;TContext&gt; {
226
245
  private context: TContext;
227
246
  private strategy?: IExecutionStrategy&lt;TContext&gt;;
228
247
  private listeners: {
229
- [K in keyof RunnerEventPayloads&lt;TContext&gt;]?: RunnerEventListener&lt;TContext, K&gt;[];
248
+ [K in keyof RunnerEventPayloads&lt;TContext&gt;]?: RunnerEventListener&lt;
249
+ TContext,
250
+ K
251
+ &gt;[];
230
252
  } = {};
231
253
  &nbsp;
232
254
  /**
@@ -274,7 +296,9 @@ export class TaskRunnerBuilder&lt;TContext&gt; {
274
296
  runner.setExecutionStrategy(this.strategy);
275
297
  }
276
298
  &nbsp;
277
- (Object.keys(this.listeners) as Array&lt;keyof RunnerEventPayloads&lt;TContext&gt;&gt;).forEach((event) =&gt; {
299
+ (
300
+ Object.keys(this.listeners) as Array&lt;keyof RunnerEventPayloads&lt;TContext&gt;&gt;
301
+ ).forEach((event) =&gt; {
278
302
  const callbacks = this.listeners[event];
279
303
  // callbacks is always defined because we are iterating keys of the object
280
304
  callbacks!.forEach((callback) =&gt;
@@ -298,7 +322,7 @@ export class TaskRunnerBuilder&lt;TContext&gt; {
298
322
  <div class='footer quiet pad2 space-top1 center small'>
299
323
  Code coverage generated by
300
324
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
301
- at 2026-01-18T20:19:46.886Z
325
+ at 2026-01-18T21:02:31.387Z
302
326
  </div>
303
327
  <script src="../prettify.js"></script>
304
328
  <script>
@@ -139,7 +139,7 @@ export interface TaskRunnerExecutionConfig {
139
139
  <div class='footer quiet pad2 space-top1 center small'>
140
140
  Code coverage generated by
141
141
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
142
- at 2026-01-18T20:19:46.886Z
142
+ at 2026-01-18T21:02:31.387Z
143
143
  </div>
144
144
  <script src="../prettify.js"></script>
145
145
  <script>
@@ -496,7 +496,7 @@ export class TaskStateManager&lt;TContext&gt; {
496
496
  <div class='footer quiet pad2 space-top1 center small'>
497
497
  Code coverage generated by
498
498
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
499
- at 2026-01-18T20:19:46.886Z
499
+ at 2026-01-18T21:02:31.387Z
500
500
  </div>
501
501
  <script src="../prettify.js"></script>
502
502
  <script>
@@ -203,7 +203,10 @@
203
203
  <a name='L138'></a><a href='#L138'>138</a>
204
204
  <a name='L139'></a><a href='#L139'>139</a>
205
205
  <a name='L140'></a><a href='#L140'>140</a>
206
- <a name='L141'></a><a href='#L141'>141</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
207
210
  <span class="cline-any cline-neutral">&nbsp;</span>
208
211
  <span class="cline-any cline-neutral">&nbsp;</span>
209
212
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -247,6 +250,8 @@
247
250
  <span class="cline-any cline-neutral">&nbsp;</span>
248
251
  <span class="cline-any cline-yes">47x</span>
249
252
  <span class="cline-any cline-yes">2x</span>
253
+ <span class="cline-any cline-neutral">&nbsp;</span>
254
+ <span class="cline-any cline-neutral">&nbsp;</span>
250
255
  <span class="cline-any cline-yes">2x</span>
251
256
  <span class="cline-any cline-yes">2x</span>
252
257
  <span class="cline-any cline-yes">2x</span>
@@ -331,6 +336,7 @@
331
336
  <span class="cline-any cline-neutral">&nbsp;</span>
332
337
  <span class="cline-any cline-yes">119x</span>
333
338
  <span class="cline-any cline-neutral">&nbsp;</span>
339
+ <span class="cline-any cline-neutral">&nbsp;</span>
334
340
  <span class="cline-any cline-yes">119x</span>
335
341
  <span class="cline-any cline-neutral">&nbsp;</span>
336
342
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -386,7 +392,9 @@ export class WorkflowExecutor&lt;TContext&gt; {
386
392
  &nbsp;
387
393
  // Check if already aborted
388
394
  if (signal?.aborted) {
389
- this.stateManager.cancelAllPending("Workflow cancelled before execution started.");
395
+ this.stateManager.cancelAllPending(
396
+ "Workflow cancelled before execution started."
397
+ );
390
398
  const results = this.stateManager.getResults();
391
399
  this.eventBus.emit("workflowEnd", { context: this.context, results });
392
400
  return results;
@@ -400,7 +408,7 @@ export class WorkflowExecutor&lt;TContext&gt; {
400
408
  };
401
409
  &nbsp;
402
410
  if (signal) {
403
- signal.addEventListener("abort", onAbort);
411
+ signal.addEventListener("abort", onAbort);
404
412
  }
405
413
  &nbsp;
406
414
  try {
@@ -422,10 +430,10 @@ export class WorkflowExecutor&lt;TContext&gt; {
422
430
  }
423
431
  &nbsp;
424
432
  if (signal?.aborted) {
425
- this.stateManager.cancelAllPending("Workflow cancelled.");
433
+ this.stateManager.cancelAllPending("Workflow cancelled.");
426
434
  } else {
427
- // After a task finishes, check for new work
428
- this.processLoop(executingPromises, signal);
435
+ // After a task finishes, check for new work
436
+ this.processLoop(executingPromises, signal);
429
437
  }
430
438
  }
431
439
  &nbsp;
@@ -469,14 +477,15 @@ export class WorkflowExecutor&lt;TContext&gt; {
469
477
  &nbsp;
470
478
  this.stateManager.markRunning(step);
471
479
  &nbsp;
472
- const taskPromise = this.strategy.execute(step, this.context, signal)
480
+ const taskPromise = this.strategy
481
+ .execute(step, this.context, signal)
473
482
  .then((result) =&gt; {
474
- this.stateManager.markCompleted(step, result);
483
+ this.stateManager.markCompleted(step, result);
475
484
  })
476
485
  .finally(() =&gt; {
477
- executingPromises.delete(taskPromise);
478
- // When a task finishes, we try to run more
479
- this.processLoop(executingPromises, signal);
486
+ executingPromises.delete(taskPromise);
487
+ // When a task finishes, we try to run more
488
+ this.processLoop(executingPromises, signal);
480
489
  });
481
490
  &nbsp;
482
491
  executingPromises.add(taskPromise);
@@ -490,7 +499,7 @@ export class WorkflowExecutor&lt;TContext&gt; {
490
499
  <div class='footer quiet pad2 space-top1 center small'>
491
500
  Code coverage generated by
492
501
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
493
- at 2026-01-18T20:19:46.886Z
502
+ at 2026-01-18T21:02:31.387Z
494
503
  </div>
495
504
  <script src="../prettify.js"></script>
496
505
  <script>
@@ -202,7 +202,7 @@ export type ListenerMap&lt;TContext&gt; = {
202
202
  <div class='footer quiet pad2 space-top1 center small'>
203
203
  Code coverage generated by
204
204
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
205
- at 2026-01-18T20:19:46.886Z
205
+ at 2026-01-18T21:02:31.387Z
206
206
  </div>
207
207
  <script src="../../prettify.js"></script>
208
208
  <script>
@@ -101,7 +101,7 @@
101
101
  <div class='footer quiet pad2 space-top1 center small'>
102
102
  Code coverage generated by
103
103
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
104
- at 2026-01-18T20:19:46.886Z
104
+ at 2026-01-18T21:02:31.387Z
105
105
  </div>
106
106
  <script src="../../prettify.js"></script>
107
107
  <script>
@@ -25,7 +25,7 @@
25
25
  <div class='fl pad1y space-right2'>
26
26
  <span class="strong">100% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>230/230</span>
28
+ <span class='fraction'>231/231</span>
29
29
  </div>
30
30
 
31
31
 
@@ -39,14 +39,14 @@
39
39
  <div class='fl pad1y space-right2'>
40
40
  <span class="strong">100% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>43/43</span>
42
+ <span class='fraction'>44/44</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
47
  <span class="strong">100% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>226/226</span>
49
+ <span class='fraction'>228/228</span>
50
50
  </div>
51
51
 
52
52
 
@@ -84,13 +84,13 @@
84
84
  <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
85
85
  </td>
86
86
  <td data-value="100" class="pct high">100%</td>
87
- <td data-value="15" class="abs high">15/15</td>
87
+ <td data-value="16" class="abs high">16/16</td>
88
88
  <td data-value="100" class="pct high">100%</td>
89
89
  <td data-value="8" class="abs high">8/8</td>
90
90
  <td data-value="100" class="pct high">100%</td>
91
- <td data-value="4" class="abs high">4/4</td>
91
+ <td data-value="5" class="abs high">5/5</td>
92
92
  <td data-value="100" class="pct high">100%</td>
93
- <td data-value="15" class="abs high">15/15</td>
93
+ <td data-value="16" class="abs high">16/16</td>
94
94
  </tr>
95
95
 
96
96
  <tr>
@@ -120,7 +120,7 @@
120
120
  <td data-value="100" class="pct high">100%</td>
121
121
  <td data-value="5" class="abs high">5/5</td>
122
122
  <td data-value="100" class="pct high">100%</td>
123
- <td data-value="54" class="abs high">54/54</td>
123
+ <td data-value="55" class="abs high">55/55</td>
124
124
  </tr>
125
125
 
126
126
  <tr>
@@ -206,7 +206,7 @@
206
206
  <div class='footer quiet pad2 space-top1 center small'>
207
207
  Code coverage generated by
208
208
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
209
- at 2026-01-18T20:19:46.886Z
209
+ at 2026-01-18T21:02:31.387Z
210
210
  </div>
211
211
  <script src="../prettify.js"></script>
212
212
  <script>
@@ -132,9 +132,9 @@ import { TaskResult } from "../TaskResult.js";
132
132
  /**
133
133
  * Execution strategy that simulates task execution without running the actual logic.
134
134
  */
135
- export class DryRunExecutionStrategy&lt;TContext&gt;
136
- implements IExecutionStrategy&lt;TContext&gt;
137
- {
135
+ export class DryRunExecutionStrategy&lt;
136
+ TContext,
137
+ &gt; implements IExecutionStrategy&lt;TContext&gt; {
138
138
  /**
139
139
  * Simulates execution by returning a success result immediately.
140
140
  * @param step The task step (ignored).
@@ -163,7 +163,7 @@ export class DryRunExecutionStrategy&lt;TContext&gt;
163
163
  <div class='footer quiet pad2 space-top1 center small'>
164
164
  Code coverage generated by
165
165
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
166
- at 2026-01-18T20:19:46.886Z
166
+ at 2026-01-18T21:02:31.387Z
167
167
  </div>
168
168
  <script src="../../prettify.js"></script>
169
169
  <script>
@@ -153,7 +153,15 @@
153
153
  <a name='L88'></a><a href='#L88'>88</a>
154
154
  <a name='L89'></a><a href='#L89'>89</a>
155
155
  <a name='L90'></a><a href='#L90'>90</a>
156
- <a name='L91'></a><a href='#L91'>91</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
163
+ <span class="cline-any cline-neutral">&nbsp;</span>
164
+ <span class="cline-any cline-neutral">&nbsp;</span>
157
165
  <span class="cline-any cline-neutral">&nbsp;</span>
158
166
  <span class="cline-any cline-neutral">&nbsp;</span>
159
167
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -186,6 +194,10 @@
186
194
  <span class="cline-any cline-yes">12x</span>
187
195
  <span class="cline-any cline-neutral">&nbsp;</span>
188
196
  <span class="cline-any cline-yes">12x</span>
197
+ <span class="cline-any cline-neutral">&nbsp;</span>
198
+ <span class="cline-any cline-neutral">&nbsp;</span>
199
+ <span class="cline-any cline-neutral">&nbsp;</span>
200
+ <span class="cline-any cline-neutral">&nbsp;</span>
189
201
  <span class="cline-any cline-yes">1x</span>
190
202
  <span class="cline-any cline-neutral">&nbsp;</span>
191
203
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -250,7 +262,9 @@ import { TaskResult } from "../TaskResult.js";
250
262
  /**
251
263
  * Execution strategy that retries tasks upon failure based on their retry configuration.
252
264
  */
253
- export class RetryingExecutionStrategy&lt;TContext&gt; implements IExecutionStrategy&lt;TContext&gt; {
265
+ export class RetryingExecutionStrategy&lt;
266
+ TContext,
267
+ &gt; implements IExecutionStrategy&lt;TContext&gt; {
254
268
  constructor(private innerStrategy: IExecutionStrategy&lt;TContext&gt;) {}
255
269
  &nbsp;
256
270
  async execute(
@@ -275,7 +289,11 @@ export class RetryingExecutionStrategy&lt;TContext&gt; implements IExecutionStra
275
289
  &nbsp;
276
290
  const result = await this.innerStrategy.execute(step, context, signal);
277
291
  &nbsp;
278
- if (result.status === "success" || result.status === "cancelled" || result.status === "skipped") {
292
+ if (
293
+ result.status === "success" ||
294
+ result.status === "cancelled" ||
295
+ result.status === "skipped"
296
+ ) {
279
297
  return result;
280
298
  }
281
299
  &nbsp;
@@ -296,13 +314,13 @@ export class RetryingExecutionStrategy&lt;TContext&gt; implements IExecutionStra
296
314
  try {
297
315
  await this.sleep(delay, signal);
298
316
  } catch (e) {
299
- if (signal?.aborted) {
300
- return {
301
- status: "cancelled",
302
- message: "Task cancelled during retry delay",
303
- };
304
- }
305
- throw e;
317
+ if (signal?.aborted) {
318
+ return {
319
+ status: "cancelled",
320
+ message: "Task cancelled during retry delay",
321
+ };
322
+ }
323
+ throw e;
306
324
  }
307
325
  }
308
326
  }
@@ -340,7 +358,7 @@ export class RetryingExecutionStrategy&lt;TContext&gt; implements IExecutionStra
340
358
  <div class='footer quiet pad2 space-top1 center small'>
341
359
  Code coverage generated by
342
360
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
343
- at 2026-01-18T20:19:46.886Z
361
+ at 2026-01-18T21:02:31.387Z
344
362
  </div>
345
363
  <script src="../../prettify.js"></script>
346
364
  <script>
@@ -140,9 +140,9 @@ import { TaskResult } from "../TaskResult.js";
140
140
  /**
141
141
  * Standard execution strategy that runs the task's run method.
142
142
  */
143
- export class StandardExecutionStrategy&lt;TContext&gt;
144
- implements IExecutionStrategy&lt;TContext&gt;
145
- {
143
+ export class StandardExecutionStrategy&lt;
144
+ TContext,
145
+ &gt; implements IExecutionStrategy&lt;TContext&gt; {
146
146
  async execute(
147
147
  step: TaskStep&lt;TContext&gt;,
148
148
  context: TContext,
@@ -154,7 +154,7 @@ export class StandardExecutionStrategy&lt;TContext&gt;
154
154
  // Check if error is due to abort
155
155
  if (
156
156
  signal?.aborted &amp;&amp;
157
- (e instanceof Error &amp;&amp; e.name === "AbortError" || signal.reason === e)
157
+ ((e instanceof Error &amp;&amp; e.name === "AbortError") || signal.reason === e)
158
158
  ) {
159
159
  return {
160
160
  status: "cancelled",
@@ -175,7 +175,7 @@ export class StandardExecutionStrategy&lt;TContext&gt;
175
175
  <div class='footer quiet pad2 space-top1 center small'>
176
176
  Code coverage generated by
177
177
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
178
- at 2026-01-18T20:19:46.886Z
178
+ at 2026-01-18T21:02:31.387Z
179
179
  </div>
180
180
  <script src="../../prettify.js"></script>
181
181
  <script>
@@ -131,7 +131,7 @@
131
131
  <div class='footer quiet pad2 space-top1 center small'>
132
132
  Code coverage generated by
133
133
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
134
- at 2026-01-18T20:19:46.886Z
134
+ at 2026-01-18T21:02:31.387Z
135
135
  </div>
136
136
  <script src="../../prettify.js"></script>
137
137
  <script>