popeye-cli 1.6.0 → 1.7.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.
Files changed (50) hide show
  1. package/README.md +139 -28
  2. package/dist/state/index.d.ts.map +1 -1
  3. package/dist/state/index.js +1 -0
  4. package/dist/state/index.js.map +1 -1
  5. package/dist/types/consensus.d.ts +3 -0
  6. package/dist/types/consensus.d.ts.map +1 -1
  7. package/dist/types/consensus.js +1 -0
  8. package/dist/types/consensus.js.map +1 -1
  9. package/dist/types/index.d.ts +1 -0
  10. package/dist/types/index.d.ts.map +1 -1
  11. package/dist/types/index.js +2 -0
  12. package/dist/types/index.js.map +1 -1
  13. package/dist/types/tester.d.ts +138 -0
  14. package/dist/types/tester.d.ts.map +1 -0
  15. package/dist/types/tester.js +110 -0
  16. package/dist/types/tester.js.map +1 -0
  17. package/dist/types/workflow.d.ts +145 -0
  18. package/dist/types/workflow.d.ts.map +1 -1
  19. package/dist/types/workflow.js +12 -0
  20. package/dist/types/workflow.js.map +1 -1
  21. package/dist/workflow/execution-mode.js +2 -2
  22. package/dist/workflow/execution-mode.js.map +1 -1
  23. package/dist/workflow/index.d.ts +1 -0
  24. package/dist/workflow/index.d.ts.map +1 -1
  25. package/dist/workflow/index.js +1 -0
  26. package/dist/workflow/index.js.map +1 -1
  27. package/dist/workflow/task-workflow.d.ts +5 -0
  28. package/dist/workflow/task-workflow.d.ts.map +1 -1
  29. package/dist/workflow/task-workflow.js +172 -6
  30. package/dist/workflow/task-workflow.js.map +1 -1
  31. package/dist/workflow/tester.d.ts +120 -0
  32. package/dist/workflow/tester.d.ts.map +1 -0
  33. package/dist/workflow/tester.js +589 -0
  34. package/dist/workflow/tester.js.map +1 -0
  35. package/dist/workflow/workflow-logger.d.ts +1 -1
  36. package/dist/workflow/workflow-logger.d.ts.map +1 -1
  37. package/dist/workflow/workflow-logger.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/state/index.ts +1 -0
  40. package/src/types/consensus.ts +3 -0
  41. package/src/types/index.ts +21 -0
  42. package/src/types/tester.ts +136 -0
  43. package/src/types/workflow.ts +26 -0
  44. package/src/workflow/execution-mode.ts +2 -2
  45. package/src/workflow/index.ts +1 -0
  46. package/src/workflow/task-workflow.ts +227 -5
  47. package/src/workflow/tester.ts +723 -0
  48. package/src/workflow/workflow-logger.ts +2 -0
  49. package/tests/types/tester.test.ts +174 -0
  50. package/tests/workflow/tester.test.ts +401 -0
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-logger.js","sourceRoot":"","sources":["../../src/workflow/workflow-logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workflow-logger.js","sourceRoot":"","sources":["../../src/workflow/workflow-logger.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "popeye-cli",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Fully autonomous code generation tool powered by Claude CLI and OpenAI consensus",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {
@@ -60,6 +60,7 @@ export async function createProject(
60
60
  consensusHistory: [],
61
61
  createdAt: now,
62
62
  updatedAt: now,
63
+ qaEnabled: true,
63
64
  };
64
65
 
65
66
  await saveState(projectDir, state);
@@ -91,6 +91,8 @@ export interface ConsensusConfig {
91
91
  additionalReviewers?: AIProvider[];
92
92
  /** Custom reviewer persona for domain-specific reviews (e.g., marketing strategist for website projects) */
93
93
  reviewerPersona?: string;
94
+ /** Consensus threshold for test plans (default: 90, lower than code plan threshold) */
95
+ testPlanThreshold?: number;
94
96
  }
95
97
 
