@tangle-network/traces 0.10.3 → 0.11.2

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.d.ts CHANGED
@@ -1,13 +1,205 @@
1
- import { ToolUseMetrics, InMemoryTraceStore } from '@tangle-network/agent-eval';
1
+ import { TraceValidation, SpanKind, Outcome } from '@tangle-network/agent-trace-contract';
2
+ export { Capability, ConformanceFinding, ContractSpan, SpanLink, TraceValidation } from '@tangle-network/agent-trace-contract';
3
+ import { ToolUseMetrics, InMemoryTraceStore, CounterfactualRunner, CounterfactualContext, TraceEmitter, TraceStore } from '@tangle-network/agent-eval';
2
4
  import { StuckLoopReport, FailureClusterReport } from '@tangle-network/agent-eval/pipelines';
3
5
  import { TraceAnalystDefinition, TraceAnalysisEngine, AnalystRegistry, AnalystFinding, buildDefaultAnalystRegistry, AnalystRunSummary, AnalystRunResult, Analyst } from '@tangle-network/agent-eval/analyst';
4
6
  export { Analyst, AnalystContext, AnalystFinding, AnalystRegistry, buildDefaultAnalystRegistry, makeFinding } from '@tangle-network/agent-eval/analyst';
5
7
  import { ExecutionReport } from '@tangle-network/agent-eval/contract';
6
8
  import { TraceAnalysisStore, RedactionRule, RedactionReport } from '@tangle-network/agent-eval/traces';
7
9
  export { DEFAULT_REDACTION_RULES, ErrorCluster, RedactionReport, RedactionRule, TraceAnalysisStore, redactString, redactValue } from '@tangle-network/agent-eval/traces';
10
+ import { SpawnEvent, NodeStatus, Runtime, Budget, Spend } from '@tangle-network/agent-runtime/kernel';
11
+ import { SupervisorRunNodeRole, SupervisorRunReader, SupervisorRunSources } from '@tangle-network/agent-eval/supervisor-run';
8
12
  import { TraceSpanEvent } from '@tangle-network/agent-eval/hosted';
9
13
  export { HostedClient, createHostedClient, hostedClientFromEnv } from '@tangle-network/agent-eval/hosted';
10
14
 
15
+ /**
16
+ * The INBOUND path: read OTLP-JSONL that some other system emitted and hand it
17
+ * to the same analysis pipeline the adapters feed.
18
+ *
19
+ * The adapters (`src/adapters/`) exist because Claude Code, Codex, OpenCode and
20
+ * friends write proprietary session logs we do not control, so somebody has to
21
+ * translate. A system you DO control should not need one: emit
22
+ * `@tangle-network/agent-trace-contract` spans and point `--otlp` at the file.
23
+ *
24
+ * Two rules govern everything here:
25
+ *
26
+ * 1. **Never throw on foreign input.** A tool that crashes on somebody else's
27
+ * trace cannot read "any AI system". A malformed line, a missing timestamp, a
28
+ * link pointing at nothing — each becomes a counted, named issue and the run
29
+ * continues on what is readable.
30
+ * 2. **Validate what the PRODUCER wrote.** {@link readOtlpInput} runs
31
+ * `validateTraceSpans` over the raw rows, before this module normalizes
32
+ * anything, so the report tells the producer what to fix rather than
33
+ * describing our own repairs back to them.
34
+ */
35
+
36
+ /** Why one row of an OTLP file did not become an analyzable span AT ALL. */
37
+ type OtlpIngestIssueKind = 'unparseable-line' | 'not-an-object' | 'missing-span-id' | 'unreadable-timestamp' | 'conflicting-span-id';
38
+ interface OtlpIngestIssue {
39
+ readonly kind: OtlpIngestIssueKind;
40
+ readonly file: string;
41
+ /** 1-indexed line within `file`. */
42
+ readonly line: number;
43
+ readonly detail: string;
44
+ }
45
+ /** Which unusable field cost a span one measurement, without costing it its existence. */
46
+ type OtlpWithheldFieldKind = 'negative-duration';
47
+ /**
48
+ * A row that DID become a span, with one unusable field withheld.
49
+ *
50
+ * This is a different event from an {@link OtlpIngestIssue} and the two must
51
+ * never be merged. A span whose `end_time` precedes its `start_time` has an
52
+ * unusable INTERVAL — it does not have an unusable identity, name, tool name or
53
+ * status. Dropping the whole span for it silently deleted a real tool call from
54
+ * every count in the report, which is a worse failure than the wrong duration
55
+ * it was avoiding: a wrong number is visible and a missing row is not.
56
+ *
57
+ * So the span survives, its interval is withheld rather than repaired (no
58
+ * synthesized end time enters any total), and the withholding is reported
59
+ * here. The contract's own `negative-duration` finding independently marks
60
+ * `latency-analysis` unavailable, so every table that prints a duration is
61
+ * already gated.
62
+ */
63
+ interface OtlpFieldWithheld {
64
+ readonly kind: OtlpWithheldFieldKind;
65
+ /** The span field that could not be used. */
66
+ readonly field: string;
67
+ readonly file: string;
68
+ /** 1-indexed line within `file`. */
69
+ readonly line: number;
70
+ readonly detail: string;
71
+ }
72
+ /**
73
+ * A span field this package ANALYSES as something other than what the producer
74
+ * wrote.
75
+ *
76
+ * Every one of these is a place the reader has to substitute a value to analyse
77
+ * the row at all — a trace id to group by, an end time to subtract, a status to
78
+ * count, a kind to bucket, a link to follow. Substituting is correct; writing
79
+ * the substitute into the EXPORT is not, because the export is re-validated and
80
+ * the substitute is by construction more conforming than the source. Every
81
+ * `missing-trace-id`, `invalid-timestamp`, `invalid-status`, `unknown-span-kind`
82
+ * and `dangling-link` this package's own re-export ever laundered away was one
83
+ * of these fields, so they are enumerated in ONE place and the export reads that
84
+ * list rather than knowing them one at a time — a sixth substitution cannot be
85
+ * added without the export learning about it.
86
+ */
87
+ type SubstitutedField = 'trace_id' | 'end_time' | 'status.code' | 'kind' | 'links';
88
+ interface OtlpInputFile {
89
+ readonly path: string;
90
+ readonly rows: number;
91
+ readonly spans: number;
92
+ /** Rows that re-declared a span already read, byte-identically. */
93
+ readonly repeats: number;
94
+ /** Distinct trace ids this file contributed, so a caller can attribute a
95
+ * trace back to the file it came from when a directory was ingested. */
96
+ readonly traceIds: readonly string[];
97
+ }
98
+ /** A `*.jsonl` in the directory that does not hold OTLP spans, and how we know. */
99
+ interface SkippedInputFile {
100
+ readonly path: string;
101
+ /** What the first readable line was instead of a span. */
102
+ readonly reason: string;
103
+ }
104
+ /**
105
+ * How much of the original source could not be represented as spans, summed
106
+ * across every export hop that led to this file.
107
+ *
108
+ * `rows` is the count and `kinds` names the ingest issues behind it. On a file a
109
+ * producer wrote, this is just what THIS ingest dropped. On a file
110
+ * `traces` re-exported, it also carries what earlier hops dropped, read back off
111
+ * the spans — so a re-export can never present itself as a complete copy of a
112
+ * source it is missing rows from.
113
+ */
114
+ interface UnreadableSourceRows {
115
+ readonly rows: number;
116
+ readonly kinds: readonly OtlpIngestIssueKind[];
117
+ /** Rows dropped by EARLIER hops, already absent from the file just read. */
118
+ readonly inherited: number;
119
+ }
120
+ interface OtlpInput {
121
+ /** Every file read, in ingest order. */
122
+ readonly files: readonly OtlpInputFile[];
123
+ /** JSONL files in the directory that hold something other than OTLP spans. */
124
+ readonly skipped: readonly SkippedInputFile[];
125
+ /** Rows exactly as the producer wrote them — the input to `validateTraceSpans`. */
126
+ readonly rows: readonly unknown[];
127
+ /** Rows normalized into this package's span model, ready for the pipeline. */
128
+ readonly spans: readonly OtlpSpan[];
129
+ /** Conformance of the RAW rows: what this trace can and cannot answer. */
130
+ readonly validation: TraceValidation;
131
+ /** Rows that could not become spans, each with its reason. */
132
+ readonly issues: readonly OtlpIngestIssue[];
133
+ /** Rows that DID become spans, with one unusable field withheld from them. */
134
+ readonly withheld: readonly OtlpFieldWithheld[];
135
+ /** Source rows absent from `spans`, this hop's and every earlier hop's. */
136
+ readonly unreadable: UnreadableSourceRows;
137
+ }
138
+ /** A file or directory resolved to the OTLP files in it, plus the JSONL that is not OTLP. */
139
+ interface ResolvedOtlpInput {
140
+ readonly files: readonly string[];
141
+ readonly skipped: readonly SkippedInputFile[];
142
+ }
143
+ /**
144
+ * Resolve a file or directory to the OTLP files it names.
145
+ *
146
+ * A named FILE is read as OTLP whatever it contains — the caller pointed at it,
147
+ * and reporting its rows as unreadable is more useful than refusing it. A
148
+ * DIRECTORY is a guess about which files were meant, so its non-OTLP JSONL is
149
+ * skipped and named rather than ingested.
150
+ */
151
+ declare function resolveOtlpInputFiles(path: string): Promise<ResolvedOtlpInput>;
152
+ /**
153
+ * Classify a span from its EVIDENCE — name and attributes — ignoring whatever
154
+ * kind it declared. Callers decide whether a declaration wins; this answers the
155
+ * separate question "what does this span look like".
156
+ *
157
+ * The contract's `resolveSpanKind` does the classifying, so a foreign trace
158
+ * cannot land in one bucket here and another there. What sits on top of it are
159
+ * only signals the contract deliberately does not read, and only where it
160
+ * returned `UNKNOWN`:
161
+ *
162
+ * - `span.type`, a Tangle-internal marker. Its tool-telemetry values name
163
+ * children that DESCRIBE a tool call; counting them as calls doubles every
164
+ * tool total, which is why that check runs first.
165
+ * - the local tool spellings above, and a name that mentions a tool.
166
+ * - an interaction/agent name, which is the run container this model calls
167
+ * AGENT.
168
+ *
169
+ * Anything still unrecognised stays `UNKNOWN`. It is not `CHAIN`: CHAIN claims
170
+ * the span CONTAINS other work, and inventing that relationship is how an
171
+ * unclassifiable span ends up misreported as a container.
172
+ */
173
+ declare function inferSpanKind(name: string, attributes: Record<string, unknown>): OtlpSpanKind;
174
+ /**
175
+ * Exactly one of `span` or `issue`: a usable span, or the named reason there
176
+ * isn't one. `withheld` accompanies a SPAN — the row was analysable, one field
177
+ * on it was not.
178
+ */
179
+ interface OtlpRowConversion {
180
+ span?: OtlpSpan;
181
+ issue?: Omit<OtlpIngestIssue, 'file' | 'line'>;
182
+ withheld?: Omit<OtlpFieldWithheld, 'file' | 'line'>;
183
+ }
184
+ /**
185
+ * One raw row to one analyzable span, or one named reason it is not analyzable.
186
+ *
187
+ * `fallbackTraceId` covers a row with no trace_id: `validateTraceSpans` reports
188
+ * that as `missing-trace-id`, and grouping still needs SOME key, so the source
189
+ * file names the anonymous trace instead of each span becoming its own run.
190
+ */
191
+ declare function otlpRowToSpan(row: unknown, fallbackTraceId: string): OtlpRowConversion;
192
+ /**
193
+ * Read OTLP-JSONL from a file or a directory of them.
194
+ *
195
+ * A directory ingests the OTLP files under it, recursively — every `*.jsonl` /
196
+ * `*.ndjson` that holds spans, or only the contents of an `otlp/` subdirectory
197
+ * when the producer made one — so a results directory of per-shot exports
198
+ * analyses as one body of work while its raw event and stream logs are named
199
+ * and skipped rather than counted as broken spans.
200
+ */
201
+ declare function readOtlpInput(path: string): Promise<OtlpInput>;
202
+
11
203
  /**
12
204
  * OTLP-flat-line emitter — the canonical normalized trace shape.
13
205
  *
@@ -19,7 +211,7 @@ export { HostedClient, createHostedClient, hostedClientFromEnv } from '@tangle-n
19
211
  * (which reads the attribute vocabulary), HALO, and any OpenInference tool.
20
212
  *
21
213
  * Attribute vocabulary the downstream analysts key off:
22
- * - `openinference.span.kind` → span kind (AGENT | LLM | TOOL | CHAIN)
214
+ * - `openinference.span.kind` → span kind ({@link OtlpSpanKind})
23
215
  * - `service.name` → harness id (claude-code, codex, …)
24
216
  * - `agent.name` → agent / subagent name
25
217
  * - `llm.model_name` → model
@@ -27,8 +219,34 @@ export { HostedClient, createHostedClient, hostedClientFromEnv } from '@tangle-n
27
219
  * - `tool.name` → tool histogram (monoculture / no-verify)
28
220
  * - `step` → run order (falls back to start_time)
29
221
  */
