@tangle-network/traces 0.9.0 → 0.9.1

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/cli.js CHANGED
@@ -3,9 +3,7 @@ import {
3
3
  ACTOR_ATTR,
4
4
  ATTR,
5
5
  CORRUPTION_RECEIPT_DISPLAY_LIMIT,
6
- analyzeAdoption,
7
- analyzeReactions,
8
- analyzeSpans,
6
+ appendAll,
9
7
  buildPolicyEvidenceRecord,
10
8
  buildSessionIndexFromRows,
11
9
  commandAnalyzer,
@@ -23,14 +21,8 @@ import {
23
21
  parseSince,
24
22
  planUpload,
25
23
  readSessionIndexFile,
26
- renderAdoption,
27
24
  renderInspectionReport,
28
- renderPipelines,
29
- renderReactions,
30
- renderReport,
31
25
  resolveAdapter,
32
- runExternalAnalyzers,
33
- runPipelines,
34
26
  runTraceImprovement,
35
27
  runTraceInvestigation,
36
28
  saveReport,
@@ -41,7 +33,6 @@ import {
41
33
  serializeTraceStreamEvent,
42
34
  sessionIdFromAttributes,
43
35
  streamSessions,
44
- summarizeDeterministicSignals,
45
36
  traceStreamEventsFromSpans,
46
37
  watchSessions,
47
38
  writeInspectionReportFile,
@@ -49,11 +40,11 @@ import {
49
40
  writePolicyEvidenceFile,
50
41
  writeSessionIndexFile,
51
42
  writeTraceEvidenceExportFile
52
- } from "./chunk-5SBXL62V.js";
43
+ } from "./chunk-RUG26PIS.js";
53
44
 
54
45
  // src/cli.ts
55
46
  import { readFileSync } from "fs";
56
- import { readFile, stat, writeFile } from "fs/promises";
47
+ import { readFile, stat } from "fs/promises";
57
48
  import { basename, resolve } from "path";
58
49
  function packageVersion() {
59
50
  const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
@@ -226,7 +217,7 @@ async function buildAxService() {
226
217
  }
227
218
  const apiURL = process.env.OPENAI_BASE_URL || void 0;
228
219
  const { AxAI } = await import("@ax-llm/ax");
229
- return new AxAI({ name: "openai", apiKey, ...apiURL ? { apiURL } : {} });
220
+ return AxAI.create({ name: "openai", apiKey, ...apiURL ? { apiURL } : {} });
230
221
  }
231
222
  async function cmdList(args) {
232
223
  const groups = await discover({ ...args, last: args.last || 20 });
@@ -303,7 +294,7 @@ async function collectSpans(args) {
303
294
  if (refs.length > 0) harnesses.push(adapter.harness);
304
295
  for (const ref of refs) {
305
296
  const parsed = await parseSession(adapter, ref);
306
- spans.push(...parsed);
297
+ appendAll(spans, parsed);
307
298
  sources.push(selectedSessionSource(ref, parsed));
308
299
  if (ref.cwd) cwds.push(ref.cwd);
309
300
  }
@@ -438,52 +429,14 @@ async function loadExportAttributes(args) {
438
429
  return attributes;
439
430
  }
440
431
  async function cmdAnalyze(args) {
441
- const { spans, harness, cwds, sources } = await collectSpans(args);
442
- if (spans.length === 0) throw new Error("no spans found for the given selection");
443
- const ai = args.llm ? await buildAxService() : void 0;
444
- const { otlpPath, execution, result } = await analyzeSpans(spans, {
445
- ai,
446
- model: args.model,
447
- budgetUsd: args.budget,
448
- otlpOutPath: args.otlp,
449
- log: (msg) => process.stderr.write(`${msg}
450
- `)
451
- });
452
- const pipelines = await runPipelines(spans, { minLoopOccurrences: args.minLoop });
453
- const reactions = analyzeReactions(spans);
454
- const adoption = await analyzeAdoption(spans, { cwds });
455
- const deterministic = summarizeDeterministicSignals(pipelines, reactions);
456
- let report = `${renderReport(result, {
457
- harness,
458
- sessionCount: adoption.identifiedSessionCount,
459
- unassignedTraceCount: adoption.unassignedTraceCount,
460
- spanCount: spans.length,
461
- otlpPath,
462
- execution,
463
- deterministic,
464
- sources
465
- })}
466
- ${renderPipelines(pipelines)}
467
- ${renderReactions(reactions)}
468
- ${renderAdoption(adoption)}`;
469
- if (args.analyzers.length > 0 && otlpPath) {
470
- const engines = externalAnalyzersFromArgs(args);
471
- const results = await runExternalAnalyzers(otlpPath, engines, { prompt: args.analyzerPrompt });
472
- for (const r of results) {
473
- report += `
474
-
475
- ## ${r.analyzer} (external analyzer)
476
-
477
- ${r.ok ? r.output || "(no output)" : `failed: ${r.error}`}`;
478
- }
479
- }
432
+ const result = await investigate(args, { loadDefaultConfig: false });
480
433
  if (args.out) {
481
- await writeFile(args.out, report, "utf8");
434
+ await saveReport(args.out, result.report);
482
435
  console.log(
483
- `report \u2192 ${args.out} (${result.findings.length} findings, ${pipelines.stuckLoops.findings.length} loops, OTLP: ${otlpPath})`
436
+ `report \u2192 ${args.out} (${result.findings.length} findings, ${result.pipelines.stuckLoops.findings.length} loops, OTLP: ${result.otlpPath})`
484
437
  );
485
438
  } else {
486
- console.log(report);
439
+ console.log(result.report);
487
440
  }
488
441
  }
489
442
  async function collectImportedSpans(args) {
@@ -521,11 +474,20 @@ function externalAnalyzersFromArgs(args) {
521
474
  );
522
475
  }
523
476
  async function cmdInvestigate(args) {
477
+ const result = await investigate(args);
478
+ if (args.out) {
479
+ await saveReport(args.out, result.report);
480
+ console.log(`investigation report \u2192 ${args.out} (${result.findings.length} findings with actions, OTLP: ${result.otlpPath})`);
481
+ } else {
482
+ console.log(result.report);
483
+ }
484
+ }
485
+ async function investigate(args, options = {}) {
524
486
  const { spans, harness, cwds, sources } = await collectSpans(args);
525
487
  if (spans.length === 0) throw new Error("no spans found for the given selection");
526
- const config = await loadTracesConfig(args.config);
488
+ const config = args.config !== void 0 || options.loadDefaultConfig !== false ? await loadTracesConfig(args.config) : void 0;
527
489
  const ai = args.llm ? await buildAxService() : void 0;
528
- const result = await runTraceInvestigation(mergeTracesConfig({
490
+ return runTraceInvestigation(mergeTracesConfig({
529
491
  spans,
530
492
  harness,
531
493
  sources,
@@ -540,12 +502,6 @@ async function cmdInvestigate(args) {
540
502
  log: (msg) => process.stderr.write(`${msg}
541
503
  `)
542
504
  }, config));
543
- if (args.out) {
544
- await saveReport(args.out, result.report);
545
- console.log(`investigation report \u2192 ${args.out} (${result.findings.length} findings with actions, OTLP: ${result.otlpPath})`);
546
- } else {
547
- console.log(result.report);
548
- }
549
505
  }
550
506
  async function cmdImprove(args) {
551
507
  const { spans, harness, cwds, sources } = await collectSpans(args);
package/dist/index.d.ts CHANGED
@@ -815,13 +815,9 @@ declare function analyzeReactions(spans: readonly OtlpSpan[]): ReactionReport;
815
815
  * 2. per-skill invocation frequency
816
816
  * 3. subagent (Task/Agent) spawn frequency
817
817
  *
818
- * CRITICAL undercount fix: the trace-level `Skill` tool-use count only sees
819
- * skills a session invoked *interactively*. Skills dispatched inside an
820
- * automation loop (e.g. `/evolve`, `/converge`) are logged to
821
- * `.evolve/skill-runs.jsonl` under the session's cwd and never surface as a
822
- * `Skill` tool span — historically ~370× more runs than the trace count. So we
823
- * read those files too and report "explicit invocations" and "loop-dispatched
824
- * runs" SEPARATELY, so neither silently reads as zero.
818
+ * A repository's `.evolve/skill-runs.jsonl` is historical context, not session
819
+ * evidence, unless a row carries the selected session ID. This keeps old runs
820
+ * from being attributed to the current trace.
825
821
  */
826
822
 
827
823
  interface AdoptionReport {
@@ -843,6 +839,11 @@ interface AdoptionReport {
843
839
  sessionsWithMaterializedSkills: number;
844
840
  /** Sessions with tool inputs that reference a SKILL.md path. */
845
841
  sessionsWithSkillFileReference: number;
842
+ /** Skill documents opened by a successful captured shell-read command.
843
+ * Inspection is not evidence that the skill changed the outcome. */
844
+ skillDocumentReads: Record<string, number>;
845
+ /** Total observed skill-document reads. */
846
+ totalSkillDocumentReads: number;
846
847
  /** Explicit `Skill` tool invocations per skill name, corpus-wide. */
847
848
  skillInvocations: Record<string, number>;
848
849
  /** Total explicit `Skill` tool invocations. */
@@ -853,19 +854,18 @@ interface AdoptionReport {
853
854
  totalSubagentSpawns: number;
854
855
  /** Sessions that spawned ≥1 subagent. */
855
856
  sessionsWithSubagent: number;
856
- /** Loop-dispatched skill runs per skill, read from `.evolve/skill-runs.jsonl`
857
- * (NOT visible at trace level — counted separately to avoid silent zeros). */
857
+ /** Loop-dispatched skill runs whose row names a selected session ID. */
858
858
  loopDispatchedRuns: Record<string, number>;
859
- /** Total loop-dispatched skill runs. */
859
+ /** Total session-linked loop-dispatched skill runs. */
860
860
  totalLoopDispatchedRuns: number;
861
861
  /** `.evolve/skill-runs.jsonl` files that were read. */
862
862
  skillRunFilesRead: number;
863
+ /** Same-repository loop history without a selected session ID. Never treat
864
+ * this as evidence that a selected session used a skill. */
865
+ unlinkedLoopDispatchedRuns: Record<string, number>;
866
+ /** Total unlinked same-repository loop history rows. */
867
+ totalUnlinkedLoopDispatchedRuns: number;
863
868
  }
864
- /**
865
- * Count loop-dispatched skill runs from a `.evolve/skill-runs.jsonl` file's raw
866
- * contents. Each line records one or more skills under `skills` (array) or
867
- * `skill` (string) — the schema varies across producers, so accept both.
868
- */
869
869
  declare function countSkillRunsJsonl(raw: string): Record<string, number>;
870
870
  interface AdoptionOptions {
871
871
  /** Session cwds to probe for `.evolve/skill-runs.jsonl`. The CLI passes the
package/dist/index.js CHANGED
@@ -115,7 +115,7 @@ import {
115
115
  writeSessionIndexFile,
116
116
  writeTraceEvidenceExportFile,
117
117
  writeTraceImprovementArtifacts
118
- } from "./chunk-5SBXL62V.js";
118
+ } from "./chunk-RUG26PIS.js";
119
119
 
120
120
  // src/collect.ts
121
121
  async function collectSessions(opts = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/traces",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
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",
@@ -44,8 +44,8 @@
44
44
  "node": ">=22"
45
45
  },
46
46
  "dependencies": {
47
- "@ax-llm/ax": "^19.0.45",
48
- "@tangle-network/agent-eval": "^0.118.3"
47
+ "@ax-llm/ax": "^23.0.1",
48
+ "@tangle-network/agent-eval": "^0.122.8"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/node": "^22.0.0",