@riddledc/riddle-proof 0.5.25 → 0.5.27

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.5.25",
3
+ "version": "0.5.27",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",
@@ -112,8 +112,12 @@ def select_capture_hint(state):
112
112
  if str(item).strip()
113
113
  ]
114
114
  matched_tokens = [token for token in current_tokens if token in hint_tokens]
115
+ mode_matches = bool(current_mode and hint_mode == current_mode)
116
+ root_hint = server_path == '/'
117
+ if not matched_tokens and mode_matches and not root_hint:
118
+ continue
115
119
  score = len(matched_tokens) * 3
116
- if current_mode and hint_mode == current_mode:
120
+ if mode_matches:
117
121
  score += 2
118
122
  if score <= 0:
119
123
  continue
@@ -375,6 +375,7 @@ def extract_page_state(payload):
375
375
 
376
376
 
377
377
  def extract_proof_evidence(payload):
378
+ payload = enrich_capture_payload(payload)
378
379
  evidence = []
379
380
  for text in iter_console_messages(payload.get('console') or []):
380
381
  raw_evidence = proof_evidence_console_payload(text)
@@ -154,11 +154,19 @@ class FakeRiddle:
154
154
  'ok': True,
155
155
  'outputs': [{'name': 'proof.json', 'url': 'https://cdn.example.com/proof.json'}],
156
156
  'result': {'pageState': page_state},
157
- 'console': [
158
- 'RIDDLE_PROOF_STATE:' + json.dumps(page_state),
159
- 'RIDDLE_PROOF_EVIDENCE:' + json.dumps(proof_evidence),
160
- ],
161
157
  '_artifact_json': {
158
+ 'console.json': {
159
+ 'summary': {'total_entries': 3, 'log_count': 2, 'warn_count': 0, 'error_count': 1, 'info_count': 0},
160
+ 'entries': {
161
+ 'log': [
162
+ {'message': 'RIDDLE_PROOF_STATE:' + json.dumps(page_state)},
163
+ {'message': 'RIDDLE_PROOF_EVIDENCE:' + json.dumps(proof_evidence)},
164
+ ],
165
+ 'warn': [],
166
+ 'error': [{'message': 'Uncaught exception: intentional capture script failure after evidence'}],
167
+ 'info': [],
168
+ },
169
+ },
162
170
  'proof.json': {
163
171
  'script_error': 'Error: intentional capture script failure after evidence',
164
172
  },
@@ -949,6 +957,73 @@ def run_recon_prefers_hint_root_over_single_route_literal():
949
957
  shutil.rmtree(tempdir, ignore_errors=True)
950
958
 
951
959
 
960
+ def run_capture_hint_rejects_route_specific_mode_only_match():
961
+ tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-hint-selection-'))
962
+ try:
963
+ util = load_module('util_hint_selection', UTIL_PATH)
964
+ repo_key = str(tempdir / 'repo')
965
+ state = {
966
+ 'repo': repo_key,
967
+ 'verification_mode': 'text',
968
+ 'change_request': 'Change the Tic Tac Toe reset button label to Reset Board.',
969
+ 'success_criteria': 'The Tic Tac Toe page shows Reset Board on /games/tic-tac-toe.',
970
+ }
971
+ _, cache_path = util.load_capture_hint_cache(state)
972
+ cache_file = Path(cache_path)
973
+ cache_file.parent.mkdir(parents=True, exist_ok=True)
974
+ cache_file.write_text(json.dumps({
975
+ 'version': util.CAPTURE_HINT_CACHE_VERSION,
976
+ 'hints': [
977
+ {
978
+ 'saved_at': '2026-04-25T00:00:00Z',
979
+ 'verification_mode': 'text',
980
+ 'request_tokens': ['sequencer', 'monkberry', 'drum'],
981
+ 'server_path': '/games/drum-sequencer',
982
+ 'wait_for_selector': '.drum-sequencer h1',
983
+ 'observed_path': '/games/drum-sequencer',
984
+ }
985
+ ],
986
+ }))
987
+
988
+ selected = util.select_capture_hint(state)
989
+ applied = util.apply_capture_hint(state)
990
+
991
+ assert selected is None, selected
992
+ assert applied is None, applied
993
+ assert 'server_path' not in state, state
994
+
995
+ cache_file.write_text(json.dumps({
996
+ 'version': util.CAPTURE_HINT_CACHE_VERSION,
997
+ 'hints': [
998
+ {
999
+ 'saved_at': '2026-04-25T00:00:00Z',
1000
+ 'verification_mode': 'text',
1001
+ 'request_tokens': ['homepage', 'hero'],
1002
+ 'server_path': '/',
1003
+ 'wait_for_selector': '',
1004
+ 'observed_path': '/',
1005
+ }
1006
+ ],
1007
+ }))
1008
+
1009
+ root_state = {
1010
+ 'repo': repo_key,
1011
+ 'verification_mode': 'text',
1012
+ 'change_request': 'Make a tiny harmless copy tweak.',
1013
+ 'success_criteria': 'The changed copy is visible.',
1014
+ }
1015
+ root_applied = util.apply_capture_hint(root_state)
1016
+ assert root_applied is not None, root_applied
1017
+ assert root_state['server_path'] == '/', root_state
1018
+ assert root_state['server_path_source'] == 'hint_cache', root_state
1019
+
1020
+ return {'ok': True, 'route_specific_selected': selected, 'root_server_path': root_state['server_path']}
1021
+ finally:
1022
+ if 'cache_file' in locals():
1023
+ cache_file.unlink(missing_ok=True)
1024
+ shutil.rmtree(tempdir, ignore_errors=True)
1025
+
1026
+
952
1027
  def run_author_applies_supervisor_packet():
953
1028
  tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-supervisor-apply-'))
954
1029
  state_path = tempdir / 'state.json'
@@ -1309,6 +1384,8 @@ def run_verify_preserves_proof_evidence_on_capture_script_error():
1309
1384
  assert supporting['has_structured_payload'] is True
1310
1385
  assert supporting['proof_evidence_present'] is True
1311
1386
  assert 'Captured structured audio evidence before the capture script threw' in supporting['proof_evidence_sample']
1387
+ assert after_verify['evidence_bundle']['proof_evidence'] is not None
1388
+ assert after_verify['evidence_bundle']['proof_evidence']['proof_evidence_present'] is False
1312
1389
  capture_quality = after_verify['verify_decision_request']['capture_quality']
1313
1390
  assert capture_quality['decision'] == 'failed_proof_evidence'
1314
1391
  assert capture_quality['recommended_stage'] == 'author'
@@ -1638,6 +1715,7 @@ if __name__ == '__main__':
1638
1715
  'recon_preserves_query_route': run_recon_preserves_query_route(),
1639
1716
  'recon_route_literal_preference': run_recon_prefers_route_literals_over_import_paths(),
1640
1717
  'recon_hint_root_preference': run_recon_prefers_hint_root_over_single_route_literal(),
1718
+ 'capture_hint_rejects_route_specific_mode_only_match': run_capture_hint_rejects_route_specific_mode_only_match(),
1641
1719
  'author_applies_supervisor_packet': run_author_applies_supervisor_packet(),
1642
1720
  'verify_requests_supervisor_assessment': run_verify_requests_supervisor_assessment(),
1643
1721
  'verify_structured_evidence_without_screenshot': run_verify_structured_evidence_without_screenshot(),