@riddledc/riddle-proof 0.7.171 → 0.7.173

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/README.md CHANGED
@@ -398,7 +398,7 @@ when body matching overrides sequence order.
398
398
  appears only after a picker, tab, login stub, storage seed, form fill,
399
399
  transport control, or other bounded interaction. Supported setup actions are
400
400
  `click`, `drag`, `press`, `fill`, `set_input_value`, `set_range_value`,
401
- `canvas_signature`, `assert_text_visible`, `assert_text_absent`,
401
+ `deterministic_runtime`, `canvas_signature`, `assert_text_visible`, `assert_text_absent`,
402
402
  `assert_selector_count`, `assert_window_value`, `assert_window_number`,
403
403
  `local_storage`, `session_storage`, `clear_storage`, `clear_console`,
404
404
  `screenshot`, `wait`, `wait_for_selector`, `wait_for_text`, `window_eval`,
@@ -423,6 +423,14 @@ events, and records the requested value plus the browser's actual normalized
423
423
  value, numeric value, `min`, `max`, and `step`. The action is intentionally
424
424
  strict: if the target is not an `input[type="range"]`, setup fails with
425
425
  `not_range_input` instead of silently treating the control like a text field.
426
+ Use `deterministic_runtime` when randomized or clock-driven gameplay needs a
427
+ stable proof path. It can install a deterministic `Math.random` queue with
428
+ `random_queue` / `randomValues`, pin `Date.now()` with `now` / `mockNow`,
429
+ advance the pinned clock with `advance_ms`, append more random values with
430
+ `append: true`, and restore browser originals with `restore: true`. Receipts
431
+ record whether random and clock mocks are active, queue length, clock time, and
432
+ random-queue underflows. Values in `random_queue` must be finite numbers from
433
+ `0` inclusive to `1` exclusive.
426
434
  Use `canvas_signature` for canvas-only proof surfaces. It requires `selector`,
427
435
  reads the selected canvas with `toDataURL("image/png")`, records a sampled hash,
428
436
  canvas dimensions, CSS dimensions, and data length, and can store the result
@@ -49,6 +49,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
49
49
  "fill",
50
50
  "set_input_value",
51
51
  "set_range_value",
52
+ "deterministic_runtime",
52
53
  "canvas_signature",
53
54
  "assert_text_visible",
54
55
  "assert_text_absent",
@@ -511,6 +512,23 @@ function profileSetupWindowEvalReceipts(results) {
511
512
  return receipt;
512
513
  });
513
514
  }
