nightralph 0.0.22 → 0.0.24
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/index.js +95 -35
- package/dist/index.js.map +2 -2
- package/dist/meta.json +12 -12
- package/dist/orchestrator.js +56 -6
- package/dist/orchestrator.js.map +2 -2
- package/dist/setup.js +19 -22
- package/dist/setup.js.map +2 -2
- package/dist/src/orchestrator.d.ts.map +1 -1
- package/dist/src/setup.d.ts +0 -1
- package/dist/src/setup.d.ts.map +1 -1
- package/dist/src/testcmd.d.ts +1 -0
- package/dist/src/testcmd.d.ts.map +1 -1
- package/dist/src/worktree.d.ts.map +1 -1
- package/dist/testcmd.js +9 -0
- package/dist/testcmd.js.map +2 -2
- package/dist/worktree.js +10 -1
- package/dist/worktree.js.map +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -79,7 +79,6 @@ function setup(opts) {
|
|
|
79
79
|
bundledSkillsDir,
|
|
80
80
|
docsTemplatesDir,
|
|
81
81
|
projectDir,
|
|
82
|
-
claude,
|
|
83
82
|
tracker
|
|
84
83
|
} = opts;
|
|
85
84
|
const agentsSkillsDir = join(
|
|
@@ -104,29 +103,27 @@ function setup(opts) {
|
|
|
104
103
|
` ${skill}/ (${files.join(", ")})`
|
|
105
104
|
);
|
|
106
105
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
skill
|
|
122
|
-
);
|
|
123
|
-
if (existsSync(linkPath)) continue;
|
|
124
|
-
symlinkSync(target, linkPath);
|
|
125
|
-
}
|
|
126
|
-
console.log(
|
|
127
|
-
"\nCreated symlinks in .claude/skills/"
|
|
106
|
+
const claudeSkillsDir = join(
|
|
107
|
+
projectDir,
|
|
108
|
+
".claude",
|
|
109
|
+
"skills"
|
|
110
|
+
);
|
|
111
|
+
mkdirSync(claudeSkillsDir, { recursive: true });
|
|
112
|
+
for (const skill of SKILL_DIRS) {
|
|
113
|
+
const linkPath = join(claudeSkillsDir, skill);
|
|
114
|
+
const target = join(
|
|
115
|
+
"..",
|
|
116
|
+
"..",
|
|
117
|
+
".agents",
|
|
118
|
+
"skills",
|
|
119
|
+
skill
|
|
128
120
|
);
|
|
121
|
+
if (existsSync(linkPath)) continue;
|
|
122
|
+
symlinkSync(target, linkPath);
|
|
129
123
|
}
|
|
124
|
+
console.log(
|
|
125
|
+
"\nCreated symlinks in .claude/skills/"
|
|
126
|
+
);
|
|
130
127
|
const docsAgentsDir = join(
|
|
131
128
|
projectDir,
|
|
132
129
|
"docs",
|
|
@@ -296,7 +293,7 @@ function createWorktree(opts) {
|
|
|
296
293
|
return result;
|
|
297
294
|
}
|
|
298
295
|
__name(createWorktree, "createWorktree");
|
|
299
|
-
async function
|
|
296
|
+
async function removeWorktreeNow(worktreePath, opts) {
|
|
300
297
|
const args = [
|
|
301
298
|
"-C",
|
|
302
299
|
worktreePath,
|
|
@@ -307,6 +304,15 @@ async function removeWorktree(worktreePath, opts) {
|
|
|
307
304
|
args.push(worktreePath);
|
|
308
305
|
await execFileAsync("git", args);
|
|
309
306
|
}
|
|
307
|
+
__name(removeWorktreeNow, "removeWorktreeNow");
|
|
308
|
+
function removeWorktree(worktreePath, opts) {
|
|
309
|
+
const result = worktreeQueue.then(
|
|
310
|
+
() => removeWorktreeNow(worktreePath, opts)
|
|
311
|
+
);
|
|
312
|
+
worktreeQueue = result.catch(() => {
|
|
313
|
+
});
|
|
314
|
+
return result;
|
|
315
|
+
}
|
|
310
316
|
__name(removeWorktree, "removeWorktree");
|
|
311
317
|
function hasNewCommits(repoRoot, base, branch) {
|
|
312
318
|
const stdout = execFileSync(
|
|
@@ -1025,6 +1031,9 @@ function runTestCmd(opts) {
|
|
|
1025
1031
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1026
1032
|
detached: true
|
|
1027
1033
|
});
|
|
1034
|
+
if (child.pid !== void 0 && opts.registry) {
|
|
1035
|
+
opts.registry.add(child.pid);
|
|
1036
|
+
}
|
|
1028
1037
|
const chunks = [];
|
|
1029
1038
|
child.stdout.on("data", (d) => chunks.push(String(d)));
|
|
1030
1039
|
child.stderr.on("data", (d) => chunks.push(String(d)));
|
|
@@ -1043,6 +1052,9 @@ function runTestCmd(opts) {
|
|
|
1043
1052
|
if (settled) return;
|
|
1044
1053
|
settled = true;
|
|
1045
1054
|
clearTimeout(timer);
|
|
1055
|
+
if (child.pid !== void 0 && opts.registry) {
|
|
1056
|
+
opts.registry.delete(child.pid);
|
|
1057
|
+
}
|
|
1046
1058
|
chunks.push(String(err));
|
|
1047
1059
|
resolve({
|
|
1048
1060
|
exitCode: 1,
|
|
@@ -1053,6 +1065,9 @@ function runTestCmd(opts) {
|
|
|
1053
1065
|
if (settled) return;
|
|
1054
1066
|
settled = true;
|
|
1055
1067
|
clearTimeout(timer);
|
|
1068
|
+
if (child.pid !== void 0 && opts.registry) {
|
|
1069
|
+
opts.registry.delete(child.pid);
|
|
1070
|
+
}
|
|
1056
1071
|
resolve({
|
|
1057
1072
|
exitCode: code ?? 1,
|
|
1058
1073
|
output: chunks.join("")
|
|
@@ -1243,6 +1258,7 @@ function renderMergePrompt(specBody, ticket) {
|
|
|
1243
1258
|
"3. Commit the resolved files.",
|
|
1244
1259
|
"",
|
|
1245
1260
|
"Do NOT re-implement the ticket from scratch.",
|
|
1261
|
+
"Do NOT read or modify files outside your current directory (the worktree).",
|
|
1246
1262
|
"Do NOT run git push."
|
|
1247
1263
|
].join("\n");
|
|
1248
1264
|
}
|
|
@@ -1624,6 +1640,7 @@ function spawnAgent(opts) {
|
|
|
1624
1640
|
__name(finish, "finish");
|
|
1625
1641
|
proc.on("exit", (code) => {
|
|
1626
1642
|
graceTimer = setTimeout(() => {
|
|
1643
|
+
killProcessGroup(proc.pid);
|
|
1627
1644
|
proc.stdout.destroy();
|
|
1628
1645
|
proc.stderr.destroy();
|
|
1629
1646
|
finish(code ?? 1);
|
|
@@ -1734,7 +1751,7 @@ Test command: ${opts.testCmd ?? "(none)"}`
|
|
|
1734
1751
|
`Retries: ${opts.retries ?? DEFAULT_RETRIES}`
|
|
1735
1752
|
);
|
|
1736
1753
|
console.log(
|
|
1737
|
-
`Retry delay: ${opts.retryDelay ??
|
|
1754
|
+
`Retry delay: ${opts.retryDelay ?? 0}s`
|
|
1738
1755
|
);
|
|
1739
1756
|
console.log(
|
|
1740
1757
|
`
|
|
@@ -1747,7 +1764,8 @@ async function runTestGate(opts) {
|
|
|
1747
1764
|
const result = await runTestCmd({
|
|
1748
1765
|
cmd: opts.testCmd,
|
|
1749
1766
|
cwd: opts.worktreePath,
|
|
1750
|
-
timeout: opts.timeout
|
|
1767
|
+
timeout: opts.timeout,
|
|
1768
|
+
registry: opts.registry
|
|
1751
1769
|
});
|
|
1752
1770
|
const testLogPath = attemptLogPath(
|
|
1753
1771
|
opts.logsDir,
|
|
@@ -1823,7 +1841,8 @@ async function respawnAndRetryMerge(opts) {
|
|
|
1823
1841
|
worktreePath: opts.worktreePath,
|
|
1824
1842
|
timeout: opts.timeout,
|
|
1825
1843
|
logsDir: opts.logsDir,
|
|
1826
|
-
log
|
|
1844
|
+
log,
|
|
1845
|
+
registry: runningAgents
|
|
1827
1846
|
});
|
|
1828
1847
|
if (!passed) {
|
|
1829
1848
|
log(
|
|
@@ -1939,7 +1958,12 @@ async function runTicketAttempt(opts) {
|
|
|
1939
1958
|
opts.baseBranch,
|
|
1940
1959
|
worktree.branchName
|
|
1941
1960
|
)) {
|
|
1942
|
-
|
|
1961
|
+
await removeWorktreeQuietly(worktree.worktreePath, d);
|
|
1962
|
+
return {
|
|
1963
|
+
kind: "no-commits",
|
|
1964
|
+
worktreePath: worktree.worktreePath,
|
|
1965
|
+
branchName: worktree.branchName
|
|
1966
|
+
};
|
|
1943
1967
|
}
|
|
1944
1968
|
if (opts.testCmd) {
|
|
1945
1969
|
const passed = await runTestGate({
|
|
@@ -1949,7 +1973,8 @@ async function runTicketAttempt(opts) {
|
|
|
1949
1973
|
timeout: opts.timeout,
|
|
1950
1974
|
logsDir: opts.logsDir,
|
|
1951
1975
|
attempt: opts.attempt,
|
|
1952
|
-
log: /* @__PURE__ */ __name((msg) => d.log(msg), "log")
|
|
1976
|
+
log: /* @__PURE__ */ __name((msg) => d.log(msg), "log"),
|
|
1977
|
+
registry: runningAgents
|
|
1953
1978
|
});
|
|
1954
1979
|
if (!passed) {
|
|
1955
1980
|
await removeWorktreeQuietly(
|
|
@@ -1978,7 +2003,11 @@ async function runTicketAttempts(opts) {
|
|
|
1978
2003
|
const maxAttempts = opts.retries + 1;
|
|
1979
2004
|
const isPi = basename2(opts.agentCmd) === "pi";
|
|
1980
2005
|
let thinking = opts.thinking;
|
|
1981
|
-
let outcome = {
|
|
2006
|
+
let outcome = {
|
|
2007
|
+
kind: "no-commits",
|
|
2008
|
+
worktreePath: "",
|
|
2009
|
+
branchName: ""
|
|
2010
|
+
};
|
|
1982
2011
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
1983
2012
|
if (attempt === 1) {
|
|
1984
2013
|
d.log(` Starting ${ticket.filename}`);
|
|
@@ -2239,6 +2268,18 @@ async function runWavesIsolated(opts) {
|
|
|
2239
2268
|
d.log(
|
|
2240
2269
|
` ${ticket.filename}: failed to create worktree: ${formatErrorMessage(outcome.error)}`
|
|
2241
2270
|
);
|
|
2271
|
+
checkTicket(progress, ticket.num, {
|
|
2272
|
+
branch: "",
|
|
2273
|
+
exitCode: -1,
|
|
2274
|
+
done: false
|
|
2275
|
+
});
|
|
2276
|
+
await saveProgress(
|
|
2277
|
+
repoRoot,
|
|
2278
|
+
progressPath,
|
|
2279
|
+
progress,
|
|
2280
|
+
`nightralph: ${ticket.filename} worktree error`,
|
|
2281
|
+
d
|
|
2282
|
+
);
|
|
2242
2283
|
continue;
|
|
2243
2284
|
}
|
|
2244
2285
|
if (outcome.kind === "error") {
|
|
@@ -2247,6 +2288,18 @@ async function runWavesIsolated(opts) {
|
|
|
2247
2288
|
d.log(
|
|
2248
2289
|
` ${ticket.filename}: attempt error: ` + formatErrorMessage(outcome.error)
|
|
2249
2290
|
);
|
|
2291
|
+
checkTicket(progress, ticket.num, {
|
|
2292
|
+
branch: outcome.branchName ?? "",
|
|
2293
|
+
exitCode: -1,
|
|
2294
|
+
done: false
|
|
2295
|
+
});
|
|
2296
|
+
await saveProgress(
|
|
2297
|
+
repoRoot,
|
|
2298
|
+
progressPath,
|
|
2299
|
+
progress,
|
|
2300
|
+
`nightralph: ${ticket.filename} error`,
|
|
2301
|
+
d
|
|
2302
|
+
);
|
|
2250
2303
|
continue;
|
|
2251
2304
|
}
|
|
2252
2305
|
if (outcome.kind === "no-commits") {
|
|
@@ -2255,6 +2308,18 @@ async function runWavesIsolated(opts) {
|
|
|
2255
2308
|
d.log(
|
|
2256
2309
|
` ${ticket.filename}: agent exited 0 but made no changes; leaving ticket ready-for-agent`
|
|
2257
2310
|
);
|
|
2311
|
+
checkTicket(progress, ticket.num, {
|
|
2312
|
+
branch: outcome.branchName,
|
|
2313
|
+
exitCode: 0,
|
|
2314
|
+
done: false
|
|
2315
|
+
});
|
|
2316
|
+
await saveProgress(
|
|
2317
|
+
repoRoot,
|
|
2318
|
+
progressPath,
|
|
2319
|
+
progress,
|
|
2320
|
+
`nightralph: ${ticket.filename} no commits`,
|
|
2321
|
+
d
|
|
2322
|
+
);
|
|
2258
2323
|
continue;
|
|
2259
2324
|
}
|
|
2260
2325
|
if (outcome.kind === "failed") {
|
|
@@ -2525,11 +2590,7 @@ var scriptDir = getScriptDir(import.meta.url);
|
|
|
2525
2590
|
yargs(hideBin(process.argv)).scriptName("nightralph").usage("$0 <command>").command(
|
|
2526
2591
|
"init",
|
|
2527
2592
|
"Install bundled skills and doc templates",
|
|
2528
|
-
(y) => y
|
|
2529
|
-
type: "boolean",
|
|
2530
|
-
describe: "Also create .claude/skills/ symlinks",
|
|
2531
|
-
default: true
|
|
2532
|
-
}),
|
|
2593
|
+
(y) => y,
|
|
2533
2594
|
async (argv) => {
|
|
2534
2595
|
const tracker = await select2({
|
|
2535
2596
|
message: "Issue tracker format",
|
|
@@ -2561,7 +2622,6 @@ yargs(hideBin(process.argv)).scriptName("nightralph").usage("$0 <command>").comm
|
|
|
2561
2622
|
"docs-templates"
|
|
2562
2623
|
),
|
|
2563
2624
|
projectDir: process.cwd(),
|
|
2564
|
-
claude: argv.claude,
|
|
2565
2625
|
tracker
|
|
2566
2626
|
});
|
|
2567
2627
|
}
|