@agent-inspect/mcp-server 6.17.3 → 6.17.5

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/README.md CHANGED
@@ -42,6 +42,12 @@ npx @agent-inspect/mcp-server --dir .agent-inspect
42
42
  | `compare_runs` | Structural diff |
43
43
  | `create_share_checked_evidence` | Share-gated Evidence package |
44
44
 
45
+ ### First causal failure ambiguity
46
+
47
+ Unlinked failures remain unrelated. `get_first_causal_failure` does not infer
48
+ causal parents from event adjacency or timing alone, so ambiguous relationships
49
+ remain explicit rather than being fabricated.
50
+
45
51
  Results are redacted (share profile by default), bounded, and deterministic for the same inputs.
46
52
 
47
53
  ## Privacy
@@ -2622,8 +2622,11 @@ function formatProgrammaticDiagnostic(code, detail) {
2622
2622
  }
2623
2623
 
2624
2624
  // packages/core/src/safety/sensitive-key.ts
2625
+ function keyHasExplicitSeparator(value) {
2626
+ return /[_\-.]/.test(value);
2627
+ }
2625
2628
  function normalizeSensitiveKey(value) {
2626
- return value.toLowerCase().replace(/[^a-z0-9_]/g, "");
2629
+ return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
2627
2630
  }
2628
2631
  var NON_CREDENTIAL_TOKEN_CONFIG_KEYS = new Set(
2629
2632
  [
@@ -2675,6 +2678,7 @@ function isCredentialSensitiveKey(key, sensitiveKeys = DEFAULT_CREDENTIAL_SENSIT
2675
2678
  const normalized = normalizeSensitiveKey(key);
2676
2679
  if (!normalized) return false;
2677
2680
  if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;
2681
+ const allowPrefixCompound = keyHasExplicitSeparator(key);
2678
2682
  for (const sensitive of sensitiveKeys) {
2679
2683
  const s = normalizeSensitiveKey(sensitive);
2680
2684
  if (!s) continue;
@@ -2683,7 +2687,8 @@ function isCredentialSensitiveKey(key, sensitiveKeys = DEFAULT_CREDENTIAL_SENSIT
2683
2687
  continue;
2684
2688
  }
2685
2689
  if (normalized === s) return true;
2686
- if (normalized.endsWith(`_${s}`) || normalized.startsWith(`${s}_`)) return true;
2690
+ if (normalized.endsWith(`_${s}`)) return true;
2691
+ if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;
2687
2692
  }
2688
2693
  return false;
2689
2694
  }
@@ -3168,10 +3173,11 @@ function emptySummary() {
3168
3173
  passed: 0,
3169
3174
  failed: 0,
3170
3175
  warnings: 0,
3171
- errors: 0
3176
+ errors: 0,
3177
+ rulesEvaluated: 0
3172
3178
  };
3173
3179
  }
3174
- function errorResult(input, diagnostics, selectedRun) {
3180
+ function errorResult(input, diagnostics, selectedRun, ruleExecutions = []) {
3175
3181
  return {
3176
3182
  ok: false,
3177
3183
  status: "error",
@@ -3179,10 +3185,12 @@ function errorResult(input, diagnostics, selectedRun) {
3179
3185
  ...selectedRun ? { runId: selectedRun.runId } : {},
3180
3186
  summary: {
3181
3187
  ...emptySummary(),
3182
- errors: diagnostics.filter((item) => item.severity === "error").length
3188
+ errors: diagnostics.filter((item) => item.severity === "error").length,
3189
+ rulesEvaluated: ruleExecutions.length
3183
3190
  },
3184
3191
  findings: [],
3185
- diagnostics: [...diagnostics]
3192
+ diagnostics: [...diagnostics],
3193
+ ruleExecutions: [...ruleExecutions]
3186
3194
  };
3187
3195
  }
3188
3196
  function flattenNodes(nodes) {
@@ -3338,7 +3346,7 @@ function normalizeFinding(rule, finding) {
3338
3346
  ...finding.action !== void 0 ? { action: finding.action } : {}
3339
3347
  };
3340
3348
  }
3341
- function summarize(findings, diagnostics) {
3349
+ function summarize(findings, diagnostics, rulesEvaluated) {
3342
3350
  return {
3343
3351
  passed: findings.filter((finding) => finding.status === "pass").length,
3344
3352
  failed: findings.filter(
@@ -3347,9 +3355,21 @@ function summarize(findings, diagnostics) {
3347
3355
  warnings: findings.filter(
3348
3356
  (finding) => finding.status === "warning" || finding.severity === "warning"
3349
3357
  ).length,
3350
- errors: diagnostics.filter((item) => item.severity === "error").length
3358
+ errors: diagnostics.filter((item) => item.severity === "error").length,
3359
+ rulesEvaluated
3351
3360
  };
3352
3361
  }
3362
+ function classifyRuleExecution(findings, threw) {
3363
+ if (findings.some((finding) => finding.status === "fail" && finding.severity === "error")) {
3364
+ return "fail";
3365
+ }
3366
+ if (findings.some(
3367
+ (finding) => finding.status === "warning" || finding.severity === "warning"
3368
+ )) {
3369
+ return "warning";
3370
+ }
3371
+ return "pass";
3372
+ }
3353
3373
  function eventEvidence(event, path16) {
3354
3374
  return {
3355
3375
  runId: event.runId,
@@ -3715,6 +3735,18 @@ function runTraceChecks(input, options = {}) {
3715
3735
  if (rules.diagnostics.length > 0) {
3716
3736
  return errorResult(input, rules.diagnostics, selected.run);
3717
3737
  }
3738
+ if (rules.rules.length === 0) {
3739
+ return errorResult(
3740
+ input,
3741
+ [
3742
+ diagnostic(
3743
+ "AI_CHECK_NO_RULES_EVALUATED",
3744
+ "No trace check rules were evaluated. Configure at least one rule, contract, or CLI check option."
3745
+ )
3746
+ ],
3747
+ selected.run
3748
+ );
3749
+ }
3718
3750
  const facts = buildFacts(input, selected.run);
3719
3751
  const context = {
3720
3752
  ...facts,
@@ -3723,22 +3755,38 @@ function runTraceChecks(input, options = {}) {
3723
3755
  };
3724
3756
  const diagnostics = [];
3725
3757
  const findings = [];
3758
+ const ruleExecutions = [];
3726
3759
  for (const rule of rules.rules) {
3727
3760
  try {
3728
- findings.push(...rule.evaluate(context).map((finding) => normalizeFinding(rule, finding)));
3761
+ const ruleFindings = rule.evaluate(context).map((finding) => normalizeFinding(rule, finding));
3762
+ findings.push(...ruleFindings);
3763
+ ruleExecutions.push({
3764
+ ruleId: rule.id,
3765
+ category: rule.category,
3766
+ status: classifyRuleExecution(ruleFindings, false),
3767
+ findingCount: ruleFindings.length,
3768
+ ...selected.run ? { runId: selected.run.runId } : {}
3769
+ });
3729
3770
  } catch (error) {
3730
3771
  const message = error instanceof Error ? error.message : String(error);
3731
3772
  diagnostics.push(
3732
3773
  diagnostic("AI_CHECK_INTERNAL_ERROR", `Rule ${rule.id} failed: ${message}`, rule.id)
3733
3774
  );
3775
+ ruleExecutions.push({
3776
+ ruleId: rule.id,
3777
+ category: rule.category,
3778
+ status: "error",
3779
+ findingCount: 0,
3780
+ ...selected.run ? { runId: selected.run.runId } : {}
3781
+ });
3734
3782
  }
3735
3783
  }
3736
3784
  if (diagnostics.length > 0) {
3737
- return errorResult(input, diagnostics, selected.run);
3785
+ return errorResult(input, diagnostics, selected.run, ruleExecutions);
3738
3786
  }
3739
3787
  const eventById = new Map(input.read.events.map((event) => [event.eventId, event]));
3740
3788
  const sortedFindings = findings.sort(compareFindings(eventById));
3741
- const summary = summarize(sortedFindings, diagnostics);
3789
+ const summary = summarize(sortedFindings, diagnostics, ruleExecutions.length);
3742
3790
  const status = summary.failed > 0 ? "fail" : "pass";
3743
3791
  return {
3744
3792
  ok: status === "pass",
@@ -3747,7 +3795,8 @@ function runTraceChecks(input, options = {}) {
3747
3795
  ...selected.run ? { runId: selected.run.runId } : {},
3748
3796
  summary,
3749
3797
  findings: sortedFindings,
3750
- diagnostics
3798
+ diagnostics,
3799
+ ruleExecutions
3751
3800
  };
3752
3801
  }
3753
3802
 
@@ -6634,8 +6683,11 @@ function exportRunTree(tree, options) {
6634
6683
  }
6635
6684
 
6636
6685
  // packages/redact/src/sensitive-key.ts
6686
+ function keyHasExplicitSeparator2(value) {
6687
+ return /[_\-.]/.test(value);
6688
+ }
6637
6689
  function normalizeSensitiveKey2(value) {
6638
- return value.toLowerCase().replace(/[^a-z0-9_]/g, "");
6690
+ return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
6639
6691
  }
6640
6692
  var NON_CREDENTIAL_TOKEN_CONFIG_KEYS2 = new Set(
6641
6693
  [
@@ -6665,6 +6717,7 @@ function isCredentialSensitiveKey2(key, sensitiveKeys) {
6665
6717
  const normalized = normalizeSensitiveKey2(key);
6666
6718
  if (!normalized) return false;
6667
6719
  if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS2.has(normalized)) return false;
6720
+ const allowPrefixCompound = keyHasExplicitSeparator2(key);
6668
6721
  for (const sensitive of sensitiveKeys) {
6669
6722
  const s = normalizeSensitiveKey2(sensitive);
6670
6723
  if (!s) continue;
@@ -6673,7 +6726,8 @@ function isCredentialSensitiveKey2(key, sensitiveKeys) {
6673
6726
  continue;
6674
6727
  }
6675
6728
  if (normalized === s) return true;
6676
- if (normalized.endsWith(`_${s}`) || normalized.startsWith(`${s}_`)) return true;
6729
+ if (normalized.endsWith(`_${s}`)) return true;
6730
+ if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;
6677
6731
  }
6678
6732
  return false;
6679
6733
  }
@@ -7949,5 +8003,5 @@ async function runReadOnlyMcpServer(options = {}) {
7949
8003
  }
7950
8004
 
7951
8005
  export { MCP_MAX_REQUEST_BYTES, MCP_PROTOCOL_VERSION, READ_ONLY_TOOLS, callReadOnlyTool, createMcpServerContext, handleMcpProtocolLine, runReadOnlyMcpServer };
7952
- //# sourceMappingURL=chunk-RAYFTVFK.mjs.map
7953
- //# sourceMappingURL=chunk-RAYFTVFK.mjs.map
8006
+ //# sourceMappingURL=chunk-GMXH2CU3.mjs.map
8007
+ //# sourceMappingURL=chunk-GMXH2CU3.mjs.map