@tangle-network/traces 0.9.17 → 0.9.18

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.
@@ -8975,7 +8975,58 @@ function traceCoverageFinding(pipelines, adoption) {
8975
8975
  }
8976
8976
  });
8977
8977
  }
8978
- function deterministicFindings(pipelines, reactions, adoption) {
8978
+ function sortedToolErrorSpans(spans) {
8979
+ return spans.filter((item) => item.attributes["openinference.span.kind"] === "TOOL" && item.status.code === "ERROR").sort((left, right) => left.start_time.localeCompare(right.start_time) || left.trace_id.localeCompare(right.trace_id) || left.span_id.localeCompare(right.span_id));
8980
+ }
8981
+ function toolErrorEvidence(item) {
8982
+ return evidence(
8983
+ "span",
8984
+ spanEvidenceUri(item.trace_id, item.span_id),
8985
+ `${String(item.attributes["tool.name"] ?? item.name)}: ${item.status.message ?? "tool span ended with ERROR"}`.slice(0, 240)
8986
+ );
8987
+ }
8988
+ function toolErrorFinding(pipelines, spans) {
8989
+ const terminalFailureTraceIds = new Set(
8990
+ spans.filter((item) => item.parent_span_id === null && item.status.code === "ERROR").map((item) => item.trace_id)
8991
+ );
8992
+ const nonTerminalRuns = pipelines.toolUse.filter(
8993
+ (run) => !terminalFailureTraceIds.has(run.runId)
8994
+ );
8995
+ const totalCalls = nonTerminalRuns.reduce((total, run) => total + run.totalCalls, 0);
8996
+ const errorCount = nonTerminalRuns.reduce(
8997
+ (total, run) => total + Object.values(run.byTool).reduce((runTotal, tool) => runTotal + tool.errors, 0),
8998
+ 0
8999
+ );
9000
+ if (errorCount === 0) return void 0;
9001
+ const errorSpans = sortedToolErrorSpans(spans).filter((item) => !terminalFailureTraceIds.has(item.trace_id));
9002
+ if (errorSpans.length === 0) return void 0;
9003
+ const affectedRuns = new Set(errorSpans.map((item) => item.trace_id)).size;
9004
+ const errorRate = errorCount / Math.max(1, totalCalls);
9005
+ const citedSpans = errorSpans.slice(0, 3);
9006
+ return makeFinding({
9007
+ analyst_id: "traces-deterministic",
9008
+ area: "tool-use",
9009
+ subject: "non-terminal-tool-errors",
9010
+ claim: `${errorCount}/${totalCalls} tool call(s) ended in errors across ${affectedRuns} run(s) without a terminal failure`,
9011
+ severity: errorRate >= 0.25 ? "high" : "medium",
9012
+ rationale: "Recovered tool errors still consume time and tokens, and repeated failures can hide brittle retry or recovery behavior.",
9013
+ evidence_refs: citedSpans.map(toolErrorEvidence),
9014
+ recommended_action: "Inspect the most frequent failing tool and its cited inputs, then change the retry or recovery policy so a failure produces new state before another call.",
9015
+ validation_plan: "Rerun comparable sessions and require non-terminal tool errors to decrease without increasing terminal failures.",
9016
+ confidence: 1,
9017
+ metadata: {
9018
+ source: "agent-eval.computeToolUseMetrics",
9019
+ errorCount,
9020
+ totalCalls,
9021
+ errorRate,
9022
+ affectedRuns,
9023
+ citedErrorSpans: citedSpans.length,
9024
+ omittedErrorSpans: Math.max(0, errorSpans.length - citedSpans.length)
9025
+ },
9026
+ id_basis: "non-terminal-tool-errors"
9027
+ });
9028
+ }
9029
+ function deterministicFindings(pipelines, reactions, adoption, spans) {
8979
9030
  const findings = [];
8980
9031
  const coverage = traceCoverageFinding(pipelines, adoption);
8981
9032
  if (coverage) findings.push(coverage);
@@ -8998,10 +9049,16 @@ function deterministicFindings(pipelines, reactions, adoption) {
8998
9049
  metadata: { source: "traces.pipeline.stuckLoopView", loopCount: loops.length }
8999
9050
  }));
9000
9051
  }
9052
+ const toolErrors = toolErrorFinding(pipelines, spans);
9053
+ if (toolErrors) findings.push(toolErrors);
9001
9054
  const failedRuns = pipelines.failureClusters.totalFailures;
