@mastra/factory 0.0.0-esbuild-bundle-worker-20260807173433

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 (329) hide show
  1. package/CHANGELOG.md +1008 -0
  2. package/LICENSE.md +30 -0
  3. package/README.md +27 -0
  4. package/dist/auth.d.ts +183 -0
  5. package/dist/auth.d.ts.map +1 -0
  6. package/dist/auth.js +507 -0
  7. package/dist/auth.js.map +1 -0
  8. package/dist/capabilities/connection.d.ts +9 -0
  9. package/dist/capabilities/connection.d.ts.map +1 -0
  10. package/dist/capabilities/connection.js +1 -0
  11. package/dist/capabilities/intake.d.ts +141 -0
  12. package/dist/capabilities/intake.d.ts.map +1 -0
  13. package/dist/capabilities/intake.js +1 -0
  14. package/dist/capabilities/version-control.d.ts +247 -0
  15. package/dist/capabilities/version-control.d.ts.map +1 -0
  16. package/dist/capabilities/version-control.js +1 -0
  17. package/dist/factory.d.ts +159 -0
  18. package/dist/factory.d.ts.map +1 -0
  19. package/dist/factory.js +491 -0
  20. package/dist/factory.js.map +1 -0
  21. package/dist/index.d.ts +14 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +7 -0
  24. package/dist/integrations/base.d.ts +254 -0
  25. package/dist/integrations/base.d.ts.map +1 -0
  26. package/dist/integrations/base.js +1 -0
  27. package/dist/integrations/github/config.d.ts +60 -0
  28. package/dist/integrations/github/config.d.ts.map +1 -0
  29. package/dist/integrations/github/config.js +42 -0
  30. package/dist/integrations/github/config.js.map +1 -0
  31. package/dist/integrations/github/integration.d.ts +220 -0
  32. package/dist/integrations/github/integration.d.ts.map +1 -0
  33. package/dist/integrations/github/integration.js +1162 -0
  34. package/dist/integrations/github/integration.js.map +1 -0
  35. package/dist/integrations/github/issue-triage.d.ts +27 -0
  36. package/dist/integrations/github/issue-triage.d.ts.map +1 -0
  37. package/dist/integrations/github/issue-triage.js +82 -0
  38. package/dist/integrations/github/issue-triage.js.map +1 -0
  39. package/dist/integrations/github/pat.d.ts +38 -0
  40. package/dist/integrations/github/pat.d.ts.map +1 -0
  41. package/dist/integrations/github/pat.js +59 -0
  42. package/dist/integrations/github/pat.js.map +1 -0
  43. package/dist/integrations/github/provenance.d.ts +27 -0
  44. package/dist/integrations/github/provenance.d.ts.map +1 -0
  45. package/dist/integrations/github/provenance.js +75 -0
  46. package/dist/integrations/github/provenance.js.map +1 -0
  47. package/dist/integrations/github/reconcile-worker.d.ts +41 -0
  48. package/dist/integrations/github/reconcile-worker.d.ts.map +1 -0
  49. package/dist/integrations/github/reconcile-worker.js +125 -0
  50. package/dist/integrations/github/reconcile-worker.js.map +1 -0
  51. package/dist/integrations/github/routes.d.ts +69 -0
  52. package/dist/integrations/github/routes.d.ts.map +1 -0
  53. package/dist/integrations/github/routes.js +1335 -0
  54. package/dist/integrations/github/routes.js.map +1 -0
  55. package/dist/integrations/github/rules.d.ts +105 -0
  56. package/dist/integrations/github/rules.d.ts.map +1 -0
  57. package/dist/integrations/github/rules.js +551 -0
  58. package/dist/integrations/github/rules.js.map +1 -0
  59. package/dist/integrations/github/sandbox-release.d.ts +53 -0
  60. package/dist/integrations/github/sandbox-release.d.ts.map +1 -0
  61. package/dist/integrations/github/sandbox-release.js +115 -0
  62. package/dist/integrations/github/sandbox-release.js.map +1 -0
  63. package/dist/integrations/github/sandbox.d.ts +281 -0
  64. package/dist/integrations/github/sandbox.d.ts.map +1 -0
  65. package/dist/integrations/github/sandbox.js +547 -0
  66. package/dist/integrations/github/sandbox.js.map +1 -0
  67. package/dist/integrations/github/session-subscriptions.d.ts +26 -0
  68. package/dist/integrations/github/session-subscriptions.d.ts.map +1 -0
  69. package/dist/integrations/github/session-subscriptions.js +192 -0
  70. package/dist/integrations/github/session-subscriptions.js.map +1 -0
  71. package/dist/integrations/github/subscriptions.d.ts +54 -0
  72. package/dist/integrations/github/subscriptions.d.ts.map +1 -0
  73. package/dist/integrations/github/subscriptions.js +62 -0
  74. package/dist/integrations/github/subscriptions.js.map +1 -0
  75. package/dist/integrations/github/token-refresh.d.ts +12 -0
  76. package/dist/integrations/github/token-refresh.d.ts.map +1 -0
  77. package/dist/integrations/github/token-refresh.js +24 -0
  78. package/dist/integrations/github/token-refresh.js.map +1 -0
  79. package/dist/integrations/github/webhook.d.ts +107 -0
  80. package/dist/integrations/github/webhook.d.ts.map +1 -0
  81. package/dist/integrations/github/webhook.js +371 -0
  82. package/dist/integrations/github/webhook.js.map +1 -0
  83. package/dist/integrations/linear/agent-tools.d.ts +34 -0
  84. package/dist/integrations/linear/agent-tools.d.ts.map +1 -0
  85. package/dist/integrations/linear/agent-tools.js +85 -0
  86. package/dist/integrations/linear/agent-tools.js.map +1 -0
  87. package/dist/integrations/linear/integration.d.ts +235 -0
  88. package/dist/integrations/linear/integration.d.ts.map +1 -0
  89. package/dist/integrations/linear/integration.js +676 -0
  90. package/dist/integrations/linear/integration.js.map +1 -0
  91. package/dist/integrations/linear/routes.d.ts +61 -0
  92. package/dist/integrations/linear/routes.d.ts.map +1 -0
  93. package/dist/integrations/linear/routes.js +240 -0
  94. package/dist/integrations/linear/routes.js.map +1 -0
  95. package/dist/integrations/linear/rules.d.ts +44 -0
  96. package/dist/integrations/linear/rules.d.ts.map +1 -0
  97. package/dist/integrations/linear/rules.js +133 -0
  98. package/dist/integrations/linear/rules.js.map +1 -0
  99. package/dist/integrations/linear/storage.d.ts +65 -0
  100. package/dist/integrations/linear/storage.d.ts.map +1 -0
  101. package/dist/integrations/linear/storage.js +1 -0
  102. package/dist/integrations/platform/api-client.d.ts +26 -0
  103. package/dist/integrations/platform/api-client.d.ts.map +1 -0
  104. package/dist/integrations/platform/api-client.js +156 -0
  105. package/dist/integrations/platform/api-client.js.map +1 -0
  106. package/dist/integrations/platform/github/event-worker.d.ts +44 -0
  107. package/dist/integrations/platform/github/event-worker.d.ts.map +1 -0
  108. package/dist/integrations/platform/github/event-worker.js +349 -0
  109. package/dist/integrations/platform/github/event-worker.js.map +1 -0
  110. package/dist/integrations/platform/github/integration.d.ts +64 -0
  111. package/dist/integrations/platform/github/integration.d.ts.map +1 -0
  112. package/dist/integrations/platform/github/integration.js +1006 -0
  113. package/dist/integrations/platform/github/integration.js.map +1 -0
  114. package/dist/integrations/platform/linear/integration.d.ts +46 -0
  115. package/dist/integrations/platform/linear/integration.d.ts.map +1 -0
  116. package/dist/integrations/platform/linear/integration.js +483 -0
  117. package/dist/integrations/platform/linear/integration.js.map +1 -0
  118. package/dist/integrations/slack/connect-route.d.ts +46 -0
  119. package/dist/integrations/slack/connect-route.d.ts.map +1 -0
  120. package/dist/integrations/slack/connect-route.js +186 -0
  121. package/dist/integrations/slack/connect-route.js.map +1 -0
  122. package/dist/integrations/slack/integration.d.ts +62 -0
  123. package/dist/integrations/slack/integration.d.ts.map +1 -0
  124. package/dist/integrations/slack/integration.js +68 -0
  125. package/dist/integrations/slack/integration.js.map +1 -0
  126. package/dist/integrations/slack/slack.d.ts +200 -0
  127. package/dist/integrations/slack/slack.d.ts.map +1 -0
  128. package/dist/integrations/slack/slack.js +411 -0
  129. package/dist/integrations/slack/slack.js.map +1 -0
  130. package/dist/integrations/workos/integration.d.ts +39 -0
  131. package/dist/integrations/workos/integration.d.ts.map +1 -0
  132. package/dist/integrations/workos/integration.js +91 -0
  133. package/dist/integrations/workos/integration.js.map +1 -0
  134. package/dist/routes/config.d.ts +235 -0
  135. package/dist/routes/config.d.ts.map +1 -0
  136. package/dist/routes/config.js +972 -0
  137. package/dist/routes/config.js.map +1 -0
  138. package/dist/routes/custom-provider-source.d.ts +52 -0
  139. package/dist/routes/custom-provider-source.d.ts.map +1 -0
  140. package/dist/routes/custom-provider-source.js +124 -0
  141. package/dist/routes/custom-provider-source.js.map +1 -0
  142. package/dist/routes/fs.d.ts +151 -0
  143. package/dist/routes/fs.d.ts.map +1 -0
  144. package/dist/routes/fs.js +708 -0
  145. package/dist/routes/fs.js.map +1 -0
  146. package/dist/routes/intake.d.ts +23 -0
  147. package/dist/routes/intake.d.ts.map +1 -0
  148. package/dist/routes/intake.js +179 -0
  149. package/dist/routes/intake.js.map +1 -0
  150. package/dist/routes/oauth.d.ts +43 -0
  151. package/dist/routes/oauth.d.ts.map +1 -0
  152. package/dist/routes/oauth.js +463 -0
  153. package/dist/routes/oauth.js.map +1 -0
  154. package/dist/routes/projects.d.ts +19 -0
  155. package/dist/routes/projects.d.ts.map +1 -0
  156. package/dist/routes/projects.js +461 -0
  157. package/dist/routes/projects.js.map +1 -0
  158. package/dist/routes/provider-credentials.d.ts +81 -0
  159. package/dist/routes/provider-credentials.d.ts.map +1 -0
  160. package/dist/routes/provider-credentials.js +86 -0
  161. package/dist/routes/provider-credentials.js.map +1 -0
  162. package/dist/routes/route.d.ts +48 -0
  163. package/dist/routes/route.d.ts.map +1 -0
  164. package/dist/routes/route.js +15 -0
  165. package/dist/routes/route.js.map +1 -0
  166. package/dist/routes/skills.d.ts +30 -0
  167. package/dist/routes/skills.d.ts.map +1 -0
  168. package/dist/routes/skills.js +168 -0
  169. package/dist/routes/skills.js.map +1 -0
  170. package/dist/routes/surface.d.ts +107 -0
  171. package/dist/routes/surface.d.ts.map +1 -0
  172. package/dist/routes/surface.js +297 -0
  173. package/dist/routes/surface.js.map +1 -0
  174. package/dist/routes/tenant-credentials.d.ts +74 -0
  175. package/dist/routes/tenant-credentials.d.ts.map +1 -0
  176. package/dist/routes/tenant-credentials.js +156 -0
  177. package/dist/routes/tenant-credentials.js.map +1 -0
  178. package/dist/routes/work-items.d.ts +40 -0
  179. package/dist/routes/work-items.d.ts.map +1 -0
  180. package/dist/routes/work-items.js +695 -0
  181. package/dist/routes/work-items.js.map +1 -0
  182. package/dist/rules/binding-context.d.ts +5 -0
  183. package/dist/rules/binding-context.d.ts.map +1 -0
  184. package/dist/rules/binding-context.js +28 -0
  185. package/dist/rules/binding-context.js.map +1 -0
  186. package/dist/rules/defaults.d.ts +9 -0
  187. package/dist/rules/defaults.d.ts.map +1 -0
  188. package/dist/rules/defaults.js +322 -0
  189. package/dist/rules/defaults.js.map +1 -0
  190. package/dist/rules/dispatcher.d.ts +43 -0
  191. package/dist/rules/dispatcher.d.ts.map +1 -0
  192. package/dist/rules/dispatcher.js +547 -0
  193. package/dist/rules/dispatcher.js.map +1 -0
  194. package/dist/rules/index.d.ts +7 -0
  195. package/dist/rules/index.d.ts.map +1 -0
  196. package/dist/rules/index.js +5 -0
  197. package/dist/rules/processor.d.ts +54 -0
  198. package/dist/rules/processor.d.ts.map +1 -0
  199. package/dist/rules/processor.js +378 -0
  200. package/dist/rules/processor.js.map +1 -0
  201. package/dist/rules/resolve.d.ts +17 -0
  202. package/dist/rules/resolve.d.ts.map +1 -0
  203. package/dist/rules/resolve.js +30 -0
  204. package/dist/rules/resolve.js.map +1 -0
  205. package/dist/rules/start-coordinator.d.ts +60 -0
  206. package/dist/rules/start-coordinator.d.ts.map +1 -0
  207. package/dist/rules/start-coordinator.js +175 -0
  208. package/dist/rules/start-coordinator.js.map +1 -0
  209. package/dist/rules/tools.d.ts +10 -0
  210. package/dist/rules/tools.d.ts.map +1 -0
  211. package/dist/rules/tools.js +59 -0
  212. package/dist/rules/tools.js.map +1 -0
  213. package/dist/rules/transition-service.d.ts +49 -0
  214. package/dist/rules/transition-service.d.ts.map +1 -0
  215. package/dist/rules/transition-service.js +232 -0
  216. package/dist/rules/transition-service.js.map +1 -0
  217. package/dist/rules/types.d.ts +261 -0
  218. package/dist/rules/types.d.ts.map +1 -0
  219. package/dist/rules/types.js +43 -0
  220. package/dist/rules/types.js.map +1 -0
  221. package/dist/rules/validation.d.ts +11 -0
  222. package/dist/rules/validation.d.ts.map +1 -0
  223. package/dist/rules/validation.js +308 -0
  224. package/dist/rules/validation.js.map +1 -0
  225. package/dist/sandbox/fleet.d.ts +222 -0
  226. package/dist/sandbox/fleet.d.ts.map +1 -0
  227. package/dist/sandbox/fleet.js +322 -0
  228. package/dist/sandbox/fleet.js.map +1 -0
  229. package/dist/sandbox/reattach.d.ts +3 -0
  230. package/dist/sandbox/reattach.d.ts.map +1 -0
  231. package/dist/sandbox/reattach.js +16 -0
  232. package/dist/sandbox/reattach.js.map +1 -0
  233. package/dist/server-error.d.ts +12 -0
  234. package/dist/server-error.d.ts.map +1 -0
  235. package/dist/server-error.js +16 -0
  236. package/dist/server-error.js.map +1 -0
  237. package/dist/session/factory-session.d.ts +116 -0
  238. package/dist/session/factory-session.d.ts.map +1 -0
  239. package/dist/session/factory-session.js +162 -0
  240. package/dist/session/factory-session.js.map +1 -0
  241. package/dist/skills/service.d.ts +48 -0
  242. package/dist/skills/service.d.ts.map +1 -0
  243. package/dist/skills/service.js +40 -0
  244. package/dist/skills/service.js.map +1 -0
  245. package/dist/spa-static.d.ts +33 -0
  246. package/dist/spa-static.d.ts.map +1 -0
  247. package/dist/spa-static.js +104 -0
  248. package/dist/spa-static.js.map +1 -0
  249. package/dist/state-signing.d.ts +59 -0
  250. package/dist/state-signing.d.ts.map +1 -0
  251. package/dist/state-signing.js +83 -0
  252. package/dist/state-signing.js.map +1 -0
  253. package/dist/storage/domains/audit/agent-audit.d.ts +27 -0
  254. package/dist/storage/domains/audit/agent-audit.d.ts.map +1 -0
  255. package/dist/storage/domains/audit/agent-audit.js +66 -0
  256. package/dist/storage/domains/audit/agent-audit.js.map +1 -0
  257. package/dist/storage/domains/audit/base.d.ts +140 -0
  258. package/dist/storage/domains/audit/base.d.ts.map +1 -0
  259. package/dist/storage/domains/audit/base.js +184 -0
  260. package/dist/storage/domains/audit/base.js.map +1 -0
  261. package/dist/storage/domains/audit/domain.d.ts +76 -0
  262. package/dist/storage/domains/audit/domain.d.ts.map +1 -0
  263. package/dist/storage/domains/audit/domain.js +269 -0
  264. package/dist/storage/domains/audit/domain.js.map +1 -0
  265. package/dist/storage/domains/channel-identity/base.d.ts +96 -0
  266. package/dist/storage/domains/channel-identity/base.d.ts.map +1 -0
  267. package/dist/storage/domains/channel-identity/base.js +149 -0
  268. package/dist/storage/domains/channel-identity/base.js.map +1 -0
  269. package/dist/storage/domains/credentials/base.d.ts +134 -0
  270. package/dist/storage/domains/credentials/base.d.ts.map +1 -0
  271. package/dist/storage/domains/credentials/base.js +273 -0
  272. package/dist/storage/domains/credentials/base.js.map +1 -0
  273. package/dist/storage/domains/custom-providers/base.d.ts +57 -0
  274. package/dist/storage/domains/custom-providers/base.d.ts.map +1 -0
  275. package/dist/storage/domains/custom-providers/base.js +145 -0
  276. package/dist/storage/domains/custom-providers/base.js.map +1 -0
  277. package/dist/storage/domains/intake/base.d.ts +38 -0
  278. package/dist/storage/domains/intake/base.d.ts.map +1 -0
  279. package/dist/storage/domains/intake/base.js +80 -0
  280. package/dist/storage/domains/intake/base.js.map +1 -0
  281. package/dist/storage/domains/integrations/base.d.ts +126 -0
  282. package/dist/storage/domains/integrations/base.d.ts.map +1 -0
  283. package/dist/storage/domains/integrations/base.js +317 -0
  284. package/dist/storage/domains/integrations/base.js.map +1 -0
  285. package/dist/storage/domains/memory-settings/base.d.ts +62 -0
  286. package/dist/storage/domains/memory-settings/base.d.ts.map +1 -0
  287. package/dist/storage/domains/memory-settings/base.js +126 -0
  288. package/dist/storage/domains/memory-settings/base.js.map +1 -0
  289. package/dist/storage/domains/model-packs/base.d.ts +49 -0
  290. package/dist/storage/domains/model-packs/base.d.ts.map +1 -0
  291. package/dist/storage/domains/model-packs/base.js +96 -0
  292. package/dist/storage/domains/model-packs/base.js.map +1 -0
  293. package/dist/storage/domains/projects/base.d.ts +58 -0
  294. package/dist/storage/domains/projects/base.d.ts.map +1 -0
  295. package/dist/storage/domains/projects/base.js +111 -0
  296. package/dist/storage/domains/projects/base.js.map +1 -0
  297. package/dist/storage/domains/queue-health/base.d.ts +52 -0
  298. package/dist/storage/domains/queue-health/base.d.ts.map +1 -0
  299. package/dist/storage/domains/queue-health/base.js +122 -0
  300. package/dist/storage/domains/queue-health/base.js.map +1 -0
  301. package/dist/storage/domains/source-control/base.d.ts +360 -0
  302. package/dist/storage/domains/source-control/base.d.ts.map +1 -0
  303. package/dist/storage/domains/source-control/base.js +914 -0
  304. package/dist/storage/domains/source-control/base.js.map +1 -0
  305. package/dist/storage/domains/source-control/inmemory.d.ts +175 -0
  306. package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -0
  307. package/dist/storage/domains/source-control/inmemory.js +380 -0
  308. package/dist/storage/domains/source-control/inmemory.js.map +1 -0
  309. package/dist/storage/domains/work-items/base.d.ts +412 -0
  310. package/dist/storage/domains/work-items/base.d.ts.map +1 -0
  311. package/dist/storage/domains/work-items/base.js +1320 -0
  312. package/dist/storage/domains/work-items/base.js.map +1 -0
  313. package/dist/storage/domains/work-items/metrics.d.ts +101 -0
  314. package/dist/storage/domains/work-items/metrics.d.ts.map +1 -0
  315. package/dist/storage/domains/work-items/metrics.js +221 -0
  316. package/dist/storage/domains/work-items/metrics.js.map +1 -0
  317. package/dist/timing.d.ts +15 -0
  318. package/dist/timing.d.ts.map +1 -0
  319. package/dist/timing.js +34 -0
  320. package/dist/timing.js.map +1 -0
  321. package/dist/workspace.d.ts +24 -0
  322. package/dist/workspace.d.ts.map +1 -0
  323. package/dist/workspace.js +287 -0
  324. package/dist/workspace.js.map +1 -0
  325. package/factory-skills/configure-factory-rules/SKILL.md +67 -0
  326. package/factory-skills/factory-plan/SKILL.md +61 -0
  327. package/factory-skills/factory-review/SKILL.md +157 -0
  328. package/factory-skills/factory-triage/SKILL.md +99 -0
  329. package/package.json +83 -0
