@triedotdev/mcp 1.0.167 → 1.0.169

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 (54) hide show
  1. package/README.md +64 -27
  2. package/dist/{chunk-YDHUCDHM.js → chunk-3XR6WVAW.js} +8 -8
  3. package/dist/{chunk-4MXH2ZPT.js → chunk-7IO4YUI3.js} +8 -8
  4. package/dist/{chunk-7WITSO22.js → chunk-AHD2CBQ7.js} +77 -55
  5. package/dist/chunk-AHD2CBQ7.js.map +1 -0
  6. package/dist/{chunk-575YT2SD.js → chunk-BUTOP5EB.js} +195 -1
  7. package/dist/chunk-BUTOP5EB.js.map +1 -0
  8. package/dist/{chunk-MRHKX5M5.js → chunk-FBNURWRY.js} +3 -3
  9. package/dist/{chunk-YZ6Y2H3P.js → chunk-FVRO5RN3.js} +66 -49
  10. package/dist/chunk-FVRO5RN3.js.map +1 -0
  11. package/dist/{chunk-5BRRRTN6.js → chunk-G3I7SZLW.js} +4 -4
  12. package/dist/{chunk-XTFWT2XM.js → chunk-I2O5OYQT.js} +2 -2
  13. package/dist/{chunk-XE6KQRKZ.js → chunk-KCUOWRPX.js} +2 -2
  14. package/dist/{chunk-LQIMKE3P.js → chunk-SASNMSB5.js} +106 -33
  15. package/dist/{chunk-LQIMKE3P.js.map → chunk-SASNMSB5.js.map} +1 -1
  16. package/dist/cli/main.js +7 -9
  17. package/dist/cli/main.js.map +1 -1
  18. package/dist/cli/yolo-daemon.js +10 -12
  19. package/dist/cli/yolo-daemon.js.map +1 -1
  20. package/dist/{fast-analyzer-XXYMOXRK.js → fast-analyzer-3GCCZMLK.js} +3 -3
  21. package/dist/{goal-manager-YOB7VWK7.js → goal-manager-QUKX2W6C.js} +3 -3
  22. package/dist/{goal-validator-ULKIBDPX.js → goal-validator-2SFSKKVU.js} +3 -3
  23. package/dist/{hypothesis-7BFFT5JY.js → hypothesis-KCPBR652.js} +3 -3
  24. package/dist/index.js +11 -13
  25. package/dist/index.js.map +1 -1
  26. package/dist/{issue-store-ZIRP23EP.js → issue-store-YAXTNRRY.js} +2 -2
  27. package/dist/server/mcp-server.js +11 -13
  28. package/dist/{tiered-storage-Z3YCR465.js → tiered-storage-DYNC5CQ6.js} +3 -2
  29. package/dist/{trie-agent-3YDPEGHJ.js → trie-agent-I3HAHY2G.js} +7 -9
  30. package/dist/{chunk-OMR4YCBS.js → vibe-code-signatures-5ZULYP3D.js} +4 -4
  31. package/dist/{chunk-OMR4YCBS.js.map → vibe-code-signatures-5ZULYP3D.js.map} +1 -1
  32. package/dist/{chunk-SY6KQG44.js → vulnerability-signatures-2URZSXAQ.js} +5 -5
  33. package/dist/{chunk-SY6KQG44.js.map → vulnerability-signatures-2URZSXAQ.js.map} +1 -1
  34. package/package.json +1 -1
  35. package/dist/chunk-575YT2SD.js.map +0 -1
  36. package/dist/chunk-7WITSO22.js.map +0 -1
  37. package/dist/chunk-YZ6Y2H3P.js.map +0 -1
  38. package/dist/vibe-code-signatures-F6URTBW3.js +0 -16
  39. package/dist/vibe-code-signatures-F6URTBW3.js.map +0 -1
  40. package/dist/vulnerability-signatures-T7SKHORW.js +0 -18
  41. package/dist/vulnerability-signatures-T7SKHORW.js.map +0 -1
  42. /package/dist/{chunk-YDHUCDHM.js.map → chunk-3XR6WVAW.js.map} +0 -0
  43. /package/dist/{chunk-4MXH2ZPT.js.map → chunk-7IO4YUI3.js.map} +0 -0
  44. /package/dist/{chunk-MRHKX5M5.js.map → chunk-FBNURWRY.js.map} +0 -0
  45. /package/dist/{chunk-5BRRRTN6.js.map → chunk-G3I7SZLW.js.map} +0 -0
  46. /package/dist/{chunk-XTFWT2XM.js.map → chunk-I2O5OYQT.js.map} +0 -0
  47. /package/dist/{chunk-XE6KQRKZ.js.map → chunk-KCUOWRPX.js.map} +0 -0
  48. /package/dist/{fast-analyzer-XXYMOXRK.js.map → fast-analyzer-3GCCZMLK.js.map} +0 -0
  49. /package/dist/{goal-manager-YOB7VWK7.js.map → goal-manager-QUKX2W6C.js.map} +0 -0
  50. /package/dist/{goal-validator-ULKIBDPX.js.map → goal-validator-2SFSKKVU.js.map} +0 -0
  51. /package/dist/{hypothesis-7BFFT5JY.js.map → hypothesis-KCPBR652.js.map} +0 -0
  52. /package/dist/{issue-store-ZIRP23EP.js.map → issue-store-YAXTNRRY.js.map} +0 -0
  53. /package/dist/{tiered-storage-Z3YCR465.js.map → tiered-storage-DYNC5CQ6.js.map} +0 -0
  54. /package/dist/{trie-agent-3YDPEGHJ.js.map → trie-agent-I3HAHY2G.js.map} +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Trie: Governance ledger for agent-human teams
2
2
 
3
- **Decision memory that travels from Cursor → CLI → CI/CD, keeping agents and humans aligned.**
3
+ **Context that travels from Agents → CLI → CI/CD, keeping agents and humans aligned.**
4
4
 
