@riddledc/riddle-proof 0.7.140 → 0.7.141

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
@@ -401,7 +401,7 @@ transport control, or other bounded interaction. Supported setup actions are
401
401
  `assert_text_absent`, `assert_selector_count`, `assert_window_value`,
402
402
  `assert_window_number`, `local_storage`, `session_storage`, `clear_storage`,
403
403
  `clear_console`, `screenshot`, `wait`, `wait_for_selector`, `wait_for_text`,
404
- `window_call`, and `window_call_until`;
404
+ `window_eval`, `window_call`, and `window_call_until`;
405
405
  a failed setup action is recorded as a failed `setup_actions_succeeded` check so
406
406
  the profile cannot pass without reaching the intended state. Text-matched `click` actions prefer
407
407
  visible matching elements, which keeps responsive layouts from selecting hidden
@@ -447,6 +447,12 @@ errors, but keeps network mock hit evidence intact. Any setup action can include
447
447
  with `repeat_index` and `repeat_count`, and `after_ms` runs after each
448
448
  repetition. Use it for bounded game proof helpers, retry controls, or other
449
449
  workflows where one declarative action needs to advance the app several times.
450
+ Use `window_eval` for async browser-side helper code that is easier to express
451
+ as a short script body than as a preexisting `window` function. It accepts
452
+ `script` plus optional JSON `args`, can compare `expect_return`, can store the
453
+ JSON-safe return value with `store_return_to`, and honors `capture_return:
454
+ false` for compact receipts. The script runs as an async function body with
455
+ `args` available in scope, so `return { ok: true }` records a structured return.
450
456
  Use `window_call_until` when a proof helper needs to advance randomized or
451
457
  progressive state until a window-state receipt is true. It accepts `path` plus
452
458
  optional `args`, `until_path`, `until_expected_value`, `max_calls` from 1 to
@@ -61,6 +61,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
61
61
  "wait",
62
62
  "wait_for_selector",
63
63
  "wait_for_text",
64
+ "window_eval",
64
65
  "window_call",
65
66
  "window_call_until"
66
67
  ];
@@ -480,6 +481,21 @@ function profileSetupWindowCallReceipts(results) {
480
481
  return receipt;
481
482
  });
482
483
  }
