@riddledc/riddle-proof 0.8.75 → 0.8.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -18137,6 +18137,33 @@ function collectProfileArtifacts(result) {
18137
18137
  }
18138
18138
  return artifacts;
18139
18139
  }
18140
+ function collectChangeReceiptArtifacts(result) {
18141
+ const artifacts = [];
18142
+ const seen = /* @__PURE__ */ new Set();
18143
+ const collectSide = (sideName, side) => {
18144
+ const candidates = [
18145
+ ...asArray(side.screenshots),
18146
+ ...asArray(side.artifacts)
18147
+ ];
18148
+ for (const [index, item] of candidates.entries()) {
18149
+ const artifact = asRecord2(item);
18150
+ const url = stringValue4(artifact.url) || stringValue4(artifact.path);
18151
+ if (!url || seen.has(url)) continue;
18152
+ seen.add(url);
18153
+ const fallbackName = `${sideName}-artifact-${index + 1}`;
18154
+ const name = `${sideName}/${artifactDisplayName(artifact.name, fallbackName)}`;
18155
+ artifacts.push({
18156
+ name,
18157
+ url,
18158
+ kind: artifactKind(name, url),
18159
+ size_bytes: numberValue3(artifact.size_bytes) ?? numberValue3(artifact.size)
18160
+ });
18161
+ }
18162
+ };
18163
+ collectSide("before", asRecord2(result.before));
18164
+ collectSide("after", asRecord2(result.after));
18165
+ return artifacts;
18166
+ }
18140
18167
  function mergeArtifacts(...artifactLists) {
18141
18168
  const artifacts = [];
18142
18169
  const seen = /* @__PURE__ */ new Set();
@@ -18192,6 +18219,32 @@ function profilePageSummaries(result, counts) {
18192
18219
  failed: counts.failed
18193
18220
  }];
18194
18221
  }
