next-issue 2.4.9 → 2.5.0
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 +11 -6
- package/dist/agents.mjs +1 -1
- package/dist/git.mjs +6 -0
- package/dist/observe.mjs +5 -2
- package/dist/pipeline.mjs +9 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,7 +41,10 @@ and exits with code 1. For each issue:
|
|
|
41
41
|
fixes it, and the harness commits again. A `commit:` line in the reply of
|
|
42
42
|
the agent replaces the subject, so a hook that rejects the subject can pass.
|
|
43
43
|
The budget is `maxCommitFixes`. Any other git failure in the commit stops
|
|
44
|
-
the run with an error.
|
|
44
|
+
the run with an error. An implementer that makes no change hands the issue
|
|
45
|
+
to a person, unless the branch is already ahead of the base, for example
|
|
46
|
+
after the state file was lost: the run then carries on with the commits on
|
|
47
|
+
the branch, and the newest of them gives the title of the pull request.
|
|
45
48
|
5. Open a draft pull request that closes the issue. Its title is the subject
|
|
46
49
|
of the commit that starts it, so a squash merge gives a conventional
|
|
47
50
|
commit.
|
|
@@ -198,17 +201,19 @@ the issue authors, or run it in a container.
|
|
|
198
201
|
|
|
199
202
|
## Observability
|
|
200
203
|
|
|
201
|
-
Every run has an id, `<timestamp>`, and writes
|
|
202
|
-
`.next-issue/runs/`:
|
|
204
|
+
Every run has an id, `<timestamp>`, and writes these under `.next-issue/runs/`:
|
|
203
205
|
|
|
204
206
|
- `<id>.jsonl` — one JSON object per event, with `ts`, `runId`, `kind`, and the
|
|
205
207
|
`issue`, `role` or `round` in scope;
|
|
206
208
|
- `<id>.summary.json` — token totals per agent role, event counts, and
|
|
207
209
|
one report per issue with the outcome, the reason, the pull request number
|
|
208
|
-
and the budgets used
|
|
210
|
+
and the budgets used;
|
|
211
|
+
- `<id>/sessions/` — the full pi session of each agent call, with every
|
|
212
|
+
message, tool call and tool result. The session id in a `usage` event is
|
|
213
|
+
part of the file name.
|
|
209
214
|
|
|
210
|
-
At the start of a run, the harness deletes the files under
|
|
211
|
-
that are older than `keepRunDays`. Set the field to `0` to keep them all.
|
|
215
|
+
At the start of a run, the harness deletes the files and folders under
|
|
216
|
+
`.next-issue/runs/` that are older than `keepRunDays`. Set the field to `0` to keep them all.
|
|
212
217
|
|
|
213
218
|
A short text summary of the same data goes to standard output. Use `--json` to
|
|
214
219
|
get the full summary object there instead, so the harness fits in a pipe. All
|
package/dist/agents.mjs
CHANGED
|
@@ -56,7 +56,7 @@ export async function runAgent(recorder, request) {
|
|
|
56
56
|
cwd: request.cwd,
|
|
57
57
|
agentDir,
|
|
58
58
|
resourceLoader,
|
|
59
|
-
sessionManager: SessionManager.
|
|
59
|
+
sessionManager: SessionManager.create(request.cwd, recorder.sessionDir),
|
|
60
60
|
tools: [...request.profile.tools, ...customTools.map((tool) => tool.name)],
|
|
61
61
|
customTools,
|
|
62
62
|
modelRuntime,
|
package/dist/git.mjs
CHANGED
|
@@ -157,6 +157,12 @@ export async function resetToBase(cwd, base, remote) {
|
|
|
157
157
|
await must('git', ['fetch', remote, base], { cwd });
|
|
158
158
|
await must('git', ['reset', '--hard', `${remote}/${base}`], { cwd });
|
|
159
159
|
}
|
|
160
|
+
export async function latestSubject(cwd, base, remote) {
|
|
161
|
+
const subject = await must('git', ['log', '-1', '--format=%s', `${remote}/${base}..HEAD`], {
|
|
162
|
+
cwd,
|
|
163
|
+
});
|
|
164
|
+
return subject === '' ? undefined : subject;
|
|
165
|
+
}
|
|
160
166
|
export async function revision(cwd) {
|
|
161
167
|
return must('git', ['rev-parse', 'HEAD'], { cwd });
|
|
162
168
|
}
|
package/dist/observe.mjs
CHANGED
|
@@ -73,6 +73,9 @@ export class Recorder {
|
|
|
73
73
|
get logFile() {
|
|
74
74
|
return this.sink.file;
|
|
75
75
|
}
|
|
76
|
+
get sessionDir() {
|
|
77
|
+
return join(this.sink.file.replace(/\.jsonl$/, ''), 'sessions');
|
|
78
|
+
}
|
|
76
79
|
get level() {
|
|
77
80
|
return this.sink.level;
|
|
78
81
|
}
|
|
@@ -154,8 +157,8 @@ export async function pruneRuns(root, keepDays) {
|
|
|
154
157
|
const path = join(dir, name);
|
|
155
158
|
try {
|
|
156
159
|
const info = await stat(path);
|
|
157
|
-
if (info.
|
|
158
|
-
await rm(path, { force: true });
|
|
160
|
+
if (info.mtimeMs < cutoff) {
|
|
161
|
+
await rm(path, { force: true, recursive: true });
|
|
159
162
|
dropped += 1;
|
|
160
163
|
}
|
|
161
164
|
}
|
package/dist/pipeline.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CODING, REVIEWING, runAgent } from './agents.mjs';
|
|
2
2
|
import { managedLabels } from './config.mjs';
|
|
3
3
|
import { run } from './exec.mjs';
|
|
4
|
-
import { addWorktree, branchName, commitAll, deleteBranch, diff, discardChanges, disputeBranches, findWorktree, HookError, isDirty, push, removeWorktree, resetToBase, revision, setAside, } from './git.mjs';
|
|
4
|
+
import { addWorktree, branchName, commitAll, deleteBranch, diff, discardChanges, disputeBranches, findWorktree, HookError, isDirty, latestSubject, push, removeWorktree, resetToBase, revision, setAside, } from './git.mjs';
|
|
5
5
|
import { commentOnIssue, 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';
|
|
@@ -25,6 +25,7 @@ export const PORTS = {
|
|
|
25
25
|
findWorktree,
|
|
26
26
|
isDirty,
|
|
27
27
|
issueComments,
|
|
28
|
+
latestSubject,
|
|
28
29
|
markPrReady,
|
|
29
30
|
mergeCommit,
|
|
30
31
|
mergePr,
|
|
@@ -211,8 +212,13 @@ async function work(context, issue, log, state, start) {
|
|
|
211
212
|
}));
|
|
212
213
|
const subject = parseCommitSubject(result.text, `fix: resolve issue #${issue.number}`);
|
|
213
214
|
if (!(await commitWork(job, before, subject, 'implementer'))) {
|
|
214
|
-
await
|
|
215
|
-
|
|
215
|
+
const earlier = await ports.latestSubject(worktree, context.base, config.remote);
|
|
216
|
+
if (earlier === undefined) {
|
|
217
|
+
await escalate(job, 'The implementer produced no change.');
|
|
218
|
+
return finish(job, 'needs-human', 'no implementation commit');
|
|
219
|
+
}
|
|
220
|
+
log.event('implement.earlier', { subject: earlier }, 'quiet');
|
|
221
|
+
state.title = earlier;
|
|
216
222
|
}
|
|
217
223
|
state.phase = 'implemented';
|
|
218
224
|
await writeState(repo, state);
|