agent-inspect 6.12.0 → 6.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +27 -6
  3. package/docs/ADOPTION.md +1 -1
  4. package/docs/DEMO-SCRIPT.md +30 -25
  5. package/docs/DESIGN-PARTNER-GUIDE.md +23 -10
  6. package/docs/FIRST-TRACE-IN-5-MINUTES.md +5 -2
  7. package/docs/GOLDEN-PATH.md +2 -2
  8. package/docs/KNOWN-ISSUES.md +1 -0
  9. package/docs/PRE-V7-PILOT-KIT.md +41 -15
  10. package/docs/SUPPORT-LEVELS.md +1 -1
  11. package/docs/TEAM-WORKFLOWS.md +1 -1
  12. package/docs/TECHNICAL-GUIDE.md +2 -2
  13. package/docs/USE-CASES.md +34 -10
  14. package/package.json +2 -2
  15. package/packages/cli/dist/{chunk-XTAA733P.mjs → chunk-4WA7DQCM.mjs} +316 -55
  16. package/packages/cli/dist/chunk-4WA7DQCM.mjs.map +1 -0
  17. package/packages/cli/dist/index.cjs +337 -70
  18. package/packages/cli/dist/index.cjs.map +1 -1
  19. package/packages/cli/dist/index.mjs +4 -4
  20. package/packages/cli/dist/index.mjs.map +1 -1
  21. package/packages/cli/dist/{src-G7PM24W2.mjs → src-YAASTXGE.mjs} +3 -3
  22. package/packages/cli/dist/{src-G7PM24W2.mjs.map → src-YAASTXGE.mjs.map} +1 -1
  23. package/packages/core/dist/advanced.cjs +290 -30
  24. package/packages/core/dist/advanced.cjs.map +1 -1
  25. package/packages/core/dist/advanced.d.cts +1 -1
  26. package/packages/core/dist/advanced.d.ts +1 -1
  27. package/packages/core/dist/advanced.mjs +1 -1
  28. package/packages/core/dist/checks.cjs +295 -30
  29. package/packages/core/dist/checks.cjs.map +1 -1
  30. package/packages/core/dist/checks.d.cts +2 -2
  31. package/packages/core/dist/checks.d.ts +2 -2
  32. package/packages/core/dist/checks.mjs +1 -1
  33. package/packages/core/dist/{chunk-QT6CQ2XA.mjs → chunk-KJICERSD.mjs} +296 -33
  34. package/packages/core/dist/chunk-KJICERSD.mjs.map +1 -0
  35. package/packages/core/dist/{index-mdFcxSOR.d.cts → index-BOP33T4O.d.cts} +72 -1
  36. package/packages/core/dist/{index-BO7l0iAe.d.ts → index-CgCH8NE9.d.ts} +72 -1
  37. package/packages/cli/dist/chunk-XTAA733P.mjs.map +0 -1
  38. package/packages/core/dist/chunk-QT6CQ2XA.mjs.map +0 -1
@@ -717,12 +717,12 @@ function persistedInspectEventToTraceEvents(event) {
717
717
  if (!isPersistedInspectEvent(event)) {
718
718
  throw new Error("Invalid PersistedInspectEvent: failed isPersistedInspectEvent");
719
719
  }
720
- const legacyEvent = event.attributes?.legacyEvent;
721
- if (legacyEvent === "run_started") return [fromLegacyRunStarted(event)];
722
- if (legacyEvent === "run_completed") return [fromLegacyRunCompleted(event)];
723
- if (legacyEvent === "step_started") return [fromLegacyStepStarted(event)];
724
- if (legacyEvent === "step_completed") return [fromLegacyStepCompleted(event)];
725
- if (legacyEvent === "outcome_observed") return [fromLegacyOutcomeObserved(event)];
720
+ const legacyEvent2 = event.attributes?.legacyEvent;
721
+ if (legacyEvent2 === "run_started") return [fromLegacyRunStarted(event)];
722
+ if (legacyEvent2 === "run_completed") return [fromLegacyRunCompleted(event)];
723
+ if (legacyEvent2 === "step_started") return [fromLegacyStepStarted(event)];
724
+ if (legacyEvent2 === "step_completed") return [fromLegacyStepCompleted(event)];
725
+ if (legacyEvent2 === "outcome_observed") return [fromLegacyOutcomeObserved(event)];
726
726
  if (event.kind === "RUN") {
727
727
  return fromNativeRun(event);
728
728
  }
@@ -6352,6 +6352,264 @@ var init_resolve2 = __esm({
6352
6352
  }
6353
6353
  });
6354
6354
 
