@riddledc/riddle-proof 0.8.22 → 0.8.23

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
- export { p as proofRunCore } from '../proof-run-core-C8FDUhle.cjs';
4
- export { p as proofRunEngine } from '../proof-run-engine-D80hVFMf.cjs';
3
+ export { p as proofRunCore } from '../proof-run-core-CrpYH-qH.cjs';
4
+ export { p as proofRunEngine } from '../proof-run-engine-C6vYAZd8.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
- export { p as proofRunCore } from '../proof-run-core-C8FDUhle.js';
4
- export { p as proofRunEngine } from '../proof-run-engine-By7oLsF-.js';
3
+ export { p as proofRunCore } from '../proof-run-core-CrpYH-qH.js';
4
+ export { p as proofRunEngine } from '../proof-run-engine-h9C1lC0w.js';
5
5
  import '../types.js';
@@ -1 +1 @@
1
- export { B as BUNDLED_RIDDLE_PROOF_DIR, C as CHECKPOINT_CONTRACT_VERSION, b as CheckpointInputContract, P as PluginConfig, R as RIDDLE_PROOF_DIR_CANDIDATES, S as ShipGateValidation, c as WORKFLOW_STAGE_ORDER, d as WorkflowAction, W as WorkflowParams, a as WorkflowStage, e as buildCheckpointContract, f as buildSetupArgs, g as checkpointContinueStage, h as clearStageDecisionRequest, i as ensureAction, j as ensureStageLoopState, k as invalidateVerifyEvidence, m as mergeStateFromParams, n as noImplementationModeFor, l as previewModeFromWorkflowMode, o as proofAssessmentHardBlockersForState, q as readState, s as recordStageAttempt, t as requiredBaselineLabelsForState, r as resolveConfig, u as resolveRiddleProofDir, v as setStageDecisionRequest, w as summarizeState, x as validateShipGate, y as visualDeltaForState, z as visualDeltaRequiredForState, A as visualDeltaShipGateReason, D as workflowFile, E as writeState } from '../proof-run-core-C8FDUhle.cjs';
1
+ export { B as BUNDLED_RIDDLE_PROOF_DIR, C as CHECKPOINT_CONTRACT_VERSION, b as CheckpointInputContract, P as PluginConfig, R as RIDDLE_PROOF_DIR_CANDIDATES, S as ShipGateValidation, c as WORKFLOW_STAGE_ORDER, d as WorkflowAction, W as WorkflowParams, a as WorkflowStage, e as buildCheckpointContract, f as buildSetupArgs, g as checkpointContinueStage, h as clearStageDecisionRequest, i as ensureAction, j as ensureStageLoopState, k as invalidateVerifyEvidence, m as mergeStateFromParams, n as noImplementationModeFor, l as previewModeFromWorkflowMode, o as proofAssessmentHardBlockersForState, q as readState, s as recordStageAttempt, t as requiredBaselineLabelsForState, r as resolveConfig, u as resolveRiddleProofDir, v as setStageDecisionRequest, w as summarizeState, x as validateShipGate, y as visualDeltaForState, z as visualDeltaRequiredForState, A as visualDeltaShipGateReason, D as workflowFile, E as writeState } from '../proof-run-core-CrpYH-qH.cjs';
@@ -1 +1 @@
1
- export { B as BUNDLED_RIDDLE_PROOF_DIR, C as CHECKPOINT_CONTRACT_VERSION, b as CheckpointInputContract, P as PluginConfig, R as RIDDLE_PROOF_DIR_CANDIDATES, S as ShipGateValidation, c as WORKFLOW_STAGE_ORDER, d as WorkflowAction, W as WorkflowParams, a as WorkflowStage, e as buildCheckpointContract, f as buildSetupArgs, g as checkpointContinueStage, h as clearStageDecisionRequest, i as ensureAction, j as ensureStageLoopState, k as invalidateVerifyEvidence, m as mergeStateFromParams, n as noImplementationModeFor, l as previewModeFromWorkflowMode, o as proofAssessmentHardBlockersForState, q as readState, s as recordStageAttempt, t as requiredBaselineLabelsForState, r as resolveConfig, u as resolveRiddleProofDir, v as setStageDecisionRequest, w as summarizeState, x as validateShipGate, y as visualDeltaForState, z as visualDeltaRequiredForState, A as visualDeltaShipGateReason, D as workflowFile, E as writeState } from '../proof-run-core-C8FDUhle.js';
1
+ export { B as BUNDLED_RIDDLE_PROOF_DIR, C as CHECKPOINT_CONTRACT_VERSION, b as CheckpointInputContract, P as PluginConfig, R as RIDDLE_PROOF_DIR_CANDIDATES, S as ShipGateValidation, c as WORKFLOW_STAGE_ORDER, d as WorkflowAction, W as WorkflowParams, a as WorkflowStage, e as buildCheckpointContract, f as buildSetupArgs, g as checkpointContinueStage, h as clearStageDecisionRequest, i as ensureAction, j as ensureStageLoopState, k as invalidateVerifyEvidence, m as mergeStateFromParams, n as noImplementationModeFor, l as previewModeFromWorkflowMode, o as proofAssessmentHardBlockersForState, q as readState, s as recordStageAttempt, t as requiredBaselineLabelsForState, r as resolveConfig, u as resolveRiddleProofDir, v as setStageDecisionRequest, w as summarizeState, x as validateShipGate, y as visualDeltaForState, z as visualDeltaRequiredForState, A as visualDeltaShipGateReason, D as workflowFile, E as writeState } from '../proof-run-core-CrpYH-qH.js';
@@ -1,2 +1,2 @@
1
- export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from '../proof-run-engine-D80hVFMf.cjs';
2
- import '../proof-run-core-C8FDUhle.cjs';
1
+ export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from '../proof-run-engine-C6vYAZd8.cjs';
2
+ import '../proof-run-core-CrpYH-qH.cjs';
@@ -1,2 +1,2 @@
1
- export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from '../proof-run-engine-By7oLsF-.js';
2
- import '../proof-run-core-C8FDUhle.js';
1
+ export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from '../proof-run-engine-h9C1lC0w.js';
2
+ import '../proof-run-core-CrpYH-qH.js';
@@ -121,7 +121,7 @@ declare function buildSetupArgs(params: WorkflowParams, config: ReturnType<typeo
121
121
  target_image_hash: string;
122
122
  viewport_matrix_json: string;
123
123
  deterministic_setup_json: string;
124
- reference: "before" | "prod" | "both";
124
+ reference: "prod" | "before" | "both";
125
125
  base_branch: string;
126
126
  before_ref: string;
127
127
  allow_static_preview_fallback: string;
@@ -121,7 +121,7 @@ declare function buildSetupArgs(params: WorkflowParams, config: ReturnType<typeo
121
121
  target_image_hash: string;
122
122
  viewport_matrix_json: string;
123
123
  deterministic_setup_json: string;
124
- reference: "before" | "prod" | "both";
124
+ reference: "prod" | "before" | "both";
125
125
  base_branch: string;
126
126
  before_ref: string;
127
127
  allow_static_preview_fallback: string;
@@ -1 +1 @@
1
- export { B as BUNDLED_RIDDLE_PROOF_DIR, C as CHECKPOINT_CONTRACT_VERSION, b as CheckpointInputContract, P as PluginConfig, R as RIDDLE_PROOF_DIR_CANDIDATES, S as ShipGateValidation, c as WORKFLOW_STAGE_ORDER, d as WorkflowAction, W as WorkflowParams, a as WorkflowStage, e as buildCheckpointContract, f as buildSetupArgs, g as checkpointContinueStage, h as clearStageDecisionRequest, i as ensureAction, j as ensureStageLoopState, k as invalidateVerifyEvidence, m as mergeStateFromParams, n as noImplementationModeFor, l as previewModeFromWorkflowMode, o as proofAssessmentHardBlockersForState, q as readState, s as recordStageAttempt, t as requiredBaselineLabelsForState, r as resolveConfig, u as resolveRiddleProofDir, v as setStageDecisionRequest, w as summarizeState, x as validateShipGate, y as visualDeltaForState, z as visualDeltaRequiredForState, A as visualDeltaShipGateReason, D as workflowFile, E as writeState } from './proof-run-core-C8FDUhle.cjs';
1
+ export { B as BUNDLED_RIDDLE_PROOF_DIR, C as CHECKPOINT_CONTRACT_VERSION, b as CheckpointInputContract, P as PluginConfig, R as RIDDLE_PROOF_DIR_CANDIDATES, S as ShipGateValidation, c as WORKFLOW_STAGE_ORDER, d as WorkflowAction, W as WorkflowParams, a as WorkflowStage, e as buildCheckpointContract, f as buildSetupArgs, g as checkpointContinueStage, h as clearStageDecisionRequest, i as ensureAction, j as ensureStageLoopState, k as invalidateVerifyEvidence, m as mergeStateFromParams, n as noImplementationModeFor, l as previewModeFromWorkflowMode, o as proofAssessmentHardBlockersForState, q as readState, s as recordStageAttempt, t as requiredBaselineLabelsForState, r as resolveConfig, u as resolveRiddleProofDir, v as setStageDecisionRequest, w as summarizeState, x as validateShipGate, y as visualDeltaForState, z as visualDeltaRequiredForState, A as visualDeltaShipGateReason, D as workflowFile, E as writeState } from './proof-run-core-CrpYH-qH.cjs';
@@ -1 +1 @@
1
- export { B as BUNDLED_RIDDLE_PROOF_DIR, C as CHECKPOINT_CONTRACT_VERSION, b as CheckpointInputContract, P as PluginConfig, R as RIDDLE_PROOF_DIR_CANDIDATES, S as ShipGateValidation, c as WORKFLOW_STAGE_ORDER, d as WorkflowAction, W as WorkflowParams, a as WorkflowStage, e as buildCheckpointContract, f as buildSetupArgs, g as checkpointContinueStage, h as clearStageDecisionRequest, i as ensureAction, j as ensureStageLoopState, k as invalidateVerifyEvidence, m as mergeStateFromParams, n as noImplementationModeFor, l as previewModeFromWorkflowMode, o as proofAssessmentHardBlockersForState, q as readState, s as recordStageAttempt, t as requiredBaselineLabelsForState, r as resolveConfig, u as resolveRiddleProofDir, v as setStageDecisionRequest, w as summarizeState, x as validateShipGate, y as visualDeltaForState, z as visualDeltaRequiredForState, A as visualDeltaShipGateReason, D as workflowFile, E as writeState } from './proof-run-core-C8FDUhle.js';
1
+ export { B as BUNDLED_RIDDLE_PROOF_DIR, C as CHECKPOINT_CONTRACT_VERSION, b as CheckpointInputContract, P as PluginConfig, R as RIDDLE_PROOF_DIR_CANDIDATES, S as ShipGateValidation, c as WORKFLOW_STAGE_ORDER, d as WorkflowAction, W as WorkflowParams, a as WorkflowStage, e as buildCheckpointContract, f as buildSetupArgs, g as checkpointContinueStage, h as clearStageDecisionRequest, i as ensureAction, j as ensureStageLoopState, k as invalidateVerifyEvidence, m as mergeStateFromParams, n as noImplementationModeFor, l as previewModeFromWorkflowMode, o as proofAssessmentHardBlockersForState, q as readState, s as recordStageAttempt, t as requiredBaselineLabelsForState, r as resolveConfig, u as resolveRiddleProofDir, v as setStageDecisionRequest, w as summarizeState, x as validateShipGate, y as visualDeltaForState, z as visualDeltaRequiredForState, A as visualDeltaShipGateReason, D as workflowFile, E as writeState } from './proof-run-core-CrpYH-qH.js';
@@ -1,4 +1,4 @@
1
- import { W as WorkflowParams, r as resolveConfig, P as PluginConfig, a as WorkflowStage } from './proof-run-core-C8FDUhle.cjs';
1
+ import { W as WorkflowParams, r as resolveConfig, P as PluginConfig, a as WorkflowStage } from './proof-run-core-CrpYH-qH.cjs';
2
2
 
3
3
  declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, resolvedConfig?: ReturnType<typeof resolveConfig>): Promise<{
4
4
  ok: boolean;
@@ -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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
295
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
385
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup";
662
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship";
663
663
  state_path: string;
664
664
  stage: any;
665
665
  summary: string;
@@ -1,4 +1,4 @@
1
- import { W as WorkflowParams, r as resolveConfig, P as PluginConfig, a as WorkflowStage } from './proof-run-core-C8FDUhle.js';
1
+ import { W as WorkflowParams, r as resolveConfig, P as PluginConfig, a as WorkflowStage } from './proof-run-core-CrpYH-qH.js';
2
2
 
3
3
  declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, resolvedConfig?: ReturnType<typeof resolveConfig>): Promise<{
4
4
  ok: boolean;
@@ -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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
295
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup" | "run";
385
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship" | "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: "author" | "recon" | "ship" | "implement" | "verify" | "setup";
662
+ action: "setup" | "recon" | "author" | "implement" | "verify" | "ship";
663
663
  state_path: string;
664
664
  stage: any;
665
665
  summary: string;
@@ -1,2 +1,2 @@
1
- import './proof-run-core-C8FDUhle.cjs';
2
- export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-D80hVFMf.cjs';
1
+ import './proof-run-core-CrpYH-qH.cjs';
2
+ export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-C6vYAZd8.cjs';
@@ -1,2 +1,2 @@
1
- import './proof-run-core-C8FDUhle.js';
2
- export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-By7oLsF-.js';
1
+ import './proof-run-core-CrpYH-qH.js';
2
+ export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-h9C1lC0w.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.8.22",
3
+ "version": "0.8.23",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",
@@ -2723,6 +2723,29 @@ def failed_interaction_evidence_summary(proof_evidence):
2723
2723
  return summary
2724
2724
 
2725
2725
 
2726
+ def interaction_failed_evidence_after_script_error_summary(proof_evidence, capture_error):
2727
+ capture_error = str(capture_error or '').strip()
2728
+ if not capture_error:
2729
+ return ''
2730
+ failures = []
2731
+ for record in proof_evidence_records(proof_evidence):
2732
+ failures.extend(collect_interaction_failed_assertions(record))
2733
+ deduped = []
2734
+ seen = set()
2735
+ for failure in failures:
2736
+ failure = str(failure or '').strip()
2737
+ if not failure or failure in seen:
2738
+ continue
2739
+ seen.add(failure)
2740
+ deduped.append(failure)
2741
+ if not deduped:
2742
+ return ''
2743
+ summary = 'Interaction capture emitted failed structured proof evidence before the capture script completed.'
2744
+ summary += ' Failed checks: ' + ', '.join(deduped[:8]) + '.'
2745
+ summary += ' Capture script error: ' + capture_error[:300]
2746
+ return summary
2747
+
2748
+
2726
2749
  def interaction_capture_failure_evidence_summary(proof_evidence):
2727
2750
  for record in proof_evidence_records_deep(proof_evidence):
2728
2751
  if not isinstance(record, dict):
@@ -4073,8 +4096,20 @@ structured_interaction_failure_summary = ''
4073
4096
  structured_interaction_capture_failure_summary = ''
4074
4097
  proof_evidence = evidence_bundle.get('proof_evidence')
4075
4098
  if verification_mode in INTERACTION_MODES and proof_evidence is not None:
4099
+ capture_error_messages = []
4100
+ if isinstance(after_observation.get('details'), dict):
4101
+ capture_error_messages = [
4102
+ str(item).strip()
4103
+ for item in (after_observation.get('details') or {}).get('capture_error_messages') or []
4104
+ if str(item).strip()
4105
+ ]
4076
4106
  structured_interaction_failure_summary = failed_interaction_evidence_summary(proof_evidence)
4077
4107
  structured_interaction_capture_failure_summary = interaction_capture_failure_evidence_summary(proof_evidence)
4108
+ if capture_error_messages and not structured_interaction_capture_failure_summary:
4109
+ structured_interaction_capture_failure_summary = interaction_failed_evidence_after_script_error_summary(
4110
+ proof_evidence,
4111
+ capture_error_messages[0],
4112
+ )
4078
4113
  if structured_interaction_failure_summary:
4079
4114
  summary_lines.append('Structured interaction evidence gate: ' + structured_interaction_failure_summary)
4080
4115
  if structured_interaction_capture_failure_summary:
@@ -718,6 +718,47 @@ class FakeRiddle:
718
718
  'proof.json': {'script_error': message},
719
719
  },
720
720
  }
