@straiffi/archon 1.8.14 → 1.8.16

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 (250) hide show
  1. package/dist/client/assets/ActivityView-p8gBUxYN.js +1 -0
  2. package/dist/client/assets/GitHubActionsDialog-BRxGcSyq.js +1 -0
  3. package/dist/client/assets/VerificationDialog-B6l5TYOS.js +4 -0
  4. package/dist/client/assets/{arc-C83vRtlz.js → arc-D2Nn9xIj.js} +1 -1
  5. package/dist/client/assets/architecture-7EHR7CIX-C-4Cp4ml.js +1 -0
  6. package/dist/client/assets/{architectureDiagram-3BPJPVTR-DFbki8mi.js → architectureDiagram-3BPJPVTR-DnuKO1RY.js} +1 -1
  7. package/dist/client/assets/{blockDiagram-GPEHLZMM-BZFehG8P.js → blockDiagram-GPEHLZMM-CnQ7FwEp.js} +1 -1
  8. package/dist/client/assets/{c4Diagram-AAUBKEIU-FVDXRu1t.js → c4Diagram-AAUBKEIU-BF1hFXwp.js} +1 -1
  9. package/dist/client/assets/channel-TJtf4cBJ.js +1 -0
  10. package/dist/client/assets/{chunk-2J33WTMH-4tuVZaT0.js → chunk-2J33WTMH-UvCFvkZO.js} +1 -1
  11. package/dist/client/assets/{chunk-3OPIFGDE-DSn14S35.js → chunk-3OPIFGDE-z1l5nBD0.js} +1 -1
  12. package/dist/client/assets/{chunk-4BX2VUAB-C5pU9ApX.js → chunk-4BX2VUAB-CtLS8D71.js} +1 -1
  13. package/dist/client/assets/{chunk-4EGX6M5U-CAjWPjND.js → chunk-4EGX6M5U-Btnm0QNe.js} +1 -1
  14. package/dist/client/assets/{chunk-55IACEB6-DhO4-AG4.js → chunk-55IACEB6-74CcJaub.js} +1 -1
  15. package/dist/client/assets/{chunk-5DO6E6H7-BDKA-zHS.js → chunk-5DO6E6H7-WLZ8L4ko.js} +1 -1
  16. package/dist/client/assets/{chunk-5ZQYHXKU-Cwx1KNjg.js → chunk-5ZQYHXKU-Bis0Pw2_.js} +1 -1
  17. package/dist/client/assets/{chunk-727SXJPM-Odza4hes.js → chunk-727SXJPM-B3gUO8rD.js} +1 -1
  18. package/dist/client/assets/{chunk-AQP2D5EJ-BmVoQT7M.js → chunk-AQP2D5EJ-hPBzrrh5.js} +1 -1
  19. package/dist/client/assets/{chunk-BR22UD5L-12D2GWh4.js → chunk-BR22UD5L-Cou5beGe.js} +1 -1
  20. package/dist/client/assets/{chunk-BSJP7CBP-DMi77e84.js → chunk-BSJP7CBP-DJ57XcV5.js} +1 -1
  21. package/dist/client/assets/{chunk-CSCIHK7Q-Bg7Ktx0B.js → chunk-CSCIHK7Q-BfOng_VY.js} +2 -2
  22. package/dist/client/assets/{chunk-FHYWG6QK-BhSajKiB.js → chunk-FHYWG6QK-Ba10e2kj.js} +1 -1
  23. package/dist/client/assets/{chunk-FMBD7UC4-Drmlc0wM.js → chunk-FMBD7UC4-CEo2wZMx.js} +1 -1
  24. package/dist/client/assets/{chunk-KSCS5N6A-2tnhar2x.js → chunk-KSCS5N6A-B2Jg7PW5.js} +1 -1
  25. package/dist/client/assets/{chunk-L5ZTLDWV-dAyg8qMJ.js → chunk-L5ZTLDWV-CUYujZxt.js} +1 -1
  26. package/dist/client/assets/{chunk-LZXEDZCA-0gElxrlR.js → chunk-LZXEDZCA-CH_eV8jH.js} +2 -2
  27. package/dist/client/assets/{chunk-MPE355IW-Cw8YmjTC.js → chunk-MPE355IW-MqEt-J8G.js} +1 -1
  28. package/dist/client/assets/{chunk-MZUSXYTE-jvxRCZ7x.js → chunk-MZUSXYTE-DdNi9lhx.js} +1 -1
  29. package/dist/client/assets/{chunk-N66VUXT2-00i4y0yD.js → chunk-N66VUXT2-CjemTW4E.js} +1 -1
  30. package/dist/client/assets/{chunk-ND2GUHAM-Bu-8Lz91.js → chunk-ND2GUHAM-BVF5evM9.js} +1 -1
  31. package/dist/client/assets/{chunk-NZK2D7GU-CInZFdzd.js → chunk-NZK2D7GU-WfG-2AOS.js} +1 -1
  32. package/dist/client/assets/{chunk-O5CBEL6O-rAzpvdNR.js → chunk-O5CBEL6O-CSF9ozqy.js} +1 -1
  33. package/dist/client/assets/{chunk-PUPMXCY4-DfWourL7.js → chunk-PUPMXCY4-ZvwTw0To.js} +1 -1
  34. package/dist/client/assets/chunk-QZHKN3VN-LI_RZca2.js +1 -0
  35. package/dist/client/assets/{chunk-UIBZB4QT-v-a5ZfN6.js → chunk-UIBZB4QT-BTY9be9s.js} +1 -1
  36. package/dist/client/assets/{chunk-WCWK7LTN-CtYzhvvb.js → chunk-WCWK7LTN-Db1n3n3-.js} +1 -1
  37. package/dist/client/assets/chunk-WU5MYG2G-DoVpb2oe.js +1 -0
  38. package/dist/client/assets/{chunk-XPW4576I-CvnAuXH2.js → chunk-XPW4576I-DObFPxjB.js} +1 -1
  39. package/dist/client/assets/classDiagram-4FO5ZUOK-CnKIRKWC.js +1 -0
  40. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-5ZgjUwTv.js +1 -0
  41. package/dist/client/assets/{cose-bilkent-S5V4N54A-fchD-dH2.js → cose-bilkent-S5V4N54A-MlOPiG6P.js} +1 -1
  42. package/dist/client/assets/{dagre-BM42HDAG-Dgua1iuh.js → dagre-BM42HDAG-rekDIYnC.js} +1 -1
  43. package/dist/client/assets/{dagre-DSrzm-Gq.js → dagre-BWNHuDdf.js} +1 -1
  44. package/dist/client/assets/{diagram-2AECGRRQ-odacwlwu.js → diagram-2AECGRRQ-Z4mXdhW0.js} +1 -1
  45. package/dist/client/assets/{diagram-5GNKFQAL-BiKjFmJ1.js → diagram-5GNKFQAL-DqeVe5Vc.js} +1 -1
  46. package/dist/client/assets/{diagram-KO2AKTUF-CmYcvFri.js → diagram-KO2AKTUF-ijppTuNc.js} +1 -1
  47. package/dist/client/assets/{diagram-LMA3HP47-ncx0RBuX.js → diagram-LMA3HP47-CDGLx0-N.js} +1 -1
  48. package/dist/client/assets/{diagram-OG6HWLK6-DbchKIzw.js → diagram-OG6HWLK6-DDlnjzF8.js} +1 -1
  49. package/dist/client/assets/{erDiagram-TEJ5UH35-CMnpvRyQ.js → erDiagram-TEJ5UH35-V_axe9oz.js} +1 -1
  50. package/dist/client/assets/eventmodeling-FCH6USID-Dqb6QKoI.js +1 -0
  51. package/dist/client/assets/{flowDiagram-I6XJVG4X-Bi02_PK5.js → flowDiagram-I6XJVG4X-GH5q79jg.js} +1 -1
  52. package/dist/client/assets/{ganttDiagram-6RSMTGT7-BiS992US.js → ganttDiagram-6RSMTGT7-BMWVdLeQ.js} +1 -1
  53. package/dist/client/assets/gitGraph-WXDBUCRP-DYEsqh93.js +1 -0
  54. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-Cc1hrTsT.js → gitGraphDiagram-PVQCEYII-VrV8jMUg.js} +1 -1
  55. package/dist/client/assets/index-B7J4DYDu.js +275 -0
  56. package/dist/client/assets/index-CsZfTdMO.css +2 -0
  57. package/dist/client/assets/info-J43DQDTF-CfjXFZai.js +1 -0
  58. package/dist/client/assets/{infoDiagram-5YYISTIA-BKVfqJCe.js → infoDiagram-5YYISTIA-EGiVbp17.js} +1 -1
  59. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-B-IbFOty.js → ishikawaDiagram-YF4QCWOH-Dw3CiXbm.js} +1 -1
  60. package/dist/client/assets/{journeyDiagram-JHISSGLW-DAZBgAQW.js → journeyDiagram-JHISSGLW-2S631RY5.js} +1 -1
  61. package/dist/client/assets/{kanban-definition-UN3LZRKU-Bkr_fXev.js → kanban-definition-UN3LZRKU-pc9vzUtB.js} +1 -1
  62. package/dist/client/assets/{line-CROuuXDO.js → line-BBMBmEjI.js} +1 -1
  63. package/dist/client/assets/{linear-BOwW57yX.js → linear-DT4rSZvy.js} +1 -1
  64. package/dist/client/assets/{mermaid-parser.core-DrBw_Rsc.js → mermaid-parser.core-ClNeolx0.js} +2 -2
  65. package/dist/client/assets/{mermaid.core-pPd6OYYj.js → mermaid.core-Q4IJbm5V.js} +3 -3
  66. package/dist/client/assets/{mindmap-definition-RKZ34NQL-BXSd3TZU.js → mindmap-definition-RKZ34NQL-DUTZxR8H.js} +1 -1
  67. package/dist/client/assets/{ordinal-CZ33lFpK.js → ordinal-k--hYEme.js} +1 -1
  68. package/dist/client/assets/packet-YPE3B663-Dv0HkRHU.js +1 -0
  69. package/dist/client/assets/pie-LRSECV5Y-S5zPzZFN.js +1 -0
  70. package/dist/client/assets/{pieDiagram-4H26LBE5-DoT7PIZC.js → pieDiagram-4H26LBE5-RW5hNtJq.js} +1 -1
  71. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-ycZkLowm.js → quadrantDiagram-W4KKPZXB-CK60c7X9.js} +1 -1
  72. package/dist/client/assets/radar-GUYGQ44K-B7psLv22.js +1 -0
  73. package/dist/client/assets/{requirementDiagram-4Y6WPE33-BPkO1yLu.js → requirementDiagram-4Y6WPE33-Dz35FvcC.js} +1 -1
  74. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-D7AvhhCw.js → sankeyDiagram-5OEKKPKP-ByyluoXu.js} +1 -1
  75. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-C982swnH.js → sequenceDiagram-3UESZ5HK-C-879UFe.js} +1 -1
  76. package/dist/client/assets/{stateDiagram-AJRCARHV-xvJ3u8lc.js → stateDiagram-AJRCARHV-B8neDlUu.js} +1 -1
  77. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-B4Mq8Abu.js +1 -0
  78. package/dist/client/assets/{timeline-definition-PNZ67QCA-D89qjzb5.js → timeline-definition-PNZ67QCA-iAwrltn1.js} +1 -1
  79. package/dist/client/assets/treeView-BLDUP644-B8H0kT67.js +1 -0
  80. package/dist/client/assets/treemap-LRROVOQU-DPLhFHnh.js +1 -0
  81. package/dist/client/assets/{vennDiagram-CIIHVFJN-CoKeC__u.js → vennDiagram-CIIHVFJN-DHN61m8d.js} +1 -1
  82. package/dist/client/assets/wardley-L42UT6IY-B5-Vb08V.js +1 -0
  83. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DKhjzvSE.js → wardleyDiagram-YWT4CUSO-XDVo7Jy1.js} +1 -1
  84. package/dist/client/assets/{xychartDiagram-2RQKCTM6-DFn9ass1.js → xychartDiagram-2RQKCTM6-Cb-HLpaN.js} +1 -1
  85. package/dist/client/index.html +2 -2
  86. package/dist/server/db.js +237 -0
  87. package/dist/server/db.js.map +1 -1
  88. package/dist/server/index.js +211 -87
  89. package/dist/server/index.js.map +1 -1
  90. package/dist/server/lib/agent.js +198 -100
  91. package/dist/server/lib/agent.js.map +1 -1
  92. package/dist/server/lib/agentProvider.js +14 -9
  93. package/dist/server/lib/agentProvider.js.map +1 -1
  94. package/dist/server/lib/agentRuns.js +20 -9
  95. package/dist/server/lib/agentRuns.js.map +1 -1
  96. package/dist/server/lib/buildExecutionEnvironment.js +517 -0
  97. package/dist/server/lib/buildExecutionEnvironment.js.map +1 -0
  98. package/dist/server/lib/buildOpenQuestionOperations.js +9 -3
  99. package/dist/server/lib/buildOpenQuestionOperations.js.map +1 -1
  100. package/dist/server/lib/chatOperations.js +30 -1
  101. package/dist/server/lib/chatOperations.js.map +1 -1
  102. package/dist/server/lib/checkAutoFix.js +1 -0
  103. package/dist/server/lib/checkAutoFix.js.map +1 -1
  104. package/dist/server/lib/checkRepairDispatch.js +3 -1
  105. package/dist/server/lib/checkRepairDispatch.js.map +1 -1
  106. package/dist/server/lib/dockerSandboxCredentials.js +62 -0
  107. package/dist/server/lib/dockerSandboxCredentials.js.map +1 -0
  108. package/dist/server/lib/dockerSandboxEnvironmentOperations.js +54 -0
  109. package/dist/server/lib/dockerSandboxEnvironmentOperations.js.map +1 -0
  110. package/dist/server/lib/dockerSandboxExecutionEnvironment.js +631 -0
  111. package/dist/server/lib/dockerSandboxExecutionEnvironment.js.map +1 -0
  112. package/dist/server/lib/dockerSandboxExecutionProvider.js +196 -0
  113. package/dist/server/lib/dockerSandboxExecutionProvider.js.map +1 -0
  114. package/dist/server/lib/dockerSandboxOpencodeSessionOperations.js +29 -0
  115. package/dist/server/lib/dockerSandboxOpencodeSessionOperations.js.map +1 -0
  116. package/dist/server/lib/dockerSandboxRuntimeController.js +187 -0
  117. package/dist/server/lib/dockerSandboxRuntimeController.js.map +1 -0
  118. package/dist/server/lib/executionEnvironment.js +22 -0
  119. package/dist/server/lib/executionEnvironment.js.map +1 -1
  120. package/dist/server/lib/executionEnvironmentContexts.js +144 -0
  121. package/dist/server/lib/executionEnvironmentContexts.js.map +1 -0
  122. package/dist/server/lib/executionEnvironmentLifecycle.js +63 -0
  123. package/dist/server/lib/executionEnvironmentLifecycle.js.map +1 -0
  124. package/dist/server/lib/executionEnvironmentReconciliation.js +782 -0
  125. package/dist/server/lib/executionEnvironmentReconciliation.js.map +1 -0
  126. package/dist/server/lib/executionEnvironmentRoutes.js +354 -0
  127. package/dist/server/lib/executionEnvironmentRoutes.js.map +1 -0
  128. package/dist/server/lib/executionEnvironmentValidation.js +486 -0
  129. package/dist/server/lib/executionEnvironmentValidation.js.map +1 -0
  130. package/dist/server/lib/executionEnvironmentValidationOperations.js +635 -0
  131. package/dist/server/lib/executionEnvironmentValidationOperations.js.map +1 -0
  132. package/dist/server/lib/executionEnvironments.js +726 -0
  133. package/dist/server/lib/executionEnvironments.js.map +1 -0
  134. package/dist/server/lib/executionReconciliation.js +77 -0
  135. package/dist/server/lib/executionReconciliation.js.map +1 -1
  136. package/dist/server/lib/executionRetry.js +3 -0
  137. package/dist/server/lib/executionRetry.js.map +1 -1
  138. package/dist/server/lib/executionRuns.js +1 -0
  139. package/dist/server/lib/executionRuns.js.map +1 -1
  140. package/dist/server/lib/executionTargets.js +107 -0
  141. package/dist/server/lib/executionTargets.js.map +1 -0
  142. package/dist/server/lib/executionTimeline.js +3 -0
  143. package/dist/server/lib/executionTimeline.js.map +1 -1
  144. package/dist/server/lib/git.js +32 -1
  145. package/dist/server/lib/git.js.map +1 -1
  146. package/dist/server/lib/hostExecutionEnvironment.js +47 -1
  147. package/dist/server/lib/hostExecutionEnvironment.js.map +1 -1
  148. package/dist/server/lib/lightweightPrompt.js +1 -0
  149. package/dist/server/lib/lightweightPrompt.js.map +1 -1
  150. package/dist/server/lib/mobileAccess.js +2 -2
  151. package/dist/server/lib/mobileAccess.js.map +1 -1
  152. package/dist/server/lib/models.js +11 -0
  153. package/dist/server/lib/models.js.map +1 -1
  154. package/dist/server/lib/opencodeErrors.js +31 -3
  155. package/dist/server/lib/opencodeErrors.js.map +1 -1
  156. package/dist/server/lib/opencodeExecutionReliability.js +52 -0
  157. package/dist/server/lib/opencodeExecutionReliability.js.map +1 -0
  158. package/dist/server/lib/opencodeSessionOperations.js +210 -20
  159. package/dist/server/lib/opencodeSessionOperations.js.map +1 -1
  160. package/dist/server/lib/opencodeTaskSessions.js +7 -12
  161. package/dist/server/lib/opencodeTaskSessions.js.map +1 -1
  162. package/dist/server/lib/postBuildChecks.js +2 -1
  163. package/dist/server/lib/postBuildChecks.js.map +1 -1
  164. package/dist/server/lib/projectAutoConfig.js +1 -0
  165. package/dist/server/lib/projectAutoConfig.js.map +1 -1
  166. package/dist/server/lib/projects.js +10 -0
  167. package/dist/server/lib/projects.js.map +1 -1
  168. package/dist/server/lib/specArtifact.js +20 -1
  169. package/dist/server/lib/specArtifact.js.map +1 -1
  170. package/dist/server/lib/specBundleGroups.js +151 -0
  171. package/dist/server/lib/specBundleGroups.js.map +1 -0
  172. package/dist/server/lib/specDraft.js +1 -5
  173. package/dist/server/lib/specDraft.js.map +1 -1
  174. package/dist/server/lib/specExport.js +2 -6
  175. package/dist/server/lib/specExport.js.map +1 -1
  176. package/dist/server/lib/specFormatting.js +13 -0
  177. package/dist/server/lib/specFormatting.js.map +1 -1
  178. package/dist/server/lib/specGraphFeature.js +3 -0
  179. package/dist/server/lib/specGraphFeature.js.map +1 -0
  180. package/dist/server/lib/specRepositoryEvidenceFormatting.js +2 -1
  181. package/dist/server/lib/specRepositoryEvidenceFormatting.js.map +1 -1
  182. package/dist/server/lib/specRepositoryImpact.js +4 -0
  183. package/dist/server/lib/specRepositoryImpact.js.map +1 -1
  184. package/dist/server/lib/specReviewContext.js +6 -20
  185. package/dist/server/lib/specReviewContext.js.map +1 -1
  186. package/dist/server/lib/specReviewValidation.js +22 -1
  187. package/dist/server/lib/specReviewValidation.js.map +1 -1
  188. package/dist/server/lib/specReviews.js +1 -1
  189. package/dist/server/lib/specSections.js +8 -1
  190. package/dist/server/lib/specSections.js.map +1 -1
  191. package/dist/server/lib/specSnapshotEvidence.js +4 -0
  192. package/dist/server/lib/specSnapshotEvidence.js.map +1 -1
  193. package/dist/server/lib/specTicketMaterialization.js +122 -0
  194. package/dist/server/lib/specTicketMaterialization.js.map +1 -0
  195. package/dist/server/lib/specs.js +27 -5
  196. package/dist/server/lib/specs.js.map +1 -1
  197. package/dist/server/lib/ticketFollowUpOperations.js +8 -1
  198. package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
  199. package/dist/server/lib/ticketRunOperations.js +0 -3
  200. package/dist/server/lib/ticketRunOperations.js.map +1 -1
  201. package/dist/server/lib/types.js +1 -0
  202. package/dist/server/lib/types.js.map +1 -1
  203. package/dist/server/lib/workspaceIdentity.js +3 -0
  204. package/dist/server/lib/workspaceIdentity.js.map +1 -1
  205. package/dist/server/workers/build.js +114 -8
  206. package/dist/server/workers/build.js.map +1 -1
  207. package/dist/server/workers/followUp.js +143 -7
  208. package/dist/server/workers/followUp.js.map +1 -1
  209. package/dist/server/workers/plan.js +57 -24
  210. package/dist/server/workers/plan.js.map +1 -1
  211. package/dist/server/workers/review.js +43 -23
  212. package/dist/server/workers/review.js.map +1 -1
  213. package/dist/server/workers/specReview.js +7 -2
  214. package/dist/server/workers/specReview.js.map +1 -1
  215. package/dist/server/workers/specSession.js +109 -153
  216. package/dist/server/workers/specSession.js.map +1 -1
  217. package/package.json +1 -1
  218. package/dist/client/assets/ActivityView-DYDYyqIN.js +0 -1
  219. package/dist/client/assets/GitHubActionsDialog-jhi4GOyV.js +0 -1
  220. package/dist/client/assets/RepositoryGraphDialog-BZV0vHu6.js +0 -1
  221. package/dist/client/assets/VerificationDialog-Sc6e8AKH.js +0 -4
  222. package/dist/client/assets/architecture-7EHR7CIX-Dm8H7N6Z.js +0 -1
  223. package/dist/client/assets/channel-D1kOpezG.js +0 -1
  224. package/dist/client/assets/chunk-QZHKN3VN-CtbsU1Bj.js +0 -1
  225. package/dist/client/assets/chunk-WU5MYG2G-DOOw2vq7.js +0 -1
  226. package/dist/client/assets/classDiagram-4FO5ZUOK-C253nwny.js +0 -1
  227. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DFgDA23g.js +0 -1
  228. package/dist/client/assets/eventmodeling-FCH6USID-BWhw0UJ8.js +0 -1
  229. package/dist/client/assets/gitGraph-WXDBUCRP-BSnxAa1J.js +0 -1
  230. package/dist/client/assets/index-B1gdJKwK.js +0 -275
  231. package/dist/client/assets/index-CCQwWUKF.css +0 -2
  232. package/dist/client/assets/info-J43DQDTF-DcFwF1-h.js +0 -1
  233. package/dist/client/assets/packet-YPE3B663-1VZiO_9r.js +0 -1
  234. package/dist/client/assets/pie-LRSECV5Y-BX1-tQCu.js +0 -1
  235. package/dist/client/assets/radar-GUYGQ44K-B2HRrCR4.js +0 -1
  236. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-BKQG8NCn.js +0 -1
  237. package/dist/client/assets/treeView-BLDUP644-CDfUVbUi.js +0 -1
  238. package/dist/client/assets/treemap-LRROVOQU-DUWqu8sK.js +0 -1
  239. package/dist/client/assets/wardley-L42UT6IY-BEFuPUCy.js +0 -1
  240. /package/dist/client/assets/{array-B2f2amhX.js → array-BNor45A1.js} +0 -0
  241. /package/dist/client/assets/{chunk-NNHCCRGN-DgKrp8T-.js → chunk-NNHCCRGN-CZB-V-Gv.js} +0 -0
  242. /package/dist/client/assets/{cytoscape.esm-BInZCgaJ.js → cytoscape.esm-B2lJcMSI.js} +0 -0
  243. /package/dist/client/assets/{defaultLocale-sPXJ5urm.js → defaultLocale-DPzUsThw.js} +0 -0
  244. /package/dist/client/assets/{dist-DfHDMDTt.js → dist-CERhmQhR.js} +0 -0
  245. /package/dist/client/assets/{graphlib-DacNv4Jd.js → graphlib-BHOW-eWz.js} +0 -0
  246. /package/dist/client/assets/{init-BVCnG1lj.js → init-C0L3woqb.js} +0 -0
  247. /package/dist/client/assets/{katex-BlkrXOwm.js → katex-CpjQsUQe.js} +0 -0
  248. /package/dist/client/assets/{path-Bw5AvBNC.js → path-sMK4d_s9.js} +0 -0
  249. /package/dist/client/assets/{rough.esm-DeLgKbOI.js → rough.esm-BoTisKeL.js} +0 -0
  250. /package/dist/client/assets/{src-CFGsdLiG.js → src-BRjoYtUW.js} +0 -0
