@riddledc/riddle-proof 0.8.77 → 0.8.79

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 (48) hide show
  1. package/README.md +65 -3
  2. package/dist/change-proof.cjs +744 -85
  3. package/dist/change-proof.d.cts +100 -8
  4. package/dist/change-proof.d.ts +100 -8
  5. package/dist/change-proof.js +15 -1
  6. package/dist/{chunk-B2DP2LET.js → chunk-5IFZSUPF.js} +52 -13
  7. package/dist/chunk-6VFS2JFR.js +886 -0
  8. package/dist/{chunk-IY4W6STC.js → chunk-7N6X54WG.js} +116 -17
  9. package/dist/{chunk-GG2D3MFZ.js → chunk-FCSJZBC5.js} +26 -1
  10. package/dist/chunk-MEVVL4TI.js +258 -0
  11. package/dist/{chunk-H25IDX76.js → chunk-NEXWITV4.js} +221 -35
  12. package/dist/{chunk-UE4I7RTI.js → chunk-RQPCKRKT.js} +1 -1
  13. package/dist/cli/index.js +7 -6
  14. package/dist/cli.cjs +2026 -1060
  15. package/dist/cli.js +7 -6
  16. package/dist/index.cjs +932 -122
  17. package/dist/index.d.cts +4 -3
  18. package/dist/index.d.ts +4 -3
  19. package/dist/index.js +42 -14
  20. package/dist/pr-comment.cjs +416 -17
  21. package/dist/pr-comment.d.cts +6 -1
  22. package/dist/pr-comment.d.ts +6 -1
  23. package/dist/pr-comment.js +6 -1
  24. package/dist/profile/index.cjs +26 -1
  25. package/dist/profile/index.js +1 -1
  26. package/dist/profile-suggestions.js +2 -2
  27. package/dist/profile.cjs +26 -1
  28. package/dist/profile.d.cts +7 -0
  29. package/dist/profile.d.ts +7 -0
  30. package/dist/profile.js +1 -1
  31. package/dist/receipts.cjs +286 -0
  32. package/dist/receipts.d.cts +115 -0
  33. package/dist/receipts.d.ts +115 -0
  34. package/dist/receipts.js +15 -0
  35. package/dist/riddle-client.cjs +98 -13
  36. package/dist/riddle-client.d.cts +18 -5
  37. package/dist/riddle-client.d.ts +18 -5
  38. package/dist/riddle-client.js +4 -1
  39. package/dist/runtime/index.cjs +98 -13
  40. package/dist/runtime/index.d.cts +5 -1
  41. package/dist/runtime/index.d.ts +5 -1
  42. package/dist/runtime/index.js +4 -1
  43. package/dist/runtime/riddle-client.cjs +98 -13
  44. package/dist/runtime/riddle-client.d.cts +5 -1
  45. package/dist/runtime/riddle-client.d.ts +5 -1
  46. package/dist/runtime/riddle-client.js +4 -1
  47. package/package.json +7 -2
  48. package/dist/chunk-BILL3UC2.js +0 -488
