@straiffi/archon 1.10.10 → 1.11.0

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 (215) hide show
  1. package/README.md +9 -2
  2. package/dist/client/assets/{ActivityView-CRkM5TeN.js → ActivityView-BvXSn9Jw.js} +1 -1
  3. package/dist/client/assets/GitHubActionsDialog-BPZg_Wy3.js +1 -0
  4. package/dist/client/assets/VerificationDialog-D3mOY3z9.js +4 -0
  5. package/dist/client/assets/{architectureDiagram-3BPJPVTR-u0PSZlNP.js → architectureDiagram-3BPJPVTR-Bj7m5nzx.js} +1 -1
  6. package/dist/client/assets/{blockDiagram-GPEHLZMM-DFXLHRIk.js → blockDiagram-GPEHLZMM-Dv4SrhZg.js} +1 -1
  7. package/dist/client/assets/{c4Diagram-AAUBKEIU-Dvic8tCt.js → c4Diagram-AAUBKEIU-BKGsMo_n.js} +1 -1
  8. package/dist/client/assets/channel-DmiHuOD2.js +1 -0
  9. package/dist/client/assets/{chunk-2J33WTMH-t5CxhRXJ.js → chunk-2J33WTMH-oppoEflV.js} +1 -1
  10. package/dist/client/assets/{chunk-3OPIFGDE-YHT1dP8Q.js → chunk-3OPIFGDE-FoeHxEDL.js} +1 -1
  11. package/dist/client/assets/{chunk-5ZQYHXKU-DcxuI7lb.js → chunk-5ZQYHXKU-DFo7Hn8f.js} +1 -1
  12. package/dist/client/assets/{chunk-727SXJPM-D1F6DmrT.js → chunk-727SXJPM-BbM0ijwZ.js} +1 -1
  13. package/dist/client/assets/{chunk-AQP2D5EJ-BIx6Ohbk.js → chunk-AQP2D5EJ-hGswj21x.js} +1 -1
  14. package/dist/client/assets/{chunk-CSCIHK7Q-B355h6HA.js → chunk-CSCIHK7Q-k3Y3HBPl.js} +1 -1
  15. package/dist/client/assets/{chunk-KSCS5N6A-CLHGYOLQ.js → chunk-KSCS5N6A-D-fMWFHX.js} +1 -1
  16. package/dist/client/assets/{chunk-L5ZTLDWV-DFLYcMx8.js → chunk-L5ZTLDWV-Cp8034Xo.js} +1 -1
  17. package/dist/client/assets/{chunk-LZXEDZCA-DtljFujX.js → chunk-LZXEDZCA-DCmWwuZY.js} +2 -2
  18. package/dist/client/assets/{chunk-ND2GUHAM-CIuUQ86K.js → chunk-ND2GUHAM-CPxoYLrb.js} +1 -1
  19. package/dist/client/assets/{chunk-NZK2D7GU-CIwqlxek.js → chunk-NZK2D7GU-B1xsQ-Ge.js} +1 -1
  20. package/dist/client/assets/{chunk-O5CBEL6O-W42BEPu4.js → chunk-O5CBEL6O-CP_QLulv.js} +1 -1
  21. package/dist/client/assets/{chunk-WU5MYG2G-C_zuaNxV.js → chunk-WU5MYG2G-CqDmmASz.js} +1 -1
  22. package/dist/client/assets/classDiagram-4FO5ZUOK-GuChK9KD.js +1 -0
  23. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-ezsQe4jc.js +1 -0
  24. package/dist/client/assets/{dagre-BM42HDAG-UKfIUJTP.js → dagre-BM42HDAG-I60HgRr5.js} +1 -1
  25. package/dist/client/assets/{diagram-2AECGRRQ-Xn6yojqq.js → diagram-2AECGRRQ-DH7489lu.js} +1 -1
  26. package/dist/client/assets/{diagram-5GNKFQAL-BzpY1ZEl.js → diagram-5GNKFQAL-UG5kJveS.js} +1 -1
  27. package/dist/client/assets/{diagram-KO2AKTUF-Dyrvzvsg.js → diagram-KO2AKTUF-DLPd9cl-.js} +1 -1
  28. package/dist/client/assets/{diagram-LMA3HP47-AqImKwAr.js → diagram-LMA3HP47-gfoMHIE-.js} +1 -1
  29. package/dist/client/assets/{diagram-OG6HWLK6-CaQQ46mi.js → diagram-OG6HWLK6-D7zejHzo.js} +1 -1
  30. package/dist/client/assets/{erDiagram-TEJ5UH35-Dkw4Aa5u.js → erDiagram-TEJ5UH35-DB1R9rUd.js} +1 -1
  31. package/dist/client/assets/{flowDiagram-I6XJVG4X-CJTuGX9h.js → flowDiagram-I6XJVG4X-rSasRun9.js} +1 -1
  32. package/dist/client/assets/{ganttDiagram-6RSMTGT7-CidgOdS-.js → ganttDiagram-6RSMTGT7-ickt48MT.js} +1 -1
  33. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-Bj02mIQj.js → gitGraphDiagram-PVQCEYII-B2MWuej-.js} +1 -1
  34. package/dist/client/assets/index-4RQBXPuO.css +2 -0
  35. package/dist/client/assets/index-BN2UMUYo.js +276 -0
  36. package/dist/client/assets/{infoDiagram-5YYISTIA-GwJWfo_r.js → infoDiagram-5YYISTIA-ClB9-yBC.js} +1 -1
  37. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-rbrlWbUn.js → ishikawaDiagram-YF4QCWOH-CyUX0IyE.js} +1 -1
  38. package/dist/client/assets/{journeyDiagram-JHISSGLW-BLi_uzQM.js → journeyDiagram-JHISSGLW-CvZv1SZ7.js} +1 -1
  39. package/dist/client/assets/{kanban-definition-UN3LZRKU-ynlywm-_.js → kanban-definition-UN3LZRKU-C3MgzQMY.js} +1 -1
  40. package/dist/client/assets/{line-BNyTZBB4.js → line-Dpj7mkeR.js} +1 -1
  41. package/dist/client/assets/{mermaid-parser.core-CzUOsZAD.js → mermaid-parser.core-Ezn4UHHp.js} +1 -1
  42. package/dist/client/assets/{mermaid.core-K0QR6SzN.js → mermaid.core-GVI7XZqR.js} +3 -3
  43. package/dist/client/assets/{mindmap-definition-RKZ34NQL-BKcgqXm0.js → mindmap-definition-RKZ34NQL-Bu2cgOo4.js} +1 -1
  44. package/dist/client/assets/{pieDiagram-4H26LBE5-Bjx0lvDI.js → pieDiagram-4H26LBE5-_WS41t2_.js} +1 -1
  45. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CmUlgyUv.js → quadrantDiagram-W4KKPZXB-Urvq-XqI.js} +1 -1
  46. package/dist/client/assets/{requirementDiagram-4Y6WPE33-Dj2mzg1y.js → requirementDiagram-4Y6WPE33-bkmWG0rM.js} +1 -1
  47. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-DC--H6qf.js → sankeyDiagram-5OEKKPKP-DI0SArVz.js} +1 -1
  48. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BkNrt6Ra.js → sequenceDiagram-3UESZ5HK-n7PKrHd3.js} +1 -1
  49. package/dist/client/assets/{stateDiagram-AJRCARHV-BuxxRu1Y.js → stateDiagram-AJRCARHV-CxnEzrQA.js} +1 -1
  50. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DXTMu4iJ.js +1 -0
  51. package/dist/client/assets/{timeline-definition-PNZ67QCA-Db3pCVSp.js → timeline-definition-PNZ67QCA-BFr88_A9.js} +1 -1
  52. package/dist/client/assets/{vennDiagram-CIIHVFJN-BgBSGThQ.js → vennDiagram-CIIHVFJN-BNYs6tfr.js} +1 -1
  53. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BJhPdjYS.js → wardleyDiagram-YWT4CUSO-CaGZd3fe.js} +1 -1
  54. package/dist/client/assets/{xychartDiagram-2RQKCTM6-BY4Ra0kX.js → xychartDiagram-2RQKCTM6-CMyDrx2a.js} +1 -1
  55. package/dist/client/index.html +2 -2
  56. package/dist/server/db.js +181 -28
  57. package/dist/server/db.js.map +1 -1
  58. package/dist/server/index.js +118 -40
  59. package/dist/server/index.js.map +1 -1
  60. package/dist/server/lib/activeTool.js +23 -0
  61. package/dist/server/lib/activeTool.js.map +1 -0
  62. package/dist/server/lib/agent.js +291 -67
  63. package/dist/server/lib/agent.js.map +1 -1
  64. package/dist/server/lib/agentCatalog.js +92 -4
  65. package/dist/server/lib/agentCatalog.js.map +1 -1
  66. package/dist/server/lib/agentProvider.js +8 -11
  67. package/dist/server/lib/agentProvider.js.map +1 -1
  68. package/dist/server/lib/agentRuns.js +26 -2
  69. package/dist/server/lib/agentRuns.js.map +1 -1
  70. package/dist/server/lib/automationCheckGate.js +6 -0
  71. package/dist/server/lib/automationCheckGate.js.map +1 -1
  72. package/dist/server/lib/buildExecutionEnvironment.js +82 -29
  73. package/dist/server/lib/buildExecutionEnvironment.js.map +1 -1
  74. package/dist/server/lib/buildFlow.js +5 -4
  75. package/dist/server/lib/buildFlow.js.map +1 -1
  76. package/dist/server/lib/buildSequences.js +7 -29
  77. package/dist/server/lib/buildSequences.js.map +1 -1
  78. package/dist/server/lib/buildTicketCommit.js +82 -11
  79. package/dist/server/lib/buildTicketCommit.js.map +1 -1
  80. package/dist/server/lib/bundleReviewOperations.js +6 -0
  81. package/dist/server/lib/bundleReviewOperations.js.map +1 -1
  82. package/dist/server/lib/chatOperations.js +109 -93
  83. package/dist/server/lib/chatOperations.js.map +1 -1
  84. package/dist/server/lib/chatSessionTitle.js +66 -0
  85. package/dist/server/lib/chatSessionTitle.js.map +1 -0
  86. package/dist/server/lib/chats.js +20 -4
  87. package/dist/server/lib/chats.js.map +1 -1
  88. package/dist/server/lib/checkAutoFix.js +65 -61
  89. package/dist/server/lib/checkAutoFix.js.map +1 -1
  90. package/dist/server/lib/codexAgentProvider.js +320 -0
  91. package/dist/server/lib/codexAgentProvider.js.map +1 -0
  92. package/dist/server/lib/codexAppServer.js +678 -0
  93. package/dist/server/lib/codexAppServer.js.map +1 -0
  94. package/dist/server/lib/codexCatalogDiscoveryExecutionEnvironment.js +302 -0
  95. package/dist/server/lib/codexCatalogDiscoveryExecutionEnvironment.js.map +1 -0
  96. package/dist/server/lib/codexDiscovery.js +137 -0
  97. package/dist/server/lib/codexDiscovery.js.map +1 -0
  98. package/dist/server/lib/config.js.map +1 -1
  99. package/dist/server/lib/dockerSandboxEnvironmentOperations.js +2 -2
  100. package/dist/server/lib/dockerSandboxEnvironmentOperations.js.map +1 -1
  101. package/dist/server/lib/dockerSandboxExecutionEnvironment.js +39 -10
  102. package/dist/server/lib/dockerSandboxExecutionEnvironment.js.map +1 -1
  103. package/dist/server/lib/dockerSandboxExecutionProvider.js +3 -1
  104. package/dist/server/lib/dockerSandboxExecutionProvider.js.map +1 -1
  105. package/dist/server/lib/dockerSandboxReleaseProfiles.js +8 -0
  106. package/dist/server/lib/dockerSandboxReleaseProfiles.js.map +1 -1
  107. package/dist/server/lib/executionCredentialCapabilities.js +39 -14
  108. package/dist/server/lib/executionCredentialCapabilities.js.map +1 -1
  109. package/dist/server/lib/executionEnvironment.js.map +1 -1
  110. package/dist/server/lib/executionEnvironmentContexts.js +1 -1
  111. package/dist/server/lib/executionEnvironmentContexts.js.map +1 -1
  112. package/dist/server/lib/executionEnvironmentLifecycle.js +1 -1
  113. package/dist/server/lib/executionEnvironmentLifecycle.js.map +1 -1
  114. package/dist/server/lib/executionEnvironmentReconciliation.js +22 -9
  115. package/dist/server/lib/executionEnvironmentReconciliation.js.map +1 -1
  116. package/dist/server/lib/executionEnvironmentRoutes.js +29 -25
  117. package/dist/server/lib/executionEnvironmentRoutes.js.map +1 -1
  118. package/dist/server/lib/executionEnvironmentValidation.js +205 -20
  119. package/dist/server/lib/executionEnvironmentValidation.js.map +1 -1
  120. package/dist/server/lib/executionEnvironmentValidationOperations.js +34 -29
  121. package/dist/server/lib/executionEnvironmentValidationOperations.js.map +1 -1
  122. package/dist/server/lib/executionEnvironments.js +74 -1
  123. package/dist/server/lib/executionEnvironments.js.map +1 -1
  124. package/dist/server/lib/executionProfiles.js +6 -3
  125. package/dist/server/lib/executionProfiles.js.map +1 -1
  126. package/dist/server/lib/executionRetryPredicates.js +2 -1
  127. package/dist/server/lib/executionRetryPredicates.js.map +1 -1
  128. package/dist/server/lib/executionRunAuthority.js +6 -1
  129. package/dist/server/lib/executionRunAuthority.js.map +1 -1
  130. package/dist/server/lib/genericToolCall.js +131 -9
  131. package/dist/server/lib/genericToolCall.js.map +1 -1
  132. package/dist/server/lib/hostExecutionEnvironment.js +5 -0
  133. package/dist/server/lib/hostExecutionEnvironment.js.map +1 -1
  134. package/dist/server/lib/lightweightPrompt.js +258 -18
  135. package/dist/server/lib/lightweightPrompt.js.map +1 -1
  136. package/dist/server/lib/mobileAccess.js +21 -13
  137. package/dist/server/lib/mobileAccess.js.map +1 -1
  138. package/dist/server/lib/modelResolutionErrors.js +4 -2
  139. package/dist/server/lib/modelResolutionErrors.js.map +1 -1
  140. package/dist/server/lib/models.js +15 -2
  141. package/dist/server/lib/models.js.map +1 -1
  142. package/dist/server/lib/oneShotAgent.js +11 -0
  143. package/dist/server/lib/oneShotAgent.js.map +1 -0
  144. package/dist/server/lib/projectAutoConfig.js +11 -5
  145. package/dist/server/lib/projectAutoConfig.js.map +1 -1
  146. package/dist/server/lib/projectMemory.js +3 -1
  147. package/dist/server/lib/projectMemory.js.map +1 -1
  148. package/dist/server/lib/projectMemoryScan.js +13 -3
  149. package/dist/server/lib/projectMemoryScan.js.map +1 -1
  150. package/dist/server/lib/projectMemoryTransfer.js +5 -2
  151. package/dist/server/lib/projectMemoryTransfer.js.map +1 -1
  152. package/dist/server/lib/projectTargets.js +10 -2
  153. package/dist/server/lib/projectTargets.js.map +1 -1
  154. package/dist/server/lib/promptSkills.js +1 -1
  155. package/dist/server/lib/promptSkills.js.map +1 -1
  156. package/dist/server/lib/run.js +32 -12
  157. package/dist/server/lib/run.js.map +1 -1
  158. package/dist/server/lib/runProcesses.js +13 -1
  159. package/dist/server/lib/runProcesses.js.map +1 -1
  160. package/dist/server/lib/runServices.js +5 -3
  161. package/dist/server/lib/runServices.js.map +1 -1
  162. package/dist/server/lib/runSessionLifecycle.js +10 -1
  163. package/dist/server/lib/runSessionLifecycle.js.map +1 -1
  164. package/dist/server/lib/runStatus.js +2 -1
  165. package/dist/server/lib/runStatus.js.map +1 -1
  166. package/dist/server/lib/serviceRunCleanup.js +70 -0
  167. package/dist/server/lib/serviceRunCleanup.js.map +1 -0
  168. package/dist/server/lib/serviceRuns.js +194 -12
  169. package/dist/server/lib/serviceRuns.js.map +1 -1
  170. package/dist/server/lib/skills.js +21 -4
  171. package/dist/server/lib/skills.js.map +1 -1
  172. package/dist/server/lib/specOperations.js +14 -10
  173. package/dist/server/lib/specOperations.js.map +1 -1
  174. package/dist/server/lib/specReviewOperations.js +20 -11
  175. package/dist/server/lib/specReviewOperations.js.map +1 -1
  176. package/dist/server/lib/specs.js +14 -4
  177. package/dist/server/lib/specs.js.map +1 -1
  178. package/dist/server/lib/ticketAutomationCommit.js +23 -7
  179. package/dist/server/lib/ticketAutomationCommit.js.map +1 -1
  180. package/dist/server/lib/ticketFollowUpOperations.js +7 -0
  181. package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
  182. package/dist/server/lib/ticketRunOperations.js +11 -1
  183. package/dist/server/lib/ticketRunOperations.js.map +1 -1
  184. package/dist/server/lib/ticketSettingsOperations.js +4 -1
  185. package/dist/server/lib/ticketSettingsOperations.js.map +1 -1
  186. package/dist/server/lib/toolUpgrade.js +1 -0
  187. package/dist/server/lib/toolUpgrade.js.map +1 -1
  188. package/dist/server/lib/transcriptRuns.js +4 -1
  189. package/dist/server/lib/transcriptRuns.js.map +1 -1
  190. package/dist/server/lib/types.js.map +1 -1
  191. package/dist/server/workers/build.js +9 -4
  192. package/dist/server/workers/build.js.map +1 -1
  193. package/dist/server/workers/chat.js +55 -11
  194. package/dist/server/workers/chat.js.map +1 -1
  195. package/dist/server/workers/followUp.js +6 -1
  196. package/dist/server/workers/followUp.js.map +1 -1
  197. package/dist/server/workers/plan.js +235 -68
  198. package/dist/server/workers/plan.js.map +1 -1
  199. package/dist/server/workers/planFollowUp.js +11 -4
  200. package/dist/server/workers/planFollowUp.js.map +1 -1
  201. package/dist/server/workers/review.js +15 -18
  202. package/dist/server/workers/review.js.map +1 -1
  203. package/dist/server/workers/specReview.js +7 -7
  204. package/dist/server/workers/specReview.js.map +1 -1
  205. package/dist/server/workers/specSession.js +8 -12
  206. package/dist/server/workers/specSession.js.map +1 -1
  207. package/package.json +1 -1
  208. package/dist/client/assets/GitHubActionsDialog-KFUiR00H.js +0 -1
  209. package/dist/client/assets/VerificationDialog-BIDttgiW.js +0 -4
  210. package/dist/client/assets/channel-Dhv_uSKx.js +0 -1
  211. package/dist/client/assets/classDiagram-4FO5ZUOK-9XKvSSLq.js +0 -1
  212. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Dbr5_49Y.js +0 -1
  213. package/dist/client/assets/index-ClRB9YWJ.css +0 -2
  214. package/dist/client/assets/index-DBMdsTvy.js +0 -276
  215. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Cyo85GPN.js +0 -1
