@riddledc/riddle-proof 0.7.181 → 0.7.182

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
@@ -402,7 +402,7 @@ when body matching overrides sequence order.
402
402
  `target.setup_actions` is optional. Use it when the meaningful proof surface
403
403
  appears only after a picker, tab, login stub, storage seed, form fill,
404
404
  transport control, or other bounded interaction. Supported setup actions are
405
- `click`, `tap`, `drag`, `press`, `fill`, `set_input_value`, `set_range_value`,
405
+ `click`, `tap`, `drag`, `press`, `key_down`, `key_up`, `fill`, `set_input_value`, `set_range_value`,
406
406
  `deterministic_runtime`, `canvas_signature`, `assert_text_visible`, `assert_text_absent`,
407
407
  `assert_selector_count`, `assert_window_value`, `assert_window_number`,
408
408
  `local_storage`, `session_storage`, `clear_storage`, `clear_console`,
@@ -418,7 +418,10 @@ with a Playwright key name, such as `Enter`, `Space`, or `ArrowLeft`,
418
418
  when a route's intended browser control is keyboard-driven; omit `selector` for
419
419
  a page-level key press, or provide `selector` to press against a focused element.
420
420
  For canvas games that read key state rather than keypress events, add `hold_ms`
421
- or `holdMs` to keep the key down before releasing it.
421
+ or `holdMs` to keep the key down before releasing it. When the profile needs
422
+ to observe or wait on runtime evidence while a key remains held, use paired
423
+ `key_down` / `key_up` actions around `wait`, `window_eval`, or
424
+ `window_call_until` actions.
422
425
  Use `click_count` / `clickCount` / `clicks` from 1 to 10 on a single `click`
423
426
  action for atomic double-click or double-submit contracts where modeling the
424
427
  interaction as repeated setup actions would incorrectly require the target to
@@ -47,6 +47,8 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
47
47
  "tap",
48
48
  "drag",
49
49
  "press",
50
+ "key_down",
51
+ "key_up",
50
52
  "fill",
51
53
  "set_input_value",
52
54
  "set_range_value",
@@ -612,7 +614,8 @@ function profileSetupTapReceipts(results) {
612
614
  }));
613
615
  }
