@equilateral_ai/mindmeld 3.5.2 → 4.0.1

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 (140) hide show
  1. package/hooks/session-end.js +25 -0
  2. package/hooks/session-start.js +363 -83
  3. package/hooks/session-watcher.js +585 -0
  4. package/package.json +19 -13
  5. package/scripts/init-project.js +9 -23
  6. package/src/client/dbShim.js +16 -0
  7. package/src/core/AuthManager.js +3 -2
  8. package/src/handlers/helpers/dbOperations.js +9 -46
  9. package/src/index.js +2 -217
  10. package/src/utils/piiMask.js +16 -0
  11. package/scripts/harvest.js +0 -601
  12. package/scripts/inject.js +0 -409
  13. package/scripts/mcp-bridge.js +0 -220
  14. package/scripts/repo-analyzer.js +0 -870
  15. package/src/collaboration/CollaborationPrompt.js +0 -460
  16. package/src/core/AlertEngine.js +0 -813
  17. package/src/core/AlertNotifier.js +0 -363
  18. package/src/core/CorrelationAnalyzer.js +0 -931
  19. package/src/core/CrossReferenceEngine.js +0 -624
  20. package/src/core/CurationEngine.js +0 -688
  21. package/src/core/DeprecationScheduler.js +0 -183
  22. package/src/core/LoadBearingDetector.js +0 -242
  23. package/src/core/NotificationService.js +0 -1032
  24. package/src/core/RapportOrchestrator.js +0 -632
  25. package/src/core/RelevanceDetector.js +0 -694
  26. package/src/core/StandardLifecycle.js +0 -244
  27. package/src/core/StandardsIngestion.js +0 -991
  28. package/src/core/TeamLoadBearingDetector.js +0 -431
  29. package/src/core/parsers/adrParser.js +0 -479
  30. package/src/core/parsers/cursorRulesParser.js +0 -564
  31. package/src/core/parsers/eslintParser.js +0 -439
  32. package/src/database/dbOperations.js +0 -105
  33. package/src/handlers/activity/activityGetMe.js +0 -98
  34. package/src/handlers/activity/activityGetTeam.js +0 -175
  35. package/src/handlers/admin/adminSetup.js +0 -216
  36. package/src/handlers/alerts/alertsAcknowledge.js +0 -92
  37. package/src/handlers/alerts/alertsGet.js +0 -250
  38. package/src/handlers/analytics/activitySummaryGet.js +0 -234
  39. package/src/handlers/analytics/coachingGet.js +0 -361
  40. package/src/handlers/analytics/convergenceGet.js +0 -236
  41. package/src/handlers/analytics/developerScoreGet.js +0 -137
  42. package/src/handlers/collaborators/collaboratorAdd.js +0 -200
  43. package/src/handlers/collaborators/collaboratorInvite.js +0 -219
  44. package/src/handlers/collaborators/collaboratorList.js +0 -82
  45. package/src/handlers/collaborators/collaboratorRemove.js +0 -128
  46. package/src/handlers/collaborators/inviteAccept.js +0 -122
  47. package/src/handlers/company/companyUsersDelete.js +0 -141
  48. package/src/handlers/company/companyUsersGet.js +0 -90
  49. package/src/handlers/company/companyUsersPost.js +0 -267
  50. package/src/handlers/company/companyUsersPut.js +0 -76
  51. package/src/handlers/context/contextGet.js +0 -57
  52. package/src/handlers/context/invariantsGet.js +0 -74
  53. package/src/handlers/context/loopsGet.js +0 -82
  54. package/src/handlers/context/notesCreate.js +0 -74
  55. package/src/handlers/context/purposeGet.js +0 -78
  56. package/src/handlers/correlations/correlationsDeveloperGet.js +0 -227
  57. package/src/handlers/correlations/correlationsGet.js +0 -93
  58. package/src/handlers/correlations/correlationsProjectGet.js +0 -153
  59. package/src/handlers/enterprise/controlTowerGet.js +0 -224
  60. package/src/handlers/enterprise/enterpriseAuditGet.js +0 -108
  61. package/src/handlers/enterprise/enterpriseContributorsGet.js +0 -85
  62. package/src/handlers/enterprise/enterpriseKnowledgeCategoriesGet.js +0 -53
  63. package/src/handlers/enterprise/enterpriseKnowledgeCreate.js +0 -77
  64. package/src/handlers/enterprise/enterpriseKnowledgeDelete.js +0 -71
  65. package/src/handlers/enterprise/enterpriseKnowledgeGet.js +0 -87
  66. package/src/handlers/enterprise/enterpriseKnowledgeUpdate.js +0 -122
  67. package/src/handlers/enterprise/enterpriseOnboardingComplete.js +0 -77
  68. package/src/handlers/enterprise/enterpriseOnboardingInvite.js +0 -138
  69. package/src/handlers/enterprise/enterpriseOnboardingSetup.js +0 -128
  70. package/src/handlers/enterprise/enterpriseOnboardingStatus.js +0 -88
  71. package/src/handlers/github/githubConnectionStatus.js +0 -49
  72. package/src/handlers/github/githubDiscoverPatterns.js +0 -621
  73. package/src/handlers/github/githubOAuthCallback.js +0 -178
  74. package/src/handlers/github/githubOAuthStart.js +0 -59
  75. package/src/handlers/github/githubPatternsReview.js +0 -76
  76. package/src/handlers/github/githubReposList.js +0 -105
  77. package/src/handlers/health/healthGet.js +0 -55
  78. package/src/handlers/helpers/auditLogger.js +0 -201
  79. package/src/handlers/helpers/checkSuperAdmin.js +0 -84
  80. package/src/handlers/helpers/decisionFrames.js +0 -29
  81. package/src/handlers/helpers/errorHandler.js +0 -49
  82. package/src/handlers/helpers/index.js +0 -138
  83. package/src/handlers/helpers/lambdaWrapper.js +0 -60
  84. package/src/handlers/helpers/mindmeldMcpCore.js +0 -1103
  85. package/src/handlers/helpers/predictiveCache.js +0 -51
  86. package/src/handlers/helpers/projectAccess.js +0 -88
  87. package/src/handlers/helpers/responseUtil.js +0 -55
  88. package/src/handlers/helpers/subscriptionTiers.js +0 -1168
  89. package/src/handlers/mcp/mcpHandler.js +0 -569
  90. package/src/handlers/mcp/mindmeldMcpHandler.js +0 -124
  91. package/src/handlers/mcp/mindmeldMcpStreamHandler.js +0 -342
  92. package/src/handlers/notifications/getPreferences.js +0 -84
  93. package/src/handlers/notifications/sendNotification.js +0 -170
  94. package/src/handlers/notifications/updatePreferences.js +0 -316
  95. package/src/handlers/patterns/patternEvaluatePromotionPost.js +0 -173
  96. package/src/handlers/patterns/patternUsagePost.js +0 -182
  97. package/src/handlers/patterns/patternViolationPost.js +0 -185
  98. package/src/handlers/projects/projectCreate.js +0 -248
  99. package/src/handlers/projects/projectDelete.js +0 -82
  100. package/src/handlers/projects/projectGet.js +0 -95
  101. package/src/handlers/projects/projectUpdate.js +0 -117
  102. package/src/handlers/reports/aiLeverage.js +0 -210
  103. package/src/handlers/reports/engineeringInvestment.js +0 -132
  104. package/src/handlers/reports/riskForecast.js +0 -206
  105. package/src/handlers/reports/standardsRoi.js +0 -254
  106. package/src/handlers/scheduled/analyzeCorrelations.js +0 -178
  107. package/src/handlers/scheduled/analyzeGitHistory.js +0 -510
  108. package/src/handlers/scheduled/generateAlerts.js +0 -135
  109. package/src/handlers/scheduled/maturityUpdateJob.js +0 -166
  110. package/src/handlers/scheduled/refreshActivity.js +0 -21
  111. package/src/handlers/scheduled/scanCompliance.js +0 -334
  112. package/src/handlers/sessions/sessionEndPost.js +0 -180
  113. package/src/handlers/sessions/sessionStandardsPost.js +0 -171
  114. package/src/handlers/standards/catalogGet.js +0 -185
  115. package/src/handlers/standards/catalogSync.js +0 -120
  116. package/src/handlers/standards/discoveriesGet.js +0 -89
  117. package/src/handlers/standards/projectStandardsGet.js +0 -129
  118. package/src/handlers/standards/projectStandardsPut.js +0 -151
  119. package/src/handlers/standards/standardsAuditGet.js +0 -65
  120. package/src/handlers/standards/standardsParseUpload.js +0 -149
  121. package/src/handlers/standards/standardsRelevantPost.js +0 -405
  122. package/src/handlers/standards/standardsTransition.js +0 -161
  123. package/src/handlers/stripe/addonManagePost.js +0 -240
  124. package/src/handlers/stripe/billingPortalPost.js +0 -93
  125. package/src/handlers/stripe/enterpriseCheckoutPost.js +0 -272
  126. package/src/handlers/stripe/seatsUpdatePost.js +0 -185
  127. package/src/handlers/stripe/subscriptionCancelDelete.js +0 -169
  128. package/src/handlers/stripe/subscriptionCreatePost.js +0 -221
  129. package/src/handlers/stripe/subscriptionUpdatePut.js +0 -163
  130. package/src/handlers/stripe/webhookPost.js +0 -482
  131. package/src/handlers/user/apiTokenCreate.js +0 -71
  132. package/src/handlers/user/apiTokenList.js +0 -64
  133. package/src/handlers/user/userSplashAck.js +0 -91
  134. package/src/handlers/user/userSplashGet.js +0 -211
  135. package/src/handlers/users/cognitoPostConfirmation.js +0 -186
  136. package/src/handlers/users/cognitoPreSignUp.js +0 -114
  137. package/src/handlers/users/userEntitlementsGet.js +0 -89
  138. package/src/handlers/users/userGet.js +0 -118
  139. package/src/handlers/users/userProfilePut.js +0 -77
  140. package/src/handlers/webhooks/githubWebhook.js +0 -215
