agent-inspect 6.18.0 → 6.19.1

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 (62) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +3 -1
  3. package/SECURITY.md +2 -0
  4. package/docs/API.md +2 -1
  5. package/docs/ARCHITECTURE.md +28 -16
  6. package/docs/KNOWN-ISSUES.md +3 -3
  7. package/docs/LIMITATIONS.md +5 -4
  8. package/docs/PERFORMANCE.md +1 -1
  9. package/docs/SUPPORT-LEVELS.md +2 -1
  10. package/package.json +3 -2
  11. package/packages/cli/dist/{chunk-S4TLTLXN.mjs → chunk-QDYVK4MF.mjs} +403 -42
  12. package/packages/cli/dist/chunk-QDYVK4MF.mjs.map +1 -0
  13. package/packages/cli/dist/index.cjs +443 -63
  14. package/packages/cli/dist/index.cjs.map +1 -1
  15. package/packages/cli/dist/index.mjs +11 -7
  16. package/packages/cli/dist/index.mjs.map +1 -1
  17. package/packages/cli/dist/{src-R6V5EZZH.mjs → src-CIC27TS2.mjs} +3 -3
  18. package/packages/cli/dist/{src-R6V5EZZH.mjs.map → src-CIC27TS2.mjs.map} +1 -1
  19. package/packages/core/dist/advanced.cjs +118 -18
  20. package/packages/core/dist/advanced.cjs.map +1 -1
  21. package/packages/core/dist/advanced.d.cts +14 -3
  22. package/packages/core/dist/advanced.d.ts +14 -3
  23. package/packages/core/dist/advanced.mjs +8 -8
  24. package/packages/core/dist/advanced.mjs.map +1 -1
  25. package/packages/core/dist/checks.cjs +334 -5
  26. package/packages/core/dist/checks.cjs.map +1 -1
  27. package/packages/core/dist/checks.d.cts +81 -4
  28. package/packages/core/dist/checks.d.ts +81 -4
  29. package/packages/core/dist/checks.mjs +3 -3
  30. package/packages/core/dist/{chunk-VFO76UH3.mjs → chunk-3XS5O4JI.mjs} +3 -3
  31. package/packages/core/dist/{chunk-VFO76UH3.mjs.map → chunk-3XS5O4JI.mjs.map} +1 -1
  32. package/packages/core/dist/{chunk-ZWA5RWMV.mjs → chunk-5YFJJFXU.mjs} +4 -4
  33. package/packages/core/dist/{chunk-ZWA5RWMV.mjs.map → chunk-5YFJJFXU.mjs.map} +1 -1
  34. package/packages/core/dist/{chunk-LQC7IED3.mjs → chunk-6LP2J5CA.mjs} +337 -9
  35. package/packages/core/dist/chunk-6LP2J5CA.mjs.map +1 -0
  36. package/packages/core/dist/{chunk-SGL4JGCD.mjs → chunk-JBNRJLIV.mjs} +58 -18
  37. package/packages/core/dist/chunk-JBNRJLIV.mjs.map +1 -0
  38. package/packages/core/dist/{chunk-ULCGIRTC.mjs → chunk-U25RHRSU.mjs} +65 -5
  39. package/packages/core/dist/chunk-U25RHRSU.mjs.map +1 -0
  40. package/packages/core/dist/{context-Ca5yK8Cs.d.cts → context-C5ye_xcS.d.cts} +0 -4
  41. package/packages/core/dist/{context-D6cS4XIL.d.ts → context-CNsNSgE2.d.ts} +0 -4
  42. package/packages/core/dist/exporters.cjs +55 -15
  43. package/packages/core/dist/exporters.cjs.map +1 -1
  44. package/packages/core/dist/exporters.mjs +3 -3
  45. package/packages/core/dist/{index-B9ZGvUVL.d.ts → index-AMAGuO_i.d.ts} +1 -1
  46. package/packages/core/dist/{index-DWu54Y28.d.cts → index-DCR816Yt.d.cts} +2 -2
  47. package/packages/core/dist/{index-DlwbVqEs.d.ts → index-DKwuGSe-.d.ts} +2 -2
  48. package/packages/core/dist/{index-B259NKkH.d.cts → index-vqr-g6ev.d.cts} +1 -1
  49. package/packages/core/dist/index.cjs +63 -3
  50. package/packages/core/dist/index.cjs.map +1 -1
  51. package/packages/core/dist/index.d.cts +1 -1
  52. package/packages/core/dist/index.d.ts +1 -1
  53. package/packages/core/dist/index.mjs +4 -4
  54. package/packages/core/dist/readers.d.cts +1 -1
  55. package/packages/core/dist/readers.d.ts +1 -1
  56. package/packages/core/dist/writers.cjs +33 -2
  57. package/packages/core/dist/writers.cjs.map +1 -1
  58. package/packages/core/dist/writers.mjs +1 -1
  59. package/packages/cli/dist/chunk-S4TLTLXN.mjs.map +0 -1
  60. package/packages/core/dist/chunk-LQC7IED3.mjs.map +0 -1
  61. package/packages/core/dist/chunk-SGL4JGCD.mjs.map +0 -1
  62. package/packages/core/dist/chunk-ULCGIRTC.mjs.map +0 -1
