@straiffi/archon 1.8.15 → 1.8.17

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 (227) hide show
  1. package/dist/client/assets/ActivityView-XT8l-IRo.js +1 -0
  2. package/dist/client/assets/GitHubActionsDialog-C1nmgELc.js +1 -0
  3. package/dist/client/assets/VerificationDialog-Cg5XNaPd.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-Dx7MJofM.js → architectureDiagram-3BPJPVTR-YDD_HNbm.js} +1 -1
  7. package/dist/client/assets/{blockDiagram-GPEHLZMM-CSSJR8F_.js → blockDiagram-GPEHLZMM-BCgBIlJR.js} +1 -1
  8. package/dist/client/assets/{c4Diagram-AAUBKEIU-C4F9969r.js → c4Diagram-AAUBKEIU-BLfk5bKl.js} +1 -1
  9. package/dist/client/assets/channel-3_WpUZue.js +1 -0
  10. package/dist/client/assets/{chunk-2J33WTMH-23HW6i-y.js → chunk-2J33WTMH-DvwqUfn2.js} +1 -1
  11. package/dist/client/assets/{chunk-3OPIFGDE-C3ZmRDMb.js → chunk-3OPIFGDE-D9R3JLGz.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-B_-UQvCg.js → chunk-5ZQYHXKU-CZeWOab2.js} +1 -1
  17. package/dist/client/assets/{chunk-727SXJPM-5Dua6u1B.js → chunk-727SXJPM-YdTt6zCi.js} +1 -1
  18. package/dist/client/assets/{chunk-AQP2D5EJ-DcpcaFRO.js → chunk-AQP2D5EJ-BFHbP_eb.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-CLCpOw52.js → chunk-CSCIHK7Q-C0BPXL2C.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-uOZFe2JI.js → chunk-KSCS5N6A-DqC4tO6g.js} +1 -1
  25. package/dist/client/assets/{chunk-L5ZTLDWV-DNnzSNoX.js → chunk-L5ZTLDWV-BERUWsJ6.js} +1 -1
  26. package/dist/client/assets/{chunk-LZXEDZCA-CSA3Xnoh.js → chunk-LZXEDZCA-BUHwhuWm.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-BQR5rD7w.js → chunk-ND2GUHAM-DCfmNJ41.js} +1 -1
  31. package/dist/client/assets/{chunk-NZK2D7GU-DyIwcQYQ.js → chunk-NZK2D7GU-CHOkPepJ.js} +1 -1
  32. package/dist/client/assets/{chunk-O5CBEL6O-DfW60w5V.js → chunk-O5CBEL6O-ByMuL2EO.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-BGsB3vTj.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--L8rxPgF.js +1 -0
  40. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-uW5z5Qib.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-Ba7Pz-ZI.js → dagre-BM42HDAG-CtmlVYvf.js} +1 -1
  43. package/dist/client/assets/{dagre-DSrzm-Gq.js → dagre-BWNHuDdf.js} +1 -1
  44. package/dist/client/assets/{diagram-2AECGRRQ-BxYfgpZ6.js → diagram-2AECGRRQ-DmQ2-tFR.js} +1 -1
  45. package/dist/client/assets/{diagram-5GNKFQAL-Bc4-O-UJ.js → diagram-5GNKFQAL-l49VXoBJ.js} +1 -1
  46. package/dist/client/assets/{diagram-KO2AKTUF-Ds1Lmrzm.js → diagram-KO2AKTUF-0-U37RyJ.js} +1 -1
  47. package/dist/client/assets/{diagram-LMA3HP47-VFQabxKS.js → diagram-LMA3HP47-DupuMWgW.js} +1 -1
  48. package/dist/client/assets/{diagram-OG6HWLK6-Baff59Zc.js → diagram-OG6HWLK6-D5DoIHW2.js} +1 -1
  49. package/dist/client/assets/{erDiagram-TEJ5UH35-Da5zHjOK.js → erDiagram-TEJ5UH35-DO-3-WYF.js} +1 -1
  50. package/dist/client/assets/eventmodeling-FCH6USID-Dqb6QKoI.js +1 -0
  51. package/dist/client/assets/{flowDiagram-I6XJVG4X-pdGMAuog.js → flowDiagram-I6XJVG4X-CG1viGSO.js} +1 -1
  52. package/dist/client/assets/{ganttDiagram-6RSMTGT7-DjJGX0nm.js → ganttDiagram-6RSMTGT7-CV-6ALMZ.js} +1 -1
  53. package/dist/client/assets/gitGraph-WXDBUCRP-DYEsqh93.js +1 -0
  54. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-kErlwtcT.js → gitGraphDiagram-PVQCEYII-CHnyP-d3.js} +1 -1
  55. package/dist/client/assets/index-CsZfTdMO.css +2 -0
  56. package/dist/client/assets/index-DQ7z6ZWk.js +275 -0
  57. package/dist/client/assets/info-J43DQDTF-CfjXFZai.js +1 -0
  58. package/dist/client/assets/{infoDiagram-5YYISTIA-Bx78HhDi.js → infoDiagram-5YYISTIA-iKC-l4xs.js} +1 -1
  59. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-BP0YQCMl.js → ishikawaDiagram-YF4QCWOH-zi-y6jRI.js} +1 -1
  60. package/dist/client/assets/{journeyDiagram-JHISSGLW-DUgrCOuD.js → journeyDiagram-JHISSGLW-Da4wMeC4.js} +1 -1
  61. package/dist/client/assets/{kanban-definition-UN3LZRKU-K0Zc5_M8.js → kanban-definition-UN3LZRKU-CZQ1yL5y.js} +1 -1
  62. package/dist/client/assets/{line-Dtg-krjk.js → line-B-FS1zIN.js} +1 -1
  63. package/dist/client/assets/{linear-BOwW57yX.js → linear-DT4rSZvy.js} +1 -1
  64. package/dist/client/assets/{mermaid-parser.core-Dw5BI77W.js → mermaid-parser.core-DPXl3axs.js} +2 -2
  65. package/dist/client/assets/{mermaid.core-BE-qlWNj.js → mermaid.core-DjqrtE_A.js} +3 -3
  66. package/dist/client/assets/{mindmap-definition-RKZ34NQL-1Piz4H9I.js → mindmap-definition-RKZ34NQL-Day2-dLJ.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-zlWdJ7lL.js → pieDiagram-4H26LBE5-BmZiJzvi.js} +1 -1
  71. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-DRQY8Adp.js → quadrantDiagram-W4KKPZXB-DJgAcycV.js} +1 -1
  72. package/dist/client/assets/radar-GUYGQ44K-B7psLv22.js +1 -0
  73. package/dist/client/assets/{requirementDiagram-4Y6WPE33-B8_GJFxl.js → requirementDiagram-4Y6WPE33-y94ek5ya.js} +1 -1
  74. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BaI0Njo8.js → sankeyDiagram-5OEKKPKP-ChuulS6b.js} +1 -1
  75. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-DjqAXbRF.js → sequenceDiagram-3UESZ5HK-C7eiUu5p.js} +1 -1
  76. package/dist/client/assets/{stateDiagram-AJRCARHV-Ovr_3LeO.js → stateDiagram-AJRCARHV-Dy4QkKUV.js} +1 -1
  77. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-HdcReOP7.js +1 -0
  78. package/dist/client/assets/{timeline-definition-PNZ67QCA-DkczYKeZ.js → timeline-definition-PNZ67QCA-CTtZLJWJ.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-BZyo4ESi.js → vennDiagram-CIIHVFJN-C5matxMS.js} +1 -1
  82. package/dist/client/assets/wardley-L42UT6IY-B5-Vb08V.js +1 -0
  83. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BEISrECX.js → wardleyDiagram-YWT4CUSO-m_iOvfzY.js} +1 -1
  84. package/dist/client/assets/{xychartDiagram-2RQKCTM6-CyNzGK7f.js → xychartDiagram-2RQKCTM6-BmOxTt9K.js} +1 -1
  85. package/dist/client/index.html +2 -2
  86. package/dist/server/db.js +235 -0
  87. package/dist/server/db.js.map +1 -1
  88. package/dist/server/index.js +200 -45
  89. package/dist/server/index.js.map +1 -1
  90. package/dist/server/lib/agent.js +139 -90
  91. package/dist/server/lib/agent.js.map +1 -1
  92. package/dist/server/lib/agentProvider.js +1 -6
  93. package/dist/server/lib/agentProvider.js.map +1 -1
  94. package/dist/server/lib/buildExecutionEnvironment.js +535 -0
  95. package/dist/server/lib/buildExecutionEnvironment.js.map +1 -0
  96. package/dist/server/lib/buildOpenQuestionOperations.js +9 -3
  97. package/dist/server/lib/buildOpenQuestionOperations.js.map +1 -1
  98. package/dist/server/lib/checkAutoFix.js +1 -0
  99. package/dist/server/lib/checkAutoFix.js.map +1 -1
  100. package/dist/server/lib/checkRepairDispatch.js +3 -1
  101. package/dist/server/lib/checkRepairDispatch.js.map +1 -1
  102. package/dist/server/lib/dockerSandboxCredentials.js +62 -0
  103. package/dist/server/lib/dockerSandboxCredentials.js.map +1 -0
  104. package/dist/server/lib/dockerSandboxEnvironmentOperations.js +54 -0
  105. package/dist/server/lib/dockerSandboxEnvironmentOperations.js.map +1 -0
  106. package/dist/server/lib/dockerSandboxExecutionEnvironment.js +725 -0
  107. package/dist/server/lib/dockerSandboxExecutionEnvironment.js.map +1 -0
  108. package/dist/server/lib/dockerSandboxExecutionProvider.js +196 -0
  109. package/dist/server/lib/dockerSandboxExecutionProvider.js.map +1 -0
  110. package/dist/server/lib/dockerSandboxOpencodeSessionOperations.js +29 -0
  111. package/dist/server/lib/dockerSandboxOpencodeSessionOperations.js.map +1 -0
  112. package/dist/server/lib/dockerSandboxRuntimeController.js +187 -0
  113. package/dist/server/lib/dockerSandboxRuntimeController.js.map +1 -0
  114. package/dist/server/lib/executionEnvironment.js +22 -0
  115. package/dist/server/lib/executionEnvironment.js.map +1 -1
  116. package/dist/server/lib/executionEnvironmentContexts.js +144 -0
  117. package/dist/server/lib/executionEnvironmentContexts.js.map +1 -0
  118. package/dist/server/lib/executionEnvironmentLifecycle.js +63 -0
  119. package/dist/server/lib/executionEnvironmentLifecycle.js.map +1 -0
  120. package/dist/server/lib/executionEnvironmentReconciliation.js +782 -0
  121. package/dist/server/lib/executionEnvironmentReconciliation.js.map +1 -0
  122. package/dist/server/lib/executionEnvironmentRoutes.js +375 -0
  123. package/dist/server/lib/executionEnvironmentRoutes.js.map +1 -0
  124. package/dist/server/lib/executionEnvironmentValidation.js +540 -0
  125. package/dist/server/lib/executionEnvironmentValidation.js.map +1 -0
  126. package/dist/server/lib/executionEnvironmentValidationOperations.js +636 -0
  127. package/dist/server/lib/executionEnvironmentValidationOperations.js.map +1 -0
  128. package/dist/server/lib/executionEnvironments.js +726 -0
  129. package/dist/server/lib/executionEnvironments.js.map +1 -0
  130. package/dist/server/lib/executionReconciliation.js +77 -0
  131. package/dist/server/lib/executionReconciliation.js.map +1 -1
  132. package/dist/server/lib/executionRetry.js +3 -0
  133. package/dist/server/lib/executionRetry.js.map +1 -1
  134. package/dist/server/lib/executionRuns.js +1 -0
  135. package/dist/server/lib/executionRuns.js.map +1 -1
  136. package/dist/server/lib/executionTargets.js +107 -0
  137. package/dist/server/lib/executionTargets.js.map +1 -0
  138. package/dist/server/lib/executionTimeline.js +3 -0
  139. package/dist/server/lib/executionTimeline.js.map +1 -1
  140. package/dist/server/lib/hostExecutionEnvironment.js +47 -1
  141. package/dist/server/lib/hostExecutionEnvironment.js.map +1 -1
  142. package/dist/server/lib/mobileAccess.js +2 -2
  143. package/dist/server/lib/mobileAccess.js.map +1 -1
  144. package/dist/server/lib/models.js +11 -0
  145. package/dist/server/lib/models.js.map +1 -1
  146. package/dist/server/lib/opencodeErrors.js +31 -3
  147. package/dist/server/lib/opencodeErrors.js.map +1 -1
  148. package/dist/server/lib/opencodeSessionOperations.js +189 -9
  149. package/dist/server/lib/opencodeSessionOperations.js.map +1 -1
  150. package/dist/server/lib/opencodeTaskSessions.js +7 -12
  151. package/dist/server/lib/opencodeTaskSessions.js.map +1 -1
  152. package/dist/server/lib/postBuildChecks.js +2 -1
  153. package/dist/server/lib/postBuildChecks.js.map +1 -1
  154. package/dist/server/lib/projects.js +10 -0
  155. package/dist/server/lib/projects.js.map +1 -1
  156. package/dist/server/lib/specArtifact.js +1 -1
  157. package/dist/server/lib/specArtifact.js.map +1 -1
  158. package/dist/server/lib/specDraft.js +1 -5
  159. package/dist/server/lib/specDraft.js.map +1 -1
  160. package/dist/server/lib/specExport.js +1 -6
  161. package/dist/server/lib/specExport.js.map +1 -1
  162. package/dist/server/lib/specGraphFeature.js +3 -0
  163. package/dist/server/lib/specGraphFeature.js.map +1 -0
  164. package/dist/server/lib/specRepositoryEvidenceFormatting.js +2 -1
  165. package/dist/server/lib/specRepositoryEvidenceFormatting.js.map +1 -1
  166. package/dist/server/lib/specRepositoryImpact.js +4 -0
  167. package/dist/server/lib/specRepositoryImpact.js.map +1 -1
  168. package/dist/server/lib/specReviewContext.js +6 -20
  169. package/dist/server/lib/specReviewContext.js.map +1 -1
  170. package/dist/server/lib/specSnapshotEvidence.js +4 -0
  171. package/dist/server/lib/specSnapshotEvidence.js.map +1 -1
  172. package/dist/server/lib/specTicketMaterialization.js +4 -1
  173. package/dist/server/lib/specTicketMaterialization.js.map +1 -1
  174. package/dist/server/lib/ticketFollowUpOperations.js +8 -1
  175. package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
  176. package/dist/server/lib/ticketRunOperations.js +0 -3
  177. package/dist/server/lib/ticketRunOperations.js.map +1 -1
  178. package/dist/server/lib/types.js +1 -0
  179. package/dist/server/lib/types.js.map +1 -1
  180. package/dist/server/lib/workspaceIdentity.js +3 -0
  181. package/dist/server/lib/workspaceIdentity.js.map +1 -1
  182. package/dist/server/workers/build.js +115 -8
  183. package/dist/server/workers/build.js.map +1 -1
  184. package/dist/server/workers/followUp.js +119 -3
  185. package/dist/server/workers/followUp.js.map +1 -1
  186. package/dist/server/workers/plan.js +34 -22
  187. package/dist/server/workers/plan.js.map +1 -1
  188. package/dist/server/workers/review.js +14 -13
  189. package/dist/server/workers/review.js.map +1 -1
  190. package/dist/server/workers/specReview.js +0 -1
  191. package/dist/server/workers/specReview.js.map +1 -1
  192. package/dist/server/workers/specSession.js +46 -122
  193. package/dist/server/workers/specSession.js.map +1 -1
  194. package/package.json +1 -1
  195. package/dist/client/assets/ActivityView-DpY9GZez.js +0 -1
  196. package/dist/client/assets/GitHubActionsDialog-BCr-hjvp.js +0 -1
  197. package/dist/client/assets/RepositoryGraphDialog-_hm-x1Dx.js +0 -1
  198. package/dist/client/assets/VerificationDialog-CsjDzpE1.js +0 -4
  199. package/dist/client/assets/architecture-7EHR7CIX-Dm8H7N6Z.js +0 -1
  200. package/dist/client/assets/channel-DVkhJzgx.js +0 -1
  201. package/dist/client/assets/chunk-QZHKN3VN-CtbsU1Bj.js +0 -1
  202. package/dist/client/assets/chunk-WU5MYG2G-CzMMPYdi.js +0 -1
  203. package/dist/client/assets/classDiagram-4FO5ZUOK-6oZ93s5p.js +0 -1
  204. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DYO_YnkU.js +0 -1
  205. package/dist/client/assets/eventmodeling-FCH6USID-BWhw0UJ8.js +0 -1
  206. package/dist/client/assets/gitGraph-WXDBUCRP-BSnxAa1J.js +0 -1
  207. package/dist/client/assets/index-CS4TzG41.css +0 -2
  208. package/dist/client/assets/index-D5TEfELZ.js +0 -275
  209. package/dist/client/assets/info-J43DQDTF-DcFwF1-h.js +0 -1
  210. package/dist/client/assets/packet-YPE3B663-1VZiO_9r.js +0 -1
  211. package/dist/client/assets/pie-LRSECV5Y-BX1-tQCu.js +0 -1
  212. package/dist/client/assets/radar-GUYGQ44K-B2HRrCR4.js +0 -1
  213. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-9pmeAorV.js +0 -1
  214. package/dist/client/assets/treeView-BLDUP644-CDfUVbUi.js +0 -1
  215. package/dist/client/assets/treemap-LRROVOQU-DUWqu8sK.js +0 -1
  216. package/dist/client/assets/wardley-L42UT6IY-BEFuPUCy.js +0 -1
  217. /package/dist/client/assets/{array-B2f2amhX.js → array-BNor45A1.js} +0 -0
  218. /package/dist/client/assets/{chunk-NNHCCRGN-DgKrp8T-.js → chunk-NNHCCRGN-CZB-V-Gv.js} +0 -0
  219. /package/dist/client/assets/{cytoscape.esm-BInZCgaJ.js → cytoscape.esm-B2lJcMSI.js} +0 -0
  220. /package/dist/client/assets/{defaultLocale-sPXJ5urm.js → defaultLocale-DPzUsThw.js} +0 -0
  221. /package/dist/client/assets/{dist-DfHDMDTt.js → dist-CERhmQhR.js} +0 -0
  222. /package/dist/client/assets/{graphlib-DacNv4Jd.js → graphlib-BHOW-eWz.js} +0 -0
  223. /package/dist/client/assets/{init-BVCnG1lj.js → init-C0L3woqb.js} +0 -0
  224. /package/dist/client/assets/{katex-BlkrXOwm.js → katex-CpjQsUQe.js} +0 -0
  225. /package/dist/client/assets/{path-Bw5AvBNC.js → path-sMK4d_s9.js} +0 -0
  226. /package/dist/client/assets/{rough.esm-DeLgKbOI.js → rough.esm-BoTisKeL.js} +0 -0
  227. /package/dist/client/assets/{src-CFGsdLiG.js → src-BRjoYtUW.js} +0 -0
