@riddledc/riddle-proof 0.8.11 → 0.8.12

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.
Files changed (44) hide show
  1. package/dist/advanced/engine-harness.cjs +97 -12
  2. package/dist/advanced/engine-harness.js +2 -2
  3. package/dist/advanced/index.cjs +98 -12
  4. package/dist/advanced/index.d.cts +2 -2
  5. package/dist/advanced/index.d.ts +2 -2
  6. package/dist/advanced/index.js +4 -4
  7. package/dist/advanced/proof-run-core.cjs +31 -1
  8. package/dist/advanced/proof-run-core.d.cts +1 -1
  9. package/dist/advanced/proof-run-core.d.ts +1 -1
  10. package/dist/advanced/proof-run-core.js +3 -1
  11. package/dist/advanced/proof-run-engine.cjs +46 -12
  12. package/dist/advanced/proof-run-engine.d.cts +2 -2
  13. package/dist/advanced/proof-run-engine.d.ts +2 -2
  14. package/dist/advanced/proof-run-engine.js +2 -2
  15. package/dist/advanced/runner.js +2 -2
  16. package/dist/{chunk-5N5QFI2S.js → chunk-7GZY5PLT.js} +31 -1
  17. package/dist/{chunk-46DDSZJR.js → chunk-JBY2SU5U.js} +18 -12
  18. package/dist/{chunk-5N6MQCLC.js → chunk-NGX4SUQN.js} +1 -1
  19. package/dist/{chunk-BBUO7HM4.js → chunk-RTLA6CPP.js} +53 -1
  20. package/dist/{chunk-2PXL3RDB.js → chunk-SZUC4MDN.js} +1 -1
  21. package/dist/cli/index.js +3 -3
  22. package/dist/cli.cjs +97 -12
  23. package/dist/cli.js +3 -3
  24. package/dist/engine-harness.cjs +97 -12
  25. package/dist/engine-harness.js +2 -2
  26. package/dist/index.cjs +97 -12
  27. package/dist/index.js +3 -3
  28. package/dist/{proof-run-core-CE0jx7wL.d.cts → proof-run-core-CrpYH-qH.d.cts} +6 -3
  29. package/dist/{proof-run-core-CE0jx7wL.d.ts → proof-run-core-CrpYH-qH.d.ts} +6 -3
  30. package/dist/proof-run-core.cjs +31 -1
  31. package/dist/proof-run-core.d.cts +1 -1
  32. package/dist/proof-run-core.d.ts +1 -1
  33. package/dist/proof-run-core.js +3 -1
  34. package/dist/{proof-run-engine-B7DCPzpK.d.cts → proof-run-engine-C6vYAZd8.d.cts} +4 -4
  35. package/dist/{proof-run-engine-BomAcXhA.d.ts → proof-run-engine-h9C1lC0w.d.ts} +4 -4
  36. package/dist/proof-run-engine.cjs +46 -12
  37. package/dist/proof-run-engine.d.cts +2 -2
  38. package/dist/proof-run-engine.d.ts +2 -2
  39. package/dist/proof-run-engine.js +2 -2
  40. package/dist/runner.js +2 -2
  41. package/package.json +1 -1
  42. package/runtime/lib/verify.py +97 -11
  43. package/runtime/tests/recon_verify_smoke.py +154 -4
  44. package/runtime/tests/trust_boundary_regression.py +12 -0
@@ -345,7 +345,12 @@ class FakeRiddle:
345
345
  'version': 'riddle-proof.interaction.v1',
346
346
  'start': {'href': 'https://riddledc.com/'},
347
347
  'action': {'type': 'click', 'target': 'Pricing'},
348
- 'terminal': {'href': 'https://riddledc.com/pricing/?rp_probe=1#pricing-probe'},
348
+ 'terminal': {
349
+ 'pathname': '/pricing/',
350
+ 'search': '?rp_probe=1',
351
+ 'hash': '#pricing-probe',
352
+ 'href': 'https://riddledc.com/pricing/?rp_probe=1#pricing-probe',
353
+ },
349
354
  'afterUrl': 'https://riddledc.com/pricing/?rp_probe=1#pricing-probe',
350
355
  'routeMatched': True,
351
356
  'assertions': {
@@ -480,6 +485,36 @@ class FakeRiddle:
480
485
  'proof.json': {'script_error': message},
481
486
  },
482
487
  }
