next-issue 1.0.7 → 1.0.8

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
@@ -9,7 +9,11 @@ npx -y next-issue@latest
9
9
 
10
10
  ## What it does
11
11
 
12
- For each open issue, oldest first:
12
+ Before each issue, fetch the open issues again and take the oldest one not yet
13
+ seen in this run. An issue seen once in a run, also a skipped or failed one, is
14
+ not tried again in that run. The run ends when no unseen issue is left. When
15
+ the fetch fails, the run ends there, writes the summary of the issues it handled
16
+ and exits with code 1. For each issue:
13
17
 
14
18
  1. Claim the issue only when it holds the `status:todo` label and holds no
15
19
  `status:in-progress` or `status:in-review` label. A `status:done`,
package/dist/cli.mjs CHANGED
@@ -82,16 +82,21 @@ async function handle(args, config, repo, recorder) {
82
82
  base,
83
83
  log: recorder.logFile,
84
84
  }, "quiet");
85
- const issues = await pendingIssues(context);
86
- recorder.event("issues", { open: issues.length }, "quiet");
87
- const { reports, stoppedAt } = await runIssues(args, {
88
- issues,
85
+ const { reports, stoppedAt, error } = await runIssues(args, {
86
+ issues: async () => {
87
+ const issues = await pendingIssues(context);
88
+ recorder.event("issues", { open: issues.length }, "quiet");
89
+ return issues;
90
+ },
89
91
  process: (issue) => processIssue(context, issue),
90
92
  stop: interrupts.afterIssue,
91
93
  });
92
94
  if (stoppedAt !== undefined) {
93
95
  recorder.event("run.stop", { issue: stoppedAt }, "quiet");
94
96
  }
97
+ if (error !== undefined) {
98
+ recorder.event("issues.fail", { error: message(error) }, "quiet");
99
+ }
95
100
  recorder.event("run.end", {
96
101
  done: count(reports, "done"),
97
102
  needsHuman: count(reports, "needs-human"),
@@ -103,7 +108,7 @@ async function handle(args, config, repo, recorder) {
103
108
  const summaryFile = join(repo.root, STATE_DIR, "runs", `${recorder.runId}.summary.json`);
104
109
  await writeFile(summaryFile, `${JSON.stringify(summary, null, 2)}\n`);
105
110
  await write(process.stdout, args.json ? `${JSON.stringify(summary, null, 2)}\n` : formatSummary(summary));
106
- return exitCode(reports);
111
+ return error === undefined ? exitCode(reports) : 1;
107
112
  }
108
113
  function count(reports, outcome) {
109
114
  return reports.filter((report) => report.outcome === outcome).length;
package/dist/loop.mjs CHANGED
@@ -1,9 +1,19 @@
1
1
  export async function runIssues(args, loop) {
2
2
  const reports = [];
3
- for (const issue of loop.issues) {
4
- if (args.max !== undefined && handled(reports) >= args.max) {
3
+ const seen = new Set();
4
+ while (args.max === undefined || handled(reports) < args.max) {
5
+ let issues;
6
+ try {
7
+ issues = await loop.issues();
8
+ }
9
+ catch (error) {
10
+ return { reports, error };
11
+ }
12
+ const issue = issues.find((candidate) => !seen.has(candidate.number));
13
+ if (issue === undefined) {
5
14
  break;
6
15
  }
16
+ seen.add(issue.number);
7
17
  const report = await loop.process(issue);
8
18
  reports.push(report);
9
19
  if (loop.stop() || report.halt === true) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-issue",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Autonomous issue harness driven by the Claude Agent SDK",
5
5
  "keywords": [
6
6
  "github",