@calmo/task-runner 3.4.0 → 3.5.0

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 (95) 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 +21 -16
  8. package/CHANGELOG.md +192 -174
  9. package/README.md +95 -88
  10. package/coverage/coverage-final.json +9 -9
  11. package/coverage/index.html +9 -9
  12. package/coverage/lcov-report/index.html +9 -9
  13. package/coverage/lcov-report/src/EventBus.ts.html +30 -24
  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 +82 -52
  20. package/coverage/lcov-report/src/WorkflowExecutor.ts.html +210 -66
  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 +16 -16
  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 +7 -7
  27. package/coverage/lcov-report/src/strategies/index.html +1 -1
  28. package/coverage/lcov.info +426 -383
  29. package/coverage/src/EventBus.ts.html +30 -24
  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 +82 -52
  36. package/coverage/src/WorkflowExecutor.ts.html +210 -66
  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 +16 -16
  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 +7 -7
  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/TaskStateManager.d.ts +6 -0
  52. package/dist/TaskStateManager.js +11 -2
  53. package/dist/TaskStateManager.js.map +1 -1
  54. package/dist/TaskStep.d.ts +5 -0
  55. package/dist/WorkflowExecutor.js +49 -7
  56. package/dist/WorkflowExecutor.js.map +1 -1
  57. package/dist/strategies/RetryingExecutionStrategy.js +3 -1
  58. package/dist/strategies/RetryingExecutionStrategy.js.map +1 -1
  59. package/dist/strategies/StandardExecutionStrategy.js +1 -1
  60. package/dist/strategies/StandardExecutionStrategy.js.map +1 -1
  61. package/openspec/AGENTS.md +81 -15
  62. package/openspec/changes/archive/2026-01-18-add-concurrency-control/proposal.md +7 -4
  63. package/openspec/changes/archive/2026-01-18-add-concurrency-control/tasks.md +1 -0
  64. package/openspec/changes/archive/2026-01-18-add-external-task-cancellation/proposal.md +4 -1
  65. package/openspec/changes/archive/2026-01-18-add-external-task-cancellation/tasks.md +2 -1
  66. package/openspec/changes/archive/2026-01-18-add-integration-tests/proposal.md +3 -0
  67. package/openspec/changes/archive/2026-01-18-add-integration-tests/tasks.md +1 -0
  68. package/openspec/changes/archive/2026-01-18-add-task-retry-policy/proposal.md +3 -0
  69. package/openspec/changes/archive/2026-01-18-add-task-retry-policy/tasks.md +1 -0
  70. package/openspec/changes/archive/2026-01-18-add-workflow-preview/proposal.md +3 -0
  71. package/openspec/changes/archive/2026-01-18-add-workflow-preview/tasks.md +1 -0
  72. package/openspec/changes/archive/2026-01-18-feat-conditional-execution/proposal.md +35 -0
  73. package/openspec/changes/archive/2026-01-18-feat-conditional-execution/tasks.md +32 -0
  74. package/openspec/changes/archive/2026-01-18-refactor-core-architecture/proposal.md +3 -0
  75. package/openspec/changes/archive/2026-01-18-refactor-core-architecture/tasks.md +1 -0
  76. package/openspec/changes/feat-per-task-timeout/proposal.md +11 -6
  77. package/openspec/changes/feat-per-task-timeout/tasks.md +1 -1
  78. package/openspec/project.md +21 -15
  79. package/package.json +2 -1
  80. package/src/EventBus.ts +18 -16
  81. package/src/TaskGraph.ts +8 -8
  82. package/src/TaskGraphValidationError.ts +4 -1
  83. package/src/TaskGraphValidator.ts +148 -143
  84. package/src/TaskRunner.ts +42 -41
  85. package/src/TaskRunnerBuilder.ts +11 -3
  86. package/src/TaskStateManager.ts +12 -2
  87. package/src/TaskStep.ts +6 -0
  88. package/src/WorkflowExecutor.ts +63 -15
  89. package/src/contracts/ITaskGraphValidator.ts +12 -12
  90. package/src/contracts/ValidationError.ts +6 -6
  91. package/src/contracts/ValidationResult.ts +4 -4
  92. package/src/strategies/DryRunExecutionStrategy.ts +3 -3
  93. package/src/strategies/RetryingExecutionStrategy.ts +15 -9
  94. package/src/strategies/StandardExecutionStrategy.ts +4 -4
  95. package/test-report.xml +132 -108
