@riddledc/riddle-proof 0.8.41 → 0.8.43

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.
@@ -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-DYUu2mqY.cjs';
4
+ export { p as proofRunEngine } from '../proof-run-engine-4dM37pEx.cjs';
5
5
  import '../types.cjs';
@@ -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-BmNYuOJ7.js';
4
+ export { p as proofRunEngine } from '../proof-run-engine-BqaeqAze.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-DYUu2mqY.cjs';
1
+ export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from '../proof-run-engine-4dM37pEx.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-BmNYuOJ7.js';
1
+ export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from '../proof-run-engine-BqaeqAze.js';
2
2
  import '../proof-run-core-B1GeqkR8.js';
@@ -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: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
295
+ action: "author" | "recon" | "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: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
385
+ action: "author" | "recon" | "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: "setup" | "recon" | "author" | "implement" | "verify" | "ship";
662
+ action: "author" | "recon" | "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: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
295
+ action: "author" | "recon" | "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: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "run";
385
+ action: "author" | "recon" | "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: "setup" | "recon" | "author" | "implement" | "verify" | "ship";
662
+ action: "author" | "recon" | "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-DYUu2mqY.cjs';
2
+ export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-4dM37pEx.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-BmNYuOJ7.js';
2
+ export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-BqaeqAze.js';
@@ -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.146",
8
- "@riddledc/riddle-proof": "0.8.18"
7
+ "@riddledc/openclaw-riddle-proof": "0.4.155",
8
+ "@riddledc/riddle-proof": "0.8.43"
9
9
  },
10
10
  "runtime_gate": {
11
11
  "tool": "riddle_proof_status",
@@ -287,7 +287,7 @@
287
287
  "wait for main#main-content",
288
288
  "click a visible Proof link whose href includes /proof",
289
289
  "wait for terminal URL https://riddledc.com/proof/",
290
- "return riddle-proof.interaction.v1 evidence with start, action, terminal, assertions, and routeExpectationSource=capture_script.expectedUrl",
290
+ "return riddle-proof.interaction.v1 evidence with start, action, terminal, assertions, and routeExpectationSource=expected_terminal_path",
291
291
  "save screenshot after-proof"
292
292
  ]
293
293
  },
@@ -295,7 +295,7 @@
295
295
  "terminal_status": "ready_to_ship",
296
296
  "terminal_path": "/proof/",
297
297
  "proof_evidence_present": true,
298
- "route_expectation_source": "capture_script.expectedUrl",
298
+ "route_expectation_source": "expected_terminal_path",
299
299
  "forbidden_terminal_markers": []
300
300
  }
301
301
  },
@@ -321,7 +321,7 @@
321
321
  "terminal_status": "ready_to_ship",
322
322
  "terminal_path": "/",
323
323
  "proof_evidence_present": true,
324
- "route_expectation_source": "capture_script.expectedUrl",
324
+ "route_expectation_source": "expected_terminal_path",
325
325
  "forbidden_terminal_markers": []
326
326
  }
327
327
  },
@@ -386,9 +386,9 @@
386
386
  {
387
387
  "id": "no-diff-prod-audit-pass",
388
388
  "tool": "riddle_proof_change",
389
- "intent": "Audit the live production home page without implementation or PR handoff, and prove the current target evidence directly.",
389
+ "intent": "Audit the live production home page without implementation or PR handoff, and prove the current target visually without any browser interaction.",
390
390
  "params": {
391
- "verification_mode": "interaction",
391
+ "verification_mode": "visual",
392
392
  "implementation_mode": "none",
393
393
  "require_diff": false,
394
394
  "allow_code_changes": false,
@@ -398,15 +398,18 @@
398
398
  "capture_script_contract": [
399
399
  "use the current production target only",
400
400
  "do not request implementation or git diff",
401
+ "do not click, type, submit, copy, navigate, or interact with any button or link",
401
402
  "prove main#main-content and expected home-page content are visible",
402
- "return structured evidence and save screenshot after-proof"
403
+ "save screenshot after-proof and treat this as a passive visual/no-diff audit, not an interaction proof"
403
404
  ]
404
405
  },
405
406
  "expect": {
406
407
  "terminal_status": "ready_to_ship",
407
408
  "ship_handoff": "none",
408
409
  "implementation_attempted": false,
409
- "proof_evidence_present": true,
410
+ "proof_evidence_required": false,
411
+ "screenshot_required": true,
412
+ "browser_interaction_performed": false,
410
413
  "forbidden_terminal_markers": []
411
414
  }
412
415
  },
@@ -473,16 +476,22 @@
473
476
  "verification_mode": "interaction",
474
477
  "server_path": "/",
475
478
  "wait_for_selector": "main#main-content",
