@calmo/task-runner 4.2.0 → 4.3.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 (40) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +24 -0
  3. package/dist/EventBus.js +3 -2
  4. package/dist/EventBus.js.map +1 -1
  5. package/dist/PluginManager.d.ts +1 -1
  6. package/dist/PluginManager.js +5 -4
  7. package/dist/PluginManager.js.map +1 -1
  8. package/dist/TaskRunner.js +18 -16
  9. package/dist/TaskRunner.js.map +1 -1
  10. package/dist/TaskStateManager.d.ts +1 -0
  11. package/dist/TaskStateManager.js +13 -1
  12. package/dist/TaskStateManager.js.map +1 -1
  13. package/dist/TaskStep.d.ts +12 -0
  14. package/dist/strategies/DryRunExecutionStrategy.js +2 -2
  15. package/dist/strategies/DryRunExecutionStrategy.js.map +1 -1
  16. package/dist/strategies/StandardExecutionStrategy.js +43 -1
  17. package/dist/strategies/StandardExecutionStrategy.js.map +1 -1
  18. package/openspec/changes/feat-task-caching/design.md +34 -0
  19. package/openspec/changes/feat-task-caching/proposal.md +18 -0
  20. package/openspec/changes/feat-task-caching/specs/task-runner/spec.md +58 -0
  21. package/openspec/changes/feat-task-caching/tasks.md +24 -0
  22. package/openspec/proposals/feat-matrix-execution/proposal.md +23 -0
  23. package/openspec/proposals/feat-matrix-execution/specs/task-runner/spec.md +47 -0
  24. package/openspec/proposals/feat-matrix-execution/tasks.md +11 -0
  25. package/openspec/proposals/feat-task-observability/proposal.md +16 -0
  26. package/openspec/proposals/feat-task-observability/specs/task-runner/spec.md +14 -0
  27. package/openspec/proposals/feat-task-observability/tasks.md +7 -0
  28. package/package.json +1 -1
  29. package/src/EventBus.ts +4 -7
  30. package/src/PluginManager.ts +6 -4
  31. package/src/TaskRunner.ts +20 -16
  32. package/src/TaskStateManager.ts +11 -1
  33. package/src/TaskStep.ts +14 -0
  34. package/src/strategies/DryRunExecutionStrategy.ts +2 -2
  35. package/src/strategies/StandardExecutionStrategy.ts +48 -1
  36. /package/openspec/changes/{feat-continue-on-error → archive/2026-02-18-feat-continue-on-error}/proposal.md +0 -0
  37. /package/openspec/changes/{feat-continue-on-error → archive/2026-02-18-feat-continue-on-error}/tasks.md +0 -0
  38. /package/openspec/changes/{feat-per-task-timeout → archive/2026-02-25-feat-per-task-timeout}/proposal.md +0 -0
  39. /package/openspec/changes/{feat-per-task-timeout → archive/2026-02-25-feat-per-task-timeout}/specs/task-runner/spec.md +0 -0
  40. /package/openspec/changes/{feat-per-task-timeout → archive/2026-02-25-feat-per-task-timeout}/tasks.md +0 -0
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "4.2.0"
2
+ ".": "4.3.0"
3
3
  }