@@ -25,28 +25,28 @@
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'>46/46</span>
28
+ <span class='fraction'>64/64</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
33
  <span class="strong">100% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>16/16</span>
35
+ <span class='fraction'>31/31</span>
36
36
  </div>
37
37
 
38
38
 
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'>6/6</span>
42
+ <span class='fraction'>7/7</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'>46/46</span>
49
+ <span class='fraction'>64/64</span>
50
50
  </div>
51
51
 
52
52
 
@@ -203,7 +203,55 @@
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>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
207
255
  <span class="cline-any cline-neutral">&nbsp;</span>
208
256
  <span class="cline-any cline-neutral">&nbsp;</span>
209
257
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -214,7 +262,7 @@
214
262
  <span class="cline-any cline-neutral">&nbsp;</span>
215
263
  <span class="cline-any cline-neutral">&nbsp;</span>
216
264
  <span class="cline-any cline-neutral">&nbsp;</span>
217
- <span class="cline-any cline-yes">47x</span>
265
+ <span class="cline-any cline-yes">58x</span>
218
266
  <span class="cline-any cline-neutral">&nbsp;</span>
219
267
  <span class="cline-any cline-neutral">&nbsp;</span>
220
268
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -224,11 +272,11 @@
224
272
  <span class="cline-any cline-neutral">&nbsp;</span>
225
273
  <span class="cline-any cline-neutral">&nbsp;</span>
226
274
  <span class="cline-any cline-neutral">&nbsp;</span>
227
- <span class="cline-any cline-yes">47x</span>
228
- <span class="cline-any cline-yes">47x</span>
229
- <span class="cline-any cline-yes">47x</span>
230
- <span class="cline-any cline-yes">47x</span>
231
- <span class="cline-any cline-yes">47x</span>
275
+ <span class="cline-any cline-yes">58x</span>
276
+ <span class="cline-any cline-yes">58x</span>
277
+ <span class="cline-any cline-yes">58x</span>
278
+ <span class="cline-any cline-yes">58x</span>
279
+ <span class="cline-any cline-yes">58x</span>
232
280
  <span class="cline-any cline-neutral">&nbsp;</span>
233
281
  <span class="cline-any cline-neutral">&nbsp;</span>
234
282
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -241,105 +289,153 @@
241
289
  <span class="cline-any cline-neutral">&nbsp;</span>
242
290
  <span class="cline-any cline-neutral">&nbsp;</span>
243
291
  <span class="cline-any cline-neutral">&nbsp;</span>
244
- <span class="cline-any cline-yes">47x</span>
245
- <span class="cline-any cline-yes">47x</span>
292
+ <span class="cline-any cline-yes">58x</span>
293
+ <span class="cline-any cline-yes">58x</span>
246
294
  <span class="cline-any cline-neutral">&nbsp;</span>
247
295
  <span class="cline-any cline-neutral">&nbsp;</span>
248
- <span class="cline-any cline-yes">47x</span>
249
- <span class="cline-any cline-yes">2x</span>
250
- <span class="cline-any cline-yes">2x</span>
251
- <span class="cline-any cline-yes">2x</span>
296
+ <span class="cline-any cline-yes">58x</span>
297
+ <span class="cline-any cline-yes">3x</span>
298
+ <span class="cline-any cline-neutral">&nbsp;</span>
299
+ <span class="cline-any cline-neutral">&nbsp;</span>
300
+ <span class="cline-any cline-yes">3x</span>
301
+ <span class="cline-any cline-yes">3x</span>
302
+ <span class="cline-any cline-yes">3x</span>
303
+ <span class="cline-any cline-neutral">&nbsp;</span>
304
+ <span class="cline-any cline-neutral">&nbsp;</span>
305
+ <span class="cline-any cline-yes">55x</span>
306
+ <span class="cline-any cline-neutral">&nbsp;</span>
307
+ <span class="cline-any cline-yes">55x</span>
308
+ <span class="cline-any cline-neutral">&nbsp;</span>
309
+ <span class="cline-any cline-yes">11x</span>
310
+ <span class="cline-any cline-neutral">&nbsp;</span>
311
+ <span class="cline-any cline-neutral">&nbsp;</span>
312
+ <span class="cline-any cline-yes">55x</span>
313
+ <span class="cline-any cline-yes">11x</span>
314
+ <span class="cline-any cline-neutral">&nbsp;</span>
315
+ <span class="cline-any cline-neutral">&nbsp;</span>
316
+ <span class="cline-any cline-yes">55x</span>
317
+ <span class="cline-any cline-neutral">&nbsp;</span>
318
+ <span class="cline-any cline-yes">55x</span>
319
+ <span class="cline-any cline-neutral">&nbsp;</span>
320
+ <span class="cline-any cline-yes">55x</span>
321
+ <span class="cline-any cline-neutral">&nbsp;</span>
322
+ <span class="cline-any cline-neutral">&nbsp;</span>
323
+ <span class="cline-any cline-neutral">&nbsp;</span>
324
+ <span class="cline-any cline-neutral">&nbsp;</span>
325
+ <span class="cline-any cline-neutral">&nbsp;</span>
326
+ <span class="cline-any cline-neutral">&nbsp;</span>
327
+ <span class="cline-any cline-neutral">&nbsp;</span>
328
+ <span class="cline-any cline-yes">102x</span>
252
329
  <span class="cline-any cline-yes">2x</span>