@@ -3,15 +3,27 @@ import {
3
3
  createRiddleApiClient,
4
4
  isTerminalRiddleJobStatus,
5
5
  parseRiddleViewport
6
- } from "./chunk-B2DP2LET.js";
6
+ } from "./chunk-5IFZSUPF.js";
7
7
  import {
8
8
  RIDDLE_PROOF_PR_COMMENT_MARKER,
9
9
  buildRiddleProofPrCommentMarkdown,
10
10
  summarizeRiddleProofPrComment
11
- } from "./chunk-IY4W6STC.js";
11
+ } from "./chunk-7N6X54WG.js";
12
12
  import {
13
13
  suggestRiddleProofProfileChecks
14
- } from "./chunk-UE4I7RTI.js";
14
+ } from "./chunk-RQPCKRKT.js";
15
+ import {
16
+ assessRiddleProofChange,
17
+ createRiddleProofChangeReceipt,
18
+ createRiddleProofHandoffReceipt,
19
+ riddleProofChangeReceiptHtml,
20
+ riddleProofChangeReceiptMarkdown
21
+ } from "./chunk-6VFS2JFR.js";
22
+ import {
23
+ createRiddleProofObservationReceipt,
24
+ parseRiddlePreviewReceipt,
25
+ parseRiddleProofObservationReceipt
26
+ } from "./chunk-MEVVL4TI.js";
15
27
  import {
16
28
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
17
29
  applyRiddleProofProfileArtifactCompleteness,
@@ -29,13 +41,7 @@ import {
29
41
  profileStatusExitCode,
30
42
  resolveRiddleProofProfileTargetUrl,
31
43
  resolveRiddleProofProfileTimeoutSec
32
- } from "./chunk-GG2D3MFZ.js";
33
- import {
34
- assessRiddleProofChange,
35
- createRiddleProofChangeReceipt,
36
- riddleProofChangeReceiptHtml,
37
- riddleProofChangeReceiptMarkdown
38
- } from "./chunk-BILL3UC2.js";
44
+ } from "./chunk-FCSJZBC5.js";
39
45
  import {
40
46
  createCodexExecAgentAdapter,
41
47
  runCodexExecAgentDoctor
@@ -64,8 +70,14 @@ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
64
70
  "balancePreflight",
65
71
  "baseUrl",
66
72
  "afterResult",
73
+ "afterObservation",
74
+ "afterPreviewReceipt",
75
+ "afterSourceRevision",
67
76
  "afterUrl",
68
77
  "beforeResult",
78
+ "beforeObservation",
79
+ "beforePreviewReceipt",
80
+ "beforeSourceRevision",
69
81
  "beforeUrl",
70
82
  "candidateJson",
71
83
  "candidatesJson",
@@ -119,6 +131,7 @@ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
119
131
  "pack",
120
132
  "packFile",
121
133
  "profile",
134
+ "previewReceipt",
122
135
  "proofDir",
123
136
  "pr",
124
137
  "progressEveryMs",
@@ -142,6 +155,9 @@ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
142
155
  "scriptFile",
143
156
  "selectors",
144
157
  "sourceKind",
158
+ "sourceDirty",
159
+ "sourceRepository",
160
+ "sourceRevision",
145
161
  "splitViewports",
146
162
  "stateDir",
147
163
  "statePath",
@@ -173,16 +189,16 @@ function usage() {
173
189
  " riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
174
190
  " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
175
191
  " riddle-proof-loop status --state-path <path>",
176
- " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--base-url <base-url>] [--runner riddle] [--viewport-name <name[,name...]>] [--strict true|false; default false] [--split-viewports true|false; default false] [--balance-preflight true|false; default true] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json] [--quiet]",
192
+ " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--preview-receipt <file|json>] [--source-revision <sha>] [--runner riddle] [--viewport-name <name[,name...]>] [--strict true|false; default false] [--split-viewports true|false; default false] [--balance-preflight true|false; default true] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json] [--quiet]",
177
193
  " riddle-proof-loop run-profile aggregate --profile <file|json|-> --url <base-url> [--base-url <base-url>] --input-dir <dir>|--inputs <path[,path...]> [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
178
194
  " riddle-proof-loop run-profile recover --profile <file|json|-> --url <base-url> [--base-url <base-url>] --job <job-id> [--viewport-name <name[,name...]>] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
179
- " riddle-proof-loop run-change-proof --profile <file|json|-> --change-contract <file|json|-> (--before-url <url> --after-url <url> | --before-result <file> --after-result <file>) [--viewport-name <name[,name...]>] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
195
+ " riddle-proof-loop run-change-proof --profile <file|json|-> --change-contract <file|json|-> (--before-url <url> --after-url <url> | --before-result <file> --after-result <file> | --before-observation <file> --after-observation <file>) [--before-preview-receipt <file|json>] [--after-preview-receipt <file|json>] [--before-source-revision <sha>] [--after-source-revision <sha>] [--viewport-name <name[,name...]>] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
180
196
  " riddle-proof-loop profile-suggest --route /path|--url <url> [--changed-files a,b] [--selectors .a,.b] [--changed-text-json <file|json|->] [--format json|profile]",
181
197
  " riddle-proof-loop regression-pack run [--pack oc-flow-regression|--pack-file <file>] [--local-core true|false; default true] [--hosted-riddle true|false; default false] [--format json|markdown|compact-json; default json] [--output <dir>|--output-dir <dir>]",
182
198
  " riddle-proof-loop pr-comment --proof-dir <dir>|--run-response <file> [--result-json <file>] --pr <number|url> [--repo owner/name] [--dry-run] [--body-file <file>] [--comment-mode update|append]",
183
199
  " riddle-proof-loop profile-body-assertions --artifact <file|url|-> --candidates-json <file|json|-> [--required-json <file|json|->] [--format json|body-contains]",
184
200
  " riddle-proof-loop profile-http-status-preflight --profile <file|json|-> --url <base-url> [--format json|summary]",
185
- " riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static] [--quiet]",
201
+ " riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static] [--output <dir>] [--quiet]",
186
202
  " riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
187
203
  " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
188
204
  " riddle-proof-loop riddle-poll <job-id> [--wait] [--attempts n] [--quiet]",
@@ -342,6 +358,7 @@ function compactRunProfileResult(result, options) {
342
358
  output_dir: outputDir,
343
359
  output_files: outputDir ? {
344
360
  profile_result: "profile-result.json",
361
+ observation_receipt: "observation-receipt.json",
345
362
  summary: "summary.md",
346
363
  proof_json: result.evidence ? "proof.json" : void 0,
347
364
  console: result.evidence?.console ? "console.json" : void 0,
@@ -970,12 +987,13 @@ function formatByteCount(bytes) {
970
987
  }
971
988
  function riddlePollProgressLine(snapshot) {
972
989
  const submittedAt = snapshot.submitted_at || "not-submitted";
973
- const queuePart = snapshot.running_without_submission ? ` waiting_for_worker_submit=${formatPollDuration(snapshot.pre_submission_elapsed_ms)} worker_wake=possible${snapshot.queue_elapsed_ms !== null ? ` queued_for=${formatPollDuration(snapshot.queue_elapsed_ms)}` : ""}` : snapshot.queue_elapsed_ms !== null ? ` queue=${formatPollDuration(snapshot.queue_elapsed_ms)}` : "";
990
+ const queuePart = snapshot.active_execution ? `${snapshot.queue_elapsed_ms !== null ? ` queue=${formatPollDuration(snapshot.queue_elapsed_ms)}` : ""} active_execution=${formatPollDuration(snapshot.elapsed_ms)}` : snapshot.running_without_submission ? ` waiting_for_worker_claim=${formatPollDuration(snapshot.pre_submission_elapsed_ms)} worker_wake=possible${snapshot.queue_elapsed_ms !== null ? ` queued_for=${formatPollDuration(snapshot.queue_elapsed_ms)}` : ""}` : snapshot.queue_elapsed_ms !== null ? ` queue=${formatPollDuration(snapshot.queue_elapsed_ms)}` : "";
974
991
  const terminalPart = snapshot.terminal ? " terminal=true" : "";
975
992
  return [
976
993
  "[riddle-poll]",
977
994
  snapshot.job_id,
978
995
  `status=${snapshot.status || "unknown"}`,
996
+ `phase=${snapshot.phase || "unknown"}`,
979
997
  `attempt=${snapshot.attempt}/${snapshot.attempts}`,
980
998
  `elapsed=${formatPollDuration(snapshot.elapsed_ms)}`,
981
999
  `submitted_at=${submittedAt}${queuePart}${terminalPart}`
@@ -3913,10 +3931,63 @@ function profileHttpStatusSummaryMarkdown(result) {
3913
3931
  }
3914
3932
  return lines;
3915
3933
  }
3916
- function writeProfileOutput(outputDir, result) {
3934
+ function profileResultTargetUrl(result) {
3935
+ const legacyRoute = result.route;
3936
+ const observed = result.route.observed;
3937
+ const requested = result.route.requested || legacyRoute.url || result.evidence?.target_url;
3938
+ if (observed) {
3939
+ try {
3940
+ return new URL(observed, requested).href;
3941
+ } catch {
3942
+ }
3943
+ }
3944
+ if (requested) {
3945
+ try {
3946
+ return new URL(requested).href;
3947
+ } catch {
3948
+ return requested;
3949
+ }
3950
+ }
3951
+ return observed || "unknown";
3952
+ }
3953
+ function profileObservationForOutput(result, outputDir, options) {
3954
+ if (options.observation) return options.observation;
3955
+ const preview = options.previewReceipt;
3956
+ const targetUrl = profileResultTargetUrl(result);
3957
+ return createRiddleProofObservationReceipt({
3958
+ comparison_role: options.comparisonRole || "standalone",
3959
+ executor: result.runner === "local-playwright" ? { kind: "local_playwright", runner: result.runner } : {
3960
+ kind: "riddle_hosted",
3961
+ runner: result.runner,
3962
+ job_id: result.riddle?.job_id,
3963
+ worker_id: typeof result.riddle?.execution?.worker_id === "string" ? result.riddle.execution.worker_id : void 0
3964
+ },
3965
+ target: preview ? { kind: "preview", url: targetUrl, preview } : { kind: "url", url: targetUrl },
3966
+ source: options.source || preview?.source,
3967
+ profile_result: result,
3968
+ publication: { kind: "local", path: outputDir },
3969
+ execution: result.riddle?.execution
3970
+ });
3971
+ }
3972
+ function profileOutputOptionsForCli(options) {
3973
+ const previewInput = optionString(options, "previewReceipt");
3974
+ const previewReceipt = previewInput ? parseRiddlePreviewReceipt(readJsonValue(previewInput, "--preview-receipt")) : void 0;
3975
+ const sourceDirty = optionBoolean(options, "sourceDirty");
3976
+ const source = {
3977
+ ...previewReceipt?.source || {},
3978
+ ...optionString(options, "sourceRevision") ? { git_revision: optionString(options, "sourceRevision") } : {},
3979
+ ...optionString(options, "sourceRepository") ? { repository: optionString(options, "sourceRepository") } : {},
3980
+ ...typeof sourceDirty === "boolean" ? { dirty: sourceDirty } : {}
3981
+ };
3982
+ return { previewReceipt, source };
3983
+ }
3984
+ function writeProfileOutput(outputDir, result, options = {}) {
3917
3985
  if (!outputDir) return;
3918
3986
  mkdirSync(outputDir, { recursive: true });
3919
3987
  writeFileSync(path.join(outputDir, "profile-result.json"), `${JSON.stringify(result, null, 2)}
3988
+ `);
3989
+ const observation = profileObservationForOutput(result, outputDir, options);
3990
+ writeFileSync(path.join(outputDir, "observation-receipt.json"), `${JSON.stringify(observation, null, 2)}
3920
3991
  `);
3921
3992
  writeFileSync(path.join(outputDir, "summary.md"), profileResultMarkdown(result));
3922
3993
  if (result.evidence) writeFileSync(path.join(outputDir, "proof.json"), `${JSON.stringify(result, null, 2)}
@@ -3957,6 +4028,12 @@ function profileOptionsForChangeProofSide(options, url, outputDir) {
3957
4028
  }
3958
4029
  return next;
3959
4030
  }
4031
+ function observationForChangeSide(observation, side) {
4032
+ if (observation.comparison_role !== "standalone" && observation.comparison_role !== side) {
4033
+ throw new Error(`${side} observation has incompatible comparison_role ${observation.comparison_role}.`);
4034
+ }
4035
+ return observation.comparison_role === side ? observation : { ...observation, comparison_role: side };
4036
+ }
3960
4037
  function compactChangeProofResult(run, options) {
3961
4038
  const outputDir = profileOutputDirOption(options);
3962
4039
  return {
@@ -3992,9 +4069,13 @@ function compactChangeProofResult(run, options) {
3992
4069
  change_proof_receipt: "change-proof-receipt.json",
3993
4070
  change_proof_receipt_markdown: "change-proof-receipt.md",
3994
4071
  change_proof_receipt_html: "change-proof-receipt.html",
4072
+ handoff_receipt: "handoff-receipt.json",
4073
+ handoff_receipt_markdown: "handoff-receipt.md",
3995
4074
  summary: "summary.md",
3996
4075
  before_profile_result: "before/profile-result.json",
3997
- after_profile_result: "after/profile-result.json"
4076
+ after_profile_result: "after/profile-result.json",
4077
+ before_observation_receipt: "before/observation-receipt.json",
4078
+ after_observation_receipt: "after/observation-receipt.json"
3998
4079
  } : void 0
3999
4080
  };
4000
4081
  }
@@ -4010,9 +4091,12 @@ function writeChangeProofOutput(outputDir, run) {
4010
4091
  `);
4011
4092
  writeFileSync(path.join(outputDir, "change-proof-receipt.md"), riddleProofChangeReceiptMarkdown(run.receipt));
4012
4093
  writeFileSync(path.join(outputDir, "change-proof-receipt.html"), riddleProofChangeReceiptHtml(run.receipt));
4094
+ writeFileSync(path.join(outputDir, "handoff-receipt.json"), `${JSON.stringify(run.handoff, null, 2)}
4095
+ `);
4096
+ writeFileSync(path.join(outputDir, "handoff-receipt.md"), buildRiddleProofPrCommentMarkdown({ result: run.handoff }));
4013
4097
  writeFileSync(path.join(outputDir, "summary.md"), changeProofResultMarkdown(run));
4014
- writeProfileOutput(changeProofSideOutputDir(outputDir, "before"), run.beforeResult);
4015
- writeProfileOutput(changeProofSideOutputDir(outputDir, "after"), run.afterResult);
4098
+ writeProfileOutput(changeProofSideOutputDir(outputDir, "before"), run.beforeResult, { observation: run.beforeObservation });
4099
+ writeProfileOutput(changeProofSideOutputDir(outputDir, "after"), run.afterResult, { observation: run.afterObservation });
4016
4100
  }
4017
4101
  function writeRunChangeProofResult(run, options) {
4018
4102
  const format = runProfileResultFormatOption(options);
@@ -4111,6 +4195,7 @@ function withRiddleMetadata(result, input) {
4111
4195
  ...result.riddle || {},
4112
4196
  job_id: input.job_id || result.riddle?.job_id,
4113
4197
  status: input.status ?? result.riddle?.status,
4198
+ phase: poll?.phase ?? result.riddle?.phase,
4114
4199
  terminal: input.terminal ?? result.riddle?.terminal,
4115
4200
  created_at: poll?.created_at ?? result.riddle?.created_at,
4116
4201
  submitted_at: poll?.submitted_at ?? result.riddle?.submitted_at,
@@ -4123,7 +4208,8 @@ function withRiddleMetadata(result, input) {
4123
4208
  timed_out: poll?.timed_out ?? result.riddle?.timed_out,
4124
4209
  retry_count: input.retryCount ?? result.riddle?.retry_count,
4125
4210
  stale_job_ids: staleJobIds?.length ? staleJobIds : result.riddle?.stale_job_ids,
4126
- artifact_recovery: input.artifactRecovery ?? result.riddle?.artifact_recovery
4211
+ artifact_recovery: input.artifactRecovery ?? result.riddle?.artifact_recovery,
4212
+ execution: poll?.execution ?? result.riddle?.execution
4127
4213
  },
4128
4214
  artifacts: {
4129
4215
  ...result.artifacts,
@@ -4191,6 +4277,7 @@ function riddleMetadataFromPoll(jobId, poll) {
4191
4277
  return {
4192
4278
  job_id: jobId,
4193
4279
  status: poll.status,
4280
+ phase: poll.poll?.phase,
4194
4281
  terminal: poll.terminal,
4195
4282
  created_at: poll.poll?.created_at,
4196
4283
  submitted_at: poll.poll?.submitted_at,
@@ -4200,7 +4287,8 @@ function riddleMetadataFromPoll(jobId, poll) {
4200
4287
  elapsed_ms: poll.poll?.elapsed_ms,
4201
4288
  attempt: poll.poll?.attempt,
4202
4289
  attempts: poll.poll?.attempts,
4203
- timed_out: poll.poll?.timed_out
4290
+ timed_out: poll.poll?.timed_out,
4291
+ execution: poll.poll?.execution
4204
4292
  };
4205
4293
  }
4206
4294
  function profileUnsubmittedRetryTimeoutMs(options) {
@@ -4746,7 +4834,7 @@ async function runSplitViewportProfileForCli(profile, options, input) {
4746
4834
  const childProfile = profileForSplitViewport(profile, viewport);
4747
4835
  const childOutputDir = outputDir ? splitViewportOutputDir(outputDir, viewport.name, seenOutputNames) : void 0;
4748
4836
  const result2 = await runSingleRiddleProfileForCli(childProfile, options, { ...input, outputDir: childOutputDir });
4749
- if (childOutputDir) writeProfileOutput(childOutputDir, result2);
4837
+ if (childOutputDir) writeProfileOutput(childOutputDir, result2, profileOutputOptionsForCli(options));
4750
4838
  childRuns.push({ viewport, profile: childProfile, result: result2 });
4751
4839
  }
4752
4840
  const artifacts = childRuns.flatMap(splitViewportArtifactRefs);
@@ -4878,18 +4966,34 @@ async function runChangeProofForCli(rawProfile, options) {
4878
4966
  const contract = readChangeContractForCli(options);
4879
4967
  const beforeResultPath = optionString(options, "beforeResult");
4880
4968
  const afterResultPath = optionString(options, "afterResult");
4969
+ const beforeObservationPath = optionString(options, "beforeObservation");
4970
+ const afterObservationPath = optionString(options, "afterObservation");
4881
4971
  const beforeUrl = optionString(options, "beforeUrl");
4882
4972
  const afterUrl = optionString(options, "afterUrl");
4973
+ const beforePreviewInput = optionString(options, "beforePreviewReceipt");
4974
+ const afterPreviewInput = optionString(options, "afterPreviewReceipt");
4975
+ const beforePreview = beforePreviewInput ? parseRiddlePreviewReceipt(readJsonValue(beforePreviewInput, "--before-preview-receipt")) : void 0;
4976
+ const afterPreview = afterPreviewInput ? parseRiddlePreviewReceipt(readJsonValue(afterPreviewInput, "--after-preview-receipt")) : void 0;
4883
4977
  const hasResultInputs = Boolean(beforeResultPath || afterResultPath);
4978
+ const hasObservationInputs = Boolean(beforeObservationPath || afterObservationPath);
4884
4979
  const hasUrlInputs = Boolean(beforeUrl || afterUrl);
4885
- if (hasResultInputs && hasUrlInputs) {
4886
- throw new Error("run-change-proof accepts either --before-result/--after-result or --before-url/--after-url, not both.");
4980
+ if ([hasResultInputs, hasObservationInputs, hasUrlInputs].filter(Boolean).length > 1) {
4981
+ throw new Error("run-change-proof accepts one before/after input pair: result, observation, or URL.");
4887
4982
  }
4888
4983
  if (hasResultInputs && (!beforeResultPath || !afterResultPath)) {
4889
4984
  throw new Error("run-change-proof requires both --before-result and --after-result.");
4890
4985
  }
4891
- if (!hasResultInputs && (!beforeUrl || !afterUrl)) {
4892
- throw new Error("run-change-proof requires both --before-url and --after-url unless saved results are provided.");
4986
+ if (hasObservationInputs && (!beforeObservationPath || !afterObservationPath)) {
4987
+ throw new Error("run-change-proof requires both --before-observation and --after-observation.");
4988
+ }
4989
+ if (hasUrlInputs && (!beforeUrl || !afterUrl)) {
4990
+ throw new Error("run-change-proof requires both --before-url and --after-url.");
4991
+ }
4992
+ if (!hasResultInputs && !hasObservationInputs && !hasUrlInputs) {
4993
+ throw new Error("run-change-proof requires a before/after result, observation, or URL pair.");
4994
+ }
4995
+ if ((beforePreview || afterPreview) && !hasUrlInputs) {
4996
+ throw new Error("--before-preview-receipt and --after-preview-receipt require the URL input mode.");
4893
4997
  }
4894
4998
  const outputDir = profileOutputDirOption(options);
4895
4999
  let profile;
@@ -4897,15 +5001,53 @@ async function runChangeProofForCli(rawProfile, options) {
4897
5001
  let afterResult;
4898
5002
  let beforeSource;
4899
5003
  let afterSource;
4900
- if (hasResultInputs) {
5004
+ let beforeObservation;
5005
+ let afterObservation;
5006
+ if (hasObservationInputs) {
5007
+ if (!beforeObservationPath || !afterObservationPath) {
5008
+ throw new Error("run-change-proof requires both --before-observation and --after-observation.");
5009
+ }
5010
+ profile = profileWithSelectedViewportNamesForCli(normalizeProfileRecordForCli(rawProfile, options), options);
5011
+ beforeObservation = observationForChangeSide(
5012
+ parseRiddleProofObservationReceipt(readJsonValue(beforeObservationPath, "--before-observation")),
5013
+ "before"
5014
+ );
5015
+ afterObservation = observationForChangeSide(
5016
+ parseRiddleProofObservationReceipt(readJsonValue(afterObservationPath, "--after-observation")),
5017
+ "after"
5018
+ );
5019
+ if (!beforeObservation.proof?.result || !afterObservation.proof?.result) {
5020
+ throw new Error("Change Proof observations must include their profile results.");
5021
+ }
5022
+ beforeResult = beforeObservation.proof.result;
5023
+ afterResult = afterObservation.proof.result;
5024
+ beforeSource = beforeObservation.target.url;
5025
+ afterSource = afterObservation.target.url;
5026
+ } else if (hasResultInputs) {
4901
5027
  if (!beforeResultPath || !afterResultPath) {
4902
5028
  throw new Error("run-change-proof requires both --before-result and --after-result.");
4903
5029
  }
4904
5030
  profile = profileWithSelectedViewportNamesForCli(normalizeProfileRecordForCli(rawProfile, options), options);
4905
5031
  beforeResult = readProfileResultForCli(beforeResultPath, "--before-result");
4906
5032
  afterResult = readProfileResultForCli(afterResultPath, "--after-result");
4907
- beforeSource = beforeResultPath;
4908
- afterSource = afterResultPath;
5033
+ beforeSource = profileResultTargetUrl(beforeResult);
5034
+ afterSource = profileResultTargetUrl(afterResult);
5035
+ beforeObservation = createRiddleProofObservationReceipt({
5036
+ comparison_role: "before",
5037
+ executor: { kind: beforeResult.runner === "local-playwright" ? "local_playwright" : "riddle_hosted", runner: beforeResult.runner, job_id: beforeResult.riddle?.job_id },
5038
+ target: { kind: "url", url: beforeSource },
5039
+ profile_result: beforeResult,
5040
+ execution: beforeResult.riddle?.execution,
5041
+ publication: { kind: "local", path: beforeResultPath }
5042
+ });
5043
+ afterObservation = createRiddleProofObservationReceipt({
5044
+ comparison_role: "after",
5045
+ executor: { kind: afterResult.runner === "local-playwright" ? "local_playwright" : "riddle_hosted", runner: afterResult.runner, job_id: afterResult.riddle?.job_id },
5046
+ target: { kind: "url", url: afterSource },
5047
+ profile_result: afterResult,
5048
+ execution: afterResult.riddle?.execution,
5049
+ publication: { kind: "local", path: afterResultPath }
5050
+ });
4909
5051
  } else {
4910
5052
  if (!beforeUrl || !afterUrl) {
4911
5053
  throw new Error("run-change-proof requires both --before-url and --after-url unless saved results are provided.");
@@ -4919,21 +5061,54 @@ async function runChangeProofForCli(rawProfile, options) {
4919
5061
  afterResult = await runProfileForCli(afterProfile, afterOptions);
4920
5062
  beforeSource = beforeUrl;
4921
5063
  afterSource = afterUrl;
5064
+ beforeObservation = createRiddleProofObservationReceipt({
5065
+ comparison_role: "before",
5066
+ executor: { kind: "riddle_hosted", runner: beforeResult.runner, job_id: beforeResult.riddle?.job_id },
5067
+ target: beforePreview ? { kind: "preview", url: beforeSource, preview: beforePreview } : { kind: "url", url: beforeSource },
5068
+ source: beforePreview?.source,
5069
+ profile_result: beforeResult,
5070
+ execution: beforeResult.riddle?.execution
5071
+ });
5072
+ afterObservation = createRiddleProofObservationReceipt({
5073
+ comparison_role: "after",
5074
+ executor: { kind: "riddle_hosted", runner: afterResult.runner, job_id: afterResult.riddle?.job_id },
5075
+ target: afterPreview ? { kind: "preview", url: afterSource, preview: afterPreview } : { kind: "url", url: afterSource },
5076
+ source: afterPreview?.source,
5077
+ profile_result: afterResult,
5078
+ execution: afterResult.riddle?.execution
5079
+ });
4922
5080
  }
4923
5081
  const result = assessRiddleProofChange(contract, {
4924
5082
  before_result: beforeResult,
4925
- after_result: afterResult
5083
+ after_result: afterResult,
5084
+ before_observation: beforeObservation,
5085
+ after_observation: afterObservation,
5086
+ expected_source_revisions: {
5087
+ before: optionString(options, "beforeSourceRevision"),
5088
+ after: optionString(options, "afterSourceRevision")
5089
+ }
4926
5090
  });
4927
5091
  const receipt = createRiddleProofChangeReceipt({
4928
5092
  contract,
4929
5093
  result,
4930
- before_result: beforeResult,
4931
- after_result: afterResult,
4932
- before_source: beforeSource,
4933
- after_source: afterSource,
5094
+ before_observation: beforeObservation,
5095
+ after_observation: afterObservation,
4934
5096
  profile_name: profile.name
4935
5097
  });
4936
- return { profile, contract, beforeResult, afterResult, result, receipt, beforeSource, afterSource };
5098
+ const handoff = createRiddleProofHandoffReceipt(receipt);
5099
+ return {
5100
+ profile,
5101
+ contract,
5102
+ beforeResult,
5103
+ afterResult,
5104
+ result,
5105
+ receipt,
5106
+ handoff,
5107
+ beforeObservation,
5108
+ afterObservation,
5109
+ beforeSource,
5110
+ afterSource
5111
+ };
4937
5112
  }
4938
5113
  function requestForRun(options) {
4939
5114
  const statePath = optionString(options, "statePath");
@@ -4985,7 +5160,7 @@ async function main() {
4985
5160
  if (command === "run-profile") {
4986
5161
  const profile = profileWithSelectedViewportNamesForCli(normalizeProfileForCli(options), options);
4987
5162
  const result = positional[1] === "recover" ? await recoverProfileForCli(profile, options) : positional[1] === "aggregate" ? await aggregateProfileResultsForCli(profile, options) : await runProfileForCli(profile, options);
4988
- writeProfileOutput(profileOutputDirOption(options), result);
5163
+ writeProfileOutput(profileOutputDirOption(options), result, profileOutputOptionsForCli(options));
4989
5164
  const diagnosticLine = profileCliDiagnosticLine(result);
4990
5165
  if (diagnosticLine && optionBoolean(options, "quiet") !== true) {
4991
5166
  process.stderr.write(`${diagnosticLine}
@@ -5016,6 +5191,7 @@ async function main() {
5016
5191
  const explicitResultJsonPath = optionString(options, "resultJson");
5017
5192
  const runResponsePath = explicitRunResponsePath || defaultProofDirJsonPath(proofDir, "riddle-run-response.json");
5018
5193
  const resultJsonPaths = explicitResultJsonPath ? [explicitResultJsonPath] : [
5194
+ defaultProofDirJsonPath(proofDir, "handoff-receipt.json"),
5019
5195
  defaultProofDirJsonPath(proofDir, "result.json"),
5020
5196
  defaultProofDirJsonPath(proofDir, "change-proof-receipt.json"),
5021
5197
  defaultProofDirJsonPath(proofDir, "change-proof-result.json"),
@@ -5137,6 +5313,16 @@ async function main() {
5137
5313
  };
5138
5314
  }
5139
5315
  const result = await createRiddleApiClient(clientConfig).deployPreview(buildDir, label, previewFrameworkOption(options));
5316
+ const outputDir = profileOutputDirOption(options);
5317
+ if (outputDir) {
5318
+ mkdirSync(outputDir, { recursive: true });
5319
+ writeFileSync(path.join(outputDir, "preview-deploy-result.json"), `${JSON.stringify(result, null, 2)}
5320
+ `);
5321
+ if (result.receipt) {
5322
+ writeFileSync(path.join(outputDir, "preview-receipt.json"), `${JSON.stringify(result.receipt, null, 2)}
5323
+ `);
5324
+ }
5325
+ }
5140
5326
  for (const warning of result.warnings ?? []) {
5141
5327
  process.stderr.write(`Warning: ${warning}
5142
5328
  `);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  RIDDLE_PROOF_PROFILE_VERSION
3
- } from "./chunk-GG2D3MFZ.js";
3
+ } from "./chunk-FCSJZBC5.js";
4
4
 
5
5
  // src/profile-suggestions.ts
6
6
  var RIDDLE_PROOF_PROFILE_SUGGESTIONS_VERSION = "riddle-proof.profile-suggestions.v1";
package/dist/cli/index.js CHANGED
@@ -1,10 +1,11 @@
1
- import "../chunk-H25IDX76.js";
2
- import "../chunk-B2DP2LET.js";
1
+ import "../chunk-NEXWITV4.js";
2
+ import "../chunk-5IFZSUPF.js";
3
3
  import "../chunk-JFQXAJH2.js";
4
- import "../chunk-IY4W6STC.js";
5
- import "../chunk-UE4I7RTI.js";
6
- import "../chunk-GG2D3MFZ.js";
7
- import "../chunk-BILL3UC2.js";
4
+ import "../chunk-7N6X54WG.js";
5
+ import "../chunk-RQPCKRKT.js";
6
+ import "../chunk-6VFS2JFR.js";
7
+ import "../chunk-MEVVL4TI.js";
8
+ import "../chunk-FCSJZBC5.js";
8
9
  import "../chunk-KXLEN4SA.js";
9
10
  import "../chunk-WLUMLHII.js";
10
11
  import "../chunk-CGJX7LJO.js";