@mastra/factory 0.15.1-alpha.0 → 0.16.0-alpha.11

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 (372) hide show
  1. package/README.md +41 -3
  2. package/dist/auth.js +1 -1
  3. package/dist/auth.js.map +1 -1
  4. package/dist/boards/index.d.ts +1 -1
  5. package/dist/boards/index.d.ts.map +1 -1
  6. package/dist/boards/index.js +2 -2
  7. package/dist/boards/index.js.map +1 -1
  8. package/dist/boards/review.d.ts.map +1 -1
  9. package/dist/boards/review.js +23 -9
  10. package/dist/boards/review.js.map +1 -1
  11. package/dist/boards/semantics.d.ts +7 -0
  12. package/dist/boards/semantics.d.ts.map +1 -1
  13. package/dist/boards/semantics.js +15 -1
  14. package/dist/boards/semantics.js.map +1 -1
  15. package/dist/boards/work.d.ts.map +1 -1
  16. package/dist/boards/work.js +68 -6
  17. package/dist/boards/work.js.map +1 -1
  18. package/dist/capabilities/intake.d.ts +8 -0
  19. package/dist/capabilities/intake.d.ts.map +1 -1
  20. package/dist/capabilities/version-control.d.ts +15 -0
  21. package/dist/capabilities/version-control.d.ts.map +1 -1
  22. package/dist/factory.d.ts +8 -5
  23. package/dist/factory.d.ts.map +1 -1
  24. package/dist/factory.js +136 -53
  25. package/dist/factory.js.map +1 -1
  26. package/dist/integrations/base.d.ts +5 -0
  27. package/dist/integrations/base.d.ts.map +1 -1
  28. package/dist/integrations/github/integration.d.ts.map +1 -1
  29. package/dist/integrations/github/integration.js +21 -0
  30. package/dist/integrations/github/integration.js.map +1 -1
  31. package/dist/integrations/github/routes.js +2 -1
  32. package/dist/integrations/github/routes.js.map +1 -1
  33. package/dist/integrations/github/sandbox.d.ts +41 -42
  34. package/dist/integrations/github/sandbox.d.ts.map +1 -1
  35. package/dist/integrations/github/sandbox.js +416 -227
  36. package/dist/integrations/github/sandbox.js.map +1 -1
  37. package/dist/integrations/github/webhook.d.ts +2 -5
  38. package/dist/integrations/github/webhook.d.ts.map +1 -1
  39. package/dist/integrations/github/webhook.js +8 -48
  40. package/dist/integrations/github/webhook.js.map +1 -1
  41. package/dist/integrations/gitlab/agent-tools.d.ts +14 -0
  42. package/dist/integrations/gitlab/agent-tools.d.ts.map +1 -0
  43. package/dist/integrations/gitlab/agent-tools.js +42 -0
  44. package/dist/integrations/gitlab/agent-tools.js.map +1 -0
  45. package/dist/integrations/gitlab/api.d.ts +222 -0
  46. package/dist/integrations/gitlab/api.d.ts.map +1 -0
  47. package/dist/integrations/gitlab/api.js +274 -0
  48. package/dist/integrations/gitlab/api.js.map +1 -0
  49. package/dist/integrations/gitlab/default-rules.d.ts +125 -0
  50. package/dist/integrations/gitlab/default-rules.d.ts.map +1 -0
  51. package/dist/integrations/gitlab/default-rules.js +172 -0
  52. package/dist/integrations/gitlab/default-rules.js.map +1 -0
  53. package/dist/integrations/gitlab/integration.d.ts +138 -0
  54. package/dist/integrations/gitlab/integration.d.ts.map +1 -0
  55. package/dist/integrations/gitlab/integration.js +705 -0
  56. package/dist/integrations/gitlab/integration.js.map +1 -0
  57. package/dist/integrations/gitlab/issue-reconciler.d.ts +6 -0
  58. package/dist/integrations/gitlab/issue-reconciler.d.ts.map +1 -0
  59. package/dist/integrations/gitlab/issue-reconciler.js +123 -0
  60. package/dist/integrations/gitlab/issue-reconciler.js.map +1 -0
  61. package/dist/integrations/gitlab/merge-request-reconciler.d.ts +6 -0
  62. package/dist/integrations/gitlab/merge-request-reconciler.d.ts.map +1 -0
  63. package/dist/integrations/gitlab/merge-request-reconciler.js +267 -0
  64. package/dist/integrations/gitlab/merge-request-reconciler.js.map +1 -0
  65. package/dist/integrations/gitlab/reconciler.d.ts +5 -0
  66. package/dist/integrations/gitlab/reconciler.d.ts.map +1 -0
  67. package/dist/integrations/gitlab/reconciler.js +31 -0
  68. package/dist/integrations/gitlab/reconciler.js.map +1 -0
  69. package/dist/integrations/gitlab/reconciliation-config.d.ts +3 -0
  70. package/dist/integrations/gitlab/reconciliation-config.d.ts.map +1 -0
  71. package/dist/integrations/gitlab/reconciliation-config.js +17 -0
  72. package/dist/integrations/gitlab/reconciliation-config.js.map +1 -0
  73. package/dist/integrations/gitlab/routes.d.ts +20 -0
  74. package/dist/integrations/gitlab/routes.d.ts.map +1 -0
  75. package/dist/integrations/gitlab/routes.js +473 -0
  76. package/dist/integrations/gitlab/routes.js.map +1 -0
  77. package/dist/integrations/gitlab/rules.d.ts +35 -0
  78. package/dist/integrations/gitlab/rules.d.ts.map +1 -0
  79. package/dist/integrations/gitlab/rules.js +391 -0
  80. package/dist/integrations/gitlab/rules.js.map +1 -0
  81. package/dist/integrations/gitlab/session-subscriptions.d.ts +32 -0
  82. package/dist/integrations/gitlab/session-subscriptions.d.ts.map +1 -0
  83. package/dist/integrations/gitlab/session-subscriptions.js +192 -0
  84. package/dist/integrations/gitlab/session-subscriptions.js.map +1 -0
  85. package/dist/integrations/gitlab/subscriptions.d.ts +70 -0
  86. package/dist/integrations/gitlab/subscriptions.d.ts.map +1 -0
  87. package/dist/integrations/gitlab/subscriptions.js +76 -0
  88. package/dist/integrations/gitlab/subscriptions.js.map +1 -0
  89. package/dist/integrations/gitlab/version-control.d.ts +16 -0
  90. package/dist/integrations/gitlab/version-control.d.ts.map +1 -0
  91. package/dist/integrations/gitlab/version-control.js +622 -0
  92. package/dist/integrations/gitlab/version-control.js.map +1 -0
  93. package/dist/integrations/gitlab/webhook-dispatch.d.ts +75 -0
  94. package/dist/integrations/gitlab/webhook-dispatch.d.ts.map +1 -0
  95. package/dist/integrations/gitlab/webhook-dispatch.js +235 -0
  96. package/dist/integrations/gitlab/webhook-dispatch.js.map +1 -0
  97. package/dist/integrations/gitlab/webhook.d.ts +72 -0
  98. package/dist/integrations/gitlab/webhook.d.ts.map +1 -0
  99. package/dist/integrations/gitlab/webhook.js +201 -0
  100. package/dist/integrations/gitlab/webhook.js.map +1 -0
  101. package/dist/integrations/incidentio/agent-tools.d.ts +49 -0
  102. package/dist/integrations/incidentio/agent-tools.d.ts.map +1 -0
  103. package/dist/integrations/incidentio/agent-tools.js +90 -0
  104. package/dist/integrations/incidentio/agent-tools.js.map +1 -0
  105. package/dist/integrations/incidentio/claim.d.ts +8 -0
  106. package/dist/integrations/incidentio/claim.d.ts.map +1 -0
  107. package/dist/integrations/incidentio/claim.js +14 -0
  108. package/dist/integrations/incidentio/claim.js.map +1 -0
  109. package/dist/integrations/incidentio/default-rules.d.ts +46 -0
  110. package/dist/integrations/incidentio/default-rules.d.ts.map +1 -0
  111. package/dist/integrations/incidentio/default-rules.js +66 -0
  112. package/dist/integrations/incidentio/default-rules.js.map +1 -0
  113. package/dist/integrations/incidentio/integration.d.ts +48 -2
  114. package/dist/integrations/incidentio/integration.d.ts.map +1 -1
  115. package/dist/integrations/incidentio/integration.js +89 -3
  116. package/dist/integrations/incidentio/integration.js.map +1 -1
  117. package/dist/integrations/incidentio/issue-reconciler.d.ts +2 -0
  118. package/dist/integrations/incidentio/issue-reconciler.d.ts.map +1 -1
  119. package/dist/integrations/incidentio/issue-reconciler.js +38 -2
  120. package/dist/integrations/incidentio/issue-reconciler.js.map +1 -1
  121. package/dist/integrations/incidentio/routes.d.ts +71 -0
  122. package/dist/integrations/incidentio/routes.d.ts.map +1 -0
  123. package/dist/integrations/incidentio/routes.js +245 -0
  124. package/dist/integrations/incidentio/routes.js.map +1 -0
  125. package/dist/integrations/incidentio/rules.d.ts +55 -0
  126. package/dist/integrations/incidentio/rules.d.ts.map +1 -0
  127. package/dist/integrations/incidentio/rules.js +175 -0
  128. package/dist/integrations/incidentio/rules.js.map +1 -0
  129. package/dist/integrations/issue-reconciler.d.ts +3 -3
  130. package/dist/integrations/issue-reconciler.d.ts.map +1 -1
  131. package/dist/integrations/issue-reconciler.js +22 -2
  132. package/dist/integrations/issue-reconciler.js.map +1 -1
  133. package/dist/integrations/jira/adf.d.ts +26 -0
  134. package/dist/integrations/jira/adf.d.ts.map +1 -0
  135. package/dist/integrations/jira/adf.js +73 -0
  136. package/dist/integrations/jira/adf.js.map +1 -0
  137. package/dist/integrations/jira/agent-tools.d.ts +45 -0
  138. package/dist/integrations/jira/agent-tools.d.ts.map +1 -0
  139. package/dist/integrations/jira/agent-tools.js +87 -0
  140. package/dist/integrations/jira/agent-tools.js.map +1 -0
  141. package/dist/integrations/jira/api.d.ts +157 -0
  142. package/dist/integrations/jira/api.d.ts.map +1 -0
  143. package/dist/integrations/jira/api.js +141 -0
  144. package/dist/integrations/jira/api.js.map +1 -0
  145. package/dist/integrations/jira/claim.d.ts +9 -0
  146. package/dist/integrations/jira/claim.d.ts.map +1 -0
  147. package/dist/integrations/jira/claim.js +15 -0
  148. package/dist/integrations/jira/claim.js.map +1 -0
  149. package/dist/integrations/jira/default-rules.d.ts +47 -0
  150. package/dist/integrations/jira/default-rules.d.ts.map +1 -0
  151. package/dist/integrations/jira/default-rules.js +67 -0
  152. package/dist/integrations/jira/default-rules.js.map +1 -0
  153. package/dist/integrations/jira/integration.d.ts +114 -0
  154. package/dist/integrations/jira/integration.d.ts.map +1 -0
  155. package/dist/integrations/jira/integration.js +401 -0
  156. package/dist/integrations/jira/integration.js.map +1 -0
  157. package/dist/integrations/jira/issue-reconciler.d.ts +10 -0
  158. package/dist/integrations/jira/issue-reconciler.d.ts.map +1 -0
  159. package/dist/integrations/jira/issue-reconciler.js +70 -0
  160. package/dist/integrations/jira/issue-reconciler.js.map +1 -0
  161. package/dist/integrations/jira/reconciliation-config.d.ts +3 -0
  162. package/dist/integrations/jira/reconciliation-config.d.ts.map +1 -0
  163. package/dist/integrations/jira/reconciliation-config.js +17 -0
  164. package/dist/integrations/jira/reconciliation-config.js.map +1 -0
  165. package/dist/integrations/jira/routes.d.ts +54 -0
  166. package/dist/integrations/jira/routes.d.ts.map +1 -0
  167. package/dist/integrations/jira/routes.js +260 -0
  168. package/dist/integrations/jira/routes.js.map +1 -0
  169. package/dist/integrations/jira/rules.d.ts +57 -0
  170. package/dist/integrations/jira/rules.d.ts.map +1 -0
  171. package/dist/integrations/jira/rules.js +175 -0
  172. package/dist/integrations/jira/rules.js.map +1 -0
  173. package/dist/integrations/linear/claim.d.ts +8 -0
  174. package/dist/integrations/linear/claim.d.ts.map +1 -0
  175. package/dist/integrations/linear/claim.js +14 -0
  176. package/dist/integrations/linear/claim.js.map +1 -0
  177. package/dist/integrations/linear/default-rules.d.ts +1 -0
  178. package/dist/integrations/linear/default-rules.d.ts.map +1 -1
  179. package/dist/integrations/linear/default-rules.js +2 -0
  180. package/dist/integrations/linear/default-rules.js.map +1 -1
  181. package/dist/integrations/linear/integration.d.ts +24 -6
  182. package/dist/integrations/linear/integration.d.ts.map +1 -1
  183. package/dist/integrations/linear/integration.js +257 -37
  184. package/dist/integrations/linear/integration.js.map +1 -1
  185. package/dist/integrations/linear/routes.d.ts +10 -0
  186. package/dist/integrations/linear/routes.d.ts.map +1 -1
  187. package/dist/integrations/linear/routes.js +74 -10
  188. package/dist/integrations/linear/routes.js.map +1 -1
  189. package/dist/integrations/linear/rules.d.ts +1 -1
  190. package/dist/integrations/linear/rules.d.ts.map +1 -1
  191. package/dist/integrations/linear/rules.js +27 -2
  192. package/dist/integrations/linear/rules.js.map +1 -1
  193. package/dist/integrations/platform/connect/routes.d.ts +39 -0
  194. package/dist/integrations/platform/connect/routes.d.ts.map +1 -0
  195. package/dist/integrations/platform/connect/routes.js +129 -0
  196. package/dist/integrations/platform/connect/routes.js.map +1 -0
  197. package/dist/integrations/platform/github/event-worker.js +1 -1
  198. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  199. package/dist/integrations/platform/github/integration.js +22 -1
  200. package/dist/integrations/platform/github/integration.js.map +1 -1
  201. package/dist/integrations/platform/gitlab/event-worker.d.ts +64 -0
  202. package/dist/integrations/platform/gitlab/event-worker.d.ts.map +1 -0
  203. package/dist/integrations/platform/gitlab/event-worker.js +306 -0
  204. package/dist/integrations/platform/gitlab/event-worker.js.map +1 -0
  205. package/dist/integrations/platform/gitlab/integration.d.ts +57 -0
  206. package/dist/integrations/platform/gitlab/integration.d.ts.map +1 -0
  207. package/dist/integrations/platform/gitlab/integration.js +125 -0
  208. package/dist/integrations/platform/gitlab/integration.js.map +1 -0
  209. package/dist/integrations/platform/incidentio/integration.d.ts +61 -4
  210. package/dist/integrations/platform/incidentio/integration.d.ts.map +1 -1
  211. package/dist/integrations/platform/incidentio/integration.js +372 -23
  212. package/dist/integrations/platform/incidentio/integration.js.map +1 -1
  213. package/dist/integrations/platform/jira/agent-tools.d.ts +36 -0
  214. package/dist/integrations/platform/jira/agent-tools.d.ts.map +1 -0
  215. package/dist/integrations/platform/jira/agent-tools.js +85 -0
  216. package/dist/integrations/platform/jira/agent-tools.js.map +1 -0
  217. package/dist/integrations/platform/jira/integration.d.ts +65 -0
  218. package/dist/integrations/platform/jira/integration.d.ts.map +1 -0
  219. package/dist/integrations/platform/jira/integration.js +540 -0
  220. package/dist/integrations/platform/jira/integration.js.map +1 -0
  221. package/dist/integrations/platform/jira/routes.d.ts +55 -0
  222. package/dist/integrations/platform/jira/routes.d.ts.map +1 -0
  223. package/dist/integrations/platform/jira/routes.js +274 -0
  224. package/dist/integrations/platform/jira/routes.js.map +1 -0
  225. package/dist/integrations/platform/linear/integration.d.ts +34 -1
  226. package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
  227. package/dist/integrations/platform/linear/integration.js +271 -48
  228. package/dist/integrations/platform/linear/integration.js.map +1 -1
  229. package/dist/integrations/slack/integration.d.ts.map +1 -1
  230. package/dist/integrations/slack/integration.js +3 -3
  231. package/dist/integrations/slack/integration.js.map +1 -1
  232. package/dist/integrations/slack/slack.d.ts +2 -0
  233. package/dist/integrations/slack/slack.d.ts.map +1 -1
  234. package/dist/integrations/slack/slack.js +21 -7
  235. package/dist/integrations/slack/slack.js.map +1 -1
  236. package/dist/integrations/subscription-session.d.ts +37 -0
  237. package/dist/integrations/subscription-session.d.ts.map +1 -0
  238. package/dist/integrations/subscription-session.js +83 -0
  239. package/dist/integrations/subscription-session.js.map +1 -0
  240. package/dist/packages/_internals/workspace/dist/index.js +1 -11
  241. package/dist/packages/_internals/workspace/dist/index.js.map +1 -1
  242. package/dist/routes/intake.d.ts.map +1 -1
  243. package/dist/routes/intake.js +16 -4
  244. package/dist/routes/intake.js.map +1 -1
  245. package/dist/routes/oauth.js +3 -6
  246. package/dist/routes/oauth.js.map +1 -1
  247. package/dist/routes/projects.d.ts +1 -0
  248. package/dist/routes/projects.d.ts.map +1 -1
  249. package/dist/routes/projects.js +1 -0
  250. package/dist/routes/projects.js.map +1 -1
  251. package/dist/routes/source-control-sessions.d.ts +20 -0
  252. package/dist/routes/source-control-sessions.d.ts.map +1 -0
  253. package/dist/routes/source-control-sessions.js +319 -0
  254. package/dist/routes/source-control-sessions.js.map +1 -0
  255. package/dist/routes/source-control-settings.d.ts +10 -0
  256. package/dist/routes/source-control-settings.d.ts.map +1 -0
  257. package/dist/routes/source-control-settings.js +87 -0
  258. package/dist/routes/source-control-settings.js.map +1 -0
  259. package/dist/routes/surface.d.ts +3 -3
  260. package/dist/routes/surface.d.ts.map +1 -1
  261. package/dist/routes/surface.js +79 -17
  262. package/dist/routes/surface.js.map +1 -1
  263. package/dist/routes/tenant-credentials.d.ts +8 -0
  264. package/dist/routes/tenant-credentials.d.ts.map +1 -1
  265. package/dist/routes/tenant-credentials.js +20 -3
  266. package/dist/routes/tenant-credentials.js.map +1 -1
  267. package/dist/routes/work-items.d.ts.map +1 -1
  268. package/dist/routes/work-items.js +1 -1
  269. package/dist/routes/work-items.js.map +1 -1
  270. package/dist/rules/dispatch-errors.d.ts.map +1 -1
  271. package/dist/rules/dispatch-errors.js +8 -0
  272. package/dist/rules/dispatch-errors.js.map +1 -1
  273. package/dist/rules/dispatcher.d.ts +1 -0
  274. package/dist/rules/dispatcher.d.ts.map +1 -1
  275. package/dist/rules/dispatcher.js +186 -106
  276. package/dist/rules/dispatcher.js.map +1 -1
  277. package/dist/rules/index.d.ts +2 -2
  278. package/dist/rules/index.d.ts.map +1 -1
  279. package/dist/rules/index.js +2 -2
  280. package/dist/rules/start-coordinator.d.ts +1 -1
  281. package/dist/rules/start-coordinator.d.ts.map +1 -1
  282. package/dist/rules/start-coordinator.js +7 -3
  283. package/dist/rules/start-coordinator.js.map +1 -1
  284. package/dist/rules/terminal-cleanup.d.ts +14 -1
  285. package/dist/rules/terminal-cleanup.d.ts.map +1 -1
  286. package/dist/rules/terminal-cleanup.js +20 -0
  287. package/dist/rules/terminal-cleanup.js.map +1 -1
  288. package/dist/rules/tools.d.ts +2 -0
  289. package/dist/rules/tools.d.ts.map +1 -1
  290. package/dist/rules/tools.js +30 -2
  291. package/dist/rules/tools.js.map +1 -1
  292. package/dist/rules/transition-service.d.ts +3 -0
  293. package/dist/rules/transition-service.d.ts.map +1 -1
  294. package/dist/rules/transition-service.js +10 -5
  295. package/dist/rules/transition-service.js.map +1 -1
  296. package/dist/rules/types.d.ts +136 -3
  297. package/dist/rules/types.d.ts.map +1 -1
  298. package/dist/rules/types.js +31 -2
  299. package/dist/rules/types.js.map +1 -1
  300. package/dist/rules/validation.d.ts.map +1 -1
  301. package/dist/rules/validation.js +15 -2
  302. package/dist/rules/validation.js.map +1 -1
  303. package/dist/sandbox/git-ref.d.ts +7 -0
  304. package/dist/sandbox/git-ref.d.ts.map +1 -0
  305. package/dist/sandbox/git-ref.js +15 -0
  306. package/dist/sandbox/git-ref.js.map +1 -0
  307. package/dist/sandbox/session-retirement.js +1 -1
  308. package/dist/sandbox/workdir.d.ts.map +1 -1
  309. package/dist/sandbox/workdir.js +6 -6
  310. package/dist/sandbox/workdir.js.map +1 -1
  311. package/dist/session/factory-session.d.ts +31 -1
  312. package/dist/session/factory-session.d.ts.map +1 -1
  313. package/dist/session/factory-session.js +60 -1
  314. package/dist/session/factory-session.js.map +1 -1
  315. package/dist/session/run-audit.d.ts +9 -0
  316. package/dist/session/run-audit.d.ts.map +1 -1
  317. package/dist/session/run-audit.js +37 -6
  318. package/dist/session/run-audit.js.map +1 -1
  319. package/dist/session/source-control-tools.d.ts +16 -0
  320. package/dist/session/source-control-tools.d.ts.map +1 -0
  321. package/dist/session/source-control-tools.js +464 -0
  322. package/dist/session/source-control-tools.js.map +1 -0
  323. package/dist/skills/service.d.ts +12 -0
  324. package/dist/skills/service.d.ts.map +1 -1
  325. package/dist/skills/service.js +27 -1
  326. package/dist/skills/service.js.map +1 -1
  327. package/dist/storage/domains/intake/base.d.ts +18 -0
  328. package/dist/storage/domains/intake/base.d.ts.map +1 -1
  329. package/dist/storage/domains/intake/base.js +77 -0
  330. package/dist/storage/domains/intake/base.js.map +1 -1
  331. package/dist/storage/domains/work-items/base.d.ts +41 -2
  332. package/dist/storage/domains/work-items/base.d.ts.map +1 -1
  333. package/dist/storage/domains/work-items/base.js +159 -12
  334. package/dist/storage/domains/work-items/base.js.map +1 -1
  335. package/dist/supervisor/session-messaging.d.ts +23 -0
  336. package/dist/supervisor/session-messaging.d.ts.map +1 -0
  337. package/dist/supervisor/session-messaging.js +15 -0
  338. package/dist/supervisor/session-messaging.js.map +1 -0
  339. package/dist/supervisor/write-tools.d.ts +2 -1
  340. package/dist/supervisor/write-tools.d.ts.map +1 -1
  341. package/dist/supervisor/write-tools.js +11 -7
  342. package/dist/supervisor/write-tools.js.map +1 -1
  343. package/dist/work-item-branch.d.ts +3 -1
  344. package/dist/work-item-branch.d.ts.map +1 -1
  345. package/dist/work-item-branch.js +26 -6
  346. package/dist/work-item-branch.js.map +1 -1
  347. package/dist/workspace.d.ts +15 -1
  348. package/dist/workspace.d.ts.map +1 -1
  349. package/dist/workspace.js +57 -23
  350. package/dist/workspace.js.map +1 -1
  351. package/factory-skills/factory-gitlab-rereview/SKILL.md +19 -0
  352. package/factory-skills/factory-gitlab-review/SKILL.md +30 -0
  353. package/factory-skills/factory-rereview/SKILL.md +13 -6
  354. package/factory-skills/factory-review/SKILL.md +13 -6
  355. package/factory-skills/factory-review/references/archaeology.md +225 -0
  356. package/factory-skills/factory-review/references/categories/README.md +34 -0
  357. package/factory-skills/factory-review/references/categories/behavior-change.md +36 -0
  358. package/factory-skills/factory-review/references/categories/bug-fix.md +37 -0
  359. package/factory-skills/factory-review/references/categories/docs.md +32 -0
  360. package/factory-skills/factory-review/references/categories/experimental-flagged.md +34 -0
  361. package/factory-skills/factory-review/references/categories/infra-tooling.md +37 -0
  362. package/factory-skills/factory-review/references/categories/internal-capability.md +35 -0
  363. package/factory-skills/factory-review/references/categories/large-cross-cutting.md +35 -0
  364. package/factory-skills/factory-review/references/categories/mechanical.md +36 -0
  365. package/factory-skills/factory-review/references/categories/performance.md +33 -0
  366. package/factory-skills/factory-review/references/categories/public-api.md +38 -0
  367. package/factory-skills/factory-review/references/categories/refactor.md +35 -0
  368. package/factory-skills/factory-review/references/categories/revert.md +31 -0
  369. package/factory-skills/factory-review/references/categories/schema-storage.md +39 -0
  370. package/factory-skills/factory-review/references/categories/security.md +35 -0
  371. package/factory-skills/factory-review/references/categories/tests-only.md +38 -0
  372. package/package.json +12 -12