6355
+ // packages/core/src/checks/logical-events.ts
6356
+ function isRecord7(value) {
6357
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6358
+ }
6359
+ function legacyEvent(event) {
6360
+ const value = event.attributes?.legacyEvent;
6361
+ return typeof value === "string" ? value : void 0;
6362
+ }
6363
+ function stepIdOf(event) {
6364
+ const value = event.attributes?.stepId;
6365
+ if (typeof value === "string" && value.trim() !== "") return value;
6366
+ return void 0;
6367
+ }
6368
+ function cloneEvent(event) {
6369
+ return {
6370
+ ...event,
6371
+ ...event.attributes !== void 0 ? { attributes: { ...event.attributes } } : {},
6372
+ ...event.error !== void 0 ? { error: { ...event.error } } : {},
6373
+ ...event.tokenUsage !== void 0 ? { tokenUsage: { ...event.tokenUsage } } : {},
6374
+ ...event.source !== void 0 ? { source: { ...event.source } } : {}
6375
+ };
6376
+ }
6377
+ function mergeAttributes(start, complete) {
6378
+ const merged = {
6379
+ ...isRecord7(complete.attributes) ? complete.attributes : {},
6380
+ ...isRecord7(start.attributes) ? start.attributes : {}
6381
+ };
6382
+ merged.legacyEvent = start.attributes?.legacyEvent ?? complete.attributes?.legacyEvent;
6383
+ merged.legacyCompleteEvent = complete.attributes?.legacyEvent;
6384
+ if (complete.attributes?.errorStack !== void 0) {
6385
+ merged.errorStack = complete.attributes.errorStack;
6386
+ }
6387
+ return Object.keys(merged).length > 0 ? merged : void 0;
6388
+ }
6389
+ function pairStartComplete(start, complete) {
6390
+ const attributes = mergeAttributes(start, complete);
6391
+ const paired = {
6392
+ ...cloneEvent(start),
6393
+ status: complete.status,
6394
+ timestamp: complete.timestamp ?? start.timestamp,
6395
+ ...complete.endedAt !== void 0 ? { endedAt: complete.endedAt } : {},
6396
+ ...complete.durationMs !== void 0 ? { durationMs: complete.durationMs } : {},
6397
+ ...complete.error !== void 0 ? { error: { ...complete.error } } : {},
6398
+ ...complete.tokenUsage !== void 0 && start.tokenUsage === void 0 ? { tokenUsage: { ...complete.tokenUsage } } : {},
6399
+ ...attributes !== void 0 ? { attributes } : {}
6400
+ };
6401
+ return {
6402
+ ...paired,
6403
+ sourceEventIds: Object.freeze([start.eventId, complete.eventId]),
6404
+ projection: {
6405
+ paired: true,
6406
+ absorbedEventIds: Object.freeze([complete.eventId]),
6407
+ parentNormalized: false,
6408
+ ...start.parentId !== void 0 ? { originalParentId: start.parentId } : {}
6409
+ }
6410
+ };
6411
+ }
6412
+ function asLogical(event, extras) {
6413
+ return {
6414
+ ...cloneEvent(event),
6415
+ sourceEventIds: Object.freeze([event.eventId]),
6416
+ projection: {
6417
+ paired: false,
6418
+ absorbedEventIds: Object.freeze([]),
6419
+ parentNormalized: extras?.parentNormalized === true,
6420
+ ...{}
6421
+ }
6422
+ };
6423
+ }
6424
+ function projectLogicalEvents(events) {
6425
+ const diagnostics = [];
6426
+ const byRun = /* @__PURE__ */ new Map();
6427
+ for (const event of events) {
6428
+ const list2 = byRun.get(event.runId) ?? [];
6429
+ list2.push(event);
6430
+ byRun.set(event.runId, list2);
6431
+ }
6432
+ const absorbedIds = /* @__PURE__ */ new Set();
6433
+ const logicalByRawId = /* @__PURE__ */ new Map();
6434
+ const stepIdToLogicalId = /* @__PURE__ */ new Map();
6435
+ const logical = [];
6436
+ const orderedRuns = [...byRun.keys()].sort((a, b) => a.localeCompare(b));
6437
+ for (const runId of orderedRuns) {
6438
+ const runEvents = byRun.get(runId) ?? [];
6439
+ const starts = [];
6440
+ const completes = [];
6441
+ const others = [];
6442
+ for (const event of runEvents) {
6443
+ const legacy = legacyEvent(event);
6444
+ if (legacy === "step_started" || legacy === "run_started" && event.status === "running") {
6445
+ starts.push(event);
6446
+ } else if (legacy === "step_completed" || legacy === "run_completed") {
6447
+ completes.push(event);
6448
+ } else {
6449
+ others.push(event);
6450
+ }
6451
+ }
6452
+ const usedCompletes = /* @__PURE__ */ new Set();
6453
+ for (const start of starts) {
6454
+ const stepId = stepIdOf(start);
6455
+ let match;
6456
+ if (legacyEvent(start) === "run_started") {
6457
+ const candidates = completes.filter(
6458
+ (c) => !usedCompletes.has(c.eventId) && legacyEvent(c) === "run_completed"
6459
+ );
6460
+ if (candidates.length > 1) {
6461
+ diagnostics.push({
6462
+ code: "AI_LOGICAL_PAIR_AMBIGUOUS",
6463
+ message: `Multiple run_completed rows for run ${runId}; using first by eventId.`,
6464
+ eventIds: candidates.map((c) => c.eventId)
6465
+ });
6466
+ candidates.sort((a, b) => a.eventId.localeCompare(b.eventId));
6467
+ }
6468
+ match = candidates[0];
6469
+ } else if (stepId) {
6470
+ const candidates = completes.filter(
6471
+ (c) => !usedCompletes.has(c.eventId) && legacyEvent(c) === "step_completed" && stepIdOf(c) === stepId
6472
+ );
6473
+ if (candidates.length > 1) {
6474
+ diagnostics.push({
6475
+ code: "AI_LOGICAL_PAIR_AMBIGUOUS",
6476
+ message: `Multiple step_completed rows for stepId ${stepId}; using first by eventId.`,
6477
+ eventIds: candidates.map((c) => c.eventId)
6478
+ });
6479
+ candidates.sort((a, b) => a.eventId.localeCompare(b.eventId));
6480
+ }
6481
+ match = candidates[0];
6482
+ }
6483
+ if (match) {
6484
+ usedCompletes.add(match.eventId);
6485
+ absorbedIds.add(match.eventId);
6486
+ const paired = pairStartComplete(start, match);
6487
+ logical.push(paired);
6488
+ logicalByRawId.set(start.eventId, paired);
6489
+ logicalByRawId.set(match.eventId, paired);
6490
+ if (stepId) stepIdToLogicalId.set(`${runId}:${stepId}`, paired.eventId);
6491
+ } else {
6492
+ diagnostics.push({
6493
+ code: "AI_LOGICAL_PAIR_UNMATCHED_START",
6494
+ message: `No matching complete for start ${start.eventId}.`,
6495
+ eventIds: [start.eventId]
6496
+ });
6497
+ const alone = asLogical(start);
6498
+ logical.push(alone);
6499
+ logicalByRawId.set(start.eventId, alone);
6500
+ if (stepId) stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
6501
+ }
6502
+ }
6503
+ for (const complete of completes) {
6504
+ if (usedCompletes.has(complete.eventId)) continue;
6505
+ diagnostics.push({
6506
+ code: "AI_LOGICAL_PAIR_UNMATCHED_COMPLETE",
6507
+ message: `No matching start for complete ${complete.eventId}.`,
6508
+ eventIds: [complete.eventId]
6509
+ });
6510
+ const alone = asLogical(complete);
6511
+ logical.push(alone);
6512
+ logicalByRawId.set(complete.eventId, alone);
6513
+ const stepId = stepIdOf(complete);
6514
+ if (stepId && !stepIdToLogicalId.has(`${runId}:${stepId}`)) {
6515
+ stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
6516
+ }
6517
+ }
6518
+ for (const event of others) {
6519
+ const alone = asLogical(event);
6520
+ logical.push(alone);
6521
+ logicalByRawId.set(event.eventId, alone);
6522
+ const stepId = stepIdOf(event);
6523
+ if (stepId && !stepIdToLogicalId.has(`${runId}:${stepId}`)) {
6524
+ stepIdToLogicalId.set(`${runId}:${stepId}`, alone.eventId);
6525
+ }
6526
+ }
6527
+ }
6528
+ const logicalById = new Map(logical.map((e) => [e.eventId, e]));
6529
+ const normalized = [];
6530
+ for (const event of logical) {
6531
+ const originalParentId = event.parentId;
6532
+ if (!originalParentId) {
6533
+ normalized.push(event);
6534
+ continue;
6535
+ }
6536
+ let nextParent = originalParentId;
6537
+ let remapped = false;
6538
+ const viaAbsorbed = logicalByRawId.get(originalParentId);
6539
+ if (viaAbsorbed && viaAbsorbed.eventId !== originalParentId) {
6540
+ nextParent = viaAbsorbed.eventId;
6541
+ remapped = true;
6542
+ } else if (!logicalById.has(originalParentId)) {
6543
+ const viaStep = stepIdToLogicalId.get(`${event.runId}:${originalParentId}`);
6544
+ if (viaStep) {
6545
+ nextParent = viaStep;
6546
+ remapped = true;
6547
+ }
6548
+ }
6549
+ if (!remapped) {
6550
+ if (!logicalById.has(originalParentId) && !logicalByRawId.has(originalParentId)) {
6551
+ diagnostics.push({
6552
+ code: "AI_LOGICAL_PARENT_UNRESOLVED",
6553
+ message: `Parent ${originalParentId} unresolved for ${event.eventId}.`,
6554
+ eventIds: [event.eventId]
6555
+ });
6556
+ }
6557
+ normalized.push(event);
6558
+ continue;
6559
+ }
6560
+ diagnostics.push({
6561
+ code: "AI_LOGICAL_PARENT_REMAPPED",
6562
+ message: `Remapped parent ${originalParentId} \u2192 ${nextParent} for ${event.eventId}.`,
6563
+ eventIds: [event.eventId]
6564
+ });
6565
+ normalized.push({
6566
+ ...event,
6567
+ parentId: nextParent,
6568
+ projection: {
6569
+ ...event.projection,
6570
+ parentNormalized: true,
6571
+ originalParentId
6572
+ }
6573
+ });
6574
+ }
6575
+ const rawIndex = new Map(events.map((e, i) => [e.eventId, i]));
6576
+ normalized.sort((a, b) => {
6577
+ const ai = rawIndex.get(a.sourceEventIds[0]) ?? 0;
6578
+ const bi = rawIndex.get(b.sourceEventIds[0]) ?? 0;
6579
+ return ai - bi || a.eventId.localeCompare(b.eventId);
6580
+ });
6581
+ return {
6582
+ logicalEvents: Object.freeze(normalized),
6583
+ diagnostics: Object.freeze(diagnostics)
6584
+ };
6585
+ }
6586
+ function resolveCanonicalToolName(event) {
6587
+ const attrs = event.attributes;
6588
+ const direct = pickString(attrs, ["toolName", "tool"]);
6589
+ if (direct) return direct;
6590
+ const metadata = attrs?.metadata;
6591
+ if (isRecord7(metadata)) {
6592
+ const nested = pickString(metadata, ["toolName", "tool"]);
6593
+ if (nested) return nested;
6594
+ }
6595
+ for (const prefix of ["tool:", "function:", "mcp-tools:"]) {
6596
+ if (event.name.startsWith(prefix)) return event.name.slice(prefix.length);
6597
+ }
6598
+ return event.name;
6599
+ }
6600
+ function pickString(record, keys) {
6601
+ if (!record) return void 0;
6602
+ for (const key of keys) {
6603
+ const value = record[key];
6604
+ if (typeof value === "string" && value.trim() !== "") return value.trim();
6605
+ }
6606
+ return void 0;
6607
+ }
6608
+ var init_logical_events = __esm({
6609
+ "packages/core/src/checks/logical-events.ts"() {
6610
+ }
6611
+ });
6612
+
6355
6613
  // packages/core/src/checks/contract.ts