@@ -0,0 +1,551 @@
1
+ import { changeRequestTargetKey } from "./subscriptions.js";
2
+ import { resolveFactoryGithubRule } from "../../rules/resolve.js";
3
+ import { validateFactoryRuleDecisions } from "../../rules/validation.js";
4
+ //#region src/integrations/github/rules.ts
5
+ const TRUSTED_PERMISSIONS = /* @__PURE__ */ new Set(["write", "admin"]);
6
+ const RULE_TIMEOUT_MS = 5e3;
7
+ const FACTORY_TRIAGE_COMMENT_MARKER = "<!-- mastra-factory-triage -->";
8
+ async function withRuleTimeout(promise) {
9
+ let timeout;
10
+ try {
11
+ return await Promise.race([promise, new Promise((_, reject) => {
12
+ timeout = setTimeout(() => reject(/* @__PURE__ */ new Error("FACTORY_RULE_TIMEOUT")), RULE_TIMEOUT_MS);
13
+ })]);
14
+ } finally {
15
+ if (timeout) clearTimeout(timeout);
16
+ }
17
+ }
18
+ function object(value) {
19
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
20
+ }
21
+ function string(value) {
22
+ return typeof value === "string" && value.length > 0 ? value : void 0;
23
+ }
24
+ function number(value) {
25
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
26
+ }
27
+ function boolean(value) {
28
+ return typeof value === "boolean" ? value : void 0;
29
+ }
30
+ function actorLogins(value) {
31
+ if (!Array.isArray(value)) return [];
32
+ return value.flatMap((actor) => {
33
+ const login = string(object(actor)?.login);
34
+ return login ? [login] : [];
35
+ });
36
+ }
37
+ function eventName(parsed) {
38
+ const action = string(parsed.payload.action);
39
+ if (parsed.event === "issues" && action === "opened") return "issueOpened";
40
+ if (parsed.event === "issues" && action === "edited") {
41
+ const changes = object(parsed.payload.changes);
42
+ return object(changes?.title) || object(changes?.body) ? "issueEdited" : void 0;
43
+ }
44
+ if (parsed.event === "issues" && action === "closed") return "issueClosed";
45
+ if (parsed.event === "issue_comment") {
46
+ if (object(object(parsed.payload.issue)?.pull_request)) return void 0;
47
+ if (action === "created") return "issueCommentCreated";
48
+ if (action === "edited") return "issueCommentEdited";
49
+ if (action === "deleted") return "issueCommentDeleted";
50
+ }
51
+ if (parsed.event === "pull_request" && action === "opened") return "pullRequestOpened";
52
+ if (parsed.event === "pull_request" && action === "synchronize") return "pullRequestUpdated";
53
+ if (parsed.event === "pull_request" && action === "closed") return boolean(object(parsed.payload.pull_request)?.merged) ? "pullRequestMerged" : "pullRequestClosed";
54
+ if (parsed.event === "pull_request" && action === "review_requested") return "pullRequestReviewRequested";
55
+ }
56
+ /**
57
+ * Canonical source keys (`github-issue:N`, `github-pr:N`) do not identify a
58
+ * repository, so a project linked to several repositories could bind repo A's
59
+ * event to repo B's same-numbered card. The card's intake-stamped URL is
60
+ * authoritative; the intake-stamped `githubRepositoryId` covers URL-less
61
+ * cards. A card with neither signal cannot be attributed by number alone.
62
+ */
63
+ function cardBelongsToRepository(item, repositoryId, repositoryFullName) {
64
+ const url = item.externalSource?.url;
65
+ if (url) {
66
+ const match = /^https?:\/\/[^/]+\/(.+)\/(?:issues|pull)\/\d+(?:[/?#]|$)/.exec(url);
67
+ if (match && match[1] === repositoryFullName) return true;
68
+ }
69
+ return item.metadata?.githubRepositoryId === repositoryId;
70
+ }
71
+ function canonicalSourceKey(kind, itemNumber) {
72
+ return kind === "issue" ? `github-issue:${itemNumber}` : `github-pr:${itemNumber}`;
73
+ }
74
+ function legacySourceKey(repositoryId, kind, itemNumber) {
75
+ return `github:${repositoryId}:${kind}:${itemNumber}`;
76
+ }
77
+ function provenanceTarget(repositoryId, pullRequestNumber) {
78
+ return `factory-pr-provenance:${repositoryId}:${pullRequestNumber}`;
79
+ }
80
+ function workItemSource(item) {
81
+ if (!item.externalSource) return "manual";
82
+ return item.externalSource.type === "pull-request" ? "github-pr" : "github-issue";
83
+ }
84
+ function workItemSourceKey(item) {
85
+ return item.externalSource?.externalId ?? null;
86
+ }
87
+ async function githubActor(github, input) {
88
+ let trusted = false;
89
+ try {
90
+ const permission = await github.getRepositoryCollaboratorPermission(input.installationId, input.repository, input.login);
91
+ trusted = permission !== void 0 && TRUSTED_PERMISSIONS.has(permission);
92
+ } catch {
93
+ trusted = false;
94
+ }
95
+ return {
96
+ type: "github",
97
+ login: input.login,
98
+ trusted,
99
+ factoryAuthored: input.factoryAuthored
100
+ };
101
+ }
102
+ function pullRequestProvenance(data) {
103
+ if (!data || data.kind !== "factory-pr-provenance" || typeof data.workItemId !== "string") return null;
104
+ return {
105
+ kind: "factory-pr-provenance",
106
+ workItemId: data.workItemId
107
+ };
108
+ }
109
+ var GithubRules = class {
110
+ options;
111
+ constructor(options) {
112
+ this.options = options;
113
+ }
114
+ async ingest(parsed) {
115
+ const event = eventName(parsed);
116
+ const repository = object(parsed.payload.repository);
117
+ const installationId = number(object(parsed.payload.installation)?.id);
118
+ const repositoryId = number(repository?.id);
119
+ const repositoryName = string(repository?.full_name);
120
+ const login = string(object(parsed.payload.sender)?.login);
121
+ if (!event || !installationId || !repositoryId || !repositoryName || !login) return { status: "ignored" };
122
+ const projects = await this.options.sourceControl.projectRepositories.listByExternalRepository({
123
+ installationExternalId: String(installationId),
124
+ repositoryExternalId: String(repositoryId)
125
+ });
126
+ if (projects.length === 0) return { status: "ignored" };
127
+ const results = [];
128
+ for (const project of projects) results.push(await this.#ingestProject(parsed, event, installationId, repositoryId, repositoryName, login, project));
129
+ if (results.some((result) => result.status === "committed")) return { status: "committed" };
130
+ if (results.some((result) => result.status === "replayed")) return { status: "replayed" };
131
+ return results[0] ?? { status: "ignored" };
132
+ }
133
+ async #ingestProject(parsed, event, installationId, repositoryId, repositoryName, login, project) {
134
+ const factoryProject = await this.options.projects.get({
135
+ orgId: project.orgId,
136
+ id: project.factoryProjectId
137
+ });
138
+ if (!factoryProject) return { status: "missing" };
139
+ const issue = object(parsed.payload.issue);
140
+ const issueComment = object(parsed.payload.comment);
141
+ const changes = object(parsed.payload.changes);
142
+ const pullRequest = object(parsed.payload.pull_request);
143
+ const issueNumber = number(issue?.number);
144
+ const pullRequestNumber = number(pullRequest?.number);
145
+ const provenance = pullRequestNumber ? pullRequestProvenance((await this.options.integrationStorage.subscriptions.listByTarget(provenanceTarget(repositoryId, pullRequestNumber), { status: "active" })).find((subscription) => subscription.orgId === project.orgId)?.data) : null;
146
+ const reviewRequested = event === "pullRequestReviewRequested";
147
+ const requestedReviewer = string(object(parsed.payload.requested_reviewer)?.login);
148
+ const relatedItem = await this.#relatedItem(project.orgId, project.factoryProjectId, repositoryId, repositoryName, issueNumber, pullRequestNumber, string(object(pullRequest?.head)?.ref), reviewRequested ? null : provenance);
149
+ const actor = await githubActor(this.options.github, {
150
+ installationId,
151
+ repository: repositoryName,
152
+ login,
153
+ factoryAuthored: !reviewRequested && provenance !== null || login === `${this.options.github.slug}[bot]`
154
+ });
155
+ if (actor.type === "github" && actor.factoryAuthored && (event === "issueCommentCreated" || event === "issueCommentEdited") && string(issueComment?.body)?.includes(FACTORY_TRIAGE_COMMENT_MARKER)) return { status: "ignored" };
156
+ const context = {
157
+ tenant: {
158
+ orgId: project.orgId,
159
+ projectId: project.factoryProjectId
160
+ },
161
+ actor,
162
+ ingress: {
163
+ type: "github",
164
+ id: `${installationId}:${parsed.deliveryId}`
165
+ },
166
+ cause: `github.${event}`,
167
+ causalChain: [],
168
+ ruleSetVersion: this.options.rules.version,
169
+ ...relatedItem ? {
170
+ item: {
171
+ id: relatedItem.id,
172
+ source: workItemSource(relatedItem),
173
+ sourceKey: workItemSourceKey(relatedItem),
174
+ parentWorkItemId: relatedItem.parentWorkItemId,
175
+ title: relatedItem.title,
176
+ url: relatedItem.externalSource?.url ?? null,
177
+ stages: relatedItem.stages
178
+ },
179
+ board: relatedItem.externalSource?.type === "pull-request" ? "review" : "work",
180
+ itemRevision: relatedItem.revision
181
+ } : {},
182
+ event,
183
+ deliveryId: parsed.deliveryId,
184
+ factory: { createdAt: factoryProject.createdAt.toISOString() },
185
+ repository: {
186
+ id: repositoryId,
187
+ fullName: repositoryName
188
+ },
189
+ ...issueNumber && string(issue?.title) && string(issue?.html_url) ? { issue: {
190
+ number: issueNumber,
191
+ title: string(issue?.title),
192
+ url: string(issue?.html_url),
193
+ ...string(issue?.created_at) ? { createdAt: string(issue?.created_at) } : {},
194
+ ...string(issue?.updated_at) ? { updatedAt: string(issue?.updated_at) } : {},
195
+ assignees: actorLogins(issue?.assignees),
196
+ ...string(issue?.state) === "closed" || string(issue?.state) === "open" ? { state: string(issue?.state) } : {},
197
+ ...string(issue?.state_reason) ? { stateReason: string(issue?.state_reason) } : {}
198
+ } } : {},
199
+ ...event === "issueEdited" ? { issueChange: {
200
+ title: Boolean(object(changes?.title)),
201
+ body: Boolean(object(changes?.body))
202
+ } } : {},
203
+ ...number(issueComment?.id) ? { issueComment: {
204
+ id: number(issueComment?.id),
205
+ ...string(issueComment?.body) ? { body: string(issueComment?.body) } : {},
206
+ ...string(issueComment?.html_url) ? { url: string(issueComment?.html_url) } : {},
207
+ ...string(object(issueComment?.user)?.login) ? { author: string(object(issueComment?.user)?.login) } : {},
208
+ ...string(object(issueComment?.user)?.type) ? { authorType: string(object(issueComment?.user)?.type) } : {},
209
+ ...string(issueComment?.created_at) ? { createdAt: string(issueComment?.created_at) } : {},
210
+ ...string(issueComment?.updated_at) ? { updatedAt: string(issueComment?.updated_at) } : {}
211
+ } } : {},
212
+ ...pullRequestNumber && string(pullRequest?.title) && string(pullRequest?.html_url) ? { pullRequest: {
213
+ number: pullRequestNumber,
214
+ title: string(pullRequest?.title),
215
+ url: string(pullRequest?.html_url),
216
+ ...string(pullRequest?.created_at) ? { createdAt: string(pullRequest?.created_at) } : {},
217
+ state: string(pullRequest?.state) === "closed" ? "closed" : "open",
218
+ draft: boolean(pullRequest?.draft) ?? false,
219
+ merged: boolean(pullRequest?.merged) ?? false,
220
+ assignees: actorLogins(pullRequest?.assignees),
221
+ requestedReviewers: actorLogins(pullRequest?.requested_reviewers),
222
+ headBranch: string(object(pullRequest?.head)?.ref) ?? "",
223
+ baseBranch: string(object(pullRequest?.base)?.ref) ?? ""
224
+ } } : {},
225
+ ...reviewRequested && requestedReviewer ? { reviewRequest: {
226
+ reviewer: requestedReviewer,
227
+ factoryReviewer: requestedReviewer === `${this.options.github.slug}[bot]`
228
+ } } : {},
229
+ ...object(parsed.payload.review) ? { review: {
230
+ id: number(object(parsed.payload.review)?.id) ?? 0,
231
+ state: string(object(parsed.payload.review)?.state) ?? "unknown",
232
+ url: string(object(parsed.payload.review)?.html_url) ?? ""
233
+ } } : {}
234
+ };
235
+ const rule = resolveFactoryGithubRule(this.options.rules, event);
236
+ let decision;
237
+ let decisions = [];
238
+ let outcome = { status: "accepted" };
239
+ try {
240
+ decision = rule ? await withRuleTimeout(Promise.resolve(rule(Object.freeze(context)))) : void 0;
241
+ if (decision?.type === "reject") outcome = {
242
+ status: "rejected",
243
+ code: decision.code,
244
+ reason: decision.reason
245
+ };
246
+ else if (decision) decisions = validateFactoryRuleDecisions([decision]).map((entry) => ({ ...entry }));
247
+ } catch (error) {
248
+ const timedOut = error instanceof Error && error.message === "FACTORY_RULE_TIMEOUT";
249
+ outcome = {
250
+ status: "rejected",
251
+ code: timedOut ? "timeout" : "rule_error",
252
+ reason: timedOut ? "Factory rule evaluation timed out." : error instanceof Error ? error.message.slice(0, 2e3) : "Factory GitHub rule failed."
253
+ };
254
+ }
255
+ return { status: (await this.options.storage.commitRuleEvaluation({
256
+ orgId: project.orgId,
257
+ factoryProjectId: project.factoryProjectId,
258
+ workItemId: relatedItem?.id ?? null,
259
+ ingress: {
260
+ identity: `${installationId}:${parsed.deliveryId}`,
261
+ triggerType: `github.${event}`
262
+ },
263
+ ruleSetVersion: this.options.rules.version,
264
+ expectedRevision: relatedItem?.revision ?? null,
265
+ actor: { ...actor },
266
+ outcome,
267
+ decisions,
268
+ causalChain: [],
269
+ now: /* @__PURE__ */ new Date()
270
+ })).status };
271
+ }
272
+ async #relatedItem(orgId, projectId, repositoryId, repositoryFullName, issueNumber, pullRequestNumber, pullRequestHeadBranch, provenance) {
273
+ const items = await this.options.storage.list({
274
+ orgId,
275
+ factoryProjectId: projectId
276
+ });
277
+ if (provenance) return items.find((item) => item.id === provenance.workItemId);
278
+ if (issueNumber) return items.find((item) => item.externalSource?.externalId === canonicalSourceKey("issue", issueNumber) && cardBelongsToRepository(item, repositoryId, repositoryFullName)) ?? items.find((item) => item.externalSource?.externalId === legacySourceKey(repositoryId, "issue", issueNumber));
279
+ if (pullRequestNumber) return items.find((item) => item.externalSource?.externalId === canonicalSourceKey("pull-request", pullRequestNumber) && cardBelongsToRepository(item, repositoryId, repositoryFullName)) ?? items.find((item) => item.externalSource?.externalId === legacySourceKey(repositoryId, "pull-request", pullRequestNumber)) ?? (pullRequestHeadBranch ? items.find((item) => item.externalSource?.type !== "pull-request" && Object.values(item.sessions).some((session) => session.branch === pullRequestHeadBranch)) : void 0);
280
+ }
281
+ };
282
+ const RECONCILE_ERROR_SAMPLE_LIMIT = 5;
283
+ function sameStrings(left, right) {
284
+ if (right === void 0) return true;
285
+ if (!Array.isArray(left)) return false;
286
+ const leftValues = new Set(left.flatMap((value) => typeof value === "string" ? [value] : []));
287
+ const rightValues = new Set(right);
288
+ return leftValues.size === rightValues.size && [...leftValues].every((value) => rightValues.has(value));
289
+ }
290
+ /**
291
+ * Extracts the PR number a work item tracks, but only when the item belongs
292
+ * to the given repository. Card URLs pin the repository unambiguously; the
293
+ * legacy source key embeds the repository id. Canonical keys (`github-pr:N`)
294
+ * carry no repository, so they are only trusted when the item has no URL —
295
+ * a project mapped to multiple repositories must not reconcile one repo's
296
+ * card against another repo's PR number.
297
+ */
298
+ function reconcilablePullRequestNumber(item, repository) {
299
+ if (item.externalSource?.type !== "pull-request") return void 0;
300
+ const url = item.externalSource.url;
301
+ if (url) {
302
+ const match = /^https?:\/\/[^/]+\/(.+)\/pull\/(\d+)(?:[/?#]|$)/.exec(url);
303
+ if (!match) return void 0;
304
+ return match[1] === repository.fullName ? Number(match[2]) : void 0;
305
+ }
306
+ const externalId = item.externalSource.externalId;
307
+ const legacy = /^github:(\d+):pull-request:(\d+)$/.exec(externalId);
308
+ if (legacy) return Number(legacy[1]) === repository.id ? Number(legacy[2]) : void 0;
309
+ const canonical = /^github-pr:(\d+)$/.exec(externalId);
310
+ return canonical ? Number(canonical[1]) : void 0;
311
+ }
312
+ /**
313
+ * Extracts the issue number a work item tracks, but only when the item
314
+ * belongs to the given repository. Stricter than
315
+ * {@link reconcilablePullRequestNumber}: a canonical key with no URL is only
316
+ * trusted when the intake-stamped `githubRepositoryId` confirms the
317
+ * repository, because the sweep initiates closes on its own.
318
+ */
319
+ function reconcilableIssueNumber(item, repository) {
320
+ if (item.externalSource?.type !== "issue") return void 0;
321
+ const url = item.externalSource.url;
322
+ if (url) {
323
+ const match = /^https?:\/\/[^/]+\/(.+)\/issues\/(\d+)(?:[/?#]|$)/.exec(url);
324
+ if (!match) return void 0;
325
+ return match[1] === repository.fullName || item.metadata?.githubRepositoryId === repository.id ? Number(match[2]) : void 0;
326
+ }
327
+ const externalId = item.externalSource.externalId;
328
+ const legacy = /^github:(\d+):issue:(\d+)$/.exec(externalId);
329
+ if (legacy) return Number(legacy[1]) === repository.id ? Number(legacy[2]) : void 0;
330
+ const canonical = /^github-issue:(\d+)$/.exec(externalId);
331
+ if (!canonical) return void 0;
332
+ return item.metadata?.githubRepositoryId === repository.id ? Number(canonical[1]) : void 0;
333
+ }
334
+ function reconciledIssueClosedEvent(repository, issueNumber, state) {
335
+ return {
336
+ event: "issues",
337
+ deliveryId: `reconcile:${repository.id}:issue:${issueNumber}:closed`,
338
+ payload: {
339
+ action: "closed",
340
+ installation: { id: repository.installationId },
341
+ repository: {
342
+ id: repository.id,
343
+ full_name: repository.fullName
344
+ },
345
+ sender: { login: state.author ?? "github" },
346
+ issue: {
347
+ number: issueNumber,
348
+ title: state.title,
349
+ html_url: state.url,
350
+ state: "closed",
351
+ ...state.stateReason ? { state_reason: state.stateReason } : {},
352
+ ...state.createdAt ? { created_at: state.createdAt } : {},
353
+ ...state.updatedAt ? { updated_at: state.updatedAt } : {},
354
+ assignees: (state.assignees ?? []).map((login) => ({ login }))
355
+ }
356
+ }
357
+ };
358
+ }
359
+ function reconciledClosedEvent(repository, pullRequestNumber, state) {
360
+ return {
361
+ event: "pull_request",
362
+ deliveryId: `reconcile:${repository.id}:pull-request:${pullRequestNumber}:${state.merged ? "merged" : "closed"}`,
363
+ payload: {
364
+ action: "closed",
365
+ installation: { id: repository.installationId },
366
+ repository: {
367
+ id: repository.id,
368
+ full_name: repository.fullName
369
+ },
370
+ sender: { login: state.mergedBy ?? "github" },
371
+ pull_request: {
372
+ number: pullRequestNumber,
373
+ title: state.title,
374
+ html_url: state.url,
375
+ ...state.createdAt ? { created_at: state.createdAt } : {},
376
+ state: "closed",
377
+ draft: state.draft,
378
+ merged: state.merged,
379
+ assignees: (state.assignees ?? []).map((login) => ({ login })),
380
+ requested_reviewers: (state.requestedReviewers ?? []).map((login) => ({ login })),
381
+ head: { ref: state.headBranch },
382
+ base: { ref: state.baseBranch }
383
+ }
384
+ }
385
+ };
386
+ }
387
+ /**
388
+ * The webhook handler retires subscriptions itself; the sweep replays only the
389
+ * rules ingress, so without this the thread's PR chip and the workspace row
390
+ * stay `open` forever on a deployment GitHub cannot reach.
391
+ */
392
+ async function retireReconciledSubscriptions(storage, repository, pullRequestNumber, merged) {
393
+ const target = changeRequestTargetKey({
394
+ installationExternalId: String(repository.installationId),
395
+ repositoryExternalId: String(repository.id),
396
+ changeRequestId: String(pullRequestNumber)
397
+ });
398
+ const rows = await storage.subscriptions.listByTarget(target);
399
+ await Promise.all(rows.filter((row) => row.status === "open").map((row) => storage.subscriptions.updateStatus(row.id, merged ? "merged" : "closed")));
400
+ }
401
+ /**
402
+ * State-based safety net for merge signals: webhooks and event-log tailing
403
+ * can miss a merge (cursor gaps, downtime, terminally failed decisions), so
404
+ * this sweep compares still-open PR cards against actual GitHub state and
405
+ * replays the merge through the normal rules ingress when they disagree.
406
+ */
407
+ function createGithubPullRequestReconciler(options, fetchPullRequest, fetchIssue) {
408
+ const rules = new GithubRules(options);
409
+ return async (repositories) => {
410
+ const summary = {
411
+ repositories: 0,
412
+ checked: 0,
413
+ merged: 0,
414
+ closed: 0,
415
+ issuesChecked: 0,
416
+ issuesClosed: 0,
417
+ failed: 0,
418
+ errors: []
419
+ };
420
+ const recordFailure = (repository, error, numbers) => {
421
+ summary.failed += 1;
422
+ if (summary.errors.length < RECONCILE_ERROR_SAMPLE_LIMIT) summary.errors.push({
423
+ repository: repository.fullName,
424
+ ...numbers?.pullRequestNumber === void 0 ? {} : { pullRequestNumber: numbers.pullRequestNumber },
425
+ ...numbers?.issueNumber === void 0 ? {} : { issueNumber: numbers.issueNumber },
426
+ error: error instanceof Error ? error.message : String(error)
427
+ });
428
+ };
429
+ const configured = new Set((await options.sourceControl.projectRepositories.listConfiguredExternalKeys()).map((key) => `${key.installationExternalId}\u0000${key.repositoryExternalId}`));
430
+ const scoped = repositories.filter((repository) => configured.has(`${repository.installationId}\u0000${repository.id}`));
431
+ summary.repositories = scoped.length;
432
+ for (const repository of scoped) {
433
+ let cardsByNumber;
434
+ const issueNumbers = /* @__PURE__ */ new Set();
435
+ try {
436
+ const projects = await options.sourceControl.projectRepositories.listByExternalRepository({
437
+ installationExternalId: String(repository.installationId),
438
+ repositoryExternalId: String(repository.id)
439
+ });
440
+ if (projects.length === 0) continue;
441
+ cardsByNumber = /* @__PURE__ */ new Map();
442
+ for (const project of projects) {
443
+ const items = await options.storage.list({
444
+ orgId: project.orgId,
445
+ factoryProjectId: project.factoryProjectId
446
+ });
447
+ for (const item of items) {
448
+ const stage = item.stages[0];
449
+ if (fetchIssue) {
450
+ const issueNumber = reconcilableIssueNumber(item, repository);
451
+ if (issueNumber && stage !== "done" && stage !== "canceled") issueNumbers.add(issueNumber);
452
+ }
453
+ const pullRequestNumber = reconcilablePullRequestNumber(item, repository);
454
+ if (!pullRequestNumber) continue;
455
+ const metadata = item.metadata ?? {};
456
+ const hasReconciledMetadata = (metadata.state === "open" || metadata.state === "closed") && typeof metadata.draft === "boolean" && typeof metadata.merged === "boolean" && typeof metadata.author === "string" && Array.isArray(metadata.assignees) && Array.isArray(metadata.requestedReviewers);
457
+ if ((stage === "done" || stage === "canceled") && hasReconciledMetadata) continue;
458
+ const cards = cardsByNumber.get(pullRequestNumber) ?? [];
459
+ cards.push(item);
460
+ cardsByNumber.set(pullRequestNumber, cards);
461
+ }
462
+ }
463
+ } catch (error) {
464
+ recordFailure(repository, error);
465
+ continue;
466
+ }
467
+ for (const [pullRequestNumber, cards] of cardsByNumber) try {
468
+ const state = await fetchPullRequest({
469
+ installationId: repository.installationId,
470
+ repository: repository.fullName,
471
+ number: pullRequestNumber
472
+ });
473
+ summary.checked += 1;
474
+ if (!state) continue;
475
+ for (const card of cards) {
476
+ const metadata = card.metadata ?? {};
477
+ const statusChanged = metadata.state !== state.state || metadata.draft !== state.draft || metadata.merged !== state.merged;
478
+ const authorChanged = state.author !== void 0 && metadata.author !== state.author;
479
+ const assigneesChanged = !sameStrings(metadata.assignees, state.assignees);
480
+ const reviewersChanged = !sameStrings(metadata.requestedReviewers, state.requestedReviewers);
481
+ if (!statusChanged && !authorChanged && !assigneesChanged && !reviewersChanged) continue;
482
+ try {
483
+ await options.storage.update({
484
+ orgId: card.orgId,
485
+ id: card.id,
486
+ userId: "factory-rule-dispatcher",
487
+ patch: { metadata: {
488
+ state: state.state,
489
+ draft: state.draft,
490
+ merged: state.merged,
491
+ ...state.author ? { author: state.author } : {},
492
+ ...state.assignees ? { assignees: state.assignees } : {},
493
+ ...state.requestedReviewers ? { requestedReviewers: state.requestedReviewers } : {}
494
+ } }
495
+ });
496
+ } catch (error) {
497
+ recordFailure(repository, error, { pullRequestNumber });
498
+ }
499
+ }
500
+ if (state.state !== "closed") continue;
501
+ await rules.ingest(reconciledClosedEvent(repository, pullRequestNumber, state));
502
+ await retireReconciledSubscriptions(options.integrationStorage, repository, pullRequestNumber, state.merged);
503
+ if (state.merged) summary.merged += 1;
504
+ else summary.closed += 1;
505
+ } catch (error) {
506
+ recordFailure(repository, error, { pullRequestNumber });
507
+ }
508
+ if (!fetchIssue) continue;
509
+ for (const issueNumber of issueNumbers) try {
510
+ const state = await fetchIssue({
511
+ installationId: repository.installationId,
512
+ repository: repository.fullName,
513
+ number: issueNumber
514
+ });
515
+ summary.issuesChecked += 1;
516
+ if (!state || state.state !== "closed") continue;
517
+ await rules.ingest(reconciledIssueClosedEvent(repository, issueNumber, state));
518
+ summary.issuesClosed += 1;
519
+ } catch (error) {
520
+ recordFailure(repository, error, { issueNumber });
521
+ }
522
+ }
523
+ return summary;
524
+ };
525
+ }
526
+ function githubRulesOptions(github, context) {
527
+ if (!context.rules) return void 0;
528
+ return {
529
+ github,
530
+ sourceControl: context.storage.sourceControl,
531
+ integrationStorage: context.storage.generic,
532
+ projects: context.storage.projects,
533
+ storage: context.rules.workItems,
534
+ rules: context.rules.config
535
+ };
536
+ }
537
+ function attachGithubRules(github, context) {
538
+ const options = githubRulesOptions(github, context);
539
+ if (!options) return void 0;
540
+ const rules = new GithubRules(options);
541
+ return (event) => rules.ingest(event);
542
+ }
543
+ function attachGithubReconciler(github, context, fetchPullRequest, fetchIssue) {
544
+ const options = githubRulesOptions(github, context);
545
+ if (!options) return void 0;
546
+ return createGithubPullRequestReconciler(options, fetchPullRequest, fetchIssue);
547
+ }
548
+ //#endregion
549
+ export { GithubRules, attachGithubReconciler, attachGithubRules, createGithubPullRequestReconciler, reconciledClosedEvent, reconciledIssueClosedEvent };
550
+
551
+ //# sourceMappingURL=rules.js.map