@riddledc/riddle-proof 0.7.55 → 0.7.57

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
@@ -174,6 +174,9 @@ riddle-proof-loop run-profile \
174
174
  Hosted profile runs emit Riddle poll progress to stderr while waiting. Use
175
175
  `--quiet` to suppress progress lines, or `--progress-every-ms` to tune the
176
176
  heartbeat cadence for long route-inventory or workflow profiles.
177
+ Strict Riddle script validation remains on by default; use `--strict=false`
178
+ only for trusted profile-generated scripts when the validator blocks a large
179
+ workflow profile.
177
180
 
178
181
  The package includes a generic starter profile at
179
182
  `examples/profiles/page-content-basic.json`; copy that shape into a repository
@@ -239,7 +242,7 @@ appears only after a picker, tab, login stub, storage seed, form fill,
239
242
  transport control, or other bounded interaction. Supported setup actions are
240
243
  `click`, `fill`, `set_input_value`, `assert_text_visible`,
241
244
  `assert_text_absent`, `assert_selector_count`, `assert_window_value`,
242
- `local_storage`, `session_storage`, `clear_storage`, `wait`,
245
+ `assert_window_number`, `local_storage`, `session_storage`, `clear_storage`, `wait`,
243
246
  `wait_for_selector`, `wait_for_text`, and `window_call`; a failed setup action
244
247
  is recorded as a failed `setup_actions_succeeded` check so the profile cannot
245
248
  pass without reaching the intended state. Text-matched `click` actions prefer
@@ -253,6 +256,9 @@ source link must exist before clicking into the final route, or a canvas app's
253
256
  proof state must expose a terminal flag. `assert_selector_count` accepts
254
257
  `expected_count`; `assert_window_value` accepts `path` / `state_path` plus
255
258
  `expected_value` / `expected` and compares JSON-safe values exactly.
259
+ `assert_window_number` accepts `path` / `state_path` plus `expected_value`,
260
+ `min_value`, or `max_value`, and is useful for canvas-only proof state such as
261
+ distance, elapsed time, score, or retry counters.
256
262
  `local_storage` and `session_storage` accept a `key` plus string `value` or
257
263
  JSON `json` / `value_json`, and can reload the page with `reload: true`.
258
264
  `clear_storage` clears `local`, `session`, or `both` browser storage scopes,
@@ -38,6 +38,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
38
38
  "assert_text_absent",
39
39
  "assert_selector_count",
40
40
  "assert_window_value",
41
+ "assert_window_number",
41
42
  "local_storage",
42
43
  "session_storage",
43
44
  "clear_storage",
@@ -260,7 +261,7 @@ function normalizeSetupAction(input, index) {
260
261
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
261
262
  }
262
263
  const path = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath", "state_path", "statePath");