484
+ function profileSetupWindowEvalReceipts(results) {
485
+ return results.filter((result) => profileSetupResultAction(result) === "window_eval").map((result) => {
486
+ const receipt = {
487
+ ordinal: result.ordinal ?? null,
488
+ ok: result.ok !== false,
489
+ script_length: result.script_length ?? null,
490
+ return_captured: result.return_captured ?? null,
491
+ return_stored_to: result.return_stored_to ?? null,
492
+ reason: result.reason ?? result.error ?? result.store_reason ?? null
493
+ };
494
+ if (result.returned !== void 0) receipt.returned = result.returned;
495
+ if (result.expected_return !== void 0) receipt.expected_return = result.expected_return;
496
+ return receipt;
497
+ });
498
+ }
483
499
  function sampleProfileSetupSummaryItems(items, limit) {
484
500
  if (items.length <= limit) return items;
485
501
  const firstCount = Math.floor(limit / 2);
@@ -518,6 +534,10 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
518
534
  const windowCallStoredTotal = windowCallReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
519
535
  const windowCallCapturedTotal = windowCallReceipts.filter((result) => result.return_captured === true).length;
520
536
  const sampledWindowCallReceipts = sampleProfileSetupSummaryItems(windowCallReceipts, 8);
537
+ const windowEvalReceipts = profileSetupWindowEvalReceipts(results);
538
+ const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
539
+ const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
540
+ const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
521
541
  const clickedItems = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => {
522
542
  const clickCount = typeof result.click_count === "number" && Number.isFinite(result.click_count) && result.click_count > 1 ? result.click_count : void 0;
523
543
  return {
@@ -561,6 +581,11 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
561
581
  window_call_captured_total: windowCallCapturedTotal,
562
582
  window_call_truncated: windowCallReceipts.length > sampledWindowCallReceipts.length,
563
583
  window_call: sampledWindowCallReceipts,
584
+ window_eval_total: windowEvalReceipts.length,
585
+ window_eval_stored_total: windowEvalStoredTotal,
586
+ window_eval_captured_total: windowEvalCapturedTotal,
587
+ window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
588
+ window_eval: sampledWindowEvalReceipts,
564
589
  clicked,
565
590
  text_samples,
566
591
  failed: failed.map((result) => ({
@@ -613,7 +638,7 @@ function isSupportedCheckType(value) {
613
638
  }
614
639
  function normalizeSetupActionType(value, index) {
615
640
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
616
- 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 === "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;
641
+ 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 === "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;
617
642
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
618
643
  return normalized;
619
644
  }
@@ -631,7 +656,7 @@ function normalizeSetupActionArgs(input, index) {
631
656
  const argsInput = valueFromOwn(input, "args", "arguments", "args_json", "argsJson");
632
657
  if (argsInput === void 0) return void 0;
633
658
  if (!Array.isArray(argsInput)) {
634
- throw new Error(`target.setup_actions[${index}] window_call args must be an array.`);
659
+ throw new Error(`target.setup_actions[${index}] window_call/window_eval args must be an array.`);
635
660
  }
636
661
  return argsInput.map(toJsonValue);
637
662
  }
@@ -775,7 +800,11 @@ function normalizeSetupAction(input, index) {
775
800
  if ((type === "window_call" || type === "window_call_until" || type === "assert_window_value" || type === "assert_window_number") && !path) {
776
801
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
777
802
  }
778
- const args = type === "window_call" || type === "window_call_until" ? normalizeSetupActionArgs(input, index) : void 0;
803
+ const script = stringFromOwn(input, "script", "code", "source", "body");
804
+ if (type === "window_eval" && !script) {
805
+ throw new Error(`target.setup_actions[${index}] window_eval requires script.`);
806
+ }
807
+ const args = type === "window_call" || type === "window_call_until" || type === "window_eval" ? normalizeSetupActionArgs(input, index) : void 0;
779
808
  const hasExpectedValue = hasOwn(input, "expected_value") || hasOwn(input, "expectedValue") || hasOwn(input, "expected") || hasOwn(input, "expect_value") || hasOwn(input, "expectValue") || hasOwn(input, "expect");
780
809
  if (type === "assert_window_value" && !hasExpectedValue) {
781
810
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
@@ -846,6 +875,7 @@ function normalizeSetupAction(input, index) {
846
875
  value,
847
876
  value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
848
877
  label: stringFromOwn(input, "label", "name", "screenshot_label", "screenshotLabel"),
878
+ script,
849
879
  path,
850
880
  args,
851
881
  expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
@@ -3797,6 +3827,23 @@ function profileSetupWindowCallReceipts(results) {
3797
3827
  return receipt;
3798
3828
  });
3799
3829
  }
3830
+ function profileSetupWindowEvalReceipts(results) {
3831
+ return (results || [])
3832
+ .filter((result) => result && profileSetupResultAction(result) === "window_eval")
3833
+ .map((result) => {
3834
+ const receipt = {
3835
+ ordinal: result.ordinal ?? null,
3836
+ ok: result.ok !== false,
3837
+ script_length: result.script_length ?? null,
3838
+ return_captured: result.return_captured ?? null,
3839
+ return_stored_to: result.return_stored_to ?? null,
3840
+ reason: result.reason || result.error || result.store_reason || null,
3841
+ };
3842
+ if (result.returned !== undefined) receipt.returned = result.returned;
3843
+ if (result.expected_return !== undefined) receipt.expected_return = result.expected_return;
3844
+ return receipt;
3845
+ });
3846
+ }
3800
3847
  function sampleProfileSetupSummaryItems(items, limit) {
3801
3848
  if ((items || []).length <= limit) return items || [];
3802
3849
  const firstCount = Math.floor(limit / 2);
@@ -3849,6 +3896,10 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
3849
3896
  const windowCallStoredTotal = windowCallReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
3850
3897
  const windowCallCapturedTotal = windowCallReceipts.filter((result) => result.return_captured === true).length;
3851
3898
  const sampledWindowCallReceipts = sampleProfileSetupSummaryItems(windowCallReceipts, 8);
3899
+ const windowEvalReceipts = profileSetupWindowEvalReceipts(results);
3900
+ const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
3901
+ const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
3902
+ const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
3852
3903
  const clickedItems = results
3853
3904
  .filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
3854
3905
  .map((result) => {
@@ -3902,6 +3953,11 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
3902
3953
  window_call_captured_total: windowCallCapturedTotal,
3903
3954
  window_call_truncated: windowCallReceipts.length > sampledWindowCallReceipts.length,
3904
3955
  window_call: sampledWindowCallReceipts,
3956
+ window_eval_total: windowEvalReceipts.length,
3957
+ window_eval_stored_total: windowEvalStoredTotal,
3958
+ window_eval_captured_total: windowEvalCapturedTotal,
3959
+ window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
3960
+ window_eval: sampledWindowEvalReceipts,
3905
3961
  clicked,
3906
3962
  text_samples: textSamples,
3907
3963
  failed: failed.map((result) => ({
@@ -4882,6 +4938,49 @@ async function setupCallWindowFunction(context, path, args, storeReturnTo, captu
4882
4938
  }
4883
4939
  }, { path, args, storeReturnTo, captureReturn });
4884
4940
  }
4941
+ async function setupEvaluateWindowScript(context, script, args, storeReturnTo, captureReturn) {
4942
+ return await context.evaluate(async ({ script, args, storeReturnTo, captureReturn }) => {
4943
+ const toJsonValue = (value) => {
4944
+ if (value === null || value === undefined) return null;
4945
+ if (typeof value === "string" || typeof value === "boolean") return value;
4946
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
4947
+ if (Array.isArray(value)) return value.map(toJsonValue);
4948
+ if (typeof value === "object") {
4949
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
4950
+ }
4951
+ return String(value);
4952
+ };
4953
+ const storeWindowReturn = (storePath, value) => {
4954
+ const pathParts = String(storePath || "").split(".").map((part) => part.trim()).filter(Boolean);
4955
+ if (pathParts[0] === "window") pathParts.shift();
4956
+ if (!pathParts.length) return { ok: false, reason: "missing_store_path" };
4957
+ let target = window;
4958
+ for (let index = 0; index < pathParts.length - 1; index += 1) {
4959
+ const part = pathParts[index];
4960
+ if (target[part] === null || typeof target[part] !== "object") target[part] = {};
4961
+ target = target[part];
4962
+ }
4963
+ target[pathParts[pathParts.length - 1]] = value;
4964
+ return { ok: true, path: pathParts.join(".") };
4965
+ };
4966
+ const body = String(script || "");
4967
+ if (!body.trim()) return { ok: false, reason: "missing_script" };
4968
+ try {
4969
+ const run = new Function("args", "\"use strict\"; return (async () => {\\n" + body + "\\n})();");
4970
+ const returned = await run(Array.isArray(args) ? args : []);
4971
+ const jsonReturned = toJsonValue(returned);
4972
+ const returnedForResult = captureReturn === false ? undefined : jsonReturned;
4973
+ if (storeReturnTo) {
4974
+ const stored = storeWindowReturn(storeReturnTo, jsonReturned);
4975
+ if (!stored.ok) return { ok: false, reason: "return_store_failed", store_reason: stored.reason, returned: returnedForResult };
4976
+ return { ok: true, returned: returnedForResult, return_stored_to: stored.path };
4977
+ }
4978
+ return { ok: true, returned: returnedForResult };
4979
+ } catch (error) {
4980
+ return { ok: false, reason: "script_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
4981
+ }
4982
+ }, { script, args, storeReturnTo, captureReturn });
4983
+ }
4885
4984
  function setupFrameSelector(action) {
4886
4985
  return String(action?.frame_selector || action?.frameSelector || action?.iframe_selector || action?.iframeSelector || "").trim();
4887
4986
  }
@@ -5395,6 +5494,44 @@ async function executeSetupAction(action, ordinal, viewport) {
5395
5494
  }
5396
5495
  return { ...base, ...setupScopeEvidence(scope), ok: true, storage, reload: action.reload === true };
5397
5496
  }
5497
+ if (type === "window_eval") {
5498
+ const script = String(action.script || action.code || action.source || action.body || "");
5499
+ const args = Array.isArray(action.args) ? action.args : [];
5500
+ const storeReturnTo = String(action.store_return_to || action.storeReturnTo || action.save_return_to || action.saveReturnTo || action.assign_return_to || action.assignReturnTo || action.return_state_path || action.returnStatePath || "").trim();
5501
+ if (!script.trim()) return { ...base, reason: "missing_script" };
5502
+ const scope = await setupActionScope(action, timeout);
5503
+ if (!scope.ok) return setupScopeFailure(base, scope);
5504
+ const hasExpectation = setupHasOwn(action, "expect_return")
5505
+ || setupHasOwn(action, "expectReturn")
5506
+ || setupHasOwn(action, "expected_return")
5507
+ || setupHasOwn(action, "expectedReturn");
5508
+ const expected = setupHasOwn(action, "expect_return")
5509
+ ? action.expect_return
5510
+ : setupHasOwn(action, "expectReturn")
5511
+ ? action.expectReturn
5512
+ : setupHasOwn(action, "expected_return")
5513
+ ? action.expected_return
5514
+ : action.expectedReturn;
5515
+ const captureReturn = action.capture_return === false || action.captureReturn === false || action.include_return === false || action.includeReturn === false || action.omit_return === true || action.omitReturn === true
5516
+ ? hasExpectation
5517
+ : true;
5518
+ const result = await setupEvaluateWindowScript(scope.context, script, args, storeReturnTo, captureReturn);
5519
+ const expectationMet = !hasExpectation || setupValuesEqual(result.returned, expected);
5520
+ return {
5521
+ ...base,
5522
+ ...setupScopeEvidence(scope),
5523
+ ok: Boolean(result.ok && expectationMet),
5524
+ script_length: script.length,
5525
+ arg_count: args.length,
5526
+ returned: captureReturn ? setupJsonValue(result.returned) : undefined,
5527
+ return_captured: captureReturn,
5528
+ expected_return: hasExpectation ? setupJsonValue(expected) : undefined,
5529
+ return_stored_to: result.return_stored_to || storeReturnTo || undefined,
5530
+ reason: result.ok ? (expectationMet ? undefined : "unexpected_return_value") : result.reason,
5531
+ store_reason: result.store_reason || undefined,
5532
+ error: result.error || undefined,
5533
+ };
5534
+ }
5398
5535
  if (type === "window_call") {
5399
5536
  const path = String(action.path || action.function_path || action.functionPath || "");
5400
5537
  const args = Array.isArray(action.args) ? action.args : [];
package/dist/cli.cjs CHANGED
@@ -6998,6 +6998,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
6998
6998
  "wait",
6999
6999
  "wait_for_selector",
7000
7000
  "wait_for_text",
7001
+ "window_eval",
7001
7002
  "window_call",
7002
7003
  "window_call_until"
7003
7004
  ];
@@ -7417,6 +7418,21 @@ function profileSetupWindowCallReceipts(results) {
7417
7418
  return receipt;
7418
7419
  });
7419
7420
  }
7421
+ function profileSetupWindowEvalReceipts(results) {
7422
+ return results.filter((result) => profileSetupResultAction(result) === "window_eval").map((result) => {
7423
+ const receipt = {
7424
+ ordinal: result.ordinal ?? null,
7425
+ ok: result.ok !== false,
7426
+ script_length: result.script_length ?? null,
7427
+ return_captured: result.return_captured ?? null,
7428
+ return_stored_to: result.return_stored_to ?? null,
7429
+ reason: result.reason ?? result.error ?? result.store_reason ?? null
7430
+ };
7431
+ if (result.returned !== void 0) receipt.returned = result.returned;
7432
+ if (result.expected_return !== void 0) receipt.expected_return = result.expected_return;
7433
+ return receipt;
7434
+ });
7435
+ }
7420
7436
  function sampleProfileSetupSummaryItems(items, limit) {
7421
7437
  if (items.length <= limit) return items;
7422
7438
  const firstCount = Math.floor(limit / 2);
@@ -7455,6 +7471,10 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
7455
7471
  const windowCallStoredTotal = windowCallReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
7456
7472
  const windowCallCapturedTotal = windowCallReceipts.filter((result) => result.return_captured === true).length;
7457
7473
  const sampledWindowCallReceipts = sampleProfileSetupSummaryItems(windowCallReceipts, 8);
7474
+ const windowEvalReceipts = profileSetupWindowEvalReceipts(results);
7475
+ const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
7476
+ const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
7477
+ const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
7458
7478
  const clickedItems = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => {
7459
7479
  const clickCount = typeof result.click_count === "number" && Number.isFinite(result.click_count) && result.click_count > 1 ? result.click_count : void 0;
7460
7480
  return {
@@ -7498,6 +7518,11 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
7498
7518
  window_call_captured_total: windowCallCapturedTotal,
7499
7519
  window_call_truncated: windowCallReceipts.length > sampledWindowCallReceipts.length,
7500
7520
  window_call: sampledWindowCallReceipts,
7521
+ window_eval_total: windowEvalReceipts.length,
7522
+ window_eval_stored_total: windowEvalStoredTotal,
7523
+ window_eval_captured_total: windowEvalCapturedTotal,
7524
+ window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
7525
+ window_eval: sampledWindowEvalReceipts,
7501
7526
  clicked,
7502
7527
  text_samples,
7503
7528
  failed: failed.map((result) => ({
@@ -7550,7 +7575,7 @@ function isSupportedCheckType(value) {
7550
7575
  }
7551
7576
  function normalizeSetupActionType(value, index) {
7552
7577
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
7553
- 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 === "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;
7578
+ 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 === "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;
7554
7579
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
7555
7580
  return normalized;
7556
7581
  }
@@ -7568,7 +7593,7 @@ function normalizeSetupActionArgs(input, index) {
7568
7593
  const argsInput = valueFromOwn(input, "args", "arguments", "args_json", "argsJson");
7569
7594
  if (argsInput === void 0) return void 0;
7570
7595
  if (!Array.isArray(argsInput)) {
7571
- throw new Error(`target.setup_actions[${index}] window_call args must be an array.`);
7596
+ throw new Error(`target.setup_actions[${index}] window_call/window_eval args must be an array.`);
7572
7597
  }
7573
7598
  return argsInput.map(toJsonValue);
7574
7599
  }
@@ -7712,7 +7737,11 @@ function normalizeSetupAction(input, index) {
7712
7737
  if ((type === "window_call" || type === "window_call_until" || type === "assert_window_value" || type === "assert_window_number") && !path7) {
7713
7738
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
7714
7739
  }
7715
- const args = type === "window_call" || type === "window_call_until" ? normalizeSetupActionArgs(input, index) : void 0;
7740
+ const script = stringFromOwn(input, "script", "code", "source", "body");
7741
+ if (type === "window_eval" && !script) {
7742
+ throw new Error(`target.setup_actions[${index}] window_eval requires script.`);
7743
+ }
7744
+ const args = type === "window_call" || type === "window_call_until" || type === "window_eval" ? normalizeSetupActionArgs(input, index) : void 0;
7716
7745
  const hasExpectedValue = hasOwn(input, "expected_value") || hasOwn(input, "expectedValue") || hasOwn(input, "expected") || hasOwn(input, "expect_value") || hasOwn(input, "expectValue") || hasOwn(input, "expect");
7717
7746
  if (type === "assert_window_value" && !hasExpectedValue) {
7718
7747
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
@@ -7783,6 +7812,7 @@ function normalizeSetupAction(input, index) {
7783
7812
  value,
7784
7813
  value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
7785
7814
  label: stringFromOwn(input, "label", "name", "screenshot_label", "screenshotLabel"),
7815
+ script,
7786
7816
  path: path7,
7787
7817
  args,
7788
7818
  expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
@@ -10718,6 +10748,23 @@ function profileSetupWindowCallReceipts(results) {
10718
10748
  return receipt;
10719
10749
  });
10720
10750
  }
10751
+ function profileSetupWindowEvalReceipts(results) {
10752
+ return (results || [])
10753
+ .filter((result) => result && profileSetupResultAction(result) === "window_eval")
10754
+ .map((result) => {
10755
+ const receipt = {
10756
+ ordinal: result.ordinal ?? null,
10757
+ ok: result.ok !== false,
10758
+ script_length: result.script_length ?? null,
10759
+ return_captured: result.return_captured ?? null,
10760
+ return_stored_to: result.return_stored_to ?? null,
10761
+ reason: result.reason || result.error || result.store_reason || null,
10762
+ };
10763
+ if (result.returned !== undefined) receipt.returned = result.returned;
10764
+ if (result.expected_return !== undefined) receipt.expected_return = result.expected_return;
10765
+ return receipt;
10766
+ });
10767
+ }
10721
10768
  function sampleProfileSetupSummaryItems(items, limit) {
10722
10769
  if ((items || []).length <= limit) return items || [];
10723
10770
  const firstCount = Math.floor(limit / 2);
@@ -10770,6 +10817,10 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
10770
10817
  const windowCallStoredTotal = windowCallReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
10771
10818
  const windowCallCapturedTotal = windowCallReceipts.filter((result) => result.return_captured === true).length;
10772
10819
  const sampledWindowCallReceipts = sampleProfileSetupSummaryItems(windowCallReceipts, 8);
10820
+ const windowEvalReceipts = profileSetupWindowEvalReceipts(results);
10821
+ const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
10822
+ const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
10823
+ const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
10773
10824
  const clickedItems = results
10774
10825
  .filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
10775
10826
  .map((result) => {
@@ -10823,6 +10874,11 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
10823
10874
  window_call_captured_total: windowCallCapturedTotal,
10824
10875
  window_call_truncated: windowCallReceipts.length > sampledWindowCallReceipts.length,
10825
10876
  window_call: sampledWindowCallReceipts,
10877
+ window_eval_total: windowEvalReceipts.length,
10878
+ window_eval_stored_total: windowEvalStoredTotal,
10879
+ window_eval_captured_total: windowEvalCapturedTotal,
10880
+ window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
10881
+ window_eval: sampledWindowEvalReceipts,
10826
10882
  clicked,
10827
10883
  text_samples: textSamples,
10828
10884
  failed: failed.map((result) => ({
@@ -11803,6 +11859,49 @@ async function setupCallWindowFunction(context, path, args, storeReturnTo, captu
11803
11859
  }
11804
11860
  }, { path, args, storeReturnTo, captureReturn });
11805
11861
  }
11862
+ async function setupEvaluateWindowScript(context, script, args, storeReturnTo, captureReturn) {
11863
+ return await context.evaluate(async ({ script, args, storeReturnTo, captureReturn }) => {
11864
+ const toJsonValue = (value) => {
11865
+ if (value === null || value === undefined) return null;
11866
+ if (typeof value === "string" || typeof value === "boolean") return value;
11867
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
11868
+ if (Array.isArray(value)) return value.map(toJsonValue);
11869
+ if (typeof value === "object") {
11870
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
11871
+ }
11872
+ return String(value);
11873
+ };
11874
+ const storeWindowReturn = (storePath, value) => {
11875
+ const pathParts = String(storePath || "").split(".").map((part) => part.trim()).filter(Boolean);
11876
+ if (pathParts[0] === "window") pathParts.shift();
11877
+ if (!pathParts.length) return { ok: false, reason: "missing_store_path" };
11878
+ let target = window;
11879
+ for (let index = 0; index < pathParts.length - 1; index += 1) {
11880
+ const part = pathParts[index];
11881
+ if (target[part] === null || typeof target[part] !== "object") target[part] = {};
11882
+ target = target[part];
11883
+ }
11884
+ target[pathParts[pathParts.length - 1]] = value;
11885
+ return { ok: true, path: pathParts.join(".") };
11886
+ };
11887
+ const body = String(script || "");
11888
+ if (!body.trim()) return { ok: false, reason: "missing_script" };
11889
+ try {
11890
+ const run = new Function("args", "\"use strict\"; return (async () => {\\n" + body + "\\n})();");
11891
+ const returned = await run(Array.isArray(args) ? args : []);
11892
+ const jsonReturned = toJsonValue(returned);
11893
+ const returnedForResult = captureReturn === false ? undefined : jsonReturned;
11894
+ if (storeReturnTo) {
11895
+ const stored = storeWindowReturn(storeReturnTo, jsonReturned);
11896
+ if (!stored.ok) return { ok: false, reason: "return_store_failed", store_reason: stored.reason, returned: returnedForResult };
11897
+ return { ok: true, returned: returnedForResult, return_stored_to: stored.path };
11898
+ }
11899
+ return { ok: true, returned: returnedForResult };
11900
+ } catch (error) {
11901
+ return { ok: false, reason: "script_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
11902
+ }
11903
+ }, { script, args, storeReturnTo, captureReturn });
11904
+ }
11806
11905
  function setupFrameSelector(action) {
11807
11906
  return String(action?.frame_selector || action?.frameSelector || action?.iframe_selector || action?.iframeSelector || "").trim();
11808
11907
  }
@@ -12316,6 +12415,44 @@ async function executeSetupAction(action, ordinal, viewport) {
12316
12415
  }
12317
12416
  return { ...base, ...setupScopeEvidence(scope), ok: true, storage, reload: action.reload === true };
12318
12417
  }
12418
+ if (type === "window_eval") {
12419
+ const script = String(action.script || action.code || action.source || action.body || "");
12420
+ const args = Array.isArray(action.args) ? action.args : [];
12421
+ const storeReturnTo = String(action.store_return_to || action.storeReturnTo || action.save_return_to || action.saveReturnTo || action.assign_return_to || action.assignReturnTo || action.return_state_path || action.returnStatePath || "").trim();
12422
+ if (!script.trim()) return { ...base, reason: "missing_script" };
12423
+ const scope = await setupActionScope(action, timeout);
12424
+ if (!scope.ok) return setupScopeFailure(base, scope);
12425
+ const hasExpectation = setupHasOwn(action, "expect_return")
12426
+ || setupHasOwn(action, "expectReturn")
12427
+ || setupHasOwn(action, "expected_return")
12428
+ || setupHasOwn(action, "expectedReturn");
12429
+ const expected = setupHasOwn(action, "expect_return")
12430
+ ? action.expect_return
12431
+ : setupHasOwn(action, "expectReturn")
12432
+ ? action.expectReturn
12433
+ : setupHasOwn(action, "expected_return")
12434
+ ? action.expected_return
12435
+ : action.expectedReturn;
12436
+ const captureReturn = action.capture_return === false || action.captureReturn === false || action.include_return === false || action.includeReturn === false || action.omit_return === true || action.omitReturn === true
12437
+ ? hasExpectation
12438
+ : true;
12439
+ const result = await setupEvaluateWindowScript(scope.context, script, args, storeReturnTo, captureReturn);
12440
+ const expectationMet = !hasExpectation || setupValuesEqual(result.returned, expected);
12441
+ return {
12442
+ ...base,
12443
+ ...setupScopeEvidence(scope),
12444
+ ok: Boolean(result.ok && expectationMet),
12445
+ script_length: script.length,
12446
+ arg_count: args.length,
12447
+ returned: captureReturn ? setupJsonValue(result.returned) : undefined,
12448
+ return_captured: captureReturn,
12449
+ expected_return: hasExpectation ? setupJsonValue(expected) : undefined,
12450
+ return_stored_to: result.return_stored_to || storeReturnTo || undefined,
12451
+ reason: result.ok ? (expectationMet ? undefined : "unexpected_return_value") : result.reason,
12452
+ store_reason: result.store_reason || undefined,
12453
+ error: result.error || undefined,
12454
+ };
12455
+ }
12319
12456
  if (type === "window_call") {
12320
12457
  const path = String(action.path || action.function_path || action.functionPath || "");
12321
12458
  const args = Array.isArray(action.args) ? action.args : [];
@@ -14714,6 +14851,9 @@ function profileSetupSummaryMarkdown(result) {
14714
14851
  const windowCallTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_total) || 0), 0);
14715
14852
  const windowCallStoredTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_stored_total) || 0), 0);
14716
14853
  const windowCallCapturedTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_captured_total) || 0), 0);
14854
+ const windowEvalTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_eval_total) || 0), 0);
14855
+ const windowEvalStoredTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_eval_stored_total) || 0), 0);
14856
+ const windowEvalCapturedTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_eval_captured_total) || 0), 0);
14717
14857
  const windowCallUntilTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_until_total) || 0), 0);
