@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,846 +0,0 @@
1
- import {
2
- getStorage
3
- } from "./chunk-BUTOP5EB.js";
4
- import {
5
- tryGetClient
6
- } from "./chunk-FQ45QP5A.js";
7
- import {
8
- searchIssues
9
- } from "./chunk-KCUOWRPX.js";
10
- import {
11
- BackupManager,
12
- GlobalPatternsIndexSchema,
13
- safeParseAndValidate
14
- } from "./chunk-EFWVF6TI.js";
15
- import {
16
- atomicWriteJSON
17
- } from "./chunk-43X6JBEM.js";
18
-
19
- // src/memory/global-memory.ts
20
- import { mkdir, writeFile, readFile, readdir } from "fs/promises";
21
- import { createHash } from "crypto";
22
- import { existsSync } from "fs";
23
- import { join } from "path";
24
- import { homedir } from "os";
25
- var GLOBAL_TRIE_DIR = join(homedir(), ".trie");
26
- var GLOBAL_MEMORY_DIR = join(GLOBAL_TRIE_DIR, "memory");
27
- async function recordToGlobalMemory(issues, projectName, projectPath) {
28
- await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });
29
- await mkdir(join(GLOBAL_MEMORY_DIR, "projects"), { recursive: true });
30
- const patterns = await loadGlobalPatterns();
31
- const now = (/* @__PURE__ */ new Date()).toISOString();
32
- for (const issue of issues) {
33
- const patternId = extractPatternId(issue);
34
- const existing = patterns.find((p) => p.id === patternId);
35
- if (existing) {
36
- existing.occurrences++;
37
- existing.lastSeen = now;
38
- if (!existing.projects.includes(projectName)) {
39
- existing.projects.push(projectName);
40
- }
41
- } else {
42
- patterns.push({
43
- id: patternId,
44
- pattern: issue.issue.slice(0, 200),
45
- description: issue.fix.slice(0, 200),
46
- severity: issue.severity,
47
- agent: issue.agent,
48
- occurrences: 1,
49
- projects: [projectName],
50
- firstSeen: now,
51
- lastSeen: now
52
- });
53
- }
54
- }
55
- await saveGlobalPatterns(patterns);
56
- const summaryPath = join(GLOBAL_MEMORY_DIR, "projects", `${sanitizeName(projectName)}.json`);
57
- const summary = {
58
- name: projectName,
59
- path: projectPath,
60
- lastScan: now,
61
- totalIssues: issues.length,
62
- patterns: [...new Set(issues.map((i) => extractPatternId(i)))]
63
- };
64
- await atomicWriteJSON(summaryPath, summary);
65
- }
66
- async function findCrossProjectPatterns(minOccurrences = 2) {
67
- const patterns = await loadGlobalPatterns();
68
- return patterns.filter((p) => p.projects.length >= minOccurrences).sort((a, b) => b.occurrences - a.occurrences);
69
- }
70
- async function listTrackedProjects() {
71
- const projectsDir = join(GLOBAL_MEMORY_DIR, "projects");
72
- try {
73
- if (!existsSync(projectsDir)) return [];
74
- const files = await readdir(projectsDir);
75
- const summaries = [];
76
- for (const file of files) {
77
- if (!file.endsWith(".json")) continue;
78
- try {
79
- const content = await readFile(join(projectsDir, file), "utf-8");
80
- summaries.push(JSON.parse(content));
81
- } catch {
82
- }
83
- }
84
- return summaries.sort(
85
- (a, b) => new Date(b.lastScan).getTime() - new Date(a.lastScan).getTime()
86
- );
87
- } catch {
88
- return [];
89
- }
90
- }
91
- async function getGlobalMemoryStats() {
92
- const patterns = await loadGlobalPatterns();
93
- const projects = await listTrackedProjects();
94
- const MAX_PATTERNS = 500;
95
- const patternsByAgent = {};
96
- for (const pattern of patterns) {
97
- patternsByAgent[pattern.agent] = (patternsByAgent[pattern.agent] || 0) + 1;
98
- }
99
- const totalOccurrences = patterns.reduce((sum, p) => sum + p.occurrences, 0);
100
- const avgOccurrences = patterns.length > 0 ? totalOccurrences / patterns.length : 0;
101
- return {
102
- totalPatterns: patterns.length,
103
- crossProjectPatterns: patterns.filter((p) => p.projects.length >= 2).length,
104
- trackedProjects: projects.length,
105
- totalOccurrences,
106
- fixedPatterns: patterns.filter((p) => p.fixApplied).length,
107
- patternsByAgent,
108
- capacityInfo: {
109
- current: patterns.length,
110
- max: MAX_PATTERNS,
111
- percentFull: Math.round(patterns.length / MAX_PATTERNS * 100),
112
- isAtCap: patterns.length >= MAX_PATTERNS
113
- },
114
- deduplicationStats: {
115
- uniquePatterns: patterns.length,
116
- averageOccurrences: Math.round(avgOccurrences * 10) / 10
117
- }
118
- };
119
- }
120
- async function updateGlobalMemoryMd() {
121
- const patterns = await loadGlobalPatterns();
122
- const crossProject = patterns.filter((p) => p.projects.length >= 2);
123
- const projects = await listTrackedProjects();
124
- const lines = [
125
- "# Global Trie Memory",
126
- "",
127
- "> Auto-generated file tracking patterns across all your projects.",
128
- `> Last updated: ${(/* @__PURE__ */ new Date()).toISOString()}`,
129
- "",
130
- "## Summary",
131
- "",
132
- `- **Projects tracked:** ${projects.length}`,
133
- `- **Total patterns:** ${patterns.length}`,
134
- `- **Cross-project patterns:** ${crossProject.length}`,
135
- "",
136
- "## Cross-Project Patterns",
137
- "",
138
- "These issues appear in multiple projects:",
139
- ""
140
- ];
141
- for (const p of crossProject.slice(0, 20)) {
142
- lines.push(
143
- `### ${p.pattern.slice(0, 60)}${p.pattern.length > 60 ? "..." : ""}`,
144
- "",
145
- `- **Severity:** ${p.severity}`,
146
- `- **Agent:** ${p.agent}`,
147
- `- **Occurrences:** ${p.occurrences} across ${p.projects.length} projects`,
148
- `- **Projects:** ${p.projects.slice(0, 5).join(", ")}${p.projects.length > 5 ? "..." : ""}`
149
- );
150
- if (p.fixApplied) {
151
- lines.push(`- **Fixed in:** ${p.fixApplied.project} on ${p.fixApplied.timestamp.split("T")[0]}`);
152
- } else {
153
- lines.push("- **Status:** Not fixed");
154
- }
155
- lines.push("");
156
- }
157
- lines.push(
158
- "## Tracked Projects",
159
- "",
160
- "| Project | Last Scan | Issues |",
161
- "|---------|-----------|--------|"
162
- );
163
- for (const p of projects.slice(0, 20)) {
164
- lines.push(`| ${p.name} | ${p.lastScan.split("T")[0]} | ${p.totalIssues} |`);
165
- }
166
- lines.push("", "---", "", "*This file is auto-generated by Trie. Do not edit manually.*");
167
- await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });
168
- await writeFile(join(GLOBAL_MEMORY_DIR, "GLOBAL_MEMORY.md"), lines.join("\n"));
169
- }
170
- async function searchGlobalPatterns(query, options = {}) {
171
- const patterns = await loadGlobalPatterns();
172
- const limit = options.limit || 10;
173
- const queryTerms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 2);
174
- const scored = patterns.filter((p) => {
175
- if (options.severity && !options.severity.includes(p.severity)) return false;
176
- if (options.agent && p.agent !== options.agent) return false;
177
- return true;
178
- }).map((p) => {
179
- const text = `${p.pattern} ${p.description} ${p.agent}`.toLowerCase();
180
- let score = 0;
181
- for (const term of queryTerms) {
182
- if (text.includes(term)) score++;
183
- }
184
- return { pattern: p, score };
185
- }).filter((s) => s.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
186
- return scored.map((s) => s.pattern);
187
- }
188
- async function loadGlobalPatterns() {
189
- const patternsPath = join(GLOBAL_MEMORY_DIR, "global-patterns.json");
190
- try {
191
- if (existsSync(patternsPath)) {
192
- const content = await readFile(patternsPath, "utf-8");
193
- const result = safeParseAndValidate(content, GlobalPatternsIndexSchema);
194
- if (result.success) {
195
- return result.data;
196
- }
197
- const backupManager = new BackupManager(patternsPath);
198
- if (await backupManager.recoverFromBackup()) {
199
- const recovered = await readFile(patternsPath, "utf-8");
200
- const recoveredResult = safeParseAndValidate(recovered, GlobalPatternsIndexSchema);
201
- if (recoveredResult.success) {
202
- return recoveredResult.data;
203
- }
204
- }
205
- }
206
- } catch {
207
- }
208
- return [];
209
- }
210
- async function saveGlobalPatterns(patterns) {
211
- await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });
212
- const patternsPath = join(GLOBAL_MEMORY_DIR, "global-patterns.json");
213
- const patternMap = /* @__PURE__ */ new Map();
214
- for (const pattern of patterns) {
215
- const existing = patternMap.get(pattern.id);
216
- if (existing) {
217
- existing.occurrences += pattern.occurrences;
218
- for (const proj of pattern.projects) {
219
- if (!existing.projects.includes(proj)) {
220
- existing.projects.push(proj);
221
- }
222
- }
223
- existing.lastSeen = pattern.lastSeen > existing.lastSeen ? pattern.lastSeen : existing.lastSeen;
224
- } else {
225
- patternMap.set(pattern.id, pattern);
226
- }
227
- }
228
- const deduplicated = Array.from(patternMap.values());
229
- const pruned = intelligentPruneGlobalPatterns(deduplicated, 500);
230
- const backupManager = new BackupManager(patternsPath);
231
- await backupManager.createBackup();
232
- await atomicWriteJSON(patternsPath, pruned);
233
- }
234
- function intelligentPruneGlobalPatterns(patterns, targetCount) {
235
- if (patterns.length <= targetCount) {
236
- return patterns;
237
- }
238
- const severityWeight = {
239
- critical: 100,
240
- high: 50,
241
- moderate: 20,
242
- low: 10,
243
- info: 5
244
- };
245
- const scored = patterns.map((pattern) => {
246
- const ageInDays = (Date.now() - new Date(pattern.lastSeen).getTime()) / (1e3 * 60 * 60 * 24);
247
- const recencyScore = Math.max(0, 100 - ageInDays * 2);
248
- const severityScore = severityWeight[pattern.severity] || 10;
249
- const crossProjectBonus = (pattern.projects.length - 1) * 30;
250
- const fixedBonus = pattern.fixApplied ? 20 : 0;
251
- const occurrenceScore = Math.min(pattern.occurrences * 2, 100);
252
- return {
253
- pattern,
254
- score: recencyScore + severityScore + crossProjectBonus + fixedBonus + occurrenceScore
255
- };
256
- });
257
- return scored.sort((a, b) => b.score - a.score).slice(0, targetCount).map((s) => s.pattern);
258
- }
259
- function extractPatternId(issue) {
260
- const normalized = issue.issue.toLowerCase().replace(/`[^`]+`/g, "CODE").replace(/\b\d+\b/g, "N").replace(/['"]/g, "").slice(0, 100);
261
- const hash = createHash("sha256").update(normalized).digest("hex").slice(0, 12);
262
- return `${issue.agent}-${issue.severity}-${hash}`;
263
- }
264
- function sanitizeName(name) {
265
- return name.replace(/[^a-zA-Z0-9-_]/g, "-").toLowerCase();
266
- }
267
-
268
- // src/agent/gotcha-predictor.ts
269
- import fs from "fs";
270
- import path from "path";
271
- var GotchaPredictor = class {
272
- projectPath;
273
- graph;
274
- constructor(projectPath, graph) {
275
- this.projectPath = projectPath;
276
- this.graph = graph;
277
- }
278
- async predictGotchas(changedFiles) {
279
- const gotchas = [];
280
- const tickets = (await this.graph.listNodes()).filter((n) => n.type === "linear-ticket");
281
- for (const file of changedFiles) {
282
- const fileGotchas = await this.predictForFile(file, tickets);
283
- gotchas.push(...fileGotchas);
284
- }
285
- return gotchas;
286
- }
287
- async predictForFile(filePath, tickets) {
288
- const gotchas = [];
289
- const fullPath = path.resolve(this.projectPath, filePath);
290
- if (!fs.existsSync(fullPath)) return [];
291
- const content = fs.readFileSync(fullPath, "utf-8");
292
- const storage = getStorage(this.projectPath);
293
- await storage.initialize();
294
- const tags = this.extractTagsFromFile(filePath, []);
295
- const relevantGovernance = await storage.queryGovernance({
296
- tags,
297
- limit: 10
298
- });
299
- const activeBlockers = await storage.queryBlockers({
300
- tags,
301
- limit: 5
302
- });
303
- for (const gov of relevantGovernance) {
304
- if (gov.files.some((f) => f.includes(filePath) || filePath.includes(f))) {
305
- gotchas.push({
306
- id: `gotcha-gov-${gov.id}`,
307
- message: `Governance: ${gov.decision}`,
308
- confidence: 0.85,
309
- riskLevel: "medium",
310
- precedentId: gov.id,
311
- recommendation: gov.reasoning || "Review this governance before making changes",
312
- evidence: {
313
- pastIncidents: [],
314
- matchingPatterns: gov.tags,
315
- relatedTickets: []
316
- }
317
- });
318
- }
319
- }
320
- for (const blocker of activeBlockers) {
321
- gotchas.push({
322
- id: `gotcha-blocker-${blocker.id}`,
323
- message: `\u26A0\uFE0F Active Blocker: ${blocker.blocker}`,
324
- confidence: 0.95,
325
- riskLevel: blocker.impact === "critical" ? "critical" : blocker.impact === "high" ? "high" : "medium",
326
- recommendation: `This area is currently blocked. Consider resolving this before making changes.`,
327
- evidence: {
328
- pastIncidents: [],
329
- matchingPatterns: blocker.tags,
330
- relatedTickets: []
331
- }
332
- });
333
- }
334
- const aiGotchas = await this.analyzeCodeWithAI(filePath, content, relevantGovernance, activeBlockers);
335
- gotchas.push(...aiGotchas);
336
- for (const ticket of tickets) {
337
- const ticketData = ticket.data;
338
- const historicalPrecedents = await this.findHistoricalPrecedents(filePath, ticketData);
339
- if (historicalPrecedents) {
340
- gotchas.push(historicalPrecedents);
341
- }
342
- }
343
- return gotchas;
344
- }
345
- /**
346
- * Use AI to analyze code for potential issues
347
- */
348
- async analyzeCodeWithAI(filePath, content, governance, blockers) {
349
- const client = tryGetClient();
350
- if (!client) return [];
351
- try {
352
- const governanceContext = governance.length > 0 ? `
353
-
354
- Relevant Governance:
355
- ${governance.map((g) => `- ${g.decision}: ${g.reasoning || "No reasoning provided"}`).join("\n")}` : "";
356
- const blockerContext = blockers.length > 0 ? `
357
-
358
- Active Blockers:
359
- ${blockers.map((b) => `- [${b.impact}] ${b.blocker}`).join("\n")}` : "";
360
- const systemPrompt = `You are a senior code reviewer analyzing code for potential issues before changes are shipped.
361
-
362
- Given a file and its context (governance decisions and blockers), identify:
363
- 1. Potential bugs or security issues
364
- 2. Violations of governance decisions
365
- 3. Conflicts with active blockers
366
- 4. Anti-patterns or code smells
367
-
368
- Return your analysis as a JSON array of issues, each with:
369
- {
370
- "message": "Brief description of the issue",
371
- "confidence": 0.0-1.0,
372
- "riskLevel": "low" | "medium" | "high" | "critical",
373
- "recommendation": "Specific recommendation",
374
- "lineNumber": number (if applicable)
375
- }
376
-
377
- IMPORTANT: Only return JSON, no other text. If no issues found, return [].`;
378
- const userPrompt = `File: ${filePath}${governanceContext}${blockerContext}
379
-
380
- Code:
381
- \`\`\`
382
- ${content.slice(0, 5e3)}
383
- \`\`\`
384
-
385
- Analyze this code and return a JSON array of potential issues.`;
386
- const response = await client.messages.create({
387
- model: "claude-sonnet-4-20250514",
388
- max_tokens: 4096,
389
- temperature: 0.2,
390
- system: systemPrompt,
391
- messages: [{ role: "user", content: userPrompt }]
392
- });
393
- const textContent = response.content.filter((block) => block.type === "text").map((block) => block.text).join("");
394
- const jsonMatch = textContent.match(/\[[\s\S]*\]/);
395
- if (!jsonMatch) return [];
396
- const issues = JSON.parse(jsonMatch[0]);
397
- return issues.map((issue, idx) => ({
398
- id: `gotcha-ai-${Date.now()}-${idx}`,
399
- message: issue.message || "AI-detected issue",
400
- confidence: issue.confidence || 0.7,
401
- riskLevel: issue.riskLevel || "medium",
402
- recommendation: issue.recommendation || "Review this code carefully",
403
- evidence: {
404
- pastIncidents: [],
405
- matchingPatterns: ["ai-analysis"],
406
- relatedTickets: []
407
- }
408
- }));
409
- } catch (error) {
410
- return [];
411
- }
412
- }
413
- /**
414
- * Extract tags from file path for storage queries
415
- */
416
- extractTagsFromFile(filePath, _signatures) {
417
- const tags = /* @__PURE__ */ new Set();
418
- const normalized = filePath.toLowerCase();
419
- if (normalized.includes("/auth/")) tags.add("auth");
420
- if (normalized.includes("/payment/")) tags.add("payments");
421
- if (normalized.includes("/api/")) tags.add("api");
422
- if (normalized.includes("/frontend/") || normalized.includes("/ui/")) tags.add("ui");
423
- if (normalized.includes("/backend/")) tags.add("backend");
424
- if (normalized.includes("/database/") || normalized.includes("/models/")) tags.add("database");
425
- return Array.from(tags);
426
- }
427
- async findHistoricalPrecedents(filePath, ticket) {
428
- const similarIssues = await searchIssues(ticket.description, {
429
- workDir: this.projectPath,
430
- limit: 3
431
- });
432
- const relevantIssues = similarIssues.filter((r) => r.issue.file === filePath || r.issue.file.includes(path.basename(filePath)));
433
- const [firstMatch] = relevantIssues;
434
- if (firstMatch) {
435
- const issue = firstMatch.issue;
436
- return {
437
- id: `gotcha-precedent-${ticket.ticketId}-${Date.now()}`,
438
- message: `A similar task in the past caused an issue: "${issue.issue}"`,
439
- confidence: 0.9,
440
- riskLevel: "critical",
441
- precedentId: issue.id,
442
- recommendation: `Last time we worked on something similar here, we had to fix: "${issue.fix}". Check this first.`,
443
- evidence: {
444
- pastIncidents: [issue.id],
445
- matchingPatterns: [],
446
- relatedTickets: [ticket.ticketId]
447
- }
448
- };
449
- }
450
- return null;
451
- }
452
- async synthesizeGotchaExplanation(gotcha) {
453
- const client = tryGetClient();
454
- if (!client) return gotcha.message;
455
- const prompt = `
456
- You are a JIT Defect Predictor. You found a potential "gotcha" for a developer.
457
-
458
- Ticket context: ${gotcha.evidence.relatedTickets.join(", ")}
459
- Tags: ${gotcha.evidence.matchingPatterns.join(", ")}
460
- Past incidents: ${gotcha.evidence.pastIncidents.join(", ")}
461
-
462
- Raw message: ${gotcha.message}
463
- Recommendation: ${gotcha.recommendation}
464
-
465
- Explain this gotcha in a concise, human-friendly way (max 2 sentences).
466
- Make it sound like a senior dev giving a helpful nudge.
467
- `;
468
- try {
469
- const response = await client.messages.create({
470
- model: "claude-3-5-sonnet-20240620",
471
- max_tokens: 100,
472
- messages: [{ role: "user", content: prompt }]
473
- });
474
- const text = response.content.filter((block) => block.type === "text").map((block) => block.text).join("");
475
- return text.trim() || gotcha.message;
476
- } catch {
477
- return gotcha.message;
478
- }
479
- }
480
- };
481
-
482
- // src/integrations/slack.ts
483
- var SlackIntegration = class {
484
- constructor(config) {
485
- this.config = config;
486
- }
487
- /**
488
- * Send scan completion notification
489
- */
490
- async sendScanNotification(_issues, priorityReport, repositoryName, branch = "main") {
491
- const { urgent, high, medium, low } = priorityReport;
492
- const statusEmoji = urgent.length > 0 ? "[URGENT]" : high.length > 0 ? "[HIGH]" : "[OK]";
493
- const message = {
494
- blocks: [
495
- {
496
- type: "section",
497
- text: {
498
- type: "mrkdwn",
499
- text: `${statusEmoji} *Trie Security Scan Complete*
500
- *Repository:* ${repositoryName} (${branch})`
501
- }
502
- },
503
- {
504
- type: "section",
505
- fields: [
506
- {
507
- type: "mrkdwn",
508
- text: `*Urgent:* ${urgent.length}`
509
- },
510
- {
511
- type: "mrkdwn",
512
- text: `*High:* ${high.length}`
513
- },
514
- {
515
- type: "mrkdwn",
516
- text: `*Medium:* ${medium.length}`
517
- },
518
- {
519
- type: "mrkdwn",
520
- text: `*\u{1F539} Low:* ${low.length}`
521
- }
522
- ]
523
- }
524
- ],
525
- attachments: []
526
- };
527
- if (urgent.length > 0) {
528
- const urgentDetails = urgent.slice(0, 5).map(
529
- (group) => `\u2022 ${group.description} (${group.count} instances)`
530
- ).join("\n");
531
- message.attachments.push({
532
- color: "danger",
533
- title: "Urgent Issues - Immediate Action Required",
534
- text: urgentDetails,
535
- footer: urgent.length > 5 ? `... and ${urgent.length - 5} more urgent issues` : void 0
536
- });
537
- }
538
- if (high.length > 0) {
539
- const highDetails = high.slice(0, 3).map(
540
- (group) => `\u2022 ${group.description} (${group.count} instances)`
541
- ).join("\n");
542
- message.attachments.push({
543
- color: "warning",
544
- title: "High Priority Issues",
545
- text: highDetails,
546
- footer: high.length > 3 ? `... and ${high.length - 3} more high priority issues` : void 0
547
- });
548
- }
549
- if (priorityReport.recommendations.length > 0) {
550
- message.attachments.push({
551
- color: "good",
552
- title: "Recommendations",
553
- text: priorityReport.recommendations.slice(0, 3).join("\n")
554
- });
555
- }
556
- await this.sendMessage(message);
557
- }
558
- /**
559
- * Send critical issue alert
560
- */
561
- async sendCriticalAlert(issues, repositoryName) {
562
- const message = {
563
- text: `CRITICAL SECURITY ALERT: ${repositoryName}`,
564
- blocks: [
565
- {
566
- type: "section",
567
- text: {
568
- type: "mrkdwn",
569
- text: `*CRITICAL SECURITY ALERT*
570
- *Repository:* ${repositoryName}
571
- *Critical Issues:* ${issues.length}`
572
- }
573
- }
574
- ],
575
- attachments: issues.slice(0, 5).map((issue) => ({
576
- color: "danger",
577
- title: `${issue.file}:${issue.line || "?"}`,
578
- text: issue.issue.slice(0, 200),
579
- fields: [
580
- {
581
- title: "Fix",
582
- value: issue.fix.slice(0, 100),
583
- short: false
584
- }
585
- ],
586
- footer: `Agent: ${issue.agent}`,
587
- ts: Math.floor(Date.now() / 1e3)
588
- }))
589
- };
590
- if (issues.length > 5) {
591
- message.attachments.push({
592
- color: "danger",
593
- text: `... and ${issues.length - 5} more critical issues. View full report for details.`
594
- });
595
- }
596
- await this.sendMessage(message);
597
- }
598
- /**
599
- * Send team notification
600
- */
601
- async sendTeamNotification(notification) {
602
- const emoji = this.getNotificationEmoji(notification.type);
603
- const message = {
604
- blocks: [
605
- {
606
- type: "section",
607
- text: {
608
- type: "mrkdwn",
609
- text: `${emoji} *${notification.title}*
610
- ${notification.message}`
611
- }
612
- }
613
- ]
614
- };
615
- if (notification.type === "assignment" && notification.data) {
616
- const { assignment, issue } = notification.data;
617
- message.attachments = [{
618
- color: this.getAssignmentColor(assignment.priority),
619
- fields: [
620
- {
621
- title: "Priority",
622
- value: assignment.priority.toUpperCase(),
623
- short: true
624
- },
625
- {
626
- title: "Due Date",
627
- value: assignment.dueDate ? new Date(assignment.dueDate).toLocaleDateString() : "Not set",
628
- short: true
629
- },
630
- {
631
- title: "File",
632
- value: issue.file,
633
- short: false
634
- }
635
- ]
636
- }];
637
- }
638
- await this.sendMessage(message);
639
- }
640
- /**
641
- * Send daily/weekly team summary
642
- */
643
- async sendTeamSummary(period, stats) {
644
- const emoji = period === "daily" ? "[DAILY]" : "[WEEKLY]";
645
- const title = `${emoji} ${period.charAt(0).toUpperCase() + period.slice(1)} Security Summary`;
646
- const message = {
647
- blocks: [
648
- {
649
- type: "section",
650
- text: {
651
- type: "mrkdwn",
652
- text: `*${title}*`
653
- }
654
- },
655
- {
656
- type: "section",
657
- fields: [
658
- {
659
- type: "mrkdwn",
660
- text: `*New Issues:* ${stats.newIssues}`
661
- },
662
- {
663
- type: "mrkdwn",
664
- text: `*\u2705 Resolved:* ${stats.resolvedIssues}`
665
- },
666
- {
667
- type: "mrkdwn",
668
- text: `*Overdue:* ${stats.overdueIssues}`
669
- },
670
- {
671
- type: "mrkdwn",
672
- text: `*Net Change:* ${stats.resolvedIssues - stats.newIssues > 0 ? "+" : ""}${stats.resolvedIssues - stats.newIssues}`
673
- }
674
- ]
675
- }
676
- ],
677
- attachments: []
678
- };
679
- if (stats.topCategories.length > 0) {
680
- const categoriesText = stats.topCategories.slice(0, 5).map((cat) => `\u2022 ${cat.category}: ${cat.count}`).join("\n");
681
- message.attachments.push({
682
- color: "good",
683
- title: "Top Issue Categories",
684
- text: categoriesText
685
- });
686
- }
687
- if (stats.topContributors.length > 0) {
688
- const contributorsText = stats.topContributors.slice(0, 5).map((contrib) => `\u2022 ${contrib.name}: ${contrib.resolved} resolved`).join("\n");
689
- message.attachments.push({
690
- color: "good",
691
- title: "Top Contributors",
692
- text: contributorsText
693
- });
694
- }
695
- await this.sendMessage(message);
696
- }
697
- /**
698
- * Send bulk fix notification
699
- */
700
- async sendBulkFixNotification(fixedGroups, totalFixed, repositoryName) {
701
- const message = {
702
- blocks: [
703
- {
704
- type: "section",
705
- text: {
706
- type: "mrkdwn",
707
- text: `*Bulk Fix Applied*
708
- *Repository:* ${repositoryName}
709
- *Issues Fixed:* ${totalFixed}`
710
- }
711
- }
712
- ],
713
- attachments: [{
714
- color: "good",
715
- title: "\u{1F527} Fixed Issue Groups",
716
- text: fixedGroups.map(
717
- (group) => `\u2022 ${group.description} (${group.count} instances)`
718
- ).join("\n")
719
- }]
720
- };
721
- await this.sendMessage(message);
722
- }
723
- /**
724
- * Send escalation notification
725
- */
726
- async sendEscalationNotification(overdueAssignments) {
727
- const message = {
728
- text: "OVERDUE ISSUE ESCALATION",
729
- blocks: [
730
- {
731
- type: "section",
732
- text: {
733
- type: "mrkdwn",
734
- text: `*Overdue Issue Escalation*
735
- ${overdueAssignments.length} issues are overdue and require attention.`
736
- }
737
- }
738
- ],
739
- attachments: overdueAssignments.map((assignment) => ({
740
- color: "warning",
741
- title: `Issue ${assignment.issueId}`,
742
- fields: [
743
- {
744
- title: "Assignee",
745
- value: assignment.assignee,
746
- short: true
747
- },
748
- {
749
- title: "Days Overdue",
750
- value: assignment.daysOverdue.toString(),
751
- short: true
752
- },
753
- {
754
- title: "Priority",
755
- value: assignment.priority.toUpperCase(),
756
- short: true
757
- }
758
- ]
759
- }))
760
- };
761
- await this.sendMessage(message);
762
- }
763
- /**
764
- * Send message to Slack
765
- */
766
- async sendMessage(message) {
767
- const payload = {
768
- ...message,
769
- channel: this.config.channel || message.channel,
770
- username: this.config.username || "Trie Security Bot",
771
- icon_emoji: this.config.iconEmoji || ":shield:"
772
- };
773
- try {
774
- const response = await fetch(this.config.webhookUrl, {
775
- method: "POST",
776
- headers: {
777
- "Content-Type": "application/json"
778
- },
779
- body: JSON.stringify(payload)
780
- });
781
- if (!response.ok) {
782
- throw new Error(`Slack API error: ${response.status} ${response.statusText}`);
783
- }
784
- } catch (error) {
785
- console.error("Failed to send Slack notification:", error);
786
- throw error;
787
- }
788
- }
789
- /**
790
- * Get emoji for notification type
791
- */
792
- getNotificationEmoji(type) {
793
- const emojis = {
794
- assignment: "[ASSIGN]",
795
- escalation: "[ESCALATE]",
796
- completion: "[DONE]",
797
- reminder: "[REMIND]"
798
- };
799
- return emojis[type] ?? "[NOTIFY]";
800
- }
801
- /**
802
- * Get color for assignment priority
803
- */
804
- getAssignmentColor(priority) {
805
- const colors = {
806
- urgent: "danger",
807
- high: "warning",
808
- medium: "good",
809
- low: "#36a64f"
810
- };
811
- return colors[priority] ?? "good";
812
- }
813
- /**
814
- * Test Slack connection
815
- */
816
- async testConnection() {
817
- try {
818
- await this.sendMessage({
819
- text: "Trie Slack Integration Test",
820
- blocks: [{
821
- type: "section",
822
- text: {
823
- type: "mrkdwn",
824
- text: "*Trie Slack Integration Test*\nIf you see this message, the integration is working correctly!"
825
- }
826
- }]
827
- });
828
- return true;
829
- } catch (error) {
830
- console.error("Slack connection test failed:", error);
831
- return false;
832
- }
833
- }
834
- };
835
-
836
- export {
837
- recordToGlobalMemory,
838
- findCrossProjectPatterns,
839
- listTrackedProjects,
840
- getGlobalMemoryStats,
841
- updateGlobalMemoryMd,
842
- searchGlobalPatterns,
843
- SlackIntegration,
844
- GotchaPredictor
845
- };
846
- //# sourceMappingURL=chunk-AHD2CBQ7.js.map