253
330
  <span class="cline-any cline-neutral">&nbsp;</span>
254
331
  <span class="cline-any cline-neutral">&nbsp;</span>
255
- <span class="cline-any cline-yes">45x</span>
332
+ <span class="cline-any cline-yes">100x</span>
256
333
  <span class="cline-any cline-neutral">&nbsp;</span>
257
- <span class="cline-any cline-yes">45x</span>
258
334
  <span class="cline-any cline-neutral">&nbsp;</span>
259
- <span class="cline-any cline-yes">9x</span>
335
+ <span class="cline-any cline-yes">100x</span>
336
+ <span class="cline-any cline-yes">11x</span>
260
337
  <span class="cline-any cline-neutral">&nbsp;</span>
261
338
  <span class="cline-any cline-neutral">&nbsp;</span>
262
- <span class="cline-any cline-yes">45x</span>
263
- <span class="cline-any cline-yes">9x</span>
339
+ <span class="cline-any cline-yes">89x</span>
264
340
  <span class="cline-any cline-neutral">&nbsp;</span>
265
341
  <span class="cline-any cline-neutral">&nbsp;</span>
266
- <span class="cline-any cline-yes">45x</span>
267
342
  <span class="cline-any cline-neutral">&nbsp;</span>
268
- <span class="cline-any cline-yes">45x</span>
269
343
  <span class="cline-any cline-neutral">&nbsp;</span>
270
- <span class="cline-any cline-yes">45x</span>
344
+ <span class="cline-any cline-yes">55x</span>
271
345
  <span class="cline-any cline-neutral">&nbsp;</span>
346
+ <span class="cline-any cline-yes">55x</span>
347
+ <span class="cline-any cline-yes">55x</span>
348
+ <span class="cline-any cline-yes">55x</span>
272
349
  <span class="cline-any cline-neutral">&nbsp;</span>
350
+ <span class="cline-any cline-yes">55x</span>
351
+ <span class="cline-any cline-yes">11x</span>
273
352
  <span class="cline-any cline-neutral">&nbsp;</span>
274
353
  <span class="cline-any cline-neutral">&nbsp;</span>
275
354
  <span class="cline-any cline-neutral">&nbsp;</span>
276
355
  <span class="cline-any cline-neutral">&nbsp;</span>
277
- <span class="cline-any cline-yes">79x</span>
278
- <span class="cline-any cline-yes">1x</span>
279
356
  <span class="cline-any cline-neutral">&nbsp;</span>
280
357
  <span class="cline-any cline-neutral">&nbsp;</span>
281
- <span class="cline-any cline-yes">78x</span>
282
358
  <span class="cline-any cline-neutral">&nbsp;</span>
283
359
  <span class="cline-any cline-neutral">&nbsp;</span>
284
- <span class="cline-any cline-yes">78x</span>
285
- <span class="cline-any cline-yes">9x</span>
286
360
  <span class="cline-any cline-neutral">&nbsp;</span>
287
361
  <span class="cline-any cline-neutral">&nbsp;</span>
288
- <span class="cline-any cline-yes">69x</span>
289
362
  <span class="cline-any cline-neutral">&nbsp;</span>
363
+ <span class="cline-any cline-yes">273x</span>
290
364
  <span class="cline-any cline-neutral">&nbsp;</span>
291
365
  <span class="cline-any cline-neutral">&nbsp;</span>
366
+ <span class="cline-any cline-yes">273x</span>
367
+ <span class="cline-any cline-yes">129x</span>
292
368
  <span class="cline-any cline-neutral">&nbsp;</span>