14718
14858
  const windowCallUntilCallTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_until_call_total) || 0), 0);
14719
14859
  const failedTotal = viewports.reduce((sum, viewport) => sum + (Array.isArray(viewport.failed) ? viewport.failed.length : 0), 0);
@@ -14729,6 +14869,9 @@ function profileSetupSummaryMarkdown(result) {
14729
14869
  if (windowCallTotal) {
14730
14870
  lines.push(`- window_call: ${windowCallTotal} action(s), stored returns ${windowCallStoredTotal}, captured returns ${windowCallCapturedTotal}`);
14731
14871
  }
14872
+ if (windowEvalTotal) {
14873
+ lines.push(`- window_eval: ${windowEvalTotal} action(s), stored returns ${windowEvalStoredTotal}, captured returns ${windowEvalCapturedTotal}`);
14874
+ }
14732
14875
  if (windowCallUntilTotal) {
14733
14876
  lines.push(`- window_call_until: ${windowCallUntilTotal} action(s), call_count total ${windowCallUntilCallTotal}`);
14734
14877
  }
@@ -14742,10 +14885,13 @@ function profileSetupSummaryMarkdown(result) {
14742
14885
  const windowCallActions = cliFiniteNumber(viewport.window_call_total) || 0;
14743
14886
  const windowCallStored = cliFiniteNumber(viewport.window_call_stored_total) || 0;
14744
14887
  const windowCallCaptured = cliFiniteNumber(viewport.window_call_captured_total) || 0;
14888
+ const windowEvalActions = cliFiniteNumber(viewport.window_eval_total) || 0;
14889
+ const windowEvalStored = cliFiniteNumber(viewport.window_eval_stored_total) || 0;
14890
+ const windowEvalCaptured = cliFiniteNumber(viewport.window_eval_captured_total) || 0;
14745
14891
  const windowCallUntilActions = cliFiniteNumber(viewport.window_call_until_total) || 0;
14746
14892
  const windowCallUntilCalls = cliFiniteNumber(viewport.window_call_until_call_total) || 0;
14747
14893
  const observedPath = cliString(viewport.observed_path);
14748
- lines.push(`- ${name}: ${ok}, ${resultCount} result(s), ${screenshotCount} setup screenshot(s), ${clicked} click(s)${clickCountActions ? `, ${clickCountActions} click_count action(s)` : ""}${windowCallActions ? `, ${windowCallActions} window_call action(s), ${windowCallStored} stored return(s), ${windowCallCaptured} captured return(s)` : ""}${windowCallUntilActions ? `, ${windowCallUntilActions} window_call_until action(s), ${windowCallUntilCalls} call(s)` : ""}${observedPath ? `, path ${observedPath}` : ""}`);
14894
+ lines.push(`- ${name}: ${ok}, ${resultCount} result(s), ${screenshotCount} setup screenshot(s), ${clicked} click(s)${clickCountActions ? `, ${clickCountActions} click_count 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}` : ""}`);
14749
14895
  }
