ai-sdlc 0.2.0-alpha.6 → 0.2.0-alpha.60
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/README.md +53 -1058
- package/dist/agents/implementation.d.ts +36 -1
- package/dist/agents/implementation.d.ts.map +1 -1
- package/dist/agents/implementation.js +259 -30
- package/dist/agents/implementation.js.map +1 -1
- package/dist/agents/index.d.ts +2 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +2 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/orchestrator.d.ts +61 -0
- package/dist/agents/orchestrator.d.ts.map +1 -0
- package/dist/agents/orchestrator.js +443 -0
- package/dist/agents/orchestrator.js.map +1 -0
- package/dist/agents/planning.d.ts +1 -1
- package/dist/agents/planning.d.ts.map +1 -1
- package/dist/agents/planning.js +55 -4
- package/dist/agents/planning.js.map +1 -1
- package/dist/agents/refinement.d.ts.map +1 -1
- package/dist/agents/refinement.js +22 -3
- package/dist/agents/refinement.js.map +1 -1
- package/dist/agents/research.d.ts +85 -1
- package/dist/agents/research.d.ts.map +1 -1
- package/dist/agents/research.js +506 -16
- package/dist/agents/research.js.map +1 -1
- package/dist/agents/review.d.ts +103 -2
- package/dist/agents/review.d.ts.map +1 -1
- package/dist/agents/review.js +777 -93
- package/dist/agents/review.js.map +1 -1
- package/dist/agents/rework.d.ts.map +1 -1
- package/dist/agents/rework.js +25 -4
- package/dist/agents/rework.js.map +1 -1
- package/dist/agents/single-task.d.ts +41 -0
- package/dist/agents/single-task.d.ts.map +1 -0
- package/dist/agents/single-task.js +357 -0
- package/dist/agents/single-task.js.map +1 -0
- package/dist/agents/state-assessor.d.ts +3 -3
- package/dist/agents/state-assessor.d.ts.map +1 -1
- package/dist/agents/state-assessor.js +6 -6
- package/dist/agents/state-assessor.js.map +1 -1
- package/dist/agents/test-pattern-detector.d.ts +49 -0
- package/dist/agents/test-pattern-detector.d.ts.map +1 -0
- package/dist/agents/test-pattern-detector.js +273 -0
- package/dist/agents/test-pattern-detector.js.map +1 -0
- package/dist/agents/verification.d.ts +11 -0
- package/dist/agents/verification.d.ts.map +1 -1
- package/dist/agents/verification.js +99 -12
- package/dist/agents/verification.js.map +1 -1
- package/dist/cli/commands/migrate.js +1 -1
- package/dist/cli/commands/migrate.js.map +1 -1
- package/dist/cli/commands.d.ts +66 -3
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +1548 -198
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/daemon.d.ts.map +1 -1
- package/dist/cli/daemon.js +25 -3
- package/dist/cli/daemon.js.map +1 -1
- package/dist/cli/runner.d.ts.map +1 -1
- package/dist/cli/runner.js +35 -12
- package/dist/cli/runner.js.map +1 -1
- package/dist/core/auth.d.ts +43 -0
- package/dist/core/auth.d.ts.map +1 -1
- package/dist/core/auth.js +105 -1
- package/dist/core/auth.js.map +1 -1
- package/dist/core/client.d.ts +25 -1
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +247 -7
- package/dist/core/client.js.map +1 -1
- package/dist/core/config.d.ts +32 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +146 -3
- package/dist/core/config.js.map +1 -1
- package/dist/core/conflict-detector.d.ts +108 -0
- package/dist/core/conflict-detector.d.ts.map +1 -0
- package/dist/core/conflict-detector.js +413 -0
- package/dist/core/conflict-detector.js.map +1 -0
- package/dist/core/git-utils.d.ts +28 -0
- package/dist/core/git-utils.d.ts.map +1 -0
- package/dist/core/git-utils.js +146 -0
- package/dist/core/git-utils.js.map +1 -0
- package/dist/core/index.d.ts +19 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +19 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/kanban.d.ts +1 -1
- package/dist/core/kanban.d.ts.map +1 -1
- package/dist/core/kanban.js +3 -3
- package/dist/core/kanban.js.map +1 -1
- package/dist/core/llm-utils.d.ts +103 -0
- package/dist/core/llm-utils.d.ts.map +1 -0
- package/dist/core/llm-utils.js +368 -0
- package/dist/core/llm-utils.js.map +1 -0
- package/dist/core/logger.d.ts +92 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +221 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/process-manager.d.ts +15 -0
- package/dist/core/process-manager.d.ts.map +1 -0
- package/dist/core/process-manager.js +132 -0
- package/dist/core/process-manager.js.map +1 -0
- package/dist/core/story-logger.d.ts +102 -0
- package/dist/core/story-logger.d.ts.map +1 -0
- package/dist/core/story-logger.js +265 -0
- package/dist/core/story-logger.js.map +1 -0
- package/dist/core/story.d.ts +113 -20
- package/dist/core/story.d.ts.map +1 -1
- package/dist/core/story.js +328 -40
- package/dist/core/story.js.map +1 -1
- package/dist/core/task-parser.d.ts +59 -0
- package/dist/core/task-parser.d.ts.map +1 -0
- package/dist/core/task-parser.js +235 -0
- package/dist/core/task-parser.js.map +1 -0
- package/dist/core/task-progress.d.ts +92 -0
- package/dist/core/task-progress.d.ts.map +1 -0
- package/dist/core/task-progress.js +280 -0
- package/dist/core/task-progress.js.map +1 -0
- package/dist/core/workflow-state.d.ts +45 -6
- package/dist/core/workflow-state.d.ts.map +1 -1
- package/dist/core/workflow-state.js +201 -12
- package/dist/core/workflow-state.js.map +1 -1
- package/dist/core/worktree.d.ts +186 -0
- package/dist/core/worktree.d.ts.map +1 -0
- package/dist/core/worktree.js +554 -0
- package/dist/core/worktree.js.map +1 -0
- package/dist/index.js +145 -5
- package/dist/index.js.map +1 -1
- package/dist/services/error-classifier.d.ts +119 -0
- package/dist/services/error-classifier.d.ts.map +1 -0
- package/dist/services/error-classifier.js +182 -0
- package/dist/services/error-classifier.js.map +1 -0
- package/dist/types/index.d.ts +381 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/package.json +5 -2
- package/templates/story.md +5 -0
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
import { spawnSync } from 'child_process';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { isCleanWorkingDirectory } from './git-utils.js';
|
|
5
|
+
/** Default patterns to exclude from working directory cleanliness checks */
|
|
6
|
+
const DEFAULT_EXCLUDE_PATTERNS = ['.ai-sdlc/**'];
|
|
7
|
+
/**
|
|
8
|
+
* Error messages used by the worktree service
|
|
9
|
+
*/
|
|
10
|
+
const ERROR_MESSAGES = {
|
|
11
|
+
UNCOMMITTED_CHANGES: 'Uncommitted changes exist. Commit or stash before using worktrees.',
|
|
12
|
+
PATH_EXISTS: 'Worktree path already exists',
|
|
13
|
+
CREATE_FAILED: 'Failed to create worktree',
|
|
14
|
+
NO_BASE_BRANCH: 'Could not detect base branch (main or master)',
|
|
15
|
+
NOT_GIT_REPO: 'Not a git repository',
|
|
16
|
+
BRANCH_EXISTS: 'A branch with this name already exists',
|
|
17
|
+
WORKTREE_NOT_FOUND: 'Worktree not found',
|
|
18
|
+
WORKTREE_HAS_CHANGES: 'Worktree has uncommitted changes. Use --force to remove.',
|
|
19
|
+
LIST_FAILED: 'Failed to list worktrees',
|
|
20
|
+
REMOVE_FAILED: 'Failed to remove worktree',
|
|
21
|
+
INSTALL_FAILED: 'Failed to install dependencies',
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Lock file to package manager mapping
|
|
25
|
+
*/
|
|
26
|
+
const LOCK_FILE_TO_PM = {
|
|
27
|
+
'package-lock.json': 'npm',
|
|
28
|
+
'yarn.lock': 'yarn',
|
|
29
|
+
'pnpm-lock.yaml': 'pnpm',
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Service for managing git worktrees for isolated story execution
|
|
33
|
+
*/
|
|
34
|
+
export class GitWorktreeService {
|
|
35
|
+
projectRoot;
|
|
36
|
+
worktreeBasePath;
|
|
37
|
+
constructor(projectRoot, worktreeBasePath) {
|
|
38
|
+
this.projectRoot = projectRoot;
|
|
39
|
+
this.worktreeBasePath = worktreeBasePath;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Generate the worktree path for a story
|
|
43
|
+
* Format: {worktreeBasePath}/{storyId}-{slug}
|
|
44
|
+
*/
|
|
45
|
+
getWorktreePath(storyId, slug) {
|
|
46
|
+
return path.join(this.worktreeBasePath, `${storyId}-${slug}`);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Generate the branch name for a worktree
|
|
50
|
+
* Format: ai-sdlc/{storyId}-{slug}
|
|
51
|
+
*/
|
|
52
|
+
getBranchName(storyId, slug) {
|
|
53
|
+
return `ai-sdlc/${storyId}-${slug}`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Detect the base branch (main or master) for branching
|
|
57
|
+
* @returns The detected base branch name
|
|
58
|
+
* @throws Error if neither main nor master exists
|
|
59
|
+
*/
|
|
60
|
+
detectBaseBranch() {
|
|
61
|
+
// Check for 'main' first
|
|
62
|
+
const mainResult = spawnSync('git', ['rev-parse', '--verify', 'main'], {
|
|
63
|
+
cwd: this.projectRoot,
|
|
64
|
+
encoding: 'utf-8',
|
|
65
|
+
shell: false,
|
|
66
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
67
|
+
});
|
|
68
|
+
if (mainResult.status === 0) {
|
|
69
|
+
return 'main';
|
|
70
|
+
}
|
|
71
|
+
// Check for 'master' as fallback
|
|
72
|
+
const masterResult = spawnSync('git', ['rev-parse', '--verify', 'master'], {
|
|
73
|
+
cwd: this.projectRoot,
|
|
74
|
+
encoding: 'utf-8',
|
|
75
|
+
shell: false,
|
|
76
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
77
|
+
});
|
|
78
|
+
if (masterResult.status === 0) {
|
|
79
|
+
return 'master';
|
|
80
|
+
}
|
|
81
|
+
throw new Error(ERROR_MESSAGES.NO_BASE_BRANCH);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Validate that a worktree can be created
|
|
85
|
+
* Checks for uncommitted changes in the working directory
|
|
86
|
+
* Note: Changes in .ai-sdlc/ directory are excluded since they're expected
|
|
87
|
+
* during normal workflow (story file updates, etc.)
|
|
88
|
+
*/
|
|
89
|
+
validateCanCreateWorktree() {
|
|
90
|
+
const cleanCheckOptions = {
|
|
91
|
+
excludePatterns: DEFAULT_EXCLUDE_PATTERNS,
|
|
92
|
+
};
|
|
93
|
+
if (!isCleanWorkingDirectory(this.projectRoot, cleanCheckOptions)) {
|
|
94
|
+
return {
|
|
95
|
+
valid: false,
|
|
96
|
+
error: ERROR_MESSAGES.UNCOMMITTED_CHANGES,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return { valid: true };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Check if a worktree already exists at the given path
|
|
103
|
+
*/
|
|
104
|
+
exists(worktreePath) {
|
|
105
|
+
return existsSync(worktreePath);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Create a new git worktree for isolated story execution
|
|
109
|
+
* @param options - Worktree creation options
|
|
110
|
+
* @returns The path to the created worktree
|
|
111
|
+
* @throws Error if worktree creation fails
|
|
112
|
+
*/
|
|
113
|
+
create(options) {
|
|
114
|
+
const worktreePath = this.getWorktreePath(options.storyId, options.slug);
|
|
115
|
+
const branchName = this.getBranchName(options.storyId, options.slug);
|
|
116
|
+
const baseBranch = options.baseBranch || this.detectBaseBranch();
|
|
117
|
+
// Check if worktree path already exists
|
|
118
|
+
if (this.exists(worktreePath)) {
|
|
119
|
+
throw new Error(`${ERROR_MESSAGES.PATH_EXISTS}: ${worktreePath}`);
|
|
120
|
+
}
|
|
121
|
+
// Execute git worktree add command
|
|
122
|
+
const result = spawnSync('git', ['worktree', 'add', '-b', branchName, worktreePath, baseBranch], {
|
|
123
|
+
cwd: this.projectRoot,
|
|
124
|
+
encoding: 'utf-8',
|
|
125
|
+
shell: false,
|
|
126
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
127
|
+
});
|
|
128
|
+
// Handle errors
|
|
129
|
+
if (result.status !== 0) {
|
|
130
|
+
const stderr = result.stderr?.toString() || '';
|
|
131
|
+
// Provide specific error messages for common failures
|
|
132
|
+
if (stderr.includes('not a git repository')) {
|
|
133
|
+
throw new Error(ERROR_MESSAGES.NOT_GIT_REPO);
|
|
134
|
+
}
|
|
135
|
+
if (stderr.includes('already exists')) {
|
|
136
|
+
throw new Error(`${ERROR_MESSAGES.BRANCH_EXISTS}: ${branchName}`);
|
|
137
|
+
}
|
|
138
|
+
// Generic error with stderr details
|
|
139
|
+
throw new Error(`${ERROR_MESSAGES.CREATE_FAILED}: ${stderr}`);
|
|
140
|
+
}
|
|
141
|
+
// Install dependencies in the new worktree
|
|
142
|
+
this.installDependencies(worktreePath);
|
|
143
|
+
return worktreePath;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Install npm dependencies in a worktree
|
|
147
|
+
* Detects the package manager (npm/yarn/pnpm) and runs the appropriate install command
|
|
148
|
+
* @param worktreePath - Path to the worktree
|
|
149
|
+
* @throws Error if installation fails
|
|
150
|
+
*/
|
|
151
|
+
installDependencies(worktreePath) {
|
|
152
|
+
const packageJsonPath = path.join(worktreePath, 'package.json');
|
|
153
|
+
// Skip if not a Node.js project
|
|
154
|
+
if (!existsSync(packageJsonPath)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// Detect package manager from lock file
|
|
158
|
+
let packageManager = 'npm'; // default
|
|
159
|
+
for (const [lockFile, pm] of Object.entries(LOCK_FILE_TO_PM)) {
|
|
160
|
+
if (existsSync(path.join(worktreePath, lockFile))) {
|
|
161
|
+
packageManager = pm;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Run install command
|
|
166
|
+
const result = spawnSync(packageManager, ['install'], {
|
|
167
|
+
cwd: worktreePath,
|
|
168
|
+
encoding: 'utf-8',
|
|
169
|
+
shell: false,
|
|
170
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
171
|
+
timeout: 120000, // 2 minute timeout
|
|
172
|
+
});
|
|
173
|
+
if (result.status !== 0) {
|
|
174
|
+
const stderr = result.stderr?.toString() || '';
|
|
175
|
+
throw new Error(`${ERROR_MESSAGES.INSTALL_FAILED}: ${stderr}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* List all ai-sdlc managed worktrees
|
|
180
|
+
* @returns Array of WorktreeInfo objects for worktrees in the basePath
|
|
181
|
+
*/
|
|
182
|
+
list() {
|
|
183
|
+
const result = spawnSync('git', ['worktree', 'list', '--porcelain'], {
|
|
184
|
+
cwd: this.projectRoot,
|
|
185
|
+
encoding: 'utf-8',
|
|
186
|
+
shell: false,
|
|
187
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
188
|
+
});
|
|
189
|
+
if (result.status !== 0) {
|
|
190
|
+
throw new Error(`${ERROR_MESSAGES.LIST_FAILED}: ${result.stderr}`);
|
|
191
|
+
}
|
|
192
|
+
const output = result.stdout || '';
|
|
193
|
+
const worktrees = [];
|
|
194
|
+
const blocks = output.trim().split('\n\n');
|
|
195
|
+
for (const block of blocks) {
|
|
196
|
+
if (!block.trim())
|
|
197
|
+
continue;
|
|
198
|
+
const lines = block.split('\n');
|
|
199
|
+
let worktreePath = '';
|
|
200
|
+
let branch = '';
|
|
201
|
+
for (const line of lines) {
|
|
202
|
+
if (line.startsWith('worktree ')) {
|
|
203
|
+
worktreePath = line.substring(9);
|
|
204
|
+
}
|
|
205
|
+
else if (line.startsWith('branch ')) {
|
|
206
|
+
branch = line.substring(7).replace('refs/heads/', '');
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// Filter to only ai-sdlc managed worktrees
|
|
210
|
+
if (worktreePath && worktreePath.startsWith(this.worktreeBasePath)) {
|
|
211
|
+
const storyIdMatch = branch.match(/^ai-sdlc\/(S-\d+)-/);
|
|
212
|
+
worktrees.push({
|
|
213
|
+
path: worktreePath,
|
|
214
|
+
branch,
|
|
215
|
+
storyId: storyIdMatch ? storyIdMatch[1] : undefined,
|
|
216
|
+
exists: existsSync(worktreePath),
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return worktrees;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Find a worktree by story ID
|
|
224
|
+
* @param storyId - The story ID to search for (e.g., 'S-0029')
|
|
225
|
+
* @returns The WorktreeInfo if found, undefined otherwise
|
|
226
|
+
*/
|
|
227
|
+
findByStoryId(storyId) {
|
|
228
|
+
const worktrees = this.list();
|
|
229
|
+
return worktrees.find(w => w.storyId === storyId);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get detailed status information for a worktree
|
|
233
|
+
* @param worktreeInfo - The worktree to get status for
|
|
234
|
+
* @returns Detailed status including last commit and working directory state
|
|
235
|
+
*/
|
|
236
|
+
getWorktreeStatus(worktreeInfo) {
|
|
237
|
+
const status = {
|
|
238
|
+
path: worktreeInfo.path,
|
|
239
|
+
branch: worktreeInfo.branch,
|
|
240
|
+
storyId: worktreeInfo.storyId || 'unknown',
|
|
241
|
+
exists: worktreeInfo.exists,
|
|
242
|
+
workingDirectoryStatus: 'clean',
|
|
243
|
+
modifiedFiles: [],
|
|
244
|
+
untrackedFiles: [],
|
|
245
|
+
};
|
|
246
|
+
if (!worktreeInfo.exists) {
|
|
247
|
+
return status;
|
|
248
|
+
}
|
|
249
|
+
const lastCommitResult = spawnSync('git', ['log', '-1', '--format=%H%n%s%n%ci'], {
|
|
250
|
+
cwd: worktreeInfo.path,
|
|
251
|
+
encoding: 'utf-8',
|
|
252
|
+
shell: false,
|
|
253
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
254
|
+
});
|
|
255
|
+
if (lastCommitResult.status === 0 && lastCommitResult.stdout) {
|
|
256
|
+
const [hash, message, timestamp] = lastCommitResult.stdout.trim().split('\n');
|
|
257
|
+
if (hash && message && timestamp) {
|
|
258
|
+
status.lastCommit = { hash, message, timestamp };
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const gitStatusResult = spawnSync('git', ['status', '--porcelain'], {
|
|
262
|
+
cwd: worktreeInfo.path,
|
|
263
|
+
encoding: 'utf-8',
|
|
264
|
+
shell: false,
|
|
265
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
266
|
+
});
|
|
267
|
+
if (gitStatusResult.status === 0 && gitStatusResult.stdout) {
|
|
268
|
+
const lines = gitStatusResult.stdout.split('\n').filter(l => l.length >= 3);
|
|
269
|
+
for (const line of lines) {
|
|
270
|
+
const statusCode = line.substring(0, 2);
|
|
271
|
+
const filePath = line.substring(3).trim();
|
|
272
|
+
if (statusCode === '??' || statusCode === '!!') {
|
|
273
|
+
status.untrackedFiles.push(filePath);
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
status.modifiedFiles.push(filePath);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (status.modifiedFiles.length > 0 && status.untrackedFiles.length > 0) {
|
|
280
|
+
status.workingDirectoryStatus = 'mixed';
|
|
281
|
+
}
|
|
282
|
+
else if (status.modifiedFiles.length > 0) {
|
|
283
|
+
status.workingDirectoryStatus = 'modified';
|
|
284
|
+
}
|
|
285
|
+
else if (status.untrackedFiles.length > 0) {
|
|
286
|
+
status.workingDirectoryStatus = 'untracked';
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return status;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Check if worktree has unpushed commits
|
|
293
|
+
* @param worktreePath - Path to the worktree
|
|
294
|
+
* @returns Object with hasUnpushed flag and count of unpushed commits
|
|
295
|
+
*/
|
|
296
|
+
hasUnpushedCommits(worktreePath) {
|
|
297
|
+
const result = spawnSync('git', ['rev-list', '@{u}..HEAD', '--count'], {
|
|
298
|
+
cwd: worktreePath,
|
|
299
|
+
encoding: 'utf-8',
|
|
300
|
+
shell: false,
|
|
301
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
302
|
+
});
|
|
303
|
+
// If no upstream branch exists (128) or command fails, assume no unpushed commits
|
|
304
|
+
if (result.status !== 0) {
|
|
305
|
+
return { hasUnpushed: false, count: 0 };
|
|
306
|
+
}
|
|
307
|
+
const count = parseInt(result.stdout.trim(), 10);
|
|
308
|
+
return { hasUnpushed: count > 0, count: isNaN(count) ? 0 : count };
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Check if a branch exists on the remote
|
|
312
|
+
* @param branch - Branch name to check
|
|
313
|
+
* @returns true if branch exists on remote, false otherwise
|
|
314
|
+
*/
|
|
315
|
+
branchExistsOnRemote(branch) {
|
|
316
|
+
const result = spawnSync('git', ['ls-remote', '--heads', 'origin', branch], {
|
|
317
|
+
cwd: this.projectRoot,
|
|
318
|
+
encoding: 'utf-8',
|
|
319
|
+
shell: false,
|
|
320
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
321
|
+
});
|
|
322
|
+
// If command fails or no output, branch doesn't exist
|
|
323
|
+
if (result.status !== 0 || !result.stdout) {
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
// If output is not empty, branch exists
|
|
327
|
+
return result.stdout.trim().length > 0;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Get the total number of commits in a worktree
|
|
331
|
+
* @param worktreePath - Path to the worktree
|
|
332
|
+
* @returns Number of commits, or 0 on error
|
|
333
|
+
*/
|
|
334
|
+
getCommitCount(worktreePath) {
|
|
335
|
+
const result = spawnSync('git', ['rev-list', '--count', 'HEAD'], {
|
|
336
|
+
cwd: worktreePath,
|
|
337
|
+
encoding: 'utf-8',
|
|
338
|
+
shell: false,
|
|
339
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
340
|
+
});
|
|
341
|
+
if (result.status !== 0) {
|
|
342
|
+
return 0;
|
|
343
|
+
}
|
|
344
|
+
const count = parseInt(result.stdout.trim(), 10);
|
|
345
|
+
return isNaN(count) ? 0 : count;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Delete a local branch
|
|
349
|
+
* @param branch - Branch name to delete
|
|
350
|
+
* @param force - Whether to force delete (use -D instead of -d)
|
|
351
|
+
* @throws Error if deletion fails (unless branch doesn't exist)
|
|
352
|
+
*/
|
|
353
|
+
deleteBranch(branch, force = true) {
|
|
354
|
+
const args = force ? ['branch', '-D', branch] : ['branch', '-d', branch];
|
|
355
|
+
const result = spawnSync('git', args, {
|
|
356
|
+
cwd: this.projectRoot,
|
|
357
|
+
encoding: 'utf-8',
|
|
358
|
+
shell: false,
|
|
359
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
360
|
+
});
|
|
361
|
+
if (result.status !== 0) {
|
|
362
|
+
const stderr = result.stderr?.toString() || '';
|
|
363
|
+
// Don't throw if branch doesn't exist (idempotent operation)
|
|
364
|
+
if (stderr.includes('not found')) {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
throw new Error(`Failed to delete branch ${branch}: ${stderr}`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Delete a remote branch
|
|
372
|
+
* @param branch - Branch name to delete from remote
|
|
373
|
+
* @throws Error if deletion fails (unless branch doesn't exist)
|
|
374
|
+
*/
|
|
375
|
+
deleteRemoteBranch(branch) {
|
|
376
|
+
const result = spawnSync('git', ['push', 'origin', '--delete', branch], {
|
|
377
|
+
cwd: this.projectRoot,
|
|
378
|
+
encoding: 'utf-8',
|
|
379
|
+
shell: false,
|
|
380
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
381
|
+
});
|
|
382
|
+
if (result.status !== 0) {
|
|
383
|
+
const stderr = result.stderr?.toString() || '';
|
|
384
|
+
// Don't throw if remote branch doesn't exist (idempotent operation)
|
|
385
|
+
if (stderr.includes('remote ref does not exist')) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
throw new Error(`Failed to delete remote branch ${branch}: ${stderr}`);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Remove a git worktree
|
|
393
|
+
* @param worktreePath - Absolute path to the worktree to remove
|
|
394
|
+
* @param force - Whether to force remove (ignores uncommitted changes)
|
|
395
|
+
* @throws Error if removal fails
|
|
396
|
+
*/
|
|
397
|
+
remove(worktreePath, force = false) {
|
|
398
|
+
const args = force
|
|
399
|
+
? ['worktree', 'remove', '--force', worktreePath]
|
|
400
|
+
: ['worktree', 'remove', worktreePath];
|
|
401
|
+
const result = spawnSync('git', args, {
|
|
402
|
+
cwd: this.projectRoot,
|
|
403
|
+
encoding: 'utf-8',
|
|
404
|
+
shell: false,
|
|
405
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
406
|
+
});
|
|
407
|
+
if (result.status !== 0) {
|
|
408
|
+
const stderr = result.stderr?.toString() || '';
|
|
409
|
+
if (stderr.includes('not a working tree')) {
|
|
410
|
+
throw new Error(ERROR_MESSAGES.WORKTREE_NOT_FOUND);
|
|
411
|
+
}
|
|
412
|
+
if (stderr.includes('modified or untracked files')) {
|
|
413
|
+
throw new Error(ERROR_MESSAGES.WORKTREE_HAS_CHANGES);
|
|
414
|
+
}
|
|
415
|
+
throw new Error(`${ERROR_MESSAGES.REMOVE_FAILED}: ${stderr}`);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Validate that a worktree can be resumed
|
|
420
|
+
* Checks directory exists, branch exists, and story file is accessible
|
|
421
|
+
* @param worktreePath - Path to the worktree to validate
|
|
422
|
+
* @param branchName - Expected branch name
|
|
423
|
+
* @returns Validation result with issues found
|
|
424
|
+
*/
|
|
425
|
+
validateWorktreeForResume(worktreePath, branchName) {
|
|
426
|
+
const issues = [];
|
|
427
|
+
let canResume = true;
|
|
428
|
+
let requiresRecreation = false;
|
|
429
|
+
// Check if directory exists
|
|
430
|
+
if (!existsSync(worktreePath)) {
|
|
431
|
+
issues.push('Worktree directory does not exist');
|
|
432
|
+
requiresRecreation = true;
|
|
433
|
+
canResume = false;
|
|
434
|
+
}
|
|
435
|
+
// Check if branch exists
|
|
436
|
+
const branchResult = spawnSync('git', ['rev-parse', '--verify', branchName], {
|
|
437
|
+
cwd: this.projectRoot,
|
|
438
|
+
encoding: 'utf-8',
|
|
439
|
+
shell: false,
|
|
440
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
441
|
+
});
|
|
442
|
+
if (branchResult.status !== 0) {
|
|
443
|
+
issues.push('Branch does not exist');
|
|
444
|
+
requiresRecreation = true;
|
|
445
|
+
canResume = false;
|
|
446
|
+
}
|
|
447
|
+
// Check if story file is accessible (only if directory exists)
|
|
448
|
+
if (existsSync(worktreePath)) {
|
|
449
|
+
const storyDirPath = path.join(worktreePath, '.ai-sdlc', 'stories');
|
|
450
|
+
if (!existsSync(storyDirPath)) {
|
|
451
|
+
issues.push('Story directory not accessible in worktree');
|
|
452
|
+
canResume = false;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return {
|
|
456
|
+
valid: issues.length === 0,
|
|
457
|
+
issues,
|
|
458
|
+
canResume,
|
|
459
|
+
requiresRecreation,
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Check how much a branch has diverged from the base branch
|
|
464
|
+
* @param branchName - Name of the branch to check
|
|
465
|
+
* @param baseBranch - Base branch to compare against (default: main)
|
|
466
|
+
* @returns Divergence information
|
|
467
|
+
*/
|
|
468
|
+
checkBranchDivergence(branchName, baseBranch) {
|
|
469
|
+
const base = baseBranch || this.detectBaseBranch();
|
|
470
|
+
// Get commit counts: ahead and behind
|
|
471
|
+
const result = spawnSync('git', ['rev-list', '--left-right', '--count', `${base}...${branchName}`], {
|
|
472
|
+
cwd: this.projectRoot,
|
|
473
|
+
encoding: 'utf-8',
|
|
474
|
+
shell: false,
|
|
475
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
476
|
+
});
|
|
477
|
+
if (result.status !== 0) {
|
|
478
|
+
// If command fails, assume no divergence
|
|
479
|
+
return { ahead: 0, behind: 0, diverged: false };
|
|
480
|
+
}
|
|
481
|
+
const output = result.stdout?.trim() || '0\t0';
|
|
482
|
+
const [behind, ahead] = output.split(/\s+/).map(s => parseInt(s, 10));
|
|
483
|
+
return {
|
|
484
|
+
ahead: ahead || 0,
|
|
485
|
+
behind: behind || 0,
|
|
486
|
+
diverged: (ahead || 0) > 0 || (behind || 0) > 0,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Get the last completed phase from a story
|
|
492
|
+
* @param story - The story to check
|
|
493
|
+
* @returns The last completed phase name, or null if no phases are complete
|
|
494
|
+
*/
|
|
495
|
+
export function getLastCompletedPhase(story) {
|
|
496
|
+
if (story.frontmatter.reviews_complete) {
|
|
497
|
+
return 'review';
|
|
498
|
+
}
|
|
499
|
+
if (story.frontmatter.implementation_complete) {
|
|
500
|
+
return 'implementation';
|
|
501
|
+
}
|
|
502
|
+
if (story.frontmatter.plan_complete) {
|
|
503
|
+
return 'plan';
|
|
504
|
+
}
|
|
505
|
+
if (story.frontmatter.research_complete) {
|
|
506
|
+
return 'research';
|
|
507
|
+
}
|
|
508
|
+
return null;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Get the next phase that should be executed for a story
|
|
512
|
+
* Uses the same logic as assessState() in kanban.ts
|
|
513
|
+
* @param story - The story to check
|
|
514
|
+
* @returns The next action type to execute, or null if story is complete
|
|
515
|
+
*/
|
|
516
|
+
export function getNextPhase(story) {
|
|
517
|
+
// Check if story is blocked
|
|
518
|
+
if (story.frontmatter.status === 'blocked') {
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
// For ready stories, follow: research → plan → implement
|
|
522
|
+
if (story.frontmatter.status === 'ready') {
|
|
523
|
+
if (!story.frontmatter.research_complete) {
|
|
524
|
+
return 'research';
|
|
525
|
+
}
|
|
526
|
+
if (!story.frontmatter.plan_complete) {
|
|
527
|
+
return 'plan';
|
|
528
|
+
}
|
|
529
|
+
return 'implement';
|
|
530
|
+
}
|
|
531
|
+
// For in-progress stories, check all phases in order: research → plan → implement → review → create_pr
|
|
532
|
+
if (story.frontmatter.status === 'in-progress') {
|
|
533
|
+
if (!story.frontmatter.research_complete) {
|
|
534
|
+
return 'research';
|
|
535
|
+
}
|
|
536
|
+
if (!story.frontmatter.plan_complete) {
|
|
537
|
+
return 'plan';
|
|
538
|
+
}
|
|
539
|
+
if (!story.frontmatter.implementation_complete) {
|
|
540
|
+
return 'implement';
|
|
541
|
+
}
|
|
542
|
+
if (!story.frontmatter.reviews_complete) {
|
|
543
|
+
return 'review';
|
|
544
|
+
}
|
|
545
|
+
return 'create_pr';
|
|
546
|
+
}
|
|
547
|
+
// For done stories, no next phase
|
|
548
|
+
if (story.frontmatter.status === 'done') {
|
|
549
|
+
return null;
|
|
550
|
+
}
|
|
551
|
+
// Default: backlog stories should be refined first
|
|
552
|
+
return 'refine';
|
|
553
|
+
}
|
|
554
|
+
//# sourceMappingURL=worktree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/core/worktree.ts"],"names":[],"mappings":"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"}
|