5
5
  [![Download Workspace](https://img.shields.io/badge/Download-Trie%20Workspace-blue)](https://www.trie.dev) [![Follow on X](https://img.shields.io/badge/Follow-@louiskishfy-1DA1F2?logo=x)](https://x.com/louiskishfy)
6
6
 
@@ -23,7 +23,7 @@ Trie keeps a **governance ledger**—a tamper-evident record of decisions, incid
23
23
  - **Governance ledger** - Decision memory with Git-backed audit trail and digital signatures
24
24
  - **Cross-tool context** - Same ledger in Cursor, CLI, CI/CD—no coordination needed
25
25
 
26
- Think of it as **double-entry bookkeeping for code decisions**—not blockchain-level immutability, but tamper-evident accountability that works with Git and your existing workflow.
26
+ Think of it as **double-entry bookkeeping for code decisions**—tamper-evident accountability that works with Git and your existing workflow.
27
27
 
28
28
  ## Quick Start
29
29
 
@@ -72,11 +72,20 @@ trie watch
72
72
  ```
73
73
 
74
74
  **Features:**
75
- - Interactive dashboard with goals, memory, and analysis activity
76
- - AI-powered goal checking using semantic understanding (not just keywords)
77
- - Token-aware to manage AI costs
78
- - Smart caching to avoid duplicate scans
79
- - Real-time nudges when violations are detected
75
+ - **Interactive dashboard** with goals, memory, and analysis activity
76
+ - **AI-powered goal checking** using semantic understanding (not just keywords)
77
+ - **AI-powered Gotcha Prediction** - Automatically analyzes changed files for potential problems using Claude
78
+ - **AI-powered Learning** - Learns from git history (fix/revert commits) every 10 file changes
79
+ - **Signal extraction** - Extracts governance decisions, facts, and blockers from code changes
80
+ - **Token-aware** to manage AI costs
81
+ - **Smart caching** to avoid duplicate scans
82
+ - **Real-time nudges** when violations are detected
83
+
84
+ **How AI integration works in watch mode:**
85
+ 1. When files change, AI extracts structured signals (governance, facts, blockers)
86
+ 2. Gotcha Predictor analyzes changes for potential problems using Claude Sonnet 4
87
+ 3. Learning Engine periodically learns from git history to improve predictions
88
+ 4. All findings are stored in the governance ledger for future reference
80
89
 
81
90
  Run in background with screen or tmux:
82
91
  ```bash
@@ -86,12 +95,16 @@ trie watch
86
95
  # Reattach: screen -r trie-watch
87
96
  ```
88
97
 
89
- ### 2. Predictive Analysis (`trie gotcha`)
98
+ ### 2. AI-Powered Predictive Analysis (`trie gotcha`)
90
99
 
91
- Predicts problems before you ship based on your actual incident history:
100
+ Uses Claude (Anthropic) to predict problems before you ship, combining:
101
+ - **AI code analysis** - Semantic understanding of bugs, security issues, and anti-patterns
102
+ - **Governance context** - Relevant decisions and blockers from the ledger
103
+ - **Historical incidents** - Past regressions in the same files
104
+ - **Active tickets** - Linear tickets that might conflict
92
105
 
93
106
  ```bash
94
- # Check current changes for risks
107
+ # Check current changes for risks (requires ANTHROPIC_API_KEY)
95
108
  trie gotcha
96
109
 
97
110
  # Connect to Linear for JIT defect prediction
@@ -99,10 +112,12 @@ trie linear auth <your-api-key>
99
112
  trie linear sync
100
113
  ```
101
114
 
102
- Trie warns you if your current changes correlate with:
103
- - Historical regressions in the same files
104
- - High-risk patterns from past incidents
105
- - Active tickets that might conflict
115
+ **How it works:**
116
+ 1. Analyzes changed files with Claude Sonnet 4
117
+ 2. Checks against governance decisions and active blockers
118
+ 3. Searches for similar past incidents
119
+ 4. Returns structured predictions with risk levels and recommendations
120
+ 5. Falls back gracefully if AI unavailable
106
121
 
107
122
  ### 3. Governance Ledger
108
123
 
@@ -391,6 +406,21 @@ Trie maintains two complementary memory systems:
391
406
 
392
407
  Both systems sync across your team and travel with your codebase via Git.
393
408
 
409
+ ### Trie-Based Autocomplete
410
+
411
+ Trie uses prefix trees (tries) for fast O(m) autocomplete on ledger data:
412
+
413
+ **Ledger Trie** (`src/trie/ledger-trie.ts`)
414
+ - Indexes governance tags for discovery (e.g., "auth" → "auth", "authentication", "authorization")
415
+ - Indexes file paths from governance for quick lookups
416
+ - Indexes agent names for history queries
417
+ - Integrated into tiered storage for instant autocomplete
418
+
419
+ **Usage in MCP:**
420
+ - Agents can autocomplete tags when querying governance
421
+ - Fast prefix search on file paths and agent names
422
+ - Makes the ledger more discoverable and navigable
423
+
394
424
  ### File Structure
395
425
 
396
426
  ```
@@ -411,19 +441,34 @@ your-project/
411
441
  └── .git/
412
442
  ```
413
443
 
414
- ### Signal Extraction
444
+ ### Signal Extraction & AI Analysis
445
+
446
+ Trie uses AI throughout for intelligent analysis:
415
447
 
448
+ **Signal Extraction** (`signal-extractor.ts`)
416
449
  Instead of dumping raw logs into context, Trie extracts structured signals:
417
450
 
418
451
  **Input:** Incident report, commit, conversation
419
- **Extraction:** AI pulls out structured data:
420
- - **Decisions**: "Chose bcrypt over sha256 for password hashing"
452
+ **Extraction:** AI (Claude Haiku/Sonnet) pulls out structured data:
453
+ - **Governance**: "Chose bcrypt over sha256 for password hashing"
421
454
  - **Facts**: "Stripe requires TLS 1.2+ for EU transactions"
422
455
  - **Blockers**: "Missing VAT validation blocks EU checkout"
423
456
  - **Questions**: "Should we cache session tokens?"
424
457
 
425
- **Storage:** Goes to queryable database with embeddings
426
- **Query:** Agents ask for targeted context, not everything at once
458
+ **Storage:** Goes to queryable database with trie-based indexing
459
+ **Query:** Agents ask for targeted context via autocomplete, not everything at once
460
+
461
+ **AI-Powered Learning** (`learning-engine.ts`)
462
+ - Analyzes git `fix` and `revert` commits to understand root causes
463
+ - Extracts patterns and categories (logic-error, null-check, race-condition)
464
+ - Stores lessons in the ledger for future predictions
465
+ - Falls back gracefully if AI unavailable
466
+
467
+ **AI-Powered Gotcha** (`gotcha-predictor.ts`)
468
+ - Analyzes code semantically for bugs and security issues
469
+ - Considers governance context and active blockers
470
+ - Returns structured predictions with risk levels
471
+ - Uses Claude Sonnet 4 for deep code understanding
427
472
 
428
473
  This prevents context pollution and keeps agents focused on relevant signals.
429
474
 
@@ -526,14 +571,6 @@ Create `.trie/config.json`:
526
571
  }
527
572
  ```
528
573
 
529
- ## Why Trie Exists
530
-
531
- When agents and humans ship code together, coordination becomes the bottleneck. Context fragments across tools, decisions get forgotten, and nothing prevents repeating the same mistakes.
532
-
533
- Trie solves this with a governance ledger—a tamper-evident record that travels with your code. Every tool reads from the same ledger, so agents and humans stay aligned. Teams that can coordinate contributors (human and AI) without losing coherence will ship faster and more reliably.
534
-
535
- As codebases move toward agent autonomy—agents that merge PRs, manage rollouts, and monitor production—governance becomes critical. Trie keeps your work compliant, scales your contributors, and turns your decision history into durable institutional knowledge.
536
-
537
574
  ## Troubleshooting
538
575
 
539
576
  **Trie not finding issues**: You haven't taught Trie about your patterns yet. Use `trie tell` to report incidents.
@@ -42,14 +42,14 @@ import {
42
42
  TrieWatchTool,
43
43
  getPrompt,
44
44
  getSystemPrompt
45
- } from "./chunk-LQIMKE3P.js";
45
+ } from "./chunk-SASNMSB5.js";
46
46
  import {
47
47
  CodebaseIndex
48
48
  } from "./chunk-Q5EKA5YA.js";
49
49
  import {
50
50
  formatFriendlyError,
51
51
  isTrieInitialized
52
- } from "./chunk-YZ6Y2H3P.js";
52
+ } from "./chunk-FVRO5RN3.js";
53
53
  import {
54
54
  exportToJson
55
55
  } from "./chunk-OBQ74FOU.js";
@@ -61,13 +61,13 @@ import {
61
61
  getGlobalMemoryStats,
62
62
  listTrackedProjects,
63
63
  searchGlobalPatterns
64
- } from "./chunk-7WITSO22.js";
64
+ } from "./chunk-AHD2CBQ7.js";
65
65
  import {
66
66
  ContextGraph
67
67
  } from "./chunk-VUL52BQL.js";