9002
9055
  if (failedRuns > 0) {
9003
9056
  const top = pipelines.failureClusters.clusters[0];
9004
9057
  const failureRate = failedRuns / Math.max(1, pipelines.failureClusters.totalRuns);
9058
+ const exampleSpans = top?.exampleRunId ? spans.filter((item) => item.trace_id === top.exampleRunId) : [];
9059
+ const exampleRoot = exampleSpans.find((item) => item.parent_span_id === null && item.status.code === "ERROR");
9060
+ const exampleToolErrors = sortedToolErrorSpans(exampleSpans);
9061
+ const citedToolErrors = exampleToolErrors.slice(0, 3);
9005
9062
  findings.push(makeFinding({
9006
9063
  analyst_id: "traces-deterministic",
9007
9064
  area: "reliability",
@@ -9009,12 +9066,17 @@ function deterministicFindings(pipelines, reactions, adoption) {
9009
9066
  severity: failureRate >= 0.1 ? "high" : "medium",
9010
9067
  rationale: "Execution errors consume time and tokens, and sparse error telemetry can hide whether the agent recovered or repeated the same failure.",
9011
9068
  evidence_refs: [
9069
+ ...exampleRoot ? [evidence(
9070
+ "span",
9071
+ spanEvidenceUri(exampleRoot.trace_id, exampleRoot.span_id),
9072
+ `${exampleRoot.name}: ${exampleRoot.status.message ?? "root span ended with ERROR"}`.slice(0, 240)
9073
+ )] : [],
9074
+ ...citedToolErrors.map(toolErrorEvidence),
9012
9075
  evidence(
9013
9076
  "metric",
9014
9077
  `pipelines.failure_cluster.${top?.failureClass ?? "unknown"}`,
9015
9078
  top ? `${top.runCount} run(s); example: ${top.exampleError ?? "error details not captured"}` : `${failedRuns} failed run(s)`
9016
- ),
9017
- ...top?.exampleRunId ? [evidence("span", `trace:${top.exampleRunId}`, top.exampleError)] : []
9079
+ )
9018
9080
  ],
9019
9081
  recommended_action: top?.failureClass === "unknown" ? "Instrument the failing operation name and arguments, then start with the highest-frequency example error and verify the agent changes state before retrying." : "Fix the highest-frequency failure cluster first, then require the agent to inspect the error and change state before retrying.",
9020
9082
  validation_plan: "Rerun a comparable trace window and require failed runs and repeated failures in the top cluster to decrease.",
@@ -9024,7 +9086,9 @@ function deterministicFindings(pipelines, reactions, adoption) {
9024
9086
  failedRuns,
9025
9087
  totalRuns: pipelines.failureClusters.totalRuns,
9026
9088
  topFailureClass: top?.failureClass,
9027
- exampleRunId: top?.exampleRunId
9089
+ exampleRunId: top?.exampleRunId,
9090
+ citedToolErrorSpans: citedToolErrors.length,
9091
+ omittedToolErrorSpans: Math.max(0, exampleToolErrors.length - citedToolErrors.length)
9028
9092
  }
9029
9093
  }));
9030
9094
  }
@@ -9212,7 +9276,7 @@ async function runTraceInvestigation(opts) {
9212
9276
  analyzeAdoption(opts.spans, { cwds: opts.cwds })
9213
9277
  ]);
9214
9278
  opts.signal?.throwIfAborted();
9215
- const deterministic = deterministicFindings(pipelines, reactions, adoption);
9279
+ const deterministic = deterministicFindings(pipelines, reactions, adoption, opts.spans);
9216
9280
  const agenticRoute = opts.ai && !opts.agenticRegistry ? planTraceAgenticRoute(pipelines, reactions) : void 0;
9217
9281
  const analysis = await analyzeSpans(opts.spans, {
9218
9282
  ai: opts.ai,
package/dist/cli.js CHANGED
@@ -43,7 +43,7 @@ import {
43
43
  writePolicyEvidenceFile,
44
44
  writeSessionIndexFile,
45
45
  writeTraceEvidenceExportFile
46
- } from "./chunk-I4W6DECY.js";
46
+ } from "./chunk-F2OEMHVZ.js";
47
47
 
48
48
  // src/cli.ts
49
49
  import { readFileSync } from "fs";
package/dist/index.js CHANGED
@@ -130,7 +130,7 @@ import {
130
130
  writeSessionIndexFile,
131
131
  writeTraceEvidenceExportFile,
132
132
  writeTraceImprovementArtifacts
133
- } from "./chunk-I4W6DECY.js";
133
+ } from "./chunk-F2OEMHVZ.js";
134
134
 
135
135
  // src/collect.ts
136
136
  async function collectSessions(opts = {}) {
@@ -175,10 +175,11 @@ It must also avoid inventing issues on clean trajectories.
175
175
  | Dataset | Labels used |
176
176
  | --- | --- |
177
177
  | AgentRx | Failure category, failed step, and root-cause step |
178
- | CodeTraceBench | Incorrect and unhelpful action steps, including clean trajectories |
178
+ | CodeTraceBench | Incorrect and unhelpful action steps; solved label-empty rows are clean controls |
179
179
 
180
180
  Use `runAnalystBenchmark` to report recall, precision, F1, root-step accuracy, citation coverage, citation validity, clean-case false positives, repeat agreement, latency, calls, tokens, and known cost.
181
181
  Use `compareAnalystRunners` for paired baseline and candidate comparisons.
182
+ Failed label-empty CodeTraceBench rows are unlabeled, not clean controls.
182
183
 
183
184
  ```ts
184
185
  import {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/traces",
3
- "version": "0.9.17",
3
+ "version": "0.9.18",
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",