@triedotdev/mcp 1.0.169 → 1.0.171

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 (145) hide show
  1. package/README.md +62 -540
  2. package/dist/chunk-2YXOBNKW.js +619 -0
  3. package/dist/chunk-2YXOBNKW.js.map +1 -0
  4. package/dist/chunk-QR64Y5TI.js +363 -0
  5. package/dist/chunk-QR64Y5TI.js.map +1 -0
  6. package/dist/cli/main.d.ts +0 -15
  7. package/dist/cli/main.js +356 -3098
  8. package/dist/cli/main.js.map +1 -1
  9. package/dist/index.js +2 -34
  10. package/dist/index.js.map +1 -1
  11. package/dist/server/mcp-server.js +2 -34
  12. package/package.json +8 -31
  13. package/dist/autonomy-config-FSERX3O3.js +0 -30
  14. package/dist/autonomy-config-FSERX3O3.js.map +0 -1
  15. package/dist/chat-store-JNGNTDSN.js +0 -15
  16. package/dist/chat-store-JNGNTDSN.js.map +0 -1
  17. package/dist/chunk-2HF65EHQ.js +0 -311
  18. package/dist/chunk-2HF65EHQ.js.map +0 -1
  19. package/dist/chunk-3XR6WVAW.js +0 -4011
  20. package/dist/chunk-3XR6WVAW.js.map +0 -1
  21. package/dist/chunk-43X6JBEM.js +0 -36
  22. package/dist/chunk-43X6JBEM.js.map +0 -1
  23. package/dist/chunk-6NLHFIYA.js +0 -344
  24. package/dist/chunk-6NLHFIYA.js.map +0 -1
  25. package/dist/chunk-7IO4YUI3.js +0 -1827
  26. package/dist/chunk-7IO4YUI3.js.map +0 -1
  27. package/dist/chunk-AHD2CBQ7.js +0 -846
  28. package/dist/chunk-AHD2CBQ7.js.map +0 -1
  29. package/dist/chunk-BUTOP5EB.js +0 -931
  30. package/dist/chunk-BUTOP5EB.js.map +0 -1
  31. package/dist/chunk-DGUM43GV.js +0 -11
  32. package/dist/chunk-DGUM43GV.js.map +0 -1
  33. package/dist/chunk-EFWVF6TI.js +0 -267
  34. package/dist/chunk-EFWVF6TI.js.map +0 -1
  35. package/dist/chunk-F6WFNUAY.js +0 -216
  36. package/dist/chunk-F6WFNUAY.js.map +0 -1
  37. package/dist/chunk-FBNURWRY.js +0 -662
  38. package/dist/chunk-FBNURWRY.js.map +0 -1
  39. package/dist/chunk-FQ45QP5A.js +0 -361
  40. package/dist/chunk-FQ45QP5A.js.map +0 -1
  41. package/dist/chunk-FVRO5RN3.js +0 -1306
  42. package/dist/chunk-FVRO5RN3.js.map +0 -1
  43. package/dist/chunk-G2TGF6TR.js +0 -573
  44. package/dist/chunk-G2TGF6TR.js.map +0 -1
  45. package/dist/chunk-G3I7SZLW.js +0 -354
  46. package/dist/chunk-G3I7SZLW.js.map +0 -1
  47. package/dist/chunk-GTKYBOXL.js +0 -700
  48. package/dist/chunk-GTKYBOXL.js.map +0 -1
  49. package/dist/chunk-HVCDY3AK.js +0 -850
  50. package/dist/chunk-HVCDY3AK.js.map +0 -1
  51. package/dist/chunk-I2O5OYQT.js +0 -727
  52. package/dist/chunk-I2O5OYQT.js.map +0 -1
  53. package/dist/chunk-JVMBCWKS.js +0 -348
  54. package/dist/chunk-JVMBCWKS.js.map +0 -1
  55. package/dist/chunk-KCUOWRPX.js +0 -816
  56. package/dist/chunk-KCUOWRPX.js.map +0 -1
  57. package/dist/chunk-KDHN2ZQE.js +0 -313
  58. package/dist/chunk-KDHN2ZQE.js.map +0 -1
  59. package/dist/chunk-ME2OERF5.js +0 -345
  60. package/dist/chunk-ME2OERF5.js.map +0 -1
  61. package/dist/chunk-OBQ74FOU.js +0 -27
  62. package/dist/chunk-OBQ74FOU.js.map +0 -1
  63. package/dist/chunk-Q5EKA5YA.js +0 -254
  64. package/dist/chunk-Q5EKA5YA.js.map +0 -1
  65. package/dist/chunk-Q63FFI6D.js +0 -132
  66. package/dist/chunk-Q63FFI6D.js.map +0 -1
  67. package/dist/chunk-SASNMSB5.js +0 -12597
  68. package/dist/chunk-SASNMSB5.js.map +0 -1
  69. package/dist/chunk-T63OHG4Q.js +0 -440
  70. package/dist/chunk-T63OHG4Q.js.map +0 -1
  71. package/dist/chunk-TN5WEKWI.js +0 -173
  72. package/dist/chunk-TN5WEKWI.js.map +0 -1
  73. package/dist/chunk-VUL52BQL.js +0 -402
  74. package/dist/chunk-VUL52BQL.js.map +0 -1
  75. package/dist/chunk-VVITXIHN.js +0 -189
  76. package/dist/chunk-VVITXIHN.js.map +0 -1
  77. package/dist/chunk-WCN7S3EI.js +0 -14
  78. package/dist/chunk-WCN7S3EI.js.map +0 -1
  79. package/dist/chunk-XPZZFPBZ.js +0 -491
  80. package/dist/chunk-XPZZFPBZ.js.map +0 -1
  81. package/dist/chunk-ZJF5FTBX.js +0 -1396
  82. package/dist/chunk-ZJF5FTBX.js.map +0 -1
  83. package/dist/chunk-ZV2K6M7T.js +0 -74
  84. package/dist/chunk-ZV2K6M7T.js.map +0 -1
  85. package/dist/cli/create-agent.d.ts +0 -1
  86. package/dist/cli/create-agent.js +0 -1050
  87. package/dist/cli/create-agent.js.map +0 -1
  88. package/dist/cli/yolo-daemon.d.ts +0 -1
  89. package/dist/cli/yolo-daemon.js +0 -421
  90. package/dist/cli/yolo-daemon.js.map +0 -1
  91. package/dist/client-NJPZE5JT.js +0 -28
  92. package/dist/client-NJPZE5JT.js.map +0 -1
  93. package/dist/codebase-index-VAPF32XX.js +0 -12
  94. package/dist/codebase-index-VAPF32XX.js.map +0 -1
  95. package/dist/fast-analyzer-3GCCZMLK.js +0 -216
  96. package/dist/fast-analyzer-3GCCZMLK.js.map +0 -1
  97. package/dist/git-EO5SRFMN.js +0 -28
  98. package/dist/git-EO5SRFMN.js.map +0 -1
  99. package/dist/github-ingester-ZOKK6GRS.js +0 -11
  100. package/dist/github-ingester-ZOKK6GRS.js.map +0 -1
  101. package/dist/goal-manager-QUKX2W6C.js +0 -25
  102. package/dist/goal-manager-QUKX2W6C.js.map +0 -1
  103. package/dist/goal-validator-2SFSKKVU.js +0 -24
  104. package/dist/goal-validator-2SFSKKVU.js.map +0 -1
  105. package/dist/graph-B3NA4S7I.js +0 -10
  106. package/dist/graph-B3NA4S7I.js.map +0 -1
  107. package/dist/hypothesis-KCPBR652.js +0 -23
  108. package/dist/hypothesis-KCPBR652.js.map +0 -1
  109. package/dist/incident-index-EFNUSGWL.js +0 -11
  110. package/dist/incident-index-EFNUSGWL.js.map +0 -1
  111. package/dist/insight-store-EC4PLSAW.js +0 -22
  112. package/dist/insight-store-EC4PLSAW.js.map +0 -1
  113. package/dist/issue-store-YAXTNRRY.js +0 -36
  114. package/dist/issue-store-YAXTNRRY.js.map +0 -1
  115. package/dist/ledger-TWZTGDFA.js +0 -58
  116. package/dist/ledger-TWZTGDFA.js.map +0 -1
  117. package/dist/linear-ingester-XXPAZZRW.js +0 -11
  118. package/dist/linear-ingester-XXPAZZRW.js.map +0 -1
  119. package/dist/output-manager-RVJ37XKA.js +0 -13
  120. package/dist/output-manager-RVJ37XKA.js.map +0 -1
  121. package/dist/parse-goal-violation-SACGFG3C.js +0 -8
  122. package/dist/parse-goal-violation-SACGFG3C.js.map +0 -1
  123. package/dist/pattern-discovery-F7LU5K6E.js +0 -8
  124. package/dist/pattern-discovery-F7LU5K6E.js.map +0 -1
  125. package/dist/progress-SRQ2V3BP.js +0 -18
  126. package/dist/progress-SRQ2V3BP.js.map +0 -1
  127. package/dist/project-state-AHPA77SM.js +0 -28
  128. package/dist/project-state-AHPA77SM.js.map +0 -1
  129. package/dist/sync-M2FSWPBC.js +0 -12
  130. package/dist/sync-M2FSWPBC.js.map +0 -1
  131. package/dist/terminal-spawn-5YXDMUCF.js +0 -157
  132. package/dist/terminal-spawn-5YXDMUCF.js.map +0 -1
  133. package/dist/tiered-storage-DYNC5CQ6.js +0 -13
  134. package/dist/tiered-storage-DYNC5CQ6.js.map +0 -1
  135. package/dist/trie-agent-I3HAHY2G.js +0 -26
  136. package/dist/trie-agent-I3HAHY2G.js.map +0 -1
  137. package/dist/ui/chat.html +0 -1014
  138. package/dist/ui/goals.html +0 -967
  139. package/dist/ui/hypotheses.html +0 -1011
  140. package/dist/ui/ledger.html +0 -954
  141. package/dist/ui/nudges.html +0 -995
  142. package/dist/vibe-code-signatures-5ZULYP3D.js +0 -987
  143. package/dist/vibe-code-signatures-5ZULYP3D.js.map +0 -1
  144. package/dist/vulnerability-signatures-2URZSXAQ.js +0 -983
  145. package/dist/vulnerability-signatures-2URZSXAQ.js.map +0 -1
