@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.
- package/README.md +64 -27
- package/dist/{chunk-YDHUCDHM.js → chunk-3XR6WVAW.js} +8 -8
- package/dist/{chunk-4MXH2ZPT.js → chunk-7IO4YUI3.js} +8 -8
- package/dist/{chunk-7WITSO22.js → chunk-AHD2CBQ7.js} +77 -55
- package/dist/chunk-AHD2CBQ7.js.map +1 -0
- package/dist/{chunk-575YT2SD.js → chunk-BUTOP5EB.js} +195 -1
- package/dist/chunk-BUTOP5EB.js.map +1 -0
- package/dist/{chunk-MRHKX5M5.js → chunk-FBNURWRY.js} +3 -3
- package/dist/{chunk-YZ6Y2H3P.js → chunk-FVRO5RN3.js} +66 -49
- package/dist/chunk-FVRO5RN3.js.map +1 -0
- package/dist/{chunk-5BRRRTN6.js → chunk-G3I7SZLW.js} +4 -4
- package/dist/{chunk-XTFWT2XM.js → chunk-I2O5OYQT.js} +2 -2
- package/dist/{chunk-XE6KQRKZ.js → chunk-KCUOWRPX.js} +2 -2
- package/dist/{chunk-LQIMKE3P.js → chunk-SASNMSB5.js} +106 -33
- package/dist/{chunk-LQIMKE3P.js.map → chunk-SASNMSB5.js.map} +1 -1
- package/dist/cli/main.js +7 -9
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +10 -12
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{fast-analyzer-XXYMOXRK.js → fast-analyzer-3GCCZMLK.js} +3 -3
- package/dist/{goal-manager-YOB7VWK7.js → goal-manager-QUKX2W6C.js} +3 -3
- package/dist/{goal-validator-ULKIBDPX.js → goal-validator-2SFSKKVU.js} +3 -3
- package/dist/{hypothesis-7BFFT5JY.js → hypothesis-KCPBR652.js} +3 -3
- package/dist/index.js +11 -13
- package/dist/index.js.map +1 -1
- package/dist/{issue-store-ZIRP23EP.js → issue-store-YAXTNRRY.js} +2 -2
- package/dist/server/mcp-server.js +11 -13
- package/dist/{tiered-storage-Z3YCR465.js → tiered-storage-DYNC5CQ6.js} +3 -2
- package/dist/{trie-agent-3YDPEGHJ.js → trie-agent-I3HAHY2G.js} +7 -9
- package/dist/{chunk-OMR4YCBS.js → vibe-code-signatures-5ZULYP3D.js} +4 -4
- package/dist/{chunk-OMR4YCBS.js.map → vibe-code-signatures-5ZULYP3D.js.map} +1 -1
- package/dist/{chunk-SY6KQG44.js → vulnerability-signatures-2URZSXAQ.js} +5 -5
- package/dist/{chunk-SY6KQG44.js.map → vulnerability-signatures-2URZSXAQ.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-575YT2SD.js.map +0 -1
- package/dist/chunk-7WITSO22.js.map +0 -1
- package/dist/chunk-YZ6Y2H3P.js.map +0 -1
- package/dist/vibe-code-signatures-F6URTBW3.js +0 -16
- package/dist/vibe-code-signatures-F6URTBW3.js.map +0 -1
- package/dist/vulnerability-signatures-T7SKHORW.js +0 -18
- package/dist/vulnerability-signatures-T7SKHORW.js.map +0 -1
- /package/dist/{chunk-YDHUCDHM.js.map → chunk-3XR6WVAW.js.map} +0 -0
- /package/dist/{chunk-4MXH2ZPT.js.map → chunk-7IO4YUI3.js.map} +0 -0
- /package/dist/{chunk-MRHKX5M5.js.map → chunk-FBNURWRY.js.map} +0 -0
- /package/dist/{chunk-5BRRRTN6.js.map → chunk-G3I7SZLW.js.map} +0 -0
- /package/dist/{chunk-XTFWT2XM.js.map → chunk-I2O5OYQT.js.map} +0 -0
- /package/dist/{chunk-XE6KQRKZ.js.map → chunk-KCUOWRPX.js.map} +0 -0
- /package/dist/{fast-analyzer-XXYMOXRK.js.map → fast-analyzer-3GCCZMLK.js.map} +0 -0
- /package/dist/{goal-manager-YOB7VWK7.js.map → goal-manager-QUKX2W6C.js.map} +0 -0
- /package/dist/{goal-validator-ULKIBDPX.js.map → goal-validator-2SFSKKVU.js.map} +0 -0
- /package/dist/{hypothesis-7BFFT5JY.js.map → hypothesis-KCPBR652.js.map} +0 -0
- /package/dist/{issue-store-ZIRP23EP.js.map → issue-store-YAXTNRRY.js.map} +0 -0
- /package/dist/{tiered-storage-Z3YCR465.js.map → tiered-storage-DYNC5CQ6.js.map} +0 -0
- /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
|
-
**
|
|
3
|
+
**Context that travels from Agents → CLI → CI/CD, keeping agents and humans aligned.**
|
|
4
4
|
|
|
5
5
|
[](https://www.trie.dev) [](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**—
|
|
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
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
- **
|
|
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
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
3259
|
-
const { getVibeCodeStats } = await import("./vibe-code-signatures-
|
|
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-
|
|
4011
|
+
//# sourceMappingURL=chunk-3XR6WVAW.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getHypothesisEngine
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-I2O5OYQT.js";
|
|
4
4
|
import {
|
|
5
5
|
getGoalManager
|
|
6
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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,
|
|
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
|
-
*
|
|
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,
|
|
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
|
-
|
|
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-
|
|
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":[]}
|