293
- <span class="cline-any cline-yes">45x</span>
294
369
  <span class="cline-any cline-neutral">&nbsp;</span>
295
- <span class="cline-any cline-yes">45x</span>
296
- <span class="cline-any cline-yes">45x</span>
297
- <span class="cline-any cline-yes">45x</span>
298
370
  <span class="cline-any cline-neutral">&nbsp;</span>
299
- <span class="cline-any cline-yes">45x</span>
300
- <span class="cline-any cline-yes">9x</span>
371
+ <span class="cline-any cline-yes">273x</span>
372
+ <span class="cline-any cline-yes">141x</span>
301
373
  <span class="cline-any cline-neutral">&nbsp;</span>
302
374
  <span class="cline-any cline-neutral">&nbsp;</span>
303
375
  <span class="cline-any cline-neutral">&nbsp;</span>
376
+ <span class="cline-any cline-yes">12x</span>
304
377
  <span class="cline-any cline-neutral">&nbsp;</span>
305
378
  <span class="cline-any cline-neutral">&nbsp;</span>
379
+ <span class="cline-any cline-yes">129x</span>
306
380
  <span class="cline-any cline-neutral">&nbsp;</span>
381
+ <span class="cline-any cline-yes">129x</span>
382
+ <span class="cline-any cline-yes">129x</span>
383
+ <span class="cline-any cline-yes">129x</span>
384
+ <span class="cline-any cline-yes">7x</span>
385
+ <span class="cline-any cline-yes">7x</span>
307
386
  <span class="cline-any cline-neutral">&nbsp;</span>
387
+ <span class="cline-any cline-yes">7x</span>
388
+ <span class="cline-any cline-yes">1x</span>
308
389
  <span class="cline-any cline-neutral">&nbsp;</span>
309
390
  <span class="cline-any cline-neutral">&nbsp;</span>
310
391
  <span class="cline-any cline-neutral">&nbsp;</span>
392
+ <span class="cline-any cline-yes">1x</span>
311
393
  <span class="cline-any cline-neutral">&nbsp;</span>
312
- <span class="cline-any cline-yes">233x</span>
313
394
  <span class="cline-any cline-neutral">&nbsp;</span>
395
+ <span class="cline-any cline-yes">4x</span>
396
+ <span class="cline-any cline-yes">3x</span>
314
397
  <span class="cline-any cline-neutral">&nbsp;</span>
315
- <span class="cline-any cline-yes">233x</span>
316
- <span class="cline-any cline-yes">119x</span>
317
398
  <span class="cline-any cline-neutral">&nbsp;</span>
318
399
  <span class="cline-any cline-neutral">&nbsp;</span>
400
+ <span class="cline-any cline-yes">3x</span>
401
+ <span class="cline-any cline-yes">3x</span>
319
402
  <span class="cline-any cline-neutral">&nbsp;</span>
320
- <span class="cline-any cline-yes">233x</span>
321
- <span class="cline-any cline-yes">130x</span>
322
403
  <span class="cline-any cline-neutral">&nbsp;</span>
323
404
  <span class="cline-any cline-neutral">&nbsp;</span>
405
+ <span class="cline-any cline-yes">2x</span>
406
+ <span class="cline-any cline-neutral">&nbsp;</span>
407
+ <span class="cline-any cline-neutral">&nbsp;</span>
408
+ <span class="cline-any cline-neutral">&nbsp;</span>
409
+ <span class="cline-any cline-neutral">&nbsp;</span>
410
+ <span class="cline-any cline-neutral">&nbsp;</span>
411
+ <span class="cline-any cline-neutral">&nbsp;</span>
412
+ <span class="cline-any cline-neutral">&nbsp;</span>
413
+ <span class="cline-any cline-yes">2x</span>
414
+ <span class="cline-any cline-yes">2x</span>
324
415
  <span class="cline-any cline-neutral">&nbsp;</span>
325
- <span class="cline-any cline-yes">11x</span>
416
+ <span class="cline-any cline-neutral">&nbsp;</span>
417
+ <span class="cline-any cline-yes">123x</span>
418
+ <span class="cline-any cline-yes">1x</span>
326
419
  <span class="cline-any cline-neutral">&nbsp;</span>
327
420
  <span class="cline-any cline-neutral">&nbsp;</span>
328
- <span class="cline-any cline-yes">119x</span>
329
421
  <span class="cline-any cline-neutral">&nbsp;</span>