96
98
  /**
@@ -153,6 +155,7 @@ export const ConsensusConfigSchema = z.object({
153
155
  temperature: z.number().min(0).max(2).default(0.3),
154
156
  maxTokens: z.number().min(100).max(32000).default(4096),
155
157
  reviewerPersona: z.string().optional(),
158
+ testPlanThreshold: z.number().min(0).max(100).optional(),
156
159
  });
157
160
 
158
161
  /**
@@ -80,6 +80,27 @@ export {
80
80
  type ConsensusTrackingRecord,
81
81
  } from './consensus.js';
82
82
 
83
+ // Tester (QA) types
84
+ export {
85
+ TestVerdictSchema,
86
+ TestScopeSchema,
87
+ TestCommandSchema,
88
+ TestCaseSchema,
89
+ TestPlanOutputSchema,
90
+ TestRunReviewSchema,
91
+ FixStepSchema,
92
+ TestFixPlanSchema,
93
+ type TestVerdict,
94
+ type TestScope,
95
+ type TestCommand,
96
+ type TestCase,
97
+ type TestPlanOutput,
98
+ type TestRunReview,
99
+ type FixStep,
100
+ type TestFixPlan,
101
+ type DiscoveredTestCommands,
102
+ } from './tester.js';
103
+
83
104
  // CLI types
84
105
  export {
85
106
  EXIT_CODES,
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Tester (QA) skill type definitions
3
+ * Defines test planning, review, and fix plan structures
4
+ */
5
+
6
+ import { z } from 'zod';
7
+
8
+ /**
9
+ * Test verdict from the Tester's review
10
+ */
11
+ export const TestVerdictSchema = z.enum(['PASS', 'PASS_WITH_NOTES', 'FAIL']);
12
+ export type TestVerdict = z.infer<typeof TestVerdictSchema>;
13
+
14
+ /**
15
+ * Scope components that a test plan can cover
16
+ */
17
+ export const TestScopeSchema = z.enum(['frontend', 'backend', 'db', 'infra']);
18
+ export type TestScope = z.infer<typeof TestScopeSchema>;
19
+
20
+ /**
21
+ * A structured test command to execute
22
+ */
23
+ export const TestCommandSchema = z.object({
24
+ /** The shell command to run */
25
+ command: z.string().min(1),
26
+ /** Working directory (relative to project root) */
27
+ cwd: z.string().optional(),
28
+ /** Human-readable purpose of this command */
29
+ purpose: z.string().min(1),
30
+ /** Whether this command must pass for the test run to succeed */
31
+ required: z.boolean(),
32
+ });
33
+ export type TestCommand = z.infer<typeof TestCommandSchema>;
34
+
35
+ /**
36
+ * Individual test case in the test matrix
37
+ */
38
+ export const TestCaseSchema = z.object({
39
+ /** Unique identifier within the test plan */
40
+ id: z.string().min(1),
41
+ /** Category: unit, integration, e2e, smoke, lint, build */
42
+ category: z.string().min(1),
43
+ /** Human-readable description of what is being tested */
44
+ description: z.string().min(1),
45
+ /** What must be true for this test to pass */
46
+ acceptanceCriteria: z.string().min(1),
47
+ /** What evidence (log output, report) is needed to verify */
48
+ evidenceRequired: z.string().min(1),
49
+ /** Priority: critical, high, medium, low */
50
+ priority: z.enum(['critical', 'high', 'medium', 'low']),
51
+ });
52
+ export type TestCase = z.infer<typeof TestCaseSchema>;
53
+
54
+ /**
55
+ * Structured test plan output from the Tester
56
+ */
57
+ export const TestPlanOutputSchema = z.object({
58
+ /** What risks this test plan targets */
59
+ summary: z.string().min(1),
60
+ /** Components covered by this plan */
61
+ scope: z.array(TestScopeSchema).min(1),
62
+ /** Matrix of test cases with acceptance criteria */
63
+ testMatrix: z.array(TestCaseSchema).min(1),
64
+ /** Exact commands to execute (with cwd, purpose, required flag) */
65
+ commands: z.array(TestCommandSchema).min(1),
66
+ /** Top risks this test plan focuses on (3-7 items) */
67
+ riskFocus: z.array(z.string().min(1)).min(1),
68
+ /** What evidence (logs, reports) to capture */
69
+ evidenceRequired: z.array(z.string().min(1)).min(1),
70
+ /** Minimum verification always present: build, lint, smoke */
71
+ minimumVerification: z.array(z.string().min(1)).min(1),
72
+ /** Rationale if tester decides no custom tests are needed (min verification still applies) */
73
+ noTestsRationale: z.string().optional(),
74
+ });
75
+ export type TestPlanOutput = z.infer<typeof TestPlanOutputSchema>;
76
+
77
+ /**
78
+ * Post-run review from the Tester
79
+ */
80
+ export const TestRunReviewSchema = z.object({
81
+ /** Overall verdict */
82
+ verdict: TestVerdictSchema,
83
+ /** Summary of the review */
84
+ summary: z.string().min(1),
85
+ /** List of evidence that was checked */
86
+ evidenceReviewed: z.array(z.string().min(1)).min(1),
87
+ /** Specific failures found (empty array if PASS) */
88
+ failures: z.array(z.string()),
89
+ /** Missing evidence or coverage gaps */
90
+ gaps: z.array(z.string()),
91
+ /** Recommendations for improvement */
92
+ recommendations: z.array(z.string()),
93
+ /** Whether this verdict requires consensus (true if FAIL) */
94
+ requiresConsensus: z.boolean(),
95
+ });
96
+ export type TestRunReview = z.infer<typeof TestRunReviewSchema>;
97
+
98
+ /**
99
+ * Individual fix step in a TestFixPlan
100
+ */
101
+ export const FixStepSchema = z.object({
102
+ /** File to modify */
103
+ file: z.string().min(1),
104
+ /** Description of the change */
105
+ change: z.string().min(1),
106
+ /** Why this change is needed */
107
+ reason: z.string().min(1),
108
+ });
109
+ export type FixStep = z.infer<typeof FixStepSchema>;
110
+
111
+ /**
112
+ * Fix plan proposed by the Tester when tests fail
113
+ */
114
+ export const TestFixPlanSchema = z.object({
115
+ /** Which acceptance criteria failed */
116
+ failedCriteria: z.array(z.string().min(1)).min(1),
117
+ /** Root cause analysis from the Tester */
118
+ rootCauseAnalysis: z.string().min(1),
119
+ /** Ordered steps to fix the failures */
120
+ fixSteps: z.array(FixStepSchema).min(1),
121
+ /** Risks of introducing regressions */
122
+ regressionRisks: z.array(z.string()),
123
+ /** Strategy for re-testing after fix */
124
+ retestStrategy: z.string().min(1),
125
+ });
126
+ export type TestFixPlan = z.infer<typeof TestFixPlanSchema>;
127
+
128
+ /**
129
+ * Discovered test infrastructure for a project
130
+ */
131
+ export interface DiscoveredTestCommands {
132
+ testCmd: string | null;
133
+ lintCmd: string | null;
134
+ buildCmd: string | null;
135
+ typecheckCmd: string | null;
136
+ }
@@ -7,6 +7,8 @@ import { z } from 'zod';
7
7
  import { OutputLanguageSchema } from './project.js';
