@oneuptime/common 11.5.4 → 11.5.5

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 (505) hide show
  1. package/Models/DatabaseModels/AIAgentTaskPullRequest.ts +56 -45
  2. package/Models/DatabaseModels/AIInsight.ts +748 -0
  3. package/Models/DatabaseModels/AIRun.ts +262 -0
  4. package/Models/DatabaseModels/CodeRepository.ts +42 -0
  5. package/Models/DatabaseModels/GlobalConfig.ts +105 -0
  6. package/Models/DatabaseModels/Index.ts +4 -8
  7. package/Models/DatabaseModels/InstanceHealthLog.ts +277 -0
  8. package/Models/DatabaseModels/LlmLog.ts +33 -0
  9. package/Models/DatabaseModels/Project.ts +123 -6
  10. package/Models/DatabaseModels/Runbook.ts +1 -1
  11. package/Server/API/AIAgentDataAPI.ts +802 -140
  12. package/Server/API/AIAgentTaskAPI.ts +132 -69
  13. package/Server/API/AIAgentTaskLogAPI.ts +65 -41
  14. package/Server/API/AIAgentTaskPullRequestAPI.ts +41 -0
  15. package/Server/API/AIInsightAPI.ts +220 -0
  16. package/Server/API/AIInvestigationAPI.ts +363 -1
  17. package/Server/API/CodeFixRunAPI.ts +251 -0
  18. package/Server/API/GitHubAPI.ts +246 -3
  19. package/Server/API/TelemetryExceptionAPI.ts +193 -48
  20. package/Server/EnvironmentConfig.ts +1 -1
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/1783943300000-DropServiceCodeRepository.ts +26 -0
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1783947444597-CodeFixRunsOnAIRun.ts +73 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1783950962813-AddCodeFixTaskType.ts +29 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1783954040984-AddInstrumentationFixTasksFlag.ts +31 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1783957160597-MigrationName.ts +51 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1783958542237-AddTaskContextToAIRun.ts +25 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1783965945957-AddInvestigationVerdictAndGrade.ts +47 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1783970619301-AddFixGuardrailColumns.ts +53 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1783970619302-DropLegacyAIAgentTaskTables.ts +31 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1783977781677-AddCiStatusToFixPullRequests.ts +37 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/1783990000000-AddCompletionTokensToLlmLog.ts +25 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/1784010274993-AddSentinelInsight.ts +75 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/1784010274994-AddSentinelInsightFlags.ts +37 -0
  34. package/Server/Infrastructure/Postgres/SchemaMigrations/1784030612266-RenameSentinelToAI.ts +203 -0
  35. package/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.ts +163 -0
  36. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +30 -0
  37. package/Server/Infrastructure/Queue.ts +82 -4
  38. package/Server/Infrastructure/Semaphore.ts +62 -1
  39. package/Server/Services/AIAgentService.ts +32 -0
  40. package/Server/Services/AIAgentTaskPullRequestService.ts +117 -0
  41. package/Server/Services/AIInsightService.ts +174 -0
  42. package/Server/Services/AIRunEventService.ts +63 -0
  43. package/Server/Services/AIRunService.ts +259 -1
  44. package/Server/Services/AIService.ts +249 -7
  45. package/Server/Services/AlertService.ts +4 -4
  46. package/Server/Services/CodeRepositoryService.ts +209 -0
  47. package/Server/Services/GlobalConfigService.ts +148 -0
  48. package/Server/Services/IncidentService.ts +183 -38
  49. package/Server/Services/IncidentStateTimelineService.ts +24 -4
  50. package/Server/Services/Index.ts +4 -4
  51. package/Server/Services/{AIAgentTaskLogService.ts → InstanceHealthLogService.ts} +1 -1
  52. package/Server/Services/LlmLogService.ts +27 -0
  53. package/Server/Services/LlmProviderService.ts +108 -0
  54. package/Server/Services/MetricBaselineService.ts +123 -0
  55. package/Server/Services/MonitorService.ts +15 -0
  56. package/Server/Services/TelemetryExceptionService.ts +323 -116
  57. package/Server/Services/TraceAggregationService.ts +176 -0
  58. package/Server/Types/Workflow/ComponentCode.ts +6 -0
  59. package/Server/Types/Workflow/Components/AI/GenerateText.ts +326 -0
  60. package/Server/Types/Workflow/Components/Index.ts +2 -0
  61. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +1 -1
  62. package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +71 -0
  63. package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +243 -0
  64. package/Server/Utils/AI/CodeFix/CodeFixRunQueue.ts +131 -0
  65. package/Server/Utils/AI/CodeFix/FixRunBudget.ts +148 -0
  66. package/Server/Utils/AI/CodeFix/OpenPullRequestCap.ts +117 -0
  67. package/Server/Utils/AI/Eval/EvalCorpus.ts +369 -0
  68. package/Server/Utils/AI/Eval/EvalScores.ts +172 -0
  69. package/Server/Utils/AI/Eval/ReplayInvestigation.ts +87 -0
  70. package/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.ts +676 -0
  71. package/Server/Utils/AI/{Sentinel/SentinelInvestigationEngine.ts → SRE/AIInvestigationEngine.ts} +58 -37
  72. package/Server/Utils/AI/{Sentinel/SentinelMemory.ts → SRE/AIMemory.ts} +3 -3
  73. package/Server/Utils/AI/{Sentinel → SRE}/AlertInvestigationRunner.ts +50 -20
  74. package/Server/Utils/AI/SRE/ConfidenceSignal.ts +293 -0
  75. package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +115 -0
  76. package/Server/Utils/AI/SRE/FixPerformanceTaskTrigger.ts +223 -0
  77. package/Server/Utils/AI/{Sentinel → SRE}/IncidentInvestigationRunner.ts +71 -21
  78. package/Server/Utils/AI/{Sentinel → SRE}/IncidentPostmortemRunner.ts +8 -8
  79. package/Server/Utils/AI/SRE/Insights/Detectors/ErrorLogSpikeDetector.ts +364 -0
  80. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +317 -0
  81. package/Server/Utils/AI/SRE/Insights/Detectors/Index.ts +27 -0
  82. package/Server/Utils/AI/SRE/Insights/Detectors/MetricDriftDetector.ts +221 -0
  83. package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +238 -0
  84. package/Server/Utils/AI/SRE/Insights/Detectors/TraceLatencyRegressionDetector.ts +521 -0
  85. package/Server/Utils/AI/SRE/Insights/FixRouting.ts +242 -0
  86. package/Server/Utils/AI/SRE/Insights/InsightScanner.ts +290 -0
  87. package/Server/Utils/AI/SRE/Insights/InsightStore.ts +283 -0
  88. package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +242 -0
  89. package/Server/Utils/AI/SRE/Insights/Triage.ts +162 -0
  90. package/Server/Utils/AI/SRE/Insights/Types.ts +49 -0
  91. package/Server/Utils/AI/SRE/InstrumentationTaskTrigger.ts +212 -0
  92. package/Server/Utils/AI/SRE/InvestigationGrader.ts +282 -0
  93. package/Server/Utils/AI/{Sentinel → SRE}/InvestigationQueue.ts +114 -19
  94. package/Server/Utils/AI/{Sentinel → SRE}/README.md +4 -4
  95. package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +172 -0
  96. package/Server/Utils/AI/Toolbox/{SentinelActionTools.ts → AIActionTools.ts} +22 -1
  97. package/Server/Utils/AI/Toolbox/Index.ts +2 -2
  98. package/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.ts +526 -0
  99. package/Server/Utils/CodeRepository/GitHub/GitHub.ts +319 -1
  100. package/Server/Utils/CodeRepository/ServiceRepoLinkSuggester.ts +221 -0
  101. package/Server/Utils/CodeRepository/StackTraceRepoResolver.ts +571 -0
  102. package/Server/Utils/Execute.ts +2 -1
  103. package/Server/Utils/LLM/LLMService.ts +160 -30
  104. package/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.ts +152 -0
  105. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +29 -0
  106. package/Tests/Server/Infrastructure/Queue.test.ts +227 -0
  107. package/Tests/Server/Infrastructure/SemaphorePermit.test.ts +159 -0
  108. package/Tests/Server/Services/AIAgentTaskPullRequestOutcomeStats.test.ts +154 -0
  109. package/Tests/Server/Services/AIInsightService.test.ts +324 -0
  110. package/Tests/Server/Services/AIRunCodeFixClaim.test.ts +401 -0
  111. package/Tests/Server/Services/AIRunHumanVerdict.test.ts +161 -0
  112. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +95 -5
  113. package/Tests/Server/Services/AIServiceProjectAccess.test.ts +259 -0
  114. package/Tests/Server/Services/FixFromIncidentTaskTrigger.test.ts +249 -0
  115. package/Tests/Server/Services/FixPerformanceTaskTrigger.test.ts +274 -0
  116. package/Tests/Server/Services/GlobalConfigService.test.ts +80 -0
  117. package/Tests/Server/Services/IncidentInternalNoteAnnouncement.test.ts +1 -1
  118. package/Tests/Server/Services/InstrumentationTaskTrigger.test.ts +313 -0
  119. package/Tests/Server/Services/LlmProviderProjectOwned.test.ts +132 -0
  120. package/Tests/Server/Services/TelemetryExceptionAIFixReadiness.test.ts +405 -0
  121. package/Tests/Server/Services/TelemetryExceptionCodeFixRun.test.ts +322 -0
  122. package/Tests/Server/Services/TraceServiceLatencyProfile.test.ts +278 -0
  123. package/Tests/Server/Types/Workflow/Components/AIGenerateText.test.ts +722 -0
  124. package/Tests/Server/Utils/AI/{SentinelAlertGating.test.ts → AIAlertGating.test.ts} +19 -19
  125. package/Tests/Server/Utils/AI/AIConfidenceSignal.test.ts +362 -0
  126. package/Tests/Server/Utils/AI/{SentinelInvestigationQueue.test.ts → AIInvestigationQueue.test.ts} +19 -19
  127. package/Tests/Server/Utils/AI/CodeAgentWorkspaceGuard.test.ts +138 -0
  128. package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +335 -0
  129. package/Tests/Server/Utils/AI/CodeFixRunQueue.test.ts +134 -0
  130. package/Tests/Server/Utils/AI/EvalCorpus.test.ts +209 -0
  131. package/Tests/Server/Utils/AI/EvalScores.test.ts +343 -0
  132. package/Tests/Server/Utils/AI/FixRunBudget.test.ts +218 -0
  133. package/Tests/Server/Utils/AI/Insights/ErrorLogSpikeDetector.test.ts +437 -0
  134. package/Tests/Server/Utils/AI/Insights/ExceptionSpikeDetector.test.ts +287 -0
  135. package/Tests/Server/Utils/AI/Insights/InsightDetectorsIndex.test.ts +34 -0
  136. package/Tests/Server/Utils/AI/Insights/InsightFixRouting.test.ts +572 -0
  137. package/Tests/Server/Utils/AI/Insights/InsightNeverThrowsHardening.test.ts +344 -0
  138. package/Tests/Server/Utils/AI/Insights/InsightScanner.test.ts +720 -0
  139. package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +467 -0
  140. package/Tests/Server/Utils/AI/Insights/InsightStoreHardening.test.ts +370 -0
  141. package/Tests/Server/Utils/AI/Insights/InsightTriage.test.ts +210 -0
  142. package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +221 -0
  143. package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +328 -0
  144. package/Tests/Server/Utils/AI/Insights/MetricBaselineDrift.test.ts +182 -0
  145. package/Tests/Server/Utils/AI/Insights/MetricDriftDetector.test.ts +280 -0
  146. package/Tests/Server/Utils/AI/Insights/NewExceptionDetector.test.ts +259 -0
  147. package/Tests/Server/Utils/AI/Insights/TraceLatencyRegressionDetector.test.ts +770 -0
  148. package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +343 -0
  149. package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +307 -0
  150. package/Tests/Server/Utils/AI/OpenPullRequestCap.test.ts +170 -0
  151. package/Tests/Server/Utils/AI/SpanTreeAnalyzer.test.ts +559 -0
  152. package/Tests/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.test.ts +158 -0
  153. package/Tests/Server/Utils/GitHubCheckRunsConclusion.test.ts +100 -0
  154. package/Tests/Server/Utils/GitHubPullRequestStateMapping.test.ts +50 -0
  155. package/Tests/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.test.ts +266 -0
  156. package/Tests/Server/Utils/ServiceRepoLinkSuggester.test.ts +167 -0
  157. package/Tests/Server/Utils/StackTraceRepoResolver.test.ts +527 -0
  158. package/Tests/Types/AI/AIChatPermissionMode.test.ts +112 -0
  159. package/Tests/Types/AI/CodeFixTaskType.test.ts +152 -0
  160. package/Tests/Types/AI/FixPullRequestCiStatus.test.ts +181 -0
  161. package/Tests/Types/Monitor/MonitorStepSqlMonitor.test.ts +110 -0
  162. package/Tests/Types/Monitor/SqlDatabaseType.test.ts +55 -0
  163. package/Tests/Types/Workflow/AIGenerateTextMetadata.test.ts +180 -0
  164. package/Tests/UI/Components/TableBulkCsvExport.test.tsx +168 -0
  165. package/Tests/UI/Utils/TableColumnsToCsv.test.ts +523 -0
  166. package/Types/AI/AIChatTypes.ts +8 -0
  167. package/Types/AI/AIInsightEvidence.ts +77 -0
  168. package/Types/AI/AIInsightHumanVerdict.ts +15 -0
  169. package/Types/AI/AIInsightSeverity.ts +13 -0
  170. package/Types/AI/AIInsightStatus.ts +38 -0
  171. package/Types/AI/AIInsightType.ts +41 -0
  172. package/Types/AI/AIRunAutoGrade.ts +18 -0
  173. package/Types/AI/AIRunEventType.ts +5 -0
  174. package/Types/AI/AIRunHumanVerdict.ts +17 -0
  175. package/Types/AI/AIRunType.ts +6 -0
  176. package/Types/AI/CodeFixTaskContext.ts +88 -0
  177. package/Types/AI/CodeFixTaskType.ts +132 -0
  178. package/Types/AI/FixPullRequestCiStatus.ts +132 -0
  179. package/Types/BaseDatabase/AggregationIntervalUtil.ts +67 -0
  180. package/Types/Incident/IncidentMetricType.ts +7 -0
  181. package/Types/Monitor/CriteriaFilter.ts +8 -0
  182. package/Types/Monitor/MonitorCriteriaInstance.ts +67 -0
  183. package/Types/Monitor/MonitorStep.ts +38 -0
  184. package/Types/Monitor/MonitorStepSqlMonitor.ts +141 -0
  185. package/Types/Monitor/MonitorType.ts +17 -0
  186. package/Types/Monitor/SqlDatabaseType.ts +49 -0
  187. package/Types/Monitor/SqlMonitor/SqlMonitorResponse.ts +28 -0
  188. package/Types/Permission.ts +11 -95
  189. package/Types/Probe/ProbeMonitorResponse.ts +2 -0
  190. package/Types/Runbook/RunbookStep.ts +26 -2
  191. package/Types/Runbook/RunbookStepType.ts +1 -0
  192. package/Types/Workflow/Component.ts +13 -0
  193. package/Types/Workflow/ComponentID.ts +1 -0
  194. package/Types/Workflow/Components/AI.ts +148 -0
  195. package/Types/Workflow/Components.ts +8 -0
  196. package/UI/Components/AI/GenerateFromAIModal.tsx +1 -1
  197. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +11 -0
  198. package/UI/Components/MoreMenu/MoreMenu.tsx +1 -1
  199. package/UI/Components/Table/Table.tsx +38 -2
  200. package/UI/Utils/TableColumnsToCsv.ts +385 -0
  201. package/Utils/Monitor/MonitorMetricType.ts +1 -0
  202. package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js +59 -45
  203. package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js.map +1 -1
  204. package/build/dist/Models/DatabaseModels/AIInsight.js +795 -0
  205. package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -0
  206. package/build/dist/Models/DatabaseModels/AIRun.js +274 -0
  207. package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
  208. package/build/dist/Models/DatabaseModels/CodeRepository.js +43 -0
  209. package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -1
  210. package/build/dist/Models/DatabaseModels/GlobalConfig.js +110 -0
  211. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  212. package/build/dist/Models/DatabaseModels/Index.js +4 -8
  213. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  214. package/build/dist/Models/DatabaseModels/InstanceHealthLog.js +304 -0
  215. package/build/dist/Models/DatabaseModels/InstanceHealthLog.js.map +1 -0
  216. package/build/dist/Models/DatabaseModels/LlmLog.js +35 -0
  217. package/build/dist/Models/DatabaseModels/LlmLog.js.map +1 -1
  218. package/build/dist/Models/DatabaseModels/Project.js +127 -6
  219. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  220. package/build/dist/Models/DatabaseModels/Runbook.js +1 -1
  221. package/build/dist/Models/DatabaseModels/Runbook.js.map +1 -1
  222. package/build/dist/Server/API/AIAgentDataAPI.js +568 -85
  223. package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
  224. package/build/dist/Server/API/AIAgentTaskAPI.js +100 -44
  225. package/build/dist/Server/API/AIAgentTaskAPI.js.map +1 -1
  226. package/build/dist/Server/API/AIAgentTaskLogAPI.js +49 -25
  227. package/build/dist/Server/API/AIAgentTaskLogAPI.js.map +1 -1
  228. package/build/dist/Server/API/AIAgentTaskPullRequestAPI.js +27 -0
  229. package/build/dist/Server/API/AIAgentTaskPullRequestAPI.js.map +1 -1
  230. package/build/dist/Server/API/AIInsightAPI.js +140 -0
  231. package/build/dist/Server/API/AIInsightAPI.js.map +1 -0
  232. package/build/dist/Server/API/AIInvestigationAPI.js +257 -1
  233. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  234. package/build/dist/Server/API/CodeFixRunAPI.js +181 -0
  235. package/build/dist/Server/API/CodeFixRunAPI.js.map +1 -0
  236. package/build/dist/Server/API/GitHubAPI.js +164 -2
  237. package/build/dist/Server/API/GitHubAPI.js.map +1 -1
  238. package/build/dist/Server/API/TelemetryExceptionAPI.js +148 -43
  239. package/build/dist/Server/API/TelemetryExceptionAPI.js.map +1 -1
  240. package/build/dist/Server/EnvironmentConfig.js +1 -1
  241. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  242. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783943300000-DropServiceCodeRepository.js +23 -0
  243. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783943300000-DropServiceCodeRepository.js.map +1 -0
  244. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783947444597-CodeFixRunsOnAIRun.js +32 -0
  245. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783947444597-CodeFixRunsOnAIRun.js.map +1 -0
  246. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783950962813-AddCodeFixTaskType.js +16 -0
  247. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783950962813-AddCodeFixTaskType.js.map +1 -0
  248. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783954040984-AddInstrumentationFixTasksFlag.js +16 -0
  249. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783954040984-AddInstrumentationFixTasksFlag.js.map +1 -0
  250. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783957160597-MigrationName.js +24 -0
  251. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783957160597-MigrationName.js.map +1 -0
  252. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783958542237-AddTaskContextToAIRun.js +16 -0
  253. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783958542237-AddTaskContextToAIRun.js.map +1 -0
  254. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783965945957-AddInvestigationVerdictAndGrade.js +24 -0
  255. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783965945957-AddInvestigationVerdictAndGrade.js.map +1 -0
  256. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619301-AddFixGuardrailColumns.js +24 -0
  257. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619301-AddFixGuardrailColumns.js.map +1 -0
  258. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619302-DropLegacyAIAgentTaskTables.js +24 -0
  259. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783970619302-DropLegacyAIAgentTaskTables.js.map +1 -0
  260. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783977781677-AddCiStatusToFixPullRequests.js +18 -0
  261. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783977781677-AddCiStatusToFixPullRequests.js.map +1 -0
  262. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783990000000-AddCompletionTokensToLlmLog.js +18 -0
  263. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783990000000-AddCompletionTokensToLlmLog.js.map +1 -0
  264. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274993-AddSentinelInsight.js +32 -0
  265. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274993-AddSentinelInsight.js.map +1 -0
  266. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274994-AddSentinelInsightFlags.js +18 -0
  267. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784010274994-AddSentinelInsightFlags.js.map +1 -0
  268. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784030612266-RenameSentinelToAI.js +125 -0
  269. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784030612266-RenameSentinelToAI.js.map +1 -0
  270. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.js +62 -0
  271. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784033837629-MigrationName.js.map +1 -0
  272. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +30 -0
  273. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  274. package/build/dist/Server/Infrastructure/Queue.js +73 -3
  275. package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
  276. package/build/dist/Server/Infrastructure/Semaphore.js +44 -1
  277. package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
  278. package/build/dist/Server/Services/AIAgentService.js +29 -0
  279. package/build/dist/Server/Services/AIAgentService.js.map +1 -1
  280. package/build/dist/Server/Services/AIAgentTaskPullRequestService.js +78 -0
  281. package/build/dist/Server/Services/AIAgentTaskPullRequestService.js.map +1 -1
  282. package/build/dist/Server/Services/AIInsightService.js +164 -0
  283. package/build/dist/Server/Services/AIInsightService.js.map +1 -0
  284. package/build/dist/Server/Services/AIRunEventService.js +49 -0
  285. package/build/dist/Server/Services/AIRunEventService.js.map +1 -1
  286. package/build/dist/Server/Services/AIRunService.js +221 -0
  287. package/build/dist/Server/Services/AIRunService.js.map +1 -1
  288. package/build/dist/Server/Services/AIService.js +198 -11
  289. package/build/dist/Server/Services/AIService.js.map +1 -1
  290. package/build/dist/Server/Services/AlertService.js +4 -4
  291. package/build/dist/Server/Services/AlertService.js.map +1 -1
  292. package/build/dist/Server/Services/CodeRepositoryService.js +180 -0
  293. package/build/dist/Server/Services/CodeRepositoryService.js.map +1 -1
  294. package/build/dist/Server/Services/GlobalConfigService.js +84 -0
  295. package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
  296. package/build/dist/Server/Services/IncidentService.js +149 -37
  297. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  298. package/build/dist/Server/Services/IncidentStateTimelineService.js +24 -4
  299. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  300. package/build/dist/Server/Services/Index.js +4 -4
  301. package/build/dist/Server/Services/Index.js.map +1 -1
  302. package/build/dist/Server/Services/{AIAgentTaskLogService.js → InstanceHealthLogService.js} +2 -2
  303. package/build/dist/Server/Services/InstanceHealthLogService.js.map +1 -0
  304. package/build/dist/Server/Services/LlmLogService.js +23 -0
  305. package/build/dist/Server/Services/LlmLogService.js.map +1 -1
  306. package/build/dist/Server/Services/LlmProviderService.js +96 -0
  307. package/build/dist/Server/Services/LlmProviderService.js.map +1 -1
  308. package/build/dist/Server/Services/MetricBaselineService.js +65 -0
  309. package/build/dist/Server/Services/MetricBaselineService.js.map +1 -1
  310. package/build/dist/Server/Services/MonitorService.js +9 -1
  311. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  312. package/build/dist/Server/Services/TelemetryExceptionService.js +243 -82
  313. package/build/dist/Server/Services/TelemetryExceptionService.js.map +1 -1
  314. package/build/dist/Server/Services/TraceAggregationService.js +124 -0
  315. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  316. package/build/dist/Server/Types/Workflow/ComponentCode.js.map +1 -1
  317. package/build/dist/Server/Types/Workflow/Components/AI/GenerateText.js +240 -0
  318. package/build/dist/Server/Types/Workflow/Components/AI/GenerateText.js.map +1 -0
  319. package/build/dist/Server/Types/Workflow/Components/Index.js +2 -0
  320. package/build/dist/Server/Types/Workflow/Components/Index.js.map +1 -1
  321. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +48 -0
  322. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js.map +1 -0
  323. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +174 -0
  324. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -0
  325. package/build/dist/Server/Utils/AI/CodeFix/CodeFixRunQueue.js +126 -0
  326. package/build/dist/Server/Utils/AI/CodeFix/CodeFixRunQueue.js.map +1 -0
  327. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +131 -0
  328. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -0
  329. package/build/dist/Server/Utils/AI/CodeFix/OpenPullRequestCap.js +99 -0
  330. package/build/dist/Server/Utils/AI/CodeFix/OpenPullRequestCap.js.map +1 -0
  331. package/build/dist/Server/Utils/AI/Eval/EvalCorpus.js +245 -0
  332. package/build/dist/Server/Utils/AI/Eval/EvalCorpus.js.map +1 -0
  333. package/build/dist/Server/Utils/AI/Eval/EvalScores.js +83 -0
  334. package/build/dist/Server/Utils/AI/Eval/EvalScores.js.map +1 -0
  335. package/build/dist/Server/Utils/AI/Eval/ReplayInvestigation.js +12 -0
  336. package/build/dist/Server/Utils/AI/Eval/ReplayInvestigation.js.map +1 -0
  337. package/build/dist/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.js +439 -0
  338. package/build/dist/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.js.map +1 -0
  339. package/build/dist/Server/Utils/AI/{Sentinel/SentinelInvestigationEngine.js → SRE/AIInvestigationEngine.js} +47 -31
  340. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -0
  341. package/build/dist/Server/Utils/AI/{Sentinel/SentinelMemory.js → SRE/AIMemory.js} +5 -5
  342. package/build/dist/Server/Utils/AI/SRE/AIMemory.js.map +1 -0
  343. package/build/dist/Server/Utils/AI/{Sentinel → SRE}/AlertInvestigationRunner.js +42 -19
  344. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -0
  345. package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js +226 -0
  346. package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js.map +1 -0
  347. package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js +100 -0
  348. package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js.map +1 -0
  349. package/build/dist/Server/Utils/AI/SRE/FixPerformanceTaskTrigger.js +174 -0
  350. package/build/dist/Server/Utils/AI/SRE/FixPerformanceTaskTrigger.js.map +1 -0
  351. package/build/dist/Server/Utils/AI/{Sentinel → SRE}/IncidentInvestigationRunner.js +60 -22
  352. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -0
  353. package/build/dist/Server/Utils/AI/{Sentinel → SRE}/IncidentPostmortemRunner.js +9 -9
  354. package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js.map +1 -0
  355. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ErrorLogSpikeDetector.js +268 -0
  356. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ErrorLogSpikeDetector.js.map +1 -0
  357. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +226 -0
  358. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -0
  359. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/Index.js +26 -0
  360. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/Index.js.map +1 -0
  361. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/MetricDriftDetector.js +159 -0
  362. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/MetricDriftDetector.js.map +1 -0
  363. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +177 -0
  364. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -0
  365. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/TraceLatencyRegressionDetector.js +384 -0
  366. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/TraceLatencyRegressionDetector.js.map +1 -0
  367. package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js +180 -0
  368. package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -0
  369. package/build/dist/Server/Utils/AI/SRE/Insights/InsightScanner.js +269 -0
  370. package/build/dist/Server/Utils/AI/SRE/Insights/InsightScanner.js.map +1 -0
  371. package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js +231 -0
  372. package/build/dist/Server/Utils/AI/SRE/Insights/InsightStore.js.map +1 -0
  373. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +206 -0
  374. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -0
  375. package/build/dist/Server/Utils/AI/SRE/Insights/Triage.js +121 -0
  376. package/build/dist/Server/Utils/AI/SRE/Insights/Triage.js.map +1 -0
  377. package/build/dist/Server/Utils/AI/SRE/Insights/Types.js +2 -0
  378. package/build/dist/Server/Utils/AI/SRE/Insights/Types.js.map +1 -0
  379. package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js +148 -0
  380. package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js.map +1 -0
  381. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +231 -0
  382. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -0
  383. package/build/dist/Server/Utils/AI/{Sentinel → SRE}/InvestigationQueue.js +102 -23
  384. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -0
  385. package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +167 -0
  386. package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -0
  387. package/build/dist/Server/Utils/AI/Toolbox/{SentinelActionTools.js → AIActionTools.js} +18 -2
  388. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -0
  389. package/build/dist/Server/Utils/AI/Toolbox/Index.js +2 -2
  390. package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
  391. package/build/dist/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.js +301 -0
  392. package/build/dist/Server/Utils/AnalyticsDatabase/ClickhouseCapacity.js.map +1 -0
  393. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +240 -2
  394. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
  395. package/build/dist/Server/Utils/CodeRepository/ServiceRepoLinkSuggester.js +127 -0
  396. package/build/dist/Server/Utils/CodeRepository/ServiceRepoLinkSuggester.js.map +1 -0
  397. package/build/dist/Server/Utils/CodeRepository/StackTraceRepoResolver.js +336 -0
  398. package/build/dist/Server/Utils/CodeRepository/StackTraceRepoResolver.js.map +1 -0
  399. package/build/dist/Server/Utils/Execute.js.map +1 -1
  400. package/build/dist/Server/Utils/LLM/LLMService.js +125 -25
  401. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  402. package/build/dist/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.js +120 -0
  403. package/build/dist/Server/Utils/Monitor/Criteria/SqlMonitorCriteria.js.map +1 -0
  404. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +21 -0
  405. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  406. package/build/dist/Types/AI/AIInsightEvidence.js +2 -0
  407. package/build/dist/Types/AI/AIInsightEvidence.js.map +1 -0
  408. package/build/dist/Types/AI/AIInsightHumanVerdict.js +16 -0
  409. package/build/dist/Types/AI/AIInsightHumanVerdict.js.map +1 -0
  410. package/build/dist/Types/AI/AIInsightSeverity.js +14 -0
  411. package/build/dist/Types/AI/AIInsightSeverity.js.map +1 -0
  412. package/build/dist/Types/AI/AIInsightStatus.js +36 -0
  413. package/build/dist/Types/AI/AIInsightStatus.js.map +1 -0
  414. package/build/dist/Types/AI/AIInsightType.js +42 -0
  415. package/build/dist/Types/AI/AIInsightType.js.map +1 -0
  416. package/build/dist/Types/AI/AIRunAutoGrade.js +19 -0
  417. package/build/dist/Types/AI/AIRunAutoGrade.js.map +1 -0
  418. package/build/dist/Types/AI/AIRunEventType.js +5 -0
  419. package/build/dist/Types/AI/AIRunEventType.js.map +1 -1
  420. package/build/dist/Types/AI/AIRunHumanVerdict.js +18 -0
  421. package/build/dist/Types/AI/AIRunHumanVerdict.js.map +1 -0
  422. package/build/dist/Types/AI/AIRunType.js +6 -0
  423. package/build/dist/Types/AI/AIRunType.js.map +1 -1
  424. package/build/dist/Types/AI/CodeFixTaskContext.js +29 -0
  425. package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -0
  426. package/build/dist/Types/AI/CodeFixTaskType.js +122 -0
  427. package/build/dist/Types/AI/CodeFixTaskType.js.map +1 -0
  428. package/build/dist/Types/AI/FixPullRequestCiStatus.js +102 -0
  429. package/build/dist/Types/AI/FixPullRequestCiStatus.js.map +1 -0
  430. package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js +55 -0
  431. package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js.map +1 -1
  432. package/build/dist/Types/Incident/IncidentMetricType.js +7 -0
  433. package/build/dist/Types/Incident/IncidentMetricType.js.map +1 -1
  434. package/build/dist/Types/Monitor/CriteriaFilter.js +7 -0
  435. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  436. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +62 -0
  437. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  438. package/build/dist/Types/Monitor/MonitorStep.js +28 -0
  439. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  440. package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js +93 -0
  441. package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -0
  442. package/build/dist/Types/Monitor/MonitorType.js +15 -0
  443. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  444. package/build/dist/Types/Monitor/SqlDatabaseType.js +47 -0
  445. package/build/dist/Types/Monitor/SqlDatabaseType.js.map +1 -0
  446. package/build/dist/Types/Monitor/SqlMonitor/SqlMonitorResponse.js +2 -0
  447. package/build/dist/Types/Monitor/SqlMonitor/SqlMonitorResponse.js.map +1 -0
  448. package/build/dist/Types/Permission.js +10 -84
  449. package/build/dist/Types/Permission.js.map +1 -1
  450. package/build/dist/Types/Runbook/RunbookStepType.js +1 -0
  451. package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
  452. package/build/dist/Types/Workflow/ComponentID.js +1 -0
  453. package/build/dist/Types/Workflow/ComponentID.js.map +1 -1
  454. package/build/dist/Types/Workflow/Components/AI.js +135 -0
  455. package/build/dist/Types/Workflow/Components/AI.js.map +1 -0
  456. package/build/dist/Types/Workflow/Components.js +7 -0
  457. package/build/dist/Types/Workflow/Components.js.map +1 -1
  458. package/build/dist/UI/Components/AI/GenerateFromAIModal.js +1 -1
  459. package/build/dist/UI/Components/AI/GenerateFromAIModal.js.map +1 -1
  460. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +9 -0
  461. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  462. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +1 -1
  463. package/build/dist/UI/Components/Table/Table.js +28 -2
  464. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  465. package/build/dist/UI/Utils/TableColumnsToCsv.js +291 -0
  466. package/build/dist/UI/Utils/TableColumnsToCsv.js.map +1 -0
  467. package/build/dist/Utils/Monitor/MonitorMetricType.js +1 -0
  468. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  469. package/package.json +1 -1
  470. package/Models/DatabaseModels/AIAgentTask.ts +0 -660
  471. package/Models/DatabaseModels/AIAgentTaskLog.ts +0 -426
  472. package/Models/DatabaseModels/AIAgentTaskTelemetryException.ts +0 -399
  473. package/Models/DatabaseModels/ServiceCodeRepository.ts +0 -647
  474. package/Server/Services/AIAgentTaskService.ts +0 -240
  475. package/Server/Services/AIAgentTaskTelemetryExceptionService.ts +0 -39
  476. package/Server/Services/ServiceCodeRepositoryService.ts +0 -55
  477. package/Tests/Server/Services/AIAgentTaskServiceClaim.test.ts +0 -146
  478. package/Types/AI/AIAgentTaskMetadata.ts +0 -25
  479. package/Types/AI/AIAgentTaskType.ts +0 -40
  480. package/build/dist/Models/DatabaseModels/AIAgentTask.js +0 -691
  481. package/build/dist/Models/DatabaseModels/AIAgentTask.js.map +0 -1
  482. package/build/dist/Models/DatabaseModels/AIAgentTaskLog.js +0 -447
  483. package/build/dist/Models/DatabaseModels/AIAgentTaskLog.js.map +0 -1
  484. package/build/dist/Models/DatabaseModels/AIAgentTaskTelemetryException.js +0 -415
  485. package/build/dist/Models/DatabaseModels/AIAgentTaskTelemetryException.js.map +0 -1
  486. package/build/dist/Models/DatabaseModels/ServiceCodeRepository.js +0 -665
  487. package/build/dist/Models/DatabaseModels/ServiceCodeRepository.js.map +0 -1
  488. package/build/dist/Server/Services/AIAgentTaskLogService.js.map +0 -1
  489. package/build/dist/Server/Services/AIAgentTaskService.js +0 -217
  490. package/build/dist/Server/Services/AIAgentTaskService.js.map +0 -1
  491. package/build/dist/Server/Services/AIAgentTaskTelemetryExceptionService.js +0 -36
  492. package/build/dist/Server/Services/AIAgentTaskTelemetryExceptionService.js.map +0 -1
  493. package/build/dist/Server/Services/ServiceCodeRepositoryService.js +0 -54
  494. package/build/dist/Server/Services/ServiceCodeRepositoryService.js.map +0 -1
  495. package/build/dist/Server/Utils/AI/Sentinel/AlertInvestigationRunner.js.map +0 -1
  496. package/build/dist/Server/Utils/AI/Sentinel/IncidentInvestigationRunner.js.map +0 -1
  497. package/build/dist/Server/Utils/AI/Sentinel/IncidentPostmortemRunner.js.map +0 -1
  498. package/build/dist/Server/Utils/AI/Sentinel/InvestigationQueue.js.map +0 -1
  499. package/build/dist/Server/Utils/AI/Sentinel/SentinelInvestigationEngine.js.map +0 -1
  500. package/build/dist/Server/Utils/AI/Sentinel/SentinelMemory.js.map +0 -1
  501. package/build/dist/Server/Utils/AI/Toolbox/SentinelActionTools.js.map +0 -1
  502. package/build/dist/Types/AI/AIAgentTaskMetadata.js +0 -6
  503. package/build/dist/Types/AI/AIAgentTaskMetadata.js.map +0 -1
  504. package/build/dist/Types/AI/AIAgentTaskType.js +0 -29
  505. package/build/dist/Types/AI/AIAgentTaskType.js.map +0 -1
