agent-inspect 6.31.21 → 6.31.23
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.
- package/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-N5JN26MW.mjs → chunk-P27XTK5U.mjs} +347 -36
- package/packages/cli/dist/chunk-P27XTK5U.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +434 -63
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +81 -33
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-VMGRSTG7.mjs → src-EWZYLDST.mjs} +3 -3
- package/packages/cli/dist/{src-VMGRSTG7.mjs.map → src-EWZYLDST.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +280 -10
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.mjs +6 -5
- package/packages/core/dist/advanced.mjs.map +1 -1
- package/packages/core/dist/checks.cjs +185 -27
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.mjs +2 -1
- package/packages/core/dist/{chunk-JE3TUFAQ.mjs → chunk-77PUPLPG.mjs} +14 -8
- package/packages/core/dist/chunk-77PUPLPG.mjs.map +1 -0
- package/packages/core/dist/chunk-AN5MOADW.mjs +204 -0
- package/packages/core/dist/chunk-AN5MOADW.mjs.map +1 -0
- package/packages/core/dist/{chunk-4CDX5GDS.mjs → chunk-IMCM42W6.mjs} +110 -99
- package/packages/core/dist/chunk-IMCM42W6.mjs.map +1 -0
- package/packages/core/dist/{chunk-YU6XT5A2.mjs → chunk-J2ST4VCX.mjs} +45 -3
- package/packages/core/dist/chunk-J2ST4VCX.mjs.map +1 -0
- package/packages/core/dist/{chunk-EIP5CNEL.mjs → chunk-JJSL346L.mjs} +58 -3
- package/packages/core/dist/chunk-JJSL346L.mjs.map +1 -0
- package/packages/core/dist/exporters.cjs +91 -29
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +78 -29
- package/packages/core/dist/exporters.mjs.map +1 -1
- package/packages/core/dist/logs.cjs +206 -1
- package/packages/core/dist/logs.cjs.map +1 -1
- package/packages/core/dist/logs.mjs +3 -2
- package/packages/core/dist/logs.mjs.map +1 -1
- package/packages/core/dist/persisted.cjs +226 -8
- package/packages/core/dist/persisted.cjs.map +1 -1
- package/packages/core/dist/persisted.mjs +9 -5
- package/packages/core/dist/persisted.mjs.map +1 -1
- package/packages/core/dist/readers.cjs +276 -6
- package/packages/core/dist/readers.cjs.map +1 -1
- package/packages/core/dist/readers.mjs +4 -3
- package/packages/cli/dist/chunk-N5JN26MW.mjs.map +0 -1
- package/packages/core/dist/chunk-4CDX5GDS.mjs.map +0 -1
- package/packages/core/dist/chunk-EIP5CNEL.mjs.map +0 -1
- package/packages/core/dist/chunk-JE3TUFAQ.mjs.map +0 -1
- package/packages/core/dist/chunk-YU6XT5A2.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 6.31.23
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 297b1f1: Compare full retry identity before OTLP length bounding and stamp converter delivery_event_base provenance so long collisions and native manual:/inspect:-shaped IDs cannot silently pass strict retry gates (Prompt A residuals / #484).
|
|
8
|
+
|
|
9
|
+
## 6.31.22
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 3f02b61: Treat native eventIds as opaque for retry redelivery fingerprints, retain conflicting same-ID evidence through tree/export, and surface direct vs nested identity disagreements on OTLP round-trip so source and OTLP strict retry gates agree (Prompt A / #484).
|
|
14
|
+
|
|
3
15
|
## 6.31.21
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -213,7 +213,7 @@ The root package is enough for custom capture, the CLI, checks, and Evidence wor
|
|
|
213
213
|
|
|
214
214
|
## Status and documentation
|
|
215
215
|
|
|
216
|
-
**Current published baseline:** **6.31.
|
|
216
|
+
**Current published baseline:** **6.31.23** · persisted schema `1.0` · Node.js `>=20` · MIT.
|
|
217
217
|
|
|
218
218
|
Legacy v0.1 and v0.2 traces remain readable. Check the npm badge and [changelog](CHANGELOG.md) for the current published version.
|
|
219
219
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-inspect",
|
|
3
|
-
"version": "6.31.
|
|
3
|
+
"version": "6.31.23",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Local evidence debugger and trajectory-test toolkit for TypeScript AI agents — execution trees, TraceContract checks, Evidence v2, and read-only MCP",
|
|
@@ -5685,6 +5685,137 @@ function evaluateToolArgumentValue(value, check, evidencePresent) {
|
|
|
5685
5685
|
};
|
|
5686
5686
|
}
|
|
5687
5687
|
|
|
5688
|
+
// packages/core/src/persisted/delivery-identity.ts
|
|
5689
|
+
var DELIVERY_CONFLICT_ATTR = "agent_inspect.delivery_conflict";
|
|
5690
|
+
var DELIVERY_EVENT_BASE_ATTR = "agent_inspect.delivery_event_base";
|
|
5691
|
+
var IDENTITY_CONFLICT_ATTR = {
|
|
5692
|
+
operationId: "agent_inspect.identity_conflict.operation_id",
|
|
5693
|
+
attemptId: "agent_inspect.identity_conflict.attempt_id",
|
|
5694
|
+
retryOf: "agent_inspect.identity_conflict.retry_of",
|
|
5695
|
+
attemptNumber: "agent_inspect.identity_conflict.attempt_number",
|
|
5696
|
+
/** Comma-separated field names when a conflict survives lossy bounding. */
|
|
5697
|
+
fields: "agent_inspect.identity_conflict.fields"
|
|
5698
|
+
};
|
|
5699
|
+
var MAX_CONFLICT_FIELDS = 8;
|
|
5700
|
+
var MAX_DELIVERY_BASE_LEN = 500;
|
|
5701
|
+
function stripReaderDeliveryDiscriminator(eventId, attributes) {
|
|
5702
|
+
if (!eventId) return eventId;
|
|
5703
|
+
const rawBase = attributes?.[DELIVERY_EVENT_BASE_ATTR];
|
|
5704
|
+
if (typeof rawBase !== "string" || rawBase.trim() === "") return eventId;
|
|
5705
|
+
const base = rawBase.trim().slice(0, MAX_DELIVERY_BASE_LEN);
|
|
5706
|
+
if (eventId === base) return base;
|
|
5707
|
+
const prefix = `${base}:`;
|
|
5708
|
+
if (!eventId.startsWith(prefix)) return eventId;
|
|
5709
|
+
const suffix = eventId.slice(prefix.length);
|
|
5710
|
+
if (/^\d+$/.test(suffix)) return base;
|
|
5711
|
+
return eventId;
|
|
5712
|
+
}
|
|
5713
|
+
function deliveryEventBaseFromIndexedId(eventId) {
|
|
5714
|
+
if (!/:\d+$/.test(eventId)) return void 0;
|
|
5715
|
+
const base = eventId.replace(/:\d+$/, "");
|
|
5716
|
+
return base.length > 0 ? base.slice(0, MAX_DELIVERY_BASE_LEN) : void 0;
|
|
5717
|
+
}
|
|
5718
|
+
function canonicalDigest(value) {
|
|
5719
|
+
if (value === void 0) return null;
|
|
5720
|
+
const encoded = encodeCanonicalStructured(value);
|
|
5721
|
+
return encoded.ok ? encoded.value : `unencodable:${encoded.code}`;
|
|
5722
|
+
}
|
|
5723
|
+
function capturedContentDigest(attributes) {
|
|
5724
|
+
if (!attributes || typeof attributes !== "object") {
|
|
5725
|
+
return { args: null, result: null };
|
|
5726
|
+
}
|
|
5727
|
+
const nested = attributes.metadata && typeof attributes.metadata === "object" ? attributes.metadata : void 0;
|
|
5728
|
+
const args = attributes.arguments ?? attributes.args ?? attributes.input ?? nested?.arguments ?? nested?.args ?? nested?.input;
|
|
5729
|
+
const result = attributes.result ?? attributes.output ?? attributes.response ?? nested?.result ?? nested?.output ?? nested?.response;
|
|
5730
|
+
return {
|
|
5731
|
+
args: args === void 0 ? null : canonicalDigest(args),
|
|
5732
|
+
result: result === void 0 ? null : canonicalDigest(result)
|
|
5733
|
+
};
|
|
5734
|
+
}
|
|
5735
|
+
function timeKey(fields) {
|
|
5736
|
+
if (typeof fields.startedAt === "string" && fields.startedAt.trim() !== "") {
|
|
5737
|
+
return fields.startedAt;
|
|
5738
|
+
}
|
|
5739
|
+
if (typeof fields.timestamp === "string" && fields.timestamp.trim() !== "") {
|
|
5740
|
+
return fields.timestamp;
|
|
5741
|
+
}
|
|
5742
|
+
if (typeof fields.timestamp === "number" && Number.isFinite(fields.timestamp)) {
|
|
5743
|
+
return String(fields.timestamp);
|
|
5744
|
+
}
|
|
5745
|
+
return null;
|
|
5746
|
+
}
|
|
5747
|
+
function deliverySemanticFingerprint(fields) {
|
|
5748
|
+
const content = capturedContentDigest(fields.attributes);
|
|
5749
|
+
return JSON.stringify({
|
|
5750
|
+
stableEventId: stripReaderDeliveryDiscriminator(fields.eventId, fields.attributes),
|
|
5751
|
+
runId: fields.runId,
|
|
5752
|
+
kind: fields.kind,
|
|
5753
|
+
name: fields.name,
|
|
5754
|
+
status: fields.status ?? null,
|
|
5755
|
+
parentId: fields.parentId ?? null,
|
|
5756
|
+
sourceType: fields.sourceType ?? null,
|
|
5757
|
+
time: timeKey(fields),
|
|
5758
|
+
operationId: fields.operationId ?? null,
|
|
5759
|
+
attemptId: fields.attemptId ?? null,
|
|
5760
|
+
attemptNumber: fields.attemptNumber ?? null,
|
|
5761
|
+
retryOf: fields.retryOf ?? null,
|
|
5762
|
+
argsDigest: content.args,
|
|
5763
|
+
resultDigest: content.result
|
|
5764
|
+
});
|
|
5765
|
+
}
|
|
5766
|
+
function identityFieldsFromAttributes(attributes) {
|
|
5767
|
+
if (!attributes || typeof attributes !== "object") {
|
|
5768
|
+
return {
|
|
5769
|
+
operationId: null,
|
|
5770
|
+
attemptId: null,
|
|
5771
|
+
attemptNumber: null,
|
|
5772
|
+
retryOf: null
|
|
5773
|
+
};
|
|
5774
|
+
}
|
|
5775
|
+
const nested = attributes.metadata && typeof attributes.metadata === "object" && !Array.isArray(attributes.metadata) ? attributes.metadata : void 0;
|
|
5776
|
+
const pickString3 = (key) => {
|
|
5777
|
+
const direct = attributes[key];
|
|
5778
|
+
if (typeof direct === "string" && direct.trim() !== "") return direct.trim();
|
|
5779
|
+
const nestedValue = nested?.[key];
|
|
5780
|
+
if (typeof nestedValue === "string" && nestedValue.trim() !== "") {
|
|
5781
|
+
return nestedValue.trim();
|
|
5782
|
+
}
|
|
5783
|
+
return null;
|
|
5784
|
+
};
|
|
5785
|
+
const pickNumber2 = () => {
|
|
5786
|
+
const direct = attributes.attemptNumber ?? attributes.attempt;
|
|
5787
|
+
if (typeof direct === "number" && Number.isFinite(direct)) return direct;
|
|
5788
|
+
const nestedValue = nested?.attemptNumber ?? nested?.attempt;
|
|
5789
|
+
if (typeof nestedValue === "number" && Number.isFinite(nestedValue)) {
|
|
5790
|
+
return nestedValue;
|
|
5791
|
+
}
|
|
5792
|
+
return null;
|
|
5793
|
+
};
|
|
5794
|
+
return {
|
|
5795
|
+
operationId: pickString3("operationId"),
|
|
5796
|
+
attemptId: pickString3("attemptId"),
|
|
5797
|
+
retryOf: pickString3("retryOf"),
|
|
5798
|
+
attemptNumber: pickNumber2()
|
|
5799
|
+
};
|
|
5800
|
+
}
|
|
5801
|
+
function identityConflictFieldsFromAttributes(attributes) {
|
|
5802
|
+
const raw = attributes?.[IDENTITY_CONFLICT_ATTR.fields];
|
|
5803
|
+
if (typeof raw !== "string" || raw.trim() === "") return [];
|
|
5804
|
+
return raw.split(",").map((part) => part.trim()).filter((part) => part.length > 0).slice(0, MAX_CONFLICT_FIELDS);
|
|
5805
|
+
}
|
|
5806
|
+
function hasDeliveryConflictMarker(attributes) {
|
|
5807
|
+
return attributes?.[DELIVERY_CONFLICT_ATTR] === true;
|
|
5808
|
+
}
|
|
5809
|
+
function stampDeliveryConflict(event) {
|
|
5810
|
+
return {
|
|
5811
|
+
...event,
|
|
5812
|
+
attributes: {
|
|
5813
|
+
...event.attributes ?? {},
|
|
5814
|
+
[DELIVERY_CONFLICT_ATTR]: true
|
|
5815
|
+
}
|
|
5816
|
+
};
|
|
5817
|
+
}
|
|
5818
|
+
|
|
5688
5819
|
// packages/core/src/checks/retry-safety.ts
|
|
5689
5820
|
function fail2(ruleId, message, evidence, expected, actual) {
|
|
5690
5821
|
return {
|
|
@@ -5740,7 +5871,7 @@ function attemptIdOf(event) {
|
|
|
5740
5871
|
}
|
|
5741
5872
|
function countOperationAttempts(members) {
|
|
5742
5873
|
const identified = /* @__PURE__ */ new Set();
|
|
5743
|
-
|
|
5874
|
+
const unidentifiedFingerprints = /* @__PURE__ */ new Set();
|
|
5744
5875
|
for (const event of members) {
|
|
5745
5876
|
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
5746
5877
|
const id = attemptIdOf(event);
|
|
@@ -5748,13 +5879,13 @@ function countOperationAttempts(members) {
|
|
|
5748
5879
|
identified.add(id);
|
|
5749
5880
|
continue;
|
|
5750
5881
|
}
|
|
5751
|
-
|
|
5882
|
+
unidentifiedFingerprints.add(redeliveryFingerprint(event));
|
|
5752
5883
|
}
|
|
5753
5884
|
if (identified.size > 0) {
|
|
5754
|
-
return identified.size +
|
|
5885
|
+
return identified.size + unidentifiedFingerprints.size;
|
|
5755
5886
|
}
|
|
5756
5887
|
const numbered = /* @__PURE__ */ new Set();
|
|
5757
|
-
|
|
5888
|
+
const unnumberedFingerprints = /* @__PURE__ */ new Set();
|
|
5758
5889
|
for (const event of members) {
|
|
5759
5890
|
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
5760
5891
|
const num = attemptNumberOf(event);
|
|
@@ -5762,12 +5893,12 @@ function countOperationAttempts(members) {
|
|
|
5762
5893
|
numbered.add(num);
|
|
5763
5894
|
continue;
|
|
5764
5895
|
}
|
|
5765
|
-
|
|
5896
|
+
unnumberedFingerprints.add(redeliveryFingerprint(event));
|
|
5766
5897
|
}
|
|
5767
5898
|
if (numbered.size > 0) {
|
|
5768
|
-
return numbered.size +
|
|
5899
|
+
return numbered.size + unnumberedFingerprints.size;
|
|
5769
5900
|
}
|
|
5770
|
-
return
|
|
5901
|
+
return unnumberedFingerprints.size;
|
|
5771
5902
|
}
|
|
5772
5903
|
function classifyRetryAttempt(event, priorOrdered, allMembers) {
|
|
5773
5904
|
const workflow = workflowFor(event);
|
|
@@ -5819,19 +5950,55 @@ function classifyRetryAttempt(event, priorOrdered, allMembers) {
|
|
|
5819
5950
|
}
|
|
5820
5951
|
function redeliveryFingerprint(event) {
|
|
5821
5952
|
const workflow = workflowFor(event);
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
stableEventId,
|
|
5953
|
+
return deliverySemanticFingerprint({
|
|
5954
|
+
eventId: event.eventId ?? "",
|
|
5825
5955
|
runId: event.runId,
|
|
5826
5956
|
kind: event.kind,
|
|
5827
5957
|
name: event.name,
|
|
5828
5958
|
status: event.status,
|
|
5959
|
+
parentId: event.parentId,
|
|
5960
|
+
timestamp: event.timestamp,
|
|
5961
|
+
startedAt: event.startedAt,
|
|
5962
|
+
sourceType: event.source?.type,
|
|
5963
|
+
attributes: event.attributes && typeof event.attributes === "object" ? event.attributes : void 0,
|
|
5829
5964
|
operationId: workflow.operationId ?? null,
|
|
5830
5965
|
attemptId: workflow.attemptId ?? null,
|
|
5831
5966
|
attemptNumber: workflow.attemptNumber ?? null,
|
|
5832
5967
|
retryOf: workflow.retryOf ?? null
|
|
5833
5968
|
});
|
|
5834
5969
|
}
|
|
5970
|
+
var IDENTITY_KEYS = ["operationId", "attemptId", "retryOf", "attemptNumber"];
|
|
5971
|
+
function identityValuesEqual(a, b) {
|
|
5972
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
5973
|
+
return Number.isFinite(a) && Number.isFinite(b) && a === b;
|
|
5974
|
+
}
|
|
5975
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
5976
|
+
return a.trim() === b.trim();
|
|
5977
|
+
}
|
|
5978
|
+
return a === b;
|
|
5979
|
+
}
|
|
5980
|
+
function directNestedIdentityConflicts(event) {
|
|
5981
|
+
const attrs = event.attributes;
|
|
5982
|
+
if (!attrs || typeof attrs !== "object") return [];
|
|
5983
|
+
const nested = attrs.metadata && typeof attrs.metadata === "object" && !Array.isArray(attrs.metadata) ? attrs.metadata : void 0;
|
|
5984
|
+
const conflicts = [];
|
|
5985
|
+
if (nested) {
|
|
5986
|
+
for (const key of IDENTITY_KEYS) {
|
|
5987
|
+
const direct = attrs[key];
|
|
5988
|
+
const nestedValue = nested[key];
|
|
5989
|
+
if (direct === void 0 || nestedValue === void 0) continue;
|
|
5990
|
+
if (!identityValuesEqual(direct, nestedValue)) {
|
|
5991
|
+
conflicts.push(key);
|
|
5992
|
+
}
|
|
5993
|
+
}
|
|
5994
|
+
}
|
|
5995
|
+
for (const key of identityConflictFieldsFromAttributes(attrs)) {
|
|
5996
|
+
if (IDENTITY_KEYS.includes(key) && !conflicts.includes(key)) {
|
|
5997
|
+
conflicts.push(key);
|
|
5998
|
+
}
|
|
5999
|
+
}
|
|
6000
|
+
return conflicts;
|
|
6001
|
+
}
|
|
5835
6002
|
function hasConflictingAttemptIdReuse(members) {
|
|
5836
6003
|
const byAttempt = /* @__PURE__ */ new Map();
|
|
5837
6004
|
for (const event of members) {
|
|
@@ -5847,6 +6014,31 @@ function hasConflictingAttemptIdReuse(members) {
|
|
|
5847
6014
|
}
|
|
5848
6015
|
return false;
|
|
5849
6016
|
}
|
|
6017
|
+
function hasConflictingEventIdReuse(members) {
|
|
6018
|
+
const byEventId = /* @__PURE__ */ new Map();
|
|
6019
|
+
for (const event of members) {
|
|
6020
|
+
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
6021
|
+
const eventId = event.eventId;
|
|
6022
|
+
if (!eventId) continue;
|
|
6023
|
+
if (hasDeliveryConflictMarker(event.attributes)) {
|
|
6024
|
+
return true;
|
|
6025
|
+
}
|
|
6026
|
+
const fingerprints = byEventId.get(eventId) ?? /* @__PURE__ */ new Set();
|
|
6027
|
+
fingerprints.add(redeliveryFingerprint(event));
|
|
6028
|
+
byEventId.set(eventId, fingerprints);
|
|
6029
|
+
}
|
|
6030
|
+
for (const fingerprints of byEventId.values()) {
|
|
6031
|
+
if (fingerprints.size > 1) return true;
|
|
6032
|
+
}
|
|
6033
|
+
return false;
|
|
6034
|
+
}
|
|
6035
|
+
function hasIdentityRepresentationConflict(members) {
|
|
6036
|
+
for (const event of members) {
|
|
6037
|
+
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
6038
|
+
if (directNestedIdentityConflicts(event).length > 0) return true;
|
|
6039
|
+
}
|
|
6040
|
+
return false;
|
|
6041
|
+
}
|
|
5850
6042
|
function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
5851
6043
|
const findings = [];
|
|
5852
6044
|
const byOperation = /* @__PURE__ */ new Map();
|
|
@@ -5854,13 +6046,14 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
5854
6046
|
const workflow = workflowFor(event);
|
|
5855
6047
|
const operationId = workflow.operationId;
|
|
5856
6048
|
if (!operationId) continue;
|
|
5857
|
-
const
|
|
5858
|
-
|
|
5859
|
-
|
|
6049
|
+
const key = `${event.runId}\0${operationId}`;
|
|
6050
|
+
const group = byOperation.get(key) ?? { operationId, members: [] };
|
|
6051
|
+
group.members.push(event);
|
|
6052
|
+
byOperation.set(key, group);
|
|
5860
6053
|
}
|
|
5861
6054
|
if (rules.maxAttempts !== void 0) {
|
|
5862
|
-
for (const
|
|
5863
|
-
if (hasConflictingAttemptIdReuse(members)) {
|
|
6055
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
6056
|
+
if (hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members)) {
|
|
5864
6057
|
findings.push(
|
|
5865
6058
|
fail2(
|
|
5866
6059
|
"contract.retry.duplicate-attempt-id",
|
|
@@ -5871,6 +6064,31 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
5871
6064
|
)
|
|
5872
6065
|
);
|
|
5873
6066
|
}
|
|
6067
|
+
if (hasIdentityRepresentationConflict(members)) {
|
|
6068
|
+
findings.push(
|
|
6069
|
+
fail2(
|
|
6070
|
+
"contract.retry.ambiguous-identity",
|
|
6071
|
+
`Operation ${operationId} has conflicting direct vs nested identity fields; strict identity cannot pass.`,
|
|
6072
|
+
members.slice(0, 4).map(eventEvidence),
|
|
6073
|
+
"agreeing identity representation",
|
|
6074
|
+
"direct/nested conflict"
|
|
6075
|
+
)
|
|
6076
|
+
);
|
|
6077
|
+
}
|
|
6078
|
+
const toolish = members.filter((event) => event.kind === "TOOL" || event.kind === "LLM");
|
|
6079
|
+
const hasAttemptId = toolish.some((event) => attemptIdOf(event) !== void 0);
|
|
6080
|
+
const missingAttemptId = toolish.some((event) => attemptIdOf(event) === void 0);
|
|
6081
|
+
if (hasAttemptId && missingAttemptId) {
|
|
6082
|
+
findings.push(
|
|
6083
|
+
fail2(
|
|
6084
|
+
"contract.retry.ambiguous-identity",
|
|
6085
|
+
`Operation ${operationId} has partial attempt identity; strict identity conformance cannot pass.`,
|
|
6086
|
+
members.slice(0, 4).map(eventEvidence),
|
|
6087
|
+
"complete attempt identity",
|
|
6088
|
+
"partial attemptId coverage"
|
|
6089
|
+
)
|
|
6090
|
+
);
|
|
6091
|
+
}
|
|
5874
6092
|
const count = countOperationAttempts(members);
|
|
5875
6093
|
if (count > rules.maxAttempts) {
|
|
5876
6094
|
findings.push(
|
|
@@ -5886,7 +6104,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
5886
6104
|
}
|
|
5887
6105
|
}
|
|
5888
6106
|
if (rules.requireTerminalResult) {
|
|
5889
|
-
for (const
|
|
6107
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
5890
6108
|
const hasTerminal = members.some((event) => event.status === "ok" || event.status === "error");
|
|
5891
6109
|
if (!hasTerminal) {
|
|
5892
6110
|
findings.push(
|
|
@@ -5906,7 +6124,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
5906
6124
|
const workflow = workflowFor(event);
|
|
5907
6125
|
const fallbackOf = workflow.fallbackOf;
|
|
5908
6126
|
if (!fallbackOf) continue;
|
|
5909
|
-
const prior = byOperation.get(fallbackOf) ?? [];
|
|
6127
|
+
const prior = byOperation.get(`${event.runId}\0${fallbackOf}`)?.members ?? [];
|
|
5910
6128
|
const fallbackStart = eventTime(event);
|
|
5911
6129
|
const earlierFailure = prior.some(
|
|
5912
6130
|
(candidate) => candidate.status === "error" && eventTime(candidate) !== "" && fallbackStart !== "" && eventTime(candidate) < fallbackStart
|
|
@@ -5933,7 +6151,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
5933
6151
|
for (const event of toolEvents) {
|
|
5934
6152
|
const name = resolveCanonicalToolName(event);
|
|
5935
6153
|
const workflow = workflowFor(event);
|
|
5936
|
-
const key = `${workflow.operationId ?? name}::${name}`;
|
|
6154
|
+
const key = `${event.runId}::${workflow.operationId ?? name}::${name}`;
|
|
5937
6155
|
const list = byToolOp.get(key) ?? [];
|
|
5938
6156
|
list.push(event);
|
|
5939
6157
|
byToolOp.set(key, list);
|
|
@@ -5991,7 +6209,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
5991
6209
|
}
|
|
5992
6210
|
}
|
|
5993
6211
|
if (rules.requireRecoveredFailureVisible) {
|
|
5994
|
-
for (const
|
|
6212
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
5995
6213
|
const ordered = sortByTime(members);
|
|
5996
6214
|
const toolish = ordered.filter(
|
|
5997
6215
|
(event) => (event.kind === "TOOL" || event.kind === "LLM") && (event.status === "ok" || event.status === "error")
|
|
@@ -6250,14 +6468,7 @@ function attemptIdOf2(event) {
|
|
|
6250
6468
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
6251
6469
|
}
|
|
6252
6470
|
function hasDuplicateAttemptIds(members) {
|
|
6253
|
-
|
|
6254
|
-
for (const event of members) {
|
|
6255
|
-
const id = attemptIdOf2(event);
|
|
6256
|
-
if (!id) continue;
|
|
6257
|
-
if (seen.has(id)) return true;
|
|
6258
|
-
seen.add(id);
|
|
6259
|
-
}
|
|
6260
|
-
return false;
|
|
6471
|
+
return hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members);
|
|
6261
6472
|
}
|
|
6262
6473
|
function findRetryTarget(members, retryOf) {
|
|
6263
6474
|
return members.find(
|
|
@@ -11912,6 +12123,11 @@ function compactAttributes2(entries) {
|
|
|
11912
12123
|
}
|
|
11913
12124
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
11914
12125
|
}
|
|
12126
|
+
function stampDeliveryEventBase(eventId, attributes) {
|
|
12127
|
+
const base = deliveryEventBaseFromIndexedId(eventId);
|
|
12128
|
+
if (!base) return attributes;
|
|
12129
|
+
return { ...attributes ?? {}, [DELIVERY_EVENT_BASE_ATTR]: base };
|
|
12130
|
+
}
|
|
11915
12131
|
function traceEventToPersistedInspectEvent(event, options) {
|
|
11916
12132
|
const eventIndex = options?.eventIndex ?? 0;
|
|
11917
12133
|
const eventId = createPersistedEventId(event, eventIndex);
|
|
@@ -11941,7 +12157,7 @@ function traceEventToPersistedInspectEvent(event, options) {
|
|
|
11941
12157
|
startedAt: tsStart.iso,
|
|
11942
12158
|
confidence: "explicit",
|
|
11943
12159
|
source,
|
|
11944
|
-
attributes
|
|
12160
|
+
attributes: stampDeliveryEventBase(eventId, attributes)
|
|
11945
12161
|
};
|
|
11946
12162
|
}
|
|
11947
12163
|
case "run_completed": {
|
|
@@ -11964,7 +12180,7 @@ function traceEventToPersistedInspectEvent(event, options) {
|
|
|
11964
12180
|
durationMs: event.durationMs,
|
|
11965
12181
|
confidence: "explicit",
|
|
11966
12182
|
source,
|
|
11967
|
-
attributes,
|
|
12183
|
+
attributes: stampDeliveryEventBase(eventId, attributes),
|
|
11968
12184
|
error
|
|
11969
12185
|
};
|
|
11970
12186
|
}
|
|
@@ -11989,7 +12205,7 @@ function traceEventToPersistedInspectEvent(event, options) {
|
|
|
11989
12205
|
startedAt: tsStart.iso,
|
|
11990
12206
|
confidence: "explicit",
|
|
11991
12207
|
source,
|
|
11992
|
-
attributes
|
|
12208
|
+
attributes: stampDeliveryEventBase(eventId, attributes)
|
|
11993
12209
|
};
|
|
11994
12210
|
if (event.parentId !== void 0) {
|
|
11995
12211
|
out.parentId = event.parentId;
|
|
@@ -12020,7 +12236,7 @@ function traceEventToPersistedInspectEvent(event, options) {
|
|
|
12020
12236
|
durationMs: event.durationMs,
|
|
12021
12237
|
confidence: "explicit",
|
|
12022
12238
|
source,
|
|
12023
|
-
attributes,
|
|
12239
|
+
attributes: stampDeliveryEventBase(eventId, attributes),
|
|
12024
12240
|
error
|
|
12025
12241
|
};
|
|
12026
12242
|
}
|
|
@@ -12047,7 +12263,7 @@ function traceEventToPersistedInspectEvent(event, options) {
|
|
|
12047
12263
|
timestamp: tsMain.iso,
|
|
12048
12264
|
confidence: "explicit",
|
|
12049
12265
|
source,
|
|
12050
|
-
attributes
|
|
12266
|
+
attributes: stampDeliveryEventBase(eventId, attributes)
|
|
12051
12267
|
};
|
|
12052
12268
|
if (event.parentId !== void 0) {
|
|
12053
12269
|
out.parentId = event.parentId;
|
|
@@ -12200,7 +12416,47 @@ var TreeBuilder = class {
|
|
|
12200
12416
|
const sorted = [...runEvents].sort((a, b) => a.timestamp - b.timestamp);
|
|
12201
12417
|
const nodes = /* @__PURE__ */ new Map();
|
|
12202
12418
|
for (const e of sorted) {
|
|
12203
|
-
nodes.
|
|
12419
|
+
const existing = nodes.get(e.eventId);
|
|
12420
|
+
if (!existing) {
|
|
12421
|
+
nodes.set(e.eventId, { event: e, children: [], depth: 0 });
|
|
12422
|
+
continue;
|
|
12423
|
+
}
|
|
12424
|
+
const existingAttrs = existing.event.attributes && typeof existing.event.attributes === "object" ? existing.event.attributes : void 0;
|
|
12425
|
+
const nextAttrs = e.attributes && typeof e.attributes === "object" ? e.attributes : void 0;
|
|
12426
|
+
const existingIdentity = identityFieldsFromAttributes(existingAttrs);
|
|
12427
|
+
const nextIdentity = identityFieldsFromAttributes(nextAttrs);
|
|
12428
|
+
const existingFp = deliverySemanticFingerprint({
|
|
12429
|
+
eventId: existing.event.eventId,
|
|
12430
|
+
runId: existing.event.runId,
|
|
12431
|
+
kind: existing.event.kind,
|
|
12432
|
+
name: existing.event.name,
|
|
12433
|
+
status: existing.event.status,
|
|
12434
|
+
parentId: existing.event.parentId,
|
|
12435
|
+
timestamp: existing.event.timestamp,
|
|
12436
|
+
sourceType: existing.event.source?.type,
|
|
12437
|
+
attributes: existingAttrs,
|
|
12438
|
+
...existingIdentity
|
|
12439
|
+
});
|
|
12440
|
+
const nextFp = deliverySemanticFingerprint({
|
|
12441
|
+
eventId: e.eventId,
|
|
12442
|
+
runId: e.runId,
|
|
12443
|
+
kind: e.kind,
|
|
12444
|
+
name: e.name,
|
|
12445
|
+
status: e.status,
|
|
12446
|
+
parentId: e.parentId,
|
|
12447
|
+
timestamp: e.timestamp,
|
|
12448
|
+
sourceType: e.source?.type,
|
|
12449
|
+
attributes: nextAttrs,
|
|
12450
|
+
...nextIdentity
|
|
12451
|
+
});
|
|
12452
|
+
if (existingFp === nextFp) {
|
|
12453
|
+
continue;
|
|
12454
|
+
}
|
|
12455
|
+
nodes.set(e.eventId, {
|
|
12456
|
+
event: stampDeliveryConflict(e),
|
|
12457
|
+
children: [],
|
|
12458
|
+
depth: 0
|
|
12459
|
+
});
|
|
12204
12460
|
}
|
|
12205
12461
|
const { roots, summary } = linkNodesVisibilityFirst(nodes);
|
|
12206
12462
|
const confidenceBreakdown = {
|
|
@@ -13665,6 +13921,12 @@ function promoteAgentInspectWorkflowIdentity(attributes, pathPrefix) {
|
|
|
13665
13921
|
["agent_inspect.retry_of", "retryOf", "string"],
|
|
13666
13922
|
["agent_inspect.attempt_number", "attemptNumber", "int"]
|
|
13667
13923
|
];
|
|
13924
|
+
const conflictMapping = [
|
|
13925
|
+
["agent_inspect.identity_conflict.operation_id", "operationId", "string"],
|
|
13926
|
+
["agent_inspect.identity_conflict.attempt_id", "attemptId", "string"],
|
|
13927
|
+
["agent_inspect.identity_conflict.retry_of", "retryOf", "string"],
|
|
13928
|
+
["agent_inspect.identity_conflict.attempt_number", "attemptNumber", "int"]
|
|
13929
|
+
];
|
|
13668
13930
|
const metadata = attributes.metadata && typeof attributes.metadata === "object" && !Array.isArray(attributes.metadata) ? { ...attributes.metadata } : {};
|
|
13669
13931
|
for (const [dotted, camel, kind] of mapping) {
|
|
13670
13932
|
const raw = attributes[dotted];
|
|
@@ -13716,6 +13978,55 @@ function promoteAgentInspectWorkflowIdentity(attributes, pathPrefix) {
|
|
|
13716
13978
|
if (direct === void 0) attributes[camel] = promoted;
|
|
13717
13979
|
if (nested === void 0) metadata[camel] = promoted;
|
|
13718
13980
|
}
|
|
13981
|
+
for (const [dotted, camel, kind] of conflictMapping) {
|
|
13982
|
+
const raw = attributes[dotted];
|
|
13983
|
+
if (raw === void 0 || raw === null) continue;
|
|
13984
|
+
let alternate;
|
|
13985
|
+
if (kind === "int") {
|
|
13986
|
+
const n = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : NaN;
|
|
13987
|
+
if (!Number.isFinite(n) || n < 1) {
|
|
13988
|
+
warnings.push({
|
|
13989
|
+
code: "otlp_identity_invalid",
|
|
13990
|
+
message: `Ignoring invalid ${dotted} identity conflict value.`,
|
|
13991
|
+
severity: "warning",
|
|
13992
|
+
field: `${pathPrefix}.${dotted}`
|
|
13993
|
+
});
|
|
13994
|
+
continue;
|
|
13995
|
+
}
|
|
13996
|
+
alternate = Math.trunc(n);
|
|
13997
|
+
} else if (typeof raw === "string" && raw.trim() !== "") {
|
|
13998
|
+
alternate = raw.trim();
|
|
13999
|
+
} else {
|
|
14000
|
+
warnings.push({
|
|
14001
|
+
code: "otlp_identity_invalid",
|
|
14002
|
+
message: `Ignoring non-string ${dotted} identity conflict value.`,
|
|
14003
|
+
severity: "warning",
|
|
14004
|
+
field: `${pathPrefix}.${dotted}`
|
|
14005
|
+
});
|
|
14006
|
+
continue;
|
|
14007
|
+
}
|
|
14008
|
+
const preferred = attributes[camel];
|
|
14009
|
+
if (preferred !== void 0 && preferred !== alternate) {
|
|
14010
|
+
metadata[camel] = alternate;
|
|
14011
|
+
warnings.push({
|
|
14012
|
+
code: "otlp_identity_conflict",
|
|
14013
|
+
message: `Conflicting ${camel}: attributes.${camel} vs nested alternate from ${dotted}; retaining both.`,
|
|
14014
|
+
severity: "warning",
|
|
14015
|
+
field: `${pathPrefix}.${dotted}`
|
|
14016
|
+
});
|
|
14017
|
+
} else if (preferred === void 0) {
|
|
14018
|
+
metadata[camel] = alternate;
|
|
14019
|
+
}
|
|
14020
|
+
}
|
|
14021
|
+
const conflictFields = attributes["agent_inspect.identity_conflict.fields"];
|
|
14022
|
+
if (typeof conflictFields === "string" && conflictFields.trim() !== "") {
|
|
14023
|
+
warnings.push({
|
|
14024
|
+
code: "otlp_identity_conflict",
|
|
14025
|
+
message: `Identity representation conflict fields retained after OTLP bounding: ${conflictFields.trim().slice(0, 200)}.`,
|
|
14026
|
+
severity: "warning",
|
|
14027
|
+
field: `${pathPrefix}.agent_inspect.identity_conflict.fields`
|
|
14028
|
+
});
|
|
14029
|
+
}
|
|
13719
14030
|
if (Object.keys(metadata).length > 0) {
|
|
13720
14031
|
attributes.metadata = metadata;
|
|
13721
14032
|
}
|
|
@@ -15696,6 +16007,6 @@ function renderGateReport(result, options = {}) {
|
|
|
15696
16007
|
return renderGateSummaryMarkdown(result);
|
|
15697
16008
|
}
|
|
15698
16009
|
|
|
15699
|
-
export { ATTRIBUTION_CONFIDENCES, COHORT_METRIC_IDS, DEFAULT_REDACT_KEYS, 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, defineTraceContract, diffRuns, diffTraceEvents, enrichSessionRunRecord, escapeHtml, escapeMarkdown, evaluateTraceContract, extractMetadata, extractOutcomesFromTraceEvents, filterMetasBySessionScope, filterTraces, flattenTree, formatDuration2 as formatDuration, formatStepLabel, formatTimestamp, gateHasThresholds, getIndent, getTraceFilePath, inferEvidenceFileRole, isAgentInspectTrace, isAttributionConfidence, isCredentialSensitiveKey, isPersistedInspectEvent, loadSessionRunRecords, loadSuiteConfig, loadTraceMetadataList, manualTraceEventsToComparableRun, nanoid, normalizeBundleOutputPath, openTrace, parseCohortMetricList, parseDuration, parseDurationFilter, parseGateList, parseTraceJsonl, persistedInspectEventsToRunTrees, persistedInspectEventsToTraceEvents, projectLogicalEvents, 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, stringContainsHighConfidenceCredential, summarizeObservedOutcomes, summarizeSemanticParity, traceEventToPersistedInspectEvent, truncateName, truncateStringForProfile, validateEvent, validateSuiteConfig, verifyEvidenceDirectory, zeroKinds };
|
|
15700
|
-
//# sourceMappingURL=chunk-
|
|
15701
|
-
//# sourceMappingURL=chunk-
|
|
16010
|
+
export { ATTRIBUTION_CONFIDENCES, COHORT_METRIC_IDS, DEFAULT_REDACT_KEYS, DEFAULT_SUITE_ARTIFACTS_DIR, DELIVERY_CONFLICT_ATTR, DELIVERY_EVENT_BASE_ATTR, EVIDENCE_FORMAT_VERSION, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, IDENTITY_CONFLICT_ATTR, 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, defineTraceContract, diffRuns, diffTraceEvents, enrichSessionRunRecord, escapeHtml, escapeMarkdown, evaluateTraceContract, extractMetadata, extractOutcomesFromTraceEvents, filterMetasBySessionScope, filterTraces, flattenTree, formatDuration2 as formatDuration, formatStepLabel, formatTimestamp, gateHasThresholds, getIndent, getTraceFilePath, inferEvidenceFileRole, isAgentInspectTrace, isAttributionConfidence, isCredentialSensitiveKey, isPersistedInspectEvent, loadSessionRunRecords, loadSuiteConfig, loadTraceMetadataList, manualTraceEventsToComparableRun, nanoid, normalizeBundleOutputPath, openTrace, parseCohortMetricList, parseDuration, parseDurationFilter, parseGateList, parseTraceJsonl, persistedInspectEventsToRunTrees, persistedInspectEventsToTraceEvents, projectLogicalEvents, 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, stringContainsHighConfidenceCredential, summarizeObservedOutcomes, summarizeSemanticParity, traceEventToPersistedInspectEvent, truncateName, truncateStringForProfile, validateEvent, validateSuiteConfig, verifyEvidenceDirectory, zeroKinds };
|
|
16011
|
+
//# sourceMappingURL=chunk-P27XTK5U.mjs.map
|
|
16012
|
+
//# sourceMappingURL=chunk-P27XTK5U.mjs.map
|