package/CHANGELOG.md CHANGED
@@ -18,6 +18,30 @@
18
18
  * refactor: Refactor TaskRunner to reduce cognitive complexity (#89) ([95c67d9](https://github.com/thalesraymond/task-runner/commit/95c67d9)), closes [#89](https://github.com/thalesraymond/task-runner/issues/89)
19
19
  * Refactor TaskGraphValidator to address SonarCloud issues (#88) ([77c1538](https://github.com/thalesraymond/task-runner/commit/77c1538)), closes [#88](https://github.com/thalesraymond/task-runner/issues/88)
20
20
 
21
+ ## [4.3.0](https://github.com/thalesraymond/task-runner/compare/task-runner-v4.2.0...task-runner-v4.3.0) (2026-03-14)
22
+
23
+
24
+ ### Features
25
+
26
+ * add continueOnError support ([#164](https://github.com/thalesraymond/task-runner/issues/164)) ([50dfb38](https://github.com/thalesraymond/task-runner/commit/50dfb3877b0edd1f233435b2d0a9c9046b30b94d))
27
+ * add per-task timeout support ([#174](https://github.com/thalesraymond/task-runner/issues/174)) ([c73abf3](https://github.com/thalesraymond/task-runner/commit/c73abf3002c8e33dbc524fe570b79fe6466839a7))
28
+
29
+
30
+ ### Bug Fixes
31
+
32
+ * filter non-promises before calling Promise.all in PluginManager ([#200](https://github.com/thalesraymond/task-runner/issues/200)) ([e4bd215](https://github.com/thalesraymond/task-runner/commit/e4bd215b2fe0223ec59e85346a4162eff77dc138))
33
+ * **strategies:** remove redundant Promise.resolve in DryRunExecutionStrategy ([#193](https://github.com/thalesraymond/task-runner/issues/193)) ([42f6185](https://github.com/thalesraymond/task-runner/commit/42f61858413c3e0c50c2c698251ef1904d30a0da))
34
+
35
+
36
+ ### Performance Improvements
37
+
38
+ * fix pending Promise memory leak in StandardExecutionStrategy ([#201](https://github.com/thalesraymond/task-runner/issues/201)) ([87223b3](https://github.com/thalesraymond/task-runner/commit/87223b3d7facd067604602ef995bbdcc165e8fd6))
39
+ * optimize getMermaidGraph duplicate tracking ([#188](https://github.com/thalesraymond/task-runner/issues/188)) ([f114024](https://github.com/thalesraymond/task-runner/commit/f11402446732db6180cb9b4620f2c7ee53d47a9f))
40
+ * optimize Mermaid graph generation ([#187](https://github.com/thalesraymond/task-runner/issues/187)) ([9b8117b](https://github.com/thalesraymond/task-runner/commit/9b8117ba53613d1b780886afbfb85d1b9b319fa8))
41
+ * optimize Mermaid graph string generation overhead in TaskRunner ([#189](https://github.com/thalesraymond/task-runner/issues/189)) ([513f343](https://github.com/thalesraymond/task-runner/commit/513f343ba2bfdb5a4c362a55da81d26741e5bb6c))
42
+ * parallelize plugin initialization in PluginManager ([#171](https://github.com/thalesraymond/task-runner/issues/171)) ([d39781f](https://github.com/thalesraymond/task-runner/commit/d39781fd1af28d2ffeb320745a386c95d74bd3f3))
43
+ * **TaskStateManager:** optimize ready queue copy ([#179](https://github.com/thalesraymond/task-runner/issues/179)) ([ea77aa0](https://github.com/thalesraymond/task-runner/commit/ea77aa0afc8da5a55730216d081f7e1c80f4982e))
44
+
21
45
  ## [4.2.0](https://github.com/thalesraymond/task-runner/compare/task-runner-v4.1.0...task-runner-v4.2.0) (2026-02-15)
22
46
 
23
47
 
package/dist/EventBus.js CHANGED
@@ -24,8 +24,9 @@ export class EventBus {
24
24
  * @param callback The callback to remove.
25
25
  */
26
26
  off(event, callback) {
27
- if (this.listeners[event]) {
28
- this.listeners[event].delete(callback);
27
+ const listeners = this.listeners[event];
28
+ if (listeners) {
29
+ listeners.delete(callback);
29
30
  }
30
31
  }
31
32
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"EventBus.js","sourceRoot":"","sources":["../src/EventBus.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,OAAO,QAAQ;IACX,SAAS,GAA0B,EAAE,CAAC;IAE9C;;;;OAIG;IACI,EAAE,CACP,KAAQ,EACR,QAA0C;QAE1C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,4EAA4E;YAC5E,iEAAiE;YACjE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,EAAyC,CAAC;QAC3E,CAAC;QACD,oFAAoF;QACnF,IAAI,CAAC,SAAS,CAAC,KAAK,CAA2C,CAAC,GAAG,CAClE,QAAQ,CACT,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACI,GAAG,CACR,KAAQ,EACR,QAA0C;QAE1C,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,SAAS,CAAC,KAAK,CAA2C,CAAC,MAAM,CACrE,QAAQ,CACT,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,IAAI,CACT,KAAQ,EACR,IAAsC;QAEtC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAEzB,CAAC;QACd,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,2EAA2E;gBAC3E,iDAAiD;gBACjD,cAAc,CAAC,GAAG,EAAE;oBAClB,IAAI,CAAC;wBACH,IAAI,CAAC;4BACH,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;4BAC9B,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gCAC9B,mCAAmC;gCACnC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;oCACrB,OAAO,CAAC,KAAK,CACX,+BAA+B,MAAM,CAAC,KAAK,CAAC,GAAG,EAC/C,KAAK,CACN,CAAC;gCACJ,CAAC,CAAC,CAAC;4BACL,CAAC;wBACH,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,8BAA8B;4BAC9B,OAAO,CAAC,KAAK,CACX,+BAA+B,MAAM,CAAC,KAAK,CAAC,GAAG,EAC/C,KAAK,CACN,CAAC;wBACJ,CAAC;oBACH,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,uDAAuD;wBACvD,OAAO,CAAC,KAAK,CACX,+CAA+C,MAAM,CAAC,KAAK,CAAC,GAAG,EAC/D,KAAK,CACN,CAAC;oBACJ,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"EventBus.js","sourceRoot":"","sources":["../src/EventBus.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,OAAO,QAAQ;IACX,SAAS,GAA0B,EAAE,CAAC;IAE9C;;;;OAIG;IACI,EAAE,CACP,KAAQ,EACR,QAA0C;QAE1C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,4EAA4E;YAC5E,iEAAiE;YACjE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,EAAyC,CAAC;QAC3E,CAAC;QACD,oFAAoF;QACnF,IAAI,CAAC,SAAS,CAAC,KAAK,CAA2C,CAAC,GAAG,CAClE,QAAQ,CACT,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACI,GAAG,CACR,KAAQ,EACR,QAA0C;QAE1C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,SAAS,EAAE,CAAC;YACd,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,IAAI,CACT,KAAQ,EACR,IAAsC;QAEtC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,2EAA2E;gBAC3E,iDAAiD;gBACjD,cAAc,CAAC,GAAG,EAAE;oBAClB,IAAI,CAAC;wBACH,IAAI,CAAC;4BACH,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;4BAC9B,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gCAC9B,mCAAmC;gCACnC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;oCACrB,OAAO,CAAC,KAAK,CACX,+BAA+B,MAAM,CAAC,KAAK,CAAC,GAAG,EAC/C,KAAK,CACN,CAAC;gCACJ,CAAC,CAAC,CAAC;4BACL,CAAC;wBACH,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,8BAA8B;4BAC9B,OAAO,CAAC,KAAK,CACX,+BAA+B,MAAM,CAAC,KAAK,CAAC,GAAG,EAC/C,KAAK,CACN,CAAC;wBACJ,CAAC;oBACH,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,uDAAuD;wBACvD,OAAO,CAAC,KAAK,CACX,+CAA+C,MAAM,CAAC,KAAK,CAAC,GAAG,EAC/D,KAAK,CACN,CAAC;oBACJ,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -12,7 +12,7 @@ export declare class PluginManager<TContext> {
12
12
  */
13
13
  use(plugin: Plugin<TContext>): void;
14
14
  /**
15
- * Initializes all registered plugins.
15
+ * Initializes all registered plugins in parallel.
16
16
  */
17
17
  initialize(): Promise<void>;
18
18
  /**
@@ -22,12 +22,13 @@ export class PluginManager {
22
22
  this.plugins.push(plugin);
23
23
  }
24
24
  /**
25
- * Initializes all registered plugins.
25
+ * Initializes all registered plugins in parallel.
26
26
  */
27
27
  async initialize() {
28
- for (const plugin of this.plugins) {
29
- await plugin.install(this.context);
30
- }
28
+ const installPromises = this.plugins
29
+ .map((plugin) => plugin.install(this.context))
30
+ .filter((result) => result instanceof Promise);
31
+ await Promise.all(installPromises);
31
32
  }
32
33
  /**
33
34
  * Returns the list of registered plugins.
@@ -1 +1 @@
1
- {"version":3,"file":"PluginManager.js","sourceRoot":"","sources":["../src/PluginManager.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,aAAa;IAGJ;IAFZ,OAAO,GAAuB,EAAE,CAAC;IAEzC,YAAoB,OAAgC;QAAhC,YAAO,GAAP,OAAO,CAAyB;IAAG,CAAC;IAExD;;;OAGG;IACI,GAAG,CAAC,MAAwB;QACjC,wCAAwC;QACxC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACrD,8CAA8C;YAC9C,2DAA2D;YAC3D,6CAA6C;YAC7C,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,CAAC,IAAI,0BAA0B,CAAC,CAAC;QAC9E,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,UAAU;QACrB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED;;OAEG;IACI,UAAU;QACf,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF"}
1
+ {"version":3,"file":"PluginManager.js","sourceRoot":"","sources":["../src/PluginManager.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,aAAa;IAGJ;IAFZ,OAAO,GAAuB,EAAE,CAAC;IAEzC,YAAoB,OAAgC;QAAhC,YAAO,GAAP,OAAO,CAAyB;IAAG,CAAC;IAExD;;;OAGG;IACI,GAAG,CAAC,MAAwB;QACjC,wCAAwC;QACxC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACrD,8CAA8C;YAC9C,2DAA2D;YAC3D,6CAA6C;YAC7C,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,CAAC,IAAI,0BAA0B,CAAC,CAAC;QAC9E,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,UAAU;QACrB,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO;aACjC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;aAC7C,MAAM,CAAC,CAAC,MAAM,EAA2B,EAAE,CAAC,MAAM,YAAY,OAAO,CAAC,CAAC;QAE1E,MAAM,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACI,UAAU;QACf,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF"}
@@ -65,7 +65,8 @@ export class TaskRunner {
65
65
  * @returns A string containing the Mermaid graph definition.
66
66
  */
67
67
  static getMermaidGraph(steps) {
68
- const graphLines = new Set(["graph TD"]);
68
+ const nodeLines = ["graph TD"];
69
+ const edgeLines = new Set();
69
70
  const idMap = new Map();
70
71
  const usedIds = new Set();
71
72
  const baseIdCounters = new Map();
@@ -93,26 +94,27 @@ export class TaskRunner {
93
94
  idMap.set(name, uniqueId);
94
95
  return uniqueId;
95
96
  };
96
- // We process nodes in input order to ensure deterministic ID generation
97
- // (getUniqueId is called for each unique step name in order, populating the cache).
98
- const processedNamesForNodes = new Set();
99
- for (const step of steps) {
100
- if (!processedNamesForNodes.has(step.name)) {
101
- const stepId = getUniqueId(step.name);
102
- graphLines.add(` ${stepId}[${JSON.stringify(step.name)}]`);
103
- processedNamesForNodes.add(step.name);
97
+ // Process nodes and edges in a single pass over input steps
98
+ const processedNodes = new Set();
99
+ for (let i = 0; i < steps.length; i++) {
100
+ const step = steps[i];
101
+ const name = step.name;
102
+ const stepId = getUniqueId(name);
103
+ const sizeBefore = processedNodes.size;
104
+ processedNodes.add(stepId);
105
+ if (processedNodes.size !== sizeBefore) {
106
+ const escapedName = name.replaceAll("\"", "&quot;");
107
+ nodeLines.push(` ${stepId}["${escapedName}"]`);
104
108
  }
105
- }
106
- for (const step of steps) {
107
109
  if (step.dependencies) {
108
- const stepId = getUniqueId(step.name);
109
- for (const dep of step.dependencies) {
110
- const depId = getUniqueId(dep);
111
- graphLines.add(` ${depId} --> ${stepId}`);
110
+ const deps = step.dependencies;
111
+ for (let j = 0; j < deps.length; j++) {
112
+ const depId = getUniqueId(deps[j]);
113
+ edgeLines.add(` ${depId} --> ${stepId}`);
112
114
  }
113
115
  }
114
116
  }
115
- return [...graphLines].join("\n");
117
+ return nodeLines.concat([...edgeLines]).join("\n");
116
118
  }
117
119
  /**
118
120
  * Sanitizes a string for use as a Mermaid node ID.
@@ -1 +1 @@
1
- {"version":3,"file":"TaskRunner.js","sourceRoot":"","sources":["../src/TaskRunner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TaskRunner.js","sourceRoot":"","sources":["../src/TaskRunner.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,7 @@ export declare class TaskStateManager<TContext> {
13
13
  private dependencyGraph;
14
14
  private dependencyCounts;
15
15
  private readyQueue;
16
+ private taskDefinitions;
16
17
  constructor(eventBus: EventBus<TContext>);
17
18
  /**
18
19
  * Initializes the state with the given steps.
@@ -11,6 +11,7 @@ export class TaskStateManager {
11
11
  dependencyGraph = new Map();
12
12
  dependencyCounts = new Map();
13
13
  readyQueue = [];
14
+ taskDefinitions = new Map();
14
15
  constructor(eventBus) {
15
16
  this.eventBus = eventBus;
16
17
  }
@@ -25,7 +26,9 @@ export class TaskStateManager {
25
26
  this.readyQueue = [];
26
27
  this.dependencyGraph.clear();
27
28
  this.dependencyCounts.clear();
29
+ this.taskDefinitions.clear();
28
30
  for (const step of steps) {
31
+ this.taskDefinitions.set(step.name, step);
29
32
  const deps = step.dependencies ?? [];
30
33
  this.dependencyCounts.set(step.name, deps.length);
31
34
  if (deps.length === 0) {
@@ -49,7 +52,7 @@ export class TaskStateManager {
49
52
  * @returns An array of tasks that are ready to run.
50
53
  */
51
54
  processDependencies() {
52
- const toRun = [...this.readyQueue];
55
+ const toRun = this.readyQueue;
53
56
  this.readyQueue = [];
54
57
  // Remove them from pendingSteps as they are now handed off to the executor
55
58
  for (const step of toRun) {
@@ -78,6 +81,15 @@ export class TaskStateManager {
78
81
  if (result.status === "success") {
79
82
  this.handleSuccess(step.name);
80
83
  }
84
+ else if (result.status === "failure") {
85
+ // If continueOnError is true, treat as success for dependents to unblock the workflow
86
+ if (this.taskDefinitions.get(step.name)?.continueOnError) {
87
+ this.handleSuccess(step.name);
88
+ }
89
+ else {
90
+ this.cascadeFailure(step.name);
91
+ }
92
+ }
81
93
  else {
82
94
  this.cascadeFailure(step.name);
83
95
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TaskStateManager.js","sourceRoot":"","sources":["../src/TaskStateManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TaskStateManager.js","sourceRoot":"","sources":["../src/TaskStateManager.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,18 @@ export interface TaskStep<TContext> {
22
22
  * Only affects ordering when multiple tasks are ready and concurrency slots are limited.
23
23
  */
24
24
  priority?: number;
25
+ /**
26
+ * Optional flag to indicate that the workflow should continue even if this task fails.
27
+ * If true, dependent tasks will execute as if this task succeeded.
28
+ * The task result will still be marked as "failure".
29
+ * Default is false.
30
+ */
31
+ continueOnError?: boolean;
32
+ /**
33
+ * Optional maximum execution time in milliseconds.
34
+ * If the task runs longer than this, it will be cancelled and marked as failed.
35
+ */
36
+ timeout?: number;
25
37
  /**
26
38
  * The core logic of the task.
27
39
  * @param context The shared context object, allowing for state to be passed between tasks.
@@ -14,10 +14,10 @@ export class DryRunExecutionStrategy {
14
14
  _context,
15
15
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
16
  _signal) {
17
- return Promise.resolve({
17
+ return {
18
18
  status: "success",
19
19
  message: "Dry run: simulated success " + step.name,
20
- });
20
+ };
21
21
  }
22
22
  }
23
23
  //# sourceMappingURL=DryRunExecutionStrategy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DryRunExecutionStrategy.js","sourceRoot":"","sources":["../../src/strategies/DryRunExecutionStrategy.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,OAAO,uBAAuB;IAGlC;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CACX,IAAwB;IACxB,6DAA6D;IAC7D,QAAkB;IAClB,6DAA6D;IAC7D,OAAqB;QAErB,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,6BAA6B,GAAG,IAAI,CAAC,IAAI;SACnD,CAAC,CAAC;IACL,CAAC;CACF"}
1
+ {"version":3,"file":"DryRunExecutionStrategy.js","sourceRoot":"","sources":["../../src/strategies/DryRunExecutionStrategy.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,OAAO,uBAAuB;IAGlC;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CACX,IAAwB;IACxB,6DAA6D;IAC7D,QAAkB;IAClB,6DAA6D;IAC7D,OAAqB;QAErB,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,6BAA6B,GAAG,IAAI,CAAC,IAAI;SACnD,CAAC;IACJ,CAAC;CACF"}
@@ -3,8 +3,45 @@
3
3
  */
4
4
  export class StandardExecutionStrategy {
5
5
  async execute(step, context, signal) {
6
+ if (!step.timeout) {
7
+ try {
8
+ return await step.run(context, signal);
9
+ }
10
+ catch (e) {
11
+ // Check if error is due to abort
12
+ if (signal?.aborted &&
13
+ ((e instanceof Error && e.name === "AbortError") ||
14
+ signal.reason === e)) {
15
+ return {
16
+ status: "cancelled",
17
+ message: "Task cancelled during execution",
18
+ };
19
+ }
20
+ return {
21
+ status: "failure",
22
+ error: e instanceof Error ? e.message : String(e),
23
+ };
24
+ }
25
+ }
26
+ const abortController = new AbortController();
27
+ const timeoutSignal = signal
28
+ ? AbortSignal.any([signal, abortController.signal])
29
+ : abortController.signal;
30
+ let timer;
31
+ let resolveTimeout;
6
32
  try {
7
- return await step.run(context, signal);
33
+ const timeoutPromise = new Promise((resolve) => {
34
+ resolveTimeout = resolve;
35
+ timer = setTimeout(() => {
36
+ abortController.abort(new Error("Timeout"));
37
+ resolve({
38
+ status: "failure",
39
+ error: `Task timed out after ${step.timeout}ms`,
40
+ });
41
+ }, step.timeout);
42
+ });
43
+ const taskPromise = step.run(context, timeoutSignal);
44
+ return await Promise.race([taskPromise, timeoutPromise]);
8
45
  }
9
46
  catch (e) {
10
47
  // Check if error is due to abort
@@ -20,6 +57,11 @@ export class StandardExecutionStrategy {
20
57
  error: e instanceof Error ? e.message : String(e),
21
58
  };
22
59
  }
60
+ finally {
61
+ clearTimeout(timer);
62
+ // Settle the timeout promise to avoid memory leaks from Promise.race
63
+ resolveTimeout({ status: "cancelled" });
64
+ }
23
65
  }
24
66
  }
25
67
  //# sourceMappingURL=StandardExecutionStrategy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StandardExecutionStrategy.js","sourceRoot":"","sources":["../../src/strategies/StandardExecutionStrategy.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,OAAO,yBAAyB;IAGpC,KAAK,CAAC,OAAO,CACX,IAAwB,EACxB,OAAiB,EACjB,MAAoB;QAEpB,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,iCAAiC;YACjC,IACE,MAAM,EAAE,OAAO;gBACf,CAAC,CAAC,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,EACxE,CAAC;gBACD,OAAO;oBACL,MAAM,EAAE,WAAW;oBACnB,OAAO,EAAE,iCAAiC;iBAC3C,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;aAClD,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"StandardExecutionStrategy.js","sourceRoot":"","sources":["../../src/strategies/StandardExecutionStrategy.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,OAAO,yBAAyB;IAGpC,KAAK,CAAC,OAAO,CACX,IAAwB,EACxB,OAAiB,EACjB,MAAoB;QAEpB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACzC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,iCAAiC;gBACjC,IACE,MAAM,EAAE,OAAO;oBACf,CAAC,CAAC,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC;wBAC9C,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,EACtB,CAAC;oBACD,OAAO;wBACL,MAAM,EAAE,WAAW;wBACnB,OAAO,EAAE,iCAAiC;qBAC3C,CAAC;gBACJ,CAAC;gBACD,OAAO;oBACL,MAAM,EAAE,SAAS;oBACjB,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;iBAClD,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAC9C,MAAM,aAAa,GAAG,MAAM;YAC1B,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;YACnD,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC;QAE3B,IAAI,KAAiC,CAAC;QACtC,IAAI,cAA4C,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,cAAc,GAAG,IAAI,OAAO,CAAa,CAAC,OAAO,EAAE,EAAE;gBACzD,cAAc,GAAG,OAAO,CAAC;gBACzB,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;oBACtB,eAAe,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;oBAC5C,OAAO,CAAC;wBACN,MAAM,EAAE,SAAS;wBACjB,KAAK,EAAE,wBAAwB,IAAI,CAAC,OAAO,IAAI;qBAChD,CAAC,CAAC;gBACL,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;YAEH,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YAErD,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;QAC3D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,iCAAiC;YACjC,IACE,MAAM,EAAE,OAAO;gBACf,CAAC,CAAC,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,EACxE,CAAC;gBACD,OAAO;oBACL,MAAM,EAAE,WAAW;oBACnB,OAAO,EAAE,iCAAiC;iBAC3C,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;aAClD,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,qEAAqE;YACrE,cAAc,CAAC,EAAE,MAAM,EAAE,WAAW,EAAgB,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,34 @@
1
+ ## Context
2
+
3
+ Currently, the task runner always re-executes tasks, even if inputs (context) have not changed. This is inefficient for workflows with expensive steps like builds or data processing.
4
+
5
+ ## Goals / Non-Goals
6
+
7
+ - **Goals**:
8
+ - Avoid redundant execution of expensive tasks.
9
+ - Support pluggable caching mechanisms (defaulting to in-memory).
10
+ - Allow restoration of context side effects when skipping execution.
11
+ - **Non-Goals**:
12
+ - Distributed caching (out of scope for now).
13
+ - Automatic dependency hashing (cache key must be provided by the user).
14
+ - Persistent file system caching (can be added later via plugin or custom provider).
15
+
16
+ ## Decisions
17
+
18
+ - **Decision**: Use `ICacheProvider` interface.
19
+ - **Rationale**: Allows users to swap the caching backend (e.g., Redis, FS) without changing core logic.
20
+ - **Decision**: Explicit `restore` callback.
21
+ - **Rationale**: Since context is mutable and side-effect driven, simply returning a cached result is insufficient. The task must explicitly define how to re-apply its changes to the context based on the cached result.
22
+ - **Decision**: Wrap execution strategy.
23
+ - **Rationale**: Follows the existing decorator pattern (like `RetryingExecutionStrategy`), keeping concerns separated.
24
+
25
+ ## Risks / Trade-offs
26
+
27
+ - **Risk**: Stale cache data if keys are not unique enough.
28
+ - **Mitigation**: Documentation must emphasize the importance of including all relevant inputs in the cache key.
29
+ - **Risk**: Context inconsistency if `restore` is implemented incorrectly.
30
+ - **Mitigation**: Provide clear examples and potentially validate context changes in debug mode.
31
+
32
+ ## Migration Plan
33
+
34
+ - This is an additive change. Existing tasks without `cache` config will work as before. No migration required.
@@ -0,0 +1,18 @@
1
+ # Change: Task Output Caching
2
+
3
+ ## Why
4
+
5
+ Currently, the task runner executes every task on every run, regardless of whether inputs or context have changed. For complex workflows involving expensive operations (e.g., builds, data processing), this leads to redundant execution and slower feedback loops. Implementing a caching mechanism will significantly improve performance by skipping tasks that have already been successfully executed with the same inputs.
6
+
7
+ ## What Changes
8
+
9
+ - **Task Configuration**: Add `cache` configuration to `TaskStep` interface, allowing tasks to define a cache key and a restoration logic.
10
+ - **Execution Strategy**: Introduce `CachingExecutionStrategy` that wraps other strategies. It checks for a cached result before execution and stores the result after successful execution.
11
+ - **Cache Provider**: Define an `ICacheProvider` interface with a default in-memory implementation (`MemoryCacheProvider`), allowing for future extension (e.g., file system or remote cache).
12
+ - **Task Result**: Ensure `TaskResult` is serializable and contains necessary metadata for caching.
13
+
14
+ ## Impact
15
+
16
+ - **Affected specs**: `task-runner`
17
+ - **Affected code**: `TaskStep.ts`, `TaskRunner.ts`, new strategy `CachingExecutionStrategy.ts`, new contract `ICacheProvider.ts`.
18
+ - **Performance**: Significant reduction in execution time for repeated workflows.
@@ -0,0 +1,58 @@
1
+ ## ADDED Requirements
2
+
3
+ ### Requirement: Task Caching Configuration
4
+
5
+ The `TaskStep` interface SHALL support an optional `cache` property of type `TaskCacheConfig`.
6
+
7
+ #### Scenario: Cache Config Structure
8
+
9
+ - **GIVEN** a `TaskCacheConfig` object
10
+ - **THEN** it SHALL support:
11
+ - `key`: A function returning a unique string key based on the context.
12
+ - `ttl`: Optional time-to-live in milliseconds.
13
+ - `restore`: Optional function to restore context side effects from a cached result.
14
+
15
+ ### Requirement: Caching Execution Strategy
16
+
17
+ The system SHALL provide a `CachingExecutionStrategy` that implements `IExecutionStrategy` and wraps another `IExecutionStrategy`.
18
+
19
+ #### Scenario: Cache Miss Execution
20
+
21
+ - **WHEN** the `CachingExecutionStrategy` executes a task with a cache key that is NOT present in the cache provider
22
+ - **THEN** it SHALL execute the task using the inner strategy.
23
+ - **AND** it SHALL store the result in the cache provider if execution is successful.
24
+ - **AND** it SHALL return the result.
25
+
26
+ #### Scenario: Cache Hit Execution
27
+
28
+ - **WHEN** the `CachingExecutionStrategy` executes a task with a cache key that IS present in the cache provider
29
+ - **THEN** it SHALL NOT execute the inner strategy.
30
+ - **AND** it SHALL invoke the `restore` function (if provided) with the current context and the cached result.
31
+ - **AND** it SHALL return the cached result.
32
+
33
+ #### Scenario: Cache Expiration
34
+
35
+ - **WHEN** a cached item's TTL has expired
36
+ - **THEN** the cache provider SHALL NOT return the item.
37
+ - **AND** the strategy SHALL proceed as a cache miss.
38
+
39
+ ### Requirement: Cache Provider Interface
40
+
41
+ The system SHALL define an `ICacheProvider` interface for pluggable caching backends.
42
+
43
+ #### Scenario: Interface Methods
44
+
45
+ - **GIVEN** an `ICacheProvider` implementation
46
+ - **THEN** it SHALL support:
47
+ - `get(key: string): Promise<TaskResult | undefined>`
48
+ - `set(key: string, value: TaskResult, ttl?: number): Promise<void>`
49
+ - `delete(key: string): Promise<void>`
50
+
51
+ ### Requirement: Default Memory Cache
52
+
53
+ The system SHALL provide a `MemoryCacheProvider` as the default implementation of `ICacheProvider`.
54
+
55
+ #### Scenario: In-Memory Storage
56
+
57
+ - **WHEN** items are set in `MemoryCacheProvider`
58
+ - **THEN** they are stored in memory and retrieved correctly until process termination or expiration.
@@ -0,0 +1,24 @@
1
+ ## 1. Implementation
2
+
3
+ - [ ] 1.1 Define `ICacheProvider` interface in `src/contracts/ICacheProvider.ts` with `get(key)`, `set(key, result, ttl)`, and `delete(key)` methods.
4
+ - [ ] 1.2 Implement `MemoryCacheProvider` in `src/utils/MemoryCacheProvider.ts` as the default in-memory cache implementation.
5
+ - [ ] 1.3 Update `TaskStep` interface in `src/TaskStep.ts` to include optional `cache` configuration:
6
+ - `key`: `(context: TContext) => string | Promise<string>`
7
+ - `ttl`: `number` (optional, default to infinite)
8
+ - `restore`: `(context: TContext, cachedResult: TaskResult) => void | Promise<void>` (optional, to re-apply context side effects)
9
+ - [ ] 1.4 Create `CachingExecutionStrategy` in `src/strategies/CachingExecutionStrategy.ts`.
10
+ - It should implement `IExecutionStrategy`.
11
+ - It should accept an inner `IExecutionStrategy` and an `ICacheProvider`.
12
+ - In `execute`:
13
+ - Calculate cache key using `step.cache.key(context)`.
14
+ - Check cache provider. If hit:
15
+ - Execute `step.cache.restore(context, result)` if provided.
16
+ - Return cached result with status `skipped` (or a new status `cached`).
17
+ - If miss:
18
+ - Execute inner strategy.
19
+ - If successful, store result in cache provider using `ttl`.
20
+ - Return result.
21
+ - [ ] 1.5 Update `TaskRunner.ts` to support configuring the cache provider and wrapping the execution strategy with `CachingExecutionStrategy` if caching is enabled.
22
+ - [ ] 1.6 Add unit tests for `MemoryCacheProvider`.
23
+ - [ ] 1.7 Add unit tests for `CachingExecutionStrategy`, verifying cache hits, misses, and restoration of context.
24
+ - [ ] 1.8 Add integration tests in `tests/TaskRunnerCaching.test.ts` to verify end-to-end caching behavior with context updates.
@@ -0,0 +1,23 @@
1
+ # Change: Add Matrix Execution Support
2
+
3
+ ## Why
4
+
5
+ Task orchestration tools in the industry (such as Nx, GitHub Actions, GitLab CI, and Turborepo) commonly support Matrix Execution. This allows a single task definition to run multiple times automatically across a set of variable combinations. In `task-runner`, defining identical tasks to process multiple permutations manually increases boilerplate and violates the DRY (Don't Repeat Yourself) principle. Introducing `matrix` configurations directly on the `TaskStep` allows developers to run a task concurrently across different configurations (e.g., Node.js versions, OS platforms, target environments) efficiently.
6
+
7
+ ## What Changes
8
+
9
+ - Introduce a `matrix` property to the `TaskStep` configuration.
10
+ - The `matrix` property should support defining variables as an object of arrays (e.g., `matrix: { node: [18, 20], os: ['ubuntu', 'windows'] }`).
11
+ - The engine will dynamically generate and execute independent child tasks for each permutation of the matrix.
12
+ - Ensure the `MermaidGraph` utility correctly visualizes these dynamic nodes.
13
+ - Expose the current permutation variables to the execution context of each child task.
14
+
15
+ ## Impact
16
+
17
+ - Affected specs: `task-runner` (Task Configuration, Core Orchestration)
18
+ - Affected code:
19
+ - `src/core/TaskStep.ts`
20
+ - `src/core/TaskRunner.ts`
21
+ - `src/core/TaskGraph.ts`
22
+ - `src/core/TaskStateManager.ts`
23
+ - `src/core/WorkflowExecutor.ts`
@@ -0,0 +1,47 @@
1
+ ## ADDED Requirements
2
+
3
+ ### Requirement: Matrix Execution Configuration
4
+
5
+ The `TaskStep` interface SHALL support an optional `matrix` configuration property to enable parameterized execution.
6
+
7
+ #### Scenario: Matrix configuration structure
8
+
9
+ - **GIVEN** a `TaskStep` definition
10
+ - **THEN** it SHALL support a `matrix` property defined as a mapping of variable names to arrays of values (e.g., `Record<string, any[]>`).
11
+
12
+ ### Requirement: Matrix Permutation Expansion
13
+
14
+ The `TaskRunner` engine SHALL dynamically expand a task with a `matrix` configuration into multiple independent task instances.
15
+
16
+ #### Scenario: Single dimension matrix
17
+
18
+ - **WHEN** a task defines a single dimension matrix (e.g., `matrix: { env: ['dev', 'prod'] }`)
19
+ - **THEN** the engine SHALL generate independent task instances for each value.
20
+
21
+ #### Scenario: Multi-dimensional matrix
22
+
23
+ - **WHEN** a task defines a multi-dimensional matrix (e.g., `matrix: { os: ['linux', 'windows'], node: [18, 20] }`)
24
+ - **THEN** the engine SHALL generate independent task instances for every combination (Cartesian product) of the matrix dimensions.
25
+
26
+ ### Requirement: Contextual Matrix Variables
27
+
28
+ The `TaskRunner` SHALL provide the matrix permutation values to the execution context of the generated child tasks.
29
+
30
+ #### Scenario: Accessing matrix variables
31
+
32
+ - **WHEN** a child matrix task is executed for a permutation like `{ os: 'linux', node: 18 }`
33
+ - **THEN** its `run` function SHALL be able to access the permutation values via the context (e.g., `context.matrix.os` would be `'linux'` and `context.matrix.node` would be `18`).
34
+
35
+ ### Requirement: Matrix Dependency Resolution
36
+
37
+ The `TaskRunner` SHALL correctly resolve dependencies involving matrix tasks.
38
+
39
+ #### Scenario: Depending on a matrix task
40
+
41
+ - **WHEN** a standard task depends on a matrix task
42
+ - **THEN** the standard task SHALL wait for all child tasks of the matrix to complete successfully before executing.
43
+
44
+ #### Scenario: Matrix task dependencies
45
+
46
+ - **WHEN** a matrix task depends on another task
47
+ - **THEN** all generated child tasks of the matrix SHALL wait for the parent task to complete before executing.
@@ -0,0 +1,11 @@
1
+ ## 1. Implementation
2
+
3
+ - [ ] 1.1 Update `TaskStep.ts` interface to include an optional `matrix` property (e.g., `Record<string, unknown[]>`).
4
+ - [ ] 1.2 Update the `TaskRunnerBuilder` and `TaskGraph` validation to accept and validate the `matrix` property.
5
+ - [ ] 1.3 Implement a matrix permutation generator utility to compute Cartesian products of matrix dimensions.
6
+ - [ ] 1.4 Update `TaskStateManager.ts` or `TaskGraph.ts` to dynamically expand matrix steps into individual nodes during initialization, resolving dependencies appropriately.
7
+ - [ ] 1.5 Update the task execution context to provide the current matrix permutation variables to the `run` function.
8
+ - [ ] 1.6 Update the Mermaid Graph utility in `TaskRunner.ts` to correctly output nodes and edges for the dynamically generated matrix steps.
9
+ - [ ] 1.7 Add unit tests covering matrix generation, execution, failure handling, and context passing.
10
+ - [ ] 1.8 Add benchmarks for graph generation and state initialization with large matrix sets to ensure performance targets are met.
11
+ - [ ] 1.9 Add user-facing documentation for the `matrix` feature, including examples.
@@ -0,0 +1,16 @@
1
+ # Change: Workflow Observability and Logging Enhancements
2
+
3
+ ## Why
4
+
5
+ As workflows scale in complexity and run in diverse environments (CI/CD, containerized workers, local development), tracking their execution becomes difficult. Currently, users have to manually hook into the `EventBus` to build their own loggers or metrics exporters. Providing built-in, standardized observability tools (like a structured logger or CLI output formatter) will significantly improve the Developer Experience (DX) and reduce boilerplate for debugging complex task graphs.
6
+
7
+ ## What Changes
8
+
9
+ - Introduce a standardized `LoggerPlugin` (or similar logging abstraction) that hooks into the existing `EventBus`.
10
+ - Support multiple output formats: `text` (human-readable for CLI) and `json` (structured logging for ingestion by tools like Datadog, ELK, CloudWatch).
11
+ - Capture and format key metrics automatically: task duration, error stack traces, and workflow summaries.
12
+
13
+ ## Impact
14
+
15
+ - Affected specs: `task-runner` (adding observability capabilities)
16
+ - Affected code: `src/plugins/LoggerPlugin.ts` (new), `TaskRunnerBuilder` (optional `.withLogger()` integration).
@@ -0,0 +1,14 @@
1
+ ## ADDED Requirements
2
+
3
+ ### Requirement: Built-in Observability Logging
4
+
5
+ The system SHALL provide a standardized mechanism to log workflow and task execution events in both human-readable and structured formats.
6
+
7
+ #### Scenario: CLI Text Logging
8
+ - **WHEN** a workflow is executed with the text logger enabled
9
+ - **THEN** it SHALL output human-readable lifecycle events (start, success, failure, skip) to the console.
10
+
11
+ #### Scenario: Structured JSON Logging
12
+ - **WHEN** a workflow is executed with the JSON logger enabled
13
+ - **THEN** it SHALL output structured JSON objects for each lifecycle event, suitable for machine ingestion.
14
+ - **AND** the JSON object SHALL contain task name, timestamp, duration, and status.
@@ -0,0 +1,7 @@
1
+ ## 1. Implementation
2
+
3
+ - [ ] 1.1 Create `LoggerPlugin` implementing the `Plugin` interface.
4
+ - [ ] 1.2 Implement human-readable text formatting for CLI.
5
+ - [ ] 1.3 Implement structured JSON formatting for log ingestion.
6
+ - [ ] 1.4 Add a fluent method to `TaskRunnerBuilder` (e.g., `.withLogger()`) to easily attach the plugin.
7
+ - [ ] 1.5 Write unit tests for the logging outputs and integration.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calmo/task-runner",
3
- "version": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "description": "A lightweight, type-safe, and domain-agnostic task orchestration engine. It resolves a Directed Acyclic Graph (DAG) of steps, executes independent tasks in parallel, and manages a shared context across the pipeline.",
5
5
  "repository": {
6
6
  "type": "git",
package/src/EventBus.ts CHANGED
@@ -40,10 +40,9 @@ export class EventBus<TContext> {
40
40
  event: K,
41
41
  callback: RunnerEventListener<TContext, K>
42
42
  ): void {
43
- if (this.listeners[event]) {
44
- (this.listeners[event] as Set<RunnerEventListener<TContext, K>>).delete(
45
- callback
46
- );
43
+ const listeners = this.listeners[event];
44
+ if (listeners) {
45
+ listeners.delete(callback);
47
46
  }
48
47
  }
49
48
 
@@ -56,9 +55,7 @@ export class EventBus<TContext> {
56
55
  event: K,
57
56
  data: RunnerEventPayloads<TContext>[K]
58
57
  ): void {
59
- const listeners = this.listeners[event] as
60
- | Set<RunnerEventListener<TContext, K>>
61
- | undefined;
58
+ const listeners = this.listeners[event];
62
59
  if (listeners) {
63
60
  for (const listener of listeners) {
64
61
  // We use queueMicrotask() to schedule the listener on the microtask queue,
@@ -24,12 +24,14 @@ export class PluginManager<TContext> {
24
24
  }
25
25
 
26
26
  /**
27
- * Initializes all registered plugins.
27
+ * Initializes all registered plugins in parallel.
28
28
  */
29
29
  public async initialize(): Promise<void> {
30
- for (const plugin of this.plugins) {
31
- await plugin.install(this.context);
32
- }
30
+ const installPromises = this.plugins
31
+ .map((plugin) => plugin.install(this.context))
32
+ .filter((result): result is Promise<void> => result instanceof Promise);
33
+
34
+ await Promise.all(installPromises);
33
35
  }
34
36
 
35
37
  /**
package/src/TaskRunner.ts CHANGED
@@ -88,7 +88,8 @@ export class TaskRunner<TContext> {
88
88
  * @returns A string containing the Mermaid graph definition.
89
89
  */
90
90
  public static getMermaidGraph<T>(steps: TaskStep<T>[]): string {
91
- const graphLines = new Set<string>(["graph TD"]);
91
+ const nodeLines: string[] = ["graph TD"];
92
+ const edgeLines = new Set<string>();
92
93
  const idMap = new Map<string, string>();
93
94
  const usedIds = new Set<string>();
94
95
  const baseIdCounters = new Map<string, number>();
@@ -124,28 +125,31 @@ export class TaskRunner<TContext> {
124
125
  return uniqueId;
125
126
  };
126
127
 
127
- // We process nodes in input order to ensure deterministic ID generation
128
- // (getUniqueId is called for each unique step name in order, populating the cache).
129
- const processedNamesForNodes = new Set<string>();
130
- for (const step of steps) {
131
- if (!processedNamesForNodes.has(step.name)) {
132
- const stepId = getUniqueId(step.name);
133
- graphLines.add(` ${stepId}[${JSON.stringify(step.name)}]`);
134
- processedNamesForNodes.add(step.name);
128
+ // Process nodes and edges in a single pass over input steps
129
+ const processedNodes = new Set<string>();
130
+ for (let i = 0; i < steps.length; i++) {
131
+ const step = steps[i];
132
+ const name = step.name;
133
+ const stepId = getUniqueId(name);
134
+
135
+ const sizeBefore = processedNodes.size;
136
+ processedNodes.add(stepId);
137
+
138
+ if (processedNodes.size !== sizeBefore) {
139
+ const escapedName = name.replaceAll("\"", "&quot;");
140
+ nodeLines.push(` ${stepId}["${escapedName}"]`);
135
141
  }
136
- }
137
142
 
138
- for (const step of steps) {
139
143
  if (step.dependencies) {
140
- const stepId = getUniqueId(step.name);
141
- for (const dep of step.dependencies) {
142
- const depId = getUniqueId(dep);
143
- graphLines.add(` ${depId} --> ${stepId}`);
144
+ const deps = step.dependencies;
145
+ for (let j = 0; j < deps.length; j++) {
146
+ const depId = getUniqueId(deps[j]);
147
+ edgeLines.add(` ${depId} --> ${stepId}`);
144
148
  }
145
149
  }
146
150
  }
147
151
 
148
- return [...graphLines].join("\n");
152
+ return nodeLines.concat([...edgeLines]).join("\n");
149
153
  }
150
154
 
151
155
  /**
@@ -15,6 +15,7 @@ export class TaskStateManager<TContext> {
15
15
  private dependencyGraph = new Map<string, TaskStep<TContext>[]>();
16
16
  private dependencyCounts = new Map<string, number>();
17
17
  private readyQueue: TaskStep<TContext>[] = [];
18
+ private taskDefinitions = new Map<string, TaskStep<TContext>>();
18
19
 
19
20
  constructor(private eventBus: EventBus<TContext>) {}
20
21
 
@@ -30,8 +31,10 @@ export class TaskStateManager<TContext> {
30
31
 
31
32
  this.dependencyGraph.clear();
32
33
  this.dependencyCounts.clear();
34
+ this.taskDefinitions.clear();
33
35
 
34
36
  for (const step of steps) {
37
+ this.taskDefinitions.set(step.name, step);
35
38
  const deps = step.dependencies ?? [];
36
39
  this.dependencyCounts.set(step.name, deps.length);
37
40
 
@@ -56,7 +59,7 @@ export class TaskStateManager<TContext> {
56
59
  * @returns An array of tasks that are ready to run.
57
60
  */
58
61
  processDependencies(): TaskStep<TContext>[] {
59
- const toRun = [...this.readyQueue];
62
+ const toRun = this.readyQueue;
60
63
  this.readyQueue = [];
61
64
 
62
65
  // Remove them from pendingSteps as they are now handed off to the executor
@@ -89,6 +92,13 @@ export class TaskStateManager<TContext> {
89
92
 
90
93
  if (result.status === "success") {
91
94
  this.handleSuccess(step.name);
95
+ } else if (result.status === "failure") {
96
+ // If continueOnError is true, treat as success for dependents to unblock the workflow
97
+ if (this.taskDefinitions.get(step.name)?.continueOnError) {
98
+ this.handleSuccess(step.name);
99
+ } else {
100
+ this.cascadeFailure(step.name);
101
+ }
92
102
  } else {
93
103
  this.cascadeFailure(step.name);
94
104
  }
package/src/TaskStep.ts CHANGED
@@ -25,6 +25,20 @@ export interface TaskStep<TContext> {
25
25
  */
26
26
  priority?: number;
27
27
 
28
+ /**
29
+ * Optional flag to indicate that the workflow should continue even if this task fails.
30
+ * If true, dependent tasks will execute as if this task succeeded.
31
+ * The task result will still be marked as "failure".
32
+ * Default is false.
33
+ */
34
+ continueOnError?: boolean;
35
+
36
+ /**
37
+ * Optional maximum execution time in milliseconds.
38
+ * If the task runs longer than this, it will be cancelled and marked as failed.
39
+ */
40
+ timeout?: number;
41
+
28
42
  /**
29
43
  * The core logic of the task.
30
44
  * @param context The shared context object, allowing for state to be passed between tasks.
@@ -22,9 +22,9 @@ export class DryRunExecutionStrategy<
22
22
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
23
23
  _signal?: AbortSignal
24
24
  ): Promise<TaskResult> {
25
- return Promise.resolve({
25
+ return {
26
26
  status: "success",
27
27
  message: "Dry run: simulated success " + step.name,
28
- });
28
+ };
29
29
  }
30
30
  }
@@ -13,8 +13,51 @@ export class StandardExecutionStrategy<
13
13
  context: TContext,
14
14
  signal?: AbortSignal
15
15
  ): Promise<TaskResult> {
16
+ if (!step.timeout) {
17
+ try {
18
+ return await step.run(context, signal);
19
+ } catch (e) {
20
+ // Check if error is due to abort
21
+ if (
22
+ signal?.aborted &&
23
+ ((e instanceof Error && e.name === "AbortError") ||
24
+ signal.reason === e)
25
+ ) {
26
+ return {
27
+ status: "cancelled",
28
+ message: "Task cancelled during execution",
29
+ };
30
+ }
31
+ return {
32
+ status: "failure",
33
+ error: e instanceof Error ? e.message : String(e),
34
+ };
35
+ }
36
+ }
37
+
38
+ const abortController = new AbortController();
39
+ const timeoutSignal = signal
40
+ ? AbortSignal.any([signal, abortController.signal])
41
+ : abortController.signal;
42
+
43
+ let timer: NodeJS.Timeout | undefined;
44
+ let resolveTimeout!: (value: TaskResult) => void;
45
+
16
46
  try {
17
- return await step.run(context, signal);
47
+ const timeoutPromise = new Promise<TaskResult>((resolve) => {
48
+ resolveTimeout = resolve;
49
+ timer = setTimeout(() => {
50
+ abortController.abort(new Error("Timeout"));
51
+ resolve({
52
+ status: "failure",
53
+ error: `Task timed out after ${step.timeout}ms`,
54
+ });
55
+ }, step.timeout);
56
+ });
57
+
58
+ const taskPromise = step.run(context, timeoutSignal);
59
+
60
+ return await Promise.race([taskPromise, timeoutPromise]);
18
61
  } catch (e) {
19
62
  // Check if error is due to abort
20
63
  if (
@@ -30,6 +73,10 @@ export class StandardExecutionStrategy<
30
73
  status: "failure",
31
74
  error: e instanceof Error ? e.message : String(e),
32
75
  };
76
+ } finally {
77
+ clearTimeout(timer);
78
+ // Settle the timeout promise to avoid memory leaks from Promise.race
79
+ resolveTimeout({ status: "cancelled" } as TaskResult);
33
80
  }
34
81
  }
35
82
  }