515
+ function profileSetupDeterministicRuntimeReceipts(results) {
516
+ return results.filter((result) => profileSetupResultAction(result) === "deterministic_runtime").map((result) => ({
517
+ ordinal: result.ordinal ?? null,
518
+ ok: result.ok !== false,
519
+ random_enabled: result.random_enabled ?? null,
520
+ random_queue_added: result.random_queue_added ?? null,
521
+ random_queue_length: result.random_queue_length ?? null,
522
+ random_queue_mode: result.random_queue_mode ?? null,
523
+ random_underflow_count: result.random_underflow_count ?? null,
524
+ clock_enabled: result.clock_enabled ?? null,
525
+ previous_now: result.previous_now ?? null,
526
+ now: result.now ?? null,
527
+ advance_ms: result.advance_ms ?? null,
528
+ restored: result.restored ?? null,
529
+ reason: result.reason ?? result.error ?? null
530
+ }));
531
+ }
514
532
  function profileSetupReturnSummaryFields(result) {
515
533
  const input = result.return_summary_fields;
516
534
  if (!Array.isArray(input)) return [];
@@ -614,21 +632,28 @@ function profileSetupCanvasSignatureStableHashGroups(results) {
614
632
  }
615
633
  const warnings = [];
616
634
  for (const group of groups.values()) {
617
- const hashes = new Set(group.receipts.map((receipt) => receipt.hash));
618
- const labels = [...new Set(group.receipts.map((receipt) => receipt.label))];
619
- if (group.receipts.length < 2 || labels.length < 2 || hashes.size !== 1) continue;
620
- const visibleLabels = labels.slice(0, 8);
621
- warnings.push({
622
- selector: group.selector,
623
- frame_selector: group.frame_selector ?? null,
624
- hash: group.receipts[0].hash,
625
- count: group.receipts.length,
626
- label_count: labels.length,
627
- labels: visibleLabels,
628
- omitted_label_count: Math.max(0, labels.length - visibleLabels.length),
629
- ordinals: group.receipts.map((receipt) => receipt.ordinal).filter((value) => value !== void 0).slice(0, 12),
630
- reason: "stable_canvas_signature_hash"
631
- });
635
+ const receiptsByHash = /* @__PURE__ */ new Map();
636
+ for (const receipt of group.receipts) {
637
+ const hashReceipts = receiptsByHash.get(receipt.hash) || [];
638
+ hashReceipts.push(receipt);
639
+ receiptsByHash.set(receipt.hash, hashReceipts);
640
+ }
641
+ for (const [hash, receipts] of receiptsByHash.entries()) {
642
+ const labels = [...new Set(receipts.map((receipt) => receipt.label))];
643
+ if (receipts.length < 2 || labels.length < 2) continue;
644
+ const visibleLabels = labels.slice(0, 8);
645
+ warnings.push({
646
+ selector: group.selector,
647
+ frame_selector: group.frame_selector ?? null,
648
+ hash,
649
+ count: receipts.length,
650
+ label_count: labels.length,
651
+ labels: visibleLabels,
652
+ omitted_label_count: Math.max(0, labels.length - visibleLabels.length),
653
+ ordinals: receipts.map((receipt) => receipt.ordinal).filter((value) => value !== void 0).slice(0, 12),
654
+ reason: "stable_canvas_signature_hash"
655
+ });
656
+ }
632
657
  }
633
658
  return warnings;
634
659
  }
@@ -725,6 +750,8 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
725
750
  const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
726
751
  const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
727
752
  const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
753
+ const deterministicRuntimeReceipts = profileSetupDeterministicRuntimeReceipts(results);
754
+ const sampledDeterministicRuntimeReceipts = sampleProfileSetupSummaryItems(deterministicRuntimeReceipts, 8);
728
755
  const rangeValueReceipts = profileSetupRangeValueReceipts(results);
729
756
  const sampledRangeValueReceipts = sampleProfileSetupSummaryItems(rangeValueReceipts, 8);
730
757
  const dragReceipts = profileSetupDragReceipts(results);
@@ -784,6 +811,9 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
784
811
  window_eval_captured_total: windowEvalCapturedTotal,
785
812
  window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
786
813
  window_eval: sampledWindowEvalReceipts,
814
+ deterministic_runtime_total: deterministicRuntimeReceipts.length,
815
+ deterministic_runtime_truncated: deterministicRuntimeReceipts.length > sampledDeterministicRuntimeReceipts.length,
816
+ deterministic_runtime: sampledDeterministicRuntimeReceipts,
787
817
  set_range_value_total: rangeValueReceipts.length,
788
818
  set_range_value_truncated: rangeValueReceipts.length > sampledRangeValueReceipts.length,
789
819
  set_range_value: sampledRangeValueReceipts,
@@ -846,7 +876,7 @@ function isSupportedCheckType(value) {
846
876
  }
847
877
  function normalizeSetupActionType(value, index) {
848
878
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
849
- 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;
879
+ 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 === "deterministic_runtime" || normalizedInput === "mock_runtime" || normalizedInput === "mock_random" || normalizedInput === "mock_random_queue" || normalizedInput === "seed_random_queue" || normalizedInput === "set_random_queue" || normalizedInput === "mock_clock" || normalizedInput === "set_mock_clock" || normalizedInput === "set_runtime_determinism" || normalizedInput === "runtime_determinism" ? "deterministic_runtime" : 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;
850
880
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
851
881
  return normalized;
852
882
  }
@@ -965,6 +995,39 @@ function normalizeSetupActionScreenshotFullPage(input, type, index) {
965
995
  }