721
+ if 'interactionThrownAfterFailedEvidence' in script:
722
+ message = 'Error: intentional-riddle-proof-0823-thrown-error-after-failed-evidence'
723
+ page_state = {
724
+ 'bodyTextLength': 180,
725
+ 'visibleTextSample': 'Riddle Proof homepage hero Start Free',
726
+ 'interactiveElements': 4,
727
+ 'visibleInteractiveElements': 4,
728
+ 'pathname': '/',
729
+ 'search': '',
730
+ 'hash': '',
731
+ 'title': 'Riddle',
732
+ 'buttons': ['Start Free'],
733
+ 'headings': ['Riddle Proof'],
734
+ 'links': [],
735
+ 'canvasCount': 0,
736
+ 'largeVisibleElements': [{'tag': 'h1', 'text': 'Riddle Proof'}],
737
+ }
738
+ proof_evidence = {
739
+ 'version': 'riddle-proof.interaction.v1',
740
+ 'evidence_summary': 'Structured interaction evidence was emitted before the diagnostic script threw.',
741
+ 'checks': {
742
+ 'passed': False,
743
+ 'success': False,
744
+ 'proofReady': False,
745
+ },
746
+ 'capture_error': message,
747
+ }
748
+ return {
749
+ 'ok': True,
750
+ 'screenshots': [{'url': 'https://cdn.example.com/thrown-error-failed-evidence.png'}],
751
+ 'outputs': [{'name': 'after-thrown-error.png', 'url': 'https://cdn.example.com/thrown-error-failed-evidence.png'}],
752
+ 'result': {'pageState': page_state, 'proofEvidence': proof_evidence},
753
+ 'console': [
754
+ 'RIDDLE_PROOF_STATE:' + json.dumps(page_state),
755
+ 'RIDDLE_PROOF_EVIDENCE:' + json.dumps(proof_evidence),
756
+ 'Uncaught exception: ' + message,
757
+ ],
758
+ '_artifact_json': {
759
+ 'proof.json': {'script_error': message},
760
+ },
761
+ }
721
762
  if 'interactionThrownError' in script:
