@riddledc/riddle-proof 0.7.225 → 0.7.226

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.
@@ -235,6 +235,16 @@ function baseContinuation(result) {
235
235
  continue_from_checkpoint: true
236
236
  };
237
237
  }
238
+ function carryRequestControlFlags(params, request) {
239
+ if (!noImplementationModeFor(request)) return params;
240
+ return compactRecord({
241
+ ...params,
242
+ mode: request.mode,
243
+ implementation_mode: request.implementation_mode || "none",
244
+ require_diff: request.require_diff ?? false,
245
+ allow_code_changes: request.allow_code_changes ?? false
246
+ });
247
+ }
238
248
  function initialRunParams(request, input, state) {
239
249
  return compactRecord({
240
250
  action: "run",
@@ -1389,7 +1399,10 @@ async function runRiddleProofEngineHarness(input) {
1389
1399
  message
1390
1400
  });
1391
1401
  }
1392
- let nextParams = input.resume_params || checkpointContinuation.next || initialRunParams(request, input, state);
1402
+ let nextParams = carryRequestControlFlags(
1403
+ input.resume_params || checkpointContinuation.next || initialRunParams(request, input, state),
1404
+ request
1405
+ );
1393
1406
  let lastResult = null;
1394
1407
  const stageIterations = {};
1395
1408
  for (let index = 0; index < maxIterations; index += 1) {
@@ -1502,7 +1515,7 @@ async function runRiddleProofEngineHarness(input) {
1502
1515
  message: "The harness route returned no next step."
1503
1516
  });
1504
1517
  }
1505
- nextParams = routed.next;
1518
+ nextParams = carryRequestControlFlags(routed.next, request);
1506
1519
  }
