@calmo/task-runner 1.2.1 → 1.2.3

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 (54) hide show
  1. package/.gemini/commands/openspec/apply.toml +21 -0
  2. package/.gemini/commands/openspec/archive.toml +25 -0
  3. package/.gemini/commands/openspec/proposal.toml +26 -0
  4. package/AGENTS.md +18 -0
  5. package/CHANGELOG.md +23 -0
  6. package/GEMINI.md +8 -0
  7. package/coverage/coverage-final.json +5 -2
  8. package/coverage/index.html +20 -20
  9. package/coverage/lcov-report/index.html +20 -20
  10. package/coverage/lcov-report/src/EventBus.ts.html +337 -0
  11. package/coverage/{TaskGraphValidator.ts.html → lcov-report/src/TaskGraphValidator.ts.html} +44 -14
  12. package/coverage/lcov-report/src/TaskRunner.ts.html +307 -0
  13. package/coverage/lcov-report/src/WorkflowExecutor.ts.html +457 -0
  14. package/coverage/lcov-report/src/contracts/RunnerEvents.ts.html +217 -0
  15. package/coverage/lcov-report/src/contracts/index.html +116 -0
  16. package/coverage/lcov-report/src/index.html +161 -0
  17. package/coverage/lcov.info +190 -165
  18. package/coverage/src/EventBus.ts.html +337 -0
  19. package/coverage/{lcov-report → src}/TaskGraphValidator.ts.html +44 -14
  20. package/coverage/src/TaskRunner.ts.html +307 -0
  21. package/coverage/src/WorkflowExecutor.ts.html +457 -0
  22. package/coverage/src/contracts/RunnerEvents.ts.html +217 -0
  23. package/coverage/src/contracts/index.html +116 -0
  24. package/coverage/src/index.html +161 -0
  25. package/dist/EventBus.d.ts +26 -0
  26. package/dist/EventBus.js +56 -0
  27. package/dist/EventBus.js.map +1 -0
  28. package/dist/TaskGraphValidator.d.ts +6 -0
  29. package/dist/TaskGraphValidator.js +9 -0
  30. package/dist/TaskGraphValidator.js.map +1 -1
  31. package/dist/TaskRunner.d.ts +3 -36
  32. package/dist/TaskRunner.js +8 -127
  33. package/dist/TaskRunner.js.map +1 -1
  34. package/dist/WorkflowExecutor.d.ts +32 -0
  35. package/dist/WorkflowExecutor.js +109 -0
  36. package/dist/WorkflowExecutor.js.map +1 -0
  37. package/dist/contracts/ITaskGraphValidator.d.ts +6 -0
  38. package/dist/contracts/RunnerEvents.d.ts +36 -0
  39. package/dist/contracts/RunnerEvents.js +2 -0
  40. package/dist/contracts/RunnerEvents.js.map +1 -0
  41. package/openspec/AGENTS.md +456 -0
  42. package/openspec/changes/add-external-task-cancellation/proposal.md +14 -0
  43. package/openspec/changes/add-external-task-cancellation/tasks.md +10 -0
  44. package/openspec/project.md +31 -0
  45. package/package.json +1 -1
  46. package/src/EventBus.ts +84 -0
  47. package/src/TaskGraphValidator.ts +10 -0
  48. package/src/TaskRunner.ts +11 -196
  49. package/src/WorkflowExecutor.ts +124 -0
  50. package/src/contracts/ITaskGraphValidator.ts +7 -0
  51. package/src/contracts/RunnerEvents.ts +44 -0
  52. package/test-report.xml +49 -37
  53. package/coverage/TaskRunner.ts.html +0 -862
  54. package/coverage/lcov-report/TaskRunner.ts.html +0 -862
