agent-inspect 6.26.0 → 6.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/docs/BUNDLES.md +4 -1
  4. package/docs/LIMITATIONS.md +1 -1
  5. package/docs/SAFE-TRACE-SHARING.md +2 -0
  6. package/docs/TRACE-CONTRACTS.md +21 -3
  7. package/package.json +1 -1
  8. package/packages/cli/dist/{chunk-HPR2OJPU.mjs → chunk-JVQ4LTHR.mjs} +4317 -3803
  9. package/packages/cli/dist/chunk-JVQ4LTHR.mjs.map +1 -0
  10. package/packages/cli/dist/index.cjs +4541 -4005
  11. package/packages/cli/dist/index.cjs.map +1 -1
  12. package/packages/cli/dist/index.mjs +4 -4
  13. package/packages/cli/dist/index.mjs.map +1 -1
  14. package/packages/cli/dist/{src-J43ECFHC.mjs → src-M5J5YC5E.mjs} +3 -3
  15. package/packages/cli/dist/{src-J43ECFHC.mjs.map → src-M5J5YC5E.mjs.map} +1 -1
  16. package/packages/core/dist/advanced.cjs +3026 -2501
  17. package/packages/core/dist/advanced.cjs.map +1 -1
  18. package/packages/core/dist/advanced.d.cts +172 -16
  19. package/packages/core/dist/advanced.d.ts +172 -16
  20. package/packages/core/dist/advanced.mjs +362 -32
  21. package/packages/core/dist/advanced.mjs.map +1 -1
  22. package/packages/core/dist/checks.cjs +537 -152
  23. package/packages/core/dist/checks.cjs.map +1 -1
  24. package/packages/core/dist/checks.d.cts +9 -414
  25. package/packages/core/dist/checks.d.ts +9 -414
  26. package/packages/core/dist/checks.mjs +1 -1
  27. package/packages/core/dist/{chunk-LHSXRIYU.mjs → chunk-ME4WXYY3.mjs} +3609 -3224
  28. package/packages/core/dist/chunk-ME4WXYY3.mjs.map +1 -0
  29. package/packages/core/dist/{context-DOOT9GZ-.d.cts → context-DGMqxFpz.d.cts} +4 -4
  30. package/packages/core/dist/{context-DOX2-RjH.d.ts → context-DgcvkJ9t.d.ts} +4 -4
  31. package/packages/core/dist/diff.d.cts +3 -3
  32. package/packages/core/dist/diff.d.ts +3 -3
  33. package/packages/core/dist/exporters.d.cts +3 -3
  34. package/packages/core/dist/exporters.d.ts +3 -3
  35. package/packages/core/dist/{index-CtK_p-ps.d.ts → index-BOA1AeEU.d.ts} +473 -6
  36. package/packages/core/dist/{index-D72DPqAF.d.ts → index-BzyNPfLm.d.ts} +2 -2
  37. package/packages/core/dist/{index-DLLz9sce.d.cts → index-C6bCIbFO.d.cts} +2 -2
  38. package/packages/core/dist/{index-CR4CCRqP.d.cts → index-DVetZwGG.d.cts} +473 -6
  39. package/packages/core/dist/index.d.cts +7 -7
  40. package/packages/core/dist/index.d.ts +7 -7
  41. package/packages/core/dist/{inspect-event-DRthdZlf.d.cts → inspect-event-CDqjcrG_.d.cts} +1 -1
  42. package/packages/core/dist/{inspect-event-DRthdZlf.d.ts → inspect-event-CDqjcrG_.d.ts} +1 -1
  43. package/packages/core/dist/{log-config-CFlIJHTf.d.cts → log-config-DcjV8ZjF.d.cts} +1 -1
  44. package/packages/core/dist/{log-config-OZRfpHED.d.ts → log-config-N_c5AE09.d.ts} +1 -1
  45. package/packages/core/dist/logs.d.cts +3 -3
  46. package/packages/core/dist/logs.d.ts +3 -3
  47. package/packages/core/dist/{persisted-inspect-event-BVucFVrP.d.ts → persisted-inspect-event-CbaRYpbw.d.ts} +1 -1
  48. package/packages/core/dist/{persisted-inspect-event-CVZWZldL.d.cts → persisted-inspect-event-DiJ0I_vi.d.cts} +1 -1
  49. package/packages/core/dist/persisted.d.cts +5 -5
  50. package/packages/core/dist/persisted.d.ts +5 -5
  51. package/packages/core/dist/readers.d.cts +3 -3
  52. package/packages/core/dist/readers.d.ts +3 -3
  53. package/packages/core/dist/{types-B562HgN_.d.cts → types-BA_IOdg4.d.cts} +1 -1
  54. package/packages/core/dist/{types-B562HgN_.d.ts → types-BA_IOdg4.d.ts} +1 -1
  55. package/packages/core/dist/{types-VzKihKQo.d.cts → types-wXuxMUop.d.cts} +2 -2
  56. package/packages/core/dist/{types-Bx3mEZ04.d.ts → types-xv9bSgOK.d.ts} +2 -2
  57. package/packages/core/dist/writers.d.cts +2 -2
  58. package/packages/core/dist/writers.d.ts +2 -2
  59. package/packages/cli/dist/chunk-HPR2OJPU.mjs.map +0 -1
  60. package/packages/core/dist/chunk-LHSXRIYU.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
