@straiffi/archon 1.8.5 → 1.8.7

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 (185) hide show
  1. package/dist/client/assets/ActivityView-D4Qh96zr.js +1 -0
  2. package/dist/client/assets/GitHubActionsDialog-Bg03OmVv.js +1 -0
  3. package/dist/client/assets/RepositoryGraphDialog-CS_hOqPw.js +1 -0
  4. package/dist/client/assets/VerificationDialog-BYH-Ek8n.js +4 -0
  5. package/dist/client/assets/{arc-D2Nn9xIj.js → arc-C83vRtlz.js} +1 -1
  6. package/dist/client/assets/architecture-7EHR7CIX-Dm8H7N6Z.js +1 -0
  7. package/dist/client/assets/{architectureDiagram-3BPJPVTR-BB0biSU2.js → architectureDiagram-3BPJPVTR-2lxabjSl.js} +1 -1
  8. package/dist/client/assets/{blockDiagram-GPEHLZMM-Bxm9GAiX.js → blockDiagram-GPEHLZMM-C80HvJmb.js} +1 -1
  9. package/dist/client/assets/{c4Diagram-AAUBKEIU-CC3YHLX3.js → c4Diagram-AAUBKEIU-BM3k_lKz.js} +1 -1
  10. package/dist/client/assets/channel-HjENOCZ0.js +1 -0
  11. package/dist/client/assets/{chunk-2J33WTMH-ComBHKwP.js → chunk-2J33WTMH-BTk3lX07.js} +1 -1
  12. package/dist/client/assets/{chunk-3OPIFGDE-DSpFzCXF.js → chunk-3OPIFGDE-DAxdBZ_4.js} +1 -1
  13. package/dist/client/assets/{chunk-4BX2VUAB-CtLS8D71.js → chunk-4BX2VUAB-C5pU9ApX.js} +1 -1
  14. package/dist/client/assets/{chunk-4EGX6M5U-Btnm0QNe.js → chunk-4EGX6M5U-CAjWPjND.js} +1 -1
  15. package/dist/client/assets/{chunk-55IACEB6-74CcJaub.js → chunk-55IACEB6-DhO4-AG4.js} +1 -1
  16. package/dist/client/assets/{chunk-5DO6E6H7-WLZ8L4ko.js → chunk-5DO6E6H7-BDKA-zHS.js} +1 -1
  17. package/dist/client/assets/{chunk-5ZQYHXKU-pL2M3Ax3.js → chunk-5ZQYHXKU-BYm9s62a.js} +1 -1
  18. package/dist/client/assets/{chunk-727SXJPM-BPi_lguN.js → chunk-727SXJPM-iVUM8xuV.js} +1 -1
  19. package/dist/client/assets/{chunk-AQP2D5EJ-Coc6laVv.js → chunk-AQP2D5EJ-DVM7riMJ.js} +1 -1
  20. package/dist/client/assets/{chunk-BR22UD5L-Cou5beGe.js → chunk-BR22UD5L-12D2GWh4.js} +1 -1
  21. package/dist/client/assets/{chunk-BSJP7CBP-DJ57XcV5.js → chunk-BSJP7CBP-DMi77e84.js} +1 -1
  22. package/dist/client/assets/{chunk-CSCIHK7Q-CpaX09-x.js → chunk-CSCIHK7Q-_D1FzP9B.js} +2 -2
  23. package/dist/client/assets/{chunk-FHYWG6QK-Ba10e2kj.js → chunk-FHYWG6QK-BhSajKiB.js} +1 -1
  24. package/dist/client/assets/{chunk-FMBD7UC4-CEo2wZMx.js → chunk-FMBD7UC4-Drmlc0wM.js} +1 -1
  25. package/dist/client/assets/{chunk-KSCS5N6A-CLzz2KFY.js → chunk-KSCS5N6A-D3XouAHf.js} +1 -1
  26. package/dist/client/assets/{chunk-L5ZTLDWV-DyyDuDZm.js → chunk-L5ZTLDWV-B7NYWgT4.js} +1 -1
  27. package/dist/client/assets/{chunk-LZXEDZCA-Cm5npwZA.js → chunk-LZXEDZCA-Dgkkbb6A.js} +2 -2
  28. package/dist/client/assets/{chunk-MPE355IW-MqEt-J8G.js → chunk-MPE355IW-Cw8YmjTC.js} +1 -1
  29. package/dist/client/assets/{chunk-MZUSXYTE-DdNi9lhx.js → chunk-MZUSXYTE-jvxRCZ7x.js} +1 -1
  30. package/dist/client/assets/{chunk-N66VUXT2-CjemTW4E.js → chunk-N66VUXT2-00i4y0yD.js} +1 -1
  31. package/dist/client/assets/{chunk-ND2GUHAM-CaopONUA.js → chunk-ND2GUHAM-CzO1oVCi.js} +1 -1
  32. package/dist/client/assets/{chunk-NZK2D7GU-DIzt4PM_.js → chunk-NZK2D7GU-re0VVZne.js} +1 -1
  33. package/dist/client/assets/{chunk-O5CBEL6O-C7Re_6FB.js → chunk-O5CBEL6O-BwsS59iy.js} +1 -1
  34. package/dist/client/assets/{chunk-PUPMXCY4-ZvwTw0To.js → chunk-PUPMXCY4-DfWourL7.js} +1 -1
  35. package/dist/client/assets/chunk-QZHKN3VN-CtbsU1Bj.js +1 -0
  36. package/dist/client/assets/{chunk-UIBZB4QT-BTY9be9s.js → chunk-UIBZB4QT-v-a5ZfN6.js} +1 -1
  37. package/dist/client/assets/{chunk-WCWK7LTN-Db1n3n3-.js → chunk-WCWK7LTN-CtYzhvvb.js} +1 -1
  38. package/dist/client/assets/chunk-WU5MYG2G-CLyh-xCA.js +1 -0
  39. package/dist/client/assets/{chunk-XPW4576I-DObFPxjB.js → chunk-XPW4576I-CvnAuXH2.js} +1 -1
  40. package/dist/client/assets/classDiagram-4FO5ZUOK-DnhdaVrK.js +1 -0
  41. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C-BjeSGJ.js +1 -0
  42. package/dist/client/assets/{cose-bilkent-S5V4N54A-MlOPiG6P.js → cose-bilkent-S5V4N54A-fchD-dH2.js} +1 -1
  43. package/dist/client/assets/{dagre-BM42HDAG-BdFEW6fG.js → dagre-BM42HDAG-x71fYlqQ.js} +1 -1
  44. package/dist/client/assets/{dagre-BWNHuDdf.js → dagre-DSrzm-Gq.js} +1 -1
  45. package/dist/client/assets/{diagram-2AECGRRQ-D2ZuWfhH.js → diagram-2AECGRRQ-CMdwzuYj.js} +1 -1
  46. package/dist/client/assets/{diagram-5GNKFQAL-Cs_AmUDw.js → diagram-5GNKFQAL-B3l6I4qJ.js} +1 -1
  47. package/dist/client/assets/{diagram-KO2AKTUF-DICE0UrL.js → diagram-KO2AKTUF-BNhypLBW.js} +1 -1
  48. package/dist/client/assets/{diagram-LMA3HP47-MwtTXZWl.js → diagram-LMA3HP47-CmrhbiDt.js} +1 -1
  49. package/dist/client/assets/{diagram-OG6HWLK6-CxDJ75F5.js → diagram-OG6HWLK6-CRobDMLl.js} +1 -1
  50. package/dist/client/assets/{erDiagram-TEJ5UH35-XgZtP-BK.js → erDiagram-TEJ5UH35-CqO7K0TS.js} +1 -1
  51. package/dist/client/assets/eventmodeling-FCH6USID-BWhw0UJ8.js +1 -0
  52. package/dist/client/assets/{flowDiagram-I6XJVG4X-B8uIExT5.js → flowDiagram-I6XJVG4X-CuLTJZU0.js} +1 -1
  53. package/dist/client/assets/{ganttDiagram-6RSMTGT7-B6TrSB4S.js → ganttDiagram-6RSMTGT7-Bm7v1eRG.js} +1 -1
  54. package/dist/client/assets/gitGraph-WXDBUCRP-BSnxAa1J.js +1 -0
  55. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-qfMWSncV.js → gitGraphDiagram-PVQCEYII-CNHZr-5i.js} +1 -1
  56. package/dist/client/assets/index-Bs5SQZhz.css +2 -0
  57. package/dist/client/assets/index-LGNsdNYM.js +274 -0
  58. package/dist/client/assets/info-J43DQDTF-DcFwF1-h.js +1 -0
  59. package/dist/client/assets/{infoDiagram-5YYISTIA-CuOimNjJ.js → infoDiagram-5YYISTIA-z27pUr2X.js} +1 -1
  60. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-BWHbLru4.js → ishikawaDiagram-YF4QCWOH-CDocZ0jf.js} +1 -1
  61. package/dist/client/assets/{journeyDiagram-JHISSGLW-SAbFsYxI.js → journeyDiagram-JHISSGLW-CgP31lsU.js} +1 -1
  62. package/dist/client/assets/{kanban-definition-UN3LZRKU-m4ZsWr_S.js → kanban-definition-UN3LZRKU-DxTm1_fc.js} +1 -1
  63. package/dist/client/assets/{line-C4dSESbS.js → line-hrZ7m44_.js} +1 -1
  64. package/dist/client/assets/{linear-DT4rSZvy.js → linear-BOwW57yX.js} +1 -1
  65. package/dist/client/assets/{mermaid-parser.core-CstDlNL1.js → mermaid-parser.core-BThJAIK-.js} +2 -2
  66. package/dist/client/assets/{mermaid.core-B-Yj5Lxm.js → mermaid.core-CfVyP_kK.js} +3 -3
  67. package/dist/client/assets/{mindmap-definition-RKZ34NQL-Bzf9o0Md.js → mindmap-definition-RKZ34NQL-CuISnLgW.js} +1 -1
  68. package/dist/client/assets/{ordinal-k--hYEme.js → ordinal-CZ33lFpK.js} +1 -1
  69. package/dist/client/assets/packet-YPE3B663-1VZiO_9r.js +1 -0
  70. package/dist/client/assets/pie-LRSECV5Y-BX1-tQCu.js +1 -0
  71. package/dist/client/assets/{pieDiagram-4H26LBE5-C8c0F0hh.js → pieDiagram-4H26LBE5-DnWAdd44.js} +1 -1
  72. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BewK5Lws.js → quadrantDiagram-W4KKPZXB-Cb-RVl5A.js} +1 -1
  73. package/dist/client/assets/radar-GUYGQ44K-B2HRrCR4.js +1 -0
  74. package/dist/client/assets/{requirementDiagram-4Y6WPE33-C_gYL5ls.js → requirementDiagram-4Y6WPE33-DrXg_gCS.js} +1 -1
  75. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-Dt8OrhUl.js → sankeyDiagram-5OEKKPKP-DzZjp_ZP.js} +1 -1
  76. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-Z578DkVy.js → sequenceDiagram-3UESZ5HK-CQJ3PhQD.js} +1 -1
  77. package/dist/client/assets/{stateDiagram-AJRCARHV-CyQ5eQTE.js → stateDiagram-AJRCARHV-B16j9pg1.js} +1 -1
  78. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-vNiFfHwm.js +1 -0
  79. package/dist/client/assets/{timeline-definition-PNZ67QCA-DMtbr-l6.js → timeline-definition-PNZ67QCA-bUG3mZQt.js} +1 -1
  80. package/dist/client/assets/treeView-BLDUP644-CDfUVbUi.js +1 -0
  81. package/dist/client/assets/treemap-LRROVOQU-DUWqu8sK.js +1 -0
  82. package/dist/client/assets/{vennDiagram-CIIHVFJN-BToePHO4.js → vennDiagram-CIIHVFJN-DALCJcZD.js} +1 -1
  83. package/dist/client/assets/wardley-L42UT6IY-BEFuPUCy.js +1 -0
  84. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-FAzbTjvI.js → wardleyDiagram-YWT4CUSO-DPQd3l9A.js} +1 -1
  85. package/dist/client/assets/{xychartDiagram-2RQKCTM6-BrlUCOgp.js → xychartDiagram-2RQKCTM6-BIv1FqXG.js} +1 -1
  86. package/dist/client/index.html +2 -2
  87. package/dist/server/db.js +399 -0
  88. package/dist/server/db.js.map +1 -1
  89. package/dist/server/index.js +183 -20
  90. package/dist/server/index.js.map +1 -1
  91. package/dist/server/lib/agent.js +9 -6
  92. package/dist/server/lib/agent.js.map +1 -1
  93. package/dist/server/lib/automationResumeDecision.js +6 -0
  94. package/dist/server/lib/automationResumeDecision.js.map +1 -1
  95. package/dist/server/lib/bundleReviewOperations.js +81 -2
  96. package/dist/server/lib/bundleReviewOperations.js.map +1 -1
  97. package/dist/server/lib/checkWorkspaceIdentity.js +2 -206
  98. package/dist/server/lib/checkWorkspaceIdentity.js.map +1 -1
  99. package/dist/server/lib/executionReconciliation.js +73 -0
  100. package/dist/server/lib/executionReconciliation.js.map +1 -1
  101. package/dist/server/lib/figmaResources.js +15 -1
  102. package/dist/server/lib/figmaResources.js.map +1 -1
  103. package/dist/server/lib/git.js +312 -32
  104. package/dist/server/lib/git.js.map +1 -1
  105. package/dist/server/lib/integrations/github.js +10 -1
  106. package/dist/server/lib/integrations/github.js.map +1 -1
  107. package/dist/server/lib/postBuildChecks.js +20 -12
  108. package/dist/server/lib/postBuildChecks.js.map +1 -1
  109. package/dist/server/lib/repositoryGraphAnalyzer.js +392 -0
  110. package/dist/server/lib/repositoryGraphAnalyzer.js.map +1 -0
  111. package/dist/server/lib/repositoryGraphGitHistory.js +371 -0
  112. package/dist/server/lib/repositoryGraphGitHistory.js.map +1 -0
  113. package/dist/server/lib/repositoryGraphIdentity.js +134 -0
  114. package/dist/server/lib/repositoryGraphIdentity.js.map +1 -0
  115. package/dist/server/lib/repositoryGraphManifest.js +386 -0
  116. package/dist/server/lib/repositoryGraphManifest.js.map +1 -0
  117. package/dist/server/lib/repositoryGraphQueries.js +370 -0
  118. package/dist/server/lib/repositoryGraphQueries.js.map +1 -0
  119. package/dist/server/lib/repositoryGraphRetention.js +104 -0
  120. package/dist/server/lib/repositoryGraphRetention.js.map +1 -0
  121. package/dist/server/lib/repositoryGraphRoutes.js +145 -0
  122. package/dist/server/lib/repositoryGraphRoutes.js.map +1 -0
  123. package/dist/server/lib/repositoryGraphScan.js +370 -0
  124. package/dist/server/lib/repositoryGraphScan.js.map +1 -0
  125. package/dist/server/lib/repositoryGraphStore.js +352 -0
  126. package/dist/server/lib/repositoryGraphStore.js.map +1 -0
  127. package/dist/server/lib/repositoryGraphTargets.js +30 -0
  128. package/dist/server/lib/repositoryGraphTargets.js.map +1 -0
  129. package/dist/server/lib/repositoryGraphTypeScript.js +288 -0
  130. package/dist/server/lib/repositoryGraphTypeScript.js.map +1 -0
  131. package/dist/server/lib/reviewFindings.js +31 -5
  132. package/dist/server/lib/reviewFindings.js.map +1 -1
  133. package/dist/server/lib/specArtifact.js +5 -1
  134. package/dist/server/lib/specArtifact.js.map +1 -1
  135. package/dist/server/lib/terminal.js +25 -1
  136. package/dist/server/lib/terminal.js.map +1 -1
  137. package/dist/server/lib/types.js +1 -0
  138. package/dist/server/lib/types.js.map +1 -1
  139. package/dist/server/lib/workspaceIdentity.js +433 -0
  140. package/dist/server/lib/workspaceIdentity.js.map +1 -0
  141. package/dist/server/workers/build.js +2 -2
  142. package/dist/server/workers/build.js.map +1 -1
  143. package/dist/server/workers/followUp.js +1 -1
  144. package/dist/server/workers/followUp.js.map +1 -1
  145. package/dist/server/workers/plan.js +9 -7
  146. package/dist/server/workers/plan.js.map +1 -1
  147. package/dist/server/workers/repositoryGraphAnalyzer.js +282 -0
  148. package/dist/server/workers/repositoryGraphAnalyzer.js.map +1 -0
  149. package/dist/server/workers/review.js +72 -6
  150. package/dist/server/workers/review.js.map +1 -1
  151. package/dist/server/workers/specSession.js +4 -1
  152. package/dist/server/workers/specSession.js.map +1 -1
  153. package/package.json +2 -1
  154. package/dist/client/assets/ActivityView-DGP4Juye.js +0 -1
  155. package/dist/client/assets/GitHubActionsDialog-P_mpYAOO.js +0 -1
  156. package/dist/client/assets/VerificationDialog-C6FVSzcF.js +0 -4
  157. package/dist/client/assets/architecture-7EHR7CIX-C-4Cp4ml.js +0 -1
  158. package/dist/client/assets/channel-CQOfjP3q.js +0 -1
  159. package/dist/client/assets/chunk-QZHKN3VN-LI_RZca2.js +0 -1
  160. package/dist/client/assets/chunk-WU5MYG2G-D5lmGfNl.js +0 -1
  161. package/dist/client/assets/classDiagram-4FO5ZUOK-DGUeerOX.js +0 -1
  162. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Cnum-Tdt.js +0 -1
  163. package/dist/client/assets/eventmodeling-FCH6USID-Dqb6QKoI.js +0 -1
  164. package/dist/client/assets/gitGraph-WXDBUCRP-DYEsqh93.js +0 -1
  165. package/dist/client/assets/index-CzRhzdmk.js +0 -274
  166. package/dist/client/assets/index-DZqqZx53.css +0 -2
  167. package/dist/client/assets/info-J43DQDTF-CfjXFZai.js +0 -1
  168. package/dist/client/assets/packet-YPE3B663-Dv0HkRHU.js +0 -1
  169. package/dist/client/assets/pie-LRSECV5Y-S5zPzZFN.js +0 -1
  170. package/dist/client/assets/radar-GUYGQ44K-B7psLv22.js +0 -1
  171. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-C9e0OccX.js +0 -1
  172. package/dist/client/assets/treeView-BLDUP644-B8H0kT67.js +0 -1
  173. package/dist/client/assets/treemap-LRROVOQU-DPLhFHnh.js +0 -1
  174. package/dist/client/assets/wardley-L42UT6IY-B5-Vb08V.js +0 -1
  175. /package/dist/client/assets/{array-BNor45A1.js → array-B2f2amhX.js} +0 -0
  176. /package/dist/client/assets/{chunk-NNHCCRGN-CZB-V-Gv.js → chunk-NNHCCRGN-DgKrp8T-.js} +0 -0
  177. /package/dist/client/assets/{cytoscape.esm-B2lJcMSI.js → cytoscape.esm-BInZCgaJ.js} +0 -0
  178. /package/dist/client/assets/{defaultLocale-DPzUsThw.js → defaultLocale-sPXJ5urm.js} +0 -0
  179. /package/dist/client/assets/{dist-CERhmQhR.js → dist-DfHDMDTt.js} +0 -0
  180. /package/dist/client/assets/{graphlib-BHOW-eWz.js → graphlib-DacNv4Jd.js} +0 -0
  181. /package/dist/client/assets/{init-C0L3woqb.js → init-BVCnG1lj.js} +0 -0
  182. /package/dist/client/assets/{katex-CpjQsUQe.js → katex-BlkrXOwm.js} +0 -0
  183. /package/dist/client/assets/{path-sMK4d_s9.js → path-Bw5AvBNC.js} +0 -0
  184. /package/dist/client/assets/{rough.esm-BoTisKeL.js → rough.esm-DeLgKbOI.js} +0 -0
  185. /package/dist/client/assets/{src-BRjoYtUW.js → src-CFGsdLiG.js} +0 -0
