@vercel/factory 0.0.14 → 0.0.15

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 (467) hide show
  1. package/README.md +306 -0
  2. package/dist/agent-routes.d.mts +69 -0
  3. package/dist/agent-routes.mjs +64 -0
  4. package/dist/agent-routes.mjs.map +1 -0
  5. package/dist/api-contracts.d.mts +1749 -0
  6. package/dist/api-contracts.mjs +118 -0
  7. package/dist/api-contracts.mjs.map +1 -0
  8. package/dist/api-images.d.mts +30 -0
  9. package/dist/api-images.mjs +28 -0
  10. package/dist/api-images.mjs.map +1 -0
  11. package/dist/api-task-graph.mjs +57 -0
  12. package/dist/api-task-graph.mjs.map +1 -0
  13. package/dist/api.d.mts +68 -216
  14. package/dist/api.mjs +872 -97
  15. package/dist/api.mjs.map +1 -1
  16. package/dist/approval-access.d.mts +39 -0
  17. package/dist/approval-access.mjs +62 -0
  18. package/dist/approval-access.mjs.map +1 -0
  19. package/dist/approval-contracts.d.mts +692 -0
  20. package/dist/approval-contracts.mjs +27 -0
  21. package/dist/approval-contracts.mjs.map +1 -0
  22. package/dist/approval.d.mts +49 -0
  23. package/dist/approval.mjs +39 -0
  24. package/dist/approval.mjs.map +1 -0
  25. package/dist/blob/artifacts.d.mts +37 -0
  26. package/dist/blob/artifacts.mjs +45 -0
  27. package/dist/blob/artifacts.mjs.map +1 -0
  28. package/dist/blob/index.d.mts +41 -6
  29. package/dist/blob/index.mjs +158 -40
  30. package/dist/blob/index.mjs.map +1 -1
  31. package/dist/budget.d.mts +108 -0
  32. package/dist/budget.mjs +141 -0
  33. package/dist/budget.mjs.map +1 -0
  34. package/dist/budgets.d.mts +4 -0
  35. package/dist/budgets.mjs +4 -0
  36. package/dist/build-factory.d.mts +6 -4
  37. package/dist/build-factory.mjs +2 -1
  38. package/dist/build-factory.mjs.map +1 -1
  39. package/dist/change-verification/brief.d.mts +9 -0
  40. package/dist/change-verification/brief.mjs +13 -0
  41. package/dist/change-verification/brief.mjs.map +1 -0
  42. package/dist/change-verification/dispatch.d.mts +24 -0
  43. package/dist/change-verification/dispatch.mjs +45 -0
  44. package/dist/change-verification/dispatch.mjs.map +1 -0
  45. package/dist/change-verification/eve-tool.d.mts +60 -0
  46. package/dist/change-verification/eve-tool.mjs +101 -0
  47. package/dist/change-verification/eve-tool.mjs.map +1 -0
  48. package/dist/changes/eve-record-change.d.mts +56 -0
  49. package/dist/changes/eve-record-change.mjs +97 -0
  50. package/dist/changes/eve-record-change.mjs.map +1 -0
  51. package/dist/changes/presentation.d.mts +14 -0
  52. package/dist/changes.d.mts +23 -0
  53. package/dist/changes.mjs +29 -0
  54. package/dist/changes.mjs.map +1 -0
  55. package/dist/client-events.d.mts +18 -0
  56. package/dist/client-events.mjs +41 -0
  57. package/dist/client-events.mjs.map +1 -0
  58. package/dist/client-stream.d.mts +28 -0
  59. package/dist/client-stream.mjs +204 -0
  60. package/dist/client-stream.mjs.map +1 -0
  61. package/dist/client-transcript.d.mts +41 -0
  62. package/dist/client-transcript.mjs +229 -0
  63. package/dist/client-transcript.mjs.map +1 -0
  64. package/dist/client.d.mts +234 -0
  65. package/dist/client.mjs +258 -0
  66. package/dist/client.mjs.map +1 -0
  67. package/dist/code-review/contracts.d.mts +26 -0
  68. package/dist/code-review/eve-post-review.d.mts +70 -0
  69. package/dist/code-review/eve-post-review.mjs +183 -0
  70. package/dist/code-review/eve-post-review.mjs.map +1 -0
  71. package/dist/code-review/eve-review-comments.d.mts +64 -0
  72. package/dist/code-review/eve-review-comments.mjs +159 -0
  73. package/dist/code-review/eve-review-comments.mjs.map +1 -0
  74. package/dist/code-review/github-contracts.d.mts +10 -0
  75. package/dist/code-review/github-reporter.d.mts +44 -0
  76. package/dist/code-review/github-reporter.mjs +260 -0
  77. package/dist/code-review/github-reporter.mjs.map +1 -0
  78. package/dist/code-review/preparation.d.mts +34 -0
  79. package/dist/code-review/preparation.mjs +23 -0
  80. package/dist/code-review/preparation.mjs.map +1 -0
  81. package/dist/code-review/stall.d.mts +17 -0
  82. package/dist/code-review/stall.mjs +30 -0
  83. package/dist/code-review/stall.mjs.map +1 -0
  84. package/dist/code-review.d.mts +6 -0
  85. package/dist/code-review.mjs +5 -0
  86. package/dist/communication.d.mts +9 -0
  87. package/dist/communication.mjs +9 -0
  88. package/dist/connectors/github.d.mts +26 -0
  89. package/dist/connectors/github.mjs +55 -0
  90. package/dist/connectors/github.mjs.map +1 -0
  91. package/dist/connectors/index.d.mts +35 -3
  92. package/dist/connectors/index.mjs +3 -52
  93. package/dist/connectors/index.mjs.map +1 -1
  94. package/dist/connectors/outbox.d.mts +34 -0
  95. package/dist/connectors/outbox.mjs +50 -0
  96. package/dist/connectors/outbox.mjs.map +1 -0
  97. package/dist/connectors/slack-approval-blocks.mjs +136 -0
  98. package/dist/connectors/slack-approval-blocks.mjs.map +1 -0
  99. package/dist/connectors/slack-approvals.d.mts +29 -0
  100. package/dist/connectors/slack-approvals.mjs +346 -0
  101. package/dist/connectors/slack-approvals.mjs.map +1 -0
  102. package/dist/connectors/slack.d.mts +35 -52
  103. package/dist/connectors/slack.mjs +13 -85
  104. package/dist/connectors/slack.mjs.map +1 -1
  105. package/dist/deepsec/eve-tool.d.mts +110 -0
  106. package/dist/deepsec/eve-tool.mjs +164 -0
  107. package/dist/deepsec/eve-tool.mjs.map +1 -0
  108. package/dist/deepsec/finding.d.mts +84 -0
  109. package/dist/deepsec/finding.mjs +56 -0
  110. package/dist/deepsec/finding.mjs.map +1 -0
  111. package/dist/deepsec.d.mts +3 -0
  112. package/dist/delivery-metrics/metrics.d.mts +93 -0
  113. package/dist/delivery-metrics/metrics.mjs +200 -0
  114. package/dist/delivery-metrics/metrics.mjs.map +1 -0
  115. package/dist/delivery-metrics.d.mts +2 -0
  116. package/dist/delivery-metrics.mjs +2 -0
  117. package/dist/dispatch.d.mts +81 -0
  118. package/dist/dispatch.mjs +140 -0
  119. package/dist/dispatch.mjs.map +1 -0
  120. package/dist/errors.d.mts +15 -0
  121. package/dist/errors.mjs +38 -0
  122. package/dist/errors.mjs.map +1 -0
  123. package/dist/eve/index.d.mts +143 -1271
  124. package/dist/eve/index.mjs +233 -1065
  125. package/dist/eve/index.mjs.map +1 -1
  126. package/dist/eve/invoke.d.mts +144 -0
  127. package/dist/eve/invoke.mjs +241 -0
  128. package/dist/eve/invoke.mjs.map +1 -0
  129. package/dist/eve/session-client.d.mts +68 -0
  130. package/dist/eve/session-client.mjs +131 -0
  131. package/dist/eve/session-client.mjs.map +1 -0
  132. package/dist/eve/task-execution.mjs +18 -0
  133. package/dist/eve/task-execution.mjs.map +1 -0
  134. package/dist/eve/task-session.d.mts +87 -0
  135. package/dist/eve/task-session.mjs +203 -0
  136. package/dist/eve/task-session.mjs.map +1 -0
  137. package/dist/eve/transcript.d.mts +37 -0
  138. package/dist/eve/transcript.mjs +65 -0
  139. package/dist/eve/transcript.mjs.map +1 -0
  140. package/dist/execution-public.d.mts +8 -0
  141. package/dist/execution-public.mjs +7 -0
  142. package/dist/execution.d.mts +75 -0
  143. package/dist/execution.mjs +153 -0
  144. package/dist/execution.mjs.map +1 -0
  145. package/dist/finding-remediation/admission.d.mts +51 -0
  146. package/dist/finding-remediation/admission.mjs +87 -0
  147. package/dist/finding-remediation/admission.mjs.map +1 -0
  148. package/dist/finding-remediation/brief.d.mts +14 -0
  149. package/dist/finding-remediation/brief.mjs +25 -0
  150. package/dist/finding-remediation/brief.mjs.map +1 -0
  151. package/dist/finding-remediation/eve-tool.d.mts +29 -0
  152. package/dist/finding-remediation/eve-tool.mjs +34 -0
  153. package/dist/finding-remediation/eve-tool.mjs.map +1 -0
  154. package/dist/findings/fingerprint.d.mts +14 -0
  155. package/dist/findings/fingerprint.mjs +28 -0
  156. package/dist/findings/fingerprint.mjs.map +1 -0
  157. package/dist/findings.d.mts +6 -0
  158. package/dist/findings.mjs +6 -0
  159. package/dist/github-app.d.mts +54 -0
  160. package/dist/github-app.mjs +121 -0
  161. package/dist/github-app.mjs.map +1 -0
  162. package/dist/github-publication.d.mts +198 -0
  163. package/dist/github-publication.mjs +429 -0
  164. package/dist/github-publication.mjs.map +1 -0
  165. package/dist/github-transfer.d.mts +72 -0
  166. package/dist/github-transfer.mjs +125 -0
  167. package/dist/github-transfer.mjs.map +1 -0
  168. package/dist/github.d.mts +406 -2
  169. package/dist/github.mjs +239 -40
  170. package/dist/github.mjs.map +1 -1
  171. package/dist/image-input.d.mts +51 -0
  172. package/dist/image-input.mjs +63 -0
  173. package/dist/image-input.mjs.map +1 -0
  174. package/dist/index.d.mts +14 -484
  175. package/dist/index.mjs +14 -522
  176. package/dist/intake-contracts.d.mts +56 -0
  177. package/dist/intake-contracts.mjs +33 -0
  178. package/dist/intake-contracts.mjs.map +1 -0
  179. package/dist/integrations/deepsec.d.mts +4 -0
  180. package/dist/integrations/deepsec.mjs +3 -0
  181. package/dist/integrations/github.d.mts +11 -0
  182. package/dist/integrations/github.mjs +9 -0
  183. package/dist/integrations/slack.d.mts +3 -0
  184. package/dist/integrations/slack.mjs +3 -0
  185. package/dist/integrations/vercel.d.mts +3 -0
  186. package/dist/integrations/vercel.mjs +3 -0
  187. package/dist/merge-resolution/contracts.d.mts +17 -0
  188. package/dist/merge-resolution/contracts.mjs +19 -0
  189. package/dist/merge-resolution/contracts.mjs.map +1 -0
  190. package/dist/merge-resolution/eve-tools.d.mts +46 -0
  191. package/dist/merge-resolution/eve-tools.mjs +117 -0
  192. package/dist/merge-resolution/eve-tools.mjs.map +1 -0
  193. package/dist/multi-repository-changes/coordination.d.mts +49 -0
  194. package/dist/multi-repository-changes/coordination.mjs +115 -0
  195. package/dist/multi-repository-changes/coordination.mjs.map +1 -0
  196. package/dist/planning/cancellation.mjs +82 -0
  197. package/dist/planning/cancellation.mjs.map +1 -0
  198. package/dist/planning/configuration.d.mts +23 -0
  199. package/dist/planning/configuration.mjs +56 -0
  200. package/dist/planning/configuration.mjs.map +1 -0
  201. package/dist/planning/contracts.d.mts +136 -0
  202. package/dist/planning/contracts.mjs +42 -0
  203. package/dist/planning/contracts.mjs.map +1 -0
  204. package/dist/planning/dependencies.mjs +44 -0
  205. package/dist/planning/dependencies.mjs.map +1 -0
  206. package/dist/planning/effects.mjs +122 -0
  207. package/dist/planning/effects.mjs.map +1 -0
  208. package/dist/planning/reconcile.mjs +273 -0
  209. package/dist/planning/reconcile.mjs.map +1 -0
  210. package/dist/planning/runtime.d.mts +27 -0
  211. package/dist/planning/runtime.mjs +25 -0
  212. package/dist/planning/runtime.mjs.map +1 -0
  213. package/dist/planning/state.mjs +92 -0
  214. package/dist/planning/state.mjs.map +1 -0
  215. package/dist/planning/turns.mjs +262 -0
  216. package/dist/planning/turns.mjs.map +1 -0
  217. package/dist/planning/validation.mjs +106 -0
  218. package/dist/planning/validation.mjs.map +1 -0
  219. package/dist/postgres/index.d.mts +7 -1
  220. package/dist/postgres/index.mjs +7 -3
  221. package/dist/postgres/index.mjs.map +1 -1
  222. package/dist/presets/software-development/approval.d.mts +14 -0
  223. package/dist/presets/software-development/approval.mjs +21 -0
  224. package/dist/presets/software-development/approval.mjs.map +1 -0
  225. package/dist/presets/software-development/deepsec-brief.d.mts +8 -0
  226. package/dist/presets/software-development/deepsec-brief.mjs +14 -0
  227. package/dist/presets/software-development/deepsec-brief.mjs.map +1 -0
  228. package/dist/presets/software-development/dispatch.d.mts +53 -0
  229. package/dist/presets/software-development/dispatch.mjs +66 -0
  230. package/dist/presets/software-development/dispatch.mjs.map +1 -0
  231. package/dist/presets/software-development/eve-delegation-policy.d.mts +7 -0
  232. package/dist/presets/software-development/eve-delegation-policy.mjs +34 -0
  233. package/dist/presets/software-development/eve-delegation-policy.mjs.map +1 -0
  234. package/dist/presets/software-development/eve.d.mts +18 -0
  235. package/dist/presets/software-development/eve.mjs +19 -0
  236. package/dist/presets/software-development/eve.mjs.map +1 -0
  237. package/dist/presets/software-development/finish-task-policy.d.mts +7 -0
  238. package/dist/presets/software-development/finish-task-policy.mjs +9 -0
  239. package/dist/presets/software-development/finish-task-policy.mjs.map +1 -0
  240. package/dist/presets/software-development/recovery.d.mts +32 -0
  241. package/dist/presets/software-development/recovery.mjs +120 -0
  242. package/dist/presets/software-development/recovery.mjs.map +1 -0
  243. package/dist/presets/software-development/task-communication.d.mts +23 -0
  244. package/dist/presets/software-development/task-communication.mjs +120 -0
  245. package/dist/presets/software-development/task-communication.mjs.map +1 -0
  246. package/dist/presets/software-development.d.mts +9 -0
  247. package/dist/presets/software-development.mjs +9 -0
  248. package/dist/pull-requests/contracts.d.mts +72 -0
  249. package/dist/pull-requests/eve-fetch.d.mts +57 -0
  250. package/dist/pull-requests/eve-fetch.mjs +151 -0
  251. package/dist/pull-requests/eve-fetch.mjs.map +1 -0
  252. package/dist/pull-requests/github-label-manager.d.mts +27 -0
  253. package/dist/pull-requests/github-label-manager.mjs +40 -0
  254. package/dist/pull-requests/github-label-manager.mjs.map +1 -0
  255. package/dist/pull-requests/github-publisher.d.mts +53 -0
  256. package/dist/pull-requests/github-publisher.mjs +345 -0
  257. package/dist/pull-requests/github-publisher.mjs.map +1 -0
  258. package/dist/pull-requests.d.mts +5 -0
  259. package/dist/pull-requests.mjs +4 -0
  260. package/dist/receipts.d.mts +4 -0
  261. package/dist/receipts.mjs +3 -0
  262. package/dist/repositories.d.mts +18 -0
  263. package/dist/repositories.mjs +33 -0
  264. package/dist/repositories.mjs.map +1 -0
  265. package/dist/sandbox/command.d.mts +18 -0
  266. package/dist/sandbox/execution-abort.d.mts +16 -0
  267. package/dist/sandbox/execution-abort.mjs +49 -0
  268. package/dist/sandbox/execution-abort.mjs.map +1 -0
  269. package/dist/sandbox/execution-environment.d.mts +25 -0
  270. package/dist/sandbox/execution-run-ledger.d.mts +115 -0
  271. package/dist/sandbox/execution-run-ledger.mjs +209 -0
  272. package/dist/sandbox/execution-run-ledger.mjs.map +1 -0
  273. package/dist/sandbox/execution.d.mts +54 -0
  274. package/dist/sandbox/execution.mjs +228 -0
  275. package/dist/sandbox/execution.mjs.map +1 -0
  276. package/dist/sandbox/harness-runner.d.mts +79 -0
  277. package/dist/sandbox/harness-runner.mjs +162 -0
  278. package/dist/sandbox/harness-runner.mjs.map +1 -0
  279. package/dist/sandbox/index.d.mts +9 -0
  280. package/dist/sandbox/index.mjs +7 -0
  281. package/dist/sandbox/task-environment.d.mts +50 -0
  282. package/dist/sandbox/task-environment.mjs +140 -0
  283. package/dist/sandbox/task-environment.mjs.map +1 -0
  284. package/dist/sandbox/workspace.d.mts +29 -0
  285. package/dist/sandbox/workspace.mjs +28 -0
  286. package/dist/sandbox/workspace.mjs.map +1 -0
  287. package/dist/schema/agent-route.d.mts +22 -0
  288. package/dist/schema/agent-route.mjs +15 -0
  289. package/dist/schema/agent-route.mjs.map +1 -0
  290. package/dist/schema/answer.d.mts +23 -0
  291. package/dist/schema/answer.mjs +21 -0
  292. package/dist/schema/answer.mjs.map +1 -0
  293. package/dist/schema/budget.d.mts +38 -0
  294. package/dist/schema/budget.mjs +30 -0
  295. package/dist/schema/budget.mjs.map +1 -0
  296. package/dist/schema/catalog.mjs +72 -0
  297. package/dist/schema/catalog.mjs.map +1 -0
  298. package/dist/schema/change.d.mts +117 -0
  299. package/dist/schema/change.mjs +68 -0
  300. package/dist/schema/change.mjs.map +1 -0
  301. package/dist/schema/common.d.mts +33 -0
  302. package/dist/{id-BLIkCVue.mjs → schema/common.mjs} +7 -16
  303. package/dist/schema/common.mjs.map +1 -0
  304. package/dist/schema/communication.d.mts +52 -0
  305. package/dist/{communication-Kd9nU5RP.mjs → schema/communication.mjs} +8 -3
  306. package/dist/schema/communication.mjs.map +1 -0
  307. package/dist/schema/execution.d.mts +101 -0
  308. package/dist/schema/execution.mjs +86 -0
  309. package/dist/schema/execution.mjs.map +1 -0
  310. package/dist/schema/factory-config.d.mts +95 -0
  311. package/dist/schema/factory-config.mjs +60 -0
  312. package/dist/schema/factory-config.mjs.map +1 -0
  313. package/dist/schema/finding.d.mts +125 -0
  314. package/dist/schema/finding.mjs +67 -0
  315. package/dist/schema/finding.mjs.map +1 -0
  316. package/dist/schema/id.d.mts +43 -0
  317. package/dist/schema/id.mjs +32 -0
  318. package/dist/schema/id.mjs.map +1 -0
  319. package/dist/schema/outbox.d.mts +240 -0
  320. package/dist/schema/outbox.mjs +53 -0
  321. package/dist/schema/outbox.mjs.map +1 -0
  322. package/dist/schema/question-route.mjs +16 -0
  323. package/dist/schema/question-route.mjs.map +1 -0
  324. package/dist/schema/receipt.d.mts +81 -0
  325. package/dist/schema/receipt.mjs +94 -0
  326. package/dist/schema/receipt.mjs.map +1 -0
  327. package/dist/schema/repository.d.mts +26 -0
  328. package/dist/schema/repository.mjs +25 -0
  329. package/dist/schema/repository.mjs.map +1 -0
  330. package/dist/schema/session.d.mts +135 -0
  331. package/dist/schema/session.mjs +53 -0
  332. package/dist/schema/session.mjs.map +1 -0
  333. package/dist/schema/signal.d.mts +105 -0
  334. package/dist/schema/signal.mjs +81 -0
  335. package/dist/schema/signal.mjs.map +1 -0
  336. package/dist/schema/stored-session.mjs +10 -0
  337. package/dist/schema/stored-session.mjs.map +1 -0
  338. package/dist/schema/stored-task.mjs +20 -0
  339. package/dist/schema/stored-task.mjs.map +1 -0
  340. package/dist/schema/task-effect.d.mts +39 -0
  341. package/dist/schema/task-effect.mjs +29 -0
  342. package/dist/schema/task-effect.mjs.map +1 -0
  343. package/dist/schema/task-graph.d.mts +3134 -0
  344. package/dist/schema/task-graph.mjs +97 -0
  345. package/dist/schema/task-graph.mjs.map +1 -0
  346. package/dist/schema/task-message.d.mts +254 -0
  347. package/dist/schema/task-message.mjs +189 -0
  348. package/dist/schema/task-message.mjs.map +1 -0
  349. package/dist/schema/task.d.mts +272 -0
  350. package/dist/schema/task.mjs +199 -0
  351. package/dist/schema/task.mjs.map +1 -0
  352. package/dist/schema/transcript.d.mts +170 -0
  353. package/dist/schema/transcript.mjs +86 -0
  354. package/dist/schema/transcript.mjs.map +1 -0
  355. package/dist/schema/transitions.d.mts +50 -0
  356. package/dist/schema/transitions.mjs +303 -0
  357. package/dist/schema/transitions.mjs.map +1 -0
  358. package/dist/schema/work.d.mts +101 -0
  359. package/dist/schema/work.mjs +102 -0
  360. package/dist/schema/work.mjs.map +1 -0
  361. package/dist/signal-triage.d.mts +20 -0
  362. package/dist/signal-triage.mjs +85 -0
  363. package/dist/signal-triage.mjs.map +1 -0
  364. package/dist/signals.d.mts +19 -0
  365. package/dist/signals.mjs +19 -0
  366. package/dist/signals.mjs.map +1 -0
  367. package/dist/stall.d.mts +38 -0
  368. package/dist/stall.mjs +79 -0
  369. package/dist/stall.mjs.map +1 -0
  370. package/dist/storage.d.mts +4 -0
  371. package/dist/storage.mjs +4 -0
  372. package/dist/store/driver.d.mts +65 -0
  373. package/dist/store/driver.mjs +42 -0
  374. package/dist/store/driver.mjs.map +1 -0
  375. package/dist/store/engine.d.mts +485 -0
  376. package/dist/store/engine.mjs +2175 -0
  377. package/dist/store/engine.mjs.map +1 -0
  378. package/dist/store/memory.d.mts +7 -0
  379. package/dist/store/memory.mjs +52 -0
  380. package/dist/store/memory.mjs.map +1 -0
  381. package/dist/store/task-effects.d.mts +38 -0
  382. package/dist/store/task-effects.mjs +118 -0
  383. package/dist/store/task-effects.mjs.map +1 -0
  384. package/dist/store/task-graphs.d.mts +60 -0
  385. package/dist/store/task-graphs.mjs +212 -0
  386. package/dist/store/task-graphs.mjs.map +1 -0
  387. package/dist/store/task-messages.d.mts +136 -0
  388. package/dist/store/task-messages.mjs +475 -0
  389. package/dist/store/task-messages.mjs.map +1 -0
  390. package/dist/store/task-work.d.mts +65 -0
  391. package/dist/store/task-work.mjs +134 -0
  392. package/dist/store/task-work.mjs.map +1 -0
  393. package/dist/store/work-notifications.d.mts +19 -0
  394. package/dist/store/work-notifications.mjs +48 -0
  395. package/dist/store/work-notifications.mjs.map +1 -0
  396. package/dist/sweep.d.mts +57 -0
  397. package/dist/sweep.mjs +143 -0
  398. package/dist/sweep.mjs.map +1 -0
  399. package/dist/task-communication.d.mts +35 -0
  400. package/dist/task-communication.mjs +47 -0
  401. package/dist/task-communication.mjs.map +1 -0
  402. package/dist/task-graph-view.d.mts +264 -0
  403. package/dist/task-graph-view.mjs +17 -0
  404. package/dist/task-graph-view.mjs.map +1 -0
  405. package/dist/task-message-processing.d.mts +60 -0
  406. package/dist/task-message-processing.mjs +200 -0
  407. package/dist/task-message-processing.mjs.map +1 -0
  408. package/dist/task-protocols.d.mts +80 -0
  409. package/dist/task-protocols.mjs +47 -0
  410. package/dist/task-protocols.mjs.map +1 -0
  411. package/dist/tasks.d.mts +17 -0
  412. package/dist/tasks.mjs +17 -0
  413. package/dist/vercel-git.d.mts +21 -0
  414. package/dist/vercel-git.mjs +112 -0
  415. package/dist/vercel-git.mjs.map +1 -0
  416. package/dist/vercel.d.mts +33 -2
  417. package/dist/vercel.mjs +48 -3
  418. package/dist/vercel.mjs.map +1 -1
  419. package/dist/work-triage/eve-tool.d.mts +29 -0
  420. package/dist/work-triage/eve-tool.mjs +32 -0
  421. package/dist/work-triage/eve-tool.mjs.map +1 -0
  422. package/dist/work-triage/find-existing-work.d.mts +32 -0
  423. package/dist/work-triage/find-existing-work.mjs +31 -0
  424. package/dist/work-triage/find-existing-work.mjs.map +1 -0
  425. package/dist/work-triage/github.d.mts +15 -0
  426. package/dist/work-triage/github.mjs +14 -0
  427. package/dist/work-triage/github.mjs.map +1 -0
  428. package/dist/work-triage.d.mts +3 -0
  429. package/dist/work-triage.mjs +3 -0
  430. package/dist/workflows.d.mts +48 -0
  431. package/dist/workflows.mjs +86 -0
  432. package/dist/workflows.mjs.map +1 -0
  433. package/dist/workspace-diff-assembly.d.mts +33 -0
  434. package/dist/workspace-diff-assembly.mjs +95 -0
  435. package/dist/workspace-diff-assembly.mjs.map +1 -0
  436. package/dist/workspace-diff.d.mts +90 -0
  437. package/dist/workspace-diff.mjs +61 -0
  438. package/dist/workspace-diff.mjs.map +1 -0
  439. package/dist/workspace-snapshot.d.mts +26 -0
  440. package/dist/workspace-snapshot.mjs +80 -0
  441. package/dist/workspace-snapshot.mjs.map +1 -0
  442. package/package.json +129 -44
  443. package/dist/approval-JX2Px9IC.mjs +0 -132
  444. package/dist/approval-JX2Px9IC.mjs.map +0 -1
  445. package/dist/budget-DzSiIA4t.mjs +0 -42
  446. package/dist/budget-DzSiIA4t.mjs.map +0 -1
  447. package/dist/change-D2U6v7Ek.mjs +0 -554
  448. package/dist/change-D2U6v7Ek.mjs.map +0 -1
  449. package/dist/communication-Kd9nU5RP.mjs.map +0 -1
  450. package/dist/coordination-Cq08hb1l.mjs +0 -76
  451. package/dist/coordination-Cq08hb1l.mjs.map +0 -1
  452. package/dist/dispatch-BaZS3PT8.d.mts +0 -76
  453. package/dist/driver-BC0Mt5KG.d.mts +0 -34
  454. package/dist/driver-Bbd25rNM.mjs +0 -23
  455. package/dist/driver-Bbd25rNM.mjs.map +0 -1
  456. package/dist/engine-DFHU2Pe-.d.mts +0 -781
  457. package/dist/engine-WaUM2cGA.mjs +0 -1068
  458. package/dist/engine-WaUM2cGA.mjs.map +0 -1
  459. package/dist/factory-config-BoRXOw43.mjs +0 -50
  460. package/dist/factory-config-BoRXOw43.mjs.map +0 -1
  461. package/dist/factory-config-D2yU3G0c.d.mts +0 -58
  462. package/dist/github-C5HNBN6p.d.mts +0 -279
  463. package/dist/id-BLIkCVue.mjs.map +0 -1
  464. package/dist/index-Bw6hggoH.d.mts +0 -40
  465. package/dist/index.mjs.map +0 -1
  466. package/dist/task-CcOyOJ3k.mjs +0 -154
  467. package/dist/task-CcOyOJ3k.mjs.map +0 -1
