@riddledc/riddle-proof 0.8.27 → 0.8.28
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/setup.py +23 -4
- package/runtime/lib/verify.py +41 -1
- package/runtime/tests/recon_verify_smoke.py +110 -0
package/package.json
CHANGED
package/runtime/lib/setup.py
CHANGED
|
@@ -213,6 +213,16 @@ def audit_no_diff_mode():
|
|
|
213
213
|
)
|
|
214
214
|
|
|
215
215
|
|
|
216
|
+
def interaction_verification_mode():
|
|
217
|
+
return str(s.get('verification_mode') or '').strip().lower() in (
|
|
218
|
+
'interaction',
|
|
219
|
+
'interactive',
|
|
220
|
+
'user_flow',
|
|
221
|
+
'user-flow',
|
|
222
|
+
'workflow',
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
|
|
216
226
|
def remote_audit_mode():
|
|
217
227
|
return bool(s.get('remote_audit')) or (
|
|
218
228
|
not repo
|
|
@@ -560,10 +570,19 @@ if remote_audit_mode():
|
|
|
560
570
|
'keyword_hits': [],
|
|
561
571
|
'max_attempts': 0,
|
|
562
572
|
}
|
|
563
|
-
s
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
573
|
+
has_capture_script = bool((s.get('capture_script') or '').strip())
|
|
574
|
+
needs_authored_interaction_capture = interaction_verification_mode() and not has_capture_script
|
|
575
|
+
if needs_authored_interaction_capture:
|
|
576
|
+
s['author_status'] = 'needs_authoring'
|
|
577
|
+
s['proof_plan_status'] = 'needs_authoring'
|
|
578
|
+
s['proof_plan'] = (s.get('proof_plan') or '').strip()
|
|
579
|
+
s['author_summary'] = 'Remote interaction audit requires an authored browser interaction capture before verify.'
|
|
580
|
+
s['capture_script_source'] = ''
|
|
581
|
+
else:
|
|
582
|
+
s['author_status'] = 'ready'
|
|
583
|
+
s['proof_plan_status'] = 'ready'
|
|
584
|
+
s['proof_plan'] = (s.get('proof_plan') or 'Audit the current prod_url target and capture current evidence without requiring a repo diff.').strip()
|
|
585
|
+
if not has_capture_script and not needs_authored_interaction_capture:
|
|
567
586
|
s['capture_script'] = 'await page.waitForTimeout(1500);'
|
|
568
587
|
s['capture_script_source'] = 'default_remote_audit_current_target'
|
|
569
588
|
s['dependency_install'] = {
|
package/runtime/lib/verify.py
CHANGED
|
@@ -3711,7 +3711,47 @@ def build_supervisor_assessment_request(state, payload, after_observation, requi
|
|
|
3711
3711
|
s = load_state()
|
|
3712
3712
|
capture_script = (s.get('capture_script') or '').strip()
|
|
3713
3713
|
no_implementation_mode = audit_no_diff_mode(s)
|
|
3714
|
-
|
|
3714
|
+
initial_verification_mode = normalized_verification_mode(s.get('verification_mode'))
|
|
3715
|
+
if not capture_script and no_implementation_mode and initial_verification_mode in INTERACTION_MODES:
|
|
3716
|
+
s['stage'] = 'verify'
|
|
3717
|
+
s['verify_status'] = 'capture_incomplete'
|
|
3718
|
+
s['merge_recommendation'] = 'do-not-merge'
|
|
3719
|
+
s['structured_interaction_capture_failure_summary'] = (
|
|
3720
|
+
'Interaction verification requires an authored browser interaction capture script; '
|
|
3721
|
+
'the default remote audit current-target capture is passive and cannot prove an interaction.'
|
|
3722
|
+
)
|
|
3723
|
+
s['verify_summary'] = s['structured_interaction_capture_failure_summary']
|
|
3724
|
+
s['proof_summary'] = s['structured_interaction_capture_failure_summary']
|
|
3725
|
+
s['proof_assessment'] = {}
|
|
3726
|
+
s['proof_assessment_source'] = None
|
|
3727
|
+
s['proof_assessment_request'] = {}
|
|
3728
|
+
s['verify_decision_request'] = {
|
|
3729
|
+
'status': s['verify_status'],
|
|
3730
|
+
'summary': s['structured_interaction_capture_failure_summary'],
|
|
3731
|
+
'expected_path': s.get('expected_terminal_path') or s.get('requested_expected_terminal_path') or s.get('server_path') or '/',
|
|
3732
|
+
'expected_start_path': s.get('expected_start_path') or s.get('server_path') or '/',
|
|
3733
|
+
'route_expectation': s.get('route_expectation') or {},
|
|
3734
|
+
'capture_quality': {
|
|
3735
|
+
'decision': 'failed_interaction_capture',
|
|
3736
|
+
'summary': s['structured_interaction_capture_failure_summary'],
|
|
3737
|
+
'recommended_stage': None,
|
|
3738
|
+
'continue_with_stage': None,
|
|
3739
|
+
'blocking': True,
|
|
3740
|
+
'terminal_blocker': True,
|
|
3741
|
+
'reasons': [s['structured_interaction_capture_failure_summary']],
|
|
3742
|
+
},
|
|
3743
|
+
'next_stage_options': ['author', 'verify', 'recon'],
|
|
3744
|
+
'recommended_stage': None,
|
|
3745
|
+
'continue_with_stage': None,
|
|
3746
|
+
'fields_agent_may_update': ['proof_plan', 'capture_script', 'server_path', 'wait_for_selector'],
|
|
3747
|
+
'instructions': [
|
|
3748
|
+
'Author a real Playwright browser interaction capture script before retrying verify.',
|
|
3749
|
+
'Do not use the default remote audit current-target capture for interaction verification.',
|
|
3750
|
+
],
|
|
3751
|
+
}
|
|
3752
|
+
save_state(s)
|
|
3753
|
+
raise SystemExit(s['structured_interaction_capture_failure_summary'])
|
|
3754
|
+
elif not capture_script and no_implementation_mode:
|
|
3715
3755
|
capture_script = 'await page.waitForTimeout(1500);'
|
|
3716
3756
|
s['capture_script'] = capture_script
|
|
3717
3757
|
s['capture_script_source'] = s.get('capture_script_source') or 'default_remote_audit_current_target'
|
|
@@ -1658,6 +1658,61 @@ def run_remote_audit_setup_without_repo():
|
|
|
1658
1658
|
shutil.rmtree(tempdir, ignore_errors=True)
|
|
1659
1659
|
|
|
1660
1660
|
|
|
1661
|
+
def run_remote_interaction_audit_setup_requires_authoring():
|
|
1662
|
+
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-remote-interaction-audit-'))
|
|
1663
|
+
args_path = tempdir / 'args.json'
|
|
1664
|
+
state_path = tempdir / 'state.json'
|
|
1665
|
+
try:
|
|
1666
|
+
args_path.write_text(json.dumps({
|
|
1667
|
+
'repo': '',
|
|
1668
|
+
'mode': 'server',
|
|
1669
|
+
'reference': 'both',
|
|
1670
|
+
'prod_url': 'https://riddledc.com/',
|
|
1671
|
+
'change_request': 'Verify Home -> Proof navigation. Start at https://riddledc.com/. Click the visible Proof nav link. Expected terminal URL is https://riddledc.com/proof/.',
|
|
1672
|
+
'commit_message': '',
|
|
1673
|
+
'success_criteria': 'Terminal URL is https://riddledc.com/proof/ and structured proof evidence is present.',
|
|
1674
|
+
'verification_mode': 'interaction',
|
|
1675
|
+
'implementation_mode': 'none',
|
|
1676
|
+
'require_diff': False,
|
|
1677
|
+
'allow_code_changes': False,
|
|
1678
|
+
'server_image': 'node:20-slim',
|
|
1679
|
+
'server_command': 'npm start',
|
|
1680
|
+
'server_port': '3000',
|
|
1681
|
+
}, indent=2))
|
|
1682
|
+
with temporary_env(
|
|
1683
|
+
RIDDLE_PROOF_ARGS_FILE=str(args_path),
|
|
1684
|
+
RIDDLE_PROOF_STATE_FILE=str(state_path),
|
|
1685
|
+
):
|
|
1686
|
+
sys.modules.pop('util', None)
|
|
1687
|
+
load_module('util_remote_interaction_audit_preflight', UTIL_PATH)
|
|
1688
|
+
load_module('preflight_remote_interaction_audit', PREFLIGHT_PATH)
|
|
1689
|
+
sys.modules.pop('util', None)
|
|
1690
|
+
try:
|
|
1691
|
+
load_module('setup_remote_interaction_audit', SETUP_PATH)
|
|
1692
|
+
except SystemExit as exc:
|
|
1693
|
+
assert exc.code in (0, None), exc
|
|
1694
|
+
state = json.loads(state_path.read_text())
|
|
1695
|
+
assert state['remote_audit'] is True
|
|
1696
|
+
assert state['workspace_ready'] is True
|
|
1697
|
+
assert state['reference'] == 'prod'
|
|
1698
|
+
assert state['implementation_status'] == 'not_required'
|
|
1699
|
+
assert state['server_path'] == '/'
|
|
1700
|
+
assert state['recon_status'] == 'ready_for_proof_plan'
|
|
1701
|
+
assert state['author_status'] == 'needs_authoring'
|
|
1702
|
+
assert state['proof_plan_status'] == 'needs_authoring'
|
|
1703
|
+
assert state.get('capture_script', '') == ''
|
|
1704
|
+
assert state.get('capture_script_source', '') == ''
|
|
1705
|
+
assert 'requires an authored browser interaction capture' in state['author_summary']
|
|
1706
|
+
return {
|
|
1707
|
+
'ok': True,
|
|
1708
|
+
'author_status': state['author_status'],
|
|
1709
|
+
'capture_script_source': state.get('capture_script_source', ''),
|
|
1710
|
+
}
|
|
1711
|
+
finally:
|
|
1712
|
+
sys.modules.pop('util', None)
|
|
1713
|
+
shutil.rmtree(tempdir, ignore_errors=True)
|
|
1714
|
+
|
|
1715
|
+
|
|
1661
1716
|
def run_preflight_resumes_visual_proof_session():
|
|
1662
1717
|
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-preflight-session-'))
|
|
1663
1718
|
args_path = tempdir / 'args.json'
|
|
@@ -2833,6 +2888,59 @@ def run_remote_audit_verify_uses_default_capture_script():
|
|
|
2833
2888
|
shutil.rmtree(tempdir, ignore_errors=True)
|
|
2834
2889
|
|
|
2835
2890
|
|
|
2891
|
+
def run_remote_interaction_audit_verify_rejects_default_capture():
|
|
2892
|
+
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-remote-interaction-audit-verify-'))
|
|
2893
|
+
state_path = tempdir / 'state.json'
|
|
2894
|
+
try:
|
|
2895
|
+
state = base_state(tempdir, reference='prod', prod_url='https://riddledc.com/')
|
|
2896
|
+
state.update({
|
|
2897
|
+
'remote_audit': True,
|
|
2898
|
+
'workspace_kind': 'remote_audit',
|
|
2899
|
+
'mode': 'server',
|
|
2900
|
+
'recon_status': 'ready_for_proof_plan',
|
|
2901
|
+
'author_status': 'ready',
|
|
2902
|
+
'proof_plan_status': 'ready',
|
|
2903
|
+
'implementation_status': 'not_required',
|
|
2904
|
+
'implementation_mode': 'none',
|
|
2905
|
+
'require_diff': False,
|
|
2906
|
+
'allow_code_changes': False,
|
|
2907
|
+
'verification_mode': 'interaction',
|
|
2908
|
+
'server_path': '/',
|
|
2909
|
+
'expected_start_path': '/',
|
|
2910
|
+
'expected_terminal_path': '/proof',
|
|
2911
|
+
'requested_expected_terminal_path': '/proof',
|
|
2912
|
+
'proof_plan': 'Verify Home -> Proof navigation.',
|
|
2913
|
+
'capture_script': '',
|
|
2914
|
+
'recon_results': {'baselines': {}, 'mode': 'remote_audit'},
|
|
2915
|
+
})
|
|
2916
|
+
write_state(state_path, state)
|
|
2917
|
+
os.environ['RIDDLE_PROOF_STATE_FILE'] = str(state_path)
|
|
2918
|
+
|
|
2919
|
+
fake = FakeRiddle()
|
|
2920
|
+
load_util_with_fake(fake)
|
|
2921
|
+
try:
|
|
2922
|
+
load_module('verify_remote_interaction_audit_rejects_default_capture', VERIFY_PATH)
|
|
2923
|
+
except SystemExit as exc:
|
|
2924
|
+
assert 'requires an authored browser interaction capture script' in str(exc), exc
|
|
2925
|
+
else:
|
|
2926
|
+
raise AssertionError('interaction remote audit verify should reject missing capture_script')
|
|
2927
|
+
after_verify = json.loads(state_path.read_text())
|
|
2928
|
+
|
|
2929
|
+
assert after_verify['verify_status'] == 'capture_incomplete'
|
|
2930
|
+
assert after_verify.get('capture_script', '') == ''
|
|
2931
|
+
assert after_verify.get('capture_script_source', '') == ''
|
|
2932
|
+
assert after_verify['verify_decision_request']['capture_quality']['decision'] == 'failed_interaction_capture'
|
|
2933
|
+
assert after_verify['verify_decision_request']['capture_quality']['blocking'] is True
|
|
2934
|
+
assert 'default remote audit current-target capture is passive' in after_verify['structured_interaction_capture_failure_summary']
|
|
2935
|
+
return {
|
|
2936
|
+
'ok': True,
|
|
2937
|
+
'verify_status': after_verify['verify_status'],
|
|
2938
|
+
'capture_quality': after_verify['verify_decision_request']['capture_quality']['decision'],
|
|
2939
|
+
}
|
|
2940
|
+
finally:
|
|
2941
|
+
shutil.rmtree(tempdir, ignore_errors=True)
|
|
2942
|
+
|
|
2943
|
+
|
|
2836
2944
|
def run_verify_interaction_terminal_route_from_proof_evidence():
|
|
2837
2945
|
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-interaction-forward-'))
|
|
2838
2946
|
state_path = tempdir / 'state.json'
|
|
@@ -3941,6 +4049,7 @@ if __name__ == '__main__':
|
|
|
3941
4049
|
payload = {
|
|
3942
4050
|
'preflight_reference_skip_reason': run_preflight_records_prod_reference_skip_reason(),
|
|
3943
4051
|
'remote_audit_setup_without_repo': run_remote_audit_setup_without_repo(),
|
|
4052
|
+
'remote_interaction_audit_setup_requires_authoring': run_remote_interaction_audit_setup_requires_authoring(),
|
|
3944
4053
|
'preflight_resume_visual_proof_session': run_preflight_resumes_visual_proof_session(),
|
|
3945
4054
|
'capture_artifact_enrichment': run_capture_artifact_enrichment(),
|
|
3946
4055
|
'capture_diagnostics_redaction': run_capture_diagnostics_redact_sensitive_values(),
|
|
@@ -3966,6 +4075,7 @@ if __name__ == '__main__':
|
|
|
3966
4075
|
'verify_preserves_proof_evidence_on_capture_script_error': run_verify_preserves_proof_evidence_on_capture_script_error(),
|
|
3967
4076
|
'verify_capture_retry': run_verify_capture_retry(),
|
|
3968
4077
|
'remote_audit_verify_uses_default_capture_script': run_remote_audit_verify_uses_default_capture_script(),
|
|
4078
|
+
'remote_interaction_audit_verify_rejects_default_capture': run_remote_interaction_audit_verify_rejects_default_capture(),
|
|
3969
4079
|
'verify_interaction_terminal_route_from_proof_evidence': run_verify_interaction_terminal_route_from_proof_evidence(),
|
|
3970
4080
|
'verify_interaction_iife_structured_evidence_without_screenshot': run_verify_interaction_iife_structured_evidence_without_screenshot(),
|
|
3971
4081
|
'verify_interaction_proof_evidence_overrides_stale_expected_path': run_verify_interaction_proof_evidence_overrides_stale_expected_path(),
|