14750
14896
  const windowCallDetails = viewports.flatMap((viewport) => {
14751
14897
  const name = cliString(viewport.name) || "viewport";
@@ -14763,6 +14909,22 @@ function profileSetupSummaryMarkdown(result) {
14763
14909
  lines.push(`- ${name} window_call: ${ok}, ${markdownInlineCode(path7)}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}, return ${captured}${expected === void 0 ? "" : `, expected ${markdownInlineCode(expected, 80)}`}${returned === void 0 ? "" : `, returned ${markdownInlineCode(returned, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
14764
14910
  }
14765
14911
  if (windowCallDetails.length > 12) lines.push(`- ${windowCallDetails.length - 12} additional window_call receipt(s) omitted.`);
14912
+ const windowEvalDetails = viewports.flatMap((viewport) => {
14913
+ const name = cliString(viewport.name) || "viewport";
14914
+ const receipts = Array.isArray(viewport.window_eval) ? viewport.window_eval.map(cliRecord).filter((item) => Boolean(item)) : [];
14915
+ return receipts.map((receipt) => ({ name, receipt }));
14916
+ });
14917
+ for (const { name, receipt } of windowEvalDetails.slice(0, 12)) {
14918
+ const scriptLength = cliFiniteNumber(receipt.script_length);
14919
+ const storedTo = cliString(receipt.return_stored_to);
14920
+ const returned = cliValueLabel(receipt.returned);
14921
+ const expected = cliValueLabel(receipt.expected_return);
14922
+ const captured = receipt.return_captured === true ? "captured" : receipt.return_captured === false ? "not captured" : "capture unknown";
14923
+ const ok = receipt.ok === false ? "failed" : "ok";
14924
+ const reason = cliString(receipt.reason);
14925
+ lines.push(`- ${name} window_eval: ${ok}${scriptLength === void 0 ? "" : `, script ${scriptLength} chars`}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}, return ${captured}${expected === void 0 ? "" : `, expected ${markdownInlineCode(expected, 80)}`}${returned === void 0 ? "" : `, returned ${markdownInlineCode(returned, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
14926
+ }
14927
+ if (windowEvalDetails.length > 12) lines.push(`- ${windowEvalDetails.length - 12} additional window_eval receipt(s) omitted.`);
14766
14928
  const windowCallUntilDetails = viewports.flatMap((viewport) => {
14767
14929
  const name = cliString(viewport.name) || "viewport";
14768
14930
  const receipts = Array.isArray(viewport.window_call_until) ? viewport.window_call_until.map(cliRecord).filter((item) => Boolean(item)) : [];
package/dist/cli.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  profileStatusExitCode,
13
13
  resolveRiddleProofProfileTargetUrl,
14
14
  resolveRiddleProofProfileTimeoutSec
15
- } from "./chunk-6VXZ6V5M.js";
15
+ } from "./chunk-F46O7DP2.js";
16
16
  import {
17
17
  createRiddleApiClient,
18
18
  parseRiddleViewport
@@ -601,6 +601,9 @@ function profileSetupSummaryMarkdown(result) {
601
601
  const windowCallTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_total) || 0), 0);
602
602
  const windowCallStoredTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_stored_total) || 0), 0);
603
603
  const windowCallCapturedTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_captured_total) || 0), 0);
604
+ const windowEvalTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_eval_total) || 0), 0);
605
+ const windowEvalStoredTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_eval_stored_total) || 0), 0);
606
+ const windowEvalCapturedTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_eval_captured_total) || 0), 0);
604
607
  const windowCallUntilTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_until_total) || 0), 0);
605
608
  const windowCallUntilCallTotal = viewports.reduce((sum, viewport) => sum + (cliFiniteNumber(viewport.window_call_until_call_total) || 0), 0);
606
609
  const failedTotal = viewports.reduce((sum, viewport) => sum + (Array.isArray(viewport.failed) ? viewport.failed.length : 0), 0);