30
- type OtlpSpanKind = 'AGENT' | 'LLM' | 'TOOL' | 'CHAIN' | 'SPAN';
222
+
223
+ /**
224
+ * The span-kind vocabulary, which is exactly
225
+ * `@tangle-network/agent-trace-contract`'s — AGENT, CHAIN, LLM, TOOL,
226
+ * EVALUATOR, RETRIEVER, UNKNOWN.
227
+ *
228
+ * It is an alias, not a copy, because the two vocabularies MUST NOT drift: a
229
+ * narrower local union silently re-typed every kind it did not list, so a
230
+ * producer's EVALUATOR verdict span came back out as CHAIN and the re-exported
231
+ * file no longer said what the original did.
232
+ */
233
+ type OtlpSpanKind = SpanKind;
31
234
  type OtlpStatusCode = 'OK' | 'ERROR' | 'UNSET';
235
+ /**
236
+ * A causal edge that is NOT containment. `parent_span_id` says "this span
237
+ * happened INSIDE that one"; a link says "that one CAUSED this one" — round N's
238
+ * verdict steering round N+1, a retry pointing at the attempt it replaces.
239
+ * Encoding those as a parent would claim a nesting that never existed, so OTLP
240
+ * gives them their own edge and this model keeps it.
241
+ *
242
+ * Matches `SpanLink` in `@tangle-network/agent-trace-contract`.
243
+ */
244
+ interface OtlpSpanLink {
245
+ trace_id: string;
246
+ span_id: string;
247
+ /** e.g. `{ 'agent.link.kind': 'steered_by' }`. */
248
+ attributes?: Record<string, unknown>;
249
+ }
32
250
  interface OtlpSpan {
33
251
  trace_id: string;
34
252
  span_id: string;
@@ -41,6 +259,8 @@ interface OtlpSpan {
41
259
  message?: string;
42
260
  };
43
261
  attributes: Record<string, unknown>;
262
+ /** Causal edges to other spans. Absent when the producer recorded none. */
263
+ links?: OtlpSpanLink[];
44
264
  }
