agent-inspect 6.14.1 → 6.15.0

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 (79) hide show
  1. package/CHANGELOG.md +14 -2
  2. package/README.md +1 -1
  3. package/docs/API.md +19 -3
  4. package/docs/KNOWN-ISSUES.md +2 -1
  5. package/package.json +2 -2
  6. package/packages/cli/dist/{chunk-MEO2Z3KE.mjs → chunk-LFSBMUCD.mjs} +316 -41
  7. package/packages/cli/dist/chunk-LFSBMUCD.mjs.map +1 -0
  8. package/packages/cli/dist/index.cjs +388 -42
  9. package/packages/cli/dist/index.cjs.map +1 -1
  10. package/packages/cli/dist/index.mjs +59 -6
  11. package/packages/cli/dist/index.mjs.map +1 -1
  12. package/packages/cli/dist/{src-6VZNGIF6.mjs → src-5J2HPOJ3.mjs} +3 -3
  13. package/packages/cli/dist/{src-6VZNGIF6.mjs.map → src-5J2HPOJ3.mjs.map} +1 -1
  14. package/packages/core/dist/advanced.cjs +268 -24
  15. package/packages/core/dist/advanced.cjs.map +1 -1
  16. package/packages/core/dist/advanced.d.cts +18 -10
  17. package/packages/core/dist/advanced.d.ts +18 -10
  18. package/packages/core/dist/advanced.mjs +7 -6
  19. package/packages/core/dist/advanced.mjs.map +1 -1
  20. package/packages/core/dist/checks.cjs +221 -22
  21. package/packages/core/dist/checks.cjs.map +1 -1
  22. package/packages/core/dist/checks.d.cts +18 -8
  23. package/packages/core/dist/checks.d.ts +18 -8
  24. package/packages/core/dist/checks.mjs +2 -1
  25. package/packages/core/dist/chunk-AK5EN4U2.mjs +174 -0
  26. package/packages/core/dist/chunk-AK5EN4U2.mjs.map +1 -0
  27. package/packages/core/dist/chunk-FWK3Q3OJ.mjs +56 -0
  28. package/packages/core/dist/chunk-FWK3Q3OJ.mjs.map +1 -0
  29. package/packages/core/dist/{chunk-CTA6XNDP.mjs → chunk-HT54OLPE.mjs} +54 -7
  30. package/packages/core/dist/chunk-HT54OLPE.mjs.map +1 -0
  31. package/packages/core/dist/{chunk-BS2QCAJX.mjs → chunk-NF4ZHNTC.mjs} +169 -25
  32. package/packages/core/dist/chunk-NF4ZHNTC.mjs.map +1 -0
  33. package/packages/core/dist/{chunk-UOPVGCOB.mjs → chunk-NXQF73EC.mjs} +3 -3
  34. package/packages/core/dist/{chunk-UOPVGCOB.mjs.map → chunk-NXQF73EC.mjs.map} +1 -1
  35. package/packages/core/dist/{chunk-LFWZEO2L.mjs → chunk-SGL4JGCD.mjs} +3 -3
  36. package/packages/core/dist/{chunk-LFWZEO2L.mjs.map → chunk-SGL4JGCD.mjs.map} +1 -1
  37. package/packages/core/dist/{context-BHAgRjOe.d.cts → context-Ca5yK8Cs.d.cts} +3 -3
  38. package/packages/core/dist/{context-Blyjb5my.d.ts → context-D6cS4XIL.d.ts} +3 -3
  39. package/packages/core/dist/diff.d.cts +3 -3
  40. package/packages/core/dist/diff.d.ts +3 -3
  41. package/packages/core/dist/exporters.d.cts +3 -3
  42. package/packages/core/dist/exporters.d.ts +3 -3
  43. package/packages/core/dist/exporters.mjs +1 -1
  44. package/packages/core/dist/index-B259NKkH.d.cts +102 -0
  45. package/packages/core/dist/index-B9ZGvUVL.d.ts +102 -0
  46. package/packages/core/dist/{index-Bu_vOjql.d.ts → index-BsCcOKxy.d.ts} +4 -4
  47. package/packages/core/dist/{index-CmXMS-MF.d.cts → index-Xk9X-yjY.d.cts} +4 -4
  48. package/packages/core/dist/index.d.cts +6 -6
  49. package/packages/core/dist/index.d.ts +6 -6
  50. package/packages/core/dist/{inspect-event-DVg84S4v.d.cts → inspect-event-DRthdZlf.d.cts} +9 -0
  51. package/packages/core/dist/{inspect-event-DVg84S4v.d.ts → inspect-event-DRthdZlf.d.ts} +9 -0
  52. package/packages/core/dist/{log-config-BG1WmWf2.d.cts → log-config-CFlIJHTf.d.cts} +1 -1
  53. package/packages/core/dist/{log-config-Ck0aT_Ou.d.ts → log-config-OZRfpHED.d.ts} +1 -1
  54. package/packages/core/dist/logs.cjs +95 -15
  55. package/packages/core/dist/logs.cjs.map +1 -1
  56. package/packages/core/dist/logs.d.cts +3 -3
  57. package/packages/core/dist/logs.d.ts +3 -3
  58. package/packages/core/dist/logs.mjs +2 -2
  59. package/packages/core/dist/{persisted-inspect-event-ChE7pGb7.d.ts → persisted-inspect-event-BVucFVrP.d.ts} +1 -1
  60. package/packages/core/dist/{persisted-inspect-event-d-mSP8kd.d.cts → persisted-inspect-event-CVZWZldL.d.cts} +1 -1
  61. package/packages/core/dist/persisted.cjs +95 -15
  62. package/packages/core/dist/persisted.cjs.map +1 -1
  63. package/packages/core/dist/persisted.d.cts +5 -5
  64. package/packages/core/dist/persisted.d.ts +5 -5
  65. package/packages/core/dist/persisted.mjs +3 -3
  66. package/packages/core/dist/readers.cjs +203 -18
  67. package/packages/core/dist/readers.cjs.map +1 -1
  68. package/packages/core/dist/readers.d.cts +27 -78
  69. package/packages/core/dist/readers.d.ts +27 -78
  70. package/packages/core/dist/readers.mjs +4 -3
  71. package/packages/core/dist/{types-MuwXSJ4b.d.ts → types--ainI31J.d.ts} +1 -1
  72. package/packages/core/dist/{types-BLX3tiOW.d.cts → types-UnrNaTo2.d.cts} +1 -1
  73. package/packages/core/dist/writers.d.cts +2 -2
  74. package/packages/core/dist/writers.d.ts +2 -2
  75. package/packages/cli/dist/chunk-MEO2Z3KE.mjs.map +0 -1
  76. package/packages/core/dist/chunk-BS2QCAJX.mjs.map +0 -1
  77. package/packages/core/dist/chunk-CTA6XNDP.mjs.map +0 -1
  78. package/packages/core/dist/chunk-T5MASTIW.mjs +0 -94
  79. package/packages/core/dist/chunk-T5MASTIW.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 6.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - e70e3be: LangGraph fidelity classes A–E and persisted-trace developer APIs: relationship conformance, scaffolding diagnostics, openTraceFile/Directory/Text, TraceFacts/TraceContract conveniences, and stable AI\_\* remediation codes. No schema break; no new packages; no default network.
