@riddledc/riddle-proof 0.7.56 → 0.7.58

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,22 +240,28 @@ 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`, `fill`, `set_input_value`, `assert_text_visible`,
243
+ `click`, `press`, `fill`, `set_input_value`, `assert_text_visible`,
244
244
  `assert_text_absent`, `assert_selector_count`, `assert_window_value`,
245
- `local_storage`, `session_storage`, `clear_storage`, `wait`,
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
247
247
  is recorded as a failed `setup_actions_succeeded` check so the profile cannot
248
248
  pass without reaching the intended state. Text-matched `click` actions prefer
249
249
  visible matching elements, which keeps responsive layouts from selecting hidden
250
250
  desktop or mobile-only links. Add `force: true` to a click action only when the
251
251
  matched visible element is intentionally animated or otherwise never becomes
252
- stable enough for Playwright's default click actionability checks. Use setup
253
- assertions when the pre-click or pre-navigation state is part of the contract,
252
+ stable enough for Playwright's default click actionability checks. Use `press`
253
+ with a Playwright key name, such as `Enter`, `Space`, or `ArrowLeft`,
254
+ when a route's intended browser control is keyboard-driven; omit `selector` for
255
+ a page-level key press, or provide `selector` to press against a focused element.
256
+ Use setup assertions when the pre-click or pre-navigation state is part of the contract,
254
257
  for example a fresh row must be present, stale copy must be absent, exactly one
255
258
  source link must exist before clicking into the final route, or a canvas app's
256
259
  proof state must expose a terminal flag. `assert_selector_count` accepts
257
260
  `expected_count`; `assert_window_value` accepts `path` / `state_path` plus
258
261
  `expected_value` / `expected` and compares JSON-safe values exactly.
262
+ `assert_window_number` accepts `path` / `state_path` plus `expected_value`,
263
+ `min_value`, or `max_value`, and is useful for canvas-only proof state such as
264
+ distance, elapsed time, score, or retry counters.
259
265
  `local_storage` and `session_storage` accept a `key` plus string `value` or
260
266
  JSON `json` / `value_json`, and can reload the page with `reload: true`.
261
267
  `clear_storage` clears `local`, `session`, or `both` browser storage scopes,
@@ -32,12 +32,14 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
32
32
  ];
33
33
  var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
34
34
  "click",
35
+ "press",
35
36
  "fill",
36
37
  "set_input_value",
37
38
  "assert_text_visible",
38
39
  "assert_text_absent",
39
40
  "assert_selector_count",
40
41
  "assert_window_value",
42
+ "assert_window_number",
41
43
  "local_storage",
42
44
  "session_storage",
43
45
  "clear_storage",
@@ -200,7 +202,7 @@ function isSupportedCheckType(value) {
200
202
  }
201
203
  function normalizeSetupActionType(value, index) {
202
204
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
203
- const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput;
205
+ const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
204
206
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
205
207
  return normalized;
206
208
  }
@@ -253,6 +255,9 @@ function normalizeSetupAction(input, index) {
253
255
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
254
256
  }
255
257
  const key = stringValue(input.key);
258
+ if (type === "press" && !key) {
259
+ throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
260
+ }
256
261
  if ((type === "local_storage" || type === "session_storage") && !key) {
257
262
  throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
258
263
  }
@@ -260,7 +265,7 @@ function normalizeSetupAction(input, index) {
260
265
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
261
266
  }
262
267
  const path = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath", "state_path", "statePath");
263
- if ((type === "window_call" || type === "assert_window_value") && !path) {
268
+ if ((type === "window_call" || type === "assert_window_value" || type === "assert_window_number") && !path) {
264
269
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
265
270
  }
266
271
  const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
@@ -268,6 +273,17 @@ function normalizeSetupAction(input, index) {
268
273
  if (type === "assert_window_value" && !hasExpectedValue) {
269
274
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
270
275
  }
276
+ const rawExpectedValue = valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect");
277
+ const minValue = numberValue(valueFromOwn(input, "min_value", "minValue", "minimum", "min", "at_least", "atLeast", "gte"));
278
+ const maxValue = numberValue(valueFromOwn(input, "max_value", "maxValue", "maximum", "max", "at_most", "atMost", "lte"));
279
+ if (type === "assert_window_number") {
280
+ if (!hasExpectedValue && minValue === void 0 && maxValue === void 0) {
281
+ throw new Error(`target.setup_actions[${index}] ${type} requires expected_value, min_value, or max_value.`);
282
+ }
283
+ if (hasExpectedValue && numberValue(rawExpectedValue) === void 0) {
284
+ throw new Error(`target.setup_actions[${index}] ${type} expected_value must be a finite number.`);
285
+ }
286
+ }
271
287
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
272
288
  return {
273
289
  type,
@@ -279,7 +295,9 @@ function normalizeSetupAction(input, index) {
279
295
  path,
280
296
  args,
281
297
  expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
282
- expected_value: hasExpectedValue ? toJsonValue(valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect")) : void 0,
298
+ expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
299
+ min_value: minValue,
300
+ max_value: maxValue,
283
301
  text: stringValue(input.text),
284
302
  pattern: stringValue(input.pattern),
285
303
  flags: stringValue(input.flags),
@@ -2103,6 +2121,10 @@ function setupNumber(value, fallback) {
2103
2121
  const number = Number(value);
2104
2122
  return Number.isFinite(number) && number >= 0 ? number : fallback;
2105
2123
  }
2124
+ function setupFiniteNumber(value) {
2125
+ const number = Number(value);
2126
+ return Number.isFinite(number) ? number : undefined;
2127
+ }
2106
2128
  function setupTextMatches(sample, action) {
2107
2129
  if (action.pattern) {
2108
2130
  try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
@@ -2326,6 +2348,21 @@ async function executeSetupAction(action, ordinal) {
2326
2348
  await page.waitForSelector(action.selector, { state: "visible", timeout });
2327
2349
  return { ...base, ok: true, timeout_ms: timeout };
2328
2350
  }
2351
+ if (type === "press") {
2352
+ const key = String(action.key || "").trim();
2353
+ if (!key) return { ...base, reason: "missing_key" };
2354
+ if (!action.selector) {
2355
+ await page.keyboard.press(key);
2356
+ return { ...base, ok: true, key };
2357
+ }
2358
+ const locator = page.locator(action.selector);
2359
+ const count = await locator.count();
2360
+ if (!count) return { ...base, reason: "selector_not_found", count, key };
2361
+ const targetIndex = Number.isInteger(action.index) ? action.index : 0;
2362
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex, key };
2363
+ await locator.nth(targetIndex).press(key, { timeout });
2364
+ return { ...base, ok: true, count, target_index: targetIndex, key };
2365
+ }
2329
2366
  if (type === "local_storage" || type === "session_storage") {
2330
2367
  const value = setupActionValue(action);
2331
2368
  await page.evaluate(({ type, key, value }) => {
@@ -2448,6 +2485,58 @@ async function executeSetupAction(action, ordinal) {
2448
2485
  timeout_ms: timeout,
2449
2486
  };
2450
2487
  }
2488
+ if (type === "assert_window_number") {
2489
+ const path = String(action.path || action.window_path || action.windowPath || "");
2490
+ const expected = setupFiniteNumber(action.expected_value ?? action.expectedValue ?? action.expected ?? action.expect_value ?? action.expectValue ?? action.expect);
2491
+ const minValue = setupFiniteNumber(action.min_value ?? action.minValue ?? action.minimum ?? action.min ?? action.at_least ?? action.atLeast ?? action.gte);
2492
+ const maxValue = setupFiniteNumber(action.max_value ?? action.maxValue ?? action.maximum ?? action.max ?? action.at_most ?? action.atMost ?? action.lte);
2493
+ const hasExpected = expected !== undefined;
2494
+ if (!path) return { ...base, path, reason: "missing_path" };
2495
+ if (!hasExpected && minValue === undefined && maxValue === undefined) return { ...base, path, reason: "missing_number_expectation" };
2496
+ const startedAt = Date.now();
2497
+ let result = null;
2498
+ let lastReason = "path_not_found";
2499
+ while (Date.now() - startedAt <= timeout) {
2500
+ result = await setupReadWindowValue(path);
2501
+ if (result.ok) {
2502
+ const actual = setupFiniteNumber(result.value);
2503
+ if (actual === undefined) {
2504
+ lastReason = "non_numeric_value";
2505
+ } else if (hasExpected && actual !== expected) {
2506
+ lastReason = "unexpected_number";
2507
+ } else if (minValue !== undefined && actual < minValue) {
2508
+ lastReason = "number_below_min";
2509
+ } else if (maxValue !== undefined && actual > maxValue) {
2510
+ lastReason = "number_above_max";
2511
+ } else {
2512
+ return {
2513
+ ...base,
2514
+ ok: true,
2515
+ path,
2516
+ value: actual,
2517
+ expected_value: hasExpected ? expected : undefined,
2518
+ min_value: minValue,
2519
+ max_value: maxValue,
2520
+ timeout_ms: timeout,
2521
+ };
2522
+ }
2523
+ } else {
2524
+ lastReason = result.reason || "path_not_found";
2525
+ }
2526
+ await page.waitForTimeout(100);
2527
+ }
2528
+ return {
2529
+ ...base,
2530
+ path,
2531
+ reason: lastReason,
2532
+ missing_part: result?.missing_part || undefined,
2533
+ value: setupJsonValue(result?.value),
2534
+ expected_value: hasExpected ? expected : undefined,
2535
+ min_value: minValue,
2536
+ max_value: maxValue,
2537
+ timeout_ms: timeout,
2538
+ };
2539
+ }
2451
2540
  if (type === "click") {
2452
2541
  const locator = page.locator(action.selector);
2453
2542
  const count = await locator.count();
package/dist/cli.cjs CHANGED
@@ -6905,12 +6905,14 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
6905
6905
  ];
6906
6906
  var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
6907
6907
  "click",
6908
+ "press",
6908
6909
  "fill",
6909
6910
  "set_input_value",
6910
6911
  "assert_text_visible",
6911
6912
  "assert_text_absent",
6912
6913
  "assert_selector_count",
6913
6914
  "assert_window_value",
6915
+ "assert_window_number",
6914
6916
  "local_storage",
6915
6917
  "session_storage",
6916
6918
  "clear_storage",
@@ -7073,7 +7075,7 @@ function isSupportedCheckType(value) {
7073
7075
  }
7074
7076
  function normalizeSetupActionType(value, index) {
7075
7077
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
7076
- const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput;
7078
+ const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
7077
7079
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
7078
7080
  return normalized;
7079
7081
  }
@@ -7126,6 +7128,9 @@ function normalizeSetupAction(input, index) {
7126
7128
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
7127
7129
  }
7128
7130
  const key = stringValue2(input.key);
7131
+ if (type === "press" && !key) {
7132
+ throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
7133
+ }
7129
7134
  if ((type === "local_storage" || type === "session_storage") && !key) {
7130
7135
  throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
7131
7136
  }
@@ -7133,7 +7138,7 @@ function normalizeSetupAction(input, index) {
7133
7138
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
7134
7139
  }
7135
7140
  const path7 = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath", "state_path", "statePath");
7136
- if ((type === "window_call" || type === "assert_window_value") && !path7) {
7141
+ if ((type === "window_call" || type === "assert_window_value" || type === "assert_window_number") && !path7) {
7137
7142
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
7138
7143
  }
7139
7144
  const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
@@ -7141,6 +7146,17 @@ function normalizeSetupAction(input, index) {
7141
7146
  if (type === "assert_window_value" && !hasExpectedValue) {
7142
7147
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
7143
7148
  }
7149
+ const rawExpectedValue = valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect");
7150
+ const minValue = numberValue(valueFromOwn(input, "min_value", "minValue", "minimum", "min", "at_least", "atLeast", "gte"));
7151
+ const maxValue = numberValue(valueFromOwn(input, "max_value", "maxValue", "maximum", "max", "at_most", "atMost", "lte"));
7152
+ if (type === "assert_window_number") {
7153
+ if (!hasExpectedValue && minValue === void 0 && maxValue === void 0) {
7154
+ throw new Error(`target.setup_actions[${index}] ${type} requires expected_value, min_value, or max_value.`);
7155
+ }
7156
+ if (hasExpectedValue && numberValue(rawExpectedValue) === void 0) {
7157
+ throw new Error(`target.setup_actions[${index}] ${type} expected_value must be a finite number.`);
7158
+ }
7159
+ }
7144
7160
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
7145
7161
  return {
7146
7162
  type,
@@ -7152,7 +7168,9 @@ function normalizeSetupAction(input, index) {
7152
7168
  path: path7,
7153
7169
  args,
7154
7170
  expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
7155
- expected_value: hasExpectedValue ? toJsonValue(valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect")) : void 0,
7171
+ expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
7172
+ min_value: minValue,
7173
+ max_value: maxValue,
7156
7174
  text: stringValue2(input.text),
7157
7175
  pattern: stringValue2(input.pattern),
7158
7176
  flags: stringValue2(input.flags),
@@ -8960,6 +8978,10 @@ function setupNumber(value, fallback) {
8960
8978
  const number = Number(value);
8961
8979
  return Number.isFinite(number) && number >= 0 ? number : fallback;
8962
8980
  }
8981
+ function setupFiniteNumber(value) {
8982
+ const number = Number(value);
8983
+ return Number.isFinite(number) ? number : undefined;
8984
+ }
8963
8985
  function setupTextMatches(sample, action) {
8964
8986
  if (action.pattern) {
8965
8987
  try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
@@ -9183,6 +9205,21 @@ async function executeSetupAction(action, ordinal) {
9183
9205
  await page.waitForSelector(action.selector, { state: "visible", timeout });
9184
9206
  return { ...base, ok: true, timeout_ms: timeout };
9185
9207
  }
9208
+ if (type === "press") {
9209
+ const key = String(action.key || "").trim();
9210
+ if (!key) return { ...base, reason: "missing_key" };
9211
+ if (!action.selector) {
9212
+ await page.keyboard.press(key);
9213
+ return { ...base, ok: true, key };
9214
+ }
9215
+ const locator = page.locator(action.selector);
9216
+ const count = await locator.count();
9217
+ if (!count) return { ...base, reason: "selector_not_found", count, key };
9218
+ const targetIndex = Number.isInteger(action.index) ? action.index : 0;
9219
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex, key };
9220
+ await locator.nth(targetIndex).press(key, { timeout });
9221
+ return { ...base, ok: true, count, target_index: targetIndex, key };
9222
+ }
9186
9223
  if (type === "local_storage" || type === "session_storage") {
9187
9224
  const value = setupActionValue(action);
9188
9225
  await page.evaluate(({ type, key, value }) => {
@@ -9305,6 +9342,58 @@ async function executeSetupAction(action, ordinal) {
9305
9342
  timeout_ms: timeout,
9306
9343
  };
9307
9344
  }
9345
+ if (type === "assert_window_number") {
9346
+ const path = String(action.path || action.window_path || action.windowPath || "");
9347
+ const expected = setupFiniteNumber(action.expected_value ?? action.expectedValue ?? action.expected ?? action.expect_value ?? action.expectValue ?? action.expect);
9348
+ const minValue = setupFiniteNumber(action.min_value ?? action.minValue ?? action.minimum ?? action.min ?? action.at_least ?? action.atLeast ?? action.gte);
9349
+ const maxValue = setupFiniteNumber(action.max_value ?? action.maxValue ?? action.maximum ?? action.max ?? action.at_most ?? action.atMost ?? action.lte);
9350
+ const hasExpected = expected !== undefined;
9351
+ if (!path) return { ...base, path, reason: "missing_path" };
9352
+ if (!hasExpected && minValue === undefined && maxValue === undefined) return { ...base, path, reason: "missing_number_expectation" };
9353
+ const startedAt = Date.now();
9354
+ let result = null;
9355
+ let lastReason = "path_not_found";
9356
+ while (Date.now() - startedAt <= timeout) {
9357
+ result = await setupReadWindowValue(path);
9358
+ if (result.ok) {
9359
+ const actual = setupFiniteNumber(result.value);
9360
+ if (actual === undefined) {
9361
+ lastReason = "non_numeric_value";
9362
+ } else if (hasExpected && actual !== expected) {
9363
+ lastReason = "unexpected_number";
9364
+ } else if (minValue !== undefined && actual < minValue) {
9365
+ lastReason = "number_below_min";
9366
+ } else if (maxValue !== undefined && actual > maxValue) {
9367
+ lastReason = "number_above_max";
9368
+ } else {
9369
+ return {
9370
+ ...base,
9371
+ ok: true,
9372
+ path,
9373
+ value: actual,
9374
+ expected_value: hasExpected ? expected : undefined,
9375
+ min_value: minValue,
9376
+ max_value: maxValue,
9377
+ timeout_ms: timeout,
9378
+ };
9379
+ }
9380
+ } else {
9381
+ lastReason = result.reason || "path_not_found";
9382
+ }
9383
+ await page.waitForTimeout(100);
9384
+ }
9385
+ return {
9386
+ ...base,
9387
+ path,
9388
+ reason: lastReason,
9389
+ missing_part: result?.missing_part || undefined,
9390
+ value: setupJsonValue(result?.value),
9391
+ expected_value: hasExpected ? expected : undefined,
9392
+ min_value: minValue,
9393
+ max_value: maxValue,
9394
+ timeout_ms: timeout,
9395
+ };
9396
+ }
9308
9397
  if (type === "click") {
9309
9398
  const locator = page.locator(action.selector);
9310
9399
  const count = await locator.count();
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  profileStatusExitCode,
11
11
  resolveRiddleProofProfileTargetUrl,
12
12
  resolveRiddleProofProfileTimeoutSec
13
- } from "./chunk-2JFDTCIC.js";
13
+ } from "./chunk-7ZBK2GQX.js";
14
14
  import {
15
15
  createRiddleApiClient,
16
16
  parseRiddleViewport
package/dist/index.cjs CHANGED
@@ -8746,12 +8746,14 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
8746
8746
  ];
8747
8747
  var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
8748
8748
  "click",
8749
+ "press",
8749
8750
  "fill",
8750
8751
  "set_input_value",
8751
8752
  "assert_text_visible",
8752
8753
  "assert_text_absent",
8753
8754
  "assert_selector_count",
8754
8755
  "assert_window_value",
8756
+ "assert_window_number",
8755
8757
  "local_storage",
8756
8758
  "session_storage",
8757
8759
  "clear_storage",
@@ -8914,7 +8916,7 @@ function isSupportedCheckType(value) {
8914
8916
  }
8915
8917
  function normalizeSetupActionType(value, index) {
8916
8918
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
8917
- const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput;
8919
+ const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
8918
8920
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
8919
8921
  return normalized;
8920
8922
  }
@@ -8967,6 +8969,9 @@ function normalizeSetupAction(input, index) {
8967
8969
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
8968
8970
  }
8969
8971
  const key = stringValue5(input.key);
8972
+ if (type === "press" && !key) {
8973
+ throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
8974
+ }
8970
8975
  if ((type === "local_storage" || type === "session_storage") && !key) {
8971
8976
  throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
8972
8977
  }
@@ -8974,7 +8979,7 @@ function normalizeSetupAction(input, index) {
8974
8979
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
8975
8980
  }
8976
8981
  const path6 = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath", "state_path", "statePath");
8977
- if ((type === "window_call" || type === "assert_window_value") && !path6) {
8982
+ if ((type === "window_call" || type === "assert_window_value" || type === "assert_window_number") && !path6) {
8978
8983
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
8979
8984
  }
8980
8985
  const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
@@ -8982,6 +8987,17 @@ function normalizeSetupAction(input, index) {
8982
8987
  if (type === "assert_window_value" && !hasExpectedValue) {
8983
8988
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
8984
8989
  }
8990
+ const rawExpectedValue = valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect");
8991
+ const minValue = numberValue3(valueFromOwn(input, "min_value", "minValue", "minimum", "min", "at_least", "atLeast", "gte"));
8992
+ const maxValue = numberValue3(valueFromOwn(input, "max_value", "maxValue", "maximum", "max", "at_most", "atMost", "lte"));
8993
+ if (type === "assert_window_number") {
8994
+ if (!hasExpectedValue && minValue === void 0 && maxValue === void 0) {
8995
+ throw new Error(`target.setup_actions[${index}] ${type} requires expected_value, min_value, or max_value.`);
8996
+ }
8997
+ if (hasExpectedValue && numberValue3(rawExpectedValue) === void 0) {
8998
+ throw new Error(`target.setup_actions[${index}] ${type} expected_value must be a finite number.`);
8999
+ }
9000
+ }
8985
9001
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
8986
9002
  return {
8987
9003
  type,
@@ -8993,7 +9009,9 @@ function normalizeSetupAction(input, index) {
8993
9009
  path: path6,
8994
9010
  args,
8995
9011
  expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
8996
- expected_value: hasExpectedValue ? toJsonValue(valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect")) : void 0,
9012
+ expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
9013
+ min_value: minValue,
9014
+ max_value: maxValue,
8997
9015
  text: stringValue5(input.text),
8998
9016
  pattern: stringValue5(input.pattern),
8999
9017
  flags: stringValue5(input.flags),
@@ -10817,6 +10835,10 @@ function setupNumber(value, fallback) {
10817
10835
  const number = Number(value);
10818
10836
  return Number.isFinite(number) && number >= 0 ? number : fallback;
10819
10837
  }
10838
+ function setupFiniteNumber(value) {
10839
+ const number = Number(value);
10840
+ return Number.isFinite(number) ? number : undefined;
10841
+ }
10820
10842
  function setupTextMatches(sample, action) {
10821
10843
  if (action.pattern) {
10822
10844
  try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
@@ -11040,6 +11062,21 @@ async function executeSetupAction(action, ordinal) {
11040
11062
  await page.waitForSelector(action.selector, { state: "visible", timeout });
11041
11063
  return { ...base, ok: true, timeout_ms: timeout };
11042
11064
  }
11065
+ if (type === "press") {
11066
+ const key = String(action.key || "").trim();
11067
+ if (!key) return { ...base, reason: "missing_key" };
11068
+ if (!action.selector) {
11069
+ await page.keyboard.press(key);
11070
+ return { ...base, ok: true, key };
11071
+ }
11072
+ const locator = page.locator(action.selector);
11073
+ const count = await locator.count();
11074
+ if (!count) return { ...base, reason: "selector_not_found", count, key };
11075
+ const targetIndex = Number.isInteger(action.index) ? action.index : 0;
11076
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex, key };
11077
+ await locator.nth(targetIndex).press(key, { timeout });
11078
+ return { ...base, ok: true, count, target_index: targetIndex, key };
11079
+ }
11043
11080
  if (type === "local_storage" || type === "session_storage") {
11044
11081
  const value = setupActionValue(action);
11045
11082
  await page.evaluate(({ type, key, value }) => {
@@ -11162,6 +11199,58 @@ async function executeSetupAction(action, ordinal) {
11162
11199
  timeout_ms: timeout,
11163
11200
  };
11164
11201
  }
11202
+ if (type === "assert_window_number") {
11203
+ const path = String(action.path || action.window_path || action.windowPath || "");
11204
+ const expected = setupFiniteNumber(action.expected_value ?? action.expectedValue ?? action.expected ?? action.expect_value ?? action.expectValue ?? action.expect);
11205
+ const minValue = setupFiniteNumber(action.min_value ?? action.minValue ?? action.minimum ?? action.min ?? action.at_least ?? action.atLeast ?? action.gte);
11206
+ const maxValue = setupFiniteNumber(action.max_value ?? action.maxValue ?? action.maximum ?? action.max ?? action.at_most ?? action.atMost ?? action.lte);
11207
+ const hasExpected = expected !== undefined;
11208
+ if (!path) return { ...base, path, reason: "missing_path" };
11209
+ if (!hasExpected && minValue === undefined && maxValue === undefined) return { ...base, path, reason: "missing_number_expectation" };
11210
+ const startedAt = Date.now();
11211
+ let result = null;
11212
+ let lastReason = "path_not_found";
11213
+ while (Date.now() - startedAt <= timeout) {
11214
+ result = await setupReadWindowValue(path);
11215
+ if (result.ok) {
11216
+ const actual = setupFiniteNumber(result.value);
11217
+ if (actual === undefined) {
11218
+ lastReason = "non_numeric_value";
11219
+ } else if (hasExpected && actual !== expected) {
11220
+ lastReason = "unexpected_number";
11221
+ } else if (minValue !== undefined && actual < minValue) {
11222
+ lastReason = "number_below_min";
11223
+ } else if (maxValue !== undefined && actual > maxValue) {
11224
+ lastReason = "number_above_max";
11225
+ } else {
11226
+ return {
11227
+ ...base,
11228
+ ok: true,
11229
+ path,
11230
+ value: actual,
11231
+ expected_value: hasExpected ? expected : undefined,
11232
+ min_value: minValue,
11233
+ max_value: maxValue,
11234
+ timeout_ms: timeout,
11235
+ };
11236
+ }
11237
+ } else {
11238
+ lastReason = result.reason || "path_not_found";
11239
+ }
11240
+ await page.waitForTimeout(100);
11241
+ }
11242
+ return {
11243
+ ...base,
11244
+ path,
11245
+ reason: lastReason,
11246
+ missing_part: result?.missing_part || undefined,
11247
+ value: setupJsonValue(result?.value),
11248
+ expected_value: hasExpected ? expected : undefined,
11249
+ min_value: minValue,
11250
+ max_value: maxValue,
11251
+ timeout_ms: timeout,
11252
+ };
11253
+ }
11165
11254
  if (type === "click") {
11166
11255
  const locator = page.locator(action.selector);
11167
11256
  const count = await locator.count();
package/dist/index.js CHANGED
@@ -58,7 +58,7 @@ import {
58
58
  resolveRiddleProofProfileTimeoutSec,
59
59
  slugifyRiddleProofProfileName,
60
60
  summarizeRiddleProofProfileResult
61
- } from "./chunk-2JFDTCIC.js";
61
+ } from "./chunk-7ZBK2GQX.js";
62
62
  import {
63
63
  DEFAULT_RIDDLE_API_BASE_URL,
64
64
  DEFAULT_RIDDLE_API_KEY_FILE,
package/dist/profile.cjs CHANGED
@@ -75,12 +75,14 @@ var RIDDLE_PROOF_PROFILE_CHECK_TYPES = [
75
75
  ];
76
76
  var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
77
77
  "click",
78
+ "press",
78
79
  "fill",
79
80
  "set_input_value",
80
81
  "assert_text_visible",
81
82
  "assert_text_absent",
82
83
  "assert_selector_count",
83
84
  "assert_window_value",
85
+ "assert_window_number",
84
86
  "local_storage",
85
87
  "session_storage",
86
88
  "clear_storage",
@@ -243,7 +245,7 @@ function isSupportedCheckType(value) {
243
245
  }
244
246
  function normalizeSetupActionType(value, index) {
245
247
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
246
- const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput;
248
+ const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput;
247
249
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
248
250
  return normalized;
249
251
  }
@@ -296,6 +298,9 @@ function normalizeSetupAction(input, index) {
296
298
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
297
299
  }
298
300
  const key = stringValue(input.key);
301
+ if (type === "press" && !key) {
302
+ throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
303
+ }
299
304
  if ((type === "local_storage" || type === "session_storage") && !key) {
300
305
  throw new Error(`target.setup_actions[${index}] ${type} requires key.`);
301
306
  }
@@ -303,7 +308,7 @@ function normalizeSetupAction(input, index) {
303
308
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
304
309
  }
305
310
  const path = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath", "state_path", "statePath");
306
- if ((type === "window_call" || type === "assert_window_value") && !path) {
311
+ if ((type === "window_call" || type === "assert_window_value" || type === "assert_window_number") && !path) {
307
312
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
308
313
  }
309
314
  const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
@@ -311,6 +316,17 @@ function normalizeSetupAction(input, index) {
311
316
  if (type === "assert_window_value" && !hasExpectedValue) {
312
317
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
313
318
  }
319
+ const rawExpectedValue = valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect");
320
+ const minValue = numberValue(valueFromOwn(input, "min_value", "minValue", "minimum", "min", "at_least", "atLeast", "gte"));
321
+ const maxValue = numberValue(valueFromOwn(input, "max_value", "maxValue", "maximum", "max", "at_most", "atMost", "lte"));
322
+ if (type === "assert_window_number") {
323
+ if (!hasExpectedValue && minValue === void 0 && maxValue === void 0) {
324
+ throw new Error(`target.setup_actions[${index}] ${type} requires expected_value, min_value, or max_value.`);
325
+ }
326
+ if (hasExpectedValue && numberValue(rawExpectedValue) === void 0) {
327
+ throw new Error(`target.setup_actions[${index}] ${type} expected_value must be a finite number.`);
328
+ }
329
+ }
314
330
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
315
331
  return {
316
332
  type,
@@ -322,7 +338,9 @@ function normalizeSetupAction(input, index) {
322
338
  path,
323
339
  args,
324
340
  expect_return: hasExpectedReturn ? toJsonValue(valueFromOwn(input, "expect_return", "expectReturn", "expected_return", "expectedReturn")) : void 0,
325
- expected_value: hasExpectedValue ? toJsonValue(valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect")) : void 0,
341
+ expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
342
+ min_value: minValue,
343
+ max_value: maxValue,
326
344
  text: stringValue(input.text),
327
345
  pattern: stringValue(input.pattern),
328
346
  flags: stringValue(input.flags),
@@ -2146,6 +2164,10 @@ function setupNumber(value, fallback) {
2146
2164
  const number = Number(value);
2147
2165
  return Number.isFinite(number) && number >= 0 ? number : fallback;
2148
2166
  }
2167
+ function setupFiniteNumber(value) {
2168
+ const number = Number(value);
2169
+ return Number.isFinite(number) ? number : undefined;
2170
+ }
2149
2171
  function setupTextMatches(sample, action) {
2150
2172
  if (action.pattern) {
2151
2173
  try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
@@ -2369,6 +2391,21 @@ async function executeSetupAction(action, ordinal) {
2369
2391
  await page.waitForSelector(action.selector, { state: "visible", timeout });
2370
2392
  return { ...base, ok: true, timeout_ms: timeout };
2371
2393
  }
2394
+ if (type === "press") {
2395
+ const key = String(action.key || "").trim();
2396
+ if (!key) return { ...base, reason: "missing_key" };
2397
+ if (!action.selector) {
2398
+ await page.keyboard.press(key);
2399
+ return { ...base, ok: true, key };
2400
+ }
2401
+ const locator = page.locator(action.selector);
2402
+ const count = await locator.count();
2403
+ if (!count) return { ...base, reason: "selector_not_found", count, key };
2404
+ const targetIndex = Number.isInteger(action.index) ? action.index : 0;
2405
+ if (targetIndex < 0 || targetIndex >= count) return { ...base, reason: "index_out_of_range", count, target_index: targetIndex, key };
2406
+ await locator.nth(targetIndex).press(key, { timeout });
2407
+ return { ...base, ok: true, count, target_index: targetIndex, key };
2408
+ }
2372
2409
  if (type === "local_storage" || type === "session_storage") {
2373
2410
  const value = setupActionValue(action);
2374
2411
  await page.evaluate(({ type, key, value }) => {
@@ -2491,6 +2528,58 @@ async function executeSetupAction(action, ordinal) {
2491
2528
  timeout_ms: timeout,
2492
2529
  };
2493
2530
  }
2531
+ if (type === "assert_window_number") {
2532
+ const path = String(action.path || action.window_path || action.windowPath || "");
2533
+ const expected = setupFiniteNumber(action.expected_value ?? action.expectedValue ?? action.expected ?? action.expect_value ?? action.expectValue ?? action.expect);
2534
+ const minValue = setupFiniteNumber(action.min_value ?? action.minValue ?? action.minimum ?? action.min ?? action.at_least ?? action.atLeast ?? action.gte);
2535
+ const maxValue = setupFiniteNumber(action.max_value ?? action.maxValue ?? action.maximum ?? action.max ?? action.at_most ?? action.atMost ?? action.lte);
2536
+ const hasExpected = expected !== undefined;
2537
+ if (!path) return { ...base, path, reason: "missing_path" };
2538
+ if (!hasExpected && minValue === undefined && maxValue === undefined) return { ...base, path, reason: "missing_number_expectation" };
2539
+ const startedAt = Date.now();
2540
+ let result = null;
2541
+ let lastReason = "path_not_found";
2542
+ while (Date.now() - startedAt <= timeout) {
2543
+ result = await setupReadWindowValue(path);
2544
+ if (result.ok) {
2545
+ const actual = setupFiniteNumber(result.value);
2546
+ if (actual === undefined) {
2547
+ lastReason = "non_numeric_value";
2548
+ } else if (hasExpected && actual !== expected) {
2549
+ lastReason = "unexpected_number";
2550
+ } else if (minValue !== undefined && actual < minValue) {
2551
+ lastReason = "number_below_min";
2552
+ } else if (maxValue !== undefined && actual > maxValue) {
2553
+ lastReason = "number_above_max";
2554
+ } else {
2555
+ return {
2556
+ ...base,
2557
+ ok: true,
2558
+ path,
2559
+ value: actual,
2560
+ expected_value: hasExpected ? expected : undefined,
2561
+ min_value: minValue,
2562
+ max_value: maxValue,
2563
+ timeout_ms: timeout,
2564
+ };
2565
+ }
2566
+ } else {
2567
+ lastReason = result.reason || "path_not_found";
2568
+ }
2569
+ await page.waitForTimeout(100);
2570
+ }
2571
+ return {
2572
+ ...base,
2573
+ path,
2574
+ reason: lastReason,
2575
+ missing_part: result?.missing_part || undefined,
2576
+ value: setupJsonValue(result?.value),
2577
+ expected_value: hasExpected ? expected : undefined,
2578
+ min_value: minValue,
2579
+ max_value: maxValue,
2580
+ timeout_ms: timeout,
2581
+ };
2582
+ }
2494
2583
  if (type === "click") {
2495
2584
  const locator = page.locator(action.selector);
2496
2585
  const count = await locator.count();
@@ -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_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", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "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", "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];
@@ -28,6 +28,8 @@ interface RiddleProofProfileSetupAction {
28
28
  args?: JsonValue[];
29
29
  expect_return?: JsonValue;
30
30
  expected_value?: JsonValue;
31
+ min_value?: number;
32
+ max_value?: number;
31
33
  text?: string;
32
34
  pattern?: string;
33
35
  flags?: string;
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_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", "fill", "set_input_value", "assert_text_visible", "assert_text_absent", "assert_selector_count", "assert_window_value", "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", "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];
@@ -28,6 +28,8 @@ interface RiddleProofProfileSetupAction {
28
28
  args?: JsonValue[];
29
29
  expect_return?: JsonValue;
30
30
  expected_value?: JsonValue;
31
+ min_value?: number;
32
+ max_value?: number;
31
33
  text?: string;
32
34
  pattern?: string;
33
35
  flags?: string;
package/dist/profile.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  resolveRiddleProofProfileTimeoutSec,
20
20
  slugifyRiddleProofProfileName,
21
21
  summarizeRiddleProofProfileResult
22
- } from "./chunk-2JFDTCIC.js";
22
+ } from "./chunk-7ZBK2GQX.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.56",
3
+ "version": "0.7.58",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",