68
68
  import {
69
69
  getStorage
70
- } from "./chunk-575YT2SD.js";
70
+ } from "./chunk-BUTOP5EB.js";
71
71
  import {
72
72
  findSimilarIssues,
73
73
  getMemoryStats,
@@ -75,7 +75,7 @@ import {
75
75
  markIssueResolved,
76
76
  purgeIssues,
77
77
  searchIssues
78
- } from "./chunk-XE6KQRKZ.js";
78
+ } from "./chunk-KCUOWRPX.js";
79
79
  import {
80
80
  getTrieDirectory,
81
81
  getWorkingDirectory
@@ -3255,8 +3255,8 @@ This information is automatically available to Claude Code, Cursor, and other AI
3255
3255
  }
3256
3256
  }
3257
3257
  async getSignaturesResource(uri) {
3258
- const { getVulnerabilityStats } = await import("./vulnerability-signatures-T7SKHORW.js");
3259
- const { getVibeCodeStats } = await import("./vibe-code-signatures-F6URTBW3.js");
3258
+ const { getVulnerabilityStats } = await import("./vulnerability-signatures-2URZSXAQ.js");
3259
+ const { getVibeCodeStats } = await import("./vibe-code-signatures-5ZULYP3D.js");
3260
3260
  const vulnStats = getVulnerabilityStats();
3261
3261
  const vibeStats = getVibeCodeStats();
3262
3262
  return {
@@ -4008,4 +4008,4 @@ export {
4008
4008
  MCPServer,
4009
4009
  startServer
4010
4010
  };
4011
- //# sourceMappingURL=chunk-YDHUCDHM.js.map
4011
+ //# sourceMappingURL=chunk-3XR6WVAW.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  getHypothesisEngine
3
- } from "./chunk-XTFWT2XM.js";
3
+ } from "./chunk-I2O5OYQT.js";
4
4
  import {
5
5
  getGoalManager
6
- } from "./chunk-MRHKX5M5.js";
6
+ } from "./chunk-FBNURWRY.js";
7
7
  import {
8
8
  getInsightStore
9
9
  } from "./chunk-T63OHG4Q.js";
@@ -12,13 +12,13 @@ import {
12
12
  SlackIntegration,
13
13
  findCrossProjectPatterns,
14
14
  recordToGlobalMemory
15
- } from "./chunk-7WITSO22.js";
15
+ } from "./chunk-AHD2CBQ7.js";
16
16
  import {
17
17
  ContextGraph
18
18
  } from "./chunk-VUL52BQL.js";
19
19
  import {
20
20
  getStorage
21
- } from "./chunk-575YT2SD.js";
21
+ } from "./chunk-BUTOP5EB.js";
22
22
  import {
23
23
  isAIAvailable,
24
24
  runAIAnalysis
@@ -29,7 +29,7 @@ import {
29
29
  getIssueHash,
30
30
  searchIssues,
31
31
  storeIssues
32
- } from "./chunk-XE6KQRKZ.js";
32
+ } from "./chunk-KCUOWRPX.js";
33
33
  import {
34
34
  getProjectState
35
35
  } from "./chunk-GTKYBOXL.js";