@@ -0,0 +1,23 @@
1
+ import type { RequestContext } from '@mastra/core/request-context';
2
+ type WorkerSession = {
3
+ sendMessage(input: {
4
+ content: string;
5
+ requestContext?: RequestContext;
6
+ }): Promise<unknown>;
7
+ queueMessage(input: {
8
+ content: string;
9
+ requestContext?: RequestContext;
10
+ }): Promise<unknown>;
11
+ };
12
+ type WorkerSessionController = {
13
+ getSessionByResource(sessionId: string): Promise<WorkerSession | undefined>;
14
+ };
15
+ export declare function messageWorkerSession({ controller, sessionId, message, delivery, requestContext, }: {
16
+ controller: WorkerSessionController;
17
+ sessionId: string;
18
+ message: string;
19
+ delivery: 'send' | 'queue';
20
+ requestContext?: RequestContext;
21
+ }): Promise<void>;
22
+ export {};
23
+ //# sourceMappingURL=session-messaging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-messaging.d.ts","sourceRoot":"","sources":["../../src/supervisor/session-messaging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE,KAAK,aAAa,GAAG;IACnB,WAAW,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3F,YAAY,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7F,CAAC;AAEF,KAAK,uBAAuB,GAAG;IAC7B,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;CAC7E,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,EACzC,UAAU,EACV,SAAS,EACT,OAAO,EACP,QAAQ,EACR,cAAc,GACf,EAAE;IACD,UAAU,EAAE,uBAAuB,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB"}
@@ -0,0 +1,15 @@
1
+ //#region src/supervisor/session-messaging.ts
2
+ async function messageWorkerSession({ controller, sessionId, message, delivery, requestContext }) {
3
+ const session = await controller.getSessionByResource(sessionId);
4
+ if (!session) throw new Error("The worker session is not currently available.");
5
+ const input = {
6
+ content: message,
7
+ ...requestContext ? { requestContext } : {}
8
+ };
9
+ if (delivery === "queue") await session.queueMessage(input);
10
+ else await session.sendMessage(input);
11
+ }
12
+ //#endregion
13
+ export { messageWorkerSession };
14
+
15
+ //# sourceMappingURL=session-messaging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-messaging.js","names":[],"sources":["../../src/supervisor/session-messaging.ts"],"sourcesContent":["import type { RequestContext } from '@mastra/core/request-context';\n\ntype WorkerSession = {\n sendMessage(input: { content: string; requestContext?: RequestContext }): Promise<unknown>;\n queueMessage(input: { content: string; requestContext?: RequestContext }): Promise<unknown>;\n};\n\ntype WorkerSessionController = {\n getSessionByResource(sessionId: string): Promise<WorkerSession | undefined>;\n};\n\nexport async function messageWorkerSession({\n controller,\n sessionId,\n message,\n delivery,\n requestContext,\n}: {\n controller: WorkerSessionController;\n sessionId: string;\n message: string;\n delivery: 'send' | 'queue';\n requestContext?: RequestContext;\n}): Promise<void> {\n const session = await controller.getSessionByResource(sessionId);\n if (!session) throw new Error('The worker session is not currently available.');\n\n const input = { content: message, ...(requestContext ? { requestContext } : {}) };\n if (delivery === 'queue') {\n await session.queueMessage(input);\n } else {\n await session.sendMessage(input);\n }\n}\n"],"mappings":";AAWA,eAAsB,qBAAqB,EACzC,YACA,WACA,SACA,UACA,kBAOgB;CAChB,MAAM,UAAU,MAAM,WAAW,qBAAqB,SAAS;CAC/D,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,gDAAgD;CAE9E,MAAM,QAAQ;EAAE,SAAS;EAAS,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;CAAG;CAChF,IAAI,aAAa,SACf,MAAM,QAAQ,aAAa,KAAK;MAEhC,MAAM,QAAQ,YAAY,KAAK;AAEnC"}
@@ -14,10 +14,11 @@ interface SupervisorWriteDependencies {
14
14
  factoryProjectId: string;
15
15
  item: WorkItemRow;
16
16
  }) => Promise<void>;
