agent-inspect 6.16.2 → 6.17.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 path30 = require('path');
7
+ var path32 = require('path');
8
8
  var async_hooks = require('async_hooks');
9
9
  var process3 = require('process');
10
10
  var tty = require('tty');
@@ -14,13 +14,14 @@ var url = require('url');
14
14
  var module$1 = require('module');
15
15
  var commander = require('commander');
16
16
  var http = require('http');
17
+ var child_process = require('child_process');
17
18
 
18
19
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
19
20
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
20
21
 
21
22
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
22
23
  var os__default = /*#__PURE__*/_interopDefault(os);
23
- var path30__default = /*#__PURE__*/_interopDefault(path30);
24
+ var path32__default = /*#__PURE__*/_interopDefault(path32);
24
25
  var process3__default = /*#__PURE__*/_interopDefault(process3);
25
26
  var tty__default = /*#__PURE__*/_interopDefault(tty);
26
27
 
@@ -864,7 +865,7 @@ function getDefaultTraceDir() {
864
865
  if (typeof home !== "string" || home.trim() === "") {
865
866
  return FALLBACK_TRACE_DIR;
866
867
  }
867
- return path30__default.default.join(home, DEFAULT_TRACE_DIR_NAME, RUNS_DIR_NAME);
868
+ return path32__default.default.join(home, DEFAULT_TRACE_DIR_NAME, RUNS_DIR_NAME);
868
869
  } catch {
869
870
  return FALLBACK_TRACE_DIR;
870
871
  }