@@ -15,7 +15,7 @@ import { appendClaudeHeadlessPlanPrompt, buildClaudeHeadlessPlanArgs } from './p
15
15
  import { formatGenericToolCall } from './genericToolCall.js';
16
16
  import { getSpecSession, updateSpecSessionResumeId, updateSpecSessionStatus, updateSpecSessionTitle, updateSpecSessionUsageSnapshot } from './specs.js';
17
17
  import { updateSpecReviewRunStatus, updateSpecReviewRunStreaming, updateSpecReviewRunUsage } from './specReviews.js';
18
- import { createAgentRun, emitAgentRunsUpdated, finalizeAgentRun, getNextAgentRunIndex, listAgentRunsForExecutionRun, listAgentRunsForParent, updateAgentRunLabel, updateAgentRunSessionId, updateAgentRunStatus } from './agentRuns.js';
18
+ import { createAgentRun, emitAgentRunsUpdated, emitExecutionAgentRunsUpdated, finalizeAgentRun, getNextAgentRunIndex, listAgentRunsForExecutionRun, listAgentRunsForParent, updateAgentRunLabel, updateAgentRunSessionId, updateAgentRunStatus } from './agentRuns.js';
19
19
  import { markTicketDescriptionVisibleInBundle } from './ticketMessages.js';
