@tangle-network/traces 0.9.18 → 0.9.19

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.
@@ -165,11 +165,11 @@ function serializeSpans(spans) {
165
165
  `;
166
166
  }
167
167
  async function writeOtlpFile(spans, outPath) {
168
- const { mkdtemp: mkdtemp7, writeFile: writeFile8 } = await import("fs/promises");
168
+ const { mkdtemp: mkdtemp8, writeFile: writeFile9 } = await import("fs/promises");
169
169
  const { tmpdir: tmpdir7 } = await import("os");
170
- const { join: join22 } = await import("path");
171
- const path = outPath ?? join22(await mkdtemp7(join22(tmpdir7(), "traces-")), "spans.otlp.jsonl");
172
- await writeFile8(path, serializeSpans(spans), "utf8");
170
+ const { join: join25 } = await import("path");
171
+ const path = outPath ?? join25(await mkdtemp8(join25(tmpdir7(), "traces-")), "spans.otlp.jsonl");
172
+ await writeFile9(path, serializeSpans(spans), "utf8");
173
173
  return path;
174
174
  }
175
175
 
@@ -291,6 +291,855 @@ function stampSessionIdentity(spans, fallbackSessionId) {
291
291
  }
292
292
  }
293
293
 
294
+ // src/chat-trajectory.ts
295
+ import { createHash } from "crypto";
296
+ function isChatTrajectoryMessage(value) {
297
+ return isObject(value) && typeof value.role === "string" && typeof value.content === "string";
298
+ }
299
+ function isChatTrajectory(value) {
300
+ return isObject(value) && Array.isArray(value.messages) && value.messages.length > 0 && value.messages.every(isChatTrajectoryMessage);
301
+ }
302
+ function chatTrajectoryToSpans(input, options = {}) {
303
+ const trajectory = Array.isArray(input) ? { messages: input } : input;
304
+ if (trajectory.messages.length === 0) throw new Error("chat trajectory contains no messages");
305
+ if (!trajectory.messages.every(isChatTrajectoryMessage)) {
306
+ throw new TypeError("chat trajectory messages require string role and content fields");
307
+ }
308
+ const traceId = options.traceId ?? trajectoryId(trajectory);
309
+ const service = options.service ?? trajectory.trajectory_format ?? "chat-trajectory";
310
+ const stepMode = options.stepMode ?? "assistant";
311
+ const times = messageTimes(trajectory.messages);
312
+ const actionCount = trajectory.messages.filter((message) => messageKind(message.role) === "LLM").length;
313
+ const root = span({
314
+ traceId,
315
+ spanId: "root",
316
+ name: "trajectory",
317
+ kind: "AGENT",
318
+ startTime: times[0],
319
+ endTime: times.at(-1),
320
+ service,
321
+ costUsd: finiteNumber(trajectory.info?.model_stats, "instance_cost"),
322
+ extra: compactAttributes({
323
+ "traces.source_format": "chat-trajectory",
324
+ "trajectory.format": trajectory.trajectory_format,
325
+ "trajectory.message_count": trajectory.messages.length,
326
+ "trajectory.action_count": actionCount,
327
+ "trajectory.source_path": options.sourcePath,
328
+ "trajectory.api_calls": finiteNumber(trajectory.info?.model_stats, "api_calls"),
329
+ "trajectory.timestamps_synthetic": trajectory.messages.some(
330
+ (message) => message.timestamp === void 0
331
+ )
332
+ })
333
+ });
334
+ const spans = [root];
335
+ let assistantStep = 0;
336
+ for (const [index, message] of trajectory.messages.entries()) {
337
+ const kind = messageKind(message.role);
338
+ if (kind === "LLM") assistantStep += 1;
339
+ const step = stepMode === "message" ? index + 1 : kind === "LLM" ? assistantStep : void 0;
340
+ const spanId = step === void 0 ? `message-${index + 1}` : `step-${step}`;
341
+ const response = isObject(message.extra?.response) ? message.extra.response : void 0;
342
+ const usage = isObject(response?.usage) ? response.usage : void 0;
343
+ const completionDetails = isObject(usage?.completion_tokens_details) ? usage.completion_tokens_details : void 0;
344
+ const promptDetails = isObject(usage?.prompt_tokens_details) ? usage.prompt_tokens_details : void 0;
345
+ spans.push(
346
+ span({
347
+ traceId,
348
+ spanId,
349
+ parentSpanId: "root",
350
+ name: messageName(kind, message),
351
+ kind,
352
+ startTime: times[index],
353
+ service,
354
+ agent: messageAgent(message.role),
355
+ model: stringValue(response?.model),
356
+ inputTokens: finiteNumber(usage, "prompt_tokens"),
357
+ outputTokens: finiteNumber(usage, "completion_tokens"),
358
+ reasoningTokens: finiteNumber(completionDetails, "reasoning_tokens"),
359
+ cachedInputTokens: finiteNumber(promptDetails, "cached_tokens"),
360
+ step,
361
+ content: capText(message.content),
362
+ extra: compactAttributes({
363
+ "traces.source_format": "chat-trajectory",
364
+ "trajectory.message_index": index + 1,
365
+ "trajectory.action_index": kind === "LLM" ? assistantStep : void 0,
366
+ "trajectory.role": message.role
367
+ })
368
+ })
369
+ );
370
+ }
371
+ return validateOtlpSpans(spans, "chat trajectory output");
372
+ }
373
+ function trajectoryId(trajectory) {
374
+ const value = trajectory.trajectory_id ?? trajectory.traj_id ?? trajectory.instance_id;
375
+ if (typeof value === "string" && value.trim()) return value;
376
+ if (typeof value === "number" && Number.isSafeInteger(value)) return String(value);
377
+ return `trajectory-${createHash("sha256").update(JSON.stringify(trajectory.messages)).digest("hex").slice(0, 24)}`;
378
+ }
379
+ function messageKind(role) {
380
+ const normalized = role.trim().toLowerCase();
381
+ if (normalized === "assistant" || normalized === "agent") return "LLM";
382
+ if (normalized === "tool" || normalized === "function" || normalized === "observation") {
383
+ return "TOOL";
384
+ }
385
+ return "CHAIN";
386
+ }
387
+ function messageName(kind, message) {
388
+ if (kind === "LLM") return "message.assistant";
389
+ if (kind === "TOOL") return `tool.${message.name?.trim() || "result"}`;
390
+ const role = message.role.trim().toLowerCase();
391
+ if (role === "system") return "system.prompt";
392
+ if (role === "user" || role === "human") return "user.prompt";
393
+ return "message.other";
394
+ }
395
+ function messageAgent(role) {
396
+ const normalized = role.trim().toLowerCase();
397
+ return ["system", "user", "human", "tool", "function", "observation"].includes(normalized) ? void 0 : role.trim();
398
+ }
399
+ function messageTimes(messages) {
400
+ const supplied = messages.filter((message) => message.timestamp !== void 0).length;
401
+ if (supplied === 0) return messages.map((_, index) => new Date(index).toISOString());
402
+ if (supplied !== messages.length) {
403
+ throw new TypeError("chat trajectory timestamps must be present on every message or none");
404
+ }
405
+ const times = messages.map((message, index) => messageTime(message.timestamp, index));
406
+ for (let index = 1; index < times.length; index += 1) {
407
+ if (Date.parse(times[index]) < Date.parse(times[index - 1])) {
408
+ throw new RangeError(
409
+ `chat trajectory message ${index + 1} timestamp precedes message ${index}`
410
+ );
411
+ }
412
+ }
413
+ return times;
414
+ }
415
+ function messageTime(value, index) {
416
+ const parsed = parseTime(value);
417
+ if (!parsed) {
418
+ throw new TypeError(`chat trajectory message ${index + 1} has an invalid timestamp`);
419
+ }
420
+ return parsed;
421
+ }
422
+ function parseTime(value) {
423
+ if (typeof value === "number" && Number.isFinite(value)) {
424
+ const millis2 = value < 1e10 ? value * 1e3 : value;
425
+ const date = new Date(millis2);
426
+ return Number.isFinite(date.getTime()) ? date.toISOString() : void 0;
427
+ }
428
+ if (typeof value !== "string" || !value.trim()) return void 0;
429
+ const millis = Date.parse(value);
430
+ return Number.isFinite(millis) ? new Date(millis).toISOString() : void 0;
431
+ }
432
+ function finiteNumber(value, key) {
433
+ if (!isObject(value)) return void 0;
434
+ const number = value[key];
435
+ return typeof number === "number" && Number.isFinite(number) ? number : void 0;
436
+ }
437
+ function stringValue(value) {
438
+ return typeof value === "string" && value.trim() ? value : void 0;
439
+ }
440
+ function compactAttributes(values) {
441
+ return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== void 0));
442
+ }
443
+ function isObject(value) {
444
+ return value !== null && typeof value === "object" && !Array.isArray(value);
445
+ }
446
+
447
+ // src/codetracebench.ts
448
+ import {
449
+ mkdir as mkdir2,
450
+ mkdtemp,
451
+ readFile as readFile3,
452
+ rm as rm2
453
+ } from "fs/promises";
454
+ import { basename as basename2, dirname as dirname2, join as join3, resolve as resolve2 } from "path";
455
+
456
+ // src/codetracebench-files.ts
457
+ import { createHash as createHash2, randomUUID } from "crypto";
458
+ import {
459
+ link,
460
+ lstat,
461
+ mkdir,
462
+ readFile,
463
+ realpath,
464
+ rename,
465
+ rm,
466
+ rmdir,
467
+ stat,
468
+ unlink,
469
+ writeFile
470
+ } from "fs/promises";
471
+ import { hostname } from "os";
472
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "path";
473
+ async function claimImportLock(input) {
474
+ const claimId = randomUUID();
475
+ const path = `${input.outputDirectory}.lock`;
476
+ const temporary = join(
477
+ dirname(path),
478
+ `.${basename(path)}.${claimId}.tmp`
479
+ );
480
+ const metadata = {
481
+ kind: "traces.codetracebench-import-lock",
482
+ claimId,
483
+ pid: process.pid,
484
+ hostname: hostname(),
485
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
486
+ revision: input.revision,
487
+ rowsPath: input.rowsPath,
488
+ trajectoryDirectory: input.trajectoryDirectory,
489
+ outputDirectory: input.outputDirectory
490
+ };
491
+ try {
492
+ await writeFile(temporary, `${JSON.stringify(metadata, null, 2)}
493
+ `, {
494
+ encoding: "utf8",
495
+ flag: "wx",
496
+ mode: 384,
497
+ signal: input.signal
498
+ });
499
+ input.signal?.throwIfAborted();
500
+ } catch (error) {
501
+ await rm(temporary, { force: true });
502
+ throw error;
503
+ }
504
+ try {
505
+ await link(temporary, path);
506
+ } catch (error) {
507
+ await rm(temporary, { force: true });
508
+ if (isErrno(error, "EEXIST")) {
509
+ throw await importLockConflictError(path, input.outputDirectory);
510
+ }
511
+ throw error;
512
+ }
513
+ try {
514
+ await rm(temporary, { force: true });
515
+ } catch (error) {
516
+ await unlink(path);
517
+ throw error;
518
+ }
519
+ return { path, claimId };
520
+ }
521
+ async function importLockConflictError(path, outputDirectory) {
522
+ let owner = "owner metadata is unreadable";
523
+ try {
524
+ const parsed = JSON.parse(await readFile(path, "utf8"));
525
+ if (isObject2(parsed) && typeof parsed.pid === "number" && typeof parsed.hostname === "string" && typeof parsed.startedAt === "string" && typeof parsed.revision === "string") {
526
+ owner = `PID ${parsed.pid} on ${parsed.hostname}, started ${parsed.startedAt}, revision ${parsed.revision}`;
527
+ }
528
+ } catch {
529
+ }
530
+ return new Error(
531
+ `CodeTraceBench import already in progress for ${outputDirectory}. Lock: ${path}. Owner: ${owner}. Wait for it to finish, or remove the lock only after confirming that process is no longer running.`
532
+ );
533
+ }
534
+ async function releaseImportLock(lock) {
535
+ let parsed;
536
+ try {
537
+ parsed = JSON.parse(await readFile(lock.path, "utf8"));
538
+ } catch (error) {
539
+ if (isErrno(error, "ENOENT")) return;
540
+ throw new Error(`Could not read CodeTraceBench import lock: ${lock.path}`, {
541
+ cause: error
542
+ });
543
+ }
544
+ if (!isObject2(parsed) || parsed.claimId !== lock.claimId) {
545
+ throw new Error(
546
+ `CodeTraceBench import lock owner changed; refusing to remove ${lock.path}`
547
+ );
548
+ }
549
+ await unlink(lock.path);
550
+ }
551
+ async function publishStagedFiles(stagingDirectory, outputDirectory, files, signal) {
552
+ signal.throwIfAborted();
553
+ try {
554
+ await mkdir(outputDirectory);
555
+ } catch (error) {
556
+ if (isErrno(error, "EEXIST")) {
557
+ throw new Error(
558
+ `CodeTraceBench output directory appeared while import was running; refusing to replace it: ${outputDirectory}`
559
+ );
560
+ }
561
+ throw error;
562
+ }
563
+ const published = [];
564
+ try {
565
+ for (const file of files) {
566
+ signal.throwIfAborted();
567
+ const destination = join(outputDirectory, file);
568
+ await link(join(stagingDirectory, file), destination);
569
+ published.push(destination);
570
+ }
571
+ } catch (error) {
572
+ for (const path of published.reverse()) {
573
+ await rm(path, { force: true });
574
+ }
575
+ try {
576
+ await rmdir(outputDirectory);
577
+ } catch (cleanupError) {
578
+ if (!isErrno(cleanupError, "ENOENT") && !isErrno(cleanupError, "ENOTEMPTY")) {
579
+ throw new AggregateError(
580
+ [error, cleanupError],
581
+ `CodeTraceBench import failed and could not clean ${outputDirectory}`
582
+ );
583
+ }
584
+ }
585
+ throw error;
586
+ }
587
+ }
588
+ async function containedDirectory(path) {
589
+ const resolved = resolve(path);
590
+ let canonical;
591
+ try {
592
+ canonical = await realpath(resolved);
593
+ } catch (error) {
594
+ throw new Error(`CodeTraceBench trajectory directory is unavailable: ${resolved}`, {
595
+ cause: error
596
+ });
597
+ }
598
+ const info = await stat(canonical);
599
+ if (!info.isDirectory()) {
600
+ throw new TypeError(`CodeTraceBench trajectory path is not a directory: ${canonical}`);
601
+ }
602
+ return canonical;
603
+ }
604
+ async function containedFile(root, candidate, label) {
605
+ const path = await optionalContainedFile(root, candidate);
606
+ if (!path) throw new Error(`${label} is missing`);
607
+ return path;
608
+ }
609
+ async function optionalContainedFile(root, candidate) {
610
+ let canonical;
611
+ try {
612
+ canonical = await realpath(candidate);
613
+ } catch (error) {
614
+ if (isErrno(error, "ENOENT")) return void 0;
615
+ throw error;
616
+ }
617
+ const fromRoot = relative(root, canonical);
618
+ if (fromRoot === ".." || fromRoot.startsWith(`..${sep}`) || isAbsolute(fromRoot)) {
619
+ throw new Error(`CodeTraceBench trajectory file escapes its input directory: ${candidate}`);
620
+ }
621
+ const info = await stat(canonical);
622
+ if (!info.isFile()) {
623
+ throw new TypeError(`CodeTraceBench trajectory path is not a file: ${candidate}`);
624
+ }
625
+ return canonical;
626
+ }
627
+ async function assertPathMissing(path) {
628
+ try {
629
+ await lstat(path);
630
+ } catch (error) {
631
+ if (isErrno(error, "ENOENT")) return;
632
+ throw error;
633
+ }
634
+ throw new Error(`CodeTraceBench output directory already exists: ${path}`);
635
+ }
636
+ async function atomicWriteFile(path, content, signal) {
637
+ signal.throwIfAborted();
638
+ const temporary = join(
639
+ dirname(path),
640
+ `.${basename(path)}.${randomUUID()}.tmp`
641
+ );
642
+ try {
643
+ await writeFile(temporary, content, {
644
+ encoding: "utf8",
645
+ flag: "wx",
646
+ signal
647
+ });
648
+ signal.throwIfAborted();
649
+ await rename(temporary, path);
650
+ } finally {
651
+ await rm(temporary, { force: true });
652
+ }
653
+ }
654
+ function sha256(value) {
655
+ return createHash2("sha256").update(value).digest("hex");
656
+ }
657
+ function isObject2(value) {
658
+ return value !== null && typeof value === "object" && !Array.isArray(value);
659
+ }
660
+ function isErrno(error, code) {
661
+ return isObject2(error) && error.code === code;
662
+ }
663
+
664
+ // src/codetracebench-trajectory.ts
665
+ import { readFile as readFile2 } from "fs/promises";
666
+ import { join as join2 } from "path";
667
+ var TRAJECTORY_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$/;
668
+ var LABEL_KEY = /\\?["'](?:incorrect_stages|incorrect_step_ids|unuseful_step_ids|annotation_relpath|incorrect_error_stage_count)\\?["']\s*:/i;
669
+ var LABEL_ARRAY = /\\?["']labels\\?["']\s*:\s*\[[^\]]*\\?["'](?:incorrect|unuseful)\\?["']/i;
670
+ var ANNOTATION_PATH = /(?:agent_failure_analysis|step_annotations(?:_all)?|merged_cleaned_step\d*)[\\/]/i;
671
+ async function importTrajectory(input) {
672
+ const { index, row, trajectoryDirectory, stagingDirectory, signal } = input;
673
+ const caseDirectory = join2(trajectoryDirectory, row.trajId);
674
+ const stepsPath = await containedFile(
675
+ trajectoryDirectory,
676
+ join2(caseDirectory, "steps.json"),
677
+ `${row.trajId}: steps.json`
678
+ );
679
+ signal.throwIfAborted();
680
+ const stepsBytes = await readFile2(stepsPath, { signal });
681
+ const steps = parseSteps(stepsBytes.toString("utf8"), row);
682
+ const task = await readOptionalTask(trajectoryDirectory, caseDirectory, row, signal);
683
+ const messages = trajectoryMessages(row, steps, task.content);
684
+ const spans = chatTrajectoryToSpans(messages, {
685
+ traceId: row.trajId,
686
+ service: "codetracebench",
687
+ sourcePath: `${row.trajId}/steps.json`
688
+ }).map((item) => ({
689
+ ...item,
690
+ attributes: {
691
+ ...item.attributes,
692
+ "benchmark.name": "CodeTraceBench",
693
+ "trajectory.id": row.trajId,
694
+ ...item.attributes["openinference.span.kind"] === "LLM" ? { "agent.name": row.agent } : {}
695
+ }
696
+ }));
697
+ const actionSpans = spans.filter(
698
+ (item) => item.attributes["openinference.span.kind"] === "LLM"
699
+ );
700
+ if (actionSpans.length !== row.stepCount) {
701
+ throw new Error(
702
+ `${row.trajId}: generated ${actionSpans.length} action spans for ${row.stepCount} steps`
703
+ );
704
+ }
705
+ for (const [stepIndex, item] of actionSpans.entries()) {
706
+ const expectedSpanId = `step-${stepIndex + 1}`;
707
+ if (item.span_id !== expectedSpanId) {
708
+ throw new Error(
709
+ `${row.trajId}: generated action span '${item.span_id}', expected '${expectedSpanId}'`
710
+ );
711
+ }
712
+ }
713
+ assertNoLabelLeak(spans, row);
714
+ const serialized = serializeSpans(spans);
715
+ assertNoLabelLeakInText(serialized, row, `${row.trajId}: serialized OTLP`);
716
+ const outputFile = `${row.trajId}.otlp.jsonl`;
717
+ await atomicWriteFile(join2(stagingDirectory, outputFile), serialized, signal);
718
+ return {
719
+ index,
720
+ traceId: row.trajId,
721
+ stepCount: row.stepCount,
722
+ spanCount: spans.length,
723
+ taskSource: task.source,
724
+ input: {
725
+ stepsPath: `${row.trajId}/steps.json`,
726
+ stepsSha256: sha256(stepsBytes),
727
+ stepsBytes: stepsBytes.byteLength,
728
+ ...task.path ? {
729
+ taskPath: `${row.trajId}/task.md`,
730
+ taskSha256: sha256(task.bytes),
731
+ taskBytes: task.bytes.byteLength
732
+ } : {}
733
+ },
734
+ output: {
735
+ path: outputFile,
736
+ sha256: sha256(serialized),
737
+ bytes: Buffer.byteLength(serialized)
738
+ }
739
+ };
740
+ }
741
+ function trajectoryMessages(row, steps, task) {
742
+ return [
743
+ { role: "user", content: task },
744
+ ...steps.flatMap((step) => {
745
+ const action = {
746
+ role: "assistant",
747
+ content: [step.thinking, step.action].filter(
748
+ (value) => typeof value === "string" && value.length > 0
749
+ ).join("\n"),
750
+ extra: { response: { model: row.model } }
751
+ };
752
+ if (step.observation === null) return [action];
753
+ return [
754
+ action,
755
+ {
756
+ role: "observation",
757
+ content: step.observation,
758
+ ...step.tool_type ? { name: step.tool_type } : {}
759
+ }
760
+ ];
761
+ })
762
+ ];
763
+ }
764
+ function parseRows(text2, path) {
765
+ const trimmed = text2.trim();
766
+ if (!trimmed) throw new Error(`CodeTraceBench rows file is empty: ${path}`);
767
+ try {
768
+ const parsed = JSON.parse(trimmed);
769
+ if (Array.isArray(parsed)) return parsed;
770
+ if (isObject2(parsed)) return [parsed];
771
+ throw new TypeError("JSON must be an object or array");
772
+ } catch (error) {
773
+ if (!/\r?\n/.test(trimmed)) {
774
+ throw new Error(`${path}: invalid JSON: ${errorMessage(error)}`);
775
+ }
776
+ }
777
+ return trimmed.split(/\r?\n/).flatMap((line, index) => {
778
+ if (!line.trim()) return [];
779
+ try {
780
+ return [JSON.parse(line)];
781
+ } catch (error) {
782
+ throw new Error(`${path}:${index + 1}: invalid JSON: ${errorMessage(error)}`);
783
+ }
784
+ });
785
+ }
786
+ function validateRows(rows, path) {
787
+ if (rows.length === 0) throw new Error(`CodeTraceBench rows file is empty: ${path}`);
788
+ const ids = /* @__PURE__ */ new Set();
789
+ return rows.map((value, index) => {
790
+ if (!isObject2(value)) {
791
+ throw new TypeError(`${path}:${index + 1}: CodeTraceBench row must be an object`);
792
+ }
793
+ const trajId = requiredString(value.traj_id, `${path}:${index + 1} traj_id`);
794
+ if (!TRAJECTORY_ID.test(trajId)) {
795
+ throw new TypeError(
796
+ `${path}:${index + 1}: traj_id must contain only letters, digits, dot, underscore, or hyphen`
797
+ );
798
+ }
799
+ if (ids.has(trajId)) {
800
+ throw new TypeError(`${path}:${index + 1}: duplicate traj_id '${trajId}'`);
801
+ }
802
+ ids.add(trajId);
803
+ const stepCount = positiveInteger(
804
+ value.step_count,
805
+ `${path}:${index + 1} step_count`
806
+ );
807
+ const annotationRelpath = value.annotation_relpath === void 0 || value.annotation_relpath === null ? void 0 : requiredString(
808
+ value.annotation_relpath,
809
+ `${path}:${index + 1} annotation_relpath`
810
+ );
811
+ return {
812
+ trajId,
813
+ agent: requiredString(value.agent, `${path}:${index + 1} agent`),
814
+ model: requiredString(value.model, `${path}:${index + 1} model`),
815
+ taskName: requiredString(value.task_name, `${path}:${index + 1} task_name`),
816
+ stepCount,
817
+ ...annotationRelpath ? { annotationRelpath } : {},
818
+ ...value.incorrect_stages === void 0 ? {} : { incorrectStages: value.incorrect_stages }
819
+ };
820
+ });
821
+ }
822
+ function parseSteps(text2, row) {
823
+ let parsed;
824
+ try {
825
+ parsed = JSON.parse(text2);
826
+ } catch (error) {
827
+ throw new Error(`${row.trajId}/steps.json: invalid JSON: ${errorMessage(error)}`);
828
+ }
829
+ if (!Array.isArray(parsed) || parsed.length === 0) {
830
+ throw new TypeError(`${row.trajId}/steps.json must contain a non-empty array`);
831
+ }
832
+ if (parsed.length !== row.stepCount) {
833
+ throw new Error(
834
+ `${row.trajId}: steps.json contains ${parsed.length} steps, row declares ${row.stepCount}`
835
+ );
836
+ }
837
+ return parsed.map((value, index) => {
838
+ const label = `${row.trajId}/steps.json[${index}]`;
839
+ if (!isObject2(value)) throw new TypeError(`${label} must be an object`);
840
+ const stepId = positiveInteger(value.step_id, `${label}.step_id`);
841
+ if (stepId !== index + 1) {
842
+ throw new Error(`${label}.step_id is ${stepId}; expected ${index + 1}`);
843
+ }
844
+ if (!Object.hasOwn(value, "observation")) {
845
+ throw new TypeError(`${label}.observation is required and may be null`);
846
+ }
847
+ const observation = value.observation;
848
+ if (observation !== null && typeof observation !== "string") {
849
+ throw new TypeError(`${label}.observation must be a string or null`);
850
+ }
851
+ return {
852
+ step_id: stepId,
853
+ action: requiredString(value.action, `${label}.action`),
854
+ observation,
855
+ ...value.thinking === void 0 ? {} : { thinking: requiredString(value.thinking, `${label}.thinking`) },
856
+ ...value.parallel_group === void 0 ? {} : {
857
+ parallel_group: nonNegativeInteger(
858
+ value.parallel_group,
859
+ `${label}.parallel_group`
860
+ )
861
+ },
862
+ ...value.tool_type === void 0 ? {} : { tool_type: requiredString(value.tool_type, `${label}.tool_type`) },
863
+ action_ref: fileRef(value.action_ref, `${label}.action_ref`),
864
+ observation_ref: fileRef(value.observation_ref, `${label}.observation_ref`)
865
+ };
866
+ });
867
+ }
868
+ function fileRef(value, label) {
869
+ if (value === null) return null;
870
+ if (!isObject2(value)) throw new TypeError(`${label} must be an object or null`);
871
+ const lineStart = positiveInteger(value.line_start, `${label}.line_start`);
872
+ const lineEnd = positiveInteger(value.line_end, `${label}.line_end`);
873
+ if (lineEnd < lineStart) {
874
+ throw new RangeError(`${label}.line_end must not precede line_start`);
875
+ }
876
+ return {
877
+ path: requiredString(value.path, `${label}.path`),
878
+ line_start: lineStart,
879
+ line_end: lineEnd,
880
+ content: stringField(value.content, `${label}.content`)
881
+ };
882
+ }
883
+ async function readOptionalTask(trajectoryDirectory, caseDirectory, row, signal) {
884
+ const candidate = join2(caseDirectory, "task.md");
885
+ const path = await optionalContainedFile(trajectoryDirectory, candidate);
886
+ if (!path) {
887
+ return {
888
+ source: "task_name",
889
+ content: `Task: ${row.taskName}`
890
+ };
891
+ }
892
+ const bytes = await readFile2(path, { signal });
893
+ const content = bytes.toString("utf8").trim();
894
+ if (!content) throw new Error(`${row.trajId}/task.md is empty`);
895
+ return { source: "task.md", content, path, bytes };
896
+ }
897
+ function assertNoLabelLeak(spans, row) {
898
+ for (const item of spans) {
899
+ const content = item.attributes.content;
900
+ if (typeof content === "string") {
901
+ assertNoLabelLeakInText(content, row, `${row.trajId}/${item.span_id} content`);
902
+ }
903
+ }
904
+ }
905
+ function assertNoLabelLeakInText(text2, row, context) {
906
+ if (LABEL_KEY.test(text2) || LABEL_ARRAY.test(text2) || ANNOTATION_PATH.test(text2)) {
907
+ throw new Error(`${context}: generated trace contains CodeTraceBench annotation data`);
908
+ }
909
+ const annotationPath = row.annotationRelpath?.replaceAll("\\", "/").toLowerCase();
910
+ if (annotationPath && text2.replaceAll("\\", "/").toLowerCase().includes(annotationPath)) {
911
+ throw new Error(`${context}: generated trace contains annotation path`);
912
+ }
913
+ const labels = normalizedLabels(row.incorrectStages);
914
+ if (labels && compact(text2).includes(labels)) {
915
+ throw new Error(`${context}: generated trace contains serialized CodeTraceBench labels`);
916
+ }
917
+ }
918
+ function normalizedLabels(value) {
919
+ if (value === void 0 || value === null) return void 0;
920
+ let parsed = value;
921
+ if (typeof value === "string") {
922
+ const trimmed = value.trim();
923
+ if (!trimmed || trimmed === "[]") return void 0;
924
+ try {
925
+ parsed = JSON.parse(trimmed);
926
+ } catch {
927
+ parsed = trimmed;
928
+ }
929
+ }
930
+ const serialized = JSON.stringify(parsed);
931
+ if (!serialized || serialized === "[]" || serialized === '""') return void 0;
932
+ return compact(serialized);
933
+ }
934
+ function compact(value) {
935
+ return value.replace(/\s+/g, "");
936
+ }
937
+ function positiveInteger(value, label) {
938
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1) {
939
+ throw new TypeError(`${label} must be a positive integer`);
940
+ }
941
+ return value;
942
+ }
943
+ function nonNegativeInteger(value, label) {
944
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
945
+ throw new TypeError(`${label} must be a non-negative integer`);
946
+ }
947
+ return value;
948
+ }
949
+ function requiredString(value, label) {
950
+ if (typeof value !== "string" || !value.trim()) {
951
+ throw new TypeError(`${label} must be a non-empty string`);
952
+ }
953
+ return value.trim();
954
+ }
955
+ function stringField(value, label) {
956
+ if (typeof value !== "string") throw new TypeError(`${label} must be a string`);
957
+ return value;
958
+ }
959
+ function errorMessage(error) {
960
+ return error instanceof Error ? error.message : String(error);
961
+ }
962
+
963
+ // src/codetracebench.ts
964
+ var DEFAULT_CONCURRENCY = 4;
965
+ var MAX_CONCURRENCY = 64;
966
+ var IMMUTABLE_REVISION = /^(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})$/;
967
+ async function importCodeTraceBench(options) {
968
+ const concurrency = validateConcurrency(options.concurrency ?? DEFAULT_CONCURRENCY);
969
+ const revision = validateRevision(options.revision);
970
+ const rowsPath = resolve2(options.rowsPath);
971
+ const trajectoryPath = resolve2(options.trajectoryDir);
972
+ const outputDirectory = resolve2(options.outDir);
973
+ const outputBase = basename2(outputDirectory);
974
+ if (!outputBase || outputDirectory === dirname2(outputDirectory)) {
975
+ throw new Error("CodeTraceBench output directory must not be a filesystem root");
976
+ }
977
+ options.signal?.throwIfAborted();
978
+ await mkdir2(dirname2(outputDirectory), { recursive: true });
979
+ const lock = await claimImportLock({
980
+ rowsPath,
981
+ trajectoryDirectory: trajectoryPath,
982
+ outputDirectory,
983
+ revision,
984
+ signal: options.signal
985
+ });
986
+ try {
987
+ return await runCodeTraceBenchImport({
988
+ concurrency,
989
+ revision,
990
+ rowsPath,
991
+ trajectoryPath,
992
+ outputDirectory,
993
+ outputBase,
994
+ signal: options.signal
995
+ });
996
+ } finally {
997
+ await releaseImportLock(lock);
998
+ }
999
+ }
1000
+ async function runCodeTraceBenchImport(input) {
1001
+ const {
1002
+ concurrency,
1003
+ revision,
1004
+ rowsPath,
1005
+ trajectoryPath,
1006
+ outputDirectory,
1007
+ outputBase,
1008
+ signal: outerSignal
1009
+ } = input;
1010
+ outerSignal?.throwIfAborted();
1011
+ await assertPathMissing(outputDirectory);
1012
+ const trajectoryDirectory = await containedDirectory(trajectoryPath);
1013
+ const rowsBytes = await readFile3(rowsPath, { signal: outerSignal });
1014
+ const rows = parseRows(rowsBytes.toString("utf8"), rowsPath);
1015
+ const sourceRows = validateRows(rows, rowsPath);
1016
+ const stagingDirectory = await mkdtemp(
1017
+ join3(dirname2(outputDirectory), `.${outputBase}.tmp-`)
1018
+ );
1019
+ const stop = new AbortController();
1020
+ const signal = outerSignal ? AbortSignal.any([outerSignal, stop.signal]) : stop.signal;
1021
+ const imported = new Array(sourceRows.length);
1022
+ let nextIndex = 0;
1023
+ try {
1024
+ const workerCount = Math.min(concurrency, sourceRows.length);
1025
+ const workerResults = await Promise.allSettled(
1026
+ Array.from({ length: workerCount }, async () => {
1027
+ while (true) {
1028
+ signal.throwIfAborted();
1029
+ const index = nextIndex;
1030
+ nextIndex += 1;
1031
+ if (index >= sourceRows.length) return;
1032
+ try {
1033
+ imported[index] = await importTrajectory({
1034
+ index,
1035
+ row: sourceRows[index],
1036
+ trajectoryDirectory,
1037
+ stagingDirectory,
1038
+ signal
1039
+ });
1040
+ } catch (error) {
1041
+ stop.abort(error);
1042
+ throw error;
1043
+ }
1044
+ }
1045
+ })
1046
+ );
1047
+ const workerFailure = workerResults.find(
1048
+ (result) => result.status === "rejected"
1049
+ );
1050
+ if (workerFailure) throw workerFailure.reason;
1051
+ signal.throwIfAborted();
1052
+ const rowsSha256 = sha256(rowsBytes);
1053
+ const inputSha256 = sha256(
1054
+ JSON.stringify({
1055
+ revision,
1056
+ rowsSha256,
1057
+ traces: imported.map((item) => ({
1058
+ traceId: item.traceId,
1059
+ stepsSha256: item.input.stepsSha256,
1060
+ taskSha256: item.input.taskSha256 ?? null
1061
+ }))
1062
+ })
1063
+ );
1064
+ const outputSha256 = sha256(
1065
+ JSON.stringify(
1066
+ imported.map((item) => ({
1067
+ traceId: item.traceId,
1068
+ sha256: item.output.sha256
1069
+ }))
1070
+ )
1071
+ );
1072
+ const receipt = {
1073
+ kind: "traces.codetracebench-import",
1074
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1075
+ input: {
1076
+ revision,
1077
+ rowsFile: basename2(rowsPath),
1078
+ rowsSha256,
1079
+ rowsBytes: rowsBytes.byteLength,
1080
+ trajectoryDirectory: basename2(trajectoryDirectory),
1081
+ sha256: inputSha256
1082
+ },
1083
+ settings: {
1084
+ concurrency,
1085
+ outputLayout: "<traj_id>.otlp.jsonl"
1086
+ },
1087
+ counts: {
1088
+ rows: sourceRows.length,
1089
+ traces: imported.length,
1090
+ steps: imported.reduce((sum, item) => sum + item.stepCount, 0),
1091
+ spans: imported.reduce((sum, item) => sum + item.spanCount, 0)
1092
+ },
1093
+ safety: {
1094
+ labelLeakScan: "passed",
1095
+ outputDirectoryCreatedExclusively: true,
1096
+ filesPublishedAtomically: true
1097
+ },
1098
+ traces: imported,
1099
+ outputSha256
1100
+ };
1101
+ const receiptFile = "codetracebench-import.json";
1102
+ await atomicWriteFile(
1103
+ join3(stagingDirectory, receiptFile),
1104
+ `${JSON.stringify(receipt, null, 2)}
1105
+ `,
1106
+ signal
1107
+ );
1108
+ signal.throwIfAborted();
1109
+ await publishStagedFiles(
1110
+ stagingDirectory,
1111
+ outputDirectory,
1112
+ [...imported.map((item) => item.output.path), receiptFile],
1113
+ signal
1114
+ );
1115
+ await rm2(stagingDirectory, { recursive: true, force: true });
1116
+ return {
1117
+ directory: outputDirectory,
1118
+ receiptPath: join3(outputDirectory, receiptFile),
1119
+ receipt
1120
+ };
1121
+ } catch (error) {
1122
+ await rm2(stagingDirectory, { recursive: true, force: true });
1123
+ throw error;
1124
+ }
1125
+ }
1126
+ function validateConcurrency(value) {
1127
+ if (!Number.isSafeInteger(value) || value < 1 || value > MAX_CONCURRENCY) {
1128
+ throw new RangeError(
1129
+ `CodeTraceBench concurrency must be an integer from 1 to ${MAX_CONCURRENCY}`
1130
+ );
1131
+ }
1132
+ return value;
1133
+ }
1134
+ function validateRevision(value) {
1135
+ if (typeof value !== "string" || !IMMUTABLE_REVISION.test(value)) {
1136
+ throw new TypeError(
1137
+ "CodeTraceBench revision must be a full 40- or 64-character hexadecimal commit or digest"
1138
+ );
1139
+ }
1140
+ return value;
1141
+ }
1142
+
294
1143
  // src/execution.ts
295
1144
  import {
296
1145
  summarizeExecution
@@ -324,7 +1173,7 @@ function summarizeSpanExecution(spans, opts = {}) {
324
1173
  import { InMemoryTraceStore } from "@tangle-network/agent-eval";
325
1174
 
326
1175
  // src/adapters/tool-io.ts
327
- import { createHash } from "crypto";
1176
+ import { createHash as createHash3 } from "crypto";
328
1177
  var TOOL_IO_VALUE_MAX_BYTES = 16 * 1024;
329
1178
  var TOOL_IO_VALUE_KEYS = ["input.value", "output.value"];
330
1179
  var TOOL_IO_SIDES = ["input", "output"];
@@ -380,14 +1229,14 @@ function valueAttributes(side, raw) {
380
1229
  const serialized = serialize(raw);
381
1230
  if (!serialized) return {};
382
1231
  const bytes = Buffer.byteLength(serialized.value);
383
- const sha256 = createHash("sha256").update(serialized.value).digest("hex");
1232
+ const sha2562 = createHash3("sha256").update(serialized.value).digest("hex");
384
1233
  const truncated = bytes > TOOL_IO_VALUE_MAX_BYTES;
385
1234
  const value = truncated ? truncatedValue(serialized.value, bytes) : serialized.value;
386
1235
  return {
387
1236
  [`${side}.value`]: value,
388
1237
  [`${side}.mime_type`]: serialized.mimeType,
389
1238
  [`traces.${side}.bytes`]: bytes,
390
- [`traces.${side}.sha256`]: sha256,
1239
+ [`traces.${side}.sha256`]: sha2562,
391
1240
  [`traces.${side}.truncated`]: truncated
392
1241
  };
393
1242
  }
@@ -431,7 +1280,7 @@ function normalizeToolIoAttributes(attributes) {
431
1280
  }
432
1281
  attributes[valueKey] = value;
433
1282
  attributes[bytesKey] = Buffer.byteLength(value);
434
- attributes[digestKey] = createHash("sha256").update(value).digest("hex");
1283
+ attributes[digestKey] = createHash3("sha256").update(value).digest("hex");
435
1284
  attributes[truncatedKey] = truncated;
436
1285
  }
437
1286
  }
@@ -529,7 +1378,7 @@ async function runPipelines(spans, opts = {}) {
529
1378
  }
530
1379
 
531
1380
  // src/integrity.ts
532
- import { createHash as createHash2 } from "crypto";
1381
+ import { createHash as createHash4 } from "crypto";
533
1382
  var receiptStates = /* @__PURE__ */ new WeakMap();
534
1383
  function receiptIdentity(receipt) {
535
1384
  return [
@@ -588,7 +1437,7 @@ function sessionIntegrityAttributes(ref) {
588
1437
  };
589
1438
  }
590
1439
  function corruptionDigest(receipts) {
591
- const hash2 = createHash2("sha256");
1440
+ const hash2 = createHash4("sha256");
592
1441
  for (const receipt of receipts) {
593
1442
  hash2.update(JSON.stringify(receiptIdentity(receipt)));
594
1443
  hash2.update("\n");
@@ -596,7 +1445,7 @@ function corruptionDigest(receipts) {
596
1445
  return `sha256:${hash2.digest("hex")}`;
597
1446
  }
598
1447
  function receiptSpanId(parentSpanId, receipt) {
599
- const digest = createHash2("sha256").update(JSON.stringify(receiptIdentity(receipt))).digest("hex");
1448
+ const digest = createHash4("sha256").update(JSON.stringify(receiptIdentity(receipt))).digest("hex");
600
1449
  return `${parentSpanId}:corruption:${digest}`;
601
1450
  }
602
1451
  function stampSessionIntegrity(ref, spans) {
@@ -641,7 +1490,7 @@ function stampSessionIntegrity(ref, spans) {
641
1490
  }
642
1491
 
643
1492
  // src/json.ts
644
- import { readdir, readFile } from "fs/promises";
1493
+ import { readdir, readFile as readFile4 } from "fs/promises";
645
1494
  var JsonSourceError = class extends Error {
646
1495
  sourcePath;
647
1496
  kind;
@@ -676,7 +1525,7 @@ function isMissingJsonSource(error) {
676
1525
  async function readJsonFile(path) {
677
1526
  let raw;
678
1527
  try {
679
- raw = await readFile(path, "utf8");
1528
+ raw = await readFile4(path, "utf8");
680
1529
  } catch (error) {
681
1530
  throw new JsonSourceError(path, "read", error);
682
1531
  }
@@ -695,9 +1544,9 @@ async function listJsonFiles(path) {
695
1544
  }
696
1545
 
697
1546
  // src/adapters/amp.ts
698
- import { readdir as readdir2, stat } from "fs/promises";
1547
+ import { readdir as readdir2, stat as stat2 } from "fs/promises";
699
1548
  import { homedir } from "os";
700
- import { basename, join } from "path";
1549
+ import { basename as basename3, join as join4 } from "path";
701
1550
  var SERVICE = "amp";
702
1551
  function textOf(content) {
703
1552
  if (typeof content === "string") return content.slice(0, CONTENT_CAP);
@@ -708,8 +1557,8 @@ function textOf(content) {
708
1557
  var AmpAdapter = class {
709
1558
  harness = "amp";
710
1559
  threadsRoot() {
711
- const base = process.env.XDG_DATA_HOME ?? join(homedir(), ".local", "share");
712
- return join(base, "amp", "threads");
1560
+ const base = process.env.XDG_DATA_HOME ?? join4(homedir(), ".local", "share");
1561
+ return join4(base, "amp", "threads");
713
1562
  }
714
1563
  async locate(opts = {}) {
715
1564
  let files;
@@ -722,17 +1571,17 @@ var AmpAdapter = class {
722
1571
  const refs = [];
723
1572
  for (const f of files) {
724
1573
  if (!f.startsWith("T-") || !f.endsWith(".json")) continue;
725
- const path = join(this.threadsRoot(), f);
1574
+ const path = join4(this.threadsRoot(), f);
726
1575
  let st;
727
1576
  try {
728
- st = await stat(path);
1577
+ st = await stat2(path);
729
1578
  } catch (error) {
730
1579
  if (isMissingPathError(error)) continue;
731
1580
  throw error;
732
1581
  }
733
1582
  if (opts.sinceMs && st.mtimeMs < opts.sinceMs) continue;
734
1583
  if (opts.cwd) continue;
735
- refs.push({ harness: this.harness, sessionId: basename(f, ".json"), path, cwd: null, mtimeMs: st.mtimeMs });
1584
+ refs.push({ harness: this.harness, sessionId: basename3(f, ".json"), path, cwd: null, mtimeMs: st.mtimeMs });
736
1585
  }
737
1586
  return refs.sort((a, b) => b.mtimeMs - a.mtimeMs);
738
1587
  }
@@ -823,7 +1672,7 @@ var AmpAdapter = class {
823
1672
 
824
1673
  // src/jsonl.ts
825
1674
  import { isUtf8 } from "buffer";
826
- import { createHash as createHash3 } from "crypto";
1675
+ import { createHash as createHash5 } from "crypto";
827
1676
  import { createReadStream } from "fs";
828
1677
  var JsonlParseError = class extends SyntaxError {
829
1678
  sourcePath;
@@ -852,7 +1701,7 @@ function corruptionReceipt(rawLine, path, lineNumber, byteOffset) {
852
1701
  lineNumber,
853
1702
  byteOffset,
854
1703
  byteLength: rawLine.length,
855
- sha256: createHash3("sha256").update(rawLine).digest("hex"),
1704
+ sha256: createHash5("sha256").update(rawLine).digest("hex"),
856
1705
  rawBytes: "local_source_only"
857
1706
  };
858
1707
  }
@@ -1044,10 +1893,10 @@ function classifyReaction(text2) {
1044
1893
  var CORRECTIVE_REACTIONS = ["correction", "frustration", "jargon", "structure"];
1045
1894
 
1046
1895
  // src/adapters/claude.ts
1047
- import { createHash as createHash4 } from "crypto";
1048
- import { readdir as readdir4, stat as stat2 } from "fs/promises";
1896
+ import { createHash as createHash6 } from "crypto";
1897
+ import { readdir as readdir4, stat as stat3 } from "fs/promises";
1049
1898
  import { homedir as homedir3 } from "os";
1050
- import { basename as basename4, join as join3, relative as relative3 } from "path";
1899
+ import { basename as basename6, join as join6, relative as relative4 } from "path";
1051
1900
  import {
1052
1901
  applyLlmSpanOtlpAttributes as applyLlmSpanOtlpAttributes2,
1053
1902
  LLM_CACHED_TOKENS,
@@ -1057,12 +1906,12 @@ import {
1057
1906
  } from "@tangle-network/agent-eval/trace-attributes";
1058
1907
 
1059
1908
  // src/adapters/claude-subagent-sources.ts
1060
- import { readdir as readdir3, realpath } from "fs/promises";
1909
+ import { readdir as readdir3, realpath as realpath2 } from "fs/promises";
1061
1910
  import { homedir as homedir2 } from "os";
1062
- import { basename as basename3, dirname as dirname2, isAbsolute as isAbsolute2, join as join2, relative as relative2, resolve as resolve2 } from "path";
1911
+ import { basename as basename5, dirname as dirname4, isAbsolute as isAbsolute3, join as join5, relative as relative3, resolve as resolve4 } from "path";
1063
1912
 
1064
1913
  // src/adapters/claude-workflow.ts
1065
- import { basename as basename2, dirname, isAbsolute, relative, resolve } from "path";
1914
+ import { basename as basename4, dirname as dirname3, isAbsolute as isAbsolute2, relative as relative2, resolve as resolve3 } from "path";
1066
1915
  var ClaudeTaskScopeError = class extends Error {
1067
1916
  constructor(message) {
1068
1917
  super(message);
@@ -1073,8 +1922,8 @@ function validWorkflowRunReference(runId, transcriptDir) {
1073
1922
  if (typeof runId !== "string" || typeof transcriptDir !== "string") return void 0;
1074
1923
  const cleanRunId = runId.trim();
1075
1924
  const cleanTranscriptDir = transcriptDir.trim();
1076
- const resolvedTranscriptDir = resolve(cleanTranscriptDir);
1077
- if (!cleanRunId || cleanRunId === "." || cleanRunId === ".." || cleanRunId.includes("/") || cleanRunId.includes("\\") || !isAbsolute(cleanTranscriptDir) || basename2(resolvedTranscriptDir) !== cleanRunId || basename2(dirname(resolvedTranscriptDir)) !== "workflows" || basename2(dirname(dirname(resolvedTranscriptDir))) !== "subagents") {
1925
+ const resolvedTranscriptDir = resolve3(cleanTranscriptDir);
1926
+ if (!cleanRunId || cleanRunId === "." || cleanRunId === ".." || cleanRunId.includes("/") || cleanRunId.includes("\\") || !isAbsolute2(cleanTranscriptDir) || basename4(resolvedTranscriptDir) !== cleanRunId || basename4(dirname3(resolvedTranscriptDir)) !== "workflows" || basename4(dirname3(dirname3(resolvedTranscriptDir))) !== "subagents") {
1078
1927
  return void 0;
1079
1928
  }
1080
1929
  return { runId: cleanRunId, transcriptDir: cleanTranscriptDir };
@@ -1097,7 +1946,7 @@ function workflowRunFromText(text2) {
1097
1946
  return validWorkflowRunReference(runIds[0], transcriptDirs[0]);
1098
1947
  }
1099
1948
  function sameWorkflowRun(left, right) {
1100
- return left.runId === right.runId && resolve(left.transcriptDir) === resolve(right.transcriptDir);
1949
+ return left.runId === right.runId && resolve3(left.transcriptDir) === resolve3(right.transcriptDir);
1101
1950
  }
1102
1951
  function resolveWorkflowRunReference(toolUseId, outputText, structured) {
1103
1952
  const text2 = workflowRunFromText(outputText);
@@ -1151,7 +2000,7 @@ function bindWorkflowRuns(index) {
1151
2000
  return bindings;
1152
2001
  }
1153
2002
  function workflowRunIdForSubagent(subDir, file) {
1154
- const parts = relative(subDir, file).split(/[\\/]/);
2003
+ const parts = relative2(subDir, file).split(/[\\/]/);
1155
2004
  if (parts[0] !== "workflows") return void 0;
1156
2005
  if (parts.length !== 3 || !parts[1] || !/^agent-.*\.jsonl$/.test(parts[2] ?? "")) {
1157
2006
  throw new ClaudeTaskScopeError(
@@ -1167,14 +2016,14 @@ function bindWorkflowSubagent(file, runId, transcriptDir, bindings) {
1167
2016
  `Cannot link Claude Workflow subagent ${file}: parent result has no run ${runId}`
1168
2017
  );
1169
2018
  }
1170
- const expectedDir = resolve(transcriptDir);
1171
- if (resolve(dirname(file)) !== expectedDir) {
2019
+ const expectedDir = resolve3(transcriptDir);
2020
+ if (resolve3(dirname3(file)) !== expectedDir) {
1172
2021
  throw new ClaudeTaskScopeError(
1173
2022
  `Cannot link Claude Workflow run ${runId}: transcript directory does not match ${expectedDir}`
1174
2023
  );
1175
2024
  }
1176
2025
  const localBindings = runBindings.filter(
1177
- (binding) => resolve(binding.transcriptDir) === expectedDir
2026
+ (binding) => resolve3(binding.transcriptDir) === expectedDir
1178
2027
  );
1179
2028
  if (localBindings.length === 0) {
1180
2029
  throw new ClaudeTaskScopeError(
@@ -1240,7 +2089,7 @@ async function listSubagentFiles(root, signal) {
1240
2089
  }
1241
2090
  signal?.throwIfAborted();
1242
2091
  for (const entry of entries) {
1243
- const path = join2(dir, entry.name);
2092
+ const path = join5(dir, entry.name);
1244
2093
  if (entry.isDirectory()) {
1245
2094
  pending.push(path);
1246
2095
  } else if (entry.isFile() && /^agent-.*\.jsonl$/.test(entry.name)) {
@@ -1251,20 +2100,20 @@ async function listSubagentFiles(root, signal) {
1251
2100
  return files.sort();
1252
2101
  }
1253
2102
  function pathIsWithin(root, target) {
1254
- const path = relative2(resolve2(root), resolve2(target));
1255
- return path === "" || path !== ".." && !path.startsWith("../") && !path.startsWith("..\\") && !isAbsolute2(path);
2103
+ const path = relative3(resolve4(root), resolve4(target));
2104
+ return path === "" || path !== ".." && !path.startsWith("../") && !path.startsWith("..\\") && !isAbsolute3(path);
1256
2105
  }
1257
2106
  function workflowStorageRoot(ref) {
1258
- const nativeRoot = resolve2(homedir2(), ".claude", "projects");
1259
- return pathIsWithin(nativeRoot, ref.path) ? nativeRoot : dirname2(resolve2(ref.path));
2107
+ const nativeRoot = resolve4(homedir2(), ".claude", "projects");
2108
+ return pathIsWithin(nativeRoot, ref.path) ? nativeRoot : dirname4(resolve4(ref.path));
1260
2109
  }
1261
2110
  async function workflowTranscriptDirectories(ref, bindings) {
1262
2111
  const allowedRoot = workflowStorageRoot(ref);
1263
- const allowedRealRoot = await realpath(allowedRoot);
2112
+ const allowedRealRoot = await realpath2(allowedRoot);
1264
2113
  const directories = /* @__PURE__ */ new Map();
1265
2114
  for (const runBindings of bindings.values()) {
1266
2115
  for (const binding of runBindings) {
1267
- const directory = resolve2(binding.transcriptDir);
2116
+ const directory = resolve4(binding.transcriptDir);
1268
2117
  if (!pathIsWithin(allowedRoot, directory)) {
1269
2118
  throw new ClaudeTaskScopeError(
1270
2119
  `Claude Workflow transcript directory escapes ${allowedRoot}: ${directory}`
@@ -1272,7 +2121,7 @@ async function workflowTranscriptDirectories(ref, bindings) {
1272
2121
  }
1273
2122
  let realDirectory;
1274
2123
  try {
1275
- realDirectory = await realpath(directory);
2124
+ realDirectory = await realpath2(directory);
1276
2125
  } catch (error) {
1277
2126
  if (isMissingPathError(error)) continue;
1278
2127
  throw error;
@@ -1288,28 +2137,28 @@ async function workflowTranscriptDirectories(ref, bindings) {
1288
2137
  return [...directories.values()].sort();
1289
2138
  }
1290
2139
  async function collectClaudeSubagentSources(ref, bindings, signal) {
1291
- const subDir = join2(ref.path.replace(/\.jsonl$/, ""), "subagents");
2140
+ const subDir = join5(ref.path.replace(/\.jsonl$/, ""), "subagents");
1292
2141
  const filesByPath = /* @__PURE__ */ new Map();
1293
2142
  const workflowByPath = /* @__PURE__ */ new Map();
1294
2143
  for (const file of await listSubagentFiles(subDir, signal)) {
1295
- const path = resolve2(file);
2144
+ const path = resolve4(file);
1296
2145
  filesByPath.set(path, file);
1297
2146
  const runId = workflowRunIdForSubagent(subDir, file);
1298
2147
  if (runId) {
1299
2148
  workflowByPath.set(path, {
1300
2149
  runId,
1301
- transcriptDir: dirname2(file)
2150
+ transcriptDir: dirname4(file)
1302
2151
  });
1303
2152
  }
1304
2153
  }
1305
2154
  for (const transcriptDir of await workflowTranscriptDirectories(ref, bindings)) {
1306
2155
  signal?.throwIfAborted();
1307
- const runId = basename3(transcriptDir);
2156
+ const runId = basename5(transcriptDir);
1308
2157
  for (const file of await listSubagentFiles(transcriptDir, signal)) {
1309
- const path = resolve2(file);
2158
+ const path = resolve4(file);
1310
2159
  filesByPath.set(path, file);
1311
2160
  const previous = workflowByPath.get(path);
1312
- if (previous && (previous.runId !== runId || resolve2(previous.transcriptDir) !== resolve2(transcriptDir))) {
2161
+ if (previous && (previous.runId !== runId || resolve4(previous.transcriptDir) !== resolve4(transcriptDir))) {
1313
2162
  throw new ClaudeTaskScopeError(
1314
2163
  `Claude Workflow subagent ${file} belongs to multiple transcript directories`
1315
2164
  );
@@ -1458,7 +2307,7 @@ function indexWorkflowProjection(projection, index) {
1458
2307
  indexWorkflowResults(index, results);
1459
2308
  }
1460
2309
  function fingerprintClaudeEvent(event) {
1461
- return createHash4("sha256").update(JSON.stringify(event)).digest("hex");
2310
+ return createHash6("sha256").update(JSON.stringify(event)).digest("hex");
1462
2311
  }
1463
2312
  function startsClaudeTask(projection) {
1464
2313
  if (projection.kind !== "user" || projection.prompt === null) return false;
@@ -1745,7 +2594,7 @@ var ClaudeAdapter = class {
1745
2594
  harness = "claude-code";
1746
2595
  aliases = ["claude", "claudish", "openclaw", "nanoclaw"];
1747
2596
  root() {
1748
- return join3(homedir3(), ".claude", "projects");
2597
+ return join6(homedir3(), ".claude", "projects");
1749
2598
  }
1750
2599
  async sourcePaths(ref, options = {}) {
1751
2600
  const bindings = await readClaudeWorkflowBindings(ref, options);
@@ -1755,7 +2604,7 @@ var ClaudeAdapter = class {
1755
2604
  options.signal?.throwIfAborted();
1756
2605
  const path = file.replace(/\.jsonl$/, ".meta.json");
1757
2606
  try {
1758
- const source = await stat2(path);
2607
+ const source = await stat3(path);
1759
2608
  if (source.isFile()) metadataFiles.push(path);
1760
2609
  } catch (error) {
1761
2610
  if (!isMissingPathError(error)) throw error;
@@ -1775,7 +2624,7 @@ var ClaudeAdapter = class {
1775
2624
  }
1776
2625
  const refs = [];
1777
2626
  for (const dir of projectDirs) {
1778
- const dirPath = join3(root, dir);
2627
+ const dirPath = join6(root, dir);
1779
2628
  let files;
1780
2629
  try {
1781
2630
  files = await readdir4(dirPath);
@@ -1785,10 +2634,10 @@ var ClaudeAdapter = class {
1785
2634
  }
1786
2635
  for (const f of files) {
1787
2636
  if (!f.endsWith(".jsonl")) continue;
1788
- const path = join3(dirPath, f);
2637
+ const path = join6(dirPath, f);
1789
2638
  let st;
1790
2639
  try {
1791
- st = await stat2(path);
2640
+ st = await stat3(path);
1792
2641
  } catch (error) {
1793
2642
  if (isMissingPathError(error)) continue;
1794
2643
  throw error;
@@ -1797,7 +2646,7 @@ var ClaudeAdapter = class {
1797
2646
  if (opts.sinceMs && st.mtimeMs < opts.sinceMs) continue;
1798
2647
  const cwd = `/${dir.replace(/^-/, "").replace(/-/g, "/")}`;
1799
2648
  if (opts.cwd && !cwd.startsWith(opts.cwd)) continue;
1800
- refs.push({ harness: this.harness, sessionId: basename4(f, ".jsonl"), path, cwd, mtimeMs: st.mtimeMs });
2649
+ refs.push({ harness: this.harness, sessionId: basename6(f, ".jsonl"), path, cwd, mtimeMs: st.mtimeMs });
1801
2650
  }
1802
2651
  }
1803
2652
  return refs.sort((a, b) => b.mtimeMs - a.mtimeMs);
@@ -1899,7 +2748,7 @@ var ClaudeAdapter = class {
1899
2748
  }
1900
2749
  /** Parse nested `subagents/.../agent-*.jsonl`, parenting each under its Agent call. */
1901
2750
  async foldSubagents(ref, traceId, main, workflowBindings, out, options) {
1902
- const subDir = join3(ref.path.replace(/\.jsonl$/, ""), "subagents");
2751
+ const subDir = join6(ref.path.replace(/\.jsonl$/, ""), "subagents");
1903
2752
  const sources = await collectClaudeSubagentSources(
1904
2753
  ref,
1905
2754
  workflowBindings,
@@ -1909,7 +2758,7 @@ var ClaudeAdapter = class {
1909
2758
  const agents = [];
1910
2759
  for (const file of sources.files) {
1911
2760
  options.signal?.throwIfAborted();
1912
- const sourceKey = relative3(subDir, file).replace(/\.jsonl$/, "").split(/[\\/]/).map((segment) => encodeURIComponent(segment)).join(":");
2761
+ const sourceKey = relative4(subDir, file).replace(/\.jsonl$/, "").split(/[\\/]/).map((segment) => encodeURIComponent(segment)).join(":");
1913
2762
  const metaPath = file.replace(/\.jsonl$/, ".meta.json");
1914
2763
  let meta = {};
1915
2764
  try {
@@ -1923,7 +2772,7 @@ var ClaudeAdapter = class {
1923
2772
  const agent = {
1924
2773
  file,
1925
2774
  sourceKey,
1926
- agentId: basename4(file, ".jsonl").replace(/^agent-/, ""),
2775
+ agentId: basename6(file, ".jsonl").replace(/^agent-/, ""),
1927
2776
  meta,
1928
2777
  ...meta.toolUseId ? { parentToolUseId: meta.toolUseId } : {}
1929
2778
  };
@@ -1936,7 +2785,7 @@ var ClaudeAdapter = class {
1936
2785
  );
1937
2786
  const parsed = await parseClaudeSubagent(ref, traceId, agent, options);
1938
2787
  const binding = selectWorkflowBinding(
1939
- basename4(file),
2788
+ basename6(file),
1940
2789
  runBindings,
1941
2790
  firstSubagentTimestamp(agent, parsed),
1942
2791
  meta.toolUseId
@@ -2304,9 +3153,9 @@ async function resolveCodexParentTask(ref, childSessionId, options = {}) {
2304
3153
  }
2305
3154
 
2306
3155
  // src/adapters/codex.ts
2307
- import { readdir as readdir5, stat as stat3 } from "fs/promises";
3156
+ import { readdir as readdir5, stat as stat4 } from "fs/promises";
2308
3157
  import { homedir as homedir4 } from "os";
2309
- import { basename as basename5, join as join4 } from "path";
3158
+ import { basename as basename7, join as join7 } from "path";
2310
3159
  var SERVICE3 = "codex";
2311
3160
  var SESSION_HEAD_LINES = 40;
2312
3161
  function tokenUsageSignature(usage) {
@@ -2527,7 +3376,7 @@ async function* walkRollouts(root) {
2527
3376
  throw error;
2528
3377
  }
2529
3378
  for (const y of years) {
2530
- const yp = join4(root, y);
3379
+ const yp = join7(root, y);
2531
3380
  let months;
2532
3381
  try {
2533
3382
  months = await readdir5(yp);
@@ -2536,7 +3385,7 @@ async function* walkRollouts(root) {
2536
3385
  throw error;
2537
3386
  }
2538
3387
  for (const m of months) {
2539
- const mp = join4(yp, m);
3388
+ const mp = join7(yp, m);
2540
3389
  let days;
2541
3390
  try {
2542
3391
  days = await readdir5(mp);
@@ -2545,7 +3394,7 @@ async function* walkRollouts(root) {
2545
3394
  throw error;
2546
3395
  }
2547
3396
  for (const d of days) {
2548
- const dp = join4(mp, d);
3397
+ const dp = join7(mp, d);
2549
3398
  let files;
2550
3399
  try {
2551
3400
  files = await readdir5(dp);
@@ -2554,7 +3403,7 @@ async function* walkRollouts(root) {
2554
3403
  throw error;
2555
3404
  }
2556
3405
  for (const f of files) {
2557
- if (f.startsWith("rollout-") && f.endsWith(".jsonl")) yield join4(dp, f);
3406
+ if (f.startsWith("rollout-") && f.endsWith(".jsonl")) yield join7(dp, f);
2558
3407
  }
2559
3408
  }
2560
3409
  }
@@ -2564,19 +3413,19 @@ var CodexAdapter = class {
2564
3413
  harness = "codex";
2565
3414
  aliases = ["codex-acp"];
2566
3415
  root() {
2567
- return process.env.CODEX_HOME ? join4(process.env.CODEX_HOME, "sessions") : join4(homedir4(), ".codex", "sessions");
3416
+ return process.env.CODEX_HOME ? join7(process.env.CODEX_HOME, "sessions") : join7(homedir4(), ".codex", "sessions");
2568
3417
  }
2569
3418
  async refFromPath(path, opts) {
2570
3419
  let st;
2571
3420
  try {
2572
- st = await stat3(path);
3421
+ st = await stat4(path);
2573
3422
  } catch (error) {
2574
3423
  if (isMissingPathError(error)) return void 0;
2575
3424
  throw error;
2576
3425
  }
2577
3426
  if (opts.sinceMs && st.mtimeMs < opts.sinceMs) return void 0;
2578
3427
  let cwd = null;
2579
- let id = basename5(path).replace(/^rollout-[\dT-]+-/, "").replace(/\.jsonl$/, "");
3428
+ let id = basename7(path).replace(/^rollout-[\dT-]+-/, "").replace(/\.jsonl$/, "");
2580
3429
  const ref = { harness: this.harness, sessionId: id, path, cwd, mtimeMs: st.mtimeMs };
2581
3430
  const head = await takeJsonl(path, SESSION_HEAD_LINES, sessionJsonlOptions(ref));
2582
3431
  for (const parsed of head) {
@@ -2604,7 +3453,7 @@ var CodexAdapter = class {
2604
3453
  async locateBySessionId(sessionId, opts = {}) {
2605
3454
  const refs = [];
2606
3455
  for await (const path of walkRollouts(this.root())) {
2607
- if (!basename5(path).includes(sessionId)) continue;
3456
+ if (!basename7(path).includes(sessionId)) continue;
2608
3457
  const ref = await this.refFromPath(path, opts);
2609
3458
  if (ref?.sessionId === sessionId) refs.push(ref);
2610
3459
  }
@@ -3002,7 +3851,7 @@ var CodexExecStreamError = class extends Error {
3002
3851
  function objectValue(value) {
3003
3852
  return value != null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
3004
3853
  }
3005
- function stringValue(value) {
3854
+ function stringValue2(value) {
3006
3855
  return typeof value === "string" && value.length > 0 ? value : void 0;
3007
3856
  }
3008
3857
  function isoTime(value) {
@@ -3043,7 +3892,7 @@ function requireObject2(value, sourcePath, label) {
3043
3892
  return object;
3044
3893
  }
3045
3894
  function requireString(value, sourcePath, label) {
3046
- const string = stringValue(value);
3895
+ const string = stringValue2(value);
3047
3896
  if (!string) throw new CodexExecStreamError(sourcePath, `${label} must be a non-empty string`);
3048
3897
  return string;
3049
3898
  }
@@ -3078,7 +3927,7 @@ function fileChanges(item, sourcePath) {
3078
3927
  function toolInput(itemType2, item, sourcePath) {
3079
3928
  if (itemType2 === "command_execution") {
3080
3929
  const command = requireString(item.command, sourcePath, "command_execution.command");
3081
- const cwd = stringValue(item.cwd);
3930
+ const cwd = stringValue2(item.cwd);
3082
3931
  return { cmd: command, ...cwd ? { cwd } : {} };
3083
3932
  }
3084
3933
  return { changes: fileChanges(item, sourcePath) };
@@ -3100,7 +3949,7 @@ function completedStatus(itemType2, item, sourcePath) {
3100
3949
  };
3101
3950
  }
3102
3951
  function itemType(item) {
3103
- return stringValue(item.type);
3952
+ return stringValue2(item.type);
3104
3953
  }
3105
3954
  function toolItemType(item) {
3106
3955
  const type = itemType(item);
@@ -3153,7 +4002,7 @@ var CodexExecAdapter = class {
3153
4002
  const id = requireString(item.id, ref.path, `${type}.id`);
3154
4003
  const name = toolName(type);
3155
4004
  const input = toolInput(type, item, ref.path);
3156
- const cwd = stringValue(item.cwd);
4005
+ const cwd = stringValue2(item.cwd);
3157
4006
  if (!ref.cwd && cwd) ref.cwd = cwd;
3158
4007
  const toolSpan = span({
3159
4008
  traceId: threadId,
@@ -3240,7 +4089,7 @@ var CodexExecAdapter = class {
3240
4089
  };
3241
4090
  for await (const raw of readJsonl(ref.path, sessionJsonlOptions(ref, options))) {
3242
4091
  const event = objectValue(raw);
3243
- const type = event ? stringValue(event.type) : void 0;
4092
+ const type = event ? stringValue2(event.type) : void 0;
3244
4093
  if (!event || !type || !SUPPORTED_EVENT_TYPES.has(type)) {
3245
4094
  ignoredEventCount += 1;
3246
4095
  continue;
@@ -3297,7 +4146,7 @@ var CodexExecAdapter = class {
3297
4146
  if (turn.pendingTools.has(id) || turn.completedItemIds.has(id)) {
3298
4147
  fail(`item ${id} started more than once`);
3299
4148
  }
3300
- const status = stringValue(item.status);
4149
+ const status = stringValue2(item.status);
3301
4150
  if (status !== void 0 && status !== "in_progress") {
3302
4151
  fail(`${toolType}.status on item.started must be "in_progress" when present`);
3303
4152
  }
@@ -3419,15 +4268,15 @@ var CodexExecAdapter = class {
3419
4268
  };
3420
4269
 
3421
4270
  // src/adapters/copilot.ts
3422
- import { readdir as readdir6, stat as stat4 } from "fs/promises";
4271
+ import { readdir as readdir6, stat as stat5 } from "fs/promises";
3423
4272
  import { homedir as homedir5 } from "os";
3424
- import { join as join5 } from "path";
4273
+ import { join as join8 } from "path";
3425
4274
  var SERVICE5 = "github-copilot";
3426
4275
  var CopilotAdapter = class {
3427
4276
  harness = "github-copilot";
3428
4277
  aliases = ["copilot"];
3429
4278
  root() {
3430
- return join5(process.env.COPILOT_HOME ?? join5(homedir5(), ".copilot"), "session-state");
4279
+ return join8(process.env.COPILOT_HOME ?? join8(homedir5(), ".copilot"), "session-state");
3431
4280
  }
3432
4281
  async locate(opts = {}) {
3433
4282
  let dirs;
@@ -3439,10 +4288,10 @@ var CopilotAdapter = class {
3439
4288
  }
3440
4289
  const refs = [];
3441
4290
  for (const id of dirs) {
3442
- const path = join5(this.root(), id, "events.jsonl");
4291
+ const path = join8(this.root(), id, "events.jsonl");
3443
4292
  let st;
3444
4293
  try {
3445
- st = await stat4(path);
4294
+ st = await stat5(path);
3446
4295
  } catch (error) {
3447
4296
  if (isMissingPathError(error)) continue;
3448
4297
  throw error;
@@ -3543,9 +4392,9 @@ var CopilotAdapter = class {
3543
4392
  };
3544
4393
 
3545
4394
  // src/adapters/factory.ts
3546
- import { readdir as readdir7, stat as stat5 } from "fs/promises";
4395
+ import { readdir as readdir7, stat as stat6 } from "fs/promises";
3547
4396
  import { homedir as homedir6 } from "os";
3548
- import { basename as basename6, join as join6 } from "path";
4397
+ import { basename as basename8, join as join9 } from "path";
3549
4398
  var SERVICE6 = "factory";
3550
4399
  function textOf4(content) {
3551
4400
  return capText(
@@ -3556,7 +4405,7 @@ var FactoryAdapter = class {
3556
4405
  harness = "factory";
3557
4406
  aliases = ["factory-droids", "droid"];
3558
4407
  root() {
3559
- return join6(homedir6(), ".factory", "sessions");
4408
+ return join9(homedir6(), ".factory", "sessions");
3560
4409
  }
3561
4410
  async locate(opts = {}) {
3562
4411
  const root = this.root();
@@ -3569,7 +4418,7 @@ var FactoryAdapter = class {
3569
4418
  }
3570
4419
  const refs = [];
3571
4420
  for (const dir of dirs) {
3572
- const dp = join6(root, dir);
4421
+ const dp = join9(root, dir);
3573
4422
  let files;
3574
4423
  try {
3575
4424
  files = await readdir7(dp);
@@ -3581,16 +4430,16 @@ var FactoryAdapter = class {
3581
4430
  if (opts.cwd && !cwd.startsWith(opts.cwd)) continue;
3582
4431
  for (const f of files) {
3583
4432
  if (!f.endsWith(".jsonl")) continue;
3584
- const path = join6(dp, f);
4433
+ const path = join9(dp, f);
3585
4434
  let st;
3586
4435
  try {
3587
- st = await stat5(path);
4436
+ st = await stat6(path);
3588
4437
  } catch (error) {
3589
4438
  if (isMissingPathError(error)) continue;
3590
4439
  throw error;
3591
4440
  }
3592
4441
  if (opts.sinceMs && st.mtimeMs < opts.sinceMs) continue;
3593
- refs.push({ harness: this.harness, sessionId: basename6(f, ".jsonl"), path, cwd, mtimeMs: st.mtimeMs });
4442
+ refs.push({ harness: this.harness, sessionId: basename8(f, ".jsonl"), path, cwd, mtimeMs: st.mtimeMs });
3594
4443
  }
3595
4444
  }
3596
4445
  return refs.sort((a, b) => b.mtimeMs - a.mtimeMs);
@@ -3715,9 +4564,9 @@ var FactoryAdapter = class {
3715
4564
  };
3716
4565
 
3717
4566
  // src/adapters/forge.ts
3718
- import { readdir as readdir8, stat as stat6 } from "fs/promises";
4567
+ import { readdir as readdir8, stat as stat7 } from "fs/promises";
3719
4568
  import { homedir as homedir7 } from "os";
3720
- import { basename as basename7, join as join7 } from "path";
4569
+ import { basename as basename9, join as join10 } from "path";
3721
4570
  var SERVICE7 = "forge";
3722
4571
  function tokens(t) {
3723
4572
  if (!t) return null;
@@ -3731,7 +4580,7 @@ var ForgeAdapter = class {
3731
4580
  aliases = ["forgecode"];
3732
4581
  /** Directories scanned for `*-dump.json` exports. */
3733
4582
  dumpDirs() {
3734
- return [process.cwd(), join7(homedir7(), ".forge")];
4583
+ return [process.cwd(), join10(homedir7(), ".forge")];
3735
4584
  }
3736
4585
  async locate(opts = {}) {
3737
4586
  const refs = [];
@@ -3746,16 +4595,16 @@ var ForgeAdapter = class {
3746
4595
  }
3747
4596
  for (const f of files) {
3748
4597
  if (!f.endsWith("-dump.json")) continue;
3749
- const path = join7(dir, f);
4598
+ const path = join10(dir, f);
3750
4599
  let st;
3751
4600
  try {
3752
- st = await stat6(path);
4601
+ st = await stat7(path);
3753
4602
  } catch (error) {
3754
4603
  if (isMissingPathError(error)) continue;
3755
4604
  throw error;
3756
4605
  }
3757
4606
  if (opts.sinceMs && st.mtimeMs < opts.sinceMs) continue;
3758
- refs.push({ harness: this.harness, sessionId: basename7(f, ".json"), path, cwd: dir, mtimeMs: st.mtimeMs });
4607
+ refs.push({ harness: this.harness, sessionId: basename9(f, ".json"), path, cwd: dir, mtimeMs: st.mtimeMs });
3759
4608
  }
3760
4609
  }
3761
4610
  return refs.sort((a, b) => b.mtimeMs - a.mtimeMs);
@@ -3845,9 +4694,9 @@ var ForgeAdapter = class {
3845
4694
  };
3846
4695
 
3847
4696
  // src/adapters/gemini.ts
3848
- import { readdir as readdir9, stat as stat7 } from "fs/promises";
4697
+ import { readdir as readdir9, stat as stat8 } from "fs/promises";
3849
4698
  import { homedir as homedir8 } from "os";
3850
- import { join as join8 } from "path";
4699
+ import { join as join11 } from "path";
3851
4700
  function iso(ts, fallback) {
3852
4701
  if (typeof ts === "number") return new Date(ts).toISOString();
3853
4702
  if (typeof ts === "string" && ts.length > 0) return ts;
@@ -3872,7 +4721,7 @@ var GeminiFamilyAdapter = class {
3872
4721
  this.homeDirName = cfg.homeDirName;
3873
4722
  }
3874
4723
  chatsRoot() {
3875
- return join8(homedir8(), this.homeDirName, "tmp");
4724
+ return join11(homedir8(), this.homeDirName, "tmp");
3876
4725
  }
3877
4726
  /** `<home>/projects.json` maps `{ <absolute-cwd>: <projectName> }`. The session
3878
4727
  * dir name (`tmp/<projectHash>/`) is that projectName for registered projects,
@@ -3882,7 +4731,7 @@ var GeminiFamilyAdapter = class {
3882
4731
  const nameToPath = /* @__PURE__ */ new Map();
3883
4732
  try {
3884
4733
  const projects = (await readJsonFile(
3885
- join8(homedir8(), this.homeDirName, "projects.json")
4734
+ join11(homedir8(), this.homeDirName, "projects.json")
3886
4735
  )).projects ?? {};
3887
4736
  for (const [path, name] of Object.entries(projects)) nameToPath.set(name, path);
3888
4737
  } catch (error) {
@@ -3903,7 +4752,7 @@ var GeminiFamilyAdapter = class {
3903
4752
  const refs = [];
3904
4753
  for (const pd of projectDirs) {
3905
4754
  const cwd = projectCwds.get(pd) ?? null;
3906
- const chatsDir = join8(root, pd, "chats");
4755
+ const chatsDir = join11(root, pd, "chats");
3907
4756
  let files;
3908
4757
  try {
3909
4758
  files = await readdir9(chatsDir);
@@ -3913,10 +4762,10 @@ var GeminiFamilyAdapter = class {
3913
4762
  }
3914
4763
  for (const f of files) {
3915
4764
  if (!f.startsWith("session-") || !f.endsWith(".json")) continue;
3916
- const path = join8(chatsDir, f);
4765
+ const path = join11(chatsDir, f);
3917
4766
  let st;
3918
4767
  try {
3919
- st = await stat7(path);
4768
+ st = await stat8(path);
3920
4769
  } catch (error) {
3921
4770
  if (isMissingPathError(error)) continue;
3922
4771
  throw error;
@@ -4020,9 +4869,9 @@ var GeminiAdapter = class extends GeminiFamilyAdapter {
4020
4869
  };
4021
4870
 
4022
4871
  // src/adapters/opencode.ts
4023
- import { readdir as readdir10, stat as stat8 } from "fs/promises";
4872
+ import { readdir as readdir10, stat as stat9 } from "fs/promises";
4024
4873
  import { homedir as homedir9 } from "os";
4025
- import { join as join9 } from "path";
4874
+ import { join as join12 } from "path";
4026
4875
  var SERVICE8 = "opencode";
4027
4876
  function isoOf(ms) {
4028
4877
  return new Date(ms ?? 0).toISOString();
@@ -4035,11 +4884,11 @@ function textOf7(parts) {
4035
4884
  var OpencodeAdapter = class {
4036
4885
  harness = "opencode";
4037
4886
  storage() {
4038
- const base = process.env.XDG_DATA_HOME ?? join9(homedir9(), ".local", "share");
4039
- return join9(base, "opencode", "storage");
4887
+ const base = process.env.XDG_DATA_HOME ?? join12(homedir9(), ".local", "share");
4888
+ return join12(base, "opencode", "storage");
4040
4889
  }
4041
4890
  async locate(opts = {}) {
4042
- const msgRoot = join9(this.storage(), "message");
4891
+ const msgRoot = join12(this.storage(), "message");
4043
4892
  let sessionDirs;
4044
4893
  try {
4045
4894
  sessionDirs = await readdir10(msgRoot);
@@ -4049,10 +4898,10 @@ var OpencodeAdapter = class {
4049
4898
  }
4050
4899
  const refs = [];
4051
4900
  for (const sid of sessionDirs) {
4052
- const dir = join9(msgRoot, sid);
4901
+ const dir = join12(msgRoot, sid);
4053
4902
  let st;
4054
4903
  try {
4055
- st = await stat8(dir);
4904
+ st = await stat9(dir);
4056
4905
  } catch (error) {
4057
4906
  if (isMissingPathError(error)) continue;
4058
4907
  throw error;
@@ -4067,11 +4916,11 @@ var OpencodeAdapter = class {
4067
4916
  async parse(ref) {
4068
4917
  const traceId = ref.sessionId;
4069
4918
  const rootId = `root:${traceId}`;
4070
- const partRoot = join9(this.storage(), "part");
4919
+ const partRoot = join12(this.storage(), "part");
4071
4920
  const msgFiles = await listJsonFiles(ref.path);
4072
4921
  const messages = [];
4073
4922
  for (const f of msgFiles) {
4074
- messages.push(await readJsonFile(join9(ref.path, f)));
4923
+ messages.push(await readJsonFile(join12(ref.path, f)));
4075
4924
  }
4076
4925
  messages.sort((a, b) => (a.time?.created ?? 0) - (b.time?.created ?? 0));
4077
4926
  const spans = [
@@ -4091,7 +4940,7 @@ var OpencodeAdapter = class {
4091
4940
  for (const msg of messages) {
4092
4941
  const mid = msg.id ?? `m${step}`;
4093
4942
  const llmId = `llm:${mid}`;
4094
- const pdir = join9(partRoot, mid);
4943
+ const pdir = join12(partRoot, mid);
4095
4944
  const parts = [];
4096
4945
  let partFiles = [];
4097
4946
  try {
@@ -4100,7 +4949,7 @@ var OpencodeAdapter = class {
4100
4949
  if (!isMissingJsonSource(error)) throw error;
4101
4950
  }
4102
4951
  for (const pf of partFiles) {
4103
- parts.push(await readJsonFile(join9(pdir, pf)));
4952
+ parts.push(await readJsonFile(join12(pdir, pf)));
4104
4953
  }
4105
4954
  const turnText = textOf7(parts);
4106
4955
  const isUser = msg.role === "user";
@@ -4176,9 +5025,9 @@ var OpencodeAdapter = class {
4176
5025
  };
4177
5026
 
4178
5027
  // src/adapters/pi.ts
4179
- import { readdir as readdir11, stat as stat9 } from "fs/promises";
5028
+ import { readdir as readdir11, stat as stat10 } from "fs/promises";
4180
5029
  import { homedir as homedir10 } from "os";
4181
- import { basename as basename8, join as join10 } from "path";
5030
+ import { basename as basename10, join as join13 } from "path";
4182
5031
  var SERVICE9 = "pi";
4183
5032
  function terminalStatus(message) {
4184
5033
  const stopReason = message?.stopReason ?? "missing";
@@ -4224,7 +5073,7 @@ function completeToolSpan(toolSpan, result) {
4224
5073
  var PiAdapter = class {
4225
5074
  harness = "pi";
4226
5075
  root() {
4227
- return join10(homedir10(), ".pi", "agent", "sessions");
5076
+ return join13(homedir10(), ".pi", "agent", "sessions");
4228
5077
  }
4229
5078
  async locate(opts = {}) {
4230
5079
  const root = this.root();
@@ -4237,7 +5086,7 @@ var PiAdapter = class {
4237
5086
  }
4238
5087
  const refs = [];
4239
5088
  for (const dir of dirs) {
4240
- const dp = join10(root, dir);
5089
+ const dp = join13(root, dir);
4241
5090
  let files;
4242
5091
  try {
4243
5092
  files = await readdir11(dp);
@@ -4249,16 +5098,16 @@ var PiAdapter = class {
4249
5098
  if (opts.cwd && !cwd.startsWith(opts.cwd)) continue;
4250
5099
  for (const f of files) {
4251
5100
  if (!f.endsWith(".jsonl")) continue;
4252
- const path = join10(dp, f);
5101
+ const path = join13(dp, f);
4253
5102
  let st;
4254
5103
  try {
4255
- st = await stat9(path);
5104
+ st = await stat10(path);
4256
5105
  } catch (error) {
4257
5106
  if (isMissingPathError(error)) continue;
4258
5107
  throw error;
4259
5108
  }
4260
5109
  if (opts.sinceMs && st.mtimeMs < opts.sinceMs) continue;
4261
- const id = basename8(f, ".jsonl").replace(/^[\dTZ.-]+_/, "");
5110
+ const id = basename10(f, ".jsonl").replace(/^[\dTZ.-]+_/, "");
4262
5111
  refs.push({ harness: this.harness, sessionId: id, path, cwd, mtimeMs: st.mtimeMs });
4263
5112
  }
4264
5113
  }
@@ -4297,14 +5146,14 @@ var PiAdapter = class {
4297
5146
  const llmId = `llm:${mid}`;
4298
5147
  if (msg.role === "toolResult") {
4299
5148
  const callId = msg.toolCallId ?? `${mid}:result`;
4300
- const errorMessage = textOf8(msg.content).slice(0, 500) || "tool result reported error";
5149
+ const errorMessage2 = textOf8(msg.content).slice(0, 500) || "tool result reported error";
4301
5150
  const result = {
4302
5151
  callId,
4303
5152
  toolName: msg.toolName ?? "tool",
4304
5153
  timestamp: ts,
4305
5154
  isError: msg.isError === true,
4306
5155
  output: toolResultOutput(msg.content),
4307
- errorMessage,
5156
+ errorMessage: errorMessage2,
4308
5157
  step
4309
5158
  };
4310
5159
  const toolSpan = toolByCallId.get(callId);
@@ -4444,9 +5293,9 @@ var PiAdapter = class {
4444
5293
  };
4445
5294
 
4446
5295
  // src/adapters/qwen.ts
4447
- import { readdir as readdir12, stat as stat10 } from "fs/promises";
5296
+ import { readdir as readdir12, stat as stat11 } from "fs/promises";
4448
5297
  import { homedir as homedir11 } from "os";
4449
- import { basename as basename9, join as join11 } from "path";
5298
+ import { basename as basename11, join as join14 } from "path";
4450
5299
  var SERVICE10 = "qwen";
4451
5300
  function textOf9(parts) {
4452
5301
  if (!parts) return "";
@@ -4456,7 +5305,7 @@ var QwenAdapter = class {
4456
5305
  harness = "qwen";
4457
5306
  aliases = ["qwen-code"];
4458
5307
  root() {
4459
- return join11(homedir11(), ".qwen", "projects");
5308
+ return join14(homedir11(), ".qwen", "projects");
4460
5309
  }
4461
5310
  async locate(opts = {}) {
4462
5311
  const root = this.root();
@@ -4469,7 +5318,7 @@ var QwenAdapter = class {
4469
5318
  }
4470
5319
  const refs = [];
4471
5320
  for (const pd of projectDirs) {
4472
- const chatsDir = join11(root, pd, "chats");
5321
+ const chatsDir = join14(root, pd, "chats");
4473
5322
  let files;
4474
5323
  try {
4475
5324
  files = await readdir12(chatsDir);
@@ -4480,16 +5329,16 @@ var QwenAdapter = class {
4480
5329
  if (opts.cwd) continue;
4481
5330
  for (const f of files) {
4482
5331
  if (!f.endsWith(".jsonl")) continue;
4483
- const path = join11(chatsDir, f);
5332
+ const path = join14(chatsDir, f);
4484
5333
  let st;
4485
5334
  try {
4486
- st = await stat10(path);
5335
+ st = await stat11(path);
4487
5336
  } catch (error) {
4488
5337
  if (isMissingPathError(error)) continue;
4489
5338
  throw error;
4490
5339
  }
4491
5340
  if (opts.sinceMs && st.mtimeMs < opts.sinceMs) continue;
4492
- refs.push({ harness: this.harness, sessionId: basename9(f, ".jsonl"), path, cwd: null, mtimeMs: st.mtimeMs });
5341
+ refs.push({ harness: this.harness, sessionId: basename11(f, ".jsonl"), path, cwd: null, mtimeMs: st.mtimeMs });
4493
5342
  }
4494
5343
  }
4495
5344
  return refs.sort((a, b) => b.mtimeMs - a.mtimeMs);
@@ -4646,8 +5495,8 @@ function selectAdapters(opts) {
4646
5495
  }
4647
5496
 
4648
5497
  // src/repo.ts
4649
- import { stat as stat11 } from "fs/promises";
4650
- import { dirname as dirname3, isAbsolute as isAbsolute3, join as join12, normalize, parse as parsePath } from "path";
5498
+ import { stat as stat12 } from "fs/promises";
5499
+ import { dirname as dirname5, isAbsolute as isAbsolute4, join as join15, normalize, parse as parsePath } from "path";
4651
5500
  function normalizeRemote(url) {
4652
5501
  const raw = url.trim();
4653
5502
  if (!raw) return null;
@@ -4671,7 +5520,7 @@ function normalizeRemote(url) {
4671
5520
  return null;
4672
5521
  }
4673
5522
  async function readGit(cwd) {
4674
- await stat11(`${cwd}/.git`);
5523
+ await stat12(`${cwd}/.git`);
4675
5524
  const { execFile } = await import("child_process");
4676
5525
  const { promisify } = await import("util");
4677
5526
  const run = promisify(execFile);
@@ -4728,7 +5577,7 @@ function parseWorktreePorcelain(output) {
4728
5577
  async function equivalentGitCwds(cwd) {
4729
5578
  if (!cwd) return [];
4730
5579
  const selected = normalize(cwd);
4731
- if (!isAbsolute3(selected)) return [selected];
5580
+ if (!isAbsolute4(selected)) return [selected];
4732
5581
  const top = await gitOutput(selected, ["rev-parse", "--show-toplevel"]);
4733
5582
  if (!top) return [selected];
4734
5583
  const worktrees = await gitOutput(top, ["worktree", "list", "--porcelain"]);
@@ -4744,7 +5593,7 @@ function cwdMatchesSelection(cwd, selections) {
4744
5593
  }
4745
5594
  async function pathStat(path) {
4746
5595
  try {
4747
- return await stat11(path);
5596
+ return await stat12(path);
4748
5597
  } catch {
4749
5598
  return null;
4750
5599
  }
@@ -4754,13 +5603,13 @@ async function directoryExists(path) {
4754
5603
  return Boolean(s?.isDirectory());
4755
5604
  }
4756
5605
  async function nearestExistingDir(path) {
4757
- if (!path || !isAbsolute3(path)) return null;
5606
+ if (!path || !isAbsolute4(path)) return null;
4758
5607
  let cur = normalize(path);
4759
5608
  for (; ; ) {
4760
5609
  const s = await pathStat(cur);
4761
5610
  if (s?.isDirectory()) return cur;
4762
- if (s?.isFile()) return dirname3(cur);
4763
- const parent = dirname3(cur);
5611
+ if (s?.isFile()) return dirname5(cur);
5612
+ const parent = dirname5(cur);
4764
5613
  if (parent === cur) return null;
4765
5614
  cur = parent;
4766
5615
  }
@@ -4768,15 +5617,15 @@ async function nearestExistingDir(path) {
4768
5617
  async function findGitRoot(path) {
4769
5618
  let cur = await nearestExistingDir(path);
4770
5619
  while (cur) {
4771
- if (await pathStat(join12(cur, ".git"))) return cur;
4772
- const parent = dirname3(cur);
5620
+ if (await pathStat(join15(cur, ".git"))) return cur;
5621
+ const parent = dirname5(cur);
4773
5622
  if (parent === cur) return null;
4774
5623
  cur = parent;
4775
5624
  }
4776
5625
  return null;
4777
5626
  }
4778
5627
  async function repairDashedPath(cwd) {
4779
- if (!isAbsolute3(cwd) || await directoryExists(cwd)) return null;
5628
+ if (!isAbsolute4(cwd) || await directoryExists(cwd)) return null;
4780
5629
  const normalized = normalize(cwd);
4781
5630
  const parsed = parsePath(normalized);
4782
5631
  const parts = normalized.slice(parsed.root.length).split("/").filter(Boolean);
@@ -4786,7 +5635,7 @@ async function repairDashedPath(cwd) {
4786
5635
  while (index < parts.length) {
4787
5636
  const nextPart = parts[index];
4788
5637
  if (!nextPart) break;
4789
- const exact = join12(current, nextPart);
5638
+ const exact = join15(current, nextPart);
4790
5639
  if (!await directoryExists(exact)) break;
4791
5640
  current = exact;
4792
5641
  index += 1;
@@ -4796,7 +5645,7 @@ async function repairDashedPath(cwd) {
4796
5645
  let consumed = 0;
4797
5646
  for (let n = parts.length - index; n >= 1; n -= 1) {
4798
5647
  const segment = parts.slice(index, index + n).join("-");
4799
- const candidate = join12(current, segment);
5648
+ const candidate = join15(current, segment);
4800
5649
  if (await directoryExists(candidate)) {
4801
5650
  match = candidate;
4802
5651
  consumed = n;
@@ -4822,7 +5671,7 @@ var SOURCE_WEIGHT = {
4822
5671
  function cleanPathCandidate(raw) {
4823
5672
  let value = raw.trim().replace(/\\n/g, "").replace(/[),\].}]+$/g, "").replace(/:\d+(?::\d+)?$/g, "");
4824
5673
  value = normalize(value);
4825
- return isAbsolute3(value) ? value : null;
5674
+ return isAbsolute4(value) ? value : null;
4826
5675
  }
4827
5676
  function looksLikeWorkdirKey(key) {
4828
5677
  return key === "cwd" || key === "workdir" || key === "workingDirectory" || key === "working_directory";
@@ -4880,7 +5729,7 @@ function extractAbsolutePaths(spans) {
4880
5729
  async function resolveRepoAttrs(cwd) {
4881
5730
  if (!cwd) return {};
4882
5731
  const attrs = { [ATTR.CWD]: cwd };
4883
- const basename12 = (() => {
5732
+ const basename14 = (() => {
4884
5733
  const trimmed = cwd.replace(/\/+$/g, "");
4885
5734
  const idx = trimmed.lastIndexOf("/");
4886
5735
  const name = idx === -1 ? trimmed : trimmed.slice(idx + 1);
@@ -4902,7 +5751,7 @@ async function resolveRepoAttrs(cwd) {
4902
5751
  if (commit) attrs[ATTR.GIT_COMMIT] = commit;
4903
5752
  } catch {
4904
5753
  }
4905
- attrs[ATTR.SUBJECT_KEY] = basename12;
5754
+ attrs[ATTR.SUBJECT_KEY] = basename14;
4906
5755
  return attrs;
4907
5756
  }
4908
5757
  async function repoCandidateForPath(path) {
@@ -5007,7 +5856,7 @@ async function stampSpanWorkdirRepoAttrs(spans) {
5007
5856
  async function awaitWithAbort(operation, signal) {
5008
5857
  if (!signal) return operation;
5009
5858
  signal.throwIfAborted();
5010
- return new Promise((resolve5, reject) => {
5859
+ return new Promise((resolve7, reject) => {
5011
5860
  const stop = () => {
5012
5861
  signal.removeEventListener("abort", stop);
5013
5862
  reject(signal.reason);
@@ -5016,7 +5865,7 @@ async function awaitWithAbort(operation, signal) {
5016
5865
  operation.then(
5017
5866
  (value) => {
5018
5867
  signal.removeEventListener("abort", stop);
5019
- resolve5(value);
5868
+ resolve7(value);
5020
5869
  },
5021
5870
  (error) => {
5022
5871
  signal.removeEventListener("abort", stop);
@@ -5189,9 +6038,9 @@ function describeSessionRelationship(ref, spans) {
5189
6038
  }
5190
6039
 
5191
6040
  // src/evidence.ts
5192
- import { mkdtemp, writeFile } from "fs/promises";
6041
+ import { mkdtemp as mkdtemp2, writeFile as writeFile2 } from "fs/promises";
5193
6042
  import { tmpdir } from "os";
5194
- import { join as join13 } from "path";
6043
+ import { join as join16 } from "path";
5195
6044
  import {
5196
6045
  OPENINFERENCE_SPAN_KIND as OPENINFERENCE_SPAN_KIND2,
5197
6046
  TOOL_NAME as TOOL_NAME2
@@ -5317,14 +6166,14 @@ function serializePolicyEvidence(records) {
5317
6166
  `;
5318
6167
  }
