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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createSafetyOversizedAttributeRule, resolveTraceDir, parseDuration, buildSessionIndex, resolveBundleRunIds, getTraceFilePath, openTrace, sha256Hex, collectTraceSchemaVersions, aggregateBundleSafeStatus, bundleFailsOnSafety, bundleRunAssetRelativePath, buildPlaceholderArtifact, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceHtmlShell, buildEvidenceProvenanceViewHtml, EVIDENCE_FORMAT_VERSION, inferEvidenceFileRole, buildEvidenceSafetyViewHtml, buildEvidenceDiffViewHtml, buildEvidenceCircuitViewHtml, buildEvidenceOutcomesViewHtml, buildEvidenceContractsViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceCausalFailureViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceTreeViewHtml, buildEvidenceManifest, serializeEvidenceManifest, buildZipArchive, assertBundlePathContained, enrichSessionRunRecord, normalizeBundleOutputPath, sanitizeBundleRunId, defaultBundleOutputPath, runTraceChecks, assertEvidenceRelativePath, TraceDirectory, loadTraceMetadataList, loadSessionRunRecords, TraceReadError, resolveRedactionProfile, applyProfileMetadataCaps, Redactor, flattenTree, escapeHtml, safeString, compactAttributes, stableJson, escapeMarkdown, truncateStringForProfile, extractMetadata, filterTraces, truncateName, buildRunSummary, formatDuration, formatTimestamp, isAgentInspectTrace, filterMetasBySessionScope, aggregateSessionCheckResults, createBaselineRegressionRule, buildEvidenceCiPackage, verifyEvidenceDirectory, diffTraceEvents, renderRunDiff, buildRunTimeline, renderTimeline, buildTraceStats, renderTraceStats, parseDurationFilter, searchTraces, buildActivitySummary, renderActivitySummaryHuman, buildRunWhatSummary, renderRunWhat, buildLocalExplanation, resolveSuiteTemplate, defaultSuiteConfigTemplate, loadSuiteConfig, validateSuiteConfig, runSuite, renderSuiteReport, analyzeCohort, renderCohortReport, gateHasThresholds, runGate, renderGateReport, persistedInspectEventsToTraceEvents, renderStepLine, renderErrorLine, getIndent, TreeBuilder, zeroKinds, validateEvent, traceEventToPersistedInspectEvent, isPersistedInspectEvent, createRunStatusRule, createStructureOrphanRule, createStructureCycleRule, createRunDurationRule, createMaxStepDurationRule, createRequireCompletedRule, createStallDetectionRule, createObservedOutcomeRule, createRunDepthRule, createToolUsageRule, createLlmUsageRule, createStructureRelationshipRule, createStructureParallelWidthRule, summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml, DEFAULT_SUITE_ARTIFACTS_DIR, parseCohortMetricList, COHORT_METRIC_IDS, parseGateList, nanoid, diffRuns, manualTraceEventsToComparableRun } from './chunk-36IJ76LH.mjs';
2
+ import { createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createSafetyOversizedAttributeRule, resolveTraceDir, parseDuration, buildSessionIndex, resolveBundleRunIds, getTraceFilePath, openTrace, sha256Hex, collectTraceSchemaVersions, aggregateBundleSafeStatus, bundleFailsOnSafety, bundleRunAssetRelativePath, buildPlaceholderArtifact, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceHtmlShell, buildEvidenceProvenanceViewHtml, EVIDENCE_FORMAT_VERSION, inferEvidenceFileRole, buildEvidenceSafetyViewHtml, buildEvidenceDiffViewHtml, buildEvidenceCircuitViewHtml, buildEvidenceOutcomesViewHtml, buildEvidenceContractsViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceCausalFailureViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceTreeViewHtml, buildEvidenceManifest, serializeEvidenceManifest, buildZipArchive, assertBundlePathContained, enrichSessionRunRecord, normalizeBundleOutputPath, sanitizeBundleRunId, defaultBundleOutputPath, runTraceChecks, assertEvidenceRelativePath, TraceDirectory, loadTraceMetadataList, loadSessionRunRecords, TraceReadError, resolveRedactionProfile, applyProfileMetadataCaps, Redactor, flattenTree, escapeHtml, safeString, compactAttributes, stableJson, escapeMarkdown, truncateStringForProfile, extractMetadata, filterTraces, truncateName, buildRunSummary, formatDuration, formatTimestamp, isAgentInspectTrace, filterMetasBySessionScope, aggregateSessionCheckResults, createBaselineRegressionRule, buildEvidenceCiPackage, verifyEvidenceDirectory, diffTraceEvents, renderRunDiff, buildRunTimeline, renderTimeline, buildTraceStats, renderTraceStats, parseDurationFilter, searchTraces, buildActivitySummary, renderActivitySummaryHuman, buildRunWhatSummary, renderRunWhat, buildLocalExplanation, resolveSuiteTemplate, defaultSuiteConfigTemplate, loadSuiteConfig, validateSuiteConfig, runSuite, renderSuiteReport, analyzeCohort, renderCohortReport, gateHasThresholds, runGate, renderGateReport, persistedInspectEventsToTraceEvents, renderStepLine, renderErrorLine, getIndent, TreeBuilder, zeroKinds, validateEvent, traceEventToPersistedInspectEvent, isPersistedInspectEvent, createRunStatusRule, createStructureOrphanRule, createStructureCycleRule, createRunDurationRule, createMaxStepDurationRule, createRequireCompletedRule, createStallDetectionRule, createObservedOutcomeRule, createRunDepthRule, createToolUsageRule, createLlmUsageRule, createStructureRelationshipRule, createStructureParallelWidthRule, summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml, DEFAULT_SUITE_ARTIFACTS_DIR, parseCohortMetricList, COHORT_METRIC_IDS, parseGateList, nanoid, diffRuns, manualTraceEventsToComparableRun } from './chunk-XTAA733P.mjs';
3
3
  import { realpathSync, constants as constants$1, existsSync, readFileSync } from 'fs';
4
- import path15 from 'path';
4
+ import path16 from 'path';
5
5
  import { fileURLToPath, pathToFileURL } from 'url';
6
6
  import { Command, Option } from 'commander';
7
7
  import { readFile, stat, mkdir, writeFile, unlink, appendFile, rm, access, open, readdir, constants } from 'fs/promises';
@@ -11,7 +11,7 @@ import { createServer } from 'http';
11
11
  import { createRequire } from 'module';
12
12
 
13
13
  // package.json
14
- var version = "6.10.0";
14
+ var version = "6.12.0";
15
15
 
16
16
  // packages/cli/src/trace-dir-scale.ts
17
17
  var TRACE_COUNT_WARN = 1e3;
