@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,355 @@
1
+ /**
2
+ * PatternValidator - Validates discovered patterns against enforced standards
3
+ *
4
+ * Phase 3 of Rapport Standards Integration
5
+ * Checks discovered patterns for violations of organization standards
6
+ * Generates actionable guidance with team evidence
7
+ *
8
+ * @module PatternValidator
9
+ */
10
+
11
+ const { executeQuery } = require('../handlers/helpers/dbOperations');
12
+
13
+ class PatternValidator {
14
+ constructor() {
15
+ this.severityLevels = {
16
+ enforced: 'critical',
17
+ validated: 'warning',
18
+ provisional: 'info'
19
+ };
20
+ }
21
+
22
+ /**
23
+ * Validate a discovered pattern against enforced standards
24
+ *
25
+ * @param {Object} discoveredPattern - Pattern to validate
26
+ * @param {string} discoveredPattern.element - Pattern element (e.g., "Lambda DB Connection")
27
+ * @param {string} discoveredPattern.rule - Pattern rule (e.g., "Use connection pools")
28
+ * @param {string} discoveredPattern.project_id - Project where pattern was discovered
29
+ * @param {string} discoveredPattern.context - Additional context for validation
30
+ * @returns {Promise<Object>} Validation result with violations if any
31
+ */
32
+ async validatePattern(discoveredPattern) {
33
+ const { element, rule, project_id, context = {} } = discoveredPattern;
34
+
35
+ // Check against enforced standards
36
+ const violations = await this.checkViolations(element, rule, context);
37
+
38
+ if (violations.length > 0) {
39
+ return {
40
+ valid: false,
41
+ violations: await Promise.all(
42
+ violations.map(async (v) => ({
43
+ standard: v.pattern_id,
44
+ element: v.element,
45
+ rule: v.rule,
46
+ severity: this.getSeverity(v.maturity),
47
+ guidance: this.generateGuidance(v, discoveredPattern),
48
+ examples: v.examples || [],
49
+ teamEvidence: await this.getTeamEvidence(v.element, project_id),
50
+ costImpact: v.cost_impact || null,
51
+ antiPattern: v.anti_patterns || null
52
+ }))
53
+ )
54
+ };
55
+ }
56
+
57
+ return { valid: true };
58
+ }
59
+
60
+ /**
61
+ * Check for violations against standards
62
+ *
63
+ * @param {string} element - Pattern element to check
64
+ * @param {string} rule - Pattern rule to check
65
+ * @param {Object} context - Additional context for validation
66
+ * @returns {Promise<Array>} Array of violated standards
67
+ */
68
+ async checkViolations(element, rule, context = {}) {
69
+ // Query for conflicting standards
70
+ const query = `
71
+ SELECT
72
+ pattern_id,
73
+ element,
74
+ rule,
75
+ maturity,
76
+ anti_patterns,
77
+ examples,
78
+ cost_impact,
79
+ category
80
+ FROM rapport.standards_patterns
81
+ WHERE element ILIKE $1
82
+ AND maturity IN ('enforced', 'validated')
83
+ AND rule != $2
84
+ ORDER BY
85
+ CASE maturity
86
+ WHEN 'enforced' THEN 1
87
+ WHEN 'validated' THEN 2
88
+ ELSE 3
89
+ END
90
+ `;
91
+
92
+ try {
93
+ const result = await executeQuery(query, [`%${element}%`, rule]);
94
+
95
+ // Additional context-based filtering
96
+ const violations = result.rows.filter(standard =>
97
+ this.matchesContext(standard, context)
98
+ );
99
+
100
+ return violations;
101
+ } catch (error) {
102
+ console.error('Error checking violations:', error);
103
+ throw new Error(`Failed to check violations: ${error.message}`);
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Check if standard matches the provided context
109
+ *
110
+ * @param {Object} standard - Standard to check
111
+ * @param {Object} context - Context to match against
112
+ * @returns {boolean} True if standard applies to this context
113
+ */
114
+ matchesContext(standard, context) {
115
+ // If no applicable_files filter, standard applies everywhere
116
+ if (!standard.applicable_files || standard.applicable_files.length === 0) {
117
+ return true;
118
+ }
119
+
120
+ // If context has file information, check if it matches
121
+ if (context.currentFile) {
122
+ return standard.applicable_files.some(pattern => {
123
+ // Simple glob-like matching
124
+ const regex = new RegExp(
125
+ pattern.replace(/\*/g, '.*').replace(/\?/g, '.')
126
+ );
127
+ return regex.test(context.currentFile);
128
+ });
129
+ }
130
+
131
+ // Default to applying the standard
132
+ return true;
133
+ }
134
+
135
+ /**
136
+ * Get severity level based on maturity
137
+ *
138
+ * @param {string} maturity - Standard maturity level
139
+ * @returns {string} Severity level
140
+ */
141
+ getSeverity(maturity) {
142
+ return this.severityLevels[maturity] || 'info';
143
+ }
144
+
145
+ /**
146
+ * Generate actionable guidance for a violation
147
+ *
148
+ * @param {Object} violation - Violated standard
149
+ * @param {Object} discoveredPattern - Pattern that violated the standard
150
+ * @returns {Object} Guidance object with problem, fix, and rationale
151
+ */
152
+ generateGuidance(violation, discoveredPattern) {
153
+ const guidance = {
154
+ problem: `Pattern violates ${violation.element} standard`,
155
+ standard: violation.pattern_id,
156
+ violatedRule: discoveredPattern.rule,
157
+ correctRule: violation.rule,
158
+ fix: null,
159
+ why: null,
160
+ category: violation.category
161
+ };
162
+
163
+ // Extract fix from examples if available
164
+ if (violation.examples && violation.examples.length > 0) {
165
+ const firstExample = violation.examples[0];
166
+ guidance.fix = typeof firstExample === 'string'
167
+ ? firstExample
168
+ : firstExample.code || firstExample.description;
169
+ }
170
+
171
+ // Extract rationale from cost impact or anti-patterns
172
+ if (violation.cost_impact) {
173
+ if (typeof violation.cost_impact === 'string') {
174
+ guidance.why = violation.cost_impact;
175
+ } else if (violation.cost_impact.description) {
176
+ guidance.why = violation.cost_impact.description;
177
+ } else if (violation.cost_impact.monthly_cost) {
178
+ guidance.why = `Cost impact: ${violation.cost_impact.monthly_cost}`;
179
+ }
180
+ } else if (violation.anti_patterns) {
181
+ const antiPattern = Array.isArray(violation.anti_patterns)
182
+ ? violation.anti_patterns[0]
183
+ : violation.anti_patterns;
184
+
185
+ if (typeof antiPattern === 'string') {
186
+ guidance.why = antiPattern;
187
+ } else if (antiPattern.reason) {
188
+ guidance.why = antiPattern.reason;
189
+ }
190
+ }
191
+
192
+ // Default rationale if none found
193
+ if (!guidance.why) {
194
+ guidance.why = 'Proven pattern from team experience and organization standards';
195
+ }
196
+
197
+ return guidance;
198
+ }
199
+
200
+ /**
201
+ * Get team evidence that reinforces this standard
202
+ *
203
+ * @param {string} element - Pattern element
204
+ * @param {string} project_id - Project ID for team context
205
+ * @returns {Promise<Array>} Array of team evidence records
206
+ */
207
+ async getTeamEvidence(element, project_id) {
208
+ const query = `
209
+ SELECT
210
+ pu.email_address,
211
+ p.project_id,
212
+ COUNT(*) as usage_count,
213
+ SUM(CASE WHEN pu.success THEN 1 ELSE 0 END) as success_count,
214
+ ROUND(
215
+ AVG(CASE WHEN pu.success THEN 1.0 ELSE 0.0 END)::numeric,
216
+ 2
217
+ ) as success_correlation,
218
+ MAX(pu.used_at) as last_used
219
+ FROM rapport.pattern_usage pu
220
+ JOIN rapport.patterns p ON pu.pattern_id = p.pattern_id
221
+ WHERE p.intent ILIKE $1
222
+ AND (p.project_id = $2 OR $2 IS NULL)
223
+ GROUP BY pu.email_address, p.project_id
224
+ HAVING COUNT(*) > 0
225
+ ORDER BY success_correlation DESC, usage_count DESC
226
+ LIMIT 5
227
+ `;
228
+
229
+ try {
230
+ const result = await executeQuery(query, [`%${element}%`, project_id]);
231
+ return result.rows.map(row => ({
232
+ user: row.email_address,
233
+ project: row.project_id,
234
+ usageCount: parseInt(row.usage_count),
235
+ successCount: parseInt(row.success_count),
236
+ successRate: parseFloat(row.success_correlation),
237
+ lastUsed: row.last_used
238
+ }));
239
+ } catch (error) {
240
+ console.error('Error fetching team evidence:', error);
241
+ return [];
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Validate multiple patterns in bulk
247
+ *
248
+ * @param {Array<Object>} patterns - Array of patterns to validate
249
+ * @returns {Promise<Object>} Validation summary with all violations
250
+ */
251
+ async validatePatterns(patterns) {
252
+ const results = await Promise.all(
253
+ patterns.map(pattern => this.validatePattern(pattern))
254
+ );
255
+
256
+ const violations = results
257
+ .filter(result => !result.valid)
258
+ .flatMap(result => result.violations);
259
+
260
+ return {
261
+ totalPatterns: patterns.length,
262
+ validPatterns: results.filter(r => r.valid).length,
263
+ invalidPatterns: results.filter(r => !r.valid).length,
264
+ criticalViolations: violations.filter(v => v.severity === 'critical').length,
265
+ warningViolations: violations.filter(v => v.severity === 'warning').length,
266
+ violations: violations
267
+ };
268
+ }
269
+
270
+ /**
271
+ * Get all anti-patterns for a specific category
272
+ *
273
+ * @param {string} category - Category to get anti-patterns for
274
+ * @returns {Promise<Array>} Array of anti-patterns with details
275
+ */
276
+ async getAntiPatterns(category) {
277
+ const query = `
278
+ SELECT
279
+ pattern_id,
280
+ element,
281
+ rule,
282
+ anti_patterns,
283
+ cost_impact,
284
+ examples
285
+ FROM rapport.standards_patterns
286
+ WHERE category = $1
287
+ AND maturity = 'enforced'
288
+ AND anti_patterns IS NOT NULL
289
+ ORDER BY pattern_id
290
+ `;
291
+
292
+ try {
293
+ const result = await executeQuery(query, [category]);
294
+ return result.rows.map(row => ({
295
+ patternId: row.pattern_id,
296
+ element: row.element,
297
+ correctRule: row.rule,
298
+ antiPatterns: row.anti_patterns,
299
+ costImpact: row.cost_impact,
300
+ examples: row.examples
301
+ }));
302
+ } catch (error) {
303
+ console.error('Error fetching anti-patterns:', error);
304
+ throw new Error(`Failed to fetch anti-patterns: ${error.message}`);
305
+ }
306
+ }
307
+
308
+ /**
309
+ * Format validation result for display
310
+ *
311
+ * @param {Object} validationResult - Result from validatePattern
312
+ * @returns {string} Formatted text output
313
+ */
314
+ formatValidationResult(validationResult) {
315
+ if (validationResult.valid) {
316
+ return '✓ Pattern is compliant with standards';
317
+ }
318
+
319
+ const lines = ['✗ Pattern violates organization standards:\n'];
320
+
321
+ validationResult.violations.forEach((violation, index) => {
322
+ const severityIcon = {
323
+ critical: '🚨',
324
+ warning: '⚠️',
325
+ info: 'ℹ️'
326
+ }[violation.severity] || '•';
327
+
328
+ lines.push(`${severityIcon} Violation ${index + 1}: ${violation.guidance.problem}`);
329
+ lines.push(` Standard: ${violation.standard}`);
330
+ lines.push(` Severity: ${violation.severity.toUpperCase()}`);
331
+ lines.push(` Your pattern: "${violation.guidance.violatedRule}"`);
332
+ lines.push(` Standard rule: "${violation.guidance.correctRule}"`);
333
+
334
+ if (violation.guidance.why) {
335
+ lines.push(` Why: ${violation.guidance.why}`);
336
+ }
337
+
338
+ if (violation.guidance.fix) {
339
+ lines.push(` Fix: ${violation.guidance.fix}`);
340
+ }
341
+
342
+ if (violation.teamEvidence && violation.teamEvidence.length > 0) {
343
+ lines.push(` Team evidence: ${violation.teamEvidence.length} team members have used this pattern`);
344
+ const topEvidence = violation.teamEvidence[0];
345
+ lines.push(` - ${topEvidence.user}: ${topEvidence.successRate * 100}% success rate (${topEvidence.usageCount} uses)`);
346
+ }
347
+
348
+ lines.push('');
349
+ });
350
+
351
+ return lines.join('\n');
352
+ }
353
+ }
354
+
355
+ module.exports = { PatternValidator };
@@ -0,0 +1,160 @@
1
+ # Rapport Core Components
2
+
3
+ This directory contains the core components of the Rapport Standards Integration system.
4
+
5
+ ## Components
6
+
7
+ ### RelevanceDetector.js (Phase 2) ✅
8
+
9
+ **Purpose**: Identifies which standards apply to current work
10
+
11
+ **Key Features**:
12
+ - Fast project characteristic detection (< 100ms)
13
+ - Intelligent category mapping
14
+ - Relevance scoring algorithm (0-100)
15
+ - Returns top 10 most relevant standards
16
+ - Database integration with Phase 1 schema
17
+
18
+ **Usage**:
19
+ ```javascript
20
+ const { RelevanceDetector } = require('./src/core/RelevanceDetector');
21
+
22
+ const detector = new RelevanceDetector({
23
+ workingDirectory: process.cwd()
24
+ });
25
+
26
+ const result = await detector.detectRelevantStandards({
27
+ projectId: 'prj_example',
28
+ currentFile: 'src/handlers/userCreate.js'
29
+ });
30
+
31
+ console.log(`Found ${result.standards.length} relevant standards`);
32
+ // Execution time: ~250ms
33
+ ```
34
+
35
+ **Documentation**: `/Users/jamesford/Source/rapport/docs/PHASE_2_RELEVANCE_DETECTION.md`
36
+
37
+ **Test Suite**: `/Users/jamesford/Source/rapport/scripts/test-relevance-detection.js`
38
+
39
+ ---
40
+
41
+ ### TeamLoadBearingDetector.js (Existing)
42
+
43
+ **Purpose**: Detects load-bearing context elements from team sessions
44
+
45
+ **Key Features**:
46
+ - Team-wide correlation analysis
47
+ - User-specific pattern tracking
48
+ - Confidence scoring
49
+ - Statistical significance testing
50
+
51
+ ---
52
+
53
+ ## Phase Implementation Status
54
+
55
+ | Phase | Status | Component | Documentation |
56
+ |-------|--------|-----------|---------------|
57
+ | Phase 1 | Pending | StandardsIngestion.js | - |
58
+ | Phase 2 | ✅ Complete | RelevanceDetector.js | PHASE_2_RELEVANCE_DETECTION.md |
59
+ | Phase 3 | Pending | PatternValidator.js | - |
60
+ | Phase 4 | Pending | CurationEngine.js | - |
61
+ | Phase 5 | Pending | Hooks (session-start, pre-compact) | - |
62
+ | Phase 6 | Pending | RapportOrchestrator.js | - |
63
+
64
+ ---
65
+
66
+ ## Testing
67
+
68
+ ```bash
69
+ # Test RelevanceDetector
70
+ node scripts/test-relevance-detection.js
71
+
72
+ # Quick validation
73
+ node -e "
74
+ const { RelevanceDetector } = require('./src/core/RelevanceDetector');
75
+ const detector = new RelevanceDetector();
76
+ console.log('✓ RelevanceDetector ready');
77
+ "
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Integration
83
+
84
+ ### With Claude Code (Phase 5)
85
+
86
+ ```javascript
87
+ // rapport/hooks/session-start.js
88
+ const { RelevanceDetector } = require('@mindmeld/rapport/relevance');
89
+
90
+ async function injectContext() {
91
+ const detector = new RelevanceDetector({
92
+ workingDirectory: process.cwd()
93
+ });
94
+
95
+ const result = await detector.detectRelevantStandards({
96
+ projectId: getCurrentProjectId(),
97
+ currentFile: getCurrentFile()
98
+ });
99
+
100
+ return detector.formatForInjection(result.standards);
101
+ }
102
+ ```
103
+
104
+ ### With Pattern Validation (Phase 3)
105
+
106
+ ```javascript
107
+ // rapport/src/core/PatternValidator.js
108
+ const { RelevanceDetector } = require('./RelevanceDetector');
109
+
110
+ async function validatePattern(pattern) {
111
+ const detector = new RelevanceDetector();
112
+ const relevant = await detector.detectRelevantStandards(context);
113
+
114
+ // Validate against only relevant standards
115
+ return checkAgainstStandards(pattern, relevant.standards);
116
+ }
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Database Requirements
122
+
123
+ All core components require PostgreSQL database with Rapport schema.
124
+
125
+ **Connection**: Uses `src/handlers/helpers/dbOperations.js`
126
+
127
+ **Schema**: See `database/schema.sql`
128
+
129
+ **Environment Variables**:
130
+ - `DB_HOST`
131
+ - `DB_PORT`
132
+ - `DB_NAME`
133
+ - `DB_USER`
134
+ - `DB_PASSWORD`
135
+
136
+ ---
137
+
138
+ ## Performance Targets
139
+
140
+ | Component | Target | Actual |
141
+ |-----------|--------|--------|
142
+ | RelevanceDetector | < 500ms | ~250ms ✓ |
143
+ | TeamLoadBearingDetector | < 1s | ~800ms ✓ |
144
+
145
+ ---
146
+
147
+ ## Contributing
148
+
149
+ When adding new core components:
150
+
151
+ 1. Follow existing patterns (constructor with options)
152
+ 2. Use `executeQuery` from dbOperations.js
153
+ 3. Include comprehensive JSDoc comments
154
+ 4. Create test script in `scripts/`
155
+ 5. Document in `docs/PHASE_X_*.md`
156
+ 6. Update this README
157
+
158
+ ---
159
+
160
+ **Last Updated**: 2025-12-20