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
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
|
-
import {
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { join } from "node:path";
|
|
5
4
|
import { CancelledFailure, Context } from "@temporalio/activity";
|
|
6
5
|
import { ApplicationFailure } from "@temporalio/common";
|
|
7
6
|
import { z } from "zod";
|
|
@@ -43,8 +42,21 @@ import {
|
|
|
43
42
|
import { refreshHarborTask } from "../harbor-task.js";
|
|
44
43
|
import { sha256 } from "../hash.js";
|
|
45
44
|
import { runCommand } from "../process.js";
|
|
46
|
-
import {
|
|
47
|
-
import {
|
|
45
|
+
import { projectRoot } from "../project-paths.js";
|
|
46
|
+
import {
|
|
47
|
+
assertProvenanceMatchesPullRequest,
|
|
48
|
+
collectGitHubPullRequestProvenance,
|
|
49
|
+
combineRunProvenance,
|
|
50
|
+
type ProvenanceMessage,
|
|
51
|
+
provenanceMessageSchema,
|
|
52
|
+
} from "../provenance.js";
|
|
53
|
+
import {
|
|
54
|
+
createSandboxExecutor,
|
|
55
|
+
SandboxExecutionError,
|
|
56
|
+
type SandboxExecutor,
|
|
57
|
+
type SandboxResult,
|
|
58
|
+
type SandboxRunOptions,
|
|
59
|
+
} from "../sandbox/index.js";
|
|
48
60
|
import { githubToken, loadCodexModelAuth, loadPiModelAuth } from "../subscription-auth.js";
|
|
49
61
|
|
|
50
62
|
const HARBOR_INFRASTRUCTURE_FAILURE_TYPE = "HarborInfrastructureFailure";
|
|
@@ -62,7 +74,6 @@ const discoveryPlanSchema = z.object({
|
|
|
62
74
|
sourceUrl: z.string().url(),
|
|
63
75
|
baseCommit: z.string().regex(/^[0-9a-f]{40}$/i),
|
|
64
76
|
completedCommit: z.string().regex(/^[0-9a-f]{40}$/i),
|
|
65
|
-
request: z.string().min(1),
|
|
66
77
|
provenance: z.object({
|
|
67
78
|
sourceType: z.enum(["pi", "claude-code", "codex", "generic", "github-pull-request"]),
|
|
68
79
|
sessionId: z.string().min(1),
|
|
@@ -105,6 +116,7 @@ export interface ExportInput {
|
|
|
105
116
|
}
|
|
106
117
|
|
|
107
118
|
export interface SelfBenchActivities {
|
|
119
|
+
collectRunProvenance(run: RunRequest): Promise<ArtifactRef>;
|
|
108
120
|
discoverCandidateShard(input: DiscoveryShardInput): Promise<DiscoveryResult>;
|
|
109
121
|
authorCandidate(input: AuthorCandidateInput): Promise<AuthorOutcome>;
|
|
110
122
|
validateTask(input: TaskStageInput): Promise<ValidationResult>;
|
|
@@ -119,6 +131,7 @@ export function createActivities(config: SelfBenchWorkerConfig): SelfBenchActivi
|
|
|
119
131
|
const store = createArtifactStore(config.artifact);
|
|
120
132
|
const sandbox = createSandboxExecutor(config.execution);
|
|
121
133
|
return {
|
|
134
|
+
collectRunProvenance: (run) => collectRunProvenance(store, run),
|
|
122
135
|
discoverCandidateShard: (input) => discoverCandidateShard(store, sandbox, input),
|
|
123
136
|
authorCandidate: (input) => authorCandidate(store, sandbox, input),
|
|
124
137
|
validateTask: (input) => validateTask(store, config.harborEnvironment, input),
|
|
@@ -130,6 +143,29 @@ export function createActivities(config: SelfBenchWorkerConfig): SelfBenchActivi
|
|
|
130
143
|
};
|
|
131
144
|
}
|
|
132
145
|
|
|
146
|
+
async function collectRunProvenance(store: ArtifactStore, run: RunRequest): Promise<ArtifactRef> {
|
|
147
|
+
return await withActivityHeartbeats(
|
|
148
|
+
"collecting merged GitHub pull requests",
|
|
149
|
+
async ({ signal }) => {
|
|
150
|
+
const [localBytes, token] = await Promise.all([store.get(run.provenance), githubToken()]);
|
|
151
|
+
const local = parseProvenance(localBytes);
|
|
152
|
+
const github = await collectGitHubPullRequestProvenance(run.repository.url, token, signal);
|
|
153
|
+
const messages = combineRunProvenance(run.repository.url, local, github);
|
|
154
|
+
if (messages.length === 0) {
|
|
155
|
+
throw ApplicationFailure.nonRetryable(
|
|
156
|
+
"no sanitized local-session or GitHub pull-request provenance was found",
|
|
157
|
+
"NoProvenance",
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
return await store.put(
|
|
161
|
+
`runs/${run.runId}/input/combined-provenance-attempt-${Context.current().info.attempt}.jsonl`,
|
|
162
|
+
Buffer.from(`${messages.map((message) => JSON.stringify(message)).join("\n")}\n`),
|
|
163
|
+
"application/x-ndjson",
|
|
164
|
+
);
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
133
169
|
async function discoverCandidateShard(
|
|
134
170
|
store: ArtifactStore,
|
|
135
171
|
sandbox: SandboxExecutor,
|
|
@@ -180,36 +216,43 @@ async function discoverCandidateShard(
|
|
|
180
216
|
Context.current().heartbeat(
|
|
181
217
|
`starting discovery wave ${input.wave} shard ${input.shardIndex} over ${shard.length} messages`,
|
|
182
218
|
);
|
|
183
|
-
const result = await
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
219
|
+
const result = await runSandboxWithFailureLog(store, `${attemptPrefix}/modal.log`, () =>
|
|
220
|
+
withActivityHeartbeats(
|
|
221
|
+
`running discovery wave ${input.wave} shard ${input.shardIndex}`,
|
|
222
|
+
(options) =>
|
|
223
|
+
sandbox.run(
|
|
224
|
+
{
|
|
225
|
+
runId: run.runId,
|
|
226
|
+
stage: `discover-${input.wave}-${input.shardIndex}`,
|
|
227
|
+
timeoutMs: DISCOVERY_TIMEOUT_MS,
|
|
228
|
+
inactivityTimeoutMs: AGENT_INACTIVITY_TIMEOUT_MS,
|
|
229
|
+
files: [
|
|
230
|
+
{ path: "/work/discovery.ts", contents: extension },
|
|
231
|
+
{
|
|
232
|
+
path: "/work/excluded-source-prs.json",
|
|
233
|
+
contents: JSON.stringify(input.excludedSourcePrs),
|
|
234
|
+
},
|
|
235
|
+
{ path: "/work/provenance.jsonl", contents: shardBytes },
|
|
236
|
+
{ path: "/work/prompt.txt", contents: discoveryShardPrompt(input, shard.length) },
|
|
237
|
+
],
|
|
238
|
+
outputPaths: ["/work/discovery.json"],
|
|
239
|
+
secrets: {
|
|
240
|
+
...(piAuth.apiKey ? { OPENAI_API_KEY: piAuth.apiKey } : {}),
|
|
241
|
+
...(piAuth.authJson ? { SELFBENCH_PI_AUTH_JSON: piAuth.authJson } : {}),
|
|
242
|
+
...(ghToken ? { GH_TOKEN: ghToken } : {}),
|
|
243
|
+
},
|
|
244
|
+
environment: {
|
|
245
|
+
SOURCE_REPO_URL: run.repository.url,
|
|
246
|
+
SOURCE_COMMIT: run.repository.commit,
|
|
247
|
+
AUTHOR_MODEL: run.authoring.model,
|
|
248
|
+
SELFBENCH_DISCOVERY_EXCLUSIONS: "/work/excluded-source-prs.json",
|
|
249
|
+
SELFBENCH_DISCOVERY_OUTPUT: "/work/discovery.json",
|
|
250
|
+
},
|
|
251
|
+
command: ["bash", "-lc", modalAgentScript("discovery.ts", "submit_discovery")],
|
|
208
252
|
},
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
),
|
|
253
|
+
options,
|
|
254
|
+
),
|
|
255
|
+
),
|
|
213
256
|
);
|
|
214
257
|
planBytes = result.outputs["/work/discovery.json"];
|
|
215
258
|
logs = await store.put(
|
|
@@ -227,6 +270,7 @@ async function discoverCandidateShard(
|
|
|
227
270
|
store,
|
|
228
271
|
run,
|
|
229
272
|
shard,
|
|
273
|
+
provenance,
|
|
230
274
|
planBytes,
|
|
231
275
|
logs,
|
|
232
276
|
input.targetCounts,
|
|
@@ -240,6 +284,7 @@ async function materializeDiscovery(
|
|
|
240
284
|
store: ArtifactStore,
|
|
241
285
|
run: RunRequest,
|
|
242
286
|
provenance: readonly ProvenanceMessage[],
|
|
287
|
+
allProvenance: readonly ProvenanceMessage[],
|
|
243
288
|
planBytes: Uint8Array,
|
|
244
289
|
logs: ArtifactRef,
|
|
245
290
|
maxCandidates: Readonly<Record<Difficulty, number>>,
|
|
@@ -251,16 +296,7 @@ async function materializeDiscovery(
|
|
|
251
296
|
|
|
252
297
|
const candidates: Candidate[] = [];
|
|
253
298
|
for (const raw of plan.candidates) {
|
|
254
|
-
const message = provenance
|
|
255
|
-
(item) =>
|
|
256
|
-
item.sourceType === raw.provenance.sourceType &&
|
|
257
|
-
item.sessionId === raw.provenance.sessionId &&
|
|
258
|
-
item.messageIndex === raw.provenance.messageIndex,
|
|
259
|
-
);
|
|
260
|
-
if (!message) {
|
|
261
|
-
throw new Error(`candidate ${raw.candidateId} references unknown provenance`);
|
|
262
|
-
}
|
|
263
|
-
assertProvenanceMatchesPullRequest(message, raw.sourcePr, raw.sourceUrl);
|
|
299
|
+
const message = selectCandidateProvenance(provenance, allProvenance, raw);
|
|
264
300
|
const staged = Buffer.from(
|
|
265
301
|
`${JSON.stringify({ source: message, messages: [{ role: "user", content: message.content }] })}\n`,
|
|
266
302
|
);
|
|
@@ -287,6 +323,38 @@ async function materializeDiscovery(
|
|
|
287
323
|
return { candidates, report };
|
|
288
324
|
}
|
|
289
325
|
|
|
326
|
+
export function selectCandidateProvenance(
|
|
327
|
+
available: readonly ProvenanceMessage[],
|
|
328
|
+
allProvenance: readonly ProvenanceMessage[],
|
|
329
|
+
candidate: {
|
|
330
|
+
readonly candidateId: string;
|
|
331
|
+
readonly sourcePr: number;
|
|
332
|
+
readonly sourceUrl: string;
|
|
333
|
+
readonly provenance: {
|
|
334
|
+
readonly sourceType: ProvenanceMessage["sourceType"];
|
|
335
|
+
readonly sessionId: string;
|
|
336
|
+
readonly messageIndex: number;
|
|
337
|
+
};
|
|
338
|
+
},
|
|
339
|
+
): ProvenanceMessage {
|
|
340
|
+
const message = available.find(
|
|
341
|
+
(item) =>
|
|
342
|
+
item.sourceType === candidate.provenance.sourceType &&
|
|
343
|
+
item.sessionId === candidate.provenance.sessionId &&
|
|
344
|
+
item.messageIndex === candidate.provenance.messageIndex,
|
|
345
|
+
);
|
|
346
|
+
if (!message) {
|
|
347
|
+
throw new Error(`candidate ${candidate.candidateId} references unknown provenance`);
|
|
348
|
+
}
|
|
349
|
+
assertProvenanceMatchesPullRequest(
|
|
350
|
+
message,
|
|
351
|
+
candidate.sourcePr,
|
|
352
|
+
candidate.sourceUrl,
|
|
353
|
+
allProvenance,
|
|
354
|
+
);
|
|
355
|
+
return message;
|
|
356
|
+
}
|
|
357
|
+
|
|
290
358
|
function parseDiscoveryPlan(
|
|
291
359
|
planBytes: Uint8Array,
|
|
292
360
|
maxCandidates: Readonly<Record<Difficulty, number>>,
|
|
@@ -357,9 +425,9 @@ async function authorCandidate(
|
|
|
357
425
|
githubToken(),
|
|
358
426
|
]);
|
|
359
427
|
const prompt = authoringPrompt(run, candidate);
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
(options) =>
|
|
428
|
+
const attemptLogKey = `runs/${run.runId}/authoring/${candidate.candidateId}/attempt-${Context.current().info.attempt}/modal.log`;
|
|
429
|
+
const result = await runSandboxWithFailureLog(store, attemptLogKey, () =>
|
|
430
|
+
withActivityHeartbeats(`running author sandbox for ${candidate.candidateId}`, (options) =>
|
|
363
431
|
sandbox.run(
|
|
364
432
|
{
|
|
365
433
|
runId: run.runId,
|
|
@@ -389,9 +457,10 @@ async function authorCandidate(
|
|
|
389
457
|
},
|
|
390
458
|
options,
|
|
391
459
|
),
|
|
460
|
+
),
|
|
392
461
|
);
|
|
393
462
|
const log = await store.put(
|
|
394
|
-
|
|
463
|
+
attemptLogKey,
|
|
395
464
|
Buffer.from(`${result.stdout}\n${result.stderr}`),
|
|
396
465
|
"text/plain",
|
|
397
466
|
);
|
|
@@ -928,13 +997,7 @@ async function buildExport(store: ArtifactStore, input: ExportInput): Promise<Ar
|
|
|
928
997
|
}
|
|
929
998
|
|
|
930
999
|
function discoveryShardPrompt(input: DiscoveryShardInput, provenanceCount: number): string {
|
|
931
|
-
|
|
932
|
-
input.excludedSourcePrs.length > 0
|
|
933
|
-
? `Do not return any of these already-considered pull requests: ${input.excludedSourcePrs.join(", ")}.`
|
|
934
|
-
: "No pull requests have been considered yet.";
|
|
935
|
-
return `Discover and rank SelfBench candidates from this assigned provenance shard. Return at most easy=${input.targetCounts.easy}, medium=${input.targetCounts.medium}, hard=${input.targetCounts.hard}.
|
|
936
|
-
|
|
937
|
-
${exclusions}
|
|
1000
|
+
return `Discover and rank SelfBench candidates from this assigned provenance shard. Return at most easy=${input.targetCounts.easy}, medium=${input.targetCounts.medium}, hard=${input.targetCounts.hard}. Before selecting a pull request, query its number against /work/excluded-source-prs.json with jq; do not print or read the full exclusion list into context. The submit_discovery tool also removes any already-considered pull requests as a final safeguard.
|
|
938
1001
|
|
|
939
1002
|
Assign each candidate exactly one difficulty using the separable implementation core, excluding tests, generated code, formatting churn, and unrelated cleanup:
|
|
940
1003
|
- easy: at least 20 changed implementation lines across at least 1 implementation file, with at least 1 viable fail-to-pass test;
|
|
@@ -944,7 +1007,7 @@ Choose the highest tier whose thresholds the candidate honestly meets. Every tie
|
|
|
944
1007
|
|
|
945
1008
|
Every candidate must be a pull request from SOURCE_REPO_URL. Repository names or pull requests mentioned inside provenance messages are context only; never follow them into another repository. sourceUrl must be the canonical GitHub pull-request URL for SOURCE_REPO_URL and sourcePr must match its number.
|
|
946
1009
|
|
|
947
|
-
The sanitized corpus at /work/provenance.jsonl contains ${provenanceCount} human requests. Local Pi, Claude Code, and Codex requests are preferred when they clearly correspond to the same change. Records with sourceType github-pull-request contain the non-bot PR author's exact title and optional body and are valid fallback provenance
|
|
1010
|
+
The sanitized corpus at /work/provenance.jsonl contains ${provenanceCount} human requests. Local Pi, Claude Code, and Codex requests are preferred when they clearly correspond to the same change. A local record with sourcePr and sourceUrl has an explicit user-supplied association and may be used only for that PR. Records with sourceType github-pull-request contain the non-bot PR author's exact title and optional body and are valid fallback provenance; they too may be used only for their own sourcePr and sourceUrl. Select provenance only by an exact sourceType, sessionId, and messageIndex present in the corpus. Never invent or reconstruct request text from implementation or tests. Inspect merged PR metadata and diffs with gh and git. Resolve the exact base and completed 40-character commits. Do not modify the repository.
|
|
948
1011
|
|
|
949
1012
|
Return fewer candidates when the shard does not contain enough valid requests; an empty candidate list is valid. Call submit_discovery exactly once. Do not return prose after the tool call.`;
|
|
950
1013
|
}
|
|
@@ -985,9 +1048,9 @@ function modalAgentScript(extension: string, tool: string): string {
|
|
|
985
1048
|
return `${sandboxBootstrap()}
|
|
986
1049
|
clone_source
|
|
987
1050
|
cd /work/repo
|
|
988
|
-
pi --print --mode json --no-session --no-approve --no-skills --no-prompt-templates --no-context-files --no-extensions \\
|
|
1051
|
+
run_with_heartbeat pi --print --mode json --no-session --no-approve --no-skills --no-prompt-templates --no-context-files --no-extensions \\
|
|
989
1052
|
--extension /work/${extension} --provider "$(model_provider)" --model "$AUTHOR_MODEL" --thinking high \\
|
|
990
|
-
--tools read,bash,grep,find,ls,${tool} "$(cat /work/prompt.txt)"
|
|
1053
|
+
--tools read,bash,grep,find,ls,${tool} "$(cat /work/prompt.txt)"`;
|
|
991
1054
|
}
|
|
992
1055
|
|
|
993
1056
|
function authoringScript(): string {
|
|
@@ -995,10 +1058,10 @@ function authoringScript(): string {
|
|
|
995
1058
|
clone_source
|
|
996
1059
|
mkdir -p /work/tasks
|
|
997
1060
|
cd /work/repo
|
|
998
|
-
pi --print --mode json --no-session --no-approve --no-prompt-templates --no-context-files --no-extensions \\
|
|
1061
|
+
run_with_heartbeat pi --print --mode json --no-session --no-approve --no-prompt-templates --no-context-files --no-extensions \\
|
|
999
1062
|
--skill /work/selfbench-skill --extension /work/authoring.ts \\
|
|
1000
1063
|
--provider "$(model_provider)" --model "$AUTHOR_MODEL" --thinking high \\
|
|
1001
|
-
--tools read,bash,grep,find,ls,submit_task "$(cat /work/prompt.txt)"
|
|
1064
|
+
--tools read,bash,grep,find,ls,submit_task "$(cat /work/prompt.txt)"
|
|
1002
1065
|
node /work/sandbox-author.js /work/tasks /work/repo /work/harbor-task
|
|
1003
1066
|
cp /work/tasks/*/definition.json /work/definition.json
|
|
1004
1067
|
tar -czf /work/task.tar.gz -C /work harbor-task`;
|
|
@@ -1014,6 +1077,25 @@ fi
|
|
|
1014
1077
|
printf '%s\n' '{"transport":"auto"}' > "$HOME/.pi/agent/settings.json"
|
|
1015
1078
|
chmod 600 "$HOME/.pi/agent/settings.json"
|
|
1016
1079
|
model_provider() { [ -n "\${OPENAI_API_KEY:-}" ] && printf openai || printf openai-codex; }
|
|
1080
|
+
run_with_heartbeat() {
|
|
1081
|
+
"$@" 2>&1 &
|
|
1082
|
+
local command_pid=$!
|
|
1083
|
+
(
|
|
1084
|
+
while sleep 60; do
|
|
1085
|
+
printf '[selfbench] agent process %s still running at %s\n' "$command_pid" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" >&2
|
|
1086
|
+
done
|
|
1087
|
+
) &
|
|
1088
|
+
local heartbeat_pid=$!
|
|
1089
|
+
trap 'kill "$command_pid" "$heartbeat_pid" 2>/dev/null || true' TERM INT
|
|
1090
|
+
set +e
|
|
1091
|
+
wait "$command_pid"
|
|
1092
|
+
local command_status=$?
|
|
1093
|
+
set -e
|
|
1094
|
+
kill "$heartbeat_pid" 2>/dev/null || true
|
|
1095
|
+
wait "$heartbeat_pid" 2>/dev/null || true
|
|
1096
|
+
trap - TERM INT
|
|
1097
|
+
return "$command_status"
|
|
1098
|
+
}
|
|
1017
1099
|
cleanup() { rm -f "$HOME/.pi/agent/auth.json" "$HOME/.pi/agent/settings.json" "$HOME/.git-credentials"; }
|
|
1018
1100
|
trap cleanup EXIT
|
|
1019
1101
|
clone_source() {
|
|
@@ -1137,6 +1219,26 @@ function boundedTail(value: string, maxBytes = 8_000): string {
|
|
|
1137
1219
|
: `[truncated ${buffer.length - maxBytes} bytes]\n${buffer.subarray(-maxBytes).toString("utf8").trimEnd()}`;
|
|
1138
1220
|
}
|
|
1139
1221
|
|
|
1222
|
+
async function runSandboxWithFailureLog(
|
|
1223
|
+
store: ArtifactStore,
|
|
1224
|
+
logKey: string,
|
|
1225
|
+
action: () => Promise<SandboxResult>,
|
|
1226
|
+
): Promise<SandboxResult> {
|
|
1227
|
+
try {
|
|
1228
|
+
return await action();
|
|
1229
|
+
} catch (error) {
|
|
1230
|
+
if (!(error instanceof SandboxExecutionError)) {
|
|
1231
|
+
throw error;
|
|
1232
|
+
}
|
|
1233
|
+
const log = await store.put(
|
|
1234
|
+
logKey,
|
|
1235
|
+
Buffer.from(`${error.result.stdout}\n${error.result.stderr}`),
|
|
1236
|
+
"text/plain",
|
|
1237
|
+
);
|
|
1238
|
+
throw new Error(`${error.message}; partial log: ${log.uri}`, { cause: error });
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1140
1242
|
async function withActivityHeartbeats<T>(
|
|
1141
1243
|
detail: string,
|
|
1142
1244
|
action: (options: SandboxRunOptions & { readonly signal: AbortSignal }) => Promise<T>,
|
|
@@ -1215,12 +1317,11 @@ function parseProvenance(value: Uint8Array): ProvenanceMessage[] {
|
|
|
1215
1317
|
.toString("utf8")
|
|
1216
1318
|
.split("\n")
|
|
1217
1319
|
.filter((line) => line.trim())
|
|
1218
|
-
.map((line) => JSON.parse(line)
|
|
1320
|
+
.map((line) => provenanceMessageSchema.parse(JSON.parse(line)));
|
|
1219
1321
|
}
|
|
1220
1322
|
|
|
1221
1323
|
function readAsset(relativePath: string): Promise<Buffer> {
|
|
1222
|
-
|
|
1223
|
-
return readFile(join(root, relativePath));
|
|
1324
|
+
return readFile(join(projectRoot(import.meta.url), relativePath));
|
|
1224
1325
|
}
|
|
1225
1326
|
|
|
1226
1327
|
function rewards(trial: unknown): Record<string, unknown> {
|