agent-inspect 6.31.21 → 6.31.22

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 (47) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +1 -1
  3. package/package.json +1 -1
  4. package/packages/cli/dist/{chunk-N5JN26MW.mjs → chunk-EMWA5EKU.mjs} +300 -31
  5. package/packages/cli/dist/chunk-EMWA5EKU.mjs.map +1 -0
  6. package/packages/cli/dist/index.cjs +379 -56
  7. package/packages/cli/dist/index.cjs.map +1 -1
  8. package/packages/cli/dist/index.mjs +75 -31
  9. package/packages/cli/dist/index.mjs.map +1 -1
  10. package/packages/cli/dist/{src-VMGRSTG7.mjs → src-VZHGOLTO.mjs} +3 -3
  11. package/packages/cli/dist/{src-VMGRSTG7.mjs.map → src-VZHGOLTO.mjs.map} +1 -1
  12. package/packages/core/dist/advanced.cjs +247 -5
  13. package/packages/core/dist/advanced.cjs.map +1 -1
  14. package/packages/core/dist/advanced.mjs +6 -5
  15. package/packages/core/dist/advanced.mjs.map +1 -1
  16. package/packages/core/dist/checks.cjs +160 -27
  17. package/packages/core/dist/checks.cjs.map +1 -1
  18. package/packages/core/dist/checks.mjs +2 -1
  19. package/packages/core/dist/chunk-GCZUWY47.mjs +182 -0
  20. package/packages/core/dist/chunk-GCZUWY47.mjs.map +1 -0
  21. package/packages/core/dist/{chunk-JE3TUFAQ.mjs → chunk-RBXD7BNX.mjs} +3 -3
  22. package/packages/core/dist/{chunk-JE3TUFAQ.mjs.map → chunk-RBXD7BNX.mjs.map} +1 -1
  23. package/packages/core/dist/{chunk-YU6XT5A2.mjs → chunk-S4NU55LU.mjs} +45 -3
  24. package/packages/core/dist/chunk-S4NU55LU.mjs.map +1 -0
  25. package/packages/core/dist/{chunk-EIP5CNEL.mjs → chunk-UPGBMRL4.mjs} +49 -3
  26. package/packages/core/dist/chunk-UPGBMRL4.mjs.map +1 -0
  27. package/packages/core/dist/{chunk-4CDX5GDS.mjs → chunk-ZOF6ON65.mjs} +104 -99
  28. package/packages/core/dist/chunk-ZOF6ON65.mjs.map +1 -0
  29. package/packages/core/dist/exporters.cjs +82 -27
  30. package/packages/core/dist/exporters.cjs.map +1 -1
  31. package/packages/core/dist/exporters.mjs +72 -27
  32. package/packages/core/dist/exporters.mjs.map +1 -1
  33. package/packages/core/dist/logs.cjs +197 -1
  34. package/packages/core/dist/logs.cjs.map +1 -1
  35. package/packages/core/dist/logs.mjs +3 -2
  36. package/packages/core/dist/logs.mjs.map +1 -1
  37. package/packages/core/dist/persisted.cjs +197 -1
  38. package/packages/core/dist/persisted.cjs.map +1 -1
  39. package/packages/core/dist/persisted.mjs +4 -3
  40. package/packages/core/dist/persisted.mjs.map +1 -1
  41. package/packages/core/dist/readers.cjs +243 -1
  42. package/packages/core/dist/readers.cjs.map +1 -1
  43. package/packages/core/dist/readers.mjs +4 -3
  44. package/packages/cli/dist/chunk-N5JN26MW.mjs.map +0 -1
  45. package/packages/core/dist/chunk-4CDX5GDS.mjs.map +0 -1
  46. package/packages/core/dist/chunk-EIP5CNEL.mjs.map +0 -1
  47. package/packages/core/dist/chunk-YU6XT5A2.mjs.map +0 -1
