@tangle-network/traces 0.11.3 → 0.11.5

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/dist/index.js CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  CodexTaskScopeError,
15
15
  CopilotAdapter,
16
16
  DEFAULT_HARNESS,
17
+ DEFAULT_SANDBOX_BASE_URL,
17
18
  EMPTY_SPAN_RUN_SNAPSHOT,
18
19
  EXPORT_RULE,
19
20
  EmptySessionError,
@@ -46,8 +47,10 @@ import {
46
47
  analyzeSpans,
47
48
  analyzeSteeringChain,
48
49
  applyRedactor,
50
+ assertSandboxReachable,
49
51
  buildFixPrompt,
50
52
  buildPolicyEvidenceRecord,
53
+ buildRetryFixPrompt,
51
54
  buildSessionIndex,
52
55
  buildSessionIndexFromRows,
53
56
  buildSpanRunTree,
@@ -56,9 +59,12 @@ import {
56
59
  chatTrajectoryToSpans,
57
60
  classifyLiveActions,
58
61
  classifyReaction,
62
+ classifyVerdict,
59
63
  claudeActor,
64
+ clipText,
60
65
  cmdReplayVerify,
61
66
  cmdReplayVerifyBatch,
67
+ cmdVerifyFindings,
62
68
  codexActor,
63
69
  collectPolicyEvidence,
64
70
  collectSessionIndex,
@@ -68,6 +74,7 @@ import {
68
74
  commandRedactor,
69
75
  conformanceOfSpans,
70
76
  connectors,
77
+ countScriptCommands,
71
78
  countSkillRunsJsonl,
72
79
  cwdMatchesSelection,
73
80
  defaultTraceLiveAnalysts,
@@ -84,6 +91,8 @@ import {
84
91
  extractFixCommand,
85
92
  fileRunContextSupervisorRunReader,
86
93
  findSpanSourceFiles,
94
+ findingReplayStep,
95
+ findingTrajectoryId,
87
96
  forEachTreeNode,
88
97
  generateFixCommand,
89
98
  goldIncorrectSteps,
@@ -114,6 +123,7 @@ import {
114
123
  otlpRowToSpan,
115
124
  outboundHash,
116
125
  parseCorpusFlag,
126
+ parseIncorrectStepsSubject,
117
127
  parseIsoToEpochMs,
118
128
  parseObservationOutput,
119
129
  parseRecordedReturncode,
@@ -121,10 +131,12 @@ import {
121
131
  parseReplayVerifyArgs,
122
132
  parseSession,
123
133
  parseSince,
134
+ parseVerifyFindingsArgs,
124
135
  planTraceAgenticRoute,
125
136
  planUpload,
126
137
  readCoordinationLog,
127
138
  readFileRunContext,
139
+ readFindingsFile,
128
140
  readJsonFile,
129
141
  readJsonl,
130
142
  readLabelEntries,
@@ -143,11 +155,15 @@ import {
143
155
  renderRunWatchSnapshot,
144
156
  renderSpanRunSnapshot,
145
157
  renderValidation,
158
+ renderVerifiedFindingsSection,
146
159
  replayBatchUsage,
147
160
  replayVerify,
161
+ replayVerifyFinding,
148
162
  replayVerifyUsage,
149
163
  resolveAdapter,
150
164
  resolveCaseResources,
165
+ resolveFindingInvocation,
166
+ resolveFindingReplayability,
151
167
  resolveOtlpInputFiles,
152
168
  resolveRepoAttrs,
153
169
  resolveRunContextDir,
@@ -155,6 +171,7 @@ import {
155
171
  resolveSessionRepoAttrs,
156
172
  runCommand,
157
173
  runExternalAnalyzers,
174
+ runFixLoop,
158
175
  runPipelines,
159
176
  runReplayBatch,
160
177
  runTotals,
@@ -201,6 +218,8 @@ import {
201
218
  userPromptSpan,
202
219
  validateOtlpSpans,
203
220
  validationExitCode,
221
+ verifyFindings,
222
+ verifyFindingsUsage,
204
223
  watchRunTarget,
205
224
  watchSessions,
206
225
  wrap,
@@ -214,7 +233,7 @@ import {
214
233
  writeTraceImprovementArtifacts,
215
234
  zaiChatCaller,
216
235
  zeroPricedCost
217
- } from "./chunk-CK5F5TWO.js";
236
+ } from "./chunk-VTYOCFGF.js";
218
237
 
219
238
  // src/collect.ts
220
239
  async function collectSessions(opts = {}) {
@@ -230,79 +249,6 @@ async function collectSessions(opts = {}) {
230
249
  return out;
231
250
  }
232
251
 
233
- // src/replay-wire.ts
234
- var SUBJECT_PATTERN = /^incorrect-steps-(\d+)-(\d+)-(escaped|unescaped)-consequence-(\d+)$/;
235
- function parseIncorrectStepsSubject(subject) {
236
- const match = SUBJECT_PATTERN.exec(subject);
237
- if (!match) return null;
238
- return {
239
- firstStep: Number(match[1]),
240
- lastStep: Number(match[2]),
241
- escapeStatus: match[3],
242
- consequenceStep: Number(match[4])
243
- };
244
- }
245
- function resolveFindingInvocation(finding, corpora) {
246
- const subject = parseIncorrectStepsSubject(finding.subject);
247
- if (!subject) {
248
- throw new Error(
249
- `replay-wire: subject '${finding.subject}' is not incorrect-steps-<first>-<last>-<escaped|unescaped>-consequence-<step>`
250
- );
251
- }
252
- const failures = [];
253
- for (const corpus of corpora) {
254
- const resolution = resolveCaseResources(corpus, finding.trajId);
255
- if (resolution.resolved) {
256
- const at = subject.firstStep;
257
- const step = resolution.resources.steps.find((s) => s.step_id === at);
258
- if (!step) {
259
- throw new Error(
260
- `replay-wire: finding step ${at} is outside ${finding.trajId} (${resolution.resources.steps.length} steps)`
261
- );
262
- }
263
- return { resources: resolution.resources, subject, at };
264
- }
265
- failures.push(`${corpus.name}: ${resolution.reason}`);
266
- }
267
- throw new Error(
268
- `replay-wire: trajectory ${finding.trajId} is not replayable in any corpus \u2014 ${failures.join("; ")}`
269
- );
270
- }
271
- async function replayVerifyFinding(finding, options) {
272
- if (options.fixCaller && options.fixCommand !== void 0) {
273
- throw new Error("replay-wire: pass fixCaller or fixCommand, not both");
274
- }
275
- const invocation = resolveFindingInvocation(finding, options.corpora);
276
- let fixCommand = options.fixCommand ?? null;
277
- if (options.fixCaller) {
278
- const generated = await generateFixCommand(options.fixCaller, {
279
- taskStatement: invocation.resources.taskStatement,
280
- steps: invocation.resources.steps,
281
- k: invocation.at
282
- });
283
- if (!generated.succeeded) {
284
- throw new Error(`replay-wire: fix generation failed \u2014 ${generated.error}`);
285
- }
286
- fixCommand = generated.value.command;
287
- }
288
- const verdict = await replayVerify({
289
- stepsPath: invocation.resources.stepsPath,
290
- image: invocation.resources.image,
291
- at: invocation.at,
292
- fixCommand: fixCommand ?? void 0,
293
- cwd: invocation.resources.cwd,
294
- out: options.out,
295
- caseId: invocation.resources.trajId,
296
- stepTimeoutMs: options.stepTimeoutMs ?? invocation.resources.recordedStepTimeoutMs ?? void 0,
297
- prefixLimit: options.prefixLimit,
298
- backend: options.backend,
299
- apiKey: options.apiKey,
300
- baseUrl: options.baseUrl,
301
- onProgress: options.onProgress
302
- });
303
- return { invocation, fixCommand, verdict };
304
- }
305
-
306
252
  // src/index.ts
307
253
  import {
308
254
  AnalystRegistry,
@@ -329,6 +275,7 @@ export {
329
275
  CopilotAdapter,
330
276
  DEFAULT_HARNESS,
331
277
  DEFAULT_REDACTION_RULES,
278
+ DEFAULT_SANDBOX_BASE_URL,
332
279
  EMPTY_SPAN_RUN_SNAPSHOT,
333
280
  EXPORT_RULE,
334
281
  EmptySessionError,
@@ -361,9 +308,11 @@ export {
361
308
  analyzeSpans,
362
309
  analyzeSteeringChain,
363
310
  applyRedactor,
311
+ assertSandboxReachable,
364
312
  buildDefaultAnalystRegistry,
365
313
  buildFixPrompt,
366
314
  buildPolicyEvidenceRecord,
315
+ buildRetryFixPrompt,
367
316
  buildSessionIndex,
368
317
  buildSessionIndexFromRows,
369
318
  buildSpanRunTree,
@@ -372,9 +321,12 @@ export {
372
321
  chatTrajectoryToSpans,
373
322
  classifyLiveActions,
374
323
  classifyReaction,
324
+ classifyVerdict,
375
325
  claudeActor,
326
+ clipText,
376
327
  cmdReplayVerify,
377
328
  cmdReplayVerifyBatch,
329
+ cmdVerifyFindings,
378
330
  codexActor,
379
331
  collectPolicyEvidence,
380
332
  collectSessionIndex,
@@ -385,6 +337,7 @@ export {
385
337
  commandRedactor,
386
338
  conformanceOfSpans,
387
339
  connectors,
340
+ countScriptCommands,
388
341
  countSkillRunsJsonl,
389
342
  createHostedClient,
390
343
  cwdMatchesSelection,
@@ -402,6 +355,8 @@ export {
402
355
  extractFixCommand,
403
356
  fileRunContextSupervisorRunReader,
404
357
  findSpanSourceFiles,
358
+ findingReplayStep,
359
+ findingTrajectoryId,
405
360
  forEachTreeNode,
406
361
  generateFixCommand,
407
362
  goldIncorrectSteps,
@@ -442,10 +397,12 @@ export {
442
397
  parseReplayVerifyArgs,
443
398
  parseSession,
444
399
  parseSince,
400
+ parseVerifyFindingsArgs,
445
401
  planTraceAgenticRoute,
446
402
  planUpload,
447
403
  readCoordinationLog,
448
404
  readFileRunContext,
405
+ readFindingsFile,
449
406
  readJsonFile,
450
407
  readJsonl,
451
408
  readLabelEntries,
@@ -466,6 +423,7 @@ export {
466
423
  renderRunWatchSnapshot,
467
424
  renderSpanRunSnapshot,
468
425
  renderValidation,
426
+ renderVerifiedFindingsSection,
469
427
  replayBatchUsage,
470
428
  replayVerify,
471
429
  replayVerifyFinding,
@@ -473,6 +431,7 @@ export {
473
431
  resolveAdapter,
474
432
  resolveCaseResources,
475
433
  resolveFindingInvocation,
434
+ resolveFindingReplayability,
476
435
  resolveOtlpInputFiles,
477
436
  resolveRepoAttrs,
478
437
  resolveRunContextDir,
@@ -480,6 +439,7 @@ export {
480
439
  resolveSessionRepoAttrs,
481
440
  runCommand,
482
441
  runExternalAnalyzers,
442
+ runFixLoop,
483
443
  runPipelines,
484
444
  runReplayBatch,
485
445
  runTotals,
@@ -526,6 +486,8 @@ export {
526
486
  userPromptSpan,
527
487
  validateOtlpSpans,
528
488
  validationExitCode,
489
+ verifyFindings,
490
+ verifyFindingsUsage,
529
491
  watchRunTarget,
530
492
  watchSessions,
531
493
  wrap,
@@ -77,6 +77,17 @@ A corpus is a gold label file plus a prepared directory (`normalized/<traj_id>/s
77
77
 
78
78
  Fix generation (`--fix generate`) runs ONE chat completion per arm-A-reproduced case against an OpenAI-compatible endpoint (default: glm-5.2 on z.ai). The prompt carries the gold step's action and observation, ±3 surrounding steps, and the task statement; the reply must be a single corrected shell command. Cases beyond `--max-fix-cases` are excluded by a seeded random sample and marked `sampled-out` in the report. Arm B replays the prefix in its own fresh sandbox and executes the corrected command; `failureVanished` = exit 0 with the failure signature absent.
79
79
 
80
+ ### Iterative fix loop (`--fix loop`)
81
+
82
+ `--fix loop` (in `src/replay-fix-loop.ts`) replaces the single shot with an execution-feedback loop of up to `--fix-attempts` attempts (default 3) per case:
83
+
84
+ - Attempt 1 is byte-identical to the one-shot prompt, so the report's `fixFlipAttempt1` stays directly comparable to `--fix generate`.
85
+ - When an arm fails (nonzero exit or the failure signature persists) or the model call itself fails, the next prompt carries every prior command with its REAL executed stdout/stderr (clipped tails), never a paraphrase.
86
+ - Retries may answer with a short script — at most 5 commands in one fenced block — executed as ONE `/bin/sh` unit; a longer script is rejected as a failed attempt and the rejection feeds the next prompt.
87
+ - Every attempt runs in its own fresh sandbox with the same replayed prefix. A used sandbox is never mutated mid-arm, so a flip always proves the corrected step against the recorded prefix state, not against debris from an earlier attempt. Wall-time cost is one extra prefix replay per attempt.
88
+
89
+ The report adds `fixFlipAttempt1` (flips at attempt 1 over cases whose attempt 1 executed), `flipsByAttempt`, the full per-attempt trail on each case row (`fix.attempts`), and one `armB-attempt<N>-result.json` per executed attempt (`armB-result.json` keeps the last executed attempt — the flipped one when the loop flips).
90
+
80
91
  Honest-reporting notes baked into the report:
81
92
 
82
93
  - A gold step whose recorded observation carries **no returncode** can never satisfy "arm A reproduces the recorded returncode": it counts against the replayability rate and the per-case table says why.
@@ -99,6 +110,12 @@ const { invocation, fixCommand, verdict } = await replayVerifyFinding(
99
110
 
100
111
  The subject grammar is the analyst benchmark's `incorrect-steps-<first>-<last>-<escaped|unescaped>-consequence-<step>`; `--at` is the finding's **first** incorrect step (the finding's claim, which may differ from the gold label). The wire resolves the trajectory across the given corpora, generates the arm-B fix through the same one-call generator (or accepts a pre-supplied `fixCommand`), and returns the full `ReplayVerdict`. It throws with a precise reason when the finding cannot be replayed (malformed subject, unknown trajectory, non-SWE case, step out of range) — the product surfaces that reason instead of a proof.
101
112
 
113
+ ## Product surface — verified findings
114
+
115
+ `traces verify-findings` (and `traces analyze --verify-findings`) runs this proof per recorded analyst finding and annotates each with `reproduced | fix-flipped | divergent | not-replayable` plus a receipt directory.
116
+ Unlike the wire above it accepts the shapes analysts actually emit (`incorrect-step-<n>` subjects, `metadata.block_first_step`, `trace://` evidence refs) and never throws on a finding-shaped dead end — the dead end becomes the finding's honest `not-replayable` receipt.
117
+ See [Verified findings](./trace-analysts.md#verified-findings-executed-replay).
118
+
102
119
  ## Orchestrator prerequisites
103
120
 
104
121
  replay-verify talks to a sandbox API (`--base-url`); in local development that is the sandbox SDK adapter in front of an orchestrator running the docker driver.
@@ -210,6 +210,34 @@ console.log(renderAnalystBenchmarkMarkdown(result))
210
210
  Public labels test the measurement code, not the quality of every built-in analyst automatically.
211
211
  A real quality claim requires running the analyst over the corresponding trajectories, retaining all rows, and comparing it with named alternatives at equal model and request limits.
212
212
 
213
+ ## Verified findings (executed replay)
214
+
215
+ An analyst finding is a cited claim until something executes it.
216
+ `traces analyze --verify-findings` (and the standalone `traces verify-findings`) replays each finding's trajectory prefix in a real sandbox, re-runs the accused step, and annotates every finding with an executed verdict:
217
+
218
+ | Verdict | Meaning |
219
+ |---|---|
220
+ | `reproduced` | the recorded failure signature (returncode + stable output substring) reproduced when the accused step re-ran |
221
+ | `fix-flipped` | reproduced, and a supplied corrected command made the failure vanish in a fresh replay |
222
+ | `divergent` | the step executed but the recorded failure did not reproduce — evidence against the finding, or against replay fidelity (the receipt carries prefix divergences so you can tell which) |
223
+ | `not-replayable` | the finding could not be executed; the receipt names the precise reason (no step subject, unknown trajectory, no docker image, submit step, …) |
224
+
225
+ ```bash
226
+ # Verify the findings an analyze run produced (marks each finding in the report):
227
+ traces analyze --last 1 --llm --verify-findings \
228
+ --replay-corpus holdout=labels.json::prepared/ --verify-out ./receipts
229
+
230
+ # Verify findings recorded earlier (e.g. extracted from an eval result.json):
231
+ traces verify-findings --findings findings.json --out ./receipts \
232
+ --steps normalized/<traj>/steps.json --image <replay-ready-image> --cwd /app
233
+ ```
234
+
235
+ Findings are matched by the shape analysts emit: subject `incorrect-step-<n>` (or the wire form `incorrect-steps-<f>-<l>-…`), `metadata.block_first_step`, and `trace://<trajectory>/…` evidence refs.
236
+ Findings accusing the same step share one executed proof; each finding still gets its own receipt directory (`receipt.json` plus, when executed, `replay-verdict.json` and `report.md` with real stdout/stderr).
237
+ Verification is execution, not generation: no LLM is involved unless you pass `--fix-command`.
238
+ A missing sandbox is an error when any finding is replayable — verification never silently skips.
239
+ Sandbox setup, execution semantics, and honest limits are in [Replay verification](./replay-verify.md).
240
+
213
241
  ## Turn findings into improvement
214
242
 
215
243
  Do not train or rewrite policy from an analyst's own prose alone.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/traces",
3
- "version": "0.11.3",
3
+ "version": "0.11.5",
4
4
  "description": "Point it at your coding-agent session traces (Claude Code, Codex, OpenCode, Gemini, Pi, …) and get failure-mode + efficiency findings. CLI + SDK over the @tangle-network/agent-eval analyst suite — observe live sessions, run your own analysts, redact, and upload to the Tangle Intelligence Platform.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -47,10 +47,10 @@
47
47
  "node": ">=22"
48
48
  },
49
49
  "dependencies": {
50
- "@tangle-network/agent-eval": "0.140.1",
51
- "@tangle-network/agent-runtime": "0.121.0",
50
+ "@tangle-network/agent-eval": "0.143.0",
51
+ "@tangle-network/agent-runtime": "0.126.0",
52
52
  "@tangle-network/agent-trace-contract": "^1.0.2",
53
- "@tangle-network/sandbox": "0.16.0"
53
+ "@tangle-network/sandbox": "0.17.2"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/node": "^22.0.0",