@@ -2971,9 +2971,9 @@ Trace directory: ${traceDir}`);
2971
2971
  process.exitCode = 1;
2972
2972
  }
2973
2973
  const resolvedOutput = resolveOutputOption(options);
2974
- const outPath = resolvedOutput !== void 0 ? path15.resolve(resolvedOutput) : void 0;
2974
+ const outPath = resolvedOutput !== void 0 ? path16.resolve(resolvedOutput) : void 0;
2975
2975
  if (outPath !== void 0) {
2976
- await mkdir(path15.dirname(outPath), { recursive: true });
2976
+ await mkdir(path16.dirname(outPath), { recursive: true });
2977
2977
  await writeFile(outPath, result.content, "utf-8");
2978
2978
  const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
2979
2979
  console.log(`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`);
@@ -3317,7 +3317,7 @@ function indexedToMetadata(row, traceDir) {
3317
3317
  endedAt: row.endedAt ?? void 0,
3318
3318
  durationMs: row.durationMs ?? void 0,
3319
3319
  eventCount: 0,
3320
- filePath: path15.join(traceDir, row.file),
3320
+ filePath: path16.join(traceDir, row.file),
3321
3321
  fileSize: 0,
3322
3322
  createdAt: new Date(row.mtimeMs)
3323
3323
  };
@@ -3346,7 +3346,7 @@ async function newestTraceMtimeMs(traceDir) {
3346
3346
  }
3347
3347
  async function loadSessionRuns(traceDir) {
3348
3348
  try {
3349
- const mod = await import('./src-YFN3Q3GP.mjs');
3349
+ const mod = await import('./src-G7PM24W2.mjs');
3350
3350
  const dbPath = mod.resolveIndexDbPath(traceDir);
3351
3351
  const status = mod.indexStatus(dbPath);
3352
3352
  if (!status.healthy) {
@@ -3795,9 +3795,9 @@ async function reportCommand(runId, options = {}) {
3795
3795
  ...options.section ? { section: options.section } : {}
3796
3796
  });
3797
3797
  const resolvedOutput = resolveOutputOption(options);
3798
- const outPath = resolvedOutput !== void 0 ? path15.resolve(resolvedOutput) : void 0;
3798
+ const outPath = resolvedOutput !== void 0 ? path16.resolve(resolvedOutput) : void 0;
3799
3799
  if (outPath !== void 0) {
3800
- await mkdir(path15.dirname(outPath), { recursive: true });
3800
+ await mkdir(path16.dirname(outPath), { recursive: true });
3801
3801
  await writeFile(outPath, result.content, "utf-8");
3802
3802
  console.log(`Wrote ${result.fileExtension} report to ${outPath}`);
3803
3803
  }
@@ -3923,8 +3923,8 @@ function passesLuhn(value) {
3923
3923
  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;
3924
3924
  var EPOCH_MS_RE = /^1[0-9]{12}$/;
3925
3925
  var EMAIL_RE = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
3926
- function pathSuggestsNonCard(path26) {
3927
- const normalized = path26.toLowerCase().replace(/[^a-z0-9._]/g, "");
3926
+ function pathSuggestsNonCard(path27) {
3927
+ const normalized = path27.toLowerCase().replace(/[^a-z0-9._]/g, "");
3928
3928
  return /(^|\.)(tokenusage|usage)(\.|$)/.test(normalized) || /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\.|$)/.test(normalized) || /(^|\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\.|$)/.test(
3929
3929
  normalized
3930
3930
  ) || /(^|\.)ts(\.|$)/.test(normalized);
@@ -4111,17 +4111,17 @@ function applyRule(rule, value, replacement) {
4111
4111
  }
4112
4112
  return value;
4113
4113
  }
4114
- function childPath(path26, key) {
4114
+ function childPath(path27, key) {
4115
4115
  if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
4116
- return path26 ? `${path26}.${key}` : key;
4116
+ return path27 ? `${path27}.${key}` : key;
4117
4117
  }
4118
- return `${path26 || "$"}[${JSON.stringify(key)}]`;
4118
+ return `${path27 || "$"}[${JSON.stringify(key)}]`;
4119
4119
  }
4120
- function indexPath(path26, index) {
4121
- return `${path26 || "$"}[${index}]`;
4120
+ function indexPath(path27, index) {
4121
+ return `${path27 || "$"}[${index}]`;
4122
4122
  }
4123
- function makeFinding(path26, detector, action, matchKind, severity = "warning", preview) {
4124
- return preview === void 0 ? { path: path26, detector, action, severity, matchKind } : { path: path26, detector, action, severity, matchKind, preview };
4123
+ function makeFinding(path27, detector, action, matchKind, severity = "warning", preview) {
4124
+ return preview === void 0 ? { path: path27, detector, action, severity, matchKind } : { path: path27, detector, action, severity, matchKind, preview };
4125
4125
  }
4126
4126
  function createRedactionProfile(profile = "local") {
4127
4127
  switch (profile) {
@@ -4190,11 +4190,11 @@ var Redactor2 = class {
4190
4190
  #recordFinding(state, finding) {
4191
4191
  if (this.#collectFindings) state.findings.push(finding);
4192
4192
  }
4193
- #redactValue(value, key, path26, depth, state) {
4193
+ #redactValue(value, key, path27, depth, state) {
4194
4194
  if (depth > this.#maxDepth) {
4195
4195
  this.#recordFinding(
4196
4196
  state,
4197
- makeFinding(path26, "structure.maxDepth", "truncate", "value", "warning")
4197
+ makeFinding(path27, "structure.maxDepth", "truncate", "value", "warning")
4198
4198
  );
4199
4199
  return "[Truncated]";
4200
4200
  }
@@ -4203,19 +4203,19 @@ var Redactor2 = class {
4203
4203
  if (rule) {
4204
4204
  this.#recordFinding(
4205
4205
  state,
4206
- makeFinding(path26, `key.${rule.key}`, actionForRule(rule), "key", "warning")
4206
+ makeFinding(path27, `key.${rule.key}`, actionForRule(rule), "key", "warning")
4207
4207
  );
4208
4208
  return applyRule(rule, value, this.#replacement);
4209
4209
  }
4210
4210
  }
4211
4211
  for (const detector of this.#detectors) {
4212
- const detections = detector.detect({ path: path26, key, value });
4212
+ const detections = detector.detect({ path: path27, key, value });
4213
4213
  for (const detection of detections) {
4214
4214
  const action = detection.action ?? "replace";
4215
4215
  this.#recordFinding(
4216
4216
  state,
4217
4217
  makeFinding(
4218
- path26,
4218
+ path27,
4219
4219
  detector.id,
4220
4220
  action,
4221
4221
  detection.matchKind ?? detector.matchKind ?? "custom",
@@ -4233,7 +4233,7 @@ var Redactor2 = class {
4233
4233
  const out = [];
4234
4234
  state.seen.set(value, out);
4235
4235
  value.forEach((item, index) => {
4236
- out[index] = this.#redactValue(item, void 0, indexPath(path26, index), depth + 1, state);
4236
+ out[index] = this.#redactValue(item, void 0, indexPath(path27, index), depth + 1, state);
4237
4237
  });
4238
4238
  return out;
4239
4239
  }
@@ -4245,7 +4245,7 @@ var Redactor2 = class {
4245
4245
  out[entryKey] = this.#redactValue(
4246
4246
  entryValue,
4247
4247
  entryKey,
4248
- childPath(path26 === "$" ? "" : path26, entryKey),
4248
+ childPath(path27 === "$" ? "" : path27, entryKey),
4249
4249
  depth + 1,
4250
4250
  state
4251
4251
  );
@@ -4706,14 +4706,14 @@ function uniqueSorted(values) {
4706
4706
  return [...new Set(values)].sort();
4707
4707
  }
4708
4708
  function isWithinDirectory(child, parent) {
4709
- const relative = path15.relative(parent, child);
4710
- return relative === "" || !relative.startsWith("..") && !path15.isAbsolute(relative);
4709
+ const relative = path16.relative(parent, child);
4710
+ return relative === "" || !relative.startsWith("..") && !path16.isAbsolute(relative);
4711
4711
  }
4712
4712
  async function resolveOutputPath(inputPath, output2, force) {
4713
4713
  if (output2 === void 0 || output2.trim() === "") return void 0;
4714
- const inputAbs = path15.resolve(inputPath);
4715
- const outputAbs = path15.resolve(output2.trim());
4716
- const inputDir = path15.dirname(inputAbs);
4714
+ const inputAbs = path16.resolve(inputPath);
4715
+ const outputAbs = path16.resolve(output2.trim());
4716
+ const inputDir = path16.dirname(inputAbs);
4717
4717
  if (!isWithinDirectory(outputAbs, inputDir)) {
4718
4718
  throw new Error("Refusing to write migrated output outside the input directory.");
4719
4719
  }
@@ -4834,7 +4834,7 @@ async function migrateCommand(input3, options = {}) {
4834
4834
  process.exitCode = 1;
4835
4835
  return;
4836
4836
  }
4837
- const inputPath = path15.resolve(input3.trim());
4837
+ const inputPath = path16.resolve(input3.trim());
4838
4838
  const dryRun = options.dryRun === true;
4839
4839
  if (!dryRun && (options.output === void 0 || options.output.trim() === "")) {
4840
4840
  console.error("migrate requires --dry-run or --output <path>.");
@@ -4853,7 +4853,7 @@ async function migrateCommand(input3, options = {}) {
4853
4853
  );
4854
4854
  const result = await buildMigration(inputPath, outputPath);
4855
4855
  if (!dryRun && outputPath !== void 0) {
4856
- await mkdir(path15.dirname(outputPath), { recursive: true });
4856
+ await mkdir(path16.dirname(outputPath), { recursive: true });
4857
4857
  await writeFile(outputPath, result.content, "utf-8");
4858
4858
  }
4859
4859
  printSummary2(result, dryRun);
@@ -5183,23 +5183,23 @@ function evaluatePromptInjection(text, options = {}) {
5183
5183
  }
5184
5184
  return fail(ruleId, `Matched ${evidence.length} injection pattern(s).`, evidence, "warning");
5185
5185
  }
5186
- function validateSchemaField(value, field, path26, evidence) {
5186
+ function validateSchemaField(value, field, path27, evidence) {
5187
5187
  const ruleId = "guardrail.structured-output";
5188
5188
  if (field.type) {
5189
5189
  const actual = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
5190
5190
  if (actual !== field.type) {
5191
- evidence.push({ ruleId, path: path26, preview: `expected ${field.type}, got ${actual}` });
5191
+ evidence.push({ ruleId, path: path27, preview: `expected ${field.type}, got ${actual}` });
5192
5192
  return;
5193
5193
  }
5194
5194
  }
5195
5195
  if (field.enum && !field.enum.some((item) => Object.is(item, value))) {
5196
- evidence.push({ ruleId, path: path26, preview: "value not in enum" });
5196
+ evidence.push({ ruleId, path: path27, preview: "value not in enum" });
5197
5197
  }
5198
5198
  if (field.type === "object" && field.required && value && typeof value === "object" && !Array.isArray(value)) {
5199
5199
  const record = value;
5200
5200
  for (const key of field.required) {
5201
5201
  if (!(key in record)) {
5202
- evidence.push({ ruleId, path: `${path26}.${key}`, preview: "missing required key" });
5202
+ evidence.push({ ruleId, path: `${path27}.${key}`, preview: "missing required key" });
5203
5203
  }
5204
5204
  }
5205
5205
  }
@@ -5526,7 +5526,7 @@ function asConfig(value) {
5526
5526
  }
5527
5527
  async function loadConfig(configPath) {
5528
5528
  if (configPath === void 0) return {};
5529
- const extension = path15.extname(configPath);
5529
+ const extension = path16.extname(configPath);
5530
5530
  if (TS_CONFIG_EXTENSIONS.has(extension)) {
5531
5531
  throw new Error(
5532
5532
  "TypeScript check configs require an explicit precompiled JavaScript config or future --config-loader support."
@@ -5535,7 +5535,7 @@ async function loadConfig(configPath) {
5535
5535
  if (!CONFIG_EXTENSIONS.has(extension)) {
5536
5536
  throw new Error("Unsupported check config extension. Use .json, .js, .mjs, or .cjs.");
5537
5537
  }
5538
- const absolute = path15.resolve(configPath);
5538
+ const absolute = path16.resolve(configPath);
5539
5539
  if (extension === ".json") {
5540
5540
  const raw = await readFile(absolute, "utf-8");
5541
5541
  return asConfig(JSON.parse(raw));
@@ -5711,10 +5711,10 @@ function printHuman(result) {
5711
5711
  console.log(`- ${diagnostic3.code}: ${diagnostic3.message}`);
5712
5712
  }
5713
5713
  for (const finding of result.findings) {
5714
- const path26 = finding.evidence[0]?.path;
5714
+ const path27 = finding.evidence[0]?.path;
5715
5715
  const run = finding.evidence[0]?.runId;
5716
5716
  const runPrefix = run ? `[${run}] ` : "";
5717
- console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${path26 ? ` (${path26})` : ""}`);
5717
+ console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${path27 ? ` (${path27})` : ""}`);
5718
5718
  }
5719
5719
  }
5720
5720
  function readErrorResult(error) {
@@ -5976,7 +5976,7 @@ async function loadSuiteViewerData(options) {
5976
5976
  for (const suiteCase of result.cases) {
5977
5977
  cases.push(await enrichCase(suiteCase, baselinePath));
5978
5978
  }
5979
- const artifactsDir = path15.join(path15.dirname(result.configPath), ".agent-inspect/suite-runs");
5979
+ const artifactsDir = path16.join(path16.dirname(result.configPath), ".agent-inspect/suite-runs");
5980
5980
  return {
5981
5981
  suiteName: result.suiteName,
5982
5982
  configPath: result.configPath,
@@ -6169,19 +6169,19 @@ function serializeWorkspaceManifest(manifest) {
6169
6169
  }
6170
6170
  var INDEX_DIR_NAME = "index";
6171
6171
  function resolveWorkspaceLocation(cwd = process.cwd()) {
6172
- const projectRoot = path15.resolve(cwd);
6173
- const workspaceDir = path15.join(projectRoot, WORKSPACE_DIR_NAME);
6172
+ const projectRoot = path16.resolve(cwd);
6173
+ const workspaceDir = path16.join(projectRoot, WORKSPACE_DIR_NAME);
6174
6174
  return {
6175
6175
  projectRoot,
6176
6176
  workspaceDir,
6177
- manifestPath: path15.join(workspaceDir, WORKSPACE_MANIFEST_FILENAME)
6177
+ manifestPath: path16.join(workspaceDir, WORKSPACE_MANIFEST_FILENAME)
6178
6178
  };
6179
6179
  }
6180
6180
  function resolveInsideWorkspace(workspaceDir, relative) {
6181
- const base = path15.resolve(workspaceDir);
6182
- const resolved = path15.resolve(base, relative);
6183
- const rel = path15.relative(base, resolved);
6184
- if (rel === "" || rel === "." || !rel.startsWith("..") && !path15.isAbsolute(rel)) {
6181
+ const base = path16.resolve(workspaceDir);
6182
+ const resolved = path16.resolve(base, relative);
6183
+ const rel = path16.relative(base, resolved);
6184
+ if (rel === "" || rel === "." || !rel.startsWith("..") && !path16.isAbsolute(rel)) {
6185
6185
  return resolved;
6186
6186
  }
6187
6187
  throw new Error(
@@ -6250,7 +6250,7 @@ async function createWorkspace(options = {}) {
6250
6250
  created = false;
6251
6251
  adopted = true;
6252
6252
  } else {
6253
- const project = options.project?.trim() || path15.basename(location.projectRoot) || "workspace";
6253
+ const project = options.project?.trim() || path16.basename(location.projectRoot) || "workspace";
6254
6254
  const traceDirs = detectedExistingTraces ? ["runs", "."] : ["runs"];
6255
6255
  manifest = createDefaultWorkspaceManifest({
6256
6256
  project,
@@ -6389,7 +6389,7 @@ async function doctorWorkspace(location) {
6389
6389
  const abs = resolveInsideWorkspace(location.workspaceDir, rel);
6390
6390
  for (const file of await listJsonl(abs)) {
6391
6391
  try {
6392
- const s = await stat(path15.join(abs, file));
6392
+ const s = await stat(path16.join(abs, file));
6393
6393
  newestTraceMtime = Math.max(newestTraceMtime, s.mtimeMs);
6394
6394
  } catch {
6395
6395
  checks2.push({ id: "trace-readability", status: "warn", message: `cannot stat ${rel}/${file}` });
@@ -6437,7 +6437,7 @@ async function cleanWorkspace(location, manifest, options = {}) {
6437
6437
  const relPath = `${rel}/${entry}`;
6438
6438
  removed.push(relPath);
6439
6439
  if (!dryRun) {
6440
- await rm(path15.join(abs, entry), { recursive: true, force: true });
6440
+ await rm(path16.join(abs, entry), { recursive: true, force: true });
6441
6441
  }
6442
6442
  }
6443
6443
  }
@@ -6446,7 +6446,7 @@ async function cleanWorkspace(location, manifest, options = {}) {
6446
6446
 
6447
6447
  // packages/viewer/src/workspace-data.ts
6448
6448
  async function loadWorkspaceViewerData(options) {
6449
- const cwd = path15.resolve(options.cwd ?? process.cwd());
6449
+ const cwd = path16.resolve(options.cwd ?? process.cwd());
6450
6450
  const location = resolveWorkspaceLocation(cwd);
6451
6451
  const manifestRead = await readWorkspaceManifestFile(location);
6452
6452
  if (!manifestRead.ok || manifestRead.manifest === void 0) {
@@ -6459,7 +6459,7 @@ async function loadWorkspaceViewerData(options) {
6459
6459
  const runs = [];
6460
6460
  for (const rel of manifestRead.manifest.traceDirs) {
6461
6461
  const traceDir = resolveTraceDir({
6462
- dir: path15.join(location.workspaceDir, rel)
6462
+ dir: path16.join(location.workspaceDir, rel)
6463
6463
  });
6464
6464
  const td = new TraceDirectory({ dir: traceDir });
6465
6465
  const files = await td.list();
@@ -6473,7 +6473,7 @@ async function loadWorkspaceViewerData(options) {
6473
6473
  runId: meta.runId,
6474
6474
  ...meta.name !== void 0 ? { name: meta.name } : {},
6475
6475
  status: meta.status,
6476
- file: path15.basename(meta.filePath)
6476
+ file: path16.basename(meta.filePath)
6477
6477
  });
6478
6478
  }
6479
6479
  }
@@ -6484,8 +6484,8 @@ async function loadWorkspaceViewerData(options) {
6484
6484
  doctor,
6485
6485
  runs,
6486
6486
  bundleDirs: [
6487
- path15.join(location.workspaceDir, manifestRead.manifest.bundlesDir),
6488
- path15.join(location.workspaceDir, manifestRead.manifest.artifactsDir)
6487
+ path16.join(location.workspaceDir, manifestRead.manifest.bundlesDir),
6488
+ path16.join(location.workspaceDir, manifestRead.manifest.artifactsDir)
6489
6489
  ]
6490
6490
  };
6491
6491
  }
@@ -6548,7 +6548,7 @@ function createViewerServer(options = {}) {
6548
6548
  ok: true,
6549
6549
  readOnly: true,
6550
6550
  mode,
6551
- traceDir: path15.resolve(traceDir)
6551
+ traceDir: path16.resolve(traceDir)
6552
6552
  });
6553
6553
  }
6554
6554
  if (pathname === "/api/suite" && mode === "suite") {
@@ -6577,7 +6577,7 @@ function createViewerServer(options = {}) {
6577
6577
  runId: meta.runId,
6578
6578
  name: meta.name,
6579
6579
  status: meta.status,
6580
- file: path15.basename(meta.filePath),
6580
+ file: path16.basename(meta.filePath),
6581
6581
  startedAt: meta.startedAt,
6582
6582
  durationMs: meta.durationMs
6583
6583
  }))
@@ -6694,7 +6694,7 @@ function startViewerServer(options = {}) {
6694
6694
  resolve({
6695
6695
  host,
6696
6696
  port: resolvedPort,
6697
- traceDir: path15.resolve(traceDir),
6697
+ traceDir: path16.resolve(traceDir),
6698
6698
  url: `http://${host}:${resolvedPort}/${modeQuery}`,
