@equilateral_ai/mindmeld 3.0.0

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 (86) hide show
  1. package/README.md +300 -0
  2. package/hooks/README.md +494 -0
  3. package/hooks/pre-compact.js +392 -0
  4. package/hooks/session-start.js +264 -0
  5. package/package.json +90 -0
  6. package/scripts/harvest.js +561 -0
  7. package/scripts/init-project.js +437 -0
  8. package/scripts/inject.js +388 -0
  9. package/src/collaboration/CollaborationPrompt.js +460 -0
  10. package/src/core/AlertEngine.js +813 -0
  11. package/src/core/AlertNotifier.js +363 -0
  12. package/src/core/CorrelationAnalyzer.js +774 -0
  13. package/src/core/CurationEngine.js +688 -0
  14. package/src/core/LLMPatternDetector.js +508 -0
  15. package/src/core/LoadBearingDetector.js +242 -0
  16. package/src/core/NotificationService.js +1032 -0
  17. package/src/core/PatternValidator.js +355 -0
  18. package/src/core/README.md +160 -0
  19. package/src/core/RapportOrchestrator.js +446 -0
  20. package/src/core/RelevanceDetector.js +577 -0
  21. package/src/core/StandardsIngestion.js +575 -0
  22. package/src/core/TeamLoadBearingDetector.js +431 -0
  23. package/src/database/dbOperations.js +105 -0
  24. package/src/handlers/activity/activityGetMe.js +98 -0
  25. package/src/handlers/activity/activityGetTeam.js +130 -0
  26. package/src/handlers/alerts/alertsAcknowledge.js +91 -0
  27. package/src/handlers/alerts/alertsGet.js +250 -0
  28. package/src/handlers/collaborators/collaboratorAdd.js +201 -0
  29. package/src/handlers/collaborators/collaboratorInvite.js +218 -0
  30. package/src/handlers/collaborators/collaboratorList.js +88 -0
  31. package/src/handlers/collaborators/collaboratorRemove.js +127 -0
  32. package/src/handlers/collaborators/inviteAccept.js +122 -0
  33. package/src/handlers/context/contextGet.js +57 -0
  34. package/src/handlers/context/invariantsGet.js +74 -0
  35. package/src/handlers/context/loopsGet.js +82 -0
  36. package/src/handlers/context/notesCreate.js +74 -0
  37. package/src/handlers/context/purposeGet.js +78 -0
  38. package/src/handlers/correlations/correlationsDeveloperGet.js +226 -0
  39. package/src/handlers/correlations/correlationsGet.js +93 -0
  40. package/src/handlers/correlations/correlationsProjectGet.js +161 -0
  41. package/src/handlers/github/githubConnectionStatus.js +49 -0
  42. package/src/handlers/github/githubDiscoverPatterns.js +364 -0
  43. package/src/handlers/github/githubOAuthCallback.js +166 -0
  44. package/src/handlers/github/githubOAuthStart.js +59 -0
  45. package/src/handlers/github/githubPatternsReview.js +109 -0
  46. package/src/handlers/github/githubReposList.js +105 -0
  47. package/src/handlers/helpers/checkSuperAdmin.js +85 -0
  48. package/src/handlers/helpers/dbOperations.js +53 -0
  49. package/src/handlers/helpers/errorHandler.js +49 -0
  50. package/src/handlers/helpers/index.js +106 -0
  51. package/src/handlers/helpers/lambdaWrapper.js +60 -0
  52. package/src/handlers/helpers/responseUtil.js +55 -0
  53. package/src/handlers/helpers/subscriptionTiers.js +1168 -0
  54. package/src/handlers/notifications/getPreferences.js +84 -0
  55. package/src/handlers/notifications/sendNotification.js +170 -0
  56. package/src/handlers/notifications/updatePreferences.js +316 -0
  57. package/src/handlers/patterns/patternUsagePost.js +182 -0
  58. package/src/handlers/patterns/patternViolationPost.js +185 -0
  59. package/src/handlers/projects/projectCreate.js +107 -0
  60. package/src/handlers/projects/projectDelete.js +82 -0
  61. package/src/handlers/projects/projectGet.js +95 -0
  62. package/src/handlers/projects/projectUpdate.js +118 -0
  63. package/src/handlers/reports/aiLeverage.js +206 -0
  64. package/src/handlers/reports/engineeringInvestment.js +132 -0
  65. package/src/handlers/reports/riskForecast.js +186 -0
  66. package/src/handlers/reports/standardsRoi.js +162 -0
  67. package/src/handlers/scheduled/analyzeCorrelations.js +178 -0
  68. package/src/handlers/scheduled/analyzeGitHistory.js +510 -0
  69. package/src/handlers/scheduled/generateAlerts.js +135 -0
  70. package/src/handlers/scheduled/refreshActivity.js +21 -0
  71. package/src/handlers/scheduled/scanCompliance.js +334 -0
  72. package/src/handlers/sessions/sessionEndPost.js +180 -0
  73. package/src/handlers/sessions/sessionStandardsPost.js +135 -0
  74. package/src/handlers/stripe/addonManagePost.js +240 -0
  75. package/src/handlers/stripe/billingPortalPost.js +93 -0
  76. package/src/handlers/stripe/enterpriseCheckoutPost.js +272 -0
  77. package/src/handlers/stripe/seatsUpdatePost.js +185 -0
  78. package/src/handlers/stripe/subscriptionCancelDelete.js +169 -0
  79. package/src/handlers/stripe/subscriptionCreatePost.js +221 -0
  80. package/src/handlers/stripe/subscriptionUpdatePut.js +163 -0
  81. package/src/handlers/stripe/webhookPost.js +454 -0
  82. package/src/handlers/users/cognitoPostConfirmation.js +150 -0
  83. package/src/handlers/users/userEntitlementsGet.js +89 -0
  84. package/src/handlers/users/userGet.js +114 -0
  85. package/src/handlers/webhooks/githubWebhook.js +223 -0
  86. package/src/index.js +969 -0
