@sudocode-ai/cli 0.1.16 → 0.1.18-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/better-sqlite3-loader.d.ts +9 -0
- package/dist/better-sqlite3-loader.d.ts.map +1 -0
- package/dist/better-sqlite3-loader.js +24 -0
- package/dist/better-sqlite3-loader.js.map +1 -0
- package/dist/cli/merge-commands.d.ts.map +1 -1
- package/dist/cli/merge-commands.js +290 -15
- package/dist/cli/merge-commands.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +2 -2
- package/dist/db.js.map +1 -1
- package/dist/git-merge.d.ts +88 -0
- package/dist/git-merge.d.ts.map +1 -0
- package/dist/git-merge.js +214 -0
- package/dist/git-merge.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/merge-resolver.d.ts +73 -1
- package/dist/merge-resolver.d.ts.map +1 -1
- package/dist/merge-resolver.js +420 -5
- package/dist/merge-resolver.js.map +1 -1
- package/dist/watcher.d.ts +6 -0
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +15 -1
- package/dist/watcher.js.map +1 -1
- package/dist/yaml-conflict-resolver.d.ts +91 -0
- package/dist/yaml-conflict-resolver.d.ts.map +1 -0
- package/dist/yaml-conflict-resolver.js +197 -0
- package/dist/yaml-conflict-resolver.js.map +1 -0
- package/dist/yaml-converter.d.ts +68 -0
- package/dist/yaml-converter.d.ts.map +1 -0
- package/dist/yaml-converter.js +109 -0
- package/dist/yaml-converter.js.map +1 -0
- package/package.json +9 -3
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Merge-File Wrapper
|
|
3
|
+
*
|
|
4
|
+
* Wrapper around `git merge-file` command for three-way merging of YAML content.
|
|
5
|
+
* Enables git's native three-way merge algorithm to work on YAML representations.
|
|
6
|
+
*
|
|
7
|
+
* Security: Uses execFile (not exec) to prevent shell injection vulnerabilities.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Result of a merge operation
|
|
11
|
+
*/
|
|
12
|
+
export interface MergeResult {
|
|
13
|
+
/** Whether the merge completed without conflicts */
|
|
14
|
+
success: boolean;
|
|
15
|
+
/** The merged content (may include conflict markers if success=false) */
|
|
16
|
+
content: string;
|
|
17
|
+
/** Whether conflicts were detected */
|
|
18
|
+
hasConflicts: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Three-way merge input versions
|
|
22
|
+
*/
|
|
23
|
+
export interface MergeInput {
|
|
24
|
+
/** Base version (common ancestor) */
|
|
25
|
+
base: string;
|
|
26
|
+
/** Our version (current/local changes) */
|
|
27
|
+
ours: string;
|
|
28
|
+
/** Their version (incoming changes) */
|
|
29
|
+
theirs: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Perform three-way merge using git merge-file
|
|
33
|
+
*
|
|
34
|
+
* This function wraps the `git merge-file` command to provide three-way merging
|
|
35
|
+
* of YAML content. It creates temporary files for the merge operation and cleans
|
|
36
|
+
* them up afterwards.
|
|
37
|
+
*
|
|
38
|
+
* Security: Uses execFileSync with array arguments to prevent shell injection.
|
|
39
|
+
*
|
|
40
|
+
* Git merge-file exit codes:
|
|
41
|
+
* - 0: Clean merge, no conflicts
|
|
42
|
+
* - 1: Conflicts detected (most common, merge produces output with conflict markers)
|
|
43
|
+
* - 2+: Can indicate conflicts OR fatal errors
|
|
44
|
+
*
|
|
45
|
+
* Strategy: If git produced output (file exists and has content), treat as conflict
|
|
46
|
+
* scenario regardless of exit code. Only throw if no output was produced.
|
|
47
|
+
*
|
|
48
|
+
* @param input - The three versions to merge (base, ours, theirs)
|
|
49
|
+
* @returns MergeResult - The merge result with success status and content
|
|
50
|
+
* @throws Error if git command fails fatally (no output produced)
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const result = mergeYamlContent({
|
|
55
|
+
* base: 'title: Original\nstatus: open',
|
|
56
|
+
* ours: 'title: Updated\nstatus: open',
|
|
57
|
+
* theirs: 'title: Original\nstatus: closed'
|
|
58
|
+
* });
|
|
59
|
+
*
|
|
60
|
+
* if (result.success) {
|
|
61
|
+
* console.log('Clean merge:', result.content);
|
|
62
|
+
* } else {
|
|
63
|
+
* console.log('Conflicts detected:', result.content);
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare function mergeYamlContent(input: MergeInput): MergeResult;
|
|
68
|
+
/**
|
|
69
|
+
* Read content from a specific git index stage
|
|
70
|
+
*
|
|
71
|
+
* During a merge conflict, git maintains three versions in the index:
|
|
72
|
+
* - Stage 1: Base version (common ancestor)
|
|
73
|
+
* - Stage 2: Ours version (current branch)
|
|
74
|
+
* - Stage 3: Theirs version (incoming branch)
|
|
75
|
+
*
|
|
76
|
+
* @param filePath - Path to the file (relative to git root or absolute)
|
|
77
|
+
* @param stage - Git stage number (1=base, 2=ours, 3=theirs)
|
|
78
|
+
* @returns File content as string, or null if stage doesn't exist
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const base = readGitStage('.sudocode/issues/issues.jsonl', 1);
|
|
83
|
+
* const ours = readGitStage('.sudocode/issues/issues.jsonl', 2);
|
|
84
|
+
* const theirs = readGitStage('.sudocode/issues/issues.jsonl', 3);
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export declare function readGitStage(filePath: string, stage: 1 | 2 | 3): string | null;
|
|
88
|
+
//# sourceMappingURL=git-merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-merge.d.ts","sourceRoot":"","sources":["../src/git-merge.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,oDAAoD;IACpD,OAAO,EAAE,OAAO,CAAC;IACjB,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAkG/D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,IAAI,CAiE9E"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Merge-File Wrapper
|
|
3
|
+
*
|
|
4
|
+
* Wrapper around `git merge-file` command for three-way merging of YAML content.
|
|
5
|
+
* Enables git's native three-way merge algorithm to work on YAML representations.
|
|
6
|
+
*
|
|
7
|
+
* Security: Uses execFile (not exec) to prevent shell injection vulnerabilities.
|
|
8
|
+
*/
|
|
9
|
+
import { execFileSync } from 'child_process';
|
|
10
|
+
import * as fs from 'fs';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import * as os from 'os';
|
|
13
|
+
/**
|
|
14
|
+
* Perform three-way merge using git merge-file
|
|
15
|
+
*
|
|
16
|
+
* This function wraps the `git merge-file` command to provide three-way merging
|
|
17
|
+
* of YAML content. It creates temporary files for the merge operation and cleans
|
|
18
|
+
* them up afterwards.
|
|
19
|
+
*
|
|
20
|
+
* Security: Uses execFileSync with array arguments to prevent shell injection.
|
|
21
|
+
*
|
|
22
|
+
* Git merge-file exit codes:
|
|
23
|
+
* - 0: Clean merge, no conflicts
|
|
24
|
+
* - 1: Conflicts detected (most common, merge produces output with conflict markers)
|
|
25
|
+
* - 2+: Can indicate conflicts OR fatal errors
|
|
26
|
+
*
|
|
27
|
+
* Strategy: If git produced output (file exists and has content), treat as conflict
|
|
28
|
+
* scenario regardless of exit code. Only throw if no output was produced.
|
|
29
|
+
*
|
|
30
|
+
* @param input - The three versions to merge (base, ours, theirs)
|
|
31
|
+
* @returns MergeResult - The merge result with success status and content
|
|
32
|
+
* @throws Error if git command fails fatally (no output produced)
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const result = mergeYamlContent({
|
|
37
|
+
* base: 'title: Original\nstatus: open',
|
|
38
|
+
* ours: 'title: Updated\nstatus: open',
|
|
39
|
+
* theirs: 'title: Original\nstatus: closed'
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* if (result.success) {
|
|
43
|
+
* console.log('Clean merge:', result.content);
|
|
44
|
+
* } else {
|
|
45
|
+
* console.log('Conflicts detected:', result.content);
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function mergeYamlContent(input) {
|
|
50
|
+
// Create temporary directory for merge files
|
|
51
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'git-merge-'));
|
|
52
|
+
// Temp file paths
|
|
53
|
+
const basePath = path.join(tmpDir, 'base.yaml');
|
|
54
|
+
const oursPath = path.join(tmpDir, 'ours.yaml');
|
|
55
|
+
const theirsPath = path.join(tmpDir, 'theirs.yaml');
|
|
56
|
+
// Track whether base is empty (simulated 3-way merge)
|
|
57
|
+
const baseIsEmpty = input.base.length === 0;
|
|
58
|
+
try {
|
|
59
|
+
// Write content to temp files
|
|
60
|
+
fs.writeFileSync(basePath, input.base, 'utf8');
|
|
61
|
+
fs.writeFileSync(oursPath, input.ours, 'utf8');
|
|
62
|
+
fs.writeFileSync(theirsPath, input.theirs, 'utf8');
|
|
63
|
+
// Execute git merge-file using execFileSync (safe from shell injection)
|
|
64
|
+
try {
|
|
65
|
+
execFileSync('git', ['merge-file', oursPath, basePath, theirsPath], {
|
|
66
|
+
encoding: 'utf8',
|
|
67
|
+
});
|
|
68
|
+
// Exit code 0 means clean merge
|
|
69
|
+
const mergedContent = fs.readFileSync(oursPath, 'utf8');
|
|
70
|
+
return {
|
|
71
|
+
success: true,
|
|
72
|
+
content: mergedContent,
|
|
73
|
+
hasConflicts: false,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
// Git merge-file exit codes:
|
|
78
|
+
// - 0: Clean merge (handled above, no error thrown)
|
|
79
|
+
// - 1: Conflicts detected (most common)
|
|
80
|
+
// - 2+: Can indicate conflicts OR fatal errors
|
|
81
|
+
//
|
|
82
|
+
// Strategy: If git produced output (file exists and has content),
|
|
83
|
+
// treat as conflict scenario regardless of exit code.
|
|
84
|
+
// Only throw if no output was produced (indicates real error).
|
|
85
|
+
const exitCode = error.status || error.code || 'unknown';
|
|
86
|
+
// Debug: log what we got
|
|
87
|
+
if (process.env.DEBUG_GIT_MERGE) {
|
|
88
|
+
console.log('Git merge-file error:', {
|
|
89
|
+
status: error.status,
|
|
90
|
+
code: error.code,
|
|
91
|
+
baseIsEmpty,
|
|
92
|
+
stderr: error.stderr?.toString(),
|
|
93
|
+
stdout: error.stdout?.toString(),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
// Try to read the output file - if it has content, this is a conflict scenario
|
|
97
|
+
if (error.status > 0) {
|
|
98
|
+
try {
|
|
99
|
+
const mergedContent = fs.readFileSync(oursPath, 'utf8');
|
|
100
|
+
// Validate that git produced output (not a real error)
|
|
101
|
+
if (mergedContent.length > 0) {
|
|
102
|
+
return {
|
|
103
|
+
success: false,
|
|
104
|
+
content: mergedContent,
|
|
105
|
+
hasConflicts: true,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// If no output, this is likely a real error - fall through to throw
|
|
109
|
+
}
|
|
110
|
+
catch (readError) {
|
|
111
|
+
// File read failed - fall through to throw with details
|
|
112
|
+
const stderr = error.stderr?.toString().trim();
|
|
113
|
+
const stdout = error.stdout?.toString().trim();
|
|
114
|
+
const errorDetails = stderr || stdout || error.message || 'Unknown error';
|
|
115
|
+
throw new Error(`Git merge-file command failed (exit code ${exitCode}, baseIsEmpty=${baseIsEmpty}, fileExists=${fs.existsSync(oursPath)}, readError=${readError}): ${errorDetails}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// No exit code or negative exit code means a fatal error occurred
|
|
119
|
+
// Include stderr output which contains the actual git error message
|
|
120
|
+
const stderr = error.stderr?.toString().trim();
|
|
121
|
+
const stdout = error.stdout?.toString().trim();
|
|
122
|
+
const errorDetails = stderr || stdout || error.message || 'Unknown error';
|
|
123
|
+
throw new Error(`Git merge-file command failed (status=${error.status}, code=${error.code}, exitCode=${exitCode}, baseIsEmpty=${baseIsEmpty}, baseLength=${input.base.length}, oursLength=${input.ours.length}, theirsLength=${input.theirs.length}): ${errorDetails}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
// Clean up temp files and directory
|
|
128
|
+
try {
|
|
129
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
130
|
+
}
|
|
131
|
+
catch (cleanupError) {
|
|
132
|
+
// Log cleanup errors but don't throw
|
|
133
|
+
console.error('Warning: Failed to clean up temp files:', cleanupError);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Read content from a specific git index stage
|
|
139
|
+
*
|
|
140
|
+
* During a merge conflict, git maintains three versions in the index:
|
|
141
|
+
* - Stage 1: Base version (common ancestor)
|
|
142
|
+
* - Stage 2: Ours version (current branch)
|
|
143
|
+
* - Stage 3: Theirs version (incoming branch)
|
|
144
|
+
*
|
|
145
|
+
* @param filePath - Path to the file (relative to git root or absolute)
|
|
146
|
+
* @param stage - Git stage number (1=base, 2=ours, 3=theirs)
|
|
147
|
+
* @returns File content as string, or null if stage doesn't exist
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* const base = readGitStage('.sudocode/issues/issues.jsonl', 1);
|
|
152
|
+
* const ours = readGitStage('.sudocode/issues/issues.jsonl', 2);
|
|
153
|
+
* const theirs = readGitStage('.sudocode/issues/issues.jsonl', 3);
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export function readGitStage(filePath, stage) {
|
|
157
|
+
try {
|
|
158
|
+
// Convert absolute path to relative path from repo root
|
|
159
|
+
let relativePath = filePath;
|
|
160
|
+
if (path.isAbsolute(filePath)) {
|
|
161
|
+
const repoRoot = execFileSync('git', ['rev-parse', '--show-toplevel'], {
|
|
162
|
+
encoding: 'utf8',
|
|
163
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
164
|
+
}).trim();
|
|
165
|
+
relativePath = path.relative(repoRoot, filePath);
|
|
166
|
+
}
|
|
167
|
+
// Use git checkout-index to extract stage to temp file
|
|
168
|
+
// This avoids buffer size limits by having git write directly to disk
|
|
169
|
+
// Format: "tempfile\tpath" (tempfile is relative to repo root)
|
|
170
|
+
const output = execFileSync('git', ['checkout-index', `--stage=${stage}`, '--temp', relativePath], {
|
|
171
|
+
encoding: 'utf8',
|
|
172
|
+
cwd: path.isAbsolute(filePath)
|
|
173
|
+
? execFileSync('git', ['rev-parse', '--show-toplevel'], { encoding: 'utf8' }).trim()
|
|
174
|
+
: undefined,
|
|
175
|
+
}).trim();
|
|
176
|
+
// Parse output: "tempfile\toriginalpath"
|
|
177
|
+
const [tempFile] = output.split('\t');
|
|
178
|
+
if (!tempFile) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
// Get repo root to resolve temp file path (git outputs relative to repo root)
|
|
182
|
+
const repoRoot = execFileSync('git', ['rev-parse', '--show-toplevel'], {
|
|
183
|
+
encoding: 'utf8',
|
|
184
|
+
}).trim();
|
|
185
|
+
const tempFilePath = path.join(repoRoot, tempFile);
|
|
186
|
+
try {
|
|
187
|
+
// Read content from git's temp file
|
|
188
|
+
const content = fs.readFileSync(tempFilePath, 'utf8');
|
|
189
|
+
return content;
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
// Always clean up the temp file git created
|
|
193
|
+
try {
|
|
194
|
+
fs.unlinkSync(tempFilePath);
|
|
195
|
+
}
|
|
196
|
+
catch (unlinkError) {
|
|
197
|
+
// Best effort cleanup - don't fail if file already gone
|
|
198
|
+
if (process.env.DEBUG_GIT_MERGE) {
|
|
199
|
+
console.warn('Warning: Failed to clean up temp file:', unlinkError);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
// Stage doesn't exist (e.g., file added in one branch, deleted in another)
|
|
206
|
+
// This is expected and not an error
|
|
207
|
+
if (error.status === 128 || error.status === 1) {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
// Re-throw unexpected errors
|
|
211
|
+
throw new Error(`Failed to read git stage ${stage} for ${filePath}: ${error.message}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=git-merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-merge.js","sourceRoot":"","sources":["../src/git-merge.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC"}
|
package/dist/merge-resolver.d.ts
CHANGED
|
@@ -70,16 +70,88 @@ export declare function hasGitConflictMarkers(filePath: string): boolean;
|
|
|
70
70
|
export declare function parseMergeConflictFile(content: string): ConflictSection[];
|
|
71
71
|
/**
|
|
72
72
|
* Merge metadata from multiple versions of same entity
|
|
73
|
+
*
|
|
74
|
+
* USE FOR: Two-way merge scenarios (manual conflict resolution)
|
|
75
|
+
* Merges both array fields (union) and scalar fields (latest-wins)
|
|
73
76
|
*/
|
|
74
77
|
export declare function mergeMetadata<T extends JSONLEntity>(entities: T[]): T;
|
|
78
|
+
/**
|
|
79
|
+
* Merge ONLY array fields from multiple versions (union semantics)
|
|
80
|
+
*
|
|
81
|
+
* USE FOR: Three-way merge scenarios (git merge driver)
|
|
82
|
+
* Only merges array fields (relationships, tags, feedback)
|
|
83
|
+
* Scalar fields (status, priority, title, etc.) are NOT merged
|
|
84
|
+
*
|
|
85
|
+
* This allows git merge-file to see actual differences in scalar fields
|
|
86
|
+
* for proper three-way merge semantics.
|
|
87
|
+
*/
|
|
88
|
+
export declare function mergeArrayFields<T extends JSONLEntity>(entities: T[]): Partial<T>;
|
|
89
|
+
/**
|
|
90
|
+
* Resolve git conflict markers in YAML content using latest-wins per block
|
|
91
|
+
*
|
|
92
|
+
* When git merge-file produces conflicts in YAML, this function resolves
|
|
93
|
+
* each conflict block individually while preserving cleanly merged sections.
|
|
94
|
+
*
|
|
95
|
+
* @param yamlWithConflicts - YAML content containing git conflict markers
|
|
96
|
+
* @param useOurs - If true, use "ours" side for conflicts; if false, use "theirs"
|
|
97
|
+
* @returns Resolved YAML content without conflict markers
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* const yaml = `title: test
|
|
102
|
+
* <<<<<<< ours
|
|
103
|
+
* content: ours text
|
|
104
|
+
* =======
|
|
105
|
+
* content: theirs text
|
|
106
|
+
* >>>>>>> theirs
|
|
107
|
+
* priority: 3`;
|
|
108
|
+
*
|
|
109
|
+
* const resolved = resolveYamlConflicts(yaml, true);
|
|
110
|
+
* // Returns: "title: test\ncontent: ours text\npriority: 3"
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export declare function resolveYamlConflicts(yamlWithConflicts: string, useOurs: boolean): string;
|
|
75
114
|
/**
|
|
76
115
|
* Resolve all entities using UUID-based deduplication
|
|
77
116
|
* Handles different UUIDs, same UUID conflicts, and metadata merging
|
|
117
|
+
*
|
|
118
|
+
* USE CASE: TWO-WAY MERGE
|
|
119
|
+
* - Manual conflict resolution (sudocode resolve-conflicts)
|
|
120
|
+
* - Conflicts already isolated by git conflict markers
|
|
121
|
+
* - No base version available (git index cleared after conflict)
|
|
122
|
+
* - Simple UUID deduplication is sufficient and faster
|
|
123
|
+
* - No benefit from YAML expansion overhead
|
|
124
|
+
*
|
|
125
|
+
* DO NOT USE FOR: Three-way merge with base/ours/theirs
|
|
126
|
+
* For that case, use mergeThreeWay() instead.
|
|
78
127
|
*/
|
|
79
128
|
export declare function resolveEntities<T extends JSONLEntity>(entities: T[], options?: ResolveOptions): ResolvedResult<T>;
|
|
80
129
|
/**
|
|
81
130
|
* Three-way merge for git merge driver
|
|
82
|
-
*
|
|
131
|
+
* Uses hybrid approach: field-level merge for scalars + line-level merge for multi-line text
|
|
132
|
+
*
|
|
133
|
+
* USE CASE: THREE-WAY MERGE
|
|
134
|
+
* - Git merge driver operations (automatic merge)
|
|
135
|
+
* - Worktree sync with true base/ours/theirs versions
|
|
136
|
+
* - Field-level merging preserves changes from either branch
|
|
137
|
+
*
|
|
138
|
+
* DO NOT USE FOR: Manual conflict resolution (use resolveEntities)
|
|
139
|
+
*
|
|
140
|
+
* This function implements true three-way merge semantics:
|
|
141
|
+
* 1. Group entities by UUID across base/ours/theirs
|
|
142
|
+
* 2. Handle deletion cases (modification wins over deletion)
|
|
143
|
+
* 3. Merge array fields FIRST (tags, relationships, feedback) with union semantics
|
|
144
|
+
* 4. Field-level three-way merge for SCALAR fields only (status, priority, etc.)
|
|
145
|
+
* 5. YAML + git merge-file for multi-line text fields (content, description)
|
|
146
|
+
* 6. Handle ID collisions (hash conflicts with .1, .2 suffixes)
|
|
147
|
+
* 7. Sort by created_at (git-friendly)
|
|
148
|
+
*
|
|
149
|
+
* Field-level three-way merge logic:
|
|
150
|
+
* - If base == ours == theirs: use any value (no changes)
|
|
151
|
+
* - If base == ours && base != theirs: use theirs (only theirs changed)
|
|
152
|
+
* - If base == theirs && base != ours: use ours (only ours changed)
|
|
153
|
+
* - If base != ours && base != theirs && ours == theirs: use either (both made same change)
|
|
154
|
+
* - If base != ours && base != theirs && ours != theirs: conflict -> latest wins
|
|
83
155
|
*/
|
|
84
156
|
export declare function mergeThreeWay<T extends JSONLEntity>(base: T[], ours: T[], theirs: T[]): ResolvedResult<T>;
|
|
85
157
|
//# sourceMappingURL=merge-resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-resolver.d.ts","sourceRoot":"","sources":["../src/merge-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"merge-resolver.d.ts","sourceRoot":"","sources":["../src/merge-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIxD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;IAC3B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,EAAE,CAAC;IACd,KAAK,EAAE,eAAe,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,kBAAkB,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,iBAAiB,GAAG,wBAAwB,GAAG,mBAAmB,CAAC;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAW/D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,EAAE,CA0FzE;AAmCD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,WAAW,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,CAAC,CAsDrE;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,WAAW,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAkDjF;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAAC,iBAAiB,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAgBxF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,WAAW,EACnD,QAAQ,EAAE,CAAC,EAAE,EACb,OAAO,GAAE,cAAmB,GAC3B,cAAc,CAAC,CAAC,CAAC,CAuHnB;AAsDD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,WAAW,EACjD,IAAI,EAAE,CAAC,EAAE,EACT,IAAI,EAAE,CAAC,EAAE,EACT,MAAM,EAAE,CAAC,EAAE,GACV,cAAc,CAAC,CAAC,CAAC,CAmSnB"}
|