popeye-cli 1.5.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.
- package/CHANGELOG.md +54 -0
- package/README.md +184 -31
- package/dist/cli/commands/create.d.ts.map +1 -1
- package/dist/cli/commands/create.js +54 -4
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/interactive.d.ts +29 -0
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +90 -7
- package/dist/cli/interactive.js.map +1 -1
- package/dist/generators/all.d.ts +4 -1
- package/dist/generators/all.d.ts.map +1 -1
- package/dist/generators/all.js +36 -316
- package/dist/generators/all.js.map +1 -1
- package/dist/generators/doc-parser.d.ts +18 -3
- package/dist/generators/doc-parser.d.ts.map +1 -1
- package/dist/generators/doc-parser.js +81 -10
- package/dist/generators/doc-parser.js.map +1 -1
- package/dist/generators/frontend-design-analyzer.d.ts +30 -0
- package/dist/generators/frontend-design-analyzer.d.ts.map +1 -0
- package/dist/generators/frontend-design-analyzer.js +208 -0
- package/dist/generators/frontend-design-analyzer.js.map +1 -0
- package/dist/generators/shared-packages.d.ts +45 -0
- package/dist/generators/shared-packages.d.ts.map +1 -0
- package/dist/generators/shared-packages.js +456 -0
- package/dist/generators/shared-packages.js.map +1 -0
- package/dist/generators/templates/index.d.ts +4 -0
- package/dist/generators/templates/index.d.ts.map +1 -1
- package/dist/generators/templates/index.js +4 -0
- package/dist/generators/templates/index.js.map +1 -1
- package/dist/generators/templates/website-components.d.ts.map +1 -1
- package/dist/generators/templates/website-components.js +36 -11
- package/dist/generators/templates/website-components.js.map +1 -1
- package/dist/generators/templates/website-config.d.ts +15 -1
- package/dist/generators/templates/website-config.d.ts.map +1 -1
- package/dist/generators/templates/website-config.js +155 -13
- package/dist/generators/templates/website-config.js.map +1 -1
- package/dist/generators/templates/website-landing.d.ts +24 -0
- package/dist/generators/templates/website-landing.d.ts.map +1 -0
- package/dist/generators/templates/website-landing.js +276 -0
- package/dist/generators/templates/website-landing.js.map +1 -0
- package/dist/generators/templates/website-layout.d.ts +42 -0
- package/dist/generators/templates/website-layout.d.ts.map +1 -0
- package/dist/generators/templates/website-layout.js +408 -0
- package/dist/generators/templates/website-layout.js.map +1 -0
- package/dist/generators/templates/website-pricing.d.ts +11 -0
- package/dist/generators/templates/website-pricing.d.ts.map +1 -0
- package/dist/generators/templates/website-pricing.js +313 -0
- package/dist/generators/templates/website-pricing.js.map +1 -0
- package/dist/generators/templates/website-sections.d.ts +102 -0
- package/dist/generators/templates/website-sections.d.ts.map +1 -0
- package/dist/generators/templates/website-sections.js +444 -0
- package/dist/generators/templates/website-sections.js.map +1 -0
- package/dist/generators/templates/website.d.ts +10 -50
- package/dist/generators/templates/website.d.ts.map +1 -1
- package/dist/generators/templates/website.js +12 -788
- package/dist/generators/templates/website.js.map +1 -1
- package/dist/generators/website-content-scanner.d.ts +37 -0
- package/dist/generators/website-content-scanner.d.ts.map +1 -0
- package/dist/generators/website-content-scanner.js +165 -0
- package/dist/generators/website-content-scanner.js.map +1 -0
- package/dist/generators/website-context.d.ts +38 -2
- package/dist/generators/website-context.d.ts.map +1 -1
- package/dist/generators/website-context.js +179 -19
- package/dist/generators/website-context.js.map +1 -1
- package/dist/generators/website-debug.d.ts +68 -0
- package/dist/generators/website-debug.d.ts.map +1 -0
- package/dist/generators/website-debug.js +93 -0
- package/dist/generators/website-debug.js.map +1 -0
- package/dist/generators/website.d.ts +2 -0
- package/dist/generators/website.d.ts.map +1 -1
- package/dist/generators/website.js +66 -4
- package/dist/generators/website.js.map +1 -1
- package/dist/generators/workspace-root.d.ts +27 -0
- package/dist/generators/workspace-root.d.ts.map +1 -0
- package/dist/generators/workspace-root.js +100 -0
- package/dist/generators/workspace-root.js.map +1 -0
- package/dist/state/index.d.ts +8 -0
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +11 -0
- package/dist/state/index.js.map +1 -1
- package/dist/types/consensus.d.ts +3 -0
- package/dist/types/consensus.d.ts.map +1 -1
- package/dist/types/consensus.js +1 -0
- package/dist/types/consensus.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- 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/tester.d.ts +138 -0
- package/dist/types/tester.d.ts.map +1 -0
- package/dist/types/tester.js +110 -0
- package/dist/types/tester.js.map +1 -0
- package/dist/types/workflow.d.ts +151 -0
- package/dist/types/workflow.d.ts.map +1 -1
- package/dist/types/workflow.js +14 -0
- package/dist/types/workflow.js.map +1 -1
- package/dist/upgrade/handlers.d.ts +15 -0
- package/dist/upgrade/handlers.d.ts.map +1 -1
- package/dist/upgrade/handlers.js +52 -0
- package/dist/upgrade/handlers.js.map +1 -1
- package/dist/workflow/auto-fix-bundler.d.ts +37 -0
- package/dist/workflow/auto-fix-bundler.d.ts.map +1 -0
- package/dist/workflow/auto-fix-bundler.js +320 -0
- package/dist/workflow/auto-fix-bundler.js.map +1 -0
- package/dist/workflow/auto-fix.d.ts.map +1 -1
- package/dist/workflow/auto-fix.js +10 -3
- package/dist/workflow/auto-fix.js.map +1 -1
- package/dist/workflow/execution-mode.js +2 -2
- package/dist/workflow/execution-mode.js.map +1 -1
- package/dist/workflow/index.d.ts +2 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +13 -0
- package/dist/workflow/index.js.map +1 -1
- package/dist/workflow/overview.d.ts.map +1 -1
- package/dist/workflow/overview.js +4 -0
- package/dist/workflow/overview.js.map +1 -1
- package/dist/workflow/plan-mode.d.ts +4 -3
- package/dist/workflow/plan-mode.d.ts.map +1 -1
- package/dist/workflow/plan-mode.js +69 -5
- package/dist/workflow/plan-mode.js.map +1 -1
- package/dist/workflow/task-workflow.d.ts +5 -0
- package/dist/workflow/task-workflow.d.ts.map +1 -1
- package/dist/workflow/task-workflow.js +172 -6
- package/dist/workflow/task-workflow.js.map +1 -1
- package/dist/workflow/tester.d.ts +120 -0
- package/dist/workflow/tester.d.ts.map +1 -0
- package/dist/workflow/tester.js +589 -0
- package/dist/workflow/tester.js.map +1 -0
- package/dist/workflow/website-strategy.d.ts +9 -0
- package/dist/workflow/website-strategy.d.ts.map +1 -1
- package/dist/workflow/website-strategy.js +73 -1
- package/dist/workflow/website-strategy.js.map +1 -1
- package/dist/workflow/website-updater.d.ts.map +1 -1
- package/dist/workflow/website-updater.js +15 -4
- package/dist/workflow/website-updater.js.map +1 -1
- package/dist/workflow/workflow-logger.d.ts +1 -1
- package/dist/workflow/workflow-logger.d.ts.map +1 -1
- package/dist/workflow/workflow-logger.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/create.ts +58 -4
- package/src/cli/interactive.ts +96 -7
- package/src/generators/all.ts +44 -332
- package/src/generators/doc-parser.ts +87 -10
- package/src/generators/frontend-design-analyzer.ts +261 -0
- package/src/generators/shared-packages.ts +500 -0
- package/src/generators/templates/index.ts +4 -0
- package/src/generators/templates/website-components.ts +36 -11
- package/src/generators/templates/website-config.ts +166 -13
- package/src/generators/templates/website-landing.ts +331 -0
- package/src/generators/templates/website-layout.ts +443 -0
- package/src/generators/templates/website-pricing.ts +330 -0
- package/src/generators/templates/website-sections.ts +541 -0
- package/src/generators/templates/website.ts +38 -851
- package/src/generators/website-content-scanner.ts +208 -0
- package/src/generators/website-context.ts +248 -20
- package/src/generators/website-debug.ts +130 -0
- package/src/generators/website.ts +71 -3
- package/src/generators/workspace-root.ts +113 -0
- package/src/state/index.ts +15 -0
- package/src/types/consensus.ts +3 -0
- package/src/types/index.ts +21 -0
- package/src/types/tester.ts +136 -0
- package/src/types/workflow.ts +32 -0
- package/src/upgrade/handlers.ts +65 -0
- package/src/workflow/auto-fix-bundler.ts +392 -0
- package/src/workflow/auto-fix.ts +11 -3
- package/src/workflow/execution-mode.ts +2 -2
- package/src/workflow/index.ts +13 -0
- package/src/workflow/overview.ts +6 -0
- package/src/workflow/plan-mode.ts +81 -7
- package/src/workflow/task-workflow.ts +227 -5
- package/src/workflow/tester.ts +723 -0
- package/src/workflow/website-strategy.ts +75 -1
- package/src/workflow/website-updater.ts +17 -6
- package/src/workflow/workflow-logger.ts +2 -0
- package/tests/cli/project-naming.test.ts +136 -0
- package/tests/generators/doc-parser.test.ts +121 -0
- package/tests/generators/frontend-design-analyzer.test.ts +90 -0
- package/tests/generators/quality-gate.test.ts +183 -0
- package/tests/generators/shared-packages.test.ts +83 -0
- package/tests/generators/website-components.test.ts +1 -1
- package/tests/generators/website-config.test.ts +84 -0
- package/tests/generators/website-content-scanner.test.ts +181 -0
- package/tests/generators/website-context.test.ts +109 -0
- package/tests/generators/website-debug.test.ts +77 -0
- package/tests/generators/website-landing.test.ts +188 -0
- package/tests/generators/website-pricing.test.ts +98 -0
- package/tests/generators/website-sections.test.ts +245 -0
- package/tests/generators/workspace-root.test.ts +105 -0
- package/tests/types/tester.test.ts +174 -0
- package/tests/upgrade/handlers.test.ts +162 -0
- package/tests/workflow/auto-fix-bundler.test.ts +242 -0
- package/tests/workflow/plan-mode.test.ts +111 -1
- package/tests/workflow/tester.test.ts +401 -0
- package/tests/workflow/website-strategy.test.ts +55 -0
|
@@ -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. **
|
|
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:
|
|
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
|
-
|
|
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
|
|