@@ -616,6 +619,9 @@ function profileSetupSummaryMarkdown(result) {
616
619
  if (windowCallTotal) {
617
620
  lines.push(`- window_call: ${windowCallTotal} action(s), stored returns ${windowCallStoredTotal}, captured returns ${windowCallCapturedTotal}`);
618
621
  }
622
+ if (windowEvalTotal) {
623
+ lines.push(`- window_eval: ${windowEvalTotal} action(s), stored returns ${windowEvalStoredTotal}, captured returns ${windowEvalCapturedTotal}`);
624
+ }
619
625
  if (windowCallUntilTotal) {
620
626
  lines.push(`- window_call_until: ${windowCallUntilTotal} action(s), call_count total ${windowCallUntilCallTotal}`);
621
627
  }
@@ -629,10 +635,13 @@ function profileSetupSummaryMarkdown(result) {
629
635
  const windowCallActions = cliFiniteNumber(viewport.window_call_total) || 0;
630
636
  const windowCallStored = cliFiniteNumber(viewport.window_call_stored_total) || 0;
631
637
  const windowCallCaptured = cliFiniteNumber(viewport.window_call_captured_total) || 0;
638
+ const windowEvalActions = cliFiniteNumber(viewport.window_eval_total) || 0;
639
+ const windowEvalStored = cliFiniteNumber(viewport.window_eval_stored_total) || 0;
640
+ const windowEvalCaptured = cliFiniteNumber(viewport.window_eval_captured_total) || 0;
632
641
  const windowCallUntilActions = cliFiniteNumber(viewport.window_call_until_total) || 0;
633
642
  const windowCallUntilCalls = cliFiniteNumber(viewport.window_call_until_call_total) || 0;
634
643
  const observedPath = cliString(viewport.observed_path);
635
- lines.push(`- ${name}: ${ok}, ${resultCount} result(s), ${screenshotCount} setup screenshot(s), ${clicked} click(s)${clickCountActions ? `, ${clickCountActions} click_count action(s)` : ""}${windowCallActions ? `, ${windowCallActions} window_call action(s), ${windowCallStored} stored return(s), ${windowCallCaptured} captured return(s)` : ""}${windowCallUntilActions ? `, ${windowCallUntilActions} window_call_until action(s), ${windowCallUntilCalls} call(s)` : ""}${observedPath ? `, path ${observedPath}` : ""}`);
644
+ lines.push(`- ${name}: ${ok}, ${resultCount} result(s), ${screenshotCount} setup screenshot(s), ${clicked} click(s)${clickCountActions ? `, ${clickCountActions} click_count 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}` : ""}`);
636
645
  }