18222
+ function changeReceiptCheckCounts(result) {
18223
+ const deltas = asArray(result.deltas);
18224
+ if (!deltas.length) return void 0;
18225
+ let passed = 0;
18226
+ let failed = 0;
18227
+ for (const item of deltas) {
18228
+ const status = stringValue4(asRecord2(item).status);
18229
+ if (status === "passed") passed += 1;
18230
+ if (status === "failed" || status === "proof_insufficient" || status === "configuration_error") failed += 1;
18231
+ }
18232
+ return { passed, failed };
18233
+ }
18234
+ function changeReceiptPageSummaries(result) {
18235
+ const pages = [];
18236
+ for (const sideName of ["before", "after"]) {
18237
+ const side = asRecord2(result[sideName]);
18238
+ if (!Object.keys(side).length) continue;
18239
+ const checks = asRecord2(side.checks);
18240
+ pages.push({
18241
+ route: firstStringValue2(side.source, side.profile_name) || sideName,
18242
+ passed: numberValue3(checks.passed) ?? 0,
18243
+ failed: numberValue3(checks.failed) ?? 0
18244
+ });
18245
+ }
18246
+ return pages;
18247
+ }
18195
18248
  function summarizeExplicitChecks(value) {
18196
18249
  let passed = 0;
18197
18250
  let failed = 0;
@@ -18247,11 +18300,20 @@ function isProfileResult(result) {
18247
18300
  const version = stringValue4(result.version);
18248
18301
  return version === "riddle-proof.profile-result.v1" || version === "riddle-proof.profile-compact-result.v1";
18249
18302
  }
18303
+ function isChangeReceiptResult(result) {
18304
+ return stringValue4(result.version) === "riddle-proof.change-receipt.v1";
18305
+ }
18306
+ function isChangeResult(result) {
18307
+ const version = stringValue4(result.version);
18308
+ return version === "riddle-proof.change-result.v1" || version === "riddle-proof.change-compact-result.v1";
18309
+ }
18250
18310
  function summarizeRiddleProofPrComment(input) {
18251
18311
  const runResponse = asRecord2(input.runResponse);
18252
18312
  const result = asRecord2(input.result);
18253
18313
  const proofResult = asRecord2(runResponse.proofResult);
18254
18314
  const profileResult = isProfileResult(result);
18315
+ const changeReceiptResult = isChangeReceiptResult(result);
18316
+ const changeResult = changeReceiptResult || isChangeResult(result);
18255
18317
  const profileRiddle = asRecord2(result.riddle);
18256
18318
  const preview = asRecord2(runResponse.preview);
18257
18319
  const resultRunCard = asRecord2(result.run_card);
@@ -18260,15 +18322,18 @@ function summarizeRiddleProofPrComment(input) {
18260
18322
  const resultRaw = asRecord2(result.raw);
18261
18323
  const rawDetails = asRecord2(resultRaw.details);
18262
18324
  const profileChecks = profileResult ? profileCheckCounts(result) : void 0;
18325
+ const changeChecks = changeResult ? changeReceiptCheckCounts(result) : void 0;
18263
18326
  const artifacts = mergeArtifacts(
18264
18327
  collectArtifacts(runResponse),
18265
- profileResult ? collectProfileArtifacts(result) : []
18328
+ profileResult ? collectProfileArtifacts(result) : [],
18329
+ changeReceiptResult ? collectChangeReceiptArtifacts(result) : []
18266
18330
  );
18267
- const pages = profileResult ? profilePageSummaries(result, profileChecks) : pageSummaries(result);
18331
+ const pages = changeReceiptResult ? changeReceiptPageSummaries(result) : profileResult ? profilePageSummaries(result, profileChecks) : pageSummaries(result);
18268
18332
  const checkSource = { ...result };
18269
18333
  delete checkSource.ok;
18270
18334
  const nestedChecks = summarizeExplicitChecks(checkSource);
18271
- const ok = booleanValue3(result.ok) ?? booleanValue3(runResponse.ok) ?? null;
18335
+ const resultStatus = firstStringValue2(result.status, stopCondition.status);
18336
+ const ok = changeResult ? resultStatus === "passed" : booleanValue3(result.ok) ?? booleanValue3(runResponse.ok) ?? null;
18272
18337
  const checkpointSummary = checkpointSummaryFrom2(
18273
18338
  result.checkpoint_summary,
18274
18339
  stopCondition.checkpoint_summary,
@@ -18278,7 +18343,7 @@ function summarizeRiddleProofPrComment(input) {
18278
18343
  );
18279
18344
  const publicState = summarizeRiddleProofPublicState({
18280
18345
  ...result,
18281
- status: firstStringValue2(result.status, stopCondition.status),
18346
+ status: resultStatus,
18282
18347
  checkpoint_summary: checkpointSummary || result.checkpoint_summary
18283
18348
  });
18284
18349
  const mergeRecommendation = riddleProofPublicStateMergeRecommendation(
@@ -18288,7 +18353,7 @@ function summarizeRiddleProofPrComment(input) {
18288
18353
  return {
18289
18354
  ok,
18290
18355
  status: firstStringValue2(proofResult.status, profileRiddle.status),
18291
- result_status: publicState.status,
18356
+ result_status: changeResult ? resultStatus : publicState.status,
18292
18357
  job_id: firstStringValue2(proofResult.job_id, profileRiddle.job_id),
18293
18358
  duration_ms: numberValue3(proofResult.duration_ms) ?? numberValue3(profileRiddle.elapsed_ms),
18294
18359
  proof_url: stringValue4(runResponse.proofUrl),
@@ -18302,11 +18367,11 @@ function summarizeRiddleProofPrComment(input) {
18302
18367
  merge_ready: publicState.merge_ready,
18303
18368
  sync_allowed: publicState.sync_allowed,
18304
18369
  proof_decision: firstStringValue2(result.proof_decision, stopCondition.proof_decision, resultRaw.proof_decision),
18305
- merge_recommendation: mergeRecommendation,
18370
+ merge_recommendation: changeReceiptResult && resultStatus ? stringValue4(result.verdict) : mergeRecommendation,
18306
18371
  checkpoint_summary: checkpointSummary,
18307
18372
  public_state: publicState,
18308
- passed_checks: profileChecks?.passed ?? nestedChecks.passed,
18309
- failed_checks: profileChecks?.failed ?? nestedChecks.failed,
18373
+ passed_checks: changeChecks?.passed ?? profileChecks?.passed ?? nestedChecks.passed,
18374
+ failed_checks: changeChecks?.failed ?? profileChecks?.failed ?? nestedChecks.failed,
18310
18375
  pages,
18311
18376
  artifacts,
18312
18377
  primary_image: selectPrimaryImage(artifacts)
@@ -18610,6 +18675,7 @@ function suggestRiddleProofProfileChecks(input) {
18610
18675
 
18611
18676
  // src/change-proof.ts
18612
18677
  var RIDDLE_PROOF_CHANGE_RESULT_VERSION = "riddle-proof.change-result.v1";
18678
+ var RIDDLE_PROOF_CHANGE_RECEIPT_VERSION = "riddle-proof.change-receipt.v1";
18613
18679
  var DEFAULT_BEFORE_STATUSES = ["passed", "product_regression"];
18614
18680
  var DEFAULT_AFTER_STATUSES = ["passed"];
18615
18681
  var DEFAULT_PROFILE_STATUS_TRANSITION_BEFORE = ["product_regression"];
@@ -18768,6 +18834,322 @@ function assessRiddleProofChange(contract, input) {
18768
18834
  metadata: contract.metadata
18769
18835
  };
18770
18836
  }
18837
+ function changeReceiptVerdict(status) {
18838
+ if (status === "passed") return "mergeable";
18839
+ if (status === "environment_blocked") return "environment_blocked";
18840
+ if (status === "configuration_error") return "configuration_error";
18841
+ if (status === "needs_human_review") return "needs_human_review";
18842
+ if (status === "proof_insufficient") return "proof_insufficient";
18843
+ return "not_mergeable";
18844
+ }
18845
+ function profileCheckCounts2(result) {
18846
+ const counts = {
18847
+ total: result.checks.length,
18848
+ passed: 0,
18849
+ failed: 0,
18850
+ skipped: 0,
18851
+ needs_human_review: 0
18852
+ };
18853
+ for (const check of result.checks) {
18854
+ if (check.status === "passed") counts.passed += 1;
18855
+ if (check.status === "failed") counts.failed += 1;
18856
+ if (check.status === "skipped") counts.skipped += 1;
18857
+ if (check.status === "needs_human_review") counts.needs_human_review += 1;
18858
+ }
18859
+ return counts;
18860
+ }
18861
+ function artifactKind2(ref) {
18862
+ const text = [ref.name, ref.url, ref.path, ref.kind, ref.content_type].filter(Boolean).join(" ").toLowerCase();
18863
+ if (/\bimage\b/.test(text) || /\.(png|jpe?g|gif|webp|avif|svg)(\?|#|$)/.test(text)) return "image";
18864
+ if (/\bjson\b|\btext\b|\bmarkdown\b|\bhtml\b|\blog\b/.test(text) || /\.(json|md|txt|html|log|har)(\?|#|$)/.test(text)) return "data";
18865
+ return "artifact";
18866
+ }
18867
+ function receiptArtifactFromRef(side, ref) {
18868
+ return {
18869
+ side,
18870
+ name: ref.name,
18871
+ kind: artifactKind2(ref),
18872
+ url: ref.url,
18873
+ path: ref.path,
18874
+ source: ref.source
18875
+ };
18876
+ }
18877
+ function comparableArtifactName(value) {
18878
+ return (value || "").split(/[/?#]/).pop()?.toLowerCase().replace(/\.(png|jpe?g|gif|webp|avif|svg)$/u, "").replace(/[^a-z0-9_-]+/gu, "-").replace(/^-+|-+$/g, "") || "";
18879
+ }
18880
+ function artifactMatchesScreenshotLabel(artifact, screenshot) {
18881
+ const screenshotName = comparableArtifactName(screenshot);
18882
+ if (!screenshotName) return false;
18883
+ return [artifact.name, artifact.url, artifact.path].map(comparableArtifactName).some((name) => name === screenshotName || name.endsWith(`-${screenshotName}`));
18884
+ }
18885
+ function collectReceiptArtifacts(side, result) {
18886
+ const artifacts = [];
18887
+ const seen = /* @__PURE__ */ new Set();
18888
+ const add = (artifact) => {
18889
+ const key = artifact.url || artifact.path || `${artifact.kind}:${artifact.name}`;
18890
+ if (!artifact.name || seen.has(key)) return;
18891
+ seen.add(key);
18892
+ artifacts.push(artifact);
18893
+ };
18894
+ for (const ref of result.artifacts.riddle_artifacts || []) {
18895
+ add(receiptArtifactFromRef(side, ref));
18896
+ }
18897
+ for (const screenshot of result.artifacts.screenshots || []) {
18898
+ if (artifacts.some((artifact) => artifactMatchesScreenshotLabel(artifact, screenshot))) continue;
18899
+ add({
18900
+ side,
18901
+ name: screenshot,
18902
+ kind: "image"
18903
+ });
18904
+ }
18905
+ return artifacts;
18906
+ }
18907
+ function artifactIsScreenshot(artifact) {
18908
+ if (artifact.kind !== "image") return false;
18909
+ return /screenshot|\.png|\.jpe?g|\.webp|\.gif|\.avif|\.svg/i.test([artifact.name, artifact.url, artifact.path].filter(Boolean).join(" "));
18910
+ }
18911
+ function receiptSide(side, source, result) {
18912
+ const artifacts = collectReceiptArtifacts(side, result);
18913
+ return {
18914
+ side,
18915
+ source,
18916
+ profile_name: result.profile_name,
18917
+ status: result.status,
18918
+ summary: result.summary,
18919
+ route: result.route,
18920
+ captured_at: result.captured_at,
18921
+ checks: profileCheckCounts2(result),
18922
+ screenshots: artifacts.filter(artifactIsScreenshot),
18923
+ artifacts
18924
+ };
18925
+ }
18926
+ function metadataStringList(metadata, key) {
18927
+ const value = metadata?.[key];
18928
+ if (!Array.isArray(value)) return [];
18929
+ return value.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim());
18930
+ }
18931
+ function createRiddleProofChangeReceipt(input) {
18932
+ return {
18933
+ version: RIDDLE_PROOF_CHANGE_RECEIPT_VERSION,
18934
+ contract_name: input.result.contract_name,
18935
+ profile_name: input.profile_name,
18936
+ status: input.result.status,
18937
+ verdict: changeReceiptVerdict(input.result.status),
18938
+ summary: input.result.summary,
18939
+ before: receiptSide("before", input.before_source, input.before_result),
18940
+ after: receiptSide("after", input.after_source, input.after_result),
18941
+ deltas: input.result.deltas.map((delta) => ({
18942
+ type: delta.type,
18943
+ label: delta.label,
18944
+ status: delta.status,
18945
+ before_observed: delta.before_observed,
18946
+ after_observed: delta.after_observed,
18947
+ message: delta.message
18948
+ })),
18949
+ proves: metadataStringList(input.contract.metadata, "required_receipts"),
18950
+ does_not_prove: metadataStringList(input.contract.metadata, "does_not_prove"),
18951
+ metadata: input.result.metadata
18952
+ };
18953
+ }
18954
+ function markdownTableCell(value) {
18955
+ return String(value ?? "").replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
18956
+ }
18957
+ function artifactTarget(artifact) {
18958
+ return artifact.url || artifact.path;
18959
+ }
18960
+ function markdownLink2(label, target) {
18961
+ return `[${label.replace(/\]/g, "\\]")}](${target})`;
18962
+ }
18963
+ function appendMarkdownArtifacts(lines, title, artifacts) {
18964
+ lines.push(`### ${title}`, "");
18965
+ if (!artifacts.length) {
18966
+ lines.push("- No screenshot artifacts recorded.", "");
18967
+ return;
18968
+ }
18969
+ for (const artifact of artifacts.slice(0, 6)) {
18970
+ const target = artifactTarget(artifact);
18971
+ if (target && artifact.kind === "image") {
18972
+ lines.push(`![${artifact.name.replace(/\]/g, "\\]")}](${target})`);
18973
+ } else if (target) {
18974
+ lines.push(`- ${markdownLink2(artifact.name, target)}`);
18975
+ } else {
18976
+ lines.push(`- ${artifact.name}`);
18977
+ }
18978
+ }
18979
+ if (artifacts.length > 6) lines.push(`- ${artifacts.length - 6} more artifact(s) omitted`);
18980
+ lines.push("");
18981
+ }
18982
+ function riddleProofChangeReceiptMarkdown(receipt) {
18983
+ const lines = [
18984
+ "# Riddle Proof Change Receipt",
18985
+ "",
18986
+ `**Verdict:** ${receipt.verdict}`,
18987
+ `**Status:** ${receipt.status}`,
18988
+ `**Contract:** ${receipt.contract_name}`,
18989
+ receipt.profile_name ? `**Profile:** ${receipt.profile_name}` : "",
18990
+ "",
18991
+ receipt.summary,
18992
+ "",
18993
+ "## Evidence Pair",
18994
+ "",
18995
+ "| Side | Source | Status | Checks |",
18996
+ "| --- | --- | --- | --- |",
18997
+ `| Before | ${markdownTableCell(receipt.before.source)} | ${receipt.before.status} | ${receipt.before.checks.passed} passed / ${receipt.before.checks.failed} failed |`,
18998
+ `| After | ${markdownTableCell(receipt.after.source)} | ${receipt.after.status} | ${receipt.after.checks.passed} passed / ${receipt.after.checks.failed} failed |`,
18999
+ "",
19000
+ "## Delta Checks",
19001
+ "",
19002
+ "| Delta | Status | Before | After |",
19003
+ "| --- | --- | --- | --- |"
19004
+ ].filter(Boolean);
19005
+ for (const delta of receipt.deltas) {
19006
+ lines.push(`| ${markdownTableCell(delta.label)} | ${delta.status} | ${markdownTableCell(delta.before_observed)} | ${markdownTableCell(delta.after_observed)} |`);
19007
+ if (delta.message) lines.push(`| ${markdownTableCell(`${delta.label} message`)} | ${markdownTableCell(delta.message)} | | |`);
19008
+ }
19009
+ lines.push("");
19010
+ appendMarkdownArtifacts(lines, "Before Screenshot", receipt.before.screenshots);
19011
+ appendMarkdownArtifacts(lines, "After Screenshot", receipt.after.screenshots);
19012
+ if (receipt.proves.length) {
19013
+ lines.push("## What This Proves", "");
19014
+ for (const claim of receipt.proves) lines.push(`- ${claim}`);
19015
+ lines.push("");
19016
+ }
19017
+ if (receipt.does_not_prove.length) {
19018
+ lines.push("## What This Does Not Prove", "");
19019
+ for (const claim of receipt.does_not_prove) lines.push(`- ${claim}`);
19020
+ lines.push("");
19021
+ }
19022
+ const linkedArtifacts = [...receipt.before.artifacts, ...receipt.after.artifacts].filter((artifact) => artifactTarget(artifact)).slice(0, 24);
19023
+ if (linkedArtifacts.length) {
19024
+ lines.push("## Artifacts", "");
19025
+ for (const artifact of linkedArtifacts) {
19026
+ lines.push(`- ${artifact.side}: ${markdownLink2(artifact.name, artifactTarget(artifact) || "")}`);
19027
+ }
19028
+ lines.push("");
19029
+ }
19030
+ return `${lines.join("\n").trim()}
19031
+ `;
19032
+ }
19033
+ function escapeHtml(value) {
19034
+ return String(value ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
19035
+ }
19036
+ function htmlArtifactCard(artifact) {
19037
+ const target = artifactTarget(artifact);
19038
+ if (!target) return `<p>${escapeHtml(artifact.name)}</p>`;
19039
+ if (artifact.kind === "image") {
19040
+ return `<figure><img src="${escapeHtml(target)}" alt="${escapeHtml(artifact.name)}"><figcaption>${escapeHtml(artifact.name)}</figcaption></figure>`;
19041
+ }
19042
+ return `<p><a href="${escapeHtml(target)}">${escapeHtml(artifact.name)}</a></p>`;
19043
+ }
19044
+ function htmlArtifactLink(artifact) {
19045
+ const target = artifactTarget(artifact);
19046
+ if (!target) return escapeHtml(artifact.name);
19047
+ return `<a href="${escapeHtml(target)}">${escapeHtml(artifact.name)}</a>`;
19048
+ }
19049
+ function htmlList(items, emptyText) {
19050
+ if (!items.length) return `<p class="muted">${escapeHtml(emptyText)}</p>`;
19051
+ return `<ul>${items.map((item) => `<li>${escapeHtml(item)}</li>`).join("")}</ul>`;
19052
+ }
19053
+ function riddleProofChangeReceiptHtml(receipt) {
19054
+ const artifactLinks = [...receipt.before.artifacts, ...receipt.after.artifacts].filter((artifact) => artifactTarget(artifact)).slice(0, 32);
19055
+ const deltaRows = receipt.deltas.map((delta) => `
19056
+ <tr>
19057
+ <td>${escapeHtml(delta.label)}</td>
19058
+ <td><span class="status ${escapeHtml(delta.status)}">${escapeHtml(delta.status)}</span></td>
19059
+ <td>${escapeHtml(delta.before_observed)}</td>
19060
+ <td>${escapeHtml(delta.after_observed)}</td>
19061
+ </tr>
19062
+ ${delta.message ? `<tr><td class="muted">${escapeHtml(delta.label)} message</td><td colspan="3">${escapeHtml(delta.message)}</td></tr>` : ""}`).join("");
19063
+ return `<!doctype html>
19064
+ <html lang="en">
19065
+ <head>
19066
+ <meta charset="utf-8">
19067
+ <meta name="viewport" content="width=device-width, initial-scale=1">
19068
+ <title>${escapeHtml(receipt.contract_name)} - Riddle Proof Change Receipt</title>
19069
+ <style>
19070
+ :root { color-scheme: light dark; --bg: #0f141b; --panel: #171f29; --text: #eef4f8; --muted: #aebbc8; --border: #314152; --ok: #69d089; --bad: #ff7a7a; --warn: #ffd166; }
19071
+ body { margin: 0; font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: var(--bg); color: var(--text); }
19072
+ main { max-width: 1120px; margin: 0 auto; padding: 32px 20px 48px; }
19073
+ header, section { border: 1px solid var(--border); background: var(--panel); border-radius: 8px; padding: 20px; margin: 0 0 18px; }
19074
+ h1, h2, h3, p { margin-top: 0; }
19075
+ h1 { font-size: clamp(1.6rem, 3vw, 2.4rem); }
19076
+ h2 { font-size: 1.1rem; margin-bottom: 14px; }
19077
+ .muted { color: var(--muted); }
19078
+ .verdict { display: inline-flex; align-items: center; gap: 8px; padding: 6px 10px; border-radius: 999px; border: 1px solid var(--border); font-weight: 700; }
19079
+ .mergeable, .passed { color: var(--ok); }
19080
+ .not_mergeable, .failed, .product_regression { color: var(--bad); }
19081
+ .proof_insufficient, .environment_blocked, .needs_human_review, .configuration_error { color: var(--warn); }
19082
+ .grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
19083
+ .side { border: 1px solid var(--border); border-radius: 8px; padding: 14px; min-width: 0; }
19084
+ code { overflow-wrap: anywhere; color: var(--muted); }
19085
+ table { width: 100%; border-collapse: collapse; }
19086
+ th, td { border-bottom: 1px solid var(--border); padding: 10px 8px; text-align: left; vertical-align: top; }
19087
+ figure { margin: 0; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: #0b1017; }
19088
+ img { display: block; width: 100%; height: auto; }
19089
+ figcaption { padding: 8px 10px; color: var(--muted); font-size: 0.9rem; }
19090
+ ul { margin-bottom: 0; }
19091
+ a { color: #8bc7ff; }
19092
+ @media (max-width: 760px) { .grid { grid-template-columns: 1fr; } main { padding: 18px 12px 32px; } }
19093
+ </style>
19094
+ </head>
19095
+ <body>
19096
+ <main>
19097
+ <header>
19098
+ <p class="verdict ${escapeHtml(receipt.verdict)}">${escapeHtml(receipt.verdict)}</p>
19099
+ <h1>${escapeHtml(receipt.contract_name)}</h1>
19100
+ <p>${escapeHtml(receipt.summary)}</p>
19101
+ <p class="muted">Status: ${escapeHtml(receipt.status)}${receipt.profile_name ? ` | Profile: ${escapeHtml(receipt.profile_name)}` : ""}</p>
19102
+ </header>
19103
+ <section>
19104
+ <h2>Evidence Pair</h2>
19105
+ <div class="grid">
19106
+ <div class="side">
19107
+ <h3>Before</h3>
19108
+ <p><code>${escapeHtml(receipt.before.source)}</code></p>
19109
+ <p>Status: <strong class="${escapeHtml(receipt.before.status)}">${escapeHtml(receipt.before.status)}</strong></p>
19110
+ <p>${escapeHtml(receipt.before.summary)}</p>
19111
+ <p class="muted">${receipt.before.checks.passed} passed / ${receipt.before.checks.failed} failed checks</p>
19112
+ </div>
19113
+ <div class="side">
19114
+ <h3>After</h3>
19115
+ <p><code>${escapeHtml(receipt.after.source)}</code></p>
19116
+ <p>Status: <strong class="${escapeHtml(receipt.after.status)}">${escapeHtml(receipt.after.status)}</strong></p>
19117
+ <p>${escapeHtml(receipt.after.summary)}</p>
19118
+ <p class="muted">${receipt.after.checks.passed} passed / ${receipt.after.checks.failed} failed checks</p>
19119
+ </div>
19120
+ </div>
19121
+ </section>
19122
+ <section>
19123
+ <h2>Delta Checks</h2>
19124
+ <table>
19125
+ <thead><tr><th>Delta</th><th>Status</th><th>Before</th><th>After</th></tr></thead>
19126
+ <tbody>${deltaRows}</tbody>
19127
+ </table>
19128
+ </section>
19129
+ <section>
19130
+ <h2>Screenshots</h2>
19131
+ <div class="grid">
19132
+ <div>${receipt.before.screenshots.slice(0, 4).map(htmlArtifactCard).join("") || `<p class="muted">No before screenshots recorded.</p>`}</div>
19133
+ <div>${receipt.after.screenshots.slice(0, 4).map(htmlArtifactCard).join("") || `<p class="muted">No after screenshots recorded.</p>`}</div>
19134
+ </div>
19135
+ </section>
19136
+ <section>
19137
+ <h2>What This Proves</h2>
19138
+ ${htmlList(receipt.proves, "No explicit proof claims were recorded in contract metadata.")}
19139
+ </section>
19140
+ <section>
19141
+ <h2>What This Does Not Prove</h2>
19142
+ ${htmlList(receipt.does_not_prove, "No explicit limits were recorded in contract metadata.")}
19143
+ </section>
19144
+ <section>
19145
+ <h2>Artifacts</h2>
19146
+ ${artifactLinks.length ? `<ul>${artifactLinks.map((artifact) => `<li>${escapeHtml(artifact.side)}: ${htmlArtifactLink(artifact)}</li>`).join("")}</ul>` : `<p class="muted">No linked artifacts recorded.</p>`}
19147
+ </section>
19148
+ </main>
19149
+ </body>
19150
+ </html>
19151
+ `;
19152
+ }
18771
19153
 
18772
19154
  // src/cli.ts
18773
19155
  var RIDDLE_PROFILE_BALANCE_PREFLIGHT_MIN_SECONDS_PER_JOB = 30;
@@ -22706,6 +23088,9 @@ function compactChangeProofResult(run, options) {
22706
23088
  output_dir: outputDir,
22707
23089
  output_files: outputDir ? {
22708
23090
  change_proof_result: "change-proof-result.json",
23091
+ change_proof_receipt: "change-proof-receipt.json",
23092
+ change_proof_receipt_markdown: "change-proof-receipt.md",
23093
+ change_proof_receipt_html: "change-proof-receipt.html",
22709
23094
  summary: "summary.md",
22710
23095
  before_profile_result: "before/profile-result.json",
22711
23096
  after_profile_result: "after/profile-result.json"
@@ -22713,47 +23098,17 @@ function compactChangeProofResult(run, options) {
22713
23098
  };
22714
23099
  }
22715
23100
  function changeProofResultMarkdown(run) {
22716
- const lines = [
22717
- "# Riddle Proof Change Proof",
22718
- "",
22719
- `Contract: ${run.result.contract_name}`,
22720
- `Profile: ${run.profile.name}`,
22721
- `Status: ${run.result.status}`,
22722
- "",
22723
- run.result.summary,
22724
- "",
22725
- "## Before",
22726
- "",
22727
- `- source: ${markdownInlineCode(run.beforeSource, 160)}`,
22728
- `- profile: ${run.beforeResult.profile_name}`,
22729
- `- status: ${run.beforeResult.status}`,
22730
- `- summary: ${run.beforeResult.summary}`,
22731
- "",
22732
- "## After",
22733
- "",
22734
- `- source: ${markdownInlineCode(run.afterSource, 160)}`,
22735
- `- profile: ${run.afterResult.profile_name}`,
22736
- `- status: ${run.afterResult.status}`,
22737
- `- summary: ${run.afterResult.summary}`,
22738
- "",
22739
- "## Deltas",
22740
- ""
22741
- ];
22742
- for (const delta of run.result.deltas) {
22743
- const observed = [
22744
- delta.before_observed !== void 0 ? `before ${markdownInlineCode(String(delta.before_observed))}` : "",
22745
- delta.after_observed !== void 0 ? `after ${markdownInlineCode(String(delta.after_observed))}` : ""
22746
- ].filter(Boolean).join(" -> ");
22747
- lines.push(`- ${delta.status}: ${delta.label}${observed ? ` (${observed})` : ""}${delta.message ? ` - ${delta.message}` : ""}`);
22748
- }
22749
- return `${lines.join("\n")}
22750
- `;
23101
+ return riddleProofChangeReceiptMarkdown(run.receipt);
22751
23102
  }
22752
23103
  function writeChangeProofOutput(outputDir, run) {
22753
23104
  if (!outputDir) return;
22754
23105
  (0, import_node_fs6.mkdirSync)(outputDir, { recursive: true });
22755
23106
  (0, import_node_fs6.writeFileSync)(import_node_path6.default.join(outputDir, "change-proof-result.json"), `${JSON.stringify(run.result, null, 2)}
22756
23107
  `);
23108
+ (0, import_node_fs6.writeFileSync)(import_node_path6.default.join(outputDir, "change-proof-receipt.json"), `${JSON.stringify(run.receipt, null, 2)}
23109
+ `);
23110
+ (0, import_node_fs6.writeFileSync)(import_node_path6.default.join(outputDir, "change-proof-receipt.md"), riddleProofChangeReceiptMarkdown(run.receipt));
23111
+ (0, import_node_fs6.writeFileSync)(import_node_path6.default.join(outputDir, "change-proof-receipt.html"), riddleProofChangeReceiptHtml(run.receipt));
22757
23112
  (0, import_node_fs6.writeFileSync)(import_node_path6.default.join(outputDir, "summary.md"), changeProofResultMarkdown(run));
22758
23113
  writeProfileOutput(changeProofSideOutputDir(outputDir, "before"), run.beforeResult);
22759
23114
  writeProfileOutput(changeProofSideOutputDir(outputDir, "after"), run.afterResult);
@@ -23668,7 +24023,16 @@ async function runChangeProofForCli(rawProfile, options) {
23668
24023
  before_result: beforeResult,
23669
24024
  after_result: afterResult
23670
24025
  });
23671
- return { profile, contract, beforeResult, afterResult, result, beforeSource, afterSource };
24026
+ const receipt = createRiddleProofChangeReceipt({
24027
+ contract,
24028
+ result,
24029
+ before_result: beforeResult,
24030
+ after_result: afterResult,
24031
+ before_source: beforeSource,
24032
+ after_source: afterSource,
24033
+ profile_name: profile.name
24034
+ });
24035
+ return { profile, contract, beforeResult, afterResult, result, receipt, beforeSource, afterSource };
23672
24036
  }
23673
24037
  function requestForRun(options) {
23674
24038
  const statePath = optionString(options, "statePath");
@@ -23752,6 +24116,8 @@ async function main() {
23752
24116
  const runResponsePath = explicitRunResponsePath || defaultProofDirJsonPath(proofDir, "riddle-run-response.json");
23753
24117
  const resultJsonPaths = explicitResultJsonPath ? [explicitResultJsonPath] : [
23754
24118
  defaultProofDirJsonPath(proofDir, "result.json"),
24119
+ defaultProofDirJsonPath(proofDir, "change-proof-receipt.json"),
24120
+ defaultProofDirJsonPath(proofDir, "change-proof-result.json"),
23755
24121
  defaultProofDirJsonPath(proofDir, "profile-result.json")
23756
24122
  ];
23757
24123
  const runResponse = readJsonFileIfExists(runResponsePath);
package/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-AK2EPEVO.js";
2
+ import "./chunk-H25IDX76.js";
3
3
  import "./chunk-B2DP2LET.js";
4
4
  import "./chunk-JFQXAJH2.js";
5
- import "./chunk-CWRIXP5H.js";
5
+ import "./chunk-IY4W6STC.js";
6
6
  import "./chunk-UE4I7RTI.js";
7
7
  import "./chunk-GG2D3MFZ.js";
8
- import "./chunk-6S7DZWVC.js";
8
+ import "./chunk-BILL3UC2.js";
9
9
  import "./chunk-KXLEN4SA.js";
10
10
  import "./chunk-WLUMLHII.js";
11
11
  import "./chunk-CGJX7LJO.js";