- import { extractSessionWorkflowMetadata, sessionKeyForRun, runTraceChecks, createRunStatusRule, createToolUsageRule, createRunDurationRule, createLlmUsageRule, createObservedOutcomeRule } from './chunk-LHSXRIYU.mjs';
2
- export { extractSessionWorkflowMetadata, sessionKeyForRun } from './chunk-LHSXRIYU.mjs';
1
+ import { extractSessionWorkflowMetadata, sessionKeyForRun, defineTraceContract, runTraceChecks, createRunStatusRule, createToolUsageRule, createRunDurationRule, createLlmUsageRule, createObservedOutcomeRule } from './chunk-ME4WXYY3.mjs';
2
+ export { extractSessionWorkflowMetadata, sessionKeyForRun } from './chunk-ME4WXYY3.mjs';
3
3
  export { MAX_TERMINAL_DEPTH, MAX_TERMINAL_NAME_LENGTH, TERMINAL_INDENT, TraceDirectory, createInspector, createInspectorRuntime, formatTerminalName, getCurrentContext, getCurrentCorrelationMetadata, getCurrentDepth, getCurrentRunId, getCurrentRunName, getCurrentStepId, getIndent, getParentStepId, getTraceDirFromContext, getTraceSafetyFromContext, hasActiveContext, isAgentInspectEnabled, isSilentContext, maybeInspectRun, printError, printFailedAt, printRunComplete, printRunStart, printStepComplete, printStepStart, renderErrorLine, renderRunSummary, renderStepLine, resolveTraceDir, runWithContext, runWithStepContext } from './chunk-WGDSM37E.mjs';
4
4
  import { buildRunTimeline, filterTraces, extractMetadata, buildRunSummary } from './chunk-JBNRJLIV.mjs';
5
5
  export { buildRunSummary, buildRunTimeline, buildRunWhatSummary, buildTraceStats, extractMetadata, filterTraces, formatStepLabel, renderRunWhat, renderTimeline, renderTraceStats } from './chunk-JBNRJLIV.mjs';
@@ -22,7 +22,7 @@ import { persistedInspectEventsToTraceEvents } from './chunk-P366CCL2.mjs';
22
22
  import './chunk-7TGZLWEE.mjs';
23
23
  import { createReadStream } from 'fs';
24
24
  import { createInterface } from 'readline';
25
- import path from 'path';
25
+ import path3 from 'path';
26
26
  import { createHash } from 'crypto';
27
27
  import { stat, readFile, access, readdir } from 'fs/promises';
28
28
  import { pathToFileURL } from 'url';
@@ -1719,7 +1719,7 @@ function buildBundleSummaryMarkdown(parts) {
1719
1719
  }