8
8
  import type { OutputLanguage, OpenAIModel } from './project.js';
9
9
  import type { ConsensusIteration } from './consensus.js';
10
+ import type { TestPlanOutput } from './tester.js';
11
+ import { TestPlanOutputSchema, TestVerdictSchema } from './tester.js';
10
12
 
11
13
  /**
12
14
  * Workflow phases
@@ -68,6 +70,17 @@ export interface Task {
68
70
 
69
71
  // App target (which app this task affects)
70
72
  appTarget?: 'frontend' | 'backend' | 'unified';
73
+
74
+ // Tester (QA) tracking
75
+ qaTestPlanText?: string; // Approved test plan (markdown, for humans)
76
+ qaTestPlanParsed?: TestPlanOutput; // Parsed structured plan (for machine flow)
77
+ qaTestPlanScore?: number; // Consensus score (0-100)
78
+ qaTestPlanIterations?: number; // Iterations to reach consensus
79
+ qaTestPlanApproved?: boolean; // Whether consensus was reached
80
+ qaTestPlanDoc?: string; // Path to docs/qa/test-plans/...
81
+ qaVerdict?: 'PASS' | 'PASS_WITH_NOTES' | 'FAIL';
82
+ qaReviewNotes?: string; // Tester's review notes
83
+ qaReviewDoc?: string; // Path to docs/qa/test-runs/...
71
84
  }
72
85
 
73
86
  /**
@@ -107,6 +120,16 @@ export const TaskSchema = z.object({
107
120
  backendConsensus: AppConsensusTrackingSchema.optional(),
108
121
  unifiedConsensus: AppConsensusTrackingSchema.optional(),
109
122
  appTarget: z.enum(['frontend', 'backend', 'unified']).optional(),
123
+ // Tester (QA) tracking
124
+ qaTestPlanText: z.string().optional(),
125
+ qaTestPlanParsed: TestPlanOutputSchema.optional(),
126
+ qaTestPlanScore: z.number().optional(),
127
+ qaTestPlanIterations: z.number().optional(),
128
+ qaTestPlanApproved: z.boolean().optional(),
129
+ qaTestPlanDoc: z.string().optional(),
130
+ qaVerdict: TestVerdictSchema.optional(),
131
+ qaReviewNotes: z.string().optional(),
132
+ qaReviewDoc: z.string().optional(),
110
133
  });
111
134
 
112
135
  /**
@@ -205,6 +228,8 @@ export interface ProjectState {
205
228
  strategyError?: string;
206
229
  /** Absolute paths to discovered source documentation files */