@@ -1,1827 +0,0 @@
1
- import {
2
- getHypothesisEngine
3
- } from "./chunk-I2O5OYQT.js";
4
- import {
5
- getGoalManager
6
- } from "./chunk-FBNURWRY.js";
7
- import {
8
- getInsightStore
9
- } from "./chunk-T63OHG4Q.js";
10
- import {
11
- GotchaPredictor,
12
- SlackIntegration,
13
- findCrossProjectPatterns,
14
- recordToGlobalMemory
15
- } from "./chunk-AHD2CBQ7.js";
16
- import {
17
- ContextGraph
18
- } from "./chunk-VUL52BQL.js";
19
- import {
20
- getStorage
21
- } from "./chunk-BUTOP5EB.js";
22
- import {
23
- isAIAvailable,
24
- runAIAnalysis
25
- } from "./chunk-FQ45QP5A.js";
26
- import {
27
- autoResolveIssues,
28
- getHistoricalInsights,
29
- getIssueHash,
30
- searchIssues,
31
- storeIssues
32
- } from "./chunk-KCUOWRPX.js";
33
- import {
34
- getProjectState
35
- } from "./chunk-GTKYBOXL.js";
36
-
37
- // src/agent/trie-agent.ts
38
- import { basename as basename2 } from "path";
39
-
40
- // src/agent/risk-predictor.ts
41
- import { basename, dirname } from "path";
42
- var DEFAULT_CONFIG = {
43
- historyDays: 30,
44
- incidentThreshold: 3,
45
- riskWeights: {
46
- incidentCount: 0.35,
47
- recency: 0.25,
48
- severity: 0.2,
49
- complexity: 0.1,
50
- churn: 0.1
51
- }
52
- };
53
- var RiskPredictor = class {
54
- projectPath;
55
- config;
56
- insightStore;
57
- constructor(projectPath, config = {}) {
58
- this.projectPath = projectPath;
59
- this.config = { ...DEFAULT_CONFIG, ...config };
60
- this.insightStore = getInsightStore(projectPath);
61
- }
62
- /**
63
- * Calculate risk for a specific file or directory
64
- */
65
- async calculateRisk(target) {
66
- const factors = [];
67
- let totalRisk = 0;
68
- try {
69
- const issues = await searchIssues(target, {
70
- workDir: this.projectPath,
71
- limit: 500,
72
- includeResolved: true
73
- });
74
- const targetIssues = issues.filter(
75
- (r) => r.issue.file === target || r.issue.file.startsWith(target + "/") || dirname(r.issue.file) === target
76
- );
77
- const incidentCount = targetIssues.length;
78
- const incidentWeight = this.config.riskWeights.incidentCount;
79
- const incidentScore = Math.min(100, incidentCount * 10);
80
- factors.push({
81
- name: "Incident Count",
82
- weight: incidentWeight,
83
- value: incidentCount,
84
- description: `${incidentCount} historical incidents`,
85
- trend: this.calculateTrend(targetIssues.map((i) => i.issue))
86
- });
87
- totalRisk += incidentScore * incidentWeight;
88
- let recencyScore = 0;
89
- let lastIncidentDaysAgo;
90
- if (targetIssues.length > 0) {
91
- const latestIssue = targetIssues.sort((a, b) => new Date(b.issue.timestamp).getTime() - new Date(a.issue.timestamp).getTime())[0];
92
- if (latestIssue) {
93
- const daysSince = (Date.now() - new Date(latestIssue.issue.timestamp).getTime()) / (1e3 * 60 * 60 * 24);
94
- lastIncidentDaysAgo = Math.floor(daysSince);
95
- if (daysSince < 1) recencyScore = 100;
96
- else if (daysSince < 7) recencyScore = 80;
97
- else if (daysSince < 14) recencyScore = 60;
98
- else if (daysSince < 30) recencyScore = 40;
99
- else recencyScore = 20;
100
- }
101
- }
102
- factors.push({
103
- name: "Recency",
104
- weight: this.config.riskWeights.recency,
105
- value: lastIncidentDaysAgo ?? 999,
106
- description: lastIncidentDaysAgo !== void 0 ? `Last incident ${lastIncidentDaysAgo} days ago` : "No recent incidents"
107
- });
108
- totalRisk += recencyScore * this.config.riskWeights.recency;
109
- const criticalCount = targetIssues.filter((r) => r.issue.severity === "critical").length;
110
- const seriousCount = targetIssues.filter((r) => r.issue.severity === "serious").length;
111
- const severityScore = Math.min(100, criticalCount * 25 + seriousCount * 10);
112
- factors.push({
113
- name: "Severity",
114
- weight: this.config.riskWeights.severity,
115
- value: severityScore,
116
- description: `${criticalCount} critical, ${seriousCount} serious`
117
- });
118
- totalRisk += severityScore * this.config.riskWeights.severity;
119
- const uniqueAgents = new Set(targetIssues.map((r) => r.issue.agent)).size;
120
- const complexityScore = Math.min(100, uniqueAgents * 20);
121
- factors.push({
122
- name: "Complexity",
123
- weight: this.config.riskWeights.complexity,
124
- value: uniqueAgents,
125
- description: `Issues from ${uniqueAgents} different analysis types`
126
- });
127
- totalRisk += complexityScore * this.config.riskWeights.complexity;
128
- const uniqueDates = new Set(
129
- targetIssues.map((r) => r.issue.timestamp.split("T")[0])
130
- ).size;
131
- const churnScore = Math.min(100, uniqueDates * 10);
132
- factors.push({
133
- name: "Churn",
134
- weight: this.config.riskWeights.churn,
135
- value: uniqueDates,
136
- description: `Issues found on ${uniqueDates} different days`
137
- });
138
- totalRisk += churnScore * this.config.riskWeights.churn;
139
- const trend = this.calculateTrend(targetIssues.map((i) => i.issue));
140
- let predictedRisk = totalRisk;
141
- if (trend === "increasing") {
142
- predictedRisk = Math.min(100, totalRisk * 1.2);
143
- } else if (trend === "decreasing") {
144
- predictedRisk = Math.max(0, totalRisk * 0.8);
145
- }
146
- const recommendations = this.generateRecommendations(factors, totalRisk);
147
- const confidence = Math.min(0.95, 0.3 + incidentCount * 0.05);
148
- const prediction = {
149
- target,
150
- currentRisk: Math.round(totalRisk),
151
- predictedRisk: Math.round(predictedRisk),
152
- trend,
153
- factors,
154
- confidence,
155
- recommendations,
156
- incidentCount
157
- };
158
- if (lastIncidentDaysAgo !== void 0) {
159
- prediction.lastIncidentDaysAgo = lastIncidentDaysAgo;
160
- }
161
- return prediction;
162
- } catch (error) {
163
- console.error(`Failed to calculate risk for ${target}:`, error);
164
- return {
165
- target,
166
- currentRisk: 50,
167
- predictedRisk: 50,
168
- trend: "stable",
169
- factors: [],
170
- confidence: 0.1,
171
- recommendations: ["Unable to analyze - insufficient data"],
172
- incidentCount: 0
173
- };
174
- }
175
- }
176
- /**
177
- * Calculate trend from issues
178
- */
179
- calculateTrend(issues) {
180
- if (issues.length < 3) return "stable";
181
- const now = Date.now();
182
- const recentCutoff = now - 7 * 24 * 60 * 60 * 1e3;
183
- const olderCutoff = now - 30 * 24 * 60 * 60 * 1e3;
184
- const recentIssues = issues.filter((i) => new Date(i.timestamp).getTime() > recentCutoff).length;
185
- const olderIssues = issues.filter((i) => {
186
- const time = new Date(i.timestamp).getTime();
187
- return time > olderCutoff && time <= recentCutoff;
188
- }).length;
189
- const recentRate = recentIssues / 7;
190
- const olderRate = olderIssues / 23;
191
- if (recentRate > olderRate * 1.5) return "increasing";
192
- if (recentRate < olderRate * 0.5) return "decreasing";
193
- return "stable";
194
- }
195
- /**
196
- * Generate recommendations based on risk factors
197
- */
198
- generateRecommendations(factors, totalRisk) {
199
- const recommendations = [];
200
- if (totalRisk >= 70) {
201
- recommendations.push("Consider extra code review before merging changes");
202
- }
203
- const incidentFactor = factors.find((f) => f.name === "Incident Count");
204
- if (incidentFactor && incidentFactor.value >= 5) {
205
- recommendations.push("This area has recurring issues - consider refactoring");
206
- }
207
- const recencyFactor = factors.find((f) => f.name === "Recency");
208
- if (recencyFactor && recencyFactor.value < 7) {
209
- recommendations.push("Recent incident activity - monitor closely");
210
- }
211
- const severityFactor = factors.find((f) => f.name === "Severity");
212
- if (severityFactor && severityFactor.value >= 25) {
213
- recommendations.push("High severity issues present - prioritize fixes");
214
- }
215
- const complexityFactor = factors.find((f) => f.name === "Complexity");
216
- if (complexityFactor && complexityFactor.value >= 4) {
217
- recommendations.push("Multiple issue types - consider comprehensive review");
218
- }
219
- if (recommendations.length === 0) {
220
- recommendations.push("No specific concerns - maintain normal review process");
221
- }
222
- return recommendations;
223
- }
224
- /**
225
- * Predict risk trend for files that have recently changed
226
- */
227
- async predictRiskTrend(changedFiles) {
228
- const predictions = await Promise.all(
229
- changedFiles.map((f) => this.calculateRisk(f))
230
- );
231
- const highRiskFiles = predictions.filter((p) => p.currentRisk >= 50);
232
- const totalRisk = predictions.reduce((sum, p) => sum + p.currentRisk, 0) / Math.max(1, predictions.length);
233
- const trends = predictions.map((p) => p.trend);
234
- const increasingCount = trends.filter((t) => t === "increasing").length;
235
- const decreasingCount = trends.filter((t) => t === "decreasing").length;
236
- let overallTrend = "stable";
237
- if (increasingCount > decreasingCount + 1) {
238
- overallTrend = "increasing";
239
- } else if (decreasingCount > increasingCount + 1) {
240
- overallTrend = "decreasing";
241
- }
242
- const factors = highRiskFiles.map((p) => ({
243
- file: p.target,
244
- reasons: p.incidentCount > 0 ? ["past incidents", ...p.recommendations.slice(0, 2)] : ["no historical data"]
245
- }));
246
- return {
247
- trend: overallTrend,
248
- factors,
249
- overallRisk: Math.round(totalRisk)
250
- };
251
- }
252
- /**
253
- * Get project-wide risk summary
254
- */
255
- async getProjectRiskSummary() {
256
- try {
257
- const issues = await searchIssues("", {
258
- workDir: this.projectPath,
259
- limit: 1e3,
260
- includeResolved: true
261
- });
262
- const dirIssueCount = /* @__PURE__ */ new Map();
263
- for (const { issue } of issues) {
264
- const dir = dirname(issue.file);
265
- const existing = dirIssueCount.get(dir) || [];
266
- existing.push(issue);
267
- dirIssueCount.set(dir, existing);
268
- }
269
- const hotspotDirs = [...dirIssueCount.entries()].filter(([_, issues2]) => issues2.length >= this.config.incidentThreshold).sort((a, b) => b[1].length - a[1].length).slice(0, 5);
270
- const hotspots = await Promise.all(
271
- hotspotDirs.map(([dir]) => this.calculateRisk(dir))
272
- );
273
- const allDirs = [...dirIssueCount.keys()];
274
- const lowRiskPredictions = await Promise.all(
275
- allDirs.map((dir) => this.calculateRisk(dir))
276
- );
277
- const lowRiskAreas = lowRiskPredictions.filter((p) => p.currentRisk < 20 && p.incidentCount === 0).map((p) => p.target).slice(0, 5);
278
- const overallRisk = hotspots.length > 0 ? hotspots.reduce((sum, p) => sum + p.currentRisk, 0) / hotspots.length : 0;
279
- const trends = hotspots.map((p) => p.trend);
280
- const increasingCount = trends.filter((t) => t === "increasing").length;
281
- const decreasingCount = trends.filter((t) => t === "decreasing").length;
282
- let trend = "stable";
283
- if (increasingCount > decreasingCount) {
284
- trend = "increasing";
285
- } else if (decreasingCount > increasingCount) {
286
- trend = "decreasing";
287
- }
288
- const confidence = Math.min(0.9, 0.4 + issues.length * 1e-3);
289
- return {
290
- overallRisk: Math.round(overallRisk),
291
- trend,
292
- hotspots,
293
- lowRiskAreas,
294
- predictions: hotspots,
295
- confidence
296
- };
297
- } catch (error) {
298
- console.error("Failed to get project risk summary:", error);
299
- return {
300
- overallRisk: 0,
301
- trend: "stable",
302
- hotspots: [],
303
- lowRiskAreas: [],
304
- predictions: [],
305
- confidence: 0.1
306
- };
307
- }
308
- }
309
- /**
310
- * Create risk prediction insight
311
- */
312
- async generateRiskInsight() {
313
- if (!this.insightStore.canCreateInsight("risk-prediction")) {
314
- return null;
315
- }
316
- const summary = await this.getProjectRiskSummary();
317
- if (summary.hotspots.length === 0 || summary.overallRisk < 30) {
318
- return null;
319
- }
320
- const topHotspot = summary.hotspots[0];
321
- if (!topHotspot) return null;
322
- const trendMap = {
323
- "increasing": "worsening",
324
- "stable": "stable",
325
- "decreasing": "improving"
326
- };
327
- const insight = {
328
- id: `insight-risk-${Date.now()}`,
329
- type: "warning",
330
- message: `[!] ${basename(topHotspot.target)}/ has elevated risk (${topHotspot.currentRisk}/100)`,
331
- context: `${topHotspot.incidentCount} past incidents. ${topHotspot.recommendations[0]}`,
332
- suggestedAction: "Request extra review before merging changes to this area",
333
- relatedIssues: [],
334
- priority: Math.min(9, 5 + Math.floor(topHotspot.currentRisk / 20)),
335
- timestamp: Date.now(),
336
- dismissed: false,
337
- category: "security",
338
- details: {
339
- affectedFiles: summary.hotspots.map((h) => basename(h.target)),
340
- trend: trendMap[summary.trend],
341
- examples: topHotspot.recommendations
342
- }
343
- };
344
- await this.insightStore.addInsight(insight);
345
- await this.insightStore.markInsightCreated("risk-prediction");
346
- return insight;
347
- }
348
- };
349
- var riskPredictors = /* @__PURE__ */ new Map();
350
- function getRiskPredictor(projectPath) {
351
- let predictor = riskPredictors.get(projectPath);
352
- if (!predictor) {
353
- predictor = new RiskPredictor(projectPath);
354
- riskPredictors.set(projectPath, predictor);
355
- }
356
- return predictor;
357
- }
358
-
359
- // src/agent/escalation.ts
360
- var DEFAULT_CONFIG2 = {
361
- enabled: true,
362
- targets: [],
363
- cooldownMinutes: 15,
364
- maxEscalationsPerHour: 5,
365
- respectQuietHours: true,
366
- criticalBypassQuietHours: true,
367
- draftFallbackEnabled: true
368
- };
369
- var EscalationManager = class {
370
- projectPath;
371
- config;
372
- projectState;
373
- insightStore;
374
- escalationHistory = [];
375
- slackClient;
376
- constructor(projectPath, config = {}) {
377
- this.projectPath = projectPath;
378
- this.config = { ...DEFAULT_CONFIG2, ...config };
379
- this.projectState = getProjectState(projectPath);
380
- this.insightStore = getInsightStore(projectPath);
381
- const slackTarget = this.config.targets.find((t) => t.type === "slack" && t.enabled);
382
- if (slackTarget?.config.webhookUrl) {
383
- this.slackClient = new SlackIntegration({
384
- webhookUrl: slackTarget.config.webhookUrl,
385
- channel: slackTarget.config.channel,
386
- username: slackTarget.config.username
387
- });
388
- }
389
- }
390
- /**
391
- * Check if an issue should be auto-escalated
392
- */
393
- shouldAutoEscalate(issue) {
394
- if (!this.config.enabled) {
395
- return false;
396
- }
397
- if (issue.severity !== "critical") {
398
- return false;
399
- }
400
- const isSecurityIssue = issue.category === "security" || issue.agent === "security" || issue.issue.toLowerCase().includes("security") || issue.issue.toLowerCase().includes("vulnerability") || issue.issue.toLowerCase().includes("injection") || issue.issue.toLowerCase().includes("xss") || issue.issue.toLowerCase().includes("secret");
401
- if (!isSecurityIssue) {
402
- return false;
403
- }
404
- if (this.projectState.isQuietHours()) {
405
- if (!this.config.criticalBypassQuietHours) {
406
- return false;
407
- }
408
- }
409
- if (!this.insightStore.canCreateInsight("auto-escalation")) {
410
- return false;
411
- }
412
- const recentEscalations = this.escalationHistory.filter(
413
- (e) => e.timestamp > Date.now() - 60 * 60 * 1e3
414
- );
415
- if (recentEscalations.length >= this.config.maxEscalationsPerHour) {
416
- return false;
417
- }
418
- const recentlyEscalated = this.escalationHistory.some(
419
- (e) => e.issues.some((i) => i.file === issue.file) && e.timestamp > Date.now() - this.config.cooldownMinutes * 60 * 1e3
420
- );
421
- if (recentlyEscalated) {
422
- return false;
423
- }
424
- return this.hasValidEscalationTarget("critical", "security");
425
- }
426
- /**
427
- * Check if we have a valid escalation target
428
- */
429
- hasValidEscalationTarget(severity, category) {
430
- return this.config.targets.some(
431
- (t) => t.enabled && t.forSeverities.includes(severity) && (t.forCategories.includes(category) || t.forCategories.includes("all"))
432
- );
433
- }
434
- /**
435
- * Auto-escalate if issue is critical
436
- */
437
- async autoEscalateIfCritical(issue) {
438
- if (!this.shouldAutoEscalate(issue)) {
439
- if (issue.severity === "critical" && this.config.draftFallbackEnabled) {
440
- if (this.projectState.isQuietHours()) {
441
- return this.createDraftEscalation([issue], "Blocked by quiet hours");
442
- }
443
- }
444
- return {
445
- action: "no_action",
446
- reason: "Issue does not meet escalation criteria"
447
- };
448
- }
449
- const message = this.createEscalationMessage([issue]);
450
- try {
451
- await this.sendEscalation(message);
452
- this.escalationHistory.push(message);
453
- await this.insightStore.markInsightCreated("auto-escalation");
454
- await this.createEscalationInsight(message);
455
- await this.projectState.useRiskBudget(1);
456
- return {
457
- action: "auto_escalated",
458
- reason: "Critical security issue auto-escalated",
459
- message
460
- };
461
- } catch (error) {
462
- console.error("Failed to send escalation:", error);
463
- if (this.config.draftFallbackEnabled) {
464
- return this.createDraftEscalation([issue], String(error));
465
- }
466
- return {
467
- action: "failed",
468
- reason: `Send failed: ${error}`,
469
- message
470
- };
471
- }
472
- }
473
- /**
474
- * Escalate multiple issues at once
475
- */
476
- async escalateIssues(issues) {
477
- const criticalSecurityIssues = issues.filter(
478
- (i) => i.severity === "critical" && (i.category === "security" || i.agent === "security")
479
- );
480
- if (criticalSecurityIssues.length === 0) {
481
- return {
482
- action: "no_action",
483
- reason: "No critical security issues to escalate"
484
- };
485
- }
486
- if (this.projectState.isQuietHours() && !this.config.criticalBypassQuietHours) {
487
- return this.createDraftEscalation(criticalSecurityIssues, "Blocked by quiet hours");
488
- }
489
- const message = this.createEscalationMessage(criticalSecurityIssues);
490
- try {
491
- await this.sendEscalation(message);
492
- this.escalationHistory.push(message);
493
- await this.insightStore.markInsightCreated("auto-escalation");
494
- await this.createEscalationInsight(message);
495
- return {
496
- action: "auto_escalated",
497
- reason: `Escalated ${criticalSecurityIssues.length} critical security issues`,
498
- message
499
- };
500
- } catch (error) {
501
- if (this.config.draftFallbackEnabled) {
502
- return this.createDraftEscalation(criticalSecurityIssues, String(error));
503
- }
504
- return {
505
- action: "failed",
506
- reason: `Send failed: ${error}`,
507
- message
508
- };
509
- }
510
- }
511
- /**
512
- * Create an escalation message
513
- */
514
- createEscalationMessage(issues) {
515
- const severity = issues.some((i) => i.severity === "critical") ? "critical" : "serious";
516
- return {
517
- id: `esc-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
518
- severity,
519
- title: `${severity.toUpperCase()} Security Alert: ${issues.length} issue${issues.length > 1 ? "s" : ""} detected`,
520
- body: this.formatEscalationBody(issues),
521
- issues,
522
- timestamp: Date.now(),
523
- sent: false
524
- };
525
- }
526
- /**
527
- * Format escalation body text
528
- */
529
- formatEscalationBody(issues) {
530
- const lines = [
531
- `**Critical Security Issues Detected**`,
532
- ``,
533
- `**Project:** ${this.projectPath.split("/").pop()}`,
534
- `**Issues:** ${issues.length}`,
535
- `**Detected:** ${(/* @__PURE__ */ new Date()).toISOString()}`,
536
- ``,
537
- `**Summary:**`
538
- ];
539
- for (const issue of issues.slice(0, 5)) {
540
- lines.push(`- \`${issue.file}:${issue.line || "?"}\`: ${issue.issue.slice(0, 100)}`);
541
- }
542
- if (issues.length > 5) {
543
- lines.push(`- ... and ${issues.length - 5} more`);
544
- }
545
- lines.push("");
546
- lines.push("**Action Required:** Review and address these issues immediately.");
547
- return lines.join("\n");
548
- }
549
- /**
550
- * Send escalation through configured channels
551
- */
552
- async sendEscalation(message) {
553
- const enabledTargets = this.config.targets.filter((t) => t.enabled);
554
- if (enabledTargets.length === 0) {
555
- throw new Error("No enabled escalation targets configured");
556
- }
557
- const errors = [];
558
- for (const target of enabledTargets) {
559
- try {
560
- switch (target.type) {
561
- case "slack":
562
- await this.sendToSlack(message, target);
563
- break;
564
- case "email":
565
- await this.sendToEmail(message, target);
566
- break;
567
- case "webhook":
568
- await this.sendToWebhook(message, target);
569
- break;
570
- }
571
- message.sent = true;
572
- message.sentAt = Date.now();
573
- message.channel = target.type;
574
- } catch (error) {
575
- errors.push(`${target.type}: ${error}`);
576
- }
577
- }
578
- if (errors.length === enabledTargets.length) {
579
- throw new Error(`All escalation channels failed: ${errors.join("; ")}`);
580
- }
581
- }
582
- /**
583
- * Send to Slack
584
- */
585
- async sendToSlack(message, target) {
586
- if (!target.config.webhookUrl) {
587
- throw new Error("Slack webhook URL not configured");
588
- }
589
- if (this.slackClient) {
590
- await this.slackClient.sendCriticalAlert(message.issues, this.projectPath.split("/").pop() || "Unknown");
591
- } else {
592
- const slack = new SlackIntegration({
593
- webhookUrl: target.config.webhookUrl,
594
- channel: target.config.channel,
595
- username: target.config.username || "Trie Agent"
596
- });
597
- await slack.sendCriticalAlert(message.issues, this.projectPath.split("/").pop() || "Unknown");
598
- }
599
- }
600
- /**
601
- * Send to email (placeholder - would need email provider integration)
602
- */
603
- async sendToEmail(message, target) {
604
- if (!target.config.email) {
605
- throw new Error("Email address not configured");
606
- }
607
- console.log(`[EMAIL ESCALATION] To: ${target.config.email}`);
608
- console.log(`Subject: ${message.title}`);
609
- console.log(`Body: ${message.body}`);
610
- }
611
- /**
612
- * Send to webhook
613
- */
614
- async sendToWebhook(message, target) {
615
- if (!target.config.webhookUrl) {
616
- throw new Error("Webhook URL not configured");
617
- }
618
- const response = await fetch(target.config.webhookUrl, {
619
- method: "POST",
620
- headers: {
621
- "Content-Type": "application/json"
622
- },
623
- body: JSON.stringify({
624
- id: message.id,
625
- severity: message.severity,
626
- title: message.title,
627
- body: message.body,
628
- issues: message.issues.map((i) => ({
629
- file: i.file,
630
- line: i.line,
631
- severity: i.severity,
632
- issue: i.issue,
633
- agent: i.agent
634
- })),
635
- timestamp: message.timestamp,
636
- project: this.projectPath
637
- })
638
- });
639
- if (!response.ok) {
640
- throw new Error(`Webhook returned ${response.status}: ${response.statusText}`);
641
- }
642
- }
643
- /**
644
- * Create a draft escalation (when sending is blocked)
645
- */
646
- createDraftEscalation(issues, reason) {
647
- const message = this.createEscalationMessage(issues);
648
- message.error = reason;
649
- this.escalationHistory.push(message);
650
- return {
651
- action: "draft_only",
652
- reason,
653
- message,
654
- draftLocation: `.trie/drafts/escalation-${message.id}.json`
655
- };
656
- }
657
- /**
658
- * Create insight about escalation
659
- */
660
- async createEscalationInsight(message) {
661
- const insight = {
662
- id: `insight-esc-${message.id}`,
663
- type: "warning",
664
- message: `Auto-escalated: ${message.issues.length} critical security issue${message.issues.length > 1 ? "s" : ""}`,
665
- context: `Sent to ${message.channel}. Issues in: ${[...new Set(message.issues.map((i) => i.file))].slice(0, 3).join(", ")}`,
666
- relatedIssues: message.issues.map((i) => i.id),
667
- priority: 10,
668
- timestamp: Date.now(),
669
- dismissed: false,
670
- category: "security",
671
- details: {
672
- affectedFiles: [...new Set(message.issues.map((i) => i.file))]
673
- }
674
- };
675
- await this.insightStore.addInsight(insight);
676
- }
677
- /**
678
- * Get escalation history
679
- */
680
- getEscalationHistory() {
681
- return [...this.escalationHistory];
682
- }
683
- /**
684
- * Get pending draft escalations
685
- */
686
- getPendingDrafts() {
687
- return this.escalationHistory.filter((e) => !e.sent);
688
- }
689
- /**
690
- * Retry a failed/draft escalation
691
- */
692
- async retryEscalation(messageId) {
693
- const message = this.escalationHistory.find((e) => e.id === messageId);
694
- if (!message) {
695
- return {
696
- action: "failed",
697
- reason: "Escalation message not found"
698
- };
699
- }
700
- try {
701
- await this.sendEscalation(message);
702
- return {
703
- action: "auto_escalated",
704
- reason: "Retry successful",
705
- message
706
- };
707
- } catch (error) {
708
- return {
709
- action: "failed",
710
- reason: `Retry failed: ${error}`,
711
- message
712
- };
713
- }
714
- }
715
- /**
716
- * Configure escalation targets
717
- */
718
- addEscalationTarget(target) {
719
- this.config.targets.push(target);
720
- if (target.type === "slack" && target.enabled && target.config.webhookUrl) {
721
- this.slackClient = new SlackIntegration({
722
- webhookUrl: target.config.webhookUrl,
723
- channel: target.config.channel,
724
- username: target.config.username
725
- });
726
- }
727
- }
728
- /**
729
- * Get current configuration
730
- */
731
- getConfig() {
732
- return { ...this.config };
733
- }
734
- /**
735
- * Update configuration
736
- */
737
- setConfig(config) {
738
- this.config = { ...this.config, ...config };
739
- }
740
- };
741
- var escalationManagers = /* @__PURE__ */ new Map();
742
- function getEscalationManager(projectPath) {
743
- let manager = escalationManagers.get(projectPath);
744
- if (!manager) {
745
- manager = new EscalationManager(projectPath);
746
- escalationManagers.set(projectPath, manager);
747
- }
748
- return manager;
749
- }
750
-
751
- // src/agent/meta-learning.ts
752
- var MetaLearner = class {
753
- projectState;
754
- insightStore;
755
- feedbackHistory = [];
756
- weights;
757
- constructor(projectPath) {
758
- this.projectState = getProjectState(projectPath);
759
- this.insightStore = getInsightStore(projectPath);
760
- this.weights = {
761
- security: 1,
762
- quality: 1,
763
- performance: 1,
764
- pattern: 1,
765
- progress: 1,
766
- general: 1
767
- };
768
- }
769
- /**
770
- * Record user feedback on an insight
771
- */
772
- async recordFeedback(feedback, context) {
773
- await this.insightStore.load();
774
- const insight = this.insightStore.getInsight(context.insightId);
775
- if (!insight) {
776
- console.error(`Insight not found: ${context.insightId}`);
777
- return;
778
- }
779
- const record = {
780
- insightId: context.insightId,
781
- insightType: insight.type,
782
- insightCategory: insight.category,
783
- feedback,
784
- timestamp: Date.now()
785
- };
786
- if (context.latencyMs !== void 0) {
787
- record.latencyMs = context.latencyMs;
788
- }
789
- this.feedbackHistory.push(record);
790
- await this.projectState.recordInsightFeedback(
791
- feedback === "dismissed" ? "dismissed" : feedback === "acted" ? "acted" : "helpful"
792
- );
793
- await this.adjustWeights(record);
794
- }
795
- /**
796
- * Adjust insight weights based on feedback
797
- */
798
- async adjustWeights(feedback) {
799
- const category = feedback.insightCategory;
800
- const currentWeight = this.weights[category];
801
- if (currentWeight === void 0) return;
802
- let adjustment = 0;
803
- switch (feedback.feedback) {
804
- case "acted":
805
- adjustment = 0.05;
806
- break;
807
- case "helpful":
808
- adjustment = 0.02;
809
- break;
810
- case "dismissed":
811
- adjustment = -0.03;
812
- break;
813
- case "ignored":
814
- adjustment = -0.01;
815
- break;
816
- }
817
- this.weights[category] = Math.max(0.3, Math.min(1.5, currentWeight + adjustment));
818
- }
819
- /**
820
- * Get current insight weights
821
- */
822
- getWeights() {
823
- return { ...this.weights };
824
- }
825
- /**
826
- * Get weight for a category (used to adjust insight priority)
827
- */
828
- getCategoryWeight(category) {
829
- return this.weights[category] ?? 1;
830
- }
831
- /**
832
- * Calculate category effectiveness
833
- */
834
- calculateCategoryEffectiveness() {
835
- const categories = ["security", "quality", "performance", "pattern", "progress", "general"];
836
- const effectiveness = [];
837
- for (const category of categories) {
838
- const categoryFeedback = this.feedbackHistory.filter((f) => f.insightCategory === category);
839
- if (categoryFeedback.length === 0) {
840
- effectiveness.push({
841
- category,
842
- totalInsights: 0,
843
- helpfulCount: 0,
844
- dismissedCount: 0,
845
- actedCount: 0,
846
- effectivenessScore: 0.5
847
- // Neutral when no data
848
- });
849
- continue;
850
- }
851
- const helpfulCount = categoryFeedback.filter((f) => f.feedback === "helpful" || f.feedback === "acted").length;
852
- const dismissedCount = categoryFeedback.filter((f) => f.feedback === "dismissed").length;
853
- const actedCount = categoryFeedback.filter((f) => f.feedback === "acted").length;
854
- const score = (helpfulCount + actedCount) / Math.max(1, categoryFeedback.length);
855
- effectiveness.push({
856
- category,
857
- totalInsights: categoryFeedback.length,
858
- helpfulCount,
859
- dismissedCount,
860
- actedCount,
861
- effectivenessScore: score
862
- });
863
- }
864
- return effectiveness;
865
- }
866
- /**
867
- * Get agent effectiveness metrics
868
- */
869
- getEffectiveness() {
870
- return this.projectState.getMetrics();
871
- }
872
- /**
873
- * Generate a comprehensive effectiveness report
874
- */
875
- async generateEffectivenessReport() {
876
- await this.projectState.load();
877
- const metrics = this.projectState.getMetrics();
878
- const categoryBreakdown = this.calculateCategoryEffectiveness();
879
- const overallScore = metrics.userSatisfaction * 0.4 + metrics.predictiveAccuracy * 0.3 + (1 - metrics.falsePositiveRate) * 0.3;
880
- const recommendations = this.generateRecommendations(metrics, categoryBreakdown);
881
- const trend = this.calculateTrend();
882
- return {
883
- overallScore,
884
- predictiveAccuracy: metrics.predictiveAccuracy,
885
- userSatisfaction: metrics.userSatisfaction,
886
- falsePositiveRate: metrics.falsePositiveRate,
887
- categoryBreakdown,
888
- recommendations,
889
- trends: trend
890
- };
891
- }
892
- /**
893
- * Generate improvement recommendations
894
- */
895
- generateRecommendations(metrics, categoryBreakdown) {
896
- const recommendations = [];
897
- if (metrics.falsePositiveRate > 0.3) {
898
- recommendations.push("High dismissal rate detected. Consider raising insight thresholds.");
899
- }
900
- if (metrics.userSatisfaction < 0.5) {
901
- recommendations.push("User satisfaction is low. Review insight quality and relevance.");
902
- }
903
- const weakCategories = categoryBreakdown.filter((c) => c.totalInsights >= 5 && c.effectivenessScore < 0.4).map((c) => c.category);
904
- if (weakCategories.length > 0) {
905
- recommendations.push(
906
- `Low effectiveness in: ${weakCategories.join(", ")}. Consider adjusting insight generation for these categories.`
907
- );
908
- }
909
- const strongCategories = categoryBreakdown.filter((c) => c.totalInsights >= 5 && c.effectivenessScore > 0.7).map((c) => c.category);
910
- if (strongCategories.length > 0) {
911
- recommendations.push(
912
- `Strong performance in: ${strongCategories.join(", ")}. Consider emphasizing these insights.`
913
- );
914
- }
915
- if (metrics.predictiveAccuracy < 0.6 && metrics.totalPredictions >= 10) {
916
- recommendations.push("Prediction accuracy below target. Review risk scoring factors.");
917
- }
918
- if (metrics.userSatisfaction >= 0.7 && metrics.falsePositiveRate <= 0.2) {
919
- recommendations.push("Agent performance is excellent. Keep up the good work!");
920
- }
921
- return recommendations;
922
- }
923
- /**
924
- * Calculate trend direction
925
- */
926
- calculateTrend() {
927
- const now = Date.now();
928
- const recentCutoff = now - 7 * 24 * 60 * 60 * 1e3;
929
- const olderCutoff = now - 30 * 24 * 60 * 60 * 1e3;
930
- const recentFeedback = this.feedbackHistory.filter((f) => f.timestamp > recentCutoff);
931
- const olderFeedback = this.feedbackHistory.filter(
932
- (f) => f.timestamp > olderCutoff && f.timestamp <= recentCutoff
933
- );
934
- if (recentFeedback.length < 5 || olderFeedback.length < 5) {
935
- return { period: "last 30 days", direction: "stable" };
936
- }
937
- const recentPositive = recentFeedback.filter(
938
- (f) => f.feedback === "helpful" || f.feedback === "acted"
939
- ).length / recentFeedback.length;
940
- const olderPositive = olderFeedback.filter(
941
- (f) => f.feedback === "helpful" || f.feedback === "acted"
942
- ).length / olderFeedback.length;
943
- const diff = recentPositive - olderPositive;
944
- if (diff > 0.1) {
945
- return { period: "last 30 days", direction: "improving" };
946
- } else if (diff < -0.1) {
947
- return { period: "last 30 days", direction: "declining" };
948
- }
949
- return { period: "last 30 days", direction: "stable" };
950
- }
951
- /**
952
- * Should an insight be shown based on learning?
953
- *
954
- * Uses weights and user patterns to filter low-value insights.
955
- */
956
- shouldShowInsight(insight) {
957
- const weight = this.getCategoryWeight(insight.category);
958
- if (weight < 0.5 && insight.priority < 5) {
959
- return false;
960
- }
961
- const adjustedPriority = insight.priority * weight;
962
- return adjustedPriority >= 3;
963
- }
964
- /**
965
- * Adjust insight priority based on learning
966
- */
967
- adjustInsightPriority(insight) {
968
- const weight = this.getCategoryWeight(insight.category);
969
- return Math.round(insight.priority * weight);
970
- }
971
- /**
972
- * Get feedback history stats
973
- */
974
- getFeedbackStats() {
975
- const stats = {
976
- total: this.feedbackHistory.length,
977
- helpful: 0,
978
- dismissed: 0,
979
- acted: 0,
980
- ignored: 0,
981
- averageLatencyMs: null
982
- };
983
- let totalLatency = 0;
984
- let latencyCount = 0;
985
- for (const feedback of this.feedbackHistory) {
986
- switch (feedback.feedback) {
987
- case "helpful":
988
- stats.helpful++;
989
- break;
990
- case "dismissed":
991
- stats.dismissed++;
992
- break;
993
- case "acted":
994
- stats.acted++;
995
- break;
996
- case "ignored":
997
- stats.ignored++;
998
- break;
999
- }
1000
- if (feedback.latencyMs !== void 0) {
1001
- totalLatency += feedback.latencyMs;
1002
- latencyCount++;
1003
- }
1004
- }
1005
- if (latencyCount > 0) {
1006
- stats.averageLatencyMs = Math.round(totalLatency / latencyCount);
1007
- }
1008
- return stats;
1009
- }
1010
- /**
1011
- * Reset learning (for testing)
1012
- */
1013
- reset() {
1014
- this.feedbackHistory = [];
1015
- this.weights = {
1016
- security: 1,
1017
- quality: 1,
1018
- performance: 1,
1019
- pattern: 1,
1020
- progress: 1,
1021
- general: 1
1022
- };
1023
- }
1024
- };
1025
- var metaLearners = /* @__PURE__ */ new Map();
1026
- function getMetaLearner(projectPath) {
1027
- let learner = metaLearners.get(projectPath);
1028
- if (!learner) {
1029
- learner = new MetaLearner(projectPath);
1030
- metaLearners.set(projectPath, learner);
1031
- }
1032
- return learner;
1033
- }
1034
-
1035
- // src/agent/trie-agent.ts
1036
- var PERSONALITY = {
1037
- greetings: [
1038
- "Hey, quick heads up...",
1039
- "Noticed something while scanning...",
1040
- "Worth mentioning...",
1041
- "Just so you know...",
1042
- "Spotted this..."
1043
- ],
1044
- warnings: [
1045
- "This needs your attention:",
1046
- "I'd pause on this:",
1047
- "Before you push...",
1048
- "Hold up \u2014",
1049
- "Important:"
1050
- ],
1051
- celebrations: [
1052
- "Nice work!",
1053
- "Good catch!",
1054
- "That's better.",
1055
- "Clean.",
1056
- "Progress."
1057
- ],
1058
- suggestions: [
1059
- "You might want to",
1060
- "Consider",
1061
- "Suggestion:",
1062
- "Quick win:",
1063
- "Idea:"
1064
- ],
1065
- questions: [
1066
- "Did you mean to",
1067
- "Should this",
1068
- "Is it intentional that",
1069
- "Quick question:"
1070
- ]
1071
- };
1072
- var TrieAgent = class {
1073
- projectPath;
1074
- projectName;
1075
- lastIssueHashes = /* @__PURE__ */ new Set();
1076
- initialized = false;
1077
- // Persistent stores
1078
- insightStore;
1079
- projectState;
1080
- // Agency modules
1081
- goalManager;
1082
- riskPredictor;
1083
- hypothesisEngine;
1084
- escalationManager;
1085
- metaLearner;
1086
- gotchaPredictor;
1087
- constructor(projectPath) {
1088
- this.projectPath = projectPath;
1089
- this.projectName = basename2(projectPath);
1090
- this.insightStore = getInsightStore(projectPath);
1091
- this.projectState = getProjectState(projectPath);
1092
- this.goalManager = getGoalManager(projectPath);
1093
- this.riskPredictor = getRiskPredictor(projectPath);
1094
- this.hypothesisEngine = getHypothesisEngine(projectPath);
1095
- this.escalationManager = getEscalationManager(projectPath);
1096
- this.metaLearner = getMetaLearner(projectPath);
1097
- this.gotchaPredictor = new GotchaPredictor(projectPath, new ContextGraph(projectPath));
1098
- }
1099
- /**
1100
- * Initialize the agent - loads persistent state and historical data
1101
- */
1102
- async initialize() {
1103
- if (this.initialized) return;
1104
- try {
1105
- await this.insightStore.load();
1106
- await this.projectState.load();
1107
- await this.projectState.touchActive();
1108
- const historical = await getHistoricalInsights(this.projectPath);
1109
- if (historical && historical.totalHistoricalIssues > 0) {
1110
- const trend = historical.improvementTrend;
1111
- if (trend === "improving" && this.canCreateInsight("progress-trend")) {
1112
- await this.addInsight(this.createInsight({
1113
- type: "celebration",
1114
- message: `${this.pick(PERSONALITY.celebrations)} Your code quality has been improving over time.`,
1115
- priority: 2,
1116
- category: "progress"
1117
- }));
1118
- await this.markInsightCreated("progress-trend");
1119
- } else if (trend === "declining" && this.canCreateInsight("progress-trend")) {
1120
- await this.addInsight(this.createInsight({
1121
- type: "observation",
1122
- message: `${this.pick(PERSONALITY.greetings)} Issue count has been trending up. Might be worth a focused cleanup session.`,
1123
- suggestedAction: "Run `trie watch` to monitor and address issues",
1124
- priority: 5,
1125
- category: "quality"
1126
- }));
1127
- await this.markInsightCreated("progress-trend");
1128
- }
1129
- }
1130
- this.initialized = true;
1131
- } catch {
1132
- this.initialized = true;
1133
- }
1134
- }
1135
- /**
1136
- * Add an insight to persistent storage
1137
- */
1138
- async addInsight(insight) {
1139
- return this.insightStore.addInsight(insight);
1140
- }
1141
- /**
1142
- * Restart the agent (reload state from disk)
1143
- */
1144
- async restart() {
1145
- this.initialized = false;
1146
- await this.insightStore.reload();
1147
- await this.projectState.reload();
1148
- await this.initialize();
1149
- }
1150
- /**
1151
- * Load state from disk (for testing)
1152
- */
1153
- async loadState() {
1154
- await this.projectState.load();
1155
- return {
1156
- goals: this.projectState.getAllGoals(),
1157
- riskBudget: this.projectState.getRiskBudget()
1158
- };
1159
- }
1160
- /**
1161
- * Process new issues from a scan and generate insights
1162
- * Stores issues in memory and optionally uses LLM for deeper analysis
1163
- */
1164
- async processIssues(issues, context) {
1165
- const newInsights = [];
1166
- try {
1167
- await storeIssues(issues, this.projectName, this.projectPath);
1168
- await recordToGlobalMemory(issues, this.projectName, this.projectPath);
1169
- if (context.filesChanged && context.filesChanged.length > 0) {
1170
- const currentHashes2 = new Set(issues.map((i) => getIssueHash(i)));
1171
- await autoResolveIssues(currentHashes2, context.filesChanged, this.projectPath);
1172
- }
1173
- } catch {
1174
- }
1175
- const currentHashes = new Set(issues.map((i) => `${i.file}:${i.line}:${i.issue.slice(0, 50)}`));
1176
- const newIssues = issues.filter((i) => !this.lastIssueHashes.has(`${i.file}:${i.line}:${i.issue.slice(0, 50)}`));
1177
- const fixedCount = [...this.lastIssueHashes].filter((h) => !currentHashes.has(h)).length;
1178
- const accessibilityIssues = issues.filter(
1179
- (i) => i.agent === "accessibility" && (i.severity === "critical" || i.severity === "serious")
1180
- );
1181
- if (accessibilityIssues.length >= 2 && this.canCreateInsight("accessibility-visual-qa")) {
1182
- const critical = accessibilityIssues.filter((i) => i.severity === "critical");
1183
- const serious = accessibilityIssues.filter((i) => i.severity === "serious");
1184
- const breakdown = {};
1185
- if (critical.length > 0) breakdown["critical"] = critical.length;
1186
- if (serious.length > 0) breakdown["serious"] = serious.length;
1187
- const affectedFiles = [...new Set(accessibilityIssues.map((i) => i.file))];
1188
- const examples = [...critical, ...serious].slice(0, 3).map((i) => `${basename2(i.file)}:${i.line} - ${i.issue.slice(0, 60)}`);
1189
- const insight = this.createInsight({
1190
- type: "suggestion",
1191
- message: `Found ${accessibilityIssues.length} accessibility issue${accessibilityIssues.length > 1 ? "s" : ""} that could block users. Screenshots would help validate real impact.`,
1192
- suggestedAction: "Capture screenshots for visual analysis",
1193
- actionCommand: 'trie_visual_qa_browser url:"http://localhost:3000"',
1194
- priority: 7,
1195
- category: "quality",
1196
- relatedIssues: accessibilityIssues.map((i) => i.id),
1197
- details: {
1198
- affectedFiles: affectedFiles.map((f) => basename2(f)),
1199
- issueBreakdown: breakdown,
1200
- examples
1201
- }
1202
- });
1203
- newInsights.push(insight);
1204
- await this.addInsight(insight);
1205
- await this.markInsightCreated("accessibility-visual-qa");
1206
- }
1207
- const securityIssues = issues.filter(
1208
- (i) => i.category === "security" || i.issue.toLowerCase().includes("secret") || i.issue.toLowerCase().includes("vulnerability") || i.issue.toLowerCase().includes("injection") || i.issue.toLowerCase().includes("xss")
1209
- );
1210
- if (securityIssues.length > 0 && this.canCreateInsight("security-warning")) {
1211
- const critical = securityIssues.filter((i) => i.severity === "critical");
1212
- const serious = securityIssues.filter((i) => i.severity === "serious");
1213
- if (critical.length > 0 || serious.length >= 2) {
1214
- const breakdown = {};
1215
- if (critical.length > 0) breakdown["critical"] = critical.length;
1216
- if (serious.length > 0) breakdown["serious"] = serious.length;
1217
- const affectedFiles = [...new Set(securityIssues.map((i) => i.file))];
1218
- const examples = [...critical, ...serious].slice(0, 3).map((i) => `${basename2(i.file)}:${i.line} - ${i.issue.slice(0, 60)}`);
1219
- const insight = this.createInsight({
1220
- type: "warning",
1221
- message: `Found ${securityIssues.length} security issue${securityIssues.length > 1 ? "s" : ""} that could expose your app.`,
1222
- suggestedAction: `Review ${affectedFiles.length} file${affectedFiles.length > 1 ? "s" : ""} immediately`,
1223
- actionCommand: "trie check",
1224
- priority: 10,
1225
- category: "security",
1226
- relatedIssues: securityIssues.map((i) => i.id),
1227
- details: {
1228
- affectedFiles: affectedFiles.map((f) => basename2(f)),
1229
- issueBreakdown: breakdown,
1230
- examples
1231
- }
1232
- });
1233
- newInsights.push(insight);
1234
- await this.addInsight(insight);
1235
- await this.markInsightCreated("security-warning");
1236
- }
1237
- }
1238
- if (newIssues.length >= 3 && context.filesChanged && context.filesChanged.length > 0 && this.canCreateInsight("new-issues")) {
1239
- const affectedFiles = [...new Set(newIssues.map((i) => basename2(i.file)))];
1240
- const filesChanged = context.filesChanged.map((f) => basename2(f));
1241
- const breakdown = {};
1242
- const critical = newIssues.filter((i) => i.severity === "critical");
1243
- const serious = newIssues.filter((i) => i.severity === "serious");
1244
- const moderate = newIssues.filter((i) => i.severity === "moderate");
1245
- if (critical.length > 0) breakdown["critical"] = critical.length;
1246
- if (serious.length > 0) breakdown["serious"] = serious.length;
1247
- if (moderate.length > 0) breakdown["moderate"] = moderate.length;
1248
- const examples = newIssues.sort((a, b) => {
1249
- const sev = { critical: 3, serious: 2, moderate: 1, minor: 0, low: 0 };
1250
- return (sev[b.severity] || 0) - (sev[a.severity] || 0);
1251
- }).slice(0, 3).map((i) => `${basename2(i.file)}:${i.line} - ${i.issue.slice(0, 50)}`);
1252
- const insight = this.createInsight({
1253
- type: "observation",
1254
- message: `Recent changes introduced ${newIssues.length} new issues in ${affectedFiles.slice(0, 3).join(", ")}.`,
1255
- suggestedAction: `Review ${affectedFiles.length} affected file${affectedFiles.length > 1 ? "s" : ""}`,
1256
- priority: 6,
1257
- category: "quality",
1258
- details: {
1259
- affectedFiles: affectedFiles.slice(0, 8),
1260
- issueBreakdown: breakdown,
1261
- examples,
1262
- comparison: `Changed: ${filesChanged.slice(0, 3).join(", ")}${filesChanged.length > 3 ? ` +${filesChanged.length - 3} more` : ""}`
1263
- }
1264
- });
1265
- newInsights.push(insight);
1266
- await this.addInsight(insight);
1267
- await this.markInsightCreated("new-issues");
1268
- }
1269
- if (fixedCount > 0 && newIssues.length === 0 && this.canCreateInsight("celebration")) {
1270
- const insight = this.createInsight({
1271
- type: "celebration",
1272
- message: `${this.pick(PERSONALITY.celebrations)} ${fixedCount} issue${fixedCount > 1 ? "s" : ""} resolved.`,
1273
- priority: 3,
1274
- category: "progress"
1275
- });
1276
- newInsights.push(insight);
1277
- await this.addInsight(insight);
1278
- await this.markInsightCreated("celebration");
1279
- }
1280
- if (issues.length >= 10 && this.canCreateInsight("hypothesis-generation")) {
1281
- try {
1282
- const patterns = [];
1283
- const observations = [];
1284
- if (newIssues.length > issues.length * 0.3) {
1285
- observations.push(`High new issue rate: ${newIssues.length} new out of ${issues.length} total`);
1286
- }
1287
- const fileFreq = {};
1288
- for (const issue of issues) {
1289
- fileFreq[issue.file] = (fileFreq[issue.file] || 0) + 1;
1290
- }
1291
- const hotFiles = Object.entries(fileFreq).filter(([, count]) => count >= 3);
1292
- if (hotFiles.length > 0) {
1293
- patterns.push(`Hotspot files: ${hotFiles.map(([f]) => basename2(f)).join(", ")}`);
1294
- }
1295
- const generated = await this.hypothesisEngine.generateHypothesesWithAI({
1296
- recentIssues: issues.map((i) => ({ issue: i, score: 1 })),
1297
- patterns,
1298
- observations
1299
- });
1300
- for (const hypothesis of generated) {
1301
- const insight = this.createInsight({
1302
- type: "observation",
1303
- message: `${this.pick(PERSONALITY.questions)} New hypothesis to test: "${hypothesis.statement}"`,
1304
- context: `Confidence: ${Math.round(hypothesis.confidence * 100)}%`,
1305
- suggestedAction: `Monitor this pattern over time`,
1306
- priority: 4,
1307
- category: "pattern",
1308
- details: {
1309
- hypothesis: hypothesis.statement,
1310
- testCriteria: hypothesis.testCriteria || "Collecting evidence...",
1311
- confidence: Math.round(hypothesis.confidence * 100)
1312
- }
1313
- });
1314
- newInsights.push(insight);
1315
- await this.addInsight(insight);
1316
- }
1317
- if (generated.length > 0) {
1318
- await this.markInsightCreated("hypothesis-generation");
1319
- }
1320
- } catch (error) {
1321
- }
1322
- }
1323
- if (issues.length >= 5 && this.canCreateInsight("pattern-discovery")) {
1324
- try {
1325
- const { IncidentIndex } = await import("./incident-index-EFNUSGWL.js");
1326
- const { TriePatternDiscovery } = await import("./pattern-discovery-F7LU5K6E.js");
1327
- const { ContextGraph: ContextGraph2 } = await import("./graph-B3NA4S7I.js");
1328
- const graph = new ContextGraph2(this.projectPath);
1329
- const incidentIndex = await IncidentIndex.build(graph, this.projectPath);
1330
- const discovery = new TriePatternDiscovery(graph, incidentIndex);
1331
- const hotPatterns = discovery.discoverHotPatterns(2);
1332
- let patternsAdded = 0;
1333
- for (const hot of hotPatterns.slice(0, 5)) {
1334
- const existingPatterns = await graph.listNodes();
1335
- const alreadyExists = existingPatterns.some(
1336
- (n) => n.type === "pattern" && n.data.description?.includes(hot.path)
1337
- );
1338
- if (!alreadyExists) {
1339
- await graph.addNode("pattern", {
1340
- description: `${hot.type === "directory" ? "Directory" : "File"} hot zone: ${hot.path}`,
1341
- appliesTo: [hot.path],
1342
- confidence: Math.min(0.95, hot.confidence),
1343
- occurrences: hot.incidentCount,
1344
- firstSeen: (/* @__PURE__ */ new Date()).toISOString(),
1345
- lastSeen: (/* @__PURE__ */ new Date()).toISOString(),
1346
- isAntiPattern: hot.incidentCount >= 3,
1347
- source: "local"
1348
- });
1349
- patternsAdded++;
1350
- }
1351
- }
1352
- if (patternsAdded > 0) {
1353
- const insight = this.createInsight({
1354
- type: "observation",
1355
- message: `${this.pick(PERSONALITY.greetings)} Discovered ${patternsAdded} pattern${patternsAdded > 1 ? "s" : ""} in your codebase.`,
1356
- suggestedAction: `Check Memory \u2192 Learned Patterns to see`,
1357
- priority: 5,
1358
- category: "pattern",
1359
- details: {
1360
- patternsCount: patternsAdded,
1361
- topPattern: hotPatterns[0]?.path
1362
- }
1363
- });
1364
- newInsights.push(insight);
1365
- await this.addInsight(insight);
1366
- await this.markInsightCreated("pattern-discovery");
1367
- }
1368
- } catch (error) {
1369
- }
1370
- }
1371
- if (this.canCreateInsight("pattern-suggestion")) {
1372
- try {
1373
- const globalPatterns = await findCrossProjectPatterns();
1374
- const crossProjectPattern = globalPatterns.find((p) => p.projects.length > 1 && p.occurrences > 3);
1375
- if (crossProjectPattern) {
1376
- const insight = this.createInsight({
1377
- type: "suggestion",
1378
- message: `"${crossProjectPattern.description}" appears in ${crossProjectPattern.projects.length} projects. Consider a shared lint rule.`,
1379
- priority: 4,
1380
- category: "pattern"
1381
- });
1382
- newInsights.push(insight);
1383
- await this.addInsight(insight);
1384
- await this.markInsightCreated("pattern-suggestion");
1385
- }
1386
- } catch {
1387
- }
1388
- }
1389
- if (context.isWatchMode && this.shouldWarnBeforePush(issues) && this.canCreateInsight("pre-push-warning")) {
1390
- const criticalIssues = issues.filter((i) => i.severity === "critical");
1391
- const seriousIssues = issues.filter((i) => i.severity === "serious");
1392
- const moderateIssues = issues.filter((i) => i.severity === "moderate");
1393
- const breakdown = {};
1394
- if (criticalIssues.length > 0) breakdown["critical"] = criticalIssues.length;
1395
- if (seriousIssues.length > 0) breakdown["serious"] = seriousIssues.length;
1396
- if (moderateIssues.length > 0) breakdown["moderate"] = moderateIssues.length;
1397
- const criticalFiles = [...new Set(criticalIssues.map((i) => basename2(i.file)))];
1398
- const seriousFiles = [...new Set(seriousIssues.map((i) => basename2(i.file)))];
1399
- const affectedFiles = [.../* @__PURE__ */ new Set([...criticalFiles, ...seriousFiles])].slice(0, 5);
1400
- const examples = [...criticalIssues, ...seriousIssues].slice(0, 4).map((i) => `${basename2(i.file)}:${i.line} - ${i.issue.slice(0, 50)}`);
1401
- const totalBlocking = criticalIssues.length + seriousIssues.length;
1402
- const trend = this.lastIssueHashes.size > 0 ? totalBlocking > this.lastIssueHashes.size ? "worsening" : "improving" : void 0;
1403
- const insightDetails = {
1404
- affectedFiles,
1405
- issueBreakdown: breakdown,
1406
- examples
1407
- };
1408
- if (trend) insightDetails.trend = trend;
1409
- if (moderateIssues.length > 0) insightDetails.comparison = `+${moderateIssues.length} moderate (non-blocking)`;
1410
- const insight = this.createInsight({
1411
- type: "warning",
1412
- message: `${totalBlocking} issue${totalBlocking > 1 ? "s" : ""} need attention before pushing.`,
1413
- suggestedAction: "Run pre-push check",
1414
- actionCommand: "trie check",
1415
- priority: 8,
1416
- category: "quality",
1417
- details: insightDetails
1418
- });
1419
- newInsights.push(insight);
1420
- await this.addInsight(insight);
1421
- await this.markInsightCreated("pre-push-warning");
1422
- }
1423
- if (isAIAvailable() && issues.length > 0 && newIssues.length > 0) {
1424
- const aiInsights = await this.generateAIInsights(issues, newIssues);
1425
- newInsights.push(...aiInsights);
1426
- }
1427
- if (this.canCreateInsight("goal-progress")) {
1428
- try {
1429
- const patterns = await this.goalManager.analyzeIncidentPatterns();
1430
- const significantPatterns = patterns.filter((p) => p.confidence >= 0.6 && p.currentValue >= 3);
1431
- if (significantPatterns.length > 0) {
1432
- await this.goalManager.autoGenerateGoals();
1433
- }
1434
- await this.goalManager.updateGoalProgress();
1435
- const goals = this.projectState.getAllGoals();
1436
- for (const goal of goals.filter((g) => g.status === "active")) {
1437
- const startVal = goal.startValue ?? goal.currentValue;
1438
- if (startVal > 0 && goal.currentValue <= startVal) {
1439
- const percentComplete = Math.round((1 - goal.currentValue / startVal) * 100);
1440
- if (percentComplete >= 50 && this.canCreateInsight(`goal-${goal.id}`)) {
1441
- const insight = this.createInsight({
1442
- type: "celebration",
1443
- message: `Goal "${goal.description}" is ${percentComplete}% complete! ${goal.currentValue} issues remaining (started at ${startVal}).`,
1444
- priority: 4,
1445
- category: "progress",
1446
- details: {
1447
- affectedFiles: goal.category ? [goal.category] : [],
1448
- comparison: `${startVal} \u2192 ${goal.currentValue}`
1449
- }
1450
- });
1451
- newInsights.push(insight);
1452
- await this.addInsight(insight);
1453
- await this.markInsightCreated(`goal-${goal.id}`);
1454
- }
1455
- }
1456
- }
1457
- await this.markInsightCreated("goal-progress");
1458
- } catch {
1459
- }
1460
- }
1461
- if (context.filesChanged && context.filesChanged.length > 0 && this.canCreateInsight("risk-prediction")) {
1462
- try {
1463
- const riskSummary = await this.riskPredictor.predictRiskTrend(context.filesChanged);
1464
- if (riskSummary.overallRisk >= 50) {
1465
- const highRiskFactors = riskSummary.factors.filter((f) => f.reasons.length > 0);
1466
- if (highRiskFactors.length > 0) {
1467
- const topFile = highRiskFactors[0];
1468
- const insight = this.createInsight({
1469
- type: "warning",
1470
- message: `Risk score ${Math.round(riskSummary.overallRisk)}/100 for changed files (${riskSummary.trend}). ${topFile ? basename2(topFile.file) + " is high-risk." : ""}`,
1471
- suggestedAction: "Consider extra review before pushing",
1472
- priority: 7,
1473
- category: "quality",
1474
- details: {
1475
- affectedFiles: highRiskFactors.slice(0, 5).map((f) => basename2(f.file)),
1476
- trend: riskSummary.trend === "increasing" ? "worsening" : riskSummary.trend === "decreasing" ? "improving" : "stable"
1477
- }
1478
- });
1479
- newInsights.push(insight);
1480
- await this.addInsight(insight);
1481
- await this.markInsightCreated("risk-prediction");
1482
- }
1483
- }
1484
- } catch {
1485
- }
1486
- }
1487
- if (context.filesChanged && context.filesChanged.length > 0) {
1488
- try {
1489
- const gotchas = await this.gotchaPredictor.predictGotchas(context.filesChanged);
1490
- const storage = getStorage(this.projectPath);
1491
- for (const gotcha of gotchas) {
1492
- if (this.canCreateInsight(`gotcha-${gotcha.id}`)) {
1493
- const explanation = await this.gotchaPredictor.synthesizeGotchaExplanation(gotcha);
1494
- const insight = this.createInsight({
1495
- type: "warning",
1496
- message: `[Gotcha] ${gotcha.message}`,
1497
- context: explanation,
1498
- suggestedAction: gotcha.recommendation,
1499
- priority: gotcha.riskLevel === "critical" ? 9 : 7,
1500
- category: "quality",
1501
- details: {
1502
- affectedFiles: context.filesChanged.map((f) => basename2(f)),
1503
- examples: [gotcha.message, explanation]
1504
- }
1505
- });
1506
- newInsights.push(insight);
1507
- await this.addInsight(insight);
1508
- await this.markInsightCreated(`gotcha-${gotcha.id}`);
1509
- }
1510
- const primaryFile = context.filesChanged?.[0];
1511
- const ledgerGotcha = {
1512
- id: gotcha.id,
1513
- message: gotcha.message,
1514
- confidence: gotcha.confidence,
1515
- riskLevel: gotcha.riskLevel,
1516
- recommendation: gotcha.recommendation,
1517
- ...primaryFile && { file: primaryFile },
1518
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1519
- ...gotcha.precedentId && { precedentId: gotcha.precedentId },
1520
- tags: gotcha.evidence.matchingPatterns,
1521
- evidence: gotcha.evidence,
1522
- resolved: false
1523
- };
1524
- await storage.storeGotcha(ledgerGotcha);
1525
- }
1526
- } catch {
1527
- }
1528
- }
1529
- if (this.canCreateInsight("hypothesis-update")) {
1530
- try {
1531
- const hypotheses = this.projectState.getAllHypotheses();
1532
- const testingHypotheses = hypotheses.filter((h) => h.status === "testing");
1533
- if (testingHypotheses.length < 3) {
1534
- await this.hypothesisEngine.autoGenerateHypotheses();
1535
- }
1536
- const validatedHypotheses = hypotheses.filter(
1537
- (h) => h.status === "validated" && h.validatedAt && Date.now() - new Date(h.validatedAt).getTime() < 24 * 60 * 60 * 1e3
1538
- // Within last 24h
1539
- );
1540
- for (const hypothesis of validatedHypotheses.slice(0, 2)) {
1541
- if (this.canCreateInsight(`hypothesis-${hypothesis.id}`)) {
1542
- const insight = this.createInsight({
1543
- type: "celebration",
1544
- message: `Hypothesis validated: "${hypothesis.statement}" (${Math.round(hypothesis.confidence * 100)}% confidence)`,
1545
- priority: 5,
1546
- category: "pattern"
1547
- });
1548
- newInsights.push(insight);
1549
- await this.addInsight(insight);
1550
- await this.markInsightCreated(`hypothesis-${hypothesis.id}`);
1551
- }
1552
- }
1553
- await this.markInsightCreated("hypothesis-update");
1554
- } catch {
1555
- }
1556
- }
1557
- const criticalSecurityIssues = issues.filter(
1558
- (i) => i.severity === "critical" && (i.category === "security" || i.issue.toLowerCase().includes("secret"))
1559
- );
1560
- if (criticalSecurityIssues.length > 0) {
1561
- try {
1562
- const result = await this.escalationManager.escalateIssues(criticalSecurityIssues);
1563
- if (result.action === "auto_escalated" && result.message) {
1564
- const insight = this.createInsight({
1565
- type: "observation",
1566
- message: `Auto-escalated ${criticalSecurityIssues.length} critical security issue(s). Check your notifications.`,
1567
- priority: 9,
1568
- category: "security",
1569
- details: {
1570
- affectedFiles: criticalSecurityIssues.slice(0, 5).map((i) => basename2(i.file)),
1571
- examples: criticalSecurityIssues.slice(0, 3).map((i) => i.issue.slice(0, 60))
1572
- }
1573
- });
1574
- newInsights.push(insight);
1575
- await this.addInsight(insight);
1576
- }
1577
- } catch {
1578
- }
1579
- }
1580
- this.lastIssueHashes = currentHashes;
1581
- await this.projectState.recordScan();
1582
- try {
1583
- const riskLevel = issues.filter((i) => i.severity === "critical").length > 0 ? "critical" : issues.filter((i) => i.severity === "serious").length >= 3 ? "high" : issues.length > 10 ? "medium" : "low";
1584
- const { calculateAdaptiveScanFrequency } = await import("./goal-manager-QUKX2W6C.js");
1585
- const result = await calculateAdaptiveScanFrequency(riskLevel);
1586
- await this.projectState.setScanFrequency(result.frequencyMs);
1587
- } catch {
1588
- }
1589
- try {
1590
- const { getStorage: getStorage2 } = await import("./tiered-storage-DYNC5CQ6.js");
1591
- const storage = getStorage2(this.projectPath);
1592
- const resolvedIssueIds = [...this.lastIssueHashes].filter((h) => !currentHashes.has(h)).map((h) => {
1593
- return h.split(":").join("-");
1594
- });
1595
- if (resolvedIssueIds.length > 0) {
1596
- const resolvedCount = await storage.autoResolveFixedNudges(resolvedIssueIds);
1597
- if (resolvedCount > 0) {
1598
- console.debug(`[Agent] Auto-resolved ${resolvedCount} nudge${resolvedCount !== 1 ? "s" : ""} for fixed issues`);
1599
- }
1600
- }
1601
- } catch {
1602
- }
1603
- return newInsights;
1604
- }
1605
- /**
1606
- * Use LLM to generate deeper insights (optional, requires ANTHROPIC_API_KEY)
1607
- */
1608
- async generateAIInsights(_allIssues, newIssues) {
1609
- const insights = [];
1610
- try {
1611
- if (newIssues.length < 2) return insights;
1612
- const issuesSummary = newIssues.slice(0, 10).map((i) => ({
1613
- severity: i.severity,
1614
- issue: i.issue.slice(0, 100),
1615
- file: basename2(i.file),
1616
- agent: i.agent
1617
- }));
1618
- const result = await runAIAnalysis({
1619
- systemPrompt: `You are a helpful code reviewer. Analyze these issues and provide ONE brief, conversational insight.
1620
- Be specific and actionable. Speak like a helpful colleague, not a system.
1621
- Keep your response under 100 words. Focus on the most important pattern or concern.`,
1622
- userPrompt: `New issues found:
1623
- ${JSON.stringify(issuesSummary, null, 2)}
1624
-
1625
- What's the most important thing the developer should know? Provide a brief, conversational insight.`,
1626
- maxTokens: 200,
1627
- temperature: 0.7
1628
- });
1629
- if (result.success && result.content) {
1630
- const insight = this.createInsight({
1631
- type: "observation",
1632
- message: result.content.trim(),
1633
- priority: 5,
1634
- category: "general"
1635
- });
1636
- insights.push(insight);
1637
- await this.addInsight(insight);
1638
- }
1639
- } catch {
1640
- }
1641
- return insights;
1642
- }
1643
- /**
1644
- * Get active insights (not dismissed, still relevant)
1645
- */
1646
- getActiveInsights() {
1647
- return this.insightStore.getActiveInsights();
1648
- }
1649
- /**
1650
- * Dismiss an insight
1651
- */
1652
- async dismissInsight(insightId) {
1653
- const result = await this.insightStore.dismissInsight(insightId);
1654
- if (result) {
1655
- await this.projectState.recordInsightFeedback("dismissed");
1656
- }
1657
- return result;
1658
- }
1659
- /**
1660
- * Record that a user found an insight helpful
1661
- */
1662
- async markInsightHelpful(_insightId) {
1663
- await this.projectState.recordInsightFeedback("helpful");
1664
- }
1665
- /**
1666
- * Record that a user acted on an insight
1667
- */
1668
- async markInsightActedOn(_insightId) {
1669
- await this.projectState.recordInsightFeedback("acted");
1670
- }
1671
- /**
1672
- * Get insight statistics
1673
- */
1674
- getInsightStats() {
1675
- return this.insightStore.getStats();
1676
- }
1677
- /**
1678
- * Get agent metrics (for dashboard display)
1679
- */
1680
- getAgentMetrics() {
1681
- return this.projectState.getMetrics();
1682
- }
1683
- /**
1684
- * Check if in quiet hours
1685
- */
1686
- isQuietHours() {
1687
- return this.projectState.isQuietHours();
1688
- }
1689
- /**
1690
- * Check if in crunch mode
1691
- */
1692
- isInCrunchMode() {
1693
- return this.projectState.isInCrunchMode();
1694
- }
1695
- /**
1696
- * Get the insight store (for advanced operations)
1697
- */
1698
- getInsightStore() {
1699
- return this.insightStore;
1700
- }
1701
- /**
1702
- * Get the project state (for advanced operations)
1703
- */
1704
- getProjectState() {
1705
- return this.projectState;
1706
- }
1707
- /**
1708
- * Get agency modules (for watch mode integration)
1709
- */
1710
- getGoalManager() {
1711
- return this.goalManager;
1712
- }
1713
- getRiskPredictor() {
1714
- return this.riskPredictor;
1715
- }
1716
- getHypothesisEngine() {
1717
- return this.hypothesisEngine;
1718
- }
1719
- getEscalationManager() {
1720
- return this.escalationManager;
1721
- }
1722
- getMetaLearner() {
1723
- return this.metaLearner;
1724
- }
1725
- /**
1726
- * Get a rich agency status for display in watch mode
1727
- */
1728
- async getAgencyStatus() {
1729
- const goals = this.projectState.getAllGoals();
1730
- const activeGoals = goals.filter((g) => g.status === "active");
1731
- const completedGoals = goals.filter((g) => g.status === "achieved");
1732
- const hypotheses = this.projectState.getAllHypotheses();
1733
- const testingHypotheses = hypotheses.filter((h) => h.status === "testing");
1734
- const validatedHypotheses = hypotheses.filter((h) => h.status === "validated");
1735
- const metrics = this.projectState.getMetrics();
1736
- const budget = this.projectState.getRiskBudget();
1737
- const dailyActionsRemaining = budget.daily - budget.usedToday;
1738
- let riskLevel = "low";
1739
- if (dailyActionsRemaining <= 1) riskLevel = "critical";
1740
- else if (dailyActionsRemaining <= 3) riskLevel = "high";
1741
- else if (dailyActionsRemaining <= 5) riskLevel = "medium";
1742
- const totalFeedback = metrics.helpfulInsights + metrics.dismissedInsights + metrics.actedOnInsights;
1743
- const effectiveness = totalFeedback > 0 ? Math.round((metrics.helpfulInsights + metrics.actedOnInsights) / totalFeedback * 100) : 100;
1744
- const topGoal = activeGoals[0]?.description;
1745
- const topHypothesis = testingHypotheses[0]?.statement?.slice(0, 50);
1746
- const result = {
1747
- goals: {
1748
- active: activeGoals.length,
1749
- completed: completedGoals.length
1750
- },
1751
- hypotheses: {
1752
- testing: testingHypotheses.length,
1753
- validated: validatedHypotheses.length
1754
- },
1755
- riskLevel,
1756
- scanFrequency: this.projectState.getScanFrequencyMs(),
1757
- effectiveness,
1758
- isQuietHours: this.projectState.isQuietHours()
1759
- };
1760
- if (topGoal) result.goals.topGoal = topGoal;
1761
- if (topHypothesis) result.hypotheses.topHypothesis = topHypothesis;
1762
- return result;
1763
- }
1764
- /**
1765
- * Get a summary for the current state
1766
- */
1767
- getSummary(issues) {
1768
- const critical = issues.filter((i) => i.severity === "critical").length;
1769
- const serious = issues.filter((i) => i.severity === "serious").length;
1770
- const total = issues.length;
1771
- if (total === 0) {
1772
- return "All clear. Your code looks good.";
1773
- }
1774
- if (critical > 0) {
1775
- return `${critical} critical issue${critical > 1 ? "s" : ""} need${critical === 1 ? "s" : ""} immediate attention.`;
1776
- }
1777
- if (serious > 0) {
1778
- return `${serious} serious issue${serious > 1 ? "s" : ""} worth reviewing before shipping.`;
1779
- }
1780
- return `${total} minor thing${total > 1 ? "s" : ""} to polish when you have time.`;
1781
- }
1782
- // === Private helpers ===
1783
- shouldWarnBeforePush(issues) {
1784
- const critical = issues.filter((i) => i.severity === "critical").length;
1785
- const serious = issues.filter((i) => i.severity === "serious").length;
1786
- return critical > 0 || serious >= 3;
1787
- }
1788
- /**
1789
- * Check if we should create an insight of this type (cooldown not expired)
1790
- */
1791
- canCreateInsight(insightKey) {
1792
- return this.insightStore.canCreateInsight(insightKey);
1793
- }
1794
- /**
1795
- * Mark that we created an insight of this type
1796
- */
1797
- async markInsightCreated(insightKey) {
1798
- await this.insightStore.markInsightCreated(insightKey);
1799
- }
1800
- createInsight(params) {
1801
- return {
1802
- id: `insight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
1803
- timestamp: Date.now(),
1804
- dismissed: false,
1805
- relatedIssues: params.relatedIssues || [],
1806
- ...params
1807
- };
1808
- }
1809
- pick(arr) {
1810
- return arr[Math.floor(Math.random() * arr.length)];
1811
- }
1812
- };
1813
- var agentInstances = /* @__PURE__ */ new Map();
1814
- function getTrieAgent(projectPath) {
1815
- let agent = agentInstances.get(projectPath);
1816
- if (!agent) {
1817
- agent = new TrieAgent(projectPath);
1818
- agentInstances.set(projectPath, agent);
1819
- }
1820
- return agent;
1821
- }
1822
-
1823
- export {
1824
- TrieAgent,
1825
- getTrieAgent
1826
- };
1827
- //# sourceMappingURL=chunk-7IO4YUI3.js.map