edsger 0.34.0 ā 0.35.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/dist/api/features/approval-checker.js +6 -8
- package/dist/commands/agent-workflow/chat-worker.js +2 -1
- package/dist/commands/agent-workflow/processor.js +3 -1
- package/dist/commands/code-review/index.js +5 -7
- package/dist/commands/workflow/phase-orchestrator.js +16 -32
- package/dist/constants.js +2 -0
- package/dist/index.js +3 -1
- package/dist/phases/app-store-generation/__tests__/agent.test.js +1 -3
- package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.js +2 -4
- package/dist/phases/app-store-generation/agent.js +1 -3
- package/dist/phases/app-store-generation/index.js +4 -3
- package/dist/phases/app-store-generation/screenshot-composer.js +3 -5
- package/dist/phases/autonomous/index.js +4 -3
- package/dist/phases/branch-planning/context.js +7 -7
- package/dist/phases/branch-planning/index.js +5 -3
- package/dist/phases/bug-fixing/analyzer.js +13 -13
- package/dist/phases/bug-fixing/context-fetcher.js +9 -9
- package/dist/phases/bug-fixing/mcp-server.js +14 -17
- package/dist/phases/code-implementation/context.js +5 -5
- package/dist/phases/code-implementation/index.js +5 -4
- package/dist/phases/code-implementation-verification/agent.js +3 -1
- package/dist/phases/code-refine/context.js +1 -1
- package/dist/phases/code-refine/index.js +4 -6
- package/dist/phases/code-refine/refine-iteration.js +10 -10
- package/dist/phases/code-refine-verification/index.js +80 -82
- package/dist/phases/code-review/index.js +8 -8
- package/dist/phases/code-testing/analyzer.js +3 -1
- package/dist/phases/code-testing/context-fetcher.js +5 -5
- package/dist/phases/feature-analysis/agent.js +1 -3
- package/dist/phases/feature-analysis/context.js +5 -5
- package/dist/phases/feature-analysis/index.js +4 -4
- package/dist/phases/feature-analysis/outcome.d.ts +1 -1
- package/dist/phases/feature-analysis/outcome.js +7 -7
- package/dist/phases/feature-analysis-verification/index.js +6 -6
- package/dist/phases/functional-testing/analyzer.js +4 -2
- package/dist/phases/functional-testing/context-fetcher.js +5 -5
- package/dist/phases/functional-testing/http-fallback.js +4 -2
- package/dist/phases/functional-testing/mcp-server.js +3 -3
- package/dist/phases/growth-analysis/agent.js +1 -3
- package/dist/phases/pr-execution/index.js +3 -1
- package/dist/phases/pr-splitting/context.js +6 -6
- package/dist/phases/pr-splitting/index.js +3 -1
- package/dist/phases/pull-request/handler.js +2 -4
- package/dist/phases/task/agent.js +6 -8
- package/dist/phases/technical-design/context.js +5 -5
- package/dist/phases/technical-design/index.js +9 -8
- package/dist/phases/test-cases-analysis/agent.js +1 -3
- package/dist/phases/test-cases-analysis/context.js +5 -5
- package/dist/phases/test-cases-analysis/index.js +3 -3
- package/dist/phases/test-cases-analysis/outcome.d.ts +1 -1
- package/dist/phases/test-cases-analysis/outcome.js +4 -4
- package/dist/phases/user-stories-analysis/agent.js +1 -3
- package/dist/phases/user-stories-analysis/context.js +5 -5
- package/dist/phases/user-stories-analysis/index.js +3 -3
- package/dist/phases/user-stories-analysis/outcome.d.ts +1 -1
- package/dist/phases/user-stories-analysis/outcome.js +4 -4
- package/dist/services/coaching/coaching-loop.js +1 -1
- package/dist/services/coaching/self-rating.js +1 -1
- package/dist/services/phase-ratings.js +2 -1
- package/dist/services/video/__tests__/video-pipeline.test.js +3 -1
- package/dist/services/video/retry.js +5 -2
- package/dist/services/video/screenshot-generator.js +1 -1
- package/dist/services/video/video-assembler.d.ts +1 -1
- package/dist/services/video/video-assembler.js +3 -3
- package/dist/utils/conflict-resolver.js +13 -15
- package/dist/utils/git-branch-manager-async.js +5 -7
- package/dist/utils/git-push.js +2 -2
- package/package.json +1 -1
|
@@ -89,14 +89,12 @@ export async function checkApprovalBeforePhaseExecution(featureId, verbose = fal
|
|
|
89
89
|
message: `Approval request created for status: ${currentStatus}`,
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
};
|
|
99
|
-
}
|
|
92
|
+
logError('Failed to create approval request');
|
|
93
|
+
return {
|
|
94
|
+
canProceed: false,
|
|
95
|
+
requiresApproval: true,
|
|
96
|
+
message: `Failed to create approval request for status: ${currentStatus}`,
|
|
97
|
+
};
|
|
100
98
|
}
|
|
101
99
|
catch (error) {
|
|
102
100
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -115,7 +115,8 @@ function stopPolling() {
|
|
|
115
115
|
// Event Handlers
|
|
116
116
|
// ============================================================
|
|
117
117
|
async function handleInit(msg) {
|
|
118
|
-
|
|
118
|
+
;
|
|
119
|
+
({ config } = msg);
|
|
119
120
|
verbose = msg.verbose ?? false;
|
|
120
121
|
log('info', `Chat worker initialized (id: ${WORKER_ID})`);
|
|
121
122
|
// Load existing channels before starting the poll loop
|
|
@@ -27,7 +27,9 @@ import { calculateStats, createCompletedState, createFailedState, createInitialS
|
|
|
27
27
|
*/
|
|
28
28
|
export const MAX_CONCURRENCY = 10;
|
|
29
29
|
/** Path to the compiled worker entry points */
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
|
|
30
31
|
const __filename = fileURLToPath(import.meta.url);
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
|
|
31
33
|
const __dirname = dirname(__filename);
|
|
32
34
|
const WORKER_SCRIPT = join(__dirname, 'feature-worker.js');
|
|
33
35
|
const CHAT_WORKER_SCRIPT = join(__dirname, 'chat-worker.js');
|
|
@@ -362,7 +364,7 @@ export class AgentWorkflowProcessor {
|
|
|
362
364
|
}
|
|
363
365
|
});
|
|
364
366
|
// Set up worker timeout
|
|
365
|
-
const workerTimeout = this.config.workflow
|
|
367
|
+
const { workerTimeout } = this.config.workflow;
|
|
366
368
|
activeWorker.timeoutTimer = setTimeout(() => {
|
|
367
369
|
logError(`Worker for ${feature.name} timed out after ${Math.round(workerTimeout / 1000)}s, killing...`);
|
|
368
370
|
try {
|
|
@@ -22,13 +22,11 @@ export const runCodeReview = async (options) => {
|
|
|
22
22
|
if (exitCode === 0) {
|
|
23
23
|
logSuccess('Review completed successfully');
|
|
24
24
|
}
|
|
25
|
-
else {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
logError('Review failed with warnings');
|
|
31
|
-
}
|
|
25
|
+
else if (hasBlockingIssues) {
|
|
26
|
+
logError('Review failed with blocking issues');
|
|
27
|
+
}
|
|
28
|
+
else if (hasWarnings) {
|
|
29
|
+
logError('Review failed with warnings');
|
|
32
30
|
}
|
|
33
31
|
process.exit(exitCode);
|
|
34
32
|
}
|
|
@@ -221,10 +221,8 @@ const runFromUserStoriesAnalysis = async (options, config) => {
|
|
|
221
221
|
if (prCreated) {
|
|
222
222
|
await continueWithCodeReviewAndRefine(options, config, results, verbose);
|
|
223
223
|
}
|
|
224
|
-
else {
|
|
225
|
-
|
|
226
|
-
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
227
|
-
}
|
|
224
|
+
else if (verbose) {
|
|
225
|
+
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
228
226
|
}
|
|
229
227
|
}
|
|
230
228
|
return finalizePipelineExecution(options, results, verbose);
|
|
@@ -274,10 +272,8 @@ const runFromTestCasesAnalysis = async (options, config) => {
|
|
|
274
272
|
if (prCreated) {
|
|
275
273
|
await continueWithCodeReviewAndRefine(options, config, results, verbose);
|
|
276
274
|
}
|
|
277
|
-
else {
|
|
278
|
-
|
|
279
|
-
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
280
|
-
}
|
|
275
|
+
else if (verbose) {
|
|
276
|
+
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
281
277
|
}
|
|
282
278
|
}
|
|
283
279
|
return finalizePipelineExecution(options, results, verbose);
|
|
@@ -378,10 +374,8 @@ const runFromPRSplitting = async (options, config) => {
|
|
|
378
374
|
if (prCreated) {
|
|
379
375
|
await continueWithCodeReviewAndRefine(options, config, results, verbose);
|
|
380
376
|
}
|
|
381
|
-
else {
|
|
382
|
-
|
|
383
|
-
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
384
|
-
}
|
|
377
|
+
else if (verbose) {
|
|
378
|
+
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
385
379
|
}
|
|
386
380
|
}
|
|
387
381
|
return finalizePipelineExecution(options, results, verbose);
|
|
@@ -430,10 +424,8 @@ const runFromPRExecution = async (options, config) => {
|
|
|
430
424
|
if (prCreated) {
|
|
431
425
|
await continueWithCodeReviewAndRefine(options, config, results, verbose);
|
|
432
426
|
}
|
|
433
|
-
else {
|
|
434
|
-
|
|
435
|
-
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
436
|
-
}
|
|
427
|
+
else if (verbose) {
|
|
428
|
+
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
437
429
|
}
|
|
438
430
|
}
|
|
439
431
|
return finalizePipelineExecution(options, results, verbose);
|
|
@@ -496,10 +488,8 @@ const runFromFeatureAnalysis = async (options, config) => {
|
|
|
496
488
|
if (prCreated) {
|
|
497
489
|
await continueWithCodeReviewAndRefine(options, config, results, verbose);
|
|
498
490
|
}
|
|
499
|
-
else {
|
|
500
|
-
|
|
501
|
-
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
502
|
-
}
|
|
491
|
+
else if (verbose) {
|
|
492
|
+
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
503
493
|
}
|
|
504
494
|
}
|
|
505
495
|
return finalizePipelineExecution(options, results, verbose);
|
|
@@ -545,10 +535,8 @@ const runFromTechnicalDesign = async (options, config) => {
|
|
|
545
535
|
if (prCreated) {
|
|
546
536
|
await continueWithCodeReviewAndRefine(options, config, results, verbose);
|
|
547
537
|
}
|
|
548
|
-
else {
|
|
549
|
-
|
|
550
|
-
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
551
|
-
}
|
|
538
|
+
else if (verbose) {
|
|
539
|
+
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
552
540
|
}
|
|
553
541
|
}
|
|
554
542
|
return finalizePipelineExecution(options, results, verbose);
|
|
@@ -588,10 +576,8 @@ const runFromCodeImplementation = async (options, config) => {
|
|
|
588
576
|
if (prCreated) {
|
|
589
577
|
await continueWithCodeReviewAndRefine(options, config, results, verbose);
|
|
590
578
|
}
|
|
591
|
-
else {
|
|
592
|
-
|
|
593
|
-
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
594
|
-
}
|
|
579
|
+
else if (verbose) {
|
|
580
|
+
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
595
581
|
}
|
|
596
582
|
}
|
|
597
583
|
return finalizePipelineExecution(options, results, verbose);
|
|
@@ -625,10 +611,8 @@ const runFromFunctionalTesting = async (options, config) => {
|
|
|
625
611
|
if (prCreated) {
|
|
626
612
|
await continueWithCodeReviewAndRefine(options, config, results, verbose);
|
|
627
613
|
}
|
|
628
|
-
else {
|
|
629
|
-
|
|
630
|
-
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
631
|
-
}
|
|
614
|
+
else if (verbose) {
|
|
615
|
+
logInfo('ā ļø Skipping code review and refine workflow: pull request creation failed');
|
|
632
616
|
}
|
|
633
617
|
}
|
|
634
618
|
return finalizePipelineExecution(options, results, verbose);
|
package/dist/constants.js
CHANGED
|
@@ -16,7 +16,9 @@ export function getVersion() {
|
|
|
16
16
|
return _cachedVersion;
|
|
17
17
|
}
|
|
18
18
|
try {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
|
|
19
20
|
const __filename = fileURLToPath(import.meta.url);
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
|
|
20
22
|
const __dirname = dirname(__filename);
|
|
21
23
|
const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
|
|
22
24
|
_cachedVersion = pkg.version;
|
package/dist/index.js
CHANGED
|
@@ -19,10 +19,12 @@ import { runTaskWorker } from './commands/task-worker/index.js';
|
|
|
19
19
|
import { runWorkflow } from './commands/workflow/index.js';
|
|
20
20
|
import { logError, logInfo } from './utils/logger.js';
|
|
21
21
|
// Get package.json version dynamically
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
|
|
22
23
|
const __filename = fileURLToPath(import.meta.url);
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- ESM __filename/__dirname polyfill
|
|
23
25
|
const __dirname = dirname(__filename);
|
|
24
26
|
const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
|
|
25
|
-
const version = packageJson
|
|
27
|
+
const { version } = packageJson;
|
|
26
28
|
// Load environment variables (each only sets vars not already defined):
|
|
27
29
|
// 1. Real environment variables (highest priority - already in process.env)
|
|
28
30
|
// 2. .env file in cwd (medium priority - loaded first)
|
|
@@ -18,9 +18,7 @@ function parseAppStoreResult(responseText) {
|
|
|
18
18
|
if (jsonResult && jsonResult.app_store) {
|
|
19
19
|
return { appStore: jsonResult.app_store };
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
return { error: 'Invalid JSON structure: missing app_store key' };
|
|
23
|
-
}
|
|
21
|
+
return { error: 'Invalid JSON structure: missing app_store key' };
|
|
24
22
|
}
|
|
25
23
|
catch (error) {
|
|
26
24
|
return {
|
|
@@ -91,8 +91,7 @@ function createCompositionHtml(framedScreenshotDataUrl, spec, targetWidth, targe
|
|
|
91
91
|
</body>
|
|
92
92
|
</html>`;
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
return `<!DOCTYPE html>
|
|
94
|
+
return `<!DOCTYPE html>
|
|
96
95
|
<html>
|
|
97
96
|
<head>
|
|
98
97
|
<style>
|
|
@@ -152,7 +151,6 @@ function createCompositionHtml(framedScreenshotDataUrl, spec, targetWidth, targe
|
|
|
152
151
|
</div>
|
|
153
152
|
</body>
|
|
154
153
|
</html>`;
|
|
155
|
-
}
|
|
156
154
|
}
|
|
157
155
|
// ============================================================
|
|
158
156
|
// escapeHtml tests
|
|
@@ -381,7 +379,7 @@ void describe('STORE_SCREENSHOT_SIZES - Orientation', () => {
|
|
|
381
379
|
}
|
|
382
380
|
});
|
|
383
381
|
void it('should have Google phone in portrait (height > width)', () => {
|
|
384
|
-
const phone = STORE_SCREENSHOT_SIZES.google
|
|
382
|
+
const { phone } = STORE_SCREENSHOT_SIZES.google;
|
|
385
383
|
assert.ok(phone.height > phone.width, `Google phone should be portrait: ${phone.width}x${phone.height}`);
|
|
386
384
|
});
|
|
387
385
|
void it('should have Google tablet_7 in portrait (height > width)', () => {
|
|
@@ -20,9 +20,7 @@ function parseAppStoreResult(responseText) {
|
|
|
20
20
|
if (jsonResult && jsonResult.app_store) {
|
|
21
21
|
return { appStore: jsonResult.app_store };
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
return { error: 'Invalid JSON structure: missing app_store key' };
|
|
25
|
-
}
|
|
23
|
+
return { error: 'Invalid JSON structure: missing app_store key' };
|
|
26
24
|
}
|
|
27
25
|
catch (error) {
|
|
28
26
|
return {
|
|
@@ -5,7 +5,7 @@ import { cloneFeatureRepo, ensureWorkspaceDir, } from '../../workspace/workspace
|
|
|
5
5
|
import { executeAppStoreQuery } from './agent.js';
|
|
6
6
|
import { prepareAppStoreContext } from './context.js';
|
|
7
7
|
import { createAppStoreSystemPrompt } from './prompts.js';
|
|
8
|
-
import { generateStoreScreenshots } from './screenshot-composer.js';
|
|
8
|
+
import { generateStoreScreenshots, } from './screenshot-composer.js';
|
|
9
9
|
import { uploadAppStoreScreenshots } from './uploader.js';
|
|
10
10
|
export const generateAppStoreAssets = async (options, config
|
|
11
11
|
// eslint-disable-next-line complexity -- orchestration function with sequential asset generation steps
|
|
@@ -17,7 +17,7 @@ export const generateAppStoreAssets = async (options, config
|
|
|
17
17
|
}
|
|
18
18
|
try {
|
|
19
19
|
// Resolve locale: use explicit param, or fetch from Apple App Store Connect
|
|
20
|
-
let locale = options
|
|
20
|
+
let { locale } = options;
|
|
21
21
|
if (!locale) {
|
|
22
22
|
logInfo('No locale specified, fetching primary locale from Apple App Store Connect...');
|
|
23
23
|
const appleLocale = await getAppStorePrimaryLocale(productId, verbose);
|
|
@@ -53,7 +53,8 @@ export const generateAppStoreAssets = async (options, config
|
|
|
53
53
|
if (!aiResult) {
|
|
54
54
|
throw new Error('No results received from AI');
|
|
55
55
|
}
|
|
56
|
-
const listings = (aiResult.listings ||
|
|
56
|
+
const listings = (aiResult.listings ||
|
|
57
|
+
{});
|
|
57
58
|
const screenshotSpecs = (aiResult.screenshots || []);
|
|
58
59
|
logInfo(`AI generated: ${Object.keys(listings).length} locale(s), ${screenshotSpecs.length} screenshot spec(s)`);
|
|
59
60
|
// Ensure store configs exist
|
|
@@ -52,7 +52,7 @@ async function composeStoreScreenshot(opts) {
|
|
|
52
52
|
}
|
|
53
53
|
async function loadChromium() {
|
|
54
54
|
try {
|
|
55
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-new-func -- dynamic import to avoid bundler resolution of optional peer dependency
|
|
56
56
|
const pw = await Function('return import("playwright")')();
|
|
57
57
|
return pw.chromium;
|
|
58
58
|
}
|
|
@@ -144,9 +144,8 @@ function createCompositionHtml(framedScreenshotDataUrl, spec, targetWidth, targe
|
|
|
144
144
|
</body>
|
|
145
145
|
</html>`;
|
|
146
146
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
return `<!DOCTYPE html>
|
|
147
|
+
// Landscape: text on left, device on right
|
|
148
|
+
return `<!DOCTYPE html>
|
|
150
149
|
<html>
|
|
151
150
|
<head>
|
|
152
151
|
<style>
|
|
@@ -206,7 +205,6 @@ function createCompositionHtml(framedScreenshotDataUrl, spec, targetWidth, targe
|
|
|
206
205
|
</div>
|
|
207
206
|
</body>
|
|
208
207
|
</html>`;
|
|
209
|
-
}
|
|
210
208
|
}
|
|
211
209
|
function escapeHtml(str) {
|
|
212
210
|
return str
|
|
@@ -48,7 +48,9 @@ function userMessage(content) {
|
|
|
48
48
|
}
|
|
49
49
|
async function* prompt(userPrompt) {
|
|
50
50
|
yield userMessage(userPrompt);
|
|
51
|
-
await new Promise((res) =>
|
|
51
|
+
await new Promise((res) => {
|
|
52
|
+
setTimeout(res, 10000);
|
|
53
|
+
});
|
|
52
54
|
}
|
|
53
55
|
/**
|
|
54
56
|
* Run a single autonomous iteration using Claude Code SDK
|
|
@@ -143,8 +145,7 @@ async function handleSuccessfulIteration(opts) {
|
|
|
143
145
|
let prNumber;
|
|
144
146
|
if (!prUrl) {
|
|
145
147
|
const prInfo = await createAutonomousPR(githubConfig, devBranchName, currentBranch, verbose);
|
|
146
|
-
prUrl = prInfo
|
|
147
|
-
prNumber = prInfo.prNumber;
|
|
148
|
+
({ prUrl, prNumber } = prInfo);
|
|
148
149
|
}
|
|
149
150
|
// Log iteration completion to audit logs
|
|
150
151
|
await logFeaturePhaseEvent({
|
|
@@ -11,7 +11,7 @@ export async function fetchBranchPlanningContext(featureId, verbose) {
|
|
|
11
11
|
logInfo(`Fetching branch planning context for feature: ${featureId}`);
|
|
12
12
|
}
|
|
13
13
|
// Fetch all required data in parallel for better performance
|
|
14
|
-
const [feature,
|
|
14
|
+
const [feature, userStories, testCases, existingBranches] = await Promise.all([
|
|
15
15
|
getFeature(featureId, verbose),
|
|
16
16
|
getUserStories(featureId, verbose),
|
|
17
17
|
getTestCases(featureId, verbose),
|
|
@@ -22,17 +22,17 @@ export async function fetchBranchPlanningContext(featureId, verbose) {
|
|
|
22
22
|
logInfo(`ā
Branch planning context fetched successfully:`);
|
|
23
23
|
logInfo(` Feature: ${feature.name}`);
|
|
24
24
|
logInfo(` Product: ${product.name}`);
|
|
25
|
-
logInfo(` User Stories: ${
|
|
26
|
-
logInfo(` Test Cases: ${
|
|
25
|
+
logInfo(` User Stories: ${userStories.length}`);
|
|
26
|
+
logInfo(` Test Cases: ${testCases.length}`);
|
|
27
27
|
logInfo(` Technical Design: ${feature.technical_design ? 'Yes' : 'No'}`);
|
|
28
|
-
logInfo(` Existing Branches: ${
|
|
28
|
+
logInfo(` Existing Branches: ${existingBranches.length}`);
|
|
29
29
|
}
|
|
30
30
|
return {
|
|
31
31
|
feature,
|
|
32
32
|
product,
|
|
33
|
-
user_stories,
|
|
34
|
-
test_cases,
|
|
35
|
-
existing_branches,
|
|
33
|
+
user_stories: userStories,
|
|
34
|
+
test_cases: testCases,
|
|
35
|
+
existing_branches: existingBranches,
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
catch (error) {
|
|
@@ -29,7 +29,9 @@ function userMessage(content) {
|
|
|
29
29
|
}
|
|
30
30
|
async function* prompt(analysisPrompt) {
|
|
31
31
|
yield userMessage(analysisPrompt);
|
|
32
|
-
await new Promise((res) =>
|
|
32
|
+
await new Promise((res) => {
|
|
33
|
+
setTimeout(res, 10000);
|
|
34
|
+
});
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
37
|
* Fetch feedbacks for branch planning phase
|
|
@@ -81,8 +83,8 @@ async function buildUserPrompt(opts) {
|
|
|
81
83
|
}
|
|
82
84
|
const feedbacksInfo = await formatFeedbacksForContext(feedbacksContext);
|
|
83
85
|
const currentPlanInfo = existingBranchesInfo || 'No existing branch plan documented.';
|
|
84
|
-
const
|
|
85
|
-
return `${
|
|
86
|
+
const systemPrompt = createImprovementPrompt(feedbacksInfo, currentPlanInfo);
|
|
87
|
+
return `${systemPrompt}\n\n## Feature Context\n\n${contextInfo}`;
|
|
86
88
|
}
|
|
87
89
|
return createBranchPlanningPromptWithContext(featureId, contextInfo, existingBranchesInfo || '');
|
|
88
90
|
}
|
|
@@ -27,7 +27,9 @@ function userMessage(content) {
|
|
|
27
27
|
}
|
|
28
28
|
async function* prompt(bugFixPrompt) {
|
|
29
29
|
yield userMessage(bugFixPrompt);
|
|
30
|
-
await new Promise((res) =>
|
|
30
|
+
await new Promise((res) => {
|
|
31
|
+
setTimeout(res, 10000);
|
|
32
|
+
});
|
|
31
33
|
}
|
|
32
34
|
export const fixTestFailures = async (options, config
|
|
33
35
|
// eslint-disable-next-line complexity -- orchestration function with agent setup, message processing, and result extraction
|
|
@@ -131,15 +133,13 @@ export const fixTestFailures = async (options, config
|
|
|
131
133
|
attemptNumber,
|
|
132
134
|
};
|
|
133
135
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
};
|
|
142
|
-
}
|
|
136
|
+
return {
|
|
137
|
+
featureId,
|
|
138
|
+
fixSummary: null,
|
|
139
|
+
status: 'error',
|
|
140
|
+
message: 'Bug fixing failed or incomplete',
|
|
141
|
+
attemptNumber,
|
|
142
|
+
};
|
|
143
143
|
}
|
|
144
144
|
catch (error) {
|
|
145
145
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -272,16 +272,16 @@ function parseBugFixResponse(response) {
|
|
|
272
272
|
const summaryMatch = response.match(/## Fix Summary\n([\s\S]*?)(?=\n##|\n\n|$)/);
|
|
273
273
|
const summary = summaryMatch ? summaryMatch[1].trim() : 'Bug fixes applied';
|
|
274
274
|
const filesMatch = response.match(/## Files Fixed\n([\s\S]*?)(?=\n##|\n\n|$)/);
|
|
275
|
-
let
|
|
275
|
+
let filesModified = [];
|
|
276
276
|
if (filesMatch) {
|
|
277
|
-
|
|
277
|
+
filesModified = filesMatch[1]
|
|
278
278
|
.split('\n')
|
|
279
279
|
.filter((line) => line.trim().startsWith('-'))
|
|
280
280
|
.map((line) => line.replace(/^-\s*/, '').trim());
|
|
281
281
|
}
|
|
282
282
|
return {
|
|
283
283
|
summary,
|
|
284
|
-
files_modified,
|
|
284
|
+
files_modified: filesModified,
|
|
285
285
|
tests_passed: true,
|
|
286
286
|
fixes_applied: [],
|
|
287
287
|
};
|
|
@@ -10,13 +10,13 @@ export async function fetchBugFixingContext(featureId, verbose) {
|
|
|
10
10
|
logInfo(`Fetching complete bug fixing context for feature: ${featureId}`);
|
|
11
11
|
}
|
|
12
12
|
// Fetch all required data in parallel for better performance
|
|
13
|
-
const [feature,
|
|
13
|
+
const [feature, userStories, testCases] = await Promise.all([
|
|
14
14
|
getFeature(featureId, verbose),
|
|
15
15
|
getUserStories(featureId, verbose),
|
|
16
16
|
getTestCases(featureId, verbose),
|
|
17
17
|
]);
|
|
18
18
|
// Get latest test report to understand what has been tested
|
|
19
|
-
let
|
|
19
|
+
let latestTestReport = null;
|
|
20
20
|
try {
|
|
21
21
|
if (verbose) {
|
|
22
22
|
logInfo('Fetching latest test report...');
|
|
@@ -25,7 +25,7 @@ export async function fetchBugFixingContext(featureId, verbose) {
|
|
|
25
25
|
feature_id: featureId,
|
|
26
26
|
}));
|
|
27
27
|
if (testReportResult.test_report) {
|
|
28
|
-
|
|
28
|
+
latestTestReport = testReportResult.test_report;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
catch (error) {
|
|
@@ -36,16 +36,16 @@ export async function fetchBugFixingContext(featureId, verbose) {
|
|
|
36
36
|
if (verbose) {
|
|
37
37
|
logInfo(`ā
Bug fixing context fetched successfully:`);
|
|
38
38
|
logInfo(` Feature: ${feature.name}`);
|
|
39
|
-
logInfo(` User Stories: ${
|
|
40
|
-
logInfo(` Test Cases: ${
|
|
39
|
+
logInfo(` User Stories: ${userStories.length}`);
|
|
40
|
+
logInfo(` Test Cases: ${testCases.length} (${testCases.filter((tc) => tc.is_critical).length} critical)`);
|
|
41
41
|
logInfo(` Technical Design: ${feature.technical_design ? 'Available' : 'Not available'}`);
|
|
42
|
-
logInfo(` Latest Test Report: ${
|
|
42
|
+
logInfo(` Latest Test Report: ${latestTestReport ? 'Available' : 'Not available'}`);
|
|
43
43
|
}
|
|
44
44
|
return {
|
|
45
45
|
feature,
|
|
46
|
-
user_stories,
|
|
47
|
-
test_cases,
|
|
48
|
-
latest_test_report,
|
|
46
|
+
user_stories: userStories,
|
|
47
|
+
test_cases: testCases,
|
|
48
|
+
latest_test_report: latestTestReport,
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
51
|
catch (error) {
|
|
@@ -58,23 +58,20 @@ export const createBugFixingMcpServer = () => {
|
|
|
58
58
|
files_modified: z
|
|
59
59
|
.array(z.string())
|
|
60
60
|
.describe('List of files that were modified'),
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
],
|
|
76
|
-
};
|
|
77
|
-
}),
|
|
61
|
+
}, (args) => Promise.resolve({
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: 'text',
|
|
65
|
+
text: JSON.stringify({
|
|
66
|
+
verified: true,
|
|
67
|
+
feature_id: args.feature_id,
|
|
68
|
+
summary: args.fix_summary,
|
|
69
|
+
files_modified: args.files_modified,
|
|
70
|
+
message: 'Bug fix verification complete',
|
|
71
|
+
}, null, 2),
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
})),
|
|
78
75
|
],
|
|
79
76
|
});
|
|
80
77
|
};
|
|
@@ -10,7 +10,7 @@ export async function fetchCodeImplementationContext(featureId, verbose) {
|
|
|
10
10
|
logInfo(`Fetching complete code implementation context for feature: ${featureId}`);
|
|
11
11
|
}
|
|
12
12
|
// Fetch all required data in parallel for better performance
|
|
13
|
-
const [feature,
|
|
13
|
+
const [feature, userStories, testCases] = await Promise.all([
|
|
14
14
|
getFeature(featureId, verbose),
|
|
15
15
|
getUserStories(featureId, verbose),
|
|
16
16
|
getTestCases(featureId, verbose),
|
|
@@ -20,15 +20,15 @@ export async function fetchCodeImplementationContext(featureId, verbose) {
|
|
|
20
20
|
logInfo(`ā
Code implementation context fetched successfully:`);
|
|
21
21
|
logInfo(` Feature: ${feature.name}`);
|
|
22
22
|
logInfo(` Product: ${product.name}`);
|
|
23
|
-
logInfo(` User Stories: ${
|
|
24
|
-
logInfo(` Test Cases: ${
|
|
23
|
+
logInfo(` User Stories: ${userStories.length}`);
|
|
24
|
+
logInfo(` Test Cases: ${testCases.length}`);
|
|
25
25
|
logInfo(` Technical Design: ${feature.technical_design ? 'Available' : 'Not available'}`);
|
|
26
26
|
}
|
|
27
27
|
return {
|
|
28
28
|
feature,
|
|
29
29
|
product,
|
|
30
|
-
user_stories,
|
|
31
|
-
test_cases,
|
|
30
|
+
user_stories: userStories,
|
|
31
|
+
test_cases: testCases,
|
|
32
32
|
technical_design: feature.technical_design,
|
|
33
33
|
};
|
|
34
34
|
}
|
|
@@ -33,7 +33,9 @@ function userMessage(content) {
|
|
|
33
33
|
}
|
|
34
34
|
async function* prompt(implementationPrompt) {
|
|
35
35
|
yield userMessage(implementationPrompt);
|
|
36
|
-
await new Promise((res) =>
|
|
36
|
+
await new Promise((res) => {
|
|
37
|
+
setTimeout(res, 10000);
|
|
38
|
+
});
|
|
37
39
|
}
|
|
38
40
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
41
|
function processAssistantContent(content, verbose) {
|
|
@@ -265,8 +267,7 @@ export const implementFeatureCode = async (options, config, checklistContext
|
|
|
265
267
|
});
|
|
266
268
|
const baseBranchInfo = getBaseBranchInfo(currentBranch, allBranches, baseBranch);
|
|
267
269
|
actualBaseBranch = baseBranchInfo.baseBranch;
|
|
268
|
-
rebaseTargetBranch = baseBranchInfo
|
|
269
|
-
originalBaseBranch = baseBranchInfo.originalBaseBranch;
|
|
270
|
+
({ rebaseTargetBranch, originalBaseBranch } = baseBranchInfo);
|
|
270
271
|
baseBranchCompleted = baseBranchInfo.baseBranchCompleted || false;
|
|
271
272
|
if (verbose) {
|
|
272
273
|
logInfo(`š Branch chaining detected:`);
|
|
@@ -525,7 +526,7 @@ export const implementFeatureCode = async (options, config, checklistContext
|
|
|
525
526
|
maxIterations,
|
|
526
527
|
verbose,
|
|
527
528
|
});
|
|
528
|
-
verificationResult = verificationCycle
|
|
529
|
+
({ verificationResult } = verificationCycle);
|
|
529
530
|
// If verification passed, exit
|
|
530
531
|
if (verificationCycle.passed) {
|
|
531
532
|
if (verbose) {
|
|
@@ -10,7 +10,9 @@ function userMessage(content) {
|
|
|
10
10
|
}
|
|
11
11
|
async function* prompt(verificationPrompt) {
|
|
12
12
|
yield userMessage(verificationPrompt);
|
|
13
|
-
await new Promise((res) =>
|
|
13
|
+
await new Promise((res) => {
|
|
14
|
+
setTimeout(res, 10000);
|
|
15
|
+
});
|
|
14
16
|
}
|
|
15
17
|
const FAILED_VERIFICATION = {
|
|
16
18
|
overall_status: 'failed',
|
|
@@ -118,7 +118,7 @@ export async function fetchPRDataGraphQL(octokit, owner, repo, prNumber, verbose
|
|
|
118
118
|
repo,
|
|
119
119
|
prNumber,
|
|
120
120
|
});
|
|
121
|
-
const pullRequest = result.repository
|
|
121
|
+
const { pullRequest } = result.repository;
|
|
122
122
|
// Transform GraphQL reviews to our interface
|
|
123
123
|
const reviews = (pullRequest.reviews.nodes || []).map(
|
|
124
124
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -9,8 +9,8 @@ import { getBaseBranchInfo, getBranches, updateBranch, } from '../../services/br
|
|
|
9
9
|
import { getUncommittedFiles, hasUncommittedChanges, prepareCustomBranchGitEnvironmentAsync, preparePhaseGitEnvironmentAsync, syncFeatBranchWithMain, } from '../../utils/git-branch-manager.js';
|
|
10
10
|
import { gitPushCurrentBranch } from '../../utils/git-push.js';
|
|
11
11
|
import { logError, logInfo } from '../../utils/logger.js';
|
|
12
|
-
import { fetchCodeRefineContext } from './context.js';
|
|
13
12
|
import { verifyAndResolveComments, } from '../code-refine-verification/index.js';
|
|
13
|
+
import { fetchCodeRefineContext } from './context.js';
|
|
14
14
|
import { executeRefineIteration } from './refine-iteration.js';
|
|
15
15
|
/**
|
|
16
16
|
* Log base branch info for verbose mode
|
|
@@ -295,7 +295,7 @@ Please ensure Claude Code commits all changes before completing the refine phase
|
|
|
295
295
|
const verificationData = verificationResult.data;
|
|
296
296
|
const suggestions = verificationData.suggestions || [];
|
|
297
297
|
const unresolvedCommentDetails = verificationData.unresolvedCommentDetails || [];
|
|
298
|
-
const unresolvedReviewDetails = verificationData
|
|
298
|
+
const { unresolvedReviewDetails } = verificationData;
|
|
299
299
|
verificationFailureContext = {
|
|
300
300
|
attempt: currentIteration + 1,
|
|
301
301
|
suggestions,
|
|
@@ -313,11 +313,9 @@ Please ensure Claude Code commits all changes before completing the refine phase
|
|
|
313
313
|
logInfo(`\nš Will retry... (${MAX_REFINE_ITERATIONS - currentIteration} attempts remaining)`);
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
|
-
else {
|
|
316
|
+
else if (verbose) {
|
|
317
317
|
// Max iterations reached
|
|
318
|
-
|
|
319
|
-
logInfo(`\nā ļø Maximum iterations (${MAX_REFINE_ITERATIONS}) reached. Verification still failing.`);
|
|
320
|
-
}
|
|
318
|
+
logInfo(`\nā ļø Maximum iterations (${MAX_REFINE_ITERATIONS}) reached. Verification still failing.`);
|
|
321
319
|
}
|
|
322
320
|
}
|
|
323
321
|
// Return last verification result (which failed)
|