@@ -8,6 +8,8 @@ import { createHash, randomUUID } from 'crypto';
8
8
  import cors from 'cors';
9
9
  import { adjectives, animals, uniqueNamesGenerator } from 'unique-names-generator';
10
10
  import db from './db.js';
11
+ import { pruneAllRepositoryGraphScans } from './lib/repositoryGraphRetention.js';
12
+ import { registerRepositoryGraphRoutes } from './lib/repositoryGraphRoutes.js';
11
13
  import { deleteChatSession, getChatSession, listChatSessions } from './lib/chats.js';
12
14
  import { deleteSpecSession, getCreatedTicketIdsForSnapshot, getSpecSession, getSpecSnapshot, listSpecSessions } from './lib/specs.js';
13
15
  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';
@@ -19,7 +21,7 @@ import { resolveSessionTargetForExecution } from './lib/sessionTargets.js';
19
21
  import { createChatMessage, getChatMessage, updateChatMessageContent } from './lib/chatMessages.js';
20
22
  import { attachChatTicketProposalsToMessageContent } from './lib/chatTicketProposals.js';
21
23
  import { createCorsOriginResolver, parseCorsOrigins } from './lib/cors.js';
22
- import { abortGitOperation, branchExistsLocally, commitGitChanges, createWorktreeAsync, deleteWorktree, getBundleReviewDiffForCwd, getGitDiffData, getGitDiffFiles, getGitStatus, getGitUnifiedDiff, getLocalProjectBranch, getProjectBranch, getProjectBranchSuggestions, getSelectedGitUnifiedDiff, getUnpushedCommitDiffForCwd, hasKnownBranchRef, listUnpushedCommitsForCwd, pullGitBranch, pushCurrentBranch, rebaseGitBranchOntoBase, resolveExistingWorktreePath, resolveWorktreePath, summarizeTicketDiffFiles, switchProjectBranch, syncWorktreeFilesAsync, undoLatestUnpushedCommitForCwd, UnpushedCommitDiffSelectionError } from './lib/git.js';
24
+ import { abortGitOperation, branchExistsLocally, commitGitChanges, createWorktreeAsync, deleteWorktree, getBundleReviewDiffForCwd, getGitDiffData, getGitDiffFiles, getGitStatus, getGitUnifiedDiff, getLocalProjectBranch, getProjectBranch, getProjectBranchSuggestions, getSelectedGitUnifiedDiff, getUnpushedCommitDiffForCwd, getUnpushedCommitSummaryForCwd, hasKnownBranchRef, listUnpushedCommitsForCwd, pullGitBranch, pushCurrentBranch, rebaseGitBranchOntoBase, resolveExistingWorktreePath, resolveWorktreePath, squashUnpushedCommitsForCwd, summarizeTicketDiffFiles, switchProjectBranch, syncWorktreeFilesAsync, undoLatestUnpushedCommitForCwd, UnpushedCommitDiffSelectionError } from './lib/git.js';
23
25
  import config from './lib/config.js';
