@tangle-network/traces 0.22.0 → 0.23.0
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/README.md +21 -5
- package/dist/{chunk-DON6NQ7H.js → chunk-COSWFESO.js} +211 -66
- package/dist/cli.js +69 -11
- package/dist/index.d.ts +94 -6
- package/dist/index.js +9 -1
- package/docs/trace-analysts.md +3 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -295,6 +295,7 @@ traces investigate --all --last 10 --out report.md # explicit investigation ali
|
|
|
295
295
|
traces improve --all --last 10 --dir .traces/improvement
|
|
296
296
|
traces ask --harness codex --session <id> --question "Which commands failed?"
|
|
297
297
|
traces facts --harness codex --session <id> # the deterministic facts sheet, $0
|
|
298
|
+
traces facts --all --since 2026-10-14 --until 2026-10-15 # every session with a record that day, that day's turns
|
|
298
299
|
traces skills --since 30d # skill use across every local session, incremental, $0
|
|
299
300
|
traces diff run-a.otlp.jsonl run-b.otlp.jsonl # where two runs of one task first diverge
|
|
300
301
|
traces mcp --otlp spans.otlp.jsonl # read-only trace tools for an MCP client
|
|
@@ -347,7 +348,8 @@ See [Replay verification](./docs/replay-verify.md) for setup, semantics, and hon
|
|
|
347
348
|
| `--workflow` | Expand selected files through stable parent and child session IDs |
|
|
348
349
|
| `--max-workflow-sessions <n>` | Stop workflow expansion before parsing more than `n` files; default `100` |
|
|
349
350
|
| `--cwd <dir>` | Filter by working directory |
|
|
350
|
-
| `--since <t>` | `
|
|
351
|
+
| `--since <t>` | `30m`/`2h`/`7d` before now, or an ISO date. Commands that select sessions read those modified at or after it; `upload`: its window (default 24h); `facts`: opens a time window — see [Session facts](#session-facts) |
|
|
352
|
+
| `--until <t>` | `facts`: closes the time window (exclusive), same forms as `--since` |
|
|
351
353
|
| `--out <path>` | Write the report to a file |
|
|
352
354
|
| `--dir <path>` | `improve`: write the full artifact pack to this directory; `ask`: write `answers.json` + `report.md` there |
|
|
353
355
|
| `--otlp <file\|dir>` | **READ** OTLP-JSONL from any system, skipping the adapters; a directory reads the OTLP files under it (only `otlp/` when the producer made one) and names the JSONL that is not OTLP. `validate`, `check`, `analyze`, `investigate`, `improve`, `ask`, `stream` |
|
|
@@ -590,11 +592,14 @@ The same facts sheet includes observed tool outcomes, captured input/output byte
|
|
|
590
592
|
volumes, call-to-result intervals, compaction boundaries and available context
|
|
591
593
|
sizes, spawn intervals, and existing skill invocation/document-read evidence.
|
|
592
594
|
Each measurement carries coverage; absent telemetry remains unknown.
|
|
593
|
-
`facts --no-content` withholds conversation
|
|
594
|
-
|
|
595
|
+
`facts --no-content` withholds conversation (including each turn's `answered` text),
|
|
596
|
+
command, changed-file, working-directory and assignment text while retaining
|
|
597
|
+
measurement metadata. This is a local metadata view, not a
|
|
595
598
|
share-safety certificate.
|
|
596
599
|
|
|
597
600
|
SDK consumers use `buildSessionFactsReport(spans, { includeContent: false })`.
|
|
601
|
+
Pass `window: { since, until }` (ISO bounds) for the windowed report `facts --since/--until` prints, and use
|
|
602
|
+
`createSessionFactsReportBuilder(options)` (`add(spans)`, `addUnread(...)`, `build()`) to build it one session at a time.
|
|
598
603
|
Cache by `measurementVersion` and `sourceDigest`; `evidenceThrough` is the latest
|
|
599
604
|
recorded endpoint, not current liveness. Computing the sheet parses the supplied
|
|
600
605
|
spans; returning a stored sheet needs no model call or trace scan. Semantic
|
|
@@ -608,8 +613,17 @@ No model call, no engine, no budget — it costs $0 and always returns the same
|
|
|
608
613
|
traces facts --harness codex --session <id> # JSON on stdout
|
|
609
614
|
traces facts --harness codex --last 5 --format text # the short readable form
|
|
610
615
|
traces facts --otlp spans.otlp.jsonl --out facts.json
|
|
616
|
+
traces facts --harness claude-code --since 7d # every session with a record in the last week
|
|
617
|
+
traces facts --all --since 2026-10-14 --until 2026-10-15 # one day, across every harness
|
|
611
618
|
```
|
|
612
619
|
|
|
620
|
+
`--since <t>` and `--until <t>` open a half-open time window `[since, until)`; each takes `30m`/`2h`/`7d` before now or an ISO date, and either may be left open.
|
|
621
|
+
With a window, `facts` selects **every** session with a record that starts or ends inside it, not only the newest (`--last <n>` still caps it to the newest `n` per harness, and `--session` or `--otlp` still name the input).
|
|
622
|
+
Sessions are read one at a time, and a session file last modified before `since` is not read, because it cannot hold a later record.
|
|
623
|
+
Within a selected session, `humanTurns`, `excludedTurns` and `turnsByActor` keep only turns that started inside the window, so a one-day run counts only that day's turns; every other fact covers the whole session.
|
|
624
|
+
The report's `selection` states the window, both rules, the sessions read whose records all fell outside it (`outsideWindow`), and every session that could not be read (`unreadSessions`, each with its reason).
|
|
625
|
+
A report built without a window has `selection: null`.
|
|
626
|
+
|
|
613
627
|
| Fact | What it is |
|
|
614
628
|
|---|---|
|
|
615
629
|
| `toolCalls` | TOOL spans **this session's agent** actually invoked. Synthesized lifecycle spans are excluded and counted in `synthesizedToolSpans`, so the total is not high by the number of subagents; calls a spawned subagent made are excluded and counted in `subagentToolSpans` |
|
|
@@ -617,7 +631,8 @@ traces facts --otlp spans.otlp.jsonl --out facts.json
|
|
|
617
631
|
| `subagentToolSpans` | TOOL spans excluded because a subagent, not this agent, made the call. Zero on a trace that carries no subagent records |
|
|
618
632
|
| `subagents` | every subagent-spawning call with the task name the adapter recorded |
|
|
619
633
|
| `pullRequests` | the pull requests the commands created and merged, each named by number or head branch, with the command span and how the identity was joined. Scanned the way a shell reads the script, so a `gh pr create` inside a heredoc body is not a command that ran |
|
|
620
|
-
| `
|
|
634
|
+
| `cwd` | the working directory the harness recorded for the session (`traces.session.cwd` on the root span): Claude Code's first record `cwd`, Codex's `session_meta` cwd, Pi's session header, OpenCode's session directory (the older JSON store: its messages' `path.cwd`), Factory's `session_start`. Never decoded from a directory name or inferred from paths; `null` with the reason when the source names none or its adapter does not read one |
|
|
635
|
+
| `humanTurns` | `user.prompt` turns a person typed into this session, in order, with the timestamp. Inherited fork or compaction history, harness-injected blocks, and a second record of the same turn are excluded — each listed in `excludedTurns` with its reason and span ids, never silently dropped. `turnsByActor` shows every turn by actor so the filter is checkable. Each turn's `answered` is the last message this session's own agent wrote before it (not a subagent's, not inherited history), clipped to 1,500 characters with a `… [+N chars]` marker, with its span in `answeredSpanId`; `null` when the agent had written no text yet in the spans read (a `--latest-turn` read starts at the latest task, so its first turn has none) |
|
|
621
636
|
| `finalMessages` | the last message of the session's own agent, and of each subagent task, kept apart |
|
|
622
637
|
| `changedFiles` | paths the harness recorded for the changes it applied, plus paths named by patch headers and file-editing tool arguments, with the operation |
|
|
623
638
|
| `firstRecordAt` / `lastRecordAt` | the earliest span start and latest span end among this session's own records — a subagent that outlives the session does not stretch its window |
|
|
@@ -631,7 +646,8 @@ Three rules hold for every field:
|
|
|
631
646
|
- **Every fact names its span ids.** `spanIds` lists the spans the value was computed from, so any number here can be opened and checked. The sheet itself is not a span and cannot be cited.
|
|
632
647
|
- **A fact the spans cannot support is `null` with its reason.** It is never guessed, and never a silent zero. `partial` marks a measured value that is known to be incomplete — a truncated patch, or a list above the entry cap.
|
|
633
648
|
|
|
634
|
-
`facts` exits non-zero when a selected session cannot be read at all: a session that produced no record spans would otherwise print a sheet of zeros stating, in the sheet's own voice, that the session did nothing.
|
|
649
|
+
Without a window, `facts` exits non-zero when a selected session cannot be read at all: a session that produced no record spans would otherwise print a sheet of zeros stating, in the sheet's own voice, that the session did nothing.
|
|
650
|
+
With a window, a session that cannot be read — the parser failed, or no record could be read — is named in `selection.unreadSessions` with its reason and a warning on stderr, and the run still exits 0 with the sessions it could read; it is never counted as a session with no turns.
|
|
635
651
|
|
|
636
652
|
The same sheet reaches the model-backed analysts as prepared context, before their first model call — see [Trace analysts](docs/trace-analysts.md#session-facts-as-prepared-context).
|
|
637
653
|
|
|
@@ -151,6 +151,7 @@ var ATTR = {
|
|
|
151
151
|
* in-container path even when no such path exists on this host. */
|
|
152
152
|
ENVIRONMENT_CWD: "tangle.environment.cwd"
|
|
153
153
|
};
|
|
154
|
+
var SESSION_CWD_ATTR = "traces.session.cwd";
|
|
154
155
|
var INGEST_SOURCE_CLI = "cli";
|
|
155
156
|
function environmentAttributes(environment) {
|
|
156
157
|
if (!environment) return {};
|
|
@@ -254,6 +255,9 @@ function parseIsoToEpochMs(ts) {
|
|
|
254
255
|
return n;
|
|
255
256
|
}
|
|
256
257
|
function parseSince(value) {
|
|
258
|
+
return parseTimeBound(value, "--since");
|
|
259
|
+
}
|
|
260
|
+
function parseTimeBound(value, flag) {
|
|
257
261
|
const m = value.match(/^(\d+)\s*([mhd])$/i);
|
|
258
262
|
if (m) {
|
|
259
263
|
const unit = m[2].toLowerCase();
|
|
@@ -261,7 +265,7 @@ function parseSince(value) {
|
|
|
261
265
|
return Date.now() - Number(m[1]) * ms2;
|
|
262
266
|
}
|
|
263
267
|
const t = Date.parse(value);
|
|
264
|
-
if (Number.isNaN(t)) throw new Error(
|
|
268
|
+
if (Number.isNaN(t)) throw new Error(`${flag}: expected 30m / 2h / 7d or an ISO date, got "${value}"`);
|
|
265
269
|
return t;
|
|
266
270
|
}
|
|
267
271
|
|
|
@@ -2585,6 +2589,7 @@ var GeminiAdapter = class extends GeminiFamilyAdapter {
|
|
|
2585
2589
|
};
|
|
2586
2590
|
|
|
2587
2591
|
// src/adapters/actor.ts
|
|
2592
|
+
import { claudeRecordIsMachine } from "@tangle-network/harness-sessions";
|
|
2588
2593
|
var CMD_MARKERS = [
|
|
2589
2594
|
"<command-name>",
|
|
2590
2595
|
"<local-command-caveat>",
|
|
@@ -2633,22 +2638,6 @@ var SYNTHETIC_MARKERS = [
|
|
|
2633
2638
|
"Staff-engineer code review"
|
|
2634
2639
|
];
|
|
2635
2640
|
var AGENT_PROMPT = /^(you are\b|you're\b|read[- ]only\b|stop now\b|your task\b|your job\b|review the\b|audit\b|analyze the\b|return (only|a |the )|here is the\b|context:|task:|do not (revert|edit|touch)|work only in\b|you have been\b|act as\b|operate the\b|goal:|objective:)/i;
|
|
2636
|
-
var CLAUDE_MACHINE_PREFIXES = [
|
|
2637
|
-
"<local-command-caveat>",
|
|
2638
|
-
"<local-command-stdout>",
|
|
2639
|
-
"<local-command-stderr>",
|
|
2640
|
-
"Caveat: The messages below",
|
|
2641
|
-
"<task-notification>",
|
|
2642
|
-
"<bash-stdout>",
|
|
2643
|
-
"<bash-stderr>",
|
|
2644
|
-
"<user-prompt-submit-hook>",
|
|
2645
|
-
"[Request interrupted by user"
|
|
2646
|
-
];
|
|
2647
|
-
function claudeRecordIsMachine(args) {
|
|
2648
|
-
if (args.isMeta === true || args.isCompactSummary === true || args.entrypoint === "sdk-cli") return true;
|
|
2649
|
-
const text2 = args.text.trimStart();
|
|
2650
|
-
return CLAUDE_MACHINE_PREFIXES.some((prefix) => text2.startsWith(prefix));
|
|
2651
|
-
}
|
|
2652
2641
|
function textIsCmdOrInject(s) {
|
|
2653
2642
|
return CMD_MARKERS.some((m) => s.includes(m)) || INJECT_MARKERS.some((m) => s.includes(m));
|
|
2654
2643
|
}
|
|
@@ -2686,7 +2675,7 @@ function claudePromptStartsTask(args) {
|
|
|
2686
2675
|
}
|
|
2687
2676
|
function claudeActor(args) {
|
|
2688
2677
|
if (args.isSidechain === true) return "subagent-spawn";
|
|
2689
|
-
if (claudeRecordIsMachine(args)) return "injected";
|
|
2678
|
+
if (claudeRecordIsMachine({ ...args, entrypoint: args.entrypoint ?? void 0 })) return "injected";
|
|
2690
2679
|
if (args.userType != null && args.userType !== "external") return "injected";
|
|
2691
2680
|
if (textIsCmdOrInject(args.text)) return "injected";
|
|
2692
2681
|
if (textIsSynthetic(args.text)) return "injected";
|
|
@@ -2770,6 +2759,7 @@ import {
|
|
|
2770
2759
|
LLM_OUTPUT_TOKENS as LLM_OUTPUT_TOKENS2
|
|
2771
2760
|
} from "@tangle-network/agent-eval/trace-attributes";
|
|
2772
2761
|
import { ATTR as ATTR3, deriveHexId as deriveHexId2 } from "@tangle-network/agent-trace-contract";
|
|
2762
|
+
import { claudeRecordIsMachine as claudeRecordIsMachine2, claudeTypedPromptText } from "@tangle-network/harness-sessions";
|
|
2773
2763
|
|
|
2774
2764
|
// src/adapters/claude-subagent-sources.ts
|
|
2775
2765
|
import { readdir as readdir6, realpath } from "fs/promises";
|
|
@@ -3125,8 +3115,6 @@ var ORIGIN_EVIDENCE_ATTR = "traces.claude.actor_evidence";
|
|
|
3125
3115
|
var MACHINE_RECORD_ATTR = "traces.claude.machine_record";
|
|
3126
3116
|
var ORIGIN_RECORDED_ATTR = "traces.claude.origin_recorded";
|
|
3127
3117
|
var ORIGIN_KIND_ATTR = "traces.claude.origin_kind";
|
|
3128
|
-
var COMMAND_NAME = /<command-name>([\s\S]*?)<\/command-name>/;
|
|
3129
|
-
var COMMAND_ARGS = /<command-args>([\s\S]*?)<\/command-args>/;
|
|
3130
3118
|
var SPAWN_TYPE_KEY = "subagent_type";
|
|
3131
3119
|
var SPAWN_DESCRIPTION_KEY = "description";
|
|
3132
3120
|
var SPAWN_TYPE_ATTR = "traces.claude.subagent_type";
|
|
@@ -3322,12 +3310,6 @@ function claudeActorFromOrigin(recorded, fallback) {
|
|
|
3322
3310
|
}
|
|
3323
3311
|
return fallback();
|
|
3324
3312
|
}
|
|
3325
|
-
function typedPromptText(text2) {
|
|
3326
|
-
const name = COMMAND_NAME.exec(text2)?.[1]?.trim();
|
|
3327
|
-
if (!name) return text2;
|
|
3328
|
-
const args = COMMAND_ARGS.exec(text2)?.[1]?.trim();
|
|
3329
|
-
return args ? `${name} ${args}` : name;
|
|
3330
|
-
}
|
|
3331
3313
|
function recordedOrigin(origin) {
|
|
3332
3314
|
const kind = origin?.kind;
|
|
3333
3315
|
return typeof kind === "string" && kind.length > 0 ? kind : null;
|
|
@@ -3533,11 +3515,11 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3533
3515
|
}
|
|
3534
3516
|
} else if (event.kind === "user") {
|
|
3535
3517
|
if (event.prompt) {
|
|
3536
|
-
const machine =
|
|
3518
|
+
const machine = claudeRecordIsMachine2({
|
|
3537
3519
|
text: event.prompt,
|
|
3538
3520
|
isMeta: event.isMeta,
|
|
3539
3521
|
isCompactSummary: event.isCompactSummary,
|
|
3540
|
-
entrypoint: event.entrypoint
|
|
3522
|
+
entrypoint: event.entrypoint ?? void 0
|
|
3541
3523
|
});
|
|
3542
3524
|
const actor = machine ? "injected" : claudeActorFromOrigin(event.originKind, () => claudeActor({
|
|
3543
3525
|
text: event.prompt ?? "",
|
|
@@ -3556,7 +3538,7 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3556
3538
|
service: SERVICE4,
|
|
3557
3539
|
agent: ctx.agent,
|
|
3558
3540
|
step: state.step,
|
|
3559
|
-
content: actor === "human" ?
|
|
3541
|
+
content: actor === "human" ? claudeTypedPromptText(event.prompt) : event.prompt,
|
|
3560
3542
|
contentSource: event.contentSource,
|
|
3561
3543
|
actor
|
|
3562
3544
|
});
|
|
@@ -3577,7 +3559,7 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3577
3559
|
} else if (event.kind === "attachment") {
|
|
3578
3560
|
backfillResult(state.toolSpanByUseId.get(event.result.toolUseId), event.timestamp, event.result);
|
|
3579
3561
|
} else if (event.kind === "queued-prompt") {
|
|
3580
|
-
const machine =
|
|
3562
|
+
const machine = claudeRecordIsMachine2({ text: event.prompt });
|
|
3581
3563
|
const actor = machine ? "injected" : claudeActorFromOrigin(event.originKind, () => "injected");
|
|
3582
3564
|
if (event.originKind) state.sawRecordedOrigin = true;
|
|
3583
3565
|
const prompt = userPromptSpan({
|
|
@@ -3588,7 +3570,7 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3588
3570
|
service: SERVICE4,
|
|
3589
3571
|
agent: ctx.agent,
|
|
3590
3572
|
step: state.step,
|
|
3591
|
-
content: actor === "human" ?
|
|
3573
|
+
content: actor === "human" ? claudeTypedPromptText(event.prompt) : event.prompt,
|
|
3592
3574
|
contentSource: event.contentSource,
|
|
3593
3575
|
actor
|
|
3594
3576
|
});
|
|
@@ -3900,10 +3882,12 @@ var ClaudeAdapter = class {
|
|
|
3900
3882
|
let active = taskScope === "all";
|
|
3901
3883
|
let offeredTools;
|
|
3902
3884
|
let runResult;
|
|
3885
|
+
let recordedCwd;
|
|
3903
3886
|
for await (const event of readJsonl(ref.path, sessionJsonlOptions(ref, options))) {
|
|
3904
3887
|
options.signal?.throwIfAborted();
|
|
3905
3888
|
const eventSessionId = event.sessionId ?? event.session_id;
|
|
3906
3889
|
if (!discoveredTraceId && eventSessionId) discoveredTraceId = eventSessionId;
|
|
3890
|
+
if (!recordedCwd && typeof event.cwd === "string" && event.cwd.length > 0) recordedCwd = event.cwd;
|
|
3907
3891
|
if (event.type === "system" && event.subtype === "init" && Array.isArray(event.tools)) {
|
|
3908
3892
|
offeredTools = modelFacingToolNames(
|
|
3909
3893
|
event.tools.filter((t) => typeof t === "string"),
|
|
@@ -3973,6 +3957,7 @@ var ClaudeAdapter = class {
|
|
|
3973
3957
|
if (offeredTools) {
|
|
3974
3958
|
root.attributes[TOOL_DEFINITIONS_ATTR] = JSON.stringify(offeredTools.map((name) => ({ type: "function", name })));
|
|
3975
3959
|
}
|
|
3960
|
+
if (recordedCwd) root.attributes[SESSION_CWD_ATTR] = recordedCwd;
|
|
3976
3961
|
if (runResult) {
|
|
3977
3962
|
root.attributes[RUN_STATUS_ATTR] = runResult.failed ? "failed" : "completed";
|
|
3978
3963
|
root.status = runResult.failed ? { code: "ERROR", message: `the run ended with ${runResult.subtype}` } : { code: "OK" };
|
|
@@ -4626,6 +4611,9 @@ var CODEX_TOTAL_TOKENS_SOURCE = "codex.token_count.info.total_token_usage";
|
|
|
4626
4611
|
function reportedCount(value) {
|
|
4627
4612
|
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
4628
4613
|
}
|
|
4614
|
+
function nonEmpty(value) {
|
|
4615
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
4616
|
+
}
|
|
4629
4617
|
function normalizeCodexIds(spans) {
|
|
4630
4618
|
for (const item of spans) {
|
|
4631
4619
|
const sourceTraceId = item.trace_id;
|
|
@@ -5203,6 +5191,7 @@ var CodexAdapter = class {
|
|
|
5203
5191
|
}
|
|
5204
5192
|
}
|
|
5205
5193
|
const traceId = meta?.payload?.id ?? ref.sessionId;
|
|
5194
|
+
const recordedCwd = nonEmpty(meta?.payload?.cwd);
|
|
5206
5195
|
const scriptLaunched = meta?.payload?.originator === "codex_exec" || meta?.payload?.source === "exec";
|
|
5207
5196
|
const sessionRole = parentSessionId || meta?.payload?.thread_source === "subagent" ? "child" : "operator";
|
|
5208
5197
|
const rootId = `root:${traceId}`;
|
|
@@ -5221,6 +5210,7 @@ var CodexAdapter = class {
|
|
|
5221
5210
|
// Keep the source session identity searchable after the wire id is normalized.
|
|
5222
5211
|
"tangle.sessionId": traceId,
|
|
5223
5212
|
"traces.session.role": sessionRole,
|
|
5213
|
+
...recordedCwd ? { [SESSION_CWD_ATTR]: recordedCwd } : {},
|
|
5224
5214
|
"traces.codex.task_scope": options.taskScope === "latest" ? "latest" : options.taskScope === "turn" ? "turn" : forkBoundary ? "fork-current" : "all",
|
|
5225
5215
|
...selectedBoundary?.turnId ? { "traces.codex.turn_id": selectedBoundary.turnId } : {},
|
|
5226
5216
|
...parentSessionId ? { "traces.parent_session_id": parentSessionId } : {},
|
|
@@ -5865,6 +5855,7 @@ var OpencodeAdapter = class {
|
|
|
5865
5855
|
messages.push(await readJsonFile(join9(ref.path, f), options));
|
|
5866
5856
|
}
|
|
5867
5857
|
messages.sort((a, b) => (a.time?.created ?? 0) - (b.time?.created ?? 0));
|
|
5858
|
+
const recordedCwd = messages.map((message) => message.path?.cwd).find((cwd) => typeof cwd === "string" && cwd.length > 0);
|
|
5868
5859
|
const spans = [
|
|
5869
5860
|
span({
|
|
5870
5861
|
traceId,
|
|
@@ -5875,7 +5866,8 @@ var OpencodeAdapter = class {
|
|
|
5875
5866
|
startTime: isoOf(messages[0]?.time?.created),
|
|
5876
5867
|
endTime: isoOf(messages.at(-1)?.time?.completed ?? messages.at(-1)?.time?.created),
|
|
5877
5868
|
service: SERVICE6,
|
|
5878
|
-
agent: SERVICE6
|
|
5869
|
+
agent: SERVICE6,
|
|
5870
|
+
...recordedCwd ? { extra: { [SESSION_CWD_ATTR]: recordedCwd } } : {}
|
|
5879
5871
|
})
|
|
5880
5872
|
];
|
|
5881
5873
|
let step = 0;
|
|
@@ -6317,6 +6309,7 @@ var HarnessSessionsAdapter = class {
|
|
|
6317
6309
|
const root = spans[0];
|
|
6318
6310
|
root.attributes["service.name"] = this.harness;
|
|
6319
6311
|
root.attributes["traces.session.role"] = session.parentNativeSessionId ? "child" : "operator";
|
|
6312
|
+
if (session.cwd) root.attributes[SESSION_CWD_ATTR] = session.cwd;
|
|
6320
6313
|
if (session.parentNativeSessionId) root.attributes["traces.parent_session_id"] = session.parentNativeSessionId;
|
|
6321
6314
|
if (session.children.length > 0) {
|
|
6322
6315
|
root.attributes["traces.child_session_ids"] = JSON.stringify(session.children.map((child) => child.nativeSessionId));
|
|
@@ -8811,12 +8804,13 @@ function computeSessionMeasurements(spans, tools, sessionId, harness) {
|
|
|
8811
8804
|
// src/session-facts.ts
|
|
8812
8805
|
import { OPENINFERENCE_SPAN_KIND as OPENINFERENCE_SPAN_KIND4, TOOL_NAME as TOOL_NAME5 } from "@tangle-network/agent-eval/trace-attributes";
|
|
8813
8806
|
import { ingestSpans, rankFirstFailure } from "@tangle-network/agent-eval/diagnosis";
|
|
8814
|
-
var SESSION_FACTS_MEASUREMENT_VERSION = "
|
|
8807
|
+
var SESSION_FACTS_MEASUREMENT_VERSION = "4";
|
|
8815
8808
|
var SESSION_TOKEN_TOTAL_ATTR = "traces.session.total_tokens";
|
|
8816
8809
|
var SPAN_SYNTHESIZED_ATTR = "traces.codex.span_synthesized";
|
|
8817
8810
|
var CORRUPTION_COUNT_ATTR = "traces.session.corruption_count";
|
|
8818
8811
|
var CORRUPTION_RECEIPT_VERSION_ATTR = "traces.session.corruption.receipt_version";
|
|
8819
8812
|
var FACT_TEXT_CAP = 2e3;
|
|
8813
|
+
var ANSWERED_TEXT_CAP = 1500;
|
|
8820
8814
|
var FACT_LIST_CAP = 200;
|
|
8821
8815
|
var CHANGED_FILE_LIST_CAP = 5e3;
|
|
8822
8816
|
function attr(span2, key) {
|
|
@@ -9046,47 +9040,105 @@ function turnText(span2) {
|
|
|
9046
9040
|
function normalizedTurnText(span2) {
|
|
9047
9041
|
return turnText(span2).replace(/\s+/g, " ").trim();
|
|
9048
9042
|
}
|
|
9043
|
+
var CAPTURE_CUT_MARKER = /… \[\+(\d+) chars\]$/;
|
|
9044
|
+
function clipAnswered(raw) {
|
|
9045
|
+
const text2 = raw.trim();
|
|
9046
|
+
const marker = CAPTURE_CUT_MARKER.exec(text2);
|
|
9047
|
+
const body = marker ? text2.slice(0, marker.index) : text2;
|
|
9048
|
+
if (body.length <= ANSWERED_TEXT_CAP) return text2;
|
|
9049
|
+
const lastKept = body.charCodeAt(ANSWERED_TEXT_CAP - 1);
|
|
9050
|
+
const keep = lastKept >= 55296 && lastKept <= 56319 ? ANSWERED_TEXT_CAP - 1 : ANSWERED_TEXT_CAP;
|
|
9051
|
+
const hidden = body.length - keep + (marker ? Number(marker[1]) : 0);
|
|
9052
|
+
return `${body.slice(0, keep)}\u2026 [+${hidden} chars]`;
|
|
9053
|
+
}
|
|
9054
|
+
function isOwnAgentMessage(span2) {
|
|
9055
|
+
return span2.name === "message.assistant" && span2.attributes[INHERITED_SPAN_ATTR] !== true && typeof span2.attributes.content === "string" && span2.attributes.content.trim().length > 0;
|
|
9056
|
+
}
|
|
9049
9057
|
function humanTurnsOf(spans) {
|
|
9050
9058
|
const excluded = /* @__PURE__ */ new Map();
|
|
9051
|
-
const drop = (reason,
|
|
9052
|
-
excluded.set(reason, [...excluded.get(reason) ?? [], spanId]);
|
|
9059
|
+
const drop = (reason, span2) => {
|
|
9060
|
+
excluded.set(reason, [...excluded.get(reason) ?? [], { spanId: span2.span_id, at: span2.start_time }]);
|
|
9053
9061
|
};
|
|
9054
9062
|
const kept = [];
|
|
9063
|
+
const turns = [];
|
|
9055
9064
|
let sinceKept = [];
|
|
9065
|
+
let lastAgentMessage = null;
|
|
9056
9066
|
for (const span2 of spans) {
|
|
9057
9067
|
if (isSubagentSpan(span2.attributes)) {
|
|
9058
|
-
if (span2.name === "user.prompt") drop(SUBAGENT_TURN_REASON, span2
|
|
9068
|
+
if (span2.name === "user.prompt") drop(SUBAGENT_TURN_REASON, span2);
|
|
9059
9069
|
continue;
|
|
9060
9070
|
}
|
|
9061
9071
|
if (span2.name !== "user.prompt") {
|
|
9072
|
+
if (isOwnAgentMessage(span2)) lastAgentMessage = span2;
|
|
9062
9073
|
sinceKept.push(span2);
|
|
9063
9074
|
continue;
|
|
9064
9075
|
}
|
|
9065
9076
|
if (span2.attributes[INHERITED_SPAN_ATTR] === true) {
|
|
9066
9077
|
const source = stringAttr2(span2, INHERITED_SOURCE_ATTR);
|
|
9067
|
-
drop(source === null ? INHERITED_TURN_REASON : `${INHERITED_TURN_REASON} (${source})`, span2
|
|
9078
|
+
drop(source === null ? INHERITED_TURN_REASON : `${INHERITED_TURN_REASON} (${source})`, span2);
|
|
9068
9079
|
continue;
|
|
9069
9080
|
}
|
|
9070
9081
|
const actor = stringAttr2(span2, ACTOR_ATTR) ?? "unclassified";
|
|
9071
9082
|
if (actor !== "human") {
|
|
9072
|
-
drop(TURN_EXCLUSION_REASONS[actor] ?? `the adapter classified this turn as "${actor}", not as a person typing`, span2
|
|
9083
|
+
drop(TURN_EXCLUSION_REASONS[actor] ?? `the adapter classified this turn as "${actor}", not as a person typing`, span2);
|
|
9073
9084
|
continue;
|
|
9074
9085
|
}
|
|
9075
9086
|
const previous = kept[kept.length - 1];
|
|
9076
9087
|
const duplicate = previous !== void 0 && previous.start_time === span2.start_time && normalizedTurnText(previous) === normalizedTurnText(span2) && normalizedTurnText(span2).length > 0 && !sinceKept.some(isAgentActivity);
|
|
9077
9088
|
if (duplicate) {
|
|
9078
|
-
drop(DUPLICATE_TURN_REASON, span2
|
|
9089
|
+
drop(DUPLICATE_TURN_REASON, span2);
|
|
9079
9090
|
continue;
|
|
9080
9091
|
}
|
|
9081
9092
|
kept.push(span2);
|
|
9093
|
+
turns.push({
|
|
9094
|
+
actor: "human",
|
|
9095
|
+
at: span2.start_time,
|
|
9096
|
+
text: turnText(span2),
|
|
9097
|
+
spanId: span2.span_id,
|
|
9098
|
+
answered: lastAgentMessage ? clipAnswered(lastAgentMessage.attributes.content) : null,
|
|
9099
|
+
answeredSpanId: lastAgentMessage?.span_id ?? null
|
|
9100
|
+
});
|
|
9082
9101
|
sinceKept = [];
|
|
9083
9102
|
}
|
|
9103
|
+
return { turns, excluded };
|
|
9104
|
+
}
|
|
9105
|
+
function excludedTurnFacts(excluded, keep) {
|
|
9106
|
+
return [...excluded].map(([reason, entries]) => [reason, entries.filter((entry) => keep(entry.at)).map((entry) => entry.spanId)]).filter(([, spanIds]) => spanIds.length > 0).sort(([left], [right]) => left.localeCompare(right)).map(([reason, spanIds]) => ({ reason, turns: spanIds.length, spanIds }));
|
|
9107
|
+
}
|
|
9108
|
+
function windowBounds(window) {
|
|
9109
|
+
if (!window || window.since === void 0 && window.until === void 0) return null;
|
|
9110
|
+
const bound = (value, name, open4) => {
|
|
9111
|
+
if (value === void 0) return open4;
|
|
9112
|
+
const ms2 = Date.parse(value);
|
|
9113
|
+
if (!Number.isFinite(ms2)) throw new RangeError(`window ${name} is not a readable time: ${value}`);
|
|
9114
|
+
return ms2;
|
|
9115
|
+
};
|
|
9116
|
+
const sinceMs = bound(window.since, "since", Number.NEGATIVE_INFINITY);
|
|
9117
|
+
const untilMs = bound(window.until, "until", Number.POSITIVE_INFINITY);
|
|
9118
|
+
if (!(sinceMs < untilMs)) throw new RangeError(`window since (${window.since}) must be before until (${window.until})`);
|
|
9084
9119
|
return {
|
|
9085
|
-
|
|
9086
|
-
|
|
9120
|
+
since: window.since === void 0 ? null : new Date(sinceMs).toISOString(),
|
|
9121
|
+
until: window.until === void 0 ? null : new Date(untilMs).toISOString(),
|
|
9122
|
+
sinceMs,
|
|
9123
|
+
untilMs
|
|
9087
9124
|
};
|
|
9088
9125
|
}
|
|
9126
|
+
function insideWindow(bounds, time) {
|
|
9127
|
+
if (bounds === null) return true;
|
|
9128
|
+
const ms2 = Date.parse(time);
|
|
9129
|
+
return Number.isFinite(ms2) && ms2 >= bounds.sinceMs && ms2 < bounds.untilMs;
|
|
9130
|
+
}
|
|
9131
|
+
function isRecordSpan(span2) {
|
|
9132
|
+
return span2.parent_span_id !== null && span2.attributes[CORRUPTION_RECEIPT_VERSION_ATTR] === void 0;
|
|
9133
|
+
}
|
|
9089
9134
|
function computeSessionFacts(spans, options = {}) {
|
|
9135
|
+
const bounds = windowBounds(options.window);
|
|
9136
|
+
return groupByTrace(spans).sort((left, right) => compareIds(left.traceId, right.traceId)).map((group) => sessionFactsForTrace(group.traceId, group.sessionId, group.spans, options, bounds));
|
|
9137
|
+
}
|
|
9138
|
+
function compareIds(left, right) {
|
|
9139
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
9140
|
+
}
|
|
9141
|
+
function groupByTrace(spans) {
|
|
9090
9142
|
const { sessionByTrace } = indexSessionIdsByTrace(spans);
|
|
9091
9143
|
const byTrace = /* @__PURE__ */ new Map();
|
|
9092
9144
|
for (const span2 of spans) {
|
|
@@ -9094,9 +9146,13 @@ function computeSessionFacts(spans, options = {}) {
|
|
|
9094
9146
|
if (group) group.push(span2);
|
|
9095
9147
|
else byTrace.set(span2.trace_id, [span2]);
|
|
9096
9148
|
}
|
|
9097
|
-
return [...byTrace].
|
|
9149
|
+
return [...byTrace].map(([traceId, traceSpans]) => ({
|
|
9150
|
+
traceId,
|
|
9151
|
+
sessionId: sessionByTrace.get(traceId) ?? null,
|
|
9152
|
+
spans: traceSpans
|
|
9153
|
+
}));
|
|
9098
9154
|
}
|
|
9099
|
-
function sessionFactsForTrace(traceId, sessionId, unordered, options) {
|
|
9155
|
+
function sessionFactsForTrace(traceId, sessionId, unordered, options, bounds) {
|
|
9100
9156
|
const spans = [...unordered].sort(byTraceOrder);
|
|
9101
9157
|
const harness = spans.map((span2) => stringAttr2(span2, "service.name")).find((name) => name !== null) ?? null;
|
|
9102
9158
|
const ownSpans = spans.filter((span2) => !isSubagentSpan(span2.attributes));
|
|
@@ -9110,8 +9166,11 @@ function sessionFactsForTrace(traceId, sessionId, unordered, options) {
|
|
|
9110
9166
|
for (const span2 of invoked) byName[toolName3(span2)] = (byName[toolName3(span2)] ?? 0) + 1;
|
|
9111
9167
|
const subagents = subagentsOf(ownSpans, spans);
|
|
9112
9168
|
const pullRequests = readPullRequests(ownSpans);
|
|
9113
|
-
const
|
|
9114
|
-
const
|
|
9169
|
+
const inWindow = (at) => insideWindow(bounds, at);
|
|
9170
|
+
const promptSpans = spans.filter((span2) => span2.name === "user.prompt" && inWindow(span2.start_time));
|
|
9171
|
+
const turnFacts = humanTurnsOf(spans);
|
|
9172
|
+
const humanTurns = turnFacts.turns.filter((turn) => inWindow(turn.at));
|
|
9173
|
+
const excludedTurns = excludedTurnFacts(turnFacts.excluded, inWindow);
|
|
9115
9174
|
const actorCounts = /* @__PURE__ */ new Map();
|
|
9116
9175
|
for (const span2 of promptSpans) {
|
|
9117
9176
|
const actor = stringAttr2(span2, ACTOR_ATTR) ?? "unclassified";
|
|
@@ -9131,16 +9190,20 @@ function sessionFactsForTrace(traceId, sessionId, unordered, options) {
|
|
|
9131
9190
|
);
|
|
9132
9191
|
const tokenSpan = spans.find((span2) => typeof span2.attributes[SESSION_TOKEN_TOTAL_ATTR] === "number");
|
|
9133
9192
|
const receipts = spans.filter((span2) => span2.attributes[CORRUPTION_RECEIPT_VERSION_ATTR] !== void 0);
|
|
9134
|
-
const recordSpans = spans.filter(
|
|
9135
|
-
(span2) => span2.parent_span_id !== null && span2.attributes[CORRUPTION_RECEIPT_VERSION_ATTR] === void 0
|
|
9136
|
-
).length;
|
|
9193
|
+
const recordSpans = spans.filter(isRecordSpan).length;
|
|
9137
9194
|
const corruptionSpan = spans.find((span2) => typeof span2.attributes[CORRUPTION_COUNT_ATTR] === "number");
|
|
9195
|
+
const cwdSpan = spans.find((span2) => stringAttr2(span2, SESSION_CWD_ATTR) !== null);
|
|
9138
9196
|
const facts = {
|
|
9139
9197
|
schemaVersion: 1,
|
|
9140
9198
|
kind: "traces.session_facts",
|
|
9141
9199
|
traceId,
|
|
9142
9200
|
sessionId,
|
|
9143
9201
|
harness,
|
|
9202
|
+
cwd: cwdSpan ? { value: stringAttr2(cwdSpan, SESSION_CWD_ATTR), spanIds: [cwdSpan.span_id], unavailable: null } : {
|
|
9203
|
+
value: null,
|
|
9204
|
+
spanIds: [],
|
|
9205
|
+
unavailable: `no span carries ${SESSION_CWD_ATTR}: the session source records no working directory, or the adapter that read it does not read one`
|
|
9206
|
+
},
|
|
9144
9207
|
spanCount: spans.length,
|
|
9145
9208
|
recordSpans,
|
|
9146
9209
|
unreadRecords: corruptionSpan ? {
|
|
@@ -9213,6 +9276,7 @@ function sessionFactsForTrace(traceId, sessionId, unordered, options) {
|
|
|
9213
9276
|
});
|
|
9214
9277
|
return {
|
|
9215
9278
|
...facts,
|
|
9279
|
+
cwd: withheld(),
|
|
9216
9280
|
humanTurns: withheld(),
|
|
9217
9281
|
finalMessages: withheld(),
|
|
9218
9282
|
changedFiles: withheld(),
|
|
@@ -9229,26 +9293,88 @@ function sessionFactsForTrace(traceId, sessionId, unordered, options) {
|
|
|
9229
9293
|
};
|
|
9230
9294
|
}
|
|
9231
9295
|
function buildSessionFactsReport(spans, options = {}) {
|
|
9232
|
-
const
|
|
9233
|
-
|
|
9296
|
+
const builder = createSessionFactsReportBuilder(options);
|
|
9297
|
+
builder.add(spans);
|
|
9298
|
+
return builder.build();
|
|
9299
|
+
}
|
|
9300
|
+
var WINDOW_SESSION_RULE = "a session is selected when at least one of its records starts or ends inside [since, until)";
|
|
9301
|
+
var WINDOW_TURN_RULE = "humanTurns, excludedTurns and turnsByActor keep only user.prompt turns that started inside [since, until); every other fact, and each turn's answered text, covers the whole session";
|
|
9302
|
+
function createSessionFactsReportBuilder(options = {}) {
|
|
9303
|
+
const bounds = windowBounds(options.window);
|
|
9304
|
+
const sessions = [];
|
|
9305
|
+
const digests = [];
|
|
9306
|
+
const outsideWindow = [];
|
|
9307
|
+
const unreadSessions = [];
|
|
9308
|
+
let spanCount = 0;
|
|
9234
9309
|
let evidenceThrough = null;
|
|
9235
|
-
|
|
9236
|
-
digest
|
|
9237
|
-
for (const
|
|
9238
|
-
|
|
9310
|
+
const select = (group) => {
|
|
9311
|
+
const digest = createHash7("sha256");
|
|
9312
|
+
for (const span2 of [...group.spans].sort((a, b) => a.span_id.localeCompare(b.span_id))) {
|
|
9313
|
+
digest.update(canonicalJson(span2)).update("\n");
|
|
9314
|
+
for (const time of [span2.start_time, span2.end_time]) {
|
|
9315
|
+
if (Number.isFinite(Date.parse(time)) && (evidenceThrough === null || Date.parse(time) > Date.parse(evidenceThrough))) evidenceThrough = time;
|
|
9316
|
+
}
|
|
9239
9317
|
}
|
|
9240
|
-
|
|
9318
|
+
digests.push({ traceId: group.traceId, digest: digest.digest("hex") });
|
|
9319
|
+
spanCount += group.spans.length;
|
|
9320
|
+
sessions.push(sessionFactsForTrace(group.traceId, group.sessionId, group.spans, options, bounds));
|
|
9321
|
+
};
|
|
9241
9322
|
return {
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
|
|
9251
|
-
|
|
9323
|
+
add(spans) {
|
|
9324
|
+
for (const group of groupByTrace(spans)) {
|
|
9325
|
+
if (bounds === null) {
|
|
9326
|
+
select(group);
|
|
9327
|
+
continue;
|
|
9328
|
+
}
|
|
9329
|
+
const records = group.spans.filter(isRecordSpan);
|
|
9330
|
+
if (records.length === 0) {
|
|
9331
|
+
const unread = group.spans.find((span2) => typeof span2.attributes[CORRUPTION_COUNT_ATTR] === "number");
|
|
9332
|
+
unreadSessions.push({
|
|
9333
|
+
sessionId: group.sessionId,
|
|
9334
|
+
traceId: group.traceId,
|
|
9335
|
+
source: null,
|
|
9336
|
+
reason: `no record could be read (${unread ? `${unread.attributes[CORRUPTION_COUNT_ATTR]} unread record(s)` : "no record spans"}), so whether the session holds a record inside the window is unknown`
|
|
9337
|
+
});
|
|
9338
|
+
continue;
|
|
9339
|
+
}
|
|
9340
|
+
if (records.some((span2) => insideWindow(bounds, span2.start_time) || insideWindow(bounds, span2.end_time))) select(group);
|
|
9341
|
+
else outsideWindow.push(group.sessionId ?? group.traceId);
|
|
9342
|
+
}
|
|
9343
|
+
},
|
|
9344
|
+
addUnread(session) {
|
|
9345
|
+
if (bounds === null) {
|
|
9346
|
+
throw new Error("an unread session is reported only by a windowed report; without a window, refuse the selection");
|
|
9347
|
+
}
|
|
9348
|
+
unreadSessions.push(session);
|
|
9349
|
+
},
|
|
9350
|
+
build() {
|
|
9351
|
+
const digest = createHash7("sha256");
|
|
9352
|
+
for (const entry of [...digests].sort((a, b) => a.traceId.localeCompare(b.traceId) || a.digest.localeCompare(b.digest))) {
|
|
9353
|
+
digest.update(`${entry.traceId}
|
|
9354
|
+
${entry.digest}
|
|
9355
|
+
`);
|
|
9356
|
+
}
|
|
9357
|
+
return {
|
|
9358
|
+
schemaVersion: 1,
|
|
9359
|
+
kind: "traces.session_facts_report",
|
|
9360
|
+
measurementVersion: SESSION_FACTS_MEASUREMENT_VERSION,
|
|
9361
|
+
sourceDigest: "sha256:" + digest.digest("hex"),
|
|
9362
|
+
evidenceThrough,
|
|
9363
|
+
contentIncluded: options.includeContent !== false,
|
|
9364
|
+
generatedAt: options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
9365
|
+
harness: options.harness ?? null,
|
|
9366
|
+
spanCount,
|
|
9367
|
+
selection: bounds === null ? null : {
|
|
9368
|
+
since: bounds.since,
|
|
9369
|
+
until: bounds.until,
|
|
9370
|
+
sessionRule: WINDOW_SESSION_RULE,
|
|
9371
|
+
turnRule: WINDOW_TURN_RULE,
|
|
9372
|
+
outsideWindow: [...outsideWindow].sort(compareIds),
|
|
9373
|
+
unreadSessions: [...unreadSessions]
|
|
9374
|
+
},
|
|
9375
|
+
sessions: [...sessions].sort((left, right) => compareIds(left.traceId, right.traceId))
|
|
9376
|
+
};
|
|
9377
|
+
}
|
|
9252
9378
|
};
|
|
9253
9379
|
}
|
|
9254
9380
|
function factLine(label2, fact, rendered) {
|
|
@@ -9260,8 +9386,18 @@ function renderSessionFacts(report) {
|
|
|
9260
9386
|
const lines = [
|
|
9261
9387
|
`session facts \u2014 ${report.sessions.length} session(s), ${report.spanCount} span(s), deterministic, $0`
|
|
9262
9388
|
];
|
|
9389
|
+
const selection = report.selection;
|
|
9390
|
+
if (selection) {
|
|
9391
|
+
lines.push(
|
|
9392
|
+
`window [${selection.since ?? "open"}, ${selection.until ?? "open"}): turn facts count only turns inside it; ${selection.outsideWindow.length} session(s) read with no record inside it`
|
|
9393
|
+
);
|
|
9394
|
+
for (const unread of selection.unreadSessions) {
|
|
9395
|
+
lines.push(` unread session ${unread.sessionId ?? unread.traceId ?? unread.source ?? "unknown"}: ${unread.reason}`);
|
|
9396
|
+
}
|
|
9397
|
+
}
|
|
9263
9398
|
for (const facts of report.sessions) {
|
|
9264
9399
|
lines.push("", `${facts.sessionId ?? facts.traceId} [${facts.harness ?? "unknown harness"}] ${facts.spanCount} spans`);
|
|
9400
|
+
lines.push(factLine("cwd", facts.cwd, String(facts.cwd.value)));
|
|
9265
9401
|
lines.push(
|
|
9266
9402
|
factLine(
|
|
9267
9403
|
"tool calls",
|
|
@@ -9329,6 +9465,9 @@ function renderSessionFactsContext(report, options = {}) {
|
|
|
9329
9465
|
${JSON.stringify({ sessions, ...dropped2.length ? { omitted_fields: dropped2 } : {} })}`;
|
|
9330
9466
|
const dropped = [];
|
|
9331
9467
|
const sheds = [
|
|
9468
|
+
["human_turn_answered", (facts) => {
|
|
9469
|
+
for (const turn of facts.human_turns) delete turn.answered;
|
|
9470
|
+
}],
|
|
9332
9471
|
["human_turn_text", (facts) => {
|
|
9333
9472
|
for (const turn of facts.human_turns) delete turn.text;
|
|
9334
9473
|
}],
|
|
@@ -9419,6 +9558,7 @@ function compactFacts(facts) {
|
|
|
9419
9558
|
return {
|
|
9420
9559
|
session_id: facts.sessionId,
|
|
9421
9560
|
trace_id: facts.traceId,
|
|
9561
|
+
cwd: factJson(facts.cwd),
|
|
9422
9562
|
spans: facts.spanCount,
|
|
9423
9563
|
tool_calls: {
|
|
9424
9564
|
count: facts.toolCalls.value,
|
|
@@ -9441,7 +9581,8 @@ function compactFacts(facts) {
|
|
|
9441
9581
|
human_turns: (facts.humanTurns.value ?? []).map((turn) => ({
|
|
9442
9582
|
at: turn.at,
|
|
9443
9583
|
span_id: turn.spanId,
|
|
9444
|
-
text: turn.text
|
|
9584
|
+
text: turn.text,
|
|
9585
|
+
answered: turn.answered
|
|
9445
9586
|
})),
|
|
9446
9587
|
excluded_turns: facts.excludedTurns.value?.map((entry) => ({
|
|
9447
9588
|
reason: entry.reason,
|
|
@@ -20550,6 +20691,7 @@ export {
|
|
|
20550
20691
|
isSynthesizedSpan,
|
|
20551
20692
|
isInheritedSpan,
|
|
20552
20693
|
ATTR,
|
|
20694
|
+
SESSION_CWD_ATTR,
|
|
20553
20695
|
INGEST_SOURCE_CLI,
|
|
20554
20696
|
environmentAttributes,
|
|
20555
20697
|
stampEnvironmentAttrs,
|
|
@@ -20561,6 +20703,7 @@ export {
|
|
|
20561
20703
|
appendAll,
|
|
20562
20704
|
parseIsoToEpochMs,
|
|
20563
20705
|
parseSince,
|
|
20706
|
+
parseTimeBound,
|
|
20564
20707
|
resolveOtlpInputFiles,
|
|
20565
20708
|
inferSpanKind,
|
|
20566
20709
|
otlpRowToSpan,
|
|
@@ -20649,10 +20792,12 @@ export {
|
|
|
20649
20792
|
SESSION_TOKEN_TOTAL_ATTR,
|
|
20650
20793
|
SPAN_SYNTHESIZED_ATTR,
|
|
20651
20794
|
FACT_TEXT_CAP,
|
|
20795
|
+
ANSWERED_TEXT_CAP,
|
|
20652
20796
|
FACT_LIST_CAP,
|
|
20653
20797
|
CHANGED_FILE_LIST_CAP,
|
|
20654
20798
|
computeSessionFacts,
|
|
20655
20799
|
buildSessionFactsReport,
|
|
20800
|
+
createSessionFactsReportBuilder,
|
|
20656
20801
|
renderSessionFacts,
|
|
20657
20802
|
PREPARED_CONTEXT_BYTE_CEILING,
|
|
20658
20803
|
renderSessionFactsContext,
|
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
assertOutsideSourceBundle,
|
|
14
14
|
assessSpans,
|
|
15
15
|
buildPolicyEvidenceRecord,
|
|
16
|
-
buildSessionFactsReport,
|
|
17
16
|
buildSessionIndexFromRows,
|
|
18
17
|
buildSkillUsageReport,
|
|
19
18
|
cmdReplayVerify,
|
|
@@ -22,6 +21,7 @@ import {
|
|
|
22
21
|
collectSessionSelection,
|
|
23
22
|
commandAnalyzer,
|
|
24
23
|
commandRedactor,
|
|
24
|
+
createSessionFactsReportBuilder,
|
|
25
25
|
defaultSkillUsageStorePath,
|
|
26
26
|
diffRuns,
|
|
27
27
|
executeUpload,
|
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
parseIsoToEpochMs,
|
|
48
48
|
parseSession,
|
|
49
49
|
parseSince,
|
|
50
|
+
parseTimeBound,
|
|
50
51
|
planUpload,
|
|
51
52
|
primeAnalyzer,
|
|
52
53
|
projectSessionBundle,
|
|
@@ -66,6 +67,7 @@ import {
|
|
|
66
67
|
runTraceInvestigation,
|
|
67
68
|
runTraceQuestions,
|
|
68
69
|
saveReport,
|
|
70
|
+
scanSessions,
|
|
69
71
|
selectAdapters,
|
|
70
72
|
serializePolicyEvidence,
|
|
71
73
|
serializeSessionIndex,
|
|
@@ -90,7 +92,7 @@ import {
|
|
|
90
92
|
writeSessionIndexFile,
|
|
91
93
|
writeTraceEvidenceExportFile,
|
|
92
94
|
writeTraceQuestionsArtifacts
|
|
93
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-COSWFESO.js";
|
|
94
96
|
|
|
95
97
|
// src/cli.ts
|
|
96
98
|
import { readFileSync } from "fs";
|
|
@@ -489,6 +491,9 @@ function parseArgs(argv) {
|
|
|
489
491
|
case "--since":
|
|
490
492
|
a.since = next();
|
|
491
493
|
break;
|
|
494
|
+
case "--until":
|
|
495
|
+
a.until = next();
|
|
496
|
+
break;
|
|
492
497
|
case "--out":
|
|
493
498
|
a.out = next();
|
|
494
499
|
break;
|
|
@@ -703,6 +708,10 @@ function validateViewSelection(args) {
|
|
|
703
708
|
`--view is not supported by ${args.command}. A view is a projection of an assembled bundle: run \`traces bundle ... --out <dir>\` first, then \`traces bundle-view <dir> --view evidence-only --out <view-dir>\`.`
|
|
704
709
|
);
|
|
705
710
|
}
|
|
711
|
+
function validateUntilSelection(args) {
|
|
712
|
+
if (args.until === void 0 || args.command === "facts") return args;
|
|
713
|
+
throw new Error(`--until is not supported by ${args.command}; it bounds the facts window (traces facts --since <t> --until <t>)`);
|
|
714
|
+
}
|
|
706
715
|
function validateWorkflowSelection(args) {
|
|
707
716
|
if (!args.workflow && !args.latestTurn) return args;
|
|
708
717
|
if (!WORKFLOW_COMMANDS.has(args.command)) {
|
|
@@ -736,7 +745,7 @@ function adaptersFor(args) {
|
|
|
736
745
|
return selectAdapters({ all: args.all, harnesses: [args.harness] });
|
|
737
746
|
}
|
|
738
747
|
async function discover(args) {
|
|
739
|
-
const sinceMs = args.since ?
|
|
748
|
+
const sinceMs = args.since ? parseSince(args.since) : void 0;
|
|
740
749
|
const out = [];
|
|
741
750
|
for (const adapter of adaptersFor(args)) {
|
|
742
751
|
let refs = await locateSessions(adapter, { cwd: args.cwd, sinceMs });
|
|
@@ -1201,10 +1210,50 @@ async function cmdFacts(args) {
|
|
|
1201
1210
|
if (format !== "json" && format !== "text") {
|
|
1202
1211
|
throw new Error(`unknown facts format "${format}" (expected json or text)`);
|
|
1203
1212
|
}
|
|
1204
|
-
const
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1213
|
+
const window = args.since !== void 0 || args.until !== void 0 ? {
|
|
1214
|
+
...args.since !== void 0 ? { since: new Date(parseSince(args.since)).toISOString() } : {},
|
|
1215
|
+
...args.until !== void 0 ? { until: new Date(parseTimeBound(args.until, "--until")).toISOString() } : {}
|
|
1216
|
+
} : void 0;
|
|
1217
|
+
const builder = createSessionFactsReportBuilder({ includeContent: !args.noContent, window });
|
|
1218
|
+
let report;
|
|
1219
|
+
const discoversWindow = window !== void 0 && !args.session && !args.otlp && !args.input && !args.sourceBundle && !args.workflow;
|
|
1220
|
+
if (discoversWindow) {
|
|
1221
|
+
const harnesses = /* @__PURE__ */ new Set();
|
|
1222
|
+
for await (const scanned of scanSessions({
|
|
1223
|
+
adapters: adaptersFor(args),
|
|
1224
|
+
cwd: args.cwd,
|
|
1225
|
+
sinceMs: window.since === void 0 ? void 0 : Date.parse(window.since),
|
|
1226
|
+
last: args.last > 0 ? args.last : void 0,
|
|
1227
|
+
taskScope: args.latestTurn ? "latest" : "all",
|
|
1228
|
+
onError: (error, ref) => {
|
|
1229
|
+
if (!ref) throw error;
|
|
1230
|
+
builder.addUnread({
|
|
1231
|
+
sessionId: ref.sessionId,
|
|
1232
|
+
traceId: null,
|
|
1233
|
+
source: ref.path,
|
|
1234
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
1235
|
+
});
|
|
1236
|
+
}
|
|
1237
|
+
})) {
|
|
1238
|
+
harnesses.add(scanned.adapter.harness);
|
|
1239
|
+
builder.add(scanned.spans);
|
|
1240
|
+
}
|
|
1241
|
+
report = { ...builder.build(), harness: [...harnesses].join("+") || args.harness };
|
|
1242
|
+
} else {
|
|
1243
|
+
const collected = await collectSpans(args);
|
|
1244
|
+
if (collected.spans.length === 0) throw new Error("no spans found for the given selection");
|
|
1245
|
+
warnIncompleteWorkflow(collected.workflow);
|
|
1246
|
+
builder.add(collected.spans);
|
|
1247
|
+
report = { ...builder.build(), harness: collected.harness };
|
|
1248
|
+
}
|
|
1249
|
+
const unreadInWindow = report.selection?.unreadSessions ?? [];
|
|
1250
|
+
if (unreadInWindow.length > 0) {
|
|
1251
|
+
const named = unreadInWindow.slice(0, 3).map((entry) => entry.source ?? entry.sessionId ?? entry.traceId);
|
|
1252
|
+
process.stderr.write(
|
|
1253
|
+
`warning: ${unreadInWindow.length} session(s) could not be read; each is named with its reason in selection.unreadSessions (${named.join(", ")}${unreadInWindow.length > named.length ? ", \u2026" : ""})
|
|
1254
|
+
`
|
|
1255
|
+
);
|
|
1256
|
+
}
|
|
1208
1257
|
const unread = report.sessions.filter((facts) => facts.recordSpans === 0);
|
|
1209
1258
|
if (unread.length > 0) {
|
|
1210
1259
|
throw new Error(
|
|
@@ -2050,10 +2099,15 @@ Commands:
|
|
|
2050
2099
|
sessions: tool calls excluding synthesized spans, subagent spawns
|
|
2051
2100
|
with task names, human turns in order, the final message per task,
|
|
2052
2101
|
changed paths, first/last record times, the harness token total, and
|
|
2053
|
-
the first failure by agent-eval's fixed precedence (or none)
|
|
2102
|
+
the first failure by agent-eval's fixed precedence (or none), the
|
|
2103
|
+
session's recorded working directory, and for each human turn the
|
|
2104
|
+
agent message it answered.
|
|
2054
2105
|
No model call, no budget, $0. Every fact names the span ids it came
|
|
2055
2106
|
from; a fact the spans cannot support is null with its reason.
|
|
2056
|
-
--
|
|
2107
|
+
--since/--until select every session with a record in the window and
|
|
2108
|
+
count only that window's turns; a session that cannot be read is named
|
|
2109
|
+
in selection.unreadSessions. Without a window: exit 1 when a selected
|
|
2110
|
+
session cannot be read. --format json (default) or text
|
|
2057
2111
|
skills Count skill use across Claude Code, Codex, and Kimi Code sessions on this
|
|
2058
2112
|
machine, and list installed skills with no use in the window.
|
|
2059
2113
|
Incremental: a run reads only transcript bytes appended since the
|
|
@@ -2129,7 +2183,11 @@ Options:
|
|
|
2129
2183
|
accepted vs rejected. Rolls up when the dir holds many runs.
|
|
2130
2184
|
analyze reads Runtime journals and recorded startup failures.
|
|
2131
2185
|
watch reads a live Runtime journal and OTLP span files.
|
|
2132
|
-
--since <t>
|
|
2186
|
+
--since <t> 30m / 2h / 7d (before now) or an ISO date. Selection commands read
|
|
2187
|
+
sessions modified at or after it; upload: its window (default 24h).
|
|
2188
|
+
facts: opens a time window and selects EVERY session with a record
|
|
2189
|
+
in it, not only the newest; its turn facts keep only turns inside it
|
|
2190
|
+
--until <t> facts: closes the window (exclusive), same forms as --since
|
|
2133
2191
|
--out <path> Write report to a file
|
|
2134
2192
|
--dir <path> improve/ask: write artifacts to this directory
|
|
2135
2193
|
--otlp <file|dir> READ OTLP-JSONL emitted by any system, skipping the adapters.
|
|
@@ -2261,7 +2319,7 @@ async function main() {
|
|
|
2261
2319
|
return;
|
|
2262
2320
|
}
|
|
2263
2321
|
const args = validateOtlpSelection(
|
|
2264
|
-
validateViewSelection(validateWorkflowSelection(applyCurrentSessionSelection(parsedArgs)))
|
|
2322
|
+
validateViewSelection(validateWorkflowSelection(validateUntilSelection(applyCurrentSessionSelection(parsedArgs))))
|
|
2265
2323
|
);
|
|
2266
2324
|
switch (args.command) {
|
|
2267
2325
|
case "help":
|
package/dist/index.d.ts
CHANGED
|
@@ -900,6 +900,14 @@ declare const ATTR: {
|
|
|
900
900
|
* in-container path even when no such path exists on this host. */
|
|
901
901
|
readonly ENVIRONMENT_CWD: "tangle.environment.cwd";
|
|
902
902
|
};
|
|
903
|
+
/**
|
|
904
|
+
* The working directory the harness recorded for a session, verbatim, on the
|
|
905
|
+
* adapter's root `session` span. Unlike `tangle.cwd` it is never repaired,
|
|
906
|
+
* decoded from a directory name, or inferred from paths the spans mention: an
|
|
907
|
+
* adapter sets it only from a field the session source itself carries, and
|
|
908
|
+
* leaves it absent when the source names none.
|
|
909
|
+
*/
|
|
910
|
+
declare const SESSION_CWD_ATTR = "traces.session.cwd";
|
|
903
911
|
/** `tangle.ingest_source` value for CLI-uploaded traces. Wire contract. */
|
|
904
912
|
declare const INGEST_SOURCE_CLI = "cli";
|
|
905
913
|
/**
|
|
@@ -957,6 +965,9 @@ declare function parseIsoToEpochMs(ts: string): number;
|
|
|
957
965
|
/** Parse a `--since` window: `30m` / `2h` / `7d` (relative to now) or an ISO
|
|
958
966
|
* date, → epoch ms. Throws on a malformed value (fail-loud, not silent). */
|
|
959
967
|
declare function parseSince(value: string): number;
|
|
968
|
+
/** Parse one time bound the way `--since` reads it: `30m` / `2h` / `7d` before
|
|
969
|
+
* now, or an ISO date. `flag` names the option in the error. */
|
|
970
|
+
declare function parseTimeBound(value: string, flag: string): number;
|
|
960
971
|
|
|
961
972
|
type JsonSourceErrorKind = 'read' | 'parse';
|
|
962
973
|
declare class JsonSourceError extends Error {
|
|
@@ -3844,10 +3855,28 @@ declare function readPullRequests(spans: readonly OtlpSpan[]): PullRequestReadin
|
|
|
3844
3855
|
* deltas, which is a different (and smaller) number.
|
|
3845
3856
|
*/
|
|
3846
3857
|
/** Cache invalidation key for deterministic measurements and prepared analyst context. */
|
|
3847
|
-
declare const SESSION_FACTS_MEASUREMENT_VERSION = "
|
|
3858
|
+
declare const SESSION_FACTS_MEASUREMENT_VERSION = "4";
|
|
3859
|
+
/**
|
|
3860
|
+
* A half-open time window: a time `t` is inside when `since <= t < until`.
|
|
3861
|
+
* Either bound may be absent, which leaves that side open.
|
|
3862
|
+
*/
|
|
3863
|
+
interface SessionFactsWindow {
|
|
3864
|
+
/** ISO-8601 lower bound, inclusive. */
|
|
3865
|
+
readonly since?: string;
|
|
3866
|
+
/** ISO-8601 upper bound, exclusive. */
|
|
3867
|
+
readonly until?: string;
|
|
3868
|
+
}
|
|
3848
3869
|
interface SessionFactsOptions {
|
|
3849
3870
|
/** Defaults to true for compatibility. False withholds conversation, commands, paths and assignment text. */
|
|
3850
3871
|
readonly includeContent?: boolean;
|
|
3872
|
+
/**
|
|
3873
|
+
* Limit the turn facts to a time window. `humanTurns`, `excludedTurns` and
|
|
3874
|
+
* `turnsByActor` keep only `user.prompt` turns that started inside it; every
|
|
3875
|
+
* other fact still covers the whole session. A report built with a window
|
|
3876
|
+
* also leaves out every session with no record inside it, and names them in
|
|
3877
|
+
* {@link SessionFactsReport.selection}.
|
|
3878
|
+
*/
|
|
3879
|
+
readonly window?: SessionFactsWindow;
|
|
3851
3880
|
}
|
|
3852
3881
|
declare const SESSION_TOKEN_TOTAL_ATTR = "traces.session.total_tokens";
|
|
3853
3882
|
/**
|
|
@@ -3859,6 +3888,8 @@ declare const SESSION_TOKEN_TOTAL_ATTR = "traces.session.total_tokens";
|
|
|
3859
3888
|
declare const SPAN_SYNTHESIZED_ATTR = "traces.codex.span_synthesized";
|
|
3860
3889
|
/** Max characters of message or prompt text kept per fact entry. */
|
|
3861
3890
|
declare const FACT_TEXT_CAP = 2000;
|
|
3891
|
+
/** Max characters of the agent message kept in {@link SessionTurnFact.answered}. */
|
|
3892
|
+
declare const ANSWERED_TEXT_CAP = 1500;
|
|
3862
3893
|
/** Entries kept per list field before the sheet reports the rest as omitted. */
|
|
3863
3894
|
declare const FACT_LIST_CAP = 200;
|
|
3864
3895
|
/**
|
|
@@ -3904,6 +3935,15 @@ interface SessionTurnFact {
|
|
|
3904
3935
|
readonly at: string;
|
|
3905
3936
|
readonly text: string;
|
|
3906
3937
|
readonly spanId: string;
|
|
3938
|
+
/**
|
|
3939
|
+
* The text of the last message this session's own agent wrote before the
|
|
3940
|
+
* turn: what the person was answering. Clipped to {@link ANSWERED_TEXT_CAP}
|
|
3941
|
+
* characters with a visible `… [+N chars]` marker. Null when the agent had
|
|
3942
|
+
* written no text before the turn.
|
|
3943
|
+
*/
|
|
3944
|
+
readonly answered: string | null;
|
|
3945
|
+
/** The `message.assistant` span `answered` was read from. */
|
|
3946
|
+
readonly answeredSpanId: string | null;
|
|
3907
3947
|
}
|
|
3908
3948
|
/** How many `user.prompt` turns each actor produced. */
|
|
3909
3949
|
interface TurnActorCount {
|
|
@@ -3952,6 +3992,13 @@ interface SessionFacts {
|
|
|
3952
3992
|
readonly traceId: string;
|
|
3953
3993
|
readonly sessionId: string | null;
|
|
3954
3994
|
readonly harness: string | null;
|
|
3995
|
+
/**
|
|
3996
|
+
* The working directory the harness recorded for the session, read from
|
|
3997
|
+
* `traces.session.cwd` on the adapter's root span. Null with the reason when
|
|
3998
|
+
* no span carries it; never decoded from a directory name or inferred from
|
|
3999
|
+
* the paths the session touched.
|
|
4000
|
+
*/
|
|
4001
|
+
readonly cwd: SessionFact<string>;
|
|
3955
4002
|
/** Spans in this trace, including the synthesized ones. */
|
|
3956
4003
|
readonly spanCount: number;
|
|
3957
4004
|
/**
|
|
@@ -4002,18 +4049,45 @@ interface SessionFacts {
|
|
|
4002
4049
|
readonly firstFailure: FirstFailure;
|
|
4003
4050
|
readonly measurements: SessionMeasurements;
|
|
4004
4051
|
}
|
|
4052
|
+
/** A session the report could not read, so whether it belongs in the window is unknown. */
|
|
4053
|
+
interface UnreadSessionFact {
|
|
4054
|
+
readonly sessionId: string | null;
|
|
4055
|
+
readonly traceId: string | null;
|
|
4056
|
+
/** Where the session was read from, when the reader knows. */
|
|
4057
|
+
readonly source: string | null;
|
|
4058
|
+
readonly reason: string;
|
|
4059
|
+
}
|
|
4060
|
+
/** How a windowed report chose its sessions and turns. Null on a report built without a window. */
|
|
4061
|
+
interface SessionFactsSelection {
|
|
4062
|
+
/** The window's inclusive lower bound, or null when open. */
|
|
4063
|
+
readonly since: string | null;
|
|
4064
|
+
/** The window's exclusive upper bound, or null when open. */
|
|
4065
|
+
readonly until: string | null;
|
|
4066
|
+
/** Which sessions the report holds. */
|
|
4067
|
+
readonly sessionRule: string;
|
|
4068
|
+
/** Which turns `humanTurns`, `excludedTurns` and `turnsByActor` hold. */
|
|
4069
|
+
readonly turnRule: string;
|
|
4070
|
+
/** Sessions read in full whose records all fall outside the window, by session id. */
|
|
4071
|
+
readonly outsideWindow: readonly string[];
|
|
4072
|
+
/** Sessions that could not be read; each is named with the reason, never counted as empty. */
|
|
4073
|
+
readonly unreadSessions: readonly UnreadSessionFact[];
|
|
4074
|
+
}
|
|
4005
4075
|
interface SessionFactsReport {
|
|
4006
4076
|
readonly schemaVersion: 1;
|
|
4007
4077
|
readonly kind: 'traces.session_facts_report';
|
|
4008
4078
|
readonly generatedAt: string;
|
|
4009
4079
|
readonly measurementVersion: typeof SESSION_FACTS_MEASUREMENT_VERSION;
|
|
4010
|
-
/**
|
|
4080
|
+
/**
|
|
4081
|
+
* SHA-256 over the selected sessions in trace-id order, each contributing the
|
|
4082
|
+
* SHA-256 of its canonical spans (content, attributes, links and timing).
|
|
4083
|
+
*/
|
|
4011
4084
|
readonly sourceDigest: string;
|
|
4012
4085
|
/** Latest recorded endpoint, not the last time the filesystem was checked. */
|
|
4013
4086
|
readonly evidenceThrough: string | null;
|
|
4014
4087
|
readonly contentIncluded: boolean;
|
|
4015
4088
|
readonly harness: string | null;
|
|
4016
4089
|
readonly spanCount: number;
|
|
4090
|
+
readonly selection: SessionFactsSelection | null;
|
|
4017
4091
|
readonly sessions: readonly SessionFacts[];
|
|
4018
4092
|
}
|
|
4019
4093
|
/**
|
|
@@ -4022,11 +4096,25 @@ interface SessionFactsReport {
|
|
|
4022
4096
|
* model, network call, or budget is involved.
|
|
4023
4097
|
*/
|
|
4024
4098
|
declare function computeSessionFacts(spans: readonly OtlpSpan[], options?: SessionFactsOptions): SessionFacts[];
|
|
4025
|
-
|
|
4026
|
-
declare function buildSessionFactsReport(spans: readonly OtlpSpan[], options?: SessionFactsOptions & {
|
|
4099
|
+
type SessionFactsReportOptions = SessionFactsOptions & {
|
|
4027
4100
|
harness?: string | null;
|
|
4028
4101
|
generatedAt?: string;
|
|
4029
|
-
}
|
|
4102
|
+
};
|
|
4103
|
+
/** The facts sheet for a set of spans, as one report. */
|
|
4104
|
+
declare function buildSessionFactsReport(spans: readonly OtlpSpan[], options?: SessionFactsReportOptions): SessionFactsReport;
|
|
4105
|
+
/**
|
|
4106
|
+
* Builds one report from sessions supplied a batch at a time, so a caller
|
|
4107
|
+
* reading many sessions holds one session's spans at once rather than all of
|
|
4108
|
+
* them. `add` the whole spans of one or more sessions per call; a trace split
|
|
4109
|
+
* across two calls is reported as two sessions.
|
|
4110
|
+
*/
|
|
4111
|
+
interface SessionFactsReportBuilder {
|
|
4112
|
+
add(spans: readonly OtlpSpan[]): void;
|
|
4113
|
+
/** Name a session that could not be read at all. Only a windowed report holds these. */
|
|
4114
|
+
addUnread(session: UnreadSessionFact): void;
|
|
4115
|
+
build(): SessionFactsReport;
|
|
4116
|
+
}
|
|
4117
|
+
declare function createSessionFactsReportBuilder(options?: SessionFactsReportOptions): SessionFactsReportBuilder;
|
|
4030
4118
|
/** The short readable form: the same facts, one screen, no span-id lists. */
|
|
4031
4119
|
declare function renderSessionFacts(report: SessionFactsReport): string;
|
|
4032
4120
|
/**
|
|
@@ -5129,4 +5217,4 @@ declare function parseRetainedSession(input: {
|
|
|
5129
5217
|
readonly signal?: AbortSignal;
|
|
5130
5218
|
}): Promise<RetainedSessionSelection>;
|
|
5131
5219
|
|
|
5132
|
-
export { ACTOR_ATTR, ATTR, type Actor, type AdoptionOptions, type AdoptionReport, AmpAdapter, type AnalysisEngineFromEnvOptions, type AnalyzeOptions, type AnalyzeResult, type AnswerSchema, type AssembleSessionBundleOptions, BLOBS_DIR, type BuildPolicyEvidenceOptions, type BuildSessionIndexOptions, type BuildTraceFindingPacketOptions, CHANGED_FILE_LIST_CAP, CITATION_NORMALIZATION_VERSION, CONTENT_CAP, COORDINATION_LOG_FILE, CORRECTIVE_REACTIONS, type ChangedFileFact, 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 CompactionMeasurement, type ConformanceRenderOptions, type ContentFootprint, type CoordinationLog, type CoordinationQuestion, type CoordinationSteer, CopilotAdapter, type CorruptionMode, type CoveredMeasurement, DEFAULT_ANALYST_MODEL, DEFAULT_ASK_CONCURRENCY, DEFAULT_HARNESS, DEFAULT_SANDBOX_BASE_URL, DEFAULT_SWEEP_THRESHOLD, EMPTY_SPAN_RUN_SNAPSHOT, EXPORT_RULE, EmptySessionError, type EvidenceOnlyVerdict, type ExcludedTurnFact, type ExecuteOptions, type ExportRule, type ExternalAnalysisKind, type ExternalAnalysisPayload, type ExternalAnalysisResult, type ExternalAnalyzer, type ExternalAnalyzerOptions, type ExternalDiscoveryCandidate, FACT_LIST_CAP, FACT_TEXT_CAP, FactoryAdapter, type FailureFollowUp, type FailureFollowUpReport, type FileRunContextReaderOptions, type FinalMessageFact, type FindSessionTextLeaksOptions, type FindingRejectionCounts, type FindingRejectionReasons, type FindingRejectionTally, type FindingsFileOutcome, type FollowUpKind, GeminiAdapter, type HaloAnalyzerOptions, type HaloReasoningEffort, HarnessSessionsAdapter, type HarnessTraceAdapter, type HodoscopeAnalyzerOptions, type HodoscopeInput, type HodoscopeMessage, type HodoscopeSourceMapEntry, type HodoscopeTrajectory, INGEST_SOURCE_CLI, INHERITED_SOURCE_ATTR, INHERITED_SPANS_OMITTED_ATTR, INHERITED_SPAN_ATTR, INHERITED_SPAN_COUNT_ATTR, type InheritedSpanSource, type InspectSessionIndexOptions, type InstalledSkill, JsonSourceError, type JsonlCorruptionReceipt, JsonlParseError, type JsonlReadOptions, type LiveBatchOptions, type LocateOptions, type LoopConvergence, type LoopConvergenceReport, type LoopIteration, type LoopTrend, type LoopTrendBasis, MAX_SHELL_DEPTH, MAX_TRACE_QUESTION_CHARS, type ObservedLoop, type ObserverOptions, OpencodeAdapter, type OtlpIngestIssue, type OtlpIngestIssueKind, type OtlpInput, type OtlpInputFile, type OtlpRowConversion, type OtlpSpan, type OtlpSpanKind, type OtlpSpanLink, type OtlpStatusCode, POLICY_EVIDENCE_NOTE, PREPARED_CONTEXT_BYTE_CEILING, type ParentTaskResolution, type ParseOptions, PartialUploadError, PiAdapter, type PiAdapterOptions, type PipelineOptions, type PipelineReport, type PlanOptions, type PolicyEvidenceLoopSummary, type PolicyEvidenceRecord, type PolicyEvidenceToolSummary, type PrimeAnalyzerOptions, type PrimeTransport, type PrimeTransportRequest, type PrimeTransportResponse, type ProjectSessionBundleOptions, type ProjectSessionBundleResult, type PullRequestFact, type PullRequestFacts, type PullRequestReading, QwenAdapter, REACTIONS, RESULT_FILE, RETAINED_SESSION_READER_VERSION, RULE, type Reaction, type ReactionReport, type ReactionSessionReport, type RedactSpansOptions, type Redactor, type RefusedSession, type RepoAttrs, type RepoResolution, type RepoResolutionSource, type ResolvedOtlpInput, type RetainedSessionFile, type RetainedSessionSelection, type RunContextJournal, type RunContextNode, type RunContextResult, type RunContextSnapshot, type RunDiffOptions, type RunDiffReport, type RunDiffSide, type RunResult, type RunWatchSnapshot, type RunWatchTarget, type RuntimeTrace, SESSION_FACTS_MEASUREMENT_VERSION, SESSION_FACTS_VERSION_SUFFIX, SESSION_TOKEN_TOTAL_ATTR, SOURCE_ATTRIBUTE_PREFIX, SPAN_SYNTHESIZED_ATTR, SPAWN_JOURNAL_FILE, STATUS_MARK, SYNTHESIZED_SOURCE_ATTR, SYNTHESIZED_SPAN_ATTR, type SandboxReplayBackendOptions, type ScanOptions, type ScannedSession, type SessionBatch, type SessionBundleAbsence, type SessionBundleCarriedSignatures, type SessionBundleExclusion, type SessionBundleExclusionRule, type SessionBundleFile, type SessionBundleIssue, type SessionBundleIssueKind, type SessionBundleLeakCheck, type SessionBundleLedgerSlice, type SessionBundleManifest, type SessionBundleProjection, type SessionBundleResult, type SessionBundleSliceRule, type SessionBundleVerification, type SessionBundleView, type SessionCorruptionReceipt, type SessionEnvironment, type SessionFact, type SessionFacts, type SessionFactsOptions, type SessionFactsReport, type SessionIdentityConflict, type SessionIdentityIndex, type SessionIntegrity, type SessionMeasurements, type SessionRef, type SessionRelationship, type SessionRole, type SessionSeedGroup, type SessionSelection, type SessionSelectionRow, type SessionSourceFile, type SessionTextLeak, type SessionTextLeakReport, type SessionTurnFact, type SessionWorkflow, SessionWorkflowError, type SessionWorkflowErrorCode, type SessionWorkflowIssue, type SessionWorkflowSession, type SessionWorkflowSummary, type SkillCatalogRoots, type SkillUsageEvent, type SkillUsageHarness, type SkillUsageKind, type SkillUsageRefresh, type SkillUsageReport, type SkillUsageReportOptions, type SkillUsageRow, type SkillUsageSources, SkillUsageStore, type SkippedAnalysis, type SkippedInputFile, type SourceRecordReference, type SpanInput, type SpanNodeStatus, type SpanRedaction, type SpanRunNode, type SpanRunSnapshot, type SpanStructure, type SpawnedChildResolution, type SpendRoll, type SteeringChainReport, type SteeringEdge, type SubagentSpawnFact, TRACE_QUESTION_PREVIEW_HEAD_CHARS, type ToolMeasurement, 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 TraceQuestion, type TraceQuestionAnswer, type TraceQuestionCitation, type TraceQuestionFailureKind, type TraceQuestionTrace, type TraceQuestionsArtifacts, type TraceQuestionsOptions, type TraceQuestionsResult, type TraceQuestionsTotals, type TraceSessionIndex, type TraceSessionIndexRow, type TraceStoreInvestigationOptions, type TraceStoreInvestigationResult, type TraceStreamEvent, type TraceStreamOptions, type TraceStreamReplayOptions, type TraceStreamSession, type TracesConfig, type TriggerPair, type TurnActorCount, type UnavailableCapabilities, type UploadBackend, type UploadIdentity, type UploadItem, type UploadPlan, type UploadRecord, type UploadResult, type UploadState, type UserPromptInput, type VerifySafeOptions, type VerifySafeResult, type WatchRunTargetOptions, ZERO_ROLL, type ZaiChatCallerOptions, addSpend, alreadyUploaded, analysisEngineFromEnv, analyzeAdoption, analyzeLiveBatch, analyzeLoopConvergence, analyzeReactions, analyzeSpans, analyzeSteeringChain, answerSchemaErrors, applyRedactor, assembleSessionBundle, assertAnswerSchema, assertSandboxReachable, assessSpans, buildPolicyEvidenceRecord, buildSessionFactsReport, buildSessionIndex, buildSessionIndexFromRows, buildSkillUsageReport, buildSpanRunTree, buildTraceFindingPacket, capText, chatTrajectoryToSpans, classifyEvidenceOnlyPath, classifyFailureFollowUps, classifyLiveActions, classifyReaction, claudeActor, codexActor, collectPolicyEvidence, collectSessionIndex, collectSessionSelection, collectSessionWorkflow, collectSessions, commandAnalyzer, commandRedactor, commandTextFromInput, computeAdoption, computeSessionFacts, conformanceOfSpans, connectors, countSkillRunsJsonl, createBundleSourceReader, createFindingRejectionTally, cwdMatchesSelection, cwdMatchesSelectionResolved, defaultSkillCatalogRoots, defaultSkillUsageSources, defaultSkillUsageStorePath, defaultTraceLiveAnalysts, describeSessionRelationship, diffRuns, engineCallReservationFloorUsd, environmentAttributes, environmentFromSpanAttributes, equivalentGitCwds, executeUpload, exportTraceEvidenceFile, exportTraceEvidenceRows, exportTraceEvidenceText, externalFailureMessage, fileRunContextSupervisorRunReader, fileSha256, findContextRoot, findSessionTextLeaks, findSpanSourceFiles, findingRejection, findingRejectionDetail, forEachTreeNode, formatFindingRejections, formatVerdict, haloAnalyzer, hashSessionBundleFiles, hodoscopeAnalyzer, httpJsonTransport, importCodeTraceBench, incompleteInputsNote, indexSessionIdsByTrace, inferRole, inferSpanKind, inspectSessionIndex, int, isBridgeMismatchError, isChatTrajectory, isChatTrajectoryMessage, isFileRunContextDir, isInheritedSpan, isSynthesizedSpan, iterSerializedSpans, knownHarnesses, listAdapters, listSessionBundleFiles, loadState, loadTraceQuestionsFile, loadTracesConfig, locateSessions, looksLikeAgentPrompt, mergeRolls, mergeTracesConfig, ms, normalizeAnalystCitations, normalizeRemote, normalizeTraceQuestions, otlpRowToSpan, outboundHash, parseIsoToEpochMs, parseJsonAnswer, parseRetainedSession, parseSession, parseSince, planTraceAgenticRoute, planUpload, primeAnalyzer, projectSessionBundle, readCoordinationLog, readFileRunContext, readInstalledSkills, readJsonFile, readJsonl, readOtlpInput, readPullRequests, readRunContextJournal, readRunContextSnapshot, readRunSide, readRunWatchSnapshot, readSessionBundleManifest, readSessionIndexFile, readSpanRunSnapshot, recordSessionCorruption, redactSpans, renderConformance, renderInspectionReport, renderRunContextSnapshot, renderRunDiff, renderRunWatchSnapshot, renderSessionFacts, renderSessionFactsContext, renderSkillUsage, renderSpanRunSnapshot, renderTraceQuestionInstructions, renderTraceQuestionPrompt, renderTraceQuestionsReport, renderValidation, resolveAdapter, resolveOtlpInputFiles, resolveRepoAttrs, resolveRunContextDir, resolveRunWatchTarget, resolveSessionRepoAttrs, runCommand, runExternalAnalyzers, runPipelines, runTotals, runTraceImprovement, runTraceInvestigation, runTraceQuestions, runTraceStoreInvestigation, sandboxReplayBackend, saveReport, saveState, scanSessions, selectAdapters, serializeInspectionReport, serializePolicyEvidence, serializeSessionIndex, serializeSpans, serializeTraceStreamEvent, sessionFactsContext, sessionHash, sessionIdFromAttributes, sessionIntegrityAttributes, sessionTextSignatures, shellCommands, skippedAnalyses, span, spanRunTotals, stampEnvironmentAttrs, stampRepoAttrs, stampSessionIdentity, stampSessionIntegrity, stampSpanWorkdirRepoAttrs, streamSessions, summarizeOtlpExecution, summarizeSpanExecution, summarizeSpanStructure, takeJsonl, textIsSynthetic, toOpenInferenceSpan, toRuntimeStore, toTraceSpanEvents, tokens, totalAgenticFailureMessage, totalFindingRejections, traceAgenticKinds, traceCitationsInText, traceStreamEventsFromSpans, unavailableCapabilities, uploadKey, usd, userPromptSpan, validateOtlpSpans, validationExitCode, verdictExitCode, verifyFindingsInSandbox, verifySafe, verifySessionBundle, watchRunTarget, watchSessions, withSessionFactsContext, wrap, writeHodoscopeInput, writeInspectionReportFile, writeOtlpFile, writePolicyEvidenceFile, writeSessionBundleManifest, writeSessionIndexFile, writeTraceEvidenceExportFile, writeTraceImprovementArtifacts, writeTraceQuestionsArtifacts, zaiChatCaller, zeroPricedCost };
|
|
5220
|
+
export { ACTOR_ATTR, ANSWERED_TEXT_CAP, ATTR, type Actor, type AdoptionOptions, type AdoptionReport, AmpAdapter, type AnalysisEngineFromEnvOptions, type AnalyzeOptions, type AnalyzeResult, type AnswerSchema, type AssembleSessionBundleOptions, BLOBS_DIR, type BuildPolicyEvidenceOptions, type BuildSessionIndexOptions, type BuildTraceFindingPacketOptions, CHANGED_FILE_LIST_CAP, CITATION_NORMALIZATION_VERSION, CONTENT_CAP, COORDINATION_LOG_FILE, CORRECTIVE_REACTIONS, type ChangedFileFact, 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 CompactionMeasurement, type ConformanceRenderOptions, type ContentFootprint, type CoordinationLog, type CoordinationQuestion, type CoordinationSteer, CopilotAdapter, type CorruptionMode, type CoveredMeasurement, DEFAULT_ANALYST_MODEL, DEFAULT_ASK_CONCURRENCY, DEFAULT_HARNESS, DEFAULT_SANDBOX_BASE_URL, DEFAULT_SWEEP_THRESHOLD, EMPTY_SPAN_RUN_SNAPSHOT, EXPORT_RULE, EmptySessionError, type EvidenceOnlyVerdict, type ExcludedTurnFact, type ExecuteOptions, type ExportRule, type ExternalAnalysisKind, type ExternalAnalysisPayload, type ExternalAnalysisResult, type ExternalAnalyzer, type ExternalAnalyzerOptions, type ExternalDiscoveryCandidate, FACT_LIST_CAP, FACT_TEXT_CAP, FactoryAdapter, type FailureFollowUp, type FailureFollowUpReport, type FileRunContextReaderOptions, type FinalMessageFact, type FindSessionTextLeaksOptions, type FindingRejectionCounts, type FindingRejectionReasons, type FindingRejectionTally, type FindingsFileOutcome, type FollowUpKind, GeminiAdapter, type HaloAnalyzerOptions, type HaloReasoningEffort, HarnessSessionsAdapter, type HarnessTraceAdapter, type HodoscopeAnalyzerOptions, type HodoscopeInput, type HodoscopeMessage, type HodoscopeSourceMapEntry, type HodoscopeTrajectory, INGEST_SOURCE_CLI, INHERITED_SOURCE_ATTR, INHERITED_SPANS_OMITTED_ATTR, INHERITED_SPAN_ATTR, INHERITED_SPAN_COUNT_ATTR, type InheritedSpanSource, type InspectSessionIndexOptions, type InstalledSkill, JsonSourceError, type JsonlCorruptionReceipt, JsonlParseError, type JsonlReadOptions, type LiveBatchOptions, type LocateOptions, type LoopConvergence, type LoopConvergenceReport, type LoopIteration, type LoopTrend, type LoopTrendBasis, MAX_SHELL_DEPTH, MAX_TRACE_QUESTION_CHARS, type ObservedLoop, type ObserverOptions, OpencodeAdapter, type OtlpIngestIssue, type OtlpIngestIssueKind, type OtlpInput, type OtlpInputFile, type OtlpRowConversion, type OtlpSpan, type OtlpSpanKind, type OtlpSpanLink, type OtlpStatusCode, POLICY_EVIDENCE_NOTE, PREPARED_CONTEXT_BYTE_CEILING, type ParentTaskResolution, type ParseOptions, PartialUploadError, PiAdapter, type PiAdapterOptions, type PipelineOptions, type PipelineReport, type PlanOptions, type PolicyEvidenceLoopSummary, type PolicyEvidenceRecord, type PolicyEvidenceToolSummary, type PrimeAnalyzerOptions, type PrimeTransport, type PrimeTransportRequest, type PrimeTransportResponse, type ProjectSessionBundleOptions, type ProjectSessionBundleResult, type PullRequestFact, type PullRequestFacts, type PullRequestReading, QwenAdapter, REACTIONS, RESULT_FILE, RETAINED_SESSION_READER_VERSION, RULE, type Reaction, type ReactionReport, type ReactionSessionReport, type RedactSpansOptions, type Redactor, type RefusedSession, type RepoAttrs, type RepoResolution, type RepoResolutionSource, type ResolvedOtlpInput, type RetainedSessionFile, type RetainedSessionSelection, type RunContextJournal, type RunContextNode, type RunContextResult, type RunContextSnapshot, type RunDiffOptions, type RunDiffReport, type RunDiffSide, type RunResult, type RunWatchSnapshot, type RunWatchTarget, type RuntimeTrace, SESSION_CWD_ATTR, SESSION_FACTS_MEASUREMENT_VERSION, SESSION_FACTS_VERSION_SUFFIX, SESSION_TOKEN_TOTAL_ATTR, SOURCE_ATTRIBUTE_PREFIX, SPAN_SYNTHESIZED_ATTR, SPAWN_JOURNAL_FILE, STATUS_MARK, SYNTHESIZED_SOURCE_ATTR, SYNTHESIZED_SPAN_ATTR, type SandboxReplayBackendOptions, type ScanOptions, type ScannedSession, type SessionBatch, type SessionBundleAbsence, type SessionBundleCarriedSignatures, type SessionBundleExclusion, type SessionBundleExclusionRule, type SessionBundleFile, type SessionBundleIssue, type SessionBundleIssueKind, type SessionBundleLeakCheck, type SessionBundleLedgerSlice, type SessionBundleManifest, type SessionBundleProjection, type SessionBundleResult, type SessionBundleSliceRule, type SessionBundleVerification, type SessionBundleView, type SessionCorruptionReceipt, type SessionEnvironment, type SessionFact, type SessionFacts, type SessionFactsOptions, type SessionFactsReport, type SessionFactsReportBuilder, type SessionFactsReportOptions, type SessionFactsSelection, type SessionFactsWindow, type SessionIdentityConflict, type SessionIdentityIndex, type SessionIntegrity, type SessionMeasurements, type SessionRef, type SessionRelationship, type SessionRole, type SessionSeedGroup, type SessionSelection, type SessionSelectionRow, type SessionSourceFile, type SessionTextLeak, type SessionTextLeakReport, type SessionTurnFact, type SessionWorkflow, SessionWorkflowError, type SessionWorkflowErrorCode, type SessionWorkflowIssue, type SessionWorkflowSession, type SessionWorkflowSummary, type SkillCatalogRoots, type SkillUsageEvent, type SkillUsageHarness, type SkillUsageKind, type SkillUsageRefresh, type SkillUsageReport, type SkillUsageReportOptions, type SkillUsageRow, type SkillUsageSources, SkillUsageStore, type SkippedAnalysis, type SkippedInputFile, type SourceRecordReference, type SpanInput, type SpanNodeStatus, type SpanRedaction, type SpanRunNode, type SpanRunSnapshot, type SpanStructure, type SpawnedChildResolution, type SpendRoll, type SteeringChainReport, type SteeringEdge, type SubagentSpawnFact, TRACE_QUESTION_PREVIEW_HEAD_CHARS, type ToolMeasurement, 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 TraceQuestion, type TraceQuestionAnswer, type TraceQuestionCitation, type TraceQuestionFailureKind, type TraceQuestionTrace, type TraceQuestionsArtifacts, type TraceQuestionsOptions, type TraceQuestionsResult, type TraceQuestionsTotals, type TraceSessionIndex, type TraceSessionIndexRow, type TraceStoreInvestigationOptions, type TraceStoreInvestigationResult, type TraceStreamEvent, type TraceStreamOptions, type TraceStreamReplayOptions, type TraceStreamSession, type TracesConfig, type TriggerPair, type TurnActorCount, type UnavailableCapabilities, type UnreadSessionFact, type UploadBackend, type UploadIdentity, type UploadItem, type UploadPlan, type UploadRecord, type UploadResult, type UploadState, type UserPromptInput, type VerifySafeOptions, type VerifySafeResult, type WatchRunTargetOptions, ZERO_ROLL, type ZaiChatCallerOptions, addSpend, alreadyUploaded, analysisEngineFromEnv, analyzeAdoption, analyzeLiveBatch, analyzeLoopConvergence, analyzeReactions, analyzeSpans, analyzeSteeringChain, answerSchemaErrors, applyRedactor, assembleSessionBundle, assertAnswerSchema, assertSandboxReachable, assessSpans, buildPolicyEvidenceRecord, buildSessionFactsReport, buildSessionIndex, buildSessionIndexFromRows, buildSkillUsageReport, buildSpanRunTree, buildTraceFindingPacket, capText, chatTrajectoryToSpans, classifyEvidenceOnlyPath, classifyFailureFollowUps, classifyLiveActions, classifyReaction, claudeActor, codexActor, collectPolicyEvidence, collectSessionIndex, collectSessionSelection, collectSessionWorkflow, collectSessions, commandAnalyzer, commandRedactor, commandTextFromInput, computeAdoption, computeSessionFacts, conformanceOfSpans, connectors, countSkillRunsJsonl, createBundleSourceReader, createFindingRejectionTally, createSessionFactsReportBuilder, cwdMatchesSelection, cwdMatchesSelectionResolved, defaultSkillCatalogRoots, defaultSkillUsageSources, defaultSkillUsageStorePath, defaultTraceLiveAnalysts, describeSessionRelationship, diffRuns, engineCallReservationFloorUsd, environmentAttributes, environmentFromSpanAttributes, equivalentGitCwds, executeUpload, exportTraceEvidenceFile, exportTraceEvidenceRows, exportTraceEvidenceText, externalFailureMessage, fileRunContextSupervisorRunReader, fileSha256, findContextRoot, findSessionTextLeaks, findSpanSourceFiles, findingRejection, findingRejectionDetail, forEachTreeNode, formatFindingRejections, formatVerdict, haloAnalyzer, hashSessionBundleFiles, hodoscopeAnalyzer, httpJsonTransport, importCodeTraceBench, incompleteInputsNote, indexSessionIdsByTrace, inferRole, inferSpanKind, inspectSessionIndex, int, isBridgeMismatchError, isChatTrajectory, isChatTrajectoryMessage, isFileRunContextDir, isInheritedSpan, isSynthesizedSpan, iterSerializedSpans, knownHarnesses, listAdapters, listSessionBundleFiles, loadState, loadTraceQuestionsFile, loadTracesConfig, locateSessions, looksLikeAgentPrompt, mergeRolls, mergeTracesConfig, ms, normalizeAnalystCitations, normalizeRemote, normalizeTraceQuestions, otlpRowToSpan, outboundHash, parseIsoToEpochMs, parseJsonAnswer, parseRetainedSession, parseSession, parseSince, parseTimeBound, planTraceAgenticRoute, planUpload, primeAnalyzer, projectSessionBundle, readCoordinationLog, readFileRunContext, readInstalledSkills, readJsonFile, readJsonl, readOtlpInput, readPullRequests, readRunContextJournal, readRunContextSnapshot, readRunSide, readRunWatchSnapshot, readSessionBundleManifest, readSessionIndexFile, readSpanRunSnapshot, recordSessionCorruption, redactSpans, renderConformance, renderInspectionReport, renderRunContextSnapshot, renderRunDiff, renderRunWatchSnapshot, renderSessionFacts, renderSessionFactsContext, renderSkillUsage, renderSpanRunSnapshot, renderTraceQuestionInstructions, renderTraceQuestionPrompt, renderTraceQuestionsReport, renderValidation, resolveAdapter, resolveOtlpInputFiles, resolveRepoAttrs, resolveRunContextDir, resolveRunWatchTarget, resolveSessionRepoAttrs, runCommand, runExternalAnalyzers, runPipelines, runTotals, runTraceImprovement, runTraceInvestigation, runTraceQuestions, runTraceStoreInvestigation, sandboxReplayBackend, saveReport, saveState, scanSessions, selectAdapters, serializeInspectionReport, serializePolicyEvidence, serializeSessionIndex, serializeSpans, serializeTraceStreamEvent, sessionFactsContext, sessionHash, sessionIdFromAttributes, sessionIntegrityAttributes, sessionTextSignatures, shellCommands, skippedAnalyses, span, spanRunTotals, stampEnvironmentAttrs, stampRepoAttrs, stampSessionIdentity, stampSessionIntegrity, stampSpanWorkdirRepoAttrs, streamSessions, summarizeOtlpExecution, summarizeSpanExecution, summarizeSpanStructure, takeJsonl, textIsSynthetic, toOpenInferenceSpan, toRuntimeStore, toTraceSpanEvents, tokens, totalAgenticFailureMessage, totalFindingRejections, traceAgenticKinds, traceCitationsInText, traceStreamEventsFromSpans, unavailableCapabilities, uploadKey, usd, userPromptSpan, validateOtlpSpans, validationExitCode, verdictExitCode, verifyFindingsInSandbox, verifySafe, verifySessionBundle, watchRunTarget, watchSessions, withSessionFactsContext, wrap, writeHodoscopeInput, writeInspectionReportFile, writeOtlpFile, writePolicyEvidenceFile, writeSessionBundleManifest, writeSessionIndexFile, writeTraceEvidenceExportFile, writeTraceImprovementArtifacts, writeTraceQuestionsArtifacts, zaiChatCaller, zeroPricedCost };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ACTOR_ATTR,
|
|
3
|
+
ANSWERED_TEXT_CAP,
|
|
3
4
|
ATTR,
|
|
4
5
|
AmpAdapter,
|
|
5
6
|
BLOBS_DIR,
|
|
@@ -43,6 +44,7 @@ import {
|
|
|
43
44
|
REACTIONS,
|
|
44
45
|
RESULT_FILE,
|
|
45
46
|
RULE,
|
|
47
|
+
SESSION_CWD_ATTR,
|
|
46
48
|
SESSION_FACTS_MEASUREMENT_VERSION,
|
|
47
49
|
SESSION_FACTS_VERSION_SUFFIX,
|
|
48
50
|
SESSION_TOKEN_TOTAL_ATTR,
|
|
@@ -100,6 +102,7 @@ import {
|
|
|
100
102
|
countSkillRunsJsonl,
|
|
101
103
|
createBundleSourceReader,
|
|
102
104
|
createFindingRejectionTally,
|
|
105
|
+
createSessionFactsReportBuilder,
|
|
103
106
|
cwdMatchesSelection,
|
|
104
107
|
cwdMatchesSelectionResolved,
|
|
105
108
|
defaultSkillCatalogRoots,
|
|
@@ -167,6 +170,7 @@ import {
|
|
|
167
170
|
parseJsonAnswer,
|
|
168
171
|
parseSession,
|
|
169
172
|
parseSince,
|
|
173
|
+
parseTimeBound,
|
|
170
174
|
planTraceAgenticRoute,
|
|
171
175
|
planUpload,
|
|
172
176
|
primeAnalyzer,
|
|
@@ -283,7 +287,7 @@ import {
|
|
|
283
287
|
writeTraceQuestionsArtifacts,
|
|
284
288
|
zaiChatCaller,
|
|
285
289
|
zeroPricedCost
|
|
286
|
-
} from "./chunk-
|
|
290
|
+
} from "./chunk-COSWFESO.js";
|
|
287
291
|
|
|
288
292
|
// src/adapters/factory.ts
|
|
289
293
|
import { readdir, stat } from "fs/promises";
|
|
@@ -936,6 +940,7 @@ async function parseRetainedSession(input) {
|
|
|
936
940
|
}
|
|
937
941
|
export {
|
|
938
942
|
ACTOR_ATTR,
|
|
943
|
+
ANSWERED_TEXT_CAP,
|
|
939
944
|
ATTR,
|
|
940
945
|
AmpAdapter,
|
|
941
946
|
AnalystRegistry,
|
|
@@ -983,6 +988,7 @@ export {
|
|
|
983
988
|
RESULT_FILE,
|
|
984
989
|
RETAINED_SESSION_READER_VERSION,
|
|
985
990
|
RULE,
|
|
991
|
+
SESSION_CWD_ATTR,
|
|
986
992
|
SESSION_FACTS_MEASUREMENT_VERSION,
|
|
987
993
|
SESSION_FACTS_VERSION_SUFFIX,
|
|
988
994
|
SESSION_TOKEN_TOTAL_ATTR,
|
|
@@ -1044,6 +1050,7 @@ export {
|
|
|
1044
1050
|
createBundleSourceReader,
|
|
1045
1051
|
createFindingRejectionTally,
|
|
1046
1052
|
createHostedClient,
|
|
1053
|
+
createSessionFactsReportBuilder,
|
|
1047
1054
|
cwdMatchesSelection,
|
|
1048
1055
|
cwdMatchesSelectionResolved,
|
|
1049
1056
|
defaultSkillCatalogRoots,
|
|
@@ -1112,6 +1119,7 @@ export {
|
|
|
1112
1119
|
parseRetainedSession,
|
|
1113
1120
|
parseSession,
|
|
1114
1121
|
parseSince,
|
|
1122
|
+
parseTimeBound,
|
|
1115
1123
|
planTraceAgenticRoute,
|
|
1116
1124
|
planUpload,
|
|
1117
1125
|
primeAnalyzer,
|
package/docs/trace-analysts.md
CHANGED
|
@@ -198,7 +198,8 @@ The sheet is that extraction, made part of the tool.
|
|
|
198
198
|
| `subagentToolSpans` | TOOL spans excluded because a subagent, not this agent, made the call |
|
|
199
199
|
| `subagents` | every subagent-spawning call, with the task name the call recorded |
|
|
200
200
|
| `pullRequests` | pull requests the commands created and merged, each named by number or head branch, with the command span and the join evidence |
|
|
201
|
-
| `
|
|
201
|
+
| `cwd` | the working directory the harness recorded for the session, or `null` with the reason |
|
|
202
|
+
| `humanTurns` | `user.prompt` turns a person typed into this session, in order, with timestamps, each with the agent message it `answered` |
|
|
202
203
|
| `excludedTurns` | every `user.prompt` turn `humanTurns` left out, grouped by the reason, with the span ids |
|
|
203
204
|
| `turnsByActor` | every `user.prompt` turn by actor, so the human filter is checkable |
|
|
204
205
|
| `finalMessages` | the last message of the session's own agent, and of each subagent task, separately |
|
|
@@ -242,7 +243,7 @@ It reaches the built-in kinds run by `analyze --llm`, `investigate`, and `improv
|
|
|
242
243
|
|
|
243
244
|
- The sheet is bounded at `PREPARED_CONTEXT_BYTE_CEILING` (30,000 bytes), a fifth of the `perCallByteCeiling` of 150,000 the trace tools work to, so the rest of the budget stays available for the tool calls the model still makes.
|
|
244
245
|
- When the sheet does not fit, fields are shed from the largest downward and the shed is listed in `omitted_fields`. The tool-call counts are the last facts to go.
|
|
245
|
-
- Receiving the sheet changes an analyst's behavior, so its version carries `+session-facts.
|
|
246
|
+
- Receiving the sheet changes an analyst's behavior, so its version carries `SESSION_FACTS_VERSION_SUFFIX` (`+session-facts.` and the sheet's `measurementVersion`). `createTraceAnalyst` records `prepare_context` in the exact-run identity, and a changed prepared context must not hide behind an unchanged version.
|
|
246
247
|
- The sheet is not evidence. Citations still resolve against the raw spans, which is why every fact names its span ids rather than asking the model to trust the sheet.
|
|
247
248
|
|
|
248
249
|
Pass `sessionFactsContext: false` to `analyzeSpans` to run an analyst without it.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/traces",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Point it at your coding-agent session traces (Claude Code, Codex, OpenCode, Gemini, Pi, \u2026) and get failure-mode + efficiency findings. CLI + SDK over the @tangle-network/agent-eval analyst suite \u2014 observe live sessions, run your own analysts, redact, and upload to the Tangle Intelligence Platform.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@tangle-network/agent-interface": "5.2.0",
|
|
66
66
|
"@tangle-network/agent-runtime": "0.318.0",
|
|
67
67
|
"@tangle-network/agent-trace-contract": "2.0.0",
|
|
68
|
-
"@tangle-network/harness-sessions": "0.1.
|
|
68
|
+
"@tangle-network/harness-sessions": "0.1.2",
|
|
69
69
|
"@tangle-network/sandbox": "0.60.49"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|