@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.
- package/dist/client/assets/ActivityView-p8gBUxYN.js +1 -0
- package/dist/client/assets/GitHubActionsDialog-BRxGcSyq.js +1 -0
- package/dist/client/assets/VerificationDialog-B6l5TYOS.js +4 -0
- package/dist/client/assets/{arc-C83vRtlz.js → arc-D2Nn9xIj.js} +1 -1
- package/dist/client/assets/architecture-7EHR7CIX-C-4Cp4ml.js +1 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-DFbki8mi.js → architectureDiagram-3BPJPVTR-DnuKO1RY.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-BZFehG8P.js → blockDiagram-GPEHLZMM-CnQ7FwEp.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-FVDXRu1t.js → c4Diagram-AAUBKEIU-BF1hFXwp.js} +1 -1
- package/dist/client/assets/channel-TJtf4cBJ.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-4tuVZaT0.js → chunk-2J33WTMH-UvCFvkZO.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-DSn14S35.js → chunk-3OPIFGDE-z1l5nBD0.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-C5pU9ApX.js → chunk-4BX2VUAB-CtLS8D71.js} +1 -1
- package/dist/client/assets/{chunk-4EGX6M5U-CAjWPjND.js → chunk-4EGX6M5U-Btnm0QNe.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-DhO4-AG4.js → chunk-55IACEB6-74CcJaub.js} +1 -1
- package/dist/client/assets/{chunk-5DO6E6H7-BDKA-zHS.js → chunk-5DO6E6H7-WLZ8L4ko.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-Cwx1KNjg.js → chunk-5ZQYHXKU-Bis0Pw2_.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-Odza4hes.js → chunk-727SXJPM-B3gUO8rD.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-BmVoQT7M.js → chunk-AQP2D5EJ-hPBzrrh5.js} +1 -1
- package/dist/client/assets/{chunk-BR22UD5L-12D2GWh4.js → chunk-BR22UD5L-Cou5beGe.js} +1 -1
- package/dist/client/assets/{chunk-BSJP7CBP-DMi77e84.js → chunk-BSJP7CBP-DJ57XcV5.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-Bg7Ktx0B.js → chunk-CSCIHK7Q-BfOng_VY.js} +2 -2
- package/dist/client/assets/{chunk-FHYWG6QK-BhSajKiB.js → chunk-FHYWG6QK-Ba10e2kj.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-Drmlc0wM.js → chunk-FMBD7UC4-CEo2wZMx.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-2tnhar2x.js → chunk-KSCS5N6A-B2Jg7PW5.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-dAyg8qMJ.js → chunk-L5ZTLDWV-CUYujZxt.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-0gElxrlR.js → chunk-LZXEDZCA-CH_eV8jH.js} +2 -2
- package/dist/client/assets/{chunk-MPE355IW-Cw8YmjTC.js → chunk-MPE355IW-MqEt-J8G.js} +1 -1
- package/dist/client/assets/{chunk-MZUSXYTE-jvxRCZ7x.js → chunk-MZUSXYTE-DdNi9lhx.js} +1 -1
- package/dist/client/assets/{chunk-N66VUXT2-00i4y0yD.js → chunk-N66VUXT2-CjemTW4E.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-Bu-8Lz91.js → chunk-ND2GUHAM-BVF5evM9.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-CInZFdzd.js → chunk-NZK2D7GU-WfG-2AOS.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-rAzpvdNR.js → chunk-O5CBEL6O-CSF9ozqy.js} +1 -1
- package/dist/client/assets/{chunk-PUPMXCY4-DfWourL7.js → chunk-PUPMXCY4-ZvwTw0To.js} +1 -1
- package/dist/client/assets/chunk-QZHKN3VN-LI_RZca2.js +1 -0
- package/dist/client/assets/{chunk-UIBZB4QT-v-a5ZfN6.js → chunk-UIBZB4QT-BTY9be9s.js} +1 -1
- package/dist/client/assets/{chunk-WCWK7LTN-CtYzhvvb.js → chunk-WCWK7LTN-Db1n3n3-.js} +1 -1
- package/dist/client/assets/chunk-WU5MYG2G-DoVpb2oe.js +1 -0
- package/dist/client/assets/{chunk-XPW4576I-CvnAuXH2.js → chunk-XPW4576I-DObFPxjB.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CnKIRKWC.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-5ZgjUwTv.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-fchD-dH2.js → cose-bilkent-S5V4N54A-MlOPiG6P.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-Dgua1iuh.js → dagre-BM42HDAG-rekDIYnC.js} +1 -1
- package/dist/client/assets/{dagre-DSrzm-Gq.js → dagre-BWNHuDdf.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-odacwlwu.js → diagram-2AECGRRQ-Z4mXdhW0.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-BiKjFmJ1.js → diagram-5GNKFQAL-DqeVe5Vc.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-CmYcvFri.js → diagram-KO2AKTUF-ijppTuNc.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-ncx0RBuX.js → diagram-LMA3HP47-CDGLx0-N.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-DbchKIzw.js → diagram-OG6HWLK6-DDlnjzF8.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-CMnpvRyQ.js → erDiagram-TEJ5UH35-V_axe9oz.js} +1 -1
- package/dist/client/assets/eventmodeling-FCH6USID-Dqb6QKoI.js +1 -0
- package/dist/client/assets/{flowDiagram-I6XJVG4X-Bi02_PK5.js → flowDiagram-I6XJVG4X-GH5q79jg.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-BiS992US.js → ganttDiagram-6RSMTGT7-BMWVdLeQ.js} +1 -1
- package/dist/client/assets/gitGraph-WXDBUCRP-DYEsqh93.js +1 -0
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-Cc1hrTsT.js → gitGraphDiagram-PVQCEYII-VrV8jMUg.js} +1 -1
- package/dist/client/assets/index-B7J4DYDu.js +275 -0
- package/dist/client/assets/index-CsZfTdMO.css +2 -0
- package/dist/client/assets/info-J43DQDTF-CfjXFZai.js +1 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-BKVfqJCe.js → infoDiagram-5YYISTIA-EGiVbp17.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-B-IbFOty.js → ishikawaDiagram-YF4QCWOH-Dw3CiXbm.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-DAZBgAQW.js → journeyDiagram-JHISSGLW-2S631RY5.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-Bkr_fXev.js → kanban-definition-UN3LZRKU-pc9vzUtB.js} +1 -1
- package/dist/client/assets/{line-CROuuXDO.js → line-BBMBmEjI.js} +1 -1
- package/dist/client/assets/{linear-BOwW57yX.js → linear-DT4rSZvy.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-DrBw_Rsc.js → mermaid-parser.core-ClNeolx0.js} +2 -2
- package/dist/client/assets/{mermaid.core-pPd6OYYj.js → mermaid.core-Q4IJbm5V.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-BXSd3TZU.js → mindmap-definition-RKZ34NQL-DUTZxR8H.js} +1 -1
- package/dist/client/assets/{ordinal-CZ33lFpK.js → ordinal-k--hYEme.js} +1 -1
- package/dist/client/assets/packet-YPE3B663-Dv0HkRHU.js +1 -0
- package/dist/client/assets/pie-LRSECV5Y-S5zPzZFN.js +1 -0
- package/dist/client/assets/{pieDiagram-4H26LBE5-DoT7PIZC.js → pieDiagram-4H26LBE5-RW5hNtJq.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-ycZkLowm.js → quadrantDiagram-W4KKPZXB-CK60c7X9.js} +1 -1
- package/dist/client/assets/radar-GUYGQ44K-B7psLv22.js +1 -0
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-BPkO1yLu.js → requirementDiagram-4Y6WPE33-Dz35FvcC.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-D7AvhhCw.js → sankeyDiagram-5OEKKPKP-ByyluoXu.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-C982swnH.js → sequenceDiagram-3UESZ5HK-C-879UFe.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-xvJ3u8lc.js → stateDiagram-AJRCARHV-B8neDlUu.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-B4Mq8Abu.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-D89qjzb5.js → timeline-definition-PNZ67QCA-iAwrltn1.js} +1 -1
- package/dist/client/assets/treeView-BLDUP644-B8H0kT67.js +1 -0
- package/dist/client/assets/treemap-LRROVOQU-DPLhFHnh.js +1 -0
- package/dist/client/assets/{vennDiagram-CIIHVFJN-CoKeC__u.js → vennDiagram-CIIHVFJN-DHN61m8d.js} +1 -1
- package/dist/client/assets/wardley-L42UT6IY-B5-Vb08V.js +1 -0
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DKhjzvSE.js → wardleyDiagram-YWT4CUSO-XDVo7Jy1.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DFn9ass1.js → xychartDiagram-2RQKCTM6-Cb-HLpaN.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +237 -0
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +211 -87
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/agent.js +198 -100
- package/dist/server/lib/agent.js.map +1 -1
- package/dist/server/lib/agentProvider.js +14 -9
- package/dist/server/lib/agentProvider.js.map +1 -1
- package/dist/server/lib/agentRuns.js +20 -9
- package/dist/server/lib/agentRuns.js.map +1 -1
- package/dist/server/lib/buildExecutionEnvironment.js +517 -0
- package/dist/server/lib/buildExecutionEnvironment.js.map +1 -0
- package/dist/server/lib/buildOpenQuestionOperations.js +9 -3
- package/dist/server/lib/buildOpenQuestionOperations.js.map +1 -1
- package/dist/server/lib/chatOperations.js +30 -1
- package/dist/server/lib/chatOperations.js.map +1 -1
- package/dist/server/lib/checkAutoFix.js +1 -0
- package/dist/server/lib/checkAutoFix.js.map +1 -1
- package/dist/server/lib/checkRepairDispatch.js +3 -1
- package/dist/server/lib/checkRepairDispatch.js.map +1 -1
- package/dist/server/lib/dockerSandboxCredentials.js +62 -0
- package/dist/server/lib/dockerSandboxCredentials.js.map +1 -0
- package/dist/server/lib/dockerSandboxEnvironmentOperations.js +54 -0
- package/dist/server/lib/dockerSandboxEnvironmentOperations.js.map +1 -0
- package/dist/server/lib/dockerSandboxExecutionEnvironment.js +631 -0
- package/dist/server/lib/dockerSandboxExecutionEnvironment.js.map +1 -0
- package/dist/server/lib/dockerSandboxExecutionProvider.js +196 -0
- package/dist/server/lib/dockerSandboxExecutionProvider.js.map +1 -0
- package/dist/server/lib/dockerSandboxOpencodeSessionOperations.js +29 -0
- package/dist/server/lib/dockerSandboxOpencodeSessionOperations.js.map +1 -0
- package/dist/server/lib/dockerSandboxRuntimeController.js +187 -0
- package/dist/server/lib/dockerSandboxRuntimeController.js.map +1 -0
- package/dist/server/lib/executionEnvironment.js +22 -0
- package/dist/server/lib/executionEnvironment.js.map +1 -1
- package/dist/server/lib/executionEnvironmentContexts.js +144 -0
- package/dist/server/lib/executionEnvironmentContexts.js.map +1 -0
- package/dist/server/lib/executionEnvironmentLifecycle.js +63 -0
- package/dist/server/lib/executionEnvironmentLifecycle.js.map +1 -0
- package/dist/server/lib/executionEnvironmentReconciliation.js +782 -0
- package/dist/server/lib/executionEnvironmentReconciliation.js.map +1 -0
- package/dist/server/lib/executionEnvironmentRoutes.js +354 -0
- package/dist/server/lib/executionEnvironmentRoutes.js.map +1 -0
- package/dist/server/lib/executionEnvironmentValidation.js +486 -0
- package/dist/server/lib/executionEnvironmentValidation.js.map +1 -0
- package/dist/server/lib/executionEnvironmentValidationOperations.js +635 -0
- package/dist/server/lib/executionEnvironmentValidationOperations.js.map +1 -0
- package/dist/server/lib/executionEnvironments.js +726 -0
- package/dist/server/lib/executionEnvironments.js.map +1 -0
- package/dist/server/lib/executionReconciliation.js +77 -0
- package/dist/server/lib/executionReconciliation.js.map +1 -1
- package/dist/server/lib/executionRetry.js +3 -0
- package/dist/server/lib/executionRetry.js.map +1 -1
- package/dist/server/lib/executionRuns.js +1 -0
- package/dist/server/lib/executionRuns.js.map +1 -1
- package/dist/server/lib/executionTargets.js +107 -0
- package/dist/server/lib/executionTargets.js.map +1 -0
- package/dist/server/lib/executionTimeline.js +3 -0
- package/dist/server/lib/executionTimeline.js.map +1 -1
- package/dist/server/lib/git.js +32 -1
- package/dist/server/lib/git.js.map +1 -1
- package/dist/server/lib/hostExecutionEnvironment.js +47 -1
- package/dist/server/lib/hostExecutionEnvironment.js.map +1 -1
- package/dist/server/lib/lightweightPrompt.js +1 -0
- package/dist/server/lib/lightweightPrompt.js.map +1 -1
- package/dist/server/lib/mobileAccess.js +2 -2
- package/dist/server/lib/mobileAccess.js.map +1 -1
- package/dist/server/lib/models.js +11 -0
- package/dist/server/lib/models.js.map +1 -1
- package/dist/server/lib/opencodeErrors.js +31 -3
- package/dist/server/lib/opencodeErrors.js.map +1 -1
- package/dist/server/lib/opencodeExecutionReliability.js +52 -0
- package/dist/server/lib/opencodeExecutionReliability.js.map +1 -0
- package/dist/server/lib/opencodeSessionOperations.js +210 -20
- package/dist/server/lib/opencodeSessionOperations.js.map +1 -1
- package/dist/server/lib/opencodeTaskSessions.js +7 -12
- package/dist/server/lib/opencodeTaskSessions.js.map +1 -1
- package/dist/server/lib/postBuildChecks.js +2 -1
- package/dist/server/lib/postBuildChecks.js.map +1 -1
- package/dist/server/lib/projectAutoConfig.js +1 -0
- package/dist/server/lib/projectAutoConfig.js.map +1 -1
- package/dist/server/lib/projects.js +10 -0
- package/dist/server/lib/projects.js.map +1 -1
- package/dist/server/lib/specArtifact.js +20 -1
- package/dist/server/lib/specArtifact.js.map +1 -1
- package/dist/server/lib/specBundleGroups.js +151 -0
- package/dist/server/lib/specBundleGroups.js.map +1 -0
- package/dist/server/lib/specDraft.js +1 -5
- package/dist/server/lib/specDraft.js.map +1 -1
- package/dist/server/lib/specExport.js +2 -6
- package/dist/server/lib/specExport.js.map +1 -1
- package/dist/server/lib/specFormatting.js +13 -0
- package/dist/server/lib/specFormatting.js.map +1 -1
- package/dist/server/lib/specGraphFeature.js +3 -0
- package/dist/server/lib/specGraphFeature.js.map +1 -0
- package/dist/server/lib/specRepositoryEvidenceFormatting.js +2 -1
- package/dist/server/lib/specRepositoryEvidenceFormatting.js.map +1 -1
- package/dist/server/lib/specRepositoryImpact.js +4 -0
- package/dist/server/lib/specRepositoryImpact.js.map +1 -1
- package/dist/server/lib/specReviewContext.js +6 -20
- package/dist/server/lib/specReviewContext.js.map +1 -1
- package/dist/server/lib/specReviewValidation.js +22 -1
- package/dist/server/lib/specReviewValidation.js.map +1 -1
- package/dist/server/lib/specReviews.js +1 -1
- package/dist/server/lib/specSections.js +8 -1
- package/dist/server/lib/specSections.js.map +1 -1
- package/dist/server/lib/specSnapshotEvidence.js +4 -0
- package/dist/server/lib/specSnapshotEvidence.js.map +1 -1
- package/dist/server/lib/specTicketMaterialization.js +122 -0
- package/dist/server/lib/specTicketMaterialization.js.map +1 -0
- package/dist/server/lib/specs.js +27 -5
- package/dist/server/lib/specs.js.map +1 -1
- package/dist/server/lib/ticketFollowUpOperations.js +8 -1
- package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
- package/dist/server/lib/ticketRunOperations.js +0 -3
- package/dist/server/lib/ticketRunOperations.js.map +1 -1
- package/dist/server/lib/types.js +1 -0
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/lib/workspaceIdentity.js +3 -0
- package/dist/server/lib/workspaceIdentity.js.map +1 -1
- package/dist/server/workers/build.js +114 -8
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/followUp.js +143 -7
- package/dist/server/workers/followUp.js.map +1 -1
- package/dist/server/workers/plan.js +57 -24
- package/dist/server/workers/plan.js.map +1 -1
- package/dist/server/workers/review.js +43 -23
- package/dist/server/workers/review.js.map +1 -1
- package/dist/server/workers/specReview.js +7 -2
- package/dist/server/workers/specReview.js.map +1 -1
- package/dist/server/workers/specSession.js +109 -153
- package/dist/server/workers/specSession.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/ActivityView-DYDYyqIN.js +0 -1
- package/dist/client/assets/GitHubActionsDialog-jhi4GOyV.js +0 -1
- package/dist/client/assets/RepositoryGraphDialog-BZV0vHu6.js +0 -1
- package/dist/client/assets/VerificationDialog-Sc6e8AKH.js +0 -4
- package/dist/client/assets/architecture-7EHR7CIX-Dm8H7N6Z.js +0 -1
- package/dist/client/assets/channel-D1kOpezG.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-CtbsU1Bj.js +0 -1
- package/dist/client/assets/chunk-WU5MYG2G-DOOw2vq7.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-C253nwny.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DFgDA23g.js +0 -1
- package/dist/client/assets/eventmodeling-FCH6USID-BWhw0UJ8.js +0 -1
- package/dist/client/assets/gitGraph-WXDBUCRP-BSnxAa1J.js +0 -1
- package/dist/client/assets/index-B1gdJKwK.js +0 -275
- package/dist/client/assets/index-CCQwWUKF.css +0 -2
- package/dist/client/assets/info-J43DQDTF-DcFwF1-h.js +0 -1
- package/dist/client/assets/packet-YPE3B663-1VZiO_9r.js +0 -1
- package/dist/client/assets/pie-LRSECV5Y-BX1-tQCu.js +0 -1
- package/dist/client/assets/radar-GUYGQ44K-B2HRrCR4.js +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-BKQG8NCn.js +0 -1
- package/dist/client/assets/treeView-BLDUP644-CDfUVbUi.js +0 -1
- package/dist/client/assets/treemap-LRROVOQU-DUWqu8sK.js +0 -1
- package/dist/client/assets/wardley-L42UT6IY-BEFuPUCy.js +0 -1
- /package/dist/client/assets/{array-B2f2amhX.js → array-BNor45A1.js} +0 -0
- /package/dist/client/assets/{chunk-NNHCCRGN-DgKrp8T-.js → chunk-NNHCCRGN-CZB-V-Gv.js} +0 -0
- /package/dist/client/assets/{cytoscape.esm-BInZCgaJ.js → cytoscape.esm-B2lJcMSI.js} +0 -0
- /package/dist/client/assets/{defaultLocale-sPXJ5urm.js → defaultLocale-DPzUsThw.js} +0 -0
- /package/dist/client/assets/{dist-DfHDMDTt.js → dist-CERhmQhR.js} +0 -0
- /package/dist/client/assets/{graphlib-DacNv4Jd.js → graphlib-BHOW-eWz.js} +0 -0
- /package/dist/client/assets/{init-BVCnG1lj.js → init-C0L3woqb.js} +0 -0
- /package/dist/client/assets/{katex-BlkrXOwm.js → katex-CpjQsUQe.js} +0 -0
- /package/dist/client/assets/{path-Bw5AvBNC.js → path-sMK4d_s9.js} +0 -0
- /package/dist/client/assets/{rough.esm-DeLgKbOI.js → rough.esm-BoTisKeL.js} +0 -0
- /package/dist/client/assets/{src-CFGsdLiG.js → src-BRjoYtUW.js} +0 -0
package/dist/server/index.js
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
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
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
4261
|
+
for (const ticket of listBoardBundleTickets(result.project.id, bundle.id)) {
|
|
4206
4262
|
io.emit('ticket:updated', ticket);
|
|
4207
4263
|
}
|
|
4208
|
-
return res.json(
|
|
4264
|
+
return res.json({
|
|
4265
|
+
kind: accepted.kind,
|
|
4266
|
+
batch_id: accepted.batchId,
|
|
4267
|
+
target_ticket_id: null,
|
|
4268
|
+
});
|
|
4209
4269
|
}
|
|
4210
|
-
const ticketsBeforeReview =
|
|
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(
|
|
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 =
|
|
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(
|
|
4260
|
-
|
|
4261
|
-
|
|
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
|
|
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(
|
|
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
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
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
|
|
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();
|