steroids-cli 0.8.22 → 0.8.23

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 (71) hide show
  1. package/dist/commands/loop-phases.d.ts +1 -1
  2. package/dist/commands/loop-phases.d.ts.map +1 -1
  3. package/dist/commands/loop-phases.js +3 -3
  4. package/dist/commands/loop-phases.js.map +1 -1
  5. package/dist/commands/runners.js +4 -0
  6. package/dist/commands/runners.js.map +1 -1
  7. package/dist/database/schema.d.ts +2 -2
  8. package/dist/database/schema.d.ts.map +1 -1
  9. package/dist/database/schema.js +30 -0
  10. package/dist/database/schema.js.map +1 -1
  11. package/dist/orchestrator/task-selector.d.ts +7 -2
  12. package/dist/orchestrator/task-selector.d.ts.map +1 -1
  13. package/dist/orchestrator/task-selector.js +91 -14
  14. package/dist/orchestrator/task-selector.js.map +1 -1
  15. package/dist/parallel/clone.d.ts +41 -0
  16. package/dist/parallel/clone.d.ts.map +1 -0
  17. package/dist/parallel/clone.js +176 -0
  18. package/dist/parallel/clone.js.map +1 -0
  19. package/dist/parallel/clone.test.d.ts +2 -0
  20. package/dist/parallel/clone.test.d.ts.map +1 -0
  21. package/dist/parallel/clone.test.js +252 -0
  22. package/dist/parallel/clone.test.js.map +1 -0
  23. package/dist/parallel/merge-conflict.d.ts +22 -0
  24. package/dist/parallel/merge-conflict.d.ts.map +1 -0
  25. package/dist/parallel/merge-conflict.js +227 -0
  26. package/dist/parallel/merge-conflict.js.map +1 -0
  27. package/dist/parallel/merge-errors.d.ts +10 -0
  28. package/dist/parallel/merge-errors.d.ts.map +1 -0
  29. package/dist/parallel/merge-errors.js +16 -0
  30. package/dist/parallel/merge-errors.js.map +1 -0
  31. package/dist/parallel/merge-git.d.ts +25 -0
  32. package/dist/parallel/merge-git.d.ts.map +1 -0
  33. package/dist/parallel/merge-git.js +134 -0
  34. package/dist/parallel/merge-git.js.map +1 -0
  35. package/dist/parallel/merge-lock.d.ts +26 -0
  36. package/dist/parallel/merge-lock.d.ts.map +1 -0
  37. package/dist/parallel/merge-lock.js +58 -0
  38. package/dist/parallel/merge-lock.js.map +1 -0
  39. package/dist/parallel/merge-progress.d.ts +20 -0
  40. package/dist/parallel/merge-progress.d.ts.map +1 -0
  41. package/dist/parallel/merge-progress.js +36 -0
  42. package/dist/parallel/merge-progress.js.map +1 -0
  43. package/dist/parallel/merge.d.ts +39 -0
  44. package/dist/parallel/merge.d.ts.map +1 -0
  45. package/dist/parallel/merge.js +231 -0
  46. package/dist/parallel/merge.js.map +1 -0
  47. package/dist/parallel/merge.test.d.ts +5 -0
  48. package/dist/parallel/merge.test.d.ts.map +1 -0
  49. package/dist/parallel/merge.test.js +322 -0
  50. package/dist/parallel/merge.test.js.map +1 -0
  51. package/dist/parallel/scheduler.d.ts +43 -0
  52. package/dist/parallel/scheduler.d.ts.map +1 -0
  53. package/dist/parallel/scheduler.js +281 -0
  54. package/dist/parallel/scheduler.js.map +1 -0
  55. package/dist/runners/daemon.d.ts +11 -1
  56. package/dist/runners/daemon.d.ts.map +1 -1
  57. package/dist/runners/daemon.js +18 -4
  58. package/dist/runners/daemon.js.map +1 -1
  59. package/dist/runners/global-db.d.ts.map +1 -1
  60. package/dist/runners/global-db.js +42 -1
  61. package/dist/runners/global-db.js.map +1 -1
  62. package/dist/runners/orchestrator-loop.d.ts +3 -0
  63. package/dist/runners/orchestrator-loop.d.ts.map +1 -1
  64. package/dist/runners/orchestrator-loop.js +19 -9
  65. package/dist/runners/orchestrator-loop.js.map +1 -1
  66. package/dist/runners/wakeup.d.ts.map +1 -1
  67. package/dist/runners/wakeup.js +2 -1
  68. package/dist/runners/wakeup.js.map +1 -1
  69. package/migrations/011_add_merge_locks_and_progress.sql +39 -0
  70. package/migrations/manifest.json +9 -1
  71. package/package.json +1 -1
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ /**
3
+ * Merge conflict resolution helpers.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseReviewDecision = parseReviewDecision;
7
+ exports.runConflictResolutionCycle = runConflictResolutionCycle;
8
+ const node_crypto_1 = require("node:crypto");
9
+ const loader_js_1 = require("../config/loader.js");
10
+ const queries_js_1 = require("../database/queries.js");
11
+ const invocation_logger_js_1 = require("../providers/invocation-logger.js");
12
+ const registry_js_1 = require("../providers/registry.js");
13
+ const merge_git_js_1 = require("./merge-git.js");
14
+ const merge_errors_js_1 = require("./merge-errors.js");
15
+ const merge_progress_js_1 = require("./merge-progress.js");
16
+ function parseReviewDecision(raw) {
17
+ const trimmed = raw.trim();
18
+ const upper = trimmed.toUpperCase();
19
+ const hasApprove = upper.includes('APPROVE');
20
+ const hasReject = upper.includes('REJECT');
21
+ if (hasApprove && !hasReject) {
22
+ return {
23
+ decision: 'approve',
24
+ notes: trimmed || 'APPROVED by merge-conflict reviewer',
25
+ };
26
+ }
27
+ if (hasReject) {
28
+ return {
29
+ decision: 'reject',
30
+ notes: trimmed || 'Please review and correct conflict resolution',
31
+ };
32
+ }
33
+ return {
34
+ decision: 'reject',
35
+ notes: trimmed || 'Decision was not clear. Please provide explicit APPROVE/REJECT.',
36
+ };
37
+ }
38
+ function buildMergeConflictSectionName() {
39
+ return 'merge-conflicts';
40
+ }
41
+ function getNowISOString() {
42
+ return new Date().toISOString();
43
+ }
44
+ function createMergeConflictSection(db) {
45
+ const sectionName = buildMergeConflictSectionName();
46
+ const existing = db
47
+ .prepare('SELECT id FROM sections WHERE name = ? LIMIT 1')
48
+ .get(sectionName);
49
+ if (existing) {
50
+ return existing.id;
51
+ }
52
+ const maxPosRow = db
53
+ .prepare('SELECT MAX(position) as maxPos FROM sections')
54
+ .get();
55
+ const position = (maxPosRow?.maxPos ?? -1) + 1;
56
+ const sectionId = (0, node_crypto_1.createHash)('sha1').update(sectionName + position).digest('hex');
57
+ db.prepare(`INSERT INTO sections (id, name, position, priority, skipped, created_at)
58
+ VALUES (?, ?, ?, ?, ?, ?)`).run(sectionId, sectionName, position, 80, 0, getNowISOString());
59
+ return sectionId;
60
+ }
61
+ function ensureMergeConflictTask(db, workstreamId, shortSha, branchName, commitMessage, conflictedFiles, conflictPatch, forceNew = false) {
62
+ const sectionId = createMergeConflictSection(db);
63
+ if (!forceNew) {
64
+ const existing = db
65
+ .prepare(`SELECT t.id
66
+ FROM tasks t
67
+ INNER JOIN sections s ON s.id = t.section_id
68
+ WHERE s.name = ? AND t.title LIKE ?
69
+ ORDER BY t.created_at DESC
70
+ LIMIT 1`)
71
+ .get(buildMergeConflictSectionName(), `Merge conflict: cherry-pick ${shortSha}%`);
72
+ if (existing?.id) {
73
+ return existing.id;
74
+ }
75
+ }
76
+ const title = `Merge conflict: cherry-pick ${shortSha} from ${branchName}`;
77
+ const created = (0, queries_js_1.createTask)(db, title, {
78
+ sectionId,
79
+ sourceFile: `merge-conflict (${workstreamId})`,
80
+ filePath: conflictedFiles.join(', '),
81
+ status: 'pending',
82
+ fileContentHash: conflictPatch.substring(0, 2048),
83
+ fileCommitSha: commitMessage,
84
+ });
85
+ (0, queries_js_1.addAuditEntry)(db, created.id, 'null', 'pending', 'merge', {
86
+ actorType: 'orchestrator',
87
+ notes: `Generated from conflict while cherry-picking ${shortSha} from ${branchName}:\n${commitMessage}`,
88
+ });
89
+ return created.id;
90
+ }
91
+ function createPromptForConflictCoder(options) {
92
+ const notesSection = options.rejectionNotes
93
+ ? `\n\nLatest review note from the resolver:\n${options.rejectionNotes}\n`
94
+ : '';
95
+ return `You are resolving a merge conflict for a cherry-pick during parallel merge.\n\n## Conflict context\nWorkstream: ${options.workstreamId}\nBranch: ${options.branchName}\nCommit: ${options.shortSha}\nCommit Message:\n${options.commitMessage}\n\nConflicted files:\n${options.conflictedFiles.map((file) => `- ${file}`).join('\n')}\n\nIntended patch:\n${options.conflictPatch}\n\nRules:\n1) Edit conflicted files to a correct resolution.\n2) Remove ALL conflict markers (<<<<<<, =======, >>>>>>) in resolved files.\n3) Stage only the resolved files using git add.\n4) Do NOT commit.\n5) Be surgical; change only files required for this commit.\n${notesSection}\n\nRespond with a short confirmation when done.`;
96
+ }
97
+ function createPromptForConflictReviewer(options) {
98
+ const files = options.stagedFiles.length > 0
99
+ ? options.stagedFiles.map((file) => `- ${file}`).join('\n')
100
+ : 'No files staged yet';
101
+ return `You are reviewing a staged resolution for a cherry-pick conflict in parallel merge.\n\nWorkstream: ${options.workstreamId}\nBranch: ${options.branchName}\nCommit: ${options.shortSha}\nOriginal message: ${options.commitMessage}\n\nCurrent staged diff to be committed by cherry-pick --continue:\n${options.stagedDiff || '(empty diff)'}\n\nFiles staged:\n${files}\n\nDecision rules:\n- Reply with APPROVE if the resolution is correct.\n- Reply with REJECT and actionable notes if any conflict marker remains or logic is incorrect.\n\nFormat:\nAPPROVE - <optional note> or\nREJECT - <checklist itemized note>`;
102
+ }
103
+ async function invokeModel(role, projectPath, taskId, prompt) {
104
+ const config = (0, loader_js_1.loadConfig)(projectPath);
105
+ const modelConfig = role === 'coder' ? config.ai?.coder : config.ai?.reviewer;
106
+ if (!modelConfig?.provider || !modelConfig?.model) {
107
+ throw new merge_errors_js_1.ParallelMergeError(`Missing AI ${role} configuration. Configure via config.ai.${role}.`, 'AI_CONFIG_MISSING');
108
+ }
109
+ const providerName = modelConfig.provider;
110
+ const model = modelConfig.model;
111
+ const registry = (0, registry_js_1.getProviderRegistry)();
112
+ const provider = registry.get(providerName);
113
+ const result = await (0, invocation_logger_js_1.logInvocation)(prompt, (ctx) => provider.invoke(prompt, {
114
+ model,
115
+ timeout: 60 * 60 * 1000,
116
+ cwd: projectPath,
117
+ role,
118
+ streamOutput: false,
119
+ onActivity: ctx?.onActivity,
120
+ }), {
121
+ role,
122
+ provider: providerName,
123
+ model,
124
+ taskId,
125
+ projectPath,
126
+ });
127
+ if (!result.success) {
128
+ const details = result.stderr || result.stdout || 'model returned non-zero exit code';
129
+ throw new merge_errors_js_1.ParallelMergeError(`${role.toUpperCase()} invocation failed during merge conflict handling: ${details}`, 'AI_INVOCATION_FAILED');
130
+ }
131
+ if (result.timedOut) {
132
+ throw new merge_errors_js_1.ParallelMergeError(`${role} invocation timed out`, 'AI_INVOKE_TIMEOUT');
133
+ }
134
+ return result.stdout;
135
+ }
136
+ async function runConflictResolutionCycle(options) {
137
+ const { db, projectPath, sessionId, workstreamId, branchName, position, commitSha, existingTaskId, } = options;
138
+ const shortSha = options.commitSha.slice(0, 7);
139
+ const conflictedFiles = (0, merge_git_js_1.getConflictedFiles)(projectPath);
140
+ const conflictPatch = (0, merge_git_js_1.getCommitPatch)(projectPath, commitSha);
141
+ const commitMessage = (0, merge_git_js_1.getCommitMessage)(projectPath, commitSha);
142
+ const taskId = ensureMergeConflictTask(db, workstreamId, shortSha, branchName, commitMessage, conflictedFiles, conflictPatch, !existingTaskId);
143
+ let conflictTaskId = existingTaskId ?? taskId;
144
+ if (conflictTaskId !== taskId) {
145
+ conflictTaskId = taskId;
146
+ }
147
+ (0, merge_progress_js_1.upsertProgressEntry)(db, sessionId, workstreamId, position, commitSha, 'conflict', conflictTaskId);
148
+ const currentConflictTask = (0, queries_js_1.getTask)(db, conflictTaskId);
149
+ if (!currentConflictTask) {
150
+ throw new merge_errors_js_1.ParallelMergeError('Created merge-conflict task not found', 'TASK_MISSING');
151
+ }
152
+ if (currentConflictTask.status === 'completed') {
153
+ (0, merge_progress_js_1.upsertProgressEntry)(db, sessionId, workstreamId, position, commitSha, 'applied', conflictTaskId);
154
+ return 'continued';
155
+ }
156
+ (0, queries_js_1.updateTaskStatus)(db, currentConflictTask.id, 'in_progress', 'merge-conflict-orchestrator');
157
+ while (true) {
158
+ const existingTask = (0, queries_js_1.getTask)(db, currentConflictTask.id);
159
+ const lastNotes = existingTask?.rejection_count
160
+ ? `After ${existingTask.rejection_count} rejection(s).`
161
+ : undefined;
162
+ const coderPrompt = createPromptForConflictCoder({
163
+ workstreamId,
164
+ shortSha,
165
+ branchName,
166
+ commitMessage,
167
+ conflictedFiles,
168
+ conflictPatch,
169
+ rejectionNotes: lastNotes,
170
+ });
171
+ await invokeModel('coder', projectPath, currentConflictTask.id, coderPrompt);
172
+ const remaining = (0, merge_git_js_1.getConflictedFiles)(projectPath);
173
+ if (remaining.length > 0) {
174
+ (0, queries_js_1.updateTaskStatus)(db, currentConflictTask.id, 'in_progress', 'merge-conflict-orchestrator', `Conflict markers still present: ${remaining.join(', ')}`);
175
+ continue;
176
+ }
177
+ const stagedFiles = (0, merge_git_js_1.getCachedFiles)(projectPath);
178
+ const stagedDiff = (0, merge_git_js_1.getCachedDiff)(projectPath);
179
+ if (stagedFiles.length === 0 || stagedDiff.trim().length === 0) {
180
+ (0, queries_js_1.updateTaskStatus)(db, currentConflictTask.id, 'in_progress', 'merge-conflict-orchestrator', 'No staged diff found. Stage resolved files before requesting review.');
181
+ continue;
182
+ }
183
+ (0, queries_js_1.updateTaskStatus)(db, currentConflictTask.id, 'review', 'merge-conflict-orchestrator');
184
+ const reviewerPrompt = createPromptForConflictReviewer({
185
+ workstreamId,
186
+ shortSha,
187
+ branchName,
188
+ commitMessage,
189
+ stagedDiff,
190
+ stagedFiles,
191
+ });
192
+ const decisionText = await invokeModel('reviewer', projectPath, currentConflictTask.id, reviewerPrompt);
193
+ const decision = parseReviewDecision(decisionText);
194
+ if (decision.decision === 'reject') {
195
+ (0, queries_js_1.rejectTask)(db, currentConflictTask.id, 'merge-conflict-reviewer', decision.notes);
196
+ if ((0, merge_git_js_1.cleanTreeHasConflicts)(projectPath)) {
197
+ continue;
198
+ }
199
+ // If no explicit conflict markers remain but reviewer still rejects, keep iterating.
200
+ continue;
201
+ }
202
+ if ((0, merge_git_js_1.hasUnmergedFiles)(projectPath)) {
203
+ (0, queries_js_1.rejectTask)(db, currentConflictTask.id, 'merge-conflict-reviewer', 'Conflict markers still present. Please fix.');
204
+ continue;
205
+ }
206
+ if (!(0, merge_git_js_1.hasCherryPickInProgress)(projectPath)) {
207
+ throw new merge_errors_js_1.ParallelMergeError('Cherry-pick no longer in progress while resolving conflict', 'CHERRY_PICK_CONTEXT_LOST');
208
+ }
209
+ try {
210
+ (0, merge_git_js_1.runGitCommand)(projectPath, ['-c', 'core.editor=true', 'cherry-pick', '--continue']);
211
+ (0, queries_js_1.approveTask)(db, currentConflictTask.id, 'merge-conflict-reviewer', decision.notes);
212
+ (0, merge_progress_js_1.upsertProgressEntry)(db, sessionId, workstreamId, position, commitSha, 'applied', currentConflictTask.id);
213
+ return 'continued';
214
+ }
215
+ catch (error) {
216
+ const message = error instanceof Error ? error.message : String(error);
217
+ if (/nothing to commit|previous cherry-pick is empty/i.test(message)) {
218
+ (0, merge_git_js_1.runGitCommand)(projectPath, ['cherry-pick', '--skip']);
219
+ (0, merge_progress_js_1.upsertProgressEntry)(db, sessionId, workstreamId, position, commitSha, 'skipped', currentConflictTask.id);
220
+ (0, queries_js_1.updateTaskStatus)(db, currentConflictTask.id, 'completed', 'merge-conflict-reviewer', 'Cherry-pick is now empty after resolution; skipped this commit.');
221
+ return 'skipped';
222
+ }
223
+ throw error;
224
+ }
225
+ }
226
+ }
227
+ //# sourceMappingURL=merge-conflict.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-conflict.js","sourceRoot":"","sources":["../../src/parallel/merge-conflict.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Merge orchestration error type.
3
+ */
4
+ export declare class ParallelMergeError extends Error {
5
+ readonly code: string;
6
+ constructor(message: string, code?: string, options?: {
7
+ cause?: unknown;
8
+ });
9
+ }
10
+ //# sourceMappingURL=merge-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-errors.d.ts","sourceRoot":"","sources":["../../src/parallel/merge-errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAEjB,OAAO,EAAE,MAAM,EAAE,IAAI,SAAyB,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAK1F"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ /**
3
+ * Merge orchestration error type.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ParallelMergeError = void 0;
7
+ class ParallelMergeError extends Error {
8
+ code;
9
+ constructor(message, code = 'PARALLEL_MERGE_ERROR', options) {
10
+ super(message, options);
11
+ this.name = 'ParallelMergeError';
12
+ this.code = code;
13
+ }
14
+ }
15
+ exports.ParallelMergeError = ParallelMergeError;
16
+ //# sourceMappingURL=merge-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-errors.js","sourceRoot":"","sources":["../../src/parallel/merge-errors.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,MAAa,kBAAmB,SAAQ,KAAK;IAC3B,IAAI,CAAS;IAE7B,YAAY,OAAe,EAAE,IAAI,GAAG,sBAAsB,EAAE,OAA6B;QACvF,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AARD,gDAQC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Git helper operations used by parallel merge orchestration.
3
+ */
4
+ export interface GitCommandOptions {
5
+ allowFailure?: boolean;
6
+ maxBuffer?: number;
7
+ timeoutMs?: number;
8
+ }
9
+ export declare function runGitCommand(cwd: string, args: string[], options?: GitCommandOptions): string;
10
+ export declare function cleanTreeHasConflicts(projectPath: string): boolean;
11
+ export declare function hasUnmergedFiles(projectPath: string): boolean;
12
+ export declare function gitStatusLines(projectPath: string): string[];
13
+ export declare function hasCherryPickInProgress(projectPath: string): boolean;
14
+ export declare function getWorkstreamCommitList(projectPath: string, remote: string, workstreamBranch: string, mainBranch: string): string[];
15
+ export declare function getCommitPatch(projectPath: string, commitSha: string): string;
16
+ export declare function getCommitMessage(projectPath: string, commitSha: string): string;
17
+ export declare function getCommitShortSha(commitSha: string): string;
18
+ export declare function getConflictedFiles(projectPath: string): string[];
19
+ export declare function getCachedDiff(projectPath: string): string;
20
+ export declare function getCachedFiles(projectPath: string): string[];
21
+ export declare function isNonFatalFetchResult(output: string): boolean;
22
+ export declare function isMissingRemoteBranchFailure(output: string): boolean;
23
+ export declare function safeRunMergeCommand(projectPath: string, remote: string, branchName: string): void;
24
+ export declare function isNoPushError(output: string): boolean;
25
+ //# sourceMappingURL=merge-git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-git.d.ts","sourceRoot":"","sources":["../../src/parallel/merge-git.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,iBAAsB,GAC9B,MAAM,CA8BR;AAED,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAGlE;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAG7D;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAG5D;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,EACxB,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAuBV;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE/E;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAGhE;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAG5D;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAO7D;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CASpE;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAajG;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGrD"}
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ /**
3
+ * Git helper operations used by parallel merge orchestration.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runGitCommand = runGitCommand;
7
+ exports.cleanTreeHasConflicts = cleanTreeHasConflicts;
8
+ exports.hasUnmergedFiles = hasUnmergedFiles;
9
+ exports.gitStatusLines = gitStatusLines;
10
+ exports.hasCherryPickInProgress = hasCherryPickInProgress;
11
+ exports.getWorkstreamCommitList = getWorkstreamCommitList;
12
+ exports.getCommitPatch = getCommitPatch;
13
+ exports.getCommitMessage = getCommitMessage;
14
+ exports.getCommitShortSha = getCommitShortSha;
15
+ exports.getConflictedFiles = getConflictedFiles;
16
+ exports.getCachedDiff = getCachedDiff;
17
+ exports.getCachedFiles = getCachedFiles;
18
+ exports.isNonFatalFetchResult = isNonFatalFetchResult;
19
+ exports.isMissingRemoteBranchFailure = isMissingRemoteBranchFailure;
20
+ exports.safeRunMergeCommand = safeRunMergeCommand;
21
+ exports.isNoPushError = isNoPushError;
22
+ const node_child_process_1 = require("node:child_process");
23
+ const node_fs_1 = require("node:fs");
24
+ const node_path_1 = require("node:path");
25
+ const merge_errors_js_1 = require("./merge-errors.js");
26
+ function runGitCommand(cwd, args, options = {}) {
27
+ const { allowFailure = false, timeoutMs = 120_000 } = options;
28
+ try {
29
+ return (0, node_child_process_1.execFileSync)('git', args, {
30
+ cwd,
31
+ encoding: 'utf-8',
32
+ stdio: ['pipe', 'pipe', 'pipe'],
33
+ timeout: timeoutMs,
34
+ maxBuffer: options.maxBuffer,
35
+ }).trim();
36
+ }
37
+ catch (error) {
38
+ if (allowFailure) {
39
+ if (error instanceof Error) {
40
+ const err = error;
41
+ return [err.stdout, err.stderr]
42
+ .map((value) => (typeof value === 'string' ? value : value?.toString()))
43
+ .filter(Boolean)
44
+ .join('\n')
45
+ .trim();
46
+ }
47
+ return '';
48
+ }
49
+ const err = error;
50
+ const stderr = err.stderr ? err.stderr.toString() : '';
51
+ const stdout = err.stdout ? err.stdout.toString() : '';
52
+ const details = [stderr, stdout].filter(Boolean).join('\n') || err.message || 'Unknown git error';
53
+ throw new merge_errors_js_1.ParallelMergeError(`Git command failed: git ${args.join(' ')}\n${details}`, 'GIT_ERROR');
54
+ }
55
+ }
56
+ function cleanTreeHasConflicts(projectPath) {
57
+ const status = runGitCommand(projectPath, ['status', '--porcelain']);
58
+ return status.split('\n').some((line) => line.startsWith('UU') || line.includes('U'));
59
+ }
60
+ function hasUnmergedFiles(projectPath) {
61
+ const unmerged = runGitCommand(projectPath, ['diff', '--name-only', '--diff-filter=U']);
62
+ return unmerged.trim().length > 0;
63
+ }
64
+ function gitStatusLines(projectPath) {
65
+ const status = runGitCommand(projectPath, ['status', '--porcelain']);
66
+ return status.split('\n').filter(Boolean);
67
+ }
68
+ function hasCherryPickInProgress(projectPath) {
69
+ return (0, node_fs_1.existsSync)((0, node_path_1.resolve)(projectPath, '.git', 'CHERRY_PICK_HEAD'));
70
+ }
71
+ function getWorkstreamCommitList(projectPath, remote, workstreamBranch, mainBranch) {
72
+ const arg = `${mainBranch}..${remote}/${workstreamBranch}`;
73
+ const output = runGitCommand(projectPath, ['log', arg, '--format=%H', '--reverse'], { allowFailure: true });
74
+ if (/error:|fatal:|error /.test(output.toLowerCase()) && !isMissingRemoteBranchFailure(output)) {
75
+ throw new merge_errors_js_1.ParallelMergeError(`Failed to list commits from ${remote}/${workstreamBranch}: ${output}`, 'COMMIT_LIST_FAILED');
76
+ }
77
+ if (isMissingRemoteBranchFailure(output)) {
78
+ return [];
79
+ }
80
+ return output
81
+ .split('\n')
82
+ .map((line) => line.trim())
83
+ .filter(Boolean);
84
+ }
85
+ function getCommitPatch(projectPath, commitSha) {
86
+ return runGitCommand(projectPath, ['show', commitSha, '--']);
87
+ }
88
+ function getCommitMessage(projectPath, commitSha) {
89
+ return runGitCommand(projectPath, ['log', '-1', '--format=%s%n%b', commitSha]);
90
+ }
91
+ function getCommitShortSha(commitSha) {
92
+ return commitSha.length > 7 ? commitSha.slice(0, 7) : commitSha;
93
+ }
94
+ function getConflictedFiles(projectPath) {
95
+ const output = runGitCommand(projectPath, ['diff', '--name-only', '--diff-filter=U']);
96
+ return output.split('\n').filter(Boolean);
97
+ }
98
+ function getCachedDiff(projectPath) {
99
+ return runGitCommand(projectPath, ['diff', '--cached']);
100
+ }
101
+ function getCachedFiles(projectPath) {
102
+ const output = runGitCommand(projectPath, ['diff', '--cached', '--name-only']);
103
+ return output.split('\n').filter(Boolean);
104
+ }
105
+ function isNonFatalFetchResult(output) {
106
+ const lower = output.toLowerCase();
107
+ return (lower.includes('couldn\'t find remote ref') ||
108
+ lower.includes('does not exist') ||
109
+ lower.includes('fatal: remote ref does not exist'));
110
+ }
111
+ function isMissingRemoteBranchFailure(output) {
112
+ const lower = output.toLowerCase();
113
+ return (lower.includes('couldn\'t find remote ref') ||
114
+ (lower.includes('remote branch') && lower.includes('not found')) ||
115
+ lower.includes('unknown revision or path not in the working tree') ||
116
+ lower.includes('does not exist') ||
117
+ lower.includes('fatal: remote ref does not exist'));
118
+ }
119
+ function safeRunMergeCommand(projectPath, remote, branchName) {
120
+ const output = runGitCommand(projectPath, ['fetch', '--prune', remote, branchName], { allowFailure: true });
121
+ const lower = output.toLowerCase();
122
+ if (!/error:|fatal:/.test(lower)) {
123
+ return;
124
+ }
125
+ if (isNonFatalFetchResult(lower)) {
126
+ return;
127
+ }
128
+ throw new merge_errors_js_1.ParallelMergeError(`Failed to fetch ${branchName} from ${remote}: ${output}`, 'FETCH_FAILED');
129
+ }
130
+ function isNoPushError(output) {
131
+ const lower = output.toLowerCase();
132
+ return lower.includes('error:') || lower.includes('fatal:');
133
+ }
134
+ //# sourceMappingURL=merge-git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-git.js","sourceRoot":"","sources":["../../src/parallel/merge-git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Merge lock management for concurrent merge workers.
3
+ */
4
+ import type Database from 'better-sqlite3';
5
+ export interface MergeLockRecord {
6
+ id: number;
7
+ session_id: string;
8
+ runner_id: string;
9
+ acquired_at: string;
10
+ expires_at: string;
11
+ heartbeat_at: string;
12
+ }
13
+ export interface MergeLockOptions {
14
+ sessionId: string;
15
+ runnerId: string;
16
+ timeoutMinutes: number;
17
+ }
18
+ export declare function isLockExpired(lock: MergeLockRecord): boolean;
19
+ export declare function getLatestMergeLock(db: Database.Database, sessionId: string): MergeLockRecord | null;
20
+ export declare function acquireMergeLock(db: Database.Database, options: MergeLockOptions): {
21
+ acquired: boolean;
22
+ lock?: MergeLockRecord;
23
+ };
24
+ export declare function refreshMergeLock(db: Database.Database, sessionId: string, runnerId: string, timeoutMinutes: number): MergeLockRecord;
25
+ export declare function releaseMergeLock(db: Database.Database, sessionId: string, runnerId: string): void;
26
+ //# sourceMappingURL=merge-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-lock.d.ts","sourceRoot":"","sources":["../../src/parallel/merge-lock.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAG3C,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB;AAUD,wBAAgB,aAAa,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAE5D;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CASnG;AAED,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,OAAO,EAAE,gBAAgB,GACxB;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,eAAe,CAAA;CAAE,CA6B/C;AAED,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACrB,eAAe,CAajB;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAEjG"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * Merge lock management for concurrent merge workers.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isLockExpired = isLockExpired;
7
+ exports.getLatestMergeLock = getLatestMergeLock;
8
+ exports.acquireMergeLock = acquireMergeLock;
9
+ exports.refreshMergeLock = refreshMergeLock;
10
+ exports.releaseMergeLock = releaseMergeLock;
11
+ const merge_errors_js_1 = require("./merge-errors.js");
12
+ function getNowISOString() {
13
+ return new Date().toISOString();
14
+ }
15
+ function utcExpiresAt(timeoutMinutes) {
16
+ return new Date(Date.now() + timeoutMinutes * 60_000).toISOString();
17
+ }
18
+ function isLockExpired(lock) {
19
+ return new Date(lock.expires_at).getTime() < Date.now();
20
+ }
21
+ function getLatestMergeLock(db, sessionId) {
22
+ return db
23
+ .prepare(`SELECT * FROM merge_locks
24
+ WHERE session_id = ?
25
+ ORDER BY acquired_at DESC
26
+ LIMIT 1`)
27
+ .get(sessionId);
28
+ }
29
+ function acquireMergeLock(db, options) {
30
+ const lock = getLatestMergeLock(db, options.sessionId);
31
+ if (lock && !isLockExpired(lock)) {
32
+ if (lock.runner_id === options.runnerId) {
33
+ const refreshed = refreshMergeLock(db, lock.session_id, options.runnerId, options.timeoutMinutes);
34
+ return { acquired: true, lock: refreshed };
35
+ }
36
+ return { acquired: false, lock };
37
+ }
38
+ db.prepare('DELETE FROM merge_locks WHERE session_id = ?').run(options.sessionId);
39
+ const inserted = db.prepare('INSERT INTO merge_locks (session_id, runner_id, acquired_at, expires_at, heartbeat_at) VALUES (?, ?, ?, ?, ?)').run(options.sessionId, options.runnerId, getNowISOString(), utcExpiresAt(options.timeoutMinutes), getNowISOString());
40
+ if (inserted.changes !== 1) {
41
+ return { acquired: false };
42
+ }
43
+ return { acquired: true, lock: getLatestMergeLock(db, options.sessionId) ?? undefined };
44
+ }
45
+ function refreshMergeLock(db, sessionId, runnerId, timeoutMinutes) {
46
+ db.prepare(`UPDATE merge_locks
47
+ SET heartbeat_at = ?, expires_at = ?
48
+ WHERE session_id = ? AND runner_id = ?`).run(getNowISOString(), utcExpiresAt(timeoutMinutes), sessionId, runnerId);
49
+ const lock = getLatestMergeLock(db, sessionId);
50
+ if (!lock) {
51
+ throw new merge_errors_js_1.ParallelMergeError('Lost merge lock unexpectedly', 'MERGE_LOCK_NOT_FOUND');
52
+ }
53
+ return lock;
54
+ }
55
+ function releaseMergeLock(db, sessionId, runnerId) {
56
+ db.prepare('DELETE FROM merge_locks WHERE session_id = ? AND runner_id = ?').run(sessionId, runnerId);
57
+ }
58
+ //# sourceMappingURL=merge-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-lock.js","sourceRoot":"","sources":["../../src/parallel/merge-lock.ts"],"names":[],"mappings":";AAAA;;GAEG;;AA4BH,sCAEC;AAED,gDASC;AAED,4CAgCC;AAED,4CAkBC;AAED,4CAEC;AAhGD,uDAAuD;AAiBvD,SAAS,eAAe;IACtB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,SAAS,YAAY,CAAC,cAAsB;IAC1C,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;AACtE,CAAC;AAED,SAAgB,aAAa,CAAC,IAAqB;IACjD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAC1D,CAAC;AAED,SAAgB,kBAAkB,CAAC,EAAqB,EAAE,SAAiB;IACzE,OAAO,EAAE;SACN,OAAO,CACN;;;eAGS,CACV;SACA,GAAG,CAAC,SAAS,CAA2B,CAAC;AAC9C,CAAC;AAED,SAAgB,gBAAgB,CAC9B,EAAqB,EACrB,OAAyB;IAEzB,MAAM,IAAI,GAAG,kBAAkB,CAAC,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAEvD,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;YACxC,MAAM,SAAS,GAAG,gBAAgB,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;YAClG,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC7C,CAAC;QAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;IAED,EAAE,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAElF,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CACzB,+GAA+G,CAChH,CAAC,GAAG,CACH,OAAO,CAAC,SAAS,EACjB,OAAO,CAAC,QAAQ,EAChB,eAAe,EAAE,EACjB,YAAY,CAAC,OAAO,CAAC,cAAc,CAAC,EACpC,eAAe,EAAE,CAClB,CAAC;IAEF,IAAI,QAAQ,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,kBAAkB,CAAC,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,SAAS,EAAE,CAAC;AAC1F,CAAC;AAED,SAAgB,gBAAgB,CAC9B,EAAqB,EACrB,SAAiB,EACjB,QAAgB,EAChB,cAAsB;IAEtB,EAAE,CAAC,OAAO,CACR;;4CAEwC,CACzC,CAAC,GAAG,CAAC,eAAe,EAAE,EAAE,YAAY,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAE5E,MAAM,IAAI,GAAG,kBAAkB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,oCAAkB,CAAC,8BAA8B,EAAE,sBAAsB,CAAC,CAAC;IACvF,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,gBAAgB,CAAC,EAAqB,EAAE,SAAiB,EAAE,QAAgB;IACzF,EAAE,CAAC,OAAO,CAAC,gEAAgE,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AACxG,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Merge progress persistence for crash recovery.
3
+ */
4
+ import type Database from 'better-sqlite3';
5
+ export interface MergeProgressRow {
6
+ id: number;
7
+ session_id: string;
8
+ workstream_id: string;
9
+ position: number;
10
+ commit_sha: string;
11
+ status: 'applied' | 'conflict' | 'skipped';
12
+ conflict_task_id: string | null;
13
+ created_at: string;
14
+ applied_at: string | null;
15
+ }
16
+ export declare function listMergeProgress(db: Database.Database, sessionId: string): MergeProgressRow[];
17
+ export declare function clearProgressEntry(db: Database.Database, sessionId: string, workstreamId: string, position: number): void;
18
+ export declare function upsertProgressEntry(db: Database.Database, sessionId: string, workstreamId: string, position: number, commitSha: string, status: MergeProgressRow['status'], conflictTaskId?: string | null): void;
19
+ export declare function getMergeProgressForWorkstream(rows: MergeProgressRow[], workstreamId: string): MergeProgressRow[];
20
+ //# sourceMappingURL=merge-progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-progress.d.ts","sourceRoot":"","sources":["../../src/parallel/merge-progress.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAMD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAS9F;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,IAAI,CAIN;AAED,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAClC,cAAc,GAAE,MAAM,GAAG,IAAW,GACnC,IAAI,CASN;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,gBAAgB,EAAE,EACxB,YAAY,EAAE,MAAM,GACnB,gBAAgB,EAAE,CAIpB"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ /**
3
+ * Merge progress persistence for crash recovery.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.listMergeProgress = listMergeProgress;
7
+ exports.clearProgressEntry = clearProgressEntry;
8
+ exports.upsertProgressEntry = upsertProgressEntry;
9
+ exports.getMergeProgressForWorkstream = getMergeProgressForWorkstream;
10
+ function getNowISOString() {
11
+ return new Date().toISOString();
12
+ }
13
+ function listMergeProgress(db, sessionId) {
14
+ return db
15
+ .prepare(`SELECT id, session_id, workstream_id, position, commit_sha, status, conflict_task_id, created_at, applied_at
16
+ FROM merge_progress
17
+ WHERE session_id = ?
18
+ ORDER BY workstream_id, position ASC`)
19
+ .all(sessionId);
20
+ }
21
+ function clearProgressEntry(db, sessionId, workstreamId, position) {
22
+ db.prepare('DELETE FROM merge_progress WHERE session_id = ? AND workstream_id = ? AND position = ?').run(sessionId, workstreamId, position);
23
+ }
24
+ function upsertProgressEntry(db, sessionId, workstreamId, position, commitSha, status, conflictTaskId = null) {
25
+ const payloadApplied = status === 'applied' ? getNowISOString() : null;
26
+ clearProgressEntry(db, sessionId, workstreamId, position);
27
+ db.prepare(`INSERT INTO merge_progress
28
+ (session_id, workstream_id, position, commit_sha, status, conflict_task_id, applied_at)
29
+ VALUES (?, ?, ?, ?, ?, ?, ?)`).run(sessionId, workstreamId, position, commitSha, status, conflictTaskId, payloadApplied);
30
+ }
31
+ function getMergeProgressForWorkstream(rows, workstreamId) {
32
+ return rows
33
+ .filter((row) => row.workstream_id === workstreamId)
34
+ .sort((left, right) => left.position - right.position);
35
+ }
36
+ //# sourceMappingURL=merge-progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-progress.js","sourceRoot":"","sources":["../../src/parallel/merge-progress.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAoBH,8CASC;AAED,gDASC;AAED,kDAiBC;AAED,sEAOC;AApDD,SAAS,eAAe;IACtB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,SAAgB,iBAAiB,CAAC,EAAqB,EAAE,SAAiB;IACxE,OAAO,EAAE;SACN,OAAO,CACN;;;4CAGsC,CACvC;SACA,GAAG,CAAC,SAAS,CAAuB,CAAC;AAC1C,CAAC;AAED,SAAgB,kBAAkB,CAChC,EAAqB,EACrB,SAAiB,EACjB,YAAoB,EACpB,QAAgB;IAEhB,EAAE,CAAC,OAAO,CACR,wFAAwF,CACzF,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,SAAgB,mBAAmB,CACjC,EAAqB,EACrB,SAAiB,EACjB,YAAoB,EACpB,QAAgB,EAChB,SAAiB,EACjB,MAAkC,EAClC,iBAAgC,IAAI;IAEpC,MAAM,cAAc,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAEvE,kBAAkB,CAAC,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;IAC1D,EAAE,CAAC,OAAO,CACR;;kCAE8B,CAC/B,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC;AAC9F,CAAC;AAED,SAAgB,6BAA6B,CAC3C,IAAwB,EACxB,YAAoB;IAEpB,OAAO,IAAI;SACR,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,aAAa,KAAK,YAAY,CAAC;SACnD,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC3D,CAAC"}