next-issue 2.4.6 → 2.4.7

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 CHANGED
@@ -51,7 +51,10 @@ and exits with code 1. For each issue:
51
51
  while no check failed counts as such a read, not as a red build. A repository that reports no
52
52
  check keeps asking for `checkGraceSeconds`, because a new pull request often
53
53
  shows no check yet, and only then goes straight to the review. The later
54
- gates of the same issue ask once.
54
+ gates of the same issue ask once. GitHub runs no check on a pull request
55
+ that conflicts with its base, so no check and a conflict hand the issue to
56
+ a person. While GitHub still works out whether the pull request can merge,
57
+ the run asks again until `checkTimeoutMinutes`.
55
58
  7. On a red build, give the failed job logs to the fixer agent, then go to step
56
59
  6 again. The budget is `maxCiFixes`.
57
60
  8. Let the reviewer agent judge the diff, at most `diffMaxChars` of it. The
package/dist/github.mjs CHANGED
@@ -330,6 +330,17 @@ export async function mergePr(repo, pr) {
330
330
  const result = await run('gh', ['pr', 'merge', String(pr), '--squash', '--delete-branch', '--repo', slug(repo)], { cwd: repo.root });
331
331
  return result.code === 0;
332
332
  }
333
+ export async function prConflicts(repo, pr, options, clock = REAL_CLOCK) {
334
+ const deadline = clock.now() + options.timeoutMs;
335
+ for (;;) {
336
+ const mergeable = (await gh(repo, ['pr', 'view', String(pr), '--json', 'mergeable', '--jq', '.mergeable'])).trim();
337
+ const rest = deadline - clock.now();
338
+ if (mergeable !== 'UNKNOWN' || rest <= 0) {
339
+ return mergeable === 'CONFLICTING';
340
+ }
341
+ await clock.sleep(Math.min(options.intervalSeconds * 1000, rest));
342
+ }
343
+ }
333
344
  export async function prMerged(repo, pr) {
334
345
  return ((await gh(repo, ['pr', 'view', String(pr), '--json', 'state', '--jq', '.state'])).trim() ===
335
346
  'MERGED');
package/dist/pipeline.mjs CHANGED
@@ -2,7 +2,7 @@ import { CODING, REVIEWING, runAgent } from './agents.mjs';
2
2
  import { managedLabels } from './config.mjs';
3
3
  import { run } from './exec.mjs';
4
4
  import { addWorktree, branchName, commitAll, deleteBranch, diff, discardChanges, disputeBranches, findWorktree, HookError, isDirty, push, removeWorktree, resetToBase, revision, setAside, } from './git.mjs';
5
- import { commentOnPr, createPr, failedBaseLogs, failedCheckLogs, findPr, issueComments, markPrReady, mergeCommit, mergePr, openBlockers, openIssues, prMerged, reopenIssue, setLabel, viewIssue, waitForBaseChecks, waitForChecks, } from './github.mjs';
5
+ import { commentOnPr, createPr, failedBaseLogs, failedCheckLogs, findPr, issueComments, markPrReady, mergeCommit, mergePr, openBlockers, openIssues, prConflicts, prMerged, reopenIssue, setLabel, viewIssue, waitForBaseChecks, waitForChecks, } from './github.mjs';
6
6
  import { message } from './observe.mjs';
7
7
  import { capDiff, fixPrompt, hookPrompt, implementPrompt, parseCommitSubject, parseUnrelated, reviewPrompt, } from './prompts.mjs';
8
8
  import { detectSetupCommand } from './setup.mjs';
@@ -29,6 +29,7 @@ export const PORTS = {
29
29
  mergePr,
30
30
  openBlockers,
31
31
  openIssues,
32
+ prConflicts,
32
33
  prMerged,
33
34
  push,
34
35
  removeWorktree,
@@ -292,6 +293,14 @@ async function checkGate(job) {
292
293
  await escalate(job, 'The checks did not finish in time.');
293
294
  return { done: true, report: await finish(job, 'needs-human', 'checks timeout') };
294
295
  }
296
+ if (checks === 'none' &&
297
+ (await ports.prConflicts(repo, state.pr, {
298
+ intervalSeconds: config.checkIntervalSeconds,
299
+ timeoutMs: config.checkTimeoutMinutes * 60_000,
300
+ }))) {
301
+ await escalate(job, 'The pull request conflicts with its base, so no checks ran.');
302
+ return { done: true, report: await finish(job, 'needs-human', 'merge conflict') };
303
+ }
295
304
  if (checks !== 'fail') {
296
305
  return { done: false, fixed: false };
297
306
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-issue",
3
- "version": "2.4.6",
3
+ "version": "2.4.7",
4
4
  "description": "Autonomous issue harness driven by the pi SDK",
5
5
  "keywords": [
6
6
  "github",