@@ -0,0 +1,370 @@
1
+ import InsightStore, {
2
+ INSIGHT_FINGERPRINT_MAX_LENGTH,
3
+ INSIGHT_METRIC_NAME_MAX_LENGTH,
4
+ INSIGHT_SERVICE_NAME_MAX_LENGTH,
5
+ INSIGHT_TITLE_MAX_LENGTH,
6
+ INSIGHT_TRACE_ID_MAX_LENGTH,
7
+ MAX_NEW_INSIGHTS_PER_PROJECT_PER_SCAN,
8
+ UpsertCandidatesResult,
9
+ } from "../../../../../Server/Utils/AI/SRE/Insights/InsightStore";
10
+ import { InsightCandidate } from "../../../../../Server/Utils/AI/SRE/Insights/Types";
11
+ import AIInsightService from "../../../../../Server/Services/AIInsightService";
12
+ import CreateBy from "../../../../../Server/Types/Database/CreateBy";
13
+ import FindOneBy from "../../../../../Server/Types/Database/FindOneBy";
14
+ import AIInsight from "../../../../../Models/DatabaseModels/AIInsight";
15
+ import AIInsightStatus from "../../../../../Types/AI/AIInsightStatus";
16
+ import AIInsightType from "../../../../../Types/AI/AIInsightType";
17
+ import AIInsightSeverity from "../../../../../Types/AI/AIInsightSeverity";
18
+ import ColumnLength from "../../../../../Types/Database/ColumnLength";
19
+ import ObjectID from "../../../../../Types/ObjectID";
20
+ import { describe, expect, test, afterEach } from "@jest/globals";
21
+
22
+ /*
23
+ * Adversarial hardening of the insight store. The invariants these tests
24
+ * lock in:
25
+ * (a) column safety: detector-produced strings are clamped to the model's
26
+ * declared column lengths BEFORE hitting DatabaseService's length
27
+ * check (which throws on overflow), and the clamped fingerprint is the
28
+ * row's identity for the dedupe LOOKUP too — so an over-long
29
+ * fingerprint refreshes one row across ticks instead of failing or
30
+ * duplicating on every scan;
31
+ * (b) per-candidate isolation: one failing candidate never aborts the
32
+ * batch — siblings are still upserted and every successfully created
33
+ * insight is returned for routing (otherwise a mid-batch failure would
34
+ * strand already-created rows in Detected forever);
35
+ * (c) a failed create does not consume the per-scan cap;
36
+ * (d) same-fingerprint behavior is pinned: within one batch (DB-faithful
37
+ * lookup) the second candidate refreshes the row the first created;
38
+ * when the lookup misses for both (the concurrent-scan race —
39
+ * (projectId, fingerprint) is deliberately NOT unique and there is no
40
+ * DB-level guard) the store creates duplicates. The single-flight cron
41
+ * (10-min timeout < 15-min tick) is the real concurrency guard.
42
+ */
43
+
44
+ const projectId: ObjectID = ObjectID.generate();
45
+ const now: Date = new Date("2026-07-14T12:00:00.000Z");
46
+
47
+ function makeCandidate(
48
+ overrides?: Partial<InsightCandidate>,
49
+ ): InsightCandidate {
50
+ return {
51
+ insightType: AIInsightType.TraceLatencyRegression,
52
+ fingerprint: "latency:svc-1:GET /checkout",
53
+ title: "Latency regression: p99 3.0x on GET /checkout",
54
+ detailMarkdown: "**p99** went from 800ms to 2400ms.",
55
+ severity: AIInsightSeverity.Medium,
56
+ evidence: {
57
+ latency: {
58
+ recentP99Ms: 2400,
59
+ baselineP99Ms: 800,
60
+ regressionMultiplier: 3,
61
+ },
62
+ },
63
+ ...overrides,
64
+ };
65
+ }
66
+
67
+ /*
68
+ * create echoes back the model it was handed (with an id), so assertions can
69
+ * inspect exactly what the store persisted.
70
+ */
71
+ function mockCreate(): jest.SpyInstance {
72
+ return jest
73
+ .spyOn(AIInsightService, "create")
74
+ .mockImplementation((createBy: CreateBy<AIInsight>) => {
75
+ const model: AIInsight = createBy.data;
76
+ model.id = ObjectID.generate();
77
+ return Promise.resolve(model);
78
+ });
79
+ }
80
+
81
+ function mockFindOneBy(existing: AIInsight | null): jest.SpyInstance {
82
+ return jest.spyOn(AIInsightService, "findOneBy").mockResolvedValue(existing);
83
+ }
84
+
85
+ function mockUpdateOneById(): jest.SpyInstance {
86
+ return jest
87
+ .spyOn(AIInsightService, "updateOneById")
88
+ .mockResolvedValue(undefined);
89
+ }
90
+
91
+ describe("InsightStore — column-length clamps", () => {
92
+ afterEach(() => {
93
+ jest.restoreAllMocks();
94
+ });
95
+
96
+ test("the clamp caps mirror the AIInsight column definitions", () => {
97
+ expect(INSIGHT_FINGERPRINT_MAX_LENGTH).toBe(ColumnLength.LongText);
98
+ expect(INSIGHT_TITLE_MAX_LENGTH).toBe(ColumnLength.LongText);
99
+ expect(INSIGHT_SERVICE_NAME_MAX_LENGTH).toBe(ColumnLength.LongText);
100
+ expect(INSIGHT_METRIC_NAME_MAX_LENGTH).toBe(ColumnLength.LongText);
101
+ expect(INSIGHT_TRACE_ID_MAX_LENGTH).toBe(ColumnLength.ShortText);
102
+ });
103
+
104
+ test("over-long detector strings are clamped to the column caps on create — and the dedupe lookup uses the CLAMPED fingerprint", async () => {
105
+ /*
106
+ * A span name can be an entire SQL statement — every string that ends up
107
+ * in a length-checked varchar column must be clamped or the create
108
+ * throws and the candidate (and, without isolation, the batch) is lost.
109
+ */
110
+ const hugeOperation: string = `SELECT ${"column_name, ".repeat(100)}FROM orders`;
111
+ const findOneBy: jest.SpyInstance = mockFindOneBy(null);
112
+ const create: jest.SpyInstance = mockCreate();
113
+
114
+ const result: UpsertCandidatesResult = await InsightStore.upsertCandidates({
115
+ projectId,
116
+ candidates: [
117
+ makeCandidate({
118
+ fingerprint: `latency:svc-1:${hugeOperation}`,
119
+ title: `Latency regression: p99 3.0x on ${hugeOperation}`,
120
+ serviceName: "s".repeat(INSIGHT_SERVICE_NAME_MAX_LENGTH + 100),
121
+ metricName: "m".repeat(INSIGHT_METRIC_NAME_MAX_LENGTH + 100),
122
+ traceId: "t".repeat(INSIGHT_TRACE_ID_MAX_LENGTH + 50),
123
+ }),
124
+ ],
125
+ now,
126
+ });
127
+
128
+ expect(create).toHaveBeenCalledTimes(1);
129
+ expect(result.created).toHaveLength(1);
130
+
131
+ const persisted: AIInsight = result.created[0]!;
132
+ const expectedFingerprint: string = `latency:svc-1:${hugeOperation}`.slice(
133
+ 0,
134
+ INSIGHT_FINGERPRINT_MAX_LENGTH,
135
+ );
136
+
137
+ expect(persisted.fingerprint).toBe(expectedFingerprint);
138
+ expect(persisted.title!.length).toBe(INSIGHT_TITLE_MAX_LENGTH);
139
+ expect(persisted.serviceName!.length).toBe(INSIGHT_SERVICE_NAME_MAX_LENGTH);
140
+ expect(persisted.metricName!.length).toBe(INSIGHT_METRIC_NAME_MAX_LENGTH);
141
+ expect(persisted.traceId!.length).toBe(INSIGHT_TRACE_ID_MAX_LENGTH);
142
+
143
+ // Identity consistency: the lookup asked for what the insert stored.
144
+ expect(findOneBy).toHaveBeenCalledWith(
145
+ expect.objectContaining({
146
+ query: expect.objectContaining({
147
+ fingerprint: expectedFingerprint,
148
+ }),
149
+ }),
150
+ );
151
+ });
152
+
153
+ test("a clamped fingerprint still dedupes on the next tick — refresh, not a duplicate row", async () => {
154
+ const hugeFingerprint: string = `latency:svc-1:${"x".repeat(1000)}`;
155
+ const clamped: string = hugeFingerprint.slice(
156
+ 0,
157
+ INSIGHT_FINGERPRINT_MAX_LENGTH,
158
+ );
159
+
160
+ /*
161
+ * DB-faithful stateful lookup: rows created by this run are visible to
162
+ * later lookups keyed on their (clamped) stored fingerprint.
163
+ */
164
+ const rowsByFingerprint: Map<string, AIInsight> = new Map();
165
+
166
+ jest
167
+ .spyOn(AIInsightService, "findOneBy")
168
+ .mockImplementation((findOneBy: FindOneBy<AIInsight>) => {
169
+ const fingerprint: string = (
170
+ findOneBy.query as { fingerprint?: string }
171
+ ).fingerprint!;
172
+ return Promise.resolve(rowsByFingerprint.get(fingerprint) || null);
173
+ });
174
+
175
+ const create: jest.SpyInstance = jest
176
+ .spyOn(AIInsightService, "create")
177
+ .mockImplementation((createBy: CreateBy<AIInsight>) => {
178
+ const model: AIInsight = createBy.data;
179
+ model.id = ObjectID.generate();
180
+ model.status = AIInsightStatus.ActionRequired;
181
+ rowsByFingerprint.set(model.fingerprint!, model);
182
+ return Promise.resolve(model);
183
+ });
184
+ const update: jest.SpyInstance = mockUpdateOneById();
185
+
186
+ const firstTick: UpsertCandidatesResult =
187
+ await InsightStore.upsertCandidates({
188
+ projectId,
189
+ candidates: [makeCandidate({ fingerprint: hugeFingerprint })],
190
+ now,
191
+ });
192
+
193
+ const secondTick: UpsertCandidatesResult =
194
+ await InsightStore.upsertCandidates({
195
+ projectId,
196
+ candidates: [makeCandidate({ fingerprint: hugeFingerprint })],
197
+ now: new Date(now.getTime() + 15 * 60 * 1000),
198
+ });
199
+
200
+ expect(firstTick.created).toHaveLength(1);
201
+ expect(firstTick.created[0]?.fingerprint).toBe(clamped);
202
+ expect(secondTick.created).toHaveLength(0);
203
+ expect(secondTick.refreshed).toBe(1);
204
+ expect(create).toHaveBeenCalledTimes(1);
205
+ expect(update).toHaveBeenCalledTimes(1);
206
+ });
207
+ });
208
+
209
+ describe("InsightStore — per-candidate failure isolation", () => {
210
+ afterEach(() => {
211
+ jest.restoreAllMocks();
212
+ });
213
+
214
+ test("a create rejection on the middle candidate does not abort the batch — siblings are created and returned for routing", async () => {
215
+ mockFindOneBy(null);
216
+ jest
217
+ .spyOn(AIInsightService, "create")
218
+ .mockImplementation((createBy: CreateBy<AIInsight>) => {
219
+ const model: AIInsight = createBy.data;
220
+ if (model.fingerprint === "boom") {
221
+ return Promise.reject(new Error("title length cannot be more..."));
222
+ }
223
+ model.id = ObjectID.generate();
224
+ return Promise.resolve(model);
225
+ });
226
+
227
+ const result: UpsertCandidatesResult = await InsightStore.upsertCandidates({
228
+ projectId,
229
+ candidates: [
230
+ makeCandidate({ fingerprint: "first" }),
231
+ makeCandidate({ fingerprint: "boom" }),
232
+ makeCandidate({ fingerprint: "third" }),
233
+ ],
234
+ now,
235
+ });
236
+
237
+ expect(result.created).toHaveLength(2);
238
+ expect(result.created[0]?.fingerprint).toBe("first");
239
+ expect(result.created[1]?.fingerprint).toBe("third");
240
+ expect(result.droppedByCap).toBe(0);
241
+ });
242
+
243
+ test("a dedupe-lookup rejection is isolated too — the remaining candidates still upsert", async () => {
244
+ jest
245
+ .spyOn(AIInsightService, "findOneBy")
246
+ .mockImplementation((findOneBy: FindOneBy<AIInsight>) => {
247
+ const fingerprint: string = (
248
+ findOneBy.query as { fingerprint?: string }
249
+ ).fingerprint!;
250
+ if (fingerprint === "first") {
251
+ return Promise.reject(new Error("connection reset"));
252
+ }
253
+ return Promise.resolve(null);
254
+ });
255
+ mockCreate();
256
+
257
+ const result: UpsertCandidatesResult = await InsightStore.upsertCandidates({
258
+ projectId,
259
+ candidates: [
260
+ makeCandidate({ fingerprint: "first" }),
261
+ makeCandidate({ fingerprint: "second" }),
262
+ ],
263
+ now,
264
+ });
265
+
266
+ expect(result.created).toHaveLength(1);
267
+ expect(result.created[0]?.fingerprint).toBe("second");
268
+ });
269
+
270
+ test("a failed create does not consume the per-scan cap — later candidates still fill it", async () => {
271
+ mockFindOneBy(null);
272
+ jest
273
+ .spyOn(AIInsightService, "create")
274
+ .mockImplementation((createBy: CreateBy<AIInsight>) => {
275
+ const model: AIInsight = createBy.data;
276
+ if (model.fingerprint === "fp-2") {
277
+ return Promise.reject(new Error("transient"));
278
+ }
279
+ model.id = ObjectID.generate();
280
+ return Promise.resolve(model);
281
+ });
282
+
283
+ /*
284
+ * Cap + 1 candidates with one failure: exactly cap creates succeed and
285
+ * nothing is counted as dropped — the failure freed a cap slot.
286
+ */
287
+ const candidates: Array<InsightCandidate> = [];
288
+ for (
289
+ let i: number = 0;
290
+ i < MAX_NEW_INSIGHTS_PER_PROJECT_PER_SCAN + 1;
291
+ i++
292
+ ) {
293
+ candidates.push(makeCandidate({ fingerprint: `fp-${i}` }));
294
+ }
295
+
296
+ const result: UpsertCandidatesResult = await InsightStore.upsertCandidates({
297
+ projectId,
298
+ candidates,
299
+ now,
300
+ });
301
+
302
+ expect(result.created).toHaveLength(MAX_NEW_INSIGHTS_PER_PROJECT_PER_SCAN);
303
+ expect(result.droppedByCap).toBe(0);
304
+ });
305
+ });
306
+
307
+ describe("InsightStore — same-fingerprint duplicates (batch and race)", () => {
308
+ afterEach(() => {
309
+ jest.restoreAllMocks();
310
+ });
311
+
312
+ test("two same-fingerprint candidates in ONE batch: the second refreshes the row the first created (DB-faithful lookup)", async () => {
313
+ const rowsByFingerprint: Map<string, AIInsight> = new Map();
314
+
315
+ jest
316
+ .spyOn(AIInsightService, "findOneBy")
317
+ .mockImplementation((findOneBy: FindOneBy<AIInsight>) => {
318
+ const fingerprint: string = (
319
+ findOneBy.query as { fingerprint?: string }
320
+ ).fingerprint!;
321
+ return Promise.resolve(rowsByFingerprint.get(fingerprint) || null);
322
+ });
323
+ jest
324
+ .spyOn(AIInsightService, "create")
325
+ .mockImplementation((createBy: CreateBy<AIInsight>) => {
326
+ const model: AIInsight = createBy.data;
327
+ model.id = ObjectID.generate();
328
+ rowsByFingerprint.set(model.fingerprint!, model);
329
+ return Promise.resolve(model);
330
+ });
331
+ const update: jest.SpyInstance = mockUpdateOneById();
332
+
333
+ const result: UpsertCandidatesResult = await InsightStore.upsertCandidates({
334
+ projectId,
335
+ candidates: [
336
+ makeCandidate({ fingerprint: "shared" }),
337
+ makeCandidate({ fingerprint: "shared" }),
338
+ ],
339
+ now,
340
+ });
341
+
342
+ expect(result.created).toHaveLength(1);
343
+ expect(result.refreshed).toBe(1);
344
+ expect(update).toHaveBeenCalledTimes(1);
345
+ });
346
+
347
+ test("PINNED: when the lookup misses for both (concurrent-scan race), the store creates duplicates — there is no DB-level uniqueness guard", async () => {
348
+ /*
349
+ * (projectId, fingerprint) is deliberately NOT unique (terminal rows
350
+ * accumulate as history), so nothing below the store prevents two racing
351
+ * scans from double-creating. The operational guard is the single-flight
352
+ * cron (10-minute job timeout < 15-minute tick). If multi-instance
353
+ * workers ever run this job, a real dedupe guard must be added.
354
+ */
355
+ mockFindOneBy(null);
356
+ const create: jest.SpyInstance = mockCreate();
357
+
358
+ const result: UpsertCandidatesResult = await InsightStore.upsertCandidates({
359
+ projectId,
360
+ candidates: [
361
+ makeCandidate({ fingerprint: "raced" }),
362
+ makeCandidate({ fingerprint: "raced" }),
363
+ ],
364
+ now,
365
+ });
366
+
367
+ expect(create).toHaveBeenCalledTimes(2);
368
+ expect(result.created).toHaveLength(2);
369
+ });
370
+ });
@@ -0,0 +1,210 @@
1
+ import InsightTriage, {
2
+ InsightTriageResult,
3
+ } from "../../../../../Server/Utils/AI/SRE/Insights/Triage";
4
+ import AIInvestigationQueue from "../../../../../Server/Utils/AI/SRE/InvestigationQueue";
5
+ import ProjectService from "../../../../../Server/Services/ProjectService";
6
+ import LlmProviderService from "../../../../../Server/Services/LlmProviderService";
7
+ import AIRunService from "../../../../../Server/Services/AIRunService";
8
+ import AIInsightService from "../../../../../Server/Services/AIInsightService";
9
+ import AIInsight from "../../../../../Models/DatabaseModels/AIInsight";
10
+ import Project from "../../../../../Models/DatabaseModels/Project";
11
+ import LlmProvider from "../../../../../Models/DatabaseModels/LlmProvider";
12
+ import AIRunType from "../../../../../Types/AI/AIRunType";
13
+ import ObjectID from "../../../../../Types/ObjectID";
14
+ import PositiveNumber from "../../../../../Types/PositiveNumber";
15
+ import { describe, expect, test, afterEach } from "@jest/globals";
16
+
17
+ /*
18
+ * Per-insight LLM triage enqueue. The invariants these tests lock in:
19
+ * (a) the gates mirror the engine's enablement posture: enableAi must not
20
+ * be false, Project.enableAiInsights must be EXACTLY true
21
+ * (strict opt-in, default false), and an LLM provider must exist —
22
+ * each miss is a quiet skip;
23
+ * (b) dedupe: at most one non-terminal triage run per insight (the
24
+ * scanner refreshes recurring insights every tick — refreshes must
25
+ * not fan out into duplicate runs);
26
+ * (c) the happy path enqueues with subjectAIInsightId (so the
27
+ * queue stamps triggeredByAiInsightId and dispatch routes to
28
+ * the triage runner) and persists triageAiRunId onto the insight;
29
+ * (d) a null enqueue result (the queue's budget quiet-skip) means no
30
+ * link is written and no id is returned;
31
+ * (e) enqueueInsightTriage NEVER throws.
32
+ */
33
+
34
+ const projectId: ObjectID = ObjectID.generate();
35
+ const insightId: ObjectID = ObjectID.generate();
36
+ const triageRunId: ObjectID = ObjectID.generate();
37
+
38
+ function makeInsight(): AIInsight {
39
+ return { id: insightId, projectId } as unknown as AIInsight;
40
+ }
41
+
42
+ function mockProject(
43
+ overrides: Record<string, unknown> = {},
44
+ ): jest.SpyInstance {
45
+ return jest.spyOn(ProjectService, "findOneById").mockResolvedValue({
46
+ id: projectId,
47
+ enableAiInsights: true,
48
+ ...overrides,
49
+ } as unknown as Project);
50
+ }
51
+
52
+ function mockProvider(exists: boolean): jest.SpyInstance {
53
+ return jest
54
+ .spyOn(LlmProviderService, "getLLMProviderForProject")
55
+ .mockResolvedValue(
56
+ exists ? ({ id: ObjectID.generate() } as unknown as LlmProvider) : null,
57
+ );
58
+ }
59
+
60
+ function mockNonTerminalTriageRunCount(count: number): jest.SpyInstance {
61
+ return jest
62
+ .spyOn(AIRunService, "countBy")
63
+ .mockResolvedValue(new PositiveNumber(count));
64
+ }
65
+
66
+ describe("InsightTriage.enqueueInsightTriage", () => {
67
+ afterEach(() => {
68
+ jest.restoreAllMocks();
69
+ });
70
+
71
+ test("skips when the project is not found", async () => {
72
+ jest.spyOn(ProjectService, "findOneById").mockResolvedValue(null);
73
+ const enqueue: jest.SpyInstance = jest.spyOn(
74
+ AIInvestigationQueue,
75
+ "enqueue",
76
+ );
77
+
78
+ const result: InsightTriageResult =
79
+ await InsightTriage.enqueueInsightTriage({ insight: makeInsight() });
80
+
81
+ expect(result).toEqual({});
82
+ expect(enqueue).not.toHaveBeenCalled();
83
+ });
84
+
85
+ test("skips when AI is disabled for the project", async () => {
86
+ mockProject({ enableAi: false });
87
+ const enqueue: jest.SpyInstance = jest.spyOn(
88
+ AIInvestigationQueue,
89
+ "enqueue",
90
+ );
91
+
92
+ const result: InsightTriageResult =
93
+ await InsightTriage.enqueueInsightTriage({ insight: makeInsight() });
94
+
95
+ expect(result).toEqual({});
96
+ expect(enqueue).not.toHaveBeenCalled();
97
+ });
98
+
99
+ test("skips unless enableAiInsights is EXACTLY true (strict opt-in)", async () => {
100
+ mockProject({ enableAiInsights: undefined });
101
+ const enqueue: jest.SpyInstance = jest.spyOn(
102
+ AIInvestigationQueue,
103
+ "enqueue",
104
+ );
105
+
106
+ const result: InsightTriageResult =
107
+ await InsightTriage.enqueueInsightTriage({ insight: makeInsight() });
108
+
109
+ expect(result).toEqual({});
110
+ expect(enqueue).not.toHaveBeenCalled();
111
+ });
112
+
113
+ test("skips quietly when no LLM provider is configured", async () => {
114
+ mockProject();
115
+ mockProvider(false);
116
+ const enqueue: jest.SpyInstance = jest.spyOn(
117
+ AIInvestigationQueue,
118
+ "enqueue",
119
+ );
120
+
121
+ const result: InsightTriageResult =
122
+ await InsightTriage.enqueueInsightTriage({ insight: makeInsight() });
123
+
124
+ expect(result).toEqual({});
125
+ expect(enqueue).not.toHaveBeenCalled();
126
+ });
127
+
128
+ test("dedupes: an existing non-terminal triage run for the insight blocks a second one", async () => {
129
+ mockProject();
130
+ mockProvider(true);
131
+ const countBy: jest.SpyInstance = mockNonTerminalTriageRunCount(1);
132
+ const enqueue: jest.SpyInstance = jest.spyOn(
133
+ AIInvestigationQueue,
134
+ "enqueue",
135
+ );
136
+
137
+ const result: InsightTriageResult =
138
+ await InsightTriage.enqueueInsightTriage({ insight: makeInsight() });
139
+
140
+ expect(result).toEqual({});
141
+ expect(enqueue).not.toHaveBeenCalled();
142
+ // The dedupe key is the provenance column, scoped to Investigation runs.
143
+ expect(countBy).toHaveBeenCalledWith(
144
+ expect.objectContaining({
145
+ query: expect.objectContaining({
146
+ runType: AIRunType.Investigation,
147
+ triggeredByAiInsightId: insightId,
148
+ }),
149
+ props: expect.objectContaining({ isRoot: true }),
150
+ }),
151
+ );
152
+ });
153
+
154
+ test("happy path: enqueues with subjectAIInsightId and persists triageAiRunId onto the insight", async () => {
155
+ mockProject();
156
+ mockProvider(true);
157
+ mockNonTerminalTriageRunCount(0);
158
+ const enqueue: jest.SpyInstance = jest
159
+ .spyOn(AIInvestigationQueue, "enqueue")
160
+ .mockResolvedValue(triageRunId);
161
+ const persist: jest.SpyInstance = jest
162
+ .spyOn(AIInsightService, "updateOneById")
163
+ .mockResolvedValue(undefined);
164
+
165
+ const result: InsightTriageResult =
166
+ await InsightTriage.enqueueInsightTriage({ insight: makeInsight() });
167
+
168
+ expect(result).toEqual({ triageAiRunId: triageRunId });
169
+ expect(enqueue).toHaveBeenCalledWith(
170
+ expect.objectContaining({
171
+ projectId,
172
+ subjectAIInsightId: insightId,
173
+ }),
174
+ );
175
+ expect(persist).toHaveBeenCalledWith(
176
+ expect.objectContaining({
177
+ id: insightId,
178
+ data: expect.objectContaining({ triageAiRunId: triageRunId }),
179
+ props: expect.objectContaining({ isRoot: true }),
180
+ }),
181
+ );
182
+ });
183
+
184
+ test("the queue's budget quiet-skip (null) means no link written and no id returned", async () => {
185
+ mockProject();
186
+ mockProvider(true);
187
+ mockNonTerminalTriageRunCount(0);
188
+ jest.spyOn(AIInvestigationQueue, "enqueue").mockResolvedValue(null);
189
+ const persist: jest.SpyInstance = jest.spyOn(
190
+ AIInsightService,
191
+ "updateOneById",
192
+ );
193
+
194
+ const result: InsightTriageResult =
195
+ await InsightTriage.enqueueInsightTriage({ insight: makeInsight() });
196
+
197
+ expect(result).toEqual({});
198
+ expect(persist).not.toHaveBeenCalled();
199
+ });
200
+
201
+ test("NEVER throws: a gate failure resolves to an empty result", async () => {
202
+ jest
203
+ .spyOn(ProjectService, "findOneById")
204
+ .mockRejectedValue(new Error("db down"));
205
+
206
+ await expect(
207
+ InsightTriage.enqueueInsightTriage({ insight: makeInsight() }),
208
+ ).resolves.toEqual({});
209
+ });
210
+ });