self-bench 0.3.5 → 0.3.6
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 +16 -14
- package/biome.json +7 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +7 -7
- package/dist/api.js.map +1 -1
- package/dist/build-metadata.js +1 -1
- package/dist/cli.js +75 -15
- package/dist/cli.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/contracts.d.ts +1 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +6 -5
- package/dist/contracts.js.map +1 -1
- package/dist/extensions/discovery.d.ts.map +1 -1
- package/dist/extensions/discovery.js +12 -5
- package/dist/extensions/discovery.js.map +1 -1
- package/dist/harbor-task.d.ts.map +1 -1
- package/dist/harbor-task.js +3 -1
- package/dist/harbor-task.js.map +1 -1
- package/dist/project-paths.d.ts +2 -0
- package/dist/project-paths.d.ts.map +1 -0
- package/dist/project-paths.js +15 -0
- package/dist/project-paths.js.map +1 -0
- package/dist/provenance-associations.d.ts +49 -0
- package/dist/provenance-associations.d.ts.map +1 -0
- package/dist/provenance-associations.js +220 -0
- package/dist/provenance-associations.js.map +1 -0
- package/dist/provenance.d.ts +34 -13
- package/dist/provenance.d.ts.map +1 -1
- package/dist/provenance.js +81 -9
- package/dist/provenance.js.map +1 -1
- package/dist/reaudit-main.js +3 -3
- package/dist/reaudit-main.js.map +1 -1
- package/dist/repair-main.js +4 -4
- package/dist/repair-main.js.map +1 -1
- package/dist/{sandbox.d.ts → sandbox/contracts.d.ts} +5 -3
- package/dist/sandbox/contracts.d.ts.map +1 -0
- package/dist/sandbox/contracts.js +9 -0
- package/dist/sandbox/contracts.js.map +1 -0
- package/dist/sandbox/index.d.ts +5 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/{sandbox.js → sandbox/index.js} +6 -5
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/programs/author.d.ts +3 -0
- package/dist/sandbox/programs/author.d.ts.map +1 -0
- package/dist/{sandbox-author.js → sandbox/programs/author.js} +2 -2
- package/dist/sandbox/programs/author.js.map +1 -0
- package/dist/sandbox/programs/prepare-repair.d.ts +7 -0
- package/dist/sandbox/programs/prepare-repair.d.ts.map +1 -0
- package/dist/sandbox/programs/prepare-repair.js +30 -0
- package/dist/sandbox/programs/prepare-repair.js.map +1 -0
- package/dist/sandbox/programs/repair.d.ts +3 -0
- package/dist/sandbox/programs/repair.d.ts.map +1 -0
- package/dist/{sandbox-repair.js → sandbox/programs/repair.js} +7 -28
- package/dist/sandbox/programs/repair.js.map +1 -0
- package/dist/sandbox/programs/review.d.ts +2 -0
- package/dist/sandbox/programs/review.d.ts.map +1 -0
- package/dist/{sandbox-review.js → sandbox/programs/review.js} +2 -2
- package/dist/sandbox/programs/review.js.map +1 -0
- package/dist/sandbox/programs/validation-repair.d.ts +3 -0
- package/dist/sandbox/programs/validation-repair.d.ts.map +1 -0
- package/dist/{sandbox-validation-repair.js → sandbox/programs/validation-repair.js} +7 -28
- package/dist/sandbox/programs/validation-repair.js.map +1 -0
- package/dist/{docker-executor.d.ts → sandbox/providers/docker/executor.d.ts} +3 -3
- package/dist/sandbox/providers/docker/executor.d.ts.map +1 -0
- package/dist/{docker-executor.js → sandbox/providers/docker/executor.js} +2 -2
- package/dist/sandbox/providers/docker/executor.js.map +1 -0
- package/dist/{modal-executor.d.ts → sandbox/providers/modal/executor.d.ts} +3 -3
- package/dist/sandbox/providers/modal/executor.d.ts.map +1 -0
- package/dist/{modal-executor.js → sandbox/providers/modal/executor.js} +50 -19
- package/dist/sandbox/providers/modal/executor.js.map +1 -0
- package/dist/{vercel-command.d.ts → sandbox/providers/vercel/command.d.ts} +3 -3
- package/dist/sandbox/providers/vercel/command.d.ts.map +1 -0
- package/dist/{vercel-command.js → sandbox/providers/vercel/command.js} +3 -3
- package/dist/sandbox/providers/vercel/command.js.map +1 -0
- package/dist/{vercel-executor.d.ts → sandbox/providers/vercel/executor.d.ts} +3 -3
- package/dist/sandbox/providers/vercel/executor.d.ts.map +1 -0
- package/dist/{vercel-executor.js → sandbox/providers/vercel/executor.js} +5 -5
- package/dist/sandbox/providers/vercel/executor.js.map +1 -0
- package/dist/{vercel-fetch.d.ts → sandbox/providers/vercel/fetch.d.ts} +1 -1
- package/dist/sandbox/providers/vercel/fetch.d.ts.map +1 -0
- package/dist/{vercel-fetch.js → sandbox/providers/vercel/fetch.js} +1 -1
- package/dist/sandbox/providers/vercel/fetch.js.map +1 -0
- package/dist/{sandbox-timeout.d.ts → sandbox/timeout.d.ts} +2 -2
- package/dist/sandbox/timeout.d.ts.map +1 -0
- package/dist/{sandbox-timeout.js → sandbox/timeout.js} +1 -1
- package/dist/sandbox/timeout.js.map +1 -0
- package/dist/sandbox-author.bundle.js +11 -8
- package/dist/sandbox-repair.bundle.js +43 -35
- package/dist/sandbox-review.bundle.js +2 -2
- package/dist/sandbox-validation-repair.bundle.js +50 -41
- package/dist/{vercel-cli.d.ts → setup/vercel/cli.d.ts} +2 -2
- package/dist/setup/vercel/cli.d.ts.map +1 -0
- package/dist/{vercel-cli.js → setup/vercel/cli.js} +2 -2
- package/dist/setup/vercel/cli.js.map +1 -0
- package/dist/setup/vercel/index.d.ts +4 -0
- package/dist/setup/vercel/index.d.ts.map +1 -0
- package/dist/setup/vercel/index.js +3 -0
- package/dist/setup/vercel/index.js.map +1 -0
- package/dist/{vercel-setup-probe.d.ts → setup/vercel/probe.d.ts} +2 -2
- package/dist/setup/vercel/probe.d.ts.map +1 -0
- package/dist/{vercel-setup-probe.js → setup/vercel/probe.js} +2 -2
- package/dist/setup/vercel/probe.js.map +1 -0
- package/dist/{vercel-profile.d.ts → setup/vercel/profile.d.ts} +1 -1
- package/dist/setup/vercel/profile.d.ts.map +1 -0
- package/dist/{vercel-profile.js → setup/vercel/profile.js} +2 -2
- package/dist/setup/vercel/profile.js.map +1 -0
- package/dist/{vercel-runtime-image.d.ts → setup/vercel/runtime-image.d.ts} +5 -5
- package/dist/setup/vercel/runtime-image.d.ts.map +1 -0
- package/dist/{vercel-runtime-image.js → setup/vercel/runtime-image.js} +2 -2
- package/dist/setup/vercel/runtime-image.js.map +1 -0
- package/dist/{vercel-setup.d.ts → setup/vercel/setup.d.ts} +8 -8
- package/dist/setup/vercel/setup.d.ts.map +1 -0
- package/dist/{vercel-setup.js → setup/vercel/setup.js} +8 -8
- package/dist/setup/vercel/setup.js.map +1 -0
- package/dist/temporal/activities.d.ts +12 -0
- package/dist/temporal/activities.d.ts.map +1 -1
- package/dist/temporal/activities.js +80 -33
- package/dist/temporal/activities.js.map +1 -1
- package/dist/temporal/workflow.d.ts +1 -1
- package/dist/temporal/workflow.d.ts.map +1 -1
- package/dist/temporal/workflow.js +90 -65
- package/dist/temporal/workflow.js.map +1 -1
- package/docs/operations.md +39 -5
- package/docs/task-construction.md +3 -1
- package/package.json +5 -5
- package/scripts/build-sandbox-programs.ts +22 -0
- package/scripts/verify-package.ts +25 -4
- package/scripts/write-build-metadata.ts +1 -1
- package/src/api.ts +7 -6
- package/src/cli.ts +99 -15
- package/src/config.ts +1 -1
- package/src/contracts.ts +7 -5
- package/src/extensions/discovery.ts +14 -5
- package/src/harbor-task.ts +6 -1
- package/src/project-paths.ts +15 -0
- package/src/provenance-associations.ts +311 -0
- package/src/provenance.ts +132 -28
- package/src/reaudit-main.ts +3 -3
- package/src/repair-main.ts +4 -4
- package/src/{sandbox.ts → sandbox/contracts.ts} +11 -20
- package/src/sandbox/index.ts +23 -0
- package/src/{sandbox-author.ts → sandbox/programs/author.ts} +1 -1
- package/src/sandbox/programs/prepare-repair.ts +44 -0
- package/src/{sandbox-repair.ts → sandbox/programs/repair.ts} +7 -31
- package/src/{sandbox-review.ts → sandbox/programs/review.ts} +1 -1
- package/src/{sandbox-validation-repair.ts → sandbox/programs/validation-repair.ts} +6 -30
- package/src/{docker-executor.ts → sandbox/providers/docker/executor.ts} +3 -3
- package/src/{modal-executor.ts → sandbox/providers/modal/executor.ts} +66 -25
- package/src/{vercel-command.ts → sandbox/providers/vercel/command.ts} +3 -3
- package/src/{vercel-executor.ts → sandbox/providers/vercel/executor.ts} +5 -5
- package/src/{sandbox-timeout.ts → sandbox/timeout.ts} +1 -1
- package/src/{vercel-cli.ts → setup/vercel/cli.ts} +1 -1
- package/src/setup/vercel/index.ts +3 -0
- package/src/{vercel-setup-probe.ts → setup/vercel/probe.ts} +5 -2
- package/src/{vercel-profile.ts → setup/vercel/profile.ts} +4 -1
- package/src/{vercel-runtime-image.ts → setup/vercel/runtime-image.ts} +5 -5
- package/src/{vercel-setup.ts → setup/vercel/setup.ts} +8 -8
- package/src/temporal/activities.ts +164 -63
- package/src/temporal/workflow.ts +120 -71
- package/tsconfig.json +1 -1
- package/dist/docker-executor.d.ts.map +0 -1
- package/dist/docker-executor.js.map +0 -1
- package/dist/modal-executor.d.ts.map +0 -1
- package/dist/modal-executor.js.map +0 -1
- package/dist/sandbox-author.d.ts +0 -3
- package/dist/sandbox-author.d.ts.map +0 -1
- package/dist/sandbox-author.js.map +0 -1
- package/dist/sandbox-repair.d.ts +0 -3
- package/dist/sandbox-repair.d.ts.map +0 -1
- package/dist/sandbox-repair.js.map +0 -1
- package/dist/sandbox-review.d.ts +0 -2
- package/dist/sandbox-review.d.ts.map +0 -1
- package/dist/sandbox-review.js.map +0 -1
- package/dist/sandbox-timeout.d.ts.map +0 -1
- package/dist/sandbox-timeout.js.map +0 -1
- package/dist/sandbox-validation-repair.d.ts +0 -3
- package/dist/sandbox-validation-repair.d.ts.map +0 -1
- package/dist/sandbox-validation-repair.js.map +0 -1
- package/dist/sandbox.d.ts.map +0 -1
- package/dist/sandbox.js.map +0 -1
- package/dist/vercel-cli.d.ts.map +0 -1
- package/dist/vercel-cli.js.map +0 -1
- package/dist/vercel-command.d.ts.map +0 -1
- package/dist/vercel-command.js.map +0 -1
- package/dist/vercel-executor.d.ts.map +0 -1
- package/dist/vercel-executor.js.map +0 -1
- package/dist/vercel-fetch.d.ts.map +0 -1
- package/dist/vercel-fetch.js.map +0 -1
- package/dist/vercel-profile.d.ts.map +0 -1
- package/dist/vercel-profile.js.map +0 -1
- package/dist/vercel-runtime-image.d.ts.map +0 -1
- package/dist/vercel-runtime-image.js.map +0 -1
- package/dist/vercel-setup-probe.d.ts.map +0 -1
- package/dist/vercel-setup-probe.js.map +0 -1
- package/dist/vercel-setup.d.ts.map +0 -1
- package/dist/vercel-setup.js.map +0 -1
- /package/src/{vercel-fetch.ts → sandbox/providers/vercel/fetch.ts} +0 -0
package/src/provenance.ts
CHANGED
|
@@ -1,23 +1,50 @@
|
|
|
1
|
-
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
-
import { basename, join } from "node:path";
|
|
1
|
+
import { readdir, readFile, stat } from "node:fs/promises";
|
|
2
|
+
import { basename, join, relative } from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
3
4
|
import { assertPullRequestBelongsToRepository, githubRepository } from "./github.js";
|
|
4
5
|
import { runCommand } from "./process.js";
|
|
5
6
|
|
|
6
7
|
export type SessionProvenanceFormat = "codex" | "claude-code" | "pi" | "generic";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
const provenanceMessageBaseSchema = z.object({
|
|
10
|
+
sessionId: z.string().min(1),
|
|
11
|
+
messageIndex: z.number().int().nonnegative(),
|
|
12
|
+
content: z.string().min(1),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const localProvenanceMessageSchema = provenanceMessageBaseSchema
|
|
16
|
+
.extend({
|
|
17
|
+
sourceType: z.enum(["codex", "claude-code", "pi", "generic"]),
|
|
18
|
+
sourcePr: z.number().int().positive().optional(),
|
|
19
|
+
sourceUrl: z.string().url().optional(),
|
|
20
|
+
})
|
|
21
|
+
.refine(
|
|
22
|
+
(message) => (message.sourcePr === undefined) === (message.sourceUrl === undefined),
|
|
23
|
+
"sourcePr and sourceUrl must be supplied together",
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
export const provenanceMessageSchema = z.union([
|
|
27
|
+
localProvenanceMessageSchema,
|
|
28
|
+
provenanceMessageBaseSchema.extend({
|
|
29
|
+
sourceType: z.literal("github-pull-request"),
|
|
30
|
+
sourcePr: z.number().int().positive(),
|
|
31
|
+
sourceUrl: z.string().url(),
|
|
32
|
+
}),
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
export type ProvenanceMessage = z.infer<typeof provenanceMessageSchema>;
|
|
36
|
+
|
|
37
|
+
export interface LocalSessionMetadata {
|
|
38
|
+
readonly sourceType: SessionProvenanceFormat;
|
|
9
39
|
readonly sessionId: string;
|
|
10
|
-
readonly
|
|
11
|
-
readonly
|
|
40
|
+
readonly path: string;
|
|
41
|
+
readonly modifiedAt: string;
|
|
12
42
|
}
|
|
13
43
|
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
readonly sourcePr: number;
|
|
19
|
-
readonly sourceUrl: string;
|
|
20
|
-
});
|
|
44
|
+
export interface RepositoryProvenanceCollection {
|
|
45
|
+
readonly messages: readonly ProvenanceMessage[];
|
|
46
|
+
readonly sessions: readonly LocalSessionMetadata[];
|
|
47
|
+
}
|
|
21
48
|
|
|
22
49
|
interface JsonRecord {
|
|
23
50
|
readonly [key: string]: unknown;
|
|
@@ -51,9 +78,19 @@ export async function collectRepositoryProvenance(
|
|
|
51
78
|
repositoryPath: string,
|
|
52
79
|
homeDirectory: string,
|
|
53
80
|
): Promise<ProvenanceMessage[]> {
|
|
81
|
+
return [
|
|
82
|
+
...(await collectRepositoryProvenanceWithMetadata(repositoryPath, homeDirectory)).messages,
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function collectRepositoryProvenanceWithMetadata(
|
|
87
|
+
repositoryPath: string,
|
|
88
|
+
homeDirectory: string,
|
|
89
|
+
): Promise<RepositoryProvenanceCollection> {
|
|
54
90
|
const worktrees = await repositoryWorktrees(repositoryPath);
|
|
55
91
|
const encodedWorktrees = worktrees.flatMap((path) => [path, encodeSessionPath(path)]);
|
|
56
92
|
const messages: ProvenanceMessage[] = [];
|
|
93
|
+
const sessions: LocalSessionMetadata[] = [];
|
|
57
94
|
|
|
58
95
|
for (const [format, relativeRoot] of SOURCE_ROOTS) {
|
|
59
96
|
const root = join(homeDirectory, relativeRoot);
|
|
@@ -65,29 +102,54 @@ export async function collectRepositoryProvenance(
|
|
|
65
102
|
) {
|
|
66
103
|
continue;
|
|
67
104
|
}
|
|
68
|
-
|
|
105
|
+
const extracted = extractProvenanceMessages(raw, format, basename(path));
|
|
106
|
+
if (extracted.length === 0) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
messages.push(...extracted);
|
|
110
|
+
const file = await stat(path).catch(() => undefined);
|
|
111
|
+
if (file) {
|
|
112
|
+
const sessionIds = new Set(extracted.map((message) => message.sessionId));
|
|
113
|
+
for (const sessionId of sessionIds) {
|
|
114
|
+
sessions.push({
|
|
115
|
+
sourceType: format,
|
|
116
|
+
sessionId,
|
|
117
|
+
path: displaySessionPath(path, homeDirectory),
|
|
118
|
+
modifiedAt: file.mtime.toISOString(),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
69
122
|
}
|
|
70
123
|
}
|
|
71
124
|
|
|
72
|
-
return deduplicateMessages(messages);
|
|
125
|
+
return { messages: deduplicateMessages(messages), sessions };
|
|
73
126
|
}
|
|
74
127
|
|
|
75
128
|
export async function collectGitHubPullRequestProvenance(
|
|
76
129
|
repositoryUrl: string,
|
|
130
|
+
token?: string,
|
|
131
|
+
signal?: AbortSignal,
|
|
77
132
|
): Promise<ProvenanceMessage[]> {
|
|
78
133
|
const repository = githubRepository(repositoryUrl);
|
|
79
|
-
const result = await runCommand(
|
|
80
|
-
"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
134
|
+
const result = await runCommand(
|
|
135
|
+
"gh",
|
|
136
|
+
[
|
|
137
|
+
"pr",
|
|
138
|
+
"list",
|
|
139
|
+
"--repo",
|
|
140
|
+
repository,
|
|
141
|
+
"--state",
|
|
142
|
+
"merged",
|
|
143
|
+
"--limit",
|
|
144
|
+
String(GITHUB_PULL_REQUEST_LIMIT),
|
|
145
|
+
"--json",
|
|
146
|
+
"number,title,body,url,author,isDraft,additions,deletions,changedFiles",
|
|
147
|
+
],
|
|
148
|
+
{
|
|
149
|
+
env: token ? { ...process.env, GH_TOKEN: token } : process.env,
|
|
150
|
+
...(signal ? { signal } : {}),
|
|
151
|
+
},
|
|
152
|
+
);
|
|
91
153
|
return extractGitHubPullRequestProvenance(result.stdout, repositoryUrl);
|
|
92
154
|
}
|
|
93
155
|
|
|
@@ -130,19 +192,55 @@ export function extractGitHubPullRequestProvenance(
|
|
|
130
192
|
return messages;
|
|
131
193
|
}
|
|
132
194
|
|
|
195
|
+
export function combineRunProvenance(
|
|
196
|
+
repositoryUrl: string,
|
|
197
|
+
local: readonly ProvenanceMessage[],
|
|
198
|
+
github: readonly ProvenanceMessage[],
|
|
199
|
+
): ProvenanceMessage[] {
|
|
200
|
+
const explicitlyAssociatedPrs = new Set<number>();
|
|
201
|
+
for (const message of local) {
|
|
202
|
+
if (message.sourcePr === undefined || message.sourceUrl === undefined) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
assertPullRequestBelongsToRepository(repositoryUrl, message.sourceUrl, message.sourcePr);
|
|
206
|
+
explicitlyAssociatedPrs.add(message.sourcePr);
|
|
207
|
+
}
|
|
208
|
+
return [
|
|
209
|
+
...local,
|
|
210
|
+
...github.filter(
|
|
211
|
+
(message) =>
|
|
212
|
+
message.sourceType !== "github-pull-request" ||
|
|
213
|
+
!explicitlyAssociatedPrs.has(message.sourcePr),
|
|
214
|
+
),
|
|
215
|
+
];
|
|
216
|
+
}
|
|
217
|
+
|
|
133
218
|
export function assertProvenanceMatchesPullRequest(
|
|
134
219
|
message: ProvenanceMessage,
|
|
135
220
|
sourcePr: number,
|
|
136
221
|
sourceUrl: string,
|
|
222
|
+
provenance: readonly ProvenanceMessage[] = [message],
|
|
137
223
|
): void {
|
|
138
224
|
if (
|
|
139
|
-
message.
|
|
225
|
+
(message.sourcePr !== undefined || message.sourceUrl !== undefined) &&
|
|
140
226
|
(message.sourcePr !== sourcePr || message.sourceUrl !== sourceUrl)
|
|
141
227
|
) {
|
|
142
228
|
throw new Error(
|
|
143
229
|
`pull request ${sourceUrl}#${sourcePr} does not match provenance ${message.sourceUrl}#${message.sourcePr}`,
|
|
144
230
|
);
|
|
145
231
|
}
|
|
232
|
+
const hasExplicitLocalAssociation = provenance.some(
|
|
233
|
+
(item) => item.sourceType !== "github-pull-request" && item.sourcePr === sourcePr,
|
|
234
|
+
);
|
|
235
|
+
if (
|
|
236
|
+
hasExplicitLocalAssociation &&
|
|
237
|
+
message.sourceType !== "github-pull-request" &&
|
|
238
|
+
(message.sourcePr !== sourcePr || message.sourceUrl !== sourceUrl)
|
|
239
|
+
) {
|
|
240
|
+
throw new Error(
|
|
241
|
+
`pull request ${sourceUrl}#${sourcePr} has explicit local provenance; unbound local provenance cannot be selected`,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
146
244
|
}
|
|
147
245
|
|
|
148
246
|
export function extractProvenanceMessages(
|
|
@@ -418,13 +516,19 @@ async function listJsonFiles(root: string): Promise<string[]> {
|
|
|
418
516
|
const entries = await readdir(root, { recursive: true, withFileTypes: true }).catch(() => []);
|
|
419
517
|
return entries
|
|
420
518
|
.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl"))
|
|
421
|
-
.map((entry) => join(entry.parentPath, entry.name))
|
|
519
|
+
.map((entry) => join(entry.parentPath, entry.name))
|
|
520
|
+
.sort();
|
|
422
521
|
}
|
|
423
522
|
|
|
424
523
|
function encodeSessionPath(path: string): string {
|
|
425
524
|
return path.replaceAll("/", "-");
|
|
426
525
|
}
|
|
427
526
|
|
|
527
|
+
function displaySessionPath(path: string, homeDirectory: string): string {
|
|
528
|
+
const fromHome = relative(homeDirectory, path);
|
|
529
|
+
return fromHome && !fromHome.startsWith("..") ? `~/${fromHome}` : path;
|
|
530
|
+
}
|
|
531
|
+
|
|
428
532
|
function deduplicateMessages(messages: readonly ProvenanceMessage[]): ProvenanceMessage[] {
|
|
429
533
|
const seen = new Set<string>();
|
|
430
534
|
return messages.filter((message) => {
|
package/src/reaudit-main.ts
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { access, mkdir, mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { basename, dirname, join, resolve } from "node:path";
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
7
6
|
import { parseArgs } from "node:util";
|
|
8
7
|
import {
|
|
9
8
|
COUPLING_REVIEW_MODEL,
|
|
@@ -19,7 +18,8 @@ import {
|
|
|
19
18
|
} from "./coupling.js";
|
|
20
19
|
import { parallelMap } from "./parallel.js";
|
|
21
20
|
import { runCommand } from "./process.js";
|
|
22
|
-
import {
|
|
21
|
+
import { projectRoot } from "./project-paths.js";
|
|
22
|
+
import { createSandboxExecutor, type SandboxExecutor } from "./sandbox/index.js";
|
|
23
23
|
import { loadPiModelAuth } from "./subscription-auth.js";
|
|
24
24
|
|
|
25
25
|
const parsed = parseArgs({
|
|
@@ -182,7 +182,7 @@ async function auditTask(
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
function assetRoot(): string {
|
|
185
|
-
return
|
|
185
|
+
return projectRoot(import.meta.url);
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
function positiveInteger(value: string | undefined, label: string): number {
|
package/src/repair-main.ts
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import { access, cp, mkdir, mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
|
-
import { basename,
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { basename, join, resolve } from "node:path";
|
|
7
6
|
import { parseArgs } from "node:util";
|
|
8
7
|
import { defaultStandaloneConcurrency, loadWorkerConfig } from "./config.js";
|
|
9
8
|
import { parallelMap } from "./parallel.js";
|
|
10
9
|
import { runCommand } from "./process.js";
|
|
11
|
-
import {
|
|
10
|
+
import { projectRoot } from "./project-paths.js";
|
|
11
|
+
import { createSandboxExecutor } from "./sandbox/index.js";
|
|
12
12
|
import { loadCodexModelAuth } from "./subscription-auth.js";
|
|
13
13
|
|
|
14
14
|
const parsed = parseArgs({
|
|
@@ -189,7 +189,7 @@ function reviewReport(value: unknown): { readonly tasks: readonly ReviewTask[] }
|
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
function assetRoot(): string {
|
|
192
|
-
return
|
|
192
|
+
return projectRoot(import.meta.url);
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
function positiveInteger(value: string | undefined, label: string): number {
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import type { SelfBenchWorkerConfig } from "./config.js";
|
|
2
|
-
import { DockerSandboxExecutor } from "./docker-executor.js";
|
|
3
|
-
import { ModalSandboxExecutor } from "./modal-executor.js";
|
|
4
|
-
import { TimeoutCappedSandboxExecutor } from "./sandbox-timeout.js";
|
|
5
|
-
import { VercelSandboxExecutor } from "./vercel-executor.js";
|
|
6
|
-
|
|
7
1
|
export interface SandboxFile {
|
|
8
2
|
readonly path: string;
|
|
9
3
|
readonly contents: Uint8Array | string;
|
|
@@ -41,21 +35,18 @@ export interface SandboxResult {
|
|
|
41
35
|
readonly outputs: Readonly<Record<string, Uint8Array>>;
|
|
42
36
|
}
|
|
43
37
|
|
|
38
|
+
export class SandboxExecutionError extends Error {
|
|
39
|
+
constructor(
|
|
40
|
+
message: string,
|
|
41
|
+
readonly result: SandboxResult,
|
|
42
|
+
options?: ErrorOptions,
|
|
43
|
+
) {
|
|
44
|
+
super(message, options);
|
|
45
|
+
this.name = "SandboxExecutionError";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
44
49
|
export interface SandboxExecutor {
|
|
45
50
|
run(request: SandboxRequest, options?: SandboxRunOptions): Promise<SandboxResult>;
|
|
46
51
|
close(): void;
|
|
47
52
|
}
|
|
48
|
-
|
|
49
|
-
export function createSandboxExecutor(config: SelfBenchWorkerConfig["execution"]): SandboxExecutor {
|
|
50
|
-
switch (config.kind) {
|
|
51
|
-
case "docker":
|
|
52
|
-
return new DockerSandboxExecutor(config);
|
|
53
|
-
case "modal":
|
|
54
|
-
return new ModalSandboxExecutor(config);
|
|
55
|
-
case "vercel":
|
|
56
|
-
return new TimeoutCappedSandboxExecutor(
|
|
57
|
-
new VercelSandboxExecutor(config),
|
|
58
|
-
config.timeoutCapMs,
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SelfBenchWorkerConfig } from "../config.js";
|
|
2
|
+
import { DockerSandboxExecutor } from "./providers/docker/executor.js";
|
|
3
|
+
import { ModalSandboxExecutor } from "./providers/modal/executor.js";
|
|
4
|
+
import { VercelSandboxExecutor } from "./providers/vercel/executor.js";
|
|
5
|
+
import { TimeoutCappedSandboxExecutor } from "./timeout.js";
|
|
6
|
+
|
|
7
|
+
export * from "./contracts.js";
|
|
8
|
+
|
|
9
|
+
import type { SandboxExecutor } from "./contracts.js";
|
|
10
|
+
|
|
11
|
+
export function createSandboxExecutor(config: SelfBenchWorkerConfig["execution"]): SandboxExecutor {
|
|
12
|
+
switch (config.kind) {
|
|
13
|
+
case "docker":
|
|
14
|
+
return new DockerSandboxExecutor(config);
|
|
15
|
+
case "modal":
|
|
16
|
+
return new ModalSandboxExecutor(config);
|
|
17
|
+
case "vercel":
|
|
18
|
+
return new TimeoutCappedSandboxExecutor(
|
|
19
|
+
new VercelSandboxExecutor(config),
|
|
20
|
+
config.timeoutCapMs,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { readdir } from "node:fs/promises";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
-
import { compileHarborTask } from "
|
|
5
|
+
import { compileHarborTask } from "../../harbor-task.js";
|
|
6
6
|
|
|
7
7
|
const [tasksRoot, repositoryDirectory, outputDirectory] = process.argv.slice(2);
|
|
8
8
|
if (!tasksRoot || !repositoryDirectory || !outputDirectory) {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { access, mkdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { runCommand } from "../../process.js";
|
|
4
|
+
|
|
5
|
+
export interface PreparedRepairTask {
|
|
6
|
+
readonly extractedDirectory: string;
|
|
7
|
+
readonly taskDirectory: string;
|
|
8
|
+
readonly repositoryDirectory: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function prepareRepairTask(
|
|
12
|
+
archivePath: string,
|
|
13
|
+
workDirectory = "/work",
|
|
14
|
+
): Promise<PreparedRepairTask> {
|
|
15
|
+
const extractedDirectory = join(workDirectory, "task");
|
|
16
|
+
const repositoryDirectory = join(workDirectory, "repo");
|
|
17
|
+
await Promise.all([mkdir(extractedDirectory, { recursive: true }), mkdir(repositoryDirectory)]);
|
|
18
|
+
await runCommand("tar", ["-xzf", archivePath, "-C", extractedDirectory]);
|
|
19
|
+
const taskDirectory = await access(join(extractedDirectory, "instruction.md")).then(
|
|
20
|
+
() => extractedDirectory,
|
|
21
|
+
() => join(extractedDirectory, "harbor-task"),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
await runCommand("tar", [
|
|
25
|
+
"-xzf",
|
|
26
|
+
join(taskDirectory, "tests/repo.tar.gz"),
|
|
27
|
+
"-C",
|
|
28
|
+
repositoryDirectory,
|
|
29
|
+
]);
|
|
30
|
+
await runCommand("git", ["-C", repositoryDirectory, "init", "-q"]);
|
|
31
|
+
await runCommand("git", ["-C", repositoryDirectory, "config", "user.name", "SelfBench"]);
|
|
32
|
+
await runCommand("git", ["-C", repositoryDirectory, "config", "user.email", "selfbench@local"]);
|
|
33
|
+
await runCommand("git", ["-C", repositoryDirectory, "add", "-A"]);
|
|
34
|
+
await runCommand("git", ["-C", repositoryDirectory, "commit", "-qm", "base"]);
|
|
35
|
+
await runCommand("git", [
|
|
36
|
+
"-C",
|
|
37
|
+
repositoryDirectory,
|
|
38
|
+
"apply",
|
|
39
|
+
join(taskDirectory, "tests/test.patch"),
|
|
40
|
+
]);
|
|
41
|
+
await runCommand("git", ["-C", repositoryDirectory, "add", "-N", "--all"]);
|
|
42
|
+
|
|
43
|
+
return { extractedDirectory, taskDirectory, repositoryDirectory };
|
|
44
|
+
}
|
|
@@ -1,25 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
4
|
import { homedir, tmpdir } from "node:os";
|
|
5
5
|
import { join } from "node:path";
|
|
6
|
-
import { sha256 } from "
|
|
7
|
-
import { runCommand } from "
|
|
8
|
-
import { assertRepairPaths, patchPaths, repairPrompt } from "
|
|
6
|
+
import { sha256 } from "../../hash.js";
|
|
7
|
+
import { runCommand } from "../../process.js";
|
|
8
|
+
import { assertRepairPaths, patchPaths, repairPrompt } from "../../repair.js";
|
|
9
|
+
import { prepareRepairTask } from "./prepare-repair.js";
|
|
9
10
|
|
|
10
11
|
const [archivePath, reviewPath, outputArchive, outputReport] = process.argv.slice(2);
|
|
11
12
|
if (!archivePath || !reviewPath || !outputArchive || !outputReport) {
|
|
12
13
|
throw new Error("usage: sandbox-repair TASK.tar.gz REVIEW.json OUTPUT.tar.gz OUTPUT-REPORT.json");
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
const extractedDirectory =
|
|
16
|
-
|
|
17
|
-
await Promise.all([mkdir(extractedDirectory, { recursive: true }), mkdir(repositoryDirectory)]);
|
|
18
|
-
await runCommand("tar", ["-xzf", archivePath, "-C", extractedDirectory]);
|
|
19
|
-
const taskDirectory = await access(join(extractedDirectory, "instruction.md")).then(
|
|
20
|
-
() => extractedDirectory,
|
|
21
|
-
() => join(extractedDirectory, "harbor-task"),
|
|
22
|
-
);
|
|
16
|
+
const { extractedDirectory, taskDirectory, repositoryDirectory } =
|
|
17
|
+
await prepareRepairTask(archivePath);
|
|
23
18
|
|
|
24
19
|
const [instruction, originalPatch, review] = await Promise.all([
|
|
25
20
|
readFile(join(taskDirectory, "instruction.md"), "utf8"),
|
|
@@ -31,25 +26,6 @@ const manifest = JSON.parse(await readFile(manifestPath, "utf8")) as Record<stri
|
|
|
31
26
|
const taskId = typeof manifest.taskId === "string" ? manifest.taskId : "unknown-task";
|
|
32
27
|
const allowedPaths = patchPaths(originalPatch);
|
|
33
28
|
|
|
34
|
-
await runCommand("tar", [
|
|
35
|
-
"-xzf",
|
|
36
|
-
join(taskDirectory, "tests/repo.tar.gz"),
|
|
37
|
-
"-C",
|
|
38
|
-
repositoryDirectory,
|
|
39
|
-
]);
|
|
40
|
-
await runCommand("git", ["-C", repositoryDirectory, "init", "-q"]);
|
|
41
|
-
await runCommand("git", ["-C", repositoryDirectory, "config", "user.name", "SelfBench"]);
|
|
42
|
-
await runCommand("git", ["-C", repositoryDirectory, "config", "user.email", "selfbench@local"]);
|
|
43
|
-
await runCommand("git", ["-C", repositoryDirectory, "add", "-A"]);
|
|
44
|
-
await runCommand("git", ["-C", repositoryDirectory, "commit", "-qm", "base"]);
|
|
45
|
-
await runCommand("git", [
|
|
46
|
-
"-C",
|
|
47
|
-
repositoryDirectory,
|
|
48
|
-
"apply",
|
|
49
|
-
join(taskDirectory, "tests/test.patch"),
|
|
50
|
-
]);
|
|
51
|
-
await runCommand("git", ["-C", repositoryDirectory, "add", "-N", "--all"]);
|
|
52
|
-
|
|
53
29
|
const codexAuth = process.env.SELFBENCH_CODEX_AUTH_JSON;
|
|
54
30
|
const apiKey = process.env.OPENAI_API_KEY;
|
|
55
31
|
if (!apiKey && !codexAuth) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import { reviewCouplingWithCodex } from "
|
|
2
|
+
import { reviewCouplingWithCodex } from "../../codex-review.js";
|
|
3
3
|
|
|
4
4
|
const apiKey = process.env.OPENAI_API_KEY;
|
|
5
5
|
const authJson = process.env.SELFBENCH_PI_AUTH_JSON;
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
4
|
import { homedir, tmpdir } from "node:os";
|
|
5
5
|
import { join } from "node:path";
|
|
6
|
-
import { taskDefinitionSchema } from "
|
|
7
|
-
import { runCommand } from "
|
|
6
|
+
import { taskDefinitionSchema } from "../../contracts.js";
|
|
7
|
+
import { runCommand } from "../../process.js";
|
|
8
8
|
import {
|
|
9
9
|
assertValidationRepair,
|
|
10
10
|
validationRepairPaths,
|
|
11
11
|
validationRepairPrompt,
|
|
12
|
-
} from "
|
|
12
|
+
} from "../../validation-repair.js";
|
|
13
|
+
import { prepareRepairTask } from "./prepare-repair.js";
|
|
13
14
|
|
|
14
15
|
const [archivePath, definitionPath, diagnosticsPath, outputDefinition, outputPatch, outputReport] =
|
|
15
16
|
process.argv.slice(2);
|
|
@@ -26,14 +27,7 @@ if (
|
|
|
26
27
|
);
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
const
|
|
30
|
-
const repositoryDirectory = "/work/repo";
|
|
31
|
-
await Promise.all([mkdir(extractedDirectory, { recursive: true }), mkdir(repositoryDirectory)]);
|
|
32
|
-
await runCommand("tar", ["-xzf", archivePath, "-C", extractedDirectory]);
|
|
33
|
-
const taskDirectory = await access(join(extractedDirectory, "instruction.md")).then(
|
|
34
|
-
() => extractedDirectory,
|
|
35
|
-
() => join(extractedDirectory, "harbor-task"),
|
|
36
|
-
);
|
|
30
|
+
const { taskDirectory, repositoryDirectory } = await prepareRepairTask(archivePath);
|
|
37
31
|
const [instruction, originalPatch, diagnostics, originalDefinitionBytes] = await Promise.all([
|
|
38
32
|
readFile(join(taskDirectory, "instruction.md"), "utf8"),
|
|
39
33
|
readFile(join(taskDirectory, "tests/test.patch"), "utf8"),
|
|
@@ -43,24 +37,6 @@ const [instruction, originalPatch, diagnostics, originalDefinitionBytes] = await
|
|
|
43
37
|
const originalDefinition = taskDefinitionSchema.parse(JSON.parse(originalDefinitionBytes));
|
|
44
38
|
const allowedPaths = validationRepairPaths(originalPatch);
|
|
45
39
|
|
|
46
|
-
await runCommand("tar", [
|
|
47
|
-
"-xzf",
|
|
48
|
-
join(taskDirectory, "tests/repo.tar.gz"),
|
|
49
|
-
"-C",
|
|
50
|
-
repositoryDirectory,
|
|
51
|
-
]);
|
|
52
|
-
await runCommand("git", ["-C", repositoryDirectory, "init", "-q"]);
|
|
53
|
-
await runCommand("git", ["-C", repositoryDirectory, "config", "user.name", "SelfBench"]);
|
|
54
|
-
await runCommand("git", ["-C", repositoryDirectory, "config", "user.email", "selfbench@local"]);
|
|
55
|
-
await runCommand("git", ["-C", repositoryDirectory, "add", "-A"]);
|
|
56
|
-
await runCommand("git", ["-C", repositoryDirectory, "commit", "-qm", "base"]);
|
|
57
|
-
await runCommand("git", [
|
|
58
|
-
"-C",
|
|
59
|
-
repositoryDirectory,
|
|
60
|
-
"apply",
|
|
61
|
-
join(taskDirectory, "tests/test.patch"),
|
|
62
|
-
]);
|
|
63
|
-
await runCommand("git", ["-C", repositoryDirectory, "add", "-N", "--all"]);
|
|
64
40
|
await Promise.all([
|
|
65
41
|
writeFile("/work/definition.json", `${JSON.stringify(originalDefinition, null, 2)}\n`),
|
|
66
42
|
writeFile("/work/gold.patch", await readFile(join(taskDirectory, "solution/gold.patch"))),
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { dirname, join, relative, resolve } from "node:path";
|
|
4
|
-
import type { SelfBenchConfig } from "
|
|
5
|
-
import { runCommand } from "
|
|
4
|
+
import type { SelfBenchConfig } from "../../../config.js";
|
|
5
|
+
import { runCommand } from "../../../process.js";
|
|
6
6
|
import type {
|
|
7
7
|
SandboxExecutor,
|
|
8
8
|
SandboxRequest,
|
|
9
9
|
SandboxResult,
|
|
10
10
|
SandboxRunOptions,
|
|
11
|
-
} from "
|
|
11
|
+
} from "../../contracts.js";
|
|
12
12
|
|
|
13
13
|
export class DockerSandboxExecutor implements SandboxExecutor {
|
|
14
14
|
readonly #config: Extract<SelfBenchConfig["execution"], { kind: "docker" }>;
|