@@ -1581,13 +1581,13 @@ var TrieAgent = class {
1581
1581
  await this.projectState.recordScan();
1582
1582
  try {
1583
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-YOB7VWK7.js");
1584
+ const { calculateAdaptiveScanFrequency } = await import("./goal-manager-QUKX2W6C.js");
1585
1585
  const result = await calculateAdaptiveScanFrequency(riskLevel);
1586
1586
  await this.projectState.setScanFrequency(result.frequencyMs);
1587
1587
  } catch {
1588
1588
  }
1589
1589
  try {
1590
- const { getStorage: getStorage2 } = await import("./tiered-storage-Z3YCR465.js");
1590
+ const { getStorage: getStorage2 } = await import("./tiered-storage-DYNC5CQ6.js");
1591
1591
  const storage = getStorage2(this.projectPath);
1592
1592
  const resolvedIssueIds = [...this.lastIssueHashes].filter((h) => !currentHashes.has(h)).map((h) => {
1593
1593
  return h.split(":").join("-");
@@ -1824,4 +1824,4 @@ export {
1824
1824
  TrieAgent,
1825
1825
  getTrieAgent
1826
1826
  };
1827
- //# sourceMappingURL=chunk-4MXH2ZPT.js.map
1827
+ //# sourceMappingURL=chunk-7IO4YUI3.js.map
@@ -1,18 +1,12 @@
1
- import {
2
- scanForVulnerabilities
3
- } from "./chunk-SY6KQG44.js";
4
- import {
5
- scanForVibeCodeIssues
6
- } from "./chunk-OMR4YCBS.js";
7
1
  import {
8
2
  getStorage
9
- } from "./chunk-575YT2SD.js";
3
+ } from "./chunk-BUTOP5EB.js";
10
4
  import {
11
5
  tryGetClient
12
6
  } from "./chunk-FQ45QP5A.js";
13
7
  import {
14
8
  searchIssues
15
- } from "./chunk-XE6KQRKZ.js";
9
+ } from "./chunk-KCUOWRPX.js";
16
10
  import {
17
11
  BackupManager,
18
12
  GlobalPatternsIndexSchema,
@@ -295,15 +289,9 @@ var GotchaPredictor = class {
295
289
  const fullPath = path.resolve(this.projectPath, filePath);
296
290
  if (!fs.existsSync(fullPath)) return [];
297
291
  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
292
  const storage = getStorage(this.projectPath);
305
293
  await storage.initialize();
306
- const tags = this.extractTagsFromFile(filePath, signatures);
294
+ const tags = this.extractTagsFromFile(filePath, []);
307
295
  const relevantGovernance = await storage.queryGovernance({
308
296
  tags,
309
297
  limit: 10
@@ -343,12 +331,10 @@ var GotchaPredictor = class {
343
331
  }
344
332
  });
345
333
  }
334
+ const aiGotchas = await this.analyzeCodeWithAI(filePath, content, relevantGovernance, activeBlockers);
335
+ gotchas.push(...aiGotchas);
346
336
  for (const ticket of tickets) {
347
337
  const ticketData = ticket.data;
348
- const intentMatch = this.correlateIntentWithSignatures(ticketData, signatures);
349
- if (intentMatch) {
350
- gotchas.push(intentMatch);
351
- }
352
338
  const historicalPrecedents = await this.findHistoricalPrecedents(filePath, ticketData);
353
339
  if (historicalPrecedents) {
354
340
  gotchas.push(historicalPrecedents);
@@ -357,9 +343,77 @@ var GotchaPredictor = class {
357
343
  return gotchas;
358
344
  }
359
345
  /**
360
- * Extract tags from file path and signatures for storage queries
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
361
415
  */
362
- extractTagsFromFile(filePath, signatures) {
416
+ extractTagsFromFile(filePath, _signatures) {
363
417
  const tags = /* @__PURE__ */ new Set();
364
418
  const normalized = filePath.toLowerCase();
365
419
  if (normalized.includes("/auth/")) tags.add("auth");
@@ -368,29 +422,8 @@ var GotchaPredictor = class {
368
422
  if (normalized.includes("/frontend/") || normalized.includes("/ui/")) tags.add("ui");
369
423
  if (normalized.includes("/backend/")) tags.add("backend");
370
424
  if (normalized.includes("/database/") || normalized.includes("/models/")) tags.add("database");
371
- signatures.forEach((sig) => tags.add(sig.toLowerCase()));
372
425
  return Array.from(tags);
373
426
  }
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
427
  async findHistoricalPrecedents(filePath, ticket) {
395
428
  const similarIssues = await searchIssues(ticket.description, {
396
429
  workDir: this.projectPath,
@@ -416,17 +449,6 @@ var GotchaPredictor = class {
416
449
  }
417
450
  return null;
418
451
  }
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
452
  async synthesizeGotchaExplanation(gotcha) {
431
453
  const client = tryGetClient();
432
454
  if (!client) return gotcha.message;
@@ -434,7 +456,7 @@ var GotchaPredictor = class {
434
456
  You are a JIT Defect Predictor. You found a potential "gotcha" for a developer.
435
457
 
436
458
  Ticket context: ${gotcha.evidence.relatedTickets.join(", ")}
437
- Signatures detected: ${gotcha.evidence.matchingPatterns.join(", ")}
459
+ Tags: ${gotcha.evidence.matchingPatterns.join(", ")}
438
460
  Past incidents: ${gotcha.evidence.pastIncidents.join(", ")}
439
461
 
440
462
  Raw message: ${gotcha.message}
@@ -821,4 +843,4 @@ export {
821
843
  SlackIntegration,
822
844
  GotchaPredictor
823
845
  };
824
- //# sourceMappingURL=chunk-7WITSO22.js.map
846
+ //# sourceMappingURL=chunk-AHD2CBQ7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory/global-memory.ts","../src/agent/gotcha-predictor.ts","../src/integrations/slack.ts"],"sourcesContent":["/**\n * Cross-Project Memory\n * \n * Stores and retrieves patterns across all projects.\n * Location: ~/.trie/memory/\n * \n * Phase 1 Hardening:\n * - SHA256 hashing for pattern IDs\n * - Atomic writes to prevent corruption\n * - Rotational backups for recovery\n * - Zod validation for data integrity\n */\n\nimport { mkdir, writeFile, readFile, readdir } from 'fs/promises';\nimport { createHash } from 'crypto';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport type { Issue } from '../types/index.js';\nimport { atomicWriteJSON } from '../utils/atomic-write.js';\nimport { BackupManager } from '../utils/backup-manager.js';\nimport { GlobalPatternsIndexSchema, safeParseAndValidate } from './validation.js';\n\nconst GLOBAL_TRIE_DIR = join(homedir(), '.trie');\nconst GLOBAL_MEMORY_DIR = join(GLOBAL_TRIE_DIR, 'memory');\n\nexport interface GlobalPattern {\n id: string;\n pattern: string;\n description: string;\n severity: string;\n agent: string;\n occurrences: number;\n projects: string[];\n firstSeen: string;\n lastSeen: string;\n fixApplied?: {\n project: string;\n timestamp: string;\n fix: string;\n };\n}\n\nexport interface ProjectSummary {\n name: string;\n path: string;\n lastScan: string;\n totalIssues: number;\n patterns: string[];\n}\n\n/**\n * Record issues to global memory\n */\nexport async function recordToGlobalMemory(\n issues: Issue[],\n projectName: string,\n projectPath: string\n): Promise<void> {\n await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });\n await mkdir(join(GLOBAL_MEMORY_DIR, 'projects'), { recursive: true });\n\n const patterns = await loadGlobalPatterns();\n const now = new Date().toISOString();\n\n for (const issue of issues) {\n const patternId = extractPatternId(issue);\n const existing = patterns.find(p => p.id === patternId);\n\n if (existing) {\n existing.occurrences++;\n existing.lastSeen = now;\n if (!existing.projects.includes(projectName)) {\n existing.projects.push(projectName);\n }\n } else {\n patterns.push({\n id: patternId,\n pattern: issue.issue.slice(0, 200),\n description: issue.fix.slice(0, 200),\n severity: issue.severity,\n agent: issue.agent,\n occurrences: 1,\n projects: [projectName],\n firstSeen: now,\n lastSeen: now,\n });\n }\n }\n\n await saveGlobalPatterns(patterns);\n\n const summaryPath = join(GLOBAL_MEMORY_DIR, 'projects', `${sanitizeName(projectName)}.json`);\n const summary: ProjectSummary = {\n name: projectName,\n path: projectPath,\n lastScan: now,\n totalIssues: issues.length,\n patterns: [...new Set(issues.map(i => extractPatternId(i)))],\n };\n \n // Use atomic write for project summary\n await atomicWriteJSON(summaryPath, summary);\n}\n\n/**\n * Find patterns that appear across multiple projects\n */\nexport async function findCrossProjectPatterns(\n minOccurrences: number = 2\n): Promise<GlobalPattern[]> {\n const patterns = await loadGlobalPatterns();\n return patterns\n .filter(p => p.projects.length >= minOccurrences)\n .sort((a, b) => b.occurrences - a.occurrences);\n}\n\n/**\n * Check if an issue has been fixed in another project\n */\nexport async function findFixFromOtherProjects(\n issue: Issue\n): Promise<GlobalPattern | null> {\n const patterns = await loadGlobalPatterns();\n const patternId = extractPatternId(issue);\n const pattern = patterns.find(p => p.id === patternId);\n\n if (pattern?.fixApplied) {\n return pattern;\n }\n\n return null;\n}\n\n/**\n * Record that a pattern was fixed\n */\nexport async function recordPatternFix(\n issue: Issue,\n projectName: string,\n fix: string\n): Promise<void> {\n const patterns = await loadGlobalPatterns();\n const patternId = extractPatternId(issue);\n const pattern = patterns.find(p => p.id === patternId);\n\n if (pattern && !pattern.fixApplied) {\n pattern.fixApplied = {\n project: projectName,\n timestamp: new Date().toISOString(),\n fix: fix.slice(0, 500),\n };\n await saveGlobalPatterns(patterns);\n }\n}\n\n/**\n * Get all tracked projects\n */\nexport async function listTrackedProjects(): Promise<ProjectSummary[]> {\n const projectsDir = join(GLOBAL_MEMORY_DIR, 'projects');\n \n try {\n if (!existsSync(projectsDir)) return [];\n \n const files = await readdir(projectsDir);\n const summaries: ProjectSummary[] = [];\n \n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n try {\n const content = await readFile(join(projectsDir, file), 'utf-8');\n summaries.push(JSON.parse(content));\n } catch {\n // Skip invalid files\n }\n }\n \n return summaries.sort((a, b) => \n new Date(b.lastScan).getTime() - new Date(a.lastScan).getTime()\n );\n } catch {\n return [];\n }\n}\n\n/**\n * Get global memory statistics\n */\nexport async function getGlobalMemoryStats(): Promise<{\n totalPatterns: number;\n crossProjectPatterns: number;\n trackedProjects: number;\n totalOccurrences: number;\n fixedPatterns: number;\n patternsByAgent: Record<string, number>;\n capacityInfo: {\n current: number;\n max: number;\n percentFull: number;\n isAtCap: boolean;\n };\n deduplicationStats: {\n uniquePatterns: number;\n averageOccurrences: number;\n };\n}> {\n const patterns = await loadGlobalPatterns();\n const projects = await listTrackedProjects();\n \n const MAX_PATTERNS = 500;\n \n // Count patterns by agent type\n const patternsByAgent: Record<string, number> = {};\n for (const pattern of patterns) {\n patternsByAgent[pattern.agent] = (patternsByAgent[pattern.agent] || 0) + 1;\n }\n \n const totalOccurrences = patterns.reduce((sum, p) => sum + p.occurrences, 0);\n const avgOccurrences = patterns.length > 0 ? totalOccurrences / patterns.length : 0;\n \n return {\n totalPatterns: patterns.length,\n crossProjectPatterns: patterns.filter(p => p.projects.length >= 2).length,\n trackedProjects: projects.length,\n totalOccurrences,\n fixedPatterns: patterns.filter(p => p.fixApplied).length,\n patternsByAgent,\n capacityInfo: {\n current: patterns.length,\n max: MAX_PATTERNS,\n percentFull: Math.round((patterns.length / MAX_PATTERNS) * 100),\n isAtCap: patterns.length >= MAX_PATTERNS,\n },\n deduplicationStats: {\n uniquePatterns: patterns.length,\n averageOccurrences: Math.round(avgOccurrences * 10) / 10,\n },\n };\n}\n\n/**\n * Update GLOBAL_MEMORY.md with current patterns\n */\nexport async function updateGlobalMemoryMd(): Promise<void> {\n const patterns = await loadGlobalPatterns();\n const crossProject = patterns.filter(p => p.projects.length >= 2);\n const projects = await listTrackedProjects();\n\n const lines: string[] = [\n '# Global Trie Memory',\n '',\n '> Auto-generated file tracking patterns across all your projects.',\n `> Last updated: ${new Date().toISOString()}`,\n '',\n '## Summary',\n '',\n `- **Projects tracked:** ${projects.length}`,\n `- **Total patterns:** ${patterns.length}`,\n `- **Cross-project patterns:** ${crossProject.length}`,\n '',\n '## Cross-Project Patterns',\n '',\n 'These issues appear in multiple projects:',\n '',\n ];\n \n for (const p of crossProject.slice(0, 20)) {\n lines.push(\n `### ${p.pattern.slice(0, 60)}${p.pattern.length > 60 ? '...' : ''}`,\n '',\n `- **Severity:** ${p.severity}`,\n `- **Agent:** ${p.agent}`,\n `- **Occurrences:** ${p.occurrences} across ${p.projects.length} projects`,\n `- **Projects:** ${p.projects.slice(0, 5).join(', ')}${p.projects.length > 5 ? '...' : ''}`,\n );\n if (p.fixApplied) {\n lines.push(`- **Fixed in:** ${p.fixApplied.project} on ${p.fixApplied.timestamp.split('T')[0]}`);\n } else {\n lines.push('- **Status:** Not fixed');\n }\n lines.push('');\n }\n\n lines.push(\n '## Tracked Projects',\n '',\n '| Project | Last Scan | Issues |',\n '|---------|-----------|--------|',\n );\n \n for (const p of projects.slice(0, 20)) {\n lines.push(`| ${p.name} | ${p.lastScan.split('T')[0]} | ${p.totalIssues} |`);\n }\n\n lines.push('', '---', '', '*This file is auto-generated by Trie. Do not edit manually.*');\n\n await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });\n await writeFile(join(GLOBAL_MEMORY_DIR, 'GLOBAL_MEMORY.md'), lines.join('\\n'));\n}\n\n/**\n * Search global patterns\n */\nexport async function searchGlobalPatterns(\n query: string,\n options: {\n limit?: number;\n severity?: string[];\n agent?: string;\n } = {}\n): Promise<GlobalPattern[]> {\n const patterns = await loadGlobalPatterns();\n const limit = options.limit || 10;\n const queryTerms = query.toLowerCase().split(/\\s+/).filter(t => t.length > 2);\n \n const scored = patterns\n .filter(p => {\n if (options.severity && !options.severity.includes(p.severity)) return false;\n if (options.agent && p.agent !== options.agent) return false;\n return true;\n })\n .map(p => {\n const text = `${p.pattern} ${p.description} ${p.agent}`.toLowerCase();\n let score = 0;\n for (const term of queryTerms) {\n if (text.includes(term)) score++;\n }\n return { pattern: p, score };\n })\n .filter(s => s.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n \n return scored.map(s => s.pattern);\n}\n\n// Private helpers\n\n/**\n * Load global patterns with validation and auto-recovery\n */\nasync function loadGlobalPatterns(): Promise<GlobalPattern[]> {\n const patternsPath = join(GLOBAL_MEMORY_DIR, 'global-patterns.json');\n \n try {\n if (existsSync(patternsPath)) {\n const content = await readFile(patternsPath, 'utf-8');\n const result = safeParseAndValidate(content, GlobalPatternsIndexSchema);\n \n if (result.success) {\n return result.data as GlobalPattern[];\n }\n \n // Validation failed - attempt recovery\n const backupManager = new BackupManager(patternsPath);\n if (await backupManager.recoverFromBackup()) {\n const recovered = await readFile(patternsPath, 'utf-8');\n const recoveredResult = safeParseAndValidate(recovered, GlobalPatternsIndexSchema);\n if (recoveredResult.success) {\n return recoveredResult.data as GlobalPattern[];\n }\n }\n }\n } catch {\n // File doesn't exist or recovery failed\n }\n \n return [];\n}\n\n/**\n * Save global patterns with backup and atomic write\n */\nasync function saveGlobalPatterns(patterns: GlobalPattern[]): Promise<void> {\n await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });\n const patternsPath = join(GLOBAL_MEMORY_DIR, 'global-patterns.json');\n \n // Intelligent deduplication: merge patterns with same ID\n const patternMap = new Map<string, GlobalPattern>();\n for (const pattern of patterns) {\n const existing = patternMap.get(pattern.id);\n if (existing) {\n // Merge: update occurrences, projects, and timestamps\n existing.occurrences += pattern.occurrences;\n for (const proj of pattern.projects) {\n if (!existing.projects.includes(proj)) {\n existing.projects.push(proj);\n }\n }\n existing.lastSeen = pattern.lastSeen > existing.lastSeen ? pattern.lastSeen : existing.lastSeen;\n } else {\n patternMap.set(pattern.id, pattern);\n }\n }\n \n const deduplicated = Array.from(patternMap.values());\n \n // Intelligent pruning: prioritize recent, high-severity, cross-project patterns\n const pruned = intelligentPruneGlobalPatterns(deduplicated, 500);\n \n // Create backup before writing\n const backupManager = new BackupManager(patternsPath);\n await backupManager.createBackup();\n \n // Atomic write\n await atomicWriteJSON(patternsPath, pruned);\n}\n\n/**\n * Intelligently prune global patterns to target count\n * Prioritizes: cross-project, high severity, recent, fixed patterns\n */\nfunction intelligentPruneGlobalPatterns(patterns: GlobalPattern[], targetCount: number): GlobalPattern[] {\n if (patterns.length <= targetCount) {\n return patterns;\n }\n \n const severityWeight: Record<string, number> = {\n critical: 100,\n high: 50,\n moderate: 20,\n low: 10,\n info: 5,\n };\n \n const scored = patterns.map(pattern => {\n const ageInDays = (Date.now() - new Date(pattern.lastSeen).getTime()) / (1000 * 60 * 60 * 24);\n const recencyScore = Math.max(0, 100 - ageInDays * 2);\n const severityScore = severityWeight[pattern.severity] || 10;\n const crossProjectBonus = (pattern.projects.length - 1) * 30; // More projects = higher score\n const fixedBonus = pattern.fixApplied ? 20 : 0;\n const occurrenceScore = Math.min(pattern.occurrences * 2, 100);\n \n return {\n pattern,\n score: recencyScore + severityScore + crossProjectBonus + fixedBonus + occurrenceScore,\n };\n });\n \n return scored\n .sort((a, b) => b.score - a.score)\n .slice(0, targetCount)\n .map(s => s.pattern);\n}\n\n/**\n * Extract a pattern ID using SHA256 for proper deduplication\n * \n * Normalizes the issue text to group similar patterns:\n * - Lowercases\n * - Replaces code snippets with 'CODE'\n * - Replaces numbers with 'N'\n * - Removes quotes\n * \n * Uses SHA256 truncated to 12 chars for collision-free IDs.\n */\nfunction extractPatternId(issue: Issue): string {\n const normalized = issue.issue\n .toLowerCase()\n .replace(/`[^`]+`/g, 'CODE')\n .replace(/\\b\\d+\\b/g, 'N')\n .replace(/['\"]/g, '')\n .slice(0, 100);\n \n const hash = createHash('sha256')\n .update(normalized)\n .digest('hex')\n .slice(0, 12);\n \n return `${issue.agent}-${issue.severity}-${hash}`;\n}\n\nfunction sanitizeName(name: string): string {\n return name.replace(/[^a-zA-Z0-9-_]/g, '-').toLowerCase();\n}\n","import { ContextGraph } from '../context/graph.js';\nimport { searchIssues } from '../memory/issue-store.js';\nimport type { LinearTicketNode, LinearTicketNodeData } from '../context/nodes.js';\nimport { tryGetClient } from '../ai/client.js';\nimport { getStorage } from '../storage/tiered-storage.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface GotchaPrediction {\n id: string;\n message: string;\n confidence: number;\n riskLevel: 'low' | 'medium' | 'high' | 'critical';\n precedentId?: string;\n recommendation: string;\n evidence: {\n pastIncidents: string[];\n matchingPatterns: string[];\n relatedTickets: string[];\n };\n}\n\nexport class GotchaPredictor {\n private readonly projectPath: string;\n private readonly graph: ContextGraph;\n\n constructor(projectPath: string, graph: ContextGraph) {\n this.projectPath = projectPath;\n this.graph = graph;\n }\n\n async predictGotchas(changedFiles: string[]): Promise<GotchaPrediction[]> {\n const gotchas: GotchaPrediction[] = [];\n\n // 1. Get active Linear tickets\n const tickets = (await this.graph.listNodes()).filter(n => n.type === 'linear-ticket') as LinearTicketNode[];\n \n for (const file of changedFiles) {\n const fileGotchas = await this.predictForFile(file, tickets);\n gotchas.push(...fileGotchas);\n }\n\n return gotchas;\n }\n\n private async predictForFile(filePath: string, tickets: LinearTicketNode[]): Promise<GotchaPrediction[]> {\n const gotchas: GotchaPrediction[] = [];\n const fullPath = path.resolve(this.projectPath, filePath);\n\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n\n // Query warm storage for relevant governance and blockers\n const storage = getStorage(this.projectPath);\n await storage.initialize();\n\n // Infer tags from file path\n const tags = this.extractTagsFromFile(filePath, []);\n \n // Query relevant governance for this file/area\n const relevantGovernance = await storage.queryGovernance({\n tags,\n limit: 10,\n });\n\n // Query active blockers for this area\n const activeBlockers = await storage.queryBlockers({\n tags,\n limit: 5,\n });\n\n // Add gotchas from governance ledger\n for (const gov of relevantGovernance) {\n // Check if this file is in the governance record's file list\n if (gov.files.some(f => f.includes(filePath) || filePath.includes(f))) {\n gotchas.push({\n id: `gotcha-gov-${gov.id}`,\n message: `Governance: ${gov.decision}`,\n confidence: 0.85,\n riskLevel: 'medium',\n precedentId: gov.id,\n recommendation: gov.reasoning || 'Review this governance before making changes',\n evidence: {\n pastIncidents: [],\n matchingPatterns: gov.tags,\n relatedTickets: []\n }\n });\n }\n }\n\n // Add gotchas from active blockers\n for (const blocker of activeBlockers) {\n gotchas.push({\n id: `gotcha-blocker-${blocker.id}`,\n message: `⚠️ Active Blocker: ${blocker.blocker}`,\n confidence: 0.95,\n riskLevel: blocker.impact === 'critical' ? 'critical' : \n blocker.impact === 'high' ? 'high' : 'medium',\n recommendation: `This area is currently blocked. Consider resolving this before making changes.`,\n evidence: {\n pastIncidents: [],\n matchingPatterns: blocker.tags,\n relatedTickets: []\n }\n });\n }\n\n // Use AI to analyze the code if available\n const aiGotchas = await this.analyzeCodeWithAI(filePath, content, relevantGovernance, activeBlockers);\n gotchas.push(...aiGotchas);\n\n for (const ticket of tickets) {\n const ticketData = ticket.data as LinearTicketNodeData;\n \n // Correlation: Historical Precedents\n const historicalPrecedents = await this.findHistoricalPrecedents(filePath, ticketData);\n if (historicalPrecedents) {\n gotchas.push(historicalPrecedents);\n }\n }\n\n return gotchas;\n }\n\n /**\n * Use AI to analyze code for potential issues\n */\n private async analyzeCodeWithAI(\n filePath: string,\n content: string,\n governance: Array<{ decision: string; reasoning?: string; tags: string[] }>,\n blockers: Array<{ blocker: string; impact: string; tags: string[] }>\n ): Promise<GotchaPrediction[]> {\n const client = tryGetClient();\n if (!client) return [];\n\n try {\n // Build context from governance and blockers\n const governanceContext = governance.length > 0\n ? `\\n\\nRelevant Governance:\\n${governance.map(g => `- ${g.decision}: ${g.reasoning || 'No reasoning provided'}`).join('\\n')}`\n : '';\n\n const blockerContext = blockers.length > 0\n ? `\\n\\nActive Blockers:\\n${blockers.map(b => `- [${b.impact}] ${b.blocker}`).join('\\n')}`\n : '';\n\n const systemPrompt = `You are a senior code reviewer analyzing code for potential issues before changes are shipped.\n\nGiven a file and its context (governance decisions and blockers), identify:\n1. Potential bugs or security issues\n2. Violations of governance decisions\n3. Conflicts with active blockers\n4. Anti-patterns or code smells\n\nReturn your analysis as a JSON array of issues, each with:\n{\n \"message\": \"Brief description of the issue\",\n \"confidence\": 0.0-1.0,\n \"riskLevel\": \"low\" | \"medium\" | \"high\" | \"critical\",\n \"recommendation\": \"Specific recommendation\",\n \"lineNumber\": number (if applicable)\n}\n\nIMPORTANT: Only return JSON, no other text. If no issues found, return [].`;\n\n const userPrompt = `File: ${filePath}${governanceContext}${blockerContext}\n\nCode:\n\\`\\`\\`\n${content.slice(0, 5000)}\n\\`\\`\\`\n\nAnalyze this code and return a JSON array of potential issues.`;\n\n const response = await client.messages.create({\n model: 'claude-sonnet-4-20250514',\n max_tokens: 4096,\n temperature: 0.2,\n system: systemPrompt,\n messages: [{ role: 'user', content: userPrompt }]\n });\n\n const textContent = response.content\n .filter((block): block is { type: 'text'; text: string } => block.type === 'text')\n .map(block => block.text)\n .join('');\n\n // Extract JSON from response\n const jsonMatch = textContent.match(/\\[[\\s\\S]*\\]/);\n if (!jsonMatch) return [];\n\n const issues = JSON.parse(jsonMatch[0]);\n \n return issues.map((issue: any, idx: number) => ({\n id: `gotcha-ai-${Date.now()}-${idx}`,\n message: issue.message || 'AI-detected issue',\n confidence: issue.confidence || 0.7,\n riskLevel: issue.riskLevel || 'medium',\n recommendation: issue.recommendation || 'Review this code carefully',\n evidence: {\n pastIncidents: [],\n matchingPatterns: ['ai-analysis'],\n relatedTickets: []\n }\n }));\n } catch (error) {\n // AI analysis failed, return empty array\n return [];\n }\n }\n\n /**\n * Extract tags from file path for storage queries\n */\n private extractTagsFromFile(filePath: string, _signatures: string[]): string[] {\n const tags = new Set<string>();\n\n // Add tags from file path\n const normalized = filePath.toLowerCase();\n if (normalized.includes('/auth/')) tags.add('auth');\n if (normalized.includes('/payment/')) tags.add('payments');\n if (normalized.includes('/api/')) tags.add('api');\n if (normalized.includes('/frontend/') || normalized.includes('/ui/')) tags.add('ui');\n if (normalized.includes('/backend/')) tags.add('backend');\n if (normalized.includes('/database/') || normalized.includes('/models/')) tags.add('database');\n\n return Array.from(tags);\n }\n\n private async findHistoricalPrecedents(filePath: string, ticket: LinearTicketNodeData): Promise<GotchaPrediction | null> {\n // Search for historical issues similar to this ticket's description\n const similarIssues = await searchIssues(ticket.description, {\n workDir: this.projectPath,\n limit: 3\n });\n\n const relevantIssues = similarIssues.filter(r => r.issue.file === filePath || r.issue.file.includes(path.basename(filePath)));\n\n const [firstMatch] = relevantIssues;\n if (firstMatch) {\n const issue = firstMatch.issue;\n return {\n id: `gotcha-precedent-${ticket.ticketId}-${Date.now()}`,\n message: `A similar task in the past caused an issue: \"${issue.issue}\"`,\n confidence: 0.9,\n riskLevel: 'critical',\n precedentId: issue.id,\n recommendation: `Last time we worked on something similar here, we had to fix: \"${issue.fix}\". Check this first.`,\n evidence: {\n pastIncidents: [issue.id],\n matchingPatterns: [],\n relatedTickets: [ticket.ticketId]\n }\n };\n }\n\n return null;\n }\n\n async synthesizeGotchaExplanation(gotcha: GotchaPrediction): Promise<string> {\n const client = tryGetClient();\n if (!client) return gotcha.message;\n\n const prompt = `\n You are a JIT Defect Predictor. You found a potential \"gotcha\" for a developer.\n \n Ticket context: ${gotcha.evidence.relatedTickets.join(', ')}\n Tags: ${gotcha.evidence.matchingPatterns.join(', ')}\n Past incidents: ${gotcha.evidence.pastIncidents.join(', ')}\n \n Raw message: ${gotcha.message}\n Recommendation: ${gotcha.recommendation}\n \n Explain this gotcha in a concise, human-friendly way (max 2 sentences). \n Make it sound like a senior dev giving a helpful nudge.\n `;\n\n try {\n const response = await client.messages.create({\n model: 'claude-3-5-sonnet-20240620',\n max_tokens: 100,\n messages: [{ role: 'user', content: prompt }]\n });\n\n const text = response.content\n .filter((block): block is { type: 'text'; text: string } => block.type === 'text')\n .map(block => block.text)\n .join('');\n \n return text.trim() || gotcha.message;\n } catch {\n return gotcha.message;\n }\n }\n}\n","import type { Issue } from '../types/index.js';\nimport type { IssueGroup, PriorityReport } from '../utils/issue-analyzer.js';\nimport type { TeamNotification } from './team-collaboration.js';\n\ninterface SlackConfig {\n webhookUrl: string;\n channel?: string | undefined;\n username?: string | undefined;\n iconEmoji?: string | undefined;\n}\n\ninterface SlackMessage {\n text?: string;\n blocks?: SlackBlock[];\n attachments?: SlackAttachment[];\n channel?: string;\n username?: string;\n icon_emoji?: string;\n}\n\ninterface SlackBlock {\n type: string;\n text?: {\n type: string;\n text: string;\n };\n fields?: Array<{\n type: string;\n text: string;\n }>;\n accessory?: any;\n}\n\ninterface SlackAttachment {\n color: string;\n title?: string | undefined;\n text?: string | undefined;\n fields?: Array<{\n title: string;\n value: string;\n short?: boolean;\n }> | undefined;\n footer?: string | undefined;\n ts?: number | undefined;\n}\n\n/**\n * Slack integration for Trie team notifications\n */\nexport class SlackIntegration {\n constructor(private config: SlackConfig) {}\n\n /**\n * Send scan completion notification\n */\n async sendScanNotification(\n _issues: Issue[],\n priorityReport: PriorityReport,\n repositoryName: string,\n branch: string = 'main'\n ): Promise<void> {\n const { urgent, high, medium, low } = priorityReport;\n const statusEmoji = urgent.length > 0 ? '[URGENT]' : high.length > 0 ? '[HIGH]' : '[OK]';\n\n const message: SlackMessage = {\n blocks: [\n {\n type: 'section',\n text: {\n type: 'mrkdwn',\n text: `${statusEmoji} *Trie Security Scan Complete*\\n*Repository:* ${repositoryName} (${branch})`\n }\n },\n {\n type: 'section',\n fields: [\n {\n type: 'mrkdwn',\n text: `*Urgent:* ${urgent.length}`\n },\n {\n type: 'mrkdwn',\n text: `*High:* ${high.length}`\n },\n {\n type: 'mrkdwn',\n text: `*Medium:* ${medium.length}`\n },\n {\n type: 'mrkdwn',\n text: `*🔹 Low:* ${low.length}`\n }\n ]\n }\n ],\n attachments: []\n };\n\n // Add urgent issues details\n if (urgent.length > 0) {\n const urgentDetails = urgent.slice(0, 5).map(group =>\n `• ${group.description} (${group.count} instances)`\n ).join('\\n');\n\n message.attachments!.push({\n color: 'danger',\n title: 'Urgent Issues - Immediate Action Required',\n text: urgentDetails,\n footer: urgent.length > 5 ? `... and ${urgent.length - 5} more urgent issues` : undefined\n });\n }\n\n // Add high priority issues\n if (high.length > 0) {\n const highDetails = high.slice(0, 3).map(group =>\n `• ${group.description} (${group.count} instances)`\n ).join('\\n');\n\n message.attachments!.push({\n color: 'warning',\n title: 'High Priority Issues',\n text: highDetails,\n footer: high.length > 3 ? `... and ${high.length - 3} more high priority issues` : undefined\n });\n }\n\n // Add recommendations\n if (priorityReport.recommendations.length > 0) {\n message.attachments!.push({\n color: 'good',\n title: 'Recommendations',\n text: priorityReport.recommendations.slice(0, 3).join('\\n')\n });\n }\n\n await this.sendMessage(message);\n }\n\n /**\n * Send critical issue alert\n */\n async sendCriticalAlert(issues: Issue[], repositoryName: string): Promise<void> {\n const message: SlackMessage = {\n text: `CRITICAL SECURITY ALERT: ${repositoryName}`,\n blocks: [\n {\n type: 'section',\n text: {\n type: 'mrkdwn',\n text: `*CRITICAL SECURITY ALERT*\\n*Repository:* ${repositoryName}\\n*Critical Issues:* ${issues.length}`\n }\n }\n ],\n attachments: issues.slice(0, 5).map(issue => ({\n color: 'danger',\n title: `${issue.file}:${issue.line || '?'}`,\n text: issue.issue.slice(0, 200),\n fields: [\n {\n title: 'Fix',\n value: issue.fix.slice(0, 100),\n short: false\n }\n ],\n footer: `Agent: ${issue.agent}`,\n ts: Math.floor(Date.now() / 1000)\n }))\n };\n\n if (issues.length > 5) {\n message.attachments!.push({\n color: 'danger',\n text: `... and ${issues.length - 5} more critical issues. View full report for details.`\n });\n }\n\n await this.sendMessage(message);\n }\n\n /**\n * Send team notification\n */\n async sendTeamNotification(notification: TeamNotification): Promise<void> {\n const emoji = this.getNotificationEmoji(notification.type);\n\n const message: SlackMessage = {\n blocks: [\n {\n type: 'section',\n text: {\n type: 'mrkdwn',\n text: `${emoji} *${notification.title}*\\n${notification.message}`\n }\n }\n ]\n };\n\n // Add specific data based on notification type\n if (notification.type === 'assignment' && notification.data) {\n const { assignment, issue } = notification.data;\n message.attachments = [{\n color: this.getAssignmentColor(assignment.priority),\n fields: [\n {\n title: 'Priority',\n value: assignment.priority.toUpperCase(),\n short: true\n },\n {\n title: 'Due Date',\n value: assignment.dueDate ? new Date(assignment.dueDate).toLocaleDateString() : 'Not set',\n short: true\n },\n {\n title: 'File',\n value: issue.file,\n short: false\n }\n ]\n }];\n }\n\n await this.sendMessage(message);\n }\n\n /**\n * Send daily/weekly team summary\n */\n async sendTeamSummary(\n period: 'daily' | 'weekly',\n stats: {\n newIssues: number;\n resolvedIssues: number;\n overdueIssues: number;\n topCategories: Array<{ category: string; count: number }>;\n topContributors: Array<{ name: string; resolved: number }>;\n }\n ): Promise<void> {\n const emoji = period === 'daily' ? '[DAILY]' : '[WEEKLY]';\n const title = `${emoji} ${period.charAt(0).toUpperCase() + period.slice(1)} Security Summary`;\n\n const message: SlackMessage = {\n blocks: [\n {\n type: 'section',\n text: {\n type: 'mrkdwn',\n text: `*${title}*`\n }\n },\n {\n type: 'section',\n fields: [\n {\n type: 'mrkdwn',\n text: `*New Issues:* ${stats.newIssues}`\n },\n {\n type: 'mrkdwn',\n text: `*✅ Resolved:* ${stats.resolvedIssues}`\n },\n {\n type: 'mrkdwn',\n text: `*Overdue:* ${stats.overdueIssues}`\n },\n {\n type: 'mrkdwn',\n text: `*Net Change:* ${stats.resolvedIssues - stats.newIssues > 0 ? '+' : ''}${stats.resolvedIssues - stats.newIssues}`\n }\n ]\n }\n ],\n attachments: []\n };\n\n // Top issue categories\n if (stats.topCategories.length > 0) {\n const categoriesText = stats.topCategories\n .slice(0, 5)\n .map(cat => `• ${cat.category}: ${cat.count}`)\n .join('\\n');\n\n message.attachments!.push({\n color: 'good',\n title: 'Top Issue Categories',\n text: categoriesText\n });\n }\n\n // Top contributors\n if (stats.topContributors.length > 0) {\n const contributorsText = stats.topContributors\n .slice(0, 5)\n .map(contrib => `• ${contrib.name}: ${contrib.resolved} resolved`)\n .join('\\n');\n\n message.attachments!.push({\n color: 'good',\n title: 'Top Contributors',\n text: contributorsText\n });\n }\n\n await this.sendMessage(message);\n }\n\n /**\n * Send bulk fix notification\n */\n async sendBulkFixNotification(\n fixedGroups: IssueGroup[],\n totalFixed: number,\n repositoryName: string\n ): Promise<void> {\n const message: SlackMessage = {\n blocks: [\n {\n type: 'section',\n text: {\n type: 'mrkdwn',\n text: `*Bulk Fix Applied*\\n*Repository:* ${repositoryName}\\n*Issues Fixed:* ${totalFixed}`\n }\n }\n ],\n attachments: [{\n color: 'good',\n title: '🔧 Fixed Issue Groups',\n text: fixedGroups.map(group =>\n `• ${group.description} (${group.count} instances)`\n ).join('\\n')\n }]\n };\n\n await this.sendMessage(message);\n }\n\n /**\n * Send escalation notification\n */\n async sendEscalationNotification(\n overdueAssignments: Array<{\n issueId: string;\n assignee: string;\n daysOverdue: number;\n priority: string;\n }>\n ): Promise<void> {\n const message: SlackMessage = {\n text: 'OVERDUE ISSUE ESCALATION',\n blocks: [\n {\n type: 'section',\n text: {\n type: 'mrkdwn',\n text: `*Overdue Issue Escalation*\\n${overdueAssignments.length} issues are overdue and require attention.`\n }\n }\n ],\n attachments: overdueAssignments.map(assignment => ({\n color: 'warning',\n title: `Issue ${assignment.issueId}`,\n fields: [\n {\n title: 'Assignee',\n value: assignment.assignee,\n short: true\n },\n {\n title: 'Days Overdue',\n value: assignment.daysOverdue.toString(),\n short: true\n },\n {\n title: 'Priority',\n value: assignment.priority.toUpperCase(),\n short: true\n }\n ]\n }))\n };\n\n await this.sendMessage(message);\n }\n\n /**\n * Send message to Slack\n */\n private async sendMessage(message: SlackMessage): Promise<void> {\n const payload = {\n ...message,\n channel: this.config.channel || message.channel,\n username: this.config.username || 'Trie Security Bot',\n icon_emoji: this.config.iconEmoji || ':shield:'\n };\n\n try {\n const response = await fetch(this.config.webhookUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(payload)\n });\n\n if (!response.ok) {\n throw new Error(`Slack API error: ${response.status} ${response.statusText}`);\n }\n } catch (error) {\n console.error('Failed to send Slack notification:', error);\n throw error;\n }\n }\n\n /**\n * Get emoji for notification type\n */\n private getNotificationEmoji(type: string): string {\n const emojis: Record<string, string> = {\n assignment: '[ASSIGN]',\n escalation: '[ESCALATE]',\n completion: '[DONE]',\n reminder: '[REMIND]'\n };\n return emojis[type] ?? '[NOTIFY]';\n }\n\n /**\n * Get color for assignment priority\n */\n private getAssignmentColor(priority: string): string {\n const colors: Record<string, string> = {\n urgent: 'danger',\n high: 'warning',\n medium: 'good',\n low: '#36a64f'\n };\n return colors[priority] ?? 'good';\n }\n\n /**\n * Test Slack connection\n */\n async testConnection(): Promise<boolean> {\n try {\n await this.sendMessage({\n text: 'Trie Slack Integration Test',\n blocks: [{\n type: 'section',\n text: {\n type: 'mrkdwn',\n text: '*Trie Slack Integration Test*\\nIf you see this message, the integration is working correctly!'\n }\n }]\n });\n return true;\n } catch (error) {\n console.error('Slack connection test failed:', error);\n return false;\n }\n }\n}"],"mappings":"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","names":[]}