5319
6168
  async function writePolicyEvidenceFile(records, outPath) {
5320
- const path = outPath ?? join13(await mkdtemp(join13(tmpdir(), "traces-evidence-")), "policy-evidence.jsonl");
5321
- await writeFile(path, serializePolicyEvidence(records), "utf8");
6169
+ const path = outPath ?? join16(await mkdtemp2(join16(tmpdir(), "traces-evidence-")), "policy-evidence.jsonl");
6170
+ await writeFile2(path, serializePolicyEvidence(records), "utf8");
5322
6171
  return path;
5323
6172
  }
5324
6173
 
5325
6174
  // src/external.ts
5326
6175
  import { spawn } from "child_process";
5327
- import { readdir as readdir13, readFile as readFile2 } from "fs/promises";
6176
+ import { readdir as readdir13, readFile as readFile5 } from "fs/promises";
5328
6177
 
5329
6178
  // src/external-analysis-validation.ts
5330
6179
  var FINDING_KEYS = /* @__PURE__ */ new Set([
@@ -5600,13 +6449,13 @@ function terminateWindowsProcessTree(child) {
5600
6449
  forceKill(child);
5601
6450
  return Promise.resolve();
5602
6451
  }
5603
- return new Promise((resolve5) => {
6452
+ return new Promise((resolve7) => {
5604
6453
  let finished = false;
5605
6454
  const finish = () => {
5606
6455
  if (finished) return;
5607
6456
  finished = true;
5608
6457
  forceKill(child);
5609
- resolve5();
6458
+ resolve7();
5610
6459
  };
5611
6460
  let killer;
5612
6461
  try {
@@ -5633,7 +6482,7 @@ function signalProcess(pid, signal) {
5633
6482
  }
5634
6483
  }
5635
6484
  function readProcessTableWithPs() {
5636
- return new Promise((resolve5, reject) => {
6485
+ return new Promise((resolve7, reject) => {
5637
6486
  let child;
5638
6487
  try {
5639
6488
  child = spawn("ps", ["-A", "-o", "pid=", "-o", "ppid="], {
@@ -5687,7 +6536,7 @@ function readProcessTableWithPs() {
5687
6536
  reject(new Error("ps: returned no process records"));
5688
6537
  return;
5689
6538
  }
5690
- resolve5(rows);
6539
+ resolve7(rows);
5691
6540
  });
5692
6541
  });
5693
6542
  });
@@ -5697,10 +6546,10 @@ async function readLinuxProcProcessTable() {
5697
6546
  const rows = await Promise.all(
5698
6547
  entries.filter((entry) => entry.isDirectory() && /^\d+$/.test(entry.name)).map(async (entry) => {
5699
6548
  try {
5700
- const stat13 = await readFile2(`/proc/${entry.name}/stat`, "utf8");
5701
- const commandEnd = stat13.lastIndexOf(")");
6549
+ const stat14 = await readFile5(`/proc/${entry.name}/stat`, "utf8");
6550
+ const commandEnd = stat14.lastIndexOf(")");
5702
6551
  if (commandEnd < 0) return void 0;
5703
- const fields = stat13.slice(commandEnd + 1).trim().split(/\s+/);
6552
+ const fields = stat14.slice(commandEnd + 1).trim().split(/\s+/);
5704
6553
  const pid = Number(entry.name);
5705
6554
  const parentPid = Number(fields[1]);
5706
6555
  if (!Number.isSafeInteger(pid) || pid < 1 || !Number.isSafeInteger(parentPid) || parentPid < 0) {
@@ -5822,7 +6671,7 @@ function runCommand(command, args = [], opts = {}) {
5822
6671
  throw new RangeError("maxBuffer must be a positive safe integer");
5823
6672
  }
5824
6673
  if (opts.signal?.aborted) return Promise.reject(abortError(opts.signal));
5825
- return new Promise((resolve5, reject) => {
6674
+ return new Promise((resolve7, reject) => {
5826
6675
  let child;
5827
6676
  try {
5828
6677
  child = spawn(command, [...args], { detached: process.platform !== "win32" });
@@ -5854,7 +6703,7 @@ function runCommand(command, args = [], opts = {}) {
5854
6703
  } else if (spawnError) {
5855
6704
  reject(spawnError);
5856
6705
  } else {
5857
- resolve5({ stdout: out, stderr: err, code: closeCode });
6706
+ resolve7({ stdout: out, stderr: err, code: closeCode });
5858
6707
  }
5859
6708
  };
5860
6709
  function requestTermination(error) {
@@ -6083,22 +6932,22 @@ function commandRedactor(spec) {
6083
6932
  }
6084
6933
 
6085
6934
  // src/hodoscope.ts
6086
- import { createHash as createHash5 } from "crypto";
6087
- import { mkdir, mkdtemp as mkdtemp2, readFile as readFile3, readdir as readdir14, writeFile as writeFile2 } from "fs/promises";
6935
+ import { createHash as createHash7 } from "crypto";
6936
+ import { mkdir as mkdir3, mkdtemp as mkdtemp3, readFile as readFile6, readdir as readdir14, writeFile as writeFile3 } from "fs/promises";
6088
6937
  import { endianness, tmpdir as tmpdir2 } from "os";
6089
- import { join as join14, resolve as resolve3 } from "path";
6938
+ import { join as join17, resolve as resolve5 } from "path";
6090
6939
  var HODOSCOPE_VERSION = "0.2.4";
6091
6940
  async function writeHodoscopeInput(otlpPath, options = {}) {
6092
- const explicitDirectory = options.directory ? resolve3(options.directory) : void 0;
6093
- const directory = explicitDirectory ?? await mkdtemp2(join14(tmpdir2(), "traces-hodoscope-input-"));
6941
+ const explicitDirectory = options.directory ? resolve5(options.directory) : void 0;
6942
+ const directory = explicitDirectory ?? await mkdtemp3(join17(tmpdir2(), "traces-hodoscope-input-"));
6094
6943
  if (explicitDirectory) {
6095
- await mkdir(directory, { recursive: true });
6944
+ await mkdir3(directory, { recursive: true });
6096
6945
  if ((await readdir14(directory)).length > 0) {
6097
6946
  throw new Error(`Hodoscope explicit directory must be empty: ${directory}`);
6098
6947
  }
6099
6948
  }
6100
- const samples = join14(directory, "samples");
6101
- await mkdir(samples);
6949
+ const samples = join17(directory, "samples");
6950
+ await mkdir3(samples);
6102
6951
  const rows = [];
6103
6952
  for await (const value of readJsonl(otlpPath)) rows.push(parseOpenInferenceRow(value));
6104
6953
  if (rows.length === 0) throw new Error("Hodoscope input contains no spans");
@@ -6122,8 +6971,8 @@ async function writeHodoscopeInput(otlpPath, options = {}) {
6122
6971
  throw new Error(`Hodoscope trace '${traceId}' contains no assistant actions`);
6123
6972
  }
6124
6973
  actionCount += actions;
6125
- const file = `${createHash5("sha256").update(traceId).digest("hex").slice(0, 24)}.json`;
6126
- await writeFile2(join14(samples, file), `${JSON.stringify(trajectory, null, 2)}
6974
+ const file = `${createHash7("sha256").update(traceId).digest("hex").slice(0, 24)}.json`;
6975
+ await writeFile3(join17(samples, file), `${JSON.stringify(trajectory, null, 2)}
6127
6976
  `, "utf8");
6128
6977
  }
6129
6978
  return {
@@ -6145,12 +6994,12 @@ function hodoscopeAnalyzer(options = {}) {
6145
6994
  return {
6146
6995
  name: "hodoscope",
6147
6996
  async analyze(otlpPath, runOptions2 = {}) {
6148
- const outputRoot = options.outputDir ? resolve3(options.outputDir) : tmpdir2();
6149
- await mkdir(outputRoot, { recursive: true });
6150
- const directory = await mkdtemp2(join14(outputRoot, "traces-hodoscope-"));
6151
- const input = join14(directory, "input");
6152
- const analysisFile = join14(directory, "analysis.hodoscope.json");
6153
- const samplesFile = join14(directory, "samples.json");
6997
+ const outputRoot = options.outputDir ? resolve5(options.outputDir) : tmpdir2();
6998
+ await mkdir3(outputRoot, { recursive: true });
6999
+ const directory = await mkdtemp3(join17(outputRoot, "traces-hodoscope-"));
7000
+ const input = join17(directory, "input");
7001
+ const analysisFile = join17(directory, "analysis.hodoscope.json");
7002
+ const samplesFile = join17(directory, "samples.json");
6154
7003
  try {
6155
7004
  const prepared = await writeHodoscopeInput(otlpPath, {
6156
7005
  directory: input,
@@ -6341,20 +7190,20 @@ function sourceMapEntry(traceId, spanId, turnId) {
6341
7190
  }
6342
7191
  async function readHodoscopeAnalysis(path, expected) {
6343
7192
  const value = await readJson(path);
6344
- if (!isObject(value) || value.version !== 1 || !Array.isArray(value.summaries)) {
7193
+ if (!isObject3(value) || value.version !== 1 || !Array.isArray(value.summaries)) {
6345
7194
  throw new Error("Hodoscope analysis has an unsupported shape");
6346
7195
  }
6347
- const createdAt = requiredString(value.created_at, "analysis.created_at");
7196
+ const createdAt = requiredString2(value.created_at, "analysis.created_at");
6348
7197
  if (!Number.isFinite(Date.parse(createdAt))) {
6349
7198
  throw new Error("Hodoscope analysis.created_at must be a valid date-time");
6350
7199
  }
6351
- const source = requiredString(value.source, "analysis.source");
6352
- if (resolve3(source) !== resolve3(expected.source)) {
7200
+ const source = requiredString2(value.source, "analysis.source");
7201
+ if (resolve5(source) !== resolve5(expected.source)) {
6353
7202
  throw new Error(
6354
7203
  `Hodoscope analysis.source '${source}' does not match requested input '${expected.source}'`
6355
7204
  );
6356
7205
  }
6357
- const embeddingModel = requiredString(value.embedding_model, "analysis.embedding_model");
7206
+ const embeddingModel = requiredString2(value.embedding_model, "analysis.embedding_model");
6358
7207
  if (embeddingModel !== expected.embeddingModel) {
6359
7208
  throw new Error(
6360
7209
  `Hodoscope analysis.embedding_model '${embeddingModel}' does not match requested model '${expected.embeddingModel}'`
@@ -6411,15 +7260,15 @@ async function readHodoscopeAnalysis(path, expected) {
6411
7260
  }
6412
7261
  function parseHodoscopeSummary(value, index, embeddingDimensions) {
6413
7262
  const path = `analysis.summaries[${index}]`;
6414
- if (!isObject(value)) throw new Error(`Hodoscope ${path} must be an object`);
6415
- const trajectoryId2 = requiredString(value.trajectory_id, `${path}.trajectory_id`);
7263
+ if (!isObject3(value)) throw new Error(`Hodoscope ${path} must be an object`);
7264
+ const trajectoryId2 = requiredString2(value.trajectory_id, `${path}.trajectory_id`);
6416
7265
  const turnId = nonNegativeSafeInteger(value.turn_id, `${path}.turn_id`);
6417
- const summary = requiredString(value.summary, `${path}.summary`);
7266
+ const summary = requiredString2(value.summary, `${path}.summary`);
6418
7267
  if (summary.trimStart().toLowerCase().startsWith("[error:")) {
6419
7268
  throw new Error(`Hodoscope failed to summarize ${formatAction(trajectoryId2, turnId)}`);
6420
7269
  }
6421
- const actionText = requiredString(value.action_text, `${path}.action_text`);
6422
- const embedding = requiredString(value.embedding, `${path}.embedding`);
7270
+ const actionText = requiredString2(value.action_text, `${path}.action_text`);
7271
+ const embedding = requiredString2(value.embedding, `${path}.embedding`);
6423
7272
  validateEmbedding(embedding, embeddingDimensions, `${path}.embedding`);
6424
7273
  const taskContext = value.task_context;
6425
7274
  if (typeof taskContext !== "string") {
@@ -6436,16 +7285,16 @@ function parseHodoscopeSummary(value, index, embeddingDimensions) {
6436
7285
  };
6437
7286
  }
6438
7287
  function parseHodoscopeSamples(value, expected) {
6439
- if (!isObject(value) || !isObject(value.groups)) {
7288
+ if (!isObject3(value) || !isObject3(value.groups)) {
6440
7289
  throw new Error("Hodoscope samples have an unsupported shape");
6441
7290
  }
6442
- const groupBy = requiredString(value.group_by, "samples.group_by");
7291
+ const groupBy = requiredString2(value.group_by, "samples.group_by");
6443
7292
  if (groupBy !== expected.groupBy) {
6444
7293
  throw new Error(
6445
7294
  `Hodoscope samples.group_by '${groupBy}' does not match requested '${expected.groupBy}'`
6446
7295
  );
6447
7296
  }
6448
- const method = requiredString(value.method, "samples.method");
7297
+ const method = requiredString2(value.method, "samples.method");
6449
7298
  if (method !== expected.method) {
6450
7299
  throw new Error(
6451
7300
  `Hodoscope samples.method '${method}' does not match requested '${expected.method}'`
@@ -6465,7 +7314,7 @@ function parseHodoscopeSamples(value, expected) {
6465
7314
  );
6466
7315
  const expectedGroupTotals = /* @__PURE__ */ new Map();
6467
7316
  for (const [index, summary] of expected.summaries.entries()) {
6468
- const group = requiredString(
7317
+ const group = requiredString2(
6469
7318
  summary.metadata[groupBy],
6470
7319
  `analysis.summaries[${index}].metadata.${groupBy}`
6471
7320
  );
@@ -6477,7 +7326,7 @@ function parseHodoscopeSamples(value, expected) {
6477
7326
  let reportedSamples = 0;
6478
7327
  for (const [group, groupValue] of Object.entries(value.groups)) {
6479
7328
  if (!group.trim()) throw new Error("Hodoscope sample group names must be non-empty");
6480
- if (!isObject(groupValue) || !Array.isArray(groupValue.samples)) {
7329
+ if (!isObject3(groupValue) || !Array.isArray(groupValue.samples)) {
6481
7330
  throw new Error(`Hodoscope sample group '${group}' has an unsupported shape`);
6482
7331
  }
6483
7332
  const total = nonNegativeSafeInteger(groupValue.total, `samples.groups.${group}.total`);
@@ -6498,12 +7347,12 @@ function parseHodoscopeSamples(value, expected) {
6498
7347
  }
6499
7348
  const parsedSamples = groupValue.samples.map((row, index) => {
6500
7349
  const path = `samples.groups.${group}.samples[${index}]`;
6501
- if (!isObject(row)) throw new Error(`Hodoscope ${path} must be an object`);
7350
+ if (!isObject3(row)) throw new Error(`Hodoscope ${path} must be an object`);
6502
7351
  const rank = nonNegativeSafeInteger(row.rank, `${path}.rank`);
6503
7352
  if (rank !== index) {
6504
7353
  throw new Error(`Hodoscope ${path}.rank must be ${index}, received ${rank}`);
6505
7354
  }
6506
- const trajectoryId2 = requiredString(row.trajectory_id, `${path}.trajectory_id`);
7355
+ const trajectoryId2 = requiredString2(row.trajectory_id, `${path}.trajectory_id`);
6507
7356
  const turnId = nonNegativeSafeInteger(row.turn_id, `${path}.turn_id`);
6508
7357
  const key = actionKey(trajectoryId2, turnId);
6509
7358
  if (!expected.sourceByAction.has(key)) {
@@ -6522,8 +7371,8 @@ function parseHodoscopeSamples(value, expected) {
6522
7371
  `Hodoscope ${path} has no matching analysis row for ${formatAction(trajectoryId2, turnId)}`
6523
7372
  );
6524
7373
  }
6525
- const summary = requiredString(row.summary, `${path}.summary`);
6526
- const actionText = requiredString(row.action_text, `${path}.action_text`);
7374
+ const summary = requiredString2(row.summary, `${path}.summary`);
7375
+ const actionText = requiredString2(row.action_text, `${path}.action_text`);
6527
7376
  const metadata = jsonRecord(row.metadata, `${path}.metadata`);
6528
7377
  if (summary !== sourceSummary.summary || actionText !== sourceSummary.action_text) {
6529
7378
  throw new Error(
@@ -6577,7 +7426,7 @@ function parseHodoscopeSamples(value, expected) {
6577
7426
  function candidatesFromSamples(samples, sourceByAction) {
6578
7427
  const candidates = [];
6579
7428
  for (const [group, value] of Object.entries(samples.groups)) {
6580
- if (!isObject(value) || !Array.isArray(value.samples) || !Number.isInteger(value.total)) {
7429
+ if (!isObject3(value) || !Array.isArray(value.samples) || !Number.isInteger(value.total)) {
6581
7430
  throw new Error(`Hodoscope sample group '${group}' has an unsupported shape`);
6582
7431
  }
6583
7432
  for (const row of value.samples) {
@@ -6663,7 +7512,7 @@ function validateEmbedding(encoded, dimensions, path) {
6663
7512
  }
6664
7513
  }
6665
7514
  }
6666
- function requiredString(value, path) {
7515
+ function requiredString2(value, path) {
6667
7516
  if (typeof value !== "string" || value.trim().length === 0) {
6668
7517
  throw new Error(`Hodoscope ${path} must be a non-empty string`);
6669
7518
  }
@@ -6676,7 +7525,7 @@ function nonNegativeSafeInteger(value, path) {
6676
7525
  return value;
6677
7526
  }
6678
7527
  function jsonRecord(value, path) {
6679
- if (!isObject(value)) throw new Error(`Hodoscope ${path} must be a JSON object`);
7528
+ if (!isObject3(value)) throw new Error(`Hodoscope ${path} must be a JSON object`);
6680
7529
  assertJsonValue(value, path);
6681
7530
  return value;
6682
7531
  }
@@ -6691,7 +7540,7 @@ function assertJsonValue(value, path, depth = 0) {
6691
7540
  }
6692
7541
  return;
6693
7542
  }
6694
- if (isObject(value)) {
7543
+ if (isObject3(value)) {
6695
7544
  for (const [key, child] of Object.entries(value)) {
6696
7545
  assertJsonValue(child, `${path}.${key}`, depth + 1);
6697
7546
  }
@@ -6705,8 +7554,8 @@ function jsonEquals(left, right) {
6705
7554
  if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) return false;
6706
7555
  return left.every((value, index) => jsonEquals(value, right[index]));
6707
7556
  }
6708
- if (isObject(left) || isObject(right)) {
6709
- if (!isObject(left) || !isObject(right)) return false;
7557
+ if (isObject3(left) || isObject3(right)) {
7558
+ if (!isObject3(left) || !isObject3(right)) return false;
6710
7559
  const leftKeys = Object.keys(left).sort();
6711
7560
  const rightKeys = Object.keys(right).sort();
6712
7561
  return leftKeys.length === rightKeys.length && leftKeys.every(
@@ -6716,10 +7565,10 @@ function jsonEquals(left, right) {
6716
7565
  return false;
6717
7566
  }
6718
7567
  async function readJson(path) {
6719
- return JSON.parse(await readFile3(path, "utf8"));
7568
+ return JSON.parse(await readFile6(path, "utf8"));
6720
7569
  }
6721
7570
  function parseOpenInferenceRow(value) {
6722
- if (!isObject(value) || typeof value.trace_id !== "string" || !value.trace_id || typeof value.span_id !== "string" || !value.span_id || typeof value.name !== "string" || typeof value.start_time !== "string" || !isObject(value.status) || !isObject(value.attributes) || value.parent_span_id !== void 0 && value.parent_span_id !== null && typeof value.parent_span_id !== "string") {
7571
+ if (!isObject3(value) || typeof value.trace_id !== "string" || !value.trace_id || typeof value.span_id !== "string" || !value.span_id || typeof value.name !== "string" || typeof value.start_time !== "string" || !isObject3(value.status) || !isObject3(value.attributes) || value.parent_span_id !== void 0 && value.parent_span_id !== null && typeof value.parent_span_id !== "string") {
6723
7572
  throw new TypeError("Hodoscope input must contain complete OpenInference spans");
6724
7573
  }
6725
7574
  return value;
@@ -6752,7 +7601,7 @@ function toJson(value) {
6752
7601
  if (value === null || typeof value === "string" || typeof value === "boolean") return value;
6753
7602
  if (typeof value === "number") return Number.isFinite(value) ? value : String(value);
6754
7603
  if (Array.isArray(value)) return value.map(toJson);
6755
- if (isObject(value)) {
7604
+ if (isObject3(value)) {
6756
7605
  return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJson(child)]));
6757
7606
  }
6758
7607
  return String(value ?? "");
@@ -6760,7 +7609,7 @@ function toJson(value) {
6760
7609
  function stringifyCompact(value) {
6761
7610
  return typeof value === "string" ? value : JSON.stringify(value);
6762
7611
  }
6763
- function isObject(value) {
7612
+ function isObject3(value) {
6764
7613
  return value !== null && typeof value === "object" && !Array.isArray(value);
6765
7614
  }
6766
7615
  function assertPositiveInteger(name, value) {
@@ -6769,159 +7618,6 @@ function assertPositiveInteger(name, value) {
6769
7618
  }
6770
7619
  }
6771
7620
 
6772
- // src/chat-trajectory.ts
6773
- import { createHash as createHash6 } from "crypto";
6774
- function isChatTrajectoryMessage(value) {
6775
- return isObject2(value) && typeof value.role === "string" && typeof value.content === "string";
6776
- }
6777
- function isChatTrajectory(value) {
6778
- return isObject2(value) && Array.isArray(value.messages) && value.messages.length > 0 && value.messages.every(isChatTrajectoryMessage);
6779
- }
6780
- function chatTrajectoryToSpans(input, options = {}) {
6781
- const trajectory = Array.isArray(input) ? { messages: input } : input;
6782
- if (trajectory.messages.length === 0) throw new Error("chat trajectory contains no messages");
6783
- if (!trajectory.messages.every(isChatTrajectoryMessage)) {
6784
- throw new TypeError("chat trajectory messages require string role and content fields");
6785
- }
6786
- const traceId = options.traceId ?? trajectoryId(trajectory);
6787
- const service = options.service ?? trajectory.trajectory_format ?? "chat-trajectory";
6788
- const stepMode = options.stepMode ?? "assistant";
6789
- const times = messageTimes(trajectory.messages);
6790
- const actionCount = trajectory.messages.filter((message) => messageKind(message.role) === "LLM").length;
6791
- const root = span({
6792
- traceId,
6793
- spanId: "root",
6794
- name: "trajectory",
6795
- kind: "AGENT",
6796
- startTime: times[0],
6797
- endTime: times.at(-1),
6798
- service,
6799
- costUsd: finiteNumber(trajectory.info?.model_stats, "instance_cost"),
6800
- extra: compactAttributes({
6801
- "traces.source_format": "chat-trajectory",
6802
- "trajectory.format": trajectory.trajectory_format,
6803
- "trajectory.message_count": trajectory.messages.length,
6804
- "trajectory.action_count": actionCount,
6805
- "trajectory.source_path": options.sourcePath,
6806
- "trajectory.api_calls": finiteNumber(trajectory.info?.model_stats, "api_calls"),
6807
- "trajectory.timestamps_synthetic": trajectory.messages.some(
6808
- (message) => message.timestamp === void 0
6809
- )
6810
- })
6811
- });
6812
- const spans = [root];
6813
- let assistantStep = 0;
6814
- for (const [index, message] of trajectory.messages.entries()) {
6815
- const kind = messageKind(message.role);
6816
- if (kind === "LLM") assistantStep += 1;
6817
- const step = stepMode === "message" ? index + 1 : kind === "LLM" ? assistantStep : void 0;
6818
- const spanId = step === void 0 ? `message-${index + 1}` : `step-${step}`;
6819
- const response = isObject2(message.extra?.response) ? message.extra.response : void 0;
6820
- const usage = isObject2(response?.usage) ? response.usage : void 0;
6821
- const completionDetails = isObject2(usage?.completion_tokens_details) ? usage.completion_tokens_details : void 0;
6822
- const promptDetails = isObject2(usage?.prompt_tokens_details) ? usage.prompt_tokens_details : void 0;
6823
- spans.push(
6824
- span({
6825
- traceId,
6826
- spanId,
6827
- parentSpanId: "root",
6828
- name: messageName(kind, message),
6829
- kind,
6830
- startTime: times[index],
6831
- service,
6832
- agent: messageAgent(message.role),
6833
- model: stringValue2(response?.model),
6834
- inputTokens: finiteNumber(usage, "prompt_tokens"),
6835
- outputTokens: finiteNumber(usage, "completion_tokens"),
6836
- reasoningTokens: finiteNumber(completionDetails, "reasoning_tokens"),
6837
- cachedInputTokens: finiteNumber(promptDetails, "cached_tokens"),
6838
- step,
6839
- content: capText(message.content),
6840
- extra: compactAttributes({
6841
- "traces.source_format": "chat-trajectory",
6842
- "trajectory.message_index": index + 1,
6843
- "trajectory.action_index": kind === "LLM" ? assistantStep : void 0,
6844
- "trajectory.role": message.role
6845
- })
6846
- })
6847
- );
6848
- }
6849
- return validateOtlpSpans(spans, "chat trajectory output");
6850
- }
6851
- function trajectoryId(trajectory) {
6852
- const value = trajectory.trajectory_id ?? trajectory.traj_id ?? trajectory.instance_id;
6853
- if (typeof value === "string" && value.trim()) return value;
6854
- if (typeof value === "number" && Number.isSafeInteger(value)) return String(value);
6855
- return `trajectory-${createHash6("sha256").update(JSON.stringify(trajectory.messages)).digest("hex").slice(0, 24)}`;
6856
- }
6857
- function messageKind(role) {
6858
- const normalized = role.trim().toLowerCase();
6859
- if (normalized === "assistant" || normalized === "agent") return "LLM";
6860
- if (normalized === "tool" || normalized === "function" || normalized === "observation") {
6861
- return "TOOL";
6862
- }
6863
- return "CHAIN";
6864
- }
6865
- function messageName(kind, message) {
6866
- if (kind === "LLM") return "message.assistant";
6867
- if (kind === "TOOL") return `tool.${message.name?.trim() || "result"}`;
6868
- const role = message.role.trim().toLowerCase();
6869
- if (role === "system") return "system.prompt";
6870
- if (role === "user" || role === "human") return "user.prompt";
6871
- return "message.other";
6872
- }
6873
- function messageAgent(role) {
6874
- const normalized = role.trim().toLowerCase();
6875
- return ["system", "user", "human", "tool", "function", "observation"].includes(normalized) ? void 0 : role.trim();
6876
- }
6877
- function messageTimes(messages) {
6878
- const supplied = messages.filter((message) => message.timestamp !== void 0).length;
6879
- if (supplied === 0) return messages.map((_, index) => new Date(index).toISOString());
6880
- if (supplied !== messages.length) {
6881
- throw new TypeError("chat trajectory timestamps must be present on every message or none");
6882
- }
6883
- const times = messages.map((message, index) => messageTime(message.timestamp, index));
6884
- for (let index = 1; index < times.length; index += 1) {
6885
- if (Date.parse(times[index]) < Date.parse(times[index - 1])) {
6886
- throw new RangeError(
6887
- `chat trajectory message ${index + 1} timestamp precedes message ${index}`
6888
- );
6889
- }
6890
- }
6891
- return times;
6892
- }
6893
- function messageTime(value, index) {
6894
- const parsed = parseTime(value);
6895
- if (!parsed) {
6896
- throw new TypeError(`chat trajectory message ${index + 1} has an invalid timestamp`);
6897
- }
6898
- return parsed;
6899
- }
6900
- function parseTime(value) {
6901
- if (typeof value === "number" && Number.isFinite(value)) {
6902
- const millis2 = value < 1e10 ? value * 1e3 : value;
6903
- const date = new Date(millis2);
6904
- return Number.isFinite(date.getTime()) ? date.toISOString() : void 0;
6905
- }
6906
- if (typeof value !== "string" || !value.trim()) return void 0;
6907
- const millis = Date.parse(value);
6908
- return Number.isFinite(millis) ? new Date(millis).toISOString() : void 0;
6909
- }
6910
- function finiteNumber(value, key) {
6911
- if (!isObject2(value)) return void 0;
6912
- const number = value[key];
6913
- return typeof number === "number" && Number.isFinite(number) ? number : void 0;
6914
- }
6915
- function stringValue2(value) {
6916
- return typeof value === "string" && value.trim() ? value : void 0;
6917
- }
6918
- function compactAttributes(values) {
6919
- return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== void 0));
6920
- }
6921
- function isObject2(value) {
6922
- return value !== null && typeof value === "object" && !Array.isArray(value);
6923
- }
6924
-
6925
7621
  // src/redact.ts
6926
7622
  import { DEFAULT_REDACTION_RULES, redactValue } from "@tangle-network/agent-eval/traces";
6927
7623
  var CODING_REDACTION_RULES = [
@@ -7002,10 +7698,10 @@ async function applyRedactor(spans, redactor) {
7002
7698
  }
7003
7699
 
7004
7700
  // src/file-export.ts
7005
- import { createHash as createHash7 } from "crypto";
7006
- import { mkdtemp as mkdtemp3, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
7701
+ import { createHash as createHash8 } from "crypto";
7702
+ import { mkdtemp as mkdtemp4, readFile as readFile7, writeFile as writeFile4 } from "fs/promises";
7007
7703
  import { tmpdir as tmpdir3 } from "os";
7008
- import { join as join15 } from "path";
7704
+ import { join as join18 } from "path";
7009
7705
  import {
7010
7706
  firstNumberAttr,
7011
7707
  LLM_CACHED_TOKEN_ATTR_KEYS,
@@ -7021,18 +7717,18 @@ import {
7021
7717
  LLM_REASONING_TOKEN_ATTR_KEYS,
7022
7718
  LLM_REASONING_TOKENS
7023
7719
  } from "@tangle-network/agent-eval/trace-attributes";
7024
- function isObject3(value) {
7720
+ function isObject4(value) {
7025
7721
  return value != null && typeof value === "object" && !Array.isArray(value);
7026
7722
  }
7027
7723
  function stringValue3(value) {
7028
7724
  return typeof value === "string" && value.length > 0 ? value : void 0;
7029
7725
  }
7030
7726
  function objectValue2(value) {
7031
- return isObject3(value) ? value : void 0;
7727
+ return isObject4(value) ? value : void 0;
7032
7728
  }
7033
7729
  function stableJson(value) {
7034
7730
  return JSON.stringify(value, (_key, v) => {
7035
- if (!isObject3(v)) return v;
7731
+ if (!isObject4(v)) return v;
7036
7732
  return Object.keys(v).sort().reduce((acc, key) => {
7037
7733
  acc[key] = v[key];
7038
7734
  return acc;
@@ -7040,7 +7736,7 @@ function stableJson(value) {
7040
7736
  });
7041
7737
  }
7042
7738
  function hashId(value, chars = 16) {
7043
- return createHash7("sha256").update(stableJson(value)).digest("hex").slice(0, chars);
7739
+ return createHash8("sha256").update(stableJson(value)).digest("hex").slice(0, chars);
7044
7740
  }
7045
7741
  function isoTime2(value) {
7046
7742
  if (typeof value === "string") {
@@ -7064,7 +7760,7 @@ function firstTime(obj, keys) {
7064
7760
  }
7065
7761
  function firstTimeDeep(value, keys, depth = 5) {
7066
7762
  if (depth < 0) return void 0;
7067
- if (isObject3(value)) {
7763
+ if (isObject4(value)) {
7068
7764
  const direct = firstTime(value, keys);
7069
7765
  if (direct) return direct;
7070
7766
  for (const child of Object.values(value)) {
@@ -7091,7 +7787,7 @@ function parseJsonRows(text2) {
7091
7787
  try {
7092
7788
  const parsed = JSON.parse(trimmed);
7093
7789
  if (Array.isArray(parsed)) return { rows: parsed };
7094
- if (isObject3(parsed)) {
7790
+ if (isObject4(parsed)) {
7095
7791
  const events = parsed.events;
7096
7792
  if (Array.isArray(events)) return { rows: events, wrapper: parsed };
7097
7793
  return { rows: [parsed] };
@@ -7107,21 +7803,21 @@ function parseJsonRows(text2) {
7107
7803
  };
7108
7804
  }
7109
7805
  function isPolicyEvidenceRow(row) {
7110
- return isObject3(row) && row.kind === "traces.policy_evidence.session";
7806
+ return isObject4(row) && row.kind === "traces.policy_evidence.session";
7111
7807
  }
7112
7808
  function isOpenInferenceRow(row) {
7113
- if (!isObject3(row)) return false;
7114
- return typeof row.trace_id === "string" && typeof row.span_id === "string" && (row.parent_span_id === null || typeof row.parent_span_id === "string") && typeof row.name === "string" && typeof row.start_time === "string" && typeof row.end_time === "string" && isObject3(row.status) && isObject3(row.attributes) && isObject3(row.resource) && isObject3(row.scope);
7809
+ if (!isObject4(row)) return false;
7810
+ return typeof row.trace_id === "string" && typeof row.span_id === "string" && (row.parent_span_id === null || typeof row.parent_span_id === "string") && typeof row.name === "string" && typeof row.start_time === "string" && typeof row.end_time === "string" && isObject4(row.status) && isObject4(row.attributes) && isObject4(row.resource) && isObject4(row.scope);
7115
7811
  }
7116
7812
  function isIntelligenceSpanRow(row) {
7117
- if (!isObject3(row)) return false;
7118
- return typeof row.trace_id === "string" && typeof row.name === "string" && isObject3(row.attributes) && (row.start_unix_nano != null || row.start_time != null || row.received_at != null);
7813
+ if (!isObject4(row)) return false;
7814
+ return typeof row.trace_id === "string" && typeof row.name === "string" && isObject4(row.attributes) && (row.start_unix_nano != null || row.start_time != null || row.received_at != null);
7119
7815
  }
7120
7816
  function eventType(row) {
7121
7817
  return stringValue3(row.type) ?? stringValue3(row.event) ?? stringValue3(row.name) ?? stringValue3(row.kind);
7122
7818
  }
7123
7819
  function looksLikeSandboxEvent(row) {
7124
- if (!isObject3(row)) return false;
7820
+ if (!isObject4(row)) return false;
7125
7821
  const type = eventType(row)?.toLowerCase();
7126
7822
  return type === "start" || type === "raw" || type === "result" || type === "done" || type === "error";
7127
7823
  }
@@ -7153,7 +7849,7 @@ function requireIntelligenceSpanRows(rows) {
7153
7849
  return rows;
7154
7850
  }
7155
7851
  function requireObjectRows(rows) {
7156
- if (!rows.every(isObject3)) throw new Error("sandbox-events input must contain only JSON object events");
7852
+ if (!rows.every(isObject4)) throw new Error("sandbox-events input must contain only JSON object events");
7157
7853
  return rows;
7158
7854
  }
7159
7855
  function chatTrajectoryRowsToSpans(rows, sourcePath) {
@@ -7236,7 +7932,7 @@ function policyEvidenceToSpans(records) {
7236
7932
  }
7237
7933
  function findStringKey(value, keys, depth = 4) {
7238
7934
  if (depth < 0) return void 0;
7239
- if (isObject3(value)) {
7935
+ if (isObject4(value)) {
7240
7936
  for (const key of keys) {
7241
7937
  const found = stringValue3(value[key]);
7242
7938
  if (found) return found;
@@ -7289,9 +7985,9 @@ function eventEndTimestamp(row, fallback) {
7289
7985
  }
7290
7986
  function eventStatus(row, type) {
7291
7987
  const lowered = type.toLowerCase();
7292
- const errorMessage = stringValue3(row.error) ?? findStringKey(row, ["error", "errorMessage", "error_message"], 3);
7293
- if (lowered.includes("error") || errorMessage) {
7294
- const message = errorMessage ?? stringValue3(row.message);
7988
+ const errorMessage2 = stringValue3(row.error) ?? findStringKey(row, ["error", "errorMessage", "error_message"], 3);
7989
+ if (lowered.includes("error") || errorMessage2) {
7990
+ const message = errorMessage2 ?? stringValue3(row.message);
7295
7991
  return { status: "ERROR", ...message ? { message: capText(message) } : {} };
7296
7992
  }
7297
7993
  return { status: "OK" };
@@ -7524,7 +8220,7 @@ function intelligenceSpansToSpans(rows) {
7524
8220
  }
7525
8221
  function openInferenceToSpans(rows) {
7526
8222
  return rows.map((row) => {
7527
- const attrs = isObject3(row.attributes) ? { ...row.attributes } : {};
8223
+ const attrs = isObject4(row.attributes) ? { ...row.attributes } : {};
7528
8224
  const resource = objectValue2(row.resource);
7529
8225
  const resourceAttrs = objectValue2(resource?.attributes);
7530
8226
  if (resourceAttrs) copyDefined(attrs, resourceAttrs);
@@ -7637,20 +8333,20 @@ async function exportTraceEvidenceFile(inputPath, opts = {}) {
7637
8333
  redactionsByRule
7638
8334
  };
7639
8335
  }
7640
- const text2 = await readFile4(inputPath, "utf8");
8336
+ const text2 = await readFile7(inputPath, "utf8");
7641
8337
  return exportTraceEvidenceText(text2, { ...opts, sourcePath: inputPath });
7642
8338
  }
7643
8339
  async function writeTraceEvidenceExportFile(inputPath, outPath, opts = {}) {
7644
8340
  const result = await exportTraceEvidenceFile(inputPath, opts);
7645
- const path = outPath ?? join15(await mkdtemp3(join15(tmpdir3(), "traces-export-")), "spans.openinference.jsonl");
7646
- await writeFile3(path, serializeSpans(result.spans), "utf8");
8341
+ const path = outPath ?? join18(await mkdtemp4(join18(tmpdir3(), "traces-export-")), "spans.openinference.jsonl");
8342
+ await writeFile4(path, serializeSpans(result.spans), "utf8");
7647
8343
  return { ...result, path };
7648
8344
  }
7649
8345
 
7650
8346
  // src/inspect.ts
7651
- import { mkdtemp as mkdtemp4, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
8347
+ import { mkdtemp as mkdtemp5, readFile as readFile8, writeFile as writeFile5 } from "fs/promises";
7652
8348
  import { tmpdir as tmpdir4 } from "os";
7653
- import { basename as basename10, join as join16 } from "path";
8349
+ import { basename as basename12, join as join19 } from "path";
7654
8350
  var severityRank = {
7655
8351
  high: 0,
7656
8352
  medium: 1,
@@ -7833,7 +8529,7 @@ function addContextFindings(index, findings) {
7833
8529
  refs: invalidJsonlFiles.slice(0, 5).map((file) => file.path)
7834
8530
  });
7835
8531
  }
7836
- const skillRunFiles = files.filter((file) => basename10(file.path) === "skill-runs.jsonl" && (file.jsonl?.rows ?? 0) > 0).map((file) => {
8532
+ const skillRunFiles = files.filter((file) => basename12(file.path) === "skill-runs.jsonl" && (file.jsonl?.rows ?? 0) > 0).map((file) => {
7837
8533
  const rows = file.jsonl?.rows ?? 0;
7838
8534
  const keys = file.jsonl?.keys ?? {};
7839
8535
  const linkKeyCounts = {
@@ -7934,19 +8630,19 @@ function assertSessionIndex(value) {
7934
8630
  }
7935
8631
  }
7936
8632
  async function readSessionIndexFile(path) {
7937
- const parsed = JSON.parse(await readFile5(path, "utf8"));
8633
+ const parsed = JSON.parse(await readFile8(path, "utf8"));
7938
8634
  assertSessionIndex(parsed);
7939
8635
  return parsed;
7940
8636
  }
7941
8637
  async function writeInspectionReportFile(report, outPath) {
7942
- const path = outPath ?? join16(await mkdtemp4(join16(tmpdir4(), "traces-inspect-")), "inspection-report.md");
7943
- await writeFile4(path, renderInspectionReport(report), "utf8");
8638
+ const path = outPath ?? join19(await mkdtemp5(join19(tmpdir4(), "traces-inspect-")), "inspection-report.md");
8639
+ await writeFile5(path, renderInspectionReport(report), "utf8");
7944
8640
  return path;
7945
8641
  }
7946
8642
 
7947
8643
  // src/adoption.ts
7948
- import { readFile as readFile6 } from "fs/promises";
7949
- import { join as join17 } from "path";
8644
+ import { readFile as readFile9 } from "fs/promises";
8645
+ import { join as join20 } from "path";
7950
8646
  function toolName2(s) {
7951
8647
  const n = s.attributes["tool.name"];
7952
8648
  if (typeof n === "string") return n;
@@ -8066,10 +8762,10 @@ async function readLoopRuns(cwds, sessionIds) {
8066
8762
  seenCwds.add(cwd);
8067
8763
  const firstSourceByRun = /* @__PURE__ */ new Map();
8068
8764
  for (const artifactDir of [".agent", ".evolve"]) {
8069
- const path = join17(cwd, artifactDir, "skill-runs.jsonl");
8765
+ const path = join20(cwd, artifactDir, "skill-runs.jsonl");
8070
8766
  let raw;
8071
8767
  try {
8072
- raw = await readFile6(path, "utf8");
8768
+ raw = await readFile9(path, "utf8");
8073
8769
  } catch {
8074
8770
  continue;
8075
8771
  }
@@ -8881,9 +9577,9 @@ function renderAdoption(ar) {
8881
9577
  }
8882
9578
 
8883
9579
  // src/improvement.ts
8884
- import { access, mkdir as mkdir2, mkdtemp as mkdtemp5, writeFile as writeFile5 } from "fs/promises";
9580
+ import { access, mkdir as mkdir4, mkdtemp as mkdtemp6, writeFile as writeFile6 } from "fs/promises";
8885
9581
  import { tmpdir as tmpdir5 } from "os";
8886
- import { dirname as dirname4, join as join18, resolve as resolve4 } from "path";
9582
+ import { dirname as dirname6, join as join21, resolve as resolve6 } from "path";
8887
9583
  import { pathToFileURL } from "url";
8888
9584
  import {
8889
9585
  AnalystRegistry,
@@ -9227,7 +9923,7 @@ function registryFromConfig(config) {
9227
9923
  async function existingConfigPath(path) {
9228
9924
  const candidates = path ? [path] : ["traces.config.mjs", "traces.config.js", "traces.config.cjs"];
9229
9925
  for (const candidate of candidates) {
9230
- const resolved = resolve4(candidate);
9926
+ const resolved = resolve6(candidate);
9231
9927
  try {
9232
9928
  await access(resolved);
9233
9929
  return resolved;
@@ -9353,29 +10049,29 @@ async function runTraceStoreInvestigation(opts) {
9353
10049
  };
9354
10050
  }
9355
10051
  async function writeTraceImprovementArtifacts(result, outDir) {
9356
- const directory = outDir ? resolve4(outDir) : await mkdtemp5(join18(tmpdir5(), "traces-improvement-"));
9357
- await mkdir2(directory, { recursive: true });
10052
+ const directory = outDir ? resolve6(outDir) : await mkdtemp6(join21(tmpdir5(), "traces-improvement-"));
10053
+ await mkdir4(directory, { recursive: true });
9358
10054
  const paths = {
9359
10055
  directory,
9360
- result: join18(directory, "result.json"),
9361
- evidence: join18(directory, "evidence.jsonl"),
9362
- report: join18(directory, "report.md"),
10056
+ result: join21(directory, "result.json"),
10057
+ evidence: join21(directory, "evidence.jsonl"),
10058
+ report: join21(directory, "report.md"),
9363
10059
  traces: result.otlpPath
9364
10060
  };
9365
10061
  const { report, ...machineResult } = result;
9366
10062
  await Promise.all([
9367
- writeFile5(paths.result, json(machineResult), "utf8"),
9368
- writeFile5(paths.evidence, jsonl(buildEvidenceRows(result.findings)), "utf8"),
9369
- writeFile5(paths.report, report, "utf8")
10063
+ writeFile6(paths.result, json(machineResult), "utf8"),
10064
+ writeFile6(paths.evidence, jsonl(buildEvidenceRows(result.findings)), "utf8"),
10065
+ writeFile6(paths.report, report, "utf8")
9370
10066
  ]);
9371
10067
  return paths;
9372
10068
  }
9373
10069
  async function runTraceImprovement(opts) {
9374
- const directory = opts.outDir ? resolve4(opts.outDir) : await mkdtemp5(join18(tmpdir5(), "traces-improvement-"));
9375
- await mkdir2(directory, { recursive: true });
10070
+ const directory = opts.outDir ? resolve6(opts.outDir) : await mkdtemp6(join21(tmpdir5(), "traces-improvement-"));
10071
+ await mkdir4(directory, { recursive: true });
9376
10072
  const investigation = await runTraceInvestigation({
9377
10073
  ...opts,
9378
- otlpOutPath: opts.otlpOutPath ?? join18(directory, "traces.otlp.jsonl")
10074
+ otlpOutPath: opts.otlpOutPath ?? join21(directory, "traces.otlp.jsonl")
9379
10075
  });
9380
10076
  const result = {
9381
10077
  ...investigation,
@@ -9387,32 +10083,32 @@ async function runTraceImprovement(opts) {
9387
10083
  };
9388
10084
  }
9389
10085
  async function saveReport(path, report) {
9390
- await mkdir2(dirname4(resolve4(path)), { recursive: true });
9391
- await writeFile5(path, report, "utf8");
10086
+ await mkdir4(dirname6(resolve6(path)), { recursive: true });
10087
+ await writeFile6(path, report, "utf8");
9392
10088
  }
9393
10089
 
9394
10090
  // src/live.ts
9395
- import { createHash as createHash8 } from "crypto";
10091
+ import { createHash as createHash9 } from "crypto";
9396
10092
  var VERIFY_RE = /\b(test|tests|vitest|jest|pytest|go test|cargo test|tsc|typecheck|lint|biome|eslint|build|check:invariants|preflight)\b/i;
9397
10093
  var CHANGE_RE = /\b(apply_patch|edit|write|create|delete|rename|replace|update|git apply|sed -i|perl -pi|tee\s|cat\s+>)/i;
9398
10094
  var CLAIM_DONE_RE = /\b(done|fixed|complete|completed|implemented|merged|verified|all green|tests pass|ready|works now)\b/i;
9399
- var sleep = (ms, signal) => new Promise((resolve5) => {
10095
+ var sleep = (ms, signal) => new Promise((resolve7) => {
9400
10096
  if (signal?.aborted) {
9401
- resolve5();
10097
+ resolve7();
9402
10098
  return;
9403
10099
  }
9404
10100
  const onAbort = () => {
9405
10101
  clearTimeout(t);
9406
- resolve5();
10102
+ resolve7();
9407
10103
  };
9408
10104
  const t = setTimeout(() => {
9409
10105
  signal?.removeEventListener("abort", onAbort);
9410
- resolve5();
10106
+ resolve7();
9411
10107
  }, ms);
9412
10108
  signal?.addEventListener("abort", onAbort, { once: true });
9413
10109
  });
9414
10110
  function hash(parts) {
9415
- return createHash8("sha256").update(parts.join("\0")).digest("hex").slice(0, 16);
10111
+ return createHash9("sha256").update(parts.join("\0")).digest("hex").slice(0, 16);
9416
10112
  }
9417
10113
  function asString(value) {
9418
10114
  if (typeof value === "string" && value.trim()) return value;
@@ -10149,11 +10845,11 @@ async function collectSessionWorkflow(adapter, seeds, options = {}) {
10149
10845
  }
10150
10846
 
10151
10847
  // src/session-selection.ts
10152
- import { createHash as createHash9 } from "crypto";
10848
+ import { createHash as createHash10 } from "crypto";
10153
10849
  import { createReadStream as createReadStream2 } from "fs";
10154
10850
  async function fileSha256(path, signal) {
10155
10851
  signal?.throwIfAborted();
10156
- const hash2 = createHash9("sha256");
10852
+ const hash2 = createHash10("sha256");
10157
10853
  try {
10158
10854
  for await (const chunk of createReadStream2(path, { signal })) {
10159
10855
  signal?.throwIfAborted();
@@ -10181,8 +10877,8 @@ async function sourceSnapshot(adapter, ref, signal) {
10181
10877
  signal?.throwIfAborted();
10182
10878
  files.push({ path, sha256: await fileSha256(path, signal) });
10183
10879
  }
10184
- const sha256 = files.length === 1 ? files[0].sha256 : createHash9("sha256").update(JSON.stringify(files)).digest("hex");
10185
- return { sha256, files };
10880
+ const sha2562 = files.length === 1 ? files[0].sha256 : createHash10("sha256").update(JSON.stringify(files)).digest("hex");
10881
+ return { sha256: sha2562, files };
10186
10882
  }
10187
10883
  function summarizeWorkflows(workflows) {
10188
10884
  if (workflows.length === 0) return void 0;
@@ -10276,9 +10972,9 @@ async function collectSessionSelection(groups, options = {}) {
10276
10972
  }
10277
10973
 
10278
10974
  // src/session-index.ts
10279
- import { mkdtemp as mkdtemp6, readdir as readdir15, readFile as readFile7, stat as stat12, writeFile as writeFile6 } from "fs/promises";
10975
+ import { mkdtemp as mkdtemp7, readdir as readdir15, readFile as readFile10, stat as stat13, writeFile as writeFile7 } from "fs/promises";
10280
10976
  import { tmpdir as tmpdir6 } from "os";
10281
- import { dirname as dirname5, join as join19 } from "path";
10977
+ import { dirname as dirname7, join as join22 } from "path";
10282
10978
  function indexRow(record2) {
10283
10979
  return {
10284
10980
  session: record2.session,
@@ -10333,7 +11029,7 @@ function buildSessionIndex(records, opts = {}) {
10333
11029
  }
10334
11030
  async function pathStat2(path) {
10335
11031
  try {
10336
- return await stat12(path);
11032
+ return await stat13(path);
10337
11033
  } catch {
10338
11034
  return null;
10339
11035
  }
@@ -10349,13 +11045,13 @@ async function findContextRoot(cwd) {
10349
11045
  let current = cwd;
10350
11046
  const s = await pathStat2(current);
10351
11047
  if (!s) return null;
10352
- if (!s.isDirectory()) current = dirname5(current);
11048
+ if (!s.isDirectory()) current = dirname7(current);
10353
11049
  for (; ; ) {
10354
- if (await pathStat2(join19(current, ".git")) || await dirExists(join19(current, ".evolve")) || await fileExists(join19(current, "AGENTS.md")) || await fileExists(join19(current, "CLAUDE.md"))) {
11050
+ if (await pathStat2(join22(current, ".git")) || await dirExists(join22(current, ".evolve")) || await fileExists(join22(current, "AGENTS.md")) || await fileExists(join22(current, "CLAUDE.md"))) {
10355
11051
  return current;
10356
11052
  }
10357
- const parent = dirname5(current);
10358
- if (parent === current) return s.isDirectory() ? cwd : dirname5(cwd);
11053
+ const parent = dirname7(current);
11054
+ if (parent === current) return s.isDirectory() ? cwd : dirname7(cwd);
10359
11055
  current = parent;
10360
11056
  }
10361
11057
  }
@@ -10394,7 +11090,7 @@ async function summarizeFile(path, kind) {
10394
11090
  const base = { kind, path, bytes: Number(s.size), mtimeMs: Number(s.mtimeMs) };
10395
11091
  if (!path.endsWith(".md") && !path.endsWith(".jsonl")) return base;
10396
11092
  try {
10397
- const text2 = await readFile7(path, "utf8");
11093
+ const text2 = await readFile10(path, "utf8");
10398
11094
  const lines = countLines(text2);
10399
11095
  const jsonl2 = path.endsWith(".jsonl") ? summarizeJsonl(text2) : void 0;
10400
11096
  return {
@@ -10419,7 +11115,7 @@ async function walkMarkdown(root, kind, maxFiles = 100) {
10419
11115
  }
10420
11116
  for (const entry of entries) {
10421
11117
  if (out.length >= maxFiles) return;
10422
- const path = join19(dir, entry.name);
11118
+ const path = join22(dir, entry.name);
10423
11119
  if (entry.isDirectory()) {
10424
11120
  await walk(path);
10425
11121
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -10434,20 +11130,20 @@ async function walkMarkdown(root, kind, maxFiles = 100) {
10434
11130
  async function collectContextRoot(root) {
10435
11131
  const files = [];
10436
11132
  for (const name of ["AGENTS.md", "CLAUDE.md", "GEMINI.md"]) {
10437
- const summary = await summarizeFile(join19(root, name), "instruction-doc");
11133
+ const summary = await summarizeFile(join22(root, name), "instruction-doc");
10438
11134
  if (summary) files.push(summary);
10439
11135
  }
10440
- const evolve = join19(root, ".evolve");
11136
+ const evolve = join22(root, ".evolve");
10441
11137
  for (const name of ["skill-runs.jsonl", "governor.jsonl", "experiments.jsonl"]) {
10442
- const summary = await summarizeFile(join19(evolve, name), "evolve-jsonl");
11138
+ const summary = await summarizeFile(join22(evolve, name), "evolve-jsonl");
10443
11139
  if (summary) files.push(summary);
10444
11140
  }
10445
11141
  for (const name of ["scorecard.json"]) {
10446
- const summary = await summarizeFile(join19(evolve, name), "evolve-json");
11142
+ const summary = await summarizeFile(join22(evolve, name), "evolve-json");
10447
11143
  if (summary) files.push(summary);
10448
11144
  }
10449
- files.push(...await walkMarkdown(join19(evolve, "reflections"), "reflection"));
10450
- files.push(...await walkMarkdown(join19(evolve, "handoffs"), "handoff"));
11145
+ files.push(...await walkMarkdown(join22(evolve, "reflections"), "reflection"));
11146
+ files.push(...await walkMarkdown(join22(evolve, "handoffs"), "handoff"));
10451
11147
  return { root, files: files.sort((a, b) => a.path.localeCompare(b.path)) };
10452
11148
  }
10453
11149
  async function collectContextIndex(records) {
@@ -10493,19 +11189,19 @@ function serializeSessionIndex(index) {
10493
11189
  `;
10494
11190
  }
10495
11191
  async function writeSessionIndexFile(index, outPath) {
10496
- const path = outPath ?? join19(await mkdtemp6(join19(tmpdir6(), "traces-index-")), "session-index.json");
10497
- await writeFile6(path, serializeSessionIndex(index), "utf8");
11192
+ const path = outPath ?? join22(await mkdtemp7(join22(tmpdir6(), "traces-index-")), "session-index.json");
11193
+ await writeFile7(path, serializeSessionIndex(index), "utf8");
10498
11194
  return path;
10499
11195
  }
10500
11196
 
10501
11197
  // src/upload-state.ts
10502
- import { mkdir as mkdir3, readFile as readFile8, writeFile as writeFile7 } from "fs/promises";
11198
+ import { mkdir as mkdir5, readFile as readFile11, writeFile as writeFile8 } from "fs/promises";
10503
11199
  import { homedir as homedir12 } from "os";
10504
- import { dirname as dirname6, join as join20 } from "path";
11200
+ import { dirname as dirname8, join as join23 } from "path";
10505
11201
  import { contentHash } from "@tangle-network/agent-eval";
10506
11202
  function stateFile() {
10507
- const base = process.env.XDG_STATE_HOME ?? join20(homedir12(), ".local", "state");
10508
- return join20(base, "tangle-traces", "uploaded.json");
11203
+ const base = process.env.XDG_STATE_HOME ?? join23(homedir12(), ".local", "state");
11204
+ return join23(base, "tangle-traces", "uploaded.json");
10509
11205
  }
10510
11206
  function uploadKey(harness, sessionId) {
10511
11207
  return `${harness}:${sessionId}`;
@@ -10518,15 +11214,15 @@ function outboundHash(events, identity) {
10518
11214
  }
10519
11215
  async function loadState() {
10520
11216
  try {
10521
- return JSON.parse(await readFile8(stateFile(), "utf8"));
11217
+ return JSON.parse(await readFile11(stateFile(), "utf8"));
10522
11218
  } catch {
10523
11219
  return {};
10524
11220
  }
10525
11221
  }
10526
11222
  async function saveState(state) {
10527
11223
  const f = stateFile();
10528
- await mkdir3(dirname6(f), { recursive: true });
10529
- await writeFile7(f, `${JSON.stringify(state, null, 2)}
11224
+ await mkdir5(dirname8(f), { recursive: true });
11225
+ await writeFile8(f, `${JSON.stringify(state, null, 2)}
10530
11226
  `, "utf8");
10531
11227
  }
10532
11228
  function alreadyUploaded(state, harness, sessionId, hash2) {
@@ -10534,10 +11230,10 @@ function alreadyUploaded(state, harness, sessionId, hash2) {
10534
11230
  }
10535
11231
 
10536
11232
  // src/upload.ts
10537
- import { readFile as readFile9 } from "fs/promises";
11233
+ import { readFile as readFile12 } from "fs/promises";
10538
11234
  import { createRequire } from "module";
10539
- import { hostname } from "os";
10540
- import { basename as basename11, join as join21 } from "path";
11235
+ import { hostname as hostname2 } from "os";
11236
+ import { basename as basename13, join as join24 } from "path";
10541
11237
  import { hostedClientFromEnv } from "@tangle-network/agent-eval/hosted";
10542
11238
  import { REDACTION_VERSION } from "@tangle-network/agent-eval/traces";
10543
11239
  var require2 = createRequire(import.meta.url);
@@ -10561,7 +11257,7 @@ async function planUpload(opts = {}) {
10561
11257
  async function gitBranch(cwd) {
10562
11258
  if (!cwd) return void 0;
10563
11259
  try {
10564
- const head = await readFile9(join21(cwd, ".git", "HEAD"), "utf8");
11260
+ const head = await readFile12(join24(cwd, ".git", "HEAD"), "utf8");
10565
11261
  const m = head.match(/^ref:\s*refs\/heads\/(.+)$/m);
10566
11262
  return m?.[1]?.trim();
10567
11263
  } catch {
@@ -10571,8 +11267,8 @@ async function gitBranch(cwd) {
10571
11267
  async function sessionMeta(item) {
10572
11268
  const meta = {
10573
11269
  [ATTR.HARNESS]: item.ref.harness,
10574
- [ATTR.SESSION_FILE]: basename11(item.ref.path),
10575
- [ATTR.HOST]: hostname(),
11270
+ [ATTR.SESSION_FILE]: basename13(item.ref.path),
11271
+ [ATTR.HOST]: hostname2(),
10576
11272
  [ATTR.UPLOADER]: `tangle-traces@${TRACES_VERSION}`,
10577
11273
  [ATTR.REDACTION_VERSION]: REDACTION_VERSION,
10578
11274
  [ATTR.REDACTION_COUNT]: item.redaction.redactionCount
@@ -10745,6 +11441,10 @@ export {
10745
11441
  sessionIdFromAttributes,
10746
11442
  indexSessionIdsByTrace,
10747
11443
  stampSessionIdentity,
11444
+ isChatTrajectoryMessage,
11445
+ isChatTrajectory,
11446
+ chatTrajectoryToSpans,
11447
+ importCodeTraceBench,
10748
11448
  summarizeOtlpExecution,
10749
11449
  summarizeSpanExecution,
10750
11450
  toRuntimeStore,
@@ -10804,9 +11504,6 @@ export {
10804
11504
  commandRedactor,
10805
11505
  writeHodoscopeInput,
10806
11506
  hodoscopeAnalyzer,
10807
- isChatTrajectoryMessage,
10808
- isChatTrajectory,
10809
- chatTrajectoryToSpans,
10810
11507
  CODING_REDACTION_RULES,
10811
11508
  TRACES_REDACTION_RULES,
10812
11509
  redactSpans,