@tangle-network/traces 0.8.5 → 0.8.12

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
@@ -4,28 +4,36 @@ import {
4
4
  analyzeReactions,
5
5
  analyzeSpans,
6
6
  buildPolicyEvidenceRecord,
7
+ buildSessionIndexFromRows,
7
8
  commandAnalyzer,
8
9
  commandRedactor,
9
10
  executeUpload,
10
11
  exportTraceEvidenceFile,
11
12
  haloAnalyzer,
13
+ inspectSessionIndex,
12
14
  knownHarnesses,
13
15
  parseSession,
14
16
  parseSince,
15
17
  planUpload,
18
+ readSessionIndexFile,
19
+ renderInspectionReport,
16
20
  resolveAdapter,
17
21
  runExternalAnalyzers,
18
22
  runPipelines,
19
23
  selectAdapters,
20
24
  serializePolicyEvidence,
25
+ serializeSessionIndex,
21
26
  serializeSpans,
22
27
  watchSessions,
28
+ writeInspectionReportFile,
23
29
  writeOtlpFile,
24
30
  writePolicyEvidenceFile,
31
+ writeSessionIndexFile,
25
32
  writeTraceEvidenceExportFile
26
- } from "./chunk-D5OMTM4S.js";
33
+ } from "./chunk-PRRWLKSI.js";
27
34
 
28
35
  // src/cli.ts
36
+ import { readFileSync } from "fs";
29
37
  import { readFile, stat, writeFile } from "fs/promises";
30
38
 
31
39
  // src/report.ts
@@ -187,6 +195,11 @@ function renderAdoption(ar) {
187
195
  }
188
196
 
189
197
  // src/cli.ts
198
+ function packageVersion() {
199
+ const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
200
+ if (typeof pkg.version !== "string" || !pkg.version) throw new Error("package.json is missing version");
201
+ return pkg.version;
202
+ }
190
203
  function parseArgs(argv) {
191
204
  const a = {
192
205
  command: argv[0] === "--help" || argv[0] === "-h" ? "help" : argv[0] ?? "help",
@@ -357,7 +370,8 @@ async function collectSpans(args) {
357
370
  cwd: args.cwd ?? null,
358
371
  mtimeMs: st.mtimeMs
359
372
  };
360
- return { spans: await parseSession(adapter, ref), harness: adapter.harness, sessionCount: 1, cwds: ref.cwd ? [ref.cwd] : [] };
373
+ const spans2 = await parseSession(adapter, ref);
374
+ return { spans: spans2, harness: adapter.harness, sessionCount: 1, cwds: ref.cwd ? [ref.cwd] : [] };
361
375
  }
362
376
  const groups = await discover({ ...args, last: args.last || 1 });
363
377
  const spans = [];
@@ -421,6 +435,39 @@ async function cmdEvidence(args) {
421
435
  process.stdout.write(serializePolicyEvidence(records));
422
436
  }
423
437
  }
