@mastra/factory 0.24.0-alpha.1 → 0.24.0-alpha.10

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 (389) hide show
  1. package/README.md +106 -4
  2. package/dist/auth.d.ts +14 -0
  3. package/dist/auth.d.ts.map +1 -1
  4. package/dist/auth.js +45 -9
  5. package/dist/auth.js.map +1 -1
  6. package/dist/boards/review.d.ts.map +1 -1
  7. package/dist/boards/review.js +21 -1
  8. package/dist/boards/review.js.map +1 -1
  9. package/dist/boards/work-transition-policy.d.ts.map +1 -1
  10. package/dist/boards/work-transition-policy.js +12 -1
  11. package/dist/boards/work-transition-policy.js.map +1 -1
  12. package/dist/boards/work.d.ts +14 -0
  13. package/dist/boards/work.d.ts.map +1 -1
  14. package/dist/boards/work.js +70 -7
  15. package/dist/boards/work.js.map +1 -1
  16. package/dist/capabilities/version-control.d.ts +26 -0
  17. package/dist/capabilities/version-control.d.ts.map +1 -1
  18. package/dist/factory.d.ts +8 -0
  19. package/dist/factory.d.ts.map +1 -1
  20. package/dist/factory.js +354 -27
  21. package/dist/factory.js.map +1 -1
  22. package/dist/integrations/base.d.ts +1 -1
  23. package/dist/integrations/base.d.ts.map +1 -1
  24. package/dist/integrations/github/default-rules.d.ts.map +1 -1
  25. package/dist/integrations/github/default-rules.js +1 -16
  26. package/dist/integrations/github/default-rules.js.map +1 -1
  27. package/dist/integrations/github/integration.d.ts.map +1 -1
  28. package/dist/integrations/github/integration.js +37 -1
  29. package/dist/integrations/github/integration.js.map +1 -1
  30. package/dist/integrations/github/routes.d.ts +1 -1
  31. package/dist/integrations/github/routes.d.ts.map +1 -1
  32. package/dist/integrations/github/routes.js +19 -11
  33. package/dist/integrations/github/routes.js.map +1 -1
  34. package/dist/integrations/github/rules.d.ts.map +1 -1
  35. package/dist/integrations/github/rules.js +26 -22
  36. package/dist/integrations/github/rules.js.map +1 -1
  37. package/dist/integrations/github/sandbox-release.d.ts +15 -3
  38. package/dist/integrations/github/sandbox-release.d.ts.map +1 -1
  39. package/dist/integrations/github/sandbox-release.js +20 -3
  40. package/dist/integrations/github/sandbox-release.js.map +1 -1
  41. package/dist/integrations/github/sandbox.d.ts +2 -3
  42. package/dist/integrations/github/sandbox.d.ts.map +1 -1
  43. package/dist/integrations/github/sandbox.js +78 -7
  44. package/dist/integrations/github/sandbox.js.map +1 -1
  45. package/dist/integrations/github/session-subscriptions.d.ts.map +1 -1
  46. package/dist/integrations/github/session-subscriptions.js +1 -2
  47. package/dist/integrations/github/session-subscriptions.js.map +1 -1
  48. package/dist/integrations/github/subscriptions.d.ts +7 -4
  49. package/dist/integrations/github/subscriptions.d.ts.map +1 -1
  50. package/dist/integrations/github/subscriptions.js +5 -5
  51. package/dist/integrations/github/subscriptions.js.map +1 -1
  52. package/dist/integrations/github/webhook.d.ts +4 -2
  53. package/dist/integrations/github/webhook.d.ts.map +1 -1
  54. package/dist/integrations/github/webhook.js +59 -36
  55. package/dist/integrations/github/webhook.js.map +1 -1
  56. package/dist/integrations/gitlab/api.d.ts +16 -1
  57. package/dist/integrations/gitlab/api.d.ts.map +1 -1
  58. package/dist/integrations/gitlab/api.js +9 -0
  59. package/dist/integrations/gitlab/api.js.map +1 -1
  60. package/dist/integrations/gitlab/routes.d.ts.map +1 -1
  61. package/dist/integrations/gitlab/routes.js +10 -6
  62. package/dist/integrations/gitlab/routes.js.map +1 -1
  63. package/dist/integrations/gitlab/rules.d.ts.map +1 -1
  64. package/dist/integrations/gitlab/rules.js +28 -21
  65. package/dist/integrations/gitlab/rules.js.map +1 -1
  66. package/dist/integrations/gitlab/session-subscriptions.d.ts.map +1 -1
  67. package/dist/integrations/gitlab/session-subscriptions.js +1 -2
  68. package/dist/integrations/gitlab/session-subscriptions.js.map +1 -1
  69. package/dist/integrations/gitlab/subscriptions.d.ts +7 -4
  70. package/dist/integrations/gitlab/subscriptions.d.ts.map +1 -1
  71. package/dist/integrations/gitlab/subscriptions.js +5 -5
  72. package/dist/integrations/gitlab/subscriptions.js.map +1 -1
  73. package/dist/integrations/gitlab/version-control.d.ts.map +1 -1
  74. package/dist/integrations/gitlab/version-control.js +37 -3
  75. package/dist/integrations/gitlab/version-control.js.map +1 -1
  76. package/dist/integrations/incidentio/intake.d.ts +1 -1
  77. package/dist/integrations/incidentio/intake.d.ts.map +1 -1
  78. package/dist/integrations/incidentio/intake.js.map +1 -1
  79. package/dist/integrations/linear/agent-tools.d.ts.map +1 -1
  80. package/dist/integrations/linear/agent-tools.js.map +1 -1
  81. package/dist/integrations/platform/connect/routes.d.ts +1 -1
  82. package/dist/integrations/platform/connect/routes.d.ts.map +1 -1
  83. package/dist/integrations/platform/connect/routes.js.map +1 -1
  84. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  85. package/dist/integrations/platform/github/integration.js +27 -1
  86. package/dist/integrations/platform/github/integration.js.map +1 -1
  87. package/dist/integrations/platform/incidentio/integration.d.ts +1 -1
  88. package/dist/integrations/platform/incidentio/integration.d.ts.map +1 -1
  89. package/dist/integrations/platform/incidentio/integration.js.map +1 -1
  90. package/dist/integrations/platform/jira/integration.d.ts +1 -1
  91. package/dist/integrations/platform/jira/integration.d.ts.map +1 -1
  92. package/dist/integrations/platform/jira/integration.js.map +1 -1
  93. package/dist/integrations/platform/linear/event-worker.d.ts +1 -1
  94. package/dist/integrations/platform/linear/event-worker.d.ts.map +1 -1
  95. package/dist/integrations/platform/linear/event-worker.js.map +1 -1
  96. package/dist/integrations/slack/integration.d.ts.map +1 -1
  97. package/dist/integrations/slack/integration.js +33 -6
  98. package/dist/integrations/slack/integration.js.map +1 -1
  99. package/dist/integrations/slack/slack.d.ts +16 -5
  100. package/dist/integrations/slack/slack.d.ts.map +1 -1
  101. package/dist/integrations/slack/slack.js +137 -64
  102. package/dist/integrations/slack/slack.js.map +1 -1
  103. package/dist/integrations/subscription-session.d.ts +14 -0
  104. package/dist/integrations/subscription-session.d.ts.map +1 -1
  105. package/dist/integrations/subscription-session.js +30 -16
  106. package/dist/integrations/subscription-session.js.map +1 -1
  107. package/dist/mcp/disconnect.d.ts +10 -0
  108. package/dist/mcp/disconnect.d.ts.map +1 -0
  109. package/dist/mcp/disconnect.js +44 -0
  110. package/dist/mcp/disconnect.js.map +1 -0
  111. package/dist/mcp/routes.d.ts +46 -0
  112. package/dist/mcp/routes.d.ts.map +1 -0
  113. package/dist/mcp/routes.js +243 -0
  114. package/dist/mcp/routes.js.map +1 -0
  115. package/dist/provider-display-name.d.ts +2 -0
  116. package/dist/provider-display-name.d.ts.map +1 -0
  117. package/dist/provider-display-name.js +16 -0
  118. package/dist/provider-display-name.js.map +1 -0
  119. package/dist/review-verdict.d.ts +11 -0
  120. package/dist/review-verdict.d.ts.map +1 -1
  121. package/dist/review-verdict.js +16 -1
  122. package/dist/review-verdict.js.map +1 -1
  123. package/dist/routes/attention-activity.d.ts.map +1 -1
  124. package/dist/routes/attention-activity.js +5 -2
  125. package/dist/routes/attention-activity.js.map +1 -1
  126. package/dist/routes/attention-providers.d.ts +0 -1
  127. package/dist/routes/attention-providers.d.ts.map +1 -1
  128. package/dist/routes/attention-providers.js +5 -6
  129. package/dist/routes/attention-providers.js.map +1 -1
  130. package/dist/routes/config.d.ts +44 -5
  131. package/dist/routes/config.d.ts.map +1 -1
  132. package/dist/routes/config.js +181 -58
  133. package/dist/routes/config.js.map +1 -1
  134. package/dist/routes/contracts.d.ts +4 -0
  135. package/dist/routes/contracts.d.ts.map +1 -1
  136. package/dist/routes/contracts.js +3 -1
  137. package/dist/routes/contracts.js.map +1 -1
  138. package/dist/routes/custom-provider-source.d.ts +8 -0
  139. package/dist/routes/custom-provider-source.d.ts.map +1 -1
  140. package/dist/routes/custom-provider-source.js +22 -1
  141. package/dist/routes/custom-provider-source.js.map +1 -1
  142. package/dist/routes/oauth.js +1 -1
  143. package/dist/routes/oauth.js.map +1 -1
  144. package/dist/routes/projects.d.ts +1 -1
  145. package/dist/routes/projects.d.ts.map +1 -1
  146. package/dist/routes/projects.js +1 -1
  147. package/dist/routes/projects.js.map +1 -1
  148. package/dist/routes/provider-credentials.d.ts +7 -2
  149. package/dist/routes/provider-credentials.d.ts.map +1 -1
  150. package/dist/routes/provider-credentials.js +30 -8
  151. package/dist/routes/provider-credentials.js.map +1 -1
  152. package/dist/routes/skills.d.ts +2 -4
  153. package/dist/routes/skills.d.ts.map +1 -1
  154. package/dist/routes/skills.js +19 -65
  155. package/dist/routes/skills.js.map +1 -1
  156. package/dist/routes/source-control-sessions.d.ts +9 -1
  157. package/dist/routes/source-control-sessions.d.ts.map +1 -1
  158. package/dist/routes/source-control-sessions.js +131 -7
  159. package/dist/routes/source-control-sessions.js.map +1 -1
  160. package/dist/routes/surface.d.ts +3 -2
  161. package/dist/routes/surface.d.ts.map +1 -1
  162. package/dist/routes/surface.js +7 -3
  163. package/dist/routes/surface.js.map +1 -1
  164. package/dist/routes/work-items.d.ts.map +1 -1
  165. package/dist/routes/work-items.js +60 -120
  166. package/dist/routes/work-items.js.map +1 -1
  167. package/dist/rules/binding-context.js +7 -7
  168. package/dist/rules/binding-context.js.map +1 -1
  169. package/dist/rules/dispatch-errors.d.ts.map +1 -1
  170. package/dist/rules/dispatch-errors.js +12 -0
  171. package/dist/rules/dispatch-errors.js.map +1 -1
  172. package/dist/rules/dispatcher.d.ts +8 -1
  173. package/dist/rules/dispatcher.d.ts.map +1 -1
  174. package/dist/rules/dispatcher.js +117 -12
  175. package/dist/rules/dispatcher.js.map +1 -1
  176. package/dist/rules/processor.d.ts.map +1 -1
  177. package/dist/rules/processor.js +2 -1
  178. package/dist/rules/processor.js.map +1 -1
  179. package/dist/rules/start-coordinator.d.ts +4 -0
  180. package/dist/rules/start-coordinator.d.ts.map +1 -1
  181. package/dist/rules/start-coordinator.js +36 -4
  182. package/dist/rules/start-coordinator.js.map +1 -1
  183. package/dist/rules/tools.d.ts.map +1 -1
  184. package/dist/rules/tools.js +82 -3
  185. package/dist/rules/tools.js.map +1 -1
  186. package/dist/rules/transition-service.d.ts +17 -0
  187. package/dist/rules/transition-service.d.ts.map +1 -1
  188. package/dist/rules/transition-service.js +25 -0
  189. package/dist/rules/transition-service.js.map +1 -1
  190. package/dist/rules/types.d.ts +2 -4
  191. package/dist/rules/types.d.ts.map +1 -1
  192. package/dist/rules/types.js +1 -4
  193. package/dist/rules/types.js.map +1 -1
  194. package/dist/sandbox/local-factory-sandbox.d.ts.map +1 -1
  195. package/dist/sandbox/local-factory-sandbox.js +1 -0
  196. package/dist/sandbox/local-factory-sandbox.js.map +1 -1
  197. package/dist/sandbox/session-retirement.d.ts +27 -3
  198. package/dist/sandbox/session-retirement.d.ts.map +1 -1
  199. package/dist/sandbox/session-retirement.js +158 -20
  200. package/dist/sandbox/session-retirement.js.map +1 -1
  201. package/dist/secret-encryption.d.ts.map +1 -1
  202. package/dist/secret-encryption.js +65 -25
  203. package/dist/secret-encryption.js.map +1 -1
  204. package/dist/session/channel-reply-processor.d.ts +36 -0
  205. package/dist/session/channel-reply-processor.d.ts.map +1 -0
  206. package/dist/session/channel-reply-processor.js +46 -0
  207. package/dist/session/channel-reply-processor.js.map +1 -0
  208. package/dist/session/channel-session-link-processor.d.ts +39 -0
  209. package/dist/session/channel-session-link-processor.d.ts.map +1 -0
  210. package/dist/session/channel-session-link-processor.js +100 -0
  211. package/dist/session/channel-session-link-processor.js.map +1 -0
  212. package/dist/session/credential-policy.d.ts +1 -1
  213. package/dist/session/credential-policy.d.ts.map +1 -1
  214. package/dist/session/credential-policy.js +7 -6
  215. package/dist/session/credential-policy.js.map +1 -1
  216. package/dist/session/default-model-hydration.d.ts +1 -0
  217. package/dist/session/default-model-hydration.d.ts.map +1 -1
  218. package/dist/session/default-model-hydration.js +3 -2
  219. package/dist/session/default-model-hydration.js.map +1 -1
  220. package/dist/session/environment-state-processor.js +1 -1
  221. package/dist/session/environment-state-processor.js.map +1 -1
  222. package/dist/session/factory-session.d.ts +19 -1
  223. package/dist/session/factory-session.d.ts.map +1 -1
  224. package/dist/session/factory-session.js +5 -2
  225. package/dist/session/factory-session.js.map +1 -1
  226. package/dist/session/filesystem-capture.d.ts +3 -3
  227. package/dist/session/filesystem-capture.d.ts.map +1 -1
  228. package/dist/session/filesystem-capture.js +16 -17
  229. package/dist/session/filesystem-capture.js.map +1 -1
  230. package/dist/session/first-exec-capture.d.ts +1 -1
  231. package/dist/session/first-exec-capture.d.ts.map +1 -1
  232. package/dist/session/first-exec-capture.js +1 -1
  233. package/dist/session/first-exec-capture.js.map +1 -1
  234. package/dist/session/first-message-capture.d.ts +1 -1
  235. package/dist/session/first-message-capture.d.ts.map +1 -1
  236. package/dist/session/first-message-capture.js +1 -1
  237. package/dist/session/first-message-capture.js.map +1 -1
  238. package/dist/session/live-sessions.d.ts +1 -1
  239. package/dist/session/live-sessions.js +1 -1
  240. package/dist/session/live-sessions.js.map +1 -1
  241. package/dist/session/memory-settings-hydration.d.ts +1 -1
  242. package/dist/session/memory-settings-hydration.d.ts.map +1 -1
  243. package/dist/session/memory-settings-hydration.js +1 -1
  244. package/dist/session/memory-settings-hydration.js.map +1 -1
  245. package/dist/session/reply-credential-processor.d.ts +15 -0
  246. package/dist/session/reply-credential-processor.d.ts.map +1 -0
  247. package/dist/session/reply-credential-processor.js +38 -0
  248. package/dist/session/reply-credential-processor.js.map +1 -0
  249. package/dist/session/resource-migration.d.ts +87 -0
  250. package/dist/session/resource-migration.d.ts.map +1 -0
  251. package/dist/session/resource-migration.js +163 -0
  252. package/dist/session/resource-migration.js.map +1 -0
  253. package/dist/session/run-audit.d.ts +24 -0
  254. package/dist/session/run-audit.d.ts.map +1 -1
  255. package/dist/session/run-audit.js +93 -7
  256. package/dist/session/run-audit.js.map +1 -1
  257. package/dist/session/session-threads.d.ts +49 -0
  258. package/dist/session/session-threads.d.ts.map +1 -0
  259. package/dist/session/session-threads.js +70 -0
  260. package/dist/session/session-threads.js.map +1 -0
  261. package/dist/session/source-control-tools.d.ts +19 -1
  262. package/dist/session/source-control-tools.d.ts.map +1 -1
  263. package/dist/session/source-control-tools.js +78 -11
  264. package/dist/session/source-control-tools.js.map +1 -1
  265. package/dist/session/thinking-default.d.ts.map +1 -1
  266. package/dist/session/thinking-default.js +3 -4
  267. package/dist/session/thinking-default.js.map +1 -1
  268. package/dist/session/thread-session-stamp.d.ts +21 -0
  269. package/dist/session/thread-session-stamp.d.ts.map +1 -0
  270. package/dist/session/thread-session-stamp.js +20 -0
  271. package/dist/session/thread-session-stamp.js.map +1 -0
  272. package/dist/session/thread-title-mirror.d.ts +1 -1
  273. package/dist/session/thread-title-mirror.d.ts.map +1 -1
  274. package/dist/session/thread-title-mirror.js +1 -1
  275. package/dist/session/thread-title-mirror.js.map +1 -1
  276. package/dist/session/work-item-repository.d.ts +1 -1
  277. package/dist/session/work-item-repository.d.ts.map +1 -1
  278. package/dist/session/work-item-repository.js.map +1 -1
  279. package/dist/skills/service.d.ts +6 -8
  280. package/dist/skills/service.d.ts.map +1 -1
  281. package/dist/skills/service.js +3 -3
  282. package/dist/skills/service.js.map +1 -1
  283. package/dist/storage/domains/audit/agent-audit.d.ts.map +1 -1
  284. package/dist/storage/domains/audit/agent-audit.js +2 -2
  285. package/dist/storage/domains/audit/agent-audit.js.map +1 -1
  286. package/dist/storage/domains/audit/domain.js +1 -1
  287. package/dist/storage/domains/filesystem/base.d.ts +4 -0
  288. package/dist/storage/domains/filesystem/base.d.ts.map +1 -1
  289. package/dist/storage/domains/filesystem/base.js +5 -0
  290. package/dist/storage/domains/filesystem/base.js.map +1 -1
  291. package/dist/storage/domains/integrations/base.d.ts +8 -0
  292. package/dist/storage/domains/integrations/base.d.ts.map +1 -1
  293. package/dist/storage/domains/integrations/base.js +7 -0
  294. package/dist/storage/domains/integrations/base.js.map +1 -1
  295. package/dist/storage/domains/projects/base.d.ts +6 -0
  296. package/dist/storage/domains/projects/base.d.ts.map +1 -1
  297. package/dist/storage/domains/projects/base.js +12 -0
  298. package/dist/storage/domains/projects/base.js.map +1 -1
  299. package/dist/storage/domains/source-control/base.d.ts +28 -0
  300. package/dist/storage/domains/source-control/base.d.ts.map +1 -1
  301. package/dist/storage/domains/source-control/base.js +48 -0
  302. package/dist/storage/domains/source-control/base.js.map +1 -1
  303. package/dist/storage/domains/source-control/inmemory.d.ts +8 -0
  304. package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -1
  305. package/dist/storage/domains/source-control/inmemory.js +13 -1
  306. package/dist/storage/domains/source-control/inmemory.js.map +1 -1
  307. package/dist/storage/domains/work-items/base.d.ts +79 -7
  308. package/dist/storage/domains/work-items/base.d.ts.map +1 -1
  309. package/dist/storage/domains/work-items/base.js +172 -30
  310. package/dist/storage/domains/work-items/base.js.map +1 -1
  311. package/dist/timing.d.ts +23 -0
  312. package/dist/timing.d.ts.map +1 -1
  313. package/dist/timing.js +85 -6
  314. package/dist/timing.js.map +1 -1
  315. package/dist/tools/annotations.d.ts +7 -0
  316. package/dist/tools/annotations.d.ts.map +1 -0
  317. package/dist/tools/annotations.js +102 -0
  318. package/dist/tools/annotations.js.map +1 -0
  319. package/dist/tools/approval-tools.d.ts +15 -0
  320. package/dist/tools/approval-tools.d.ts.map +1 -0
  321. package/dist/tools/approval-tools.js +79 -0
  322. package/dist/tools/approval-tools.js.map +1 -0
  323. package/dist/tools/deliver.d.ts +71 -0
  324. package/dist/tools/deliver.d.ts.map +1 -0
  325. package/dist/tools/deliver.js +129 -0
  326. package/dist/tools/deliver.js.map +1 -0
  327. package/dist/tools/index.d.ts +30 -0
  328. package/dist/tools/index.d.ts.map +1 -0
  329. package/dist/tools/index.js +36 -0
  330. package/dist/tools/index.js.map +1 -0
  331. package/dist/tools/messaging-tools.d.ts +28 -0
  332. package/dist/tools/messaging-tools.d.ts.map +1 -0
  333. package/dist/tools/messaging-tools.js +396 -0
  334. package/dist/tools/messaging-tools.js.map +1 -0
  335. package/dist/tools/permissions.d.ts +31 -0
  336. package/dist/tools/permissions.d.ts.map +1 -0
  337. package/dist/tools/permissions.js +48 -0
  338. package/dist/tools/permissions.js.map +1 -0
  339. package/dist/tools/read-tools.d.ts +30 -0
  340. package/dist/tools/read-tools.d.ts.map +1 -0
  341. package/dist/tools/read-tools.js +293 -0
  342. package/dist/tools/read-tools.js.map +1 -0
  343. package/dist/tools/reports.d.ts +174 -0
  344. package/dist/tools/reports.d.ts.map +1 -0
  345. package/dist/tools/reports.js +380 -0
  346. package/dist/tools/reports.js.map +1 -0
  347. package/dist/tools/run-watch.d.ts +46 -0
  348. package/dist/tools/run-watch.d.ts.map +1 -0
  349. package/dist/tools/run-watch.js +102 -0
  350. package/dist/tools/run-watch.js.map +1 -0
  351. package/dist/tools/scope.d.ts +54 -0
  352. package/dist/tools/scope.d.ts.map +1 -0
  353. package/dist/tools/scope.js +87 -0
  354. package/dist/tools/scope.js.map +1 -0
  355. package/dist/tools/session-tools.d.ts +43 -0
  356. package/dist/tools/session-tools.d.ts.map +1 -0
  357. package/dist/tools/session-tools.js +410 -0
  358. package/dist/tools/session-tools.js.map +1 -0
  359. package/dist/tools/sessions-state-processor.d.ts +41 -0
  360. package/dist/tools/sessions-state-processor.d.ts.map +1 -0
  361. package/dist/tools/sessions-state-processor.js +190 -0
  362. package/dist/tools/sessions-state-processor.js.map +1 -0
  363. package/dist/tools/side-sessions.d.ts +53 -0
  364. package/dist/tools/side-sessions.d.ts.map +1 -0
  365. package/dist/tools/side-sessions.js +83 -0
  366. package/dist/tools/side-sessions.js.map +1 -0
  367. package/dist/tools/work-item-tools.d.ts +28 -0
  368. package/dist/tools/work-item-tools.d.ts.map +1 -0
  369. package/dist/tools/work-item-tools.js +342 -0
  370. package/dist/tools/work-item-tools.js.map +1 -0
  371. package/dist/work-items/create-work-item.d.ts +55 -0
  372. package/dist/work-items/create-work-item.d.ts.map +1 -0
  373. package/dist/work-items/create-work-item.js +101 -0
  374. package/dist/work-items/create-work-item.js.map +1 -0
  375. package/dist/work-items/decision-actions.d.ts +42 -0
  376. package/dist/work-items/decision-actions.d.ts.map +1 -0
  377. package/dist/work-items/decision-actions.js +70 -0
  378. package/dist/work-items/decision-actions.js.map +1 -0
  379. package/dist/workspace.d.ts +1 -1
  380. package/dist/workspace.d.ts.map +1 -1
  381. package/dist/workspace.js +15 -7
  382. package/dist/workspace.js.map +1 -1
  383. package/factory-skills/factory-gitlab-rereview/SKILL.md +1 -1
  384. package/factory-skills/factory-gitlab-review/SKILL.md +1 -1
  385. package/factory-skills/factory-plan/SKILL.md +4 -4
  386. package/factory-skills/factory-rereview/SKILL.md +3 -1
  387. package/factory-skills/factory-review/SKILL.md +3 -1
  388. package/factory-skills/factory-self-review/SKILL.md +46 -0
  389. package/package.json +13 -13