17
- signalSession?: (input: {
17
+ messageSession?: (input: {
18
18
  sessionId: string;
19
19
  message: string;
20
20
  userId: string;
21
+ delivery: 'send' | 'queue';
21
22
  }) => Promise<unknown>;
22
23
  now?: () => Date;
23
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"write-tools.d.ts","sourceRoot":"","sources":["../../src/supervisor/write-tools.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAG/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,UAAU,2BAA2B;IACnC,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,iBAAiB,EAAE,wBAAwB,CAAC;IAC5C,yBAAyB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACpG,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,2BAA2B,GAAG,gBAAgB,CA4LrG"}
1
+ {"version":3,"file":"write-tools.d.ts","sourceRoot":"","sources":["../../src/supervisor/write-tools.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAG/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,UAAU,2BAA2B;IACnC,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,iBAAiB,EAAE,wBAAwB,CAAC;IAC5C,yBAAyB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QACvB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;KAC5B,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,2BAA2B,GAAG,gBAAgB,CAkMrG"}
@@ -175,31 +175,35 @@ function createFactorySupervisorWriteTools(deps) {
175
175
  }),
176
176
  factory_signal_session: createTool({
177
177
  id: "factory_signal_session",
178
- description: "Send bounded guidance to a worker session after the person confirms the exact message.",
178
+ description: "Send bounded guidance to a worker session after the person confirms the exact message. Use queue only when the guidance should wait for the current run to finish.",
179
179
  inputSchema: z.object({
180
180
  sessionId: z.string().min(1),
181
- message: z.string().trim().min(1).max(2e3)
181
+ message: z.string().trim().min(1).max(2e3),
182
+ delivery: z.enum(["send", "queue"]).default("send")
182
183
  }),
183
184
  requireApproval: true,
184
- execute: async ({ sessionId, message }) => {
185
- if (!deps.signalSession) throw new Error("Worker session signaling is unavailable.");
185
+ execute: async ({ sessionId, message, delivery }) => {
186
+ if (!deps.messageSession) throw new Error("Worker session messaging is unavailable.");
186
187
  const binding = (await deps.workItems.listRunBindings(deps.scope.orgId, deps.scope.factoryProjectId)).find((row) => row.sessionId === sessionId);
187
188
  if (!binding) throw new Error("The session does not belong to this factory.");
188
- await deps.signalSession({
189
+ await deps.messageSession({
189
190
  sessionId,
190
191
  message,
191
- userId: deps.userId
192
+ userId: deps.userId,
193
+ delivery
192
194
  });
193
195
  await audit("factory.agent.signaled", {
194
196
  type: "factory_session",
195
197
  id: sessionId
196
198
  }, {
197
199
  workItemId: binding.workItemId,
198
- role: binding.role
200
+ role: binding.role,
201
+ delivery
199
202
  });
200
203
  return {
201
204
  sessionId,
202
205
  delivered: true,
206
+ delivery,
203
207
  workItemId: binding.workItemId,
204
208
  role: binding.role
205
209
  };
@@ -1 +1 @@
1
- {"version":3,"file":"write-tools.js","names":[],"sources":["../../src/supervisor/write-tools.ts"],"sourcesContent":["import { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { IntegrationTools } from '../integrations/base.js';\nimport type { FactoryTransitionService } from '../rules/transition-service.js';\nimport { BOARD_IDENTIFIER_RE, MAX_BOARD_IDENTIFIER_LENGTH } from '../rules/validation.js';\nimport type { AuditAction } from '../storage/domains/audit/actions.js';\nimport type { AuditRecorder } from '../storage/domains/audit/domain.js';\nimport type { WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport type { SupervisorScope } from './read-tools.js';\n\ninterface SupervisorWriteDependencies {\n scope: SupervisorScope;\n userId: string;\n workItems: WorkItemsStorage;\n audit: AuditRecorder;\n transitionService: FactoryTransitionService;\n reconcileAcceptanceLabels?: (input: { orgId: string; factoryProjectId: string; item: WorkItemRow }) => Promise<void>;\n signalSession?: (input: { sessionId: string; message: string; userId: string }) => Promise<unknown>;\n now?: () => Date;\n}\n\nexport function createFactorySupervisorWriteTools(deps: SupervisorWriteDependencies): IntegrationTools {\n const now = deps.now ?? (() => new Date());\n const audit = async (\n action: AuditAction,\n target: { type: string; id: string },\n metadata: Record<string, unknown> = {},\n ) =>\n deps.audit.record({\n orgId: deps.scope.orgId,\n actorId: deps.userId,\n actorType: 'human',\n action,\n targets: [target],\n factoryProjectId: deps.scope.factoryProjectId,\n metadata: { ...metadata, cause: 'supervisor' },\n occurredAt: now(),\n });\n\n return {\n factory_retry_decision: createTool({\n id: 'factory_retry_decision',\n description: 'Retry one failed Factory decision after the person confirms the repair.',\n inputSchema: z.object({ decisionId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ decisionId }) => {\n const decision = await deps.workItems.retryDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision) throw new Error('The decision is not failed, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.run.retry',\n { type: 'rule_decision', id: decisionId },\n { workItemId: decision.workItemId },\n );\n return { decisionId, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_dismiss_decision: createTool({\n id: 'factory_dismiss_decision',\n description: 'Dismiss one parked Factory proposal after the person confirms it is no longer wanted.',\n inputSchema: z.object({ decisionId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ decisionId }) => {\n const decision = await deps.workItems.dismissDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision)\n throw new Error('The decision is not proposed, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.run.dismissed',\n { type: 'rule_decision', id: decisionId },\n { workItemId: decision.workItemId },\n );\n return { decisionId, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_resolve_proposal: createTool({\n id: 'factory_resolve_proposal',\n description: 'Approve or dismiss one proposed Factory decision after the person confirms the choice.',\n inputSchema: z.object({ decisionId: z.string().min(1), resolution: z.enum(['approve', 'dismiss']) }),\n requireApproval: true,\n execute: async ({ decisionId, resolution }) => {\n const decision =\n resolution === 'approve'\n ? await deps.workItems.approveDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n deps.userId,\n )\n : await deps.workItems.dismissDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision) throw new Error('The proposal is no longer open or belongs to another factory.');\n await audit(\n resolution === 'approve' ? 'factory.run.approved' : 'factory.run.dismissed',\n {\n type: 'rule_decision',\n id: decisionId,\n },\n { workItemId: decision.workItemId },\n );\n return { decisionId, resolution, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_transition_work_item: createTool({\n id: 'factory_transition_work_item',\n description: 'Move or accept one Factory work item after the person confirms the destination stage.',\n inputSchema: z.object({\n workItemId: z.string().min(1),\n stage: z.string().max(MAX_BOARD_IDENTIFIER_LENGTH).regex(BOARD_IDENTIFIER_RE),\n }),\n requireApproval: true,\n execute: async ({ workItemId, stage }) => {\n const item = await deps.workItems.get({ orgId: deps.scope.orgId, id: workItemId });\n if (!item || item.factoryProjectId !== deps.scope.factoryProjectId) throw new Error('Work item not found.');\n const from = item.stages.length === 1 ? item.stages[0] : undefined;\n if (!from) throw new Error('The work item does not have one valid Factory stage.');\n const result = await deps.transitionService.transition({\n orgId: deps.scope.orgId,\n factoryProjectId: deps.scope.factoryProjectId,\n workItemId,\n board: boardForWorkItem(item),\n stage,\n expectedRevision: item.revision,\n actor: { type: 'human', id: deps.userId },\n ingress: { type: 'human', identity: `supervisor:${deps.userId}:${workItemId}:${item.revision}:${stage}` },\n cause: 'supervisor',\n });\n if (result.status !== 'accepted') {\n throw new Error(`The transition was rejected (${result.code}): ${result.reason}`);\n }\n return result;\n },\n }),\n factory_reconcile_labels: createTool({\n id: 'factory_reconcile_labels',\n description: 'Reconcile stale acceptance labels for one accepted work item after the person confirms the repair.',\n inputSchema: z.object({ workItemId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ workItemId }) => {\n if (!deps.reconcileAcceptanceLabels) throw new Error('Acceptance-label reconciliation is unavailable.');\n const item = await deps.workItems.get({ orgId: deps.scope.orgId, id: workItemId });\n if (!item || item.factoryProjectId !== deps.scope.factoryProjectId) throw new Error('Work item not found.');\n if (!item.acceptedAt) throw new Error('The work item has not been accepted.');\n await deps.reconcileAcceptanceLabels({ ...deps.scope, item });\n await audit('factory.work_item.labels_reconciled', { type: 'work_item', id: workItemId });\n return { workItemId, reconciled: true };\n },\n }),\n factory_revoke_binding: createTool({\n id: 'factory_revoke_binding',\n description: 'Revoke an orphaned or stale run binding after a health finding and person confirmation.',\n inputSchema: z.object({ bindingId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ bindingId }) => {\n const binding = await deps.workItems.revokeRunBinding({\n orgId: deps.scope.orgId,\n factoryProjectId: deps.scope.factoryProjectId,\n bindingId,\n revokedAt: now(),\n });\n if (!binding) throw new Error('The binding is not active, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.intake.binding_updated',\n { type: 'run_binding', id: bindingId },\n {\n workItemId: binding.workItemId,\n role: binding.role,\n status: 'revoked',\n },\n );\n return { bindingId, status: binding.status, workItemId: binding.workItemId, role: binding.role };\n },\n }),\n factory_signal_session: createTool({\n id: 'factory_signal_session',\n description: 'Send bounded guidance to a worker session after the person confirms the exact message.',\n inputSchema: z.object({ sessionId: z.string().min(1), message: z.string().trim().min(1).max(2000) }),\n requireApproval: true,\n execute: async ({ sessionId, message }) => {\n if (!deps.signalSession) throw new Error('Worker session signaling is unavailable.');\n const bindings = await deps.workItems.listRunBindings(deps.scope.orgId, deps.scope.factoryProjectId);\n const binding = bindings.find(row => row.sessionId === sessionId);\n if (!binding) throw new Error('The session does not belong to this factory.');\n await deps.signalSession({ sessionId, message, userId: deps.userId });\n await audit(\n 'factory.agent.signaled',\n { type: 'factory_session', id: sessionId },\n {\n workItemId: binding.workItemId,\n role: binding.role,\n },\n );\n return { sessionId, delivered: true, workItemId: binding.workItemId, role: binding.role };\n },\n }),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"write-tools.js","names":[],"sources":["../../src/supervisor/write-tools.ts"],"sourcesContent":["import { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { IntegrationTools } from '../integrations/base.js';\nimport type { FactoryTransitionService } from '../rules/transition-service.js';\nimport { BOARD_IDENTIFIER_RE, MAX_BOARD_IDENTIFIER_LENGTH } from '../rules/validation.js';\nimport type { AuditAction } from '../storage/domains/audit/actions.js';\nimport type { AuditRecorder } from '../storage/domains/audit/domain.js';\nimport type { WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport type { SupervisorScope } from './read-tools.js';\n\ninterface SupervisorWriteDependencies {\n scope: SupervisorScope;\n userId: string;\n workItems: WorkItemsStorage;\n audit: AuditRecorder;\n transitionService: FactoryTransitionService;\n reconcileAcceptanceLabels?: (input: { orgId: string; factoryProjectId: string; item: WorkItemRow }) => Promise<void>;\n messageSession?: (input: {\n sessionId: string;\n message: string;\n userId: string;\n delivery: 'send' | 'queue';\n }) => Promise<unknown>;\n now?: () => Date;\n}\n\nexport function createFactorySupervisorWriteTools(deps: SupervisorWriteDependencies): IntegrationTools {\n const now = deps.now ?? (() => new Date());\n const audit = async (\n action: AuditAction,\n target: { type: string; id: string },\n metadata: Record<string, unknown> = {},\n ) =>\n deps.audit.record({\n orgId: deps.scope.orgId,\n actorId: deps.userId,\n actorType: 'human',\n action,\n targets: [target],\n factoryProjectId: deps.scope.factoryProjectId,\n metadata: { ...metadata, cause: 'supervisor' },\n occurredAt: now(),\n });\n\n return {\n factory_retry_decision: createTool({\n id: 'factory_retry_decision',\n description: 'Retry one failed Factory decision after the person confirms the repair.',\n inputSchema: z.object({ decisionId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ decisionId }) => {\n const decision = await deps.workItems.retryDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision) throw new Error('The decision is not failed, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.run.retry',\n { type: 'rule_decision', id: decisionId },\n { workItemId: decision.workItemId },\n );\n return { decisionId, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_dismiss_decision: createTool({\n id: 'factory_dismiss_decision',\n description: 'Dismiss one parked Factory proposal after the person confirms it is no longer wanted.',\n inputSchema: z.object({ decisionId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ decisionId }) => {\n const decision = await deps.workItems.dismissDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision)\n throw new Error('The decision is not proposed, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.run.dismissed',\n { type: 'rule_decision', id: decisionId },\n { workItemId: decision.workItemId },\n );\n return { decisionId, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_resolve_proposal: createTool({\n id: 'factory_resolve_proposal',\n description: 'Approve or dismiss one proposed Factory decision after the person confirms the choice.',\n inputSchema: z.object({ decisionId: z.string().min(1), resolution: z.enum(['approve', 'dismiss']) }),\n requireApproval: true,\n execute: async ({ decisionId, resolution }) => {\n const decision =\n resolution === 'approve'\n ? await deps.workItems.approveDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n deps.userId,\n )\n : await deps.workItems.dismissDeferredDecision(\n deps.scope.orgId,\n deps.scope.factoryProjectId,\n decisionId,\n now(),\n );\n if (!decision) throw new Error('The proposal is no longer open or belongs to another factory.');\n await audit(\n resolution === 'approve' ? 'factory.run.approved' : 'factory.run.dismissed',\n {\n type: 'rule_decision',\n id: decisionId,\n },\n { workItemId: decision.workItemId },\n );\n return { decisionId, resolution, status: decision.status, workItemId: decision.workItemId };\n },\n }),\n factory_transition_work_item: createTool({\n id: 'factory_transition_work_item',\n description: 'Move or accept one Factory work item after the person confirms the destination stage.',\n inputSchema: z.object({\n workItemId: z.string().min(1),\n stage: z.string().max(MAX_BOARD_IDENTIFIER_LENGTH).regex(BOARD_IDENTIFIER_RE),\n }),\n requireApproval: true,\n execute: async ({ workItemId, stage }) => {\n const item = await deps.workItems.get({ orgId: deps.scope.orgId, id: workItemId });\n if (!item || item.factoryProjectId !== deps.scope.factoryProjectId) throw new Error('Work item not found.');\n const from = item.stages.length === 1 ? item.stages[0] : undefined;\n if (!from) throw new Error('The work item does not have one valid Factory stage.');\n const result = await deps.transitionService.transition({\n orgId: deps.scope.orgId,\n factoryProjectId: deps.scope.factoryProjectId,\n workItemId,\n board: boardForWorkItem(item),\n stage,\n expectedRevision: item.revision,\n actor: { type: 'human', id: deps.userId },\n ingress: { type: 'human', identity: `supervisor:${deps.userId}:${workItemId}:${item.revision}:${stage}` },\n cause: 'supervisor',\n });\n if (result.status !== 'accepted') {\n throw new Error(`The transition was rejected (${result.code}): ${result.reason}`);\n }\n return result;\n },\n }),\n factory_reconcile_labels: createTool({\n id: 'factory_reconcile_labels',\n description: 'Reconcile stale acceptance labels for one accepted work item after the person confirms the repair.',\n inputSchema: z.object({ workItemId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ workItemId }) => {\n if (!deps.reconcileAcceptanceLabels) throw new Error('Acceptance-label reconciliation is unavailable.');\n const item = await deps.workItems.get({ orgId: deps.scope.orgId, id: workItemId });\n if (!item || item.factoryProjectId !== deps.scope.factoryProjectId) throw new Error('Work item not found.');\n if (!item.acceptedAt) throw new Error('The work item has not been accepted.');\n await deps.reconcileAcceptanceLabels({ ...deps.scope, item });\n await audit('factory.work_item.labels_reconciled', { type: 'work_item', id: workItemId });\n return { workItemId, reconciled: true };\n },\n }),\n factory_revoke_binding: createTool({\n id: 'factory_revoke_binding',\n description: 'Revoke an orphaned or stale run binding after a health finding and person confirmation.',\n inputSchema: z.object({ bindingId: z.string().min(1) }),\n requireApproval: true,\n execute: async ({ bindingId }) => {\n const binding = await deps.workItems.revokeRunBinding({\n orgId: deps.scope.orgId,\n factoryProjectId: deps.scope.factoryProjectId,\n bindingId,\n revokedAt: now(),\n });\n if (!binding) throw new Error('The binding is not active, no longer exists, or belongs to another factory.');\n await audit(\n 'factory.intake.binding_updated',\n { type: 'run_binding', id: bindingId },\n {\n workItemId: binding.workItemId,\n role: binding.role,\n status: 'revoked',\n },\n );\n return { bindingId, status: binding.status, workItemId: binding.workItemId, role: binding.role };\n },\n }),\n factory_signal_session: createTool({\n id: 'factory_signal_session',\n description:\n 'Send bounded guidance to a worker session after the person confirms the exact message. Use queue only when the guidance should wait for the current run to finish.',\n inputSchema: z.object({\n sessionId: z.string().min(1),\n message: z.string().trim().min(1).max(2000),\n delivery: z.enum(['send', 'queue']).default('send'),\n }),\n requireApproval: true,\n execute: async ({ sessionId, message, delivery }) => {\n if (!deps.messageSession) throw new Error('Worker session messaging is unavailable.');\n const bindings = await deps.workItems.listRunBindings(deps.scope.orgId, deps.scope.factoryProjectId);\n const binding = bindings.find(row => row.sessionId === sessionId);\n if (!binding) throw new Error('The session does not belong to this factory.');\n await deps.messageSession({ sessionId, message, userId: deps.userId, delivery });\n await audit(\n 'factory.agent.signaled',\n { type: 'factory_session', id: sessionId },\n {\n workItemId: binding.workItemId,\n role: binding.role,\n delivery,\n },\n );\n return { sessionId, delivered: true, delivery, workItemId: binding.workItemId, role: binding.role };\n },\n }),\n };\n}\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ import type { ExternalWorkItemSource } from './storage/domains/work-items/base.j
4
4
  * map their `externalSource` into this with {@link workItemBranchSource}; the
5
5
  * board's own `WorkItem['source']` is already this union.
6
6
  */
7
- export type WorkItemBranchSource = 'github-issue' | 'github-pr' | 'linear-issue' | 'slack-thread' | 'manual';
7
+ export type WorkItemBranchSource = 'github-issue' | 'github-pr' | 'gitlab-issue' | 'gitlab-pr' | 'linear-issue' | 'jira-issue' | 'incidentio-follow-up' | 'slack-thread' | 'manual';
8
8
  export interface WorkItemBranchInput {
9
9
  id: string;
10
10
  source: WorkItemBranchSource;
@@ -28,4 +28,6 @@ export declare function workItemThreadTitle(item: Pick<WorkItemBranchInput, 'sou
28
28
  export declare function workItemBranch(item: WorkItemBranchInput): string;
29
29
  /** The pull request a `factory/pr-<number>` branch was named after, the inverse of {@link workItemBranch}. */
30
30
  export declare function pullRequestNumberFromBranch(branch: string): number | undefined;
31
+ /** The GitLab MR IID encoded in Factory's collision-resistant review branch. */
32
+ export declare function mergeRequestNumberFromBranch(branch: string): number | undefined;
31
33
  //# sourceMappingURL=work-item-branch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"work-item-branch.d.ts","sourceRoot":"","sources":["../src/work-item-branch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAEnF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,cAAc,GAAG,WAAW,GAAG,cAAc,GAAG,cAAc,GAAG,QAAQ,CAAC;AAE7G,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,oBAAoB,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3C;AAED,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,sBAAsB,GAAG,IAAI,GAAG,SAAS,GAAG,oBAAoB,CAOpH;AAOD,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,UAAU,CAAC,GAAG,MAAM,GAAG,SAAS,CAKzG;AAED,yHAAyH;AACzH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,UAAU,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACzE,MAAM,CAIR;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAWhE;AAED,8GAA8G;AAC9G,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG9E"}
1
+ {"version":3,"file":"work-item-branch.d.ts","sourceRoot":"","sources":["../src/work-item-branch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAEnF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAC5B,cAAc,GACd,WAAW,GACX,cAAc,GACd,WAAW,GACX,cAAc,GACd,YAAY,GACZ,sBAAsB,GACtB,cAAc,GACd,QAAQ,CAAC;AAEb,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,oBAAoB,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3C;AAED,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,sBAAsB,GAAG,IAAI,GAAG,SAAS,GAAG,oBAAoB,CAYpH;AAOD,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,UAAU,CAAC,GAAG,MAAM,GAAG,SAAS,CAOzG;AAED,yHAAyH;AACzH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,UAAU,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACzE,MAAM,CAKR;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAmChE;AAED,8GAA8G;AAC9G,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG9E;AAED,gFAAgF;AAChF,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI/E"}
@@ -3,6 +3,9 @@
3
3
  function workItemBranchSource(externalSource) {
4
4
  if (!externalSource) return "manual";
5
5
  if (externalSource.integrationId === "linear") return "linear-issue";
6
+ if (externalSource.integrationId === "gitlab") return externalSource.type === "pull-request" ? "gitlab-pr" : "gitlab-issue";
7
+ if (externalSource.integrationId === "jira") return "jira-issue";
8
+ if (externalSource.integrationId === "incidentio") return "incidentio-follow-up";
6
9
  if (externalSource.integrationId !== "github") return "manual";
7
10
  return externalSource.type === "pull-request" ? "github-pr" : "github-issue";
8
11
  }
@@ -15,12 +18,14 @@ function workItemNumber(item) {
15
18
  const metadata = item.metadata ?? {};
16
19
  if (item.source === "github-issue") return branchNumber(metadata, "githubIssueNumber");
17
20
  if (item.source === "github-pr") return branchNumber(metadata, "githubPullRequestNumber");
21
+ if (item.source === "gitlab-issue") return branchNumber(metadata, "gitlabIssueIid");
22
+ if (item.source === "gitlab-pr") return branchNumber(metadata, "gitlabMergeRequestIid");
18
23
  }
19
24
  /** How a card names its thread: a Linear title already opens with its identifier, a GitHub card gets its number here. */
20
25
  function workItemThreadTitle(item) {
21
26
  const number = workItemNumber(item);
22
27
  if (number === void 0) return item.title;
23
- return `${item.source === "github-pr" ? "PR" : "Issue"} #${number}: ${item.title}`;
28
+ return `${item.source === "github-pr" ? "PR" : item.source === "gitlab-pr" ? "MR" : "Issue"} #${number}: ${item.title}`;
24
29
  }
25
30
  /**
26
31
  * The git branch an item's runs and sessions share, one grammar for both sides
@@ -31,11 +36,20 @@ function workItemThreadTitle(item) {
31
36
  */
32
37
  function workItemBranch(item) {
33
38
  const metadata = item.metadata ?? {};
34
- const githubNumber = workItemNumber(item);
35
- if (githubNumber !== void 0) return item.source === "github-issue" ? `factory/issue-${githubNumber}` : `factory/pr-${githubNumber}`;
36
- if (item.source === "linear-issue" && typeof metadata.identifier === "string") {
39
+ const providerNumber = workItemNumber(item);
40
+ if (providerNumber !== void 0 && (item.source === "github-issue" || item.source === "github-pr")) return item.source === "github-issue" ? `factory/issue-${providerNumber}` : `factory/pr-${providerNumber}`;
41
+ if ((item.source === "linear-issue" || item.source === "jira-issue" || item.source === "incidentio-follow-up") && typeof metadata.identifier === "string") {
37
42
  const identifier = metadata.identifier.trim();
38
- if (identifier) return `factory/linear-${identifier.toLowerCase()}`;
43
+ if (identifier) return `factory/${item.source === "linear-issue" ? "linear" : item.source === "jira-issue" ? "jira" : "incidentio"}-${identifier.toLowerCase()}`;
44
+ }
45
+ if (item.source === "gitlab-pr" && providerNumber !== void 0) {
46
+ const uniqueSuffix = item.id.toLowerCase().replace(/[^a-z0-9]+/g, "").slice(-12);
47
+ if (uniqueSuffix) return `factory/gitlab-mr-${providerNumber}-${uniqueSuffix}`;
48
+ }
49
+ if (item.source === "gitlab-issue" && typeof metadata.identifier === "string") {
50
+ const identifier = metadata.identifier.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-");
51
+ const uniqueSuffix = item.id.toLowerCase().replace(/[^a-z0-9]+/g, "").slice(-12);
52
+ if (identifier && uniqueSuffix) return `factory/gitlab-${identifier.slice(0, 60)}-${uniqueSuffix}`;
39
53
  }
40
54
  return `factory/item-${item.id}`;
41
55
  }
@@ -44,7 +58,13 @@ function pullRequestNumberFromBranch(branch) {
44
58
  const match = /^factory\/pr-([1-9]\d*)$/.exec(branch);
45
59
  return match ? Number(match[1]) : void 0;
46
60
  }
61
+ /** The GitLab MR IID encoded in Factory's collision-resistant review branch. */
62
+ function mergeRequestNumberFromBranch(branch) {
63
+ const match = /^factory\/gitlab-mr-([1-9]\d*)-[a-z0-9]{1,12}$/.exec(branch);
64
+ const number = match ? Number(match[1]) : void 0;
65
+ return number !== void 0 && Number.isSafeInteger(number) ? number : void 0;
66
+ }
47
67
  //#endregion
48
- export { pullRequestNumberFromBranch, workItemBranch, workItemBranchSource, workItemNumber, workItemThreadTitle };
68
+ export { mergeRequestNumberFromBranch, pullRequestNumberFromBranch, workItemBranch, workItemBranchSource, workItemNumber, workItemThreadTitle };
49
69
 
50
70
  //# sourceMappingURL=work-item-branch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"work-item-branch.js","names":[],"sources":["../src/work-item-branch.ts"],"sourcesContent":["import type { ExternalWorkItemSource } from './storage/domains/work-items/base.js';\n\n/**\n * Where a card came from, in the vocabulary branch naming reads. Server rows\n * map their `externalSource` into this with {@link workItemBranchSource}; the\n * board's own `WorkItem['source']` is already this union.\n */\nexport type WorkItemBranchSource = 'github-issue' | 'github-pr' | 'linear-issue' | 'slack-thread' | 'manual';\n\nexport interface WorkItemBranchInput {\n id: string;\n source: WorkItemBranchSource;\n metadata?: Record<string, unknown> | null;\n}\n\n/** Map a stored item's provenance onto the source vocabulary branch naming reads. */\nexport function workItemBranchSource(externalSource: ExternalWorkItemSource | null | undefined): WorkItemBranchSource {\n if (!externalSource) return 'manual';\n if (externalSource.integrationId === 'linear') return 'linear-issue';\n // Only GitHub and Linear carry provider identities; anything else (a Slack\n // thread, say) is a plain work item rather than a mislabeled GitHub issue.\n if (externalSource.integrationId !== 'github') return 'manual';\n return externalSource.type === 'pull-request' ? 'github-pr' : 'github-issue';\n}\n\nfunction branchNumber(metadata: Record<string, unknown>, key: string): number | undefined {\n const value = metadata[key] ?? metadata.number;\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : undefined;\n}\n\n/** The provider number a GitHub card carries — the `#12` its runs and thread titles name it by. */\nexport function workItemNumber(item: Pick<WorkItemBranchInput, 'source' | 'metadata'>): number | undefined {\n const metadata = item.metadata ?? {};\n if (item.source === 'github-issue') return branchNumber(metadata, 'githubIssueNumber');\n if (item.source === 'github-pr') return branchNumber(metadata, 'githubPullRequestNumber');\n return;\n}\n\n/** How a card names its thread: a Linear title already opens with its identifier, a GitHub card gets its number here. */\nexport function workItemThreadTitle(\n item: Pick<WorkItemBranchInput, 'source' | 'metadata'> & { title: string },\n): string {\n const number = workItemNumber(item);\n if (number === undefined) return item.title;\n return `${item.source === 'github-pr' ? 'PR' : 'Issue'} #${number}: ${item.title}`;\n}\n\n/**\n * The git branch an item's runs and sessions share, one grammar for both sides\n * of the wire: the dispatcher names autonomous run branches with it and the\n * board opens card sessions on it, so both converge on one checkout per item.\n * Cards without a provider identity (manual, Slack) and cards whose metadata\n * lost their identifier fall back to the id-derived branch.\n */\nexport function workItemBranch(item: WorkItemBranchInput): string {\n const metadata = item.metadata ?? {};\n const githubNumber = workItemNumber(item);\n if (githubNumber !== undefined) {\n return item.source === 'github-issue' ? `factory/issue-${githubNumber}` : `factory/pr-${githubNumber}`;\n }\n if (item.source === 'linear-issue' && typeof metadata.identifier === 'string') {\n const identifier = metadata.identifier.trim();\n if (identifier) return `factory/linear-${identifier.toLowerCase()}`;\n }\n return `factory/item-${item.id}`;\n}\n\n/** The pull request a `factory/pr-<number>` branch was named after, the inverse of {@link workItemBranch}. */\nexport function pullRequestNumberFromBranch(branch: string): number | undefined {\n const match = /^factory\\/pr-([1-9]\\d*)$/.exec(branch);\n return match ? Number(match[1]) : undefined;\n}\n"],"mappings":";;AAgBA,SAAgB,qBAAqB,gBAAiF;CACpH,IAAI,CAAC,gBAAgB,OAAO;CAC5B,IAAI,eAAe,kBAAkB,UAAU,OAAO;CAGtD,IAAI,eAAe,kBAAkB,UAAU,OAAO;CACtD,OAAO,eAAe,SAAS,iBAAiB,cAAc;AAChE;AAEA,SAAS,aAAa,UAAmC,KAAiC;CACxF,MAAM,QAAQ,SAAS,QAAQ,SAAS;CACxC,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,QAAQ,IAAI,QAAQ,KAAA;AACrF;;AAGA,SAAgB,eAAe,MAA4E;CACzG,MAAM,WAAW,KAAK,YAAY,CAAC;CACnC,IAAI,KAAK,WAAW,gBAAgB,OAAO,aAAa,UAAU,mBAAmB;CACrF,IAAI,KAAK,WAAW,aAAa,OAAO,aAAa,UAAU,yBAAyB;AAE1F;;AAGA,SAAgB,oBACd,MACQ;CACR,MAAM,SAAS,eAAe,IAAI;CAClC,IAAI,WAAW,KAAA,GAAW,OAAO,KAAK;CACtC,OAAO,GAAG,KAAK,WAAW,cAAc,OAAO,QAAQ,IAAI,OAAO,IAAI,KAAK;AAC7E;;;;;;;;AASA,SAAgB,eAAe,MAAmC;CAChE,MAAM,WAAW,KAAK,YAAY,CAAC;CACnC,MAAM,eAAe,eAAe,IAAI;CACxC,IAAI,iBAAiB,KAAA,GACnB,OAAO,KAAK,WAAW,iBAAiB,iBAAiB,iBAAiB,cAAc;CAE1F,IAAI,KAAK,WAAW,kBAAkB,OAAO,SAAS,eAAe,UAAU;EAC7E,MAAM,aAAa,SAAS,WAAW,KAAK;EAC5C,IAAI,YAAY,OAAO,kBAAkB,WAAW,YAAY;CAClE;CACA,OAAO,gBAAgB,KAAK;AAC9B;;AAGA,SAAgB,4BAA4B,QAAoC;CAC9E,MAAM,QAAQ,2BAA2B,KAAK,MAAM;CACpD,OAAO,QAAQ,OAAO,MAAM,EAAE,IAAI,KAAA;AACpC"}
1
+ {"version":3,"file":"work-item-branch.js","names":[],"sources":["../src/work-item-branch.ts"],"sourcesContent":["import type { ExternalWorkItemSource } from './storage/domains/work-items/base.js';\n\n/**\n * Where a card came from, in the vocabulary branch naming reads. Server rows\n * map their `externalSource` into this with {@link workItemBranchSource}; the\n * board's own `WorkItem['source']` is already this union.\n */\nexport type WorkItemBranchSource =\n | 'github-issue'\n | 'github-pr'\n | 'gitlab-issue'\n | 'gitlab-pr'\n | 'linear-issue'\n | 'jira-issue'\n | 'incidentio-follow-up'\n | 'slack-thread'\n | 'manual';\n\nexport interface WorkItemBranchInput {\n id: string;\n source: WorkItemBranchSource;\n metadata?: Record<string, unknown> | null;\n}\n\n/** Map a stored item's provenance onto the source vocabulary branch naming reads. */\nexport function workItemBranchSource(externalSource: ExternalWorkItemSource | null | undefined): WorkItemBranchSource {\n if (!externalSource) return 'manual';\n if (externalSource.integrationId === 'linear') return 'linear-issue';\n if (externalSource.integrationId === 'gitlab') {\n return externalSource.type === 'pull-request' ? 'gitlab-pr' : 'gitlab-issue';\n }\n if (externalSource.integrationId === 'jira') return 'jira-issue';\n if (externalSource.integrationId === 'incidentio') return 'incidentio-follow-up';\n // Only GitHub, GitLab, Linear, Jira, and incident.io carry provider identities; anything\n // else (a Slack thread, say) is a plain work item rather than a mislabeled GitHub issue.\n if (externalSource.integrationId !== 'github') return 'manual';\n return externalSource.type === 'pull-request' ? 'github-pr' : 'github-issue';\n}\n\nfunction branchNumber(metadata: Record<string, unknown>, key: string): number | undefined {\n const value = metadata[key] ?? metadata.number;\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : undefined;\n}\n\n/** The provider number a GitHub card carries — the `#12` its runs and thread titles name it by. */\nexport function workItemNumber(item: Pick<WorkItemBranchInput, 'source' | 'metadata'>): number | undefined {\n const metadata = item.metadata ?? {};\n if (item.source === 'github-issue') return branchNumber(metadata, 'githubIssueNumber');\n if (item.source === 'github-pr') return branchNumber(metadata, 'githubPullRequestNumber');\n if (item.source === 'gitlab-issue') return branchNumber(metadata, 'gitlabIssueIid');\n if (item.source === 'gitlab-pr') return branchNumber(metadata, 'gitlabMergeRequestIid');\n return;\n}\n\n/** How a card names its thread: a Linear title already opens with its identifier, a GitHub card gets its number here. */\nexport function workItemThreadTitle(\n item: Pick<WorkItemBranchInput, 'source' | 'metadata'> & { title: string },\n): string {\n const number = workItemNumber(item);\n if (number === undefined) return item.title;\n const kind = item.source === 'github-pr' ? 'PR' : item.source === 'gitlab-pr' ? 'MR' : 'Issue';\n return `${kind} #${number}: ${item.title}`;\n}\n\n/**\n * The git branch an item's runs and sessions share, one grammar for both sides\n * of the wire: the dispatcher names autonomous run branches with it and the\n * board opens card sessions on it, so both converge on one checkout per item.\n * Cards without a provider identity (manual, Slack) and cards whose metadata\n * lost their identifier fall back to the id-derived branch.\n */\nexport function workItemBranch(item: WorkItemBranchInput): string {\n const metadata = item.metadata ?? {};\n const providerNumber = workItemNumber(item);\n if (providerNumber !== undefined && (item.source === 'github-issue' || item.source === 'github-pr')) {\n return item.source === 'github-issue' ? `factory/issue-${providerNumber}` : `factory/pr-${providerNumber}`;\n }\n if (\n (item.source === 'linear-issue' || item.source === 'jira-issue' || item.source === 'incidentio-follow-up') &&\n typeof metadata.identifier === 'string'\n ) {\n const identifier = metadata.identifier.trim();\n if (identifier) {\n const provider = item.source === 'linear-issue' ? 'linear' : item.source === 'jira-issue' ? 'jira' : 'incidentio';\n return `factory/${provider}-${identifier.toLowerCase()}`;\n }\n }\n if (item.source === 'gitlab-pr' && providerNumber !== undefined) {\n const uniqueSuffix = item.id\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '')\n .slice(-12);\n if (uniqueSuffix) return `factory/gitlab-mr-${providerNumber}-${uniqueSuffix}`;\n }\n if (item.source === 'gitlab-issue' && typeof metadata.identifier === 'string') {\n const identifier = metadata.identifier\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, '-');\n const uniqueSuffix = item.id\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '')\n .slice(-12);\n if (identifier && uniqueSuffix) return `factory/gitlab-${identifier.slice(0, 60)}-${uniqueSuffix}`;\n }\n return `factory/item-${item.id}`;\n}\n\n/** The pull request a `factory/pr-<number>` branch was named after, the inverse of {@link workItemBranch}. */\nexport function pullRequestNumberFromBranch(branch: string): number | undefined {\n const match = /^factory\\/pr-([1-9]\\d*)$/.exec(branch);\n return match ? Number(match[1]) : undefined;\n}\n\n/** The GitLab MR IID encoded in Factory's collision-resistant review branch. */\nexport function mergeRequestNumberFromBranch(branch: string): number | undefined {\n const match = /^factory\\/gitlab-mr-([1-9]\\d*)-[a-z0-9]{1,12}$/.exec(branch);\n const number = match ? Number(match[1]) : undefined;\n return number !== undefined && Number.isSafeInteger(number) ? number : undefined;\n}\n"],"mappings":";;AAyBA,SAAgB,qBAAqB,gBAAiF;CACpH,IAAI,CAAC,gBAAgB,OAAO;CAC5B,IAAI,eAAe,kBAAkB,UAAU,OAAO;CACtD,IAAI,eAAe,kBAAkB,UACnC,OAAO,eAAe,SAAS,iBAAiB,cAAc;CAEhE,IAAI,eAAe,kBAAkB,QAAQ,OAAO;CACpD,IAAI,eAAe,kBAAkB,cAAc,OAAO;CAG1D,IAAI,eAAe,kBAAkB,UAAU,OAAO;CACtD,OAAO,eAAe,SAAS,iBAAiB,cAAc;AAChE;AAEA,SAAS,aAAa,UAAmC,KAAiC;CACxF,MAAM,QAAQ,SAAS,QAAQ,SAAS;CACxC,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,QAAQ,IAAI,QAAQ,KAAA;AACrF;;AAGA,SAAgB,eAAe,MAA4E;CACzG,MAAM,WAAW,KAAK,YAAY,CAAC;CACnC,IAAI,KAAK,WAAW,gBAAgB,OAAO,aAAa,UAAU,mBAAmB;CACrF,IAAI,KAAK,WAAW,aAAa,OAAO,aAAa,UAAU,yBAAyB;CACxF,IAAI,KAAK,WAAW,gBAAgB,OAAO,aAAa,UAAU,gBAAgB;CAClF,IAAI,KAAK,WAAW,aAAa,OAAO,aAAa,UAAU,uBAAuB;AAExF;;AAGA,SAAgB,oBACd,MACQ;CACR,MAAM,SAAS,eAAe,IAAI;CAClC,IAAI,WAAW,KAAA,GAAW,OAAO,KAAK;CAEtC,OAAO,GADM,KAAK,WAAW,cAAc,OAAO,KAAK,WAAW,cAAc,OAAO,QACxE,IAAI,OAAO,IAAI,KAAK;AACrC;;;;;;;;AASA,SAAgB,eAAe,MAAmC;CAChE,MAAM,WAAW,KAAK,YAAY,CAAC;CACnC,MAAM,iBAAiB,eAAe,IAAI;CAC1C,IAAI,mBAAmB,KAAA,MAAc,KAAK,WAAW,kBAAkB,KAAK,WAAW,cACrF,OAAO,KAAK,WAAW,iBAAiB,iBAAiB,mBAAmB,cAAc;CAE5F,KACG,KAAK,WAAW,kBAAkB,KAAK,WAAW,gBAAgB,KAAK,WAAW,2BACnF,OAAO,SAAS,eAAe,UAC/B;EACA,MAAM,aAAa,SAAS,WAAW,KAAK;EAC5C,IAAI,YAEF,OAAO,WADU,KAAK,WAAW,iBAAiB,WAAW,KAAK,WAAW,eAAe,SAAS,aAC1E,GAAG,WAAW,YAAY;CAEzD;CACA,IAAI,KAAK,WAAW,eAAe,mBAAmB,KAAA,GAAW;EAC/D,MAAM,eAAe,KAAK,GACvB,YAAY,CAAC,CACb,QAAQ,eAAe,EAAE,CAAC,CAC1B,MAAM,GAAG;EACZ,IAAI,cAAc,OAAO,qBAAqB,eAAe,GAAG;CAClE;CACA,IAAI,KAAK,WAAW,kBAAkB,OAAO,SAAS,eAAe,UAAU;EAC7E,MAAM,aAAa,SAAS,WACzB,KAAK,CAAC,CACN,YAAY,CAAC,CACb,QAAQ,kBAAkB,GAAG;EAChC,MAAM,eAAe,KAAK,GACvB,YAAY,CAAC,CACb,QAAQ,eAAe,EAAE,CAAC,CAC1B,MAAM,GAAG;EACZ,IAAI,cAAc,cAAc,OAAO,kBAAkB,WAAW,MAAM,GAAG,EAAE,EAAE,GAAG;CACtF;CACA,OAAO,gBAAgB,KAAK;AAC9B;;AAGA,SAAgB,4BAA4B,QAAoC;CAC9E,MAAM,QAAQ,2BAA2B,KAAK,MAAM;CACpD,OAAO,QAAQ,OAAO,MAAM,EAAE,IAAI,KAAA;AACpC;;AAGA,SAAgB,6BAA6B,QAAoC;CAC/E,MAAM,QAAQ,iDAAiD,KAAK,MAAM;CAC1E,MAAM,SAAS,QAAQ,OAAO,MAAM,EAAE,IAAI,KAAA;CAC1C,OAAO,WAAW,KAAA,KAAa,OAAO,cAAc,MAAM,IAAI,SAAS,KAAA;AACzE"}
@@ -2,9 +2,11 @@ import { SandboxFilesystem } from '@mastra/code-sdk/agents/sandbox-filesystem';
2
2
  import type { getDynamicWorkspace } from '@mastra/code-sdk/agents/workspace';
3
3
  import { Workspace } from '@mastra/core/workspace';
4
4
  import type { SkillSource, SkillSourceEntry, SkillSourceStat, WorkspaceSandbox } from '@mastra/core/workspace';
5
+ import type { VersionControl } from './capabilities/version-control.js';
5
6
  import type { MastraFactorySandboxConfig } from './factory.js';
6
7
  import type { GithubIntegration } from './integrations/github/integration.js';
7
8
  import type { FactoryProjectsStorage } from './storage/domains/projects/base.js';
9
+ import type { SourceControlStorageHandle } from './storage/domains/source-control/base.js';
8
10
  import type { WorkItemsStorage } from './storage/domains/work-items/base.js';
9
11
  export declare const BUNDLED_FACTORY_SKILLS_PATH: string;
10
12
  /**
@@ -33,12 +35,24 @@ type DynamicWorkspaceContext = Parameters<typeof getDynamicWorkspace>[0];
33
35
  * An eager start is fire-and-forget; if it fails, the lazy path still runs.
34
36
  */
35
37
  export type FactorySandboxStart = 'lazy' | 'eager';
38
+ export interface WorkspaceSourceControlProvider {
39
+ /** Stable integration id used to select the provider-owned storage partition. */
40
+ id: string;
41
+ /** Provider capability used to resolve fresh repository credentials. */
42
+ versionControl: Pick<VersionControl, 'getRepositoryAccess'>;
43
+ /** Provider-owned source-control rows, including Factory sessions. */
44
+ storage: SourceControlStorageHandle;
45
+ /** Present only for GitHub, whose CLI PAT rotation has additional semantics. */
46
+ github?: GithubIntegration;
47
+ }
36
48
  export interface CreateWorkspaceFactoryOptions {
37
49
  /** Factory sandbox runtime config (session sandbox callback). */
38
50
  sandbox?: MastraFactorySandboxConfig;
39
51
  /** Defaults to `'lazy'`. */
40
52
  sandboxStart?: FactorySandboxStart;
41
- /** GitHub integration used to resolve Factory sessions and mint repo tokens. */
53
+ /** Source-control providers whose repositories may back Factory sessions. */
54
+ sourceControls?: WorkspaceSourceControlProvider[];
55
+ /** @deprecated GitHub-only compatibility path; prefer sourceControls. */
42
56
  github?: GithubIntegration;
43
57
  /** Work-items storage used to resolve the session's run-binding role, so
44
58
  * review-board sessions get the reviewer PAT as `GH_TOKEN`. Optional —
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAE/E,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,mCAAmC,CAAC;AAItG,OAAO,EAAoB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAEV,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAwB9E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAQ7E,eAAO,MAAM,2BAA2B,QAQQ,CAAC;AAEjD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,SAAS,CAS7F;AAED,eAAO,MAAM,mBAAmB,aAO9B,CAAC;AAEH,qBAAa,kBAAmB,YAAW,WAAW;;IAMlD,QAAQ,CAAC,QAAQ,EAAE,WAAW;gBAArB,QAAQ,EAAE,WAAW,EAC9B,kBAAkB,EAAE,MAAM,EAAE,EAC5B,eAAe,GAAE,MAAM,GAAG,SAA2C;IAqBjE,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO3C,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAMjD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAMrD,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAyB7D,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAI7C;AAuDD,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzE;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,6BAA6B;IAC5C,iEAAiE;IACjE,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC,4BAA4B;IAC5B,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,gFAAgF;IAChF,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;iEAE6D;IAC7D,SAAS,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,yBAAyB,CAAC,CAAC;IAC9D,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;IAC/C,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;CAC9C;AAED,KAAK,mBAAmB,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEtD,gFAAgF;AAChF,qBAAa,wBAAwB;;IAInC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI/B,QAAQ,CACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,mBAAmB,GAC9B,OAAO,CAAC,OAAO,CAAC;IAWb,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAS1D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,6BAAkC,IAuBlE,4CAA4C,uBAAuB,2MA8elF"}
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAE/E,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,mCAAmC,CAAC;AAItG,OAAO,EAAoB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAEV,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAwB9E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,KAAK,EAAwB,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AACjH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAQ7E,eAAO,MAAM,2BAA2B,QAQQ,CAAC;AAEjD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,SAAS,CAS7F;AAED,eAAO,MAAM,mBAAmB,aAS9B,CAAC;AAEH,qBAAa,kBAAmB,YAAW,WAAW;;IAMlD,QAAQ,CAAC,QAAQ,EAAE,WAAW;gBAArB,QAAQ,EAAE,WAAW,EAC9B,kBAAkB,EAAE,MAAM,EAAE,EAC5B,eAAe,GAAE,MAAM,GAAG,SAA2C;IAqBjE,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO3C,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAMjD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAMrD,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAyB7D,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAI7C;AAuDD,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzE;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,8BAA8B;IAC7C,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,wEAAwE;IACxE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAC;IAC5D,sEAAsE;IACtE,OAAO,EAAE,0BAA0B,CAAC;IACpC,gFAAgF;IAChF,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,WAAW,6BAA6B;IAC5C,iEAAiE;IACjE,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC,4BAA4B;IAC5B,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,6EAA6E;IAC7E,cAAc,CAAC,EAAE,8BAA8B,EAAE,CAAC;IAClD,yEAAyE;IACzE,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;iEAE6D;IAC7D,SAAS,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,yBAAyB,CAAC,CAAC;IAC9D,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;IAC/C,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;CAC9C;AAED,KAAK,mBAAmB,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEtD,gFAAgF;AAChF,qBAAa,wBAAwB;;IAInC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI/B,QAAQ,CACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,mBAAmB,GAC9B,OAAO,CAAC,OAAO,CAAC;IAWb,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAS1D;AAuBD,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,6BAAkC,IA4BlE,4CAA4C,uBAAuB,2MAugBlF"}
package/dist/workspace.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { timedPhase } from "./timing.js";
2
2
  import { getFactoryAuthOrgId, getFactoryAuthUserFromContext, getFactoryAuthUserId } from "./auth.js";
3
- import { pullRequestNumberFromBranch } from "./work-item-branch.js";
3
+ import { mergeRequestNumberFromBranch, pullRequestNumberFromBranch } from "./work-item-branch.js";
4
4
  import { getGithubPat } from "./integrations/github/pat.js";
5
5
  import { registerGithubPatKind, registerGithubTokenInjector } from "./integrations/github/token-refresh.js";
6
- import { DEFAULT_COMMAND_TIMEOUT_MS, SetupCommandError, checkoutSessionBranch, materializeRepo, runSetupCommand, runTeardownCommand } from "./integrations/github/sandbox.js";
7
6
  import { requireExec } from "./sandbox/materialization.js";
8
7
  import { createSessionSetupHook, evictSessionSandbox, getSessionSandbox, hasFailedSetupCommand, recordFailedSetupCommand, resolveSessionWorkdir } from "./sandbox/session-sandbox.js";
8
+ import { DEFAULT_COMMAND_TIMEOUT_MS, SetupCommandError, checkoutSessionBranch, materializeRepo, runSetupCommand, runTeardownCommand } from "./integrations/github/sandbox.js";
9
9
  import { getFactorySessionAddress } from "./rules/binding-context.js";
10
10
  import { parseSupervisorResourceId } from "./supervisor/session.js";
11
11
  import path, { dirname, join } from "path";
@@ -38,6 +38,8 @@ const FACTORY_SKILLS_MOUNT = path.resolve(path.parse(process.cwd()).root, "__mas
38
38
  const FACTORY_SKILL_NAMES = /* @__PURE__ */ new Set([
39
39
  "configure-factory-rules",
40
40
  "factory-complete-issue",
41
+ "factory-gitlab-rereview",
42
+ "factory-gitlab-review",
41
43
  "factory-plan",
42
44
  "factory-rereview",
43
45
  "factory-review",
@@ -174,8 +176,22 @@ var FactoryWorkspaceRegistry = class {
174
176
  if (failure?.status === "rejected") throw failure.reason;
175
177
  }
176
178
  };
179
+ async function resolveSourceControlSession(providers, sessionId) {
180
+ const matches = (await Promise.all(providers.map(async (provider) => ({
181
+ provider,
182
+ session: await provider.storage.sessions.getBySessionId(sessionId)
183
+ })))).filter((match) => match.session !== null);
184
+ if (matches.length > 1) throw new Error(`Factory session ${sessionId} is ambiguous across source-control providers`);
185
+ return matches[0] ?? null;
186
+ }
177
187
  function createWorkspaceFactory(options = {}) {
178
188
  const { sandbox: sandboxConfig, github, projects, workItems } = options;
189
+ const sourceControls = options.sourceControls ?? (github ? [{
190
+ id: github.id,
191
+ versionControl: github.versionControl,
192
+ storage: github.sourceControlStorage,
193
+ github
194
+ }] : []);
179
195
  const eagerSandboxStart = options.sandboxStart === "eager";
180
196
  const workspaceRegistry = options.workspaceRegistry ?? new FactoryWorkspaceRegistry();
181
197
  const githubTokenInjectors = /* @__PURE__ */ new Map();
@@ -193,15 +209,18 @@ function createWorkspaceFactory(options = {}) {
193
209
  }) : null)) throw new Error(`Factory supervisor ${supervisorProjectId} is not available to the current user`);
194
210
  return;
195
211
  }
196
- const session = ctx?.resourceId && github ? await github.sourceControlStorage.sessions.getBySessionId(ctx.resourceId) : null;
197
- if (!session) return;
212
+ const resolvedSession = ctx?.resourceId ? await resolveSourceControlSession(sourceControls, ctx.resourceId) : null;
213
+ const session = resolvedSession?.session ?? null;
214
+ const sourceControl = resolvedSession?.provider;
215
+ if (!session || !sourceControl) return;
198
216
  const user = getFactoryAuthUserFromContext(requestContext);
199
217
  const userId = getFactoryAuthUserId(user);
200
218
  if (!user?.organizationId || !userId) throw new Error(`Factory session ${session.sessionId} was resolved without a caller identity`);
201
219
  if (user.organizationId !== session.orgId || session.visibility === "private" && userId !== session.userId) throw new Error(`Factory session ${session.sessionId} is not available to the current user`);
202
- if (!sandboxConfig || !github) throw new Error("GitHub and a sandbox callback are required to create a Factory session workspace");
220
+ if (!sandboxConfig) throw new Error("A sandbox callback is required to create a Factory session workspace");
203
221
  const createSessionSandboxInstance = sandboxConfig;
204
- const storage = github.sourceControlStorage;
222
+ const githubProvider = sourceControl.github;
223
+ const storage = sourceControl.storage;
205
224
  const projectRepository = await storage.projectRepositories.get({
206
225
  orgId: session.orgId,
207
226
  id: session.projectRepositoryId
@@ -218,7 +237,7 @@ function createWorkspaceFactory(options = {}) {
218
237
  if (!await storage.installations.get({
219
238
  orgId: session.orgId,
220
239
  id: connection.installationId
221
- })) throw new Error(`GitHub installation ${connection.installationId} was not found`);
240
+ })) throw new Error(`${sourceControl.id} installation ${connection.installationId} was not found`);
222
241
  const repoFullName = repository.slug;
223
242
  const runSetupOn = (target, workdir, gate) => runSessionSetup(requireExec(target), workdir, gate);
224
243
  const guardedSetup = createSessionSetupHook(runSetupOn, session.id, repoFullName, projectRepository.setupCommand ?? void 0);
@@ -235,6 +254,10 @@ function createWorkspaceFactory(options = {}) {
235
254
  }).catch(() => {});
236
255
  constructedWorkspaces.get(workspaceId)?.skills?.refresh().catch(() => {});
237
256
  };
257
+ if (!githubProvider) {
258
+ publishStartSideEffects();
259
+ return;
260
+ }
238
261
  const existingRegistration = githubTokenInjectors.get(workspaceId);
239
262
  if (existingRegistration) {
240
263
  existingRegistration.inject = (freshToken) => {
@@ -250,7 +273,7 @@ function createWorkspaceFactory(options = {}) {
250
273
  return;
251
274
  }
252
275
  const patKind = await resolveGithubPatKind("default");
253
- const ghCliToken = await getGithubPat(() => github.integrationStorage, session.orgId, patKind) ?? await getRepositoryToken();
276
+ const ghCliToken = await getGithubPat(() => githubProvider.integrationStorage, session.orgId, patKind) ?? await getRepositoryToken();
254
277
  target.setEnv?.((env) => ({
255
278
  ...env,
256
279
  GH_TOKEN: ghCliToken
@@ -278,7 +301,7 @@ function createWorkspaceFactory(options = {}) {
278
301
  sessionId: session.id,
279
302
  repoFullName,
280
303
  setupCommand: projectRepository.setupCommand ?? void 0,
281
- getRepositoryAccess: () => github.versionControl.getRepositoryAccess({
304
+ getRepositoryAccess: () => sourceControl.versionControl.getRepositoryAccess({
282
305
  orgId: session.orgId,
283
306
  repositoryId: repository.id
284
307
  })
@@ -311,11 +334,12 @@ function createWorkspaceFactory(options = {}) {
311
334
  const workspaceId = `${WORKSPACE_ID_PREFIX}-${projectRepository.id}-${session.id}${extensionId}`;
312
335
  const workspaceGeneration = workspaceRegistry.generation(session.sessionId);
313
336
  const configDir = DEFAULT_CONFIG_DIR;
337
+ const getRepositoryAccess = () => sourceControl.versionControl.getRepositoryAccess({
338
+ orgId: session.orgId,
339
+ repositoryId: repository.id
340
+ });
314
341
  const getRepositoryToken = async () => {
315
- const token = (await github.versionControl.getRepositoryAccess({
316
- orgId: session.orgId,
317
- repositoryId: repository.id
318
- })).authorization?.token;
342
+ const token = (await getRepositoryAccess()).authorization?.token;
319
343
  if (!token) throw new Error("Repository access did not include a bearer token for the Factory session");
320
344
  return token;
321
345
  };
@@ -338,6 +362,7 @@ function createWorkspaceFactory(options = {}) {
338
362
  registerGithubPatKind(requestContext, registered.patKind);
339
363
  };
340
364
  const reconcileGithubToken = async () => {
365
+ if (!githubProvider) return;
341
366
  const reconciliation = (githubTokenReconciliations.get(workspaceId) ?? Promise.resolve()).catch(() => {}).then(async () => {
342
367
  const registered = githubTokenInjectors.get(workspaceId);
343
368
  if (!registered) return;
@@ -350,7 +375,7 @@ function createWorkspaceFactory(options = {}) {
350
375
  }
351
376
  if (patKind === "reviewer") registered.tokenReplacementPending = false;
352
377
  if (previousPatKind === "reviewer" && patKind === "default") registered.tokenReplacementPending = true;
353
- let token = await getGithubPat(() => github.integrationStorage, session.orgId, patKind);
378
+ let token = await getGithubPat(() => githubProvider.integrationStorage, session.orgId, patKind);
354
379
  if (!token && registered.tokenReplacementPending) token = await getRepositoryToken();
355
380
  if (githubTokenInjectors.get(workspaceId) !== registered) return;
356
381
  if (token && token !== registered.ghToken) try {
@@ -405,13 +430,17 @@ function createWorkspaceFactory(options = {}) {
405
430
  }
406
431
  const retiredError = () => /* @__PURE__ */ new Error(`Factory session ${session.sessionId} was retired during workspace materialization`);
407
432
  const runSessionSetup = async (target, workdir, gate) => {
408
- const token = await getRepositoryToken();
409
- const setupPatKind = await resolveGithubPatKind("default");
410
- const setupGhToken = await getGithubPat(() => github.integrationStorage, session.orgId, setupPatKind) ?? token;
411
- target.setEnv?.((env) => ({
412
- ...env,
413
- GH_TOKEN: setupGhToken
414
- }));
433
+ const access = await getRepositoryAccess();
434
+ const token = access.authorization?.token;
435
+ if (!token) throw new Error("Repository access did not include a bearer token for the Factory session");
436
+ if (githubProvider) {
437
+ const setupPatKind = await resolveGithubPatKind("default");
438
+ const setupGhToken = await getGithubPat(() => githubProvider.integrationStorage, session.orgId, setupPatKind) ?? token;
439
+ target.setEnv?.((env) => ({
440
+ ...env,
441
+ GH_TOKEN: setupGhToken
442
+ }));
443
+ }
415
444
  await materializeRepo({
416
445
  row: {
417
446
  id: session.id,
@@ -420,7 +449,9 @@ function createWorkspaceFactory(options = {}) {
420
449
  },
421
450
  repoInfo: {
422
451
  repoFullName,
423
- defaultBranch: repository.defaultBranch
452
+ defaultBranch: repository.defaultBranch,
453
+ cloneUrl: access.cloneUrl,
454
+ authUsername: access.authorization?.username
424
455
  },
425
456
  sandbox: target,
426
457
  token,
@@ -431,7 +462,10 @@ function createWorkspaceFactory(options = {}) {
431
462
  baseBranch: session.baseBranch || projectRepository.branch || repository.defaultBranch,
432
463
  token,
433
464
  repoFullName,
434
- pullRequestNumber: pullRequestNumberFromBranch(session.branch)
465
+ cloneUrl: access.cloneUrl,
466
+ authUsername: access.authorization?.username,
467
+ pullRequestNumber: pullRequestNumberFromBranch(session.branch),
468
+ mergeRequestNumber: sourceControl.id === "gitlab" ? mergeRequestNumberFromBranch(session.branch) : void 0
435
469
  });
436
470
  if (projectRepository.setupCommand && !gate.setupDone) {
437
471
  if (hasFailedSetupCommand(session.id, projectRepository.setupCommand)) {