@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/index.js CHANGED
@@ -61,7 +61,7 @@ import {
61
61
  RIDDLE_PROOF_PR_COMMENT_MARKER,
62
62
  buildRiddleProofPrCommentMarkdown,
63
63
  summarizeRiddleProofPrComment
64
- } from "./chunk-CWRIXP5H.js";
64
+ } from "./chunk-IY4W6STC.js";
65
65
  import {
66
66
  RIDDLE_PROOF_PROFILE_SUGGESTIONS_VERSION,
67
67
  suggestRiddleProofProfileChecks
@@ -98,9 +98,13 @@ import {
98
98
  } from "./chunk-GG2D3MFZ.js";
99
99
  import {
100
100
  RIDDLE_PROOF_CHANGE_CONTRACT_VERSION,
101
+ RIDDLE_PROOF_CHANGE_RECEIPT_VERSION,
101
102
  RIDDLE_PROOF_CHANGE_RESULT_VERSION,
102
- assessRiddleProofChange
103
- } from "./chunk-6S7DZWVC.js";
103
+ assessRiddleProofChange,
104
+ createRiddleProofChangeReceipt,
105
+ riddleProofChangeReceiptHtml,
106
+ riddleProofChangeReceiptMarkdown
107
+ } from "./chunk-BILL3UC2.js";
104
108
  import {
105
109
  createCodexExecAgentAdapter,
106
110
  createCodexExecJsonRunner,
@@ -193,6 +197,7 @@ export {
193
197
  RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION,
194
198
  RIDDLE_PROOF_CAPTURE_DIAGNOSTIC_VERSION,
195
199
  RIDDLE_PROOF_CHANGE_CONTRACT_VERSION,
200
+ RIDDLE_PROOF_CHANGE_RECEIPT_VERSION,
196
201
  RIDDLE_PROOF_CHANGE_RESULT_VERSION,
197
202
  RIDDLE_PROOF_CHECKPOINT_PACKET_VERSION,
198
203
  RIDDLE_PROOF_CHECKPOINT_RESPONSE_VERSION,
@@ -258,6 +263,7 @@ export {
258
263
  createCodexExecAgentAdapter as createLocalAgentAdapter,
259
264
  createCodexExecJsonRunner as createLocalAgentJsonRunner,
260
265
  createRiddleApiClient,
266
+ createRiddleProofChangeReceipt,
261
267
  createRiddleProofProfileConfigurationError,
262
268
  createRiddleProofProfileEnvironmentBlockedResult,
263
269
  createRiddleProofProfileInsufficientResult,
@@ -303,6 +309,8 @@ export {
303
309
  resolveRiddleProofProfileRouteUrl,
304
310
  resolveRiddleProofProfileTargetUrl,
305
311
  resolveRiddleProofProfileTimeoutSec,
312
+ riddleProofChangeReceiptHtml,
313
+ riddleProofChangeReceiptMarkdown,
306
314
  riddleProofPublicStateAllowsClaim,
307
315
  riddleProofPublicStateAllowsMergeRecommendation,
308
316
  riddleProofPublicStateMergeRecommendation,
@@ -277,6 +277,33 @@ function collectProfileArtifacts(result) {
277
277
  }
278
278
  return artifacts;
279
279
  }
280
+ function collectChangeReceiptArtifacts(result) {
281
+ const artifacts = [];
282
+ const seen = /* @__PURE__ */ new Set();
283
+ const collectSide = (sideName, side) => {
284
+ const candidates = [
285
+ ...asArray(side.screenshots),
286
+ ...asArray(side.artifacts)
287
+ ];
288
+ for (const [index, item] of candidates.entries()) {
289
+ const artifact = asRecord2(item);
290
+ const url = stringValue2(artifact.url) || stringValue2(artifact.path);
291
+ if (!url || seen.has(url)) continue;
292
+ seen.add(url);
293
+ const fallbackName = `${sideName}-artifact-${index + 1}`;
294
+ const name = `${sideName}/${artifactDisplayName(artifact.name, fallbackName)}`;
295
+ artifacts.push({
296
+ name,
297
+ url,
298
+ kind: artifactKind(name, url),
299
+ size_bytes: numberValue2(artifact.size_bytes) ?? numberValue2(artifact.size)
300
+ });
301
+ }
302
+ };
303
+ collectSide("before", asRecord2(result.before));
304
+ collectSide("after", asRecord2(result.after));
305
+ return artifacts;
306
+ }
280
307
  function mergeArtifacts(...artifactLists) {
281
308
  const artifacts = [];
282
309
  const seen = /* @__PURE__ */ new Set();
@@ -332,6 +359,32 @@ function profilePageSummaries(result, counts) {
332
359
  failed: counts.failed
333
360
  }];
334
361
  }
362
+ function changeReceiptCheckCounts(result) {
363
+ const deltas = asArray(result.deltas);
364
+ if (!deltas.length) return void 0;
365
+ let passed = 0;
366
+ let failed = 0;
367
+ for (const item of deltas) {
368
+ const status = stringValue2(asRecord2(item).status);
369
+ if (status === "passed") passed += 1;
370
+ if (status === "failed" || status === "proof_insufficient" || status === "configuration_error") failed += 1;
371
+ }
372
+ return { passed, failed };
373
+ }
374
+ function changeReceiptPageSummaries(result) {
375
+ const pages = [];
376
+ for (const sideName of ["before", "after"]) {
377
+ const side = asRecord2(result[sideName]);
378
+ if (!Object.keys(side).length) continue;
379
+ const checks = asRecord2(side.checks);
380
+ pages.push({
381
+ route: firstStringValue2(side.source, side.profile_name) || sideName,
382
+ passed: numberValue2(checks.passed) ?? 0,
383
+ failed: numberValue2(checks.failed) ?? 0
384
+ });
385
+ }
386
+ return pages;
387
+ }
335
388
  function summarizeExplicitChecks(value) {
336
389
  let passed = 0;
337
390
  let failed = 0;
@@ -387,11 +440,20 @@ function isProfileResult(result) {
387
440
  const version = stringValue2(result.version);
388
441
  return version === "riddle-proof.profile-result.v1" || version === "riddle-proof.profile-compact-result.v1";
389
442
  }
443
+ function isChangeReceiptResult(result) {
444
+ return stringValue2(result.version) === "riddle-proof.change-receipt.v1";
445
+ }
446
+ function isChangeResult(result) {
447
+ const version = stringValue2(result.version);
448
+ return version === "riddle-proof.change-result.v1" || version === "riddle-proof.change-compact-result.v1";
449
+ }
390
450
  function summarizeRiddleProofPrComment(input) {
391
451
  const runResponse = asRecord2(input.runResponse);
392
452
  const result = asRecord2(input.result);
393
453
  const proofResult = asRecord2(runResponse.proofResult);
394
454
  const profileResult = isProfileResult(result);
455
+ const changeReceiptResult = isChangeReceiptResult(result);
456
+ const changeResult = changeReceiptResult || isChangeResult(result);
395
457
  const profileRiddle = asRecord2(result.riddle);
396
458
  const preview = asRecord2(runResponse.preview);
397
459
  const resultRunCard = asRecord2(result.run_card);
@@ -400,15 +462,18 @@ function summarizeRiddleProofPrComment(input) {
400
462
  const resultRaw = asRecord2(result.raw);
401
463
  const rawDetails = asRecord2(resultRaw.details);
402
464
  const profileChecks = profileResult ? profileCheckCounts(result) : void 0;
465
+ const changeChecks = changeResult ? changeReceiptCheckCounts(result) : void 0;
403
466
  const artifacts = mergeArtifacts(
404
467
  collectArtifacts(runResponse),
405
- profileResult ? collectProfileArtifacts(result) : []
468
+ profileResult ? collectProfileArtifacts(result) : [],
469
+ changeReceiptResult ? collectChangeReceiptArtifacts(result) : []
406
470
  );
407
- const pages = profileResult ? profilePageSummaries(result, profileChecks) : pageSummaries(result);
471
+ const pages = changeReceiptResult ? changeReceiptPageSummaries(result) : profileResult ? profilePageSummaries(result, profileChecks) : pageSummaries(result);
408
472
  const checkSource = { ...result };
409
473
  delete checkSource.ok;
410
474
  const nestedChecks = summarizeExplicitChecks(checkSource);
411
- const ok = booleanValue2(result.ok) ?? booleanValue2(runResponse.ok) ?? null;
475
+ const resultStatus = firstStringValue2(result.status, stopCondition.status);
476
+ const ok = changeResult ? resultStatus === "passed" : booleanValue2(result.ok) ?? booleanValue2(runResponse.ok) ?? null;
412
477
  const checkpointSummary = checkpointSummaryFrom2(
413
478
  result.checkpoint_summary,
414
479
  stopCondition.checkpoint_summary,
@@ -418,7 +483,7 @@ function summarizeRiddleProofPrComment(input) {
418
483
  );
419
484
  const publicState = summarizeRiddleProofPublicState({
420
485
  ...result,
421
- status: firstStringValue2(result.status, stopCondition.status),
486
+ status: resultStatus,
422
487
  checkpoint_summary: checkpointSummary || result.checkpoint_summary
423
488
  });
424
489
  const mergeRecommendation = riddleProofPublicStateMergeRecommendation(
@@ -428,7 +493,7 @@ function summarizeRiddleProofPrComment(input) {
428
493
  return {
429
494
  ok,
430
495
  status: firstStringValue2(proofResult.status, profileRiddle.status),
431
- result_status: publicState.status,
496
+ result_status: changeResult ? resultStatus : publicState.status,
432
497
  job_id: firstStringValue2(proofResult.job_id, profileRiddle.job_id),
433
498
  duration_ms: numberValue2(proofResult.duration_ms) ?? numberValue2(profileRiddle.elapsed_ms),
434
499
  proof_url: stringValue2(runResponse.proofUrl),
@@ -442,11 +507,11 @@ function summarizeRiddleProofPrComment(input) {
442
507
  merge_ready: publicState.merge_ready,
443
508
  sync_allowed: publicState.sync_allowed,
444
509
  proof_decision: firstStringValue2(result.proof_decision, stopCondition.proof_decision, resultRaw.proof_decision),
445
- merge_recommendation: mergeRecommendation,
510
+ merge_recommendation: changeReceiptResult && resultStatus ? stringValue2(result.verdict) : mergeRecommendation,
446
511
  checkpoint_summary: checkpointSummary,
447
512
  public_state: publicState,
448
- passed_checks: profileChecks?.passed ?? nestedChecks.passed,
449
- failed_checks: profileChecks?.failed ?? nestedChecks.failed,
513
+ passed_checks: changeChecks?.passed ?? profileChecks?.passed ?? nestedChecks.passed,
514
+ failed_checks: changeChecks?.failed ?? profileChecks?.failed ?? nestedChecks.failed,
450
515
  pages,
451
516
  artifacts,
452
517
  primary_image: selectPrimaryImage(artifacts)
@@ -2,7 +2,7 @@ import {
2
2
  RIDDLE_PROOF_PR_COMMENT_MARKER,
3
3
  buildRiddleProofPrCommentMarkdown,
4
4
  summarizeRiddleProofPrComment
5
- } from "./chunk-CWRIXP5H.js";
5
+ } from "./chunk-IY4W6STC.js";
6
6
  import "./chunk-ZAR7BWMN.js";
7
7
  import "./chunk-MLKGABMK.js";
8
8
  export {
@@ -0,0 +1,16 @@
1
+ {
2
+ "version": "riddle-proof.change-contract.v1",
3
+ "name": "Hosted preview marker appears after change",
4
+ "deltas": [
5
+ {
6
+ "type": "check_status_transition",
7
+ "label": "hosted preview marker becomes visible",
8
+ "check_label": "hosted-preview-marker-visible",
9
+ "before_status": "failed",
10
+ "after_status": "passed"
11
+ }
12
+ ],
13
+ "metadata": {
14
+ "example": "hosted preview before/after proof"
15
+ }
16
+ }
@@ -28,6 +28,10 @@
28
28
  <dt>Fixture</dt>
29
29
  <dd>neutral-fixture-pass</dd>
30
30
  </div>
31
+ <div>
32
+ <dt>Hosted proof</dt>
33
+ <dd data-rp-change-proof="hosted-preview">hosted preview change proof</dd>
34
+ </div>
31
35
  </dl>
32
36
  </section>
33
37
  </main>
@@ -70,7 +70,7 @@ p {
70
70
 
71
71
  dl {
72
72
  display: grid;
73
- grid-template-columns: repeat(3, minmax(0, 1fr));
73
+ grid-template-columns: repeat(4, minmax(0, 1fr));
74
74
  margin: 0;
75
75
  }
76
76
 
@@ -0,0 +1,36 @@
1
+ {
2
+ "version": "riddle-proof.profile.v1",
3
+ "name": "hosted-change-proof-preview",
4
+ "target": {
5
+ "route": "/pass.html",
6
+ "viewports": [
7
+ { "name": "phone", "width": 390, "height": 844 },
8
+ { "name": "desktop", "width": 1440, "height": 1000 }
9
+ ],
10
+ "auth": "none",
11
+ "wait_for_selector": "[data-rp-fixture=\"pass\"]",
12
+ "setup_actions": [
13
+ { "type": "screenshot", "label": "initial-fixture-state", "full_page": false },
14
+ { "type": "wait", "ms": 100 }
15
+ ],
16
+ "screenshot_full_page": false
17
+ },
18
+ "checks": [
19
+ { "type": "route_loaded", "expected_path": "/pass.html" },
20
+ { "type": "selector_visible", "selector": "[data-rp-fixture=\"pass\"]" },
21
+ {
22
+ "type": "selector_text_visible",
23
+ "label": "hosted-preview-marker-visible",
24
+ "selector": "[data-rp-change-proof=\"hosted-preview\"]",
25
+ "text": "hosted preview change proof"
26
+ },
27
+ { "type": "no_mobile_horizontal_overflow" },
28
+ { "type": "no_fatal_console_errors" }
29
+ ],
30
+ "artifacts": ["screenshot", "console", "dom_summary", "proof_json"],
31
+ "failure_policy": {
32
+ "environment_blocked": "neutral",
33
+ "proof_insufficient": "fail",
34
+ "product_regression": "fail"
35
+ }
36
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.8.75",
3
+ "version": "0.8.77",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",
@@ -1,167 +0,0 @@
1
- // src/change-proof.ts
2
- var RIDDLE_PROOF_CHANGE_CONTRACT_VERSION = "riddle-proof.change-contract.v1";
3
- var RIDDLE_PROOF_CHANGE_RESULT_VERSION = "riddle-proof.change-result.v1";
4
- var DEFAULT_BEFORE_STATUSES = ["passed", "product_regression"];
5
- var DEFAULT_AFTER_STATUSES = ["passed"];
6
- var DEFAULT_PROFILE_STATUS_TRANSITION_BEFORE = ["product_regression"];
7
- var DEFAULT_PROFILE_STATUS_TRANSITION_AFTER = ["passed"];
8
- var DEFAULT_CHECK_STATUS_TRANSITION_BEFORE = ["failed"];
9
- var DEFAULT_CHECK_STATUS_TRANSITION_AFTER = ["passed"];
10
- function listValue(value, fallback) {
11
- if (Array.isArray(value)) return value;
12
- if (value === void 0) return fallback;
13
- return [value];
14
- }
15
- function includesValue(allowed, observed) {
16
- return observed !== void 0 && allowed.includes(observed);
17
- }
18
- function groupResult(side, contract, result) {
19
- const fallback = side === "before" ? DEFAULT_BEFORE_STATUSES : DEFAULT_AFTER_STATUSES;
20
- const requiredStatus = listValue(contract?.required_status, fallback);
21
- const label = contract?.label || side;
22
- if (!result) {
23
- return {
24
- side,
25
- label,
26
- ok: false,
27
- status: "missing",
28
- required_status: requiredStatus,
29
- message: `${label} profile result is missing.`
30
- };
31
- }
32
- const ok = includesValue(requiredStatus, result.status);
33
- return {
34
- side,
35
- label,
36
- ok,
37
- profile_name: result.profile_name,
38
- status: result.status,
39
- required_status: requiredStatus,
40
- summary: result.summary,
41
- message: ok ? void 0 : `${label} profile status ${result.status} did not match required status ${requiredStatus.join(", ")}.`
42
- };
43
- }
44
- function findCheck(result, delta) {
45
- return result.checks.find((check) => {
46
- if (delta.check_label && check.label !== delta.check_label) return false;
47
- if (delta.check_type && check.type !== delta.check_type) return false;
48
- return Boolean(delta.check_label || delta.check_type);
49
- });
50
- }
51
- function profileStatusTransitionResult(delta, before, after) {
52
- const label = delta.label || "profile-status-transition";
53
- if (!before || !after) {
54
- return {
55
- type: delta.type,
56
- label,
57
- status: "proof_insufficient",
58
- before_observed: before?.status,
59
- after_observed: after?.status,
60
- message: `${label} needs both before and after profile results.`
61
- };
62
- }
63
- const beforeAllowed = listValue(delta.before_status, DEFAULT_PROFILE_STATUS_TRANSITION_BEFORE);
64
- const afterAllowed = listValue(delta.after_status, DEFAULT_PROFILE_STATUS_TRANSITION_AFTER);
65
- const passed = includesValue(beforeAllowed, before.status) && includesValue(afterAllowed, after.status);
66
- return {
67
- type: delta.type,
68
- label,
69
- status: passed ? "passed" : "failed",
70
- before_observed: before.status,
71
- after_observed: after.status,
72
- message: passed ? void 0 : `${label} expected before ${beforeAllowed.join(", ")} and after ${afterAllowed.join(", ")}, got ${before.status} -> ${after.status}.`
73
- };
74
- }
75
- function checkStatusTransitionResult(delta, before, after) {
76
- const label = delta.label || delta.check_label || delta.check_type || "check-status-transition";
77
- if (!delta.check_label && !delta.check_type) {
78
- return {
79
- type: delta.type,
80
- label,
81
- status: "configuration_error",
82
- message: `${label} needs check_label or check_type.`
83
- };
84
- }
85
- if (!before || !after) {
86
- return {
87
- type: delta.type,
88
- label,
89
- status: "proof_insufficient",
90
- before_observed: before?.status,
91
- after_observed: after?.status,
92
- message: `${label} needs both before and after profile results.`
93
- };
94
- }
95
- const beforeCheck = findCheck(before, delta);
96
- const afterCheck = findCheck(after, delta);
97
- if (!beforeCheck || !afterCheck) {
98
- return {
99
- type: delta.type,
100
- label,
101
- status: "proof_insufficient",
102
- before_observed: beforeCheck?.status,
103
- after_observed: afterCheck?.status,
104
- message: `${label} was not present in ${!beforeCheck && !afterCheck ? "before or after" : !beforeCheck ? "before" : "after"} profile checks.`
105
- };
106
- }
107
- const beforeAllowed = listValue(delta.before_status, DEFAULT_CHECK_STATUS_TRANSITION_BEFORE);
108
- const afterAllowed = listValue(delta.after_status, DEFAULT_CHECK_STATUS_TRANSITION_AFTER);
109
- const passed = includesValue(beforeAllowed, beforeCheck.status) && includesValue(afterAllowed, afterCheck.status);
110
- return {
111
- type: delta.type,
112
- label,
113
- status: passed ? "passed" : "failed",
114
- before_observed: beforeCheck.status,
115
- after_observed: afterCheck.status,
116
- message: passed ? void 0 : `${label} expected before ${beforeAllowed.join(", ")} and after ${afterAllowed.join(", ")}, got ${beforeCheck.status} -> ${afterCheck.status}.`
117
- };
118
- }
119
- function assessDelta(delta, before, after) {
120
- if (delta.type === "profile_status_transition") {
121
- return profileStatusTransitionResult(delta, before, after);
122
- }
123
- return checkStatusTransitionResult(delta, before, after);
124
- }
125
- function collapsedChangeStatus(groups, deltas) {
126
- const groupResults = [groups.before, groups.after];
127
- if (groupResults.some((group) => group.status === "environment_blocked")) return "environment_blocked";
128
- if (groupResults.some((group) => group.status === "configuration_error")) return "configuration_error";
129
- if (deltas.some((delta) => delta.status === "configuration_error")) return "configuration_error";
130
- if (groupResults.some((group) => group.status === "needs_human_review")) return "needs_human_review";
131
- if (groupResults.some((group) => group.status === "missing" || group.status === "proof_insufficient")) return "proof_insufficient";
132
- if (!deltas.length || deltas.some((delta) => delta.status === "proof_insufficient")) return "proof_insufficient";
133
- if (groupResults.some((group) => !group.ok)) return "product_regression";
134
- if (deltas.some((delta) => delta.status === "failed")) return "product_regression";
135
- return "passed";
136
- }
137
- function changeSummary(name, status, deltas) {
138
- if (status === "passed") return `${name} passed ${deltas.length} change delta(s).`;
139
- if (status === "environment_blocked") return `${name} could not compare reliable evidence because an environment was blocked.`;
140
- if (status === "configuration_error") return `${name} has an invalid change proof contract.`;
141
- if (status === "needs_human_review") return `${name} needs human review before the change proof can pass.`;
142
- if (status === "proof_insufficient") return `${name} did not produce enough before/after evidence for a change proof.`;
143
- return `${name} failed ${deltas.filter((delta) => delta.status === "failed").length} change delta(s).`;
144
- }
145
- function assessRiddleProofChange(contract, input) {
146
- const groups = {
147
- before: groupResult("before", contract.before, input.before_result),
148
- after: groupResult("after", contract.after, input.after_result)
149
- };
150
- const deltas = (contract.deltas || []).map((delta) => assessDelta(delta, input.before_result, input.after_result));
151
- const status = collapsedChangeStatus(groups, deltas);
152
- return {
153
- version: RIDDLE_PROOF_CHANGE_RESULT_VERSION,
154
- contract_name: contract.name,
155
- status,
156
- groups,
157
- deltas,
158
- summary: changeSummary(contract.name, status, deltas),
159
- metadata: contract.metadata
160
- };
161
- }
162
-
163
- export {
164
- RIDDLE_PROOF_CHANGE_CONTRACT_VERSION,
165
- RIDDLE_PROOF_CHANGE_RESULT_VERSION,
166
- assessRiddleProofChange
167
- };