614
616
  function profileSetupPressReceipts(results) {
615
- return results.filter((result) => profileSetupResultAction(result) === "press").map((result) => ({
617
+ return results.filter((result) => ["press", "key_down", "key_up"].includes(profileSetupResultAction(result))).map((result) => ({
618
+ action: profileSetupResultAction(result),
616
619
  ordinal: result.ordinal ?? null,
617
620
  ok: result.ok !== false,
618
621
  selector: result.selector ?? null,
@@ -913,7 +916,7 @@ function isSupportedCheckType(value) {
913
916
  }
914
917
  function normalizeSetupActionType(value, index) {
915
918
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
916
- 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 === "pointer_tap" || normalizedInput === "touch_tap" || normalizedInput === "canvas_tap" ? "tap" : 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;
919
+ 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 === "pointer_tap" || normalizedInput === "touch_tap" || normalizedInput === "canvas_tap" ? "tap" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "keyboard_down" || normalizedInput === "key_down" || normalizedInput === "keydown" || normalizedInput === "press_down" ? "key_down" : normalizedInput === "keyboard_up" || normalizedInput === "key_up" || normalizedInput === "keyup" || normalizedInput === "press_up" || normalizedInput === "release_key" || normalizedInput === "key_release" ? "key_up" : 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;
917
920
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
918
921
  return normalized;
919
922
  }
@@ -1169,7 +1172,7 @@ function normalizeSetupAction(input, index) {
1169
1172
  dialogAccept = true;
1170
1173
  }
1171
1174
  }
1172
- if (type === "press" && !key) {
1175
+ if ((type === "press" || type === "key_down" || type === "key_up") && !key) {
1173
1176
  throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
1174
1177
  }
1175
1178
  if ((type === "local_storage" || type === "session_storage") && !key) {
@@ -4496,8 +4499,9 @@ function profileSetupTapReceipts(results) {
4496
4499
  }
4497
4500
  function profileSetupPressReceipts(results) {
4498
4501
  return (results || [])
4499
- .filter((result) => result && profileSetupResultAction(result) === "press")
4502
+ .filter((result) => result && ["press", "key_down", "key_up"].includes(profileSetupResultAction(result)))
4500
4503
  .map((result) => ({
4504
+ action: profileSetupResultAction(result),
4501
4505
  ordinal: result.ordinal ?? null,
4502
4506
  ok: result.ok !== false,
4503
4507
  selector: result.selector ?? null,
@@ -6437,6 +6441,37 @@ async function executeSetupAction(action, ordinal, viewport) {
6437
6441
  duration_ms: durationMs || undefined,
6438
6442
  };
6439
6443
  }
6444
+ if (type === "key_down" || type === "key_up") {
6445
+ const key = String(action.key || "").trim();
6446
+ if (!key) return { ...base, reason: "missing_key" };
6447
+ const scope = await setupActionScope(action, timeout);
6448
+ if (!scope.ok) return setupScopeFailure(base, scope);
6449
+ let count;
6450
+ let targetIndex;
6451
+ if (action.selector) {
6452
+ const locator = scope.context.locator(action.selector);
6453
+ count = await locator.count();
6454
+ if (!count) return { ...base, reason: "selector_not_found", count, key };
6455
+ targetIndex = Number.isInteger(action.index) ? action.index : 0;
6456
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex, key };
6457
+ await locator.nth(targetIndex).focus({ timeout }).catch(() => {});
6458
+ } else if (scope.frame_selector) {
6459
+ await scope.context.locator("body").focus({ timeout }).catch(() => {});
6460
+ }
6461
+ if (type === "key_down") {
6462
+ await page.keyboard.down(key);
6463
+ } else {
6464
+ await page.keyboard.up(key);
6465
+ }
6466
+ return {
6467
+ ...base,
6468
+ ...setupScopeEvidence(scope),
6469
+ ok: true,
6470
+ count,
6471
+ target_index: targetIndex,
6472
+ key,
6473
+ };
6474
+ }
6440
6475
  if (type === "press") {
6441
6476
  const key = String(action.key || "").trim();
6442
6477
  if (!key) return { ...base, reason: "missing_key" };
package/dist/cli.cjs CHANGED
@@ -7004,6 +7004,8 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
7004
7004
  "tap",
7005
7005
  "drag",
7006
7006
  "press",
7007
+ "key_down",
7008
+ "key_up",
7007
7009
  "fill",
7008
7010
  "set_input_value",
7009
7011
  "set_range_value",
@@ -7569,7 +7571,8 @@ function profileSetupTapReceipts(results) {
7569
7571
  }));
7570
7572
  }
7571
7573
  function profileSetupPressReceipts(results) {
7572
- return results.filter((result) => profileSetupResultAction(result) === "press").map((result) => ({
7574
+ return results.filter((result) => ["press", "key_down", "key_up"].includes(profileSetupResultAction(result))).map((result) => ({
7575
+ action: profileSetupResultAction(result),
7573
7576
  ordinal: result.ordinal ?? null,
7574
7577
  ok: result.ok !== false,
7575
7578
  selector: result.selector ?? null,
@@ -7870,7 +7873,7 @@ function isSupportedCheckType(value) {
7870
7873
  }
7871
7874
  function normalizeSetupActionType(value, index) {
7872
7875
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
7873
- 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 === "pointer_tap" || normalizedInput === "touch_tap" || normalizedInput === "canvas_tap" ? "tap" : 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;
7876
+ 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 === "pointer_tap" || normalizedInput === "touch_tap" || normalizedInput === "canvas_tap" ? "tap" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "keyboard_down" || normalizedInput === "key_down" || normalizedInput === "keydown" || normalizedInput === "press_down" ? "key_down" : normalizedInput === "keyboard_up" || normalizedInput === "key_up" || normalizedInput === "keyup" || normalizedInput === "press_up" || normalizedInput === "release_key" || normalizedInput === "key_release" ? "key_up" : 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;
7874
7877
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
7875
7878
  return normalized;
7876
7879
  }
@@ -8126,7 +8129,7 @@ function normalizeSetupAction(input, index) {
8126
8129
  dialogAccept = true;
8127
8130
  }
8128
8131
  }
8129
- if (type === "press" && !key) {
8132
+ if ((type === "press" || type === "key_down" || type === "key_up") && !key) {
8130
8133
  throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
8131
8134
  }
8132
8135
  if ((type === "local_storage" || type === "session_storage") && !key) {
@@ -11437,8 +11440,9 @@ function profileSetupTapReceipts(results) {
11437
11440
  }
11438
11441
  function profileSetupPressReceipts(results) {
11439
11442
  return (results || [])
11440
- .filter((result) => result && profileSetupResultAction(result) === "press")
11443
+ .filter((result) => result && ["press", "key_down", "key_up"].includes(profileSetupResultAction(result)))
11441
11444
  .map((result) => ({
11445
+ action: profileSetupResultAction(result),
11442
11446
  ordinal: result.ordinal ?? null,
11443
11447
  ok: result.ok !== false,
11444
11448
  selector: result.selector ?? null,
@@ -13378,6 +13382,37 @@ async function executeSetupAction(action, ordinal, viewport) {
13378
13382
  duration_ms: durationMs || undefined,
13379
13383
  };
13380
13384
  }
13385
+ if (type === "key_down" || type === "key_up") {
13386
+ const key = String(action.key || "").trim();
13387
+ if (!key) return { ...base, reason: "missing_key" };
13388
+ const scope = await setupActionScope(action, timeout);
13389
+ if (!scope.ok) return setupScopeFailure(base, scope);
13390
+ let count;
13391
+ let targetIndex;
13392
+ if (action.selector) {
13393
+ const locator = scope.context.locator(action.selector);
13394
+ count = await locator.count();
13395
+ if (!count) return { ...base, reason: "selector_not_found", count, key };
13396
+ targetIndex = Number.isInteger(action.index) ? action.index : 0;
13397
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex, key };
13398
+ await locator.nth(targetIndex).focus({ timeout }).catch(() => {});
13399
+ } else if (scope.frame_selector) {
13400
+ await scope.context.locator("body").focus({ timeout }).catch(() => {});
13401
+ }
13402
+ if (type === "key_down") {
13403
+ await page.keyboard.down(key);
13404
+ } else {
13405
+ await page.keyboard.up(key);
13406
+ }
13407
+ return {
13408
+ ...base,
13409
+ ...setupScopeEvidence(scope),
13410
+ ok: true,
13411
+ count,
13412
+ target_index: targetIndex,
13413
+ key,
13414
+ };
13415
+ }
13381
13416
  if (type === "press") {
13382
13417
  const key = String(action.key || "").trim();
13383
13418
  if (!key) return { ...base, reason: "missing_key" };
@@ -16370,7 +16405,18 @@ function profileCheckMarkdownTarget(check) {
16370
16405
  }
16371
16406
  if (check.type === "no_console_warnings") {
16372
16407
  const warningCount = cliFiniteNumber(evidence.console_warning_count) ?? 0;
16373
- return `${warningCount} unallowed warning${warningCount === 1 ? "" : "s"}`;
16408
+ const totalConsoleCount = cliFiniteNumber(evidence.total_console_warning_count);
16409
+ const allowedConsoleCount = cliFiniteNumber(evidence.allowed_console_warning_count);
16410
+ const allowedTextCount = Array.isArray(evidence.allowed_console_texts) ? evidence.allowed_console_texts.filter((value) => typeof value === "string" && value.trim()).length : 0;
16411
+ const allowedPatternCount = Array.isArray(evidence.allowed_console_patterns) ? evidence.allowed_console_patterns.filter((value) => typeof value === "string" && value.trim()).length : 0;
16412
+ const parts = [`${warningCount} unallowed warning${warningCount === 1 ? "" : "s"}`];
16413
+ if (totalConsoleCount !== void 0 && allowedConsoleCount !== void 0) {
16414
+ parts.push(`${allowedConsoleCount}/${totalConsoleCount} warning${totalConsoleCount === 1 ? "" : "s"} allowed`);
16415
+ }
16416
+ if (allowedTextCount || allowedPatternCount) {
16417
+ parts.push(`allowlist ${allowedTextCount} text${allowedTextCount === 1 ? "" : "s"}, ${allowedPatternCount} pattern${allowedPatternCount === 1 ? "" : "s"}`);
16418
+ }
16419
+ return parts.join(", ");
16374
16420
  }
16375
16421
  return void 0;
16376
16422
  }
@@ -16407,6 +16453,100 @@ function cliReturnSummaryLabel(value) {
16407
16453
  }).filter(Boolean);
16408
16454
  return parts.length ? parts.join(", ") : void 0;
16409
16455
  }
16456
+ function setupFailureObstructionSnippet(reason) {
16457
+ if (!reason || !reason.includes("intercepts pointer events")) return void 0;
16458
+ const line = reason.split(/\r?\n/).find((item) => item.includes("intercepts pointer events"));
16459
+ const match = line?.match(/-\s+(.+?)\s+intercepts pointer events/);
16460
+ const snippet = match?.[1]?.replace(/\s+/g, " ").trim();
16461
+ return snippet || void 0;
16462
+ }
16463
+ function setupReceiptArray(viewport, key) {
16464
+ return Array.isArray(viewport[key]) ? viewport[key].map(cliRecord).filter((item) => Boolean(item)) : [];
16465
+ }
16466
+ function setupReturnSummaryValue(receipt, names) {
16467
+ for (const name of names) {
16468
+ if (receipt[name] !== void 0) return receipt[name];
16469
+ }
16470
+ const returned = cliRecord(receipt.returned);
16471
+ for (const name of names) {
16472
+ if (returned?.[name] !== void 0) return returned[name];
16473
+ }
16474
+ const summaries = Array.isArray(receipt.return_summary) ? receipt.return_summary.map(cliRecord).filter((item) => Boolean(item)) : [];
16475
+ for (const item of summaries) {
16476
+ const label = cliString(item.label);
16477
+ const path7 = cliString(item.path);
16478
+ if (names.some((name) => label === name || path7 === name)) return item.value;
16479
+ }
16480
+ return void 0;
16481
+ }
16482
+ function setupMetricPart(receipts, label, names = [label]) {
16483
+ for (const receipt of receipts) {
16484
+ const value = setupReturnSummaryValue(receipt, names);
16485
+ const valueLabel = cliValueLabel(value);
16486
+ if (valueLabel !== void 0) return `${label}=${valueLabel}`;
16487
+ }
16488
+ return void 0;
16489
+ }
16490
+ function setupInputReceiptLabel(kind, receipt) {
16491
+ const selector = cliString(receipt.selector);
16492
+ const pointerType = cliString(receipt.pointer_type);
16493
+ const inputDispatch = cliString(receipt.input_dispatch);
16494
+ const key = cliString(receipt.key);
16495
+ return [
16496
+ kind,
16497
+ selector ? markdownInlineCode(selector) : "",
16498
+ pointerType ? markdownInlineCode(pointerType) : "",
16499
+ key ? markdownInlineCode(key) : "",
16500
+ inputDispatch ? `via ${markdownInlineCode(inputDispatch)}` : ""
16501
+ ].filter(Boolean).join(" ");
16502
+ }
16503
+ function setupCanvasHashChangeLabel(receipts) {
16504
+ const changed = receipts.find((receipt) => cliString(receipt.previous_hash) && cliString(receipt.hash) && receipt.changed === true);
16505
+ if (changed) return `${markdownInlineCode(cliString(changed.previous_hash) || "")} -> ${markdownInlineCode(cliString(changed.hash) || "")}`;
16506
+ const hashes = receipts.map((receipt) => cliString(receipt.hash)).filter((hash) => Boolean(hash));
16507
+ const first = hashes[0];
16508
+ const last = [...hashes].reverse().find((hash) => hash !== first);
16509
+ return first && last ? `${markdownInlineCode(first)} -> ${markdownInlineCode(last)}` : void 0;
16510
+ }
16511
+ function setupNaturalInputSummaryMarkdown(viewports) {
16512
+ const lines = [];
16513
+ for (const viewport of viewports.slice(0, 8)) {
16514
+ const name = cliString(viewport.name) || "viewport";
16515
+ const inputReceipts = [
16516
+ ...setupReceiptArray(viewport, "drag").map((receipt) => ({ kind: "drag", receipt })),
16517
+ ...setupReceiptArray(viewport, "tap").map((receipt) => ({ kind: "tap", receipt })),
16518
+ ...setupReceiptArray(viewport, "press").map((receipt) => ({ kind: "press", receipt }))
16519
+ ].filter(({ receipt }) => receipt.ok !== false);
16520
+ if (!inputReceipts.length) continue;
16521
+ const valueReceipts = [
16522
+ ...setupReceiptArray(viewport, "window_eval"),
16523
+ ...setupReceiptArray(viewport, "window_call")
16524
+ ].filter((receipt) => receipt.ok !== false);
16525
+ const canvasReceipts = setupReceiptArray(viewport, "canvas_signature").filter((receipt) => receipt.ok !== false);
16526
+ const eventParts = [
16527
+ setupMetricPart(valueReceipts, "pointerDowns"),
16528
+ setupMetricPart(valueReceipts, "pointerMoves"),
16529
+ setupMetricPart(valueReceipts, "pointerUps"),
16530
+ setupMetricPart(valueReceipts, "trustedEvents"),
16531
+ setupMetricPart(valueReceipts, "eventCount")
16532
+ ].filter((part) => Boolean(part));
16533
+ const pixelParts = [
16534
+ setupMetricPart(valueReceipts, "nonWhiteDelta"),
16535
+ setupMetricPart(valueReceipts, "darkDelta")
16536
+ ].filter((part) => Boolean(part));
16537
+ const hashChange = setupCanvasHashChangeLabel(canvasReceipts);
16538
+ if (!eventParts.length && !pixelParts.length && !hashChange) continue;
16539
+ const inputText = inputReceipts.slice(0, 3).map(({ kind, receipt }) => setupInputReceiptLabel(kind, receipt)).join(", ");
16540
+ const parts = [
16541
+ inputText,
16542
+ eventParts.length ? `events ${eventParts.join(", ")}` : "",
16543
+ pixelParts.length ? `pixel deltas ${pixelParts.join(", ")}` : "",
16544
+ hashChange ? `canvas hash ${hashChange}` : ""
16545
+ ].filter(Boolean);
16546
+ lines.push(`- natural input ${name}: ${parts.join("; ")}`);
16547
+ }
16548
+ return lines;
16549
+ }
16410
16550
  function balancedSetupReceiptDetails(groups, limit) {
16411
16551
  if (limit <= 0) return [];
16412
16552
  const total = groups.reduce((sum, group) => sum + group.length, 0);
@@ -16596,6 +16736,7 @@ function profileSetupSummaryMarkdown(result) {
16596
16736
  if (canvasSignatureTotal) {
16597
16737
  lines.push(`- canvas_signature: ${canvasSignatureTotal} action(s)`);
16598
16738
  }
16739
+ lines.push(...setupNaturalInputSummaryMarkdown(viewports));
16599
16740
  for (const viewport of viewports.slice(0, 8)) {
16600
16741
  const name = cliString(viewport.name) || "viewport";
16601
16742
  const ok = viewport.ok === false ? "failed" : "ok";
@@ -16707,13 +16848,14 @@ function profileSetupSummaryMarkdown(result) {
16707
16848
  }
16708
16849
  const sampledPressDetails = balancedSetupReceiptDetails(pressGroups, 12);
16709
16850
  for (const { name, receipt } of sampledPressDetails) {
16851
+ const action = cliString(receipt.action) || "press";
16710
16852
  const key = cliString(receipt.key) || "key";
16711
16853
  const selector = cliString(receipt.selector);
16712
16854
  const frameSelector = cliString(receipt.frame_selector);
16713
16855
  const holdMs = cliFiniteNumber(receipt.hold_ms);
16714
16856
  const ok = receipt.ok === false ? "failed" : "ok";
16715
16857
  const reason = cliString(receipt.reason);
16716
- lines.push(`- ${name} press: ${ok}, ${markdownInlineCode(key)}${selector ? ` on ${markdownInlineCode(selector)}` : ""}${frameSelector ? ` in frame ${markdownInlineCode(frameSelector)}` : ""}${holdMs === void 0 ? "" : `, held ${holdMs}ms`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
16858
+ lines.push(`- ${name} ${action}: ${ok}, ${markdownInlineCode(key)}${selector ? ` on ${markdownInlineCode(selector)}` : ""}${frameSelector ? ` in frame ${markdownInlineCode(frameSelector)}` : ""}${holdMs === void 0 ? "" : `, held ${holdMs}ms`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
16717
16859
  }
16718
16860
  if (pressDetails.length > sampledPressDetails.length) lines.push(`- ${pressDetails.length - sampledPressDetails.length} additional press receipt(s) omitted.`);
16719
16861
  const canvasSignatureGroups = viewports.map((viewport) => {
@@ -16876,7 +17018,11 @@ function profileSetupSummaryMarkdown(result) {
16876
17018
  const selector = cliString(failure.selector);
16877
17019
  const reason = cliString(failure.reason);
16878
17020
  const caseInsensitiveText = cliString(failure.case_insensitive_text);
17021
+ const obstruction = setupFailureObstructionSnippet(reason);
16879
17022
  lines.push(`- failed ${name}: ${action}${selector ? ` ${markdownInlineCode(selector)}` : ""}${reason ? ` reason ${markdownInlineCode(reason)}` : ""}${caseInsensitiveText ? `; case-insensitive sample ${markdownInlineCode(caseInsensitiveText, 140)}` : ""}`);
17023
+ if (obstruction) {
17024
+ lines.push(`- obstruction ${name}: target ${selector ? markdownInlineCode(selector) : markdownInlineCode(action)} intercepted by ${markdownInlineCode(obstruction, 120)}`);
17025
+ }
16880
17026
  }
16881
17027
  if (failedDetails.length > 8) lines.push(`- ${failedDetails.length - 8} additional failed setup action(s) omitted.`);
16882
17028
  if (viewports.length > 8) lines.push(`- ${viewports.length - 8} additional viewport(s) omitted from setup summary.`);
package/dist/cli.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  profileStatusExitCode,
14
14
  resolveRiddleProofProfileTargetUrl,
15
15
  resolveRiddleProofProfileTimeoutSec
16
- } from "./chunk-T664I6R3.js";
16
+ } from "./chunk-XL7Q4M6D.js";
17
17
  import {
18
18
  createRiddleApiClient,
19
19
  isTerminalRiddleJobStatus,
@@ -622,7 +622,18 @@ function profileCheckMarkdownTarget(check) {
622
622
  }
623
623
  if (check.type === "no_console_warnings") {
624
624
  const warningCount = cliFiniteNumber(evidence.console_warning_count) ?? 0;
625
- return `${warningCount} unallowed warning${warningCount === 1 ? "" : "s"}`;
625
+ const totalConsoleCount = cliFiniteNumber(evidence.total_console_warning_count);
626
+ const allowedConsoleCount = cliFiniteNumber(evidence.allowed_console_warning_count);
627
+ const allowedTextCount = Array.isArray(evidence.allowed_console_texts) ? evidence.allowed_console_texts.filter((value) => typeof value === "string" && value.trim()).length : 0;
628
+ const allowedPatternCount = Array.isArray(evidence.allowed_console_patterns) ? evidence.allowed_console_patterns.filter((value) => typeof value === "string" && value.trim()).length : 0;
629
+ const parts = [`${warningCount} unallowed warning${warningCount === 1 ? "" : "s"}`];
630
+ if (totalConsoleCount !== void 0 && allowedConsoleCount !== void 0) {
631
+ parts.push(`${allowedConsoleCount}/${totalConsoleCount} warning${totalConsoleCount === 1 ? "" : "s"} allowed`);
632
+ }
633
+ if (allowedTextCount || allowedPatternCount) {
634
+ parts.push(`allowlist ${allowedTextCount} text${allowedTextCount === 1 ? "" : "s"}, ${allowedPatternCount} pattern${allowedPatternCount === 1 ? "" : "s"}`);
635
+ }
636
+ return parts.join(", ");
626
637
  }
627
638
  return void 0;
628
639
  }
@@ -659,6 +670,100 @@ function cliReturnSummaryLabel(value) {
659
670
  }).filter(Boolean);
660
671
  return parts.length ? parts.join(", ") : void 0;
661
672
  }
673
+ function setupFailureObstructionSnippet(reason) {
674
+ if (!reason || !reason.includes("intercepts pointer events")) return void 0;
675
+ const line = reason.split(/\r?\n/).find((item) => item.includes("intercepts pointer events"));
676
+ const match = line?.match(/-\s+(.+?)\s+intercepts pointer events/);
677
+ const snippet = match?.[1]?.replace(/\s+/g, " ").trim();
678
+ return snippet || void 0;
679
+ }
680
+ function setupReceiptArray(viewport, key) {
681
+ return Array.isArray(viewport[key]) ? viewport[key].map(cliRecord).filter((item) => Boolean(item)) : [];
682
+ }
683
+ function setupReturnSummaryValue(receipt, names) {
684
+ for (const name of names) {
685
+ if (receipt[name] !== void 0) return receipt[name];
686
+ }
687
+ const returned = cliRecord(receipt.returned);
688
+ for (const name of names) {
689
+ if (returned?.[name] !== void 0) return returned[name];
690
+ }
691
+ const summaries = Array.isArray(receipt.return_summary) ? receipt.return_summary.map(cliRecord).filter((item) => Boolean(item)) : [];
692
+ for (const item of summaries) {
693
+ const label = cliString(item.label);
694
+ const path2 = cliString(item.path);
695
+ if (names.some((name) => label === name || path2 === name)) return item.value;
696
+ }
697
+ return void 0;
698
+ }
699
+ function setupMetricPart(receipts, label, names = [label]) {
700
+ for (const receipt of receipts) {
701
+ const value = setupReturnSummaryValue(receipt, names);
702
+ const valueLabel = cliValueLabel(value);
703
+ if (valueLabel !== void 0) return `${label}=${valueLabel}`;
704
+ }
705
+ return void 0;
706
+ }
707
+ function setupInputReceiptLabel(kind, receipt) {
708
+ const selector = cliString(receipt.selector);
709
+ const pointerType = cliString(receipt.pointer_type);
710
+ const inputDispatch = cliString(receipt.input_dispatch);
711
+ const key = cliString(receipt.key);
712
+ return [
713
+ kind,
714
+ selector ? markdownInlineCode(selector) : "",
715
+ pointerType ? markdownInlineCode(pointerType) : "",
716
+ key ? markdownInlineCode(key) : "",
717
+ inputDispatch ? `via ${markdownInlineCode(inputDispatch)}` : ""
718
+ ].filter(Boolean).join(" ");
719
+ }
720
+ function setupCanvasHashChangeLabel(receipts) {
721
+ const changed = receipts.find((receipt) => cliString(receipt.previous_hash) && cliString(receipt.hash) && receipt.changed === true);
722
+ if (changed) return `${markdownInlineCode(cliString(changed.previous_hash) || "")} -> ${markdownInlineCode(cliString(changed.hash) || "")}`;
723
+ const hashes = receipts.map((receipt) => cliString(receipt.hash)).filter((hash) => Boolean(hash));
724
+ const first = hashes[0];
725
+ const last = [...hashes].reverse().find((hash) => hash !== first);
726
+ return first && last ? `${markdownInlineCode(first)} -> ${markdownInlineCode(last)}` : void 0;
727
+ }
728
+ function setupNaturalInputSummaryMarkdown(viewports) {
729
+ const lines = [];
730
+ for (const viewport of viewports.slice(0, 8)) {
731
+ const name = cliString(viewport.name) || "viewport";
732
+ const inputReceipts = [
733
+ ...setupReceiptArray(viewport, "drag").map((receipt) => ({ kind: "drag", receipt })),
734
+ ...setupReceiptArray(viewport, "tap").map((receipt) => ({ kind: "tap", receipt })),
735
+ ...setupReceiptArray(viewport, "press").map((receipt) => ({ kind: "press", receipt }))
736
+ ].filter(({ receipt }) => receipt.ok !== false);
737
+ if (!inputReceipts.length) continue;
738
+ const valueReceipts = [
739
+ ...setupReceiptArray(viewport, "window_eval"),
740
+ ...setupReceiptArray(viewport, "window_call")
741
+ ].filter((receipt) => receipt.ok !== false);
742
+ const canvasReceipts = setupReceiptArray(viewport, "canvas_signature").filter((receipt) => receipt.ok !== false);
743
+ const eventParts = [
744
+ setupMetricPart(valueReceipts, "pointerDowns"),
745
+ setupMetricPart(valueReceipts, "pointerMoves"),
746
+ setupMetricPart(valueReceipts, "pointerUps"),
747
+ setupMetricPart(valueReceipts, "trustedEvents"),
748
+ setupMetricPart(valueReceipts, "eventCount")
749
+ ].filter((part) => Boolean(part));
750
+ const pixelParts = [
751
+ setupMetricPart(valueReceipts, "nonWhiteDelta"),
752
+ setupMetricPart(valueReceipts, "darkDelta")
753
+ ].filter((part) => Boolean(part));
754
+ const hashChange = setupCanvasHashChangeLabel(canvasReceipts);
755
+ if (!eventParts.length && !pixelParts.length && !hashChange) continue;
756
+ const inputText = inputReceipts.slice(0, 3).map(({ kind, receipt }) => setupInputReceiptLabel(kind, receipt)).join(", ");
757
+ const parts = [
758
+ inputText,
759
+ eventParts.length ? `events ${eventParts.join(", ")}` : "",
760
+ pixelParts.length ? `pixel deltas ${pixelParts.join(", ")}` : "",
761
+ hashChange ? `canvas hash ${hashChange}` : ""
762
+ ].filter(Boolean);
763
+ lines.push(`- natural input ${name}: ${parts.join("; ")}`);
764
+ }
765
+ return lines;
766
+ }
662
767
  function balancedSetupReceiptDetails(groups, limit) {
663
768
  if (limit <= 0) return [];
664
769
  const total = groups.reduce((sum, group) => sum + group.length, 0);
@@ -848,6 +953,7 @@ function profileSetupSummaryMarkdown(result) {
848
953
  if (canvasSignatureTotal) {
849
954
  lines.push(`- canvas_signature: ${canvasSignatureTotal} action(s)`);
850
955
  }
956
+ lines.push(...setupNaturalInputSummaryMarkdown(viewports));
851
957
  for (const viewport of viewports.slice(0, 8)) {
852
958
  const name = cliString(viewport.name) || "viewport";
853
959
  const ok = viewport.ok === false ? "failed" : "ok";
@@ -959,13 +1065,14 @@ function profileSetupSummaryMarkdown(result) {
959
1065
  }
960
1066
  const sampledPressDetails = balancedSetupReceiptDetails(pressGroups, 12);
961
1067
  for (const { name, receipt } of sampledPressDetails) {
1068
+ const action = cliString(receipt.action) || "press";
962
1069
  const key = cliString(receipt.key) || "key";
963
1070
  const selector = cliString(receipt.selector);
964
1071
  const frameSelector = cliString(receipt.frame_selector);
965
1072
  const holdMs = cliFiniteNumber(receipt.hold_ms);
966
1073
  const ok = receipt.ok === false ? "failed" : "ok";
967
1074
  const reason = cliString(receipt.reason);
968
- lines.push(`- ${name} press: ${ok}, ${markdownInlineCode(key)}${selector ? ` on ${markdownInlineCode(selector)}` : ""}${frameSelector ? ` in frame ${markdownInlineCode(frameSelector)}` : ""}${holdMs === void 0 ? "" : `, held ${holdMs}ms`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
1075
+ lines.push(`- ${name} ${action}: ${ok}, ${markdownInlineCode(key)}${selector ? ` on ${markdownInlineCode(selector)}` : ""}${frameSelector ? ` in frame ${markdownInlineCode(frameSelector)}` : ""}${holdMs === void 0 ? "" : `, held ${holdMs}ms`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
969
1076
  }
970
1077
  if (pressDetails.length > sampledPressDetails.length) lines.push(`- ${pressDetails.length - sampledPressDetails.length} additional press receipt(s) omitted.`);
971
1078
  const canvasSignatureGroups = viewports.map((viewport) => {
@@ -1128,7 +1235,11 @@ function profileSetupSummaryMarkdown(result) {
1128
1235
  const selector = cliString(failure.selector);
1129
1236
  const reason = cliString(failure.reason);
1130
1237
  const caseInsensitiveText = cliString(failure.case_insensitive_text);
1238
+ const obstruction = setupFailureObstructionSnippet(reason);
1131
1239
  lines.push(`- failed ${name}: ${action}${selector ? ` ${markdownInlineCode(selector)}` : ""}${reason ? ` reason ${markdownInlineCode(reason)}` : ""}${caseInsensitiveText ? `; case-insensitive sample ${markdownInlineCode(caseInsensitiveText, 140)}` : ""}`);
1240
+ if (obstruction) {
1241
+ lines.push(`- obstruction ${name}: target ${selector ? markdownInlineCode(selector) : markdownInlineCode(action)} intercepted by ${markdownInlineCode(obstruction, 120)}`);
1242
+ }
1132
1243
  }
1133
1244
  if (failedDetails.length > 8) lines.push(`- ${failedDetails.length - 8} additional failed setup action(s) omitted.`);
1134
1245
  if (viewports.length > 8) lines.push(`- ${viewports.length - 8} additional viewport(s) omitted from setup summary.`);
package/dist/index.cjs CHANGED
@@ -8780,6 +8780,8 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
8780
8780
  "tap",
8781
8781
  "drag",
8782
8782
  "press",
8783
+ "key_down",
8784
+ "key_up",
8783
8785
  "fill",
8784
8786
  "set_input_value",
8785
8787
  "set_range_value",
@@ -9345,7 +9347,8 @@ function profileSetupTapReceipts(results) {
9345
9347
  }));
9346
9348
  }
9347
9349
  function profileSetupPressReceipts(results) {
9348
- return results.filter((result) => profileSetupResultAction(result) === "press").map((result) => ({
9350
+ return results.filter((result) => ["press", "key_down", "key_up"].includes(profileSetupResultAction(result))).map((result) => ({
9351
+ action: profileSetupResultAction(result),
9349
9352
  ordinal: result.ordinal ?? null,
9350
9353
  ok: result.ok !== false,
9351
9354
  selector: result.selector ?? null,
@@ -9646,7 +9649,7 @@ function isSupportedCheckType(value) {
9646
9649
  }
9647
9650
  function normalizeSetupActionType(value, index) {
9648
9651
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
9649
- 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 === "pointer_tap" || normalizedInput === "touch_tap" || normalizedInput === "canvas_tap" ? "tap" : 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;
9652
+ 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 === "pointer_tap" || normalizedInput === "touch_tap" || normalizedInput === "canvas_tap" ? "tap" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "keyboard_down" || normalizedInput === "key_down" || normalizedInput === "keydown" || normalizedInput === "press_down" ? "key_down" : normalizedInput === "keyboard_up" || normalizedInput === "key_up" || normalizedInput === "keyup" || normalizedInput === "press_up" || normalizedInput === "release_key" || normalizedInput === "key_release" ? "key_up" : 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;
9650
9653
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
9651
9654
  return normalized;
9652
9655
  }
@@ -9902,7 +9905,7 @@ function normalizeSetupAction(input, index) {
9902
9905
  dialogAccept = true;
9903
9906
  }
9904
9907
  }
9905
- if (type === "press" && !key) {
9908
+ if ((type === "press" || type === "key_down" || type === "key_up") && !key) {
9906
9909
  throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
9907
9910
  }
9908
9911
  if ((type === "local_storage" || type === "session_storage") && !key) {
@@ -13229,8 +13232,9 @@ function profileSetupTapReceipts(results) {
13229
13232
  }
13230
13233
  function profileSetupPressReceipts(results) {
13231
13234
  return (results || [])
13232
- .filter((result) => result && profileSetupResultAction(result) === "press")
13235
+ .filter((result) => result && ["press", "key_down", "key_up"].includes(profileSetupResultAction(result)))
13233
13236
  .map((result) => ({
13237
+ action: profileSetupResultAction(result),
13234
13238
  ordinal: result.ordinal ?? null,
13235
13239
  ok: result.ok !== false,
13236
13240
  selector: result.selector ?? null,
@@ -15170,6 +15174,37 @@ async function executeSetupAction(action, ordinal, viewport) {
15170
15174
  duration_ms: durationMs || undefined,
15171
15175
  };
15172
15176
  }
15177
+ if (type === "key_down" || type === "key_up") {
15178
+ const key = String(action.key || "").trim();
15179
+ if (!key) return { ...base, reason: "missing_key" };
15180
+ const scope = await setupActionScope(action, timeout);
15181
+ if (!scope.ok) return setupScopeFailure(base, scope);
15182
+ let count;
15183
+ let targetIndex;
15184
+ if (action.selector) {
15185
+ const locator = scope.context.locator(action.selector);
15186
+ count = await locator.count();
15187
+ if (!count) return { ...base, reason: "selector_not_found", count, key };
15188
+ targetIndex = Number.isInteger(action.index) ? action.index : 0;
15189
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex, key };
15190
+ await locator.nth(targetIndex).focus({ timeout }).catch(() => {});
15191
+ } else if (scope.frame_selector) {
15192
+ await scope.context.locator("body").focus({ timeout }).catch(() => {});
15193
+ }
15194
+ if (type === "key_down") {
15195
+ await page.keyboard.down(key);
15196
+ } else {
15197
+ await page.keyboard.up(key);
15198
+ }
15199
+ return {
15200
+ ...base,
15201
+ ...setupScopeEvidence(scope),
15202
+ ok: true,
15203
+ count,
15204
+ target_index: targetIndex,
15205
+ key,
15206
+ };
15207
+ }
15173
15208
  if (type === "press") {
15174
15209
  const key = String(action.key || "").trim();
15175
15210
  if (!key) return { ...base, reason: "missing_key" };
package/dist/index.js CHANGED
@@ -62,7 +62,7 @@ import {
62
62
  resolveRiddleProofProfileTimeoutSec,
63
63
  slugifyRiddleProofProfileName,
64
64
  summarizeRiddleProofProfileResult
65
- } from "./chunk-T664I6R3.js";
65
+ } from "./chunk-XL7Q4M6D.js";
66
66
  import {
67
67
  DEFAULT_RIDDLE_API_BASE_URL,
68
68
  DEFAULT_RIDDLE_API_KEY_FILE,
package/dist/profile.cjs CHANGED
@@ -94,6 +94,8 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
94
94
  "tap",
95
95
  "drag",
96
96
  "press",
97
+ "key_down",
98
+ "key_up",
97
99
  "fill",
98
100
  "set_input_value",
99
101
  "set_range_value",
@@ -659,7 +661,8 @@ function profileSetupTapReceipts(results) {
659
661
  }));
660
662
  }
661
663
  function profileSetupPressReceipts(results) {
662
- return results.filter((result) => profileSetupResultAction(result) === "press").map((result) => ({
664
+ return results.filter((result) => ["press", "key_down", "key_up"].includes(profileSetupResultAction(result))).map((result) => ({
665
+ action: profileSetupResultAction(result),
663
666
  ordinal: result.ordinal ?? null,
664
667
  ok: result.ok !== false,
665
668
  selector: result.selector ?? null,
@@ -960,7 +963,7 @@ function isSupportedCheckType(value) {
960
963
  }
961
964
  function normalizeSetupActionType(value, index) {
962
965
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
963
- 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 === "pointer_tap" || normalizedInput === "touch_tap" || normalizedInput === "canvas_tap" ? "tap" : 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;
966
+ 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 === "pointer_tap" || normalizedInput === "touch_tap" || normalizedInput === "canvas_tap" ? "tap" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "keyboard_down" || normalizedInput === "key_down" || normalizedInput === "keydown" || normalizedInput === "press_down" ? "key_down" : normalizedInput === "keyboard_up" || normalizedInput === "key_up" || normalizedInput === "keyup" || normalizedInput === "press_up" || normalizedInput === "release_key" || normalizedInput === "key_release" ? "key_up" : 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;
964
967
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
965
968
  return normalized;
966
969
  }
@@ -1216,7 +1219,7 @@ function normalizeSetupAction(input, index) {
1216
1219
  dialogAccept = true;
1217
1220
  }
1218
1221
  }
1219
- if (type === "press" && !key) {
1222
+ if ((type === "press" || type === "key_down" || type === "key_up") && !key) {
1220
1223
  throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
1221
1224
  }
1222
1225
  if ((type === "local_storage" || type === "session_storage") && !key) {
@@ -4543,8 +4546,9 @@ function profileSetupTapReceipts(results) {
4543
4546
  }
4544
4547
  function profileSetupPressReceipts(results) {
4545
4548
  return (results || [])
4546
- .filter((result) => result && profileSetupResultAction(result) === "press")
4549
+ .filter((result) => result && ["press", "key_down", "key_up"].includes(profileSetupResultAction(result)))
4547
4550
  .map((result) => ({
4551
+ action: profileSetupResultAction(result),
4548
4552
  ordinal: result.ordinal ?? null,
4549
4553
  ok: result.ok !== false,
4550
4554
  selector: result.selector ?? null,
@@ -6484,6 +6488,37 @@ async function executeSetupAction(action, ordinal, viewport) {
6484
6488
  duration_ms: durationMs || undefined,
6485
6489
  };
6486
6490
  }
6491
+ if (type === "key_down" || type === "key_up") {
6492
+ const key = String(action.key || "").trim();
6493
+ if (!key) return { ...base, reason: "missing_key" };
6494
+ const scope = await setupActionScope(action, timeout);
6495
+ if (!scope.ok) return setupScopeFailure(base, scope);
6496
+ let count;
6497
+ let targetIndex;
6498
+ if (action.selector) {
6499
+ const locator = scope.context.locator(action.selector);
6500
+ count = await locator.count();
6501
+ if (!count) return { ...base, reason: "selector_not_found", count, key };
6502
+ targetIndex = Number.isInteger(action.index) ? action.index : 0;
6503
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex, key };
6504
+ await locator.nth(targetIndex).focus({ timeout }).catch(() => {});
6505
+ } else if (scope.frame_selector) {
6506
+ await scope.context.locator("body").focus({ timeout }).catch(() => {});
6507
+ }
6508
+ if (type === "key_down") {
6509
+ await page.keyboard.down(key);
6510
+ } else {
6511
+ await page.keyboard.up(key);
6512
+ }
6513
+ return {
6514
+ ...base,
6515
+ ...setupScopeEvidence(scope),
6516
+ ok: true,
6517
+ count,
6518
+ target_index: targetIndex,
6519
+ key,
6520
+ };
6521
+ }
6487
6522
  if (type === "press") {
6488
6523
  const key = String(action.key || "").trim();
6489
6524
  if (!key) return { ...base, reason: "missing_key" };
@@ -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", "observe_within", "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", "tap", "drag", "press", "fill", "set_input_value", "set_range_value", "deterministic_runtime", "canvas_signature", "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"];
8
+ declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "tap", "drag", "press", "key_down", "key_up", "fill", "set_input_value", "set_range_value", "deterministic_runtime", "canvas_signature", "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];
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", "observe_within", "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", "tap", "drag", "press", "fill", "set_input_value", "set_range_value", "deterministic_runtime", "canvas_signature", "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"];
8
+ declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "tap", "drag", "press", "key_down", "key_up", "fill", "set_input_value", "set_range_value", "deterministic_runtime", "canvas_signature", "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];
package/dist/profile.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  resolveRiddleProofProfileTimeoutSec,
24
24
  slugifyRiddleProofProfileName,
25
25
  summarizeRiddleProofProfileResult
26
- } from "./chunk-T664I6R3.js";
26
+ } from "./chunk-XL7Q4M6D.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.181",
3
+ "version": "0.7.182",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",