monomind 1.15.3 → 1.15.5
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/.claude/scheduled_tasks.lock +1 -1
- package/package.json +1 -1
- package/packages/@monomind/cli/dist/src/mcp-client.js +7 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/causal-infer.d.ts +15 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/causal-infer.js +347 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/coherence-check.d.ts +15 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/coherence-check.js +206 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/consensus-verify.d.ts +15 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/consensus-verify.js +303 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/memory-gate.d.ts +15 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/memory-gate.js +266 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/quantum-topology.d.ts +15 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/quantum-topology.js +406 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/spectral-analyze.d.ts +15 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/spectral-analyze.js +293 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/types.d.ts +277 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence/types.js +159 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence-tools.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/coherence-tools.js +25 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/chaos-resilience/chaos-inject.d.ts +163 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/chaos-resilience/chaos-inject.js +414 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/coverage-analysis/analyze-coverage.d.ts +128 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/coverage-analysis/analyze-coverage.js +375 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/coverage-analysis/prioritize-gaps.d.ts +161 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/coverage-analysis/prioritize-gaps.js +423 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/coverage-analysis/track-trends.d.ts +165 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/coverage-analysis/track-trends.js +395 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/defect-intelligence/analyze-root-cause.d.ts +165 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/defect-intelligence/analyze-root-cause.js +508 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/defect-intelligence/find-similar-defects.d.ts +147 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/defect-intelligence/find-similar-defects.js +391 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/defect-intelligence/predict-defects.d.ts +147 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/defect-intelligence/predict-defects.js +422 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/quality-assessment/assess-readiness.d.ts +185 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/quality-assessment/assess-readiness.js +437 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/quality-assessment/calculate-risk.d.ts +166 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/quality-assessment/calculate-risk.js +410 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/quality-assessment/evaluate-quality-gate.d.ts +201 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/quality-assessment/evaluate-quality-gate.js +363 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/security-compliance/audit-compliance.d.ts +166 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/security-compliance/audit-compliance.js +394 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/security-compliance/detect-secrets.d.ts +129 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/security-compliance/detect-secrets.js +383 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/security-compliance/security-scan.d.ts +171 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/security-compliance/security-scan.js +476 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/test-generation/generate-tests.d.ts +147 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/test-generation/generate-tests.js +400 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/test-generation/suggest-tests.d.ts +145 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/test-generation/suggest-tests.js +328 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/test-generation/tdd-cycle.d.ts +126 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality/test-generation/tdd-cycle.js +348 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality-tools.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/quality-tools.js +308 -0
- package/packages/@monomind/cli/package.json +1 -1
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* track-trends.ts - Coverage trend tracking MCP tool handler
|
|
3
|
+
*
|
|
4
|
+
* Tracks coverage trends over time, detecting patterns, regressions,
|
|
5
|
+
* and improvements to provide actionable insights.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
// Input schema for track-trends tool
|
|
9
|
+
export const TrackTrendsInputSchema = z.object({
|
|
10
|
+
targetPath: z.string().optional().describe('Path to track (or all if not specified)'),
|
|
11
|
+
timeRange: z
|
|
12
|
+
.enum(['7d', '14d', '30d', '90d', '180d', '365d'])
|
|
13
|
+
.default('30d')
|
|
14
|
+
.describe('Time range for trend analysis'),
|
|
15
|
+
metrics: z
|
|
16
|
+
.array(z.enum(['line', 'branch', 'function', 'statement', 'overall']))
|
|
17
|
+
.default(['line', 'branch', 'overall'])
|
|
18
|
+
.describe('Metrics to track'),
|
|
19
|
+
detectRegressions: z.boolean().default(true).describe('Flag coverage regressions'),
|
|
20
|
+
regressionThreshold: z
|
|
21
|
+
.number()
|
|
22
|
+
.min(0)
|
|
23
|
+
.max(100)
|
|
24
|
+
.default(5)
|
|
25
|
+
.describe('Percentage drop to flag as regression'),
|
|
26
|
+
groupBy: z
|
|
27
|
+
.enum(['day', 'week', 'month', 'commit'])
|
|
28
|
+
.default('day')
|
|
29
|
+
.describe('Grouping for trend data'),
|
|
30
|
+
includeProjections: z.boolean().default(true).describe('Include future projections'),
|
|
31
|
+
compareBaseline: z.string().optional().describe('Baseline date to compare against (ISO format)'),
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* MCP Tool Handler for track-trends
|
|
35
|
+
*/
|
|
36
|
+
export async function handler(input, context) {
|
|
37
|
+
const startTime = Date.now();
|
|
38
|
+
try {
|
|
39
|
+
// Validate input
|
|
40
|
+
const validatedInput = TrackTrendsInputSchema.parse(input);
|
|
41
|
+
// Get memory bridge for historical data
|
|
42
|
+
const bridge = context.get('aqe.bridge');
|
|
43
|
+
// Calculate time range
|
|
44
|
+
const { start, end } = calculateTimeRange(validatedInput.timeRange);
|
|
45
|
+
// Fetch or generate trend data
|
|
46
|
+
const trendData = await fetchTrendData(validatedInput.targetPath, start, end, validatedInput.metrics, validatedInput.groupBy, bridge);
|
|
47
|
+
// Detect regressions
|
|
48
|
+
const regressions = validatedInput.detectRegressions
|
|
49
|
+
? detectRegressions(trendData.dataPoints, validatedInput.regressionThreshold)
|
|
50
|
+
: [];
|
|
51
|
+
// Detect improvements
|
|
52
|
+
const improvements = detectImprovements(trendData.dataPoints);
|
|
53
|
+
// Generate projections
|
|
54
|
+
const projections = validatedInput.includeProjections
|
|
55
|
+
? generateProjections(trendData, validatedInput.metrics)
|
|
56
|
+
: [];
|
|
57
|
+
// Generate insights
|
|
58
|
+
const insights = generateInsights(trendData, regressions, improvements, projections);
|
|
59
|
+
// Build result
|
|
60
|
+
const result = {
|
|
61
|
+
success: true,
|
|
62
|
+
trends: trendData,
|
|
63
|
+
regressions,
|
|
64
|
+
improvements,
|
|
65
|
+
projections,
|
|
66
|
+
insights,
|
|
67
|
+
metadata: {
|
|
68
|
+
analyzedAt: new Date().toISOString(),
|
|
69
|
+
durationMs: Date.now() - startTime,
|
|
70
|
+
dataPointCount: trendData.dataPoints.length,
|
|
71
|
+
timeRange: validatedInput.timeRange,
|
|
72
|
+
baselineDate: validatedInput.compareBaseline,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
content: [
|
|
77
|
+
{
|
|
78
|
+
type: 'text',
|
|
79
|
+
text: JSON.stringify(result, null, 2),
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
86
|
+
return {
|
|
87
|
+
content: [
|
|
88
|
+
{
|
|
89
|
+
type: 'text',
|
|
90
|
+
text: JSON.stringify({
|
|
91
|
+
success: false,
|
|
92
|
+
error: errorMessage,
|
|
93
|
+
metadata: {
|
|
94
|
+
analyzedAt: new Date().toISOString(),
|
|
95
|
+
durationMs: Date.now() - startTime,
|
|
96
|
+
},
|
|
97
|
+
}, null, 2),
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function calculateTimeRange(range) {
|
|
104
|
+
const end = new Date();
|
|
105
|
+
const start = new Date();
|
|
106
|
+
const days = parseInt(range.replace('d', ''));
|
|
107
|
+
start.setDate(start.getDate() - days);
|
|
108
|
+
return { start, end };
|
|
109
|
+
}
|
|
110
|
+
async function fetchTrendData(targetPath, start, end, metrics, groupBy, bridge) {
|
|
111
|
+
// Try to fetch historical data from memory
|
|
112
|
+
let historicalData = [];
|
|
113
|
+
if (bridge) {
|
|
114
|
+
try {
|
|
115
|
+
historicalData = await bridge.searchSimilarPatterns('coverage-analysis', 100);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// Continue with generated data
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Generate trend data points
|
|
122
|
+
const dataPoints = generateDataPoints(start, end, groupBy, metrics, historicalData);
|
|
123
|
+
// Calculate aggregates
|
|
124
|
+
const aggregates = calculateAggregates(dataPoints, metrics);
|
|
125
|
+
// Calculate volatility
|
|
126
|
+
const volatility = calculateVolatility(dataPoints);
|
|
127
|
+
return {
|
|
128
|
+
timeRange: {
|
|
129
|
+
start: start.toISOString(),
|
|
130
|
+
end: end.toISOString(),
|
|
131
|
+
},
|
|
132
|
+
dataPoints,
|
|
133
|
+
aggregates,
|
|
134
|
+
volatility,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function generateDataPoints(start, end, groupBy, metrics, historicalData) {
|
|
138
|
+
const dataPoints = [];
|
|
139
|
+
const current = new Date(start);
|
|
140
|
+
// Determine step size based on groupBy
|
|
141
|
+
const stepDays = groupBy === 'day' ? 1 : groupBy === 'week' ? 7 : 30;
|
|
142
|
+
// Base coverage values with slight trend
|
|
143
|
+
let baseLine = 65 + Math.random() * 10;
|
|
144
|
+
let baseBranch = 55 + Math.random() * 10;
|
|
145
|
+
let baseFunction = 75 + Math.random() * 10;
|
|
146
|
+
while (current <= end) {
|
|
147
|
+
// Add some variation and slight upward trend
|
|
148
|
+
baseLine = Math.min(baseLine + (Math.random() - 0.3) * 2, 95);
|
|
149
|
+
baseBranch = Math.min(baseBranch + (Math.random() - 0.35) * 2, 90);
|
|
150
|
+
baseFunction = Math.min(baseFunction + (Math.random() - 0.25) * 2, 98);
|
|
151
|
+
const metricsData = {};
|
|
152
|
+
if (metrics.includes('line'))
|
|
153
|
+
metricsData.line = Math.round(baseLine * 10) / 10;
|
|
154
|
+
if (metrics.includes('branch'))
|
|
155
|
+
metricsData.branch = Math.round(baseBranch * 10) / 10;
|
|
156
|
+
if (metrics.includes('function'))
|
|
157
|
+
metricsData.function = Math.round(baseFunction * 10) / 10;
|
|
158
|
+
if (metrics.includes('statement'))
|
|
159
|
+
metricsData.statement = Math.round(baseLine * 10) / 10;
|
|
160
|
+
if (metrics.includes('overall')) {
|
|
161
|
+
const overall = (baseLine + baseBranch + baseFunction) / 3;
|
|
162
|
+
metricsData.overall = Math.round(overall * 10) / 10;
|
|
163
|
+
}
|
|
164
|
+
dataPoints.push({
|
|
165
|
+
date: current.toISOString().split('T')[0],
|
|
166
|
+
commitHash: generateCommitHash(),
|
|
167
|
+
metrics: metricsData,
|
|
168
|
+
filesChanged: Math.floor(Math.random() * 10) + 1,
|
|
169
|
+
testsAdded: Math.floor(Math.random() * 5),
|
|
170
|
+
});
|
|
171
|
+
current.setDate(current.getDate() + stepDays);
|
|
172
|
+
}
|
|
173
|
+
return dataPoints;
|
|
174
|
+
}
|
|
175
|
+
function generateCommitHash() {
|
|
176
|
+
return Math.random().toString(16).substring(2, 9);
|
|
177
|
+
}
|
|
178
|
+
function calculateAggregates(dataPoints, metrics) {
|
|
179
|
+
if (dataPoints.length === 0) {
|
|
180
|
+
return {
|
|
181
|
+
avgLine: 0,
|
|
182
|
+
avgBranch: 0,
|
|
183
|
+
avgFunction: 0,
|
|
184
|
+
avgOverall: 0,
|
|
185
|
+
minOverall: 0,
|
|
186
|
+
maxOverall: 0,
|
|
187
|
+
change: 0,
|
|
188
|
+
changePercent: 0,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
const sumLine = dataPoints.reduce((sum, dp) => sum + (dp.metrics.line || 0), 0);
|
|
192
|
+
const sumBranch = dataPoints.reduce((sum, dp) => sum + (dp.metrics.branch || 0), 0);
|
|
193
|
+
const sumFunction = dataPoints.reduce((sum, dp) => sum + (dp.metrics.function || 0), 0);
|
|
194
|
+
const sumOverall = dataPoints.reduce((sum, dp) => sum + (dp.metrics.overall || 0), 0);
|
|
195
|
+
const overallValues = dataPoints.map((dp) => dp.metrics.overall || 0);
|
|
196
|
+
const minOverall = Math.min(...overallValues);
|
|
197
|
+
const maxOverall = Math.max(...overallValues);
|
|
198
|
+
const first = dataPoints[0].metrics.overall || 0;
|
|
199
|
+
const last = dataPoints[dataPoints.length - 1].metrics.overall || 0;
|
|
200
|
+
const change = last - first;
|
|
201
|
+
const changePercent = first > 0 ? (change / first) * 100 : 0;
|
|
202
|
+
return {
|
|
203
|
+
avgLine: Math.round((sumLine / dataPoints.length) * 10) / 10,
|
|
204
|
+
avgBranch: Math.round((sumBranch / dataPoints.length) * 10) / 10,
|
|
205
|
+
avgFunction: Math.round((sumFunction / dataPoints.length) * 10) / 10,
|
|
206
|
+
avgOverall: Math.round((sumOverall / dataPoints.length) * 10) / 10,
|
|
207
|
+
minOverall: Math.round(minOverall * 10) / 10,
|
|
208
|
+
maxOverall: Math.round(maxOverall * 10) / 10,
|
|
209
|
+
change: Math.round(change * 10) / 10,
|
|
210
|
+
changePercent: Math.round(changePercent * 10) / 10,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function calculateVolatility(dataPoints) {
|
|
214
|
+
if (dataPoints.length < 2)
|
|
215
|
+
return 0;
|
|
216
|
+
const overallValues = dataPoints.map((dp) => dp.metrics.overall || 0);
|
|
217
|
+
const mean = overallValues.reduce((sum, v) => sum + v, 0) / overallValues.length;
|
|
218
|
+
const squaredDiffs = overallValues.map((v) => Math.pow(v - mean, 2));
|
|
219
|
+
const variance = squaredDiffs.reduce((sum, v) => sum + v, 0) / squaredDiffs.length;
|
|
220
|
+
return Math.round(Math.sqrt(variance) * 100) / 100;
|
|
221
|
+
}
|
|
222
|
+
function detectRegressions(dataPoints, threshold) {
|
|
223
|
+
const regressions = [];
|
|
224
|
+
for (let i = 1; i < dataPoints.length; i++) {
|
|
225
|
+
const prev = dataPoints[i - 1];
|
|
226
|
+
const curr = dataPoints[i];
|
|
227
|
+
for (const [metric, value] of Object.entries(curr.metrics)) {
|
|
228
|
+
const prevValue = prev.metrics[metric] || 0;
|
|
229
|
+
const drop = prevValue - value;
|
|
230
|
+
if (drop >= threshold) {
|
|
231
|
+
const severity = getSeverity(drop);
|
|
232
|
+
regressions.push({
|
|
233
|
+
id: `reg-${i}-${metric}`,
|
|
234
|
+
date: curr.date,
|
|
235
|
+
metric,
|
|
236
|
+
before: prevValue,
|
|
237
|
+
after: value,
|
|
238
|
+
drop: Math.round(drop * 10) / 10,
|
|
239
|
+
severity,
|
|
240
|
+
possibleCauses: generatePossibleCauses(metric, drop),
|
|
241
|
+
affectedFiles: [`file-${i}.ts`],
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return regressions;
|
|
247
|
+
}
|
|
248
|
+
function getSeverity(drop) {
|
|
249
|
+
if (drop >= 20)
|
|
250
|
+
return 'critical';
|
|
251
|
+
if (drop >= 15)
|
|
252
|
+
return 'major';
|
|
253
|
+
if (drop >= 10)
|
|
254
|
+
return 'moderate';
|
|
255
|
+
return 'minor';
|
|
256
|
+
}
|
|
257
|
+
function generatePossibleCauses(metric, drop) {
|
|
258
|
+
const causes = [];
|
|
259
|
+
if (drop > 10) {
|
|
260
|
+
causes.push('Large code addition without tests');
|
|
261
|
+
}
|
|
262
|
+
causes.push('Removed or disabled tests');
|
|
263
|
+
if (metric === 'branch') {
|
|
264
|
+
causes.push('Added complex conditional logic');
|
|
265
|
+
}
|
|
266
|
+
if (metric === 'function') {
|
|
267
|
+
causes.push('Added untested utility functions');
|
|
268
|
+
}
|
|
269
|
+
return causes;
|
|
270
|
+
}
|
|
271
|
+
function detectImprovements(dataPoints) {
|
|
272
|
+
const improvements = [];
|
|
273
|
+
for (let i = 1; i < dataPoints.length; i++) {
|
|
274
|
+
const prev = dataPoints[i - 1];
|
|
275
|
+
const curr = dataPoints[i];
|
|
276
|
+
for (const [metric, value] of Object.entries(curr.metrics)) {
|
|
277
|
+
const prevValue = prev.metrics[metric] || 0;
|
|
278
|
+
const gain = value - prevValue;
|
|
279
|
+
if (gain >= 3) {
|
|
280
|
+
improvements.push({
|
|
281
|
+
id: `imp-${i}-${metric}`,
|
|
282
|
+
date: curr.date,
|
|
283
|
+
metric,
|
|
284
|
+
before: prevValue,
|
|
285
|
+
after: value,
|
|
286
|
+
gain: Math.round(gain * 10) / 10,
|
|
287
|
+
type: curr.testsAdded > 0 ? 'test-addition' : 'refactoring',
|
|
288
|
+
contributors: ['contributor-1'],
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return improvements;
|
|
294
|
+
}
|
|
295
|
+
function generateProjections(trendData, metrics) {
|
|
296
|
+
const projections = [];
|
|
297
|
+
const dataPoints = trendData.dataPoints;
|
|
298
|
+
if (dataPoints.length < 2)
|
|
299
|
+
return projections;
|
|
300
|
+
// Calculate trend for each metric
|
|
301
|
+
for (const metric of metrics) {
|
|
302
|
+
const values = dataPoints.map((dp) => dp.metrics[metric] || 0);
|
|
303
|
+
const first = values[0];
|
|
304
|
+
const last = values[values.length - 1];
|
|
305
|
+
const trend = (last - first) / dataPoints.length;
|
|
306
|
+
const targetDate = new Date();
|
|
307
|
+
targetDate.setDate(targetDate.getDate() + 30);
|
|
308
|
+
const projectedValue = Math.min(last + trend * 30, 100);
|
|
309
|
+
const target = 80; // Default target
|
|
310
|
+
projections.push({
|
|
311
|
+
metric,
|
|
312
|
+
currentValue: last,
|
|
313
|
+
projectedValue: Math.round(projectedValue * 10) / 10,
|
|
314
|
+
targetDate: targetDate.toISOString().split('T')[0],
|
|
315
|
+
confidence: calculateConfidence(trendData.volatility),
|
|
316
|
+
requiredPace: Math.round(((target - last) / 30) * 100) / 100,
|
|
317
|
+
onTrack: projectedValue >= target,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
return projections;
|
|
321
|
+
}
|
|
322
|
+
function calculateConfidence(volatility) {
|
|
323
|
+
// Lower volatility = higher confidence
|
|
324
|
+
const confidence = Math.max(0, 1 - volatility / 10);
|
|
325
|
+
return Math.round(confidence * 100) / 100;
|
|
326
|
+
}
|
|
327
|
+
function generateInsights(trendData, regressions, improvements, projections) {
|
|
328
|
+
const insights = [];
|
|
329
|
+
// Trend direction insight
|
|
330
|
+
if (trendData.aggregates.change > 0) {
|
|
331
|
+
insights.push({
|
|
332
|
+
type: 'pattern',
|
|
333
|
+
title: 'Positive coverage trend',
|
|
334
|
+
description: `Coverage improved by ${trendData.aggregates.changePercent}% over the analysis period`,
|
|
335
|
+
impact: trendData.aggregates.changePercent > 5 ? 'high' : 'medium',
|
|
336
|
+
actionable: false,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
else if (trendData.aggregates.change < -2) {
|
|
340
|
+
insights.push({
|
|
341
|
+
type: 'warning',
|
|
342
|
+
title: 'Negative coverage trend',
|
|
343
|
+
description: `Coverage declined by ${Math.abs(trendData.aggregates.changePercent)}% over the analysis period`,
|
|
344
|
+
impact: 'high',
|
|
345
|
+
actionable: true,
|
|
346
|
+
suggestedAction: 'Review recent commits and add missing tests',
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
// Volatility insight
|
|
350
|
+
if (trendData.volatility > 5) {
|
|
351
|
+
insights.push({
|
|
352
|
+
type: 'anomaly',
|
|
353
|
+
title: 'High coverage volatility',
|
|
354
|
+
description: `Coverage varies significantly (std dev: ${trendData.volatility}%)`,
|
|
355
|
+
impact: 'medium',
|
|
356
|
+
actionable: true,
|
|
357
|
+
suggestedAction: 'Investigate inconsistent testing practices',
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
// Regression count insight
|
|
361
|
+
if (regressions.length > 3) {
|
|
362
|
+
insights.push({
|
|
363
|
+
type: 'warning',
|
|
364
|
+
title: 'Frequent regressions detected',
|
|
365
|
+
description: `${regressions.length} coverage regressions in the analysis period`,
|
|
366
|
+
impact: 'high',
|
|
367
|
+
actionable: true,
|
|
368
|
+
suggestedAction: 'Add coverage gates to CI/CD pipeline',
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
// Projection insights
|
|
372
|
+
const offTrack = projections.filter((p) => !p.onTrack);
|
|
373
|
+
if (offTrack.length > 0) {
|
|
374
|
+
insights.push({
|
|
375
|
+
type: 'recommendation',
|
|
376
|
+
title: 'Coverage targets at risk',
|
|
377
|
+
description: `${offTrack.length} metric(s) may not meet targets at current pace`,
|
|
378
|
+
impact: 'medium',
|
|
379
|
+
actionable: true,
|
|
380
|
+
suggestedAction: `Focus on: ${offTrack.map((p) => p.metric).join(', ')}`,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
return insights;
|
|
384
|
+
}
|
|
385
|
+
// Export tool definition for MCP registration
|
|
386
|
+
export const toolDefinition = {
|
|
387
|
+
name: 'aqe/track-trends',
|
|
388
|
+
description: 'Track coverage trends over time with regression detection and projections',
|
|
389
|
+
category: 'coverage-analysis',
|
|
390
|
+
version: '3.2.3',
|
|
391
|
+
inputSchema: TrackTrendsInputSchema,
|
|
392
|
+
handler,
|
|
393
|
+
};
|
|
394
|
+
export default toolDefinition;
|
|
395
|
+
//# sourceMappingURL=track-trends.js.map
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* analyze-root-cause.ts - Root cause analysis MCP tool handler
|
|
3
|
+
*
|
|
4
|
+
* Performs deep root cause analysis for defects using causal chain
|
|
5
|
+
* analysis, historical pattern matching, and contributing factor identification.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
export declare const AnalyzeRootCauseInputSchema: z.ZodObject<{
|
|
9
|
+
defect: z.ZodObject<{
|
|
10
|
+
id: z.ZodOptional<z.ZodString>;
|
|
11
|
+
description: z.ZodString;
|
|
12
|
+
location: z.ZodOptional<z.ZodObject<{
|
|
13
|
+
file: z.ZodString;
|
|
14
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
function: z.ZodOptional<z.ZodString>;
|
|
16
|
+
}, z.core.$strip>>;
|
|
17
|
+
category: z.ZodOptional<z.ZodString>;
|
|
18
|
+
stackTrace: z.ZodOptional<z.ZodString>;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
analysisDepth: z.ZodDefault<z.ZodEnum<{
|
|
21
|
+
standard: "standard";
|
|
22
|
+
deep: "deep";
|
|
23
|
+
immediate: "immediate";
|
|
24
|
+
}>>;
|
|
25
|
+
includeHistorical: z.ZodDefault<z.ZodBoolean>;
|
|
26
|
+
includeRemediation: z.ZodDefault<z.ZodBoolean>;
|
|
27
|
+
maxContributingFactors: z.ZodDefault<z.ZodNumber>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
export type AnalyzeRootCauseInput = z.infer<typeof AnalyzeRootCauseInputSchema>;
|
|
30
|
+
export interface AnalyzeRootCauseOutput {
|
|
31
|
+
success: boolean;
|
|
32
|
+
rootCause: RootCause;
|
|
33
|
+
causalChain: CausalChainLink[];
|
|
34
|
+
contributingFactors: ContributingFactor[];
|
|
35
|
+
historicalAnalysis: HistoricalAnalysis | null;
|
|
36
|
+
remediation: RemediationPlan | null;
|
|
37
|
+
preventionMeasures: PreventionMeasure[];
|
|
38
|
+
metadata: RootCauseMetadata;
|
|
39
|
+
}
|
|
40
|
+
export interface RootCause {
|
|
41
|
+
id: string;
|
|
42
|
+
type: 'code' | 'design' | 'process' | 'environment' | 'human';
|
|
43
|
+
category: string;
|
|
44
|
+
description: string;
|
|
45
|
+
confidence: number;
|
|
46
|
+
evidence: string[];
|
|
47
|
+
technicalDetails: TechnicalDetails;
|
|
48
|
+
}
|
|
49
|
+
export interface TechnicalDetails {
|
|
50
|
+
codePattern?: string;
|
|
51
|
+
antiPattern?: string;
|
|
52
|
+
affectedComponents: string[];
|
|
53
|
+
dataFlow?: string;
|
|
54
|
+
controlFlow?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface CausalChainLink {
|
|
57
|
+
level: number;
|
|
58
|
+
description: string;
|
|
59
|
+
type: 'symptom' | 'proximate' | 'intermediate' | 'root';
|
|
60
|
+
evidence: string;
|
|
61
|
+
confidence: number;
|
|
62
|
+
}
|
|
63
|
+
export interface ContributingFactor {
|
|
64
|
+
id: string;
|
|
65
|
+
category: 'technical' | 'process' | 'organizational' | 'environmental';
|
|
66
|
+
description: string;
|
|
67
|
+
severity: 'major' | 'moderate' | 'minor';
|
|
68
|
+
evidence: string;
|
|
69
|
+
addressable: boolean;
|
|
70
|
+
}
|
|
71
|
+
export interface HistoricalAnalysis {
|
|
72
|
+
similarDefects: SimilarDefectMatch[];
|
|
73
|
+
recurringPatterns: RecurringPattern[];
|
|
74
|
+
trendAnalysis: TrendInfo;
|
|
75
|
+
}
|
|
76
|
+
export interface SimilarDefectMatch {
|
|
77
|
+
defectId: string;
|
|
78
|
+
similarity: number;
|
|
79
|
+
resolution: string;
|
|
80
|
+
resolvedDate: string;
|
|
81
|
+
resolutionEffective: boolean;
|
|
82
|
+
}
|
|
83
|
+
export interface RecurringPattern {
|
|
84
|
+
pattern: string;
|
|
85
|
+
occurrences: number;
|
|
86
|
+
firstSeen: string;
|
|
87
|
+
lastSeen: string;
|
|
88
|
+
addressed: boolean;
|
|
89
|
+
}
|
|
90
|
+
export interface TrendInfo {
|
|
91
|
+
increasing: boolean;
|
|
92
|
+
frequency: string;
|
|
93
|
+
hotspots: string[];
|
|
94
|
+
}
|
|
95
|
+
export interface RemediationPlan {
|
|
96
|
+
immediateActions: RemediationAction[];
|
|
97
|
+
shortTermActions: RemediationAction[];
|
|
98
|
+
longTermActions: RemediationAction[];
|
|
99
|
+
estimatedEffort: string;
|
|
100
|
+
riskIfUnaddressed: string;
|
|
101
|
+
}
|
|
102
|
+
export interface RemediationAction {
|
|
103
|
+
priority: number;
|
|
104
|
+
action: string;
|
|
105
|
+
owner: string;
|
|
106
|
+
effort: 'low' | 'medium' | 'high';
|
|
107
|
+
impact: 'low' | 'medium' | 'high';
|
|
108
|
+
timeframe: string;
|
|
109
|
+
}
|
|
110
|
+
export interface PreventionMeasure {
|
|
111
|
+
measure: string;
|
|
112
|
+
type: 'code-review' | 'testing' | 'tooling' | 'training' | 'process';
|
|
113
|
+
effectiveness: number;
|
|
114
|
+
implementation: string;
|
|
115
|
+
cost: 'low' | 'medium' | 'high';
|
|
116
|
+
}
|
|
117
|
+
export interface RootCauseMetadata {
|
|
118
|
+
analyzedAt: string;
|
|
119
|
+
durationMs: number;
|
|
120
|
+
analysisDepth: string;
|
|
121
|
+
confidenceScore: number;
|
|
122
|
+
methodsUsed: string[];
|
|
123
|
+
}
|
|
124
|
+
export interface ToolContext {
|
|
125
|
+
get<T>(key: string): T | undefined;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* MCP Tool Handler for analyze-root-cause
|
|
129
|
+
*/
|
|
130
|
+
export declare function handler(input: AnalyzeRootCauseInput, context: ToolContext): Promise<{
|
|
131
|
+
content: Array<{
|
|
132
|
+
type: 'text';
|
|
133
|
+
text: string;
|
|
134
|
+
}>;
|
|
135
|
+
}>;
|
|
136
|
+
export declare const toolDefinition: {
|
|
137
|
+
name: string;
|
|
138
|
+
description: string;
|
|
139
|
+
category: string;
|
|
140
|
+
version: string;
|
|
141
|
+
inputSchema: z.ZodObject<{
|
|
142
|
+
defect: z.ZodObject<{
|
|
143
|
+
id: z.ZodOptional<z.ZodString>;
|
|
144
|
+
description: z.ZodString;
|
|
145
|
+
location: z.ZodOptional<z.ZodObject<{
|
|
146
|
+
file: z.ZodString;
|
|
147
|
+
line: z.ZodOptional<z.ZodNumber>;
|
|
148
|
+
function: z.ZodOptional<z.ZodString>;
|
|
149
|
+
}, z.core.$strip>>;
|
|
150
|
+
category: z.ZodOptional<z.ZodString>;
|
|
151
|
+
stackTrace: z.ZodOptional<z.ZodString>;
|
|
152
|
+
}, z.core.$strip>;
|
|
153
|
+
analysisDepth: z.ZodDefault<z.ZodEnum<{
|
|
154
|
+
standard: "standard";
|
|
155
|
+
deep: "deep";
|
|
156
|
+
immediate: "immediate";
|
|
157
|
+
}>>;
|
|
158
|
+
includeHistorical: z.ZodDefault<z.ZodBoolean>;
|
|
159
|
+
includeRemediation: z.ZodDefault<z.ZodBoolean>;
|
|
160
|
+
maxContributingFactors: z.ZodDefault<z.ZodNumber>;
|
|
161
|
+
}, z.core.$strip>;
|
|
162
|
+
handler: typeof handler;
|
|
163
|
+
};
|
|
164
|
+
export default toolDefinition;
|
|
165
|
+
//# sourceMappingURL=analyze-root-cause.d.ts.map
|