@tangle-network/agent-eval 0.139.2 → 0.139.3
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/dist/analyst/index.d.ts +101 -9
- package/dist/analyst/index.d.ts.map +1 -1
- package/dist/analyst/index.js +2 -2
- package/dist/{benchmark-command-DzUZJl8M.js → benchmark-command-xvi2liH7.js} +590 -317
- package/dist/benchmark-command-xvi2liH7.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/{index-BipJlj-C.d.ts → index-B798zyGh.d.ts} +5 -2
- package/dist/{index-BipJlj-C.d.ts.map → index-B798zyGh.d.ts.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/openapi.json +1 -1
- package/dist/supervisor-run/index.d.ts +1 -1
- package/dist/supervisor-run/index.js +1 -1
- package/dist/{supervisor-run-B2EWUmQY.js → supervisor-run-D6A5oQw-.js} +18 -9
- package/dist/supervisor-run-D6A5oQw-.js.map +1 -0
- package/package.json +1 -1
- package/dist/benchmark-command-DzUZJl8M.js.map +0 -1
- package/dist/supervisor-run-B2EWUmQY.js.map +0 -1
|
@@ -1172,7 +1172,7 @@ const ANALYST_BENCHMARK_DEPENDENCY_LOCK_FILES = Object.freeze([
|
|
|
1172
1172
|
"package.json",
|
|
1173
1173
|
"pnpm-lock.yaml"
|
|
1174
1174
|
]);
|
|
1175
|
-
const ANALYST_BENCHMARK_DEPENDENCY_LOCK_SHA256 = "
|
|
1175
|
+
const ANALYST_BENCHMARK_DEPENDENCY_LOCK_SHA256 = "11ea62baf2914dba71dd62e45ba4bb8e856b2cefdd5b1b73dc2f14b4b6e6d115";
|
|
1176
1176
|
/** The published benchmark evidence was produced at this package version, by
|
|
1177
1177
|
* the retired one-shot direct runner, before trace analysts moved to the
|
|
1178
1178
|
* recursive DSPy RLM engine. Both evidence digests below are historical facts
|
|
@@ -1203,6 +1203,7 @@ const ANALYST_BENCHMARK_IMPLEMENTATION_FILES = Object.freeze([
|
|
|
1203
1203
|
"src/analyst/benchmark-public-data.ts",
|
|
1204
1204
|
"src/analyst/benchmark-public-errors.ts",
|
|
1205
1205
|
"src/analyst/benchmark-public-model.ts",
|
|
1206
|
+
"src/analyst/benchmark-public-prompt.ts",
|
|
1206
1207
|
"src/analyst/benchmark-public-rlm.ts",
|
|
1207
1208
|
"src/analyst/benchmark-public-types.ts",
|
|
1208
1209
|
"src/analyst/benchmark-real-model.ts",
|
|
@@ -1265,7 +1266,7 @@ const ANALYST_BENCHMARK_IMPLEMENTATION_FILES = Object.freeze([
|
|
|
1265
1266
|
"src/trace/otlp-attributes.ts",
|
|
1266
1267
|
"src/trace/raw-provider-sink.ts"
|
|
1267
1268
|
]);
|
|
1268
|
-
const ANALYST_BENCHMARK_IMPLEMENTATION_SHA256 = "
|
|
1269
|
+
const ANALYST_BENCHMARK_IMPLEMENTATION_SHA256 = "26820de559ca069145eb9649283d2efba51a0a7b8d3662d4c378b9ecebfd4777";
|
|
1269
1270
|
function analystBenchmarkImplementationDigest() {
|
|
1270
1271
|
return ANALYST_BENCHMARK_IMPLEMENTATION_SHA256;
|
|
1271
1272
|
}
|
|
@@ -1332,19 +1333,12 @@ async function validateCodeTraceFindingEvidence(options) {
|
|
|
1332
1333
|
if (citations.length === 0) return;
|
|
1333
1334
|
for (const citation of citations) if (!citation.location || citation.location.traceId !== options.trajectoryId) throw new Error(`model finding '${citation.findingId}' cites non-case evidence '${citation.evidence.uri}'`);
|
|
1334
1335
|
const spanIds = [...new Set(citations.map((citation) => `step-${citation.location.step}`))];
|
|
1335
|
-
const spans
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
}, options.signal ? { signal: options.signal } : void 0);
|
|
1342
|
-
if (result.missing_span_ids.length > 0 || result.omitted_span_ids.length > 0) {
|
|
1343
|
-
const unavailable = [...result.missing_span_ids, ...result.omitted_span_ids];
|
|
1344
|
-
throw new Error(`model finding evidence is unavailable in the case trace: ${unavailable.join(", ")}`);
|
|
1345
|
-
}
|
|
1346
|
-
for (const span of result.spans) spans.set(span.span_id, span);
|
|
1347
|
-
}
|
|
1336
|
+
const { spans, missing } = await fetchTraceSpans(options.store, {
|
|
1337
|
+
trajectoryId: options.trajectoryId,
|
|
1338
|
+
spanIds,
|
|
1339
|
+
...options.signal ? { signal: options.signal } : {}
|
|
1340
|
+
});
|
|
1341
|
+
if (missing.length > 0) throw new Error(`model finding evidence is unavailable in the case trace: ${missing.join(", ")}`);
|
|
1348
1342
|
for (const citation of citations) {
|
|
1349
1343
|
const spanId = `step-${citation.location.step}`;
|
|
1350
1344
|
const span = spans.get(spanId);
|
|
@@ -1353,31 +1347,45 @@ async function validateCodeTraceFindingEvidence(options) {
|
|
|
1353
1347
|
assertExactActionExcerpt(citation.findingId, citation.evidence, spanId, span.attributes.content);
|
|
1354
1348
|
}
|
|
1355
1349
|
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Resolve assistant-step evidence for a trajectory.
|
|
1352
|
+
*
|
|
1353
|
+
* `steps` are claims the model made explicitly: an unresolvable one is a model
|
|
1354
|
+
* error and throws. `optionalSteps` are derived by the runner (a block's
|
|
1355
|
+
* interior, a block's consequence step), so an unresolvable one is simply
|
|
1356
|
+
* absent from the returned map and the caller decides what that means.
|
|
1357
|
+
*/
|
|
1356
1358
|
async function resolveAssistantStepEvidence(options) {
|
|
1357
|
-
const
|
|
1358
|
-
|
|
1359
|
-
const
|
|
1360
|
-
const
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
throw new Error(`model selected unavailable assistant steps: ${unavailable.join(", ")}`);
|
|
1370
|
-
}
|
|
1371
|
-
for (const span of result.spans) spans.set(span.span_id, span);
|
|
1372
|
-
}
|
|
1359
|
+
const required = [...new Set(options.steps)];
|
|
1360
|
+
const optional = [...new Set(options.optionalSteps ?? [])].filter((step) => !required.includes(step));
|
|
1361
|
+
for (const step of [...required, ...optional]) if (!Number.isSafeInteger(step) || step < 1) throw new TypeError(`assistant evidence step must be a positive safe integer: ${step}`);
|
|
1362
|
+
const steps = [...required, ...optional];
|
|
1363
|
+
if (steps.length === 0) return /* @__PURE__ */ new Map();
|
|
1364
|
+
const { spans, missing } = await fetchTraceSpans(options.store, {
|
|
1365
|
+
trajectoryId: options.trajectoryId,
|
|
1366
|
+
spanIds: steps.map((step) => `step-${step}`),
|
|
1367
|
+
...options.signal ? { signal: options.signal } : {}
|
|
1368
|
+
});
|
|
1369
|
+
const missingRequired = missing.filter((spanId) => required.some((step) => `step-${step}` === spanId));
|
|
1370
|
+
if (missingRequired.length > 0) throw new Error(`model selected unavailable assistant steps: ${missingRequired.join(", ")}`);
|
|
1373
1371
|
const evidence = /* @__PURE__ */ new Map();
|
|
1374
1372
|
for (const step of steps) {
|
|
1375
1373
|
const spanId = `step-${step}`;
|
|
1374
|
+
const optionalStep = optional.includes(step);
|
|
1376
1375
|
const span = spans.get(spanId);
|
|
1377
|
-
if (!span)
|
|
1378
|
-
|
|
1376
|
+
if (!span) {
|
|
1377
|
+
if (optionalStep) continue;
|
|
1378
|
+
throw new Error(`model selected missing assistant step '${spanId}'`);
|
|
1379
|
+
}
|
|
1380
|
+
if (span.kind !== "LLM") {
|
|
1381
|
+
if (optionalStep) continue;
|
|
1382
|
+
throw new Error(`model selected '${spanId}', which is ${span.kind}, not an assistant LLM span`);
|
|
1383
|
+
}
|
|
1379
1384
|
const content = span.attributes.content;
|
|
1380
|
-
if (typeof content !== "string" || content.trim().length === 0)
|
|
1385
|
+
if (typeof content !== "string" || content.trim().length === 0) {
|
|
1386
|
+
if (optionalStep) continue;
|
|
1387
|
+
throw new Error(`model selected '${spanId}' without action content`);
|
|
1388
|
+
}
|
|
1381
1389
|
evidence.set(step, {
|
|
1382
1390
|
kind: "span",
|
|
1383
1391
|
uri: codeTraceStepEvidenceUri(options.trajectoryId, step),
|
|
@@ -1386,6 +1394,38 @@ async function resolveAssistantStepEvidence(options) {
|
|
|
1386
1394
|
}
|
|
1387
1395
|
return evidence;
|
|
1388
1396
|
}
|
|
1397
|
+
/**
|
|
1398
|
+
* Read spans by id, paging over the store's byte-budget omissions.
|
|
1399
|
+
*
|
|
1400
|
+
* `omitted_span_ids` names spans that exist but did not fit the response
|
|
1401
|
+
* ceiling; the store guarantees at least one span lands per call, so
|
|
1402
|
+
* re-requesting exactly the omitted ids terminates. Only `missing_span_ids`
|
|
1403
|
+
* describes a span the trace does not contain.
|
|
1404
|
+
*/
|
|
1405
|
+
async function fetchTraceSpans(store, options) {
|
|
1406
|
+
const spans = /* @__PURE__ */ new Map();
|
|
1407
|
+
const missing = [];
|
|
1408
|
+
const unique = [...new Set(options.spanIds)];
|
|
1409
|
+
const context = options.signal ? { signal: options.signal } : void 0;
|
|
1410
|
+
for (let offset = 0; offset < unique.length; offset += TRACE_ANALYSIS_LIMITS.viewSpans) {
|
|
1411
|
+
let pending = unique.slice(offset, offset + TRACE_ANALYSIS_LIMITS.viewSpans);
|
|
1412
|
+
while (pending.length > 0) {
|
|
1413
|
+
const result = await store.viewSpans({
|
|
1414
|
+
trace_id: options.trajectoryId,
|
|
1415
|
+
span_ids: pending
|
|
1416
|
+
}, context);
|
|
1417
|
+
for (const span of result.spans) spans.set(span.span_id, span);
|
|
1418
|
+
missing.push(...result.missing_span_ids);
|
|
1419
|
+
const omitted = result.omitted_span_ids.filter((spanId) => !spans.has(spanId));
|
|
1420
|
+
if (omitted.length >= pending.length) throw new Error(`trace '${options.trajectoryId}' cannot project spans within the store response budget: ${omitted.join(", ")}`);
|
|
1421
|
+
pending = omitted;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
return {
|
|
1425
|
+
spans,
|
|
1426
|
+
missing
|
|
1427
|
+
};
|
|
1428
|
+
}
|
|
1389
1429
|
function scanValue(value, traceId, path, depth, serializedDepth) {
|
|
1390
1430
|
if (depth > MAX_LABEL_SCAN_DEPTH) throw new Error(`trace '${traceId}' exceeds benchmark label scan depth at ${path}`);
|
|
1391
1431
|
if (Array.isArray(value)) return 1 + value.reduce((count, entry, index) => count + scanValue(entry, traceId, `${path}[${index}]`, depth + 1, serializedDepth), 0);
|
|
@@ -1445,119 +1485,6 @@ function assertExactActionExcerpt(findingId, evidence, spanId, content) {
|
|
|
1445
1485
|
if (!content.includes(excerpt)) throw new Error(`model finding '${findingId}' excerpt is not present in '${spanId}' action content`);
|
|
1446
1486
|
}
|
|
1447
1487
|
//#endregion
|
|
1448
|
-
//#region src/analyst/benchmark-public-adapters.ts
|
|
1449
|
-
function emptyPublicBenchmarkRunner() {
|
|
1450
|
-
return {
|
|
1451
|
-
id: "empty",
|
|
1452
|
-
analyze() {
|
|
1453
|
-
return {
|
|
1454
|
-
findings: [],
|
|
1455
|
-
usage: {
|
|
1456
|
-
calls: 0,
|
|
1457
|
-
tokens: {
|
|
1458
|
-
input: 0,
|
|
1459
|
-
output: 0
|
|
1460
|
-
},
|
|
1461
|
-
cost: {
|
|
1462
|
-
kind: "observed",
|
|
1463
|
-
usd: 0
|
|
1464
|
-
}
|
|
1465
|
-
},
|
|
1466
|
-
metadata: { baseline: "emit-no-findings" }
|
|
1467
|
-
};
|
|
1468
|
-
}
|
|
1469
|
-
};
|
|
1470
|
-
}
|
|
1471
|
-
function adaptPublicBenchmarkFindings(dataset, trajectoryId, findings, analystId) {
|
|
1472
|
-
return dataset === "agentrx" ? adaptAgentRxFindings(trajectoryId, findings, analystId) : adaptCodeTraceFindings(trajectoryId, findings, analystId);
|
|
1473
|
-
}
|
|
1474
|
-
function adaptAgentRxFindings(trajectoryId, findings, analystId) {
|
|
1475
|
-
if (findings.length === 0) return [];
|
|
1476
|
-
if (findings.length !== 1) throw new Error(`AgentRx model analyst must emit zero or one root cause, received ${findings.length}`);
|
|
1477
|
-
const source = findings[0];
|
|
1478
|
-
if (!source.subject) throw new Error("AgentRx model analyst finding is missing its failure-category subject");
|
|
1479
|
-
const steps = exactFindingSteps(trajectoryId, source);
|
|
1480
|
-
if (steps.length !== 1) throw new Error(`AgentRx model analyst must cite exactly one root-cause step, received ${steps.length}`);
|
|
1481
|
-
const [adapted] = agentRxPredictionsToFindings(trajectoryId, [{
|
|
1482
|
-
failure_case: source.subject,
|
|
1483
|
-
step_number: steps[0],
|
|
1484
|
-
description: source.rationale ?? source.claim
|
|
1485
|
-
}], {
|
|
1486
|
-
analystId,
|
|
1487
|
-
producedAt: source.produced_at,
|
|
1488
|
-
confidence: source.confidence
|
|
1489
|
-
});
|
|
1490
|
-
if (!adapted) throw new Error("AgentRx output adapter produced no root-cause finding");
|
|
1491
|
-
return [{
|
|
1492
|
-
...adapted,
|
|
1493
|
-
metadata: {
|
|
1494
|
-
...adapted.metadata,
|
|
1495
|
-
sourceFindingId: source.finding_id
|
|
1496
|
-
}
|
|
1497
|
-
}];
|
|
1498
|
-
}
|
|
1499
|
-
function adaptCodeTraceFindings(trajectoryId, findings, analystId) {
|
|
1500
|
-
const clean = findings.filter((finding) => finding.subject === "clean");
|
|
1501
|
-
if (clean.length > 0) {
|
|
1502
|
-
if (findings.length !== 1) throw new Error("CodeTraceBench model analyst mixed a clean verdict with incorrect steps");
|
|
1503
|
-
exactFindingSteps(trajectoryId, clean[0]);
|
|
1504
|
-
return [];
|
|
1505
|
-
}
|
|
1506
|
-
const byStep = /* @__PURE__ */ new Map();
|
|
1507
|
-
for (const source of findings) {
|
|
1508
|
-
const steps = exactFindingSteps(trajectoryId, source);
|
|
1509
|
-
for (const step of steps) {
|
|
1510
|
-
if (byStep.has(step)) continue;
|
|
1511
|
-
byStep.set(step, makeFinding({
|
|
1512
|
-
analyst_id: analystId,
|
|
1513
|
-
area: "incorrect",
|
|
1514
|
-
subject: `incorrect-step-${step}`,
|
|
1515
|
-
claim: `Step ${step} is incorrect. ${source.claim}`,
|
|
1516
|
-
rationale: source.rationale,
|
|
1517
|
-
severity: source.severity,
|
|
1518
|
-
confidence: source.confidence,
|
|
1519
|
-
evidence_refs: [{
|
|
1520
|
-
kind: "span",
|
|
1521
|
-
uri: codeTraceStepEvidenceUri(trajectoryId, step),
|
|
1522
|
-
excerpt: source.evidence_refs.find((evidence) => evidence.uri === codeTraceStepEvidenceUri(trajectoryId, step))?.excerpt
|
|
1523
|
-
}],
|
|
1524
|
-
recommended_action: source.recommended_action,
|
|
1525
|
-
metadata: { sourceFindingId: source.finding_id },
|
|
1526
|
-
produced_at: source.produced_at,
|
|
1527
|
-
id_basis: `incorrect-step-${step}`
|
|
1528
|
-
}));
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
return [...byStep].sort(([left], [right]) => left - right).map(([, finding]) => finding);
|
|
1532
|
-
}
|
|
1533
|
-
function exactFindingSteps(trajectoryId, finding) {
|
|
1534
|
-
if (finding.evidence_refs.length === 0) throw new Error(`model finding '${finding.finding_id}' has no step evidence`);
|
|
1535
|
-
const steps = finding.evidence_refs.map((evidence) => {
|
|
1536
|
-
const parsed = codeTraceStepFromEvidence(evidence.uri);
|
|
1537
|
-
if (!parsed || parsed.traceId !== trajectoryId) throw new Error(`model finding '${finding.finding_id}' cites non-case evidence '${evidence.uri}'`);
|
|
1538
|
-
return parsed.step;
|
|
1539
|
-
});
|
|
1540
|
-
return [...new Set(steps)];
|
|
1541
|
-
}
|
|
1542
|
-
//#endregion
|
|
1543
|
-
//#region src/analyst/benchmark-public-types.ts
|
|
1544
|
-
function requiredString(value, field) {
|
|
1545
|
-
const trimmed = value.trim();
|
|
1546
|
-
if (!trimmed) throw new TypeError(`${field} must be a non-empty string`);
|
|
1547
|
-
return trimmed;
|
|
1548
|
-
}
|
|
1549
|
-
function positiveSafeInteger(value, field) {
|
|
1550
|
-
if (!Number.isSafeInteger(value) || value < 1) throw new RangeError(`${field} must be a positive safe integer`);
|
|
1551
|
-
return value;
|
|
1552
|
-
}
|
|
1553
|
-
function safeInteger(value, field) {
|
|
1554
|
-
if (!Number.isSafeInteger(value)) throw new RangeError(`${field} must be a safe integer`);
|
|
1555
|
-
return value;
|
|
1556
|
-
}
|
|
1557
|
-
function isRecord(value) {
|
|
1558
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1559
|
-
}
|
|
1560
|
-
//#endregion
|
|
1561
1488
|
//#region src/analyst/benchmark-verification-outcome.ts
|
|
1562
1489
|
const MAX_REPORTED_CHECKS = 20;
|
|
1563
1490
|
const SWE_MULTI_NO_TEST_RESULTS = "After applying the fix patch, no test results were captured when executing the test command.";
|
|
@@ -2157,6 +2084,376 @@ function isNodeError$1(error, code) {
|
|
|
2157
2084
|
return error instanceof Error && "code" in error && error.code === code;
|
|
2158
2085
|
}
|
|
2159
2086
|
//#endregion
|
|
2087
|
+
//#region src/analyst/benchmark-public-prompt.ts
|
|
2088
|
+
/** Widest contiguous failure block a model may report. The published corpus's
|
|
2089
|
+
* widest labeled block is 8 steps and its widest stage span is 9, so this bound
|
|
2090
|
+
* never binds honest enumeration; it caps how far one over-wide block can push
|
|
2091
|
+
* unlabeled steps into the precision denominator. */
|
|
2092
|
+
const MAX_INCORRECT_BLOCK_STEPS = 12;
|
|
2093
|
+
/** Most blocks a model may report for one trajectory. The published corpus's
|
|
2094
|
+
* densest case carries 4 disjoint labeled blocks. Together with the per-block
|
|
2095
|
+
* cap this bounds one case at 192 predicted steps without a second ceiling. */
|
|
2096
|
+
const MAX_INCORRECT_BLOCKS = 16;
|
|
2097
|
+
const TRACE_PROJECTION_ATTRIBUTE_BYTE_CAPS = [
|
|
2098
|
+
4096,
|
|
2099
|
+
2048,
|
|
2100
|
+
1024,
|
|
2101
|
+
512,
|
|
2102
|
+
256,
|
|
2103
|
+
128,
|
|
2104
|
+
64
|
|
2105
|
+
];
|
|
2106
|
+
const CODE_TRACE_BENCH_ANALYST_PROMPT = `Analyze exactly one coding-agent trajectory and its attached final verification.
|
|
2107
|
+
Your task is the CodeTraceBench incorrect-step task: identify every wrong state-changing action, bad hypothesis that drives an action, and regression.
|
|
2108
|
+
An incorrect step remains incorrect when the agent later recovers or the final verification passes; a trajectory that ends in success still contains every mistake the agent made along the way.
|
|
2109
|
+
Incorrect steps occur in contiguous failure blocks: one mistake plus every consecutive following step that commits to, compounds, or acts on it.
|
|
2110
|
+
Report each failure block as exactly one finding whose first_step is the block's first incorrect step and whose last_step is its last, covering every consecutive step between them.
|
|
2111
|
+
Set first_step to the first step that commits the mistake, not the step that planned it and not a later step that repeats it.
|
|
2112
|
+
Extend last_step one step at a time, and only while the next step independently satisfies the incorrect-step definition on its own action and its own following observation.
|
|
2113
|
+
Stop at the first step where the agent detects the problem, inspects it, or begins repairing it: a diagnostic probe, a test run that exposes the defect, or a repair action ends the block and is never inside it.
|
|
2114
|
+
A one-step block is a complete and correct answer.
|
|
2115
|
+
Every step inside a block is scored on its own: naming a correct step costs exactly as much as missing an incorrect one, and naming only the first step of a longer block forfeits every unnamed step.
|
|
2116
|
+
Report blocks separated by at least one correct step as separate findings, and never let two blocks overlap.
|
|
2117
|
+
Inspect the complete supplied trace data.
|
|
2118
|
+
Use the final-verification outcome as evidence about the final state, not as a rule for whether earlier steps were incorrect.
|
|
2119
|
+
For each candidate block, inspect every assistant action in it and its following observation.
|
|
2120
|
+
Admit a block only when you can point at the specific evidence it produced: name as consequence_step the step number whose action or observation shows the damage — a failing command, a wrong file state, a repeated failure, or rework the agent had to do because of this block. That step is the block's own last step when its observation already shows the damage, and a later step otherwise.
|
|
2121
|
+
When you cannot name that later step number from the trace you were given, drop the block; a plausible story about why a step looks wrong is not evidence that it was.
|
|
2122
|
+
Judge that consequence from the trajectory itself: a passing final verification is not evidence that a block caused nothing, and a failing final verification is not evidence that any particular block caused it.
|
|
2123
|
+
For every block, decide whether the agent escaped the failure.
|
|
2124
|
+
Mark escape_status "escaped" only when you can name the single later step that fully reversed the block, the agent needed no other step to recover, and nothing after that step revisits the same file, command, or hypothesis; write that step number in the rationale.
|
|
2125
|
+
Mark escape_status "unescaped" in every other case, including whenever you are unsure.
|
|
2126
|
+
A passing final verification never makes a block escaped: the agent may have made the mistake and repaired it over several steps, and those steps are still incorrect.
|
|
2127
|
+
Label a failed command when the assistant caused it through a wrong action or unsupported hypothesis.
|
|
2128
|
+
Label the later corrective action only when that action is itself wrong.
|
|
2129
|
+
Do not label a diagnostic probe merely because it exposes an earlier defect.
|
|
2130
|
+
Do not label a redundant but correct read or search; CodeTraceBench scores unuseful steps separately, and this run scores incorrect steps only.
|
|
2131
|
+
Do not label a step solely because final verification failed.
|
|
2132
|
+
When final verification is unavailable, use only directly observed trajectory evidence.
|
|
2133
|
+
Every step in a reported block MUST be the positive integer n from an existing assistant LLM span named step-<n>.
|
|
2134
|
+
Never select an EVALUATOR, TOOL, CHAIN, final-verification, benchmark-verification, or message-<n> span.
|
|
2135
|
+
Before emitting a finding, inspect every covered span's attributes.content and describe only the actions shown there.
|
|
2136
|
+
Report at most 16 blocks and at most 12 steps in one block; when more candidates than that exist, report the ones you can support with the clearest downstream evidence.
|
|
2137
|
+
When the trajectory has no incorrect steps, return an empty findings array.`;
|
|
2138
|
+
const AGENT_RX_PROMPT = `Analyze exactly one failed agent trajectory.
|
|
2139
|
+
Find the first unrecoverable critical failure, not every later symptom.
|
|
2140
|
+
Inspect the complete supplied trace data.
|
|
2141
|
+
Emit zero findings only when the trace does not contain enough evidence.
|
|
2142
|
+
Otherwise emit exactly one finding.
|
|
2143
|
+
Its category MUST be exactly one of:
|
|
2144
|
+
instruction-plan-adherence-failure
|
|
2145
|
+
invention-of-new-information
|
|
2146
|
+
invalid-invocation
|
|
2147
|
+
misinterpretation-of-tool-output-handoff-failure
|
|
2148
|
+
intent-plan-misalignment
|
|
2149
|
+
underspecified-user-intent
|
|
2150
|
+
intent-not-supported
|
|
2151
|
+
guardrails-triggered
|
|
2152
|
+
system-failure
|
|
2153
|
+
inconclusive
|
|
2154
|
+
Its step is the positive integer n from the first unrecoverable assistant span named step-<n>.`;
|
|
2155
|
+
const AGENT_RX_JSON_CONTRACT = `Each finding must contain only:
|
|
2156
|
+
- "step": a positive integer matching an existing assistant LLM span named step-<n>
|
|
2157
|
+
- "severity": "critical", "high", "medium", "low", or "info"
|
|
2158
|
+
- "claim": one sentence
|
|
2159
|
+
- "confidence": a number from 0 through 1
|
|
2160
|
+
- optional "rationale" and "recommended_action" strings
|
|
2161
|
+
- "category": one allowed failure category listed above`;
|
|
2162
|
+
const CODE_TRACE_JSON_CONTRACT = `Each finding is one contiguous failure block and must contain only:
|
|
2163
|
+
- "first_step": a positive integer, the block's first incorrect step, matching an existing assistant LLM span named step-<n>
|
|
2164
|
+
- "last_step": a positive integer >= first_step, the block's last incorrect step; every step from first_step through last_step must be an existing assistant LLM span, and a block spans at most 12 steps
|
|
2165
|
+
- "consequence_step": a positive integer >= first_step, the step whose action or following observation shows the damage this block caused; it may sit inside the block when the damage is already visible there
|
|
2166
|
+
- "escape_status": "escaped" only when one single later step fully reversed the block and nothing afterwards revisits it, "unescaped" otherwise and whenever you are unsure
|
|
2167
|
+
- "severity": "critical", "high", "medium", "low", or "info"
|
|
2168
|
+
- "claim": one sentence describing the block's failure
|
|
2169
|
+
- "confidence": a number from 0 through 1
|
|
2170
|
+
- optional "rationale" and "recommended_action" strings`;
|
|
2171
|
+
const AGENT_RX_RLM_CONTRACT = `Use the trace tools to inspect the action and its following observation.
|
|
2172
|
+
Emit exactly one finding whose subject is exactly one of the allowed failure categories.
|
|
2173
|
+
Cite exactly one assistant span named step-<n> as trace://<URL-encoded-trace-id>/span/step-<n>.
|
|
2174
|
+
The excerpt must quote the assistant action exactly.`;
|
|
2175
|
+
const CODE_TRACE_RLM_CONTRACT = `Use the trace tools rather than asking for the whole trajectory in the prompt.
|
|
2176
|
+
Keep retrieved trace objects in Python variables.
|
|
2177
|
+
Never print an entire trace, full source file, or more than 12000 characters in one iteration.
|
|
2178
|
+
Build a compact table of assistant step ids, actions, following observations, and final verification.
|
|
2179
|
+
Inspect suspicious steps with viewSpans or searchSpan instead of repeatedly printing the table.
|
|
2180
|
+
This runner emits no JSON fields, so the block is encoded in the finding's subject.
|
|
2181
|
+
Emit exactly one finding per contiguous failure block.
|
|
2182
|
+
Set the finding's subject to incorrect-steps-<first_step>-<last_step>-<escape_status>-consequence-<consequence_step>, using the same four values the task defines; for a block covering only step 7 that the agent never escaped and whose damage shows at step 9, the subject is incorrect-steps-7-7-unescaped-consequence-9.
|
|
2183
|
+
The runner expands the block to one scored step per member and builds every scored citation itself.
|
|
2184
|
+
Cite the block's first step and its last step as trace://<URL-encoded-trace-id>/span/step-<n>, each excerpt an exact quote from that step's own action content.
|
|
2185
|
+
Give the rationale as the concrete downstream evidence visible at the consequence step.
|
|
2186
|
+
Submit as soon as every candidate failure block has a supported verdict.
|
|
2187
|
+
Return no finding for a clean trajectory.`;
|
|
2188
|
+
/** One-shot JSON transport prompt for the direct runner. */
|
|
2189
|
+
function publicBenchmarkSystemPrompt(dataset) {
|
|
2190
|
+
const fieldContract = dataset === "agentrx" ? AGENT_RX_JSON_CONTRACT : CODE_TRACE_JSON_CONTRACT;
|
|
2191
|
+
return `${publicBenchmarkTaskPrompt(dataset)}
|
|
2192
|
+
|
|
2193
|
+
${fieldContract}
|
|
2194
|
+
|
|
2195
|
+
Return exactly one JSON object with:
|
|
2196
|
+
- "report": a concise evidence-based explanation, at most 4000 characters
|
|
2197
|
+
- "findings": the strict finding array
|
|
2198
|
+
Use an empty findings array when the trace does not support a finding.
|
|
2199
|
+
Do not return a bare array, markdown, trace URIs, copied excerpts, or fields not listed above.
|
|
2200
|
+
The runner constructs exact trace URIs and action previews from each selected step.`;
|
|
2201
|
+
}
|
|
2202
|
+
/** Tool-loop prompt for the recursive runner. Same task, subject-encoded block. */
|
|
2203
|
+
function publicBenchmarkRlmInstructions(dataset) {
|
|
2204
|
+
const outputContract = dataset === "agentrx" ? AGENT_RX_RLM_CONTRACT : CODE_TRACE_RLM_CONTRACT;
|
|
2205
|
+
return `${publicBenchmarkTaskPrompt(dataset)}
|
|
2206
|
+
${outputContract}`;
|
|
2207
|
+
}
|
|
2208
|
+
function publicBenchmarkTaskPrompt(dataset) {
|
|
2209
|
+
return dataset === "agentrx" ? AGENT_RX_PROMPT : CODE_TRACE_BENCH_ANALYST_PROMPT;
|
|
2210
|
+
}
|
|
2211
|
+
/** Digest of every prompt a runner can send plus the shared transport limits.
|
|
2212
|
+
* Both runner contracts are hashed so an edit to either one changes the digest
|
|
2213
|
+
* a run records, whichever runner executed. */
|
|
2214
|
+
function publicBenchmarkProtocolSha256(dataset) {
|
|
2215
|
+
return sha256Digest(JSON.stringify({
|
|
2216
|
+
dataset,
|
|
2217
|
+
systemPrompt: publicBenchmarkSystemPrompt(dataset),
|
|
2218
|
+
rlmInstructions: publicBenchmarkRlmInstructions(dataset),
|
|
2219
|
+
transport: {
|
|
2220
|
+
attempts: 1,
|
|
2221
|
+
jsonMode: true,
|
|
2222
|
+
thinking: "disabled"
|
|
2223
|
+
},
|
|
2224
|
+
blockLimits: dataset === "agentrx" ? null : {
|
|
2225
|
+
maxBlocks: 16,
|
|
2226
|
+
maxBlockSteps: 12
|
|
2227
|
+
},
|
|
2228
|
+
traceProjectionAttributeByteCaps: TRACE_PROJECTION_ATTRIBUTE_BYTE_CAPS,
|
|
2229
|
+
evidence: {
|
|
2230
|
+
location: "model-selected-positive-integer-assistant-step",
|
|
2231
|
+
uri: "deterministic-trace-uri",
|
|
2232
|
+
excerpt: `exact-action-prefix-512`
|
|
2233
|
+
}
|
|
2234
|
+
}));
|
|
2235
|
+
}
|
|
2236
|
+
//#endregion
|
|
2237
|
+
//#region src/analyst/benchmark-public-adapters.ts
|
|
2238
|
+
function emptyPublicBenchmarkRunner() {
|
|
2239
|
+
return {
|
|
2240
|
+
id: "empty",
|
|
2241
|
+
analyze() {
|
|
2242
|
+
return {
|
|
2243
|
+
findings: [],
|
|
2244
|
+
usage: {
|
|
2245
|
+
calls: 0,
|
|
2246
|
+
tokens: {
|
|
2247
|
+
input: 0,
|
|
2248
|
+
output: 0
|
|
2249
|
+
},
|
|
2250
|
+
cost: {
|
|
2251
|
+
kind: "observed",
|
|
2252
|
+
usd: 0
|
|
2253
|
+
}
|
|
2254
|
+
},
|
|
2255
|
+
metadata: { baseline: "emit-no-findings" }
|
|
2256
|
+
};
|
|
2257
|
+
}
|
|
2258
|
+
};
|
|
2259
|
+
}
|
|
2260
|
+
async function adaptPublicBenchmarkFindings(options) {
|
|
2261
|
+
if (options.dataset === "agentrx") return {
|
|
2262
|
+
findings: adaptAgentRxFindings(options.trajectoryId, options.findings, options.analystId),
|
|
2263
|
+
diagnostics: void 0
|
|
2264
|
+
};
|
|
2265
|
+
return adaptCodeTraceFindings(options.trajectoryId, options.findings, options.analystId, options.store, options.signal);
|
|
2266
|
+
}
|
|
2267
|
+
function adaptAgentRxFindings(trajectoryId, findings, analystId) {
|
|
2268
|
+
if (findings.length === 0) return [];
|
|
2269
|
+
if (findings.length !== 1) throw new Error(`AgentRx model analyst must emit zero or one root cause, received ${findings.length}`);
|
|
2270
|
+
const source = findings[0];
|
|
2271
|
+
if (!source.subject) throw new Error("AgentRx model analyst finding is missing its failure-category subject");
|
|
2272
|
+
const steps = exactFindingSteps(trajectoryId, source);
|
|
2273
|
+
if (steps.length !== 1) throw new Error(`AgentRx model analyst must cite exactly one root-cause step, received ${steps.length}`);
|
|
2274
|
+
const [adapted] = agentRxPredictionsToFindings(trajectoryId, [{
|
|
2275
|
+
failure_case: source.subject,
|
|
2276
|
+
step_number: steps[0],
|
|
2277
|
+
description: source.rationale ?? source.claim
|
|
2278
|
+
}], {
|
|
2279
|
+
analystId,
|
|
2280
|
+
producedAt: source.produced_at,
|
|
2281
|
+
confidence: source.confidence
|
|
2282
|
+
});
|
|
2283
|
+
if (!adapted) throw new Error("AgentRx output adapter produced no root-cause finding");
|
|
2284
|
+
return [{
|
|
2285
|
+
...adapted,
|
|
2286
|
+
metadata: {
|
|
2287
|
+
...adapted.metadata,
|
|
2288
|
+
sourceFindingId: source.finding_id
|
|
2289
|
+
}
|
|
2290
|
+
}];
|
|
2291
|
+
}
|
|
2292
|
+
const CODE_TRACE_BLOCK_SUBJECT = /^incorrect-steps-(\d+)-(\d+)-(escaped|unescaped)-consequence-(\d+)$/;
|
|
2293
|
+
async function adaptCodeTraceFindings(trajectoryId, findings, analystId, store, signal) {
|
|
2294
|
+
const clean = findings.filter((finding) => finding.subject === "clean");
|
|
2295
|
+
if (clean.length > 0) {
|
|
2296
|
+
if (findings.length !== 1) throw new Error("CodeTraceBench model analyst mixed a clean verdict with incorrect steps");
|
|
2297
|
+
exactFindingSteps(trajectoryId, clean[0]);
|
|
2298
|
+
return {
|
|
2299
|
+
findings: [],
|
|
2300
|
+
diagnostics: emptyCodeTraceBlockDiagnostics()
|
|
2301
|
+
};
|
|
2302
|
+
}
|
|
2303
|
+
await validateCodeTraceFindingEvidence({
|
|
2304
|
+
trajectoryId,
|
|
2305
|
+
findings,
|
|
2306
|
+
store,
|
|
2307
|
+
...signal ? { signal } : {}
|
|
2308
|
+
});
|
|
2309
|
+
return expandCodeTraceFailureBlocks({
|
|
2310
|
+
trajectoryId,
|
|
2311
|
+
blocks: findings.map((source) => codeTraceBlockFromFinding(trajectoryId, source)),
|
|
2312
|
+
store,
|
|
2313
|
+
analystId,
|
|
2314
|
+
...findings[0] ? { producedAt: findings[0].produced_at } : {},
|
|
2315
|
+
...signal ? { signal } : {}
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
function codeTraceBlockFromFinding(trajectoryId, source) {
|
|
2319
|
+
const parsed = CODE_TRACE_BLOCK_SUBJECT.exec(source.subject ?? "");
|
|
2320
|
+
if (!parsed) throw new Error(`CodeTraceBench model finding '${source.finding_id}' must set subject to incorrect-steps-<first>-<last>-<escaped|unescaped>-consequence-<step>, received '${source.subject ?? ""}'`);
|
|
2321
|
+
const firstStep = Number(parsed[1]);
|
|
2322
|
+
const lastStep = Number(parsed[2]);
|
|
2323
|
+
const consequenceStep = Number(parsed[4]);
|
|
2324
|
+
const cited = exactFindingSteps(trajectoryId, source);
|
|
2325
|
+
for (const step of cited) if (step < firstStep || step > lastStep) throw new Error(`CodeTraceBench model finding '${source.finding_id}' cites step ${step} outside its block ${firstStep}-${lastStep}`);
|
|
2326
|
+
return {
|
|
2327
|
+
firstStep,
|
|
2328
|
+
lastStep,
|
|
2329
|
+
consequenceStep,
|
|
2330
|
+
escapeStatus: parsed[3],
|
|
2331
|
+
severity: source.severity,
|
|
2332
|
+
claim: source.claim,
|
|
2333
|
+
confidence: source.confidence,
|
|
2334
|
+
...source.rationale === void 0 ? {} : { rationale: source.rationale },
|
|
2335
|
+
...source.recommended_action === void 0 ? {} : { recommendedAction: source.recommended_action },
|
|
2336
|
+
metadata: { sourceFindingId: source.finding_id }
|
|
2337
|
+
};
|
|
2338
|
+
}
|
|
2339
|
+
/**
|
|
2340
|
+
* Expand contiguous failure blocks into one scored finding per member step.
|
|
2341
|
+
*
|
|
2342
|
+
* The official scorer matches on area plus the exact step evidence URI, so
|
|
2343
|
+
* blocks never reach it: every runner reports blocks, and this function turns
|
|
2344
|
+
* them into the per-step findings the benchmark defines.
|
|
2345
|
+
*/
|
|
2346
|
+
async function expandCodeTraceFailureBlocks(options) {
|
|
2347
|
+
const diagnostics = emptyCodeTraceBlockDiagnostics();
|
|
2348
|
+
diagnostics.reportedBlocks = options.blocks.length;
|
|
2349
|
+
if (options.blocks.length === 0) return {
|
|
2350
|
+
findings: [],
|
|
2351
|
+
diagnostics
|
|
2352
|
+
};
|
|
2353
|
+
assertCodeTraceBlockShape(options.blocks);
|
|
2354
|
+
const boundarySteps = options.blocks.flatMap((block) => [block.firstStep, block.lastStep]);
|
|
2355
|
+
const derivedSteps = options.blocks.flatMap((block) => [block.consequenceStep, ...interiorSteps(block)]);
|
|
2356
|
+
const evidenceByStep = await resolveAssistantStepEvidence({
|
|
2357
|
+
trajectoryId: options.trajectoryId,
|
|
2358
|
+
steps: boundarySteps,
|
|
2359
|
+
optionalSteps: derivedSteps,
|
|
2360
|
+
store: options.store,
|
|
2361
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2362
|
+
});
|
|
2363
|
+
const byStep = /* @__PURE__ */ new Map();
|
|
2364
|
+
for (const block of options.blocks) {
|
|
2365
|
+
if (!evidenceByStep.has(block.consequenceStep)) {
|
|
2366
|
+
diagnostics.blocksWithoutConsequenceEvidence.push(block);
|
|
2367
|
+
continue;
|
|
2368
|
+
}
|
|
2369
|
+
if (block.escapeStatus === "escaped") diagnostics.escapedBlocks += 1;
|
|
2370
|
+
for (let step = block.firstStep; step <= block.lastStep; step += 1) {
|
|
2371
|
+
if (!evidenceByStep.has(step)) {
|
|
2372
|
+
diagnostics.unresolvedBlockInteriorSteps.push(step);
|
|
2373
|
+
continue;
|
|
2374
|
+
}
|
|
2375
|
+
if (byStep.has(step)) {
|
|
2376
|
+
diagnostics.overlappingBlockSteps.push(step);
|
|
2377
|
+
continue;
|
|
2378
|
+
}
|
|
2379
|
+
byStep.set(step, block);
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
return {
|
|
2383
|
+
findings: [...byStep].sort(([left], [right]) => left - right).map(([step, block]) => makeFinding({
|
|
2384
|
+
analyst_id: options.analystId,
|
|
2385
|
+
area: "incorrect",
|
|
2386
|
+
subject: `incorrect-step-${step}`,
|
|
2387
|
+
claim: `Step ${step} is incorrect. ${block.claim}`,
|
|
2388
|
+
rationale: block.rationale,
|
|
2389
|
+
severity: block.severity,
|
|
2390
|
+
confidence: block.confidence,
|
|
2391
|
+
evidence_refs: [evidenceByStep.get(step)],
|
|
2392
|
+
recommended_action: block.recommendedAction,
|
|
2393
|
+
metadata: {
|
|
2394
|
+
...block.metadata,
|
|
2395
|
+
block_first_step: block.firstStep,
|
|
2396
|
+
block_last_step: block.lastStep,
|
|
2397
|
+
block_consequence_step: block.consequenceStep,
|
|
2398
|
+
escape_status: block.escapeStatus
|
|
2399
|
+
},
|
|
2400
|
+
...options.producedAt === void 0 ? {} : { produced_at: options.producedAt },
|
|
2401
|
+
id_basis: `incorrect-step-${step}`
|
|
2402
|
+
})),
|
|
2403
|
+
diagnostics
|
|
2404
|
+
};
|
|
2405
|
+
}
|
|
2406
|
+
function assertCodeTraceBlockShape(blocks) {
|
|
2407
|
+
if (blocks.length > 16) throw new Error(`model reported ${blocks.length} failure blocks; the maximum is 16`);
|
|
2408
|
+
for (const block of blocks) {
|
|
2409
|
+
if (block.lastStep < block.firstStep) throw new Error(`failure block last_step ${block.lastStep} precedes first_step ${block.firstStep}`);
|
|
2410
|
+
const length = block.lastStep - block.firstStep + 1;
|
|
2411
|
+
if (length > 12) throw new Error(`failure block spans ${length} steps; the maximum is 12`);
|
|
2412
|
+
if (block.consequenceStep < block.firstStep) throw new Error(`failure block consequence_step ${block.consequenceStep} precedes first_step ${block.firstStep}`);
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
function interiorSteps(block) {
|
|
2416
|
+
const steps = [];
|
|
2417
|
+
for (let step = block.firstStep + 1; step < block.lastStep; step += 1) steps.push(step);
|
|
2418
|
+
return steps;
|
|
2419
|
+
}
|
|
2420
|
+
function emptyCodeTraceBlockDiagnostics() {
|
|
2421
|
+
return {
|
|
2422
|
+
reportedBlocks: 0,
|
|
2423
|
+
escapedBlocks: 0,
|
|
2424
|
+
blocksWithoutConsequenceEvidence: [],
|
|
2425
|
+
unresolvedBlockInteriorSteps: [],
|
|
2426
|
+
overlappingBlockSteps: []
|
|
2427
|
+
};
|
|
2428
|
+
}
|
|
2429
|
+
function exactFindingSteps(trajectoryId, finding) {
|
|
2430
|
+
if (finding.evidence_refs.length === 0) throw new Error(`model finding '${finding.finding_id}' has no step evidence`);
|
|
2431
|
+
const steps = finding.evidence_refs.map((evidence) => {
|
|
2432
|
+
const parsed = codeTraceStepFromEvidence(evidence.uri);
|
|
2433
|
+
if (!parsed || parsed.traceId !== trajectoryId) throw new Error(`model finding '${finding.finding_id}' cites non-case evidence '${evidence.uri}'`);
|
|
2434
|
+
return parsed.step;
|
|
2435
|
+
});
|
|
2436
|
+
return [...new Set(steps)];
|
|
2437
|
+
}
|
|
2438
|
+
//#endregion
|
|
2439
|
+
//#region src/analyst/benchmark-public-types.ts
|
|
2440
|
+
function requiredString(value, field) {
|
|
2441
|
+
const trimmed = value.trim();
|
|
2442
|
+
if (!trimmed) throw new TypeError(`${field} must be a non-empty string`);
|
|
2443
|
+
return trimmed;
|
|
2444
|
+
}
|
|
2445
|
+
function positiveSafeInteger(value, field) {
|
|
2446
|
+
if (!Number.isSafeInteger(value) || value < 1) throw new RangeError(`${field} must be a positive safe integer`);
|
|
2447
|
+
return value;
|
|
2448
|
+
}
|
|
2449
|
+
function safeInteger(value, field) {
|
|
2450
|
+
if (!Number.isSafeInteger(value)) throw new RangeError(`${field} must be a safe integer`);
|
|
2451
|
+
return value;
|
|
2452
|
+
}
|
|
2453
|
+
function isRecord(value) {
|
|
2454
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2455
|
+
}
|
|
2456
|
+
//#endregion
|
|
2160
2457
|
//#region src/analyst/benchmark-public-data.ts
|
|
2161
2458
|
const DEFAULT_MAX_PUBLIC_BENCHMARK_LABEL_BYTES = 256 * 1024 * 1024;
|
|
2162
2459
|
const INPUT_OPEN_FLAGS = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0);
|
|
@@ -2655,15 +2952,6 @@ function fileContext() {
|
|
|
2655
2952
|
}
|
|
2656
2953
|
//#endregion
|
|
2657
2954
|
//#region src/analyst/benchmark-public-model.ts
|
|
2658
|
-
const TRACE_PROJECTION_ATTRIBUTE_BYTE_CAPS = [
|
|
2659
|
-
4096,
|
|
2660
|
-
2048,
|
|
2661
|
-
1024,
|
|
2662
|
-
512,
|
|
2663
|
-
256,
|
|
2664
|
-
128,
|
|
2665
|
-
64
|
|
2666
|
-
];
|
|
2667
2955
|
/** One-shot JSON baseline. This is not a recursive trace analyst. */
|
|
2668
2956
|
function createPublicBenchmarkDirectRunner(dataset, config) {
|
|
2669
2957
|
const model = requiredString(config.model, "model");
|
|
@@ -2677,7 +2965,7 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
|
|
|
2677
2965
|
responseCacheDir: requiredString(config.durability.responseCacheDir, "durability.responseCacheDir")
|
|
2678
2966
|
} : void 0;
|
|
2679
2967
|
const actor = dataset === "agentrx" ? "agentrx-root-cause-localizer" : "codetracebench-step-localizer";
|
|
2680
|
-
const outputAdapter = dataset === "agentrx" ? "agentrx-taxonomy-and-root-step" : "codetracebench-incorrect-
|
|
2968
|
+
const outputAdapter = dataset === "agentrx" ? "agentrx-taxonomy-and-root-step" : "codetracebench-incorrect-block";
|
|
2681
2969
|
const llmOptions = {
|
|
2682
2970
|
baseUrl,
|
|
2683
2971
|
apiKey,
|
|
@@ -2697,6 +2985,7 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
|
|
|
2697
2985
|
benchmarkRepetition: String(context.repetition)
|
|
2698
2986
|
};
|
|
2699
2987
|
let rawPredictions = [];
|
|
2988
|
+
let rejectedBlocks = [];
|
|
2700
2989
|
let modelFindings = [];
|
|
2701
2990
|
let providerModel = model;
|
|
2702
2991
|
let producedAt;
|
|
@@ -2748,6 +3037,7 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
|
|
|
2748
3037
|
};
|
|
2749
3038
|
const response = parsePublicBenchmarkModelResponse(dataset, cached.response);
|
|
2750
3039
|
rawPredictions = response.findings;
|
|
3040
|
+
rejectedBlocks = response.rejectedBlocks;
|
|
2751
3041
|
providerModel = cached.metadata.providerModel;
|
|
2752
3042
|
producedAt = cached.metadata.producedAt;
|
|
2753
3043
|
modelMetadata = {
|
|
@@ -2784,7 +3074,7 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
|
|
|
2784
3074
|
...cacheIdentity,
|
|
2785
3075
|
callId: providerCallId,
|
|
2786
3076
|
status: "succeeded",
|
|
2787
|
-
response,
|
|
3077
|
+
response: completed.value,
|
|
2788
3078
|
metadata: {
|
|
2789
3079
|
providerModel: completed.result.model,
|
|
2790
3080
|
providerDurationMs: completed.result.durationMs,
|
|
@@ -2816,6 +3106,7 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
|
|
|
2816
3106
|
if (!paid.succeeded) throw paid.error;
|
|
2817
3107
|
const response = paid.value.response;
|
|
2818
3108
|
rawPredictions = response.findings;
|
|
3109
|
+
rejectedBlocks = response.rejectedBlocks;
|
|
2819
3110
|
providerModel = paid.value.result.model;
|
|
2820
3111
|
producedAt = paid.value.producedAt;
|
|
2821
3112
|
modelMetadata = {
|
|
@@ -2828,7 +3119,7 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
|
|
|
2828
3119
|
cost: costReceiptMetadata(paid.receipt)
|
|
2829
3120
|
};
|
|
2830
3121
|
}
|
|
2831
|
-
|
|
3122
|
+
const converted = await publicBenchmarkPredictionsToFindings({
|
|
2832
3123
|
dataset,
|
|
2833
3124
|
trajectoryId,
|
|
2834
3125
|
predictions: rawPredictions,
|
|
@@ -2838,6 +3129,14 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
|
|
|
2838
3129
|
producedAt: requiredString(producedAt ?? "", "finding producedAt"),
|
|
2839
3130
|
...context.signal ? { signal: context.signal } : {}
|
|
2840
3131
|
});
|
|
3132
|
+
modelFindings = converted.findings;
|
|
3133
|
+
if (converted.diagnostics) modelMetadata = {
|
|
3134
|
+
...modelMetadata,
|
|
3135
|
+
blockDiagnostics: {
|
|
3136
|
+
...converted.diagnostics,
|
|
3137
|
+
rejectedBlocks
|
|
3138
|
+
}
|
|
3139
|
+
};
|
|
2841
3140
|
if (dataset === "codetracebench") await validateCodeTraceFindingEvidence({
|
|
2842
3141
|
trajectoryId,
|
|
2843
3142
|
findings: modelFindings,
|
|
@@ -2935,7 +3234,7 @@ const ModelSeveritySchema = z.enum([
|
|
|
2935
3234
|
"low",
|
|
2936
3235
|
"info"
|
|
2937
3236
|
]);
|
|
2938
|
-
const
|
|
3237
|
+
const AgentRxPredictionSchema = z.object({
|
|
2939
3238
|
step: z.number().int().positive(),
|
|
2940
3239
|
severity: ModelSeveritySchema,
|
|
2941
3240
|
claim: z.string().min(1),
|
|
@@ -2943,6 +3242,34 @@ const PublicBenchmarkPredictionSchema = z.object({
|
|
|
2943
3242
|
rationale: z.string().min(1).optional(),
|
|
2944
3243
|
recommended_action: z.string().min(1).optional()
|
|
2945
3244
|
}).strict();
|
|
3245
|
+
const CodeTraceBlockPredictionSchema = z.object({
|
|
3246
|
+
first_step: z.number().int().positive(),
|
|
3247
|
+
last_step: z.number().int().positive(),
|
|
3248
|
+
consequence_step: z.number().int().positive(),
|
|
3249
|
+
escape_status: z.enum(["escaped", "unescaped"]),
|
|
3250
|
+
severity: ModelSeveritySchema,
|
|
3251
|
+
claim: z.string().min(1),
|
|
3252
|
+
confidence: z.number().min(0).max(1),
|
|
3253
|
+
rationale: z.string().min(1).optional(),
|
|
3254
|
+
recommended_action: z.string().min(1).optional()
|
|
3255
|
+
}).strict().superRefine((block, ctx) => {
|
|
3256
|
+
if (block.last_step < block.first_step) {
|
|
3257
|
+
ctx.addIssue({
|
|
3258
|
+
code: z.ZodIssueCode.custom,
|
|
3259
|
+
message: `failure block last_step ${block.last_step} precedes first_step ${block.first_step}`
|
|
3260
|
+
});
|
|
3261
|
+
return;
|
|
3262
|
+
}
|
|
3263
|
+
const length = block.last_step - block.first_step + 1;
|
|
3264
|
+
if (length > 12) ctx.addIssue({
|
|
3265
|
+
code: z.ZodIssueCode.custom,
|
|
3266
|
+
message: `failure block spans ${length} steps; the maximum is 12`
|
|
3267
|
+
});
|
|
3268
|
+
if (block.consequence_step < block.first_step) ctx.addIssue({
|
|
3269
|
+
code: z.ZodIssueCode.custom,
|
|
3270
|
+
message: `failure block consequence_step ${block.consequence_step} precedes first_step ${block.first_step}`
|
|
3271
|
+
});
|
|
3272
|
+
});
|
|
2946
3273
|
const AgentRxCategorySchema = z.enum([
|
|
2947
3274
|
"instruction-plan-adherence-failure",
|
|
2948
3275
|
"invention-of-new-information",
|
|
@@ -2955,28 +3282,52 @@ const AgentRxCategorySchema = z.enum([
|
|
|
2955
3282
|
"system-failure",
|
|
2956
3283
|
"inconclusive"
|
|
2957
3284
|
]);
|
|
2958
|
-
const
|
|
3285
|
+
const CodeTraceModelResponseEnvelopeSchema = z.object({
|
|
2959
3286
|
report: z.string().min(1).max(4e3),
|
|
2960
|
-
findings: z.array(
|
|
3287
|
+
findings: z.array(z.unknown()).max(16)
|
|
2961
3288
|
}).strict();
|
|
2962
3289
|
const AgentRxModelResponseSchema = z.object({
|
|
2963
3290
|
report: z.string().min(1).max(4e3),
|
|
2964
|
-
findings: z.array(
|
|
3291
|
+
findings: z.array(AgentRxPredictionSchema.extend({ category: AgentRxCategorySchema }).strict()).max(1)
|
|
2965
3292
|
}).strict();
|
|
2966
3293
|
function parsePublicBenchmarkModelResponse(dataset, value) {
|
|
2967
|
-
|
|
3294
|
+
if (dataset === "agentrx") return {
|
|
3295
|
+
...AgentRxModelResponseSchema.parse(value),
|
|
3296
|
+
rejectedBlocks: []
|
|
3297
|
+
};
|
|
3298
|
+
const envelope = CodeTraceModelResponseEnvelopeSchema.parse(value);
|
|
3299
|
+
const findings = [];
|
|
3300
|
+
const rejectedBlocks = [];
|
|
3301
|
+
for (const [index, block] of envelope.findings.entries()) {
|
|
3302
|
+
const parsed = CodeTraceBlockPredictionSchema.safeParse(block);
|
|
3303
|
+
if (parsed.success) {
|
|
3304
|
+
findings.push(parsed.data);
|
|
3305
|
+
continue;
|
|
3306
|
+
}
|
|
3307
|
+
rejectedBlocks.push(`block ${index}: ${parsed.error.issues.map((issue) => `${issue.path.join(".") || "<root>"} ${issue.message}`).join("; ")}`);
|
|
3308
|
+
}
|
|
3309
|
+
if (findings.length === 0 && envelope.findings.length > 0) throw new ValidationError(`every reported failure block was malformed: ${rejectedBlocks.join(" | ")}`);
|
|
3310
|
+
return {
|
|
3311
|
+
report: envelope.report,
|
|
3312
|
+
findings,
|
|
3313
|
+
rejectedBlocks
|
|
3314
|
+
};
|
|
2968
3315
|
}
|
|
2969
3316
|
async function publicBenchmarkPredictionsToFindings(options) {
|
|
2970
|
-
if (options.predictions.length === 0) return
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
store: options.store,
|
|
2975
|
-
...options.signal ? { signal: options.signal } : {}
|
|
2976
|
-
});
|
|
3317
|
+
if (options.predictions.length === 0 && options.dataset === "agentrx") return {
|
|
3318
|
+
findings: [],
|
|
3319
|
+
diagnostics: void 0
|
|
3320
|
+
};
|
|
2977
3321
|
if (options.dataset === "agentrx") {
|
|
2978
3322
|
const prediction = options.predictions[0];
|
|
3323
|
+
if (!("step" in prediction)) throw new Error("AgentRx model output must name a single root-cause step");
|
|
2979
3324
|
if (!prediction.category) throw new Error("AgentRx model output is missing its failure category");
|
|
3325
|
+
const evidenceByStep = await resolveAssistantStepEvidence({
|
|
3326
|
+
trajectoryId: options.trajectoryId,
|
|
3327
|
+
steps: [prediction.step],
|
|
3328
|
+
store: options.store,
|
|
3329
|
+
...options.signal ? { signal: options.signal } : {}
|
|
3330
|
+
});
|
|
2980
3331
|
const [finding] = agentRxPredictionsToFindings(options.trajectoryId, [{
|
|
2981
3332
|
failure_case: prediction.category,
|
|
2982
3333
|
step_number: prediction.step,
|
|
@@ -2987,69 +3338,44 @@ async function publicBenchmarkPredictionsToFindings(options) {
|
|
|
2987
3338
|
confidence: prediction.confidence
|
|
2988
3339
|
});
|
|
2989
3340
|
if (!finding) throw new Error("AgentRx output adapter produced no root-cause finding");
|
|
2990
|
-
return
|
|
2991
|
-
|
|
2992
|
-
|
|
3341
|
+
return {
|
|
3342
|
+
findings: [{
|
|
3343
|
+
...finding,
|
|
3344
|
+
evidence_refs: [evidenceByStep.get(prediction.step)],
|
|
3345
|
+
metadata: {
|
|
3346
|
+
...finding.metadata,
|
|
3347
|
+
model: options.providerModel
|
|
3348
|
+
}
|
|
3349
|
+
}],
|
|
3350
|
+
diagnostics: void 0
|
|
3351
|
+
};
|
|
3352
|
+
}
|
|
3353
|
+
const blocks = options.predictions.map((prediction) => {
|
|
3354
|
+
if (!("first_step" in prediction)) throw new Error("CodeTraceBench model output must report first_step/last_step failure blocks");
|
|
3355
|
+
return {
|
|
3356
|
+
firstStep: prediction.first_step,
|
|
3357
|
+
lastStep: prediction.last_step,
|
|
3358
|
+
consequenceStep: prediction.consequence_step,
|
|
3359
|
+
escapeStatus: prediction.escape_status,
|
|
3360
|
+
severity: prediction.severity,
|
|
3361
|
+
claim: prediction.claim,
|
|
3362
|
+
confidence: prediction.confidence,
|
|
3363
|
+
...prediction.rationale === void 0 ? {} : { rationale: prediction.rationale },
|
|
3364
|
+
...prediction.recommended_action === void 0 ? {} : { recommendedAction: prediction.recommended_action },
|
|
2993
3365
|
metadata: {
|
|
2994
|
-
|
|
3366
|
+
analysis_mode: "direct-baseline",
|
|
2995
3367
|
model: options.providerModel
|
|
2996
3368
|
}
|
|
2997
|
-
}
|
|
2998
|
-
}
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
severity: prediction.severity,
|
|
3008
|
-
confidence: prediction.confidence,
|
|
3009
|
-
evidence_refs: [evidenceByStep.get(step)],
|
|
3010
|
-
recommended_action: prediction.recommended_action,
|
|
3011
|
-
metadata: {
|
|
3012
|
-
analysis_mode: "direct-baseline",
|
|
3013
|
-
model: options.providerModel
|
|
3014
|
-
},
|
|
3015
|
-
produced_at: options.producedAt,
|
|
3016
|
-
id_basis: `incorrect-step-${step}`
|
|
3017
|
-
}));
|
|
3018
|
-
}
|
|
3019
|
-
function publicBenchmarkSystemPrompt(dataset) {
|
|
3020
|
-
return `${dataset === "agentrx" ? AGENT_RX_PROMPT : CODE_TRACE_BENCH_ANALYST_PROMPT}
|
|
3021
|
-
|
|
3022
|
-
Each finding must contain only:
|
|
3023
|
-
- "step": a positive integer matching an existing assistant LLM span named step-<n>
|
|
3024
|
-
- "severity": "critical", "high", "medium", "low", or "info"
|
|
3025
|
-
- "claim": one sentence
|
|
3026
|
-
- "confidence": a number from 0 through 1
|
|
3027
|
-
- optional "rationale" and "recommended_action" strings
|
|
3028
|
-
${dataset === "agentrx" ? `- "category": one allowed failure category listed above` : ""}
|
|
3029
|
-
|
|
3030
|
-
Return exactly one JSON object with:
|
|
3031
|
-
- "report": a concise evidence-based explanation, at most 4000 characters
|
|
3032
|
-
- "findings": the strict finding array
|
|
3033
|
-
Use an empty findings array when the trace does not support a finding.
|
|
3034
|
-
Do not return a bare array, markdown, trace URIs, copied excerpts, or fields not listed above.
|
|
3035
|
-
The runner constructs exact trace URIs and action previews from each selected step.`;
|
|
3036
|
-
}
|
|
3037
|
-
function publicBenchmarkProtocolSha256(dataset) {
|
|
3038
|
-
return sha256Digest(JSON.stringify({
|
|
3039
|
-
dataset,
|
|
3040
|
-
systemPrompt: publicBenchmarkSystemPrompt(dataset),
|
|
3041
|
-
transport: {
|
|
3042
|
-
attempts: 1,
|
|
3043
|
-
jsonMode: true,
|
|
3044
|
-
thinking: "disabled"
|
|
3045
|
-
},
|
|
3046
|
-
traceProjectionAttributeByteCaps: TRACE_PROJECTION_ATTRIBUTE_BYTE_CAPS,
|
|
3047
|
-
evidence: {
|
|
3048
|
-
location: "model-selected-positive-integer-assistant-step",
|
|
3049
|
-
uri: "deterministic-trace-uri",
|
|
3050
|
-
excerpt: `exact-action-prefix-512`
|
|
3051
|
-
}
|
|
3052
|
-
}));
|
|
3369
|
+
};
|
|
3370
|
+
});
|
|
3371
|
+
return expandCodeTraceFailureBlocks({
|
|
3372
|
+
trajectoryId: options.trajectoryId,
|
|
3373
|
+
blocks,
|
|
3374
|
+
store: options.store,
|
|
3375
|
+
analystId: options.analystId,
|
|
3376
|
+
producedAt: options.producedAt,
|
|
3377
|
+
...options.signal ? { signal: options.signal } : {}
|
|
3378
|
+
});
|
|
3053
3379
|
}
|
|
3054
3380
|
async function prepareSingleTraceContext(store, context) {
|
|
3055
3381
|
const storeContext = context.signal ? { signal: context.signal } : void 0;
|
|
@@ -3069,40 +3395,6 @@ async function prepareSingleTraceContext(store, context) {
|
|
|
3069
3395
|
});
|
|
3070
3396
|
}
|
|
3071
3397
|
}
|
|
3072
|
-
const AGENT_RX_PROMPT = `Analyze exactly one failed agent trajectory.
|
|
3073
|
-
Find the first unrecoverable critical failure, not every later symptom.
|
|
3074
|
-
Inspect the complete supplied trace data.
|
|
3075
|
-
Emit zero findings only when the trace does not contain enough evidence.
|
|
3076
|
-
Otherwise emit exactly one finding.
|
|
3077
|
-
Its category MUST be exactly one of:
|
|
3078
|
-
instruction-plan-adherence-failure
|
|
3079
|
-
invention-of-new-information
|
|
3080
|
-
invalid-invocation
|
|
3081
|
-
misinterpretation-of-tool-output-handoff-failure
|
|
3082
|
-
intent-plan-misalignment
|
|
3083
|
-
underspecified-user-intent
|
|
3084
|
-
intent-not-supported
|
|
3085
|
-
guardrails-triggered
|
|
3086
|
-
system-failure
|
|
3087
|
-
inconclusive
|
|
3088
|
-
Its step is the positive integer n from the first unrecoverable assistant span named step-<n>.`;
|
|
3089
|
-
const CODE_TRACE_BENCH_ANALYST_PROMPT = `Analyze exactly one coding-agent trajectory and its attached final verification.
|
|
3090
|
-
Your task is the CodeTraceBench incorrect-step task: identify every wrong state-changing action, bad hypothesis that drives an action, and regression.
|
|
3091
|
-
An incorrect step remains incorrect when the agent later recovers or the final verification passes.
|
|
3092
|
-
Inspect the complete supplied trace data.
|
|
3093
|
-
Use the final-verification outcome as evidence about the final state, not as a rule for whether earlier steps were incorrect.
|
|
3094
|
-
For each candidate, inspect the assistant action and its following observation.
|
|
3095
|
-
Label a failed command when the assistant caused it through a wrong action or unsupported hypothesis.
|
|
3096
|
-
Label the later corrective action only when that action is itself wrong.
|
|
3097
|
-
Do not label a diagnostic probe merely because it exposes an earlier defect.
|
|
3098
|
-
Do not label a redundant but correct read or search; CodeTraceBench scores unuseful steps separately, and this run scores incorrect steps only.
|
|
3099
|
-
Do not label a step solely because final verification failed.
|
|
3100
|
-
When final verification is unavailable, use only directly observed trajectory evidence.
|
|
3101
|
-
Emit one finding per incorrect assistant step.
|
|
3102
|
-
Each finding's step MUST be the positive integer n from an existing assistant LLM span named step-<n>.
|
|
3103
|
-
Never select an EVALUATOR, TOOL, CHAIN, final-verification, benchmark-verification, or message-<n> span.
|
|
3104
|
-
Before emitting a finding, inspect its candidate span's attributes.content and describe only the action shown there.
|
|
3105
|
-
When the trajectory has no incorrect steps, return an empty findings array.`;
|
|
3106
3398
|
function trajectoryIdFromCaseId$1(dataset, caseId) {
|
|
3107
3399
|
const prefix = dataset === "agentrx" ? "agentrx:" : "codetrace:";
|
|
3108
3400
|
if (!caseId.startsWith(prefix) || caseId.length === prefix.length) throw new Error(`unexpected ${dataset} benchmark case id '${caseId}'`);
|
|
@@ -3110,34 +3402,6 @@ function trajectoryIdFromCaseId$1(dataset, caseId) {
|
|
|
3110
3402
|
}
|
|
3111
3403
|
//#endregion
|
|
3112
3404
|
//#region src/analyst/benchmark-public-rlm.ts
|
|
3113
|
-
const AGENT_RX_RLM_INSTRUCTIONS = `Analyze exactly one failed agent trajectory.
|
|
3114
|
-
Find the first unrecoverable critical failure, not every later symptom.
|
|
3115
|
-
Use the trace tools to inspect the action and its following observation.
|
|
3116
|
-
Emit zero findings only when evidence does not support a root cause.
|
|
3117
|
-
Otherwise emit exactly one finding whose subject is exactly one of:
|
|
3118
|
-
instruction-plan-adherence-failure
|
|
3119
|
-
invention-of-new-information
|
|
3120
|
-
invalid-invocation
|
|
3121
|
-
misinterpretation-of-tool-output-handoff-failure
|
|
3122
|
-
intent-plan-misalignment
|
|
3123
|
-
underspecified-user-intent
|
|
3124
|
-
intent-not-supported
|
|
3125
|
-
guardrails-triggered
|
|
3126
|
-
system-failure
|
|
3127
|
-
inconclusive
|
|
3128
|
-
Cite exactly one assistant span named step-<n> as trace://<trace-id>/span/step-<n>.
|
|
3129
|
-
The excerpt must quote the assistant action exactly.`;
|
|
3130
|
-
const CODE_TRACE_RLM_INSTRUCTIONS = `${CODE_TRACE_BENCH_ANALYST_PROMPT}
|
|
3131
|
-
Use the trace tools rather than asking for the whole trajectory in the prompt.
|
|
3132
|
-
Keep retrieved trace objects in Python variables.
|
|
3133
|
-
Never print an entire trace, full source file, or more than 12000 characters in one iteration.
|
|
3134
|
-
Build a compact table of assistant step ids, actions, following observations, and final verification.
|
|
3135
|
-
Inspect suspicious steps with viewSpans or searchSpan instead of repeatedly printing the table.
|
|
3136
|
-
Submit as soon as every state-changing assistant step has a supported verdict.
|
|
3137
|
-
For each incorrect step, set subject to incorrect-step-<n>.
|
|
3138
|
-
Cite the assistant span as trace://<URL-encoded-trace-id>/span/step-<n>.
|
|
3139
|
-
The evidence excerpt must be an exact quote from that span's action content.
|
|
3140
|
-
Return no finding for a clean trajectory.`;
|
|
3141
3405
|
/** Public benchmark candidate that runs the actual recursive trace analyst. */
|
|
3142
3406
|
function createPublicBenchmarkRlmRunner(dataset, config) {
|
|
3143
3407
|
const costLedger = config.costLedger ?? new CostLedger();
|
|
@@ -3205,20 +3469,22 @@ function createPublicBenchmarkRlmRunner(dataset, config) {
|
|
|
3205
3469
|
},
|
|
3206
3470
|
produced_at: producedAt
|
|
3207
3471
|
}));
|
|
3208
|
-
const
|
|
3209
|
-
|
|
3472
|
+
const adapted = await adaptPublicBenchmarkFindings({
|
|
3473
|
+
dataset,
|
|
3210
3474
|
trajectoryId,
|
|
3211
|
-
findings,
|
|
3475
|
+
findings: rawFindings,
|
|
3476
|
+
analystId: "dspy-rlm",
|
|
3212
3477
|
store: input.traceStore,
|
|
3213
3478
|
...context.signal ? { signal: context.signal } : {}
|
|
3214
3479
|
});
|
|
3215
3480
|
return {
|
|
3216
|
-
findings,
|
|
3481
|
+
findings: adapted.findings,
|
|
3217
3482
|
usage,
|
|
3218
3483
|
metadata: {
|
|
3219
3484
|
analysisMode: "recursive",
|
|
3220
3485
|
engine: "dspy-rlm",
|
|
3221
3486
|
protocolSha256: publicBenchmarkProtocolSha256(dataset),
|
|
3487
|
+
...adapted.diagnostics ? { blockDiagnostics: adapted.diagnostics } : {},
|
|
3222
3488
|
answer: completed.answer,
|
|
3223
3489
|
trajectory: completed.trajectory,
|
|
3224
3490
|
modelCalls: completed.modelCalls,
|
|
@@ -3250,7 +3516,7 @@ function publicBenchmarkDefinition(dataset, limits) {
|
|
|
3250
3516
|
area: dataset === "agentrx" ? "root-cause" : "incorrect",
|
|
3251
3517
|
version: "1.0.0",
|
|
3252
3518
|
question: dataset === "agentrx" ? "What is the first unrecoverable root cause in this failed trajectory?" : "Which assistant steps are incorrect under the CodeTraceBench definition?",
|
|
3253
|
-
instructions: dataset
|
|
3519
|
+
instructions: publicBenchmarkRlmInstructions(dataset),
|
|
3254
3520
|
toolGroup: "singleTrace",
|
|
3255
3521
|
limits
|
|
3256
3522
|
};
|
|
@@ -3341,7 +3607,7 @@ function createRunIdentity(config, prepared) {
|
|
|
3341
3607
|
analystProtocolSha256: publicBenchmarkProtocolSha256(config.dataset),
|
|
3342
3608
|
implementationSha256: ANALYST_BENCHMARK_IMPLEMENTATION_SHA256,
|
|
3343
3609
|
dependencyLockSha256: ANALYST_BENCHMARK_DEPENDENCY_LOCK_SHA256,
|
|
3344
|
-
runnerIds: ["empty",
|
|
3610
|
+
runnerIds: ["empty", config.analyst]
|
|
3345
3611
|
},
|
|
3346
3612
|
inputs: {
|
|
3347
3613
|
labelsSha256: prepared.labelsSha256,
|
|
@@ -3512,7 +3778,7 @@ function createObservationAppender(path, runIdentitySha256, progress) {
|
|
|
3512
3778
|
return write;
|
|
3513
3779
|
};
|
|
3514
3780
|
}
|
|
3515
|
-
async function readProgress(path, runIdentitySha256, caseIds, repetitions) {
|
|
3781
|
+
async function readProgress(path, runIdentitySha256, caseIds, repetitions, analystRunnerId) {
|
|
3516
3782
|
const rawLines = (await readRegularFile(path, "benchmark observation log")).split("\n");
|
|
3517
3783
|
if (rawLines.at(-1) === "") rawLines.pop();
|
|
3518
3784
|
const observations = [];
|
|
@@ -3546,7 +3812,7 @@ async function readProgress(path, runIdentitySha256, caseIds, repetitions) {
|
|
|
3546
3812
|
previousRowSha256: parsed.previousRowSha256,
|
|
3547
3813
|
observation
|
|
3548
3814
|
}) !== parsed.rowSha256) throw new Error(`benchmark observation row ${index + 1} digest does not match its contents`);
|
|
3549
|
-
if (!allowedCases.has(observation.caseId) || observation.runnerId !== "empty" && observation.runnerId !==
|
|
3815
|
+
if (!allowedCases.has(observation.caseId) || observation.runnerId !== "empty" && observation.runnerId !== analystRunnerId || observation.repetition >= repetitions || observation.executionIndex >= plannedObservationCount) throw new Error(`benchmark observation row ${index + 1} does not match a planned case, runner, and repetition`);
|
|
3550
3816
|
if (executionIndexes.has(observation.executionIndex)) throw new Error(`duplicate benchmark executionIndex ${observation.executionIndex} at line ${index + 1}`);
|
|
3551
3817
|
observations.push(observation);
|
|
3552
3818
|
seen.add(key);
|
|
@@ -3991,7 +4257,7 @@ function assertCompletedArtifactMatchesRun(artifact, manifest, observations, pre
|
|
|
3991
4257
|
if (canonicalJson(artifact.inputs) !== canonicalJson(expectedInputs)) throw new Error("completed benchmark result inputs do not match the run manifest");
|
|
3992
4258
|
const provenance = artifact.result.provenance;
|
|
3993
4259
|
const expectedDatasetId = config.dataset === "agentrx" ? "microsoft/AgentRx" : "NJU-LINK/CodeTraceBench";
|
|
3994
|
-
const expectedOutputAdapter = config.dataset === "agentrx" ? "agentrx-taxonomy-and-root-step" : "codetracebench-incorrect-
|
|
4260
|
+
const expectedOutputAdapter = config.dataset === "agentrx" ? "agentrx-taxonomy-and-root-step" : "codetracebench-incorrect-block";
|
|
3995
4261
|
if (provenance.id !== `${config.dataset}-real-model-analyst` || provenance.startedAt !== manifest.createdAt || !Number.isFinite(Date.parse(provenance.endedAt)) || Date.parse(provenance.endedAt) < Date.parse(provenance.startedAt) || canonicalJson(provenance.dataset) !== canonicalJson({
|
|
3996
4262
|
id: expectedDatasetId,
|
|
3997
4263
|
revision: config.datasetRevision,
|
|
@@ -4001,7 +4267,7 @@ function assertCompletedArtifactMatchesRun(artifact, manifest, observations, pre
|
|
|
4001
4267
|
if (canonicalJson(artifact.result.summaries) !== canonicalJson(expectedSummaries)) throw new Error("completed benchmark summaries do not match durable observations");
|
|
4002
4268
|
const expectedComparisons = [compareAnalystRunners(artifact.result, {
|
|
4003
4269
|
baselineRunnerId: "empty",
|
|
4004
|
-
candidateRunnerId:
|
|
4270
|
+
candidateRunnerId: config.runnerIds[1],
|
|
4005
4271
|
seed: config.seed
|
|
4006
4272
|
})];
|
|
4007
4273
|
if (canonicalJson(artifact.comparisons) !== canonicalJson(expectedComparisons)) throw new Error("completed benchmark comparisons do not match durable observations");
|
|
@@ -4134,7 +4400,7 @@ async function executeAnalystBenchmarkCommand(config, dependencies) {
|
|
|
4134
4400
|
const localIdentitySha256 = digestCanonical(localReceipt.local);
|
|
4135
4401
|
const identitySha256 = digestCanonical(identity);
|
|
4136
4402
|
const manifest = config.resume ? await readAndValidateResumeFiles(paths, identity, identitySha256, localIdentitySha256, localReceipt) : await initializeRunFiles(paths, identity, identitySha256, localIdentitySha256, localReceipt);
|
|
4137
|
-
const progress = await readProgress(paths.observations, manifest.identitySha256, prepared.selectedCaseIds, config.repetitions);
|
|
4403
|
+
const progress = await readProgress(paths.observations, manifest.identitySha256, prepared.selectedCaseIds, config.repetitions, config.analyst);
|
|
4138
4404
|
const costLedger = createRunCostLedger({
|
|
4139
4405
|
storage: fsCampaignStorage(),
|
|
4140
4406
|
runDir: paths.directory,
|
|
@@ -4147,10 +4413,10 @@ async function executeAnalystBenchmarkCommand(config, dependencies) {
|
|
|
4147
4413
|
const markdown = renderArtifactMarkdown(artifact);
|
|
4148
4414
|
await writeExclusiveOrVerify(paths.report, markdown);
|
|
4149
4415
|
printSuccessSummary(artifact, paths);
|
|
4150
|
-
return benchmarkExitCode(artifact.result);
|
|
4416
|
+
return benchmarkExitCode(artifact.result, config.analyst);
|
|
4151
4417
|
}
|
|
4152
4418
|
if (await regularFileExists(paths.report)) throw new Error(`benchmark report exists without a completed result; refusing ambiguous resume: ${paths.report}`);
|
|
4153
|
-
const createAnalystRunner = dependencies.createAnalystRunner ?? ((dataset, model) => createPublicBenchmarkRlmRunner(dataset, model));
|
|
4419
|
+
const createAnalystRunner = dependencies.createAnalystRunner ?? ((dataset, model) => config.analyst === "direct" ? createPublicBenchmarkDirectRunner(dataset, model) : createPublicBenchmarkRlmRunner(dataset, model));
|
|
4154
4420
|
const runners = [emptyPublicBenchmarkRunner(), createAnalystRunner(config.dataset, {
|
|
4155
4421
|
...config.model,
|
|
4156
4422
|
costLedger,
|
|
@@ -4172,7 +4438,7 @@ async function executeAnalystBenchmarkCommand(config, dependencies) {
|
|
|
4172
4438
|
initialObservations: progress.observations,
|
|
4173
4439
|
signal: runAbort.signal,
|
|
4174
4440
|
onObservation: async (observation) => {
|
|
4175
|
-
assertObservationAccountingComplete(observation, costLedger);
|
|
4441
|
+
assertObservationAccountingComplete(observation, costLedger, config.analyst);
|
|
4176
4442
|
await appendObservation(observation);
|
|
4177
4443
|
},
|
|
4178
4444
|
resolveEvidence: traceStoreEvidenceResolver((input) => {
|
|
@@ -4193,7 +4459,7 @@ async function executeAnalystBenchmarkCommand(config, dependencies) {
|
|
|
4193
4459
|
},
|
|
4194
4460
|
metadata: {
|
|
4195
4461
|
model: config.model.model,
|
|
4196
|
-
outputAdapter: config.dataset === "agentrx" ? "agentrx-taxonomy-and-root-step" : "codetracebench-incorrect-
|
|
4462
|
+
outputAdapter: config.dataset === "agentrx" ? "agentrx-taxonomy-and-root-step" : "codetracebench-incorrect-block",
|
|
4197
4463
|
caseSelection: prepared.selection.method,
|
|
4198
4464
|
caseSelectionSeed: config.seed,
|
|
4199
4465
|
selectionStratified: prepared.selection.stratified,
|
|
@@ -4211,11 +4477,11 @@ async function executeAnalystBenchmarkCommand(config, dependencies) {
|
|
|
4211
4477
|
}
|
|
4212
4478
|
assertCostLedgerFinalizable(costLedger);
|
|
4213
4479
|
result.provenance.startedAt = manifest.createdAt;
|
|
4214
|
-
const persisted = await readProgress(paths.observations, manifest.identitySha256, prepared.selectedCaseIds, config.repetitions);
|
|
4480
|
+
const persisted = await readProgress(paths.observations, manifest.identitySha256, prepared.selectedCaseIds, config.repetitions, config.analyst);
|
|
4215
4481
|
assertSameObservations(result.observations, persisted.observations);
|
|
4216
4482
|
const comparisons = [compareAnalystRunners(result, {
|
|
4217
4483
|
baselineRunnerId: "empty",
|
|
4218
|
-
candidateRunnerId:
|
|
4484
|
+
candidateRunnerId: config.analyst,
|
|
4219
4485
|
seed: config.seed
|
|
4220
4486
|
})];
|
|
4221
4487
|
const codeTraceCalibration = config.dataset === "codetracebench" ? summarizeCodeTraceCalibration(result) : void 0;
|
|
@@ -4260,7 +4526,7 @@ async function executeAnalystBenchmarkCommand(config, dependencies) {
|
|
|
4260
4526
|
await writeExclusiveOrVerify(paths.result, `${JSON.stringify(artifact, null, 2)}\n`);
|
|
4261
4527
|
await writeExclusiveOrVerify(paths.report, markdown);
|
|
4262
4528
|
printSuccessSummary(artifact, paths);
|
|
4263
|
-
return benchmarkExitCode(result);
|
|
4529
|
+
return benchmarkExitCode(result, config.analyst);
|
|
4264
4530
|
}
|
|
4265
4531
|
const NON_SCORABLE_COST_ERRORS = /* @__PURE__ */ new Set([
|
|
4266
4532
|
"CostAccountingIncompleteError",
|
|
@@ -4270,9 +4536,9 @@ const NON_SCORABLE_COST_ERRORS = /* @__PURE__ */ new Set([
|
|
|
4270
4536
|
"CostReceiptCaptureError",
|
|
4271
4537
|
"CostReservationExceededError"
|
|
4272
4538
|
]);
|
|
4273
|
-
function assertObservationAccountingComplete(observation, costLedger) {
|
|
4539
|
+
function assertObservationAccountingComplete(observation, costLedger, analystRunnerId) {
|
|
4274
4540
|
if (observation.error && NON_SCORABLE_COST_ERRORS.has(observation.error.class)) throw new CostAccountingIncompleteError(`Analyst benchmark stopped before scoring: ${observation.error.message}`);
|
|
4275
|
-
if (observation.runnerId !==
|
|
4541
|
+
if (observation.runnerId !== analystRunnerId) return;
|
|
4276
4542
|
const summary = costLedger.summary({
|
|
4277
4543
|
channel: "analyst",
|
|
4278
4544
|
tags: {
|
|
@@ -4302,6 +4568,9 @@ Run the recursive DSPy trace analyst against public AgentRx or CodeTraceBench la
|
|
|
4302
4568
|
|
|
4303
4569
|
Required:
|
|
4304
4570
|
--dataset agentrx|codetracebench
|
|
4571
|
+
--analyst dspy-rlm|direct Scored analyst. Default: dspy-rlm.
|
|
4572
|
+
'direct' is the retired one-shot runner that
|
|
4573
|
+
produced the published evidence.
|
|
4305
4574
|
--labels <dataset.json|dataset.jsonl>
|
|
4306
4575
|
--trace-dir <one-trace-per-file OTLP JSONL directory>
|
|
4307
4576
|
--artifact-dir <extracted artifact root> Required for CodeTraceBench
|
|
@@ -4344,8 +4613,11 @@ function parseCommandConfig(argv, env) {
|
|
|
4344
4613
|
if (!apiKey) throw new Error(`--api-key-env points to an empty or missing variable: ${apiKeyEnv}`);
|
|
4345
4614
|
const maxCostUsd = positiveFiniteFlag(flags, "max-cost-usd", 5);
|
|
4346
4615
|
const python = flags.get("python")?.trim();
|
|
4616
|
+
const analyst = flags.get("analyst")?.trim() ?? "dspy-rlm";
|
|
4617
|
+
if (analyst !== "dspy-rlm" && analyst !== "direct") throw new Error("--analyst must be 'dspy-rlm' or 'direct'");
|
|
4347
4618
|
return {
|
|
4348
4619
|
dataset,
|
|
4620
|
+
analyst,
|
|
4349
4621
|
labelsPath: requiredFlag(flags, "labels"),
|
|
4350
4622
|
traceDir: requiredFlag(flags, "trace-dir"),
|
|
4351
4623
|
...artifactDir ? { artifactDir } : {},
|
|
@@ -4396,6 +4668,7 @@ function parseFlags(argv) {
|
|
|
4396
4668
|
const KNOWN_FLAGS = /* @__PURE__ */ new Set([
|
|
4397
4669
|
"resume",
|
|
4398
4670
|
"dataset",
|
|
4671
|
+
"analyst",
|
|
4399
4672
|
"labels",
|
|
4400
4673
|
"trace-dir",
|
|
4401
4674
|
"artifact-dir",
|
|
@@ -4519,8 +4792,8 @@ function renderArtifactMarkdown(artifact) {
|
|
|
4519
4792
|
const verificationMarkdown = artifact.inputs.dataset === "codetracebench" ? `\n\n${renderVerificationAvailability(artifact.inputs.verificationAvailability)}` : "";
|
|
4520
4793
|
return `${renderAnalystBenchmarkMarkdown(artifact.result, artifact.comparisons).trimEnd()}${calibrationMarkdown}${verificationMarkdown}\n\n${renderSelectionMarkdown(artifact.inputs.selection.report)}\n`;
|
|
4521
4794
|
}
|
|
4522
|
-
function benchmarkExitCode(result) {
|
|
4523
|
-
return result.summaries.find((summary) => summary.runnerId ===
|
|
4795
|
+
function benchmarkExitCode(result, analystRunnerId) {
|
|
4796
|
+
return result.summaries.find((summary) => summary.runnerId === analystRunnerId)?.failedRuns ? 2 : 0;
|
|
4524
4797
|
}
|
|
4525
4798
|
function printSuccessSummary(artifact, paths) {
|
|
4526
4799
|
const failures = artifact.result.summaries.reduce((total, summary) => total + summary.failedRuns, 0);
|
|
@@ -4532,6 +4805,6 @@ function shellQuote(value) {
|
|
|
4532
4805
|
return /^[a-zA-Z0-9_./:@%+=,-]+$/.test(value) ? value : `'${value.replaceAll("'", "'\\''")}'`;
|
|
4533
4806
|
}
|
|
4534
4807
|
//#endregion
|
|
4535
|
-
export {
|
|
4808
|
+
export { ANALYST_BENCHMARK_DEPENDENCY_LOCK_SHA256 as A, ANALYST_BENCHMARK_LOCAL_RECEIPT_FILE as B, publicBenchmarkSystemPrompt as C, parseVerificationOutcome as D, loadCodeTraceVerificationArtifacts as E, ANALYST_BENCHMARK_IMPLEMENTATION_FILES as F, summarizeAgentRxCalibration as G, ANALYST_BENCHMARK_OBSERVATIONS_FILE as H, ANALYST_BENCHMARK_IMPLEMENTATION_SHA256 as I, agentRxBenchmarkCase as J, codeTraceBenchCase as K, analystBenchmarkDependencyLockDigest as L, ANALYST_BENCHMARK_EVIDENCE_IMPLEMENTATION_SHA256 as M, ANALYST_BENCHMARK_EVIDENCE_PACKAGE_VERSION as N, ANALYST_BENCHMARK_DEPENDENCY_LOCK_DIGEST_ALGORITHM as O, ANALYST_BENCHMARK_IMPLEMENTATION_DIGEST_ALGORITHM as P, normalizeBenchmarkLabel as Q, analystBenchmarkImplementationDigest as R, publicBenchmarkRlmInstructions as S, appendVerificationArtifactsToOtlp as T, AGENT_RX_UPSTREAM_REVISION as U, ANALYST_BENCHMARK_MANIFEST_FILE as V, renderAgentRxCalibrationMarkdown as W, normalizeAgentRxCategory as X, agentRxPredictionsToFindings as Y, roundAgentRxStep as Z, expandCodeTraceFailureBlocks as _, renderCodeTraceCalibrationMarkdown as a, MAX_INCORRECT_BLOCK_STEPS as b, createPublicBenchmarkRlmRunner as c, preparePublicAnalystBenchmark as d, publicBenchmarkDistributions as f, emptyPublicBenchmarkRunner as g, adaptPublicBenchmarkFindings as h, readAnalystBenchmarkArtifact as i, ANALYST_BENCHMARK_EVIDENCE_DEPENDENCY_LOCK_SHA256 as j, ANALYST_BENCHMARK_DEPENDENCY_LOCK_FILES as k, createPublicBenchmarkDirectRunner as l, selectPublicBenchmarkRows as m, runAnalystBenchmarkCommand as n, summarizeCodeTraceCalibration as o, publicBenchmarkSelectionReport as p, codeTracerPredictionsToFindings as q, renderAnalystBenchmarkMarkdown as r, compareAnalystRunners as s, ANALYST_BENCHMARK_HELP as t, loadPublicBenchmarkRows as u, CODE_TRACE_BENCH_ANALYST_PROMPT as v, DEFAULT_MAX_VERIFICATION_ARTIFACT_BYTES as w, publicBenchmarkProtocolSha256 as x, MAX_INCORRECT_BLOCKS as y, ANALYST_BENCHMARK_COST_LEDGER_FILE as z };
|
|
4536
4809
|
|
|
4537
|
-
//# sourceMappingURL=benchmark-command-
|
|
4810
|
+
//# sourceMappingURL=benchmark-command-xvi2liH7.js.map
|