@riddledc/riddle-proof 0.7.60 → 0.7.61

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
@@ -240,7 +240,7 @@ where the second request must carry newer state.
240
240
  `target.setup_actions` is optional. Use it when the meaningful proof surface
241
241
  appears only after a picker, tab, login stub, storage seed, form fill,
242
242
  transport control, or other bounded interaction. Supported setup actions are
243
- `click`, `press`, `fill`, `set_input_value`, `assert_text_visible`,
243
+ `click`, `drag`, `press`, `fill`, `set_input_value`, `assert_text_visible`,
244
244
  `assert_text_absent`, `assert_selector_count`, `assert_window_value`,
245
245
  `assert_window_number`, `local_storage`, `session_storage`, `clear_storage`, `wait`,
246
246
  `wait_for_selector`, `wait_for_text`, and `window_call`; a failed setup action
@@ -253,6 +253,12 @@ stable enough for Playwright's default click actionability checks. Use `press`
253
253
  with a Playwright key name, such as `Enter`, `Space`, or `ArrowLeft`,
254
254
  when a route's intended browser control is keyboard-driven; omit `selector` for
255
255
  a page-level key press, or provide `selector` to press against a focused element.
256
+ Use `drag` for pointer-driven controls such as canvas launch areas, sliders, or
257
+ drag-to-aim games. Provide `selector`, `from_x`, `from_y`, `to_x`, and `to_y`;
258
+ coordinates are element-relative pixels by default. Set `coordinate_mode:
259
+ "ratio"` to make coordinates relative to the target element size, for example
260
+ `from_x: 0.5, from_y: 0.5, to_x: 0.2, to_y: 0.5`. Optional `steps` and
261
+ `duration_ms` control how gradually the pointer moves before release.
256
262
  Use setup assertions when the pre-click or pre-navigation state is part of the contract,
257
263
  for example a fresh row must be present, stale copy must be absent, exactly one
258
264
  source link must exist before clicking into the final route, or a canvas app's
@@ -34,6 +34,7 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
34
34
  ];
35
35
  var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
36
36
  "click",
37
+ "drag",
37
38
  "press",
38
39
  "fill",
39
40
  "set_input_value",
@@ -204,7 +205,7 @@ function isSupportedCheckType(value) {
204
205
  }
205
206
  function normalizeSetupActionType(value, index) {
206
207
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
207
- const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
208
+ const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
208
209
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
209
210
  return normalized;
210
211
  }
@@ -234,6 +235,13 @@ function normalizeSetupActionRepeat(input, index) {
234
235
  }
235
236
  return repeat;
236
237
  }
