@riddledc/riddle-proof 0.7.158 → 0.7.160

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
@@ -7006,6 +7006,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
7006
7006
  "fill",
7007
7007
  "set_input_value",
7008
7008
  "set_range_value",
7009
+ "canvas_signature",
7009
7010
  "assert_text_visible",
7010
7011
  "assert_text_absent",
7011
7012
  "assert_selector_count",
@@ -7507,6 +7508,26 @@ function profileSetupRangeValueReceipts(results) {
7507
7508
  reason: result.reason ?? result.error ?? null
7508
7509
  }));
7509
7510
  }
7511
+ function profileSetupCanvasSignatureReceipts(results) {
7512
+ return results.filter((result) => profileSetupResultAction(result) === "canvas_signature").map((result) => ({
7513
+ ordinal: result.ordinal ?? null,
7514
+ ok: result.ok !== false,
7515
+ selector: result.selector ?? null,
7516
+ frame_selector: result.frame_selector ?? null,
7517
+ label: result.label ?? null,
7518
+ hash: result.hash ?? null,
7519
+ data_length: result.data_length ?? null,
7520
+ width: result.width ?? null,
7521
+ height: result.height ?? null,
7522
+ css_width: result.css_width ?? null,
7523
+ css_height: result.css_height ?? null,
7524
+ compare_to: result.compare_to ?? null,
7525
+ previous_hash: result.previous_hash ?? null,
7526
+ changed: result.changed ?? null,
7527
+ return_stored_to: result.return_stored_to ?? null,
7528
+ reason: result.reason ?? result.error ?? null
7529
+ }));
7530
+ }
7510
7531
  function sampleProfileSetupSummaryItems(items, limit) {
7511
7532
  if (items.length <= limit) return items;
7512
7533
  const firstCount = Math.floor(limit / 2);
@@ -7551,6 +7572,8 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
7551
7572
  const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
7552
7573
  const rangeValueReceipts = profileSetupRangeValueReceipts(results);
7553
7574
  const sampledRangeValueReceipts = sampleProfileSetupSummaryItems(rangeValueReceipts, 8);
7575
+ const canvasSignatureReceipts = profileSetupCanvasSignatureReceipts(results);
7576
+ const sampledCanvasSignatureReceipts = sampleProfileSetupSummaryItems(canvasSignatureReceipts, 8);
7554
7577
  const clickedItems = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => {
7555
7578
  const clickCount = typeof result.click_count === "number" && Number.isFinite(result.click_count) && result.click_count > 1 ? result.click_count : void 0;
7556
7579
  return {
@@ -7602,6 +7625,9 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
7602
7625
  set_range_value_total: rangeValueReceipts.length,
7603
7626
  set_range_value_truncated: rangeValueReceipts.length > sampledRangeValueReceipts.length,
7604
7627
  set_range_value: sampledRangeValueReceipts,
7628
+ canvas_signature_total: canvasSignatureReceipts.length,
7629
+ canvas_signature_truncated: canvasSignatureReceipts.length > sampledCanvasSignatureReceipts.length,
7630
+ canvas_signature: sampledCanvasSignatureReceipts,
7605
7631
  clicked,
7606
7632
  text_samples,
7607
7633
  failed: failed.map((result) => ({
@@ -7654,7 +7680,7 @@ function isSupportedCheckType(value) {
7654
7680
  }
7655
7681
  function normalizeSetupActionType(value, index) {
7656
7682
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
7657
- const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "reset_console" || normalizedInput === "clear_browser_console" || normalizedInput === "reset_browser_console" ? "clear_console" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "set_slider_value" || normalizedInput === "slider_value" || normalizedInput === "set_slider" || normalizedInput === "set_range" || normalizedInput === "range_value" || normalizedInput === "range_input" || normalizedInput === "set_range_input" ? "set_range_value" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput === "accept_dialog" || normalizedInput === "accept_dialogs" || normalizedInput === "confirm_dialog" || normalizedInput === "set_dialog_response" ? "dialog_response" : normalizedInput === "dismiss_dialog" || normalizedInput === "dismiss_dialogs" || normalizedInput === "cancel_dialog" ? "dialog_response" : normalizedInput === "window_call_until" || normalizedInput === "call_until" || normalizedInput === "window_call_repeat_until" || normalizedInput === "repeat_window_call_until" ? "window_call_until" : normalizedInput === "window_evaluate" || normalizedInput === "browser_eval" || normalizedInput === "browser_evaluate" || normalizedInput === "evaluate_script" || normalizedInput === "profile_script" ? "window_eval" : normalizedInput;
7683
+ const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "reset_console" || normalizedInput === "clear_browser_console" || normalizedInput === "reset_browser_console" ? "clear_console" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "set_slider_value" || normalizedInput === "slider_value" || normalizedInput === "set_slider" || normalizedInput === "set_range" || normalizedInput === "range_value" || normalizedInput === "range_input" || normalizedInput === "set_range_input" ? "set_range_value" : normalizedInput === "canvas_hash" || normalizedInput === "capture_canvas_hash" || normalizedInput === "capture_canvas_signature" || normalizedInput === "canvas_state_signature" ? "canvas_signature" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput === "accept_dialog" || normalizedInput === "accept_dialogs" || normalizedInput === "confirm_dialog" || normalizedInput === "set_dialog_response" ? "dialog_response" : normalizedInput === "dismiss_dialog" || normalizedInput === "dismiss_dialogs" || normalizedInput === "cancel_dialog" ? "dialog_response" : normalizedInput === "window_call_until" || normalizedInput === "call_until" || normalizedInput === "window_call_repeat_until" || normalizedInput === "repeat_window_call_until" ? "window_call_until" : normalizedInput === "window_evaluate" || normalizedInput === "browser_eval" || normalizedInput === "browser_evaluate" || normalizedInput === "evaluate_script" || normalizedInput === "profile_script" ? "window_eval" : normalizedInput;
7658
7684
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
7659
7685
  return normalized;
7660
7686
  }
@@ -7783,7 +7809,7 @@ function normalizeSetupAction(input, index) {
7783
7809
  if (frameIndex !== void 0 && (!Number.isInteger(frameIndex) || frameIndex < 0)) {
7784
7810
  throw new Error(`target.setup_actions[${index}].frame_index must be a non-negative integer.`);
7785
7811
  }
7786
- if ((type === "click" || type === "drag" || type === "fill" || type === "set_input_value" || type === "set_range_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
7812
+ if ((type === "click" || type === "drag" || type === "fill" || type === "set_input_value" || type === "set_range_value" || type === "canvas_signature" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
7787
7813
  throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
7788
7814
  }
7789
7815
  const fromX = numberValue(valueFromOwn(input, "from_x", "fromX", "start_x", "startX", "x1"));
@@ -7877,7 +7903,11 @@ function normalizeSetupAction(input, index) {
7877
7903
  "assign_return_to",
7878
7904
  "assignReturnTo",
7879
7905
  "return_state_path",
7880
- "returnStatePath"
7906
+ "returnStatePath",
7907
+ "store_signature_to",
7908
+ "storeSignatureTo",
7909
+ "signature_path",
7910
+ "signaturePath"
7881
7911
  );
7882
7912
  const captureReturn = input.capture_return === false || input.captureReturn === false || input.include_return === false || input.includeReturn === false || input.omit_return === true || input.omitReturn === true ? false : void 0;
7883
7913
  const untilPath = stringFromOwn(input, "until_path", "untilPath", "until_state_path", "untilStatePath", "until_window_path", "untilWindowPath", "until");
@@ -7929,6 +7959,8 @@ function normalizeSetupAction(input, index) {
7929
7959
  store_return_to: storeReturnTo,
7930
7960
  capture_return: captureReturn,
7931
7961
  return_summary_fields: normalizeReturnSummaryFields(input, index),
7962
+ compare_to: stringFromOwn(input, "compare_to", "compareTo", "previous_signature_path", "previousSignaturePath", "previous_path", "previousPath", "changed_from", "changedFrom"),
7963
+ expect_changed: booleanValue(valueFromOwn(input, "expect_changed", "expectChanged", "should_change", "shouldChange", "changed")),
7932
7964
  until_path: untilPath,
7933
7965
  until_expected_value: hasUntilExpectedValue ? toJsonValue(valueFromOwn(input, "until_expected_value", "untilExpectedValue", "until_expected", "untilExpected", "until_value", "untilValue", "expected_value", "expectedValue", "expected")) : void 0,
7934
7966
  max_calls: maxCalls,
@@ -9051,7 +9083,14 @@ function textSequenceForCheck(viewport, check) {
9051
9083
  const matchTexts = Array.isArray(sequence.match_texts) ? sequence.match_texts : [];
9052
9084
  const visibleTexts = Array.isArray(sequence.visible_texts) ? sequence.visible_texts : [];
9053
9085
  const texts = Array.isArray(sequence.texts) ? sequence.texts : [];
9054
- const candidates = visibleMatchTexts.length ? visibleMatchTexts : matchTexts.length ? matchTexts : visibleTexts.length ? visibleTexts : texts;
9086
+ let candidates;
9087
+ if (check.type === "selector_text_visible") {
9088
+ candidates = visibleMatchTexts.length ? visibleMatchTexts : visibleTexts;
9089
+ } else if (check.type === "selector_text_absent") {
9090
+ candidates = matchTexts.length ? matchTexts : texts;
9091
+ } else {
9092
+ candidates = visibleMatchTexts.length ? visibleMatchTexts : matchTexts.length ? matchTexts : visibleTexts.length ? visibleTexts : texts;
9093
+ }
9055
9094
  return candidates.map((text) => String(text).replace(/\s+/g, " ").trim()).filter(Boolean);
9056
9095
  }
9057
9096
  return [];
@@ -10415,7 +10454,14 @@ function textSequenceForCheck(viewport, check) {
10415
10454
  const matchTexts = Array.isArray(sequence.match_texts) ? sequence.match_texts : [];
10416
10455
  const visibleTexts = Array.isArray(sequence.visible_texts) ? sequence.visible_texts : [];
10417
10456
  const texts = Array.isArray(sequence.texts) ? sequence.texts : [];
10418
- const candidates = visibleMatchTexts.length ? visibleMatchTexts : matchTexts.length ? matchTexts : visibleTexts.length ? visibleTexts : texts;
10457
+ let candidates;
10458
+ if (check.type === "selector_text_visible") {
10459
+ candidates = visibleMatchTexts.length ? visibleMatchTexts : visibleTexts;
10460
+ } else if (check.type === "selector_text_absent") {
10461
+ candidates = matchTexts.length ? matchTexts : texts;
10462
+ } else {
10463
+ candidates = visibleMatchTexts.length ? visibleMatchTexts : matchTexts.length ? matchTexts : visibleTexts.length ? visibleTexts : texts;
10464
+ }
10419
10465
  return candidates.map((text) => String(text || "").replace(/\s+/g, " ").trim()).filter(Boolean);
10420
10466
  }
10421
10467
  return [];
@@ -11025,6 +11071,28 @@ function profileSetupRangeValueReceipts(results) {
11025
11071
  reason: result.reason || result.error || null,
11026
11072
  }));
11027
11073
  }
11074
+ function profileSetupCanvasSignatureReceipts(results) {
11075
+ return (results || [])
11076
+ .filter((result) => result && profileSetupResultAction(result) === "canvas_signature")
11077
+ .map((result) => ({
11078
+ ordinal: result.ordinal ?? null,
11079
+ ok: result.ok !== false,
11080
+ selector: result.selector ?? null,
11081
+ frame_selector: result.frame_selector ?? null,
11082
+ label: result.label ?? null,
11083
+ hash: result.hash ?? null,
11084
+ data_length: result.data_length ?? null,
11085
+ width: result.width ?? null,
11086
+ height: result.height ?? null,
11087
+ css_width: result.css_width ?? null,
11088
+ css_height: result.css_height ?? null,
11089
+ compare_to: result.compare_to ?? null,
11090
+ previous_hash: result.previous_hash ?? null,
11091
+ changed: result.changed ?? null,
11092
+ return_stored_to: result.return_stored_to ?? null,
11093
+ reason: result.reason || result.error || null,
11094
+ }));
11095
+ }
11028
11096
  function sampleProfileSetupSummaryItems(items, limit) {
11029
11097
  if ((items || []).length <= limit) return items || [];
11030
11098
  const firstCount = Math.floor(limit / 2);
@@ -11083,6 +11151,8 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
11083
11151
  const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
11084
11152
  const rangeValueReceipts = profileSetupRangeValueReceipts(results);
11085
11153
  const sampledRangeValueReceipts = sampleProfileSetupSummaryItems(rangeValueReceipts, 8);
11154
+ const canvasSignatureReceipts = profileSetupCanvasSignatureReceipts(results);
11155
+ const sampledCanvasSignatureReceipts = sampleProfileSetupSummaryItems(canvasSignatureReceipts, 8);
11086
11156
  const clickedItems = results
11087
11157
  .filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
11088
11158
  .map((result) => {
@@ -11144,6 +11214,9 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
11144
11214
  set_range_value_total: rangeValueReceipts.length,
11145
11215
  set_range_value_truncated: rangeValueReceipts.length > sampledRangeValueReceipts.length,
11146
11216
  set_range_value: sampledRangeValueReceipts,
11217
+ canvas_signature_total: canvasSignatureReceipts.length,
11218
+ canvas_signature_truncated: canvasSignatureReceipts.length > sampledCanvasSignatureReceipts.length,
11219
+ canvas_signature: sampledCanvasSignatureReceipts,
11147
11220
  clicked,
11148
11221
  text_samples: textSamples,
11149
11222
  failed: failed.map((result) => ({
@@ -13159,6 +13232,156 @@ async function executeSetupAction(action, ordinal, viewport) {
13159
13232
  reason: rangeResult && rangeResult.ok === true ? undefined : rangeResult?.reason || "range_value_not_set",
13160
13233
  };
13161
13234
  }
13235
+ if (type === "canvas_signature") {
13236
+ const scope = await setupActionScope(action, timeout);
13237
+ if (!scope.ok) return setupScopeFailure(base, scope);
13238
+ const locator = scope.context.locator(action.selector);
13239
+ const count = await locator.count();
13240
+ if (!count) return { ...base, ...setupScopeEvidence(scope), reason: "selector_not_found", count };
13241
+ const targetIndex = Number.isInteger(action.index) ? action.index : 0;
13242
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, ...setupScopeEvidence(scope), reason: "index_out_of_range", count, target_index: targetIndex };
13243
+ const target = locator.nth(targetIndex);
13244
+ await target.waitFor({ state: "visible", timeout });
13245
+ const storeReturnTo = String(action.store_return_to || action.storeReturnTo || action.save_return_to || action.saveReturnTo || action.store_signature_to || action.storeSignatureTo || action.signature_path || action.signaturePath || "").trim();
13246
+ const compareTo = String(action.compare_to || action.compareTo || action.previous_signature_path || action.previousSignaturePath || action.previous_path || action.previousPath || action.changed_from || action.changedFrom || "").trim();
13247
+ const expectChanged = action.expect_changed === true || action.expectChanged === true || action.should_change === true || action.shouldChange === true || action.changed === true
13248
+ ? true
13249
+ : action.expect_changed === false || action.expectChanged === false || action.should_change === false || action.shouldChange === false || action.changed === false
13250
+ ? false
13251
+ : undefined;
13252
+ const signatureResult = await target.evaluate((element, payload) => {
13253
+ const toJsonValue = (value) => {
13254
+ if (value === null || value === undefined) return null;
13255
+ if (typeof value === "string" || typeof value === "boolean") return value;
13256
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
13257
+ if (Array.isArray(value)) return value.map(toJsonValue);
13258
+ if (typeof value === "object") {
13259
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
13260
+ }
13261
+ return String(value);
13262
+ };
13263
+ const pathParts = (path) => String(path || "").split(".").map((part) => part.trim()).filter(Boolean);
13264
+ const readWindowPath = (path) => {
13265
+ const parts = pathParts(path);
13266
+ if (parts[0] === "window") parts.shift();
13267
+ if (!parts.length) return { ok: false, reason: "missing_path" };
13268
+ let current = window;
13269
+ for (const part of parts) {
13270
+ if (current === null || current === undefined) return { ok: false, reason: "path_not_found", missing_part: part };
13271
+ current = current[part];
13272
+ if (current === undefined) return { ok: false, reason: "path_not_found", missing_part: part };
13273
+ }
13274
+ return { ok: true, value: toJsonValue(current) };
13275
+ };
13276
+ const storeWindowValue = (path, value) => {
13277
+ const parts = pathParts(path);
13278
+ if (parts[0] === "window") parts.shift();
13279
+ if (!parts.length) return { ok: false, reason: "missing_store_path" };
13280
+ let target = window;
13281
+ for (let index = 0; index < parts.length - 1; index += 1) {
13282
+ const part = parts[index];
13283
+ if (target[part] === null || typeof target[part] !== "object") target[part] = {};
13284
+ target = target[part];
13285
+ }
13286
+ target[parts[parts.length - 1]] = value;
13287
+ return { ok: true, path: parts.join(".") };
13288
+ };
13289
+ const hashText = (text) => {
13290
+ let hash = 2166136261;
13291
+ const step = Math.max(1, Math.floor((text.length || 1) / 4000));
13292
+ for (let index = 0; index < text.length; index += step) {
13293
+ hash ^= text.charCodeAt(index);
13294
+ hash = Math.imul(hash, 16777619) >>> 0;
13295
+ }
13296
+ return String(hash);
13297
+ };
13298
+ const tag = String(element && element.tagName ? element.tagName : "").toLowerCase();
13299
+ if (tag !== "canvas") return { ok: false, reason: "not_canvas_element", tag };
13300
+ const rect = element.getBoundingClientRect();
13301
+ let data = "";
13302
+ try {
13303
+ data = element.toDataURL("image/png");
13304
+ } catch (error) {
13305
+ return {
13306
+ ok: false,
13307
+ reason: "canvas_read_failed",
13308
+ error: String(error && error.message ? error.message : error).slice(0, 1000),
13309
+ width: element.width || 0,
13310
+ height: element.height || 0,
13311
+ css_width: Math.round(rect.width || 0),
13312
+ css_height: Math.round(rect.height || 0),
13313
+ };
13314
+ }
13315
+ const result = {
13316
+ ok: Boolean(element.width > 0 && element.height > 0 && data.length > 0),
13317
+ reason: element.width > 0 && element.height > 0 && data.length > 0 ? undefined : "empty_canvas_signature",
13318
+ hash: hashText(data),
13319
+ data_length: data.length,
13320
+ width: element.width || 0,
13321
+ height: element.height || 0,
13322
+ css_width: Math.round(rect.width || 0),
13323
+ css_height: Math.round(rect.height || 0),
13324
+ compare_to: payload.compareTo || undefined,
13325
+ previous_hash: null,
13326
+ changed: null,
13327
+ };
13328
+ if (payload.compareTo) {
13329
+ const previous = readWindowPath(payload.compareTo);
13330
+ if (!previous.ok) {
13331
+ result.ok = false;
13332
+ result.reason = previous.reason || "compare_path_not_found";
13333
+ result.missing_part = previous.missing_part || undefined;
13334
+ } else {
13335
+ const previousValue = previous.value;
13336
+ const previousHash = previousValue && typeof previousValue === "object" && !Array.isArray(previousValue)
13337
+ ? previousValue.hash || previousValue.signature || previousValue.canvas_hash || null
13338
+ : typeof previousValue === "string"
13339
+ ? previousValue
13340
+ : null;
13341
+ result.previous_hash = previousHash === null || previousHash === undefined ? null : String(previousHash);
13342
+ result.changed = result.previous_hash === null ? null : result.previous_hash !== result.hash;
13343
+ if (payload.expectChanged === true && result.changed !== true) {
13344
+ result.ok = false;
13345
+ result.reason = "canvas_signature_unchanged";
13346
+ } else if (payload.expectChanged === false && result.changed !== false) {
13347
+ result.ok = false;
13348
+ result.reason = "canvas_signature_changed";
13349
+ }
13350
+ }
13351
+ }
13352
+ if (payload.storeReturnTo) {
13353
+ const stored = storeWindowValue(payload.storeReturnTo, result);
13354
+ if (!stored.ok) {
13355
+ return { ...result, ok: false, reason: "signature_store_failed", store_reason: stored.reason };
13356
+ }
13357
+ return { ...result, return_stored_to: stored.path };
13358
+ }
13359
+ return result;
13360
+ }, { compareTo, expectChanged, storeReturnTo });
13361
+ return {
13362
+ ...base,
13363
+ ...setupScopeEvidence(scope),
13364
+ ok: signatureResult && signatureResult.ok === true,
13365
+ count,
13366
+ target_index: targetIndex,
13367
+ label: action.label || action.name || undefined,
13368
+ hash: signatureResult?.hash,
13369
+ data_length: signatureResult?.data_length,
13370
+ width: signatureResult?.width,
13371
+ height: signatureResult?.height,
13372
+ css_width: signatureResult?.css_width,
13373
+ css_height: signatureResult?.css_height,
13374
+ compare_to: signatureResult?.compare_to || compareTo || undefined,
13375
+ previous_hash: signatureResult?.previous_hash,
13376
+ changed: signatureResult?.changed,
13377
+ return_stored_to: signatureResult?.return_stored_to || storeReturnTo || undefined,
13378
+ missing_part: signatureResult?.missing_part || undefined,
13379
+ store_reason: signatureResult?.store_reason || undefined,
13380
+ tag: signatureResult?.tag,
13381
+ reason: signatureResult && signatureResult.ok === true ? undefined : signatureResult?.reason || "canvas_signature_failed",
13382
+ error: signatureResult?.error || undefined,
13383
+ };
13384
+ }
13162
13385
  if (type === "assert_selector_count") {
13163
13386
  const scope = await setupActionScope(action, timeout);
13164
13387
  if (!scope.ok) return setupScopeFailure(base, scope);
@@ -15398,22 +15621,34 @@ function balancedSetupReceiptDetails(groups, limit) {
15398
15621
  const total = groups.reduce((sum, group) => sum + group.length, 0);
15399
15622
  if (total <= limit) return groups.flat();
15400
15623
  const selected = [];
15624
+ const selectedKeys = /* @__PURE__ */ new Set();
15401
15625
  const indexes = new Array(groups.length).fill(0);
15402
15626
  const nonEmptyIndexes = groups.map((group, index) => group.length ? index : -1).filter((index) => index >= 0);
15627
+ const pushReceipt = (groupIndex, itemIndex, advance = true) => {
15628
+ const receipt = groups[groupIndex][itemIndex];
15629
+ if (!receipt) return false;
15630
+ const key = `${groupIndex}:${itemIndex}`;
15631
+ if (selectedKeys.has(key)) return false;
15632
+ selected.push(receipt);
15633
+ selectedKeys.add(key);
15634
+ if (advance) indexes[groupIndex] = Math.max(indexes[groupIndex], itemIndex + 1);
15635
+ return true;
15636
+ };
15637
+ for (const index of nonEmptyIndexes) {
15638
+ if (selected.length >= limit) return selected;
15639
+ pushReceipt(index, 0);
15640
+ }
15403
15641
  for (const index of nonEmptyIndexes) {
15404
15642
  if (selected.length >= limit) return selected;
15405
- selected.push(groups[index][0]);
15406
- indexes[index] = 1;
15643
+ const lastIndex = groups[index].length - 1;
15644
+ if (lastIndex > 0) pushReceipt(index, lastIndex, false);
15407
15645
  }
15408
15646
  while (selected.length < limit) {
15409
15647
  let progressed = false;
15410
15648
  for (const index of nonEmptyIndexes) {
15411
15649
  const nextIndex = indexes[index];
15412
- const next = groups[index][nextIndex];
15413
- if (!next) continue;
15414
- selected.push(next);
15415
- indexes[index] = nextIndex + 1;
15416
- progressed = true;
15650
+ if (nextIndex >= groups[index].length) continue;
15651
+ progressed = pushReceipt(index, nextIndex) || progressed;
15417
15652
  if (selected.length >= limit) break;
15418
15653
  }
15419
15654
  if (!progressed) break;
@@ -15524,6 +15759,7 @@ function profileSetupSummaryMarkdown(result) {
15524
15759
  const windowCallUntilTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_until_total) || 0), 0);
15525
15760
  const windowCallUntilCallTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_until_call_total) || 0), 0);
15526
15761
  const rangeValueTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.set_range_value_total) || 0), 0);
15762
+ const canvasSignatureTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.canvas_signature_total) || 0), 0);
15527
15763
  const failedTotal = viewports.reduce((sum, viewport) => sum + (Array.isArray(viewport.failed) ? viewport.failed.length : 0), 0);
15528
15764
  const lines = [
15529
15765
  `- setup actions: ${declaredActions === void 0 ? "unknown" : declaredActions} declared, ${totalResults} recorded result(s) across ${viewports.length} viewport(s)`,
@@ -15546,6 +15782,9 @@ function profileSetupSummaryMarkdown(result) {
15546
15782
  if (rangeValueTotal) {
15547
15783
  lines.push(`- set_range_value: ${rangeValueTotal} action(s)`);
15548
15784
  }
15785
+ if (canvasSignatureTotal) {
15786
+ lines.push(`- canvas_signature: ${canvasSignatureTotal} action(s)`);
15787
+ }
15549
15788
  for (const viewport of viewports.slice(0, 8)) {
15550
15789
  const name = cliString(viewport.name) || "viewport";
15551
15790
  const ok = viewport.ok === false ? "failed" : "ok";
@@ -15562,9 +15801,37 @@ function profileSetupSummaryMarkdown(result) {
15562
15801
  const windowCallUntilActions = cliFiniteNumber(viewport.window_call_until_total) || 0;
15563
15802
  const windowCallUntilCalls = cliFiniteNumber(viewport.window_call_until_call_total) || 0;
15564
15803
  const rangeValueActions = cliFiniteNumber(viewport.set_range_value_total) || 0;
15804
+ const canvasSignatureActions = cliFiniteNumber(viewport.canvas_signature_total) || 0;
15565
15805
  const observedPath = cliString(viewport.observed_path);
15566
- lines.push(`- ${name}: ${ok}, ${resultCount} result(s), ${screenshotCount} setup screenshot(s), ${clicked} click(s)${clickCountActions ? `, ${clickCountActions} click_count action(s)` : ""}${rangeValueActions ? `, ${rangeValueActions} set_range_value action(s)` : ""}${windowCallActions ? `, ${windowCallActions} window_call action(s), ${windowCallStored} stored return(s), ${windowCallCaptured} captured return(s)` : ""}${windowEvalActions ? `, ${windowEvalActions} window_eval action(s), ${windowEvalStored} stored return(s), ${windowEvalCaptured} captured return(s)` : ""}${windowCallUntilActions ? `, ${windowCallUntilActions} window_call_until action(s), ${windowCallUntilCalls} call(s)` : ""}${observedPath ? `, path ${observedPath}` : ""}`);
15806
+ lines.push(`- ${name}: ${ok}, ${resultCount} result(s), ${screenshotCount} setup screenshot(s), ${clicked} click(s)${clickCountActions ? `, ${clickCountActions} click_count action(s)` : ""}${rangeValueActions ? `, ${rangeValueActions} set_range_value action(s)` : ""}${canvasSignatureActions ? `, ${canvasSignatureActions} canvas_signature action(s)` : ""}${windowCallActions ? `, ${windowCallActions} window_call action(s), ${windowCallStored} stored return(s), ${windowCallCaptured} captured return(s)` : ""}${windowEvalActions ? `, ${windowEvalActions} window_eval action(s), ${windowEvalStored} stored return(s), ${windowEvalCaptured} captured return(s)` : ""}${windowCallUntilActions ? `, ${windowCallUntilActions} window_call_until action(s), ${windowCallUntilCalls} call(s)` : ""}${observedPath ? `, path ${observedPath}` : ""}`);
15807
+ }
15808
+ const canvasSignatureGroups = viewports.map((viewport) => {
15809
+ const name = cliString(viewport.name) || "viewport";
15810
+ const receipts = Array.isArray(viewport.canvas_signature) ? viewport.canvas_signature.map(cliRecord).filter((item) => Boolean(item)) : [];
15811
+ return receipts.map((receipt) => ({ name, receipt }));
15812
+ });
15813
+ const canvasSignatureDetails = canvasSignatureGroups.flat();
15814
+ const sampledCanvasSignatureDetails = balancedSetupReceiptDetails(canvasSignatureGroups, 12);
15815
+ for (const { name, receipt } of sampledCanvasSignatureDetails) {
15816
+ const selector = cliString(receipt.selector) || "canvas";
15817
+ const label = cliString(receipt.label);
15818
+ const hash = cliString(receipt.hash);
15819
+ const dataLength = cliFiniteNumber(receipt.data_length);
15820
+ const width = cliFiniteNumber(receipt.width);
15821
+ const height = cliFiniteNumber(receipt.height);
15822
+ const cssWidth = cliFiniteNumber(receipt.css_width);
15823
+ const cssHeight = cliFiniteNumber(receipt.css_height);
15824
+ const compareTo = cliString(receipt.compare_to);
15825
+ const previousHash = cliString(receipt.previous_hash);
15826
+ const changed = typeof receipt.changed === "boolean" ? receipt.changed : void 0;
15827
+ const storedTo = cliString(receipt.return_stored_to);
15828
+ const ok = receipt.ok === false ? "failed" : "ok";
15829
+ const reason = cliString(receipt.reason);
15830
+ const sizeText = width === void 0 || height === void 0 ? "" : `, ${width}x${height}`;
15831
+ const cssSizeText = cssWidth === void 0 || cssHeight === void 0 ? "" : `, css ${cssWidth}x${cssHeight}`;
15832
+ lines.push(`- ${name} canvas_signature: ${ok}, ${markdownInlineCode(selector)}${label ? ` ${markdownInlineCode(label, 80)}` : ""}${hash ? ` hash ${markdownInlineCode(hash, 80)}` : ""}${sizeText}${cssSizeText}${dataLength === void 0 ? "" : `, data chars ${dataLength}`}${compareTo ? `, compared ${markdownInlineCode(compareTo)}` : ""}${previousHash ? ` previous ${markdownInlineCode(previousHash, 80)}` : ""}${changed === void 0 ? "" : `, changed ${changed}`}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
15567
15833
  }
15834
+ if (canvasSignatureDetails.length > sampledCanvasSignatureDetails.length) lines.push(`- ${canvasSignatureDetails.length - sampledCanvasSignatureDetails.length} additional canvas_signature receipt(s) omitted.`);
15568
15835
  const rangeValueGroups = viewports.map((viewport) => {
15569
15836
  const name = cliString(viewport.name) || "viewport";
15570
15837
  const receipts = Array.isArray(viewport.set_range_value) ? viewport.set_range_value.map(cliRecord).filter((item) => Boolean(item)) : [];
package/dist/cli.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  profileStatusExitCode,
14
14
  resolveRiddleProofProfileTargetUrl,
15
15
  resolveRiddleProofProfileTimeoutSec
16
- } from "./chunk-YB3LNLZB.js";
16
+ } from "./chunk-MV7UM4EV.js";
17
17
  import {
18
18
  createRiddleApiClient,
19
19
  isTerminalRiddleJobStatus,
@@ -649,22 +649,34 @@ function balancedSetupReceiptDetails(groups, limit) {
649
649
  const total = groups.reduce((sum, group) => sum + group.length, 0);
650
650
  if (total <= limit) return groups.flat();
651
651
  const selected = [];
652
+ const selectedKeys = /* @__PURE__ */ new Set();
652
653
  const indexes = new Array(groups.length).fill(0);
653
654
  const nonEmptyIndexes = groups.map((group, index) => group.length ? index : -1).filter((index) => index >= 0);
655
+ const pushReceipt = (groupIndex, itemIndex, advance = true) => {
656
+ const receipt = groups[groupIndex][itemIndex];
657
+ if (!receipt) return false;
658
+ const key = `${groupIndex}:${itemIndex}`;
659
+ if (selectedKeys.has(key)) return false;
660
+ selected.push(receipt);
661
+ selectedKeys.add(key);
662
+ if (advance) indexes[groupIndex] = Math.max(indexes[groupIndex], itemIndex + 1);
663
+ return true;
664
+ };
665
+ for (const index of nonEmptyIndexes) {
666
+ if (selected.length >= limit) return selected;
667
+ pushReceipt(index, 0);
668
+ }
654
669
  for (const index of nonEmptyIndexes) {
655
670
  if (selected.length >= limit) return selected;
656
- selected.push(groups[index][0]);
657
- indexes[index] = 1;
671
+ const lastIndex = groups[index].length - 1;
672
+ if (lastIndex > 0) pushReceipt(index, lastIndex, false);
658
673
  }
659
674
  while (selected.length < limit) {
660
675
  let progressed = false;
661
676
  for (const index of nonEmptyIndexes) {
662
677
  const nextIndex = indexes[index];
663
- const next = groups[index][nextIndex];
664
- if (!next) continue;
665
- selected.push(next);
666
- indexes[index] = nextIndex + 1;
667
- progressed = true;
678
+ if (nextIndex >= groups[index].length) continue;
679
+ progressed = pushReceipt(index, nextIndex) || progressed;
668
680
  if (selected.length >= limit) break;
669
681
  }
670
682
  if (!progressed) break;
@@ -775,6 +787,7 @@ function profileSetupSummaryMarkdown(result) {
775
787
  const windowCallUntilTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_until_total) || 0), 0);
776
788
  const windowCallUntilCallTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_until_call_total) || 0), 0);
777
789
  const rangeValueTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.set_range_value_total) || 0), 0);
790
+ const canvasSignatureTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.canvas_signature_total) || 0), 0);
778
791
  const failedTotal = viewports.reduce((sum, viewport) => sum + (Array.isArray(viewport.failed) ? viewport.failed.length : 0), 0);
779
792
  const lines = [
780
793
  `- setup actions: ${declaredActions === void 0 ? "unknown" : declaredActions} declared, ${totalResults} recorded result(s) across ${viewports.length} viewport(s)`,
@@ -797,6 +810,9 @@ function profileSetupSummaryMarkdown(result) {
797
810
  if (rangeValueTotal) {
798
811
  lines.push(`- set_range_value: ${rangeValueTotal} action(s)`);
799
812
  }
813
+ if (canvasSignatureTotal) {
814
+ lines.push(`- canvas_signature: ${canvasSignatureTotal} action(s)`);
815
+ }
800
816
  for (const viewport of viewports.slice(0, 8)) {
801
817
  const name = cliString(viewport.name) || "viewport";
802
818
  const ok = viewport.ok === false ? "failed" : "ok";
@@ -813,9 +829,37 @@ function profileSetupSummaryMarkdown(result) {
813
829
  const windowCallUntilActions = cliFiniteNumber(viewport.window_call_until_total) || 0;
814
830
  const windowCallUntilCalls = cliFiniteNumber(viewport.window_call_until_call_total) || 0;
815
831
  const rangeValueActions = cliFiniteNumber(viewport.set_range_value_total) || 0;
832
+ const canvasSignatureActions = cliFiniteNumber(viewport.canvas_signature_total) || 0;
816
833
  const observedPath = cliString(viewport.observed_path);
817
- lines.push(`- ${name}: ${ok}, ${resultCount} result(s), ${screenshotCount} setup screenshot(s), ${clicked} click(s)${clickCountActions ? `, ${clickCountActions} click_count action(s)` : ""}${rangeValueActions ? `, ${rangeValueActions} set_range_value action(s)` : ""}${windowCallActions ? `, ${windowCallActions} window_call action(s), ${windowCallStored} stored return(s), ${windowCallCaptured} captured return(s)` : ""}${windowEvalActions ? `, ${windowEvalActions} window_eval action(s), ${windowEvalStored} stored return(s), ${windowEvalCaptured} captured return(s)` : ""}${windowCallUntilActions ? `, ${windowCallUntilActions} window_call_until action(s), ${windowCallUntilCalls} call(s)` : ""}${observedPath ? `, path ${observedPath}` : ""}`);
834
+ lines.push(`- ${name}: ${ok}, ${resultCount} result(s), ${screenshotCount} setup screenshot(s), ${clicked} click(s)${clickCountActions ? `, ${clickCountActions} click_count action(s)` : ""}${rangeValueActions ? `, ${rangeValueActions} set_range_value action(s)` : ""}${canvasSignatureActions ? `, ${canvasSignatureActions} canvas_signature action(s)` : ""}${windowCallActions ? `, ${windowCallActions} window_call action(s), ${windowCallStored} stored return(s), ${windowCallCaptured} captured return(s)` : ""}${windowEvalActions ? `, ${windowEvalActions} window_eval action(s), ${windowEvalStored} stored return(s), ${windowEvalCaptured} captured return(s)` : ""}${windowCallUntilActions ? `, ${windowCallUntilActions} window_call_until action(s), ${windowCallUntilCalls} call(s)` : ""}${observedPath ? `, path ${observedPath}` : ""}`);
835
+ }
836
+ const canvasSignatureGroups = viewports.map((viewport) => {
837
+ const name = cliString(viewport.name) || "viewport";
838
+ const receipts = Array.isArray(viewport.canvas_signature) ? viewport.canvas_signature.map(cliRecord).filter((item) => Boolean(item)) : [];
839
+ return receipts.map((receipt) => ({ name, receipt }));
840
+ });
841
+ const canvasSignatureDetails = canvasSignatureGroups.flat();
842
+ const sampledCanvasSignatureDetails = balancedSetupReceiptDetails(canvasSignatureGroups, 12);
843
+ for (const { name, receipt } of sampledCanvasSignatureDetails) {
844
+ const selector = cliString(receipt.selector) || "canvas";
845
+ const label = cliString(receipt.label);
846
+ const hash = cliString(receipt.hash);
847
+ const dataLength = cliFiniteNumber(receipt.data_length);
848
+ const width = cliFiniteNumber(receipt.width);
849
+ const height = cliFiniteNumber(receipt.height);
850
+ const cssWidth = cliFiniteNumber(receipt.css_width);
851
+ const cssHeight = cliFiniteNumber(receipt.css_height);
852
+ const compareTo = cliString(receipt.compare_to);
853
+ const previousHash = cliString(receipt.previous_hash);
854
+ const changed = typeof receipt.changed === "boolean" ? receipt.changed : void 0;
855
+ const storedTo = cliString(receipt.return_stored_to);
856
+ const ok = receipt.ok === false ? "failed" : "ok";
857
+ const reason = cliString(receipt.reason);
858
+ const sizeText = width === void 0 || height === void 0 ? "" : `, ${width}x${height}`;
859
+ const cssSizeText = cssWidth === void 0 || cssHeight === void 0 ? "" : `, css ${cssWidth}x${cssHeight}`;
860
+ lines.push(`- ${name} canvas_signature: ${ok}, ${markdownInlineCode(selector)}${label ? ` ${markdownInlineCode(label, 80)}` : ""}${hash ? ` hash ${markdownInlineCode(hash, 80)}` : ""}${sizeText}${cssSizeText}${dataLength === void 0 ? "" : `, data chars ${dataLength}`}${compareTo ? `, compared ${markdownInlineCode(compareTo)}` : ""}${previousHash ? ` previous ${markdownInlineCode(previousHash, 80)}` : ""}${changed === void 0 ? "" : `, changed ${changed}`}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
818
861
  }
862
+ if (canvasSignatureDetails.length > sampledCanvasSignatureDetails.length) lines.push(`- ${canvasSignatureDetails.length - sampledCanvasSignatureDetails.length} additional canvas_signature receipt(s) omitted.`);
819
863
  const rangeValueGroups = viewports.map((viewport) => {
820
864
  const name = cliString(viewport.name) || "viewport";
821
865
  const receipts = Array.isArray(viewport.set_range_value) ? viewport.set_range_value.map(cliRecord).filter((item) => Boolean(item)) : [];