@@ -34,6 +34,7 @@ import { attachChatTicketProposalsToMessageContent } from './lib/chatTicketPropo
34
34
  import { createCorsOriginResolver, parseCorsOrigins } from './lib/cors.js';
35
35
  import { abortGitOperation, branchExistsLocally, commitGitChanges, createWorktreeAsync, deleteLocalBranch, deleteWorktree, getBundleReviewDiffForCwd, getGitDiffDataAsync, getGitDiffFiles, getGitDiffFilesAsync, getGitStatus, getGitStatusAsync, getGitUnifiedDiff, getGitUnifiedDiffAsync, getLocalProjectBranch, getProjectBranch, getProjectBranchAsync, getProjectBranchSuggestions, getReviewDiffDataAsync, getSelectedGitUnifiedDiff, getUnpushedCommitDiffForCwd, getUnpushedCommitSummaryForCwd, getUnpushedCommitSummaryForCwdAsync, hasKnownBranchRef, listUnpushedCommitsForCwd, pullGitBranch, pushCurrentBranch, rebaseGitBranchOntoBase, resolveExistingWorktreePath, resolveWorktreePath, squashUnpushedCommitsForCwd, summarizeTicketDiffFiles, switchProjectBranch, syncWorktreeFilesAsync, undoLatestUnpushedCommitForCwd, UnpushedCommitDiffSelectionError } from './lib/git.js';
