@riddledc/riddle-proof 0.8.17 → 0.8.18
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.
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
"public_name": "Riddle Proof OC Flow Regression Pack",
|
|
5
5
|
"description": "Reusable regression pack for the trust boundary between browser evidence, verifier judgment, retry policy, wrapper checkpoint handling, and terminal status.",
|
|
6
6
|
"minimum_versions": {
|
|
7
|
-
"@riddledc/openclaw-riddle-proof": "0.4.
|
|
8
|
-
"@riddledc/riddle-proof": "0.8.
|
|
7
|
+
"@riddledc/openclaw-riddle-proof": "0.4.146",
|
|
8
|
+
"@riddledc/riddle-proof": "0.8.18"
|
|
9
9
|
},
|
|
10
10
|
"runtime_gate": {
|
|
11
11
|
"tool": "riddle_proof_status",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"required_cases": [
|
|
27
27
|
"route-change-forward-pass",
|
|
28
28
|
"route-change-retry-state-drift-ignored",
|
|
29
|
+
"route-change-proof-plan-placeholder-ignored",
|
|
29
30
|
"route-change-reverse-pass",
|
|
30
31
|
"route-change-reverse-nested-terminal-url-pass",
|
|
31
32
|
"query-hash-trailing-slash-pass",
|
package/package.json
CHANGED
package/runtime/lib/verify.py
CHANGED
|
@@ -2319,11 +2319,22 @@ def text_path_candidate(value):
|
|
|
2319
2319
|
return path_candidate(raw)
|
|
2320
2320
|
|
|
2321
2321
|
|
|
2322
|
+
PROSE_ROUTE_PLACEHOLDER_PATHS = {
|
|
2323
|
+
'/href',
|
|
2324
|
+
'/path',
|
|
2325
|
+
'/pathname',
|
|
2326
|
+
'/route',
|
|
2327
|
+
'/url',
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
|
|
2322
2331
|
def text_route_candidate(value):
|
|
2323
2332
|
candidate = text_path_candidate(value)
|
|
2324
2333
|
if not candidate:
|
|
2325
2334
|
return ''
|
|
2326
2335
|
parsed = urlparse(candidate)
|
|
2336
|
+
if (parsed.path or '').lower() in PROSE_ROUTE_PLACEHOLDER_PATHS and not parsed.query and not parsed.fragment:
|
|
2337
|
+
return ''
|
|
2327
2338
|
first_segment = next((part for part in (parsed.path or '').split('/') if part), '')
|
|
2328
2339
|
if first_segment and first_segment[:1].isupper():
|
|
2329
2340
|
return ''
|
|
@@ -2350,11 +2361,11 @@ def terminal_path_from_text(value):
|
|
|
2350
2361
|
def interaction_assertions_pass(value):
|
|
2351
2362
|
for record in proof_evidence_records(value):
|
|
2352
2363
|
if any(record.get(key) is False for key in (
|
|
2353
|
-
'passed', 'ok', 'proofReady', 'proof_ready', 'routeMatches', 'route_matches',
|
|
2364
|
+
'passed', 'pass', 'ok', 'success', 'proofReady', 'proof_ready', 'routeMatches', 'route_matches',
|
|
2354
2365
|
)):
|
|
2355
2366
|
return False
|
|
2356
2367
|
if any(record.get(key) is True for key in (
|
|
2357
|
-
'passed', 'ok', 'proofReady', 'proof_ready', 'interactionPassed', 'interaction_passed',
|
|
2368
|
+
'passed', 'pass', 'ok', 'success', 'proofReady', 'proof_ready', 'interactionPassed', 'interaction_passed',
|
|
2358
2369
|
)):
|
|
2359
2370
|
return True
|
|
2360
2371
|
for key in ('assertions', 'checks', 'predicates', 'expectations'):
|
|
@@ -2369,7 +2380,7 @@ def interaction_assertions_pass(value):
|
|
|
2369
2380
|
if isinstance(item, bool):
|
|
2370
2381
|
bools.append(item)
|
|
2371
2382
|
elif isinstance(item, dict):
|
|
2372
|
-
for flag_key in ('passed', 'ok', 'valid'):
|
|
2383
|
+
for flag_key in ('passed', 'pass', 'ok', 'valid', 'success'):
|
|
2373
2384
|
if isinstance(item.get(flag_key), bool):
|
|
2374
2385
|
bools.append(item.get(flag_key))
|
|
2375
2386
|
break
|
|
@@ -2381,6 +2392,7 @@ def interaction_assertions_pass(value):
|
|
|
2381
2392
|
INTERACTION_ASSERTION_CONTAINER_KEYS = ('assertions', 'checks', 'predicates', 'expectations')
|
|
2382
2393
|
INTERACTION_FAILURE_FLAG_KEYS = (
|
|
2383
2394
|
'passed',
|
|
2395
|
+
'pass',
|
|
2384
2396
|
'ok',
|
|
2385
2397
|
'valid',
|
|
2386
2398
|
'success',
|
|
@@ -444,6 +444,62 @@ class FakeRiddle:
|
|
|
444
444
|
'totalPixels': 972000,
|
|
445
445
|
},
|
|
446
446
|
}
|
|
447
|
+
if 'clickedProofNavigationOcLiveShape' in script:
|
|
448
|
+
page_state = {
|
|
449
|
+
'bodyTextLength': 4113,
|
|
450
|
+
'visibleTextSample': 'RIDDLE PROOF Turn a URL into evidence an agent can cite.',
|
|
451
|
+
'interactiveElements': 6,
|
|
452
|
+
'visibleInteractiveElements': 6,
|
|
453
|
+
'pathname': '/proof/',
|
|
454
|
+
'href': 'https://riddledc.com/proof/',
|
|
455
|
+
'title': 'Riddle Proof',
|
|
456
|
+
'buttons': ['Proof'],
|
|
457
|
+
'headings': ['Riddle Proof'],
|
|
458
|
+
'links': [],
|
|
459
|
+
'canvasCount': 0,
|
|
460
|
+
'largeVisibleElements': [{'tag': 'h1', 'text': 'Riddle Proof'}],
|
|
461
|
+
}
|
|
462
|
+
proof_evidence = {
|
|
463
|
+
'version': 'riddle-proof.interaction.v1',
|
|
464
|
+
'expectedUrl': 'https://riddledc.com/proof/',
|
|
465
|
+
'routeExpectationSource': 'capture_script.expectedUrl',
|
|
466
|
+
'startRoute': {'url': 'https://riddledc.com/', 'pathname': '/'},
|
|
467
|
+
'terminalRoute': {'url': 'https://riddledc.com/proof/', 'pathname': '/proof/'},
|
|
468
|
+
'action': {'type': 'click', 'target': 'visible Proof navigation link', 'clicked': True},
|
|
469
|
+
'startState': {'url': 'https://riddledc.com/', 'pathname': '/'},
|
|
470
|
+
'terminalState': {'url': 'https://riddledc.com/proof/', 'pathname': '/proof/'},
|
|
471
|
+
'assertions': [
|
|
472
|
+
{
|
|
473
|
+
'name': 'route expectation source is capture_script.expectedUrl',
|
|
474
|
+
'pass': True,
|
|
475
|
+
'routeExpectationSource': 'capture_script.expectedUrl',
|
|
476
|
+
'expectedUrl': 'https://riddledc.com/proof/',
|
|
477
|
+
},
|
|
478
|
+
{'name': 'start URL is production home', 'pass': True, 'startPathname': '/'},
|
|
479
|
+
{
|
|
480
|
+
'name': 'terminal URL matched expected proof route',
|
|
481
|
+
'pass': True,
|
|
482
|
+
'terminalUrl': 'https://riddledc.com/proof/',
|
|
483
|
+
},
|
|
484
|
+
{'name': 'Proof page content visible', 'pass': True},
|
|
485
|
+
],
|
|
486
|
+
'success': True,
|
|
487
|
+
}
|
|
488
|
+
return {
|
|
489
|
+
'ok': True,
|
|
490
|
+
'screenshots': [{'url': 'https://cdn.example.com/proof-after.png'}],
|
|
491
|
+
'outputs': [{'name': 'after-proof.png', 'url': 'https://cdn.example.com/proof-after.png'}],
|
|
492
|
+
'result': {'pageState': page_state, 'proofEvidence': proof_evidence},
|
|
493
|
+
'console': [
|
|
494
|
+
'RIDDLE_PROOF_STATE:' + json.dumps(page_state),
|
|
495
|
+
'RIDDLE_PROOF_EVIDENCE:' + json.dumps(proof_evidence),
|
|
496
|
+
],
|
|
497
|
+
'visual_diff': {
|
|
498
|
+
'diffPercentage': 1.2,
|
|
499
|
+
'differentPixels': 12000,
|
|
500
|
+
'totalPixels': 972000,
|
|
501
|
+
},
|
|
502
|
+
}
|
|
447
503
|
if 'clickedProofNavigation' in script:
|
|
448
504
|
page_state = {
|
|
449
505
|
'bodyTextLength': 180,
|
|
@@ -2787,6 +2843,51 @@ def run_verify_interaction_proof_evidence_overrides_stale_expected_path():
|
|
|
2787
2843
|
shutil.rmtree(tempdir, ignore_errors=True)
|
|
2788
2844
|
|
|
2789
2845
|
|
|
2846
|
+
def run_verify_interaction_proof_plan_placeholder_uses_live_evidence():
|
|
2847
|
+
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-interaction-placeholder-route-'))
|
|
2848
|
+
state_path = tempdir / 'state.json'
|
|
2849
|
+
try:
|
|
2850
|
+
state = base_state(tempdir, reference='before')
|
|
2851
|
+
state.update({
|
|
2852
|
+
'recon_status': 'ready_for_proof_plan',
|
|
2853
|
+
'author_status': 'ready',
|
|
2854
|
+
'proof_plan_status': 'ready',
|
|
2855
|
+
'implementation_status': 'changes_detected',
|
|
2856
|
+
'verification_mode': 'interaction',
|
|
2857
|
+
'server_path': '/',
|
|
2858
|
+
'before_cdn': 'https://cdn.example.com/before-home.png',
|
|
2859
|
+
'proof_plan': 'Start at /, click Proof, and verify the terminal pathname /pathname.',
|
|
2860
|
+
'capture_script': "clickedProofNavigationOcLiveShape(); await saveScreenshot('after-proof');",
|
|
2861
|
+
'recon_results': {
|
|
2862
|
+
'baselines': {'before': {'path': '/', 'url': 'https://cdn.example.com/before-home.png'}},
|
|
2863
|
+
},
|
|
2864
|
+
})
|
|
2865
|
+
write_state(state_path, state)
|
|
2866
|
+
os.environ['RIDDLE_PROOF_STATE_FILE'] = str(state_path)
|
|
2867
|
+
|
|
2868
|
+
fake = FakeRiddle()
|
|
2869
|
+
load_util_with_fake(fake)
|
|
2870
|
+
load_module('verify_interaction_placeholder_route_uses_evidence', VERIFY_PATH)
|
|
2871
|
+
after_verify = json.loads(state_path.read_text())
|
|
2872
|
+
|
|
2873
|
+
assert after_verify['verify_status'] == 'evidence_captured'
|
|
2874
|
+
assert after_verify['route_expectation']['source'] == 'proof_evidence_contract'
|
|
2875
|
+
assert after_verify['route_expectation']['expected_path'] == '/proof'
|
|
2876
|
+
route = after_verify['proof_assessment_request']['semantic_context']['route']
|
|
2877
|
+
assert route['expected_after_path'] == '/proof'
|
|
2878
|
+
assert route['after_observed_path'] == '/proof'
|
|
2879
|
+
assert after_verify.get('expected_terminal_path') == '/proof'
|
|
2880
|
+
assert '/pathname' not in json.dumps(after_verify['route_expectation'])
|
|
2881
|
+
assert 'wrong route' not in after_verify['verify_results']['after']['observation']['reason']
|
|
2882
|
+
return {
|
|
2883
|
+
'ok': True,
|
|
2884
|
+
'expected_path': after_verify['route_expectation']['expected_path'],
|
|
2885
|
+
'source': after_verify['route_expectation']['source'],
|
|
2886
|
+
}
|
|
2887
|
+
finally:
|
|
2888
|
+
shutil.rmtree(tempdir, ignore_errors=True)
|
|
2889
|
+
|
|
2890
|
+
|
|
2790
2891
|
def run_verify_interaction_reverse_terminal_route_from_proof_evidence():
|
|
2791
2892
|
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-interaction-reverse-'))
|
|
2792
2893
|
state_path = tempdir / 'state.json'
|
|
@@ -3665,6 +3766,7 @@ if __name__ == '__main__':
|
|
|
3665
3766
|
'remote_audit_verify_uses_default_capture_script': run_remote_audit_verify_uses_default_capture_script(),
|
|
3666
3767
|
'verify_interaction_terminal_route_from_proof_evidence': run_verify_interaction_terminal_route_from_proof_evidence(),
|
|
3667
3768
|
'verify_interaction_proof_evidence_overrides_stale_expected_path': run_verify_interaction_proof_evidence_overrides_stale_expected_path(),
|
|
3769
|
+
'verify_interaction_proof_plan_placeholder_uses_live_evidence': run_verify_interaction_proof_plan_placeholder_uses_live_evidence(),
|
|
3668
3770
|
'verify_interaction_reverse_terminal_route_from_proof_evidence': run_verify_interaction_reverse_terminal_route_from_proof_evidence(),
|
|
3669
3771
|
'verify_interaction_reverse_terminal_expected_url_from_nested_terminal_evidence': run_verify_interaction_reverse_terminal_expected_url_from_nested_terminal_evidence(),
|
|
3670
3772
|
'verify_interaction_prose_route_noise_uses_proof_evidence': run_verify_interaction_prose_route_noise_uses_proof_evidence(),
|
|
@@ -31,6 +31,12 @@ CASES = [
|
|
|
31
31
|
'function': 'run_verify_interaction_proof_evidence_overrides_stale_expected_path',
|
|
32
32
|
'expected_terminal': 'pass',
|
|
33
33
|
},
|
|
34
|
+
{
|
|
35
|
+
'name': 'route-change-proof-plan-placeholder-ignored',
|
|
36
|
+
'covers': ['route-changing interactions', 'proof-evidence-present'],
|
|
37
|
+
'function': 'run_verify_interaction_proof_plan_placeholder_uses_live_evidence',
|
|
38
|
+
'expected_terminal': 'pass',
|
|
39
|
+
},
|
|
34
40
|
{
|
|
35
41
|
'name': 'route-change-reverse-pass',
|
|
36
42
|
'covers': ['route-changing interactions'],
|