438
+ async function cmdIndex(args) {
439
+ const rows = (await collectSessionRows(args)).filter((row) => row.spans.length > 0);
440
+ if (rows.length === 0) throw new Error("no spans found for the given selection");
441
+ const index = await buildSessionIndexFromRows(rows, {
442
+ minLoopOccurrences: args.minLoop,
443
+ selection: {
444
+ command: "index",
445
+ harness: args.harnessExplicit ? args.harness : void 0,
446
+ all: args.all || void 0,
447
+ last: args.last || void 0,
448
+ session: args.session,
449
+ cwd: args.cwd,
450
+ since: args.since
451
+ }
452
+ });
453
+ if (args.out) {
454
+ const path = await writeSessionIndexFile(index, args.out);
455
+ console.log(`session index \u2192 ${path} (${index.totals.sessions} session rows)`);
456
+ } else {
457
+ process.stdout.write(serializeSessionIndex(index));
458
+ }
459
+ }
460
+ async function cmdInspect(args) {
461
+ if (!args.input) throw new Error("inspect needs an index file; run `traces index --out session-index.json` first");
462
+ const index = await readSessionIndexFile(args.input);
463
+ const report = inspectSessionIndex(index);
464
+ if (args.out) {
465
+ const path = await writeInspectionReportFile(report, args.out);
466
+ console.log(`inspection report \u2192 ${path} (${report.totals.findings} finding(s), high ${report.totals.high})`);
467
+ } else {
468
+ process.stdout.write(renderInspectionReport(report));
469
+ }
470
+ }
424
471
  async function cmdExport(args) {
425
472
  if (!args.input) throw new Error("export needs an input file; run `traces export --help` for examples");
426
473
  const format = args.format ?? "auto";
@@ -616,6 +663,8 @@ Commands:
616
663
  list List discovered sessions
617
664
  analyze Run analyst suite + loop/waste pipelines, write a markdown report
618
665
  convert Emit OTLP-JSONL only (HALO: use analyze --analyzer halo)
666
+ index Emit a reusable session index JSON for later investigation
667
+ inspect Read a session index and print ranked improvement findings
619
668
  export Convert evidence/events files to OpenInference JSONL for HALO
620
669
  evidence Emit compact session-evidence JSONL for downstream policy miners
621
670
  watch Online observer: tail active sessions, notify on stuck loops (read-only)
@@ -645,12 +694,18 @@ Options:
645
694
  --no-content upload: strip prompt/response text \u2014 send metadata only
646
695
  --redactor <cmd> upload: external PII scrubber (JSON array stdin\u2192stdout) after the regex pass
647
696
  --yes, -y upload: skip the confirmation prompt
697
+ --version, -v Print the installed traces version
648
698
  --help, -h Show help (use \`traces export --help\` for export examples)
649
699
 
650
700
  Upload env: TANGLE_INGEST_URL (or TANGLE_ORCHESTRATOR_URL), TANGLE_INGEST_API_KEY (or TANGLE_API_KEY), TANGLE_TENANT_ID`);
651
701
  }