722
763
  message = 'Error: intentional-riddle-proof-0811-thrown-error'
723
764
  page_state = {
@@ -3449,6 +3490,65 @@ def run_verify_interaction_thrown_error_terminal_blocker():
3449
3490
  shutil.rmtree(tempdir, ignore_errors=True)
3450
3491
 
3451
3492
 
3493
+ def run_verify_interaction_thrown_error_after_failed_evidence_terminal_blocker():
3494
+ tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-interaction-thrown-after-evidence-'))
3495
+ state_path = tempdir / 'state.json'
3496
+ try:
3497
+ state = base_state(tempdir, reference='before')
3498
+ state.update({
3499
+ 'recon_status': 'ready_for_proof_plan',
3500
+ 'author_status': 'ready',
3501
+ 'proof_plan_status': 'ready',
3502
+ 'implementation_status': 'changes_detected',
3503
+ 'verification_mode': 'interaction',
3504
+ 'server_path': '/',
3505
+ 'before_cdn': 'https://cdn.example.com/before-home.png',
3506
+ 'proof_plan': 'Run a diagnostic interaction script that emits failed proof evidence and then intentionally throws.',
3507
+ 'capture_script': "interactionThrownAfterFailedEvidence();",
3508
+ 'recon_results': {
3509
+ 'baselines': {'before': {'path': '/', 'url': 'https://cdn.example.com/before-home.png'}},
3510
+ },
3511
+ })
3512
+ write_state(state_path, state)
3513
+ os.environ['RIDDLE_PROOF_STATE_FILE'] = str(state_path)
3514
+
3515
+ fake = FakeRiddle()
3516
+ load_util_with_fake(fake)
3517
+ load_module('verify_interaction_thrown_error_after_failed_evidence_terminal_blocker', VERIFY_PATH)
3518
+ after_verify = json.loads(state_path.read_text())
3519
+
3520
+ assert after_verify['verify_status'] == 'capture_incomplete'
3521
+ assert after_verify['merge_recommendation'] == 'do-not-merge'
3522
+ assert after_verify['proof_assessment_request'] == {}
3523
+ capture_quality = after_verify['verify_decision_request']['capture_quality']
3524
+ assert capture_quality['decision'] == 'failed_interaction_capture'
3525
+ assert capture_quality['recommended_stage'] is None
3526
+ assert capture_quality['continue_with_stage'] is None
3527
+ assert capture_quality['blocking'] is True
3528
+ assert capture_quality['terminal_blocker'] is True
3529
+ capture_quality_text = json.dumps(capture_quality, sort_keys=True)
3530
+ assert 'intentional-riddle-proof-0823-thrown-error-after-failed-evidence' in capture_quality_text
3531
+ assert 'proofReady' in capture_quality_text
3532
+ assert after_verify['structured_interaction_capture_failure_summary']
3533
+ evidence = after_verify['evidence_bundle']['proof_evidence']
3534
+ if isinstance(evidence, list):
3535
+ evidence = next(
3536
+ record for record in evidence_records(evidence)
3537
+ if isinstance(record.get('checks'), dict) and record['checks'].get('proofReady') is False
3538
+ )
3539
+ assert evidence['checks']['passed'] is False
3540
+ assert evidence['checks']['success'] is False
3541
+ assert evidence['checks']['proofReady'] is False
3542
+ assert 'Structured interaction capture blocker' in after_verify['proof_summary']
3543
+ return {
3544
+ 'ok': True,
3545
+ 'decision': capture_quality['decision'],
3546
+ 'blocking': capture_quality['blocking'],
3547
+ }
3548
+ finally:
3549
+ shutil.rmtree(tempdir, ignore_errors=True)
3550
+
3551
+
3452
3552
  def run_verify_capture_retry_surfaces_script_timeout():
3453
3553
  tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-capture-timeout-'))
3454
3554
  state_path = tempdir / 'state.json'
@@ -3878,6 +3978,7 @@ if __name__ == '__main__':
3878
3978
  'verify_interaction_query_hash_pass_uses_proof_evidence_route': run_verify_interaction_query_hash_pass_uses_proof_evidence_route(),
3879
3979
  'verify_interaction_explicit_expected_url_blocks_dropped_terminal_route': run_verify_interaction_explicit_expected_url_blocks_dropped_terminal_route(),
3880
3980
  'verify_interaction_thrown_error_terminal_blocker': run_verify_interaction_thrown_error_terminal_blocker(),
3981
+ 'verify_interaction_thrown_error_after_failed_evidence_terminal_blocker': run_verify_interaction_thrown_error_after_failed_evidence_terminal_blocker(),
3881
3982
  'verify_capture_retry_surfaces_script_timeout': run_verify_capture_retry_surfaces_script_timeout(),
3882
3983
  'missing_baseline_guard': run_verify_missing_baseline(),
3883
3984
  'ship_supervisor_gate': run_ship_missing_supervisor_gate(),
@@ -97,6 +97,12 @@ CASES = [
97
97
  'function': 'run_verify_interaction_thrown_error_terminal_blocker',
98
98
  'expected_terminal': 'specific_blocker',
99
99
  },
100
+ {
101
+ 'name': 'interaction-thrown-error-after-failed-evidence-specific-blocker',
102
+ 'covers': ['thrown errors', 'proof-evidence-present', 'invalid browser evidence'],
103
+ 'function': 'run_verify_interaction_thrown_error_after_failed_evidence_terminal_blocker',
104
+ 'expected_terminal': 'specific_blocker',
105
+ },
100
106
  {
101
107
  'name': 'structured-proof-without-screenshot-pass',
102
108
  'covers': ['proof-evidence-present'],