@@ -10,10 +10,13 @@ import { adjectives, animals, uniqueNamesGenerator } from 'unique-names-generato
10
10
  import db from './db.js';
11
11
  import { pruneAllRepositoryGraphScans } from './lib/repositoryGraphRetention.js';
12
12
  import { registerRepositoryGraphRoutes } from './lib/repositoryGraphRoutes.js';
13
+ import { registerExecutionEnvironmentRoutes } from './lib/executionEnvironmentRoutes.js';
14
+ import { dockerSandboxAdapter, dockerSandboxRunner, dockerSandboxRuntimeController, } from './lib/dockerSandboxEnvironmentOperations.js';
13
15
  import { deleteChatSession, getChatSession, listChatSessions } from './lib/chats.js';
14
16
  import { deleteSpecSession, getCreatedTicketIdsForSnapshot, getSpecSession, getSpecSnapshot, listSpecSessions } from './lib/specs.js';
15
17
  import { getSpecSnapshotRepositoryEvidenceFreshness } from './lib/specSnapshotEvidence.js';
16
18
  import { projectSpecSnapshotForActionPrompt } from './lib/specRepositoryEvidenceFormatting.js';
19
+ import { MULTI_BUNDLE_SPEC_CHAT_UNAVAILABLE_ERROR, hasMultipleSpecBundleGroups } from './lib/specBundleGroups.js';
17
20
  import { createChatAttachment, createSpecAttachment, getAttachmentById, deleteChatAttachment, deleteProjectAttachments, deleteSpecSessionAttachment, getChatAttachmentForSession, getChatAttachmentLinkedMessageId, getSpecAttachmentForSession, getSpecAttachmentLinkedMessageId, MAX_CHAT_ATTACHMENTS_PER_TURN, MAX_CHAT_ATTACHMENT_SIZE_BYTES, MAX_SPEC_ATTACHMENTS_PER_TURN, MAX_SPEC_ATTACHMENT_SIZE_BYTES, readChatAttachmentContent, readSpecAttachmentContent, validateImageAttachment, } from './lib/attachments.js';