6356
6614
  var init_contract = __esm({
6357
6615
  "packages/core/src/checks/contract.ts"() {
@@ -6413,10 +6671,13 @@ function buildFacts2(input3, selectedRun) {
6413
6671
  childrenByParentId.set(parentId, children);
6414
6672
  }
6415
6673
  }
6674
+ const projection = projectLogicalEvents(scopedEvents);
6416
6675
  return {
6417
6676
  format: input3.read.format,
6418
6677
  runs: Object.freeze([...input3.read.runs]),
6419
6678
  events: Object.freeze([...scopedEvents]),
6679
+ logicalEvents: projection.logicalEvents,
6680
+ logicalProjectionDiagnostics: projection.diagnostics,
6420
6681
  readerWarnings: Object.freeze([...input3.read.warnings]),
6421
6682
  unsupportedFields: Object.freeze([...input3.read.unsupportedFields]),
6422
6683
  sourceFiles: Object.freeze([...input3.read.sourceFiles]),
@@ -6609,7 +6870,10 @@ function failFinding(ruleId, message, evidence, expected, actual, meta2) {
6609
6870
  };
6610
6871
  }
6611
6872
  function toolName(event) {
6612
- return stringAttr(event, ["toolName", "tool"]) ?? stripPrefix(event.name, ["tool:", "function:", "mcp-tools:"]);
6873
+ return resolveCanonicalToolName(event);
6874
+ }
6875
+ function semanticEvents(context) {
6876
+ return context.logicalEvents ?? context.events;
6613
6877
  }
6614
6878
  function llmModel(event) {
6615
6879
  return stringAttr(event, ["model", "modelId", "responseModelId", "modelName", "model_name"]) ?? stripPrefix(event.name, ["llm:", "generation:", "transcription:", "speech:"]);
@@ -6624,11 +6888,11 @@ function retryCount(event) {
6624
6888
  return numericAttr(event, ["retryCount", "retryAttempt", "retry_attempt", "attempt"]);
6625
6889
  }
6626
6890
  function finishedEvents(context, kind) {
6627
- return context.events.filter(
6891
+ return semanticEvents(context).filter(
6628
6892
  (event) => (kind === void 0 || event.kind === kind) && event.status !== "running"
6629
6893
  );
6630
6894
  }
6631
- function isRecord7(value) {
6895
+ function isRecord8(value) {
6632
6896
  return typeof value === "object" && value !== null && !Array.isArray(value);
6633
6897
  }
6634
6898
  function eventMap(events) {
@@ -6679,7 +6943,7 @@ function pushValueEntries(entries, event, value, path41, key, depth = 0) {
6679
6943
  }
6680
6944
  return;
6681
6945
  }
6682
- if (!isRecord7(value)) return;
6946
+ if (!isRecord8(value)) return;
6683
6947
  for (const nestedKey of Object.keys(value).sort((a, b) => a.localeCompare(b))) {
6684
6948
  pushValueEntries(
6685
6949
  entries,
@@ -6759,14 +7023,11 @@ function signalName(event, attributeKeys, prefixes) {
6759
7023
  return stringAttr(event, attributeKeys) ?? stripPrefix(event.name, prefixes);
6760
7024
  }
6761
7025
  function guardrailEvents(context) {
6762
- return finishedEvents2().filter((event) => {
7026
+ return finishedEvents(context).filter((event) => {
6763
7027
  const name = event.name.toLowerCase();
6764
7028
  if (name.startsWith("guardrail:") || name.includes(".guardrail.")) return true;
6765
7029
  return stringAttr(event, ["guardrailName", "guardrail", "guardrailId"]) !== void 0;
6766
7030
  });
6767
- function finishedEvents2() {
6768
- return context.events.filter((event) => event.status !== "running");
6769
- }
6770
7031
  }
6771
7032
  function retryValue(event) {
6772
7033
  return retryCount(event) ?? 0;
@@ -6787,7 +7048,7 @@ function treeShape(nodes) {
6787
7048
  return lines;
6788
7049
  }
6789
7050
  function statusShape(context) {
6790
- return context.events.map((event) => `${event.kind}:${event.name}:${event.status ?? "unknown"}`).sort((a, b) => a.localeCompare(b));
7051
+ return semanticEvents(context).map((event) => `${event.kind}:${event.name}:${event.status ?? "unknown"}`).sort((a, b) => a.localeCompare(b));
6791
7052
  }
6792
7053
  function toolShape(context) {
6793
7054
  return finishedEvents(context, "TOOL").map(
@@ -6813,7 +7074,7 @@ function llmShape(context) {
6813
7074
  );
6814
7075
  }
6815
7076
  function errorShape(context) {
6816
- return context.events.filter((event) => event.status === "error" || event.error !== void 0).map(
7077
+ return semanticEvents(context).filter((event) => event.status === "error" || event.error !== void 0).map(
6817
7078
  (event) => [
6818
7079
  event.kind,
6819
7080
  event.name,
@@ -6831,7 +7092,7 @@ function guardrailShape(context) {
6831
7092
  return guardrailEvents(context).map((event) => signalName(event, ["guardrailName", "guardrail", "guardrailId"], ["guardrail:"])).sort((a, b) => a.localeCompare(b));
6832
7093
  }
6833
7094
  function firstEvidenceForKind(context, kind, path41) {
6834
- const event = context.events.find((candidate) => candidate.kind === kind);
7095
+ const event = semanticEvents(context).find((candidate) => candidate.kind === kind);
6835
7096
  return event ? [eventEvidence(event, path41)] : runEvidence(context.selectedRun);
6836
7097
  }
6837
7098
  function baselineDiffFinding(message, evidence, expected, actual) {
@@ -6859,7 +7120,7 @@ function createRunStatusRule(options = {}) {
6859
7120
  );
6860
7121
  }
6861
7122
  if (!allowIncomplete) {
6862
- const running = context.events.filter((event) => event.status === "running");
7123
+ const running = semanticEvents(context).filter((event) => event.status === "running");
6863
7124
  if (running.length > 0) {
6864
7125
  findings.push(
6865
7126
  failFinding(
@@ -6902,7 +7163,7 @@ function createMaxStepDurationRule(options) {
6902
7163
  category: "run",
6903
7164
  defaultSeverity: "error",
6904
7165
  evaluate(context) {
6905
- const over = context.events.filter((event) => {
7166
+ const over = semanticEvents(context).filter((event) => {
6906
7167
  const duration = eventDurationMs(event);
6907
7168
  return duration !== void 0 && duration > options.maxDurationMs;
6908
7169
  });
@@ -6931,7 +7192,7 @@ function createStallDetectionRule(options = {}) {
6931
7192
  defaultSeverity: "warning",
6932
7193
  evaluate(context) {
6933
7194
  const findings = [];
6934
- const running = context.events.filter((event) => event.status === "running");
7195
+ const running = semanticEvents(context).filter((event) => event.status === "running");
6935
7196
  if (running.length > 0) {
6936
7197
  findings.push(
6937
7198
  failFinding(
@@ -6944,7 +7205,7 @@ function createStallDetectionRule(options = {}) {
6944
7205
  );
6945
7206
  }
6946
7207
  if (requireEndedAt) {
6947
- const incomplete = context.events.filter(
7208
+ const incomplete = semanticEvents(context).filter(
6948
7209
  (event) => event.startedAt !== void 0 && event.endedAt === void 0 && event.status !== "running"
6949
7210
  );
6950
7211
  if (incomplete.length > 0) {
@@ -6982,7 +7243,7 @@ function createRequireCompletedRule() {
6982
7243
  )
6983
7244
  );
6984
7245
  }
6985
- const running = context.events.filter((event) => event.status === "running");
7246
+ const running = semanticEvents(context).filter((event) => event.status === "running");
6986
7247
  if (running.length > 0) {
6987
7248
  findings.push(
6988
7249
  failFinding(
@@ -7154,8 +7415,8 @@ function createStructureOrphanRule(options = {}) {
7154
7415
  category: "structure",
7155
7416
  defaultSeverity: "error",
7156
7417
  evaluate(context) {
7157
- const byId = eventMap(context.events);
7158
- const orphans = context.events.filter((event) => {
7418
+ const byId = eventMap(semanticEvents(context));
7419
+ const orphans = semanticEvents(context).filter((event) => {
7159
7420
  if (!event.parentId || byId.has(event.parentId)) return false;
7160
7421
  return !(allowMarkedUnresolved && parentMarkedUnresolved(event));
7161
7422
  });
@@ -7178,10 +7439,10 @@ function createStructureCycleRule() {
7178
7439
  category: "structure",
7179
7440
  defaultSeverity: "error",
7180
7441
  evaluate(context) {
7181
- const byId = eventMap(context.events);
7442
+ const byId = eventMap(semanticEvents(context));
7182
7443
  const seenCycles = /* @__PURE__ */ new Set();
7183
7444
  const findings = [];
7184
- for (const event of [...context.events].sort((a, b) => a.eventId.localeCompare(b.eventId))) {
7445
+ for (const event of [...semanticEvents(context)].sort((a, b) => a.eventId.localeCompare(b.eventId))) {
7185
7446
  const path41 = [];
7186
7447
  const seenAt = /* @__PURE__ */ new Map();
7187
7448
  let current = event;
@@ -7219,10 +7480,10 @@ function createStructureRelationshipRule(options = {}) {
7219
7480
  category: "structure",
7220
7481
  defaultSeverity: "error",
7221
7482
  evaluate(context) {
7222
- const byId = eventMap(context.events);
7483
+ const byId = eventMap(semanticEvents(context));
7223
7484
  const findings = [];
7224
7485
  const minConfidence = options.minConfidence;
7225
- for (const event of context.events) {
7486
+ for (const event of semanticEvents(context)) {
7226
7487
  if (minConfidence && CONFIDENCE_RANK[event.confidence] < CONFIDENCE_RANK[minConfidence]) {
7227
7488
  findings.push(
7228
7489
  failFinding(
@@ -7290,7 +7551,7 @@ function createStructureParallelWidthRule(options) {
7290
7551
  defaultSeverity: "error",
7291
7552
  evaluate(context) {
7292
7553
  const findings = [];
7293
- const byId = eventMap(context.events);
7554
+ const byId = eventMap(semanticEvents(context));
7294
7555
  if (options.maxChildren !== void 0) {
7295
7556
  for (const [parentId, children] of context.childrenByParentId.entries()) {
7296
7557
  if (children.length <= options.maxChildren) continue;
@@ -7317,7 +7578,7 @@ function createStructureParallelWidthRule(options) {
7317
7578
  }
7318
7579
  }
7319
7580
  if (options.maxConcurrent !== void 0) {
7320
- const intervals = context.events.map((event) => ({ event, start: eventStartMs(event), end: eventEndMs(event) })).filter(
7581
+ const intervals = semanticEvents(context).map((event) => ({ event, start: eventStartMs(event), end: eventEndMs(event) })).filter(
7321
7582
  (item) => item.start !== void 0 && item.end !== void 0 && item.end > item.start
7322
7583
  );
7323
7584
  const points = intervals.flatMap((item) => [
@@ -7510,7 +7771,7 @@ function createSafetyOversizedAttributeRule(options) {
7510
7771
  )
7511
7772
  );
7512
7773
  }
7513
- if (isRecord7(entry.value) && options.maxObjectKeys !== void 0 && Object.keys(entry.value).length > options.maxObjectKeys) {
7774
+ if (isRecord8(entry.value) && options.maxObjectKeys !== void 0 && Object.keys(entry.value).length > options.maxObjectKeys) {
7514
7775
  findings.push(
7515
7776
  failFinding(
7516
7777
  "safety.oversizedAttribute",
@@ -7763,6 +8024,8 @@ var SEVERITY_RANK, STATUS_RANK, CONFIDENCE_RANK, DEFAULT_SENSITIVE_KEYS, DEFAULT
7763
8024
  var init_checks2 = __esm({
7764
8025
  "packages/core/src/checks/index.ts"() {
7765
8026
  init_outcomes();
8027
+ init_logical_events();
8028
+ init_logical_events();
7766
8029
  init_contract();
7767
8030
  SEVERITY_RANK = {
7768
8031
  error: 0,
@@ -7821,7 +8084,11 @@ var init_checks2 = __esm({
7821
8084
  "conversationtext",
7822
8085
  "conversation_text"
7823
8086
  ];
7824
- DEFAULT_SAFE_RAW_CONTENT_PATH_PREFIXES = ["tokenUsage", "usage"];
8087
+ DEFAULT_SAFE_RAW_CONTENT_PATH_PREFIXES = [
8088
+ "tokenUsage",
8089
+ "usage",
8090
+ "tokens"
8091
+ ];
7825
8092
  SAFE_USAGE_LEAF_KEYS = /* @__PURE__ */ new Set([
7826
8093
  "input",
7827
8094
  "output",
@@ -7849,14 +8116,14 @@ var init_checks2 = __esm({
7849
8116
  });
7850
8117
 
7851
8118
  // packages/core/src/persisted/token-usage.ts
7852
- function isRecord8(value) {
8119
+ function isRecord9(value) {
7853
8120
  return typeof value === "object" && value !== null && !Array.isArray(value);
7854
8121
  }
7855
8122
  function nonNegativeFinite(value) {
7856
8123
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
7857
8124
  }
7858
8125
  function normalizeTokenUsage(value) {
7859
- if (!isRecord8(value)) return void 0;
8126
+ if (!isRecord9(value)) return void 0;
7860
8127
  const input3 = nonNegativeFinite(value.input);
7861
8128
  const output2 = nonNegativeFinite(value.output);
7862
8129
  const suppliedTotal = nonNegativeFinite(value.total);
@@ -8577,7 +8844,7 @@ function persistedEventsForParsedTrace(parsed) {
8577
8844
  sourceName: "agent-inspect-jsonl-reader"
8578
8845
  });
8579
8846
  }
8580
- function isRecord9(value) {
8847
+ function isRecord10(value) {
8581
8848
  return typeof value === "object" && value !== null && !Array.isArray(value);
8582
8849
  }
8583
8850
  function isNonEmptyString4(value) {
@@ -8592,13 +8859,13 @@ function readStringField(record, keys) {
8592
8859
  }
8593
8860
  function readRecordField(record, key) {
8594
8861
  const value = record[key];
8595
- return isRecord9(value) ? value : void 0;
8862
+ return isRecord10(value) ? value : void 0;
8596
8863
  }
8597
8864
  function parseJsonDocument(content) {
8598
8865
  return JSON.parse(content);
8599
8866
  }
8600
8867
  function looksLikeOpenInferenceSpan(value) {
8601
- if (!isRecord9(value)) return false;
8868
+ if (!isRecord10(value)) return false;
8602
8869
  const attributes = readRecordField(value, "attributes");
8603
8870
  return readStringField(value, ["trace_id", "traceId"]) !== void 0 && readStringField(value, ["span_id", "spanId"]) !== void 0 && (readStringField(value, ["name"]) !== void 0 || attributes?.["openinference.span.kind"] !== void 0);
8604
8871
  }
@@ -8623,7 +8890,7 @@ function extractOpenInferenceDocument(root) {
8623
8890
  unsupportedFields
8624
8891
  };
8625
8892
  }
8626
- if (!isRecord9(root)) return void 0;
8893
+ if (!isRecord10(root)) return void 0;
8627
8894
  const rootFormat = root.format;
8628
8895
  const rootCompatibility = root.compatibility;
8629
8896
  const version2 = typeof root.version === "string" && root.version.trim() !== "" ? root.version : void 0;
@@ -8763,7 +9030,7 @@ function summarizeAttributeValue(value) {
8763
9030
  if (Array.isArray(value)) {
8764
9031
  return { type: "array", length: value.length };
8765
9032
  }
8766
- if (isRecord9(value)) {
9033
+ if (isRecord10(value)) {
8767
9034
  return { type: "object", keyCount: Object.keys(value).length };
8768
9035
  }
8769
9036
  if (value === null) {
@@ -8850,7 +9117,7 @@ function mapOpenInferenceKind(span, attributes, pathPrefix) {
8850
9117
  }
8851
9118
  }
8852
9119
  function mapOpenInferenceStatus(status) {
8853
- if (!isRecord9(status)) return void 0;
9120
+ if (!isRecord10(status)) return void 0;
8854
9121
  const rawCode = status.code;
8855
9122
  if (typeof rawCode !== "string") return void 0;
8856
9123
  switch (rawCode.toUpperCase()) {
@@ -8950,7 +9217,7 @@ function mapOpenInferenceSpan(span, index, version2) {
8950
9217
  warnings.push(...kindWarnings);
8951
9218
  const status = mapOpenInferenceStatus(span.status);
8952
9219
  const tokenUsage = readOpenInferenceTokenUsage(rawAttributes);
8953
- const errorMessage = isRecord9(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
9220
+ const errorMessage = isRecord10(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
8954
9221
  const event = {
8955
9222
  schemaVersion: "0.2",
8956
9223
  eventId: typeof rawAttributes["agent_inspect.event_id"] === "string" ? rawAttributes["agent_inspect.event_id"] : spanId,
@@ -9018,7 +9285,7 @@ function mapOpenInferenceEvents(document) {
9018
9285
  };
9019
9286
  }
9020
9287
  function parseOtlpAnyValue(value, field, warnings, unsupportedFields) {
9021
- if (!isRecord9(value)) {
9288
+ if (!isRecord10(value)) {
9022
9289
  unsupportedFields.push(field);
9023
9290
  warnings.push({
9024
9291
  code: "otlp_attribute_value_invalid",
@@ -9040,15 +9307,15 @@ function parseOtlpAnyValue(value, field, warnings, unsupportedFields) {
9040
9307
  if (typeof value.doubleValue === "number" && Number.isFinite(value.doubleValue)) {
9041
9308
  return value.doubleValue;
9042
9309
  }
9043
- if (isRecord9(value.arrayValue) && Array.isArray(value.arrayValue.values)) {
9310
+ if (isRecord10(value.arrayValue) && Array.isArray(value.arrayValue.values)) {
9044
9311
  return value.arrayValue.values.map(
9045
9312
  (item, index) => parseOtlpAnyValue(item, `${field}.arrayValue.values[${index}]`, warnings, unsupportedFields)
9046
9313
  );
9047
9314
  }
9048
- if (isRecord9(value.kvlistValue) && Array.isArray(value.kvlistValue.values)) {
9315
+ if (isRecord10(value.kvlistValue) && Array.isArray(value.kvlistValue.values)) {
9049
9316
  const out = {};
9050
9317
  for (const [index, item] of value.kvlistValue.values.entries()) {
9051
- if (!isRecord9(item) || typeof item.key !== "string") {
9318
+ if (!isRecord10(item) || typeof item.key !== "string") {
9052
9319
  unsupportedFields.push(`${field}.kvlistValue.values[${index}]`);
9053
9320
  continue;
9054
9321
  }
@@ -9099,7 +9366,7 @@ function parseOtlpAttributes(value, pathPrefix) {
9099
9366
  }
9100
9367
  for (const [index, item] of value.entries()) {
9101
9368
  const field = `${pathPrefix}[${index}]`;
9102
- if (!isRecord9(item) || typeof item.key !== "string") {
9369
+ if (!isRecord10(item) || typeof item.key !== "string") {
9103
9370
  unsupportedFields.push(field);
9104
9371
  warnings.push({
9105
9372
  code: "otlp_attribute_invalid",
@@ -9122,16 +9389,16 @@ function parseOtlpAttributes(value, pathPrefix) {
9122
9389
  return { attributes, warnings, unsupportedFields };
9123
9390
  }
9124
9391
  function looksLikeOtlpSpan(value) {
9125
- return isRecord9(value) && readStringField(value, ["traceId"]) !== void 0 && readStringField(value, ["spanId"]) !== void 0 && readStringField(value, ["name"]) !== void 0;
9392
+ return isRecord10(value) && readStringField(value, ["traceId"]) !== void 0 && readStringField(value, ["spanId"]) !== void 0 && readStringField(value, ["name"]) !== void 0;
9126
9393
  }
9127
9394
  function extractOtlpDocument(root) {
9128
- if (!isRecord9(root) || !Array.isArray(root.resourceSpans)) return void 0;
9395
+ if (!isRecord10(root) || !Array.isArray(root.resourceSpans)) return void 0;
9129
9396
  const spans = [];
9130
9397
  const warnings = [];
9131
9398
  const unsupportedFields = [];
9132
9399
  for (const [resourceIndex, resourceSpan] of root.resourceSpans.entries()) {
9133
9400
  const resourcePath = `resourceSpans[${resourceIndex}]`;
9134
- if (!isRecord9(resourceSpan)) {
9401
+ if (!isRecord10(resourceSpan)) {
9135
9402
  unsupportedFields.push(resourcePath);
9136
9403
  continue;
9137
9404
  }
@@ -9154,7 +9421,7 @@ function extractOtlpDocument(root) {
9154
9421
  }
9155
9422
  for (const [scopeIndex, scopeSpan] of resourceSpan.scopeSpans.entries()) {
9156
9423
  const scopePath = `${resourcePath}.scopeSpans[${scopeIndex}]`;
9157
- if (!isRecord9(scopeSpan)) {
9424
+ if (!isRecord10(scopeSpan)) {
9158
9425
  unsupportedFields.push(scopePath);
9159
9426
  continue;
9160
9427
  }
@@ -9221,7 +9488,7 @@ function extractOtlpDocument(root) {
9221
9488
  };
9222
9489
  }
9223
9490
  function mapOtlpStatus(status) {
9224
- if (!isRecord9(status)) return void 0;
9491
+ if (!isRecord10(status)) return void 0;
9225
9492
  const rawCode = status.code;
9226
9493
  if (typeof rawCode !== "string") return void 0;
9227
9494
  switch (rawCode.toUpperCase()) {
@@ -9321,7 +9588,7 @@ function mapOtlpEvents(value, pathPrefix) {
9321
9588
  const events = [];
9322
9589
  for (const [index, event] of value.entries()) {
9323
9590
  const eventPath = `${pathPrefix}[${index}]`;
9324
- if (!isRecord9(event)) {
9591
+ if (!isRecord10(event)) {
9325
9592
  unsupportedFields.push(eventPath);
9326
9593
  continue;
9327
9594
  }
@@ -9459,7 +9726,7 @@ function mapOtlpSpan(context) {
9459
9726
  warnings.push(...kindWarnings);
9460
9727
  const status = mapOtlpStatus(span.status);
9461
9728
  const tokenUsage = readOtlpTokenUsage(parsedSpanAttributes.attributes);
9462
- const errorMessage = isRecord9(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
9729
+ const errorMessage = isRecord10(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
9463
9730
  const event = {
9464
9731
  schemaVersion: "0.2",
9465
9732
  eventId: typeof parsedSpanAttributes.attributes["agent_inspect.event_id"] === "string" ? parsedSpanAttributes.attributes["agent_inspect.event_id"] : spanId,
@@ -11889,7 +12156,7 @@ var init_src = __esm({
11889
12156
  });
11890
12157
 
11891
12158
  // package.json
11892
- var version = "6.12.0";
12159
+ var version = "6.12.2";
11893
12160
 
11894
12161
  // packages/cli/src/list.ts
11895
12162
  init_advanced();
@@ -12506,7 +12773,7 @@ async function view(runId, options = {}) {
12506
12773
  process.exitCode = 1;
12507
12774
  }
12508
12775
  }
12509
- function isRecord10(v) {
12776
+ function isRecord11(v) {
12510
12777
  return typeof v === "object" && v !== null && !Array.isArray(v);
12511
12778
  }
12512
12779
  function isNonEmptyStringArray(v) {
@@ -12518,7 +12785,7 @@ function validateRedact(redact2) {
12518
12785
  }
12519
12786
  for (const r of redact2) {
12520
12787
  if (typeof r === "string") continue;
12521
- if (!isRecord10(r)) {
12788
+ if (!isRecord11(r)) {
12522
12789
  throw new Error("Invalid config: redact entries must be strings or objects");
12523
12790
  }
12524
12791
  if (typeof r.key !== "string" || r.key.trim() === "") {
@@ -12537,7 +12804,7 @@ function validateRedact(redact2) {
12537
12804
  }
12538
12805
  }
12539
12806
  function validateMappings(mappings) {
12540
- if (!isRecord10(mappings)) {
12807
+ if (!isRecord11(mappings)) {
12541
12808
  throw new Error("Invalid config: mappings must be an object");
12542
12809
  }
12543
12810
  }
@@ -12587,7 +12854,7 @@ async function loadLogIngestConfig(configPath) {
12587
12854
  const msg = e instanceof Error ? e.message : String(e);
12588
12855
  throw new Error(`Invalid JSON in config file: ${configPath} (${msg})`);
12589
12856
  }
12590
- if (!isRecord10(parsed)) {
12857
+ if (!isRecord11(parsed)) {
12591
12858
  throw new Error("Invalid config: expected a JSON object at top-level");
12592
12859
  }
12593
12860
  const user = parsed;
@@ -12624,7 +12891,7 @@ async function loadLogIngestConfig(configPath) {
12624
12891
  }
12625
12892
  return mergeLogIngestConfig(DEFAULT_LOG_INGEST_CONFIG, user);
12626
12893
  }
12627
- function isRecord11(v) {
12894
+ function isRecord12(v) {
12628
12895
  return typeof v === "object" && v !== null && !Array.isArray(v);
12629
12896
  }
12630
12897
  var JsonLogParser = class {
@@ -12649,7 +12916,7 @@ var JsonLogParser = class {
12649
12916
  });
12650
12917
  continue;
12651
12918
  }
12652
- if (!isRecord11(parsed)) {
12919
+ if (!isRecord12(parsed)) {
12653
12920
  warnings.push({
12654
12921
  code: "MALFORMED_JSON",
12655
12922
  message: "JSON log line must be an object",
@@ -12680,7 +12947,7 @@ var JsonLogParser = class {
12680
12947
  return this.parseLines(lines, filePath);
12681
12948
  }
12682
12949
  };
12683
- function isRecord12(v) {
12950
+ function isRecord13(v) {
12684
12951
  return typeof v === "object" && v !== null && !Array.isArray(v);
12685
12952
  }
12686
12953
  function findLastJsonObjectSubstring(line) {
@@ -12756,7 +13023,7 @@ var Log4jsParser = class {
12756
13023
  });
12757
13024
  continue;
12758
13025
  }
12759
- if (!isRecord12(parsed)) {
13026
+ if (!isRecord13(parsed)) {
12760
13027
  warnings.push({
12761
13028
  code: "UNSUPPORTED_LOG4JS_PAYLOAD",
12762
13029
  message: "Embedded JSON payload must be an object",
@@ -13630,7 +13897,7 @@ var EXPORT_PAYLOAD_VERSION = "0.1.2";
13630
13897
  // packages/core/src/exporters/redact-export.ts
13631
13898
  init_redactor();
13632
13899
  init_redaction_profiles();
13633
- function isRecord13(value) {
13900
+ function isRecord14(value) {
13634
13901
  return typeof value === "object" && value !== null && !Array.isArray(value);
13635
13902
  }
13636
13903
  function deepClone(value) {
@@ -13704,7 +13971,7 @@ function redactEventAttributes(attrs, redactor, maxMetadataValueLength, maxPrevi
13704
13971
  0
13705
13972
  );
13706
13973
  const err = bounded.error;
13707
- if (isRecord13(err) && typeof err.message === "string") {
13974
+ if (isRecord14(err) && typeof err.message === "string") {
13708
13975
  bounded.error = {
13709
13976
  ...err,
13710
13977
  message: truncateStringForProfile(
@@ -13734,7 +14001,7 @@ function redactErrorInfo(error, redactor, maxMetadataValueLength, maxPreviewLeng
13734
14001
  maxPreviewLength
13735
14002
  );
13736
14003
  const redacted = record?.error;
13737
- if (!isRecord13(redacted) || typeof redacted.message !== "string") {
14004
+ if (!isRecord14(redacted) || typeof redacted.message !== "string") {
13738
14005
  return void 0;
13739
14006
  }
13740
14007
  return {
@@ -13814,7 +14081,7 @@ function redactTraceEventsForReport(events, options) {
13814
14081
  ) : void 0;
13815
14082
  const redactedActual = actualAttrs !== void 0 && "value" in actualAttrs ? actualAttrs.value : void 0;
13816
14083
  const redactedEvidence = event.evidence !== void 0 ? redactEventAttributes(
13817
- isRecord13(event.evidence) ? event.evidence : { value: event.evidence },
14084
+ isRecord14(event.evidence) ? event.evidence : { value: event.evidence },
13818
14085
  redactor,
13819
14086
  maxMetadataValueLength,
13820
14087
  maxPreviewLength
@@ -15834,7 +16101,7 @@ var STRICT_PROFILE_EXTRA_KEYS2 = [
15834
16101
  "retrieval",
15835
16102
  "query"
15836
16103
  ];
15837
- function isRecord14(value) {
16104
+ function isRecord15(value) {
15838
16105
  return typeof value === "object" && value !== null && !Array.isArray(value);
15839
16106
  }
15840
16107
  function toKey2(key) {
@@ -16199,7 +16466,7 @@ var Redactor2 = class {
16199
16466
  });
16200
16467
  return out;
16201
16468
  }
16202
- if (isRecord14(value)) {
16469
+ if (isRecord15(value)) {
16203
16470
  if (state.seen.has(value)) return state.seen.get(value);
16204
16471
  const out = {};
16205
16472
  state.seen.set(value, out);
@@ -16656,7 +16923,7 @@ async function openCommand(input3, options = {}, stdin = process.stdin) {
16656
16923
 
16657
16924
  // packages/cli/src/migrate.ts
16658
16925
  init_advanced();
16659
- function isRecord15(value) {
16926
+ function isRecord16(value) {
16660
16927
  return typeof value === "object" && value !== null && !Array.isArray(value);
16661
16928
  }
16662
16929
  function parseTarget(value) {
@@ -16665,7 +16932,7 @@ function parseTarget(value) {
16665
16932
  throw new Error('Unsupported migration target. Use "--to 1.0".');
16666
16933
  }
16667
16934
  function formatOf(value) {
16668
- if (!isRecord15(value)) return "unknown";
16935
+ if (!isRecord16(value)) return "unknown";
16669
16936
  if (value.schemaVersion === "0.1") return "0.1";
16670
16937
  if (value.schemaVersion === "0.2") return "0.2";
16671
16938
  if (value.schemaVersion === "1.0") return "1.0";