36
36
  import config from './lib/config.js';
37
+ import { getActiveTool, initializeActiveTool, setActiveTool } from './lib/activeTool.js';
37
38
  import { autoConfigProject, ProjectAutoConfigError } from './lib/projectAutoConfig.js';
38
39
  import { analyzeRepoPath, createInitialCommit, ensureInitialCommitForWorktrees, initializeGitRepo, isInitialCommitRequiredError, } from './lib/projectRepos.js';
39
40
  import { browseRepoPath } from './lib/directoryPicker.js';
@@ -41,14 +42,14 @@ import { resolveDesktopServerHost } from './lib/desktopServerHost.js';
41
42
  import { emitMobileRealtime, getMobileAccessStatus, regenerateMobilePairingChallenge, revokeMobileSession, setMobileAccessStatusChangeListener, startMobileAccess, stopMobileAccess, } from './lib/mobileAccess.js';
42
43
  import { validateDesktopMobileAccessRequest } from './lib/mobileAccessSecurity.js';
43
44
  import { refreshChatSessionUsageSnapshot, refreshSpecSessionUsageSnapshot, stopAllBuildAgents, stopAllReviewAgents, stopBuildAgent, stopReviewAgent } from './lib/agent.js';
44
- import { runLightweightPrompt } from './lib/lightweightPrompt.js';
45
+ import { runTrackedLightweightPrompt } from './lib/lightweightPrompt.js';
45
46
  import { advanceBuildChain, startBuildChain, stopBuildChain } from './lib/buildChains.js';