207
230
  sourceDocPaths?: string[];
231
+ /** Whether QA Tester skill is active (default: true for new projects, undefined/false for existing) */
232
+ qaEnabled?: boolean;
208
233
  }
209
234
 
210
235
  /**
@@ -250,6 +275,7 @@ export const ProjectStateSchema = z.object({
250
275
  websiteStrategy: z.string().optional(),
251
276
  strategyError: z.string().optional(),
252
277
  sourceDocPaths: z.array(z.string()).optional(),
278
+ qaEnabled: z.boolean().optional(),
253
279
  });
254
280
 
255
281
  /**
@@ -865,10 +865,10 @@ ${task.name}
865
865
  ## Description
866
866
  ${task.description || task.name}
867
867
 
868
- ${task.testPlan ? `## Test Requirements\n${task.testPlan}\n` : ''}
868
+ ${task.qaTestPlanText ? `## QA Test Plan\nImplement tests according to this approved test plan:\n${task.qaTestPlanText}\n` : ''}
869
869
 
870
870
  Please implement this task completely. After implementing:
871
- 1. Create appropriate tests if needed
871
+ 1. Implement tests as specified in the QA Test Plan above
872
872
  2. Ensure code follows best practices
873
873
  3. Document any complex logic
874
874
  `.trim();
@@ -48,6 +48,7 @@ export * from './project-structure.js';
48
48
  export * from './separation-guard.js';
49
49
  export * from './seo-tests.js';
50
50
  export * from './task-workflow.js';
51
+ export * from './tester.js';
51
52
  export * from './milestone-workflow.js';
52
53
  export * from './plan-storage.js';
53
54
  export * from './workspace-manager.js';
@@ -8,6 +8,7 @@ import path from 'node:path';
8
8
  import { isWorkspace } from '../types/project.js';
9
9
  import type { ProjectState, Task, Milestone } from '../types/workflow.js';
10
10
  import type { ConsensusConfig } from '../types/consensus.js';
11
+ import type { TestRunReview } from '../types/tester.js';
11
12
  import { createPlan as claudeCreatePlan } from '../adapters/claude.js';
12
13
  import {
13
14
  loadProject,
@@ -16,6 +17,14 @@ import {
16
17
  import { iterateUntilConsensus, runOptimizedConsensusProcess, type ConsensusProcessResult } from './consensus.js';
17
18
  import { executeTask as executeTaskCode, handleTestFailure } from './execution-mode.js';
18
19
  import { runTests, testsExist, getTestSummary, type TestResult } from './test-runner.js';
20
+ import {
21
+ isQaEnabled,
22
+ runTestPlanningPhase,
23
+ runTestReviewPhase,
24
+ createTesterFixPlan,
25
+ documentTestPlan as documentQaTestPlan,
26
+ documentTestReview,
27
+ } from './tester.js';
19
28
 
20
29
  /**
21
30
  * Options for task workflow
@@ -38,6 +47,10 @@ export interface TaskWorkflowResult {
38
47
  error?: string;
39
48
  /** True if workflow paused due to rate limiting (not a failure) */
40
49
  rateLimitPaused?: boolean;