652
702
  async function main() {
653
- const args = parseArgs(process.argv.slice(2));
703
+ const rawArgs = process.argv.slice(2);
704
+ if (rawArgs[0] === "--version" || rawArgs[0] === "-v" || rawArgs[0] === "version") {
705
+ console.log(`traces ${packageVersion()}`);
706
+ return;
707
+ }
708
+ const args = parseArgs(rawArgs);
654
709
  if (args.help) {
655
710
  if (args.command === "export" || args.command === "help" && args.input === "export") usageExport();
656
711
  else usage();
@@ -670,6 +725,12 @@ async function main() {
670
725
  case "convert":
671
726
  await cmdConvert(args);
672
727
  break;
728
+ case "index":
729
+ await cmdIndex(args);
730
+ break;
731
+ case "inspect":
732
+ await cmdInspect(args);
733
+ break;
673
734
  case "export":
674
735
  await cmdExport(args);
675
736
  break;
package/dist/index.d.ts CHANGED
@@ -158,6 +158,8 @@ declare const ATTR: {
158
158
  readonly GIT_BRANCH_NAME: "git.branch";
159
159
  /** HEAD short sha at conversion time. */
160
160
  readonly GIT_COMMIT: "git.commit";
161
+ /** How traces resolved the session cwd: recorded cwd, repaired cwd, or span path. */
162
+ readonly REPO_RESOLUTION_SOURCE: "traces.repo_resolution_source";
161
163
  readonly GIT_BRANCH: "tangle.git_branch";
162
164
  readonly HOST: "tangle.host";
163
165
  /** Basename of the session file. (Renamed from the ambiguous `tangle.source`,
@@ -239,8 +241,17 @@ interface ScannedSession {
239
241
  * errors route to `onError` and skip that adapter/session, never aborting. */
240
242
  declare function scanSessions(opts: ScanOptions): AsyncGenerator<ScannedSession>;
241
243
 
244
+ type RepoResolutionSource = 'none' | 'ref-cwd' | 'repaired-cwd' | 'span-path' | 'span-workdir';
242
245
  /** Resource-attribute keys this resolver may stamp. */
243
- type RepoAttrs = Partial<Record<typeof ATTR.SUBJECT_KEY | typeof ATTR.GIT_REPOSITORY | typeof ATTR.GIT_BRANCH_NAME | typeof ATTR.GIT_COMMIT | typeof ATTR.CWD, string>>;
246
+ type RepoAttrs = Partial<Record<typeof ATTR.SUBJECT_KEY | typeof ATTR.GIT_REPOSITORY | typeof ATTR.GIT_BRANCH_NAME | typeof ATTR.GIT_COMMIT | typeof ATTR.CWD, string>> & Partial<Record<typeof ATTR.REPO_RESOLUTION_SOURCE, RepoResolutionSource>>;
247
+ interface RepoResolution {
248
+ /** Resource attributes to stamp onto spans. */
249
+ attrs: RepoAttrs;
250
+ /** Best-known cwd/repo directory after repair or span-path inference. */
251
+ cwd: string | null;
252
+ /** Which signal produced the selected cwd. */
253
+ source: RepoResolutionSource;
254
+ }
244
255
  /**
245
256
  * Normalize a git remote url to `host/owner/repo`, dropping scheme, auth, the
246
257
  * `.git` suffix, and any trailing slash. Handles both `https://` and the
@@ -252,6 +263,7 @@ declare function normalizeRemote(url: string): string | null;
252
263
  * Fail-safe and never throws; see the module doc for the derivation contract.
253
264
  */
254
265
  declare function resolveRepoAttrs(cwd: string | null | undefined): Promise<RepoAttrs>;
266
+ declare function resolveSessionRepoAttrs(cwd: string | null | undefined, spans: readonly OtlpSpan[]): Promise<RepoResolution>;
255
267
  /**
256
268
  * Stamp resolved repo attrs onto every span's attributes (so they land in the
257
269
  * OTLP resource attributes via `toOpenInferenceSpan`). Additive — existing
@@ -351,6 +363,11 @@ declare class GeminiFamilyAdapter implements HarnessTraceAdapter {
351
363
  private readonly homeDirName;
352
364
  constructor(cfg: GeminiFamilyConfig);
353
365
  private chatsRoot;
366
+ /** `<home>/projects.json` maps `{ <absolute-cwd>: <projectName> }`. The session
367
+ * dir name (`tmp/<projectHash>/`) is that projectName for registered projects,
368
+ * so inverting the map recovers cwd. (Unregistered/older dirs are opaque cwd
369
+ * digests and stay null.) Loaded once per locate(). */
370
+ private loadProjectCwds;
354
371
  locate(opts?: LocateOptions): Promise<SessionRef[]>;
355
372
  parse(ref: SessionRef): Promise<OtlpSpan[]>;
356
373
  }
@@ -806,6 +823,7 @@ interface PolicyEvidenceRecord {
806
823
  readonly branch?: string;
807
824
  readonly commit?: string;
808
825
  readonly cwd?: string;
826
+ readonly resolutionSource?: string;
809
827
  };
810
828
  readonly metrics: {
811
829
  readonly spanCount: number;
@@ -847,6 +865,138 @@ declare function collectPolicyEvidence(opts: CollectPolicyEvidenceOptions): Prom
847
865
  declare function serializePolicyEvidence(records: readonly PolicyEvidenceRecord[]): string;
848
866
  declare function writePolicyEvidenceFile(records: readonly PolicyEvidenceRecord[], outPath?: string): Promise<string>;
849
867
 
868
+ interface TraceSessionIndexRow {
869
+ readonly session: PolicyEvidenceRecord['session'];
870
+ readonly repo: PolicyEvidenceRecord['repo'];
871
+ readonly time: {
872
+ readonly firstSpanAt: string | null;
873
+ readonly lastSpanAt: string | null;
874
+ };
875
+ readonly metrics: {
876
+ readonly spanCount: number;
877
+ readonly llmTurnCount: number;
878
+ readonly toolCallCount: number;
879
+ readonly erroredToolCallCount: number;
880
+ readonly inputTokens: number;
881
+ readonly outputTokens: number;
882
+ readonly toolErrorRate: number;
883
+ };
884
+ readonly models: readonly string[];
885
+ readonly tools: PolicyEvidenceRecord['metrics']['tools'];
886
+ readonly signals: PolicyEvidenceRecord['signals'];
887
+ }
888
+ interface TraceIndexedFile {
889
+ readonly kind: 'instruction-doc' | 'evolve-jsonl' | 'evolve-json' | 'reflection' | 'handoff' | 'other';
890
+ readonly path: string;
891
+ readonly bytes: number;
892
+ readonly mtimeMs: number;
893
+ readonly lines?: number;
894
+ readonly jsonlRows?: number;
895
+ readonly markdown?: {
896
+ readonly headings: number;
897
+ readonly hasToc: boolean;
898
+ };
899
+ readonly jsonl?: {
900
+ readonly rows: number;
901
+ readonly invalidRows: number;
902
+ readonly keys: Record<string, number>;
903
+ };
904
+ }
905
+ interface TraceContextRoot {
906
+ readonly root: string;
907
+ readonly files: readonly TraceIndexedFile[];
908
+ }
909
+ interface TraceContextIndex {
910
+ readonly totals: {
911
+ readonly roots: number;
912
+ readonly files: number;
913
+ readonly instructionDocs: number;
914
+ readonly evolveFiles: number;
915
+ readonly jsonlRows: number;
916
+ readonly invalidJsonlRows: number;
917
+ };
918
+ readonly roots: readonly TraceContextRoot[];
919
+ }
920
+ interface TraceSessionIndex {
921
+ readonly schemaVersion: 1;
922
+ readonly kind: 'traces.session_index';
923
+ readonly generatedAt: string;
924
+ readonly selection?: Record<string, unknown>;
925
+ readonly totals: {
926
+ readonly sessions: number;
927
+ readonly spans: number;
928
+ readonly llmTurns: number;
929
+ readonly toolCalls: number;
930
+ readonly erroredToolCalls: number;
931
+ readonly inputTokens: number;
932
+ readonly outputTokens: number;
933
+ readonly stuckLoopSessions: number;
934
+ readonly stuckLoops: number;
935
+ readonly harnesses: readonly string[];
936
+ readonly repos: readonly string[];
937
+ readonly models: readonly string[];
938
+ readonly tools: readonly string[];
939
+ };
940
+ readonly context?: TraceContextIndex;
941
+ readonly sessions: readonly TraceSessionIndexRow[];
942
+ }
943
+ interface BuildSessionIndexOptions extends Pick<BuildPolicyEvidenceOptions, 'generatedAt' | 'minLoopOccurrences'> {
944
+ readonly selection?: Record<string, unknown>;
945
+ /** Index nearby local docs/artifacts for joins. Defaults to true in scan paths. */
946
+ readonly includeContext?: boolean;
947
+ }
948
+ interface CollectSessionIndexOptions extends ScanOptions, BuildSessionIndexOptions {
949
+ }
950
+ declare function buildSessionIndex(records: readonly PolicyEvidenceRecord[], opts?: BuildSessionIndexOptions & {
951
+ context?: TraceContextIndex;
952
+ }): TraceSessionIndex;
953
+ declare function buildSessionIndexFromRows(rows: readonly {
954
+ ref: SessionRef;
955
+ spans: readonly OtlpSpan[];
956
+ }[], opts?: BuildSessionIndexOptions): Promise<TraceSessionIndex>;
957
+ declare function collectSessionIndex(opts?: CollectSessionIndexOptions): Promise<TraceSessionIndex>;
958
+ declare function serializeSessionIndex(index: TraceSessionIndex): string;
959
+ declare function writeSessionIndexFile(index: TraceSessionIndex, outPath?: string): Promise<string>;
960
+
961
+ type TraceInspectionSeverity = 'high' | 'medium' | 'low';
962
+ type TraceInspectionArea = 'index' | 'session' | 'repo' | 'context';
963
+ interface TraceInspectionFinding {
964
+ readonly id: string;
965
+ readonly severity: TraceInspectionSeverity;
966
+ readonly area: TraceInspectionArea;
967
+ readonly title: string;
968
+ readonly impact: number;
969
+ readonly evidence: readonly string[];
970
+ readonly next: string;
971
+ readonly refs?: readonly string[];
972
+ }
973
+ interface TraceInspectionReport {
974
+ readonly schemaVersion: 1;
975
+ readonly kind: 'traces.inspection_report';
976
+ readonly generatedAt: string;
977
+ readonly source: {
978
+ readonly indexGeneratedAt?: string;
979
+ readonly sessions: number;
980
+ readonly contextFiles: number;
981
+ };
982
+ readonly totals: {
983
+ readonly findings: number;
984
+ readonly high: number;
985
+ readonly medium: number;
986
+ readonly low: number;
987
+ };
988
+ readonly findings: readonly TraceInspectionFinding[];
989
+ }
990
+ interface InspectSessionIndexOptions {
991
+ readonly generatedAt?: string;
992
+ readonly maxFindings?: number;
993
+ }
994
+ declare function inspectSessionIndex(index: TraceSessionIndex, opts?: InspectSessionIndexOptions): TraceInspectionReport;
995
+ declare function renderInspectionReport(report: TraceInspectionReport): string;
996
+ declare function serializeInspectionReport(report: TraceInspectionReport): string;
997
+ declare function readSessionIndexFile(path: string): Promise<TraceSessionIndex>;
998
+ declare function writeInspectionReportFile(report: TraceInspectionReport, outPath?: string): Promise<string>;
999
+
850
1000
  type JsonObject = Record<string, unknown>;
851
1001
  type TraceEvidenceInputFormat = 'policy-evidence' | 'sandbox-events' | 'openinference';
852
1002
  type TraceEvidenceFormatOption = TraceEvidenceInputFormat | 'auto';
@@ -1169,4 +1319,4 @@ interface ExecuteOptions {
1169
1319
  /** Send the NEW items (or, on dryRun, write the redacted OTLP that would send). */
1170
1320
  declare function executeUpload(plan: UploadPlan, opts?: ExecuteOptions): Promise<UploadResult>;
1171
1321
 
1172
- export { ACTOR_ATTR, ATTR, type Actor, type AdoptionOptions, type AdoptionReport, AmpAdapter, type AnalyzeOptions, type AnalyzeResult, type BuildPolicyEvidenceOptions, CODING_REDACTION_RULES, CONTENT_CAP, CORRECTIVE_REACTIONS, ClaudeAdapter, CodexAdapter, type CollectOptions, type CollectPolicyEvidenceOptions, CopilotAdapter, DEFAULT_HARNESS, type ExecuteOptions, type ExternalAnalysisResult, type ExternalAnalyzer, FactoryAdapter, ForgeAdapter, GeminiAdapter, type HarnessTraceAdapter, INGEST_SOURCE_CLI, type LocateOptions, type ObservedLoop, type ObserverOptions, OpencodeAdapter, type OtlpSpan, type OtlpSpanKind, type OtlpStatusCode, PiAdapter, type PipelineOptions, type PipelineReport, type PlanOptions, type PolicyEvidenceLoopSummary, type PolicyEvidenceRecord, type PolicyEvidenceToolSummary, QwenAdapter, REACTIONS, type Reaction, type ReactionReport, type ReactionSessionReport, type Redactor, type RepoAttrs, type RunResult, type RuntimeTrace, type ScanOptions, type ScannedSession, type SessionBatch, type SessionRef, type SpanInput, type SpanRedaction, TRACES_REDACTION_RULES, type TraceEvidenceExportOptions, type TraceEvidenceExportResult, type TraceEvidenceFormatOption, type TraceEvidenceInputFormat, type TriggerPair, type UploadBackend, type UploadItem, type UploadPlan, type UploadRecord, type UploadResult, type UploadState, type UserPromptInput, alreadyUploaded, analyzeAdoption, analyzeReactions, analyzeSpans, applyRedactor, buildPolicyEvidenceRecord, capText, classifyReaction, claudeActor, codexActor, collectPolicyEvidence, collectSessions, commandAnalyzer, commandRedactor, countSkillRunsJsonl, executeUpload, exportTraceEvidenceFile, exportTraceEvidenceRows, exportTraceEvidenceText, haloAnalyzer, knownHarnesses, listAdapters, loadState, looksLikeAgentPrompt, normalizeRemote, parseIsoToEpochMs, parseSession, parseSince, planUpload, redactSpans, resolveAdapter, resolveRepoAttrs, runCommand, runExternalAnalyzers, runPipelines, saveState, scanSessions, selectAdapters, serializePolicyEvidence, serializeSpans, sessionHash, span, stampRepoAttrs, textIsSynthetic, toOpenInferenceSpan, toRuntimeStore, toTraceSpanEvents, uploadKey, userPromptSpan, watchSessions, writeOtlpFile, writePolicyEvidenceFile, writeTraceEvidenceExportFile };
1322
+ export { ACTOR_ATTR, ATTR, type Actor, type AdoptionOptions, type AdoptionReport, AmpAdapter, type AnalyzeOptions, type AnalyzeResult, type BuildPolicyEvidenceOptions, type BuildSessionIndexOptions, CODING_REDACTION_RULES, CONTENT_CAP, CORRECTIVE_REACTIONS, ClaudeAdapter, CodexAdapter, type CollectOptions, type CollectPolicyEvidenceOptions, type CollectSessionIndexOptions, CopilotAdapter, DEFAULT_HARNESS, type ExecuteOptions, type ExternalAnalysisResult, type ExternalAnalyzer, FactoryAdapter, ForgeAdapter, GeminiAdapter, type HarnessTraceAdapter, INGEST_SOURCE_CLI, type InspectSessionIndexOptions, type LocateOptions, type ObservedLoop, type ObserverOptions, OpencodeAdapter, type OtlpSpan, type OtlpSpanKind, type OtlpStatusCode, PiAdapter, type PipelineOptions, type PipelineReport, type PlanOptions, type PolicyEvidenceLoopSummary, type PolicyEvidenceRecord, type PolicyEvidenceToolSummary, QwenAdapter, REACTIONS, type Reaction, type ReactionReport, type ReactionSessionReport, type Redactor, type RepoAttrs, type RepoResolution, type RepoResolutionSource, type RunResult, type RuntimeTrace, type ScanOptions, type ScannedSession, type SessionBatch, type SessionRef, type SpanInput, type SpanRedaction, TRACES_REDACTION_RULES, type TraceContextIndex, type TraceContextRoot, type TraceEvidenceExportOptions, type TraceEvidenceExportResult, type TraceEvidenceFormatOption, type TraceEvidenceInputFormat, type TraceIndexedFile, type TraceInspectionArea, type TraceInspectionFinding, type TraceInspectionReport, type TraceInspectionSeverity, type TraceSessionIndex, type TraceSessionIndexRow, type TriggerPair, type UploadBackend, type UploadItem, type UploadPlan, type UploadRecord, type UploadResult, type UploadState, type UserPromptInput, alreadyUploaded, analyzeAdoption, analyzeReactions, analyzeSpans, applyRedactor, buildPolicyEvidenceRecord, buildSessionIndex, buildSessionIndexFromRows, capText, classifyReaction, claudeActor, codexActor, collectPolicyEvidence, collectSessionIndex, collectSessions, commandAnalyzer, commandRedactor, countSkillRunsJsonl, executeUpload, exportTraceEvidenceFile, exportTraceEvidenceRows, exportTraceEvidenceText, haloAnalyzer, inspectSessionIndex, knownHarnesses, listAdapters, loadState, looksLikeAgentPrompt, normalizeRemote, parseIsoToEpochMs, parseSession, parseSince, planUpload, readSessionIndexFile, redactSpans, renderInspectionReport, resolveAdapter, resolveRepoAttrs, resolveSessionRepoAttrs, runCommand, runExternalAnalyzers, runPipelines, saveState, scanSessions, selectAdapters, serializeInspectionReport, serializePolicyEvidence, serializeSessionIndex, serializeSpans, sessionHash, span, stampRepoAttrs, textIsSynthetic, toOpenInferenceSpan, toRuntimeStore, toTraceSpanEvents, uploadKey, userPromptSpan, watchSessions, writeInspectionReportFile, writeOtlpFile, writePolicyEvidenceFile, writeSessionIndexFile, writeTraceEvidenceExportFile };
package/dist/index.js CHANGED
@@ -24,11 +24,14 @@ import {
24
24
  analyzeSpans,
25
25
  applyRedactor,
26
26
  buildPolicyEvidenceRecord,
27
+ buildSessionIndex,
28
+ buildSessionIndexFromRows,
27
29
  capText,
28
30
  classifyReaction,
29
31
  claudeActor,
30
32
  codexActor,
31
33
  collectPolicyEvidence,
34
+ collectSessionIndex,
32
35
  commandAnalyzer,
33
36
  commandRedactor,
34
37
  countSkillRunsJsonl,
@@ -37,6 +40,7 @@ import {
37
40
  exportTraceEvidenceRows,
38
41
  exportTraceEvidenceText,
39
42
  haloAnalyzer,
43
+ inspectSessionIndex,
40
44
  knownHarnesses,
41
45
  listAdapters,
42
46
  loadState,
@@ -46,16 +50,21 @@ import {
46
50
  parseSession,
47
51
  parseSince,
48
52
  planUpload,
53
+ readSessionIndexFile,
49
54
  redactSpans,
55
+ renderInspectionReport,
50
56
  resolveAdapter,
51
57
  resolveRepoAttrs,
58
+ resolveSessionRepoAttrs,
52
59
  runCommand,
53
60
  runExternalAnalyzers,
54
61
  runPipelines,
55
62
  saveState,
56
63
  scanSessions,
57
64
  selectAdapters,
65
+ serializeInspectionReport,
58
66
  serializePolicyEvidence,
67
+ serializeSessionIndex,
59
68
  serializeSpans,
60
69
  sessionHash,
61
70
  span,
@@ -67,10 +76,12 @@ import {
67
76
  uploadKey,
68
77
  userPromptSpan,
69
78
  watchSessions,
79
+ writeInspectionReportFile,
70
80
  writeOtlpFile,
71
81
  writePolicyEvidenceFile,
82
+ writeSessionIndexFile,
72
83
  writeTraceEvidenceExportFile
73
- } from "./chunk-D5OMTM4S.js";
84
+ } from "./chunk-PRRWLKSI.js";
74
85
 
75
86
  // src/collect.ts
76
87
  async function collectSessions(opts = {}) {
@@ -123,11 +134,14 @@ export {
123
134
  applyRedactor,
124
135
  buildDefaultAnalystRegistry,
125
136
  buildPolicyEvidenceRecord,
137
+ buildSessionIndex,
138
+ buildSessionIndexFromRows,
126
139
  capText,
127
140
  classifyReaction,
128
141
  claudeActor,
129
142
  codexActor,
130
143
  collectPolicyEvidence,
144
+ collectSessionIndex,
131
145
  collectSessions,
132
146
  commandAnalyzer,
133
147
  commandRedactor,
@@ -139,6 +153,7 @@ export {
139
153
  exportTraceEvidenceText,
140
154
  haloAnalyzer,
141
155
  hostedClientFromEnv,
156
+ inspectSessionIndex,
142
157
  knownHarnesses,
143
158
  listAdapters,
144
159
  loadState,
@@ -149,18 +164,23 @@ export {
149
164
  parseSession,
150
165
  parseSince,
151
166
  planUpload,
167
+ readSessionIndexFile,
152
168
  redactSpans,
153
169
  redactString,
154
170
  redactValue,
171
+ renderInspectionReport,
155
172
  resolveAdapter,
156
173
  resolveRepoAttrs,
174
+ resolveSessionRepoAttrs,
157
175
  runCommand,
158
176
  runExternalAnalyzers,
159
177
  runPipelines,
160
178
  saveState,
161
179
  scanSessions,
162
180
  selectAdapters,
181
+ serializeInspectionReport,
163
182
  serializePolicyEvidence,
183
+ serializeSessionIndex,
164
184
  serializeSpans,
165
185
  sessionHash,
166
186
  span,
@@ -172,7 +192,9 @@ export {
172
192
  uploadKey,
173
193
  userPromptSpan,
174
194
  watchSessions,
195
+ writeInspectionReportFile,
175
196
  writeOtlpFile,
176
197
  writePolicyEvidenceFile,
198
+ writeSessionIndexFile,
177
199
  writeTraceEvidenceExportFile
178
200
  };
package/install.sh ADDED
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ PACKAGE="@tangle-network/traces"
5
+ VERSION="${TRACES_VERSION:-latest}"
6
+ PREFIX="${TRACES_PREFIX:-}"
7
+
8
+ usage() {
9
+ cat <<'USAGE'
10
+ Install the traces CLI from npm.
11
+
12
+ Usage:
13
+ curl -fsSL https://raw.githubusercontent.com/tangle-network/traces/main/install.sh | bash
14
+ ./install.sh [--version <version>] [--prefix <dir>]
15
+
16
+ Environment:
17
+ TRACES_VERSION npm version or tag to install (default: latest)
18
+ TRACES_PREFIX npm global prefix to use when the default is not writable
19
+ USAGE
20
+ }
21
+
22
+ while [ "$#" -gt 0 ]; do
23
+ case "$1" in
24
+ --version)
25
+ [ "${2:-}" ] || { echo "missing value for --version" >&2; exit 2; }
26
+ VERSION="$2"
27
+ shift 2
28
+ ;;
29
+ --prefix)
30
+ [ "${2:-}" ] || { echo "missing value for --prefix" >&2; exit 2; }
31
+ PREFIX="$2"
32
+ shift 2
33
+ ;;
34
+ -h|--help)
35
+ usage
36
+ exit 0
37
+ ;;
38
+ *)
39
+ echo "unknown argument: $1" >&2
40
+ usage >&2
41
+ exit 2
42
+ ;;
43
+ esac
44
+ done
45
+
46
+ if ! command -v node >/dev/null 2>&1; then
47
+ echo "Node.js >=22 is required before installing traces." >&2
48
+ exit 1
49
+ fi
50
+
51
+ node_version="$(node -e "process.stdout.write(process.versions.node)")"
52
+ node_major="${node_version%%.*}"
53
+ if [ "$node_major" -lt 22 ]; then
54
+ echo "Node.js >=22 is required; found v$node_version." >&2
55
+ exit 1
56
+ fi
57
+
58
+ if ! command -v npm >/dev/null 2>&1; then
59
+ echo "npm is required before installing traces." >&2
60
+ exit 1
61
+ fi
62
+
63
+ install_args=(install -g "${PACKAGE}@${VERSION}")
64
+ npm_prefix="$(npm prefix -g)"
65
+ install_prefix="$npm_prefix"
66
+
67
+ if [ -n "$PREFIX" ]; then
68
+ mkdir -p "$PREFIX"
69
+ install_args+=(--prefix "$PREFIX")
70
+ install_prefix="$PREFIX"
71
+ else
72
+ if [ ! -w "$npm_prefix" ]; then
73
+ install_prefix="$HOME/.local"
74
+ mkdir -p "$install_prefix"
75
+ install_args+=(--prefix "$install_prefix")
76
+ echo "npm global prefix is not writable; installing into $install_prefix"
77
+ fi
78
+ fi
79
+
80
+ npm "${install_args[@]}"
81
+
82
+ bin_dir="$install_prefix/bin"
83
+ if [ -x "$bin_dir/traces" ]; then
84
+ traces_cmd="$bin_dir/traces"
85
+ elif command -v traces >/dev/null 2>&1; then
86
+ traces_cmd="traces"
87
+ else
88
+ echo "Installed ${PACKAGE}@${VERSION}, but the traces binary was not found at $bin_dir/traces or on PATH." >&2
89
+ echo "Add this to PATH: $bin_dir" >&2
90
+ exit 1
91
+ fi
92
+
93
+ version_output="$("$traces_cmd" --version 2>/dev/null || true)"
94
+ case "$version_output" in
95
+ traces\ [0-9]*.[0-9]*.[0-9]*) echo "$version_output" ;;
96
+ *) echo "traces installed: $traces_cmd" ;;
97
+ esac
98
+ case ":$PATH:" in
99
+ *":$bin_dir:"*) ;;
100
+ *) echo "Add this to PATH for future shells: $bin_dir" ;;
101
+ esac
102
+ echo "Run: traces analyze --harness claude-code --last 1"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/traces",
3
- "version": "0.8.5",
3
+ "version": "0.8.12",
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",
@@ -36,6 +36,7 @@
36
36
  },
37
37
  "files": [
38
38
  "dist",
39
+ "install.sh",
39
40
  "README.md"
40
41
  ],
41
42
  "engines": {
@@ -56,6 +57,7 @@
56
57
  "scripts": {
57
58
  "dev": "tsx src/cli.ts",
58
59
  "build": "tsup src/index.ts src/cli.ts --format esm --target node22 --clean --dts",
60
+ "check:package": "node scripts/check-package-bin.mjs",
59
61
  "test": "vitest run",
60
62
  "test:watch": "vitest",
61
63
  "typecheck": "tsc --noEmit"