46
47
  import { activateQueuedBuildSequenceTicket, bindBuildSequenceTicketExecutionRun, compensateBuildSequenceAcceptance, enqueueBundledBuild, getDependencyOrderedBundleTicketIds, getBuildSequenceIdForTicket, getBuildSequenceTicketExecutionProfileSelection, hasActiveSequenceForBundle, releaseQueuedBuildSequenceTicketExecutionRunForRetry, removeTicketFromBuildSequence, stopBuildSequence, } from './lib/buildSequences.js';
47
48
  import { createExecutionProfileSelection, createServiceExecutionProfileSelection, executionProfileSelectionMetadata, validateExecutionProfileSelection } from './lib/executionRunAuthority.js';
48
49
  import { prepareTicketForBuild } from './lib/buildFlow.js';
49
50
  import { getActiveBundleRepairBlocker, getBundlePlanMutationBlockerById, shouldBlockPlanForBundleMutationById, } from './lib/bundleActivity.js';
50
- import { getDiscoveredModels, normalizeModelId, normalizeTicketModelId } from './lib/models.js';
51
- import { getSupportedAgentCatalog, normalizeAgentModelId } from './lib/agentCatalog.js';
51
+ import { getModelDiscoveryResult, normalizeModelId, normalizeTicketModelId } from './lib/models.js';
52
+ import { agentSupportsVariants, getSupportedAgentCatalog, isAgentExecutable, isSupportedAgent, normalizeAgentModelId } from './lib/agentCatalog.js';
52
53
  import { parseStoredAgentModelConfig, resolveHelperModelConfig, serializeAgentModelConfig, validateAgentModelConfigUpdate, validateDiscoveredAgentModelConfig, } from './lib/agentModelConfig.js';
53
54
  import { upgradeTool, UpgradeInProgressError } from './lib/toolUpgrade.js';
54
55
  import { acceptProjectMemorySuggestion, applyProjectMemorySuggestionToDecision, applyProjectMemorySuggestionToConvention, archiveProjectConvention, archiveProjectDecision, createProjectConvention, createProjectDecision, dismissProjectMemorySuggestion, getProjectMemoryById, getProjectMemorySuggestionById, isProjectMemoryEnabled, listProjectConventions, listLatestSuccessfulProjectContextArtifacts, listProjectDecisions, listProjectMemories, listProjectMemorySuggestions, restoreProjectConvention, restoreProjectDecision, serializeProjectMemoryFromConventionValue, serializeProjectMemoryFromDecisionValue, serializeProjectMemoryFromSuggestionValue, supersedeProjectDecision, supersedeProjectDecisionFromSuggestion, updateProjectConvention, updateProjectDecision, validateProjectConventionPayload, validateProjectDecisionPayload, } from './lib/projectMemory.js';
