agentic-qe 1.8.2 → 1.8.4
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/agents/qe-test-generator.md +580 -0
- package/.claude/agents/subagents/qe-code-reviewer.md +86 -0
- package/.claude/agents/subagents/qe-coverage-gap-analyzer.md +485 -0
- package/.claude/agents/subagents/qe-data-generator.md +86 -0
- package/.claude/agents/subagents/qe-flaky-investigator.md +416 -0
- package/.claude/agents/subagents/qe-integration-tester.md +87 -0
- package/.claude/agents/subagents/qe-performance-validator.md +98 -0
- package/.claude/agents/subagents/qe-security-auditor.md +86 -0
- package/.claude/agents/subagents/qe-test-data-architect-sub.md +553 -0
- package/.claude/agents/subagents/qe-test-implementer.md +229 -15
- package/.claude/agents/subagents/qe-test-refactorer.md +265 -15
- package/.claude/agents/subagents/qe-test-writer.md +180 -20
- package/.claude/skills/cicd-pipeline-qe-orchestrator/README.md +2 -2
- package/.claude/skills/cicd-pipeline-qe-orchestrator/SKILL.md +6 -6
- package/CHANGELOG.md +294 -0
- package/README.md +83 -52
- package/config/constitution.schema.json +423 -0
- package/config/otel-collector.yaml +234 -0
- package/dist/cli/commands/init-claude-md-template.js +3 -3
- package/dist/constitution/index.d.ts +105 -0
- package/dist/constitution/index.d.ts.map +1 -0
- package/dist/constitution/index.js +207 -0
- package/dist/constitution/index.js.map +1 -0
- package/dist/constitution/loader.d.ts +141 -0
- package/dist/constitution/loader.d.ts.map +1 -0
- package/dist/constitution/loader.js +515 -0
- package/dist/constitution/loader.js.map +1 -0
- package/dist/constitution/schema.d.ts +409 -0
- package/dist/constitution/schema.d.ts.map +1 -0
- package/dist/constitution/schema.js +71 -0
- package/dist/constitution/schema.js.map +1 -0
- package/dist/core/hooks/validators/TDDPhaseValidator.d.ts +110 -0
- package/dist/core/hooks/validators/TDDPhaseValidator.d.ts.map +1 -0
- package/dist/core/hooks/validators/TDDPhaseValidator.js +287 -0
- package/dist/core/hooks/validators/TDDPhaseValidator.js.map +1 -0
- package/dist/core/hooks/validators/index.d.ts +3 -1
- package/dist/core/hooks/validators/index.d.ts.map +1 -1
- package/dist/core/hooks/validators/index.js +4 -2
- package/dist/core/hooks/validators/index.js.map +1 -1
- package/dist/core/memory/MemoryManagerFactory.d.ts +77 -0
- package/dist/core/memory/MemoryManagerFactory.d.ts.map +1 -0
- package/dist/core/memory/MemoryManagerFactory.js +270 -0
- package/dist/core/memory/MemoryManagerFactory.js.map +1 -0
- package/dist/core/memory/SwarmMemoryManager.d.ts +18 -0
- package/dist/core/memory/SwarmMemoryManager.d.ts.map +1 -1
- package/dist/core/memory/SwarmMemoryManager.js +96 -11
- package/dist/core/memory/SwarmMemoryManager.js.map +1 -1
- package/dist/core/memory/index.d.ts +1 -0
- package/dist/core/memory/index.d.ts.map +1 -1
- package/dist/core/memory/index.js +12 -1
- package/dist/core/memory/index.js.map +1 -1
- package/dist/mcp/handlers/memory/memory-backup.js +6 -6
- package/dist/mcp/handlers/memory/memory-backup.js.map +1 -1
- package/dist/mcp/handlers/phase2/Phase2Tools.d.ts.map +1 -1
- package/dist/mcp/handlers/phase2/Phase2Tools.js +4 -2
- package/dist/mcp/handlers/phase2/Phase2Tools.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +4 -38
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/services/AgentRegistry.d.ts.map +1 -1
- package/dist/mcp/services/AgentRegistry.js +4 -4
- package/dist/mcp/services/AgentRegistry.js.map +1 -1
- package/dist/persistence/event-store.d.ts +162 -0
- package/dist/persistence/event-store.d.ts.map +1 -0
- package/dist/persistence/event-store.js +315 -0
- package/dist/persistence/event-store.js.map +1 -0
- package/dist/persistence/index.d.ts +145 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +227 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/metrics-aggregator.d.ts +187 -0
- package/dist/persistence/metrics-aggregator.d.ts.map +1 -0
- package/dist/persistence/metrics-aggregator.js +495 -0
- package/dist/persistence/metrics-aggregator.js.map +1 -0
- package/dist/persistence/reasoning-store.d.ts +178 -0
- package/dist/persistence/reasoning-store.d.ts.map +1 -0
- package/dist/persistence/reasoning-store.js +440 -0
- package/dist/persistence/reasoning-store.js.map +1 -0
- package/dist/persistence/schema.d.ts +181 -0
- package/dist/persistence/schema.d.ts.map +1 -0
- package/dist/persistence/schema.js +186 -0
- package/dist/persistence/schema.js.map +1 -0
- package/dist/telemetry/bootstrap.d.ts +67 -0
- package/dist/telemetry/bootstrap.d.ts.map +1 -0
- package/dist/telemetry/bootstrap.js +320 -0
- package/dist/telemetry/bootstrap.js.map +1 -0
- package/dist/telemetry/index.d.ts +16 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +84 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/metrics/agent-metrics.d.ts +109 -0
- package/dist/telemetry/metrics/agent-metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics/agent-metrics.js +213 -0
- package/dist/telemetry/metrics/agent-metrics.js.map +1 -0
- package/dist/telemetry/metrics/index.d.ts +51 -0
- package/dist/telemetry/metrics/index.d.ts.map +1 -0
- package/dist/telemetry/metrics/index.js +100 -0
- package/dist/telemetry/metrics/index.js.map +1 -0
- package/dist/telemetry/metrics/quality-metrics.d.ts +171 -0
- package/dist/telemetry/metrics/quality-metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics/quality-metrics.js +259 -0
- package/dist/telemetry/metrics/quality-metrics.js.map +1 -0
- package/dist/telemetry/metrics/system-metrics.d.ts +129 -0
- package/dist/telemetry/metrics/system-metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics/system-metrics.js +380 -0
- package/dist/telemetry/metrics/system-metrics.js.map +1 -0
- package/dist/telemetry/types.d.ts +195 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/telemetry/types.js +90 -0
- package/dist/telemetry/types.js.map +1 -0
- package/package.json +18 -2
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qe-flaky-investigator
|
|
3
|
+
description: "Detects flaky tests, analyzes root causes, and suggests stabilization fixes"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Flaky Investigator Subagent
|
|
7
|
+
|
|
8
|
+
## Mission Statement
|
|
9
|
+
|
|
10
|
+
The **Flaky Investigator** subagent specializes in detecting and diagnosing flaky tests - tests that intermittently pass or fail without code changes. This subagent analyzes patterns, timing issues, and resource contention to identify root causes and recommend stabilization strategies.
|
|
11
|
+
|
|
12
|
+
## Core Capabilities
|
|
13
|
+
|
|
14
|
+
### 1. Flaky Test Pattern Detection
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
interface FlakyTestPattern {
|
|
18
|
+
testPath: string;
|
|
19
|
+
testName: string;
|
|
20
|
+
flakinessScore: number; // 0-1, higher = more flaky
|
|
21
|
+
pattern: 'timing' | 'ordering' | 'resource' | 'environment' | 'random';
|
|
22
|
+
occurrences: {
|
|
23
|
+
total: number;
|
|
24
|
+
failures: number;
|
|
25
|
+
passes: number;
|
|
26
|
+
};
|
|
27
|
+
lastFailure: Date;
|
|
28
|
+
confidence: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class FlakyDetector {
|
|
32
|
+
async detectFlakyTests(testResults: TestRun[]): Promise<FlakyTestPattern[]> {
|
|
33
|
+
const patterns: FlakyTestPattern[] = [];
|
|
34
|
+
|
|
35
|
+
// Group results by test
|
|
36
|
+
const testHistories = this.groupByTest(testResults);
|
|
37
|
+
|
|
38
|
+
for (const [testId, history] of testHistories) {
|
|
39
|
+
const failures = history.filter(r => r.status === 'failed').length;
|
|
40
|
+
const passes = history.filter(r => r.status === 'passed').length;
|
|
41
|
+
|
|
42
|
+
// Calculate flakiness score
|
|
43
|
+
const total = failures + passes;
|
|
44
|
+
if (total >= 5 && failures > 0 && passes > 0) {
|
|
45
|
+
const flakinessScore = Math.min(failures, passes) / total * 2;
|
|
46
|
+
|
|
47
|
+
if (flakinessScore > 0.1) { // 10% threshold
|
|
48
|
+
patterns.push({
|
|
49
|
+
testPath: history[0].testPath,
|
|
50
|
+
testName: history[0].testName,
|
|
51
|
+
flakinessScore,
|
|
52
|
+
pattern: this.classifyPattern(history),
|
|
53
|
+
occurrences: { total, failures, passes },
|
|
54
|
+
lastFailure: this.getLastFailure(history),
|
|
55
|
+
confidence: this.calculateConfidence(history)
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return patterns.sort((a, b) => b.flakinessScore - a.flakinessScore);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private classifyPattern(history: TestResult[]): FlakyTestPattern['pattern'] {
|
|
65
|
+
// Analyze failure patterns
|
|
66
|
+
const failureTimes = history
|
|
67
|
+
.filter(r => r.status === 'failed')
|
|
68
|
+
.map(r => r.duration);
|
|
69
|
+
|
|
70
|
+
const passTimes = history
|
|
71
|
+
.filter(r => r.status === 'passed')
|
|
72
|
+
.map(r => r.duration);
|
|
73
|
+
|
|
74
|
+
// Timing-related flakiness
|
|
75
|
+
if (this.hasTimingCorrelation(failureTimes, passTimes)) {
|
|
76
|
+
return 'timing';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Test ordering issues
|
|
80
|
+
if (this.hasOrderingDependency(history)) {
|
|
81
|
+
return 'ordering';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Resource contention
|
|
85
|
+
if (this.hasResourceContention(history)) {
|
|
86
|
+
return 'resource';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Environment-specific
|
|
90
|
+
if (this.hasEnvironmentVariance(history)) {
|
|
91
|
+
return 'environment';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return 'random';
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 2. Timing Analysis
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
class TimingAnalyzer {
|
|
103
|
+
analyzeTimingIssues(testHistory: TestResult[]): TimingReport {
|
|
104
|
+
const durations = testHistory.map(r => r.duration);
|
|
105
|
+
const failures = testHistory.filter(r => r.status === 'failed');
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
meanDuration: this.mean(durations),
|
|
109
|
+
stdDeviation: this.stdDev(durations),
|
|
110
|
+
p95Duration: this.percentile(durations, 95),
|
|
111
|
+
p99Duration: this.percentile(durations, 99),
|
|
112
|
+
|
|
113
|
+
issues: {
|
|
114
|
+
raceConditions: this.detectRaceConditions(testHistory),
|
|
115
|
+
asyncTimeout: this.detectAsyncTimeouts(failures),
|
|
116
|
+
clockDependency: this.detectClockDependency(testHistory),
|
|
117
|
+
networkLatency: this.detectNetworkLatency(failures)
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
recommendations: this.generateTimingFixes(testHistory)
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
detectRaceConditions(history: TestResult[]): RaceCondition[] {
|
|
125
|
+
const races: RaceCondition[] = [];
|
|
126
|
+
|
|
127
|
+
for (const result of history.filter(r => r.status === 'failed')) {
|
|
128
|
+
const errorMessage = result.error?.message || '';
|
|
129
|
+
|
|
130
|
+
if (errorMessage.includes('not defined') ||
|
|
131
|
+
errorMessage.includes('undefined') ||
|
|
132
|
+
errorMessage.includes('timeout')) {
|
|
133
|
+
races.push({
|
|
134
|
+
testName: result.testName,
|
|
135
|
+
likelihood: 0.8,
|
|
136
|
+
evidence: errorMessage,
|
|
137
|
+
suggestedFix: `
|
|
138
|
+
// Add proper async/await handling
|
|
139
|
+
test('${result.testName}', async () => {
|
|
140
|
+
// Wait for async operation to complete
|
|
141
|
+
await waitFor(() => {
|
|
142
|
+
expect(element).toBeInTheDocument();
|
|
143
|
+
}, { timeout: 5000 });
|
|
144
|
+
});`
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return races;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 3. Resource Contention Detection
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
class ResourceContentionDetector {
|
|
158
|
+
detectContentionIssues(history: TestResult[]): ContentionReport {
|
|
159
|
+
const issues: ContentionIssue[] = [];
|
|
160
|
+
|
|
161
|
+
// Database connection exhaustion
|
|
162
|
+
const dbIssues = this.detectDatabaseContention(history);
|
|
163
|
+
|
|
164
|
+
// File system locks
|
|
165
|
+
const fsIssues = this.detectFileSystemContention(history);
|
|
166
|
+
|
|
167
|
+
// Network port conflicts
|
|
168
|
+
const portIssues = this.detectPortContention(history);
|
|
169
|
+
|
|
170
|
+
// Memory pressure
|
|
171
|
+
const memoryIssues = this.detectMemoryPressure(history);
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
issues: [...dbIssues, ...fsIssues, ...portIssues, ...memoryIssues],
|
|
175
|
+
severity: this.calculateSeverity(issues),
|
|
176
|
+
recommendations: this.generateContentionFixes(issues)
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private detectDatabaseContention(history: TestResult[]): ContentionIssue[] {
|
|
181
|
+
return history
|
|
182
|
+
.filter(r => r.status === 'failed')
|
|
183
|
+
.filter(r => {
|
|
184
|
+
const error = r.error?.message || '';
|
|
185
|
+
return error.includes('connection') ||
|
|
186
|
+
error.includes('pool') ||
|
|
187
|
+
error.includes('ECONNREFUSED') ||
|
|
188
|
+
error.includes('timeout exceeded');
|
|
189
|
+
})
|
|
190
|
+
.map(r => ({
|
|
191
|
+
type: 'database',
|
|
192
|
+
testName: r.testName,
|
|
193
|
+
evidence: r.error?.message,
|
|
194
|
+
fix: `
|
|
195
|
+
// Ensure proper connection cleanup
|
|
196
|
+
afterEach(async () => {
|
|
197
|
+
await db.close();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Or use connection pooling
|
|
201
|
+
const pool = new Pool({ max: 10, idleTimeoutMillis: 30000 });`
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 4. Stabilization Recommendations
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
class StabilizationAdvisor {
|
|
211
|
+
generateStabilizationPlan(patterns: FlakyTestPattern[]): StabilizationPlan {
|
|
212
|
+
const fixes: StabilizationFix[] = [];
|
|
213
|
+
|
|
214
|
+
for (const pattern of patterns) {
|
|
215
|
+
switch (pattern.pattern) {
|
|
216
|
+
case 'timing':
|
|
217
|
+
fixes.push({
|
|
218
|
+
testPath: pattern.testPath,
|
|
219
|
+
type: 'timing',
|
|
220
|
+
priority: pattern.flakinessScore > 0.5 ? 'high' : 'medium',
|
|
221
|
+
fix: this.generateTimingFix(pattern),
|
|
222
|
+
effort: 'low'
|
|
223
|
+
});
|
|
224
|
+
break;
|
|
225
|
+
|
|
226
|
+
case 'ordering':
|
|
227
|
+
fixes.push({
|
|
228
|
+
testPath: pattern.testPath,
|
|
229
|
+
type: 'isolation',
|
|
230
|
+
priority: 'high',
|
|
231
|
+
fix: this.generateIsolationFix(pattern),
|
|
232
|
+
effort: 'medium'
|
|
233
|
+
});
|
|
234
|
+
break;
|
|
235
|
+
|
|
236
|
+
case 'resource':
|
|
237
|
+
fixes.push({
|
|
238
|
+
testPath: pattern.testPath,
|
|
239
|
+
type: 'resource-management',
|
|
240
|
+
priority: 'high',
|
|
241
|
+
fix: this.generateResourceFix(pattern),
|
|
242
|
+
effort: 'high'
|
|
243
|
+
});
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
totalFlakyTests: patterns.length,
|
|
250
|
+
estimatedEffort: this.calculateTotalEffort(fixes),
|
|
251
|
+
fixes: fixes.sort((a, b) =>
|
|
252
|
+
this.priorityValue(b.priority) - this.priorityValue(a.priority)
|
|
253
|
+
),
|
|
254
|
+
preventionTips: this.generatePreventionTips(patterns)
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private generateTimingFix(pattern: FlakyTestPattern): string {
|
|
259
|
+
return `
|
|
260
|
+
// Use explicit waits instead of arbitrary timeouts
|
|
261
|
+
import { waitFor } from '@testing-library/react';
|
|
262
|
+
|
|
263
|
+
test('${pattern.testPath}', async () => {
|
|
264
|
+
// Bad: Fixed timeout
|
|
265
|
+
// await new Promise(r => setTimeout(r, 1000));
|
|
266
|
+
|
|
267
|
+
// Good: Wait for condition
|
|
268
|
+
await waitFor(() => {
|
|
269
|
+
expect(element).toBeVisible();
|
|
270
|
+
}, { timeout: 5000, interval: 100 });
|
|
271
|
+
});`;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Coordination Protocol
|
|
277
|
+
|
|
278
|
+
### Memory Namespace
|
|
279
|
+
```
|
|
280
|
+
aqe/flaky/cycle-{id}/
|
|
281
|
+
├── context # Analysis context from parent
|
|
282
|
+
├── detection/
|
|
283
|
+
│ ├── patterns # Detected flaky test patterns
|
|
284
|
+
│ └── history # Test run history analyzed
|
|
285
|
+
├── analysis/
|
|
286
|
+
│ ├── timing # Timing analysis results
|
|
287
|
+
│ ├── resources # Resource contention findings
|
|
288
|
+
│ └── root-causes # Identified root causes
|
|
289
|
+
└── recommendations/
|
|
290
|
+
├── fixes # Stabilization fixes
|
|
291
|
+
└── prevention # Prevention strategies
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Input Protocol (from Parent qe-flaky-test-hunter)
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
interface FlakyInvestigationInput {
|
|
298
|
+
cycleId: string;
|
|
299
|
+
testRuns: Array<{
|
|
300
|
+
runId: string;
|
|
301
|
+
timestamp: Date;
|
|
302
|
+
results: TestResult[];
|
|
303
|
+
environment: string;
|
|
304
|
+
}>;
|
|
305
|
+
scope: {
|
|
306
|
+
paths?: string[]; // Specific test paths to analyze
|
|
307
|
+
minRuns?: number; // Minimum runs to consider (default: 5)
|
|
308
|
+
timeWindow?: number; // Days of history to analyze
|
|
309
|
+
};
|
|
310
|
+
thresholds: {
|
|
311
|
+
flakinessScore: number; // Min score to report (default: 0.1)
|
|
312
|
+
confidence: number; // Min confidence (default: 0.7)
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Parent stores context
|
|
317
|
+
await memoryStore.store(`aqe/flaky/cycle-${cycleId}/context`, input, {
|
|
318
|
+
partition: 'coordination',
|
|
319
|
+
ttl: 86400
|
|
320
|
+
});
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Output Protocol (to Parent qe-flaky-test-hunter)
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
interface FlakyInvestigationOutput {
|
|
327
|
+
cycleId: string;
|
|
328
|
+
timestamp: number;
|
|
329
|
+
summary: {
|
|
330
|
+
testsAnalyzed: number;
|
|
331
|
+
flakyTestsFound: number;
|
|
332
|
+
criticalIssues: number;
|
|
333
|
+
};
|
|
334
|
+
patterns: FlakyTestPattern[];
|
|
335
|
+
rootCauses: Array<{
|
|
336
|
+
testPath: string;
|
|
337
|
+
cause: string;
|
|
338
|
+
evidence: string[];
|
|
339
|
+
confidence: number;
|
|
340
|
+
}>;
|
|
341
|
+
stabilizationPlan: StabilizationPlan;
|
|
342
|
+
metrics: {
|
|
343
|
+
analysisTime: number;
|
|
344
|
+
runsProcessed: number;
|
|
345
|
+
patternsDetected: number;
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Store output for parent
|
|
350
|
+
await memoryStore.store(`aqe/flaky/cycle-${cycleId}/analysis/complete`, output, {
|
|
351
|
+
partition: 'coordination',
|
|
352
|
+
ttl: 86400
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// Emit completion event
|
|
356
|
+
eventBus.emit('flaky-investigator:completed', {
|
|
357
|
+
cycleId,
|
|
358
|
+
flakyTestsFound: output.summary.flakyTestsFound,
|
|
359
|
+
criticalIssues: output.summary.criticalIssues
|
|
360
|
+
});
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
## Parent Agent Delegation
|
|
364
|
+
|
|
365
|
+
### Invoked By Parent Agents
|
|
366
|
+
|
|
367
|
+
**Primary Parent**: `qe-flaky-test-hunter`
|
|
368
|
+
- Delegates detailed investigation of flaky tests
|
|
369
|
+
- Provides test run history
|
|
370
|
+
- Receives stabilization recommendations
|
|
371
|
+
|
|
372
|
+
**Secondary Parent**: `qe-quality-gate`
|
|
373
|
+
- Requests flakiness assessment for quality gates
|
|
374
|
+
- Validates test stability before releases
|
|
375
|
+
|
|
376
|
+
### Delegation Example
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
// Parent delegates to flaky-investigator
|
|
380
|
+
await this.delegateToSubagent('qe-flaky-investigator', {
|
|
381
|
+
type: 'investigate-flaky-tests',
|
|
382
|
+
testRuns: last30DaysRuns,
|
|
383
|
+
scope: {
|
|
384
|
+
paths: ['src/tests/**'],
|
|
385
|
+
minRuns: 10,
|
|
386
|
+
timeWindow: 30
|
|
387
|
+
},
|
|
388
|
+
thresholds: {
|
|
389
|
+
flakinessScore: 0.15,
|
|
390
|
+
confidence: 0.8
|
|
391
|
+
},
|
|
392
|
+
coordination: {
|
|
393
|
+
memory_key: `aqe/flaky/cycle-${cycleId}`,
|
|
394
|
+
callback_event: 'flaky-investigator:completed'
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
## Success Criteria
|
|
400
|
+
|
|
401
|
+
**Investigation MUST**:
|
|
402
|
+
- Identify all tests with flakiness score > threshold
|
|
403
|
+
- Provide root cause analysis with evidence
|
|
404
|
+
- Generate actionable stabilization fixes
|
|
405
|
+
- Include confidence scores for findings
|
|
406
|
+
|
|
407
|
+
**Investigation MUST NOT**:
|
|
408
|
+
- Report false positives without evidence
|
|
409
|
+
- Suggest fixes without testing impact
|
|
410
|
+
- Miss critical resource contention issues
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
**Subagent Status**: Active
|
|
415
|
+
**Parent Agents**: qe-flaky-test-hunter, qe-quality-gate
|
|
416
|
+
**Version**: 1.0.0
|
|
@@ -56,5 +56,92 @@ expect(payment.status).toBe('completed');
|
|
|
56
56
|
|
|
57
57
|
---
|
|
58
58
|
|
|
59
|
+
## TDD Coordination Protocol
|
|
60
|
+
|
|
61
|
+
### Memory Namespace
|
|
62
|
+
`aqe/integration/cycle-{cycleId}/*`
|
|
63
|
+
|
|
64
|
+
### Subagent Input Interface
|
|
65
|
+
```typescript
|
|
66
|
+
interface IntegrationTestRequest {
|
|
67
|
+
cycleId: string; // Links to parent TDD workflow
|
|
68
|
+
scope: 'api' | 'database' | 'service' | 'full';
|
|
69
|
+
endpoints?: {
|
|
70
|
+
method: string;
|
|
71
|
+
path: string;
|
|
72
|
+
expectedStatus: number;
|
|
73
|
+
schema: object;
|
|
74
|
+
expectedHeaders?: Record<string, string>;
|
|
75
|
+
}[];
|
|
76
|
+
databaseConfig?: {
|
|
77
|
+
connectionString: string;
|
|
78
|
+
migrations: string[];
|
|
79
|
+
seedData?: string;
|
|
80
|
+
};
|
|
81
|
+
services?: {
|
|
82
|
+
name: string;
|
|
83
|
+
baseUrl: string;
|
|
84
|
+
healthCheck: string;
|
|
85
|
+
}[];
|
|
86
|
+
contractFiles?: string[]; // Pact/OpenAPI contract files
|
|
87
|
+
timeout: number; // Test timeout in ms
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Subagent Output Interface
|
|
92
|
+
```typescript
|
|
93
|
+
interface IntegrationTestOutput {
|
|
94
|
+
cycleId: string;
|
|
95
|
+
testResults: {
|
|
96
|
+
total: number;
|
|
97
|
+
passed: number;
|
|
98
|
+
failed: number;
|
|
99
|
+
skipped: number;
|
|
100
|
+
duration: number;
|
|
101
|
+
};
|
|
102
|
+
apiResults?: {
|
|
103
|
+
endpoint: string;
|
|
104
|
+
status: 'pass' | 'fail';
|
|
105
|
+
responseTime: number;
|
|
106
|
+
schemaValid: boolean;
|
|
107
|
+
errors?: string[];
|
|
108
|
+
}[];
|
|
109
|
+
databaseResults?: {
|
|
110
|
+
operation: string;
|
|
111
|
+
status: 'pass' | 'fail';
|
|
112
|
+
duration: number;
|
|
113
|
+
rowsAffected?: number;
|
|
114
|
+
}[];
|
|
115
|
+
serviceResults?: {
|
|
116
|
+
serviceName: string;
|
|
117
|
+
status: 'pass' | 'fail';
|
|
118
|
+
healthCheckPassed: boolean;
|
|
119
|
+
latency: number;
|
|
120
|
+
}[];
|
|
121
|
+
contractValidations: {
|
|
122
|
+
contractFile: string;
|
|
123
|
+
provider: string;
|
|
124
|
+
consumer: string;
|
|
125
|
+
passed: boolean;
|
|
126
|
+
mismatches?: string[];
|
|
127
|
+
}[];
|
|
128
|
+
readyForHandoff: boolean;
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Memory Coordination
|
|
133
|
+
- **Read from**: `aqe/integration/cycle-{cycleId}/input` (parent agent request)
|
|
134
|
+
- **Write to**: `aqe/integration/cycle-{cycleId}/results`
|
|
135
|
+
- **Status updates**: `aqe/integration/cycle-{cycleId}/status`
|
|
136
|
+
|
|
137
|
+
### Handoff Protocol
|
|
138
|
+
1. Read test configuration from `aqe/integration/cycle-{cycleId}/input`
|
|
139
|
+
2. Execute integration tests by scope
|
|
140
|
+
3. Validate all API contracts
|
|
141
|
+
4. Write comprehensive results to `aqe/integration/cycle-{cycleId}/results`
|
|
142
|
+
5. Set `readyForHandoff: true` when all critical tests pass
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
59
146
|
**Status**: Active
|
|
60
147
|
**Version**: 1.0.0
|
|
@@ -35,5 +35,103 @@ function validatePerformance(results, sla) {
|
|
|
35
35
|
|
|
36
36
|
---
|
|
37
37
|
|
|
38
|
+
## TDD Coordination Protocol
|
|
39
|
+
|
|
40
|
+
### Memory Namespace
|
|
41
|
+
`aqe/performance/cycle-{cycleId}/*`
|
|
42
|
+
|
|
43
|
+
### Subagent Input Interface
|
|
44
|
+
```typescript
|
|
45
|
+
interface PerformanceRequest {
|
|
46
|
+
cycleId: string; // Links to parent TDD workflow
|
|
47
|
+
testType: 'load' | 'stress' | 'endurance' | 'spike';
|
|
48
|
+
targets: {
|
|
49
|
+
endpoint: string;
|
|
50
|
+
method: string;
|
|
51
|
+
payload?: object;
|
|
52
|
+
}[];
|
|
53
|
+
sla: {
|
|
54
|
+
responseTime: {
|
|
55
|
+
max: number; // Maximum acceptable (ms)
|
|
56
|
+
p95: number; // 95th percentile target
|
|
57
|
+
p99: number; // 99th percentile target
|
|
58
|
+
};
|
|
59
|
+
throughput: {
|
|
60
|
+
min: number; // Minimum requests/second
|
|
61
|
+
};
|
|
62
|
+
errorRate: {
|
|
63
|
+
max: number; // Maximum error rate (0.01 = 1%)
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
loadProfile?: {
|
|
67
|
+
users: number;
|
|
68
|
+
rampUp: number; // seconds
|
|
69
|
+
duration: number; // seconds
|
|
70
|
+
};
|
|
71
|
+
baselineResults?: object; // Previous results for regression detection
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Subagent Output Interface
|
|
76
|
+
```typescript
|
|
77
|
+
interface PerformanceOutput {
|
|
78
|
+
cycleId: string;
|
|
79
|
+
validationResult: 'pass' | 'fail' | 'warning';
|
|
80
|
+
metrics: {
|
|
81
|
+
responseTime: {
|
|
82
|
+
min: number;
|
|
83
|
+
max: number;
|
|
84
|
+
mean: number;
|
|
85
|
+
median: number;
|
|
86
|
+
p95: number;
|
|
87
|
+
p99: number;
|
|
88
|
+
};
|
|
89
|
+
throughput: {
|
|
90
|
+
requestsPerSecond: number;
|
|
91
|
+
bytesPerSecond: number;
|
|
92
|
+
};
|
|
93
|
+
errorRate: number;
|
|
94
|
+
concurrentUsers: number;
|
|
95
|
+
};
|
|
96
|
+
slaValidation: {
|
|
97
|
+
responseTimePassed: boolean;
|
|
98
|
+
throughputPassed: boolean;
|
|
99
|
+
errorRatePassed: boolean;
|
|
100
|
+
allPassed: boolean;
|
|
101
|
+
};
|
|
102
|
+
violations: {
|
|
103
|
+
metric: string;
|
|
104
|
+
actual: number;
|
|
105
|
+
expected: number;
|
|
106
|
+
severity: 'critical' | 'warning';
|
|
107
|
+
}[];
|
|
108
|
+
regressionDetected: boolean;
|
|
109
|
+
regressionDetails?: {
|
|
110
|
+
metric: string;
|
|
111
|
+
previousValue: number;
|
|
112
|
+
currentValue: number;
|
|
113
|
+
percentageChange: number;
|
|
114
|
+
}[];
|
|
115
|
+
recommendations: string[];
|
|
116
|
+
readyForHandoff: boolean;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Memory Coordination
|
|
121
|
+
- **Read from**: `aqe/performance/cycle-{cycleId}/input` (test configuration)
|
|
122
|
+
- **Write to**: `aqe/performance/cycle-{cycleId}/results`
|
|
123
|
+
- **Status updates**: `aqe/performance/cycle-{cycleId}/status`
|
|
124
|
+
- **Baseline storage**: `aqe/performance/baselines/{endpoint}`
|
|
125
|
+
|
|
126
|
+
### Handoff Protocol
|
|
127
|
+
1. Read performance test config from `aqe/performance/cycle-{cycleId}/input`
|
|
128
|
+
2. Execute performance tests based on load profile
|
|
129
|
+
3. Validate results against SLAs
|
|
130
|
+
4. Detect regressions against baselines
|
|
131
|
+
5. Write results to `aqe/performance/cycle-{cycleId}/results`
|
|
132
|
+
6. Set `readyForHandoff: true` if all SLA validations pass
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
38
136
|
**Status**: Active
|
|
39
137
|
**Version**: 1.0.0
|
|
@@ -31,5 +31,91 @@ function auditSecurity(code) {
|
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
34
|
+
## TDD Coordination Protocol
|
|
35
|
+
|
|
36
|
+
### Memory Namespace
|
|
37
|
+
`aqe/security/cycle-{cycleId}/*`
|
|
38
|
+
|
|
39
|
+
### Subagent Input Interface
|
|
40
|
+
```typescript
|
|
41
|
+
interface SecurityAuditRequest {
|
|
42
|
+
cycleId: string; // Links to parent TDD workflow
|
|
43
|
+
scanType: 'static' | 'dynamic' | 'dependency' | 'full';
|
|
44
|
+
targetFiles: string[]; // Files/directories to audit
|
|
45
|
+
compliance: string[]; // e.g., ['OWASP', 'SOC2', 'PCI-DSS']
|
|
46
|
+
severityThreshold: 'critical' | 'high' | 'medium' | 'low';
|
|
47
|
+
excludePatterns?: string[]; // Files to skip
|
|
48
|
+
customRules?: {
|
|
49
|
+
pattern: string;
|
|
50
|
+
severity: string;
|
|
51
|
+
message: string;
|
|
52
|
+
}[];
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Subagent Output Interface
|
|
57
|
+
```typescript
|
|
58
|
+
interface SecurityAuditOutput {
|
|
59
|
+
cycleId: string;
|
|
60
|
+
auditResult: 'pass' | 'fail';
|
|
61
|
+
vulnerabilities: {
|
|
62
|
+
id: string;
|
|
63
|
+
type: string; // SQL_INJECTION, XSS, etc.
|
|
64
|
+
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
65
|
+
file: string;
|
|
66
|
+
line: number;
|
|
67
|
+
description: string;
|
|
68
|
+
cweId?: string; // Common Weakness Enumeration
|
|
69
|
+
remediation: string;
|
|
70
|
+
falsePositive: boolean;
|
|
71
|
+
}[];
|
|
72
|
+
dependencyVulnerabilities?: {
|
|
73
|
+
package: string;
|
|
74
|
+
version: string;
|
|
75
|
+
vulnerability: string;
|
|
76
|
+
severity: string;
|
|
77
|
+
fixedVersion?: string;
|
|
78
|
+
}[];
|
|
79
|
+
complianceReport: {
|
|
80
|
+
standard: string;
|
|
81
|
+
passed: boolean;
|
|
82
|
+
findings: {
|
|
83
|
+
control: string;
|
|
84
|
+
status: 'pass' | 'fail' | 'not-applicable';
|
|
85
|
+
evidence?: string;
|
|
86
|
+
}[];
|
|
87
|
+
}[];
|
|
88
|
+
summary: {
|
|
89
|
+
totalVulnerabilities: number;
|
|
90
|
+
bySeverity: {
|
|
91
|
+
critical: number;
|
|
92
|
+
high: number;
|
|
93
|
+
medium: number;
|
|
94
|
+
low: number;
|
|
95
|
+
};
|
|
96
|
+
filesScanned: number;
|
|
97
|
+
scanDuration: number;
|
|
98
|
+
};
|
|
99
|
+
readyForHandoff: boolean;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Memory Coordination
|
|
104
|
+
- **Read from**: `aqe/security/cycle-{cycleId}/input` (audit request)
|
|
105
|
+
- **Write to**: `aqe/security/cycle-{cycleId}/results`
|
|
106
|
+
- **Status updates**: `aqe/security/cycle-{cycleId}/status`
|
|
107
|
+
- **Vulnerability database**: `aqe/security/known-vulnerabilities`
|
|
108
|
+
|
|
109
|
+
### Handoff Protocol
|
|
110
|
+
1. Read audit configuration from `aqe/security/cycle-{cycleId}/input`
|
|
111
|
+
2. Execute security scans based on scan type
|
|
112
|
+
3. Cross-reference with known vulnerability database
|
|
113
|
+
4. Generate compliance reports
|
|
114
|
+
5. Write results to `aqe/security/cycle-{cycleId}/results`
|
|
115
|
+
6. Set `readyForHandoff: true` only if no critical/high vulnerabilities found
|
|
116
|
+
7. Always block handoff if critical vulnerabilities detected
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
34
120
|
**Status**: Active
|
|
35
121
|
**Version**: 1.0.0
|