@tangle-network/agent-bench 0.7.1 → 0.8.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/CHANGELOG.md +8 -0
- package/HARNESS.md +1 -1
- package/dist/adapters.js +2 -2
- package/dist/benchmarks/appworld.d.ts +61 -2
- package/dist/benchmarks/appworld.js +111 -40
- package/dist/benchmarks/appworld.js.map +1 -1
- package/dist/benchmarks/cadbench.js +1 -1
- package/dist/benchmarks/cadgenbench.js +1 -1
- package/dist/benchmarks/finresearchbench.js +16 -22
- package/dist/benchmarks/finresearchbench.js.map +1 -1
- package/dist/benchmarks/finsearchcomp.js +16 -22
- package/dist/benchmarks/finsearchcomp.js.map +1 -1
- package/dist/benchmarks/frames.js +18 -20
- package/dist/benchmarks/frames.js.map +1 -1
- package/dist/benchmarks/simpleqa.js +15 -19
- package/dist/benchmarks/simpleqa.js.map +1 -1
- package/dist/benchmarks/trata-hedge.js +20 -23
- package/dist/benchmarks/trata-hedge.js.map +1 -1
- package/dist/{cadbench-BrpwOU6A.js → cadbench-BLSyxR1N.js} +21 -20
- package/dist/cadbench-BLSyxR1N.js.map +1 -0
- package/dist/{cadgenbench-DF7hYHdl.js → cadgenbench-x2OFkf8y.js} +2 -2
- package/dist/cadgenbench-x2OFkf8y.js.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +10 -9
- package/dist/index.js.map +1 -1
- package/dist/router-turn-C2wMiDoo.js +31 -0
- package/dist/router-turn-C2wMiDoo.js.map +1 -0
- package/package.json +7 -7
- package/scripts/appworld_driver.py +1 -170
- package/scripts/run-package-tests.mjs +56 -36
- package/scripts/run-package-tests.test.mjs +33 -0
- package/scripts/trata-hedge/README.md +3 -3
- package/scripts/trata-hedge/run.sh +6 -2
- package/src/aec-gate.mts +30 -9
- package/src/agent-graphs-gen2.mts +523 -0
- package/src/agent-graphs-gen3.mts +660 -0
- package/src/agent-graphs-improve/offline-seams.mts +128 -0
- package/src/agent-graphs-improve.mts +747 -0
- package/src/atom-humaneval.mts +76 -55
- package/src/atom-mcp-e2e.mts +27 -13
- package/src/benchmarks/appworld.test.mts +119 -1
- package/src/benchmarks/appworld.ts +156 -33
- package/src/benchmarks/cadbench.ts +21 -8
- package/src/benchmarks/finresearchbench.ts +20 -16
- package/src/benchmarks/finsearchcomp.ts +20 -20
- package/src/benchmarks/frames.ts +19 -18
- package/src/benchmarks/simpleqa.ts +19 -17
- package/src/benchmarks/trata-hedge.ts +26 -18
- package/src/browser/ui-reviewer.ts +1 -1
- package/src/clbench-context-gate.mts +45 -9
- package/src/cloud-loop.mts +24 -6
- package/src/commit0-env-run.mts +6 -3
- package/src/commit0-env.ts +2 -3
- package/src/commit0-gate.mts +53 -24
- package/src/corpus.ts +3 -3
- package/src/david-attribution.mts +28 -9
- package/src/david-goliath.mts +31 -12
- package/src/egress-probe.mts +3 -3
- package/src/examples/lean-proof-gate.mts +10 -3
- package/src/examples/math-demo.mts +10 -3
- package/src/examples/strategy-demo.mts +10 -4
- package/src/fleet.mts +30 -8
- package/src/gate-cli.mts +9 -4
- package/src/gate.test.mts +7 -2
- package/src/gate.ts +23 -75
- package/src/generate-eval/certify.ts +13 -5
- package/src/hev-eval.mts +39 -10
- package/src/hev-improve.mts +28 -16
- package/src/hev-structural.mts +28 -20
- package/src/humaneval-gate.mts +24 -8
- package/src/humaneval-object-ablation.mts +52 -14
- package/src/humaneval-repair-gate.mts +53 -14
- package/src/mbpp-structural.mts +28 -20
- package/src/mcp-mount-probe.mts +23 -11
- package/src/official-optimizer-config.mts +61 -12
- package/src/official-optimizer-config.test.mts +72 -3
- package/src/quant-arena/profiles/quant-researcher.profile.json +6 -1
- package/src/quant-arena/quant-loop.mts +88 -61
- package/src/research-shot.ts +21 -11
- package/src/resolve-client.ts +6 -8
- package/src/rollout-ledger/backfill-swe-arena.test.mts +7 -2
- package/src/router-executor.ts +1 -1
- package/src/router-turn.ts +135 -0
- package/src/run-benchmarks.ts +7 -2
- package/src/sandbox-run.ts +23 -41
- package/src/search-bench/bridge.ts +66 -8
- package/src/search-bench/parametric-check.mts +19 -4
- package/src/search-bench/profiles.ts +24 -9
- package/src/search-bench/run.mts +3 -4
- package/src/smoke-structural-rollout.mts +21 -5
- package/src/supervisor-arena.mts +28 -20
- package/src/swe-arena/arms.ts +73 -15
- package/src/swe-arena/capacity.ts +44 -41
- package/src/swe-arena/diagnosis-ensemble.ts +51 -48
- package/src/swe-arena/execution.test.mts +12 -12
- package/src/swe-arena/gepa-seat.mts +12 -5
- package/src/swe-arena/gepa-seat.test.mts +45 -33
- package/src/swe-arena/outer-loop.mts +94 -70
- package/src/swe-arena/premeasured-from-cells.mts +16 -1
- package/src/swe-arena/premeasured-from-cells.test.mts +21 -1
- package/src/swe-arena/profiles/deepseek-author.profile.json +12 -0
- package/src/swe-arena/profiles/default-author.profile.json +9 -1
- package/src/swe-arena/proposer-fanout.mts +52 -99
- package/src/swe-arena/proposer-fanout.test.mts +92 -57
- package/src/swe-arena/proposer-provenance.mts +1 -1
- package/src/swe-code-improve.mts +30 -52
- package/src/swe-emit-patch.mts +26 -5
- package/src/swe-improve.mts +27 -8
- package/src/swe-jail.test.ts +128 -0
- package/src/swe-jail.ts +106 -22
- package/src/swe-local-proof.mts +27 -5
- package/src/swe-repro-calibrate.mts +5 -0
- package/src/swe-self-improve.mts +45 -10
- package/src/swe-stream.mts +68 -6
- package/src/swe-structural.mts +46 -7
- package/src/tb-container-executor.mts +38 -6
- package/src/tb-container-executor.test.mts +11 -3
- package/src/tb-supervisor-sidecar.mts +11 -27
- package/src/terminal-compare.ts +38 -18
- package/src/trata-gate.mts +26 -26
- package/src/trata-gepa.mts +25 -16
- package/src/trata-hedge-solve.mts +80 -0
- package/src/worker-blender.ts +21 -11
- package/src/worker-browser.ts +18 -5
- package/src/worker-build123d.ts +17 -8
- package/src/worker-cad.ts +31 -12
- package/src/worker.ts +1 -1
- package/tb_agents/opencode_router_agent.py +84 -42
- package/dist/cadbench-BrpwOU6A.js.map +0 -1
- package/dist/cadgenbench-DF7hYHdl.js.map +0 -1
- package/scripts/trata-hedge/solve.py +0 -83
|
@@ -69,10 +69,10 @@ import {
|
|
|
69
69
|
improve,
|
|
70
70
|
rawTraceDistiller,
|
|
71
71
|
type CandidateGenerator,
|
|
72
|
+
type ImproveCodeRunOptions,
|
|
72
73
|
type Verifier,
|
|
73
74
|
} from '@tangle-network/agent-runtime'
|
|
74
|
-
import {
|
|
75
|
-
import { canonicalCandidateDigest } from '@tangle-network/agent-interface'
|
|
75
|
+
import { canonicalCandidateDigest, type AgentProfile } from '@tangle-network/agent-interface'
|
|
76
76
|
import {
|
|
77
77
|
makeProposalFinding,
|
|
78
78
|
type AnalystFinding,
|
|
@@ -89,7 +89,6 @@ import {
|
|
|
89
89
|
type PremeasuredOptimizationBaseline,
|
|
90
90
|
type Scenario,
|
|
91
91
|
} from '@tangle-network/agent-eval/campaign'
|
|
92
|
-
import type { CostLedgerHandle } from '@tangle-network/agent-eval'
|
|
93
92
|
import { runVenvPython } from '../benchmarks/_harness.ts'
|
|
94
93
|
import { createSweBenchAdapter } from '../benchmarks/swe-bench.ts'
|
|
95
94
|
import {
|
|
@@ -134,6 +133,7 @@ import {
|
|
|
134
133
|
fanOutLoopsGenerator,
|
|
135
134
|
materializeParetoParents,
|
|
136
135
|
proposerShotHooks,
|
|
136
|
+
resolveAuthorProfile,
|
|
137
137
|
type ParetoParentContext,
|
|
138
138
|
type ParetoParentSeed,
|
|
139
139
|
type PrefilterConfig,
|
|
@@ -646,7 +646,9 @@ export interface OuterLoopConfig {
|
|
|
646
646
|
* budget.maxImprovementShots; the LIB owns the dial (capabilities.mts
|
|
647
647
|
* fails loud on a substrate that would drop it). */
|
|
648
648
|
maxShots: number
|
|
649
|
-
proposerHarness: '
|
|
649
|
+
proposerHarness: 'pi'
|
|
650
|
+
/** Complete profile used by the single-author path and as the run's admitted author identity. */
|
|
651
|
+
proposerProfile: string
|
|
650
652
|
proposerTimeoutMs: number
|
|
651
653
|
/** GEN-3 proposer fan-out: N proposers author candidates CONCURRENTLY, each
|
|
652
654
|
* an AgentProfile-pinned harness invocation (see proposer-fanout.mts).
|
|
@@ -759,7 +761,8 @@ export function defaultRound4Config(
|
|
|
759
761
|
// bootstrap run writes it; the lib validates it on every consumption.
|
|
760
762
|
premeasuredBaselinePath: join(hh, 'r4', 'premeasured-baseline.json'),
|
|
761
763
|
maxShots: 3,
|
|
762
|
-
proposerHarness: '
|
|
764
|
+
proposerHarness: 'pi',
|
|
765
|
+
proposerProfile: 'default-author.profile.json',
|
|
763
766
|
// Per author SHOT (agenticGenerator timeoutMs). 20 min timed out 3× under
|
|
764
767
|
// degraded capacity in gen-1 ("author shot timed out") — doubled to 40 min.
|
|
765
768
|
proposerTimeoutMs: 2_400_000,
|
|
@@ -836,7 +839,7 @@ export function resolveSmokeInstance(
|
|
|
836
839
|
* The gen-3 config: protocol round 4 continues (frozen arm, same holdout
|
|
837
840
|
* registry, same roundsDir staircase) with the gen-3 machinery on:
|
|
838
841
|
*
|
|
839
|
-
* - THREE parallel proposers
|
|
842
|
+
* - THREE parallel Pi proposers using the exact GLM author profile that
|
|
840
843
|
* differ by diagnosis slice/lens — fan-out diversity without unproven
|
|
841
844
|
* harness seats; `populationSize` = `proposers.length`.
|
|
842
845
|
* - Pre-filter enabled at the mechanism bar on the cheapest-of-set smoke
|
|
@@ -858,18 +861,25 @@ export function defaultGen3Config(
|
|
|
858
861
|
const base = defaultRound4Config(hh, opts)
|
|
859
862
|
const outDirName = opts.outDirName ?? 'gen3'
|
|
860
863
|
const proposers: ProposerSpec[] = [
|
|
861
|
-
{
|
|
864
|
+
{
|
|
865
|
+
name: 'default-author',
|
|
866
|
+
profile: 'default-author.profile.json',
|
|
867
|
+
harness: 'pi',
|
|
868
|
+
model: 'glm-5.2',
|
|
869
|
+
},
|
|
862
870
|
{
|
|
863
871
|
name: 'mechanics-author',
|
|
864
872
|
profile: 'default-author.profile.json',
|
|
865
|
-
harness: '
|
|
873
|
+
harness: 'pi',
|
|
874
|
+
model: 'glm-5.2',
|
|
866
875
|
diagnosisSlice: 'mechanics',
|
|
867
876
|
lens: 'Focus on MECHANICS: worker lifecycle, sandbox/clone contracts, settlement and delivery paths. Prefer code-path fixes over prompt wording.',
|
|
868
877
|
},
|
|
869
878
|
{
|
|
870
879
|
name: 'prompts-author',
|
|
871
880
|
profile: 'default-author.profile.json',
|
|
872
|
-
harness: '
|
|
881
|
+
harness: 'pi',
|
|
882
|
+
model: 'glm-5.2',
|
|
873
883
|
diagnosisSlice: 'prompts',
|
|
874
884
|
lens: 'Focus on PROMPTS: worker/brain instruction wording, placement guidance, self-check discipline. Prefer prompt/instruction changes over code-path rewrites.',
|
|
875
885
|
},
|
|
@@ -921,13 +931,8 @@ export const GEN3_PARETO_PARENTS: ParetoParentSeed[] = [
|
|
|
921
931
|
* The gen-4 config: protocol round 4 continues (frozen arm, same holdout
|
|
922
932
|
* registry, same roundsDir staircase) with three changes as a unit:
|
|
923
933
|
*
|
|
924
|
-
* 1. PINNED PER-PROPOSER MODELS —
|
|
925
|
-
*
|
|
926
|
-
* `<outDir>/proposer-provenance.json` at t=0), glm-author (opencode
|
|
927
|
-
* pinned to zai-coding-plan/glm-5.2 via `-m`), codex-author (codex CLI on
|
|
928
|
-
* its ChatGPT login, auth provenance-gated at launch; drop the seat via
|
|
929
|
-
* `includeCodex: false` when the CLI is absent), and merge-author (claude,
|
|
930
|
-
* merge seat).
|
|
934
|
+
* 1. PINNED PER-PROPOSER MODELS — GLM 5.2 and DeepSeek V4 Flash run through
|
|
935
|
+
* Pi and Tangle Router; the merge seat uses the same exact GLM profile.
|
|
931
936
|
* 2. PARETO PARENTS — the gen-3 winner + runner-up diffs and their measured
|
|
932
937
|
* per-instance results seed every author's prompt; the merge seat's task
|
|
933
938
|
* is their coherent union. Seeded at the buildPrompt seam (our seam): the
|
|
@@ -941,14 +946,33 @@ export const GEN3_PARETO_PARENTS: ParetoParentSeed[] = [
|
|
|
941
946
|
*/
|
|
942
947
|
export function defaultGen4Config(
|
|
943
948
|
hh = DEFAULT_HH_SCRATCHPAD,
|
|
944
|
-
opts: { outDirName?: string;
|
|
949
|
+
opts: { outDirName?: string; includeDeepseek?: boolean } = {},
|
|
945
950
|
): OuterLoopConfig {
|
|
946
951
|
const base = defaultGen3Config(hh, { outDirName: opts.outDirName ?? 'gen4' })
|
|
947
952
|
const proposers: ProposerSpec[] = [
|
|
948
|
-
{
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
953
|
+
{
|
|
954
|
+
name: 'glm-author',
|
|
955
|
+
profile: 'default-author.profile.json',
|
|
956
|
+
harness: 'pi',
|
|
957
|
+
model: 'glm-5.2',
|
|
958
|
+
},
|
|
959
|
+
...(opts.includeDeepseek === false
|
|
960
|
+
? []
|
|
961
|
+
: [
|
|
962
|
+
{
|
|
963
|
+
name: 'deepseek-author',
|
|
964
|
+
profile: 'deepseek-author.profile.json',
|
|
965
|
+
harness: 'pi',
|
|
966
|
+
model: 'deepseek-v4-flash',
|
|
967
|
+
} satisfies ProposerSpec,
|
|
968
|
+
]),
|
|
969
|
+
{
|
|
970
|
+
name: 'merge-author',
|
|
971
|
+
profile: 'default-author.profile.json',
|
|
972
|
+
harness: 'pi',
|
|
973
|
+
model: 'glm-5.2',
|
|
974
|
+
merge: true,
|
|
975
|
+
},
|
|
952
976
|
]
|
|
953
977
|
return {
|
|
954
978
|
...base,
|
|
@@ -979,11 +1003,11 @@ export function defaultGen4Config(
|
|
|
979
1003
|
|
|
980
1004
|
export function defaultGen5Config(
|
|
981
1005
|
hh = DEFAULT_HH_SCRATCHPAD,
|
|
982
|
-
opts: { outDirName?: string;
|
|
1006
|
+
opts: { outDirName?: string; includeDeepseek?: boolean } = {},
|
|
983
1007
|
): OuterLoopConfig {
|
|
984
1008
|
const base = defaultGen4Config(hh, {
|
|
985
1009
|
outDirName: opts.outDirName ?? 'gen5',
|
|
986
|
-
...(opts.
|
|
1010
|
+
...(opts.includeDeepseek !== undefined ? { includeDeepseek: opts.includeDeepseek } : {}),
|
|
987
1011
|
})
|
|
988
1012
|
return {
|
|
989
1013
|
...base,
|
|
@@ -1261,7 +1285,7 @@ const CLAUDE_AMBIENT_AUTH_VARS = ['ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN', '
|
|
|
1261
1285
|
* leaked auth is stripped for the shot subprocess only. */
|
|
1262
1286
|
const CODEX_AMBIENT_AUTH_VARS = ['OPENAI_API_KEY', 'OPENAI_BASE_URL'] as const
|
|
1263
1287
|
|
|
1264
|
-
export function proposerShotEnv(harness:
|
|
1288
|
+
export function proposerShotEnv(harness: NonNullable<ProposerSpec['harness']>): NodeJS.ProcessEnv {
|
|
1265
1289
|
const env: NodeJS.ProcessEnv = { ...process.env }
|
|
1266
1290
|
if (harness === 'claude-code') {
|
|
1267
1291
|
for (const name of CLAUDE_AMBIENT_AUTH_VARS) delete env[name]
|
|
@@ -1272,43 +1296,51 @@ export function proposerShotEnv(harness: OuterLoopConfig['proposerHarness']): No
|
|
|
1272
1296
|
return env
|
|
1273
1297
|
}
|
|
1274
1298
|
|
|
1299
|
+
function configuredAuthorProfile(config: OuterLoopConfig): AgentProfile {
|
|
1300
|
+
const spec =
|
|
1301
|
+
config.proposers?.find((proposer) => proposer.engine === undefined) ??
|
|
1302
|
+
({
|
|
1303
|
+
name: 'single-author',
|
|
1304
|
+
profile: config.proposerProfile,
|
|
1305
|
+
harness: config.proposerHarness,
|
|
1306
|
+
} satisfies ProposerSpec)
|
|
1307
|
+
const profile = resolveAuthorProfile(spec)
|
|
1308
|
+
if (!profile) throw new Error(`author ${spec.name}: an exact AgentProfile is required`)
|
|
1309
|
+
return profile
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
function authorExecutorForWorktree(worktreePath: string) {
|
|
1313
|
+
const bridgeUrl = process.env.CLI_BRIDGE_URL ?? process.env.BRIDGE_URL
|
|
1314
|
+
const bridgeBearer = process.env.CLI_BRIDGE_BEARER ?? process.env.BRIDGE_BEARER
|
|
1315
|
+
if (!bridgeUrl || !bridgeBearer) {
|
|
1316
|
+
throw new Error(
|
|
1317
|
+
'authoring requires CLI_BRIDGE_URL/BRIDGE_URL and CLI_BRIDGE_BEARER/BRIDGE_BEARER',
|
|
1318
|
+
)
|
|
1319
|
+
}
|
|
1320
|
+
return {
|
|
1321
|
+
backend: 'bridge' as const,
|
|
1322
|
+
bridgeUrl,
|
|
1323
|
+
bridgeBearer,
|
|
1324
|
+
cwd: worktreePath,
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1275
1328
|
export function constrainedLoopsGenerator(config: OuterLoopConfig): CandidateGenerator {
|
|
1276
1329
|
const shotDir = join(config.outDir, 'proposer-shots')
|
|
1277
|
-
// The run-wide CostLedger the current generate() call rides — captured so
|
|
1278
|
-
// onShotCompleted can settle each shot's spend into it. maxConcurrency is 1
|
|
1279
|
-
// and shots run inside generate(), so a single slot cannot interleave.
|
|
1280
|
-
let activeLedger: CostLedgerHandle | undefined
|
|
1281
|
-
let activePhase: string | undefined
|
|
1282
1330
|
const inner = agenticGenerator({
|
|
1283
|
-
|
|
1331
|
+
profile: configuredAuthorProfile(config),
|
|
1332
|
+
executorForWorktree: authorExecutorForWorktree,
|
|
1284
1333
|
timeoutMs: config.proposerTimeoutMs,
|
|
1285
1334
|
buildPrompt: round4BuildPrompt,
|
|
1286
1335
|
verify: loopsCandidateVerifier(config.loopsRepo),
|
|
1287
|
-
runHarness: (options) => runLocalHarness({ ...options, env: proposerShotEnv(config.proposerHarness) }),
|
|
1288
|
-
// Three runs died as "author shot exited with code 1" with the shot's
|
|
1289
|
-
// stderr lost (nothing wires receipt persistence by default). Persist every
|
|
1290
|
-
// attempted shot — receipt plus bounded stream tails — so the NEXT failure
|
|
1291
|
-
// names its cause from disk. Shared implementation with the gen-3 fan-out
|
|
1292
|
-
// authors (proposer-fanout.mts): receipt persistence + spend settlement
|
|
1293
|
-
// into the run ledger for the claude/opencode paths whose shots would
|
|
1294
|
-
// otherwise read $0.
|
|
1295
1336
|
onShotCompleted: proposerShotHooks({
|
|
1296
1337
|
shotDir,
|
|
1297
|
-
harness: config.proposerHarness,
|
|
1298
|
-
ledger: () => activeLedger,
|
|
1299
|
-
phase: () => activePhase,
|
|
1300
1338
|
}),
|
|
1301
1339
|
})
|
|
1302
1340
|
return {
|
|
1303
1341
|
kind: `round4-constrained:${inner.kind}`,
|
|
1304
1342
|
proposesWithoutFindings: true,
|
|
1305
|
-
generate: (args) =>
|
|
1306
|
-
activeLedger = args.costLedger
|
|
1307
|
-
activePhase = args.costPhase
|
|
1308
|
-
// args.maxShots is the LIB's dial (budget.maxImprovementShots → the
|
|
1309
|
-
// improvement driver); capabilities.mts guarantees it is threaded.
|
|
1310
|
-
return inner.generate(args)
|
|
1311
|
-
},
|
|
1343
|
+
generate: (args) => inner.generate(args),
|
|
1312
1344
|
}
|
|
1313
1345
|
}
|
|
1314
1346
|
|
|
@@ -2001,12 +2033,9 @@ export async function runRound(config: OuterLoopConfig, signal?: AbortSignal): P
|
|
|
2001
2033
|
evidence_refs: [],
|
|
2002
2034
|
proposal_origin: 'search',
|
|
2003
2035
|
})
|
|
2004
|
-
const analyzeGeneration
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
candidates: Array<{ surfaceHash: string; composite: number; campaign: unknown }>
|
|
2008
|
-
history: unknown[]
|
|
2009
|
-
}): Promise<ProposalFinding[]> => {
|
|
2036
|
+
const analyzeGeneration: NonNullable<
|
|
2037
|
+
ImproveCodeRunOptions<Scenario, R4Artifact>['analyzeGeneration']
|
|
2038
|
+
> = async (input): Promise<ProposalFinding[]> => {
|
|
2010
2039
|
signal?.throwIfAborted()
|
|
2011
2040
|
const runs: SupRunArtifacts[] = []
|
|
2012
2041
|
if (input.generation === -1) {
|
|
@@ -2030,9 +2059,11 @@ export async function runRound(config: OuterLoopConfig, signal?: AbortSignal): P
|
|
|
2030
2059
|
// Candidate failure artifacts come from the LIB's campaign cells (the
|
|
2031
2060
|
// artifacts name their own runDir/patch) — resume-replayed cells included,
|
|
2032
2061
|
// which the old recorder-based lookup silently dropped.
|
|
2033
|
-
const worstFirst = [...input.candidates]
|
|
2062
|
+
const worstFirst = [...input.candidates]
|
|
2063
|
+
.sort((a, b) => (a.composite ?? -Infinity) - (b.composite ?? -Infinity))
|
|
2064
|
+
.slice(0, 4)
|
|
2034
2065
|
for (const cand of worstFirst) {
|
|
2035
|
-
const cells = cellsFromCampaign(cand.campaign
|
|
2066
|
+
const cells = cellsFromCampaign(cand.campaign)
|
|
2036
2067
|
for (const cell of cells) {
|
|
2037
2068
|
const a = cell.artifact
|
|
2038
2069
|
if (a === null || a.kind !== 'swe-arm' || !a.runDir) continue
|
|
@@ -2083,16 +2114,17 @@ export async function runRound(config: OuterLoopConfig, signal?: AbortSignal): P
|
|
|
2083
2114
|
: {
|
|
2084
2115
|
...input,
|
|
2085
2116
|
candidates: input.candidates.map((cand) => {
|
|
2086
|
-
const campaign = cand.campaign as { cells?: Array<{ scenarioId: string }> } | null
|
|
2087
|
-
if (campaign === null || typeof campaign !== 'object' || !Array.isArray(campaign.cells)) return cand
|
|
2088
2117
|
return {
|
|
2089
2118
|
...cand,
|
|
2090
|
-
campaign: {
|
|
2119
|
+
campaign: {
|
|
2120
|
+
...cand.campaign,
|
|
2121
|
+
cells: cand.campaign.cells.filter((cell) => !privateIids.has(cell.scenarioId)),
|
|
2122
|
+
},
|
|
2091
2123
|
}
|
|
2092
2124
|
}),
|
|
2093
2125
|
}
|
|
2094
2126
|
signal?.throwIfAborted()
|
|
2095
|
-
const rawFindings = await rawTrace(censoredInput
|
|
2127
|
+
const rawFindings = await rawTrace(censoredInput)
|
|
2096
2128
|
signal?.throwIfAborted()
|
|
2097
2129
|
return [steeringFinding, ...ensembleFindings, ...rawFindings]
|
|
2098
2130
|
}
|
|
@@ -2161,6 +2193,7 @@ export async function runRound(config: OuterLoopConfig, signal?: AbortSignal): P
|
|
|
2161
2193
|
repoRoot: config.loopsRepo,
|
|
2162
2194
|
baseRef: config.loopsBaseRef,
|
|
2163
2195
|
worktreeDir: join(config.outDir, 'loops-worktrees'),
|
|
2196
|
+
profile: configuredAuthorProfile(config),
|
|
2164
2197
|
generator,
|
|
2165
2198
|
},
|
|
2166
2199
|
scenarios: sweScenarios,
|
|
@@ -2764,17 +2797,8 @@ if (isMain) {
|
|
|
2764
2797
|
let config: OuterLoopConfig
|
|
2765
2798
|
let flavor: string
|
|
2766
2799
|
if (gen4 || gen5) {
|
|
2767
|
-
// The codex seat rides only when the CLI is actually present — a config
|
|
2768
|
-
// naming a missing harness would fail the whole launch at t=0.
|
|
2769
|
-
const codexProbe = await run('codex', ['--version'])
|
|
2770
|
-
const includeCodex = codexProbe.code === 0
|
|
2771
|
-
if (!includeCodex) {
|
|
2772
|
-
console.log(
|
|
2773
|
-
`codex CLI unavailable (rc=${codexProbe.code}) — ${gen5 ? 'gen-5' : 'gen-4'} config written WITHOUT the codex-author seat`,
|
|
2774
|
-
)
|
|
2775
|
-
}
|
|
2776
2800
|
const make = gen5 ? defaultGen5Config : defaultGen4Config
|
|
2777
|
-
config = make(undefined, { ...(outDirName ? { outDirName } : {})
|
|
2801
|
+
config = make(undefined, { ...(outDirName ? { outDirName } : {}) })
|
|
2778
2802
|
flavor = gen5 ? 'gen-5' : 'gen-4'
|
|
2779
2803
|
} else {
|
|
2780
2804
|
const make = gen3 ? defaultGen3Config : defaultRound4Config
|
|
@@ -153,6 +153,16 @@ export function buildPremeasuredFromCells(input: {
|
|
|
153
153
|
if (cell.artifact === null || cell.artifact.kind !== 'swe-arm') {
|
|
154
154
|
throw new Error(`premeasured-from-cells: cell ${cell.cellId} has no swe-arm artifact`)
|
|
155
155
|
}
|
|
156
|
+
if (cell.costProvenance.kind === 'uncaptured') {
|
|
157
|
+
throw new Error(`premeasured-from-cells: cell ${cell.cellId} has uncaptured cost`)
|
|
158
|
+
}
|
|
159
|
+
if (
|
|
160
|
+
cell.costProvenance.usd !== cell.costUsd
|
|
161
|
+
) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
`premeasured-from-cells: cell ${cell.cellId} cost provenance does not match costUsd`,
|
|
164
|
+
)
|
|
165
|
+
}
|
|
156
166
|
}
|
|
157
167
|
|
|
158
168
|
const scenarios: Scenario[] = instances.map((iid) => ({ id: iid, kind: 'swe-instance' }))
|
|
@@ -180,6 +190,11 @@ export function buildPremeasuredFromCells(input: {
|
|
|
180
190
|
}),
|
|
181
191
|
)
|
|
182
192
|
const totalCostUsd = sorted.reduce((s, c) => s + c.costUsd, 0)
|
|
193
|
+
const costProvenance: CampaignCellResult<R4Artifact>['costProvenance'] = sorted.some(
|
|
194
|
+
(cell) => cell.costProvenance.kind === 'estimated',
|
|
195
|
+
)
|
|
196
|
+
? { kind: 'estimated', usd: totalCostUsd }
|
|
197
|
+
: { kind: 'observed', usd: totalCostUsd }
|
|
183
198
|
const inputTokens = sorted.reduce((s, c) => s + c.tokenUsage.input, 0)
|
|
184
199
|
const outputTokens = sorted.reduce((s, c) => s + c.tokenUsage.output, 0)
|
|
185
200
|
const totalCalls = sorted.reduce((s, c) => s + (c.costCallIds?.length ?? 0), 0)
|
|
@@ -213,6 +228,7 @@ export function buildPremeasuredFromCells(input: {
|
|
|
213
228
|
outputTokens,
|
|
214
229
|
cachedTokens: 0,
|
|
215
230
|
totalCostUsd,
|
|
231
|
+
costProvenance,
|
|
216
232
|
byChannel: [
|
|
217
233
|
{
|
|
218
234
|
channel: 'agent',
|
|
@@ -231,7 +247,6 @@ export function buildPremeasuredFromCells(input: {
|
|
|
231
247
|
accountingComplete: true,
|
|
232
248
|
incompleteReasons: [],
|
|
233
249
|
},
|
|
234
|
-
totalCostUsd,
|
|
235
250
|
cellsExecuted: sorted.length,
|
|
236
251
|
cellsSkipped: 0,
|
|
237
252
|
cellsCached: sorted.length,
|
|
@@ -49,6 +49,7 @@ const cell = (iid: string, rep: number, resolved: boolean, over: Partial<FullCel
|
|
|
49
49
|
},
|
|
50
50
|
},
|
|
51
51
|
costUsd: 0.05,
|
|
52
|
+
costProvenance: { kind: 'observed', usd: 0.05 },
|
|
52
53
|
costCallIds: [`call-${iid}-${rep}`],
|
|
53
54
|
tokenUsage: { input: 100, output: 50 },
|
|
54
55
|
resolvedModel: 'zai-coding-plan/glm-5.2',
|
|
@@ -85,7 +86,11 @@ describe('buildPremeasuredFromCells', () => {
|
|
|
85
86
|
expect(out.campaign.cells.every((c) => c.cached)).toBe(true)
|
|
86
87
|
expect(out.campaign.cells.every((c) => !('mtimeMs' in c))).toBe(true)
|
|
87
88
|
// Honest spend rollup from the real cells.
|
|
88
|
-
expect(out.campaign.aggregates.totalCostUsd).toBeCloseTo(0.2)
|
|
89
|
+
expect(out.campaign.aggregates.cost.totalCostUsd).toBeCloseTo(0.2)
|
|
90
|
+
expect(out.campaign.aggregates.cost.costProvenance).toEqual({
|
|
91
|
+
kind: 'observed',
|
|
92
|
+
usd: 0.2,
|
|
93
|
+
})
|
|
89
94
|
expect(out.campaign.aggregates.cost.inputTokens).toBe(400)
|
|
90
95
|
expect(out.campaign.runDir).toBe('/prior/baseline')
|
|
91
96
|
// Window reconstructed from mtimes: ends at the last cell write.
|
|
@@ -126,6 +131,21 @@ describe('buildPremeasuredFromCells', () => {
|
|
|
126
131
|
expect(() =>
|
|
127
132
|
buildPremeasuredFromCells({ cells: errored, instances: INSTANCES, reps: 2, surfaceHash: 'x', sourceDir: '/p' }),
|
|
128
133
|
).toThrow(/carries an error/)
|
|
134
|
+
const uncapturedCost = [
|
|
135
|
+
cell('inst-a', 0, false, { costProvenance: { kind: 'uncaptured', usd: null } }),
|
|
136
|
+
cell('inst-a', 1, true),
|
|
137
|
+
cell('inst-b', 0, true),
|
|
138
|
+
cell('inst-b', 1, true),
|
|
139
|
+
]
|
|
140
|
+
expect(() =>
|
|
141
|
+
buildPremeasuredFromCells({
|
|
142
|
+
cells: uncapturedCost,
|
|
143
|
+
instances: INSTANCES,
|
|
144
|
+
reps: 2,
|
|
145
|
+
surfaceHash: 'x',
|
|
146
|
+
sourceDir: '/p',
|
|
147
|
+
}),
|
|
148
|
+
).toThrow(/has uncaptured cost/)
|
|
129
149
|
})
|
|
130
150
|
})
|
|
131
151
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "swe-arena-deepseek-author",
|
|
3
|
+
"description": "Pi author using DeepSeek V4 Flash through Tangle Router.",
|
|
4
|
+
"harness": "pi",
|
|
5
|
+
"model": {
|
|
6
|
+
"provider": "tangle-router",
|
|
7
|
+
"default": "deepseek-v4-flash"
|
|
8
|
+
},
|
|
9
|
+
"prompt": {
|
|
10
|
+
"systemPrompt": "Improve the candidate worktree from measured failure evidence. Make the smallest coherent change, verify it, and leave the edit uncommitted."
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "swe-arena-default-author",
|
|
3
|
-
"description": "
|
|
3
|
+
"description": "Pi author for measured SWE arena code improvement.",
|
|
4
|
+
"harness": "pi",
|
|
5
|
+
"model": {
|
|
6
|
+
"provider": "tangle-router",
|
|
7
|
+
"default": "glm-5.2"
|
|
8
|
+
},
|
|
9
|
+
"prompt": {
|
|
10
|
+
"systemPrompt": "Improve the candidate worktree from measured failure evidence. Make the smallest coherent change, verify it, and leave the edit uncommitted."
|
|
11
|
+
}
|
|
4
12
|
}
|