@@ -1714,9 +1714,63 @@ async function extractMetadata(filePath, _quickScan) {
1714
1714
  createdAt: stats.birthtime
1715
1715
  };
1716
1716
  }
1717
+ var ROOT_STEP_DEPTH = 0;
1718
+ var MAX_RUN_SUMMARY_DEPTH = 1e3;
1717
1719
  function isNonNegativeFiniteNumber(value) {
1718
1720
  return typeof value === "number" && Number.isFinite(value) && value >= 0;
1719
1721
  }
1722
+ function resolveParentStepId(step, steps) {
1723
+ const parentId = step.parentId;
1724
+ if (typeof parentId !== "string" || parentId.trim() === "") {
1725
+ return void 0;
1726
+ }
1727
+ return steps.has(parentId) ? parentId : void 0;
1728
+ }
1729
+ function computeStepDepth(stepId, steps, depthCache) {
1730
+ const cached = depthCache.get(stepId);
1731
+ if (cached !== void 0) return cached;
1732
+ const ancestry = [];
1733
+ const ancestryIndexes = /* @__PURE__ */ new Map();
1734
+ let currentStepId = stepId;
1735
+ let resolvedDepth;
1736
+ while (resolvedDepth === void 0) {
1737
+ const cachedDepth = depthCache.get(currentStepId);
1738
+ if (cachedDepth !== void 0) {
1739
+ resolvedDepth = cachedDepth;
1740
+ continue;
1741
+ }
1742
+ const cycleStart = ancestryIndexes.get(currentStepId);
1743
+ if (cycleStart !== void 0) {
1744
+ const cycleStepIds = ancestry.splice(cycleStart);
1745
+ for (const cycleStepId of cycleStepIds) {
1746
+ depthCache.set(cycleStepId, ROOT_STEP_DEPTH);
1747
+ }
1748
+ resolvedDepth = ROOT_STEP_DEPTH;
1749
+ continue;
1750
+ }
1751
+ const currentStep = steps.get(currentStepId);
1752
+ if (!currentStep) {
1753
+ resolvedDepth = ROOT_STEP_DEPTH;
1754
+ continue;
1755
+ }
1756
+ ancestryIndexes.set(currentStepId, ancestry.length);
1757
+ ancestry.push(currentStepId);
1758
+ const parentStepId = resolveParentStepId(currentStep, steps);
1759
+ if (parentStepId === void 0) {
1760
+ ancestry.pop();
1761
+ depthCache.set(currentStepId, ROOT_STEP_DEPTH);
1762
+ resolvedDepth = ROOT_STEP_DEPTH;
1763
+ continue;
1764
+ }
1765
+ currentStepId = parentStepId;
1766
+ }
1767
+ ancestry.reverse();
1768
+ for (const ancestorStepId of ancestry) {
1769
+ resolvedDepth = Math.min(MAX_RUN_SUMMARY_DEPTH, resolvedDepth + 1);
1770
+ depthCache.set(ancestorStepId, resolvedDepth);
1771
+ }
1772
+ return depthCache.get(stepId) ?? ROOT_STEP_DEPTH;
1773
+ }
1720
1774
  function buildRunSummary(events) {
1721
1775
  const started = events.find(
1722
1776
  (e) => e.event === "run_started"
@@ -1770,27 +1824,13 @@ function buildRunSummary(events) {
1770
1824
  let stepsWithKnownTotal = 0;
1771
1825
  let hasCachedTokens = false;
1772
1826
  const depthCache = /* @__PURE__ */ new Map();
1773
- const computeDepth = (stepId) => {
1774
- const cached = depthCache.get(stepId);
1775
- if (cached !== void 0) return cached;
1776
- const node = steps.get(stepId);
1777
- if (!node) return 0;
1778
- const parent = node.parentId;
1779
- if (typeof parent !== "string" || parent.trim() === "" || !steps.has(parent)) {
1780
- depthCache.set(stepId, 0);
1781
- return 0;
1782
- }
1783
- const d = Math.min(1e3, computeDepth(parent) + 1);
1784
- depthCache.set(stepId, d);
1785
- return d;
1786
- };
1787
1827
  for (const [id, s] of steps.entries()) {
1788
1828
  totalSteps += 1;
1789
1829
  if (s.type === "llm") llmSteps += 1;
1790
1830
  else if (s.type === "tool") toolSteps2 += 1;
1791
1831
  else logicSteps += 1;
1792
1832
  if (s.status === "error") errorSteps += 1;
1793
- const depth = computeDepth(id);
1833
+ const depth = computeStepDepth(id, steps, depthCache);
1794
1834
  if (depth > maxDepth) maxDepth = depth;
1795
1835
  if (typeof s.durationMs === "number" && Number.isFinite(s.durationMs)) {
1796
1836
  if (!longestStep || s.durationMs > longestStep.durationMs) {
@@ -6221,6 +6261,325 @@ function pickString(record, keys) {
6221
6261
  return void 0;
6222
6262
  }
6223
6263
 
6264
+ // packages/core/src/checks/derived-failure.ts
6265
+ function isRecord8(value) {
6266
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6267
+ }
6268
+ function pickString2(record, keys) {
6269
+ if (!record) return void 0;
6270
+ for (const key of keys) {
6271
+ const value = record[key];
6272
+ if (typeof value === "string" && value.trim() !== "") return value;
6273
+ }
6274
+ return void 0;
6275
+ }
6276
+ function pickNumber(record, keys) {
6277
+ if (!record) return void 0;
6278
+ for (const key of keys) {
6279
+ const value = record[key];
6280
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
6281
+ return value;
6282
+ }
6283
+ }
6284
+ return void 0;
6285
+ }
6286
+ function eventMetadata(event) {
6287
+ const attrs = isRecord8(event.attributes) ? event.attributes : void 0;
6288
+ const nested = attrs !== void 0 && isRecord8(attrs.metadata) ? attrs.metadata : void 0;
6289
+ return {
6290
+ ...attrs ?? {},
6291
+ ...nested ?? {}
6292
+ };
6293
+ }
6294
+ function canonicalName(event) {
6295
+ if (event.kind === "TOOL") return resolveCanonicalToolName(event);
6296
+ return event.name;
6297
+ }
6298
+ function linkKeys(event) {
6299
+ const meta = eventMetadata(event);
6300
+ const keys = [];
6301
+ for (const key of ["linkedStepId", "toolCallId", "mcpToolCallId"]) {
6302
+ const value = pickString2(meta, [key]);
6303
+ if (value !== void 0) keys.push(`${key}:${value}`);
6304
+ }
6305
+ const stepId = pickString2(meta, ["stepId"]);
6306
+ if (stepId !== void 0) keys.push(`stepId:${stepId}`);
6307
+ return keys;
6308
+ }
6309
+ function buildRunContexts(logicalEvents) {
6310
+ const byRun = /* @__PURE__ */ new Map();
6311
+ for (const event of logicalEvents) {
6312
+ const existing = byRun.get(event.runId) ?? {
6313
+ runId: event.runId,
6314
+ name: event.name
6315
+ };
6316
+ const meta = eventMetadata(event);
6317
+ if (event.kind === "RUN" || existing.name === event.runId) {
6318
+ existing.name = event.name || existing.name;
6319
+ }
6320
+ if (event.kind === "RUN" && event.status !== void 0 && event.status !== "running") {
6321
+ existing.status = event.status;
6322
+ }
6323
+ existing.retryOf ??= pickString2(meta, ["retryOf"]);
6324
+ existing.attempt ??= pickNumber(meta, ["attempt", "retryAttempt", "retryCount"]);
6325
+ existing.sessionId ??= pickString2(meta, ["sessionId", "conversationId"]);
6326
+ existing.groupId ??= pickString2(meta, ["groupId"]);
6327
+ existing.parentGroupId ??= pickString2(meta, ["parentGroupId"]);
6328
+ existing.fallbackOf ??= pickString2(meta, ["fallbackOf", "fallbackFrom"]);
6329
+ byRun.set(event.runId, existing);
6330
+ }
6331
+ return byRun;
6332
+ }
6333
+ function sameCorrelationScope(a, b) {
6334
+ if (a.sessionId && b.sessionId && a.sessionId === b.sessionId) return true;
6335
+ if (a.groupId && b.groupId && a.groupId === b.groupId) return true;
6336
+ if (a.parentGroupId && b.parentGroupId && a.parentGroupId === b.parentGroupId) {
6337
+ return true;
6338
+ }
6339
+ return false;
6340
+ }
6341
+ function isSuccessful(event) {
6342
+ return event.status === "ok";
6343
+ }
6344
+ function isFailure(event) {
6345
+ return event.status === "error";
6346
+ }
6347
+ function compareEventOrder(a, b) {
6348
+ const byTime = a.timestamp.localeCompare(b.timestamp);
6349
+ if (byTime !== 0) return byTime;
6350
+ return a.eventId.localeCompare(b.eventId);
6351
+ }
6352
+ function collectCandidates(failure, logicalEvents, runs) {
6353
+ const failureRun = runs.get(failure.runId);
6354
+ const failureLinks = new Set(linkKeys(failure));
6355
+ const failureName = canonicalName(failure);
6356
+ const failureAttempt = pickNumber(eventMetadata(failure), ["attempt", "retryAttempt", "retryCount"]) ?? failureRun?.attempt;
6357
+ const candidates = [];
6358
+ for (const event of logicalEvents) {
6359
+ if (event.eventId === failure.eventId) continue;
6360
+ if (event.status === "running") continue;
6361
+ const eventRun = runs.get(event.runId);
6362
+ const eventMeta = eventMetadata(event);
6363
+ const sameRun = event.runId === failure.runId;
6364
+ if (eventRun?.retryOf === failure.runId) {
6365
+ candidates.push({
6366
+ event,
6367
+ basis: "retryOf",
6368
+ confidence: "explicit",
6369
+ viaRunId: event.runId
6370
+ });
6371
+ continue;
6372
+ }
6373
+ if (eventRun?.fallbackOf === failure.runId || pickString2(eventMeta, ["fallbackOf", "fallbackFrom"]) === failure.runId) {
6374
+ candidates.push({
6375
+ event,
6376
+ basis: "fallbackOf",
6377
+ confidence: "explicit",
6378
+ viaRunId: event.runId
6379
+ });
6380
+ continue;
6381
+ }
6382
+ if (sameRun && compareEventOrder(failure, event) >= 0) continue;
6383
+ const eventLinks = linkKeys(event);
6384
+ const sharedLink = eventLinks.find((key) => failureLinks.has(key));
6385
+ if (sharedLink !== void 0) {
6386
+ candidates.push({
6387
+ event,
6388
+ basis: sharedLink.split(":")[0] ?? "linkedId",
6389
+ confidence: "explicit"
6390
+ });
6391
+ continue;
6392
+ }
6393
+ const eventAttempt = pickNumber(eventMeta, ["attempt", "retryAttempt", "retryCount"]) ?? eventRun?.attempt;
6394
+ const sameParent = failure.parentId !== void 0 && event.parentId !== void 0 && failure.parentId === event.parentId;
6395
+ const differentParent = failure.parentId !== void 0 && event.parentId !== void 0 && failure.parentId !== event.parentId;
6396
+ const sessionScoped = failureRun !== void 0 && eventRun !== void 0 && sameCorrelationScope(failureRun, eventRun);
6397
+ if (canonicalName(event) === failureName && failureAttempt !== void 0 && eventAttempt !== void 0 && eventAttempt > failureAttempt && !differentParent && (sameParent || sessionScoped || sameRun)) {
6398
+ candidates.push({
6399
+ event,
6400
+ basis: "attempt-progression",
6401
+ confidence: "correlated",
6402
+ ...event.runId !== failure.runId ? { viaRunId: event.runId } : {}
6403
+ });
6404
+ }
6405
+ }
6406
+ const byId = /* @__PURE__ */ new Map();
6407
+ for (const candidate of candidates) {
6408
+ const prev = byId.get(candidate.event.eventId);
6409
+ if (!prev || prev.confidence !== "explicit" && candidate.confidence === "explicit") {
6410
+ byId.set(candidate.event.eventId, candidate);
6411
+ }
6412
+ }
6413
+ return [...byId.values()].sort((a, b) => compareEventOrder(a.event, b.event));
6414
+ }
6415
+ function classifyFailure(failure, candidates, runs, logicalEvents) {
6416
+ const successful = candidates.filter((c) => isSuccessful(c.event));
6417
+ const unsuccessful = candidates.filter((c) => !isSuccessful(c.event));
6418
+ const retryRunIds = Object.freeze(
6419
+ [...new Set(candidates.map((c) => c.viaRunId).filter((id) => id !== void 0))].sort(
6420
+ (a, b) => a.localeCompare(b)
6421
+ )
6422
+ );
6423
+ if (successful.length > 1) {
6424
+ const distinctRuns = new Set(successful.map((c) => c.event.runId));
6425
+ const distinctParents = new Set(
6426
+ successful.map((c) => c.event.parentId ?? "").filter((id) => id !== "")
6427
+ );
6428
+ if (distinctRuns.size > 1 || distinctParents.size > 1) {
6429
+ return {
6430
+ eventId: failure.eventId,
6431
+ runId: failure.runId,
6432
+ name: failure.name,
6433
+ kind: failure.kind,
6434
+ role: "unknown",
6435
+ confidence: "unknown",
6436
+ basis: Object.freeze(["ambiguous-recovery-candidates"]),
6437
+ recoveryEventIds: Object.freeze(
6438
+ successful.map((c) => c.event.eventId).sort((a, b) => a.localeCompare(b))
6439
+ ),
6440
+ retryRunIds
6441
+ };
6442
+ }
6443
+ }
6444
+ if (successful.length >= 1) {
6445
+ const best = successful[0];
6446
+ return {
6447
+ eventId: failure.eventId,
6448
+ runId: failure.runId,
6449
+ name: failure.name,
6450
+ kind: failure.kind,
6451
+ role: "recovered",
6452
+ confidence: best.confidence,
6453
+ basis: Object.freeze([best.basis]),
6454
+ recoveryEventIds: Object.freeze(
6455
+ successful.map((c) => c.event.eventId).sort((a, b) => a.localeCompare(b))
6456
+ ),
6457
+ retryRunIds
6458
+ };
6459
+ }
6460
+ if (candidates.length > 0) {
6461
+ const best = candidates[0];
6462
+ return {
6463
+ eventId: failure.eventId,
6464
+ runId: failure.runId,
6465
+ name: failure.name,
6466
+ kind: failure.kind,
6467
+ role: "transient",
6468
+ confidence: best.confidence,
6469
+ basis: Object.freeze([
6470
+ best.basis,
6471
+ unsuccessful.some((c) => c.event.status === void 0) ? "retry-incomplete" : "retry-without-success"
6472
+ ]),
6473
+ recoveryEventIds: Object.freeze([]),
6474
+ retryRunIds
6475
+ };
6476
+ }
6477
+ const failureMeta = eventMetadata(failure);
6478
+ const declaredSuccessor = pickString2(failureMeta, [
6479
+ "retriedBy",
6480
+ "nextRetryRunId",
6481
+ "retryRunId"
6482
+ ]);
6483
+ if (declaredSuccessor !== void 0 && !runs.has(declaredSuccessor)) {
6484
+ return {
6485
+ eventId: failure.eventId,
6486
+ runId: failure.runId,
6487
+ name: failure.name,
6488
+ kind: failure.kind,
6489
+ role: "transient",
6490
+ confidence: "explicit",
6491
+ basis: Object.freeze(["retry-declared", "retry-run-missing"]),
6492
+ recoveryEventIds: Object.freeze([]),
6493
+ retryRunIds: Object.freeze([declaredSuccessor])
6494
+ };
6495
+ }
6496
+ for (const run of runs.values()) {
6497
+ if (run.retryOf === failure.runId) {
6498
+ return {
6499
+ eventId: failure.eventId,
6500
+ runId: failure.runId,
6501
+ name: failure.name,
6502
+ kind: failure.kind,
6503
+ role: "transient",
6504
+ confidence: "explicit",
6505
+ basis: Object.freeze(["retryOf", "retry-run-missing-or-empty"]),
6506
+ recoveryEventIds: Object.freeze([]),
6507
+ retryRunIds: Object.freeze([run.runId])
6508
+ };
6509
+ }
6510
+ }
6511
+ const failureRun = runs.get(failure.runId);
6512
+ const hasSuccessorDeclared = [...runs.values()].some((run) => run.retryOf === failure.runId);
6513
+ const isFinalInChain = failureRun !== void 0 && !hasSuccessorDeclared && (failureRun.retryOf !== void 0 || failureRun.attempt !== void 0 && failureRun.attempt > 1 || pickNumber(eventMetadata(failure), ["attempt"]) !== void 0);
6514
+ if (isFinalInChain && failureRun?.status === "error" && !logicalEvents.some(
6515
+ (event) => event.runId === failure.runId && event.eventId !== failure.eventId && isSuccessful(event) && canonicalName(event) === canonicalName(failure)
6516
+ )) {
6517
+ return {
6518
+ eventId: failure.eventId,
6519
+ runId: failure.runId,
6520
+ name: failure.name,
6521
+ kind: failure.kind,
6522
+ role: "terminal",
6523
+ confidence: failureRun.retryOf !== void 0 ? "explicit" : "correlated",
6524
+ basis: Object.freeze(["final-retry-chain-member", "enclosing-run-error"]),
6525
+ recoveryEventIds: Object.freeze([]),
6526
+ retryRunIds: Object.freeze(
6527
+ failureRun.retryOf !== void 0 ? [failureRun.retryOf] : []
6528
+ )
6529
+ };
6530
+ }
6531
+ return {
6532
+ eventId: failure.eventId,
6533
+ runId: failure.runId,
6534
+ name: failure.name,
6535
+ kind: failure.kind,
6536
+ role: "unknown",
6537
+ confidence: "unknown",
6538
+ basis: Object.freeze(["no-explicit-or-correlated-recovery"]),
6539
+ recoveryEventIds: Object.freeze([]),
6540
+ retryRunIds: Object.freeze([])
6541
+ };
6542
+ }
6543
+ function deriveFailureFacts(logicalEvents) {
6544
+ const runs = buildRunContexts(logicalEvents);
6545
+ const failures = logicalEvents.filter((event) => isFailure(event)).sort(compareEventOrder);
6546
+ const failureFacts = failures.map(
6547
+ (failure) => classifyFailure(failure, collectCandidates(failure, logicalEvents, runs), runs, logicalEvents)
6548
+ );
6549
+ const byRole = /* @__PURE__ */ new Map([
6550
+ ["transient", []],
6551
+ ["recovered", []],
6552
+ ["terminal", []],
6553
+ ["unknown", []]
6554
+ ]);
6555
+ for (const fact2 of failureFacts) {
6556
+ byRole.get(fact2.role).push(fact2);
6557
+ }
6558
+ for (const [role, list] of byRole) {
6559
+ byRole.set(
6560
+ role,
6561
+ Object.freeze(
6562
+ [...list].sort((a, b) => {
6563
+ const byRun = a.runId.localeCompare(b.runId);
6564
+ if (byRun !== 0) return byRun;
6565
+ return a.eventId.localeCompare(b.eventId);
6566
+ })
6567
+ )
6568
+ );
6569
+ }
6570
+ const failureRoleCounts = {
6571
+ transient: byRole.get("transient").length,
6572
+ recovered: byRole.get("recovered").length,
6573
+ terminal: byRole.get("terminal").length,
6574
+ unknown: byRole.get("unknown").length
6575
+ };
6576
+ return {
6577
+ failureFacts: Object.freeze(failureFacts),
6578
+ failuresByRole: byRole,
6579
+ failureRoleCounts
6580
+ };
6581
+ }
6582
+
6224
6583
  // packages/core/src/checks/trace-facts.ts
6225
6584
  function summarizeSemanticParity(events) {
6226
6585
  const projection = projectLogicalEvents(events);
@@ -6231,6 +6590,7 @@ function summarizeSemanticParity(events) {
6231
6590
  const finishedToolNames = Object.freeze(
6232
6591
  finishedTools.map((event) => resolveCanonicalToolName(event)).sort((a, b) => a.localeCompare(b))
6233
6592
  );
6593
+ const derived = deriveFailureFacts(logical);
6234
6594
  return {
6235
6595
  rawEventCount: events.length,
6236
6596
  logicalEventCount: logical.length,
@@ -6241,7 +6601,8 @@ function summarizeSemanticParity(events) {
6241
6601
  parentRemapCount: projection.diagnostics.filter(
6242
6602
  (item) => item.code === "AI_LOGICAL_PARENT_REMAPPED"
6243
6603
  ).length,
6244
- diagnostics: projection.diagnostics
6604
+ diagnostics: projection.diagnostics,
6605
+ failureRoleCounts: derived.failureRoleCounts
6245
6606
  };
6246
6607
  }
6247
6608
  formatProgrammaticDiagnostic(
@@ -6713,7 +7074,7 @@ function finishedEvents(context, kind) {
6713
7074
  function toolInvocationEvents(context) {
6714
7075
  return semanticEvents(context).filter((event) => event.kind === "TOOL");
6715
7076
  }
6716
- function isRecord8(value) {
7077
+ function isRecord9(value) {
6717
7078
  return typeof value === "object" && value !== null && !Array.isArray(value);
6718
7079
  }
6719
7080
  function eventMap(events) {
@@ -6764,7 +7125,7 @@ function pushValueEntries(entries, event, value, path14, key, depth = 0) {
6764
7125
  }
6765
7126
  return;
6766
7127
  }
6767
- if (!isRecord8(value)) return;
7128
+ if (!isRecord9(value)) return;
6768
7129
  for (const nestedKey of Object.keys(value).sort((a, b) => a.localeCompare(b))) {
6769
7130
  pushValueEntries(
6770
7131
  entries,
@@ -7590,7 +7951,7 @@ function createSafetyOversizedAttributeRule(options) {
7590
7951
  )
7591
7952
  );
7592
7953
  }
7593
- if (isRecord8(entry.value) && options.maxObjectKeys !== void 0 && Object.keys(entry.value).length > options.maxObjectKeys) {
7954
+ if (isRecord9(entry.value) && options.maxObjectKeys !== void 0 && Object.keys(entry.value).length > options.maxObjectKeys) {
7594
7955
  findings.push(
7595
7956
  failFinding(
7596
7957
  "safety.oversizedAttribute",
@@ -7882,14 +8243,14 @@ function runTraceChecks(input, options = {}) {
7882
8243
  }
7883
8244
 
7884
8245
  // packages/core/src/persisted/token-usage.ts
7885
- function isRecord9(value) {
8246
+ function isRecord10(value) {
7886
8247
  return typeof value === "object" && value !== null && !Array.isArray(value);
7887
8248
  }
7888
8249
  function nonNegativeFinite(value) {
7889
8250
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
7890
8251
  }
7891
8252
  function normalizeTokenUsage(value) {
7892
- if (!isRecord9(value)) return void 0;
8253
+ if (!isRecord10(value)) return void 0;
7893
8254
  const input = nonNegativeFinite(value.input);
7894
8255
  const output = nonNegativeFinite(value.output);
7895
8256
  const suppliedTotal = nonNegativeFinite(value.total);
@@ -8770,7 +9131,7 @@ function persistedEventsForParsedTrace(parsed) {
8770
9131
  sourceName: "agent-inspect-jsonl-reader"
8771
9132
  });
8772
9133
  }
8773
- function isRecord10(value) {
9134
+ function isRecord11(value) {
8774
9135
  return typeof value === "object" && value !== null && !Array.isArray(value);
8775
9136
  }
8776
9137
  function isNonEmptyString4(value) {
@@ -8785,13 +9146,13 @@ function readStringField(record, keys) {
8785
9146
  }
8786
9147
  function readRecordField(record, key) {
8787
9148
  const value = record[key];
8788
- return isRecord10(value) ? value : void 0;
9149
+ return isRecord11(value) ? value : void 0;
8789
9150
  }
8790
9151
  function parseJsonDocument(content) {
8791
9152
  return JSON.parse(content);
8792
9153
  }
8793
9154
  function looksLikeOpenInferenceSpan(value) {
8794
- if (!isRecord10(value)) return false;
9155
+ if (!isRecord11(value)) return false;
8795
9156
  const attributes = readRecordField(value, "attributes");
8796
9157
  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);
8797
9158
  }
@@ -8816,7 +9177,7 @@ function extractOpenInferenceDocument(root) {
8816
9177
  unsupportedFields
8817
9178
  };
8818
9179
  }
8819
- if (!isRecord10(root)) return void 0;
9180
+ if (!isRecord11(root)) return void 0;
8820
9181
  const rootFormat = root.format;
8821
9182
  const rootCompatibility = root.compatibility;
8822
9183
  const version = typeof root.version === "string" && root.version.trim() !== "" ? root.version : void 0;
@@ -8956,7 +9317,7 @@ function summarizeAttributeValue(value) {
8956
9317
  if (Array.isArray(value)) {
8957
9318
  return { type: "array", length: value.length };
8958
9319
  }
8959
- if (isRecord10(value)) {
9320
+ if (isRecord11(value)) {
8960
9321
  return { type: "object", keyCount: Object.keys(value).length };
8961
9322
  }
8962
9323
  if (value === null) {
@@ -9043,7 +9404,7 @@ function mapOpenInferenceKind(span, attributes, pathPrefix) {
9043
9404
  }
9044
9405
  }
9045
9406
  function mapOpenInferenceStatus(status) {
9046
- if (!isRecord10(status)) return void 0;
9407
+ if (!isRecord11(status)) return void 0;
9047
9408
  const rawCode = status.code;
9048
9409
  if (typeof rawCode !== "string") return void 0;
9049
9410
  switch (rawCode.toUpperCase()) {
@@ -9143,7 +9504,7 @@ function mapOpenInferenceSpan(span, index, version) {
9143
9504
  warnings.push(...kindWarnings);
9144
9505
  const status = mapOpenInferenceStatus(span.status);
9145
9506
  const tokenUsage = readOpenInferenceTokenUsage(rawAttributes);
9146
- const errorMessage = isRecord10(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
9507
+ const errorMessage = isRecord11(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
9147
9508
  const event = {
9148
9509
  schemaVersion: "0.2",
9149
9510
  eventId: typeof rawAttributes["agent_inspect.event_id"] === "string" ? rawAttributes["agent_inspect.event_id"] : spanId,
@@ -9289,7 +9650,7 @@ var openInferenceJsonReader = {
9289
9650
  }
9290
9651
  };
9291
9652
  function parseOtlpAnyValue(value, field, warnings, unsupportedFields) {
9292
- if (!isRecord10(value)) {
9653
+ if (!isRecord11(value)) {
9293
9654
  unsupportedFields.push(field);
9294
9655
  warnings.push({
9295
9656
  code: "otlp_attribute_value_invalid",
@@ -9311,15 +9672,15 @@ function parseOtlpAnyValue(value, field, warnings, unsupportedFields) {
9311
9672
  if (typeof value.doubleValue === "number" && Number.isFinite(value.doubleValue)) {
9312
9673
  return value.doubleValue;
9313
9674
  }
9314
- if (isRecord10(value.arrayValue) && Array.isArray(value.arrayValue.values)) {
9675
+ if (isRecord11(value.arrayValue) && Array.isArray(value.arrayValue.values)) {
9315
9676
  return value.arrayValue.values.map(
9316
9677
  (item, index) => parseOtlpAnyValue(item, `${field}.arrayValue.values[${index}]`, warnings, unsupportedFields)
9317
9678
  );
9318
9679
  }
9319
- if (isRecord10(value.kvlistValue) && Array.isArray(value.kvlistValue.values)) {
9680
+ if (isRecord11(value.kvlistValue) && Array.isArray(value.kvlistValue.values)) {
9320
9681
  const out = {};
9321
9682
  for (const [index, item] of value.kvlistValue.values.entries()) {
9322
- if (!isRecord10(item) || typeof item.key !== "string") {
9683
+ if (!isRecord11(item) || typeof item.key !== "string") {
9323
9684
  unsupportedFields.push(`${field}.kvlistValue.values[${index}]`);
9324
9685
  continue;
9325
9686
  }
@@ -9370,7 +9731,7 @@ function parseOtlpAttributes(value, pathPrefix) {
9370
9731
  }
9371
9732
  for (const [index, item] of value.entries()) {
9372
9733
  const field = `${pathPrefix}[${index}]`;
9373
- if (!isRecord10(item) || typeof item.key !== "string") {
9734
+ if (!isRecord11(item) || typeof item.key !== "string") {
9374
9735
  unsupportedFields.push(field);
9375
9736
  warnings.push({
9376
9737
  code: "otlp_attribute_invalid",
@@ -9393,16 +9754,16 @@ function parseOtlpAttributes(value, pathPrefix) {
9393
9754
  return { attributes, warnings, unsupportedFields };
9394
9755
  }
9395
9756
  function looksLikeOtlpSpan(value) {
9396
- return isRecord10(value) && readStringField(value, ["traceId"]) !== void 0 && readStringField(value, ["spanId"]) !== void 0 && readStringField(value, ["name"]) !== void 0;
9757
+ return isRecord11(value) && readStringField(value, ["traceId"]) !== void 0 && readStringField(value, ["spanId"]) !== void 0 && readStringField(value, ["name"]) !== void 0;
9397
9758
  }
9398
9759
  function extractOtlpDocument(root) {
9399
- if (!isRecord10(root) || !Array.isArray(root.resourceSpans)) return void 0;
9760
+ if (!isRecord11(root) || !Array.isArray(root.resourceSpans)) return void 0;
9400
9761
  const spans = [];
9401
9762
  const warnings = [];
9402
9763
  const unsupportedFields = [];
9403
9764
  for (const [resourceIndex, resourceSpan] of root.resourceSpans.entries()) {
9404
9765
  const resourcePath = `resourceSpans[${resourceIndex}]`;
9405
- if (!isRecord10(resourceSpan)) {
9766
+ if (!isRecord11(resourceSpan)) {
9406
9767
  unsupportedFields.push(resourcePath);
9407
9768
  continue;
9408
9769
  }
@@ -9425,7 +9786,7 @@ function extractOtlpDocument(root) {
9425
9786
  }
9426
9787
  for (const [scopeIndex, scopeSpan] of resourceSpan.scopeSpans.entries()) {
9427
9788
  const scopePath = `${resourcePath}.scopeSpans[${scopeIndex}]`;
9428
- if (!isRecord10(scopeSpan)) {
9789
+ if (!isRecord11(scopeSpan)) {
9429
9790
  unsupportedFields.push(scopePath);
9430
9791
  continue;
9431
9792
  }
@@ -9492,7 +9853,7 @@ function extractOtlpDocument(root) {
9492
9853
  };
9493
9854
  }
9494
9855
  function mapOtlpStatus(status) {
9495
- if (!isRecord10(status)) return void 0;
9856
+ if (!isRecord11(status)) return void 0;
9496
9857
  const rawCode = status.code;
9497
9858
  if (typeof rawCode !== "string") return void 0;
9498
9859
  switch (rawCode.toUpperCase()) {
@@ -9592,7 +9953,7 @@ function mapOtlpEvents(value, pathPrefix) {
9592
9953
  const events = [];
9593
9954
  for (const [index, event] of value.entries()) {
9594
9955
  const eventPath = `${pathPrefix}[${index}]`;
9595
- if (!isRecord10(event)) {
9956
+ if (!isRecord11(event)) {
9596
9957
  unsupportedFields.push(eventPath);
9597
9958
  continue;
9598
9959
  }
@@ -9730,7 +10091,7 @@ function mapOtlpSpan(context) {
9730
10091
  warnings.push(...kindWarnings);
9731
10092
  const status = mapOtlpStatus(span.status);
9732
10093
  const tokenUsage = readOtlpTokenUsage(parsedSpanAttributes.attributes);
9733
- const errorMessage = isRecord10(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
10094
+ const errorMessage = isRecord11(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
9734
10095
  const event = {
9735
10096
  schemaVersion: "0.2",
9736
10097
  eventId: typeof parsedSpanAttributes.attributes["agent_inspect.event_id"] === "string" ? parsedSpanAttributes.attributes["agent_inspect.event_id"] : spanId,
@@ -11420,5 +11781,5 @@ function renderGateReport(result, options = {}) {
11420
11781
  }
11421
11782
 
11422
11783
  export { COHORT_METRIC_IDS, DEFAULT_SUITE_ARTIFACTS_DIR, EVIDENCE_FORMAT_VERSION, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, Redactor, TraceDirectory, TraceReadError, TreeBuilder, aggregateBundleSafeStatus, aggregateSessionCheckResults, analyzeCohort, applyProfileMetadataCaps, assertBundlePathContained, assertEvidenceRelativePath, buildActivitySummary, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceCausalFailureViewHtml, buildEvidenceCiPackage, buildEvidenceCircuitViewHtml, buildEvidenceContractsViewHtml, buildEvidenceDiffViewHtml, buildEvidenceHtmlShell, buildEvidenceManifest, buildEvidenceOutcomesViewHtml, buildEvidenceProvenanceViewHtml, buildEvidenceSafetyViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceTreeViewHtml, buildLocalExplanation, buildPlaceholderArtifact, buildRunSummary, buildRunTimeline, buildRunWhatSummary, buildSessionIndex, buildTraceStats, buildZipArchive, bundleFailsOnSafety, bundleRunAssetRelativePath, collectTraceSchemaVersions, compactAttributes, createBaselineRegressionRule, createLlmUsageRule, createMaxStepDurationRule, createObservedOutcomeRule, createRequireCompletedRule, createRunDepthRule, createRunDurationRule, createRunStatusRule, createSafetyOversizedAttributeRule, createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createStallDetectionRule, createStructureCycleRule, createStructureOrphanRule, createStructureParallelWidthRule, createStructureRelationshipRule, createToolUsageRule, defaultBundleOutputPath, defaultSuiteConfigTemplate, diffRuns, diffTraceEvents, enrichSessionRunRecord, escapeHtml, escapeMarkdown, extractMetadata, extractOutcomesFromTraceEvents, filterMetasBySessionScope, filterTraces, flattenTree, formatDuration2 as formatDuration, formatStepLabel, formatTimestamp, gateHasThresholds, getIndent, getTraceFilePath, inferEvidenceFileRole, isAgentInspectTrace, isPersistedInspectEvent, loadSessionRunRecords, loadSuiteConfig, loadTraceMetadataList, manualTraceEventsToComparableRun, nanoid, normalizeBundleOutputPath, openTrace, parseCohortMetricList, parseDuration, parseDurationFilter, parseGateList, parseTraceJsonl, persistedInspectEventsToTraceEvents, renderActivitySummaryHuman, renderCohortReport, renderErrorLine, renderGateReport, renderObservedOutcomesHtml, renderObservedOutcomesMarkdown, renderRunDiff, renderRunWhat, renderStepLine, renderSuiteReport, renderTimeline, renderTraceStats, resolveBundleRunIds, resolveRedactionProfile, resolveSuiteTemplate, resolveTraceDir, runGate, runSuite, runTraceChecks, safeString, sanitizeBundleRunId, searchTraces, serializeEvidenceManifest, sha256Hex, stableJson, summarizeObservedOutcomes, summarizeSemanticParity, traceEventToPersistedInspectEvent, truncateName, truncateStringForProfile, validateEvent, validateSuiteConfig, verifyEvidenceDirectory, zeroKinds };
11423
- //# sourceMappingURL=chunk-S4TLTLXN.mjs.map
11424
- //# sourceMappingURL=chunk-S4TLTLXN.mjs.map
11784
+ //# sourceMappingURL=chunk-QDYVK4MF.mjs.map
11785
+ //# sourceMappingURL=chunk-QDYVK4MF.mjs.map