@motivation-labs/crosscheck 0.13.0-beta.13 → 0.13.0-beta.18
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/__tests__/onboard-preservation.test.js +67 -1
- package/dist/__tests__/onboard-preservation.test.js.map +1 -1
- package/dist/commands/onboard.d.ts +2 -0
- package/dist/commands/onboard.d.ts.map +1 -1
- package/dist/commands/onboard.js +53 -6
- package/dist/commands/onboard.js.map +1 -1
- package/dist/lib/board.d.ts.map +1 -1
- package/dist/lib/board.js +12 -4
- package/dist/lib/board.js.map +1 -1
- package/dist/lib/runner.d.ts.map +1 -1
- package/dist/lib/runner.js +144 -0
- package/dist/lib/runner.js.map +1 -1
- package/dist/lib/workflow.d.ts +9 -8
- package/dist/lib/workflow.d.ts.map +1 -1
- package/dist/lib/workflow.js +7 -1
- package/dist/lib/workflow.js.map +1 -1
- package/dist/reviewers/conflict-resolve.d.ts +6 -0
- package/dist/reviewers/conflict-resolve.d.ts.map +1 -0
- package/dist/reviewers/conflict-resolve.js +142 -0
- package/dist/reviewers/conflict-resolve.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { execa } from 'execa';
|
|
5
|
+
import { applyEdit } from './fix.js';
|
|
6
|
+
const PROMPT_TEMPLATE = `This pull request has merge conflicts. Resolve all conflict markers in the files listed below.
|
|
7
|
+
|
|
8
|
+
PR title: {PR_TITLE}
|
|
9
|
+
|
|
10
|
+
Conflicted files:
|
|
11
|
+
{CONFLICTED_FILES}
|
|
12
|
+
|
|
13
|
+
{EXTRA_INSTRUCTIONS}
|
|
14
|
+
|
|
15
|
+
Rules for resolving each conflict:
|
|
16
|
+
- Keep ALL meaningful changes from both sides if they are not directly contradictory
|
|
17
|
+
- When both sides modify the same line, prefer the incoming branch changes (the >>>>>>> side) unless they clearly break existing logic
|
|
18
|
+
- Remove ALL conflict markers: <<<<<<<, =======, >>>>>>>
|
|
19
|
+
|
|
20
|
+
For each file, output ONLY the resolved conflict regions using this format:
|
|
21
|
+
|
|
22
|
+
<edit path="relative/path/to/file.ext">
|
|
23
|
+
<old>
|
|
24
|
+
exact conflict region including all markers (copy verbatim from the file)
|
|
25
|
+
</old>
|
|
26
|
+
<new>
|
|
27
|
+
resolved content with no conflict markers
|
|
28
|
+
</new>
|
|
29
|
+
</edit>
|
|
30
|
+
|
|
31
|
+
Rules for <edit> blocks:
|
|
32
|
+
- <old> must match the file content EXACTLY, including conflict markers and surrounding lines
|
|
33
|
+
- <new> must not contain ANY conflict markers
|
|
34
|
+
- Include 2–3 context lines around the conflict region to make the match unambiguous
|
|
35
|
+
- One block per conflict region; multiple blocks per file are fine
|
|
36
|
+
- Output ONLY <edit> blocks. No other text.`;
|
|
37
|
+
// Returns file paths that have unmerged conflict markers (git status: UU/AA/DD).
|
|
38
|
+
export function findConflictedFiles(tmpDir) {
|
|
39
|
+
try {
|
|
40
|
+
const out = execSync('git diff --name-only --diff-filter=U', { cwd: tmpDir, encoding: 'utf8' });
|
|
41
|
+
return out.trim().split('\n').filter(Boolean);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function buildConflictedFilesBlock(tmpDir, filePaths) {
|
|
48
|
+
return filePaths.map(f => {
|
|
49
|
+
try {
|
|
50
|
+
const content = readFileSync(join(tmpDir, f), 'utf8').slice(0, 4000);
|
|
51
|
+
return `### ${f}\n\`\`\`\n${content}\n\`\`\``;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return `### ${f}\n(could not read file)`;
|
|
55
|
+
}
|
|
56
|
+
}).join('\n\n');
|
|
57
|
+
}
|
|
58
|
+
export async function runConflictResolveStep(tmpDir, prTitle, instructions) {
|
|
59
|
+
const conflictedFiles = findConflictedFiles(tmpDir);
|
|
60
|
+
if (conflictedFiles.length === 0)
|
|
61
|
+
return { appliedCount: 0 };
|
|
62
|
+
const filesBlock = buildConflictedFilesBlock(tmpDir, conflictedFiles);
|
|
63
|
+
const prompt = PROMPT_TEMPLATE
|
|
64
|
+
.replace('{PR_TITLE}', prTitle)
|
|
65
|
+
.replace('{CONFLICTED_FILES}', filesBlock)
|
|
66
|
+
.replace('{EXTRA_INSTRUCTIONS}', instructions ? `Additional instructions: ${instructions}` : '');
|
|
67
|
+
let output = '';
|
|
68
|
+
let tokensUsed;
|
|
69
|
+
try {
|
|
70
|
+
const { stdout } = await execa('claude', ['--print', '--output-format', 'json'], {
|
|
71
|
+
input: prompt,
|
|
72
|
+
timeout: 180_000,
|
|
73
|
+
env: { ...process.env },
|
|
74
|
+
});
|
|
75
|
+
const raw = stdout.trim();
|
|
76
|
+
try {
|
|
77
|
+
const parsed = JSON.parse(raw);
|
|
78
|
+
output = typeof parsed.result === 'string' ? parsed.result : raw;
|
|
79
|
+
const inTok = parsed.usage?.input_tokens;
|
|
80
|
+
const outTok = parsed.usage?.output_tokens;
|
|
81
|
+
tokensUsed = typeof inTok === 'number' && typeof outTok === 'number' ? inTok + outTok : undefined;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
output = raw;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
89
|
+
if (/not logged in|auth|credential/i.test(msg)) {
|
|
90
|
+
throw new Error('claude auth failure during conflict-resolve step — run: claude auth login');
|
|
91
|
+
}
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
if (!output || output === 'NO_CHANGES')
|
|
95
|
+
return { appliedCount: 0, tokensUsed };
|
|
96
|
+
let appliedCount = 0;
|
|
97
|
+
const editRegex = /<edit path="([^"]+)">([\s\S]*?)<\/edit>/g;
|
|
98
|
+
const fileEdits = new Map();
|
|
99
|
+
const fileCache = new Map();
|
|
100
|
+
let match;
|
|
101
|
+
while ((match = editRegex.exec(output)) !== null) {
|
|
102
|
+
const [, filePath, body] = match;
|
|
103
|
+
if (filePath.includes('..') || filePath.startsWith('/'))
|
|
104
|
+
continue;
|
|
105
|
+
const oldMatch = body.match(/<old>([\s\S]*?)<\/old>/);
|
|
106
|
+
const newMatch = body.match(/<new>([\s\S]*?)<\/new>/);
|
|
107
|
+
if (!oldMatch || !newMatch)
|
|
108
|
+
continue;
|
|
109
|
+
const oldText = oldMatch[1].replace(/^\n/, '').replace(/\n$/, '');
|
|
110
|
+
const newText = newMatch[1].replace(/^\n/, '').replace(/\n$/, '');
|
|
111
|
+
const absPath = join(tmpDir, filePath);
|
|
112
|
+
let current = fileEdits.get(filePath) ?? fileCache.get(filePath);
|
|
113
|
+
if (current === undefined) {
|
|
114
|
+
try {
|
|
115
|
+
current = readFileSync(absPath, 'utf8');
|
|
116
|
+
fileCache.set(filePath, current);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (oldText === '')
|
|
123
|
+
continue;
|
|
124
|
+
const updated = applyEdit(current, oldText, newText);
|
|
125
|
+
if (updated === null)
|
|
126
|
+
continue;
|
|
127
|
+
fileEdits.set(filePath, updated);
|
|
128
|
+
}
|
|
129
|
+
const { writeFileSync, mkdirSync } = await import('fs');
|
|
130
|
+
const { dirname } = await import('path');
|
|
131
|
+
for (const [filePath, content] of fileEdits) {
|
|
132
|
+
const absPath = join(tmpDir, filePath);
|
|
133
|
+
try {
|
|
134
|
+
mkdirSync(dirname(absPath), { recursive: true });
|
|
135
|
+
writeFileSync(absPath, content);
|
|
136
|
+
appliedCount++;
|
|
137
|
+
}
|
|
138
|
+
catch { /* skip unwritable paths */ }
|
|
139
|
+
}
|
|
140
|
+
return { appliedCount, tokensUsed };
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=conflict-resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict-resolve.js","sourceRoot":"","sources":["../../src/reviewers/conflict-resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAOpC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4CA8BoB,CAAA;AAE5C,iFAAiF;AACjF,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAAC,sCAAsC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;QAC/F,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAc,EAAE,SAAmB;IACpE,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QACvB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;YACpE,OAAO,OAAO,CAAC,aAAa,OAAO,UAAU,CAAA;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,OAAO,CAAC,yBAAyB,CAAA;QAC1C,CAAC;IACH,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAc,EACd,OAAe,EACf,YAAoB;IAEpB,MAAM,eAAe,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAA;IACnD,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,YAAY,EAAE,CAAC,EAAE,CAAA;IAE5D,MAAM,UAAU,GAAG,yBAAyB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACrE,MAAM,MAAM,GAAG,eAAe;SAC3B,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC;SAC9B,OAAO,CAAC,oBAAoB,EAAE,UAAU,CAAC;SACzC,OAAO,CAAC,sBAAsB,EAAE,YAAY,CAAC,CAAC,CAAC,4BAA4B,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAElG,IAAI,MAAM,GAAG,EAAE,CAAA;IACf,IAAI,UAA8B,CAAA;IAClC,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE;YAC/E,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,OAAO;YAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;SACxB,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;QACzB,IAAI,CAAC;YACH,MAAM,MAAM,GAAqB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAChD,MAAM,GAAG,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAA;YAChE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,YAAY,CAAA;YACxC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,aAAa,CAAA;YAC1C,UAAU,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;QACnG,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,GAAG,CAAA;QACd,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC5D,IAAI,gCAAgC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAA;QAC9F,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,YAAY;QAAE,OAAO,EAAE,YAAY,EAAE,CAAC,EAAE,UAAU,EAAE,CAAA;IAE9E,IAAI,YAAY,GAAG,CAAC,CAAA;IACpB,MAAM,SAAS,GAAG,0CAA0C,CAAA;IAC5D,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAA;IAC3C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAA;IAE3C,IAAI,KAA6B,CAAA;IACjC,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACjD,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,KAAK,CAAA;QAChC,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAQ;QAEjE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;QACrD,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ;YAAE,SAAQ;QAEpC,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QACjE,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QAEjE,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QACtC,IAAI,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAChE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;gBACvC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YAClC,CAAC;YAAC,MAAM,CAAC;gBACP,SAAQ;YACV,CAAC;QACH,CAAC;QAED,IAAI,OAAO,KAAK,EAAE;YAAE,SAAQ;QAE5B,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QACpD,IAAI,OAAO,KAAK,IAAI;YAAE,SAAQ;QAC9B,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAClC,CAAC;IAED,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAA;IACvD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAA;IACxC,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,SAAS,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QACtC,IAAI,CAAC;YACH,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YAChD,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YAC/B,YAAY,EAAE,CAAA;QAChB,CAAC;QAAC,MAAM,CAAC,CAAC,2BAA2B,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,CAAA;AACrC,CAAC"}
|