50
+ /** Consensus result for the QA test plan (when QA enabled) */
51
+ testPlanConsensusResult?: ConsensusProcessResult;
52
+ /** Tester's post-run review (when QA enabled) */
53
+ testRunReview?: TestRunReview;
41
54
  }
42
55
 
43
56
  /**
@@ -81,15 +94,14 @@ Create a detailed implementation plan for the following task:
81
94
  ## Task: ${task.name}
82
95
  ${task.description}
83
96
 
84
- ${task.testPlan ? `## Test Requirements\n${task.testPlan}` : ''}
85
-
86
97
  Please provide:
87
98
  1. **Implementation Steps**: Specific code changes needed
88
99
  2. **Files to Create/Modify**: List all files that will be touched
89
100
  3. **Dependencies**: Any packages or modules needed
90
101
  4. **Acceptance Criteria**: How to verify the task is complete
91
- 5. **Test Plan**: Specific tests to write
102
+ 5. **Integration Points**: How this code connects with existing modules
92
103
 
104
+ Do NOT include test planning -- a dedicated QA engineer will handle test design separately.
93
105
  Be specific and actionable. This plan will be reviewed for consensus before implementation.
94
106
  `.trim();
95
107
 
@@ -369,7 +381,9 @@ export async function runTaskWorkflow(
369
381
 
370
382
  // Check if we're resuming from a previous attempt
371
383
  const hasApprovedPlan = task.consensusApproved && task.plan;
384
+ const hasApprovedTestPlan = task.qaTestPlanApproved && task.qaTestPlanText;
372
385
  const hasCompletedImplementation = task.implementationComplete;
386
+ const qaActive = isQaEnabled(state);
373
387
 
374
388
  // Mark task as in-progress
375
389
  state = await updateTaskInState(projectDir, task.id, {
@@ -509,16 +523,83 @@ Task: ${task.name}
509
523
  }
510
524
 
511
525
  // ============================================
512
- // PHASE 3: Implement the Task (skip if already complete)
526
+ // PHASE 3-4: Tester creates TestPlan + Consensus (only if QA enabled)
527
+ // ============================================
528
+ let testPlanConsensusResult: ConsensusProcessResult | undefined;
529
+
530
+ if (qaActive && !hasApprovedTestPlan) {
531
+ onProgress?.('test-planning', `Tester is designing test plan for: ${task.name}`);
532
+
533
+ const testPlanResult = await runTestPlanningPhase(
534
+ task, milestone, state, consensusResult.bestPlan,
535
+ { projectDir, consensusConfig, onProgress },
536
+ );
537
+
538
+ if (testPlanResult.error) {
539
+ state = await updateTaskInState(projectDir, task.id, {
540
+ status: 'failed',
541
+ error: testPlanResult.error,
542
+ });
543
+ return {
544
+ success: false,
545
+ task: { ...task, status: 'failed' },
546
+ consensusResult,
547
+ error: testPlanResult.error,
548
+ };
549
+ }
550
+
551
+ testPlanConsensusResult = testPlanResult.consensusResult;
552
+
553
+ // Document and persist test plan
554
+ const qaDocPath = await documentQaTestPlan(
555
+ projectDir, milestone, task, testPlanResult.testPlanText, testPlanResult.consensusResult,
556
+ );
557
+
558
+ state = await updateTaskInState(projectDir, task.id, {
559
+ qaTestPlanText: testPlanResult.testPlanText,
560
+ qaTestPlanParsed: testPlanResult.testPlanParsed ?? undefined,
561
+ qaTestPlanScore: testPlanResult.consensusResult.finalScore,
562
+ qaTestPlanIterations: testPlanResult.consensusResult.totalIterations,
563
+ qaTestPlanApproved: testPlanResult.consensusResult.approved,
564
+ qaTestPlanDoc: qaDocPath,
565
+ });
566
+
567
+ if (!testPlanResult.consensusResult.approved) {
568
+ onProgress?.('test-planning', `Test plan consensus not reached: ${testPlanResult.consensusResult.finalScore}%`);
569
+ state = await updateTaskInState(projectDir, task.id, {
570
+ status: 'failed',
571
+ error: `Test plan consensus not reached: ${testPlanResult.consensusResult.finalScore}%`,
572
+ });
573
+ return {
574
+ success: false,
575
+ task: { ...task, status: 'failed' },
576
+ consensusResult,
577
+ testPlanConsensusResult,
578
+ error: `Test plan not approved. Score: ${testPlanResult.consensusResult.finalScore}%`,
579
+ };
580
+ }
581
+
582
+ onProgress?.('test-planning', `Test plan approved with ${testPlanResult.consensusResult.finalScore}% consensus`);
583
+ } else if (qaActive && hasApprovedTestPlan) {
584
+ onProgress?.('test-planning', `Using existing approved test plan for: ${task.name} (Score: ${task.qaTestPlanScore}%)`);
585
+ }
586
+
587
+ // ============================================
588
+ // PHASE 5: Implement the Task (skip if already complete)
513
589
  // ============================================
514
590
  if (hasCompletedImplementation) {
515
591
  onProgress?.('task-implement', `Implementation already complete for: ${task.name}, skipping to tests...`);
516
592
  } else {
517
593
  onProgress?.('task-implement', `Implementing task: ${task.name}`);
518
594
 
595
+ // When QA is active, provide both approved plans as context
596
+ const implementationContext = (qaActive && task.qaTestPlanText)
597
+ ? `${consensusResult.bestPlan}\n\n## Approved Test Plan\n${task.qaTestPlanText}`
598
+ : consensusResult.bestPlan;
599
+
519
600
  const implementResult = await executeTaskCode(
520
601
  task,
521
- consensusResult.bestPlan, // Use the approved plan as context
602
+ implementationContext,
522
603
  projectDir,
523
604
  (msg) => onProgress?.('task-implement', msg)
524
605
  );
@@ -738,10 +819,150 @@ Phase: Test failure fix (attempt ${retries}/${maxRetries})
738
819
  task: { ...task, status: 'failed', testsPassed: false },
739
820
  consensusResult,
740
821
  testResult,
822
+ testPlanConsensusResult,
741
823
  error: `Tests failed: ${getTestSummary(testResult)}`,
742
824
  };
743
825
  }
744
826
 
827
+ // ============================================
828
+ // PHASE 7: Tester reviews test results (only if QA enabled)
829
+ // ============================================
830
+ if (qaActive && task.qaTestPlanText && testResult) {
831
+ onProgress?.('test-review', `Tester is reviewing test results for: ${task.name}`);
832
+
833
+ const review = await runTestReviewPhase(
834
+ task, task.qaTestPlanText, testResult, state, onProgress,
835
+ );
836
+
837
+ // Document the review
838
+ const reviewDocPath = await documentTestReview(projectDir, milestone, task, review);
839
+
840
+ state = await updateTaskInState(projectDir, task.id, {
841
+ qaVerdict: review.verdict,
842
+ qaReviewNotes: review.summary,
843
+ qaReviewDoc: reviewDocPath,
844
+ });
845
+
846
+ if (review.verdict === 'FAIL') {
847
+ onProgress?.('test-review', `Tester verdict: FAIL - ${review.summary}`);
848
+
849
+ // Tester creates a fix plan -> consensus -> coder implements -> re-review loop
850
+ const fixPlanText = await createTesterFixPlan(
851
+ task, task.qaTestPlanText, testResult, review, state, onProgress,
852
+ );
853
+
854
+ // Get consensus on the fix plan
855
+ const fixContext = `Project: ${state.name}\nLanguage: ${state.language}\nMilestone: ${milestone.name}\nTask: ${task.name}\nPhase: QA Fix Plan`;
856
+ const useOptimized = consensusConfig?.useOptimizedConsensus !== false;
857
+ let fixConsensus: ConsensusProcessResult;
858
+
859
+ if (useOptimized) {
860
+ fixConsensus = await runOptimizedConsensusProcess(
861
+ fixPlanText, fixContext,
862
+ {
863
+ projectDir, config: consensusConfig,
864
+ milestoneId: milestone.id, milestoneName: milestone.name,
865
+ taskId: task.id, taskName: `${task.name} - QA Fix`,
866
+ parallelReviews: true, isFullstack: isWorkspace(state.language),
867
+ onIteration: (iteration, result) => {
868
+ onProgress?.('test-review', `QA fix consensus iteration ${iteration}: ${result.score}%`);
869
+ },
870
+ onProgress,
871
+ },
872
+ ) as ConsensusProcessResult;
873
+ } else {
874
+ fixConsensus = await iterateUntilConsensus(
875
+ fixPlanText, fixContext,
876
+ {
877
+ projectDir, config: consensusConfig,
878
+ isFullstack: isWorkspace(state.language), language: state.language,
879
+ onIteration: (iteration, result) => {
880
+ onProgress?.('test-review', `QA fix consensus iteration ${iteration}: ${result.score}%`);
881
+ },
882
+ onProgress,
883
+ },
884
+ ) as ConsensusProcessResult;
885
+ }
886
+
887
+ if (!fixConsensus.approved) {
888
+ state = await updateTaskInState(projectDir, task.id, {
889
+ status: 'failed',
890
+ error: `QA fix plan not approved (${fixConsensus.finalScore}%)`,
891
+ });
892
+ return {
893
+ success: false,
894
+ task: { ...task, status: 'failed' },
895
+ consensusResult,
896
+ testResult,
897
+ testPlanConsensusResult,
898
+ testRunReview: review,
899
+ error: `QA fix plan not approved. Score: ${fixConsensus.finalScore}%`,
900
+ };
901
+ }
902
+
903
+ // Implement the fix
904
+ onProgress?.('test-review', 'Implementing QA-approved fix...');
905
+ const fixResult = await handleTestFailure(
906
+ task, testResult, fixConsensus.bestPlan, projectDir,
907
+ (msg) => onProgress?.('test-review', msg),
908
+ );
909
+
910
+ if (!fixResult.success) {
911
+ state = await updateTaskInState(projectDir, task.id, {
912
+ status: 'failed',
913
+ error: `QA fix implementation failed: ${fixResult.error}`,
914
+ });
915
+ return {
916
+ success: false,
917
+ task: { ...task, status: 'failed' },
918
+ consensusResult,
919
+ testResult,
920
+ testPlanConsensusResult,
921
+ testRunReview: review,
922
+ error: `QA fix failed: ${fixResult.error}`,
923
+ };
924
+ }
925
+
926
+ // Re-run tests after fix
927
+ onProgress?.('test-review', 'Re-running tests after QA fix...');
928
+ const reTestResult = await runTests(projectDir, state.language);
929
+
930
+ // Tester re-reviews
931
+ const reReview = await runTestReviewPhase(
932
+ task, task.qaTestPlanText!, reTestResult, state, onProgress,
933
+ );
934
+
935
+ const reReviewDocPath = await documentTestReview(projectDir, milestone, task, reReview);
936
+ state = await updateTaskInState(projectDir, task.id, {
937
+ qaVerdict: reReview.verdict,
938
+ qaReviewNotes: reReview.summary,
939
+ qaReviewDoc: reReviewDocPath,
940
+ });
941
+
942
+ if (reReview.verdict === 'FAIL') {
943
+ state = await updateTaskInState(projectDir, task.id, {
944
+ status: 'failed',
945
+ testsPassed: false,
946
+ error: `QA re-review: FAIL - ${reReview.summary}`,
947
+ });
948
+ return {
949
+ success: false,
950
+ task: { ...task, status: 'failed', testsPassed: false },
951
+ consensusResult,
952
+ testResult: reTestResult,
953
+ testPlanConsensusResult,
954
+ testRunReview: reReview,
955
+ error: `QA verdict: FAIL after fix attempt`,
956
+ };
957
+ }
958
+
959
+ // PASS or PASS_WITH_NOTES after fix
960
+ onProgress?.('test-review', `Tester re-review verdict: ${reReview.verdict}`);
961
+ } else {
962
+ onProgress?.('test-review', `Tester verdict: ${review.verdict}`);
963
+ }
964
+ }
965
+
745
966
  // Mark task as complete
746
967
  state = await updateTaskInState(projectDir, task.id, {
747
968
  status: 'complete',
@@ -753,6 +974,7 @@ Phase: Test failure fix (attempt ${retries}/${maxRetries})
753
974
  task: { ...task, status: 'complete', testsPassed: true },
754
975
  consensusResult,
755
976
  testResult,
977
+ testPlanConsensusResult,
756
978
  };
757
979
  }
758
980