18
21
  import { createProjectChatSession, resolveChatTool, resolveProjectChatPlanQuestionSet, stopProjectChatSessionResponse, submitProjectChatSessionMessage, updateProjectChatSessionMode, } from './lib/chatOperations.js';
19
22
  import { createProjectSpecSession, deleteProjectSpecSession, resolveProjectSpecPlanQuestionSet, stopProjectSpecSessionResponse, submitProjectSpecSessionMessage, updateProjectSpecSessionMode, } from './lib/specOperations.js';
@@ -81,6 +84,9 @@ import { buildImportedIssueSessionTitle, importProviderHostedIssueImages } from
81
84
  import { dispatchGitHubWorkflow, getGitHubWorkflowDispatchConfig, getGitHubWorkflowRun, getGitHubWorkflowRunJobs, listGitHubWorkflows, listGitHubWorkflowRuns, } from './lib/integrations/githubActions.js';
82
85
  import { clearAllGitHubActionsSessions, getActiveTrackedRunCount, getTrackedGitHubActionsRuns, startGitHubActionsPolling, trackGitHubActionsRun, } from './lib/integrations/githubActionsSessions.js';
83
86
  import { reconcileStartupExecutions } from './lib/executionReconciliation.js';
87
+ import { cleanupProjectExecutionEnvironments, cleanupExecutionEnvironmentsForTarget, ExecutionEnvironmentCleanupError, reconcileOrphanedExecutionEnvironments, reconcileExecutionEnvironments, reconcileProductionExecutionEnvironmentBindings, } from './lib/executionEnvironmentReconciliation.js';
88
+ import { createExecutionTargetKey } from './lib/executionTargets.js';
89
+ import { getExecutionEnvironmentContextForRun } from './lib/executionEnvironmentContexts.js';
84
90
  import { PlanningReferenceError, resolveExternalPlanningDescription } from './lib/integrations/planning.js';