@@ -2,6 +2,7 @@ import { OBSERVED_OUTCOME_METHODS, extractOutcomesFromPersistedEvents, outcomesM
2
2
  import { DEFAULT_CREDENTIAL_SENSITIVE_KEYS, isCredentialSensitiveKey } from './chunk-VLVCLAPB.mjs';
3
3
  import { projectLogicalEvents, resolveCanonicalToolName } from './chunk-AHUZNHFI.mjs';
4
4
  import { formatProgrammaticDiagnostic } from './chunk-S6LQBLX5.mjs';
5
+ import { canonicalStructuredEqual, hasDeliveryConflictMarker, deliverySemanticFingerprint, encodeCanonicalStructured } from './chunk-GCZUWY47.mjs';
5
6
  import { isAttributionConfidence, ATTRIBUTION_CONFIDENCES, ATTRIBUTION_CONFIDENCE_RANK } from './chunk-EE5Z2GQ3.mjs';
6
7
 
7
8
  // packages/core/src/sessions/metadata.ts
@@ -976,76 +977,6 @@ function evaluateControlRules(events, rules, runEvidence2, observationNames) {
976
977
  return findings;
977
978
  }
978
979
 
979
- // packages/core/src/checks/canonical-equality.ts
980
- var DEFAULT_MAX_DEPTH = 8;
981
- var DEFAULT_MAX_BYTES = 16384;
982
- function sortKeysDeep(input, depth, maxDepth) {
983
- if (depth > maxDepth) {
984
- throw new Error("AI_CHECK_CANONICAL_DEPTH_EXCEEDED");
985
- }
986
- if (input === null || typeof input !== "object") return input;
987
- if (Array.isArray(input)) {
988
- return input.map((item) => sortKeysDeep(item, depth + 1, maxDepth));
989
- }
990
- const record = input;
991
- const out = {};
992
- for (const key of Object.keys(record).sort()) {
993
- out[key] = sortKeysDeep(record[key], depth + 1, maxDepth);
994
- }
995
- return out;
996
- }
997
- function encodeCanonicalStructured(value, limits) {
998
- const maxDepth = DEFAULT_MAX_DEPTH;
999
- const maxBytes = DEFAULT_MAX_BYTES;
1000
- try {
1001
- const sorted = sortKeysDeep(value, 0, maxDepth);
1002
- const encoded = JSON.stringify(sorted);
1003
- if (encoded === void 0) {
1004
- return {
1005
- ok: false,
1006
- reason: "Value is not JSON-serializable for canonical comparison.",
1007
- code: "AI_CHECK_CANONICAL_UNSERIALIZABLE"
1008
- };
1009
- }
1010
- if (Buffer.byteLength(encoded, "utf8") > maxBytes) {
1011
- return {
1012
- ok: false,
1013
- reason: "Canonical structured value exceeds bounded size limit.",
1014
- code: "AI_CHECK_CANONICAL_SIZE_EXCEEDED"
1015
- };
1016
- }
1017
- return { ok: true, value: encoded };
1018
- } catch (error) {
1019
- const message = error instanceof Error ? error.message : String(error);
1020
- if (message === "AI_CHECK_CANONICAL_DEPTH_EXCEEDED") {
1021
- return {
1022
- ok: false,
1023
- reason: "Canonical structured value exceeds bounded depth limit.",
1024
- code: "AI_CHECK_CANONICAL_DEPTH_EXCEEDED"
1025
- };
1026
- }
1027
- return {
1028
- ok: false,
1029
- reason: "Canonical structured encoding failed.",
1030
- code: "AI_CHECK_CANONICAL_UNSERIALIZABLE"
1031
- };
1032
- }
1033
- }
1034
- function canonicalStructuredEqual(left, right, limits) {
1035
- const a = encodeCanonicalStructured(left);
1036
- if (!a.ok) return { equal: false, reason: a.reason, code: a.code };
1037
- const b = encodeCanonicalStructured(right);
1038
- if (!b.ok) return { equal: false, reason: b.reason, code: b.code };
1039
- if (a.value !== b.value) {
1040
- return {
1041
- equal: false,
1042
- reason: "Canonical structured values differ.",
1043
- code: "AI_CHECK_CANONICAL_NOT_EQUAL"
1044
- };
1045
- }
1046
- return { equal: true };
1047
- }
1048
-
1049
980
  // packages/core/src/checks/tool-arguments.ts
1050
981
  function decodeToken(token) {
1051
982
  return token.replace(/~1/g, "/").replace(/~0/g, "~");
@@ -1241,7 +1172,7 @@ function attemptIdOf(event) {
1241
1172
  }
1242
1173
  function countOperationAttempts(members) {
1243
1174
  const identified = /* @__PURE__ */ new Set();
1244
- let unidentified = 0;
1175
+ const unidentifiedFingerprints = /* @__PURE__ */ new Set();
1245
1176
  for (const event of members) {
1246
1177
  if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1247
1178
  const id = attemptIdOf(event);
@@ -1249,13 +1180,13 @@ function countOperationAttempts(members) {
1249
1180
  identified.add(id);
1250
1181
  continue;
1251
1182
  }
1252
- unidentified += 1;
1183
+ unidentifiedFingerprints.add(redeliveryFingerprint(event));
1253
1184
  }
1254
1185
  if (identified.size > 0) {
1255
- return identified.size + unidentified;
1186
+ return identified.size + unidentifiedFingerprints.size;
1256
1187
  }
1257
1188
  const numbered = /* @__PURE__ */ new Set();
1258
- let unnumbered = 0;
1189
+ const unnumberedFingerprints = /* @__PURE__ */ new Set();
1259
1190
  for (const event of members) {
1260
1191
  if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1261
1192
  const num = attemptNumberOf(event);
@@ -1263,12 +1194,12 @@ function countOperationAttempts(members) {
1263
1194
  numbered.add(num);
1264
1195
  continue;
1265
1196
  }
1266
- unnumbered += 1;
1197
+ unnumberedFingerprints.add(redeliveryFingerprint(event));
1267
1198
  }
1268
1199
  if (numbered.size > 0) {
1269
- return numbered.size + unnumbered;
1200
+ return numbered.size + unnumberedFingerprints.size;
1270
1201
  }
1271
- return unnumbered;
1202
+ return unnumberedFingerprints.size;
1272
1203
  }
1273
1204
  function classifyRetryAttempt(event, priorOrdered, allMembers) {
1274
1205
  const workflow = workflowFor(event);
@@ -1320,19 +1251,49 @@ function classifyRetryAttempt(event, priorOrdered, allMembers) {
1320
1251
  }
1321
1252
  function redeliveryFingerprint(event) {
1322
1253
  const workflow = workflowFor(event);
1323
- const stableEventId = (event.eventId ?? "").replace(/:\d+$/, "");
1324
- return JSON.stringify({
1325
- stableEventId,
1254
+ return deliverySemanticFingerprint({
1255
+ eventId: event.eventId ?? "",
1326
1256
  runId: event.runId,
1327
1257
  kind: event.kind,
1328
1258
  name: event.name,
1329
1259
  status: event.status,
1260
+ parentId: event.parentId,
1261
+ timestamp: event.timestamp,
1262
+ startedAt: event.startedAt,
1263
+ sourceType: event.source?.type,
1264
+ attributes: event.attributes && typeof event.attributes === "object" ? event.attributes : void 0,
1330
1265
  operationId: workflow.operationId ?? null,
1331
1266
  attemptId: workflow.attemptId ?? null,
1332
1267
  attemptNumber: workflow.attemptNumber ?? null,
1333
1268
  retryOf: workflow.retryOf ?? null
1334
1269
  });
1335
1270
  }
1271
+ var IDENTITY_KEYS = ["operationId", "attemptId", "retryOf", "attemptNumber"];
1272
+ function identityValuesEqual(a, b) {
1273
+ if (typeof a === "number" && typeof b === "number") {
1274
+ return Number.isFinite(a) && Number.isFinite(b) && a === b;
1275
+ }
1276
+ if (typeof a === "string" && typeof b === "string") {
1277
+ return a.trim() === b.trim();
1278
+ }
1279
+ return a === b;
1280
+ }
1281
+ function directNestedIdentityConflicts(event) {
1282
+ const attrs2 = event.attributes;
1283
+ if (!attrs2 || typeof attrs2 !== "object") return [];
1284
+ const nested = attrs2.metadata && typeof attrs2.metadata === "object" && !Array.isArray(attrs2.metadata) ? attrs2.metadata : void 0;
1285
+ if (!nested) return [];
1286
+ const conflicts = [];
1287
+ for (const key of IDENTITY_KEYS) {
1288
+ const direct = attrs2[key];
1289
+ const nestedValue = nested[key];
1290
+ if (direct === void 0 || nestedValue === void 0) continue;
1291
+ if (!identityValuesEqual(direct, nestedValue)) {
1292
+ conflicts.push(key);
1293
+ }
1294
+ }
1295
+ return conflicts;
1296
+ }
1336
1297
  function hasConflictingAttemptIdReuse(members) {
1337
1298
  const byAttempt = /* @__PURE__ */ new Map();
1338
1299
  for (const event of members) {
@@ -1348,6 +1309,31 @@ function hasConflictingAttemptIdReuse(members) {
1348
1309
  }
1349
1310
  return false;
1350
1311
  }
1312
+ function hasConflictingEventIdReuse(members) {
1313
+ const byEventId = /* @__PURE__ */ new Map();
1314
+ for (const event of members) {
1315
+ if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1316
+ const eventId = event.eventId;
1317
+ if (!eventId) continue;
1318
+ if (hasDeliveryConflictMarker(event.attributes)) {
1319
+ return true;
1320
+ }
1321
+ const fingerprints = byEventId.get(eventId) ?? /* @__PURE__ */ new Set();
1322
+ fingerprints.add(redeliveryFingerprint(event));
1323
+ byEventId.set(eventId, fingerprints);
1324
+ }
1325
+ for (const fingerprints of byEventId.values()) {
1326
+ if (fingerprints.size > 1) return true;
1327
+ }
1328
+ return false;
1329
+ }
1330
+ function hasIdentityRepresentationConflict(members) {
1331
+ for (const event of members) {
1332
+ if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1333
+ if (directNestedIdentityConflicts(event).length > 0) return true;
1334
+ }
1335
+ return false;
1336
+ }
1351
1337
  function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1352
1338
  const findings = [];
1353
1339
  const byOperation = /* @__PURE__ */ new Map();
@@ -1355,13 +1341,14 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1355
1341
  const workflow = workflowFor(event);
1356
1342
  const operationId = workflow.operationId;
1357
1343
  if (!operationId) continue;
1358
- const list = byOperation.get(operationId) ?? [];
1359
- list.push(event);
1360
- byOperation.set(operationId, list);
1344
+ const key = `${event.runId}\0${operationId}`;
1345
+ const group = byOperation.get(key) ?? { operationId, members: [] };
1346
+ group.members.push(event);
1347
+ byOperation.set(key, group);
1361
1348
  }
1362
1349
  if (rules.maxAttempts !== void 0) {
1363
- for (const [operationId, members] of byOperation) {
1364
- if (hasConflictingAttemptIdReuse(members)) {
1350
+ for (const { operationId, members } of byOperation.values()) {
1351
+ if (hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members)) {
1365
1352
  findings.push(
1366
1353
  fail2(
1367
1354
  "contract.retry.duplicate-attempt-id",
@@ -1372,6 +1359,31 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1372
1359
  )
1373
1360
  );
1374
1361
  }
1362
+ if (hasIdentityRepresentationConflict(members)) {
1363
+ findings.push(
1364
+ fail2(
1365
+ "contract.retry.ambiguous-identity",
1366
+ `Operation ${operationId} has conflicting direct vs nested identity fields; strict identity cannot pass.`,
1367
+ members.slice(0, 4).map(eventEvidence),
1368
+ "agreeing identity representation",
1369
+ "direct/nested conflict"
1370
+ )
1371
+ );
1372
+ }
1373
+ const toolish = members.filter((event) => event.kind === "TOOL" || event.kind === "LLM");
1374
+ const hasAttemptId = toolish.some((event) => attemptIdOf(event) !== void 0);
1375
+ const missingAttemptId = toolish.some((event) => attemptIdOf(event) === void 0);
1376
+ if (hasAttemptId && missingAttemptId) {
1377
+ findings.push(
1378
+ fail2(
1379
+ "contract.retry.ambiguous-identity",
1380
+ `Operation ${operationId} has partial attempt identity; strict identity conformance cannot pass.`,
1381
+ members.slice(0, 4).map(eventEvidence),
1382
+ "complete attempt identity",
1383
+ "partial attemptId coverage"
1384
+ )
1385
+ );
1386
+ }
1375
1387
  const count = countOperationAttempts(members);
1376
1388
  if (count > rules.maxAttempts) {
1377
1389
  findings.push(
@@ -1387,7 +1399,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1387
1399
  }
1388
1400
  }
1389
1401
  if (rules.requireTerminalResult) {
1390
- for (const [operationId, members] of byOperation) {
1402
+ for (const { operationId, members } of byOperation.values()) {
1391
1403
  const hasTerminal = members.some((event) => event.status === "ok" || event.status === "error");
1392
1404
  if (!hasTerminal) {
1393
1405
  findings.push(
@@ -1407,7 +1419,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1407
1419
  const workflow = workflowFor(event);
1408
1420
  const fallbackOf = workflow.fallbackOf;
1409
1421
  if (!fallbackOf) continue;
1410
- const prior = byOperation.get(fallbackOf) ?? [];
1422
+ const prior = byOperation.get(`${event.runId}\0${fallbackOf}`)?.members ?? [];
1411
1423
  const fallbackStart = eventTime(event);
1412
1424
  const earlierFailure = prior.some(
1413
1425
  (candidate) => candidate.status === "error" && eventTime(candidate) !== "" && fallbackStart !== "" && eventTime(candidate) < fallbackStart
@@ -1434,7 +1446,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1434
1446
  for (const event of toolEvents) {
1435
1447
  const name = resolveCanonicalToolName(event);
1436
1448
  const workflow = workflowFor(event);
1437
- const key = `${workflow.operationId ?? name}::${name}`;
1449
+ const key = `${event.runId}::${workflow.operationId ?? name}::${name}`;
1438
1450
  const list = byToolOp.get(key) ?? [];
1439
1451
  list.push(event);
1440
1452
  byToolOp.set(key, list);
@@ -1492,7 +1504,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1492
1504
  }
1493
1505
  }
1494
1506
  if (rules.requireRecoveredFailureVisible) {
1495
- for (const [operationId, members] of byOperation) {
1507
+ for (const { operationId, members } of byOperation.values()) {
1496
1508
  const ordered = sortByTime(members);
1497
1509
  const toolish = ordered.filter(
1498
1510
  (event) => (event.kind === "TOOL" || event.kind === "LLM") && (event.status === "ok" || event.status === "error")
@@ -1751,14 +1763,7 @@ function attemptIdOf2(event) {
1751
1763
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
1752
1764
  }
1753
1765
  function hasDuplicateAttemptIds(members) {
1754
- const seen = /* @__PURE__ */ new Set();
1755
- for (const event of members) {
1756
- const id = attemptIdOf2(event);
1757
- if (!id) continue;
1758
- if (seen.has(id)) return true;
1759
- seen.add(id);
1760
- }
1761
- return false;
1766
+ return hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members);
1762
1767
  }
1763
1768
  function findRetryTarget(members, retryOf) {
1764
1769
  return members.find(
@@ -5338,5 +5343,5 @@ function runTraceChecks(input, options = {}) {
5338
5343
  }
5339
5344
 
5340
5345
  export { buildTraceFacts, createBaselineRegressionRule, createDecisionRule, createGuardrailRule, createLlmUsageRule, createMaxStepDurationRule, createObservedOutcomeRule, createRequireCompletedRule, createRetrievalRule, createRunDepthRule, createRunDurationRule, createRunEventCountRule, createRunStatusRule, createSafetyOversizedAttributeRule, createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createStallDetectionRule, createStepOrderingRule, createStructureCycleRule, createStructureIncompleteRule, createStructureOrphanRule, createStructureParallelWidthRule, createStructureRelationshipRule, createToolFailureRule, createToolOrderingRule, createToolUsageRule, defineTraceContract, deriveFailureFacts, deriveRelationshipFacts, evaluateToolArgumentValue, evaluateTraceContract, evaluateTraceContractRead, explainTraceContract, extractSessionWorkflowMetadata, extractToolArgumentPayload, lintTraceContract, resolveJsonPointer, resolveTraceContractScope, runTraceChecks, sessionKeyForRun, summarizeSemanticParity, workflowMetadataForRun };
5341
- //# sourceMappingURL=chunk-4CDX5GDS.mjs.map
5342
- //# sourceMappingURL=chunk-4CDX5GDS.mjs.map
5346
+ //# sourceMappingURL=chunk-ZOF6ON65.mjs.map
5347
+ //# sourceMappingURL=chunk-ZOF6ON65.mjs.map