488
+ if 'interactionThrownError' in script:
489
+ message = 'Error: intentional-riddle-proof-0811-thrown-error'
490
+ page_state = {
491
+ 'bodyTextLength': 180,
492
+ 'visibleTextSample': 'Riddle Proof homepage hero Start Free',
493
+ 'interactiveElements': 4,
494
+ 'visibleInteractiveElements': 4,
495
+ 'pathname': '/',
496
+ 'search': '',
497
+ 'hash': '',
498
+ 'title': 'Riddle',
499
+ 'buttons': ['Start Free'],
500
+ 'headings': ['Riddle Proof'],
501
+ 'links': [],
502
+ 'canvasCount': 0,
503
+ 'largeVisibleElements': [{'tag': 'h1', 'text': 'Riddle Proof'}],
504
+ }
505
+ return {
506
+ 'ok': True,
507
+ 'screenshots': [{'url': 'https://cdn.example.com/thrown-error.png'}],
508
+ 'outputs': [{'name': 'after-thrown-error.png', 'url': 'https://cdn.example.com/thrown-error.png'}],
509
+ 'result': {'pageState': page_state},
510
+ 'console': [
511
+ 'RIDDLE_PROOF_STATE:' + json.dumps(page_state),
512
+ 'Uncaught exception: ' + message,
513
+ ],
514
+ '_artifact_json': {
515
+ 'proof.json': {'script_error': message},
516
+ },
517
+ }
483
518
  if 'after-proof' in script:
484
519
  after_url = 'https://cdn.example.com/after-artifact' if 'noVisualDelta' in script else 'https://cdn.example.com/after.png'
485
520
  outputs = [{'name': 'after.png', 'url': after_url}]
@@ -2568,6 +2603,58 @@ def run_verify_interaction_terminal_route_from_proof_evidence():
2568
2603
  shutil.rmtree(tempdir, ignore_errors=True)
2569
2604
 
2570
2605
 
2606
+ def run_verify_interaction_proof_evidence_overrides_stale_expected_path():
2607
+ tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-interaction-stale-route-'))
2608
+ state_path = tempdir / 'state.json'
2609
+ try:
2610
+ state = base_state(tempdir, reference='before')
2611
+ state.update({
2612
+ 'recon_status': 'ready_for_proof_plan',
2613
+ 'author_status': 'ready',
2614
+ 'proof_plan_status': 'ready',
2615
+ 'implementation_status': 'changes_detected',
2616
+ 'verification_mode': 'interaction',
2617
+ 'server_path': '/',
2618
+ 'expected_terminal_path': '/state',
2619
+ 'before_cdn': 'https://cdn.example.com/before-home.png',
2620
+ 'proof_plan': 'Start at /, click Proof, and verify the terminal /proof/ route.',
2621
+ 'capture_script': "clickedProofNavigation(); await saveScreenshot('after-proof');",
2622
+ 'supervisor_author_packet': {
2623
+ 'proof_plan': 'Click Proof and prove the terminal route.',
2624
+ 'capture_script': "clickedProofNavigation(); await saveScreenshot('after-proof');",
2625
+ 'refined_inputs': {
2626
+ 'server_path': '/',
2627
+ 'expected_terminal_path': '/state',
2628
+ },
2629
+ },
2630
+ 'recon_results': {
2631
+ 'baselines': {'before': {'path': '/', 'url': 'https://cdn.example.com/before-home.png'}},
2632
+ },
2633
+ })
2634
+ write_state(state_path, state)
2635
+ os.environ['RIDDLE_PROOF_STATE_FILE'] = str(state_path)
2636
+
2637
+ fake = FakeRiddle()
2638
+ load_util_with_fake(fake)
2639
+ load_module('verify_interaction_stale_route_uses_evidence', VERIFY_PATH)
2640
+ after_verify = json.loads(state_path.read_text())
2641
+
2642
+ assert after_verify['verify_status'] == 'evidence_captured'
2643
+ assert after_verify['route_expectation']['source'] == 'proof_evidence_contract'
2644
+ assert after_verify['route_expectation']['expected_path'] == '/proof'
2645
+ route = after_verify['proof_assessment_request']['semantic_context']['route']
2646
+ assert route['expected_after_path'] == '/proof'
2647
+ assert route['after_observed_path'] == '/proof'
2648
+ assert 'wrong route' not in after_verify['verify_results']['after']['observation']['reason']
2649
+ return {
2650
+ 'ok': True,
2651
+ 'expected_path': after_verify['route_expectation']['expected_path'],
2652
+ 'source': after_verify['route_expectation']['source'],
2653
+ }
2654
+ finally:
2655
+ shutil.rmtree(tempdir, ignore_errors=True)
2656
+
2657
+
2571
2658
  def run_verify_interaction_reverse_terminal_route_from_proof_evidence():