1507
1520
  return blockerResult(state, lastResult, {
1508
1521
  code: "max_iterations_reached",
package/dist/cli.cjs CHANGED
@@ -1661,6 +1661,10 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1661
1661
  const timer = beginRuntimeStep(config.statePath, action, step, stepWorkflowFile);
1662
1662
  let output;
1663
1663
  try {
1664
+ if (step === "setup") {
1665
+ (0, import_node_fs2.mkdirSync)(import_node_path2.default.dirname(config.argsPath), { recursive: true });
1666
+ (0, import_node_fs2.writeFileSync)(config.argsPath, JSON.stringify(args, null, 2));
1667
+ }
1664
1668
  output = JSON.parse(
1665
1669
  (0, import_node_child_process.execFileSync)(lobsterCommand, [...lobsterPrefix, "run", "--file", stepWorkflowFile, "--args-json", JSON.stringify(args)], {
1666
1670
  encoding: "utf-8",
@@ -4465,6 +4469,16 @@ function baseContinuation(result) {
4465
4469
  continue_from_checkpoint: true
4466
4470
  };
4467
4471
  }
4472
+ function carryRequestControlFlags(params, request) {
4473
+ if (!noImplementationModeFor(request)) return params;
4474
+ return compactRecord({
4475
+ ...params,
4476
+ mode: request.mode,
4477
+ implementation_mode: request.implementation_mode || "none",
4478
+ require_diff: request.require_diff ?? false,
4479
+ allow_code_changes: request.allow_code_changes ?? false
4480
+ });
4481
+ }
4468
4482
  function initialRunParams(request, input, state) {
4469
4483
  return compactRecord({
4470
4484
  action: "run",
@@ -5619,7 +5633,10 @@ async function runRiddleProofEngineHarness(input) {
5619
5633
  message
5620
5634
  });
5621
5635
  }
5622
- let nextParams = input.resume_params || checkpointContinuation.next || initialRunParams(request, input, state);
5636
+ let nextParams = carryRequestControlFlags(
5637
+ input.resume_params || checkpointContinuation.next || initialRunParams(request, input, state),
5638
+ request
5639
+ );
5623
5640
  let lastResult = null;
5624
5641
  const stageIterations = {};
5625
5642
  for (let index = 0; index < maxIterations; index += 1) {
@@ -5732,7 +5749,7 @@ async function runRiddleProofEngineHarness(input) {
5732
5749
  message: "The harness route returned no next step."
5733
5750
  });
5734
5751
  }
5735
- nextParams = routed.next;
5752
+ nextParams = carryRequestControlFlags(routed.next, request);
5736
5753
  }
5737
5754
  return blockerResult(state, lastResult, {
5738
5755
  code: "max_iterations_reached",
package/dist/cli.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  createDisabledRiddleProofAgentAdapter,
24
24
  readRiddleProofRunStatus,
25
25
  runRiddleProofEngineHarness
26
- } from "./chunk-4DRRIJDX.js";
26
+ } from "./chunk-QUAZAMOM.js";
27
27
  import "./chunk-OHJQRDST.js";
28
28
  import "./chunk-Y2KTBACQ.js";
29
29
  import "./chunk-GBVEQQIM.js";
@@ -1661,6 +1661,10 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1661
1661
  const timer = beginRuntimeStep(config.statePath, action, step, stepWorkflowFile);
1662
1662
  let output;
1663
1663
  try {
1664
+ if (step === "setup") {
1665
+ (0, import_node_fs2.mkdirSync)(import_node_path2.default.dirname(config.argsPath), { recursive: true });
1666
+ (0, import_node_fs2.writeFileSync)(config.argsPath, JSON.stringify(args, null, 2));
1667
+ }
1664
1668
  output = JSON.parse(
1665
1669
  (0, import_node_child_process.execFileSync)(lobsterCommand, [...lobsterPrefix, "run", "--file", stepWorkflowFile, "--args-json", JSON.stringify(args)], {
1666
1670
  encoding: "utf-8",
@@ -4394,6 +4398,16 @@ function baseContinuation(result) {
4394
4398
  continue_from_checkpoint: true
4395
4399
  };
4396
4400
  }
4401
+ function carryRequestControlFlags(params, request) {
4402
+ if (!noImplementationModeFor(request)) return params;
4403
+ return compactRecord({
4404
+ ...params,
4405
+ mode: request.mode,
4406
+ implementation_mode: request.implementation_mode || "none",
4407
+ require_diff: request.require_diff ?? false,
4408
+ allow_code_changes: request.allow_code_changes ?? false
4409
+ });
4410
+ }
4397
4411
  function initialRunParams(request, input, state) {
4398
4412
  return compactRecord({
4399
4413
  action: "run",
@@ -5548,7 +5562,10 @@ async function runRiddleProofEngineHarness(input) {
5548
5562
  message
5549
5563
  });
5550
5564
  }
5551
- let nextParams = input.resume_params || checkpointContinuation.next || initialRunParams(request, input, state);
5565
+ let nextParams = carryRequestControlFlags(
5566
+ input.resume_params || checkpointContinuation.next || initialRunParams(request, input, state),
5567
+ request
5568
+ );
5552
5569
  let lastResult = null;
5553
5570
  const stageIterations = {};
5554
5571
  for (let index = 0; index < maxIterations; index += 1) {
@@ -5661,7 +5678,7 @@ async function runRiddleProofEngineHarness(input) {
5661
5678
  message: "The harness route returned no next step."
5662
5679
  });
5663
5680
  }
5664
- nextParams = routed.next;
5681
+ nextParams = carryRequestControlFlags(routed.next, request);
5665
5682
  }
5666
5683
  return blockerResult(state, lastResult, {
5667
5684
  code: "max_iterations_reached",
@@ -2,7 +2,7 @@ import {
2
2
  createDisabledRiddleProofAgentAdapter,
3
3
  readRiddleProofRunStatus,
4
4
  runRiddleProofEngineHarness
5
- } from "./chunk-4DRRIJDX.js";
5
+ } from "./chunk-QUAZAMOM.js";
6
6
  import "./chunk-OHJQRDST.js";
7
7
  import "./chunk-Y2KTBACQ.js";
8
8
  import "./chunk-GBVEQQIM.js";
package/dist/index.cjs CHANGED
@@ -1661,6 +1661,10 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1661
1661
  const timer = beginRuntimeStep(config.statePath, action, step, stepWorkflowFile);
1662
1662
  let output;
1663
1663
  try {
1664
+ if (step === "setup") {
1665
+ (0, import_node_fs2.mkdirSync)(import_node_path2.default.dirname(config.argsPath), { recursive: true });
1666
+ (0, import_node_fs2.writeFileSync)(config.argsPath, JSON.stringify(args, null, 2));
1667
+ }
1664
1668
  output = JSON.parse(
1665
1669
  (0, import_node_child_process.execFileSync)(lobsterCommand, [...lobsterPrefix, "run", "--file", stepWorkflowFile, "--args-json", JSON.stringify(args)], {
1666
1670
  encoding: "utf-8",
@@ -5128,6 +5132,16 @@ function baseContinuation(result) {
5128
5132
  continue_from_checkpoint: true
5129
5133
  };
5130
5134
  }
5135
+ function carryRequestControlFlags(params, request) {
5136
+ if (!noImplementationModeFor(request)) return params;
5137
+ return compactRecord({
5138
+ ...params,
5139
+ mode: request.mode,
5140
+ implementation_mode: request.implementation_mode || "none",
5141
+ require_diff: request.require_diff ?? false,
5142
+ allow_code_changes: request.allow_code_changes ?? false
5143
+ });
5144
+ }
5131
5145
  function initialRunParams(request, input, state) {
5132
5146
  return compactRecord({
5133
5147
  action: "run",
@@ -6282,7 +6296,10 @@ async function runRiddleProofEngineHarness(input) {
6282
6296
  message
6283
6297
  });
6284
6298
  }
6285
- let nextParams = input.resume_params || checkpointContinuation.next || initialRunParams(request, input, state);
6299
+ let nextParams = carryRequestControlFlags(
6300
+ input.resume_params || checkpointContinuation.next || initialRunParams(request, input, state),
6301
+ request
6302
+ );
6286
6303
  let lastResult = null;
6287
6304
  const stageIterations = {};
6288
6305
  for (let index = 0; index < maxIterations; index += 1) {
@@ -6395,7 +6412,7 @@ async function runRiddleProofEngineHarness(input) {
6395
6412
  message: "The harness route returned no next step."
6396
6413
  });
6397
6414
  }
6398
- nextParams = routed.next;
6415
+ nextParams = carryRequestControlFlags(routed.next, request);
6399
6416
  }
6400
6417
  return blockerResult(state, lastResult, {
6401
6418
  code: "max_iterations_reached",
package/dist/index.js CHANGED
@@ -95,7 +95,7 @@ import {
95
95
  createDisabledRiddleProofAgentAdapter,
96
96
  readRiddleProofRunStatus,
97
97
  runRiddleProofEngineHarness
98
- } from "./chunk-4DRRIJDX.js";
98
+ } from "./chunk-QUAZAMOM.js";
99
99
  import {
100
100
  RIDDLE_PROOF_RUN_STATE_VERSION,
101
101
  appendRunEvent,
@@ -1659,6 +1659,10 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1659
1659
  const timer = beginRuntimeStep(config.statePath, action, step, stepWorkflowFile);
1660
1660
  let output;
1661
1661
  try {
1662
+ if (step === "setup") {
1663
+ (0, import_node_fs2.mkdirSync)(import_node_path2.default.dirname(config.argsPath), { recursive: true });
1664
+ (0, import_node_fs2.writeFileSync)(config.argsPath, JSON.stringify(args, null, 2));
1665
+ }
1662
1666
  output = JSON.parse(
1663
1667
  (0, import_node_child_process.execFileSync)(lobsterCommand, [...lobsterPrefix, "run", "--file", stepWorkflowFile, "--args-json", JSON.stringify(args)], {
1664
1668
  encoding: "utf-8",
@@ -19,7 +19,7 @@ import {
19
19
 
20
20
  // src/proof-run-engine.ts
21
21
  import { execFileSync } from "child_process";
22
- import { existsSync, mkdirSync } from "fs";
22
+ import { existsSync, mkdirSync, writeFileSync } from "fs";
23
23
  import path from "path";
24
24
  function snapshotFor(statePath) {
25
25
  return summarizeState(readState(statePath));
@@ -647,6 +647,10 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
647
647
  const timer = beginRuntimeStep(config.statePath, action, step, stepWorkflowFile);
648
648
  let output;
649
649
  try {
650
+ if (step === "setup") {
651
+ mkdirSync(path.dirname(config.argsPath), { recursive: true });
652
+ writeFileSync(config.argsPath, JSON.stringify(args, null, 2));
653
+ }
650
654
  output = JSON.parse(
651
655
  execFileSync(lobsterCommand, [...lobsterPrefix, "run", "--file", stepWorkflowFile, "--args-json", JSON.stringify(args)], {
652
656
  encoding: "utf-8",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.7.225",
3
+ "version": "0.7.226",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",
@@ -557,6 +557,50 @@ def extract_proof_evidence(payload):
557
557
  return evidence
558
558
 
559
559
 
560
+ def proof_evidence_records(value):
561
+ if isinstance(value, dict):
562
+ return [value]
563
+ if isinstance(value, list):
564
+ records = []
565
+ for item in value:
566
+ records.extend(proof_evidence_records(item))
567
+ return records
568
+ return []
569
+
570
+
571
+ def static_audit_evidence_support(value):
572
+ for record in proof_evidence_records(value):
573
+ explicit_static = (
574
+ record.get('interactionNotRequired') is True
575
+ or record.get('interactionExpected') is False
576
+ or record.get('zeroInteractiveElementsExpected') is True
577
+ or record.get('staticPageExpected') is True
578
+ )
579
+ ready = record.get('proofReady') is True or record.get('staticAuditReady') is True
580
+ failed = any(record.get(key) is False for key in (
581
+ 'proofReady',
582
+ 'staticAuditReady',
583
+ 'routeMatches',
584
+ 'titleMatches',
585
+ 'headingMatches',
586
+ 'markerMatches',
587
+ 'normalizedCopyVisible',
588
+ 'noConsoleErrors',
589
+ 'noPageErrors',
590
+ ))
591
+ if explicit_static and ready and not failed:
592
+ return {
593
+ 'ready': True,
594
+ 'interaction_not_required': True,
595
+ 'source': str(record.get('version') or record.get('mode') or 'proof_evidence'),
596
+ }
597
+ return {
598
+ 'ready': False,
599
+ 'interaction_not_required': False,
600
+ 'source': '',
601
+ }
602
+
603
+
560
604
  PLAYABILITY_EVIDENCE_VERSION = 'riddle-proof.playability.v1'
561
605
  PLAYABILITY_ASSESSMENT_VERSION = 'riddle-proof.playability.assessment.v1'
562
606
  PLAYABILITY_CONTAINER_KEYS = (
@@ -2012,6 +2056,8 @@ def evaluate_capture_quality(payload, expected_path, verification_mode='proof'):
2012
2056
  payload = enrich_capture_payload(payload)
2013
2057
  mode = normalized_verification_mode(verification_mode)
2014
2058
  supporting = collect_supporting_artifacts(payload)
2059
+ proof_evidence = extract_proof_evidence(payload)
2060
+ static_audit_support = static_audit_evidence_support(proof_evidence)
2015
2061
  structured_ready = bool(supporting.get('has_structured_payload'))
2016
2062
  playability_ready = mode in PLAYABILITY_MODES and bool(supporting.get('playability_ready'))
2017
2063
  screenshot_required = screenshot_required_for_mode(mode)
@@ -2023,6 +2069,8 @@ def evaluate_capture_quality(payload, expected_path, verification_mode='proof'):
2023
2069
  'structured_evidence_present': structured_ready,
2024
2070
  'proof_evidence_present': bool(supporting.get('proof_evidence_present')),
2025
2071
  'playability_ready': playability_ready,
2072
+ 'static_audit_ready': bool(static_audit_support.get('ready')),
2073
+ 'static_audit_support_source': static_audit_support.get('source', ''),
2026
2074
  'canvas_capture_ready': False,
2027
2075
  'large_canvas_area': 0,
2028
2076
  'min_canvas_area': MIN_CANVAS_AREA,
@@ -2110,13 +2158,15 @@ def evaluate_capture_quality(payload, expected_path, verification_mode='proof'):
2110
2158
 
2111
2159
  should_enforce_visual_readiness = screenshot_required or (details['has_screenshot'] and not structured_ready)
2112
2160
  canvas_ready = bool(details.get('canvas_capture_ready'))
2113
- body_text_ready = details['body_text_length'] >= MIN_BODY_TEXT_LENGTH or canvas_ready or playability_ready
2114
- interactive_ready = details['interactive_elements'] >= MIN_INTERACTIVE_ELEMENTS or canvas_ready or playability_ready
2115
- semantic_ready = (not has_enriched_page_state(page_state)) or details['semantic_anchor_count'] >= 1 or canvas_ready or playability_ready
2161
+ static_audit_ready = bool(static_audit_support.get('ready'))
2162
+ body_text_ready = details['body_text_length'] >= MIN_BODY_TEXT_LENGTH or canvas_ready or playability_ready or static_audit_ready
2163
+ interactive_ready = details['interactive_elements'] >= MIN_INTERACTIVE_ELEMENTS or canvas_ready or playability_ready or static_audit_ready
2164
+ semantic_ready = (not has_enriched_page_state(page_state)) or details['semantic_anchor_count'] >= 1 or canvas_ready or playability_ready or static_audit_ready
2116
2165
  details['body_text_ready'] = body_text_ready
2117
2166
  details['interactive_ready'] = interactive_ready
2118
2167
  details['semantic_ready'] = semantic_ready
2119
2168
  details['canvas_or_playability_override'] = bool(should_enforce_visual_readiness and (canvas_ready or playability_ready))
2169
+ details['static_audit_readiness_override'] = bool(should_enforce_visual_readiness and static_audit_ready)
2120
2170
 
2121
2171
  if should_enforce_visual_readiness and not body_text_ready:
2122
2172
  reasons.append(f'blank/near-blank page (text length: {details["body_text_length"]})')
@@ -101,48 +101,52 @@ steps:
101
101
  command: |
102
102
  python3 << 'PYEOF'
103
103
  import json, os
104
- raw_server_path = """${server_path}""".strip()
105
- args = {
106
- 'mode': """${mode}""".strip() or 'server',
107
- 'reference': """${reference}""".strip() or 'both',
108
- 'repo': """${repo}""".strip(),
109
- 'branch': """${branch}""".strip(),
110
- 'change_request': """${change_request}""".strip(),
111
- 'commit_message': """${commit_message}""".strip(),
112
- 'prod_url': """${prod_url}""".strip(),
113
- 'capture_script': """${capture_script}""".strip(),
114
- 'success_criteria': """${success_criteria}""".strip(),
115
- 'assertions_json': """${assertions_json}""".strip(),
116
- 'verification_mode': """${verification_mode}""".strip() or 'proof',
117
- 'context': """${context}""".strip(),
118
- 'reviewer': """${reviewer}""".strip() or 'davisdiehl',
119
- 'base_branch': """${base_branch}""".strip() or 'main',
120
- 'before_ref': """${before_ref}""".strip(),
121
- 'allow_static_preview_fallback': """${allow_static_preview_fallback}""".strip(),
122
- 'implementation_mode': """${implementation_mode}""".strip(),
123
- 'require_diff': """${require_diff}""".strip(),
124
- 'allow_code_changes': """${allow_code_changes}""".strip(),
125
- 'build_command': """${build_command}""".strip() or 'npm run build',
126
- 'build_output': """${build_output}""".strip() or 'build',
127
- 'server_image': """${server_image}""".strip() or 'node:20-slim',
128
- 'server_command': """${server_command}""".strip() or 'npm start',
129
- 'server_port': """${server_port}""".strip() or '3000',
130
- 'server_path': raw_server_path,
131
- 'server_path_source': 'user' if raw_server_path else '',
132
- 'use_auth': """${use_auth}""".strip(),
133
- 'auth_localStorage_json': """${auth_localStorage_json}""".strip(),
134
- 'auth_cookies_json': """${auth_cookies_json}""".strip(),
135
- 'auth_headers_json': """${auth_headers_json}""".strip(),
136
- 'color_scheme': """${color_scheme}""".strip(),
137
- 'wait_for_selector': """${wait_for_selector}""".strip(),
138
- 'discord_channel': """${discord_channel}""".strip(),
139
- 'discord_thread_id': """${discord_thread_id}""".strip(),
140
- 'discord_message_id': """${discord_message_id}""".strip(),
141
- 'discord_source_url': """${discord_source_url}""".strip(),
142
- }
143
104
  args_file = os.environ.get('RIDDLE_PROOF_ARGS_FILE', '/tmp/riddle-proof-args.json')
144
- with open(args_file, 'w') as f:
145
- json.dump(args, f, indent=2)
105
+ if os.environ.get('RIDDLE_PROOF_ARGS_FILE') and os.path.exists(args_file):
106
+ with open(args_file) as f:
107
+ json.load(f)
108
+ else:
109
+ raw_server_path = '''${server_path}'''.strip()
110
+ args = {
111
+ 'mode': '''${mode}'''.strip() or 'server',
112
+ 'reference': '''${reference}'''.strip() or 'both',
113
+ 'repo': '''${repo}'''.strip(),
114
+ 'branch': '''${branch}'''.strip(),
115
+ 'change_request': '''${change_request}'''.strip(),
116
+ 'commit_message': '''${commit_message}'''.strip(),
117
+ 'prod_url': '''${prod_url}'''.strip(),
118
+ 'capture_script': '''${capture_script}'''.strip(),
119
+ 'success_criteria': '''${success_criteria}'''.strip(),
120
+ 'assertions_json': '''${assertions_json}'''.strip(),
121
+ 'verification_mode': '''${verification_mode}'''.strip() or 'proof',
122
+ 'context': '''${context}'''.strip(),
123
+ 'reviewer': '''${reviewer}'''.strip() or 'davisdiehl',
124
+ 'base_branch': '''${base_branch}'''.strip() or 'main',
125
+ 'before_ref': '''${before_ref}'''.strip(),
126
+ 'allow_static_preview_fallback': '''${allow_static_preview_fallback}'''.strip(),
127
+ 'implementation_mode': '''${implementation_mode}'''.strip(),
128
+ 'require_diff': '''${require_diff}'''.strip(),
129
+ 'allow_code_changes': '''${allow_code_changes}'''.strip(),
130
+ 'build_command': '''${build_command}'''.strip() or 'npm run build',
131
+ 'build_output': '''${build_output}'''.strip() or 'build',
132
+ 'server_image': '''${server_image}'''.strip() or 'node:20-slim',
133
+ 'server_command': '''${server_command}'''.strip() or 'npm start',
134
+ 'server_port': '''${server_port}'''.strip() or '3000',
135
+ 'server_path': raw_server_path,
136
+ 'server_path_source': 'user' if raw_server_path else '',
137
+ 'use_auth': '''${use_auth}'''.strip(),
138
+ 'auth_localStorage_json': '''${auth_localStorage_json}'''.strip(),
139
+ 'auth_cookies_json': '''${auth_cookies_json}'''.strip(),
140
+ 'auth_headers_json': '''${auth_headers_json}'''.strip(),
141
+ 'color_scheme': '''${color_scheme}'''.strip(),
142
+ 'wait_for_selector': '''${wait_for_selector}'''.strip(),
143
+ 'discord_channel': '''${discord_channel}'''.strip(),
144
+ 'discord_thread_id': '''${discord_thread_id}'''.strip(),
145
+ 'discord_message_id': '''${discord_message_id}'''.strip(),
146
+ 'discord_source_url': '''${discord_source_url}'''.strip(),
147
+ }
148
+ with open(args_file, 'w') as f:
149
+ json.dump(args, f, indent=2)
146
150
  PYEOF
147
151
  RP="${RIDDLE_PROOF_DIR:-/root/.openclaw/extensions/openclaw-riddle-proof/node_modules/@riddledc/riddle-proof/runtime}"
148
152
  python3 "${RP}/lib/preflight.py"
@@ -562,6 +562,47 @@ def run_verify_quality_ignores_proof_telemetry_console_text():
562
562
  assert missing_query_quality['valid'] is False
563
563
  assert 'wrong route' in missing_query_quality['reason']
564
564
 
565
+ static_audit_payload = {
566
+ 'bodyTextLength': 61,
567
+ 'visibleTextSample': 'Riddle static preview smoke Static preview marker is visible.',
568
+ 'interactiveElements': 0,
569
+ 'visibleInteractiveElements': 0,
570
+ 'pathname': '/s/ps_b7b5f0dc/',
571
+ 'title': 'Riddle Preview Smoke',
572
+ 'headings': ['Riddle static preview smoke'],
573
+ 'buttons': [],
574
+ 'links': [],
575
+ 'canvasCount': 0,
576
+ 'largeVisibleElements': [{'tag': 'h1', 'text': 'Riddle static preview smoke', 'area': 17208}],
577
+ }
578
+ static_audit_evidence = {
579
+ 'version': 'riddle-proof.static-smoke.v4',
580
+ 'proofReady': True,
581
+ 'staticAuditReady': True,
582
+ 'interactionExpected': False,
583
+ 'interactionNotRequired': True,
584
+ 'zeroInteractiveElementsExpected': True,
585
+ 'routeMatches': True,
586
+ 'titleMatches': True,
587
+ 'headingMatches': True,
588
+ 'markerMatches': True,
589
+ 'normalizedCopyVisible': True,
590
+ 'noConsoleErrors': True,
591
+ 'noPageErrors': True,
592
+ }
593
+ static_audit_quality = namespace['evaluate_capture_quality']({
594
+ 'ok': True,
595
+ 'screenshots': [{'name': 'after-proof.png', 'url': 'https://cdn.example.com/static-after.png'}],
596
+ 'outputs': [{'name': 'after-proof.png', 'url': 'https://cdn.example.com/static-after.png'}],
597
+ 'console': [
598
+ 'RIDDLE_PROOF_STATE:' + json.dumps(static_audit_payload),
599
+ 'RIDDLE_PROOF_EVIDENCE:' + json.dumps(static_audit_evidence),
600
+ ],
601
+ }, '/s/ps_b7b5f0dc/', 'visual')
602
+ assert static_audit_quality['valid'] is True, static_audit_quality
603
+ assert static_audit_quality['details']['interactive_ready'] is True
604
+ assert static_audit_quality['details']['static_audit_readiness_override'] is True
605
+
565
606
  strong_delta = namespace['extract_visual_delta']({
566
607
  'ok': True,
567
608
  'result': {