@generacy-ai/orchestrator 0.0.0-preview-20260304013206

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 (274) hide show
  1. package/LICENSE +191 -0
  2. package/dist/auth/api-key.d.ts +63 -0
  3. package/dist/auth/api-key.d.ts.map +1 -0
  4. package/dist/auth/api-key.js +102 -0
  5. package/dist/auth/api-key.js.map +1 -0
  6. package/dist/auth/github-oauth.d.ts +29 -0
  7. package/dist/auth/github-oauth.d.ts.map +1 -0
  8. package/dist/auth/github-oauth.js +136 -0
  9. package/dist/auth/github-oauth.js.map +1 -0
  10. package/dist/auth/index.d.ts +5 -0
  11. package/dist/auth/index.d.ts.map +1 -0
  12. package/dist/auth/index.js +9 -0
  13. package/dist/auth/index.js.map +1 -0
  14. package/dist/auth/jwt.d.ts +34 -0
  15. package/dist/auth/jwt.d.ts.map +1 -0
  16. package/dist/auth/jwt.js +74 -0
  17. package/dist/auth/jwt.js.map +1 -0
  18. package/dist/auth/middleware.d.ts +43 -0
  19. package/dist/auth/middleware.d.ts.map +1 -0
  20. package/dist/auth/middleware.js +101 -0
  21. package/dist/auth/middleware.js.map +1 -0
  22. package/dist/config/index.d.ts +3 -0
  23. package/dist/config/index.d.ts.map +1 -0
  24. package/dist/config/index.js +5 -0
  25. package/dist/config/index.js.map +1 -0
  26. package/dist/config/loader.d.ts +21 -0
  27. package/dist/config/loader.d.ts.map +1 -0
  28. package/dist/config/loader.js +295 -0
  29. package/dist/config/loader.js.map +1 -0
  30. package/dist/config/schema.d.ts +733 -0
  31. package/dist/config/schema.d.ts.map +1 -0
  32. package/dist/config/schema.js +174 -0
  33. package/dist/config/schema.js.map +1 -0
  34. package/dist/index.d.ts +24 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +33 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/middleware/error-handler.d.ts +30 -0
  39. package/dist/middleware/error-handler.d.ts.map +1 -0
  40. package/dist/middleware/error-handler.js +173 -0
  41. package/dist/middleware/error-handler.js.map +1 -0
  42. package/dist/middleware/index.d.ts +4 -0
  43. package/dist/middleware/index.d.ts.map +1 -0
  44. package/dist/middleware/index.js +4 -0
  45. package/dist/middleware/index.js.map +1 -0
  46. package/dist/middleware/rate-limit.d.ts +32 -0
  47. package/dist/middleware/rate-limit.d.ts.map +1 -0
  48. package/dist/middleware/rate-limit.js +92 -0
  49. package/dist/middleware/rate-limit.js.map +1 -0
  50. package/dist/middleware/request-logger.d.ts +31 -0
  51. package/dist/middleware/request-logger.d.ts.map +1 -0
  52. package/dist/middleware/request-logger.js +89 -0
  53. package/dist/middleware/request-logger.js.map +1 -0
  54. package/dist/routes/agents.d.ts +7 -0
  55. package/dist/routes/agents.d.ts.map +1 -0
  56. package/dist/routes/agents.js +78 -0
  57. package/dist/routes/agents.js.map +1 -0
  58. package/dist/routes/dispatch.d.ts +8 -0
  59. package/dist/routes/dispatch.d.ts.map +1 -0
  60. package/dist/routes/dispatch.js +46 -0
  61. package/dist/routes/dispatch.js.map +1 -0
  62. package/dist/routes/events.d.ts +14 -0
  63. package/dist/routes/events.d.ts.map +1 -0
  64. package/dist/routes/events.js +240 -0
  65. package/dist/routes/events.js.map +1 -0
  66. package/dist/routes/health.d.ts +14 -0
  67. package/dist/routes/health.d.ts.map +1 -0
  68. package/dist/routes/health.js +132 -0
  69. package/dist/routes/health.js.map +1 -0
  70. package/dist/routes/index.d.ts +36 -0
  71. package/dist/routes/index.d.ts.map +1 -0
  72. package/dist/routes/index.js +34 -0
  73. package/dist/routes/index.js.map +1 -0
  74. package/dist/routes/integrations.d.ts +34 -0
  75. package/dist/routes/integrations.d.ts.map +1 -0
  76. package/dist/routes/integrations.js +81 -0
  77. package/dist/routes/integrations.js.map +1 -0
  78. package/dist/routes/metrics.d.ts +31 -0
  79. package/dist/routes/metrics.d.ts.map +1 -0
  80. package/dist/routes/metrics.js +157 -0
  81. package/dist/routes/metrics.js.map +1 -0
  82. package/dist/routes/pr-webhooks.d.ts +15 -0
  83. package/dist/routes/pr-webhooks.d.ts.map +1 -0
  84. package/dist/routes/pr-webhooks.js +114 -0
  85. package/dist/routes/pr-webhooks.js.map +1 -0
  86. package/dist/routes/queue.d.ts +7 -0
  87. package/dist/routes/queue.d.ts.map +1 -0
  88. package/dist/routes/queue.js +94 -0
  89. package/dist/routes/queue.js.map +1 -0
  90. package/dist/routes/webhooks.d.ts +15 -0
  91. package/dist/routes/webhooks.d.ts.map +1 -0
  92. package/dist/routes/webhooks.js +117 -0
  93. package/dist/routes/webhooks.js.map +1 -0
  94. package/dist/routes/workflows.d.ts +7 -0
  95. package/dist/routes/workflows.d.ts.map +1 -0
  96. package/dist/routes/workflows.js +138 -0
  97. package/dist/routes/workflows.js.map +1 -0
  98. package/dist/server.d.ts +35 -0
  99. package/dist/server.d.ts.map +1 -0
  100. package/dist/server.js +264 -0
  101. package/dist/server.js.map +1 -0
  102. package/dist/services/agent-registry.d.ts +89 -0
  103. package/dist/services/agent-registry.d.ts.map +1 -0
  104. package/dist/services/agent-registry.js +173 -0
  105. package/dist/services/agent-registry.js.map +1 -0
  106. package/dist/services/epic-completion-monitor-service.d.ts +69 -0
  107. package/dist/services/epic-completion-monitor-service.d.ts.map +1 -0
  108. package/dist/services/epic-completion-monitor-service.js +200 -0
  109. package/dist/services/epic-completion-monitor-service.js.map +1 -0
  110. package/dist/services/identity.d.ts +41 -0
  111. package/dist/services/identity.d.ts.map +1 -0
  112. package/dist/services/identity.js +91 -0
  113. package/dist/services/identity.js.map +1 -0
  114. package/dist/services/index.d.ts +13 -0
  115. package/dist/services/index.d.ts.map +1 -0
  116. package/dist/services/index.js +13 -0
  117. package/dist/services/index.js.map +1 -0
  118. package/dist/services/label-monitor-service.d.ts +95 -0
  119. package/dist/services/label-monitor-service.d.ts.map +1 -0
  120. package/dist/services/label-monitor-service.js +414 -0
  121. package/dist/services/label-monitor-service.js.map +1 -0
  122. package/dist/services/label-sync-service.d.ts +76 -0
  123. package/dist/services/label-sync-service.d.ts.map +1 -0
  124. package/dist/services/label-sync-service.js +108 -0
  125. package/dist/services/label-sync-service.js.map +1 -0
  126. package/dist/services/phase-tracker-service.d.ts +32 -0
  127. package/dist/services/phase-tracker-service.d.ts.map +1 -0
  128. package/dist/services/phase-tracker-service.js +82 -0
  129. package/dist/services/phase-tracker-service.js.map +1 -0
  130. package/dist/services/pr-feedback-monitor-service.d.ts +86 -0
  131. package/dist/services/pr-feedback-monitor-service.d.ts.map +1 -0
  132. package/dist/services/pr-feedback-monitor-service.js +423 -0
  133. package/dist/services/pr-feedback-monitor-service.js.map +1 -0
  134. package/dist/services/queue-service.d.ts +62 -0
  135. package/dist/services/queue-service.d.ts.map +1 -0
  136. package/dist/services/queue-service.js +147 -0
  137. package/dist/services/queue-service.js.map +1 -0
  138. package/dist/services/redis-queue-adapter.d.ts +35 -0
  139. package/dist/services/redis-queue-adapter.d.ts.map +1 -0
  140. package/dist/services/redis-queue-adapter.js +218 -0
  141. package/dist/services/redis-queue-adapter.js.map +1 -0
  142. package/dist/services/smee-receiver.d.ts +87 -0
  143. package/dist/services/smee-receiver.d.ts.map +1 -0
  144. package/dist/services/smee-receiver.js +225 -0
  145. package/dist/services/smee-receiver.js.map +1 -0
  146. package/dist/services/webhook-setup-service.d.ts +253 -0
  147. package/dist/services/webhook-setup-service.d.ts.map +1 -0
  148. package/dist/services/webhook-setup-service.js +369 -0
  149. package/dist/services/webhook-setup-service.js.map +1 -0
  150. package/dist/services/worker-dispatcher.d.ts +57 -0
  151. package/dist/services/worker-dispatcher.d.ts.map +1 -0
  152. package/dist/services/worker-dispatcher.js +211 -0
  153. package/dist/services/worker-dispatcher.js.map +1 -0
  154. package/dist/services/workflow-service.d.ts +65 -0
  155. package/dist/services/workflow-service.d.ts.map +1 -0
  156. package/dist/services/workflow-service.js +164 -0
  157. package/dist/services/workflow-service.js.map +1 -0
  158. package/dist/sse/events.d.ts +50 -0
  159. package/dist/sse/events.d.ts.map +1 -0
  160. package/dist/sse/events.js +152 -0
  161. package/dist/sse/events.js.map +1 -0
  162. package/dist/sse/index.d.ts +4 -0
  163. package/dist/sse/index.d.ts.map +1 -0
  164. package/dist/sse/index.js +7 -0
  165. package/dist/sse/index.js.map +1 -0
  166. package/dist/sse/stream.d.ts +109 -0
  167. package/dist/sse/stream.d.ts.map +1 -0
  168. package/dist/sse/stream.js +239 -0
  169. package/dist/sse/stream.js.map +1 -0
  170. package/dist/sse/subscriptions.d.ts +91 -0
  171. package/dist/sse/subscriptions.d.ts.map +1 -0
  172. package/dist/sse/subscriptions.js +299 -0
  173. package/dist/sse/subscriptions.js.map +1 -0
  174. package/dist/types/api.d.ts +651 -0
  175. package/dist/types/api.d.ts.map +1 -0
  176. package/dist/types/api.js +169 -0
  177. package/dist/types/api.js.map +1 -0
  178. package/dist/types/index.d.ts +6 -0
  179. package/dist/types/index.d.ts.map +1 -0
  180. package/dist/types/index.js +27 -0
  181. package/dist/types/index.js.map +1 -0
  182. package/dist/types/monitor.d.ts +243 -0
  183. package/dist/types/monitor.d.ts.map +1 -0
  184. package/dist/types/monitor.js +2 -0
  185. package/dist/types/monitor.js.map +1 -0
  186. package/dist/types/problem-details.d.ts +63 -0
  187. package/dist/types/problem-details.d.ts.map +1 -0
  188. package/dist/types/problem-details.js +37 -0
  189. package/dist/types/problem-details.js.map +1 -0
  190. package/dist/types/sse.d.ts +224 -0
  191. package/dist/types/sse.d.ts.map +1 -0
  192. package/dist/types/sse.js +103 -0
  193. package/dist/types/sse.js.map +1 -0
  194. package/dist/types/webhook.d.ts +59 -0
  195. package/dist/types/webhook.d.ts.map +1 -0
  196. package/dist/types/webhook.js +2 -0
  197. package/dist/types/webhook.js.map +1 -0
  198. package/dist/utils/correlation.d.ts +30 -0
  199. package/dist/utils/correlation.d.ts.map +1 -0
  200. package/dist/utils/correlation.js +34 -0
  201. package/dist/utils/correlation.js.map +1 -0
  202. package/dist/utils/index.d.ts +3 -0
  203. package/dist/utils/index.d.ts.map +1 -0
  204. package/dist/utils/index.js +3 -0
  205. package/dist/utils/index.js.map +1 -0
  206. package/dist/utils/shutdown.d.ts +28 -0
  207. package/dist/utils/shutdown.d.ts.map +1 -0
  208. package/dist/utils/shutdown.js +86 -0
  209. package/dist/utils/shutdown.js.map +1 -0
  210. package/dist/worker/claude-cli-worker.d.ts +61 -0
  211. package/dist/worker/claude-cli-worker.d.ts.map +1 -0
  212. package/dist/worker/claude-cli-worker.js +330 -0
  213. package/dist/worker/claude-cli-worker.js.map +1 -0
  214. package/dist/worker/cli-spawner.d.ts +42 -0
  215. package/dist/worker/cli-spawner.d.ts.map +1 -0
  216. package/dist/worker/cli-spawner.js +183 -0
  217. package/dist/worker/cli-spawner.js.map +1 -0
  218. package/dist/worker/config.d.ts +76 -0
  219. package/dist/worker/config.d.ts.map +1 -0
  220. package/dist/worker/config.js +39 -0
  221. package/dist/worker/config.js.map +1 -0
  222. package/dist/worker/epic-post-tasks.d.ts +73 -0
  223. package/dist/worker/epic-post-tasks.d.ts.map +1 -0
  224. package/dist/worker/epic-post-tasks.js +266 -0
  225. package/dist/worker/epic-post-tasks.js.map +1 -0
  226. package/dist/worker/gate-checker.d.ts +22 -0
  227. package/dist/worker/gate-checker.d.ts.map +1 -0
  228. package/dist/worker/gate-checker.js +41 -0
  229. package/dist/worker/gate-checker.js.map +1 -0
  230. package/dist/worker/index.d.ts +13 -0
  231. package/dist/worker/index.d.ts.map +1 -0
  232. package/dist/worker/index.js +19 -0
  233. package/dist/worker/index.js.map +1 -0
  234. package/dist/worker/label-manager.d.ts +89 -0
  235. package/dist/worker/label-manager.d.ts.map +1 -0
  236. package/dist/worker/label-manager.js +200 -0
  237. package/dist/worker/label-manager.js.map +1 -0
  238. package/dist/worker/output-capture.d.ts +58 -0
  239. package/dist/worker/output-capture.d.ts.map +1 -0
  240. package/dist/worker/output-capture.js +153 -0
  241. package/dist/worker/output-capture.js.map +1 -0
  242. package/dist/worker/phase-loop.d.ts +64 -0
  243. package/dist/worker/phase-loop.d.ts.map +1 -0
  244. package/dist/worker/phase-loop.js +185 -0
  245. package/dist/worker/phase-loop.js.map +1 -0
  246. package/dist/worker/phase-resolver.d.ts +62 -0
  247. package/dist/worker/phase-resolver.d.ts.map +1 -0
  248. package/dist/worker/phase-resolver.js +144 -0
  249. package/dist/worker/phase-resolver.js.map +1 -0
  250. package/dist/worker/pr-feedback-handler.d.ts +105 -0
  251. package/dist/worker/pr-feedback-handler.d.ts.map +1 -0
  252. package/dist/worker/pr-feedback-handler.js +391 -0
  253. package/dist/worker/pr-feedback-handler.js.map +1 -0
  254. package/dist/worker/pr-linker.d.ts +69 -0
  255. package/dist/worker/pr-linker.d.ts.map +1 -0
  256. package/dist/worker/pr-linker.js +108 -0
  257. package/dist/worker/pr-linker.js.map +1 -0
  258. package/dist/worker/pr-manager.d.ts +61 -0
  259. package/dist/worker/pr-manager.d.ts.map +1 -0
  260. package/dist/worker/pr-manager.js +140 -0
  261. package/dist/worker/pr-manager.js.map +1 -0
  262. package/dist/worker/repo-checkout.d.ts +63 -0
  263. package/dist/worker/repo-checkout.d.ts.map +1 -0
  264. package/dist/worker/repo-checkout.js +160 -0
  265. package/dist/worker/repo-checkout.js.map +1 -0
  266. package/dist/worker/stage-comment-manager.d.ts +34 -0
  267. package/dist/worker/stage-comment-manager.d.ts.map +1 -0
  268. package/dist/worker/stage-comment-manager.js +114 -0
  269. package/dist/worker/stage-comment-manager.js.map +1 -0
  270. package/dist/worker/types.d.ts +192 -0
  271. package/dist/worker/types.d.ts.map +1 -0
  272. package/dist/worker/types.js +53 -0
  273. package/dist/worker/types.js.map +1 -0
  274. package/package.json +64 -0