6699
6699
  mode
6700
6700
  });
@@ -7065,10 +7065,10 @@ async function evalRun(input3, options = {}) {
7065
7065
  diagnostics: []
7066
7066
  };
7067
7067
  }
7068
- function evidenceForRun(run, path26) {
7069
- return [{ runId: run.runId, ...path26 !== void 0 ? { path: path26 } : {} }];
7068
+ function evidenceForRun(run, path27) {
7069
+ return [{ runId: run.runId, ...path27 !== void 0 ? { path: path27 } : {} }];
7070
7070
  }
7071
- function evidenceForEvent(event, path26) {
7071
+ function evidenceForEvent(event, path27) {
7072
7072
  return [
7073
7073
  {
7074
7074
  runId: event.runId,
@@ -7076,7 +7076,7 @@ function evidenceForEvent(event, path26) {
7076
7076
  ...event.parentId !== void 0 ? { parentId: event.parentId } : {},
7077
7077
  kind: event.kind,
7078
7078
  name: event.name,
7079
- ...path26 !== void 0 ? { path: path26 } : {}
7079
+ ...path27 !== void 0 ? { path: path27 } : {}
7080
7080
  }
7081
7081
  ];
7082
7082
  }
@@ -7234,9 +7234,9 @@ function collectTextFields(nodes, keys, preferredKinds = []) {
7234
7234
  function tokenize(text) {
7235
7235
  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));
7236
7236
  }
7237
- function firstEvidence(fields, run, path26) {
7237
+ function firstEvidence(fields, run, path27) {
7238
7238
  const first = fields[0];
7239
- return first === void 0 ? evidenceForRun(run, path26) : evidenceForEvent(first.node.event, first.path);
7239
+ return first === void 0 ? evidenceForRun(run, path27) : evidenceForEvent(first.node.event, first.path);
7240
7240
  }
7241
7241
  function collectSourceIds(nodes, keys) {
7242
7242
  const wanted = keySet(keys);
@@ -7613,8 +7613,8 @@ function renderEvalMarkdown(result) {
7613
7613
  if (result.findings.length > 0) {
7614
7614
  lines.push("", "## Findings");
7615
7615
  for (const finding of result.findings) {
7616
- const path26 = finding.evidence[0]?.path;
7617
- lines.push(`- ${finding.ruleId}: ${finding.message}${path26 ? ` (${path26})` : ""}`);
7616
+ const path27 = finding.evidence[0]?.path;
7617
+ lines.push(`- ${finding.ruleId}: ${finding.message}${path27 ? ` (${path27})` : ""}`);
7618
7618
  }
7619
7619
  }
7620
7620
  return `${lines.join("\n")}
@@ -7661,7 +7661,7 @@ function asConfig2(value) {
7661
7661
  }
7662
7662
  async function loadConfig2(configPath) {
7663
7663
  if (configPath === void 0) return {};
7664
- const extension = path15.extname(configPath);
7664
+ const extension = path16.extname(configPath);
7665
7665
  if (TS_CONFIG_EXTENSIONS2.has(extension)) {
7666
7666
  throw new Error(
7667
7667
  "TypeScript eval configs require an explicit precompiled JavaScript config or future --config-loader support."
@@ -7670,7 +7670,7 @@ async function loadConfig2(configPath) {
7670
7670
  if (!CONFIG_EXTENSIONS2.has(extension)) {
7671
7671
  throw new Error("Unsupported eval config extension. Use .json, .js, .mjs, or .cjs.");
7672
7672
  }
7673
- const absolute = path15.resolve(configPath);
7673
+ const absolute = path16.resolve(configPath);
7674
7674
  if (extension === ".json") {
7675
7675
  const raw = await readFile(absolute, "utf-8");
7676
7676
  return asConfig2(JSON.parse(raw));
@@ -7807,8 +7807,8 @@ function printHuman2(result) {
7807
7807
  console.log(`- ${diagnostic3.code}: ${diagnostic3.message}`);
7808
7808
  }
7809
7809
  for (const finding of result.findings) {
7810
- const path26 = finding.evidence[0]?.path;
7811
- console.log(`- ${finding.ruleId}: ${finding.message}${path26 ? ` (${path26})` : ""}`);
7810
+ const path27 = finding.evidence[0]?.path;
7811
+ console.log(`- ${finding.ruleId}: ${finding.message}${path27 ? ` (${path27})` : ""}`);
7812
7812
  }
7813
7813
  }
7814
7814
  function readErrorResult2(error) {
@@ -8061,14 +8061,14 @@ function exitCodeFor3(result) {
8061
8061
  return 2;
8062
8062
  }
8063
8063
  function explainFinding(finding, blocksBundle) {
8064
- const path26 = finding.evidence[0]?.path ?? "(unknown path)";
8064
+ const path27 = finding.evidence[0]?.path ?? "(unknown path)";
8065
8065
  const category = finding.category ?? "structure";
8066
8066
  const confidence = finding.confidence ?? "medium";
8067
8067
  const detector = finding.detector ?? finding.ruleId;
8068
8068
  const action = finding.action ?? "review";
8069
8069
  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.";
8070
8070
  return [
8071
- ` Matched: detector=${detector}; path=${path26}; category=${category}`,
8071
+ ` Matched: detector=${detector}; path=${path27}; category=${category}`,
8072
8072
  ` Why: ${finding.message}`,
8073
8073
  ` Confidence: ${confidence}`,
8074
8074
  ` Redaction: ${redactionHint}`,
@@ -8110,9 +8110,9 @@ function printHuman3(result, explain = false) {
8110
8110
  console.log(`- ${diagnostic3.code}: ${diagnostic3.message}`);
8111
8111
  }
8112
8112
  for (const finding of result.findings) {
8113
- const path26 = finding.evidence[0]?.path;
8113
+ const path27 = finding.evidence[0]?.path;
8114
8114
  const taxonomy = finding.category !== void 0 || finding.confidence !== void 0 ? ` [${[finding.category, finding.confidence].filter(Boolean).join("/")}]` : "";
8115
- console.log(`- ${finding.ruleId}: ${finding.message}${path26 ? ` (${path26})` : ""}${taxonomy}`);
8115
+ console.log(`- ${finding.ruleId}: ${finding.message}${path27 ? ` (${path27})` : ""}${taxonomy}`);
8116
8116
  if (explain) {
8117
8117
  const blocks = finding.severity === "error" || finding.status === "fail";
8118
8118
  for (const line of explainFinding(finding, blocks)) {
@@ -8227,7 +8227,7 @@ function messageStartsWithDash(error) {
8227
8227
  return message.startsWith("--");
8228
8228
  }
8229
8229
  function validateReporterArtifactPath(options) {
8230
- const outputDir = path15.resolve(options.outputDir);
8230
+ const outputDir = path16.resolve(options.outputDir);
8231
8231
  const diagnostics = [];
8232
8232
  const rawPath = options.relativePath;
8233
8233
  if (rawPath.length === 0) {
@@ -8247,7 +8247,7 @@ function validateReporterArtifactPath(options) {
8247
8247
  });
8248
8248
  return { ok: false, outputDir, diagnostics };
8249
8249
  }
8250
- if (path15.isAbsolute(rawPath) || path15.win32.isAbsolute(rawPath)) {
8250
+ if (path16.isAbsolute(rawPath) || path16.win32.isAbsolute(rawPath)) {
8251
8251
  diagnostics.push({
8252
8252
  code: "artifact_path_absolute",
8253
8253
  severity: "error",
@@ -8256,7 +8256,7 @@ function validateReporterArtifactPath(options) {
8256
8256
  });
8257
8257
  return { ok: false, outputDir, diagnostics };
8258
8258
  }
8259
- const normalized = path15.posix.normalize(rawPath.replace(/\\/g, "/"));
8259
+ const normalized = path16.posix.normalize(rawPath.replace(/\\/g, "/"));
8260
8260
  const segments = normalized.split("/");
8261
8261
  if (normalized === "." || normalized.startsWith("../") || segments.some((segment) => segment === "..")) {
8262
8262
  diagnostics.push({
@@ -8267,9 +8267,9 @@ function validateReporterArtifactPath(options) {
8267
8267
  });
8268
8268
  return { ok: false, outputDir, diagnostics };
8269
8269
  }
8270
- const absolutePath = path15.resolve(outputDir, normalized);
8271
- const relFromOutput = path15.relative(outputDir, absolutePath);
8272
- if (relFromOutput.length === 0 || relFromOutput.startsWith("..") || path15.isAbsolute(relFromOutput)) {
8270
+ const absolutePath = path16.resolve(outputDir, normalized);
8271
+ const relFromOutput = path16.relative(outputDir, absolutePath);
8272
+ if (relFromOutput.length === 0 || relFromOutput.startsWith("..") || path16.isAbsolute(relFromOutput)) {
8273
8273
  diagnostics.push({
8274
8274
  code: "artifact_path_escape",
8275
8275
  severity: "error",
@@ -8295,7 +8295,7 @@ var EVIDENCE_CI_ARTIFACT_FILES = [
8295
8295
  function createEvidenceCiArtifacts(options) {
8296
8296
  const profile = options.redactionProfile;
8297
8297
  const prefix = options.relativeDir !== void 0 && options.relativeDir.trim() !== "" ? options.relativeDir.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "") : "";
8298
- const join = (name) => prefix === "" ? name : path15.posix.join(prefix, name);
8298
+ const join = (name) => prefix === "" ? name : path16.posix.join(prefix, name);
8299
8299
  const formatFor = (name) => {
8300
8300
  if (name.endsWith(".html")) return "html";
8301
8301
  if (name.endsWith(".jsonl")) return "jsonl";
@@ -8384,8 +8384,8 @@ function renderCheckSection(result) {
8384
8384
  `Diagnostics: ${result.diagnostics.length}`
8385
8385
  ];
8386
8386
  for (const finding of result.findings.slice(0, 10)) {
8387
- const path26 = finding.evidence[0]?.path ?? "(run)";
8388
- lines.push(`- ${finding.ruleId}: ${finding.message} (${path26})`);
8387
+ const path27 = finding.evidence[0]?.path ?? "(run)";
8388
+ lines.push(`- ${finding.ruleId}: ${finding.message} (${path27})`);
8389
8389
  }
8390
8390
  for (const diagnostic3 of result.diagnostics.slice(0, 10)) {
8391
8391
  lines.push(`- ${diagnostic3.code}: ${diagnostic3.message}`);
@@ -8463,8 +8463,8 @@ function renderHtml(trace, check, diff) {
8463
8463
  `;
8464
8464
  }
8465
8465
  async function writeArtifact(outputDir, relativePath, content, files) {
8466
- const outPath = path15.join(outputDir, relativePath);
8467
- await mkdir(path15.dirname(outPath), { recursive: true });
8466
+ const outPath = path16.join(outputDir, relativePath);
8467
+ await mkdir(path16.dirname(outPath), { recursive: true });
8468
8468
  await writeFile(outPath, content, "utf-8");
8469
8469
  files.push(relativePath);
8470
8470
  }
@@ -8493,7 +8493,7 @@ function shouldWriteEvidence(options, status) {
8493
8493
  return status === "unsafe" || status === "regression" || status === "unknown" || status === "warning";
8494
8494
  }
8495
8495
  async function artifactsCommand(target, options = {}, stdin = process.stdin) {
8496
- const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ? path15.resolve(options.outputDir.trim()) : "";
8496
+ const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ? path16.resolve(options.outputDir.trim()) : "";
8497
8497
  if (outputDir === "") {
8498
8498
  console.error("--output-dir is required.");
8499
8499
  process.exitCode = 1;
@@ -8621,8 +8621,8 @@ async function artifactsCommand(target, options = {}, stdin = process.stdin) {
8621
8621
  }
8622
8622
  const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
8623
8623
  if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
8624
- await mkdir(path15.dirname(path15.resolve(summaryTarget)), { recursive: true });
8625
- await appendFile(path15.resolve(summaryTarget), `
8624
+ await mkdir(path16.dirname(path16.resolve(summaryTarget)), { recursive: true });
8625
+ await appendFile(path16.resolve(summaryTarget), `
8626
8626
  ${renderMarkdown(trace, check, diff)}`, "utf-8");
8627
8627
  }
8628
8628
  const manifestFiles = [...files, "manifest.json"].sort((a, b) => a.localeCompare(b));
@@ -8641,10 +8641,10 @@ ${renderMarkdown(trace, check, diff)}`, "utf-8");
8641
8641
  findings: diff?.findings.length ?? 0,
8642
8642
  diagnostics: diff?.diagnostics.length ?? 0
8643
8643
  },
8644
- ...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary: path15.resolve(summaryTarget) } : {},
8644
+ ...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary: path16.resolve(summaryTarget) } : {},
8645
8645
  note: NOTE
8646
8646
  };
8647
- await writeFile(path15.join(outputDir, "manifest.json"), writeJson3(manifest), "utf-8");
8647
+ await writeFile(path16.join(outputDir, "manifest.json"), writeJson3(manifest), "utf-8");
8648
8648
  if (options.json === true) {
8649
8649
  console.log(writeJson3(manifest).trimEnd());
8650
8650
  } else {
@@ -8702,8 +8702,8 @@ async function resolveOutputDir(options, runIds, cwd, format) {
8702
8702
  const location = resolveWorkspaceLocation(cwd);
8703
8703
  const manifest = await readWorkspaceManifestFile(location);
8704
8704
  if (manifest.ok && manifest.manifest) {
8705
- const rel = path15.relative(location.workspaceDir, normalized);
8706
- if (!rel.startsWith("..") && !path15.isAbsolute(rel)) {
8705
+ const rel = path16.relative(location.workspaceDir, normalized);
8706
+ if (!rel.startsWith("..") && !path16.isAbsolute(rel)) {
8707
8707
  return resolveInsideWorkspace(location.workspaceDir, rel);
8708
8708
  }
8709
8709
  }
@@ -8719,7 +8719,7 @@ async function resolveOutputDir(options, runIds, cwd, format) {
8719
8719
  const label = runIds.length === 1 ? sanitizeBundleRunId(runIds[0]) : `multi-${runIds.length}`;
8720
8720
  const base2 = resolveInsideWorkspace(
8721
8721
  location.workspaceDir,
8722
- path15.join(manifest.manifest.bundlesDir, `bundle-${label}-${stamp}`)
8722
+ path16.join(manifest.manifest.bundlesDir, `bundle-${label}-${stamp}`)
8723
8723
  );
8724
8724
  return format === "zip" ? `${base2}.zip` : base2;
8725
8725
  }
@@ -9124,19 +9124,19 @@ async function bundleCommand(runIdArg, options = {}) {
9124
9124
  let sidecarDir = outputDir;
9125
9125
  if (outputDir.toLowerCase().endsWith(".html")) {
9126
9126
  htmlPath = outputDir;
9127
- sidecarDir = path15.dirname(outputDir);
9127
+ sidecarDir = path16.dirname(outputDir);
9128
9128
  } else {
9129
9129
  await mkdir(outputDir, { recursive: true });
9130
- htmlPath = path15.join(outputDir, EVIDENCE_HTML_FILENAME);
9130
+ htmlPath = path16.join(outputDir, EVIDENCE_HTML_FILENAME);
9131
9131
  sidecarDir = outputDir;
9132
9132
  }
9133
9133
  await mkdir(sidecarDir, { recursive: true });
9134
9134
  await writeFile(htmlPath, htmlContent, "utf-8");
9135
- await writeFile(path15.join(sidecarDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
9135
+ await writeFile(path16.join(sidecarDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
9136
9136
  outputPath = htmlPath;
9137
9137
  } else if (format === "zip") {
9138
9138
  const zipPath = outputDir.toLowerCase().endsWith(".zip") ? outputDir : `${outputDir}.zip`;
9139
- const zipParent = path15.dirname(zipPath);
9139
+ const zipParent = path16.dirname(zipPath);
9140
9140
  await mkdir(zipParent, { recursive: true });
9141
9141
  const entries = [
9142
9142
  ...[...packaged.entries()].map(([relativePath, content]) => ({
@@ -9152,10 +9152,10 @@ async function bundleCommand(runIdArg, options = {}) {
9152
9152
  await mkdir(outputDir, { recursive: true });
9153
9153
  for (const [relativePath, content] of packaged.entries()) {
9154
9154
  const outPath = assertBundlePathContained(outputDir, relativePath);
9155
- await mkdir(path15.dirname(outPath), { recursive: true });
9155
+ await mkdir(path16.dirname(outPath), { recursive: true });
9156
9156
  await writeFile(outPath, content, "utf-8");
9157
9157
  }
9158
- await writeFile(path15.join(outputDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
9158
+ await writeFile(path16.join(outputDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
9159
9159
  if (!files.includes(EVIDENCE_MANIFEST_FILENAME)) {
9160
9160
  files.push(EVIDENCE_MANIFEST_FILENAME);
9161
9161
  }
@@ -9201,7 +9201,7 @@ function writeJson5(value) {
9201
9201
  `;
9202
9202
  }
9203
9203
  async function bundleVerifyCommand(targetPath, options = {}) {
9204
- const root = path15.resolve(targetPath.trim() || ".");
9204
+ const root = path16.resolve(targetPath.trim() || ".");
9205
9205
  const result = await verifyEvidenceDirectory(root, {
9206
9206
  unexpectedFiles: options.unexpected ?? "fail"
9207
9207
  });
@@ -9234,6 +9234,141 @@ async function bundleVerifyCommand(targetPath, options = {}) {
9234
9234
  process.exitCode = 1;
9235
9235
  }
9236
9236
  }
9237
+ var CLIENTS = [
9238
+ "cursor",
9239
+ "claude-code",
9240
+ "codex",
9241
+ "gemini"
9242
+ ];
9243
+ function isMcpConfigureClient(value) {
9244
+ return CLIENTS.includes(value);
9245
+ }
9246
+ function buildServerBlock(traceDir) {
9247
+ return {
9248
+ command: "npx",
9249
+ args: ["-y", "@agent-inspect/mcp-server", "--dir", traceDir],
9250
+ env: {
9251
+ AGENT_INSPECT_TRACE_DIR: traceDir,
9252
+ AGENT_INSPECT_MCP_REDACTION_PROFILE: "share"
9253
+ }
9254
+ };
9255
+ }
9256
+ function buildMcpClientConfig(client, traceDir) {
9257
+ const server = buildServerBlock(traceDir);
9258
+ switch (client) {
9259
+ case "cursor":
9260
+ return {
9261
+ mcpServers: {
9262
+ "agent-inspect": server
9263
+ }
9264
+ };
9265
+ case "claude-code":
9266
+ return {
9267
+ mcpServers: {
9268
+ "agent-inspect": server
9269
+ }
9270
+ };
9271
+ case "codex":
9272
+ return {
9273
+ mcp_servers: {
9274
+ "agent-inspect": {
9275
+ command: server.command,
9276
+ args: server.args,
9277
+ env: server.env
9278
+ }
9279
+ }
9280
+ };
9281
+ case "gemini":
9282
+ return {
9283
+ mcpServers: {
9284
+ "agent-inspect": server
9285
+ }
9286
+ };
9287
+ default: {
9288
+ const _exhaustive = client;
9289
+ return _exhaustive;
9290
+ }
9291
+ }
9292
+ }
9293
+ function resolveTargetPath(client, projectLocal) {
9294
+ if (projectLocal) {
9295
+ switch (client) {
9296
+ case "cursor":
9297
+ return path16.join(".cursor", "mcp.json");
9298
+ case "claude-code":
9299
+ return path16.join(".mcp.json");
9300
+ case "codex":
9301
+ return path16.join(".codex", "config.toml.json");
9302
+ case "gemini":
9303
+ return path16.join(".gemini", "settings.json");
9304
+ }
9305
+ }
9306
+ switch (client) {
9307
+ case "cursor":
9308
+ return path16.join("~", ".cursor", "mcp.json");
9309
+ case "claude-code":
9310
+ return path16.join("~", ".claude.json");
9311
+ case "codex":
9312
+ return path16.join("~", ".codex", "config.toml");
9313
+ case "gemini":
9314
+ return path16.join("~", ".gemini", "settings.json");
9315
+ }
9316
+ }
9317
+ async function mcpConfigureCommand(options) {
9318
+ if (!isMcpConfigureClient(options.client)) {
9319
+ throw new Error(
9320
+ `Unsupported client "${String(options.client)}". Use: ${CLIENTS.join(", ")}`
9321
+ );
9322
+ }
9323
+ const traceDir = options.dir?.trim() || ".agent-inspect";
9324
+ const projectLocal = Boolean(options.projectLocal);
9325
+ const write = Boolean(options.write);
9326
+ const yes = Boolean(options.yes);
9327
+ const dryRun = !(write && yes && projectLocal);
9328
+ const config = buildMcpClientConfig(options.client, traceDir);
9329
+ const targetPath = resolveTargetPath(options.client, projectLocal);
9330
+ const notes = [
9331
+ "Read-only MCP server; no network upload; share redaction by default.",
9332
+ "Dry-run by default. Pass --project-local --write --yes to write a project file.",
9333
+ "User-level paths are never auto-written by this command.",
9334
+ "Remove the agent-inspect server block to uninstall."
9335
+ ];
9336
+ let wrote = false;
9337
+ if (!dryRun && projectLocal) {
9338
+ const abs = path16.resolve(targetPath);
9339
+ await mkdir(path16.dirname(abs), { recursive: true });
9340
+ await writeFile(abs, `${JSON.stringify(config, null, 2)}
9341
+ `, "utf8");
9342
+ wrote = true;
9343
+ }
9344
+ const result = {
9345
+ client: options.client,
9346
+ dryRun,
9347
+ wrote,
9348
+ targetPath,
9349
+ config,
9350
+ notes
9351
+ };
9352
+ if (options.json) {
9353
+ process.stdout.write(`${JSON.stringify(result, null, 2)}
9354
+ `);
9355
+ } else {
9356
+ process.stdout.write(
9357
+ [
9358
+ `Client: ${result.client}`,
9359
+ `Mode: ${result.dryRun ? "dry-run" : "write"}`,
9360
+ `Target: ${result.targetPath}`,
9361
+ `Wrote: ${result.wrote}`,
9362
+ "",
9363
+ JSON.stringify(result.config, null, 2),
9364
+ "",
9365
+ ...result.notes.map((note) => `- ${note}`),
9366
+ ""
9367
+ ].join("\n")
9368
+ );
9369
+ }
9370
+ return result;
9371
+ }
9237
9372
  var NOTE2 = "Generated locally by AgentInspect from reporter artifact manifests. Trace contents are not embedded.";
9238
9373
  var MAX_TEXT = 180;
9239
9374
  var FRAMEWORKS = /* @__PURE__ */ new Set(["vitest", "jest", "manual"]);
@@ -9361,23 +9496,23 @@ function readManifestDocument(value) {
9361
9496
  };
9362
9497
  }
9363
9498
  function cwdRelative(filePath) {
9364
- const relative = path15.relative(process.cwd(), path15.resolve(filePath)).replace(/\\/g, "/");
9365
- if (relative === "" || relative.startsWith("../") || path15.isAbsolute(relative)) {
9366
- return path15.basename(filePath);
9499
+ const relative = path16.relative(process.cwd(), path16.resolve(filePath)).replace(/\\/g, "/");
9500
+ if (relative === "" || relative.startsWith("../") || path16.isAbsolute(relative)) {
9501
+ return path16.basename(filePath);
9367
9502
  }
9368
9503
  return relative;
9369
9504
  }
9370
9505
  async function readReporterManifest(filePath) {
9371
- const absolute = path15.resolve(filePath);
9506
+ const absolute = path16.resolve(filePath);
9372
9507
  const raw = await readFile(absolute, "utf-8");
9373
9508
  const document = readManifestDocument(JSON.parse(raw));
9374
9509
  const manifest = document.manifest;
9375
9510
  const results = manifest.results.map((result) => ({
9376
9511
  testId: safeText(result.testId),
9377
9512
  name: safeText(result.name),
9378
- ...result.file === void 0 ? {} : { file: safeText(path15.basename(result.file)) },
9513
+ ...result.file === void 0 ? {} : { file: safeText(path16.basename(result.file)) },
9379
9514
  status: result.status,
9380
- ...result.tracePath === void 0 ? {} : { tracePath: safeText(path15.basename(result.tracePath)) },
9515
+ ...result.tracePath === void 0 ? {} : { tracePath: safeText(path16.basename(result.tracePath)) },
9381
9516
  artifacts: result.artifacts,
9382
9517
  diagnostics: result.diagnostics
9383
9518
  }));
@@ -9516,15 +9651,15 @@ async function ciSummaryCommand(manifestPaths, options = {}) {
9516
9651
  return;
9517
9652
  }
9518
9653
  const markdown = renderMarkdown2(result);
9519
- const outputPath = options.output !== void 0 && options.output.trim() !== "" ? path15.resolve(options.output.trim()) : void 0;
9654
+ const outputPath = options.output !== void 0 && options.output.trim() !== "" ? path16.resolve(options.output.trim()) : void 0;
9520
9655
  if (outputPath !== void 0) {
9521
- await mkdir(path15.dirname(outputPath), { recursive: true });
9656
+ await mkdir(path16.dirname(outputPath), { recursive: true });
9522
9657
  await writeFile(outputPath, markdown, "utf-8");
9523
9658
  }
9524
9659
  const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
9525
9660
  if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
9526
- const summaryPath = path15.resolve(summaryTarget);
9527
- await mkdir(path15.dirname(summaryPath), { recursive: true });
9661
+ const summaryPath = path16.resolve(summaryTarget);
9662
+ await mkdir(path16.dirname(summaryPath), { recursive: true });
9528
9663
  await appendFile(summaryPath, `
9529
9664
  ${markdown}`, "utf-8");
9530
9665
  }
@@ -9672,7 +9807,7 @@ jobs:
9672
9807
  }
9673
9808
  async function planInit(options = {}) {
9674
9809
  const framework = normalizeFramework(options.framework);
9675
- const cwd = path15.resolve(options.cwd ?? process.cwd());
9810
+ const cwd = path16.resolve(options.cwd ?? process.cwd());
9676
9811
  const demoPath = framework === "custom" ? "examples/agent-inspect-demo.mjs" : `examples/agent-inspect-${framework}-demo.mjs`;
9677
9812
  const candidates = [
9678
9813
  { rel: CONFIG_FILE, content: configTemplate(framework) },
@@ -9687,7 +9822,7 @@ async function planInit(options = {}) {
9687
9822
  }
9688
9823
  const files = [];
9689
9824
  for (const candidate of candidates) {
9690
- const abs = path15.join(cwd, candidate.rel);
9825
+ const abs = path16.join(cwd, candidate.rel);
9691
9826
  try {
9692
9827
  await access(abs);
9693
9828
  files.push({
@@ -9708,12 +9843,12 @@ async function writePlannedFiles(plan, cwd, options) {
9708
9843
  if (entry.action === "skip") {
9709
9844
  continue;
9710
9845
  }
9711
- const abs = path15.join(cwd, entry.path);
9846
+ const abs = path16.join(cwd, entry.path);
9712
9847
  if (options.dryRun) {
9713
9848
  written.push(entry.path);
9714
9849
  continue;
9715
9850
  }
9716
- await mkdir(path15.dirname(abs), { recursive: true });
9851
+ await mkdir(path16.dirname(abs), { recursive: true });
9717
9852
  const content = entry.path === CONFIG_FILE ? configTemplate(plan.framework) : entry.path === GITKEEP ? "" : entry.path.endsWith(".yml") ? githubWorkflowTemplate() : demoTemplate(plan.framework);
9718
9853
  await writeFile(abs, content, "utf-8");
9719
9854
  written.push(entry.path);
@@ -9721,7 +9856,7 @@ async function writePlannedFiles(plan, cwd, options) {
9721
9856
  return written;
9722
9857
  }
9723
9858
  async function initCommand(options = {}) {
9724
- const cwd = path15.resolve(options.cwd ?? process.cwd());
9859
+ const cwd = path16.resolve(options.cwd ?? process.cwd());
9725
9860
  try {
9726
9861
  const plan = await planInit({ ...options, cwd });
9727
9862
  const toWrite = plan.files.filter((file) => file.action === "create").map((f) => f.path);
@@ -9812,7 +9947,7 @@ function envCheck(name, optional = true) {
9812
9947
  };
9813
9948
  }
9814
9949
  async function traceDirWritable(traceDir) {
9815
- const resolved = path15.resolve(traceDir);
9950
+ const resolved = path16.resolve(traceDir);
9816
9951
  try {
9817
9952
  await mkdir(resolved, { recursive: true });
9818
9953
  await access(resolved, constants.W_OK);
@@ -9833,10 +9968,10 @@ async function traceDirWritable(traceDir) {
9833
9968
  }
9834
9969
  }
9835
9970
  function readPackageVersionNearEntry(entryPath, packageName) {
9836
- let dir = path15.dirname(path15.resolve(entryPath));
9837
- const { root } = path15.parse(dir);
9971
+ let dir = path16.dirname(path16.resolve(entryPath));
9972
+ const { root } = path16.parse(dir);
9838
9973
  while (true) {
9839
- const candidate = path15.join(dir, "package.json");
9974
+ const candidate = path16.join(dir, "package.json");
9840
9975
  if (existsSync(candidate)) {
9841
9976
  try {
9842
9977
  const pkg = JSON.parse(readFileSync(candidate, "utf8"));
@@ -9847,14 +9982,14 @@ function readPackageVersionNearEntry(entryPath, packageName) {
9847
9982
  }
9848
9983
  }
9849
9984
  if (dir === root) break;
9850
- const parent = path15.dirname(dir);
9985
+ const parent = path16.dirname(dir);
9851
9986
  if (parent === dir) break;
9852
9987
  dir = parent;
9853
9988
  }
9854
9989
  return void 0;
9855
9990
  }
9856
9991
  function resolveInstalledPackage(cwd, name) {
9857
- const require2 = createRequire(path15.join(cwd, "package.json"));
9992
+ const require2 = createRequire(path16.join(cwd, "package.json"));
9858
9993
  try {
9859
9994
  const entry = require2.resolve(name);
9860
9995
  let version2;
@@ -9952,7 +10087,7 @@ function versionMismatchCheck(cwd) {
9952
10087
  };
9953
10088
  }
9954
10089
  async function runDoctorChecks(options = {}) {
9955
- const cwd = path15.resolve(options.cwd ?? process2.cwd());
10090
+ const cwd = path16.resolve(options.cwd ?? process2.cwd());
9956
10091
  const traceDir = options.traceDir?.trim() || process2.env.AGENT_INSPECT_TRACE_DIR?.trim() || ".agent-inspect";
9957
10092
  const checks2 = [
9958
10093
  nodeVersionCheck(),
@@ -10192,7 +10327,7 @@ function parsePluginManifest(input3) {
10192
10327
  };
10193
10328
  }
10194
10329
  async function readPluginManifestFile(packageDir) {
10195
- const manifestPath = path15.join(packageDir, PLUGIN_MANIFEST_FILENAME);
10330
+ const manifestPath = path16.join(packageDir, PLUGIN_MANIFEST_FILENAME);
10196
10331
  try {
10197
10332
  const raw = await readFile(manifestPath, "utf8");
10198
10333
  const parsed = parsePluginManifest(JSON.parse(raw));
@@ -10266,7 +10401,7 @@ function createTraceDirectoryIndexer() {
10266
10401
  // packages/cli/src/plugins.ts
10267
10402
  async function readPackageName(packageDir) {
10268
10403
  try {
10269
- const raw = await readFile(path15.join(packageDir, "package.json"), "utf8");
10404
+ const raw = await readFile(path16.join(packageDir, "package.json"), "utf8");
10270
10405
  const parsed = JSON.parse(raw);
10271
10406
  return typeof parsed.name === "string" ? parsed.name : void 0;
10272
10407
  } catch {
@@ -10274,7 +10409,7 @@ async function readPackageName(packageDir) {
10274
10409
  }
10275
10410
  }
10276
10411
  async function discoverPlugins(cwd = process.cwd()) {
10277
- const nodeModules = path15.join(cwd, "node_modules");
10412
+ const nodeModules = path16.join(cwd, "node_modules");
10278
10413
  const found = [];
10279
10414
  let entries;
10280
10415
  try {
@@ -10285,7 +10420,7 @@ async function discoverPlugins(cwd = process.cwd()) {
10285
10420
  for (const entry of entries.sort()) {
10286
10421
  if (entry.startsWith("@")) continue;
10287
10422
  if (!isPluginPackageName(entry)) continue;
10288
- const packageDir = path15.join(nodeModules, entry);
10423
+ const packageDir = path16.join(nodeModules, entry);
10289
10424
  const manifestRead = await readPluginManifestFile(packageDir);
10290
10425
  found.push({
10291
10426
  packageName: entry,
@@ -10298,7 +10433,7 @@ async function discoverPlugins(cwd = process.cwd()) {
10298
10433
  return found;
10299
10434
  }
10300
10435
  async function validatePluginPackage(packageRef, cwd = process.cwd()) {
10301
- const packageDir = path15.isAbsolute(packageRef) ? packageRef : path15.join(cwd, "node_modules", packageRef);
10436
+ const packageDir = path16.isAbsolute(packageRef) ? packageRef : path16.join(cwd, "node_modules", packageRef);
10302
10437
  const packageName = await readPackageName(packageDir) ?? packageRef;
10303
10438
  const errors = [];
10304
10439
  const warnings = [];
@@ -10374,7 +10509,7 @@ async function pluginsValidateCommand(packageRef, cwd) {
10374
10509
  }
10375
10510
  var INDEX_FILENAME = ".agent-inspect-index.json";
10376
10511
  function traceIndexPath(traceDir) {
10377
- return path15.join(traceDir, INDEX_FILENAME);
10512
+ return path16.join(traceDir, INDEX_FILENAME);
10378
10513
  }
10379
10514
  function parseMaxEntries(raw) {
10380
10515
  if (raw === void 0 || raw.trim() === "") return void 0;
@@ -10487,7 +10622,7 @@ function isModuleNotFound4(e) {
10487
10622
  }
10488
10623
  async function loadIndexSqlite() {
10489
10624
  try {
10490
- return await import('./src-YFN3Q3GP.mjs');
10625
+ return await import('./src-G7PM24W2.mjs');
10491
10626
  } catch (e) {
10492
10627
  if (isModuleNotFound4(e)) {
10493
10628
  console.error(
@@ -10517,7 +10652,7 @@ async function newestTraceMtimeMs2(traceDir) {
10517
10652
  for (const file of files) {
10518
10653
  if (!file.endsWith(".jsonl")) continue;
10519
10654
  try {
10520
- const s = await stat(path15.join(traceDir, file));
10655
+ const s = await stat(path16.join(traceDir, file));
10521
10656
  if (s.mtimeMs > newest) newest = s.mtimeMs;
10522
10657
  } catch {
10523
10658
  }
@@ -10769,11 +10904,11 @@ function printJson5(value) {
10769
10904
  console.log(JSON.stringify(value, null, 2));
10770
10905
  }
10771
10906
  function resolveCwd(options) {
10772
- return path15.resolve(options.cwd ?? process.cwd());
10907
+ return path16.resolve(options.cwd ?? process.cwd());
10773
10908
  }
10774
10909
  async function suiteInitCommand(options = {}) {
10775
10910
  const cwd = resolveCwd(options);
10776
- const configPath = path15.join(cwd, DEFAULT_CONFIG_FILENAME);
10911
+ const configPath = path16.join(cwd, DEFAULT_CONFIG_FILENAME);
10777
10912
  const template = options.template?.trim();
10778
10913
  const suiteConfig = template !== void 0 && template !== "" ? resolveSuiteTemplate(template) : defaultSuiteConfigTemplate();
10779
10914
  if (options.dryRun) {
@@ -10892,13 +11027,13 @@ async function suiteListCommand(options = {}) {
10892
11027
  }
10893
11028
  async function writeSuiteArtifact(result, configOutputDir, options) {
10894
11029
  const cwd = resolveCwd(options);
10895
- const outputDir = path15.resolve(
11030
+ const outputDir = path16.resolve(
10896
11031
  cwd,
10897
11032
  options.output ?? configOutputDir ?? DEFAULT_SUITE_ARTIFACTS_DIR
10898
11033
  );
10899
11034
  await mkdir(outputDir, { recursive: true });
10900
11035
  const stamp = result.startedAt.replace(/[:.]/g, "-");
10901
- const filePath = path15.join(outputDir, `${result.suiteName}-${stamp}.json`);
11036
+ const filePath = path16.join(outputDir, `${result.suiteName}-${stamp}.json`);
10902
11037
  await writeFile(filePath, `${JSON.stringify(result, null, 2)}
10903
11038
  `, "utf-8");
10904
11039
  return filePath;
@@ -10956,7 +11091,7 @@ async function loadSuiteResultFromInput(options) {
10956
11091
  if (options.input === void 0 || options.input.trim() === "") {
10957
11092
  throw new Error("Pass --input <suite-run.json> from a prior suite run.");
10958
11093
  }
10959
- const inputPath = path15.resolve(cwd, options.input.trim());
11094
+ const inputPath = path16.resolve(cwd, options.input.trim());
10960
11095
  const raw = await readFile(inputPath, "utf-8");
10961
11096
  return JSON.parse(raw);
10962
11097
  }
@@ -10990,9 +11125,9 @@ function normalizeMetrics(raw) {
10990
11125
  }
10991
11126
  async function writeArtifacts(result, outputDir) {
10992
11127
  await mkdir(outputDir, { recursive: true });
10993
- const jsonPath = path15.join(outputDir, "cohort-results.json");
10994
- const markdownPath = path15.join(outputDir, "cohort-summary.md");
10995
- const htmlPath = path15.join(outputDir, "cohort-report.html");
11128
+ const jsonPath = path16.join(outputDir, "cohort-results.json");
11129
+ const markdownPath = path16.join(outputDir, "cohort-summary.md");
11130
+ const htmlPath = path16.join(outputDir, "cohort-report.html");
10996
11131
  await writeFile(jsonPath, `${renderCohortReport(result, { format: "json" })}
10997
11132
  `, "utf-8");
10998
11133
  await writeFile(
@@ -11020,7 +11155,7 @@ async function cohortCommand(options = {}) {
11020
11155
  const format = options.format ?? (options.json ? "json" : "markdown");
11021
11156
  let artifacts;
11022
11157
  if (options.output !== void 0 && options.output.trim() !== "") {
11023
- artifacts = await writeArtifacts(result, path15.resolve(options.output.trim()));
11158
+ artifacts = await writeArtifacts(result, path16.resolve(options.output.trim()));
11024
11159
  }
11025
11160
  if (options.json || format === "json") {
11026
11161
  console.log(
@@ -11090,11 +11225,11 @@ function parseDuration2(value) {
11090
11225
  async function writeArtifacts2(result, outputDir) {
11091
11226
  await mkdir(outputDir, { recursive: true });
11092
11227
  const paths = {
11093
- jsonPath: path15.join(outputDir, "gate-results.json"),
11094
- markdownPath: path15.join(outputDir, "gate-summary.md"),
11095
- htmlPath: path15.join(outputDir, "gate-report.html"),
11096
- junitPath: path15.join(outputDir, "junit.xml"),
11097
- githubPath: path15.join(outputDir, "github-step-summary.md")
11228
+ jsonPath: path16.join(outputDir, "gate-results.json"),
11229
+ markdownPath: path16.join(outputDir, "gate-summary.md"),
11230
+ htmlPath: path16.join(outputDir, "gate-report.html"),
11231
+ junitPath: path16.join(outputDir, "junit.xml"),
11232
+ githubPath: path16.join(outputDir, "github-step-summary.md")
11098
11233
  };
11099
11234
  await writeFile(
11100
11235
  paths.jsonPath,
@@ -11162,7 +11297,7 @@ async function gateCommand(options = {}) {
11162
11297
  const result = await runGate(runs, gateOptions);
11163
11298
  let artifacts;
11164
11299
  if (options.output !== void 0 && options.output.trim() !== "") {
11165
- artifacts = await writeArtifacts2(result, path15.resolve(options.output.trim()));
11300
+ artifacts = await writeArtifacts2(result, path16.resolve(options.output.trim()));
11166
11301
  }
11167
11302
  if (options.json || format === "json") {
11168
11303
  console.log(JSON.stringify({ ...result, artifacts: artifacts ?? null }, null, 2));
@@ -11694,6 +11829,20 @@ function createCliProgram() {
11694
11829
  ).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) => {
11695
11830
  runCommand(() => cohortCommand(opts));
11696
11831
  });
11832
+ const mcpCmd = program.command("mcp").description("Configure local coding-agent MCP clients (read-only; dry-run by default)");
11833
+ mcpCmd.command("configure").description("Print or write MCP client config for Cursor/Claude/Codex/Gemini").requiredOption(
11834
+ "--client <name>",
11835
+ "cursor | claude-code | codex | gemini"
11836
+ ).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) => {
11837
+ runCommand(async () => {
11838
+ if (!isMcpConfigureClient(opts.client)) {
11839
+ throw new Error(
11840
+ `Unsupported --client "${opts.client}". Use: cursor, claude-code, codex, gemini`
11841
+ );
11842
+ }
11843
+ await mcpConfigureCommand({ ...opts, client: opts.client });
11844
+ });
11845
+ });
11697
11846
  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(
11698
11847
  "--require-observation <name>",
11699
11848
  "required passed observation (repeatable or comma-separated)"
@@ -11710,9 +11859,9 @@ function isPrimaryModule() {
11710
11859
  if (!entry) return false;
11711
11860
  const selfPath = fileURLToPath(import.meta.url);
11712
11861
  try {
11713
- return realpathSync(path15.resolve(entry)) === realpathSync(path15.resolve(selfPath));
11862
+ return realpathSync(path16.resolve(entry)) === realpathSync(path16.resolve(selfPath));
11714
11863
  } catch {
11715
- return path15.resolve(entry) === path15.resolve(selfPath);
11864
+ return path16.resolve(entry) === path16.resolve(selfPath);
11716
11865
  }
11717
11866
  }
11718
11867
  if (isPrimaryModule()) {