@@ -0,0 +1,508 @@
1
+ /**
2
+ * LLMPatternDetector - LLM-powered pattern detection for Rapport v3
3
+ *
4
+ * Uses AWS Bedrock (Claude) to analyze session transcripts and detect:
5
+ * - Architectural decisions made during coding
6
+ * - Coding patterns and conventions applied
7
+ * - Anti-patterns or standards violations
8
+ * - Semantic intent behind code changes
9
+ *
10
+ * Replaces regex-based pattern detection with semantic understanding.
11
+ *
12
+ * @module LLMPatternDetector
13
+ */
14
+
15
+ const { BedrockRuntimeClient, InvokeModelCommand } = require('@aws-sdk/client-bedrock-runtime');
16
+ const fs = require('fs').promises;
17
+ const path = require('path');
18
+
19
+ class LLMPatternDetector {
20
+ constructor(config = {}) {
21
+ this.config = {
22
+ // Bedrock model ID for Claude 3.5 Haiku (cross-region inference profile)
23
+ model: config.model || 'us.anthropic.claude-3-5-haiku-20241022-v1:0',
24
+ maxTokens: config.maxTokens || 2048,
25
+ enabled: config.enabled !== false,
26
+ cacheEnabled: config.cacheEnabled !== false,
27
+ cacheTTL: config.cacheTTL || 300000, // 5 minutes
28
+ region: config.region || 'us-east-2',
29
+ ...config
30
+ };
31
+
32
+ this.client = null;
33
+ this.cache = new Map();
34
+ this.patternExamples = null;
35
+
36
+ // Initialize Bedrock client (uses default AWS credentials)
37
+ try {
38
+ this.client = new BedrockRuntimeClient({ region: this.config.region });
39
+ } catch (error) {
40
+ console.error('[LLMPatternDetector] Failed to initialize Bedrock client:', error.message);
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Check if LLM detection is available
46
+ * Uses AWS Bedrock - no API key needed, uses default AWS credentials
47
+ */
48
+ isAvailable() {
49
+ return this.config.enabled && this.client !== null;
50
+ }
51
+
52
+ /**
53
+ * Load pattern examples for LLM context
54
+ */
55
+ async loadPatternExamples() {
56
+ if (this.patternExamples) return this.patternExamples;
57
+
58
+ try {
59
+ const examplesPath = path.join(__dirname, '../../docs/PATTERN_EXAMPLES.md');
60
+ this.patternExamples = await fs.readFile(examplesPath, 'utf-8');
61
+ } catch (error) {
62
+ this.patternExamples = '';
63
+ }
64
+ return this.patternExamples;
65
+ }
66
+
67
+ /**
68
+ * Analyze a Claude Code session transcript for patterns
69
+ *
70
+ * @param {string} transcript - Full session transcript text
71
+ * @param {Object} context - Additional context (project, files, etc.)
72
+ * @returns {Promise<Object>} Detected patterns and analysis
73
+ */
74
+ async analyzeSessionTranscript(transcript, context = {}) {
75
+ if (!this.isAvailable()) {
76
+ return this.fallbackAnalysis(transcript, context);
77
+ }
78
+
79
+ // Check cache
80
+ const cacheKey = this.getCacheKey(transcript);
81
+ if (this.config.cacheEnabled && this.cache.has(cacheKey)) {
82
+ const cached = this.cache.get(cacheKey);
83
+ if (Date.now() - cached.timestamp < this.config.cacheTTL) {
84
+ return cached.result;
85
+ }
86
+ }
87
+
88
+ try {
89
+ const result = await this.callLLM(transcript, context);
90
+
91
+ // Cache result
92
+ if (this.config.cacheEnabled) {
93
+ this.cache.set(cacheKey, {
94
+ result,
95
+ timestamp: Date.now()
96
+ });
97
+ }
98
+
99
+ return result;
100
+ } catch (error) {
101
+ console.error('[LLMPatternDetector] Analysis error:', error.message);
102
+ return this.fallbackAnalysis(transcript, context);
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Call AWS Bedrock (Claude) for pattern analysis
108
+ */
109
+ async callLLM(transcript, context) {
110
+ const systemPrompt = await this.buildSystemPrompt(context);
111
+ const userPrompt = this.buildUserPrompt(transcript, context);
112
+
113
+ // Bedrock request body for Claude Messages API
114
+ const requestBody = {
115
+ anthropic_version: 'bedrock-2023-05-31',
116
+ max_tokens: this.config.maxTokens,
117
+ system: systemPrompt,
118
+ messages: [
119
+ { role: 'user', content: userPrompt }
120
+ ]
121
+ };
122
+
123
+ const command = new InvokeModelCommand({
124
+ modelId: this.config.model,
125
+ contentType: 'application/json',
126
+ accept: 'application/json',
127
+ body: JSON.stringify(requestBody)
128
+ });
129
+
130
+ const response = await this.client.send(command);
131
+ const responseBody = JSON.parse(new TextDecoder().decode(response.body));
132
+
133
+ const content = responseBody.content?.[0]?.text || '';
134
+ return this.parseResponse(content);
135
+ }
136
+
137
+ /**
138
+ * Build system prompt for pattern detection
139
+ */
140
+ async buildSystemPrompt(context) {
141
+ const examples = await this.loadPatternExamples();
142
+ const techStack = context.techStack || 'Node.js, AWS Lambda, PostgreSQL, React';
143
+
144
+ return `You are an expert software architecture analyst for MindMeld/Rapport, a team knowledge sharing platform.
145
+
146
+ Your task is to analyze Claude Code session transcripts and extract:
147
+ 1. **Architectural Decisions**: Key decisions made about code structure, patterns, or approaches
148
+ 2. **Coding Patterns**: Reusable patterns applied (e.g., error handling, database access, API design)
149
+ 3. **Anti-Patterns**: Potential violations of best practices or standards
150
+ 4. **Invariants**: Rules that should always be followed based on this session
151
+
152
+ Context about the codebase:
153
+ - Tech stack: ${techStack}
154
+ - Standards: .equilateral-standards/ (serverless-saas-aws, tim-combo pattern)
155
+
156
+ Key patterns to detect:
157
+ - Lambda database connections (MUST use cached single client, NEVER pools)
158
+ - API Gateway CORS (NEVER use DefaultAuthorizer)
159
+ - Handler pattern (wrapHandler, executeQuery, createSuccessResponse)
160
+ - Business-scoped IDs (NOT random UUIDs)
161
+ - SSM parameters (NEVER fetch at runtime, use env vars)
162
+
163
+ ${examples ? `\n## Pattern Examples Reference:\n${examples.substring(0, 8000)}` : ''}
164
+
165
+ Respond ONLY with valid JSON in this exact format:
166
+ {
167
+ "patterns": [
168
+ {
169
+ "element": "Pattern name",
170
+ "type": "standard|anti_pattern|invariant|architectural_decision",
171
+ "intent": "What this pattern achieves",
172
+ "evidence": "Quote or reference from transcript",
173
+ "confidence": 0.95,
174
+ "severity": "info|warning|critical",
175
+ "category": "database|api|security|performance|architecture"
176
+ }
177
+ ],
178
+ "summary": "Brief summary of key patterns detected",
179
+ "recommendations": ["Actionable recommendations"],
180
+ "violations": [
181
+ {
182
+ "standard": "Which standard was violated",
183
+ "description": "What the violation is",
184
+ "fix": "How to fix it"
185
+ }
186
+ ]
187
+ }`;
188
+ }
189
+
190
+ /**
191
+ * Build user prompt with transcript
192
+ */
193
+ buildUserPrompt(transcript, context) {
194
+ // Truncate very long transcripts to stay within token limits
195
+ const maxLength = 50000;
196
+ const truncated = transcript.length > maxLength
197
+ ? transcript.substring(0, maxLength) + '\n\n[... transcript truncated ...]'
198
+ : transcript;
199
+
200
+ const projectName = context.projectName || 'Unknown';
201
+ const filesChanged = context.filesChanged?.join(', ') || 'Unknown';
202
+
203
+ return `Analyze this Claude Code session transcript for patterns, decisions, and potential violations:
204
+
205
+ ---
206
+ PROJECT: ${projectName}
207
+ FILES CHANGED: ${filesChanged}
208
+ ---
209
+
210
+ TRANSCRIPT:
211
+ ${truncated}
212
+
213
+ ---
214
+
215
+ Extract all architectural decisions, coding patterns, anti-patterns, and invariants from this session. Focus on:
216
+ 1. Database connection patterns
217
+ 2. Error handling approaches
218
+ 3. API design decisions
219
+ 4. Security considerations
220
+ 5. Performance patterns
221
+
222
+ Respond with JSON only.`;
223
+ }
224
+
225
+ /**
226
+ * Parse LLM response into structured data
227
+ */
228
+ parseResponse(content) {
229
+ try {
230
+ // Extract JSON from response (handle markdown code blocks)
231
+ let jsonStr = content;
232
+ const jsonMatch = content.match(/```(?:json)?\s*([\s\S]*?)```/);
233
+ if (jsonMatch) {
234
+ jsonStr = jsonMatch[1];
235
+ }
236
+
237
+ const parsed = JSON.parse(jsonStr.trim());
238
+
239
+ return {
240
+ success: true,
241
+ source: 'llm',
242
+ model: this.config.model,
243
+ timestamp: new Date().toISOString(),
244
+ ...parsed
245
+ };
246
+ } catch (error) {
247
+ console.error('[LLMPatternDetector] Failed to parse response:', error.message);
248
+ return {
249
+ success: false,
250
+ source: 'llm',
251
+ error: 'Failed to parse LLM response',
252
+ rawContent: content.substring(0, 500),
253
+ patterns: [],
254
+ violations: []
255
+ };
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Fallback to regex-based analysis when LLM unavailable
261
+ */
262
+ fallbackAnalysis(transcript, context) {
263
+ const patterns = [];
264
+
265
+ // Basic regex patterns (existing logic)
266
+ const patternMatchers = [
267
+ {
268
+ regex: /wrapHandler/g,
269
+ element: 'Lambda Handler Pattern',
270
+ type: 'standard',
271
+ category: 'api',
272
+ intent: 'Consistent error handling and logging for Lambda functions'
273
+ },
274
+ {
275
+ regex: /executeQuery/g,
276
+ element: 'Database Query Pattern',
277
+ type: 'standard',
278
+ category: 'database',
279
+ intent: 'Standardized database query execution with error handling'
280
+ },
281
+ {
282
+ regex: /createSuccessResponse/g,
283
+ element: 'API Response Pattern',
284
+ type: 'standard',
285
+ category: 'api',
286
+ intent: 'Consistent API response format'
287
+ },
288
+ {
289
+ regex: /new Pool\(|createPool/g,
290
+ element: 'Connection Pool in Lambda',
291
+ type: 'anti_pattern',
292
+ category: 'database',
293
+ severity: 'critical',
294
+ intent: 'Connection pools are wasteful in Lambda - use cached single client'
295
+ },
296
+ {
297
+ regex: /ssm\.getParameter|GetParameter/g,
298
+ element: 'SSM Runtime Fetch',
299
+ type: 'anti_pattern',
300
+ category: 'performance',
301
+ severity: 'critical',
302
+ intent: 'SSM at runtime costs $25/month per million - use env vars'
303
+ },
304
+ {
305
+ regex: /DefaultAuthorizer/g,
306
+ element: 'DefaultAuthorizer Usage',
307
+ type: 'anti_pattern',
308
+ category: 'api',
309
+ severity: 'critical',
310
+ intent: 'DefaultAuthorizer breaks CORS preflight'
311
+ },
312
+ {
313
+ regex: /uuid(?:v4)?|randomUUID/gi,
314
+ element: 'Random UUID for Business ID',
315
+ type: 'anti_pattern',
316
+ category: 'architecture',
317
+ severity: 'warning',
318
+ intent: 'Use business-scoped IDs, not random UUIDs'
319
+ },
320
+ {
321
+ regex: /console\.log\s*\(/g,
322
+ element: 'Console.log in Production',
323
+ type: 'anti_pattern',
324
+ category: 'performance',
325
+ severity: 'warning',
326
+ intent: 'Debug logging should be removed from production code'
327
+ },
328
+ {
329
+ regex: /(password|secret|key)\s*[:=]\s*['"][^'"]{8,}['"]/gi,
330
+ element: 'Hardcoded Secret',
331
+ type: 'anti_pattern',
332
+ category: 'security',
333
+ severity: 'critical',
334
+ intent: 'Secrets must come from environment variables, never hardcoded'
335
+ }
336
+ ];
337
+
338
+ for (const matcher of patternMatchers) {
339
+ const matches = transcript.match(matcher.regex);
340
+ if (matches && matches.length > 0) {
341
+ patterns.push({
342
+ element: matcher.element,
343
+ type: matcher.type,
344
+ intent: matcher.intent,
345
+ category: matcher.category,
346
+ severity: matcher.severity || 'info',
347
+ confidence: 0.7, // Lower confidence for regex matches
348
+ evidence: `Found ${matches.length} occurrence(s)`,
349
+ matchCount: matches.length
350
+ });
351
+ }
352
+ }
353
+
354
+ return {
355
+ success: true,
356
+ source: 'fallback_regex',
357
+ timestamp: new Date().toISOString(),
358
+ patterns,
359
+ summary: `Detected ${patterns.length} patterns using regex fallback`,
360
+ violations: patterns.filter(p => p.type === 'anti_pattern'),
361
+ recommendations: []
362
+ };
363
+ }
364
+
365
+ /**
366
+ * Generate cache key from transcript
367
+ */
368
+ getCacheKey(transcript) {
369
+ // Simple hash based on length and sample content
370
+ const sample = transcript.substring(0, 1000) + transcript.slice(-1000);
371
+ let hash = 0;
372
+ for (let i = 0; i < sample.length; i++) {
373
+ const char = sample.charCodeAt(i);
374
+ hash = ((hash << 5) - hash) + char;
375
+ hash = hash & hash;
376
+ }
377
+ return `session_${hash}_${transcript.length}`;
378
+ }
379
+
380
+ /**
381
+ * Analyze code content for patterns (standalone file analysis)
382
+ */
383
+ async analyzeCode(code, filename, context = {}) {
384
+ if (!this.isAvailable()) {
385
+ return this.fallbackAnalysis(code, context);
386
+ }
387
+
388
+ const codeSnippet = code.substring(0, 10000);
389
+
390
+ const prompt = `Analyze this code file for patterns and potential issues:
391
+
392
+ FILE: ${filename}
393
+ CONTEXT: ${context.projectName || 'Unknown project'}
394
+
395
+ \`\`\`
396
+ ${codeSnippet}
397
+ \`\`\`
398
+
399
+ Focus on:
400
+ 1. Adherence to Lambda database standards (no pools, cached client)
401
+ 2. Error handling patterns
402
+ 3. Security issues (hardcoded secrets, SQL injection)
403
+ 4. Performance anti-patterns
404
+
405
+ Respond with JSON containing patterns and violations.`;
406
+
407
+ try {
408
+ const systemPrompt = await this.buildSystemPrompt(context);
409
+
410
+ const requestBody = {
411
+ anthropic_version: 'bedrock-2023-05-31',
412
+ max_tokens: 1024,
413
+ system: systemPrompt,
414
+ messages: [{ role: 'user', content: prompt }]
415
+ };
416
+
417
+ const command = new InvokeModelCommand({
418
+ modelId: this.config.model,
419
+ contentType: 'application/json',
420
+ accept: 'application/json',
421
+ body: JSON.stringify(requestBody)
422
+ });
423
+
424
+ const response = await this.client.send(command);
425
+ const responseBody = JSON.parse(new TextDecoder().decode(response.body));
426
+
427
+ return this.parseResponse(responseBody.content?.[0]?.text || '');
428
+ } catch (error) {
429
+ console.error('[LLMPatternDetector] Code analysis error:', error.message);
430
+ return this.fallbackAnalysis(code, context);
431
+ }
432
+ }
433
+
434
+ /**
435
+ * Extract invariants from session patterns
436
+ * Returns patterns that should become team invariants
437
+ */
438
+ extractInvariants(analysisResult) {
439
+ if (!analysisResult.success || !analysisResult.patterns) {
440
+ return [];
441
+ }
442
+
443
+ return analysisResult.patterns
444
+ .filter(p =>
445
+ p.type === 'invariant' ||
446
+ (p.type === 'anti_pattern' && p.severity === 'critical') ||
447
+ (p.confidence >= 0.9 && p.type === 'standard')
448
+ )
449
+ .map(p => ({
450
+ element: p.element,
451
+ rule: p.intent,
452
+ severity: p.severity || 'info',
453
+ source: 'llm_detected',
454
+ confidence: p.confidence,
455
+ evidence: p.evidence
456
+ }));
457
+ }
458
+
459
+ /**
460
+ * Summarize session for team learning
461
+ */
462
+ async summarizeSession(transcript, context = {}) {
463
+ if (!this.isAvailable()) {
464
+ return { summary: 'LLM not available for summarization' };
465
+ }
466
+
467
+ const prompt = `Summarize this Claude Code session in 2-3 sentences, focusing on:
468
+ 1. What was accomplished
469
+ 2. Key architectural decisions made
470
+ 3. Any patterns or invariants established
471
+
472
+ TRANSCRIPT:
473
+ ${transcript.substring(0, 20000)}
474
+
475
+ Respond with a JSON object: { "summary": "...", "keyDecisions": ["..."], "newPatterns": ["..."] }`;
476
+
477
+ try {
478
+ const requestBody = {
479
+ anthropic_version: 'bedrock-2023-05-31',
480
+ max_tokens: 512,
481
+ messages: [{ role: 'user', content: prompt }]
482
+ };
483
+
484
+ const command = new InvokeModelCommand({
485
+ modelId: this.config.model,
486
+ contentType: 'application/json',
487
+ accept: 'application/json',
488
+ body: JSON.stringify(requestBody)
489
+ });
490
+
491
+ const response = await this.client.send(command);
492
+ const responseBody = JSON.parse(new TextDecoder().decode(response.body));
493
+
494
+ return this.parseResponse(responseBody.content?.[0]?.text || '');
495
+ } catch (error) {
496
+ return { summary: 'Failed to summarize session', error: error.message };
497
+ }
498
+ }
499
+
500
+ /**
501
+ * Clear cache (for testing or memory management)
502
+ */
503
+ clearCache() {
504
+ this.cache.clear();
505
+ }
506
+ }
507
+
508
+ module.exports = { LLMPatternDetector };