@@ -1,554 +0,0 @@
1
- import { d as isoDateTimeSchema, l as taskIdSchema, n as changeIdSchema, o as repositoryIdSchema, p as schemaVersionSchema, r as factoryIdSchema } from "./id-BLIkCVue.mjs";
2
- import { o as taskExecutionRepositoryIdsSchema } from "./task-CcOyOJ3k.mjs";
3
- import { n as RecordNotFoundError, r as VersionConflictError } from "./driver-Bbd25rNM.mjs";
4
- import { z } from "zod";
5
- import { createHash } from "node:crypto";
6
- //#region src/budget.ts
7
- /**
8
- * Stable factory identity for budget rows. Nothing mints factory ids yet, so
9
- * the app derives one from a deployment-stable seed such as the Vercel
10
- * project id.
11
- */
12
- function deriveFactoryId(seed) {
13
- return factoryIdSchema.parse(`fac_${createHash("sha256").update(seed).digest("hex").slice(0, 32)}`);
14
- }
15
- /** The budget month ("YYYY-MM", UTC) a timestamp falls into. */
16
- function budgetMonthOf(isoDateTime) {
17
- return isoDateTime.slice(0, 7);
18
- }
19
- function microsOf(usd) {
20
- return Math.round(usd * 1e6);
21
- }
22
- /**
23
- * Monthly spend is derived from task rows, never stored: each task counts its
24
- * settled cost once that exists, otherwise its held reservation. A task
25
- * settles once, so a settled row never also counts its reservation.
26
- * Attribution uses the reservation time so tasks that wait across a month
27
- * boundary charge the month they actually ran in.
28
- */
29
- function computeMonthSpendUsd(tasks, month) {
30
- let spendMicros = 0;
31
- for (const task of tasks) {
32
- if (budgetMonthOf(task.reservedAt ?? task.createdAt) !== month) continue;
33
- spendMicros += microsOf(task.settledUsd ?? task.reservedUsd ?? 0);
34
- }
35
- return spendMicros / 1e6;
36
- }
37
- /**
38
- * True when one more per-task slice fits under the monthly total. Dispatch
39
- * refuses on this exact predicate and budgetStatus reports "exhausted" on its
40
- * negation, so refusing and reporting can never disagree.
41
- */
42
- function canReserve(spendUsd, limits) {
43
- return microsOf(spendUsd) + microsOf(limits.perTaskReservationUsd) <= microsOf(limits.totalUsd);
44
- }
45
- function budgetStatus(spendUsd, limits) {
46
- if (!canReserve(spendUsd, limits)) return "exhausted";
47
- if (microsOf(spendUsd) * 100 >= microsOf(limits.totalUsd) * limits.warningPercent) return "warning";
48
- return "ok";
49
- }
50
- const TERMINAL_TASK_STATES = /* @__PURE__ */ new Set([
51
- "succeeded",
52
- "failed",
53
- "cancelled"
54
- ]);
55
- /**
56
- * Settle reserved terminal tasks the session hook did not: a task that ended
57
- * after its session (a change verified later) or whose session died. Settles
58
- * at the recorded usage, or at zero with a warning reason when none was
59
- * recorded within the grace window.
60
- */
61
- async function sweepSettlements(stores, options = {}) {
62
- const graceMs = (options.graceMinutes ?? 10) * 6e4;
63
- const nowMs = (options.now ?? (() => /* @__PURE__ */ new Date()))().getTime();
64
- const settled = [];
65
- for (const task of await stores.tasks.list()) {
66
- if (task.reservedUsd === void 0 || task.settledUsd !== void 0) continue;
67
- if (!TERMINAL_TASK_STATES.has(task.state)) continue;
68
- if (nowMs - Date.parse(task.updatedAt) < graceMs) continue;
69
- const totalUsd = task.usage?.costUsd ?? 0;
70
- try {
71
- const result = await stores.tasks.settle(task.id, { totalUsd }, { reason: task.usage === void 0 ? "usage missing after ten minutes; settled at zero" : "measured usage settled by sweep" });
72
- settled.push({
73
- taskId: result.id,
74
- totalUsd
75
- });
76
- } catch {
77
- continue;
78
- }
79
- }
80
- return { settled };
81
- }
82
- /**
83
- * Ensure the month's budget row, derive spend, and record threshold crossings
84
- * write-once. Delivery comes first and the stamp only lands after it, so a
85
- * failed notification retries on the next sweep instead of being lost; the
86
- * write-once stamp still keeps each threshold to one message per month.
87
- */
88
- async function sweepBudget(stores, options) {
89
- const now = options.now ?? (() => /* @__PURE__ */ new Date());
90
- const month = options.month ?? budgetMonthOf(now().toISOString());
91
- const budget = await stores.budgets.ensure({
92
- factoryId: options.factoryId,
93
- month,
94
- limits: options.limits
95
- });
96
- const spendUsd = computeMonthSpendUsd(await stores.tasks.list(), month);
97
- const status = budgetStatus(spendUsd, options.limits);
98
- async function crossThreshold(notice, outcome) {
99
- const field = notice === "warning" ? "warningAt" : "exhaustedAt";
100
- if (budget.notices[field] !== void 0) return false;
101
- if (options.notify !== void 0) try {
102
- await options.notify({
103
- outcome,
104
- month,
105
- spendUsd,
106
- limits: options.limits
107
- });
108
- } catch {
109
- return false;
110
- }
111
- return (await stores.budgets.stampNotice(month, notice)).stamped;
112
- }
113
- let warned = false;
114
- let exhausted = false;
115
- if (status === "exhausted") {
116
- exhausted = await crossThreshold("exhausted", "budget_exhausted");
117
- if (budget.notices.warningAt === void 0) await stores.budgets.stampNotice(month, "warning");
118
- } else if (status === "warning") warned = await crossThreshold("warning", "budget_warning");
119
- return {
120
- month,
121
- spendUsd,
122
- status,
123
- warned,
124
- exhausted
125
- };
126
- }
127
- //#endregion
128
- //#region src/schema/transitions.ts
129
- const taskInitialState = "queued";
130
- const taskTransitions = [
131
- {
132
- from: "queued",
133
- to: "running",
134
- trigger: "dependencies have a change, reservation succeeded, devbox created",
135
- actor: "reconciler"
136
- },
137
- {
138
- from: "queued",
139
- to: "failed",
140
- trigger: "reservation refused",
141
- actor: "reconciler"
142
- },
143
- {
144
- from: "queued",
145
- to: "needs_human",
146
- trigger: "kind is question",
147
- actor: "system"
148
- },
149
- {
150
- from: "queued",
151
- to: "cancelled",
152
- trigger: "cancel or kill",
153
- actor: "operator"
154
- },
155
- {
156
- from: "running",
157
- to: "verifying",
158
- trigger: "devbox task reported complete",
159
- actor: "reconciler"
160
- },
161
- {
162
- from: "running",
163
- to: "queued",
164
- trigger: "launch failed below attempt limit",
165
- actor: "reconciler"
166
- },
167
- {
168
- from: "running",
169
- to: "failed",
170
- trigger: "devbox task errored, deadline exceeded, or launch failed at attempt limit",
171
- actor: "reconciler"
172
- },
173
- {
174
- from: "running",
175
- to: "needs_human",
176
- trigger: "an open QuestionTask requests human input or action",
177
- actor: "reconciler"
178
- },
179
- {
180
- from: "running",
181
- to: "cancelled",
182
- trigger: "cancel or kill",
183
- actor: "operator"
184
- },
185
- {
186
- from: "running",
187
- to: "stalled",
188
- trigger: "no progress within the stall window",
189
- actor: "reconciler"
190
- },
191
- {
192
- from: "stalled",
193
- to: "queued",
194
- trigger: "replacement attempt below attempt limit, or operator retry",
195
- actor: "reconciler"
196
- },
197
- {
198
- from: "stalled",
199
- to: "failed",
200
- trigger: "attempt limit exhausted",
201
- actor: "reconciler"
202
- },
203
- {
204
- from: "stalled",
205
- to: "cancelled",
206
- trigger: "cancel or kill",
207
- actor: "operator"
208
- },
209
- {
210
- from: "verifying",
211
- to: "succeeded",
212
- trigger: "kind criterion true",
213
- actor: "reconciler"
214
- },
215
- {
216
- from: "verifying",
217
- to: "running",
218
- trigger: "verification failed below attempt limit",
219
- actor: "reconciler"
220
- },
221
- {
222
- from: "verifying",
223
- to: "failed",
224
- trigger: "verification failed at attempt limit",
225
- actor: "reconciler"
226
- },
227
- {
228
- from: "verifying",
229
- to: "cancelled",
230
- trigger: "cancel or kill",
231
- actor: "operator"
232
- },
233
- {
234
- from: "needs_human",
235
- to: "succeeded",
236
- trigger: "question answered",
237
- actor: "operator"
238
- },
239
- {
240
- from: "needs_human",
241
- to: "queued",
242
- trigger: "operator retry",
243
- actor: "operator"
244
- },
245
- {
246
- from: "needs_human",
247
- to: "cancelled",
248
- trigger: "cancel or kill",
249
- actor: "operator"
250
- },
251
- {
252
- from: "failed",
253
- to: "queued",
254
- trigger: "operator retry",
255
- actor: "operator"
256
- }
257
- ];
258
- const changeInitialState = "verifying";
259
- const changeTransitions = [
260
- {
261
- from: "ready",
262
- to: "verifying",
263
- trigger: "a code_change task updated the existing pull request head",
264
- actor: "reconciler"
265
- },
266
- {
267
- from: "verifying",
268
- to: "ready",
269
- trigger: "configured verification policy completed, risk and confidence written",
270
- actor: "reconciler"
271
- },
272
- {
273
- from: "verifying",
274
- to: "closed",
275
- trigger: "verification failed at attempt limit or pr closed upstream",
276
- actor: "reconciler"
277
- },
278
- {
279
- from: "ready",
280
- to: "merged",
281
- trigger: "pr merged on github",
282
- actor: "webhook"
283
- },
284
- {
285
- from: "ready",
286
- to: "closed",
287
- trigger: "pr closed without merge",
288
- actor: "webhook"
289
- },
290
- {
291
- from: "merged",
292
- to: "deployed",
293
- trigger: "production deployment ready containing the merge sha",
294
- actor: "webhook"
295
- },
296
- {
297
- from: "deployed",
298
- to: "rolled_out",
299
- trigger: "no flag, or flag ramped to full and held",
300
- actor: "foreman"
301
- },
302
- {
303
- from: "deployed",
304
- to: "rolled_back",
305
- trigger: "rollback rule crossed",
306
- actor: "foreman"
307
- },
308
- {
309
- from: "rolled_out",
310
- to: "rolled_back",
311
- trigger: "rollback rule crossed or flag flipped off",
312
- actor: "foreman"
313
- },
314
- {
315
- from: "rolled_back",
316
- to: "deployed",
317
- trigger: "human retried the ramp",
318
- actor: "human"
319
- }
320
- ];
321
- const signalInitialOutcome = "pending";
322
- const signalOutcomeTransitions = [
323
- {
324
- from: "pending",
325
- to: "accepted",
326
- trigger: "classified as actionable",
327
- actor: "reconciler"
328
- },
329
- {
330
- from: "pending",
331
- to: "duplicate",
332
- trigger: "classified as duplicate",
333
- actor: "reconciler"
334
- },
335
- {
336
- from: "pending",
337
- to: "unactionable",
338
- trigger: "classified as unactionable",
339
- actor: "reconciler"
340
- },
341
- {
342
- from: "pending",
343
- to: "low_confidence",
344
- trigger: "classified below confidence threshold",
345
- actor: "reconciler"
346
- },
347
- {
348
- from: "pending",
349
- to: "ignored",
350
- trigger: "classified as ignorable",
351
- actor: "reconciler"
352
- }
353
- ];
354
- function isTransitionAllowed(transitions, from, to) {
355
- return transitions.some((transition) => transition.from === from && transition.to === to);
356
- }
357
- function legalNextStates(transitions, from) {
358
- return [...new Set(transitions.filter((transition) => transition.from === from).map((t) => t.to))];
359
- }
360
- var InvalidTransitionError = class extends Error {
361
- from;
362
- to;
363
- legalNextStates;
364
- constructor(from, to, legal) {
365
- super(legal.length > 0 ? `invalid transition from "${from}" to "${to}"; legal next states: ${legal.map((state) => `"${state}"`).join(", ")}` : `invalid transition from "${from}" to "${to}"; "${from}" is terminal`);
366
- this.name = "InvalidTransitionError";
367
- this.from = from;
368
- this.to = to;
369
- this.legalNextStates = legal;
370
- }
371
- };
372
- function assertTransition(transitions, from, to) {
373
- if (!isTransitionAllowed(transitions, from, to)) throw new InvalidTransitionError(from, to, legalNextStates(transitions, from));
374
- }
375
- function terminalStates(transitions) {
376
- const states = /* @__PURE__ */ new Set();
377
- for (const transition of transitions) {
378
- states.add(transition.from);
379
- states.add(transition.to);
380
- }
381
- return [...states].filter((state) => !transitions.some((transition) => transition.from === state));
382
- }
383
- //#endregion
384
- //#region src/dispatch.ts
385
- var DispatchRefusedError = class extends Error {
386
- taskId;
387
- reason;
388
- constructor(taskId, reason) {
389
- super(`dispatch of "${taskId}" refused: ${reason}`);
390
- this.name = "DispatchRefusedError";
391
- this.taskId = taskId;
392
- this.reason = reason;
393
- }
394
- };
395
- /**
396
- * An exhausted budget is definitive, not a retryable refusal: the task has
397
- * already been failed and receipted when this throws, so it never re-enters
398
- * the sweep. Operator retry recovers it once budget frees up.
399
- */
400
- var BudgetExhaustedError = class extends Error {
401
- taskId;
402
- month;
403
- spendUsd;
404
- constructor(taskId, month, spendUsd) {
405
- super(`dispatch of "${taskId}" refused: budget for ${month} is exhausted at $${spendUsd}`);
406
- this.name = "BudgetExhaustedError";
407
- this.taskId = taskId;
408
- this.month = month;
409
- this.spendUsd = spendUsd;
410
- }
411
- };
412
- const DEFAULT_MAX_LAUNCH_ATTEMPTS = 45;
413
- /**
414
- * The handshake between recorded work and execution: win the store-gated
415
- * transition (at most one dispatcher can succeed), then start the run. A
416
- * launch failure re-queues the task (bumping its attempt) until the attempt
417
- * limit, then fails it; a crash between the transition and the launch leaves
418
- * a running task with no execution, which the sweep reaps.
419
- */
420
- async function dispatchTask(stores, taskId, options) {
421
- const task = await stores.tasks.get(taskId);
422
- if (task === null) throw new RecordNotFoundError("tasks", taskId);
423
- if (task.kind === "question") throw new DispatchRefusedError(taskId, "question tasks are answered, not dispatched");
424
- if (task.kind === "coordination") throw new DispatchRefusedError(taskId, "coordination tasks are reconciled, not dispatched");
425
- if (!taskExecutionRepositoryIdsSchema.safeParse(task.repositoryIds).success) throw new DispatchRefusedError(taskId, "task execution requires exactly one repository");
426
- if (task.approval === "required") throw new DispatchRefusedError(taskId, "awaiting human approval");
427
- if (task.approval === "denied") throw new DispatchRefusedError(taskId, "approval was denied");
428
- for (const dependencyId of task.dependsOn ?? []) {
429
- const dependency = await stores.tasks.get(dependencyId);
430
- if (dependency === null) throw new DispatchRefusedError(taskId, `dependency "${dependencyId}" does not exist`);
431
- if (dependency.changeId === void 0) throw new DispatchRefusedError(taskId, `dependency "${dependencyId}" has not produced a change`);
432
- }
433
- let reservation;
434
- if (options.budget !== void 0 && task.state === "queued") {
435
- const budgetNow = (options.budget.now ?? (() => /* @__PURE__ */ new Date()))().toISOString();
436
- const month = options.budget.month ?? budgetMonthOf(budgetNow);
437
- const spendUsd = computeMonthSpendUsd((await stores.tasks.list()).map((row) => row.id === taskId ? {
438
- ...row,
439
- reservedUsd: void 0
440
- } : row), month);
441
- const { totalUsd, perTaskReservationUsd } = options.budget.limits;
442
- if (!canReserve(spendUsd, options.budget.limits)) {
443
- const reason = `budget exhausted: ${month} spend $${spendUsd} cannot fit a $${perTaskReservationUsd} reservation under $${totalUsd}`;
444
- try {
445
- await stores.tasks.transition(taskId, "failed", {
446
- reason,
447
- expectFrom: "queued"
448
- });
449
- } catch (error) {
450
- if (error instanceof InvalidTransitionError || error instanceof VersionConflictError) throw new DispatchRefusedError(taskId, "another dispatcher took the task");
451
- throw error;
452
- }
453
- if (task.repositoryIds !== void 0) await stores.receipts.append({
454
- repositoryIds: task.repositoryIds,
455
- taskId,
456
- kind: task.kind,
457
- state: "reservation_refused",
458
- phase: "budget",
459
- reason,
460
- attempt: task.attempt,
461
- dedupeKey: `task:${taskId}:reservation_refused:${task.attempt}`
462
- }).catch(() => void 0);
463
- throw new BudgetExhaustedError(taskId, month, spendUsd);
464
- }
465
- reservation = {
466
- reservedUsd: perTaskReservationUsd,
467
- reservedAt: budgetNow
468
- };
469
- }
470
- const running = await stores.tasks.transition(taskId, "running", reservation === void 0 ? void 0 : { patch: {
471
- reservedUsd: reservation.reservedUsd,
472
- reservedAt: reservation.reservedAt
473
- } });
474
- let execution;
475
- try {
476
- execution = await options.launch(running);
477
- } catch (error) {
478
- const reason = (error instanceof Error ? error.message : String(error)).slice(0, 500);
479
- const limit = options.maxLaunchAttempts ?? 45;
480
- if (running.attempt < limit) {
481
- const retryReason = `launch failed (attempt ${running.attempt} of ${limit}), will retry: ${reason}`;
482
- await stores.tasks.transition(taskId, "queued", { reason: retryReason }).catch(() => void 0);
483
- if (running.repositoryIds !== void 0) await stores.receipts.append({
484
- repositoryIds: running.repositoryIds,
485
- taskId,
486
- kind: "task",
487
- state: "launch_retry",
488
- reason: retryReason,
489
- dedupeKey: `task:${taskId}:launch_retry:${running.attempt}`
490
- }).catch(() => void 0);
491
- } else await stores.tasks.transition(taskId, "failed", { reason: `launch failed after ${running.attempt} attempts: ${reason}` }).catch(() => void 0);
492
- throw error;
493
- }
494
- if (execution === void 0) return running;
495
- return stores.tasks.recordExecution(taskId, execution).catch(() => running);
496
- }
497
- //#endregion
498
- //#region src/schema/change.ts
499
- const levelSchema = z.enum([
500
- "low",
501
- "medium",
502
- "high"
503
- ]);
504
- const changeStateSchema = z.enum([
505
- "verifying",
506
- "ready",
507
- "merged",
508
- "deployed",
509
- "rolled_out",
510
- "rolled_back",
511
- "closed"
512
- ]);
513
- const postMergeStates = [
514
- "merged",
515
- "deployed",
516
- "rolled_out",
517
- "rolled_back"
518
- ];
519
- const changeEvidenceSchema = z.strictObject({
520
- reproVerified: z.boolean(),
521
- testsAdded: z.number().int().min(0),
522
- checksGreen: z.boolean(),
523
- attackPassed: z.boolean(),
524
- scopeMatches: z.boolean(),
525
- previewUrl: z.url().optional()
526
- });
527
- const changeSchema = z.strictObject({
528
- schemaVersion: schemaVersionSchema,
529
- id: changeIdSchema,
530
- repositoryId: repositoryIdSchema,
531
- taskId: taskIdSchema.optional(),
532
- groupId: taskIdSchema.optional(),
533
- prNumber: z.number().int().min(1),
534
- prUrl: z.url(),
535
- author: z.string().min(1),
536
- risk: levelSchema,
537
- confidence: levelSchema,
538
- evidence: changeEvidenceSchema,
539
- state: changeStateSchema,
540
- mergeSha: z.string().regex(/^[0-9a-f]{40}$/).optional().describe("Merge commit sha recorded when the pull request merges, matched against production deployments."),
541
- decidedBy: z.string().min(1).optional(),
542
- createdAt: isoDateTimeSchema,
543
- updatedAt: isoDateTimeSchema
544
- }).superRefine((change, ctx) => {
545
- if (postMergeStates.includes(change.state) && change.decidedBy === void 0) ctx.addIssue({
546
- code: "custom",
547
- path: ["decidedBy"],
548
- message: `${change.state} changes require decidedBy`
549
- });
550
- });
551
- //#endregion
552
- export { computeMonthSpendUsd as C, sweepSettlements as E, canReserve as S, sweepBudget as T, taskInitialState as _, BudgetExhaustedError as a, budgetMonthOf as b, dispatchTask as c, changeInitialState as d, changeTransitions as f, signalOutcomeTransitions as g, signalInitialOutcome as h, levelSchema as i, InvalidTransitionError as l, legalNextStates as m, changeSchema as n, DEFAULT_MAX_LAUNCH_ATTEMPTS as o, isTransitionAllowed as p, changeStateSchema as r, DispatchRefusedError as s, changeEvidenceSchema as t, assertTransition as u, taskTransitions as v, deriveFactoryId as w, budgetStatus as x, terminalStates as y };
553
-
554
- //# sourceMappingURL=change-D2U6v7Ek.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"change-D2U6v7Ek.mjs","names":[],"sources":["../src/budget.ts","../src/schema/transitions.ts","../src/dispatch.ts","../src/schema/change.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { factoryIdSchema, type FactoryId, type TaskId } from \"./schema/id\";\nimport type { BudgetLimits } from \"./schema/budget\";\nimport type { Task } from \"./schema/task\";\nimport type { FactoryStores } from \"./store/engine\";\n\n/**\n * Stable factory identity for budget rows. Nothing mints factory ids yet, so\n * the app derives one from a deployment-stable seed such as the Vercel\n * project id.\n */\nexport function deriveFactoryId(seed: string): FactoryId {\n return factoryIdSchema.parse(\n `fac_${createHash(\"sha256\").update(seed).digest(\"hex\").slice(0, 32)}`,\n );\n}\n\n/** The budget month (\"YYYY-MM\", UTC) a timestamp falls into. */\nexport function budgetMonthOf(isoDateTime: string): string {\n return isoDateTime.slice(0, 7);\n}\n\n// Currency math runs in integer micro-dollars so decimal limits compare\n// exactly; 0.1 + 0.2 must never refuse an exact-fit reservation.\nfunction microsOf(usd: number): number {\n return Math.round(usd * 1_000_000);\n}\n\n/**\n * Monthly spend is derived from task rows, never stored: each task counts its\n * settled cost once that exists, otherwise its held reservation. A task\n * settles once, so a settled row never also counts its reservation.\n * Attribution uses the reservation time so tasks that wait across a month\n * boundary charge the month they actually ran in.\n */\nexport function computeMonthSpendUsd(tasks: readonly Task[], month: string): number {\n let spendMicros = 0;\n for (const task of tasks) {\n if (budgetMonthOf(task.reservedAt ?? task.createdAt) !== month) {\n continue;\n }\n spendMicros += microsOf(task.settledUsd ?? task.reservedUsd ?? 0);\n }\n return spendMicros / 1_000_000;\n}\n\nexport type BudgetStatus = \"ok\" | \"warning\" | \"exhausted\";\n\n/**\n * True when one more per-task slice fits under the monthly total. Dispatch\n * refuses on this exact predicate and budgetStatus reports \"exhausted\" on its\n * negation, so refusing and reporting can never disagree.\n */\nexport function canReserve(\n spendUsd: number,\n limits: Pick<BudgetLimits, \"totalUsd\" | \"perTaskReservationUsd\">,\n): boolean {\n return microsOf(spendUsd) + microsOf(limits.perTaskReservationUsd) <= microsOf(limits.totalUsd);\n}\n\nexport function budgetStatus(\n spendUsd: number,\n limits: Pick<BudgetLimits, \"totalUsd\" | \"perTaskReservationUsd\" | \"warningPercent\">,\n): BudgetStatus {\n if (!canReserve(spendUsd, limits)) {\n return \"exhausted\";\n }\n // Integer comparison: spend/total * 100 >= warningPercent without float\n // drift on decimal limits.\n if (microsOf(spendUsd) * 100 >= microsOf(limits.totalUsd) * limits.warningPercent) {\n return \"warning\";\n }\n return \"ok\";\n}\n\nconst TERMINAL_TASK_STATES = new Set<Task[\"state\"]>([\"succeeded\", \"failed\", \"cancelled\"]);\n\nexport interface SettleSweepOptions {\n /** How long a terminal task waits for late usage before the sweep settles it. */\n graceMinutes?: number;\n now?: () => Date;\n}\n\nexport interface SettleSweepResult {\n settled: { taskId: TaskId; totalUsd: number }[];\n}\n\n/**\n * Settle reserved terminal tasks the session hook did not: a task that ended\n * after its session (a change verified later) or whose session died. Settles\n * at the recorded usage, or at zero with a warning reason when none was\n * recorded within the grace window.\n */\nexport async function sweepSettlements(\n stores: FactoryStores,\n options: SettleSweepOptions = {},\n): Promise<SettleSweepResult> {\n const graceMs = (options.graceMinutes ?? 10) * 60_000;\n const nowMs = (options.now ?? (() => new Date()))().getTime();\n const settled: SettleSweepResult[\"settled\"] = [];\n for (const task of await stores.tasks.list()) {\n if (task.reservedUsd === undefined || task.settledUsd !== undefined) {\n continue;\n }\n if (!TERMINAL_TASK_STATES.has(task.state)) {\n continue;\n }\n if (nowMs - Date.parse(task.updatedAt) < graceMs) {\n continue;\n }\n // A concurrent writer (operator retry, another sweep) may move the task\n // between the list and the settle; skip it rather than aborting the pass.\n const totalUsd = task.usage?.costUsd ?? 0;\n try {\n const result = await stores.tasks.settle(\n task.id,\n { totalUsd },\n {\n reason: task.usage === undefined\n ? \"usage missing after ten minutes; settled at zero\"\n : \"measured usage settled by sweep\",\n },\n );\n // Report this settlement's amount, not the task's accumulated total.\n settled.push({ taskId: result.id, totalUsd });\n } catch {\n continue;\n }\n }\n return { settled };\n}\n\nexport interface BudgetNotice {\n outcome: \"budget_warning\" | \"budget_exhausted\";\n month: string;\n spendUsd: number;\n limits: BudgetLimits;\n}\n\nexport interface BudgetSweepOptions {\n factoryId: FactoryId;\n limits: BudgetLimits;\n /** Defaults to the current UTC month. */\n month?: string;\n now?: () => Date;\n /** Owner-only delivery; invoked at most once per month per outcome. */\n notify?: (notice: BudgetNotice) => Promise<void>;\n}\n\nexport interface BudgetSweepResult {\n month: string;\n spendUsd: number;\n status: BudgetStatus;\n warned: boolean;\n exhausted: boolean;\n}\n\n/**\n * Ensure the month's budget row, derive spend, and record threshold crossings\n * write-once. Delivery comes first and the stamp only lands after it, so a\n * failed notification retries on the next sweep instead of being lost; the\n * write-once stamp still keeps each threshold to one message per month.\n */\nexport async function sweepBudget(\n stores: FactoryStores,\n options: BudgetSweepOptions,\n): Promise<BudgetSweepResult> {\n const now = options.now ?? (() => new Date());\n const month = options.month ?? budgetMonthOf(now().toISOString());\n const budget = await stores.budgets.ensure({\n factoryId: options.factoryId,\n month,\n limits: options.limits,\n });\n const spendUsd = computeMonthSpendUsd(await stores.tasks.list(), month);\n const status = budgetStatus(spendUsd, options.limits);\n\n async function crossThreshold(\n notice: \"warning\" | \"exhausted\",\n outcome: BudgetNotice[\"outcome\"],\n ): Promise<boolean> {\n const field = notice === \"warning\" ? \"warningAt\" : \"exhaustedAt\";\n if (budget.notices[field] !== undefined) {\n return false;\n }\n if (options.notify !== undefined) {\n try {\n await options.notify({ outcome, month, spendUsd, limits: options.limits });\n } catch {\n // Leave the notice unstamped so the next sweep retries delivery.\n return false;\n }\n }\n return (await stores.budgets.stampNotice(month, notice)).stamped;\n }\n\n let warned = false;\n let exhausted = false;\n if (status === \"exhausted\") {\n exhausted = await crossThreshold(\"exhausted\", \"budget_exhausted\");\n // The warning threshold was necessarily crossed too; stamp it silently so\n // a later settle-down cannot deliver \"warning\" after \"exhausted\".\n if (budget.notices.warningAt === undefined) {\n await stores.budgets.stampNotice(month, \"warning\");\n }\n } else if (status === \"warning\") {\n warned = await crossThreshold(\"warning\", \"budget_warning\");\n }\n return { month, spendUsd, status, warned, exhausted };\n}\n","import type { ChangeState } from \"./change\";\nimport type { SignalOutcome } from \"./signal\";\nimport type { TaskState } from \"./task\";\n\nexport type TransitionActor =\n | \"system\"\n | \"reconciler\"\n | \"foreman\"\n | \"operator\"\n | \"webhook\"\n | \"human\";\n\nexport interface Transition<State extends string> {\n readonly from: State;\n readonly to: State;\n readonly trigger: string;\n readonly actor: TransitionActor;\n}\n\nexport const taskInitialState = \"queued\" satisfies TaskState;\n\nexport const taskTransitions: readonly Transition<TaskState>[] = [\n {\n from: \"queued\",\n to: \"running\",\n trigger: \"dependencies have a change, reservation succeeded, devbox created\",\n actor: \"reconciler\",\n },\n { from: \"queued\", to: \"failed\", trigger: \"reservation refused\", actor: \"reconciler\" },\n { from: \"queued\", to: \"needs_human\", trigger: \"kind is question\", actor: \"system\" },\n { from: \"queued\", to: \"cancelled\", trigger: \"cancel or kill\", actor: \"operator\" },\n { from: \"running\", to: \"verifying\", trigger: \"devbox task reported complete\", actor: \"reconciler\" },\n {\n from: \"running\",\n to: \"queued\",\n trigger: \"launch failed below attempt limit\",\n actor: \"reconciler\",\n },\n {\n from: \"running\",\n to: \"failed\",\n trigger: \"devbox task errored, deadline exceeded, or launch failed at attempt limit\",\n actor: \"reconciler\",\n },\n {\n from: \"running\",\n to: \"needs_human\",\n trigger: \"an open QuestionTask requests human input or action\",\n actor: \"reconciler\",\n },\n { from: \"running\", to: \"cancelled\", trigger: \"cancel or kill\", actor: \"operator\" },\n { from: \"running\", to: \"stalled\", trigger: \"no progress within the stall window\", actor: \"reconciler\" },\n {\n from: \"stalled\",\n to: \"queued\",\n trigger: \"replacement attempt below attempt limit, or operator retry\",\n actor: \"reconciler\",\n },\n { from: \"stalled\", to: \"failed\", trigger: \"attempt limit exhausted\", actor: \"reconciler\" },\n { from: \"stalled\", to: \"cancelled\", trigger: \"cancel or kill\", actor: \"operator\" },\n { from: \"verifying\", to: \"succeeded\", trigger: \"kind criterion true\", actor: \"reconciler\" },\n {\n from: \"verifying\",\n to: \"running\",\n trigger: \"verification failed below attempt limit\",\n actor: \"reconciler\",\n },\n {\n from: \"verifying\",\n to: \"failed\",\n trigger: \"verification failed at attempt limit\",\n actor: \"reconciler\",\n },\n { from: \"verifying\", to: \"cancelled\", trigger: \"cancel or kill\", actor: \"operator\" },\n { from: \"needs_human\", to: \"succeeded\", trigger: \"question answered\", actor: \"operator\" },\n { from: \"needs_human\", to: \"queued\", trigger: \"operator retry\", actor: \"operator\" },\n { from: \"needs_human\", to: \"cancelled\", trigger: \"cancel or kill\", actor: \"operator\" },\n { from: \"failed\", to: \"queued\", trigger: \"operator retry\", actor: \"operator\" },\n];\n\nexport const changeInitialState = \"verifying\" satisfies ChangeState;\n\nexport const changeTransitions: readonly Transition<ChangeState>[] = [\n {\n from: \"ready\",\n to: \"verifying\",\n trigger: \"a code_change task updated the existing pull request head\",\n actor: \"reconciler\",\n },\n {\n from: \"verifying\",\n to: \"ready\",\n trigger: \"configured verification policy completed, risk and confidence written\",\n actor: \"reconciler\",\n },\n {\n from: \"verifying\",\n to: \"closed\",\n trigger: \"verification failed at attempt limit or pr closed upstream\",\n actor: \"reconciler\",\n },\n { from: \"ready\", to: \"merged\", trigger: \"pr merged on github\", actor: \"webhook\" },\n { from: \"ready\", to: \"closed\", trigger: \"pr closed without merge\", actor: \"webhook\" },\n {\n from: \"merged\",\n to: \"deployed\",\n trigger: \"production deployment ready containing the merge sha\",\n actor: \"webhook\",\n },\n {\n from: \"deployed\",\n to: \"rolled_out\",\n trigger: \"no flag, or flag ramped to full and held\",\n actor: \"foreman\",\n },\n { from: \"deployed\", to: \"rolled_back\", trigger: \"rollback rule crossed\", actor: \"foreman\" },\n {\n from: \"rolled_out\",\n to: \"rolled_back\",\n trigger: \"rollback rule crossed or flag flipped off\",\n actor: \"foreman\",\n },\n { from: \"rolled_back\", to: \"deployed\", trigger: \"human retried the ramp\", actor: \"human\" },\n];\n\nexport const signalInitialOutcome = \"pending\" satisfies SignalOutcome;\n\nexport const signalOutcomeTransitions: readonly Transition<SignalOutcome>[] = [\n { from: \"pending\", to: \"accepted\", trigger: \"classified as actionable\", actor: \"reconciler\" },\n { from: \"pending\", to: \"duplicate\", trigger: \"classified as duplicate\", actor: \"reconciler\" },\n {\n from: \"pending\",\n to: \"unactionable\",\n trigger: \"classified as unactionable\",\n actor: \"reconciler\",\n },\n {\n from: \"pending\",\n to: \"low_confidence\",\n trigger: \"classified below confidence threshold\",\n actor: \"reconciler\",\n },\n { from: \"pending\", to: \"ignored\", trigger: \"classified as ignorable\", actor: \"reconciler\" },\n];\n\nexport function isTransitionAllowed<State extends string>(\n transitions: readonly Transition<State>[],\n from: State,\n to: State,\n): boolean {\n return transitions.some((transition) => transition.from === from && transition.to === to);\n}\n\nexport function legalNextStates<State extends string>(\n transitions: readonly Transition<State>[],\n from: State,\n): readonly State[] {\n return [\n ...new Set(\n transitions.filter((transition) => transition.from === from).map((t) => t.to),\n ),\n ];\n}\n\nexport class InvalidTransitionError<State extends string> extends Error {\n readonly from: State;\n readonly to: State;\n readonly legalNextStates: readonly State[];\n\n constructor(from: State, to: State, legal: readonly State[]) {\n super(\n legal.length > 0\n ? `invalid transition from \"${from}\" to \"${to}\"; legal next states: ${legal\n .map((state) => `\"${state}\"`)\n .join(\", \")}`\n : `invalid transition from \"${from}\" to \"${to}\"; \"${from}\" is terminal`,\n );\n this.name = \"InvalidTransitionError\";\n this.from = from;\n this.to = to;\n this.legalNextStates = legal;\n }\n}\n\nexport function assertTransition<State extends string>(\n transitions: readonly Transition<State>[],\n from: State,\n to: State,\n): void {\n if (!isTransitionAllowed(transitions, from, to)) {\n throw new InvalidTransitionError(from, to, legalNextStates(transitions, from));\n }\n}\n\nexport function terminalStates<State extends string>(\n transitions: readonly Transition<State>[],\n): readonly State[] {\n const states = new Set<State>();\n for (const transition of transitions) {\n states.add(transition.from);\n states.add(transition.to);\n }\n return [...states].filter(\n (state) => !transitions.some((transition) => transition.from === state),\n );\n}\n","import { budgetMonthOf, canReserve, computeMonthSpendUsd } from \"./budget\";\nimport type { BudgetLimits } from \"./schema/budget\";\nimport type { TaskId } from \"./schema/id\";\nimport { taskExecutionRepositoryIdsSchema, type ExecutionReference, type Task } from \"./schema/task\";\nimport { InvalidTransitionError } from \"./schema/transitions\";\nimport { RecordNotFoundError, VersionConflictError } from \"./store/driver\";\nimport type { FactoryStores } from \"./store/engine\";\n\nexport class DispatchRefusedError extends Error {\n readonly taskId: TaskId;\n readonly reason: string;\n\n constructor(taskId: TaskId, reason: string) {\n super(`dispatch of \"${taskId}\" refused: ${reason}`);\n this.name = \"DispatchRefusedError\";\n this.taskId = taskId;\n this.reason = reason;\n }\n}\n\n/**\n * An exhausted budget is definitive, not a retryable refusal: the task has\n * already been failed and receipted when this throws, so it never re-enters\n * the sweep. Operator retry recovers it once budget frees up.\n */\nexport class BudgetExhaustedError extends Error {\n readonly taskId: TaskId;\n readonly month: string;\n readonly spendUsd: number;\n\n constructor(taskId: TaskId, month: string, spendUsd: number) {\n super(`dispatch of \"${taskId}\" refused: budget for ${month} is exhausted at $${spendUsd}`);\n this.name = \"BudgetExhaustedError\";\n this.taskId = taskId;\n this.month = month;\n this.spendUsd = spendUsd;\n }\n}\n\nexport interface DispatchBudget {\n limits: Pick<BudgetLimits, \"totalUsd\" | \"perTaskReservationUsd\">;\n /** Defaults to the current UTC month. */\n month?: string;\n now?: () => Date;\n}\n\nexport interface DispatchOptions {\n /**\n * Starts the durable execution for the task (an Eve agent run). Runs after\n * the task has won the queued -> running transition. Returning the\n * provider's execution reference records it on the task so the reconciler\n * can find the run; returning nothing leaves the task reachable only by the\n * stall window.\n */\n launch: (task: Task) => Promise<ExecutionReference | void>;\n /** How many launches to try before the task fails for good; a failure re-queues for the next sweep. */\n maxLaunchAttempts?: number;\n /**\n * Reserve-before-execution. When set, dispatch refuses definitively once\n * the month's derived spend cannot fit another reservation, and otherwise\n * stamps the reservation in the same write that wins queued -> running.\n */\n budget?: DispatchBudget;\n}\n\n// A fresh Vercel project rejects its own agents' sessions until its identity\n// finishes provisioning; at one sweep per minute the budget must outlast that.\nexport const DEFAULT_MAX_LAUNCH_ATTEMPTS = 45;\n\n/**\n * The handshake between recorded work and execution: win the store-gated\n * transition (at most one dispatcher can succeed), then start the run. A\n * launch failure re-queues the task (bumping its attempt) until the attempt\n * limit, then fails it; a crash between the transition and the launch leaves\n * a running task with no execution, which the sweep reaps.\n */\nexport async function dispatchTask(\n stores: FactoryStores,\n taskId: TaskId,\n options: DispatchOptions,\n): Promise<Task> {\n const task = await stores.tasks.get(taskId);\n if (task === null) {\n throw new RecordNotFoundError(\"tasks\", taskId);\n }\n if (task.kind === \"question\") {\n throw new DispatchRefusedError(taskId, \"question tasks are answered, not dispatched\");\n }\n if (task.kind === \"coordination\") {\n throw new DispatchRefusedError(taskId, \"coordination tasks are reconciled, not dispatched\");\n }\n if (!taskExecutionRepositoryIdsSchema.safeParse(task.repositoryIds).success) {\n throw new DispatchRefusedError(taskId, \"task execution requires exactly one repository\");\n }\n if (task.approval === \"required\") {\n throw new DispatchRefusedError(taskId, \"awaiting human approval\");\n }\n if (task.approval === \"denied\") {\n throw new DispatchRefusedError(taskId, \"approval was denied\");\n }\n for (const dependencyId of task.dependsOn ?? []) {\n const dependency = await stores.tasks.get(dependencyId);\n if (dependency === null) {\n throw new DispatchRefusedError(taskId, `dependency \"${dependencyId}\" does not exist`);\n }\n if (dependency.changeId === undefined) {\n throw new DispatchRefusedError(\n taskId,\n `dependency \"${dependencyId}\" has not produced a change`,\n );\n }\n }\n\n // The reservation gates queued -> running only; any other state falls\n // through to the transition below, which rejects it as invalid.\n let reservation: { reservedUsd: number; reservedAt: string } | undefined;\n if (options.budget !== undefined && task.state === \"queued\") {\n const budgetNow = (options.budget.now ?? (() => new Date()))().toISOString();\n const month = options.budget.month ?? budgetMonthOf(budgetNow);\n // This task's own retained reservation from a prior attempt is excluded,\n // because re-reserving overwrites it. Its settled cost stays counted:\n // that money was actually spent and a retry must not reopen it.\n const rows = (await stores.tasks.list()).map((row) =>\n row.id === taskId ? { ...row, reservedUsd: undefined } : row,\n );\n const spendUsd = computeMonthSpendUsd(rows, month);\n const { totalUsd, perTaskReservationUsd } = options.budget.limits;\n if (!canReserve(spendUsd, options.budget.limits)) {\n const reason = `budget exhausted: ${month} spend $${spendUsd} cannot fit a $${perTaskReservationUsd} reservation under $${totalUsd}`;\n // Fail first, so BudgetExhaustedError's contract (task already failed)\n // holds; losing the task to a concurrent dispatcher surfaces as a\n // refusal, never as a false exhaustion with a misleading receipt.\n try {\n await stores.tasks.transition(taskId, \"failed\", { reason, expectFrom: \"queued\" });\n } catch (error) {\n if (error instanceof InvalidTransitionError || error instanceof VersionConflictError) {\n throw new DispatchRefusedError(taskId, \"another dispatcher took the task\");\n }\n throw error;\n }\n // Best-effort: the failed transition above already wrote its own\n // receipt carrying this reason, so losing this supplementary one\n // cannot lose the evidence.\n if (task.repositoryIds !== undefined) {\n await stores.receipts\n .append({\n repositoryIds: task.repositoryIds,\n taskId,\n kind: task.kind,\n state: \"reservation_refused\",\n phase: \"budget\",\n reason,\n attempt: task.attempt,\n dedupeKey: `task:${taskId}:reservation_refused:${task.attempt}`,\n })\n .catch(() => undefined);\n }\n throw new BudgetExhaustedError(taskId, month, spendUsd);\n }\n reservation = { reservedUsd: perTaskReservationUsd, reservedAt: budgetNow };\n }\n\n // A resurrected task keeps its settled cost: multi-attempt accumulation is\n // an open spec decision, so the first settlement stays authoritative and\n // the new slice is only held until then.\n const running = await stores.tasks.transition(\n taskId,\n \"running\",\n reservation === undefined\n ? undefined\n : {\n patch: {\n reservedUsd: reservation.reservedUsd,\n reservedAt: reservation.reservedAt,\n },\n },\n );\n let execution: ExecutionReference | void;\n try {\n execution = await options.launch(running);\n } catch (error) {\n const reason = (error instanceof Error ? error.message : String(error)).slice(0, 500);\n const limit = options.maxLaunchAttempts ?? DEFAULT_MAX_LAUNCH_ATTEMPTS;\n if (running.attempt < limit) {\n const retryReason = `launch failed (attempt ${running.attempt} of ${limit}), will retry: ${reason}`;\n await stores.tasks.transition(taskId, \"queued\", { reason: retryReason }).catch(() => undefined);\n // The queued transition writes no receipt; leave one so the retry is visible.\n if (running.repositoryIds !== undefined) {\n await stores.receipts\n .append({\n repositoryIds: running.repositoryIds,\n taskId,\n kind: \"task\",\n state: \"launch_retry\",\n reason: retryReason,\n dedupeKey: `task:${taskId}:launch_retry:${running.attempt}`,\n })\n .catch(() => undefined);\n }\n } else {\n await stores.tasks\n .transition(taskId, \"failed\", { reason: `launch failed after ${running.attempt} attempts: ${reason}` })\n .catch(() => undefined);\n }\n throw error;\n }\n if (execution === undefined) {\n return running;\n }\n // The run exists either way; a lost write here leaves a running task with\n // no reference, which the stall sweep still reaps.\n return stores.tasks.recordExecution(taskId, execution).catch(() => running);\n}\n","import { z } from \"zod\";\nimport { isoDateTimeSchema, schemaVersionSchema } from \"./common\";\nimport { changeIdSchema, repositoryIdSchema, taskIdSchema } from \"./id\";\n\nexport const levelSchema = z.enum([\"low\", \"medium\", \"high\"]);\n\nexport const changeStateSchema = z.enum([\n \"verifying\",\n \"ready\",\n \"merged\",\n \"deployed\",\n \"rolled_out\",\n \"rolled_back\",\n \"closed\",\n]);\n\nconst postMergeStates: readonly string[] = [\"merged\", \"deployed\", \"rolled_out\", \"rolled_back\"];\n\nexport const changeEvidenceSchema = z.strictObject({\n reproVerified: z.boolean(),\n testsAdded: z.number().int().min(0),\n checksGreen: z.boolean(),\n attackPassed: z.boolean(),\n scopeMatches: z.boolean(),\n previewUrl: z.url().optional(),\n});\n\nexport const changeSchema = z\n .strictObject({\n schemaVersion: schemaVersionSchema,\n id: changeIdSchema,\n repositoryId: repositoryIdSchema,\n taskId: taskIdSchema.optional(),\n groupId: taskIdSchema.optional(),\n prNumber: z.number().int().min(1),\n prUrl: z.url(),\n author: z.string().min(1),\n risk: levelSchema,\n confidence: levelSchema,\n evidence: changeEvidenceSchema,\n state: changeStateSchema,\n mergeSha: z\n .string()\n .regex(/^[0-9a-f]{40}$/)\n .optional()\n .describe(\"Merge commit sha recorded when the pull request merges, matched against production deployments.\"),\n decidedBy: z.string().min(1).optional(),\n createdAt: isoDateTimeSchema,\n updatedAt: isoDateTimeSchema,\n })\n .superRefine((change, ctx) => {\n if (postMergeStates.includes(change.state) && change.decidedBy === undefined) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"decidedBy\"],\n message: `${change.state} changes require decidedBy`,\n });\n }\n });\n\nexport type Level = z.infer<typeof levelSchema>;\nexport type ChangeState = z.infer<typeof changeStateSchema>;\nexport type ChangeEvidence = z.infer<typeof changeEvidenceSchema>;\nexport type Change = z.infer<typeof changeSchema>;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"communication-Kd9nU5RP.mjs","names":[],"sources":["../src/schema/communication.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { replyToSchema } from \"./common\";\nimport { changeIdSchema, repositoryIdsSchema, taskIdSchema } from \"./id\";\n\nexport const communicationOutcomes = [\n \"accepted\",\n \"started\",\n \"succeeded\",\n \"failed\",\n \"needs_human\",\n \"question\",\n \"digest\",\n \"rolled_back\",\n \"budget_warning\",\n \"budget_exhausted\",\n \"message\",\n] as const;\n\nexport const communicationOutcomeSchema = z\n .enum(communicationOutcomes)\n .describe(\"Lifecycle outcome a connector should render and deliver.\");\n\nexport const communicationEventSchema = z.strictObject({\n eventId: z.string().min(1).describe(\"Stable idempotency key for this delivery.\"),\n repositoryIds: repositoryIdsSchema,\n taskId: taskIdSchema.optional(),\n changeId: changeIdSchema.optional(),\n replyTo: replyToSchema,\n outcome: communicationOutcomeSchema,\n data: z.record(z.string(), z.unknown()).describe(\"Outcome-specific connector payload.\"),\n});\n\nexport type CommunicationOutcome = z.infer<typeof communicationOutcomeSchema>;\nexport type CommunicationEvent = z.infer<typeof communicationEventSchema>;\n"],"mappings":";;;AAIA,MAAa,wBAAwB;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,6BAA6B,EACvC,KAAK,qBAAqB,CAAC,CAC3B,SAAS,0DAA0D;AAEtE,MAAa,2BAA2B,EAAE,aAAa;CACrD,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,2CAA2C;CAC/E,eAAe;CACf,QAAQ,aAAa,SAAS;CAC9B,UAAU,eAAe,SAAS;CAClC,SAAS;CACT,SAAS;CACT,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,qCAAqC;AACxF,CAAC"}