85
91
  import { refreshIfNeeded as refreshAssignedIssues, clearCachedAssignedIssues } from './lib/integrations/assignedIssuesCache.js';
86
92
  import { buildCommitMessagePrompt, normalizeGeneratedCommitMessage } from './lib/commitMessage.js';
@@ -116,7 +122,8 @@ import { parseIncomingExternalSource } from './lib/externalSource.js';
116
122
  import { resolveReviewerConfig } from './lib/reviewerConfig.js';
117
123
  import { materializeTicketsWithDependencies } from './lib/ticketBatch.js';
118
124
  import { IMPLEMENTATION_READY_DESCRIPTION_SECTION_HEADINGS } from './lib/ticketDescriptionContract.js';
119
- import { buildImplementationResourcesAppendix, buildSpecImplementationDraft, buildVisualizationAppendix } from './lib/specDraft.js';
125
+ import { buildSpecImplementationDraft } from './lib/specDraft.js';
126
+ import { materializeSpecSnapshotTickets } from './lib/specTicketMaterialization.js';
120
127
  import { exportSpecToDocs, checkSpecExportCollision, SpecExportCollisionError } from './lib/specExport.js';
121
128
  import { createTicketDependency, deleteTicketDependenciesForTicket, deleteTicketDependency, getTicketDependency, isTicketBuildComplete, isTicketRunSetupReady, listTicketDependencies, validateCreateTicketDependency, } from './lib/ticketDependencies.js';
122
129
  import { startBuild } from './workers/build.js';
@@ -451,6 +458,7 @@ const buildExecutionRunDetailResponse = async (project, run) => {
451
458
  details,
452
459
  agent_runs: listAgentRunsForExecutionRun(run.id),
453
460
  ...artifacts,
461
+ environment_context: getExecutionEnvironmentContextForRun(project.id, run.id),
454
462
  };
455
463
  };