@@ -77,7 +78,7 @@ import { buildAutomationFixInstruction, clearAutomationPause, countBlockingFindi
77
78
  import { resolveAutomationCheckGateResume, runAutomationCommitChain, runAutomationCommitOperation } from './lib/ticketAutomationCommit.js';
78
79
  import { resolveBuildTicketCommitCheckpointLineage, canMutateBuildTicketCommitCheckpoint } from './lib/buildTicketCommit.js';
79
80
  import { continueAfterBuildCheckpoint } from './lib/automationBuildContinuation.js';
80
- import { getDiscoveredSkills, normalizeSkillNames } from './lib/skills.js';
81
+ import { getSkillDiscoveryResult, normalizeSkillNames } from './lib/skills.js';
81
82
  import { clearAllPreviewProxies } from './lib/previewProxy.js';
82
83
  import { createExecutionRun, addExecutionRunLink, addExecutionRunLinks, getExecutionRun, getLifecycleEvent, hasActiveBuildExecutionRunForTicket, getGitHubActionsExecutionDetails, getTestExecutionDetails, GitHubActionsDispatchConflictError, listExecutionRunLinks, listExecutionRuns, listLifecycleEvents, listProjectLifecycleEvents, toCanonicalLifecycleEvent, transitionExecutionRun, withExecutionRunTransaction, } from './lib/executionRuns.js';
83
84
  import { appendReviewRepairIterationDecisionInTransaction, attachReviewRepairActionEnvelopeInTransaction, attachReviewRepairActionInTransaction, claimReviewRepairIterationInTransaction, assertReviewRepairIterationDeletionEligible, deleteTerminalReviewRepairIterationsForTicketInTransaction, getActiveReviewRepairIteration, getReviewRepairIteration, pauseReviewRepairIteration, rewindStaleReviewRepairVerification, replaceReviewRepairActionEnvelopeRetryInTransaction, replaceReviewRepairActionRetryInTransaction, replaceReviewRepairVerificationRetryInTransaction, resetReviewRepairGateForRetry, resumePausedReviewRepairIteration, terminalizeReviewRepairIteration, terminalizeReviewRepairIterationInTransaction, } from './lib/reviewRepairIterations.js';
@@ -105,8 +106,9 @@ import { refreshIfNeeded as refreshAssignedIssues, clearCachedAssignedIssues } f
105
106
  import { buildCommitMessagePrompt, normalizeGeneratedCommitMessage } from './lib/commitMessage.js';
106
107
  import { BUNDLE_PULL_REQUEST_SYNC_TTL_MS, getBundlePullRequestRecord, hasOpenBundlePullRequest, serializeBundlePullRequest, shouldSyncBundlePullRequest, syncTrackedBundlePullRequestIfNeeded, upsertBundlePullRequest, upsertBundlePullRequestFromGitHub, } from './lib/bundlePullRequests.js';
107
108
  import { countInboundProjectLinks, getEffectiveProject, getProjectCheckDefinitions, getProjectById, getProjectTestCommands, getProjectTicketStats, hasProjectRunIde, listInterruptedProjectDeletions, listProjects, releaseInterruptedProjectDeletionClaims, replaceProjectLinks, serializeProject, updateProjectActiveTarget, validateProjectRequiredCheckPolicyReferences, validateProjectPayload, } from './lib/projects.js';
108
- import { getActiveRunStatus, getActiveRunStatusForProject, getLastRunStatusForProject, getPreviewStatusForProject, hasRunConfig, isRunning, openIde, openTicketIdeInWorkspace, resolveProjectRunContextKey, runTicketInWorkspace, stopAllTickets, stopTicket } from './lib/run.js';
109
- import { hasActiveProjectServiceRun } from './lib/serviceRuns.js';
109
+ import { forceReleaseProjectRunCleanup, getActiveRunStatus, getActiveRunStatusForProject, getLastRunStatusForProject, getPreviewStatusForProject, hasRunConfig, isRunning, openIde, openTicketIdeInWorkspace, resolveProjectRunContextKey, runTicketInWorkspace, stopAllTickets, stopTicket } from './lib/run.js';
110
+ import { reconcilePendingServiceCleanups } from './lib/serviceRunCleanup.js';
111
+ import { getProjectServiceCleanupStatus, hasActiveProjectServiceRun } from './lib/serviceRuns.js';
110
112
  import { projectRunStatus } from './lib/runStatus.js';
111
113
  import { clearAllTestSessions, createTestSession, deleteTestSession, discoverTestsForSession, doesTestFileExistForSession, getTestSession, isTestSelectionSupported, startTestSessionRun, stopTestSessionRun } from './lib/testSessions.js';
112
114
  import { closeCheckRunnerAdmissions, finalizeProductionCheckApproval, getCheckBatchAttempts, openCheckRunnerAdmissions, rerunCheckBatchAndSchedule, resumeProductionCheckApproval, shutdownCheckRunner, startCheckBatch, stopCheckBatch } from './lib/checkRunner.js';
@@ -768,6 +770,7 @@ const scheduleBuildAfterTicketDeletion = (result) => {
768
770
  };
769
771
  const CORS_ORIGINS = parseCorsOrigins(process.env.CORS_ORIGIN);
770
772
  const CORS_ORIGIN_RESOLVER = createCorsOriginResolver(CORS_ORIGINS);
773
+ initializeActiveTool();
771
774
  const app = express();
772
775
  const API_TIMING_ENABLED = process.env.ARCHON_API_TIMING === '1';
773
776
  const createApiTiming = (route, details = {}) => {
@@ -1992,6 +1995,7 @@ const serializeBundleDetails = (project, bundle, extras = {}) => {
1992
1995
  execution_order_ticket_ids: tickets.map(ticket => ticket.id),
1993
1996
  latest_session_ticket_id: latestSessionTicket?.id ?? null,
1994
1997
  latest_session_id: latestSessionTicket?.session_id ?? null,
1998
+ latest_session_tool: latestSessionTicket?.tool ?? null,
1995
1999
  review_owner_ticket_id: extras.review_owner_ticket_id ?? null,
1996
2000
  target_ticket_id: resolvedTargetTicket?.id ?? null,
1997
2001
  has_completed_review: bundleReviewState.has_completed_review,
@@ -2026,6 +2030,7 @@ const serializeBundleConversationDetails = (project, bundle, extras = {}) => {
2026
2030
  execution_order_ticket_ids: tickets.map(ticket => ticket.id),
2027
2031
  latest_session_ticket_id: latestSessionTicket?.id ?? null,
2028
2032
  latest_session_id: latestSessionTicket?.session_id ?? null,
2033
+ latest_session_tool: latestSessionTicket?.tool ?? null,
2029
2034
  review_owner_ticket_id: reviewOwnerTicketId,
2030
2035
  target_ticket_id: resolvedTargetTicket?.id ?? null,
2031
2036
  };
@@ -2823,7 +2828,7 @@ app.get('/run-status', (req, res) => {
2823
2828
  const requestedProjectId = getRequestedProjectId(req);
2824
2829
  const activeRun = requestedProjectId ? getActiveRunStatusForProject(requestedProjectId) : getActiveRunStatus();
2825
2830
  const durableAuthority = hasActiveProjectServiceRun(requestedProjectId);
2826
- return res.json(projectRunStatus(activeRun, requestedProjectId ? getLastRunStatusForProject(requestedProjectId) : null, durableAuthority));
2831
+ return res.json(projectRunStatus(activeRun, requestedProjectId ? getLastRunStatusForProject(requestedProjectId) : null, durableAuthority, requestedProjectId && !activeRun && durableAuthority ? getProjectServiceCleanupStatus(requestedProjectId) : null));
2827
2832
  });
2828
2833
  app.get('/preview-status', (req, res) => {
2829
2834
  const projectId = getRequestedProjectId(req);
@@ -3876,6 +3881,9 @@ app.post('/bundles/:id/pull-request-description', async (req, res) => {
3876
3881
  return res.status(409).json({ error: 'Pull request descriptions are not available for the project root bundle.' });
3877
3882
  }
3878
3883
  const helperTool = config.tool ?? 'opencode';
3884
+ if (!isAgentExecutable(helperTool)) {
3885
+ return res.status(409).json({ error: `${helperTool} execution is not available` });
3886
+ }
3879
3887
  const helperConfig = resolveHelperModelConfig({
3880
3888
  helperModelsJson: result.project.helper_models_json,
3881
3889
  agent: helperTool,
@@ -3895,16 +3903,15 @@ app.post('/bundles/:id/pull-request-description', async (req, res) => {
3895
3903
  .map(ticket => ticket.title.trim())
3896
3904
  .filter(Boolean);
3897
3905
  try {
3898
- const worktreePath = resolveWorktreePath(bundle.branch, result.project);
3899
- const rawDescription = await runLightweightPrompt({
3900
- tool: helperTool,
3901
- model: helperConfig.model,
3902
- variant: helperConfig.variant,
3906
+ const rawDescription = await runTrackedLightweightPrompt({
3907
+ project: result.project,
3908
+ execution: { tool: helperTool, model: helperConfig.model, variant: helperConfig.variant },
3909
+ target: { kind: 'bundle-worktree', bundleId: bundle.id, branch: bundle.branch },
3903
3910
  }, buildPullRequestDescriptionPrompt({
3904
3911
  title,
3905
3912
  ticketTitles,
3906
3913
  commitSubjects,
3907
- }), worktreePath);
3914
+ }));
3908
3915
  const description = normalizeGeneratedPullRequestDescription(rawDescription);
3909
3916
  if (!description) {
3910
3917
  return res.status(500).json({ error: 'Unable to generate a pull request description right now.' });
@@ -5687,22 +5694,25 @@ app.post('/bundles/:id/dismiss-automation-pause', async (req, res) => {
5687
5694
  return res.json(serializeBundleDetails(result.project, bundle));
5688
5695
  });
5689
5696
  app.get('/tool', (_req, res) => {
5690
- res.json({ tool: config.tool ?? 'opencode' });
5697
+ res.json({ tool: getActiveTool() });
5691
5698
  });
5692
5699
  app.post('/tool', (req, res) => {
5693
5700
  const { tool } = req.body;
5694
- if (tool !== 'claude' && tool !== 'opencode') {
5701
+ if (!isSupportedAgent(tool)) {
5695
5702
  return res.status(400).json({ error: 'Invalid tool' });
5696
5703
  }
5697
- config.tool = tool;
5704
+ setActiveTool(tool);
5698
5705
  io.emit('tool:updated', { tool });
5699
5706
  res.json({ tool });
5700
5707
  });
5701
5708
  app.post('/tools/upgrade', async (req, res) => {
5702
5709
  const { tool } = req.body ?? {};
5703
- if (tool !== 'claude' && tool !== 'opencode') {
5710
+ if (!isSupportedAgent(tool)) {
5704
5711
  return res.status(400).json({ error: 'Invalid tool' });
5705
5712
  }
5713
+ if (!isAgentExecutable(tool)) {
5714
+ return res.status(409).json({ error: `${tool} execution is not available` });
5715
+ }
5706
5716
  try {
5707
5717
  const result = await upgradeTool(tool);
5708
5718
  return res.json(result);
@@ -5724,13 +5734,16 @@ app.post('/projects/auto-config', async (req, res) => {
5724
5734
  }
5725
5735
  try {
5726
5736
  const requestedTool = req.body?.tool;
5727
- if (requestedTool !== undefined && requestedTool !== 'claude' && requestedTool !== 'opencode') {
5737
+ if (requestedTool !== undefined && !isSupportedAgent(requestedTool)) {
5728
5738
  return res.status(400).json({ error: 'tool must be a supported agent' });
5729
5739
  }
5730
5740
  const tool = requestedTool
5731
5741
  ?? (hasOwn(req.body ?? {}, 'helper_model') && validation.values.helper_model ? 'opencode' : null)
5732
5742
  ?? config.tool
5733
5743
  ?? 'opencode';
5744
+ if (!isAgentExecutable(tool)) {
5745
+ return res.status(409).json({ error: `${tool} execution is not available` });
5746
+ }
5734
5747
  const helperConfig = resolveHelperModelConfig({
5735
5748
  helperModelsJson: validation.values.helper_models_json,
5736
5749
  agent: tool,
@@ -5807,30 +5820,37 @@ app.post('/projects/browse-repo-path', (_req, res) => {
5807
5820
  });
5808
5821
  app.get('/models', async (req, res) => {
5809
5822
  const tool = typeof req.query.tool === 'string' ? req.query.tool : '';
5810
- if (tool !== 'opencode' && tool !== 'claude') {
5811
- return res.status(400).json({ error: 'Model discovery is only available for opencode or claude' });
5823
+ if (!isSupportedAgent(tool)) {
5824
+ return res.status(400).json({ error: 'Model discovery is only available for supported agents' });
5812
5825
  }
5813
5826
  const timing = createApiTiming('/models', { tool });
5814
5827
  res.set('Cache-Control', 'no-store');
5815
- const models = await getDiscoveredModels(tool);
5828
+ const result = await getModelDiscoveryResult(tool);
5816
5829
  timing.mark('get_discovered_models');
5817
- timing.end({ count: models.length });
5818
- return res.json(models);
5830
+ timing.end({ count: result.models.length, status: result.status });
5831
+ return res.json(result);
5819
5832
  });
5820
5833
  app.get('/agents', async (_req, res) => {
5821
5834
  res.set('Cache-Control', 'no-store');
5822
- return res.json(await getSupportedAgentCatalog());
5835
+ const projectId = typeof _req.query.project_id === 'string' ? _req.query.project_id : null;
5836
+ const project = projectId ? getProjectById(projectId) : null;
5837
+ return res.json(await getSupportedAgentCatalog({
5838
+ probeHostAvailability: project?.build_execution_provider === 'host',
5839
+ }));
5823
5840
  });
5824
5841
  app.get('/skills', async (req, res) => {
5825
5842
  const tool = typeof req.query.tool === 'string' ? req.query.tool : '';
5826
5843
  const projectId = typeof req.query.project_id === 'string' ? req.query.project_id : null;
5827
- if (tool !== 'opencode') {
5828
- return res.status(400).json({ error: 'Skill discovery is only available for opencode' });
5844
+ if (tool !== 'opencode' && tool !== 'codex') {
5845
+ return res.status(400).json({ error: 'Skill discovery is only available for agents with skill support' });
5829
5846
  }
5830
5847
  res.set('Cache-Control', 'no-store');
5831
5848
  const project = projectId ? getProjectById(projectId) : null;
5832
- const skills = await getDiscoveredSkills(tool, { projectPath: project?.repo_path ?? null });
5833
- return res.json(skills);
5849
+ const result = await getSkillDiscoveryResult(tool, {
5850
+ projectId: project?.id ?? null,
5851
+ projectPath: project?.repo_path ?? null,
5852
+ });
5853
+ return res.json(result);
5834
5854
  });
5835
5855
  app.get('/integrations', (req, res) => {
5836
5856
  const result = getRequiredProject(req);
@@ -6606,6 +6626,12 @@ app.post('/plan', async (req, res) => {
6606
6626
  app.post('/planning-agent', async (req, res) => {
6607
6627
  const { description, model, variant, project_id } = req.body;
6608
6628
  const tool = resolveChatTool(req.body.tool);
6629
+ if (!tool) {
6630
+ return res.status(400).json({ error: 'tool must be a supported agent' });
6631
+ }
6632
+ if (!isAgentExecutable(tool)) {
6633
+ return res.status(409).json({ error: `${tool} execution is not available` });
6634
+ }
6609
6635
  if (typeof description !== 'string' || !description.trim()) {
6610
6636
  return res.status(400).json({ error: 'Description is required' });
6611
6637
  }
@@ -6693,8 +6719,8 @@ app.post('/planning-agent', async (req, res) => {
6693
6719
  draft,
6694
6720
  initiativePrompt: resolvedDescription,
6695
6721
  projectId: project.id,
6696
- model: tool === 'opencode' && typeof model === 'string' ? normalizeModelId(model) || null : null,
6697
- variant: tool === 'opencode' && typeof variant === 'string' && variant.trim() ? variant.trim() : null,
6722
+ model: typeof model === 'string' ? normalizeAgentModelId(tool, model) || null : null,
6723
+ variant: (tool === 'opencode' || tool === 'codex') && typeof variant === 'string' && variant.trim() ? variant.trim() : null,
6698
6724
  skills: resolveRequestedSkills(req.body?.skills),
6699
6725
  worktreeBundleId: bundleSelection.bundleId,
6700
6726
  });
@@ -7840,11 +7866,20 @@ app.post('/projects/:id/git-commit-message', async (req, res) => {
7840
7866
  });
7841
7867
  try {
7842
7868
  const helperTool = config.tool ?? 'opencode';
7869
+ if (!isAgentExecutable(helperTool)) {
7870
+ return res.status(409).json({ error: `${helperTool} execution is not available` });
7871
+ }
7843
7872
  const helperConfig = resolveHelperModelConfig({
7844
7873
  helperModelsJson: workspace.project.helper_models_json,
7845
7874
  agent: helperTool,
7846
7875
  });
7847
- const rawMessage = await runLightweightPrompt({ tool: helperTool, ...helperConfig }, prompt, workspace.cwd);
7876
+ const rawMessage = await runTrackedLightweightPrompt({
7877
+ project: workspace.project,
7878
+ execution: { tool: helperTool, ...helperConfig },
7879
+ target: workspace.target_kind === 'bundle'
7880
+ ? { kind: 'bundle-worktree', bundleId: workspace.target_bundle_id, branch: workspace.branch }
7881
+ : { kind: 'project-root', bundleId: null, branch: workspace.branch },
7882
+ }, prompt);
7848
7883
  const message = normalizeGeneratedCommitMessage(rawMessage);
7849
7884
  if (!message) {
7850
7885
  return res.status(500).json({ error: 'Unable to generate a commit message right now.' });
@@ -7868,6 +7903,9 @@ app.post('/projects/:id/pull-request-description', async (req, res) => {
7868
7903
  return res.status(409).json({ error: 'Pull request descriptions for bundle targets should use the bundle route.' });
7869
7904
  }
7870
7905
  const helperTool = config.tool ?? 'opencode';
7906
+ if (!isAgentExecutable(helperTool)) {
7907
+ return res.status(409).json({ error: `${helperTool} execution is not available` });
7908
+ }
7871
7909
  const helperConfig = resolveHelperModelConfig({
7872
7910
  helperModelsJson: project.helper_models_json,
7873
7911
  agent: helperTool,
@@ -7883,15 +7921,15 @@ app.post('/projects/:id/pull-request-description', async (req, res) => {
7883
7921
  .filter(Boolean)
7884
7922
  : [];
7885
7923
  try {
7886
- const rawDescription = await runLightweightPrompt({
7887
- tool: helperTool,
7888
- model: helperConfig.model,
7889
- variant: helperConfig.variant,
7924
+ const rawDescription = await runTrackedLightweightPrompt({
7925
+ project,
7926
+ execution: { tool: helperTool, model: helperConfig.model, variant: helperConfig.variant },
7927
+ target: { kind: 'project-root', bundleId: null, branch: workspace.branch },
7890
7928
  }, buildPullRequestDescriptionPrompt({
7891
7929
  title,
7892
7930
  ticketTitles: [],
7893
7931
  commitSubjects,
7894
- }), workspace.cwd);
7932
+ }));
7895
7933
  const description = normalizeGeneratedPullRequestDescription(rawDescription);
7896
7934
  if (!description) {
7897
7935
  return res.status(500).json({ error: 'Unable to generate a pull request description right now.' });
@@ -8385,8 +8423,11 @@ app.post('/tickets', (req, res) => {
8385
8423
  return res.status(400).json({ error: 'project_id must reference an existing project' });
8386
8424
  }
8387
8425
  const requestTool = resolveChatTool(req.body.tool ?? config.tool);
8426
+ if (!requestTool) {
8427
+ return res.status(400).json({ error: 'tool must be a supported agent' });
8428
+ }
8388
8429
  const model = req.body.model != null ? normalizeAgentModelId(requestTool, req.body.model) || null : null;
8389
- const variant = requestTool === 'opencode' && typeof req.body.variant === 'string' && req.body.variant.trim()
8430
+ const variant = agentSupportsVariants(requestTool) && typeof req.body.variant === 'string' && req.body.variant.trim()
8390
8431
  ? req.body.variant.trim()
8391
8432
  : null;
8392
8433
  const skills = resolveRequestedSkills(req.body.skills);
@@ -8503,7 +8544,9 @@ app.patch('/tickets/:id', async (req, res) => {
8503
8544
  resolvedModel = null;
8504
8545
  }
8505
8546
  else {
8506
- const normalizedModel = normalizeTicketModelId(req.body.model);
8547
+ const normalizedModel = ticket.tool
8548
+ ? normalizeAgentModelId(ticket.tool, req.body.model)
8549
+ : normalizeTicketModelId(req.body.model);
8507
8550
  if (normalizedModel) {
8508
8551
  resolvedModel = normalizedModel;
8509
8552
  }
@@ -9150,11 +9193,22 @@ app.post('/tickets/:id/git-commit-message', async (req, res) => {
9150
9193
  });
9151
9194
  try {
9152
9195
  const helperTool = resolveTicketTool(ticket, config.tool ?? 'opencode');
9196
+ if (!isAgentExecutable(helperTool)) {
9197
+ return res.status(409).json({ error: `${helperTool} execution is not available` });
9198
+ }
9153
9199
  const helperConfig = resolveHelperModelConfig({
9154
9200
  helperModelsJson: workspace.project.helper_models_json,
9155
9201
  agent: helperTool,
9156
9202
  });
9157
- const rawMessage = await runLightweightPrompt({ tool: helperTool, ...helperConfig }, prompt, workspace.cwd);
9203
+ const rawMessage = await runTrackedLightweightPrompt({
9204
+ project: workspace.project,
9205
+ execution: { tool: helperTool, ...helperConfig },
9206
+ target: workspace.kind === 'project_root'
9207
+ ? { kind: 'project-root', bundleId: null, branch: workspace.branch }
9208
+ : ticket.worktree_bundle_id
9209
+ ? { kind: 'bundle-worktree', bundleId: ticket.worktree_bundle_id, branch: workspace.branch }
9210
+ : { kind: 'branch-worktree', bundleId: null, branch: workspace.branch },
9211
+ }, prompt);
9158
9212
  const message = normalizeGeneratedCommitMessage(rawMessage);
9159
9213
  if (!message) {
9160
9214
  return res.status(500).json({ error: 'Unable to generate a commit message right now.' });
@@ -10073,6 +10127,23 @@ app.post('/projects/:id/stop-run', async (req, res) => {
10073
10127
  }
10074
10128
  return res.status(result.status).json(result.value);
10075
10129
  });
10130
+ app.post('/projects/:id/service-cleanup/force-release', (req, res) => {
10131
+ if (req.body?.confirm !== true) {
10132
+ return res.status(400).json({ error: 'Force release requires explicit confirmation' });
10133
+ }
10134
+ if (!getProjectById(req.params.id)) {
10135
+ return res.status(404).json({ error: 'Not found' });
10136
+ }
10137
+ try {
10138
+ const released = forceReleaseProjectRunCleanup(req.params.id);
10139
+ return released
10140
+ ? res.json({ active_run: null })
10141
+ : res.status(409).json({ error: 'No pending service cleanup was found' });
10142
+ }
10143
+ catch (error) {
10144
+ return res.status(409).json({ error: error instanceof Error ? error.message : String(error) });
10145
+ }
10146
+ });
10076
10147
  app.post('/tickets/:id/stop-build', async (req, res) => {
10077
10148
  const result = await stopBuildTicketRun({
10078
10149
  ticketId: req.params.id,
@@ -10177,6 +10248,10 @@ app.post('/tickets/:id/plan', (req, res) => {
10177
10248
  });
10178
10249
  }
10179
10250
  }
10251
+ const planTool = resolveTicketTool(ticket, config.tool ?? 'opencode');
10252
+ if (!isAgentExecutable(planTool)) {
10253
+ return res.status(409).json({ error: `${planTool} execution is not available` });
10254
+ }
10180
10255
  const scheduling = startPlan(ticket, io, {
10181
10256
  branch,
10182
10257
  targetBundleId,
@@ -10362,7 +10437,10 @@ const runExecutionEnvironmentLifecycleReconciliation = () => {
10362
10437
  if (executionEnvironmentReconciliationPromise) {
10363
10438
  return executionEnvironmentReconciliationPromise;
10364
10439
  }
10365
- executionEnvironmentReconciliationPromise = reconcileExecutionEnvironmentLifecycleOperations()
10440
+ executionEnvironmentReconciliationPromise = reconcilePendingServiceCleanups({
10441
+ isProjectOwnedInMemory: projectId => getActiveRunStatusForProject(projectId) !== null,
10442
+ })
10443
+ .then(() => reconcileExecutionEnvironmentLifecycleOperations())
10366
10444
  .then(() => undefined)
10367
10445
  .catch(error => {
10368
10446
  console.error('Failed to reconcile execution environment lifecycle operations', error);