nightralph 0.0.22 → 0.0.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.
package/dist/index.js CHANGED
@@ -296,7 +296,7 @@ function createWorktree(opts) {
296
296
  return result;
297
297
  }
298
298
  __name(createWorktree, "createWorktree");
299
- async function removeWorktree(worktreePath, opts) {
299
+ async function removeWorktreeNow(worktreePath, opts) {
300
300
  const args = [
301
301
  "-C",
302
302
  worktreePath,
@@ -307,6 +307,15 @@ async function removeWorktree(worktreePath, opts) {
307
307
  args.push(worktreePath);
308
308
  await execFileAsync("git", args);
309
309
  }
310
+ __name(removeWorktreeNow, "removeWorktreeNow");
311
+ function removeWorktree(worktreePath, opts) {
312
+ const result = worktreeQueue.then(
313
+ () => removeWorktreeNow(worktreePath, opts)
314
+ );
315
+ worktreeQueue = result.catch(() => {
316
+ });
317
+ return result;
318
+ }
310
319
  __name(removeWorktree, "removeWorktree");
311
320
  function hasNewCommits(repoRoot, base, branch) {
312
321
  const stdout = execFileSync(
@@ -1025,6 +1034,9 @@ function runTestCmd(opts) {
1025
1034
  stdio: ["ignore", "pipe", "pipe"],
1026
1035
  detached: true
1027
1036
  });
1037
+ if (child.pid !== void 0 && opts.registry) {
1038
+ opts.registry.add(child.pid);
1039
+ }
1028
1040
  const chunks = [];
1029
1041
  child.stdout.on("data", (d) => chunks.push(String(d)));
1030
1042
  child.stderr.on("data", (d) => chunks.push(String(d)));
@@ -1043,6 +1055,9 @@ function runTestCmd(opts) {
1043
1055
  if (settled) return;
1044
1056
  settled = true;
1045
1057
  clearTimeout(timer);
1058
+ if (child.pid !== void 0 && opts.registry) {
1059
+ opts.registry.delete(child.pid);
1060
+ }
1046
1061
  chunks.push(String(err));
1047
1062
  resolve({
1048
1063
  exitCode: 1,
@@ -1053,6 +1068,9 @@ function runTestCmd(opts) {
1053
1068
  if (settled) return;
1054
1069
  settled = true;
1055
1070
  clearTimeout(timer);
1071
+ if (child.pid !== void 0 && opts.registry) {
1072
+ opts.registry.delete(child.pid);
1073
+ }
1056
1074
  resolve({
1057
1075
  exitCode: code ?? 1,
1058
1076
  output: chunks.join("")
@@ -1243,6 +1261,7 @@ function renderMergePrompt(specBody, ticket) {
1243
1261
  "3. Commit the resolved files.",
1244
1262
  "",
1245
1263
  "Do NOT re-implement the ticket from scratch.",
1264
+ "Do NOT read or modify files outside your current directory (the worktree).",
1246
1265
  "Do NOT run git push."
1247
1266
  ].join("\n");
1248
1267
  }
@@ -1624,6 +1643,7 @@ function spawnAgent(opts) {
1624
1643
  __name(finish, "finish");
1625
1644
  proc.on("exit", (code) => {
1626
1645
  graceTimer = setTimeout(() => {
1646
+ killProcessGroup(proc.pid);
1627
1647
  proc.stdout.destroy();
1628
1648
  proc.stderr.destroy();
1629
1649
  finish(code ?? 1);
@@ -1734,7 +1754,7 @@ Test command: ${opts.testCmd ?? "(none)"}`
1734
1754
  `Retries: ${opts.retries ?? DEFAULT_RETRIES}`
1735
1755
  );
1736
1756
  console.log(
1737
- `Retry delay: ${opts.retryDelay ?? DEFAULT_RETRY_DELAY}s`
1757
+ `Retry delay: ${opts.retryDelay ?? 0}s`
1738
1758
  );
1739
1759
  console.log(
1740
1760
  `
@@ -1747,7 +1767,8 @@ async function runTestGate(opts) {
1747
1767
  const result = await runTestCmd({
1748
1768
  cmd: opts.testCmd,
1749
1769
  cwd: opts.worktreePath,
1750
- timeout: opts.timeout
1770
+ timeout: opts.timeout,
1771
+ registry: opts.registry
1751
1772
  });
1752
1773
  const testLogPath = attemptLogPath(
1753
1774
  opts.logsDir,
@@ -1823,7 +1844,8 @@ async function respawnAndRetryMerge(opts) {
1823
1844
  worktreePath: opts.worktreePath,
1824
1845
  timeout: opts.timeout,
1825
1846
  logsDir: opts.logsDir,
1826
- log
1847
+ log,
1848
+ registry: runningAgents
1827
1849
  });
1828
1850
  if (!passed) {
1829
1851
  log(
@@ -1939,7 +1961,12 @@ async function runTicketAttempt(opts) {
1939
1961
  opts.baseBranch,
1940
1962
  worktree.branchName
1941
1963
  )) {
1942
- return { kind: "no-commits" };
1964
+ await removeWorktreeQuietly(worktree.worktreePath, d);
1965
+ return {
1966
+ kind: "no-commits",
1967
+ worktreePath: worktree.worktreePath,
1968
+ branchName: worktree.branchName
1969
+ };
1943
1970
  }
1944
1971
  if (opts.testCmd) {
1945
1972
  const passed = await runTestGate({
@@ -1949,7 +1976,8 @@ async function runTicketAttempt(opts) {
1949
1976
  timeout: opts.timeout,
1950
1977
  logsDir: opts.logsDir,
1951
1978
  attempt: opts.attempt,
1952
- log: /* @__PURE__ */ __name((msg) => d.log(msg), "log")
1979
+ log: /* @__PURE__ */ __name((msg) => d.log(msg), "log"),
1980
+ registry: runningAgents
1953
1981
  });
1954
1982
  if (!passed) {
1955
1983
  await removeWorktreeQuietly(
@@ -1978,7 +2006,11 @@ async function runTicketAttempts(opts) {
1978
2006
  const maxAttempts = opts.retries + 1;
1979
2007
  const isPi = basename2(opts.agentCmd) === "pi";
1980
2008
  let thinking = opts.thinking;
1981
- let outcome = { kind: "no-commits" };
2009
+ let outcome = {
2010
+ kind: "no-commits",
2011
+ worktreePath: "",
2012
+ branchName: ""
2013
+ };
1982
2014
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1983
2015
  if (attempt === 1) {
1984
2016
  d.log(` Starting ${ticket.filename}`);
@@ -2239,6 +2271,18 @@ async function runWavesIsolated(opts) {
2239
2271
  d.log(
2240
2272
  ` ${ticket.filename}: failed to create worktree: ${formatErrorMessage(outcome.error)}`
2241
2273
  );
2274
+ checkTicket(progress, ticket.num, {
2275
+ branch: "",
2276
+ exitCode: -1,
2277
+ done: false
2278
+ });
2279
+ await saveProgress(
2280
+ repoRoot,
2281
+ progressPath,
2282
+ progress,
2283
+ `nightralph: ${ticket.filename} worktree error`,
2284
+ d
2285
+ );
2242
2286
  continue;
2243
2287
  }
2244
2288
  if (outcome.kind === "error") {
@@ -2247,6 +2291,18 @@ async function runWavesIsolated(opts) {
2247
2291
  d.log(
2248
2292
  ` ${ticket.filename}: attempt error: ` + formatErrorMessage(outcome.error)
2249
2293
  );
2294
+ checkTicket(progress, ticket.num, {
2295
+ branch: outcome.branchName ?? "",
2296
+ exitCode: -1,
2297
+ done: false
2298
+ });
2299
+ await saveProgress(
2300
+ repoRoot,
2301
+ progressPath,
2302
+ progress,
2303
+ `nightralph: ${ticket.filename} error`,
2304
+ d
2305
+ );
2250
2306
  continue;
2251
2307
  }
2252
2308
  if (outcome.kind === "no-commits") {
@@ -2255,6 +2311,18 @@ async function runWavesIsolated(opts) {
2255
2311
  d.log(
2256
2312
  ` ${ticket.filename}: agent exited 0 but made no changes; leaving ticket ready-for-agent`
2257
2313
  );
2314
+ checkTicket(progress, ticket.num, {
2315
+ branch: outcome.branchName,
2316
+ exitCode: 0,
2317
+ done: false
2318
+ });
2319
+ await saveProgress(
2320
+ repoRoot,
2321
+ progressPath,
2322
+ progress,
2323
+ `nightralph: ${ticket.filename} no commits`,
2324
+ d
2325
+ );
2258
2326
  continue;
2259
2327
  }
2260
2328
  if (outcome.kind === "failed") {