@tangle-network/agent-bench 0.1.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 +15 -0
- package/package.json +35 -0
- package/src/adapters.ts +60 -0
- package/src/aec-gate.mts +217 -0
- package/src/atom-humaneval.mts +197 -0
- package/src/atom-mcp-e2e.mts +223 -0
- package/src/benchmarks/_harness.ts +206 -0
- package/src/benchmarks/aec-bench.test.mts +53 -0
- package/src/benchmarks/aec-bench.ts +319 -0
- package/src/benchmarks/appworld.test.mts +45 -0
- package/src/benchmarks/appworld.ts +426 -0
- package/src/benchmarks/cad-design.ts +429 -0
- package/src/benchmarks/cadbench.ts +135 -0
- package/src/benchmarks/cadgenbench.ts +121 -0
- package/src/benchmarks/commit0.test.mts +71 -0
- package/src/benchmarks/commit0.ts +266 -0
- package/src/benchmarks/enterpriseops-gym.test.mts +77 -0
- package/src/benchmarks/enterpriseops-gym.ts +343 -0
- package/src/benchmarks/finsearchcomp.ts +371 -0
- package/src/benchmarks/frames.ts +520 -0
- package/src/benchmarks/hotpotqa.ts +320 -0
- package/src/benchmarks/humaneval.ts +251 -0
- package/src/benchmarks/mind2web.ts +311 -0
- package/src/benchmarks/programbench.test.mts +60 -0
- package/src/benchmarks/programbench.ts +210 -0
- package/src/benchmarks/simpleqa.ts +390 -0
- package/src/benchmarks/swe-bench.ts +152 -0
- package/src/benchmarks/terminal-bench.ts +182 -0
- package/src/benchmarks/trata-hedge.ts +496 -0
- package/src/benchmarks/types.ts +58 -0
- package/src/browser/adapters/bad-design-audit.ts +153 -0
- package/src/browser/adapters/bad-design-audit.verify.ts +85 -0
- package/src/browser/adapters/bad.ts +165 -0
- package/src/browser/agent-adapter.ts +145 -0
- package/src/browser/process-adapter.ts +146 -0
- package/src/browser/run-to-spans.ts +105 -0
- package/src/browser/run-to-spans.verify.ts +89 -0
- package/src/browser/ui-reviewer.ts +200 -0
- package/src/browser/ui-reviewer.verify.ts +94 -0
- package/src/browser/verify.ts +96 -0
- package/src/clbench-codebase-gate.mts +314 -0
- package/src/clbench-context-gate.mts +305 -0
- package/src/cloud-loop.mts +138 -0
- package/src/coding-skills/minimal-diff.md +9 -0
- package/src/coding-skills/read-before-edit.md +9 -0
- package/src/coding-skills/reproduce-first.md +10 -0
- package/src/coding-skills/run-tests-after-edit.md +9 -0
- package/src/coding-skills/trace-the-failure.md +9 -0
- package/src/commit0-env-run.mts +59 -0
- package/src/commit0-env.ts +173 -0
- package/src/commit0-gate.mts +529 -0
- package/src/commit0-prereqs.sh +48 -0
- package/src/corpus-replay.mts +300 -0
- package/src/corpus-report.mts +504 -0
- package/src/corpus.test.mts +273 -0
- package/src/corpus.ts +325 -0
- package/src/decoder-live.mts +133 -0
- package/src/directives.ts +84 -0
- package/src/diverse-gate.mjs +112 -0
- package/src/egress-probe.mts +26 -0
- package/src/eops-skills/address-every-subtask.md +5 -0
- package/src/eops-skills/exact-tools-and-args.md +5 -0
- package/src/eops-skills/full-sequence-to-goal.md +5 -0
- package/src/eops-skills/ground-every-value.md +5 -0
- package/src/eops-skills/honor-the-policies.md +5 -0
- package/src/examples/README.md +58 -0
- package/src/examples/math-demo.mts +110 -0
- package/src/examples/strategy-demo.mts +119 -0
- package/src/fleet.mts +121 -0
- package/src/gate-cli.mts +101 -0
- package/src/gate.test.mts +129 -0
- package/src/gate.ts +460 -0
- package/src/generate-eval/certify.ts +178 -0
- package/src/generate-eval/schema.ts +78 -0
- package/src/humaneval-gate.mts +204 -0
- package/src/humaneval-repair-gate.mts +143 -0
- package/src/index.ts +19 -0
- package/src/mcp-mount-probe.mts +126 -0
- package/src/profile-coordinates.ts +134 -0
- package/src/profiles.ts +128 -0
- package/src/refine-loop.test.mts +106 -0
- package/src/refine-loop.ts +106 -0
- package/src/research-gate.mts +132 -0
- package/src/research-shot.ts +134 -0
- package/src/resolve-client.ts +58 -0
- package/src/router-executor.ts +51 -0
- package/src/run-pool.ts +48 -0
- package/src/runtime-hook-recorder.ts +137 -0
- package/src/sandbox-run.ts +125 -0
- package/src/search-bench/bridge.ts +124 -0
- package/src/search-bench/export.mts +0 -0
- package/src/search-bench/parametric-check.mts +63 -0
- package/src/search-bench/profiles.ts +98 -0
- package/src/search-bench/run.mts +287 -0
- package/src/search-bench/tasks-fresh.ts +688 -0
- package/src/search-bench/tasks.ts +129 -0
- package/src/search-tool.ts +95 -0
- package/src/selector.test.mts +189 -0
- package/src/selector.ts +366 -0
- package/src/skill-sandbox-smoke.mts +100 -0
- package/src/stats.mts +90 -0
- package/src/terminal-compare.ts +519 -0
- package/src/trajectory-assemble.mjs +130 -0
- package/src/trata-gate.mts +243 -0
- package/src/trata-gepa.mts +434 -0
- package/src/worker-blender.ts +230 -0
- package/src/worker-browser.ts +102 -0
- package/src/worker-build123d.ts +143 -0
- package/src/worker-cad.ts +451 -0
- package/src/worker.ts +136 -0
- package/src/workspace-loop.mts +133 -0
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commit0 Layer-1 gate runner — the verifier-grounded selector AND the
|
|
3
|
+
* observe→steer efficacy experiment on REAL stateful coding rollouts. Each shot is
|
|
4
|
+
* a fresh sandbox where an opencode agent clones the stubbed repo at base_commit,
|
|
5
|
+
* implements the source, and WRITES its diff to a file we read back over the
|
|
6
|
+
* sandbox FS — NOT pasted in the final message (a large diff truncates there →
|
|
7
|
+
* `git apply` "corrupt patch", the failure that made the generic stream-parse path
|
|
8
|
+
* unusable). The official commit0 pytest harness then grades each diff to a
|
|
9
|
+
* continuous (passed+xfail)/total reward — the within-task variance the
|
|
10
|
+
* verifier-grounded selector needs (unlike aec's per-task-deterministic scores).
|
|
11
|
+
*
|
|
12
|
+
* ARMS (comma-separated, default `random`):
|
|
13
|
+
* - random — K independent blind shots (the equal-compute control).
|
|
14
|
+
* - refineAudit — shot 0 blind, then for each later shot a TRACE-ONLY analyst
|
|
15
|
+
* (ANALYST_MODEL, default deepseek-v4-pro, off-box via the router) reads the
|
|
16
|
+
* prior shot's diff + stream-trace tail and its findings are appended to a
|
|
17
|
+
* FRESH sandbox's prompt. The analyst never sees a judge score — judging is
|
|
18
|
+
* phase 2, after every rollout, so selector≠judge holds by construction.
|
|
19
|
+
* Both arms run K shots per task: equal compute is the non-negotiable invariant
|
|
20
|
+
* (the analyst call is the steering overhead, one cheap router completion).
|
|
21
|
+
*
|
|
22
|
+
* Two phases, deliberately split:
|
|
23
|
+
* 1. ROLLOUTS run concurrently (sandbox-bound; CONCURRENCY units in flight; a
|
|
24
|
+
* steered arm's shots chain sequentially inside one unit).
|
|
25
|
+
* 2. JUDGES run SEQUENTIALLY (Docker-bound). commit0 keys its report dir on
|
|
26
|
+
* hash(test_ids), shared across a repo's attempts, so concurrent judging of the
|
|
27
|
+
* same repo races/overwrites report.json — the `None`-score bug.
|
|
28
|
+
*
|
|
29
|
+
* Judge prerequisite: the per-repo Docker image MUST exist before judging — the
|
|
30
|
+
* local Docker backend ignores `rebuild_image` (only the Modal context honors it),
|
|
31
|
+
* so run `./src/commit0-prereqs.sh <repo…>` (pulls wentingzhao/<repo>:v0, else
|
|
32
|
+
* builds via commit0.harness.build) for every repo in the task list first.
|
|
33
|
+
*
|
|
34
|
+
* Fail loud: an attempt whose rollout errored, whose diff never materialized, or
|
|
35
|
+
* whose judge harness failed is recorded as an INFRA attempt (error on the
|
|
36
|
+
* AttemptRecord, no score) and its record is marked infraError — counted +
|
|
37
|
+
* reported, excluded by corpus-report, never a silent 0.
|
|
38
|
+
*
|
|
39
|
+
* Writes one corpus RunRecord per (task, arm) (conditions `random@K`,
|
|
40
|
+
* `refineAudit@K`) the existing `corpus-replay --selector=verifier` +
|
|
41
|
+
* `corpus-report` consume unchanged.
|
|
42
|
+
*
|
|
43
|
+
* ./src/commit0-prereqs.sh wcwidth tinydb … # once per repo set
|
|
44
|
+
* dotenvx run -f … -- env N=8 K=2 ARMS=random,refineAudit \
|
|
45
|
+
* WORKER_MODEL=deepseek-v4-pro CONCURRENCY=3 CORPUS=/tmp/commit0.jsonl \
|
|
46
|
+
* tsx src/commit0-gate.mts
|
|
47
|
+
* tsx src/corpus-report.mts /tmp/commit0.jsonl # paired steering verdict
|
|
48
|
+
* tsx src/corpus-replay.mts /tmp/commit0.jsonl --selector=verifier
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
import { spawn } from 'node:child_process'
|
|
52
|
+
import { mkdtemp, rm } from 'node:fs/promises'
|
|
53
|
+
import { tmpdir } from 'node:os'
|
|
54
|
+
import { join } from 'node:path'
|
|
55
|
+
import {
|
|
56
|
+
type AgentRunSpec,
|
|
57
|
+
type Deliverable,
|
|
58
|
+
openSandboxRun,
|
|
59
|
+
type SandboxRun,
|
|
60
|
+
} from '@tangle-network/agent-runtime/loops'
|
|
61
|
+
import { Sandbox } from '@tangle-network/sandbox'
|
|
62
|
+
import { createCommit0Adapter } from './benchmarks/commit0'
|
|
63
|
+
import type { BenchTask } from './benchmarks/types'
|
|
64
|
+
import { type AttemptRecord, appendRunRecord, buildRunRecordFromAttempts } from './corpus'
|
|
65
|
+
import { type AnalystFn, llmAnalyst } from './sandbox-run'
|
|
66
|
+
import {
|
|
67
|
+
type BenchRuntimeDecisionPoint,
|
|
68
|
+
type BenchRuntimeHookEvent,
|
|
69
|
+
createRuntimeHookRecorder,
|
|
70
|
+
} from './runtime-hook-recorder'
|
|
71
|
+
import { pool } from './stats.mts'
|
|
72
|
+
|
|
73
|
+
function must(name: string): string {
|
|
74
|
+
const v = process.env[name]
|
|
75
|
+
if (!v) throw new Error(`env ${name} is required`)
|
|
76
|
+
return v
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const PATCH_PATH = '/tmp/solution.patch'
|
|
80
|
+
const randomSuffix = () => Math.random().toString(36).slice(2, 10)
|
|
81
|
+
|
|
82
|
+
interface Commit0Meta {
|
|
83
|
+
repo: string
|
|
84
|
+
baseCommit: string
|
|
85
|
+
srcDir: string
|
|
86
|
+
testDir: string
|
|
87
|
+
specification: string
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface Shot {
|
|
91
|
+
task: BenchTask
|
|
92
|
+
attempt: number
|
|
93
|
+
diff: string
|
|
94
|
+
ok: boolean
|
|
95
|
+
detail?: string
|
|
96
|
+
wallMs: number
|
|
97
|
+
/** measured count of stream events from the rollout (0 if it errored before streaming) */
|
|
98
|
+
events: number
|
|
99
|
+
/** bounded tail of the raw stream events — the trace the analyst reads (trace-only). */
|
|
100
|
+
traceEvents?: unknown[]
|
|
101
|
+
/** the analyst findings appended to this shot's prompt (steered arm, round ≥ 1). */
|
|
102
|
+
steer?: string
|
|
103
|
+
runtimeEvents?: BenchRuntimeHookEvent[]
|
|
104
|
+
runtimeDecisionPoints?: BenchRuntimeDecisionPoint[]
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Last events of a rollout stream, kept for the trace-only analyst. */
|
|
108
|
+
const TRACE_EVENTS_TAIL = 12
|
|
109
|
+
/** Diff prefix shown to the analyst (it names files + hunks; the full diff can be 100KB+). */
|
|
110
|
+
const ANALYST_DIFF_MAX = 6_000
|
|
111
|
+
/** Findings ceiling appended to a steered prompt (the analyst is told 1-3 sentences). */
|
|
112
|
+
const STEER_MAX = 1_500
|
|
113
|
+
|
|
114
|
+
/** Append the analyst's findings to the base rollout prompt (fresh box — the
|
|
115
|
+
* agent has no memory of the prior attempt, so the framing names it). */
|
|
116
|
+
function steeredPrompt(base: string, steer: string): string {
|
|
117
|
+
return `${base}\n\n--- Analysis of a previous attempt at this task ---\n${steer}\n\nApply this correction while you implement.`
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Build the rollout prompt: clone the stub, implement the source, write the diff to
|
|
121
|
+
* a FILE (the robust deliverable). Mirrors solveShot's file-read contract. */
|
|
122
|
+
function rolloutPrompt(meta: Commit0Meta): string {
|
|
123
|
+
return [
|
|
124
|
+
`Clone https://github.com/${meta.repo} into /work, then \`cd /work && git checkout ${meta.baseCommit}\`.`,
|
|
125
|
+
`The public functions/classes under \`${meta.srcDir}\` are stubbed (empty \`pass\`/\`...\` bodies). Your job is to`,
|
|
126
|
+
`implement COMPLETE, CORRECT bodies under \`${meta.srcDir}\` so the existing test suite under \`${meta.testDir}\` passes.`,
|
|
127
|
+
'',
|
|
128
|
+
'Work iteratively — do NOT stop at a first draft:',
|
|
129
|
+
`1. Read the spec (${meta.specification}) and the tests under \`${meta.testDir}\` to learn the exact required behavior.`,
|
|
130
|
+
`2. Install the package editable so imports resolve: \`pip install -e .\` (use the repo's setup if it differs).`,
|
|
131
|
+
`3. Implement ALL stubbed bodies under \`${meta.srcDir}\` — every function/class, not just the easy ones.`,
|
|
132
|
+
`4. RUN the suite: \`python -m pytest ${meta.testDir} -q\`. Read failures and FIX them. Repeat until as many tests`,
|
|
133
|
+
` pass as you can get — keep iterating; a partial implementation that fails most tests is not done.`,
|
|
134
|
+
'5. Do NOT edit the tests — the evaluation re-runs them on a fresh clone.',
|
|
135
|
+
'',
|
|
136
|
+
`When the suite is green (or you have maximized passing tests), from /work run EXACTLY:`,
|
|
137
|
+
` git add -A && git diff --cached -- ${meta.srcDir} > ${PATCH_PATH}`,
|
|
138
|
+
`Then stop. The patch file is the only deliverable — do NOT paste the diff in your reply.`,
|
|
139
|
+
].join('\n')
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
interface ShotCfg {
|
|
143
|
+
sandboxBaseUrl: string
|
|
144
|
+
sandboxKey: string
|
|
145
|
+
routerBaseUrl: string
|
|
146
|
+
/** Host-side opencode (`COMMIT0_BACKEND=local`) only — routes `openai/*` models
|
|
147
|
+
* through the router from THIS machine. The sandbox path never sends it into
|
|
148
|
+
* the box: in-box model auth is the box-provisioned `OPENCODE_MODEL_API_KEY`. */
|
|
149
|
+
routerKey: string
|
|
150
|
+
model: string
|
|
151
|
+
/** in-box opencode provider. `openai-compat` (default) is the generic passthrough,
|
|
152
|
+
* so router-served cheap models resolve in-box; `openai` only accepts its
|
|
153
|
+
* registered model names (e.g. gpt-4.1). Override via WORKER_PROVIDER. */
|
|
154
|
+
provider: string
|
|
155
|
+
timeoutMs: number
|
|
156
|
+
/** local-backend: the opencode CLI binary (cli-bridge fallback when the sandbox is down). */
|
|
157
|
+
opencodeBin: string
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** The diff the in-box agent produces, read back off the box FS (+ any stream error). */
|
|
161
|
+
interface RolloutDeliverable {
|
|
162
|
+
diff: string
|
|
163
|
+
lastErr?: string
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Reads the patch FILE the agent wrote (the robust deliverable — a large diff
|
|
167
|
+
* truncates in the chat stream → `git apply` "corrupt patch"), folding any in-box
|
|
168
|
+
* error event into `lastErr` so a failed rollout still surfaces on an empty patch. */
|
|
169
|
+
const commit0Deliverable: Deliverable<RolloutDeliverable> = {
|
|
170
|
+
kind: 'artifact',
|
|
171
|
+
path: PATCH_PATH,
|
|
172
|
+
fromArtifact: (raw, events) => {
|
|
173
|
+
let lastErr: string | undefined
|
|
174
|
+
for (const ev of events) {
|
|
175
|
+
if ((ev as { type?: string }).type === 'error') lastErr = JSON.stringify((ev as { data?: unknown }).data).slice(0, 300)
|
|
176
|
+
}
|
|
177
|
+
return { diff: raw, ...(lastErr ? { lastErr } : {}) }
|
|
178
|
+
},
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function runShot(task: BenchTask, attempt: number, cfg: ShotCfg, steer?: string): Promise<Shot> {
|
|
182
|
+
const meta = task.metadata as unknown as Commit0Meta
|
|
183
|
+
const startedAt = Date.now()
|
|
184
|
+
const client = new Sandbox({ baseUrl: cfg.sandboxBaseUrl, apiKey: cfg.sandboxKey })
|
|
185
|
+
// A stream/transport ceiling for the flaky sandbox path (0 ⇒ untimed); the run
|
|
186
|
+
// tears its own box down in `close()`. The whole rollout is fault-isolated: ANY
|
|
187
|
+
// error (502 / stream drop / provision fail / abort) becomes a recorded NO-DIFF
|
|
188
|
+
// attempt — it MUST NOT throw, or one flaky box aborts the pool and loses every
|
|
189
|
+
// other rollout (the powered-run crash).
|
|
190
|
+
const controller = new AbortController()
|
|
191
|
+
const timer = cfg.timeoutMs > 0 ? setTimeout(() => controller.abort(), cfg.timeoutMs) : undefined
|
|
192
|
+
// backend.model pins provider/model/baseUrl only; the platform writes the in-box
|
|
193
|
+
// provider config keyed to the box's own OPENCODE_MODEL_API_KEY. The inline
|
|
194
|
+
// profile + backend override is the same generic AgentRunSpec the runLoop kernel
|
|
195
|
+
// boots. Never inject an external key — the egress proxy 403s foreign credentials.
|
|
196
|
+
const agentRun: AgentRunSpec<string> = {
|
|
197
|
+
profile: { name: 'commit0-worker', metadata: { backendType: 'opencode' } },
|
|
198
|
+
name: 'commit0-worker',
|
|
199
|
+
taskToPrompt: () => '', // unused — the prompt is streamed directly by openSandboxRun
|
|
200
|
+
sandboxOverrides: {
|
|
201
|
+
name: `commit0-${task.id}-${attempt}-${randomSuffix()}`.replace(/[^a-zA-Z0-9_.-]/g, '_').slice(0, 60),
|
|
202
|
+
environment: 'universal',
|
|
203
|
+
backend: {
|
|
204
|
+
type: 'opencode',
|
|
205
|
+
model: { provider: cfg.provider, model: cfg.model, baseUrl: cfg.routerBaseUrl },
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
}
|
|
209
|
+
let run: SandboxRun<RolloutDeliverable> | undefined
|
|
210
|
+
const runtime = createRuntimeHookRecorder()
|
|
211
|
+
try {
|
|
212
|
+
run = await openSandboxRun(
|
|
213
|
+
client,
|
|
214
|
+
{
|
|
215
|
+
agentRun,
|
|
216
|
+
signal: controller.signal,
|
|
217
|
+
hooks: runtime.hooks,
|
|
218
|
+
runId: `commit0:${task.id}:${attempt}`,
|
|
219
|
+
scenarioId: task.id,
|
|
220
|
+
},
|
|
221
|
+
commit0Deliverable,
|
|
222
|
+
)
|
|
223
|
+
const prompt = steer ? steeredPrompt(rolloutPrompt(meta), steer) : rolloutPrompt(meta)
|
|
224
|
+
const turn = await run.start(prompt)
|
|
225
|
+
const ok = turn.out.diff.trim().length > 0
|
|
226
|
+
return {
|
|
227
|
+
task,
|
|
228
|
+
attempt,
|
|
229
|
+
diff: turn.out.diff,
|
|
230
|
+
ok,
|
|
231
|
+
events: turn.events.length,
|
|
232
|
+
traceEvents: turn.events.slice(-TRACE_EVENTS_TAIL),
|
|
233
|
+
...(steer ? { steer } : {}),
|
|
234
|
+
runtimeEvents: runtime.events,
|
|
235
|
+
runtimeDecisionPoints: runtime.decisionPoints,
|
|
236
|
+
wallMs: Date.now() - startedAt,
|
|
237
|
+
...(ok ? {} : { detail: `empty patch${turn.readError ? ` (read failed: ${turn.readError.slice(0, 120)})` : ''}${turn.out.lastErr ? `; lastError=${turn.out.lastErr}` : ''}` }),
|
|
238
|
+
}
|
|
239
|
+
} catch (err) {
|
|
240
|
+
const msg = err instanceof Error ? err.message : String(err)
|
|
241
|
+
return {
|
|
242
|
+
task,
|
|
243
|
+
attempt,
|
|
244
|
+
diff: '',
|
|
245
|
+
ok: false,
|
|
246
|
+
events: 0,
|
|
247
|
+
...(steer ? { steer } : {}),
|
|
248
|
+
runtimeEvents: runtime.events,
|
|
249
|
+
runtimeDecisionPoints: runtime.decisionPoints,
|
|
250
|
+
wallMs: Date.now() - startedAt,
|
|
251
|
+
detail: `rollout error: ${msg.slice(0, 200)}`,
|
|
252
|
+
}
|
|
253
|
+
} finally {
|
|
254
|
+
if (timer) clearTimeout(timer)
|
|
255
|
+
if (run) await run.close()
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** Run a subprocess, capturing combined stdout+stderr; never throws (returns rc). */
|
|
260
|
+
function sh(cmd: string, args: string[], opts: { cwd?: string; timeoutMs?: number; env?: NodeJS.ProcessEnv } = {}): Promise<{ code: number; out: string }> {
|
|
261
|
+
return new Promise((resolve) => {
|
|
262
|
+
const child = spawn(cmd, args, {
|
|
263
|
+
...(opts.cwd ? { cwd: opts.cwd } : {}),
|
|
264
|
+
env: opts.env ?? process.env,
|
|
265
|
+
...(opts.timeoutMs ? { timeout: opts.timeoutMs } : {}),
|
|
266
|
+
})
|
|
267
|
+
let out = ''
|
|
268
|
+
child.stdout?.on('data', (c: Buffer) => { out += c.toString() })
|
|
269
|
+
child.stderr?.on('data', (c: Buffer) => { out += c.toString() })
|
|
270
|
+
child.on('error', (e) => resolve({ code: -1, out: `${out}\n${e}` }))
|
|
271
|
+
child.on('close', (code) => resolve({ code: code ?? -1, out }))
|
|
272
|
+
})
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/** Local-rollout prompt: the repo is ALREADY cloned + checked out into the cwd, so
|
|
276
|
+
* (unlike the sandbox prompt) the agent implements + test-iterates in place; the diff
|
|
277
|
+
* is read from git afterward (no chat-message truncation). */
|
|
278
|
+
function localRolloutPrompt(meta: Commit0Meta): string {
|
|
279
|
+
return [
|
|
280
|
+
`The current directory is the stubbed Python library \`${meta.repo}\`, checked out at its base commit.`,
|
|
281
|
+
`The public functions/classes under \`${meta.srcDir}\` are stubbed (empty \`pass\`/\`...\`). Implement COMPLETE, CORRECT bodies so the tests under \`${meta.testDir}\` pass.`,
|
|
282
|
+
'Work iteratively, do NOT stop at a first draft:',
|
|
283
|
+
`1. Read the spec (${meta.specification}) and the tests under \`${meta.testDir}\`.`,
|
|
284
|
+
'2. Set up an ISOLATED venv so imports + pytest resolve: `python3 -m venv .venv && .venv/bin/pip install -e .` (use the repo setup if it differs).',
|
|
285
|
+
`3. Implement ALL stubbed bodies under \`${meta.srcDir}\`.`,
|
|
286
|
+
`4. Run \`.venv/bin/python -m pytest ${meta.testDir} -q\`, read failures, FIX them, and repeat until as many tests pass as you can.`,
|
|
287
|
+
'5. Do NOT edit the test files.',
|
|
288
|
+
'When done, just stop — do NOT print the diff; it is collected from git.',
|
|
289
|
+
].join('\n')
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* LOCAL rollout backend (cli-bridge fallback for when the sandbox gateway is down):
|
|
294
|
+
* clone + checkout the stub into a tmpdir, run local opencode (its own kimi/zai
|
|
295
|
+
* coding-plan auth, or the router when model is `openai/*`) to implement + test-iterate
|
|
296
|
+
* in place, then read the diff straight from git (complete — no message truncation).
|
|
297
|
+
* Fault-isolated like runShot: any failure → a recorded NO-DIFF attempt, never a throw.
|
|
298
|
+
*/
|
|
299
|
+
async function runShotLocal(task: BenchTask, attempt: number, cfg: ShotCfg, steer?: string): Promise<Shot> {
|
|
300
|
+
const meta = task.metadata as unknown as Commit0Meta
|
|
301
|
+
const startedAt = Date.now()
|
|
302
|
+
let dir: string | undefined
|
|
303
|
+
try {
|
|
304
|
+
dir = await mkdtemp(join(tmpdir(), 'commit0-local-'))
|
|
305
|
+
const clone = await sh('git', ['clone', '--quiet', `https://github.com/${meta.repo}`, dir], { timeoutMs: 180_000 })
|
|
306
|
+
if (clone.code !== 0) {
|
|
307
|
+
return { task, attempt, diff: '', ok: false, events: 0, wallMs: Date.now() - startedAt, detail: `git clone failed: ${clone.out.trim().slice(-180)}` }
|
|
308
|
+
}
|
|
309
|
+
const co = await sh('git', ['-C', dir, 'checkout', '--quiet', meta.baseCommit], { timeoutMs: 60_000 })
|
|
310
|
+
if (co.code !== 0) {
|
|
311
|
+
return { task, attempt, diff: '', ok: false, events: 0, wallMs: Date.now() - startedAt, detail: `git checkout ${meta.baseCommit} failed: ${co.out.trim().slice(-180)}` }
|
|
312
|
+
}
|
|
313
|
+
// openai/* → route through the router (OPENAI_* env); anything else → opencode's
|
|
314
|
+
// OWN configured auth (kimi-for-coding / zai coding-plan subscriptions).
|
|
315
|
+
const env = cfg.model.startsWith('openai/')
|
|
316
|
+
? { ...process.env, OPENAI_API_KEY: cfg.routerKey, OPENAI_BASE_URL: cfg.routerBaseUrl }
|
|
317
|
+
: process.env
|
|
318
|
+
const prompt = steer ? steeredPrompt(localRolloutPrompt(meta), steer) : localRolloutPrompt(meta)
|
|
319
|
+
const oc = await sh(cfg.opencodeBin, ['run', prompt, '-m', cfg.model, '--dir', dir], { timeoutMs: cfg.timeoutMs, env })
|
|
320
|
+
const lines = oc.out.split('\n')
|
|
321
|
+
const events = lines.length
|
|
322
|
+
// Read the diff straight from git, scoped to src_dir (excludes the .venv the agent made).
|
|
323
|
+
const diffRes = await sh('bash', ['-c', `cd ${JSON.stringify(dir)} && git add -- ${JSON.stringify(meta.srcDir)} && git diff --cached -- ${JSON.stringify(meta.srcDir)}`], { timeoutMs: 60_000 })
|
|
324
|
+
const diff = diffRes.out
|
|
325
|
+
const ok = diff.trim().length > 0
|
|
326
|
+
return {
|
|
327
|
+
task,
|
|
328
|
+
attempt,
|
|
329
|
+
diff,
|
|
330
|
+
ok,
|
|
331
|
+
events,
|
|
332
|
+
traceEvents: lines.slice(-TRACE_EVENTS_TAIL),
|
|
333
|
+
...(steer ? { steer } : {}),
|
|
334
|
+
wallMs: Date.now() - startedAt,
|
|
335
|
+
...(ok ? {} : { detail: `no diff (opencode rc=${oc.code}): ${oc.out.trim().slice(-160)}` }),
|
|
336
|
+
}
|
|
337
|
+
} catch (err) {
|
|
338
|
+
return { task, attempt, diff: '', ok: false, events: 0, ...(steer ? { steer } : {}), wallMs: Date.now() - startedAt, detail: `local rollout error: ${(err instanceof Error ? err.message : String(err)).slice(0, 180)}` }
|
|
339
|
+
} finally {
|
|
340
|
+
if (dir) await rm(dir, { recursive: true, force: true }).catch(() => {})
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
async function main(): Promise<void> {
|
|
345
|
+
// BACKEND=local → cli-bridge fallback (local opencode, no remote sandbox); needs a
|
|
346
|
+
// sandbox-down workaround. Default 'sandbox' (the remote gateway). Local uses opencode's
|
|
347
|
+
// OWN auth (kimi-for-coding / zai coding-plan), so TANGLE_API_KEY is only required for
|
|
348
|
+
// the sandbox backend or an `openai/*` local model (router).
|
|
349
|
+
const backend = process.env.COMMIT0_BACKEND === 'local' ? 'local' : 'sandbox'
|
|
350
|
+
const n = Number(process.env.N ?? 8)
|
|
351
|
+
const k = Number(process.env.K ?? 4)
|
|
352
|
+
const model = process.env.WORKER_MODEL ?? (backend === 'local' ? 'kimi-for-coding/kimi-k2-thinking' : 'gpt-4.1')
|
|
353
|
+
const routerBaseUrl = process.env.ROUTER_BASE ?? 'https://router.tangle.tools/v1'
|
|
354
|
+
// The arms under test. `random` = K independent blind shots (the equal-compute
|
|
355
|
+
// control); `refineAudit` = blind shot 0, then trace-only-analyst-steered shots.
|
|
356
|
+
const armNames = (process.env.ARMS ?? 'random').split(',').map((s) => s.trim()).filter(Boolean)
|
|
357
|
+
for (const a of armNames) {
|
|
358
|
+
if (a !== 'random' && a !== 'refineAudit') throw new Error(`unknown arm ${a} (have: random, refineAudit)`)
|
|
359
|
+
}
|
|
360
|
+
// The analyst is an OFF-BOX router call (host-side), so it needs the router key
|
|
361
|
+
// even when the worker runs on its own auth.
|
|
362
|
+
const analystModel = process.env.ANALYST_MODEL ?? 'deepseek-v4-pro'
|
|
363
|
+
const needsRouterKey = backend === 'sandbox' || model.startsWith('openai/') || armNames.includes('refineAudit')
|
|
364
|
+
const routerKey = needsRouterKey ? must('TANGLE_API_KEY') : (process.env.TANGLE_API_KEY ?? '')
|
|
365
|
+
const sandboxBaseUrl = process.env.SANDBOX_BASE_URL ?? 'https://sandbox.tangle.tools'
|
|
366
|
+
const opencodeBin = process.env.OPENCODE_BIN ?? join(process.env.HOME ?? '', '.local/bin/opencode')
|
|
367
|
+
// openai-compat = generic passthrough so cheap router models resolve in-box;
|
|
368
|
+
// `openai` rejects non-registered model names. Override via WORKER_PROVIDER.
|
|
369
|
+
const provider = process.env.WORKER_PROVIDER ?? 'openai-compat'
|
|
370
|
+
const concurrency = Number(process.env.CONCURRENCY ?? 3)
|
|
371
|
+
// No tight cap on the agentic rollout — it runs until the agent finishes (the clone→
|
|
372
|
+
// implement→pytest-iterate loop genuinely takes a while). 0 = untimed. Only set
|
|
373
|
+
// SHOT_TIMEOUT_MS to impose a deliberate ceiling. Sandbox keeps a stream cap (flaky transport).
|
|
374
|
+
const timeoutMs = process.env.SHOT_TIMEOUT_MS ? Number(process.env.SHOT_TIMEOUT_MS) : backend === 'local' ? 0 : 900_000
|
|
375
|
+
const corpusPath = process.env.CORPUS ?? '/tmp/commit0.jsonl'
|
|
376
|
+
if (!Number.isInteger(n) || n < 1) throw new Error(`N must be a positive integer, got ${process.env.N}`)
|
|
377
|
+
if (!Number.isInteger(k) || k < 1) throw new Error(`K must be a positive integer, got ${process.env.K}`)
|
|
378
|
+
|
|
379
|
+
const adapter = createCommit0Adapter()
|
|
380
|
+
console.log(`=== commit0 Layer-1 gate · backend=${backend} · N=${n} K=${k} arms=${armNames.join(',')} model=${model} analyst=${analystModel} rolloutConc=${concurrency} ===`)
|
|
381
|
+
await adapter.preflight()
|
|
382
|
+
const tasks = await adapter.loadTasks({ limit: n })
|
|
383
|
+
console.log(`loaded ${tasks.length} task(s): ${tasks.map((t) => t.id).join(', ')}`)
|
|
384
|
+
|
|
385
|
+
// Phase 1 — rollouts, concurrent. sandbox = remote box; local = cli-bridge (opencode
|
|
386
|
+
// in a tmpdir, diff read from git). Both fault-isolated → a failure is a NO-DIFF, never a throw.
|
|
387
|
+
const cfg: ShotCfg = { sandboxBaseUrl, sandboxKey: routerKey, routerBaseUrl, routerKey, model, provider, timeoutMs, opencodeBin }
|
|
388
|
+
const runRollout = backend === 'local' ? runShotLocal : runShot
|
|
389
|
+
const analyze: AnalystFn = llmAnalyst({ routerBaseUrl, routerKey, model: analystModel })
|
|
390
|
+
const logShot = (armName: string, s: Shot) =>
|
|
391
|
+
console.log(` rollout ${s.task.id}[${armName}]#${s.attempt}: ${s.ok ? `diff ${s.diff.length}B` : `NO DIFF (${s.detail})`}${s.steer ? ' [steered]' : ''} (${(s.wallMs / 1000) | 0}s)`)
|
|
392
|
+
|
|
393
|
+
interface TaggedShot {
|
|
394
|
+
arm: string
|
|
395
|
+
shot: Shot
|
|
396
|
+
}
|
|
397
|
+
// A unit is the pool's schedulable atom: one blind shot for the control arm
|
|
398
|
+
// (max packing), the WHOLE blind→analyst→steered chain for the steered arm
|
|
399
|
+
// (shot i+1 depends on shot i's trace). Units never throw — every failure is a
|
|
400
|
+
// recorded NO-DIFF/INFRA shot, so one flaky box cannot abort the pool.
|
|
401
|
+
const units: Array<() => Promise<TaggedShot[]>> = []
|
|
402
|
+
for (const task of tasks) {
|
|
403
|
+
for (const armName of armNames) {
|
|
404
|
+
if (armName === 'random') {
|
|
405
|
+
for (let attempt = 0; attempt < k; attempt += 1) {
|
|
406
|
+
units.push(async () => {
|
|
407
|
+
const s = await runRollout(task, attempt, cfg)
|
|
408
|
+
logShot(armName, s)
|
|
409
|
+
return [{ arm: armName, shot: s }]
|
|
410
|
+
})
|
|
411
|
+
}
|
|
412
|
+
continue
|
|
413
|
+
}
|
|
414
|
+
units.push(async () => {
|
|
415
|
+
const out: TaggedShot[] = []
|
|
416
|
+
let prev: Shot | undefined
|
|
417
|
+
for (let attempt = 0; attempt < k; attempt += 1) {
|
|
418
|
+
let steer: string | undefined
|
|
419
|
+
if (prev) {
|
|
420
|
+
// Trace-only: the analyst sees the prior shot's diff + stream tail,
|
|
421
|
+
// never a judge score (judging is phase 2 — selector≠judge by
|
|
422
|
+
// construction). "no change needed" is the policy's informed no-op.
|
|
423
|
+
try {
|
|
424
|
+
const events = prev.traceEvents?.length ? prev.traceEvents : prev.detail ? [prev.detail] : []
|
|
425
|
+
const feedback = (await analyze([{ output: prev.diff.slice(0, ANALYST_DIFF_MAX), events }])).trim()
|
|
426
|
+
if (feedback && !/^no change needed/i.test(feedback)) steer = feedback.slice(0, STEER_MAX)
|
|
427
|
+
} catch (err) {
|
|
428
|
+
// A steered arm whose analyst died is no longer a steered arm —
|
|
429
|
+
// record the attempt as INFRA rather than degrading to blind.
|
|
430
|
+
const msg = (err instanceof Error ? err.message : String(err)).slice(0, 200)
|
|
431
|
+
const s: Shot = { task, attempt, diff: '', ok: false, events: 0, wallMs: 0, detail: `analyst error: ${msg}` }
|
|
432
|
+
logShot(armName, s)
|
|
433
|
+
out.push({ arm: armName, shot: s })
|
|
434
|
+
break
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
const s = await runRollout(task, attempt, cfg, steer)
|
|
438
|
+
logShot(armName, s)
|
|
439
|
+
out.push({ arm: armName, shot: s })
|
|
440
|
+
prev = s
|
|
441
|
+
}
|
|
442
|
+
return out
|
|
443
|
+
})
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
const where = backend === 'local' ? 'local opencode (cli-bridge)' : `in-box (${PATCH_PATH})`
|
|
447
|
+
console.log(`\n▶ phase 1: ${tasks.length * armNames.length * k} rollouts in ${units.length} units (conc=${concurrency}) via ${where}`)
|
|
448
|
+
const tagged = (await pool(units, concurrency, (u) => u())).flat()
|
|
449
|
+
|
|
450
|
+
// Phase 2 — judging, SEQUENTIAL (Docker-bound; commit0 keys its report dir on
|
|
451
|
+
// hash(test_ids), shared across a repo's attempts → concurrent judging of one repo
|
|
452
|
+
// races/overwrites report.json). Judged PER (TASK, ARM), writing each RunRecord
|
|
453
|
+
// immediately so a mid-run crash keeps completed records. Fail loud: an attempt
|
|
454
|
+
// with no diff or a failed judge becomes an INFRA attempt (error recorded, no
|
|
455
|
+
// score) and the whole record is infra-excluded — never a silent 0.
|
|
456
|
+
console.log(`\n▶ phase 2: judging sequentially per task (official commit0 pytest harness) → ${corpusPath}`)
|
|
457
|
+
let scoredRecords = 0
|
|
458
|
+
let infraRecords = 0
|
|
459
|
+
let infraAttempts = 0
|
|
460
|
+
for (const task of tasks) {
|
|
461
|
+
let imageTouched = false
|
|
462
|
+
for (const armName of armNames) {
|
|
463
|
+
const armShots = tagged.filter((t) => t.arm === armName && t.shot.task.id === task.id).map((t) => t.shot)
|
|
464
|
+
const attempts: AttemptRecord[] = []
|
|
465
|
+
let recordInfra = false
|
|
466
|
+
for (let i = 0; i < k; i += 1) {
|
|
467
|
+
const s = armShots.find((x) => x.attempt === i)
|
|
468
|
+
let sc: { score: number; resolved: boolean } | undefined
|
|
469
|
+
let attemptError: string | undefined
|
|
470
|
+
if (s?.ok) {
|
|
471
|
+
// Local Docker backend: images must pre-exist (src/commit0-prereqs.sh);
|
|
472
|
+
// rebuild_image is honored by the Modal backend only, where the first
|
|
473
|
+
// judged attempt of a repo force-builds and the rest reuse.
|
|
474
|
+
process.env.COMMIT0_REBUILD_IMAGE = imageTouched ? '0' : '1'
|
|
475
|
+
imageTouched = true
|
|
476
|
+
try {
|
|
477
|
+
const v = await adapter.judge(s.task, s.diff)
|
|
478
|
+
sc = { score: v.score, resolved: v.resolved }
|
|
479
|
+
console.log(` judge ${task.id}[${armName}]#${i}: score=${(v.score * 100).toFixed(1)}% resolved=${v.resolved}`)
|
|
480
|
+
} catch (err) {
|
|
481
|
+
attemptError = `judge harness failed: ${(err instanceof Error ? err.message : String(err)).slice(0, 300)}`
|
|
482
|
+
console.log(` judge ${task.id}[${armName}]#${i}: INFRA ${attemptError.slice(0, 200)}`)
|
|
483
|
+
}
|
|
484
|
+
} else {
|
|
485
|
+
attemptError = s ? `no diff: ${s.detail ?? 'unknown'}` : 'missing shot'
|
|
486
|
+
console.log(` judge ${task.id}[${armName}]#${i}: INFRA (${attemptError.slice(0, 160)})`)
|
|
487
|
+
}
|
|
488
|
+
if (attemptError) {
|
|
489
|
+
recordInfra = true
|
|
490
|
+
infraAttempts += 1
|
|
491
|
+
}
|
|
492
|
+
attempts.push({
|
|
493
|
+
round: i,
|
|
494
|
+
prompt: s?.steer ? `commit0-rollout + steer:\n${s.steer}` : 'commit0-rollout',
|
|
495
|
+
output: s?.diff ?? '',
|
|
496
|
+
...(sc ? { valid: sc.resolved, score: sc.score } : {}),
|
|
497
|
+
...(attemptError ? { error: attemptError } : {}),
|
|
498
|
+
wallMs: s?.wallMs ?? 0,
|
|
499
|
+
eventCount: s?.events ?? 0,
|
|
500
|
+
eventTypes: { 'sandbox.stream': s?.events ?? 0 },
|
|
501
|
+
traceTail: (s?.diff ?? '').slice(-600),
|
|
502
|
+
})
|
|
503
|
+
}
|
|
504
|
+
if (recordInfra) infraRecords += 1
|
|
505
|
+
else if (attempts.some((a) => a.score !== undefined)) scoredRecords += 1
|
|
506
|
+
const record = buildRunRecordFromAttempts(attempts, {
|
|
507
|
+
benchmark: adapter.name,
|
|
508
|
+
instanceId: task.id,
|
|
509
|
+
condition: `${armName}@${k}`,
|
|
510
|
+
model,
|
|
511
|
+
infraError: recordInfra,
|
|
512
|
+
runtimeEvents: armShots.flatMap((x) => x.runtimeEvents ?? []),
|
|
513
|
+
runtimeDecisionPoints: armShots.flatMap((x) => x.runtimeDecisionPoints ?? []),
|
|
514
|
+
})
|
|
515
|
+
await appendRunRecord(corpusPath, record) // incremental: partial progress survives a crash
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
console.log(
|
|
520
|
+
`\n=== wrote ${tasks.length * armNames.length} record(s) (${scoredRecords} fully scored, ${infraRecords} infra-excluded; ${infraAttempts} infra attempts) → ${corpusPath} ===\n` +
|
|
521
|
+
` STEERING VERDICT: tsx src/corpus-report.mts ${corpusPath}\n` +
|
|
522
|
+
` SELECTOR GATE: tsx src/corpus-replay.mts ${corpusPath} --selector=verifier`,
|
|
523
|
+
)
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
main().catch((err) => {
|
|
527
|
+
console.error(`commit0-gate: ${err instanceof Error ? err.message : String(err)}`)
|
|
528
|
+
process.exit(1)
|
|
529
|
+
})
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# commit0 judge prerequisites: ensure the per-repo Docker image exists for each
|
|
3
|
+
# argument — a repo short name (`wcwidth`, `tinydb`, …) or a split (`lite`, `all`).
|
|
4
|
+
#
|
|
5
|
+
# The judge (scripts/commit0_judge.py) grades on commit0's LOCAL Docker backend,
|
|
6
|
+
# whose execution context only CREATES containers from an existing image —
|
|
7
|
+
# `rebuild_image` is honored by the Modal backend only. Without the image every
|
|
8
|
+
# judge call fails with ImageNotFound ("commit0 harness failed"), so images must
|
|
9
|
+
# exist BEFORE a gate run.
|
|
10
|
+
#
|
|
11
|
+
# Fast path: pull the official prebuilt image (docker.io/wentingzhao/<repo>:v0 —
|
|
12
|
+
# the exact tag commit0's spec.repo_image_tag resolves). Fallback: build locally
|
|
13
|
+
# via commit0.harness.build (minutes + multi-GB per repo; skips existing images).
|
|
14
|
+
#
|
|
15
|
+
# ./src/commit0-prereqs.sh wcwidth tinydb # individual repos
|
|
16
|
+
# ./src/commit0-prereqs.sh lite # a whole split
|
|
17
|
+
# COMMIT0_VENV=.venv-commit0 ./src/commit0-prereqs.sh wcwidth
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
cd "$(dirname "$0")/.." # bench/
|
|
20
|
+
|
|
21
|
+
venv="${COMMIT0_VENV:-.venv-commit0}"
|
|
22
|
+
dataset="${COMMIT0_DATASET:-wentingzhao/commit0_combined}"
|
|
23
|
+
split="${COMMIT0_SPLIT:-test}"
|
|
24
|
+
|
|
25
|
+
[ $# -ge 1 ] || { echo "usage: $0 <repo-or-split> [more…]" >&2; exit 2; }
|
|
26
|
+
[ -x "$venv/bin/python" ] || { echo "missing $venv/bin/python — create it per benchmarks/commit0.ts preflight (pip install commit0 datasets)" >&2; exit 2; }
|
|
27
|
+
docker info >/dev/null 2>&1 || { echo "Docker daemon unavailable — commit0 judges on --backend local" >&2; exit 2; }
|
|
28
|
+
|
|
29
|
+
for target in "$@"; do
|
|
30
|
+
image="wentingzhao/$(printf '%s' "$target" | tr '[:upper:]' '[:lower:]'):v0"
|
|
31
|
+
if docker image inspect "$image" >/dev/null 2>&1; then
|
|
32
|
+
echo "ok: $image already present"
|
|
33
|
+
continue
|
|
34
|
+
fi
|
|
35
|
+
if docker pull "$image" >/dev/null 2>&1; then
|
|
36
|
+
echo "ok: pulled $image"
|
|
37
|
+
continue
|
|
38
|
+
fi
|
|
39
|
+
# No hub image (or the target is a split name): build through the harness,
|
|
40
|
+
# which skips repos whose image already exists.
|
|
41
|
+
echo "building $target via commit0.harness.build (this takes minutes per repo)…"
|
|
42
|
+
"$venv/bin/python" -c '
|
|
43
|
+
import sys
|
|
44
|
+
from commit0.harness.build import main
|
|
45
|
+
main(sys.argv[1], sys.argv[2], sys.argv[3], 1, 1)
|
|
46
|
+
' "$dataset" "$split" "$target"
|
|
47
|
+
done
|
|
48
|
+
echo "prereqs done."
|