@@ -872,11 +873,11 @@ function getDefaultTraceDir() {
872
873
  function getTraceFilePath(runId, traceDir) {
873
874
  const baseDir = traceDir ?? getDefaultTraceDir();
874
875
  let safeId = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "run_unknown";
875
- safeId = path30__default.default.basename(safeId);
876
+ safeId = path32__default.default.basename(safeId);
876
877
  if (safeId === "" || safeId === "." || safeId === "..") {
877
878
  safeId = "run_unknown";
878
879
  }
879
- return path30__default.default.join(baseDir, `${safeId}.jsonl`);
880
+ return path32__default.default.join(baseDir, `${safeId}.jsonl`);
880
881
  }
881
882
  function formatError(error) {
882
883
  if (error instanceof Error) {
@@ -933,7 +934,7 @@ var init_utils = __esm({
933
934
  init_duration();
934
935
  DEFAULT_TRACE_DIR_NAME = ".agent-inspect";
935
936
  RUNS_DIR_NAME = "runs";
936
- FALLBACK_TRACE_DIR = path30__default.default.join(
937
+ FALLBACK_TRACE_DIR = path32__default.default.join(
937
938
  os__default.default.tmpdir(),
938
939
  "agent-inspect",
939
940
  RUNS_DIR_NAME
@@ -1899,7 +1900,7 @@ var init_trace_directory = __esm({
1899
1900
  this.#dir = resolveTraceDir(options);
1900
1901
  }
1901
1902
  getPath(filename) {
1902
- return filename ? path30__default.default.join(this.#dir, filename) : this.#dir;
1903
+ return filename ? path32__default.default.join(this.#dir, filename) : this.#dir;
1903
1904
  }
1904
1905
  async list() {
1905
1906
  try {
@@ -1928,7 +1929,7 @@ function parseIsoToMs2(value) {
1928
1929
  }
1929
1930
  async function extractMetadata(filePath, _quickScan) {
1930
1931
  const stats = await promises.stat(filePath);
1931
- let runIdFromFile = path30__default.default.basename(filePath);
1932
+ let runIdFromFile = path32__default.default.basename(filePath);
1932
1933
  if (runIdFromFile.endsWith(".jsonl")) {
1933
1934
  runIdFromFile = runIdFromFile.slice(0, -".jsonl".length);
1934
1935
  }
@@ -3781,12 +3782,12 @@ function buildCriticalPath(runs, handoffs) {
3781
3782
  handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.from)
3782
3783
  );
3783
3784
  const ordered = [...runs].sort(compareRuns);
3784
- const path41 = [];
3785
+ const path43 = [];
3785
3786
  const visited = /* @__PURE__ */ new Set();
3786
3787
  const pushRun = (run, confidence, source) => {
3787
3788
  if (visited.has(run.runId)) return;
3788
3789
  visited.add(run.runId);
3789
- path41.push({
3790
+ path43.push({
3790
3791
  runId: run.runId,
3791
3792
  name: run.name,
3792
3793
  startedAt: run.startedAt,
@@ -3811,7 +3812,7 @@ function buildCriticalPath(runs, handoffs) {
3811
3812
  const confidence = explicitTargets.has(run.runId) || explicitSources.has(run.runId) ? "explicit" : "correlated";
3812
3813
  pushRun(run, confidence, confidence === "explicit" ? "manual" : "inferred");
3813
3814
  }
3814
- return path41;
3815
+ return path43;
3815
3816
  }
3816
3817
  function metaRunIdMatches(run, token, runById) {
3817
3818
  const meta2 = extractSessionWorkflowMetadata(run.metadata);
@@ -4140,7 +4141,7 @@ var init_summary = __esm({
4140
4141
  });
4141
4142
  function sanitizeBundleRunId(runId) {
4142
4143
  let safe = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "run_unknown";
4143
- safe = path30__default.default.basename(safe);
4144
+ safe = path32__default.default.basename(safe);
4144
4145
  safe = safe.replace(/[^a-zA-Z0-9._-]+/g, "_");
4145
4146
  if (safe === "" || safe === "." || safe === "..") {
4146
4147
  safe = "run_unknown";
@@ -4150,12 +4151,12 @@ function sanitizeBundleRunId(runId) {
4150
4151
  function bundleRunAssetRelativePath(runId, extension) {
4151
4152
  const safe = sanitizeBundleRunId(runId);
4152
4153
  const ext = extension.startsWith(".") ? extension : `.${extension}`;
4153
- return path30__default.default.posix.join("assets", "runs", `${safe}${ext}`);
4154
+ return path32__default.default.posix.join("assets", "runs", `${safe}${ext}`);
4154
4155
  }
4155
4156
  function assertBundlePathContained(outputDir, relativePath) {
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)) {
4157
+ const base = path32__default.default.resolve(outputDir);
4158
+ const resolved = path32__default.default.resolve(base, relativePath);
4159
+ if (resolved !== base && !resolved.startsWith(base + path32__default.default.sep)) {
4159
4160
  throw new Error(`Bundle path escapes output directory: ${relativePath}`);
4160
4161
  }
4161
4162
  return resolved;
@@ -4165,7 +4166,7 @@ function normalizeBundleOutputPath(out, options) {
4165
4166
  if (trimmed === "") {
4166
4167
  throw new Error("--out requires a non-empty path.");
4167
4168
  }
4168
- const resolved = path30__default.default.resolve(trimmed);
4169
+ const resolved = path32__default.default.resolve(trimmed);
4169
4170
  if (options?.preserveZipExtension !== true && resolved.toLowerCase().endsWith(".zip")) {
4170
4171
  return resolved.slice(0, -4);
4171
4172
  }
@@ -4174,7 +4175,7 @@ function normalizeBundleOutputPath(out, options) {
4174
4175
  function defaultBundleOutputPath(runIds) {
4175
4176
  const label = runIds.length === 1 ? sanitizeBundleRunId(runIds[0]) : `multi-${runIds.length}`;
4176
4177
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4177
- return path30__default.default.resolve(`agent-inspect-bundle-${label}-${stamp}`);
4178
+ return path32__default.default.resolve(`agent-inspect-bundle-${label}-${stamp}`);
4178
4179
  }
4179
4180
  var init_paths = __esm({
4180
4181
  "packages/core/src/bundle/paths.ts"() {
@@ -4237,7 +4238,7 @@ function assertEvidenceRelativePath(relativePath) {
4237
4238
  throw new Error("Evidence file path must be a non-empty relative path.");
4238
4239
  }
4239
4240
  const trimmed = relativePath.trim().replaceAll("\\", "/");
4240
- if (path30__default.default.isAbsolute(trimmed) || trimmed.startsWith("/")) {
4241
+ if (path32__default.default.isAbsolute(trimmed) || trimmed.startsWith("/")) {
4241
4242
  throw new Error(`Evidence file path must be relative: ${relativePath}`);
4242
4243
  }
4243
4244
  const parts = trimmed.split("/").filter((part) => part !== "");
@@ -5104,13 +5105,13 @@ function pairSteps(left, right) {
5104
5105
  return pairs;
5105
5106
  }
5106
5107
  function compareLeafSteps(L, R, segments, opts, out) {
5107
- const path41 = buildPath(segments);
5108
+ const path43 = buildPath(segments);
5108
5109
  if (L.name !== R.name) {
5109
5110
  out.push({
5110
5111
  kind: "structure",
5111
5112
  severity: "warning",
5112
5113
  message: "Step name differs",
5113
- path: path41,
5114
+ path: path43,
5114
5115
  left: L.name,
5115
5116
  right: R.name
5116
5117
  });
@@ -5120,7 +5121,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5120
5121
  kind: "step-type",
5121
5122
  severity: "warning",
5122
5123
  message: "Step type differs",
5123
- path: path41,
5124
+ path: path43,
5124
5125
  left: L.type,
5125
5126
  right: R.type
5126
5127
  });
@@ -5130,7 +5131,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5130
5131
  kind: "step-status",
5131
5132
  severity: "warning",
5132
5133
  message: "Step status differs",
5133
- path: path41,
5134
+ path: path43,
5134
5135
  left: L.status,
5135
5136
  right: R.status
5136
5137
  });
@@ -5142,7 +5143,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5142
5143
  kind: "error",
5143
5144
  severity: "error",
5144
5145
  message: "Step error message differs",
5145
- path: path41,
5146
+ path: path43,
5146
5147
  left: le || void 0,
5147
5148
  right: re || void 0
5148
5149
  });
@@ -5160,7 +5161,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5160
5161
  kind: "duration",
5161
5162
  severity: "info",
5162
5163
  message: "Step duration differs",
5163
- path: path41,
5164
+ path: path43,
5164
5165
  left: ld,
5165
5166
  right: rd
5166
5167
  });
@@ -5173,7 +5174,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5173
5174
  kind: "metadata",
5174
5175
  severity: "info",
5175
5176
  message: "Step metadata differs",
5176
- path: path41,
5177
+ path: path43,
5177
5178
  left: L.metadata,
5178
5179
  right: R.metadata
5179
5180
  });
@@ -5185,7 +5186,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
5185
5186
  kind: "output",
5186
5187
  severity: "info",
5187
5188
  message: "Output preview differs",
5188
- path: path41,
5189
+ path: path43,
5189
5190
  left: L.outputPreview,
5190
5191
  right: R.outputPreview
5191
5192
  });
@@ -5352,11 +5353,11 @@ var init_engine = __esm({
5352
5353
  });
5353
5354
 
5354
5355
  // packages/core/src/diff/renderer.ts
5355
- function formatPath(path41) {
5356
- if (path41 === void 0 || path41.path.length === 0) {
5356
+ function formatPath(path43) {
5357
+ if (path43 === void 0 || path43.path.length === 0) {
5357
5358
  return "(run)";
5358
5359
  }
5359
- return path41.path.map((s) => s.name).join(" > ");
5360
+ return path43.path.map((s) => s.name).join(" > ");
5360
5361
  }
5361
5362
  function formatValue(v, verbose) {
5362
5363
  if (v === void 0) return "(undefined)";
@@ -5736,11 +5737,11 @@ async function listFilesRecursive(root) {
5736
5737
  async function walk(dir) {
5737
5738
  const entries = await promises.readdir(dir, { withFileTypes: true });
5738
5739
  for (const entry of entries) {
5739
- const abs = path30__default.default.join(dir, entry.name);
5740
+ const abs = path32__default.default.join(dir, entry.name);
5740
5741
  if (entry.isDirectory()) {
5741
5742
  await walk(abs);
5742
5743
  } else if (entry.isFile()) {
5743
- const rel = path30__default.default.relative(root, abs).split(path30__default.default.sep).join("/");
5744
+ const rel = path32__default.default.relative(root, abs).split(path32__default.default.sep).join("/");
5744
5745
  out.push(rel);
5745
5746
  }
5746
5747
  }
@@ -5750,7 +5751,7 @@ async function listFilesRecursive(root) {
5750
5751
  }
5751
5752
  async function verifyEvidenceDirectory(rootPath, options = {}) {
5752
5753
  const unexpectedMode = options.unexpectedFiles ?? "fail";
5753
- const root = path30__default.default.resolve(rootPath);
5754
+ const root = path32__default.default.resolve(rootPath);
5754
5755
  const issues = [];
5755
5756
  let rootStat;
5756
5757
  try {
@@ -5780,7 +5781,7 @@ async function verifyEvidenceDirectory(rootPath, options = {}) {
5780
5781
  checkedFiles: 0
5781
5782
  };
5782
5783
  }
5783
- const manifestPath = path30__default.default.join(root, EVIDENCE_MANIFEST_FILENAME);
5784
+ const manifestPath = path32__default.default.join(root, EVIDENCE_MANIFEST_FILENAME);
5784
5785
  let manifestText;
5785
5786
  try {
5786
5787
  manifestText = await promises.readFile(manifestPath, "utf-8");
@@ -5866,7 +5867,7 @@ async function verifyEvidenceDirectory(rootPath, options = {}) {
5866
5867
  continue;
5867
5868
  }
5868
5869
  listed.add(rel);
5869
- const abs = path30__default.default.join(root, ...rel.split("/"));
5870
+ const abs = path32__default.default.join(root, ...rel.split("/"));
5870
5871
  let bytes;
5871
5872
  try {
5872
5873
  bytes = await promises.readFile(abs);
@@ -6181,7 +6182,7 @@ function normalizeSuiteConfig(value) {
6181
6182
  }
6182
6183
  async function validateSuiteConfig(config, options) {
6183
6184
  const diagnostics = [];
6184
- const tracesDir = path30__default.default.resolve(options.configDir, config.traces);
6185
+ const tracesDir = path32__default.default.resolve(options.configDir, config.traces);
6185
6186
  try {
6186
6187
  await promises.access(tracesDir);
6187
6188
  } catch {
@@ -6191,7 +6192,7 @@ async function validateSuiteConfig(config, options) {
6191
6192
  }
6192
6193
  for (const suiteCase of config.cases) {
6193
6194
  if (suiteCase.input !== void 0) {
6194
- const inputPath = path30__default.default.resolve(options.configDir, suiteCase.input);
6195
+ const inputPath = path32__default.default.resolve(options.configDir, suiteCase.input);
6195
6196
  try {
6196
6197
  await promises.access(inputPath);
6197
6198
  } catch {
@@ -6224,12 +6225,12 @@ async function fileExists(filePath) {
6224
6225
  }
6225
6226
  }
6226
6227
  async function resolveSuiteConfigPath(options = {}) {
6227
- const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
6228
+ const cwd = path32__default.default.resolve(options.cwd ?? process.cwd());
6228
6229
  if (options.configPath !== void 0 && options.configPath.trim() !== "") {
6229
- return path30__default.default.resolve(cwd, options.configPath.trim());
6230
+ return path32__default.default.resolve(cwd, options.configPath.trim());
6230
6231
  }
6231
6232
  for (const name of DEFAULT_SUITE_CONFIG_NAMES) {
6232
- const candidate = path30__default.default.join(cwd, name);
6233
+ const candidate = path32__default.default.join(cwd, name);
6233
6234
  if (await fileExists(candidate)) return candidate;
6234
6235
  }
6235
6236
  throw new Error(
@@ -6246,7 +6247,7 @@ async function loadSuiteConfig(options = {}) {
6246
6247
  diagnostics: [diagnostic2("AI_SUITE_CONFIG_LOAD_FAILED", message)]
6247
6248
  });
6248
6249
  }
6249
- const extension = path30__default.default.extname(configPath);
6250
+ const extension = path32__default.default.extname(configPath);
6250
6251
  if (TS_CONFIG_EXTENSIONS.has(extension)) {
6251
6252
  const message = "TypeScript suite configs require an explicit precompiled JavaScript config or future --config-loader support.";
6252
6253
  throw Object.assign(new Error(message), {
@@ -6271,7 +6272,7 @@ async function loadSuiteConfig(options = {}) {
6271
6272
  return {
6272
6273
  config,
6273
6274
  configPath,
6274
- configDir: path30__default.default.dirname(configPath)
6275
+ configDir: path32__default.default.dirname(configPath)
6275
6276
  };
6276
6277
  } catch (error) {
6277
6278
  const message = error instanceof Error ? error.message : String(error);
@@ -6321,7 +6322,7 @@ async function exists(filePath) {
6321
6322
  }
6322
6323
  async function resolveSuiteCaseTrace(suiteCase, options) {
6323
6324
  if (suiteCase.trace !== void 0) {
6324
- const tracePath = path30__default.default.resolve(options.configDir, suiteCase.trace);
6325
+ const tracePath = path32__default.default.resolve(options.configDir, suiteCase.trace);
6325
6326
  if (await exists(tracePath)) {
6326
6327
  return { caseId: suiteCase.id, tracePath, missing: false };
6327
6328
  }
@@ -6337,7 +6338,7 @@ async function resolveSuiteCaseTrace(suiteCase, options) {
6337
6338
  if (await exists(directPath)) {
6338
6339
  return { caseId: suiteCase.id, tracePath: directPath, runId: runKey, missing: false };
6339
6340
  }
6340
- const nestedPath = path30__default.default.join(options.tracesDir, `${path30__default.default.basename(runKey)}.jsonl`);
6341
+ const nestedPath = path32__default.default.join(options.tracesDir, `${path32__default.default.basename(runKey)}.jsonl`);
6341
6342
  if (await exists(nestedPath)) {
6342
6343
  return { caseId: suiteCase.id, tracePath: nestedPath, runId: runKey, missing: false };
6343
6344
  }
@@ -7055,7 +7056,7 @@ function stripPrefix(name, prefixes) {
7055
7056
  }
7056
7057
  return name;
7057
7058
  }
7058
- function eventEvidence(event, path41) {
7059
+ function eventEvidence(event, path43) {
7059
7060
  return {
7060
7061
  runId: event.runId,
7061
7062
  eventId: event.eventId,
@@ -7065,7 +7066,7 @@ function eventEvidence(event, path41) {
7065
7066
  kind: event.kind,
7066
7067
  name: event.name,
7067
7068
  status: event.status,
7068
- ...path41 ? { path: path41 } : {}
7069
+ ...path43 ? { path: path43 } : {}
7069
7070
  };
7070
7071
  }
7071
7072
  function runEvidence(run) {
@@ -7135,9 +7136,9 @@ function eventEndMs(event) {
7135
7136
  function normalizedKey(value) {
7136
7137
  return value.toLowerCase().replace(/[^a-z0-9_]/g, "");
7137
7138
  }
7138
- function lastPathSegment(path41) {
7139
- const parts = path41.split(".");
7140
- return parts[parts.length - 1] ?? path41;
7139
+ function lastPathSegment(path43) {
7140
+ const parts = path43.split(".");
7141
+ return parts[parts.length - 1] ?? path43;
7141
7142
  }
7142
7143
  function valueType(value) {
7143
7144
  if (Array.isArray(value)) return "array";
@@ -7151,12 +7152,12 @@ function serializedByteLength(value) {
7151
7152
  return void 0;
7152
7153
  }
7153
7154
  }
7154
- function pushValueEntries(entries, event, value, path41, key, depth = 0) {
7155
- entries.push({ event, path: path41, key, value });
7155
+ function pushValueEntries(entries, event, value, path43, key, depth = 0) {
7156
+ entries.push({ event, path: path43, key, value });
7156
7157
  if (depth >= 8) return;
7157
7158
  if (Array.isArray(value)) {
7158
7159
  for (const [index, item] of value.entries()) {
7159
- pushValueEntries(entries, event, item, `${path41}.${index}`, String(index), depth + 1);
7160
+ pushValueEntries(entries, event, item, `${path43}.${index}`, String(index), depth + 1);
7160
7161
  }
7161
7162
  return;
7162
7163
  }
@@ -7166,7 +7167,7 @@ function pushValueEntries(entries, event, value, path41, key, depth = 0) {
7166
7167
  entries,
7167
7168
  event,
7168
7169
  value[nestedKey],
7169
- `${path41}.${nestedKey}`,
7170
+ `${path43}.${nestedKey}`,
7170
7171
  nestedKey,
7171
7172
  depth + 1
7172
7173
  );
@@ -7205,18 +7206,18 @@ function isRawContentKey(key, forbiddenKeys) {
7205
7206
  const normalized = normalizedKey(key);
7206
7207
  return forbiddenKeys.some((forbidden) => normalized === normalizedKey(forbidden));
7207
7208
  }
7208
- function isSafeRawContentMetricPath(path41, key, safePathPrefixes) {
7209
- const leaf = normalizedKey(key ?? lastPathSegment(path41));
7209
+ function isSafeRawContentMetricPath(path43, key, safePathPrefixes) {
7210
+ const leaf = normalizedKey(key ?? lastPathSegment(path43));
7210
7211
  if (!SAFE_USAGE_LEAF_KEYS.has(leaf)) return false;
7211
- const parts = path41.split(".").filter(Boolean);
7212
+ const parts = path43.split(".").filter(Boolean);
7212
7213
  if (parts.length < 2) return false;
7213
7214
  const parent = parts[parts.length - 2] ?? "";
7214
7215
  const parentNorm = normalizedKey(parent);
7215
7216
  return safePathPrefixes.some((prefix) => parentNorm === normalizedKey(prefix));
7216
7217
  }
7217
- function isRawContentPath(path41, key, forbiddenKeys, safePathPrefixes) {
7218
- if (isSafeRawContentMetricPath(path41, key, safePathPrefixes)) return false;
7219
- return isRawContentKey(key ?? lastPathSegment(path41), forbiddenKeys);
7218
+ function isRawContentPath(path43, key, forbiddenKeys, safePathPrefixes) {
7219
+ if (isSafeRawContentMetricPath(path43, key, safePathPrefixes)) return false;
7220
+ return isRawContentKey(key ?? lastPathSegment(path43), forbiddenKeys);
7220
7221
  }
7221
7222
  function parentMarkedUnresolved(event) {
7222
7223
  if (booleanAttr(event, [
@@ -7255,9 +7256,9 @@ function eventDurationMs(event) {
7255
7256
  }
7256
7257
  function treeShape(nodes) {
7257
7258
  const lines = [];
7258
- const visit = (node, path41) => {
7259
- lines.push(`${path41}:${node.event.kind}:${node.event.name}:${node.event.status ?? "unknown"}`);
7260
- node.children.forEach((child, index) => visit(child, `${path41}.${index}`));
7259
+ const visit = (node, path43) => {
7260
+ lines.push(`${path43}:${node.event.kind}:${node.event.name}:${node.event.status ?? "unknown"}`);
7261
+ node.children.forEach((child, index) => visit(child, `${path43}.${index}`));
7261
7262
  };
7262
7263
  nodes.forEach((node, index) => visit(node, String(index)));
7263
7264
  return lines;
@@ -7306,9 +7307,9 @@ function retrievalShape(context) {
7306
7307
  function guardrailShape(context) {
7307
7308
  return guardrailEvents(context).map((event) => signalName(event, ["guardrailName", "guardrail", "guardrailId"], ["guardrail:"])).sort((a, b) => a.localeCompare(b));
7308
7309
  }
7309
- function firstEvidenceForKind(context, kind, path41) {
7310
+ function firstEvidenceForKind(context, kind, path43) {
7310
7311
  const event = semanticEvents(context).find((candidate) => candidate.kind === kind);
7311
- return event ? [eventEvidence(event, path41)] : runEvidence(context.selectedRun);
7312
+ return event ? [eventEvidence(event, path43)] : runEvidence(context.selectedRun);
7312
7313
  }
7313
7314
  function baselineDiffFinding(message, evidence, expected, actual) {
7314
7315
  return failFinding("baseline.regression", message, evidence, expected, actual);
@@ -7658,13 +7659,13 @@ function createStructureCycleRule() {
7658
7659
  const seenCycles = /* @__PURE__ */ new Set();
7659
7660
  const findings = [];
7660
7661
  for (const event of [...semanticEvents(context)].sort((a, b) => a.eventId.localeCompare(b.eventId))) {
7661
- const path41 = [];
7662
+ const path43 = [];
7662
7663
  const seenAt = /* @__PURE__ */ new Map();
7663
7664
  let current = event;
7664
7665
  while (current) {
7665
7666
  const existing = seenAt.get(current.eventId);
7666
7667
  if (existing !== void 0) {
7667
- const cycle = path41.slice(existing);
7668
+ const cycle = path43.slice(existing);
7668
7669
  const key = cycle.map((item) => item.eventId).sort().join("\0");
7669
7670
  if (!seenCycles.has(key)) {
7670
7671
  seenCycles.add(key);
@@ -7680,8 +7681,8 @@ function createStructureCycleRule() {
7680
7681
  }
7681
7682
  break;
7682
7683
  }
7683
- seenAt.set(current.eventId, path41.length);
7684
- path41.push(current);
7684
+ seenAt.set(current.eventId, path43.length);
7685
+ path43.push(current);
7685
7686
  current = current.parentId ? byId.get(current.parentId) : void 0;
7686
7687
  }
7687
7688
  }
@@ -9015,7 +9016,7 @@ function findReaderByFormat(format, readers) {
9015
9016
  }
9016
9017
  async function jsonlFilesInDirectory(dirPath) {
9017
9018
  const entries = await promises.readdir(dirPath, { withFileTypes: true });
9018
- 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));
9019
+ return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => path32__default.default.join(dirPath, entry.name)).sort((a, b) => a.localeCompare(b));
9019
9020
  }
9020
9021
  async function resolveInput(input3) {
9021
9022
  const cached2 = resolvedInputCache.get(input3);
@@ -10723,7 +10724,7 @@ async function runSuiteCase(suiteCase, config, options) {
10723
10724
  async function runSuite(options = {}) {
10724
10725
  const startedAt = new Date(options.nowMs ?? Date.now()).toISOString();
10725
10726
  const { config, configPath, configDir } = await loadSuiteConfig(options);
10726
- const tracesDir = path30__default.default.resolve(configDir, config.traces);
10727
+ const tracesDir = path32__default.default.resolve(configDir, config.traces);
10727
10728
  const cases = [];
10728
10729
  const diagnostics = [];
10729
10730
  for (const suiteCase of config.cases) {
@@ -11750,7 +11751,7 @@ function validateOptions(options) {
11750
11751
  }
11751
11752
  function isConfigLoadError(error) {
11752
11753
  if (!(error instanceof Error)) return false;
11753
- const ext = path30__default.default.extname(error.message);
11754
+ const ext = path32__default.default.extname(error.message);
11754
11755
  if (error.message.includes("Unsupported suite config extension")) return true;
11755
11756
  if (error.message.includes("TypeScript suite configs require")) return true;
11756
11757
  if (error.message.includes("No suite config found")) return true;
@@ -12144,8 +12145,8 @@ var init_load_sqlite = __esm({
12144
12145
  }
12145
12146
  });
12146
12147
  function resolveIndexDbPath(traceDir, dbPath) {
12147
- if (dbPath && dbPath.trim() !== "") return path30__default.default.resolve(dbPath);
12148
- return path30__default.default.join(path30__default.default.resolve(traceDir), INDEX_DB_FILENAME);
12148
+ if (dbPath && dbPath.trim() !== "") return path32__default.default.resolve(dbPath);
12149
+ return path32__default.default.join(path32__default.default.resolve(traceDir), INDEX_DB_FILENAME);
12149
12150
  }
12150
12151
  function str(value) {
12151
12152
  return typeof value === "string" && value !== "" ? value : null;
@@ -12237,7 +12238,7 @@ async function buildIndex(options = {}) {
12237
12238
  warnings.push(`index.unreadable: ${file}`);
12238
12239
  }
12239
12240
  }
12240
- await promises.mkdir(path30__default.default.dirname(dbPath), { recursive: true });
12241
+ await promises.mkdir(path32__default.default.dirname(dbPath), { recursive: true });
12241
12242
  await promises.rm(dbPath, { force: true });
12242
12243
  const Sqlite = loadBetterSqlite3();
12243
12244
  const db = new Sqlite(dbPath);
@@ -12485,7 +12486,7 @@ var init_src = __esm({
12485
12486
  });
12486
12487
 
12487
12488
  // package.json
12488
- var version = "6.16.2";
12489
+ var version = "6.17.0";
12489
12490
 
12490
12491
  // packages/cli/src/list.ts
12491
12492
  init_advanced();
@@ -15508,9 +15509,9 @@ Trace directory: ${traceDir}`);
15508
15509
  process.exitCode = 1;
15509
15510
  }
15510
15511
  const resolvedOutput = resolveOutputOption(options);
15511
- const outPath = resolvedOutput !== void 0 ? path30__default.default.resolve(resolvedOutput) : void 0;
15512
+ const outPath = resolvedOutput !== void 0 ? path32__default.default.resolve(resolvedOutput) : void 0;
15512
15513
  if (outPath !== void 0) {
15513
- await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
15514
+ await promises.mkdir(path32__default.default.dirname(outPath), { recursive: true });
15514
15515
  await promises.writeFile(outPath, result.content, "utf-8");
15515
15516
  const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
15516
15517
  console.log(`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`);
@@ -15869,7 +15870,7 @@ function indexedToMetadata(row, traceDir) {
15869
15870
  endedAt: row.endedAt ?? void 0,
15870
15871
  durationMs: row.durationMs ?? void 0,
15871
15872
  eventCount: 0,
15872
- filePath: path30__default.default.join(traceDir, row.file),
15873
+ filePath: path32__default.default.join(traceDir, row.file),
15873
15874
  fileSize: 0,
15874
15875
  createdAt: new Date(row.mtimeMs)
15875
15876
  };
@@ -16351,9 +16352,9 @@ async function reportCommand(runId, options = {}) {
16351
16352
  ...options.section ? { section: options.section } : {}
16352
16353
  });
16353
16354
  const resolvedOutput = resolveOutputOption(options);
16354
- const outPath = resolvedOutput !== void 0 ? path30__default.default.resolve(resolvedOutput) : void 0;
16355
+ const outPath = resolvedOutput !== void 0 ? path32__default.default.resolve(resolvedOutput) : void 0;
16355
16356
  if (outPath !== void 0) {
16356
- await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
16357
+ await promises.mkdir(path32__default.default.dirname(outPath), { recursive: true });
16357
16358
  await promises.writeFile(outPath, result.content, "utf-8");
16358
16359
  console.log(`Wrote ${result.fileExtension} report to ${outPath}`);
16359
16360
  }
@@ -16535,8 +16536,8 @@ function passesLuhn(value) {
16535
16536
  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;
16536
16537
  var EPOCH_MS_RE = /^1[0-9]{12}$/;
16537
16538
  var EMAIL_RE = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
16538
- function pathSuggestsNonCard(path41) {
16539
- const normalized = path41.toLowerCase().replace(/[^a-z0-9._]/g, "");
16539
+ function pathSuggestsNonCard(path43) {
16540
+ const normalized = path43.toLowerCase().replace(/[^a-z0-9._]/g, "");
16540
16541
  return /(^|\.)(tokenusage|usage)(\.|$)/.test(normalized) || /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\.|$)/.test(normalized) || /(^|\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\.|$)/.test(
16541
16542
  normalized
16542
16543
  ) || /(^|\.)ts(\.|$)/.test(normalized);
@@ -16723,17 +16724,17 @@ function applyRule(rule, value, replacement) {
16723
16724
  }
16724
16725
  return value;
16725
16726
  }
16726
- function childPath(path41, key) {
16727
+ function childPath(path43, key) {
16727
16728
  if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
16728
- return path41 ? `${path41}.${key}` : key;
16729
+ return path43 ? `${path43}.${key}` : key;
16729
16730
  }
16730
- return `${path41 || "$"}[${JSON.stringify(key)}]`;
16731
+ return `${path43 || "$"}[${JSON.stringify(key)}]`;
16731
16732
  }
16732
- function indexPath(path41, index) {
16733
- return `${path41 || "$"}[${index}]`;
16733
+ function indexPath(path43, index) {
16734
+ return `${path43 || "$"}[${index}]`;
16734
16735
  }
16735
- function makeFinding(path41, detector, action, matchKind, severity = "warning", preview) {
16736
- return preview === void 0 ? { path: path41, detector, action, severity, matchKind } : { path: path41, detector, action, severity, matchKind, preview };
16736
+ function makeFinding(path43, detector, action, matchKind, severity = "warning", preview) {
16737
+ return preview === void 0 ? { path: path43, detector, action, severity, matchKind } : { path: path43, detector, action, severity, matchKind, preview };
16737
16738
  }
16738
16739
  function createRedactionProfile(profile = "local") {
16739
16740
  switch (profile) {
@@ -16802,11 +16803,11 @@ var Redactor2 = class {
16802
16803
  #recordFinding(state, finding) {
16803
16804
  if (this.#collectFindings) state.findings.push(finding);
16804
16805
  }
16805
- #redactValue(value, key, path41, depth, state) {
16806
+ #redactValue(value, key, path43, depth, state) {
16806
16807
  if (depth > this.#maxDepth) {
16807
16808
  this.#recordFinding(
16808
16809
  state,
16809
- makeFinding(path41, "structure.maxDepth", "truncate", "value", "warning")
16810
+ makeFinding(path43, "structure.maxDepth", "truncate", "value", "warning")
16810
16811
  );
16811
16812
  return "[Truncated]";
16812
16813
  }
@@ -16815,19 +16816,19 @@ var Redactor2 = class {
16815
16816
  if (rule) {
16816
16817
  this.#recordFinding(
16817
16818
  state,
16818
- makeFinding(path41, `key.${rule.key}`, actionForRule(rule), "key", "warning")
16819
+ makeFinding(path43, `key.${rule.key}`, actionForRule(rule), "key", "warning")
16819
16820
  );
16820
16821
  return applyRule(rule, value, this.#replacement);
16821
16822
  }
16822
16823
  }
16823
16824
  for (const detector of this.#detectors) {
16824
- const detections = detector.detect({ path: path41, key, value });
16825
+ const detections = detector.detect({ path: path43, key, value });
16825
16826
  for (const detection of detections) {
16826
16827
  const action = detection.action ?? "replace";
16827
16828
  this.#recordFinding(
16828
16829
  state,
16829
16830
  makeFinding(
16830
- path41,
16831
+ path43,
16831
16832
  detector.id,
16832
16833
  action,
16833
16834
  detection.matchKind ?? detector.matchKind ?? "custom",
@@ -16845,7 +16846,7 @@ var Redactor2 = class {
16845
16846
  const out = [];
16846
16847
  state.seen.set(value, out);
16847
16848
  value.forEach((item, index) => {
16848
- out[index] = this.#redactValue(item, void 0, indexPath(path41, index), depth + 1, state);
16849
+ out[index] = this.#redactValue(item, void 0, indexPath(path43, index), depth + 1, state);
16849
16850
  });
16850
16851
  return out;
16851
16852
  }
@@ -16857,7 +16858,7 @@ var Redactor2 = class {
16857
16858
  out[entryKey] = this.#redactValue(
16858
16859
  entryValue,
16859
16860
  entryKey,
16860
- childPath(path41 === "$" ? "" : path41, entryKey),
16861
+ childPath(path43 === "$" ? "" : path43, entryKey),
16861
16862
  depth + 1,
16862
16863
  state
16863
16864
  );
@@ -17328,14 +17329,14 @@ function uniqueSorted(values) {
17328
17329
  return [...new Set(values)].sort();
17329
17330
  }
17330
17331
  function isWithinDirectory(child, parent) {
17331
- const relative = path30__default.default.relative(parent, child);
17332
- return relative === "" || !relative.startsWith("..") && !path30__default.default.isAbsolute(relative);
17332
+ const relative = path32__default.default.relative(parent, child);
17333
+ return relative === "" || !relative.startsWith("..") && !path32__default.default.isAbsolute(relative);
17333
17334
  }
17334
17335
  async function resolveOutputPath(inputPath, output2, force) {
17335
17336
  if (output2 === void 0 || output2.trim() === "") return void 0;
17336
- const inputAbs = path30__default.default.resolve(inputPath);
17337
- const outputAbs = path30__default.default.resolve(output2.trim());
17338
- const inputDir = path30__default.default.dirname(inputAbs);
17337
+ const inputAbs = path32__default.default.resolve(inputPath);
17338
+ const outputAbs = path32__default.default.resolve(output2.trim());
17339
+ const inputDir = path32__default.default.dirname(inputAbs);
17339
17340
  if (!isWithinDirectory(outputAbs, inputDir)) {
17340
17341
  throw new Error("Refusing to write migrated output outside the input directory.");
17341
17342
  }
@@ -17456,7 +17457,7 @@ async function migrateCommand(input3, options = {}) {
17456
17457
  process.exitCode = 1;
17457
17458
  return;
17458
17459
  }
17459
- const inputPath = path30__default.default.resolve(input3.trim());
17460
+ const inputPath = path32__default.default.resolve(input3.trim());
17460
17461
  const dryRun = options.dryRun === true;
17461
17462
  if (!dryRun && (options.output === void 0 || options.output.trim() === "")) {
17462
17463
  console.error("migrate requires --dry-run or --output <path>.");
@@ -17475,7 +17476,7 @@ async function migrateCommand(input3, options = {}) {
17475
17476
  );
17476
17477
  const result = await buildMigration(inputPath, outputPath);
17477
17478
  if (!dryRun && outputPath !== void 0) {
17478
- await promises.mkdir(path30__default.default.dirname(outputPath), { recursive: true });
17479
+ await promises.mkdir(path32__default.default.dirname(outputPath), { recursive: true });
17479
17480
  await promises.writeFile(outputPath, result.content, "utf-8");
17480
17481
  }
17481
17482
  printSummary2(result, dryRun);
@@ -17489,6 +17490,246 @@ init_advanced();
17489
17490
 
17490
17491
  // packages/core/src/entries/checks.ts
17491
17492
  init_checks2();
17493
+
17494
+ // packages/cli/src/evidence-on.ts
17495
+ init_advanced();
17496
+ function validateReporterArtifactPath(options) {
17497
+ const outputDir = path32__default.default.resolve(options.outputDir);
17498
+ const diagnostics = [];
17499
+ const rawPath = options.relativePath;
17500
+ if (rawPath.length === 0) {
17501
+ diagnostics.push({
17502
+ code: "artifact_path_empty",
17503
+ severity: "error",
17504
+ message: "Reporter artifact path must not be empty."
17505
+ });
17506
+ return { ok: false, outputDir, diagnostics };
17507
+ }
17508
+ if (rawPath.includes("\0")) {
17509
+ diagnostics.push({
17510
+ code: "invalid_artifact_path",
17511
+ severity: "error",
17512
+ message: "Reporter artifact path must not contain null bytes.",
17513
+ target: rawPath
17514
+ });
17515
+ return { ok: false, outputDir, diagnostics };
17516
+ }
17517
+ if (path32__default.default.isAbsolute(rawPath) || path32__default.default.win32.isAbsolute(rawPath)) {
17518
+ diagnostics.push({
17519
+ code: "artifact_path_absolute",
17520
+ severity: "error",
17521
+ message: "Reporter artifact path must be relative.",
17522
+ target: rawPath
17523
+ });
17524
+ return { ok: false, outputDir, diagnostics };
17525
+ }
17526
+ const normalized = path32__default.default.posix.normalize(rawPath.replace(/\\/g, "/"));
17527
+ const segments = normalized.split("/");
17528
+ if (normalized === "." || normalized.startsWith("../") || segments.some((segment) => segment === "..")) {
17529
+ diagnostics.push({
17530
+ code: "artifact_path_escape",
17531
+ severity: "error",
17532
+ message: "Reporter artifact path must stay under the output directory.",
17533
+ target: rawPath
17534
+ });
17535
+ return { ok: false, outputDir, diagnostics };
17536
+ }
17537
+ const absolutePath = path32__default.default.resolve(outputDir, normalized);
17538
+ const relFromOutput = path32__default.default.relative(outputDir, absolutePath);
17539
+ if (relFromOutput.length === 0 || relFromOutput.startsWith("..") || path32__default.default.isAbsolute(relFromOutput)) {
17540
+ diagnostics.push({
17541
+ code: "artifact_path_escape",
17542
+ severity: "error",
17543
+ message: "Reporter artifact path resolved outside the output directory.",
17544
+ target: rawPath
17545
+ });
17546
+ return { ok: false, outputDir, diagnostics };
17547
+ }
17548
+ return {
17549
+ ok: true,
17550
+ outputDir,
17551
+ relativePath: normalized,
17552
+ absolutePath,
17553
+ diagnostics
17554
+ };
17555
+ }
17556
+ var EVIDENCE_CI_ARTIFACT_FILES = [
17557
+ "evidence.html",
17558
+ "evidence.json",
17559
+ "check-results.json",
17560
+ "trace.jsonl"
17561
+ ];
17562
+ function createEvidenceCiArtifacts(options) {
17563
+ const profile = options.redactionProfile ?? "share";
17564
+ const prefix = options.relativeDir !== void 0 && options.relativeDir.trim() !== "" ? options.relativeDir.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "") : "";
17565
+ const join = (name) => prefix === "" ? name : path32__default.default.posix.join(prefix, name);
17566
+ const formatFor = (name) => {
17567
+ if (name.endsWith(".html")) return "html";
17568
+ if (name.endsWith(".jsonl")) return "jsonl";
17569
+ return "json";
17570
+ };
17571
+ return EVIDENCE_CI_ARTIFACT_FILES.map((name) => ({
17572
+ kind: "evidence",
17573
+ path: join(name),
17574
+ format: formatFor(name),
17575
+ redactionProfile: profile,
17576
+ title: `Evidence v2 ${name}`
17577
+ }));
17578
+ }
17579
+
17580
+ // packages/cli/src/evidence-on.ts
17581
+ function shouldEmitEvidence(mode, failed) {
17582
+ if (mode === void 0 || mode === "never") return false;
17583
+ if (mode === "always") return true;
17584
+ return failed;
17585
+ }
17586
+ function parseEvidenceProfile(value) {
17587
+ const profile = (value ?? "share").trim().toLowerCase();
17588
+ if (profile === "local" || profile === "share" || profile === "strict") {
17589
+ return profile;
17590
+ }
17591
+ throw new Error(
17592
+ `Unsupported --evidence-profile "${value}". Use local, share, or strict.`
17593
+ );
17594
+ }
17595
+ function parseEvidenceFormat(value) {
17596
+ const format = (value ?? "directory").trim().toLowerCase();
17597
+ if (format === "directory" || format === "html" || format === "zip") {
17598
+ return format;
17599
+ }
17600
+ throw new Error(
17601
+ `Unsupported --evidence-format "${value}". Use directory, html, or zip.`
17602
+ );
17603
+ }
17604
+ function toAssessmentStatus(failed) {
17605
+ return failed ? "UNSAFE" : "SAFE";
17606
+ }
17607
+ function stableJson2(value) {
17608
+ return `${JSON.stringify(value, null, 2)}
17609
+ `;
17610
+ }
17611
+ async function writeLocalEvidence(input3) {
17612
+ const profile = input3.redactionProfile ?? "share";
17613
+ const format = input3.format ?? "directory";
17614
+ const baseDir = path32__default.default.resolve(input3.outputDir);
17615
+ await promises.mkdir(
17616
+ format === "zip" && baseDir.toLowerCase().endsWith(".zip") ? path32__default.default.dirname(baseDir) : baseDir,
17617
+ { recursive: true }
17618
+ );
17619
+ const sourceContents = /* @__PURE__ */ new Map();
17620
+ if (input3.sourceContents instanceof Map) {
17621
+ for (const [runId, content] of input3.sourceContents) {
17622
+ sourceContents.set(runId, content);
17623
+ }
17624
+ } else if (input3.sourceContents !== void 0) {
17625
+ for (const [runId, content] of Object.entries(input3.sourceContents)) {
17626
+ sourceContents.set(runId, content);
17627
+ }
17628
+ }
17629
+ const traceDir = resolveTraceDir({ dir: input3.dir });
17630
+ let combined = "";
17631
+ for (const runId of input3.runIds) {
17632
+ let raw = sourceContents.get(runId) ?? "";
17633
+ if (raw === "") {
17634
+ try {
17635
+ raw = await promises.readFile(getTraceFilePath(runId, traceDir), "utf-8");
17636
+ } catch {
17637
+ raw = "";
17638
+ }
17639
+ sourceContents.set(runId, raw);
17640
+ }
17641
+ const redacted = redactTraceContent(raw, profile);
17642
+ combined += redacted.content.endsWith("\n") ? redacted.content : `${redacted.content}
17643
+ `;
17644
+ }
17645
+ const assessmentStatus = toAssessmentStatus(input3.failed);
17646
+ const evidencePackage = buildEvidenceCiPackage({
17647
+ generatorVersion: version,
17648
+ runIds: input3.runIds,
17649
+ sourceContents,
17650
+ redactedTraceJsonl: combined,
17651
+ redactionProfile: profile,
17652
+ assessmentStatus,
17653
+ checkResultsJson: input3.checkResultsJson,
17654
+ ...input3.summaryText !== void 0 ? { summaryText: input3.summaryText } : {}
17655
+ });
17656
+ const files = [
17657
+ ["evidence.html", evidencePackage["evidence.html"]],
17658
+ ["evidence.json", evidencePackage["evidence.json"]],
17659
+ ["check-results.json", evidencePackage["check-results.json"]],
17660
+ ["trace.jsonl", evidencePackage["trace.jsonl"]]
17661
+ ];
17662
+ const expected = createEvidenceCiArtifacts({
17663
+ redactionProfile: profile
17664
+ }).map((a) => a.path);
17665
+ for (const name of expected) {
17666
+ if (!files.some(([fileName]) => fileName === name)) {
17667
+ throw new Error(`Evidence CI package missing expected file: ${name}`);
17668
+ }
17669
+ }
17670
+ if (format === "zip") {
17671
+ const zipPath = baseDir.toLowerCase().endsWith(".zip") ? baseDir : `${baseDir}.zip`;
17672
+ await promises.mkdir(path32__default.default.dirname(zipPath), { recursive: true });
17673
+ const archive = buildZipArchive(
17674
+ files.map(([relativePath, content]) => ({
17675
+ path: relativePath,
17676
+ content
17677
+ }))
17678
+ );
17679
+ await promises.writeFile(zipPath, archive);
17680
+ return zipPath;
17681
+ }
17682
+ if (format === "html") {
17683
+ let htmlPath = baseDir;
17684
+ let sidecarDir = baseDir;
17685
+ if (baseDir.toLowerCase().endsWith(".html")) {
17686
+ htmlPath = baseDir;
17687
+ sidecarDir = path32__default.default.dirname(baseDir);
17688
+ } else {
17689
+ await promises.mkdir(baseDir, { recursive: true });
17690
+ htmlPath = path32__default.default.join(baseDir, "evidence.html");
17691
+ sidecarDir = baseDir;
17692
+ }
17693
+ await promises.mkdir(sidecarDir, { recursive: true });
17694
+ await promises.writeFile(htmlPath, evidencePackage["evidence.html"], "utf-8");
17695
+ await promises.writeFile(
17696
+ path32__default.default.join(sidecarDir, "evidence.json"),
17697
+ evidencePackage["evidence.json"],
17698
+ "utf-8"
17699
+ );
17700
+ return htmlPath;
17701
+ }
17702
+ await promises.mkdir(baseDir, { recursive: true });
17703
+ for (const [name, content] of files) {
17704
+ await promises.writeFile(path32__default.default.join(baseDir, name), content, "utf-8");
17705
+ }
17706
+ return baseDir;
17707
+ }
17708
+ function checkResultToEvidenceJson(result, runIds) {
17709
+ const status = result.status === "pass" ? "SAFE" : result.status === "fail" ? "UNSAFE" : "UNKNOWN";
17710
+ return stableJson2({
17711
+ aggregateStatus: status,
17712
+ runs: runIds.map((runId) => ({
17713
+ runId,
17714
+ status,
17715
+ errors: result.summary.errors,
17716
+ warnings: result.summary.warnings,
17717
+ findings: result.findings.length
17718
+ })),
17719
+ findings: result.findings,
17720
+ diagnostics: result.diagnostics
17721
+ });
17722
+ }
17723
+ function defaultEvidenceDir(label) {
17724
+ const safe = label.replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 80) || "evidence";
17725
+ return path32__default.default.join(".agent-inspect", "evidence", safe);
17726
+ }
17727
+ function resolveEvidenceOutputDir(evidenceDir, label) {
17728
+ if (evidenceDir !== void 0 && evidenceDir.trim() !== "") {
17729
+ return path32__default.default.resolve(evidenceDir.trim());
17730
+ }
17731
+ return defaultEvidenceDir(label);
17732
+ }
17492
17733
  var ALL_RULES = [
17493
17734
  "circuit.same-tool-repetition",
17494
17735
  "circuit.same-args-repetition",
@@ -17809,23 +18050,23 @@ function evaluatePromptInjection(text, options = {}) {
17809
18050
  }
17810
18051
  return fail(ruleId, `Matched ${evidence.length} injection pattern(s).`, evidence, "warning");
17811
18052
  }
17812
- function validateSchemaField(value, field, path41, evidence) {
18053
+ function validateSchemaField(value, field, path43, evidence) {
17813
18054
  const ruleId = "guardrail.structured-output";
17814
18055
  if (field.type) {
17815
18056
  const actual = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
17816
18057
  if (actual !== field.type) {
17817
- evidence.push({ ruleId, path: path41, preview: `expected ${field.type}, got ${actual}` });
18058
+ evidence.push({ ruleId, path: path43, preview: `expected ${field.type}, got ${actual}` });
17818
18059
  return;
17819
18060
  }
17820
18061
  }
17821
18062
  if (field.enum && !field.enum.some((item) => Object.is(item, value))) {
17822
- evidence.push({ ruleId, path: path41, preview: "value not in enum" });
18063
+ evidence.push({ ruleId, path: path43, preview: "value not in enum" });
17823
18064
  }
17824
18065
  if (field.type === "object" && field.required && value && typeof value === "object" && !Array.isArray(value)) {
17825
18066
  const record = value;
17826
18067
  for (const key of field.required) {
17827
18068
  if (!(key in record)) {
17828
- evidence.push({ ruleId, path: `${path41}.${key}`, preview: "missing required key" });
18069
+ evidence.push({ ruleId, path: `${path43}.${key}`, preview: "missing required key" });
17829
18070
  }
17830
18071
  }
17831
18072
  }
@@ -18106,6 +18347,54 @@ function mergeSafetyExtensions(result, read, options) {
18106
18347
  }
18107
18348
 
18108
18349
  // packages/cli/src/check.ts
18350
+ function resolvePreset(preset, context = {}) {
18351
+ if (preset === void 0 || preset.trim() === "") return void 0;
18352
+ const name = preset.trim().toLowerCase();
18353
+ if (name !== "trajectory" && name !== "safety" && name !== "comprehensive") {
18354
+ throw new Error(
18355
+ `Unknown --preset "${preset}". Use trajectory, safety, or comprehensive.`
18356
+ );
18357
+ }
18358
+ const trajectorySelect = [
18359
+ "run.status",
18360
+ "run.requireCompleted",
18361
+ "structure.orphan",
18362
+ "structure.cycle",
18363
+ "structure.relationship"
18364
+ ];
18365
+ if (context.hasToolRules === true) {
18366
+ trajectorySelect.push("tool.usage");
18367
+ }
18368
+ const safetySelect = [
18369
+ "run.status",
18370
+ "safety.rawPrompt",
18371
+ "safety.secretPattern",
18372
+ "safety.redaction"
18373
+ ];
18374
+ if (name === "trajectory") {
18375
+ return {
18376
+ requireCompleted: true,
18377
+ enableSafetyRedaction: false,
18378
+ enableStructureRelationshipDefaults: true,
18379
+ select: trajectorySelect
18380
+ };
18381
+ }
18382
+ if (name === "safety") {
18383
+ return {
18384
+ requireCompleted: false,
18385
+ enableSafetyRedaction: true,
18386
+ enableStructureRelationshipDefaults: false,
18387
+ select: safetySelect
18388
+ };
18389
+ }
18390
+ const select = [.../* @__PURE__ */ new Set([...trajectorySelect, ...safetySelect])];
18391
+ return {
18392
+ requireCompleted: true,
18393
+ enableSafetyRedaction: true,
18394
+ enableStructureRelationshipDefaults: true,
18395
+ select
18396
+ };
18397
+ }
18109
18398
  var DEFAULT_SELECT = ["run.status"];
18110
18399
  var CONFIG_EXTENSIONS2 = /* @__PURE__ */ new Set([".json", ".js", ".mjs", ".cjs"]);
18111
18400
  var TS_CONFIG_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".mts", ".cts"]);
@@ -18152,7 +18441,7 @@ function asConfig(value) {
18152
18441
  }
18153
18442
  async function loadConfig(configPath) {
18154
18443
  if (configPath === void 0) return {};
18155
- const extension = path30__default.default.extname(configPath);
18444
+ const extension = path32__default.default.extname(configPath);
18156
18445
  if (TS_CONFIG_EXTENSIONS2.has(extension)) {
18157
18446
  throw new Error(
18158
18447
  "TypeScript check configs require an explicit precompiled JavaScript config or future --config-loader support."
@@ -18161,7 +18450,7 @@ async function loadConfig(configPath) {
18161
18450
  if (!CONFIG_EXTENSIONS2.has(extension)) {
18162
18451
  throw new Error("Unsupported check config extension. Use .json, .js, .mjs, or .cjs.");
18163
18452
  }
18164
- const absolute = path30__default.default.resolve(configPath);
18453
+ const absolute = path32__default.default.resolve(configPath);
18165
18454
  if (extension === ".json") {
18166
18455
  const raw = await promises.readFile(absolute, "utf-8");
18167
18456
  return asConfig(JSON.parse(raw));
@@ -18176,6 +18465,33 @@ function normalizeConfig(config) {
18176
18465
  }
18177
18466
  return config.checks;
18178
18467
  }
18468
+ function hasToolRulesConfigured(config, options) {
18469
+ const tool = normalizeConfig(config).tool ?? {};
18470
+ return Boolean(
18471
+ (tool.required?.length ?? 0) > 0 || (tool.forbidden?.length ?? 0) > 0 || (tool.allowed?.length ?? 0) > 0 || tool.minCount !== void 0 || tool.maxCount !== void 0 || (options.requiredTool?.length ?? 0) > 0 || (options.forbiddenTool?.length ?? 0) > 0
18472
+ );
18473
+ }
18474
+ function applyResolvedPreset(config, options, resolved) {
18475
+ const checks2 = { ...normalizeConfig(config) };
18476
+ if (resolved.enableSafetyRedaction) {
18477
+ checks2.safety = { ...checks2.safety, redaction: true };
18478
+ }
18479
+ if (resolved.enableStructureRelationshipDefaults) {
18480
+ const structure = checks2.structure ?? {};
18481
+ const needed = structure.minConfidence === void 0 && structure.requireParentBeforeChild === void 0 && structure.requireTraceParentSpan === void 0;
18482
+ if (needed) {
18483
+ checks2.structure = { ...structure, requireParentBeforeChild: true };
18484
+ }
18485
+ }
18486
+ return {
18487
+ config: { checks: checks2 },
18488
+ options: {
18489
+ ...options,
18490
+ ...resolved.requireCompleted ? { requireCompleted: true } : {},
18491
+ rule: [...resolved.select, ...options.rule ?? []]
18492
+ }
18493
+ };
18494
+ }
18179
18495
  function buildRules(config, options) {
18180
18496
  const diagnostics = [];
18181
18497
  const checks2 = normalizeConfig(config);
@@ -18319,7 +18635,42 @@ function stable3(value) {
18319
18635
  function printJson(result) {
18320
18636
  console.log(JSON.stringify(stable3(result), null, 2));
18321
18637
  }
18322
- function printHuman(result) {
18638
+ function isSafetyFinding(ruleId) {
18639
+ return ruleId.startsWith("safety.") || ruleId.startsWith("guardrail.") || ruleId.includes("pii") || ruleId.includes("secret");
18640
+ }
18641
+ function printPresetClassSummary(result, preset) {
18642
+ const name = preset?.trim().toLowerCase();
18643
+ if (name !== "trajectory" && name !== "safety" && name !== "comprehensive") {
18644
+ return;
18645
+ }
18646
+ const hasSafetyFindings = result.findings.some(
18647
+ (finding) => isSafetyFinding(finding.ruleId)
18648
+ );
18649
+ const hasTrajectoryFindings = result.findings.some(
18650
+ (finding) => !isSafetyFinding(finding.ruleId)
18651
+ );
18652
+ if (name === "trajectory") {
18653
+ console.log(
18654
+ `Trajectory: ${result.status === "pass" && !hasTrajectoryFindings ? "PASS" : result.status === "pass" ? "PASS" : "FAIL"}`
18655
+ );
18656
+ console.log("Share safety: not evaluated");
18657
+ console.log("Run verify-safe before sharing.");
18658
+ return;
18659
+ }
18660
+ if (name === "safety") {
18661
+ console.log(
18662
+ `Share safety: ${result.status === "pass" && !hasSafetyFindings ? "PASS" : result.status === "pass" ? "PASS" : "FAIL"}`
18663
+ );
18664
+ return;
18665
+ }
18666
+ console.log(
18667
+ `Trajectory: ${hasTrajectoryFindings || result.status === "error" ? "FAIL" : "PASS"}`
18668
+ );
18669
+ console.log(
18670
+ `Share safety: ${hasSafetyFindings || result.status === "fail" ? "FAIL" : result.status === "pass" ? "PASS" : "FAIL"}`
18671
+ );
18672
+ }
18673
+ function printHuman(result, options = {}) {
18323
18674
  const scoped = result;
18324
18675
  if (scoped.scopeLabel) {
18325
18676
  console.log(`Scope: ${scoped.scopeKind} ${scoped.scopeLabel}`);
@@ -18328,6 +18679,7 @@ function printHuman(result) {
18328
18679
  }
18329
18680
  }
18330
18681
  console.log(`Check status: ${result.status}`);
18682
+ printPresetClassSummary(result, options.preset);
18331
18683
  console.log(`Format: ${result.format}`);
18332
18684
  if (result.runId !== void 0) console.log(`Run: ${result.runId}`);
18333
18685
  console.log(
@@ -18337,10 +18689,10 @@ function printHuman(result) {
18337
18689
  console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
18338
18690
  }
18339
18691
  for (const finding of result.findings) {
18340
- const path41 = finding.evidence[0]?.path;
18692
+ const path43 = finding.evidence[0]?.path;
18341
18693
  const run = finding.evidence[0]?.runId;
18342
18694
  const runPrefix = run ? `[${run}] ` : "";
18343
- console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}`);
18695
+ console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${path43 ? ` (${path43})` : ""}`);
18344
18696
  }
18345
18697
  }
18346
18698
  function readErrorResult(error) {
@@ -18356,12 +18708,24 @@ function readErrorResult(error) {
18356
18708
  async function checkCommand(target, options = {}, stdin = process.stdin) {
18357
18709
  let result;
18358
18710
  let phase = "config";
18711
+ let evidenceRead;
18712
+ let evidenceRunIds = [];
18713
+ let evidenceSourceContents;
18359
18714
  const sessionId = options.session?.trim();
18360
18715
  const groupId = options.group?.trim();
18361
18716
  const useSessionScope = Boolean(sessionId || groupId);
18362
18717
  try {
18363
- const config = await loadConfig(options.config);
18364
- const built = buildRules(config, options);
18718
+ let config = await loadConfig(options.config);
18719
+ let effectiveOptions = options;
18720
+ const resolved = resolvePreset(options.preset, {
18721
+ hasToolRules: hasToolRulesConfigured(config, options)
18722
+ });
18723
+ if (resolved !== void 0) {
18724
+ const applied = applyResolvedPreset(config, options, resolved);
18725
+ config = applied.config;
18726
+ effectiveOptions = applied.options;
18727
+ }
18728
+ const built = buildRules(config, effectiveOptions);
18365
18729
  if (built.diagnostics.some((item) => item.severity === "error")) {
18366
18730
  result = errorResult2("AI_CHECK_INVALID_CONFIG", "Invalid check configuration.");
18367
18731
  result.diagnostics = [...built.diagnostics];
@@ -18382,6 +18746,7 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
18382
18746
  correlateByGroupId: options.correlateGroup === true
18383
18747
  });
18384
18748
  const perRun = [];
18749
+ const sourceContents = /* @__PURE__ */ new Map();
18385
18750
  for (const meta2 of scoped.metas) {
18386
18751
  const read = await openTrace(
18387
18752
  { type: "file", path: meta2.filePath },
@@ -18389,6 +18754,15 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
18389
18754
  ...options.format !== void 0 ? { format: options.format } : {}
18390
18755
  }
18391
18756
  );
18757
+ try {
18758
+ sourceContents.set(meta2.runId, await promises.readFile(meta2.filePath, "utf-8"));
18759
+ } catch {
18760
+ sourceContents.set(
18761
+ meta2.runId,
18762
+ `${read.events.map((event) => JSON.stringify(event)).join("\n")}
18763
+ `
18764
+ );
18765
+ }
18392
18766
  perRun.push(
18393
18767
  mergeSafetyExtensions(
18394
18768
  runTraceChecks(
@@ -18407,6 +18781,8 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
18407
18781
  )
18408
18782
  );
18409
18783
  }
18784
+ evidenceRunIds = scoped.runIds;
18785
+ evidenceSourceContents = sourceContents;
18410
18786
  result = aggregateSessionCheckResults(perRun, {
18411
18787
  scopeKind: scoped.scopeKind,
18412
18788
  scopeLabel: scoped.scopeLabel,
@@ -18421,6 +18797,26 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
18421
18797
  const read = await openTrace(input3, {
18422
18798
  ...options.format !== void 0 ? { format: options.format } : {}
18423
18799
  });
18800
+ evidenceRead = read;
18801
+ evidenceRunIds = options.run !== void 0 ? [options.run] : read.runs.length === 1 ? [read.runs[0].runId] : read.runs.map((run) => run.runId);
18802
+ if (input3.type === "file") {
18803
+ try {
18804
+ const raw = await promises.readFile(input3.path, "utf-8");
18805
+ evidenceSourceContents = new Map(
18806
+ evidenceRunIds.map((runId) => [runId, raw])
18807
+ );
18808
+ } catch {
18809
+ evidenceSourceContents = void 0;
18810
+ }
18811
+ } else {
18812
+ evidenceSourceContents = new Map(
18813
+ evidenceRunIds.map((runId) => [
18814
+ runId,
18815
+ `${read.events.filter((event) => event.runId === runId).map((event) => JSON.stringify(event)).join("\n")}
18816
+ `
18817
+ ])
18818
+ );
18819
+ }
18424
18820
  result = mergeSafetyExtensions(
18425
18821
  runTraceChecks(
18426
18822
  { read },
@@ -18440,7 +18836,7 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
18440
18836
  } catch (error) {
18441
18837
  if (phase === "config") {
18442
18838
  const message = error instanceof Error ? error.message : String(error);
18443
- const code = message.startsWith("--") ? "AI_CHECK_INVALID_ARGUMENTS" : error instanceof SyntaxError || message.includes("Unsupported check config extension") || message.includes("TypeScript check configs") || message.includes("Config must") || message.includes("checks config") || message.includes("Expected an array") ? "AI_CHECK_INVALID_CONFIG" : "AI_CHECK_CONFIG_LOAD_FAILED";
18839
+ const code = message.startsWith("--") || message.includes("Unknown --preset") ? "AI_CHECK_INVALID_ARGUMENTS" : error instanceof SyntaxError || message.includes("Unsupported check config extension") || message.includes("TypeScript check configs") || message.includes("Config must") || message.includes("checks config") || message.includes("Expected an array") ? "AI_CHECK_INVALID_CONFIG" : "AI_CHECK_CONFIG_LOAD_FAILED";
18444
18840
  result = errorResult2(
18445
18841
  code,
18446
18842
  message
@@ -18450,8 +18846,47 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
18450
18846
  }
18451
18847
  }
18452
18848
  process.exitCode = exitCodeFor(result);
18849
+ const failed = result.status !== "pass";
18850
+ if (shouldEmitEvidence(options.evidenceOn, failed)) {
18851
+ try {
18852
+ const runIds = evidenceRunIds.length > 0 ? evidenceRunIds : result.runId !== void 0 ? [result.runId] : ["check"];
18853
+ if (evidenceSourceContents === void 0 && evidenceRead !== void 0) {
18854
+ evidenceSourceContents = new Map(
18855
+ runIds.map((runId) => [
18856
+ runId,
18857
+ `${evidenceRead.events.filter((event) => event.runId === runId).map((event) => JSON.stringify(event)).join("\n")}
18858
+ `
18859
+ ])
18860
+ );
18861
+ }
18862
+ let redactionProfile = parseEvidenceProfile(options.evidenceProfile);
18863
+ let evidenceFormat = parseEvidenceFormat(options.evidenceFormat);
18864
+ const outputDir = resolveEvidenceOutputDir(
18865
+ options.evidenceDir,
18866
+ runIds[0] ?? "check"
18867
+ );
18868
+ const written = await writeLocalEvidence({
18869
+ outputDir,
18870
+ runIds,
18871
+ ...evidenceSourceContents !== void 0 ? { sourceContents: evidenceSourceContents } : {},
18872
+ ...options.dir !== void 0 ? { dir: options.dir } : {},
18873
+ failed,
18874
+ checkResultsJson: checkResultToEvidenceJson(result, runIds),
18875
+ summaryText: `Check status: ${result.status}`,
18876
+ redactionProfile,
18877
+ format: evidenceFormat
18878
+ });
18879
+ if (!options.json) {
18880
+ console.log(`Evidence: ${written}`);
18881
+ }
18882
+ } catch (error) {
18883
+ console.error(
18884
+ `[AgentInspect] evidence package skipped: ${error instanceof Error ? error.message : String(error)}`
18885
+ );
18886
+ }
18887
+ }
18453
18888
  if (options.json) printJson(result);
18454
- else printHuman(result);
18889
+ else printHuman(result, options);
18455
18890
  }
18456
18891
 
18457
18892
  // packages/viewer/src/server.ts
@@ -18608,7 +19043,7 @@ async function loadSuiteViewerData(options) {
18608
19043
  for (const suiteCase of result.cases) {
18609
19044
  cases.push(await enrichCase(suiteCase, baselinePath));
18610
19045
  }
18611
- const artifactsDir = path30__default.default.join(path30__default.default.dirname(result.configPath), ".agent-inspect/suite-runs");
19046
+ const artifactsDir = path32__default.default.join(path32__default.default.dirname(result.configPath), ".agent-inspect/suite-runs");
18612
19047
  return {
18613
19048
  suiteName: result.suiteName,
18614
19049
  configPath: result.configPath,
@@ -18804,19 +19239,19 @@ function serializeWorkspaceManifest(manifest) {
18804
19239
  }
18805
19240
  var INDEX_DIR_NAME = "index";
18806
19241
  function resolveWorkspaceLocation(cwd = process.cwd()) {
18807
- const projectRoot = path30__default.default.resolve(cwd);
18808
- const workspaceDir = path30__default.default.join(projectRoot, WORKSPACE_DIR_NAME);
19242
+ const projectRoot = path32__default.default.resolve(cwd);
19243
+ const workspaceDir = path32__default.default.join(projectRoot, WORKSPACE_DIR_NAME);
18809
19244
  return {
18810
19245
  projectRoot,
18811
19246
  workspaceDir,
18812
- manifestPath: path30__default.default.join(workspaceDir, WORKSPACE_MANIFEST_FILENAME)
19247
+ manifestPath: path32__default.default.join(workspaceDir, WORKSPACE_MANIFEST_FILENAME)
18813
19248
  };
18814
19249
  }
18815
19250
  function resolveInsideWorkspace(workspaceDir, relative) {
18816
- const base = path30__default.default.resolve(workspaceDir);
18817
- const resolved = path30__default.default.resolve(base, relative);
18818
- const rel = path30__default.default.relative(base, resolved);
18819
- if (rel === "" || rel === "." || !rel.startsWith("..") && !path30__default.default.isAbsolute(rel)) {
19251
+ const base = path32__default.default.resolve(workspaceDir);
19252
+ const resolved = path32__default.default.resolve(base, relative);
19253
+ const rel = path32__default.default.relative(base, resolved);
19254
+ if (rel === "" || rel === "." || !rel.startsWith("..") && !path32__default.default.isAbsolute(rel)) {
18820
19255
  return resolved;
18821
19256
  }
18822
19257
  throw new Error(
@@ -18885,7 +19320,7 @@ async function createWorkspace(options = {}) {
18885
19320
  created = false;
18886
19321
  adopted = true;
18887
19322
  } else {
18888
- const project = options.project?.trim() || path30__default.default.basename(location.projectRoot) || "workspace";
19323
+ const project = options.project?.trim() || path32__default.default.basename(location.projectRoot) || "workspace";
18889
19324
  const traceDirs = detectedExistingTraces ? ["runs", "."] : ["runs"];
18890
19325
  manifest = createDefaultWorkspaceManifest({
18891
19326
  project,
@@ -19024,7 +19459,7 @@ async function doctorWorkspace(location) {
19024
19459
  const abs = resolveInsideWorkspace(location.workspaceDir, rel);
19025
19460
  for (const file of await listJsonl(abs)) {
19026
19461
  try {
19027
- const s = await promises.stat(path30__default.default.join(abs, file));
19462
+ const s = await promises.stat(path32__default.default.join(abs, file));
19028
19463
  newestTraceMtime = Math.max(newestTraceMtime, s.mtimeMs);
19029
19464
  } catch {
19030
19465
  checks2.push({ id: "trace-readability", status: "warn", message: `cannot stat ${rel}/${file}` });
@@ -19072,7 +19507,7 @@ async function cleanWorkspace(location, manifest, options = {}) {
19072
19507
  const relPath = `${rel}/${entry}`;
19073
19508
  removed.push(relPath);
19074
19509
  if (!dryRun) {
19075
- await promises.rm(path30__default.default.join(abs, entry), { recursive: true, force: true });
19510
+ await promises.rm(path32__default.default.join(abs, entry), { recursive: true, force: true });
19076
19511
  }
19077
19512
  }
19078
19513
  }
@@ -19081,7 +19516,7 @@ async function cleanWorkspace(location, manifest, options = {}) {
19081
19516
 
19082
19517
  // packages/viewer/src/workspace-data.ts
19083
19518
  async function loadWorkspaceViewerData(options) {
19084
- const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
19519
+ const cwd = path32__default.default.resolve(options.cwd ?? process.cwd());
19085
19520
  const location = resolveWorkspaceLocation(cwd);
19086
19521
  const manifestRead = await readWorkspaceManifestFile(location);
19087
19522
  if (!manifestRead.ok || manifestRead.manifest === void 0) {
@@ -19094,7 +19529,7 @@ async function loadWorkspaceViewerData(options) {
19094
19529
  const runs = [];
19095
19530
  for (const rel of manifestRead.manifest.traceDirs) {
19096
19531
  const traceDir = resolveTraceDir({
19097
- dir: path30__default.default.join(location.workspaceDir, rel)
19532
+ dir: path32__default.default.join(location.workspaceDir, rel)
19098
19533
  });
19099
19534
  const td = new TraceDirectory({ dir: traceDir });
19100
19535
  const files = await td.list();
@@ -19108,7 +19543,7 @@ async function loadWorkspaceViewerData(options) {
19108
19543
  runId: meta2.runId,
19109
19544
  ...meta2.name !== void 0 ? { name: meta2.name } : {},
19110
19545
  status: meta2.status,
19111
- file: path30__default.default.basename(meta2.filePath)
19546
+ file: path32__default.default.basename(meta2.filePath)
19112
19547
  });
19113
19548
  }
19114
19549
  }
@@ -19119,8 +19554,8 @@ async function loadWorkspaceViewerData(options) {
19119
19554
  doctor,
19120
19555
  runs,
19121
19556
  bundleDirs: [
19122
- path30__default.default.join(location.workspaceDir, manifestRead.manifest.bundlesDir),
19123
- path30__default.default.join(location.workspaceDir, manifestRead.manifest.artifactsDir)
19557
+ path32__default.default.join(location.workspaceDir, manifestRead.manifest.bundlesDir),
19558
+ path32__default.default.join(location.workspaceDir, manifestRead.manifest.artifactsDir)
19124
19559
  ]
19125
19560
  };
19126
19561
  }
@@ -19183,7 +19618,7 @@ function createViewerServer(options = {}) {
19183
19618
  ok: true,
19184
19619
  readOnly: true,
19185
19620
  mode,
19186
- traceDir: path30__default.default.resolve(traceDir)
19621
+ traceDir: path32__default.default.resolve(traceDir)
19187
19622
  });
19188
19623
  }
19189
19624
  if (pathname === "/api/suite" && mode === "suite") {
@@ -19212,7 +19647,7 @@ function createViewerServer(options = {}) {
19212
19647
  runId: meta2.runId,
19213
19648
  name: meta2.name,
19214
19649
  status: meta2.status,
19215
- file: path30__default.default.basename(meta2.filePath),
19650
+ file: path32__default.default.basename(meta2.filePath),
19216
19651
  startedAt: meta2.startedAt,
19217
19652
  durationMs: meta2.durationMs
19218
19653
  }))
@@ -19329,7 +19764,7 @@ function startViewerServer(options = {}) {
19329
19764
  resolve({
19330
19765
  host,
19331
19766
  port: resolvedPort,
19332
- traceDir: path30__default.default.resolve(traceDir),
19767
+ traceDir: path32__default.default.resolve(traceDir),
19333
19768
  url: `http://${host}:${resolvedPort}/${modeQuery}`,
19334
19769
  mode
19335
19770
  });
@@ -19700,10 +20135,10 @@ async function evalRun(input3, options = {}) {
19700
20135
  diagnostics: []
19701
20136
  };
19702
20137
  }
19703
- function evidenceForRun(run, path41) {
19704
- return [{ runId: run.runId, ...path41 !== void 0 ? { path: path41 } : {} }];
20138
+ function evidenceForRun(run, path43) {
20139
+ return [{ runId: run.runId, ...path43 !== void 0 ? { path: path43 } : {} }];
19705
20140
  }
19706
- function evidenceForEvent(event, path41) {
20141
+ function evidenceForEvent(event, path43) {
19707
20142
  return [
19708
20143
  {
19709
20144
  runId: event.runId,
@@ -19711,7 +20146,7 @@ function evidenceForEvent(event, path41) {
19711
20146
  ...event.parentId !== void 0 ? { parentId: event.parentId } : {},
19712
20147
  kind: event.kind,
19713
20148
  name: event.name,
19714
- ...path41 !== void 0 ? { path: path41 } : {}
20149
+ ...path43 !== void 0 ? { path: path43 } : {}
19715
20150
  }
19716
20151
  ];
19717
20152
  }
@@ -19869,9 +20304,9 @@ function collectTextFields(nodes, keys, preferredKinds = []) {
19869
20304
  function tokenize(text) {
19870
20305
  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));
19871
20306
  }
19872
- function firstEvidence(fields, run, path41) {
20307
+ function firstEvidence(fields, run, path43) {
19873
20308
  const first = fields[0];
19874
- return first === void 0 ? evidenceForRun(run, path41) : evidenceForEvent(first.node.event, first.path);
20309
+ return first === void 0 ? evidenceForRun(run, path43) : evidenceForEvent(first.node.event, first.path);
19875
20310
  }
19876
20311
  function collectSourceIds(nodes, keys) {
19877
20312
  const wanted = keySet(keys);
@@ -20248,8 +20683,8 @@ function renderEvalMarkdown(result) {
20248
20683
  if (result.findings.length > 0) {
20249
20684
  lines.push("", "## Findings");
20250
20685
  for (const finding of result.findings) {
20251
- const path41 = finding.evidence[0]?.path;
20252
- lines.push(`- ${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}`);
20686
+ const path43 = finding.evidence[0]?.path;
20687
+ lines.push(`- ${finding.ruleId}: ${finding.message}${path43 ? ` (${path43})` : ""}`);
20253
20688
  }
20254
20689
  }
20255
20690
  return `${lines.join("\n")}
@@ -20296,7 +20731,7 @@ function asConfig2(value) {
20296
20731
  }
20297
20732
  async function loadConfig2(configPath) {
20298
20733
  if (configPath === void 0) return {};
20299
- const extension = path30__default.default.extname(configPath);
20734
+ const extension = path32__default.default.extname(configPath);
20300
20735
  if (TS_CONFIG_EXTENSIONS3.has(extension)) {
20301
20736
  throw new Error(
20302
20737
  "TypeScript eval configs require an explicit precompiled JavaScript config or future --config-loader support."
@@ -20305,7 +20740,7 @@ async function loadConfig2(configPath) {
20305
20740
  if (!CONFIG_EXTENSIONS3.has(extension)) {
20306
20741
  throw new Error("Unsupported eval config extension. Use .json, .js, .mjs, or .cjs.");
20307
20742
  }
20308
- const absolute = path30__default.default.resolve(configPath);
20743
+ const absolute = path32__default.default.resolve(configPath);
20309
20744
  if (extension === ".json") {
20310
20745
  const raw = await promises.readFile(absolute, "utf-8");
20311
20746
  return asConfig2(JSON.parse(raw));
@@ -20442,8 +20877,8 @@ function printHuman2(result) {
20442
20877
  console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
20443
20878
  }
20444
20879
  for (const finding of result.findings) {
20445
- const path41 = finding.evidence[0]?.path;
20446
- console.log(`- ${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}`);
20880
+ const path43 = finding.evidence[0]?.path;
20881
+ console.log(`- ${finding.ruleId}: ${finding.message}${path43 ? ` (${path43})` : ""}`);
20447
20882
  }
20448
20883
  }
20449
20884
  function readErrorResult2(error) {
@@ -20696,14 +21131,14 @@ function exitCodeFor3(result) {
20696
21131
  return 2;
20697
21132
  }
20698
21133
  function explainFinding(finding, blocksBundle) {
20699
- const path41 = finding.evidence[0]?.path ?? "(unknown path)";
21134
+ const path43 = finding.evidence[0]?.path ?? "(unknown path)";
20700
21135
  const category = finding.category ?? "structure";
20701
21136
  const confidence = finding.confidence ?? "medium";
20702
21137
  const detector = finding.detector ?? finding.ruleId;
20703
21138
  const action = finding.action ?? "review";
20704
21139
  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.";
20705
21140
  return [
20706
- ` Matched: detector=${detector}; path=${path41}; category=${category}`,
21141
+ ` Matched: detector=${detector}; path=${path43}; category=${category}`,
20707
21142
  ` Why: ${finding.message}`,
20708
21143
  ` Confidence: ${confidence}`,
20709
21144
  ` Redaction: ${redactionHint}`,
@@ -20745,9 +21180,9 @@ function printHuman3(result, explain = false) {
20745
21180
  console.log(`- ${diagnostic7.code}: ${diagnostic7.message}`);
20746
21181
  }
20747
21182
  for (const finding of result.findings) {
20748
- const path41 = finding.evidence[0]?.path;
21183
+ const path43 = finding.evidence[0]?.path;
20749
21184
  const taxonomy = finding.category !== void 0 || finding.confidence !== void 0 ? ` [${[finding.category, finding.confidence].filter(Boolean).join("/")}]` : "";
20750
- console.log(`- ${finding.ruleId}: ${finding.message}${path41 ? ` (${path41})` : ""}${taxonomy}`);
21185
+ console.log(`- ${finding.ruleId}: ${finding.message}${path43 ? ` (${path43})` : ""}${taxonomy}`);
20751
21186
  if (explain) {
20752
21187
  const blocks = finding.severity === "error" || finding.status === "fail";
20753
21188
  for (const line of explainFinding(finding, blocks)) {
@@ -20862,91 +21297,6 @@ function messageStartsWithDash(error) {
20862
21297
  return message.startsWith("--");
20863
21298
  }
20864
21299
  init_advanced();
20865
- function validateReporterArtifactPath(options) {
20866
- const outputDir = path30__default.default.resolve(options.outputDir);
20867
- const diagnostics = [];
20868
- const rawPath = options.relativePath;
20869
- if (rawPath.length === 0) {
20870
- diagnostics.push({
20871
- code: "artifact_path_empty",
20872
- severity: "error",
20873
- message: "Reporter artifact path must not be empty."
20874
- });
20875
- return { ok: false, outputDir, diagnostics };
20876
- }
20877
- if (rawPath.includes("\0")) {
20878
- diagnostics.push({
20879
- code: "invalid_artifact_path",
20880
- severity: "error",
20881
- message: "Reporter artifact path must not contain null bytes.",
20882
- target: rawPath
20883
- });
20884
- return { ok: false, outputDir, diagnostics };
20885
- }
20886
- if (path30__default.default.isAbsolute(rawPath) || path30__default.default.win32.isAbsolute(rawPath)) {
20887
- diagnostics.push({
20888
- code: "artifact_path_absolute",
20889
- severity: "error",
20890
- message: "Reporter artifact path must be relative.",
20891
- target: rawPath
20892
- });
20893
- return { ok: false, outputDir, diagnostics };
20894
- }
20895
- const normalized = path30__default.default.posix.normalize(rawPath.replace(/\\/g, "/"));
20896
- const segments = normalized.split("/");
20897
- if (normalized === "." || normalized.startsWith("../") || segments.some((segment) => segment === "..")) {
20898
- diagnostics.push({
20899
- code: "artifact_path_escape",
20900
- severity: "error",
20901
- message: "Reporter artifact path must stay under the output directory.",
20902
- target: rawPath
20903
- });
20904
- return { ok: false, outputDir, diagnostics };
20905
- }
20906
- const absolutePath = path30__default.default.resolve(outputDir, normalized);
20907
- const relFromOutput = path30__default.default.relative(outputDir, absolutePath);
20908
- if (relFromOutput.length === 0 || relFromOutput.startsWith("..") || path30__default.default.isAbsolute(relFromOutput)) {
20909
- diagnostics.push({
20910
- code: "artifact_path_escape",
20911
- severity: "error",
20912
- message: "Reporter artifact path resolved outside the output directory.",
20913
- target: rawPath
20914
- });
20915
- return { ok: false, outputDir, diagnostics };
20916
- }
20917
- return {
20918
- ok: true,
20919
- outputDir,
20920
- relativePath: normalized,
20921
- absolutePath,
20922
- diagnostics
20923
- };
20924
- }
20925
- var EVIDENCE_CI_ARTIFACT_FILES = [
20926
- "evidence.html",
20927
- "evidence.json",
20928
- "check-results.json",
20929
- "trace.jsonl"
20930
- ];
20931
- function createEvidenceCiArtifacts(options) {
20932
- const profile = options.redactionProfile;
20933
- const prefix = options.relativeDir !== void 0 && options.relativeDir.trim() !== "" ? options.relativeDir.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "") : "";
20934
- const join = (name) => prefix === "" ? name : path30__default.default.posix.join(prefix, name);
20935
- const formatFor = (name) => {
20936
- if (name.endsWith(".html")) return "html";
20937
- if (name.endsWith(".jsonl")) return "jsonl";
20938
- return "json";
20939
- };
20940
- return EVIDENCE_CI_ARTIFACT_FILES.map((name) => ({
20941
- kind: "evidence",
20942
- path: join(name),
20943
- format: formatFor(name),
20944
- redactionProfile: profile,
20945
- title: `Evidence v2 ${name}`
20946
- }));
20947
- }
20948
-
20949
- // packages/cli/src/artifacts.ts
20950
21300
  var NOTE = "Generated locally by AgentInspect. Artifacts are best-effort summaries, not compliance or security certification.";
20951
21301
  var SAFETY_RULES = [
20952
21302
  createSafetyRawContentRule(),
@@ -21020,8 +21370,8 @@ function renderCheckSection(result) {
21020
21370
  `Diagnostics: ${result.diagnostics.length}`
21021
21371
  ];
21022
21372
  for (const finding of result.findings.slice(0, 10)) {
21023
- const path41 = finding.evidence[0]?.path ?? "(run)";
21024
- lines.push(`- ${finding.ruleId}: ${finding.message} (${path41})`);
21373
+ const path43 = finding.evidence[0]?.path ?? "(run)";
21374
+ lines.push(`- ${finding.ruleId}: ${finding.message} (${path43})`);
21025
21375
  }
21026
21376
  for (const diagnostic7 of result.diagnostics.slice(0, 10)) {
21027
21377
  lines.push(`- ${diagnostic7.code}: ${diagnostic7.message}`);
@@ -21099,8 +21449,8 @@ function renderHtml(trace, check, diff) {
21099
21449
  `;
21100
21450
  }
21101
21451
  async function writeArtifact(outputDir, relativePath, content, files) {
21102
- const outPath = path30__default.default.join(outputDir, relativePath);
21103
- await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
21452
+ const outPath = path32__default.default.join(outputDir, relativePath);
21453
+ await promises.mkdir(path32__default.default.dirname(outPath), { recursive: true });
21104
21454
  await promises.writeFile(outPath, content, "utf-8");
21105
21455
  files.push(relativePath);
21106
21456
  }
@@ -21129,7 +21479,7 @@ function shouldWriteEvidence(options, status) {
21129
21479
  return status === "unsafe" || status === "regression" || status === "unknown" || status === "warning";
21130
21480
  }
21131
21481
  async function artifactsCommand(target, options = {}, stdin = process.stdin) {
21132
- const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ? path30__default.default.resolve(options.outputDir.trim()) : "";
21482
+ const outputDir = options.outputDir !== void 0 && options.outputDir.trim() !== "" ? path32__default.default.resolve(options.outputDir.trim()) : "";
21133
21483
  if (outputDir === "") {
21134
21484
  console.error("--output-dir is required.");
21135
21485
  process.exitCode = 1;
@@ -21269,8 +21619,8 @@ async function artifactsCommand(target, options = {}, stdin = process.stdin) {
21269
21619
  }
21270
21620
  const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
21271
21621
  if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
21272
- await promises.mkdir(path30__default.default.dirname(path30__default.default.resolve(summaryTarget)), { recursive: true });
21273
- await promises.appendFile(path30__default.default.resolve(summaryTarget), `
21622
+ await promises.mkdir(path32__default.default.dirname(path32__default.default.resolve(summaryTarget)), { recursive: true });
21623
+ await promises.appendFile(path32__default.default.resolve(summaryTarget), `
21274
21624
  ${renderMarkdown(trace, check, diff)}`, "utf-8");
21275
21625
  }
21276
21626
  const manifestFiles = [...files, "manifest.json"].sort((a, b) => a.localeCompare(b));
@@ -21289,10 +21639,10 @@ ${renderMarkdown(trace, check, diff)}`, "utf-8");
21289
21639
  findings: diff?.findings.length ?? 0,
21290
21640
  diagnostics: diff?.diagnostics.length ?? 0
21291
21641
  },
21292
- ...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary: path30__default.default.resolve(summaryTarget) } : {},
21642
+ ...summaryTarget !== void 0 && summaryTarget.trim() !== "" ? { githubSummary: path32__default.default.resolve(summaryTarget) } : {},
21293
21643
  note: NOTE
21294
21644
  };
21295
- await promises.writeFile(path30__default.default.join(outputDir, "manifest.json"), writeJson3(manifest), "utf-8");
21645
+ await promises.writeFile(path32__default.default.join(outputDir, "manifest.json"), writeJson3(manifest), "utf-8");
21296
21646
  if (options.json === true) {
21297
21647
  console.log(writeJson3(manifest).trimEnd());
21298
21648
  } else {
@@ -21353,8 +21703,8 @@ async function resolveOutputDir(options, runIds, cwd, format) {
21353
21703
  const location = resolveWorkspaceLocation(cwd);
21354
21704
  const manifest = await readWorkspaceManifestFile(location);
21355
21705
  if (manifest.ok && manifest.manifest) {
21356
- const rel = path30__default.default.relative(location.workspaceDir, normalized);
21357
- if (!rel.startsWith("..") && !path30__default.default.isAbsolute(rel)) {
21706
+ const rel = path32__default.default.relative(location.workspaceDir, normalized);
21707
+ if (!rel.startsWith("..") && !path32__default.default.isAbsolute(rel)) {
21358
21708
  return resolveInsideWorkspace(location.workspaceDir, rel);
21359
21709
  }
21360
21710
  }
@@ -21370,7 +21720,7 @@ async function resolveOutputDir(options, runIds, cwd, format) {
21370
21720
  const label = runIds.length === 1 ? sanitizeBundleRunId(runIds[0]) : `multi-${runIds.length}`;
21371
21721
  const base2 = resolveInsideWorkspace(
21372
21722
  location.workspaceDir,
21373
- path30__default.default.join(manifest.manifest.bundlesDir, `bundle-${label}-${stamp}`)
21723
+ path32__default.default.join(manifest.manifest.bundlesDir, `bundle-${label}-${stamp}`)
21374
21724
  );
21375
21725
  return format === "zip" ? `${base2}.zip` : base2;
21376
21726
  }
@@ -21775,19 +22125,19 @@ async function bundleCommand(runIdArg, options = {}) {
21775
22125
  let sidecarDir = outputDir;
21776
22126
  if (outputDir.toLowerCase().endsWith(".html")) {
21777
22127
  htmlPath = outputDir;
21778
- sidecarDir = path30__default.default.dirname(outputDir);
22128
+ sidecarDir = path32__default.default.dirname(outputDir);
21779
22129
  } else {
21780
22130
  await promises.mkdir(outputDir, { recursive: true });
21781
- htmlPath = path30__default.default.join(outputDir, EVIDENCE_HTML_FILENAME);
22131
+ htmlPath = path32__default.default.join(outputDir, EVIDENCE_HTML_FILENAME);
21782
22132
  sidecarDir = outputDir;
21783
22133
  }
21784
22134
  await promises.mkdir(sidecarDir, { recursive: true });
21785
22135
  await promises.writeFile(htmlPath, htmlContent, "utf-8");
21786
- await promises.writeFile(path30__default.default.join(sidecarDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
22136
+ await promises.writeFile(path32__default.default.join(sidecarDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
21787
22137
  outputPath = htmlPath;
21788
22138
  } else if (format === "zip") {
21789
22139
  const zipPath = outputDir.toLowerCase().endsWith(".zip") ? outputDir : `${outputDir}.zip`;
21790
- const zipParent = path30__default.default.dirname(zipPath);
22140
+ const zipParent = path32__default.default.dirname(zipPath);
21791
22141
  await promises.mkdir(zipParent, { recursive: true });
21792
22142
  const entries = [
21793
22143
  ...[...packaged.entries()].map(([relativePath, content]) => ({
@@ -21803,10 +22153,10 @@ async function bundleCommand(runIdArg, options = {}) {
21803
22153
  await promises.mkdir(outputDir, { recursive: true });
21804
22154
  for (const [relativePath, content] of packaged.entries()) {
21805
22155
  const outPath = assertBundlePathContained(outputDir, relativePath);
21806
- await promises.mkdir(path30__default.default.dirname(outPath), { recursive: true });
22156
+ await promises.mkdir(path32__default.default.dirname(outPath), { recursive: true });
21807
22157
  await promises.writeFile(outPath, content, "utf-8");
21808
22158
  }
21809
- await promises.writeFile(path30__default.default.join(outputDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
22159
+ await promises.writeFile(path32__default.default.join(outputDir, EVIDENCE_MANIFEST_FILENAME), evidenceJson, "utf-8");
21810
22160
  if (!files.includes(EVIDENCE_MANIFEST_FILENAME)) {
21811
22161
  files.push(EVIDENCE_MANIFEST_FILENAME);
21812
22162
  }
@@ -21855,7 +22205,7 @@ function writeJson5(value) {
21855
22205
  `;
21856
22206
  }
21857
22207
  async function bundleVerifyCommand(targetPath, options = {}) {
21858
- const root = path30__default.default.resolve(targetPath.trim() || ".");
22208
+ const root = path32__default.default.resolve(targetPath.trim() || ".");
21859
22209
  const result = await verifyEvidenceDirectory(root, {
21860
22210
  unexpectedFiles: options.unexpected ?? "fail"
21861
22211
  });
@@ -21888,6 +22238,147 @@ async function bundleVerifyCommand(targetPath, options = {}) {
21888
22238
  process.exitCode = 1;
21889
22239
  }
21890
22240
  }
22241
+
22242
+ // packages/cli/src/bundle-open.ts
22243
+ init_advanced();
22244
+ function writeJson6(value) {
22245
+ return `${JSON.stringify(value, null, 2)}
22246
+ `;
22247
+ }
22248
+ async function resolveHtmlPath(root) {
22249
+ const candidates = [
22250
+ path32__default.default.join(root, "evidence.html"),
22251
+ root.toLowerCase().endsWith(".html") ? root : ""
22252
+ ].filter(Boolean);
22253
+ for (const candidate of candidates) {
22254
+ try {
22255
+ const info = await promises.stat(candidate);
22256
+ if (info.isFile()) return candidate;
22257
+ } catch {
22258
+ }
22259
+ }
22260
+ throw new Error(
22261
+ `No evidence.html found under ${root}. Pass a bundle directory or .html path.`
22262
+ );
22263
+ }
22264
+ function openLocalFile(filePath) {
22265
+ const fileUrl = url.pathToFileURL(filePath).href;
22266
+ const platform = process.platform;
22267
+ const command = platform === "darwin" ? "open" : platform === "win32" ? "cmd" : "xdg-open";
22268
+ const args = platform === "darwin" ? [filePath] : platform === "win32" ? ["/c", "start", "", filePath] : [filePath];
22269
+ return new Promise((resolve) => {
22270
+ try {
22271
+ const child = child_process.spawn(command, args, {
22272
+ detached: true,
22273
+ stdio: "ignore"
22274
+ });
22275
+ child.on("error", (error) => {
22276
+ resolve({
22277
+ ok: false,
22278
+ detail: `${error instanceof Error ? error.message : String(error)}; open manually: ${fileUrl}`
22279
+ });
22280
+ });
22281
+ child.unref();
22282
+ resolve({ ok: true, detail: fileUrl });
22283
+ } catch (error) {
22284
+ resolve({
22285
+ ok: false,
22286
+ detail: `${error instanceof Error ? error.message : String(error)}; open manually: ${fileUrl}`
22287
+ });
22288
+ }
22289
+ });
22290
+ }
22291
+ async function bundleOpenCommand(targetPath, options = {}) {
22292
+ const root = path32__default.default.resolve(targetPath.trim() || ".");
22293
+ try {
22294
+ await promises.access(root);
22295
+ } catch {
22296
+ const message = `Evidence path not found: ${root}`;
22297
+ if (options.json) {
22298
+ console.log(writeJson6({ ok: false, error: message }).trimEnd());
22299
+ } else {
22300
+ console.error(`[AgentInspect] ${message}`);
22301
+ }
22302
+ process.exitCode = 1;
22303
+ return;
22304
+ }
22305
+ let verifyRoot = root;
22306
+ try {
22307
+ const info = await promises.stat(root);
22308
+ if (info.isFile() && root.toLowerCase().endsWith(".html")) {
22309
+ verifyRoot = path32__default.default.dirname(root);
22310
+ }
22311
+ } catch {
22312
+ }
22313
+ if (options.skipVerify !== true) {
22314
+ const result = await verifyEvidenceDirectory(verifyRoot, {
22315
+ unexpectedFiles: "fail"
22316
+ });
22317
+ if (!result.ok) {
22318
+ if (options.json) {
22319
+ console.log(
22320
+ writeJson6({
22321
+ ok: false,
22322
+ error: "Evidence verify failed",
22323
+ root: result.root,
22324
+ issues: result.issues
22325
+ }).trimEnd()
22326
+ );
22327
+ } else {
22328
+ console.error(`Evidence verify: fail (${result.issues.length} issue(s))`);
22329
+ for (const issue of result.issues) {
22330
+ console.error(`- [${issue.severity}] ${issue.code}: ${issue.message}`);
22331
+ }
22332
+ console.error("Fix integrity issues or pass --skip-verify (not recommended).");
22333
+ }
22334
+ process.exitCode = 1;
22335
+ return;
22336
+ }
22337
+ }
22338
+ let htmlPath;
22339
+ try {
22340
+ htmlPath = await resolveHtmlPath(
22341
+ root.toLowerCase().endsWith(".html") ? path32__default.default.dirname(root) : root
22342
+ );
22343
+ if (root.toLowerCase().endsWith(".html")) {
22344
+ htmlPath = root;
22345
+ }
22346
+ } catch (error) {
22347
+ const message = error instanceof Error ? error.message : String(error);
22348
+ if (options.json) {
22349
+ console.log(writeJson6({ ok: false, error: message }).trimEnd());
22350
+ } else {
22351
+ console.error(`[AgentInspect] ${message}`);
22352
+ }
22353
+ process.exitCode = 1;
22354
+ return;
22355
+ }
22356
+ try {
22357
+ await promises.readFile(path32__default.default.join(path32__default.default.dirname(htmlPath), "evidence.json"), "utf-8");
22358
+ } catch {
22359
+ }
22360
+ const opened = await openLocalFile(htmlPath);
22361
+ if (options.json) {
22362
+ console.log(
22363
+ writeJson6({
22364
+ ok: opened.ok,
22365
+ path: htmlPath,
22366
+ opened: opened.ok,
22367
+ detail: opened.detail
22368
+ }).trimEnd()
22369
+ );
22370
+ } else if (opened.ok) {
22371
+ console.log(`Opened local Evidence: ${htmlPath}`);
22372
+ console.log(`URL: ${opened.detail}`);
22373
+ } else {
22374
+ console.error(`[AgentInspect] Could not open browser automatically.`);
22375
+ console.error(`Open this file locally: ${htmlPath}`);
22376
+ console.error(opened.detail);
22377
+ }
22378
+ if (!opened.ok) {
22379
+ process.exitCode = 0;
22380
+ }
22381
+ }
21891
22382
  var CLIENTS = [
21892
22383
  "cursor",
21893
22384
  "claude-code",
@@ -21948,24 +22439,24 @@ function resolveTargetPath(client, projectLocal) {
21948
22439
  if (projectLocal) {
21949
22440
  switch (client) {
21950
22441
  case "cursor":
21951
- return path30__default.default.join(".cursor", "mcp.json");
22442
+ return path32__default.default.join(".cursor", "mcp.json");
21952
22443
  case "claude-code":
21953
- return path30__default.default.join(".mcp.json");
22444
+ return path32__default.default.join(".mcp.json");
21954
22445
  case "codex":
21955
- return path30__default.default.join(".codex", "config.toml.json");
22446
+ return path32__default.default.join(".codex", "config.toml.json");
21956
22447
  case "gemini":
21957
- return path30__default.default.join(".gemini", "settings.json");
22448
+ return path32__default.default.join(".gemini", "settings.json");
21958
22449
  }
21959
22450
  }
21960
22451
  switch (client) {
21961
22452
  case "cursor":
21962
- return path30__default.default.join("~", ".cursor", "mcp.json");
22453
+ return path32__default.default.join("~", ".cursor", "mcp.json");
21963
22454
  case "claude-code":
21964
- return path30__default.default.join("~", ".claude.json");
22455
+ return path32__default.default.join("~", ".claude.json");
21965
22456
  case "codex":
21966
- return path30__default.default.join("~", ".codex", "config.toml");
22457
+ return path32__default.default.join("~", ".codex", "config.toml");
21967
22458
  case "gemini":
21968
- return path30__default.default.join("~", ".gemini", "settings.json");
22459
+ return path32__default.default.join("~", ".gemini", "settings.json");
21969
22460
  }
21970
22461
  }
21971
22462
  async function mcpConfigureCommand(options) {
@@ -21989,8 +22480,8 @@ async function mcpConfigureCommand(options) {
21989
22480
  ];
21990
22481
  let wrote = false;
21991
22482
  if (!dryRun && projectLocal) {
21992
- const abs = path30__default.default.resolve(targetPath);
21993
- await promises.mkdir(path30__default.default.dirname(abs), { recursive: true });
22483
+ const abs = path32__default.default.resolve(targetPath);
22484
+ await promises.mkdir(path32__default.default.dirname(abs), { recursive: true });
21994
22485
  await promises.writeFile(abs, `${JSON.stringify(config, null, 2)}
21995
22486
  `, "utf8");
21996
22487
  wrote = true;
@@ -22038,7 +22529,7 @@ function stable8(value) {
22038
22529
  Object.keys(record).sort((a, b) => a.localeCompare(b)).map((key) => [key, stable8(record[key])])
22039
22530
  );
22040
22531
  }
22041
- function writeJson6(value) {
22532
+ function writeJson7(value) {
22042
22533
  return `${JSON.stringify(stable8(value), null, 2)}
22043
22534
  `;
22044
22535
  }
@@ -22150,23 +22641,23 @@ function readManifestDocument(value) {
22150
22641
  };
22151
22642
  }
22152
22643
  function cwdRelative(filePath) {
22153
- const relative = path30__default.default.relative(process.cwd(), path30__default.default.resolve(filePath)).replace(/\\/g, "/");
22154
- if (relative === "" || relative.startsWith("../") || path30__default.default.isAbsolute(relative)) {
22155
- return path30__default.default.basename(filePath);
22644
+ const relative = path32__default.default.relative(process.cwd(), path32__default.default.resolve(filePath)).replace(/\\/g, "/");
22645
+ if (relative === "" || relative.startsWith("../") || path32__default.default.isAbsolute(relative)) {
22646
+ return path32__default.default.basename(filePath);
22156
22647
  }
22157
22648
  return relative;
22158
22649
  }
22159
22650
  async function readReporterManifest(filePath) {
22160
- const absolute = path30__default.default.resolve(filePath);
22651
+ const absolute = path32__default.default.resolve(filePath);
22161
22652
  const raw = await promises.readFile(absolute, "utf-8");
22162
22653
  const document = readManifestDocument(JSON.parse(raw));
22163
22654
  const manifest = document.manifest;
22164
22655
  const results = manifest.results.map((result) => ({
22165
22656
  testId: safeText(result.testId),
22166
22657
  name: safeText(result.name),
22167
- ...result.file === void 0 ? {} : { file: safeText(path30__default.default.basename(result.file)) },
22658
+ ...result.file === void 0 ? {} : { file: safeText(path32__default.default.basename(result.file)) },
22168
22659
  status: result.status,
22169
- ...result.tracePath === void 0 ? {} : { tracePath: safeText(path30__default.default.basename(result.tracePath)) },
22660
+ ...result.tracePath === void 0 ? {} : { tracePath: safeText(path32__default.default.basename(result.tracePath)) },
22170
22661
  artifacts: result.artifacts,
22171
22662
  diagnostics: result.diagnostics
22172
22663
  }));
@@ -22305,20 +22796,20 @@ async function ciSummaryCommand(manifestPaths, options = {}) {
22305
22796
  return;
22306
22797
  }
22307
22798
  const markdown = renderMarkdown2(result);
22308
- const outputPath = options.output !== void 0 && options.output.trim() !== "" ? path30__default.default.resolve(options.output.trim()) : void 0;
22799
+ const outputPath = options.output !== void 0 && options.output.trim() !== "" ? path32__default.default.resolve(options.output.trim()) : void 0;
22309
22800
  if (outputPath !== void 0) {
22310
- await promises.mkdir(path30__default.default.dirname(outputPath), { recursive: true });
22801
+ await promises.mkdir(path32__default.default.dirname(outputPath), { recursive: true });
22311
22802
  await promises.writeFile(outputPath, markdown, "utf-8");
22312
22803
  }
22313
22804
  const summaryTarget = options.githubSummary ?? process.env.GITHUB_STEP_SUMMARY;
22314
22805
  if (summaryTarget !== void 0 && summaryTarget.trim() !== "") {
22315
- const summaryPath = path30__default.default.resolve(summaryTarget);
22316
- await promises.mkdir(path30__default.default.dirname(summaryPath), { recursive: true });
22806
+ const summaryPath = path32__default.default.resolve(summaryTarget);
22807
+ await promises.mkdir(path32__default.default.dirname(summaryPath), { recursive: true });
22317
22808
  await promises.appendFile(summaryPath, `
22318
22809
  ${markdown}`, "utf-8");
22319
22810
  }
22320
22811
  if (options.json === true) {
22321
- console.log(writeJson6(result).trimEnd());
22812
+ console.log(writeJson7(result).trimEnd());
22322
22813
  } else if (outputPath !== void 0) {
22323
22814
  console.log(`Wrote AgentInspect CI summary to ${outputPath}`);
22324
22815
  console.log(`Status: ${result.status}`);
@@ -22456,7 +22947,7 @@ console.log("Trace written to .agent-inspect/");
22456
22947
  `;
22457
22948
  }
22458
22949
  }
22459
- function githubWorkflowTemplate() {
22950
+ function githubWorkflowTemplate(demoPath) {
22460
22951
  return `name: AgentInspect artifacts
22461
22952
 
22462
22953
  on:
@@ -22473,19 +22964,32 @@ jobs:
22473
22964
  with:
22474
22965
  node-version: "22"
22475
22966
  - run: npm ci
22476
- - run: npm test
22477
- - name: Upload AgentInspect traces
22967
+ - name: Run deterministic agent fixture
22968
+ run: node ${demoPath}
22969
+ - name: Trajectory check with Evidence on failure
22970
+ run: >
22971
+ npx --yes agent-inspect check --dir .agent-inspect
22972
+ --preset trajectory
22973
+ --evidence-on fail
22974
+ --evidence-profile share
22975
+ --evidence-format directory
22976
+ - name: Verify share safety
22977
+ if: always()
22978
+ run: npx --yes agent-inspect verify-safe . --dir .agent-inspect
22979
+ - name: Upload AgentInspect traces and Evidence
22478
22980
  if: always()
22479
22981
  uses: actions/upload-artifact@v4
22480
22982
  with:
22481
22983
  name: agent-inspect-traces
22482
- path: .agent-inspect/**/*.jsonl
22984
+ path: |
22985
+ .agent-inspect/**/*.jsonl
22986
+ .agent-inspect/evidence/**
22483
22987
  if-no-files-found: ignore
22484
22988
  `;
22485
22989
  }
22486
22990
  async function planInit(options = {}) {
22487
22991
  const framework = normalizeFramework(options.framework);
22488
- const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
22992
+ const cwd = path32__default.default.resolve(options.cwd ?? process.cwd());
22489
22993
  const demoPath = framework === "custom" ? "examples/agent-inspect-demo.mjs" : `examples/agent-inspect-${framework}-demo.mjs`;
22490
22994
  const candidates = [
22491
22995
  { rel: CONFIG_FILE, content: configTemplate(framework) },
@@ -22495,12 +22999,12 @@ async function planInit(options = {}) {
22495
22999
  if (options.ci === "github") {
22496
23000
  candidates.push({
22497
23001
  rel: ".github/workflows/agent-inspect-artifacts.yml",
22498
- content: githubWorkflowTemplate()
23002
+ content: githubWorkflowTemplate(demoPath)
22499
23003
  });
22500
23004
  }
22501
23005
  const files = [];
22502
23006
  for (const candidate of candidates) {
22503
- const abs = path30__default.default.join(cwd, candidate.rel);
23007
+ const abs = path32__default.default.join(cwd, candidate.rel);
22504
23008
  try {
22505
23009
  await promises.access(abs);
22506
23010
  files.push({
@@ -22521,20 +23025,21 @@ async function writePlannedFiles(plan, cwd, options) {
22521
23025
  if (entry.action === "skip") {
22522
23026
  continue;
22523
23027
  }
22524
- const abs = path30__default.default.join(cwd, entry.path);
23028
+ const abs = path32__default.default.join(cwd, entry.path);
22525
23029
  if (options.dryRun) {
22526
23030
  written.push(entry.path);
22527
23031
  continue;
22528
23032
  }
22529
- await promises.mkdir(path30__default.default.dirname(abs), { recursive: true });
22530
- const content = entry.path === CONFIG_FILE ? configTemplate(plan.framework) : entry.path === GITKEEP ? "" : entry.path.endsWith(".yml") ? githubWorkflowTemplate() : demoTemplate(plan.framework);
23033
+ await promises.mkdir(path32__default.default.dirname(abs), { recursive: true });
23034
+ const demoPath = plan.framework === "custom" ? "examples/agent-inspect-demo.mjs" : `examples/agent-inspect-${plan.framework}-demo.mjs`;
23035
+ const content = entry.path === CONFIG_FILE ? configTemplate(plan.framework) : entry.path === GITKEEP ? "" : entry.path.endsWith(".yml") ? githubWorkflowTemplate(demoPath) : demoTemplate(plan.framework);
22531
23036
  await promises.writeFile(abs, content, "utf-8");
22532
23037
  written.push(entry.path);
22533
23038
  }
22534
23039
  return written;
22535
23040
  }
22536
23041
  async function initCommand(options = {}) {
22537
- const cwd = path30__default.default.resolve(options.cwd ?? process.cwd());
23042
+ const cwd = path32__default.default.resolve(options.cwd ?? process.cwd());
22538
23043
  try {
22539
23044
  const plan = await planInit({ ...options, cwd });
22540
23045
  const toWrite = plan.files.filter((file) => file.action === "create").map((f) => f.path);
@@ -22626,7 +23131,7 @@ function envCheck(name, optional = true) {
22626
23131
  };
22627
23132
  }
22628
23133
  async function traceDirWritable(traceDir) {
22629
- const resolved = path30__default.default.resolve(traceDir);
23134
+ const resolved = path32__default.default.resolve(traceDir);
22630
23135
  try {
22631
23136
  await promises.mkdir(resolved, { recursive: true });
22632
23137
  await promises.access(resolved, promises.constants.W_OK);
@@ -22647,10 +23152,10 @@ async function traceDirWritable(traceDir) {
22647
23152
  }
22648
23153
  }
22649
23154
  function readPackageVersionNearEntry(entryPath, packageName) {
22650
- let dir = path30__default.default.dirname(path30__default.default.resolve(entryPath));
22651
- const { root } = path30__default.default.parse(dir);
23155
+ let dir = path32__default.default.dirname(path32__default.default.resolve(entryPath));
23156
+ const { root } = path32__default.default.parse(dir);
22652
23157
  while (true) {
22653
- const candidate = path30__default.default.join(dir, "package.json");
23158
+ const candidate = path32__default.default.join(dir, "package.json");
22654
23159
  if (fs.existsSync(candidate)) {
22655
23160
  try {
22656
23161
  const pkg = JSON.parse(fs.readFileSync(candidate, "utf8"));
@@ -22661,14 +23166,14 @@ function readPackageVersionNearEntry(entryPath, packageName) {
22661
23166
  }
22662
23167
  }
22663
23168
  if (dir === root) break;
22664
- const parent = path30__default.default.dirname(dir);
23169
+ const parent = path32__default.default.dirname(dir);
22665
23170
  if (parent === dir) break;
22666
23171
  dir = parent;
22667
23172
  }
22668
23173
  return void 0;
22669
23174
  }
22670
23175
  function resolveInstalledPackage(cwd, name) {
22671
- const require2 = module$1.createRequire(path30__default.default.join(cwd, "package.json"));
23176
+ const require2 = module$1.createRequire(path32__default.default.join(cwd, "package.json"));
22672
23177
  try {
22673
23178
  const entry = require2.resolve(name);
22674
23179
  let version2;
@@ -22766,7 +23271,7 @@ function versionMismatchCheck(cwd) {
22766
23271
  };
22767
23272
  }
22768
23273
  async function runDoctorChecks(options = {}) {
22769
- const cwd = path30__default.default.resolve(options.cwd ?? process3__default.default.cwd());
23274
+ const cwd = path32__default.default.resolve(options.cwd ?? process3__default.default.cwd());
22770
23275
  const traceDir = options.traceDir?.trim() || process3__default.default.env.AGENT_INSPECT_TRACE_DIR?.trim() || ".agent-inspect";
22771
23276
  const checks2 = [
22772
23277
  nodeVersionCheck(),
@@ -23006,7 +23511,7 @@ function parsePluginManifest(input3) {
23006
23511
  };
23007
23512
  }
23008
23513
  async function readPluginManifestFile(packageDir) {
23009
- const manifestPath = path30__default.default.join(packageDir, PLUGIN_MANIFEST_FILENAME);
23514
+ const manifestPath = path32__default.default.join(packageDir, PLUGIN_MANIFEST_FILENAME);
23010
23515
  try {
23011
23516
  const raw = await promises.readFile(manifestPath, "utf8");
23012
23517
  const parsed = parsePluginManifest(JSON.parse(raw));
@@ -23081,7 +23586,7 @@ function createTraceDirectoryIndexer() {
23081
23586
  // packages/cli/src/plugins.ts
23082
23587
  async function readPackageName(packageDir) {
23083
23588
  try {
23084
- const raw = await promises.readFile(path30__default.default.join(packageDir, "package.json"), "utf8");
23589
+ const raw = await promises.readFile(path32__default.default.join(packageDir, "package.json"), "utf8");
23085
23590
  const parsed = JSON.parse(raw);
23086
23591
  return typeof parsed.name === "string" ? parsed.name : void 0;
23087
23592
  } catch {
@@ -23089,7 +23594,7 @@ async function readPackageName(packageDir) {
23089
23594
  }
23090
23595
  }
23091
23596
  async function discoverPlugins(cwd = process.cwd()) {
23092
- const nodeModules = path30__default.default.join(cwd, "node_modules");
23597
+ const nodeModules = path32__default.default.join(cwd, "node_modules");
23093
23598
  const found = [];
23094
23599
  let entries;
23095
23600
  try {
@@ -23100,7 +23605,7 @@ async function discoverPlugins(cwd = process.cwd()) {
23100
23605
  for (const entry of entries.sort()) {
23101
23606
  if (entry.startsWith("@")) continue;
23102
23607
  if (!isPluginPackageName(entry)) continue;
23103
- const packageDir = path30__default.default.join(nodeModules, entry);
23608
+ const packageDir = path32__default.default.join(nodeModules, entry);
23104
23609
  const manifestRead = await readPluginManifestFile(packageDir);
23105
23610
  found.push({
23106
23611
  packageName: entry,
@@ -23113,7 +23618,7 @@ async function discoverPlugins(cwd = process.cwd()) {
23113
23618
  return found;
23114
23619
  }
23115
23620
  async function validatePluginPackage(packageRef, cwd = process.cwd()) {
23116
- const packageDir = path30__default.default.isAbsolute(packageRef) ? packageRef : path30__default.default.join(cwd, "node_modules", packageRef);
23621
+ const packageDir = path32__default.default.isAbsolute(packageRef) ? packageRef : path32__default.default.join(cwd, "node_modules", packageRef);
23117
23622
  const packageName = await readPackageName(packageDir) ?? packageRef;
23118
23623
  const errors = [];
23119
23624
  const warnings = [];
@@ -23190,7 +23695,7 @@ async function pluginsValidateCommand(packageRef, cwd) {
23190
23695
  init_advanced();
23191
23696
  var INDEX_FILENAME = ".agent-inspect-index.json";
23192
23697
  function traceIndexPath(traceDir) {
23193
- return path30__default.default.join(traceDir, INDEX_FILENAME);
23698
+ return path32__default.default.join(traceDir, INDEX_FILENAME);
23194
23699
  }
23195
23700
  function parseMaxEntries(raw) {
23196
23701
  if (raw === void 0 || raw.trim() === "") return void 0;
@@ -23336,7 +23841,7 @@ async function newestTraceMtimeMs2(traceDir) {
23336
23841
  for (const file of files) {
23337
23842
  if (!file.endsWith(".jsonl")) continue;
23338
23843
  try {
23339
- const s = await promises.stat(path30__default.default.join(traceDir, file));
23844
+ const s = await promises.stat(path32__default.default.join(traceDir, file));
23340
23845
  if (s.mtimeMs > newest) newest = s.mtimeMs;
23341
23846
  } catch {
23342
23847
  }
@@ -23591,11 +24096,11 @@ function printJson5(value) {
23591
24096
  console.log(JSON.stringify(value, null, 2));
23592
24097
  }
23593
24098
  function resolveCwd(options) {
23594
- return path30__default.default.resolve(options.cwd ?? process.cwd());
24099
+ return path32__default.default.resolve(options.cwd ?? process.cwd());
23595
24100
  }
23596
24101
  async function suiteInitCommand(options = {}) {
23597
24102
  const cwd = resolveCwd(options);
23598
- const configPath = path30__default.default.join(cwd, DEFAULT_CONFIG_FILENAME);
24103
+ const configPath = path32__default.default.join(cwd, DEFAULT_CONFIG_FILENAME);
23599
24104
  const template = options.template?.trim();
23600
24105
  const suiteConfig = template !== void 0 && template !== "" ? resolveSuiteTemplate(template) : defaultSuiteConfigTemplate();
23601
24106
  if (options.dryRun) {
@@ -23714,13 +24219,13 @@ async function suiteListCommand(options = {}) {
23714
24219
  }
23715
24220
  async function writeSuiteArtifact(result, configOutputDir, options) {
23716
24221
  const cwd = resolveCwd(options);
23717
- const outputDir = path30__default.default.resolve(
24222
+ const outputDir = path32__default.default.resolve(
23718
24223
  cwd,
23719
24224
  options.output ?? configOutputDir ?? DEFAULT_SUITE_ARTIFACTS_DIR
23720
24225
  );
23721
24226
  await promises.mkdir(outputDir, { recursive: true });
23722
24227
  const stamp = result.startedAt.replace(/[:.]/g, "-");
23723
- const filePath = path30__default.default.join(outputDir, `${result.suiteName}-${stamp}.json`);
24228
+ const filePath = path32__default.default.join(outputDir, `${result.suiteName}-${stamp}.json`);
23724
24229
  await promises.writeFile(filePath, `${JSON.stringify(result, null, 2)}
23725
24230
  `, "utf-8");
23726
24231
  return filePath;
@@ -23778,7 +24283,7 @@ async function loadSuiteResultFromInput(options) {
23778
24283
  if (options.input === void 0 || options.input.trim() === "") {
23779
24284
  throw new Error("Pass --input <suite-run.json> from a prior suite run.");
23780
24285
  }
23781
- const inputPath = path30__default.default.resolve(cwd, options.input.trim());
24286
+ const inputPath = path32__default.default.resolve(cwd, options.input.trim());
23782
24287
  const raw = await promises.readFile(inputPath, "utf-8");
23783
24288
  return JSON.parse(raw);
23784
24289
  }
@@ -23815,9 +24320,9 @@ function normalizeMetrics2(raw) {
23815
24320
  }
23816
24321
  async function writeArtifacts(result, outputDir) {
23817
24322
  await promises.mkdir(outputDir, { recursive: true });
23818
- const jsonPath = path30__default.default.join(outputDir, "cohort-results.json");
23819
- const markdownPath = path30__default.default.join(outputDir, "cohort-summary.md");
23820
- const htmlPath = path30__default.default.join(outputDir, "cohort-report.html");
24323
+ const jsonPath = path32__default.default.join(outputDir, "cohort-results.json");
24324
+ const markdownPath = path32__default.default.join(outputDir, "cohort-summary.md");
24325
+ const htmlPath = path32__default.default.join(outputDir, "cohort-report.html");
23821
24326
  await promises.writeFile(jsonPath, `${renderCohortReport(result, { format: "json" })}
23822
24327
  `, "utf-8");
23823
24328
  await promises.writeFile(
@@ -23845,7 +24350,7 @@ async function cohortCommand(options = {}) {
23845
24350
  const format = options.format ?? (options.json ? "json" : "markdown");
23846
24351
  let artifacts;
23847
24352
  if (options.output !== void 0 && options.output.trim() !== "") {
23848
- artifacts = await writeArtifacts(result, path30__default.default.resolve(options.output.trim()));
24353
+ artifacts = await writeArtifacts(result, path32__default.default.resolve(options.output.trim()));
23849
24354
  }
23850
24355
  if (options.json || format === "json") {
23851
24356
  console.log(
@@ -23918,11 +24423,11 @@ function parseDuration2(value) {
23918
24423
  async function writeArtifacts2(result, outputDir) {
23919
24424
  await promises.mkdir(outputDir, { recursive: true });
23920
24425
  const paths = {
23921
- jsonPath: path30__default.default.join(outputDir, "gate-results.json"),
23922
- markdownPath: path30__default.default.join(outputDir, "gate-summary.md"),
23923
- htmlPath: path30__default.default.join(outputDir, "gate-report.html"),
23924
- junitPath: path30__default.default.join(outputDir, "junit.xml"),
23925
- githubPath: path30__default.default.join(outputDir, "github-step-summary.md")
24426
+ jsonPath: path32__default.default.join(outputDir, "gate-results.json"),
24427
+ markdownPath: path32__default.default.join(outputDir, "gate-summary.md"),
24428
+ htmlPath: path32__default.default.join(outputDir, "gate-report.html"),
24429
+ junitPath: path32__default.default.join(outputDir, "junit.xml"),
24430
+ githubPath: path32__default.default.join(outputDir, "github-step-summary.md")
23926
24431
  };
23927
24432
  await promises.writeFile(
23928
24433
  paths.jsonPath,
@@ -23990,7 +24495,57 @@ async function gateCommand(options = {}) {
23990
24495
  const result = await runGate(runs, gateOptions);
23991
24496
  let artifacts;
23992
24497
  if (options.output !== void 0 && options.output.trim() !== "") {
23993
- artifacts = await writeArtifacts2(result, path30__default.default.resolve(options.output.trim()));
24498
+ artifacts = await writeArtifacts2(result, path32__default.default.resolve(options.output.trim()));
24499
+ }
24500
+ const failed = !result.ok;
24501
+ if (shouldEmitEvidence(options.evidenceOn, failed)) {
24502
+ try {
24503
+ const runIds = runs.length > 0 ? runs.map((run) => run.runId) : result.suiteResult?.cases.map((item) => item.runId).filter((id) => typeof id === "string" && id.length > 0) ?? ["gate"];
24504
+ const sourceContents = /* @__PURE__ */ new Map();
24505
+ for (const run of runs) {
24506
+ if (run.filePath) {
24507
+ try {
24508
+ sourceContents.set(run.runId, await promises.readFile(run.filePath, "utf-8"));
24509
+ } catch {
24510
+ sourceContents.set(run.runId, "");
24511
+ }
24512
+ }
24513
+ }
24514
+ const label = runIds[0] ?? "gate";
24515
+ const outputDir = resolveEvidenceOutputDir(
24516
+ options.evidenceDir,
24517
+ `gate-${label}`
24518
+ );
24519
+ const written = await writeLocalEvidence({
24520
+ outputDir,
24521
+ runIds: runIds.length > 0 ? runIds : ["gate"],
24522
+ sourceContents,
24523
+ ...gateOptions.traceDir !== void 0 ? { dir: gateOptions.traceDir } : {},
24524
+ failed,
24525
+ checkResultsJson: `${JSON.stringify(
24526
+ {
24527
+ aggregateStatus: failed ? "UNSAFE" : "SAFE",
24528
+ gate: result
24529
+ },
24530
+ null,
24531
+ 2
24532
+ )}
24533
+ `,
24534
+ summaryText: renderGateReport(result, { format: "markdown" }),
24535
+ redactionProfile: parseEvidenceProfile(options.evidenceProfile),
24536
+ format: parseEvidenceFormat(options.evidenceFormat)
24537
+ });
24538
+ if (!options.json && format !== "json") {
24539
+ console.log(`Evidence: ${written}`);
24540
+ }
24541
+ if (artifacts !== void 0) {
24542
+ artifacts = { ...artifacts, evidence: written };
24543
+ }
24544
+ } catch (error) {
24545
+ console.error(
24546
+ `[AgentInspect] evidence package skipped: ${error instanceof Error ? error.message : String(error)}`
24547
+ );
24548
+ }
23994
24549
  }
23995
24550
  if (options.json || format === "json") {
23996
24551
  console.log(JSON.stringify({ ...result, artifacts: artifacts ?? null }, null, 2));
@@ -24167,6 +24722,23 @@ function createCliProgram() {
24167
24722
  "--circuit <rule>",
24168
24723
  "run optional circuit rules (repeatable): same-tool-repetition, max-retries, ...",
24169
24724
  (value, previous = []) => [...previous, value]
24725
+ ).addOption(
24726
+ new commander.Option("--preset <name>", "additive check preset").choices(["trajectory", "safety", "comprehensive"])
24727
+ ).addOption(
24728
+ new commander.Option(
24729
+ "--evidence-on <mode>",
24730
+ "write local Evidence v2 (fail=on failure, always, never; no upload)"
24731
+ ).choices(["fail", "always", "never"])
24732
+ ).option("--evidence-dir <path>", "local Evidence output directory or base path").addOption(
24733
+ new commander.Option(
24734
+ "--evidence-profile <profile>",
24735
+ "Evidence redaction profile (default share)"
24736
+ ).choices(["local", "share", "strict"])
24737
+ ).addOption(
24738
+ new commander.Option(
24739
+ "--evidence-format <format>",
24740
+ "Evidence output format (default directory)"
24741
+ ).choices(["directory", "html", "zip"])
24170
24742
  ).action((target, opts) => {
24171
24743
  runCommand(() => checkCommand(target, opts));
24172
24744
  });
@@ -24265,6 +24837,9 @@ function createCliProgram() {
24265
24837
  ).option("--json", "print deterministic JSON verify result").action((targetPath, opts) => {
24266
24838
  runCommand(() => bundleVerifyCommand(targetPath, opts));
24267
24839
  });
24840
+ bundleCmd.command("open").description("Verify then open local Evidence HTML in the platform browser (no network)").argument("<path>", "evidence/bundle directory or evidence.html path").option("--skip-verify", "skip integrity verify before open (not recommended)").option("--json", "print deterministic JSON open result").action((targetPath, opts) => {
24841
+ runCommand(() => bundleOpenCommand(targetPath, opts));
24842
+ });
24268
24843
  program.command("ci-summary").description("Summarize local reporter artifact manifests for CI").argument("<manifest...>", "reporter artifact manifest JSON files").option("-o, --output <path>", "write Markdown summary to a local file").option("--github-summary <path>", "append Markdown summary to this local file, e.g. GITHUB_STEP_SUMMARY").option("--json", "print deterministic JSON summary").action((manifest, opts) => {
24269
24844
  runCommand(() => ciSummaryCommand(manifest, opts));
24270
24845
  });
@@ -24544,7 +25119,22 @@ function createCliProgram() {
24544
25119
  ).option("--format <format>", "markdown, json, html, junit, or github", "markdown").option(
24545
25120
  "-o, --output <dir>",
24546
25121
  "write gate-results.json, gate-summary.md, gate-report.html, junit.xml, github-step-summary.md"
24547
- ).option("--json", "print deterministic JSON result").action((opts) => {
25122
+ ).option("--json", "print deterministic JSON result").addOption(
25123
+ new commander.Option(
25124
+ "--evidence-on <mode>",
25125
+ "write local Evidence v2 (fail=on failure, always, never; no upload)"
25126
+ ).choices(["fail", "always", "never"])
25127
+ ).option("--evidence-dir <path>", "local Evidence output directory or base path").addOption(
25128
+ new commander.Option(
25129
+ "--evidence-profile <profile>",
25130
+ "Evidence redaction profile (default share)"
25131
+ ).choices(["local", "share", "strict"])
25132
+ ).addOption(
25133
+ new commander.Option(
25134
+ "--evidence-format <format>",
25135
+ "Evidence output format (default directory)"
25136
+ ).choices(["directory", "html", "zip"])
25137
+ ).action((opts) => {
24548
25138
  runCommand(() => gateCommand(opts));
24549
25139
  });
24550
25140
  return program;
@@ -24554,9 +25144,9 @@ function isPrimaryModule() {
24554
25144
  if (!entry) return false;
24555
25145
  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)));
24556
25146
  try {
24557
- return fs.realpathSync(path30__default.default.resolve(entry)) === fs.realpathSync(path30__default.default.resolve(selfPath));
25147
+ return fs.realpathSync(path32__default.default.resolve(entry)) === fs.realpathSync(path32__default.default.resolve(selfPath));
24558
25148
  } catch {
24559
- return path30__default.default.resolve(entry) === path30__default.default.resolve(selfPath);
25149
+ return path32__default.default.resolve(entry) === path32__default.default.resolve(selfPath);
24560
25150
  }
24561
25151
  }
24562
25152
  if (isPrimaryModule()) {