@@ -1,363 +0,0 @@
1
- /**
2
- * Rapport v3 - Alert Notifier
3
- *
4
- * Purpose: Sends notifications when attention alerts are generated
5
- *
6
- * Integration: Called by generateAlerts scheduled handler
7
- * Channels: Email and Slack based on user preferences
8
- */
9
-
10
- // Note: When used in Lambda, executeQuery comes from helpers (injected via setExecuteQuery)
11
- // When used in CLI/scripts, it can be provided via constructor
12
- let executeQueryFn = null;
13
-
14
- function setExecuteQuery(queryFn) {
15
- executeQueryFn = queryFn;
16
- }
17
-
18
- function getExecuteQuery() {
19
- if (!executeQueryFn) {
20
- // Try to require from database/dbOperations as fallback
21
- try {
22
- return require('../handlers/helpers/dbOperations').executeQuery;
23
- } catch (e) {
24
- throw new Error('AlertNotifier: executeQuery not initialized. Call setExecuteQuery() first.');
25
- }
26
- }
27
- return executeQueryFn;
28
- }
29
-
30
- const { NotificationService } = require('./NotificationService');
31
-
32
- class AlertNotifier {
33
- constructor(config = {}) {
34
- this.config = {
35
- notifyOnSeverity: config.notifyOnSeverity || ['concern', 'warning'], // Which severities trigger notifications
36
- slackOnlyForCritical: config.slackOnlyForCritical !== false, // Only send Slack for critical/concern alerts
37
- ...config
38
- };
39
-
40
- this.notificationService = config.notificationService || new NotificationService();
41
- }
42
-
43
- /**
44
- * Notify managers about new alerts
45
- *
46
- * @param {Array} alerts - List of alert objects
47
- * @returns {Promise<Object>} Notification results
48
- */
49
- async notifyForAlerts(alerts) {
50
- if (!alerts || alerts.length === 0) {
51
- return { notified: 0, skipped: 0, failed: 0 };
52
- }
53
-
54
- const results = {
55
- notified: 0,
56
- skipped: 0,
57
- failed: 0,
58
- errors: []
59
- };
60
-
61
- // Group alerts by company for batch processing
62
- const alertsByCompany = this.groupAlertsByCompany(alerts);
63
-
64
- for (const [companyId, companyAlerts] of Object.entries(alertsByCompany)) {
65
- try {
66
- // Get managers for this company
67
- const managers = await this.getCompanyManagers(companyId);
68
-
69
- if (managers.length === 0) {
70
- console.log(`[AlertNotifier] No managers found for company ${companyId}`);
71
- results.skipped += companyAlerts.length;
72
- continue;
73
- }
74
-
75
- // Send notifications to each manager
76
- for (const manager of managers) {
77
- const preferences = await this.getUserPreferences(manager.email_address);
78
-
79
- for (const alert of companyAlerts) {
80
- // Check if alert severity warrants notification
81
- if (!this.config.notifyOnSeverity.includes(alert.severity)) {
82
- results.skipped++;
83
- continue;
84
- }
85
-
86
- try {
87
- const sendResult = await this.notificationService.sendNotification({
88
- type: 'team_alert',
89
- email: manager.email_address,
90
- preferences: preferences,
91
- data: {
92
- alertId: alert.alert_id,
93
- alertType: alert.alert_type,
94
- severity: alert.severity,
95
- userName: alert.user_name || alert.email_address,
96
- details: alert.details,
97
- message: this.getAlertMessage(alert.alert_type, alert.details),
98
- referenceType: 'attention_alert',
99
- referenceId: String(alert.alert_id)
100
- },
101
- projectId: null // Alerts are company-wide
102
- });
103
-
104
- if (sendResult.email?.sent || sendResult.slack?.sent) {
105
- results.notified++;
106
-
107
- // Log the notification
108
- await this.logNotification(
109
- manager.email_address,
110
- 'team_alert',
111
- sendResult.email?.sent ? 'email' : 'slack',
112
- 'sent',
113
- alert
114
- );
115
- } else {
116
- results.skipped++;
117
- }
118
- } catch (error) {
119
- results.failed++;
120
- results.errors.push({
121
- alertId: alert.alert_id,
122
- manager: manager.email_address,
123
- error: error.message
124
- });
125
-
126
- // Log failed notification
127
- await this.logNotification(
128
- manager.email_address,
129
- 'team_alert',
130
- 'email',
131
- 'failed',
132
- alert,
133
- error.message
134
- );
135
- }
136
- }
137
- }
138
- } catch (error) {
139
- console.error(`[AlertNotifier] Error processing company ${companyId}:`, error);
140
- results.failed += companyAlerts.length;
141
- }
142
- }
143
-
144
- console.log(`[AlertNotifier] Results: ${results.notified} notified, ${results.skipped} skipped, ${results.failed} failed`);
145
- return results;
146
- }
147
-
148
- /**
149
- * Group alerts by company ID
150
- */
151
- groupAlertsByCompany(alerts) {
152
- const grouped = {};
153
- for (const alert of alerts) {
154
- const companyId = alert.company_id || 'unknown';
155
- if (!grouped[companyId]) {
156
- grouped[companyId] = [];
157
- }
158
- grouped[companyId].push(alert);
159
- }
160
- return grouped;
161
- }
162
-
163
- /**
164
- * Get managers for a company
165
- */
166
- async getCompanyManagers(companyId) {
167
- const executeQuery = getExecuteQuery();
168
- const query = `
169
- SELECT DISTINCT
170
- ue."Email_Address" as email_address,
171
- u."User_Display_Name" as user_name
172
- FROM "UserEntitlements" ue
173
- JOIN "Users" u ON ue."Email_Address" = u."Email_Address"
174
- WHERE ue."Company_ID" = $1
175
- AND (ue."Manager" = true OR ue."Admin" = true OR u."Super_Admin" = true)
176
- AND u."active" = true
177
- `;
178
-
179
- const result = await executeQuery(query, [companyId]);
180
- return result.rows;
181
- }
182
-
183
- /**
184
- * Get user notification preferences
185
- */
186
- async getUserPreferences(email) {
187
- const executeQuery = getExecuteQuery();
188
- const query = `SELECT rapport.get_notification_preferences($1) as preferences`;
189
- const result = await executeQuery(query, [email]);
190
- return result.rows[0]?.preferences || null;
191
- }
192
-
193
- /**
194
- * Generate human-readable alert message
195
- */
196
- getAlertMessage(alertType, details) {
197
- switch (alertType) {
198
- case 'stale_commits':
199
- return `No commits in ${details.days_since_commit} days`;
200
- case 'low_conversion':
201
- return `Low session-to-commit conversion: ${details.conversion_pct}%`;
202
- case 'no_ai_usage':
203
- return `Active committer not using AI assistance`;
204
- case 'declining_activity':
205
- return `Activity declining over past ${details.period || 'week'}`;
206
- case 'blocked_developer':
207
- return `Developer appears blocked - ${details.reason || 'multiple failed sessions'}`;
208
- case 'pattern_violation':
209
- return `Repeated pattern violations detected`;
210
- default:
211
- return `Alert: ${alertType}`;
212
- }
213
- }
214
-
215
- /**
216
- * Log notification to database
217
- */
218
- async logNotification(email, type, channel, status, alert, errorMessage = null) {
219
- try {
220
- const executeQuery = getExecuteQuery();
221
- await executeQuery(`
222
- SELECT rapport.log_notification($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
223
- `, [
224
- email,
225
- type,
226
- channel,
227
- status,
228
- null, // project_id
229
- 'attention_alert',
230
- String(alert.alert_id),
231
- JSON.stringify({ alertType: alert.alert_type, severity: alert.severity }),
232
- null, // message_id
233
- errorMessage
234
- ]);
235
- } catch (error) {
236
- console.error('[AlertNotifier] Failed to log notification:', error);
237
- }
238
- }
239
-
240
- /**
241
- * Send critical alert immediately (bypass preferences for critical issues)
242
- *
243
- * @param {Object} alert - Alert object
244
- * @param {string} managerEmail - Manager email to notify
245
- * @returns {Promise<Object>} Send result
246
- */
247
- async sendCriticalAlert(alert, managerEmail) {
248
- // For critical alerts, always send both email and Slack
249
- const preferences = {
250
- email_enabled: true,
251
- slack_enabled: true,
252
- notification_types: {
253
- team_alert: { email: true, slack: true }
254
- }
255
- };
256
-
257
- return this.notificationService.sendNotification({
258
- type: 'team_alert',
259
- email: managerEmail,
260
- preferences: preferences,
261
- data: {
262
- alertId: alert.alert_id,
263
- alertType: alert.alert_type,
264
- severity: 'critical',
265
- userName: alert.user_name || alert.email_address,
266
- details: alert.details,
267
- message: this.getAlertMessage(alert.alert_type, alert.details),
268
- referenceType: 'attention_alert',
269
- referenceId: String(alert.alert_id)
270
- }
271
- });
272
- }
273
-
274
- /**
275
- * Send daily digest of alerts to managers
276
- *
277
- * @param {string} companyId - Company ID
278
- * @returns {Promise<Object>} Send results
279
- */
280
- async sendAlertDigest(companyId) {
281
- const executeQuery = getExecuteQuery();
282
-
283
- // Get active alerts for the company
284
- const alerts = await executeQuery(`
285
- SELECT
286
- aa.alert_id,
287
- aa.email_address,
288
- u."User_Display_Name" as user_name,
289
- aa.alert_type,
290
- aa.severity,
291
- aa.details,
292
- aa.created_at
293
- FROM rapport.attention_alerts aa
294
- JOIN "Users" u ON aa.email_address = u."Email_Address"
295
- WHERE aa.company_id = $1
296
- AND aa.status = 'active'
297
- ORDER BY
298
- CASE aa.severity WHEN 'concern' THEN 1 WHEN 'warning' THEN 2 ELSE 3 END,
299
- aa.created_at DESC
300
- LIMIT 10
301
- `, [companyId]);
302
-
303
- if (alerts.rows.length === 0) {
304
- return { sent: false, reason: 'no_active_alerts' };
305
- }
306
-
307
- // Get managers for this company
308
- const managers = await this.getCompanyManagers(companyId);
309
-
310
- const results = {
311
- sent: 0,
312
- failed: 0
313
- };
314
-
315
- for (const manager of managers) {
316
- const preferences = await this.getUserPreferences(manager.email_address);
317
-
318
- // Build digest data
319
- const digestData = {
320
- companyId: companyId,
321
- alertCount: alerts.rows.length,
322
- alerts: alerts.rows.map(a => ({
323
- userName: a.user_name,
324
- alertType: a.alert_type,
325
- severity: a.severity,
326
- message: this.getAlertMessage(a.alert_type, a.details),
327
- createdAt: a.created_at
328
- })),
329
- concernCount: alerts.rows.filter(a => a.severity === 'concern').length,
330
- warningCount: alerts.rows.filter(a => a.severity === 'warning').length
331
- };
332
-
333
- try {
334
- // Use weekly_digest type but with alert data
335
- await this.notificationService.sendNotification({
336
- type: 'weekly_digest',
337
- email: manager.email_address,
338
- preferences: preferences,
339
- data: {
340
- userName: manager.user_name || manager.email_address,
341
- weekStart: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toLocaleDateString(),
342
- weekEnd: new Date().toLocaleDateString(),
343
- teamActivity: {
344
- activeAlerts: digestData.alertCount,
345
- concernAlerts: digestData.concernCount,
346
- warningAlerts: digestData.warningCount
347
- },
348
- alerts: digestData.alerts
349
- }
350
- });
351
-
352
- results.sent++;
353
- } catch (error) {
354
- console.error(`[AlertNotifier] Failed to send digest to ${manager.email_address}:`, error);
355
- results.failed++;
356
- }
357
- }
358
-
359
- return results;
360
- }
361
- }
362
-
363
- module.exports = { AlertNotifier, setExecuteQuery };