966
996
  return values[0];
967
997
  }
998
+ function normalizeSetupActionRandomQueue(input, index) {
999
+ const rawQueue = valueFromOwn(
1000
+ input,
1001
+ "random_queue",
1002
+ "randomQueue",
1003
+ "random_values",
1004
+ "randomValues",
1005
+ "random_sequence",
1006
+ "randomSequence",
1007
+ "math_random",
1008
+ "mathRandom"
1009
+ );
1010
+ if (rawQueue === void 0) return void 0;
1011
+ if (!Array.isArray(rawQueue) || rawQueue.length === 0) {
1012
+ throw new Error(`target.setup_actions[${index}].random_queue must be a non-empty array of numbers from 0 inclusive to 1 exclusive.`);
1013
+ }
1014
+ return rawQueue.map((item, queueIndex) => {
1015
+ const value = numberValue(item);
1016
+ if (value === void 0 || value < 0 || value >= 1) {
1017
+ throw new Error(`target.setup_actions[${index}].random_queue[${queueIndex}] must be a finite number from 0 inclusive to 1 exclusive.`);
1018
+ }
1019
+ return value;
1020
+ });
1021
+ }
1022
+ function normalizeSetupActionNonNegativeNumber(input, index, outputKey, ...keys) {
1023
+ const rawValue = valueFromOwn(input, ...keys);
1024
+ if (rawValue === void 0) return void 0;
1025
+ const value = numberValue(rawValue);
1026
+ if (value === void 0 || value < 0) {
1027
+ throw new Error(`target.setup_actions[${index}].${outputKey} must be a finite non-negative number.`);
1028
+ }
1029
+ return value;
1030
+ }
968
1031
  function normalizeSetupAction(input, index) {
969
1032
  if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
970
1033
  const type = normalizeSetupActionType(stringValue(input.type), index);
@@ -1025,6 +1088,14 @@ function normalizeSetupAction(input, index) {
1025
1088
  if ((type === "fill" || type === "set_input_value" || type === "set_range_value") && value === void 0 && !hasJsonValue) {
1026
1089
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
1027
1090
  }
1091
+ const randomQueue = type === "deterministic_runtime" ? normalizeSetupActionRandomQueue(input, index) : void 0;
1092
+ const deterministicNow = type === "deterministic_runtime" ? normalizeSetupActionNonNegativeNumber(input, index, "now", "now", "date_now", "dateNow", "mock_now", "mockNow", "clock", "timestamp", "time_ms", "timeMs") : void 0;
1093
+ const deterministicAdvanceMs = type === "deterministic_runtime" ? normalizeSetupActionNonNegativeNumber(input, index, "advance_ms", "advance_ms", "advanceMs", "tick_ms", "tickMs", "add_ms", "addMs") : void 0;
1094
+ const deterministicAppend = type === "deterministic_runtime" && booleanValue(valueFromOwn(input, "append", "append_random", "appendRandom")) === true;
1095
+ const deterministicRestore = type === "deterministic_runtime" && booleanValue(valueFromOwn(input, "restore", "reset", "restore_originals", "restoreOriginals")) === true;
1096
+ if (type === "deterministic_runtime" && randomQueue === void 0 && deterministicNow === void 0 && deterministicAdvanceMs === void 0 && !deterministicRestore) {
1097
+ throw new Error(`target.setup_actions[${index}] deterministic_runtime requires random_queue, now, advance_ms, or restore.`);
1098
+ }
1028
1099
  const key = stringValue(input.key);
1029
1100
  let dialogAccept;
1030
1101
  if (type === "dialog_response") {
@@ -1132,6 +1203,11 @@ function normalizeSetupAction(input, index) {
1132
1203
  key,
1133
1204
  value,
1134
1205
  value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
1206
+ random_queue: randomQueue,
1207
+ now: deterministicNow,
1208
+ advance_ms: deterministicAdvanceMs,
1209
+ append: deterministicAppend || void 0,
1210
+ restore: deterministicRestore || void 0,
1135
1211
  label: stringFromOwn(input, "label", "name", "screenshot_label", "screenshotLabel"),
1136
1212
  script,
1137
1213
  path,
@@ -4208,6 +4284,25 @@ function profileSetupWindowEvalReceipts(results) {
4208
4284
  return receipt;
4209
4285
  });
4210
4286
  }
4287
+ function profileSetupDeterministicRuntimeReceipts(results) {
4288
+ return (results || [])
4289
+ .filter((result) => result && profileSetupResultAction(result) === "deterministic_runtime")
4290
+ .map((result) => ({
4291
+ ordinal: result.ordinal ?? null,
4292
+ ok: result.ok !== false,
4293
+ random_enabled: result.random_enabled ?? null,
4294
+ random_queue_added: result.random_queue_added ?? null,
4295
+ random_queue_length: result.random_queue_length ?? null,
4296
+ random_queue_mode: result.random_queue_mode ?? null,
4297
+ random_underflow_count: result.random_underflow_count ?? null,
4298
+ clock_enabled: result.clock_enabled ?? null,
4299
+ previous_now: result.previous_now ?? null,
4300
+ now: result.now ?? null,
4301
+ advance_ms: result.advance_ms ?? null,
4302
+ restored: result.restored ?? null,
4303
+ reason: result.reason || result.error || null,
4304
+ }));
4305
+ }
4211
4306
  function profileSetupReturnSummaryFields(result) {
4212
4307
  const input = result && result.return_summary_fields;
4213
4308
  if (!Array.isArray(input)) return [];
@@ -4321,24 +4416,31 @@ function profileSetupCanvasSignatureStableHashGroups(results) {
4321
4416
  }
4322
4417
  const warnings = [];
4323
4418
  for (const group of groups.values()) {
4324
- const hashes = new Set(group.receipts.map((receipt) => receipt.hash));
4325
- const labels = [...new Set(group.receipts.map((receipt) => receipt.label))];
4326
- if (group.receipts.length < 2 || labels.length < 2 || hashes.size !== 1) continue;
4327
- const visibleLabels = labels.slice(0, 8);
4328
- warnings.push({
4329
- selector: group.selector,
4330
- frame_selector: group.frame_selector || null,
4331
- hash: group.receipts[0].hash,
4332
- count: group.receipts.length,
4333
- label_count: labels.length,
4334
- labels: visibleLabels,
4335
- omitted_label_count: Math.max(0, labels.length - visibleLabels.length),
4336
- ordinals: group.receipts
4337
- .map((receipt) => receipt.ordinal)
4338
- .filter((value) => value !== undefined)
4339
- .slice(0, 12),
4340
- reason: "stable_canvas_signature_hash",
4341
- });
4419
+ const receiptsByHash = new Map();
4420
+ for (const receipt of group.receipts) {
4421
+ const hashReceipts = receiptsByHash.get(receipt.hash) || [];
4422
+ hashReceipts.push(receipt);
4423
+ receiptsByHash.set(receipt.hash, hashReceipts);
4424
+ }
4425
+ for (const [hash, receipts] of receiptsByHash.entries()) {
4426
+ const labels = [...new Set(receipts.map((receipt) => receipt.label))];
4427
+ if (receipts.length < 2 || labels.length < 2) continue;
4428
+ const visibleLabels = labels.slice(0, 8);
4429
+ warnings.push({
4430
+ selector: group.selector,
4431
+ frame_selector: group.frame_selector || null,
4432
+ hash,
4433
+ count: receipts.length,
4434
+ label_count: labels.length,
4435
+ labels: visibleLabels,
4436
+ omitted_label_count: Math.max(0, labels.length - visibleLabels.length),
4437
+ ordinals: receipts
4438
+ .map((receipt) => receipt.ordinal)
4439
+ .filter((value) => value !== undefined)
4440
+ .slice(0, 12),
4441
+ reason: "stable_canvas_signature_hash",
4442
+ });
4443
+ }
4342
4444
  }
4343
4445
  return warnings;
4344
4446
  }
@@ -4451,6 +4553,8 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
4451
4553
  const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
4452
4554
  const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
4453
4555
  const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
4556
+ const deterministicRuntimeReceipts = profileSetupDeterministicRuntimeReceipts(results);
4557
+ const sampledDeterministicRuntimeReceipts = sampleProfileSetupSummaryItems(deterministicRuntimeReceipts, 8);
4454
4558
  const rangeValueReceipts = profileSetupRangeValueReceipts(results);
4455
4559
  const sampledRangeValueReceipts = sampleProfileSetupSummaryItems(rangeValueReceipts, 8);
4456
4560
  const dragReceipts = profileSetupDragReceipts(results);
@@ -4520,6 +4624,9 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
4520
4624
  window_eval_captured_total: windowEvalCapturedTotal,
4521
4625
  window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
4522
4626
  window_eval: sampledWindowEvalReceipts,
4627
+ deterministic_runtime_total: deterministicRuntimeReceipts.length,
4628
+ deterministic_runtime_truncated: deterministicRuntimeReceipts.length > sampledDeterministicRuntimeReceipts.length,
4629
+ deterministic_runtime: sampledDeterministicRuntimeReceipts,
4523
4630
  set_range_value_total: rangeValueReceipts.length,
4524
4631
  set_range_value_truncated: rangeValueReceipts.length > sampledRangeValueReceipts.length,
4525
4632
  set_range_value: sampledRangeValueReceipts,
@@ -6141,6 +6248,111 @@ async function executeSetupAction(action, ordinal, viewport) {
6141
6248
  }
6142
6249
  return { ...base, ...setupScopeEvidence(scope), ok: true, storage, reload: action.reload === true };
6143
6250
  }
6251
+ if (type === "deterministic_runtime") {
6252
+ const scope = await setupActionScope(action, timeout);
6253
+ if (!scope.ok) return setupScopeFailure(base, scope);
6254
+ const randomQueue = Array.isArray(action.random_queue)
6255
+ ? action.random_queue
6256
+ : Array.isArray(action.randomQueue)
6257
+ ? action.randomQueue
6258
+ : null;
6259
+ const now = setupFiniteNumber(action.now ?? action.date_now ?? action.dateNow ?? action.mock_now ?? action.mockNow ?? action.clock ?? action.timestamp ?? action.time_ms ?? action.timeMs);
6260
+ const advanceMs = setupFiniteNumber(action.advance_ms ?? action.advanceMs ?? action.tick_ms ?? action.tickMs ?? action.add_ms ?? action.addMs);
6261
+ const append = action.append === true || action.append_random === true || action.appendRandom === true;
6262
+ const restore = action.restore === true || action.reset === true || action.restore_originals === true || action.restoreOriginals === true;
6263
+ const runtimeResult = await scope.context.evaluate((payload) => {
6264
+ const root = window;
6265
+ const stateKey = "__RIDDLE_PROOF_DETERMINISTIC_RUNTIME__";
6266
+ const state = root[stateKey] && typeof root[stateKey] === "object" && !Array.isArray(root[stateKey])
6267
+ ? root[stateKey]
6268
+ : {};
6269
+ root[stateKey] = state;
6270
+ if (typeof state.originalRandom !== "function") state.originalRandom = Math.random;
6271
+ if (typeof state.originalDateNow !== "function") state.originalDateNow = Date.now;
6272
+ const previousNow = typeof state.now === "number" && Number.isFinite(state.now)
6273
+ ? state.now
6274
+ : Date.now === state.originalDateNow
6275
+ ? null
6276
+ : Date.now();
6277
+ if (payload.restore) {
6278
+ Math.random = state.originalRandom;
6279
+ Date.now = state.originalDateNow;
6280
+ delete root[stateKey];
6281
+ return {
6282
+ ok: true,
6283
+ restored: true,
6284
+ random_enabled: false,
6285
+ random_queue_added: 0,
6286
+ random_queue_length: 0,
6287
+ random_queue_mode: null,
6288
+ random_underflow_count: typeof state.randomUnderflowCount === "number" ? state.randomUnderflowCount : 0,
6289
+ clock_enabled: false,
6290
+ previous_now: previousNow,
6291
+ now: null,
6292
+ advance_ms: null,
6293
+ };
6294
+ }
6295
+ let randomQueueAdded = null;
6296
+ let randomQueueMode = null;
6297
+ if (Array.isArray(payload.random_queue)) {
6298
+ const queue = payload.random_queue.filter((value) => typeof value === "number" && Number.isFinite(value) && value >= 0 && value < 1);
6299
+ const existing = Array.isArray(state.randomQueue) ? state.randomQueue : [];
6300
+ state.randomQueue = payload.append ? existing.concat(queue) : queue.slice();
6301
+ randomQueueAdded = queue.length;
6302
+ randomQueueMode = payload.append ? "append" : "replace";
6303
+ Math.random = function riddleProofMockRandom() {
6304
+ const activeQueue = Array.isArray(state.randomQueue) ? state.randomQueue : [];
6305
+ if (activeQueue.length) return activeQueue.shift();
6306
+ state.randomUnderflowCount = (typeof state.randomUnderflowCount === "number" ? state.randomUnderflowCount : 0) + 1;
6307
+ return 0;
6308
+ };
6309
+ }
6310
+ if (typeof payload.now === "number" && Number.isFinite(payload.now)) {
6311
+ state.now = payload.now;
6312
+ Date.now = function riddleProofMockDateNow() {
6313
+ return state.now;
6314
+ };
6315
+ }
6316
+ if (typeof payload.advance_ms === "number" && Number.isFinite(payload.advance_ms)) {
6317
+ const baseNow = typeof state.now === "number" && Number.isFinite(state.now)
6318
+ ? state.now
6319
+ : Date.now();
6320
+ state.now = baseNow + payload.advance_ms;
6321
+ Date.now = function riddleProofMockDateNow() {
6322
+ return state.now;
6323
+ };
6324
+ }
6325
+ return {
6326
+ ok: true,
6327
+ restored: false,
6328
+ random_enabled: Math.random !== state.originalRandom,
6329
+ random_queue_added: randomQueueAdded,
6330
+ random_queue_length: Array.isArray(state.randomQueue) ? state.randomQueue.length : 0,
6331
+ random_queue_mode: randomQueueMode,
6332
+ random_underflow_count: typeof state.randomUnderflowCount === "number" ? state.randomUnderflowCount : 0,
6333
+ clock_enabled: Date.now !== state.originalDateNow,
6334
+ previous_now: previousNow,
6335
+ now: typeof state.now === "number" && Number.isFinite(state.now) ? state.now : null,
6336
+ advance_ms: typeof payload.advance_ms === "number" && Number.isFinite(payload.advance_ms) ? payload.advance_ms : null,
6337
+ };
6338
+ }, { random_queue: randomQueue, now, advance_ms: advanceMs, append, restore });
6339
+ return {
6340
+ ...base,
6341
+ ...setupScopeEvidence(scope),
6342
+ ok: runtimeResult && runtimeResult.ok === true,
6343
+ random_enabled: runtimeResult?.random_enabled,
6344
+ random_queue_added: runtimeResult?.random_queue_added,
6345
+ random_queue_length: runtimeResult?.random_queue_length,
6346
+ random_queue_mode: runtimeResult?.random_queue_mode,
6347
+ random_underflow_count: runtimeResult?.random_underflow_count,
6348
+ clock_enabled: runtimeResult?.clock_enabled,
6349
+ previous_now: runtimeResult?.previous_now,
6350
+ now: runtimeResult?.now,
6351
+ advance_ms: runtimeResult?.advance_ms,
6352
+ restored: runtimeResult?.restored,
6353
+ reason: runtimeResult && runtimeResult.ok === true ? undefined : runtimeResult?.reason || "deterministic_runtime_not_applied",
6354
+ };
6355
+ }
6144
6356
  if (type === "window_eval") {
6145
6357
  const script = String(action.script || action.code || action.source || action.body || "");
6146
6358
  const args = Array.isArray(action.args) ? action.args : [];