1720
1720
  function sanitizeBundleRunId(runId) {
1721
1721
  let safe = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "run_unknown";
1722
- safe = path.basename(safe);
1722
+ safe = path3.basename(safe);
1723
1723
  safe = safe.replace(/[^a-zA-Z0-9._-]+/g, "_");
1724
1724
  if (safe === "" || safe === "." || safe === "..") {
1725
1725
  safe = "run_unknown";
@@ -1729,12 +1729,12 @@ function sanitizeBundleRunId(runId) {
1729
1729
  function bundleRunAssetRelativePath(runId, extension) {
1730
1730
  const safe = sanitizeBundleRunId(runId);
1731
1731
  const ext = extension.startsWith(".") ? extension : `.${extension}`;
1732
- return path.posix.join("assets", "runs", `${safe}${ext}`);
1732
+ return path3.posix.join("assets", "runs", `${safe}${ext}`);
1733
1733
  }
1734
1734
  function assertBundlePathContained(outputDir, relativePath) {
1735
- const base = path.resolve(outputDir);
1736
- const resolved = path.resolve(base, relativePath);
1737
- if (resolved !== base && !resolved.startsWith(base + path.sep)) {
1735
+ const base = path3.resolve(outputDir);
1736
+ const resolved = path3.resolve(base, relativePath);
1737
+ if (resolved !== base && !resolved.startsWith(base + path3.sep)) {
1738
1738
  throw new Error(`Bundle path escapes output directory: ${relativePath}`);
1739
1739
  }
1740
1740
  return resolved;
@@ -1744,7 +1744,7 @@ function normalizeBundleOutputPath(out, options) {
1744
1744
  if (trimmed === "") {
1745
1745
  throw new Error("--out requires a non-empty path.");
1746
1746
  }
1747
- const resolved = path.resolve(trimmed);
1747
+ const resolved = path3.resolve(trimmed);
1748
1748
  if (options?.preserveZipExtension !== true && resolved.toLowerCase().endsWith(".zip")) {
1749
1749
  return resolved.slice(0, -4);
1750
1750
  }
@@ -1753,13 +1753,14 @@ function normalizeBundleOutputPath(out, options) {
1753
1753
  function defaultBundleOutputPath(runIds) {
1754
1754
  const label = runIds.length === 1 ? sanitizeBundleRunId(runIds[0]) : `multi-${runIds.length}`;
1755
1755
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
1756
- return path.resolve(`agent-inspect-bundle-${label}-${stamp}`);
1756
+ return path3.resolve(`agent-inspect-bundle-${label}-${stamp}`);
1757
1757
  }
1758
1758
 
1759
1759
  // packages/core/src/evidence/types.ts
1760
1760
  var EVIDENCE_FORMAT_VERSION = "1.0";
1761
1761
  var EVIDENCE_ASSESSMENT_NOTE = "Best-effort local safety verification only; not a compliance certification.";
1762
1762
  var EVIDENCE_MANIFEST_FILENAME = "evidence.json";
1763
+ var EVIDENCE_RESOLVED_CONTRACT_FILENAME = "contract.resolved.json";
1763
1764
  var SHA256_RE = /^[a-f0-9]{64}$/i;
1764
1765
  function sha256Hex(data) {
1765
1766
  const hash = createHash("sha256");
@@ -1791,7 +1792,7 @@ function assertEvidenceRelativePath(relativePath) {
1791
1792
  throw new Error("Evidence file path must be a non-empty relative path.");
1792
1793
  }
1793
1794
  const trimmed = relativePath.trim().replaceAll("\\", "/");
1794
- if (path.isAbsolute(trimmed) || trimmed.startsWith("/")) {
1795
+ if (path3.isAbsolute(trimmed) || trimmed.startsWith("/")) {
1795
1796
  throw new Error(`Evidence file path must be relative: ${relativePath}`);
1796
1797
  }
1797
1798
  const parts = trimmed.split("/").filter((part) => part !== "");
@@ -1831,6 +1832,9 @@ function inferEvidenceFileRole(relativePath) {
1831
1832
  if (base === "check-results.json") {
1832
1833
  return "checks";
1833
1834
  }
1835
+ if (base === "contract.resolved.json") {
1836
+ return "contract";
1837
+ }
1834
1838
  if (base === "redaction-report.json") {
1835
1839
  return "redaction-report";
1836
1840
  }
@@ -1897,6 +1901,7 @@ function buildEvidenceManifest(parts) {
1897
1901
  },
1898
1902
  assessment,
1899
1903
  ...parts.semantics !== void 0 ? { semantics: { ...parts.semantics } } : {},
1904
+ ...parts.contract !== void 0 ? { contract: { ...parts.contract } } : {},
1900
1905
  files: buildEvidenceFileEntries(parts.files)
1901
1906
  };
1902
1907
  }
@@ -1980,6 +1985,284 @@ function collectTraceSchemaVersions(jsonl) {
1980
1985
  return [...versions].sort((a, b) => a.localeCompare(b));
1981
1986
  }
1982
1987
 
1988
+ // packages/core/src/evidence/contract-binding.ts
1989
+ var EVIDENCE_CONTRACT_CANONICALIZATION_VERSION = "1";
1990
+ var EVIDENCE_CONTRACT_PARTIAL_NOTE = "Custom or programmatic rules are not serializable; Evidence records rule IDs only and does not claim complete reviewer replay.";
1991
+ var EVIDENCE_CONTRACT_UNAVAILABLE_NOTE = "No resolved TraceContract or check preset was packaged with this Evidence artifact.";
1992
+ var EVIDENCE_CONTRACT_ASSURANCE_NOTE = "Contract binding verifies packaged digest integrity only; it does not prove producer identity, trusted time, source completeness, semantic truth, or external acceptance.";
1993
+ function serializeCanonicalJson(value) {
1994
+ return `${JSON.stringify(stableValue(value), null, 2)}
1995
+ `;
1996
+ }
1997
+ function stableValue(value) {
1998
+ if (Array.isArray(value)) return value.map(stableValue);
1999
+ if (value === null || typeof value !== "object") return value;
2000
+ if (typeof value === "function") return void 0;
2001
+ const record = value;
2002
+ return Object.fromEntries(
2003
+ Object.keys(record).filter((key) => record[key] !== void 0 && typeof record[key] !== "function").sort((a, b) => a.localeCompare(b)).map((key) => [key, stableValue(record[key])])
2004
+ );
2005
+ }
2006
+ function sortedUniqueStrings(values) {
2007
+ return [...new Set(values.map((item) => item.trim()).filter((item) => item !== ""))].sort(
2008
+ (a, b) => a.localeCompare(b)
2009
+ );
2010
+ }
2011
+ function resolveSerializableTraceContract(input) {
2012
+ const defined = defineTraceContract(input);
2013
+ const tools = defined.tools ? {
2014
+ ...defined.tools,
2015
+ required: sortedUniqueStrings([
2016
+ ...defined.tools.required ?? [],
2017
+ ...defined.tools.requiredTools ?? []
2018
+ ]),
2019
+ forbidden: sortedUniqueStrings([
2020
+ ...defined.tools.forbidden ?? [],
2021
+ ...defined.tools.forbiddenTools ?? []
2022
+ ]),
2023
+ ...defined.tools.allowed ? { allowed: sortedUniqueStrings(defined.tools.allowed) } : {},
2024
+ ...defined.tools.requiredOrder ? {
2025
+ requiredOrder: [...defined.tools.requiredOrder],
2026
+ requiredOrderMode: defined.tools.requiredOrderMode ?? "first-occurrence"
2027
+ } : {}
2028
+ } : void 0;
2029
+ if (tools) {
2030
+ delete tools.requiredTools;
2031
+ delete tools.forbiddenTools;
2032
+ if (tools.required?.length === 0) delete tools.required;
2033
+ if (tools.forbidden?.length === 0) delete tools.forbidden;
2034
+ }
2035
+ const run = defined.run ? {
2036
+ ...defined.run,
2037
+ // Evaluator default: requireCompleted is true unless explicitly false.
2038
+ requireCompleted: defined.run.requireCompleted !== false
2039
+ } : void 0;
2040
+ return {
2041
+ ...defined,
2042
+ ...run ? { run } : {},
2043
+ ...tools && Object.keys(tools).length > 0 ? { tools } : {}
2044
+ };
2045
+ }
2046
+ function collectResolvedContractRuleIds(contract) {
2047
+ const ids = [];
2048
+ if (contract.run) {
2049
+ if (contract.run.allowedStatuses?.length) ids.push("contract.run.allowedStatuses");
2050
+ if (contract.run.requireCompleted === true) ids.push("run.requireCompleted");
2051
+ if (contract.run.maxDurationMs !== void 0) ids.push("run.duration");
2052
+ }
2053
+ if (contract.tools) {
2054
+ if ((contract.tools.required?.length ?? 0) > 0 || (contract.tools.forbidden?.length ?? 0) > 0 || contract.tools.allowed || contract.tools.maxCalls !== void 0) {
2055
+ ids.push("tool.usage");
2056
+ }
2057
+ if (contract.tools.requiredOrder?.length) {
2058
+ for (let i = 0; i < contract.tools.requiredOrder.length - 1; i += 1) {
2059
+ ids.push(`contract.tool.order.${i}`);
2060
+ }
2061
+ }
2062
+ if (contract.tools.orderRules?.length) {
2063
+ for (let index = 0; index < contract.tools.orderRules.length; index += 1) {
2064
+ ids.push(`contract.tool.orderRule.${index}`);
2065
+ }
2066
+ }
2067
+ if (contract.tools.arguments?.length) ids.push("contract.tool.arguments");
2068
+ }
2069
+ if (contract.llm) ids.push("llm.usage");
2070
+ if (contract.observations?.required?.length) ids.push("contract.observation.required");
2071
+ if (contract.observations?.failOn?.length) ids.push("outcome.status");
2072
+ if (contract.observations?.requireProvenance) ids.push("contract.observation.provenance");
2073
+ if (contract.controls) ids.push("contract.controls");
2074
+ if (contract.retry) ids.push("contract.retry");
2075
+ if (contract.scope) ids.push("contract.scope.selected");
2076
+ if (contract.alternatives?.anyOf?.length) ids.push("contract.alternatives.anyOf");
2077
+ return sortedUniqueStrings(ids);
2078
+ }
2079
+ function buildUnavailablePackage(engineVersion, note) {
2080
+ const binding = {
2081
+ status: "unavailable",
2082
+ source: "programmatic",
2083
+ canonicalizationVersion: EVIDENCE_CONTRACT_CANONICALIZATION_VERSION,
2084
+ engineVersion,
2085
+ ruleIds: [],
2086
+ note: note ?? EVIDENCE_CONTRACT_UNAVAILABLE_NOTE
2087
+ };
2088
+ return {
2089
+ binding,
2090
+ checkBinding: {
2091
+ canonicalizationVersion: EVIDENCE_CONTRACT_CANONICALIZATION_VERSION,
2092
+ engineVersion,
2093
+ evaluatedRuleIds: [],
2094
+ bindingStatus: "unavailable"
2095
+ }
2096
+ };
2097
+ }
2098
+ function buildEvidenceContractPackage(input) {
2099
+ const unsupported = sortedUniqueStrings(input.unsupportedRuleIds ?? []);
2100
+ const hasContract = input.contract !== void 0;
2101
+ const hasPreset = input.preset !== void 0;
2102
+ if (!hasContract && !hasPreset) {
2103
+ return buildUnavailablePackage(input.engineVersion, input.note);
2104
+ }
2105
+ let kind = "trace-contract";
2106
+ let resolved;
2107
+ let ruleIds;
2108
+ if (hasContract) {
2109
+ const normalized = resolveSerializableTraceContract(input.contract);
2110
+ resolved = stableValue(normalized);
2111
+ ruleIds = collectResolvedContractRuleIds(normalized);
2112
+ } else {
2113
+ kind = "check-preset";
2114
+ resolved = stableValue(input.preset.resolved);
2115
+ const select = Array.isArray(input.preset.resolved.select) ? input.preset.resolved.select.filter(
2116
+ (item) => typeof item === "string"
2117
+ ) : [];
2118
+ ruleIds = sortedUniqueStrings(select);
2119
+ }
2120
+ if (input.ruleIds !== void 0) {
2121
+ ruleIds = sortedUniqueStrings(input.ruleIds);
2122
+ }
2123
+ if (unsupported.length > 0) {
2124
+ ruleIds = sortedUniqueStrings([...ruleIds, ...unsupported]);
2125
+ }
2126
+ const document = {
2127
+ canonicalizationVersion: EVIDENCE_CONTRACT_CANONICALIZATION_VERSION,
2128
+ kind,
2129
+ resolved,
2130
+ origin: {
2131
+ source: input.source,
2132
+ ...input.preset?.name ? { preset: input.preset.name } : {},
2133
+ ...input.path !== void 0 && input.path.trim() !== "" ? { path: input.path.trim() } : {}
2134
+ }
2135
+ };
2136
+ const resolvedJson = serializeCanonicalJson(document);
2137
+ const digest = sha256Hex(resolvedJson);
2138
+ const status = unsupported.length > 0 ? "partial" : "complete";
2139
+ const binding = {
2140
+ status,
2141
+ source: input.source,
2142
+ ...input.contractId !== void 0 ? { contractId: input.contractId } : {},
2143
+ ...input.contractVersion !== void 0 ? { contractVersion: input.contractVersion } : {},
2144
+ canonicalizationVersion: EVIDENCE_CONTRACT_CANONICALIZATION_VERSION,
2145
+ engineVersion: input.engineVersion,
2146
+ path: EVIDENCE_RESOLVED_CONTRACT_FILENAME,
2147
+ sha256: digest,
2148
+ ruleIds,
2149
+ ...unsupported.length > 0 ? { unsupportedRuleIds: unsupported } : {},
2150
+ note: input.note ?? (status === "partial" ? EVIDENCE_CONTRACT_PARTIAL_NOTE : EVIDENCE_CONTRACT_ASSURANCE_NOTE)
2151
+ };
2152
+ const checkBinding = {
2153
+ contractDigest: digest,
2154
+ canonicalizationVersion: EVIDENCE_CONTRACT_CANONICALIZATION_VERSION,
2155
+ engineVersion: input.engineVersion,
2156
+ evaluatedRuleIds: ruleIds,
2157
+ bindingStatus: status,
2158
+ ...input.preset?.name ? {
2159
+ origin: {
2160
+ source: input.source,
2161
+ preset: input.preset.name
2162
+ }
2163
+ } : {
2164
+ origin: {
2165
+ source: input.source
2166
+ }
2167
+ },
2168
+ ...unsupported.length > 0 ? { unsupportedRuleIds: unsupported } : {}
2169
+ };
2170
+ return {
2171
+ file: {
2172
+ path: EVIDENCE_RESOLVED_CONTRACT_FILENAME,
2173
+ content: resolvedJson,
2174
+ role: "contract"
2175
+ },
2176
+ binding,
2177
+ checkBinding,
2178
+ resolvedJson
2179
+ };
2180
+ }
2181
+ function bindCheckResultsToContract(checkResults, checkBinding) {
2182
+ return {
2183
+ ...checkResults,
2184
+ contract: {
2185
+ ...checkBinding
2186
+ }
2187
+ };
2188
+ }
2189
+ function serializeCheckResultsJson(value) {
2190
+ return serializeCanonicalJson(value);
2191
+ }
2192
+ function readCheckResultsContractBinding(checkResultsJson) {
2193
+ try {
2194
+ const parsed = JSON.parse(checkResultsJson);
2195
+ if (parsed.contract === null || typeof parsed.contract !== "object" || Array.isArray(parsed.contract)) {
2196
+ return void 0;
2197
+ }
2198
+ return parsed.contract;
2199
+ } catch {
2200
+ return void 0;
2201
+ }
2202
+ }
2203
+ function verifyEvidenceContractBinding(parts) {
2204
+ const issues = [];
2205
+ const binding = parts.binding;
2206
+ if (binding === void 0) return issues;
2207
+ if (binding.canonicalizationVersion !== EVIDENCE_CONTRACT_CANONICALIZATION_VERSION) {
2208
+ issues.push({
2209
+ code: "contract_binding_invalid",
2210
+ severity: "error",
2211
+ message: `Unsupported contract canonicalizationVersion: ${String(binding.canonicalizationVersion)}`
2212
+ });
2213
+ }
2214
+ if (binding.status === "unavailable") {
2215
+ if (binding.path !== void 0 || binding.sha256 !== void 0) {
2216
+ issues.push({
2217
+ code: "contract_binding_invalid",
2218
+ severity: "error",
2219
+ message: "unavailable contract binding must not reference a packaged contract file."
2220
+ });
2221
+ }
2222
+ return issues;
2223
+ }
2224
+ const expectedPath = binding.path ?? EVIDENCE_RESOLVED_CONTRACT_FILENAME;
2225
+ if (parts.resolvedContractBytes === void 0) {
2226
+ issues.push({
2227
+ code: "contract_file_missing",
2228
+ severity: "error",
2229
+ message: `Referenced contract file missing: ${expectedPath}`,
2230
+ path: expectedPath
2231
+ });
2232
+ return issues;
2233
+ }
2234
+ const actual = sha256Hex(parts.resolvedContractBytes);
2235
+ if (binding.sha256 !== void 0 && !sha256Equals(binding.sha256, actual)) {
2236
+ issues.push({
2237
+ code: "contract_hash_mismatch",
2238
+ severity: "error",
2239
+ message: `SHA-256 mismatch for ${expectedPath}`,
2240
+ path: expectedPath
2241
+ });
2242
+ }
2243
+ if (parts.checkResultsJson !== void 0) {
2244
+ const checkBinding = readCheckResultsContractBinding(parts.checkResultsJson);
2245
+ if (checkBinding?.contractDigest !== void 0 && binding.sha256 !== void 0) {
2246
+ if (!sha256Equals(checkBinding.contractDigest, binding.sha256)) {
2247
+ issues.push({
2248
+ code: "contract_digest_mismatch",
2249
+ severity: "error",
2250
+ message: "check-results.json contractDigest does not match evidence.json contract.sha256.",
2251
+ path: "check-results.json"
2252
+ });
2253
+ }
2254
+ } else if (binding.status === "complete" || binding.status === "partial") {
2255
+ issues.push({
2256
+ code: "contract_digest_mismatch",
2257
+ severity: "error",
2258
+ message: "check-results.json is missing contract.contractDigest for a packaged contract binding.",
2259
+ path: "check-results.json"
2260
+ });
2261
+ }
2262
+ }
2263
+ return issues;
2264
+ }
2265
+
1983
2266
  // packages/core/src/evidence/views.ts
1984
2267
  function renderTreeHtml(nodes, ulClass = "tree") {
1985
2268
  if (nodes.length === 0) return "";
@@ -2654,11 +2937,11 @@ async function listFilesRecursive(root) {
2654
2937
  async function walk(dir) {
2655
2938
  const entries = await readdir(dir, { withFileTypes: true });
2656
2939
  for (const entry of entries) {
2657
- const abs = path.join(dir, entry.name);
2940
+ const abs = path3.join(dir, entry.name);
2658
2941
  if (entry.isDirectory()) {
2659
2942
  await walk(abs);
2660
2943
  } else if (entry.isFile()) {
2661
- const rel = path.relative(root, abs).split(path.sep).join("/");
2944
+ const rel = path3.relative(root, abs).split(path3.sep).join("/");
2662
2945
  out.push(rel);
2663
2946
  }
2664
2947
  }
@@ -2668,7 +2951,7 @@ async function listFilesRecursive(root) {
2668
2951
  }
2669
2952
  async function verifyEvidenceDirectory(rootPath, options = {}) {
2670
2953
  const unexpectedMode = options.unexpectedFiles ?? "fail";
2671
- const root = path.resolve(rootPath);
2954
+ const root = path3.resolve(rootPath);
2672
2955
  const issues = [];
2673
2956
  let rootStat;
2674
2957
  try {
@@ -2698,7 +2981,7 @@ async function verifyEvidenceDirectory(rootPath, options = {}) {
2698
2981
  checkedFiles: 0
2699
2982
  };
2700
2983
  }
2701
- const manifestPath = path.join(root, EVIDENCE_MANIFEST_FILENAME);
2984
+ const manifestPath = path3.join(root, EVIDENCE_MANIFEST_FILENAME);
2702
2985
  let manifestText;
2703
2986
  try {
2704
2987
  manifestText = await readFile(manifestPath, "utf-8");
@@ -2784,7 +3067,7 @@ async function verifyEvidenceDirectory(rootPath, options = {}) {
2784
3067
  continue;
2785
3068
  }
2786
3069
  listed.add(rel);
2787
- const abs = path.join(root, ...rel.split("/"));
3070
+ const abs = path3.join(root, ...rel.split("/"));
2788
3071
  let bytes;
2789
3072
  try {
2790
3073
  bytes = await readFile(abs);
@@ -2825,6 +3108,28 @@ async function verifyEvidenceDirectory(rootPath, options = {}) {
2825
3108
  path: rel
2826
3109
  });
2827
3110
  }
3111
+ if (manifest.contract !== void 0) {
3112
+ const contractRel = manifest.contract.path ?? EVIDENCE_RESOLVED_CONTRACT_FILENAME;
3113
+ let resolvedBytes;
3114
+ try {
3115
+ resolvedBytes = await readFile(path3.join(root, ...contractRel.split("/")), "utf-8");
3116
+ } catch {
3117
+ resolvedBytes = void 0;
3118
+ }
3119
+ let checkResultsJson;
3120
+ try {
3121
+ checkResultsJson = await readFile(path3.join(root, "check-results.json"), "utf-8");
3122
+ } catch {
3123
+ checkResultsJson = void 0;
3124
+ }
3125
+ for (const issue of verifyEvidenceContractBinding({
3126
+ binding: manifest.contract,
3127
+ ...resolvedBytes !== void 0 ? { resolvedContractBytes: resolvedBytes } : {},
3128
+ ...checkResultsJson !== void 0 ? { checkResultsJson } : {}
3129
+ })) {
3130
+ issues.push(issue);
3131
+ }
3132
+ }
2828
3133
  const hasError = issues.some((issue) => issue.severity === "error");
2829
3134
  return {
2830
3135
  ok: !hasError,
@@ -2881,10 +3186,33 @@ function buildEvidenceCiPackage(input) {
2881
3186
  }))
2882
3187
  }
2883
3188
  });
3189
+ let checkResultsJson = input.checkResultsJson;
3190
+ let contractBinding;
3191
+ let contractFileContent;
3192
+ if (input.contractPackage !== void 0) {
3193
+ const packaged2 = buildEvidenceContractPackage({
3194
+ ...input.contractPackage,
3195
+ engineVersion: input.contractPackage.engineVersion || input.generatorVersion
3196
+ });
3197
+ contractBinding = packaged2.binding;
3198
+ if (packaged2.resolvedJson !== void 0) {
3199
+ contractFileContent = packaged2.resolvedJson;
3200
+ }
3201
+ let parsed;
3202
+ try {
3203
+ parsed = JSON.parse(checkResultsJson);
3204
+ } catch {
3205
+ parsed = { raw: checkResultsJson };
3206
+ }
3207
+ checkResultsJson = serializeCheckResultsJson(
3208
+ bindCheckResultsToContract(parsed, packaged2.checkBinding)
3209
+ );
3210
+ }
2884
3211
  const packaged = [
2885
3212
  { path: EVIDENCE_HTML_FILENAME, content: evidenceHtml },
2886
- { path: "check-results.json", content: input.checkResultsJson },
2887
- { path: "trace.jsonl", content: input.redactedTraceJsonl }
3213
+ { path: "check-results.json", content: checkResultsJson },
3214
+ { path: "trace.jsonl", content: input.redactedTraceJsonl },
3215
+ ...contractFileContent !== void 0 ? [{ path: EVIDENCE_RESOLVED_CONTRACT_FILENAME, content: contractFileContent }] : []
2888
3216
  ];
2889
3217
  const manifest = buildEvidenceManifest({
2890
3218
  generatorVersion: input.generatorVersion,
@@ -2898,13 +3226,15 @@ function buildEvidenceCiPackage(input) {
2898
3226
  files: packaged,
2899
3227
  createdAt,
2900
3228
  note: EVIDENCE_ASSESSMENT_NOTE,
2901
- ...input.semantics !== void 0 ? { semantics: input.semantics } : {}
3229
+ ...input.semantics !== void 0 ? { semantics: input.semantics } : {},
3230
+ ...contractBinding !== void 0 ? { contract: contractBinding } : {}
2902
3231
  });
2903
3232
  return {
2904
3233
  "evidence.html": evidenceHtml,
2905
3234
  "evidence.json": serializeEvidenceManifest(manifest),
2906
- "check-results.json": input.checkResultsJson,
3235
+ "check-results.json": checkResultsJson,
2907
3236
  "trace.jsonl": input.redactedTraceJsonl,
3237
+ ...contractFileContent !== void 0 ? { [EVIDENCE_RESOLVED_CONTRACT_FILENAME]: contractFileContent } : {},
2908
3238
  manifest
2909
3239
  };
2910
3240
  }
@@ -3060,7 +3390,7 @@ function normalizeSuiteConfig(value) {
3060
3390
  }
3061
3391
  async function validateSuiteConfig(config, options) {
3062
3392
  const diagnostics = [];
3063
- const tracesDir = path.resolve(options.configDir, config.traces);
3393
+ const tracesDir = path3.resolve(options.configDir, config.traces);
3064
3394
  try {
3065
3395
  await access(tracesDir);
3066
3396
  } catch {
@@ -3070,7 +3400,7 @@ async function validateSuiteConfig(config, options) {
3070
3400
  }
3071
3401
  for (const suiteCase of config.cases) {
3072
3402
  if (suiteCase.input !== void 0) {
3073
- const inputPath = path.resolve(options.configDir, suiteCase.input);
3403
+ const inputPath = path3.resolve(options.configDir, suiteCase.input);
3074
3404
  try {
3075
3405
  await access(inputPath);
3076
3406
  } catch {
@@ -3103,12 +3433,12 @@ async function fileExists(filePath) {
3103
3433
  }
3104
3434
  }
3105
3435
  async function resolveSuiteConfigPath(options = {}) {
3106
- const cwd = path.resolve(options.cwd ?? process.cwd());
3436
+ const cwd = path3.resolve(options.cwd ?? process.cwd());
3107
3437
  if (options.configPath !== void 0 && options.configPath.trim() !== "") {
3108
- return path.resolve(cwd, options.configPath.trim());
3438
+ return path3.resolve(cwd, options.configPath.trim());
3109
3439
  }
3110
3440
  for (const name of DEFAULT_SUITE_CONFIG_NAMES) {
3111
- const candidate = path.join(cwd, name);
3441
+ const candidate = path3.join(cwd, name);
3112
3442
  if (await fileExists(candidate)) return candidate;
3113
3443
  }
3114
3444
  throw new Error(
@@ -3125,7 +3455,7 @@ async function loadSuiteConfig(options = {}) {
3125
3455
  diagnostics: [diagnostic2("AI_SUITE_CONFIG_LOAD_FAILED", message)]
3126
3456
  });
3127
3457
  }
3128
- const extension = path.extname(configPath);
3458
+ const extension = path3.extname(configPath);
3129
3459
  if (TS_CONFIG_EXTENSIONS.has(extension)) {
3130
3460
  const message = "TypeScript suite configs require an explicit precompiled JavaScript config or future --config-loader support.";
3131
3461
  throw Object.assign(new Error(message), {
@@ -3150,7 +3480,7 @@ async function loadSuiteConfig(options = {}) {
3150
3480
  return {
3151
3481
  config,
3152
3482
  configPath,
3153
- configDir: path.dirname(configPath)
3483
+ configDir: path3.dirname(configPath)
3154
3484
  };
3155
3485
  } catch (error) {
3156
3486
  const message = error instanceof Error ? error.message : String(error);
@@ -3191,7 +3521,7 @@ async function exists(filePath) {
3191
3521
  }
3192
3522
  async function resolveSuiteCaseTrace(suiteCase, options) {
3193
3523
  if (suiteCase.trace !== void 0) {
3194
- const tracePath = path.resolve(options.configDir, suiteCase.trace);
3524
+ const tracePath = path3.resolve(options.configDir, suiteCase.trace);
3195
3525
  if (await exists(tracePath)) {
3196
3526
  return { caseId: suiteCase.id, tracePath, missing: false };
3197
3527
  }
@@ -3207,7 +3537,7 @@ async function resolveSuiteCaseTrace(suiteCase, options) {
3207
3537
  if (await exists(directPath)) {
3208
3538
  return { caseId: suiteCase.id, tracePath: directPath, runId: runKey, missing: false };
3209
3539
  }
3210
- const nestedPath = path.join(options.tracesDir, `${path.basename(runKey)}.jsonl`);
3540
+ const nestedPath = path3.join(options.tracesDir, `${path3.basename(runKey)}.jsonl`);
3211
3541
  if (await exists(nestedPath)) {
3212
3542
  return { caseId: suiteCase.id, tracePath: nestedPath, runId: runKey, missing: false };
3213
3543
  }
@@ -3385,7 +3715,7 @@ async function runSuiteCase(suiteCase, config, options) {
3385
3715
  async function runSuite(options = {}) {
3386
3716
  const startedAt = new Date(options.nowMs ?? Date.now()).toISOString();
3387
3717
  const { config, configPath, configDir } = await loadSuiteConfig(options);
3388
- const tracesDir = path.resolve(configDir, config.traces);
3718
+ const tracesDir = path3.resolve(configDir, config.traces);
3389
3719
  const cases = [];
3390
3720
  const diagnostics = [];
3391
3721
  for (const suiteCase of config.cases) {
@@ -4340,7 +4670,7 @@ function validateOptions(options) {
4340
4670
  }
4341
4671
  function isConfigLoadError(error) {
4342
4672
  if (!(error instanceof Error)) return false;
4343
- const ext = path.extname(error.message);
4673
+ const ext = path3.extname(error.message);
4344
4674
  if (error.message.includes("Unsupported suite config extension")) return true;
4345
4675
  if (error.message.includes("TypeScript suite configs require")) return true;
4346
4676
  if (error.message.includes("No suite config found")) return true;
@@ -4582,6 +4912,6 @@ function createOmittedPayloadCommitment(payload, options = {}) {
4582
4912
  };
4583
4913
  }
4584
4914
 
4585
- export { ADAPTER_CAPTURE_DIAGNOSTIC_CODES, COHORT_METRIC_IDS, DEFAULT_ADAPTER_MAX_PREVIEW_CHARS, DEFAULT_SUITE_ARTIFACTS_DIR, DEFAULT_SUITE_CONFIG_NAMES, EVIDENCE_ASSESSMENT_NOTE, EVIDENCE_FORMAT_VERSION, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, EVIDENCE_VIEW_CSS, EVIDENCE_VIEW_IDS, OMITTED_PAYLOAD_MAX_DIGEST_INPUT_BYTES, SESSION_WORKFLOW_KEYS, SUITE_TEMPLATE_IDS, aggregateBundleSafeStatus, aggregateSessionCheckResults, analyzeCohort, assertBundlePathContained, assertEvidenceRelativePath, buildActivitySummary, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceCausalFailureViewHtml, buildEvidenceCiPackage, buildEvidenceCircuitViewHtml, buildEvidenceContractsViewHtml, buildEvidenceDiffViewHtml, buildEvidenceFileEntries, buildEvidenceHtmlShell, buildEvidenceHtmlShellFromManifest, buildEvidenceManifest, buildEvidenceOutcomesViewHtml, buildEvidenceProvenanceViewHtml, buildEvidenceSafetyViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceTreeViewHtml, buildLocalExplanation, buildPlaceholderArtifact, buildSessionIndex, buildZipArchive, bundleFailsOnSafety, bundleRunAssetRelativePath, collectTraceSchemaVersions, compareCohortAggregates, createAdapterPreviewCapture, createOmittedPayloadCommitment, defaultBundleOutputPath, defaultSuiteConfigTemplate, deriveSessionStatus, encodeEmbeddedEvidenceJson, enrichSessionRunRecord, enrichSessionSummary, filterMetasBySessionScope, findFirstCausalFailure, gateHasThresholds, getSuiteTemplate, groupSessionCohorts, inferEvidenceFileRole, isAgentInspectTrace, isSha256Hex, listSuiteTemplates, loadSessionRunRecords, loadSuiteConfig, loadTraceMetadataList, normalizeBundleOutputPath, normalizeSuiteConfig, omittedPayloadByteLength, parseCohortMetricList, parseDurationFilter, parseEvidenceManifestJson, parseGateList, parseGateNumber, parseGroupBySpec, renderActivitySummaryHuman, renderCohortReport, renderCohortSummaryMarkdown, renderGateGithubAnnotations, renderGateGithubStepSummary, renderGateJUnit, renderGateReport, renderGateSummaryMarkdown, renderSuiteReport, renderSuiteReportMarkdown, resolveAdapterMaxPreviewChars, resolveBundleRunIds, resolveSuiteCaseTrace, resolveSuiteConfigPath, resolveSuiteTemplate, runGate, runSuite, sanitizeBundleRunId, searchTraces, serializeAdapterPreview, serializeEvidenceManifest, sha256Equals, sha256Hex, toMetadataSafeStatus, traceMetasToSessionRunRecords, validateEvidenceManifest, validateSuiteConfig, verifyEvidenceDirectory };
4915
+ export { ADAPTER_CAPTURE_DIAGNOSTIC_CODES, COHORT_METRIC_IDS, DEFAULT_ADAPTER_MAX_PREVIEW_CHARS, DEFAULT_SUITE_ARTIFACTS_DIR, DEFAULT_SUITE_CONFIG_NAMES, EVIDENCE_ASSESSMENT_NOTE, EVIDENCE_CONTRACT_ASSURANCE_NOTE, EVIDENCE_CONTRACT_CANONICALIZATION_VERSION, EVIDENCE_CONTRACT_PARTIAL_NOTE, EVIDENCE_CONTRACT_UNAVAILABLE_NOTE, EVIDENCE_FORMAT_VERSION, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, EVIDENCE_RESOLVED_CONTRACT_FILENAME, EVIDENCE_VIEW_CSS, EVIDENCE_VIEW_IDS, OMITTED_PAYLOAD_MAX_DIGEST_INPUT_BYTES, SESSION_WORKFLOW_KEYS, SUITE_TEMPLATE_IDS, aggregateBundleSafeStatus, aggregateSessionCheckResults, analyzeCohort, assertBundlePathContained, assertEvidenceRelativePath, bindCheckResultsToContract, buildActivitySummary, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceCausalFailureViewHtml, buildEvidenceCiPackage, buildEvidenceCircuitViewHtml, buildEvidenceContractPackage, buildEvidenceContractsViewHtml, buildEvidenceDiffViewHtml, buildEvidenceFileEntries, buildEvidenceHtmlShell, buildEvidenceHtmlShellFromManifest, buildEvidenceManifest, buildEvidenceOutcomesViewHtml, buildEvidenceProvenanceViewHtml, buildEvidenceSafetyViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceTreeViewHtml, buildLocalExplanation, buildPlaceholderArtifact, buildSessionIndex, buildZipArchive, bundleFailsOnSafety, bundleRunAssetRelativePath, collectResolvedContractRuleIds, collectTraceSchemaVersions, compareCohortAggregates, createAdapterPreviewCapture, createOmittedPayloadCommitment, defaultBundleOutputPath, defaultSuiteConfigTemplate, deriveSessionStatus, encodeEmbeddedEvidenceJson, enrichSessionRunRecord, enrichSessionSummary, filterMetasBySessionScope, findFirstCausalFailure, gateHasThresholds, getSuiteTemplate, groupSessionCohorts, inferEvidenceFileRole, isAgentInspectTrace, isSha256Hex, listSuiteTemplates, loadSessionRunRecords, loadSuiteConfig, loadTraceMetadataList, normalizeBundleOutputPath, normalizeSuiteConfig, omittedPayloadByteLength, parseCohortMetricList, parseDurationFilter, parseEvidenceManifestJson, parseGateList, parseGateNumber, parseGroupBySpec, readCheckResultsContractBinding, renderActivitySummaryHuman, renderCohortReport, renderCohortSummaryMarkdown, renderGateGithubAnnotations, renderGateGithubStepSummary, renderGateJUnit, renderGateReport, renderGateSummaryMarkdown, renderSuiteReport, renderSuiteReportMarkdown, resolveAdapterMaxPreviewChars, resolveBundleRunIds, resolveSerializableTraceContract, resolveSuiteCaseTrace, resolveSuiteConfigPath, resolveSuiteTemplate, runGate, runSuite, sanitizeBundleRunId, searchTraces, serializeAdapterPreview, serializeCanonicalJson, serializeCheckResultsJson, serializeEvidenceManifest, sha256Equals, sha256Hex, toMetadataSafeStatus, traceMetasToSessionRunRecords, validateEvidenceManifest, validateSuiteConfig, verifyEvidenceContractBinding, verifyEvidenceDirectory };
4586
4916
  //# sourceMappingURL=advanced.mjs.map
4587
4917
  //# sourceMappingURL=advanced.mjs.map