@riddledc/riddle-proof 0.7.200 → 0.7.202
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 +36 -9
- package/dist/{chunk-FNVDZCVZ.js → chunk-OUZKZ5U4.js} +12 -0
- package/dist/cli.cjs +245 -10
- package/dist/cli.js +234 -11
- package/dist/index.cjs +12 -0
- package/dist/index.js +1 -1
- package/dist/profile.cjs +12 -0
- package/dist/profile.d.cts +1 -0
- package/dist/profile.d.ts +1 -0
- package/dist/profile.js +1 -1
- package/dist/proof-run-engine.d.cts +3 -3
- package/dist/proof-run-engine.d.ts +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -202,6 +202,31 @@ generic inline-script warning threshold. Use `--strict=true` when you
|
|
|
202
202
|
deliberately want Riddle's non-critical script-safety warnings to block the run.
|
|
203
203
|
Critical script-safety violations remain blocked by Riddle either way.
|
|
204
204
|
|
|
205
|
+
Use `--viewport-name <name>` to run only one named viewport from a
|
|
206
|
+
multi-viewport profile while preserving viewport-scoped setup actions and
|
|
207
|
+
checks:
|
|
208
|
+
|
|
209
|
+
```sh
|
|
210
|
+
riddle-proof-loop run-profile \
|
|
211
|
+
--profile .riddle-proof/profiles/pricing.json \
|
|
212
|
+
--url https://example.com \
|
|
213
|
+
--viewport-name ipad-mini \
|
|
214
|
+
--output artifacts/riddle-proof/pricing-ipad-mini
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
When `--output` / `--output-dir` is set, hosted profile runs write
|
|
218
|
+
`riddle-job.json` as soon as Riddle returns a job id. If the local process is
|
|
219
|
+
interrupted or pruned, recover the profile artifacts from the hosted job:
|
|
220
|
+
|
|
221
|
+
```sh
|
|
222
|
+
riddle-proof-loop run-profile recover \
|
|
223
|
+
--profile .riddle-proof/profiles/pricing.json \
|
|
224
|
+
--url https://example.com \
|
|
225
|
+
--job job_abc123 \
|
|
226
|
+
--viewport-name ipad-mini \
|
|
227
|
+
--output artifacts/riddle-proof/pricing-ipad-mini-recovered
|
|
228
|
+
```
|
|
229
|
+
|
|
205
230
|
When promoting proof artifacts into a durable public profile, avoid guessing
|
|
206
231
|
which backend or runner tokens are preserved inside `proof.json`. Derive the
|
|
207
232
|
`body_contains` fragments from the artifact body first:
|
|
@@ -441,11 +466,12 @@ until a browser-state predicate is satisfied. It accepts the same selector,
|
|
|
441
466
|
coordinate, and pointer options as `tap`, plus `until_path`,
|
|
442
467
|
`until_expected_value`, `max_taps` / `max_calls` from 1 to 100, and optional
|
|
443
468
|
`interval_ms`. Set `tap_burst_size` from 1 to 100 when gameplay needs several
|
|
444
|
-
fast taps before the next predicate check
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
469
|
+
fast taps before the next predicate check, and `settle_ms` when the app needs a
|
|
470
|
+
short post-burst frame/update delay before the predicate is trustworthy. The
|
|
471
|
+
action stops early when the predicate matches and records one compact receipt
|
|
472
|
+
with `tap_count`, `condition_check_count`, `settle_ms`, `elapsed_ms`, final
|
|
473
|
+
`until_value`, and input dispatch details, so long canvas interaction loops do
|
|
474
|
+
not need dozens of repeated setup actions.
|
|
449
475
|
Use `set_range_value` for HTML range inputs and React-controlled sliders. It
|
|
450
476
|
accepts aliases such as `set-slider-value`, requires `selector` plus `value`,
|
|
451
477
|
uses the native input value setter, dispatches bubbling `input` and `change`
|
|
@@ -543,10 +569,11 @@ and `click_count_value_total`. Repeated selector runs such as long gameplay
|
|
|
543
569
|
button loops are also grouped as compact `same-selector` click-sequence
|
|
544
570
|
receipts with click totals and ordinals. `tap_until` actions are summarized as
|
|
545
571
|
one compact receipt with total taps, optional burst size, predicate-check count,
|
|
546
|
-
elapsed time, and the final predicate value, which is the
|
|
547
|
-
long canvas gameplay loops. Setup receipt sampling favors
|
|
548
|
-
per-viewport receipts before filling remaining space, so
|
|
549
|
-
such as terminal or restart remain visible in compact
|
|
572
|
+
optional settle time, elapsed time, and the final predicate value, which is the
|
|
573
|
+
preferred shape for long canvas gameplay loops. Setup receipt sampling favors
|
|
574
|
+
both first and last per-viewport receipts before filling remaining space, so
|
|
575
|
+
late lifecycle phases such as terminal or restart remain visible in compact
|
|
576
|
+
summaries.
|
|
550
577
|
|
|
551
578
|
`target.timeout_sec` is optional. Use it for known-heavy profile targets so the
|
|
552
579
|
profile carries its own hosted Riddle worker budget; an explicit CLI `--timeout`
|
|
@@ -635,6 +635,7 @@ function profileSetupTapUntilReceipts(results) {
|
|
|
635
635
|
max_taps: result.max_taps ?? result.max_calls ?? null,
|
|
636
636
|
tap_burst_size: result.tap_burst_size ?? null,
|
|
637
637
|
condition_check_count: result.condition_check_count ?? null,
|
|
638
|
+
settle_ms: result.settle_ms ?? null,
|
|
638
639
|
elapsed_ms: result.elapsed_ms ?? null,
|
|
639
640
|
interval_ms: result.interval_ms ?? null,
|
|
640
641
|
timeout_ms: result.timeout_ms ?? null,
|
|
@@ -1280,6 +1281,10 @@ function normalizeSetupAction(input, index) {
|
|
|
1280
1281
|
if (type === "tap_until" && tapBurstSize !== void 0 && (!Number.isInteger(tapBurstSize) || tapBurstSize < 1 || tapBurstSize > 100)) {
|
|
1281
1282
|
throw new Error(`target.setup_actions[${index}].tap_burst_size must be an integer from 1 to 100.`);
|
|
1282
1283
|
}
|
|
1284
|
+
const settleMs = type === "tap_until" ? numberValue(valueFromOwn(input, "settle_ms", "settleMs", "predicate_settle_ms", "predicateSettleMs", "post_burst_wait_ms", "postBurstWaitMs", "after_burst_ms", "afterBurstMs", "settle_after_tap_ms", "settleAfterTapMs")) : void 0;
|
|
1285
|
+
if (type === "tap_until" && settleMs !== void 0 && (!Number.isInteger(settleMs) || settleMs < 0 || settleMs > 1e4)) {
|
|
1286
|
+
throw new Error(`target.setup_actions[${index}].settle_ms must be an integer from 0 to 10000.`);
|
|
1287
|
+
}
|
|
1283
1288
|
const intervalMs = numberValue(valueFromOwn(input, "interval_ms", "intervalMs", "poll_ms", "pollMs", "call_interval_ms", "callIntervalMs"));
|
|
1284
1289
|
if ((type === "window_call_until" || type === "tap_until") && intervalMs !== void 0 && (!Number.isInteger(intervalMs) || intervalMs < 0 || intervalMs > 5e3)) {
|
|
1285
1290
|
throw new Error(`target.setup_actions[${index}].interval_ms must be an integer from 0 to 5000.`);
|
|
@@ -1328,6 +1333,7 @@ function normalizeSetupAction(input, index) {
|
|
|
1328
1333
|
until_expected_value: hasUntilExpectedValue ? toJsonValue(valueFromOwn(input, "until_expected_value", "untilExpectedValue", "until_expected", "untilExpected", "until_value", "untilValue", "expected_value", "expectedValue", "expected")) : void 0,
|
|
1329
1334
|
max_calls: maxCalls,
|
|
1330
1335
|
tap_burst_size: tapBurstSize,
|
|
1336
|
+
settle_ms: settleMs,
|
|
1331
1337
|
interval_ms: intervalMs,
|
|
1332
1338
|
expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
|
|
1333
1339
|
min_value: minValue,
|
|
@@ -4569,6 +4575,7 @@ function profileSetupTapUntilReceipts(results) {
|
|
|
4569
4575
|
max_taps: result.max_taps ?? result.max_calls ?? null,
|
|
4570
4576
|
tap_burst_size: result.tap_burst_size ?? null,
|
|
4571
4577
|
condition_check_count: result.condition_check_count ?? null,
|
|
4578
|
+
settle_ms: result.settle_ms ?? null,
|
|
4572
4579
|
elapsed_ms: result.elapsed_ms ?? null,
|
|
4573
4580
|
interval_ms: result.interval_ms ?? null,
|
|
4574
4581
|
timeout_ms: result.timeout_ms ?? null,
|
|
@@ -6560,6 +6567,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
6560
6567
|
if (!hasUntilExpected) return { ...base, until_path: untilPath, reason: "missing_until_expected_value" };
|
|
6561
6568
|
const maxTaps = Math.min(100, Math.max(1, Math.floor(setupNumber(action.max_taps ?? action.maxTaps ?? action.tap_limit ?? action.tapLimit ?? action.max_calls ?? action.maxCalls ?? action.max_attempts ?? action.maxAttempts ?? action.attempts, 1) || 1)));
|
|
6562
6569
|
const tapBurstSize = Math.min(maxTaps, Math.min(100, Math.max(1, Math.floor(setupNumber(action.tap_burst_size ?? action.tapBurstSize ?? action.burst_size ?? action.burstSize ?? action.check_every_taps ?? action.checkEveryTaps ?? action.predicate_interval_taps ?? action.predicateIntervalTaps, 1) || 1))));
|
|
6570
|
+
const settleMs = Math.min(10000, Math.max(0, Math.floor(setupNumber(action.settle_ms ?? action.settleMs ?? action.predicate_settle_ms ?? action.predicateSettleMs ?? action.post_burst_wait_ms ?? action.postBurstWaitMs ?? action.after_burst_ms ?? action.afterBurstMs ?? action.settle_after_tap_ms ?? action.settleAfterTapMs, 0) || 0)));
|
|
6563
6571
|
const intervalMs = Math.min(5000, Math.max(0, Math.floor(setupNumber(action.interval_ms ?? action.intervalMs ?? action.poll_ms ?? action.pollMs ?? action.tap_interval_ms ?? action.tapIntervalMs, 100) || 0)));
|
|
6564
6572
|
const scope = await setupActionScope(action, timeout);
|
|
6565
6573
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
@@ -6585,6 +6593,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
6585
6593
|
max_calls: maxTaps,
|
|
6586
6594
|
tap_burst_size: tapBurstSize,
|
|
6587
6595
|
condition_check_count: conditionCheckCount,
|
|
6596
|
+
settle_ms: settleMs,
|
|
6588
6597
|
elapsed_ms: elapsedMs,
|
|
6589
6598
|
interval_ms: intervalMs,
|
|
6590
6599
|
timeout_ms: timeout,
|
|
@@ -6597,6 +6606,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
6597
6606
|
tapCount += 1;
|
|
6598
6607
|
if (tapCount < maxTaps && burstIndex < burstCount - 1 && intervalMs) await page.waitForTimeout(intervalMs);
|
|
6599
6608
|
}
|
|
6609
|
+
if (settleMs) await page.waitForTimeout(settleMs);
|
|
6600
6610
|
lastPredicateResult = await setupReadWindowValue(scope.context, untilPath);
|
|
6601
6611
|
conditionCheckCount += 1;
|
|
6602
6612
|
if (lastPredicateResult.ok && setupValuesEqual(lastPredicateResult.value, untilExpected)) {
|
|
@@ -6614,6 +6624,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
6614
6624
|
max_calls: maxTaps,
|
|
6615
6625
|
tap_burst_size: tapBurstSize,
|
|
6616
6626
|
condition_check_count: conditionCheckCount,
|
|
6627
|
+
settle_ms: settleMs,
|
|
6617
6628
|
elapsed_ms: elapsedMs,
|
|
6618
6629
|
interval_ms: intervalMs,
|
|
6619
6630
|
timeout_ms: timeout,
|
|
@@ -6634,6 +6645,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
6634
6645
|
max_calls: maxTaps,
|
|
6635
6646
|
tap_burst_size: tapBurstSize,
|
|
6636
6647
|
condition_check_count: conditionCheckCount,
|
|
6648
|
+
settle_ms: settleMs,
|
|
6637
6649
|
elapsed_ms: elapsedMs,
|
|
6638
6650
|
interval_ms: intervalMs,
|
|
6639
6651
|
timeout_ms: timeout,
|
package/dist/cli.cjs
CHANGED
|
@@ -7592,6 +7592,7 @@ function profileSetupTapUntilReceipts(results) {
|
|
|
7592
7592
|
max_taps: result.max_taps ?? result.max_calls ?? null,
|
|
7593
7593
|
tap_burst_size: result.tap_burst_size ?? null,
|
|
7594
7594
|
condition_check_count: result.condition_check_count ?? null,
|
|
7595
|
+
settle_ms: result.settle_ms ?? null,
|
|
7595
7596
|
elapsed_ms: result.elapsed_ms ?? null,
|
|
7596
7597
|
interval_ms: result.interval_ms ?? null,
|
|
7597
7598
|
timeout_ms: result.timeout_ms ?? null,
|
|
@@ -8237,6 +8238,10 @@ function normalizeSetupAction(input, index) {
|
|
|
8237
8238
|
if (type === "tap_until" && tapBurstSize !== void 0 && (!Number.isInteger(tapBurstSize) || tapBurstSize < 1 || tapBurstSize > 100)) {
|
|
8238
8239
|
throw new Error(`target.setup_actions[${index}].tap_burst_size must be an integer from 1 to 100.`);
|
|
8239
8240
|
}
|
|
8241
|
+
const settleMs = type === "tap_until" ? numberValue(valueFromOwn(input, "settle_ms", "settleMs", "predicate_settle_ms", "predicateSettleMs", "post_burst_wait_ms", "postBurstWaitMs", "after_burst_ms", "afterBurstMs", "settle_after_tap_ms", "settleAfterTapMs")) : void 0;
|
|
8242
|
+
if (type === "tap_until" && settleMs !== void 0 && (!Number.isInteger(settleMs) || settleMs < 0 || settleMs > 1e4)) {
|
|
8243
|
+
throw new Error(`target.setup_actions[${index}].settle_ms must be an integer from 0 to 10000.`);
|
|
8244
|
+
}
|
|
8240
8245
|
const intervalMs = numberValue(valueFromOwn(input, "interval_ms", "intervalMs", "poll_ms", "pollMs", "call_interval_ms", "callIntervalMs"));
|
|
8241
8246
|
if ((type === "window_call_until" || type === "tap_until") && intervalMs !== void 0 && (!Number.isInteger(intervalMs) || intervalMs < 0 || intervalMs > 5e3)) {
|
|
8242
8247
|
throw new Error(`target.setup_actions[${index}].interval_ms must be an integer from 0 to 5000.`);
|
|
@@ -8285,6 +8290,7 @@ function normalizeSetupAction(input, index) {
|
|
|
8285
8290
|
until_expected_value: hasUntilExpectedValue ? toJsonValue(valueFromOwn(input, "until_expected_value", "untilExpectedValue", "until_expected", "untilExpected", "until_value", "untilValue", "expected_value", "expectedValue", "expected")) : void 0,
|
|
8286
8291
|
max_calls: maxCalls,
|
|
8287
8292
|
tap_burst_size: tapBurstSize,
|
|
8293
|
+
settle_ms: settleMs,
|
|
8288
8294
|
interval_ms: intervalMs,
|
|
8289
8295
|
expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
|
|
8290
8296
|
min_value: minValue,
|
|
@@ -11510,6 +11516,7 @@ function profileSetupTapUntilReceipts(results) {
|
|
|
11510
11516
|
max_taps: result.max_taps ?? result.max_calls ?? null,
|
|
11511
11517
|
tap_burst_size: result.tap_burst_size ?? null,
|
|
11512
11518
|
condition_check_count: result.condition_check_count ?? null,
|
|
11519
|
+
settle_ms: result.settle_ms ?? null,
|
|
11513
11520
|
elapsed_ms: result.elapsed_ms ?? null,
|
|
11514
11521
|
interval_ms: result.interval_ms ?? null,
|
|
11515
11522
|
timeout_ms: result.timeout_ms ?? null,
|
|
@@ -13501,6 +13508,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
13501
13508
|
if (!hasUntilExpected) return { ...base, until_path: untilPath, reason: "missing_until_expected_value" };
|
|
13502
13509
|
const maxTaps = Math.min(100, Math.max(1, Math.floor(setupNumber(action.max_taps ?? action.maxTaps ?? action.tap_limit ?? action.tapLimit ?? action.max_calls ?? action.maxCalls ?? action.max_attempts ?? action.maxAttempts ?? action.attempts, 1) || 1)));
|
|
13503
13510
|
const tapBurstSize = Math.min(maxTaps, Math.min(100, Math.max(1, Math.floor(setupNumber(action.tap_burst_size ?? action.tapBurstSize ?? action.burst_size ?? action.burstSize ?? action.check_every_taps ?? action.checkEveryTaps ?? action.predicate_interval_taps ?? action.predicateIntervalTaps, 1) || 1))));
|
|
13511
|
+
const settleMs = Math.min(10000, Math.max(0, Math.floor(setupNumber(action.settle_ms ?? action.settleMs ?? action.predicate_settle_ms ?? action.predicateSettleMs ?? action.post_burst_wait_ms ?? action.postBurstWaitMs ?? action.after_burst_ms ?? action.afterBurstMs ?? action.settle_after_tap_ms ?? action.settleAfterTapMs, 0) || 0)));
|
|
13504
13512
|
const intervalMs = Math.min(5000, Math.max(0, Math.floor(setupNumber(action.interval_ms ?? action.intervalMs ?? action.poll_ms ?? action.pollMs ?? action.tap_interval_ms ?? action.tapIntervalMs, 100) || 0)));
|
|
13505
13513
|
const scope = await setupActionScope(action, timeout);
|
|
13506
13514
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
@@ -13526,6 +13534,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
13526
13534
|
max_calls: maxTaps,
|
|
13527
13535
|
tap_burst_size: tapBurstSize,
|
|
13528
13536
|
condition_check_count: conditionCheckCount,
|
|
13537
|
+
settle_ms: settleMs,
|
|
13529
13538
|
elapsed_ms: elapsedMs,
|
|
13530
13539
|
interval_ms: intervalMs,
|
|
13531
13540
|
timeout_ms: timeout,
|
|
@@ -13538,6 +13547,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
13538
13547
|
tapCount += 1;
|
|
13539
13548
|
if (tapCount < maxTaps && burstIndex < burstCount - 1 && intervalMs) await page.waitForTimeout(intervalMs);
|
|
13540
13549
|
}
|
|
13550
|
+
if (settleMs) await page.waitForTimeout(settleMs);
|
|
13541
13551
|
lastPredicateResult = await setupReadWindowValue(scope.context, untilPath);
|
|
13542
13552
|
conditionCheckCount += 1;
|
|
13543
13553
|
if (lastPredicateResult.ok && setupValuesEqual(lastPredicateResult.value, untilExpected)) {
|
|
@@ -13555,6 +13565,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
13555
13565
|
max_calls: maxTaps,
|
|
13556
13566
|
tap_burst_size: tapBurstSize,
|
|
13557
13567
|
condition_check_count: conditionCheckCount,
|
|
13568
|
+
settle_ms: settleMs,
|
|
13558
13569
|
elapsed_ms: elapsedMs,
|
|
13559
13570
|
interval_ms: intervalMs,
|
|
13560
13571
|
timeout_ms: timeout,
|
|
@@ -13575,6 +13586,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
13575
13586
|
max_calls: maxTaps,
|
|
13576
13587
|
tap_burst_size: tapBurstSize,
|
|
13577
13588
|
condition_check_count: conditionCheckCount,
|
|
13589
|
+
settle_ms: settleMs,
|
|
13578
13590
|
elapsed_ms: elapsedMs,
|
|
13579
13591
|
interval_ms: intervalMs,
|
|
13580
13592
|
timeout_ms: timeout,
|
|
@@ -16211,7 +16223,8 @@ function usage() {
|
|
|
16211
16223
|
" riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
|
|
16212
16224
|
" riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
|
|
16213
16225
|
" riddle-proof-loop status --state-path <path>",
|
|
16214
|
-
" riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false; default false] [--split-viewports true|false; default false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json] [--quiet]",
|
|
16226
|
+
" riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--viewport-name <name[,name...]>] [--strict true|false; default false] [--split-viewports true|false; default false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json] [--quiet]",
|
|
16227
|
+
" riddle-proof-loop run-profile recover --profile <file|json|-> --url <base-url> --job <job-id> [--viewport-name <name[,name...]>] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
|
|
16215
16228
|
" riddle-proof-loop profile-body-assertions --artifact <file|url|-> --candidates-json <file|json|-> [--required-json <file|json|->] [--format json|body-contains]",
|
|
16216
16229
|
" riddle-proof-loop profile-http-status-preflight --profile <file|json|-> --url <base-url> [--format json|summary]",
|
|
16217
16230
|
" riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
|
|
@@ -16271,6 +16284,11 @@ function runProfileStrictOption(options) {
|
|
|
16271
16284
|
function runProfileSplitViewportsOption(options) {
|
|
16272
16285
|
return optionBoolean(options, "splitViewports") ?? false;
|
|
16273
16286
|
}
|
|
16287
|
+
function runProfileViewportNamesOption(options) {
|
|
16288
|
+
const raw = optionString(options, "viewportName") ?? optionString(options, "viewportNames");
|
|
16289
|
+
if (!raw) return [];
|
|
16290
|
+
return raw.split(",").map((part) => part.trim()).filter(Boolean);
|
|
16291
|
+
}
|
|
16274
16292
|
var DEFAULT_PROFILE_UNSUBMITTED_RETRY_TIMEOUT_MS = 9e4;
|
|
16275
16293
|
var DEFAULT_PROFILE_UNSUBMITTED_RETRIES = 2;
|
|
16276
16294
|
function optionNumber(options, ...keys) {
|
|
@@ -16871,6 +16889,61 @@ function profileHasRouteExitAffordanceReceipt(receipts) {
|
|
|
16871
16889
|
return routeFields.some((name) => setupReturnSummaryValue(receipt, [name]) !== void 0) || haystack.includes("route=") || haystack.includes("browserpath=");
|
|
16872
16890
|
});
|
|
16873
16891
|
}
|
|
16892
|
+
function profileCleanupLabelMatches(value) {
|
|
16893
|
+
if (!value) return false;
|
|
16894
|
+
return /\b(cleanup|clean|clear|reset|undo|discard|new)\b/i.test(value);
|
|
16895
|
+
}
|
|
16896
|
+
function profileHasCleanupBoundaryAffordanceReceipt(receipts) {
|
|
16897
|
+
const visibleFields = [
|
|
16898
|
+
"cleanupControlVisible",
|
|
16899
|
+
"cleanupVisible",
|
|
16900
|
+
"clearControlVisible",
|
|
16901
|
+
"resetControlVisible",
|
|
16902
|
+
"undoVisible",
|
|
16903
|
+
"discardVisible",
|
|
16904
|
+
"newControlVisible",
|
|
16905
|
+
"exitControlVisible"
|
|
16906
|
+
];
|
|
16907
|
+
const textFields = [
|
|
16908
|
+
"cleanupControlText",
|
|
16909
|
+
"cleanupText",
|
|
16910
|
+
"clearControlText",
|
|
16911
|
+
"resetControlText",
|
|
16912
|
+
"undoText",
|
|
16913
|
+
"discardText",
|
|
16914
|
+
"newControlText",
|
|
16915
|
+
"exitControlText",
|
|
16916
|
+
"controlText",
|
|
16917
|
+
"affordanceText"
|
|
16918
|
+
];
|
|
16919
|
+
return receipts.some((receipt) => {
|
|
16920
|
+
const storedTo = cliString(receipt.return_stored_to) || "";
|
|
16921
|
+
const label = cliString(receipt.label) || "";
|
|
16922
|
+
const path7 = cliString(receipt.path) || cliString(receipt.function_name) || "";
|
|
16923
|
+
const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
|
|
16924
|
+
const haystack = `${storedTo} ${label} ${path7} ${summary}`.toLowerCase();
|
|
16925
|
+
const mentionsCleanupBoundary = haystack.includes("cleanup") || haystack.includes("precleanup") || haystack.includes("pre-cleanup") || haystack.includes("boundary") || haystack.includes("undo") || haystack.includes("clear") || haystack.includes("reset") || haystack.includes("discard");
|
|
16926
|
+
const visibleControl = visibleFields.some((name) => setupReturnSummaryValue(receipt, [name]) === true);
|
|
16927
|
+
const controlText = textFields.map((name) => cliString(setupReturnSummaryValue(receipt, [name]))).find((value) => profileCleanupLabelMatches(value));
|
|
16928
|
+
return mentionsCleanupBoundary && (visibleControl || Boolean(controlText));
|
|
16929
|
+
});
|
|
16930
|
+
}
|
|
16931
|
+
function profileVisibleCleanupActionCount(setupViewports) {
|
|
16932
|
+
const keys = /* @__PURE__ */ new Set();
|
|
16933
|
+
const clickedReceipts = setupViewports.flatMap((viewport) => [
|
|
16934
|
+
...setupReceiptArray(viewport, "clicked"),
|
|
16935
|
+
...setupReceiptArray(viewport, "tap"),
|
|
16936
|
+
...setupReceiptArray(viewport, "tap_until")
|
|
16937
|
+
]);
|
|
16938
|
+
clickedReceipts.forEach((receipt, index) => {
|
|
16939
|
+
if (receipt.ok === false) return;
|
|
16940
|
+
const text = cliString(receipt.text) || cliString(receipt.label) || cliString(receipt.target) || cliString(receipt.selector);
|
|
16941
|
+
if (!profileCleanupLabelMatches(text)) return;
|
|
16942
|
+
const ordinal = cliFiniteNumber(receipt.ordinal);
|
|
16943
|
+
keys.add(ordinal === void 0 ? `idx:${index}:${text}` : `ord:${ordinal}:${text}`);
|
|
16944
|
+
});
|
|
16945
|
+
return keys.size;
|
|
16946
|
+
}
|
|
16874
16947
|
function profileHasOfflineAudioMetricsReceipt(receipts) {
|
|
16875
16948
|
const metricFields = [
|
|
16876
16949
|
"mixPeak",
|
|
@@ -16972,7 +17045,7 @@ function profileHasRecoveredStateReceipt(receipts) {
|
|
|
16972
17045
|
const path7 = cliString(receipt.path) || cliString(receipt.function_name) || "";
|
|
16973
17046
|
const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
|
|
16974
17047
|
const haystack = `${storedTo} ${label} ${path7} ${summary}`.toLowerCase();
|
|
16975
|
-
const labelsRecovery = haystack.includes("recover") || haystack.includes("repaired") || haystack.includes("repair") || haystack.includes("try fix") || haystack.includes("tryfix") || haystack.includes("after-fix") || haystack.includes("fixed");
|
|
17048
|
+
const labelsRecovery = haystack.includes("recover") || haystack.includes("repaired") || haystack.includes("repair") || haystack.includes("restart") || haystack.includes("play again") || haystack.includes("playagain") || haystack.includes("play-again") || haystack.includes("try fix") || haystack.includes("tryfix") || haystack.includes("after-fix") || haystack.includes("fixed");
|
|
16976
17049
|
if (!labelsRecovery) return false;
|
|
16977
17050
|
const status = profileLowerSummaryValue(receipt, ["status", "state", "phase"]);
|
|
16978
17051
|
const outcome = profileLowerSummaryValue(receipt, ["lastOutcome", "outcome", "result"]);
|
|
@@ -16983,6 +17056,38 @@ function profileHasRecoveredStateReceipt(receipts) {
|
|
|
16983
17056
|
return hasRecoveredState || success || hasValid && hasInvalid === false;
|
|
16984
17057
|
});
|
|
16985
17058
|
}
|
|
17059
|
+
function profileMetadataHasGeneratedOutputContract(metadata) {
|
|
17060
|
+
const contract = cliRecord(metadata.declared_state_contract);
|
|
17061
|
+
if (!contract) return false;
|
|
17062
|
+
const keys = Object.keys(contract).join(" ").toLowerCase();
|
|
17063
|
+
const values = Object.values(contract).map((value) => cliString(value)?.toLowerCase() || "").join(" ");
|
|
17064
|
+
const haystack = `${keys} ${values}`;
|
|
17065
|
+
return haystack.includes("generated_output") || haystack.includes("generated output") || haystack.includes("output-size") || haystack.includes("output size") || haystack.includes("output result") || haystack.includes("optimizer size");
|
|
17066
|
+
}
|
|
17067
|
+
function profileHasGeneratedOutputReceipt(receipts) {
|
|
17068
|
+
let outputReady = false;
|
|
17069
|
+
let outputChanged = false;
|
|
17070
|
+
for (const receipt of receipts) {
|
|
17071
|
+
const storedTo = cliString(receipt.return_stored_to) || "";
|
|
17072
|
+
const label = cliString(receipt.label) || "";
|
|
17073
|
+
const path7 = cliString(receipt.path) || cliString(receipt.function_name) || "";
|
|
17074
|
+
const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
|
|
17075
|
+
const haystack = `${storedTo} ${label} ${path7} ${summary}`.toLowerCase();
|
|
17076
|
+
const readySignal = setupReturnSummaryValue(receipt, ["outputReady", "outputStillReady"]) === true || cliFiniteNumber(setupReturnSummaryValue(receipt, ["surfaceCount", "before.surfaceCount", "after.surfaceCount"])) !== void 0 || setupReturnSummaryValue(receipt, ["size", "before.size", "after.size", "size.text", "before.size.text", "after.size.text"]) !== void 0;
|
|
17077
|
+
if (readySignal && (haystack.includes("output") || haystack.includes("size") || haystack.includes("result"))) {
|
|
17078
|
+
outputReady = true;
|
|
17079
|
+
}
|
|
17080
|
+
const beforeBytes = cliFiniteNumber(setupReturnSummaryValue(receipt, ["before.size.outputBytes", "before.outputBytes", "beforeBytes"]));
|
|
17081
|
+
const afterBytes = cliFiniteNumber(setupReturnSummaryValue(receipt, ["after.size.outputBytes", "after.outputBytes", "afterBytes"]));
|
|
17082
|
+
const beforeText = cliString(setupReturnSummaryValue(receipt, ["before.size.text", "before.outputText", "beforeText"]));
|
|
17083
|
+
const afterText = cliString(setupReturnSummaryValue(receipt, ["after.size.text", "after.outputText", "afterText"]));
|
|
17084
|
+
const explicitChange = setupReturnSummaryValue(receipt, ["sizeChanged", "outputChanged", "resultChanged"]) === true;
|
|
17085
|
+
const byteChange = beforeBytes !== void 0 && afterBytes !== void 0 && beforeBytes !== afterBytes;
|
|
17086
|
+
const textChange = Boolean(beforeText && afterText && beforeText !== afterText);
|
|
17087
|
+
if (explicitChange || byteChange || textChange) outputChanged = true;
|
|
17088
|
+
}
|
|
17089
|
+
return outputReady && outputChanged;
|
|
17090
|
+
}
|
|
16986
17091
|
function profilePackReceiptStatus(result, metadata, receipt) {
|
|
16987
17092
|
const text = receipt.toLowerCase();
|
|
16988
17093
|
const setupSummary = profileSetupSummaryRecord(result);
|
|
@@ -17013,6 +17118,7 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
17013
17118
|
const clickFallbackTapCount = clickFallbackTapKeys.size;
|
|
17014
17119
|
const tapUntilCount = profileSetupReceiptTotal(setupViewports, "tap_until");
|
|
17015
17120
|
const visibleUiActionCount = clickCount + profileSetupReceiptTotal(setupViewports, "tap") + tapUntilCount;
|
|
17121
|
+
const visibleCleanupActionCount = profileVisibleCleanupActionCount(setupViewports);
|
|
17016
17122
|
const setupFailureCount = profileSetupFailureCount(setupViewports);
|
|
17017
17123
|
const setupObstructionCount = profileSetupObstructionCount(setupViewports);
|
|
17018
17124
|
const inputDispatchCount = profileSetupReceiptTotal(setupViewports, "drag") + profileSetupReceiptTotal(setupViewports, "tap") + tapUntilCount + profileSetupReceiptTotal(setupViewports, "press") + profileSetupReceiptTotal(setupViewports, "keyboard_sequence");
|
|
@@ -17048,6 +17154,7 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
17048
17154
|
const hasTextAbsence = profileHasPassedCheck(result, ["text_absent", "selector_text_absent"]);
|
|
17049
17155
|
const hasMeasuredStateChange = hasNaturalInput || hasCanvasChange || valueReceipts.some((item) => setupReturnSummaryValue(item, ["changed"]) === true || setupReturnSummaryValue(item, ["nonWhiteDelta", "darkDelta", "pixelDelta", "movementDelta"]) !== void 0);
|
|
17050
17156
|
const hasRouteExitAffordanceReceipt = profileHasRouteExitAffordanceReceipt(valueReceipts);
|
|
17157
|
+
const hasCleanupBoundaryAffordanceReceipt = profileHasCleanupBoundaryAffordanceReceipt(valueReceipts);
|
|
17051
17158
|
const hasOfflineAudioMetricsReceipt = profileHasOfflineAudioMetricsReceipt(valueReceipts);
|
|
17052
17159
|
const hasActiveRouteLocalProofReceipt = profileHasActiveRouteLocalProofReceipt(valueReceipts);
|
|
17053
17160
|
const hasTerminalLossReceipt = profileHasTerminalLossReceipt(valueReceipts);
|
|
@@ -17056,6 +17163,8 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
17056
17163
|
const hasControlledSuccessLaunchReceipt = profileHasControlledLaunchReceipt(valueReceipts, "success");
|
|
17057
17164
|
const hasRouteContinuationReceipt = profileHasRouteContinuationReceipt(valueReceipts);
|
|
17058
17165
|
const hasRecoveredStateReceipt = profileHasRecoveredStateReceipt(valueReceipts);
|
|
17166
|
+
const hasGeneratedOutputContract = profileMetadataHasGeneratedOutputContract(metadata);
|
|
17167
|
+
const hasGeneratedOutputReceipt = profileHasGeneratedOutputReceipt(valueReceipts);
|
|
17059
17168
|
const failedCleanupInventoryReason = profileFailedCleanupInventoryReason(setupViewports);
|
|
17060
17169
|
const passedCleanupInventoryReason = profilePassedCleanupInventoryReason(setupViewports);
|
|
17061
17170
|
if (text.includes("artifact link") || text.includes("artifact path")) {
|
|
@@ -17109,6 +17218,13 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
17109
17218
|
}
|
|
17110
17219
|
return profileReceiptSignalStatus(hasTextAbsence, "absence check passed", "absence check missing");
|
|
17111
17220
|
}
|
|
17221
|
+
if (text.includes("generated-output") || text.includes("generated output") || text.includes("output-size") || text.includes("output size") || (text.includes("output") || text.includes("result")) && (text.includes("mutation") || text.includes("final"))) {
|
|
17222
|
+
return profileReceiptSignalStatus(
|
|
17223
|
+
hasGeneratedOutputContract && hasGeneratedOutputReceipt,
|
|
17224
|
+
"generated-output mutation receipt present",
|
|
17225
|
+
"generated-output mutation receipt missing"
|
|
17226
|
+
);
|
|
17227
|
+
}
|
|
17112
17228
|
if (text.includes("recovered") || text.includes("final state")) {
|
|
17113
17229
|
return profileReceiptSignalStatus(hasStateContract || hasTextVisibility, "final state receipt present", "final state receipt missing");
|
|
17114
17230
|
}
|
|
@@ -17165,6 +17281,13 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
17165
17281
|
"route continuation receipt missing"
|
|
17166
17282
|
);
|
|
17167
17283
|
}
|
|
17284
|
+
if (text.includes("cleanup") && text.includes("action") && (text.includes("visible ui") || text.includes("visible"))) {
|
|
17285
|
+
return profileReceiptSignalStatus(
|
|
17286
|
+
visibleCleanupActionCount > 0,
|
|
17287
|
+
`visible cleanup action receipt present (${visibleCleanupActionCount})`,
|
|
17288
|
+
"visible cleanup action receipt missing"
|
|
17289
|
+
);
|
|
17290
|
+
}
|
|
17168
17291
|
if (text.includes("through visible ui") || text.includes("visible ui action") || text.includes("ui-routed") || text.includes("ui routed") || text.includes("visible") && text.includes("route") && text.includes("exit") && text.includes("action") || text.includes("visible") && text.includes("mode") && text.includes("exit") && text.includes("action")) {
|
|
17169
17292
|
return profileReceiptSignalStatus(
|
|
17170
17293
|
visibleUiActionCount > 0,
|
|
@@ -17179,6 +17302,13 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
17179
17302
|
"affordance receipt missing"
|
|
17180
17303
|
);
|
|
17181
17304
|
}
|
|
17305
|
+
if (text.includes("cleanup") && (text.includes("affordance") || text.includes("control") || text.includes("boundary") || text.includes("inventory"))) {
|
|
17306
|
+
return profileReceiptSignalStatus(
|
|
17307
|
+
hasCleanupBoundaryAffordanceReceipt,
|
|
17308
|
+
"visible cleanup affordance receipt present",
|
|
17309
|
+
"visible cleanup affordance receipt missing"
|
|
17310
|
+
);
|
|
17311
|
+
}
|
|
17182
17312
|
if (text.includes("retry") || text.includes("repair") || text.includes("reset") || text.includes("affordance")) {
|
|
17183
17313
|
return profileReceiptSignalStatus(hasStateContract || clickCount > 0, "affordance or transition receipt present", "affordance receipt missing");
|
|
17184
17314
|
}
|
|
@@ -18084,6 +18214,7 @@ function profileSetupSummaryMarkdown(result) {
|
|
|
18084
18214
|
const maxTaps = cliFiniteNumber(receipt.max_taps) ?? cliFiniteNumber(receipt.max_calls);
|
|
18085
18215
|
const tapBurstSize = cliFiniteNumber(receipt.tap_burst_size);
|
|
18086
18216
|
const conditionCheckCount = cliFiniteNumber(receipt.condition_check_count);
|
|
18217
|
+
const settleMs = cliFiniteNumber(receipt.settle_ms);
|
|
18087
18218
|
const elapsedMs3 = cliFiniteNumber(receipt.elapsed_ms);
|
|
18088
18219
|
const ok = receipt.ok === false ? "failed" : "ok";
|
|
18089
18220
|
const reason = cliString(receipt.reason);
|
|
@@ -18091,8 +18222,9 @@ function profileSetupSummaryMarkdown(result) {
|
|
|
18091
18222
|
const tapText = tapCount === void 0 ? "" : ` in ${tapCount}${maxTaps === void 0 ? "" : `/${maxTaps}`} tap(s)`;
|
|
18092
18223
|
const burstText = tapBurstSize === void 0 || tapBurstSize <= 1 ? "" : `, burst ${tapBurstSize}`;
|
|
18093
18224
|
const conditionCheckText = conditionCheckCount === void 0 ? "" : `, ${conditionCheckCount} check(s)`;
|
|
18225
|
+
const settleText = settleMs === void 0 || settleMs <= 0 ? "" : `, settle ${settleMs}ms`;
|
|
18094
18226
|
const elapsedText = elapsedMs3 === void 0 ? "" : `, elapsed ${elapsedMs3}ms`;
|
|
18095
|
-
lines.push(`- ${name} tap_until: ${ok}, ${markdownInlineCode(selector)}${pointerType ? ` ${markdownInlineCode(pointerType)}` : ""}${inputDispatch ? ` via ${markdownInlineCode(inputDispatch)}` : ""}${coordinateText}${durationMs === void 0 ? "" : `, duration ${durationMs}ms`} until ${markdownInlineCode(untilPath)}${expected === void 0 ? "" : ` == ${markdownInlineCode(expected, 80)}`}${tapText}${burstText}${conditionCheckText}${elapsedText}${actual === void 0 ? "" : `, observed ${markdownInlineCode(actual, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
|
|
18227
|
+
lines.push(`- ${name} tap_until: ${ok}, ${markdownInlineCode(selector)}${pointerType ? ` ${markdownInlineCode(pointerType)}` : ""}${inputDispatch ? ` via ${markdownInlineCode(inputDispatch)}` : ""}${coordinateText}${durationMs === void 0 ? "" : `, duration ${durationMs}ms`} until ${markdownInlineCode(untilPath)}${expected === void 0 ? "" : ` == ${markdownInlineCode(expected, 80)}`}${tapText}${burstText}${conditionCheckText}${settleText}${elapsedText}${actual === void 0 ? "" : `, observed ${markdownInlineCode(actual, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
|
|
18096
18228
|
}
|
|
18097
18229
|
if (tapUntilDetails.length > sampledTapUntilDetails.length) lines.push(`- ${tapUntilDetails.length - sampledTapUntilDetails.length} additional tap_until receipt(s) omitted.`);
|
|
18098
18230
|
const keyboardGroups = viewports.map((viewport) => {
|
|
@@ -18514,6 +18646,21 @@ function writeProfileOutput(outputDir, result) {
|
|
|
18514
18646
|
if (result.evidence?.dom_summary) (0, import_node_fs6.writeFileSync)(import_node_path6.default.join(outputDir, "dom-summary.json"), `${JSON.stringify(result.evidence.dom_summary, null, 2)}
|
|
18515
18647
|
`);
|
|
18516
18648
|
}
|
|
18649
|
+
function writeRiddleJobReceipt(outputDir, input) {
|
|
18650
|
+
if (!outputDir) return;
|
|
18651
|
+
(0, import_node_fs6.mkdirSync)(outputDir, { recursive: true });
|
|
18652
|
+
(0, import_node_fs6.writeFileSync)(import_node_path6.default.join(outputDir, "riddle-job.json"), `${JSON.stringify({
|
|
18653
|
+
version: "riddle-proof.riddle-job-receipt.v1",
|
|
18654
|
+
profile_name: input.profile.name,
|
|
18655
|
+
job_id: input.jobId,
|
|
18656
|
+
target_url: input.targetUrl,
|
|
18657
|
+
viewport: input.viewport || null,
|
|
18658
|
+
captured_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18659
|
+
created: input.created || null,
|
|
18660
|
+
recovery_command: `riddle-proof-loop run-profile recover --profile <profile> --job ${input.jobId} --output-dir ${outputDir}`
|
|
18661
|
+
}, null, 2)}
|
|
18662
|
+
`);
|
|
18663
|
+
}
|
|
18517
18664
|
async function readArtifactJson(artifact) {
|
|
18518
18665
|
const target = artifact.url || artifact.path;
|
|
18519
18666
|
if (!target) return void 0;
|
|
@@ -18717,6 +18864,43 @@ function profileForSplitViewport(profile, viewport) {
|
|
|
18717
18864
|
}
|
|
18718
18865
|
};
|
|
18719
18866
|
}
|
|
18867
|
+
function profileItemAppliesToAnySelectedViewport(item, viewports) {
|
|
18868
|
+
if (!item.viewports?.length) return true;
|
|
18869
|
+
const names = new Set(viewports.map((viewport) => viewport.name).filter(Boolean));
|
|
18870
|
+
return item.viewports.some((name) => names.has(name));
|
|
18871
|
+
}
|
|
18872
|
+
function profileForSelectedViewports(profile, viewports) {
|
|
18873
|
+
const suffix = viewports.map((viewport) => viewport.name || `${viewport.width}x${viewport.height}`).join("-");
|
|
18874
|
+
const setupActions = profile.target.setup_actions?.filter((action) => profileItemAppliesToAnySelectedViewport(action, viewports));
|
|
18875
|
+
return {
|
|
18876
|
+
...profile,
|
|
18877
|
+
name: `${profile.name}-${suffix}`,
|
|
18878
|
+
checks: profile.checks.filter((check) => profileItemAppliesToAnySelectedViewport(check, viewports)),
|
|
18879
|
+
target: {
|
|
18880
|
+
...profile.target,
|
|
18881
|
+
viewports,
|
|
18882
|
+
...setupActions ? { setup_actions: setupActions } : {}
|
|
18883
|
+
},
|
|
18884
|
+
metadata: {
|
|
18885
|
+
...profile.metadata || {},
|
|
18886
|
+
selected_parent_profile: profile.name,
|
|
18887
|
+
selected_viewports: viewports.map((viewport) => viewport.name || `${viewport.width}x${viewport.height}`)
|
|
18888
|
+
}
|
|
18889
|
+
};
|
|
18890
|
+
}
|
|
18891
|
+
function profileWithSelectedViewportNamesForCli(profile, options) {
|
|
18892
|
+
const names = runProfileViewportNamesOption(options);
|
|
18893
|
+
if (!names.length) return profile;
|
|
18894
|
+
const requested = new Set(names);
|
|
18895
|
+
const viewports = profile.target.viewports.filter((viewport) => viewport.name && requested.has(viewport.name));
|
|
18896
|
+
const matched = new Set(viewports.map((viewport) => viewport.name).filter(Boolean));
|
|
18897
|
+
const missing = names.filter((name) => !matched.has(name));
|
|
18898
|
+
if (missing.length) {
|
|
18899
|
+
const available = profile.target.viewports.map((viewport) => viewport.name).filter(Boolean).join(", ") || "none";
|
|
18900
|
+
throw new Error(`Unknown --viewport-name ${missing.join(", ")}. Available viewport names: ${available}.`);
|
|
18901
|
+
}
|
|
18902
|
+
return profileForSelectedViewports(profile, viewports);
|
|
18903
|
+
}
|
|
18720
18904
|
function safeProfileOutputSegment(value) {
|
|
18721
18905
|
const safe = value.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
18722
18906
|
return safe || "viewport";
|
|
@@ -18905,6 +19089,13 @@ async function runSingleRiddleProfileForCli(profile, options, input) {
|
|
|
18905
19089
|
const directResult = extractRiddleProofProfileResult(created);
|
|
18906
19090
|
return directResult ? withRiddleMetadata(withProfileMetadata(profile, directResult), { artifacts: collectRiddleProfileArtifactRefs(created) }) : createRiddleProofProfileInsufficientResult({ profile, runner, error: "Riddle run response was missing job_id.", artifacts: collectRiddleProfileArtifactRefs(created) });
|
|
18907
19091
|
}
|
|
19092
|
+
writeRiddleJobReceipt(input.outputDir, {
|
|
19093
|
+
profile,
|
|
19094
|
+
jobId,
|
|
19095
|
+
targetUrl,
|
|
19096
|
+
viewport: profile.target.viewports[0],
|
|
19097
|
+
created
|
|
19098
|
+
});
|
|
18908
19099
|
poll = await client.pollJob(jobId, pollOptions);
|
|
18909
19100
|
if (attempt < retryLimit && shouldRetryUnsubmittedRiddleJob(poll)) {
|
|
18910
19101
|
const recoveredResult = await recoverProfileResultFromRiddleArtifacts(profile, {
|
|
@@ -18981,10 +19172,9 @@ async function runSplitViewportProfileForCli(profile, options, input) {
|
|
|
18981
19172
|
const childRuns = [];
|
|
18982
19173
|
for (const viewport of profile.target.viewports) {
|
|
18983
19174
|
const childProfile = profileForSplitViewport(profile, viewport);
|
|
18984
|
-
const
|
|
18985
|
-
|
|
18986
|
-
|
|
18987
|
-
}
|
|
19175
|
+
const childOutputDir = outputDir ? splitViewportOutputDir(outputDir, viewport.name, seenOutputNames) : void 0;
|
|
19176
|
+
const result2 = await runSingleRiddleProfileForCli(childProfile, options, { ...input, outputDir: childOutputDir });
|
|
19177
|
+
if (childOutputDir) writeProfileOutput(childOutputDir, result2);
|
|
18988
19178
|
childRuns.push({ viewport, profile: childProfile, result: result2 });
|
|
18989
19179
|
}
|
|
18990
19180
|
const artifacts = childRuns.flatMap(splitViewportArtifactRefs);
|
|
@@ -19006,6 +19196,51 @@ async function runSplitViewportProfileForCli(profile, options, input) {
|
|
|
19006
19196
|
});
|
|
19007
19197
|
return withSplitViewportWarnings(profile, withSplitViewportChildStatusCheck(profile, result, childRuns));
|
|
19008
19198
|
}
|
|
19199
|
+
async function recoverProfileForCli(profile, options) {
|
|
19200
|
+
const runner = optionString(options, "runner") || "riddle";
|
|
19201
|
+
if (runner !== "riddle") {
|
|
19202
|
+
throw new Error(`Unsupported --runner ${runner}. The current CLI supports --runner riddle.`);
|
|
19203
|
+
}
|
|
19204
|
+
const jobId = optionString(options, "job") ?? optionString(options, "jobId");
|
|
19205
|
+
if (!jobId) throw new Error("run-profile recover requires --job <job-id>.");
|
|
19206
|
+
const client = createRiddleApiClient(riddleClientConfig(options));
|
|
19207
|
+
let artifactPayload;
|
|
19208
|
+
try {
|
|
19209
|
+
artifactPayload = await client.requestJson(`/v1/jobs/${jobId}/artifacts`);
|
|
19210
|
+
} catch (error) {
|
|
19211
|
+
return createRiddleProofProfileEnvironmentBlockedResult({
|
|
19212
|
+
profile,
|
|
19213
|
+
runner,
|
|
19214
|
+
error,
|
|
19215
|
+
riddle: { job_id: jobId, terminal: false }
|
|
19216
|
+
});
|
|
19217
|
+
}
|
|
19218
|
+
const artifacts = collectRiddleProfileArtifactRefs(artifactPayload);
|
|
19219
|
+
const artifactStatus = riddleArtifactsPayloadStatus(artifactPayload);
|
|
19220
|
+
const terminal = artifactStatus ? isTerminalRiddleJobStatus(artifactStatus) : artifacts.length > 0;
|
|
19221
|
+
const recovered = await profileResultFromRiddleArtifacts(profile, artifacts, [artifactPayload]);
|
|
19222
|
+
if (recovered) {
|
|
19223
|
+
return withRiddleMetadata(recovered, {
|
|
19224
|
+
job_id: jobId,
|
|
19225
|
+
status: artifactStatus,
|
|
19226
|
+
terminal,
|
|
19227
|
+
artifacts,
|
|
19228
|
+
artifactRecovery: true
|
|
19229
|
+
});
|
|
19230
|
+
}
|
|
19231
|
+
return createRiddleProofProfileInsufficientResult({
|
|
19232
|
+
profile,
|
|
19233
|
+
runner,
|
|
19234
|
+
error: artifacts.length ? `Riddle job ${jobId} artifacts were recovered without a proof result.` : `Riddle job ${jobId} had no recoverable artifacts.`,
|
|
19235
|
+
riddle: {
|
|
19236
|
+
job_id: jobId,
|
|
19237
|
+
status: artifactStatus,
|
|
19238
|
+
terminal,
|
|
19239
|
+
artifact_recovery: artifacts.length > 0
|
|
19240
|
+
},
|
|
19241
|
+
artifacts
|
|
19242
|
+
});
|
|
19243
|
+
}
|
|
19009
19244
|
async function runProfileForCli(profile, options) {
|
|
19010
19245
|
const runner = optionString(options, "runner") || "riddle";
|
|
19011
19246
|
if (runner !== "riddle") {
|
|
@@ -19015,7 +19250,7 @@ async function runProfileForCli(profile, options) {
|
|
|
19015
19250
|
if (runProfileSplitViewportsOption(options) && profile.target.viewports.length > 1) {
|
|
19016
19251
|
return runSplitViewportProfileForCli(profile, options, { client, runner });
|
|
19017
19252
|
}
|
|
19018
|
-
return runSingleRiddleProfileForCli(profile, options, { client, runner });
|
|
19253
|
+
return runSingleRiddleProfileForCli(profile, options, { client, runner, outputDir: profileOutputDirOption(options) });
|
|
19019
19254
|
}
|
|
19020
19255
|
function requestForRun(options) {
|
|
19021
19256
|
const statePath = optionString(options, "statePath");
|
|
@@ -19064,8 +19299,8 @@ async function main() {
|
|
|
19064
19299
|
return;
|
|
19065
19300
|
}
|
|
19066
19301
|
if (command === "run-profile") {
|
|
19067
|
-
const profile = normalizeProfileForCli(options);
|
|
19068
|
-
const result = await runProfileForCli(profile, options);
|
|
19302
|
+
const profile = profileWithSelectedViewportNamesForCli(normalizeProfileForCli(options), options);
|
|
19303
|
+
const result = positional[1] === "recover" ? await recoverProfileForCli(profile, options) : await runProfileForCli(profile, options);
|
|
19069
19304
|
writeProfileOutput(profileOutputDirOption(options), result);
|
|
19070
19305
|
const diagnosticLine = profileCliDiagnosticLine(result);
|
|
19071
19306
|
if (diagnosticLine && optionBoolean(options, "quiet") !== true) {
|
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
profileStatusExitCode,
|
|
14
14
|
resolveRiddleProofProfileTargetUrl,
|
|
15
15
|
resolveRiddleProofProfileTimeoutSec
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-OUZKZ5U4.js";
|
|
17
17
|
import {
|
|
18
18
|
createRiddleApiClient,
|
|
19
19
|
isTerminalRiddleJobStatus,
|
|
@@ -48,7 +48,8 @@ function usage() {
|
|
|
48
48
|
" riddle-proof-loop respond --state-path <path> --response-json <file|json|->",
|
|
49
49
|
" riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
|
|
50
50
|
" riddle-proof-loop status --state-path <path>",
|
|
51
|
-
" riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false; default false] [--split-viewports true|false; default false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json] [--quiet]",
|
|
51
|
+
" riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--viewport-name <name[,name...]>] [--strict true|false; default false] [--split-viewports true|false; default false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json] [--quiet]",
|
|
52
|
+
" riddle-proof-loop run-profile recover --profile <file|json|-> --url <base-url> --job <job-id> [--viewport-name <name[,name...]>] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
|
|
52
53
|
" riddle-proof-loop profile-body-assertions --artifact <file|url|-> --candidates-json <file|json|-> [--required-json <file|json|->] [--format json|body-contains]",
|
|
53
54
|
" riddle-proof-loop profile-http-status-preflight --profile <file|json|-> --url <base-url> [--format json|summary]",
|
|
54
55
|
" riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
|
|
@@ -108,6 +109,11 @@ function runProfileStrictOption(options) {
|
|
|
108
109
|
function runProfileSplitViewportsOption(options) {
|
|
109
110
|
return optionBoolean(options, "splitViewports") ?? false;
|
|
110
111
|
}
|
|
112
|
+
function runProfileViewportNamesOption(options) {
|
|
113
|
+
const raw = optionString(options, "viewportName") ?? optionString(options, "viewportNames");
|
|
114
|
+
if (!raw) return [];
|
|
115
|
+
return raw.split(",").map((part) => part.trim()).filter(Boolean);
|
|
116
|
+
}
|
|
111
117
|
var DEFAULT_PROFILE_UNSUBMITTED_RETRY_TIMEOUT_MS = 9e4;
|
|
112
118
|
var DEFAULT_PROFILE_UNSUBMITTED_RETRIES = 2;
|
|
113
119
|
function optionNumber(options, ...keys) {
|
|
@@ -708,6 +714,61 @@ function profileHasRouteExitAffordanceReceipt(receipts) {
|
|
|
708
714
|
return routeFields.some((name) => setupReturnSummaryValue(receipt, [name]) !== void 0) || haystack.includes("route=") || haystack.includes("browserpath=");
|
|
709
715
|
});
|
|
710
716
|
}
|
|
717
|
+
function profileCleanupLabelMatches(value) {
|
|
718
|
+
if (!value) return false;
|
|
719
|
+
return /\b(cleanup|clean|clear|reset|undo|discard|new)\b/i.test(value);
|
|
720
|
+
}
|
|
721
|
+
function profileHasCleanupBoundaryAffordanceReceipt(receipts) {
|
|
722
|
+
const visibleFields = [
|
|
723
|
+
"cleanupControlVisible",
|
|
724
|
+
"cleanupVisible",
|
|
725
|
+
"clearControlVisible",
|
|
726
|
+
"resetControlVisible",
|
|
727
|
+
"undoVisible",
|
|
728
|
+
"discardVisible",
|
|
729
|
+
"newControlVisible",
|
|
730
|
+
"exitControlVisible"
|
|
731
|
+
];
|
|
732
|
+
const textFields = [
|
|
733
|
+
"cleanupControlText",
|
|
734
|
+
"cleanupText",
|
|
735
|
+
"clearControlText",
|
|
736
|
+
"resetControlText",
|
|
737
|
+
"undoText",
|
|
738
|
+
"discardText",
|
|
739
|
+
"newControlText",
|
|
740
|
+
"exitControlText",
|
|
741
|
+
"controlText",
|
|
742
|
+
"affordanceText"
|
|
743
|
+
];
|
|
744
|
+
return receipts.some((receipt) => {
|
|
745
|
+
const storedTo = cliString(receipt.return_stored_to) || "";
|
|
746
|
+
const label = cliString(receipt.label) || "";
|
|
747
|
+
const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
|
|
748
|
+
const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
|
|
749
|
+
const haystack = `${storedTo} ${label} ${path2} ${summary}`.toLowerCase();
|
|
750
|
+
const mentionsCleanupBoundary = haystack.includes("cleanup") || haystack.includes("precleanup") || haystack.includes("pre-cleanup") || haystack.includes("boundary") || haystack.includes("undo") || haystack.includes("clear") || haystack.includes("reset") || haystack.includes("discard");
|
|
751
|
+
const visibleControl = visibleFields.some((name) => setupReturnSummaryValue(receipt, [name]) === true);
|
|
752
|
+
const controlText = textFields.map((name) => cliString(setupReturnSummaryValue(receipt, [name]))).find((value) => profileCleanupLabelMatches(value));
|
|
753
|
+
return mentionsCleanupBoundary && (visibleControl || Boolean(controlText));
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
function profileVisibleCleanupActionCount(setupViewports) {
|
|
757
|
+
const keys = /* @__PURE__ */ new Set();
|
|
758
|
+
const clickedReceipts = setupViewports.flatMap((viewport) => [
|
|
759
|
+
...setupReceiptArray(viewport, "clicked"),
|
|
760
|
+
...setupReceiptArray(viewport, "tap"),
|
|
761
|
+
...setupReceiptArray(viewport, "tap_until")
|
|
762
|
+
]);
|
|
763
|
+
clickedReceipts.forEach((receipt, index) => {
|
|
764
|
+
if (receipt.ok === false) return;
|
|
765
|
+
const text = cliString(receipt.text) || cliString(receipt.label) || cliString(receipt.target) || cliString(receipt.selector);
|
|
766
|
+
if (!profileCleanupLabelMatches(text)) return;
|
|
767
|
+
const ordinal = cliFiniteNumber(receipt.ordinal);
|
|
768
|
+
keys.add(ordinal === void 0 ? `idx:${index}:${text}` : `ord:${ordinal}:${text}`);
|
|
769
|
+
});
|
|
770
|
+
return keys.size;
|
|
771
|
+
}
|
|
711
772
|
function profileHasOfflineAudioMetricsReceipt(receipts) {
|
|
712
773
|
const metricFields = [
|
|
713
774
|
"mixPeak",
|
|
@@ -809,7 +870,7 @@ function profileHasRecoveredStateReceipt(receipts) {
|
|
|
809
870
|
const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
|
|
810
871
|
const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
|
|
811
872
|
const haystack = `${storedTo} ${label} ${path2} ${summary}`.toLowerCase();
|
|
812
|
-
const labelsRecovery = haystack.includes("recover") || haystack.includes("repaired") || haystack.includes("repair") || haystack.includes("try fix") || haystack.includes("tryfix") || haystack.includes("after-fix") || haystack.includes("fixed");
|
|
873
|
+
const labelsRecovery = haystack.includes("recover") || haystack.includes("repaired") || haystack.includes("repair") || haystack.includes("restart") || haystack.includes("play again") || haystack.includes("playagain") || haystack.includes("play-again") || haystack.includes("try fix") || haystack.includes("tryfix") || haystack.includes("after-fix") || haystack.includes("fixed");
|
|
813
874
|
if (!labelsRecovery) return false;
|
|
814
875
|
const status = profileLowerSummaryValue(receipt, ["status", "state", "phase"]);
|
|
815
876
|
const outcome = profileLowerSummaryValue(receipt, ["lastOutcome", "outcome", "result"]);
|
|
@@ -820,6 +881,38 @@ function profileHasRecoveredStateReceipt(receipts) {
|
|
|
820
881
|
return hasRecoveredState || success || hasValid && hasInvalid === false;
|
|
821
882
|
});
|
|
822
883
|
}
|
|
884
|
+
function profileMetadataHasGeneratedOutputContract(metadata) {
|
|
885
|
+
const contract = cliRecord(metadata.declared_state_contract);
|
|
886
|
+
if (!contract) return false;
|
|
887
|
+
const keys = Object.keys(contract).join(" ").toLowerCase();
|
|
888
|
+
const values = Object.values(contract).map((value) => cliString(value)?.toLowerCase() || "").join(" ");
|
|
889
|
+
const haystack = `${keys} ${values}`;
|
|
890
|
+
return haystack.includes("generated_output") || haystack.includes("generated output") || haystack.includes("output-size") || haystack.includes("output size") || haystack.includes("output result") || haystack.includes("optimizer size");
|
|
891
|
+
}
|
|
892
|
+
function profileHasGeneratedOutputReceipt(receipts) {
|
|
893
|
+
let outputReady = false;
|
|
894
|
+
let outputChanged = false;
|
|
895
|
+
for (const receipt of receipts) {
|
|
896
|
+
const storedTo = cliString(receipt.return_stored_to) || "";
|
|
897
|
+
const label = cliString(receipt.label) || "";
|
|
898
|
+
const path2 = cliString(receipt.path) || cliString(receipt.function_name) || "";
|
|
899
|
+
const summary = cliReturnSummaryLabel(receipt.return_summary) || "";
|
|
900
|
+
const haystack = `${storedTo} ${label} ${path2} ${summary}`.toLowerCase();
|
|
901
|
+
const readySignal = setupReturnSummaryValue(receipt, ["outputReady", "outputStillReady"]) === true || cliFiniteNumber(setupReturnSummaryValue(receipt, ["surfaceCount", "before.surfaceCount", "after.surfaceCount"])) !== void 0 || setupReturnSummaryValue(receipt, ["size", "before.size", "after.size", "size.text", "before.size.text", "after.size.text"]) !== void 0;
|
|
902
|
+
if (readySignal && (haystack.includes("output") || haystack.includes("size") || haystack.includes("result"))) {
|
|
903
|
+
outputReady = true;
|
|
904
|
+
}
|
|
905
|
+
const beforeBytes = cliFiniteNumber(setupReturnSummaryValue(receipt, ["before.size.outputBytes", "before.outputBytes", "beforeBytes"]));
|
|
906
|
+
const afterBytes = cliFiniteNumber(setupReturnSummaryValue(receipt, ["after.size.outputBytes", "after.outputBytes", "afterBytes"]));
|
|
907
|
+
const beforeText = cliString(setupReturnSummaryValue(receipt, ["before.size.text", "before.outputText", "beforeText"]));
|
|
908
|
+
const afterText = cliString(setupReturnSummaryValue(receipt, ["after.size.text", "after.outputText", "afterText"]));
|
|
909
|
+
const explicitChange = setupReturnSummaryValue(receipt, ["sizeChanged", "outputChanged", "resultChanged"]) === true;
|
|
910
|
+
const byteChange = beforeBytes !== void 0 && afterBytes !== void 0 && beforeBytes !== afterBytes;
|
|
911
|
+
const textChange = Boolean(beforeText && afterText && beforeText !== afterText);
|
|
912
|
+
if (explicitChange || byteChange || textChange) outputChanged = true;
|
|
913
|
+
}
|
|
914
|
+
return outputReady && outputChanged;
|
|
915
|
+
}
|
|
823
916
|
function profilePackReceiptStatus(result, metadata, receipt) {
|
|
824
917
|
const text = receipt.toLowerCase();
|
|
825
918
|
const setupSummary = profileSetupSummaryRecord(result);
|
|
@@ -850,6 +943,7 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
850
943
|
const clickFallbackTapCount = clickFallbackTapKeys.size;
|
|
851
944
|
const tapUntilCount = profileSetupReceiptTotal(setupViewports, "tap_until");
|
|
852
945
|
const visibleUiActionCount = clickCount + profileSetupReceiptTotal(setupViewports, "tap") + tapUntilCount;
|
|
946
|
+
const visibleCleanupActionCount = profileVisibleCleanupActionCount(setupViewports);
|
|
853
947
|
const setupFailureCount = profileSetupFailureCount(setupViewports);
|
|
854
948
|
const setupObstructionCount = profileSetupObstructionCount(setupViewports);
|
|
855
949
|
const inputDispatchCount = profileSetupReceiptTotal(setupViewports, "drag") + profileSetupReceiptTotal(setupViewports, "tap") + tapUntilCount + profileSetupReceiptTotal(setupViewports, "press") + profileSetupReceiptTotal(setupViewports, "keyboard_sequence");
|
|
@@ -885,6 +979,7 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
885
979
|
const hasTextAbsence = profileHasPassedCheck(result, ["text_absent", "selector_text_absent"]);
|
|
886
980
|
const hasMeasuredStateChange = hasNaturalInput || hasCanvasChange || valueReceipts.some((item) => setupReturnSummaryValue(item, ["changed"]) === true || setupReturnSummaryValue(item, ["nonWhiteDelta", "darkDelta", "pixelDelta", "movementDelta"]) !== void 0);
|
|
887
981
|
const hasRouteExitAffordanceReceipt = profileHasRouteExitAffordanceReceipt(valueReceipts);
|
|
982
|
+
const hasCleanupBoundaryAffordanceReceipt = profileHasCleanupBoundaryAffordanceReceipt(valueReceipts);
|
|
888
983
|
const hasOfflineAudioMetricsReceipt = profileHasOfflineAudioMetricsReceipt(valueReceipts);
|
|
889
984
|
const hasActiveRouteLocalProofReceipt = profileHasActiveRouteLocalProofReceipt(valueReceipts);
|
|
890
985
|
const hasTerminalLossReceipt = profileHasTerminalLossReceipt(valueReceipts);
|
|
@@ -893,6 +988,8 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
893
988
|
const hasControlledSuccessLaunchReceipt = profileHasControlledLaunchReceipt(valueReceipts, "success");
|
|
894
989
|
const hasRouteContinuationReceipt = profileHasRouteContinuationReceipt(valueReceipts);
|
|
895
990
|
const hasRecoveredStateReceipt = profileHasRecoveredStateReceipt(valueReceipts);
|
|
991
|
+
const hasGeneratedOutputContract = profileMetadataHasGeneratedOutputContract(metadata);
|
|
992
|
+
const hasGeneratedOutputReceipt = profileHasGeneratedOutputReceipt(valueReceipts);
|
|
896
993
|
const failedCleanupInventoryReason = profileFailedCleanupInventoryReason(setupViewports);
|
|
897
994
|
const passedCleanupInventoryReason = profilePassedCleanupInventoryReason(setupViewports);
|
|
898
995
|
if (text.includes("artifact link") || text.includes("artifact path")) {
|
|
@@ -946,6 +1043,13 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
946
1043
|
}
|
|
947
1044
|
return profileReceiptSignalStatus(hasTextAbsence, "absence check passed", "absence check missing");
|
|
948
1045
|
}
|
|
1046
|
+
if (text.includes("generated-output") || text.includes("generated output") || text.includes("output-size") || text.includes("output size") || (text.includes("output") || text.includes("result")) && (text.includes("mutation") || text.includes("final"))) {
|
|
1047
|
+
return profileReceiptSignalStatus(
|
|
1048
|
+
hasGeneratedOutputContract && hasGeneratedOutputReceipt,
|
|
1049
|
+
"generated-output mutation receipt present",
|
|
1050
|
+
"generated-output mutation receipt missing"
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
949
1053
|
if (text.includes("recovered") || text.includes("final state")) {
|
|
950
1054
|
return profileReceiptSignalStatus(hasStateContract || hasTextVisibility, "final state receipt present", "final state receipt missing");
|
|
951
1055
|
}
|
|
@@ -1002,6 +1106,13 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
1002
1106
|
"route continuation receipt missing"
|
|
1003
1107
|
);
|
|
1004
1108
|
}
|
|
1109
|
+
if (text.includes("cleanup") && text.includes("action") && (text.includes("visible ui") || text.includes("visible"))) {
|
|
1110
|
+
return profileReceiptSignalStatus(
|
|
1111
|
+
visibleCleanupActionCount > 0,
|
|
1112
|
+
`visible cleanup action receipt present (${visibleCleanupActionCount})`,
|
|
1113
|
+
"visible cleanup action receipt missing"
|
|
1114
|
+
);
|
|
1115
|
+
}
|
|
1005
1116
|
if (text.includes("through visible ui") || text.includes("visible ui action") || text.includes("ui-routed") || text.includes("ui routed") || text.includes("visible") && text.includes("route") && text.includes("exit") && text.includes("action") || text.includes("visible") && text.includes("mode") && text.includes("exit") && text.includes("action")) {
|
|
1006
1117
|
return profileReceiptSignalStatus(
|
|
1007
1118
|
visibleUiActionCount > 0,
|
|
@@ -1016,6 +1127,13 @@ function profilePackReceiptStatus(result, metadata, receipt) {
|
|
|
1016
1127
|
"affordance receipt missing"
|
|
1017
1128
|
);
|
|
1018
1129
|
}
|
|
1130
|
+
if (text.includes("cleanup") && (text.includes("affordance") || text.includes("control") || text.includes("boundary") || text.includes("inventory"))) {
|
|
1131
|
+
return profileReceiptSignalStatus(
|
|
1132
|
+
hasCleanupBoundaryAffordanceReceipt,
|
|
1133
|
+
"visible cleanup affordance receipt present",
|
|
1134
|
+
"visible cleanup affordance receipt missing"
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1019
1137
|
if (text.includes("retry") || text.includes("repair") || text.includes("reset") || text.includes("affordance")) {
|
|
1020
1138
|
return profileReceiptSignalStatus(hasStateContract || clickCount > 0, "affordance or transition receipt present", "affordance receipt missing");
|
|
1021
1139
|
}
|
|
@@ -1921,6 +2039,7 @@ function profileSetupSummaryMarkdown(result) {
|
|
|
1921
2039
|
const maxTaps = cliFiniteNumber(receipt.max_taps) ?? cliFiniteNumber(receipt.max_calls);
|
|
1922
2040
|
const tapBurstSize = cliFiniteNumber(receipt.tap_burst_size);
|
|
1923
2041
|
const conditionCheckCount = cliFiniteNumber(receipt.condition_check_count);
|
|
2042
|
+
const settleMs = cliFiniteNumber(receipt.settle_ms);
|
|
1924
2043
|
const elapsedMs = cliFiniteNumber(receipt.elapsed_ms);
|
|
1925
2044
|
const ok = receipt.ok === false ? "failed" : "ok";
|
|
1926
2045
|
const reason = cliString(receipt.reason);
|
|
@@ -1928,8 +2047,9 @@ function profileSetupSummaryMarkdown(result) {
|
|
|
1928
2047
|
const tapText = tapCount === void 0 ? "" : ` in ${tapCount}${maxTaps === void 0 ? "" : `/${maxTaps}`} tap(s)`;
|
|
1929
2048
|
const burstText = tapBurstSize === void 0 || tapBurstSize <= 1 ? "" : `, burst ${tapBurstSize}`;
|
|
1930
2049
|
const conditionCheckText = conditionCheckCount === void 0 ? "" : `, ${conditionCheckCount} check(s)`;
|
|
2050
|
+
const settleText = settleMs === void 0 || settleMs <= 0 ? "" : `, settle ${settleMs}ms`;
|
|
1931
2051
|
const elapsedText = elapsedMs === void 0 ? "" : `, elapsed ${elapsedMs}ms`;
|
|
1932
|
-
lines.push(`- ${name} tap_until: ${ok}, ${markdownInlineCode(selector)}${pointerType ? ` ${markdownInlineCode(pointerType)}` : ""}${inputDispatch ? ` via ${markdownInlineCode(inputDispatch)}` : ""}${coordinateText}${durationMs === void 0 ? "" : `, duration ${durationMs}ms`} until ${markdownInlineCode(untilPath)}${expected === void 0 ? "" : ` == ${markdownInlineCode(expected, 80)}`}${tapText}${burstText}${conditionCheckText}${elapsedText}${actual === void 0 ? "" : `, observed ${markdownInlineCode(actual, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
|
|
2052
|
+
lines.push(`- ${name} tap_until: ${ok}, ${markdownInlineCode(selector)}${pointerType ? ` ${markdownInlineCode(pointerType)}` : ""}${inputDispatch ? ` via ${markdownInlineCode(inputDispatch)}` : ""}${coordinateText}${durationMs === void 0 ? "" : `, duration ${durationMs}ms`} until ${markdownInlineCode(untilPath)}${expected === void 0 ? "" : ` == ${markdownInlineCode(expected, 80)}`}${tapText}${burstText}${conditionCheckText}${settleText}${elapsedText}${actual === void 0 ? "" : `, observed ${markdownInlineCode(actual, 80)}`}${reason ? `, reason ${markdownInlineCode(reason, 100)}` : ""}`);
|
|
1933
2053
|
}
|
|
1934
2054
|
if (tapUntilDetails.length > sampledTapUntilDetails.length) lines.push(`- ${tapUntilDetails.length - sampledTapUntilDetails.length} additional tap_until receipt(s) omitted.`);
|
|
1935
2055
|
const keyboardGroups = viewports.map((viewport) => {
|
|
@@ -2351,6 +2471,21 @@ function writeProfileOutput(outputDir, result) {
|
|
|
2351
2471
|
if (result.evidence?.dom_summary) writeFileSync(path.join(outputDir, "dom-summary.json"), `${JSON.stringify(result.evidence.dom_summary, null, 2)}
|
|
2352
2472
|
`);
|
|
2353
2473
|
}
|
|
2474
|
+
function writeRiddleJobReceipt(outputDir, input) {
|
|
2475
|
+
if (!outputDir) return;
|
|
2476
|
+
mkdirSync(outputDir, { recursive: true });
|
|
2477
|
+
writeFileSync(path.join(outputDir, "riddle-job.json"), `${JSON.stringify({
|
|
2478
|
+
version: "riddle-proof.riddle-job-receipt.v1",
|
|
2479
|
+
profile_name: input.profile.name,
|
|
2480
|
+
job_id: input.jobId,
|
|
2481
|
+
target_url: input.targetUrl,
|
|
2482
|
+
viewport: input.viewport || null,
|
|
2483
|
+
captured_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2484
|
+
created: input.created || null,
|
|
2485
|
+
recovery_command: `riddle-proof-loop run-profile recover --profile <profile> --job ${input.jobId} --output-dir ${outputDir}`
|
|
2486
|
+
}, null, 2)}
|
|
2487
|
+
`);
|
|
2488
|
+
}
|
|
2354
2489
|
async function readArtifactJson(artifact) {
|
|
2355
2490
|
const target = artifact.url || artifact.path;
|
|
2356
2491
|
if (!target) return void 0;
|
|
@@ -2554,6 +2689,43 @@ function profileForSplitViewport(profile, viewport) {
|
|
|
2554
2689
|
}
|
|
2555
2690
|
};
|
|
2556
2691
|
}
|
|
2692
|
+
function profileItemAppliesToAnySelectedViewport(item, viewports) {
|
|
2693
|
+
if (!item.viewports?.length) return true;
|
|
2694
|
+
const names = new Set(viewports.map((viewport) => viewport.name).filter(Boolean));
|
|
2695
|
+
return item.viewports.some((name) => names.has(name));
|
|
2696
|
+
}
|
|
2697
|
+
function profileForSelectedViewports(profile, viewports) {
|
|
2698
|
+
const suffix = viewports.map((viewport) => viewport.name || `${viewport.width}x${viewport.height}`).join("-");
|
|
2699
|
+
const setupActions = profile.target.setup_actions?.filter((action) => profileItemAppliesToAnySelectedViewport(action, viewports));
|
|
2700
|
+
return {
|
|
2701
|
+
...profile,
|
|
2702
|
+
name: `${profile.name}-${suffix}`,
|
|
2703
|
+
checks: profile.checks.filter((check) => profileItemAppliesToAnySelectedViewport(check, viewports)),
|
|
2704
|
+
target: {
|
|
2705
|
+
...profile.target,
|
|
2706
|
+
viewports,
|
|
2707
|
+
...setupActions ? { setup_actions: setupActions } : {}
|
|
2708
|
+
},
|
|
2709
|
+
metadata: {
|
|
2710
|
+
...profile.metadata || {},
|
|
2711
|
+
selected_parent_profile: profile.name,
|
|
2712
|
+
selected_viewports: viewports.map((viewport) => viewport.name || `${viewport.width}x${viewport.height}`)
|
|
2713
|
+
}
|
|
2714
|
+
};
|
|
2715
|
+
}
|
|
2716
|
+
function profileWithSelectedViewportNamesForCli(profile, options) {
|
|
2717
|
+
const names = runProfileViewportNamesOption(options);
|
|
2718
|
+
if (!names.length) return profile;
|
|
2719
|
+
const requested = new Set(names);
|
|
2720
|
+
const viewports = profile.target.viewports.filter((viewport) => viewport.name && requested.has(viewport.name));
|
|
2721
|
+
const matched = new Set(viewports.map((viewport) => viewport.name).filter(Boolean));
|
|
2722
|
+
const missing = names.filter((name) => !matched.has(name));
|
|
2723
|
+
if (missing.length) {
|
|
2724
|
+
const available = profile.target.viewports.map((viewport) => viewport.name).filter(Boolean).join(", ") || "none";
|
|
2725
|
+
throw new Error(`Unknown --viewport-name ${missing.join(", ")}. Available viewport names: ${available}.`);
|
|
2726
|
+
}
|
|
2727
|
+
return profileForSelectedViewports(profile, viewports);
|
|
2728
|
+
}
|
|
2557
2729
|
function safeProfileOutputSegment(value) {
|
|
2558
2730
|
const safe = value.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
2559
2731
|
return safe || "viewport";
|
|
@@ -2742,6 +2914,13 @@ async function runSingleRiddleProfileForCli(profile, options, input) {
|
|
|
2742
2914
|
const directResult = extractRiddleProofProfileResult(created);
|
|
2743
2915
|
return directResult ? withRiddleMetadata(withProfileMetadata(profile, directResult), { artifacts: collectRiddleProfileArtifactRefs(created) }) : createRiddleProofProfileInsufficientResult({ profile, runner, error: "Riddle run response was missing job_id.", artifacts: collectRiddleProfileArtifactRefs(created) });
|
|
2744
2916
|
}
|
|
2917
|
+
writeRiddleJobReceipt(input.outputDir, {
|
|
2918
|
+
profile,
|
|
2919
|
+
jobId,
|
|
2920
|
+
targetUrl,
|
|
2921
|
+
viewport: profile.target.viewports[0],
|
|
2922
|
+
created
|
|
2923
|
+
});
|
|
2745
2924
|
poll = await client.pollJob(jobId, pollOptions);
|
|
2746
2925
|
if (attempt < retryLimit && shouldRetryUnsubmittedRiddleJob(poll)) {
|
|
2747
2926
|
const recoveredResult = await recoverProfileResultFromRiddleArtifacts(profile, {
|
|
@@ -2818,10 +2997,9 @@ async function runSplitViewportProfileForCli(profile, options, input) {
|
|
|
2818
2997
|
const childRuns = [];
|
|
2819
2998
|
for (const viewport of profile.target.viewports) {
|
|
2820
2999
|
const childProfile = profileForSplitViewport(profile, viewport);
|
|
2821
|
-
const
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
}
|
|
3000
|
+
const childOutputDir = outputDir ? splitViewportOutputDir(outputDir, viewport.name, seenOutputNames) : void 0;
|
|
3001
|
+
const result2 = await runSingleRiddleProfileForCli(childProfile, options, { ...input, outputDir: childOutputDir });
|
|
3002
|
+
if (childOutputDir) writeProfileOutput(childOutputDir, result2);
|
|
2825
3003
|
childRuns.push({ viewport, profile: childProfile, result: result2 });
|
|
2826
3004
|
}
|
|
2827
3005
|
const artifacts = childRuns.flatMap(splitViewportArtifactRefs);
|
|
@@ -2843,6 +3021,51 @@ async function runSplitViewportProfileForCli(profile, options, input) {
|
|
|
2843
3021
|
});
|
|
2844
3022
|
return withSplitViewportWarnings(profile, withSplitViewportChildStatusCheck(profile, result, childRuns));
|
|
2845
3023
|
}
|
|
3024
|
+
async function recoverProfileForCli(profile, options) {
|
|
3025
|
+
const runner = optionString(options, "runner") || "riddle";
|
|
3026
|
+
if (runner !== "riddle") {
|
|
3027
|
+
throw new Error(`Unsupported --runner ${runner}. The current CLI supports --runner riddle.`);
|
|
3028
|
+
}
|
|
3029
|
+
const jobId = optionString(options, "job") ?? optionString(options, "jobId");
|
|
3030
|
+
if (!jobId) throw new Error("run-profile recover requires --job <job-id>.");
|
|
3031
|
+
const client = createRiddleApiClient(riddleClientConfig(options));
|
|
3032
|
+
let artifactPayload;
|
|
3033
|
+
try {
|
|
3034
|
+
artifactPayload = await client.requestJson(`/v1/jobs/${jobId}/artifacts`);
|
|
3035
|
+
} catch (error) {
|
|
3036
|
+
return createRiddleProofProfileEnvironmentBlockedResult({
|
|
3037
|
+
profile,
|
|
3038
|
+
runner,
|
|
3039
|
+
error,
|
|
3040
|
+
riddle: { job_id: jobId, terminal: false }
|
|
3041
|
+
});
|
|
3042
|
+
}
|
|
3043
|
+
const artifacts = collectRiddleProfileArtifactRefs(artifactPayload);
|
|
3044
|
+
const artifactStatus = riddleArtifactsPayloadStatus(artifactPayload);
|
|
3045
|
+
const terminal = artifactStatus ? isTerminalRiddleJobStatus(artifactStatus) : artifacts.length > 0;
|
|
3046
|
+
const recovered = await profileResultFromRiddleArtifacts(profile, artifacts, [artifactPayload]);
|
|
3047
|
+
if (recovered) {
|
|
3048
|
+
return withRiddleMetadata(recovered, {
|
|
3049
|
+
job_id: jobId,
|
|
3050
|
+
status: artifactStatus,
|
|
3051
|
+
terminal,
|
|
3052
|
+
artifacts,
|
|
3053
|
+
artifactRecovery: true
|
|
3054
|
+
});
|
|
3055
|
+
}
|
|
3056
|
+
return createRiddleProofProfileInsufficientResult({
|
|
3057
|
+
profile,
|
|
3058
|
+
runner,
|
|
3059
|
+
error: artifacts.length ? `Riddle job ${jobId} artifacts were recovered without a proof result.` : `Riddle job ${jobId} had no recoverable artifacts.`,
|
|
3060
|
+
riddle: {
|
|
3061
|
+
job_id: jobId,
|
|
3062
|
+
status: artifactStatus,
|
|
3063
|
+
terminal,
|
|
3064
|
+
artifact_recovery: artifacts.length > 0
|
|
3065
|
+
},
|
|
3066
|
+
artifacts
|
|
3067
|
+
});
|
|
3068
|
+
}
|
|
2846
3069
|
async function runProfileForCli(profile, options) {
|
|
2847
3070
|
const runner = optionString(options, "runner") || "riddle";
|
|
2848
3071
|
if (runner !== "riddle") {
|
|
@@ -2852,7 +3075,7 @@ async function runProfileForCli(profile, options) {
|
|
|
2852
3075
|
if (runProfileSplitViewportsOption(options) && profile.target.viewports.length > 1) {
|
|
2853
3076
|
return runSplitViewportProfileForCli(profile, options, { client, runner });
|
|
2854
3077
|
}
|
|
2855
|
-
return runSingleRiddleProfileForCli(profile, options, { client, runner });
|
|
3078
|
+
return runSingleRiddleProfileForCli(profile, options, { client, runner, outputDir: profileOutputDirOption(options) });
|
|
2856
3079
|
}
|
|
2857
3080
|
function requestForRun(options) {
|
|
2858
3081
|
const statePath = optionString(options, "statePath");
|
|
@@ -2901,8 +3124,8 @@ async function main() {
|
|
|
2901
3124
|
return;
|
|
2902
3125
|
}
|
|
2903
3126
|
if (command === "run-profile") {
|
|
2904
|
-
const profile = normalizeProfileForCli(options);
|
|
2905
|
-
const result = await runProfileForCli(profile, options);
|
|
3127
|
+
const profile = profileWithSelectedViewportNamesForCli(normalizeProfileForCli(options), options);
|
|
3128
|
+
const result = positional[1] === "recover" ? await recoverProfileForCli(profile, options) : await runProfileForCli(profile, options);
|
|
2906
3129
|
writeProfileOutput(profileOutputDirOption(options), result);
|
|
2907
3130
|
const diagnosticLine = profileCliDiagnosticLine(result);
|
|
2908
3131
|
if (diagnosticLine && optionBoolean(options, "quiet") !== true) {
|
package/dist/index.cjs
CHANGED
|
@@ -9368,6 +9368,7 @@ function profileSetupTapUntilReceipts(results) {
|
|
|
9368
9368
|
max_taps: result.max_taps ?? result.max_calls ?? null,
|
|
9369
9369
|
tap_burst_size: result.tap_burst_size ?? null,
|
|
9370
9370
|
condition_check_count: result.condition_check_count ?? null,
|
|
9371
|
+
settle_ms: result.settle_ms ?? null,
|
|
9371
9372
|
elapsed_ms: result.elapsed_ms ?? null,
|
|
9372
9373
|
interval_ms: result.interval_ms ?? null,
|
|
9373
9374
|
timeout_ms: result.timeout_ms ?? null,
|
|
@@ -10013,6 +10014,10 @@ function normalizeSetupAction(input, index) {
|
|
|
10013
10014
|
if (type === "tap_until" && tapBurstSize !== void 0 && (!Number.isInteger(tapBurstSize) || tapBurstSize < 1 || tapBurstSize > 100)) {
|
|
10014
10015
|
throw new Error(`target.setup_actions[${index}].tap_burst_size must be an integer from 1 to 100.`);
|
|
10015
10016
|
}
|
|
10017
|
+
const settleMs = type === "tap_until" ? numberValue3(valueFromOwn(input, "settle_ms", "settleMs", "predicate_settle_ms", "predicateSettleMs", "post_burst_wait_ms", "postBurstWaitMs", "after_burst_ms", "afterBurstMs", "settle_after_tap_ms", "settleAfterTapMs")) : void 0;
|
|
10018
|
+
if (type === "tap_until" && settleMs !== void 0 && (!Number.isInteger(settleMs) || settleMs < 0 || settleMs > 1e4)) {
|
|
10019
|
+
throw new Error(`target.setup_actions[${index}].settle_ms must be an integer from 0 to 10000.`);
|
|
10020
|
+
}
|
|
10016
10021
|
const intervalMs = numberValue3(valueFromOwn(input, "interval_ms", "intervalMs", "poll_ms", "pollMs", "call_interval_ms", "callIntervalMs"));
|
|
10017
10022
|
if ((type === "window_call_until" || type === "tap_until") && intervalMs !== void 0 && (!Number.isInteger(intervalMs) || intervalMs < 0 || intervalMs > 5e3)) {
|
|
10018
10023
|
throw new Error(`target.setup_actions[${index}].interval_ms must be an integer from 0 to 5000.`);
|
|
@@ -10061,6 +10066,7 @@ function normalizeSetupAction(input, index) {
|
|
|
10061
10066
|
until_expected_value: hasUntilExpectedValue ? toJsonValue(valueFromOwn(input, "until_expected_value", "untilExpectedValue", "until_expected", "untilExpected", "until_value", "untilValue", "expected_value", "expectedValue", "expected")) : void 0,
|
|
10062
10067
|
max_calls: maxCalls,
|
|
10063
10068
|
tap_burst_size: tapBurstSize,
|
|
10069
|
+
settle_ms: settleMs,
|
|
10064
10070
|
interval_ms: intervalMs,
|
|
10065
10071
|
expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
|
|
10066
10072
|
min_value: minValue,
|
|
@@ -13302,6 +13308,7 @@ function profileSetupTapUntilReceipts(results) {
|
|
|
13302
13308
|
max_taps: result.max_taps ?? result.max_calls ?? null,
|
|
13303
13309
|
tap_burst_size: result.tap_burst_size ?? null,
|
|
13304
13310
|
condition_check_count: result.condition_check_count ?? null,
|
|
13311
|
+
settle_ms: result.settle_ms ?? null,
|
|
13305
13312
|
elapsed_ms: result.elapsed_ms ?? null,
|
|
13306
13313
|
interval_ms: result.interval_ms ?? null,
|
|
13307
13314
|
timeout_ms: result.timeout_ms ?? null,
|
|
@@ -15293,6 +15300,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
15293
15300
|
if (!hasUntilExpected) return { ...base, until_path: untilPath, reason: "missing_until_expected_value" };
|
|
15294
15301
|
const maxTaps = Math.min(100, Math.max(1, Math.floor(setupNumber(action.max_taps ?? action.maxTaps ?? action.tap_limit ?? action.tapLimit ?? action.max_calls ?? action.maxCalls ?? action.max_attempts ?? action.maxAttempts ?? action.attempts, 1) || 1)));
|
|
15295
15302
|
const tapBurstSize = Math.min(maxTaps, Math.min(100, Math.max(1, Math.floor(setupNumber(action.tap_burst_size ?? action.tapBurstSize ?? action.burst_size ?? action.burstSize ?? action.check_every_taps ?? action.checkEveryTaps ?? action.predicate_interval_taps ?? action.predicateIntervalTaps, 1) || 1))));
|
|
15303
|
+
const settleMs = Math.min(10000, Math.max(0, Math.floor(setupNumber(action.settle_ms ?? action.settleMs ?? action.predicate_settle_ms ?? action.predicateSettleMs ?? action.post_burst_wait_ms ?? action.postBurstWaitMs ?? action.after_burst_ms ?? action.afterBurstMs ?? action.settle_after_tap_ms ?? action.settleAfterTapMs, 0) || 0)));
|
|
15296
15304
|
const intervalMs = Math.min(5000, Math.max(0, Math.floor(setupNumber(action.interval_ms ?? action.intervalMs ?? action.poll_ms ?? action.pollMs ?? action.tap_interval_ms ?? action.tapIntervalMs, 100) || 0)));
|
|
15297
15305
|
const scope = await setupActionScope(action, timeout);
|
|
15298
15306
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
@@ -15318,6 +15326,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
15318
15326
|
max_calls: maxTaps,
|
|
15319
15327
|
tap_burst_size: tapBurstSize,
|
|
15320
15328
|
condition_check_count: conditionCheckCount,
|
|
15329
|
+
settle_ms: settleMs,
|
|
15321
15330
|
elapsed_ms: elapsedMs,
|
|
15322
15331
|
interval_ms: intervalMs,
|
|
15323
15332
|
timeout_ms: timeout,
|
|
@@ -15330,6 +15339,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
15330
15339
|
tapCount += 1;
|
|
15331
15340
|
if (tapCount < maxTaps && burstIndex < burstCount - 1 && intervalMs) await page.waitForTimeout(intervalMs);
|
|
15332
15341
|
}
|
|
15342
|
+
if (settleMs) await page.waitForTimeout(settleMs);
|
|
15333
15343
|
lastPredicateResult = await setupReadWindowValue(scope.context, untilPath);
|
|
15334
15344
|
conditionCheckCount += 1;
|
|
15335
15345
|
if (lastPredicateResult.ok && setupValuesEqual(lastPredicateResult.value, untilExpected)) {
|
|
@@ -15347,6 +15357,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
15347
15357
|
max_calls: maxTaps,
|
|
15348
15358
|
tap_burst_size: tapBurstSize,
|
|
15349
15359
|
condition_check_count: conditionCheckCount,
|
|
15360
|
+
settle_ms: settleMs,
|
|
15350
15361
|
elapsed_ms: elapsedMs,
|
|
15351
15362
|
interval_ms: intervalMs,
|
|
15352
15363
|
timeout_ms: timeout,
|
|
@@ -15367,6 +15378,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
15367
15378
|
max_calls: maxTaps,
|
|
15368
15379
|
tap_burst_size: tapBurstSize,
|
|
15369
15380
|
condition_check_count: conditionCheckCount,
|
|
15381
|
+
settle_ms: settleMs,
|
|
15370
15382
|
elapsed_ms: elapsedMs,
|
|
15371
15383
|
interval_ms: intervalMs,
|
|
15372
15384
|
timeout_ms: timeout,
|
package/dist/index.js
CHANGED
|
@@ -62,7 +62,7 @@ import {
|
|
|
62
62
|
resolveRiddleProofProfileTimeoutSec,
|
|
63
63
|
slugifyRiddleProofProfileName,
|
|
64
64
|
summarizeRiddleProofProfileResult
|
|
65
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-OUZKZ5U4.js";
|
|
66
66
|
import {
|
|
67
67
|
DEFAULT_RIDDLE_API_BASE_URL,
|
|
68
68
|
DEFAULT_RIDDLE_API_KEY_FILE,
|
package/dist/profile.cjs
CHANGED
|
@@ -682,6 +682,7 @@ function profileSetupTapUntilReceipts(results) {
|
|
|
682
682
|
max_taps: result.max_taps ?? result.max_calls ?? null,
|
|
683
683
|
tap_burst_size: result.tap_burst_size ?? null,
|
|
684
684
|
condition_check_count: result.condition_check_count ?? null,
|
|
685
|
+
settle_ms: result.settle_ms ?? null,
|
|
685
686
|
elapsed_ms: result.elapsed_ms ?? null,
|
|
686
687
|
interval_ms: result.interval_ms ?? null,
|
|
687
688
|
timeout_ms: result.timeout_ms ?? null,
|
|
@@ -1327,6 +1328,10 @@ function normalizeSetupAction(input, index) {
|
|
|
1327
1328
|
if (type === "tap_until" && tapBurstSize !== void 0 && (!Number.isInteger(tapBurstSize) || tapBurstSize < 1 || tapBurstSize > 100)) {
|
|
1328
1329
|
throw new Error(`target.setup_actions[${index}].tap_burst_size must be an integer from 1 to 100.`);
|
|
1329
1330
|
}
|
|
1331
|
+
const settleMs = type === "tap_until" ? numberValue(valueFromOwn(input, "settle_ms", "settleMs", "predicate_settle_ms", "predicateSettleMs", "post_burst_wait_ms", "postBurstWaitMs", "after_burst_ms", "afterBurstMs", "settle_after_tap_ms", "settleAfterTapMs")) : void 0;
|
|
1332
|
+
if (type === "tap_until" && settleMs !== void 0 && (!Number.isInteger(settleMs) || settleMs < 0 || settleMs > 1e4)) {
|
|
1333
|
+
throw new Error(`target.setup_actions[${index}].settle_ms must be an integer from 0 to 10000.`);
|
|
1334
|
+
}
|
|
1330
1335
|
const intervalMs = numberValue(valueFromOwn(input, "interval_ms", "intervalMs", "poll_ms", "pollMs", "call_interval_ms", "callIntervalMs"));
|
|
1331
1336
|
if ((type === "window_call_until" || type === "tap_until") && intervalMs !== void 0 && (!Number.isInteger(intervalMs) || intervalMs < 0 || intervalMs > 5e3)) {
|
|
1332
1337
|
throw new Error(`target.setup_actions[${index}].interval_ms must be an integer from 0 to 5000.`);
|
|
@@ -1375,6 +1380,7 @@ function normalizeSetupAction(input, index) {
|
|
|
1375
1380
|
until_expected_value: hasUntilExpectedValue ? toJsonValue(valueFromOwn(input, "until_expected_value", "untilExpectedValue", "until_expected", "untilExpected", "until_value", "untilValue", "expected_value", "expectedValue", "expected")) : void 0,
|
|
1376
1381
|
max_calls: maxCalls,
|
|
1377
1382
|
tap_burst_size: tapBurstSize,
|
|
1383
|
+
settle_ms: settleMs,
|
|
1378
1384
|
interval_ms: intervalMs,
|
|
1379
1385
|
expected_value: hasExpectedValue ? toJsonValue(rawExpectedValue) : void 0,
|
|
1380
1386
|
min_value: minValue,
|
|
@@ -4616,6 +4622,7 @@ function profileSetupTapUntilReceipts(results) {
|
|
|
4616
4622
|
max_taps: result.max_taps ?? result.max_calls ?? null,
|
|
4617
4623
|
tap_burst_size: result.tap_burst_size ?? null,
|
|
4618
4624
|
condition_check_count: result.condition_check_count ?? null,
|
|
4625
|
+
settle_ms: result.settle_ms ?? null,
|
|
4619
4626
|
elapsed_ms: result.elapsed_ms ?? null,
|
|
4620
4627
|
interval_ms: result.interval_ms ?? null,
|
|
4621
4628
|
timeout_ms: result.timeout_ms ?? null,
|
|
@@ -6607,6 +6614,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
6607
6614
|
if (!hasUntilExpected) return { ...base, until_path: untilPath, reason: "missing_until_expected_value" };
|
|
6608
6615
|
const maxTaps = Math.min(100, Math.max(1, Math.floor(setupNumber(action.max_taps ?? action.maxTaps ?? action.tap_limit ?? action.tapLimit ?? action.max_calls ?? action.maxCalls ?? action.max_attempts ?? action.maxAttempts ?? action.attempts, 1) || 1)));
|
|
6609
6616
|
const tapBurstSize = Math.min(maxTaps, Math.min(100, Math.max(1, Math.floor(setupNumber(action.tap_burst_size ?? action.tapBurstSize ?? action.burst_size ?? action.burstSize ?? action.check_every_taps ?? action.checkEveryTaps ?? action.predicate_interval_taps ?? action.predicateIntervalTaps, 1) || 1))));
|
|
6617
|
+
const settleMs = Math.min(10000, Math.max(0, Math.floor(setupNumber(action.settle_ms ?? action.settleMs ?? action.predicate_settle_ms ?? action.predicateSettleMs ?? action.post_burst_wait_ms ?? action.postBurstWaitMs ?? action.after_burst_ms ?? action.afterBurstMs ?? action.settle_after_tap_ms ?? action.settleAfterTapMs, 0) || 0)));
|
|
6610
6618
|
const intervalMs = Math.min(5000, Math.max(0, Math.floor(setupNumber(action.interval_ms ?? action.intervalMs ?? action.poll_ms ?? action.pollMs ?? action.tap_interval_ms ?? action.tapIntervalMs, 100) || 0)));
|
|
6611
6619
|
const scope = await setupActionScope(action, timeout);
|
|
6612
6620
|
if (!scope.ok) return setupScopeFailure(base, scope);
|
|
@@ -6632,6 +6640,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
6632
6640
|
max_calls: maxTaps,
|
|
6633
6641
|
tap_burst_size: tapBurstSize,
|
|
6634
6642
|
condition_check_count: conditionCheckCount,
|
|
6643
|
+
settle_ms: settleMs,
|
|
6635
6644
|
elapsed_ms: elapsedMs,
|
|
6636
6645
|
interval_ms: intervalMs,
|
|
6637
6646
|
timeout_ms: timeout,
|
|
@@ -6644,6 +6653,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
6644
6653
|
tapCount += 1;
|
|
6645
6654
|
if (tapCount < maxTaps && burstIndex < burstCount - 1 && intervalMs) await page.waitForTimeout(intervalMs);
|
|
6646
6655
|
}
|
|
6656
|
+
if (settleMs) await page.waitForTimeout(settleMs);
|
|
6647
6657
|
lastPredicateResult = await setupReadWindowValue(scope.context, untilPath);
|
|
6648
6658
|
conditionCheckCount += 1;
|
|
6649
6659
|
if (lastPredicateResult.ok && setupValuesEqual(lastPredicateResult.value, untilExpected)) {
|
|
@@ -6661,6 +6671,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
6661
6671
|
max_calls: maxTaps,
|
|
6662
6672
|
tap_burst_size: tapBurstSize,
|
|
6663
6673
|
condition_check_count: conditionCheckCount,
|
|
6674
|
+
settle_ms: settleMs,
|
|
6664
6675
|
elapsed_ms: elapsedMs,
|
|
6665
6676
|
interval_ms: intervalMs,
|
|
6666
6677
|
timeout_ms: timeout,
|
|
@@ -6681,6 +6692,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
6681
6692
|
max_calls: maxTaps,
|
|
6682
6693
|
tap_burst_size: tapBurstSize,
|
|
6683
6694
|
condition_check_count: conditionCheckCount,
|
|
6695
|
+
settle_ms: settleMs,
|
|
6684
6696
|
elapsed_ms: elapsedMs,
|
|
6685
6697
|
interval_ms: intervalMs,
|
|
6686
6698
|
timeout_ms: timeout,
|
package/dist/profile.d.cts
CHANGED
package/dist/profile.d.ts
CHANGED
package/dist/profile.js
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
resolveRiddleProofProfileTimeoutSec,
|
|
24
24
|
slugifyRiddleProofProfileName,
|
|
25
25
|
summarizeRiddleProofProfileResult
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-OUZKZ5U4.js";
|
|
27
27
|
export {
|
|
28
28
|
RIDDLE_PROOF_PROFILE_CHECK_TYPES,
|
|
29
29
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
@@ -292,7 +292,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
292
292
|
blocking?: boolean;
|
|
293
293
|
details?: Record<string, unknown>;
|
|
294
294
|
ok: boolean;
|
|
295
|
-
action: "
|
|
295
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
296
296
|
state_path: string;
|
|
297
297
|
stage: any;
|
|
298
298
|
summary: string;
|
|
@@ -382,7 +382,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
382
382
|
continueWithStage?: WorkflowStage | null;
|
|
383
383
|
blocking?: boolean;
|
|
384
384
|
details?: Record<string, unknown>;
|
|
385
|
-
action: "
|
|
385
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
386
386
|
state_path: string;
|
|
387
387
|
stage: any;
|
|
388
388
|
checkpoint: string;
|
|
@@ -659,7 +659,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
659
659
|
error?: undefined;
|
|
660
660
|
} | {
|
|
661
661
|
ok: boolean;
|
|
662
|
-
action: "
|
|
662
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
663
663
|
state_path: string;
|
|
664
664
|
stage: any;
|
|
665
665
|
summary: string;
|
|
@@ -292,7 +292,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
292
292
|
blocking?: boolean;
|
|
293
293
|
details?: Record<string, unknown>;
|
|
294
294
|
ok: boolean;
|
|
295
|
-
action: "
|
|
295
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
296
296
|
state_path: string;
|
|
297
297
|
stage: any;
|
|
298
298
|
summary: string;
|
|
@@ -382,7 +382,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
382
382
|
continueWithStage?: WorkflowStage | null;
|
|
383
383
|
blocking?: boolean;
|
|
384
384
|
details?: Record<string, unknown>;
|
|
385
|
-
action: "
|
|
385
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
386
386
|
state_path: string;
|
|
387
387
|
stage: any;
|
|
388
388
|
checkpoint: string;
|
|
@@ -659,7 +659,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
659
659
|
error?: undefined;
|
|
660
660
|
} | {
|
|
661
661
|
ok: boolean;
|
|
662
|
-
action: "
|
|
662
|
+
action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
|
|
663
663
|
state_path: string;
|
|
664
664
|
stage: any;
|
|
665
665
|
summary: string;
|