@riddledc/riddle-proof 0.8.3 → 0.8.5
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/dist/adapters/openclaw.js +4 -4
- package/dist/advanced/engine-harness.cjs +34 -12
- package/dist/advanced/engine-harness.js +4 -4
- package/dist/advanced/index.cjs +34 -12
- package/dist/advanced/index.d.cts +1 -1
- package/dist/advanced/index.d.ts +1 -1
- package/dist/advanced/index.js +6 -6
- package/dist/advanced/proof-run-engine.cjs +29 -9
- package/dist/advanced/proof-run-engine.d.cts +1 -1
- package/dist/advanced/proof-run-engine.d.ts +1 -1
- package/dist/advanced/proof-run-engine.js +1 -1
- package/dist/advanced/runner.js +4 -4
- package/dist/checkpoint.cjs +3 -1
- package/dist/checkpoint.js +1 -1
- package/dist/{chunk-SKIAZTQ7.js → chunk-4FOHZ7JG.js} +3 -1
- package/dist/{chunk-YB5ACBZE.js → chunk-BDFSMWTI.js} +5 -5
- package/dist/{chunk-U4FUFBSH.js → chunk-FMOYUYH2.js} +1 -1
- package/dist/{chunk-TZ3YMCDM.js → chunk-GMZ57RRY.js} +29 -9
- package/dist/{chunk-OIFHYMHP.js → chunk-OD5UNE57.js} +2 -2
- package/dist/{chunk-SMBZT46I.js → chunk-RBWSCU6V.js} +1 -1
- package/dist/{chunk-ZX45XGDJ.js → chunk-UIJ7X63P.js} +1 -1
- package/dist/{chunk-TNCDVE5O.js → chunk-YZUVEJ5B.js} +1 -1
- package/dist/cli/index.js +5 -5
- package/dist/cli.cjs +34 -12
- package/dist/cli.js +5 -5
- package/dist/engine-harness.cjs +34 -12
- package/dist/engine-harness.js +4 -4
- package/dist/index.cjs +34 -12
- package/dist/index.js +5 -5
- package/dist/openclaw.js +4 -4
- package/dist/{proof-run-engine-Rkd_hXB-.d.cts → proof-run-engine-B7DCPzpK.d.cts} +3 -3
- package/dist/{proof-run-engine-DxWW1VX1.d.ts → proof-run-engine-BomAcXhA.d.ts} +3 -3
- package/dist/proof-run-engine.cjs +29 -9
- package/dist/proof-run-engine.d.cts +1 -1
- package/dist/proof-run-engine.d.ts +1 -1
- package/dist/proof-run-engine.js +1 -1
- package/dist/run-card.js +2 -2
- package/dist/runner.js +4 -4
- package/dist/spec/checkpoint.cjs +3 -1
- package/dist/spec/checkpoint.js +1 -1
- package/dist/spec/index.cjs +3 -1
- package/dist/spec/index.js +3 -3
- package/dist/spec/run-card.js +2 -2
- package/dist/spec/state.js +3 -3
- package/dist/state.js +3 -3
- package/package.json +1 -1
- package/runtime/lib/util.py +57 -0
- package/runtime/lib/verify.py +158 -14
- package/runtime/tests/recon_verify_smoke.py +211 -0
|
@@ -249,6 +249,82 @@ class FakeRiddle:
|
|
|
249
249
|
'largeVisibleElements': [{'tag': 'button', 'text': 'Buy Now'}],
|
|
250
250
|
}),
|
|
251
251
|
}
|
|
252
|
+
if 'clickedSkipHashNavigation' in script:
|
|
253
|
+
page_state = {
|
|
254
|
+
'bodyTextLength': 180,
|
|
255
|
+
'visibleTextSample': 'Riddle Proof homepage main content',
|
|
256
|
+
'interactiveElements': 4,
|
|
257
|
+
'visibleInteractiveElements': 4,
|
|
258
|
+
'pathname': '/',
|
|
259
|
+
'search': '',
|
|
260
|
+
'hash': '#main-content',
|
|
261
|
+
'title': 'Riddle',
|
|
262
|
+
'buttons': ['Start Free'],
|
|
263
|
+
'headings': ['Riddle Proof'],
|
|
264
|
+
'links': [{'text': 'Skip to main content', 'href': '#main-content'}],
|
|
265
|
+
'canvasCount': 0,
|
|
266
|
+
'largeVisibleElements': [{'tag': 'main', 'text': 'Riddle Proof'}],
|
|
267
|
+
}
|
|
268
|
+
proof_evidence = {
|
|
269
|
+
'before': {'href': 'https://riddledc.com/'},
|
|
270
|
+
'action': 'clicked Skip to main content',
|
|
271
|
+
'after': {'href': 'https://riddledc.com/#main-content'},
|
|
272
|
+
'assertions': {
|
|
273
|
+
'startedOnHome': True,
|
|
274
|
+
'hashPreserved': True,
|
|
275
|
+
'mainContentFocused': True,
|
|
276
|
+
},
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
'ok': True,
|
|
280
|
+
'screenshots': [{'url': 'https://cdn.example.com/hash-after.png'}],
|
|
281
|
+
'outputs': [{'name': 'after-hash.png', 'url': 'https://cdn.example.com/hash-after.png'}],
|
|
282
|
+
'result': {'pageState': page_state, 'proofEvidence': proof_evidence},
|
|
283
|
+
'console': [
|
|
284
|
+
'RIDDLE_PROOF_STATE:' + json.dumps(page_state),
|
|
285
|
+
'RIDDLE_PROOF_EVIDENCE:' + json.dumps(proof_evidence),
|
|
286
|
+
],
|
|
287
|
+
'visual_diff': {
|
|
288
|
+
'diffPercentage': 1.2,
|
|
289
|
+
'differentPixels': 12000,
|
|
290
|
+
'totalPixels': 972000,
|
|
291
|
+
},
|
|
292
|
+
}
|
|
293
|
+
if 'pricingQueryHashDropsTerminal' in script:
|
|
294
|
+
message = (
|
|
295
|
+
'page.waitForURL: Timeout 15000ms exceeded.\n'
|
|
296
|
+
'=========================== logs ===========================\n'
|
|
297
|
+
'waiting for navigation until "load"\n'
|
|
298
|
+
' navigated to "https://riddledc.com/pricing/"'
|
|
299
|
+
)
|
|
300
|
+
page_state = {
|
|
301
|
+
'bodyTextLength': 260,
|
|
302
|
+
'visibleTextSample': 'Pricing One rate Browser Compute Example Costs',
|
|
303
|
+
'interactiveElements': 8,
|
|
304
|
+
'visibleInteractiveElements': 8,
|
|
305
|
+
'pathname': '/pricing/',
|
|
306
|
+
'search': '',
|
|
307
|
+
'hash': '',
|
|
308
|
+
'title': 'Pricing',
|
|
309
|
+
'buttons': [],
|
|
310
|
+
'headings': ['Pricing', 'Browser Compute'],
|
|
311
|
+
'links': [{'text': 'Pricing', 'href': '/pricing/?rp_probe=1#pricing-probe'}],
|
|
312
|
+
'canvasCount': 0,
|
|
313
|
+
'largeVisibleElements': [{'tag': 'main', 'text': 'Pricing'}],
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
'ok': True,
|
|
317
|
+
'screenshots': [{'url': 'https://cdn.example.com/pricing-no-query-hash.png'}],
|
|
318
|
+
'outputs': [{'name': 'after-pricing-query-hash.png', 'url': 'https://cdn.example.com/pricing-no-query-hash.png'}],
|
|
319
|
+
'result': {'pageState': page_state},
|
|
320
|
+
'console': [
|
|
321
|
+
'RIDDLE_PROOF_STATE:' + json.dumps(page_state),
|
|
322
|
+
'Uncaught exception: ' + message,
|
|
323
|
+
],
|
|
324
|
+
'_artifact_json': {
|
|
325
|
+
'proof.json': {'script_error': message},
|
|
326
|
+
},
|
|
327
|
+
}
|
|
252
328
|
if 'clickedProofNavigation' in script:
|
|
253
329
|
page_state = {
|
|
254
330
|
'bodyTextLength': 180,
|
|
@@ -1376,6 +1452,34 @@ def run_project_build_retries_after_clean_failure():
|
|
|
1376
1452
|
shutil.rmtree(tempdir)
|
|
1377
1453
|
|
|
1378
1454
|
|
|
1455
|
+
def run_invoke_retry_stops_on_playwright_locator_timeout():
|
|
1456
|
+
util = load_module('util_retry_timeout', UTIL_PATH)
|
|
1457
|
+
calls = []
|
|
1458
|
+
original_invoke = util.invoke
|
|
1459
|
+
original_sleep = util.time.sleep
|
|
1460
|
+
|
|
1461
|
+
def fake_invoke(tool, args, timeout=180):
|
|
1462
|
+
calls.append({'tool': tool, 'args': args, 'timeout': timeout})
|
|
1463
|
+
return {
|
|
1464
|
+
'ok': False,
|
|
1465
|
+
'error': 'locator.scrollIntoViewIfNeeded: Timeout 30000ms exceeded',
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
try:
|
|
1469
|
+
util.invoke = fake_invoke
|
|
1470
|
+
util.time.sleep = lambda _seconds: None
|
|
1471
|
+
result = util.invoke_retry('riddle_script', {'script': 'await page.locator("a").click();'}, retries=3, timeout=60)
|
|
1472
|
+
assert result['ok'] is False
|
|
1473
|
+
assert len(calls) == 1, calls
|
|
1474
|
+
calls.clear()
|
|
1475
|
+
generic = util.invoke_retry('riddle_preview', {'directory': '/tmp/nope'}, retries=3, timeout=60)
|
|
1476
|
+
assert generic['ok'] is False
|
|
1477
|
+
assert len(calls) == 3, calls
|
|
1478
|
+
finally:
|
|
1479
|
+
util.invoke = original_invoke
|
|
1480
|
+
util.time.sleep = original_sleep
|
|
1481
|
+
|
|
1482
|
+
|
|
1379
1483
|
def run_implement_records_detection_when_changes_missing():
|
|
1380
1484
|
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-implement-missing-'))
|
|
1381
1485
|
state_path = tempdir / 'state.json'
|
|
@@ -2381,6 +2485,110 @@ def run_verify_interaction_reverse_terminal_route_from_proof_evidence():
|
|
|
2381
2485
|
shutil.rmtree(tempdir, ignore_errors=True)
|
|
2382
2486
|
|
|
2383
2487
|
|
|
2488
|
+
def run_verify_interaction_hash_terminal_route_from_proof_evidence():
|
|
2489
|
+
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-interaction-hash-'))
|
|
2490
|
+
state_path = tempdir / 'state.json'
|
|
2491
|
+
try:
|
|
2492
|
+
state = base_state(tempdir, reference='before')
|
|
2493
|
+
state.update({
|
|
2494
|
+
'recon_status': 'ready_for_proof_plan',
|
|
2495
|
+
'author_status': 'ready',
|
|
2496
|
+
'proof_plan_status': 'ready',
|
|
2497
|
+
'implementation_status': 'changes_detected',
|
|
2498
|
+
'verification_mode': 'interaction',
|
|
2499
|
+
'server_path': '/',
|
|
2500
|
+
'before_cdn': 'https://cdn.example.com/before-home.png',
|
|
2501
|
+
'proof_plan': 'Start at /, click the skip link, and verify the terminal /#main-content route.',
|
|
2502
|
+
'capture_script': "clickedSkipHashNavigation(); await saveScreenshot('after-hash');",
|
|
2503
|
+
'recon_results': {
|
|
2504
|
+
'baselines': {'before': {'path': '/', 'url': 'https://cdn.example.com/before-home.png'}},
|
|
2505
|
+
},
|
|
2506
|
+
})
|
|
2507
|
+
write_state(state_path, state)
|
|
2508
|
+
os.environ['RIDDLE_PROOF_STATE_FILE'] = str(state_path)
|
|
2509
|
+
|
|
2510
|
+
fake = FakeRiddle()
|
|
2511
|
+
load_util_with_fake(fake)
|
|
2512
|
+
load_module('verify_interaction_hash_terminal_route', VERIFY_PATH)
|
|
2513
|
+
after_verify = json.loads(state_path.read_text())
|
|
2514
|
+
|
|
2515
|
+
assert after_verify['verify_status'] == 'evidence_captured'
|
|
2516
|
+
assert after_verify['route_expectation']['expected_path'] == '/#main-content'
|
|
2517
|
+
assert after_verify['route_expectation']['expected_hash'] == '#main-content'
|
|
2518
|
+
route = after_verify['proof_assessment_request']['semantic_context']['route']
|
|
2519
|
+
assert route['expected_after_path'] == '/#main-content'
|
|
2520
|
+
assert route['expected_terminal_hash'] == '#main-content'
|
|
2521
|
+
assert route['after_observed_path'] == '/#main-content'
|
|
2522
|
+
assert route['after_observed_hash'] == '#main-content'
|
|
2523
|
+
assert 'wrong route' not in after_verify['verify_results']['after']['observation']['reason']
|
|
2524
|
+
return {
|
|
2525
|
+
'ok': True,
|
|
2526
|
+
'expected_path': after_verify['route_expectation']['expected_path'],
|
|
2527
|
+
'after_observed_hash': route['after_observed_hash'],
|
|
2528
|
+
}
|
|
2529
|
+
finally:
|
|
2530
|
+
shutil.rmtree(tempdir, ignore_errors=True)
|
|
2531
|
+
|
|
2532
|
+
|
|
2533
|
+
def run_verify_interaction_authored_query_hash_mismatch_returns_author():
|
|
2534
|
+
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-interaction-query-hash-mismatch-'))
|
|
2535
|
+
state_path = tempdir / 'state.json'
|
|
2536
|
+
try:
|
|
2537
|
+
state = base_state(tempdir, reference='before')
|
|
2538
|
+
state.update({
|
|
2539
|
+
'recon_status': 'ready_for_proof_plan',
|
|
2540
|
+
'author_status': 'ready',
|
|
2541
|
+
'proof_plan_status': 'ready',
|
|
2542
|
+
'implementation_status': 'changes_detected',
|
|
2543
|
+
'implementation_mode': 'none',
|
|
2544
|
+
'require_diff': False,
|
|
2545
|
+
'allow_code_changes': False,
|
|
2546
|
+
'verification_mode': 'interaction',
|
|
2547
|
+
'server_path': '/',
|
|
2548
|
+
'before_cdn': 'https://cdn.example.com/before-home.png',
|
|
2549
|
+
'proof_plan': 'Start at /, click Pricing, and verify /pricing/?rp_probe=1#pricing-probe.',
|
|
2550
|
+
'capture_script': "pricingQueryHashDropsTerminal(); await page.waitForURL('/pricing/?rp_probe=1#pricing-probe');",
|
|
2551
|
+
'supervisor_author_packet': {
|
|
2552
|
+
'proof_plan': 'Click Pricing and prove the terminal query/hash route.',
|
|
2553
|
+
'capture_script': "pricingQueryHashDropsTerminal(); await page.waitForURL('/pricing/?rp_probe=1#pricing-probe');",
|
|
2554
|
+
'refined_inputs': {
|
|
2555
|
+
'server_path': '/',
|
|
2556
|
+
'expected_terminal_path': '/pricing/?rp_probe=1#pricing-probe',
|
|
2557
|
+
},
|
|
2558
|
+
},
|
|
2559
|
+
'recon_results': {
|
|
2560
|
+
'baselines': {'before': {'path': '/', 'url': 'https://cdn.example.com/before-home.png'}},
|
|
2561
|
+
},
|
|
2562
|
+
})
|
|
2563
|
+
write_state(state_path, state)
|
|
2564
|
+
os.environ['RIDDLE_PROOF_STATE_FILE'] = str(state_path)
|
|
2565
|
+
|
|
2566
|
+
fake = FakeRiddle()
|
|
2567
|
+
load_util_with_fake(fake)
|
|
2568
|
+
load_module('verify_interaction_authored_query_hash_mismatch', VERIFY_PATH)
|
|
2569
|
+
after_verify = json.loads(state_path.read_text())
|
|
2570
|
+
|
|
2571
|
+
request = after_verify['verify_decision_request']
|
|
2572
|
+
capture_quality = request['capture_quality']
|
|
2573
|
+
assert after_verify['verify_status'] == 'capture_incomplete'
|
|
2574
|
+
assert after_verify['route_expectation']['expected_query'] == 'rp_probe=1'
|
|
2575
|
+
assert after_verify['route_expectation']['expected_hash'] == '#pricing-probe'
|
|
2576
|
+
assert request['recommended_stage'] == 'author'
|
|
2577
|
+
assert request['continue_with_stage'] == 'author'
|
|
2578
|
+
assert capture_quality['recommended_stage'] == 'author'
|
|
2579
|
+
assert capture_quality['mismatch']['expected_path'] == '/pricing?rp_probe=1#pricing-probe'
|
|
2580
|
+
assert capture_quality['mismatch']['observed_after_path'] == '/pricing/'
|
|
2581
|
+
assert 'page.waitForURL: Timeout 15000ms exceeded' in capture_quality['summary']
|
|
2582
|
+
assert any('capture plan should be revised' in reason for reason in capture_quality['reasons'])
|
|
2583
|
+
return {
|
|
2584
|
+
'ok': True,
|
|
2585
|
+
'summary': capture_quality['summary'],
|
|
2586
|
+
'recommended_stage': request['recommended_stage'],
|
|
2587
|
+
}
|
|
2588
|
+
finally:
|
|
2589
|
+
shutil.rmtree(tempdir, ignore_errors=True)
|
|
2590
|
+
|
|
2591
|
+
|
|
2384
2592
|
def run_verify_capture_retry_surfaces_script_timeout():
|
|
2385
2593
|
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-capture-timeout-'))
|
|
2386
2594
|
state_path = tempdir / 'state.json'
|
|
@@ -2778,6 +2986,7 @@ if __name__ == '__main__':
|
|
|
2778
2986
|
'capture_diagnostics_redaction': run_capture_diagnostics_redact_sensitive_values(),
|
|
2779
2987
|
'apply_auth_context': run_apply_auth_context_passes_supported_auth_payloads(),
|
|
2780
2988
|
'run_project_build_retries_after_clean_failure': run_project_build_retries_after_clean_failure(),
|
|
2989
|
+
'invoke_retry_stops_on_playwright_locator_timeout': run_invoke_retry_stops_on_playwright_locator_timeout(),
|
|
2781
2990
|
'implement_records_detection_when_changes_missing': run_implement_records_detection_when_changes_missing(),
|
|
2782
2991
|
'implement_ignores_tool_noise_when_detecting_changes': run_implement_ignores_tool_noise_when_detecting_changes(),
|
|
2783
2992
|
'verify_quality_ignores_proof_telemetry_console_text': run_verify_quality_ignores_proof_telemetry_console_text(),
|
|
@@ -2798,6 +3007,8 @@ if __name__ == '__main__':
|
|
|
2798
3007
|
'remote_audit_verify_uses_default_capture_script': run_remote_audit_verify_uses_default_capture_script(),
|
|
2799
3008
|
'verify_interaction_terminal_route_from_proof_evidence': run_verify_interaction_terminal_route_from_proof_evidence(),
|
|
2800
3009
|
'verify_interaction_reverse_terminal_route_from_proof_evidence': run_verify_interaction_reverse_terminal_route_from_proof_evidence(),
|
|
3010
|
+
'verify_interaction_hash_terminal_route_from_proof_evidence': run_verify_interaction_hash_terminal_route_from_proof_evidence(),
|
|
3011
|
+
'verify_interaction_authored_query_hash_mismatch_returns_author': run_verify_interaction_authored_query_hash_mismatch_returns_author(),
|
|
2801
3012
|
'verify_capture_retry_surfaces_script_timeout': run_verify_capture_retry_surfaces_script_timeout(),
|
|
2802
3013
|
'missing_baseline_guard': run_verify_missing_baseline(),
|
|
2803
3014
|
'ship_supervisor_gate': run_ship_missing_supervisor_gate(),
|