@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,293 @@
1
+ import ObjectID from "../../../../Types/ObjectID";
2
+ import { AIChatCitation } from "../../../../Types/AI/AIChatTypes";
3
+ import AIService, {
4
+ AILogResponse,
5
+ AI_CONFIDENCE_CLASSIFICATION_FEATURE,
6
+ } from "../../../Services/AIService";
7
+ import logger from "../../Logger";
8
+ import CaptureSpan from "../../Telemetry/CaptureSpan";
9
+
10
+ /*
11
+ * AI SRE — the structured, server-verified confidence signal (G6).
12
+ *
13
+ * The vision's §6 threat model forbids deriving control flow from free-form
14
+ * model prose: adversarial telemetry can steer what the model writes, so a
15
+ * regex over the analysis (the old INCONCLUSIVE_RE) was forgeable by prompt
16
+ * injection. This module replaces it with a two-part signal:
17
+ *
18
+ * 1. Deterministic evidence floor (pure, no LLM): computed from the run's
19
+ * OWN recorded tool activity. Citations are minted server-side from
20
+ * validated tool arguments — never by the model — so prose cannot fake
21
+ * evidence that was never minted. Zero citations AND zero data-bearing
22
+ * tool calls → INCONCLUSIVE, regardless of anything the analysis says.
23
+ *
24
+ * 2. Constrained classification (only when the floor passes): ONE metered
25
+ * LLM call (temperature 0, tiny token cap, word-bounded single-token
26
+ * parse — the InvestigationGrader idiom) asking whether the analysis
27
+ * asserts a specific, evidenced root cause or is inconclusive. The
28
+ * classifier sees the analysis as DATA and can only emit one of two
29
+ * tokens — it cannot be steered into an arbitrary control decision.
30
+ *
31
+ * FAIL DIRECTIONS ARE PER-CONSUMER, and that is the point of the structured
32
+ * result: `{confident, source}` lets each consumer choose its own safe
33
+ * degradation when the classification itself failed (unparseable response or
34
+ * the call errored). As implemented:
35
+ *
36
+ * | source | confident | workspace ping | instrumentation PR |
37
+ * |-----------------------|-----------|----------------|--------------------|
38
+ * | deterministic-floor | false | no (quiet) | yes (enqueue) |
39
+ * | classification | true | yes | no |
40
+ * | classification | false | no (quiet) | yes (enqueue) |
41
+ * | classification-failed | false (*) | YES — louder | NO — no PR |
42
+ *
43
+ * - The workspace ping treats classification-failed as CONFIDENT: quiet
44
+ * mode's fail direction is "louder, not silent" (vision §6) — a broken
45
+ * classifier must never suppress the on-call ping.
46
+ * - The instrumentation trigger treats classification-failed as
47
+ * NOT-inconclusive: autonomous PR creation (G11 posture) requires a
48
+ * POSITIVE, verified inconclusive verdict — "we don't know" must fail
49
+ * toward doing nothing.
50
+ * - (*) When source is "classification-failed" the `confident` boolean is
51
+ * a placeholder, NOT a verdict — consumers must route decisions through
52
+ * the helpers below, never through the raw boolean.
53
+ *
54
+ * Budget accounting: the classification call runs AFTER the investigation's
55
+ * agent loop has finished, so it is deliberately OUTSIDE the engine's per-run
56
+ * caps (MAX_LLM_CALLS / MAX_OUTPUT_TOKENS govern the loop, whose counts are
57
+ * persisted at the Completed transition before this call fires). It is still
58
+ * metered per-call in LlmLog and its feature is in AUTONOMOUS_AI_FEATURES, so
59
+ * the G4 daily autonomous token budget covers it — and a budget rejection
60
+ * degrades the signal to "classification-failed", never a run failure.
61
+ */
62
+
63
+ /*
64
+ * Persisted LlmLog label, and a member of AUTONOMOUS_AI_FEATURES (G4 budget).
65
+ * Owned by AIService so this writer and the budget match-list cannot drift —
66
+ * a drift would silently drop classification out of the budget forever.
67
+ */
68
+ export const CONFIDENCE_CLASSIFICATION_FEATURE: string =
69
+ AI_CONFIDENCE_CLASSIFICATION_FEATURE;
70
+
71
+ // Truncation cap keeps the classification call cheap and inside context limits.
72
+ const MAX_ANALYSIS_CHARS: number = 8000;
73
+
74
+ /*
75
+ * Word-bounded token matchers (hoisted: wrap-regex and prettier disagree
76
+ * inline). Word boundaries mean CONFIDENTLY / INCONCLUSIVELY do not parse.
77
+ */
78
+ const CONFIDENT_RE: RegExp = /\bCONFIDENT\b/;
79
+ const INCONCLUSIVE_RE: RegExp = /\bINCONCLUSIVE\b/;
80
+
81
+ export type ConfidenceSource =
82
+ // The evidence floor failed: zero server-minted evidence exists.
83
+ | "deterministic-floor"
84
+ // The constrained classification call returned exactly one valid token.
85
+ | "classification"
86
+ // The classification call errored or its response was unparseable.
87
+ | "classification-failed";
88
+
89
+ export interface ConfidenceSignal {
90
+ /*
91
+ * Whether the investigation asserted an evidenced root cause. NOT a verdict
92
+ * when source is "classification-failed" — use the decision helpers.
93
+ */
94
+ confident: boolean;
95
+ source: ConfidenceSource;
96
+ }
97
+
98
+ /*
99
+ * The deterministic inputs, derived from the run's own recorded tool activity
100
+ * (server-side state — the model never writes any of these numbers).
101
+ */
102
+ export interface EvidenceInput {
103
+ // Citations minted by the engine (one per successful tool call).
104
+ citationCount: number;
105
+ // Successful tool calls whose result carried at least one row of data.
106
+ dataBearingToolCallCount: number;
107
+ // Whether ANY tool returned non-empty data.
108
+ anyToolReturnedData: boolean;
109
+ }
110
+
111
+ export default class AIConfidenceSignal {
112
+ /*
113
+ * THE single definition of "data-bearing" (shared with the eval harness in
114
+ * Utils/AI/Eval): a tool result that carried at least one row of data.
115
+ * rowCount 0 is still server-verified evidence — proof of absence ("checked,
116
+ * found nothing") — but it is not data-BEARING. Both the live confidence
117
+ * floor (over minted citations) and the offline corpus derivation (over
118
+ * recorded AIRunEvent resultSummary.rowCount) route through this helper so
119
+ * the two can never drift apart.
120
+ */
121
+ public static isDataBearingRowCount(
122
+ rowCount: number | null | undefined,
123
+ ): boolean {
124
+ return (rowCount || 0) > 0;
125
+ }
126
+
127
+ // Derive the deterministic evidence inputs from the run's minted citations.
128
+ public static evidenceFromCitations(
129
+ citations: Array<AIChatCitation>,
130
+ ): EvidenceInput {
131
+ const dataBearingToolCallCount: number = citations.filter(
132
+ (citation: AIChatCitation) => {
133
+ return this.isDataBearingRowCount(citation.rowCount);
134
+ },
135
+ ).length;
136
+
137
+ return {
138
+ citationCount: citations.length,
139
+ dataBearingToolCallCount,
140
+ anyToolReturnedData: dataBearingToolCallCount > 0,
141
+ };
142
+ }
143
+
144
+ /*
145
+ * The deterministic floor (pure, exported for tests): zero citations AND
146
+ * zero successful data-bearing tool calls → no server-verified evidence
147
+ * exists, so the run is INCONCLUSIVE no matter what the prose claims.
148
+ * Prose cannot fake evidence that was never minted server-side.
149
+ */
150
+ public static hasVerifiableEvidence(evidence: EvidenceInput): boolean {
151
+ return (
152
+ evidence.citationCount > 0 ||
153
+ evidence.dataBearingToolCallCount > 0 ||
154
+ evidence.anyToolReturnedData
155
+ );
156
+ }
157
+
158
+ /*
159
+ * Defensive one-token parse (pure, exported for tests). The prompt demands
160
+ * exactly one token, but models editorialize — accept the verdict when
161
+ * exactly ONE of the two tokens appears, word-bounded. Both found, neither
162
+ * found, or empty → null (classification failed; per-consumer fail
163
+ * directions apply).
164
+ */
165
+ public static parseClassificationToken(
166
+ response: string | null | undefined,
167
+ ): boolean | null {
168
+ if (!response) {
169
+ return null;
170
+ }
171
+
172
+ const text: string = response.toUpperCase();
173
+
174
+ const isConfident: boolean = CONFIDENT_RE.test(text);
175
+ const isInconclusive: boolean = INCONCLUSIVE_RE.test(text);
176
+
177
+ if (isConfident === isInconclusive) {
178
+ // Both or neither → unparseable.
179
+ return null;
180
+ }
181
+
182
+ return isConfident;
183
+ }
184
+
185
+ /*
186
+ * Consumer decision: should the analysis post ping the workspace/on-call?
187
+ * Fail direction: classification-failed → TRUE. Quiet mode fails LOUDER,
188
+ * not silent — a broken classifier must never suppress the ping (the old
189
+ * regex's fail direction, kept deliberately).
190
+ */
191
+ public static shouldSendWorkspaceNotification(
192
+ signal: ConfidenceSignal,
193
+ ): boolean {
194
+ if (signal.source === "classification-failed") {
195
+ return true;
196
+ }
197
+
198
+ return signal.confident;
199
+ }
200
+
201
+ /*
202
+ * Consumer decision: should an ImproveInstrumentation fix task be enqueued
203
+ * (opted-in projects only — the trigger has its own gates)? Requires a
204
+ * POSITIVE inconclusive verdict: either the deterministic floor proved no
205
+ * evidence exists, or the classification said INCONCLUSIVE. Fail direction:
206
+ * classification-failed → FALSE — autonomous PR creation fails toward
207
+ * doing nothing (G11 posture).
208
+ */
209
+ public static shouldEnqueueInstrumentationTask(
210
+ signal: ConfidenceSignal,
211
+ ): boolean {
212
+ if (signal.source === "classification-failed") {
213
+ return false;
214
+ }
215
+
216
+ return !signal.confident;
217
+ }
218
+
219
+ /*
220
+ * Compute the full signal: deterministic floor first (no LLM call when it
221
+ * fails), then one constrained classification call. NEVER throws — an
222
+ * errored or unparseable classification returns "classification-failed"
223
+ * and each consumer applies its own fail direction.
224
+ */
225
+ @CaptureSpan()
226
+ public static async computeConfidenceSignal(data: {
227
+ projectId: ObjectID;
228
+ aiRunId: ObjectID;
229
+ analysisMarkdown: string;
230
+ evidence: EvidenceInput;
231
+ }): Promise<ConfidenceSignal> {
232
+ if (!this.hasVerifiableEvidence(data.evidence)) {
233
+ /*
234
+ * No server-minted evidence exists — inconclusive by construction,
235
+ * regardless of the prose. No classification call is spent.
236
+ */
237
+ return { confident: false, source: "deterministic-floor" };
238
+ }
239
+
240
+ try {
241
+ const response: AILogResponse = await AIService.executeWithLogging({
242
+ projectId: data.projectId,
243
+ feature: CONFIDENCE_CLASSIFICATION_FEATURE,
244
+ aiRunId: data.aiRunId,
245
+ // The verdict drives control flow; no prompt previews in LlmLog.
246
+ storeContentPreviews: false,
247
+ temperature: 0,
248
+ maxTokens: 20,
249
+ messages: [
250
+ {
251
+ role: "system",
252
+ content: [
253
+ "You judge an AI incident investigation's own analysis.",
254
+ "Does this analysis assert a specific root cause with supporting evidence, or is it inconclusive?",
255
+ "Reply with exactly one token and nothing else:",
256
+ "CONFIDENT — the analysis asserts a specific root cause with supporting evidence.",
257
+ "INCONCLUSIVE — the analysis could not determine a cause, or asserts one without supporting evidence.",
258
+ ].join("\n"),
259
+ },
260
+ {
261
+ role: "user",
262
+ content: [
263
+ "AI investigation analysis:",
264
+ '"""',
265
+ data.analysisMarkdown.substring(0, MAX_ANALYSIS_CHARS),
266
+ '"""',
267
+ "",
268
+ "One token only: CONFIDENT or INCONCLUSIVE.",
269
+ ].join("\n"),
270
+ },
271
+ ],
272
+ });
273
+
274
+ const verdict: boolean | null = this.parseClassificationToken(
275
+ response.content,
276
+ );
277
+
278
+ if (verdict === null) {
279
+ logger.warn(
280
+ `AI confidence: unparseable classification response for run ${data.aiRunId.toString()} — per-consumer fail directions apply.`,
281
+ );
282
+ return { confident: false, source: "classification-failed" };
283
+ }
284
+
285
+ return { confident: verdict, source: "classification" };
286
+ } catch (error) {
287
+ logger.error(
288
+ `AI confidence: classification call failed for run ${data.aiRunId.toString()} — per-consumer fail directions apply: ${error}`,
289
+ );
290
+ return { confident: false, source: "classification-failed" };
291
+ }
292
+ }
293
+ }
@@ -0,0 +1,115 @@
1
+ import ObjectID from "../../../../Types/ObjectID";
2
+ import AIRunType from "../../../../Types/AI/AIRunType";
3
+ import AIRunStatus from "../../../../Types/AI/AIRunStatus";
4
+ import CodeFixTaskType from "../../../../Types/AI/CodeFixTaskType";
5
+ import BadDataException from "../../../../Types/Exception/BadDataException";
6
+ import AIRun from "../../../../Models/DatabaseModels/AIRun";
7
+ import AIRunService from "../../../Services/AIRunService";
8
+ import SubjectCodeFixRun from "./SubjectCodeFixRun";
9
+ import CaptureSpan from "../../Telemetry/CaptureSpan";
10
+
11
+ /*
12
+ * AI SRE — the FixFromIncident trigger (the roadmap's headline `code_fix`
13
+ * capability, vision §4.8, in human-triggered form).
14
+ *
15
+ * After a AI investigation posts a root-cause analysis on an incident
16
+ * or alert, the user can click "Open Fix PR from this analysis" on the
17
+ * investigation panel: the agent takes the posted analysis (the RootCause
18
+ * feed item) as its entire context and opens a fix pull request. Unlike the
19
+ * ImproveInstrumentation sibling this is NOT automatic — a human reads the
20
+ * analysis and decides a fix PR is worth opening, so no project opt-in flag
21
+ * is needed: the human in the loop IS the gate (G11 posture preserved).
22
+ *
23
+ * And unlike InstrumentationTaskTrigger (fire-and-forget inside the
24
+ * investigation's postAnalysis, never throws), this runs inside a
25
+ * user-facing endpoint (POST /ai-investigation/create-fix-task) and FAILS
26
+ * EARLY with a clear message when a gate is not met.
27
+ */
28
+ export default class FixFromIncidentTaskTrigger {
29
+ /*
30
+ * Gate and enqueue a FixFromIncident CodeFix run for the subject. The
31
+ * caller must already have access-checked the subject under the USER's
32
+ * permissions — this method reads and writes as root. Exactly one of
33
+ * incidentId/alertId is expected; userId is the clicking user
34
+ * (attribution on the run).
35
+ *
36
+ * Throws BadDataException naming the failed gate: no completed
37
+ * investigation, no GitHub-App repository, or a duplicate active run.
38
+ */
39
+ @CaptureSpan()
40
+ public static async createFixTaskFromInvestigation(data: {
41
+ projectId: ObjectID;
42
+ incidentId?: ObjectID | undefined;
43
+ alertId?: ObjectID | undefined;
44
+ userId: ObjectID;
45
+ }): Promise<AIRun> {
46
+ if (!data.incidentId && !data.alertId) {
47
+ throw new BadDataException(
48
+ "An incident or alert subject is required to create a fix task.",
49
+ );
50
+ }
51
+
52
+ const subjectLabel: "incident" | "alert" = data.incidentId
53
+ ? "incident"
54
+ : "alert";
55
+
56
+ /*
57
+ * Gate 1: a COMPLETED investigation must exist for the subject — its
58
+ * posted analysis (the RootCause feed item) is the fix task's entire
59
+ * context. Without one the worker would have nothing to work from.
60
+ */
61
+ const completedInvestigation: AIRun | null = await AIRunService.findOneBy({
62
+ query: {
63
+ runType: AIRunType.Investigation,
64
+ status: AIRunStatus.Completed,
65
+ ...(data.incidentId
66
+ ? { triggeredByIncidentId: data.incidentId }
67
+ : { triggeredByAlertId: data.alertId! }),
68
+ },
69
+ select: { _id: true },
70
+ props: { isRoot: true },
71
+ });
72
+
73
+ if (!completedInvestigation) {
74
+ throw new BadDataException(
75
+ `No completed AI investigation exists for this ${subjectLabel} — the fix task uses the investigation's posted analysis as its context. Wait for the investigation to complete, or enable AI investigations in the AI settings.`,
76
+ );
77
+ }
78
+
79
+ // Gate 2: a repository the agent can actually open a PR against.
80
+ const hasConnectedRepository: boolean =
81
+ await SubjectCodeFixRun.hasGitHubAppConnectedRepository(data.projectId);
82
+
83
+ if (!hasConnectedRepository) {
84
+ throw new BadDataException(
85
+ "No GitHub-App-connected repository exists for this project, so the agent has nowhere to open the fix pull request. Connect one under AI > Code Repositories.",
86
+ );
87
+ }
88
+
89
+ /*
90
+ * Gate 3: per-subject dedupe — at most one non-terminal FixFromIncident
91
+ * run per incident/alert (repeated clicks must not fan out into
92
+ * duplicate PRs).
93
+ */
94
+ const existingRun: AIRun | null =
95
+ await SubjectCodeFixRun.findNonTerminalRunForSubject({
96
+ taskType: CodeFixTaskType.FixFromIncident,
97
+ incidentId: data.incidentId,
98
+ alertId: data.alertId,
99
+ });
100
+
101
+ if (existingRun) {
102
+ throw new BadDataException(
103
+ `A fix pull request task is already queued or running for this ${subjectLabel}. Track its progress on the AI > Tasks page.`,
104
+ );
105
+ }
106
+
107
+ return SubjectCodeFixRun.enqueueSubjectCodeFixRun({
108
+ projectId: data.projectId,
109
+ taskType: CodeFixTaskType.FixFromIncident,
110
+ incidentId: data.incidentId,
111
+ alertId: data.alertId,
112
+ userId: data.userId,
113
+ });
114
+ }
115
+ }
@@ -0,0 +1,223 @@
1
+ import ObjectID from "../../../../Types/ObjectID";
2
+ import CodeFixTaskType from "../../../../Types/AI/CodeFixTaskType";
3
+ import CodeFixTaskContext, {
4
+ PerformanceCodeLocation,
5
+ PerformanceFinding,
6
+ } from "../../../../Types/AI/CodeFixTaskContext";
7
+ import BadDataException from "../../../../Types/Exception/BadDataException";
8
+ import AIRun from "../../../../Models/DatabaseModels/AIRun";
9
+ import SpanTreeAnalyzer, {
10
+ AnalyzableSpan,
11
+ } from "../PerfEvidence/SpanTreeAnalyzer";
12
+ import SubjectCodeFixRun from "./SubjectCodeFixRun";
13
+ import CaptureSpan from "../../Telemetry/CaptureSpan";
14
+
15
+ /*
16
+ * AI SRE — the FixPerformance trigger: from a slow trace, one click opens
17
+ * a performance-fix pull request grounded in the actual span-tree evidence.
18
+ *
19
+ * The gate that makes this recipe honest is DETERMINISTIC: the
20
+ * SpanTreeAnalyzer must find a mechanical performance pattern (N+1,
21
+ * dominant span, sequential-that-could-be-parallel) in the trace's spans,
22
+ * or the task is refused — the agent never goes hunting for "something
23
+ * slow" on vibes. Like FixFromIncident (b4) this is human-triggered from a
24
+ * user-facing endpoint (POST /ai-investigation/create-performance-fix-task),
25
+ * so there is no project opt-in flag — the human in the loop IS the gate —
26
+ * and every unmet gate FAILS EARLY with a clear message.
27
+ *
28
+ * The findings (plus best-effort service attribution and code.* locations
29
+ * for repository resolution) are serialized into AIRun.taskContext at
30
+ * enqueue time: ClickHouse span retention is short, so by the time the
31
+ * worker claims the run the spans may be gone. The stored evidence IS the
32
+ * task's context.
33
+ */
34
+
35
+ // Max code.* locations stored — mirrors the resolver's own candidate cap.
36
+ const MAX_CODE_LOCATIONS: number = 10;
37
+
38
+ export default class FixPerformanceTaskTrigger {
39
+ /*
40
+ * Collect code.filepath/code.function/code.lineno (and their newer
41
+ * semconv spellings) from the spans a finding implicates, so the
42
+ * task-details endpoint can attempt stack-trace-style repository
43
+ * resolution. Best-effort: most instrumentations do not stamp code
44
+ * attributes on client spans, and an empty result just means the
45
+ * resolver falls back to name-match / only-repository.
46
+ */
47
+ public static collectCodeLocations(
48
+ spans: Array<AnalyzableSpan>,
49
+ findings: Array<PerformanceFinding>,
50
+ ): Array<PerformanceCodeLocation> {
51
+ const implicatedSpanIds: Set<string> = new Set();
52
+
53
+ for (const finding of findings) {
54
+ for (const implicated of finding.implicatedSpans) {
55
+ implicatedSpanIds.add(implicated.spanId);
56
+ }
57
+ }
58
+
59
+ const locations: Array<PerformanceCodeLocation> = [];
60
+ const seenFilePaths: Set<string> = new Set();
61
+
62
+ for (const span of spans) {
63
+ if (!implicatedSpanIds.has(span.spanId) || !span.attributes) {
64
+ continue;
65
+ }
66
+
67
+ const filePath: string | undefined =
68
+ span.attributes["code.filepath"] || span.attributes["code.file.path"];
69
+
70
+ if (!filePath || seenFilePaths.has(filePath)) {
71
+ continue;
72
+ }
73
+
74
+ seenFilePaths.add(filePath);
75
+
76
+ const functionName: string | undefined =
77
+ span.attributes["code.function"] ||
78
+ span.attributes["code.function.name"];
79
+
80
+ const rawLineNumber: string | undefined =
81
+ span.attributes["code.lineno"] || span.attributes["code.line.number"];
82
+ const lineNumber: number = rawLineNumber
83
+ ? parseInt(rawLineNumber, 10)
84
+ : NaN;
85
+
86
+ locations.push({
87
+ filePath,
88
+ functionName,
89
+ lineNumber: Number.isFinite(lineNumber) ? lineNumber : undefined,
90
+ });
91
+
92
+ if (locations.length >= MAX_CODE_LOCATIONS) {
93
+ break;
94
+ }
95
+ }
96
+
97
+ return locations;
98
+ }
99
+
100
+ /*
101
+ * Gate and enqueue a FixPerformance CodeFix run for a trace. The caller
102
+ * must already have loaded the spans under the USER's telemetry-read
103
+ * permissions (the access check) — this method reads and writes as root.
104
+ *
105
+ * Throws BadDataException naming the failed gate: no deterministic
106
+ * finding, no GitHub-App repository, or a duplicate active run for the
107
+ * same trace.
108
+ */
109
+ @CaptureSpan()
110
+ public static async createPerformanceFixTaskFromTrace(data: {
111
+ projectId: ObjectID;
112
+ traceId: string;
113
+ spans: Array<AnalyzableSpan>;
114
+ serviceName?: string | undefined;
115
+ userId: ObjectID;
116
+ }): Promise<AIRun> {
117
+ if (!data.traceId) {
118
+ throw new BadDataException(
119
+ "A traceId is required to create a performance fix task.",
120
+ );
121
+ }
122
+
123
+ if (data.spans.length === 0) {
124
+ throw new BadDataException(
125
+ "This trace has no spans to analyze (or you do not have access to them).",
126
+ );
127
+ }
128
+
129
+ /*
130
+ * Gate 1 — the deterministic evidence gate, and the recipe's whole
131
+ * point: no mechanical pattern in the span tree means no fix task.
132
+ * This gate lives HERE, not in the findings entry point below: callers
133
+ * of that entry point (insight fix routing) hand over findings that
134
+ * were already computed — and gated on — at detect time.
135
+ */
136
+ const findings: Array<PerformanceFinding> = SpanTreeAnalyzer.analyzeTrace(
137
+ data.spans,
138
+ );
139
+
140
+ if (findings.length === 0) {
141
+ throw new BadDataException(
142
+ "No deterministic performance pattern was found in this trace. The analyzer looks for N+1 patterns (5+ near-identical sibling spans), a dominant slow span (60%+ of the trace), and sequential same-operation siblings that could run in parallel (3+, 50%+ of their parent) — none matched, so the AI agent has no grounded evidence to fix.",
143
+ );
144
+ }
145
+
146
+ return this.createPerformanceFixTaskFromFindings({
147
+ projectId: data.projectId,
148
+ traceId: data.traceId,
149
+ serviceName: data.serviceName,
150
+ findings,
151
+ codeLocations: this.collectCodeLocations(data.spans, findings),
152
+ userId: data.userId,
153
+ });
154
+ }
155
+
156
+ /*
157
+ * The findings-based entry point: gate and enqueue a FixPerformance run
158
+ * for ALREADY-COMPUTED deterministic findings (the spans path above after
159
+ * its analyzer gate, and AI insight fix routing whose findings were
160
+ * drilled — and stored as evidence — at detect time, because the spans
161
+ * are likely gone by now). `userId` is attribution for human-triggered
162
+ * callers; automatic triggers pass none and the run stays system-authored.
163
+ *
164
+ * Throws BadDataException naming the failed gate: no GitHub-App
165
+ * repository, a duplicate active run for the same trace, or (via
166
+ * enqueueSubjectCodeFixRun) the daily fix-run budget.
167
+ */
168
+ @CaptureSpan()
169
+ public static async createPerformanceFixTaskFromFindings(data: {
170
+ projectId: ObjectID;
171
+ traceId: string;
172
+ serviceName?: string | undefined;
173
+ findings: Array<PerformanceFinding>;
174
+ codeLocations: Array<PerformanceCodeLocation>;
175
+ userId?: ObjectID | undefined;
176
+ }): Promise<AIRun> {
177
+ if (!data.traceId) {
178
+ throw new BadDataException(
179
+ "A traceId is required to create a performance fix task.",
180
+ );
181
+ }
182
+
183
+ // Gate — a repository the agent can actually open a PR against.
184
+ const hasConnectedRepository: boolean =
185
+ await SubjectCodeFixRun.hasGitHubAppConnectedRepository(data.projectId);
186
+
187
+ if (!hasConnectedRepository) {
188
+ throw new BadDataException(
189
+ "No GitHub-App-connected repository exists for this project, so the agent has nowhere to open the performance-fix pull request. Connect one under AI > Code Repositories.",
190
+ );
191
+ }
192
+
193
+ /*
194
+ * Gate — per-trace dedupe: at most one non-terminal FixPerformance
195
+ * run per trace (repeated clicks must not fan out into duplicate PRs).
196
+ */
197
+ const existingRun: AIRun | null =
198
+ await SubjectCodeFixRun.findNonTerminalPerformanceFixRunForTrace({
199
+ projectId: data.projectId,
200
+ traceId: data.traceId,
201
+ });
202
+
203
+ if (existingRun) {
204
+ throw new BadDataException(
205
+ "A performance fix task is already queued or running for this trace. Track its progress on the AI > Tasks page.",
206
+ );
207
+ }
208
+
209
+ const taskContext: CodeFixTaskContext = {
210
+ traceId: data.traceId,
211
+ serviceName: data.serviceName,
212
+ performanceFindings: data.findings,
213
+ codeLocations: data.codeLocations,
214
+ };
215
+
216
+ return SubjectCodeFixRun.enqueueSubjectCodeFixRun({
217
+ projectId: data.projectId,
218
+ taskType: CodeFixTaskType.FixPerformance,
219
+ userId: data.userId,
220
+ taskContext,
221
+ });
222
+ }
223
+ }