agent-inspect 6.10.0 → 6.12.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.
@@ -4,7 +4,7 @@
4
4
  var crypto = require('crypto');
5
5
  var promises = require('fs/promises');
6
6
  var os = require('os');
7
- var path29 = require('path');
7
+ var path30 = require('path');
8
8
  var async_hooks = require('async_hooks');
9
9
  var process3 = require('process');
10
10
  var tty = require('tty');
@@ -20,7 +20,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
20
20
 
21
21
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
22
22
  var os__default = /*#__PURE__*/_interopDefault(os);
23
- var path29__default = /*#__PURE__*/_interopDefault(path29);
23
+ var path30__default = /*#__PURE__*/_interopDefault(path30);
24
24
  var process3__default = /*#__PURE__*/_interopDefault(process3);
25
25
  var tty__default = /*#__PURE__*/_interopDefault(tty);
26
26
 
@@ -864,7 +864,7 @@ function getDefaultTraceDir() {
864
864
  if (typeof home !== "string" || home.trim() === "") {
865
865
  return FALLBACK_TRACE_DIR;
866
866
  }
867
- return path29__default.default.join(home, DEFAULT_TRACE_DIR_NAME, RUNS_DIR_NAME);
867
+ return path30__default.default.join(home, DEFAULT_TRACE_DIR_NAME, RUNS_DIR_NAME);
868
868
  } catch {
869
869
  return FALLBACK_TRACE_DIR;
870
870
  }