330
- <span class="cline-any cline-yes">119x</span>
422
+ <span class="cline-any cline-yes">1x</span>
423
+ <span class="cline-any cline-neutral">&nbsp;</span>
331
424
  <span class="cline-any cline-neutral">&nbsp;</span>
332
- <span class="cline-any cline-yes">119x</span>
425
+ <span class="cline-any cline-yes">122x</span>
333
426
  <span class="cline-any cline-neutral">&nbsp;</span>
334
- <span class="cline-any cline-yes">119x</span>
427
+ <span class="cline-any cline-yes">122x</span>
335
428
  <span class="cline-any cline-neutral">&nbsp;</span>
336
429
  <span class="cline-any cline-neutral">&nbsp;</span>
337
- <span class="cline-any cline-yes">119x</span>
430
+ <span class="cline-any cline-yes">122x</span>
338
431
  <span class="cline-any cline-neutral">&nbsp;</span>
339
- <span class="cline-any cline-yes">119x</span>
340
432
  <span class="cline-any cline-neutral">&nbsp;</span>
433
+ <span class="cline-any cline-yes">129x</span>
341
434
  <span class="cline-any cline-neutral">&nbsp;</span>
342
- <span class="cline-any cline-yes">119x</span>
435
+ <span class="cline-any cline-yes">129x</span>
436
+ <span class="cline-any cline-neutral">&nbsp;</span>
437
+ <span class="cline-any cline-neutral">&nbsp;</span>
438
+ <span class="cline-any cline-yes">129x</span>
343
439
  <span class="cline-any cline-neutral">&nbsp;</span>
344
440
  <span class="cline-any cline-neutral">&nbsp;</span>