8
+
9
+ ## 6.14.2
10
+
11
+ ### Patch Changes
12
+
13
+ - 4850b62: Swarm relationship and safety precision: fix self-parent capture/ordering, normalize legacy self-edges, cycle-safe trees, and stop treating token-configuration fields as credentials.
14
+
3
15
  ## 6.14.1
4
16
 
5
17
  ### Patch Changes
@@ -8,9 +20,9 @@
8
20
 
9
21
  ## Unreleased
10
22
 
11
- ### Patch
23
+ ### Minor
12
24
 
13
- - (pending 6.14.1) Public positioning, documentation truth, and AI discoverability refresh.
25
+ - LangGraph fidelity classes A–E and persisted-trace developer APIs (6.15.0): relationship conformance corpus, ambiguous scaffolding diagnostics, `openTraceFile` / `openTraceDirectory` / `openTraceText`, `buildTraceFacts(TraceReadResult)`, `evaluateTraceContractRead`, stable `AI_*` programmatic diagnostics with remediation, ESM/CJS quickstarts, and A–E cross-surface semantic parity. No schema break; no new packages; no default network.
14
26
 
15
27
  ## 6.14.0
16
28
 
package/README.md CHANGED
@@ -157,7 +157,7 @@ Details: [Safe sharing](https://github.com/rajudandigam/agent-inspect/blob/main/
157
157
 
158
158
  ## Project status
159
159
 
160
- **Current release:** **6.14.1** · schema **1.0** · Node.js **≥ 20** · **MIT** · **actively maintained** (eighteen linked npm packages).
160
+ **Current release:** **6.14.2** · schema **1.0** · Node.js **≥ 20** · **MIT** · **actively maintained** (eighteen linked npm packages).
161
161
 
162
162
  The 6.14 line is actively maintained for correctness, compatibility, documentation, security, and framework evolution.
163
163
 
package/docs/API.md CHANGED
@@ -487,8 +487,12 @@ import {
487
487
  detectTraceFormat,
488
488
  openInferenceJsonReader,
489
489
  openTrace,
490
+ openTraceDirectory,
491
+ openTraceFile,
492
+ openTraceText,
490
493
  otlpJsonReader,
491
494
  readTrace,
495
+ formatProgrammaticDiagnostic,
492
496
  } from "agent-inspect/readers";
493
497
  import type { TraceReader } from "agent-inspect/readers";
494
498
  ```
@@ -498,12 +502,14 @@ import type { TraceReader } from "agent-inspect/readers";
498
502
  - **`detectTraceFormat(input, { readers?, format? })`**: deterministic, conservative format detection. Explicit `format` acts as an override only when a matching reader is registered.
499
503
  - **`readTrace(input, { readers?, format? })`**: detects a reader and returns `TraceReadResult`; unsupported or ambiguous input throws `TraceReadError`.
500
504
  - **`openTrace(input, options?)`**: alias for `readTrace()` and the API path used by the universal `agent-inspect open` command.
505
+ - **`openTraceFile(path)` / `openTraceDirectory(path)` / `openTraceText(content)`**: additive conveniences that wrap structured `TraceInput` (prefer these over bare path strings).
506
+ - **`assertTraceInput` / `formatProgrammaticDiagnostic`**: runtime input guard and stable `AI_*` message helpers (lowercase `TraceReadError.code` values remain published).
501
507
  - **`agentInspectJsonlReader`**: built-in local AgentInspect JSONL reader for v0.1, v0.2, and mixed files/directories.
502
508
  - **`openInferenceJsonReader`**: local OpenInference JSON compatibility reader. Prompt/output-like attributes are summarized and bounded rather than stored as raw content.
503
509
  - **`otlpJsonReader`**: local OTLP/HTTP JSON trace payload reader. Resource, scope, span, status, event, and parent metadata are preserved where possible with warnings for unsupported fields.
504
510
  - **`DEFAULT_TRACE_READERS`**: ordered built-in reader registry used when no custom `readers` array is supplied.
505
511
 
506
- The reader contract does not silently accept arbitrary JSON and does not add OTel SDK, database, hosted ingestion, or network upload dependencies.
512
+ The reader contract does not silently accept arbitrary JSON and does not add OTel SDK, database, hosted ingestion, or network upload dependencies. See also [PROGRAMMATIC-TRACE-ANALYSIS.md](./PROGRAMMATIC-TRACE-ANALYSIS.md).
507
513
 
508
514
  ## 21. Experimental Checks
509
515
 
@@ -512,11 +518,21 @@ The reader contract does not silently accept arbitrary JSON and does not add OTe
512
518
  Import from `agent-inspect/checks`:
513
519
 
514
520
  ```ts
515
- import { runTraceChecks } from "agent-inspect/checks";
516
- import type { TraceCheckRule, TraceCheckResult } from "agent-inspect/checks";
521
+ import {
522
+ runTraceChecks,
523
+ buildTraceFacts,
524
+ defineTraceContract,
525
+ evaluateTraceContract,
526
+ evaluateTraceContractRead,
527
+ formatProgrammaticDiagnostic,
528
+ } from "agent-inspect/checks";
529
+ import type { TraceCheckRule, TraceCheckResult, TraceFacts } from "agent-inspect/checks";
517
530
  ```
518
531
 
519
532
  - **`runTraceChecks({ read }, { rules?, select?, runId? })`**: executes provided rules against a `TraceReadResult` from `agent-inspect/readers`.
533
+ - **`buildTraceFacts(read | events)`**: experimental TraceFacts over logical projection; accepts `TraceReadResult` or normalized `PersistedInspectEvent[]`.
534
+ - **`defineTraceContract` / `evaluateTraceContract` / `evaluateTraceContractRead`**: experimental contract helpers; `evaluateTraceContractRead(read, contract)` wraps `{ read }`.
535
+ - **`formatProgrammaticDiagnostic` / `PROGRAMMATIC_DIAGNOSTIC_SPECS`**: stable `AI_*` codes with remediation hints.
520
536
  - **Built-in rule factories**: run, tool, LLM, structure, retrieval, guardrail, decision, safety, and baseline helpers including `createRunStatusRule`, `createToolUsageRule`, `createLlmUsageRule`, `createStructureOrphanRule`, `createStructureCycleRule`, `createStructureRelationshipRule`, `createRetrievalRule`, `createGuardrailRule`, `createDecisionRule`, `createSafetyRawContentRule`, `createSafetySecretPatternRule`, and `createBaselineRegressionRule`.
521
537
  - **`TraceCheckRule`**: synchronous pure rule contract.
522
538
  - **`TraceCheckResult`**: deterministic aggregate result with findings, evidence, summary counts, and execution diagnostics.
@@ -33,8 +33,9 @@ AgentInspect is **local-first** and **CLI-first**. These behaviors are intention
33
33
  - **LangGraph support** is currently a documented boundary through `@agent-inspect/langchain`, not a dedicated package.
34
34
  - **LangChain adapter** captures **metadata-oriented** signals by default; it does not replace full framework observability.
35
35
  - **LangChain `stream: true`** records chunk counts and timing only — not a full token replay. Per-token JSONL events are not emitted.
36
+ - **Deep swarm / nested RunnableSequence (6.14.2+):** capture resolves parents before registering child indexes and rejects `parentId === stepId`. Legacy traces that still contain self-parent edges are normalized in logical projection (`AI_LOGICAL_SELF_PARENT_REMOVED`) and rendered with visibility-first, cycle-safe trees so nested LLM/tool steps remain visible.
36
37
  - **Correlation metadata** (`correlationId`, `requestId`, `decisionId`, `groupId`) is written on `run_started` but **CLI list/view does not filter by correlation fields** yet.
37
- - **Built-in check/contract semantics (6.12.2+)** use an additive `logicalEvents` projection that pairs v0.1 start/complete rows. Custom rules that only read raw `context.events` still see bridged `running` TOOL starts and separate LOGIC completions—opt into `logicalEvents` for lifecycle-aware matching. Formal `TraceFacts` promotion is planned for 6.13.
38
+ - **Built-in check/contract semantics (6.12.2+)** use an additive `logicalEvents` projection that pairs v0.1 start/complete rows. Custom rules that only read raw `context.events` still see bridged `running` TOOL starts and separate LOGIC completions—opt into `logicalEvents` for lifecycle-aware matching. Formal `TraceFacts` promotion shipped experimentally in 6.13.
38
39
 
39
40
  ## Structured log parsing
40
41
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-inspect",
3
- "version": "6.14.1",
3
+ "version": "6.15.0",
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",
@@ -234,7 +234,7 @@
234
234
  "test:all": "pnpm run typecheck && pnpm run linked-versions:check && pnpm run build && pnpm run test && pnpm run size",
235
235
  "prepublish:checks": "pnpm run typecheck && pnpm run test && pnpm run test:coverage && pnpm run build && pnpm run fixtures:check && pnpm run recipes:check && pnpm run size && pnpm run linked-versions:check && pnpm run pack:smoke",
236
236
  "pack:dry-run": "pnpm run build && npm pack --dry-run",
237
- "pack:smoke": "pnpm run build && node scripts/package-smoke.mjs && node scripts/packed-quickstart-e2e.mjs && node scripts/packed-semantic-loop-e2e.mjs",
237
+ "pack:smoke": "pnpm run build && node scripts/package-smoke.mjs && node scripts/packed-quickstart-e2e.mjs && node scripts/packed-semantic-loop-e2e.mjs && node scripts/packed-swarm-loop-e2e.mjs",
238
238
  "linked-versions:check": "node scripts/check-linked-versions.mjs",
239
239
  "docs:commands": "node scripts/validate-doc-commands.mjs",
240
240
  "docs:links": "node scripts/validate-doc-links.mjs",
@@ -5852,6 +5852,59 @@ function defaultSuiteConfigTemplate() {
5852
5852
  };
5853
5853
  }
5854
5854
 
5855
+ // packages/core/src/diagnostics/programmatic.ts
5856
+ var PROGRAMMATIC_DIAGNOSTIC_SPECS = Object.freeze({
5857
+ AI_TRACE_INPUT_INVALID: {
5858
+ code: "AI_TRACE_INPUT_INVALID",
5859
+ summary: 'Expected { type: "file", path }, { type: "directory", path }, { type: "string", content }, { type: "buffer", content }, or { type: "stdin" }.',
5860
+ remediation: "For a file path, use openTraceFile(path).",
5861
+ relatedCodes: ["invalid_input"]
5862
+ },
5863
+ AI_TRACE_FORMAT_UNSUPPORTED: {
5864
+ code: "AI_TRACE_FORMAT_UNSUPPORTED",
5865
+ summary: "No trace reader could detect the input format.",
5866
+ remediation: "Pass an AgentInspect JSONL file via openTraceFile, or set options.format to a registered reader.",
5867
+ relatedCodes: ["unsupported_format"]
5868
+ },
5869
+ AI_TRACE_FORMAT_AMBIGUOUS: {
5870
+ code: "AI_TRACE_FORMAT_AMBIGUOUS",
5871
+ summary: "Multiple trace readers matched the input with equal confidence.",
5872
+ remediation: "Set options.format explicitly to disambiguate the reader.",
5873
+ relatedCodes: ["ambiguous_format"]
5874
+ },
5875
+ AI_TRACE_FACTS_INPUT_NOT_NORMALIZED: {
5876
+ code: "AI_TRACE_FACTS_INPUT_NOT_NORMALIZED",
5877
+ summary: "TraceFacts requires TraceReadResult or PersistedInspectEvent[].",
5878
+ remediation: "Use openTraceFile() to normalize a JSONL trace first."
5879
+ },
5880
+ AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED: {
5881
+ code: "AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED",
5882
+ summary: "Multiple runs are available; select a run before executing checks.",
5883
+ remediation: "Pass options.runId or TraceCheckInput.selectedRun.",
5884
+ relatedCodes: ["AI_CHECK_RUN_SELECTION_REQUIRED"]
5885
+ },
5886
+ AI_TRACE_RELATIONSHIP_SELF_PARENT: {
5887
+ code: "AI_TRACE_RELATIONSHIP_SELF_PARENT",
5888
+ summary: "A parentId equals its own event/step id.",
5889
+ remediation: "Reject at capture (AI_LANGGRAPH_SELF_PARENT_REJECTED) or drop via logical projection; do not invent replacement parents.",
5890
+ relatedCodes: [
5891
+ "AI_LANGGRAPH_SELF_PARENT_REJECTED",
5892
+ "AI_LOGICAL_SELF_PARENT_REMOVED"
5893
+ ]
5894
+ },
5895
+ AI_TRACE_RELATIONSHIP_CYCLE: {
5896
+ code: "AI_TRACE_RELATIONSHIP_CYCLE",
5897
+ summary: "Trace contains a parentId cycle.",
5898
+ remediation: "Use visibility-first tree linking for legacy fixtures; prefer acyclic capture for new adapter output.",
5899
+ relatedCodes: ["structure.cycle"]
5900
+ }
5901
+ });
5902
+ function formatProgrammaticDiagnostic(code, detail) {
5903
+ const spec = PROGRAMMATIC_DIAGNOSTIC_SPECS[code];
5904
+ const summary = detail?.trim() ? detail.trim() : spec.summary;
5905
+ return `${code}: ${summary} Remediation: ${spec.remediation}`;
5906
+ }
5907
+
5855
5908
  // packages/core/src/checks/logical-events.ts
5856
5909
  function isRecord7(value) {
5857
5910
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -6047,6 +6100,26 @@ function projectLogicalEvents(events) {
6047
6100
  }
6048
6101
  }
6049
6102
  if (!remapped) {
6103
+ if (originalParentId === event.eventId) {
6104
+ diagnostics.push({
6105
+ code: "AI_LOGICAL_SELF_PARENT_REMOVED",
6106
+ message: formatProgrammaticDiagnostic(
6107
+ "AI_TRACE_RELATIONSHIP_SELF_PARENT",
6108
+ `Removed self-parent edge on ${event.eventId}.`
6109
+ ),
6110
+ eventIds: [event.eventId]
6111
+ });
6112
+ const { parentId: _drop, ...rest } = event;
6113
+ normalized.push({
6114
+ ...rest,
6115
+ projection: {
6116
+ ...event.projection,
6117
+ parentNormalized: true,
6118
+ originalParentId
6119
+ }
6120
+ });
6121
+ continue;
6122
+ }
6050
6123
  if (!logicalById.has(originalParentId) && !logicalByRawId.has(originalParentId)) {
6051
6124
  const mapping = event.attributes?.parentMapping;
6052
6125
  const unresolved = mapping === "unresolved" || event.attributes?.parentUnresolved === true || event.attributes?.unresolvedParent === true || // LangGraph/framework scaffolding sentinel labels are not event ids.
@@ -6062,6 +6135,26 @@ function projectLogicalEvents(events) {
6062
6135
  normalized.push(event);
6063
6136
  continue;
6064
6137
  }
6138
+ if (nextParent === event.eventId) {
6139
+ diagnostics.push({
6140
+ code: "AI_LOGICAL_SELF_PARENT_REMOVED",
6141
+ message: formatProgrammaticDiagnostic(
6142
+ "AI_TRACE_RELATIONSHIP_SELF_PARENT",
6143
+ `Removed self-parent edge on ${event.eventId} (was ${originalParentId}).`
6144
+ ),
6145
+ eventIds: [event.eventId]
6146
+ });
6147
+ const { parentId: _drop, ...rest } = event;
6148
+ normalized.push({
6149
+ ...rest,
6150
+ projection: {
6151
+ ...event.projection,
6152
+ parentNormalized: true,
6153
+ originalParentId
6154
+ }
6155
+ });
6156
+ continue;
6157
+ }
6065
6158
  diagnostics.push({
6066
6159
  code: "AI_LOGICAL_PARENT_REMAPPED",
6067
6160
  message: `Remapped parent ${originalParentId} \u2192 ${nextParent} for ${event.eventId}.`,
@@ -6134,6 +6227,76 @@ function summarizeSemanticParity(events) {
6134
6227
  diagnostics: projection.diagnostics
6135
6228
  };
6136
6229
  }
6230
+ formatProgrammaticDiagnostic(
6231
+ "AI_TRACE_FACTS_INPUT_NOT_NORMALIZED"
6232
+ );
6233
+
6234
+ // packages/core/src/safety/sensitive-key.ts
6235
+ function normalizeSensitiveKey(value) {
6236
+ return value.toLowerCase().replace(/[^a-z0-9_]/g, "");
6237
+ }
6238
+ var NON_CREDENTIAL_TOKEN_CONFIG_KEYS = new Set(
6239
+ [
6240
+ "tokens",
6241
+ "max_tokens",
6242
+ "min_tokens",
6243
+ "ls_max_tokens",
6244
+ "token_count",
6245
+ "token_limit",
6246
+ "token_budget",
6247
+ "input_tokens",
6248
+ "output_tokens",
6249
+ "total_tokens",
6250
+ "cached_tokens",
6251
+ "prompt_tokens",
6252
+ "completion_tokens"
6253
+ ].map(normalizeSensitiveKey)
6254
+ );
6255
+ var DEFAULT_CREDENTIAL_SENSITIVE_KEYS = [
6256
+ "authorization",
6257
+ "cookie",
6258
+ "token",
6259
+ "access_token",
6260
+ "accesstoken",
6261
+ "auth_token",
6262
+ "authtoken",
6263
+ "refresh_token",
6264
+ "refreshtoken",
6265
+ "id_token",
6266
+ "idtoken",
6267
+ "bearer_token",
6268
+ "bearertoken",
6269
+ "api_token",
6270
+ "apitoken",
6271
+ "apikey",
6272
+ "api_key",
6273
+ "password",
6274
+ "secret",
6275
+ "email"
6276
+ ];
6277
+ function isTokenCredentialKey(normalized) {
6278
+ if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;
6279
+ if (normalized === "token") return true;
6280
+ if (normalized.endsWith("tokens")) return false;
6281
+ return normalized.endsWith("token");
6282
+ }
6283
+ function isCredentialSensitiveKey(key, sensitiveKeys = DEFAULT_CREDENTIAL_SENSITIVE_KEYS) {
6284
+ if (!key) return false;
6285
+ const normalized = normalizeSensitiveKey(key);
6286
+ if (!normalized) return false;
6287
+ if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;
6288
+ for (const sensitive of sensitiveKeys) {
6289
+ const s = normalizeSensitiveKey(sensitive);
6290
+ if (!s) continue;
6291
+ if (s === "token") {
6292
+ if (isTokenCredentialKey(normalized)) return true;
6293
+ continue;
6294
+ }
6295
+ if (normalized === s) return true;
6296
+ if (normalized.endsWith(`_${s}`) || normalized.startsWith(`${s}_`)) return true;
6297
+ }
6298
+ return false;
6299
+ }
6137
6300
 
6138
6301
  // packages/core/src/checks/index.ts
6139
6302
  var SEVERITY_RANK = {
@@ -6152,16 +6315,7 @@ var CONFIDENCE_RANK = {
6152
6315
  correlated: 2,
6153
6316
  explicit: 3
6154
6317
  };
6155
- var DEFAULT_SENSITIVE_KEYS = [
6156
- "authorization",
6157
- "cookie",
6158
- "token",
6159
- "apikey",
6160
- "api_key",
6161
- "password",
6162
- "secret",
6163
- "email"
6164
- ];
6318
+ var DEFAULT_SENSITIVE_KEYS = DEFAULT_CREDENTIAL_SENSITIVE_KEYS;
6165
6319
  var DEFAULT_RAW_CONTENT_KEYS = [
6166
6320
  "body",
6167
6321
  "headers",
@@ -6319,7 +6473,13 @@ function resolveSelectedRun(input, runId) {
6319
6473
  if (input.read.runs.length === 0) {
6320
6474
  return {
6321
6475
  diagnostics: [
6322
- diagnostic3("AI_CHECK_RUN_SELECTION_REQUIRED", "No runs are available for checks.")
6476
+ diagnostic3(
6477
+ "AI_CHECK_RUN_SELECTION_REQUIRED",
6478
+ formatProgrammaticDiagnostic(
6479
+ "AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED",
6480
+ "No runs are available for checks."
6481
+ )
6482
+ )
6323
6483
  ]
6324
6484
  };
6325
6485
  }
@@ -6327,7 +6487,7 @@ function resolveSelectedRun(input, runId) {
6327
6487
  diagnostics: [
6328
6488
  diagnostic3(
6329
6489
  "AI_CHECK_RUN_SELECTION_REQUIRED",
6330
- "Multiple runs are available; select a run before executing checks."
6490
+ formatProgrammaticDiagnostic("AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED")
6331
6491
  )
6332
6492
  ]
6333
6493
  };
@@ -6583,9 +6743,7 @@ function hasRedactionMarker(value, markers) {
6583
6743
  return markers.some((marker) => value.includes(marker)) || /^\[HASH:[A-Za-z0-9_-]+\]$/.test(value);
6584
6744
  }
6585
6745
  function isSensitiveKey(key, sensitiveKeys) {
6586
- if (!key) return false;
6587
- const normalized = normalizedKey(key);
6588
- return sensitiveKeys.some((sensitive) => normalized.includes(normalizedKey(sensitive)));
6746
+ return isCredentialSensitiveKey(key, sensitiveKeys);
6589
6747
  }
6590
6748
  function isRawContentKey(key, forbiddenKeys) {
6591
6749
  if (!key) return false;
@@ -6908,7 +7066,7 @@ function createToolUsageRule(options) {
6908
7066
  }
6909
7067
  }
6910
7068
  const forbidden = new Set(options.forbidden ?? []);
6911
- const allowed = options.allowed ? new Set(options.allowed) : void 0;
7069
+ const allowed = options.allowed?.length ? new Set(options.allowed) : void 0;
6912
7070
  for (const event of tools) {
6913
7071
  const name = toolName(event);
6914
7072
  if (forbidden.has(name)) {
@@ -6944,9 +7102,9 @@ function createLlmUsageRule(options) {
6944
7102
  evaluate(context) {
6945
7103
  const llms = finishedEvents(context, "LLM");
6946
7104
  const findings = [];
6947
- const allowedModels = options.allowedModels ? new Set(options.allowedModels) : void 0;
6948
- const allowedProviders = options.allowedProviders ? new Set(options.allowedProviders) : void 0;
6949
- const finishReasons = options.finishReasons ? new Set(options.finishReasons) : void 0;
7105
+ const allowedModels = options.allowedModels?.length ? new Set(options.allowedModels) : void 0;
7106
+ const allowedProviders = options.allowedProviders?.length ? new Set(options.allowedProviders) : void 0;
7107
+ const finishReasons = options.finishReasons?.length ? new Set(options.finishReasons) : void 0;
6950
7108
  if (options.maxCalls !== void 0 && llms.length > options.maxCalls) {
6951
7109
  findings.push(
6952
7110
  failFinding(
@@ -7058,7 +7216,7 @@ function createStructureCycleRule() {
7058
7216
  findings.push(
7059
7217
  failFinding(
7060
7218
  "structure.cycle",
7061
- "Trace contains a parentId cycle.",
7219
+ formatProgrammaticDiagnostic("AI_TRACE_RELATIONSHIP_CYCLE"),
7062
7220
  cycle.map((item) => eventEvidence(item, "parentId")),
7063
7221
  "acyclic parentId graph",
7064
7222
  cycle.map((item) => item.eventId).sort()
@@ -7895,6 +8053,20 @@ function traceEventsToPersistedInspectEvents(events, options) {
7895
8053
  function inc(map, key) {
7896
8054
  map[key] = (map[key] ?? 0) + 1;
7897
8055
  }
8056
+ function confidenceRank(confidence) {
8057
+ switch (confidence) {
8058
+ case "unknown":
8059
+ return 0;
8060
+ case "heuristic":
8061
+ return 1;
8062
+ case "correlated":
8063
+ return 2;
8064
+ case "explicit":
8065
+ return 3;
8066
+ default:
8067
+ return 0;
8068
+ }
8069
+ }
7898
8070
  function computeRunStatus(events) {
7899
8071
  let runTerminal;
7900
8072
  let sawRunEvent = false;
@@ -7915,6 +8087,84 @@ function computeRunStatus(events) {
7915
8087
  }
7916
8088
  return hasRunning ? "running" : "ok";
7917
8089
  }
8090
+ function linkNodesVisibilityFirst(nodes) {
8091
+ let selfParentCount = 0;
8092
+ let unresolvedParentCount = 0;
8093
+ let normalizedEdgeCount = 0;
8094
+ let cycleCount = 0;
8095
+ const pending = [];
8096
+ for (const node of nodes.values()) {
8097
+ const parentId = node.event.parentId;
8098
+ if (!parentId) continue;
8099
+ if (parentId === node.event.eventId) {
8100
+ selfParentCount += 1;
8101
+ normalizedEdgeCount += 1;
8102
+ continue;
8103
+ }
8104
+ if (!nodes.has(parentId)) {
8105
+ unresolvedParentCount += 1;
8106
+ continue;
8107
+ }
8108
+ pending.push({
8109
+ childId: node.event.eventId,
8110
+ parentId,
8111
+ childTimestamp: node.event.timestamp,
8112
+ childConfidence: node.event.confidence
8113
+ });
8114
+ }
8115
+ pending.sort((a, b) => {
8116
+ const conf = confidenceRank(b.childConfidence) - confidenceRank(a.childConfidence);
8117
+ if (conf !== 0) return conf;
8118
+ return a.childTimestamp - b.childTimestamp;
8119
+ });
8120
+ const parentOf = /* @__PURE__ */ new Map();
8121
+ for (const edge of pending) {
8122
+ parentOf.set(edge.childId, edge.parentId);
8123
+ let cursor = edge.parentId;
8124
+ const seen = /* @__PURE__ */ new Set([edge.childId]);
8125
+ let cyclic = false;
8126
+ while (cursor) {
8127
+ if (seen.has(cursor)) {
8128
+ cyclic = true;
8129
+ break;
8130
+ }
8131
+ seen.add(cursor);
8132
+ cursor = parentOf.get(cursor);
8133
+ }
8134
+ if (cyclic) {
8135
+ parentOf.delete(edge.childId);
8136
+ cycleCount += 1;
8137
+ normalizedEdgeCount += 1;
8138
+ }
8139
+ }
8140
+ for (const [childId, parentId] of parentOf) {
8141
+ nodes.get(parentId).children.push(nodes.get(childId));
8142
+ }
8143
+ const roots = [];
8144
+ for (const node of nodes.values()) {
8145
+ if (!parentOf.has(node.event.eventId)) {
8146
+ roots.push(node);
8147
+ }
8148
+ }
8149
+ const assignDepth = (n, depth, stack) => {
8150
+ if (stack.has(n.event.eventId)) return;
8151
+ n.depth = depth;
8152
+ stack.add(n.event.eventId);
8153
+ for (const c of n.children) assignDepth(c, depth + 1, stack);
8154
+ stack.delete(n.event.eventId);
8155
+ };
8156
+ for (const r of roots) assignDepth(r, 0, /* @__PURE__ */ new Set());
8157
+ return {
8158
+ roots,
8159
+ summary: {
8160
+ rootCount: roots.length,
8161
+ selfParentCount,
8162
+ cycleCount,
8163
+ unresolvedParentCount,
8164
+ normalizedEdgeCount
8165
+ }
8166
+ };
8167
+ }
7918
8168
  var TreeBuilder = class {
7919
8169
  constructor(options) {
7920
8170
  void options?.config;
@@ -7932,20 +8182,7 @@ var TreeBuilder = class {
7932
8182
  for (const e of sorted) {
7933
8183
  nodes.set(e.eventId, { event: e, children: [], depth: 0 });
7934
8184
  }
7935
- const roots = [];
7936
- for (const node of nodes.values()) {
7937
- const parentId = node.event.parentId;
7938
- if (parentId && nodes.has(parentId)) {
7939
- nodes.get(parentId).children.push(node);
7940
- } else {
7941
- roots.push(node);
7942
- }
7943
- }
7944
- const assignDepth = (n, depth) => {
7945
- n.depth = depth;
7946
- for (const c of n.children) assignDepth(c, depth + 1);
7947
- };
7948
- for (const r of roots) assignDepth(r, 0);
8185
+ const { roots, summary } = linkNodesVisibilityFirst(nodes);
7949
8186
  const confidenceBreakdown = {
7950
8187
  explicit: 0,
7951
8188
  correlated: 0,
@@ -7973,7 +8210,8 @@ var TreeBuilder = class {
7973
8210
  metadata: {
7974
8211
  totalEvents: sorted.length,
7975
8212
  confidenceBreakdown,
7976
- kinds
8213
+ kinds,
8214
+ relationshipSummary: summary
7977
8215
  }
7978
8216
  });
7979
8217
  }
@@ -8202,6 +8440,38 @@ var TraceReadError = class extends Error {
8202
8440
  this.warnings = warnings;
8203
8441
  }
8204
8442
  };
8443
+ var TRACE_INPUT_INVALID_MESSAGE = formatProgrammaticDiagnostic(
8444
+ "AI_TRACE_INPUT_INVALID"
8445
+ );
8446
+ function isTraceInput(input) {
8447
+ if (typeof input !== "object" || input === null || Array.isArray(input)) {
8448
+ return false;
8449
+ }
8450
+ const record = input;
8451
+ switch (record.type) {
8452
+ case "file":
8453
+ case "directory":
8454
+ return typeof record.path === "string";
8455
+ case "string":
8456
+ return typeof record.content === "string";
8457
+ case "buffer":
8458
+ return Buffer.isBuffer(record.content);
8459
+ case "stdin":
8460
+ return true;
8461
+ default:
8462
+ return false;
8463
+ }
8464
+ }
8465
+ function assertTraceInput(input) {
8466
+ if (isTraceInput(input)) return;
8467
+ throw new TraceReadError("invalid_input", TRACE_INPUT_INVALID_MESSAGE, [
8468
+ {
8469
+ code: "AI_TRACE_INPUT_INVALID",
8470
+ message: TRACE_INPUT_INVALID_MESSAGE,
8471
+ severity: "error"
8472
+ }
8473
+ ]);
8474
+ }
8205
8475
  function normalizeCandidate(reader, candidate) {
8206
8476
  const confidence = Number.isFinite(candidate.confidence) ? Math.max(0, Math.min(1, candidate.confidence)) : 0;
8207
8477
  return {
@@ -9556,6 +9826,7 @@ var DEFAULT_TRACE_READERS = [
9556
9826
  otlpJsonReader
9557
9827
  ];
9558
9828
  async function detectTraceFormat(input, options = {}) {
9829
+ assertTraceInput(input);
9559
9830
  const readers = options.readers ?? DEFAULT_TRACE_READERS;
9560
9831
  if (options.format !== void 0) {
9561
9832
  const reader = findReaderByFormat(options.format, readers);
@@ -9652,19 +9923,20 @@ async function detectTraceFormat(input, options = {}) {
9652
9923
  };
9653
9924
  }
9654
9925
  async function readTrace(input, options = {}) {
9926
+ assertTraceInput(input);
9655
9927
  const readers = options.readers ?? DEFAULT_TRACE_READERS;
9656
9928
  const detection = await detectTraceFormat(input, options);
9657
9929
  if (detection.status === "unsupported" || detection.format === void 0) {
9658
9930
  throw new TraceReadError(
9659
9931
  "unsupported_format",
9660
- "No trace reader could detect the input format.",
9932
+ formatProgrammaticDiagnostic("AI_TRACE_FORMAT_UNSUPPORTED"),
9661
9933
  detection.warnings
9662
9934
  );
9663
9935
  }
9664
9936
  if (detection.status === "ambiguous") {
9665
9937
  throw new TraceReadError(
9666
9938
  "ambiguous_format",
9667
- "Multiple trace readers matched the input with equal confidence.",
9939
+ formatProgrammaticDiagnostic("AI_TRACE_FORMAT_AMBIGUOUS"),
9668
9940
  detection.warnings
9669
9941
  );
9670
9942
  }
@@ -9672,7 +9944,10 @@ async function readTrace(input, options = {}) {
9672
9944
  if (!reader) {
9673
9945
  throw new TraceReadError(
9674
9946
  "unsupported_format",
9675
- `No trace reader is registered for format "${detection.format}".`,
9947
+ formatProgrammaticDiagnostic(
9948
+ "AI_TRACE_FORMAT_UNSUPPORTED",
9949
+ `No trace reader is registered for format "${detection.format}".`
9950
+ ),
9676
9951
  detection.warnings
9677
9952
  );
9678
9953
  }
@@ -11045,6 +11320,6 @@ function renderGateReport(result, options = {}) {
11045
11320
  return renderGateSummaryMarkdown(result);
11046
11321
  }
11047
11322
 
11048
- 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, 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 };
11049
- //# sourceMappingURL=chunk-MEO2Z3KE.mjs.map
11050
- //# sourceMappingURL=chunk-MEO2Z3KE.mjs.map
11323
+ 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 };
11324
+ //# sourceMappingURL=chunk-LFSBMUCD.mjs.map
11325
+ //# sourceMappingURL=chunk-LFSBMUCD.mjs.map