@nathapp/nax 0.36.1 → 0.36.2
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/nax.js +323 -51
- package/package.json +1 -1
- package/src/execution/dry-run.ts +1 -1
- package/src/execution/escalation/escalation.ts +5 -3
- package/src/execution/escalation/tier-escalation.ts +41 -4
- package/src/execution/iteration-runner.ts +5 -0
- package/src/execution/parallel-executor.ts +293 -9
- package/src/execution/parallel.ts +40 -21
- package/src/execution/pipeline-result-handler.ts +3 -2
- package/src/execution/runner.ts +13 -3
- package/src/metrics/tracker.ts +8 -4
- package/src/metrics/types.ts +2 -0
- package/src/pipeline/event-bus.ts +1 -1
- package/src/pipeline/stages/completion.ts +1 -1
- package/src/pipeline/stages/verify.ts +8 -1
- package/src/pipeline/subscribers/reporters.ts +3 -3
- package/src/pipeline/types.ts +4 -0
- package/src/plugins/types.ts +1 -1
- package/src/prd/types.ts +2 -0
- package/src/tdd/types.ts +2 -1
- package/src/verification/crash-detector.ts +34 -0
- package/src/verification/orchestrator-types.ts +8 -1
package/dist/nax.js
CHANGED
|
@@ -20063,6 +20063,22 @@ function computeStoryContentHash(story) {
|
|
|
20063
20063
|
}
|
|
20064
20064
|
|
|
20065
20065
|
// src/routing/index.ts
|
|
20066
|
+
var exports_routing = {};
|
|
20067
|
+
__export(exports_routing, {
|
|
20068
|
+
tryLlmBatchRoute: () => tryLlmBatchRoute,
|
|
20069
|
+
routeTask: () => routeTask,
|
|
20070
|
+
routeStory: () => routeStory,
|
|
20071
|
+
manualStrategy: () => manualStrategy,
|
|
20072
|
+
loadCustomStrategy: () => loadCustomStrategy,
|
|
20073
|
+
llmStrategy: () => llmStrategy,
|
|
20074
|
+
keywordStrategy: () => keywordStrategy,
|
|
20075
|
+
determineTestStrategy: () => determineTestStrategy2,
|
|
20076
|
+
computeStoryContentHash: () => computeStoryContentHash,
|
|
20077
|
+
complexityToModelTier: () => complexityToModelTier2,
|
|
20078
|
+
classifyComplexity: () => classifyComplexity2,
|
|
20079
|
+
buildStrategyChain: () => buildStrategyChain,
|
|
20080
|
+
StrategyChain: () => StrategyChain
|
|
20081
|
+
});
|
|
20066
20082
|
var init_routing = __esm(() => {
|
|
20067
20083
|
init_router();
|
|
20068
20084
|
init_chain();
|
|
@@ -20657,7 +20673,7 @@ var package_default;
|
|
|
20657
20673
|
var init_package = __esm(() => {
|
|
20658
20674
|
package_default = {
|
|
20659
20675
|
name: "@nathapp/nax",
|
|
20660
|
-
version: "0.36.
|
|
20676
|
+
version: "0.36.2",
|
|
20661
20677
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
20662
20678
|
type: "module",
|
|
20663
20679
|
bin: {
|
|
@@ -20718,8 +20734,8 @@ var init_version = __esm(() => {
|
|
|
20718
20734
|
NAX_VERSION = package_default.version;
|
|
20719
20735
|
NAX_COMMIT = (() => {
|
|
20720
20736
|
try {
|
|
20721
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
20722
|
-
return "
|
|
20737
|
+
if (/^[0-9a-f]{6,10}$/.test("eb77e7d"))
|
|
20738
|
+
return "eb77e7d";
|
|
20723
20739
|
} catch {}
|
|
20724
20740
|
try {
|
|
20725
20741
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|
|
@@ -20791,9 +20807,10 @@ function collectStoryMetrics(ctx, storyStartTime) {
|
|
|
20791
20807
|
const routing = ctx.routing;
|
|
20792
20808
|
const agentResult = ctx.agentResult;
|
|
20793
20809
|
const escalationCount = story.escalations?.length || 0;
|
|
20794
|
-
const
|
|
20810
|
+
const priorFailureCount = story.priorFailures?.length || 0;
|
|
20811
|
+
const attempts = priorFailureCount + Math.max(1, story.attempts || 1);
|
|
20795
20812
|
const finalTier = escalationCount > 0 ? story.escalations[escalationCount - 1].toTier : routing.modelTier;
|
|
20796
|
-
const firstPassSuccess = agentResult?.success === true && escalationCount === 0;
|
|
20813
|
+
const firstPassSuccess = agentResult?.success === true && escalationCount === 0 && priorFailureCount === 0;
|
|
20797
20814
|
const modelEntry = ctx.config.models[routing.modelTier];
|
|
20798
20815
|
const modelDef = modelEntry ? resolveModel(modelEntry) : null;
|
|
20799
20816
|
const modelUsed = modelDef?.model || routing.modelTier;
|
|
@@ -20809,12 +20826,13 @@ function collectStoryMetrics(ctx, storyStartTime) {
|
|
|
20809
20826
|
attempts,
|
|
20810
20827
|
finalTier,
|
|
20811
20828
|
success: agentResult?.success || false,
|
|
20812
|
-
cost: agentResult?.estimatedCost || 0,
|
|
20829
|
+
cost: (ctx.accumulatedAttemptCost ?? 0) + (agentResult?.estimatedCost || 0),
|
|
20813
20830
|
durationMs: agentResult?.durationMs || 0,
|
|
20814
20831
|
firstPassSuccess,
|
|
20815
20832
|
startedAt: storyStartTime,
|
|
20816
20833
|
completedAt: new Date().toISOString(),
|
|
20817
|
-
fullSuiteGatePassed
|
|
20834
|
+
fullSuiteGatePassed,
|
|
20835
|
+
runtimeCrashes: ctx.storyRuntimeCrashes ?? 0
|
|
20818
20836
|
};
|
|
20819
20837
|
}
|
|
20820
20838
|
function collectBatchMetrics(ctx, storyStartTime) {
|
|
@@ -20844,7 +20862,8 @@ function collectBatchMetrics(ctx, storyStartTime) {
|
|
|
20844
20862
|
firstPassSuccess: true,
|
|
20845
20863
|
startedAt: storyStartTime,
|
|
20846
20864
|
completedAt: new Date().toISOString(),
|
|
20847
|
-
fullSuiteGatePassed: false
|
|
20865
|
+
fullSuiteGatePassed: false,
|
|
20866
|
+
runtimeCrashes: 0
|
|
20848
20867
|
};
|
|
20849
20868
|
});
|
|
20850
20869
|
}
|
|
@@ -22227,6 +22246,11 @@ var init_interaction = __esm(() => {
|
|
|
22227
22246
|
});
|
|
22228
22247
|
|
|
22229
22248
|
// src/pipeline/runner.ts
|
|
22249
|
+
var exports_runner = {};
|
|
22250
|
+
__export(exports_runner, {
|
|
22251
|
+
runPipeline: () => runPipeline,
|
|
22252
|
+
MAX_STAGE_RETRIES: () => MAX_STAGE_RETRIES
|
|
22253
|
+
});
|
|
22230
22254
|
async function runPipeline(stages, context, eventEmitter) {
|
|
22231
22255
|
const logger = getLogger();
|
|
22232
22256
|
const retryCountMap = new Map;
|
|
@@ -22946,7 +22970,7 @@ var init_completion = __esm(() => {
|
|
|
22946
22970
|
storyId: completedStory.id,
|
|
22947
22971
|
story: completedStory,
|
|
22948
22972
|
passed: true,
|
|
22949
|
-
|
|
22973
|
+
runElapsedMs: storyMetric?.durationMs ?? 0,
|
|
22950
22974
|
cost: costPerStory,
|
|
22951
22975
|
modelTier: ctx.routing?.modelTier,
|
|
22952
22976
|
testStrategy: ctx.routing?.testStrategy
|
|
@@ -27456,6 +27480,22 @@ var init_routing2 = __esm(() => {
|
|
|
27456
27480
|
};
|
|
27457
27481
|
});
|
|
27458
27482
|
|
|
27483
|
+
// src/verification/crash-detector.ts
|
|
27484
|
+
function detectRuntimeCrash(output) {
|
|
27485
|
+
if (!output)
|
|
27486
|
+
return false;
|
|
27487
|
+
return CRASH_PATTERNS.some((pattern) => output.includes(pattern));
|
|
27488
|
+
}
|
|
27489
|
+
var CRASH_PATTERNS;
|
|
27490
|
+
var init_crash_detector = __esm(() => {
|
|
27491
|
+
CRASH_PATTERNS = [
|
|
27492
|
+
"panic(main thread)",
|
|
27493
|
+
"Segmentation fault",
|
|
27494
|
+
"Bun has crashed",
|
|
27495
|
+
"oh no: Bun has crashed"
|
|
27496
|
+
];
|
|
27497
|
+
});
|
|
27498
|
+
|
|
27459
27499
|
// src/pipeline/stages/verify.ts
|
|
27460
27500
|
function coerceSmartTestRunner(val) {
|
|
27461
27501
|
if (val === undefined || val === true)
|
|
@@ -27473,6 +27513,7 @@ function buildScopedCommand2(testFiles, baseCommand, testScopedTemplate) {
|
|
|
27473
27513
|
var DEFAULT_SMART_RUNNER_CONFIG2, verifyStage, _verifyDeps;
|
|
27474
27514
|
var init_verify = __esm(() => {
|
|
27475
27515
|
init_logger2();
|
|
27516
|
+
init_crash_detector();
|
|
27476
27517
|
init_runners();
|
|
27477
27518
|
init_smart_runner();
|
|
27478
27519
|
DEFAULT_SMART_RUNNER_CONFIG2 = {
|
|
@@ -27544,7 +27585,7 @@ var init_verify = __esm(() => {
|
|
|
27544
27585
|
});
|
|
27545
27586
|
ctx.verifyResult = {
|
|
27546
27587
|
success: result.success,
|
|
27547
|
-
status: result.status === "TIMEOUT" ? "TIMEOUT" : result.success ? "PASS" : "TEST_FAILURE",
|
|
27588
|
+
status: result.status === "TIMEOUT" ? "TIMEOUT" : result.success ? "PASS" : detectRuntimeCrash(result.output) ? "RUNTIME_CRASH" : "TEST_FAILURE",
|
|
27548
27589
|
storyId: ctx.story.id,
|
|
27549
27590
|
strategy: "scoped",
|
|
27550
27591
|
passCount: result.passCount ?? 0,
|
|
@@ -27595,6 +27636,25 @@ var init_verify = __esm(() => {
|
|
|
27595
27636
|
});
|
|
27596
27637
|
|
|
27597
27638
|
// src/pipeline/stages/index.ts
|
|
27639
|
+
var exports_stages = {};
|
|
27640
|
+
__export(exports_stages, {
|
|
27641
|
+
verifyStage: () => verifyStage,
|
|
27642
|
+
routingStage: () => routingStage,
|
|
27643
|
+
reviewStage: () => reviewStage,
|
|
27644
|
+
regressionStage: () => regressionStage,
|
|
27645
|
+
rectifyStage: () => rectifyStage,
|
|
27646
|
+
queueCheckStage: () => queueCheckStage,
|
|
27647
|
+
promptStage: () => promptStage,
|
|
27648
|
+
postRunPipeline: () => postRunPipeline,
|
|
27649
|
+
optimizerStage: () => optimizerStage,
|
|
27650
|
+
executionStage: () => executionStage,
|
|
27651
|
+
defaultPipeline: () => defaultPipeline,
|
|
27652
|
+
contextStage: () => contextStage,
|
|
27653
|
+
constitutionStage: () => constitutionStage,
|
|
27654
|
+
completionStage: () => completionStage,
|
|
27655
|
+
autofixStage: () => autofixStage,
|
|
27656
|
+
acceptanceStage: () => acceptanceStage
|
|
27657
|
+
});
|
|
27598
27658
|
var defaultPipeline, postRunPipeline;
|
|
27599
27659
|
var init_stages = __esm(() => {
|
|
27600
27660
|
init_acceptance2();
|
|
@@ -29244,11 +29304,12 @@ var init_crash_recovery = __esm(() => {
|
|
|
29244
29304
|
|
|
29245
29305
|
// src/execution/escalation/escalation.ts
|
|
29246
29306
|
function escalateTier(currentTier, tierOrder) {
|
|
29247
|
-
const
|
|
29307
|
+
const getName = (t) => t.tier ?? t.name ?? null;
|
|
29308
|
+
const currentIndex = tierOrder.findIndex((t) => getName(t) === currentTier);
|
|
29248
29309
|
if (currentIndex === -1 || currentIndex === tierOrder.length - 1) {
|
|
29249
29310
|
return null;
|
|
29250
29311
|
}
|
|
29251
|
-
return tierOrder[currentIndex + 1]
|
|
29312
|
+
return getName(tierOrder[currentIndex + 1]);
|
|
29252
29313
|
}
|
|
29253
29314
|
function calculateMaxIterations(tierOrder) {
|
|
29254
29315
|
return tierOrder.reduce((sum, t) => sum + t.attempts, 0);
|
|
@@ -29345,13 +29406,14 @@ var init_tier_outcome = __esm(() => {
|
|
|
29345
29406
|
});
|
|
29346
29407
|
|
|
29347
29408
|
// src/execution/escalation/tier-escalation.ts
|
|
29348
|
-
function buildEscalationFailure(story, currentTier, reviewFindings) {
|
|
29409
|
+
function buildEscalationFailure(story, currentTier, reviewFindings, cost) {
|
|
29349
29410
|
return {
|
|
29350
29411
|
attempt: (story.attempts ?? 0) + 1,
|
|
29351
29412
|
modelTier: currentTier,
|
|
29352
29413
|
stage: "escalation",
|
|
29353
29414
|
summary: `Failed with tier ${currentTier}, escalating to next tier`,
|
|
29354
29415
|
reviewFindings: reviewFindings && reviewFindings.length > 0 ? reviewFindings : undefined,
|
|
29416
|
+
cost: cost ?? 0,
|
|
29355
29417
|
timestamp: new Date().toISOString()
|
|
29356
29418
|
};
|
|
29357
29419
|
}
|
|
@@ -29364,6 +29426,8 @@ function resolveMaxAttemptsOutcome(failureCategory) {
|
|
|
29364
29426
|
case "verifier-rejected":
|
|
29365
29427
|
case "greenfield-no-tests":
|
|
29366
29428
|
return "pause";
|
|
29429
|
+
case "runtime-crash":
|
|
29430
|
+
return "pause";
|
|
29367
29431
|
case "session-failure":
|
|
29368
29432
|
case "tests-failing":
|
|
29369
29433
|
return "fail";
|
|
@@ -29387,8 +29451,17 @@ async function tryLlmBatchRoute2(config2, stories, label = "routing") {
|
|
|
29387
29451
|
});
|
|
29388
29452
|
}
|
|
29389
29453
|
}
|
|
29454
|
+
function shouldRetrySameTier(verifyResult) {
|
|
29455
|
+
return verifyResult?.status === "RUNTIME_CRASH";
|
|
29456
|
+
}
|
|
29390
29457
|
async function handleTierEscalation(ctx) {
|
|
29391
29458
|
const logger = getSafeLogger();
|
|
29459
|
+
if (shouldRetrySameTier(ctx.verifyResult)) {
|
|
29460
|
+
logger?.warn("escalation", "Runtime crash detected \u2014 retrying same tier (transient, not a code issue)", {
|
|
29461
|
+
storyId: ctx.story.id
|
|
29462
|
+
});
|
|
29463
|
+
return { outcome: "retry-same", prdDirty: false, prd: ctx.prd };
|
|
29464
|
+
}
|
|
29392
29465
|
const nextTier = escalateTier(ctx.routing.modelTier, ctx.config.autoMode.escalation.tierOrder);
|
|
29393
29466
|
const escalateWholeBatch = ctx.config.autoMode.escalation.escalateEntireBatch ?? true;
|
|
29394
29467
|
const storiesToEscalate = ctx.isBatchExecution && escalateWholeBatch ? ctx.storiesToExecute : [ctx.story];
|
|
@@ -29442,7 +29515,7 @@ async function handleTierEscalation(ctx) {
|
|
|
29442
29515
|
const currentStoryTier = s.routing?.modelTier ?? ctx.routing.modelTier;
|
|
29443
29516
|
const isChangingTier = currentStoryTier !== nextTier;
|
|
29444
29517
|
const shouldResetAttempts = isChangingTier || shouldSwitchToTestAfter;
|
|
29445
|
-
const escalationFailure = buildEscalationFailure(s, currentStoryTier, escalateReviewFindings);
|
|
29518
|
+
const escalationFailure = buildEscalationFailure(s, currentStoryTier, escalateReviewFindings, ctx.attemptCost);
|
|
29446
29519
|
return {
|
|
29447
29520
|
...s,
|
|
29448
29521
|
attempts: shouldResetAttempts ? 0 : (s.attempts ?? 0) + 1,
|
|
@@ -29452,7 +29525,7 @@ async function handleTierEscalation(ctx) {
|
|
|
29452
29525
|
};
|
|
29453
29526
|
})
|
|
29454
29527
|
};
|
|
29455
|
-
await savePRD(updatedPrd, ctx.prdPath);
|
|
29528
|
+
await _tierEscalationDeps.savePRD(updatedPrd, ctx.prdPath);
|
|
29456
29529
|
for (const story of storiesToEscalate) {
|
|
29457
29530
|
clearCacheForStory(story.id);
|
|
29458
29531
|
}
|
|
@@ -29465,6 +29538,7 @@ async function handleTierEscalation(ctx) {
|
|
|
29465
29538
|
prd: updatedPrd
|
|
29466
29539
|
};
|
|
29467
29540
|
}
|
|
29541
|
+
var _tierEscalationDeps;
|
|
29468
29542
|
var init_tier_escalation = __esm(() => {
|
|
29469
29543
|
init_hooks();
|
|
29470
29544
|
init_logger2();
|
|
@@ -29474,6 +29548,9 @@ var init_tier_escalation = __esm(() => {
|
|
|
29474
29548
|
init_helpers();
|
|
29475
29549
|
init_progress();
|
|
29476
29550
|
init_tier_outcome();
|
|
29551
|
+
_tierEscalationDeps = {
|
|
29552
|
+
savePRD
|
|
29553
|
+
};
|
|
29477
29554
|
});
|
|
29478
29555
|
|
|
29479
29556
|
// src/execution/escalation/index.ts
|
|
@@ -30075,6 +30152,10 @@ var init_headless_formatter = __esm(() => {
|
|
|
30075
30152
|
});
|
|
30076
30153
|
|
|
30077
30154
|
// src/worktree/manager.ts
|
|
30155
|
+
var exports_manager = {};
|
|
30156
|
+
__export(exports_manager, {
|
|
30157
|
+
WorktreeManager: () => WorktreeManager
|
|
30158
|
+
});
|
|
30078
30159
|
import { existsSync as existsSync26, symlinkSync } from "fs";
|
|
30079
30160
|
import { join as join32 } from "path";
|
|
30080
30161
|
|
|
@@ -30219,6 +30300,11 @@ var init_manager = __esm(() => {
|
|
|
30219
30300
|
});
|
|
30220
30301
|
|
|
30221
30302
|
// src/worktree/merge.ts
|
|
30303
|
+
var exports_merge = {};
|
|
30304
|
+
__export(exports_merge, {
|
|
30305
|
+
MergeEngine: () => MergeEngine
|
|
30306
|
+
});
|
|
30307
|
+
|
|
30222
30308
|
class MergeEngine {
|
|
30223
30309
|
worktreeManager;
|
|
30224
30310
|
constructor(worktreeManager) {
|
|
@@ -30497,10 +30583,12 @@ async function executeParallelBatch(stories, projectRoot, config2, prd, context,
|
|
|
30497
30583
|
const logger = getSafeLogger();
|
|
30498
30584
|
const worktreeManager = new WorktreeManager;
|
|
30499
30585
|
const results = {
|
|
30500
|
-
|
|
30501
|
-
|
|
30586
|
+
pipelinePassed: [],
|
|
30587
|
+
merged: [],
|
|
30588
|
+
failed: [],
|
|
30502
30589
|
totalCost: 0,
|
|
30503
|
-
|
|
30590
|
+
mergeConflicts: [],
|
|
30591
|
+
storyCosts: new Map
|
|
30504
30592
|
};
|
|
30505
30593
|
const worktreeSetup = [];
|
|
30506
30594
|
for (const story of stories) {
|
|
@@ -30513,7 +30601,7 @@ async function executeParallelBatch(stories, projectRoot, config2, prd, context,
|
|
|
30513
30601
|
worktreePath
|
|
30514
30602
|
});
|
|
30515
30603
|
} catch (error48) {
|
|
30516
|
-
results.
|
|
30604
|
+
results.failed.push({
|
|
30517
30605
|
story,
|
|
30518
30606
|
error: `Failed to create worktree: ${error48 instanceof Error ? error48.message : String(error48)}`
|
|
30519
30607
|
});
|
|
@@ -30528,14 +30616,15 @@ async function executeParallelBatch(stories, projectRoot, config2, prd, context,
|
|
|
30528
30616
|
const routing = routeTask(story.title, story.description, story.acceptanceCriteria, story.tags, config2);
|
|
30529
30617
|
const executePromise = executeStoryInWorktree(story, worktreePath, context, routing, eventEmitter).then((result) => {
|
|
30530
30618
|
results.totalCost += result.cost;
|
|
30619
|
+
results.storyCosts.set(story.id, result.cost);
|
|
30531
30620
|
if (result.success) {
|
|
30532
|
-
results.
|
|
30621
|
+
results.pipelinePassed.push(story);
|
|
30533
30622
|
logger?.info("parallel", "Story execution succeeded", {
|
|
30534
30623
|
storyId: story.id,
|
|
30535
30624
|
cost: result.cost
|
|
30536
30625
|
});
|
|
30537
30626
|
} else {
|
|
30538
|
-
results.
|
|
30627
|
+
results.failed.push({ story, error: result.error || "Unknown error" });
|
|
30539
30628
|
logger?.error("parallel", "Story execution failed", {
|
|
30540
30629
|
storyId: story.id,
|
|
30541
30630
|
error: result.error
|
|
@@ -30575,6 +30664,7 @@ async function executeParallel(stories, prdPath, projectRoot, config2, hooks, pl
|
|
|
30575
30664
|
let storiesCompleted = 0;
|
|
30576
30665
|
let totalCost = 0;
|
|
30577
30666
|
const currentPrd = prd;
|
|
30667
|
+
const allMergeConflicts = [];
|
|
30578
30668
|
for (let batchIndex = 0;batchIndex < batches.length; batchIndex++) {
|
|
30579
30669
|
const batch = batches[batchIndex];
|
|
30580
30670
|
logger?.info("parallel", `Executing batch ${batchIndex + 1}/${batches.length}`, {
|
|
@@ -30591,8 +30681,8 @@ async function executeParallel(stories, prdPath, projectRoot, config2, hooks, pl
|
|
|
30591
30681
|
};
|
|
30592
30682
|
const batchResult = await executeParallelBatch(batch, projectRoot, config2, currentPrd, baseContext, maxConcurrency, eventEmitter);
|
|
30593
30683
|
totalCost += batchResult.totalCost;
|
|
30594
|
-
if (batchResult.
|
|
30595
|
-
const successfulIds = batchResult.
|
|
30684
|
+
if (batchResult.pipelinePassed.length > 0) {
|
|
30685
|
+
const successfulIds = batchResult.pipelinePassed.map((s) => s.id);
|
|
30596
30686
|
const deps = buildDependencyMap(batch);
|
|
30597
30687
|
logger?.info("parallel", "Merging successful stories", {
|
|
30598
30688
|
storyIds: successfulIds
|
|
@@ -30602,15 +30692,19 @@ async function executeParallel(stories, prdPath, projectRoot, config2, hooks, pl
|
|
|
30602
30692
|
if (mergeResult.success) {
|
|
30603
30693
|
markStoryPassed(currentPrd, mergeResult.storyId);
|
|
30604
30694
|
storiesCompleted++;
|
|
30695
|
+
const mergedStory = batchResult.pipelinePassed.find((s) => s.id === mergeResult.storyId);
|
|
30696
|
+
if (mergedStory)
|
|
30697
|
+
batchResult.merged.push(mergedStory);
|
|
30605
30698
|
logger?.info("parallel", "Story merged successfully", {
|
|
30606
30699
|
storyId: mergeResult.storyId,
|
|
30607
30700
|
retryCount: mergeResult.retryCount
|
|
30608
30701
|
});
|
|
30609
30702
|
} else {
|
|
30610
30703
|
markStoryFailed(currentPrd, mergeResult.storyId);
|
|
30611
|
-
batchResult.
|
|
30704
|
+
batchResult.mergeConflicts.push({
|
|
30612
30705
|
storyId: mergeResult.storyId,
|
|
30613
|
-
conflictFiles: mergeResult.conflictFiles || []
|
|
30706
|
+
conflictFiles: mergeResult.conflictFiles || [],
|
|
30707
|
+
originalCost: batchResult.storyCosts.get(mergeResult.storyId) ?? 0
|
|
30614
30708
|
});
|
|
30615
30709
|
logger?.error("parallel", "Merge conflict", {
|
|
30616
30710
|
storyId: mergeResult.storyId,
|
|
@@ -30623,7 +30717,7 @@ async function executeParallel(stories, prdPath, projectRoot, config2, hooks, pl
|
|
|
30623
30717
|
}
|
|
30624
30718
|
}
|
|
30625
30719
|
}
|
|
30626
|
-
for (const { story, error: error48 } of batchResult.
|
|
30720
|
+
for (const { story, error: error48 } of batchResult.failed) {
|
|
30627
30721
|
markStoryFailed(currentPrd, story.id);
|
|
30628
30722
|
logger?.error("parallel", "Cleaning up failed story worktree", {
|
|
30629
30723
|
storyId: story.id,
|
|
@@ -30639,10 +30733,12 @@ async function executeParallel(stories, prdPath, projectRoot, config2, hooks, pl
|
|
|
30639
30733
|
}
|
|
30640
30734
|
}
|
|
30641
30735
|
await savePRD(currentPrd, prdPath);
|
|
30736
|
+
allMergeConflicts.push(...batchResult.mergeConflicts);
|
|
30642
30737
|
logger?.info("parallel", `Batch ${batchIndex + 1} complete`, {
|
|
30643
|
-
|
|
30644
|
-
|
|
30645
|
-
|
|
30738
|
+
pipelinePassed: batchResult.pipelinePassed.length,
|
|
30739
|
+
merged: batchResult.merged.length,
|
|
30740
|
+
failed: batchResult.failed.length,
|
|
30741
|
+
mergeConflicts: batchResult.mergeConflicts.length,
|
|
30646
30742
|
batchCost: batchResult.totalCost
|
|
30647
30743
|
});
|
|
30648
30744
|
}
|
|
@@ -30650,7 +30746,7 @@ async function executeParallel(stories, prdPath, projectRoot, config2, hooks, pl
|
|
|
30650
30746
|
storiesCompleted,
|
|
30651
30747
|
totalCost
|
|
30652
30748
|
});
|
|
30653
|
-
return { storiesCompleted, totalCost, updatedPrd: currentPrd };
|
|
30749
|
+
return { storiesCompleted, totalCost, updatedPrd: currentPrd, mergeConflicts: allMergeConflicts };
|
|
30654
30750
|
}
|
|
30655
30751
|
var init_parallel = __esm(() => {
|
|
30656
30752
|
init_logger2();
|
|
@@ -30742,6 +30838,123 @@ __export(exports_parallel_executor, {
|
|
|
30742
30838
|
});
|
|
30743
30839
|
import * as os5 from "os";
|
|
30744
30840
|
import path15 from "path";
|
|
30841
|
+
async function rectifyConflictedStory(options) {
|
|
30842
|
+
const { storyId, workdir, config: config2, hooks, pluginRegistry, prd, eventEmitter } = options;
|
|
30843
|
+
const logger = getSafeLogger();
|
|
30844
|
+
logger?.info("parallel", "Rectifying story on updated base", { storyId, attempt: "rectification" });
|
|
30845
|
+
try {
|
|
30846
|
+
const { WorktreeManager: WorktreeManager2 } = await Promise.resolve().then(() => (init_manager(), exports_manager));
|
|
30847
|
+
const { MergeEngine: MergeEngine2 } = await Promise.resolve().then(() => (init_merge(), exports_merge));
|
|
30848
|
+
const { runPipeline: runPipeline2 } = await Promise.resolve().then(() => (init_runner(), exports_runner));
|
|
30849
|
+
const { defaultPipeline: defaultPipeline2 } = await Promise.resolve().then(() => (init_stages(), exports_stages));
|
|
30850
|
+
const { routeTask: routeTask2 } = await Promise.resolve().then(() => (init_routing(), exports_routing));
|
|
30851
|
+
const worktreeManager = new WorktreeManager2;
|
|
30852
|
+
const mergeEngine = new MergeEngine2(worktreeManager);
|
|
30853
|
+
try {
|
|
30854
|
+
await worktreeManager.remove(workdir, storyId);
|
|
30855
|
+
} catch {}
|
|
30856
|
+
await worktreeManager.create(workdir, storyId);
|
|
30857
|
+
const worktreePath = path15.join(workdir, ".nax-wt", storyId);
|
|
30858
|
+
const story = prd.userStories.find((s) => s.id === storyId);
|
|
30859
|
+
if (!story) {
|
|
30860
|
+
return { success: false, storyId, cost: 0, finalConflict: false, pipelineFailure: true };
|
|
30861
|
+
}
|
|
30862
|
+
const routing = routeTask2(story.title, story.description, story.acceptanceCriteria, story.tags, config2);
|
|
30863
|
+
const pipelineContext = {
|
|
30864
|
+
config: config2,
|
|
30865
|
+
prd,
|
|
30866
|
+
story,
|
|
30867
|
+
stories: [story],
|
|
30868
|
+
workdir: worktreePath,
|
|
30869
|
+
featureDir: undefined,
|
|
30870
|
+
hooks,
|
|
30871
|
+
plugins: pluginRegistry,
|
|
30872
|
+
storyStartTime: new Date().toISOString(),
|
|
30873
|
+
routing
|
|
30874
|
+
};
|
|
30875
|
+
const pipelineResult = await runPipeline2(defaultPipeline2, pipelineContext, eventEmitter);
|
|
30876
|
+
const cost = pipelineResult.context.agentResult?.estimatedCost ?? 0;
|
|
30877
|
+
if (!pipelineResult.success) {
|
|
30878
|
+
logger?.info("parallel", "Rectification failed - preserving worktree", { storyId });
|
|
30879
|
+
return { success: false, storyId, cost, finalConflict: false, pipelineFailure: true };
|
|
30880
|
+
}
|
|
30881
|
+
const mergeResults = await mergeEngine.mergeAll(workdir, [storyId], { [storyId]: [] });
|
|
30882
|
+
const mergeResult = mergeResults[0];
|
|
30883
|
+
if (!mergeResult || !mergeResult.success) {
|
|
30884
|
+
const conflictFiles = mergeResult?.conflictFiles ?? [];
|
|
30885
|
+
logger?.info("parallel", "Rectification failed - preserving worktree", { storyId });
|
|
30886
|
+
return { success: false, storyId, cost, finalConflict: true, conflictFiles };
|
|
30887
|
+
}
|
|
30888
|
+
logger?.info("parallel", "Rectification succeeded - story merged", {
|
|
30889
|
+
storyId,
|
|
30890
|
+
originalCost: options.originalCost,
|
|
30891
|
+
rectificationCost: cost
|
|
30892
|
+
});
|
|
30893
|
+
return { success: true, storyId, cost };
|
|
30894
|
+
} catch (error48) {
|
|
30895
|
+
logger?.error("parallel", "Rectification failed - preserving worktree", {
|
|
30896
|
+
storyId,
|
|
30897
|
+
error: error48 instanceof Error ? error48.message : String(error48)
|
|
30898
|
+
});
|
|
30899
|
+
return { success: false, storyId, cost: 0, finalConflict: false, pipelineFailure: true };
|
|
30900
|
+
}
|
|
30901
|
+
}
|
|
30902
|
+
async function runRectificationPass(conflictedStories, options, prd) {
|
|
30903
|
+
const logger = getSafeLogger();
|
|
30904
|
+
const { workdir, config: config2, hooks, pluginRegistry, eventEmitter } = options;
|
|
30905
|
+
const rectificationMetrics = [];
|
|
30906
|
+
let rectifiedCount = 0;
|
|
30907
|
+
let stillConflictingCount = 0;
|
|
30908
|
+
let additionalCost = 0;
|
|
30909
|
+
logger?.info("parallel", "Starting merge conflict rectification", {
|
|
30910
|
+
stories: conflictedStories.map((s) => s.storyId),
|
|
30911
|
+
totalConflicts: conflictedStories.length
|
|
30912
|
+
});
|
|
30913
|
+
for (const conflictInfo of conflictedStories) {
|
|
30914
|
+
const result = await _parallelExecutorDeps.rectifyConflictedStory({
|
|
30915
|
+
...conflictInfo,
|
|
30916
|
+
workdir,
|
|
30917
|
+
config: config2,
|
|
30918
|
+
hooks,
|
|
30919
|
+
pluginRegistry,
|
|
30920
|
+
prd,
|
|
30921
|
+
eventEmitter
|
|
30922
|
+
});
|
|
30923
|
+
additionalCost += result.cost;
|
|
30924
|
+
if (result.success) {
|
|
30925
|
+
markStoryPassed(prd, result.storyId);
|
|
30926
|
+
rectifiedCount++;
|
|
30927
|
+
rectificationMetrics.push({
|
|
30928
|
+
storyId: result.storyId,
|
|
30929
|
+
complexity: "unknown",
|
|
30930
|
+
modelTier: "parallel",
|
|
30931
|
+
modelUsed: "parallel",
|
|
30932
|
+
attempts: 1,
|
|
30933
|
+
finalTier: "parallel",
|
|
30934
|
+
success: true,
|
|
30935
|
+
cost: result.cost,
|
|
30936
|
+
durationMs: 0,
|
|
30937
|
+
firstPassSuccess: false,
|
|
30938
|
+
startedAt: new Date().toISOString(),
|
|
30939
|
+
completedAt: new Date().toISOString(),
|
|
30940
|
+
source: "rectification",
|
|
30941
|
+
rectifiedFromConflict: true,
|
|
30942
|
+
originalCost: conflictInfo.originalCost,
|
|
30943
|
+
rectificationCost: result.cost
|
|
30944
|
+
});
|
|
30945
|
+
} else {
|
|
30946
|
+
const isFinalConflict = result.finalConflict === true;
|
|
30947
|
+
if (isFinalConflict) {
|
|
30948
|
+
stillConflictingCount++;
|
|
30949
|
+
}
|
|
30950
|
+
}
|
|
30951
|
+
}
|
|
30952
|
+
logger?.info("parallel", "Rectification complete", {
|
|
30953
|
+
rectified: rectifiedCount,
|
|
30954
|
+
stillConflicting: stillConflictingCount
|
|
30955
|
+
});
|
|
30956
|
+
return { rectifiedCount, stillConflictingCount, additionalCost, updatedPrd: prd, rectificationMetrics };
|
|
30957
|
+
}
|
|
30745
30958
|
async function runParallelExecution(options, initialPrd) {
|
|
30746
30959
|
const logger = getSafeLogger();
|
|
30747
30960
|
const {
|
|
@@ -30766,7 +30979,14 @@ async function runParallelExecution(options, initialPrd) {
|
|
|
30766
30979
|
const readyStories = getAllReadyStories(prd);
|
|
30767
30980
|
if (readyStories.length === 0) {
|
|
30768
30981
|
logger?.info("parallel", "No stories ready for parallel execution");
|
|
30769
|
-
return {
|
|
30982
|
+
return {
|
|
30983
|
+
prd,
|
|
30984
|
+
totalCost,
|
|
30985
|
+
storiesCompleted,
|
|
30986
|
+
completed: false,
|
|
30987
|
+
storyMetrics: [],
|
|
30988
|
+
rectificationStats: { rectified: 0, stillConflicting: 0 }
|
|
30989
|
+
};
|
|
30770
30990
|
}
|
|
30771
30991
|
const maxConcurrency = parallelCount === 0 ? os5.cpus().length : Math.max(1, parallelCount);
|
|
30772
30992
|
logger?.info("parallel", "Starting parallel execution mode", {
|
|
@@ -30784,15 +31004,45 @@ async function runParallelExecution(options, initialPrd) {
|
|
|
30784
31004
|
}))
|
|
30785
31005
|
}
|
|
30786
31006
|
});
|
|
31007
|
+
const initialPassedIds = new Set(initialPrd.userStories.filter((s) => s.status === "passed").map((s) => s.id));
|
|
31008
|
+
const batchStartedAt = new Date().toISOString();
|
|
31009
|
+
const batchStartMs = Date.now();
|
|
31010
|
+
const batchStoryMetrics = [];
|
|
31011
|
+
let conflictedStories = [];
|
|
30787
31012
|
try {
|
|
30788
|
-
const parallelResult = await executeParallel(readyStories, prdPath, workdir, config2, hooks, pluginRegistry, prd, featureDir, parallelCount, eventEmitter);
|
|
31013
|
+
const parallelResult = await _parallelExecutorDeps.executeParallel(readyStories, prdPath, workdir, config2, hooks, pluginRegistry, prd, featureDir, parallelCount, eventEmitter);
|
|
31014
|
+
const batchDurationMs = Date.now() - batchStartMs;
|
|
31015
|
+
const batchCompletedAt = new Date().toISOString();
|
|
30789
31016
|
prd = parallelResult.updatedPrd;
|
|
30790
31017
|
storiesCompleted += parallelResult.storiesCompleted;
|
|
30791
31018
|
totalCost += parallelResult.totalCost;
|
|
30792
|
-
|
|
30793
|
-
|
|
30794
|
-
|
|
30795
|
-
|
|
31019
|
+
conflictedStories = parallelResult.mergeConflicts ?? [];
|
|
31020
|
+
const newlyPassedStories = prd.userStories.filter((s) => s.status === "passed" && !initialPassedIds.has(s.id));
|
|
31021
|
+
const costPerStory = newlyPassedStories.length > 0 ? parallelResult.totalCost / newlyPassedStories.length : 0;
|
|
31022
|
+
for (const story of newlyPassedStories) {
|
|
31023
|
+
batchStoryMetrics.push({
|
|
31024
|
+
storyId: story.id,
|
|
31025
|
+
complexity: "unknown",
|
|
31026
|
+
modelTier: "parallel",
|
|
31027
|
+
modelUsed: "parallel",
|
|
31028
|
+
attempts: 1,
|
|
31029
|
+
finalTier: "parallel",
|
|
31030
|
+
success: true,
|
|
31031
|
+
cost: costPerStory,
|
|
31032
|
+
durationMs: batchDurationMs,
|
|
31033
|
+
firstPassSuccess: true,
|
|
31034
|
+
startedAt: batchStartedAt,
|
|
31035
|
+
completedAt: batchCompletedAt,
|
|
31036
|
+
source: "parallel"
|
|
31037
|
+
});
|
|
31038
|
+
}
|
|
31039
|
+
allStoryMetrics.push(...batchStoryMetrics);
|
|
31040
|
+
for (const conflict of conflictedStories) {
|
|
31041
|
+
logger?.info("parallel", "Merge conflict detected - scheduling for rectification", {
|
|
31042
|
+
storyId: conflict.storyId,
|
|
31043
|
+
conflictFiles: conflict.conflictFiles
|
|
31044
|
+
});
|
|
31045
|
+
}
|
|
30796
31046
|
statusWriter.setPrd(prd);
|
|
30797
31047
|
await statusWriter.update(totalCost, iterations, {
|
|
30798
31048
|
parallel: {
|
|
@@ -30810,6 +31060,19 @@ async function runParallelExecution(options, initialPrd) {
|
|
|
30810
31060
|
});
|
|
30811
31061
|
throw error48;
|
|
30812
31062
|
}
|
|
31063
|
+
let rectificationStats = { rectified: 0, stillConflicting: 0 };
|
|
31064
|
+
if (conflictedStories.length > 0) {
|
|
31065
|
+
const rectResult = await runRectificationPass(conflictedStories, options, prd);
|
|
31066
|
+
prd = rectResult.updatedPrd;
|
|
31067
|
+
storiesCompleted += rectResult.rectifiedCount;
|
|
31068
|
+
totalCost += rectResult.additionalCost;
|
|
31069
|
+
rectificationStats = {
|
|
31070
|
+
rectified: rectResult.rectifiedCount,
|
|
31071
|
+
stillConflicting: rectResult.stillConflictingCount
|
|
31072
|
+
};
|
|
31073
|
+
batchStoryMetrics.push(...rectResult.rectificationMetrics);
|
|
31074
|
+
allStoryMetrics.push(...rectResult.rectificationMetrics);
|
|
31075
|
+
}
|
|
30813
31076
|
if (isComplete(prd)) {
|
|
30814
31077
|
logger?.info("execution", "All stories complete!", {
|
|
30815
31078
|
feature,
|
|
@@ -30859,10 +31122,12 @@ async function runParallelExecution(options, initialPrd) {
|
|
|
30859
31122
|
totalCost,
|
|
30860
31123
|
storiesCompleted,
|
|
30861
31124
|
completed: true,
|
|
30862
|
-
durationMs
|
|
31125
|
+
durationMs,
|
|
31126
|
+
storyMetrics: batchStoryMetrics,
|
|
31127
|
+
rectificationStats
|
|
30863
31128
|
};
|
|
30864
31129
|
}
|
|
30865
|
-
return { prd, totalCost, storiesCompleted, completed: false };
|
|
31130
|
+
return { prd, totalCost, storiesCompleted, completed: false, storyMetrics: batchStoryMetrics, rectificationStats };
|
|
30866
31131
|
}
|
|
30867
31132
|
var _parallelExecutorDeps;
|
|
30868
31133
|
var init_parallel_executor = __esm(() => {
|
|
@@ -30872,7 +31137,9 @@ var init_parallel_executor = __esm(() => {
|
|
|
30872
31137
|
init_helpers();
|
|
30873
31138
|
init_parallel();
|
|
30874
31139
|
_parallelExecutorDeps = {
|
|
30875
|
-
fireHook
|
|
31140
|
+
fireHook,
|
|
31141
|
+
executeParallel,
|
|
31142
|
+
rectifyConflictedStory
|
|
30876
31143
|
};
|
|
30877
31144
|
});
|
|
30878
31145
|
|
|
@@ -31114,7 +31381,7 @@ function wireReporters(bus, pluginRegistry, runId, startTime) {
|
|
|
31114
31381
|
runId,
|
|
31115
31382
|
storyId: ev.storyId,
|
|
31116
31383
|
status: "completed",
|
|
31117
|
-
|
|
31384
|
+
runElapsedMs: ev.runElapsedMs,
|
|
31118
31385
|
cost: ev.cost ?? 0,
|
|
31119
31386
|
tier: ev.modelTier ?? "balanced",
|
|
31120
31387
|
testStrategy: ev.testStrategy ?? "test-after"
|
|
@@ -31136,7 +31403,7 @@ function wireReporters(bus, pluginRegistry, runId, startTime) {
|
|
|
31136
31403
|
runId,
|
|
31137
31404
|
storyId: ev.storyId,
|
|
31138
31405
|
status: "failed",
|
|
31139
|
-
|
|
31406
|
+
runElapsedMs: Date.now() - startTime,
|
|
31140
31407
|
cost: 0,
|
|
31141
31408
|
tier: "balanced",
|
|
31142
31409
|
testStrategy: "test-after"
|
|
@@ -31158,7 +31425,7 @@ function wireReporters(bus, pluginRegistry, runId, startTime) {
|
|
|
31158
31425
|
runId,
|
|
31159
31426
|
storyId: ev.storyId,
|
|
31160
31427
|
status: "paused",
|
|
31161
|
-
|
|
31428
|
+
runElapsedMs: Date.now() - startTime,
|
|
31162
31429
|
cost: 0,
|
|
31163
31430
|
tier: "balanced",
|
|
31164
31431
|
testStrategy: "test-after"
|
|
@@ -31236,7 +31503,7 @@ async function handleDryRun(ctx) {
|
|
|
31236
31503
|
storyId: s.id,
|
|
31237
31504
|
story: s,
|
|
31238
31505
|
passed: true,
|
|
31239
|
-
|
|
31506
|
+
runElapsedMs: 0,
|
|
31240
31507
|
cost: 0,
|
|
31241
31508
|
modelTier: ctx.routing.modelTier,
|
|
31242
31509
|
testStrategy: ctx.routing.testStrategy
|
|
@@ -31268,7 +31535,7 @@ async function handlePipelineSuccess(ctx, pipelineResult) {
|
|
|
31268
31535
|
storyId: completedStory.id,
|
|
31269
31536
|
storyTitle: completedStory.title,
|
|
31270
31537
|
totalCost: ctx.totalCost + costDelta,
|
|
31271
|
-
|
|
31538
|
+
runElapsedMs: now - ctx.startTime,
|
|
31272
31539
|
storyDurationMs: ctx.storyStartTime ? now - ctx.storyStartTime : undefined
|
|
31273
31540
|
});
|
|
31274
31541
|
pipelineEventBus.emit({
|
|
@@ -31276,7 +31543,7 @@ async function handlePipelineSuccess(ctx, pipelineResult) {
|
|
|
31276
31543
|
storyId: completedStory.id,
|
|
31277
31544
|
story: completedStory,
|
|
31278
31545
|
passed: true,
|
|
31279
|
-
|
|
31546
|
+
runElapsedMs: Date.now() - ctx.startTime,
|
|
31280
31547
|
cost: costDelta,
|
|
31281
31548
|
modelTier: ctx.routing.modelTier,
|
|
31282
31549
|
testStrategy: ctx.routing.testStrategy
|
|
@@ -31357,7 +31624,8 @@ async function handlePipelineFailure(ctx, pipelineResult) {
|
|
|
31357
31624
|
hooks: ctx.hooks,
|
|
31358
31625
|
feature: ctx.feature,
|
|
31359
31626
|
totalCost: ctx.totalCost,
|
|
31360
|
-
workdir: ctx.workdir
|
|
31627
|
+
workdir: ctx.workdir,
|
|
31628
|
+
attemptCost: pipelineResult.context.agentResult?.estimatedCost || 0
|
|
31361
31629
|
});
|
|
31362
31630
|
prd = escalationResult.prd;
|
|
31363
31631
|
prdDirty = escalationResult.prdDirty;
|
|
@@ -31399,6 +31667,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
|
|
|
31399
31667
|
}
|
|
31400
31668
|
const storyStartTime = Date.now();
|
|
31401
31669
|
const storyGitRef = await captureGitRef(ctx.workdir);
|
|
31670
|
+
const accumulatedAttemptCost = (story.priorFailures || []).reduce((sum, f) => sum + (f.cost || 0), 0);
|
|
31402
31671
|
const pipelineContext = {
|
|
31403
31672
|
config: ctx.config,
|
|
31404
31673
|
prd,
|
|
@@ -31412,7 +31681,8 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
|
|
|
31412
31681
|
plugins: ctx.pluginRegistry,
|
|
31413
31682
|
storyStartTime: new Date().toISOString(),
|
|
31414
31683
|
storyGitRef: storyGitRef ?? undefined,
|
|
31415
|
-
interaction: ctx.interactionChain ?? undefined
|
|
31684
|
+
interaction: ctx.interactionChain ?? undefined,
|
|
31685
|
+
accumulatedAttemptCost: accumulatedAttemptCost > 0 ? accumulatedAttemptCost : undefined
|
|
31416
31686
|
};
|
|
31417
31687
|
ctx.statusWriter.setPrd(prd);
|
|
31418
31688
|
ctx.statusWriter.setCurrentStory({
|
|
@@ -66499,7 +66769,8 @@ init_story_context();
|
|
|
66499
66769
|
init_escalation();
|
|
66500
66770
|
init_escalation();
|
|
66501
66771
|
var _runnerDeps = {
|
|
66502
|
-
fireHook
|
|
66772
|
+
fireHook,
|
|
66773
|
+
runParallelExecution: null
|
|
66503
66774
|
};
|
|
66504
66775
|
async function run(options) {
|
|
66505
66776
|
const {
|
|
@@ -66601,7 +66872,7 @@ async function run(options) {
|
|
|
66601
66872
|
await tryLlmBatchRoute(config2, getAllReadyStories(prd), "routing");
|
|
66602
66873
|
}
|
|
66603
66874
|
if (options.parallel !== undefined) {
|
|
66604
|
-
const
|
|
66875
|
+
const runParallelExecution2 = _runnerDeps.runParallelExecution ?? (await Promise.resolve().then(() => (init_parallel_executor(), exports_parallel_executor))).runParallelExecution;
|
|
66605
66876
|
const parallelResult = await runParallelExecution2({
|
|
66606
66877
|
prdPath,
|
|
66607
66878
|
workdir,
|
|
@@ -66626,6 +66897,7 @@ async function run(options) {
|
|
|
66626
66897
|
prd = parallelResult.prd;
|
|
66627
66898
|
totalCost = parallelResult.totalCost;
|
|
66628
66899
|
storiesCompleted = parallelResult.storiesCompleted;
|
|
66900
|
+
allStoryMetrics.push(...parallelResult.storyMetrics);
|
|
66629
66901
|
if (parallelResult.completed && parallelResult.durationMs !== undefined) {
|
|
66630
66902
|
return {
|
|
66631
66903
|
success: true,
|
|
@@ -66656,8 +66928,8 @@ async function run(options) {
|
|
|
66656
66928
|
}, prd);
|
|
66657
66929
|
prd = sequentialResult.prd;
|
|
66658
66930
|
iterations = sequentialResult.iterations;
|
|
66659
|
-
|
|
66660
|
-
|
|
66931
|
+
totalCost += sequentialResult.totalCost;
|
|
66932
|
+
storiesCompleted += sequentialResult.storiesCompleted;
|
|
66661
66933
|
allStoryMetrics.push(...sequentialResult.allStoryMetrics);
|
|
66662
66934
|
if (config2.acceptance.enabled && isComplete(prd)) {
|
|
66663
66935
|
const { runAcceptanceLoop: runAcceptanceLoop2 } = await Promise.resolve().then(() => (init_acceptance_loop(), exports_acceptance_loop));
|