@bicorne/task-flow 0.1.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.
Files changed (118) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +252 -0
  3. package/SKILL.md +250 -0
  4. package/assets/.harnessrc +10 -0
  5. package/assets/PHASE-task.json.example +50 -0
  6. package/assets/design.md +69 -0
  7. package/assets/hooks.json +15 -0
  8. package/assets/product-requirement.md +82 -0
  9. package/assets/schema.json +127 -0
  10. package/assets/tasks.md +26 -0
  11. package/dist/commands/analyze.d.ts +32 -0
  12. package/dist/commands/analyze.js +338 -0
  13. package/dist/commands/archive.d.ts +11 -0
  14. package/dist/commands/archive.js +53 -0
  15. package/dist/commands/design.d.ts +38 -0
  16. package/dist/commands/design.js +492 -0
  17. package/dist/commands/extract.d.ts +31 -0
  18. package/dist/commands/extract.js +477 -0
  19. package/dist/commands/init.d.ts +24 -0
  20. package/dist/commands/init.js +165 -0
  21. package/dist/commands/merge/index.d.ts +17 -0
  22. package/dist/commands/merge/index.js +322 -0
  23. package/dist/commands/merge/merger.d.ts +18 -0
  24. package/dist/commands/merge/merger.js +151 -0
  25. package/dist/commands/merge/types.d.ts +67 -0
  26. package/dist/commands/merge/types.js +6 -0
  27. package/dist/commands/merge/validators.d.ts +14 -0
  28. package/dist/commands/merge/validators.js +147 -0
  29. package/dist/commands/merge.d.ts +7 -0
  30. package/dist/commands/merge.js +15 -0
  31. package/dist/commands/start.d.ts +32 -0
  32. package/dist/commands/start.js +265 -0
  33. package/dist/commands/status.d.ts +15 -0
  34. package/dist/commands/status.js +143 -0
  35. package/dist/commands/sync.d.ts +11 -0
  36. package/dist/commands/sync.js +58 -0
  37. package/dist/commands/tasks-gen/doc-parser.d.ts +7 -0
  38. package/dist/commands/tasks-gen/doc-parser.js +259 -0
  39. package/dist/commands/tasks-gen/generators.d.ts +33 -0
  40. package/dist/commands/tasks-gen/generators.js +141 -0
  41. package/dist/commands/tasks-gen/index.d.ts +30 -0
  42. package/dist/commands/tasks-gen/index.js +345 -0
  43. package/dist/commands/tasks-gen/parsers.d.ts +29 -0
  44. package/dist/commands/tasks-gen/parsers.js +272 -0
  45. package/dist/commands/tasks-gen/templates.d.ts +8 -0
  46. package/dist/commands/tasks-gen/templates.js +37 -0
  47. package/dist/commands/tasks-gen/types.d.ts +71 -0
  48. package/dist/commands/tasks-gen/types.js +17 -0
  49. package/dist/commands/tasks-gen/validators.d.ts +14 -0
  50. package/dist/commands/tasks-gen/validators.js +54 -0
  51. package/dist/commands/tasks.d.ts +9 -0
  52. package/dist/commands/tasks.js +22 -0
  53. package/dist/commands/worktree.d.ts +28 -0
  54. package/dist/commands/worktree.js +275 -0
  55. package/dist/hooks/check-prd-exists.d.ts +20 -0
  56. package/dist/hooks/check-prd-exists.js +61 -0
  57. package/dist/hooks/check-worktree-conflict.d.ts +34 -0
  58. package/dist/hooks/check-worktree-conflict.js +107 -0
  59. package/dist/hooks/hook-runner/executor.d.ts +18 -0
  60. package/dist/hooks/hook-runner/executor.js +143 -0
  61. package/dist/hooks/hook-runner/index.d.ts +64 -0
  62. package/dist/hooks/hook-runner/index.js +220 -0
  63. package/dist/hooks/hook-runner/loader.d.ts +23 -0
  64. package/dist/hooks/hook-runner/loader.js +126 -0
  65. package/dist/hooks/hook-runner/types.d.ts +59 -0
  66. package/dist/hooks/hook-runner/types.js +6 -0
  67. package/dist/hooks/hook-runner.d.ts +9 -0
  68. package/dist/hooks/hook-runner.js +30 -0
  69. package/dist/hooks/phase-complete-detector.d.ts +35 -0
  70. package/dist/hooks/phase-complete-detector.js +203 -0
  71. package/dist/hooks/phase-gate-validator.d.ts +76 -0
  72. package/dist/hooks/phase-gate-validator.js +407 -0
  73. package/dist/hooks/save-checkpoint.d.ts +43 -0
  74. package/dist/hooks/save-checkpoint.js +144 -0
  75. package/dist/hooks/start-mcp-servers.d.ts +50 -0
  76. package/dist/hooks/start-mcp-servers.js +75 -0
  77. package/dist/hooks/stop-mcp-servers.d.ts +40 -0
  78. package/dist/hooks/stop-mcp-servers.js +58 -0
  79. package/dist/index.d.ts +29 -0
  80. package/dist/index.js +238 -0
  81. package/dist/lib/archive.d.ts +31 -0
  82. package/dist/lib/archive.js +226 -0
  83. package/dist/lib/config.d.ts +93 -0
  84. package/dist/lib/config.js +251 -0
  85. package/dist/lib/constants.d.ts +222 -0
  86. package/dist/lib/constants.js +247 -0
  87. package/dist/lib/interactive.d.ts +31 -0
  88. package/dist/lib/interactive.js +166 -0
  89. package/dist/lib/mcp-client.d.ts +156 -0
  90. package/dist/lib/mcp-client.js +370 -0
  91. package/dist/lib/state.d.ts +119 -0
  92. package/dist/lib/state.js +293 -0
  93. package/dist/slash/executor.d.ts +22 -0
  94. package/dist/slash/executor.js +259 -0
  95. package/dist/slash/index.d.ts +11 -0
  96. package/dist/slash/index.js +45 -0
  97. package/dist/slash/parser.d.ts +24 -0
  98. package/dist/slash/parser.js +101 -0
  99. package/dist/slash/registry.d.ts +22 -0
  100. package/dist/slash/registry.js +155 -0
  101. package/dist/spec/openspec-to-task/builders.d.ts +107 -0
  102. package/dist/spec/openspec-to-task/builders.js +138 -0
  103. package/dist/spec/openspec-to-task/index.d.ts +20 -0
  104. package/dist/spec/openspec-to-task/index.js +182 -0
  105. package/dist/spec/openspec-to-task/parsers.d.ts +65 -0
  106. package/dist/spec/openspec-to-task/parsers.js +232 -0
  107. package/dist/spec/openspec-to-task/types.d.ts +49 -0
  108. package/dist/spec/openspec-to-task/types.js +6 -0
  109. package/dist/spec/sync-openspec-to-task.d.ts +7 -0
  110. package/dist/spec/sync-openspec-to-task.js +21 -0
  111. package/dist/spec/sync-task-to-openspec.d.ts +27 -0
  112. package/dist/spec/sync-task-to-openspec.js +288 -0
  113. package/dist/types/ai-context.d.ts +108 -0
  114. package/dist/types/ai-context.js +9 -0
  115. package/package.json +66 -0
  116. package/references/AI-CONVERSATION-TUTORIAL.md +270 -0
  117. package/references/CLI-TUTORIAL.md +447 -0
  118. package/references/GIT-WORKTREE-SOP.md +109 -0