637
646
  const windowCallDetails = viewports.flatMap((viewport) => {
638
647
  const name = cliString(viewport.name) || "viewport";
@@ -650,6 +659,22 @@ function profileSetupSummaryMarkdown(result) {
650
659
  lines.push(`- ${name} window_call: ${ok}, ${markdownInlineCode(path2)}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}, return ${captured}${expected === void 0 ? "" : `, expected ${markdownInlineCode(expected, 80)}`}${returned === void 0 ? "" : `, returned ${markdownInlineCode(returned, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
651
660
  }
652
661
  if (windowCallDetails.length > 12) lines.push(`- ${windowCallDetails.length - 12} additional window_call receipt(s) omitted.`);
662
+ const windowEvalDetails = viewports.flatMap((viewport) => {
663
+ const name = cliString(viewport.name) || "viewport";
664
+ const receipts = Array.isArray(viewport.window_eval) ? viewport.window_eval.map(cliRecord).filter((item) => Boolean(item)) : [];
665
+ return receipts.map((receipt) => ({ name, receipt }));
666
+ });
667
+ for (const { name, receipt } of windowEvalDetails.slice(0, 12)) {
668
+ const scriptLength = cliFiniteNumber(receipt.script_length);
669
+ const storedTo = cliString(receipt.return_stored_to);
670
+ const returned = cliValueLabel(receipt.returned);
671
+ const expected = cliValueLabel(receipt.expected_return);
672
+ const captured = receipt.return_captured === true ? "captured" : receipt.return_captured === false ? "not captured" : "capture unknown";
673
+ const ok = receipt.ok === false ? "failed" : "ok";
674
+ const reason = cliString(receipt.reason);
675
+ lines.push(`- ${name} window_eval: ${ok}${scriptLength === void 0 ? "" : `, script ${scriptLength} chars`}${storedTo ? `, stored ${markdownInlineCode(storedTo)}` : ""}, return ${captured}${expected === void 0 ? "" : `, expected ${markdownInlineCode(expected, 80)}`}${returned === void 0 ? "" : `, returned ${markdownInlineCode(returned, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
676
+ }
677
+ if (windowEvalDetails.length > 12) lines.push(`- ${windowEvalDetails.length - 12} additional window_eval receipt(s) omitted.`);
653
678
  const windowCallUntilDetails = viewports.flatMap((viewport) => {
654
679
  const name = cliString(viewport.name) || "viewport";
655
680
  const receipts = Array.isArray(viewport.window_call_until) ? viewport.window_call_until.map(cliRecord).filter((item) => Boolean(item)) : [];
package/dist/index.cjs CHANGED
@@ -8794,6 +8794,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
8794
8794
  "wait",
8795
8795
  "wait_for_selector",
8796
8796
  "wait_for_text",
8797
+ "window_eval",
8797
8798
  "window_call",
8798
8799
  "window_call_until"
8799
8800
  ];
@@ -9213,6 +9214,21 @@ function profileSetupWindowCallReceipts(results) {
9213
9214
  return receipt;
9214
9215
  });
9215
9216
  }
9217
+ function profileSetupWindowEvalReceipts(results) {
9218
+ return results.filter((result) => profileSetupResultAction(result) === "window_eval").map((result) => {
9219
+ const receipt = {
9220
+ ordinal: result.ordinal ?? null,
9221
+ ok: result.ok !== false,
9222
+ script_length: result.script_length ?? null,
9223
+ return_captured: result.return_captured ?? null,
9224
+ return_stored_to: result.return_stored_to ?? null,
9225
+ reason: result.reason ?? result.error ?? result.store_reason ?? null
9226
+ };
9227
+ if (result.returned !== void 0) receipt.returned = result.returned;
9228
+ if (result.expected_return !== void 0) receipt.expected_return = result.expected_return;
9229
+ return receipt;
9230
+ });
9231
+ }
9216
9232
  function sampleProfileSetupSummaryItems(items, limit) {
9217
9233
  if (items.length <= limit) return items;
9218
9234
  const firstCount = Math.floor(limit / 2);
@@ -9251,6 +9267,10 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
9251
9267
  const windowCallStoredTotal = windowCallReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
9252
9268
  const windowCallCapturedTotal = windowCallReceipts.filter((result) => result.return_captured === true).length;
9253
9269
  const sampledWindowCallReceipts = sampleProfileSetupSummaryItems(windowCallReceipts, 8);
9270
+ const windowEvalReceipts = profileSetupWindowEvalReceipts(results);
9271
+ const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
9272
+ const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
9273
+ const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
9254
9274
  const clickedItems = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => {
9255
9275
  const clickCount = typeof result.click_count === "number" && Number.isFinite(result.click_count) && result.click_count > 1 ? result.click_count : void 0;
9256
9276
  return {
@@ -9294,6 +9314,11 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
9294
9314
  window_call_captured_total: windowCallCapturedTotal,
9295
9315
  window_call_truncated: windowCallReceipts.length > sampledWindowCallReceipts.length,
9296
9316
  window_call: sampledWindowCallReceipts,
9317
+ window_eval_total: windowEvalReceipts.length,
9318
+ window_eval_stored_total: windowEvalStoredTotal,
9319
+ window_eval_captured_total: windowEvalCapturedTotal,
9320
+ window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
9321
+ window_eval: sampledWindowEvalReceipts,
9297
9322
  clicked,
9298
9323
  text_samples,
9299
9324
  failed: failed.map((result) => ({
@@ -9346,7 +9371,7 @@ function isSupportedCheckType(value) {
9346
9371
  }
9347
9372
  function normalizeSetupActionType(value, index) {
9348
9373
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
9349
- 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 === "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;
9374
+ 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 === "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;
9350
9375
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
9351
9376
  return normalized;
9352
9377
  }
@@ -9364,7 +9389,7 @@ function normalizeSetupActionArgs(input, index) {
9364
9389
  const argsInput = valueFromOwn(input, "args", "arguments", "args_json", "argsJson");
9365
9390
  if (argsInput === void 0) return void 0;
9366
9391
  if (!Array.isArray(argsInput)) {
9367
- throw new Error(`target.setup_actions[${index}] window_call args must be an array.`);
9392
+ throw new Error(`target.setup_actions[${index}] window_call/window_eval args must be an array.`);
9368
9393
  }
9369
9394
  return argsInput.map(toJsonValue);
9370
9395
  }
@@ -9508,7 +9533,11 @@ function normalizeSetupAction(input, index) {
9508
9533
  if ((type === "window_call" || type === "window_call_until" || type === "assert_window_value" || type === "assert_window_number") && !path6) {
9509
9534
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
9510
9535
  }
9511
- const args = type === "window_call" || type === "window_call_until" ? normalizeSetupActionArgs(input, index) : void 0;
9536
+ const script = stringFromOwn(input, "script", "code", "source", "body");
9537
+ if (type === "window_eval" && !script) {
9538
+ throw new Error(`target.setup_actions[${index}] window_eval requires script.`);
9539
+ }
9540
+ const args = type === "window_call" || type === "window_call_until" || type === "window_eval" ? normalizeSetupActionArgs(input, index) : void 0;
9512
9541
  const hasExpectedValue = hasOwn(input, "expected_value") || hasOwn(input, "expectedValue") || hasOwn(input, "expected") || hasOwn(input, "expect_value") || hasOwn(input, "expectValue") || hasOwn(input, "expect");
9513
9542
  if (type === "assert_window_value" && !hasExpectedValue) {
9514
9543
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
@@ -9579,6 +9608,7 @@ function normalizeSetupAction(input, index) {
9579
9608
  value,
9580
9609
  value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
9581
9610
  label: stringFromOwn(input, "label", "name", "screenshot_label", "screenshotLabel"),
9611
+ script,
9582
9612
  path: path6,
9583
9613
  args,
9584
9614
  expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
@@ -12530,6 +12560,23 @@ function profileSetupWindowCallReceipts(results) {
12530
12560
  return receipt;
12531
12561
  });
12532
12562
  }
12563
+ function profileSetupWindowEvalReceipts(results) {
12564
+ return (results || [])
12565
+ .filter((result) => result && profileSetupResultAction(result) === "window_eval")
12566
+ .map((result) => {
12567
+ const receipt = {
12568
+ ordinal: result.ordinal ?? null,
12569
+ ok: result.ok !== false,
12570
+ script_length: result.script_length ?? null,
12571
+ return_captured: result.return_captured ?? null,
12572
+ return_stored_to: result.return_stored_to ?? null,
12573
+ reason: result.reason || result.error || result.store_reason || null,
12574
+ };
12575
+ if (result.returned !== undefined) receipt.returned = result.returned;
12576
+ if (result.expected_return !== undefined) receipt.expected_return = result.expected_return;
12577
+ return receipt;
12578
+ });
12579
+ }
12533
12580
  function sampleProfileSetupSummaryItems(items, limit) {
12534
12581
  if ((items || []).length <= limit) return items || [];
12535
12582
  const firstCount = Math.floor(limit / 2);
@@ -12582,6 +12629,10 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
12582
12629
  const windowCallStoredTotal = windowCallReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
12583
12630
  const windowCallCapturedTotal = windowCallReceipts.filter((result) => result.return_captured === true).length;
12584
12631
  const sampledWindowCallReceipts = sampleProfileSetupSummaryItems(windowCallReceipts, 8);
12632
+ const windowEvalReceipts = profileSetupWindowEvalReceipts(results);
12633
+ const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
12634
+ const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
12635
+ const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
12585
12636
  const clickedItems = results
12586
12637
  .filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
12587
12638
  .map((result) => {
@@ -12635,6 +12686,11 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
12635
12686
  window_call_captured_total: windowCallCapturedTotal,
12636
12687
  window_call_truncated: windowCallReceipts.length > sampledWindowCallReceipts.length,
12637
12688
  window_call: sampledWindowCallReceipts,
12689
+ window_eval_total: windowEvalReceipts.length,
12690
+ window_eval_stored_total: windowEvalStoredTotal,
12691
+ window_eval_captured_total: windowEvalCapturedTotal,
12692
+ window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
12693
+ window_eval: sampledWindowEvalReceipts,
12638
12694
  clicked,
12639
12695
  text_samples: textSamples,
12640
12696
  failed: failed.map((result) => ({
@@ -13615,6 +13671,49 @@ async function setupCallWindowFunction(context, path, args, storeReturnTo, captu
13615
13671
  }
13616
13672
  }, { path, args, storeReturnTo, captureReturn });
13617
13673
  }
13674
+ async function setupEvaluateWindowScript(context, script, args, storeReturnTo, captureReturn) {
13675
+ return await context.evaluate(async ({ script, args, storeReturnTo, captureReturn }) => {
13676
+ const toJsonValue = (value) => {
13677
+ if (value === null || value === undefined) return null;
13678
+ if (typeof value === "string" || typeof value === "boolean") return value;
13679
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
13680
+ if (Array.isArray(value)) return value.map(toJsonValue);
13681
+ if (typeof value === "object") {
13682
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
13683
+ }
13684
+ return String(value);
13685
+ };
13686
+ const storeWindowReturn = (storePath, value) => {
13687
+ const pathParts = String(storePath || "").split(".").map((part) => part.trim()).filter(Boolean);
13688
+ if (pathParts[0] === "window") pathParts.shift();
13689
+ if (!pathParts.length) return { ok: false, reason: "missing_store_path" };
13690
+ let target = window;
13691
+ for (let index = 0; index < pathParts.length - 1; index += 1) {
13692
+ const part = pathParts[index];
13693
+ if (target[part] === null || typeof target[part] !== "object") target[part] = {};
13694
+ target = target[part];
13695
+ }
13696
+ target[pathParts[pathParts.length - 1]] = value;
13697
+ return { ok: true, path: pathParts.join(".") };
13698
+ };
13699
+ const body = String(script || "");
13700
+ if (!body.trim()) return { ok: false, reason: "missing_script" };
13701
+ try {
13702
+ const run = new Function("args", "\"use strict\"; return (async () => {\\n" + body + "\\n})();");
13703
+ const returned = await run(Array.isArray(args) ? args : []);
13704
+ const jsonReturned = toJsonValue(returned);
13705
+ const returnedForResult = captureReturn === false ? undefined : jsonReturned;
13706
+ if (storeReturnTo) {
13707
+ const stored = storeWindowReturn(storeReturnTo, jsonReturned);
13708
+ if (!stored.ok) return { ok: false, reason: "return_store_failed", store_reason: stored.reason, returned: returnedForResult };
13709
+ return { ok: true, returned: returnedForResult, return_stored_to: stored.path };
13710
+ }
13711
+ return { ok: true, returned: returnedForResult };
13712
+ } catch (error) {
13713
+ return { ok: false, reason: "script_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
13714
+ }
13715
+ }, { script, args, storeReturnTo, captureReturn });
13716
+ }
13618
13717
  function setupFrameSelector(action) {
13619
13718
  return String(action?.frame_selector || action?.frameSelector || action?.iframe_selector || action?.iframeSelector || "").trim();
13620
13719
  }
@@ -14128,6 +14227,44 @@ async function executeSetupAction(action, ordinal, viewport) {
14128
14227
  }
14129
14228
  return { ...base, ...setupScopeEvidence(scope), ok: true, storage, reload: action.reload === true };
14130
14229
  }
14230
+ if (type === "window_eval") {
14231
+ const script = String(action.script || action.code || action.source || action.body || "");
14232
+ const args = Array.isArray(action.args) ? action.args : [];
14233
+ const storeReturnTo = String(action.store_return_to || action.storeReturnTo || action.save_return_to || action.saveReturnTo || action.assign_return_to || action.assignReturnTo || action.return_state_path || action.returnStatePath || "").trim();
14234
+ if (!script.trim()) return { ...base, reason: "missing_script" };
14235
+ const scope = await setupActionScope(action, timeout);
14236
+ if (!scope.ok) return setupScopeFailure(base, scope);
14237
+ const hasExpectation = setupHasOwn(action, "expect_return")
14238
+ || setupHasOwn(action, "expectReturn")
14239
+ || setupHasOwn(action, "expected_return")
14240
+ || setupHasOwn(action, "expectedReturn");
14241
+ const expected = setupHasOwn(action, "expect_return")
14242
+ ? action.expect_return
14243
+ : setupHasOwn(action, "expectReturn")
14244
+ ? action.expectReturn
14245
+ : setupHasOwn(action, "expected_return")
14246
+ ? action.expected_return
14247
+ : action.expectedReturn;
14248
+ const captureReturn = action.capture_return === false || action.captureReturn === false || action.include_return === false || action.includeReturn === false || action.omit_return === true || action.omitReturn === true
14249
+ ? hasExpectation
14250
+ : true;
14251
+ const result = await setupEvaluateWindowScript(scope.context, script, args, storeReturnTo, captureReturn);
14252
+ const expectationMet = !hasExpectation || setupValuesEqual(result.returned, expected);
14253
+ return {
14254
+ ...base,
14255
+ ...setupScopeEvidence(scope),
14256
+ ok: Boolean(result.ok && expectationMet),
14257
+ script_length: script.length,
14258
+ arg_count: args.length,
14259
+ returned: captureReturn ? setupJsonValue(result.returned) : undefined,
14260
+ return_captured: captureReturn,
14261
+ expected_return: hasExpectation ? setupJsonValue(expected) : undefined,
14262
+ return_stored_to: result.return_stored_to || storeReturnTo || undefined,
14263
+ reason: result.ok ? (expectationMet ? undefined : "unexpected_return_value") : result.reason,
14264
+ store_reason: result.store_reason || undefined,
14265
+ error: result.error || undefined,
14266
+ };
14267
+ }
14131
14268
  if (type === "window_call") {
14132
14269
  const path = String(action.path || action.function_path || action.functionPath || "");
14133
14270
  const args = Array.isArray(action.args) ? action.args : [];
package/dist/index.js CHANGED
@@ -62,7 +62,7 @@ import {
62
62
  resolveRiddleProofProfileTimeoutSec,
63
63
  slugifyRiddleProofProfileName,
64
64
  summarizeRiddleProofProfileResult
65
- } from "./chunk-6VXZ6V5M.js";
65
+ } from "./chunk-F46O7DP2.js";
66
66
  import {
67
67
  DEFAULT_RIDDLE_API_BASE_URL,
68
68
  DEFAULT_RIDDLE_API_KEY_FILE,
package/dist/profile.cjs CHANGED
@@ -108,6 +108,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
108
108
  "wait",
109
109
  "wait_for_selector",
110
110
  "wait_for_text",
111
+ "window_eval",
111
112
  "window_call",
112
113
  "window_call_until"
113
114
  ];
@@ -527,6 +528,21 @@ function profileSetupWindowCallReceipts(results) {
527
528
  return receipt;
528
529
  });
529
530
  }
531
+ function profileSetupWindowEvalReceipts(results) {
532
+ return results.filter((result) => profileSetupResultAction(result) === "window_eval").map((result) => {
533
+ const receipt = {
534
+ ordinal: result.ordinal ?? null,
535
+ ok: result.ok !== false,
536
+ script_length: result.script_length ?? null,
537
+ return_captured: result.return_captured ?? null,
538
+ return_stored_to: result.return_stored_to ?? null,
539
+ reason: result.reason ?? result.error ?? result.store_reason ?? null
540
+ };
541
+ if (result.returned !== void 0) receipt.returned = result.returned;
542
+ if (result.expected_return !== void 0) receipt.expected_return = result.expected_return;
543
+ return receipt;
544
+ });
545
+ }
530
546
  function sampleProfileSetupSummaryItems(items, limit) {
531
547
  if (items.length <= limit) return items;
532
548
  const firstCount = Math.floor(limit / 2);
@@ -565,6 +581,10 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
565
581
  const windowCallStoredTotal = windowCallReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
566
582
  const windowCallCapturedTotal = windowCallReceipts.filter((result) => result.return_captured === true).length;
567
583
  const sampledWindowCallReceipts = sampleProfileSetupSummaryItems(windowCallReceipts, 8);
584
+ const windowEvalReceipts = profileSetupWindowEvalReceipts(results);
585
+ const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
586
+ const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
587
+ const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
568
588
  const clickedItems = results.filter((result) => profileSetupResultAction(result) === "click" && result.ok !== false).map((result) => {
569
589
  const clickCount = typeof result.click_count === "number" && Number.isFinite(result.click_count) && result.click_count > 1 ? result.click_count : void 0;
570
590
  return {
@@ -608,6 +628,11 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
608
628
  window_call_captured_total: windowCallCapturedTotal,
609
629
  window_call_truncated: windowCallReceipts.length > sampledWindowCallReceipts.length,
610
630
  window_call: sampledWindowCallReceipts,
631
+ window_eval_total: windowEvalReceipts.length,
632
+ window_eval_stored_total: windowEvalStoredTotal,
633
+ window_eval_captured_total: windowEvalCapturedTotal,
634
+ window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
635
+ window_eval: sampledWindowEvalReceipts,
611
636
  clicked,
612
637
  text_samples,
613
638
  failed: failed.map((result) => ({
@@ -660,7 +685,7 @@ function isSupportedCheckType(value) {
660
685
  }
661
686
  function normalizeSetupActionType(value, index) {
662
687
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
663
- 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 === "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;
688
+ 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 === "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;
664
689
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
665
690
  return normalized;
666
691
  }
@@ -678,7 +703,7 @@ function normalizeSetupActionArgs(input, index) {
678
703
  const argsInput = valueFromOwn(input, "args", "arguments", "args_json", "argsJson");
679
704
  if (argsInput === void 0) return void 0;
680
705
  if (!Array.isArray(argsInput)) {
681
- throw new Error(`target.setup_actions[${index}] window_call args must be an array.`);
706
+ throw new Error(`target.setup_actions[${index}] window_call/window_eval args must be an array.`);
682
707
  }
683
708
  return argsInput.map(toJsonValue);
684
709
  }
@@ -822,7 +847,11 @@ function normalizeSetupAction(input, index) {
822
847
  if ((type === "window_call" || type === "window_call_until" || type === "assert_window_value" || type === "assert_window_number") && !path) {
823
848
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
824
849
  }
825
- const args = type === "window_call" || type === "window_call_until" ? normalizeSetupActionArgs(input, index) : void 0;
850
+ const script = stringFromOwn(input, "script", "code", "source", "body");
851
+ if (type === "window_eval" && !script) {
852
+ throw new Error(`target.setup_actions[${index}] window_eval requires script.`);
853
+ }
854
+ const args = type === "window_call" || type === "window_call_until" || type === "window_eval" ? normalizeSetupActionArgs(input, index) : void 0;
826
855
  const hasExpectedValue = hasOwn(input, "expected_value") || hasOwn(input, "expectedValue") || hasOwn(input, "expected") || hasOwn(input, "expect_value") || hasOwn(input, "expectValue") || hasOwn(input, "expect");
827
856
  if (type === "assert_window_value" && !hasExpectedValue) {
828
857
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
@@ -893,6 +922,7 @@ function normalizeSetupAction(input, index) {
893
922
  value,
894
923
  value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
895
924
  label: stringFromOwn(input, "label", "name", "screenshot_label", "screenshotLabel"),
925
+ script,
896
926
  path,
897
927
  args,
898
928
  expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
@@ -3844,6 +3874,23 @@ function profileSetupWindowCallReceipts(results) {
3844
3874
  return receipt;
3845
3875
  });
3846
3876
  }
3877
+ function profileSetupWindowEvalReceipts(results) {
3878
+ return (results || [])
3879
+ .filter((result) => result && profileSetupResultAction(result) === "window_eval")
3880
+ .map((result) => {
3881
+ const receipt = {
3882
+ ordinal: result.ordinal ?? null,
3883
+ ok: result.ok !== false,
3884
+ script_length: result.script_length ?? null,
3885
+ return_captured: result.return_captured ?? null,
3886
+ return_stored_to: result.return_stored_to ?? null,
3887
+ reason: result.reason || result.error || result.store_reason || null,
3888
+ };
3889
+ if (result.returned !== undefined) receipt.returned = result.returned;
3890
+ if (result.expected_return !== undefined) receipt.expected_return = result.expected_return;
3891
+ return receipt;
3892
+ });
3893
+ }
3847
3894
  function sampleProfileSetupSummaryItems(items, limit) {
3848
3895
  if ((items || []).length <= limit) return items || [];
3849
3896
  const firstCount = Math.floor(limit / 2);
@@ -3896,6 +3943,10 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
3896
3943
  const windowCallStoredTotal = windowCallReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
3897
3944
  const windowCallCapturedTotal = windowCallReceipts.filter((result) => result.return_captured === true).length;
3898
3945
  const sampledWindowCallReceipts = sampleProfileSetupSummaryItems(windowCallReceipts, 8);
3946
+ const windowEvalReceipts = profileSetupWindowEvalReceipts(results);
3947
+ const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
3948
+ const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
3949
+ const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
3899
3950
  const clickedItems = results
3900
3951
  .filter((result) => result && profileSetupResultAction(result) === "click" && result.ok !== false)
3901
3952
  .map((result) => {
@@ -3949,6 +4000,11 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
3949
4000
  window_call_captured_total: windowCallCapturedTotal,
3950
4001
  window_call_truncated: windowCallReceipts.length > sampledWindowCallReceipts.length,
3951
4002
  window_call: sampledWindowCallReceipts,
4003
+ window_eval_total: windowEvalReceipts.length,
4004
+ window_eval_stored_total: windowEvalStoredTotal,
4005
+ window_eval_captured_total: windowEvalCapturedTotal,
4006
+ window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
4007
+ window_eval: sampledWindowEvalReceipts,
3952
4008
  clicked,
3953
4009
  text_samples: textSamples,
3954
4010
  failed: failed.map((result) => ({
@@ -4929,6 +4985,49 @@ async function setupCallWindowFunction(context, path, args, storeReturnTo, captu
4929
4985
  }
4930
4986
  }, { path, args, storeReturnTo, captureReturn });
4931
4987
  }
4988
+ async function setupEvaluateWindowScript(context, script, args, storeReturnTo, captureReturn) {
4989
+ return await context.evaluate(async ({ script, args, storeReturnTo, captureReturn }) => {
4990
+ const toJsonValue = (value) => {
4991
+ if (value === null || value === undefined) return null;
4992
+ if (typeof value === "string" || typeof value === "boolean") return value;
4993
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
4994
+ if (Array.isArray(value)) return value.map(toJsonValue);
4995
+ if (typeof value === "object") {
4996
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, toJsonValue(child)]));
4997
+ }
4998
+ return String(value);
4999
+ };
5000
+ const storeWindowReturn = (storePath, value) => {
5001
+ const pathParts = String(storePath || "").split(".").map((part) => part.trim()).filter(Boolean);
5002
+ if (pathParts[0] === "window") pathParts.shift();
5003
+ if (!pathParts.length) return { ok: false, reason: "missing_store_path" };
5004
+ let target = window;
5005
+ for (let index = 0; index < pathParts.length - 1; index += 1) {
5006
+ const part = pathParts[index];
5007
+ if (target[part] === null || typeof target[part] !== "object") target[part] = {};
5008
+ target = target[part];
5009
+ }
5010
+ target[pathParts[pathParts.length - 1]] = value;
5011
+ return { ok: true, path: pathParts.join(".") };
5012
+ };
5013
+ const body = String(script || "");
5014
+ if (!body.trim()) return { ok: false, reason: "missing_script" };
5015
+ try {
5016
+ const run = new Function("args", "\"use strict\"; return (async () => {\\n" + body + "\\n})();");
5017
+ const returned = await run(Array.isArray(args) ? args : []);
5018
+ const jsonReturned = toJsonValue(returned);
5019
+ const returnedForResult = captureReturn === false ? undefined : jsonReturned;
5020
+ if (storeReturnTo) {
5021
+ const stored = storeWindowReturn(storeReturnTo, jsonReturned);
5022
+ if (!stored.ok) return { ok: false, reason: "return_store_failed", store_reason: stored.reason, returned: returnedForResult };
5023
+ return { ok: true, returned: returnedForResult, return_stored_to: stored.path };
5024
+ }
5025
+ return { ok: true, returned: returnedForResult };
5026
+ } catch (error) {
5027
+ return { ok: false, reason: "script_threw", error: String(error && error.message ? error.message : error).slice(0, 1000) };
5028
+ }
5029
+ }, { script, args, storeReturnTo, captureReturn });
5030
+ }
4932
5031
  function setupFrameSelector(action) {
4933
5032
  return String(action?.frame_selector || action?.frameSelector || action?.iframe_selector || action?.iframeSelector || "").trim();
4934
5033
  }
@@ -5442,6 +5541,44 @@ async function executeSetupAction(action, ordinal, viewport) {
5442
5541
  }
5443
5542
  return { ...base, ...setupScopeEvidence(scope), ok: true, storage, reload: action.reload === true };
5444
5543
  }
5544
+ if (type === "window_eval") {
5545
+ const script = String(action.script || action.code || action.source || action.body || "");
5546
+ const args = Array.isArray(action.args) ? action.args : [];
5547
+ const storeReturnTo = String(action.store_return_to || action.storeReturnTo || action.save_return_to || action.saveReturnTo || action.assign_return_to || action.assignReturnTo || action.return_state_path || action.returnStatePath || "").trim();
5548
+ if (!script.trim()) return { ...base, reason: "missing_script" };
5549
+ const scope = await setupActionScope(action, timeout);
5550
+ if (!scope.ok) return setupScopeFailure(base, scope);
5551
+ const hasExpectation = setupHasOwn(action, "expect_return")
5552
+ || setupHasOwn(action, "expectReturn")
5553
+ || setupHasOwn(action, "expected_return")
5554
+ || setupHasOwn(action, "expectedReturn");
5555
+ const expected = setupHasOwn(action, "expect_return")
5556
+ ? action.expect_return
5557
+ : setupHasOwn(action, "expectReturn")
5558
+ ? action.expectReturn
5559
+ : setupHasOwn(action, "expected_return")
5560
+ ? action.expected_return
5561
+ : action.expectedReturn;
5562
+ const captureReturn = action.capture_return === false || action.captureReturn === false || action.include_return === false || action.includeReturn === false || action.omit_return === true || action.omitReturn === true
5563
+ ? hasExpectation
5564
+ : true;
5565
+ const result = await setupEvaluateWindowScript(scope.context, script, args, storeReturnTo, captureReturn);
5566
+ const expectationMet = !hasExpectation || setupValuesEqual(result.returned, expected);
5567
+ return {
5568
+ ...base,
5569
+ ...setupScopeEvidence(scope),
5570
+ ok: Boolean(result.ok && expectationMet),
5571
+ script_length: script.length,
5572
+ arg_count: args.length,
5573
+ returned: captureReturn ? setupJsonValue(result.returned) : undefined,
5574
+ return_captured: captureReturn,
5575
+ expected_return: hasExpectation ? setupJsonValue(expected) : undefined,
5576
+ return_stored_to: result.return_stored_to || storeReturnTo || undefined,
5577
+ reason: result.ok ? (expectationMet ? undefined : "unexpected_return_value") : result.reason,
5578
+ store_reason: result.store_reason || undefined,
5579
+ error: result.error || undefined,
5580
+ };
5581
+ }
5445
5582
  if (type === "window_call") {
5446
5583
  const path = String(action.path || action.function_path || action.functionPath || "");
5447
5584
  const args = Array.isArray(action.args) ? action.args : [];
@@ -5,7 +5,7 @@ declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evide
5
5
  declare const RIDDLE_PROOF_PROFILE_RESULT_VERSION: "riddle-proof.profile-result.v1";
6
6
  declare const RIDDLE_PROOF_PROFILE_STATUSES: readonly ["passed", "product_regression", "proof_insufficient", "environment_blocked", "configuration_error", "needs_human_review"];
7
7
  declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "url_search_param_equals", "url_search_param_absent", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "dialog_count_equals", "dialog_accept_count_equals", "dialog_dismiss_count_equals", "selector_text_visible", "selector_text_absent", "selector_text_order", "frame_text_visible", "frame_url_equals", "frame_url_matches", "frame_no_horizontal_overflow", "text_visible", "text_absent", "http_status", "link_status", "artifact_link_status", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors", "no_console_warnings"];
8
- declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "drag", "press", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "assert_window_number", "local_storage", "session_storage", "clear_storage", "clear_console", "dialog_response", "screenshot", "wait", "wait_for_selector", "wait_for_text", "window_call", "window_call_until"];
8
+ declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "drag", "press", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "assert_window_number", "local_storage", "session_storage", "clear_storage", "clear_console", "dialog_response", "screenshot", "wait", "wait_for_selector", "wait_for_text", "window_eval", "window_call", "window_call_until"];
9
9
  type RiddleProofProfileStatus = typeof RIDDLE_PROOF_PROFILE_STATUSES[number];
10
10
  type RiddleProofProfileCheckType = typeof RIDDLE_PROOF_PROFILE_CHECK_TYPES[number];
11
11
  type RiddleProofProfileSetupActionType = typeof RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES[number];
@@ -127,6 +127,7 @@ interface RiddleProofProfileSetupAction {
127
127
  value?: string;
128
128
  value_json?: JsonValue;
129
129
  label?: string;
130
+ script?: string;
130
131
  path?: string;
131
132
  args?: JsonValue[];
132
133
  expect_return?: JsonValue;
package/dist/profile.d.ts CHANGED
@@ -5,7 +5,7 @@ declare const RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION: "riddle-proof.profile-evide
5
5
  declare const RIDDLE_PROOF_PROFILE_RESULT_VERSION: "riddle-proof.profile-result.v1";
6
6
  declare const RIDDLE_PROOF_PROFILE_STATUSES: readonly ["passed", "product_regression", "proof_insufficient", "environment_blocked", "configuration_error", "needs_human_review"];
7
7
  declare const RIDDLE_PROOF_PROFILE_CHECK_TYPES: readonly ["route_loaded", "url_search_param_equals", "url_search_param_absent", "selector_visible", "selector_absent", "selector_count_at_least", "selector_count_equals", "selector_count_equal", "selector_count_eq", "dialog_count_equals", "dialog_accept_count_equals", "dialog_dismiss_count_equals", "selector_text_visible", "selector_text_absent", "selector_text_order", "frame_text_visible", "frame_url_equals", "frame_url_matches", "frame_no_horizontal_overflow", "text_visible", "text_absent", "http_status", "link_status", "artifact_link_status", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors", "no_console_warnings"];
8
- declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "drag", "press", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "assert_window_number", "local_storage", "session_storage", "clear_storage", "clear_console", "dialog_response", "screenshot", "wait", "wait_for_selector", "wait_for_text", "window_call", "window_call_until"];
8
+ declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "drag", "press", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "assert_window_number", "local_storage", "session_storage", "clear_storage", "clear_console", "dialog_response", "screenshot", "wait", "wait_for_selector", "wait_for_text", "window_eval", "window_call", "window_call_until"];
9
9
  type RiddleProofProfileStatus = typeof RIDDLE_PROOF_PROFILE_STATUSES[number];
10
10
  type RiddleProofProfileCheckType = typeof RIDDLE_PROOF_PROFILE_CHECK_TYPES[number];
11
11
  type RiddleProofProfileSetupActionType = typeof RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES[number];
@@ -127,6 +127,7 @@ interface RiddleProofProfileSetupAction {
127
127
  value?: string;
128
128
  value_json?: JsonValue;
129
129
  label?: string;
130
+ script?: string;
130
131
  path?: string;
131
132
  args?: JsonValue[];
132
133
  expect_return?: JsonValue;
package/dist/profile.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  resolveRiddleProofProfileTimeoutSec,
24
24
  slugifyRiddleProofProfileName,
25
25
  summarizeRiddleProofProfileResult
26
- } from "./chunk-6VXZ6V5M.js";
26
+ } from "./chunk-F46O7DP2.js";
27
27
  export {
28
28
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
29
29
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.7.140",
3
+ "version": "0.7.141",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",