20
20
  import { getTicket } from './tickets.js';
21
21
  import { createTranscriptRunSnapshots } from './transcriptRuns.js';
@@ -447,29 +447,29 @@ const createThrottledProgressUpdater = (flushUpdate) => {
447
447
  },
448
448
  };
449
449
  };
450
- export const readOpencodeUsageSnapshot = ({ sessionId, spawnTimestamp = null, }) => {
451
- const snapshot = hostOpencodeSessionOperations.readUsageSnapshot(sessionId, spawnTimestamp);
450
+ export const readOpencodeUsageSnapshot = async ({ sessionId, spawnTimestamp = null, sessionOperations = hostOpencodeSessionOperations, }) => {
451
+ const snapshot = await sessionOperations.readUsageSnapshot(sessionId, spawnTimestamp);
452
452
  if (!snapshot) {
453
453
  throw new Error('OpenCode usage snapshot read failed');
454
454
  }
455
455
  return snapshot;
456
456
  };
457
- const resolveOpencodeUsageSnapshot = ({ current, sessionId, spawnTimestamp = null, }) => {
457
+ const resolveOpencodeUsageSnapshot = async ({ current, sessionId, spawnTimestamp = null, }) => {
458
458
  try {
459
- return mergeChatUsageSnapshot(current, readOpencodeUsageSnapshot({ sessionId, spawnTimestamp }));
459
+ return mergeChatUsageSnapshot(current, await readOpencodeUsageSnapshot({ sessionId, spawnTimestamp }));
460
460
  }
461
461
  catch {
462
462
  return current;
463
463
  }
464
464
  };
465
- export const refreshChatSessionUsageSnapshot = (chatSessionId, options = {}) => {
465
+ export const refreshChatSessionUsageSnapshot = async (chatSessionId, options = {}) => {
466
466
  const chatSession = getChatSession(chatSessionId, { includeMessages: options.includeMessages });
467
467
  if (!chatSession || chatSession.tool !== 'opencode' || !chatSession.opencode_session_id) {
468
468
  return chatSession;
469
469
  }
470
470
  let nextUsageSnapshot;
471
471
  try {
472
- nextUsageSnapshot = readOpencodeUsageSnapshot({
472
+ nextUsageSnapshot = await readOpencodeUsageSnapshot({
473
473
  sessionId: chatSession.opencode_session_id,
474
474
  });
475
475
  }
@@ -482,14 +482,14 @@ export const refreshChatSessionUsageSnapshot = (chatSessionId, options = {}) =>
482
482
  updateChatSessionUsageSnapshot(chatSessionId, nextUsageSnapshot);
483
483
  return getChatSession(chatSessionId, { includeMessages: options.includeMessages });
484
484
  };
485
- export const refreshSpecSessionUsageSnapshot = (specSessionId, options = {}) => {
485
+ export const refreshSpecSessionUsageSnapshot = async (specSessionId, options = {}) => {
486
486
  const specSession = getSpecSession(specSessionId, { includeMessages: options.includeMessages });
487
487
  if (!specSession || specSession.tool !== 'opencode' || !specSession.opencode_session_id) {
488
488
  return specSession;
489
489
  }
490
490
  let nextUsageSnapshot;
491
491
  try {
492
- nextUsageSnapshot = readOpencodeUsageSnapshot({
492
+ nextUsageSnapshot = await readOpencodeUsageSnapshot({
493
493
  sessionId: specSession.opencode_session_id,
494
494
  });
495
495
  }
@@ -502,9 +502,9 @@ export const refreshSpecSessionUsageSnapshot = (specSessionId, options = {}) =>
502
502
  updateSpecSessionUsageSnapshot(specSessionId, nextUsageSnapshot);
503
503
  return getSpecSession(specSessionId, { includeMessages: options.includeMessages });
504
504
  };
505
- export const storeTicketUsageSnapshot = (ticketId, opencodeSessionId) => {
505
+ export const storeTicketUsageSnapshot = async (ticketId, opencodeSessionId, sessionOperations = hostOpencodeSessionOperations) => {
506
506
  try {
507
- const snapshot = readOpencodeUsageSnapshot({ sessionId: opencodeSessionId });
507
+ const snapshot = await readOpencodeUsageSnapshot({ sessionId: opencodeSessionId, sessionOperations });
508
508
  if (snapshot.usage_snapshot_total_tokens === null) {
509
509
  return;
510
510
  }
@@ -545,7 +545,7 @@ const createOpencodeMetadataRefresher = ({ chatSessionId, io, spawnTimestamp, in
545
545
  clearTimeout(lookupTimer);
546
546
  lookupTimer = null;
547
547
  };
548
- const readCurrentSession = () => {
548
+ const readCurrentSession = async () => {
549
549
  if (knownSessionId) {
550
550
  return hostOpencodeSessionOperations.findSessionById(knownSessionId);
551
551
  }
@@ -554,12 +554,12 @@ const createOpencodeMetadataRefresher = ({ chatSessionId, io, spawnTimestamp, in
554
554
  }
555
555
  return hostOpencodeSessionOperations.findLatestSessionAfter(spawnTimestamp);
556
556
  };
557
- const refresh = () => {
557
+ const refresh = async () => {
558
558
  if (stopped) {
559
559
  return { hasSession: false, hasResolvedTitle: false, sessionId: knownSessionId };
560
560
  }
561
561
  try {
562
- const session = readCurrentSession();
562
+ const session = await readCurrentSession();
563
563
  if (!session) {
564
564
  return { hasSession: false, hasResolvedTitle: false, sessionId: knownSessionId };
565
565
  }
@@ -585,10 +585,11 @@ const createOpencodeMetadataRefresher = ({ chatSessionId, io, spawnTimestamp, in
585
585
  }
586
586
  clearLookupTimer();
587
587
  lookupTimer = setTimeout(() => {
588
- const result = refresh();
589
- if (!result.hasResolvedTitle) {
590
- scheduleRetry();
591
- }
588
+ void refresh().then(result => {
589
+ if (!result.hasResolvedTitle) {
590
+ scheduleRetry();
591
+ }
592
+ });
592
593
  }, OPENCODE_SESSION_METADATA_LOOKUP_DELAY_MS);
593
594
  };
594
595
  return {
@@ -613,7 +614,7 @@ const createSpecOpencodeMetadataRefresher = ({ specSessionId, io, spawnTimestamp
613
614
  clearTimeout(lookupTimer);
614
615
  lookupTimer = null;
615
616
  };
616
- const readCurrentSession = () => {
617
+ const readCurrentSession = async () => {
617
618
  if (knownSessionId) {
618
619
  return hostOpencodeSessionOperations.findSessionById(knownSessionId);
619
620
  }
@@ -622,12 +623,12 @@ const createSpecOpencodeMetadataRefresher = ({ specSessionId, io, spawnTimestamp
622
623
  }
623
624
  return hostOpencodeSessionOperations.findLatestSessionAfter(spawnTimestamp);
624
625
  };
625
- const refresh = () => {
626
+ const refresh = async () => {
626
627
  if (stopped) {
627
628
  return { hasSession: false, hasResolvedTitle: false, sessionId: knownSessionId };
628
629
  }
629
630
  try {
630
- const session = readCurrentSession();
631
+ const session = await readCurrentSession();
631
632
  if (!session) {
632
633
  return { hasSession: false, hasResolvedTitle: false, sessionId: knownSessionId };
633
634
  }
@@ -653,10 +654,11 @@ const createSpecOpencodeMetadataRefresher = ({ specSessionId, io, spawnTimestamp
653
654
  }
654
655
  clearLookupTimer();
655
656
  lookupTimer = setTimeout(() => {
656
- const result = refresh();
657
- if (!result.hasResolvedTitle) {
658
- scheduleRetry();
659
- }
657
+ void refresh().then(result => {
658
+ if (!result.hasResolvedTitle) {
659
+ scheduleRetry();
660
+ }
661
+ });
660
662
  }, OPENCODE_SESSION_METADATA_LOOKUP_DELAY_MS);
661
663
  };
662
664
  return {
@@ -1194,6 +1196,10 @@ export const createSubagentRunTracker = ({ parentType, parentId, io, mainRun, ex
1194
1196
  const trackedRuns = [];
1195
1197
  let nextRunIndex = Math.max(executionContext ? getNextAgentRunIndex(executionContext.runId) : getNextAgentRunIndex(parentType, parentId), mainRun ? mainRun.runIndex + 1 : 1);
1196
1198
  const emitUpdate = () => {
1199
+ if (executionContext) {
1200
+ emitExecutionAgentRunsUpdated(io, parentType, parentId, executionContext.runId);
1201
+ return;
1202
+ }
1197
1203
  emitAgentRunsUpdated(io, parentType, parentId);
1198
1204
  };
1199
1205
  const updateMain = (log, response) => {
@@ -1473,13 +1479,13 @@ export const reconstructOpencodeSubagentTranscript = (parts, cwd) => {
1473
1479
  }
1474
1480
  return { log: log || null, response: response || null };
1475
1481
  };
1476
- export const readOpencodeSessionTranscript = ({ sessionId, since, cwd, }) => {
1482
+ export const readOpencodeSessionTranscript = async ({ sessionId, since, cwd, }) => {
1477
1483
  const reader = createOpencodeTaskSessionReader();
1478
1484
  if (!reader) {
1479
1485
  return null;
1480
1486
  }
1481
1487
  try {
1482
- return reconstructOpencodeSubagentTranscript(reader.listSessionParts(sessionId, since), cwd);
1488
+ return reconstructOpencodeSubagentTranscript(await reader.listSessionParts(sessionId, since), cwd);
1483
1489
  }
1484
1490
  catch {
1485
1491
  return null;
@@ -1526,24 +1532,27 @@ export const createOpencodeSubagentMonitor = ({ initialParentSessionId, spawnTim
1526
1532
  childSessionByCallId.set(stillUnmatchedInvocations[0].callId, stillUnmatchedChildren[0].id);
1527
1533
  }
1528
1534
  };
1529
- const refresh = () => {
1535
+ let refreshInFlight = null;
1536
+ const performRefresh = async () => {
1530
1537
  if (!reader) {
1531
1538
  return;
1532
1539
  }
1533
1540
  try {
1534
1541
  if (!parentSessionId && discoverParentSession && Date.now() >= spawnTimestamp + parentDiscoveryDelayMs) {
1535
- setParentSessionId(reader.findParentSessionSince(spawnTimestamp));
1542
+ setParentSessionId(await reader.findParentSessionSince(spawnTimestamp));
1536
1543
  }
1537
1544
  if (!parentSessionId) {
1538
1545
  return;
1539
1546
  }
1540
- const invocations = reader.listTaskInvocations(parentSessionId, spawnTimestamp);
1541
- const children = reader.listChildSessions(parentSessionId, spawnTimestamp);
1547
+ const [invocations, children] = await Promise.all([
1548
+ reader.listTaskInvocations(parentSessionId, spawnTimestamp),
1549
+ reader.listChildSessions(parentSessionId, spawnTimestamp),
1550
+ ]);
1542
1551
  resolveChildSessions(invocations, children);
1543
1552
  for (const invocation of invocations) {
1544
1553
  const childSessionId = childSessionByCallId.get(invocation.callId) ?? invocation.childSessionId;
1545
1554
  const transcript = childSessionId
1546
- ? reconstructOpencodeSubagentTranscript(reader.listSessionParts(childSessionId), cwd)
1555
+ ? reconstructOpencodeSubagentTranscript(await reader.listSessionParts(childSessionId), cwd)
1547
1556
  : { log: null, response: null };
1548
1557
  tracker.applySnapshot({
1549
1558
  callId: invocation.callId,
@@ -1559,12 +1568,20 @@ export const createOpencodeSubagentMonitor = ({ initialParentSessionId, spawnTim
1559
1568
  // OpenCode persistence is a progressive enhancement; stdout remains the fallback.
1560
1569
  }
1561
1570
  };
1571
+ const refresh = () => {
1572
+ if (!refreshInFlight) {
1573
+ refreshInFlight = performRefresh().finally(() => {
1574
+ refreshInFlight = null;
1575
+ });
1576
+ }
1577
+ return refreshInFlight;
1578
+ };
1562
1579
  const start = () => {
1563
1580
  if (!reader || timer) {
1564
1581
  return;
1565
1582
  }
1566
- refresh();
1567
- timer = setInterval(refresh, OPENCODE_SUBAGENT_POLL_INTERVAL_MS);
1583
+ void refresh();
1584
+ timer = setInterval(() => void refresh(), OPENCODE_SUBAGENT_POLL_INTERVAL_MS);
1568
1585
  timer.unref?.();
1569
1586
  };
1570
1587
  const stop = () => {
@@ -1621,7 +1638,9 @@ const interruptProcess = (state, signal) => {
1621
1638
  return;
1622
1639
  }
1623
1640
  if (state.interrupt) {
1624
- state.interrupt(signal);
1641
+ void Promise.resolve(state.interrupt(signal)).catch(() => {
1642
+ // Durable sandbox execution records typed interruption failures through its lifecycle owner.
1643
+ });
1625
1644
  return;
1626
1645
  }
1627
1646
  killProcess(state.child, signal);
@@ -1668,7 +1687,13 @@ export const registerChatProcessPlaceholder = (chatSessionId) => {
1668
1687
  return state;
1669
1688
  };
1670
1689
  export const registerBuildProcessPlaceholder = (ticketId) => {
1671
- const state = { child: null, interrupt: null, stopRequested: false, sessionLookupTimer: null };
1690
+ const state = {
1691
+ child: null,
1692
+ interrupt: null,
1693
+ abortController: new AbortController(),
1694
+ stopRequested: false,
1695
+ sessionLookupTimer: null,
1696
+ };
1672
1697
  activeBuildProcesses.set(ticketId, state);
1673
1698
  return state;
1674
1699
  };
@@ -1766,11 +1791,12 @@ export const stopBuildAgent = async (ticketId) => {
1766
1791
  return false;
1767
1792
  }
1768
1793
  state.stopRequested = true;
1794
+ state.abortController.abort(new Error('Build stop requested'));
1769
1795
  if (!state.child) {
1770
1796
  return true;
1771
1797
  }
1772
1798
  if (state.interrupt) {
1773
- state.interrupt('SIGTERM');
1799
+ await state.interrupt('SIGTERM');
1774
1800
  }
1775
1801
  else {
1776
1802
  killProcess(state.child, 'SIGTERM');
@@ -1778,7 +1804,7 @@ export const stopBuildAgent = async (ticketId) => {
1778
1804
  await waitForProcessExit(state.child, 5000);
1779
1805
  if (isProcessAlive(state.child)) {
1780
1806
  if (state.interrupt) {
1781
- state.interrupt('SIGKILL');
1807
+ await state.interrupt('SIGKILL');
1782
1808
  }
1783
1809
  else {
1784
1810
  killProcess(state.child, 'SIGKILL');
@@ -1866,8 +1892,9 @@ export const stopSpecReviewAgent = async (specReviewRunId) => {
1866
1892
  }
1867
1893
  return true;
1868
1894
  };
1869
- const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null, resumeSessionId = null, sessionField = 'session_id', trackBuildProcess = false, reviewProcessState, emitSuccessUpdate = true, opencodeAgentMode, runStream, executionContext, persistSessionIdToTicket = false, spawnPermitId, executionProvider = hostExecutionEnvironment, }) => {
1895
+ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null, resumeSessionId = null, sessionField = 'session_id', trackBuildProcess = false, reviewProcessState, emitSuccessUpdate = true, opencodeAgentMode, runStream, executionContext, persistSessionIdToTicket = false, spawnPermitId, executionProvider = hostExecutionEnvironment, executionTarget, }) => {
1870
1896
  const resolvedModel = resolveAgentModel(tool, model);
1897
+ const opencodeSessionOperations = executionProvider.sessionOperations?.opencode ?? null;
1871
1898
  const subagentTracker = createSubagentRunTracker({
1872
1899
  parentType: 'ticket',
1873
1900
  parentId: ticketId,
@@ -1884,10 +1911,18 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
1884
1911
  : {}),
1885
1912
  executionContext,
1886
1913
  });
1914
+ const emitRunUpdate = () => {
1915
+ const emitter = io;
1916
+ if (executionContext) {
1917
+ emitExecutionAgentRunsUpdated(emitter, 'ticket', ticketId, executionContext.runId);
1918
+ return;
1919
+ }
1920
+ emitAgentRunsUpdated(emitter, 'ticket', ticketId);
1921
+ };
1887
1922
  const writeRunStatus = (status, log, streamingResponse = null, options = {}) => {
1888
1923
  if (runStream) {
1889
1924
  updateAgentRunStatus(runStream.runId, status, log, streamingResponse);
1890
- emitAgentRunsUpdated(io, 'ticket', ticketId);
1925
+ emitRunUpdate();
1891
1926
  return;
1892
1927
  }
1893
1928
  updateStatus(ticketId, status, log, io, streamingResponse, options);
@@ -1895,7 +1930,7 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
1895
1930
  const writeRunSessionId = (sessionId) => {
1896
1931
  if (runStream) {
1897
1932
  updateAgentRunSessionId(runStream.runId, sessionId);
1898
- emitAgentRunsUpdated(io, 'ticket', ticketId);
1933
+ emitRunUpdate();
1899
1934
  if (persistSessionIdToTicket) {
1900
1935
  updateSessionId(ticketId, sessionId, sessionField, io);
1901
1936
  }
@@ -1906,7 +1941,7 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
1906
1941
  const finalizeRun = (status, log, responseText, options = {}) => {
1907
1942
  if (runStream) {
1908
1943
  finalizeAgentRun(runStream.runId, status, responseText);
1909
- emitAgentRunsUpdated(io, 'ticket', ticketId);
1944
+ emitRunUpdate();
1910
1945
  return subagentTracker.finalize(status, log, responseText);
1911
1946
  }
1912
1947
  updateStatus(ticketId, status, log, io, responseText, options);
@@ -1959,13 +1994,13 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
1959
1994
  writeRunSessionId(normalized);
1960
1995
  }
1961
1996
  };
1962
- const attemptOpencodeSessionLookup = () => {
1997
+ const attemptOpencodeSessionLookup = async () => {
1963
1998
  if (tool !== 'opencode' || hasResolvedOpencodeSessionId || spawnTimestamp === null) {
1964
1999
  return hasResolvedOpencodeSessionId;
1965
2000
  }
1966
2001
  try {
1967
- const session = hostOpencodeSessionOperations.findLatestSessionAfter(spawnTimestamp);
1968
- if (session?.id) {
2002
+ const session = await opencodeSessionOperations?.findLatestSessionAfter(spawnTimestamp, cwd);
2003
+ if (!hasResolvedOpencodeSessionId && session?.id) {
1969
2004
  bindResolvedOpencodeSession(session.id);
1970
2005
  }
1971
2006
  }
@@ -1997,6 +2032,7 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
1997
2032
  let child;
1998
2033
  let interrupt;
1999
2034
  let placementFailure;
2035
+ let placementCompletion = Promise.resolve(null);
2000
2036
  try {
2001
2037
  if (buildState?.stopRequested) {
2002
2038
  throw new AgentSpawnPermitRevokedError();
@@ -2005,12 +2041,7 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
2005
2041
  assertAgentSpawnPermit(spawnPermitId, executionContext.runId);
2006
2042
  }
2007
2043
  const handle = executionProvider.execute({
2008
- target: {
2009
- kind: 'worktree',
2010
- id: ticketId,
2011
- workspacePath: cwd,
2012
- revision: 'working-tree',
2013
- },
2044
+ target: executionTarget ?? null,
2014
2045
  command: invocation.command,
2015
2046
  args: invocation.args,
2016
2047
  cwd,
@@ -2021,6 +2052,9 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
2021
2052
  child = handle.child;
2022
2053
  interrupt = handle.interrupt;
2023
2054
  placementFailure = handle.placementFailure;
2055
+ if (handle.placementIdentity) {
2056
+ placementCompletion = placementFailure;
2057
+ }
2024
2058
  }
2025
2059
  catch (error) {
2026
2060
  const resolvedError = agentProvider.classifyExecutionFailure(error);
@@ -2053,11 +2087,15 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
2053
2087
  });
2054
2088
  startTime = Date.now();
2055
2089
  if (tool === 'opencode' && spawnTimestamp !== null) {
2090
+ const taskSessionReader = opencodeSessionOperations
2091
+ ? createOpencodeTaskSessionReader(opencodeSessionOperations)
2092
+ : null;
2056
2093
  opencodeSubagentMonitor = createOpencodeSubagentMonitor({
2057
2094
  initialParentSessionId: resumeSessionId,
2058
2095
  spawnTimestamp,
2059
2096
  cwd,
2060
2097
  tracker: subagentTracker,
2098
+ taskSessionReader,
2061
2099
  discoverParentSession: false,
2062
2100
  onParentSessionId: discoveredSessionId => {
2063
2101
  bindResolvedOpencodeSession(discoveredSessionId);
@@ -2099,8 +2137,12 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
2099
2137
  }
2100
2138
  });
2101
2139
  child.stderr?.on('data', (chunk) => stderrChunks.push(chunk));
2102
- child.on('close', code => {
2140
+ child.on('close', async (code) => {
2103
2141
  progressUpdater.cancel();
2142
+ const finalPlacementFailure = await placementCompletion;
2143
+ if (finalPlacementFailure || settled) {
2144
+ return;
2145
+ }
2104
2146
  if (remainder.trim()) {
2105
2147
  usageSnapshot = mergeUsageFromJsonLine(usageSnapshot, remainder);
2106
2148
  const parsed = parseClaudeStreamJsonLine(remainder, cwd);
@@ -2154,6 +2196,7 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
2154
2196
  const logLines = [];
2155
2197
  const responseLines = [];
2156
2198
  const recoveryTracker = createOpencodeRecoveryTracker();
2199
+ let usageSnapshot = EMPTY_CHAT_USAGE_SNAPSHOT;
2157
2200
  let remainder = '';
2158
2201
  const stderrChunks = [];
2159
2202
  const progressUpdater = createThrottledProgressUpdater(() => {
@@ -2164,6 +2207,7 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
2164
2207
  const lines = text.split('\n');
2165
2208
  remainder = lines.pop() ?? '';
2166
2209
  for (const line of lines) {
2210
+ usageSnapshot = mergeUsageFromJsonLine(usageSnapshot, line);
2167
2211
  if (firstFinalAnswerTime === null && startTime !== null) {
2168
2212
  const trimmedLine = line.trim();
2169
2213
  if (trimmedLine.startsWith('{')) {
@@ -2197,21 +2241,22 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
2197
2241
  child.stderr?.on('data', (chunk) => stderrChunks.push(chunk));
2198
2242
  if (tool === 'opencode' && !resumeSessionId) {
2199
2243
  sessionLookupTimer = setTimeout(() => {
2200
- attemptOpencodeSessionLookup();
2201
- sessionLookupTimer = null;
2244
+ void attemptOpencodeSessionLookup().finally(() => {
2245
+ sessionLookupTimer = null;
2246
+ });
2202
2247
  }, 1500);
2203
2248
  if (trackBuildProcess && buildState) {
2204
2249
  buildState.sessionLookupTimer = sessionLookupTimer;
2205
2250
  }
2206
2251
  }
2207
- child.on('close', code => {
2252
+ child.on('close', async (code) => {
2208
2253
  progressUpdater.cancel();
2209
- const resolvedSessionOnClose = attemptOpencodeSessionLookup();
2210
- if (sessionLookupTimer && (resolvedSessionOnClose || hasResolvedOpencodeSessionId)) {
2211
- clearTimeout(sessionLookupTimer);
2212
- sessionLookupTimer = null;
2254
+ const finalPlacementFailure = await placementCompletion;
2255
+ if (finalPlacementFailure || settled) {
2256
+ return;
2213
2257
  }
2214
2258
  if (remainder.trim()) {
2259
+ usageSnapshot = mergeUsageFromJsonLine(usageSnapshot, remainder);
2215
2260
  const parsed = parseOpencodeJsonLine(remainder);
2216
2261
  const { subagentEvents, providerSessionId } = parsed;
2217
2262
  if (isExecutionCapableParsedStreamLine(parsed)) {
@@ -2223,8 +2268,13 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
2223
2268
  firstFinalAnswerTime = null;
2224
2269
  }
2225
2270
  }
2271
+ const resolvedSessionOnClose = await attemptOpencodeSessionLookup();
2272
+ if (sessionLookupTimer && (resolvedSessionOnClose || hasResolvedOpencodeSessionId)) {
2273
+ clearTimeout(sessionLookupTimer);
2274
+ sessionLookupTimer = null;
2275
+ }
2226
2276
  const stderrOutput = Buffer.concat(stderrChunks).toString();
2227
- opencodeSubagentMonitor?.refresh();
2277
+ await opencodeSubagentMonitor?.refresh();
2228
2278
  const log = logLines.join('\n\n') || stderrOutput;
2229
2279
  const recoveredResponse = recoveryTracker.getRecoveredResponse();
2230
2280
  const finalResponse = recoveryTracker.hasRecoveredFinalAnswer()
@@ -2234,12 +2284,12 @@ const runAgentOnce = ({ ticketId, tool, prompt, cwd, io, model, variant = null,
2234
2284
  const timing = buildResponseTiming({ startTime, firstFinalAnswerTime, isStopped: Boolean(buildState?.stopRequested || reviewProcessState?.stopRequested) });
2235
2285
  if (buildState?.stopRequested || reviewProcessState?.stopRequested) {
2236
2286
  const transcriptRuns = finalizeRun('stopped', log, finalResponse);
2237
- resolveOnce(withTranscriptRuns({ response: finalResponse, responseTiming: timing }, transcriptRuns));
2287
+ resolveOnce(withTranscriptRuns({ response: finalResponse, responseTiming: timing, usageSnapshot }, transcriptRuns));
2238
2288
  return;
2239
2289
  }
2240
2290
  if (isSuccessfulOpencodeExit(code, stderrModelError, recoveryTracker)) {
2241
2291
  const transcriptRuns = finalizeRun('done', log, finalResponse, { emit: emitSuccessUpdate });
2242
- resolveOnce(withTranscriptRuns({ response: finalResponse, responseTiming: timing }, transcriptRuns));
2292
+ resolveOnce(withTranscriptRuns({ response: finalResponse, responseTiming: timing, usageSnapshot }, transcriptRuns));
2243
2293
  return;
2244
2294
  }
2245
2295
  const failureMessage = `Agent exited with code ${code ?? 'null'}\n${log}${stderrOutput !== log && stderrOutput ? '\n\n' + stderrOutput : ''}`;
@@ -2345,10 +2395,12 @@ const runChatAgentOnce = ({ chatSessionId, tool, prompt, files = [], cwd, io, mo
2345
2395
  });
2346
2396
  chatState.metadataRefresher = opencodeMetadataRefresher;
2347
2397
  if (resumeSessionId) {
2348
- const result = opencodeMetadataRefresher.refresh();
2349
- if (!result.hasResolvedTitle) {
2350
- opencodeMetadataRefresher.scheduleRetry();
2351
- }
2398
+ const metadataRefresher = opencodeMetadataRefresher;
2399
+ void metadataRefresher.refresh().then(result => {
2400
+ if (!result.hasResolvedTitle) {
2401
+ metadataRefresher.scheduleRetry();
2402
+ }
2403
+ });
2352
2404
  }
2353
2405
  }
2354
2406
  let child;
@@ -2568,7 +2620,7 @@ const runChatAgentOnce = ({ chatSessionId, tool, prompt, files = [], cwd, io, mo
2568
2620
  if (!resumeSessionId) {
2569
2621
  opencodeMetadataRefresher?.scheduleRetry();
2570
2622
  }
2571
- child.on('close', code => {
2623
+ child.on('close', async (code) => {
2572
2624
  progressUpdater.cancel();
2573
2625
  if (remainder.trim()) {
2574
2626
  usageSnapshot = mergeUsageFromJsonLine(usageSnapshot, remainder);
@@ -2596,15 +2648,15 @@ const runChatAgentOnce = ({ chatSessionId, tool, prompt, files = [], cwd, io, mo
2596
2648
  response: finalResponse,
2597
2649
  })
2598
2650
  : null;
2599
- const metadataResult = opencodeMetadataRefresher?.refresh();
2651
+ const metadataResult = await opencodeMetadataRefresher?.refresh();
2600
2652
  const resolvedOpencodeSessionId = metadataResult?.sessionId
2601
2653
  ?? preservedOutput?.opencodeSessionId
2602
2654
  ?? getChatSession(chatSessionId)?.opencode_session_id
2603
2655
  ?? resumeSessionId;
2604
- opencodeSubagentMonitor?.refresh();
2656
+ await opencodeSubagentMonitor?.refresh();
2605
2657
  if (chatState.stopRequested) {
2606
2658
  if (resolvedOpencodeSessionId) {
2607
- usageSnapshot = resolveOpencodeUsageSnapshot({
2659
+ usageSnapshot = await resolveOpencodeUsageSnapshot({
2608
2660
  current: usageSnapshot,
2609
2661
  sessionId: resolvedOpencodeSessionId,
2610
2662
  spawnTimestamp,
@@ -2628,7 +2680,7 @@ const runChatAgentOnce = ({ chatSessionId, tool, prompt, files = [], cwd, io, mo
2628
2680
  response: finalResponse,
2629
2681
  });
2630
2682
  if (resolvedOpencodeSessionId && spawnTimestamp !== null) {
2631
- usageSnapshot = resolveOpencodeUsageSnapshot({
2683
+ usageSnapshot = await resolveOpencodeUsageSnapshot({
2632
2684
  current: usageSnapshot,
2633
2685
  sessionId: resolvedOpencodeSessionId,
2634
2686
  spawnTimestamp,
@@ -2756,10 +2808,12 @@ const runSpecAgentOnce = ({ specSessionId, tool, prompt, files = [], cwd, io, mo
2756
2808
  });
2757
2809
  specState.metadataRefresher = opencodeMetadataRefresher;
2758
2810
  if (resumeSessionId) {
2759
- const result = opencodeMetadataRefresher.refresh();
2760
- if (!result.hasResolvedTitle) {
2761
- opencodeMetadataRefresher.scheduleRetry();
2762
- }
2811
+ const metadataRefresher = opencodeMetadataRefresher;
2812
+ void metadataRefresher.refresh().then(result => {
2813
+ if (!result.hasResolvedTitle) {
2814
+ metadataRefresher.scheduleRetry();
2815
+ }
2816
+ });
2763
2817
  }
2764
2818
  }
2765
2819
  let child;
@@ -2955,9 +3009,9 @@ const runSpecAgentOnce = ({ specSessionId, tool, prompt, files = [], cwd, io, mo
2955
3009
  if (!resumeSessionId) {
2956
3010
  opencodeMetadataRefresher?.scheduleRetry();
2957
3011
  }
2958
- child.on('close', code => {
3012
+ child.on('close', async (code) => {
2959
3013
  progressUpdater.cancel();
2960
- opencodeSubagentMonitor?.refresh();
3014
+ await opencodeSubagentMonitor?.refresh();
2961
3015
  if (remainder.trim()) {
2962
3016
  usageSnapshot = mergeUsageFromJsonLine(usageSnapshot, remainder);
2963
3017
  const parsed = parseOpencodeJsonLine(remainder, cwd);
@@ -2981,15 +3035,15 @@ const runSpecAgentOnce = ({ specSessionId, tool, prompt, files = [], cwd, io, mo
2981
3035
  response: finalResponse,
2982
3036
  })
2983
3037
  : null;
2984
- const metadataResult = opencodeMetadataRefresher?.refresh();
3038
+ const metadataResult = await opencodeMetadataRefresher?.refresh();
2985
3039
  const resolvedOpencodeSessionId = metadataResult?.sessionId
2986
3040
  ?? preservedOutput?.opencodeSessionId
2987
3041
  ?? getSpecSession(specSessionId)?.opencode_session_id
2988
3042
  ?? resumeSessionId;
2989
- opencodeSubagentMonitor?.refresh();
3043
+ await opencodeSubagentMonitor?.refresh();
2990
3044
  if (specState.stopRequested) {
2991
3045
  if (resolvedOpencodeSessionId) {
2992
- usageSnapshot = resolveOpencodeUsageSnapshot({
3046
+ usageSnapshot = await resolveOpencodeUsageSnapshot({
2993
3047
  current: usageSnapshot,
2994
3048
  sessionId: resolvedOpencodeSessionId,
2995
3049
  spawnTimestamp,
@@ -3013,7 +3067,7 @@ const runSpecAgentOnce = ({ specSessionId, tool, prompt, files = [], cwd, io, mo
3013
3067
  response: finalResponse,
3014
3068
  });
3015
3069
  if (resolvedOpencodeSessionId && spawnTimestamp !== null) {
3016
- usageSnapshot = resolveOpencodeUsageSnapshot({
3070
+ usageSnapshot = await resolveOpencodeUsageSnapshot({
3017
3071
  current: usageSnapshot,
3018
3072
  sessionId: resolvedOpencodeSessionId,
3019
3073
  spawnTimestamp,
@@ -3136,12 +3190,7 @@ const runSpecReviewAgentOnce = ({ specReviewRunId, specSessionId, tool, prompt,
3136
3190
  const invocation = buildOpencodeSpecReviewInvocation({ prompt, files, model: resolvedModel, variant });
3137
3191
  try {
3138
3192
  const handle = hostExecutionEnvironment.execute({
3139
- target: {
3140
- kind: 'repository',
3141
- id: cwd,
3142
- workspacePath: cwd,
3143
- revision: 'working-tree',
3144
- },
3193
+ target: null,
3145
3194
  command: invocation.command,
3146
3195
  args: invocation.args,
3147
3196
  cwd,
@@ -3310,9 +3359,9 @@ const runSpecReviewAgentOnce = ({ specReviewRunId, specSessionId, tool, prompt,
3310
3359
  }
3311
3360
  });
3312
3361
  child.stderr?.on('data', (chunk) => stderrChunks.push(chunk));
3313
- child.on('close', code => {
3362
+ child.on('close', async (code) => {
3314
3363
  progressUpdater.cancel();
3315
- opencodeSubagentMonitor?.refresh();
3364
+ await opencodeSubagentMonitor?.refresh();
3316
3365
  if (remainder.trim()) {
3317
3366
  usageSnapshot = mergeUsageFromJsonLine(usageSnapshot, remainder);
3318
3367
  const parsed = parseOpencodeJsonLine(remainder, cwd);
@@ -3330,7 +3379,7 @@ const runSpecReviewAgentOnce = ({ specReviewRunId, specSessionId, tool, prompt,
3330
3379
  ? recoveredResponse
3331
3380
  : responseLines.join('\n\n') || stderrOutput;
3332
3381
  if (opencodeSessionId && spawnTimestamp !== null) {
3333
- usageSnapshot = resolveOpencodeUsageSnapshot({
3382
+ usageSnapshot = await resolveOpencodeUsageSnapshot({
3334
3383
  current: usageSnapshot,
3335
3384
  sessionId: opencodeSessionId,
3336
3385
  spawnTimestamp,