@@ -0,0 +1,322 @@
1
+ "use strict";
2
+ /**
3
+ * commands/merge/index.ts
4
+ * Merge completed worktree back to main
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.mergeTask = mergeTask;
41
+ exports.main = main;
42
+ const child_process_1 = require("child_process");
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ const readline = __importStar(require("readline"));
46
+ const config_1 = require("../../lib/config");
47
+ const state_1 = require("../../lib/state");
48
+ const validators_1 = require("./validators");
49
+ const merger_1 = require("./merger");
50
+ /**
51
+ * Parse CLI arguments
52
+ */
53
+ function parseArgs(argv) {
54
+ const args = {};
55
+ for (let i = 2; i < argv.length; i += 1) {
56
+ const token = argv[i] || '';
57
+ if (!token.startsWith('--')) {
58
+ continue;
59
+ }
60
+ const key = token.slice(2);
61
+ const next = argv[i + 1] || '';
62
+ if (!next || next.startsWith('--')) {
63
+ args[key] = true;
64
+ continue;
65
+ }
66
+ args[key] = next;
67
+ i += 1;
68
+ }
69
+ return args;
70
+ }
71
+ /**
72
+ * Extract merge setting from task file
73
+ */
74
+ function extractTaskMergeSetting(file, key) {
75
+ try {
76
+ const content = fs.readFileSync(file, 'utf8');
77
+ const lines = content.split('\n');
78
+ let inMergeStrategy = false;
79
+ for (const line of lines) {
80
+ if (/^mergeStrategy:/.test(line)) {
81
+ inMergeStrategy = true;
82
+ continue;
83
+ }
84
+ if (inMergeStrategy) {
85
+ if (/^[^\s]/.test(line)) {
86
+ break;
87
+ }
88
+ const match = line.match(new RegExp(`^\\s+${key}:\\s*(.+)$`));
89
+ if (match) {
90
+ return match?.[1]?.trim() || null;
91
+ }
92
+ }
93
+ }
94
+ }
95
+ catch {
96
+ // ignore
97
+ }
98
+ return null;
99
+ }
100
+ /**
101
+ * Get merge configuration from task file
102
+ */
103
+ function getMergeConfig(taskPath, options) {
104
+ const mergeType = extractTaskMergeSetting(taskPath, 'type') || 'squash';
105
+ let deleteBranch = extractTaskMergeSetting(taskPath, 'deleteBranch') !== 'false';
106
+ let deleteWorktree = extractTaskMergeSetting(taskPath, 'deleteWorktree') !== 'false';
107
+ if (options.deleteBranch === true) {
108
+ deleteBranch = true;
109
+ }
110
+ if (options.deleteWorktree === true) {
111
+ deleteWorktree = true;
112
+ }
113
+ return { mergeType, deleteBranch, deleteWorktree };
114
+ }
115
+ /**
116
+ * Print merge summary
117
+ */
118
+ function printMergeSummary(params) {
119
+ console.log('');
120
+ console.log('╔════════════════════════════════════════════════════════╗');
121
+ console.log('║ Task Flow Merge Summary ║');
122
+ console.log('╚════════════════════════════════════════════════════════╝');
123
+ console.log('');
124
+ console.log(`Task ID: ${params.taskId}`);
125
+ console.log(`Branch: ${params.branch}`);
126
+ console.log(`Worktree: ${params.worktreeName}`);
127
+ console.log(`Merge Type: ${params.mergeType}`);
128
+ console.log(`Delete Branch: ${params.deleteBranch}`);
129
+ console.log(`Delete Worktree: ${params.deleteWorktree}`);
130
+ console.log(`Dry Run: ${params.dryRun || false}`);
131
+ console.log('');
132
+ }
133
+ /**
134
+ * Update task state after merge
135
+ */
136
+ function updateTaskStateAfterMerge(config, taskId) {
137
+ (0, state_1.clearCurrentTask)(config);
138
+ (0, state_1.addTaskToHistory)({
139
+ taskId,
140
+ status: 'completed',
141
+ completedAt: new Date().toISOString(),
142
+ }, config);
143
+ const archiveScript = path.resolve(__dirname, '../../lib/archive.js');
144
+ (0, child_process_1.spawnSync)(process.execPath, [
145
+ archiveScript,
146
+ '--cwd', config.projectRoot,
147
+ '--task-id', taskId,
148
+ '--event', 'task_merged',
149
+ '--status', 'completed',
150
+ '--phase', 'merge',
151
+ '--phase-completed', 'review',
152
+ '--review-conclusion', 'PASS',
153
+ '--completed-at', new Date().toISOString(),
154
+ ], { stdio: 'inherit' });
155
+ const syncScript = path.resolve(__dirname, '../../spec/sync-task-to-openspec.js');
156
+ (0, child_process_1.spawnSync)(process.execPath, [
157
+ syncScript,
158
+ '--cwd', config.projectRoot,
159
+ '--task-id', taskId,
160
+ ], { stdio: 'inherit' });
161
+ }
162
+ /**
163
+ * Execute merge operation
164
+ */
165
+ async function executeMerge(config, taskId, branch, worktree, mergeType, deleteBranch, deleteWorktree, dryRun) {
166
+ console.log('[MERGE] Pulling latest changes...');
167
+ try {
168
+ const pullResult = (0, child_process_1.spawnSync)('git', ['pull', 'origin', 'main'], { stdio: 'inherit' });
169
+ if (pullResult.status !== 0) {
170
+ console.warn('[MERGE] Pull failed, continuing anyway...');
171
+ }
172
+ }
173
+ catch {
174
+ console.warn('[MERGE] Pull failed, continuing anyway...');
175
+ }
176
+ console.log(`[MERGE] Merging branch: ${branch}`);
177
+ if (!(0, merger_1.performMerge)(branch, mergeType, dryRun)) {
178
+ return {
179
+ success: false,
180
+ reason: 'merge-failed',
181
+ message: 'Merge failed',
182
+ };
183
+ }
184
+ (0, merger_1.cleanupWorktreeAndBranch)(config, worktree, branch, deleteWorktree, deleteBranch);
185
+ updateTaskStateAfterMerge(config, taskId);
186
+ return {
187
+ success: true,
188
+ taskId,
189
+ branch,
190
+ worktreeName: worktree.name,
191
+ };
192
+ }
193
+ /**
194
+ * Merge task
195
+ */
196
+ function mergeTask(options = {}) {
197
+ const config = (0, config_1.loadConfig)({ cwd: options.cwd });
198
+ const state = (0, state_1.loadState)(config);
199
+ const taskId = options.taskId || state.currentTask;
200
+ if (!taskId) {
201
+ return {
202
+ success: false,
203
+ reason: 'missing-task-id',
204
+ message: 'No current task in state.json. Please specify task-id.',
205
+ };
206
+ }
207
+ const taskPath = path.resolve(config.tasksDirAbs, `${taskId}.json`);
208
+ if (!fs.existsSync(taskPath)) {
209
+ return {
210
+ success: false,
211
+ reason: 'missing-task-file',
212
+ message: `Task file not found: ${taskPath}`,
213
+ };
214
+ }
215
+ const mergeConfig = getMergeConfig(taskPath, options);
216
+ const reviewPath = path.resolve(config.reportsDirAbs, `${taskId}-review.md`);
217
+ const reviewValidation = (0, validators_1.validateReview)(reviewPath, options.skipReviewCheck);
218
+ if (!reviewValidation.valid) {
219
+ return {
220
+ success: false,
221
+ reason: reviewValidation.reason,
222
+ message: reviewValidation.message,
223
+ };
224
+ }
225
+ const worktreeValidation = (0, validators_1.validateWorktreeAndBranch)(state, taskId);
226
+ if (!worktreeValidation.valid) {
227
+ return {
228
+ success: false,
229
+ reason: worktreeValidation.reason,
230
+ message: worktreeValidation.message,
231
+ };
232
+ }
233
+ const { worktree, branch } = worktreeValidation;
234
+ printMergeSummary({
235
+ taskId,
236
+ branch: branch,
237
+ worktreeName: worktree.name,
238
+ mergeType: mergeConfig.mergeType,
239
+ deleteBranch: mergeConfig.deleteBranch,
240
+ deleteWorktree: mergeConfig.deleteWorktree,
241
+ dryRun: options.dryRun,
242
+ });
243
+ if (!options.dryRun) {
244
+ const rl = readline.createInterface({
245
+ input: process.stdin,
246
+ output: process.stdout,
247
+ });
248
+ return new Promise((resolve) => {
249
+ rl.question('Proceed with merge? (y/N) ', (answer) => {
250
+ rl.close();
251
+ if (!/^[Yy]$/.test(answer)) {
252
+ resolve({
253
+ success: false,
254
+ reason: 'cancelled',
255
+ message: 'Merge cancelled',
256
+ });
257
+ return;
258
+ }
259
+ executeMerge(config, taskId, branch, worktree, mergeConfig.mergeType, mergeConfig.deleteBranch, mergeConfig.deleteWorktree, options.dryRun).then(resolve);
260
+ });
261
+ });
262
+ }
263
+ return {
264
+ success: true,
265
+ taskId,
266
+ branch,
267
+ worktreeName: worktree.name,
268
+ dryRun: true,
269
+ };
270
+ }
271
+ /**
272
+ * Main entry point
273
+ */
274
+ function main() {
275
+ const args = parseArgs(process.argv);
276
+ const positionalArgs = Array.isArray(args._) ? args._ : [];
277
+ const result = mergeTask({
278
+ cwd: args.cwd,
279
+ taskId: positionalArgs[0] || args['task-id'],
280
+ skipReviewCheck: args['skip-review-check'] === true,
281
+ deleteBranch: args['no-delete-branch'] !== true,
282
+ deleteWorktree: args['no-delete-worktree'] !== true,
283
+ dryRun: args['dry-run'] === true,
284
+ });
285
+ if (result instanceof Promise) {
286
+ result.then((res) => {
287
+ if (!res.success) {
288
+ console.error(`[MERGE] ${res.message}`);
289
+ process.exit(1);
290
+ }
291
+ console.log('');
292
+ console.log('[MERGE] Merge completed successfully!');
293
+ console.log(` Task: ${res.taskId}`);
294
+ console.log(` Status: completed`);
295
+ console.log('');
296
+ process.exit(0);
297
+ }).catch((error) => {
298
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
299
+ console.error('[MERGE] Error:', errorMessage);
300
+ process.exit(1);
301
+ });
302
+ }
303
+ else {
304
+ if (!result.success) {
305
+ console.error(`[MERGE] ${result.message}`);
306
+ process.exit(1);
307
+ }
308
+ if (result.dryRun) {
309
+ console.log('[MERGE] Dry run completed. No changes made.');
310
+ }
311
+ else {
312
+ console.log('[MERGE] Merge completed successfully!');
313
+ }
314
+ process.exit(0);
315
+ }
316
+ }
317
+ if (require.main === module) {
318
+ main();
319
+ }
320
+ exports.default = {
321
+ mergeTask,
322
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * commands/merge/merger.ts
3
+ * Merge execution utilities
4
+ */
5
+ import { Config } from '../../lib/config';
6
+ import { WorktreeInfo } from '../../lib/state';
7
+ /**
8
+ * Handle merge conflicts
9
+ */
10
+ export declare function handleMergeConflict(): boolean;
11
+ /**
12
+ * Perform the actual merge
13
+ */
14
+ export declare function performMerge(branch: string, mergeType: string, dryRun?: boolean): boolean;
15
+ /**
16
+ * Cleanup worktree and branch
17
+ */
18
+ export declare function cleanupWorktreeAndBranch(config: Config, worktree: WorktreeInfo, branch: string, deleteWorktree: boolean, deleteBranch: boolean): void;
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ /**
3
+ * commands/merge/merger.ts
4
+ * Merge execution utilities
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.handleMergeConflict = handleMergeConflict;
41
+ exports.performMerge = performMerge;
42
+ exports.cleanupWorktreeAndBranch = cleanupWorktreeAndBranch;
43
+ const child_process_1 = require("child_process");
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ /**
47
+ * Handle merge conflicts
48
+ */
49
+ function handleMergeConflict() {
50
+ try {
51
+ const conflicted = (0, child_process_1.execSync)('git diff --name-only --diff-filter=U', { encoding: 'utf8' });
52
+ if (conflicted.trim()) {
53
+ console.error('[MERGE] Merge conflicts detected:');
54
+ console.error(conflicted);
55
+ (0, child_process_1.execSync)('git merge --abort 2>/dev/null || git reset --merge 2>/dev/null || true');
56
+ return true;
57
+ }
58
+ }
59
+ catch {
60
+ // no conflicts
61
+ }
62
+ return false;
63
+ }
64
+ /**
65
+ * Perform the actual merge
66
+ */
67
+ function performMerge(branch, mergeType, dryRun) {
68
+ if (dryRun) {
69
+ console.log(`[DRY-RUN] Would merge ${branch} using ${mergeType}`);
70
+ return true;
71
+ }
72
+ try {
73
+ if (mergeType === 'squash') {
74
+ const squashResult = (0, child_process_1.spawnSync)('git', ['merge', '--squash', branch], { stdio: 'inherit' });
75
+ if (squashResult.status !== 0) {
76
+ console.error('[MERGE] Squash merge failed');
77
+ return false;
78
+ }
79
+ if (handleMergeConflict()) {
80
+ return false;
81
+ }
82
+ try {
83
+ const commitResult = (0, child_process_1.spawnSync)('git', ['commit', '-m', `feat: merged from harness worktree ${branch}`], { stdio: 'inherit' });
84
+ if (commitResult.status !== 0) {
85
+ console.warn('[MERGE] No changes to commit');
86
+ }
87
+ }
88
+ catch {
89
+ console.warn('[MERGE] No changes to commit');
90
+ }
91
+ }
92
+ else if (mergeType === 'merge') {
93
+ const mergeResult = (0, child_process_1.spawnSync)('git', ['merge', '--no-ff', branch, '-m', `feat: merged from harness worktree ${branch}`], { stdio: 'inherit' });
94
+ if (mergeResult.status !== 0) {
95
+ console.error('[MERGE] Merge failed');
96
+ return false;
97
+ }
98
+ if (handleMergeConflict()) {
99
+ return false;
100
+ }
101
+ }
102
+ else if (mergeType === 'rebase') {
103
+ console.error('[MERGE] Rebase strategy requires worktree rebase - use manual merge for now');
104
+ return false;
105
+ }
106
+ else {
107
+ console.error(`[MERGE] Unsupported merge strategy: ${mergeType}`);
108
+ return false;
109
+ }
110
+ return true;
111
+ }
112
+ catch (error) {
113
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
114
+ console.error('[MERGE] Merge failed:', errorMessage);
115
+ return false;
116
+ }
117
+ }
118
+ /**
119
+ * Cleanup worktree and branch
120
+ */
121
+ function cleanupWorktreeAndBranch(config, worktree, branch, deleteWorktree, deleteBranch) {
122
+ if (deleteWorktree && worktree.path) {
123
+ const worktreePath = path.resolve(config.projectRoot, worktree.path);
124
+ if (fs.existsSync(worktreePath)) {
125
+ console.log(`[MERGE] Removing worktree: ${worktree.name}`);
126
+ try {
127
+ const result = (0, child_process_1.spawnSync)('git', ['worktree', 'remove', worktreePath, '--force'], { stdio: 'inherit' });
128
+ if (result.status !== 0) {
129
+ console.warn('[MERGE] Failed to remove worktree');
130
+ }
131
+ }
132
+ catch (error) {
133
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
134
+ console.warn('[MERGE] Failed to remove worktree:', errorMessage);
135
+ }
136
+ }
137
+ }
138
+ if (deleteBranch) {
139
+ console.log(`[MERGE] Deleting branch: ${branch}`);
140
+ try {
141
+ const result = (0, child_process_1.spawnSync)('git', ['branch', '-D', branch], { stdio: 'inherit' });
142
+ if (result.status !== 0) {
143
+ console.warn('[MERGE] Failed to delete branch');
144
+ }
145
+ }
146
+ catch (error) {
147
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
148
+ console.warn('[MERGE] Failed to delete branch:', errorMessage);
149
+ }
150
+ }
151
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * commands/merge/types.ts
3
+ * Type definitions for merge command
4
+ */
5
+ import { WorktreeInfo } from '../../lib/state';
6
+ /**
7
+ * Merge command options
8
+ */
9
+ export interface MergeOptions {
10
+ cwd?: string;
11
+ taskId?: string;
12
+ skipReviewCheck?: boolean;
13
+ deleteBranch?: boolean;
14
+ deleteWorktree?: boolean;
15
+ dryRun?: boolean;
16
+ }
17
+ /**
18
+ * Merge command result
19
+ */
20
+ export interface MergeResult {
21
+ success: boolean;
22
+ reason?: string;
23
+ message?: string;
24
+ taskId?: string;
25
+ branch?: string;
26
+ worktreeName?: string;
27
+ dryRun?: boolean;
28
+ }
29
+ /**
30
+ * Merge configuration
31
+ */
32
+ export interface MergeConfig {
33
+ mergeType: string;
34
+ deleteBranch: boolean;
35
+ deleteWorktree: boolean;
36
+ }
37
+ /**
38
+ * Validation context for review
39
+ */
40
+ export interface ReviewValidation {
41
+ valid: boolean;
42
+ reason?: string;
43
+ message?: string;
44
+ conclusion?: string | null;
45
+ }
46
+ /**
47
+ * Validation context for worktree and branch
48
+ */
49
+ export interface WorktreeValidation {
50
+ valid: boolean;
51
+ reason?: string;
52
+ message?: string;
53
+ worktree?: WorktreeInfo;
54
+ branch?: string;
55
+ }
56
+ /**
57
+ * Merge summary parameters
58
+ */
59
+ export interface MergeSummaryParams {
60
+ taskId: string;
61
+ branch: string;
62
+ worktreeName: string;
63
+ mergeType: string;
64
+ deleteBranch: boolean;
65
+ deleteWorktree: boolean;
66
+ dryRun?: boolean;
67
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * commands/merge/types.ts
4
+ * Type definitions for merge command
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,14 @@
1
+ /**
2
+ * commands/merge/validators.ts
3
+ * Validation utilities for merge command
4
+ */
5
+ import { State } from '../../lib/state';
6
+ import { ReviewValidation, WorktreeValidation } from './types';
7
+ /**
8
+ * Validate review report
9
+ */
10
+ export declare function validateReview(reviewPath: string, skipReviewCheck?: boolean): ReviewValidation;
11
+ /**
12
+ * Validate worktree and branch
13
+ */
14
+ export declare function validateWorktreeAndBranch(state: State, taskId: string): WorktreeValidation;