@renseiai/agentfactory 0.8.7 → 0.8.9

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 (276) hide show
  1. package/dist/src/config/index.d.ts +1 -1
  2. package/dist/src/config/index.d.ts.map +1 -1
  3. package/dist/src/config/index.js +1 -1
  4. package/dist/src/config/repository-config.d.ts +37 -0
  5. package/dist/src/config/repository-config.d.ts.map +1 -1
  6. package/dist/src/config/repository-config.js +47 -0
  7. package/dist/src/config/repository-config.test.js +140 -1
  8. package/dist/src/governor/decision-engine.d.ts +3 -0
  9. package/dist/src/governor/decision-engine.d.ts.map +1 -1
  10. package/dist/src/governor/decision-engine.js +11 -0
  11. package/dist/src/governor/decision-engine.test.js +33 -0
  12. package/dist/src/governor/event-types.d.ts +18 -1
  13. package/dist/src/governor/event-types.d.ts.map +1 -1
  14. package/dist/src/governor/event-types.js +4 -0
  15. package/dist/src/governor/governor-types.d.ts +1 -1
  16. package/dist/src/governor/governor-types.d.ts.map +1 -1
  17. package/dist/src/governor/governor.d.ts +17 -1
  18. package/dist/src/governor/governor.d.ts.map +1 -1
  19. package/dist/src/governor/governor.js +112 -1
  20. package/dist/src/governor/governor.test.js +155 -0
  21. package/dist/src/index.d.ts +1 -0
  22. package/dist/src/index.d.ts.map +1 -1
  23. package/dist/src/index.js +1 -0
  24. package/dist/src/merge-queue/adapters/github-native.d.ts +22 -0
  25. package/dist/src/merge-queue/adapters/github-native.d.ts.map +1 -0
  26. package/dist/src/merge-queue/adapters/github-native.js +243 -0
  27. package/dist/src/merge-queue/adapters/github-native.test.d.ts +2 -0
  28. package/dist/src/merge-queue/adapters/github-native.test.d.ts.map +1 -0
  29. package/dist/src/merge-queue/adapters/github-native.test.js +384 -0
  30. package/dist/src/merge-queue/index.d.ts +18 -0
  31. package/dist/src/merge-queue/index.d.ts.map +1 -0
  32. package/dist/src/merge-queue/index.js +28 -0
  33. package/dist/src/merge-queue/merge-queue.integration.test.d.ts +2 -0
  34. package/dist/src/merge-queue/merge-queue.integration.test.d.ts.map +1 -0
  35. package/dist/src/merge-queue/merge-queue.integration.test.js +128 -0
  36. package/dist/src/merge-queue/types.d.ts +48 -0
  37. package/dist/src/merge-queue/types.d.ts.map +1 -0
  38. package/dist/src/merge-queue/types.js +8 -0
  39. package/dist/src/orchestrator/artifact-tracker.d.ts +93 -0
  40. package/dist/src/orchestrator/artifact-tracker.d.ts.map +1 -0
  41. package/dist/src/orchestrator/artifact-tracker.js +235 -0
  42. package/dist/src/orchestrator/artifact-tracker.test.d.ts +2 -0
  43. package/dist/src/orchestrator/artifact-tracker.test.d.ts.map +1 -0
  44. package/dist/src/orchestrator/artifact-tracker.test.js +189 -0
  45. package/dist/src/orchestrator/context-manager.d.ts +72 -0
  46. package/dist/src/orchestrator/context-manager.d.ts.map +1 -0
  47. package/dist/src/orchestrator/context-manager.js +120 -0
  48. package/dist/src/orchestrator/context-manager.test.d.ts +2 -0
  49. package/dist/src/orchestrator/context-manager.test.d.ts.map +1 -0
  50. package/dist/src/orchestrator/context-manager.test.js +137 -0
  51. package/dist/src/orchestrator/index.d.ts +8 -2
  52. package/dist/src/orchestrator/index.d.ts.map +1 -1
  53. package/dist/src/orchestrator/index.js +8 -1
  54. package/dist/src/orchestrator/issue-tracker-client.d.ts +4 -0
  55. package/dist/src/orchestrator/issue-tracker-client.d.ts.map +1 -1
  56. package/dist/src/orchestrator/orchestrator.d.ts +12 -0
  57. package/dist/src/orchestrator/orchestrator.d.ts.map +1 -1
  58. package/dist/src/orchestrator/orchestrator.js +282 -2
  59. package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -1
  60. package/dist/src/orchestrator/parse-work-result.js +6 -0
  61. package/dist/src/orchestrator/parse-work-result.test.js +19 -0
  62. package/dist/src/orchestrator/state-recovery.d.ts +21 -2
  63. package/dist/src/orchestrator/state-recovery.d.ts.map +1 -1
  64. package/dist/src/orchestrator/state-recovery.js +54 -2
  65. package/dist/src/orchestrator/state-recovery.test.js +106 -2
  66. package/dist/src/orchestrator/state-types.d.ts +62 -0
  67. package/dist/src/orchestrator/state-types.d.ts.map +1 -1
  68. package/dist/src/orchestrator/state-types.js +5 -1
  69. package/dist/src/orchestrator/summary-builder.d.ts +47 -0
  70. package/dist/src/orchestrator/summary-builder.d.ts.map +1 -0
  71. package/dist/src/orchestrator/summary-builder.js +240 -0
  72. package/dist/src/orchestrator/summary-builder.test.d.ts +2 -0
  73. package/dist/src/orchestrator/summary-builder.test.d.ts.map +1 -0
  74. package/dist/src/orchestrator/summary-builder.test.js +236 -0
  75. package/dist/src/orchestrator/types.d.ts +2 -0
  76. package/dist/src/orchestrator/types.d.ts.map +1 -1
  77. package/dist/src/orchestrator/work-types.d.ts +1 -1
  78. package/dist/src/orchestrator/work-types.d.ts.map +1 -1
  79. package/dist/src/providers/index.d.ts +64 -1
  80. package/dist/src/providers/index.d.ts.map +1 -1
  81. package/dist/src/providers/index.js +132 -1
  82. package/dist/src/providers/index.test.js +340 -2
  83. package/dist/src/routing/index.d.ts +7 -0
  84. package/dist/src/routing/index.d.ts.map +1 -0
  85. package/dist/src/routing/index.js +6 -0
  86. package/dist/src/routing/observation-recorder.d.ts +19 -0
  87. package/dist/src/routing/observation-recorder.d.ts.map +1 -0
  88. package/dist/src/routing/observation-recorder.js +73 -0
  89. package/dist/src/routing/observation-recorder.test.d.ts +2 -0
  90. package/dist/src/routing/observation-recorder.test.d.ts.map +1 -0
  91. package/dist/src/routing/observation-recorder.test.js +322 -0
  92. package/dist/src/routing/observation-store.d.ts +40 -0
  93. package/dist/src/routing/observation-store.d.ts.map +1 -0
  94. package/dist/src/routing/observation-store.js +1 -0
  95. package/dist/src/routing/observation-store.test.d.ts +2 -0
  96. package/dist/src/routing/observation-store.test.d.ts.map +1 -0
  97. package/dist/src/routing/observation-store.test.js +138 -0
  98. package/dist/src/routing/posterior-store.d.ts +12 -0
  99. package/dist/src/routing/posterior-store.d.ts.map +1 -0
  100. package/dist/src/routing/posterior-store.js +13 -0
  101. package/dist/src/routing/posterior-store.test.d.ts +2 -0
  102. package/dist/src/routing/posterior-store.test.d.ts.map +1 -0
  103. package/dist/src/routing/posterior-store.test.js +37 -0
  104. package/dist/src/routing/reward.d.ts +16 -0
  105. package/dist/src/routing/reward.d.ts.map +1 -0
  106. package/dist/src/routing/reward.js +29 -0
  107. package/dist/src/routing/reward.test.d.ts +2 -0
  108. package/dist/src/routing/reward.test.d.ts.map +1 -0
  109. package/dist/src/routing/reward.test.js +210 -0
  110. package/dist/src/routing/routing-engine.d.ts +20 -0
  111. package/dist/src/routing/routing-engine.d.ts.map +1 -0
  112. package/dist/src/routing/routing-engine.js +113 -0
  113. package/dist/src/routing/routing-engine.test.d.ts +2 -0
  114. package/dist/src/routing/routing-engine.test.d.ts.map +1 -0
  115. package/dist/src/routing/routing-engine.test.js +310 -0
  116. package/dist/src/routing/types.d.ts +157 -0
  117. package/dist/src/routing/types.d.ts.map +1 -0
  118. package/dist/src/routing/types.js +68 -0
  119. package/dist/src/routing/types.test.d.ts +2 -0
  120. package/dist/src/routing/types.test.d.ts.map +1 -0
  121. package/dist/src/routing/types.test.js +184 -0
  122. package/dist/src/templates/registry.test.js +2 -2
  123. package/dist/src/templates/types.d.ts +5 -0
  124. package/dist/src/templates/types.d.ts.map +1 -1
  125. package/dist/src/templates/types.js +3 -0
  126. package/dist/src/workflow/agent-cancellation.d.ts +37 -0
  127. package/dist/src/workflow/agent-cancellation.d.ts.map +1 -0
  128. package/dist/src/workflow/agent-cancellation.js +41 -0
  129. package/dist/src/workflow/agent-cancellation.test.d.ts +2 -0
  130. package/dist/src/workflow/agent-cancellation.test.d.ts.map +1 -0
  131. package/dist/src/workflow/agent-cancellation.test.js +86 -0
  132. package/dist/src/workflow/branching-router.d.ts +38 -0
  133. package/dist/src/workflow/branching-router.d.ts.map +1 -0
  134. package/dist/src/workflow/branching-router.js +52 -0
  135. package/dist/src/workflow/branching-router.test.d.ts +2 -0
  136. package/dist/src/workflow/branching-router.test.d.ts.map +1 -0
  137. package/dist/src/workflow/branching-router.test.js +209 -0
  138. package/dist/src/workflow/concurrency-semaphore.d.ts +21 -0
  139. package/dist/src/workflow/concurrency-semaphore.d.ts.map +1 -0
  140. package/dist/src/workflow/concurrency-semaphore.js +46 -0
  141. package/dist/src/workflow/concurrency-semaphore.test.d.ts +2 -0
  142. package/dist/src/workflow/concurrency-semaphore.test.d.ts.map +1 -0
  143. package/dist/src/workflow/concurrency-semaphore.test.js +183 -0
  144. package/dist/src/workflow/duration.d.ts +28 -0
  145. package/dist/src/workflow/duration.d.ts.map +1 -0
  146. package/dist/src/workflow/duration.js +57 -0
  147. package/dist/src/workflow/duration.test.d.ts +2 -0
  148. package/dist/src/workflow/duration.test.d.ts.map +1 -0
  149. package/dist/src/workflow/duration.test.js +74 -0
  150. package/dist/src/workflow/expression/ast.d.ts +53 -0
  151. package/dist/src/workflow/expression/ast.d.ts.map +1 -0
  152. package/dist/src/workflow/expression/ast.js +8 -0
  153. package/dist/src/workflow/expression/context.d.ts +40 -0
  154. package/dist/src/workflow/expression/context.d.ts.map +1 -0
  155. package/dist/src/workflow/expression/context.js +37 -0
  156. package/dist/src/workflow/expression/evaluator.d.ts +28 -0
  157. package/dist/src/workflow/expression/evaluator.d.ts.map +1 -0
  158. package/dist/src/workflow/expression/evaluator.js +165 -0
  159. package/dist/src/workflow/expression/evaluator.test.d.ts +2 -0
  160. package/dist/src/workflow/expression/evaluator.test.d.ts.map +1 -0
  161. package/dist/src/workflow/expression/evaluator.test.js +792 -0
  162. package/dist/src/workflow/expression/expression.test.d.ts +2 -0
  163. package/dist/src/workflow/expression/expression.test.d.ts.map +1 -0
  164. package/dist/src/workflow/expression/expression.test.js +516 -0
  165. package/dist/src/workflow/expression/helpers.d.ts +21 -0
  166. package/dist/src/workflow/expression/helpers.d.ts.map +1 -0
  167. package/dist/src/workflow/expression/helpers.js +56 -0
  168. package/dist/src/workflow/expression/index.d.ts +55 -0
  169. package/dist/src/workflow/expression/index.d.ts.map +1 -0
  170. package/dist/src/workflow/expression/index.js +71 -0
  171. package/dist/src/workflow/expression/lexer.d.ts +37 -0
  172. package/dist/src/workflow/expression/lexer.d.ts.map +1 -0
  173. package/dist/src/workflow/expression/lexer.js +166 -0
  174. package/dist/src/workflow/expression/parser.d.ts +23 -0
  175. package/dist/src/workflow/expression/parser.d.ts.map +1 -0
  176. package/dist/src/workflow/expression/parser.js +181 -0
  177. package/dist/src/workflow/gate-state.d.ts +115 -0
  178. package/dist/src/workflow/gate-state.d.ts.map +1 -0
  179. package/dist/src/workflow/gate-state.js +185 -0
  180. package/dist/src/workflow/gate-state.test.d.ts +2 -0
  181. package/dist/src/workflow/gate-state.test.d.ts.map +1 -0
  182. package/dist/src/workflow/gate-state.test.js +251 -0
  183. package/dist/src/workflow/gates/gate-evaluator.d.ts +119 -0
  184. package/dist/src/workflow/gates/gate-evaluator.d.ts.map +1 -0
  185. package/dist/src/workflow/gates/gate-evaluator.js +243 -0
  186. package/dist/src/workflow/gates/gate-evaluator.test.d.ts +2 -0
  187. package/dist/src/workflow/gates/gate-evaluator.test.d.ts.map +1 -0
  188. package/dist/src/workflow/gates/gate-evaluator.test.js +240 -0
  189. package/dist/src/workflow/gates/signal-gate.d.ts +114 -0
  190. package/dist/src/workflow/gates/signal-gate.d.ts.map +1 -0
  191. package/dist/src/workflow/gates/signal-gate.js +216 -0
  192. package/dist/src/workflow/gates/signal-gate.test.d.ts +2 -0
  193. package/dist/src/workflow/gates/signal-gate.test.d.ts.map +1 -0
  194. package/dist/src/workflow/gates/signal-gate.test.js +199 -0
  195. package/dist/src/workflow/gates/timeout-engine.d.ts +96 -0
  196. package/dist/src/workflow/gates/timeout-engine.d.ts.map +1 -0
  197. package/dist/src/workflow/gates/timeout-engine.js +162 -0
  198. package/dist/src/workflow/gates/timeout-engine.test.d.ts +2 -0
  199. package/dist/src/workflow/gates/timeout-engine.test.d.ts.map +1 -0
  200. package/dist/src/workflow/gates/timeout-engine.test.js +186 -0
  201. package/dist/src/workflow/gates/timer-gate.d.ts +125 -0
  202. package/dist/src/workflow/gates/timer-gate.d.ts.map +1 -0
  203. package/dist/src/workflow/gates/timer-gate.js +381 -0
  204. package/dist/src/workflow/gates/timer-gate.test.d.ts +2 -0
  205. package/dist/src/workflow/gates/timer-gate.test.d.ts.map +1 -0
  206. package/dist/src/workflow/gates/timer-gate.test.js +211 -0
  207. package/dist/src/workflow/gates/webhook-gate.d.ts +132 -0
  208. package/dist/src/workflow/gates/webhook-gate.d.ts.map +1 -0
  209. package/dist/src/workflow/gates/webhook-gate.js +216 -0
  210. package/dist/src/workflow/gates/webhook-gate.test.d.ts +2 -0
  211. package/dist/src/workflow/gates/webhook-gate.test.d.ts.map +1 -0
  212. package/dist/src/workflow/gates/webhook-gate.test.js +182 -0
  213. package/dist/src/workflow/index.d.ts +31 -3
  214. package/dist/src/workflow/index.d.ts.map +1 -1
  215. package/dist/src/workflow/index.js +20 -1
  216. package/dist/src/workflow/parallelism-executor.d.ts +25 -0
  217. package/dist/src/workflow/parallelism-executor.d.ts.map +1 -0
  218. package/dist/src/workflow/parallelism-executor.js +53 -0
  219. package/dist/src/workflow/parallelism-executor.test.d.ts +2 -0
  220. package/dist/src/workflow/parallelism-executor.test.d.ts.map +1 -0
  221. package/dist/src/workflow/parallelism-executor.test.js +191 -0
  222. package/dist/src/workflow/parallelism-types.d.ts +80 -0
  223. package/dist/src/workflow/parallelism-types.d.ts.map +1 -0
  224. package/dist/src/workflow/parallelism-types.js +8 -0
  225. package/dist/src/workflow/phase-context-injector.d.ts +29 -0
  226. package/dist/src/workflow/phase-context-injector.d.ts.map +1 -0
  227. package/dist/src/workflow/phase-context-injector.js +43 -0
  228. package/dist/src/workflow/phase-context-injector.test.d.ts +2 -0
  229. package/dist/src/workflow/phase-context-injector.test.d.ts.map +1 -0
  230. package/dist/src/workflow/phase-context-injector.test.js +123 -0
  231. package/dist/src/workflow/phase-output-collector.d.ts +39 -0
  232. package/dist/src/workflow/phase-output-collector.d.ts.map +1 -0
  233. package/dist/src/workflow/phase-output-collector.js +141 -0
  234. package/dist/src/workflow/phase-output-collector.test.d.ts +2 -0
  235. package/dist/src/workflow/phase-output-collector.test.d.ts.map +1 -0
  236. package/dist/src/workflow/phase-output-collector.test.js +179 -0
  237. package/dist/src/workflow/retry-resolver.d.ts +51 -0
  238. package/dist/src/workflow/retry-resolver.d.ts.map +1 -0
  239. package/dist/src/workflow/retry-resolver.js +70 -0
  240. package/dist/src/workflow/retry-resolver.test.d.ts +2 -0
  241. package/dist/src/workflow/retry-resolver.test.d.ts.map +1 -0
  242. package/dist/src/workflow/retry-resolver.test.js +149 -0
  243. package/dist/src/workflow/strategies/fan-in-strategy.d.ts +21 -0
  244. package/dist/src/workflow/strategies/fan-in-strategy.d.ts.map +1 -0
  245. package/dist/src/workflow/strategies/fan-in-strategy.js +92 -0
  246. package/dist/src/workflow/strategies/fan-in-strategy.test.d.ts +2 -0
  247. package/dist/src/workflow/strategies/fan-in-strategy.test.d.ts.map +1 -0
  248. package/dist/src/workflow/strategies/fan-in-strategy.test.js +182 -0
  249. package/dist/src/workflow/strategies/fan-out-strategy.d.ts +16 -0
  250. package/dist/src/workflow/strategies/fan-out-strategy.d.ts.map +1 -0
  251. package/dist/src/workflow/strategies/fan-out-strategy.js +47 -0
  252. package/dist/src/workflow/strategies/fan-out-strategy.test.d.ts +2 -0
  253. package/dist/src/workflow/strategies/fan-out-strategy.test.d.ts.map +1 -0
  254. package/dist/src/workflow/strategies/fan-out-strategy.test.js +97 -0
  255. package/dist/src/workflow/strategies/index.d.ts +4 -0
  256. package/dist/src/workflow/strategies/index.d.ts.map +1 -0
  257. package/dist/src/workflow/strategies/index.js +3 -0
  258. package/dist/src/workflow/strategies/race-strategy.d.ts +19 -0
  259. package/dist/src/workflow/strategies/race-strategy.d.ts.map +1 -0
  260. package/dist/src/workflow/strategies/race-strategy.js +92 -0
  261. package/dist/src/workflow/strategies/race-strategy.test.d.ts +2 -0
  262. package/dist/src/workflow/strategies/race-strategy.test.d.ts.map +1 -0
  263. package/dist/src/workflow/strategies/race-strategy.test.js +318 -0
  264. package/dist/src/workflow/transition-engine.d.ts +3 -1
  265. package/dist/src/workflow/transition-engine.d.ts.map +1 -1
  266. package/dist/src/workflow/transition-engine.js +26 -7
  267. package/dist/src/workflow/transition-engine.test.js +215 -11
  268. package/dist/src/workflow/workflow-registry.d.ts +46 -1
  269. package/dist/src/workflow/workflow-registry.d.ts.map +1 -1
  270. package/dist/src/workflow/workflow-registry.js +74 -0
  271. package/dist/src/workflow/workflow-registry.test.js +54 -0
  272. package/dist/src/workflow/workflow-types.d.ts +330 -12
  273. package/dist/src/workflow/workflow-types.d.ts.map +1 -1
  274. package/dist/src/workflow/workflow-types.js +100 -5
  275. package/dist/src/workflow/workflow-types.test.js +293 -2
  276. package/package.json +2 -2