45
265
  interface SpanInput {
46
266
  traceId: string;
@@ -68,6 +288,8 @@ interface SpanInput {
68
288
  step?: number;
69
289
  /** Verbatim content the agentic analysts read via regex search. */
70
290
  content?: string | null;
291
+ /** Causal edges (steered-by / graded-by / retry-of), not containment. */
292
+ links?: readonly OtlpSpanLink[];
71
293
  /** Extra attributes merged last (escape hatch for harness-specific signal). */
72
294
  extra?: Record<string, unknown>;
73
295
  }
@@ -77,11 +299,43 @@ interface SpanInput {
77
299
  * so the behavioral analyst's "no LLM data" case stays honest.
78
300
  */
79
301
  declare function span(input: SpanInput): OtlpSpan;
80
- /** Project an in-memory span to a COMPLETE OpenInference span: the standard shape
81
- * OTel/OpenInference consumers (and HALO) expect — top-level `kind`, `resource`,
82
- * `scope`, and a string `parent_span_id` ("" at the root) — while keeping the
83
- * attribute vocabulary (incl. `openinference.span.kind`) our own analysts read.
84
- * One artifact feeds our pipeline, HALO, and any OpenInference tool. */
302
+ /** The three things an export can write for a substituted field, and nothing else. */
303
+ type ExportRule = 'faithful' | 'declared-or-analysed' | 'analysed';
304
+ /**
305
+ * What the export writes for a field this package substituted. One rule per
306
+ * field, in one table, because the difference between them is not a style choice
307
+ * — each `analysed` entry is a consumer that HARD-REQUIRES the field, named.
308
+ *
309
+ * The table is EXPORTED because it is a guarantee, not documentation:
310
+ * `tests/otlp-export-rule.test.ts` reads it and derives, per field, the checks
311
+ * the declared word promises — the exact value written in each of the two
312
+ * producer states, that a `faithful` field erases no finding its source earned,
313
+ * and that the artifact stays readable by the consumer whose hard requirement is
314
+ * the only reason `analysed` exists. A field could be declared `faithful` here
315
+ * while nothing implemented it (`status.code` was, and the finding vanished from
316
+ * every re-export); a table that reads as a guarantee and is not one is worse
317
+ * than no table.
318
+ *
319
+ * - `faithful` — the producer's value, or NO field at all when they wrote none.
320
+ * This is the default and the only rule that reproduces the source's finding
321
+ * exactly.
322
+ * - `declared-or-analysed` — the producer's word when they wrote one, else this
323
+ * package's. A kind is what every consumer buckets by, and a span with none is
324
+ * re-derived differently by each of them (the tool-execution demotion that
325
+ * stops a tool call being counted twice is one such re-derivation), so the
326
+ * export always declares one. Writing the producer's word when there is one is
327
+ * what keeps `unknown-span-kind` alive across the trip.
328
+ * - `analysed` — this package's value regardless. `trace_id` is the one field
329
+ * here, and it is not a choice: `analyze --otlp-out` hands the artifact
330
+ * straight to `agent-eval`'s `OtlpFileTraceStore`, whose `projectOtlpFlatLine`
331
+ * drops any row with a falsy `trace_id` and then throws `TraceFileMalformed`
332
+ * on the drop. A faithful (absent) trace id makes the artifact unreadable by
333
+ * the tool that reads it, so `missing-trace-id` CANNOT survive the trip. The
334
+ * substitution is disclosed instead — the span carries the pairing, and
335
+ * `renderConformance` states it above the findings so a reader of the artifact
336
+ * is told the id was minted here rather than left to assume the source had one.
337
+ */
338
+ declare const EXPORT_RULE: Readonly<Record<SubstitutedField, ExportRule>>;
85
339
  declare function toOpenInferenceSpan(s: OtlpSpan): Record<string, unknown>;
86
340
  /** Serialize spans to OpenInference JSONL (one complete span per line). This is a
87
341
  * standard OpenInference representation: it feeds our analysts, HALO, and other
@@ -207,6 +461,226 @@ interface HarnessTraceAdapter {
207
461
  resolveParentTask?(ref: SessionRef, childSessionId: string, options?: Pick<ParseOptions, 'corruptionMode' | 'signal'>): Promise<ParentTaskResolution>;
208
462
  }
209
463
 
464
+ /**
465
+ * What a trace can and cannot answer, said out loud.
466
+ *
467
+ * `@tangle-network/agent-trace-contract` decides conformance: it reports
468
+ * findings (what is wrong, and the consequence) and capabilities (what a
469
+ * consumer can compute, and why not when it cannot). That package is
470
+ * deliberately generic. This module adds the one thing it cannot know — which
471
+ * section of THIS report each missing capability empties — so a thin report
472
+ * explains its own thinness instead of reading as "the agent did nothing".
473
+ */
474
+
475
+ /**
476
+ * Capabilities the trace cannot support, mapped to the trace's own reason.
477
+ *
478
+ * This is what makes the conformance section GATE rather than narrate: the
479
+ * renderer takes it and marks every section whose inputs are incomplete, at the
480
+ * table, so a number and the reason it is wrong cannot end up forty lines
481
+ * apart.
482
+ */
483
+ type UnavailableCapabilities = ReadonlyMap<string, string>;
484
+ /** The trace's unavailable capabilities, each mapped to the validator's own reason. */
485
+ declare function unavailableCapabilities(validation: TraceValidation): UnavailableCapabilities;
486
+ /**
487
+ * The inline marker a section carries when its inputs are incomplete. Empty
488
+ * when the capability is available — the caller concatenates unconditionally,
489
+ * so a section can never be marked in one place and silently not in another.
490
+ */
491
+ declare function incompleteInputsNote(unavailable: UnavailableCapabilities | undefined, capability: string): string;
492
+ interface SpanStructure {
493
+ readonly spans: number;
494
+ readonly traces: number;
495
+ /** Spans carrying no `parent_span_id` at all. */
496
+ readonly rootless: number;
497
+ /**
498
+ * Rootless spans BEYOND the one root each trace is supposed to have. This,
499
+ * not `rootless`, is the number of spans that attribute to nothing: a
500
+ * textbook-correct trace has exactly one root, so `rootless === traces` with
501
+ * one root each is a conforming shape and must read as one.
502
+ */
503
+ readonly extraRoots: number;
504
+ /** Traces where every span names a parent, so the trace has no top at all. */
505
+ readonly tracesWithoutRoot: number;
506
+ /** Spans naming a parent that is absent from the export. */
507
+ readonly orphans: number;
508
+ readonly links: number;
509
+ }
510
+ /**
511
+ * How much of the span tree actually attaches.
512
+ *
513
+ * The contract's `flat-hierarchy` finding is per-trace and all-or-nothing: one
514
+ * parented span anywhere in a trace suppresses it for every other span. A trace
515
+ * where the overwhelming majority of spans have no parent is not flat by that
516
+ * definition and is entirely flat in practice, so this reports the DEGREE the
517
+ * binary finding cannot express. It measures, it does not re-implement — the
518
+ * finding still comes from the validator.
519
+ *
520
+ * Roots are counted PER TRACE, because "has no parent" is the definition of a
521
+ * root, not of a defect. Counting every rootless span as unattributed made a
522
+ * correct one-root trace narrate itself as broken.
523
+ */
524
+ declare function summarizeSpanStructure(spans: readonly OtlpSpan[]): SpanStructure;
525
+ interface SkippedAnalysis {
526
+ readonly capability: string;
527
+ /** The analysis in this report that the missing capability empties. */
528
+ readonly analysis: string;
529
+ /** The trace's own reason, from the contract validator. */
530
+ readonly reason: string;
531
+ }
532
+ /**
533
+ * Conformance of spans this package produced (adapters, importers), measured on
534
+ * the same OpenInference projection that gets written to disk — so the report
535
+ * grades the artifact a consumer would actually receive, not an in-memory shape
536
+ * nobody sees. For spans read from a foreign OTLP file, validate the RAW rows
537
+ * instead (`readOtlpInput` does): that tells the producer what to fix rather
538
+ * than describing our own normalization back to them.
539
+ */
540
+ declare function conformanceOfSpans(spans: readonly OtlpSpan[]): TraceValidation;
541
+ /** Unavailable capabilities, paired with the analysis each one empties. */
542
+ declare function skippedAnalyses(validation: TraceValidation): SkippedAnalysis[];
543
+ interface ConformanceRenderOptions {
544
+ /** What was validated, e.g. a file path or "spans emitted by the claude-code adapter". */
545
+ readonly subject: string;
546
+ /** Files read, when the source was an OTLP file or directory. */
547
+ readonly files?: readonly OtlpInputFile[];
548
+ /** JSONL files in the directory that hold something other than OTLP spans. */
549
+ readonly skipped?: readonly SkippedInputFile[];
550
+ /** Rows that never became spans, when the source was an OTLP file or directory. */
551
+ readonly issues?: readonly OtlpIngestIssue[];
552
+ /** Rows that DID become spans, with one field withheld from them. */
553
+ readonly withheld?: readonly OtlpFieldWithheld[];
554
+ /** Source rows absent from this file — this ingest's, and any earlier export's. */
555
+ readonly unreadable?: UnreadableSourceRows;
556
+ /** The spans that were analysed, for the hierarchy summary. */
557
+ readonly spans?: readonly OtlpSpan[];
558
+ /** Markdown heading level for the section title (default 2). */
559
+ readonly headingLevel?: number;
560
+ }
561
+ /**
562
+ * The conformance section of an analysis report: findings, the capability
563
+ * table, and — the part that makes a thin report honest — the named analyses
564
+ * that produced nothing and why.
565
+ */
566
+ declare function renderConformance(validation: TraceValidation, opts: ConformanceRenderOptions): string;
567
+ /**
568
+ * The `traces validate` report. Same body, plus a verdict line a reader (or a
569
+ * CI job reading the exit code) can act on.
570
+ *
571
+ * The three verdicts are the three answers `@tangle-network/agent-trace-contract`
572
+ * can give, in its own terms — `ok` says whether the input is a trace AT ALL, and
573
+ * `capabilities` says what a trace can answer. Nothing here re-derives either.
574
+ */
575
+ declare function renderValidation(validation: TraceValidation, opts: ConformanceRenderOptions): string;
576
+ /**
577
+ * Exit code for `traces validate`, which is read by CI.
578
+ *
579
+ * Non-zero on exactly one condition: the input is not a trace. That is what
580
+ * `TraceValidation.ok` means and the contract's severities are defined to match
581
+ * it — `error` is "nothing readable", `warn` is "readable but degraded", `info`
582
+ * is "nothing lost" — so a severity scan here would only be a second, driftable
583
+ * copy of the same rule.
584
+ *
585
+ * A degraded trace exits 0 deliberately. Failing on degradation is failing on
586
+ * thinness, and every real-world trace is thin somewhere: a gate that red-lights
587
+ * `flat-hierarchy` or `no-usage` is one a producer learns to ignore. What a
588
+ * missing field costs is stated per capability, in the table, where it can be
589
+ * acted on.
590
+ */
591
+ declare function validationExitCode(validation: TraceValidation): number;
592
+
593
+ /**
594
+ * The two questions a LOOP trace exists to answer, and that a flat event list
595
+ * cannot: **did round N+1 improve on round N**, and **which verdict caused
596
+ * which retry**.
597
+ *
598
+ * Both are read from the contract's own vocabulary and nothing else:
599
+ *
600
+ * - `agent.loop.id` / `agent.loop.iteration` group and order the rounds.
601
+ * - `agent.outcome` / `agent.outcome.score` carry the verdict. A round rarely
602
+ * grades itself — the grade lives on an EVALUATOR span underneath it — so the
603
+ * verdict is taken from the shallowest descendant that has one, which is the
604
+ * round's own verdict rather than one of its per-layer sub-verdicts.
605
+ * - `links` carry causality. `parent_span_id` says round N+1 happened INSIDE
606
+ * round N, which is false; the link says round N's verdict CAUSED it, which
607
+ * is the edge a steering chain is made of.
608
+ *
609
+ * Nothing here throws on malformed input, and nothing is inferred where the
610
+ * trace is silent: a loop with no scores reports `unscored`, not a flat trend.
611
+ */
612
+
613
+ /** Whether the rounds got better, stayed put, or got worse — and on what basis. */
614
+ type LoopTrend = 'improved' | 'plateaued' | 'regressed' | 'mixed' | 'unscored';
615
+ /** What the trend was computed from, so a reader can tell a score series from
616
+ * a pass/fail series from nothing at all. */
617
+ type LoopTrendBasis = 'score' | 'outcome' | 'none';
618
+ interface LoopIteration {
619
+ readonly iteration: number;
620
+ readonly spanId: string;
621
+ readonly name: string;
622
+ /** Terminal verdict for the round, from the round or its shallowest graded descendant. */
623
+ readonly outcome: Outcome | null;
624
+ readonly score: number | null;
625
+ /** Span the verdict was read from; equals `spanId` when the round graded itself. */
626
+ readonly verdictSpanId: string | null;
627
+ readonly startTime: string;
628
+ readonly durationMs: number | null;
629
+ }
630
+ interface LoopConvergence {
631
+ readonly loopId: string;
632
+ readonly traceId: string;
633
+ readonly iterations: readonly LoopIteration[];
634
+ readonly trend: LoopTrend;
635
+ readonly basis: LoopTrendBasis;
636
+ /** The trend in the trace's own numbers, e.g. "score 0.4 → 0.9 over 4 rounds". */
637
+ readonly detail: string;
638
+ }
639
+ interface LoopConvergenceReport {
640
+ readonly loops: readonly LoopConvergence[];
641
+ /** Spans carrying `agent.loop.iteration` — 0 means the trace records no rounds. */
642
+ readonly iterationSpans: number;
643
+ }
644
+ /** One causal edge: a graded span, and the work it caused. */
645
+ interface SteeringEdge {
646
+ /** The span that CAUSED the work — a verdict, an earlier attempt. */
647
+ readonly causeSpanId: string;
648
+ readonly causeName: string | null;
649
+ readonly causeOutcome: Outcome | null;
650
+ readonly causeScore: number | null;
651
+ /** The span the link was recorded on: the work that was caused. */
652
+ readonly effectSpanId: string;
653
+ readonly effectName: string;
654
+ readonly effectIteration: number | null;
655
+ /** `agent.link.kind`, or `unspecified` when the producer recorded none. */
656
+ readonly linkKind: string;
657
+ /** False when the cause is absent from this export, so the chain breaks here. */
658
+ readonly resolved: boolean;
659
+ }
660
+ interface SteeringChainReport {
661
+ readonly edges: readonly SteeringEdge[];
662
+ readonly links: number;
663
+ readonly dangling: number;
664
+ readonly byKind: Readonly<Record<string, number>>;
665
+ }
666
+ /**
667
+ * Round-over-round convergence, per loop.
668
+ *
669
+ * Rounds are ordered by `agent.loop.iteration`, not by time: a resumed or
670
+ * re-run round is written later than the round it replaces, and time order
671
+ * would report the replacement as a new round.
672
+ */
673
+ declare function analyzeLoopConvergence(spans: readonly OtlpSpan[]): LoopConvergenceReport;
674
+ /**
675
+ * The steering chain: which graded span caused which subsequent unit of work.
676
+ *
677
+ * A link is recorded on the EFFECT and points at the CAUSE, so the edge is read
678
+ * backwards from the span that carries it. A link whose target is absent from
679
+ * the export is kept and marked unresolved — dropping it would report a shorter
680
+ * chain than the producer recorded, which is the opposite of the truth.
681
+ */
682
+ declare function analyzeSteeringChain(spans: readonly OtlpSpan[]): SteeringChainReport;
683
+
210
684
  interface CodeTraceBenchFileRef {
211
685
  readonly path: string;
212
686
  readonly line_start: number;
@@ -1847,6 +2321,24 @@ interface TraceInvestigationOptions {
1847
2321
  readonly analyzerPrompt?: string;
1848
2322
  readonly otlpOutPath?: string;
1849
2323
  readonly generatedAt?: string;
2324
+ /**
2325
+ * Conformance of the SOURCE the spans were read from. Supply it when the
2326
+ * source was a foreign OTLP file, so the report grades what the producer
2327
+ * wrote; omitted, it is computed from the spans themselves.
2328
+ */
2329
+ readonly conformance?: TraceValidation;
2330
+ /** What was validated, named in the conformance section (default: the harness). */
2331
+ readonly conformanceSubject?: string;
2332
+ /** OTLP files read, when the spans came from `--otlp`. */
2333
+ readonly conformanceFiles?: readonly OtlpInputFile[];
2334
+ /** JSONL files that were not OTLP, when the spans came from `--otlp` on a directory. */
2335
+ readonly conformanceSkipped?: readonly SkippedInputFile[];
2336
+ /** Rows that never became spans, when the spans came from `--otlp`. */
2337
+ readonly conformanceIssues?: readonly OtlpIngestIssue[];
2338
+ /** Rows analysed with one field withheld, when the spans came from `--otlp`. */
2339
+ readonly conformanceWithheld?: readonly OtlpFieldWithheld[];
2340
+ /** Source rows absent from the file read, including any earlier export's. */
2341
+ readonly conformanceUnreadable?: UnreadableSourceRows;
1850
2342
  readonly signal?: AbortSignal;
1851
2343
  readonly log?: (msg: string, fields?: Record<string, unknown>) => void;
1852
2344
  }
@@ -1879,12 +2371,22 @@ interface TraceInvestigationResult {
1879
2371
  readonly workflow?: SessionWorkflowSummary;
1880
2372
  readonly spanCount: number;
1881
2373
  readonly otlpPath: string;
2374
+ /**
2375
+ * What these spans can and cannot answer. Every report carries it: a thin
2376
+ * report that does not explain its own thinness reads as "the agent did
2377
+ * nothing" when the truth is "the trace never recorded it".
2378
+ */
2379
+ readonly conformance: TraceValidation;
1882
2380
  readonly execution: ExecutionReport;
1883
2381
  readonly analystResult: AnalystRunResult;
1884
2382
  readonly findings: readonly AnalystFinding[];
1885
2383
  readonly pipelines: PipelineReport;
1886
2384
  readonly reactions: ReactionReport;
1887
2385
  readonly adoption: AdoptionReport;
2386
+ /** Did round N+1 improve on round N, per loop. */
2387
+ readonly loopConvergence: LoopConvergenceReport;
2388
+ /** Which verdict caused which subsequent round. */
2389
+ readonly steeringChain: SteeringChainReport;
1888
2390
  /** Deterministic routing record for the agentic trace-analysis pass. */
1889
2391
  readonly agenticRoute?: TraceAgenticRoute;
1890
2392
  /**
@@ -2052,6 +2554,512 @@ interface ObserverOptions {
2052
2554
  }
2053
2555
  declare function watchSessions(opts: ObserverOptions): Promise<void>;
2054
2556
 
2557
+ /**
2558
+ * A SECOND implementation of agent-eval's `SupervisorRunReader` port, over the
2559
+ * run directory that agent-runtime's `createFileRunContext(dir)` writes:
2560
+ *
2561
+ * <runDir>/spawn-journal.jsonl required — the append-only SpawnEvent log
2562
+ * <runDir>/coordination-log.jsonl optional — steer / delivery / question / settled
2563
+ * <runDir>/blobs/ optional — content-addressed settled results
2564
+ * <runDir>/result.json optional — the terminal outcome document
2565
+ *
2566
+ * `loopsSupervisorRunReader` is the other implementation, over a completely
2567
+ * different layout. Neither knows about the other, and NOTHING here analyzes:
2568
+ * `analyzeSupervisorRun` / `parseSupervisorTree` / `rollupSupervisorRuns` in
2569
+ * `@tangle-network/agent-eval/supervisor-run` compute every metric, and
2570
+ * `materializeTreeView` in `@tangle-network/agent-runtime/kernel` folds the
2571
+ * event log into the tree. This file is translation only.
2572
+ *
2573
+ * ## Two translations, both faithful
2574
+ *
2575
+ * 1. **The envelope.** agent-runtime's `FileSpawnJournal` writes each event
2576
+ * wrapped as `{kind:'event', root, event:{…}}` after one `{kind:'begin'}`
2577
+ * record. agent-eval's parser reads `kind` at the TOP level, so an
2578
+ * un-translated file parses as zero spawns AND zero malformed rows — a run
2579
+ * that reads as "the supervisor did nothing" rather than "I cannot read
2580
+ * this". The reader unwraps the envelope and re-emits flat JSONL.
2581
+ *
2582
+ * 2. **`role`.** `SupervisorRunSources.journal` documents
2583
+ * `role: 'supervisor' | 'worker'` on spawned rows for recursive readers.
2584
+ * agent-runtime's `SpawnEvent` has no such field, so it is INFERRED
2585
+ * structurally and exactly: a node that appears as another spawn's `parent`
2586
+ * is a supervisor; the root is a supervisor because it has no parent;
2587
+ * everything else is a worker. No new upstream field is needed for this,
2588
+ * and no depth limit applies — `<root>:s0:s0` classifies its parent
2589
+ * `<root>:s0` as a supervisor by the same rule that classifies the root.
2590
+ *
2591
+ * Steer traffic is translated the same way: this layout records steers in
2592
+ * `coordination-log.jsonl` rather than per-worker inbox files, and each
2593
+ * recorded field maps 1:1 onto the per-worker artifacts the analyzer reads.
2594
+ * Nothing is synthesized from an absent fact — an artifact this layout does
2595
+ * not keep is declared in `SourceLimits`, which is what turns the dependent
2596
+ * metric into `unavailable` instead of 0.
2597
+ */
2598
+
2599
+ declare const SPAWN_JOURNAL_FILE = "spawn-journal.jsonl";
2600
+ declare const COORDINATION_LOG_FILE = "coordination-log.jsonl";
2601
+ declare const RESULT_FILE = "result.json";
2602
+ declare const BLOBS_DIR = "blobs";
2603
+ interface RunContextJournal {
2604
+ /** The `root` of the `begin` record, or of the first event envelope. */
2605
+ readonly root: string | null;
2606
+ /** ISO instant the tree was begun, when a `begin` record was written. */
2607
+ readonly begunAt: string | null;
2608
+ /** Events in file order, unwrapped from their envelopes. */
2609
+ readonly events: readonly SpawnEvent[];
2610
+ /** Node ids that appear as some spawn's `parent` — the exact supervisor set. */
2611
+ readonly supervisorIds: ReadonlySet<string>;
2612
+ readonly invalidRows: number;
2613
+ readonly partialTail: boolean;
2614
+ readonly present: boolean;
2615
+ }
2616
+ /**
2617
+ * Unwrap `FileSpawnJournal`'s `{kind:'begin'|'event', root, event}` records.
2618
+ * A record whose `kind` is neither is counted as invalid rather than dropped:
2619
+ * an unrecognized record shape is a finding, not silence.
2620
+ */
2621
+ declare function readRunContextJournal(text: string | null): RunContextJournal;
2622
+ /**
2623
+ * A node's role, decided by the tree's own shape. `supervisorIds` is the set of
2624
+ * ids some spawn named as its parent, so the rule is exact at any depth and
2625
+ * needs no field agent-runtime does not emit.
2626
+ */
2627
+ declare function inferRole(id: string, parent: string | null | undefined, supervisorIds: ReadonlySet<string>): SupervisorRunNodeRole;
2628
+ /** One steer the driver sent down to a named node. */
2629
+ interface CoordinationSteer {
2630
+ readonly messageId: string | null;
2631
+ readonly toWorker: string | null;
2632
+ readonly instruction: string;
2633
+ readonly deliveryMode: string | null;
2634
+ readonly at: number | null;
2635
+ }
2636
+ /** A question a node raised up. `blocking` is the run-stopping urgency. */
2637
+ interface CoordinationQuestion {
2638
+ readonly id: string | null;
2639
+ readonly from: string | null;
2640
+ readonly question: string;
2641
+ readonly reason: string | null;
2642
+ readonly urgency: string | null;
2643
+ readonly status: string | null;
2644
+ readonly blocking: boolean;
2645
+ readonly at: number | null;
2646
+ }
2647
+ interface CoordinationLog {
2648
+ readonly present: boolean;
2649
+ readonly steers: readonly CoordinationSteer[];
2650
+ /** `messageId → delivered`, from `delivery` receipts. */
2651
+ readonly deliveries: readonly {
2652
+ messageId: string | null;
2653
+ delivered: boolean | null;
2654
+ }[];
2655
+ readonly questions: readonly CoordinationQuestion[];
2656
+ readonly invalidRows: number;
2657
+ readonly partialTail: boolean;
2658
+ }
2659
+ /**
2660
+ * Two record envelopes are in the wild for this file: the versioned
2661
+ * `{version, runId, source, record:{seq, at, event}}` and the flat
2662
+ * `{runId, at, event}`. Both carry the same `event`, so the unwrap is a single
2663
+ * lookup and neither shape is privileged.
2664
+ */
2665
+ declare function readCoordinationLog(text: string | null): CoordinationLog;
2666
+ interface FileRunContextReaderOptions {
2667
+ /** Override the run identity used for rollup grouping (default: the journal root). */
2668
+ readonly instanceId?: string | null;
2669
+ /** Which arm of a comparison this run is (default: the run directory's basename). */
2670
+ readonly arm?: string | null;
2671
+ }
2672
+ /**
2673
+ * Read a `createFileRunContext` run directory into `SupervisorRunSources`.
2674
+ * Never throws on a missing artifact: an absent file becomes a `null` field or
2675
+ * a declared `SourceLimits` reason, which is what makes the dependent metric
2676
+ * `unavailable` rather than 0.
2677
+ */
2678
+ declare function readFileRunContext(runDir: string, opts?: FileRunContextReaderOptions): Promise<SupervisorRunSources>;
2679
+ /** The `createFileRunContext` on-disk layout, as a `SupervisorRunReader`. */
2680
+ declare function fileRunContextSupervisorRunReader(runDir: string, opts?: FileRunContextReaderOptions): SupervisorRunReader;
2681
+ /** Does this directory hold a `createFileRunContext` run? */
2682
+ declare function isFileRunContextDir(runDir: string): Promise<boolean>;
2683
+ /**
2684
+ * A sum over spend records that keeps "unknown" out of the number.
2685
+ *
2686
+ * `usd` is the total of the records that priced themselves; `usdUnknown` is how
2687
+ * many declined to. A renderer that has 0 known records and >=1 unknown one must
2688
+ * print "unknown", never `$0.0000`: an unmetered turn and a free turn are
2689
+ * different facts, and agent-runtime's `Spend.usdKnown` is the only signal that
2690
+ * separates them (absent means known, per its contract).
2691
+ */
2692
+ interface SpendRoll {
2693
+ readonly records: number;
2694
+ readonly iterations: number;
2695
+ readonly tokensIn: number;
2696
+ readonly tokensOut: number;
2697
+ readonly usd: number;
2698
+ readonly usdKnownRecords: number;
2699
+ readonly usdUnknownRecords: number;
2700
+ }
2701
+ declare const ZERO_ROLL: SpendRoll;
2702
+ declare function addSpend(roll: SpendRoll, spend: Spend): SpendRoll;
2703
+ declare function mergeRolls(a: SpendRoll, b: SpendRoll): SpendRoll;
2704
+ interface RunContextNode {
2705
+ readonly id: string;
2706
+ readonly parent: string | null;
2707
+ readonly label: string;
2708
+ readonly depth: number;
2709
+ readonly role: SupervisorRunNodeRole;
2710
+ readonly status: NodeStatus;
2711
+ readonly runtime: Runtime | null;
2712
+ /** The budget this node was AUTHORED with, exactly as the spawn recorded it. */
2713
+ readonly budget: Budget;
2714
+ /** This node's own driver inference — its `metered` events. */
2715
+ readonly driver: SpendRoll;
2716
+ /** What this node's direct children consumed — their `settled` spend. */
2717
+ readonly children: SpendRoll;
2718
+ /** What this node's own settlement charged its parent (its whole subtree). */
2719
+ readonly settled: SpendRoll;
2720
+ readonly spawnedAt: number | null;
2721
+ readonly settledAt: number | null;
2722
+ /** Wall from spawn to settlement; null while the node is still live. */
2723
+ readonly wallMs: number | null;
2724
+ readonly outRef: string | null;
2725
+ /** Why a cancelled node was cancelled. */
2726
+ readonly cancelReason: string | null;
2727
+ }
2728
+ interface RunContextResult {
2729
+ readonly kind: string | null;
2730
+ readonly reason: string | null;
2731
+ readonly errorName: string | null;
2732
+ readonly errorMessage: string | null;
2733
+ }
2734
+ interface RunContextSnapshot {
2735
+ readonly runDir: string;
2736
+ readonly runId: string | null;
2737
+ readonly present: boolean;
2738
+ /** Depth-first, parents before children. */
2739
+ readonly nodes: readonly RunContextNode[];
2740
+ readonly maxDepth: number;
2741
+ readonly begunAt: number | null;
2742
+ /** Latest instant any event carried. */
2743
+ readonly lastEventAt: number | null;
2744
+ readonly questions: readonly CoordinationQuestion[];
2745
+ readonly steers: readonly CoordinationSteer[];
2746
+ readonly result: RunContextResult | null;
2747
+ /** True once `result.json` exists — the run has reached a terminal state. */
2748
+ readonly terminal: boolean;
2749
+ /** Rows that were present and unreadable, per artifact. */
2750
+ readonly invalidJournalRows: number;
2751
+ readonly invalidCoordinationRows: number;
2752
+ /** True when an artifact's last line was still being written. */
2753
+ readonly partialTail: boolean;
2754
+ /** Why the tree could not be folded, when it could not. */
2755
+ readonly treeError: string | null;
2756
+ }
2757
+ /**
2758
+ * Read the run directory into the shape a live view renders. The tree comes
2759
+ * from agent-runtime's own `materializeTreeView` — the owner's fold of its own
2760
+ * event log, so a new event kind stays correctly classified here without this
2761
+ * file changing.
2762
+ *
2763
+ * The one thing the fold deliberately does NOT answer is the split this view
2764
+ * exists for: `materializeTreeView` accumulates a node's `metered` driver
2765
+ * inference ONTO its settled child-work base, which is the right total and the
2766
+ * wrong breakdown. Driver and child spend are therefore rolled separately
2767
+ * straight off the events, which is a partition of the same rows, not a second
2768
+ * tree.
2769
+ */
2770
+ declare function readRunContextSnapshot(runDir: string): Promise<RunContextSnapshot>;
2771
+
2772
+ /**
2773
+ * The GENERAL run-tree source: reconstruct a run's shape from OTLP spans alone.
2774
+ *
2775
+ * `supervisor-run-context.ts` is the specific source — agent-runtime's durable
2776
+ * spawn journal, which carries the exact authored budget, settled spend, and
2777
+ * settlement status that telemetry does not. This file is the one that works
2778
+ * for emitters nobody has written yet: anything that emits spans carrying
2779
+ * `trace_id` / `span_id` / `parent_span_id` gets a tree, because the parent
2780
+ * pointer IS the tree. A supervisor, a pi session, a Claude subagent fan-out,
2781
+ * and a custom fanout all reach the same view through the same three fields.
2782
+ *
2783
+ * ## Nothing here is a second exporter or a second attribute vocabulary
2784
+ *
2785
+ * Spans are read with this repo's existing `exportTraceEvidenceFile`, which
2786
+ * already detects OpenInference / intelligence-span / sandbox-event files,
2787
+ * normalizes them onto `OtlpSpan`, redacts, and validates. Every attribute is
2788
+ * read through `@tangle-network/agent-eval/trace-attributes` alias lists
2789
+ * (`LLM_INPUT_TOKEN_ATTR_KEYS`, `LLM_COST_ATTR_KEYS`, `SPAN_KIND_ATTR_KEYS`, …),
2790
+ * which already cover both live vocabularies — OpenInference's
2791
+ * `llm.token_count.*` and GenAI semconv's `gen_ai.usage.*`. No key is invented
2792
+ * here, so a span this repo can already read is a span this view can already
2793
+ * place.
2794
+ *
2795
+ * ## What a span tree can and cannot say
2796
+ *
2797
+ * It can say the shape, the wall time, the tokens, and — when the emitter
2798
+ * priced them — the dollars. It CANNOT say the authored budget: neither
2799
+ * vocabulary carries a spawn's ceiling, so budget is reported as absent, never
2800
+ * as 0. That gap is exactly why the journal source exists and why, when both
2801
+ * are present, the journal's numbers win.
2802
+ */
2803
+
2804
+ type SpanNodeStatus = 'running' | 'done' | 'failed';
2805
+ interface SpanRunNode {
2806
+ readonly traceId: string;
2807
+ readonly spanId: string;
2808
+ /** The enclosing NODE's span id — not necessarily the raw parent span. */
2809
+ readonly parentNodeId: string | null;
2810
+ readonly label: string;
2811
+ readonly depth: number;
2812
+ /**
2813
+ * `driver` when this node has nested agent nodes below it, `leaf` otherwise.
2814
+ * Spans carry no spawn relationship, so delegation is read from the tree
2815
+ * itself — the only fact the telemetry actually states.
2816
+ */
2817
+ readonly role: 'driver' | 'leaf';
2818
+ readonly status: SpanNodeStatus;
2819
+ /** `service.name` — which harness or runtime emitted this subtree. */
2820
+ readonly runtime: string | null;
2821
+ /** This node's OWN inference: the LLM spans it emitted directly. */
2822
+ readonly driver: SpendRoll;
2823
+ /** What its nested agent nodes consumed, whole subtrees included. */
2824
+ readonly children: SpendRoll;
2825
+ /** Tool spans attributed to this node directly. */
2826
+ readonly toolCalls: number;
2827
+ readonly startMs: number;
2828
+ readonly endMs: number;
2829
+ readonly wallMs: number;
2830
+ /** Span status messages on this node or its non-node descendants. */
2831
+ readonly errors: readonly string[];
2832
+ }
2833
+ interface SpanRunSnapshot {
2834
+ readonly source: string;
2835
+ readonly present: boolean;
2836
+ /** Depth-first, parents before children, one subtree per trace. */
2837
+ readonly nodes: readonly SpanRunNode[];
2838
+ readonly maxDepth: number;
2839
+ readonly traceIds: readonly string[];
2840
+ readonly spanCount: number;
2841
+ readonly startMs: number | null;
2842
+ readonly endMs: number | null;
2843
+ /** LLM spans that recorded no token count at all — a gap, not a zero. */
2844
+ readonly llmSpansWithoutTokens: number;
2845
+ /** LLM spans that recorded no cost at all — a gap, not $0. */
2846
+ readonly llmSpansWithoutCost: number;
2847
+ /** Spans whose `parent_span_id` names a span not in the file. */
2848
+ readonly orphanSpans: number;
2849
+ /** Why the file could not be read, when it could not. */
2850
+ readonly readError: string | null;
2851
+ }
2852
+ declare const EMPTY_SPAN_RUN_SNAPSHOT: Omit<SpanRunSnapshot, 'source'>;
2853
+ /**
2854
+ * Fold a flat span batch into the node tree. Pure, so the same spans always
2855
+ * render the same text — which is what lets the live tail print only on change.
2856
+ */
2857
+ declare function buildSpanRunTree(spans: readonly OtlpSpan[], source: string): SpanRunSnapshot;
2858
+ /**
2859
+ * Read one span file into a snapshot. Never throws: a tail that catches the
2860
+ * writer mid-line, or an empty file the emitter has not filled yet, is a state
2861
+ * to display, not a crash.
2862
+ */
2863
+ declare function readSpanRunSnapshot(path: string): Promise<SpanRunSnapshot>;
2864
+ /**
2865
+ * The two run-level halves of a span tree, each counted exactly once: the
2866
+ * inference emitted by nodes that DELEGATED, and the inference emitted by the
2867
+ * leaves they delegated to. Every LLM span lands in exactly one half, so the
2868
+ * two add up to the run and neither hides inside the other.
2869
+ */
2870
+ declare function spanRunTotals(snapshot: SpanRunSnapshot): {
2871
+ driver: SpendRoll;
2872
+ leaves: SpendRoll;
2873
+ };
2874
+ /** The rendered view for one span snapshot. Pure. */
2875
+ declare function renderSpanRunSnapshot(snapshot: SpanRunSnapshot): string;
2876
+ /**
2877
+ * Span files at or immediately under `dir`. One level only, matching how the
2878
+ * journal source resolves a run directory: a run is the unit a caller names.
2879
+ */
2880
+ declare function findSpanSourceFiles(dir: string): Promise<string[]>;
2881
+
2882
+ /**
2883
+ * `traces watch <runDir>` — a live terminal view of a supervised run written by
2884
+ * agent-runtime's `createFileRunContext`.
2885
+ *
2886
+ * Plain stdout, no dependency, no cursor control: it works over SSH, in a CI
2887
+ * log, and through a pipe, and it prints a new block only when something
2888
+ * changed, so a long idle stretch does not scroll away the last real event.
2889
+ *
2890
+ * The whole view model comes from `readRunContextSnapshot`; this file only
2891
+ * formats. Two formatting rules carry the weight:
2892
+ *
2893
+ * - **Driver inference and child work never merge.** A supervisor's own
2894
+ * thinking and the work it spawned are separate lines on the same node,
2895
+ * because a single total cannot answer "which half spent the budget" — the
2896
+ * decisive question in three real runs, where a root burned its pool on its
2897
+ * own turns while its one child cost almost nothing.
2898
+ * - **Unknown is never rendered as zero.** `Spend.usdKnown === false` means
2899
+ * the harness did not price that inference; it does not mean the inference
2900
+ * was free. Those records are counted and named, never summed into `$0.00`.
2901
+ */
2902
+
2903
+ /**
2904
+ * The whole view for one snapshot. Pure: the same snapshot always renders the
2905
+ * same text, which is what lets the tail print only on change.
2906
+ */
2907
+ declare function renderRunContextSnapshot(snapshot: RunContextSnapshot): string;
2908
+ /**
2909
+ * The two run-level halves, each counted exactly once.
2910
+ *
2911
+ * Driver total sums every node's OWN `metered` inference, at any depth. Worker
2912
+ * total sums the settled spend of LEAF nodes only, because a nested
2913
+ * supervisor's settlement re-homes its whole subtree up to its parent — adding
2914
+ * it would count every grandchild twice, and the sub-total would silently
2915
+ * exceed the pool the run actually spent.
2916
+ */
2917
+ declare function runTotals(snapshot: RunContextSnapshot): {
2918
+ driver: SpendRoll;
2919
+ workers: SpendRoll;
2920
+ };
2921
+ /**
2922
+ * Resolve what the user pointed at: the run directory itself, or a parent
2923
+ * holding exactly one. A parent holding several is ambiguous and says so with
2924
+ * the candidates, rather than picking one.
2925
+ */
2926
+ declare function resolveRunContextDir(dir: string): Promise<string>;
2927
+
2928
+ /**
2929
+ * Formatting primitives shared by every `traces watch <target>` view.
2930
+ *
2931
+ * Two rules live here rather than in each renderer, because they are the whole
2932
+ * reason this view exists and a second copy would eventually disagree with the
2933
+ * first:
2934
+ *
2935
+ * - **Unknown is never rendered as zero.** A roll with no priced record prints
2936
+ * "cost unknown", not `$0.0000`. An unmetered turn and a free turn are
2937
+ * different facts.
2938
+ * - **A recorded $0 that burned tokens is printed AND flagged.** The recorded
2939
+ * value stands; the ambiguity is named next to it.
2940
+ *
2941
+ * Plain ASCII-plus-box-drawing, no cursor control and no colour: the output has
2942
+ * to survive SSH, a CI log, and a pipe into a file.
2943
+ */
2944
+
2945
+ declare const RULE: string;
2946
+ declare function int(n: number): string;
2947
+ declare function ms(value: number | null): string;
2948
+ /**
2949
+ * A dollar figure that keeps unknown out of the number. With no priced record
2950
+ * at all the answer is "cost unknown" — printing `$0.0000` there is the exact
2951
+ * fabrication this view exists to prevent.
2952
+ */
2953
+ declare function usd(roll: SpendRoll): string;
2954
+ /**
2955
+ * A roll that claims a price of exactly $0 while recording real tokens.
2956
+ *
2957
+ * agent-runtime's contract is that `Spend.usdKnown` absent means the dollar
2958
+ * figure IS known, so the honest number is $0 and this view prints it. But a
2959
+ * harness-billed brain (a CLI on a subscription) also records $0 without ever
2960
+ * setting `usdKnown:false`, and "free" and "unmetered" are the two facts this
2961
+ * view exists to keep apart. So the value stands and the ambiguity is named —
2962
+ * never the reverse.
2963
+ */
2964
+ declare function zeroPricedCost(roll: SpendRoll): boolean;
2965
+ declare function tokens(roll: SpendRoll): string;
2966
+ declare const STATUS_MARK: Record<string, string>;
2967
+ /**
2968
+ * Tree connectors for a depth-first node list. `lastAtDepth` records, per
2969
+ * ancestor level, whether that ancestor was its parent's last child, which is
2970
+ * what decides between a continuing `│` and a blank column — the difference
2971
+ * between a readable tree and an ambiguous indent at depth 3+.
2972
+ */
2973
+ declare function connectors(depth: number, lastAtDepth: readonly boolean[]): {
2974
+ head: string;
2975
+ detail: string;
2976
+ };
2977
+ /**
2978
+ * Walk a depth-first node list, handing each node the `lastAtDepth` state its
2979
+ * connectors need. A node is its parent's last child when no later node shares
2980
+ * that parent, which the caller's list order already encodes.
2981
+ */
2982
+ declare function forEachTreeNode<T extends {
2983
+ readonly depth: number;
2984
+ }>(nodes: readonly T[], parentKey: (node: T) => string | null, selfKey: (node: T) => string, visit: (node: T, lastAtDepth: readonly boolean[]) => void): void;
2985
+ /** Wrap to a terminal width so a long question is readable, never truncated. */
2986
+ declare function wrap(text: string, indent: number): string[];
2987
+
2988
+ /**
2989
+ * `traces watch <target>` — the live terminal view, over whichever sources the
2990
+ * target actually has.
2991
+ *
2992
+ * Two sources, one verb:
2993
+ *
2994
+ * - **General** — `run-span-tree.ts`, over OTLP spans. `trace_id` /
2995
+ * `span_id` / `parent_span_id` reconstruct the tree for ANY emitter, so a
2996
+ * system nobody has written yet is watchable the day it emits its first
2997
+ * span. It cannot report an authored budget, because no span vocabulary
2998
+ * carries one.
2999
+ * - **Specific** — `supervisor-run-context.ts`, over agent-runtime's durable
3000
+ * spawn journal. It carries the exact budget, spend, and settlement the
3001
+ * telemetry does not.
3002
+ *
3003
+ * When a run has both, the output shows both and LABELS which number came from
3004
+ * which: the journal section first, because its numbers are the authoritative
3005
+ * ones, then the span section for the shape and the per-turn detail. They are
3006
+ * never merged into one column, because a merged column cannot be audited —
3007
+ * and the numbers legitimately differ (a driver's spans price each turn; the
3008
+ * journal's `settled` re-homes a whole subtree onto its parent).
3009
+ *
3010
+ * Plain stdout, no dependency, no cursor control: it works over SSH, in a CI
3011
+ * log, and through a pipe. A block prints only when the rendered view changed,
3012
+ * so a long idle stretch never scrolls the last real event away.
3013
+ */
3014
+
3015
+ /** What a resolved target will be read from. At least one is always present. */
3016
+ interface RunWatchTarget {
3017
+ /** The directory holding `spawn-journal.jsonl`, when there is one. */
3018
+ readonly runDir: string | null;
3019
+ /** OTLP span files to fold, in read order. */
3020
+ readonly spanFiles: readonly string[];
3021
+ /** What the caller named, verbatim — the thing to print in an error. */
3022
+ readonly requested: string;
3023
+ }
3024
+ /**
3025
+ * Resolve what the user pointed at.
3026
+ *
3027
+ * A file the caller named is read as spans, whatever it is called. A directory
3028
+ * is the run directory when it holds a spawn journal, or the parent of exactly
3029
+ * one — the same rule `resolveRunContextDir` already applies — and either way
3030
+ * its span files come along. A directory with neither is an error naming both
3031
+ * things it looked for, because "nothing here" and "wrong kind of thing here"
3032
+ * are different mistakes.
3033
+ */
3034
+ declare function resolveRunWatchTarget(target: string): Promise<RunWatchTarget>;
3035
+ interface RunWatchSnapshot {
3036
+ readonly target: RunWatchTarget;
3037
+ /** Present only when the target has a spawn journal. */
3038
+ readonly journal: RunContextSnapshot | null;
3039
+ readonly spans: readonly SpanRunSnapshot[];
3040
+ /** True once every present source says the run is over. */
3041
+ readonly terminal: boolean;
3042
+ }
3043
+ declare function readRunWatchSnapshot(target: RunWatchTarget): Promise<RunWatchSnapshot>;
3044
+ declare function renderRunWatchSnapshot(snapshot: RunWatchSnapshot): string;
3045
+ interface WatchRunTargetOptions {
3046
+ /** Print one snapshot and return — what a script or an agent wants. */
3047
+ readonly once?: boolean;
3048
+ /** Poll period in ms (default 2000). */
3049
+ readonly intervalMs?: number;
3050
+ /** Where to write (default stdout). */
3051
+ readonly write?: (text: string) => void;
3052
+ readonly signal?: AbortSignal;
3053
+ /** Keep tailing after the run reaches a terminal state (default: stop). */
3054
+ readonly follow?: boolean;
3055
+ }
3056
+ /**
3057
+ * Tail a target until every source says the run is over. Prints a block only
3058
+ * when the rendered view changed, so the last thing on screen is always the
3059
+ * last thing that happened.
3060
+ */
3061
+ declare function watchRunTarget(target: RunWatchTarget, opts?: WatchRunTargetOptions): Promise<RunWatchSnapshot>;
3062
+
2055
3063
  /**
2056
3064
  * Privacy redaction for trace spans before upload.
2057
3065
  *
@@ -2110,6 +3118,206 @@ interface SessionBatch {
2110
3118
  /** Select + parse (+ redact) sessions into per-session span batches. */
2111
3119
  declare function collectSessions(opts?: CollectOptions): Promise<SessionBatch[]>;
2112
3120
 
3121
+ /**
3122
+ * Execution-replay verification for CodeTraceBench-style shell trajectories.
3123
+ *
3124
+ * Turns a cited analyst finding ("step k is the error-critical step") into an
3125
+ * executed proof: replay steps 1..k-1 inside a real sandbox on the
3126
+ * trajectory's own docker image, then
3127
+ * arm A — run the recorded step k and check the recorded failure signature
3128
+ * reproduces (returncode + a stable output substring), and
3129
+ * arm B — run a corrected step k and check the failure vanishes.
3130
+ *
3131
+ * Built on the agent-eval counterfactual scaffold: the trajectory is ingested
3132
+ * into a TraceStore, each arm is a `runCounterfactual` meta-run, and the
3133
+ * sandbox-backed `CounterfactualRunner` here supplies the `executeFrom`
3134
+ * callback that scaffold deliberately leaves to consumers.
3135
+ *
3136
+ * Honest limits:
3137
+ * - Only SWE-style trajectories carry `docker_config.base_image`; tasks whose
3138
+ * environment needs external compose peers cannot be replayed this way.
3139
+ * - Copy-on-write forks (`box.branch()`) are firecracker-only; on the docker
3140
+ * driver each arm replays the prefix in its own fresh sandbox instead.
3141
+ * - Prefix divergence (recorded vs replayed returncode) is recorded per step
3142
+ * and surfaced in the verdict, never hidden: a high divergence count is a
3143
+ * finding about replayability, not an error of the harness.
3144
+ */
3145
+
3146
+ /** Recorded returncode from a mini-SWE observation, or null when absent
3147
+ * (terminal submit steps carry no returncode tag). */
3148
+ declare function parseRecordedReturncode(observation: string | null): number | null;
3149
+ /** Text between the observation's <output> tags, or the raw observation when
3150
+ * the tags are absent. */
3151
+ declare function parseObservationOutput(observation: string | null): string;
3152
+ /**
3153
+ * Stable failure-signature candidate: the first line of the recorded output
3154
+ * that contains the word "error". Null when no such line exists — the verdict
3155
+ * then falls back to returncode-only matching and says so.
3156
+ * Pass an explicit signature to override (compiler quote glyphs vary with
3157
+ * locale, so a hand-picked ASCII substring is often more robust).
3158
+ */
3159
+ declare function deriveFailureSignature(observation: string | null): string | null;
3160
+ interface IngestedTrajectory {
3161
+ runId: string;
3162
+ stepCount: number;
3163
+ }
3164
+ /**
3165
+ * Emit one tool span per trajectory step, in order, with a monotonic
3166
+ * injected clock so `buildTrajectory` ordering is deterministic even when
3167
+ * two spans would share a Date.now() millisecond.
3168
+ */
3169
+ declare function ingestCodeTraceBenchSteps(store: TraceStore, steps: readonly CodeTraceBenchStep[], caseId: string): Promise<IngestedTrajectory>;
3170
+ interface ReplayExecResult {
3171
+ exitCode: number;
3172
+ stdout: string;
3173
+ stderr: string;
3174
+ }
3175
+ interface ReplayExecSession {
3176
+ exec(command: string, timeoutMs: number): Promise<ReplayExecResult>;
3177
+ close(): Promise<void>;
3178
+ }
3179
+ interface ReplayExecBackend {
3180
+ open(): Promise<ReplayExecSession>;
3181
+ }
3182
+ interface SandboxReplayBackendOptions {
3183
+ image: string;
3184
+ apiKey: string;
3185
+ baseUrl: string;
3186
+ maxLifetimeSeconds?: number;
3187
+ /**
3188
+ * The local SDK-adapter test harness does not translate `agent: false`
3189
+ * into the platform-control-runtime marker the way the production
3190
+ * sandbox API does, so images without node need the marker passed as
3191
+ * container env. Harmless against the production API path. Default true.
3192
+ */
3193
+ platformRuntimeEnvMarker?: boolean;
3194
+ }
3195
+ /** One fresh sandbox per open(); close() deletes it. */
3196
+ declare function sandboxReplayBackend(options: SandboxReplayBackendOptions): ReplayExecBackend;
3197
+ /**
3198
+ * mini-SWE runs every action as a fresh /bin/sh subshell from a fixed
3199
+ * workdir. Reproduce that exactly — and stay quote-proof for arbitrary
3200
+ * recorded actions — by piping the base64 of the action into `sh` after
3201
+ * cd-ing to the workdir. Exit code is sh's, i.e. the action's.
3202
+ */
3203
+ declare function wrapActionForExec(action: string, cwd: string): string;
3204
+ interface PrefixDivergence {
3205
+ step: number;
3206
+ expectedReturncode: number | null;
3207
+ actualExit: number;
3208
+ }
3209
+ interface PrefixReplayResult {
3210
+ prefixExecuted: number;
3211
+ prefixDivergences: PrefixDivergence[];
3212
+ wallMs: number;
3213
+ }
3214
+ interface ArmExecutionResult {
3215
+ command: string;
3216
+ exitCode: number;
3217
+ stdout: string;
3218
+ stderr: string;
3219
+ wallMs: number;
3220
+ }
3221
+ interface SandboxCounterfactualRunnerOptions {
3222
+ cwd: string;
3223
+ stepTimeoutMs: number;
3224
+ /** Execute at most this many prefix steps (from the start). Fast-iteration
3225
+ * knob; a truncated prefix weakens state fidelity and the verdict says so. */
3226
+ prefixLimit?: number;
3227
+ onProgress?: (message: string) => void;
3228
+ }
3229
+ /**
3230
+ * Replays `ctx.prefix` in a fresh sandbox session, then executes the mutated
3231
+ * step. Divergences are recorded and never abort the replay. Results land on
3232
+ * `lastPrefix` / `lastArm` for the caller; spans for every exec land in the
3233
+ * counterfactual meta-run.
3234
+ */
3235
+ declare class SandboxCounterfactualRunner implements CounterfactualRunner {
3236
+ private readonly backend;
3237
+ private readonly options;
3238
+ lastPrefix: PrefixReplayResult | null;
3239
+ lastArm: ArmExecutionResult | null;
3240
+ constructor(backend: ReplayExecBackend, options: SandboxCounterfactualRunnerOptions);
3241
+ executeFrom(ctx: CounterfactualContext, emitter: TraceEmitter): Promise<void>;
3242
+ }
3243
+ interface ReplayVerifyOptions {
3244
+ stepsPath: string;
3245
+ image: string;
3246
+ /** 1-based step_id of the error-critical step (matches CodeTraceBench). */
3247
+ at: number;
3248
+ /** Corrected command for arm B. Omit to run arm A only. */
3249
+ fixCommand?: string;
3250
+ cwd: string;
3251
+ out: string;
3252
+ caseId?: string;
3253
+ /** Override the auto-derived failure signature substring. */
3254
+ signature?: string;
3255
+ stepTimeoutMs?: number;
3256
+ prefixLimit?: number;
3257
+ /** Label of the orchestrator driver backing the sandbox (reported, not probed). */
3258
+ driverLabel?: string;
3259
+ /** Injectable for tests; defaults to sandboxReplayBackend(). */
3260
+ backend?: ReplayExecBackend;
3261
+ apiKey?: string;
3262
+ baseUrl?: string;
3263
+ maxLifetimeSeconds?: number;
3264
+ onProgress?: (message: string) => void;
3265
+ }
3266
+ interface ReplayArmVerdict {
3267
+ command: string;
3268
+ exitCode: number;
3269
+ wallMs: number;
3270
+ prefix: PrefixReplayResult;
3271
+ }
3272
+ interface ReplayVerdict {
3273
+ case: string;
3274
+ image: string;
3275
+ driver: string;
3276
+ k: number;
3277
+ cwd: string;
3278
+ recordedReturncode: number | null;
3279
+ signature: string | null;
3280
+ signatureBasis: 'returncode+output-substring' | 'returncode-only';
3281
+ prefixExecuted: number;
3282
+ prefixDivergences: PrefixDivergence[];
3283
+ armA: ReplayArmVerdict & {
3284
+ failureSignatureMatch: boolean;
3285
+ };
3286
+ armB: (ReplayArmVerdict & {
3287
+ failureVanished: boolean;
3288
+ }) | null;
3289
+ timings: {
3290
+ armAMs: number;
3291
+ armBMs: number | null;
3292
+ totalMs: number;
3293
+ };
3294
+ runIds: {
3295
+ original: string;
3296
+ armA: string;
3297
+ armB: string | null;
3298
+ };
3299
+ }
3300
+ declare function replayVerify(options: ReplayVerifyOptions): Promise<ReplayVerdict>;
3301
+ interface ReplayVerifyCliArgs {
3302
+ stepsPath: string;
3303
+ image: string;
3304
+ at: number;
3305
+ fixCommand?: string;
3306
+ cwd: string;
3307
+ out: string;
3308
+ caseId?: string;
3309
+ signature?: string;
3310
+ stepTimeoutMs?: number;
3311
+ prefixLimit?: number;
3312
+ driverLabel?: string;
3313
+ baseUrl: string;
3314
+ apiKeyEnv: string;
3315
+ maxLifetimeSeconds?: number;
3316
+ }
3317
+ declare function parseReplayVerifyArgs(argv: readonly string[]): ReplayVerifyCliArgs | 'help';
3318
+ declare function replayVerifyUsage(): string;
3319
+ declare function cmdReplayVerify(argv: readonly string[]): Promise<void>;
3320
+
2113
3321
  /**
2114
3322
  * Local upload-dedup state.
2115
3323
  *
@@ -2212,4 +3420,4 @@ interface ExecuteOptions {
2212
3420
  /** Send the final, new outbound items (or write their dry-run OTLP). */
2213
3421
  declare function executeUpload(plan: UploadPlan, opts?: ExecuteOptions): Promise<UploadResult>;
2214
3422
 
2215
- export { ACTOR_ATTR, ATTR, type Actor, type AdoptionOptions, type AdoptionReport, AmpAdapter, type AnalyzeOptions, type AnalyzeResult, type BuildPolicyEvidenceOptions, type BuildSessionIndexOptions, type BuildTraceFindingPacketOptions, CODING_REDACTION_RULES, CONTENT_CAP, CORRECTIVE_REACTIONS, type ChatTrajectory, type ChatTrajectoryMessage, type ChatTrajectoryOptions, ClaudeAdapter, type CodeTraceBenchFileRef, type CodeTraceBenchImportOptions, type CodeTraceBenchImportReceipt, type CodeTraceBenchImportResult, type CodeTraceBenchImportedTrace, type CodeTraceBenchStep, CodexAdapter, CodexExecAdapter, CodexExecStreamError, CodexTaskScopeError, type CollectOptions, type CollectPolicyEvidenceOptions, type CollectSessionIndexOptions, type CollectSessionSelectionOptions, type CollectSessionWorkflowOptions, CopilotAdapter, type CorruptionMode, DEFAULT_HARNESS, EmptySessionError, type ExecuteOptions, type ExternalAnalysisKind, type ExternalAnalysisPayload, type ExternalAnalysisResult, type ExternalAnalyzer, type ExternalAnalyzerOptions, type ExternalDiscoveryCandidate, FactoryAdapter, ForgeAdapter, GeminiAdapter, type HaloAnalyzerOptions, type HaloReasoningEffort, type HarnessTraceAdapter, type HodoscopeAnalyzerOptions, type HodoscopeInput, type HodoscopeMessage, type HodoscopeSourceMapEntry, type HodoscopeTrajectory, INGEST_SOURCE_CLI, type InspectSessionIndexOptions, JsonSourceError, type JsonlCorruptionReceipt, JsonlParseError, type JsonlReadOptions, type LiveBatchOptions, type LocateOptions, type ObservedLoop, type ObserverOptions, OpencodeAdapter, type OtlpSpan, type OtlpSpanKind, type OtlpStatusCode, type ParentTaskResolution, type ParseOptions, PartialUploadError, 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 SessionCorruptionReceipt, type SessionIdentityConflict, type SessionIdentityIndex, type SessionIntegrity, type SessionRef, type SessionRelationship, type SessionRole, type SessionSeedGroup, type SessionSelection, type SessionSelectionRow, type SessionSourceFile, type SessionWorkflow, SessionWorkflowError, type SessionWorkflowErrorCode, type SessionWorkflowIssue, type SessionWorkflowSession, type SessionWorkflowSummary, type SpanInput, type SpanRedaction, TRACES_REDACTION_RULES, type TraceAgenticRoute, type TraceAgenticRouteReason, type TraceAgenticRouteReasonCode, type TraceContextIndex, type TraceContextRoot, type TraceEvidenceExportOptions, type TraceEvidenceExportResult, type TraceEvidenceFormatOption, type TraceEvidenceInputFormat, type TraceEvidenceRow, type TraceExecutionOptions, type TraceFindingPacket, type TraceImprovementArtifacts, type TraceImprovementOptions, type TraceImprovementResult, type TraceIndexedFile, type TraceInspectionArea, type TraceInspectionFinding, type TraceInspectionReport, type TraceInspectionSeverity, type TraceInvestigationOptions, type TraceInvestigationResult, type TraceLiveAction, type TraceLiveActionKind, type TraceLiveAnalysisContext, type TraceLiveAnalyst, type TraceLiveBatch, type TraceLiveEvidence, type TraceLiveFinding, type TraceLiveLoop, type TraceLiveSeverity, type TraceSessionIndex, type TraceSessionIndexRow, type TraceStoreInvestigationOptions, type TraceStoreInvestigationResult, type TraceStreamEvent, type TraceStreamOptions, type TraceStreamReplayOptions, type TraceStreamSession, type TracesConfig, type TriggerPair, type UploadBackend, type UploadIdentity, type UploadItem, type UploadPlan, type UploadRecord, type UploadResult, type UploadState, type UserPromptInput, alreadyUploaded, analyzeAdoption, analyzeLiveBatch, analyzeReactions, analyzeSpans, applyRedactor, buildPolicyEvidenceRecord, buildSessionIndex, buildSessionIndexFromRows, buildTraceFindingPacket, capText, chatTrajectoryToSpans, classifyLiveActions, classifyReaction, claudeActor, codexActor, collectPolicyEvidence, collectSessionIndex, collectSessionSelection, collectSessionWorkflow, collectSessions, commandAnalyzer, commandRedactor, countSkillRunsJsonl, cwdMatchesSelection, defaultTraceLiveAnalysts, describeSessionRelationship, equivalentGitCwds, executeUpload, exportTraceEvidenceFile, exportTraceEvidenceRows, exportTraceEvidenceText, haloAnalyzer, hodoscopeAnalyzer, importCodeTraceBench, indexSessionIdsByTrace, inspectSessionIndex, isChatTrajectory, isChatTrajectoryMessage, knownHarnesses, listAdapters, loadState, loadTracesConfig, locateSessions, looksLikeAgentPrompt, mergeTracesConfig, normalizeRemote, outboundHash, parseIsoToEpochMs, parseSession, parseSince, planTraceAgenticRoute, planUpload, readJsonFile, readJsonl, readSessionIndexFile, recordSessionCorruption, redactSpans, renderInspectionReport, resolveAdapter, resolveRepoAttrs, resolveSessionRepoAttrs, runCommand, runExternalAnalyzers, runPipelines, runTraceImprovement, runTraceInvestigation, runTraceStoreInvestigation, saveReport, saveState, scanSessions, selectAdapters, serializeInspectionReport, serializePolicyEvidence, serializeSessionIndex, serializeSpans, serializeTraceStreamEvent, sessionHash, sessionIdFromAttributes, sessionIntegrityAttributes, span, stampRepoAttrs, stampSessionIdentity, stampSessionIntegrity, stampSpanWorkdirRepoAttrs, streamSessions, summarizeOtlpExecution, summarizeSpanExecution, takeJsonl, textIsSynthetic, toOpenInferenceSpan, toRuntimeStore, toTraceSpanEvents, totalAgenticFailureMessage, traceAgenticKinds, traceStreamEventsFromSpans, uploadKey, userPromptSpan, validateOtlpSpans, watchSessions, writeHodoscopeInput, writeInspectionReportFile, writeOtlpFile, writePolicyEvidenceFile, writeSessionIndexFile, writeTraceEvidenceExportFile, writeTraceImprovementArtifacts };
3423
+ export { ACTOR_ATTR, ATTR, type Actor, type AdoptionOptions, type AdoptionReport, AmpAdapter, type AnalyzeOptions, type AnalyzeResult, type ArmExecutionResult, BLOBS_DIR, type BuildPolicyEvidenceOptions, type BuildSessionIndexOptions, type BuildTraceFindingPacketOptions, CODING_REDACTION_RULES, CONTENT_CAP, COORDINATION_LOG_FILE, CORRECTIVE_REACTIONS, type ChatTrajectory, type ChatTrajectoryMessage, type ChatTrajectoryOptions, ClaudeAdapter, type CodeTraceBenchFileRef, type CodeTraceBenchImportOptions, type CodeTraceBenchImportReceipt, type CodeTraceBenchImportResult, type CodeTraceBenchImportedTrace, type CodeTraceBenchStep, CodexAdapter, CodexExecAdapter, CodexExecStreamError, CodexTaskScopeError, type CollectOptions, type CollectPolicyEvidenceOptions, type CollectSessionIndexOptions, type CollectSessionSelectionOptions, type CollectSessionWorkflowOptions, type ConformanceRenderOptions, type CoordinationLog, type CoordinationQuestion, type CoordinationSteer, CopilotAdapter, type CorruptionMode, DEFAULT_HARNESS, EMPTY_SPAN_RUN_SNAPSHOT, EXPORT_RULE, EmptySessionError, type ExecuteOptions, type ExportRule, type ExternalAnalysisKind, type ExternalAnalysisPayload, type ExternalAnalysisResult, type ExternalAnalyzer, type ExternalAnalyzerOptions, type ExternalDiscoveryCandidate, FactoryAdapter, type FileRunContextReaderOptions, ForgeAdapter, GeminiAdapter, type HaloAnalyzerOptions, type HaloReasoningEffort, type HarnessTraceAdapter, type HodoscopeAnalyzerOptions, type HodoscopeInput, type HodoscopeMessage, type HodoscopeSourceMapEntry, type HodoscopeTrajectory, INGEST_SOURCE_CLI, type IngestedTrajectory, type InspectSessionIndexOptions, JsonSourceError, type JsonlCorruptionReceipt, JsonlParseError, type JsonlReadOptions, type LiveBatchOptions, type LocateOptions, type LoopConvergence, type LoopConvergenceReport, type LoopIteration, type LoopTrend, type LoopTrendBasis, type ObservedLoop, type ObserverOptions, OpencodeAdapter, type OtlpIngestIssue, type OtlpIngestIssueKind, type OtlpInput, type OtlpInputFile, type OtlpRowConversion, type OtlpSpan, type OtlpSpanKind, type OtlpSpanLink, type OtlpStatusCode, type ParentTaskResolution, type ParseOptions, PartialUploadError, PiAdapter, type PipelineOptions, type PipelineReport, type PlanOptions, type PolicyEvidenceLoopSummary, type PolicyEvidenceRecord, type PolicyEvidenceToolSummary, type PrefixDivergence, type PrefixReplayResult, QwenAdapter, REACTIONS, RESULT_FILE, RULE, type Reaction, type ReactionReport, type ReactionSessionReport, type Redactor, type ReplayArmVerdict, type ReplayExecBackend, type ReplayExecResult, type ReplayExecSession, type ReplayVerdict, type ReplayVerifyCliArgs, type ReplayVerifyOptions, type RepoAttrs, type RepoResolution, type RepoResolutionSource, type ResolvedOtlpInput, type RunContextJournal, type RunContextNode, type RunContextResult, type RunContextSnapshot, type RunResult, type RunWatchSnapshot, type RunWatchTarget, type RuntimeTrace, SPAWN_JOURNAL_FILE, STATUS_MARK, SandboxCounterfactualRunner, type SandboxCounterfactualRunnerOptions, type SandboxReplayBackendOptions, type ScanOptions, type ScannedSession, type SessionBatch, type SessionCorruptionReceipt, type SessionIdentityConflict, type SessionIdentityIndex, type SessionIntegrity, type SessionRef, type SessionRelationship, type SessionRole, type SessionSeedGroup, type SessionSelection, type SessionSelectionRow, type SessionSourceFile, type SessionWorkflow, SessionWorkflowError, type SessionWorkflowErrorCode, type SessionWorkflowIssue, type SessionWorkflowSession, type SessionWorkflowSummary, type SkippedAnalysis, type SkippedInputFile, type SpanInput, type SpanNodeStatus, type SpanRedaction, type SpanRunNode, type SpanRunSnapshot, type SpanStructure, type SpendRoll, type SteeringChainReport, type SteeringEdge, TRACES_REDACTION_RULES, type TraceAgenticRoute, type TraceAgenticRouteReason, type TraceAgenticRouteReasonCode, type TraceContextIndex, type TraceContextRoot, type TraceEvidenceExportOptions, type TraceEvidenceExportResult, type TraceEvidenceFormatOption, type TraceEvidenceInputFormat, type TraceEvidenceRow, type TraceExecutionOptions, type TraceFindingPacket, type TraceImprovementArtifacts, type TraceImprovementOptions, type TraceImprovementResult, type TraceIndexedFile, type TraceInspectionArea, type TraceInspectionFinding, type TraceInspectionReport, type TraceInspectionSeverity, type TraceInvestigationOptions, type TraceInvestigationResult, type TraceLiveAction, type TraceLiveActionKind, type TraceLiveAnalysisContext, type TraceLiveAnalyst, type TraceLiveBatch, type TraceLiveEvidence, type TraceLiveFinding, type TraceLiveLoop, type TraceLiveSeverity, type TraceSessionIndex, type TraceSessionIndexRow, type TraceStoreInvestigationOptions, type TraceStoreInvestigationResult, type TraceStreamEvent, type TraceStreamOptions, type TraceStreamReplayOptions, type TraceStreamSession, type TracesConfig, type TriggerPair, type UnavailableCapabilities, type UploadBackend, type UploadIdentity, type UploadItem, type UploadPlan, type UploadRecord, type UploadResult, type UploadState, type UserPromptInput, type WatchRunTargetOptions, ZERO_ROLL, addSpend, alreadyUploaded, analyzeAdoption, analyzeLiveBatch, analyzeLoopConvergence, analyzeReactions, analyzeSpans, analyzeSteeringChain, applyRedactor, buildPolicyEvidenceRecord, buildSessionIndex, buildSessionIndexFromRows, buildSpanRunTree, buildTraceFindingPacket, capText, chatTrajectoryToSpans, classifyLiveActions, classifyReaction, claudeActor, cmdReplayVerify, codexActor, collectPolicyEvidence, collectSessionIndex, collectSessionSelection, collectSessionWorkflow, collectSessions, commandAnalyzer, commandRedactor, conformanceOfSpans, connectors, countSkillRunsJsonl, cwdMatchesSelection, defaultTraceLiveAnalysts, deriveFailureSignature, describeSessionRelationship, equivalentGitCwds, executeUpload, exportTraceEvidenceFile, exportTraceEvidenceRows, exportTraceEvidenceText, fileRunContextSupervisorRunReader, findSpanSourceFiles, forEachTreeNode, haloAnalyzer, hodoscopeAnalyzer, importCodeTraceBench, incompleteInputsNote, indexSessionIdsByTrace, inferRole, inferSpanKind, ingestCodeTraceBenchSteps, inspectSessionIndex, int, isChatTrajectory, isChatTrajectoryMessage, isFileRunContextDir, knownHarnesses, listAdapters, loadState, loadTracesConfig, locateSessions, looksLikeAgentPrompt, mergeRolls, mergeTracesConfig, ms, normalizeRemote, otlpRowToSpan, outboundHash, parseIsoToEpochMs, parseObservationOutput, parseRecordedReturncode, parseReplayVerifyArgs, parseSession, parseSince, planTraceAgenticRoute, planUpload, readCoordinationLog, readFileRunContext, readJsonFile, readJsonl, readOtlpInput, readRunContextJournal, readRunContextSnapshot, readRunWatchSnapshot, readSessionIndexFile, readSpanRunSnapshot, recordSessionCorruption, redactSpans, renderConformance, renderInspectionReport, renderRunContextSnapshot, renderRunWatchSnapshot, renderSpanRunSnapshot, renderValidation, replayVerify, replayVerifyUsage, resolveAdapter, resolveOtlpInputFiles, resolveRepoAttrs, resolveRunContextDir, resolveRunWatchTarget, resolveSessionRepoAttrs, runCommand, runExternalAnalyzers, runPipelines, runTotals, runTraceImprovement, runTraceInvestigation, runTraceStoreInvestigation, sandboxReplayBackend, saveReport, saveState, scanSessions, selectAdapters, serializeInspectionReport, serializePolicyEvidence, serializeSessionIndex, serializeSpans, serializeTraceStreamEvent, sessionHash, sessionIdFromAttributes, sessionIntegrityAttributes, skippedAnalyses, span, spanRunTotals, stampRepoAttrs, stampSessionIdentity, stampSessionIntegrity, stampSpanWorkdirRepoAttrs, streamSessions, summarizeOtlpExecution, summarizeSpanExecution, summarizeSpanStructure, takeJsonl, textIsSynthetic, toOpenInferenceSpan, toRuntimeStore, toTraceSpanEvents, tokens, totalAgenticFailureMessage, traceAgenticKinds, traceStreamEventsFromSpans, unavailableCapabilities, uploadKey, usd, userPromptSpan, validateOtlpSpans, validationExitCode, watchRunTarget, watchSessions, wrap, wrapActionForExec, writeHodoscopeInput, writeInspectionReportFile, writeOtlpFile, writePolicyEvidenceFile, writeSessionIndexFile, writeTraceEvidenceExportFile, writeTraceImprovementArtifacts, zeroPricedCost };