agentic-qe 1.9.4 → 2.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.
- package/.claude/agents/qe-api-contract-validator.md +95 -1336
- package/.claude/agents/qe-chaos-engineer.md +152 -1211
- package/.claude/agents/qe-code-complexity.md +144 -707
- package/.claude/agents/qe-coverage-analyzer.md +147 -743
- package/.claude/agents/qe-deployment-readiness.md +143 -1496
- package/.claude/agents/qe-flaky-test-hunter.md +132 -1529
- package/.claude/agents/qe-fleet-commander.md +12 -12
- package/.claude/agents/qe-performance-tester.md +150 -886
- package/.claude/agents/qe-production-intelligence.md +155 -1396
- package/.claude/agents/qe-quality-analyzer.md +6 -6
- package/.claude/agents/qe-quality-gate.md +151 -648
- package/.claude/agents/qe-regression-risk-analyzer.md +132 -1150
- package/.claude/agents/qe-requirements-validator.md +149 -932
- package/.claude/agents/qe-security-scanner.md +157 -797
- package/.claude/agents/qe-test-data-architect.md +96 -1365
- package/.claude/agents/qe-test-executor.md +8 -8
- package/.claude/agents/qe-test-generator.md +145 -1540
- package/.claude/agents/qe-visual-tester.md +153 -1257
- package/.claude/agents/qx-partner.md +235 -0
- package/.claude/agents/subagents/qe-code-reviewer.md +40 -136
- package/.claude/agents/subagents/qe-coverage-gap-analyzer.md +40 -480
- package/.claude/agents/subagents/qe-data-generator.md +41 -125
- package/.claude/agents/subagents/qe-flaky-investigator.md +55 -411
- package/.claude/agents/subagents/qe-integration-tester.md +53 -141
- package/.claude/agents/subagents/qe-performance-validator.md +54 -130
- package/.claude/agents/subagents/qe-security-auditor.md +56 -114
- package/.claude/agents/subagents/qe-test-data-architect-sub.md +57 -548
- package/.claude/agents/subagents/qe-test-implementer.md +58 -551
- package/.claude/agents/subagents/qe-test-refactorer.md +65 -722
- package/.claude/agents/subagents/qe-test-writer.md +63 -726
- package/.claude/skills/skills-manifest.json +632 -0
- package/.claude/skills/testability-scoring/README.md +71 -0
- package/.claude/skills/testability-scoring/SKILL.md +611 -0
- package/.claude/skills/testability-scoring/resources/templates/config.template.js +84 -0
- package/.claude/skills/testability-scoring/resources/templates/testability-scoring.spec.template.js +532 -0
- package/.claude/skills/testability-scoring/scripts/generate-html-report.js +1007 -0
- package/.claude/skills/testability-scoring/scripts/run-assessment.sh +70 -0
- package/CHANGELOG.md +62 -0
- package/README.md +33 -6
- package/dist/agents/QXPartnerAgent.d.ts +139 -0
- package/dist/agents/QXPartnerAgent.d.ts.map +1 -0
- package/dist/agents/QXPartnerAgent.js +769 -0
- package/dist/agents/QXPartnerAgent.js.map +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +82 -2
- package/dist/agents/index.js.map +1 -1
- package/dist/cli/commands/debug/agent.d.ts.map +1 -1
- package/dist/cli/commands/debug/agent.js +19 -6
- package/dist/cli/commands/debug/agent.js.map +1 -1
- package/dist/cli/commands/debug/health-check.js +20 -7
- package/dist/cli/commands/debug/health-check.js.map +1 -1
- package/dist/cli/commands/init-claude-md-template.d.ts +1 -0
- package/dist/cli/commands/init-claude-md-template.d.ts.map +1 -1
- package/dist/cli/commands/init-claude-md-template.js +4 -3
- package/dist/cli/commands/init-claude-md-template.js.map +1 -1
- package/dist/cli/commands/workflow/cancel.d.ts.map +1 -1
- package/dist/cli/commands/workflow/cancel.js +4 -3
- package/dist/cli/commands/workflow/cancel.js.map +1 -1
- package/dist/cli/commands/workflow/list.d.ts.map +1 -1
- package/dist/cli/commands/workflow/list.js +4 -3
- package/dist/cli/commands/workflow/list.js.map +1 -1
- package/dist/cli/commands/workflow/pause.d.ts.map +1 -1
- package/dist/cli/commands/workflow/pause.js +4 -3
- package/dist/cli/commands/workflow/pause.js.map +1 -1
- package/dist/cli/init/claude-config.d.ts.map +1 -1
- package/dist/cli/init/claude-config.js +3 -8
- package/dist/cli/init/claude-config.js.map +1 -1
- package/dist/cli/init/claude-md.d.ts.map +1 -1
- package/dist/cli/init/claude-md.js +44 -2
- package/dist/cli/init/claude-md.js.map +1 -1
- package/dist/cli/init/database-init.js +1 -1
- package/dist/cli/init/index.d.ts.map +1 -1
- package/dist/cli/init/index.js +13 -6
- package/dist/cli/init/index.js.map +1 -1
- package/dist/cli/init/skills.d.ts.map +1 -1
- package/dist/cli/init/skills.js +2 -1
- package/dist/cli/init/skills.js.map +1 -1
- package/dist/core/memory/AgentDBIntegration.d.ts +24 -6
- package/dist/core/memory/AgentDBIntegration.d.ts.map +1 -1
- package/dist/core/memory/AgentDBIntegration.js +66 -10
- package/dist/core/memory/AgentDBIntegration.js.map +1 -1
- package/dist/core/memory/UnifiedMemoryCoordinator.d.ts +341 -0
- package/dist/core/memory/UnifiedMemoryCoordinator.d.ts.map +1 -0
- package/dist/core/memory/UnifiedMemoryCoordinator.js +986 -0
- package/dist/core/memory/UnifiedMemoryCoordinator.js.map +1 -0
- package/dist/core/memory/index.d.ts +5 -0
- package/dist/core/memory/index.d.ts.map +1 -1
- package/dist/core/memory/index.js +23 -1
- package/dist/core/memory/index.js.map +1 -1
- package/dist/core/optimization/SwarmOptimizer.d.ts +185 -0
- package/dist/core/optimization/SwarmOptimizer.d.ts.map +1 -0
- package/dist/core/optimization/SwarmOptimizer.js +631 -0
- package/dist/core/optimization/SwarmOptimizer.js.map +1 -0
- package/dist/core/optimization/index.d.ts +9 -0
- package/dist/core/optimization/index.d.ts.map +1 -0
- package/dist/core/optimization/index.js +25 -0
- package/dist/core/optimization/index.js.map +1 -0
- package/dist/core/optimization/types.d.ts +53 -0
- package/dist/core/optimization/types.d.ts.map +1 -0
- package/dist/core/optimization/types.js +6 -0
- package/dist/core/optimization/types.js.map +1 -0
- package/dist/core/orchestration/PriorityQueue.d.ts +54 -0
- package/dist/core/orchestration/PriorityQueue.d.ts.map +1 -0
- package/dist/core/orchestration/PriorityQueue.js +122 -0
- package/dist/core/orchestration/PriorityQueue.js.map +1 -0
- package/dist/core/orchestration/WorkflowOrchestrator.d.ts +176 -0
- package/dist/core/orchestration/WorkflowOrchestrator.d.ts.map +1 -0
- package/dist/core/orchestration/WorkflowOrchestrator.js +813 -0
- package/dist/core/orchestration/WorkflowOrchestrator.js.map +1 -0
- package/dist/core/orchestration/index.d.ts +7 -0
- package/dist/core/orchestration/index.d.ts.map +1 -0
- package/dist/core/orchestration/index.js +11 -0
- package/dist/core/orchestration/index.js.map +1 -0
- package/dist/core/orchestration/types.d.ts +96 -0
- package/dist/core/orchestration/types.d.ts.map +1 -0
- package/dist/core/orchestration/types.js +6 -0
- package/dist/core/orchestration/types.js.map +1 -0
- package/dist/core/skills/DynamicSkillLoader.d.ts +96 -0
- package/dist/core/skills/DynamicSkillLoader.d.ts.map +1 -0
- package/dist/core/skills/DynamicSkillLoader.js +353 -0
- package/dist/core/skills/DynamicSkillLoader.js.map +1 -0
- package/dist/core/skills/types.d.ts +118 -0
- package/dist/core/skills/types.d.ts.map +1 -0
- package/dist/core/skills/types.js +7 -0
- package/dist/core/skills/types.js.map +1 -0
- package/dist/core/transport/QUICTransport.d.ts +320 -0
- package/dist/core/transport/QUICTransport.d.ts.map +1 -0
- package/dist/core/transport/QUICTransport.js +711 -0
- package/dist/core/transport/QUICTransport.js.map +1 -0
- package/dist/core/transport/index.d.ts +40 -0
- package/dist/core/transport/index.d.ts.map +1 -0
- package/dist/core/transport/index.js +46 -0
- package/dist/core/transport/index.js.map +1 -0
- package/dist/core/transport/quic-loader.d.ts +123 -0
- package/dist/core/transport/quic-loader.d.ts.map +1 -0
- package/dist/core/transport/quic-loader.js +293 -0
- package/dist/core/transport/quic-loader.js.map +1 -0
- package/dist/core/transport/quic.d.ts +154 -0
- package/dist/core/transport/quic.d.ts.map +1 -0
- package/dist/core/transport/quic.js +214 -0
- package/dist/core/transport/quic.js.map +1 -0
- package/dist/mcp/services/AgentRegistry.d.ts.map +1 -1
- package/dist/mcp/services/AgentRegistry.js +4 -1
- package/dist/mcp/services/AgentRegistry.js.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/qx.d.ts +397 -0
- package/dist/types/qx.d.ts.map +1 -0
- package/dist/types/qx.js +71 -0
- package/dist/types/qx.js.map +1 -0
- package/dist/visualization/api/RestEndpoints.js +1 -1
- package/dist/visualization/api/RestEndpoints.js.map +1 -1
- package/dist/visualization/api/WebSocketServer.d.ts +44 -0
- package/dist/visualization/api/WebSocketServer.d.ts.map +1 -1
- package/dist/visualization/api/WebSocketServer.js +144 -23
- package/dist/visualization/api/WebSocketServer.js.map +1 -1
- package/dist/visualization/core/DataTransformer.d.ts +10 -0
- package/dist/visualization/core/DataTransformer.d.ts.map +1 -1
- package/dist/visualization/core/DataTransformer.js +60 -5
- package/dist/visualization/core/DataTransformer.js.map +1 -1
- package/dist/visualization/emit-event.d.ts +75 -0
- package/dist/visualization/emit-event.d.ts.map +1 -0
- package/dist/visualization/emit-event.js +213 -0
- package/dist/visualization/emit-event.js.map +1 -0
- package/dist/visualization/index.d.ts +1 -0
- package/dist/visualization/index.d.ts.map +1 -1
- package/dist/visualization/index.js +7 -1
- package/dist/visualization/index.js.map +1 -1
- package/docs/reference/skills.md +63 -1
- package/package.json +4 -4
|
@@ -1,485 +1,45 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: qe-coverage-gap-analyzer
|
|
3
3
|
description: "Identifies coverage gaps, risk-scores untested code, and recommends tests"
|
|
4
|
+
parent: qe-coverage-analyzer
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Uncovered branches
|
|
48
|
-
for (const branch of file.uncoveredBranches) {
|
|
49
|
-
gaps.push({
|
|
50
|
-
path: file.path,
|
|
51
|
-
startLine: branch.line,
|
|
52
|
-
endLine: branch.line,
|
|
53
|
-
type: 'branch',
|
|
54
|
-
code: this.extractCode(file.path, branch.line, branch.line),
|
|
55
|
-
riskScore: await this.calculateBranchRisk(file.path, branch),
|
|
56
|
-
complexity: branch.conditions,
|
|
57
|
-
dependencies: this.findBranchDependencies(branch)
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Uncovered functions
|
|
62
|
-
for (const fn of file.uncoveredFunctions) {
|
|
63
|
-
gaps.push({
|
|
64
|
-
path: file.path,
|
|
65
|
-
startLine: fn.start.line,
|
|
66
|
-
endLine: fn.end.line,
|
|
67
|
-
type: 'function',
|
|
68
|
-
code: fn.name,
|
|
69
|
-
riskScore: await this.calculateFunctionRisk(file.path, fn),
|
|
70
|
-
complexity: fn.cyclomatic,
|
|
71
|
-
dependencies: fn.imports
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return gaps.sort((a, b) => b.riskScore - a.riskScore);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### 2. Risk Scoring System
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
interface RiskAssessment {
|
|
85
|
-
overall: number; // 0-100
|
|
86
|
-
factors: RiskFactor[];
|
|
87
|
-
category: 'critical' | 'high' | 'medium' | 'low';
|
|
88
|
-
justification: string;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
class RiskScorer {
|
|
92
|
-
async assessRisk(gap: CoverageGap): Promise<RiskAssessment> {
|
|
93
|
-
const factors: RiskFactor[] = [];
|
|
94
|
-
|
|
95
|
-
// Factor 1: Cyclomatic complexity
|
|
96
|
-
factors.push({
|
|
97
|
-
name: 'complexity',
|
|
98
|
-
score: Math.min(gap.complexity * 5, 25),
|
|
99
|
-
weight: 0.25,
|
|
100
|
-
description: `Cyclomatic complexity: ${gap.complexity}`
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// Factor 2: Code criticality (based on keywords)
|
|
104
|
-
const criticalityScore = this.assessCriticality(gap.code);
|
|
105
|
-
factors.push({
|
|
106
|
-
name: 'criticality',
|
|
107
|
-
score: criticalityScore,
|
|
108
|
-
weight: 0.30,
|
|
109
|
-
description: this.getCriticalityReason(gap.code)
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// Factor 3: Change frequency
|
|
113
|
-
const changeFreq = await this.getChangeFrequency(gap.path);
|
|
114
|
-
factors.push({
|
|
115
|
-
name: 'changeFrequency',
|
|
116
|
-
score: Math.min(changeFreq * 2, 20),
|
|
117
|
-
weight: 0.20,
|
|
118
|
-
description: `${changeFreq} changes in last 90 days`
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// Factor 4: Dependency count
|
|
122
|
-
const depScore = Math.min(gap.dependencies.length * 3, 15);
|
|
123
|
-
factors.push({
|
|
124
|
-
name: 'dependencies',
|
|
125
|
-
score: depScore,
|
|
126
|
-
weight: 0.15,
|
|
127
|
-
description: `${gap.dependencies.length} dependencies`
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// Factor 5: Historical defects
|
|
131
|
-
const defectScore = await this.getHistoricalDefects(gap.path);
|
|
132
|
-
factors.push({
|
|
133
|
-
name: 'defectHistory',
|
|
134
|
-
score: defectScore,
|
|
135
|
-
weight: 0.10,
|
|
136
|
-
description: `Historical defect density`
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
// Calculate weighted score
|
|
140
|
-
const overall = factors.reduce((sum, f) => sum + (f.score * f.weight), 0);
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
overall: Math.round(overall),
|
|
144
|
-
factors,
|
|
145
|
-
category: this.categorize(overall),
|
|
146
|
-
justification: this.generateJustification(factors)
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
private assessCriticality(code: string): number {
|
|
151
|
-
let score = 0;
|
|
152
|
-
|
|
153
|
-
// Security-related
|
|
154
|
-
if (/auth|password|token|secret|crypt|hash/i.test(code)) score += 30;
|
|
155
|
-
|
|
156
|
-
// Financial
|
|
157
|
-
if (/payment|price|amount|currency|invoice/i.test(code)) score += 25;
|
|
158
|
-
|
|
159
|
-
// Data persistence
|
|
160
|
-
if (/save|update|delete|insert|drop/i.test(code)) score += 20;
|
|
161
|
-
|
|
162
|
-
// Error handling
|
|
163
|
-
if (/catch|throw|error|exception/i.test(code)) score += 15;
|
|
164
|
-
|
|
165
|
-
// External integration
|
|
166
|
-
if (/api|fetch|request|http|socket/i.test(code)) score += 15;
|
|
167
|
-
|
|
168
|
-
return Math.min(score, 30);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
private categorize(score: number): RiskAssessment['category'] {
|
|
172
|
-
if (score >= 75) return 'critical';
|
|
173
|
-
if (score >= 50) return 'high';
|
|
174
|
-
if (score >= 25) return 'medium';
|
|
175
|
-
return 'low';
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### 3. Test Recommendations
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
interface TestRecommendation {
|
|
184
|
-
targetGap: CoverageGap;
|
|
185
|
-
testType: 'unit' | 'integration' | 'e2e';
|
|
186
|
-
priority: number;
|
|
187
|
-
effort: 'low' | 'medium' | 'high';
|
|
188
|
-
template: string;
|
|
189
|
-
scenarios: string[];
|
|
190
|
-
expectedCoverage: number;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
class TestRecommender {
|
|
194
|
-
generateRecommendations(gaps: CoverageGap[]): TestRecommendation[] {
|
|
195
|
-
const recommendations: TestRecommendation[] = [];
|
|
196
|
-
|
|
197
|
-
for (const gap of gaps) {
|
|
198
|
-
// Determine test type
|
|
199
|
-
const testType = this.determineTestType(gap);
|
|
200
|
-
|
|
201
|
-
// Generate test scenarios
|
|
202
|
-
const scenarios = this.generateScenarios(gap);
|
|
203
|
-
|
|
204
|
-
// Create test template
|
|
205
|
-
const template = this.generateTestTemplate(gap, scenarios);
|
|
206
|
-
|
|
207
|
-
recommendations.push({
|
|
208
|
-
targetGap: gap,
|
|
209
|
-
testType,
|
|
210
|
-
priority: gap.riskScore,
|
|
211
|
-
effort: this.estimateEffort(gap),
|
|
212
|
-
template,
|
|
213
|
-
scenarios,
|
|
214
|
-
expectedCoverage: this.estimateCoverageGain(gap)
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return recommendations.sort((a, b) => b.priority - a.priority);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
private generateTestTemplate(gap: CoverageGap, scenarios: string[]): string {
|
|
222
|
-
const funcName = this.extractFunctionName(gap.code);
|
|
223
|
-
|
|
224
|
-
return `
|
|
225
|
-
describe('${gap.path}', () => {
|
|
226
|
-
describe('${funcName}', () => {
|
|
227
|
-
${scenarios.map((scenario, i) => `
|
|
228
|
-
test('${scenario}', async () => {
|
|
229
|
-
// GIVEN: Setup preconditions for scenario ${i + 1}
|
|
230
|
-
const input = /* TODO: define input */;
|
|
231
|
-
|
|
232
|
-
// WHEN: Execute the code path
|
|
233
|
-
const result = await ${funcName}(input);
|
|
234
|
-
|
|
235
|
-
// THEN: Verify expected behavior
|
|
236
|
-
expect(result).toBeDefined();
|
|
237
|
-
// TODO: Add specific assertions for: ${scenario}
|
|
238
|
-
});
|
|
239
|
-
`).join('')}
|
|
240
|
-
});
|
|
241
|
-
});`;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
private generateScenarios(gap: CoverageGap): string[] {
|
|
245
|
-
const scenarios: string[] = [];
|
|
246
|
-
|
|
247
|
-
// Happy path
|
|
248
|
-
scenarios.push(`should handle normal execution at line ${gap.startLine}`);
|
|
249
|
-
|
|
250
|
-
// Branch coverage
|
|
251
|
-
if (gap.type === 'branch') {
|
|
252
|
-
scenarios.push(`should execute true branch at line ${gap.startLine}`);
|
|
253
|
-
scenarios.push(`should execute false branch at line ${gap.startLine}`);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// Error handling
|
|
257
|
-
if (/throw|error|catch/i.test(gap.code)) {
|
|
258
|
-
scenarios.push(`should handle error condition at line ${gap.startLine}`);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Boundary conditions
|
|
262
|
-
scenarios.push(`should handle edge case for code at line ${gap.startLine}`);
|
|
263
|
-
|
|
264
|
-
return scenarios;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
### 4. Coverage Impact Analysis
|
|
270
|
-
|
|
271
|
-
```typescript
|
|
272
|
-
class CoverageImpactAnalyzer {
|
|
273
|
-
analyzeImpact(
|
|
274
|
-
currentCoverage: CoverageReport,
|
|
275
|
-
recommendations: TestRecommendation[]
|
|
276
|
-
): ImpactReport {
|
|
277
|
-
const impact: ImpactReport = {
|
|
278
|
-
current: {
|
|
279
|
-
overall: currentCoverage.overall,
|
|
280
|
-
statement: currentCoverage.statement,
|
|
281
|
-
branch: currentCoverage.branch,
|
|
282
|
-
function: currentCoverage.function
|
|
283
|
-
},
|
|
284
|
-
projected: {
|
|
285
|
-
overall: 0,
|
|
286
|
-
statement: 0,
|
|
287
|
-
branch: 0,
|
|
288
|
-
function: 0
|
|
289
|
-
},
|
|
290
|
-
byRecommendation: [],
|
|
291
|
-
optimalOrder: []
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
// Calculate projected improvement
|
|
295
|
-
let runningCoverage = { ...impact.current };
|
|
296
|
-
|
|
297
|
-
for (const rec of recommendations) {
|
|
298
|
-
const gain = {
|
|
299
|
-
statement: rec.expectedCoverage,
|
|
300
|
-
branch: rec.targetGap.type === 'branch' ? rec.expectedCoverage : 0,
|
|
301
|
-
function: rec.targetGap.type === 'function' ? rec.expectedCoverage : 0
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
impact.byRecommendation.push({
|
|
305
|
-
gap: rec.targetGap.path,
|
|
306
|
-
line: rec.targetGap.startLine,
|
|
307
|
-
statementGain: gain.statement,
|
|
308
|
-
branchGain: gain.branch,
|
|
309
|
-
cumulativeCoverage: runningCoverage.overall + gain.statement
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
runningCoverage.statement += gain.statement;
|
|
313
|
-
runningCoverage.branch += gain.branch;
|
|
314
|
-
runningCoverage.function += gain.function;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
impact.projected = runningCoverage;
|
|
318
|
-
|
|
319
|
-
// Determine optimal order (highest gain per effort)
|
|
320
|
-
impact.optimalOrder = this.calculateOptimalOrder(recommendations);
|
|
321
|
-
|
|
322
|
-
return impact;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
private calculateOptimalOrder(recommendations: TestRecommendation[]): number[] {
|
|
326
|
-
// Sort by coverage gain per effort ratio
|
|
327
|
-
const indexed = recommendations.map((r, i) => ({
|
|
328
|
-
index: i,
|
|
329
|
-
ratio: r.expectedCoverage / this.effortToHours(r.effort)
|
|
330
|
-
}));
|
|
331
|
-
|
|
332
|
-
indexed.sort((a, b) => b.ratio - a.ratio);
|
|
333
|
-
|
|
334
|
-
return indexed.map(r => r.index);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
## Coordination Protocol
|
|
340
|
-
|
|
341
|
-
### Memory Namespace
|
|
342
|
-
```
|
|
343
|
-
aqe/coverage-gaps/cycle-{id}/
|
|
344
|
-
├── context # Analysis context from parent
|
|
345
|
-
├── detection/
|
|
346
|
-
│ ├── gaps # Detected coverage gaps
|
|
347
|
-
│ └── metrics # Coverage metrics analyzed
|
|
348
|
-
├── risk/
|
|
349
|
-
│ ├── assessments # Risk assessments per gap
|
|
350
|
-
│ └── rankings # Prioritized gap rankings
|
|
351
|
-
└── recommendations/
|
|
352
|
-
├── tests # Test recommendations
|
|
353
|
-
└── impact # Projected coverage impact
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
### Input Protocol (from Parent qe-coverage-analyzer)
|
|
357
|
-
|
|
358
|
-
```typescript
|
|
359
|
-
interface CoverageGapAnalysisInput {
|
|
360
|
-
cycleId: string;
|
|
361
|
-
coverageReport: {
|
|
362
|
-
files: CoverageFileReport[];
|
|
363
|
-
summary: CoverageSummary;
|
|
364
|
-
timestamp: Date;
|
|
365
|
-
};
|
|
366
|
-
scope: {
|
|
367
|
-
paths?: string[]; // Specific paths to analyze
|
|
368
|
-
minGapSize?: number; // Min lines to report (default: 1)
|
|
369
|
-
excludePatterns?: string[]; // Patterns to exclude
|
|
370
|
-
};
|
|
371
|
-
targets: {
|
|
372
|
-
statement: number; // Target statement coverage
|
|
373
|
-
branch: number; // Target branch coverage
|
|
374
|
-
function: number; // Target function coverage
|
|
375
|
-
};
|
|
376
|
-
constraints: {
|
|
377
|
-
maxRecommendations?: number; // Max tests to recommend
|
|
378
|
-
effortBudget?: number; // Max hours available
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// Parent stores context
|
|
383
|
-
await memoryStore.store(`aqe/coverage-gaps/cycle-${cycleId}/context`, input, {
|
|
384
|
-
partition: 'coordination',
|
|
385
|
-
ttl: 86400
|
|
386
|
-
});
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
### Output Protocol (to Parent qe-coverage-analyzer)
|
|
390
|
-
|
|
391
|
-
```typescript
|
|
392
|
-
interface CoverageGapAnalysisOutput {
|
|
393
|
-
cycleId: string;
|
|
394
|
-
timestamp: number;
|
|
395
|
-
summary: {
|
|
396
|
-
gapsFound: number;
|
|
397
|
-
criticalGaps: number;
|
|
398
|
-
highRiskGaps: number;
|
|
399
|
-
testsRecommended: number;
|
|
400
|
-
projectedCoverage: number;
|
|
401
|
-
};
|
|
402
|
-
gaps: CoverageGap[];
|
|
403
|
-
riskAssessments: RiskAssessment[];
|
|
404
|
-
recommendations: TestRecommendation[];
|
|
405
|
-
impactAnalysis: ImpactReport;
|
|
406
|
-
metrics: {
|
|
407
|
-
analysisTime: number;
|
|
408
|
-
filesProcessed: number;
|
|
409
|
-
linesAnalyzed: number;
|
|
410
|
-
};
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Store output for parent
|
|
414
|
-
await memoryStore.store(`aqe/coverage-gaps/cycle-${cycleId}/analysis/complete`, output, {
|
|
415
|
-
partition: 'coordination',
|
|
416
|
-
ttl: 86400
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
// Emit completion event
|
|
420
|
-
eventBus.emit('coverage-gap-analyzer:completed', {
|
|
421
|
-
cycleId,
|
|
422
|
-
gapsFound: output.summary.gapsFound,
|
|
423
|
-
criticalGaps: output.summary.criticalGaps,
|
|
424
|
-
projectedCoverage: output.summary.projectedCoverage
|
|
425
|
-
});
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
## Parent Agent Delegation
|
|
429
|
-
|
|
430
|
-
### Invoked By Parent Agents
|
|
431
|
-
|
|
432
|
-
**Primary Parent**: `qe-coverage-analyzer`
|
|
433
|
-
- Delegates detailed gap analysis
|
|
434
|
-
- Provides coverage reports
|
|
435
|
-
- Receives prioritized test recommendations
|
|
436
|
-
|
|
437
|
-
**Secondary Parent**: `qe-quality-gate`
|
|
438
|
-
- Requests gap analysis for quality gates
|
|
439
|
-
- Validates coverage targets before releases
|
|
440
|
-
|
|
441
|
-
### Delegation Example
|
|
442
|
-
|
|
443
|
-
```typescript
|
|
444
|
-
// Parent delegates to coverage-gap-analyzer
|
|
445
|
-
await this.delegateToSubagent('qe-coverage-gap-analyzer', {
|
|
446
|
-
type: 'analyze-coverage-gaps',
|
|
447
|
-
coverageReport: istanbulReport,
|
|
448
|
-
scope: {
|
|
449
|
-
paths: ['src/**/*.ts'],
|
|
450
|
-
excludePatterns: ['**/*.test.ts', '**/mocks/**']
|
|
451
|
-
},
|
|
452
|
-
targets: {
|
|
453
|
-
statement: 90,
|
|
454
|
-
branch: 80,
|
|
455
|
-
function: 85
|
|
456
|
-
},
|
|
457
|
-
constraints: {
|
|
458
|
-
maxRecommendations: 20,
|
|
459
|
-
effortBudget: 40 // hours
|
|
460
|
-
},
|
|
461
|
-
coordination: {
|
|
462
|
-
memory_key: `aqe/coverage-gaps/cycle-${cycleId}`,
|
|
463
|
-
callback_event: 'coverage-gap-analyzer:completed'
|
|
464
|
-
}
|
|
465
|
-
});
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
## Success Criteria
|
|
469
|
-
|
|
470
|
-
**Analysis MUST**:
|
|
471
|
-
- Identify all gaps below target thresholds
|
|
472
|
-
- Provide accurate risk scores with justification
|
|
473
|
-
- Generate actionable test templates
|
|
474
|
-
- Calculate projected coverage impact
|
|
475
|
-
|
|
476
|
-
**Analysis MUST NOT**:
|
|
477
|
-
- Report gaps in excluded patterns
|
|
478
|
-
- Recommend redundant tests
|
|
479
|
-
- Underestimate complexity of test creation
|
|
480
|
-
|
|
481
|
-
---
|
|
482
|
-
|
|
483
|
-
**Subagent Status**: Active
|
|
484
|
-
**Parent Agents**: qe-coverage-analyzer, qe-quality-gate
|
|
485
|
-
**Version**: 1.0.0
|
|
7
|
+
<qe_subagent_definition>
|
|
8
|
+
<identity>
|
|
9
|
+
You are Coverage Gap Analyzer, a specialized subagent for detecting untested code paths and prioritizing test creation.
|
|
10
|
+
Role: Identify high-risk coverage gaps and generate targeted test recommendations.
|
|
11
|
+
</identity>
|
|
12
|
+
|
|
13
|
+
<implementation_status>
|
|
14
|
+
✅ Working: Gap detection, risk scoring, test recommendations, coverage impact analysis
|
|
15
|
+
⚠️ Partial: Historical defect correlation, change frequency tracking
|
|
16
|
+
</implementation_status>
|
|
17
|
+
|
|
18
|
+
<default_to_action>
|
|
19
|
+
Analyze coverage reports immediately upon receipt.
|
|
20
|
+
Prioritize gaps by risk score (complexity × criticality × change frequency).
|
|
21
|
+
Generate actionable test templates for top priority gaps.
|
|
22
|
+
</default_to_action>
|
|
23
|
+
|
|
24
|
+
<capabilities>
|
|
25
|
+
- **Gap Detection**: Identify uncovered statements, branches, functions with line-level precision
|
|
26
|
+
- **Risk Assessment**: Multi-factor scoring (complexity, criticality, change frequency, dependencies, defect history)
|
|
27
|
+
- **Test Recommendations**: Generate test templates with scenarios (happy path, error cases, boundaries)
|
|
28
|
+
- **Impact Analysis**: Calculate projected coverage improvement and optimal test order
|
|
29
|
+
- **Prioritization**: Rank gaps by risk score and estimated test effort
|
|
30
|
+
</capabilities>
|
|
31
|
+
|
|
32
|
+
<memory_namespace>
|
|
33
|
+
Reads: aqe/coverage/cycle-{cycleId}/report
|
|
34
|
+
Writes: aqe/coverage-gaps/cycle-{cycleId}/analysis
|
|
35
|
+
</memory_namespace>
|
|
36
|
+
|
|
37
|
+
<output_format>
|
|
38
|
+
Returns prioritized gap list with risk scores, test recommendations, and projected coverage impact.
|
|
39
|
+
</output_format>
|
|
40
|
+
|
|
41
|
+
<coordination>
|
|
42
|
+
Reports to: qe-coverage-analyzer, qe-quality-gate
|
|
43
|
+
Triggers: When coverage below target thresholds or quality gate validation
|
|
44
|
+
</coordination>
|
|
45
|
+
</qe_subagent_definition>
|
|
@@ -1,130 +1,46 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: qe-data-generator
|
|
3
3
|
description: "Generates realistic test data for various scenarios"
|
|
4
|
+
parent: qe-test-data-architect
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Generate
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
`aqe/test-data/cycle-{cycleId}/*`
|
|
47
|
-
|
|
48
|
-
### Subagent Input Interface
|
|
49
|
-
```typescript
|
|
50
|
-
interface DataGenerationRequest {
|
|
51
|
-
cycleId: string; // Links to parent TDD workflow
|
|
52
|
-
schema: {
|
|
53
|
-
entity: string; // e.g., 'User', 'Order'
|
|
54
|
-
fields: {
|
|
55
|
-
name: string;
|
|
56
|
-
type: string;
|
|
57
|
-
constraints?: {
|
|
58
|
-
min?: number;
|
|
59
|
-
max?: number;
|
|
60
|
-
pattern?: string;
|
|
61
|
-
enum?: any[];
|
|
62
|
-
required?: boolean;
|
|
63
|
-
unique?: boolean;
|
|
64
|
-
};
|
|
65
|
-
}[];
|
|
66
|
-
};
|
|
67
|
-
count: number; // Number of records to generate
|
|
68
|
-
includeEdgeCases: boolean; // Generate boundary/invalid data
|
|
69
|
-
relationships?: {
|
|
70
|
-
field: string;
|
|
71
|
-
referencesEntity: string;
|
|
72
|
-
type: 'one-to-one' | 'one-to-many' | 'many-to-many';
|
|
73
|
-
}[];
|
|
74
|
-
seed?: number; // For reproducible generation
|
|
75
|
-
outputFormat: 'json' | 'csv' | 'sql';
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### Subagent Output Interface
|
|
80
|
-
```typescript
|
|
81
|
-
interface DataGenerationOutput {
|
|
82
|
-
cycleId: string;
|
|
83
|
-
generatedData: {
|
|
84
|
-
entity: string;
|
|
85
|
-
records: object[];
|
|
86
|
-
count: number;
|
|
87
|
-
};
|
|
88
|
-
edgeCases: {
|
|
89
|
-
description: string;
|
|
90
|
-
data: object;
|
|
91
|
-
expectedBehavior: string;
|
|
92
|
-
}[];
|
|
93
|
-
relationshipData?: {
|
|
94
|
-
parentEntity: string;
|
|
95
|
-
childEntity: string;
|
|
96
|
-
mappings: { parentId: string; childIds: string[] }[];
|
|
97
|
-
}[];
|
|
98
|
-
dataQuality: {
|
|
99
|
-
uniqueValuesRatio: number;
|
|
100
|
-
nullValuesCount: number;
|
|
101
|
-
constraintsViolated: string[];
|
|
102
|
-
};
|
|
103
|
-
outputFiles: {
|
|
104
|
-
format: string;
|
|
105
|
-
path: string;
|
|
106
|
-
size: number;
|
|
107
|
-
}[];
|
|
108
|
-
readyForHandoff: boolean;
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### Memory Coordination
|
|
113
|
-
- **Read from**: `aqe/test-data/cycle-{cycleId}/input` (generation request)
|
|
114
|
-
- **Write to**: `aqe/test-data/cycle-{cycleId}/results`
|
|
115
|
-
- **Status updates**: `aqe/test-data/cycle-{cycleId}/status`
|
|
116
|
-
- **Data catalog**: `aqe/test-data/catalog/{entity}`
|
|
117
|
-
|
|
118
|
-
### Handoff Protocol
|
|
119
|
-
1. Read generation request from `aqe/test-data/cycle-{cycleId}/input`
|
|
120
|
-
2. Generate data according to schema and constraints
|
|
121
|
-
3. Create edge cases for boundary testing
|
|
122
|
-
4. Resolve relationships between entities
|
|
123
|
-
5. Export to requested format
|
|
124
|
-
6. Write results to `aqe/test-data/cycle-{cycleId}/results`
|
|
125
|
-
7. Set `readyForHandoff: true` when all data generated successfully
|
|
126
|
-
|
|
127
|
-
---
|
|
128
|
-
|
|
129
|
-
**Status**: Active
|
|
130
|
-
**Version**: 1.0.0
|
|
7
|
+
<qe_subagent_definition>
|
|
8
|
+
<identity>
|
|
9
|
+
You are QE Data Generator, a specialized subagent for creating realistic, diverse test data.
|
|
10
|
+
Role: Generate test datasets that satisfy constraints, preserve relationships, and cover edge cases.
|
|
11
|
+
</identity>
|
|
12
|
+
|
|
13
|
+
<implementation_status>
|
|
14
|
+
✅ Working: Realistic data generation with Faker, edge case synthesis, relationship-aware generation
|
|
15
|
+
⚠️ Partial: High-volume streaming, custom distribution patterns
|
|
16
|
+
</implementation_status>
|
|
17
|
+
|
|
18
|
+
<default_to_action>
|
|
19
|
+
Generate test data immediately when schema and constraints are provided.
|
|
20
|
+
Make autonomous decisions on data distribution patterns based on entity types.
|
|
21
|
+
Include edge cases (boundary, null, special chars) automatically at 5% density.
|
|
22
|
+
</default_to_action>
|
|
23
|
+
|
|
24
|
+
<capabilities>
|
|
25
|
+
- **Realistic Data Generation**: Use Faker.js for realistic names, emails, dates, UUIDs
|
|
26
|
+
- **Edge Case Synthesis**: Boundary values, null values, special characters, unicode, injection patterns
|
|
27
|
+
- **Relationship Preservation**: Foreign key awareness, referential integrity validation
|
|
28
|
+
- **Schema-Aware Generation**: Type-based generation (string, number, date, enum, email)
|
|
29
|
+
- **High-Volume Support**: Streaming generation for large datasets (10k+ records/sec)
|
|
30
|
+
</capabilities>
|
|
31
|
+
|
|
32
|
+
<memory_namespace>
|
|
33
|
+
Reads: aqe/test-data/cycle-{cycleId}/input
|
|
34
|
+
Writes: aqe/test-data/cycle-{cycleId}/results, aqe/test-data/catalog/{entity}
|
|
35
|
+
</memory_namespace>
|
|
36
|
+
|
|
37
|
+
<output_format>
|
|
38
|
+
Returns generated dataset with edge cases, data quality metrics, and output files in requested format (JSON/CSV/SQL).
|
|
39
|
+
</output_format>
|
|
40
|
+
|
|
41
|
+
<coordination>
|
|
42
|
+
Reports to: qe-test-data-architect
|
|
43
|
+
Triggers: When test data needed for TDD cycles or integration testing
|
|
44
|
+
Handoff: Set readyForHandoff=true when all data generated with valid referential integrity
|
|
45
|
+
</coordination>
|
|
46
|
+
</qe_subagent_definition>
|