@riddledc/riddle-proof 0.5.16 → 0.5.17
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/package.json +1 -1
- package/runtime/lib/verify.py +142 -0
- package/runtime/tests/recon_verify_smoke.py +14 -0
package/package.json
CHANGED
package/runtime/lib/verify.py
CHANGED
|
@@ -625,6 +625,111 @@ def collect_supporting_artifacts(payload):
|
|
|
625
625
|
}
|
|
626
626
|
|
|
627
627
|
|
|
628
|
+
def artifact_contract_for_mode(verification_mode):
|
|
629
|
+
mode = normalized_verification_mode(verification_mode)
|
|
630
|
+
return {
|
|
631
|
+
'verification_mode': mode,
|
|
632
|
+
'required': {
|
|
633
|
+
'baseline_context': True,
|
|
634
|
+
'route_semantics': True,
|
|
635
|
+
'screenshot': screenshot_required_for_mode(mode),
|
|
636
|
+
'proof_evidence': proof_evidence_required_for_mode(mode),
|
|
637
|
+
},
|
|
638
|
+
'preferred': {
|
|
639
|
+
'page_state': True,
|
|
640
|
+
'structured_payload': mode in STRUCTURED_FIRST_MODES or proof_evidence_required_for_mode(mode),
|
|
641
|
+
'visual_delta': visual_delta_applies(mode),
|
|
642
|
+
},
|
|
643
|
+
'optional': {
|
|
644
|
+
'console_summary': True,
|
|
645
|
+
'json_artifacts': True,
|
|
646
|
+
'image_outputs': True,
|
|
647
|
+
},
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
def artifact_production_summary(payload, supporting):
|
|
652
|
+
artifact_summary = summarize_capture_artifacts(payload)
|
|
653
|
+
return {
|
|
654
|
+
'output_names': [str(item.get('name') or '') for item in (artifact_summary.get('outputs') or [])[:20]],
|
|
655
|
+
'screenshot_names': [str(item.get('name') or '') for item in (artifact_summary.get('screenshots') or [])[:10]],
|
|
656
|
+
'artifact_json': list(artifact_summary.get('artifact_json') or []),
|
|
657
|
+
'artifact_error_names': sorted((artifact_summary.get('artifact_errors') or {}).keys()),
|
|
658
|
+
'image_output_count': len(supporting.get('image_outputs') or []),
|
|
659
|
+
'data_output_count': len(supporting.get('data_outputs') or []),
|
|
660
|
+
'other_output_count': len(supporting.get('other_outputs') or []),
|
|
661
|
+
'console_entries': int(supporting.get('console_entries') or 0),
|
|
662
|
+
'structured_result_keys': list(supporting.get('structured_result_keys') or []),
|
|
663
|
+
'proof_evidence_present': bool(supporting.get('proof_evidence_present')),
|
|
664
|
+
'has_structured_payload': bool(supporting.get('has_structured_payload')),
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
def artifact_signal_availability(state, after_observation, supporting, visual_delta, required_baseline_present, semantic_context):
|
|
669
|
+
details = (after_observation or {}).get('details') or {}
|
|
670
|
+
route = (semantic_context or {}).get('route') or {}
|
|
671
|
+
return {
|
|
672
|
+
'baseline_context': bool(required_baseline_present),
|
|
673
|
+
'route_semantics': bool(route.get('after_observed_path') or details.get('observed_path')),
|
|
674
|
+
'screenshot': bool(details.get('has_screenshot')),
|
|
675
|
+
'page_state': bool(
|
|
676
|
+
details.get('visible_text_sample')
|
|
677
|
+
or details.get('headings')
|
|
678
|
+
or details.get('buttons')
|
|
679
|
+
or details.get('links')
|
|
680
|
+
or details.get('semantic_anchor_count')
|
|
681
|
+
),
|
|
682
|
+
'structured_payload': bool(supporting.get('has_structured_payload')),
|
|
683
|
+
'proof_evidence': bool(supporting.get('proof_evidence_present')),
|
|
684
|
+
'visual_delta': bool((visual_delta or {}).get('status') not in ('', None, 'not_applicable')),
|
|
685
|
+
'console_summary': bool(supporting.get('console_entries')),
|
|
686
|
+
'json_artifacts': bool(supporting.get('data_outputs')),
|
|
687
|
+
'image_outputs': bool(supporting.get('image_outputs')),
|
|
688
|
+
'assertions': bool(state.get('parsed_assertions')),
|
|
689
|
+
'success_criteria': bool((state.get('success_criteria') or '').strip()),
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def artifact_usage_summary(state, after_observation, supporting, visual_delta, required_baseline_present, semantic_context, evidence_basis):
|
|
694
|
+
contract = artifact_contract_for_mode(state.get('verification_mode'))
|
|
695
|
+
available = artifact_signal_availability(
|
|
696
|
+
state,
|
|
697
|
+
after_observation,
|
|
698
|
+
supporting,
|
|
699
|
+
visual_delta,
|
|
700
|
+
required_baseline_present,
|
|
701
|
+
semantic_context,
|
|
702
|
+
)
|
|
703
|
+
capture_quality = []
|
|
704
|
+
details = (after_observation or {}).get('details') or {}
|
|
705
|
+
if details.get('has_screenshot'):
|
|
706
|
+
capture_quality.append('screenshot')
|
|
707
|
+
if available.get('page_state'):
|
|
708
|
+
capture_quality.append('page_state')
|
|
709
|
+
if available.get('console_summary'):
|
|
710
|
+
capture_quality.append('console_summary')
|
|
711
|
+
if available.get('structured_payload'):
|
|
712
|
+
capture_quality.append('structured_payload')
|
|
713
|
+
if available.get('proof_evidence'):
|
|
714
|
+
capture_quality.append('proof_evidence')
|
|
715
|
+
if available.get('visual_delta'):
|
|
716
|
+
capture_quality.append('visual_delta')
|
|
717
|
+
|
|
718
|
+
required_signals = [key for key, enabled in (contract.get('required') or {}).items() if enabled]
|
|
719
|
+
preferred_signals = [key for key, enabled in (contract.get('preferred') or {}).items() if enabled]
|
|
720
|
+
optional_signals = [key for key, enabled in (contract.get('optional') or {}).items() if enabled]
|
|
721
|
+
|
|
722
|
+
return {
|
|
723
|
+
'required_signals': required_signals,
|
|
724
|
+
'preferred_signals': preferred_signals,
|
|
725
|
+
'optional_signals': optional_signals,
|
|
726
|
+
'available_signals': [key for key, enabled in available.items() if enabled],
|
|
727
|
+
'missing_required_signals': [key for key in required_signals if not available.get(key)],
|
|
728
|
+
'capture_quality_signals': capture_quality,
|
|
729
|
+
'supervisor_review_signals': list(evidence_basis or []),
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
|
|
628
733
|
def evaluate_capture_quality(payload, expected_path, verification_mode='proof'):
|
|
629
734
|
payload = enrich_capture_payload(payload)
|
|
630
735
|
mode = normalized_verification_mode(verification_mode)
|
|
@@ -863,6 +968,17 @@ def build_evidence_bundle(state, results, after_payload, after_observation, requ
|
|
|
863
968
|
else {'status': 'not_applicable', 'passed': None, 'reason': 'Verification mode does not require visual delta gating.'}
|
|
864
969
|
)
|
|
865
970
|
semantic_context = build_semantic_context(state, results, after_observation, expected_path)
|
|
971
|
+
artifact_contract = artifact_contract_for_mode(state.get('verification_mode'))
|
|
972
|
+
artifact_production = artifact_production_summary(after_payload, supporting)
|
|
973
|
+
artifact_usage = artifact_usage_summary(
|
|
974
|
+
state,
|
|
975
|
+
after_observation,
|
|
976
|
+
supporting,
|
|
977
|
+
visual_delta,
|
|
978
|
+
required_baseline_present,
|
|
979
|
+
semantic_context,
|
|
980
|
+
[],
|
|
981
|
+
)
|
|
866
982
|
return {
|
|
867
983
|
'verification_mode': normalized_verification_mode(state.get('verification_mode')),
|
|
868
984
|
'reference': state.get('requested_reference') or state.get('reference', 'both'),
|
|
@@ -870,6 +986,9 @@ def build_evidence_bundle(state, results, after_payload, after_observation, requ
|
|
|
870
986
|
'required_baseline_present': required_baseline_present,
|
|
871
987
|
'baseline': results.get('baseline') or {},
|
|
872
988
|
'semantic_context': semantic_context,
|
|
989
|
+
'artifact_contract': artifact_contract,
|
|
990
|
+
'artifact_production': artifact_production,
|
|
991
|
+
'artifact_usage': artifact_usage,
|
|
873
992
|
'after': {
|
|
874
993
|
'screenshot_url': state.get('after_cdn') or '',
|
|
875
994
|
'observation': after_observation,
|
|
@@ -910,6 +1029,26 @@ def build_supervisor_assessment_request(state, payload, after_observation, requi
|
|
|
910
1029
|
if has_success_criteria:
|
|
911
1030
|
evidence_basis.append('success-criteria')
|
|
912
1031
|
|
|
1032
|
+
artifact_contract = (evidence_bundle or {}).get('artifact_contract') if isinstance(evidence_bundle, dict) else None
|
|
1033
|
+
if not isinstance(artifact_contract, dict):
|
|
1034
|
+
artifact_contract = artifact_contract_for_mode(verification_mode)
|
|
1035
|
+
artifact_production = (evidence_bundle or {}).get('artifact_production') if isinstance(evidence_bundle, dict) else None
|
|
1036
|
+
if not isinstance(artifact_production, dict):
|
|
1037
|
+
artifact_production = artifact_production_summary(payload, supporting)
|
|
1038
|
+
artifact_usage = artifact_usage_summary(
|
|
1039
|
+
state,
|
|
1040
|
+
after_observation,
|
|
1041
|
+
supporting,
|
|
1042
|
+
visual_delta,
|
|
1043
|
+
required_baseline_present,
|
|
1044
|
+
semantic_context,
|
|
1045
|
+
evidence_basis,
|
|
1046
|
+
)
|
|
1047
|
+
if isinstance(evidence_bundle, dict):
|
|
1048
|
+
evidence_bundle['artifact_contract'] = artifact_contract
|
|
1049
|
+
evidence_bundle['artifact_production'] = artifact_production
|
|
1050
|
+
evidence_bundle['artifact_usage'] = artifact_usage
|
|
1051
|
+
|
|
913
1052
|
return {
|
|
914
1053
|
'status': 'needs_supervising_agent_assessment',
|
|
915
1054
|
'verification_mode': verification_mode,
|
|
@@ -921,6 +1060,9 @@ def build_supervisor_assessment_request(state, payload, after_observation, requi
|
|
|
921
1060
|
'semantic_context': semantic_context,
|
|
922
1061
|
'evidence_bundle': evidence_bundle or {},
|
|
923
1062
|
'evidence_basis': evidence_basis,
|
|
1063
|
+
'artifact_contract': artifact_contract,
|
|
1064
|
+
'artifact_production': artifact_production,
|
|
1065
|
+
'artifact_usage': artifact_usage,
|
|
924
1066
|
'instructions': [
|
|
925
1067
|
'The supervising agent owns proof assessment. Inspect the recon baseline(s), after evidence, and any structured artifacts together.',
|
|
926
1068
|
'Decide whether the evidence is ready_to_ship or should continue internally through author, implement, or recon.',
|
|
@@ -790,6 +790,20 @@ def run_verify_requests_supervisor_assessment():
|
|
|
790
790
|
assert semantic_context['after']['headings'] == ['Pricing'], semantic_context
|
|
791
791
|
assert 'semantic-context' in after_verify['proof_assessment_request']['evidence_basis']
|
|
792
792
|
assert after_verify['proof_assessment_request']['evidence_bundle']['semantic_context']['after']['buttons'] == ['Buy Now']
|
|
793
|
+
artifact_contract = after_verify['proof_assessment_request']['artifact_contract']
|
|
794
|
+
assert artifact_contract['required']['baseline_context'] is True
|
|
795
|
+
assert artifact_contract['required']['screenshot'] is True
|
|
796
|
+
artifact_production = after_verify['proof_assessment_request']['artifact_production']
|
|
797
|
+
assert artifact_production['image_output_count'] >= 1
|
|
798
|
+
assert artifact_production['proof_evidence_present'] is False
|
|
799
|
+
artifact_usage = after_verify['proof_assessment_request']['artifact_usage']
|
|
800
|
+
assert artifact_usage['missing_required_signals'] == []
|
|
801
|
+
assert 'after-capture' in artifact_usage['supervisor_review_signals']
|
|
802
|
+
assert 'baseline_context' in artifact_usage['required_signals']
|
|
803
|
+
assert 'route_semantics' in artifact_usage['available_signals']
|
|
804
|
+
assert after_verify['proof_assessment_request']['evidence_bundle']['artifact_contract']['required']['screenshot'] is True
|
|
805
|
+
assert after_verify['proof_assessment_request']['evidence_bundle']['artifact_production']['image_output_count'] >= 1
|
|
806
|
+
assert after_verify['proof_assessment_request']['evidence_bundle']['artifact_usage']['missing_required_signals'] == []
|
|
793
807
|
assert 'capture success is not proof' in '\n'.join(after_verify['proof_assessment_request']['instructions'])
|
|
794
808
|
assert after_verify['verify_decision_request']['continue_with_stage'] is None
|
|
795
809
|
assert after_verify['verify_results']['baseline']['before']['source'] == 'recon'
|