@@ -0,0 +1,217 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/contracts/RunnerEvents.ts</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../../prettify.css" />
9
+ <link rel="stylesheet" href="../../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../../index.html">All files</a> / <a href="index.html">src/contracts</a> RunnerEvents.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">0% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>0/0</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">0% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>0/0</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">0% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>0/0</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">0% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>0/0</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line low'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
111
+ <span class="cline-any cline-neutral">&nbsp;</span>
112
+ <span class="cline-any cline-neutral">&nbsp;</span>
113
+ <span class="cline-any cline-neutral">&nbsp;</span>
114
+ <span class="cline-any cline-neutral">&nbsp;</span>
115
+ <span class="cline-any cline-neutral">&nbsp;</span>
116
+ <span class="cline-any cline-neutral">&nbsp;</span>
117
+ <span class="cline-any cline-neutral">&nbsp;</span>
118
+ <span class="cline-any cline-neutral">&nbsp;</span>
119
+ <span class="cline-any cline-neutral">&nbsp;</span>
120
+ <span class="cline-any cline-neutral">&nbsp;</span>
121
+ <span class="cline-any cline-neutral">&nbsp;</span>
122
+ <span class="cline-any cline-neutral">&nbsp;</span>
123
+ <span class="cline-any cline-neutral">&nbsp;</span>
124
+ <span class="cline-any cline-neutral">&nbsp;</span>
125
+ <span class="cline-any cline-neutral">&nbsp;</span>
126
+ <span class="cline-any cline-neutral">&nbsp;</span>
127
+ <span class="cline-any cline-neutral">&nbsp;</span>
128
+ <span class="cline-any cline-neutral">&nbsp;</span>
129
+ <span class="cline-any cline-neutral">&nbsp;</span>
130
+ <span class="cline-any cline-neutral">&nbsp;</span>
131
+ <span class="cline-any cline-neutral">&nbsp;</span>
132
+ <span class="cline-any cline-neutral">&nbsp;</span>
133
+ <span class="cline-any cline-neutral">&nbsp;</span>
134
+ <span class="cline-any cline-neutral">&nbsp;</span>
135
+ <span class="cline-any cline-neutral">&nbsp;</span>
136
+ <span class="cline-any cline-neutral">&nbsp;</span>
137
+ <span class="cline-any cline-neutral">&nbsp;</span>
138
+ <span class="cline-any cline-neutral">&nbsp;</span>
139
+ <span class="cline-any cline-neutral">&nbsp;</span>
140
+ <span class="cline-any cline-neutral">&nbsp;</span>
141
+ <span class="cline-any cline-neutral">&nbsp;</span>
142
+ <span class="cline-any cline-neutral">&nbsp;</span>
143
+ <span class="cline-any cline-neutral">&nbsp;</span>
144
+ <span class="cline-any cline-neutral">&nbsp;</span>
145
+ <span class="cline-any cline-neutral">&nbsp;</span>
146
+ <span class="cline-any cline-neutral">&nbsp;</span>
147
+ <span class="cline-any cline-neutral">&nbsp;</span>
148
+ <span class="cline-any cline-neutral">&nbsp;</span>
149
+ <span class="cline-any cline-neutral">&nbsp;</span>
150
+ <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></td><td class="text"><pre class="prettyprint lang-js">import { TaskStep } from "../TaskStep.js";
155
+ import { TaskResult } from "../TaskResult.js";
156
+ &nbsp;
157
+ /**
158
+ * Define the payload for every possible event in the lifecycle.
159
+ */
160
+ export interface RunnerEventPayloads&lt;TContext&gt; {
161
+ workflowStart: {
162
+ context: TContext;
163
+ steps: TaskStep&lt;TContext&gt;[];
164
+ };
165
+ workflowEnd: {
166
+ context: TContext;
167
+ results: Map&lt;string, TaskResult&gt;;
168
+ };
169
+ taskStart: {
170
+ step: TaskStep&lt;TContext&gt;;
171
+ };
172
+ taskEnd: {
173
+ step: TaskStep&lt;TContext&gt;;
174
+ result: TaskResult;
175
+ };
176
+ taskSkipped: {
177
+ step: TaskStep&lt;TContext&gt;;
178
+ result: TaskResult;
179
+ };
180
+ }
181
+ &nbsp;
182
+ /**
183
+ * A generic listener type that maps the event key to its specific payload.
184
+ */
185
+ export type RunnerEventListener&lt;
186
+ TContext,
187
+ K extends keyof RunnerEventPayloads&lt;TContext&gt;,
188
+ &gt; = (data: RunnerEventPayloads&lt;TContext&gt;[K]) =&gt; void | Promise&lt;void&gt;;
189
+ &nbsp;
190
+ /**
191
+ * Helper type for the listeners map.
192
+ */
193
+ export type ListenerMap&lt;TContext&gt; = {
194
+ [K in keyof RunnerEventPayloads&lt;TContext&gt;]?: Set&lt;
195
+ RunnerEventListener&lt;TContext, K&gt;
196
+ &gt;;
197
+ };
198
+ &nbsp;</pre></td></tr></table></pre>
199
+
200
+ <div class='push'></div><!-- for sticky footer -->
201
+ </div><!-- /wrapper -->
202
+ <div class='footer quiet pad2 space-top1 center small'>
203
+ Code coverage generated by
204
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
205
+ at 2026-01-18T14:25:37.513Z
206
+ </div>
207
+ <script src="../../prettify.js"></script>
208
+ <script>
209
+ window.onload = function () {
210
+ prettyPrint();
211
+ };
212
+ </script>
213
+ <script src="../../sorter.js"></script>
214
+ <script src="../../block-navigation.js"></script>
215
+ </body>
216
+ </html>
217
+
@@ -0,0 +1,116 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/contracts</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../../prettify.css" />
9
+ <link rel="stylesheet" href="../../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../../index.html">All files</a> src/contracts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">0% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>0/0</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">0% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>0/0</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">0% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>0/0</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">0% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>0/0</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line low'></div>
65
+ <div class="pad1">
66
+ <table class="coverage-summary">
67
+ <thead>
68
+ <tr>
69
+ <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
70
+ <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
71
+ <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
72
+ <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
73
+ <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
74
+ <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
75
+ <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
76
+ <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
77
+ <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
78
+ <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
79
+ </tr>
80
+ </thead>
81
+ <tbody><tr>
82
+ <td class="file empty" data-value="RunnerEvents.ts"><a href="RunnerEvents.ts.html">RunnerEvents.ts</a></td>
83
+ <td data-value="0" class="pic empty">
84
+ <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
85
+ </td>
86
+ <td data-value="0" class="pct empty">0%</td>
87
+ <td data-value="0" class="abs empty">0/0</td>
88
+ <td data-value="0" class="pct empty">0%</td>
89
+ <td data-value="0" class="abs empty">0/0</td>
90
+ <td data-value="0" class="pct empty">0%</td>
91
+ <td data-value="0" class="abs empty">0/0</td>
92
+ <td data-value="0" class="pct empty">0%</td>
93
+ <td data-value="0" class="abs empty">0/0</td>
94
+ </tr>
95
+
96
+ </tbody>
97
+ </table>
98
+ </div>
99
+ <div class='push'></div><!-- for sticky footer -->
100
+ </div><!-- /wrapper -->
101
+ <div class='footer quiet pad2 space-top1 center small'>
102
+ Code coverage generated by
103
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
104
+ at 2026-01-18T14:25:37.513Z
105
+ </div>
106
+ <script src="../../prettify.js"></script>
107
+ <script>
108
+ window.onload = function () {
109
+ prettyPrint();
110
+ };
111
+ </script>
112
+ <script src="../../sorter.js"></script>
113
+ <script src="../../block-navigation.js"></script>
114
+ </body>
115
+ </html>
116
+
@@ -0,0 +1,161 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../prettify.css" />
9
+ <link rel="stylesheet" href="../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../index.html">All files</a> src</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">100% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>121/121</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">100% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>42/42</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">100% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>19/19</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">100% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>119/119</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line high'></div>
65
+ <div class="pad1">
66
+ <table class="coverage-summary">
67
+ <thead>
68
+ <tr>
69
+ <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
70
+ <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
71
+ <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
72
+ <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
73
+ <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
74
+ <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
75
+ <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
76
+ <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
77
+ <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
78
+ <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
79
+ </tr>
80
+ </thead>
81
+ <tbody><tr>
82
+ <td class="file high" data-value="EventBus.ts"><a href="EventBus.ts.html">EventBus.ts</a></td>
83
+ <td data-value="100" class="pic high">
84
+ <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
85
+ </td>
86
+ <td data-value="100" class="pct high">100%</td>
87
+ <td data-value="15" class="abs high">15/15</td>
88
+ <td data-value="100" class="pct high">100%</td>
89
+ <td data-value="8" class="abs high">8/8</td>
90
+ <td data-value="100" class="pct high">100%</td>
91
+ <td data-value="4" class="abs high">4/4</td>
92
+ <td data-value="100" class="pct high">100%</td>
93
+ <td data-value="15" class="abs high">15/15</td>
94
+ </tr>
95
+
96
+ <tr>
97
+ <td class="file high" data-value="TaskGraphValidator.ts"><a href="TaskGraphValidator.ts.html">TaskGraphValidator.ts</a></td>
98
+ <td data-value="100" class="pic high">
99
+ <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
100
+ </td>
101
+ <td data-value="100" class="pct high">100%</td>
102
+ <td data-value="46" class="abs high">46/46</td>
103
+ <td data-value="100" class="pct high">100%</td>
104
+ <td data-value="16" class="abs high">16/16</td>
105
+ <td data-value="100" class="pct high">100%</td>
106
+ <td data-value="5" class="abs high">5/5</td>
107
+ <td data-value="100" class="pct high">100%</td>
108
+ <td data-value="44" class="abs high">44/44</td>
109
+ </tr>
110
+
111
+ <tr>
112
+ <td class="file high" data-value="TaskRunner.ts"><a href="TaskRunner.ts.html">TaskRunner.ts</a></td>
113
+ <td data-value="100" class="pic high">
114
+ <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
115
+ </td>
116
+ <td data-value="100" class="pct high">100%</td>
117
+ <td data-value="12" class="abs high">12/12</td>
118
+ <td data-value="100" class="pct high">100%</td>
119
+ <td data-value="4" class="abs high">4/4</td>
120
+ <td data-value="100" class="pct high">100%</td>
121
+ <td data-value="5" class="abs high">5/5</td>
122
+ <td data-value="100" class="pct high">100%</td>
123
+ <td data-value="12" class="abs high">12/12</td>
124
+ </tr>
125
+
126
+ <tr>
127
+ <td class="file high" data-value="WorkflowExecutor.ts"><a href="WorkflowExecutor.ts.html">WorkflowExecutor.ts</a></td>
128
+ <td data-value="100" class="pic high">
129
+ <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
130
+ </td>
131
+ <td data-value="100" class="pct high">100%</td>
132
+ <td data-value="48" class="abs high">48/48</td>
133
+ <td data-value="100" class="pct high">100%</td>
134
+ <td data-value="14" class="abs high">14/14</td>
135
+ <td data-value="100" class="pct high">100%</td>
136
+ <td data-value="5" class="abs high">5/5</td>
137
+ <td data-value="100" class="pct high">100%</td>
138
+ <td data-value="48" class="abs high">48/48</td>
139
+ </tr>
140
+
141
+ </tbody>
142
+ </table>
143
+ </div>
144
+ <div class='push'></div><!-- for sticky footer -->
145
+ </div><!-- /wrapper -->
146
+ <div class='footer quiet pad2 space-top1 center small'>
147
+ Code coverage generated by
148
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
149
+ at 2026-01-18T14:25:37.513Z
150
+ </div>
151
+ <script src="../prettify.js"></script>
152
+ <script>
153
+ window.onload = function () {
154
+ prettyPrint();
155
+ };
156
+ </script>
157
+ <script src="../sorter.js"></script>
158
+ <script src="../block-navigation.js"></script>
159
+ </body>
160
+ </html>
161
+
@@ -0,0 +1,26 @@
1
+ import { RunnerEventListener, RunnerEventPayloads } from "./contracts/RunnerEvents.js";
2
+ /**
3
+ * Manages event subscriptions and emissions for the TaskRunner.
4
+ * @template TContext The shape of the shared context object.
5
+ */
6
+ export declare class EventBus<TContext> {
7
+ private listeners;
8
+ /**
9
+ * Subscribe to an event.
10
+ * @param event The event name.
11
+ * @param callback The callback to execute when the event is emitted.
12
+ */
13
+ on<K extends keyof RunnerEventPayloads<TContext>>(event: K, callback: RunnerEventListener<TContext, K>): void;
14
+ /**
15
+ * Unsubscribe from an event.
16
+ * @param event The event name.
17
+ * @param callback The callback to remove.
18
+ */
19
+ off<K extends keyof RunnerEventPayloads<TContext>>(event: K, callback: RunnerEventListener<TContext, K>): void;
20
+ /**
21
+ * Emit an event to all subscribers.
22
+ * @param event The event name.
23
+ * @param data The payload for the event.
24
+ */
25
+ emit<K extends keyof RunnerEventPayloads<TContext>>(event: K, data: RunnerEventPayloads<TContext>[K]): void;
26
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Manages event subscriptions and emissions for the TaskRunner.
3
+ * @template TContext The shape of the shared context object.
4
+ */
5
+ export class EventBus {
6
+ listeners = {};
7
+ /**
8
+ * Subscribe to an event.
9
+ * @param event The event name.
10
+ * @param callback The callback to execute when the event is emitted.
11
+ */
12
+ on(event, callback) {
13
+ if (!this.listeners[event]) {
14
+ // Type assertion needed because TypeScript cannot verify that the generic K
15
+ // matches the specific key in the mapped type during assignment.
16
+ this.listeners[event] = new Set();
17
+ }
18
+ // Type assertion needed to tell TS that this specific Set matches the callback type
19
+ this.listeners[event].add(callback);
20
+ }
21
+ /**
22
+ * Unsubscribe from an event.
23
+ * @param event The event name.
24
+ * @param callback The callback to remove.
25
+ */
26
+ off(event, callback) {
27
+ if (this.listeners[event]) {
28
+ this.listeners[event].delete(callback);
29
+ }
30
+ }
31
+ /**
32
+ * Emit an event to all subscribers.
33
+ * @param event The event name.
34
+ * @param data The payload for the event.
35
+ */
36
+ emit(event, data) {
37
+ const listeners = this.listeners[event];
38
+ if (listeners) {
39
+ for (const listener of listeners) {
40
+ try {
41
+ const result = listener(data);
42
+ if (result instanceof Promise) {
43
+ result.catch((error) => {
44
+ console.error(`Error in event listener for ${String(event)}:`, error);
45
+ });
46
+ }
47
+ }
48
+ catch (error) {
49
+ // Prevent listener errors from bubbling up
50
+ console.error(`Error in event listener for ${String(event)}:`, error);
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+ //# sourceMappingURL=EventBus.js.map
@@ -0,0 +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,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;oBAC9B,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;wBAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;4BACrB,OAAO,CAAC,KAAK,CACX,+BAA+B,MAAM,CAAC,KAAK,CAAC,GAAG,EAC/C,KAAK,CACN,CAAC;wBACJ,CAAC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,2CAA2C;oBAC3C,OAAO,CAAC,KAAK,CACX,+BAA+B,MAAM,CAAC,KAAK,CAAC,GAAG,EAC/C,KAAK,CACN,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -13,5 +13,11 @@ export declare class TaskGraphValidator implements ITaskGraphValidator {
13
13
  * @returns A ValidationResult object indicating the outcome of the validation.
14
14
  */
15
15
  validate(taskGraph: TaskGraph): ValidationResult;
16
+ /**
17
+ * Creates a human-readable error message from a validation result.
18
+ * @param result The validation result containing errors.
19
+ * @returns A formatted error string.
20
+ */
21
+ createErrorMessage(result: ValidationResult): string;
16
22
  private detectCycle;
17
23
  }
@@ -78,6 +78,15 @@ export class TaskGraphValidator {
78
78
  errors
79
79
  };
80
80
  }
81
+ /**
82
+ * Creates a human-readable error message from a validation result.
83
+ * @param result The validation result containing errors.
84
+ * @returns A formatted error string.
85
+ */
86
+ createErrorMessage(result) {
87
+ const errorDetails = result.errors.map(e => e.message);
88
+ return `Task graph validation failed: ${errorDetails.join("; ")}`;
89
+ }
81
90
  detectCycle(taskId, path, visited, recursionStack, adjacencyList) {
82
91
  visited.add(taskId);
83
92
  recursionStack.add(taskId);
@@ -1 +1 @@
1
- {"version":3,"file":"TaskGraphValidator.js","sourceRoot":"","sources":["../src/TaskGraphValidator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TaskGraphValidator.js","sourceRoot":"","sources":["../src/TaskGraphValidator.ts"],"names":[],"mappings":"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"}