nightralph 0.0.16 → 0.0.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/README.md +12 -6
- package/dist/index.js +110 -27
- package/dist/index.js.map +3 -3
- package/dist/merge.js +31 -19
- package/dist/merge.js.map +2 -2
- package/dist/meta.json +8 -8
- package/dist/orchestrator.js +78 -6
- package/dist/orchestrator.js.map +3 -3
- package/dist/src/merge.d.ts +7 -2
- package/dist/src/merge.d.ts.map +1 -1
- package/dist/src/orchestrator.d.ts +1 -0
- package/dist/src/orchestrator.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/merge.js
CHANGED
|
@@ -16,8 +16,10 @@ async function mergeBranch(repoRoot, branch) {
|
|
|
16
16
|
["merge", branch, "--no-edit"],
|
|
17
17
|
{ cwd: repoRoot }
|
|
18
18
|
);
|
|
19
|
-
return true;
|
|
20
|
-
} catch {
|
|
19
|
+
return { success: true };
|
|
20
|
+
} catch (err) {
|
|
21
|
+
const execErr = err;
|
|
22
|
+
const stderr = execErr.stderr || execErr.stdout;
|
|
21
23
|
try {
|
|
22
24
|
await execFileAsync(
|
|
23
25
|
"git",
|
|
@@ -26,7 +28,7 @@ async function mergeBranch(repoRoot, branch) {
|
|
|
26
28
|
);
|
|
27
29
|
} catch {
|
|
28
30
|
}
|
|
29
|
-
return false;
|
|
31
|
+
return { success: false, stderr };
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
__name(mergeBranch, "mergeBranch");
|
|
@@ -47,8 +49,10 @@ async function rebaseBranch(repoRoot, branch, onto, worktreePath) {
|
|
|
47
49
|
["rebase", onto],
|
|
48
50
|
{ cwd: worktreePath }
|
|
49
51
|
);
|
|
50
|
-
return true;
|
|
51
|
-
} catch {
|
|
52
|
+
return { success: true };
|
|
53
|
+
} catch (err) {
|
|
54
|
+
const execErr = err;
|
|
55
|
+
const stderr = execErr.stderr || execErr.stdout;
|
|
52
56
|
try {
|
|
53
57
|
await execFileAsync(
|
|
54
58
|
"git",
|
|
@@ -57,7 +61,7 @@ async function rebaseBranch(repoRoot, branch, onto, worktreePath) {
|
|
|
57
61
|
);
|
|
58
62
|
} catch {
|
|
59
63
|
}
|
|
60
|
-
return false;
|
|
64
|
+
return { success: false, stderr };
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
67
|
try {
|
|
@@ -76,8 +80,9 @@ async function rebaseBranch(repoRoot, branch, onto, worktreePath) {
|
|
|
76
80
|
["checkout", onto],
|
|
77
81
|
{ cwd: repoRoot }
|
|
78
82
|
);
|
|
79
|
-
return true;
|
|
80
|
-
} catch {
|
|
83
|
+
return { success: true };
|
|
84
|
+
} catch (err) {
|
|
85
|
+
const stderr = err.stderr;
|
|
81
86
|
try {
|
|
82
87
|
await execFileAsync(
|
|
83
88
|
"git",
|
|
@@ -94,7 +99,7 @@ async function rebaseBranch(repoRoot, branch, onto, worktreePath) {
|
|
|
94
99
|
);
|
|
95
100
|
} catch {
|
|
96
101
|
}
|
|
97
|
-
return false;
|
|
102
|
+
return { success: false, stderr };
|
|
98
103
|
}
|
|
99
104
|
}
|
|
100
105
|
__name(rebaseBranch, "rebaseBranch");
|
|
@@ -128,13 +133,16 @@ async function mergeWave(opts) {
|
|
|
128
133
|
conflicted: false
|
|
129
134
|
};
|
|
130
135
|
if (i === 0) {
|
|
131
|
-
const
|
|
136
|
+
const result = await mergeBranch(
|
|
132
137
|
repoRoot,
|
|
133
138
|
branch
|
|
134
139
|
);
|
|
135
|
-
mergingResult.merged = success;
|
|
136
|
-
mergingResult.conflicted = !success;
|
|
137
|
-
if (!success) {
|
|
140
|
+
mergingResult.merged = result.success;
|
|
141
|
+
mergingResult.conflicted = !result.success;
|
|
142
|
+
if (!result.success) {
|
|
143
|
+
mergingResult.stderr = result.stderr;
|
|
144
|
+
}
|
|
145
|
+
if (!result.success) {
|
|
138
146
|
if (strategy === "stop") {
|
|
139
147
|
stoppedAt = mergingResult;
|
|
140
148
|
merged.push(mergingResult);
|
|
@@ -144,14 +152,15 @@ async function mergeWave(opts) {
|
|
|
144
152
|
continue;
|
|
145
153
|
}
|
|
146
154
|
} else {
|
|
147
|
-
const
|
|
155
|
+
const rebaseResult = await rebaseBranch(
|
|
148
156
|
repoRoot,
|
|
149
157
|
branch,
|
|
150
158
|
baseBranch,
|
|
151
159
|
worktreePath
|
|
152
160
|
);
|
|
153
|
-
if (!
|
|
161
|
+
if (!rebaseResult.success) {
|
|
154
162
|
mergingResult.conflicted = true;
|
|
163
|
+
mergingResult.stderr = rebaseResult.stderr;
|
|
155
164
|
if (strategy === "stop") {
|
|
156
165
|
stoppedAt = mergingResult;
|
|
157
166
|
merged.push(mergingResult);
|
|
@@ -161,13 +170,16 @@ async function mergeWave(opts) {
|
|
|
161
170
|
continue;
|
|
162
171
|
}
|
|
163
172
|
}
|
|
164
|
-
const
|
|
173
|
+
const mergeResult = await mergeBranch(
|
|
165
174
|
repoRoot,
|
|
166
175
|
branch
|
|
167
176
|
);
|
|
168
|
-
mergingResult.merged =
|
|
169
|
-
mergingResult.conflicted = !
|
|
170
|
-
if (!
|
|
177
|
+
mergingResult.merged = mergeResult.success;
|
|
178
|
+
mergingResult.conflicted = !mergeResult.success;
|
|
179
|
+
if (!mergeResult.success) {
|
|
180
|
+
mergingResult.stderr = mergeResult.stderr;
|
|
181
|
+
}
|
|
182
|
+
if (!mergeResult.success) {
|
|
171
183
|
if (strategy === "stop") {
|
|
172
184
|
stoppedAt = mergingResult;
|
|
173
185
|
merged.push(mergingResult);
|
package/dist/merge.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/merge.ts"],
|
|
4
|
-
"sourcesContent": ["import { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\n\nconst execFileAsync = promisify(execFile)\n\nexport type MergeConflictStrategy = 'respawn'|'stop'\n\nexport type MergeResult = {\n branch:string\n ticketNum:number\n merged:boolean\n conflicted:boolean\n}\n\nexport type WaveMergeResult = {\n merged:Array<MergeResult>\n stoppedAt:MergeResult|null\n}\n\nexport async function mergeBranch (\n repoRoot:string,\n branch:string\n):Promise<
|
|
5
|
-
"mappings": ";;AAAA,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAE1B,MAAM,gBAAgB,UAAU,QAAQ;
|
|
4
|
+
"sourcesContent": ["import { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\n\nconst execFileAsync = promisify(execFile)\n\nexport type MergeConflictStrategy = 'respawn'|'stop'\n\nexport type MergeResult = {\n branch:string\n ticketNum:number\n merged:boolean\n conflicted:boolean\n stderr?:string\n}\n\nexport type WaveMergeResult = {\n merged:Array<MergeResult>\n stoppedAt:MergeResult|null\n}\n\nexport type GitOpResult = {\n success:boolean\n stderr?:string\n}\n\nexport async function mergeBranch (\n repoRoot:string,\n branch:string\n):Promise<GitOpResult> {\n if (!repoRoot || typeof repoRoot !== 'string') {\n throw new Error('repoRoot must be a non-empty string')\n }\n if (!branch || typeof branch !== 'string') {\n throw new Error('branch must be a non-empty string')\n }\n\n try {\n await execFileAsync(\n 'git',\n ['merge', branch, '--no-edit'],\n { cwd:repoRoot }\n )\n return { success:true }\n } catch (err) {\n const execErr = err as {\n stdout?:string; stderr?:string\n }\n const stderr =\n execErr.stderr || execErr.stdout\n try {\n await execFileAsync(\n 'git',\n ['merge', '--abort'],\n { cwd:repoRoot }\n )\n } catch {\n // no merge in progress to abort\n }\n return { success:false, stderr }\n }\n}\n\nexport async function rebaseBranch (\n repoRoot:string,\n branch:string,\n onto:string,\n worktreePath?:string\n):Promise<GitOpResult> {\n if (!repoRoot || typeof repoRoot !== 'string') {\n throw new Error('repoRoot must be a non-empty string')\n }\n if (!branch || typeof branch !== 'string') {\n throw new Error('branch must be a non-empty string')\n }\n if (!onto || typeof onto !== 'string') {\n throw new Error('onto must be a non-empty string')\n }\n\n // When the branch has its own worktree, it is already checked\n // out there -- checking it out in repoRoot too would fail with\n // \"already used by worktree\", so rebase in place instead.\n if (worktreePath) {\n try {\n await execFileAsync(\n 'git',\n ['rebase', onto],\n { cwd:worktreePath }\n )\n return { success:true }\n } catch (err) {\n const execErr = err as {\n stdout?:string; stderr?:string\n }\n const stderr =\n execErr.stderr || execErr.stdout\n try {\n await execFileAsync(\n 'git',\n ['rebase', '--abort'],\n { cwd:worktreePath }\n )\n } catch {\n // ignore abort errors\n }\n return { success:false, stderr }\n }\n }\n\n try {\n await execFileAsync(\n 'git',\n ['checkout', branch],\n { cwd:repoRoot }\n )\n\n await execFileAsync(\n 'git',\n ['rebase', onto],\n { cwd:repoRoot }\n )\n\n await execFileAsync(\n 'git',\n ['checkout', onto],\n { cwd:repoRoot }\n )\n\n return { success:true }\n } catch (err) {\n const stderr =\n (err as { stderr?:string }).stderr\n try {\n await execFileAsync(\n 'git',\n ['rebase', '--abort'],\n { cwd:repoRoot }\n )\n } catch {\n // ignore abort errors\n }\n try {\n await execFileAsync(\n 'git',\n ['checkout', onto],\n { cwd:repoRoot }\n )\n } catch {\n // ignore checkout errors\n }\n return { success:false, stderr }\n }\n}\n\n// Merges baseBranch into the worktree's branch so a\n// respawned agent sees the latest code. Conflicts are\n// left in place (not aborted) so the agent can resolve\n// and commit them.\nexport async function updateWorktreeFromBase (\n worktreePath:string,\n baseBranch:string\n):Promise<void> {\n try {\n await execFileAsync(\n 'git',\n ['merge', baseBranch, '--no-edit'],\n { cwd:worktreePath }\n )\n } catch {\n // conflict markers intentionally left for the\n // respawned agent to resolve\n }\n}\n\nexport async function mergeWave (\n opts:Readonly<{\n repoRoot:string\n baseBranch:string\n branches:ReadonlyArray<{\n branch:string\n ticketNum:number\n worktreePath?:string\n }>\n strategy:MergeConflictStrategy\n }>\n):Promise<WaveMergeResult> {\n const { repoRoot, baseBranch, branches, strategy } = opts\n\n if (!repoRoot || typeof repoRoot !== 'string') {\n throw new Error('repoRoot must be a non-empty string')\n }\n if (!baseBranch || typeof baseBranch !== 'string') {\n throw new Error('baseBranch must be a non-empty string')\n }\n\n const merged:Array<MergeResult> = []\n let stoppedAt:MergeResult|null = null\n\n for (let i = 0; i < branches.length; i++) {\n const { branch, ticketNum, worktreePath } = branches[i]\n const mergingResult:MergeResult = {\n branch,\n ticketNum,\n merged:false,\n conflicted:false,\n }\n\n if (i === 0) {\n const result = await mergeBranch(\n repoRoot,\n branch\n )\n mergingResult.merged = result.success\n mergingResult.conflicted = !result.success\n if (!result.success) {\n mergingResult.stderr = result.stderr\n }\n\n if (!result.success) {\n if (strategy === 'stop') {\n stoppedAt = mergingResult\n merged.push(mergingResult)\n break\n }\n merged.push(mergingResult)\n continue\n }\n } else {\n const rebaseResult = await rebaseBranch(\n repoRoot,\n branch,\n baseBranch,\n worktreePath\n )\n\n if (!rebaseResult.success) {\n mergingResult.conflicted = true\n mergingResult.stderr = rebaseResult.stderr\n\n if (strategy === 'stop') {\n stoppedAt = mergingResult\n merged.push(mergingResult)\n break\n } else {\n // strategy === 'respawn'\n merged.push(mergingResult)\n continue\n }\n }\n\n const mergeResult = await mergeBranch(\n repoRoot,\n branch\n )\n mergingResult.merged = mergeResult.success\n mergingResult.conflicted = !mergeResult.success\n if (!mergeResult.success) {\n mergingResult.stderr = mergeResult.stderr\n }\n\n if (!mergeResult.success) {\n if (strategy === 'stop') {\n stoppedAt = mergingResult\n merged.push(mergingResult)\n break\n }\n merged.push(mergingResult)\n continue\n }\n }\n\n merged.push(mergingResult)\n }\n\n return {\n merged,\n stoppedAt,\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/meta.json
CHANGED
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"format": "esm"
|
|
85
85
|
},
|
|
86
86
|
"src/merge.ts": {
|
|
87
|
-
"bytes":
|
|
87
|
+
"bytes": 7457,
|
|
88
88
|
"imports": [
|
|
89
89
|
{
|
|
90
90
|
"path": "node:child_process",
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
"format": "esm"
|
|
117
117
|
},
|
|
118
118
|
"src/orchestrator.ts": {
|
|
119
|
-
"bytes":
|
|
119
|
+
"bytes": 38180,
|
|
120
120
|
"imports": [
|
|
121
121
|
{
|
|
122
122
|
"path": "node:child_process",
|
|
@@ -203,7 +203,7 @@
|
|
|
203
203
|
"format": "esm"
|
|
204
204
|
},
|
|
205
205
|
"src/index.ts": {
|
|
206
|
-
"bytes":
|
|
206
|
+
"bytes": 7132,
|
|
207
207
|
"imports": [
|
|
208
208
|
{
|
|
209
209
|
"path": "node:fs",
|
|
@@ -269,7 +269,7 @@
|
|
|
269
269
|
"imports": [],
|
|
270
270
|
"exports": [],
|
|
271
271
|
"inputs": {},
|
|
272
|
-
"bytes":
|
|
272
|
+
"bytes": 128120
|
|
273
273
|
},
|
|
274
274
|
"dist/index.js": {
|
|
275
275
|
"imports": [
|
|
@@ -411,13 +411,13 @@
|
|
|
411
411
|
"entryPoint": "src/index.ts",
|
|
412
412
|
"inputs": {
|
|
413
413
|
"src/index.ts": {
|
|
414
|
-
"bytesInOutput":
|
|
414
|
+
"bytesInOutput": 5058
|
|
415
415
|
},
|
|
416
416
|
"src/setup.ts": {
|
|
417
417
|
"bytesInOutput": 4318
|
|
418
418
|
},
|
|
419
419
|
"src/orchestrator.ts": {
|
|
420
|
-
"bytesInOutput":
|
|
420
|
+
"bytesInOutput": 29296
|
|
421
421
|
},
|
|
422
422
|
"src/worktree.ts": {
|
|
423
423
|
"bytesInOutput": 3194
|
|
@@ -426,7 +426,7 @@
|
|
|
426
426
|
"bytesInOutput": 4233
|
|
427
427
|
},
|
|
428
428
|
"src/merge.ts": {
|
|
429
|
-
"bytesInOutput":
|
|
429
|
+
"bytesInOutput": 4995
|
|
430
430
|
},
|
|
431
431
|
"src/display.ts": {
|
|
432
432
|
"bytesInOutput": 8226
|
|
@@ -435,7 +435,7 @@
|
|
|
435
435
|
"bytesInOutput": 1937
|
|
436
436
|
}
|
|
437
437
|
},
|
|
438
|
-
"bytes":
|
|
438
|
+
"bytes": 61684
|
|
439
439
|
}
|
|
440
440
|
}
|
|
441
441
|
}
|
package/dist/orchestrator.js
CHANGED
|
@@ -154,6 +154,29 @@ function renderPrompt(specBody, ticket) {
|
|
|
154
154
|
].join("\n");
|
|
155
155
|
}
|
|
156
156
|
__name(renderPrompt, "renderPrompt");
|
|
157
|
+
function renderMergePrompt(specBody, ticket) {
|
|
158
|
+
return [
|
|
159
|
+
"---- SPEC CONTEXT ----",
|
|
160
|
+
specBody,
|
|
161
|
+
"",
|
|
162
|
+
"---- TICKET ----",
|
|
163
|
+
ticket.filename,
|
|
164
|
+
ticket.body,
|
|
165
|
+
"",
|
|
166
|
+
"---- AGENT INSTRUCTIONS ----",
|
|
167
|
+
"You are an autonomous coding agent resolving a merge conflict.",
|
|
168
|
+
"",
|
|
169
|
+
"Another agent already implemented this ticket on a feature branch. The branch was then merged with the base branch, but conflicts arose. The working tree may contain conflict markers that need resolution.",
|
|
170
|
+
"",
|
|
171
|
+
"Your task:",
|
|
172
|
+
"1. Find and resolve all conflict markers (<<<<<<< / ======= / >>>>>>>).",
|
|
173
|
+
"2. Make sure the code compiles and tests pass.",
|
|
174
|
+
"3. Commit the resolved files.",
|
|
175
|
+
"",
|
|
176
|
+
"Do NOT re-implement the ticket from scratch."
|
|
177
|
+
].join("\n");
|
|
178
|
+
}
|
|
179
|
+
__name(renderMergePrompt, "renderMergePrompt");
|
|
157
180
|
function listTickets(tickets) {
|
|
158
181
|
console.log("\nTickets:");
|
|
159
182
|
for (const t of tickets) {
|
|
@@ -563,7 +586,10 @@ async function respawnAndRetryMerge(opts) {
|
|
|
563
586
|
} else {
|
|
564
587
|
console.log(msg1);
|
|
565
588
|
}
|
|
566
|
-
const prompt =
|
|
589
|
+
const prompt = renderMergePrompt(
|
|
590
|
+
opts.specBody,
|
|
591
|
+
opts.ticket
|
|
592
|
+
);
|
|
567
593
|
const logPath = join(
|
|
568
594
|
opts.logsDir,
|
|
569
595
|
opts.ticket.filename.replace(/\.md$/, ".respawn.log")
|
|
@@ -591,19 +617,27 @@ async function respawnAndRetryMerge(opts) {
|
|
|
591
617
|
}
|
|
592
618
|
return false;
|
|
593
619
|
}
|
|
594
|
-
const
|
|
620
|
+
const mergeResult = await mergeBranch(
|
|
595
621
|
opts.repoRoot,
|
|
596
622
|
opts.branch
|
|
597
623
|
);
|
|
598
|
-
if (!
|
|
624
|
+
if (!mergeResult.success) {
|
|
599
625
|
const msg3 = ` ${opts.ticket.filename}: merge still conflicted after respawn`;
|
|
600
626
|
if (opts.onLine) {
|
|
601
627
|
opts.onLine(msg3);
|
|
602
628
|
} else {
|
|
603
629
|
console.log(msg3);
|
|
604
630
|
}
|
|
631
|
+
if (mergeResult.stderr) {
|
|
632
|
+
const stderrMsg = ` git: ${mergeResult.stderr.trim()}`;
|
|
633
|
+
if (opts.onLine) {
|
|
634
|
+
opts.onLine(stderrMsg);
|
|
635
|
+
} else {
|
|
636
|
+
console.log(stderrMsg);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
605
639
|
}
|
|
606
|
-
return
|
|
640
|
+
return mergeResult.success;
|
|
607
641
|
}
|
|
608
642
|
__name(respawnAndRetryMerge, "respawnAndRetryMerge");
|
|
609
643
|
function runProgress(tickets) {
|
|
@@ -624,6 +658,10 @@ async function runWaves(tickets, specBody, agentCmd, model, timeout, logsDir, di
|
|
|
624
658
|
const ready = findReadyTickets(tickets);
|
|
625
659
|
if (ready.length === 0) break;
|
|
626
660
|
waveNum++;
|
|
661
|
+
const readyNums = new Set(ready.map((t) => t.num));
|
|
662
|
+
const remaining2 = tickets.filter(
|
|
663
|
+
(t) => t.status === "ready-for-agent" && !readyNums.has(t.num)
|
|
664
|
+
);
|
|
627
665
|
d.startWave(
|
|
628
666
|
waveNum,
|
|
629
667
|
totalWaves,
|
|
@@ -631,7 +669,11 @@ async function runWaves(tickets, specBody, agentCmd, model, timeout, logsDir, di
|
|
|
631
669
|
num: t.num,
|
|
632
670
|
filename: t.filename
|
|
633
671
|
})),
|
|
634
|
-
runProgress(tickets)
|
|
672
|
+
runProgress(tickets),
|
|
673
|
+
remaining2.map((t) => ({
|
|
674
|
+
num: t.num,
|
|
675
|
+
filename: t.filename
|
|
676
|
+
}))
|
|
635
677
|
);
|
|
636
678
|
const results = await Promise.allSettled(
|
|
637
679
|
ready.map(async (t) => {
|
|
@@ -704,6 +746,11 @@ async function runWavesIsolated(opts) {
|
|
|
704
746
|
const repoRoot = getRepoRoot();
|
|
705
747
|
const repoName = getRepoName();
|
|
706
748
|
const baseBranch = getCurrentBranch();
|
|
749
|
+
if (isDirty(repoRoot)) {
|
|
750
|
+
throw new Error(
|
|
751
|
+
"Working tree is dirty; commit or stash changes before running"
|
|
752
|
+
);
|
|
753
|
+
}
|
|
707
754
|
const progressPath = join(
|
|
708
755
|
dirname(opts.logsDir),
|
|
709
756
|
"progress.md"
|
|
@@ -724,6 +771,10 @@ async function runWavesIsolated(opts) {
|
|
|
724
771
|
const ready = findReadyTickets(opts.tickets);
|
|
725
772
|
if (ready.length === 0) break;
|
|
726
773
|
waveNum++;
|
|
774
|
+
const readyNums = new Set(ready.map((t) => t.num));
|
|
775
|
+
const remaining2 = opts.tickets.filter(
|
|
776
|
+
(t) => t.status === "ready-for-agent" && !readyNums.has(t.num)
|
|
777
|
+
);
|
|
727
778
|
d.startWave(
|
|
728
779
|
waveNum,
|
|
729
780
|
totalWaves,
|
|
@@ -731,7 +782,11 @@ async function runWavesIsolated(opts) {
|
|
|
731
782
|
num: t.num,
|
|
732
783
|
filename: t.filename
|
|
733
784
|
})),
|
|
734
|
-
runProgress(opts.tickets)
|
|
785
|
+
runProgress(opts.tickets),
|
|
786
|
+
remaining2.map((t) => ({
|
|
787
|
+
num: t.num,
|
|
788
|
+
filename: t.filename
|
|
789
|
+
}))
|
|
735
790
|
);
|
|
736
791
|
const worktreeSettled = await Promise.allSettled(
|
|
737
792
|
ready.map((t) => createWorktree({
|
|
@@ -944,6 +999,22 @@ async function runWavesIsolated(opts) {
|
|
|
944
999
|
d.log(
|
|
945
1000
|
` ${ticket.filename}: merge failed, staying ready-for-agent`
|
|
946
1001
|
);
|
|
1002
|
+
if (branchResult.stderr) {
|
|
1003
|
+
d.log(
|
|
1004
|
+
" git: " + branchResult.stderr.trim()
|
|
1005
|
+
);
|
|
1006
|
+
}
|
|
1007
|
+
checkTicket(progress, ticket.num, {
|
|
1008
|
+
branch: branchResult.branch,
|
|
1009
|
+
exitCode: 0,
|
|
1010
|
+
done: false
|
|
1011
|
+
});
|
|
1012
|
+
writeProgress(progressPath, progress);
|
|
1013
|
+
await commitProgress(
|
|
1014
|
+
repoRoot,
|
|
1015
|
+
progressPath,
|
|
1016
|
+
`nightralph: ${ticket.filename} merge failed`
|
|
1017
|
+
);
|
|
947
1018
|
}
|
|
948
1019
|
}
|
|
949
1020
|
}
|
|
@@ -1000,6 +1071,7 @@ export {
|
|
|
1000
1071
|
parseBlockers,
|
|
1001
1072
|
parseStatus,
|
|
1002
1073
|
parseTicketFilename,
|
|
1074
|
+
renderMergePrompt,
|
|
1003
1075
|
renderPrompt,
|
|
1004
1076
|
runWaves,
|
|
1005
1077
|
runWavesIsolated,
|