238
+ function normalizeSetupActionCoordinateMode(value, index) {
239
+ if (value === void 0 || value === null || value === "") return void 0;
240
+ const normalized = String(value).trim().replace(/-/g, "_").toLowerCase();
241
+ if (normalized === "pixels" || normalized === "pixel" || normalized === "px") return "pixels";
242
+ if (normalized === "ratio" || normalized === "relative" || normalized === "fraction") return "ratio";
243
+ throw new Error(`target.setup_actions[${index}].coordinate_mode ${String(value)} is not supported. Supported coordinate modes: pixels, ratio.`);
244
+ }
237
245
  function normalizeSetupAction(input, index) {
238
246
  if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
239
247
  const type = normalizeSetupActionType(stringValue(input.type), index);
@@ -243,9 +251,25 @@ function normalizeSetupAction(input, index) {
243
251
  if (frameIndex !== void 0 && (!Number.isInteger(frameIndex) || frameIndex < 0)) {
244
252
  throw new Error(`target.setup_actions[${index}].frame_index must be a non-negative integer.`);
245
253
  }
246
- if ((type === "click" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
254
+ if ((type === "click" || type === "drag" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
247
255
  throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
248
256
  }
257
+ const fromX = numberValue(valueFromOwn(input, "from_x", "fromX", "start_x", "startX", "x1"));
258
+ const fromY = numberValue(valueFromOwn(input, "from_y", "fromY", "start_y", "startY", "y1"));
259
+ const toX = numberValue(valueFromOwn(input, "to_x", "toX", "end_x", "endX", "x2"));
260
+ const toY = numberValue(valueFromOwn(input, "to_y", "toY", "end_y", "endY", "y2"));
261
+ const coordinateMode = normalizeSetupActionCoordinateMode(valueFromOwn(input, "coordinate_mode", "coordinateMode", "coords", "units"), index);
262
+ if (type === "drag") {
263
+ if (fromX === void 0 || fromY === void 0 || toX === void 0 || toY === void 0) {
264
+ throw new Error(`target.setup_actions[${index}] drag requires from_x, from_y, to_x, and to_y.`);
265
+ }
266
+ if (coordinateMode === "ratio" && [fromX, fromY, toX, toY].some((value2) => value2 < 0 || value2 > 1)) {
267
+ throw new Error(`target.setup_actions[${index}] drag ratio coordinates must be between 0 and 1.`);
268
+ }
269
+ if ((coordinateMode === void 0 || coordinateMode === "pixels") && [fromX, fromY, toX, toY].some((value2) => value2 < 0)) {
270
+ throw new Error(`target.setup_actions[${index}] drag pixel coordinates must be non-negative.`);
271
+ }
272
+ }
249
273
  if (type === "wait_for_text" && !stringValue(input.text) && !stringValue(input.pattern)) {
250
274
  throw new Error(`target.setup_actions[${index}] wait_for_text requires text or pattern.`);
251
275
  }
@@ -292,12 +316,23 @@ function normalizeSetupAction(input, index) {
292
316
  }
293
317
  }
294
318
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
319
+ const steps = numberValue(input.steps);
320
+ if (type === "drag" && steps !== void 0 && (!Number.isInteger(steps) || steps < 1 || steps > 100)) {
321
+ throw new Error(`target.setup_actions[${index}].steps must be an integer from 1 to 100.`);
322
+ }
295
323
  return {
296
324
  type,
297
325
  selector,
298
326
  frame_selector: frameSelector,
299
327
  frame_index: frameIndex,
300
328
  force: type === "click" && (input.force === true || input.force_click === true || input.forceClick === true),
329
+ coordinate_mode: coordinateMode,
330
+ from_x: fromX,
331
+ from_y: fromY,
332
+ to_x: toX,
333
+ to_y: toY,
334
+ duration_ms: numberValue(input.duration_ms) ?? numberValue(input.durationMs),
335
+ steps,
301
336
  key,
302
337
  value,
303
338
  value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
@@ -2505,6 +2540,71 @@ async function executeSetupAction(action, ordinal) {
2505
2540
  await scope.context.waitForSelector(action.selector, { state: "visible", timeout });
2506
2541
  return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
2507
2542
  }
2543
+ if (type === "drag") {
2544
+ const scope = await setupActionScope(action, timeout);
2545
+ if (!scope.ok) return setupScopeFailure(base, scope);
2546
+ const locator = scope.context.locator(action.selector);
2547
+ const count = await locator.count();
2548
+ if (!count) return { ...base, ...setupScopeEvidence(scope), reason: "selector_not_found", count };
2549
+ const targetIndex = Number.isInteger(action.index) ? action.index : 0;
2550
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, ...setupScopeEvidence(scope), reason: "index_out_of_range", count, target_index: targetIndex };
2551
+ const target = locator.nth(targetIndex);
2552
+ await target.waitFor({ state: "visible", timeout });
2553
+ const box = await target.boundingBox();
2554
+ if (!box) return { ...base, ...setupScopeEvidence(scope), reason: "bounding_box_unavailable", count, target_index: targetIndex };
2555
+ const mode = String(action.coordinate_mode || action.coordinateMode || "pixels").trim();
2556
+ const coordinate = (value, size) => mode === "ratio" ? value * size : value;
2557
+ const fromX = setupFiniteNumber(action.from_x ?? action.fromX ?? action.start_x ?? action.startX ?? action.x1);
2558
+ const fromY = setupFiniteNumber(action.from_y ?? action.fromY ?? action.start_y ?? action.startY ?? action.y1);
2559
+ const toX = setupFiniteNumber(action.to_x ?? action.toX ?? action.end_x ?? action.endX ?? action.x2);
2560
+ const toY = setupFiniteNumber(action.to_y ?? action.toY ?? action.end_y ?? action.endY ?? action.y2);
2561
+ if (fromX === undefined || fromY === undefined || toX === undefined || toY === undefined) return { ...base, ...setupScopeEvidence(scope), reason: "missing_drag_coordinates", count, target_index: targetIndex };
2562
+ if (mode === "ratio" && [fromX, fromY, toX, toY].some((value) => value < 0 || value > 1)) return { ...base, ...setupScopeEvidence(scope), reason: "invalid_ratio_coordinates", count, target_index: targetIndex };
2563
+ if (mode !== "ratio" && [fromX, fromY, toX, toY].some((value) => value < 0)) return { ...base, ...setupScopeEvidence(scope), reason: "invalid_pixel_coordinates", count, target_index: targetIndex };
2564
+ const start = {
2565
+ x: box.x + coordinate(fromX, box.width),
2566
+ y: box.y + coordinate(fromY, box.height),
2567
+ };
2568
+ const end = {
2569
+ x: box.x + coordinate(toX, box.width),
2570
+ y: box.y + coordinate(toY, box.height),
2571
+ };
2572
+ const requestedSteps = setupNumber(action.steps, 8);
2573
+ const steps = Math.min(100, Math.max(1, Math.floor(requestedSteps || 8)));
2574
+ const durationMs = setupNumber(action.duration_ms ?? action.durationMs, 0);
2575
+ await page.mouse.move(start.x, start.y);
2576
+ await page.mouse.down();
2577
+ try {
2578
+ if (durationMs && steps > 1) {
2579
+ for (let step = 1; step <= steps; step += 1) {
2580
+ const progress = step / steps;
2581
+ await page.mouse.move(
2582
+ start.x + (end.x - start.x) * progress,
2583
+ start.y + (end.y - start.y) * progress,
2584
+ );
2585
+ await page.waitForTimeout(durationMs / steps);
2586
+ }
2587
+ } else {
2588
+ await page.mouse.move(end.x, end.y, { steps });
2589
+ }
2590
+ } finally {
2591
+ await page.mouse.up().catch(() => {});
2592
+ }
2593
+ return {
2594
+ ...base,
2595
+ ...setupScopeEvidence(scope),
2596
+ ok: true,
2597
+ count,
2598
+ target_index: targetIndex,
2599
+ coordinate_mode: mode,
2600
+ from_x: fromX,
2601
+ from_y: fromY,
2602
+ to_x: toX,
2603
+ to_y: toY,
2604
+ steps,
2605
+ duration_ms: durationMs || undefined,
2606
+ };
2607
+ }
2508
2608
  if (type === "press") {
2509
2609
  const key = String(action.key || "").trim();
2510
2610
  if (!key) return { ...base, reason: "missing_key" };
package/dist/cli.cjs CHANGED
@@ -6907,6 +6907,7 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
6907
6907
  ];
6908
6908
  var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
6909
6909
  "click",
6910
+ "drag",
6910
6911
  "press",
6911
6912
  "fill",
6912
6913
  "set_input_value",
@@ -7077,7 +7078,7 @@ function isSupportedCheckType(value) {
7077
7078
  }
7078
7079
  function normalizeSetupActionType(value, index) {
7079
7080
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
7080
- const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
7081
+ const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
7081
7082
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
7082
7083
  return normalized;
7083
7084
  }
@@ -7107,6 +7108,13 @@ function normalizeSetupActionRepeat(input, index) {
7107
7108
  }
7108
7109
  return repeat;
7109
7110
  }
7111
+ function normalizeSetupActionCoordinateMode(value, index) {
7112
+ if (value === void 0 || value === null || value === "") return void 0;
7113
+ const normalized = String(value).trim().replace(/-/g, "_").toLowerCase();
7114
+ if (normalized === "pixels" || normalized === "pixel" || normalized === "px") return "pixels";
7115
+ if (normalized === "ratio" || normalized === "relative" || normalized === "fraction") return "ratio";
7116
+ throw new Error(`target.setup_actions[${index}].coordinate_mode ${String(value)} is not supported. Supported coordinate modes: pixels, ratio.`);
7117
+ }
7110
7118
  function normalizeSetupAction(input, index) {
7111
7119
  if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
7112
7120
  const type = normalizeSetupActionType(stringValue2(input.type), index);
@@ -7116,9 +7124,25 @@ function normalizeSetupAction(input, index) {
7116
7124
  if (frameIndex !== void 0 && (!Number.isInteger(frameIndex) || frameIndex < 0)) {
7117
7125
  throw new Error(`target.setup_actions[${index}].frame_index must be a non-negative integer.`);
7118
7126
  }
7119
- if ((type === "click" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
7127
+ if ((type === "click" || type === "drag" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
7120
7128
  throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
7121
7129
  }
7130
+ const fromX = numberValue(valueFromOwn(input, "from_x", "fromX", "start_x", "startX", "x1"));
7131
+ const fromY = numberValue(valueFromOwn(input, "from_y", "fromY", "start_y", "startY", "y1"));
7132
+ const toX = numberValue(valueFromOwn(input, "to_x", "toX", "end_x", "endX", "x2"));
7133
+ const toY = numberValue(valueFromOwn(input, "to_y", "toY", "end_y", "endY", "y2"));
7134
+ const coordinateMode = normalizeSetupActionCoordinateMode(valueFromOwn(input, "coordinate_mode", "coordinateMode", "coords", "units"), index);
7135
+ if (type === "drag") {
7136
+ if (fromX === void 0 || fromY === void 0 || toX === void 0 || toY === void 0) {
7137
+ throw new Error(`target.setup_actions[${index}] drag requires from_x, from_y, to_x, and to_y.`);
7138
+ }
7139
+ if (coordinateMode === "ratio" && [fromX, fromY, toX, toY].some((value2) => value2 < 0 || value2 > 1)) {
7140
+ throw new Error(`target.setup_actions[${index}] drag ratio coordinates must be between 0 and 1.`);
7141
+ }
7142
+ if ((coordinateMode === void 0 || coordinateMode === "pixels") && [fromX, fromY, toX, toY].some((value2) => value2 < 0)) {
7143
+ throw new Error(`target.setup_actions[${index}] drag pixel coordinates must be non-negative.`);
7144
+ }
7145
+ }
7122
7146
  if (type === "wait_for_text" && !stringValue2(input.text) && !stringValue2(input.pattern)) {
7123
7147
  throw new Error(`target.setup_actions[${index}] wait_for_text requires text or pattern.`);
7124
7148
  }
@@ -7165,12 +7189,23 @@ function normalizeSetupAction(input, index) {
7165
7189
  }
7166
7190
  }
7167
7191
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
7192
+ const steps = numberValue(input.steps);
7193
+ if (type === "drag" && steps !== void 0 && (!Number.isInteger(steps) || steps < 1 || steps > 100)) {
7194
+ throw new Error(`target.setup_actions[${index}].steps must be an integer from 1 to 100.`);
7195
+ }
7168
7196
  return {
7169
7197
  type,
7170
7198
  selector,
7171
7199
  frame_selector: frameSelector,
7172
7200
  frame_index: frameIndex,
7173
7201
  force: type === "click" && (input.force === true || input.force_click === true || input.forceClick === true),
7202
+ coordinate_mode: coordinateMode,
7203
+ from_x: fromX,
7204
+ from_y: fromY,
7205
+ to_x: toX,
7206
+ to_y: toY,
7207
+ duration_ms: numberValue(input.duration_ms) ?? numberValue(input.durationMs),
7208
+ steps,
7174
7209
  key,
7175
7210
  value,
7176
7211
  value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
@@ -9362,6 +9397,71 @@ async function executeSetupAction(action, ordinal) {
9362
9397
  await scope.context.waitForSelector(action.selector, { state: "visible", timeout });
9363
9398
  return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
9364
9399
  }
9400
+ if (type === "drag") {
9401
+ const scope = await setupActionScope(action, timeout);
9402
+ if (!scope.ok) return setupScopeFailure(base, scope);
9403
+ const locator = scope.context.locator(action.selector);
9404
+ const count = await locator.count();
9405
+ if (!count) return { ...base, ...setupScopeEvidence(scope), reason: "selector_not_found", count };
9406
+ const targetIndex = Number.isInteger(action.index) ? action.index : 0;
9407
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, ...setupScopeEvidence(scope), reason: "index_out_of_range", count, target_index: targetIndex };
9408
+ const target = locator.nth(targetIndex);
9409
+ await target.waitFor({ state: "visible", timeout });
9410
+ const box = await target.boundingBox();
9411
+ if (!box) return { ...base, ...setupScopeEvidence(scope), reason: "bounding_box_unavailable", count, target_index: targetIndex };
9412
+ const mode = String(action.coordinate_mode || action.coordinateMode || "pixels").trim();
9413
+ const coordinate = (value, size) => mode === "ratio" ? value * size : value;
9414
+ const fromX = setupFiniteNumber(action.from_x ?? action.fromX ?? action.start_x ?? action.startX ?? action.x1);
9415
+ const fromY = setupFiniteNumber(action.from_y ?? action.fromY ?? action.start_y ?? action.startY ?? action.y1);
9416
+ const toX = setupFiniteNumber(action.to_x ?? action.toX ?? action.end_x ?? action.endX ?? action.x2);
9417
+ const toY = setupFiniteNumber(action.to_y ?? action.toY ?? action.end_y ?? action.endY ?? action.y2);
9418
+ if (fromX === undefined || fromY === undefined || toX === undefined || toY === undefined) return { ...base, ...setupScopeEvidence(scope), reason: "missing_drag_coordinates", count, target_index: targetIndex };
9419
+ if (mode === "ratio" && [fromX, fromY, toX, toY].some((value) => value < 0 || value > 1)) return { ...base, ...setupScopeEvidence(scope), reason: "invalid_ratio_coordinates", count, target_index: targetIndex };
9420
+ if (mode !== "ratio" && [fromX, fromY, toX, toY].some((value) => value < 0)) return { ...base, ...setupScopeEvidence(scope), reason: "invalid_pixel_coordinates", count, target_index: targetIndex };
9421
+ const start = {
9422
+ x: box.x + coordinate(fromX, box.width),
9423
+ y: box.y + coordinate(fromY, box.height),
9424
+ };
9425
+ const end = {
9426
+ x: box.x + coordinate(toX, box.width),
9427
+ y: box.y + coordinate(toY, box.height),
9428
+ };
9429
+ const requestedSteps = setupNumber(action.steps, 8);
9430
+ const steps = Math.min(100, Math.max(1, Math.floor(requestedSteps || 8)));
9431
+ const durationMs = setupNumber(action.duration_ms ?? action.durationMs, 0);
9432
+ await page.mouse.move(start.x, start.y);
9433
+ await page.mouse.down();
9434
+ try {
9435
+ if (durationMs && steps > 1) {
9436
+ for (let step = 1; step <= steps; step += 1) {
9437
+ const progress = step / steps;
9438
+ await page.mouse.move(
9439
+ start.x + (end.x - start.x) * progress,
9440
+ start.y + (end.y - start.y) * progress,
9441
+ );
9442
+ await page.waitForTimeout(durationMs / steps);
9443
+ }
9444
+ } else {
9445
+ await page.mouse.move(end.x, end.y, { steps });
9446
+ }
9447
+ } finally {
9448
+ await page.mouse.up().catch(() => {});
9449
+ }
9450
+ return {
9451
+ ...base,
9452
+ ...setupScopeEvidence(scope),
9453
+ ok: true,
9454
+ count,
9455
+ target_index: targetIndex,
9456
+ coordinate_mode: mode,
9457
+ from_x: fromX,
9458
+ from_y: fromY,
9459
+ to_x: toX,
9460
+ to_y: toY,
9461
+ steps,
9462
+ duration_ms: durationMs || undefined,
9463
+ };
9464
+ }
9365
9465
  if (type === "press") {
9366
9466
  const key = String(action.key || "").trim();
9367
9467
  if (!key) return { ...base, reason: "missing_key" };
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  profileStatusExitCode,
11
11
  resolveRiddleProofProfileTargetUrl,
12
12
  resolveRiddleProofProfileTimeoutSec
13
- } from "./chunk-FLQ4HHTT.js";
13
+ } from "./chunk-T66DWLBE.js";
14
14
  import {
15
15
  createRiddleApiClient,
16
16
  parseRiddleViewport
package/dist/index.cjs CHANGED
@@ -8748,6 +8748,7 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
8748
8748
  ];
8749
8749
  var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
8750
8750
  "click",
8751
+ "drag",
8751
8752
  "press",
8752
8753
  "fill",
8753
8754
  "set_input_value",
@@ -8918,7 +8919,7 @@ function isSupportedCheckType(value) {
8918
8919
  }
8919
8920
  function normalizeSetupActionType(value, index) {
8920
8921
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
8921
- const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
8922
+ const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
8922
8923
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
8923
8924
  return normalized;
8924
8925
  }
@@ -8948,6 +8949,13 @@ function normalizeSetupActionRepeat(input, index) {
8948
8949
  }
8949
8950
  return repeat;
8950
8951
  }
8952
+ function normalizeSetupActionCoordinateMode(value, index) {
8953
+ if (value === void 0 || value === null || value === "") return void 0;
8954
+ const normalized = String(value).trim().replace(/-/g, "_").toLowerCase();
8955
+ if (normalized === "pixels" || normalized === "pixel" || normalized === "px") return "pixels";
8956
+ if (normalized === "ratio" || normalized === "relative" || normalized === "fraction") return "ratio";
8957
+ throw new Error(`target.setup_actions[${index}].coordinate_mode ${String(value)} is not supported. Supported coordinate modes: pixels, ratio.`);
8958
+ }
8951
8959
  function normalizeSetupAction(input, index) {
8952
8960
  if (!isRecord2(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
8953
8961
  const type = normalizeSetupActionType(stringValue5(input.type), index);
@@ -8957,9 +8965,25 @@ function normalizeSetupAction(input, index) {
8957
8965
  if (frameIndex !== void 0 && (!Number.isInteger(frameIndex) || frameIndex < 0)) {
8958
8966
  throw new Error(`target.setup_actions[${index}].frame_index must be a non-negative integer.`);
8959
8967
  }
8960
- if ((type === "click" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
8968
+ if ((type === "click" || type === "drag" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
8961
8969
  throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
8962
8970
  }
8971
+ const fromX = numberValue3(valueFromOwn(input, "from_x", "fromX", "start_x", "startX", "x1"));
8972
+ const fromY = numberValue3(valueFromOwn(input, "from_y", "fromY", "start_y", "startY", "y1"));
8973
+ const toX = numberValue3(valueFromOwn(input, "to_x", "toX", "end_x", "endX", "x2"));
8974
+ const toY = numberValue3(valueFromOwn(input, "to_y", "toY", "end_y", "endY", "y2"));
8975
+ const coordinateMode = normalizeSetupActionCoordinateMode(valueFromOwn(input, "coordinate_mode", "coordinateMode", "coords", "units"), index);
8976
+ if (type === "drag") {
8977
+ if (fromX === void 0 || fromY === void 0 || toX === void 0 || toY === void 0) {
8978
+ throw new Error(`target.setup_actions[${index}] drag requires from_x, from_y, to_x, and to_y.`);
8979
+ }
8980
+ if (coordinateMode === "ratio" && [fromX, fromY, toX, toY].some((value2) => value2 < 0 || value2 > 1)) {
8981
+ throw new Error(`target.setup_actions[${index}] drag ratio coordinates must be between 0 and 1.`);
8982
+ }
8983
+ if ((coordinateMode === void 0 || coordinateMode === "pixels") && [fromX, fromY, toX, toY].some((value2) => value2 < 0)) {
8984
+ throw new Error(`target.setup_actions[${index}] drag pixel coordinates must be non-negative.`);
8985
+ }
8986
+ }
8963
8987
  if (type === "wait_for_text" && !stringValue5(input.text) && !stringValue5(input.pattern)) {
8964
8988
  throw new Error(`target.setup_actions[${index}] wait_for_text requires text or pattern.`);
8965
8989
  }
@@ -9006,12 +9030,23 @@ function normalizeSetupAction(input, index) {
9006
9030
  }
9007
9031
  }
9008
9032
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
9033
+ const steps = numberValue3(input.steps);
9034
+ if (type === "drag" && steps !== void 0 && (!Number.isInteger(steps) || steps < 1 || steps > 100)) {
9035
+ throw new Error(`target.setup_actions[${index}].steps must be an integer from 1 to 100.`);
9036
+ }
9009
9037
  return {
9010
9038
  type,
9011
9039
  selector,
9012
9040
  frame_selector: frameSelector,
9013
9041
  frame_index: frameIndex,
9014
9042
  force: type === "click" && (input.force === true || input.force_click === true || input.forceClick === true),
9043
+ coordinate_mode: coordinateMode,
9044
+ from_x: fromX,
9045
+ from_y: fromY,
9046
+ to_x: toX,
9047
+ to_y: toY,
9048
+ duration_ms: numberValue3(input.duration_ms) ?? numberValue3(input.durationMs),
9049
+ steps,
9015
9050
  key,
9016
9051
  value,
9017
9052
  value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
@@ -11219,6 +11254,71 @@ async function executeSetupAction(action, ordinal) {
11219
11254
  await scope.context.waitForSelector(action.selector, { state: "visible", timeout });
11220
11255
  return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
11221
11256
  }
11257
+ if (type === "drag") {
11258
+ const scope = await setupActionScope(action, timeout);
11259
+ if (!scope.ok) return setupScopeFailure(base, scope);
11260
+ const locator = scope.context.locator(action.selector);
11261
+ const count = await locator.count();
11262
+ if (!count) return { ...base, ...setupScopeEvidence(scope), reason: "selector_not_found", count };
11263
+ const targetIndex = Number.isInteger(action.index) ? action.index : 0;
11264
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, ...setupScopeEvidence(scope), reason: "index_out_of_range", count, target_index: targetIndex };
11265
+ const target = locator.nth(targetIndex);
11266
+ await target.waitFor({ state: "visible", timeout });
11267
+ const box = await target.boundingBox();
11268
+ if (!box) return { ...base, ...setupScopeEvidence(scope), reason: "bounding_box_unavailable", count, target_index: targetIndex };
11269
+ const mode = String(action.coordinate_mode || action.coordinateMode || "pixels").trim();
11270
+ const coordinate = (value, size) => mode === "ratio" ? value * size : value;
11271
+ const fromX = setupFiniteNumber(action.from_x ?? action.fromX ?? action.start_x ?? action.startX ?? action.x1);
11272
+ const fromY = setupFiniteNumber(action.from_y ?? action.fromY ?? action.start_y ?? action.startY ?? action.y1);
11273
+ const toX = setupFiniteNumber(action.to_x ?? action.toX ?? action.end_x ?? action.endX ?? action.x2);
11274
+ const toY = setupFiniteNumber(action.to_y ?? action.toY ?? action.end_y ?? action.endY ?? action.y2);
11275
+ if (fromX === undefined || fromY === undefined || toX === undefined || toY === undefined) return { ...base, ...setupScopeEvidence(scope), reason: "missing_drag_coordinates", count, target_index: targetIndex };
11276
+ if (mode === "ratio" && [fromX, fromY, toX, toY].some((value) => value < 0 || value > 1)) return { ...base, ...setupScopeEvidence(scope), reason: "invalid_ratio_coordinates", count, target_index: targetIndex };
11277
+ if (mode !== "ratio" && [fromX, fromY, toX, toY].some((value) => value < 0)) return { ...base, ...setupScopeEvidence(scope), reason: "invalid_pixel_coordinates", count, target_index: targetIndex };
11278
+ const start = {
11279
+ x: box.x + coordinate(fromX, box.width),
11280
+ y: box.y + coordinate(fromY, box.height),
11281
+ };
11282
+ const end = {
11283
+ x: box.x + coordinate(toX, box.width),
11284
+ y: box.y + coordinate(toY, box.height),
11285
+ };
11286
+ const requestedSteps = setupNumber(action.steps, 8);
11287
+ const steps = Math.min(100, Math.max(1, Math.floor(requestedSteps || 8)));
11288
+ const durationMs = setupNumber(action.duration_ms ?? action.durationMs, 0);
11289
+ await page.mouse.move(start.x, start.y);
11290
+ await page.mouse.down();
11291
+ try {
11292
+ if (durationMs && steps > 1) {
11293
+ for (let step = 1; step <= steps; step += 1) {
11294
+ const progress = step / steps;
11295
+ await page.mouse.move(
11296
+ start.x + (end.x - start.x) * progress,
11297
+ start.y + (end.y - start.y) * progress,
11298
+ );
11299
+ await page.waitForTimeout(durationMs / steps);
11300
+ }
11301
+ } else {
11302
+ await page.mouse.move(end.x, end.y, { steps });
11303
+ }
11304
+ } finally {
11305
+ await page.mouse.up().catch(() => {});
11306
+ }
11307
+ return {
11308
+ ...base,
11309
+ ...setupScopeEvidence(scope),
11310
+ ok: true,
11311
+ count,
11312
+ target_index: targetIndex,
11313
+ coordinate_mode: mode,
11314
+ from_x: fromX,
11315
+ from_y: fromY,
11316
+ to_x: toX,
11317
+ to_y: toY,
11318
+ steps,
11319
+ duration_ms: durationMs || undefined,
11320
+ };
11321
+ }
11222
11322
  if (type === "press") {
11223
11323
  const key = String(action.key || "").trim();
11224
11324
  if (!key) return { ...base, reason: "missing_key" };
package/dist/index.js CHANGED
@@ -58,7 +58,7 @@ import {
58
58
  resolveRiddleProofProfileTimeoutSec,
59
59
  slugifyRiddleProofProfileName,
60
60
  summarizeRiddleProofProfileResult
61
- } from "./chunk-FLQ4HHTT.js";
61
+ } from "./chunk-T66DWLBE.js";
62
62
  import {
63
63
  DEFAULT_RIDDLE_API_BASE_URL,
64
64
  DEFAULT_RIDDLE_API_KEY_FILE,
package/dist/profile.cjs CHANGED
@@ -77,6 +77,7 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
77
77
  ];
78
78
  var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
79
79
  "click",
80
+ "drag",
80
81
  "press",
81
82
  "fill",
82
83
  "set_input_value",
@@ -247,7 +248,7 @@ function isSupportedCheckType(value) {
247
248
  }
248
249
  function normalizeSetupActionType(value, index) {
249
250
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
250
- const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
251
+ const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
251
252
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
252
253
  return normalized;
253
254
  }
@@ -277,6 +278,13 @@ function normalizeSetupActionRepeat(input, index) {
277
278
  }
278
279
  return repeat;
279
280
  }
281
+ function normalizeSetupActionCoordinateMode(value, index) {
282
+ if (value === void 0 || value === null || value === "") return void 0;
283
+ const normalized = String(value).trim().replace(/-/g, "_").toLowerCase();
284
+ if (normalized === "pixels" || normalized === "pixel" || normalized === "px") return "pixels";
285
+ if (normalized === "ratio" || normalized === "relative" || normalized === "fraction") return "ratio";
286
+ throw new Error(`target.setup_actions[${index}].coordinate_mode ${String(value)} is not supported. Supported coordinate modes: pixels, ratio.`);
287
+ }
280
288
  function normalizeSetupAction(input, index) {
281
289
  if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
282
290
  const type = normalizeSetupActionType(stringValue(input.type), index);
@@ -286,9 +294,25 @@ function normalizeSetupAction(input, index) {
286
294
  if (frameIndex !== void 0 && (!Number.isInteger(frameIndex) || frameIndex < 0)) {
287
295
  throw new Error(`target.setup_actions[${index}].frame_index must be a non-negative integer.`);
288
296
  }
289
- if ((type === "click" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
297
+ if ((type === "click" || type === "drag" || type === "fill" || type === "set_input_value" || type === "wait_for_selector" || type === "wait_for_text" || type === "assert_text_visible" || type === "assert_text_absent" || type === "assert_selector_count") && !selector) {
290
298
  throw new Error(`target.setup_actions[${index}] ${type} requires selector.`);
291
299
  }
300
+ const fromX = numberValue(valueFromOwn(input, "from_x", "fromX", "start_x", "startX", "x1"));
301
+ const fromY = numberValue(valueFromOwn(input, "from_y", "fromY", "start_y", "startY", "y1"));
302
+ const toX = numberValue(valueFromOwn(input, "to_x", "toX", "end_x", "endX", "x2"));
303
+ const toY = numberValue(valueFromOwn(input, "to_y", "toY", "end_y", "endY", "y2"));
304
+ const coordinateMode = normalizeSetupActionCoordinateMode(valueFromOwn(input, "coordinate_mode", "coordinateMode", "coords", "units"), index);
305
+ if (type === "drag") {
306
+ if (fromX === void 0 || fromY === void 0 || toX === void 0 || toY === void 0) {
307
+ throw new Error(`target.setup_actions[${index}] drag requires from_x, from_y, to_x, and to_y.`);
308
+ }
309
+ if (coordinateMode === "ratio" && [fromX, fromY, toX, toY].some((value2) => value2 < 0 || value2 > 1)) {
310
+ throw new Error(`target.setup_actions[${index}] drag ratio coordinates must be between 0 and 1.`);
311
+ }
312
+ if ((coordinateMode === void 0 || coordinateMode === "pixels") && [fromX, fromY, toX, toY].some((value2) => value2 < 0)) {
313
+ throw new Error(`target.setup_actions[${index}] drag pixel coordinates must be non-negative.`);
314
+ }
315
+ }
292
316
  if (type === "wait_for_text" && !stringValue(input.text) && !stringValue(input.pattern)) {
293
317
  throw new Error(`target.setup_actions[${index}] wait_for_text requires text or pattern.`);
294
318
  }
@@ -335,12 +359,23 @@ function normalizeSetupAction(input, index) {
335
359
  }
336
360
  }
337
361
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
362
+ const steps = numberValue(input.steps);
363
+ if (type === "drag" && steps !== void 0 && (!Number.isInteger(steps) || steps < 1 || steps > 100)) {
364
+ throw new Error(`target.setup_actions[${index}].steps must be an integer from 1 to 100.`);
365
+ }
338
366
  return {
339
367
  type,
340
368
  selector,
341
369
  frame_selector: frameSelector,
342
370
  frame_index: frameIndex,
343
371
  force: type === "click" && (input.force === true || input.force_click === true || input.forceClick === true),
372
+ coordinate_mode: coordinateMode,
373
+ from_x: fromX,
374
+ from_y: fromY,
375
+ to_x: toX,
376
+ to_y: toY,
377
+ duration_ms: numberValue(input.duration_ms) ?? numberValue(input.durationMs),
378
+ steps,
344
379
  key,
345
380
  value,
346
381
  value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
@@ -2548,6 +2583,71 @@ async function executeSetupAction(action, ordinal) {
2548
2583
  await scope.context.waitForSelector(action.selector, { state: "visible", timeout });
2549
2584
  return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
2550
2585
  }
2586
+ if (type === "drag") {
2587
+ const scope = await setupActionScope(action, timeout);
2588
+ if (!scope.ok) return setupScopeFailure(base, scope);
2589
+ const locator = scope.context.locator(action.selector);
2590
+ const count = await locator.count();
2591
+ if (!count) return { ...base, ...setupScopeEvidence(scope), reason: "selector_not_found", count };
2592
+ const targetIndex = Number.isInteger(action.index) ? action.index : 0;
2593
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, ...setupScopeEvidence(scope), reason: "index_out_of_range", count, target_index: targetIndex };
2594
+ const target = locator.nth(targetIndex);
2595
+ await target.waitFor({ state: "visible", timeout });
2596
+ const box = await target.boundingBox();
2597
+ if (!box) return { ...base, ...setupScopeEvidence(scope), reason: "bounding_box_unavailable", count, target_index: targetIndex };
2598
+ const mode = String(action.coordinate_mode || action.coordinateMode || "pixels").trim();
2599
+ const coordinate = (value, size) => mode === "ratio" ? value * size : value;
2600
+ const fromX = setupFiniteNumber(action.from_x ?? action.fromX ?? action.start_x ?? action.startX ?? action.x1);
2601
+ const fromY = setupFiniteNumber(action.from_y ?? action.fromY ?? action.start_y ?? action.startY ?? action.y1);
2602
+ const toX = setupFiniteNumber(action.to_x ?? action.toX ?? action.end_x ?? action.endX ?? action.x2);
2603
+ const toY = setupFiniteNumber(action.to_y ?? action.toY ?? action.end_y ?? action.endY ?? action.y2);
2604
+ if (fromX === undefined || fromY === undefined || toX === undefined || toY === undefined) return { ...base, ...setupScopeEvidence(scope), reason: "missing_drag_coordinates", count, target_index: targetIndex };
2605
+ if (mode === "ratio" && [fromX, fromY, toX, toY].some((value) => value < 0 || value > 1)) return { ...base, ...setupScopeEvidence(scope), reason: "invalid_ratio_coordinates", count, target_index: targetIndex };
2606
+ if (mode !== "ratio" && [fromX, fromY, toX, toY].some((value) => value < 0)) return { ...base, ...setupScopeEvidence(scope), reason: "invalid_pixel_coordinates", count, target_index: targetIndex };
2607
+ const start = {
2608
+ x: box.x + coordinate(fromX, box.width),
2609
+ y: box.y + coordinate(fromY, box.height),
2610
+ };
2611
+ const end = {
2612
+ x: box.x + coordinate(toX, box.width),
2613
+ y: box.y + coordinate(toY, box.height),
2614
+ };
2615
+ const requestedSteps = setupNumber(action.steps, 8);
2616
+ const steps = Math.min(100, Math.max(1, Math.floor(requestedSteps || 8)));
2617
+ const durationMs = setupNumber(action.duration_ms ?? action.durationMs, 0);
2618
+ await page.mouse.move(start.x, start.y);
2619
+ await page.mouse.down();
2620
+ try {
2621
+ if (durationMs && steps > 1) {
2622
+ for (let step = 1; step <= steps; step += 1) {
2623
+ const progress = step / steps;
2624
+ await page.mouse.move(
2625
+ start.x + (end.x - start.x) * progress,
2626
+ start.y + (end.y - start.y) * progress,
2627
+ );
2628
+ await page.waitForTimeout(durationMs / steps);
2629
+ }
2630
+ } else {
2631
+ await page.mouse.move(end.x, end.y, { steps });
2632
+ }
2633
+ } finally {
2634
+ await page.mouse.up().catch(() => {});
2635
+ }
2636
+ return {
2637
+ ...base,
2638
+ ...setupScopeEvidence(scope),
2639
+ ok: true,
2640
+ count,
2641
+ target_index: targetIndex,
2642
+ coordinate_mode: mode,
2643
+ from_x: fromX,
2644
+ from_y: fromY,
2645
+ to_x: toX,
2646
+ to_y: toY,
2647
+ steps,
2648
+ duration_ms: durationMs || undefined,
2649
+ };
2650
+ }
2551
2651
  if (type === "press") {
2552
2652
  const key = String(action.key || "").trim();
2553
2653
  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", "selector_text_order", "frame_text_visible", "frame_url_equals", "frame_url_matches", "frame_no_horizontal_overflow", "text_visible", "text_absent", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
8
- declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "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", "wait", "wait_for_selector", "wait_for_text", "window_call"];
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", "wait", "wait_for_selector", "wait_for_text", "window_call"];
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];
@@ -23,6 +23,13 @@ interface RiddleProofProfileSetupAction {
23
23
  frame_selector?: string;
24
24
  frame_index?: number;
25
25
  force?: boolean;
26
+ coordinate_mode?: "pixels" | "ratio";
27
+ from_x?: number;
28
+ from_y?: number;
29
+ to_x?: number;
30
+ to_y?: number;
31
+ duration_ms?: number;
32
+ steps?: number;
26
33
  key?: string;
27
34
  value?: string;
28
35
  value_json?: 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", "selector_text_order", "frame_text_visible", "frame_url_equals", "frame_url_matches", "frame_no_horizontal_overflow", "text_visible", "text_absent", "route_inventory", "no_horizontal_overflow", "no_mobile_horizontal_overflow", "no_fatal_console_errors"];
8
- declare const RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES: readonly ["click", "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", "wait", "wait_for_selector", "wait_for_text", "window_call"];
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", "wait", "wait_for_selector", "wait_for_text", "window_call"];
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];
@@ -23,6 +23,13 @@ interface RiddleProofProfileSetupAction {
23
23
  frame_selector?: string;
24
24
  frame_index?: number;
25
25
  force?: boolean;
26
+ coordinate_mode?: "pixels" | "ratio";
27
+ from_x?: number;
28
+ from_y?: number;
29
+ to_x?: number;
30
+ to_y?: number;
31
+ duration_ms?: number;
32
+ steps?: number;
26
33
  key?: string;
27
34
  value?: string;
28
35
  value_json?: JsonValue;
package/dist/profile.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  resolveRiddleProofProfileTimeoutSec,
20
20
  slugifyRiddleProofProfileName,
21
21
  summarizeRiddleProofProfileResult
22
- } from "./chunk-FLQ4HHTT.js";
22
+ } from "./chunk-T66DWLBE.js";
23
23
  export {
24
24
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
25
25
  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.60",
3
+ "version": "0.7.61",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",