agent-inspect 6.31.20 → 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 +12 -0
  2. package/README.md +1 -1
  3. package/package.json +1 -1
  4. package/packages/cli/dist/{chunk-EVSIYDB2.mjs → chunk-EMWA5EKU.mjs} +324 -35
  5. package/packages/cli/dist/chunk-EMWA5EKU.mjs.map +1 -0
  6. package/packages/cli/dist/index.cjs +403 -60
  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-NWDDK72G.mjs → src-VZHGOLTO.mjs} +3 -3
  11. package/packages/cli/dist/{src-NWDDK72G.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 +184 -31
  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-GFQPPNSF.mjs → chunk-ZOF6ON65.mjs} +128 -103
  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-EVSIYDB2.mjs.map +0 -1
  45. package/packages/core/dist/chunk-EIP5CNEL.mjs.map +0 -1
  46. package/packages/core/dist/chunk-GFQPPNSF.mjs.map +0 -1
  47. package/packages/core/dist/chunk-YU6XT5A2.mjs.map +0 -1
@@ -1704,6 +1704,65 @@ function evaluateToolArgumentValue(value, check, evidencePresent) {
1704
1704
  };
1705
1705
  }
1706
1706
 
1707
+ // packages/core/src/persisted/delivery-identity.ts
1708
+ var DELIVERY_CONFLICT_ATTR = "agent_inspect.delivery_conflict";
1709
+ var SYNTHETIC_DELIVERY_ID = /^(?:manual|inspect):[A-Za-z0-9_-]+:[A-Za-z0-9_-]+:[A-Za-z0-9_-]+:\d+$/;
1710
+ function stripReaderDeliveryDiscriminator(eventId) {
1711
+ if (!SYNTHETIC_DELIVERY_ID.test(eventId)) return eventId;
1712
+ return eventId.replace(/:\d+$/, "");
1713
+ }
1714
+ function canonicalDigest(value) {
1715
+ if (value === void 0) return null;
1716
+ const encoded = encodeCanonicalStructured(value);
1717
+ return encoded.ok ? encoded.value : `unencodable:${encoded.code}`;
1718
+ }
1719
+ function capturedContentDigest(attributes) {
1720
+ if (!attributes || typeof attributes !== "object") {
1721
+ return { args: null, result: null };
1722
+ }
1723
+ const nested = attributes.metadata && typeof attributes.metadata === "object" ? attributes.metadata : void 0;
1724
+ const args = attributes.arguments ?? attributes.args ?? attributes.input ?? nested?.arguments ?? nested?.args ?? nested?.input;
1725
+ const result = attributes.result ?? attributes.output ?? attributes.response ?? nested?.result ?? nested?.output ?? nested?.response;
1726
+ return {
1727
+ args: args === void 0 ? null : canonicalDigest(args),
1728
+ result: result === void 0 ? null : canonicalDigest(result)
1729
+ };
1730
+ }
1731
+ function timeKey(fields) {
1732
+ if (typeof fields.startedAt === "string" && fields.startedAt.trim() !== "") {
1733
+ return fields.startedAt;
1734
+ }
1735
+ if (typeof fields.timestamp === "string" && fields.timestamp.trim() !== "") {
1736
+ return fields.timestamp;
1737
+ }
1738
+ if (typeof fields.timestamp === "number" && Number.isFinite(fields.timestamp)) {
1739
+ return String(fields.timestamp);
1740
+ }
1741
+ return null;
1742
+ }
1743
+ function deliverySemanticFingerprint(fields) {
1744
+ const content = capturedContentDigest(fields.attributes);
1745
+ return JSON.stringify({
1746
+ stableEventId: stripReaderDeliveryDiscriminator(fields.eventId),
1747
+ runId: fields.runId,
1748
+ kind: fields.kind,
1749
+ name: fields.name,
1750
+ status: fields.status ?? null,
1751
+ parentId: fields.parentId ?? null,
1752
+ sourceType: fields.sourceType ?? null,
1753
+ time: timeKey(fields),
1754
+ operationId: fields.operationId ?? null,
1755
+ attemptId: fields.attemptId ?? null,
1756
+ attemptNumber: fields.attemptNumber ?? null,
1757
+ retryOf: fields.retryOf ?? null,
1758
+ argsDigest: content.args,
1759
+ resultDigest: content.result
1760
+ });
1761
+ }
1762
+ function hasDeliveryConflictMarker(attributes) {
1763
+ return attributes?.[DELIVERY_CONFLICT_ATTR] === true;
1764
+ }
1765
+
1707
1766
  // packages/core/src/checks/retry-safety.ts