263
- if ((type === "window_call" || type === "assert_window_value") && !path) {
264
+ if ((type === "window_call" || type === "assert_window_value" || type === "assert_window_number") && !path) {
264
265
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
265
266
  }
266
267
  const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
@@ -268,6 +269,17 @@ function normalizeSetupAction(input, index) {
268
269
  if (type === "assert_window_value" && !hasExpectedValue) {
269
270
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
270
271
  }
272
+ const rawExpectedValue = valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect");
273
+ const minValue = numberValue(valueFromOwn(input, "min_value", "minValue", "minimum", "min", "at_least", "atLeast", "gte"));
274
+ const maxValue = numberValue(valueFromOwn(input, "max_value", "maxValue", "maximum", "max", "at_most", "atMost", "lte"));
275
+ if (type === "assert_window_number") {
276
+ if (!hasExpectedValue && minValue === void 0 && maxValue === void 0) {
277
+ throw new Error(`target.setup_actions[${index}] ${type} requires expected_value, min_value, or max_value.`);
278
+ }
279
+ if (hasExpectedValue && numberValue(rawExpectedValue) === void 0) {
280
+ throw new Error(`target.setup_actions[${index}] ${type} expected_value must be a finite number.`);
281
+ }
282
+ }
271
283
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
272
284
  return {
273
285
  type,
@@ -279,7 +291,9 @@ function normalizeSetupAction(input, index) {
279
291
  path,
280
292
  args,
281
293
  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,
294
+ expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
295
+ min_value: minValue,
296
+ max_value: maxValue,
283
297
  text: stringValue(input.text),
284
298
  pattern: stringValue(input.pattern),
285
299
  flags: stringValue(input.flags),
@@ -2103,6 +2117,10 @@ function setupNumber(value, fallback) {
2103
2117
  const number = Number(value);
2104
2118
  return Number.isFinite(number) && number >= 0 ? number : fallback;
2105
2119
  }
2120
+ function setupFiniteNumber(value) {
2121
+ const number = Number(value);
2122
+ return Number.isFinite(number) ? number : undefined;
2123
+ }
2106
2124
  function setupTextMatches(sample, action) {
2107
2125
  if (action.pattern) {
2108
2126
  try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
@@ -2448,6 +2466,58 @@ async function executeSetupAction(action, ordinal) {
2448
2466
  timeout_ms: timeout,
2449
2467
  };
2450
2468
  }
2469
+ if (type === "assert_window_number") {
2470
+ const path = String(action.path || action.window_path || action.windowPath || "");
2471
+ const expected = setupFiniteNumber(action.expected_value ?? action.expectedValue ?? action.expected ?? action.expect_value ?? action.expectValue ?? action.expect);
2472
+ const minValue = setupFiniteNumber(action.min_value ?? action.minValue ?? action.minimum ?? action.min ?? action.at_least ?? action.atLeast ?? action.gte);
2473
+ const maxValue = setupFiniteNumber(action.max_value ?? action.maxValue ?? action.maximum ?? action.max ?? action.at_most ?? action.atMost ?? action.lte);
2474
+ const hasExpected = expected !== undefined;
2475
+ if (!path) return { ...base, path, reason: "missing_path" };
2476
+ if (!hasExpected && minValue === undefined && maxValue === undefined) return { ...base, path, reason: "missing_number_expectation" };
2477
+ const startedAt = Date.now();
2478
+ let result = null;
2479
+ let lastReason = "path_not_found";
2480
+ while (Date.now() - startedAt <= timeout) {
2481
+ result = await setupReadWindowValue(path);
2482
+ if (result.ok) {
2483
+ const actual = setupFiniteNumber(result.value);
2484
+ if (actual === undefined) {
2485
+ lastReason = "non_numeric_value";
2486
+ } else if (hasExpected && actual !== expected) {
2487
+ lastReason = "unexpected_number";
2488
+ } else if (minValue !== undefined && actual < minValue) {
2489
+ lastReason = "number_below_min";
2490
+ } else if (maxValue !== undefined && actual > maxValue) {
2491
+ lastReason = "number_above_max";
2492
+ } else {
2493
+ return {
2494
+ ...base,
2495
+ ok: true,
2496
+ path,
2497
+ value: actual,
2498
+ expected_value: hasExpected ? expected : undefined,
2499
+ min_value: minValue,
2500
+ max_value: maxValue,
2501
+ timeout_ms: timeout,
2502
+ };
2503
+ }
2504
+ } else {
2505
+ lastReason = result.reason || "path_not_found";
2506
+ }
2507
+ await page.waitForTimeout(100);
2508
+ }
2509
+ return {
2510
+ ...base,
2511
+ path,
2512
+ reason: lastReason,
2513
+ missing_part: result?.missing_part || undefined,
2514
+ value: setupJsonValue(result?.value),
2515
+ expected_value: hasExpected ? expected : undefined,
2516
+ min_value: minValue,
2517
+ max_value: maxValue,
2518
+ timeout_ms: timeout,
2519
+ };
2520
+ }
2451
2521
  if (type === "click") {
2452
2522
  const locator = page.locator(action.selector);
2453
2523
  const count = await locator.count();
package/dist/cli.cjs CHANGED
@@ -6911,6 +6911,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
6911
6911
  "assert_text_absent",
6912
6912
  "assert_selector_count",
6913
6913
  "assert_window_value",
6914
+ "assert_window_number",
6914
6915
  "local_storage",
6915
6916
  "session_storage",
6916
6917
  "clear_storage",
@@ -7133,7 +7134,7 @@ function normalizeSetupAction(input, index) {
7133
7134
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
7134
7135
  }
7135
7136
  const path7 = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath", "state_path", "statePath");
7136
- if ((type === "window_call" || type === "assert_window_value") && !path7) {
7137
+ if ((type === "window_call" || type === "assert_window_value" || type === "assert_window_number") && !path7) {
7137
7138
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
7138
7139
  }
7139
7140
  const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
@@ -7141,6 +7142,17 @@ function normalizeSetupAction(input, index) {
7141
7142
  if (type === "assert_window_value" && !hasExpectedValue) {
7142
7143
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
7143
7144
  }
7145
+ const rawExpectedValue = valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect");
7146
+ const minValue = numberValue(valueFromOwn(input, "min_value", "minValue", "minimum", "min", "at_least", "atLeast", "gte"));
7147
+ const maxValue = numberValue(valueFromOwn(input, "max_value", "maxValue", "maximum", "max", "at_most", "atMost", "lte"));
7148
+ if (type === "assert_window_number") {
7149
+ if (!hasExpectedValue && minValue === void 0 && maxValue === void 0) {
7150
+ throw new Error(`target.setup_actions[${index}] ${type} requires expected_value, min_value, or max_value.`);
7151
+ }
7152
+ if (hasExpectedValue && numberValue(rawExpectedValue) === void 0) {
7153
+ throw new Error(`target.setup_actions[${index}] ${type} expected_value must be a finite number.`);
7154
+ }
7155
+ }
7144
7156
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
7145
7157
  return {
7146
7158
  type,
@@ -7152,7 +7164,9 @@ function normalizeSetupAction(input, index) {
7152
7164
  path: path7,
7153
7165
  args,
7154
7166
  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,
7167
+ expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
7168
+ min_value: minValue,
7169
+ max_value: maxValue,
7156
7170
  text: stringValue2(input.text),
7157
7171
  pattern: stringValue2(input.pattern),
7158
7172
  flags: stringValue2(input.flags),
@@ -8960,6 +8974,10 @@ function setupNumber(value, fallback) {
8960
8974
  const number = Number(value);
8961
8975
  return Number.isFinite(number) && number >= 0 ? number : fallback;
8962
8976
  }
8977
+ function setupFiniteNumber(value) {
8978
+ const number = Number(value);
8979
+ return Number.isFinite(number) ? number : undefined;
8980
+ }
8963
8981
  function setupTextMatches(sample, action) {
8964
8982
  if (action.pattern) {
8965
8983
  try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
@@ -9305,6 +9323,58 @@ async function executeSetupAction(action, ordinal) {
9305
9323
  timeout_ms: timeout,
9306
9324
  };
9307
9325
  }
9326
+ if (type === "assert_window_number") {
9327
+ const path = String(action.path || action.window_path || action.windowPath || "");
9328
+ const expected = setupFiniteNumber(action.expected_value ?? action.expectedValue ?? action.expected ?? action.expect_value ?? action.expectValue ?? action.expect);
9329
+ const minValue = setupFiniteNumber(action.min_value ?? action.minValue ?? action.minimum ?? action.min ?? action.at_least ?? action.atLeast ?? action.gte);
9330
+ const maxValue = setupFiniteNumber(action.max_value ?? action.maxValue ?? action.maximum ?? action.max ?? action.at_most ?? action.atMost ?? action.lte);
9331
+ const hasExpected = expected !== undefined;
9332
+ if (!path) return { ...base, path, reason: "missing_path" };
9333
+ if (!hasExpected && minValue === undefined && maxValue === undefined) return { ...base, path, reason: "missing_number_expectation" };
9334
+ const startedAt = Date.now();
9335
+ let result = null;
9336
+ let lastReason = "path_not_found";
9337
+ while (Date.now() - startedAt <= timeout) {
9338
+ result = await setupReadWindowValue(path);
9339
+ if (result.ok) {
9340
+ const actual = setupFiniteNumber(result.value);
9341
+ if (actual === undefined) {
9342
+ lastReason = "non_numeric_value";
9343
+ } else if (hasExpected && actual !== expected) {
9344
+ lastReason = "unexpected_number";
9345
+ } else if (minValue !== undefined && actual < minValue) {
9346
+ lastReason = "number_below_min";
9347
+ } else if (maxValue !== undefined && actual > maxValue) {
9348
+ lastReason = "number_above_max";
9349
+ } else {
9350
+ return {
9351
+ ...base,
9352
+ ok: true,
9353
+ path,
9354
+ value: actual,
9355
+ expected_value: hasExpected ? expected : undefined,
9356
+ min_value: minValue,
9357
+ max_value: maxValue,
9358
+ timeout_ms: timeout,
9359
+ };
9360
+ }
9361
+ } else {
9362
+ lastReason = result.reason || "path_not_found";
9363
+ }
9364
+ await page.waitForTimeout(100);
9365
+ }
9366
+ return {
9367
+ ...base,
9368
+ path,
9369
+ reason: lastReason,
9370
+ missing_part: result?.missing_part || undefined,
9371
+ value: setupJsonValue(result?.value),
9372
+ expected_value: hasExpected ? expected : undefined,
9373
+ min_value: minValue,
9374
+ max_value: maxValue,
9375
+ timeout_ms: timeout,
9376
+ };
9377
+ }
9308
9378
  if (type === "click") {
9309
9379
  const locator = page.locator(action.selector);
9310
9380
  const count = await locator.count();
@@ -10276,7 +10346,7 @@ function usage() {
10276
10346
  " riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
10277
10347
  " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
10278
10348
  " riddle-proof-loop status --state-path <path>",
10279
- " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--output <dir>] [--quiet]",
10349
+ " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false] [--output <dir>] [--quiet]",
10280
10350
  " riddle-proof-loop riddle-preview-deploy <build-dir> <label>",
10281
10351
  " riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
10282
10352
  " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
@@ -10634,6 +10704,7 @@ async function runProfileForCli(profile, options) {
10634
10704
  profile,
10635
10705
  optionString(options, "timeout") ? Number(optionString(options, "timeout")) : void 0
10636
10706
  ),
10707
+ strict: optionBoolean(options, "strict"),
10637
10708
  sync: options.sync === true ? true : void 0
10638
10709
  });
10639
10710
  } catch (error) {
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-H5LDZKGN.js";
14
14
  import {
15
15
  createRiddleApiClient,
16
16
  parseRiddleViewport
@@ -44,7 +44,7 @@ function usage() {
44
44
  " riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
45
45
  " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
46
46
  " riddle-proof-loop status --state-path <path>",
47
- " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--output <dir>] [--quiet]",
47
+ " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false] [--output <dir>] [--quiet]",
48
48
  " riddle-proof-loop riddle-preview-deploy <build-dir> <label>",
49
49
  " riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
50
50
  " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
@@ -402,6 +402,7 @@ async function runProfileForCli(profile, options) {
402
402
  profile,
403
403
  optionString(options, "timeout") ? Number(optionString(options, "timeout")) : void 0
404
404
  ),
405
+ strict: optionBoolean(options, "strict"),
405
406
  sync: options.sync === true ? true : void 0
406
407
  });
407
408
  } catch (error) {
package/dist/index.cjs CHANGED
@@ -8752,6 +8752,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
8752
8752
  "assert_text_absent",
8753
8753
  "assert_selector_count",
8754
8754
  "assert_window_value",
8755
+ "assert_window_number",
8755
8756
  "local_storage",
8756
8757
  "session_storage",
8757
8758
  "clear_storage",
@@ -8974,7 +8975,7 @@ function normalizeSetupAction(input, index) {
8974
8975
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
8975
8976
  }
8976
8977
  const path6 = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath", "state_path", "statePath");
8977
- if ((type === "window_call" || type === "assert_window_value") && !path6) {
8978
+ if ((type === "window_call" || type === "assert_window_value" || type === "assert_window_number") && !path6) {
8978
8979
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
8979
8980
  }
8980
8981
  const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
@@ -8982,6 +8983,17 @@ function normalizeSetupAction(input, index) {
8982
8983
  if (type === "assert_window_value" && !hasExpectedValue) {
8983
8984
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
8984
8985
  }
8986
+ const rawExpectedValue = valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect");
8987
+ const minValue = numberValue3(valueFromOwn(input, "min_value", "minValue", "minimum", "min", "at_least", "atLeast", "gte"));
8988
+ const maxValue = numberValue3(valueFromOwn(input, "max_value", "maxValue", "maximum", "max", "at_most", "atMost", "lte"));
8989
+ if (type === "assert_window_number") {
8990
+ if (!hasExpectedValue && minValue === void 0 && maxValue === void 0) {
8991
+ throw new Error(`target.setup_actions[${index}] ${type} requires expected_value, min_value, or max_value.`);
8992
+ }
8993
+ if (hasExpectedValue && numberValue3(rawExpectedValue) === void 0) {
8994
+ throw new Error(`target.setup_actions[${index}] ${type} expected_value must be a finite number.`);
8995
+ }
8996
+ }
8985
8997
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
8986
8998
  return {
8987
8999
  type,
@@ -8993,7 +9005,9 @@ function normalizeSetupAction(input, index) {
8993
9005
  path: path6,
8994
9006
  args,
8995
9007
  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,
9008
+ expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
9009
+ min_value: minValue,
9010
+ max_value: maxValue,
8997
9011
  text: stringValue5(input.text),
8998
9012
  pattern: stringValue5(input.pattern),
8999
9013
  flags: stringValue5(input.flags),
@@ -10817,6 +10831,10 @@ function setupNumber(value, fallback) {
10817
10831
  const number = Number(value);
10818
10832
  return Number.isFinite(number) && number >= 0 ? number : fallback;
10819
10833
  }
10834
+ function setupFiniteNumber(value) {
10835
+ const number = Number(value);
10836
+ return Number.isFinite(number) ? number : undefined;
10837
+ }
10820
10838
  function setupTextMatches(sample, action) {
10821
10839
  if (action.pattern) {
10822
10840
  try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
@@ -11162,6 +11180,58 @@ async function executeSetupAction(action, ordinal) {
11162
11180
  timeout_ms: timeout,
11163
11181
  };
11164
11182
  }
11183
+ if (type === "assert_window_number") {
11184
+ const path = String(action.path || action.window_path || action.windowPath || "");
11185
+ const expected = setupFiniteNumber(action.expected_value ?? action.expectedValue ?? action.expected ?? action.expect_value ?? action.expectValue ?? action.expect);
11186
+ const minValue = setupFiniteNumber(action.min_value ?? action.minValue ?? action.minimum ?? action.min ?? action.at_least ?? action.atLeast ?? action.gte);
11187
+ const maxValue = setupFiniteNumber(action.max_value ?? action.maxValue ?? action.maximum ?? action.max ?? action.at_most ?? action.atMost ?? action.lte);
11188
+ const hasExpected = expected !== undefined;
11189
+ if (!path) return { ...base, path, reason: "missing_path" };
11190
+ if (!hasExpected && minValue === undefined && maxValue === undefined) return { ...base, path, reason: "missing_number_expectation" };
11191
+ const startedAt = Date.now();
11192
+ let result = null;
11193
+ let lastReason = "path_not_found";
11194
+ while (Date.now() - startedAt <= timeout) {
11195
+ result = await setupReadWindowValue(path);
11196
+ if (result.ok) {
11197
+ const actual = setupFiniteNumber(result.value);
11198
+ if (actual === undefined) {
11199
+ lastReason = "non_numeric_value";
11200
+ } else if (hasExpected && actual !== expected) {
11201
+ lastReason = "unexpected_number";
11202
+ } else if (minValue !== undefined && actual < minValue) {
11203
+ lastReason = "number_below_min";
11204
+ } else if (maxValue !== undefined && actual > maxValue) {
11205
+ lastReason = "number_above_max";
11206
+ } else {
11207
+ return {
11208
+ ...base,
11209
+ ok: true,
11210
+ path,
11211
+ value: actual,
11212
+ expected_value: hasExpected ? expected : undefined,
11213
+ min_value: minValue,
11214
+ max_value: maxValue,
11215
+ timeout_ms: timeout,
11216
+ };
11217
+ }
11218
+ } else {
11219
+ lastReason = result.reason || "path_not_found";
11220
+ }
11221
+ await page.waitForTimeout(100);
11222
+ }
11223
+ return {
11224
+ ...base,
11225
+ path,
11226
+ reason: lastReason,
11227
+ missing_part: result?.missing_part || undefined,
11228
+ value: setupJsonValue(result?.value),
11229
+ expected_value: hasExpected ? expected : undefined,
11230
+ min_value: minValue,
11231
+ max_value: maxValue,
11232
+ timeout_ms: timeout,
11233
+ };
11234
+ }
11165
11235
  if (type === "click") {
11166
11236
  const locator = page.locator(action.selector);
11167
11237
  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-H5LDZKGN.js";
62
62
  import {
63
63
  DEFAULT_RIDDLE_API_BASE_URL,
64
64
  DEFAULT_RIDDLE_API_KEY_FILE,
package/dist/profile.cjs CHANGED
@@ -81,6 +81,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
81
81
  "assert_text_absent",
82
82
  "assert_selector_count",
83
83
  "assert_window_value",
84
+ "assert_window_number",
84
85
  "local_storage",
85
86
  "session_storage",
86
87
  "clear_storage",
@@ -303,7 +304,7 @@ function normalizeSetupAction(input, index) {
303
304
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
304
305
  }
305
306
  const path = stringFromOwn(input, "path", "function_path", "functionPath", "window_path", "windowPath", "state_path", "statePath");
306
- if ((type === "window_call" || type === "assert_window_value") && !path) {
307
+ if ((type === "window_call" || type === "assert_window_value" || type === "assert_window_number") && !path) {
307
308
  throw new Error(`target.setup_actions[${index}] ${type} requires path.`);
308
309
  }
309
310
  const args = type === "window_call" ? normalizeSetupActionArgs(input, index) : void 0;
@@ -311,6 +312,17 @@ function normalizeSetupAction(input, index) {
311
312
  if (type === "assert_window_value" && !hasExpectedValue) {
312
313
  throw new Error(`target.setup_actions[${index}] ${type} requires expected_value.`);
313
314
  }
315
+ const rawExpectedValue = valueFromOwn(input, "expected_value", "expectedValue", "expected", "expect_value", "expectValue", "expect");
316
+ const minValue = numberValue(valueFromOwn(input, "min_value", "minValue", "minimum", "min", "at_least", "atLeast", "gte"));
317
+ const maxValue = numberValue(valueFromOwn(input, "max_value", "maxValue", "maximum", "max", "at_most", "atMost", "lte"));
318
+ if (type === "assert_window_number") {
319
+ if (!hasExpectedValue && minValue === void 0 && maxValue === void 0) {
320
+ throw new Error(`target.setup_actions[${index}] ${type} requires expected_value, min_value, or max_value.`);
321
+ }
322
+ if (hasExpectedValue && numberValue(rawExpectedValue) === void 0) {
323
+ throw new Error(`target.setup_actions[${index}] ${type} expected_value must be a finite number.`);
324
+ }
325
+ }
314
326
  const hasExpectedReturn = hasOwn(input, "expect_return") || hasOwn(input, "expectReturn") || hasOwn(input, "expected_return") || hasOwn(input, "expectedReturn");
315
327
  return {
316
328
  type,
@@ -322,7 +334,9 @@ function normalizeSetupAction(input, index) {
322
334
  path,
323
335
  args,
324
336
  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,
337
+ expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
338
+ min_value: minValue,
339
+ max_value: maxValue,
326
340
  text: stringValue(input.text),
327
341
  pattern: stringValue(input.pattern),
328
342
  flags: stringValue(input.flags),
@@ -2146,6 +2160,10 @@ function setupNumber(value, fallback) {
2146
2160
  const number = Number(value);
2147
2161
  return Number.isFinite(number) && number >= 0 ? number : fallback;
2148
2162
  }
2163
+ function setupFiniteNumber(value) {
2164
+ const number = Number(value);
2165
+ return Number.isFinite(number) ? number : undefined;
2166
+ }
2149
2167
  function setupTextMatches(sample, action) {
2150
2168
  if (action.pattern) {
2151
2169
  try { return new RegExp(action.pattern, action.flags || "").test(sample || ""); } catch { return false; }
@@ -2491,6 +2509,58 @@ async function executeSetupAction(action, ordinal) {
2491
2509
  timeout_ms: timeout,
2492
2510
  };
2493
2511
  }
2512
+ if (type === "assert_window_number") {
2513
+ const path = String(action.path || action.window_path || action.windowPath || "");
2514
+ const expected = setupFiniteNumber(action.expected_value ?? action.expectedValue ?? action.expected ?? action.expect_value ?? action.expectValue ?? action.expect);
2515
+ const minValue = setupFiniteNumber(action.min_value ?? action.minValue ?? action.minimum ?? action.min ?? action.at_least ?? action.atLeast ?? action.gte);
2516
+ const maxValue = setupFiniteNumber(action.max_value ?? action.maxValue ?? action.maximum ?? action.max ?? action.at_most ?? action.atMost ?? action.lte);
2517
+ const hasExpected = expected !== undefined;
2518
+ if (!path) return { ...base, path, reason: "missing_path" };
2519
+ if (!hasExpected && minValue === undefined && maxValue === undefined) return { ...base, path, reason: "missing_number_expectation" };
2520
+ const startedAt = Date.now();
2521
+ let result = null;
2522
+ let lastReason = "path_not_found";
2523
+ while (Date.now() - startedAt <= timeout) {
2524
+ result = await setupReadWindowValue(path);
2525
+ if (result.ok) {
2526
+ const actual = setupFiniteNumber(result.value);
2527
+ if (actual === undefined) {
2528
+ lastReason = "non_numeric_value";
2529
+ } else if (hasExpected && actual !== expected) {
2530
+ lastReason = "unexpected_number";
2531
+ } else if (minValue !== undefined && actual < minValue) {
2532
+ lastReason = "number_below_min";
2533
+ } else if (maxValue !== undefined && actual > maxValue) {
2534
+ lastReason = "number_above_max";
2535
+ } else {
2536
+ return {
2537
+ ...base,
2538
+ ok: true,
2539
+ path,
2540
+ value: actual,
2541
+ expected_value: hasExpected ? expected : undefined,
2542
+ min_value: minValue,
2543
+ max_value: maxValue,
2544
+ timeout_ms: timeout,
2545
+ };
2546
+ }
2547
+ } else {
2548
+ lastReason = result.reason || "path_not_found";
2549
+ }
2550
+ await page.waitForTimeout(100);
2551
+ }
2552
+ return {
2553
+ ...base,
2554
+ path,
2555
+ reason: lastReason,
2556
+ missing_part: result?.missing_part || undefined,
2557
+ value: setupJsonValue(result?.value),
2558
+ expected_value: hasExpected ? expected : undefined,
2559
+ min_value: minValue,
2560
+ max_value: maxValue,
2561
+ timeout_ms: timeout,
2562
+ };
2563
+ }
2494
2564
  if (type === "click") {
2495
2565
  const locator = page.locator(action.selector);
2496
2566
  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", "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", "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-H5LDZKGN.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.55",
3
+ "version": "0.7.57",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",