@nathapp/nax 0.21.0 → 0.22.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/.mcp.json +8 -0
- package/docs/ROADMAP.md +20 -5
- package/docs/adr/ADR-005-implementation-plan.md +655 -0
- package/docs/adr/ADR-005-pipeline-re-architecture.md +464 -0
- package/package.json +1 -1
- package/src/agents/claude.ts +44 -9
- package/src/config/types.ts +11 -0
- package/src/execution/dry-run.ts +81 -0
- package/src/execution/escalation/tier-outcome.ts +29 -44
- package/src/execution/executor-types.ts +65 -0
- package/src/execution/index.ts +0 -17
- package/src/execution/iteration-runner.ts +132 -0
- package/src/execution/lifecycle/index.ts +0 -1
- package/src/execution/lifecycle/run-regression.ts +5 -5
- package/src/execution/pipeline-result-handler.ts +51 -254
- package/src/execution/sequential-executor.ts +72 -316
- package/src/execution/story-selector.ts +75 -0
- package/src/pipeline/event-bus.ts +276 -0
- package/src/pipeline/runner.ts +51 -77
- package/src/pipeline/stages/autofix.ts +133 -0
- package/src/pipeline/stages/completion.ts +22 -30
- package/src/pipeline/stages/index.ts +30 -13
- package/src/pipeline/stages/rectify.ts +93 -0
- package/src/pipeline/stages/regression.ts +88 -0
- package/src/pipeline/stages/review.ts +19 -153
- package/src/pipeline/stages/verify.ts +18 -2
- package/src/pipeline/subscribers/hooks.ts +133 -0
- package/src/pipeline/subscribers/interaction.ts +68 -0
- package/src/pipeline/subscribers/reporters.ts +174 -0
- package/src/pipeline/types.ts +10 -1
- package/src/review/orchestrator.ts +105 -0
- package/src/tdd/prompts.ts +1 -1
- package/src/verification/index.ts +1 -1
- package/src/verification/orchestrator-types.ts +145 -0
- package/src/verification/orchestrator.ts +76 -0
- package/src/{execution/post-verify-rectification.ts → verification/rectification-loop.ts} +13 -20
- package/src/verification/{gate.ts → runners.ts} +17 -105
- package/src/verification/strategies/acceptance.ts +133 -0
- package/src/verification/strategies/regression.ts +90 -0
- package/src/verification/strategies/scoped.ts +123 -0
- package/test/COVERAGE-GAPS.md +333 -0
- package/test/{acceptance → e2e}/cm-003-default-view.test.ts +1 -0
- package/test/{integration/e2e.test.ts → e2e/plan-analyze-run.test.ts} +1 -0
- package/test/integration/{agent-validation.test.ts → cli/agent-validation.test.ts} +3 -3
- package/test/integration/{cli-config-default-edge-cases.test.ts → cli/cli-config-default-edge-cases.test.ts} +6 -5
- package/test/integration/{cli-config-default-view.test.ts → cli/cli-config-default-view.test.ts} +8 -7
- package/test/integration/{cli-config-diff.test.ts → cli/cli-config-diff.test.ts} +3 -2
- package/test/integration/{cli-config.test.ts → cli/cli-config.test.ts} +3 -2
- package/test/integration/{cli-diagnose.test.ts → cli/cli-diagnose.test.ts} +5 -4
- package/test/integration/{cli-logs.test.ts → cli/cli-logs.test.ts} +12 -3
- package/test/integration/{cli-plugins.test.ts → cli/cli-plugins.test.ts} +4 -3
- package/test/integration/{cli-precheck.test.ts → cli/cli-precheck.test.ts} +4 -3
- package/test/integration/{cli-run-headless.test.ts → cli/cli-run-headless.test.ts} +3 -2
- package/test/integration/{cli.test.ts → cli/cli.test.ts} +2 -1
- package/test/integration/{precheck-integration.test.ts → cli/precheck-integration.test.ts} +10 -9
- package/test/integration/{precheck-orchestrator.test.ts → cli/precheck-orchestrator.test.ts} +4 -3
- package/test/integration/{precheck.test.ts → cli/precheck.test.ts} +5 -4
- package/test/integration/{config-loader.test.ts → config/config-loader.test.ts} +2 -1
- package/test/integration/{config.test.ts → config/config.test.ts} +2 -2
- package/test/integration/config/merger.test.ts +1 -0
- package/test/integration/config/paths.test.ts +1 -0
- package/test/integration/{security-loader.test.ts → config/security-loader.test.ts} +2 -2
- package/test/integration/{context-integration.test.ts → context/context-integration.test.ts} +7 -6
- package/test/integration/{path-security.test.ts → context/context-path-security.test.ts} +2 -2
- package/test/integration/{context-provider-injection.test.ts → context/context-provider-injection.test.ts} +7 -6
- package/test/integration/{context-verification-integration.test.ts → context/context-verification-integration.test.ts} +5 -4
- package/test/integration/{s5-greenfield-fallback.test.ts → context/s5-greenfield-fallback.test.ts} +4 -3
- package/test/integration/{isolation.test.ts → execution/execution-isolation.test.ts} +1 -1
- package/test/integration/{execution.test.ts → execution/execution.test.ts} +8 -8
- package/test/integration/{parallel.test.ts → execution/parallel.test.ts} +2 -1
- package/test/integration/{prd-pause.test.ts → execution/prd-pause.test.ts} +2 -2
- package/test/integration/{prd-resolvers.test.ts → execution/prd-resolvers.test.ts} +3 -2
- package/test/integration/{progress.test.ts → execution/progress.test.ts} +1 -1
- package/test/integration/execution/runner-batching.test.ts +682 -0
- package/test/integration/{runner-config-plugins.test.ts → execution/runner-config-plugins.test.ts} +3 -2
- package/test/integration/execution/runner-escalation.test.ts +561 -0
- package/test/integration/{runner-fixes.test.ts → execution/runner-fixes.test.ts} +4 -3
- package/test/integration/{runner-plugin-integration.test.ts → execution/runner-plugin-integration.test.ts} +6 -5
- package/test/integration/execution/runner-queue-and-attempts.test.ts +476 -0
- package/test/integration/{status-file-integration.test.ts → execution/status-file-integration.test.ts} +9 -8
- package/test/integration/{status-file.test.ts → execution/status-file.test.ts} +3 -2
- package/test/integration/{status-writer.test.ts → execution/status-writer.test.ts} +5 -4
- package/test/integration/{story-id-in-events.test.ts → execution/story-id-in-events.test.ts} +9 -8
- package/test/integration/{interaction-chain-pipeline.test.ts → interaction/interaction-chain-pipeline.test.ts} +26 -14
- package/test/integration/{hooks.test.ts → pipeline/hooks.test.ts} +4 -2
- package/test/integration/{pipeline-acceptance.test.ts → pipeline/pipeline-acceptance.test.ts} +7 -6
- package/test/integration/{pipeline-events.test.ts → pipeline/pipeline-events.test.ts} +7 -6
- package/test/integration/{pipeline.test.ts → pipeline/pipeline.test.ts} +9 -7
- package/test/integration/{reporter-lifecycle.test.ts → pipeline/reporter-lifecycle.test.ts} +9 -7
- package/test/integration/{verify-stage.test.ts → pipeline/verify-stage.test.ts} +7 -5
- package/test/integration/{analyze-integration.test.ts → plan/analyze-integration.test.ts} +3 -2
- package/test/integration/{analyze-scanner.test.ts → plan/analyze-scanner.test.ts} +8 -7
- package/test/integration/{logger.test.ts → plan/logger.test.ts} +1 -1
- package/test/integration/{plan.test.ts → plan/plan.test.ts} +3 -3
- package/test/integration/plugins/config-integration.test.ts +1 -0
- package/test/integration/plugins/config-resolution.test.ts +1 -0
- package/test/integration/plugins/loader.test.ts +1 -0
- package/test/integration/plugins/{registry.test.ts → plugins-registry.test.ts} +1 -0
- package/test/integration/plugins/validator.test.ts +1 -0
- package/test/integration/{review-config-commands.test.ts → review/review-config-commands.test.ts} +4 -3
- package/test/integration/{review-config-schema.test.ts → review/review-config-schema.test.ts} +3 -2
- package/test/integration/{review-plugin-integration.test.ts → review/review-plugin-integration.test.ts} +5 -4
- package/test/integration/{review.test.ts → review/review.test.ts} +3 -2
- package/test/integration/routing/plugin-routing-advanced.test.ts +461 -0
- package/test/integration/{plugin-routing.test.ts → routing/plugin-routing-core.test.ts} +9 -403
- package/test/integration/{routing-stage-bug-021.test.ts → routing/routing-stage-bug-021.test.ts} +8 -7
- package/test/integration/{routing-stage-greenfield.test.ts → routing/routing-stage-greenfield.test.ts} +7 -6
- package/test/integration/{tdd-cleanup.test.ts → tdd/tdd-cleanup.test.ts} +1 -1
- package/test/integration/tdd/tdd-orchestrator-core.test.ts +565 -0
- package/test/integration/tdd/tdd-orchestrator-failureCategory.test.ts +355 -0
- package/test/integration/tdd/tdd-orchestrator-fallback.test.ts +311 -0
- package/test/integration/tdd/tdd-orchestrator-lite.test.ts +289 -0
- package/test/integration/tdd/tdd-orchestrator-prompts.test.ts +260 -0
- package/test/integration/tdd/tdd-orchestrator-verdict.test.ts +536 -0
- package/test/integration/tmp/headless-test/test.jsonl +30 -0
- package/test/integration/{test-scanner.test.ts → verification/test-scanner.test.ts} +1 -1
- package/test/integration/{verification-asset-check.test.ts → verification/verification-asset-check.test.ts} +3 -2
- package/test/unit/acceptance.test.ts +1 -0
- package/test/unit/agent-stderr-capture.test.ts +1 -0
- package/test/unit/agents/claude.test.ts +1 -0
- package/test/unit/analyze-classifier.test.ts +1 -0
- package/test/unit/auto-detect.test.ts +1 -0
- package/test/unit/cli-status.test.ts +1 -0
- package/test/unit/commands/common.test.ts +1 -0
- package/test/unit/commands/logs.test.ts +1 -0
- package/test/unit/commands/unlock.test.ts +1 -0
- package/test/unit/config/defaults.test.ts +1 -0
- package/test/unit/config/regression-gate-schema.test.ts +1 -0
- package/test/unit/config/smart-runner-flag.test.ts +1 -0
- package/test/unit/constitution-generators.test.ts +1 -0
- package/test/unit/constitution.test.ts +1 -0
- package/test/unit/context/context-autodetect.test.ts +297 -0
- package/test/unit/context/context-build.test.ts +575 -0
- package/test/unit/context/context-coverage.test.ts +236 -0
- package/test/unit/context/context-error.test.ts +93 -0
- package/test/unit/context/context-estimate-tokens.test.ts +201 -0
- package/test/unit/context/context-format.test.ts +302 -0
- package/test/unit/context/context-isolation.test.ts +267 -0
- package/test/unit/context/context-sort.test.ts +93 -0
- package/test/unit/context/context-story.test.ts +108 -0
- package/test/{context → unit/context}/prior-failures.test.ts +5 -4
- package/test/unit/context.test.ts +1 -0
- package/test/unit/crash-recovery.test.ts +1 -0
- package/test/unit/escalation.test.ts +1 -0
- package/test/unit/execution/lifecycle/run-completion.test.ts +1 -0
- package/test/unit/execution/lifecycle/run-regression.test.ts +2 -0
- package/test/{execution → unit/execution}/pid-registry.test.ts +2 -1
- package/test/{execution → unit/execution}/structured-failure.test.ts +3 -2
- package/test/unit/execution-logging-stderr.test.ts +1 -0
- package/test/unit/execution-stage.test.ts +1 -0
- package/test/unit/fix-generator.test.ts +1 -0
- package/test/unit/greenfield.test.ts +1 -0
- package/test/unit/interaction/human-review-trigger.test.ts +1 -0
- package/test/unit/interaction-network-failures.test.ts +1 -0
- package/test/unit/interaction-plugins.test.ts +1 -0
- package/test/unit/logging/formatter.test.ts +1 -0
- package/test/unit/merge.test.ts +1 -0
- package/test/unit/pipeline/event-bus.test.ts +105 -0
- package/test/unit/pipeline/routing-partial-override.test.ts +1 -0
- package/test/unit/pipeline/runner-retry.test.ts +89 -0
- package/test/unit/pipeline/stages/autofix.test.ts +97 -0
- package/test/unit/pipeline/stages/rectify.test.ts +101 -0
- package/test/unit/pipeline/stages/regression-stage.test.ts +69 -0
- package/test/unit/pipeline/stages/verify.test.ts +1 -0
- package/test/unit/pipeline/subscribers/hooks.test.ts +45 -0
- package/test/unit/pipeline/subscribers/interaction.test.ts +31 -0
- package/test/unit/pipeline/subscribers/reporters.test.ts +90 -0
- package/test/unit/pipeline/verify-smart-runner.test.ts +1 -0
- package/test/unit/prd-auto-default.test.ts +1 -0
- package/test/unit/prd-failure-category.test.ts +1 -0
- package/test/unit/prd-get-next-story.test.ts +1 -0
- package/test/unit/precheck-checks.test.ts +1 -0
- package/test/unit/precheck-story-size-gate.test.ts +1 -0
- package/test/unit/precheck-types.test.ts +1 -0
- package/test/unit/prompts.test.ts +1 -0
- package/test/unit/rectification.test.ts +2 -1
- package/test/unit/registry.test.ts +1 -0
- package/test/unit/routing/routing-stability.test.ts +1 -0
- package/test/unit/routing/strategies/llm.test.ts +1 -0
- package/test/unit/routing-advanced.test.ts +313 -0
- package/test/unit/routing-core.test.ts +341 -0
- package/test/unit/routing-strategies.test.ts +442 -0
- package/test/unit/storyid-events.test.ts +1 -0
- package/test/{ui → unit/ui}/tui-controls.test.ts +8 -7
- package/test/{ui → unit/ui}/tui-cost-and-pty.test.ts +4 -3
- package/test/{ui → unit/ui}/tui-layout.test.ts +5 -4
- package/test/{ui → unit/ui}/tui-stories.test.ts +5 -4
- package/test/unit/{isolation.test.ts → unit-isolation.test.ts} +1 -0
- package/test/unit/{helpers.test.ts → utils-helpers.test.ts} +1 -0
- package/test/unit/verdict.test.ts +1 -0
- package/test/unit/verification/orchestrator-types.test.ts +54 -0
- package/test/unit/verification/orchestrator.test.ts +66 -0
- package/test/unit/verification/smart-runner-config.test.ts +1 -0
- package/test/unit/verification/smart-runner-discovery.test.ts +8 -7
- package/test/unit/verification/strategies/acceptance.test.ts +33 -0
- package/test/unit/verification/strategies/regression.test.ts +87 -0
- package/test/unit/verification/strategies/scoped.test.ts +100 -0
- package/test/unit/worktree-manager.test.ts +1 -0
- package/src/execution/lifecycle/story-hooks.ts +0 -38
- package/src/execution/post-verify.ts +0 -193
- package/src/execution/rectification.ts +0 -13
- package/src/execution/verification.ts +0 -72
- package/test/integration/rectification-flow.test.ts +0 -512
- package/test/integration/runner.test.ts +0 -1679
- package/test/integration/tdd-orchestrator.test.ts +0 -1762
- package/test/unit/execution/post-verify-regression.test.ts +0 -362
- package/test/unit/execution/post-verify.test.ts +0 -236
- package/test/unit/routing.test.ts +0 -1039
- /package/test/{integration → helpers}/helpers.test.ts +0 -0
- /package/test/integration/worktree/{merge.test.ts → worktree-merge.test.ts} +0 -0
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Extracted from tier-escalation.ts: handles outcomes when escalation
|
|
5
5
|
* is not possible (no tier available or max attempts reached).
|
|
6
|
+
*
|
|
7
|
+
* Phase 3 (ADR-005): Replaced direct fireHook() calls with event bus emissions.
|
|
6
8
|
*/
|
|
7
9
|
|
|
8
|
-
import { fireHook } from "../../hooks";
|
|
9
10
|
import { getSafeLogger } from "../../logger";
|
|
11
|
+
import { pipelineEventBus } from "../../pipeline/event-bus";
|
|
10
12
|
import { markStoryFailed, markStoryPaused, savePRD } from "../../prd";
|
|
11
13
|
import type { FailureCategory } from "../../tdd/types";
|
|
12
|
-
import { hookCtx } from "../helpers";
|
|
13
14
|
import { appendProgress } from "../progress";
|
|
14
15
|
import type { EscalationHandlerContext, EscalationHandlerResult } from "./tier-escalation";
|
|
15
16
|
import { resolveMaxAttemptsOutcome } from "./tier-escalation";
|
|
@@ -43,16 +44,12 @@ export async function handleNoTierAvailable(
|
|
|
43
44
|
);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
cost: ctx.totalCost,
|
|
53
|
-
}),
|
|
54
|
-
ctx.workdir,
|
|
55
|
-
);
|
|
47
|
+
pipelineEventBus.emit({
|
|
48
|
+
type: "story:paused",
|
|
49
|
+
storyId: ctx.story.id,
|
|
50
|
+
reason: `Execution stopped (${failureCategory ?? "unknown"} requires human review)`,
|
|
51
|
+
cost: ctx.totalCost,
|
|
52
|
+
});
|
|
56
53
|
|
|
57
54
|
return { outcome: "paused", prdDirty: true, prd: pausedPrd };
|
|
58
55
|
}
|
|
@@ -70,17 +67,13 @@ export async function handleNoTierAvailable(
|
|
|
70
67
|
await appendProgress(ctx.featureDir, ctx.story.id, "failed", `${ctx.story.title} — Execution failed`);
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
cost: ctx.totalCost,
|
|
81
|
-
}),
|
|
82
|
-
ctx.workdir,
|
|
83
|
-
);
|
|
70
|
+
pipelineEventBus.emit({
|
|
71
|
+
type: "story:failed",
|
|
72
|
+
storyId: ctx.story.id,
|
|
73
|
+
story: ctx.story,
|
|
74
|
+
reason: "Execution failed",
|
|
75
|
+
countsTowardEscalation: true,
|
|
76
|
+
});
|
|
84
77
|
|
|
85
78
|
return { outcome: "failed", prdDirty: true, prd: failedPrd };
|
|
86
79
|
}
|
|
@@ -114,16 +107,12 @@ export async function handleMaxAttemptsReached(
|
|
|
114
107
|
);
|
|
115
108
|
}
|
|
116
109
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
cost: ctx.totalCost,
|
|
124
|
-
}),
|
|
125
|
-
ctx.workdir,
|
|
126
|
-
);
|
|
110
|
+
pipelineEventBus.emit({
|
|
111
|
+
type: "story:paused",
|
|
112
|
+
storyId: ctx.story.id,
|
|
113
|
+
reason: `Max attempts reached (${failureCategory ?? "unknown"} requires human review)`,
|
|
114
|
+
cost: ctx.totalCost,
|
|
115
|
+
});
|
|
127
116
|
|
|
128
117
|
return { outcome: "paused", prdDirty: true, prd: pausedPrd };
|
|
129
118
|
}
|
|
@@ -142,17 +131,13 @@ export async function handleMaxAttemptsReached(
|
|
|
142
131
|
await appendProgress(ctx.featureDir, ctx.story.id, "failed", `${ctx.story.title} — Max attempts reached`);
|
|
143
132
|
}
|
|
144
133
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
cost: ctx.totalCost,
|
|
153
|
-
}),
|
|
154
|
-
ctx.workdir,
|
|
155
|
-
);
|
|
134
|
+
pipelineEventBus.emit({
|
|
135
|
+
type: "story:failed",
|
|
136
|
+
storyId: ctx.story.id,
|
|
137
|
+
story: ctx.story,
|
|
138
|
+
reason: "Max attempts reached",
|
|
139
|
+
countsTowardEscalation: true,
|
|
140
|
+
});
|
|
156
141
|
|
|
157
142
|
return { outcome: "failed", prdDirty: true, prd: failedPrd };
|
|
158
143
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sequential Executor Types (ADR-005, Phase 4)
|
|
3
|
+
*
|
|
4
|
+
* Extracted from sequential-executor.ts to slim it below 200 lines.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { NaxConfig } from "../config";
|
|
8
|
+
import type { LoadedHooksConfig } from "../hooks";
|
|
9
|
+
import type { InteractionChain } from "../interaction/chain";
|
|
10
|
+
import type { StoryMetrics } from "../metrics";
|
|
11
|
+
import type { PipelineEventEmitter } from "../pipeline/events";
|
|
12
|
+
import type { RoutingResult } from "../pipeline/types";
|
|
13
|
+
import type { PluginRegistry } from "../plugins";
|
|
14
|
+
import type { PRD, UserStory } from "../prd/types";
|
|
15
|
+
import type { StoryBatch } from "./batching";
|
|
16
|
+
import type { StatusWriter } from "./status-writer";
|
|
17
|
+
|
|
18
|
+
export interface SequentialExecutionContext {
|
|
19
|
+
prdPath: string;
|
|
20
|
+
workdir: string;
|
|
21
|
+
config: NaxConfig;
|
|
22
|
+
hooks: LoadedHooksConfig;
|
|
23
|
+
feature: string;
|
|
24
|
+
featureDir?: string;
|
|
25
|
+
dryRun: boolean;
|
|
26
|
+
useBatch: boolean;
|
|
27
|
+
pluginRegistry: PluginRegistry;
|
|
28
|
+
eventEmitter?: PipelineEventEmitter;
|
|
29
|
+
statusWriter: StatusWriter;
|
|
30
|
+
logFilePath?: string;
|
|
31
|
+
runId: string;
|
|
32
|
+
startTime: number;
|
|
33
|
+
batchPlan: StoryBatch[];
|
|
34
|
+
interactionChain?: InteractionChain | null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface SequentialExecutionResult {
|
|
38
|
+
prd: PRD;
|
|
39
|
+
iterations: number;
|
|
40
|
+
storiesCompleted: number;
|
|
41
|
+
totalCost: number;
|
|
42
|
+
allStoryMetrics: StoryMetrics[];
|
|
43
|
+
exitReason: "completed" | "cost-limit" | "max-iterations" | "stalled" | "no-stories";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Build a preview routing from cached story.routing or config defaults.
|
|
48
|
+
* The pipeline routing stage performs full classification and overwrites ctx.routing.
|
|
49
|
+
* This preview is used only for logging, status display, and event emission.
|
|
50
|
+
*/
|
|
51
|
+
export function buildPreviewRouting(story: UserStory, config: NaxConfig): RoutingResult {
|
|
52
|
+
const cached = story.routing;
|
|
53
|
+
const defaultComplexity = "medium" as const;
|
|
54
|
+
const defaultTier = "balanced" as const;
|
|
55
|
+
const defaultStrategy = "test-after" as const;
|
|
56
|
+
return {
|
|
57
|
+
complexity: (cached?.complexity as RoutingResult["complexity"]) ?? defaultComplexity,
|
|
58
|
+
modelTier:
|
|
59
|
+
(cached?.modelTier as RoutingResult["modelTier"]) ??
|
|
60
|
+
(config.autoMode.complexityRouting?.[defaultComplexity] as RoutingResult["modelTier"]) ??
|
|
61
|
+
defaultTier,
|
|
62
|
+
testStrategy: (cached?.testStrategy as RoutingResult["testStrategy"]) ?? defaultStrategy,
|
|
63
|
+
reasoning: cached ? "cached from story.routing" : "preview (pending pipeline routing stage)",
|
|
64
|
+
};
|
|
65
|
+
}
|
package/src/execution/index.ts
CHANGED
|
@@ -5,23 +5,6 @@ export { appendProgress } from "./progress";
|
|
|
5
5
|
export { buildSingleSessionPrompt, buildBatchPrompt } from "./prompts";
|
|
6
6
|
export { groupStoriesIntoBatches, type StoryBatch } from "./batching";
|
|
7
7
|
export { escalateTier, getTierConfig, calculateMaxIterations } from "./escalation";
|
|
8
|
-
export {
|
|
9
|
-
verifyAssets,
|
|
10
|
-
executeWithTimeout,
|
|
11
|
-
parseTestOutput,
|
|
12
|
-
getEnvironmentalEscalationThreshold,
|
|
13
|
-
normalizeEnvironment,
|
|
14
|
-
buildTestCommand,
|
|
15
|
-
appendOpenHandlesFlag,
|
|
16
|
-
appendForceExitFlag,
|
|
17
|
-
runVerification,
|
|
18
|
-
type VerificationResult,
|
|
19
|
-
type VerificationStatus,
|
|
20
|
-
type TestOutputAnalysis,
|
|
21
|
-
type AssetVerificationResult,
|
|
22
|
-
type TimeoutExecutionResult,
|
|
23
|
-
} from "./verification";
|
|
24
|
-
export { runPostAgentVerification, type PostVerifyOptions, type PostVerifyResult } from "./post-verify";
|
|
25
8
|
export { readQueueFile, clearQueueFile } from "./queue-handler";
|
|
26
9
|
export {
|
|
27
10
|
hookCtx,
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Iteration Runner (ADR-005, Phase 4)
|
|
3
|
+
*
|
|
4
|
+
* Runs a single story through the pipeline.
|
|
5
|
+
* Extracted from sequential-executor.ts to slim it below 120 lines.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { getSafeLogger } from "../logger";
|
|
9
|
+
import type { StoryMetrics } from "../metrics";
|
|
10
|
+
import { runPipeline } from "../pipeline/runner";
|
|
11
|
+
import type { PipelineRunResult } from "../pipeline/runner";
|
|
12
|
+
import { defaultPipeline } from "../pipeline/stages";
|
|
13
|
+
import type { PipelineContext } from "../pipeline/types";
|
|
14
|
+
import type { PRD } from "../prd/types";
|
|
15
|
+
import { captureGitRef } from "../utils/git";
|
|
16
|
+
import { handleDryRun } from "./dry-run";
|
|
17
|
+
import type { SequentialExecutionContext } from "./executor-types";
|
|
18
|
+
import { handlePipelineFailure, handlePipelineSuccess } from "./pipeline-result-handler";
|
|
19
|
+
import type { StorySelection } from "./story-selector";
|
|
20
|
+
|
|
21
|
+
export interface IterationResult {
|
|
22
|
+
prd: PRD;
|
|
23
|
+
storiesCompletedDelta: number;
|
|
24
|
+
costDelta: number;
|
|
25
|
+
prdDirty: boolean;
|
|
26
|
+
finalAction?: string;
|
|
27
|
+
reason?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function runIteration(
|
|
31
|
+
ctx: SequentialExecutionContext,
|
|
32
|
+
prd: PRD,
|
|
33
|
+
selection: StorySelection,
|
|
34
|
+
iterations: number,
|
|
35
|
+
totalCost: number,
|
|
36
|
+
allStoryMetrics: StoryMetrics[],
|
|
37
|
+
): Promise<IterationResult> {
|
|
38
|
+
const logger = getSafeLogger();
|
|
39
|
+
const { story, storiesToExecute, routing, isBatchExecution } = selection;
|
|
40
|
+
|
|
41
|
+
if (ctx.dryRun) {
|
|
42
|
+
const dryRunResult = await handleDryRun({
|
|
43
|
+
prd,
|
|
44
|
+
prdPath: ctx.prdPath,
|
|
45
|
+
storiesToExecute,
|
|
46
|
+
routing,
|
|
47
|
+
statusWriter: ctx.statusWriter,
|
|
48
|
+
pluginRegistry: ctx.pluginRegistry,
|
|
49
|
+
runId: ctx.runId,
|
|
50
|
+
totalCost,
|
|
51
|
+
iterations,
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
prd,
|
|
55
|
+
storiesCompletedDelta: dryRunResult.storiesCompletedDelta,
|
|
56
|
+
costDelta: 0,
|
|
57
|
+
prdDirty: dryRunResult.prdDirty,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const storyGitRef = await captureGitRef(ctx.workdir);
|
|
62
|
+
const pipelineContext: PipelineContext = {
|
|
63
|
+
config: ctx.config,
|
|
64
|
+
prd,
|
|
65
|
+
story,
|
|
66
|
+
stories: storiesToExecute,
|
|
67
|
+
routing,
|
|
68
|
+
workdir: ctx.workdir,
|
|
69
|
+
featureDir: ctx.featureDir,
|
|
70
|
+
hooks: ctx.hooks,
|
|
71
|
+
plugins: ctx.pluginRegistry,
|
|
72
|
+
storyStartTime: new Date().toISOString(),
|
|
73
|
+
storyGitRef: storyGitRef ?? undefined,
|
|
74
|
+
interaction: ctx.interactionChain ?? undefined,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
ctx.statusWriter.setPrd(prd);
|
|
78
|
+
ctx.statusWriter.setCurrentStory({
|
|
79
|
+
storyId: story.id,
|
|
80
|
+
title: story.title,
|
|
81
|
+
complexity: routing.complexity,
|
|
82
|
+
tddStrategy: routing.testStrategy,
|
|
83
|
+
model: routing.modelTier,
|
|
84
|
+
attempt: (story.attempts ?? 0) + 1,
|
|
85
|
+
phase: "routing",
|
|
86
|
+
});
|
|
87
|
+
await ctx.statusWriter.update(totalCost, iterations);
|
|
88
|
+
|
|
89
|
+
const pipelineResult = await runPipeline(defaultPipeline, pipelineContext, ctx.eventEmitter);
|
|
90
|
+
const currentPrd = pipelineResult.context.prd;
|
|
91
|
+
|
|
92
|
+
const handlerCtx = {
|
|
93
|
+
config: ctx.config,
|
|
94
|
+
prd: currentPrd,
|
|
95
|
+
prdPath: ctx.prdPath,
|
|
96
|
+
workdir: ctx.workdir,
|
|
97
|
+
featureDir: ctx.featureDir,
|
|
98
|
+
hooks: ctx.hooks,
|
|
99
|
+
feature: ctx.feature,
|
|
100
|
+
totalCost,
|
|
101
|
+
startTime: ctx.startTime,
|
|
102
|
+
runId: ctx.runId,
|
|
103
|
+
pluginRegistry: ctx.pluginRegistry,
|
|
104
|
+
story,
|
|
105
|
+
storiesToExecute,
|
|
106
|
+
routing: pipelineResult.context.routing ?? routing,
|
|
107
|
+
isBatchExecution,
|
|
108
|
+
allStoryMetrics,
|
|
109
|
+
storyGitRef,
|
|
110
|
+
interactionChain: ctx.interactionChain,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
if (pipelineResult.success) {
|
|
114
|
+
const r = await handlePipelineSuccess(handlerCtx, pipelineResult);
|
|
115
|
+
return {
|
|
116
|
+
prd: r.prd,
|
|
117
|
+
storiesCompletedDelta: r.storiesCompletedDelta,
|
|
118
|
+
costDelta: r.costDelta,
|
|
119
|
+
prdDirty: r.prdDirty,
|
|
120
|
+
finalAction: pipelineResult.finalAction,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const r = await handlePipelineFailure(handlerCtx, pipelineResult);
|
|
124
|
+
return {
|
|
125
|
+
prd: r.prd,
|
|
126
|
+
storiesCompletedDelta: 0,
|
|
127
|
+
costDelta: 0,
|
|
128
|
+
prdDirty: r.prdDirty,
|
|
129
|
+
finalAction: pipelineResult.finalAction,
|
|
130
|
+
reason: pipelineResult.reason,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
export { runAcceptanceLoop, type AcceptanceLoopContext, type AcceptanceLoopResult } from "./acceptance-loop";
|
|
6
|
-
export { emitStoryComplete, type StoryCompleteEvent } from "./story-hooks";
|
|
7
6
|
export { outputRunHeader, outputRunFooter, type RunHeaderOptions, type RunFooterOptions } from "./headless-formatter";
|
|
8
7
|
export { handleParallelCompletion, type ParallelCompletionOptions } from "./parallel-lifecycle";
|
|
9
8
|
export { handleRunCompletion, type RunCompletionOptions, type RunCompletionResult } from "./run-completion";
|
|
@@ -14,16 +14,16 @@ import type { PRD, UserStory } from "../../prd";
|
|
|
14
14
|
import { countStories } from "../../prd";
|
|
15
15
|
import { hasCommitsForStory } from "../../utils/git";
|
|
16
16
|
import { parseBunTestOutput } from "../../verification";
|
|
17
|
+
import { runRectificationLoop } from "../../verification/rectification-loop";
|
|
18
|
+
import { fullSuite } from "../../verification/runners";
|
|
17
19
|
import { reverseMapTestToSource } from "../../verification/smart-runner";
|
|
18
|
-
import { runRectificationLoop } from "../post-verify-rectification";
|
|
19
|
-
import { runVerification } from "../verification";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Injectable dependencies for testing (avoids mock.module() which leaks in Bun 1.x).
|
|
23
23
|
* @internal - test use only.
|
|
24
24
|
*/
|
|
25
25
|
export const _regressionDeps = {
|
|
26
|
-
runVerification,
|
|
26
|
+
runVerification: fullSuite,
|
|
27
27
|
runRectificationLoop,
|
|
28
28
|
parseBunTestOutput,
|
|
29
29
|
reverseMapTestToSource,
|
|
@@ -133,7 +133,7 @@ export async function runDeferredRegression(options: DeferredRegressionOptions):
|
|
|
133
133
|
|
|
134
134
|
// Step 1: Run full test suite
|
|
135
135
|
const fullSuiteResult = await _regressionDeps.runVerification({
|
|
136
|
-
|
|
136
|
+
workdir: workdir,
|
|
137
137
|
command: testCommand,
|
|
138
138
|
timeoutSeconds,
|
|
139
139
|
forceExit: config.quality.forceExit,
|
|
@@ -268,7 +268,7 @@ export async function runDeferredRegression(options: DeferredRegressionOptions):
|
|
|
268
268
|
// Step 4: Re-run full suite to confirm
|
|
269
269
|
logger?.info("regression", "Re-running full suite after rectification");
|
|
270
270
|
const retryResult = await _regressionDeps.runVerification({
|
|
271
|
-
|
|
271
|
+
workdir: workdir,
|
|
272
272
|
command: testCommand,
|
|
273
273
|
timeoutSeconds,
|
|
274
274
|
forceExit: config.quality.forceExit,
|