1708
1767
  function fail2(ruleId, message, evidence, expected, actual) {
1709
1768
  return {
@@ -1759,7 +1818,7 @@ function attemptIdOf(event) {
1759
1818
  }
1760
1819
  function countOperationAttempts(members) {
1761
1820
  const identified = /* @__PURE__ */ new Set();
1762
- let unidentified = 0;
1821
+ const unidentifiedFingerprints = /* @__PURE__ */ new Set();
1763
1822
  for (const event of members) {
1764
1823
  if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1765
1824
  const id = attemptIdOf(event);
@@ -1767,13 +1826,13 @@ function countOperationAttempts(members) {
1767
1826
  identified.add(id);
1768
1827
  continue;
1769
1828
  }
1770
- unidentified += 1;
1829
+ unidentifiedFingerprints.add(redeliveryFingerprint(event));
1771
1830
  }
1772
1831
  if (identified.size > 0) {
1773
- return identified.size + unidentified;
1832
+ return identified.size + unidentifiedFingerprints.size;
1774
1833
  }
1775
1834
  const numbered = /* @__PURE__ */ new Set();
1776
- let unnumbered = 0;
1835
+ const unnumberedFingerprints = /* @__PURE__ */ new Set();
1777
1836
  for (const event of members) {
1778
1837
  if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1779
1838
  const num = attemptNumberOf(event);
@@ -1781,12 +1840,12 @@ function countOperationAttempts(members) {
1781
1840
  numbered.add(num);
1782
1841
  continue;
1783
1842
  }
1784
- unnumbered += 1;
1843
+ unnumberedFingerprints.add(redeliveryFingerprint(event));
1785
1844
  }
1786
1845
  if (numbered.size > 0) {
1787
- return numbered.size + unnumbered;
1846
+ return numbered.size + unnumberedFingerprints.size;
1788
1847
  }
1789
- return unnumbered;
1848
+ return unnumberedFingerprints.size;
1790
1849
  }
1791
1850
  function classifyRetryAttempt(event, priorOrdered, allMembers) {
1792
1851
  const workflow = workflowFor(event);
@@ -1836,13 +1895,88 @@ function classifyRetryAttempt(event, priorOrdered, allMembers) {
1836
1895
  }
1837
1896
  return { kind: "unknown", reason: "ambiguous attempt identity" };
1838
1897
  }
1839
- function hasDuplicateAttemptIds(members) {
1840
- const seen = /* @__PURE__ */ new Set();
1898
+ function redeliveryFingerprint(event) {
1899
+ const workflow = workflowFor(event);
1900
+ return deliverySemanticFingerprint({
1901
+ eventId: event.eventId ?? "",
1902
+ runId: event.runId,
1903
+ kind: event.kind,
1904
+ name: event.name,
1905
+ status: event.status,
1906
+ parentId: event.parentId,
1907
+ timestamp: event.timestamp,
1908
+ startedAt: event.startedAt,
1909
+ sourceType: event.source?.type,
1910
+ attributes: event.attributes && typeof event.attributes === "object" ? event.attributes : void 0,
1911
+ operationId: workflow.operationId ?? null,
1912
+ attemptId: workflow.attemptId ?? null,
1913
+ attemptNumber: workflow.attemptNumber ?? null,
1914
+ retryOf: workflow.retryOf ?? null
1915
+ });
1916
+ }
1917
+ var IDENTITY_KEYS = ["operationId", "attemptId", "retryOf", "attemptNumber"];
1918
+ function identityValuesEqual(a, b) {
1919
+ if (typeof a === "number" && typeof b === "number") {
1920
+ return Number.isFinite(a) && Number.isFinite(b) && a === b;
1921
+ }
1922
+ if (typeof a === "string" && typeof b === "string") {
1923
+ return a.trim() === b.trim();
1924
+ }
1925
+ return a === b;
1926
+ }
1927
+ function directNestedIdentityConflicts(event) {
1928
+ const attrs2 = event.attributes;
1929
+ if (!attrs2 || typeof attrs2 !== "object") return [];
1930
+ const nested = attrs2.metadata && typeof attrs2.metadata === "object" && !Array.isArray(attrs2.metadata) ? attrs2.metadata : void 0;
1931
+ if (!nested) return [];
1932
+ const conflicts = [];
1933
+ for (const key of IDENTITY_KEYS) {
1934
+ const direct = attrs2[key];
1935
+ const nestedValue = nested[key];
1936
+ if (direct === void 0 || nestedValue === void 0) continue;
1937
+ if (!identityValuesEqual(direct, nestedValue)) {
1938
+ conflicts.push(key);
1939
+ }
1940
+ }
1941
+ return conflicts;
1942
+ }
1943
+ function hasConflictingAttemptIdReuse(members) {
1944
+ const byAttempt = /* @__PURE__ */ new Map();
1841
1945
  for (const event of members) {
1946
+ if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1842
1947
  const id = attemptIdOf(event);
1843
1948
  if (!id) continue;
1844
- if (seen.has(id)) return true;
1845
- seen.add(id);
1949
+ const fingerprints = byAttempt.get(id) ?? /* @__PURE__ */ new Set();
1950
+ fingerprints.add(redeliveryFingerprint(event));
1951
+ byAttempt.set(id, fingerprints);
1952
+ }
1953
+ for (const fingerprints of byAttempt.values()) {
1954
+ if (fingerprints.size > 1) return true;
1955
+ }
1956
+ return false;
1957
+ }
1958
+ function hasConflictingEventIdReuse(members) {
1959
+ const byEventId = /* @__PURE__ */ new Map();
1960
+ for (const event of members) {
1961
+ if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1962
+ const eventId = event.eventId;
1963
+ if (!eventId) continue;
1964
+ if (hasDeliveryConflictMarker(event.attributes)) {
1965
+ return true;
1966
+ }
1967
+ const fingerprints = byEventId.get(eventId) ?? /* @__PURE__ */ new Set();
1968
+ fingerprints.add(redeliveryFingerprint(event));
1969
+ byEventId.set(eventId, fingerprints);
1970
+ }
1971
+ for (const fingerprints of byEventId.values()) {
1972
+ if (fingerprints.size > 1) return true;
1973
+ }
1974
+ return false;
1975
+ }
1976
+ function hasIdentityRepresentationConflict(members) {
1977
+ for (const event of members) {
1978
+ if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
1979
+ if (directNestedIdentityConflicts(event).length > 0) return true;
1846
1980
  }
1847
1981
  return false;
1848
1982
  }
@@ -1853,23 +1987,49 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1853
1987
  const workflow = workflowFor(event);
1854
1988
  const operationId = workflow.operationId;
1855
1989
  if (!operationId) continue;
1856
- const list = byOperation.get(operationId) ?? [];
1857
- list.push(event);
1858
- byOperation.set(operationId, list);
1990
+ const key = `${event.runId}\0${operationId}`;
1991
+ const group = byOperation.get(key) ?? { operationId, members: [] };
1992
+ group.members.push(event);
1993
+ byOperation.set(key, group);
1859
1994
  }
1860
1995
  if (rules.maxAttempts !== void 0) {
1861
- for (const [operationId, members] of byOperation) {
1862
- if (hasDuplicateAttemptIds(members)) {
1996
+ for (const { operationId, members } of byOperation.values()) {
1997
+ if (hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members)) {
1863
1998
  findings.push(
1864
1999
  fail2(
1865
2000
  "contract.retry.duplicate-attempt-id",
1866
- `Operation ${operationId} has duplicate attemptId values.`,
2001
+ `Operation ${operationId} has conflicting attemptId reuse (distinct executions).`,
1867
2002
  members.slice(0, 4).map(eventEvidence),
1868
2003
  "unique attemptId",
1869
2004
  "duplicate"
1870
2005
  )
1871
2006
  );
1872
2007
  }
2008
+ if (hasIdentityRepresentationConflict(members)) {
2009
+ findings.push(
2010
+ fail2(
2011
+ "contract.retry.ambiguous-identity",
2012
+ `Operation ${operationId} has conflicting direct vs nested identity fields; strict identity cannot pass.`,
2013
+ members.slice(0, 4).map(eventEvidence),
2014
+ "agreeing identity representation",
2015
+ "direct/nested conflict"
2016
+ )
2017
+ );
2018
+ }
2019
+ const toolish = members.filter((event) => event.kind === "TOOL" || event.kind === "LLM");
2020
+ const hasAttemptId = toolish.some((event) => attemptIdOf(event) !== void 0);
2021
+ const missingAttemptId = toolish.some((event) => attemptIdOf(event) === void 0);
2022
+ if (hasAttemptId && missingAttemptId) {
2023
+ findings.push(
2024
+ fail2(
2025
+ "contract.retry.ambiguous-identity",
2026
+ `Operation ${operationId} has partial attempt identity; strict identity conformance cannot pass.`,
2027
+ members.slice(0, 4).map(eventEvidence),
2028
+ "complete attempt identity",
2029
+ "partial attemptId coverage"
2030
+ )
2031
+ );
2032
+ }
1873
2033
  const count = countOperationAttempts(members);
1874
2034
  if (count > rules.maxAttempts) {
1875
2035
  findings.push(
@@ -1885,7 +2045,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1885
2045
  }
1886
2046
  }
1887
2047
  if (rules.requireTerminalResult) {
1888
- for (const [operationId, members] of byOperation) {
2048
+ for (const { operationId, members } of byOperation.values()) {
1889
2049
  const hasTerminal = members.some((event) => event.status === "ok" || event.status === "error");
1890
2050
  if (!hasTerminal) {
1891
2051
  findings.push(
@@ -1905,7 +2065,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1905
2065
  const workflow = workflowFor(event);
1906
2066
  const fallbackOf = workflow.fallbackOf;
1907
2067
  if (!fallbackOf) continue;
1908
- const prior = byOperation.get(fallbackOf) ?? [];
2068
+ const prior = byOperation.get(`${event.runId}\0${fallbackOf}`)?.members ?? [];
1909
2069
  const fallbackStart = eventTime(event);
1910
2070
  const earlierFailure = prior.some(
1911
2071
  (candidate) => candidate.status === "error" && eventTime(candidate) !== "" && fallbackStart !== "" && eventTime(candidate) < fallbackStart
@@ -1932,7 +2092,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1932
2092
  for (const event of toolEvents) {
1933
2093
  const name = resolveCanonicalToolName(event);
1934
2094
  const workflow = workflowFor(event);
1935
- const key = `${workflow.operationId ?? name}::${name}`;
2095
+ const key = `${event.runId}::${workflow.operationId ?? name}::${name}`;
1936
2096
  const list = byToolOp.get(key) ?? [];
1937
2097
  list.push(event);
1938
2098
  byToolOp.set(key, list);
@@ -1990,7 +2150,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
1990
2150
  }
1991
2151
  }
1992
2152
  if (rules.requireRecoveredFailureVisible) {
1993
- for (const [operationId, members] of byOperation) {
2153
+ for (const { operationId, members } of byOperation.values()) {
1994
2154
  const ordered = sortByTime(members);
1995
2155
  const toolish = ordered.filter(
1996
2156
  (event) => (event.kind === "TOOL" || event.kind === "LLM") && (event.status === "ok" || event.status === "error")
@@ -2248,15 +2408,8 @@ function attemptIdOf2(event) {
2248
2408
  const value = workflowFor2(event).attemptId;
2249
2409
  return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
2250
2410
  }
2251
- function hasDuplicateAttemptIds2(members) {
2252
- const seen = /* @__PURE__ */ new Set();
2253
- for (const event of members) {
2254
- const id = attemptIdOf2(event);
2255
- if (!id) continue;
2256
- if (seen.has(id)) return true;
2257
- seen.add(id);
2258
- }
2259
- return false;
2411
+ function hasDuplicateAttemptIds(members) {
2412
+ return hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members);
2260
2413
  }
2261
2414
  function findRetryTarget(members, retryOf) {
2262
2415
  return members.find(
@@ -2344,7 +2497,7 @@ function evaluateRecoveryOperations(events, operations) {
2344
2497
  }
2345
2498
  for (const [operationKey, members] of groups) {
2346
2499
  const ordered = sortByTime2(members);
2347
- if (hasDuplicateAttemptIds2(members)) {
2500
+ if (hasDuplicateAttemptIds(members)) {
2348
2501
  findings.push(
2349
2502
  fail3(
2350
2503
  "contract.retry.operations.duplicate-attempt-id",