@triedotdev/mcp 1.0.168 → 1.0.170

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