@@ -872,11 +872,11 @@ function getDefaultTraceDir() {
872
872
  function getTraceFilePath(runId, traceDir) {
873
873
  const baseDir = traceDir ?? getDefaultTraceDir();
874
874
  let safeId = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "run_unknown";
875
- safeId = path29__default.default.basename(safeId);
875
+ safeId = path30__default.default.basename(safeId);
876
876
  if (safeId === "" || safeId === "." || safeId === "..") {
877
877
  safeId = "run_unknown";
878
878
  }
879
- return path29__default.default.join(baseDir, `${safeId}.jsonl`);
879
+ return path30__default.default.join(baseDir, `${safeId}.jsonl`);
880
880
  }
881
881
  function formatError(error) {
882
882
  if (error instanceof Error) {
@@ -933,7 +933,7 @@ var init_utils = __esm({
933
933
  init_duration();
934
934
  DEFAULT_TRACE_DIR_NAME = ".agent-inspect";
935
935
  RUNS_DIR_NAME = "runs";
936
- FALLBACK_TRACE_DIR = path29__default.default.join(
936
+ FALLBACK_TRACE_DIR = path30__default.default.join(
937
937
  os__default.default.tmpdir(),
938
938
  "agent-inspect",
939
939
  RUNS_DIR_NAME
@@ -1899,7 +1899,7 @@ var init_trace_directory = __esm({
1899
1899
  this.#dir = resolveTraceDir(options);
1900
1900
  }
1901
1901
  getPath(filename) {
1902
- return filename ? path29__default.default.join(this.#dir, filename) : this.#dir;
1902
+ return filename ? path30__default.default.join(this.#dir, filename) : this.#dir;
1903
1903
  }
1904
1904
  async list() {
1905
1905
  try {
@@ -1928,7 +1928,7 @@ function parseIsoToMs2(value) {
1928
1928
  }
1929
1929
  async function extractMetadata(filePath, _quickScan) {
1930
1930
  const stats = await promises.stat(filePath);
1931
- let runIdFromFile = path29__default.default.basename(filePath);
1931
+ let runIdFromFile = path30__default.default.basename(filePath);
1932
1932
  if (runIdFromFile.endsWith(".jsonl")) {
1933
1933
  runIdFromFile = runIdFromFile.slice(0, -".jsonl".length);
1934
1934
  }
@@ -2720,6 +2720,14 @@ var init_what = __esm({
2720
2720
  }
2721
2721
  });
2722
2722
 
2723
+ // packages/core/src/causal-failure.ts
2724
+ var init_causal_failure = __esm({
2725
+ "packages/core/src/causal-failure.ts"() {
2726
+ init_extract();
2727
+ init_timeline();
2728
+ }
2729
+ });
2730
+
2723
2731
  // packages/core/src/explain.ts
2724
2732
  function toDisplayStatus(status) {
2725
2733
  if (status === "ok") return "success";
@@ -3773,12 +3781,12 @@ function buildCriticalPath(runs, handoffs) {
3773
3781
  handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.from)
3774
3782
  );
3775
3783
  const ordered = [...runs].sort(compareRuns);
3776
- const path40 = [];
3784
+ const path41 = [];
3777
3785
  const visited = /* @__PURE__ */ new Set();
3778
3786
  const pushRun = (run, confidence, source) => {
3779
3787
  if (visited.has(run.runId)) return;
3780
3788
  visited.add(run.runId);
3781
- path40.push({
3789
+ path41.push({
3782
3790
  runId: run.runId,
3783
3791
  name: run.name,
3784
3792
  startedAt: run.startedAt,
@@ -3803,7 +3811,7 @@ function buildCriticalPath(runs, handoffs) {
3803
3811
  const confidence = explicitTargets.has(run.runId) || explicitSources.has(run.runId) ? "explicit" : "correlated";
3804
3812
  pushRun(run, confidence, confidence === "explicit" ? "manual" : "inferred");
3805
3813
  }
3806
- return path40;
3814
+ return path41;
3807
3815
  }
3808
3816
  function metaRunIdMatches(run, token, runById) {
3809
3817
  const meta2 = extractSessionWorkflowMetadata(run.metadata);
@@ -4132,7 +4140,7 @@ var init_summary = __esm({
4132
4140
  });
4133
4141
  function sanitizeBundleRunId(runId) {
4134
4142
  let safe = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "run_unknown";
4135
- safe = path29__default.default.basename(safe);
4143
+ safe = path30__default.default.basename(safe);
4136
4144
  safe = safe.replace(/[^a-zA-Z0-9._-]+/g, "_");
4137
4145
  if (safe === "" || safe === "." || safe === "..") {
4138
4146
  safe = "run_unknown";
@@ -4142,12 +4150,12 @@ function sanitizeBundleRunId(runId) {
4142
4150
  function bundleRunAssetRelativePath(runId, extension) {
4143
4151
  const safe = sanitizeBundleRunId(runId);
4144
4152
  const ext = extension.startsWith(".") ? extension : `.${extension}`;
4145
- return path29__default.default.posix.join("assets", "runs", `${safe}${ext}`);
4153
+ return path30__default.default.posix.join("assets", "runs", `${safe}${ext}`);
4146
4154
  }
4147
4155
  function assertBundlePathContained(outputDir, relativePath) {
4148
- const base = path29__default.default.resolve(outputDir);
4149
- const resolved = path29__default.default.resolve(base, relativePath);
4150
- if (resolved !== base && !resolved.startsWith(base + path29__default.default.sep)) {
4156
+ const base = path30__default.default.resolve(outputDir);
4157
+ const resolved = path30__default.default.resolve(base, relativePath);
4158
+ if (resolved !== base && !resolved.startsWith(base + path30__default.default.sep)) {
4151
4159
  throw new Error(`Bundle path escapes output directory: ${relativePath}`);
4152
4160
  }
4153
4161
  return resolved;
@@ -4157,7 +4165,7 @@ function normalizeBundleOutputPath(out, options) {
4157
4165
  if (trimmed === "") {
4158
4166
  throw new Error("--out requires a non-empty path.");
4159
4167
  }
4160
- const resolved = path29__default.default.resolve(trimmed);
4168
+ const resolved = path30__default.default.resolve(trimmed);
4161
4169
  if (options?.preserveZipExtension !== true && resolved.toLowerCase().endsWith(".zip")) {
4162
4170
  return resolved.slice(0, -4);
4163
4171
  }
@@ -4166,7 +4174,7 @@ function normalizeBundleOutputPath(out, options) {
4166
4174
  function defaultBundleOutputPath(runIds) {
4167
4175
  const label = runIds.length === 1 ? sanitizeBundleRunId(runIds[0]) : `multi-${runIds.length}`;
4168
4176
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4169
- return path29__default.default.resolve(`agent-inspect-bundle-${label}-${stamp}`);
4177
+ return path30__default.default.resolve(`agent-inspect-bundle-${label}-${stamp}`);
4170
4178
  }
4171
4179
  var init_paths = __esm({
4172
4180
  "packages/core/src/bundle/paths.ts"() {
@@ -4229,7 +4237,7 @@ function assertEvidenceRelativePath(relativePath) {
4229
4237
  throw new Error("Evidence file path must be a non-empty relative path.");
4230
4238
  }
4231
4239
  const trimmed = relativePath.trim().replaceAll("\\", "/");
4232
- if (path29__default.default.isAbsolute(trimmed) || trimmed.startsWith("/")) {
4240
+ if (path30__default.default.isAbsolute(trimmed) || trimmed.startsWith("/")) {
4233
4241
  throw new Error(`Evidence file path must be relative: ${relativePath}`);
4234
4242
  }
4235
4243
  const parts = trimmed.split("/").filter((part) => part !== "");
@@ -5095,13 +5103,13 @@ function pairSteps(left, right) {
5095
5103
  return pairs;
5096
5104
  }
5097
5105
  function compareLeafSteps(L, R, segments, opts, out) {
5098
- const path40 = buildPath(segments);
5106
+ const path41 = buildPath(segments);
5099
5107
  if (L.name !== R.name) {
5100
5108
  out.push({
5101
5109
  kind: "structure",
5102
5110
  severity: "warning",
5103
5111
  message: "Step name differs",
5104
- path: path40,
5112
+ path: path41,
5105
5113
  left: L.name,
5106
5114
  right: R.name
5107
5115
  });
@@ -5111,7 +5119,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5111
5119
  kind: "step-type",
5112
5120
  severity: "warning",
5113
5121
  message: "Step type differs",
5114
- path: path40,
5122
+ path: path41,
5115
5123
  left: L.type,
5116
5124
  right: R.type
5117
5125
  });
@@ -5121,7 +5129,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5121
5129
  kind: "step-status",
5122
5130
  severity: "warning",
5123
5131
  message: "Step status differs",
5124
- path: path40,
5132
+ path: path41,
5125
5133
  left: L.status,
5126
5134
  right: R.status
5127
5135
  });
@@ -5133,7 +5141,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5133
5141
  kind: "error",
5134
5142
  severity: "error",
5135
5143
  message: "Step error message differs",
5136
- path: path40,
5144
+ path: path41,
5137
5145
  left: le || void 0,
5138
5146
  right: re || void 0
5139
5147
  });
@@ -5151,7 +5159,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5151
5159
  kind: "duration",
5152
5160
  severity: "info",
5153
5161
  message: "Step duration differs",
5154
- path: path40,
5162
+ path: path41,
5155
5163
  left: ld,
5156
5164
  right: rd
5157
5165
  });
@@ -5164,7 +5172,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5164
5172
  kind: "metadata",
5165
5173
  severity: "info",
5166
5174
  message: "Step metadata differs",
5167
- path: path40,
5175
+ path: path41,
5168
5176
  left: L.metadata,
5169
5177
  right: R.metadata
5170
5178
  });
@@ -5176,7 +5184,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5176
5184
  kind: "output",
5177
5185
  severity: "info",
5178
5186
  message: "Output preview differs",
5179
- path: path40,
5187
+ path: path41,
5180
5188
  left: L.outputPreview,
5181
5189
  right: R.outputPreview
5182
5190
  });
@@ -5343,11 +5351,11 @@ var init_engine = __esm({
5343
5351
  });
5344
5352
 
5345
5353
  // packages/core/src/diff/renderer.ts
5346
- function formatPath(path40) {
5347
- if (path40 === void 0 || path40.path.length === 0) {
5354
+ function formatPath(path41) {
5355
+ if (path41 === void 0 || path41.path.length === 0) {
5348
5356
  return "(run)";
5349
5357
  }
5350
- return path40.path.map((s) => s.name).join(" > ");
5358
+ return path41.path.map((s) => s.name).join(" > ");
5351
5359
  }
5352
5360
  function formatValue(v, verbose) {
5353
5361
  if (v === void 0) return "(undefined)";
@@ -5727,11 +5735,11 @@ async function listFilesRecursive(root) {
5727
5735
  async function walk(dir) {
5728
5736
  const entries = await promises.readdir(dir, { withFileTypes: true });
5729
5737
  for (const entry of entries) {
5730
- const abs = path29__default.default.join(dir, entry.name);
5738
+ const abs = path30__default.default.join(dir, entry.name);
5731
5739
  if (entry.isDirectory()) {
5732
5740
  await walk(abs);
5733
5741
  } else if (entry.isFile()) {
5734
- const rel = path29__default.default.relative(root, abs).split(path29__default.default.sep).join("/");
5742
+ const rel = path30__default.default.relative(root, abs).split(path30__default.default.sep).join("/");
5735
5743
  out.push(rel);
5736
5744
  }
5737
5745
  }
@@ -5741,7 +5749,7 @@ async function listFilesRecursive(root) {
5741
5749
  }
5742
5750
  async function verifyEvidenceDirectory(rootPath, options = {}) {
5743
5751
  const unexpectedMode = options.unexpectedFiles ?? "fail";
5744
- const root = path29__default.default.resolve(rootPath);
5752
+ const root = path30__default.default.resolve(rootPath);
5745
5753
  const issues = [];
5746
5754
  let rootStat;
5747
5755
  try {
@@ -5771,7 +5779,7 @@ async function verifyEvidenceDirectory(rootPath, options = {}) {
5771
5779
  checkedFiles: 0
5772
5780
  };
5773
5781
  }
5774
- const manifestPath = path29__default.default.join(root, EVIDENCE_MANIFEST_FILENAME);
5782
+ const manifestPath = path30__default.default.join(root, EVIDENCE_MANIFEST_FILENAME);
5775
5783
  let manifestText;
5776
5784
  try {
5777
5785
  manifestText = await promises.readFile(manifestPath, "utf-8");
@@ -5857,7 +5865,7 @@ async function verifyEvidenceDirectory(rootPath, options = {}) {
5857
5865
  continue;
5858
5866
  }
5859
5867
  listed.add(rel);
5860
- const abs = path29__default.default.join(root, ...rel.split("/"));
5868
+ const abs = path30__default.default.join(root, ...rel.split("/"));
5861
5869
  let bytes;
5862
5870
  try {
5863
5871
  bytes = await promises.readFile(abs);
@@ -6171,7 +6179,7 @@ function normalizeSuiteConfig(value) {
6171
6179
  }
6172
6180
  async function validateSuiteConfig(config, options) {
6173
6181
  const diagnostics = [];
6174
- const tracesDir = path29__default.default.resolve(options.configDir, config.traces);
6182
+ const tracesDir = path30__default.default.resolve(options.configDir, config.traces);
6175
6183
  try {
6176
6184
  await promises.access(tracesDir);
6177
6185
  } catch {
@@ -6181,7 +6189,7 @@ async function validateSuiteConfig(config, options) {
6181
6189
  }
6182
6190
  for (const suiteCase of config.cases) {
6183
6191
  if (suiteCase.input !== void 0) {
6184
- const inputPath = path29__default.default.resolve(options.configDir, suiteCase.input);
6192
+ const inputPath = path30__default.default.resolve(options.configDir, suiteCase.input);
6185
6193
  try {
6186
6194
  await promises.access(inputPath);
6187
6195
  } catch {
@@ -6214,12 +6222,12 @@ async function fileExists(filePath) {
6214
6222
  }
6215
6223
  }
6216
6224
  async function resolveSuiteConfigPath(options = {}) {
6217
- const cwd = path29__default.default.resolve(options.cwd ?? process.cwd());
6225
+ const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
6218
6226
  if (options.configPath !== void 0 && options.configPath.trim() !== "") {
6219
- return path29__default.default.resolve(cwd, options.configPath.trim());
6227
+ return path30__default.default.resolve(cwd, options.configPath.trim());
6220
6228
  }
6221
6229
  for (const name of DEFAULT_SUITE_CONFIG_NAMES) {
6222
- const candidate = path29__default.default.join(cwd, name);
6230
+ const candidate = path30__default.default.join(cwd, name);
6223
6231
  if (await fileExists(candidate)) return candidate;
6224
6232
  }
6225
6233
  throw new Error(
@@ -6236,7 +6244,7 @@ async function loadSuiteConfig(options = {}) {
6236
6244
  diagnostics: [diagnostic2("AI_SUITE_CONFIG_LOAD_FAILED", message)]
6237
6245
  });
6238
6246
  }
6239
- const extension = path29__default.default.extname(configPath);
6247
+ const extension = path30__default.default.extname(configPath);
6240
6248
  if (TS_CONFIG_EXTENSIONS.has(extension)) {
6241
6249
  const message = "TypeScript suite configs require an explicit precompiled JavaScript config or future --config-loader support.";
6242
6250
  throw Object.assign(new Error(message), {
@@ -6261,7 +6269,7 @@ async function loadSuiteConfig(options = {}) {
6261
6269
  return {
6262
6270
  config,
6263
6271
  configPath,
6264
- configDir: path29__default.default.dirname(configPath)
6272
+ configDir: path30__default.default.dirname(configPath)
6265
6273
  };
6266
6274
  } catch (error) {
6267
6275
  const message = error instanceof Error ? error.message : String(error);
@@ -6311,7 +6319,7 @@ async function exists(filePath) {
6311
6319
  }
6312
6320
  async function resolveSuiteCaseTrace(suiteCase, options) {
6313
6321
  if (suiteCase.trace !== void 0) {
6314
- const tracePath = path29__default.default.resolve(options.configDir, suiteCase.trace);
6322
+ const tracePath = path30__default.default.resolve(options.configDir, suiteCase.trace);
6315
6323
  if (await exists(tracePath)) {
6316
6324
  return { caseId: suiteCase.id, tracePath, missing: false };
6317
6325
  }
@@ -6327,7 +6335,7 @@ async function resolveSuiteCaseTrace(suiteCase, options) {
6327
6335
  if (await exists(directPath)) {
6328
6336
  return { caseId: suiteCase.id, tracePath: directPath, runId: runKey, missing: false };
6329
6337
  }
6330
- const nestedPath = path29__default.default.join(options.tracesDir, `${path29__default.default.basename(runKey)}.jsonl`);
6338
+ const nestedPath = path30__default.default.join(options.tracesDir, `${path30__default.default.basename(runKey)}.jsonl`);
6331
6339
  if (await exists(nestedPath)) {
6332
6340
  return { caseId: suiteCase.id, tracePath: nestedPath, runId: runKey, missing: false };
6333
6341
  }
@@ -6569,7 +6577,7 @@ function stripPrefix(name, prefixes) {
6569
6577
  }
6570
6578
  return name;
6571
6579
  }
6572
- function eventEvidence(event, path40) {
6580
+ function eventEvidence(event, path41) {
6573
6581
  return {
6574
6582
  runId: event.runId,
6575
6583
  eventId: event.eventId,
@@ -6579,7 +6587,7 @@ function eventEvidence(event, path40) {
6579
6587
  kind: event.kind,
6580
6588
  name: event.name,
6581
6589
  status: event.status,
6582
- ...path40 ? { path: path40 } : {}
6590
+ ...path41 ? { path: path41 } : {}
6583
6591
  };
6584
6592
  }
6585
6593
  function runEvidence(run) {
@@ -6646,9 +6654,9 @@ function eventEndMs(event) {
6646
6654
  function normalizedKey(value) {
6647
6655
  return value.toLowerCase().replace(/[^a-z0-9_]/g, "");
6648
6656
  }
6649
- function lastPathSegment(path40) {
6650
- const parts = path40.split(".");
6651
- return parts[parts.length - 1] ?? path40;
6657
+ function lastPathSegment(path41) {
6658
+ const parts = path41.split(".");
6659
+ return parts[parts.length - 1] ?? path41;
6652
6660
  }
6653
6661
  function valueType(value) {
6654
6662
  if (Array.isArray(value)) return "array";
@@ -6662,12 +6670,12 @@ function serializedByteLength(value) {
6662
6670
  return void 0;
6663
6671
  }
6664
6672
  }
6665
- function pushValueEntries(entries, event, value, path40, key, depth = 0) {
6666
- entries.push({ event, path: path40, key, value });
6673
+ function pushValueEntries(entries, event, value, path41, key, depth = 0) {
6674
+ entries.push({ event, path: path41, key, value });
6667
6675
  if (depth >= 8) return;
6668
6676
  if (Array.isArray(value)) {
6669
6677
  for (const [index, item] of value.entries()) {
6670
- pushValueEntries(entries, event, item, `${path40}.${index}`, String(index), depth + 1);
6678
+ pushValueEntries(entries, event, item, `${path41}.${index}`, String(index), depth + 1);
6671
6679
  }
6672
6680
  return;
6673
6681
  }
@@ -6677,7 +6685,7 @@ function pushValueEntries(entries, event, value, path40, key, depth = 0) {
6677
6685
  entries,
6678
6686
  event,
6679
6687
  value[nestedKey],
6680
- `${path40}.${nestedKey}`,
6688
+ `${path41}.${nestedKey}`,
6681
6689
  nestedKey,
6682
6690
  depth + 1
6683
6691
  );
@@ -6718,18 +6726,18 @@ function isRawContentKey(key, forbiddenKeys) {
6718
6726
  const normalized = normalizedKey(key);
6719
6727
  return forbiddenKeys.some((forbidden) => normalized === normalizedKey(forbidden));
6720
6728
  }
6721
- function isSafeRawContentMetricPath(path40, key, safePathPrefixes) {
6722
- const leaf = normalizedKey(key ?? lastPathSegment(path40));
6729
+ function isSafeRawContentMetricPath(path41, key, safePathPrefixes) {
6730
+ const leaf = normalizedKey(key ?? lastPathSegment(path41));
6723
6731
  if (!SAFE_USAGE_LEAF_KEYS.has(leaf)) return false;
6724
- const parts = path40.split(".").filter(Boolean);
6732
+ const parts = path41.split(".").filter(Boolean);
6725
6733
  if (parts.length < 2) return false;
6726
6734
  const parent = parts[parts.length - 2] ?? "";
6727
6735
  const parentNorm = normalizedKey(parent);
6728
6736
  return safePathPrefixes.some((prefix) => parentNorm === normalizedKey(prefix));
6729
6737
  }
6730
- function isRawContentPath(path40, key, forbiddenKeys, safePathPrefixes) {
6731
- if (isSafeRawContentMetricPath(path40, key, safePathPrefixes)) return false;
6732
- return isRawContentKey(key ?? lastPathSegment(path40), forbiddenKeys);
6738
+ function isRawContentPath(path41, key, forbiddenKeys, safePathPrefixes) {
6739
+ if (isSafeRawContentMetricPath(path41, key, safePathPrefixes)) return false;
6740
+ return isRawContentKey(key ?? lastPathSegment(path41), forbiddenKeys);
6733
6741
  }
6734
6742
  function parentMarkedUnresolved(event) {
6735
6743
  if (booleanAttr(event, [
@@ -6771,9 +6779,9 @@ function eventDurationMs(event) {
6771
6779
  }
6772
6780
  function treeShape(nodes) {
6773
6781
  const lines = [];
6774
- const visit = (node, path40) => {
6775
- lines.push(`${path40}:${node.event.kind}:${node.event.name}:${node.event.status ?? "unknown"}`);
6776
- node.children.forEach((child, index) => visit(child, `${path40}.${index}`));
6782
+ const visit = (node, path41) => {
6783
+ lines.push(`${path41}:${node.event.kind}:${node.event.name}:${node.event.status ?? "unknown"}`);
6784
+ node.children.forEach((child, index) => visit(child, `${path41}.${index}`));
6777
6785
  };
6778
6786
  nodes.forEach((node, index) => visit(node, String(index)));
6779
6787
  return lines;
@@ -6822,9 +6830,9 @@ function retrievalShape(context) {
6822
6830
  function guardrailShape(context) {
6823
6831
  return guardrailEvents(context).map((event) => signalName(event, ["guardrailName", "guardrail", "guardrailId"], ["guardrail:"])).sort((a, b) => a.localeCompare(b));
6824
6832
  }
6825
- function firstEvidenceForKind(context, kind, path40) {
6833
+ function firstEvidenceForKind(context, kind, path41) {
6826
6834
  const event = context.events.find((candidate) => candidate.kind === kind);
6827
- return event ? [eventEvidence(event, path40)] : runEvidence(context.selectedRun);
6835
+ return event ? [eventEvidence(event, path41)] : runEvidence(context.selectedRun);
6828
6836
  }
6829
6837
  function baselineDiffFinding(message, evidence, expected, actual) {
6830
6838
  return failFinding("baseline.regression", message, evidence, expected, actual);
@@ -7174,13 +7182,13 @@ function createStructureCycleRule() {
7174
7182
  const seenCycles = /* @__PURE__ */ new Set();
7175
7183
  const findings = [];
7176
7184
  for (const event of [...context.events].sort((a, b) => a.eventId.localeCompare(b.eventId))) {
7177
- const path40 = [];
7185
+ const path41 = [];
7178
7186
  const seenAt = /* @__PURE__ */ new Map();
7179
7187
  let current = event;
7180
7188
  while (current) {
7181
7189
  const existing = seenAt.get(current.eventId);
7182
7190
  if (existing !== void 0) {
7183
- const cycle = path40.slice(existing);
7191
+ const cycle = path41.slice(existing);
7184
7192
  const key = cycle.map((item) => item.eventId).sort().join("\0");
7185
7193
  if (!seenCycles.has(key)) {
7186
7194
  seenCycles.add(key);
@@ -7196,8 +7204,8 @@ function createStructureCycleRule() {
7196
7204
  }
7197
7205
  break;
7198
7206
  }
7199
- seenAt.set(current.eventId, path40.length);
7200
- path40.push(current);
7207
+ seenAt.set(current.eventId, path41.length);
7208
+ path41.push(current);
7201
7209
  current = current.parentId ? byId.get(current.parentId) : void 0;
7202
7210
  }
7203
7211
  }
@@ -8420,7 +8428,7 @@ function findReaderByFormat(format, readers) {
8420
8428
  }
8421
8429
  async function jsonlFilesInDirectory(dirPath) {
8422
8430
  const entries = await promises.readdir(dirPath, { withFileTypes: true });
8423
- return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => path29__default.default.join(dirPath, entry.name)).sort((a, b) => a.localeCompare(b));
8431
+ return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => path30__default.default.join(dirPath, entry.name)).sort((a, b) => a.localeCompare(b));
8424
8432
  }
8425
8433
  async function resolveInput(input3) {
8426
8434
  const cached2 = resolvedInputCache.get(input3);
@@ -10119,7 +10127,7 @@ async function runSuiteCase(suiteCase, config, options) {
10119
10127
  async function runSuite(options = {}) {
10120
10128
  const startedAt = new Date(options.nowMs ?? Date.now()).toISOString();
10121
10129
  const { config, configPath, configDir } = await loadSuiteConfig(options);
10122
- const tracesDir = path29__default.default.resolve(configDir, config.traces);
10130
+ const tracesDir = path30__default.default.resolve(configDir, config.traces);
10123
10131
  const cases = [];
10124
10132
  const diagnostics = [];
10125
10133
  for (const suiteCase of config.cases) {
@@ -11146,7 +11154,7 @@ function validateOptions(options) {
11146
11154
  }
11147
11155
  function isConfigLoadError(error) {
11148
11156
  if (!(error instanceof Error)) return false;
11149
- const ext = path29__default.default.extname(error.message);
11157
+ const ext = path30__default.default.extname(error.message);
11150
11158
  if (error.message.includes("Unsupported suite config extension")) return true;
11151
11159
  if (error.message.includes("TypeScript suite configs require")) return true;
11152
11160
  if (error.message.includes("No suite config found")) return true;
@@ -11403,6 +11411,7 @@ var init_advanced = __esm({
11403
11411
  init_trace_filter();
11404
11412
  init_timeline();
11405
11413
  init_what();
11414
+ init_causal_failure();
11406
11415
  init_explain();
11407
11416
  init_stats();
11408
11417
  init_search();
@@ -11539,8 +11548,8 @@ var init_load_sqlite = __esm({
11539
11548
  }
11540
11549
  });
11541
11550
  function resolveIndexDbPath(traceDir, dbPath) {
11542
- if (dbPath && dbPath.trim() !== "") return path29__default.default.resolve(dbPath);
11543
- return path29__default.default.join(path29__default.default.resolve(traceDir), INDEX_DB_FILENAME);
11551
+ if (dbPath && dbPath.trim() !== "") return path30__default.default.resolve(dbPath);
11552
+ return path30__default.default.join(path30__default.default.resolve(traceDir), INDEX_DB_FILENAME);
11544
11553
  }
11545
11554
  function str(value) {
11546
11555
  return typeof value === "string" && value !== "" ? value : null;
@@ -11632,7 +11641,7 @@ async function buildIndex(options = {}) {
11632
11641
  warnings.push(`index.unreadable: ${file}`);
11633
11642
  }
11634
11643
  }
11635
- await promises.mkdir(path29__default.default.dirname(dbPath), { recursive: true });
11644
+ await promises.mkdir(path30__default.default.dirname(dbPath), { recursive: true });
11636
11645
  await promises.rm(dbPath, { force: true });
11637
11646
  const Sqlite = loadBetterSqlite3();
11638
11647
  const db = new Sqlite(dbPath);
@@ -11880,7 +11889,7 @@ var init_src = __esm({
11880
11889
  });
11881
11890
 
11882
11891
  // package.json
11883
- var version = "6.10.0";
11892
+ var version = "6.12.0";
11884
11893
 
11885
11894
  // packages/cli/src/list.ts
11886
11895
  init_advanced();
@@ -14902,9 +14911,9 @@ Trace directory: ${traceDir}`);
14902
14911
  process.exitCode = 1;
14903
14912
  }
14904
14913
  const resolvedOutput = resolveOutputOption(options);
14905
- const outPath = resolvedOutput !== void 0 ? path29__default.default.resolve(resolvedOutput) : void 0;
14914
+ const outPath = resolvedOutput !== void 0 ? path30__default.default.resolve(resolvedOutput) : void 0;
14906
14915
  if (outPath !== void 0) {
14907
- await promises.mkdir(path29__default.default.dirname(outPath), { recursive: true });
14916
+ await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
14908
14917
  await promises.writeFile(outPath, result.content, "utf-8");
14909
14918
  const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
14910
14919
  console.log(`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`);
@@ -15263,7 +15272,7 @@ function indexedToMetadata(row, traceDir) {
15263
15272
  endedAt: row.endedAt ?? void 0,
15264
15273
  durationMs: row.durationMs ?? void 0,
15265
15274
  eventCount: 0,
15266
- filePath: path29__default.default.join(traceDir, row.file),
15275
+ filePath: path30__default.default.join(traceDir, row.file),
15267
15276
  fileSize: 0,
15268
15277
  createdAt: new Date(row.mtimeMs)
15269
15278
  };
@@ -15745,9 +15754,9 @@ async function reportCommand(runId, options = {}) {
15745
15754
  ...options.section ? { section: options.section } : {}
15746
15755
  });
15747
15756
  const resolvedOutput = resolveOutputOption(options);
15748
- const outPath = resolvedOutput !== void 0 ? path29__default.default.resolve(resolvedOutput) : void 0;
15757
+ const outPath = resolvedOutput !== void 0 ? path30__default.default.resolve(resolvedOutput) : void 0;
15749
15758
  if (outPath !== void 0) {
15750
- await promises.mkdir(path29__default.default.dirname(outPath), { recursive: true });
15759
+ await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
15751
15760
  await promises.writeFile(outPath, result.content, "utf-8");
15752
15761
  console.log(`Wrote ${result.fileExtension} report to ${outPath}`);
15753
15762
  }
@@ -15876,8 +15885,8 @@ function passesLuhn(value) {
15876
15885
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
15877
15886
  var EPOCH_MS_RE = /^1[0-9]{12}$/;
15878
15887
  var EMAIL_RE = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
15879
- function pathSuggestsNonCard(path40) {
15880
- const normalized = path40.toLowerCase().replace(/[^a-z0-9._]/g, "");
15888
+ function pathSuggestsNonCard(path41) {
15889
+ const normalized = path41.toLowerCase().replace(/[^a-z0-9._]/g, "");
15881
15890
  return /(^|\.)(tokenusage|usage)(\.|$)/.test(normalized) || /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\.|$)/.test(normalized) || /(^|\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\.|$)/.test(
15882
15891
  normalized
15883
15892
  ) || /(^|\.)ts(\.|$)/.test(normalized);
@@ -16064,17 +16073,17 @@ function applyRule(rule, value, replacement) {
16064
16073
  }
16065
16074
  return value;
16066
16075
  }
16067
- function childPath(path40, key) {
16076
+ function childPath(path41, key) {
16068
16077
  if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
16069
- return path40 ? `${path40}.${key}` : key;
16078
+ return path41 ? `${path41}.${key}` : key;
16070
16079
  }
16071
- return `${path40 || "$"}[${JSON.stringify(key)}]`;
16080
+ return `${path41 || "$"}[${JSON.stringify(key)}]`;
16072
16081
  }
16073
- function indexPath(path40, index) {
16074
- return `${path40 || "$"}[${index}]`;
16082
+ function indexPath(path41, index) {
16083
+ return `${path41 || "$"}[${index}]`;
16075
16084
  }
16076
- function makeFinding(path40, detector, action, matchKind, severity = "warning", preview) {
16077
- return preview === void 0 ? { path: path40, detector, action, severity, matchKind } : { path: path40, detector, action, severity, matchKind, preview };
16085
+ function makeFinding(path41, detector, action, matchKind, severity = "warning", preview) {
16086
+ return preview === void 0 ? { path: path41, detector, action, severity, matchKind } : { path: path41, detector, action, severity, matchKind, preview };
16078
16087
  }
16079
16088
  function createRedactionProfile(profile = "local") {
16080
16089
  switch (profile) {
@@ -16143,11 +16152,11 @@ var Redactor2 = class {
16143
16152
  #recordFinding(state, finding) {
16144
16153
  if (this.#collectFindings) state.findings.push(finding);
16145
16154
  }
16146
- #redactValue(value, key, path40, depth, state) {
16155
+ #redactValue(value, key, path41, depth, state) {
16147
16156
  if (depth > this.#maxDepth) {
16148
16157
  this.#recordFinding(
16149
16158
  state,
16150
- makeFinding(path40, "structure.maxDepth", "truncate", "value", "warning")
16159
+ makeFinding(path41, "structure.maxDepth", "truncate", "value", "warning")
16151
16160
  );
16152
16161
  return "[Truncated]";
16153
16162
  }
@@ -16156,19 +16165,19 @@ var Redactor2 = class {
16156
16165
  if (rule) {
16157
16166
  this.#recordFinding(
16158
16167
  state,
16159
- makeFinding(path40, `key.${rule.key}`, actionForRule(rule), "key", "warning")
16168
+ makeFinding(path41, `key.${rule.key}`, actionForRule(rule), "key", "warning")
16160
16169
  );
16161
16170
  return applyRule(rule, value, this.#replacement);
16162
16171
  }
16163
16172
  }
16164
16173
  for (const detector of this.#detectors) {
16165
- const detections = detector.detect({ path: path40, key, value });
16174
+ const detections = detector.detect({ path: path41, key, value });
16166
16175
  for (const detection of detections) {
16167
16176
  const action = detection.action ?? "replace";
16168
16177
  this.#recordFinding(
16169
16178
  state,
16170
16179
  makeFinding(
16171
- path40,
16180
+ path41,
16172
16181
  detector.id,
16173
16182
  action,
16174
16183
  detection.matchKind ?? detector.matchKind ?? "custom",
@@ -16186,7 +16195,7 @@ var Redactor2 = class {
16186
16195
  const out = [];
16187
16196
  state.seen.set(value, out);
16188
16197
  value.forEach((item, index) => {
16189
- out[index] = this.#redactValue(item, void 0, indexPath(path40, index), depth + 1, state);
16198
+ out[index] = this.#redactValue(item, void 0, indexPath(path41, index), depth + 1, state);
16190
16199
  });
16191
16200
  return out;
16192
16201
  }
@@ -16198,7 +16207,7 @@ var Redactor2 = class {
16198
16207
  out[entryKey] = this.#redactValue(
16199
16208
  entryValue,
16200
16209
  entryKey,
16201
- childPath(path40 === "$" ? "" : path40, entryKey),
16210
+ childPath(path41 === "$" ? "" : path41, entryKey),
16202
16211
  depth + 1,
16203
16212
  state
16204
16213
  );
@@ -16669,14 +16678,14 @@ function uniqueSorted(values) {
16669
16678
  return [...new Set(values)].sort();
16670
16679
  }
16671
16680
  function isWithinDirectory(child, parent) {
16672
- const relative = path29__default.default.relative(parent, child);
16673
- return relative === "" || !relative.startsWith("..") && !path29__default.default.isAbsolute(relative);
16681
+ const relative = path30__default.default.relative(parent, child);
16682
+ return relative === "" || !relative.startsWith("..") && !path30__default.default.isAbsolute(relative);
16674
16683
  }
16675
16684
  async function resolveOutputPath(inputPath, output2, force) {
16676
16685
  if (output2 === void 0 || output2.trim() === "") return void 0;
16677
- const inputAbs = path29__default.default.resolve(inputPath);
16678
- const outputAbs = path29__default.default.resolve(output2.trim());
16679
- const inputDir = path29__default.default.dirname(inputAbs);
16686
+ const inputAbs = path30__default.default.resolve(inputPath);
16687
+ const outputAbs = path30__default.default.resolve(output2.trim());
16688
+ const inputDir = path30__default.default.dirname(inputAbs);
16680
16689
  if (!isWithinDirectory(outputAbs, inputDir)) {
16681
16690
  throw new Error("Refusing to write migrated output outside the input directory.");
16682
16691
  }
@@ -16797,7 +16806,7 @@ async function migrateCommand(input3, options = {}) {
16797
16806
  process.exitCode = 1;
16798
16807
  return;
16799
16808
  }
16800
- const inputPath = path29__default.default.resolve(input3.trim());
16809
+ const inputPath = path30__default.default.resolve(input3.trim());
16801
16810
  const dryRun = options.dryRun === true;
16802
16811
  if (!dryRun && (options.output === void 0 || options.output.trim() === "")) {
16803
16812
  console.error("migrate requires --dry-run or --output <path>.");
@@ -16816,7 +16825,7 @@ async function migrateCommand(input3, options = {}) {
16816
16825
  );
16817
16826
  const result = await buildMigration(inputPath, outputPath);
16818
16827
  if (!dryRun && outputPath !== void 0) {
16819
- await promises.mkdir(path29__default.default.dirname(outputPath), { recursive: true });
16828
+ await promises.mkdir(path30__default.default.dirname(outputPath), { recursive: true });
16820
16829
  await promises.writeFile(outputPath, result.content, "utf-8");
16821
16830
  }
16822
16831
  printSummary2(result, dryRun);
@@ -17150,23 +17159,23 @@ function evaluatePromptInjection(text, options = {}) {
17150
17159
  }
17151
17160
  return fail(ruleId, `Matched ${evidence.length} injection pattern(s).`, evidence, "warning");
17152
17161
  }
17153
- function validateSchemaField(value, field, path40, evidence) {
17162
+ function validateSchemaField(value, field, path41, evidence) {
17154
17163
  const ruleId = "guardrail.structured-output";
17155
17164
  if (field.type) {
17156
17165
  const actual = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
17157
17166
  if (actual !== field.type) {
17158
- evidence.push({ ruleId, path: path40, preview: `expected ${field.type}, got ${actual}` });
17167
+ evidence.push({ ruleId, path: path41, preview: `expected ${field.type}, got ${actual}` });
17159
17168
  return;
17160
17169
  }
17161
17170
  }
17162
17171
  if (field.enum && !field.enum.some((item) => Object.is(item, value))) {
17163
- evidence.push({ ruleId, path: path40, preview: "value not in enum" });
17172
+ evidence.push({ ruleId, path: path41, preview: "value not in enum" });
17164
17173
  }
17165
17174
  if (field.type === "object" && field.required && value && typeof value === "object" && !Array.isArray(value)) {
17166
17175
  const record = value;
17167
17176
  for (const key of field.required) {
17168
17177
  if (!(key in record)) {
17169
- evidence.push({ ruleId, path: `${path40}.${key}`, preview: "missing required key" });
17178
+ evidence.push({ ruleId, path: `${path41}.${key}`, preview: "missing required key" });
17170
17179
  }
17171
17180
  }
17172
17181
  }
@@ -17493,7 +17502,7 @@ function asConfig(value) {
17493
17502
  }
17494
17503
  async function loadConfig(configPath) {
17495
17504
  if (configPath === void 0) return {};
17496
- const extension = path29__default.default.extname(configPath);
17505
+ const extension = path30__default.default.extname(configPath);
17497
17506
  if (TS_CONFIG_EXTENSIONS2.has(extension)) {
17498
17507
  throw new Error(
17499
17508
  "TypeScript check configs require an explicit precompiled JavaScript config or future --config-loader support."
@@ -17502,7 +17511,7 @@ async function loadConfig(configPath) {
17502
17511
  if (!CONFIG_EXTENSIONS2.has(extension)) {
17503
17512
  throw new Error("Unsupported check config extension. Use .json, .js, .mjs, or .cjs.");
17504
17513
  }
17505
- const absolute = path29__default.default.resolve(configPath);
17514
+ const absolute = path30__default.default.resolve(configPath);
17506
17515
  if (extension === ".json") {
17507
17516
  const raw = await promises.readFile(absolute, "utf-8");
17508
17517
  return asConfig(JSON.parse(raw));
@@ -17678,10 +17687,10 @@ function printHuman(result) {
17678
17687
  console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
17679
17688
  }
17680
17689
  for (const finding of result.findings) {
17681
- const path40 = finding.evidence[0]?.path;
17690
+ const path41 = finding.evidence[0]?.path;
17682
17691
  const run = finding.evidence[0]?.runId;
17683
17692
  const runPrefix = run ? `[${run}] ` : "";
17684
- console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${path40 ? ` (${path40})` : ""}`);
17693
+ console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}`);
17685
17694
  }
17686
17695
  }
17687
17696
  function readErrorResult(error) {
@@ -17949,7 +17958,7 @@ async function loadSuiteViewerData(options) {
17949
17958
  for (const suiteCase of result.cases) {
17950
17959
  cases.push(await enrichCase(suiteCase, baselinePath));
17951
17960
  }
17952
- const artifactsDir = path29__default.default.join(path29__default.default.dirname(result.configPath), ".agent-inspect/suite-runs");
17961
+ const artifactsDir = path30__default.default.join(path30__default.default.dirname(result.configPath), ".agent-inspect/suite-runs");
17953
17962
  return {
17954
17963
  suiteName: result.suiteName,
17955
17964
  configPath: result.configPath,
@@ -18145,19 +18154,19 @@ function serializeWorkspaceManifest(manifest) {
18145
18154
  }
18146
18155
  var INDEX_DIR_NAME = "index";
18147
18156
  function resolveWorkspaceLocation(cwd = process.cwd()) {
18148
- const projectRoot = path29__default.default.resolve(cwd);
18149
- const workspaceDir = path29__default.default.join(projectRoot, WORKSPACE_DIR_NAME);
18157
+ const projectRoot = path30__default.default.resolve(cwd);
18158
+ const workspaceDir = path30__default.default.join(projectRoot, WORKSPACE_DIR_NAME);
18150
18159
  return {
18151
18160
  projectRoot,
18152
18161
  workspaceDir,
18153
- manifestPath: path29__default.default.join(workspaceDir, WORKSPACE_MANIFEST_FILENAME)
18162
+ manifestPath: path30__default.default.join(workspaceDir, WORKSPACE_MANIFEST_FILENAME)
18154
18163
  };
18155
18164
  }
18156
18165
  function resolveInsideWorkspace(workspaceDir, relative) {
18157
- const base = path29__default.default.resolve(workspaceDir);
18158
- const resolved = path29__default.default.resolve(base, relative);
18159
- const rel = path29__default.default.relative(base, resolved);
18160
- if (rel === "" || rel === "." || !rel.startsWith("..") && !path29__default.default.isAbsolute(rel)) {
18166
+ const base = path30__default.default.resolve(workspaceDir);
18167
+ const resolved = path30__default.default.resolve(base, relative);
18168
+ const rel = path30__default.default.relative(base, resolved);
18169
+ if (rel === "" || rel === "." || !rel.startsWith("..") && !path30__default.default.isAbsolute(rel)) {
18161
18170
  return resolved;
18162
18171
  }
18163
18172
  throw new Error(
@@ -18226,7 +18235,7 @@ async function createWorkspace(options = {}) {
18226
18235
  created = false;
18227
18236
  adopted = true;
18228
18237
  } else {
18229
- const project = options.project?.trim() || path29__default.default.basename(location.projectRoot) || "workspace";
18238
+ const project = options.project?.trim() || path30__default.default.basename(location.projectRoot) || "workspace";
18230
18239
  const traceDirs = detectedExistingTraces ? ["runs", "."] : ["runs"];
18231
18240
  manifest = createDefaultWorkspaceManifest({
18232
18241
  project,
@@ -18365,7 +18374,7 @@ async function doctorWorkspace(location) {
18365
18374
  const abs = resolveInsideWorkspace(location.workspaceDir, rel);
18366
18375
  for (const file of await listJsonl(abs)) {
18367
18376
  try {
18368
- const s = await promises.stat(path29__default.default.join(abs, file));
18377
+ const s = await promises.stat(path30__default.default.join(abs, file));
18369
18378
  newestTraceMtime = Math.max(newestTraceMtime, s.mtimeMs);
18370
18379
  } catch {
18371
18380
  checks2.push({ id: "trace-readability", status: "warn", message: `cannot stat ${rel}/${file}` });
@@ -18413,7 +18422,7 @@ async function cleanWorkspace(location, manifest, options = {}) {
18413
18422
  const relPath = `${rel}/${entry}`;
18414
18423
  removed.push(relPath);
18415
18424
  if (!dryRun) {
18416
- await promises.rm(path29__default.default.join(abs, entry), { recursive: true, force: true });
18425
+ await promises.rm(path30__default.default.join(abs, entry), { recursive: true, force: true });
18417
18426
  }
18418
18427
  }
18419
18428
  }
@@ -18422,7 +18431,7 @@ async function cleanWorkspace(location, manifest, options = {}) {
18422
18431
 
18423
18432
  // packages/viewer/src/workspace-data.ts
18424
18433
  async function loadWorkspaceViewerData(options) {
18425
- const cwd = path29__default.default.resolve(options.cwd ?? process.cwd());
18434
+ const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
18426
18435
  const location = resolveWorkspaceLocation(cwd);
18427
18436
  const manifestRead = await readWorkspaceManifestFile(location);
18428
18437
  if (!manifestRead.ok || manifestRead.manifest === void 0) {
@@ -18435,7 +18444,7 @@ async function loadWorkspaceViewerData(options) {
18435
18444
  const runs = [];
18436
18445
  for (const rel of manifestRead.manifest.traceDirs) {
18437
18446
  const traceDir = resolveTraceDir({
18438
- dir: path29__default.default.join(location.workspaceDir, rel)
18447
+ dir: path30__default.default.join(location.workspaceDir, rel)
18439
18448
  });
18440
18449
  const td = new TraceDirectory({ dir: traceDir });
18441
18450
  const files = await td.list();
@@ -18449,7 +18458,7 @@ async function loadWorkspaceViewerData(options) {
18449
18458
  runId: meta2.runId,
18450
18459
  ...meta2.name !== void 0 ? { name: meta2.name } : {},
18451
18460
  status: meta2.status,
18452
- file: path29__default.default.basename(meta2.filePath)
18461
+ file: path30__default.default.basename(meta2.filePath)
18453
18462
  });
18454
18463
  }
18455
18464
  }
@@ -18460,8 +18469,8 @@ async function loadWorkspaceViewerData(options) {
18460
18469
  doctor,
18461
18470
  runs,
18462
18471
  bundleDirs: [
18463
- path29__default.default.join(location.workspaceDir, manifestRead.manifest.bundlesDir),
18464
- path29__default.default.join(location.workspaceDir, manifestRead.manifest.artifactsDir)
18472
+ path30__default.default.join(location.workspaceDir, manifestRead.manifest.bundlesDir),
18473
+ path30__default.default.join(location.workspaceDir, manifestRead.manifest.artifactsDir)
18465
18474
  ]
18466
18475
  };
18467
18476
  }
@@ -18524,7 +18533,7 @@ function createViewerServer(options = {}) {
18524
18533
  ok: true,
18525
18534
  readOnly: true,
18526
18535
  mode,
18527
- traceDir: path29__default.default.resolve(traceDir)
18536
+ traceDir: path30__default.default.resolve(traceDir)
18528
18537
  });
18529
18538
  }
18530
18539
  if (pathname === "/api/suite" && mode === "suite") {
@@ -18553,7 +18562,7 @@ function createViewerServer(options = {}) {
18553
18562
  runId: meta2.runId,
18554
18563
  name: meta2.name,
18555
18564
  status: meta2.status,
18556
- file: path29__default.default.basename(meta2.filePath),
18565
+ file: path30__default.default.basename(meta2.filePath),
18557
18566
  startedAt: meta2.startedAt,
18558
18567
  durationMs: meta2.durationMs
18559
18568
  }))
@@ -18670,7 +18679,7 @@ function startViewerServer(options = {}) {
18670
18679
  resolve({
18671
18680
  host,
18672
18681
  port: resolvedPort,
18673
- traceDir: path29__default.default.resolve(traceDir),
18682
+ traceDir: path30__default.default.resolve(traceDir),
18674
18683
  url: `http://${host}:${resolvedPort}/${modeQuery}`,
18675
18684
  mode
18676
18685
  });
@@ -19041,10 +19050,10 @@ async function evalRun(input3, options = {}) {
19041
19050
  diagnostics: []
19042
19051
  };
19043
19052
  }
19044
- function evidenceForRun(run, path40) {
19045
- return [{ runId: run.runId, ...path40 !== void 0 ? { path: path40 } : {} }];
19053
+ function evidenceForRun(run, path41) {
19054
+ return [{ runId: run.runId, ...path41 !== void 0 ? { path: path41 } : {} }];
19046
19055
  }
19047
- function evidenceForEvent(event, path40) {
19056
+ function evidenceForEvent(event, path41) {
19048
19057
  return [
19049
19058
  {
19050
19059
  runId: event.runId,
@@ -19052,7 +19061,7 @@ function evidenceForEvent(event, path40) {
19052
19061
  ...event.parentId !== void 0 ? { parentId: event.parentId } : {},
19053
19062
  kind: event.kind,
19054
19063
  name: event.name,
19055
- ...path40 !== void 0 ? { path: path40 } : {}
19064
+ ...path41 !== void 0 ? { path: path41 } : {}
19056
19065
  }
19057
19066
  ];
19058
19067
  }
@@ -19210,9 +19219,9 @@ function collectTextFields(nodes, keys, preferredKinds = []) {
19210
19219
  function tokenize(text) {
19211
19220
  return [...text.toLowerCase().matchAll(/[a-z0-9][a-z0-9'-]{2,}/g)].map((match) => match[0].replace(/^['-]+|['-]+$/g, "")).filter((token) => token.length > 2 && !STOP_WORDS.has(token));
19212
19221
  }
19213
- function firstEvidence(fields, run, path40) {
19222
+ function firstEvidence(fields, run, path41) {
19214
19223
  const first = fields[0];
19215
- return first === void 0 ? evidenceForRun(run, path40) : evidenceForEvent(first.node.event, first.path);
19224
+ return first === void 0 ? evidenceForRun(run, path41) : evidenceForEvent(first.node.event, first.path);
19216
19225
  }
19217
19226
  function collectSourceIds(nodes, keys) {
19218
19227
  const wanted = keySet(keys);
@@ -19589,8 +19598,8 @@ function renderEvalMarkdown(result) {
19589
19598
  if (result.findings.length > 0) {
19590
19599
  lines.push("", "## Findings");
19591
19600
  for (const finding of result.findings) {
19592
- const path40 = finding.evidence[0]?.path;
19593
- lines.push(`- ${finding.ruleId}: ${finding.message}${path40 ? ` (${path40})` : ""}`);
19601
+ const path41 = finding.evidence[0]?.path;
19602
+ lines.push(`- ${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}`);
19594
19603
  }
19595
19604
  }
19596
19605
  return `${lines.join("\n")}
@@ -19637,7 +19646,7 @@ function asConfig2(value) {
19637
19646
  }
19638
19647
  async function loadConfig2(configPath) {
19639
19648
  if (configPath === void 0) return {};
19640
- const extension = path29__default.default.extname(configPath);
19649
+ const extension = path30__default.default.extname(configPath);
19641
19650
  if (TS_CONFIG_EXTENSIONS3.has(extension)) {
19642
19651
  throw new Error(
19643
19652
  "TypeScript eval configs require an explicit precompiled JavaScript config or future --config-loader support."
@@ -19646,7 +19655,7 @@ async function loadConfig2(configPath) {
19646
19655
  if (!CONFIG_EXTENSIONS3.has(extension)) {
19647
19656
  throw new Error("Unsupported eval config extension. Use .json, .js, .mjs, or .cjs.");
19648
19657
  }
19649
- const absolute = path29__default.default.resolve(configPath);
19658
+ const absolute = path30__default.default.resolve(configPath);
19650
19659
  if (extension === ".json") {
19651
19660
  const raw = await promises.readFile(absolute, "utf-8");
19652
19661
  return asConfig2(JSON.parse(raw));
@@ -19783,8 +19792,8 @@ function printHuman2(result) {
19783
19792
  console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
19784
19793
  }
19785
19794
  for (const finding of result.findings) {
19786
- const path40 = finding.evidence[0]?.path;
19787
- console.log(`- ${finding.ruleId}: ${finding.message}${path40 ? ` (${path40})` : ""}`);
19795
+ const path41 = finding.evidence[0]?.path;
19796
+ console.log(`- ${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}`);
19788
19797
  }
19789
19798
  }
19790
19799
  function readErrorResult2(error) {
@@ -20037,14 +20046,14 @@ function exitCodeFor3(result) {
20037
20046
  return 2;
20038
20047
  }
20039
20048
  function explainFinding(finding, blocksBundle) {
20040
- const path40 = finding.evidence[0]?.path ?? "(unknown path)";
20049
+ const path41 = finding.evidence[0]?.path ?? "(unknown path)";
20041
20050
  const category = finding.category ?? "structure";
20042
20051
  const confidence = finding.confidence ?? "medium";
20043
20052
  const detector = finding.detector ?? finding.ruleId;
20044
20053
  const action = finding.action ?? "review";
20045
20054
  const redactionHint = category === "credential" || category === "personal-data" || category === "raw-content" || action.includes("redact") ? "Usually removable by share/strict redaction before bundling." : "May require omitting the field, lowering limits, or an explicit local override.";
20046
20055
  return [
20047
- ` Matched: detector=${detector}; path=${path40}; category=${category}`,
20056
+ ` Matched: detector=${detector}; path=${path41}; category=${category}`,
20048
20057
  ` Why: ${finding.message}`,
20049
20058
  ` Confidence: ${confidence}`,
20050
20059
  ` Redaction: ${redactionHint}`,
@@ -20086,9 +20095,9 @@ function printHuman3(result, explain = false) {
20086
20095
  console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
20087
20096
  }
20088
20097
  for (const finding of result.findings) {
20089
- const path40 = finding.evidence[0]?.path;
20098
+ const path41 = finding.evidence[0]?.path;
20090
20099
  const taxonomy = finding.category !== void 0 || finding.confidence !== void 0 ? ` [${[finding.category, finding.confidence].filter(Boolean).join("/")}]` : "";
20091
- console.log(`- ${finding.ruleId}: ${finding.message}${path40 ? ` (${path40})` : ""}${taxonomy}`);
20100
+ console.log(`- ${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}${taxonomy}`);
20092
20101
  if (explain) {
20093
20102
  const blocks = finding.severity === "error" || finding.status === "fail";
20094
20103
  for (const line of explainFinding(finding, blocks)) {
@@ -20204,7 +20213,7 @@ function messageStartsWithDash(error) {
20204
20213
  }
20205
20214
  init_advanced();
20206
20215
  function validateReporterArtifactPath(options) {
20207
- const outputDir = path29__default.default.resolve(options.outputDir);
20216
+ const outputDir = path30__default.default.resolve(options.outputDir);
20208
20217
  const diagnostics = [];
20209
20218
  const rawPath = options.relativePath;
20210
20219
  if (rawPath.length === 0) {
@@ -20224,7 +20233,7 @@ function validateReporterArtifactPath(options) {
20224
20233
  });
20225
20234
  return { ok: false, outputDir, diagnostics };
20226
20235
  }
20227
- if (path29__default.default.isAbsolute(rawPath) || path29__default.default.win32.isAbsolute(rawPath)) {
20236
+ if (path30__default.default.isAbsolute(rawPath) || path30__default.default.win32.isAbsolute(rawPath)) {
20228
20237
  diagnostics.push({
20229
20238
  code: "artifact_path_absolute",
20230
20239
  severity: "error",
@@ -20233,7 +20242,7 @@ function validateReporterArtifactPath(options) {
20233
20242
  });
20234
20243
  return { ok: false, outputDir, diagnostics };
20235
20244
  }
20236
- const normalized = path29__default.default.posix.normalize(rawPath.replace(/\\/g, "/"));
20245
+ const normalized = path30__default.default.posix.normalize(rawPath.replace(/\\/g, "/"));
20237
20246
  const segments = normalized.split("/");
20238
20247
  if (normalized === "." || normalized.startsWith("../") || segments.some((segment) => segment === "..")) {
20239
20248
  diagnostics.push({
@@ -20244,9 +20253,9 @@ function validateReporterArtifactPath(options) {
20244
20253
  });
20245
20254
  return { ok: false, outputDir, diagnostics };
20246
20255
  }
20247
- const absolutePath = path29__default.default.resolve(outputDir, normalized);
20248
- const relFromOutput = path29__default.default.relative(outputDir, absolutePath);
20249
- if (relFromOutput.length === 0 || relFromOutput.startsWith("..") || path29__default.default.isAbsolute(relFromOutput)) {
20256
+ const absolutePath = path30__default.default.resolve(outputDir, normalized);
20257
+ const relFromOutput = path30__default.default.relative(outputDir, absolutePath);
20258
+ if (relFromOutput.length === 0 || relFromOutput.startsWith("..") || path30__default.default.isAbsolute(relFromOutput)) {
20250
20259
  diagnostics.push({
20251
20260
  code: "artifact_path_escape",
20252
20261
  severity: "error",
@@ -20272,7 +20281,7 @@ var EVIDENCE_CI_ARTIFACT_FILES = [
20272
20281
  function createEvidenceCiArtifacts(options) {
20273
20282
  const profile = options.redactionProfile;
20274
20283
  const prefix = options.relativeDir !== void 0 && options.relativeDir.trim() !== "" ? options.relativeDir.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "") : "";
20275
- const join = (name) => prefix === "" ? name : path29__default.default.posix.join(prefix, name);
20284
+ const join = (name) => prefix === "" ? name : path30__default.default.posix.join(prefix, name);
20276
20285
  const formatFor = (name) => {
20277
20286
  if (name.endsWith(".html")) return "html";
20278
20287
  if (name.endsWith(".jsonl")) return "jsonl";
@@ -20361,8 +20370,8 @@ function renderCheckSection(result) {
20361
20370
  `Diagnostics: ${result.diagnostics.length}`
20362
20371
  ];
20363
20372
  for (const finding of result.findings.slice(0, 10)) {
20364
- const path40 = finding.evidence[0]?.path ?? "(run)";
20365
- lines.push(`- ${finding.ruleId}: ${finding.message} (${path40})`);
20373
+ const path41 = finding.evidence[0]?.path ?? "(run)";
20374
+ lines.push(`- ${finding.ruleId}: ${finding.message} (${path41})`);
20366
20375
  }
20367
20376
  for (const diagnostic7 of result.diagnostics.slice(0, 10)) {
20368
20377
  lines.push(`- ${diagnostic7.code}: ${diagnostic7.message}`);
@@ -20440,8 +20449,8 @@ function renderHtml(trace, check, diff) {
20440
20449
  `;
20441
20450
  }
20442
20451
  async function writeArtifact(outputDir, relativePath, content, files) {
20443
- const outPath = path29__default.default.join(outputDir, relativePath);
20444
- await promises.mkdir(path29__default.default.dirname(outPath), { recursive: true });
20452
+ const outPath = path30__default.default.join(outputDir, relativePath);
20453
+ await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
20445
20454
  await promises.writeFile(outPath, content, "utf-8");
20446
20455
  files.push(relativePath);
20447
20456
  }
@@ -20470,7 +20479,7 @@ function shouldWriteEvidence(options, status) {
20470
20479
  return status === "unsafe" || status === "regression" || status === "unknown" || status === "warning";
20471
20480
  }
20472
20481
  async function artifactsCommand(target, options = {}, stdin = process.stdin) {
20473
- const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ? path29__default.default.resolve(options.outputDir.trim()) : "";
20482
+ const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ? path30__default.default.resolve(options.outputDir.trim()) : "";
20474
20483
  if (outputDir === "") {
20475
20484
  console.error("--output-dir is required.");
20476
20485
  process.exitCode = 1;
@@ -20598,8 +20607,8 @@ async function artifactsCommand(target, options = {}, stdin = process.stdin) {
20598
20607
  }
20599
20608
  const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
20600
20609
  if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
20601
- await promises.mkdir(path29__default.default.dirname(path29__default.default.resolve(summaryTarget)), { recursive: true });
20602
- await promises.appendFile(path29__default.default.resolve(summaryTarget), `
20610
+ await promises.mkdir(path30__default.default.dirname(path30__default.default.resolve(summaryTarget)), { recursive: true });
20611
+ await promises.appendFile(path30__default.default.resolve(summaryTarget), `
20603
20612
  ${renderMarkdown(trace, check, diff)}`, "utf-8");
20604
20613
  }
20605
20614
  const manifestFiles = [...files, "manifest.json"].sort((a, b) => a.localeCompare(b));
@@ -20618,10 +20627,10 @@ ${renderMarkdown(trace, check, diff)}`, "utf-8");
20618
20627
  findings: diff?.findings.length ?? 0,
20619
20628
  diagnostics: diff?.diagnostics.length ?? 0
20620
20629
  },
20621
- ...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary: path29__default.default.resolve(summaryTarget) } : {},
20630
+ ...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary: path30__default.default.resolve(summaryTarget) } : {},
20622
20631
  note: NOTE
20623
20632
  };
20624
- await promises.writeFile(path29__default.default.join(outputDir, "manifest.json"), writeJson3(manifest), "utf-8");
20633
+ await promises.writeFile(path30__default.default.join(outputDir, "manifest.json"), writeJson3(manifest), "utf-8");
20625
20634
  if (options.json === true) {
20626
20635
  console.log(writeJson3(manifest).trimEnd());
20627
20636
  } else {
@@ -20682,8 +20691,8 @@ async function resolveOutputDir(options, runIds, cwd, format) {
20682
20691
  const location = resolveWorkspaceLocation(cwd);
20683
20692
  const manifest = await readWorkspaceManifestFile(location);
20684
20693
  if (manifest.ok && manifest.manifest) {
20685
- const rel = path29__default.default.relative(location.workspaceDir, normalized);
20686
- if (!rel.startsWith("..") && !path29__default.default.isAbsolute(rel)) {
20694
+ const rel = path30__default.default.relative(location.workspaceDir, normalized);
20695
+ if (!rel.startsWith("..") && !path30__default.default.isAbsolute(rel)) {
20687
20696
  return resolveInsideWorkspace(location.workspaceDir, rel);
20688
20697
  }
20689
20698
  }
@@ -20699,7 +20708,7 @@ async function resolveOutputDir(options, runIds, cwd, format) {
20699
20708
  const label = runIds.length === 1 ? sanitizeBundleRunId(runIds[0]) : `multi-${runIds.length}`;
20700
20709
  const base2 = resolveInsideWorkspace(
20701
20710
  location.workspaceDir,
20702
- path29__default.default.join(manifest.manifest.bundlesDir, `bundle-${label}-${stamp}`)
20711
+ path30__default.default.join(manifest.manifest.bundlesDir, `bundle-${label}-${stamp}`)
20703
20712
  );
20704
20713
  return format === "zip" ? `${base2}.zip` : base2;
20705
20714
  }
@@ -21104,19 +21113,19 @@ async function bundleCommand(runIdArg, options = {}) {
21104
21113
  let sidecarDir = outputDir;
21105
21114
  if (outputDir.toLowerCase().endsWith(".html")) {
21106
21115
  htmlPath = outputDir;
21107
- sidecarDir = path29__default.default.dirname(outputDir);
21116
+ sidecarDir = path30__default.default.dirname(outputDir);
21108
21117
  } else {
21109
21118
  await promises.mkdir(outputDir, { recursive: true });
21110
- htmlPath = path29__default.default.join(outputDir, EVIDENCE_HTML_FILENAME);
21119
+ htmlPath = path30__default.default.join(outputDir, EVIDENCE_HTML_FILENAME);
21111
21120
  sidecarDir = outputDir;
21112
21121
  }
21113
21122
  await promises.mkdir(sidecarDir, { recursive: true });
21114
21123
  await promises.writeFile(htmlPath, htmlContent, "utf-8");
21115
- await promises.writeFile(path29__default.default.join(sidecarDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
21124
+ await promises.writeFile(path30__default.default.join(sidecarDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
21116
21125
  outputPath = htmlPath;
21117
21126
  } else if (format === "zip") {
21118
21127
  const zipPath = outputDir.toLowerCase().endsWith(".zip") ? outputDir : `${outputDir}.zip`;
21119
- const zipParent = path29__default.default.dirname(zipPath);
21128
+ const zipParent = path30__default.default.dirname(zipPath);
21120
21129
  await promises.mkdir(zipParent, { recursive: true });
21121
21130
  const entries = [
21122
21131
  ...[...packaged.entries()].map(([relativePath, content]) => ({
@@ -21132,10 +21141,10 @@ async function bundleCommand(runIdArg, options = {}) {
21132
21141
  await promises.mkdir(outputDir, { recursive: true });
21133
21142
  for (const [relativePath, content] of packaged.entries()) {
21134
21143
  const outPath = assertBundlePathContained(outputDir, relativePath);
21135
- await promises.mkdir(path29__default.default.dirname(outPath), { recursive: true });
21144
+ await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
21136
21145
  await promises.writeFile(outPath, content, "utf-8");
21137
21146
  }
21138
- await promises.writeFile(path29__default.default.join(outputDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
21147
+ await promises.writeFile(path30__default.default.join(outputDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
21139
21148
  if (!files.includes(EVIDENCE_MANIFEST_FILENAME)) {
21140
21149
  files.push(EVIDENCE_MANIFEST_FILENAME);
21141
21150
  }
@@ -21184,7 +21193,7 @@ function writeJson5(value) {
21184
21193
  `;
21185
21194
  }
21186
21195
  async function bundleVerifyCommand(targetPath, options = {}) {
21187
- const root = path29__default.default.resolve(targetPath.trim() || ".");
21196
+ const root = path30__default.default.resolve(targetPath.trim() || ".");
21188
21197
  const result = await verifyEvidenceDirectory(root, {
21189
21198
  unexpectedFiles: options.unexpected ?? "fail"
21190
21199
  });
@@ -21217,6 +21226,141 @@ async function bundleVerifyCommand(targetPath, options = {}) {
21217
21226
  process.exitCode = 1;
21218
21227
  }
21219
21228
  }
21229
+ var CLIENTS = [
21230
+ "cursor",
21231
+ "claude-code",
21232
+ "codex",
21233
+ "gemini"
21234
+ ];
21235
+ function isMcpConfigureClient(value) {
21236
+ return CLIENTS.includes(value);
21237
+ }
21238
+ function buildServerBlock(traceDir) {
21239
+ return {
21240
+ command: "npx",
21241
+ args: ["-y", "@agent-inspect/mcp-server", "--dir", traceDir],
21242
+ env: {
21243
+ AGENT_INSPECT_TRACE_DIR: traceDir,
21244
+ AGENT_INSPECT_MCP_REDACTION_PROFILE: "share"
21245
+ }
21246
+ };
21247
+ }
21248
+ function buildMcpClientConfig(client, traceDir) {
21249
+ const server = buildServerBlock(traceDir);
21250
+ switch (client) {
21251
+ case "cursor":
21252
+ return {
21253
+ mcpServers: {
21254
+ "agent-inspect": server
21255
+ }
21256
+ };
21257
+ case "claude-code":
21258
+ return {
21259
+ mcpServers: {
21260
+ "agent-inspect": server
21261
+ }
21262
+ };
21263
+ case "codex":
21264
+ return {
21265
+ mcp_servers: {
21266
+ "agent-inspect": {
21267
+ command: server.command,
21268
+ args: server.args,
21269
+ env: server.env
21270
+ }
21271
+ }
21272
+ };
21273
+ case "gemini":
21274
+ return {
21275
+ mcpServers: {
21276
+ "agent-inspect": server
21277
+ }
21278
+ };
21279
+ default: {
21280
+ const _exhaustive = client;
21281
+ return _exhaustive;
21282
+ }
21283
+ }
21284
+ }
21285
+ function resolveTargetPath(client, projectLocal) {
21286
+ if (projectLocal) {
21287
+ switch (client) {
21288
+ case "cursor":
21289
+ return path30__default.default.join(".cursor", "mcp.json");
21290
+ case "claude-code":
21291
+ return path30__default.default.join(".mcp.json");
21292
+ case "codex":
21293
+ return path30__default.default.join(".codex", "config.toml.json");
21294
+ case "gemini":
21295
+ return path30__default.default.join(".gemini", "settings.json");
21296
+ }
21297
+ }
21298
+ switch (client) {
21299
+ case "cursor":
21300
+ return path30__default.default.join("~", ".cursor", "mcp.json");
21301
+ case "claude-code":
21302
+ return path30__default.default.join("~", ".claude.json");
21303
+ case "codex":
21304
+ return path30__default.default.join("~", ".codex", "config.toml");
21305
+ case "gemini":
21306
+ return path30__default.default.join("~", ".gemini", "settings.json");
21307
+ }
21308
+ }
21309
+ async function mcpConfigureCommand(options) {
21310
+ if (!isMcpConfigureClient(options.client)) {
21311
+ throw new Error(
21312
+ `Unsupported client "${String(options.client)}". Use: ${CLIENTS.join(", ")}`
21313
+ );
21314
+ }
21315
+ const traceDir = options.dir?.trim() || ".agent-inspect";
21316
+ const projectLocal = Boolean(options.projectLocal);
21317
+ const write = Boolean(options.write);
21318
+ const yes = Boolean(options.yes);
21319
+ const dryRun = !(write && yes && projectLocal);
21320
+ const config = buildMcpClientConfig(options.client, traceDir);
21321
+ const targetPath = resolveTargetPath(options.client, projectLocal);
21322
+ const notes = [
21323
+ "Read-only MCP server; no network upload; share redaction by default.",
21324
+ "Dry-run by default. Pass --project-local --write --yes to write a project file.",
21325
+ "User-level paths are never auto-written by this command.",
21326
+ "Remove the agent-inspect server block to uninstall."
21327
+ ];
21328
+ let wrote = false;
21329
+ if (!dryRun && projectLocal) {
21330
+ const abs = path30__default.default.resolve(targetPath);
21331
+ await promises.mkdir(path30__default.default.dirname(abs), { recursive: true });
21332
+ await promises.writeFile(abs, `${JSON.stringify(config, null, 2)}
21333
+ `, "utf8");
21334
+ wrote = true;
21335
+ }
21336
+ const result = {
21337
+ client: options.client,
21338
+ dryRun,
21339
+ wrote,
21340
+ targetPath,
21341
+ config,
21342
+ notes
21343
+ };
21344
+ if (options.json) {
21345
+ process.stdout.write(`${JSON.stringify(result, null, 2)}
21346
+ `);
21347
+ } else {
21348
+ process.stdout.write(
21349
+ [
21350
+ `Client: ${result.client}`,
21351
+ `Mode: ${result.dryRun ? "dry-run" : "write"}`,
21352
+ `Target: ${result.targetPath}`,
21353
+ `Wrote: ${result.wrote}`,
21354
+ "",
21355
+ JSON.stringify(result.config, null, 2),
21356
+ "",
21357
+ ...result.notes.map((note) => `- ${note}`),
21358
+ ""
21359
+ ].join("\n")
21360
+ );
21361
+ }
21362
+ return result;
21363
+ }
21220
21364
  var NOTE2 = "Generated locally by AgentInspect from reporter artifact manifests. Trace contents are not embedded.";
21221
21365
  var MAX_TEXT = 180;
21222
21366
  var FRAMEWORKS = /* @__PURE__ */ new Set(["vitest", "jest", "manual"]);
@@ -21344,23 +21488,23 @@ function readManifestDocument(value) {
21344
21488
  };
21345
21489
  }
21346
21490
  function cwdRelative(filePath) {
21347
- const relative = path29__default.default.relative(process.cwd(), path29__default.default.resolve(filePath)).replace(/\\/g, "/");
21348
- if (relative === "" || relative.startsWith("../") || path29__default.default.isAbsolute(relative)) {
21349
- return path29__default.default.basename(filePath);
21491
+ const relative = path30__default.default.relative(process.cwd(), path30__default.default.resolve(filePath)).replace(/\\/g, "/");
21492
+ if (relative === "" || relative.startsWith("../") || path30__default.default.isAbsolute(relative)) {
21493
+ return path30__default.default.basename(filePath);
21350
21494
  }
21351
21495
  return relative;
21352
21496
  }
21353
21497
  async function readReporterManifest(filePath) {
21354
- const absolute = path29__default.default.resolve(filePath);
21498
+ const absolute = path30__default.default.resolve(filePath);
21355
21499
  const raw = await promises.readFile(absolute, "utf-8");
21356
21500
  const document = readManifestDocument(JSON.parse(raw));
21357
21501
  const manifest = document.manifest;
21358
21502
  const results = manifest.results.map((result) => ({
21359
21503
  testId: safeText(result.testId),
21360
21504
  name: safeText(result.name),
21361
- ...result.file === void 0 ? {} : { file: safeText(path29__default.default.basename(result.file)) },
21505
+ ...result.file === void 0 ? {} : { file: safeText(path30__default.default.basename(result.file)) },
21362
21506
  status: result.status,
21363
- ...result.tracePath === void 0 ? {} : { tracePath: safeText(path29__default.default.basename(result.tracePath)) },
21507
+ ...result.tracePath === void 0 ? {} : { tracePath: safeText(path30__default.default.basename(result.tracePath)) },
21364
21508
  artifacts: result.artifacts,
21365
21509
  diagnostics: result.diagnostics
21366
21510
  }));
@@ -21499,15 +21643,15 @@ async function ciSummaryCommand(manifestPaths, options = {}) {
21499
21643
  return;
21500
21644
  }
21501
21645
  const markdown = renderMarkdown2(result);
21502
- const outputPath = options.output !== void 0 && options.output.trim() !== "" ? path29__default.default.resolve(options.output.trim()) : void 0;
21646
+ const outputPath = options.output !== void 0 && options.output.trim() !== "" ? path30__default.default.resolve(options.output.trim()) : void 0;
21503
21647
  if (outputPath !== void 0) {
21504
- await promises.mkdir(path29__default.default.dirname(outputPath), { recursive: true });
21648
+ await promises.mkdir(path30__default.default.dirname(outputPath), { recursive: true });
21505
21649
  await promises.writeFile(outputPath, markdown, "utf-8");
21506
21650
  }
21507
21651
  const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
21508
21652
  if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
21509
- const summaryPath = path29__default.default.resolve(summaryTarget);
21510
- await promises.mkdir(path29__default.default.dirname(summaryPath), { recursive: true });
21653
+ const summaryPath = path30__default.default.resolve(summaryTarget);
21654
+ await promises.mkdir(path30__default.default.dirname(summaryPath), { recursive: true });
21511
21655
  await promises.appendFile(summaryPath, `
21512
21656
  ${markdown}`, "utf-8");
21513
21657
  }
@@ -21655,7 +21799,7 @@ jobs:
21655
21799
  }
21656
21800
  async function planInit(options = {}) {
21657
21801
  const framework = normalizeFramework(options.framework);
21658
- const cwd = path29__default.default.resolve(options.cwd ?? process.cwd());
21802
+ const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
21659
21803
  const demoPath = framework === "custom" ? "examples/agent-inspect-demo.mjs" : `examples/agent-inspect-${framework}-demo.mjs`;
21660
21804
  const candidates = [
21661
21805
  { rel: CONFIG_FILE, content: configTemplate(framework) },
@@ -21670,7 +21814,7 @@ async function planInit(options = {}) {
21670
21814
  }
21671
21815
  const files = [];
21672
21816
  for (const candidate of candidates) {
21673
- const abs = path29__default.default.join(cwd, candidate.rel);
21817
+ const abs = path30__default.default.join(cwd, candidate.rel);
21674
21818
  try {
21675
21819
  await promises.access(abs);
21676
21820
  files.push({
@@ -21691,12 +21835,12 @@ async function writePlannedFiles(plan, cwd, options) {
21691
21835
  if (entry.action === "skip") {
21692
21836
  continue;
21693
21837
  }
21694
- const abs = path29__default.default.join(cwd, entry.path);
21838
+ const abs = path30__default.default.join(cwd, entry.path);
21695
21839
  if (options.dryRun) {
21696
21840
  written.push(entry.path);
21697
21841
  continue;
21698
21842
  }
21699
- await promises.mkdir(path29__default.default.dirname(abs), { recursive: true });
21843
+ await promises.mkdir(path30__default.default.dirname(abs), { recursive: true });
21700
21844
  const content = entry.path === CONFIG_FILE ? configTemplate(plan.framework) : entry.path === GITKEEP ? "" : entry.path.endsWith(".yml") ? githubWorkflowTemplate() : demoTemplate(plan.framework);
21701
21845
  await promises.writeFile(abs, content, "utf-8");
21702
21846
  written.push(entry.path);
@@ -21704,7 +21848,7 @@ async function writePlannedFiles(plan, cwd, options) {
21704
21848
  return written;
21705
21849
  }
21706
21850
  async function initCommand(options = {}) {
21707
- const cwd = path29__default.default.resolve(options.cwd ?? process.cwd());
21851
+ const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
21708
21852
  try {
21709
21853
  const plan = await planInit({ ...options, cwd });
21710
21854
  const toWrite = plan.files.filter((file) => file.action === "create").map((f) => f.path);
@@ -21795,7 +21939,7 @@ function envCheck(name, optional = true) {
21795
21939
  };
21796
21940
  }
21797
21941
  async function traceDirWritable(traceDir) {
21798
- const resolved = path29__default.default.resolve(traceDir);
21942
+ const resolved = path30__default.default.resolve(traceDir);
21799
21943
  try {
21800
21944
  await promises.mkdir(resolved, { recursive: true });
21801
21945
  await promises.access(resolved, promises.constants.W_OK);
@@ -21816,10 +21960,10 @@ async function traceDirWritable(traceDir) {
21816
21960
  }
21817
21961
  }
21818
21962
  function readPackageVersionNearEntry(entryPath, packageName) {
21819
- let dir = path29__default.default.dirname(path29__default.default.resolve(entryPath));
21820
- const { root } = path29__default.default.parse(dir);
21963
+ let dir = path30__default.default.dirname(path30__default.default.resolve(entryPath));
21964
+ const { root } = path30__default.default.parse(dir);
21821
21965
  while (true) {
21822
- const candidate = path29__default.default.join(dir, "package.json");
21966
+ const candidate = path30__default.default.join(dir, "package.json");
21823
21967
  if (fs.existsSync(candidate)) {
21824
21968
  try {
21825
21969
  const pkg = JSON.parse(fs.readFileSync(candidate, "utf8"));
@@ -21830,14 +21974,14 @@ function readPackageVersionNearEntry(entryPath, packageName) {
21830
21974
  }
21831
21975
  }
21832
21976
  if (dir === root) break;
21833
- const parent = path29__default.default.dirname(dir);
21977
+ const parent = path30__default.default.dirname(dir);
21834
21978
  if (parent === dir) break;
21835
21979
  dir = parent;
21836
21980
  }
21837
21981
  return void 0;
21838
21982
  }
21839
21983
  function resolveInstalledPackage(cwd, name) {
21840
- const require2 = module$1.createRequire(path29__default.default.join(cwd, "package.json"));
21984
+ const require2 = module$1.createRequire(path30__default.default.join(cwd, "package.json"));
21841
21985
  try {
21842
21986
  const entry = require2.resolve(name);
21843
21987
  let version2;
@@ -21935,7 +22079,7 @@ function versionMismatchCheck(cwd) {
21935
22079
  };
21936
22080
  }
21937
22081
  async function runDoctorChecks(options = {}) {
21938
- const cwd = path29__default.default.resolve(options.cwd ?? process3__default.default.cwd());
22082
+ const cwd = path30__default.default.resolve(options.cwd ?? process3__default.default.cwd());
21939
22083
  const traceDir = options.traceDir?.trim() || process3__default.default.env.AGENT_INSPECT_TRACE_DIR?.trim() || ".agent-inspect";
21940
22084
  const checks2 = [
21941
22085
  nodeVersionCheck(),
@@ -22175,7 +22319,7 @@ function parsePluginManifest(input3) {
22175
22319
  };
22176
22320
  }
22177
22321
  async function readPluginManifestFile(packageDir) {
22178
- const manifestPath = path29__default.default.join(packageDir, PLUGIN_MANIFEST_FILENAME);
22322
+ const manifestPath = path30__default.default.join(packageDir, PLUGIN_MANIFEST_FILENAME);
22179
22323
  try {
22180
22324
  const raw = await promises.readFile(manifestPath, "utf8");
22181
22325
  const parsed = parsePluginManifest(JSON.parse(raw));
@@ -22250,7 +22394,7 @@ function createTraceDirectoryIndexer() {
22250
22394
  // packages/cli/src/plugins.ts
22251
22395
  async function readPackageName(packageDir) {
22252
22396
  try {
22253
- const raw = await promises.readFile(path29__default.default.join(packageDir, "package.json"), "utf8");
22397
+ const raw = await promises.readFile(path30__default.default.join(packageDir, "package.json"), "utf8");
22254
22398
  const parsed = JSON.parse(raw);
22255
22399
  return typeof parsed.name === "string" ? parsed.name : void 0;
22256
22400
  } catch {
@@ -22258,7 +22402,7 @@ async function readPackageName(packageDir) {
22258
22402
  }
22259
22403
  }
22260
22404
  async function discoverPlugins(cwd = process.cwd()) {
22261
- const nodeModules = path29__default.default.join(cwd, "node_modules");
22405
+ const nodeModules = path30__default.default.join(cwd, "node_modules");
22262
22406
  const found = [];
22263
22407
  let entries;
22264
22408
  try {
@@ -22269,7 +22413,7 @@ async function discoverPlugins(cwd = process.cwd()) {
22269
22413
  for (const entry of entries.sort()) {
22270
22414
  if (entry.startsWith("@")) continue;
22271
22415
  if (!isPluginPackageName(entry)) continue;
22272
- const packageDir = path29__default.default.join(nodeModules, entry);
22416
+ const packageDir = path30__default.default.join(nodeModules, entry);
22273
22417
  const manifestRead = await readPluginManifestFile(packageDir);
22274
22418
  found.push({
22275
22419
  packageName: entry,
@@ -22282,7 +22426,7 @@ async function discoverPlugins(cwd = process.cwd()) {
22282
22426
  return found;
22283
22427
  }
22284
22428
  async function validatePluginPackage(packageRef, cwd = process.cwd()) {
22285
- const packageDir = path29__default.default.isAbsolute(packageRef) ? packageRef : path29__default.default.join(cwd, "node_modules", packageRef);
22429
+ const packageDir = path30__default.default.isAbsolute(packageRef) ? packageRef : path30__default.default.join(cwd, "node_modules", packageRef);
22286
22430
  const packageName = await readPackageName(packageDir) ?? packageRef;
22287
22431
  const errors = [];
22288
22432
  const warnings = [];
@@ -22359,7 +22503,7 @@ async function pluginsValidateCommand(packageRef, cwd) {
22359
22503
  init_advanced();
22360
22504
  var INDEX_FILENAME = ".agent-inspect-index.json";
22361
22505
  function traceIndexPath(traceDir) {
22362
- return path29__default.default.join(traceDir, INDEX_FILENAME);
22506
+ return path30__default.default.join(traceDir, INDEX_FILENAME);
22363
22507
  }
22364
22508
  function parseMaxEntries(raw) {
22365
22509
  if (raw === void 0 || raw.trim() === "") return void 0;
@@ -22505,7 +22649,7 @@ async function newestTraceMtimeMs2(traceDir) {
22505
22649
  for (const file of files) {
22506
22650
  if (!file.endsWith(".jsonl")) continue;
22507
22651
  try {
22508
- const s = await promises.stat(path29__default.default.join(traceDir, file));
22652
+ const s = await promises.stat(path30__default.default.join(traceDir, file));
22509
22653
  if (s.mtimeMs > newest) newest = s.mtimeMs;
22510
22654
  } catch {
22511
22655
  }
@@ -22760,11 +22904,11 @@ function printJson5(value) {
22760
22904
  console.log(JSON.stringify(value, null, 2));
22761
22905
  }
22762
22906
  function resolveCwd(options) {
22763
- return path29__default.default.resolve(options.cwd ?? process.cwd());
22907
+ return path30__default.default.resolve(options.cwd ?? process.cwd());
22764
22908
  }
22765
22909
  async function suiteInitCommand(options = {}) {
22766
22910
  const cwd = resolveCwd(options);
22767
- const configPath = path29__default.default.join(cwd, DEFAULT_CONFIG_FILENAME);
22911
+ const configPath = path30__default.default.join(cwd, DEFAULT_CONFIG_FILENAME);
22768
22912
  const template = options.template?.trim();
22769
22913
  const suiteConfig = template !== void 0 && template !== "" ? resolveSuiteTemplate(template) : defaultSuiteConfigTemplate();
22770
22914
  if (options.dryRun) {
@@ -22883,13 +23027,13 @@ async function suiteListCommand(options = {}) {
22883
23027
  }
22884
23028
  async function writeSuiteArtifact(result, configOutputDir, options) {
22885
23029
  const cwd = resolveCwd(options);
22886
- const outputDir = path29__default.default.resolve(
23030
+ const outputDir = path30__default.default.resolve(
22887
23031
  cwd,
22888
23032
  options.output ?? configOutputDir ?? DEFAULT_SUITE_ARTIFACTS_DIR
22889
23033
  );
22890
23034
  await promises.mkdir(outputDir, { recursive: true });
22891
23035
  const stamp = result.startedAt.replace(/[:.]/g, "-");
22892
- const filePath = path29__default.default.join(outputDir, `${result.suiteName}-${stamp}.json`);
23036
+ const filePath = path30__default.default.join(outputDir, `${result.suiteName}-${stamp}.json`);
22893
23037
  await promises.writeFile(filePath, `${JSON.stringify(result, null, 2)}
22894
23038
  `, "utf-8");
22895
23039
  return filePath;
@@ -22947,7 +23091,7 @@ async function loadSuiteResultFromInput(options) {
22947
23091
  if (options.input === void 0 || options.input.trim() === "") {
22948
23092
  throw new Error("Pass --input <suite-run.json> from a prior suite run.");
22949
23093
  }
22950
- const inputPath = path29__default.default.resolve(cwd, options.input.trim());
23094
+ const inputPath = path30__default.default.resolve(cwd, options.input.trim());
22951
23095
  const raw = await promises.readFile(inputPath, "utf-8");
22952
23096
  return JSON.parse(raw);
22953
23097
  }
@@ -22984,9 +23128,9 @@ function normalizeMetrics2(raw) {
22984
23128
  }
22985
23129
  async function writeArtifacts(result, outputDir) {
22986
23130
  await promises.mkdir(outputDir, { recursive: true });
22987
- const jsonPath = path29__default.default.join(outputDir, "cohort-results.json");
22988
- const markdownPath = path29__default.default.join(outputDir, "cohort-summary.md");
22989
- const htmlPath = path29__default.default.join(outputDir, "cohort-report.html");
23131
+ const jsonPath = path30__default.default.join(outputDir, "cohort-results.json");
23132
+ const markdownPath = path30__default.default.join(outputDir, "cohort-summary.md");
23133
+ const htmlPath = path30__default.default.join(outputDir, "cohort-report.html");
22990
23134
  await promises.writeFile(jsonPath, `${renderCohortReport(result, { format: "json" })}
22991
23135
  `, "utf-8");
22992
23136
  await promises.writeFile(
@@ -23014,7 +23158,7 @@ async function cohortCommand(options = {}) {
23014
23158
  const format = options.format ?? (options.json ? "json" : "markdown");
23015
23159
  let artifacts;
23016
23160
  if (options.output !== void 0 && options.output.trim() !== "") {
23017
- artifacts = await writeArtifacts(result, path29__default.default.resolve(options.output.trim()));
23161
+ artifacts = await writeArtifacts(result, path30__default.default.resolve(options.output.trim()));
23018
23162
  }
23019
23163
  if (options.json || format === "json") {
23020
23164
  console.log(
@@ -23087,11 +23231,11 @@ function parseDuration2(value) {
23087
23231
  async function writeArtifacts2(result, outputDir) {
23088
23232
  await promises.mkdir(outputDir, { recursive: true });
23089
23233
  const paths = {
23090
- jsonPath: path29__default.default.join(outputDir, "gate-results.json"),
23091
- markdownPath: path29__default.default.join(outputDir, "gate-summary.md"),
23092
- htmlPath: path29__default.default.join(outputDir, "gate-report.html"),
23093
- junitPath: path29__default.default.join(outputDir, "junit.xml"),
23094
- githubPath: path29__default.default.join(outputDir, "github-step-summary.md")
23234
+ jsonPath: path30__default.default.join(outputDir, "gate-results.json"),
23235
+ markdownPath: path30__default.default.join(outputDir, "gate-summary.md"),
23236
+ htmlPath: path30__default.default.join(outputDir, "gate-report.html"),
23237
+ junitPath: path30__default.default.join(outputDir, "junit.xml"),
23238
+ githubPath: path30__default.default.join(outputDir, "github-step-summary.md")
23095
23239
  };
23096
23240
  await promises.writeFile(
23097
23241
  paths.jsonPath,
@@ -23159,7 +23303,7 @@ async function gateCommand(options = {}) {
23159
23303
  const result = await runGate(runs, gateOptions);
23160
23304
  let artifacts;
23161
23305
  if (options.output !== void 0 && options.output.trim() !== "") {
23162
- artifacts = await writeArtifacts2(result, path29__default.default.resolve(options.output.trim()));
23306
+ artifacts = await writeArtifacts2(result, path30__default.default.resolve(options.output.trim()));
23163
23307
  }
23164
23308
  if (options.json || format === "json") {
23165
23309
  console.log(JSON.stringify({ ...result, artifacts: artifacts ?? null }, null, 2));
@@ -23691,6 +23835,20 @@ function createCliProgram() {
23691
23835
  ).option("--format <format>", "markdown, json, or html", "markdown").option("-o, --output <dir>", "write cohort-results.json, cohort-summary.md, cohort-report.html").option("--json", "print deterministic JSON result").action((opts) => {
23692
23836
  runCommand(() => cohortCommand(opts));
23693
23837
  });
23838
+ const mcpCmd = program.command("mcp").description("Configure local coding-agent MCP clients (read-only; dry-run by default)");
23839
+ mcpCmd.command("configure").description("Print or write MCP client config for Cursor/Claude/Codex/Gemini").requiredOption(
23840
+ "--client <name>",
23841
+ "cursor | claude-code | codex | gemini"
23842
+ ).option("--dir <path>", "trace directory for the MCP server", ".agent-inspect").option("--project-local", "target a project-local config path").option("--write", "write config (requires --project-local --yes)").option("--yes", "confirm write").option("--json", "print deterministic JSON result").action((opts) => {
23843
+ runCommand(async () => {
23844
+ if (!isMcpConfigureClient(opts.client)) {
23845
+ throw new Error(
23846
+ `Unsupported --client "${opts.client}". Use: cursor, claude-code, codex, gemini`
23847
+ );
23848
+ }
23849
+ await mcpConfigureCommand({ ...opts, client: opts.client });
23850
+ });
23851
+ });
23694
23852
  program.command("gate").description("Run deterministic CI quality gates over traces or suites (v5.2+)").option("--dir <path>", "trace directory for threshold checks").option("--suite <path>", "suite config path").option("--max-error-rate <percent>", "maximum allowed error rate percentage").option("--max-p95-duration <ms>", "maximum allowed p95 run duration in ms").option("--forbid-tool <name>", "forbidden tool name (repeatable or comma-separated)").option(
23695
23853
  "--require-observation <name>",
23696
23854
  "required passed observation (repeatable or comma-separated)"
@@ -23707,9 +23865,9 @@ function isPrimaryModule() {
23707
23865
  if (!entry) return false;
23708
23866
  const selfPath = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
23709
23867
  try {
23710
- return fs.realpathSync(path29__default.default.resolve(entry)) === fs.realpathSync(path29__default.default.resolve(selfPath));
23868
+ return fs.realpathSync(path30__default.default.resolve(entry)) === fs.realpathSync(path30__default.default.resolve(selfPath));
23711
23869
  } catch {
23712
- return path29__default.default.resolve(entry) === path29__default.default.resolve(selfPath);
23870
+ return path30__default.default.resolve(entry) === path30__default.default.resolve(selfPath);
23713
23871
  }
23714
23872
  }
23715
23873
  if (isPrimaryModule()) {