@tangle-network/agent-eval 0.145.10 → 0.145.11
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 +9 -0
- package/dist/analyst/index.d.ts +1 -1
- package/dist/analyst/index.js +1 -1
- package/dist/{benchmark-command-BDHW2AUg.js → benchmark-command-D8K5YJNS.js} +2 -2
- package/dist/{benchmark-command-BDHW2AUg.js.map → benchmark-command-D8K5YJNS.js.map} +1 -1
- package/dist/cli.js +1 -1
- package/dist/exec-y-DCLqK7.js +204 -0
- package/dist/exec-y-DCLqK7.js.map +1 -0
- package/dist/openapi.json +1 -1
- package/dist/steps-AmkT-GIM.d.ts +216 -0
- package/dist/steps-AmkT-GIM.d.ts.map +1 -0
- package/dist/trace-repair/index.d.ts +1 -21
- package/dist/trace-repair/index.d.ts.map +1 -1
- package/dist/trace-repair/index.js +10 -19
- package/dist/trace-repair/index.js.map +1 -1
- package/dist/trajectory-replay/index.d.ts +2 -2
- package/dist/trajectory-replay/index.js +2 -2
- package/docs/trace-repair-admission.md +134 -0
- package/docs/trajectory-replay.md +21 -1
- package/package.json +3 -3
- package/dist/exec-BLtYZdWo.js +0 -49
- package/dist/exec-BLtYZdWo.js.map +0 -1
- package/dist/steps-BArUxhna.d.ts +0 -51
- package/dist/steps-BArUxhna.d.ts.map +0 -1
|
@@ -2,7 +2,7 @@ import { t as DefaultVerdict } from "../verdict-E4eRNf7-.js";
|
|
|
2
2
|
import { s as TraceStore } from "../store-CT9YIIve.js";
|
|
3
3
|
import { i as TraceEmitter } from "../emitter-DGQGoLyj.js";
|
|
4
4
|
import { i as CounterfactualRunner, t as CounterfactualContext } from "../counterfactual--bpysZF0.js";
|
|
5
|
-
import { a as
|
|
5
|
+
import { _ as isSubmitAction, a as RecordedObservationKind, b as parseRecordedReturncode, c as SUBMIT_ACTION_SIGNATURE, d as classifyObservation, f as decodeRecordedTurns, g as isRecordedTimeout, h as isElidedField, i as RecordedFinalOutcome, l as TIMEOUT_OBSERVATION_MARKER, m as finalRecordedOutcome, n as FORMAT_ERROR_OBSERVATION_PREFIX, o as RecordedTrajectoryStep, p as deriveFailureSignature, r as RECORDED_ELISION_PATTERN, s as RecordedTrajectoryTurn, t as DecodedTrajectory, u as assertReplayableTrajectory, v as isSubmitOnlyAction, x as unreadableExitCount, y as parseObservationOutput } from "../steps-AmkT-GIM.js";
|
|
6
6
|
//#region src/trajectory-replay/corpus.d.ts
|
|
7
7
|
interface CorpusSpec {
|
|
8
8
|
readonly name: string;
|
|
@@ -790,5 +790,5 @@ interface ReplayFindingResult {
|
|
|
790
790
|
*/
|
|
791
791
|
declare function replayVerifyFinding(finding: AnalystReplayFinding, options: ReplayFindingOptions): Promise<ReplayFindingResult>;
|
|
792
792
|
//#endregion
|
|
793
|
-
export { type AnalystReplayFinding, type ArmExecutionResult, type CaseResources, type ChatCompletionCaller, type ChatOutcome, type ChatUsage, type CorpusSpec, type CwdSource, type DockerImagePreparerOptions, type EnumerationResult, type ExcludedCase, type FailedFixAttempt, type FindingReplaySource, type FindingReplayability, type FindingVerification, type FindingVerificationStatus, type FixArmExecution, type FixArmExecutor, type FixGenerationOutcome, type FixLoopAttemptRecord, type FixLoopOptions, type FixLoopResult, type FixPromptInput, type ImagePreparation, type ImagePreparer, type IncorrectStepsSubject, type IngestedTrajectory, PREFIX_DIVERGENCE_TOLERANCE_PCT, type PrefixDivergence, type PrefixDivergenceKind, type PrefixReplayResult, type RecordedTrajectoryStep, type ReplayArmVerdict, type ReplayBatchCaseRow, type ReplayBatchFixResult, type ReplayBatchOptions, type ReplayBatchReport, type ReplayExclusionReason, type ReplayExecBackend, type ReplayExecBackendFactory, type ReplayExecResult, type ReplayExecSession, type ReplayFindingOptions, type ReplayFindingResult, type ReplayVerdict, type ReplayVerifyOptions, type ReplayableCase, type ResolvedFindingReplay, type ResolvedReplayInvocation, type ResourceResolution, SUBMIT_ACTION_SIGNATURE, SandboxCounterfactualRunner, type SandboxCounterfactualRunnerOptions, type VerifiableFinding, type VerifyFindingsOptions, type VerifyFindingsRun, buildFixPrompt, buildRetryFixPrompt, classifyPrefixStep, classifyVerdict, clipText, countScriptCommands, deriveFailureSignature, derivedImageTag, dockerImagePreparer, enumerateReplayableCases, extractFixCommand, findingReplayStep, findingTrajectoryId, generateFixCommand, goldIncorrectSteps, ingestRecordedTrajectory, isSubmitAction, parseCorpusFlag, parseIncorrectStepsSubject, parseObservationOutput, parseRecordedReturncode, readFindingsFile, readLabelEntries, renderBatchReport, renderVerifiedFindingsSection, replayVerify, replayVerifyFinding, resolveCaseResources, resolveFindingInvocation, resolveFindingReplayability, runFixLoop, runReplayBatch, seededSample, summarizePrefixReplay, verifyFindings, wrapActionForExec };
|
|
793
|
+
export { type AnalystReplayFinding, type ArmExecutionResult, type CaseResources, type ChatCompletionCaller, type ChatOutcome, type ChatUsage, type CorpusSpec, type CwdSource, type DecodedTrajectory, type DockerImagePreparerOptions, type EnumerationResult, type ExcludedCase, FORMAT_ERROR_OBSERVATION_PREFIX, type FailedFixAttempt, type FindingReplaySource, type FindingReplayability, type FindingVerification, type FindingVerificationStatus, type FixArmExecution, type FixArmExecutor, type FixGenerationOutcome, type FixLoopAttemptRecord, type FixLoopOptions, type FixLoopResult, type FixPromptInput, type ImagePreparation, type ImagePreparer, type IncorrectStepsSubject, type IngestedTrajectory, PREFIX_DIVERGENCE_TOLERANCE_PCT, type PrefixDivergence, type PrefixDivergenceKind, type PrefixReplayResult, RECORDED_ELISION_PATTERN, type RecordedFinalOutcome, type RecordedObservationKind, type RecordedTrajectoryStep, type RecordedTrajectoryTurn, type ReplayArmVerdict, type ReplayBatchCaseRow, type ReplayBatchFixResult, type ReplayBatchOptions, type ReplayBatchReport, type ReplayExclusionReason, type ReplayExecBackend, type ReplayExecBackendFactory, type ReplayExecResult, type ReplayExecSession, type ReplayFindingOptions, type ReplayFindingResult, type ReplayVerdict, type ReplayVerifyOptions, type ReplayableCase, type ResolvedFindingReplay, type ResolvedReplayInvocation, type ResourceResolution, SUBMIT_ACTION_SIGNATURE, SandboxCounterfactualRunner, type SandboxCounterfactualRunnerOptions, TIMEOUT_OBSERVATION_MARKER, type VerifiableFinding, type VerifyFindingsOptions, type VerifyFindingsRun, assertReplayableTrajectory, buildFixPrompt, buildRetryFixPrompt, classifyObservation, classifyPrefixStep, classifyVerdict, clipText, countScriptCommands, decodeRecordedTurns, deriveFailureSignature, derivedImageTag, dockerImagePreparer, enumerateReplayableCases, extractFixCommand, finalRecordedOutcome, findingReplayStep, findingTrajectoryId, generateFixCommand, goldIncorrectSteps, ingestRecordedTrajectory, isElidedField, isRecordedTimeout, isSubmitAction, isSubmitOnlyAction, parseCorpusFlag, parseIncorrectStepsSubject, parseObservationOutput, parseRecordedReturncode, readFindingsFile, readLabelEntries, renderBatchReport, renderVerifiedFindingsSection, replayVerify, replayVerifyFinding, resolveCaseResources, resolveFindingInvocation, resolveFindingReplayability, runFixLoop, runReplayBatch, seededSample, summarizePrefixReplay, unreadableExitCount, verifyFindings, wrapActionForExec };
|
|
794
794
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -3,7 +3,7 @@ import { t as TraceEmitter } from "../emitter-CPBAhxum.js";
|
|
|
3
3
|
import { t as runCounterfactual } from "../counterfactual-lDfCx0Uz.js";
|
|
4
4
|
import { n as InMemoryTraceStore } from "../store-DNe_Uv1Q.js";
|
|
5
5
|
import { t as packageVersion } from "../package-version-D7lQHt_-.js";
|
|
6
|
-
import { a as parseObservationOutput, i as
|
|
6
|
+
import { _ as unreadableExitCount, a as TIMEOUT_OBSERVATION_MARKER, c as decodeRecordedTurns, d as isElidedField, f as isRecordedTimeout, g as parseRecordedReturncode, h as parseObservationOutput, i as SUBMIT_ACTION_SIGNATURE, l as deriveFailureSignature, m as isSubmitOnlyAction, n as FORMAT_ERROR_OBSERVATION_PREFIX, o as assertReplayableTrajectory, p as isSubmitAction, r as RECORDED_ELISION_PATTERN, s as classifyObservation, t as wrapActionForExec, u as finalRecordedOutcome } from "../exec-y-DCLqK7.js";
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
8
8
|
import { appendFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { join } from "node:path";
|
|
@@ -2145,6 +2145,6 @@ function readFindingsFile(path) {
|
|
|
2145
2145
|
return array;
|
|
2146
2146
|
}
|
|
2147
2147
|
//#endregion
|
|
2148
|
-
export { PREFIX_DIVERGENCE_TOLERANCE_PCT, SUBMIT_ACTION_SIGNATURE, SandboxCounterfactualRunner, buildFixPrompt, buildRetryFixPrompt, classifyPrefixStep, classifyVerdict, clipText, countScriptCommands, deriveFailureSignature, derivedImageTag, dockerImagePreparer, enumerateReplayableCases, extractFixCommand, findingReplayStep, findingTrajectoryId, generateFixCommand, goldIncorrectSteps, ingestRecordedTrajectory, isSubmitAction, parseCorpusFlag, parseIncorrectStepsSubject, parseObservationOutput, parseRecordedReturncode, readFindingsFile, readLabelEntries, renderBatchReport, renderVerifiedFindingsSection, replayVerify, replayVerifyFinding, resolveCaseResources, resolveFindingInvocation, resolveFindingReplayability, runFixLoop, runReplayBatch, seededSample, summarizePrefixReplay, verifyFindings, wrapActionForExec };
|
|
2148
|
+
export { FORMAT_ERROR_OBSERVATION_PREFIX, PREFIX_DIVERGENCE_TOLERANCE_PCT, RECORDED_ELISION_PATTERN, SUBMIT_ACTION_SIGNATURE, SandboxCounterfactualRunner, TIMEOUT_OBSERVATION_MARKER, assertReplayableTrajectory, buildFixPrompt, buildRetryFixPrompt, classifyObservation, classifyPrefixStep, classifyVerdict, clipText, countScriptCommands, decodeRecordedTurns, deriveFailureSignature, derivedImageTag, dockerImagePreparer, enumerateReplayableCases, extractFixCommand, finalRecordedOutcome, findingReplayStep, findingTrajectoryId, generateFixCommand, goldIncorrectSteps, ingestRecordedTrajectory, isElidedField, isRecordedTimeout, isSubmitAction, isSubmitOnlyAction, parseCorpusFlag, parseIncorrectStepsSubject, parseObservationOutput, parseRecordedReturncode, readFindingsFile, readLabelEntries, renderBatchReport, renderVerifiedFindingsSection, replayVerify, replayVerifyFinding, resolveCaseResources, resolveFindingInvocation, resolveFindingReplayability, runFixLoop, runReplayBatch, seededSample, summarizePrefixReplay, unreadableExitCount, verifyFindings, wrapActionForExec };
|
|
2149
2149
|
|
|
2150
2150
|
//# sourceMappingURL=index.js.map
|
|
@@ -58,6 +58,140 @@ It is on the rejected decisions too, so a reader of an artifact can tell which c
|
|
|
58
58
|
Divergence is `divergences / prefixExecuted`, and the threshold admits a row sitting exactly on it.
|
|
59
59
|
A replay that executed fewer steps than the recording holds is excluded as `prefix-replay-truncated` before that ratio is read, because a truncated run computes divergence over the steps it did reach and a short replay would look perfect.
|
|
60
60
|
|
|
61
|
+
## Reading the recording
|
|
62
|
+
|
|
63
|
+
Every condition above is asked of a recording, so a row is admitted or not by what a decoder can read out of it.
|
|
64
|
+
[`src/trajectory-replay/steps.ts`](../src/trajectory-replay/steps.ts) is that decoder, and it is the only one.
|
|
65
|
+
|
|
66
|
+
The published Terminal-Bench-2 dump holds **turns**, not steps.
|
|
67
|
+
A turn carries an observation in one of four recorded shapes, plus two absences — no observation at all, and a shape this grammar does not know.
|
|
68
|
+
Only the first shape carries an exit status.
|
|
69
|
+
|
|
70
|
+
| observation shape | what it means | carries an exit status |
|
|
71
|
+
| --- | --- | --- |
|
|
72
|
+
| `<returncode>N</returncode><output>…</output>` | a command ran | yes |
|
|
73
|
+
| `The last command <command>…</command> timed out and has been killed.` | the environment killed the command at its bound | no — the outcome is `killed` |
|
|
74
|
+
| `Please always provide EXACTLY ONE action in triple backticks, found N actions.` | the scaffold rejected the turn | no — nothing ran |
|
|
75
|
+
| `$3a` | the dump dropped the string | no — and nothing recovers it |
|
|
76
|
+
|
|
77
|
+
Three rules follow, and each one costs rows when it is missing.
|
|
78
|
+
|
|
79
|
+
**A command keeps the observation of its own turn.**
|
|
80
|
+
Collecting commands and observations into two lists and zipping them looks right and is not.
|
|
81
|
+
A rejected turn carries an observation and usually no command, so from the first rejected turn onward every observation is read against a different command than the one that produced it.
|
|
82
|
+
1,654 turns in the certified population are rejected turns, and they shift 643 of 2,727 rows.
|
|
83
|
+
|
|
84
|
+
**A rejected turn is never a step, even when the dump kept a command for it.**
|
|
85
|
+
The scaffold rejects a turn holding several bash blocks and runs none of them, while the dump keeps one block in the command field.
|
|
86
|
+
494 turns carry that pair.
|
|
87
|
+
Replaying the field would execute a command the recorded run did not, which is a worse corpus than a smaller one.
|
|
88
|
+
|
|
89
|
+
A rejected turn is recognised by its observation, so a rejected turn whose observation the dump elided reads as an executed command.
|
|
90
|
+
Nothing in the dump separates the two, and the defence is per row rather than per turn: the unknown-returncode ratio bounds how much of a row may be unreadable, and a row with no elided observation cannot hold the case at all.
|
|
91
|
+
|
|
92
|
+
**A trailing step that echoes the sentinel and nothing else is the end of the transcript, not a gap in it.**
|
|
93
|
+
The scaffold records an observation only when it hands one back to the model, and `echo COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT` ends the run.
|
|
94
|
+
2,312 of 2,727 rows end that way.
|
|
95
|
+
Reading that turn as the trajectory's last step reports no exit status for 85% of the corpus.
|
|
96
|
+
Echoing the sentinel changes no state, so the recorded end state is the state the step before it left, and that step's exit is the row's final return code.
|
|
97
|
+
|
|
98
|
+
The test is the whole action, never a substring.
|
|
99
|
+
131 of those 2,312 runs end on a command that writes files or edits them and then echoes the sentinel.
|
|
100
|
+
Dropping such a step would remove the run's last state change from the replay; keeping it leaves its exit unknown, which is what the row reports.
|
|
101
|
+
|
|
102
|
+
The elision marker is a **hexadecimal** counter over the row's strings in serialization order.
|
|
103
|
+
A decimal-only pattern (`^\$\d+$`) reads `$3a` as command text: 19,266 of 107,989 recorded commands are elided, and the decimal pattern sees 11,651 of them.
|
|
104
|
+
|
|
105
|
+
The counter is a position, not a key.
|
|
106
|
+
Across all 2,292 rows that hold a marker, the markers are strictly ascending and never repeat, and the first is always `$32` or `$33`.
|
|
107
|
+
A shell command that happened to look like a marker would repeat one or arrive out of order; none does, so the pattern has no false positive in this corpus and no marker maps back to text.
|
|
108
|
+
An elided command is unrecoverable and the row holding it is rejected.
|
|
109
|
+
|
|
110
|
+
## What the decoder recovers, and what it refuses
|
|
111
|
+
|
|
112
|
+
Measured over the 2,578 rows the earlier decoder rejected at the replayable stage, on the 46 certified tasks.
|
|
113
|
+
|
|
114
|
+
| class | rows | share | recovery |
|
|
115
|
+
| --- | --- | --- | --- |
|
|
116
|
+
| commands elided by the dump | 1,327 | 51.5% | refused — no dictionary maps the marker back |
|
|
117
|
+
| run ended on the submit sentinel | 581 | 22.5% | exact — the last executed command's own returncode |
|
|
118
|
+
| ended on the sentinel AND shifted by a rejected turn | 308 | 11.9% | exact |
|
|
119
|
+
| no executed command after decoding | 119 | 4.6% | refused — the run held only rejected turns or the sentinel |
|
|
120
|
+
| last executed command recorded no observation | 94 | 3.6% | refused — it echoed the sentinel after doing work, or its own text was elided |
|
|
121
|
+
| final observation elided by the dump | 85 | 3.3% | refused |
|
|
122
|
+
| shifted by a rejected turn | 47 | 1.8% | exact |
|
|
123
|
+
| last command killed at its timeout | 14 | 0.5% | read exactly as `killed`, then excluded as `signal-kill` |
|
|
124
|
+
| observation shape the grammar cannot read | 2 | 0.1% | refused |
|
|
125
|
+
| phantom command from a rejected turn | 1 | 0.0% | exact |
|
|
126
|
+
|
|
127
|
+
937 rows are recovered exactly — 36.3% of the 2,578 — and every refused class stays refused.
|
|
128
|
+
The 14 killed rows read their outcome exactly too, and are excluded at the stratum stage rather than counted here.
|
|
129
|
+
|
|
130
|
+
The population is one scaffold: `mini-swe-agent`.
|
|
131
|
+
No class is another scaffold's transcript format, because no other scaffold's rows enter this funnel.
|
|
132
|
+
`terminus-2`, `openhands`, `codex` and `claude-code` are pinned for later and are 0% of these 2,578.
|
|
133
|
+
|
|
134
|
+
The correction runs in both directions.
|
|
135
|
+
Six of the 142 rows the earlier decoder admitted carry a command the dump elided with a marker its pattern did not match, and one of those six is in the sealed 16.
|
|
136
|
+
Replaying it would have run the literal string `$3a` as a shell command.
|
|
137
|
+
|
|
138
|
+
## The measured funnel
|
|
139
|
+
|
|
140
|
+
Certified tasks, `mini-swe-agent`, recorded reward 0.
|
|
141
|
+
The other gates are unchanged: the end-state screen, the image-digest pin, and the oracle-determinism refusal all keep their thresholds.
|
|
142
|
+
|
|
143
|
+
The funnel opens at 2,601 rather than the 2,727 rows the dump holds for these tasks.
|
|
144
|
+
126 rows executed no command at all — every turn was rejected, or the run's only command was the sentinel — so they carry no prefix to replay.
|
|
145
|
+
[`tb-corpus-decode.json`](../benchmarks/trace-repair/tb-corpus-decode.json) records that count with the shard list and the duckdb version that produced it.
|
|
146
|
+
|
|
147
|
+
| stage | entering | excluded | remaining |
|
|
148
|
+
| --- | --- | --- | --- |
|
|
149
|
+
| `certified-deterministic-oracle` | 2,601 | 0 | 2,601 |
|
|
150
|
+
| `replayable-commands-and-final-returncode` | 2,601 | 1,528 | 1,073 |
|
|
151
|
+
| `stratum-carries-a-repairable-failure` | 1,073 | 3 | 1,070 |
|
|
152
|
+
| `unknown-returncode-ratio-at-most-25pct` | 1,070 | 126 | 944 |
|
|
153
|
+
| `recorded-commands-at-most-25` | 944 | 164 | 780 |
|
|
154
|
+
| `image-pinned-by-digest` | 780 | 0 | 780 |
|
|
155
|
+
| `one-row-per-recorded-trial` | 780 | 172 | 608 |
|
|
156
|
+
| `recorded-end-state-fails-its-own-suite` | 608 | 324 | 284 |
|
|
157
|
+
| `prefix-divergence-at-most-10pct` | 284 | 66 | 218 |
|
|
158
|
+
| `not-exposed-by-the-mechanism-pilot` | 218 | 0 | 218 |
|
|
159
|
+
| `task-carries-at-least-two-rows` | 218 | 2 | 216 |
|
|
160
|
+
|
|
161
|
+
216 rows in 22 task clusters, against 16 rows in 8 clusters before.
|
|
162
|
+
Simulated power rises from 0.19 to 0.92 at a per-row effect of 0.10, and the registered 0.80 floor is cleared.
|
|
163
|
+
|
|
164
|
+
Three of these stages are new and every one of them removes rows.
|
|
165
|
+
|
|
166
|
+
`one-row-per-recorded-trial`: 885 `mini-swe-agent` trials appear in the dump twice, under an empty and a populated trial id, and the two copies are the same recorded run.
|
|
167
|
+
A cluster holding both reads one trajectory as two independent rows.
|
|
168
|
+
|
|
169
|
+
`stratum-carries-a-repairable-failure`: a row ending on a command the environment stopped cannot be repaired by substituting a command, which is why `ADMISSION_CONFIG_DEFAULTS.admitStrata` omits `signal-kill`.
|
|
170
|
+
|
|
171
|
+
`image-pinned-by-digest` reads the checked-in lock, not one machine's docker store.
|
|
172
|
+
A gate on local presence reports a different denominator after an image eviction, and the same funnel run twice on the same corpus gave 388 rows and then 75.
|
|
173
|
+
Pulling is a prerequisite of execution: a row nothing ran on carries no end-state verdict and leaves at the next stage as unscreened, which is where the 324 exclusions there come from.
|
|
174
|
+
|
|
175
|
+
`prefix-divergence-at-most-10pct`: condition 1, which the earlier design waived and measured without acting on.
|
|
176
|
+
The measurement says the waiver was wrong. 303 rows were screened by replaying the recorded prefix and grading the state it left; 69.2% replay with no divergence at all and 76.9% at or under the threshold.
|
|
177
|
+
One row's end-state verdict is not reproducible — `qemu-startup__giTPHxJ` graded pass under the pilot and fail under two later screens — and it carries 1 divergence over 8 replayed steps, which is above the threshold.
|
|
178
|
+
The gate that was waived is the one that removes it.
|
|
179
|
+
|
|
180
|
+
## When the corpus reward and the task's own suite disagree
|
|
181
|
+
|
|
182
|
+
A row recorded with reward 0 can still pass the task's held-out suite on its replayed end state, and such a row cannot measure a repair because every arm wins it for free.
|
|
183
|
+
|
|
184
|
+
Over 303 screened rows the disagreement rate is **1 row, 0.33%**, and it is `qemu-startup__PnXK6EH`: measured passing twice, in two independent screens 2 hours apart.
|
|
185
|
+
Every task other than `qemu-startup` is 0 of 288. `qemu-startup` alone is 1 of 17, 5.9%.
|
|
186
|
+
|
|
187
|
+
The screen catches that row and does not catch the second `qemu-startup` case.
|
|
188
|
+
`qemu-startup__giTPHxJ` graded pass once and fail twice over three gradings of the same replayed prefix, so one screening grade of it is a draw rather than a measurement.
|
|
189
|
+
The task's suite certified stable on byte-identical state; a replay builds a fresh container, and this task boots a virtual machine, so identical bytes is not what a replay reproduces.
|
|
190
|
+
The divergence gate removes that row, which is the reason it is registered rather than waived.
|
|
191
|
+
|
|
192
|
+
A screen that hits a boundary failure produces no verdict at all.
|
|
193
|
+
20 of the 323 rows the screen opened a container for ended that way, and recording their default `false` would have admitted every one on a check that never ran.
|
|
194
|
+
|
|
61
195
|
## The population split
|
|
62
196
|
|
|
63
197
|
The corpus assay measured the final recorded return code of every admitted row.
|
|
@@ -88,7 +88,7 @@ A high divergence rate is a finding about replay fidelity, not a harness error.
|
|
|
88
88
|
|
|
89
89
|
| Module | Role |
|
|
90
90
|
|---|---|
|
|
91
|
-
| `steps` | The recorded
|
|
91
|
+
| `steps` | The recorded grammar: turns to steps, the four observation shapes, the final outcome. |
|
|
92
92
|
| `exec` | The execution boundary and mini-SWE `/bin/sh` command wrapping. |
|
|
93
93
|
| `verify` | One case: prefix replay, arm A, optional arm B, `ReplayVerdict`. |
|
|
94
94
|
| `corpus` | Labeled corpora to replayable cases, with a reason for every exclusion. |
|
|
@@ -97,6 +97,26 @@ A high divergence rate is a finding about replay fidelity, not a harness error.
|
|
|
97
97
|
| `batch` | Every replayable case to replayability and fix-flip rates. |
|
|
98
98
|
| `wire` / `findings` | One analyst finding to an executed, receipted proof. |
|
|
99
99
|
|
|
100
|
+
## The recorded grammar
|
|
101
|
+
|
|
102
|
+
`steps` decodes turns into steps, and it is the only place that grammar is read.
|
|
103
|
+
|
|
104
|
+
A turn is not a step.
|
|
105
|
+
The system prompt, the task statement and every turn the scaffold rejected are turns that executed nothing.
|
|
106
|
+
`decodeRecordedTurns` keeps the turns that ran a command and pairs each one with the observation of its own turn.
|
|
107
|
+
A turn the scaffold rejected is dropped even when the published dump kept a command for it, because the scaffold ran none of the blocks that turn held.
|
|
108
|
+
|
|
109
|
+
`classifyObservation` names four recorded shapes plus two absences: a command result carrying `<returncode>`, a timeout notice, a format-error notice, an elision marker `$<hex>`, no observation at all, and a shape this grammar does not know.
|
|
110
|
+
Only a command result carries an exit status.
|
|
111
|
+
|
|
112
|
+
`finalRecordedOutcome` reads the last executed command.
|
|
113
|
+
It separates `killed` — the environment stopped the command and wrote a notice instead of an exit status — from `unreadable`, which names the shape that blocked the read.
|
|
114
|
+
A run that ended on the submit sentinel has no observation for that turn, because the scaffold records one only when it hands one back to the model; `decodeRecordedTurns` reports the sentinel rather than reading it as the trajectory's last step.
|
|
115
|
+
|
|
116
|
+
An elided field is unrecoverable.
|
|
117
|
+
The marker is a counter, not a key: the same marker carries different text in different rows, and the dump ships no dictionary.
|
|
118
|
+
A row whose commands cannot be reconstructed exactly as recorded is rejected, because a replay that guesses is worse than a smaller corpus.
|
|
119
|
+
|
|
100
120
|
## Honest limits
|
|
101
121
|
|
|
102
122
|
Only trajectories that record their image are replayable.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-eval",
|
|
3
|
-
"version": "0.145.
|
|
3
|
+
"version": "0.145.11",
|
|
4
4
|
"description": "Evaluate and improve AI agents from runs, traces, judges, and feedback. Compare candidates, cluster failures, measure lift, and gate releases.",
|
|
5
5
|
"homepage": "https://github.com/tangle-network/agent-eval#readme",
|
|
6
6
|
"repository": {
|
|
@@ -180,8 +180,8 @@
|
|
|
180
180
|
"dependencies": {
|
|
181
181
|
"@asteasolutions/zod-to-openapi": "^9.1.0",
|
|
182
182
|
"@hono/node-server": "^2.0.12",
|
|
183
|
-
"@tangle-network/agent-core": "0.
|
|
184
|
-
"@tangle-network/agent-interface": "0.
|
|
183
|
+
"@tangle-network/agent-core": "0.8.0",
|
|
184
|
+
"@tangle-network/agent-interface": "0.52.0",
|
|
185
185
|
"@tangle-network/agent-trace-contract": "^1.0.2",
|
|
186
186
|
"hono": "^4.12.32",
|
|
187
187
|
"linear-sum-assignment": "1.0.9",
|
package/dist/exec-BLtYZdWo.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
//#region src/trajectory-replay/steps.ts
|
|
2
|
-
/** Recorded returncode of a step, or null when the observation carries none. */
|
|
3
|
-
function parseRecordedReturncode(observation) {
|
|
4
|
-
if (!observation) return null;
|
|
5
|
-
const m = /<returncode>(-?\d+)<\/returncode>/.exec(observation);
|
|
6
|
-
return m ? Number(m[1]) : null;
|
|
7
|
-
}
|
|
8
|
-
/** Text between the observation's <output> tags, or the raw observation when
|
|
9
|
-
* the tags are absent. */
|
|
10
|
-
function parseObservationOutput(observation) {
|
|
11
|
-
if (!observation) return "";
|
|
12
|
-
const m = /<output>\n?([\s\S]*?)\n?<\/output>/.exec(observation);
|
|
13
|
-
return m ? m[1] : observation;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Stable failure-signature candidate: the first line of the recorded output
|
|
17
|
-
* that contains the word "error". Null when no such line exists — a verdict
|
|
18
|
-
* then falls back to returncode-only matching and says so.
|
|
19
|
-
* Pass an explicit signature to override (compiler quote glyphs vary with
|
|
20
|
-
* locale, so a hand-picked ASCII substring is often more robust).
|
|
21
|
-
*/
|
|
22
|
-
function deriveFailureSignature(observation) {
|
|
23
|
-
const line = parseObservationOutput(observation).split("\n").find((l) => /\berror\b/i.test(l));
|
|
24
|
-
return line ? line.trim().slice(0, 200) : null;
|
|
25
|
-
}
|
|
26
|
-
/** mini-SWE's end-of-run submit convention: the agent echoes this sentinel
|
|
27
|
-
* and dumps the diff. A label on this step marks a bad SUBMIT DECISION, not a
|
|
28
|
-
* failed command — there is no executable failure to reproduce, so it is
|
|
29
|
-
* never a counterfactual replay target. */
|
|
30
|
-
const SUBMIT_ACTION_SIGNATURE = "COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT";
|
|
31
|
-
function isSubmitAction(action) {
|
|
32
|
-
return action.includes(SUBMIT_ACTION_SIGNATURE);
|
|
33
|
-
}
|
|
34
|
-
//#endregion
|
|
35
|
-
//#region src/trajectory-replay/exec.ts
|
|
36
|
-
/**
|
|
37
|
-
* mini-SWE runs every action as a fresh /bin/sh subshell from a fixed
|
|
38
|
-
* workdir. Reproduce that exactly — and stay quote-proof for arbitrary
|
|
39
|
-
* recorded actions — by piping the base64 of the action into `sh` after
|
|
40
|
-
* cd-ing to the workdir. Exit code is sh's, i.e. the action's.
|
|
41
|
-
*/
|
|
42
|
-
function wrapActionForExec(action, cwd) {
|
|
43
|
-
const b64 = Buffer.from(action, "utf8").toString("base64");
|
|
44
|
-
return `cd ${`'${cwd.replaceAll("'", `'\\''`)}'`} && printf %s ${b64} | base64 -d | sh`;
|
|
45
|
-
}
|
|
46
|
-
//#endregion
|
|
47
|
-
export { parseObservationOutput as a, isSubmitAction as i, SUBMIT_ACTION_SIGNATURE as n, parseRecordedReturncode as o, deriveFailureSignature as r, wrapActionForExec as t };
|
|
48
|
-
|
|
49
|
-
//# sourceMappingURL=exec-BLtYZdWo.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"exec-BLtYZdWo.js","names":[],"sources":["../src/trajectory-replay/steps.ts","../src/trajectory-replay/exec.ts"],"sourcesContent":["/**\n * Recorded shell-trajectory steps and the observation grammar they carry.\n *\n * A recorded trajectory is the action/observation sequence an agent actually\n * ran. Scaffolds that execute one shell command per step (mini-SWE and the\n * CodeTracer-normalized corpora built from it) tag each observation with the\n * command's returncode and its combined output:\n *\n * <returncode>2</returncode>\n * <output>\n * …command output…\n * </output>\n *\n * The parsers here are the only place that grammar is decoded. Everything\n * downstream — replay verdicts, corpus enumeration, fix prompts — reads the\n * returncode, the output, and the failure signature through these functions.\n */\n\n/**\n * One step of a recorded shell trajectory. Structural: any richer step record\n * (file refs, thinking text, tool type) satisfies it.\n */\nexport interface RecordedTrajectoryStep {\n /** 1-based position in the trajectory. */\n readonly step_id: number\n readonly action: string\n /** Null when the step recorded no observation (terminal submit steps). */\n readonly observation: string | null\n}\n\n/** Recorded returncode of a step, or null when the observation carries none. */\nexport function parseRecordedReturncode(observation: string | null): number | null {\n if (!observation) return null\n const m = /<returncode>(-?\\d+)<\\/returncode>/.exec(observation)\n return m ? Number(m[1]) : null\n}\n\n/** Text between the observation's <output> tags, or the raw observation when\n * the tags are absent. */\nexport function parseObservationOutput(observation: string | null): string {\n if (!observation) return ''\n const m = /<output>\\n?([\\s\\S]*?)\\n?<\\/output>/.exec(observation)\n return m ? m[1]! : observation\n}\n\n/**\n * Stable failure-signature candidate: the first line of the recorded output\n * that contains the word \"error\". Null when no such line exists — a verdict\n * then falls back to returncode-only matching and says so.\n * Pass an explicit signature to override (compiler quote glyphs vary with\n * locale, so a hand-picked ASCII substring is often more robust).\n */\nexport function deriveFailureSignature(observation: string | null): string | null {\n const line = parseObservationOutput(observation)\n .split('\\n')\n .find((l) => /\\berror\\b/i.test(l))\n return line ? line.trim().slice(0, 200) : null\n}\n\n/** mini-SWE's end-of-run submit convention: the agent echoes this sentinel\n * and dumps the diff. A label on this step marks a bad SUBMIT DECISION, not a\n * failed command — there is no executable failure to reproduce, so it is\n * never a counterfactual replay target. */\nexport const SUBMIT_ACTION_SIGNATURE = 'COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT'\n\nexport function isSubmitAction(action: string): boolean {\n return action.includes(SUBMIT_ACTION_SIGNATURE)\n}\n","/**\n * The execution boundary replay runs across.\n *\n * A replay needs one thing from its environment: a session that runs a shell\n * command inside the trajectory's own image and reports the exit code and\n * output. That is the whole contract. Concrete backends — a sandbox platform\n * client, a docker exec, an SSH shell — live with the consumer that owns the\n * infrastructure, so this package depends on no sandbox client.\n */\n\nexport interface ReplayExecResult {\n exitCode: number\n stdout: string\n stderr: string\n}\n\nexport interface ReplayExecSession {\n exec(command: string, timeoutMs: number): Promise<ReplayExecResult>\n close(): Promise<void>\n}\n\nexport interface ReplayExecBackend {\n /** One fresh execution environment per call; the caller closes it. */\n open(): Promise<ReplayExecSession>\n}\n\n/** Builds a backend pinned to one image. Callers that resolve images\n * internally (batch, corpus wire, finding verification) take this instead of\n * a backend, so every case runs against its own image. */\nexport type ReplayExecBackendFactory = (image: string) => ReplayExecBackend\n\n/**\n * mini-SWE runs every action as a fresh /bin/sh subshell from a fixed\n * workdir. Reproduce that exactly — and stay quote-proof for arbitrary\n * recorded actions — by piping the base64 of the action into `sh` after\n * cd-ing to the workdir. Exit code is sh's, i.e. the action's.\n */\nexport function wrapActionForExec(action: string, cwd: string): string {\n const b64 = Buffer.from(action, 'utf8').toString('base64')\n const quotedCwd = `'${cwd.replaceAll(\"'\", `'\\\\''`)}'`\n return `cd ${quotedCwd} && printf %s ${b64} | base64 -d | sh`\n}\n"],"mappings":";;AA+BA,SAAgB,wBAAwB,aAA2C;CACjF,IAAI,CAAC,aAAa,OAAO;CACzB,MAAM,IAAI,oCAAoC,KAAK,WAAW;CAC9D,OAAO,IAAI,OAAO,EAAE,EAAE,IAAI;AAC5B;;;AAIA,SAAgB,uBAAuB,aAAoC;CACzE,IAAI,CAAC,aAAa,OAAO;CACzB,MAAM,IAAI,qCAAqC,KAAK,WAAW;CAC/D,OAAO,IAAI,EAAE,KAAM;AACrB;;;;;;;;AASA,SAAgB,uBAAuB,aAA2C;CAChF,MAAM,OAAO,uBAAuB,WAAW,CAAC,CAC7C,MAAM,IAAI,CAAC,CACX,MAAM,MAAM,aAAa,KAAK,CAAC,CAAC;CACnC,OAAO,OAAO,KAAK,KAAK,CAAC,CAAC,MAAM,GAAG,GAAG,IAAI;AAC5C;;;;;AAMA,MAAa,0BAA0B;AAEvC,SAAgB,eAAe,QAAyB;CACtD,OAAO,OAAO,SAAS,uBAAuB;AAChD;;;;;;;;;AC9BA,SAAgB,kBAAkB,QAAgB,KAAqB;CACrE,MAAM,MAAM,OAAO,KAAK,QAAQ,MAAM,CAAC,CAAC,SAAS,QAAQ;CAEzD,OAAO,MAAM,IADS,IAAI,WAAW,KAAK,OAAO,EAAE,GAC5B,gBAAgB,IAAI;AAC7C"}
|
package/dist/steps-BArUxhna.d.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
//#region src/trajectory-replay/steps.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Recorded shell-trajectory steps and the observation grammar they carry.
|
|
4
|
-
*
|
|
5
|
-
* A recorded trajectory is the action/observation sequence an agent actually
|
|
6
|
-
* ran. Scaffolds that execute one shell command per step (mini-SWE and the
|
|
7
|
-
* CodeTracer-normalized corpora built from it) tag each observation with the
|
|
8
|
-
* command's returncode and its combined output:
|
|
9
|
-
*
|
|
10
|
-
* <returncode>2</returncode>
|
|
11
|
-
* <output>
|
|
12
|
-
* …command output…
|
|
13
|
-
* </output>
|
|
14
|
-
*
|
|
15
|
-
* The parsers here are the only place that grammar is decoded. Everything
|
|
16
|
-
* downstream — replay verdicts, corpus enumeration, fix prompts — reads the
|
|
17
|
-
* returncode, the output, and the failure signature through these functions.
|
|
18
|
-
*/
|
|
19
|
-
/**
|
|
20
|
-
* One step of a recorded shell trajectory. Structural: any richer step record
|
|
21
|
-
* (file refs, thinking text, tool type) satisfies it.
|
|
22
|
-
*/
|
|
23
|
-
interface RecordedTrajectoryStep {
|
|
24
|
-
/** 1-based position in the trajectory. */
|
|
25
|
-
readonly step_id: number;
|
|
26
|
-
readonly action: string;
|
|
27
|
-
/** Null when the step recorded no observation (terminal submit steps). */
|
|
28
|
-
readonly observation: string | null;
|
|
29
|
-
}
|
|
30
|
-
/** Recorded returncode of a step, or null when the observation carries none. */
|
|
31
|
-
declare function parseRecordedReturncode(observation: string | null): number | null;
|
|
32
|
-
/** Text between the observation's <output> tags, or the raw observation when
|
|
33
|
-
* the tags are absent. */
|
|
34
|
-
declare function parseObservationOutput(observation: string | null): string;
|
|
35
|
-
/**
|
|
36
|
-
* Stable failure-signature candidate: the first line of the recorded output
|
|
37
|
-
* that contains the word "error". Null when no such line exists — a verdict
|
|
38
|
-
* then falls back to returncode-only matching and says so.
|
|
39
|
-
* Pass an explicit signature to override (compiler quote glyphs vary with
|
|
40
|
-
* locale, so a hand-picked ASCII substring is often more robust).
|
|
41
|
-
*/
|
|
42
|
-
declare function deriveFailureSignature(observation: string | null): string | null;
|
|
43
|
-
/** mini-SWE's end-of-run submit convention: the agent echoes this sentinel
|
|
44
|
-
* and dumps the diff. A label on this step marks a bad SUBMIT DECISION, not a
|
|
45
|
-
* failed command — there is no executable failure to reproduce, so it is
|
|
46
|
-
* never a counterfactual replay target. */
|
|
47
|
-
declare const SUBMIT_ACTION_SIGNATURE = "COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT";
|
|
48
|
-
declare function isSubmitAction(action: string): boolean;
|
|
49
|
-
//#endregion
|
|
50
|
-
export { parseObservationOutput as a, isSubmitAction as i, SUBMIT_ACTION_SIGNATURE as n, parseRecordedReturncode as o, deriveFailureSignature as r, RecordedTrajectoryStep as t };
|
|
51
|
-
//# sourceMappingURL=steps-BArUxhna.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"steps-BArUxhna.d.ts","names":[],"sources":["../src/trajectory-replay/steps.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;UAsBiB;;WAEN;WACA;;WAEA;;;iBAIK,wBAAwB;;;iBAQxB,uBAAuB;;;;;;;;iBAavB,uBAAuB;;;;;cAW1B;iBAEG,eAAe"}
|