@@ -11,6 +11,9 @@
11
11
  import { DEFAULT_GOVERNOR_CONFIG } from './governor-types.js';
12
12
  import { decideAction } from './decision-engine.js';
13
13
  import { WorkflowRegistry } from '../workflow/workflow-registry.js';
14
+ import { ParallelismExecutor } from '../workflow/parallelism-executor.js';
15
+ import { FanOutStrategy, FanInStrategy, RaceStrategy } from '../workflow/strategies/index.js';
16
+ import { evaluateTransitions } from '../workflow/transition-engine.js';
14
17
  // ---------------------------------------------------------------------------
15
18
  // Logging
16
19
  // ---------------------------------------------------------------------------
@@ -41,15 +44,26 @@ export class WorkflowGovernor {
41
44
  deps;
42
45
  callbacks;
43
46
  workflowRegistry;
47
+ parallelismExecutor;
44
48
  intervalHandle = null;
45
49
  running = false;
46
50
  scanning = false;
47
- constructor(config, deps, callbacks) {
51
+ constructor(config, deps, callbacks, parallelismExecutor) {
48
52
  const { workflow: workflowConfig, ...governorConfig } = config;
49
53
  this.config = { ...DEFAULT_GOVERNOR_CONFIG, ...governorConfig };
50
54
  this.deps = deps;
51
55
  this.callbacks = callbacks ?? {};
52
56
  this.workflowRegistry = WorkflowRegistry.create(workflowConfig);
57
+ // Use the provided executor or create a default one with all strategies registered
58
+ if (parallelismExecutor) {
59
+ this.parallelismExecutor = parallelismExecutor;
60
+ }
61
+ else {
62
+ this.parallelismExecutor = new ParallelismExecutor();
63
+ this.parallelismExecutor.registerStrategy('fan-out', new FanOutStrategy());
64
+ this.parallelismExecutor.registerStrategy('fan-in', new FanInStrategy());
65
+ this.parallelismExecutor.registerStrategy('race', new RaceStrategy());
66
+ }
53
67
  }
54
68
  // -------------------------------------------------------------------------
55
69
  // Lifecycle
@@ -207,6 +221,18 @@ export class WorkflowGovernor {
207
221
  break;
208
222
  }
209
223
  try {
224
+ // Handle parallel group dispatch separately
225
+ if (item.action === 'trigger-parallel-group') {
226
+ await this.handleParallelGroupDispatch(item.issue);
227
+ result.actionsDispatched++;
228
+ log.info('Dispatched parallel group action', {
229
+ issueIdentifier: item.issue.identifier,
230
+ action: item.action,
231
+ reason: item.reason,
232
+ priority: item.priority ?? 'none',
233
+ });
234
+ continue;
235
+ }
210
236
  await this.deps.dispatchWork(item.issue, item.action);
211
237
  result.actionsDispatched++;
212
238
  log.info('Dispatched action', {
@@ -264,4 +290,89 @@ export class WorkflowGovernor {
264
290
  };
265
291
  return decideAction(ctx);
266
292
  }
293
+ /**
294
+ * Handle dispatching work for a parallel group.
295
+ *
296
+ * Fetches sub-issues for the parent, finds the applicable parallelism group,
297
+ * and executes the group using the ParallelismExecutor.
298
+ */
299
+ async handleParallelGroupDispatch(issue) {
300
+ if (!this.deps.getSubIssues) {
301
+ log.warn('getSubIssues dependency not provided, falling back to normal dispatch');
302
+ return;
303
+ }
304
+ const workflow = this.workflowRegistry.getWorkflow();
305
+ if (!workflow?.parallelism)
306
+ return;
307
+ const subIssues = await this.deps.getSubIssues(issue.id);
308
+ // Find the applicable parallelism group.
309
+ // Use the first group whose phases include a phase that can be
310
+ // resolved from the current workflow transitions.
311
+ const group = workflow.parallelism.find(g => g.phases.length > 0);
312
+ if (!group)
313
+ return;
314
+ const tasks = subIssues.map(sub => ({
315
+ id: sub.id,
316
+ issueId: sub.identifier,
317
+ phaseName: group.phases[0],
318
+ }));
319
+ const result = await this.parallelismExecutor.execute(group, tasks, async (task) => {
320
+ await this.deps.dispatchWork(subIssues.find(s => s.id === task.id), `trigger-${task.phaseName}`);
321
+ return {
322
+ id: task.id,
323
+ issueId: task.issueId,
324
+ success: true,
325
+ };
326
+ });
327
+ log.info('Parallel group dispatched', {
328
+ group: group.name,
329
+ strategy: group.strategy,
330
+ completed: result.completed.length,
331
+ failed: result.failed.length,
332
+ cancelled: result.cancelled.length,
333
+ });
334
+ // Propagate result to advance parent issue if group completed successfully
335
+ await this.handleParallelGroupCompletion(issue, result, group);
336
+ }
337
+ /**
338
+ * Handle post-parallel-group completion: if all tasks succeeded,
339
+ * evaluate transitions to advance the parent issue to the next phase.
340
+ */
341
+ async handleParallelGroupCompletion(parentIssue, result, group) {
342
+ // Only advance if the group completed with no failures
343
+ const allSucceeded = result.failed.length === 0 && result.completed.length > 0
344
+ && result.completed.every(t => t.success);
345
+ if (!allSucceeded) {
346
+ log.info('Parallel group has failures, not advancing parent', {
347
+ group: group.name,
348
+ failedCount: result.failed.length,
349
+ });
350
+ return;
351
+ }
352
+ // Evaluate the next transition for the parent issue.
353
+ // After a parallel development group completes, the parent
354
+ // should transition based on its next status mapping.
355
+ const nextPhaseResult = evaluateTransitions({
356
+ issue: { ...parentIssue, status: 'Finished' },
357
+ registry: this.workflowRegistry,
358
+ isParentIssue: true,
359
+ });
360
+ if (nextPhaseResult.action !== 'none') {
361
+ log.info('Advancing parent after parallel group completion', {
362
+ issueIdentifier: parentIssue.identifier,
363
+ nextAction: nextPhaseResult.action,
364
+ reason: nextPhaseResult.reason,
365
+ });
366
+ try {
367
+ await this.deps.dispatchWork(parentIssue, nextPhaseResult.action);
368
+ }
369
+ catch (err) {
370
+ const errorMsg = err instanceof Error ? err.message : String(err);
371
+ log.error('Failed to advance parent after parallel group', {
372
+ issueIdentifier: parentIssue.identifier,
373
+ error: errorMsg,
374
+ });
375
+ }
376
+ }
377
+ }
267
378
  }
@@ -512,3 +512,158 @@ describe('WorkflowGovernor.scanOnce — PRIORITY override sorting', () => {
512
512
  expect(dispatchWork.mock.calls[2][0]).toEqual(expect.objectContaining({ id: 'c' }));
513
513
  });
514
514
  });
515
+ // ---------------------------------------------------------------------------
516
+ // Parallel group dispatch
517
+ // ---------------------------------------------------------------------------
518
+ describe('WorkflowGovernor.scanOnce — parallel group dispatch', () => {
519
+ function makeWorkflowWithParallelism() {
520
+ return {
521
+ apiVersion: 'v1.1',
522
+ kind: 'WorkflowDefinition',
523
+ metadata: { name: 'test-parallel' },
524
+ phases: [
525
+ { name: 'development', template: 'development' },
526
+ { name: 'qa', template: 'qa' },
527
+ ],
528
+ transitions: [
529
+ { from: 'Backlog', to: 'development' },
530
+ { from: 'Finished', to: 'qa' },
531
+ ],
532
+ parallelism: [
533
+ {
534
+ name: 'dev-parallel',
535
+ phases: ['development'],
536
+ strategy: 'fan-out',
537
+ },
538
+ ],
539
+ };
540
+ }
541
+ it('handles trigger-parallel-group by dispatching sub-issues', async () => {
542
+ const parentIssue = makeIssue({
543
+ id: 'parent-1',
544
+ identifier: 'SUP-100',
545
+ status: 'Backlog',
546
+ });
547
+ const subIssues = [
548
+ makeIssue({ id: 'sub-1', identifier: 'SUP-101', status: 'Backlog', parentId: 'parent-1' }),
549
+ makeIssue({ id: 'sub-2', identifier: 'SUP-102', status: 'Backlog', parentId: 'parent-1' }),
550
+ ];
551
+ const dispatchWork = vi.fn().mockResolvedValue(undefined);
552
+ const getSubIssues = vi.fn().mockResolvedValue(subIssues);
553
+ const deps = makeMockDeps({
554
+ listIssues: vi.fn().mockResolvedValue([parentIssue]),
555
+ isParentIssue: vi.fn().mockResolvedValue(true),
556
+ dispatchWork,
557
+ getSubIssues,
558
+ });
559
+ const governor = new WorkflowGovernor(makeConfig({
560
+ workflow: { workflow: makeWorkflowWithParallelism(), useBuiltinDefault: false },
561
+ }), deps);
562
+ const results = await governor.scanOnce();
563
+ expect(results[0].actionsDispatched).toBe(1);
564
+ expect(getSubIssues).toHaveBeenCalledWith('parent-1');
565
+ // dispatchWork is called for each sub-issue via the ParallelismExecutor,
566
+ // plus once more to advance the parent to the next phase (trigger-qa)
567
+ expect(dispatchWork).toHaveBeenCalledTimes(3);
568
+ expect(dispatchWork).toHaveBeenCalledWith(expect.objectContaining({ id: 'sub-1' }), 'trigger-development');
569
+ expect(dispatchWork).toHaveBeenCalledWith(expect.objectContaining({ id: 'sub-2' }), 'trigger-development');
570
+ // Parent advanced to QA after parallel group completion
571
+ expect(dispatchWork).toHaveBeenCalledWith(expect.objectContaining({ id: 'parent-1' }), 'trigger-qa');
572
+ });
573
+ it('handles missing getSubIssues gracefully', async () => {
574
+ const parentIssue = makeIssue({
575
+ id: 'parent-1',
576
+ identifier: 'SUP-100',
577
+ status: 'Backlog',
578
+ });
579
+ const dispatchWork = vi.fn().mockResolvedValue(undefined);
580
+ const deps = makeMockDeps({
581
+ listIssues: vi.fn().mockResolvedValue([parentIssue]),
582
+ isParentIssue: vi.fn().mockResolvedValue(true),
583
+ dispatchWork,
584
+ // getSubIssues intentionally not provided
585
+ });
586
+ const governor = new WorkflowGovernor(makeConfig({
587
+ workflow: { workflow: makeWorkflowWithParallelism(), useBuiltinDefault: false },
588
+ }), deps);
589
+ const results = await governor.scanOnce();
590
+ // The action is counted as dispatched (the parallel group handler ran),
591
+ // but dispatchWork is NOT called for sub-issues since getSubIssues is missing
592
+ expect(results[0].actionsDispatched).toBe(1);
593
+ expect(dispatchWork).not.toHaveBeenCalled();
594
+ });
595
+ it('fan-in group completing advances parent to next phase', async () => {
596
+ const fanInWorkflow = {
597
+ apiVersion: 'v1.1',
598
+ kind: 'WorkflowDefinition',
599
+ metadata: { name: 'test-fan-in' },
600
+ phases: [
601
+ { name: 'development', template: 'development' },
602
+ { name: 'qa', template: 'qa' },
603
+ ],
604
+ transitions: [
605
+ { from: 'Backlog', to: 'development' },
606
+ { from: 'Finished', to: 'qa' },
607
+ ],
608
+ parallelism: [
609
+ {
610
+ name: 'dev-fan-in',
611
+ phases: ['development'],
612
+ strategy: 'fan-in',
613
+ waitForAll: true,
614
+ },
615
+ ],
616
+ };
617
+ const parentIssue = makeIssue({
618
+ id: 'parent-1',
619
+ identifier: 'SUP-200',
620
+ status: 'Backlog',
621
+ });
622
+ const subIssues = [
623
+ makeIssue({ id: 'sub-1', identifier: 'SUP-201', status: 'Backlog', parentId: 'parent-1' }),
624
+ makeIssue({ id: 'sub-2', identifier: 'SUP-202', status: 'Backlog', parentId: 'parent-1' }),
625
+ makeIssue({ id: 'sub-3', identifier: 'SUP-203', status: 'Backlog', parentId: 'parent-1' }),
626
+ ];
627
+ const dispatchWork = vi.fn().mockResolvedValue(undefined);
628
+ const getSubIssues = vi.fn().mockResolvedValue(subIssues);
629
+ const deps = makeMockDeps({
630
+ listIssues: vi.fn().mockResolvedValue([parentIssue]),
631
+ isParentIssue: vi.fn().mockResolvedValue(true),
632
+ dispatchWork,
633
+ getSubIssues,
634
+ });
635
+ const governor = new WorkflowGovernor(makeConfig({
636
+ workflow: { workflow: fanInWorkflow, useBuiltinDefault: false },
637
+ }), deps);
638
+ const results = await governor.scanOnce();
639
+ expect(results[0].actionsDispatched).toBe(1);
640
+ // All 3 sub-issues dispatched + 1 parent advancement to QA
641
+ expect(dispatchWork).toHaveBeenCalledTimes(4);
642
+ // Sub-issues dispatched for development
643
+ expect(dispatchWork).toHaveBeenCalledWith(expect.objectContaining({ id: 'sub-1' }), 'trigger-development');
644
+ expect(dispatchWork).toHaveBeenCalledWith(expect.objectContaining({ id: 'sub-2' }), 'trigger-development');
645
+ expect(dispatchWork).toHaveBeenCalledWith(expect.objectContaining({ id: 'sub-3' }), 'trigger-development');
646
+ // Parent advanced to QA after all fan-in tasks completed
647
+ expect(dispatchWork).toHaveBeenCalledWith(expect.objectContaining({ id: 'parent-1' }), 'trigger-qa');
648
+ });
649
+ it('non-parent issues with parallelism groups dispatch normally', async () => {
650
+ const issue = makeIssue({
651
+ id: 'issue-1',
652
+ identifier: 'SUP-100',
653
+ status: 'Backlog',
654
+ });
655
+ const dispatchWork = vi.fn().mockResolvedValue(undefined);
656
+ const deps = makeMockDeps({
657
+ listIssues: vi.fn().mockResolvedValue([issue]),
658
+ isParentIssue: vi.fn().mockResolvedValue(false),
659
+ dispatchWork,
660
+ });
661
+ const governor = new WorkflowGovernor(makeConfig({
662
+ workflow: { workflow: makeWorkflowWithParallelism(), useBuiltinDefault: false },
663
+ }), deps);
664
+ const results = await governor.scanOnce();
665
+ expect(results[0].actionsDispatched).toBe(1);
666
+ // Normal dispatch, not parallel
667
+ expect(dispatchWork).toHaveBeenCalledWith(expect.objectContaining({ id: 'issue-1' }), 'trigger-development');
668
+ });
669
+ });
@@ -9,4 +9,5 @@ export * from './config/index.js';
9
9
  export * from './manifest/index.js';
10
10
  export * from './tools/index.js';
11
11
  export * from './workflow/index.js';
12
+ export * from './routing/index.js';
12
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AACpC,cAAc,aAAa,CAAA;AAC3B,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AACpC,cAAc,aAAa,CAAA;AAC3B,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA"}
package/dist/src/index.js CHANGED
@@ -9,3 +9,4 @@ export * from './config/index.js';
9
9
  export * from './manifest/index.js';
10
10
  export * from './tools/index.js';
11
11
  export * from './workflow/index.js';
12
+ export * from './routing/index.js';
@@ -0,0 +1,22 @@
1
+ /**
2
+ * GitHub Native Merge Queue Adapter
3
+ *
4
+ * Implements MergeQueueAdapter for GitHub's built-in merge queue feature.
5
+ * Uses `gh api graphql` CLI for all GitHub API interactions.
6
+ */
7
+ import type { MergeQueueAdapter, MergeQueueStatus } from '../types.js';
8
+ export declare class GitHubNativeMergeQueueAdapter implements MergeQueueAdapter {
9
+ readonly name: "github-native";
10
+ canEnqueue(owner: string, repo: string, prNumber: number): Promise<boolean>;
11
+ enqueue(owner: string, repo: string, prNumber: number): Promise<MergeQueueStatus>;
12
+ getStatus(owner: string, repo: string, prNumber: number): Promise<MergeQueueStatus>;
13
+ dequeue(owner: string, repo: string, prNumber: number): Promise<void>;
14
+ isEnabled(owner: string, repo: string): Promise<boolean>;
15
+ /** Get the GraphQL node ID for a PR */
16
+ private getPRNodeId;
17
+ /** Execute a GraphQL query/mutation via gh CLI with retry */
18
+ private graphql;
19
+ /** Map GitHub merge queue entry to our MergeQueueStatus */
20
+ private mapEntryToStatus;
21
+ }
22
+ //# sourceMappingURL=github-native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-native.d.ts","sourceRoot":"","sources":["../../../../src/merge-queue/adapters/github-native.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAatE,qBAAa,6BAA8B,YAAW,iBAAiB;IACrE,QAAQ,CAAC,IAAI,EAAG,eAAe,CAAS;IAElC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA6C3E,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAwCjF,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA+FnF,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBrE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmC9D,uCAAuC;YACzB,WAAW;IAiBzB,6DAA6D;YAC/C,OAAO;IAgCrB,2DAA2D;IAC3D,OAAO,CAAC,gBAAgB;CAgBzB"}
@@ -0,0 +1,243 @@
1
+ /**
2
+ * GitHub Native Merge Queue Adapter
3
+ *
4
+ * Implements MergeQueueAdapter for GitHub's built-in merge queue feature.
5
+ * Uses `gh api graphql` CLI for all GitHub API interactions.
6
+ */
7
+ import { exec } from 'child_process';
8
+ import { promisify } from 'util';
9
+ const execAsync = promisify(exec);
10
+ /** Timeout for GitHub API calls (30s) */
11
+ const GH_API_TIMEOUT = 30000;
12
+ /** Maximum retries for transient failures */
13
+ const MAX_RETRIES = 2;
14
+ /** Backoff delay between retries (ms) */
15
+ const RETRY_DELAY = 1000;
16
+ export class GitHubNativeMergeQueueAdapter {
17
+ name = 'github-native';
18
+ async canEnqueue(owner, repo, prNumber) {
19
+ try {
20
+ const query = `
21
+ query($owner: String!, $repo: String!, $prNumber: Int!) {
22
+ repository(owner: $owner, name: $repo) {
23
+ pullRequest(number: $prNumber) {
24
+ mergeable
25
+ reviewDecision
26
+ mergeQueueEntry { state }
27
+ baseRef {
28
+ branchProtectionRule {
29
+ requiresStatusChecks
30
+ }
31
+ }
32
+ }
33
+ }
34
+ }
35
+ `;
36
+ const result = await this.graphql(query, { owner, repo, prNumber });
37
+ const pr = result.repository.pullRequest;
38
+ // Already in queue
39
+ if (pr.mergeQueueEntry)
40
+ return false;
41
+ // Must be mergeable
42
+ if (pr.mergeable !== 'MERGEABLE')
43
+ return false;
44
+ // Must be approved (if reviews are required)
45
+ if (pr.reviewDecision && pr.reviewDecision !== 'APPROVED')
46
+ return false;
47
+ return true;
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ }
53
+ async enqueue(owner, repo, prNumber) {
54
+ // First get the PR's node ID
55
+ const prId = await this.getPRNodeId(owner, repo, prNumber);
56
+ const mutation = `
57
+ mutation($prId: ID!) {
58
+ enqueuePullRequest(input: { pullRequestId: $prId }) {
59
+ mergeQueueEntry {
60
+ state
61
+ position
62
+ headCommit { oid }
63
+ enqueuedAt
64
+ }
65
+ }
66
+ }
67
+ `;
68
+ try {
69
+ const result = await this.graphql(mutation, { prId });
70
+ const entry = result.enqueuePullRequest.mergeQueueEntry;
71
+ return this.mapEntryToStatus(entry);
72
+ }
73
+ catch (error) {
74
+ return {
75
+ state: 'failed',
76
+ failureReason: error instanceof Error ? error.message : String(error),
77
+ checksStatus: [],
78
+ };
79
+ }
80
+ }
81
+ async getStatus(owner, repo, prNumber) {
82
+ const query = `
83
+ query($owner: String!, $repo: String!, $prNumber: Int!) {
84
+ repository(owner: $owner, name: $repo) {
85
+ pullRequest(number: $prNumber) {
86
+ mergeQueueEntry {
87
+ state
88
+ position
89
+ headCommit { oid }
90
+ enqueuedAt
91
+ }
92
+ commits(last: 1) {
93
+ nodes {
94
+ commit {
95
+ statusCheckRollup {
96
+ contexts(first: 50) {
97
+ nodes {
98
+ ... on CheckRun {
99
+ name
100
+ conclusion
101
+ status
102
+ }
103
+ ... on StatusContext {
104
+ context
105
+ state
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+ `;
117
+ const result = await this.graphql(query, { owner, repo, prNumber });
118
+ const pr = result.repository.pullRequest;
119
+ if (!pr.mergeQueueEntry) {
120
+ return { state: 'not-queued', checksStatus: [] };
121
+ }
122
+ const status = this.mapEntryToStatus(pr.mergeQueueEntry);
123
+ // Map check statuses
124
+ const commitNode = pr.commits.nodes[0];
125
+ if (commitNode?.commit.statusCheckRollup) {
126
+ status.checksStatus = commitNode.commit.statusCheckRollup.contexts.nodes.map((node) => {
127
+ if ('name' in node) {
128
+ return {
129
+ name: node.name,
130
+ status: node.conclusion === 'SUCCESS' ? 'pass'
131
+ : node.status === 'COMPLETED' ? 'fail'
132
+ : 'pending',
133
+ };
134
+ }
135
+ return {
136
+ name: node.context,
137
+ status: node.state === 'SUCCESS' ? 'pass'
138
+ : node.state === 'PENDING' ? 'pending'
139
+ : 'fail',
140
+ };
141
+ });
142
+ }
143
+ return status;
144
+ }
145
+ async dequeue(owner, repo, prNumber) {
146
+ const prId = await this.getPRNodeId(owner, repo, prNumber);
147
+ const mutation = `
148
+ mutation($prId: ID!) {
149
+ dequeuePullRequest(input: { pullRequestId: $prId }) {
150
+ mergeQueueEntry {
151
+ state
152
+ }
153
+ }
154
+ }
155
+ `;
156
+ await this.graphql(mutation, { prId });
157
+ }
158
+ async isEnabled(owner, repo) {
159
+ try {
160
+ const query = `
161
+ query($owner: String!, $repo: String!) {
162
+ repository(owner: $owner, name: $repo) {
163
+ defaultBranchRef {
164
+ branchProtectionRule {
165
+ requiresMergeQueue
166
+ }
167
+ }
168
+ }
169
+ }
170
+ `;
171
+ // Note: requiresMergeQueue might not be available in all GitHub API versions.
172
+ // Fallback: check if merge queue entries exist
173
+ const result = await this.graphql(query, { owner, repo });
174
+ return result.repository.defaultBranchRef?.branchProtectionRule?.requiresMergeQueue ?? false;
175
+ }
176
+ catch {
177
+ return false;
178
+ }
179
+ }
180
+ // ---------------------------------------------------------------------------
181
+ // Private helpers
182
+ // ---------------------------------------------------------------------------
183
+ /** Get the GraphQL node ID for a PR */
184
+ async getPRNodeId(owner, repo, prNumber) {
185
+ const query = `
186
+ query($owner: String!, $repo: String!, $prNumber: Int!) {
187
+ repository(owner: $owner, name: $repo) {
188
+ pullRequest(number: $prNumber) {
189
+ id
190
+ }
191
+ }
192
+ }
193
+ `;
194
+ const result = await this.graphql(query, { owner, repo, prNumber });
195
+ return result.repository.pullRequest.id;
196
+ }
197
+ /** Execute a GraphQL query/mutation via gh CLI with retry */
198
+ async graphql(query, variables) {
199
+ const varsArgs = Object.entries(variables)
200
+ .map(([key, value]) => {
201
+ if (typeof value === 'number') {
202
+ return `-F ${key}=${value}`;
203
+ }
204
+ return `-f ${key}=${String(value)}`;
205
+ })
206
+ .join(' ');
207
+ const command = `gh api graphql -f query='${query.replace(/'/g, "'\\''")}' ${varsArgs}`;
208
+ let lastError = null;
209
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
210
+ try {
211
+ const { stdout } = await execAsync(command, { timeout: GH_API_TIMEOUT });
212
+ const response = JSON.parse(stdout);
213
+ if (response.errors?.length) {
214
+ throw new Error(response.errors.map((e) => e.message).join('; '));
215
+ }
216
+ return response.data;
217
+ }
218
+ catch (error) {
219
+ lastError = error instanceof Error ? error : new Error(String(error));
220
+ if (attempt < MAX_RETRIES) {
221
+ await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY * (attempt + 1)));
222
+ }
223
+ }
224
+ }
225
+ throw lastError;
226
+ }
227
+ /** Map GitHub merge queue entry to our MergeQueueStatus */
228
+ mapEntryToStatus(entry) {
229
+ const stateMap = {
230
+ QUEUED: 'queued',
231
+ AWAITING_CHECKS: 'queued',
232
+ MERGEABLE: 'merging',
233
+ MERGED: 'merged',
234
+ UNMERGEABLE: 'failed',
235
+ LOCKED: 'blocked',
236
+ };
237
+ return {
238
+ state: stateMap[entry.state] ?? 'not-queued',
239
+ position: entry.position,
240
+ checksStatus: [],
241
+ };
242
+ }
243
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=github-native.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-native.test.d.ts","sourceRoot":"","sources":["../../../../src/merge-queue/adapters/github-native.test.ts"],"names":[],"mappings":""}