@@ -0,0 +1,61 @@
1
+ import type { QueueItem } from '../types/index.js';
2
+ import type { ProcessFactory, Logger } from './types.js';
3
+ import type { WorkerConfig } from './config.js';
4
+ import type { SSEEventEmitter } from './output-capture.js';
5
+ /**
6
+ * Dependencies that can be injected for testing.
7
+ */
8
+ export interface ClaudeCliWorkerDeps {
9
+ processFactory?: ProcessFactory;
10
+ sseEmitter?: SSEEventEmitter;
11
+ }
12
+ /**
13
+ * Top-level worker class that composes all sub-components to process
14
+ * a QueueItem through the full speckit phase loop or route to specialized handlers.
15
+ *
16
+ * This class implements the WorkerHandler signature:
17
+ * `(item: QueueItem) => Promise<void>`
18
+ *
19
+ * It orchestrates:
20
+ * - Repository checkout
21
+ * - Command routing (address-pr-feedback → PrFeedbackHandler)
22
+ * - Phase resolution from issue labels (for process/continue commands)
23
+ * - Phase loop execution (CLI spawning, label management, gate checking)
24
+ * - SSE event emission for dashboard streaming
25
+ * - Error handling with structured label reporting
26
+ */
27
+ export declare class ClaudeCliWorker {
28
+ private readonly config;
29
+ private readonly logger;
30
+ private readonly processFactory;
31
+ private readonly sseEmitter?;
32
+ private readonly repoCheckout;
33
+ private readonly phaseResolver;
34
+ constructor(config: WorkerConfig, logger: Logger, deps?: ClaudeCliWorkerDeps);
35
+ /**
36
+ * Process a queue item through the full phase loop or route to specialized handlers.
37
+ *
38
+ * This is the entry point invoked by the WorkerDispatcher.
39
+ *
40
+ * Command routing (T020):
41
+ * - `address-pr-feedback`: Routes to PrFeedbackHandler for PR review feedback
42
+ * - `process` / `continue`: Standard phase loop processing
43
+ *
44
+ * For phase loop processing:
45
+ * - Creates a WorkerContext
46
+ * - Resolves the starting phase from issue labels
47
+ * - Runs the phase loop to completion (or gate/error)
48
+ */
49
+ handle(item: QueueItem): Promise<void>;
50
+ /**
51
+ * Find the feature branch for an issue by checking for an existing PR.
52
+ *
53
+ * When resuming a workflow, the feature branch was created during the first
54
+ * run's setup phase. We find it by searching for an open draft PR that
55
+ * references the issue number.
56
+ *
57
+ * @returns The branch name, or undefined if no feature branch was found.
58
+ */
59
+ private resolveFeatureBranch;
60
+ }
61
+ //# sourceMappingURL=claude-cli-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-cli-worker.d.ts","sourceRoot":"","sources":["../../src/worker/claude-cli-worker.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAiB,cAAc,EAAsB,MAAM,EAAE,MAAM,YAAY,CAAC;AAE5F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAOhD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAyC3D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,eAAe;IAOxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAkB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;gBAG3B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EAC/B,IAAI,GAAE,mBAAwB;IAQhC;;;;;;;;;;;;;OAaG;IACG,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAiT5C;;;;;;;;OAQG;YACW,oBAAoB;CA2BnC"}
@@ -0,0 +1,330 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { createGitHubClient } from '@generacy-ai/workflow-engine';
3
+ import { getPhaseSequence } from './types.js';
4
+ import { PhaseResolver } from './phase-resolver.js';
5
+ import { LabelManager } from './label-manager.js';
6
+ import { StageCommentManager } from './stage-comment-manager.js';
7
+ import { GateChecker } from './gate-checker.js';
8
+ import { CliSpawner } from './cli-spawner.js';
9
+ import { OutputCapture } from './output-capture.js';
10
+ import { RepoCheckout } from './repo-checkout.js';
11
+ import { PhaseLoop } from './phase-loop.js';
12
+ import { PrManager } from './pr-manager.js';
13
+ import { PrFeedbackHandler } from './pr-feedback-handler.js';
14
+ import { EpicPostTasks } from './epic-post-tasks.js';
15
+ /**
16
+ * Default ProcessFactory that uses Node's child_process.spawn.
17
+ */
18
+ const defaultProcessFactory = {
19
+ spawn(command, args, options) {
20
+ const child = spawn(command, args, {
21
+ cwd: options.cwd,
22
+ env: { ...process.env, ...options.env },
23
+ stdio: ['ignore', 'pipe', 'pipe'],
24
+ });
25
+ const exitPromise = new Promise((resolve) => {
26
+ child.on('exit', (code) => {
27
+ resolve(code);
28
+ });
29
+ child.on('error', () => {
30
+ resolve(1);
31
+ });
32
+ });
33
+ return {
34
+ stdout: child.stdout,
35
+ stderr: child.stderr,
36
+ pid: child.pid,
37
+ kill: (signal) => child.kill(signal),
38
+ exitPromise,
39
+ };
40
+ },
41
+ };
42
+ /**
43
+ * Top-level worker class that composes all sub-components to process
44
+ * a QueueItem through the full speckit phase loop or route to specialized handlers.
45
+ *
46
+ * This class implements the WorkerHandler signature:
47
+ * `(item: QueueItem) => Promise<void>`
48
+ *
49
+ * It orchestrates:
50
+ * - Repository checkout
51
+ * - Command routing (address-pr-feedback → PrFeedbackHandler)
52
+ * - Phase resolution from issue labels (for process/continue commands)
53
+ * - Phase loop execution (CLI spawning, label management, gate checking)
54
+ * - SSE event emission for dashboard streaming
55
+ * - Error handling with structured label reporting
56
+ */
57
+ export class ClaudeCliWorker {
58
+ config;
59
+ logger;
60
+ processFactory;
61
+ sseEmitter;
62
+ repoCheckout;
63
+ phaseResolver;
64
+ constructor(config, logger, deps = {}) {
65
+ this.config = config;
66
+ this.logger = logger;
67
+ this.processFactory = deps.processFactory ?? defaultProcessFactory;
68
+ this.sseEmitter = deps.sseEmitter;
69
+ this.repoCheckout = new RepoCheckout(config.workspaceDir, logger);
70
+ this.phaseResolver = new PhaseResolver();
71
+ }
72
+ /**
73
+ * Process a queue item through the full phase loop or route to specialized handlers.
74
+ *
75
+ * This is the entry point invoked by the WorkerDispatcher.
76
+ *
77
+ * Command routing (T020):
78
+ * - `address-pr-feedback`: Routes to PrFeedbackHandler for PR review feedback
79
+ * - `process` / `continue`: Standard phase loop processing
80
+ *
81
+ * For phase loop processing:
82
+ * - Creates a WorkerContext
83
+ * - Resolves the starting phase from issue labels
84
+ * - Runs the phase loop to completion (or gate/error)
85
+ */
86
+ async handle(item) {
87
+ const workerId = crypto.randomUUID();
88
+ const workflowId = `${item.owner}/${item.repo}#${item.issueNumber}`;
89
+ const workerLogger = this.logger.child({
90
+ workerId,
91
+ owner: item.owner,
92
+ repo: item.repo,
93
+ issue: item.issueNumber,
94
+ workflowName: item.workflowName,
95
+ });
96
+ workerLogger.info('Worker started processing queue item');
97
+ // Emit SSE workflow:started event
98
+ this.sseEmitter?.({
99
+ type: 'workflow:started',
100
+ workflowId,
101
+ data: {
102
+ owner: item.owner,
103
+ repo: item.repo,
104
+ issueNumber: item.issueNumber,
105
+ workflowName: item.workflowName,
106
+ command: item.command,
107
+ },
108
+ });
109
+ // Create a GitHub client scoped to the checkout directory
110
+ let checkoutPath;
111
+ const abortController = new AbortController();
112
+ let labelManager;
113
+ let phasesCompleted = false;
114
+ let gateHit = false;
115
+ try {
116
+ // 1. Clone the default branch first (always works, even on first run)
117
+ const defaultBranch = await this.repoCheckout.getDefaultBranch(item.owner, item.repo);
118
+ checkoutPath = await this.repoCheckout.ensureCheckout(workerId, item.owner, item.repo, defaultBranch);
119
+ // Create GitHub client scoped to checkout dir
120
+ const github = createGitHubClient(checkoutPath);
121
+ // 2. Route address-pr-feedback command to PrFeedbackHandler (T020)
122
+ if (item.command === 'address-pr-feedback') {
123
+ workerLogger.info('Routing to PrFeedbackHandler for PR feedback addressing');
124
+ const prFeedbackHandler = new PrFeedbackHandler(this.config, workerLogger, this.processFactory, this.sseEmitter);
125
+ await prFeedbackHandler.handle(item, checkoutPath);
126
+ workerLogger.info('PR feedback addressing completed');
127
+ this.sseEmitter?.({
128
+ type: 'workflow:completed',
129
+ workflowId,
130
+ data: {
131
+ command: 'address-pr-feedback',
132
+ lastPhase: 'address-pr-feedback',
133
+ totalPhases: 1,
134
+ },
135
+ });
136
+ return;
137
+ }
138
+ // 3. Get issue labels to resolve starting phase
139
+ const issue = await github.getIssue(item.owner, item.repo, item.issueNumber);
140
+ const labels = issue.labels.map((l) => typeof l === 'string' ? l : l.name);
141
+ // 4. Resolve starting phase (for process/continue commands)
142
+ const startPhase = this.phaseResolver.resolveStartPhase(labels, item.command, item.workflowName);
143
+ workerLogger.info({ startPhase, labels }, 'Resolved starting phase');
144
+ // 5. If resuming (has completed phases), find and checkout the feature branch
145
+ if (startPhase !== 'specify') {
146
+ const featureBranch = await this.resolveFeatureBranch(github, item.owner, item.repo, item.issueNumber, workerLogger);
147
+ if (featureBranch) {
148
+ workerLogger.info({ featureBranch }, 'Switching to existing feature branch for resume');
149
+ await this.repoCheckout.switchBranch(checkoutPath, featureBranch);
150
+ }
151
+ }
152
+ // 6. Build WorkerContext
153
+ const context = {
154
+ workerId,
155
+ item,
156
+ startPhase,
157
+ github,
158
+ logger: workerLogger,
159
+ signal: abortController.signal,
160
+ checkoutPath,
161
+ issueUrl: `https://github.com/${item.owner}/${item.repo}/issues/${item.issueNumber}`,
162
+ };
163
+ // 7. Create sub-components
164
+ labelManager = new LabelManager(github, item.owner, item.repo, item.issueNumber, workerLogger);
165
+ const stageCommentManager = new StageCommentManager(github, item.owner, item.repo, item.issueNumber, workerLogger);
166
+ const gateChecker = new GateChecker(workerLogger);
167
+ const cliSpawner = new CliSpawner(this.processFactory, workerLogger, this.config.shutdownGracePeriodMs);
168
+ const outputCapture = new OutputCapture(workflowId, workerLogger, this.sseEmitter);
169
+ const prManager = new PrManager(github, item.owner, item.repo, item.issueNumber, workerLogger);
170
+ // 7b. On resume, clean up gate labels before starting the phase loop
171
+ if (item.command === 'continue') {
172
+ await labelManager.onResumeStart();
173
+ }
174
+ // 7c. Handle tasks-review gate resume for epics (T015)
175
+ // When an epic resumes after tasks-review approval, run post-tasks directly
176
+ // instead of re-entering the phase loop. The phase loop already completed
177
+ // (specify → clarify → plan → tasks); we just need to create child issues.
178
+ if (item.workflowName === 'speckit-epic' && item.command === 'continue') {
179
+ if (labels.includes('completed:tasks-review')) {
180
+ workerLogger.info('Epic tasks-review gate satisfied — running post-tasks directly');
181
+ const epicPostTasks = new EpicPostTasks(workerLogger);
182
+ const postTasksResult = await epicPostTasks.execute(context);
183
+ if (postTasksResult.success) {
184
+ workerLogger.info({ childIssues: postTasksResult.childIssues.length }, 'Epic post-tasks complete after tasks-review resume');
185
+ }
186
+ else {
187
+ workerLogger.error('Epic post-tasks failed after tasks-review resume');
188
+ }
189
+ this.sseEmitter?.({
190
+ type: 'workflow:completed',
191
+ workflowId,
192
+ data: {
193
+ command: item.command,
194
+ lastPhase: 'tasks',
195
+ totalPhases: 4,
196
+ },
197
+ });
198
+ return;
199
+ }
200
+ }
201
+ // 8. Execute the phase loop
202
+ const phaseSequence = getPhaseSequence(item.workflowName);
203
+ const phaseLoop = new PhaseLoop(workerLogger);
204
+ const loopResult = await phaseLoop.executeLoop(context, this.config, {
205
+ labelManager,
206
+ stageCommentManager,
207
+ gateChecker,
208
+ cliSpawner,
209
+ outputCapture,
210
+ prManager,
211
+ }, phaseSequence);
212
+ // 9. Handle completion
213
+ if (loopResult.completed) {
214
+ phasesCompleted = true;
215
+ if (item.workflowName === 'speckit-epic') {
216
+ // Epic workflows: create child issues and pause (do NOT complete workflow or mark PR ready)
217
+ workerLogger.info('Epic phase loop complete — running post-tasks');
218
+ const epicPostTasks = new EpicPostTasks(workerLogger);
219
+ const postTasksResult = await epicPostTasks.execute(context);
220
+ if (postTasksResult.success) {
221
+ workerLogger.info({ childIssues: postTasksResult.childIssues.length }, 'Epic post-tasks complete — epic is now waiting for children');
222
+ }
223
+ else {
224
+ workerLogger.error('Epic post-tasks failed — epic may need manual intervention');
225
+ }
226
+ this.sseEmitter?.({
227
+ type: 'workflow:completed',
228
+ workflowId,
229
+ data: {
230
+ command: item.command,
231
+ lastPhase: loopResult.lastPhase,
232
+ totalPhases: loopResult.results.length,
233
+ },
234
+ });
235
+ }
236
+ else {
237
+ // Non-epic workflows: standard completion flow
238
+ await labelManager.onWorkflowComplete();
239
+ workerLogger.info('Marking PR as ready for review');
240
+ await prManager.markReadyForReview();
241
+ workerLogger.info('Workflow completed successfully — all phases done');
242
+ this.sseEmitter?.({
243
+ type: 'workflow:completed',
244
+ workflowId,
245
+ data: {
246
+ command: item.command,
247
+ lastPhase: loopResult.lastPhase,
248
+ totalPhases: loopResult.results.length,
249
+ },
250
+ });
251
+ }
252
+ }
253
+ else if (loopResult.gateHit) {
254
+ gateHit = true;
255
+ workerLogger.info({ lastPhase: loopResult.lastPhase }, 'Workflow paused at review gate');
256
+ }
257
+ else {
258
+ // Phase failure
259
+ workerLogger.error({ lastPhase: loopResult.lastPhase }, 'Workflow stopped due to phase failure');
260
+ this.sseEmitter?.({
261
+ type: 'workflow:failed',
262
+ workflowId,
263
+ data: {
264
+ command: item.command,
265
+ lastPhase: loopResult.lastPhase,
266
+ totalPhases: loopResult.results.length,
267
+ },
268
+ });
269
+ }
270
+ }
271
+ catch (error) {
272
+ if (phasesCompleted) {
273
+ // All phases completed successfully — the failure is in post-completion
274
+ // work (e.g. markReadyForReview, SSE emission). Log at warn level and
275
+ // do NOT re-throw, so WorkerDispatcher calls queue.complete() instead
276
+ // of queue.release().
277
+ workerLogger.warn({ error: String(error) }, 'Post-completion step failed (all phases completed successfully)');
278
+ }
279
+ else {
280
+ workerLogger.error({ error: String(error) }, 'Worker encountered an unhandled error');
281
+ this.sseEmitter?.({
282
+ type: 'workflow:failed',
283
+ workflowId,
284
+ data: {
285
+ command: item.command,
286
+ error: error instanceof Error ? error.message : String(error),
287
+ },
288
+ });
289
+ throw error;
290
+ }
291
+ }
292
+ finally {
293
+ // Cleanup: abort any in-flight operations
294
+ abortController.abort();
295
+ // Ensure agent:in-progress is cleaned up on every exit path.
296
+ // This is a no-op if onWorkflowComplete() or onError() already removed it.
297
+ // Gate hits intentionally leave agent:in-progress — the guard prevents unwanted cleanup.
298
+ if (labelManager && !gateHit) {
299
+ await labelManager.ensureCleanup();
300
+ }
301
+ }
302
+ }
303
+ /**
304
+ * Find the feature branch for an issue by checking for an existing PR.
305
+ *
306
+ * When resuming a workflow, the feature branch was created during the first
307
+ * run's setup phase. We find it by searching for an open draft PR that
308
+ * references the issue number.
309
+ *
310
+ * @returns The branch name, or undefined if no feature branch was found.
311
+ */
312
+ async resolveFeatureBranch(github, owner, repo, issueNumber, logger) {
313
+ try {
314
+ // Search remote branches for one starting with the issue number
315
+ const branches = await github.listBranches(owner, repo);
316
+ const featureBranch = branches.find((b) => b.startsWith(`${issueNumber}-`));
317
+ if (featureBranch) {
318
+ logger.info({ featureBranch, issueNumber }, 'Found feature branch by issue number prefix');
319
+ return featureBranch;
320
+ }
321
+ logger.info({ issueNumber }, 'No feature branch found for issue');
322
+ return undefined;
323
+ }
324
+ catch (error) {
325
+ logger.warn({ error: String(error), issueNumber }, 'Failed to resolve feature branch (non-fatal)');
326
+ return undefined;
327
+ }
328
+ }
329
+ }
330
+ //# sourceMappingURL=claude-cli-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-cli-worker.js","sourceRoot":"","sources":["../../src/worker/claude-cli-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { CliSpawnOptions, Logger, PhaseResult, ProcessFactory, WorkflowPhase } from './types.js';
2
+ import type { OutputCapture } from './output-capture.js';
3
+ /**
4
+ * Spawns Claude CLI processes (or shell commands for validation) and manages
5
+ * their lifecycle: stdout/stderr capture, timeout with SIGTERM then SIGKILL,
6
+ * and abort signal propagation.
7
+ */
8
+ export declare class CliSpawner {
9
+ private readonly processFactory;
10
+ private readonly logger;
11
+ private readonly shutdownGracePeriodMs;
12
+ constructor(processFactory: ProcessFactory, logger: Logger, shutdownGracePeriodMs?: number);
13
+ /**
14
+ * Spawn a Claude CLI process for the given workflow phase.
15
+ *
16
+ * Builds the command line from PHASE_TO_COMMAND, captures stdout via the
17
+ * provided OutputCapture, and handles timeout / abort with a
18
+ * SIGTERM -> grace period -> SIGKILL sequence.
19
+ */
20
+ spawnPhase(phase: WorkflowPhase, options: CliSpawnOptions, capture: OutputCapture): Promise<PhaseResult>;
21
+ /**
22
+ * Run a shell validation command (e.g., `pnpm test && pnpm build`).
23
+ *
24
+ * Unlike `spawnPhase`, this does not invoke the Claude CLI; it runs an
25
+ * arbitrary shell command via `sh -c`.
26
+ */
27
+ runValidatePhase(checkoutPath: string, validateCommand: string, signal: AbortSignal): Promise<PhaseResult>;
28
+ /**
29
+ * Manages the full lifecycle of a spawned child process:
30
+ * - Capture stdout (via OutputCapture if provided) and stderr
31
+ * - Enforce timeout with SIGTERM -> grace period -> SIGKILL
32
+ * - Propagate abort signal
33
+ * - Return a PhaseResult once the process exits
34
+ */
35
+ private manageProcess;
36
+ /**
37
+ * Send SIGTERM, wait the grace period, then send SIGKILL if the process
38
+ * is still alive.
39
+ */
40
+ private gracefulKill;
41
+ }
42
+ //# sourceMappingURL=cli-spawner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-spawner.d.ts","sourceRoot":"","sources":["../../src/worker/cli-spawner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EAEf,MAAM,EACN,WAAW,EACX,cAAc,EACd,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD;;;;GAIG;AACH,qBAAa,UAAU;IAEnB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,qBAAqB;gBAFrB,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,MAAM,EACd,qBAAqB,GAAE,MAAa;IAGvD;;;;;;OAMG;IACG,UAAU,CACd,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,WAAW,CAAC;IA2CvB;;;;;OAKG;IACG,gBAAgB,CACpB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,WAAW,CAAC;IAqBvB;;;;;;OAMG;YACW,aAAa;IA4G3B;;;OAGG;IACH,OAAO,CAAC,YAAY;CAgBrB"}
@@ -0,0 +1,183 @@
1
+ import { PHASE_TO_COMMAND } from './types.js';
2
+ /** Default timeout for the validate phase (10 minutes). */
3
+ const DEFAULT_VALIDATE_TIMEOUT_MS = 600_000;
4
+ /**
5
+ * Spawns Claude CLI processes (or shell commands for validation) and manages
6
+ * their lifecycle: stdout/stderr capture, timeout with SIGTERM then SIGKILL,
7
+ * and abort signal propagation.
8
+ */
9
+ export class CliSpawner {
10
+ processFactory;
11
+ logger;
12
+ shutdownGracePeriodMs;
13
+ constructor(processFactory, logger, shutdownGracePeriodMs = 5000) {
14
+ this.processFactory = processFactory;
15
+ this.logger = logger;
16
+ this.shutdownGracePeriodMs = shutdownGracePeriodMs;
17
+ }
18
+ /**
19
+ * Spawn a Claude CLI process for the given workflow phase.
20
+ *
21
+ * Builds the command line from PHASE_TO_COMMAND, captures stdout via the
22
+ * provided OutputCapture, and handles timeout / abort with a
23
+ * SIGTERM -> grace period -> SIGKILL sequence.
24
+ */
25
+ async spawnPhase(phase, options, capture) {
26
+ const command = PHASE_TO_COMMAND[phase];
27
+ if (command === null) {
28
+ throw new Error(`Phase "${phase}" has no CLI command (use runValidatePhase instead)`);
29
+ }
30
+ const prompt = `${command} ${options.prompt}`;
31
+ const args = [
32
+ '--headless',
33
+ '--output', 'json',
34
+ '--print', 'all',
35
+ '--max-turns', String(options.maxTurns),
36
+ ];
37
+ // Resume a previous session to keep MCP servers warm and carry context
38
+ if (options.resumeSessionId) {
39
+ args.push('--resume', options.resumeSessionId);
40
+ }
41
+ args.push('--prompt', prompt);
42
+ this.logger.info({
43
+ phase,
44
+ cwd: options.cwd,
45
+ maxTurns: options.maxTurns,
46
+ timeoutMs: options.timeoutMs,
47
+ resumeSessionId: options.resumeSessionId ?? null,
48
+ }, options.resumeSessionId
49
+ ? 'Resuming Claude CLI session for phase'
50
+ : 'Spawning new Claude CLI session for phase');
51
+ const child = this.processFactory.spawn('claude', args, {
52
+ cwd: options.cwd,
53
+ env: options.env,
54
+ });
55
+ return this.manageProcess(child, phase, options.timeoutMs, options.signal, capture);
56
+ }
57
+ /**
58
+ * Run a shell validation command (e.g., `pnpm test && pnpm build`).
59
+ *
60
+ * Unlike `spawnPhase`, this does not invoke the Claude CLI; it runs an
61
+ * arbitrary shell command via `sh -c`.
62
+ */
63
+ async runValidatePhase(checkoutPath, validateCommand, signal) {
64
+ const phase = 'validate';
65
+ const timeoutMs = DEFAULT_VALIDATE_TIMEOUT_MS;
66
+ this.logger.info({ phase, cwd: checkoutPath, validateCommand, timeoutMs }, 'Spawning validation command');
67
+ const child = this.processFactory.spawn('sh', ['-c', validateCommand], {
68
+ cwd: checkoutPath,
69
+ env: {},
70
+ });
71
+ return this.manageProcess(child, phase, timeoutMs, signal, undefined);
72
+ }
73
+ // ---------------------------------------------------------------------------
74
+ // Private helpers
75
+ // ---------------------------------------------------------------------------
76
+ /**
77
+ * Manages the full lifecycle of a spawned child process:
78
+ * - Capture stdout (via OutputCapture if provided) and stderr
79
+ * - Enforce timeout with SIGTERM -> grace period -> SIGKILL
80
+ * - Propagate abort signal
81
+ * - Return a PhaseResult once the process exits
82
+ */
83
+ async manageProcess(child, phase, timeoutMs, signal, capture) {
84
+ const startTime = Date.now();
85
+ let stderrBuffer = '';
86
+ // ---- stdout ----
87
+ if (child.stdout && capture) {
88
+ child.stdout.on('data', (data) => {
89
+ capture.processChunk(typeof data === 'string' ? data : data.toString('utf-8'));
90
+ });
91
+ }
92
+ // For runValidatePhase we still want to capture stdout even without OutputCapture,
93
+ // so we attach a no-op listener to avoid back-pressure issues.
94
+ if (child.stdout && !capture) {
95
+ child.stdout.on('data', () => {
96
+ // intentionally empty
97
+ });
98
+ }
99
+ // ---- stderr ----
100
+ if (child.stderr) {
101
+ child.stderr.on('data', (data) => {
102
+ stderrBuffer += typeof data === 'string' ? data : data.toString('utf-8');
103
+ });
104
+ }
105
+ // ---- Timeout handling ----
106
+ let timedOut = false;
107
+ const timeoutTimer = setTimeout(() => {
108
+ timedOut = true;
109
+ this.logger.warn({ phase, pid: child.pid, timeoutMs }, 'Phase timed out, sending SIGTERM');
110
+ this.gracefulKill(child, phase);
111
+ }, timeoutMs);
112
+ // ---- Abort signal handling ----
113
+ let aborted = false;
114
+ const onAbort = () => {
115
+ aborted = true;
116
+ this.logger.warn({ phase, pid: child.pid }, 'Abort signal received, sending SIGTERM');
117
+ this.gracefulKill(child, phase);
118
+ };
119
+ // Avoid attaching listener if already aborted.
120
+ if (signal.aborted) {
121
+ onAbort();
122
+ }
123
+ else {
124
+ signal.addEventListener('abort', onAbort, { once: true });
125
+ }
126
+ // ---- Wait for exit ----
127
+ let exitCode;
128
+ try {
129
+ exitCode = await child.exitPromise;
130
+ }
131
+ finally {
132
+ clearTimeout(timeoutTimer);
133
+ signal.removeEventListener('abort', onAbort);
134
+ }
135
+ // ---- Flush capture ----
136
+ if (capture) {
137
+ capture.flush();
138
+ }
139
+ const durationMs = Date.now() - startTime;
140
+ const resolvedExitCode = exitCode ?? 1;
141
+ const success = resolvedExitCode === 0;
142
+ this.logger.info({ phase, exitCode: resolvedExitCode, durationMs, success, timedOut, aborted }, 'Phase process exited');
143
+ const result = {
144
+ phase,
145
+ success,
146
+ exitCode: resolvedExitCode,
147
+ durationMs,
148
+ output: capture ? capture.getOutput() : [],
149
+ sessionId: capture?.sessionId,
150
+ };
151
+ if (!success) {
152
+ let message = `Phase "${phase}" failed with exit code ${resolvedExitCode}`;
153
+ if (timedOut) {
154
+ message = `Phase "${phase}" timed out after ${timeoutMs}ms`;
155
+ }
156
+ else if (aborted) {
157
+ message = `Phase "${phase}" was aborted`;
158
+ }
159
+ result.error = {
160
+ message,
161
+ stderr: stderrBuffer,
162
+ phase,
163
+ };
164
+ }
165
+ return result;
166
+ }
167
+ /**
168
+ * Send SIGTERM, wait the grace period, then send SIGKILL if the process
169
+ * is still alive.
170
+ */
171
+ gracefulKill(child, phase) {
172
+ child.kill('SIGTERM');
173
+ const killTimer = setTimeout(() => {
174
+ this.logger.warn({ phase, pid: child.pid }, 'Grace period expired, sending SIGKILL');
175
+ child.kill('SIGKILL');
176
+ }, this.shutdownGracePeriodMs);
177
+ // Clear the SIGKILL timer once the process exits on its own.
178
+ void child.exitPromise.then(() => {
179
+ clearTimeout(killTimer);
180
+ });
181
+ }
182
+ }
183
+ //# sourceMappingURL=cli-spawner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-spawner.js","sourceRoot":"","sources":["../../src/worker/cli-spawner.ts"],"names":[],"mappings":"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"}