2572
2659
  tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-interaction-reverse-'))
2573
2660
  state_path = tempdir / 'state.json'
@@ -2751,9 +2838,11 @@ def run_verify_interaction_authored_query_hash_mismatch_blocks_with_evidence():
2751
2838
  assert after_verify['route_expectation']['expected_query'] == 'rp_probe=1'
2752
2839
  assert after_verify['route_expectation']['expected_hash'] == '#pricing-probe'
2753
2840
  capture_quality = request['capture_quality']
2754
- assert capture_quality['decision'] in ('revise_capture', 'failed_proof_evidence', 'visual_delta_unmeasured')
2755
- assert request['recommended_stage'] in ('author', 'verify')
2756
- assert request['continue_with_stage'] in ('author', 'verify')
2841
+ assert capture_quality['decision'] == 'failed_interaction_capture'
2842
+ assert request['recommended_stage'] is None
2843
+ assert request['continue_with_stage'] is None
2844
+ assert capture_quality['blocking'] is True
2845
+ assert capture_quality['terminal_blocker'] is True
2757
2846
  quality_text = json.dumps(capture_quality, sort_keys=True)
2758
2847
  assert 'page.waitForURL: Timeout 15000ms exceeded' in quality_text
2759
2848
  assert after_verify['proof_assessment_request'] == {}
@@ -2778,6 +2867,7 @@ def run_verify_interaction_authored_query_hash_mismatch_blocks_with_evidence():
2778
2867
  'ok': True,
2779
2868
  'summary': request['summary'],
2780
2869
  'recommended_stage': request['recommended_stage'],
2870
+ 'blocking': capture_quality['blocking'],
2781
2871
  }
2782
2872
  finally:
2783
2873
  shutil.rmtree(tempdir, ignore_errors=True)
@@ -2844,6 +2934,64 @@ def run_verify_interaction_query_hash_pass_uses_proof_evidence_route():
2844
2934
  shutil.rmtree(tempdir, ignore_errors=True)
2845
2935
 
2846
2936
 
2937
+ def run_verify_interaction_thrown_error_terminal_blocker():
2938
+ tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-interaction-thrown-error-'))
2939
+ state_path = tempdir / 'state.json'
2940
+ try:
2941
+ state = base_state(tempdir, reference='before')
2942
+ state.update({
2943
+ 'recon_status': 'ready_for_proof_plan',
2944
+ 'author_status': 'ready',
2945
+ 'proof_plan_status': 'ready',
2946
+ 'implementation_status': 'changes_detected',
2947
+ 'verification_mode': 'interaction',
2948
+ 'server_path': '/',
2949
+ 'before_cdn': 'https://cdn.example.com/before-home.png',
2950
+ 'proof_plan': 'Run a diagnostic interaction script that intentionally throws.',
2951
+ 'capture_script': "interactionThrownError();",
2952
+ 'recon_results': {
2953
+ 'baselines': {'before': {'path': '/', 'url': 'https://cdn.example.com/before-home.png'}},
2954
+ },
2955
+ })
2956
+ write_state(state_path, state)
2957
+ os.environ['RIDDLE_PROOF_STATE_FILE'] = str(state_path)
2958
+
2959
+ fake = FakeRiddle()
2960
+ load_util_with_fake(fake)
2961
+ load_module('verify_interaction_thrown_error_terminal_blocker', VERIFY_PATH)
2962
+ after_verify = json.loads(state_path.read_text())
2963
+
2964
+ assert after_verify['verify_status'] == 'capture_incomplete'
2965
+ assert after_verify['merge_recommendation'] == 'do-not-merge'
2966
+ assert after_verify['proof_assessment_request'] == {}
2967
+ capture_quality = after_verify['verify_decision_request']['capture_quality']
2968
+ assert capture_quality['decision'] == 'failed_interaction_capture'
2969
+ assert capture_quality['recommended_stage'] is None
2970
+ assert capture_quality['continue_with_stage'] is None
2971
+ assert capture_quality['blocking'] is True
2972
+ assert capture_quality['terminal_blocker'] is True
2973
+ capture_quality_text = json.dumps(capture_quality, sort_keys=True)
2974
+ assert 'intentional-riddle-proof-0811-thrown-error' in capture_quality_text
2975
+ assert after_verify['structured_interaction_capture_failure_summary']
2976
+ evidence = after_verify['evidence_bundle']['proof_evidence']
2977
+ if isinstance(evidence, list):
2978
+ evidence = next(
2979
+ record for record in evidence_records(evidence)
2980
+ if record.get('version') == 'riddle-proof.interaction.capture-failure.v1'
2981
+ )
2982
+ assert evidence['version'] == 'riddle-proof.interaction.capture-failure.v1'
2983
+ assert evidence['checks']['scriptCompleted'] is False
2984
+ assert evidence['checks']['authoredEvidenceReturned'] is False
2985
+ assert 'intentional-riddle-proof-0811-thrown-error' in evidence['capture_error']
2986
+ return {
2987
+ 'ok': True,
2988
+ 'decision': capture_quality['decision'],
2989
+ 'blocking': capture_quality['blocking'],
2990
+ }
2991
+ finally:
2992
+ shutil.rmtree(tempdir, ignore_errors=True)
2993
+
2994
+
2847
2995
  def run_verify_capture_retry_surfaces_script_timeout():