@@ -0,0 +1,342 @@
1
+ import { boardForWorkItem } from "../boards/semantics.js";
2
+ import "../boards/index.js";
3
+ import { WorkItemRelationError } from "../storage/domains/work-items/base.js";
4
+ import { requirePerson } from "./scope.js";
5
+ import { findWorkItem, truncate, workItemNotFound, workItemNumber, workItemRefSchema, workItemStage } from "./read-tools.js";
6
+ import { transitionBodySchema } from "../routes/contracts.js";
7
+ import { resolveWorkItemRepository } from "../session/work-item-repository.js";
8
+ import { createFactoryWorkItem } from "../work-items/create-work-item.js";
9
+ import { dismissFactoryDecision, resolveFactoryProposal, retryFactoryDecision } from "../work-items/decision-actions.js";
10
+ import { randomUUID } from "crypto";
11
+ import { z } from "zod";
12
+ import { createTool } from "@mastra/core/tools";
13
+ //#region src/tools/work-item-tools.ts
14
+ /**
15
+ * Factory tools that change work items: file one, move it, settle its
16
+ * decisions, and follow it. They act as the session's person (a human actor),
17
+ * through the same code the board's routes use.
18
+ */
19
+ const repositorySchema = z.string().trim().min(3).max(200).regex(/^[^/\s]+\/[^/\s]+$/, "Use the owner/name form, e.g. \"mastra-ai/mastra\".").describe("A repository linked to this Factory, as owner/name.");
20
+ const decisionId = z.string().trim().uuid().describe("Decision id, from factory_list_attention or inspect.");
21
+ function briefItem(item) {
22
+ return {
23
+ id: item.id,
24
+ number: workItemNumber(item),
25
+ title: truncate(item.title, 600),
26
+ stage: workItemStage(item)
27
+ };
28
+ }
29
+ function settled(result) {
30
+ if (!result.ok) throw new Error(result.message);
31
+ const { decision } = result;
32
+ return {
33
+ decisionId: decision.id,
34
+ status: decision.status,
35
+ workItemId: decision.workItemId
36
+ };
37
+ }
38
+ /** The work-item write and subscription tools for one user session's turn. */
39
+ function createFactoryWorkItemTools(scope, deps) {
40
+ const project = {
41
+ orgId: scope.orgId,
42
+ factoryProjectId: scope.factoryProjectId
43
+ };
44
+ const audit = async (input) => {
45
+ await deps.auditRecorder.record({
46
+ orgId: scope.orgId,
47
+ actorId: scope.interactive ? scope.userId : `agent:session:${scope.sessionId}`,
48
+ actorType: scope.interactive ? "human" : "agent",
49
+ ...scope.actorProfile ? { actorProfile: scope.actorProfile } : {},
50
+ ...input
51
+ });
52
+ };
53
+ const requireItem = async (ref) => {
54
+ const item = await findWorkItem(deps.workItems, scope, ref);
55
+ if (!item) throw workItemNotFound(ref);
56
+ return item;
57
+ };
58
+ /**
59
+ * Check `slug` is a repository linked to this Factory and that a card with
60
+ * `metadata` would run in it (a card synced from an issue follows the
61
+ * issue's repository, which a slug can't override).
62
+ */
63
+ const requireRepository = async (slug, metadata = null) => {
64
+ const sourceControl = await deps.sessions.getSourceControlBySessionId(scope.sessionId);
65
+ if (!sourceControl) throw new Error("This session has no source-control provider to look repositories up in.");
66
+ const resolve = (repository) => resolveWorkItemRepository({
67
+ sourceControl,
68
+ ...project,
69
+ item: { metadata: repository ? {
70
+ ...metadata,
71
+ repository
72
+ } : metadata }
73
+ });
74
+ const resolution = await resolve(slug);
75
+ if (resolution.status === "resolved" && resolution.slug === slug) return;
76
+ if (resolution.status === "resolved") throw new Error(`This card runs in ${resolution.slug}, which comes from its linked issue and can't be changed.`);
77
+ const linked = await resolve();
78
+ const candidates = linked.status === "ambiguous" ? linked.candidates : linked.status === "resolved" ? [linked.slug] : [];
79
+ throw new Error(candidates.length > 0 ? `${slug} is not linked to this Factory. Linked repositories: ${candidates.join(", ")}.` : `${slug} is not linked to this Factory, and it has no linked repositories.`);
80
+ };
81
+ const follow = (item, reason) => deps.workItems.subscribeToWorkItem({
82
+ ...project,
83
+ workItemId: item.id,
84
+ sessionId: scope.sessionId,
85
+ threadId: scope.threadId,
86
+ resourceId: scope.resourceId,
87
+ userId: scope.userId,
88
+ reason
89
+ });
90
+ return {
91
+ factory_create_work_item: createTool({
92
+ id: "factory_create_work_item",
93
+ description: "File a new work item on this Factory's Work board for the person you are working with. It lands in the board's first phase, exactly like pressing New card, and this session follows it. Check factory_list_work_items for an existing item first. Name the repository when the Factory links more than one; runs refuse to start on a card that doesn't say which.",
94
+ inputSchema: z.object({
95
+ title: z.string().trim().min(1).max(512).describe("Short title, as it should read on the card."),
96
+ brief: z.string().trim().min(1).max(8e3).describe("What needs doing and why; posted as the first comment on the card."),
97
+ repository: repositorySchema.optional()
98
+ }).strict(),
99
+ execute: async ({ title, brief, repository }) => {
100
+ if (repository) await requireRepository(repository);
101
+ const created = await createFactoryWorkItem({
102
+ workItems: deps.workItems,
103
+ boards: deps.boards,
104
+ transitionService: deps.transitionService,
105
+ audit,
106
+ ...project,
107
+ userId: scope.userId,
108
+ ...scope.actorProfile ? { origin: { actorProfile: scope.actorProfile } } : {},
109
+ input: {
110
+ title,
111
+ ...repository ? { metadata: { repository } } : {}
112
+ }
113
+ });
114
+ if (created.status === "refused") throw new Error(created.message);
115
+ if (created.status === "rejected") throw new Error(`The board refused the new item: ${created.reason}`);
116
+ const { item } = created;
117
+ const warnings = [];
118
+ try {
119
+ const comment = await deps.feed.createComment({
120
+ orgId: scope.orgId,
121
+ workItemId: item.id,
122
+ author: {
123
+ kind: "user",
124
+ id: scope.userId
125
+ },
126
+ body: brief
127
+ });
128
+ if (comment.status !== "created") warnings.push(`The brief was not posted (${comment.status === "invalid" ? comment.message : comment.status}).`);
129
+ } catch (error) {
130
+ warnings.push(`The brief was not posted: ${error instanceof Error ? error.message : String(error)}`);
131
+ }
132
+ try {
133
+ await follow(item, "created");
134
+ } catch (error) {
135
+ warnings.push(`This session does not follow it yet: ${error instanceof Error ? error.message : String(error)}`);
136
+ }
137
+ return warnings.length ? {
138
+ ...briefItem(item),
139
+ warnings
140
+ } : briefItem(item);
141
+ }
142
+ }),
143
+ factory_transition_work_item: createTool({
144
+ id: "factory_transition_work_item",
145
+ description: "Move a work item to another stage of its board, as the person you are working with. The board's rules decide whether the move is allowed and what it starts.",
146
+ inputSchema: z.object({
147
+ workItem: workItemRefSchema,
148
+ stage: z.string().trim().min(1).max(64).describe("Destination stage, e.g. \"planning\" or \"done\".")
149
+ }).strict(),
150
+ execute: async ({ workItem, stage }) => {
151
+ if (!deps.transitionService) throw new Error("Factory stage transitions are not available right now.");
152
+ const item = await requireItem(workItem);
153
+ const parsed = transitionBodySchema.safeParse({
154
+ board: boardForWorkItem(item),
155
+ stage,
156
+ expectedRevision: item.revision,
157
+ requestId: randomUUID(),
158
+ cause: "factory_tools"
159
+ });
160
+ if (!parsed.success) throw new Error(`"${stage}" is not a valid stage name.`);
161
+ const result = await deps.transitionService.transition({
162
+ ...parsed.data,
163
+ ...project,
164
+ workItemId: item.id,
165
+ ...scope.interactive ? {
166
+ actor: {
167
+ type: "human",
168
+ id: scope.userId
169
+ },
170
+ ...scope.actorProfile ? { actorProfile: scope.actorProfile } : {},
171
+ ingress: {
172
+ ...parsed.data.ingress,
173
+ identity: `human:${scope.userId}:${parsed.data.ingress.identity}`
174
+ }
175
+ } : {
176
+ actor: {
177
+ type: "agent",
178
+ bindingId: `session:${scope.sessionId}`,
179
+ role: "session"
180
+ },
181
+ ingress: {
182
+ type: "agent",
183
+ identity: `session:${scope.sessionId}:${parsed.data.ingress.identity}`
184
+ }
185
+ }
186
+ });
187
+ if (result.status === "rejected") throw new Error(`The move was refused (${result.code}): ${result.reason}`);
188
+ return {
189
+ workItemId: item.id,
190
+ stage: result.stage,
191
+ revision: result.revision
192
+ };
193
+ }
194
+ }),
195
+ factory_update_work_item: createTool({
196
+ id: "factory_update_work_item",
197
+ description: "Edit a work item's fields as the person you are working with: its title, the repository its runs use, its parent item, or pre-approving its plans. Move stages with factory_transition_work_item and start roles with factory_start_session; post to the card's feed for anything else.",
198
+ inputSchema: z.object({
199
+ workItem: workItemRefSchema,
200
+ title: z.string().trim().min(1).max(500).optional().describe("New card title."),
201
+ repository: repositorySchema.optional(),
202
+ parentWorkItem: workItemRefSchema.nullable().optional().describe("Parent work item (id or #number), or null to detach it from its parent."),
203
+ plansPreapproved: z.literal(true).optional().describe("Pre-approve the item's plans, so its runs no longer stop for plan approval. Can't be undone here.")
204
+ }).strict().refine((input) => Object.keys(input).some((key) => key !== "workItem"), "Pass at least one field to change."),
205
+ execute: async ({ workItem, title, repository, parentWorkItem, plansPreapproved }) => {
206
+ if (plansPreapproved) requirePerson(scope, "pre-approve plans");
207
+ const item = await requireItem(workItem);
208
+ if (repository) await requireRepository(repository, item.metadata);
209
+ let parentWorkItemId;
210
+ if (parentWorkItem === null) parentWorkItemId = null;
211
+ else if (parentWorkItem !== void 0) parentWorkItemId = (await requireItem(parentWorkItem)).id;
212
+ const patch = {
213
+ ...title !== void 0 ? { title } : {},
214
+ ...repository ? { metadata: { repository } } : {},
215
+ ...parentWorkItemId !== void 0 ? { parentWorkItemId } : {},
216
+ ...plansPreapproved ? { plansPreapproved } : {}
217
+ };
218
+ let updated;
219
+ try {
220
+ updated = await deps.workItems.update({
221
+ orgId: scope.orgId,
222
+ id: item.id,
223
+ userId: scope.userId,
224
+ patch
225
+ });
226
+ } catch (error) {
227
+ if (error instanceof WorkItemRelationError) throw new Error(`The parent was refused: ${error.message}`);
228
+ throw error;
229
+ }
230
+ if (!updated) throw workItemNotFound(workItem);
231
+ const fields = [
232
+ ...title !== void 0 ? ["title"] : [],
233
+ ...repository ? ["metadata"] : [],
234
+ ...parentWorkItemId !== void 0 ? ["parentWorkItemId"] : [],
235
+ ...plansPreapproved ? ["plansPreapproved"] : []
236
+ ];
237
+ await audit({
238
+ action: "factory.work_item.updated",
239
+ factoryProjectId: scope.factoryProjectId,
240
+ targets: [{
241
+ type: "work_item",
242
+ id: updated.item.id,
243
+ name: updated.item.title
244
+ }],
245
+ metadata: {
246
+ fields,
247
+ cause: "factory_tools"
248
+ }
249
+ });
250
+ const metadata = updated.item.metadata ?? {};
251
+ return {
252
+ workItem: briefItem(updated.item),
253
+ updated: fields.map((field) => field === "metadata" ? "repository" : field),
254
+ repository: typeof metadata.repository === "string" ? metadata.repository : null,
255
+ parentWorkItemId: updated.item.parentWorkItemId,
256
+ plansPreapproved: updated.item.plansPreapprovedAt !== null
257
+ };
258
+ }
259
+ }),
260
+ factory_retry_decision: createTool({
261
+ id: "factory_retry_decision",
262
+ description: "Retry one failed Factory run once its cause is fixed. Refused when the failure cannot be fixed by retrying or the item has moved on.",
263
+ inputSchema: z.object({ decisionId }).strict(),
264
+ execute: async ({ decisionId }) => settled(await retryFactoryDecision({
265
+ workItems: deps.workItems,
266
+ boards: deps.boards,
267
+ ...project,
268
+ decisionId
269
+ }))
270
+ }),
271
+ factory_dismiss_decision: createTool({
272
+ id: "factory_dismiss_decision",
273
+ description: "Dismiss one proposed Factory run that is no longer wanted.",
274
+ inputSchema: z.object({ decisionId }).strict(),
275
+ execute: async ({ decisionId }) => {
276
+ requirePerson(scope, "dismiss a proposed run");
277
+ return settled(await dismissFactoryDecision({
278
+ workItems: deps.workItems,
279
+ audit,
280
+ ...project,
281
+ userId: scope.userId,
282
+ decisionId
283
+ }));
284
+ }
285
+ }),
286
+ factory_resolve_proposal: createTool({
287
+ id: "factory_resolve_proposal",
288
+ description: "Approve or dismiss one proposed Factory run. Approving starts the run and lets the item's later runs start without asking.",
289
+ inputSchema: z.object({
290
+ decisionId,
291
+ action: z.enum(["approve", "dismiss"])
292
+ }).strict(),
293
+ execute: async ({ decisionId, action }) => {
294
+ requirePerson(scope, "approve or dismiss a proposed run");
295
+ return settled(await resolveFactoryProposal({
296
+ workItems: deps.workItems,
297
+ audit,
298
+ ...project,
299
+ userId: scope.userId,
300
+ decisionId,
301
+ action
302
+ }));
303
+ }
304
+ }),
305
+ factory_subscribe_work_item: createTool({
306
+ id: "factory_subscribe_work_item",
307
+ description: "Follow a work item from this session, so you hear about its progress and its sessions report to you. Items you file or start are followed already.",
308
+ inputSchema: z.object({ workItem: workItemRefSchema }).strict(),
309
+ execute: async ({ workItem }) => {
310
+ const item = await requireItem(workItem);
311
+ const subscription = await follow(item, "subscribed");
312
+ return {
313
+ workItem: briefItem(item),
314
+ subscribed: true,
315
+ reason: subscription.reason
316
+ };
317
+ }
318
+ }),
319
+ factory_unsubscribe_work_item: createTool({
320
+ id: "factory_unsubscribe_work_item",
321
+ description: "Stop following a work item from this session.",
322
+ inputSchema: z.object({ workItem: workItemRefSchema }).strict(),
323
+ execute: async ({ workItem }) => {
324
+ const item = await requireItem(workItem);
325
+ const removed = await deps.workItems.unsubscribeFromWorkItem({
326
+ orgId: scope.orgId,
327
+ workItemId: item.id,
328
+ sessionId: scope.sessionId
329
+ });
330
+ return {
331
+ workItem: briefItem(item),
332
+ subscribed: false,
333
+ wasSubscribed: removed
334
+ };
335
+ }
336
+ })
337
+ };
338
+ }
339
+ //#endregion
340
+ export { createFactoryWorkItemTools };
341
+
342
+ //# sourceMappingURL=work-item-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work-item-tools.js","names":[],"sources":["../../src/tools/work-item-tools.ts"],"sourcesContent":["/**\n * Factory tools that change work items: file one, move it, settle its\n * decisions, and follow it. They act as the session's person (a human actor),\n * through the same code the board's routes use.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { IntegrationTools } from '../integrations/base.js';\nimport { transitionBodySchema } from '../routes/contracts.js';\nimport type { FactoryTransitionService } from '../rules/transition-service.js';\nimport type { SourceControlSessionLookup } from '../session/factory-session.js';\nimport { resolveWorkItemRepository } from '../session/work-item-repository.js';\nimport type { AuditRecorder } from '../storage/domains/audit/domain.js';\nimport type { CommentsDomain } from '../storage/domains/comments/domain.js';\nimport { WorkItemRelationError } from '../storage/domains/work-items/base.js';\nimport type { UpdateWorkItemInput, WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport { createFactoryWorkItem } from '../work-items/create-work-item.js';\nimport type { FactoryAuditEmit } from '../work-items/create-work-item.js';\nimport {\n dismissFactoryDecision,\n resolveFactoryProposal,\n retryFactoryDecision,\n} from '../work-items/decision-actions.js';\nimport type { FactoryDecisionActionResult } from '../work-items/decision-actions.js';\nimport {\n MAX_TEXT,\n findWorkItem,\n workItemRefSchema,\n truncate,\n workItemNotFound,\n workItemNumber,\n workItemStage,\n} from './read-tools.js';\nimport { requirePerson } from './scope.js';\nimport type { FactoryToolScope } from './scope.js';\n\nexport interface FactoryWorkItemToolDependencies {\n workItems: WorkItemsStorage;\n boards: BoardRegistry;\n /** Governed stage moves; filing and moving items refuse while it is unavailable. */\n transitionService: Pick<FactoryTransitionService, 'transition'> | undefined;\n /** Writes audit rows with an explicit actor; tool calls have no HTTP request to read one from. */\n auditRecorder: AuditRecorder;\n /** The feed's front door: validates, touches open boards and mirrors to linked channels. */\n feed: Pick<CommentsDomain, 'createComment'>;\n /** Finds the caller session's source-control provider, whose linked repositories a card can name. */\n sessions: Pick<SourceControlSessionLookup, 'getSourceControlBySessionId'>;\n}\n\nconst repositorySchema = z\n .string()\n .trim()\n .min(3)\n .max(200)\n .regex(/^[^/\\s]+\\/[^/\\s]+$/, 'Use the owner/name form, e.g. \"mastra-ai/mastra\".')\n .describe('A repository linked to this Factory, as owner/name.');\n\nconst decisionId = z.string().trim().uuid().describe('Decision id, from factory_list_attention or inspect.');\n\nfunction briefItem(item: WorkItemRow) {\n return {\n id: item.id,\n number: workItemNumber(item),\n title: truncate(item.title, MAX_TEXT),\n stage: workItemStage(item),\n };\n}\n\nfunction settled(result: FactoryDecisionActionResult) {\n if (!result.ok) throw new Error(result.message);\n const { decision } = result;\n return { decisionId: decision.id, status: decision.status, workItemId: decision.workItemId };\n}\n\n/** The work-item write and subscription tools for one user session's turn. */\nexport function createFactoryWorkItemTools(\n scope: FactoryToolScope,\n deps: FactoryWorkItemToolDependencies,\n): IntegrationTools {\n const project = { orgId: scope.orgId, factoryProjectId: scope.factoryProjectId };\n const audit: FactoryAuditEmit = async input => {\n await deps.auditRecorder.record({\n orgId: scope.orgId,\n // Turns nobody signed in started are recorded as this session's agent, as their moves are.\n actorId: scope.interactive ? scope.userId : `agent:session:${scope.sessionId}`,\n actorType: scope.interactive ? 'human' : 'agent',\n ...(scope.actorProfile ? { actorProfile: scope.actorProfile } : {}),\n ...input,\n });\n };\n const requireItem = async (ref: string) => {\n const item = await findWorkItem(deps.workItems, scope, ref);\n if (!item) throw workItemNotFound(ref);\n return item;\n };\n /**\n * Check `slug` is a repository linked to this Factory and that a card with\n * `metadata` would run in it (a card synced from an issue follows the\n * issue's repository, which a slug can't override).\n */\n const requireRepository = async (slug: string, metadata: Record<string, unknown> | null = null) => {\n const sourceControl = await deps.sessions.getSourceControlBySessionId(scope.sessionId);\n if (!sourceControl) throw new Error('This session has no source-control provider to look repositories up in.');\n const resolve = (repository?: string) =>\n resolveWorkItemRepository({\n sourceControl,\n ...project,\n item: { metadata: repository ? { ...metadata, repository } : metadata },\n });\n const resolution = await resolve(slug);\n if (resolution.status === 'resolved' && resolution.slug === slug) return;\n if (resolution.status === 'resolved') {\n throw new Error(`This card runs in ${resolution.slug}, which comes from its linked issue and can't be changed.`);\n }\n const linked = await resolve();\n const candidates =\n linked.status === 'ambiguous' ? linked.candidates : linked.status === 'resolved' ? [linked.slug] : [];\n throw new Error(\n candidates.length > 0\n ? `${slug} is not linked to this Factory. Linked repositories: ${candidates.join(', ')}.`\n : `${slug} is not linked to this Factory, and it has no linked repositories.`,\n );\n };\n const follow = (item: WorkItemRow, reason: 'created' | 'subscribed') =>\n deps.workItems.subscribeToWorkItem({\n ...project,\n workItemId: item.id,\n sessionId: scope.sessionId,\n threadId: scope.threadId,\n resourceId: scope.resourceId,\n userId: scope.userId,\n reason,\n });\n\n return {\n factory_create_work_item: createTool({\n id: 'factory_create_work_item',\n description:\n \"File a new work item on this Factory's Work board for the person you are working with. It lands in the board's first phase, exactly like pressing New card, and this session follows it. Check factory_list_work_items for an existing item first. Name the repository when the Factory links more than one; runs refuse to start on a card that doesn't say which.\",\n inputSchema: z\n .object({\n title: z.string().trim().min(1).max(512).describe('Short title, as it should read on the card.'),\n brief: z\n .string()\n .trim()\n .min(1)\n .max(8000)\n .describe('What needs doing and why; posted as the first comment on the card.'),\n repository: repositorySchema.optional(),\n })\n .strict(),\n execute: async ({ title, brief, repository }) => {\n if (repository) await requireRepository(repository);\n const created = await createFactoryWorkItem({\n workItems: deps.workItems,\n boards: deps.boards,\n transitionService: deps.transitionService,\n audit,\n ...project,\n userId: scope.userId,\n ...(scope.actorProfile ? { origin: { actorProfile: scope.actorProfile } } : {}),\n input: { title, ...(repository ? { metadata: { repository } } : {}) },\n });\n if (created.status === 'refused') throw new Error(created.message);\n if (created.status === 'rejected') throw new Error(`The board refused the new item: ${created.reason}`);\n const { item } = created;\n // The card exists from here on: report follow-up failures alongside it\n // rather than failing the call, so the agent doesn't file it twice.\n const warnings: string[] = [];\n try {\n const comment = await deps.feed.createComment({\n orgId: scope.orgId,\n workItemId: item.id,\n author: { kind: 'user', id: scope.userId },\n body: brief,\n });\n if (comment.status !== 'created') {\n warnings.push(\n `The brief was not posted (${comment.status === 'invalid' ? comment.message : comment.status}).`,\n );\n }\n } catch (error) {\n warnings.push(`The brief was not posted: ${error instanceof Error ? error.message : String(error)}`);\n }\n try {\n await follow(item, 'created');\n } catch (error) {\n warnings.push(\n `This session does not follow it yet: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n return warnings.length ? { ...briefItem(item), warnings } : briefItem(item);\n },\n }),\n\n factory_transition_work_item: createTool({\n id: 'factory_transition_work_item',\n description:\n \"Move a work item to another stage of its board, as the person you are working with. The board's rules decide whether the move is allowed and what it starts.\",\n inputSchema: z\n .object({\n workItem: workItemRefSchema,\n stage: z.string().trim().min(1).max(64).describe('Destination stage, e.g. \"planning\" or \"done\".'),\n })\n .strict(),\n execute: async ({ workItem, stage }) => {\n if (!deps.transitionService) throw new Error('Factory stage transitions are not available right now.');\n const item = await requireItem(workItem);\n const parsed = transitionBodySchema.safeParse({\n board: boardForWorkItem(item),\n stage,\n expectedRevision: item.revision,\n requestId: randomUUID(),\n cause: 'factory_tools',\n });\n if (!parsed.success) throw new Error(`\"${stage}\" is not a valid stage name.`);\n const result = await deps.transitionService.transition({\n ...parsed.data,\n ...project,\n workItemId: item.id,\n ...(scope.interactive\n ? {\n actor: { type: 'human' as const, id: scope.userId },\n ...(scope.actorProfile ? { actorProfile: scope.actorProfile } : {}),\n ingress: { ...parsed.data.ingress, identity: `human:${scope.userId}:${parsed.data.ingress.identity}` },\n }\n : {\n // Nobody signed in started this turn: move as this session's agent, so the\n // plan gate and the agent's done gates apply and the move arms no runs.\n actor: { type: 'agent' as const, bindingId: `session:${scope.sessionId}`, role: 'session' },\n ingress: {\n type: 'agent' as const,\n identity: `session:${scope.sessionId}:${parsed.data.ingress.identity}`,\n },\n }),\n });\n if (result.status === 'rejected') throw new Error(`The move was refused (${result.code}): ${result.reason}`);\n return { workItemId: item.id, stage: result.stage, revision: result.revision };\n },\n }),\n\n factory_update_work_item: createTool({\n id: 'factory_update_work_item',\n description:\n \"Edit a work item's fields as the person you are working with: its title, the repository its runs use, its parent item, or pre-approving its plans. Move stages with factory_transition_work_item and start roles with factory_start_session; post to the card's feed for anything else.\",\n inputSchema: z\n .object({\n workItem: workItemRefSchema,\n title: z.string().trim().min(1).max(500).optional().describe('New card title.'),\n repository: repositorySchema.optional(),\n parentWorkItem: workItemRefSchema\n .nullable()\n .optional()\n .describe('Parent work item (id or #number), or null to detach it from its parent.'),\n plansPreapproved: z\n .literal(true)\n .optional()\n .describe(\n \"Pre-approve the item's plans, so its runs no longer stop for plan approval. Can't be undone here.\",\n ),\n })\n .strict()\n .refine(input => Object.keys(input).some(key => key !== 'workItem'), 'Pass at least one field to change.'),\n execute: async ({ workItem, title, repository, parentWorkItem, plansPreapproved }) => {\n // Pre-approval drops the plan-approval gate for good, so it is the person's call.\n if (plansPreapproved) requirePerson(scope, 'pre-approve plans');\n const item = await requireItem(workItem);\n if (repository) await requireRepository(repository, item.metadata);\n let parentWorkItemId: string | null | undefined;\n if (parentWorkItem === null) parentWorkItemId = null;\n else if (parentWorkItem !== undefined) parentWorkItemId = (await requireItem(parentWorkItem)).id;\n const patch: UpdateWorkItemInput = {\n ...(title !== undefined ? { title } : {}),\n ...(repository ? { metadata: { repository } } : {}),\n ...(parentWorkItemId !== undefined ? { parentWorkItemId } : {}),\n ...(plansPreapproved ? { plansPreapproved } : {}),\n };\n let updated: Awaited<ReturnType<WorkItemsStorage['update']>>;\n try {\n updated = await deps.workItems.update({ orgId: scope.orgId, id: item.id, userId: scope.userId, patch });\n } catch (error) {\n if (error instanceof WorkItemRelationError) throw new Error(`The parent was refused: ${error.message}`);\n throw error;\n }\n if (!updated) throw workItemNotFound(workItem);\n const fields = [\n ...(title !== undefined ? ['title'] : []),\n ...(repository ? ['metadata'] : []),\n ...(parentWorkItemId !== undefined ? ['parentWorkItemId'] : []),\n ...(plansPreapproved ? ['plansPreapproved'] : []),\n ];\n await audit({\n action: 'factory.work_item.updated',\n factoryProjectId: scope.factoryProjectId,\n targets: [{ type: 'work_item', id: updated.item.id, name: updated.item.title }],\n metadata: { fields, cause: 'factory_tools' },\n });\n const metadata = updated.item.metadata ?? {};\n return {\n workItem: briefItem(updated.item),\n updated: fields.map(field => (field === 'metadata' ? 'repository' : field)),\n repository: typeof metadata.repository === 'string' ? metadata.repository : null,\n parentWorkItemId: updated.item.parentWorkItemId,\n plansPreapproved: updated.item.plansPreapprovedAt !== null,\n };\n },\n }),\n\n factory_retry_decision: createTool({\n id: 'factory_retry_decision',\n description:\n 'Retry one failed Factory run once its cause is fixed. Refused when the failure cannot be fixed by retrying or the item has moved on.',\n inputSchema: z.object({ decisionId }).strict(),\n execute: async ({ decisionId }) =>\n settled(await retryFactoryDecision({ workItems: deps.workItems, boards: deps.boards, ...project, decisionId })),\n }),\n\n factory_dismiss_decision: createTool({\n id: 'factory_dismiss_decision',\n description: 'Dismiss one proposed Factory run that is no longer wanted.',\n inputSchema: z.object({ decisionId }).strict(),\n execute: async ({ decisionId }) => {\n requirePerson(scope, 'dismiss a proposed run');\n return settled(\n await dismissFactoryDecision({\n workItems: deps.workItems,\n audit,\n ...project,\n userId: scope.userId,\n decisionId,\n }),\n );\n },\n }),\n\n factory_resolve_proposal: createTool({\n id: 'factory_resolve_proposal',\n description:\n \"Approve or dismiss one proposed Factory run. Approving starts the run and lets the item's later runs start without asking.\",\n inputSchema: z.object({ decisionId, action: z.enum(['approve', 'dismiss']) }).strict(),\n execute: async ({ decisionId, action }) => {\n requirePerson(scope, 'approve or dismiss a proposed run');\n return settled(\n await resolveFactoryProposal({\n workItems: deps.workItems,\n audit,\n ...project,\n userId: scope.userId,\n decisionId,\n action,\n }),\n );\n },\n }),\n\n factory_subscribe_work_item: createTool({\n id: 'factory_subscribe_work_item',\n description:\n 'Follow a work item from this session, so you hear about its progress and its sessions report to you. Items you file or start are followed already.',\n inputSchema: z.object({ workItem: workItemRefSchema }).strict(),\n execute: async ({ workItem }) => {\n const item = await requireItem(workItem);\n const subscription = await follow(item, 'subscribed');\n return { workItem: briefItem(item), subscribed: true, reason: subscription.reason };\n },\n }),\n\n factory_unsubscribe_work_item: createTool({\n id: 'factory_unsubscribe_work_item',\n description: 'Stop following a work item from this session.',\n inputSchema: z.object({ workItem: workItemRefSchema }).strict(),\n execute: async ({ workItem }) => {\n const item = await requireItem(workItem);\n const removed = await deps.workItems.unsubscribeFromWorkItem({\n orgId: scope.orgId,\n workItemId: item.id,\n sessionId: scope.sessionId,\n });\n return { workItem: briefItem(item), subscribed: false, wasSubscribed: removed };\n },\n }),\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Filing a work item, shared by the board's create route and the Factory tools
3
+ * so a card filed from a session goes through exactly what "New card" does.
4
+ */
5
+ import type { BoardRegistry } from '../boards/index.js';
6
+ import type { FactoryTransitionRequest, FactoryTransitionService } from '../rules/transition-service.js';
7
+ import type { EmitAuditInput } from '../storage/domains/audit/domain.js';
8
+ import type { CreateWorkItemInput, WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';
9
+ /** Records one audit event for the caller; routes bind it to the request, tools to the session's person. */
10
+ export type FactoryAuditEmit = (input: EmitAuditInput) => Promise<void>;
11
+ type TransitionResult = Awaited<ReturnType<FactoryTransitionService['transition']>>;
12
+ export type CreateFactoryWorkItemResult =
13
+ /** A new card, entered into its board's first phase and audited. */
14
+ {
15
+ status: 'created';
16
+ item: WorkItemRow;
17
+ }
18
+ /** The source key matched an existing card, which was updated instead (the caller audits the patch). */
19
+ | {
20
+ status: 'reused';
21
+ item: WorkItemRow;
22
+ } | {
23
+ status: 'refused';
24
+ code: 'invalid_board' | 'governed_transition_required' | 'factory_transitions_unavailable';
25
+ message: string;
26
+ }
27
+ /** The first phase's entry rules refused the card; it was removed again. */
28
+ | {
29
+ status: 'rejected';
30
+ code: Extract<TransitionResult, {
31
+ status: 'rejected';
32
+ }>['code'];
33
+ reason: string;
34
+ };
35
+ export interface CreateFactoryWorkItemArgs {
36
+ workItems: WorkItemsStorage;
37
+ boards: BoardRegistry;
38
+ transitionService: Pick<FactoryTransitionService, 'transition'> | undefined;
39
+ audit: FactoryAuditEmit;
40
+ orgId: string;
41
+ /** Who files the card; becomes its `created_by` and the human actor of its first phase entry. */
42
+ userId: string;
43
+ factoryProjectId: string;
44
+ input: CreateWorkItemInput;
45
+ /** Where a browser request came from; a session's tool call carries none. */
46
+ origin?: Pick<FactoryTransitionRequest, 'actorProfile' | 'context'>;
47
+ }
48
+ /**
49
+ * Upserts the card into its board's first phase, enters that phase as the
50
+ * person (rolling the card back if its entry rules refuse it), then audits
51
+ * `factory.work_item.created`. Throws `WorkItemRelationError` for a bad parent.
52
+ */
53
+ export declare function createFactoryWorkItem({ workItems, boards, transitionService, audit, orgId, userId, factoryProjectId, input, origin, }: CreateFactoryWorkItemArgs): Promise<CreateFactoryWorkItemResult>;
54
+ export {};
55
+ //# sourceMappingURL=create-work-item.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-work-item.d.ts","sourceRoot":"","sources":["../../src/work-items/create-work-item.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AACzG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAEhH,4GAA4G;AAC5G,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAExE,KAAK,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,wBAAwB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAEpF,MAAM,MAAM,2BAA2B;AACrC,oEAAoE;AAClE;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE;AAC1C,wGAAwG;GACtG;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GACvC;IACE,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,EAAE,eAAe,GAAG,8BAA8B,GAAG,iCAAiC,CAAC;IAC3F,OAAO,EAAE,MAAM,CAAC;CACjB;AACH,4EAA4E;GAC1E;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,gBAAgB,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5G,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,gBAAgB,CAAC;IAC5B,MAAM,EAAE,aAAa,CAAC;IACtB,iBAAiB,EAAE,IAAI,CAAC,wBAAwB,EAAE,YAAY,CAAC,GAAG,SAAS,CAAC;IAC5E,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,iGAAiG;IACjG,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,6EAA6E;IAC7E,MAAM,CAAC,EAAE,IAAI,CAAC,wBAAwB,EAAE,cAAc,GAAG,SAAS,CAAC,CAAC;CACrE;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,EAC1C,SAAS,EACT,MAAM,EACN,iBAAiB,EACjB,KAAK,EACL,KAAK,EACL,MAAM,EACN,gBAAgB,EAChB,KAAK,EACL,MAAM,GACP,EAAE,yBAAyB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAyDlE"}
@@ -0,0 +1,101 @@
1
+ //#region src/work-items/create-work-item.ts
2
+ /**
3
+ * Upserts the card into its board's first phase, enters that phase as the
4
+ * person (rolling the card back if its entry rules refuse it), then audits
5
+ * `factory.work_item.created`. Throws `WorkItemRelationError` for a bad parent.
6
+ */
7
+ async function createFactoryWorkItem({ workItems, boards, transitionService, audit, orgId, userId, factoryProjectId, input, origin }) {
8
+ const boardId = input.board ?? (input.externalSource?.type === "pull-request" ? "review" : "work");
9
+ const board = boards.get(boardId);
10
+ if (!board) return {
11
+ status: "refused",
12
+ code: "invalid_board",
13
+ message: `Board '${boardId}' is not installed.`
14
+ };
15
+ const initialStages = input.stages ?? [board.initialPhase];
16
+ if (initialStages.length !== 1 || initialStages[0] !== board.initialPhase) return {
17
+ status: "refused",
18
+ code: "governed_transition_required",
19
+ message: `New work items must enter through the '${board.initialPhase}' phase of board '${boardId}'.`
20
+ };
21
+ await workItems.ensureReady();
22
+ const result = await workItems.upsert({
23
+ orgId,
24
+ userId,
25
+ factoryProjectId,
26
+ input: {
27
+ ...input,
28
+ board: boardId,
29
+ stages: initialStages
30
+ },
31
+ reuseMode: "non-stage"
32
+ });
33
+ if (!result.created) return {
34
+ status: "reused",
35
+ item: result.item
36
+ };
37
+ const created = result.item;
38
+ if (!transitionService) {
39
+ await workItems.delete({
40
+ orgId,
41
+ id: created.id
42
+ });
43
+ return {
44
+ status: "refused",
45
+ code: "factory_transitions_unavailable",
46
+ message: "Factory stage transitions are not available right now."
47
+ };
48
+ }
49
+ const entered = await transitionService.transition({
50
+ orgId,
51
+ factoryProjectId,
52
+ workItemId: created.id,
53
+ board: boardId,
54
+ stage: board.initialPhase,
55
+ expectedRevision: created.revision,
56
+ actor: {
57
+ type: "human",
58
+ id: userId
59
+ },
60
+ ...origin,
61
+ ingress: {
62
+ type: "human",
63
+ identity: `work-item:${created.id}:initial-entry`
64
+ },
65
+ cause: "work_item_created",
66
+ initialEntry: true
67
+ });
68
+ if (entered.status === "rejected") {
69
+ await workItems.delete({
70
+ orgId,
71
+ id: created.id
72
+ });
73
+ return {
74
+ status: "rejected",
75
+ code: entered.code,
76
+ reason: entered.reason
77
+ };
78
+ }
79
+ const item = await workItems.getForProject(orgId, factoryProjectId, created.id) ?? created;
80
+ await audit({
81
+ action: "factory.work_item.created",
82
+ factoryProjectId,
83
+ targets: [{
84
+ type: "work_item",
85
+ id: item.id,
86
+ name: item.title
87
+ }],
88
+ metadata: {
89
+ externalSource: item.externalSource,
90
+ stages: item.stages
91
+ }
92
+ });
93
+ return {
94
+ status: "created",
95
+ item
96
+ };
97
+ }
98
+ //#endregion
99
+ export { createFactoryWorkItem };
100
+
101
+ //# sourceMappingURL=create-work-item.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-work-item.js","names":[],"sources":["../../src/work-items/create-work-item.ts"],"sourcesContent":["/**\n * Filing a work item, shared by the board's create route and the Factory tools\n * so a card filed from a session goes through exactly what \"New card\" does.\n */\n\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { FactoryTransitionRequest, FactoryTransitionService } from '../rules/transition-service.js';\nimport type { EmitAuditInput } from '../storage/domains/audit/domain.js';\nimport type { CreateWorkItemInput, WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';\n\n/** Records one audit event for the caller; routes bind it to the request, tools to the session's person. */\nexport type FactoryAuditEmit = (input: EmitAuditInput) => Promise<void>;\n\ntype TransitionResult = Awaited<ReturnType<FactoryTransitionService['transition']>>;\n\nexport type CreateFactoryWorkItemResult =\n /** A new card, entered into its board's first phase and audited. */\n | { status: 'created'; item: WorkItemRow }\n /** The source key matched an existing card, which was updated instead (the caller audits the patch). */\n | { status: 'reused'; item: WorkItemRow }\n | {\n status: 'refused';\n code: 'invalid_board' | 'governed_transition_required' | 'factory_transitions_unavailable';\n message: string;\n }\n /** The first phase's entry rules refused the card; it was removed again. */\n | { status: 'rejected'; code: Extract<TransitionResult, { status: 'rejected' }>['code']; reason: string };\n\nexport interface CreateFactoryWorkItemArgs {\n workItems: WorkItemsStorage;\n boards: BoardRegistry;\n transitionService: Pick<FactoryTransitionService, 'transition'> | undefined;\n audit: FactoryAuditEmit;\n orgId: string;\n /** Who files the card; becomes its `created_by` and the human actor of its first phase entry. */\n userId: string;\n factoryProjectId: string;\n input: CreateWorkItemInput;\n /** Where a browser request came from; a session's tool call carries none. */\n origin?: Pick<FactoryTransitionRequest, 'actorProfile' | 'context'>;\n}\n\n/**\n * Upserts the card into its board's first phase, enters that phase as the\n * person (rolling the card back if its entry rules refuse it), then audits\n * `factory.work_item.created`. Throws `WorkItemRelationError` for a bad parent.\n */\nexport async function createFactoryWorkItem({\n workItems,\n boards,\n transitionService,\n audit,\n orgId,\n userId,\n factoryProjectId,\n input,\n origin,\n}: CreateFactoryWorkItemArgs): Promise<CreateFactoryWorkItemResult> {\n const boardId = input.board ?? (input.externalSource?.type === 'pull-request' ? 'review' : 'work');\n const board = boards.get(boardId);\n if (!board) return { status: 'refused', code: 'invalid_board', message: `Board '${boardId}' is not installed.` };\n const initialStages = input.stages ?? [board.initialPhase];\n if (initialStages.length !== 1 || initialStages[0] !== board.initialPhase) {\n return {\n status: 'refused',\n code: 'governed_transition_required',\n message: `New work items must enter through the '${board.initialPhase}' phase of board '${boardId}'.`,\n };\n }\n\n await workItems.ensureReady();\n const result = await workItems.upsert({\n orgId,\n userId,\n factoryProjectId,\n input: { ...input, board: boardId, stages: initialStages },\n reuseMode: 'non-stage',\n });\n if (!result.created) return { status: 'reused', item: result.item };\n\n const created = result.item;\n if (!transitionService) {\n await workItems.delete({ orgId, id: created.id });\n return {\n status: 'refused',\n code: 'factory_transitions_unavailable',\n message: 'Factory stage transitions are not available right now.',\n };\n }\n const entered = await transitionService.transition({\n orgId,\n factoryProjectId,\n workItemId: created.id,\n board: boardId,\n stage: board.initialPhase,\n expectedRevision: created.revision,\n actor: { type: 'human', id: userId },\n ...origin,\n ingress: { type: 'human', identity: `work-item:${created.id}:initial-entry` },\n cause: 'work_item_created',\n initialEntry: true,\n });\n if (entered.status === 'rejected') {\n await workItems.delete({ orgId, id: created.id });\n return { status: 'rejected', code: entered.code, reason: entered.reason };\n }\n const item = (await workItems.getForProject(orgId, factoryProjectId, created.id)) ?? created;\n await audit({\n action: 'factory.work_item.created',\n factoryProjectId,\n targets: [{ type: 'work_item', id: item.id, name: item.title }],\n metadata: { externalSource: item.externalSource, stages: item.stages },\n });\n return { status: 'created', item };\n}\n"],"mappings":";;;;;;AA+CA,eAAsB,sBAAsB,EAC1C,WACA,QACA,mBACA,OACA,OACA,QACA,kBACA,OACA,UACkE;CAClE,MAAM,UAAU,MAAM,UAAU,MAAM,gBAAgB,SAAS,iBAAiB,WAAW;CAC3F,MAAM,QAAQ,OAAO,IAAI,OAAO;CAChC,IAAI,CAAC,OAAO,OAAO;EAAE,QAAQ;EAAW,MAAM;EAAiB,SAAS,UAAU,QAAQ;CAAqB;CAC/G,MAAM,gBAAgB,MAAM,UAAU,CAAC,MAAM,YAAY;CACzD,IAAI,cAAc,WAAW,KAAK,cAAc,OAAO,MAAM,cAC3D,OAAO;EACL,QAAQ;EACR,MAAM;EACN,SAAS,0CAA0C,MAAM,aAAa,oBAAoB,QAAQ;CACpG;CAGF,MAAM,UAAU,YAAY;CAC5B,MAAM,SAAS,MAAM,UAAU,OAAO;EACpC;EACA;EACA;EACA,OAAO;GAAE,GAAG;GAAO,OAAO;GAAS,QAAQ;EAAc;EACzD,WAAW;CACb,CAAC;CACD,IAAI,CAAC,OAAO,SAAS,OAAO;EAAE,QAAQ;EAAU,MAAM,OAAO;CAAK;CAElE,MAAM,UAAU,OAAO;CACvB,IAAI,CAAC,mBAAmB;EACtB,MAAM,UAAU,OAAO;GAAE;GAAO,IAAI,QAAQ;EAAG,CAAC;EAChD,OAAO;GACL,QAAQ;GACR,MAAM;GACN,SAAS;EACX;CACF;CACA,MAAM,UAAU,MAAM,kBAAkB,WAAW;EACjD;EACA;EACA,YAAY,QAAQ;EACpB,OAAO;EACP,OAAO,MAAM;EACb,kBAAkB,QAAQ;EAC1B,OAAO;GAAE,MAAM;GAAS,IAAI;EAAO;EACnC,GAAG;EACH,SAAS;GAAE,MAAM;GAAS,UAAU,aAAa,QAAQ,GAAG;EAAgB;EAC5E,OAAO;EACP,cAAc;CAChB,CAAC;CACD,IAAI,QAAQ,WAAW,YAAY;EACjC,MAAM,UAAU,OAAO;GAAE;GAAO,IAAI,QAAQ;EAAG,CAAC;EAChD,OAAO;GAAE,QAAQ;GAAY,MAAM,QAAQ;GAAM,QAAQ,QAAQ;EAAO;CAC1E;CACA,MAAM,OAAQ,MAAM,UAAU,cAAc,OAAO,kBAAkB,QAAQ,EAAE,KAAM;CACrF,MAAM,MAAM;EACV,QAAQ;EACR;EACA,SAAS,CAAC;GAAE,MAAM;GAAa,IAAI,KAAK;GAAI,MAAM,KAAK;EAAM,CAAC;EAC9D,UAAU;GAAE,gBAAgB,KAAK;GAAgB,QAAQ,KAAK;EAAO;CACvE,CAAC;CACD,OAAO;EAAE,QAAQ;EAAW;CAAK;AACnC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Retrying, approving and dismissing Factory decisions, shared by the board's
3
+ * routes and the Factory tools so both refuse and audit the same way.
4
+ */
5
+ import type { BoardRegistry } from '../boards/index.js';
6
+ import type { FactoryDeferredDecisionRecord, WorkItemsStorage } from '../storage/domains/work-items/base.js';
7
+ import type { FactoryAuditEmit } from './create-work-item.js';
8
+ export type FactoryDecisionActionResult = {
9
+ ok: true;
10
+ decision: FactoryDeferredDecisionRecord;
11
+ } | {
12
+ ok: false;
13
+ code: 'decision_not_retryable' | 'decision_not_proposed';
14
+ message: string;
15
+ };
16
+ interface DecisionActionArgs {
17
+ workItems: WorkItemsStorage;
18
+ orgId: string;
19
+ factoryProjectId: string;
20
+ decisionId: string;
21
+ }
22
+ /** Re-queue a failed run, unless its failure can't be fixed by retrying or the card has left the run's phase. */
23
+ export declare function retryFactoryDecision({ workItems, boards, orgId, factoryProjectId, decisionId, }: DecisionActionArgs & {
24
+ boards: BoardRegistry;
25
+ }): Promise<FactoryDecisionActionResult>;
26
+ /**
27
+ * Release (approve) or drop (dismiss) a parked proposal as `userId`, audited as
28
+ * consent. Approval arms the item's autonomy inside the same storage
29
+ * transaction (see approveDeferredDecision), so follow-up runs no longer wait.
30
+ */
31
+ export declare function resolveFactoryProposal({ workItems, audit, orgId, factoryProjectId, userId, decisionId, action, }: DecisionActionArgs & {
32
+ audit: FactoryAuditEmit;
33
+ userId: string;
34
+ action: 'approve' | 'dismiss';
35
+ }): Promise<FactoryDecisionActionResult>;
36
+ /** Drop a parked proposal; the same as dismissing it through {@link resolveFactoryProposal}. */
37
+ export declare function dismissFactoryDecision(args: DecisionActionArgs & {
38
+ audit: FactoryAuditEmit;
39
+ userId: string;
40
+ }): Promise<FactoryDecisionActionResult>;
41
+ export {};
42
+ //# sourceMappingURL=decision-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-actions.d.ts","sourceRoot":"","sources":["../../src/work-items/decision-actions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD,OAAO,KAAK,EAAE,6BAA6B,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC7G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,MAAM,2BAA2B,GACnC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,6BAA6B,CAAA;CAAE,GACrD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,wBAAwB,GAAG,uBAAuB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7F,UAAU,kBAAkB;IAC1B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAQD,iHAAiH;AACjH,wBAAsB,oBAAoB,CAAC,EACzC,SAAS,EACT,MAAM,EACN,KAAK,EACL,gBAAgB,EAChB,UAAU,GACX,EAAE,kBAAkB,GAAG;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAevF;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,EAC3C,SAAS,EACT,KAAK,EACL,KAAK,EACL,gBAAgB,EAChB,MAAM,EACN,UAAU,EACV,MAAM,GACP,EAAE,kBAAkB,GAAG;IACtB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;CAC/B,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAuBvC;AAED,gGAAgG;AAChG,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,kBAAkB,GAAG;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrE,OAAO,CAAC,2BAA2B,CAAC,CAEtC"}