345
441
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -386,7 +482,9 @@ export class WorkflowExecutor&lt;TContext&gt; {
386
482
  &nbsp;
387
483
  // Check if already aborted
388
484
  if (signal?.aborted) {
389
- this.stateManager.cancelAllPending("Workflow cancelled before execution started.");
485
+ this.stateManager.cancelAllPending(
486
+ "Workflow cancelled before execution started."
487
+ );
390
488
  const results = this.stateManager.getResults();
391
489
  this.eventBus.emit("workflowEnd", { context: this.context, results });
392
490
  return results;
@@ -400,7 +498,7 @@ export class WorkflowExecutor&lt;TContext&gt; {
400
498
  };
401
499
  &nbsp;
402
500
  if (signal) {
403
- signal.addEventListener("abort", onAbort);
501
+ signal.addEventListener("abort", onAbort);
404
502
  }
405
503
  &nbsp;
406
504
  try {
@@ -409,7 +507,8 @@ export class WorkflowExecutor&lt;TContext&gt; {
409
507
  &nbsp;
410
508
  while (
411
509
  this.stateManager.hasPendingTasks() ||
412
- this.stateManager.hasRunningTasks()
510
+ this.stateManager.hasRunningTasks() ||
511
+ executingPromises.size &gt; 0
413
512
  ) {
414
513
  // Safety check: if no tasks are running and we still have pending tasks,
415
514
  // it means we are stuck (e.g. cycle or unhandled dependency).
@@ -422,10 +521,10 @@ export class WorkflowExecutor&lt;TContext&gt; {
422
521
  }
423
522
  &nbsp;
424
523
  if (signal?.aborted) {
425
- this.stateManager.cancelAllPending("Workflow cancelled.");
524
+ this.stateManager.cancelAllPending("Workflow cancelled.");
426
525
  } else {
427
- // After a task finishes, check for new work
428
- this.processLoop(executingPromises, signal);
526
+ // After a task finishes, check for new work
527
+ this.processLoop(executingPromises, signal);
429
528
  }
430
529
  }
431
530
  &nbsp;
@@ -467,17 +566,62 @@ export class WorkflowExecutor&lt;TContext&gt; {
467
566
  &nbsp;
468
567
  const step = this.readyQueue.shift()!;
469
568
  &nbsp;
470
- this.stateManager.markRunning(step);
569
+ const taskPromise = (async () =&gt; {
570
+ try {
571
+ if (step.condition) {
572
+ const check = step.condition(this.context);
573
+ const shouldRun = check instanceof Promise ? await check : check;
574
+ &nbsp;
575
+ if (signal?.aborted) {
576
+ this.stateManager.markCompleted(step, {
577
+ status: "cancelled",
578
+ message: "Cancelled during condition evaluation.",
579
+ });
580
+ return;
581
+ }
582
+ &nbsp;
583
+ if (!shouldRun) {
584
+ const result: TaskResult = {
585
+ status: "skipped",
586
+ message: "Skipped by condition evaluation.",
587
+ };
588
+ this.stateManager.markSkipped(step, result);
589
+ return;
590
+ }
591
+ }
592
+ } catch (error) {
593
+ const result: TaskResult = {
594
+ status: "failure",
595
+ message:
596
+ error instanceof Error
597
+ ? error.message
598
+ : "Condition evaluation failed",
599
+ error: error instanceof Error ? error.message : String(error),
600
+ };
601
+ this.stateManager.markCompleted(step, result);
602
+ return;
603
+ }
604
+ &nbsp;
605
+ if (signal?.aborted) {
606
+ this.stateManager.markCompleted(step, {
607
+ status: "cancelled",
608
+ message: "Cancelled before execution started.",
609
+ });
610
+ return;
611
+ }
612
+ &nbsp;
613
+ this.stateManager.markRunning(step);
471
614
  &nbsp;
472
- const taskPromise = this.strategy.execute(step, this.context, signal)
473
- .then((result) =&gt; {
615
+ await this.strategy
616
+ .execute(step, this.context, signal)
617
+ .then((result) =&gt; {
474
618
  this.stateManager.markCompleted(step, result);
475
- })
476
- .finally(() =&gt; {
477
- executingPromises.delete(taskPromise);
478
- // When a task finishes, we try to run more
479
- this.processLoop(executingPromises, signal);
480
- });
619
+ });
620
+ })().finally(() =&gt; {
621
+ executingPromises.delete(taskPromise);
622
+ // When a task finishes, we try to run more
623
+ this.processLoop(executingPromises, signal);
624
+ });
481
625
  &nbsp;
482
626
  executingPromises.add(taskPromise);
483
627
  }
@@ -490,7 +634,7 @@ export class WorkflowExecutor&lt;TContext&gt; {
490
634
  <div class='footer quiet pad2 space-top1 center small'>
491
635
  Code coverage generated by
492
636
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
493
- at 2026-01-18T20:19:46.886Z
637
+ at 2026-01-18T23:00:28.573Z
494
638
  </div>
495
639
  <script src="../prettify.js"></script>
496
640
  <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-18T23:00:28.573Z
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-18T23:00:28.573Z
105
105
  </div>
106
106
  <script src="../../prettify.js"></script>
107
107
  <script>
@@ -25,28 +25,28 @@
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'>251/251</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
33
  <span class="strong">100% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>78/78</span>
35
+ <span class='fraction'>93/93</span>
36
36
  </div>
37
37
 
38
38
 
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'>46/46</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'>248/248</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>
@@ -174,13 +174,13 @@
174
174
  <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
175
175
  </td>
176
176
  <td data-value="100" class="pct high">100%</td>
177
- <td data-value="45" class="abs high">45/45</td>
177
+ <td data-value="47" class="abs high">47/47</td>
178
178
  <td data-value="100" class="pct high">100%</td>
179
179
  <td data-value="16" class="abs high">16/16</td>
180
180
  <td data-value="100" class="pct high">100%</td>
181
- <td data-value="9" class="abs high">9/9</td>
181
+ <td data-value="10" class="abs high">10/10</td>
182
182
  <td data-value="100" class="pct high">100%</td>
183
- <td data-value="45" class="abs high">45/45</td>
183
+ <td data-value="47" class="abs high">47/47</td>
184
184
  </tr>
185
185
 
186
186
  <tr>
@@ -189,13 +189,13 @@
189
189
  <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
190
190
  </td>
191
191
  <td data-value="100" class="pct high">100%</td>
192
- <td data-value="46" class="abs high">46/46</td>
192
+ <td data-value="64" class="abs high">64/64</td>
193
193
  <td data-value="100" class="pct high">100%</td>
194
- <td data-value="16" class="abs high">16/16</td>
194
+ <td data-value="31" class="abs high">31/31</td>
195
195
  <td data-value="100" class="pct high">100%</td>
196
- <td data-value="6" class="abs high">6/6</td>
196
+ <td data-value="7" class="abs high">7/7</td>
197
197
  <td data-value="100" class="pct high">100%</td>
198
- <td data-value="46" class="abs high">46/46</td>
198
+ <td data-value="64" class="abs high">64/64</td>
199
199
  </tr>
200
200
 
201
201
  </tbody>
@@ -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-18T23:00:28.573Z
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-18T23:00:28.573Z
167
167
  </div>
168
168
  <script src="../../prettify.js"></script>
169
169
  <script>