2848
2996
  tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-capture-timeout-'))
2849
2997
  state_path = tempdir / 'state.json'
@@ -3262,11 +3410,13 @@ if __name__ == '__main__':
3262
3410
  'verify_capture_retry': run_verify_capture_retry(),
3263
3411
  'remote_audit_verify_uses_default_capture_script': run_remote_audit_verify_uses_default_capture_script(),
3264
3412
  'verify_interaction_terminal_route_from_proof_evidence': run_verify_interaction_terminal_route_from_proof_evidence(),
3413
+ 'verify_interaction_proof_evidence_overrides_stale_expected_path': run_verify_interaction_proof_evidence_overrides_stale_expected_path(),
3265
3414
  'verify_interaction_reverse_terminal_route_from_proof_evidence': run_verify_interaction_reverse_terminal_route_from_proof_evidence(),
3266
3415
  'verify_interaction_prose_route_noise_uses_proof_evidence': run_verify_interaction_prose_route_noise_uses_proof_evidence(),
3267
3416
  'verify_interaction_hash_terminal_route_from_proof_evidence': run_verify_interaction_hash_terminal_route_from_proof_evidence(),
3268
3417
  'verify_interaction_authored_query_hash_mismatch_blocks_with_evidence': run_verify_interaction_authored_query_hash_mismatch_blocks_with_evidence(),
3269
3418
  'verify_interaction_query_hash_pass_uses_proof_evidence_route': run_verify_interaction_query_hash_pass_uses_proof_evidence_route(),
3419
+ 'verify_interaction_thrown_error_terminal_blocker': run_verify_interaction_thrown_error_terminal_blocker(),
3270
3420
  'verify_capture_retry_surfaces_script_timeout': run_verify_capture_retry_surfaces_script_timeout(),
3271
3421
  'missing_baseline_guard': run_verify_missing_baseline(),
3272
3422
  'ship_supervisor_gate': run_ship_missing_supervisor_gate(),
@@ -25,6 +25,12 @@ CASES = [
25
25
  'function': 'run_verify_interaction_terminal_route_from_proof_evidence',
26
26
  'expected_terminal': 'pass',
27
27
  },
28
+ {
29
+ 'name': 'route-change-retry-state-drift-ignored',
30
+ 'covers': ['route-changing interactions', 'proof-evidence-present'],
31
+ 'function': 'run_verify_interaction_proof_evidence_overrides_stale_expected_path',
32
+ 'expected_terminal': 'pass',
33
+ },
28
34
  {
29
35
  'name': 'route-change-reverse-pass',
30
36
  'covers': ['route-changing interactions'],
@@ -67,6 +73,12 @@ CASES = [
67
73
  'function': 'run_verify_preserves_proof_evidence_on_capture_script_error',
68
74
  'expected_terminal': 'specific_blocker',
69
75
  },
76
+ {
77
+ 'name': 'interaction-thrown-error-specific-blocker',
78
+ 'covers': ['thrown errors', 'invalid browser evidence'],
79
+ 'function': 'run_verify_interaction_thrown_error_terminal_blocker',
80
+ 'expected_terminal': 'specific_blocker',
81
+ },
70
82
  {
71
83
  'name': 'structured-proof-without-screenshot-pass',
72
84
  'covers': ['proof-evidence-present'],