24
26
  import { autoConfigProject, ProjectAutoConfigError } from './lib/projectAutoConfig.js';
25
27
  import { analyzeRepoPath, createInitialCommit, ensureInitialCommitForWorktrees, initializeGitRepo, isInitialCommitRequiredError, } from './lib/projectRepos.js';
@@ -70,7 +72,7 @@ import { ExecutionArtifactCleanupError, reconcileExecutionArtifactRegistrationIn
70
72
  import { closeHttpServer, shutdownRealtimeServer } from './lib/shutdown.js';
71
73
  import { resolveClientBuildPaths, shouldServeClientApp, STATIC_CLIENT_DIRECTORY_OPTIONS, STATIC_CLIENT_INDEX_OPTIONS, } from './lib/staticClient.js';
72
74
  import { deleteIntegrationConnection, getGitHubConnectionConfig, getJiraConnectionConfig, listIntegrationConnections, upsertIntegrationConnection, } from './lib/integrations/index.js';
73
- import { createGitHubPullRequest, createOrFindGitHubPullRequest, findOpenGitHubPullRequest, findOpenGitHubPullRequestByHeadBranch, getGitHubPullRequestComments, getGitHubPullRequestReviews, getGitHubPullRequest, GitHubApiError, hasGitHubRemoteBranch, resolveGitHubRepository, validateGitHubConnection, } from './lib/integrations/github.js';
75
+ import { createGitHubPullRequest, createOrFindGitHubPullRequest, findOpenGitHubPullRequest, findOpenGitHubPullRequestByHeadBranch, getGitHubPullRequestComments, getGitHubPullRequestReviews, getGitHubPullRequest, GitHubApiError, hasGitHubRemoteBranch, hasGitHubRemoteBranchAsync, resolveGitHubRepository, validateGitHubConnection, } from './lib/integrations/github.js';
74
76
  import { importJiraIssue, JiraApiError, prepareJiraIssueImport, validateJiraConnection } from './lib/integrations/jira.js';
75
77
  import { importGitHubIssue, prepareGitHubIssueImport } from './lib/integrations/github-issues.js';
76
78
  import { buildImportedIssueSessionTitle, importProviderHostedIssueImages } from './lib/integrations/importedIssueImages.js';
@@ -91,6 +93,7 @@ import { getCheckAttemptDiagnosticResponse, getCheckBatchDiagnosticResponse } fr
91
93
  import { getCheckDefinitionFingerprint } from './lib/checkDefinitions.js';
92
94
  import { getCheckGateEvaluation, hydrateCheckGatePresentApplicability } from './lib/checkGateEvaluations.js';
93
95
  import { captureCheckWorkspaceIdentity } from './lib/checkWorkspaceIdentity.js';
96
+ import { hasActiveBundleRepositoryGraphScan, hasActiveProjectRepositoryGraphScan } from './lib/repositoryGraphStore.js';
94
97
  import { resolveEffectiveRequiredCheckPolicyMembership, resolveRequiredCheckPolicy } from './lib/requiredCheckPolicy.js';
95
98
  import { getBundleBuildBlockerResponse, shouldStartBundleBuildNow, transitionTicketState, } from './lib/ticketWorkflowOperations.js';
96
99
  import { submitPlanTicketFollowUp, submitTicketFollowUp, } from './lib/ticketFollowUpOperations.js';
@@ -98,7 +101,8 @@ import { closePendingTicketPlanQuestionSet, listPendingTicketPlanQuestionSetMess
98
101
  import { hasPendingAskQuestionSet } from './lib/planQuestions.js';
99
102
  import { canUseBuildControls, formatActiveRunConflict, getTicketRunReadinessError, resumeBuildTicketRun, runProjectTarget, runTicketRun, stopBuildTicketRun, stopReviewTicketRun, stopProjectTargetRun, stopTicketRun, } from './lib/ticketRunOperations.js';
100
103
  import { isTicketAgentSettingsPayload, updateTicketAgentSettings, } from './lib/ticketSettingsOperations.js';
101
- import { rerunTicketReviewOperation, resolveBundleReviewOwner, transitionBundleToReview } from './lib/bundleReviewOperations.js';
104
+ import { getBundleReviewRecovery, recoverBundleReview, rerunTicketReviewOperation, resolveBundleReviewOwner, transitionBundleToReview } from './lib/bundleReviewOperations.js';
105
+ import { resolveReviewContinuation } from './workers/review.js';
102
106
  import { clearTicketStageSnapshots, getActiveBundleStageChangeHead, reconcileStageSnapshots, undoTicketStage } from './lib/ticketUndo.js';
103
107
  import { closeAllTerminalSessions, createProjectTerminalSession, createTerminalSessionForWorkspace, destroyTerminalSessionById, registerTerminalSocketHandlers, } from './lib/terminal.js';
104
108
  import { countBundleTickets, createTicketRecord, createBundle, deleteBundle, ensureProjectRootBundle, autoParkTicketIfStale, autoParkSettledBundleTicket, isBundleSettledForAutoPark, clearAutoParkDismissalIfNeeded, assignTicketDoneOrder, assignTicketLaneOrder, getBundle, getBundleByName, getBundleByBranch, getBundleRepresentativeTicketContext, isProjectRootBundle, getTicket, isBundledTicket, listTicketsInRunContext, listBundles, listBoardTicketEnrichment, listTickets, resolveTicketBranch, resolveTicketTool, updateBundleAutomationConfig, updateBundleIdentity, } from './lib/tickets.js';
@@ -1474,9 +1478,6 @@ const shouldDiscoverBundlePullRequestOnOpen = (project, bundle) => {
1474
1478
  if (tickets.some(ticket => ticket.agent_status === 'running')) {
1475
1479
  return false;
1476
1480
  }
1477
- if (!hasGitHubRemoteBranch(project.repo_path, bundle.branch)) {
1478
- return false;
1479
- }
1480
1481
  const key = getBundlePullRequestDiscoveryKey(project.id, bundle.id);
1481
1482
  if (bundlePullRequestDiscoveryInFlight.has(key)) {
1482
1483
  return false;
@@ -1490,6 +1491,9 @@ const startBundlePullRequestDiscoveryIfNeeded = (project, bundle) => {
1490
1491
  const key = getBundlePullRequestDiscoveryKey(project.id, bundle.id);
1491
1492
  const task = (async () => {
1492
1493
  try {
1494
+ if (!await hasGitHubRemoteBranchAsync(project.repo_path, bundle.branch)) {
1495
+ return;
1496
+ }
1493
1497
  const discoveredPullRequest = await discoverOpenBundlePullRequest(project, bundle);
1494
1498
  if (!discoveredPullRequest) {
1495
1499
  bundlePullRequestDiscoveryMissTimestamps.set(key, Date.now());
@@ -1497,7 +1501,7 @@ const startBundlePullRequestDiscoveryIfNeeded = (project, bundle) => {
1497
1501
  }
1498
1502
  bundlePullRequestDiscoveryMissTimestamps.delete(key);
1499
1503
  bundlePullRequestDiscoveryErrorTimestamps.delete(key);
1500
- reconcileBundleTicketsAfterPullRequestSync(project.id, bundle.id);
1504
+ emitBundlePullRequestUpdated(project.id, bundle.id);
1501
1505
  }
1502
1506
  catch (error) {
1503
1507
  bundlePullRequestDiscoveryErrorTimestamps.set(key, Date.now());
@@ -1586,9 +1590,10 @@ const startTrackedBundlePullRequestSyncIfNeeded = (project, bundle, options = {}
1586
1590
  const key = getBundlePullRequestDiscoveryKey(project.id, bundle.id);
1587
1591
  const task = (async () => {
1588
1592
  try {
1589
- await syncTrackedBundlePullRequestIfNeeded(project, bundle, { ...options, rethrow: true });
1593
+ const nextPullRequest = await syncTrackedBundlePullRequestIfNeeded(project, bundle, { ...options, rethrow: true });
1590
1594
  bundlePullRequestSyncErrorTimestamps.delete(key);
1591
- reconcileBundleTicketsAfterPullRequestSync(project.id, bundle.id);
1595
+ emitBundlePullRequestUpdated(project.id, bundle.id);
1596
+ scheduleBundleTicketReconciliationIfTerminal(project.id, bundle.id, nextPullRequest?.state ?? null);
1592
1597
  }
1593
1598
  catch (error) {
1594
1599
  bundlePullRequestSyncErrorTimestamps.set(key, Date.now());
@@ -1665,6 +1670,26 @@ const reconcileBundleTicketsAfterPullRequestSync = (projectId, bundleId) => {
1665
1670
  }
1666
1671
  }
1667
1672
  };
1673
+ const emitBundlePullRequestUpdated = (projectId, bundleId) => {
1674
+ io.emit('bundle-pull-request:updated', {
1675
+ project_id: projectId,
1676
+ bundle_id: bundleId,
1677
+ pull_request: serializeBundlePullRequest(getBundlePullRequestRecord(bundleId, projectId)),
1678
+ });
1679
+ };
1680
+ const scheduleBundleTicketReconciliationIfTerminal = (projectId, bundleId, nextState) => {
1681
+ if (nextState !== 'merged' && nextState !== 'closed') {
1682
+ return;
1683
+ }
1684
+ setImmediate(() => {
1685
+ try {
1686
+ reconcileBundleTicketsAfterPullRequestSync(projectId, bundleId);
1687
+ }
1688
+ catch (error) {
1689
+ console.warn(`[integrations] github pr ticket reconciliation failed project=${projectId} bundle=${bundleId}`, error);
1690
+ }
1691
+ });
1692
+ };
1668
1693
  const syncProjectBundlePullRequestsIfNeeded = async (project, bundles, options = {}) => {
1669
1694
  let startedCount = 0;
1670
1695
  for (const bundle of bundles) {
@@ -1738,6 +1763,9 @@ const serializeBundleDetails = (project, bundle, extras = {}) => {
1738
1763
  has_completed_review: bundleReviewState.has_completed_review,
1739
1764
  has_follow_up_since_last_review: bundleReviewState.has_follow_up_since_last_review,
1740
1765
  can_re_review: bundleReviewState.can_re_review,
1766
+ review_recovery_available: getBundleAutomationState(project.id, bundle.id)?.automation_paused_reason
1767
+ ? false
1768
+ : getBundleReviewRecovery(project.id, bundle.id) !== null,
1741
1769
  has_helper_model: Boolean(project.helper_model),
1742
1770
  recent_commit_subjects: getBundleRecentCommitSubjects(project, bundle),
1743
1771
  };
@@ -2422,6 +2450,7 @@ const emitRunStateForContext = (ticket, isRunningValue) => {
2422
2450
  }
2423
2451
  };
2424
2452
  app.use(express.json({ limit: '5mb' }));
2453
+ registerRepositoryGraphRoutes(app, { emitter: io });
2425
2454
  const requireDesktopMobileAccessRequest = (req, res) => {
2426
2455
  const rejectionReason = validateDesktopMobileAccessRequest(req);
2427
2456
  if (!rejectionReason) {
@@ -3103,13 +3132,17 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/create-ti
3103
3132
  }
3104
3133
  const target = targetResult.target;
3105
3134
  const bundleName = specSession.external_source?.external_key ?? '';
3106
- const bundle = bundleName
3107
- ? createAutoBundleForName(bundleName, project.id, target.branch)
3108
- : createAutoPlanningBundle(project.id, target.branch);
3135
+ const bundle = target.target_kind === 'bundle'
3136
+ ? target.target_bundle_id ? getBundle(target.target_bundle_id, project.id) : null
3137
+ : bundleName
3138
+ ? createAutoBundleForName(bundleName, project.id, target.branch)
3139
+ : createAutoPlanningBundle(project.id, target.branch);
3109
3140
  if (!bundle || isProjectRootBundle(bundle)) {
3110
3141
  throw new HttpError(409, 'Unable to create a bundle for this Spec snapshot.');
3111
3142
  }
3112
- generatedBundleId = bundle.id;
3143
+ if (target.target_kind === 'repo_root') {
3144
+ generatedBundleId = bundle.id;
3145
+ }
3113
3146
  const ticketsForMaterialization = snapshot.tickets.map(ticket => {
3114
3147
  const appendices = [
3115
3148
  buildVisualizationAppendix(ticket.relevant_visualizations ?? [], snapshot),
@@ -3412,7 +3445,8 @@ app.get('/tickets/:id/git-commits', (req, res) => {
3412
3445
  if ('error' in workspace) {
3413
3446
  return res.status(workspace.status).json({ error: workspace.error });
3414
3447
  }
3415
- return res.json({ commits: listUnpushedCommitsForCwd(workspace.cwd, workspace.branch, workspace.project) });
3448
+ const summary = getUnpushedCommitSummaryForCwd(workspace.cwd, workspace.branch, workspace.project);
3449
+ return res.json({ commits: summary.commits, total_count: summary.totalCount });
3416
3450
  });
3417
3451
  app.get('/bundles', async (req, res) => {
3418
3452
  const result = getRequiredProject(req);
@@ -3632,6 +3666,7 @@ app.post('/bundles/:id/pull-request', async (req, res) => {
3632
3666
  headBranch: bundle.branch,
3633
3667
  });
3634
3668
  upsertBundlePullRequestFromGitHub(result.project.id, bundle.id, githubConfig, nextPullRequest);
3669
+ emitBundlePullRequestUpdated(result.project.id, bundle.id);
3635
3670
  return res.json(serializeBundleDetails(result.project, bundle));
3636
3671
  }
3637
3672
  catch (error) {
@@ -3659,7 +3694,7 @@ app.post('/bundles/:id/pull-request/sync', async (req, res) => {
3659
3694
  if (!trackedPullRequest) {
3660
3695
  try {
3661
3696
  trackedPullRequest = await discoverOpenBundlePullRequest(result.project, bundle);
3662
- reconcileBundleTicketsAfterPullRequestSync(result.project.id, bundle.id);
3697
+ emitBundlePullRequestUpdated(result.project.id, bundle.id);
3663
3698
  return res.json(serializeBundleDetails(result.project, bundle));
3664
3699
  }
3665
3700
  catch (error) {
@@ -3672,8 +3707,9 @@ app.post('/bundles/:id/pull-request/sync', async (req, res) => {
3672
3707
  }
3673
3708
  try {
3674
3709
  const nextPullRequest = await getGitHubPullRequest(githubConfig, trackedPullRequest.number);
3675
- upsertBundlePullRequestFromGitHub(result.project.id, bundle.id, githubConfig, nextPullRequest);
3676
- reconcileBundleTicketsAfterPullRequestSync(result.project.id, bundle.id);
3710
+ const nextRecord = upsertBundlePullRequestFromGitHub(result.project.id, bundle.id, githubConfig, nextPullRequest);
3711
+ emitBundlePullRequestUpdated(result.project.id, bundle.id);
3712
+ scheduleBundleTicketReconciliationIfTerminal(result.project.id, bundle.id, nextRecord?.state ?? null);
3677
3713
  console.info(`[integrations] github pr sync completed project=${result.project.id} bundle=${bundle.id} pr=${trackedPullRequest.number}`);
3678
3714
  return res.json(serializeBundleDetails(result.project, bundle));
3679
3715
  }
@@ -3816,6 +3852,9 @@ app.delete('/bundles/:id', (req, res) => {
3816
3852
  if (hasActiveBundleSpecWork(result.project.id, bundle.id)) {
3817
3853
  return res.status(409).json({ error: 'Cannot delete a bundle while Spec work is active' });
3818
3854
  }
3855
+ if (hasActiveBundleRepositoryGraphScan(result.project.id, bundle.id)) {
3856
+ return res.status(409).json({ error: 'Cannot delete a bundle while a repository graph scan is active' });
3857
+ }
3819
3858
  if (countBundleTickets(bundle.id, result.project.id) > 0) {
3820
3859
  return res.status(409).json({ error: 'Cannot delete a bundle that is still used by tickets' });
3821
3860
  }
@@ -4011,6 +4050,23 @@ app.post('/bundles/:id/review', (req, res) => {
4011
4050
  }
4012
4051
  return res.json(reviewResult.details);
4013
4052
  });
4053
+ app.post('/bundles/:id/review/continue', (req, res) => {
4054
+ const result = getRequiredProject(req);
4055
+ if ('error' in result) {
4056
+ return res.status(400).json({ error: result.error });
4057
+ }
4058
+ const bundle = getBundle(req.params.id, result.project.id);
4059
+ if (!bundle) {
4060
+ return res.status(404).json({ error: 'Bundle not found' });
4061
+ }
4062
+ const recovered = recoverBundleReview(result.project.id, bundle.id, io);
4063
+ if (!recovered.ok) {
4064
+ return res.status(recovered.status).json({ error: recovered.error });
4065
+ }
4066
+ return res.status(recovered.status).json(serializeBundleDetails(result.project, bundle, {
4067
+ target_ticket_id: recovered.value?.id ?? null,
4068
+ }));
4069
+ });
4014
4070
  app.post('/bundles/:id/build-open-questions/resolve', async (req, res) => {
4015
4071
  const result = getRequiredProject(req);
4016
4072
  if ('error' in result) {
@@ -4698,6 +4754,24 @@ app.post('/bundles/:id/resume-automation', async (req, res) => {
4698
4754
  return res.status(409).json({ error: error instanceof Error ? error.message : String(error) });
4699
4755
  }
4700
4756
  }
4757
+ else if (decision.outcome === 'resume_review') {
4758
+ if (!revalidateDecision()) {
4759
+ return res.status(409).json({ error: 'Bundle automation state changed before Resume could start' });
4760
+ }
4761
+ const sourceRunId = bundleState.automation_paused_stage_run_id;
4762
+ const reviewResult = rerunTicketReviewOperation(owner, io, {
4763
+ automatic: true,
4764
+ initiation: {
4765
+ causalParentRunId: progressionRunId,
4766
+ retrySourceRunId: sourceRunId,
4767
+ },
4768
+ continuation: sourceRunId ? resolveReviewContinuation(sourceRunId) : undefined,
4769
+ accept: acceptResumedReview,
4770
+ });
4771
+ if (!reviewResult.ok) {
4772
+ return res.status(reviewResult.status).json({ error: reviewResult.error });
4773
+ }
4774
+ }
4701
4775
  else if (decision.outcome === 'rerun_review') {
4702
4776
  if (!revalidateDecision()) {
4703
4777
  return res.status(409).json({ error: 'Bundle automation state changed before Resume could start' });
@@ -6847,7 +6921,8 @@ app.get('/projects/:id/git-commits', (req, res) => {
6847
6921
  if ('error' in workspace) {
6848
6922
  return res.status(workspace.status).json({ error: workspace.error });
6849
6923
  }
6850
- return res.json({ commits: listUnpushedCommitsForCwd(workspace.cwd, workspace.branch, workspace.project) });
6924
+ const summary = getUnpushedCommitSummaryForCwd(workspace.cwd, workspace.branch, workspace.project);
6925
+ return res.json({ commits: summary.commits, total_count: summary.totalCount });
6851
6926
  });
6852
6927
  app.post('/projects/:id/git-commit', async (req, res) => {
6853
6928
  const project = getProjectById(req.params.id);
@@ -7059,10 +7134,39 @@ app.post('/projects/:id/git-undo-latest', async (req, res) => {
7059
7134
  catch (error) {
7060
7135
  return res.status(409).json({ error: getErrorMessage(error) || 'Unable to undo the latest local commit right now.' });
7061
7136
  }
7137
+ const summary = getUnpushedCommitSummaryForCwd(workspace.cwd, workspace.branch, workspace.project);
7062
7138
  return res.json({
7063
7139
  ticket: null,
7064
7140
  git_status: getGitStatus(workspace.cwd, workspace.branch, workspace.project),
7065
- commits: listUnpushedCommitsForCwd(workspace.cwd, workspace.branch, workspace.project),
7141
+ commits: summary.commits,
7142
+ total_count: summary.totalCount,
7143
+ });
7144
+ });
7145
+ app.post('/projects/:id/git-squash', async (req, res) => {
7146
+ const project = getProjectById(req.params.id);
7147
+ if (!project) {
7148
+ return res.status(404).json({ error: 'Not found' });
7149
+ }
7150
+ const workspace = resolveProjectTargetGitWorkspace(project);
7151
+ if ('error' in workspace) {
7152
+ return res.status(workspace.status).json({ error: workspace.error });
7153
+ }
7154
+ const message = typeof req.body?.message === 'string' ? req.body.message.trim() : '';
7155
+ if (!message) {
7156
+ return res.status(400).json({ error: 'message is required' });
7157
+ }
7158
+ try {
7159
+ await squashUnpushedCommitsForCwd(workspace.cwd, workspace.branch, workspace.project, message);
7160
+ }
7161
+ catch (error) {
7162
+ return res.status(409).json({ error: getErrorMessage(error) || 'Unable to squash local commits right now.' });
7163
+ }
7164
+ const summary = getUnpushedCommitSummaryForCwd(workspace.cwd, workspace.branch, workspace.project);
7165
+ return res.json({
7166
+ ticket: null,
7167
+ git_status: getGitStatus(workspace.cwd, workspace.branch, workspace.project),
7168
+ commits: summary.commits,
7169
+ total_count: summary.totalCount,
7066
7170
  });
7067
7171
  });
7068
7172
  app.patch('/projects/:id', (req, res) => {
@@ -7174,6 +7278,9 @@ const assertProjectDeletionEligible = (projectId, claimId) => {
7174
7278
  if (hasActiveProjectCheckBatch(projectId)) {
7175
7279
  throw new ProjectDeletionError(409, 'Cannot delete a project while checks are active');
7176
7280
  }
7281
+ if (!claimId && hasActiveProjectRepositoryGraphScan(projectId)) {
7282
+ throw new ProjectDeletionError(409, 'Cannot delete a project while a repository graph scan is active');
7283
+ }
7177
7284
  };
7178
7285
  const completeClaimedProjectDeletion = async (projectId, claimId) => {
7179
7286
  await runExclusiveExecutionArtifactMaintenance(() => reconcileProjectExecutionArtifacts(projectId, {
@@ -8032,11 +8139,45 @@ app.post('/tickets/:id/git-undo-latest', async (req, res) => {
8032
8139
  catch (error) {
8033
8140
  return res.status(409).json({ error: getErrorMessage(error) || 'Unable to undo the latest local commit right now.' });
8034
8141
  }
8142
+ const summary = getUnpushedCommitSummaryForCwd(workspace.cwd, workspace.branch, workspace.project);
8143
+ const updated = reconcileRunContextTickets(previousTickets, ticket.id);
8144
+ return res.json({
8145
+ ticket: updated,
8146
+ git_status: getGitStatus(workspace.cwd, workspace.branch, workspace.project),
8147
+ commits: summary.commits,
8148
+ total_count: summary.totalCount,
8149
+ });
8150
+ });
8151
+ app.post('/tickets/:id/git-squash', async (req, res) => {
8152
+ const ticket = getTicket(req.params.id);
8153
+ if (!ticket) {
8154
+ return res.status(404).json({ error: 'Not found' });
8155
+ }
8156
+ if (!matchesTicketProjectContext(ticket, req)) {
8157
+ return res.status(404).json({ error: 'Not found' });
8158
+ }
8159
+ const workspace = resolveTicketGitWorkspace(ticket);
8160
+ if ('error' in workspace) {
8161
+ return res.status(workspace.status).json({ error: workspace.error });
8162
+ }
8163
+ const message = typeof req.body?.message === 'string' ? req.body.message.trim() : '';
8164
+ if (!message) {
8165
+ return res.status(400).json({ error: 'message is required' });
8166
+ }
8167
+ const previousTickets = listTicketsInRunContext(ticket);
8168
+ try {
8169
+ await squashUnpushedCommitsForCwd(workspace.cwd, workspace.branch, workspace.project, message);
8170
+ }
8171
+ catch (error) {
8172
+ return res.status(409).json({ error: getErrorMessage(error) || 'Unable to squash local commits right now.' });
8173
+ }
8174
+ const summary = getUnpushedCommitSummaryForCwd(workspace.cwd, workspace.branch, workspace.project);
8035
8175
  const updated = reconcileRunContextTickets(previousTickets, ticket.id);
8036
8176
  return res.json({
8037
8177
  ticket: updated,
8038
8178
  git_status: getGitStatus(workspace.cwd, workspace.branch, workspace.project),
8039
- commits: listUnpushedCommitsForCwd(workspace.cwd, workspace.branch, workspace.project),
8179
+ commits: summary.commits,
8180
+ total_count: summary.totalCount,
8040
8181
  });
8041
8182
  });
8042
8183
  app.post('/projects/:id/open-ide', (req, res) => {
@@ -8974,6 +9115,15 @@ const runExecutionEvidenceCleanup = () => {
8974
9115
  catch (error) {
8975
9116
  console.error('Failed to clean up expired execution evidence', error);
8976
9117
  }
9118
+ try {
9119
+ const result = pruneAllRepositoryGraphScans();
9120
+ if (result.total > 0) {
9121
+ console.log(`Pruned ${result.total} repository graph scan(s): ${result.completed} completed, ${result.non_completed} non-completed`);
9122
+ }
9123
+ }
9124
+ catch (error) {
9125
+ console.error('Failed to prune repository graph scans', error);
9126
+ }
8977
9127
  };
8978
9128
  const startExecutionEvidenceCleanupTimer = () => {
8979
9129
  if (executionEvidenceCleanupTimer) {
@@ -9047,6 +9197,13 @@ export const startServer = ({ port = DEFAULT_PORT, host } = {}) => {
9047
9197
  releaseInterruptedProjectDeletionClaims();
9048
9198
  await resumeInterruptedProjectDeletions();
9049
9199
  await reconcileStartupExecutions({ getGitHubConfig: getGitHubConnectionConfig });
9200
+ const repositoryGraphSchemaExists = db.prepare(`
9201
+ SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'repository_graph_scans'
9202
+ `).get();
9203
+ if (repositoryGraphSchemaExists) {
9204
+ const graphScans = await import('./lib/repositoryGraphScan.js');
9205
+ graphScans.openRepositoryGraphScanAdmissions();
9206
+ }
9050
9207
  throwIfShutdownRequested();
9051
9208
  await runExecutionArtifactCleanup('startup');
9052
9209
  throwIfShutdownRequested();
@@ -9107,6 +9264,12 @@ export const shutdownServer = async (signal) => {
9107
9264
  }
9108
9265
  await executionArtifactCleanupPromise;
9109
9266
  await stopMobileAccess();
9267
+ const repositoryGraphSchemaExists = db.prepare(`
9268
+ SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'repository_graph_scans'
9269
+ `).get();
9270
+ if (repositoryGraphSchemaExists) {
9271
+ await (await import('./lib/repositoryGraphScan.js')).shutdownRepositoryGraphScans();
9272
+ }
9110
9273
  await shutdownCheckRunner();
9111
9274
  await clearAllTestSessions(io);
9112
9275
  await clearAllGitHubActionsSessions();