479
+ "expected_terminal_url": "https://riddledc.com/proof/",
476
480
  "checkpoint_mode": "terminal_only",
477
481
  "report_mode": "terminal_only",
478
482
  "capture_script_contract": [
479
- "complete the Home -> Proof route proof",
483
+ "complete the Home -> Proof route proof by clicking the visible Proof nav link only",
484
+ "do not click Docs, Pricing, MCP, Blog, Playground, Copy, or any other link or button",
485
+ "terminal URL must be https://riddledc.com/proof/ and terminal path must be /proof",
480
486
  "terminalize as ready_to_ship before any manual checkpoint injection",
481
487
  "record state_path and run_id from riddle_proof_status"
482
488
  ]
483
489
  },
484
490
  "expect": {
485
491
  "terminal_status": "ready_to_ship",
492
+ "terminal_url": "https://riddledc.com/proof/",
493
+ "terminal_path": "/proof",
494
+ "route_expectation_source": "expected_terminal_path",
486
495
  "proof_evidence_present": true
487
496
  }
488
497
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.8.41",
3
+ "version": "0.8.43",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",
@@ -20,6 +20,7 @@ from util import ( # noqa: E402
20
20
  build_capture_script,
21
21
  capture_static_preview,
22
22
  capture_viewport_matrix_status,
23
+ compose_remote_capture_url,
23
24
  enrich_capture_payload,
24
25
  has_auth_context,
25
26
  invoke_retry,
@@ -41,6 +42,7 @@ MIN_CANVAS_AREA = 50000
41
42
  HYDRATION_WAIT_MS = 1500
42
43
  PAGE_STATE_PREFIX = 'RIDDLE_PROOF_STATE:'
43
44
  PROOF_EVIDENCE_PREFIX = 'RIDDLE_PROOF_EVIDENCE:'
45
+ INTERACTION_VERIFICATION_MODES = {'interaction', 'flow', 'browser_interaction'}
44
46
 
45
47
  s = load_state()
46
48
  after_dir = (s.get('after_worktree') or '').strip()
@@ -808,7 +810,7 @@ def capture_workspace_baseline(project_dir, label, plan, capture_script=''):
808
810
 
809
811
 
810
812
  def capture_prod_baseline(prod_url, plan, capture_script=''):
811
- target_url = (prod_url or '').strip()
813
+ target_url = prod_capture_target_url(prod_url, plan)
812
814
  if not target_url:
813
815
  raise SystemExit('Requested prod baseline in recon, but prod_url is missing.')
814
816
  wait_for_selector = (plan.get('wait_for_selector') or '').strip()
@@ -821,7 +823,7 @@ def capture_prod_baseline(prod_url, plan, capture_script=''):
821
823
  append_capture_diagnostic(s, 'prod', 'riddle_script', args, shot)
822
824
  record_recon_phase('prod_capture', 'completed', 'Production recon baseline capture completed.')
823
825
  return {
824
- 'source': 'prod_url',
826
+ 'source': 'prod_url_with_target_path' if target_url != (prod_url or '').strip() else 'prod_url',
825
827
  'mode': 'remote',
826
828
  'path': normalize_observed_path(target_url) or (plan.get('target_path') or '/'),
827
829
  'capture_url': target_url,
@@ -831,6 +833,19 @@ def capture_prod_baseline(prod_url, plan, capture_script=''):
831
833
  }
832
834
 
833
835
 
836
+ def interaction_verification_mode():
837
+ return str(s.get('verification_mode') or '').strip().lower() in INTERACTION_VERIFICATION_MODES
838
+
839
+
840
+ def prod_capture_target_url(prod_url, plan):
841
+ target_path = str((plan or {}).get('target_path') or '').strip()
842
+ has_explicit_start_route = bool(
843
+ str(s.get('server_path') or s.get('expected_start_path') or '').strip()
844
+ and (str(s.get('server_path_source') or '').strip() or interaction_verification_mode())
845
+ )
846
+ return compose_remote_capture_url(prod_url, target_path, explicit_target=has_explicit_start_route)
847
+
848
+
834
849
  def baseline_record(capture, observation):
835
850
  return {
836
851
  'source': capture.get('source'),
@@ -1066,7 +1081,7 @@ for label in required_baselines:
1066
1081
  expected_path = current_plan['target_path']
1067
1082
  else:
1068
1083
  capture = capture_prod_baseline(s.get('prod_url', ''), current_plan, capture_script='')
1069
- expected_path = urlparse(s.get('prod_url', '')).path or current_plan['target_path']
1084
+ expected_path = normalize_observed_path(capture.get('capture_url')) or current_plan['target_path']
1070
1085
  observation = build_observation_packet(label, expected_path, capture=capture)
1071
1086
  except SystemExit:
1072
1087
  raise
@@ -1,7 +1,7 @@
1
1
  """Shared helpers for Riddle Proof pipeline."""
2
2
 
3
3
  import hashlib, json, os, re, shlex, subprocess as sp, tempfile, time
4
- from urllib.parse import urljoin
4
+ from urllib.parse import urljoin, urlparse, urlunparse
5
5
  from urllib.request import urlopen
6
6
 
7
7
  STATE_FILE = os.environ.get('RIDDLE_PROOF_STATE_FILE', '/tmp/riddle-proof-state.json')
@@ -86,6 +86,44 @@ def normalize_browser_path(value):
86
86
  return value.lower() or '/'
87
87
 
88
88
 
89
+ def compose_remote_capture_url(base_url, target_path='', explicit_target=False):
90
+ """Resolve a remote capture URL against an explicit browser route.
91
+
92
+ prod_url identifies the deployed origin, but interaction proofs may start on
93
+ a route such as /proof/ before navigating elsewhere. In that case recon must
94
+ capture the start route, not merely the prod_url root.
95
+ """
96
+ base = str(base_url or '').strip()
97
+ target = str(target_path or '').strip()
98
+ if not base or not target.startswith('/'):
99
+ return base
100
+
101
+ parsed_base = urlparse(base)
102
+ if not parsed_base.scheme or not parsed_base.netloc:
103
+ return base
104
+
105
+ parsed_target = urlparse(target)
106
+ target_browser_path = parsed_target.path or '/'
107
+ if not target_browser_path.startswith('/'):
108
+ target_browser_path = '/' + target_browser_path.lstrip('/')
109
+
110
+ if not explicit_target:
111
+ base_browser_path = parsed_base.path or '/'
112
+ if normalize_browser_path(target_browser_path) in ('', '/') and normalize_browser_path(base_browser_path) != '/':
113
+ return base
114
+ if normalize_browser_path(target_browser_path) == normalize_browser_path(base_browser_path):
115
+ return base
116
+
117
+ return urlunparse((
118
+ parsed_base.scheme,
119
+ parsed_base.netloc,
120
+ target_browser_path,
121
+ '',
122
+ parsed_target.query,
123
+ parsed_target.fragment,
124
+ ))
125
+
126
+
89
127
  def extract_browser_paths(text):
90
128
  paths = []
91
129
  for match in re.findall(r'/(?:[A-Za-z0-9._~%!$&\'()*+,;=:@-]+/?)+(?:\?[A-Za-z0-9._~%!$&\'()*+,;=:@/?-]*)?', str(text or '')):
@@ -70,6 +70,35 @@ def load_module(name: str, path: Path):
70
70
  return module
71
71
 
72
72
 
73
+ def run_recon_remote_prod_capture_uses_interaction_start_route():
74
+ util = load_module('riddle_proof_util_route_target_smoke', UTIL_PATH)
75
+ cases = [
76
+ (
77
+ util.compose_remote_capture_url('https://riddledc.com/', '/proof/', explicit_target=True),
78
+ 'https://riddledc.com/proof/',
79
+ ),
80
+ (
81
+ util.compose_remote_capture_url('https://riddledc.com/', '/pricing/?rp_probe=1#pricing-probe', explicit_target=True),
82
+ 'https://riddledc.com/pricing/?rp_probe=1#pricing-probe',
83
+ ),
84
+ (
85
+ util.compose_remote_capture_url('https://riddledc.com/proof/', '/', explicit_target=True),
86
+ 'https://riddledc.com/',
87
+ ),
88
+ (
89
+ util.compose_remote_capture_url('https://riddledc.com/proof/', '/', explicit_target=False),
90
+ 'https://riddledc.com/proof/',
91
+ ),
92
+ ]
93
+ for observed, expected in cases:
94
+ assert observed == expected, f'expected {expected}, got {observed}'
95
+ return {
96
+ 'ok': True,
97
+ 'remote_start_route': 'https://riddledc.com/proof/',
98
+ 'query_hash_route': 'https://riddledc.com/pricing/?rp_probe=1#pricing-probe',
99
+ }
100
+
101
+
73
102
  class FakeRiddle:
74
103
  def __init__(self):
75
104
  self.calls = []
@@ -19,6 +19,12 @@ def load_smoke_module():
19
19
 
20
20
 
21
21
  CASES = [
22
+ {
23
+ 'name': 'recon-remote-prod-captures-interaction-start-route',
24
+ 'covers': ['route-changing interactions', 'no-diff prod audits'],
25
+ 'function': 'run_recon_remote_prod_capture_uses_interaction_start_route',
26
+ 'expected_terminal': 'pass',
27
+ },
22
28
  {
23
29
  'name': 'route-change-forward-pass',
24
30
  'covers': ['route-changing interactions', 'proof-evidence-present'],