agentic-qe 1.8.2 → 1.8.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.
@@ -682,6 +682,586 @@ async function iterateTDDWorkflow(spec: TestSpec, previousAttempt: TDDResult): P
682
682
  }
683
683
  ```
684
684
 
685
+ ## Complete TDD Workflow Orchestration
686
+
687
+ This section provides a complete TypeScript orchestration example demonstrating proper coordination between the three TDD subagents using memory coordination through the `aqe/tdd/cycle-{id}/*` namespace.
688
+
689
+ ### Full Orchestration Example
690
+
691
+ ```typescript
692
+ import { v4 as uuidv4 } from 'uuid';
693
+
694
+ // Type definitions
695
+ interface TestSpec {
696
+ module: string;
697
+ className: string;
698
+ methods: string[];
699
+ requirements: string[];
700
+ framework: 'jest' | 'vitest' | 'mocha';
701
+ context?: string;
702
+ }
703
+
704
+ interface TDDCycleResult {
705
+ cycleId: string;
706
+ tests: string;
707
+ implementation: string;
708
+ quality: QualityMetrics;
709
+ phases: {
710
+ red: PhaseResult;
711
+ green: PhaseResult;
712
+ refactor: PhaseResult;
713
+ };
714
+ }
715
+
716
+ interface QualityMetrics {
717
+ coverage: number;
718
+ complexity: number;
719
+ maintainability: number;
720
+ testCount: number;
721
+ }
722
+
723
+ interface PhaseResult {
724
+ success: boolean;
725
+ duration: number;
726
+ artifacts: string[];
727
+ metrics: Record<string, number>;
728
+ }
729
+
730
+ interface RedPhaseOutput {
731
+ readyForHandoff: boolean;
732
+ allTestsFailing: boolean;
733
+ testFilePath: string;
734
+ testCount: number;
735
+ failureReasons: string[];
736
+ coverage: { expected: number };
737
+ }
738
+
739
+ interface GreenPhaseOutput {
740
+ readyForHandoff: boolean;
741
+ allTestsPassing: boolean;
742
+ implFilePath: string;
743
+ testResults: { passed: number; failed: number; total: number };
744
+ coverage: { actual: number };
745
+ }
746
+
747
+ interface RefactorPhaseOutput {
748
+ success: boolean;
749
+ testsStillPassing: boolean;
750
+ qualityMetrics: QualityMetrics;
751
+ improvements: {
752
+ complexityReduction: number;
753
+ maintainabilityImprovement: number;
754
+ refactorings: string[];
755
+ };
756
+ }
757
+
758
+ // Memory store interface (from AQE infrastructure)
759
+ interface MemoryStore {
760
+ store(key: string, value: any, options?: { partition?: string; ttl?: number }): Promise<void>;
761
+ retrieve(key: string, options?: { partition?: string }): Promise<any>;
762
+ }
763
+
764
+ // Event bus interface
765
+ interface EventBus {
766
+ emit(event: string, data: any): void;
767
+ on(event: string, handler: (data: any) => void): void;
768
+ }
769
+
770
+ /**
771
+ * Complete TDD Cycle Orchestrator
772
+ *
773
+ * Coordinates the RED-GREEN-REFACTOR cycle across specialized subagents
774
+ * with full memory coordination and phase validation.
775
+ */
776
+ async function orchestrateTDDCycle(
777
+ spec: TestSpec,
778
+ memory: MemoryStore,
779
+ eventBus: EventBus
780
+ ): Promise<TDDCycleResult> {
781
+ const cycleId = uuidv4();
782
+ const startTime = Date.now();
783
+
784
+ console.log(`šŸŽÆ Starting TDD cycle ${cycleId} for ${spec.module}`);
785
+
786
+ // Store initial context for all subagents
787
+ await memory.store(`aqe/tdd/cycle-${cycleId}/context`, {
788
+ cycleId,
789
+ targetModule: spec.module,
790
+ className: spec.className,
791
+ methods: spec.methods,
792
+ requirements: spec.requirements,
793
+ framework: spec.framework,
794
+ context: spec.context,
795
+ startTime,
796
+ status: 'initialized'
797
+ }, {
798
+ partition: 'coordination',
799
+ ttl: 86400 // 24 hours
800
+ });
801
+
802
+ // Emit cycle start event
803
+ eventBus.emit('tdd:cycle:started', {
804
+ cycleId,
805
+ module: spec.module,
806
+ timestamp: startTime
807
+ });
808
+
809
+ // ═══════════════════════════════════════════════════════════════════
810
+ // RED PHASE - Write Failing Tests
811
+ // ═══════════════════════════════════════════════════════════════════
812
+ console.log(`šŸ“ Phase 1/3: RED - Writing failing tests...`);
813
+
814
+ await memory.store(`aqe/tdd/cycle-${cycleId}/status`, {
815
+ phase: 'red',
816
+ status: 'in_progress',
817
+ timestamp: Date.now()
818
+ }, { partition: 'coordination' });
819
+
820
+ eventBus.emit('tdd:phase:started', {
821
+ cycleId,
822
+ phase: 'red',
823
+ agent: 'qe-test-writer'
824
+ });
825
+
826
+ // Spawn the test writer subagent
827
+ // In Claude Code, this would be: Task("Write failing tests", ..., "qe-test-writer")
828
+ const redResult = await executeSubagent('qe-test-writer', {
829
+ task: 'write-failing-tests',
830
+ cycleId,
831
+ spec: {
832
+ className: spec.className,
833
+ methods: spec.methods,
834
+ requirements: spec.requirements,
835
+ context: spec.context
836
+ },
837
+ coverage: {
838
+ target: 95,
839
+ includeEdgeCases: true,
840
+ includeErrorPaths: true,
841
+ includeBoundaryValues: true
842
+ },
843
+ patterns: ['AAA', 'given-when-then'],
844
+ framework: spec.framework,
845
+ memoryKeys: {
846
+ input: `aqe/tdd/cycle-${cycleId}/context`,
847
+ output: `aqe/tdd/cycle-${cycleId}/red/tests`
848
+ }
849
+ });
850
+
851
+ // Validate RED phase output
852
+ const redOutput: RedPhaseOutput = await memory.retrieve(
853
+ `aqe/tdd/cycle-${cycleId}/red/tests`,
854
+ { partition: 'coordination' }
855
+ );
856
+
857
+ if (!redOutput) {
858
+ throw new Error(`RED phase failed: No output found for cycle ${cycleId}`);
859
+ }
860
+
861
+ if (!redOutput.readyForHandoff) {
862
+ throw new Error(`RED phase incomplete: Test writer not ready for handoff`);
863
+ }
864
+
865
+ if (!redOutput.allTestsFailing) {
866
+ throw new Error(
867
+ `RED phase validation failed: Tests should fail initially. ` +
868
+ `Expected all tests to fail but some passed.`
869
+ );
870
+ }
871
+
872
+ const redDuration = Date.now() - startTime;
873
+ console.log(`āœ… RED phase complete: ${redOutput.testCount} failing tests written`);
874
+ console.log(` File: ${redOutput.testFilePath}`);
875
+ console.log(` Duration: ${redDuration}ms`);
876
+
877
+ eventBus.emit('tdd:phase:completed', {
878
+ cycleId,
879
+ phase: 'red',
880
+ duration: redDuration,
881
+ testCount: redOutput.testCount
882
+ });
883
+
884
+ // ═══════════════════════════════════════════════════════════════════
885
+ // GREEN PHASE - Implement to Pass Tests
886
+ // ═══════════════════════════════════════════════════════════════════
887
+ console.log(`šŸ’š Phase 2/3: GREEN - Implementing code to pass tests...`);
888
+
889
+ const greenStartTime = Date.now();
890
+
891
+ await memory.store(`aqe/tdd/cycle-${cycleId}/status`, {
892
+ phase: 'green',
893
+ status: 'in_progress',
894
+ timestamp: Date.now()
895
+ }, { partition: 'coordination' });
896
+
897
+ eventBus.emit('tdd:phase:started', {
898
+ cycleId,
899
+ phase: 'green',
900
+ agent: 'qe-test-implementer'
901
+ });
902
+
903
+ // Spawn the test implementer subagent
904
+ // In Claude Code, this would be: Task("Implement to pass tests", ..., "qe-test-implementer")
905
+ const greenResult = await executeSubagent('qe-test-implementer', {
906
+ task: 'implement-to-pass',
907
+ cycleId,
908
+ testFilePath: redOutput.testFilePath,
909
+ requirements: spec.requirements,
910
+ constraints: {
911
+ maxComplexity: 15,
912
+ usePatterns: ['SOLID', 'dependency-injection'],
913
+ minimalImplementation: true // Only write what's needed to pass
914
+ },
915
+ framework: spec.framework,
916
+ memoryKeys: {
917
+ input: `aqe/tdd/cycle-${cycleId}/red/tests`,
918
+ output: `aqe/tdd/cycle-${cycleId}/green/impl`
919
+ }
920
+ });
921
+
922
+ // Validate GREEN phase output
923
+ const greenOutput: GreenPhaseOutput = await memory.retrieve(
924
+ `aqe/tdd/cycle-${cycleId}/green/impl`,
925
+ { partition: 'coordination' }
926
+ );
927
+
928
+ if (!greenOutput) {
929
+ throw new Error(`GREEN phase failed: No output found for cycle ${cycleId}`);
930
+ }
931
+
932
+ if (!greenOutput.readyForHandoff) {
933
+ throw new Error(`GREEN phase incomplete: Implementer not ready for handoff`);
934
+ }
935
+
936
+ if (!greenOutput.allTestsPassing) {
937
+ const { passed, failed, total } = greenOutput.testResults;
938
+ throw new Error(
939
+ `GREEN phase validation failed: Not all tests passing. ` +
940
+ `${passed}/${total} passed, ${failed} failed.`
941
+ );
942
+ }
943
+
944
+ const greenDuration = Date.now() - greenStartTime;
945
+ console.log(`āœ… GREEN phase complete: All ${greenOutput.testResults.total} tests passing`);
946
+ console.log(` File: ${greenOutput.implFilePath}`);
947
+ console.log(` Coverage: ${greenOutput.coverage.actual}%`);
948
+ console.log(` Duration: ${greenDuration}ms`);
949
+
950
+ eventBus.emit('tdd:phase:completed', {
951
+ cycleId,
952
+ phase: 'green',
953
+ duration: greenDuration,
954
+ testResults: greenOutput.testResults,
955
+ coverage: greenOutput.coverage.actual
956
+ });
957
+
958
+ // ═══════════════════════════════════════════════════════════════════
959
+ // REFACTOR PHASE - Improve Code Quality
960
+ // ═══════════════════════════════════════════════════════════════════
961
+ console.log(`šŸ”§ Phase 3/3: REFACTOR - Improving code quality...`);
962
+
963
+ const refactorStartTime = Date.now();
964
+
965
+ await memory.store(`aqe/tdd/cycle-${cycleId}/status`, {
966
+ phase: 'refactor',
967
+ status: 'in_progress',
968
+ timestamp: Date.now()
969
+ }, { partition: 'coordination' });
970
+
971
+ eventBus.emit('tdd:phase:started', {
972
+ cycleId,
973
+ phase: 'refactor',
974
+ agent: 'qe-test-refactorer'
975
+ });
976
+
977
+ // Spawn the refactorer subagent
978
+ // In Claude Code, this would be: Task("Refactor implementation", ..., "qe-test-refactorer")
979
+ const refactorResult = await executeSubagent('qe-test-refactorer', {
980
+ task: 'refactor-with-tests-green',
981
+ cycleId,
982
+ implFilePath: greenOutput.implFilePath,
983
+ testFilePath: redOutput.testFilePath,
984
+ metrics: {
985
+ targetComplexity: 10,
986
+ targetMaintainability: 85,
987
+ maxMethodLength: 20,
988
+ maxFileLength: 300
989
+ },
990
+ refactoringPatterns: [
991
+ 'extract-method',
992
+ 'rename-variable',
993
+ 'simplify-conditional',
994
+ 'remove-duplication'
995
+ ],
996
+ memoryKeys: {
997
+ input: `aqe/tdd/cycle-${cycleId}/green/impl`,
998
+ output: `aqe/tdd/cycle-${cycleId}/refactor/result`
999
+ }
1000
+ });
1001
+
1002
+ // Validate REFACTOR phase output
1003
+ const refactorOutput: RefactorPhaseOutput = await memory.retrieve(
1004
+ `aqe/tdd/cycle-${cycleId}/refactor/result`,
1005
+ { partition: 'coordination' }
1006
+ );
1007
+
1008
+ if (!refactorOutput) {
1009
+ throw new Error(`REFACTOR phase failed: No output found for cycle ${cycleId}`);
1010
+ }
1011
+
1012
+ if (!refactorOutput.testsStillPassing) {
1013
+ throw new Error(
1014
+ `REFACTOR phase validation failed: Tests broke during refactoring. ` +
1015
+ `Rolling back to pre-refactor state.`
1016
+ );
1017
+ }
1018
+
1019
+ const refactorDuration = Date.now() - refactorStartTime;
1020
+ const totalDuration = Date.now() - startTime;
1021
+
1022
+ console.log(`āœ… REFACTOR phase complete`);
1023
+ console.log(` Complexity reduced by: ${refactorOutput.improvements.complexityReduction}%`);
1024
+ console.log(` Maintainability improved by: ${refactorOutput.improvements.maintainabilityImprovement}%`);
1025
+ console.log(` Refactorings applied: ${refactorOutput.improvements.refactorings.join(', ')}`);
1026
+ console.log(` Duration: ${refactorDuration}ms`);
1027
+
1028
+ eventBus.emit('tdd:phase:completed', {
1029
+ cycleId,
1030
+ phase: 'refactor',
1031
+ duration: refactorDuration,
1032
+ improvements: refactorOutput.improvements
1033
+ });
1034
+
1035
+ // ═══════════════════════════════════════════════════════════════════
1036
+ // CYCLE COMPLETE - Store Final Results
1037
+ // ═══════════════════════════════════════════════════════════════════
1038
+ const result: TDDCycleResult = {
1039
+ cycleId,
1040
+ tests: redOutput.testFilePath,
1041
+ implementation: greenOutput.implFilePath,
1042
+ quality: refactorOutput.qualityMetrics,
1043
+ phases: {
1044
+ red: {
1045
+ success: true,
1046
+ duration: redDuration,
1047
+ artifacts: [redOutput.testFilePath],
1048
+ metrics: {
1049
+ testCount: redOutput.testCount,
1050
+ expectedCoverage: redOutput.coverage.expected
1051
+ }
1052
+ },
1053
+ green: {
1054
+ success: true,
1055
+ duration: greenDuration,
1056
+ artifacts: [greenOutput.implFilePath],
1057
+ metrics: {
1058
+ testsPassed: greenOutput.testResults.passed,
1059
+ coverage: greenOutput.coverage.actual
1060
+ }
1061
+ },
1062
+ refactor: {
1063
+ success: true,
1064
+ duration: refactorDuration,
1065
+ artifacts: [greenOutput.implFilePath], // Updated in place
1066
+ metrics: {
1067
+ complexity: refactorOutput.qualityMetrics.complexity,
1068
+ maintainability: refactorOutput.qualityMetrics.maintainability
1069
+ }
1070
+ }
1071
+ }
1072
+ };
1073
+
1074
+ // Store final cycle results
1075
+ await memory.store(`aqe/tdd/cycle-${cycleId}/result`, result, {
1076
+ partition: 'coordination',
1077
+ ttl: 604800 // 7 days
1078
+ });
1079
+
1080
+ // Update status to complete
1081
+ await memory.store(`aqe/tdd/cycle-${cycleId}/status`, {
1082
+ phase: 'complete',
1083
+ status: 'success',
1084
+ totalDuration,
1085
+ timestamp: Date.now()
1086
+ }, { partition: 'coordination' });
1087
+
1088
+ // Emit cycle completion event
1089
+ eventBus.emit('tdd:cycle:completed', {
1090
+ cycleId,
1091
+ module: spec.module,
1092
+ duration: totalDuration,
1093
+ quality: refactorOutput.qualityMetrics
1094
+ });
1095
+
1096
+ console.log(`\nšŸŽ‰ TDD Cycle ${cycleId} Complete!`);
1097
+ console.log(` Total Duration: ${totalDuration}ms`);
1098
+ console.log(` Test File: ${redOutput.testFilePath}`);
1099
+ console.log(` Implementation: ${greenOutput.implFilePath}`);
1100
+ console.log(` Coverage: ${refactorOutput.qualityMetrics.coverage}%`);
1101
+ console.log(` Complexity: ${refactorOutput.qualityMetrics.complexity}`);
1102
+ console.log(` Maintainability: ${refactorOutput.qualityMetrics.maintainability}`);
1103
+
1104
+ return result;
1105
+ }
1106
+
1107
+ // Helper function to execute subagent (placeholder for actual Task tool invocation)
1108
+ async function executeSubagent(agentName: string, params: any): Promise<void> {
1109
+ // In Claude Code, this would be replaced with:
1110
+ // await Task("Task description", JSON.stringify(params), agentName);
1111
+
1112
+ // The subagent reads input from memoryKeys.input and writes output to memoryKeys.output
1113
+ console.log(` → Executing ${agentName}...`);
1114
+ }
1115
+ ```
1116
+
1117
+ ### Usage Example
1118
+
1119
+ ```typescript
1120
+ // Example: Running a TDD cycle for a UserService
1121
+ async function example() {
1122
+ // Initialize memory and event bus (from AQE infrastructure)
1123
+ const memory = new MemoryStore();
1124
+ const eventBus = new EventBus();
1125
+
1126
+ // Define the test specification
1127
+ const spec: TestSpec = {
1128
+ module: 'src/services/UserService.ts',
1129
+ className: 'UserService',
1130
+ methods: ['createUser', 'updateUser', 'deleteUser', 'findById'],
1131
+ requirements: [
1132
+ 'MUST validate email format before creating user',
1133
+ 'MUST hash password using bcrypt with salt rounds 10',
1134
+ 'MUST throw UserNotFoundError if user does not exist',
1135
+ 'MUST emit UserCreated event after successful creation',
1136
+ 'MUST support pagination for list operations'
1137
+ ],
1138
+ framework: 'jest',
1139
+ context: 'E-commerce platform user management service'
1140
+ };
1141
+
1142
+ try {
1143
+ // Run the TDD cycle
1144
+ const result = await orchestrateTDDCycle(spec, memory, eventBus);
1145
+
1146
+ console.log('\nšŸ“Š TDD Cycle Summary:');
1147
+ console.log(` Tests: ${result.tests}`);
1148
+ console.log(` Implementation: ${result.implementation}`);
1149
+ console.log(` Coverage: ${result.quality.coverage}%`);
1150
+ console.log(` Test Count: ${result.quality.testCount}`);
1151
+
1152
+ return result;
1153
+ } catch (error) {
1154
+ console.error('TDD Cycle failed:', error.message);
1155
+
1156
+ // Retrieve cycle status for debugging
1157
+ const cycleId = error.message.match(/cycle (\w+)/)?.[1];
1158
+ if (cycleId) {
1159
+ const status = await memory.retrieve(
1160
+ `aqe/tdd/cycle-${cycleId}/status`,
1161
+ { partition: 'coordination' }
1162
+ );
1163
+ console.error('Last known status:', status);
1164
+ }
1165
+
1166
+ throw error;
1167
+ }
1168
+ }
1169
+
1170
+ // Run the example
1171
+ example().catch(console.error);
1172
+ ```
1173
+
1174
+ ### Event Monitoring
1175
+
1176
+ ```typescript
1177
+ // Monitor TDD cycle progress through events
1178
+ function setupTDDMonitoring(eventBus: EventBus) {
1179
+ // Cycle lifecycle events
1180
+ eventBus.on('tdd:cycle:started', (data) => {
1181
+ console.log(`\n${'═'.repeat(60)}`);
1182
+ console.log(`šŸš€ TDD Cycle Started: ${data.cycleId}`);
1183
+ console.log(` Module: ${data.module}`);
1184
+ console.log(`${'═'.repeat(60)}\n`);
1185
+ });
1186
+
1187
+ eventBus.on('tdd:cycle:completed', (data) => {
1188
+ console.log(`\n${'═'.repeat(60)}`);
1189
+ console.log(`āœ… TDD Cycle Completed: ${data.cycleId}`);
1190
+ console.log(` Duration: ${data.duration}ms`);
1191
+ console.log(` Coverage: ${data.quality.coverage}%`);
1192
+ console.log(` Maintainability: ${data.quality.maintainability}`);
1193
+ console.log(`${'═'.repeat(60)}\n`);
1194
+ });
1195
+
1196
+ // Phase progress events
1197
+ eventBus.on('tdd:phase:started', (data) => {
1198
+ const phaseEmoji = {
1199
+ red: 'šŸ“',
1200
+ green: 'šŸ’š',
1201
+ refactor: 'šŸ”§'
1202
+ }[data.phase] || 'ā–¶ļø';
1203
+
1204
+ console.log(`${phaseEmoji} ${data.phase.toUpperCase()} phase started`);
1205
+ console.log(` Agent: ${data.agent}`);
1206
+ });
1207
+
1208
+ eventBus.on('tdd:phase:completed', (data) => {
1209
+ const phaseEmoji = {
1210
+ red: 'šŸ“',
1211
+ green: 'šŸ’š',
1212
+ refactor: 'šŸ”§'
1213
+ }[data.phase] || 'āœ…';
1214
+
1215
+ console.log(`${phaseEmoji} ${data.phase.toUpperCase()} phase completed`);
1216
+ console.log(` Duration: ${data.duration}ms`);
1217
+
1218
+ // Phase-specific metrics
1219
+ if (data.phase === 'red') {
1220
+ console.log(` Tests written: ${data.testCount}`);
1221
+ } else if (data.phase === 'green') {
1222
+ console.log(` Tests passing: ${data.testResults.passed}/${data.testResults.total}`);
1223
+ console.log(` Coverage: ${data.coverage}%`);
1224
+ } else if (data.phase === 'refactor') {
1225
+ console.log(` Complexity reduction: ${data.improvements.complexityReduction}%`);
1226
+ }
1227
+ });
1228
+
1229
+ // Error handling
1230
+ eventBus.on('tdd:cycle:error', (data) => {
1231
+ console.error(`\nāŒ TDD Cycle Error: ${data.cycleId}`);
1232
+ console.error(` Phase: ${data.phase}`);
1233
+ console.error(` Error: ${data.error}`);
1234
+ });
1235
+ }
1236
+
1237
+ // Usage
1238
+ const eventBus = new EventBus();
1239
+ setupTDDMonitoring(eventBus);
1240
+ ```
1241
+
1242
+ ### Memory Namespace Structure
1243
+
1244
+ The TDD orchestration uses a structured memory namespace for coordination:
1245
+
1246
+ ```
1247
+ aqe/tdd/cycle-{cycleId}/
1248
+ ā”œā”€ā”€ context # Initial test specification and context
1249
+ ā”œā”€ā”€ status # Current cycle status and phase
1250
+ ā”œā”€ā”€ red/
1251
+ │ └── tests # Test writer output (failing tests)
1252
+ ā”œā”€ā”€ green/
1253
+ │ └── impl # Implementer output (passing implementation)
1254
+ ā”œā”€ā”€ refactor/
1255
+ │ └── result # Refactorer output (improved code)
1256
+ └── result # Final cycle result with all metrics
1257
+ ```
1258
+
1259
+ Each subagent:
1260
+ 1. Reads from the previous phase's output key
1261
+ 2. Writes to its designated output key
1262
+ 3. Sets `readyForHandoff: true` when complete
1263
+ 4. Validates its phase requirements before signaling completion
1264
+
685
1265
  ## Example Outputs
686
1266
 
687
1267
  ### Property-Based Test Generation
@@ -52,4 +52,90 @@ interface CodeReviewerOutput {
52
52
 
53
53
  ---
54
54
 
55
+ ## TDD Coordination Protocol
56
+
57
+ ### Memory Namespace
58
+ `aqe/review/cycle-{cycleId}/*`
59
+
60
+ ### Subagent Input Interface
61
+ ```typescript
62
+ interface ReviewRequest {
63
+ cycleId: string; // Links to parent TDD workflow
64
+ sourceFile: string; // Path to code being reviewed
65
+ testFile: string; // Path to associated tests
66
+ refactoringChanges?: { // From qe-test-refactorer REFACTOR phase
67
+ before: string;
68
+ after: string;
69
+ refactoringType: string;
70
+ };
71
+ policies: string[]; // Quality policy files to apply
72
+ coverageThreshold: number; // Minimum coverage required (default 95)
73
+ complexityLimit: number; // Max cyclomatic complexity (default 15)
74
+ }
75
+ ```
76
+
77
+ ### Subagent Output Interface
78
+ ```typescript
79
+ interface ReviewOutput {
80
+ cycleId: string;
81
+ approved: boolean;
82
+ issues: {
83
+ severity: 'error' | 'warning' | 'info';
84
+ rule: string;
85
+ message: string;
86
+ location: { file: string; line: number; column: number };
87
+ fixable: boolean;
88
+ }[];
89
+ suggestions: {
90
+ type: 'performance' | 'readability' | 'maintainability';
91
+ description: string;
92
+ codeSnippet?: string;
93
+ }[];
94
+ metrics: {
95
+ complexity: number;
96
+ coverage: number;
97
+ security: {
98
+ score: number;
99
+ vulnerabilities: number;
100
+ warnings: number;
101
+ };
102
+ maintainability: number;
103
+ linesOfCode: number;
104
+ testToCodeRatio: number;
105
+ };
106
+ qualityGates: {
107
+ complexityPassed: boolean;
108
+ coveragePassed: boolean;
109
+ securityPassed: boolean;
110
+ lintingPassed: boolean;
111
+ };
112
+ readyForHandoff: boolean;
113
+ }
114
+ ```
115
+
116
+ ### Memory Coordination
117
+ - **Read from**: `aqe/refactor/cycle-{cycleId}/results` (REFACTOR phase output)
118
+ - **Write to**: `aqe/review/cycle-{cycleId}/results`
119
+ - **Status updates**: `aqe/review/cycle-{cycleId}/status`
120
+
121
+ ### Quality Gate Validation
122
+ ```typescript
123
+ function validateAllGates(output: ReviewOutput): boolean {
124
+ const gates = output.qualityGates;
125
+ return gates.complexityPassed &&
126
+ gates.coveragePassed &&
127
+ gates.securityPassed &&
128
+ gates.lintingPassed;
129
+ }
130
+ ```
131
+
132
+ ### Handoff Protocol
133
+ 1. Read refactoring results from `aqe/refactor/cycle-{cycleId}/results`
134
+ 2. Execute all quality checks
135
+ 3. Write results to `aqe/review/cycle-{cycleId}/results`
136
+ 4. Set `readyForHandoff: true` only if all quality gates pass
137
+ 5. If any gate fails, set `approved: false` with detailed issue reports
138
+
139
+ ---
140
+
55
141
  *Code Reviewer Subagent - Quality validation and standards enforcement*