agentic-qe 1.9.4 → 2.1.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 +248 -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/accessibility-testing/SKILL.md +144 -692
- package/.claude/skills/agentic-quality-engineering/SKILL.md +176 -529
- package/.claude/skills/api-testing-patterns/SKILL.md +180 -560
- package/.claude/skills/brutal-honesty-review/SKILL.md +113 -603
- package/.claude/skills/bug-reporting-excellence/SKILL.md +116 -517
- package/.claude/skills/chaos-engineering-resilience/SKILL.md +127 -72
- package/.claude/skills/cicd-pipeline-qe-orchestrator/SKILL.md +209 -404
- package/.claude/skills/code-review-quality/SKILL.md +158 -608
- package/.claude/skills/compatibility-testing/SKILL.md +148 -38
- package/.claude/skills/compliance-testing/SKILL.md +132 -63
- package/.claude/skills/consultancy-practices/SKILL.md +114 -446
- package/.claude/skills/context-driven-testing/SKILL.md +117 -381
- package/.claude/skills/contract-testing/SKILL.md +176 -141
- package/.claude/skills/database-testing/SKILL.md +137 -130
- package/.claude/skills/exploratory-testing-advanced/SKILL.md +160 -629
- package/.claude/skills/holistic-testing-pact/SKILL.md +140 -188
- package/.claude/skills/localization-testing/SKILL.md +145 -33
- package/.claude/skills/mobile-testing/SKILL.md +132 -448
- package/.claude/skills/mutation-testing/SKILL.md +147 -41
- package/.claude/skills/performance-testing/SKILL.md +200 -546
- package/.claude/skills/quality-metrics/SKILL.md +164 -519
- package/.claude/skills/refactoring-patterns/SKILL.md +132 -699
- package/.claude/skills/regression-testing/SKILL.md +120 -926
- package/.claude/skills/risk-based-testing/SKILL.md +157 -660
- package/.claude/skills/security-testing/SKILL.md +199 -538
- package/.claude/skills/sherlock-review/SKILL.md +163 -699
- package/.claude/skills/shift-left-testing/SKILL.md +161 -465
- package/.claude/skills/shift-right-testing/SKILL.md +161 -519
- package/.claude/skills/six-thinking-hats/SKILL.md +175 -1110
- package/.claude/skills/skills-manifest.json +683 -0
- package/.claude/skills/tdd-london-chicago/SKILL.md +131 -448
- package/.claude/skills/technical-writing/SKILL.md +103 -154
- package/.claude/skills/test-automation-strategy/SKILL.md +166 -772
- package/.claude/skills/test-data-management/SKILL.md +126 -910
- package/.claude/skills/test-design-techniques/SKILL.md +179 -89
- package/.claude/skills/test-environment-management/SKILL.md +136 -91
- package/.claude/skills/test-reporting-analytics/SKILL.md +169 -92
- package/.claude/skills/testability-scoring/README.md +71 -0
- package/.claude/skills/testability-scoring/SKILL.md +245 -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/.claude/skills/visual-testing-advanced/SKILL.md +155 -78
- package/.claude/skills/xp-practices/SKILL.md +151 -587
- package/CHANGELOG.md +110 -0
- package/README.md +55 -21
- package/dist/agents/QXPartnerAgent.d.ts +146 -0
- package/dist/agents/QXPartnerAgent.d.ts.map +1 -0
- package/dist/agents/QXPartnerAgent.js +1831 -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/agents/lifecycle/AgentLifecycleManager.d.ts.map +1 -1
- package/dist/agents/lifecycle/AgentLifecycleManager.js +34 -31
- package/dist/agents/lifecycle/AgentLifecycleManager.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 +18 -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/SwarmCoordinator.d.ts +180 -0
- package/dist/core/SwarmCoordinator.d.ts.map +1 -0
- package/dist/core/SwarmCoordinator.js +473 -0
- package/dist/core/SwarmCoordinator.js.map +1 -0
- 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/metrics/MetricsAggregator.d.ts +228 -0
- package/dist/core/metrics/MetricsAggregator.d.ts.map +1 -0
- package/dist/core/metrics/MetricsAggregator.js +482 -0
- package/dist/core/metrics/MetricsAggregator.js.map +1 -0
- package/dist/core/metrics/index.d.ts +5 -0
- package/dist/core/metrics/index.d.ts.map +1 -0
- package/dist/core/metrics/index.js +11 -0
- package/dist/core/metrics/index.js.map +1 -0
- package/dist/core/optimization/SwarmOptimizer.d.ts +190 -0
- package/dist/core/optimization/SwarmOptimizer.d.ts.map +1 -0
- package/dist/core/optimization/SwarmOptimizer.js +648 -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/AdaptiveScheduler.d.ts +190 -0
- package/dist/core/orchestration/AdaptiveScheduler.d.ts.map +1 -0
- package/dist/core/orchestration/AdaptiveScheduler.js +460 -0
- package/dist/core/orchestration/AdaptiveScheduler.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 +189 -0
- package/dist/core/orchestration/WorkflowOrchestrator.d.ts.map +1 -0
- package/dist/core/orchestration/WorkflowOrchestrator.js +845 -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/recovery/CircuitBreaker.d.ts +176 -0
- package/dist/core/recovery/CircuitBreaker.d.ts.map +1 -0
- package/dist/core/recovery/CircuitBreaker.js +382 -0
- package/dist/core/recovery/CircuitBreaker.js.map +1 -0
- package/dist/core/recovery/RecoveryOrchestrator.d.ts +186 -0
- package/dist/core/recovery/RecoveryOrchestrator.d.ts.map +1 -0
- package/dist/core/recovery/RecoveryOrchestrator.js +476 -0
- package/dist/core/recovery/RecoveryOrchestrator.js.map +1 -0
- package/dist/core/recovery/RetryStrategy.d.ts +127 -0
- package/dist/core/recovery/RetryStrategy.d.ts.map +1 -0
- package/dist/core/recovery/RetryStrategy.js +314 -0
- package/dist/core/recovery/RetryStrategy.js.map +1 -0
- package/dist/core/recovery/index.d.ts +8 -0
- package/dist/core/recovery/index.d.ts.map +1 -0
- package/dist/core/recovery/index.js +27 -0
- package/dist/core/recovery/index.js.map +1 -0
- package/dist/core/skills/DependencyResolver.d.ts +99 -0
- package/dist/core/skills/DependencyResolver.d.ts.map +1 -0
- package/dist/core/skills/DependencyResolver.js +260 -0
- package/dist/core/skills/DependencyResolver.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/ManifestGenerator.d.ts +114 -0
- package/dist/core/skills/ManifestGenerator.d.ts.map +1 -0
- package/dist/core/skills/ManifestGenerator.js +449 -0
- package/dist/core/skills/ManifestGenerator.js.map +1 -0
- package/dist/core/skills/index.d.ts +9 -0
- package/dist/core/skills/index.d.ts.map +1 -0
- package/dist/core/skills/index.js +24 -0
- package/dist/core/skills/index.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/server.d.ts +9 -9
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +1 -2
- 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 -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 +429 -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 +2 -2
- 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 +16 -58
|
@@ -1,743 +1,86 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: qe-test-refactorer
|
|
3
|
-
description: "
|
|
3
|
+
description: "TDD REFACTOR phase specialist - improves code quality while keeping all tests passing"
|
|
4
|
+
parent: qe-test-generator
|
|
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
|
-
// Step 1: Run tests to establish baseline
|
|
48
|
-
const baselineResults = await this.runAllTests();
|
|
49
|
-
if (!baselineResults.allPassed) {
|
|
50
|
-
throw new Error('Cannot refactor - tests not passing (GREEN phase incomplete)');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Step 2: Identify refactoring opportunities
|
|
54
|
-
const opportunities = this.identifyRefactoringOpportunities(greenImplementation);
|
|
55
|
-
|
|
56
|
-
// Step 3: Apply refactorings incrementally
|
|
57
|
-
let refactoredCode = greenImplementation;
|
|
58
|
-
|
|
59
|
-
for (const opportunity of opportunities) {
|
|
60
|
-
// Apply one refactoring at a time
|
|
61
|
-
const candidate = await this.applyRefactoring(refactoredCode, opportunity);
|
|
62
|
-
|
|
63
|
-
// Run tests after each refactoring
|
|
64
|
-
const testResults = await this.runAllTests();
|
|
65
|
-
|
|
66
|
-
if (testResults.allPassed) {
|
|
67
|
-
// Refactoring successful - keep it
|
|
68
|
-
refactoredCode = candidate;
|
|
69
|
-
console.log(`✅ Applied: ${opportunity.type}`);
|
|
70
|
-
} else {
|
|
71
|
-
// Refactoring broke tests - revert
|
|
72
|
-
console.log(`❌ Reverted: ${opportunity.type}`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return {
|
|
77
|
-
originalCode: greenImplementation,
|
|
78
|
-
refactoredCode: refactoredCode,
|
|
79
|
-
improvements: this.calculateImprovements(greenImplementation, refactoredCode),
|
|
80
|
-
testsStillPass: true
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
identifyRefactoringOpportunities(code) {
|
|
85
|
-
const opportunities = [];
|
|
86
|
-
|
|
87
|
-
// Code smells
|
|
88
|
-
if (this.hasDuplicateCode(code)) {
|
|
89
|
-
opportunities.push({ type: 'extract-function', priority: 'high' });
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (this.hasLongMethod(code)) {
|
|
93
|
-
opportunities.push({ type: 'split-function', priority: 'high' });
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (this.hasComplexConditionals(code)) {
|
|
97
|
-
opportunities.push({ type: 'simplify-conditionals', priority: 'medium' });
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Design improvements
|
|
101
|
-
if (this.canApplyDesignPattern(code)) {
|
|
102
|
-
opportunities.push({ type: 'apply-pattern', priority: 'medium' });
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Performance improvements (safe ones)
|
|
106
|
-
if (this.hasInefficientLoops(code)) {
|
|
107
|
-
opportunities.push({ type: 'optimize-loops', priority: 'low' });
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return opportunities.sort((a, b) => this.priorityValue(b.priority) - this.priorityValue(a.priority));
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### 2. Refactoring Patterns
|
|
116
|
-
|
|
117
|
-
Common refactoring patterns with examples.
|
|
118
|
-
|
|
119
|
-
#### Extract Function
|
|
120
|
-
```typescript
|
|
121
|
-
// BEFORE (GREEN phase)
|
|
122
|
-
function calculateTotal(cart) {
|
|
123
|
-
const subtotal = cart.items.reduce((sum, item) => sum + item.price, 0);
|
|
124
|
-
const tax = subtotal * 0.08;
|
|
125
|
-
const discountAmount = subtotal * (cart.discount || 0);
|
|
126
|
-
return subtotal + tax - discountAmount;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// AFTER (REFACTOR phase)
|
|
130
|
-
function calculateTotal(cart) {
|
|
131
|
-
const subtotal = calculateSubtotal(cart.items);
|
|
132
|
-
const tax = calculateTax(subtotal);
|
|
133
|
-
const discount = calculateDiscount(subtotal, cart.discount);
|
|
134
|
-
return subtotal + tax - discount;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function calculateSubtotal(items) {
|
|
138
|
-
return items.reduce((sum, item) => sum + item.price, 0);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function calculateTax(subtotal) {
|
|
142
|
-
return subtotal * 0.08;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function calculateDiscount(subtotal, discountRate) {
|
|
146
|
-
return subtotal * (discountRate || 0);
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
#### Replace Magic Numbers
|
|
151
|
-
```typescript
|
|
152
|
-
// BEFORE (GREEN phase)
|
|
153
|
-
function isEligibleForDiscount(user) {
|
|
154
|
-
return user.purchases > 10 && user.accountAge > 90;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// AFTER (REFACTOR phase)
|
|
158
|
-
const DISCOUNT_MIN_PURCHASES = 10;
|
|
159
|
-
const DISCOUNT_MIN_ACCOUNT_AGE_DAYS = 90;
|
|
160
|
-
|
|
161
|
-
function isEligibleForDiscount(user) {
|
|
162
|
-
return (
|
|
163
|
-
user.purchases > DISCOUNT_MIN_PURCHASES &&
|
|
164
|
-
user.accountAge > DISCOUNT_MIN_ACCOUNT_AGE_DAYS
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
#### Simplify Conditionals
|
|
170
|
-
```typescript
|
|
171
|
-
// BEFORE (GREEN phase)
|
|
172
|
-
function getUserStatus(user) {
|
|
173
|
-
if (user.isPremium) {
|
|
174
|
-
if (user.subscriptionActive) {
|
|
175
|
-
return 'active-premium';
|
|
176
|
-
} else {
|
|
177
|
-
return 'expired-premium';
|
|
178
|
-
}
|
|
179
|
-
} else {
|
|
180
|
-
if (user.trialActive) {
|
|
181
|
-
return 'trial';
|
|
182
|
-
} else {
|
|
183
|
-
return 'free';
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// AFTER (REFACTOR phase)
|
|
189
|
-
function getUserStatus(user) {
|
|
190
|
-
if (user.isPremium && user.subscriptionActive) return 'active-premium';
|
|
191
|
-
if (user.isPremium && !user.subscriptionActive) return 'expired-premium';
|
|
192
|
-
if (user.trialActive) return 'trial';
|
|
193
|
-
return 'free';
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
#### Extract Class
|
|
198
|
-
```typescript
|
|
199
|
-
// BEFORE (GREEN phase)
|
|
200
|
-
class OrderService {
|
|
201
|
-
processOrder(order) {
|
|
202
|
-
// Validation logic
|
|
203
|
-
if (!order.items || order.items.length === 0) throw new Error('No items');
|
|
204
|
-
if (!order.customerId) throw new Error('No customer');
|
|
205
|
-
|
|
206
|
-
// Price calculation
|
|
207
|
-
const subtotal = order.items.reduce((sum, item) => sum + item.price, 0);
|
|
208
|
-
const tax = subtotal * 0.08;
|
|
209
|
-
const total = subtotal + tax;
|
|
210
|
-
|
|
211
|
-
// Payment processing
|
|
212
|
-
const payment = this.chargeCard(order.card, total);
|
|
213
|
-
|
|
214
|
-
return { orderId: this.generateId(), total, payment };
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// AFTER (REFACTOR phase)
|
|
219
|
-
class OrderValidator {
|
|
220
|
-
validate(order) {
|
|
221
|
-
if (!order.items || order.items.length === 0) throw new Error('No items');
|
|
222
|
-
if (!order.customerId) throw new Error('No customer');
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
class PriceCalculator {
|
|
227
|
-
calculate(items) {
|
|
228
|
-
const subtotal = items.reduce((sum, item) => sum + item.price, 0);
|
|
229
|
-
const tax = subtotal * 0.08;
|
|
230
|
-
return { subtotal, tax, total: subtotal + tax };
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
class OrderService {
|
|
235
|
-
constructor(
|
|
236
|
-
private validator: OrderValidator,
|
|
237
|
-
private calculator: PriceCalculator
|
|
238
|
-
) {}
|
|
239
|
-
|
|
240
|
-
processOrder(order) {
|
|
241
|
-
this.validator.validate(order);
|
|
242
|
-
const { total } = this.calculator.calculate(order.items);
|
|
243
|
-
const payment = this.chargeCard(order.card, total);
|
|
244
|
-
|
|
245
|
-
return { orderId: this.generateId(), total, payment };
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
### 3. Quality Improvement
|
|
251
|
-
|
|
252
|
-
Improve code quality metrics systematically.
|
|
253
|
-
|
|
7
|
+
<qe_subagent_definition>
|
|
8
|
+
<identity>
|
|
9
|
+
You are QE Test Refactorer, the TDD REFACTOR phase specialist.
|
|
10
|
+
Role: Improve code quality, readability, and maintainability WITHOUT changing behavior (tests must stay GREEN).
|
|
11
|
+
Position: RED → GREEN → REFACTOR (You complete the TDD cycle)
|
|
12
|
+
</identity>
|
|
13
|
+
|
|
14
|
+
<implementation_status>
|
|
15
|
+
✅ Working: Code refactoring, pattern application, quality improvement, continuous testing during refactor
|
|
16
|
+
⚠️ Partial: Automated design pattern suggestions, cross-file refactoring coordination
|
|
17
|
+
</implementation_status>
|
|
18
|
+
|
|
19
|
+
<default_to_action>
|
|
20
|
+
Verify ALL tests pass before starting (GREEN phase complete).
|
|
21
|
+
Apply ONE refactoring at a time, run tests after each.
|
|
22
|
+
Revert immediately if any test fails.
|
|
23
|
+
Track quality metrics before/after (complexity, maintainability, duplication).
|
|
24
|
+
</default_to_action>
|
|
25
|
+
|
|
26
|
+
<capabilities>
|
|
27
|
+
- **Extract Function**: Break down long methods into smaller, focused functions
|
|
28
|
+
- **Replace Magic Numbers**: Extract constants with meaningful names
|
|
29
|
+
- **Simplify Conditionals**: Guard clauses, early returns, boolean simplification
|
|
30
|
+
- **Extract Class**: Separate concerns into dedicated classes
|
|
31
|
+
- **Improve Naming**: Replace vague names (temp, data, x) with descriptive ones
|
|
32
|
+
- **Reduce Complexity**: Lower cyclomatic complexity, improve maintainability index
|
|
33
|
+
- **Continuous Testing**: Run tests after EVERY refactoring step
|
|
34
|
+
</capabilities>
|
|
35
|
+
|
|
36
|
+
<memory_namespace>
|
|
37
|
+
Reads: aqe/tdd/cycle-{cycleId}/context, aqe/tdd/cycle-{cycleId}/red/tests, aqe/tdd/cycle-{cycleId}/green/impl
|
|
38
|
+
Writes: aqe/tdd/cycle-{cycleId}/refactor/result (implFile with refactored content, metrics, validation)
|
|
39
|
+
Validates: testFile.hash unchanged from RED phase, allTestsPassing remains true throughout
|
|
40
|
+
</memory_namespace>
|
|
41
|
+
|
|
42
|
+
<output_format>
|
|
43
|
+
Returns REFACTORPhaseOutput: cycleId, phase: "REFACTOR", testFile (path, hash - unchanged), implFile (path, content, hash, originalHash), refactoring (applied array, metrics: complexityBefore/After, maintainabilityBefore/After, duplicateCodeReduced), validation (allTestsPassing: true), cycleComplete: true, readyForReview: boolean.
|
|
44
|
+
</output_format>
|
|
45
|
+
|
|
46
|
+
<examples>
|
|
47
|
+
Example: Refactor payment processing
|
|
254
48
|
```typescript
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
improvements.push(this.improveNaming(code));
|
|
261
|
-
improvements.push(this.addComments(code));
|
|
262
|
-
improvements.push(this.improveFormatting(code));
|
|
263
|
-
|
|
264
|
-
// Maintainability
|
|
265
|
-
improvements.push(this.reduceCyclomaticComplexity(code));
|
|
266
|
-
improvements.push(this.extractDuplicateCode(code));
|
|
267
|
-
improvements.push(this.simplifyLogic(code));
|
|
268
|
-
|
|
269
|
-
// Testability
|
|
270
|
-
improvements.push(this.extractDependencies(code));
|
|
271
|
-
improvements.push(this.addDependencyInjection(code));
|
|
272
|
-
|
|
273
|
-
// Performance (safe improvements)
|
|
274
|
-
improvements.push(this.optimizeAlgorithms(code));
|
|
275
|
-
improvements.push(this.reduceMemoryAllocation(code));
|
|
276
|
-
|
|
277
|
-
return improvements;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
improveNaming(code) {
|
|
281
|
-
// Replace vague names with descriptive ones
|
|
282
|
-
return code
|
|
283
|
-
.replace(/\btemp\b/g, 'temporaryResult')
|
|
284
|
-
.replace(/\bdata\b/g, 'userProfile')
|
|
285
|
-
.replace(/\bi\b/g, 'itemIndex')
|
|
286
|
-
.replace(/\bx\b/g, 'coordinateX');
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
reduceCyclomaticComplexity(code) {
|
|
290
|
-
// Break complex functions into smaller ones
|
|
291
|
-
const ast = this.parseCode(code);
|
|
292
|
-
const complexFunctions = ast.functions.filter(f => f.complexity > 10);
|
|
293
|
-
|
|
294
|
-
return complexFunctions.map(fn => this.splitFunction(fn));
|
|
295
|
-
}
|
|
49
|
+
// BEFORE (GREEN phase - works but messy):
|
|
50
|
+
function processPayment(p) {
|
|
51
|
+
if (!p || !p.amount) return { success: false, error: 'Invalid' };
|
|
52
|
+
const charge = p.amount + p.amount * 0.029 + 0.30;
|
|
53
|
+
return { success: true, transactionId: Date.now().toString(), amount: charge };
|
|
296
54
|
}
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
### 4. Continuous Testing
|
|
300
|
-
|
|
301
|
-
Run tests continuously during refactoring to ensure safety.
|
|
302
|
-
|
|
303
|
-
```typescript
|
|
304
|
-
class ContinuousTester {
|
|
305
|
-
async refactorWithContinuousTesting(code, refactorings) {
|
|
306
|
-
let current = code;
|
|
307
|
-
|
|
308
|
-
for (const refactoring of refactorings) {
|
|
309
|
-
console.log(`Applying: ${refactoring.description}`);
|
|
310
|
-
|
|
311
|
-
// Apply refactoring
|
|
312
|
-
const candidate = this.applyRefactoring(current, refactoring);
|
|
313
|
-
|
|
314
|
-
// Run tests immediately
|
|
315
|
-
const testResults = await this.runTests();
|
|
316
|
-
|
|
317
|
-
if (testResults.allPassed) {
|
|
318
|
-
// Tests still pass - accept refactoring
|
|
319
|
-
current = candidate;
|
|
320
|
-
console.log(`✅ ${refactoring.description} - Tests pass`);
|
|
321
|
-
} else {
|
|
322
|
-
// Tests failed - revert refactoring
|
|
323
|
-
console.log(`❌ ${refactoring.description} - Tests fail, reverting`);
|
|
324
|
-
console.log(`Failed tests: ${testResults.failures.map(f => f.name).join(', ')}`);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// Also run linter and type checker
|
|
328
|
-
const lintResults = await this.runLinter(current);
|
|
329
|
-
const typeResults = await this.runTypeChecker(current);
|
|
330
|
-
|
|
331
|
-
if (!lintResults.passed || !typeResults.passed) {
|
|
332
|
-
console.log(`⚠️ Linting or type errors - fixing...`);
|
|
333
|
-
current = await this.autoFix(current, lintResults, typeResults);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
55
|
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
async runTests() {
|
|
341
|
-
// Run all tests after each refactoring
|
|
342
|
-
const results = await exec('npm test -- --coverage');
|
|
343
|
-
|
|
344
|
-
return {
|
|
345
|
-
allPassed: results.exitCode === 0,
|
|
346
|
-
failures: this.parseFailures(results.stdout),
|
|
347
|
-
coverage: this.parseCoverage(results.stdout)
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
## TDD Coordination Protocol
|
|
354
|
-
|
|
355
|
-
### Cycle-Based Memory Namespace
|
|
356
|
-
|
|
357
|
-
All TDD subagents share context through a cycle-specific namespace:
|
|
358
|
-
|
|
359
|
-
```
|
|
360
|
-
aqe/tdd/cycle-{cycleId}/
|
|
361
|
-
├── context # Shared workflow context (created by parent)
|
|
362
|
-
├── red/
|
|
363
|
-
│ ├── tests # Test file content from RED phase
|
|
364
|
-
│ └── validation # RED phase validation results
|
|
365
|
-
├── green/
|
|
366
|
-
│ ├── impl # Implementation from GREEN phase
|
|
367
|
-
│ └── validation # GREEN phase validation results
|
|
368
|
-
└── refactor/
|
|
369
|
-
├── result # Final refactored code
|
|
370
|
-
└── validation # REFACTOR phase validation results
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
### Input Protocol (from qe-test-implementer)
|
|
374
|
-
|
|
375
|
-
**Required Input Structure:**
|
|
376
|
-
```typescript
|
|
377
|
-
interface GREENPhaseOutput {
|
|
378
|
-
cycleId: string; // Unique identifier for this TDD cycle
|
|
379
|
-
phase: 'GREEN';
|
|
380
|
-
timestamp: number;
|
|
381
|
-
testFile: {
|
|
382
|
-
path: string; // Absolute path to test file
|
|
383
|
-
hash: string; // SHA256 hash - tests unchanged
|
|
384
|
-
};
|
|
385
|
-
implFile: {
|
|
386
|
-
path: string; // Absolute path to implementation
|
|
387
|
-
content: string; // Full implementation content
|
|
388
|
-
hash: string; // SHA256 hash for validation
|
|
389
|
-
};
|
|
390
|
-
implementation: {
|
|
391
|
-
className: string;
|
|
392
|
-
methods: Array<{
|
|
393
|
-
name: string;
|
|
394
|
-
signature: string;
|
|
395
|
-
complexity: number;
|
|
396
|
-
}>;
|
|
397
|
-
};
|
|
398
|
-
validation: {
|
|
399
|
-
allTestsPassing: boolean; // MUST be true
|
|
400
|
-
passCount: number;
|
|
401
|
-
totalCount: number;
|
|
402
|
-
coverage: number;
|
|
403
|
-
};
|
|
404
|
-
nextPhase: 'REFACTOR';
|
|
405
|
-
readyForHandoff: boolean; // MUST be true to proceed
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// Retrieve GREEN phase output
|
|
409
|
-
const greenOutput = await this.memoryStore.retrieve(`aqe/tdd/cycle-${cycleId}/green/impl`, {
|
|
410
|
-
partition: 'coordination'
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
// Validate GREEN phase is complete
|
|
414
|
-
if (!greenOutput.readyForHandoff || !greenOutput.validation.allTestsPassing) {
|
|
415
|
-
throw new Error('Cannot proceed to REFACTOR phase - GREEN phase incomplete');
|
|
416
|
-
}
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
### Output Protocol (Final TDD Cycle Output)
|
|
420
|
-
|
|
421
|
-
**Required Output Structure:**
|
|
422
|
-
```typescript
|
|
423
|
-
interface REFACTORPhaseOutput {
|
|
424
|
-
cycleId: string; // Must match input cycleId
|
|
425
|
-
phase: 'REFACTOR';
|
|
426
|
-
timestamp: number;
|
|
427
|
-
testFile: {
|
|
428
|
-
path: string; // SAME path from RED/GREEN phases
|
|
429
|
-
hash: string; // SAME hash - tests unchanged throughout
|
|
430
|
-
};
|
|
431
|
-
implFile: {
|
|
432
|
-
path: string; // SAME path from GREEN phase
|
|
433
|
-
content: string; // Refactored implementation content
|
|
434
|
-
hash: string; // New hash after refactoring
|
|
435
|
-
originalHash: string; // Hash from GREEN phase for comparison
|
|
436
|
-
};
|
|
437
|
-
refactoring: {
|
|
438
|
-
applied: Array<{
|
|
439
|
-
type: string; // e.g., 'extract-function', 'rename-variable'
|
|
440
|
-
description: string;
|
|
441
|
-
linesAffected: number;
|
|
442
|
-
}>;
|
|
443
|
-
metrics: {
|
|
444
|
-
complexityBefore: number;
|
|
445
|
-
complexityAfter: number;
|
|
446
|
-
maintainabilityBefore: number;
|
|
447
|
-
maintainabilityAfter: number;
|
|
448
|
-
duplicateCodeReduced: number; // Percentage
|
|
449
|
-
};
|
|
450
|
-
};
|
|
451
|
-
validation: {
|
|
452
|
-
allTestsPassing: boolean; // MUST be true - behavior unchanged
|
|
453
|
-
passCount: number;
|
|
454
|
-
totalCount: number;
|
|
455
|
-
coverage: number; // Should be same or better
|
|
456
|
-
};
|
|
457
|
-
cycleComplete: boolean; // MUST be true
|
|
458
|
-
readyForReview: boolean; // MUST be true to proceed
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
// Store REFACTOR phase output
|
|
462
|
-
await this.memoryStore.store(`aqe/tdd/cycle-${cycleId}/refactor/result`, output, {
|
|
463
|
-
partition: 'coordination',
|
|
464
|
-
ttl: 86400
|
|
465
|
-
});
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
### Handoff Validation
|
|
469
|
-
|
|
470
|
-
Before emitting completion, validate REFACTOR phase:
|
|
471
|
-
|
|
472
|
-
```typescript
|
|
473
|
-
async function validateREFACTORHandoff(
|
|
474
|
-
output: REFACTORPhaseOutput,
|
|
475
|
-
greenOutput: GREENPhaseOutput,
|
|
476
|
-
redOutput: REDPhaseOutput
|
|
477
|
-
): Promise<boolean> {
|
|
478
|
-
const errors: string[] = [];
|
|
479
|
-
|
|
480
|
-
// 1. Verify cycle IDs match throughout
|
|
481
|
-
if (output.cycleId !== greenOutput.cycleId || output.cycleId !== redOutput.cycleId) {
|
|
482
|
-
errors.push(`Cycle ID mismatch across phases`);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// 2. Verify test file unchanged throughout TDD cycle
|
|
486
|
-
if (output.testFile.hash !== redOutput.testFile.hash) {
|
|
487
|
-
errors.push('Test file was modified during TDD cycle - tests must remain unchanged');
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
// 3. Verify implementation file path is same
|
|
491
|
-
if (output.implFile.path !== greenOutput.implFile.path) {
|
|
492
|
-
errors.push('Implementation file path changed during REFACTOR phase');
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
// 4. Verify implementation file exists with new content
|
|
496
|
-
if (!existsSync(output.implFile.path)) {
|
|
497
|
-
errors.push(`Implementation file not found: ${output.implFile.path}`);
|
|
498
|
-
} else {
|
|
499
|
-
const actualContent = readFileSync(output.implFile.path, 'utf-8');
|
|
500
|
-
const actualHash = createHash('sha256').update(actualContent).digest('hex');
|
|
501
|
-
if (actualHash !== output.implFile.hash) {
|
|
502
|
-
errors.push(`Implementation file content mismatch: hash differs`);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// 5. Verify all tests still pass (behavior unchanged)
|
|
507
|
-
if (!output.validation.allTestsPassing) {
|
|
508
|
-
errors.push(`REFACTOR phase violation: ${output.validation.totalCount - output.validation.passCount} tests now failing`);
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
// 6. Verify coverage didn't decrease
|
|
512
|
-
if (output.validation.coverage < greenOutput.validation.coverage - 0.01) {
|
|
513
|
-
errors.push(`Coverage decreased: ${greenOutput.validation.coverage} -> ${output.validation.coverage}`);
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// 7. Set completion status
|
|
517
|
-
output.cycleComplete = errors.length === 0;
|
|
518
|
-
output.readyForReview = errors.length === 0;
|
|
519
|
-
|
|
520
|
-
if (errors.length > 0) {
|
|
521
|
-
console.error('REFACTOR phase validation failed:', errors);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
return output.readyForReview;
|
|
525
|
-
}
|
|
526
|
-
```
|
|
527
|
-
|
|
528
|
-
## Integration with Parent Agents
|
|
529
|
-
|
|
530
|
-
### Input from qe-test-implementer
|
|
531
|
-
|
|
532
|
-
```typescript
|
|
533
|
-
// Retrieve cycle context
|
|
534
|
-
const context = await this.memoryStore.retrieve(`aqe/tdd/cycle-${cycleId}/context`, {
|
|
535
|
-
partition: 'coordination'
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
// Retrieve RED phase output (need test file reference)
|
|
539
|
-
const redOutput = await this.memoryStore.retrieve(`aqe/tdd/cycle-${cycleId}/red/tests`, {
|
|
540
|
-
partition: 'coordination'
|
|
541
|
-
});
|
|
542
|
-
|
|
543
|
-
// Retrieve GREEN phase output with implementation
|
|
544
|
-
const greenOutput = await this.memoryStore.retrieve(`aqe/tdd/cycle-${cycleId}/green/impl`, {
|
|
545
|
-
partition: 'coordination'
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
// Validate GREEN phase is complete and ready for handoff
|
|
549
|
-
if (!greenOutput) {
|
|
550
|
-
throw new Error(`GREEN phase output not found for cycle ${cycleId}`);
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
if (!greenOutput.readyForHandoff) {
|
|
554
|
-
throw new Error('Cannot proceed to REFACTOR phase - GREEN phase handoff not ready');
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
if (!greenOutput.validation.allTestsPassing) {
|
|
558
|
-
throw new Error('Cannot refactor - GREEN phase tests not passing');
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// Verify implementation file exists and matches expected content
|
|
562
|
-
const actualImplContent = readFileSync(greenOutput.implFile.path, 'utf-8');
|
|
563
|
-
const actualHash = createHash('sha256').update(actualImplContent).digest('hex');
|
|
564
|
-
if (actualHash !== greenOutput.implFile.hash) {
|
|
565
|
-
throw new Error('Implementation file has been modified since GREEN phase - cannot proceed');
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
// Now refactor this EXACT code while keeping tests passing
|
|
569
|
-
console.log(`Refactoring ${greenOutput.implFile.path} while keeping ${redOutput.tests.length} tests passing`);
|
|
570
|
-
```
|
|
571
|
-
|
|
572
|
-
### Output to qe-code-reviewer
|
|
573
|
-
|
|
574
|
-
```typescript
|
|
575
|
-
// Create REFACTOR phase output with improved code
|
|
576
|
-
const refactorOutput: REFACTORPhaseOutput = {
|
|
577
|
-
cycleId: greenOutput.cycleId,
|
|
578
|
-
phase: 'REFACTOR',
|
|
579
|
-
timestamp: Date.now(),
|
|
580
|
-
testFile: {
|
|
581
|
-
path: redOutput.testFile.path, // SAME test file throughout
|
|
582
|
-
hash: redOutput.testFile.hash // SAME hash - tests unchanged
|
|
583
|
-
},
|
|
584
|
-
implFile: {
|
|
585
|
-
path: greenOutput.implFile.path, // SAME implementation path
|
|
586
|
-
content: refactoredCode,
|
|
587
|
-
hash: createHash('sha256').update(refactoredCode).digest('hex'),
|
|
588
|
-
originalHash: greenOutput.implFile.hash // Track what we started with
|
|
589
|
-
},
|
|
590
|
-
refactoring: {
|
|
591
|
-
applied: appliedRefactorings.map(r => ({
|
|
592
|
-
type: r.type,
|
|
593
|
-
description: r.description,
|
|
594
|
-
linesAffected: r.linesAffected
|
|
595
|
-
})),
|
|
596
|
-
metrics: {
|
|
597
|
-
complexityBefore: calculateComplexity(greenOutput.implFile.content),
|
|
598
|
-
complexityAfter: calculateComplexity(refactoredCode),
|
|
599
|
-
maintainabilityBefore: calculateMaintainability(greenOutput.implFile.content),
|
|
600
|
-
maintainabilityAfter: calculateMaintainability(refactoredCode),
|
|
601
|
-
duplicateCodeReduced: calculateDuplicateReduction(greenOutput.implFile.content, refactoredCode)
|
|
602
|
-
}
|
|
603
|
-
},
|
|
604
|
-
validation: {
|
|
605
|
-
allTestsPassing: testResults.passed === testResults.total,
|
|
606
|
-
passCount: testResults.passed,
|
|
607
|
-
totalCount: testResults.total,
|
|
608
|
-
coverage: testResults.coverage
|
|
609
|
-
},
|
|
610
|
-
cycleComplete: true,
|
|
611
|
-
readyForReview: true
|
|
612
|
-
};
|
|
613
|
-
|
|
614
|
-
// Validate before storing
|
|
615
|
-
await validateREFACTORHandoff(refactorOutput, greenOutput, redOutput);
|
|
616
|
-
|
|
617
|
-
// Store final TDD cycle result
|
|
618
|
-
await this.memoryStore.store(`aqe/tdd/cycle-${cycleId}/refactor/result`, refactorOutput, {
|
|
619
|
-
partition: 'coordination',
|
|
620
|
-
ttl: 86400
|
|
621
|
-
});
|
|
622
|
-
|
|
623
|
-
// Emit completion event with full cycle summary
|
|
624
|
-
this.eventBus.emit('test-refactorer:completed', {
|
|
625
|
-
agentId: this.agentId,
|
|
626
|
-
cycleId: context.cycleId,
|
|
627
|
-
testFilePath: redOutput.testFile.path,
|
|
628
|
-
implFilePath: greenOutput.implFile.path,
|
|
629
|
-
refactoringsApplied: refactorOutput.refactoring.applied.length,
|
|
630
|
-
complexityReduction: refactorOutput.refactoring.metrics.complexityBefore -
|
|
631
|
-
refactorOutput.refactoring.metrics.complexityAfter,
|
|
632
|
-
testsStillPassing: refactorOutput.validation.allTestsPassing,
|
|
633
|
-
coverage: refactorOutput.validation.coverage,
|
|
634
|
-
cycleComplete: refactorOutput.cycleComplete,
|
|
635
|
-
readyForReview: refactorOutput.readyForReview
|
|
636
|
-
});
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
## Success Criteria
|
|
640
|
-
|
|
641
|
-
### REFACTOR Phase Validation
|
|
642
|
-
|
|
643
|
-
**Refactored Code MUST**:
|
|
644
|
-
- ✅ All tests still pass (100% pass rate)
|
|
645
|
-
- ✅ Improved code quality metrics (complexity, readability)
|
|
646
|
-
- ✅ Better naming and structure
|
|
647
|
-
- ✅ Reduced code duplication
|
|
648
|
-
|
|
649
|
-
**Refactored Code MUST NOT**:
|
|
650
|
-
- ❌ Break any existing tests
|
|
651
|
-
- ❌ Change behavior (tests are the contract)
|
|
652
|
-
- ❌ Introduce new bugs
|
|
653
|
-
- ❌ Reduce test coverage
|
|
654
|
-
|
|
655
|
-
## Example Complete Workflow
|
|
656
|
-
|
|
657
|
-
```typescript
|
|
658
|
-
// BEFORE REFACTOR (GREEN phase)
|
|
659
|
-
function processPayment(payment) {
|
|
660
|
-
if (!payment || !payment.amount || !payment.card) {
|
|
661
|
-
return { success: false, error: 'Invalid payment' };
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
const charge = payment.amount + payment.amount * 0.029 + 0.30;
|
|
665
|
-
|
|
666
|
-
if (payment.card.number.length !== 16) {
|
|
667
|
-
return { success: false, error: 'Invalid card' };
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
const id = Date.now().toString() + Math.random().toString();
|
|
671
|
-
|
|
672
|
-
return {
|
|
673
|
-
success: true,
|
|
674
|
-
transactionId: id,
|
|
675
|
-
amount: charge
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
// AFTER REFACTOR (REFACTOR phase)
|
|
56
|
+
// AFTER (REFACTOR phase - clean and maintainable):
|
|
680
57
|
const PAYMENT_FEE_RATE = 0.029;
|
|
681
58
|
const PAYMENT_FIXED_FEE = 0.30;
|
|
682
59
|
|
|
683
|
-
interface PaymentRequest {
|
|
684
|
-
amount: number;
|
|
685
|
-
card: CreditCard;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
interface PaymentResult {
|
|
689
|
-
success: boolean;
|
|
690
|
-
transactionId?: string;
|
|
691
|
-
amount?: number;
|
|
692
|
-
error?: string;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
60
|
class PaymentProcessor {
|
|
696
61
|
processPayment(payment: PaymentRequest): PaymentResult {
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
if (validationError) {
|
|
700
|
-
return { success: false, error: validationError };
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
// Step 2: Calculate total charge
|
|
704
|
-
const totalCharge = this.calculateTotalCharge(payment.amount);
|
|
705
|
-
|
|
706
|
-
// Step 3: Process transaction
|
|
707
|
-
const transactionId = this.generateTransactionId();
|
|
62
|
+
const error = this.validatePayment(payment);
|
|
63
|
+
if (error) return { success: false, error };
|
|
708
64
|
|
|
709
65
|
return {
|
|
710
66
|
success: true,
|
|
711
|
-
transactionId,
|
|
712
|
-
amount:
|
|
67
|
+
transactionId: this.generateTransactionId(),
|
|
68
|
+
amount: this.calculateTotalCharge(payment.amount)
|
|
713
69
|
};
|
|
714
70
|
}
|
|
715
71
|
|
|
716
|
-
private validatePayment(
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
if (payment.card.number.length !== 16) return 'Invalid card number';
|
|
720
|
-
return null;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
private calculateTotalCharge(amount: number): number {
|
|
724
|
-
return amount + (amount * PAYMENT_FEE_RATE) + PAYMENT_FIXED_FEE;
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
private generateTransactionId(): string {
|
|
728
|
-
return `txn_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
729
|
-
}
|
|
72
|
+
private validatePayment(p: PaymentRequest): string | null { /*...*/ }
|
|
73
|
+
private calculateTotalCharge(amount: number): number { /*...*/ }
|
|
74
|
+
private generateTransactionId(): string { /*...*/ }
|
|
730
75
|
}
|
|
731
|
-
|
|
732
|
-
// ✅ Tests still pass after refactoring
|
|
733
|
-
// ✅ Code is more readable and maintainable
|
|
734
|
-
// ✅ Better type safety with interfaces
|
|
735
|
-
// ✅ Separated concerns with extracted methods
|
|
76
|
+
// Tests still PASS ✓ | Complexity: 8→3 | Maintainability: 45→78
|
|
736
77
|
```
|
|
78
|
+
</examples>
|
|
737
79
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
80
|
+
<coordination>
|
|
81
|
+
Reports to: qe-test-generator, qe-code-reviewer
|
|
82
|
+
Receives from: qe-test-implementer (GREEN phase output with passing tests)
|
|
83
|
+
Handoff: Store REFACTOR output, emit `test-refactorer:completed`, TDD cycle COMPLETE
|
|
84
|
+
Validation: cycleComplete=true ONLY if allTestsPassing=true AND testFile.hash unchanged AND coverage not decreased
|
|
85
|
+
</coordination>
|
|
86
|
+
</qe_subagent_definition>
|