@riddledc/riddle-proof 0.8.38 → 0.8.40
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/advanced/index.d.cts +1 -1
- package/dist/advanced/index.d.ts +1 -1
- package/dist/advanced/proof-run-engine.d.cts +1 -1
- package/dist/advanced/proof-run-engine.d.ts +1 -1
- package/dist/{chunk-U44KBAPH.js → chunk-MVJBPCZ4.js} +2 -0
- package/dist/cli/index.js +1 -1
- package/dist/cli.cjs +2 -0
- package/dist/cli.js +1 -1
- package/dist/{proof-run-engine-BqaeqAze.d.ts → proof-run-engine-DYfmd8d7.d.ts} +3 -3
- package/dist/{proof-run-engine-4dM37pEx.d.cts → proof-run-engine-DeHxtGnW.d.cts} +3 -3
- package/dist/proof-run-engine.d.cts +1 -1
- package/dist/proof-run-engine.d.ts +1 -1
- package/package.json +1 -1
- package/runtime/lib/verify.py +103 -11
- package/runtime/tests/recon_verify_smoke.py +136 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { b as runner } from '../runner-4LJ5z0D-.cjs';
|
|
2
2
|
export { l as engineHarness } from '../engine-harness-LBfqbFSe.cjs';
|
|
3
3
|
export { p as proofRunCore } from '../proof-run-core-B1GeqkR8.cjs';
|
|
4
|
-
export { p as proofRunEngine } from '../proof-run-engine-
|
|
4
|
+
export { p as proofRunEngine } from '../proof-run-engine-DeHxtGnW.cjs';
|
|
5
5
|
import '../types.cjs';
|
package/dist/advanced/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { b as runner } from '../runner-BdQpOkZD.js';
|
|
2
2
|
export { l as engineHarness } from '../engine-harness-CMACHP6A.js';
|
|
3
3
|
export { p as proofRunCore } from '../proof-run-core-B1GeqkR8.js';
|
|
4
|
-
export { p as proofRunEngine } from '../proof-run-engine-
|
|
4
|
+
export { p as proofRunEngine } from '../proof-run-engine-DYfmd8d7.js';
|
|
5
5
|
import '../types.js';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from '../proof-run-engine-
|
|
1
|
+
export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from '../proof-run-engine-DeHxtGnW.cjs';
|
|
2
2
|
import '../proof-run-core-B1GeqkR8.cjs';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from '../proof-run-engine-
|
|
1
|
+
export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from '../proof-run-engine-DYfmd8d7.js';
|
|
2
2
|
import '../proof-run-core-B1GeqkR8.js';
|
package/dist/cli/index.js
CHANGED
package/dist/cli.cjs
CHANGED
|
@@ -17667,8 +17667,10 @@ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
|
|
|
17667
17667
|
"submitRetries",
|
|
17668
17668
|
"submitTimeoutMs",
|
|
17669
17669
|
"summary",
|
|
17670
|
+
"successCriteria",
|
|
17670
17671
|
"sync",
|
|
17671
17672
|
"timeout",
|
|
17673
|
+
"title",
|
|
17672
17674
|
"url",
|
|
17673
17675
|
"unsubmittedJobRetries",
|
|
17674
17676
|
"unsubmittedJobTimeoutMs",
|
package/dist/cli.js
CHANGED
|
@@ -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: "recon" | "author" | "ship" | "implement" | "verify" | "setup" | "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: "recon" | "author" | "ship" | "implement" | "verify" | "setup" | "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: "recon" | "author" | "ship" | "implement" | "verify" | "setup";
|
|
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: "recon" | "author" | "ship" | "implement" | "verify" | "setup" | "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: "recon" | "author" | "ship" | "implement" | "verify" | "setup" | "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: "recon" | "author" | "ship" | "implement" | "verify" | "setup";
|
|
663
663
|
state_path: string;
|
|
664
664
|
stage: any;
|
|
665
665
|
summary: string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import './proof-run-core-B1GeqkR8.cjs';
|
|
2
|
-
export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-
|
|
2
|
+
export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-DeHxtGnW.cjs';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import './proof-run-core-B1GeqkR8.js';
|
|
2
|
-
export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-
|
|
2
|
+
export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-DYfmd8d7.js';
|
package/package.json
CHANGED
package/runtime/lib/verify.py
CHANGED
|
@@ -2610,17 +2610,93 @@ def assertion_item_label(item, fallback):
|
|
|
2610
2610
|
return fallback
|
|
2611
2611
|
|
|
2612
2612
|
|
|
2613
|
-
def
|
|
2613
|
+
def assertion_route_value_equivalent(expected, actual):
|
|
2614
|
+
expected_candidate = path_candidate(expected)
|
|
2615
|
+
actual_candidate = path_candidate(actual)
|
|
2616
|
+
if expected_candidate and actual_candidate:
|
|
2617
|
+
return normalize_observed_path(expected_candidate) == normalize_observed_path(actual_candidate)
|
|
2618
|
+
return expected == actual
|
|
2619
|
+
|
|
2620
|
+
|
|
2621
|
+
EXPECTED_ACTUAL_ROUTE_KEY_ALIASES = {
|
|
2622
|
+
'expected_path': ('path', 'pathname', 'terminal_path', 'after_path', 'final_path', 'observed_path', 'actual_path'),
|
|
2623
|
+
'expected_url': ('url', 'href', 'terminal_url', 'terminal_href', 'after_url', 'after_href', 'final_url', 'final_href', 'observed_url', 'actual_url'),
|
|
2624
|
+
'expected_href': ('href', 'url', 'terminal_href', 'terminal_url', 'after_href', 'after_url', 'final_href', 'final_url', 'observed_href', 'actual_href'),
|
|
2625
|
+
'expected_route': ('route', 'path', 'pathname', 'terminal_route', 'terminal_path', 'after_route', 'after_path', 'final_route', 'final_path'),
|
|
2626
|
+
'expected_terminal_path': ('terminal_path', 'path', 'pathname', 'after_path', 'final_path', 'observed_path', 'actual_path'),
|
|
2627
|
+
'expected_terminal_url': ('terminal_url', 'url', 'href', 'after_url', 'final_url', 'observed_url', 'actual_url'),
|
|
2628
|
+
'expected_terminal_href': ('terminal_href', 'href', 'url', 'after_href', 'final_href', 'observed_href', 'actual_href'),
|
|
2629
|
+
'expected_terminal_route': ('terminal_route', 'terminal_path', 'route', 'path', 'pathname', 'after_route', 'after_path', 'final_route', 'final_path'),
|
|
2630
|
+
'expected_after_path': ('after_path', 'path', 'pathname', 'terminal_path', 'final_path', 'observed_path', 'actual_path'),
|
|
2631
|
+
'expected_after_url': ('after_url', 'url', 'href', 'terminal_url', 'final_url', 'observed_url', 'actual_url'),
|
|
2632
|
+
'expected_after_href': ('after_href', 'href', 'url', 'terminal_href', 'final_href', 'observed_href', 'actual_href'),
|
|
2633
|
+
'expected_after_route': ('after_route', 'after_path', 'route', 'path', 'pathname', 'terminal_route', 'terminal_path', 'final_route', 'final_path'),
|
|
2634
|
+
'expected_final_path': ('final_path', 'path', 'pathname', 'terminal_path', 'after_path', 'observed_path', 'actual_path'),
|
|
2635
|
+
'expected_final_url': ('final_url', 'url', 'href', 'terminal_url', 'after_url', 'observed_url', 'actual_url'),
|
|
2636
|
+
'expected_final_href': ('final_href', 'href', 'url', 'terminal_href', 'after_href', 'observed_href', 'actual_href'),
|
|
2637
|
+
'expected_final_route': ('final_route', 'final_path', 'route', 'path', 'pathname', 'terminal_route', 'terminal_path', 'after_route', 'after_path'),
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
|
|
2641
|
+
def assertion_expected_actual_equivalent(expected, actual):
|
|
2642
|
+
if isinstance(expected, str) and isinstance(actual, str):
|
|
2643
|
+
return assertion_route_value_equivalent(expected, actual)
|
|
2644
|
+
if isinstance(expected, dict) and isinstance(actual, dict):
|
|
2645
|
+
for expected_key, expected_value in expected.items():
|
|
2646
|
+
actual_keys = (expected_key,) + EXPECTED_ACTUAL_ROUTE_KEY_ALIASES.get(expected_key, ())
|
|
2647
|
+
matched = False
|
|
2648
|
+
for actual_key in actual_keys:
|
|
2649
|
+
if actual_key not in actual:
|
|
2650
|
+
continue
|
|
2651
|
+
if assertion_expected_actual_equivalent(expected_value, actual.get(actual_key)):
|
|
2652
|
+
matched = True
|
|
2653
|
+
break
|
|
2654
|
+
if not matched:
|
|
2655
|
+
return False
|
|
2656
|
+
return True
|
|
2657
|
+
return expected == actual
|
|
2658
|
+
|
|
2659
|
+
|
|
2660
|
+
def assertion_failure_is_route_equivalent(item):
|
|
2661
|
+
if not isinstance(item, dict):
|
|
2662
|
+
return False
|
|
2663
|
+
has_failure_flag = any(item.get(key) is False for key in INTERACTION_FAILURE_FLAG_KEYS)
|
|
2664
|
+
status = str(item.get('status') or item.get('result') or '').strip().lower()
|
|
2665
|
+
if status in INTERACTION_FAILURE_STATUS_VALUES:
|
|
2666
|
+
has_failure_flag = True
|
|
2667
|
+
if not has_failure_flag or 'expected' not in item or 'actual' not in item:
|
|
2668
|
+
return False
|
|
2669
|
+
return assertion_expected_actual_equivalent(item.get('expected'), item.get('actual'))
|
|
2670
|
+
|
|
2671
|
+
|
|
2672
|
+
def collect_interaction_failed_assertions_internal(value, prefix='', depth=0):
|
|
2614
2673
|
if depth > 6:
|
|
2615
|
-
return []
|
|
2674
|
+
return [], False
|
|
2616
2675
|
failures = []
|
|
2676
|
+
ignored_route_equivalent_failure = False
|
|
2617
2677
|
if isinstance(value, dict):
|
|
2678
|
+
pending_aggregate_failures = []
|
|
2679
|
+
has_assertion_container = any(
|
|
2680
|
+
isinstance(value.get(key), (dict, list))
|
|
2681
|
+
for key in INTERACTION_ASSERTION_CONTAINER_KEYS
|
|
2682
|
+
)
|
|
2683
|
+
route_equivalent_failure = assertion_failure_is_route_equivalent(value)
|
|
2618
2684
|
for key in INTERACTION_FAILURE_FLAG_KEYS:
|
|
2619
2685
|
if value.get(key) is False:
|
|
2620
|
-
|
|
2686
|
+
if route_equivalent_failure or has_assertion_container:
|
|
2687
|
+
ignored_route_equivalent_failure = ignored_route_equivalent_failure or route_equivalent_failure
|
|
2688
|
+
if has_assertion_container and not route_equivalent_failure:
|
|
2689
|
+
pending_aggregate_failures.append(failure_label(prefix, key))
|
|
2690
|
+
else:
|
|
2691
|
+
failures.append(failure_label(prefix, key))
|
|
2621
2692
|
status = str(value.get('status') or value.get('result') or '').strip().lower()
|
|
2622
2693
|
if status in INTERACTION_FAILURE_STATUS_VALUES:
|
|
2623
|
-
|
|
2694
|
+
if route_equivalent_failure or has_assertion_container:
|
|
2695
|
+
ignored_route_equivalent_failure = ignored_route_equivalent_failure or route_equivalent_failure
|
|
2696
|
+
if has_assertion_container and not route_equivalent_failure:
|
|
2697
|
+
pending_aggregate_failures.append(failure_label(prefix, assertion_item_label(value, 'status')))
|
|
2698
|
+
else:
|
|
2699
|
+
failures.append(failure_label(prefix, assertion_item_label(value, 'status')))
|
|
2624
2700
|
for key in INTERACTION_ASSERTION_CONTAINER_KEYS:
|
|
2625
2701
|
checks = value.get(key)
|
|
2626
2702
|
container_prefix = failure_label(prefix, key)
|
|
@@ -2629,39 +2705,55 @@ def collect_interaction_failed_assertions(value, prefix='', depth=0):
|
|
|
2629
2705
|
if check_value is False:
|
|
2630
2706
|
failures.append(failure_label(container_prefix, check_key))
|
|
2631
2707
|
elif isinstance(check_value, dict):
|
|
2632
|
-
nested =
|
|
2708
|
+
nested, nested_ignored = collect_interaction_failed_assertions_internal(
|
|
2633
2709
|
check_value,
|
|
2634
2710
|
failure_label(container_prefix, check_key),
|
|
2635
2711
|
depth + 1,
|
|
2636
2712
|
)
|
|
2637
2713
|
failures.extend(nested)
|
|
2714
|
+
ignored_route_equivalent_failure = ignored_route_equivalent_failure or nested_ignored
|
|
2638
2715
|
elif isinstance(check_value, list):
|
|
2639
|
-
|
|
2716
|
+
nested, nested_ignored = collect_interaction_failed_assertions_internal(
|
|
2640
2717
|
check_value,
|
|
2641
2718
|
failure_label(container_prefix, check_key),
|
|
2642
2719
|
depth + 1,
|
|
2643
|
-
)
|
|
2720
|
+
)
|
|
2721
|
+
failures.extend(nested)
|
|
2722
|
+
ignored_route_equivalent_failure = ignored_route_equivalent_failure or nested_ignored
|
|
2644
2723
|
elif isinstance(checks, list):
|
|
2645
2724
|
for index, item in enumerate(checks):
|
|
2646
2725
|
if item is False:
|
|
2647
2726
|
failures.append(failure_label(container_prefix, str(index)))
|
|
2648
2727
|
elif isinstance(item, dict):
|
|
2649
2728
|
item_label = assertion_item_label(item, str(index))
|
|
2650
|
-
|
|
2729
|
+
nested, nested_ignored = collect_interaction_failed_assertions_internal(
|
|
2651
2730
|
item,
|
|
2652
2731
|
failure_label(container_prefix, item_label),
|
|
2653
2732
|
depth + 1,
|
|
2654
|
-
)
|
|
2733
|
+
)
|
|
2734
|
+
failures.extend(nested)
|
|
2735
|
+
ignored_route_equivalent_failure = ignored_route_equivalent_failure or nested_ignored
|
|
2655
2736
|
for key in EVIDENCE_CONTAINER_KEYS:
|
|
2656
2737
|
nested = value.get(key)
|
|
2657
2738
|
if isinstance(nested, (dict, list)):
|
|
2658
|
-
|
|
2739
|
+
nested_failures, nested_ignored = collect_interaction_failed_assertions_internal(nested, failure_label(prefix, key), depth + 1)
|
|
2740
|
+
failures.extend(nested_failures)
|
|
2741
|
+
ignored_route_equivalent_failure = ignored_route_equivalent_failure or nested_ignored
|
|
2742
|
+
if pending_aggregate_failures and not failures and not ignored_route_equivalent_failure:
|
|
2743
|
+
failures.extend(pending_aggregate_failures)
|
|
2659
2744
|
elif isinstance(value, list):
|
|
2660
2745
|
for index, item in enumerate(value):
|
|
2661
2746
|
if item is False:
|
|
2662
2747
|
failures.append(failure_label(prefix, str(index)))
|
|
2663
2748
|
elif isinstance(item, (dict, list)):
|
|
2664
|
-
|
|
2749
|
+
nested_failures, nested_ignored = collect_interaction_failed_assertions_internal(item, prefix, depth + 1)
|
|
2750
|
+
failures.extend(nested_failures)
|
|
2751
|
+
ignored_route_equivalent_failure = ignored_route_equivalent_failure or nested_ignored
|
|
2752
|
+
return failures, ignored_route_equivalent_failure
|
|
2753
|
+
|
|
2754
|
+
|
|
2755
|
+
def collect_interaction_failed_assertions(value, prefix='', depth=0):
|
|
2756
|
+
failures, _ignored_route_equivalent_failure = collect_interaction_failed_assertions_internal(value, prefix, depth)
|
|
2665
2757
|
deduped = []
|
|
2666
2758
|
seen = set()
|
|
2667
2759
|
for failure in failures:
|
|
@@ -106,6 +106,7 @@ class FakeRiddle:
|
|
|
106
106
|
'pricingQueryHashDropsTerminal',
|
|
107
107
|
'pricingQueryHashStructuredNegativeControl',
|
|
108
108
|
'pricingQueryHashPassesWithPageStateHashGap',
|
|
109
|
+
'clickedProofNavigationTrailingSlashFalseAssertions',
|
|
109
110
|
'clickedProofNavigation',
|
|
110
111
|
'clickedHomeNavigation',
|
|
111
112
|
'skipLinkTimeout',
|
|
@@ -621,6 +622,74 @@ class FakeRiddle:
|
|
|
621
622
|
'RIDDLE_PROOF_EVIDENCE:' + json.dumps(proof_evidence),
|
|
622
623
|
],
|
|
623
624
|
}
|
|
625
|
+
if 'clickedProofNavigationTrailingSlashFalseAssertions' in script:
|
|
626
|
+
page_state = {
|
|
627
|
+
'bodyTextLength': 4113,
|
|
628
|
+
'visibleTextSample': 'RIDDLE PROOF Turn a URL into evidence an agent can cite.',
|
|
629
|
+
'interactiveElements': 43,
|
|
630
|
+
'visibleInteractiveElements': 42,
|
|
631
|
+
'pathname': '/proof/',
|
|
632
|
+
'href': 'https://riddledc.com/proof/',
|
|
633
|
+
'title': 'Riddle Proof',
|
|
634
|
+
'buttons': [],
|
|
635
|
+
'headings': ['Riddle Proof'],
|
|
636
|
+
'links': [{'text': 'Proof', 'href': '/proof/'}],
|
|
637
|
+
'canvasCount': 0,
|
|
638
|
+
'largeVisibleElements': [{'tag': 'main', 'text': 'Riddle Proof'}],
|
|
639
|
+
}
|
|
640
|
+
proof_evidence = {
|
|
641
|
+
'version': 'riddle-proof.interaction.v1',
|
|
642
|
+
'reference': 'prod',
|
|
643
|
+
'start': {'url': 'https://riddledc.com/', 'path': '/'},
|
|
644
|
+
'action': 'click visible Proof nav link',
|
|
645
|
+
'matchedUiText': 'Proof',
|
|
646
|
+
'matchedHref': 'https://riddledc.com/proof/',
|
|
647
|
+
'terminal': {'url': 'https://riddledc.com/proof/', 'path': '/proof/'},
|
|
648
|
+
'assertions': [
|
|
649
|
+
{'name': 'start_path_is_root', 'expected': '/', 'actual': '/', 'passed': True},
|
|
650
|
+
{'name': 'proof_nav_link_visible', 'expected': 'visible Proof link', 'actual': 'Proof', 'passed': True},
|
|
651
|
+
{
|
|
652
|
+
'name': 'terminal_url_exact',
|
|
653
|
+
'expected': 'https://riddledc.com/proof/',
|
|
654
|
+
'actual': 'https://riddledc.com/proof/',
|
|
655
|
+
'passed': True,
|
|
656
|
+
},
|
|
657
|
+
{'name': 'terminal_path_exact', 'expected': '/proof', 'actual': '/proof/', 'passed': False},
|
|
658
|
+
{
|
|
659
|
+
'name': 'interaction_contract_preserved',
|
|
660
|
+
'expected': {
|
|
661
|
+
'start_path': '/',
|
|
662
|
+
'expected_terminal_path': '/proof',
|
|
663
|
+
'expected_url': 'https://riddledc.com/proof/',
|
|
664
|
+
'action': 'click visible Proof nav link',
|
|
665
|
+
},
|
|
666
|
+
'actual': {
|
|
667
|
+
'start_path': '/',
|
|
668
|
+
'terminal_path': '/proof/',
|
|
669
|
+
'terminal_url': 'https://riddledc.com/proof/',
|
|
670
|
+
'action': 'click visible Proof nav link',
|
|
671
|
+
},
|
|
672
|
+
'passed': False,
|
|
673
|
+
},
|
|
674
|
+
],
|
|
675
|
+
'errors': [],
|
|
676
|
+
'passed': False,
|
|
677
|
+
}
|
|
678
|
+
return {
|
|
679
|
+
'ok': True,
|
|
680
|
+
'screenshots': [{'url': 'https://cdn.example.com/proof-after.png'}],
|
|
681
|
+
'outputs': [{'name': 'after-proof.png', 'url': 'https://cdn.example.com/proof-after.png'}],
|
|
682
|
+
'result': {'pageState': page_state, 'proofEvidence': proof_evidence},
|
|
683
|
+
'console': [
|
|
684
|
+
'RIDDLE_PROOF_STATE:' + json.dumps(page_state),
|
|
685
|
+
'RIDDLE_PROOF_EVIDENCE:' + json.dumps(proof_evidence),
|
|
686
|
+
],
|
|
687
|
+
'visual_diff': {
|
|
688
|
+
'diffPercentage': 1.2,
|
|
689
|
+
'differentPixels': 12000,
|
|
690
|
+
'totalPixels': 972000,
|
|
691
|
+
},
|
|
692
|
+
}
|
|
624
693
|
if 'clickedProofNavigationOcLiveShape' in script:
|
|
625
694
|
page_state = {
|
|
626
695
|
'bodyTextLength': 4113,
|
|
@@ -3198,6 +3267,72 @@ def run_verify_interaction_iife_structured_evidence_without_screenshot():
|
|
|
3198
3267
|
shutil.rmtree(tempdir, ignore_errors=True)
|
|
3199
3268
|
|
|
3200
3269
|
|
|
3270
|
+
def run_verify_interaction_trailing_slash_false_assertions_are_normalized():
|
|
3271
|
+
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-interaction-trailing-slash-assertions-'))
|
|
3272
|
+
state_path = tempdir / 'state.json'
|
|
3273
|
+
try:
|
|
3274
|
+
state = base_state(tempdir, reference='prod', prod_url='https://riddledc.com/')
|
|
3275
|
+
state.update({
|
|
3276
|
+
'remote_audit': True,
|
|
3277
|
+
'workspace_kind': 'remote_audit',
|
|
3278
|
+
'mode': 'server',
|
|
3279
|
+
'recon_status': 'ready_for_proof_plan',
|
|
3280
|
+
'author_status': 'ready',
|
|
3281
|
+
'proof_plan_status': 'ready',
|
|
3282
|
+
'implementation_status': 'not_required',
|
|
3283
|
+
'implementation_mode': 'none',
|
|
3284
|
+
'require_diff': False,
|
|
3285
|
+
'allow_code_changes': False,
|
|
3286
|
+
'verification_mode': 'interaction',
|
|
3287
|
+
'server_path': '/',
|
|
3288
|
+
'expected_start_path': '/',
|
|
3289
|
+
'expected_terminal_path': '/proof',
|
|
3290
|
+
'requested_expected_terminal_path': '/proof',
|
|
3291
|
+
'proof_plan': 'Start at /, click Proof, and verify the terminal URL https://riddledc.com/proof/.',
|
|
3292
|
+
'capture_script': "clickedProofNavigationTrailingSlashFalseAssertions(); await saveScreenshot('after-proof');",
|
|
3293
|
+
'supervisor_author_packet': {
|
|
3294
|
+
'proof_plan': 'Click Proof and prove the terminal route.',
|
|
3295
|
+
'capture_script': "clickedProofNavigationTrailingSlashFalseAssertions(); await saveScreenshot('after-proof');",
|
|
3296
|
+
'refined_inputs': {
|
|
3297
|
+
'server_path': '/',
|
|
3298
|
+
'expected_terminal_path': '/proof',
|
|
3299
|
+
},
|
|
3300
|
+
},
|
|
3301
|
+
'recon_results': {'baselines': {}, 'mode': 'remote_audit'},
|
|
3302
|
+
})
|
|
3303
|
+
write_state(state_path, state)
|
|
3304
|
+
os.environ['RIDDLE_PROOF_STATE_FILE'] = str(state_path)
|
|
3305
|
+
|
|
3306
|
+
fake = FakeRiddle()
|
|
3307
|
+
load_util_with_fake(fake)
|
|
3308
|
+
load_module('verify_interaction_trailing_slash_false_assertions', VERIFY_PATH)
|
|
3309
|
+
after_verify = json.loads(state_path.read_text())
|
|
3310
|
+
|
|
3311
|
+
assert after_verify['verify_status'] == 'evidence_captured'
|
|
3312
|
+
assert after_verify['merge_recommendation'] == 'pending-supervisor-judgment'
|
|
3313
|
+
assert after_verify['structured_interaction_failure_summary'] == ''
|
|
3314
|
+
assert 'failed assertion' not in after_verify['proof_summary']
|
|
3315
|
+
observation = after_verify['verify_results']['after']['observation']
|
|
3316
|
+
assert observation['valid'] is True
|
|
3317
|
+
assert observation['details']['proof_evidence_route_matched'] is True
|
|
3318
|
+
assert observation['details']['observed_path_source'] == 'proof_evidence'
|
|
3319
|
+
assert 'wrong route' not in observation['reason']
|
|
3320
|
+
request = after_verify['verify_decision_request']
|
|
3321
|
+
assert request['structured_interaction_failure_summary'] == ''
|
|
3322
|
+
assert request['recommended_stage'] is None
|
|
3323
|
+
route = after_verify['proof_assessment_request']['semantic_context']['route']
|
|
3324
|
+
assert route['expected_after_path'] == '/proof'
|
|
3325
|
+
assert route['after_observed_path'] == '/proof'
|
|
3326
|
+
assert route['after_observed_path_raw'] == '/proof'
|
|
3327
|
+
return {
|
|
3328
|
+
'ok': True,
|
|
3329
|
+
'expected_path': after_verify['route_expectation']['expected_path'],
|
|
3330
|
+
'after_observed_path': route['after_observed_path'],
|
|
3331
|
+
}
|
|
3332
|
+
finally:
|
|
3333
|
+
shutil.rmtree(tempdir, ignore_errors=True)
|
|
3334
|
+
|
|
3335
|
+
|
|
3201
3336
|
def run_verify_interaction_proof_evidence_overrides_stale_expected_path():
|
|
3202
3337
|
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-interaction-stale-route-'))
|
|
3203
3338
|
state_path = tempdir / 'state.json'
|
|
@@ -4238,6 +4373,7 @@ if __name__ == '__main__':
|
|
|
4238
4373
|
'remote_interaction_audit_verify_rejects_default_capture': run_remote_interaction_audit_verify_rejects_default_capture(),
|
|
4239
4374
|
'verify_interaction_terminal_route_from_proof_evidence': run_verify_interaction_terminal_route_from_proof_evidence(),
|
|
4240
4375
|
'verify_interaction_iife_structured_evidence_without_screenshot': run_verify_interaction_iife_structured_evidence_without_screenshot(),
|
|
4376
|
+
'verify_interaction_trailing_slash_false_assertions_are_normalized': run_verify_interaction_trailing_slash_false_assertions_are_normalized(),
|
|
4241
4377
|
'verify_interaction_proof_evidence_overrides_stale_expected_path': run_verify_interaction_proof_evidence_overrides_stale_expected_path(),
|
|
4242
4378
|
'verify_interaction_proof_plan_placeholder_uses_live_evidence': run_verify_interaction_proof_plan_placeholder_uses_live_evidence(),
|
|
4243
4379
|
'verify_interaction_reverse_terminal_route_from_proof_evidence': run_verify_interaction_reverse_terminal_route_from_proof_evidence(),
|