@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,200 @@
1
+ import { findChildIssues } from '@generacy-ai/workflow-engine';
2
+ // ---------------------------------------------------------------------------
3
+ // Constants
4
+ // ---------------------------------------------------------------------------
5
+ const WAITING_LABEL = 'waiting-for:children-complete';
6
+ const COMPLETED_LABEL = 'completed:children-complete';
7
+ const STATUS_MARKER = '<!-- epic-status -->';
8
+ // ---------------------------------------------------------------------------
9
+ // Service
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * Monitors epic issues for child completion. Runs as a standalone polling loop
13
+ * alongside the LabelMonitorService.
14
+ */
15
+ export class EpicCompletionMonitorService {
16
+ logger;
17
+ createClient;
18
+ config;
19
+ repositories;
20
+ abortController = null;
21
+ constructor(logger, createClient, config, repositories) {
22
+ this.logger = logger;
23
+ this.createClient = createClient;
24
+ this.config = config;
25
+ this.repositories = repositories;
26
+ }
27
+ // ==========================================================================
28
+ // Lifecycle
29
+ // ==========================================================================
30
+ async startPolling() {
31
+ if (this.abortController) {
32
+ this.logger.warn('Epic completion monitor polling already running');
33
+ return;
34
+ }
35
+ const ac = new AbortController();
36
+ this.abortController = ac;
37
+ this.logger.info({ intervalMs: this.config.pollIntervalMs, repos: this.repositories.length }, 'Starting epic completion monitor polling');
38
+ while (!ac.signal.aborted) {
39
+ try {
40
+ await this.poll();
41
+ }
42
+ catch (error) {
43
+ this.logger.error({ err: error }, 'Error during epic completion poll cycle');
44
+ }
45
+ await this.sleep(this.config.pollIntervalMs, ac.signal);
46
+ }
47
+ this.logger.info('Epic completion monitor polling stopped');
48
+ }
49
+ stopPolling() {
50
+ if (this.abortController) {
51
+ this.abortController.abort();
52
+ this.abortController = null;
53
+ this.logger.info('Epic completion monitor stop requested');
54
+ }
55
+ }
56
+ // ==========================================================================
57
+ // Polling
58
+ // ==========================================================================
59
+ /**
60
+ * Run a single poll cycle across all watched repositories.
61
+ */
62
+ async poll() {
63
+ for (const { owner, repo } of this.repositories) {
64
+ try {
65
+ await this.pollRepo(owner, repo);
66
+ }
67
+ catch (error) {
68
+ this.logger.error({ err: error, owner, repo }, 'Error polling repository for epic completion');
69
+ }
70
+ }
71
+ }
72
+ /**
73
+ * Poll a single repository for epics waiting on children.
74
+ */
75
+ async pollRepo(owner, repo) {
76
+ const client = this.createClient();
77
+ // Find all issues with the waiting-for:children-complete label
78
+ const epics = await client.listIssuesWithLabel(owner, repo, WAITING_LABEL);
79
+ if (epics.length === 0)
80
+ return;
81
+ this.logger.info({ owner, repo, count: epics.length }, 'Found epics waiting for children');
82
+ for (const epic of epics) {
83
+ try {
84
+ await this.checkEpic(client, owner, repo, epic.number);
85
+ }
86
+ catch (error) {
87
+ this.logger.error({ err: error, owner, repo, issueNumber: epic.number }, 'Error checking epic completion');
88
+ }
89
+ }
90
+ }
91
+ // ==========================================================================
92
+ // Epic Completion Check
93
+ // ==========================================================================
94
+ /**
95
+ * Check a single epic's child completion status, update the progress
96
+ * comment, and transition labels if all children are complete.
97
+ */
98
+ async checkEpic(client, owner, repo, epicNumber) {
99
+ // Find child issues
100
+ const children = await this.findChildIssues(owner, repo, epicNumber);
101
+ if (children.length === 0) {
102
+ this.logger.warn({ owner, repo, epicNumber }, 'Epic has no children found — skipping');
103
+ return;
104
+ }
105
+ // Calculate completion stats
106
+ const totalChildren = children.length;
107
+ const completedChildren = children.filter(c => c.state === 'closed' && c.pr_merged).length;
108
+ const percentage = Math.round((completedChildren / totalChildren) * 100);
109
+ this.logger.info({ owner, repo, epicNumber, percentage, completedChildren, totalChildren }, `Epic #${epicNumber} progress: ${percentage}%`);
110
+ // Update status comment
111
+ await this.updateStatusComment(client, owner, repo, epicNumber, percentage, totalChildren, completedChildren, children);
112
+ // Check if all children are complete
113
+ if (completedChildren === totalChildren) {
114
+ this.logger.info({ owner, repo, epicNumber }, 'All children complete — transitioning epic');
115
+ // Remove waiting label, add completed label
116
+ await client.removeLabels(owner, repo, epicNumber, [WAITING_LABEL]);
117
+ await client.addLabels(owner, repo, epicNumber, [COMPLETED_LABEL]);
118
+ // The LabelMonitorService will detect `completed:children-complete`
119
+ // paired with the now-removed `waiting-for:children-complete` and
120
+ // enqueue an `epic-complete` command. No direct enqueue needed here.
121
+ }
122
+ }
123
+ // ==========================================================================
124
+ // Child Issue Discovery (delegates to shared utility)
125
+ // ==========================================================================
126
+ /**
127
+ * Find child issues that reference the given epic via `epic-parent: #N` in
128
+ * their body. Delegates to the shared `findChildIssues` utility from
129
+ * `@generacy-ai/workflow-engine`.
130
+ */
131
+ async findChildIssues(owner, repo, epicNumber) {
132
+ return findChildIssues(owner, repo, epicNumber, {
133
+ state: 'all',
134
+ includePrStatus: true,
135
+ });
136
+ }
137
+ // ==========================================================================
138
+ // Status Comment
139
+ // ==========================================================================
140
+ /**
141
+ * Create or update the `<!-- epic-status -->` progress comment on the epic.
142
+ */
143
+ async updateStatusComment(client, owner, repo, epicNumber, percentage, total, completed, children) {
144
+ const body = this.generateStatusComment(percentage, total, completed, children);
145
+ // Find existing status comment
146
+ const comments = await client.getIssueComments(owner, repo, epicNumber);
147
+ const existing = comments.find(c => c.body.includes(STATUS_MARKER));
148
+ if (existing) {
149
+ await client.updateComment(owner, repo, existing.id, body);
150
+ }
151
+ else {
152
+ await client.addIssueComment(owner, repo, epicNumber, body);
153
+ }
154
+ }
155
+ /**
156
+ * Generate the markdown body for the epic status comment.
157
+ */
158
+ generateStatusComment(percentage, total, completed, children) {
159
+ const filled = Math.round(percentage / 10);
160
+ const empty = 10 - filled;
161
+ const progressBar = `${'█'.repeat(filled)}${'░'.repeat(empty)}`;
162
+ let body = `${STATUS_MARKER}\n## Epic Progress\n\n`;
163
+ body += `| Child | Status | PR |\n`;
164
+ body += `|-------|--------|----|`;
165
+ for (const child of children) {
166
+ const status = child.state === 'closed' && child.pr_merged
167
+ ? ':white_check_mark: Merged'
168
+ : child.labels.some(l => l.startsWith('waiting-for:'))
169
+ ? ':hourglass: Blocked'
170
+ : child.labels.includes('agent:in-progress')
171
+ ? ':hourglass: In progress'
172
+ : child.state === 'closed'
173
+ ? ':white_check_mark: Closed'
174
+ : ':clock1: Pending';
175
+ const prLink = child.pr_number ? `#${child.pr_number}` : '—';
176
+ body += `\n| #${child.issue_number} ${child.title} | ${status} | ${prLink} |`;
177
+ }
178
+ body += `\n\n**Progress**: ${progressBar} ${percentage}% (${completed}/${total} complete)`;
179
+ body += `\n**Last checked**: ${new Date().toISOString()}`;
180
+ return body;
181
+ }
182
+ // ==========================================================================
183
+ // Utilities
184
+ // ==========================================================================
185
+ sleep(ms, signal) {
186
+ return new Promise((resolve) => {
187
+ if (signal.aborted) {
188
+ resolve();
189
+ return;
190
+ }
191
+ const timer = setTimeout(resolve, ms);
192
+ const onAbort = () => {
193
+ clearTimeout(timer);
194
+ resolve();
195
+ };
196
+ signal.addEventListener('abort', onAbort, { once: true });
197
+ });
198
+ }
199
+ }
200
+ //# sourceMappingURL=epic-completion-monitor-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"epic-completion-monitor-service.js","sourceRoot":"","sources":["../../src/services/epic-completion-monitor-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Minimal issue shape for assignee filtering.
3
+ * Compatible with the `Issue` type from @generacy-ai/workflow-engine.
4
+ */
5
+ export interface FilterableIssue {
6
+ number: number;
7
+ assignees: string[];
8
+ }
9
+ /**
10
+ * Minimal logger interface for identity resolution.
11
+ * Uses optional `debug` since some service loggers (e.g., LabelMonitorService)
12
+ * don't expose it.
13
+ */
14
+ interface Logger {
15
+ info(msg: string): void;
16
+ info(obj: Record<string, unknown>, msg: string): void;
17
+ warn(msg: string): void;
18
+ warn(obj: Record<string, unknown>, msg: string): void;
19
+ debug?(obj: Record<string, unknown>, msg: string): void;
20
+ }
21
+ /**
22
+ * Resolve the cluster's GitHub identity for assignee-based issue filtering.
23
+ *
24
+ * Resolution order:
25
+ * 1. `configUsername` (from CLUSTER_GITHUB_USERNAME env var via config)
26
+ * 2. `gh api /user` fallback (auto-detection from gh auth)
27
+ * 3. `undefined` (filtering disabled, all issues processed)
28
+ *
29
+ * Called once at startup; result is cached for the cluster's lifetime.
30
+ */
31
+ export declare function resolveClusterIdentity(configUsername: string | undefined, logger: Logger): Promise<string | undefined>;
32
+ /**
33
+ * Filter issues to only those assigned to the cluster's GitHub username.
34
+ *
35
+ * When `clusterGithubUsername` is `undefined`, returns all issues (no filtering).
36
+ * When filtering is active, unassigned issues are skipped with a warning.
37
+ * Issues assigned to multiple users trigger a warning but are still processed.
38
+ */
39
+ export declare function filterByAssignee<T extends FilterableIssue>(issues: T[], clusterGithubUsername: string | undefined, logger: Logger): T[];
40
+ export {};
41
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/services/identity.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;GAIG;AACH,UAAU,MAAM;IACd,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,KAAK,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACzD;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAC1C,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA+C7B;AAgCD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,eAAe,EACxD,MAAM,EAAE,CAAC,EAAE,EACX,qBAAqB,EAAE,MAAM,GAAG,SAAS,EACzC,MAAM,EAAE,MAAM,GACb,CAAC,EAAE,CA8BL"}
@@ -0,0 +1,91 @@
1
+ import { execFile } from 'node:child_process';
2
+ /**
3
+ * Resolve the cluster's GitHub identity for assignee-based issue filtering.
4
+ *
5
+ * Resolution order:
6
+ * 1. `configUsername` (from CLUSTER_GITHUB_USERNAME env var via config)
7
+ * 2. `gh api /user` fallback (auto-detection from gh auth)
8
+ * 3. `undefined` (filtering disabled, all issues processed)
9
+ *
10
+ * Called once at startup; result is cached for the cluster's lifetime.
11
+ */
12
+ export async function resolveClusterIdentity(configUsername, logger) {
13
+ // 1. Explicit config (env var)
14
+ if (configUsername) {
15
+ logger.info({ username: configUsername, source: 'config' }, `Cluster identity resolved: ${configUsername} (from CLUSTER_GITHUB_USERNAME)`);
16
+ return configUsername;
17
+ }
18
+ // 2. Fallback: gh api /user
19
+ try {
20
+ const login = await ghApiUser();
21
+ logger.info({ username: login, source: 'gh-api' }, `Cluster identity resolved: ${login} (from gh api /user)`);
22
+ return login;
23
+ }
24
+ catch (error) {
25
+ const message = error instanceof Error ? error.message : String(error);
26
+ if (message.includes('ENOENT') || message.includes('not found')) {
27
+ logger.warn({ error: message }, 'gh CLI not found — set CLUSTER_GITHUB_USERNAME to enable assignee filtering');
28
+ }
29
+ else if (message.includes('auth') || message.includes('401') || message.includes('login')) {
30
+ logger.warn({ error: message }, 'gh CLI not authenticated — run "gh auth login" or set CLUSTER_GITHUB_USERNAME');
31
+ }
32
+ else if (message.includes('timeout') || message.includes('TIMEOUT')) {
33
+ logger.warn({ error: message }, 'gh api /user timed out — set CLUSTER_GITHUB_USERNAME to avoid this delay');
34
+ }
35
+ else {
36
+ logger.warn({ error: message }, 'Failed to resolve cluster identity via gh api /user — set CLUSTER_GITHUB_USERNAME to enable assignee filtering');
37
+ }
38
+ }
39
+ // 3. Both failed — filtering disabled
40
+ logger.warn('Assignee filtering disabled: no cluster identity configured. All issues will be processed.');
41
+ return undefined;
42
+ }
43
+ /**
44
+ * Call `gh api /user` with a 10s timeout and return the login field.
45
+ */
46
+ function ghApiUser() {
47
+ return new Promise((resolve, reject) => {
48
+ const child = execFile('gh', ['api', '/user', '--jq', '.login'], { timeout: 10_000 }, (error, stdout, stderr) => {
49
+ if (error) {
50
+ reject(new Error(stderr.trim() || error.message));
51
+ return;
52
+ }
53
+ const login = stdout.trim();
54
+ if (!login) {
55
+ reject(new Error('gh api /user returned empty login'));
56
+ return;
57
+ }
58
+ resolve(login);
59
+ });
60
+ // Handle spawn errors (ENOENT when gh is not installed)
61
+ child.on('error', (err) => {
62
+ reject(err);
63
+ });
64
+ });
65
+ }
66
+ /**
67
+ * Filter issues to only those assigned to the cluster's GitHub username.
68
+ *
69
+ * When `clusterGithubUsername` is `undefined`, returns all issues (no filtering).
70
+ * When filtering is active, unassigned issues are skipped with a warning.
71
+ * Issues assigned to multiple users trigger a warning but are still processed.
72
+ */
73
+ export function filterByAssignee(issues, clusterGithubUsername, logger) {
74
+ if (!clusterGithubUsername)
75
+ return issues;
76
+ return issues.filter(issue => {
77
+ if (issue.assignees.length === 0) {
78
+ logger.warn({ issueNumber: issue.number }, 'Skipping issue: no assignees set (assign before labeling)');
79
+ return false;
80
+ }
81
+ const assigned = issue.assignees.includes(clusterGithubUsername);
82
+ if (assigned && issue.assignees.length > 1) {
83
+ logger.warn({ issueNumber: issue.number, assignees: issue.assignees }, 'Issue has multiple assignees — may be processed by multiple clusters');
84
+ }
85
+ if (!assigned) {
86
+ logger.debug?.({ issueNumber: issue.number, assignees: issue.assignees, clusterUsername: clusterGithubUsername }, 'Skipping issue: not assigned to this cluster');
87
+ }
88
+ return assigned;
89
+ });
90
+ }
91
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/services/identity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export { WorkflowService, InMemoryWorkflowStore, type WorkflowEngine, } from './workflow-service.js';
2
+ export { QueueService, InMemoryQueueStore, type MessageRouter, } from './queue-service.js';
3
+ export { AgentRegistry, type AgentRegistration, } from './agent-registry.js';
4
+ export { LabelSyncService, type LabelSyncResult, type RepoSyncResult, type SyncAllResult, } from './label-sync-service.js';
5
+ export { LabelMonitorService, type LabelMonitorOptions, } from './label-monitor-service.js';
6
+ export { SmeeWebhookReceiver, type SmeeReceiverOptions, } from './smee-receiver.js';
7
+ export { PhaseTrackerService, type PhaseTrackerOptions, } from './phase-tracker-service.js';
8
+ export { RedisQueueAdapter } from './redis-queue-adapter.js';
9
+ export { WorkerDispatcher } from './worker-dispatcher.js';
10
+ export { EpicCompletionMonitorService, type EpicMonitorConfig, } from './epic-completion-monitor-service.js';
11
+ export { WebhookSetupService } from './webhook-setup-service.js';
12
+ export { resolveClusterIdentity, filterByAssignee, type FilterableIssue, } from './identity.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,KAAK,cAAc,GACpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,aAAa,EACb,KAAK,iBAAiB,GACvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,mBAAmB,EACnB,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,mBAAmB,EACnB,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,mBAAmB,EACnB,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EACL,4BAA4B,EAC5B,KAAK,iBAAiB,GACvB,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,eAAe,GACrB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,13 @@
1
+ export { WorkflowService, InMemoryWorkflowStore, } from './workflow-service.js';
2
+ export { QueueService, InMemoryQueueStore, } from './queue-service.js';
3
+ export { AgentRegistry, } from './agent-registry.js';
4
+ export { LabelSyncService, } from './label-sync-service.js';
5
+ export { LabelMonitorService, } from './label-monitor-service.js';
6
+ export { SmeeWebhookReceiver, } from './smee-receiver.js';
7
+ export { PhaseTrackerService, } from './phase-tracker-service.js';
8
+ export { RedisQueueAdapter } from './redis-queue-adapter.js';
9
+ export { WorkerDispatcher } from './worker-dispatcher.js';
10
+ export { EpicCompletionMonitorService, } from './epic-completion-monitor-service.js';
11
+ export { WebhookSetupService } from './webhook-setup-service.js';
12
+ export { resolveClusterIdentity, filterByAssignee, } from './identity.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,qBAAqB,GAEtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,YAAY,EACZ,kBAAkB,GAEnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,aAAa,GAEd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,gBAAgB,GAIjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,mBAAmB,GAEpB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,mBAAmB,GAEpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,mBAAmB,GAEpB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EACL,4BAA4B,GAE7B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EACL,sBAAsB,EACtB,gBAAgB,GAEjB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,95 @@
1
+ import { type GitHubClientFactory } from '@generacy-ai/workflow-engine';
2
+ import type { LabelEvent, MonitorState, QueueAdapter, PhaseTracker } from '../types/index.js';
3
+ import type { RepositoryConfig, MonitorConfig } from '../config/schema.js';
4
+ interface Logger {
5
+ info(msg: string): void;
6
+ info(obj: Record<string, unknown>, msg: string): void;
7
+ warn(msg: string): void;
8
+ warn(obj: Record<string, unknown>, msg: string): void;
9
+ error(msg: string): void;
10
+ error(obj: Record<string, unknown>, msg: string): void;
11
+ }
12
+ export interface LabelMonitorOptions {
13
+ repositories: RepositoryConfig[];
14
+ pollIntervalMs: number;
15
+ adaptivePolling: boolean;
16
+ maxConcurrentPolls: number;
17
+ }
18
+ /**
19
+ * Label monitor service that watches repositories for trigger labels
20
+ * using a hybrid webhook + polling approach.
21
+ */
22
+ export declare class LabelMonitorService {
23
+ private readonly logger;
24
+ private readonly createClient;
25
+ private readonly phaseTracker;
26
+ private readonly queueAdapter;
27
+ private readonly options;
28
+ private readonly clusterGithubUsername;
29
+ private abortController;
30
+ private pollCycleCount;
31
+ /**
32
+ * How often to check completed:* labels (every Nth cycle).
33
+ * Process:* labels are checked every cycle. Completed:* labels
34
+ * are for resume detection and can be checked less frequently.
35
+ */
36
+ private static readonly COMPLETED_CHECK_INTERVAL;
37
+ private state;
38
+ constructor(logger: Logger, createClient: GitHubClientFactory, phaseTracker: PhaseTracker, queueAdapter: QueueAdapter, config: MonitorConfig, repositories: RepositoryConfig[], clusterGithubUsername?: string);
39
+ /**
40
+ * Parse a label event from a label name, determining if it's a process
41
+ * trigger or a resume event.
42
+ */
43
+ parseLabelEvent(labelName: string, owner: string, repo: string, issueNumber: number, issueLabels: string[], source: 'webhook' | 'poll'): LabelEvent | null;
44
+ /**
45
+ * Re-fetch issue labels from GitHub and retry resume detection.
46
+ * Called when a webhook delivers a completed:* label but the payload's
47
+ * issueLabels didn't contain a matching waiting-for:* label (stale payload).
48
+ */
49
+ verifyAndProcessCompletedLabel(owner: string, repo: string, issueNumber: number, labelName: string): Promise<boolean>;
50
+ /**
51
+ * Resolve workflow name from a workflow:* label on the issue.
52
+ * Falls back to 'speckit-feature' for backward compatibility with
53
+ * pre-existing issues that lack a workflow: label.
54
+ */
55
+ private resolveWorkflowFromLabels;
56
+ /**
57
+ * Process a label event: check dedup, enqueue, manage labels.
58
+ * Shared by both webhook and polling paths.
59
+ */
60
+ processLabelEvent(event: LabelEvent): Promise<boolean>;
61
+ /**
62
+ * Start the polling loop.
63
+ */
64
+ startPolling(): Promise<void>;
65
+ /**
66
+ * Stop the polling loop.
67
+ */
68
+ stopPolling(): void;
69
+ /**
70
+ * Run a single poll cycle across all watched repositories.
71
+ * Process:* labels are checked every cycle (2 labels × N repos).
72
+ * Completed:* labels for resume detection are checked every Nth cycle.
73
+ */
74
+ poll(): Promise<void>;
75
+ /**
76
+ * Poll a single repository for trigger labels.
77
+ * Uses known label names from WORKFLOW_LABELS to avoid GraphQL listLabels calls.
78
+ * listIssuesWithLabel uses the REST API (separate rate limit bucket).
79
+ *
80
+ * @param checkCompleted - Whether to also check completed:* labels for resume detection
81
+ */
82
+ private pollRepo;
83
+ /**
84
+ * Record that a webhook event was received, updating health tracking.
85
+ */
86
+ recordWebhookEvent(): void;
87
+ /**
88
+ * Update adaptive polling interval based on webhook health.
89
+ */
90
+ private updateAdaptivePolling;
91
+ getState(): Readonly<MonitorState>;
92
+ private sleep;
93
+ }
94
+ export {};
95
+ //# sourceMappingURL=label-monitor-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label-monitor-service.d.ts","sourceRoot":"","sources":["../../src/services/label-monitor-service.ts"],"names":[],"mappings":"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"}