456
464
  const formatWorktreeDeleteError = (target, branch, error) => {
@@ -504,6 +512,25 @@ const getBundlePlanBlockerError = () => {
504
512
  const hasActiveBundleCheckWork = (projectId, bundleId) => Boolean(getActiveBundleRepairBlocker(bundleId)
505
513
  || findActiveCheckBatchForTarget(projectId, 'bundle', bundleId)
506
514
  || findActiveCheckAutoFixForTarget(projectId, 'bundle', bundleId));
515
+ const cleanupWorktreeExecutionTarget = async ({ project, targetKind, targetKey, targetLabel, worktreeTarget, branch, }) => {
516
+ try {
517
+ await cleanupExecutionEnvironmentsForTarget({
518
+ projectId: project.id,
519
+ targetKind,
520
+ targetKey,
521
+ });
522
+ }
523
+ catch (error) {
524
+ const message = error instanceof Error ? error.message : 'Docker Sandbox cleanup could not be verified.';
525
+ throw new HttpError(409, `Cannot delete ${targetLabel} until its Docker Sandbox cleanup completes: ${message}`);
526
+ }
527
+ try {
528
+ deleteWorktree(branch, project);
529
+ }
530
+ catch (error) {
531
+ throw new HttpError(500, formatWorktreeDeleteError(worktreeTarget, branch, error));
532
+ }
533
+ };
507
534
  const deleteTicketRecord = async (ticket) => {
508
535
  if (ticket.project_id
509
536
  && ticket.worktree_bundle_id
@@ -522,19 +549,54 @@ const deleteTicketRecord = async (ticket) => {
522
549
  const project = getEffectiveProject(ticket);
523
550
  if (project) {
524
551
  try {
525
- deleteWorktree(branch, project);
552
+ await cleanupWorktreeExecutionTarget({
553
+ project,
554
+ targetKind: 'branch-worktree',
555
+ targetKey: createExecutionTargetKey(project.id, { kind: 'branch-worktree', bundleId: null, branch }),
556
+ targetLabel: 'ticket worktree',
557
+ worktreeTarget: 'ticket',
558
+ branch,
559
+ });
526
560
  }
527
561
  catch (error) {
528
562
  return {
529
563
  ok: false,
530
- status: 500,
531
- error: formatWorktreeDeleteError('ticket', branch, error),
564
+ status: error instanceof HttpError ? error.status : 500,
565
+ error: error instanceof Error ? error.message : 'Unable to delete the ticket worktree',
532
566
  };
533
567
  }
534
568
  }
535
569
  }
536
570
  const bundledProject = isBundledTicket(ticket) ? getEffectiveProject(ticket) : null;
537
571
  const deletedBundleId = ticket.worktree_bundle_id;
572
+ const deletedBundle = bundledProject && deletedBundleId ? getBundle(deletedBundleId, bundledProject.id) : null;
573
+ const bundleResourcesWereCleaned = Boolean(bundledProject
574
+ && deletedBundle
575
+ && !isProjectRootBundle(deletedBundle)
576
+ && countBundleTickets(deletedBundle.id, bundledProject.id) === 1);
577
+ if (bundleResourcesWereCleaned && bundledProject && deletedBundle) {
578
+ try {
579
+ await cleanupWorktreeExecutionTarget({
580
+ project: bundledProject,
581
+ targetKind: 'bundle-worktree',
582
+ targetKey: createExecutionTargetKey(bundledProject.id, {
583
+ kind: 'bundle-worktree',
584
+ bundleId: deletedBundle.id,
585
+ branch: deletedBundle.branch,
586
+ }),
587
+ targetLabel: 'bundle worktree',
588
+ worktreeTarget: 'bundle',
589
+ branch: deletedBundle.branch,
590
+ });
591
+ }
592
+ catch (error) {
593
+ return {
594
+ ok: false,
595
+ status: error instanceof HttpError ? error.status : 500,
596
+ error: error instanceof Error ? error.message : 'Unable to delete the bundle worktree',
597
+ };
598
+ }
599
+ }
538
600
  let nextBuildTicketId = null;
539
601
  let nextBuildSequenceId = null;
540
602
  let affectedTicketIds = [];
@@ -555,7 +617,7 @@ const deleteTicketRecord = async (ticket) => {
555
617
  }
556
618
  if (bundledProject && deletedBundleId) {
557
619
  try {
558
- cleanupBundleIfEmpty(deletedBundleId, bundledProject);
620
+ await cleanupBundleIfEmpty(deletedBundleId, bundledProject, { resourcesAlreadyCleaned: bundleResourcesWereCleaned });
559
621
  }
560
622
  catch (error) {
561
623
  return {
@@ -868,7 +930,7 @@ const createAutoBundleForName = (name, projectId, baseBranch = null) => {
868
930
  }
869
931
  return bundle;
870
932
  };
871
- const cleanupBundleIfEmpty = (bundleId, project) => {
933
+ const cleanupBundleIfEmpty = async (bundleId, project, options = {}) => {
872
934
  if (!bundleId) {
873
935
  return;
874
936
  }
@@ -882,11 +944,19 @@ const cleanupBundleIfEmpty = (bundleId, project) => {
882
944
  if (hasActiveBundleCheckWork(project.id, bundle.id)) {
883
945
  throw new HttpError(409, 'Cannot delete a bundle while check work is active');
884
946
  }
885
- try {
886
- deleteWorktree(bundle.branch, project);
887
- }
888
- catch (error) {
889
- throw new HttpError(500, formatWorktreeDeleteError('bundle', bundle.branch, error));
947
+ if (!options.resourcesAlreadyCleaned) {
948
+ await cleanupWorktreeExecutionTarget({
949
+ project,
950
+ targetKind: 'bundle-worktree',
951
+ targetKey: createExecutionTargetKey(project.id, {
952
+ kind: 'bundle-worktree',
953
+ bundleId: bundle.id,
954
+ branch: bundle.branch,
955
+ }),
956
+ targetLabel: 'bundle worktree',
957
+ worktreeTarget: 'bundle',
958
+ branch: bundle.branch,
959
+ });
890
960
  }
891
961
  deleteBundle(bundle.id, project.id);
892
962
  };
@@ -1356,6 +1426,8 @@ const listDetailedBundleTickets = (projectId, bundleId) => {
1356
1426
  const representative = getBundleRepresentativeTicketContext(projectId, bundleId);
1357
1427
  return representative ? sortBundleTicketsByExecutionOrder(listTicketsInRunContext(representative)) : [];
1358
1428
  };
1429
+ const listBoardBundleTickets = (projectId, bundleId) => listTickets(projectId, { detail: 'board' })
1430
+ .filter(ticket => ticket.worktree_bundle_id === bundleId);
1359
1431
  const listBundleConversationTickets = (projectId, bundleId) => {
1360
1432
  const representative = getBundleRepresentativeTicketContext(projectId, bundleId);
1361
1433
  return representative
@@ -2478,6 +2550,12 @@ const emitRunStateForContext = (ticket, isRunningValue) => {
2478
2550
  };
2479
2551
  app.use(express.json({ limit: '5mb' }));
2480
2552
  registerRepositoryGraphRoutes(app, { emitter: io });
2553
+ registerExecutionEnvironmentRoutes(app, {
2554
+ emitter: io,
2555
+ runner: dockerSandboxRunner,
2556
+ adapter: dockerSandboxAdapter,
2557
+ runtimeController: dockerSandboxRuntimeController,
2558
+ });
2481
2559
  const requireDesktopMobileAccessRequest = (req, res) => {
2482
2560
  const rejectionReason = validateDesktopMobileAccessRequest(req);
2483
2561
  if (!rejectionReason) {
@@ -2596,7 +2674,7 @@ app.post('/projects/:id/chat-sessions', (req, res) => {
2596
2674
  }
2597
2675
  return res.status(result.status).json(result.value);
2598
2676
  });
2599
- app.get('/projects/:id/chat-sessions/:sessionId', (req, res) => {
2677
+ app.get('/projects/:id/chat-sessions/:sessionId', async (req, res) => {
2600
2678
  const project = getProjectById(req.params.id);
2601
2679
  if (!project) {
2602
2680
  return res.status(404).json({ error: 'Not found' });
@@ -2605,7 +2683,7 @@ app.get('/projects/:id/chat-sessions/:sessionId', (req, res) => {
2605
2683
  if (!chatSession) {
2606
2684
  return res.status(404).json({ error: 'Not found' });
2607
2685
  }
2608
- const refreshedChatSession = refreshChatSessionUsageSnapshot(chatSession.id, { includeMessages: true });
2686
+ const refreshedChatSession = await refreshChatSessionUsageSnapshot(chatSession.id, { includeMessages: true });
2609
2687
  if (!refreshedChatSession || refreshedChatSession.project_id !== project.id) {
2610
2688
  return res.json(chatSession);
2611
2689
  }
@@ -2906,7 +2984,7 @@ app.post('/projects/:id/spec-sessions', (req, res) => {
2906
2984
  }
2907
2985
  return res.status(result.status).json(result.value);
2908
2986
  });
2909
- app.get('/projects/:id/spec-sessions/:sessionId', (req, res) => {
2987
+ app.get('/projects/:id/spec-sessions/:sessionId', async (req, res) => {
2910
2988
  const project = getProjectById(req.params.id);
2911
2989
  if (!project) {
2912
2990
  return res.status(404).json({ error: 'Not found' });
@@ -2915,7 +2993,7 @@ app.get('/projects/:id/spec-sessions/:sessionId', (req, res) => {
2915
2993
  if (!specSession) {
2916
2994
  return res.status(404).json({ error: 'Not found' });
2917
2995
  }
2918
- const refreshedSpecSession = refreshSpecSessionUsageSnapshot(specSession.id, { includeMessages: true });
2996
+ const refreshedSpecSession = await refreshSpecSessionUsageSnapshot(specSession.id, { includeMessages: true });
2919
2997
  if (!refreshedSpecSession || refreshedSpecSession.project_id !== project.id) {
2920
2998
  return res.json(specSession);
2921
2999
  }
@@ -3153,50 +3231,17 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/create-ti
3153
3231
  error: `Spec tickets must include testing or verification guidance in their descriptions before they can be created on the board. Missing guidance in: ${ticketKeys}`,
3154
3232
  });
3155
3233
  }
3156
- let generatedBundleId = null;
3157
3234
  try {
3158
3235
  const targetResult = resolveSessionTargetForExecution(specSession, project, 'Spec session');
3159
3236
  if (!targetResult.ok) {
3160
3237
  throw new HttpError(409, targetResult.error);
3161
3238
  }
3162
3239
  const target = targetResult.target;
3163
- const bundleName = specSession.external_source?.external_key ?? '';
3164
- const bundle = target.target_kind === 'bundle'
3165
- ? target.target_bundle_id ? getBundle(target.target_bundle_id, project.id) : null
3166
- : bundleName
3167
- ? createAutoBundleForName(bundleName, project.id, target.branch)
3168
- : createAutoPlanningBundle(project.id, target.branch);
3169
- if (!bundle || isProjectRootBundle(bundle)) {
3170
- throw new HttpError(409, 'Unable to create a bundle for this Spec snapshot.');
3171
- }
3172
- if (target.target_kind === 'repo_root') {
3173
- generatedBundleId = bundle.id;
3174
- }
3175
- const ticketsForMaterialization = snapshot.tickets.map(ticket => {
3176
- const appendices = [
3177
- buildVisualizationAppendix(ticket.relevant_visualizations ?? [], snapshot),
3178
- buildImplementationResourcesAppendix(snapshot.resource_urls),
3179
- ].filter(Boolean);
3180
- return {
3181
- key: ticket.key,
3182
- title: ticket.title,
3183
- description: appendices.length > 0 ? `${ticket.description}\n\n${appendices.join('\n\n')}` : ticket.description,
3184
- };
3185
- });
3186
- const { createdTickets, createdDependencies } = materializeTicketsWithDependencies({
3187
- options: {
3188
- projectId: project.id,
3189
- model: specSession.model,
3190
- variant: specSession.variant,
3191
- skills: specSession.skills,
3192
- tool: null,
3193
- worktreeBundleId: bundle.id,
3194
- originSpecSessionId: specSession.id,
3195
- originSpecSnapshotId: snapshot.id,
3196
- externalSource: specSession.external_source ?? null,
3197
- },
3198
- tickets: ticketsForMaterialization,
3199
- dependencies: snapshot.dependencies,
3240
+ const { createdTickets, createdDependencies } = materializeSpecSnapshotTickets({
3241
+ project,
3242
+ specSession,
3243
+ snapshot,
3244
+ target,
3200
3245
  });
3201
3246
  for (const createdTicket of createdTickets) {
3202
3247
  io.emit('ticket:created', createdTicket);
@@ -3210,9 +3255,6 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/create-ti
3210
3255
  });
3211
3256
  }
3212
3257
  catch (error) {
3213
- if (generatedBundleId) {
3214
- cleanupBundleIfEmpty(generatedBundleId, project);
3215
- }
3216
3258
  if (error instanceof HttpError) {
3217
3259
  return res.status(error.status).json({ error: error.message });
3218
3260
  }
@@ -3236,6 +3278,9 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/implement
3236
3278
  if (!targetResult.ok) {
3237
3279
  return res.status(409).json({ error: targetResult.error });
3238
3280
  }
3281
+ if (hasMultipleSpecBundleGroups(snapshot.bundle_groups)) {
3282
+ return res.status(409).json({ error: MULTI_BUNDLE_SPEC_CHAT_UNAVAILABLE_ERROR });
3283
+ }
3239
3284
  const repositoryEvidenceFreshness = await getSpecSnapshotRepositoryEvidenceFreshness(project, snapshot.repository_evidence, { uncached: true });
3240
3285
  const promptSnapshot = projectSpecSnapshotForActionPrompt(snapshot, repositoryEvidenceFreshness);
3241
3286
  const draftText = buildSpecImplementationDraft({
@@ -3879,7 +3924,7 @@ app.post('/bundles', async (req, res) => {
3879
3924
  }
3880
3925
  res.status(201).json(serializeBundleRow(result.project.id, bundle, [], result.project));
3881
3926
  });
3882
- app.delete('/bundles/:id', (req, res) => {
3927
+ app.delete('/bundles/:id', async (req, res) => {
3883
3928
  const result = getRequiredProject(req);
3884
3929
  if ('error' in result) {
3885
3930
  return res.status(400).json({ error: result.error });
@@ -3913,11 +3958,22 @@ app.delete('/bundles/:id', (req, res) => {
3913
3958
  .filter(specSession => specSession.target_bundle_id === bundle.id)
3914
3959
  .map(specSession => specSession.id);
3915
3960
  try {
3916
- deleteWorktree(bundle.branch, result.project);
3961
+ await cleanupWorktreeExecutionTarget({
3962
+ project: result.project,
3963
+ targetKind: 'bundle-worktree',
3964
+ targetKey: createExecutionTargetKey(result.project.id, {
3965
+ kind: 'bundle-worktree',
3966
+ bundleId: bundle.id,
3967
+ branch: bundle.branch,
3968
+ }),
3969
+ targetLabel: 'bundle worktree',
3970
+ worktreeTarget: 'bundle',
3971
+ branch: bundle.branch,
3972
+ });
3917
3973
  }
3918
3974
  catch (error) {
3919
- return res.status(500).json({
3920
- error: formatWorktreeDeleteError('bundle', bundle.branch, error),
3975
+ return res.status(error instanceof HttpError ? error.status : 500).json({
3976
+ error: error instanceof Error ? error.message : 'Unable to delete the bundle worktree',
3921
3977
  });
3922
3978
  }
3923
3979
  deleteBundle(bundle.id, result.project.id);
@@ -4202,12 +4258,16 @@ app.post('/bundles/:id/build-open-questions/resolve', async (req, res) => {
4202
4258
  progressionRunId: accepted.progressionRunId,
4203
4259
  broadcaster: io,
4204
4260
  });
4205
- for (const ticket of listDetailedBundleTickets(result.project.id, bundle.id)) {
4261
+ for (const ticket of listBoardBundleTickets(result.project.id, bundle.id)) {
4206
4262
  io.emit('ticket:updated', ticket);
4207
4263
  }
4208
- return res.json(serializeBundleDetails(result.project, bundle));
4264
+ return res.json({
4265
+ kind: accepted.kind,
4266
+ batch_id: accepted.batchId,
4267
+ target_ticket_id: null,
4268
+ });
4209
4269
  }
4210
- const ticketsBeforeReview = listDetailedBundleTickets(result.project.id, bundle.id);
4270
+ const ticketsBeforeReview = listBoardBundleTickets(result.project.id, bundle.id);
4211
4271
  if (!areBundleTicketsReadyForAutomaticReview(ticketsBeforeReview, bundle.id)) {
4212
4272
  completeAutomationProgression({
4213
4273
  projectId: result.project.id,
@@ -4218,7 +4278,11 @@ app.post('/bundles/:id/build-open-questions/resolve', async (req, res) => {
4218
4278
  for (const ticket of ticketsBeforeReview) {
4219
4279
  io.emit('ticket:updated', ticket);
4220
4280
  }
4221
- return res.json(serializeBundleDetails(result.project, bundle));
4281
+ return res.json({
4282
+ kind: accepted.kind,
4283
+ batch_id: accepted.batchId,
4284
+ target_ticket_id: null,
4285
+ });
4222
4286
  }
4223
4287
  let reviewStartFailureStatus = null;
4224
4288
  let reviewStartFailureError = null;
@@ -4249,24 +4313,27 @@ app.post('/bundles/:id/build-open-questions/resolve', async (req, res) => {
4249
4313
  });
4250
4314
  return res.status(reviewStartFailureStatus).json({ error: reviewStartFailureError });
4251
4315
  }
4252
- const updatedTickets = listDetailedBundleTickets(result.project.id, bundle.id);
4316
+ const updatedTickets = listBoardBundleTickets(result.project.id, bundle.id);
4253
4317
  for (const ticket of updatedTickets) {
4254
4318
  io.emit('ticket:updated', ticket);
4255
4319
  }
4256
4320
  const reviewOwner = reviewStarted
4257
4321
  ? updatedTickets.find(ticket => ticket.state === 'review' && ticket.parked_at === null)
4258
4322
  : null;
4259
- return res.json(serializeBundleDetails(result.project, bundle, {
4260
- review_owner_ticket_id: reviewOwner?.id,
4261
- target_ticket_id: reviewOwner?.id,
4262
- }));
4323
+ return res.json({
4324
+ kind: accepted.kind,
4325
+ batch_id: accepted.batchId,
4326
+ target_ticket_id: reviewOwner?.id ?? null,
4327
+ });
4263
4328
  }
4264
- for (const ticket of listDetailedBundleTickets(result.project.id, bundle.id)) {
4329
+ for (const ticket of listBoardBundleTickets(result.project.id, bundle.id)) {
4265
4330
  io.emit('ticket:updated', ticket);
4266
4331
  }
4267
- return res.status(accepted.status).json(serializeBundleDetails(result.project, bundle, {
4332
+ return res.status(accepted.status).json({
4333
+ kind: accepted.kind,
4334
+ batch_id: accepted.batchId,
4268
4335
  target_ticket_id: accepted.targetTicket.id,
4269
- }));
4336
+ });
4270
4337
  });
4271
4338
  app.post('/bundles/:id/undo-review', (req, res) => {
4272
4339
  const result = getRequiredProject(req);
@@ -6033,7 +6100,7 @@ app.post('/projects', (req, res) => {
6033
6100
  return res.status(400).json({ error: validation.error });
6034
6101
  }
6035
6102
  const projectCount = Number(db.prepare('SELECT COUNT(*) AS count FROM projects').get()?.count ?? 0);
6036
- const { name, repo_path, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, pre_review_check_definition_ids, post_build_check_definition_ids, auto_fix_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_variant, reviewer_model, reviewer_variant, commit_message_rules, commit_after_each_ticket, auto_park_stale_tickets, memory_enabled, scan_include_globs_json, scan_exclude_globs_json, worktree_sync, spec_aware_code_review_enabled, automation_depth, automation_review_fix_enabled, automation_pause_on_open_questions, automation_review_severity, automation_review_max_iterations, } = validation.values;
6103
+ const { name, repo_path, build_execution_provider, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, pre_review_check_definition_ids, post_build_check_definition_ids, auto_fix_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_variant, reviewer_model, reviewer_variant, commit_message_rules, commit_after_each_ticket, auto_park_stale_tickets, memory_enabled, scan_include_globs_json, scan_exclude_globs_json, worktree_sync, spec_aware_code_review_enabled, automation_depth, automation_review_fix_enabled, automation_pause_on_open_questions, automation_review_severity, automation_review_max_iterations, } = validation.values;
6037
6104
  if (!repo_path) {
6038
6105
  return res.status(400).json({ error: 'repo_path must be a non-empty string' });
6039
6106
  }
@@ -6051,6 +6118,7 @@ app.post('/projects', (req, res) => {
6051
6118
  id,
6052
6119
  name,
6053
6120
  repo_path,
6121
+ build_execution_provider,
6054
6122
  run_setup,
6055
6123
  run_services,
6056
6124
  check_definitions,
@@ -6081,8 +6149,8 @@ app.post('/projects', (req, res) => {
6081
6149
  automation_review_severity,
6082
6150
  automation_review_max_iterations
6083
6151
  )
6084
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6085
- `).run(id, name, normalizedRepoPath, run_setup, run_services, check_definitions, required_check_definition_ids ?? '[]', pre_review_check_definition_ids ?? '[]', post_build_check_definition_ids ?? '[]', auto_fix_check_definition_ids ?? '[]', test_commands, run_ide ?? null, preview_service_name ?? null, preview_path ?? null, preview_capability_mode ?? null, helper_model ?? null, helper_variant ?? null, reviewer_model ?? null, reviewer_model ? reviewer_variant ?? null : null, commit_message_rules ?? null, commit_after_each_ticket ?? 0, auto_park_stale_tickets ?? 0, memory_enabled ?? 0, scan_include_globs_json ?? null, scan_exclude_globs_json ?? null, worktree_sync ?? null, spec_aware_code_review_enabled ?? 0, automation_depth ?? 'manual', automation_review_fix_enabled ?? 0, automation_pause_on_open_questions ?? 0, automation_review_severity ?? 'medium', automation_review_max_iterations ?? 3);
6152
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6153
+ `).run(id, name, normalizedRepoPath, build_execution_provider ?? 'host', run_setup, run_services, check_definitions, required_check_definition_ids ?? '[]', pre_review_check_definition_ids ?? '[]', post_build_check_definition_ids ?? '[]', auto_fix_check_definition_ids ?? '[]', test_commands, run_ide ?? null, preview_service_name ?? null, preview_path ?? null, preview_capability_mode ?? null, helper_model ?? null, helper_variant ?? null, reviewer_model ?? null, reviewer_model ? reviewer_variant ?? null : null, commit_message_rules ?? null, commit_after_each_ticket ?? 0, auto_park_stale_tickets ?? 0, memory_enabled ?? 0, scan_include_globs_json ?? null, scan_exclude_globs_json ?? null, worktree_sync ?? null, spec_aware_code_review_enabled ?? 0, automation_depth ?? 'manual', automation_review_fix_enabled ?? 0, automation_pause_on_open_questions ?? 0, automation_review_severity ?? 'medium', automation_review_max_iterations ?? 3);
6086
6154
  replaceProjectLinks(id, linked_project_ids ?? []);
6087
6155
  ensureProjectRootBundle(id);
6088
6156
  if (projectCount === 0) {
@@ -7289,11 +7357,12 @@ app.patch('/projects/:id', (req, res) => {
7289
7357
  });
7290
7358
  }
7291
7359
  }
7292
- const { name, repo_path, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, pre_review_check_definition_ids, post_build_check_definition_ids, auto_fix_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_variant, reviewer_model, reviewer_variant, commit_message_rules, commit_after_each_ticket, auto_park_stale_tickets, memory_enabled, scan_include_globs_json, scan_exclude_globs_json, worktree_sync, spec_aware_code_review_enabled, automation_depth, automation_review_fix_enabled, automation_pause_on_open_questions, automation_review_severity, automation_review_max_iterations, } = validation.values;
7360
+ const { name, repo_path, build_execution_provider, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, pre_review_check_definition_ids, post_build_check_definition_ids, auto_fix_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_variant, reviewer_model, reviewer_variant, commit_message_rules, commit_after_each_ticket, auto_park_stale_tickets, memory_enabled, scan_include_globs_json, scan_exclude_globs_json, worktree_sync, spec_aware_code_review_enabled, automation_depth, automation_review_fix_enabled, automation_pause_on_open_questions, automation_review_severity, automation_review_max_iterations, } = validation.values;
7293
7361
  const updateProject = db.prepare(`
7294
7362
  UPDATE projects SET
7295
7363
  name = ?,
7296
7364
  repo_path = ?,
7365
+ build_execution_provider = ?,
7297
7366
  run_setup = ?,
7298
7367
  run_services = ?,
7299
7368
  check_definitions = ?,
@@ -7355,7 +7424,7 @@ app.patch('/projects/:id', (req, res) => {
7355
7424
  if ('error' in policyReferences) {
7356
7425
  return policyReferences;
7357
7426
  }
7358
- updateProject.run(name ?? project.name, repo_path ?? project.repo_path, hasOwn(validation.values, 'run_setup') ? run_setup : project.run_setup, hasOwn(validation.values, 'run_services') ? run_services : project.run_services, nextCheckDefinitions, nextRequiredCheckDefinitionIds, nextPreReviewCheckDefinitionIds, nextPostBuildCheckDefinitionIds, nextAutoFixCheckDefinitionIds, hasOwn(validation.values, 'test_commands') ? test_commands : project.test_commands, hasOwn(validation.values, 'run_ide') ? run_ide : project.run_ide, hasOwn(validation.values, 'preview_service_name') ? preview_service_name : project.preview_service_name, hasOwn(validation.values, 'preview_path') ? preview_path : project.preview_path, hasOwn(validation.values, 'preview_capability_mode') ? preview_capability_mode : project.preview_capability_mode, hasOwn(validation.values, 'helper_model') ? helper_model : project.helper_model, hasOwn(validation.values, 'helper_variant') ? helper_variant : project.helper_variant, nextReviewerModel, nextReviewerVariant, hasOwn(validation.values, 'commit_message_rules') ? commit_message_rules : project.commit_message_rules, hasOwn(validation.values, 'commit_after_each_ticket') ? commit_after_each_ticket : project.commit_after_each_ticket, hasOwn(validation.values, 'auto_park_stale_tickets') ? auto_park_stale_tickets : project.auto_park_stale_tickets, hasOwn(validation.values, 'memory_enabled') ? memory_enabled : project.memory_enabled, hasOwn(validation.values, 'scan_include_globs_json') ? scan_include_globs_json : project.scan_include_globs_json, hasOwn(validation.values, 'scan_exclude_globs_json') ? scan_exclude_globs_json : project.scan_exclude_globs_json, hasOwn(validation.values, 'worktree_sync') ? worktree_sync : project.worktree_sync, hasOwn(validation.values, 'spec_aware_code_review_enabled') ? spec_aware_code_review_enabled : project.spec_aware_code_review_enabled, hasOwn(validation.values, 'automation_depth') ? automation_depth : project.automation_depth, hasOwn(validation.values, 'automation_review_fix_enabled') ? automation_review_fix_enabled : project.automation_review_fix_enabled, hasOwn(validation.values, 'automation_pause_on_open_questions') ? automation_pause_on_open_questions : project.automation_pause_on_open_questions, hasOwn(validation.values, 'automation_review_severity') ? automation_review_severity : project.automation_review_severity, hasOwn(validation.values, 'automation_review_max_iterations') ? automation_review_max_iterations : project.automation_review_max_iterations, req.params.id);
7427
+ updateProject.run(name ?? project.name, repo_path ?? project.repo_path, hasOwn(validation.values, 'build_execution_provider') ? build_execution_provider : project.build_execution_provider, hasOwn(validation.values, 'run_setup') ? run_setup : project.run_setup, hasOwn(validation.values, 'run_services') ? run_services : project.run_services, nextCheckDefinitions, nextRequiredCheckDefinitionIds, nextPreReviewCheckDefinitionIds, nextPostBuildCheckDefinitionIds, nextAutoFixCheckDefinitionIds, hasOwn(validation.values, 'test_commands') ? test_commands : project.test_commands, hasOwn(validation.values, 'run_ide') ? run_ide : project.run_ide, hasOwn(validation.values, 'preview_service_name') ? preview_service_name : project.preview_service_name, hasOwn(validation.values, 'preview_path') ? preview_path : project.preview_path, hasOwn(validation.values, 'preview_capability_mode') ? preview_capability_mode : project.preview_capability_mode, hasOwn(validation.values, 'helper_model') ? helper_model : project.helper_model, hasOwn(validation.values, 'helper_variant') ? helper_variant : project.helper_variant, nextReviewerModel, nextReviewerVariant, hasOwn(validation.values, 'commit_message_rules') ? commit_message_rules : project.commit_message_rules, hasOwn(validation.values, 'commit_after_each_ticket') ? commit_after_each_ticket : project.commit_after_each_ticket, hasOwn(validation.values, 'auto_park_stale_tickets') ? auto_park_stale_tickets : project.auto_park_stale_tickets, hasOwn(validation.values, 'memory_enabled') ? memory_enabled : project.memory_enabled, hasOwn(validation.values, 'scan_include_globs_json') ? scan_include_globs_json : project.scan_include_globs_json, hasOwn(validation.values, 'scan_exclude_globs_json') ? scan_exclude_globs_json : project.scan_exclude_globs_json, hasOwn(validation.values, 'worktree_sync') ? worktree_sync : project.worktree_sync, hasOwn(validation.values, 'spec_aware_code_review_enabled') ? spec_aware_code_review_enabled : project.spec_aware_code_review_enabled, hasOwn(validation.values, 'automation_depth') ? automation_depth : project.automation_depth, hasOwn(validation.values, 'automation_review_fix_enabled') ? automation_review_fix_enabled : project.automation_review_fix_enabled, hasOwn(validation.values, 'automation_pause_on_open_questions') ? automation_pause_on_open_questions : project.automation_pause_on_open_questions, hasOwn(validation.values, 'automation_review_severity') ? automation_review_severity : project.automation_review_severity, hasOwn(validation.values, 'automation_review_max_iterations') ? automation_review_max_iterations : project.automation_review_max_iterations, req.params.id);
7359
7428
  if (hasOwn(validation.values, 'linked_project_ids')) {
7360
7429
  replaceProjectLinks(project.id, linked_project_ids ?? []);
7361
7430
  }
@@ -7404,15 +7473,23 @@ const assertProjectDeletionEligible = (projectId, claimId) => {
7404
7473
  }
7405
7474
  };
7406
7475
  const completeClaimedProjectDeletion = async (projectId, claimId) => {
7476
+ const marked = db.prepare(`
7477
+ UPDATE projects
7478
+ SET deletion_cleanup_started_at = COALESCE(deletion_cleanup_started_at, CURRENT_TIMESTAMP)
7479
+ WHERE id = ? AND deletion_claim_id = ?
7480
+ `).run(projectId, claimId);
7481
+ if (marked.changes !== 1) {
7482
+ throw new ProjectDeletionError(409, 'Project deletion ownership was lost');
7483
+ }
7484
+ await cleanupProjectExecutionEnvironments(projectId, claimId);
7407
7485
  await runExclusiveExecutionArtifactMaintenance(() => reconcileProjectExecutionArtifacts(projectId, {
7408
7486
  emitter: io,
7409
7487
  beginCleanup: () => {
7410
- const marked = db.prepare(`
7411
- UPDATE projects
7412
- SET deletion_cleanup_started_at = COALESCE(deletion_cleanup_started_at, CURRENT_TIMESTAMP)
7413
- WHERE id = ? AND deletion_claim_id = ?
7414
- `).run(projectId, claimId);
7415
- if (marked.changes !== 1) {
7488
+ const owned = db.prepare(`
7489
+ SELECT 1 FROM projects
7490
+ WHERE id = ? AND deletion_claim_id = ? AND deletion_cleanup_started_at IS NOT NULL
7491
+ `).get(projectId, claimId);
7492
+ if (!owned) {
7416
7493
  throw new ProjectDeletionError(409, 'Project deletion ownership was lost');
7417
7494
  }
7418
7495
  },
@@ -7457,6 +7534,7 @@ const completeClaimedProjectDeletion = async (projectId, claimId) => {
7457
7534
  SET parent_run_id = NULL, retry_of_run_id = NULL
7458
7535
  WHERE project_id = ?
7459
7536
  `).run(projectId);
7537
+ db.prepare("DELETE FROM execution_environments WHERE project_id = ? AND lifecycle_state = 'retired'").run(projectId);
7460
7538
  const deleted = db.prepare('DELETE FROM projects WHERE id = ? AND deletion_claim_id = ?').run(projectId, claimId);
7461
7539
  if (deleted.changes !== 1) {
7462
7540
  throw new ProjectDeletionError(409, 'Project deletion ownership was lost');
@@ -7508,6 +7586,9 @@ app.delete('/projects/:id', async (req, res) => {
7508
7586
  if (error instanceof ExecutionArtifactCleanupError) {
7509
7587
  return res.status(409).json({ error: error.message });
7510
7588
  }
7589
+ if (error instanceof ExecutionEnvironmentCleanupError) {
7590
+ return res.status(409).json({ error: error.message });
7591
+ }
7511
7592
  if (error instanceof ProjectDeletionError) {
7512
7593
  return res.status(error.status).json({ error: error.message });
7513
7594
  }
@@ -7574,7 +7655,7 @@ app.post('/tickets', (req, res) => {
7574
7655
  return res.status(500).json({ error: getErrorMessage(error) || 'Unable to create ticket' });
7575
7656
  }
7576
7657
  });
7577
- app.patch('/tickets/:id', (req, res) => {
7658
+ app.patch('/tickets/:id', async (req, res) => {
7578
7659
  const ticket = getTicket(req.params.id);
7579
7660
  if (!ticket) {
7580
7661
  return res.status(404).json({ error: 'Not found' });
@@ -7701,16 +7782,46 @@ app.patch('/tickets/:id', (req, res) => {
7701
7782
  return res.status(404).json({ error: 'Bundle not found' });
7702
7783
  }
7703
7784
  }
7785
+ const bundleChanged = previousBundleId !== resolvedBundleId || ticket.project_id !== nextProjectId;
7786
+ let previousBundleResourcesCleaned = false;
7787
+ if (bundleChanged && previousBundleId && previousProject) {
7788
+ const previousBundle = getBundle(previousBundleId, previousProject.id);
7789
+ if (previousBundle
7790
+ && !isProjectRootBundle(previousBundle)
7791
+ && countBundleTickets(previousBundle.id, previousProject.id) === 1) {
7792
+ try {
7793
+ await cleanupWorktreeExecutionTarget({
7794
+ project: previousProject,
7795
+ targetKind: 'bundle-worktree',
7796
+ targetKey: createExecutionTargetKey(previousProject.id, {
7797
+ kind: 'bundle-worktree',
7798
+ bundleId: previousBundle.id,
7799
+ branch: previousBundle.branch,
7800
+ }),
7801
+ targetLabel: 'bundle worktree',
7802
+ worktreeTarget: 'bundle',
7803
+ branch: previousBundle.branch,
7804
+ });
7805
+ previousBundleResourcesCleaned = true;
7806
+ }
7807
+ catch (error) {
7808
+ return res.status(error instanceof HttpError ? error.status : 500).json({
7809
+ error: error instanceof Error ? error.message : 'Unable to clean up the empty bundle',
7810
+ });
7811
+ }
7812
+ }
7813
+ }
7704
7814
  if (isProjectChanging) {
7705
7815
  deleteTicketDependenciesForTicket(ticket.id);
7706
7816
  }
7707
7817
  db.prepare('UPDATE tickets SET title = ?, description = ?, model = ?, variant = ?, skills_json = ?, worktree_bundle_id = ?, project_id = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run(title?.trim() ?? ticket.title, description ?? ticket.description, resolvedModel, resolvedVariant, JSON.stringify(resolvedSkills), resolvedBundleId, nextProjectId, req.params.id);
7708
7818
  upsertTicketDescriptionMessage(req.params.id, description ?? ticket.description);
7709
7819
  const updated = getTicket(req.params.id);
7710
- const bundleChanged = previousBundleId !== resolvedBundleId || ticket.project_id !== nextProjectId;
7711
7820
  if (bundleChanged && previousBundleId && previousProject) {
7712
7821
  try {
7713
- cleanupBundleIfEmpty(previousBundleId, previousProject);
7822
+ await cleanupBundleIfEmpty(previousBundleId, previousProject, {
7823
+ resourcesAlreadyCleaned: previousBundleResourcesCleaned,
7824
+ });
7714
7825
  }
7715
7826
  catch (error) {
7716
7827
  return res.status(error instanceof HttpError ? error.status : 500).json({
@@ -7942,6 +8053,10 @@ app.post('/tickets/:id/retry', (req, res) => {
7942
8053
  if (!acceptance.sequenceId) {
7943
8054
  throw new Error('Build sequence no longer exists');
7944
8055
  }
8056
+ const project = getEffectiveProject(acceptance.ticket);
8057
+ if (!project) {
8058
+ throw new Error('Build project no longer exists');
8059
+ }
7945
8060
  transaction.createExecutionRun({
7946
8061
  projectId: ticket.project_id,
7947
8062
  kind: 'build',
@@ -7951,6 +8066,9 @@ app.post('/tickets/:id/retry', (req, res) => {
7951
8066
  { entityType: 'bundle', entityId: ticket.worktree_bundle_id, relationship: 'context' },
7952
8067
  { entityType: 'build_sequence', entityId: acceptance.sequenceId, relationship: 'context' },
7953
8068
  ],
8069
+ metadata: {
8070
+ build_execution_provider: project.build_execution_provider ?? 'host',
8071
+ },
7954
8072
  initiatedBy: 'user',
7955
8073
  retryOfRunId: retrySource?.id ?? null,
7956
8074
  eventType: 'build_created',
@@ -9292,6 +9410,10 @@ export const runExecutionArtifactCleanup = (mode) => {
9292
9410
  if (mode === 'periodic') {
9293
9411
  await resumeInterruptedProjectDeletions();
9294
9412
  }
9413
+ const orphanedEnvironments = await reconcileOrphanedExecutionEnvironments();
9414
+ if (orphanedEnvironments.scanned > 0) {
9415
+ console.log(`Reconciled ${orphanedEnvironments.cleaned} orphaned execution environment(s); ${orphanedEnvironments.failed} cleanup(s) retained for retry`);
9416
+ }
9295
9417
  await runExclusiveExecutionArtifactMaintenance(async () => {
9296
9418
  const intents = await reconcileExecutionArtifactRegistrationIntents({ mode });
9297
9419
  const artifacts = await reconcileFinalizedExecutionArtifacts({ emitter: io });
@@ -9347,8 +9469,10 @@ export const startServer = ({ port = DEFAULT_PORT, host } = {}) => {
9347
9469
  }
9348
9470
  startServerPromise = (async () => {
9349
9471
  releaseInterruptedProjectDeletionClaims();
9350
- await resumeInterruptedProjectDeletions();
9472
+ await reconcileProductionExecutionEnvironmentBindings();
9473
+ await reconcileExecutionEnvironments();
9351
9474
  await reconcileStartupExecutions({ getGitHubConfig: getGitHubConnectionConfig });
9475
+ await resumeInterruptedProjectDeletions();
9352
9476
  const repositoryGraphSchemaExists = db.prepare(`
9353
9477
  SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'repository_graph_scans'
9354
9478
  `).get();