@nathapp/nax 0.50.3 → 0.51.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/CHANGELOG.md +30 -0
- package/README.md +177 -104
- package/dist/nax.js +417 -213
- package/package.json +1 -3
- package/bin/nax.ts +0 -1195
- package/src/acceptance/fix-generator.ts +0 -322
- package/src/acceptance/generator.ts +0 -415
- package/src/acceptance/index.ts +0 -42
- package/src/acceptance/refinement.ts +0 -224
- package/src/acceptance/templates/cli.ts +0 -47
- package/src/acceptance/templates/component.ts +0 -78
- package/src/acceptance/templates/e2e.ts +0 -43
- package/src/acceptance/templates/index.ts +0 -21
- package/src/acceptance/templates/snapshot.ts +0 -50
- package/src/acceptance/templates/unit.ts +0 -48
- package/src/acceptance/types.ts +0 -138
- package/src/agents/acp/adapter.ts +0 -888
- package/src/agents/acp/cost.ts +0 -9
- package/src/agents/acp/index.ts +0 -7
- package/src/agents/acp/interaction-bridge.ts +0 -126
- package/src/agents/acp/parser.ts +0 -119
- package/src/agents/acp/spawn-client.ts +0 -373
- package/src/agents/acp/types.ts +0 -22
- package/src/agents/aider/adapter.ts +0 -135
- package/src/agents/claude/adapter.ts +0 -258
- package/src/agents/claude/complete.ts +0 -80
- package/src/agents/claude/cost.ts +0 -16
- package/src/agents/claude/execution.ts +0 -215
- package/src/agents/claude/index.ts +0 -3
- package/src/agents/claude/interactive.ts +0 -77
- package/src/agents/claude/plan.ts +0 -179
- package/src/agents/codex/adapter.ts +0 -153
- package/src/agents/cost/calculate.ts +0 -154
- package/src/agents/cost/index.ts +0 -10
- package/src/agents/cost/parse.ts +0 -97
- package/src/agents/cost/pricing.ts +0 -59
- package/src/agents/cost/types.ts +0 -45
- package/src/agents/gemini/adapter.ts +0 -177
- package/src/agents/index.ts +0 -18
- package/src/agents/opencode/adapter.ts +0 -106
- package/src/agents/registry.ts +0 -136
- package/src/agents/shared/decompose.ts +0 -154
- package/src/agents/shared/model-resolution.ts +0 -43
- package/src/agents/shared/types-extended.ts +0 -164
- package/src/agents/shared/validation.ts +0 -69
- package/src/agents/shared/version-detection.ts +0 -109
- package/src/agents/types.ts +0 -205
- package/src/analyze/classifier.ts +0 -282
- package/src/analyze/index.ts +0 -16
- package/src/analyze/scanner.ts +0 -171
- package/src/analyze/types.ts +0 -51
- package/src/cli/accept.ts +0 -108
- package/src/cli/agents.ts +0 -87
- package/src/cli/analyze-parser.ts +0 -291
- package/src/cli/analyze.ts +0 -352
- package/src/cli/config-descriptions.ts +0 -219
- package/src/cli/config-diff.ts +0 -103
- package/src/cli/config-display.ts +0 -285
- package/src/cli/config-get.ts +0 -55
- package/src/cli/config.ts +0 -14
- package/src/cli/constitution.ts +0 -17
- package/src/cli/diagnose-analysis.ts +0 -159
- package/src/cli/diagnose-formatter.ts +0 -87
- package/src/cli/diagnose.ts +0 -203
- package/src/cli/generate.ts +0 -250
- package/src/cli/index.ts +0 -42
- package/src/cli/init-context.ts +0 -405
- package/src/cli/init-detect.ts +0 -303
- package/src/cli/init.ts +0 -296
- package/src/cli/interact.ts +0 -295
- package/src/cli/plan.ts +0 -509
- package/src/cli/plugins.ts +0 -122
- package/src/cli/prompts-export.ts +0 -58
- package/src/cli/prompts-init.ts +0 -200
- package/src/cli/prompts-main.ts +0 -183
- package/src/cli/prompts-shared.ts +0 -70
- package/src/cli/prompts-tdd.ts +0 -88
- package/src/cli/prompts.ts +0 -17
- package/src/cli/runs.ts +0 -174
- package/src/cli/status-cost.ts +0 -151
- package/src/cli/status-features.ts +0 -405
- package/src/cli/status.ts +0 -13
- package/src/commands/common.ts +0 -171
- package/src/commands/diagnose.ts +0 -17
- package/src/commands/index.ts +0 -9
- package/src/commands/logs-formatter.ts +0 -201
- package/src/commands/logs-reader.ts +0 -171
- package/src/commands/logs.ts +0 -103
- package/src/commands/precheck.ts +0 -86
- package/src/commands/runs.ts +0 -220
- package/src/commands/unlock.ts +0 -96
- package/src/config/defaults.ts +0 -218
- package/src/config/index.ts +0 -22
- package/src/config/loader.ts +0 -143
- package/src/config/merge.ts +0 -106
- package/src/config/merger.ts +0 -147
- package/src/config/path-security.ts +0 -121
- package/src/config/paths.ts +0 -27
- package/src/config/permissions.ts +0 -63
- package/src/config/runtime-types.ts +0 -522
- package/src/config/schema-types.ts +0 -53
- package/src/config/schema.ts +0 -60
- package/src/config/schemas.ts +0 -426
- package/src/config/test-strategy.ts +0 -71
- package/src/config/types.ts +0 -57
- package/src/config/validate.ts +0 -103
- package/src/constitution/generator.ts +0 -158
- package/src/constitution/generators/aider.ts +0 -41
- package/src/constitution/generators/claude.ts +0 -35
- package/src/constitution/generators/cursor.ts +0 -36
- package/src/constitution/generators/opencode.ts +0 -38
- package/src/constitution/generators/types.ts +0 -33
- package/src/constitution/generators/windsurf.ts +0 -36
- package/src/constitution/index.ts +0 -11
- package/src/constitution/loader.ts +0 -121
- package/src/constitution/types.ts +0 -31
- package/src/context/auto-detect.ts +0 -228
- package/src/context/builder.ts +0 -299
- package/src/context/elements.ts +0 -122
- package/src/context/formatter.ts +0 -107
- package/src/context/generator.ts +0 -343
- package/src/context/generators/aider.ts +0 -34
- package/src/context/generators/claude.ts +0 -28
- package/src/context/generators/codex.ts +0 -28
- package/src/context/generators/cursor.ts +0 -28
- package/src/context/generators/gemini.ts +0 -28
- package/src/context/generators/opencode.ts +0 -30
- package/src/context/generators/windsurf.ts +0 -28
- package/src/context/greenfield.ts +0 -114
- package/src/context/index.ts +0 -34
- package/src/context/injector.ts +0 -279
- package/src/context/parent-context.ts +0 -39
- package/src/context/test-scanner.ts +0 -370
- package/src/context/types.ts +0 -98
- package/src/decompose/apply.ts +0 -50
- package/src/decompose/builder.ts +0 -181
- package/src/decompose/index.ts +0 -8
- package/src/decompose/sections/codebase.ts +0 -26
- package/src/decompose/sections/constraints.ts +0 -32
- package/src/decompose/sections/index.ts +0 -4
- package/src/decompose/sections/sibling-stories.ts +0 -25
- package/src/decompose/sections/target-story.ts +0 -31
- package/src/decompose/types.ts +0 -55
- package/src/decompose/validators/complexity.ts +0 -45
- package/src/decompose/validators/coverage.ts +0 -134
- package/src/decompose/validators/dependency.ts +0 -91
- package/src/decompose/validators/index.ts +0 -35
- package/src/decompose/validators/overlap.ts +0 -128
- package/src/errors.ts +0 -67
- package/src/execution/batching.ts +0 -157
- package/src/execution/crash-heartbeat.ts +0 -77
- package/src/execution/crash-recovery.ts +0 -79
- package/src/execution/crash-signals.ts +0 -165
- package/src/execution/crash-writer.ts +0 -154
- package/src/execution/deferred-review.ts +0 -105
- package/src/execution/dry-run.ts +0 -81
- package/src/execution/escalation/escalation.ts +0 -46
- package/src/execution/escalation/index.ts +0 -13
- package/src/execution/escalation/tier-escalation.ts +0 -346
- package/src/execution/escalation/tier-outcome.ts +0 -143
- package/src/execution/executor-types.ts +0 -73
- package/src/execution/helpers.ts +0 -38
- package/src/execution/index.ts +0 -27
- package/src/execution/iteration-runner.ts +0 -160
- package/src/execution/lifecycle/acceptance-loop.ts +0 -309
- package/src/execution/lifecycle/headless-formatter.ts +0 -83
- package/src/execution/lifecycle/index.ts +0 -11
- package/src/execution/lifecycle/parallel-lifecycle.ts +0 -101
- package/src/execution/lifecycle/precheck-runner.ts +0 -140
- package/src/execution/lifecycle/run-cleanup.ts +0 -81
- package/src/execution/lifecycle/run-completion.ts +0 -247
- package/src/execution/lifecycle/run-initialization.ts +0 -187
- package/src/execution/lifecycle/run-regression.ts +0 -305
- package/src/execution/lifecycle/run-setup.ts +0 -240
- package/src/execution/lifecycle/story-size-prompts.ts +0 -123
- package/src/execution/lock.ts +0 -129
- package/src/execution/parallel-coordinator.ts +0 -281
- package/src/execution/parallel-executor-rectification-pass.ts +0 -117
- package/src/execution/parallel-executor-rectify.ts +0 -136
- package/src/execution/parallel-executor.ts +0 -330
- package/src/execution/parallel-worker.ts +0 -149
- package/src/execution/parallel.ts +0 -13
- package/src/execution/pid-registry.ts +0 -275
- package/src/execution/pipeline-result-handler.ts +0 -221
- package/src/execution/progress.ts +0 -27
- package/src/execution/queue-handler.ts +0 -109
- package/src/execution/runner-completion.ts +0 -171
- package/src/execution/runner-execution.ts +0 -243
- package/src/execution/runner-setup.ts +0 -86
- package/src/execution/runner.ts +0 -265
- package/src/execution/sequential-executor.ts +0 -219
- package/src/execution/status-file.ts +0 -264
- package/src/execution/status-writer.ts +0 -181
- package/src/execution/story-context.ts +0 -266
- package/src/execution/story-selector.ts +0 -76
- package/src/execution/test-output-parser.ts +0 -14
- package/src/execution/timeout-handler.ts +0 -100
- package/src/hooks/index.ts +0 -2
- package/src/hooks/runner.ts +0 -280
- package/src/hooks/types.ts +0 -79
- package/src/interaction/chain.ts +0 -170
- package/src/interaction/index.ts +0 -61
- package/src/interaction/init.ts +0 -84
- package/src/interaction/plugins/auto.ts +0 -243
- package/src/interaction/plugins/cli.ts +0 -300
- package/src/interaction/plugins/telegram.ts +0 -384
- package/src/interaction/plugins/webhook.ts +0 -286
- package/src/interaction/state.ts +0 -171
- package/src/interaction/triggers.ts +0 -250
- package/src/interaction/types.ts +0 -170
- package/src/logger/formatters.ts +0 -84
- package/src/logger/index.ts +0 -16
- package/src/logger/logger.ts +0 -296
- package/src/logger/types.ts +0 -48
- package/src/logging/formatter.ts +0 -355
- package/src/logging/index.ts +0 -22
- package/src/logging/types.ts +0 -93
- package/src/metrics/aggregator.ts +0 -191
- package/src/metrics/index.ts +0 -14
- package/src/metrics/tracker.ts +0 -200
- package/src/metrics/types.ts +0 -115
- package/src/optimizer/index.ts +0 -63
- package/src/optimizer/noop.optimizer.ts +0 -24
- package/src/optimizer/rule-based.optimizer.ts +0 -248
- package/src/optimizer/types.ts +0 -53
- package/src/pipeline/event-bus.ts +0 -297
- package/src/pipeline/events.ts +0 -130
- package/src/pipeline/index.ts +0 -19
- package/src/pipeline/runner.ts +0 -149
- package/src/pipeline/stages/acceptance-setup.ts +0 -144
- package/src/pipeline/stages/acceptance.ts +0 -215
- package/src/pipeline/stages/autofix.ts +0 -262
- package/src/pipeline/stages/completion.ts +0 -110
- package/src/pipeline/stages/constitution.ts +0 -63
- package/src/pipeline/stages/context.ts +0 -122
- package/src/pipeline/stages/execution.ts +0 -359
- package/src/pipeline/stages/index.ts +0 -86
- package/src/pipeline/stages/optimizer.ts +0 -74
- package/src/pipeline/stages/prompt.ts +0 -79
- package/src/pipeline/stages/queue-check.ts +0 -103
- package/src/pipeline/stages/rectify.ts +0 -101
- package/src/pipeline/stages/regression.ts +0 -99
- package/src/pipeline/stages/review.ts +0 -94
- package/src/pipeline/stages/routing.ts +0 -276
- package/src/pipeline/stages/verify.ts +0 -286
- package/src/pipeline/subscribers/events-writer.ts +0 -135
- package/src/pipeline/subscribers/hooks.ts +0 -179
- package/src/pipeline/subscribers/interaction.ts +0 -103
- package/src/pipeline/subscribers/registry.ts +0 -73
- package/src/pipeline/subscribers/reporters.ts +0 -174
- package/src/pipeline/types.ts +0 -220
- package/src/plugins/extensions.ts +0 -225
- package/src/plugins/index.ts +0 -33
- package/src/plugins/loader.ts +0 -352
- package/src/plugins/plugin-logger.ts +0 -41
- package/src/plugins/registry.ts +0 -168
- package/src/plugins/types.ts +0 -206
- package/src/plugins/validator.ts +0 -352
- package/src/prd/index.ts +0 -220
- package/src/prd/schema.ts +0 -268
- package/src/prd/types.ts +0 -273
- package/src/prd/validate.ts +0 -41
- package/src/precheck/checks-agents.ts +0 -63
- package/src/precheck/checks-blockers.ts +0 -23
- package/src/precheck/checks-cli.ts +0 -68
- package/src/precheck/checks-config.ts +0 -102
- package/src/precheck/checks-git.ts +0 -117
- package/src/precheck/checks-system.ts +0 -101
- package/src/precheck/checks-warnings.ts +0 -221
- package/src/precheck/checks.ts +0 -36
- package/src/precheck/index.ts +0 -374
- package/src/precheck/story-size-gate.ts +0 -144
- package/src/precheck/types.ts +0 -31
- package/src/prompts/builder.ts +0 -166
- package/src/prompts/index.ts +0 -2
- package/src/prompts/loader.ts +0 -43
- package/src/prompts/sections/conventions.ts +0 -19
- package/src/prompts/sections/hermetic.ts +0 -41
- package/src/prompts/sections/index.ts +0 -12
- package/src/prompts/sections/isolation.ts +0 -70
- package/src/prompts/sections/role-task.ts +0 -182
- package/src/prompts/sections/story.ts +0 -55
- package/src/prompts/sections/verdict.ts +0 -70
- package/src/prompts/types.ts +0 -21
- package/src/queue/index.ts +0 -2
- package/src/queue/manager.ts +0 -254
- package/src/queue/types.ts +0 -54
- package/src/review/index.ts +0 -8
- package/src/review/orchestrator.ts +0 -154
- package/src/review/runner.ts +0 -303
- package/src/review/types.ts +0 -70
- package/src/routing/batch-route.ts +0 -35
- package/src/routing/builder.ts +0 -81
- package/src/routing/chain.ts +0 -75
- package/src/routing/content-hash.ts +0 -25
- package/src/routing/index.ts +0 -20
- package/src/routing/loader.ts +0 -62
- package/src/routing/router.ts +0 -305
- package/src/routing/strategies/adaptive.ts +0 -215
- package/src/routing/strategies/index.ts +0 -8
- package/src/routing/strategies/keyword.ts +0 -180
- package/src/routing/strategies/llm-prompts.ts +0 -224
- package/src/routing/strategies/llm.ts +0 -320
- package/src/routing/strategies/manual.ts +0 -50
- package/src/routing/strategy.ts +0 -102
- package/src/tdd/cleanup.ts +0 -120
- package/src/tdd/index.ts +0 -22
- package/src/tdd/isolation.ts +0 -117
- package/src/tdd/orchestrator.ts +0 -406
- package/src/tdd/prompts.ts +0 -40
- package/src/tdd/rectification-gate.ts +0 -274
- package/src/tdd/session-runner.ts +0 -263
- package/src/tdd/types.ts +0 -84
- package/src/tdd/verdict-reader.ts +0 -266
- package/src/tdd/verdict.ts +0 -152
- package/src/tui/App.tsx +0 -265
- package/src/tui/components/AgentPanel.tsx +0 -75
- package/src/tui/components/CostOverlay.tsx +0 -118
- package/src/tui/components/HelpOverlay.tsx +0 -107
- package/src/tui/components/StatusBar.tsx +0 -63
- package/src/tui/components/StoriesPanel.tsx +0 -177
- package/src/tui/hooks/useKeyboard.ts +0 -142
- package/src/tui/hooks/useLayout.ts +0 -137
- package/src/tui/hooks/usePipelineEvents.ts +0 -183
- package/src/tui/hooks/usePty.ts +0 -189
- package/src/tui/index.tsx +0 -38
- package/src/tui/types.ts +0 -76
- package/src/utils/errors.ts +0 -12
- package/src/utils/git.ts +0 -245
- package/src/utils/json-file.ts +0 -72
- package/src/utils/log-test-output.ts +0 -25
- package/src/utils/path-security.ts +0 -73
- package/src/utils/queue-writer.ts +0 -54
- package/src/verification/crash-detector.ts +0 -34
- package/src/verification/executor.ts +0 -250
- package/src/verification/index.ts +0 -12
- package/src/verification/orchestrator-types.ts +0 -154
- package/src/verification/orchestrator.ts +0 -76
- package/src/verification/parser.ts +0 -220
- package/src/verification/rectification-loop.ts +0 -172
- package/src/verification/rectification.ts +0 -108
- package/src/verification/runners.ts +0 -129
- package/src/verification/smart-runner.ts +0 -307
- package/src/verification/strategies/acceptance.ts +0 -136
- package/src/verification/strategies/regression.ts +0 -90
- package/src/verification/strategies/scoped.ts +0 -154
- package/src/verification/types.ts +0 -117
- package/src/version.ts +0 -40
- package/src/worktree/dispatcher.ts +0 -6
- package/src/worktree/index.ts +0 -2
- package/src/worktree/manager.ts +0 -193
- package/src/worktree/merge.ts +0 -302
- package/src/worktree/types.ts +0 -4
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Run Cleanup — Finally Block Cleanup Logic
|
|
3
|
-
*
|
|
4
|
-
* Handles cleanup operations that run in the finally block:
|
|
5
|
-
* - Stop heartbeat
|
|
6
|
-
* - Cleanup crash handlers
|
|
7
|
-
* - Fire onRunEnd for reporters
|
|
8
|
-
* - Teardown plugins
|
|
9
|
-
* - Release lock
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import type { InteractionChain } from "../../interaction";
|
|
13
|
-
import { getSafeLogger } from "../../logger";
|
|
14
|
-
import type { PluginRegistry } from "../../plugins/registry";
|
|
15
|
-
import { countStories } from "../../prd";
|
|
16
|
-
import type { PRD } from "../../prd";
|
|
17
|
-
import { releaseLock } from "../helpers";
|
|
18
|
-
|
|
19
|
-
export interface RunCleanupOptions {
|
|
20
|
-
runId: string;
|
|
21
|
-
startTime: number;
|
|
22
|
-
totalCost: number;
|
|
23
|
-
storiesCompleted: number;
|
|
24
|
-
prd: PRD;
|
|
25
|
-
pluginRegistry: PluginRegistry;
|
|
26
|
-
workdir: string;
|
|
27
|
-
interactionChain: InteractionChain | null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Execute cleanup operations in finally block
|
|
32
|
-
*/
|
|
33
|
-
export async function cleanupRun(options: RunCleanupOptions): Promise<void> {
|
|
34
|
-
const logger = getSafeLogger();
|
|
35
|
-
const { runId, startTime, totalCost, storiesCompleted, prd, pluginRegistry, workdir, interactionChain } = options;
|
|
36
|
-
|
|
37
|
-
// Fire onRunEnd for reporters (even on failure/abort)
|
|
38
|
-
const durationMs = Date.now() - startTime;
|
|
39
|
-
const finalCounts = countStories(prd);
|
|
40
|
-
const reporters = pluginRegistry.getReporters();
|
|
41
|
-
|
|
42
|
-
for (const reporter of reporters) {
|
|
43
|
-
if (reporter.onRunEnd) {
|
|
44
|
-
try {
|
|
45
|
-
await reporter.onRunEnd({
|
|
46
|
-
runId,
|
|
47
|
-
totalDurationMs: durationMs,
|
|
48
|
-
totalCost,
|
|
49
|
-
storySummary: {
|
|
50
|
-
completed: storiesCompleted,
|
|
51
|
-
failed: finalCounts.failed,
|
|
52
|
-
skipped: finalCounts.skipped,
|
|
53
|
-
paused: finalCounts.paused,
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
} catch (error) {
|
|
57
|
-
logger?.warn("plugins", `Reporter '${reporter.name}' onRunEnd failed`, { error });
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Teardown plugins
|
|
63
|
-
try {
|
|
64
|
-
await pluginRegistry.teardownAll();
|
|
65
|
-
} catch (error) {
|
|
66
|
-
logger?.warn("plugins", "Plugin teardown failed", { error });
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Destroy interaction chain (US-008)
|
|
70
|
-
if (interactionChain) {
|
|
71
|
-
try {
|
|
72
|
-
await interactionChain.destroy();
|
|
73
|
-
logger?.debug("interaction", "Interaction chain destroyed");
|
|
74
|
-
} catch (error) {
|
|
75
|
-
logger?.warn("interaction", "Interaction chain cleanup failed", { error });
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Always release lock, even if execution fails
|
|
80
|
-
await releaseLock(workdir);
|
|
81
|
-
}
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Run Completion — Final Metrics and Status Updates
|
|
3
|
-
*
|
|
4
|
-
* Handles the final steps after sequential execution completes:
|
|
5
|
-
* - Run deferred regression gate (if configured)
|
|
6
|
-
* - Save run metrics
|
|
7
|
-
* - Log completion summary with per-story metrics
|
|
8
|
-
* - Update final status
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { NaxConfig } from "../../config";
|
|
12
|
-
import { fireHook } from "../../hooks/runner";
|
|
13
|
-
import type { HooksConfig } from "../../hooks/types";
|
|
14
|
-
import { getSafeLogger } from "../../logger";
|
|
15
|
-
import type { StoryMetrics } from "../../metrics";
|
|
16
|
-
import { saveRunMetrics } from "../../metrics";
|
|
17
|
-
import { pipelineEventBus } from "../../pipeline/event-bus";
|
|
18
|
-
import type { AgentGetFn } from "../../pipeline/types";
|
|
19
|
-
import { countStories, isComplete, isStalled } from "../../prd";
|
|
20
|
-
import type { PRD } from "../../prd";
|
|
21
|
-
import type { StatusWriter } from "../status-writer";
|
|
22
|
-
import { runDeferredRegression } from "./run-regression";
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Injectable dependencies for testing (avoids mock.module() which leaks in Bun 1.x).
|
|
26
|
-
* @internal - test use only.
|
|
27
|
-
*/
|
|
28
|
-
export const _runCompletionDeps = {
|
|
29
|
-
runDeferredRegression,
|
|
30
|
-
fireHook,
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export interface RunCompletionOptions {
|
|
34
|
-
runId: string;
|
|
35
|
-
feature: string;
|
|
36
|
-
startedAt: string;
|
|
37
|
-
prd: PRD;
|
|
38
|
-
allStoryMetrics: StoryMetrics[];
|
|
39
|
-
totalCost: number;
|
|
40
|
-
storiesCompleted: number;
|
|
41
|
-
iterations: number;
|
|
42
|
-
startTime: number;
|
|
43
|
-
workdir: string;
|
|
44
|
-
statusWriter: StatusWriter;
|
|
45
|
-
config: NaxConfig;
|
|
46
|
-
hooksConfig?: HooksConfig;
|
|
47
|
-
/** Whether the run used sequential (non-parallel) execution. Defaults to true. */
|
|
48
|
-
isSequential?: boolean;
|
|
49
|
-
/** Protocol-aware agent resolver (ACP wiring). Falls back to static getAgent when absent. */
|
|
50
|
-
agentGetFn?: AgentGetFn;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface RunCompletionResult {
|
|
54
|
-
durationMs: number;
|
|
55
|
-
runCompletedAt: string;
|
|
56
|
-
finalCounts: {
|
|
57
|
-
total: number;
|
|
58
|
-
passed: number;
|
|
59
|
-
failed: number;
|
|
60
|
-
skipped: number;
|
|
61
|
-
pending: number;
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Check if deferred regression should be skipped (RL-006).
|
|
67
|
-
*
|
|
68
|
-
* Smart-skip applies when:
|
|
69
|
-
* 1. All stories have fullSuiteGatePassed === true
|
|
70
|
-
* 2. Execution is sequential (or defaults to sequential when not specified)
|
|
71
|
-
* 3. There is at least one story metric
|
|
72
|
-
*/
|
|
73
|
-
function shouldSkipDeferredRegression(allStoryMetrics: StoryMetrics[], isSequential: boolean | undefined): boolean {
|
|
74
|
-
// Default to sequential mode
|
|
75
|
-
const effectiveSequential = isSequential !== false;
|
|
76
|
-
|
|
77
|
-
// Must be sequential mode
|
|
78
|
-
if (!effectiveSequential) {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Must have at least one story metric
|
|
83
|
-
if (allStoryMetrics.length === 0) {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// All stories must have fullSuiteGatePassed === true
|
|
88
|
-
return allStoryMetrics.every((m) => m.fullSuiteGatePassed === true);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Handle final run completion: save metrics, log summary, update status
|
|
93
|
-
*/
|
|
94
|
-
export async function handleRunCompletion(options: RunCompletionOptions): Promise<RunCompletionResult> {
|
|
95
|
-
const logger = getSafeLogger();
|
|
96
|
-
const {
|
|
97
|
-
runId,
|
|
98
|
-
feature,
|
|
99
|
-
startedAt,
|
|
100
|
-
prd,
|
|
101
|
-
allStoryMetrics,
|
|
102
|
-
totalCost,
|
|
103
|
-
storiesCompleted,
|
|
104
|
-
iterations,
|
|
105
|
-
startTime,
|
|
106
|
-
workdir,
|
|
107
|
-
statusWriter,
|
|
108
|
-
config,
|
|
109
|
-
hooksConfig,
|
|
110
|
-
isSequential,
|
|
111
|
-
} = options;
|
|
112
|
-
|
|
113
|
-
// Run deferred regression gate before final metrics
|
|
114
|
-
const regressionMode = config.execution.regressionGate?.mode;
|
|
115
|
-
if (regressionMode === "deferred" && config.quality.commands.test) {
|
|
116
|
-
if (shouldSkipDeferredRegression(allStoryMetrics, isSequential)) {
|
|
117
|
-
logger?.info(
|
|
118
|
-
"regression",
|
|
119
|
-
"Smart-skip: skipping deferred regression (all stories passed full-suite gate in sequential mode)",
|
|
120
|
-
);
|
|
121
|
-
} else {
|
|
122
|
-
const regressionResult = await _runCompletionDeps.runDeferredRegression({
|
|
123
|
-
config,
|
|
124
|
-
prd,
|
|
125
|
-
workdir,
|
|
126
|
-
agentGetFn: options.agentGetFn,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
logger?.info("regression", "Deferred regression gate completed", {
|
|
130
|
-
success: regressionResult.success,
|
|
131
|
-
failedTests: regressionResult.failedTests,
|
|
132
|
-
affectedStories: regressionResult.affectedStories,
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
if (!regressionResult.success) {
|
|
136
|
-
// Mark affected stories as regression-failed (RL-004)
|
|
137
|
-
for (const storyId of regressionResult.affectedStories) {
|
|
138
|
-
const story = prd.userStories.find((s) => s.id === storyId);
|
|
139
|
-
if (story) {
|
|
140
|
-
story.status = "regression-failed";
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
// Reflect regression gate failure in run status (RL-004)
|
|
144
|
-
statusWriter.setRunStatus("failed");
|
|
145
|
-
|
|
146
|
-
if (hooksConfig) {
|
|
147
|
-
await _runCompletionDeps.fireHook(
|
|
148
|
-
hooksConfig as import("../../hooks/runner").LoadedHooksConfig,
|
|
149
|
-
"on-final-regression-fail",
|
|
150
|
-
{
|
|
151
|
-
event: "on-final-regression-fail",
|
|
152
|
-
feature,
|
|
153
|
-
status: "failed",
|
|
154
|
-
failedTests: regressionResult.failedTests,
|
|
155
|
-
affectedStories: regressionResult.affectedStories,
|
|
156
|
-
},
|
|
157
|
-
workdir,
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const durationMs = Date.now() - startTime;
|
|
165
|
-
const runCompletedAt = new Date().toISOString();
|
|
166
|
-
|
|
167
|
-
// Compute final story counts before emitting completion event (RL-002)
|
|
168
|
-
const finalCounts = countStories(prd);
|
|
169
|
-
|
|
170
|
-
// Emit run:completed after regression gate with real story counts (RL-002)
|
|
171
|
-
pipelineEventBus.emit({
|
|
172
|
-
type: "run:completed",
|
|
173
|
-
totalStories: finalCounts.total,
|
|
174
|
-
passedStories: finalCounts.passed,
|
|
175
|
-
failedStories: finalCounts.failed,
|
|
176
|
-
durationMs,
|
|
177
|
-
totalCost,
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
// Save run metrics (best-effort — disk write errors do not fail the run)
|
|
181
|
-
const runMetrics = {
|
|
182
|
-
runId,
|
|
183
|
-
feature,
|
|
184
|
-
startedAt,
|
|
185
|
-
completedAt: runCompletedAt,
|
|
186
|
-
totalCost,
|
|
187
|
-
totalStories: allStoryMetrics.length,
|
|
188
|
-
storiesCompleted,
|
|
189
|
-
storiesFailed: finalCounts.failed,
|
|
190
|
-
totalDurationMs: durationMs,
|
|
191
|
-
stories: allStoryMetrics,
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
await saveRunMetrics(workdir, runMetrics);
|
|
196
|
-
} catch (err) {
|
|
197
|
-
logger?.warn("run.complete", "Failed to save run metrics", { error: String(err) });
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Log run completion
|
|
201
|
-
|
|
202
|
-
// Prepare per-story metrics summary
|
|
203
|
-
const storyMetricsSummary = allStoryMetrics.map((sm) => ({
|
|
204
|
-
storyId: sm.storyId,
|
|
205
|
-
complexity: sm.complexity,
|
|
206
|
-
modelTier: sm.modelTier,
|
|
207
|
-
modelUsed: sm.modelUsed,
|
|
208
|
-
attempts: sm.attempts,
|
|
209
|
-
finalTier: sm.finalTier,
|
|
210
|
-
success: sm.success,
|
|
211
|
-
cost: sm.cost,
|
|
212
|
-
durationMs: sm.durationMs,
|
|
213
|
-
firstPassSuccess: sm.firstPassSuccess,
|
|
214
|
-
}));
|
|
215
|
-
|
|
216
|
-
logger?.info("run.complete", "Feature execution completed", {
|
|
217
|
-
runId,
|
|
218
|
-
feature,
|
|
219
|
-
success: isComplete(prd),
|
|
220
|
-
iterations,
|
|
221
|
-
totalStories: finalCounts.total,
|
|
222
|
-
storiesCompleted,
|
|
223
|
-
storiesFailed: finalCounts.failed,
|
|
224
|
-
storiesPending: finalCounts.pending,
|
|
225
|
-
totalCost,
|
|
226
|
-
durationMs,
|
|
227
|
-
storyMetrics: storyMetricsSummary,
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
// Update final status
|
|
231
|
-
statusWriter.setPrd(prd);
|
|
232
|
-
statusWriter.setCurrentStory(null);
|
|
233
|
-
statusWriter.setRunStatus(isComplete(prd) ? "completed" : isStalled(prd) ? "stalled" : "running");
|
|
234
|
-
await statusWriter.update(totalCost, iterations);
|
|
235
|
-
|
|
236
|
-
return {
|
|
237
|
-
durationMs,
|
|
238
|
-
runCompletedAt,
|
|
239
|
-
finalCounts: {
|
|
240
|
-
total: finalCounts.total,
|
|
241
|
-
passed: finalCounts.passed,
|
|
242
|
-
failed: finalCounts.failed,
|
|
243
|
-
skipped: finalCounts.skipped,
|
|
244
|
-
pending: finalCounts.pending,
|
|
245
|
-
},
|
|
246
|
-
};
|
|
247
|
-
}
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Run Initialization
|
|
3
|
-
*
|
|
4
|
-
* Handles initialization tasks before the main execution loop starts:
|
|
5
|
-
* 1. State reconciliation (failed stories with commits)
|
|
6
|
-
* 2. Agent installation check
|
|
7
|
-
* 3. Story count validation
|
|
8
|
-
* 4. Initial PRD analysis
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { join } from "node:path";
|
|
12
|
-
import chalk from "chalk";
|
|
13
|
-
import type { NaxConfig } from "../../config";
|
|
14
|
-
import { AgentNotFoundError, AgentNotInstalledError, StoryLimitExceededError } from "../../errors";
|
|
15
|
-
import { getSafeLogger } from "../../logger";
|
|
16
|
-
import type { AgentGetFn } from "../../pipeline/types";
|
|
17
|
-
import { countStories, loadPRD, markStoryPassed, savePRD } from "../../prd";
|
|
18
|
-
import type { PRD } from "../../prd/types";
|
|
19
|
-
import { runReview } from "../../review/runner";
|
|
20
|
-
import type { ReviewConfig } from "../../review/types";
|
|
21
|
-
import { hasCommitsForStory } from "../../utils/git";
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Injectable dependencies for reconcileState — allows tests to mock
|
|
25
|
-
* hasCommitsForStory and runReview without mock.module().
|
|
26
|
-
*/
|
|
27
|
-
export const _reconcileDeps = {
|
|
28
|
-
hasCommitsForStory: (workdir: string, storyId: string) => hasCommitsForStory(workdir, storyId),
|
|
29
|
-
runReview: (reviewConfig: ReviewConfig, workdir: string, executionConfig: NaxConfig["execution"]) =>
|
|
30
|
-
runReview(reviewConfig, workdir, executionConfig),
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export interface InitializationContext {
|
|
34
|
-
config: NaxConfig;
|
|
35
|
-
prdPath: string;
|
|
36
|
-
workdir: string;
|
|
37
|
-
dryRun: boolean;
|
|
38
|
-
/** Protocol-aware agent resolver — passed from registry at run start */
|
|
39
|
-
agentGetFn?: AgentGetFn;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface InitializationResult {
|
|
43
|
-
prd: PRD;
|
|
44
|
-
storyCounts: {
|
|
45
|
-
total: number;
|
|
46
|
-
pending: number;
|
|
47
|
-
passed: number;
|
|
48
|
-
failed: number;
|
|
49
|
-
skipped: number;
|
|
50
|
-
paused: number;
|
|
51
|
-
blocked: number;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Reconcile PRD state with git history
|
|
57
|
-
*
|
|
58
|
-
* Checks if failed stories have commits in git history and marks them as passed.
|
|
59
|
-
* For stories that failed at review/autofix stage, re-runs the review before
|
|
60
|
-
* reconciling to ensure the code quality issues were actually fixed.
|
|
61
|
-
*/
|
|
62
|
-
async function reconcileState(prd: PRD, prdPath: string, workdir: string, config: NaxConfig): Promise<PRD> {
|
|
63
|
-
const logger = getSafeLogger();
|
|
64
|
-
let reconciledCount = 0;
|
|
65
|
-
let modified = false;
|
|
66
|
-
|
|
67
|
-
for (const story of prd.userStories) {
|
|
68
|
-
if (story.status !== "failed") continue;
|
|
69
|
-
|
|
70
|
-
const hasCommits = await _reconcileDeps.hasCommitsForStory(workdir, story.id);
|
|
71
|
-
if (!hasCommits) continue;
|
|
72
|
-
|
|
73
|
-
// Gate: re-run review for stories that failed at review/autofix stage
|
|
74
|
-
if (story.failureStage === "review" || story.failureStage === "autofix") {
|
|
75
|
-
const effectiveWorkdir = story.workdir ? join(workdir, story.workdir) : workdir;
|
|
76
|
-
try {
|
|
77
|
-
const reviewResult = await _reconcileDeps.runReview(config.review, effectiveWorkdir, config.execution);
|
|
78
|
-
if (!reviewResult.success) {
|
|
79
|
-
logger?.warn("reconciliation", "Review still fails — not reconciling story", {
|
|
80
|
-
storyId: story.id,
|
|
81
|
-
failureReason: reviewResult.failureReason,
|
|
82
|
-
});
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
logger?.info("reconciliation", "Review now passes — reconciling story", { storyId: story.id });
|
|
86
|
-
} catch {
|
|
87
|
-
// Non-fatal: if review check errors, skip reconciliation for this story
|
|
88
|
-
logger?.warn("reconciliation", "Review check errored — not reconciling story", { storyId: story.id });
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
logger?.warn("reconciliation", "Failed story has commits in git history, marking as passed", {
|
|
94
|
-
storyId: story.id,
|
|
95
|
-
title: story.title,
|
|
96
|
-
});
|
|
97
|
-
markStoryPassed(prd, story.id);
|
|
98
|
-
reconciledCount++;
|
|
99
|
-
modified = true;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (reconciledCount > 0) {
|
|
103
|
-
logger?.info("reconciliation", `Reconciled ${reconciledCount} failed stories from git history`);
|
|
104
|
-
await savePRD(prd, prdPath);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return prd;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Validate agent installation
|
|
112
|
-
*/
|
|
113
|
-
async function checkAgentInstalled(config: NaxConfig, dryRun: boolean, agentGetFn?: AgentGetFn): Promise<void> {
|
|
114
|
-
if (dryRun) return;
|
|
115
|
-
|
|
116
|
-
const logger = getSafeLogger();
|
|
117
|
-
const { getAgent } = await import("../../agents");
|
|
118
|
-
const agent = (agentGetFn ?? getAgent)(config.autoMode.defaultAgent);
|
|
119
|
-
|
|
120
|
-
if (!agent) {
|
|
121
|
-
logger?.error("execution", "Agent not found", {
|
|
122
|
-
agent: config.autoMode.defaultAgent,
|
|
123
|
-
});
|
|
124
|
-
throw new AgentNotFoundError(config.autoMode.defaultAgent);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const installed = await agent.isInstalled();
|
|
128
|
-
if (!installed) {
|
|
129
|
-
logger?.error("execution", "Agent is not installed or not in PATH", {
|
|
130
|
-
agent: config.autoMode.defaultAgent,
|
|
131
|
-
binary: agent.binary,
|
|
132
|
-
});
|
|
133
|
-
logger?.error("execution", "Please install the agent and try again");
|
|
134
|
-
throw new AgentNotInstalledError(config.autoMode.defaultAgent, agent.binary);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Validate story count doesn't exceed limit
|
|
140
|
-
*/
|
|
141
|
-
function validateStoryCount(counts: ReturnType<typeof countStories>, config: NaxConfig): void {
|
|
142
|
-
const logger = getSafeLogger();
|
|
143
|
-
|
|
144
|
-
if (counts.total > config.execution.maxStoriesPerFeature) {
|
|
145
|
-
logger?.error("execution", "Feature exceeds story limit", {
|
|
146
|
-
totalStories: counts.total,
|
|
147
|
-
limit: config.execution.maxStoriesPerFeature,
|
|
148
|
-
});
|
|
149
|
-
logger?.error("execution", "Split this feature into smaller features or increase maxStoriesPerFeature in config");
|
|
150
|
-
throw new StoryLimitExceededError(counts.total, config.execution.maxStoriesPerFeature);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Log the active agent protocol to aid debugging.
|
|
156
|
-
*/
|
|
157
|
-
export function logActiveProtocol(config: NaxConfig): void {
|
|
158
|
-
const logger = getSafeLogger();
|
|
159
|
-
const protocol = config.agent?.protocol ?? "cli";
|
|
160
|
-
logger?.info("run-initialization", `Agent protocol: ${protocol}`, { protocol });
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Initialize execution: validate agent, reconcile state, check limits
|
|
165
|
-
*/
|
|
166
|
-
export async function initializeRun(ctx: InitializationContext): Promise<InitializationResult> {
|
|
167
|
-
const logger = getSafeLogger();
|
|
168
|
-
|
|
169
|
-
// Check agent installation
|
|
170
|
-
await checkAgentInstalled(ctx.config, ctx.dryRun, ctx.agentGetFn);
|
|
171
|
-
|
|
172
|
-
// Load and reconcile PRD
|
|
173
|
-
let prd = await loadPRD(ctx.prdPath);
|
|
174
|
-
prd = await reconcileState(prd, ctx.prdPath, ctx.workdir, ctx.config);
|
|
175
|
-
|
|
176
|
-
// Validate story counts
|
|
177
|
-
const counts = countStories(prd);
|
|
178
|
-
validateStoryCount(counts, ctx.config);
|
|
179
|
-
|
|
180
|
-
logger?.info("execution", "Run initialization complete", {
|
|
181
|
-
totalStories: counts.total,
|
|
182
|
-
doneStories: counts.passed,
|
|
183
|
-
pendingStories: counts.pending,
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
return { prd, storyCounts: counts };
|
|
187
|
-
}
|