agentic-qe 1.9.1 → 1.9.3
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/helpers/checkpoint-manager.sh +251 -0
- package/.claude/helpers/github-safe.js +106 -0
- package/.claude/helpers/github-setup.sh +28 -0
- package/.claude/helpers/quick-start.sh +19 -0
- package/.claude/helpers/setup-mcp.sh +18 -0
- package/.claude/helpers/standard-checkpoint-hooks.sh +179 -0
- package/CHANGELOG.md +36 -0
- package/README.md +33 -1
- package/dist/core/memory/SwarmMemoryManager.d.ts.map +1 -1
- package/dist/core/memory/SwarmMemoryManager.js +45 -5
- package/dist/core/memory/SwarmMemoryManager.js.map +1 -1
- package/dist/mcp/handlers/memory/memory-store.d.ts +6 -2
- package/dist/mcp/handlers/memory/memory-store.d.ts.map +1 -1
- package/dist/mcp/handlers/memory/memory-store.js +26 -4
- package/dist/mcp/handlers/memory/memory-store.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +2 -1
- package/dist/mcp/server.js.map +1 -1
- package/docs/README.md +839 -0
- package/docs/reference/agents.md +412 -0
- package/docs/reference/skills.md +796 -0
- package/docs/reference/usage.md +512 -0
- package/package.json +4 -1
- package/templates/agent-code-execution-template.md +619 -0
- package/templates/aqe.sh +20 -0
- package/.claude/commands/github/code-review-swarm.md +0 -514
- package/.claude/commands/github/github-modes.md +0 -147
- package/.claude/commands/github/issue-tracker.md +0 -292
- package/.claude/commands/github/multi-repo-swarm.md +0 -519
- package/.claude/commands/github/pr-manager.md +0 -170
- package/.claude/commands/github/project-board-sync.md +0 -471
- package/.claude/commands/github/release-manager.md +0 -338
- package/.claude/commands/github/release-swarm.md +0 -544
- package/.claude/commands/github/repo-architect.md +0 -367
- package/.claude/commands/github/swarm-issue.md +0 -482
- package/.claude/commands/github/swarm-pr.md +0 -285
- package/.claude/commands/github/sync-coordinator.md +0 -301
- package/.claude/commands/github/workflow-automation.md +0 -442
- package/.claude/commands/hooks/overview.md +0 -132
- package/.claude/commands/pair/commands.md +0 -546
- package/.claude/commands/pair/config.md +0 -510
- package/.claude/commands/pair/examples.md +0 -512
- package/.claude/commands/pair/modes.md +0 -348
- package/.claude/commands/pair/session.md +0 -407
- package/.claude/commands/pair/start.md +0 -209
- package/.claude/commands/sparc/orchestrator.md +0 -132
- package/.claude/commands/sparc/sparc-modes.md +0 -174
- package/.claude/commands/stream-chain/pipeline.md +0 -121
- package/.claude/commands/stream-chain/run.md +0 -70
- package/.claude/commands/swarm/analysis.md +0 -95
- package/.claude/commands/swarm/development.md +0 -96
- package/.claude/commands/swarm/examples.md +0 -168
- package/.claude/commands/swarm/maintenance.md +0 -102
- package/.claude/commands/swarm/optimization.md +0 -117
- package/.claude/commands/swarm/research.md +0 -136
- package/.claude/commands/swarm/testing.md +0 -131
- package/.claude/commands/truth/start.md +0 -143
- package/.claude/commands/verify/check.md +0 -50
- package/.claude/commands/verify/start.md +0 -128
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
# Code Execution Workflows Template for QE Agents
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
This template provides standard patterns for code execution workflows in QE agents. Anthropic recommends code execution over direct tool calls for 98.7% token reduction (150K → 2K tokens).
|
|
5
|
+
|
|
6
|
+
## Standard Import Pattern
|
|
7
|
+
|
|
8
|
+
```javascript
|
|
9
|
+
// Import MCP tools for orchestration
|
|
10
|
+
import { TestGenerateHandler } from '../src/mcp/handlers/test-generate.js';
|
|
11
|
+
import { CoverageAnalyzeHandler } from '../src/mcp/handlers/analysis/coverage-analyze.js';
|
|
12
|
+
import { TestExecuteHandler } from '../src/mcp/handlers/test-execute.js';
|
|
13
|
+
import { AgentRegistry } from '../src/mcp/services/AgentRegistry.js';
|
|
14
|
+
import { HookExecutor } from '../src/mcp/services/HookExecutor.js';
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Tool Discovery Commands
|
|
18
|
+
|
|
19
|
+
### Finding Available Tools
|
|
20
|
+
```bash
|
|
21
|
+
# List all MCP handler directories
|
|
22
|
+
ls -la ./src/mcp/handlers/
|
|
23
|
+
|
|
24
|
+
# Test domain tools
|
|
25
|
+
ls -la ./src/mcp/handlers/test/
|
|
26
|
+
# Files: test-generate-enhanced.ts, test-execute-parallel.ts,
|
|
27
|
+
# test-optimize-sublinear.ts, test-coverage-detailed.ts
|
|
28
|
+
|
|
29
|
+
# Analysis domain tools
|
|
30
|
+
ls -la ./src/mcp/handlers/analysis/
|
|
31
|
+
# Files: coverage-analyze.ts, coverage-gap-detect.ts,
|
|
32
|
+
# code-quality-check.ts, dependency-analyze.ts
|
|
33
|
+
|
|
34
|
+
# Advanced domain tools
|
|
35
|
+
ls -la ./src/mcp/handlers/advanced/
|
|
36
|
+
# Files: api-breaking-changes.ts, mutation-test-execute.ts,
|
|
37
|
+
# production-incident-replay.ts, requirements-validate.ts
|
|
38
|
+
|
|
39
|
+
# Coordination domain tools
|
|
40
|
+
ls -la ./src/mcp/handlers/coordination/
|
|
41
|
+
# Files: fleet-coordinate.ts, agent-sync.ts, task-distribute.ts
|
|
42
|
+
|
|
43
|
+
# Prediction domain tools
|
|
44
|
+
ls -la ./src/mcp/handlers/prediction/
|
|
45
|
+
# Files: defect-predict.ts, flaky-detect.ts, risk-assess.ts
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Workflow Example 1: Test Generation Orchestration
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
// Initialize handlers
|
|
52
|
+
const registry = new AgentRegistry();
|
|
53
|
+
const hookExecutor = new HookExecutor();
|
|
54
|
+
const testGenerator = new TestGenerateHandler(registry, hookExecutor);
|
|
55
|
+
|
|
56
|
+
// Define test generation specification
|
|
57
|
+
const testSpec = {
|
|
58
|
+
type: 'unit',
|
|
59
|
+
sourceCode: {
|
|
60
|
+
repositoryUrl: 'https://github.com/example/repo',
|
|
61
|
+
branch: 'main',
|
|
62
|
+
language: 'javascript'
|
|
63
|
+
},
|
|
64
|
+
frameworks: ['jest'],
|
|
65
|
+
coverageTarget: 85,
|
|
66
|
+
synthesizeData: true
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Execute test generation with error handling
|
|
70
|
+
try {
|
|
71
|
+
const result = await testGenerator.handle({ spec: testSpec });
|
|
72
|
+
|
|
73
|
+
if (result.success) {
|
|
74
|
+
console.log(`Generated ${result.data.tests.length} tests`);
|
|
75
|
+
console.log(`Coverage: ${result.data.coverage.achieved}%`);
|
|
76
|
+
|
|
77
|
+
// Conditional logic: Check if coverage target met
|
|
78
|
+
if (result.data.coverage.achieved < testSpec.coverageTarget) {
|
|
79
|
+
console.log('Coverage gap detected, generating additional tests...');
|
|
80
|
+
const gaps = result.data.coverage.gaps;
|
|
81
|
+
|
|
82
|
+
// Generate additional tests for gaps
|
|
83
|
+
for (const gap of gaps) {
|
|
84
|
+
const additionalSpec = {
|
|
85
|
+
...testSpec,
|
|
86
|
+
targetFiles: [gap.file],
|
|
87
|
+
focusAreas: gap.functions
|
|
88
|
+
};
|
|
89
|
+
await testGenerator.handle({ spec: additionalSpec });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error('Test generation failed:', error.message);
|
|
95
|
+
// Fallback strategy
|
|
96
|
+
console.log('Attempting alternative test generation strategy...');
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Workflow Example 2: Coverage Analysis Pipeline
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
import { CoverageAnalyzeHandler } from '../src/mcp/handlers/analysis/coverage-analyze.js';
|
|
104
|
+
|
|
105
|
+
const coverageAnalyzer = new CoverageAnalyzeHandler(registry, hookExecutor);
|
|
106
|
+
|
|
107
|
+
// Multi-step coverage workflow
|
|
108
|
+
async function analyzeCoverageGaps(projectPath) {
|
|
109
|
+
// Step 1: Run coverage analysis
|
|
110
|
+
const coverageResult = await coverageAnalyzer.handle({
|
|
111
|
+
projectPath,
|
|
112
|
+
thresholds: { statements: 80, branches: 75, functions: 85 },
|
|
113
|
+
includePatterns: ['src/**/*.js', 'lib/**/*.js'],
|
|
114
|
+
excludePatterns: ['**/*.test.js', '**/node_modules/**']
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Step 2: Conditional gap detection
|
|
118
|
+
if (!coverageResult.data.passesThresholds) {
|
|
119
|
+
console.log('Coverage gaps detected:');
|
|
120
|
+
|
|
121
|
+
// Analyze each gap
|
|
122
|
+
for (const file of coverageResult.data.uncoveredFiles) {
|
|
123
|
+
console.log(`File: ${file.path}`);
|
|
124
|
+
console.log(` Statements: ${file.coverage.statements}%`);
|
|
125
|
+
console.log(` Missing lines: ${file.uncoveredLines.join(', ')}`);
|
|
126
|
+
|
|
127
|
+
// Prioritize gaps by criticality
|
|
128
|
+
if (file.coverage.statements < 50) {
|
|
129
|
+
console.log(` Priority: CRITICAL - requires immediate attention`);
|
|
130
|
+
|
|
131
|
+
// Trigger test generation for critical gaps
|
|
132
|
+
await testGenerator.handle({
|
|
133
|
+
spec: {
|
|
134
|
+
type: 'unit',
|
|
135
|
+
targetFiles: [file.path],
|
|
136
|
+
coverageTarget: 80,
|
|
137
|
+
sourceCode: {
|
|
138
|
+
repositoryUrl: projectPath,
|
|
139
|
+
branch: 'main',
|
|
140
|
+
language: 'javascript'
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return coverageResult;
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Workflow Example 3: Parallel Test Execution
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
import { TestExecuteHandler } from '../src/mcp/handlers/test-execute.js';
|
|
156
|
+
|
|
157
|
+
const testExecutor = new TestExecuteHandler(registry, hookExecutor);
|
|
158
|
+
|
|
159
|
+
// Orchestrate parallel test execution
|
|
160
|
+
async function runTestSuiteWithParallelization(suites) {
|
|
161
|
+
const results = [];
|
|
162
|
+
|
|
163
|
+
// Execute test suites in parallel
|
|
164
|
+
const executions = suites.map(async (suite) => {
|
|
165
|
+
try {
|
|
166
|
+
const result = await testExecutor.handle({
|
|
167
|
+
suite: suite.name,
|
|
168
|
+
framework: suite.framework,
|
|
169
|
+
parallel: true,
|
|
170
|
+
maxWorkers: 4,
|
|
171
|
+
coverage: true,
|
|
172
|
+
bail: false // Continue on failure
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
suite: suite.name,
|
|
177
|
+
success: result.success,
|
|
178
|
+
stats: result.data.stats,
|
|
179
|
+
failures: result.data.failures
|
|
180
|
+
};
|
|
181
|
+
} catch (error) {
|
|
182
|
+
return {
|
|
183
|
+
suite: suite.name,
|
|
184
|
+
success: false,
|
|
185
|
+
error: error.message
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Wait for all executions
|
|
191
|
+
const allResults = await Promise.all(executions);
|
|
192
|
+
|
|
193
|
+
// Analyze results
|
|
194
|
+
const failedSuites = allResults.filter(r => !r.success);
|
|
195
|
+
const totalTests = allResults.reduce((sum, r) => sum + (r.stats?.total || 0), 0);
|
|
196
|
+
const totalFailures = allResults.reduce((sum, r) => sum + (r.stats?.failed || 0), 0);
|
|
197
|
+
|
|
198
|
+
console.log(`Executed ${totalTests} tests across ${suites.length} suites`);
|
|
199
|
+
console.log(`Failures: ${totalFailures}`);
|
|
200
|
+
|
|
201
|
+
// Conditional retry for failed suites
|
|
202
|
+
if (failedSuites.length > 0 && failedSuites.length < suites.length) {
|
|
203
|
+
console.log('Retrying failed suites...');
|
|
204
|
+
|
|
205
|
+
for (const failed of failedSuites) {
|
|
206
|
+
const retryResult = await testExecutor.handle({
|
|
207
|
+
suite: failed.suite,
|
|
208
|
+
framework: 'jest',
|
|
209
|
+
parallel: false, // Run serially on retry
|
|
210
|
+
maxWorkers: 1,
|
|
211
|
+
coverage: false
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (retryResult.success) {
|
|
215
|
+
console.log(`Suite ${failed.suite} passed on retry`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return allResults;
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Workflow Example 4: ML-Based Flaky Detection
|
|
225
|
+
|
|
226
|
+
```javascript
|
|
227
|
+
import { FlakyDetectHandler } from '../src/mcp/handlers/prediction/flaky-detect.js';
|
|
228
|
+
|
|
229
|
+
const flakyDetector = new FlakyDetectHandler(registry, hookExecutor);
|
|
230
|
+
|
|
231
|
+
// Orchestrate flaky test detection and stabilization
|
|
232
|
+
async function detectAndStabilizeFlakyTests(testResults) {
|
|
233
|
+
// Step 1: Analyze test results for flakiness patterns
|
|
234
|
+
const flakyAnalysis = await flakyDetector.handle({
|
|
235
|
+
testResults,
|
|
236
|
+
analysisWindow: 50, // Last 50 runs
|
|
237
|
+
confidenceThreshold: 0.85,
|
|
238
|
+
mlModel: 'random-forest',
|
|
239
|
+
features: ['duration_variance', 'failure_rate', 'timing_dependencies']
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Step 2: Process detected flaky tests
|
|
243
|
+
if (flakyAnalysis.data.flakyTests.length > 0) {
|
|
244
|
+
console.log(`Detected ${flakyAnalysis.data.flakyTests.length} flaky tests`);
|
|
245
|
+
|
|
246
|
+
for (const flakyTest of flakyAnalysis.data.flakyTests) {
|
|
247
|
+
console.log(`Test: ${flakyTest.name}`);
|
|
248
|
+
console.log(` Confidence: ${flakyTest.confidence}`);
|
|
249
|
+
console.log(` Patterns: ${flakyTest.patterns.join(', ')}`);
|
|
250
|
+
|
|
251
|
+
// Step 3: Conditional auto-stabilization
|
|
252
|
+
if (flakyTest.confidence > 0.9 && flakyTest.autoFixable) {
|
|
253
|
+
console.log(' Applying auto-stabilization...');
|
|
254
|
+
|
|
255
|
+
// Apply stabilization strategies
|
|
256
|
+
const stabilizationResult = await applyStabilization(flakyTest);
|
|
257
|
+
|
|
258
|
+
if (stabilizationResult.success) {
|
|
259
|
+
console.log(' ✓ Test stabilized successfully');
|
|
260
|
+
|
|
261
|
+
// Re-run test to verify
|
|
262
|
+
const verifyResult = await testExecutor.handle({
|
|
263
|
+
suite: flakyTest.suite,
|
|
264
|
+
testPattern: flakyTest.name,
|
|
265
|
+
runs: 10, // Run 10 times to verify stability
|
|
266
|
+
parallel: false
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const stabilityScore = verifyResult.data.stats.passed / verifyResult.data.stats.total;
|
|
270
|
+
console.log(` Stability score: ${stabilityScore * 100}%`);
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
console.log(' Manual intervention required');
|
|
274
|
+
console.log(` Recommendations: ${flakyTest.recommendations.join(', ')}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return flakyAnalysis;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async function applyStabilization(flakyTest) {
|
|
283
|
+
// Apply pattern-specific fixes
|
|
284
|
+
const strategies = {
|
|
285
|
+
'timing-dependency': async () => {
|
|
286
|
+
// Add explicit waits
|
|
287
|
+
console.log(' Adding explicit waits...');
|
|
288
|
+
},
|
|
289
|
+
'race-condition': async () => {
|
|
290
|
+
// Add synchronization
|
|
291
|
+
console.log(' Adding synchronization...');
|
|
292
|
+
},
|
|
293
|
+
'resource-leak': async () => {
|
|
294
|
+
// Add cleanup hooks
|
|
295
|
+
console.log(' Adding cleanup hooks...');
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
for (const pattern of flakyTest.patterns) {
|
|
300
|
+
if (strategies[pattern]) {
|
|
301
|
+
await strategies[pattern]();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return { success: true };
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Workflow Example 5: Quality Gate Validation
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
import { QualityGateHandler } from '../src/mcp/handlers/quality/quality-gate.js';
|
|
313
|
+
|
|
314
|
+
const qualityGate = new QualityGateHandler(registry, hookExecutor);
|
|
315
|
+
|
|
316
|
+
// Comprehensive quality gate orchestration
|
|
317
|
+
async function validateDeploymentReadiness(deploymentSpec) {
|
|
318
|
+
const checks = [];
|
|
319
|
+
|
|
320
|
+
// 1. Run code coverage check
|
|
321
|
+
console.log('Running coverage check...');
|
|
322
|
+
const coverageCheck = await coverageAnalyzer.handle({
|
|
323
|
+
projectPath: deploymentSpec.projectPath,
|
|
324
|
+
thresholds: { statements: 80, branches: 75, functions: 85 }
|
|
325
|
+
});
|
|
326
|
+
checks.push({
|
|
327
|
+
name: 'coverage',
|
|
328
|
+
passed: coverageCheck.data.passesThresholds,
|
|
329
|
+
details: coverageCheck.data
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// 2. Run test execution check
|
|
333
|
+
console.log('Running test suite...');
|
|
334
|
+
const testCheck = await testExecutor.handle({
|
|
335
|
+
suite: 'all',
|
|
336
|
+
framework: 'jest',
|
|
337
|
+
parallel: true,
|
|
338
|
+
coverage: false
|
|
339
|
+
});
|
|
340
|
+
checks.push({
|
|
341
|
+
name: 'tests',
|
|
342
|
+
passed: testCheck.data.stats.failed === 0,
|
|
343
|
+
details: testCheck.data.stats
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// 3. Run flaky test detection
|
|
347
|
+
console.log('Detecting flaky tests...');
|
|
348
|
+
const flakyCheck = await flakyDetector.handle({
|
|
349
|
+
testResults: testCheck.data.results,
|
|
350
|
+
confidenceThreshold: 0.85
|
|
351
|
+
});
|
|
352
|
+
checks.push({
|
|
353
|
+
name: 'flaky-tests',
|
|
354
|
+
passed: flakyCheck.data.flakyTests.length === 0,
|
|
355
|
+
details: { flakyCount: flakyCheck.data.flakyTests.length }
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// 4. Aggregate quality gate results
|
|
359
|
+
const qualityGateResult = await qualityGate.handle({
|
|
360
|
+
checks,
|
|
361
|
+
policy: 'strict', // All checks must pass
|
|
362
|
+
environment: deploymentSpec.environment
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
// 5. Conditional deployment decision
|
|
366
|
+
if (qualityGateResult.data.passed) {
|
|
367
|
+
console.log('✓ Quality gate PASSED - Deployment approved');
|
|
368
|
+
console.log(` Score: ${qualityGateResult.data.score}/100`);
|
|
369
|
+
return { approved: true, results: qualityGateResult };
|
|
370
|
+
} else {
|
|
371
|
+
console.log('✗ Quality gate FAILED - Deployment blocked');
|
|
372
|
+
console.log('Failed checks:');
|
|
373
|
+
|
|
374
|
+
for (const check of qualityGateResult.data.failedChecks) {
|
|
375
|
+
console.log(` - ${check.name}: ${check.reason}`);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Generate remediation plan
|
|
379
|
+
console.log('\nRemediation plan:');
|
|
380
|
+
for (const recommendation of qualityGateResult.data.recommendations) {
|
|
381
|
+
console.log(` ${recommendation.priority}: ${recommendation.action}`);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return { approved: false, results: qualityGateResult };
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## Error Handling Patterns
|
|
390
|
+
|
|
391
|
+
### Pattern 1: Retry with Backoff
|
|
392
|
+
```javascript
|
|
393
|
+
async function executeWithRetry(handler, args, maxRetries = 3) {
|
|
394
|
+
let lastError;
|
|
395
|
+
|
|
396
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
397
|
+
try {
|
|
398
|
+
return await handler.handle(args);
|
|
399
|
+
} catch (error) {
|
|
400
|
+
lastError = error;
|
|
401
|
+
|
|
402
|
+
if (attempt < maxRetries) {
|
|
403
|
+
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
|
|
404
|
+
console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
|
|
405
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
throw new Error(`Failed after ${maxRetries} attempts: ${lastError.message}`);
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### Pattern 2: Graceful Degradation
|
|
415
|
+
```javascript
|
|
416
|
+
async function executeWithFallback(primaryHandler, fallbackHandler, args) {
|
|
417
|
+
try {
|
|
418
|
+
return await primaryHandler.handle(args);
|
|
419
|
+
} catch (error) {
|
|
420
|
+
console.log('Primary handler failed, using fallback:', error.message);
|
|
421
|
+
return await fallbackHandler.handle(args);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Pattern 3: Circuit Breaker
|
|
427
|
+
```javascript
|
|
428
|
+
class CircuitBreaker {
|
|
429
|
+
constructor(handler, threshold = 5, timeout = 60000) {
|
|
430
|
+
this.handler = handler;
|
|
431
|
+
this.failureCount = 0;
|
|
432
|
+
this.threshold = threshold;
|
|
433
|
+
this.timeout = timeout;
|
|
434
|
+
this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
|
|
435
|
+
this.nextAttempt = Date.now();
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
async execute(args) {
|
|
439
|
+
if (this.state === 'OPEN') {
|
|
440
|
+
if (Date.now() < this.nextAttempt) {
|
|
441
|
+
throw new Error('Circuit breaker is OPEN');
|
|
442
|
+
}
|
|
443
|
+
this.state = 'HALF_OPEN';
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
try {
|
|
447
|
+
const result = await this.handler.handle(args);
|
|
448
|
+
this.onSuccess();
|
|
449
|
+
return result;
|
|
450
|
+
} catch (error) {
|
|
451
|
+
this.onFailure();
|
|
452
|
+
throw error;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
onSuccess() {
|
|
457
|
+
this.failureCount = 0;
|
|
458
|
+
this.state = 'CLOSED';
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
onFailure() {
|
|
462
|
+
this.failureCount++;
|
|
463
|
+
|
|
464
|
+
if (this.failureCount >= this.threshold) {
|
|
465
|
+
this.state = 'OPEN';
|
|
466
|
+
this.nextAttempt = Date.now() + this.timeout;
|
|
467
|
+
console.log('Circuit breaker opened');
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
## Best Practices
|
|
474
|
+
|
|
475
|
+
### 1. Tool Discovery Before Execution
|
|
476
|
+
Always discover available tools before importing:
|
|
477
|
+
```bash
|
|
478
|
+
# List all available handlers
|
|
479
|
+
find ./src/mcp/handlers -name "*.ts" -type f
|
|
480
|
+
|
|
481
|
+
# Check specific domain
|
|
482
|
+
ls -la ./src/mcp/handlers/[domain]/
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### 2. Type-Safe Imports
|
|
486
|
+
Import with proper TypeScript types:
|
|
487
|
+
```javascript
|
|
488
|
+
import type { TestGenerationSpec } from '../src/mcp/tools.js';
|
|
489
|
+
import type { HandlerResponse } from '../src/mcp/handlers/base-handler.js';
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### 3. Error Boundary Pattern
|
|
493
|
+
Wrap all orchestration in try-catch:
|
|
494
|
+
```javascript
|
|
495
|
+
async function safeOrchestration() {
|
|
496
|
+
try {
|
|
497
|
+
// Orchestration logic
|
|
498
|
+
} catch (error) {
|
|
499
|
+
console.error('Orchestration failed:', error);
|
|
500
|
+
// Cleanup or rollback
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### 4. Progress Tracking
|
|
506
|
+
Use logging for long-running operations:
|
|
507
|
+
```javascript
|
|
508
|
+
console.log('Step 1/5: Analyzing source code...');
|
|
509
|
+
// ... step 1
|
|
510
|
+
console.log('Step 2/5: Generating tests...');
|
|
511
|
+
// ... step 2
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### 5. Resource Cleanup
|
|
515
|
+
Always cleanup resources:
|
|
516
|
+
```javascript
|
|
517
|
+
try {
|
|
518
|
+
// Orchestration
|
|
519
|
+
} finally {
|
|
520
|
+
await registry.cleanup();
|
|
521
|
+
await hookExecutor.finalize();
|
|
522
|
+
}
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
## Integration with Agent Hooks
|
|
526
|
+
|
|
527
|
+
All code execution workflows should integrate with agent hooks:
|
|
528
|
+
|
|
529
|
+
```javascript
|
|
530
|
+
// Before orchestration
|
|
531
|
+
await hookExecutor.executePreTask({
|
|
532
|
+
description: 'Test generation workflow',
|
|
533
|
+
agentType: 'test-generator',
|
|
534
|
+
agentId: registry.getCurrentAgentId()
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
// After orchestration
|
|
538
|
+
await hookExecutor.executePostTask({
|
|
539
|
+
taskId: registry.getCurrentAgentId(),
|
|
540
|
+
results: {
|
|
541
|
+
testsGenerated: results.length,
|
|
542
|
+
coverage: coverageResult.achieved
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
## Memory Coordination
|
|
548
|
+
|
|
549
|
+
Store results in memory for agent coordination:
|
|
550
|
+
|
|
551
|
+
```javascript
|
|
552
|
+
import { MemoryStore } from '../src/memory/MemoryStore.js';
|
|
553
|
+
|
|
554
|
+
const memoryStore = new MemoryStore();
|
|
555
|
+
|
|
556
|
+
// Store results
|
|
557
|
+
await memoryStore.store('aqe/test-generation/results', {
|
|
558
|
+
suiteId: testSuite.id,
|
|
559
|
+
testsGenerated: testSuite.tests.length,
|
|
560
|
+
coverage: testSuite.coverage.achieved
|
|
561
|
+
}, {
|
|
562
|
+
partition: 'agent_results',
|
|
563
|
+
ttl: 86400 // 24 hours
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
// Retrieve shared context
|
|
567
|
+
const context = await memoryStore.retrieve('aqe/context', {
|
|
568
|
+
partition: 'coordination'
|
|
569
|
+
});
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
## Performance Optimization
|
|
573
|
+
|
|
574
|
+
### Batch Operations
|
|
575
|
+
```javascript
|
|
576
|
+
// Instead of sequential
|
|
577
|
+
for (const file of files) {
|
|
578
|
+
await processFile(file);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Use parallel
|
|
582
|
+
await Promise.all(files.map(file => processFile(file)));
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
### Caching Results
|
|
586
|
+
```javascript
|
|
587
|
+
const cache = new Map();
|
|
588
|
+
|
|
589
|
+
async function getCachedResult(key, generator) {
|
|
590
|
+
if (cache.has(key)) {
|
|
591
|
+
return cache.get(key);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
const result = await generator();
|
|
595
|
+
cache.set(key, result);
|
|
596
|
+
return result;
|
|
597
|
+
}
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### Streaming Large Results
|
|
601
|
+
```javascript
|
|
602
|
+
import { TestExecuteStreamHandler } from '../src/mcp/streaming/TestExecuteStreamHandler.js';
|
|
603
|
+
|
|
604
|
+
const streamHandler = new TestExecuteStreamHandler();
|
|
605
|
+
|
|
606
|
+
for await (const event of streamHandler.execute(params)) {
|
|
607
|
+
if (event.type === 'progress') {
|
|
608
|
+
console.log(`Progress: ${event.percent}%`);
|
|
609
|
+
} else if (event.type === 'result') {
|
|
610
|
+
processResult(event.data);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
---
|
|
616
|
+
|
|
617
|
+
**Template Version**: 1.0.0
|
|
618
|
+
**Last Updated**: 2025-11-07
|
|
619
|
+
**Compatible with**: Agentic QE v1.3.0+
|
package/templates/aqe.sh
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# AQE local wrapper - ensures aqe runs from project directory
|
|
3
|
+
|
|
4
|
+
PROJECT_DIR="${PWD}"
|
|
5
|
+
export PWD="${PROJECT_DIR}"
|
|
6
|
+
export AQE_WORKING_DIR="${PROJECT_DIR}"
|
|
7
|
+
|
|
8
|
+
# Try local node_modules first
|
|
9
|
+
if [ -f "${PROJECT_DIR}/node_modules/.bin/aqe" ]; then
|
|
10
|
+
exec "${PROJECT_DIR}/node_modules/.bin/aqe" "$@"
|
|
11
|
+
# Try parent node_modules (monorepo)
|
|
12
|
+
elif [ -f "${PROJECT_DIR}/../node_modules/.bin/aqe" ]; then
|
|
13
|
+
exec "${PROJECT_DIR}/../node_modules/.bin/aqe" "$@"
|
|
14
|
+
# Try global installation
|
|
15
|
+
elif command -v aqe &> /dev/null; then
|
|
16
|
+
exec aqe "$@"
|
|
17
|
+
# Fallback to npx
|
|
18
|
+
else
|
|
19
|
+
exec npx aqe@latest "$@"
|
|
20
|
+
fi
|