@nathapp/nax 0.50.3 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/dist/nax.js +393 -197
- 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,117 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unified Verification Types
|
|
3
|
-
*
|
|
4
|
-
* Shared type definitions for test execution, parsing, and verification.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** Verification scope: what tests to run */
|
|
8
|
-
export type VerificationScope = "scoped" | "full" | "regression";
|
|
9
|
-
|
|
10
|
-
/** Verification status outcomes */
|
|
11
|
-
export type VerificationStatus =
|
|
12
|
-
| "SUCCESS"
|
|
13
|
-
| "TEST_FAILURE"
|
|
14
|
-
| "ENVIRONMENTAL_FAILURE"
|
|
15
|
-
| "ASSET_CHECK_FAILED"
|
|
16
|
-
| "TIMEOUT";
|
|
17
|
-
|
|
18
|
-
/** Test execution result (raw) */
|
|
19
|
-
export interface TestExecutionResult {
|
|
20
|
-
success: boolean;
|
|
21
|
-
timeout: boolean;
|
|
22
|
-
exitCode?: number;
|
|
23
|
-
output?: string;
|
|
24
|
-
error?: string;
|
|
25
|
-
killed?: boolean;
|
|
26
|
-
childProcessesKilled?: boolean;
|
|
27
|
-
countsTowardEscalation: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Test output analysis (parsed) */
|
|
31
|
-
export interface TestOutputAnalysis {
|
|
32
|
-
allTestsPassed: boolean;
|
|
33
|
-
passCount: number;
|
|
34
|
-
failCount: number;
|
|
35
|
-
isEnvironmentalFailure: boolean;
|
|
36
|
-
error?: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Asset verification result */
|
|
40
|
-
export interface AssetVerificationResult {
|
|
41
|
-
success: boolean;
|
|
42
|
-
missingFiles: string[];
|
|
43
|
-
error?: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Structured test failure information */
|
|
47
|
-
export interface TestFailure {
|
|
48
|
-
/** File path where the test failed */
|
|
49
|
-
file: string;
|
|
50
|
-
/** Full test name (including nested describe blocks) */
|
|
51
|
-
testName: string;
|
|
52
|
-
/** Error message */
|
|
53
|
-
error: string;
|
|
54
|
-
/** Stack trace lines (truncated to first 5 lines) */
|
|
55
|
-
stackTrace: string[];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** Test run summary */
|
|
59
|
-
export interface TestSummary {
|
|
60
|
-
/** Number of tests that passed */
|
|
61
|
-
passed: number;
|
|
62
|
-
/** Number of tests that failed */
|
|
63
|
-
failed: number;
|
|
64
|
-
/** Structured failure details */
|
|
65
|
-
failures: TestFailure[];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Complete verification result */
|
|
69
|
-
export interface VerificationResult {
|
|
70
|
-
status: VerificationStatus;
|
|
71
|
-
success: boolean;
|
|
72
|
-
countsTowardEscalation: boolean;
|
|
73
|
-
output?: string;
|
|
74
|
-
error?: string;
|
|
75
|
-
missingFiles?: string[];
|
|
76
|
-
passCount?: number;
|
|
77
|
-
failCount?: number;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/** Rectification state tracking per story execution */
|
|
81
|
-
export interface RectificationState {
|
|
82
|
-
/** Current attempt number (0 = initial run, 1+ = retries) */
|
|
83
|
-
attempt: number;
|
|
84
|
-
/** Number of test failures on initial run */
|
|
85
|
-
initialFailures: number;
|
|
86
|
-
/** Number of test failures on current run */
|
|
87
|
-
currentFailures: number;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** Verification gate options */
|
|
91
|
-
export interface VerificationGateOptions {
|
|
92
|
-
/** Working directory */
|
|
93
|
-
workdir: string;
|
|
94
|
-
/** Test command to execute */
|
|
95
|
-
command: string;
|
|
96
|
-
/** Timeout in seconds */
|
|
97
|
-
timeoutSeconds: number;
|
|
98
|
-
/** Expected files (for asset verification) */
|
|
99
|
-
expectedFiles?: string[];
|
|
100
|
-
/** Quality config for open handle / force exit behavior */
|
|
101
|
-
forceExit?: boolean;
|
|
102
|
-
detectOpenHandles?: boolean;
|
|
103
|
-
detectOpenHandlesRetries?: number;
|
|
104
|
-
/** How many times this story has timed out (tracks across retries) */
|
|
105
|
-
timeoutRetryCount?: number;
|
|
106
|
-
/** Process management config */
|
|
107
|
-
gracePeriodMs?: number;
|
|
108
|
-
drainTimeoutMs?: number;
|
|
109
|
-
shell?: string;
|
|
110
|
-
stripEnvVars?: string[];
|
|
111
|
-
/** Whether to accept story as passed on timeout (BUG-026) */
|
|
112
|
-
acceptOnTimeout?: boolean;
|
|
113
|
-
/** Scoped test paths (for scoped verification) */
|
|
114
|
-
scopedTestPaths?: string[];
|
|
115
|
-
/** Scoped test command template with {{files}} placeholder — overrides buildSmartTestCommand heuristic */
|
|
116
|
-
testScopedTemplate?: string;
|
|
117
|
-
}
|
package/src/version.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Version and build info for nax.
|
|
3
|
-
*
|
|
4
|
-
* GIT_COMMIT is injected at build time via --define in the bun build script.
|
|
5
|
-
* When running from source (bin/nax.ts), falls back to runtime git rev-parse.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import pkg from "../package.json";
|
|
9
|
-
|
|
10
|
-
declare const GIT_COMMIT: string;
|
|
11
|
-
|
|
12
|
-
export const NAX_VERSION: string = pkg.version;
|
|
13
|
-
|
|
14
|
-
/** Short git commit hash — injected at build time, or resolved at runtime from git. */
|
|
15
|
-
export const NAX_COMMIT: string = (() => {
|
|
16
|
-
// Build-time injection (bun build --define GIT_COMMIT=...)
|
|
17
|
-
// Guard: must be a non-empty string that looks like a real commit hash
|
|
18
|
-
try {
|
|
19
|
-
if (typeof GIT_COMMIT === "string" && /^[0-9a-f]{6,10}$/.test(GIT_COMMIT)) return GIT_COMMIT;
|
|
20
|
-
} catch {
|
|
21
|
-
// not injected — fall through to runtime resolution
|
|
22
|
-
}
|
|
23
|
-
// Runtime fallback: resolve from the source file's git repo (Bun-native)
|
|
24
|
-
try {
|
|
25
|
-
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|
|
26
|
-
cwd: import.meta.dir,
|
|
27
|
-
stderr: "ignore",
|
|
28
|
-
});
|
|
29
|
-
if (result.exitCode === 0) {
|
|
30
|
-
const hash = result.stdout.toString().trim();
|
|
31
|
-
if (/^[0-9a-f]{6,10}$/.test(hash)) return hash;
|
|
32
|
-
}
|
|
33
|
-
} catch {
|
|
34
|
-
// git not available
|
|
35
|
-
}
|
|
36
|
-
return "dev";
|
|
37
|
-
})();
|
|
38
|
-
|
|
39
|
-
/** Human-readable build info string — omits commit when unavailable. */
|
|
40
|
-
export const NAX_BUILD_INFO: string = NAX_COMMIT === "dev" ? `v${NAX_VERSION}` : `v${NAX_VERSION} (${NAX_COMMIT})`;
|
package/src/worktree/index.ts
DELETED
package/src/worktree/manager.ts
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import { existsSync, symlinkSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { getSafeLogger } from "../logger";
|
|
4
|
-
import { validateStoryId } from "../prd/validate";
|
|
5
|
-
import { errorMessage } from "../utils/errors";
|
|
6
|
-
import type { WorktreeInfo } from "./types";
|
|
7
|
-
|
|
8
|
-
export class WorktreeManager {
|
|
9
|
-
/**
|
|
10
|
-
* Creates a git worktree at .nax-wt/<storyId>/ with branch nax/<storyId>
|
|
11
|
-
* and symlinks node_modules and .env from project root
|
|
12
|
-
*/
|
|
13
|
-
async create(projectRoot: string, storyId: string): Promise<void> {
|
|
14
|
-
validateStoryId(storyId);
|
|
15
|
-
|
|
16
|
-
const worktreePath = join(projectRoot, ".nax-wt", storyId);
|
|
17
|
-
const branchName = `nax/${storyId}`;
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
// Create worktree with new branch
|
|
21
|
-
const proc = Bun.spawn(["git", "worktree", "add", worktreePath, "-b", branchName], {
|
|
22
|
-
cwd: projectRoot,
|
|
23
|
-
stdout: "pipe",
|
|
24
|
-
stderr: "pipe",
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
const exitCode = await proc.exited;
|
|
28
|
-
if (exitCode !== 0) {
|
|
29
|
-
const stderr = await new Response(proc.stderr).text();
|
|
30
|
-
throw new Error(`Failed to create worktree: ${stderr || "unknown error"}`);
|
|
31
|
-
}
|
|
32
|
-
} catch (error) {
|
|
33
|
-
if (error instanceof Error) {
|
|
34
|
-
// Enhance error messages for common scenarios
|
|
35
|
-
if (error.message.includes("not a git repository")) {
|
|
36
|
-
throw new Error(`Not a git repository: ${projectRoot}`);
|
|
37
|
-
}
|
|
38
|
-
if (error.message.includes("already exists")) {
|
|
39
|
-
throw new Error(`Worktree for story ${storyId} already exists at ${worktreePath}`);
|
|
40
|
-
}
|
|
41
|
-
throw error;
|
|
42
|
-
}
|
|
43
|
-
throw new Error(`Failed to create worktree: ${String(error)}`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Symlink node_modules if it exists
|
|
47
|
-
const nodeModulesSource = join(projectRoot, "node_modules");
|
|
48
|
-
if (existsSync(nodeModulesSource)) {
|
|
49
|
-
const nodeModulesTarget = join(worktreePath, "node_modules");
|
|
50
|
-
try {
|
|
51
|
-
symlinkSync(nodeModulesSource, nodeModulesTarget, "dir");
|
|
52
|
-
} catch (error) {
|
|
53
|
-
// Clean up worktree if symlinking fails
|
|
54
|
-
await this.remove(projectRoot, storyId);
|
|
55
|
-
throw new Error(`Failed to symlink node_modules: ${errorMessage(error)}`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Symlink .env if it exists
|
|
60
|
-
const envSource = join(projectRoot, ".env");
|
|
61
|
-
if (existsSync(envSource)) {
|
|
62
|
-
const envTarget = join(worktreePath, ".env");
|
|
63
|
-
try {
|
|
64
|
-
symlinkSync(envSource, envTarget, "file");
|
|
65
|
-
} catch (error) {
|
|
66
|
-
// Clean up worktree if symlinking fails
|
|
67
|
-
await this.remove(projectRoot, storyId);
|
|
68
|
-
throw new Error(`Failed to symlink .env: ${errorMessage(error)}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Removes worktree and deletes branch
|
|
75
|
-
*/
|
|
76
|
-
async remove(projectRoot: string, storyId: string): Promise<void> {
|
|
77
|
-
validateStoryId(storyId);
|
|
78
|
-
|
|
79
|
-
const worktreePath = join(projectRoot, ".nax-wt", storyId);
|
|
80
|
-
const branchName = `nax/${storyId}`;
|
|
81
|
-
|
|
82
|
-
// Remove worktree
|
|
83
|
-
try {
|
|
84
|
-
const proc = Bun.spawn(["git", "worktree", "remove", worktreePath, "--force"], {
|
|
85
|
-
cwd: projectRoot,
|
|
86
|
-
stdout: "pipe",
|
|
87
|
-
stderr: "pipe",
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
const exitCode = await proc.exited;
|
|
91
|
-
if (exitCode !== 0) {
|
|
92
|
-
const stderr = await new Response(proc.stderr).text();
|
|
93
|
-
if (
|
|
94
|
-
stderr.includes("not found") ||
|
|
95
|
-
stderr.includes("does not exist") ||
|
|
96
|
-
stderr.includes("no such worktree") ||
|
|
97
|
-
stderr.includes("is not a working tree")
|
|
98
|
-
) {
|
|
99
|
-
throw new Error(`Worktree not found: ${worktreePath}`);
|
|
100
|
-
}
|
|
101
|
-
throw new Error(`Failed to remove worktree: ${stderr || "unknown error"}`);
|
|
102
|
-
}
|
|
103
|
-
} catch (error) {
|
|
104
|
-
if (error instanceof Error) {
|
|
105
|
-
throw error;
|
|
106
|
-
}
|
|
107
|
-
throw new Error(`Failed to remove worktree: ${String(error)}`);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Delete branch
|
|
111
|
-
try {
|
|
112
|
-
const proc = Bun.spawn(["git", "branch", "-D", branchName], {
|
|
113
|
-
cwd: projectRoot,
|
|
114
|
-
stdout: "pipe",
|
|
115
|
-
stderr: "pipe",
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
const exitCode = await proc.exited;
|
|
119
|
-
if (exitCode !== 0) {
|
|
120
|
-
const stderr = await new Response(proc.stderr).text();
|
|
121
|
-
// Don't fail if branch doesn't exist
|
|
122
|
-
if (!stderr.includes("not found")) {
|
|
123
|
-
const logger = getSafeLogger();
|
|
124
|
-
logger?.warn("worktree", `Failed to delete branch ${branchName}`, { stderr });
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
} catch (error) {
|
|
128
|
-
// Log warning but don't fail - worktree is already removed
|
|
129
|
-
const logger = getSafeLogger();
|
|
130
|
-
logger?.warn("worktree", `Failed to delete branch ${branchName}`, {
|
|
131
|
-
error: errorMessage(error),
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Returns active worktrees
|
|
138
|
-
*/
|
|
139
|
-
async list(projectRoot: string): Promise<WorktreeInfo[]> {
|
|
140
|
-
try {
|
|
141
|
-
const proc = Bun.spawn(["git", "worktree", "list", "--porcelain"], {
|
|
142
|
-
cwd: projectRoot,
|
|
143
|
-
stdout: "pipe",
|
|
144
|
-
stderr: "pipe",
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
const exitCode = await proc.exited;
|
|
148
|
-
if (exitCode !== 0) {
|
|
149
|
-
const stderr = await new Response(proc.stderr).text();
|
|
150
|
-
throw new Error(`Failed to list worktrees: ${stderr || "unknown error"}`);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const stdout = await new Response(proc.stdout).text();
|
|
154
|
-
return this.parseWorktreeList(stdout);
|
|
155
|
-
} catch (error) {
|
|
156
|
-
if (error instanceof Error) {
|
|
157
|
-
throw error;
|
|
158
|
-
}
|
|
159
|
-
throw new Error(`Failed to list worktrees: ${String(error)}`);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Parses git worktree list --porcelain output
|
|
165
|
-
*/
|
|
166
|
-
private parseWorktreeList(output: string): WorktreeInfo[] {
|
|
167
|
-
const worktrees: WorktreeInfo[] = [];
|
|
168
|
-
const lines = output.trim().split("\n");
|
|
169
|
-
|
|
170
|
-
let currentWorktree: Partial<WorktreeInfo> = {};
|
|
171
|
-
|
|
172
|
-
for (const line of lines) {
|
|
173
|
-
if (line.startsWith("worktree ")) {
|
|
174
|
-
currentWorktree.path = line.substring("worktree ".length);
|
|
175
|
-
} else if (line.startsWith("branch ")) {
|
|
176
|
-
currentWorktree.branch = line.substring("branch ".length).replace("refs/heads/", "");
|
|
177
|
-
} else if (line === "") {
|
|
178
|
-
// Empty line indicates end of worktree entry
|
|
179
|
-
if (currentWorktree.path && currentWorktree.branch) {
|
|
180
|
-
worktrees.push(currentWorktree as WorktreeInfo);
|
|
181
|
-
}
|
|
182
|
-
currentWorktree = {};
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Handle last entry if no trailing newline
|
|
187
|
-
if (currentWorktree.path && currentWorktree.branch) {
|
|
188
|
-
worktrees.push(currentWorktree as WorktreeInfo);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return worktrees;
|
|
192
|
-
}
|
|
193
|
-
}
|
package/src/worktree/merge.ts
DELETED
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import { getSafeLogger } from "../logger";
|
|
2
|
-
import { errorMessage } from "../utils/errors";
|
|
3
|
-
import type { WorktreeManager } from "./manager";
|
|
4
|
-
|
|
5
|
-
export interface MergeResult {
|
|
6
|
-
success: boolean;
|
|
7
|
-
storyId: string;
|
|
8
|
-
conflictFiles?: string[];
|
|
9
|
-
retryCount?: number;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface StoryDependencies {
|
|
13
|
-
[storyId: string]: string[];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export class MergeEngine {
|
|
17
|
-
constructor(private worktreeManager: WorktreeManager) {}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Merges branch nax/<storyId> into current branch with --no-ff
|
|
21
|
-
* Returns { success: true } on clean merge
|
|
22
|
-
* Returns { success: false, conflictFiles: [...] } on conflict
|
|
23
|
-
* Cleans up worktree after successful merge
|
|
24
|
-
*/
|
|
25
|
-
async merge(projectRoot: string, storyId: string): Promise<Omit<MergeResult, "storyId">> {
|
|
26
|
-
const branchName = `nax/${storyId}`;
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
// Perform merge with --no-ff
|
|
30
|
-
const mergeProc = Bun.spawn(["git", "merge", "--no-ff", branchName, "-m", `Merge branch '${branchName}'`], {
|
|
31
|
-
cwd: projectRoot,
|
|
32
|
-
stdout: "pipe",
|
|
33
|
-
stderr: "pipe",
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const exitCode = await mergeProc.exited;
|
|
37
|
-
const stderr = await new Response(mergeProc.stderr).text();
|
|
38
|
-
const stdout = await new Response(mergeProc.stdout).text();
|
|
39
|
-
|
|
40
|
-
if (exitCode === 0) {
|
|
41
|
-
// Clean merge - cleanup worktree
|
|
42
|
-
try {
|
|
43
|
-
await this.worktreeManager.remove(projectRoot, storyId);
|
|
44
|
-
} catch (error) {
|
|
45
|
-
// Log warning but don't fail the merge
|
|
46
|
-
const logger = getSafeLogger();
|
|
47
|
-
logger?.warn("worktree", `Failed to cleanup worktree for ${storyId}`, {
|
|
48
|
-
error: errorMessage(error),
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return { success: true };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Merge failed - check for conflicts
|
|
56
|
-
const output = `${stdout}\n${stderr}`;
|
|
57
|
-
if (output.includes("CONFLICT") || output.includes("conflict") || output.includes("Automatic merge failed")) {
|
|
58
|
-
// Extract conflict files
|
|
59
|
-
const conflictFiles = await this.getConflictFiles(projectRoot);
|
|
60
|
-
|
|
61
|
-
// Abort the merge
|
|
62
|
-
await this.abortMerge(projectRoot);
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
success: false,
|
|
66
|
-
conflictFiles,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Other error
|
|
71
|
-
throw new Error(`Merge failed: ${stderr || stdout || "unknown error"}`);
|
|
72
|
-
} catch (error) {
|
|
73
|
-
if (error instanceof Error) {
|
|
74
|
-
throw error;
|
|
75
|
-
}
|
|
76
|
-
throw new Error(`Failed to merge branch ${branchName}: ${String(error)}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Merges stories in topological order based on dependencies
|
|
82
|
-
* On conflict: retries once after rebasing worktree on updated base
|
|
83
|
-
* On 2nd conflict: marks story as failed, continues with remaining stories
|
|
84
|
-
*/
|
|
85
|
-
async mergeAll(projectRoot: string, storyIds: string[], dependencies: StoryDependencies): Promise<MergeResult[]> {
|
|
86
|
-
// Sort stories in topological order
|
|
87
|
-
const orderedStories = this.topologicalSort(storyIds, dependencies);
|
|
88
|
-
const results: MergeResult[] = [];
|
|
89
|
-
const failedStories = new Set<string>();
|
|
90
|
-
|
|
91
|
-
for (const storyId of orderedStories) {
|
|
92
|
-
// Check if any dependencies failed
|
|
93
|
-
const deps = dependencies[storyId] || [];
|
|
94
|
-
const hasFailedDeps = deps.some((dep) => failedStories.has(dep));
|
|
95
|
-
|
|
96
|
-
if (hasFailedDeps) {
|
|
97
|
-
results.push({
|
|
98
|
-
success: false,
|
|
99
|
-
storyId,
|
|
100
|
-
conflictFiles: [],
|
|
101
|
-
});
|
|
102
|
-
failedStories.add(storyId);
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Try to merge
|
|
107
|
-
let result = await this.merge(projectRoot, storyId);
|
|
108
|
-
|
|
109
|
-
// If conflict, retry once after rebasing
|
|
110
|
-
if (!result.success && result.conflictFiles) {
|
|
111
|
-
try {
|
|
112
|
-
// Rebase worktree on updated base
|
|
113
|
-
await this.rebaseWorktree(projectRoot, storyId);
|
|
114
|
-
|
|
115
|
-
// Retry merge
|
|
116
|
-
result = await this.merge(projectRoot, storyId);
|
|
117
|
-
|
|
118
|
-
// If still fails, mark as failed
|
|
119
|
-
if (!result.success) {
|
|
120
|
-
results.push({
|
|
121
|
-
success: false,
|
|
122
|
-
storyId,
|
|
123
|
-
conflictFiles: result.conflictFiles,
|
|
124
|
-
retryCount: 1,
|
|
125
|
-
});
|
|
126
|
-
failedStories.add(storyId);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Success after retry
|
|
131
|
-
results.push({
|
|
132
|
-
success: true,
|
|
133
|
-
storyId,
|
|
134
|
-
retryCount: 1,
|
|
135
|
-
});
|
|
136
|
-
} catch (error) {
|
|
137
|
-
// Rebase failed, mark as failed
|
|
138
|
-
results.push({
|
|
139
|
-
success: false,
|
|
140
|
-
storyId,
|
|
141
|
-
conflictFiles: result.conflictFiles,
|
|
142
|
-
retryCount: 1,
|
|
143
|
-
});
|
|
144
|
-
failedStories.add(storyId);
|
|
145
|
-
}
|
|
146
|
-
} else if (result.success) {
|
|
147
|
-
// First attempt succeeded
|
|
148
|
-
results.push({
|
|
149
|
-
success: true,
|
|
150
|
-
storyId,
|
|
151
|
-
retryCount: 0,
|
|
152
|
-
});
|
|
153
|
-
} else {
|
|
154
|
-
// Failed without conflicts (shouldn't happen normally)
|
|
155
|
-
results.push({
|
|
156
|
-
success: false,
|
|
157
|
-
storyId,
|
|
158
|
-
retryCount: 0,
|
|
159
|
-
});
|
|
160
|
-
failedStories.add(storyId);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return results;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Topological sort of stories based on dependencies
|
|
169
|
-
* Returns stories in order where dependencies come before dependents
|
|
170
|
-
*/
|
|
171
|
-
private topologicalSort(storyIds: string[], dependencies: StoryDependencies): string[] {
|
|
172
|
-
const visited = new Set<string>();
|
|
173
|
-
const sorted: string[] = [];
|
|
174
|
-
const visiting = new Set<string>();
|
|
175
|
-
|
|
176
|
-
const visit = (storyId: string) => {
|
|
177
|
-
if (visited.has(storyId)) {
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (visiting.has(storyId)) {
|
|
182
|
-
throw new Error(`Circular dependency detected involving ${storyId}`);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
visiting.add(storyId);
|
|
186
|
-
|
|
187
|
-
// Visit dependencies first
|
|
188
|
-
const deps = dependencies[storyId] || [];
|
|
189
|
-
for (const dep of deps) {
|
|
190
|
-
if (storyIds.includes(dep)) {
|
|
191
|
-
visit(dep);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
visiting.delete(storyId);
|
|
196
|
-
visited.add(storyId);
|
|
197
|
-
sorted.push(storyId);
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
for (const storyId of storyIds) {
|
|
201
|
-
visit(storyId);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return sorted;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Rebases worktree on current base branch
|
|
209
|
-
*/
|
|
210
|
-
private async rebaseWorktree(projectRoot: string, storyId: string): Promise<void> {
|
|
211
|
-
const worktreePath = `${projectRoot}/.nax-wt/${storyId}`;
|
|
212
|
-
|
|
213
|
-
try {
|
|
214
|
-
// Get current branch name from main repo
|
|
215
|
-
const currentBranchProc = Bun.spawn(["git", "rev-parse", "--abbrev-ref", "HEAD"], {
|
|
216
|
-
cwd: projectRoot,
|
|
217
|
-
stdout: "pipe",
|
|
218
|
-
stderr: "pipe",
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
const exitCode = await currentBranchProc.exited;
|
|
222
|
-
if (exitCode !== 0) {
|
|
223
|
-
throw new Error("Failed to get current branch");
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
const currentBranch = (await new Response(currentBranchProc.stdout).text()).trim();
|
|
227
|
-
|
|
228
|
-
// Rebase worktree branch onto current branch
|
|
229
|
-
const rebaseProc = Bun.spawn(["git", "rebase", currentBranch], {
|
|
230
|
-
cwd: worktreePath,
|
|
231
|
-
stdout: "pipe",
|
|
232
|
-
stderr: "pipe",
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
const rebaseExitCode = await rebaseProc.exited;
|
|
236
|
-
if (rebaseExitCode !== 0) {
|
|
237
|
-
const stderr = await new Response(rebaseProc.stderr).text();
|
|
238
|
-
|
|
239
|
-
// Abort rebase on failure
|
|
240
|
-
await Bun.spawn(["git", "rebase", "--abort"], {
|
|
241
|
-
cwd: worktreePath,
|
|
242
|
-
stdout: "pipe",
|
|
243
|
-
stderr: "pipe",
|
|
244
|
-
}).exited;
|
|
245
|
-
|
|
246
|
-
throw new Error(`Rebase failed: ${stderr || "unknown error"}`);
|
|
247
|
-
}
|
|
248
|
-
} catch (error) {
|
|
249
|
-
if (error instanceof Error) {
|
|
250
|
-
throw error;
|
|
251
|
-
}
|
|
252
|
-
throw new Error(`Failed to rebase worktree ${storyId}: ${String(error)}`);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Gets list of conflicted files
|
|
258
|
-
*/
|
|
259
|
-
private async getConflictFiles(projectRoot: string): Promise<string[]> {
|
|
260
|
-
try {
|
|
261
|
-
const proc = Bun.spawn(["git", "diff", "--name-only", "--diff-filter=U"], {
|
|
262
|
-
cwd: projectRoot,
|
|
263
|
-
stdout: "pipe",
|
|
264
|
-
stderr: "pipe",
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
const exitCode = await proc.exited;
|
|
268
|
-
if (exitCode !== 0) {
|
|
269
|
-
return [];
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const stdout = await new Response(proc.stdout).text();
|
|
273
|
-
return stdout
|
|
274
|
-
.trim()
|
|
275
|
-
.split("\n")
|
|
276
|
-
.filter((line) => line.length > 0);
|
|
277
|
-
} catch {
|
|
278
|
-
return [];
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Aborts an in-progress merge
|
|
284
|
-
*/
|
|
285
|
-
private async abortMerge(projectRoot: string): Promise<void> {
|
|
286
|
-
try {
|
|
287
|
-
const proc = Bun.spawn(["git", "merge", "--abort"], {
|
|
288
|
-
cwd: projectRoot,
|
|
289
|
-
stdout: "pipe",
|
|
290
|
-
stderr: "pipe",
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
await proc.exited;
|
|
294
|
-
} catch (error) {
|
|
295
|
-
// Log warning but don't throw - merge might already be aborted
|
|
296
|
-
const logger = getSafeLogger();
|
|
297
|
-
logger?.warn("worktree", "Failed to abort merge", {
|
|
298
|
-
error: errorMessage(error),
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
package/src/worktree/types.ts
DELETED