@riddledc/riddle-proof 0.8.10 → 0.8.12
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/dist/advanced/engine-harness.cjs +97 -12
- package/dist/advanced/engine-harness.js +2 -2
- package/dist/advanced/index.cjs +98 -12
- package/dist/advanced/index.d.cts +2 -2
- package/dist/advanced/index.d.ts +2 -2
- package/dist/advanced/index.js +4 -4
- package/dist/advanced/proof-run-core.cjs +31 -1
- package/dist/advanced/proof-run-core.d.cts +1 -1
- package/dist/advanced/proof-run-core.d.ts +1 -1
- package/dist/advanced/proof-run-core.js +3 -1
- package/dist/advanced/proof-run-engine.cjs +46 -12
- package/dist/advanced/proof-run-engine.d.cts +2 -2
- package/dist/advanced/proof-run-engine.d.ts +2 -2
- package/dist/advanced/proof-run-engine.js +2 -2
- package/dist/advanced/runner.js +2 -2
- package/dist/{chunk-5N5QFI2S.js → chunk-7GZY5PLT.js} +31 -1
- package/dist/{chunk-46DDSZJR.js → chunk-JBY2SU5U.js} +18 -12
- package/dist/{chunk-5N6MQCLC.js → chunk-NGX4SUQN.js} +1 -1
- package/dist/{chunk-BBUO7HM4.js → chunk-RTLA6CPP.js} +53 -1
- package/dist/{chunk-2PXL3RDB.js → chunk-SZUC4MDN.js} +1 -1
- package/dist/cli/index.js +3 -3
- package/dist/cli.cjs +97 -12
- package/dist/cli.js +3 -3
- package/dist/engine-harness.cjs +97 -12
- package/dist/engine-harness.js +2 -2
- package/dist/index.cjs +97 -12
- package/dist/index.js +3 -3
- package/dist/{proof-run-core-Ci9uFxMc.d.cts → proof-run-core-CrpYH-qH.d.cts} +5 -2
- package/dist/{proof-run-core-Ci9uFxMc.d.ts → proof-run-core-CrpYH-qH.d.ts} +5 -2
- package/dist/proof-run-core.cjs +31 -1
- package/dist/proof-run-core.d.cts +1 -1
- package/dist/proof-run-core.d.ts +1 -1
- package/dist/proof-run-core.js +3 -1
- package/dist/{proof-run-engine-Bd1T43Dy.d.cts → proof-run-engine-C6vYAZd8.d.cts} +1 -1
- package/dist/{proof-run-engine-CXyhB-io.d.ts → proof-run-engine-h9C1lC0w.d.ts} +1 -1
- package/dist/proof-run-engine.cjs +46 -12
- package/dist/proof-run-engine.d.cts +2 -2
- package/dist/proof-run-engine.d.ts +2 -2
- package/dist/proof-run-engine.js +2 -2
- package/dist/runner.js +2 -2
- package/package.json +1 -1
- package/runtime/lib/verify.py +119 -19
- package/runtime/tests/recon_verify_smoke.py +208 -4
- package/runtime/tests/trust_boundary_regression.py +18 -0
|
@@ -505,6 +505,25 @@ function visualDeltaShipGateReason(state = {}) {
|
|
|
505
505
|
if (reason) return `visual_delta.status=${status} blocks ready_to_ship for visual/UI proof: ${reason}`;
|
|
506
506
|
return `visual_delta.status=${status} blocks ready_to_ship for visual/UI proof`;
|
|
507
507
|
}
|
|
508
|
+
function proofAssessmentHardBlockersForState(state = {}) {
|
|
509
|
+
const request = objectValue(state?.proof_assessment_request);
|
|
510
|
+
const blockers = [];
|
|
511
|
+
const add = (value) => {
|
|
512
|
+
if (typeof value !== "string") return;
|
|
513
|
+
const trimmed = value.trim();
|
|
514
|
+
if (trimmed && !blockers.includes(trimmed)) blockers.push(trimmed);
|
|
515
|
+
};
|
|
516
|
+
if (Array.isArray(request.hard_blockers)) {
|
|
517
|
+
for (const blocker of request.hard_blockers) add(blocker);
|
|
518
|
+
}
|
|
519
|
+
add(state?.structured_interaction_capture_failure_summary);
|
|
520
|
+
add(state?.structured_interaction_failure_summary);
|
|
521
|
+
const mergeRecommendation = String(state?.merge_recommendation || "").trim();
|
|
522
|
+
if (mergeRecommendation === "do-not-merge" && blockers.length) {
|
|
523
|
+
add("merge_recommendation=do-not-merge because the proof bundle contains hard blockers.");
|
|
524
|
+
}
|
|
525
|
+
return blockers;
|
|
526
|
+
}
|
|
508
527
|
function visualDeltaEvidenceIssueCode(state = {}, blocker = "") {
|
|
509
528
|
const visualDelta = visualDeltaForState(state || {});
|
|
510
529
|
const status = String(visualDelta.status || "").trim();
|
|
@@ -539,6 +558,7 @@ function validateShipGate(state = {}) {
|
|
|
539
558
|
const visualDelta = visualDeltaForState(state);
|
|
540
559
|
const visualDeltaRequired = visualDeltaRequiredForState(state);
|
|
541
560
|
const visualDeltaBlocker = visualDeltaShipGateReason(state);
|
|
561
|
+
const hardBlockers = proofAssessmentHardBlockersForState(state);
|
|
542
562
|
const reasons = [];
|
|
543
563
|
if (!["before", "prod", "both"].includes(reference)) {
|
|
544
564
|
reasons.push(`reference must be before, prod, or both; got ${reference}`);
|
|
@@ -570,6 +590,9 @@ function validateShipGate(state = {}) {
|
|
|
570
590
|
if (visualDeltaBlocker) {
|
|
571
591
|
reasons.push(visualDeltaBlocker);
|
|
572
592
|
}
|
|
593
|
+
for (const blocker of hardBlockers) {
|
|
594
|
+
reasons.push(`proof hard blocker prevents ready_to_ship: ${blocker}`);
|
|
595
|
+
}
|
|
573
596
|
return {
|
|
574
597
|
ok: reasons.length === 0,
|
|
575
598
|
reasons,
|
|
@@ -586,7 +609,8 @@ function validateShipGate(state = {}) {
|
|
|
586
609
|
proof_assessment_source: proofAssessment.source,
|
|
587
610
|
visual_delta_required: visualDeltaRequired,
|
|
588
611
|
visual_delta_status: typeof visualDelta.status === "string" ? visualDelta.status : null,
|
|
589
|
-
visual_delta_passed: typeof visualDelta.passed === "boolean" ? visualDelta.passed : null
|
|
612
|
+
visual_delta_passed: typeof visualDelta.passed === "boolean" ? visualDelta.passed : null,
|
|
613
|
+
hard_blockers: hardBlockers
|
|
590
614
|
}
|
|
591
615
|
};
|
|
592
616
|
}
|
|
@@ -700,6 +724,10 @@ var CHECKPOINT_CONTRACT_SPECS = {
|
|
|
700
724
|
}],
|
|
701
725
|
required_state: ["verify_decision_request"]
|
|
702
726
|
},
|
|
727
|
+
verify_capture_blocked: {
|
|
728
|
+
purpose: "Verify capture produced conclusive failed browser evidence and should stop instead of retrying proof authoring.",
|
|
729
|
+
required_state: ["verify_decision_request"]
|
|
730
|
+
},
|
|
703
731
|
verify_supervisor_judgment: {
|
|
704
732
|
purpose: "Supervising agent judges whether captured evidence proves the change is ready to ship.",
|
|
705
733
|
accepted_inputs: [{
|
|
@@ -1284,14 +1312,18 @@ function verifyAssessment(state) {
|
|
|
1284
1312
|
};
|
|
1285
1313
|
}
|
|
1286
1314
|
if (state?.verify_status === "capture_incomplete") {
|
|
1315
|
+
const captureQuality = verifyDecision?.capture_quality || {};
|
|
1316
|
+
const terminalBlocker = captureQuality?.terminal_blocker === true || captureQuality?.blocking === true;
|
|
1317
|
+
const recommendedStage = terminalBlocker ? null : verifyDecision?.continue_with_stage || verifyDecision?.recommended_stage || "author";
|
|
1318
|
+
const continueWithStage = terminalBlocker ? null : verifyDecision?.continue_with_stage || verifyDecision?.recommended_stage || "author";
|
|
1287
1319
|
return {
|
|
1288
|
-
decision:
|
|
1320
|
+
decision: captureQuality?.decision || "revise_capture",
|
|
1289
1321
|
summary: verifyDecision?.summary || "Verify needs another internal capture iteration before the evidence can be judged.",
|
|
1290
|
-
recommendedStage
|
|
1291
|
-
continueWithStage
|
|
1322
|
+
recommendedStage,
|
|
1323
|
+
continueWithStage,
|
|
1292
1324
|
escalationTarget: "agent",
|
|
1293
|
-
reasons: Array.isArray(
|
|
1294
|
-
raw:
|
|
1325
|
+
reasons: Array.isArray(captureQuality?.reasons) ? captureQuality.reasons : [],
|
|
1326
|
+
raw: captureQuality || verifyDecision,
|
|
1295
1327
|
source: "workflow_capture"
|
|
1296
1328
|
};
|
|
1297
1329
|
}
|
|
@@ -2511,7 +2543,9 @@ ${implementRes.stderr || ""}`;
|
|
|
2511
2543
|
convergenceSignals
|
|
2512
2544
|
};
|
|
2513
2545
|
if (verifyStatus !== "evidence_captured") {
|
|
2514
|
-
|
|
2546
|
+
const captureQuality = verifyDecisionRequest?.capture_quality || {};
|
|
2547
|
+
const captureTerminalBlocker = captureQuality?.terminal_blocker === true || captureQuality?.blocking === true;
|
|
2548
|
+
if (!captureTerminalBlocker && (verifyContinueWithStage || verifyRecommendedStage || "author") === "author") {
|
|
2515
2549
|
updateState(config.statePath, (currentState) => {
|
|
2516
2550
|
currentState.author_status = "needs_authoring";
|
|
2517
2551
|
currentState.proof_plan_status = "needs_authoring";
|
|
@@ -2519,7 +2553,7 @@ ${implementRes.stderr || ""}`;
|
|
|
2519
2553
|
});
|
|
2520
2554
|
state = readState(config.statePath);
|
|
2521
2555
|
}
|
|
2522
|
-
const checkpointName = "verify_capture_retry";
|
|
2556
|
+
const checkpointName = captureTerminalBlocker ? "verify_capture_blocked" : "verify_capture_retry";
|
|
2523
2557
|
const summary = stringValue(proofAssessment.summary) || "Verify ran, but the proof packet still needs internal capture-plan work before it should ship.";
|
|
2524
2558
|
recordAttempt("verify", "checkpoint", summary, {
|
|
2525
2559
|
autoApproved: verifyRes.autoApproved || false,
|
|
@@ -2532,11 +2566,11 @@ ${implementRes.stderr || ""}`;
|
|
|
2532
2566
|
summary,
|
|
2533
2567
|
{
|
|
2534
2568
|
ok: true,
|
|
2535
|
-
nextActions: ["inspect_after_capture", "continue_internal_loop_with_checkpoint", "return_to_recon_if_baseline_is_wrong"],
|
|
2569
|
+
nextActions: captureTerminalBlocker ? ["inspect_after_capture", "report_specific_browser_evidence_blocker", "start_a_new_run_after_the_product_or_script_is_fixed"] : ["inspect_after_capture", "continue_internal_loop_with_checkpoint", "return_to_recon_if_baseline_is_wrong"],
|
|
2536
2570
|
advanceOptions: verifyLoopAdvanceOptions,
|
|
2537
|
-
recommendedAdvanceStage: verifyRecommendedStage || "author",
|
|
2538
|
-
continueWithStage: verifyContinueWithStage || "author",
|
|
2539
|
-
blocking:
|
|
2571
|
+
recommendedAdvanceStage: captureTerminalBlocker ? null : verifyRecommendedStage || "author",
|
|
2572
|
+
continueWithStage: captureTerminalBlocker ? null : verifyContinueWithStage || "author",
|
|
2573
|
+
blocking: captureTerminalBlocker,
|
|
2540
2574
|
details: verifyDetails,
|
|
2541
2575
|
verifyStatus,
|
|
2542
2576
|
verifySummary,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import './proof-run-core-
|
|
2
|
-
export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-
|
|
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-
|
|
2
|
-
export { R as RiddleProofEngine, c as createRiddleProofEngine, e as executeWorkflow } from './proof-run-engine-
|
|
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/dist/proof-run-engine.js
CHANGED
package/dist/runner.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runRiddleProof
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NGX4SUQN.js";
|
|
4
4
|
import "./chunk-YZUVEJ5B.js";
|
|
5
5
|
import "./chunk-FMOYUYH2.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-7GZY5PLT.js";
|
|
7
7
|
import "./chunk-4FOHZ7JG.js";
|
|
8
8
|
import "./chunk-VY4Y5U57.js";
|
|
9
9
|
import "./chunk-MLKGABMK.js";
|
package/package.json
CHANGED
package/runtime/lib/verify.py
CHANGED
|
@@ -2061,7 +2061,24 @@ EXPLICIT_TERMINAL_PATH_KEYS = (
|
|
|
2061
2061
|
'final_url', 'finalUrl',
|
|
2062
2062
|
'final_route', 'finalRoute',
|
|
2063
2063
|
)
|
|
2064
|
-
|
|
2064
|
+
FULL_LOCATION_PATH_KEYS = (
|
|
2065
|
+
'url', 'href',
|
|
2066
|
+
'hrefNormalized', 'href_normalized',
|
|
2067
|
+
'terminalUrl', 'terminal_url',
|
|
2068
|
+
'afterUrl', 'after_url',
|
|
2069
|
+
'finalUrl', 'final_url',
|
|
2070
|
+
'currentUrl', 'current_url',
|
|
2071
|
+
'pathWithSearchAndHash', 'path_with_search_and_hash',
|
|
2072
|
+
'fullPath', 'full_path',
|
|
2073
|
+
)
|
|
2074
|
+
PARTIAL_LOCATION_PATH_KEYS = (
|
|
2075
|
+
'route',
|
|
2076
|
+
'path',
|
|
2077
|
+
'pathname',
|
|
2078
|
+
'normalizedPath', 'normalized_path',
|
|
2079
|
+
'rawPath', 'raw_path',
|
|
2080
|
+
)
|
|
2081
|
+
LOCATION_PATH_KEYS = FULL_LOCATION_PATH_KEYS + PARTIAL_LOCATION_PATH_KEYS
|
|
2065
2082
|
AFTER_STATE_KEYS = (
|
|
2066
2083
|
'after', 'after_state', 'afterState',
|
|
2067
2084
|
'expected_after', 'expectedAfter',
|
|
@@ -2158,18 +2175,29 @@ def text_path_candidate(value):
|
|
|
2158
2175
|
return path_candidate(raw)
|
|
2159
2176
|
|
|
2160
2177
|
|
|
2178
|
+
def text_route_candidate(value):
|
|
2179
|
+
candidate = text_path_candidate(value)
|
|
2180
|
+
if not candidate:
|
|
2181
|
+
return ''
|
|
2182
|
+
parsed = urlparse(candidate)
|
|
2183
|
+
first_segment = next((part for part in (parsed.path or '').split('/') if part), '')
|
|
2184
|
+
if first_segment and first_segment[:1].isupper():
|
|
2185
|
+
return ''
|
|
2186
|
+
return candidate
|
|
2187
|
+
|
|
2188
|
+
|
|
2161
2189
|
def terminal_path_from_text(value):
|
|
2162
2190
|
if not isinstance(value, str):
|
|
2163
2191
|
return ''
|
|
2164
2192
|
for match in re.findall(r"""['"`](/[^'"`\s]+[?#][^'"`\s]*)['"`]""", value):
|
|
2165
|
-
candidate =
|
|
2193
|
+
candidate = text_route_candidate(match)
|
|
2166
2194
|
if candidate:
|
|
2167
2195
|
return candidate
|
|
2168
2196
|
context_pattern = re.compile(
|
|
2169
|
-
r"""(?is)\b(?:expected\s+(?:terminal|after|final)|terminal|after|final)\
|
|
2197
|
+
r"""(?is)\b(?:expected\s+(?:terminal|after|final)(?:\s+(?:route|path|url))?|terminal(?:\s+(?:route|path|url))?|after(?:\s+(?:route|path|url))?|final(?:\s+(?:route|path|url))?)\s*(?:should\s+(?:be|equal|match)|must\s+(?:be|equal|match)|is|as|to|=|:)?\s*['"`]?(/[^'"`\s,;)]*)"""
|
|
2170
2198
|
)
|
|
2171
2199
|
for match in context_pattern.findall(value):
|
|
2172
|
-
candidate =
|
|
2200
|
+
candidate = text_route_candidate(match)
|
|
2173
2201
|
if candidate:
|
|
2174
2202
|
return candidate
|
|
2175
2203
|
return ''
|
|
@@ -2372,6 +2400,25 @@ def failed_interaction_evidence_summary(proof_evidence):
|
|
|
2372
2400
|
return summary
|
|
2373
2401
|
|
|
2374
2402
|
|
|
2403
|
+
def interaction_capture_failure_evidence_summary(proof_evidence):
|
|
2404
|
+
for record in proof_evidence_records_deep(proof_evidence):
|
|
2405
|
+
if not isinstance(record, dict):
|
|
2406
|
+
continue
|
|
2407
|
+
version = str(record.get('version') or '').strip()
|
|
2408
|
+
source = str(record.get('source') or '').strip()
|
|
2409
|
+
if version != 'riddle-proof.interaction.capture-failure.v1' and source != 'verify_capture_failure':
|
|
2410
|
+
continue
|
|
2411
|
+
summary = str(record.get('evidence_summary') or '').strip() or 'Interaction capture failed before usable authored proof evidence was emitted.'
|
|
2412
|
+
failures = collect_interaction_failed_assertions(record)
|
|
2413
|
+
if failures:
|
|
2414
|
+
summary += ' Failed checks: ' + ', '.join(failures[:8]) + '.'
|
|
2415
|
+
error = str(record.get('capture_error') or record.get('error') or '').strip()
|
|
2416
|
+
if error:
|
|
2417
|
+
summary += ' Capture script error: ' + error[:300]
|
|
2418
|
+
return summary
|
|
2419
|
+
return ''
|
|
2420
|
+
|
|
2421
|
+
|
|
2375
2422
|
def interaction_terminal_path_from_evidence(proof_evidence):
|
|
2376
2423
|
for record in proof_evidence_records(proof_evidence):
|
|
2377
2424
|
candidate = terminal_path_from_record(record)
|
|
@@ -2389,6 +2436,13 @@ def interaction_terminal_path_from_evidence(proof_evidence):
|
|
|
2389
2436
|
|
|
2390
2437
|
|
|
2391
2438
|
def interaction_terminal_path_from_state(state):
|
|
2439
|
+
for key in (
|
|
2440
|
+
'expected_terminal_path',
|
|
2441
|
+
'expected_after_path',
|
|
2442
|
+
):
|
|
2443
|
+
candidate = path_candidate(state.get(key))
|
|
2444
|
+
if candidate:
|
|
2445
|
+
return candidate, key
|
|
2392
2446
|
for key in (
|
|
2393
2447
|
'interaction_contract',
|
|
2394
2448
|
'proof_contract',
|
|
@@ -2401,19 +2455,32 @@ def interaction_terminal_path_from_state(state):
|
|
|
2401
2455
|
if candidate:
|
|
2402
2456
|
return candidate, key
|
|
2403
2457
|
for key in (
|
|
2404
|
-
'expected_terminal_path',
|
|
2405
|
-
'expected_after_path',
|
|
2406
2458
|
'capture_script',
|
|
2407
2459
|
'proof_plan',
|
|
2408
|
-
'success_criteria',
|
|
2409
|
-
'change_request',
|
|
2410
2460
|
):
|
|
2411
|
-
candidate =
|
|
2461
|
+
candidate = terminal_path_from_text(state.get(key))
|
|
2412
2462
|
if candidate:
|
|
2413
2463
|
return candidate, key
|
|
2414
2464
|
return '', ''
|
|
2415
2465
|
|
|
2416
2466
|
|
|
2467
|
+
def proof_evidence_should_override_state_terminal_path(state_candidate, evidence_candidate, proof_evidence):
|
|
2468
|
+
if not evidence_candidate:
|
|
2469
|
+
return False
|
|
2470
|
+
if not state_candidate:
|
|
2471
|
+
return True
|
|
2472
|
+
if route_matches_expected(state_candidate, evidence_candidate):
|
|
2473
|
+
return False
|
|
2474
|
+
if interaction_assertions_pass(proof_evidence):
|
|
2475
|
+
return True
|
|
2476
|
+
for record in proof_evidence_records_deep(proof_evidence):
|
|
2477
|
+
if interaction_assertions_pass(record):
|
|
2478
|
+
return True
|
|
2479
|
+
if explicit_route_match_flag(record) is True:
|
|
2480
|
+
return True
|
|
2481
|
+
return False
|
|
2482
|
+
|
|
2483
|
+
|
|
2417
2484
|
def expected_path_for_verify(state, start_path, proof_evidence):
|
|
2418
2485
|
mode = normalized_verification_mode(state.get('verification_mode'))
|
|
2419
2486
|
normalized_start = normalize_observed_path(start_path) or '/'
|
|
@@ -2431,9 +2498,14 @@ def expected_path_for_verify(state, start_path, proof_evidence):
|
|
|
2431
2498
|
'expected_query': start_parts['query'],
|
|
2432
2499
|
'expected_hash': start_parts['hash'],
|
|
2433
2500
|
}
|
|
2434
|
-
|
|
2501
|
+
state_candidate, state_source = interaction_terminal_path_from_state(state)
|
|
2502
|
+
evidence_candidate, evidence_source = interaction_terminal_path_from_evidence(proof_evidence)
|
|
2503
|
+
if proof_evidence_should_override_state_terminal_path(state_candidate, evidence_candidate, proof_evidence):
|
|
2504
|
+
candidate, source = evidence_candidate, evidence_source
|
|
2505
|
+
else:
|
|
2506
|
+
candidate, source = state_candidate, state_source
|
|
2435
2507
|
if not candidate:
|
|
2436
|
-
candidate, source =
|
|
2508
|
+
candidate, source = evidence_candidate, evidence_source
|
|
2437
2509
|
expected = candidate or normalized_start
|
|
2438
2510
|
expected_parts = route_parts(expected)
|
|
2439
2511
|
return expected, {
|
|
@@ -2824,10 +2896,17 @@ def build_capture_retry_decision(after_observation, required_baseline_present, p
|
|
|
2824
2896
|
|
|
2825
2897
|
if proof_evidence_blocker:
|
|
2826
2898
|
reasons.append(proof_evidence_blocker)
|
|
2827
|
-
|
|
2899
|
+
interaction_capture_blocker = (
|
|
2900
|
+
proof_evidence_blocker.startswith('Interaction capture ')
|
|
2901
|
+
or 'Interaction capture failed before usable authored proof evidence was emitted' in proof_evidence_blocker
|
|
2902
|
+
or 'Interaction capture reached a different terminal route' in proof_evidence_blocker
|
|
2903
|
+
)
|
|
2904
|
+
decision = 'failed_interaction_capture' if interaction_capture_blocker else 'missing_proof_evidence'
|
|
2828
2905
|
if 'proof_evidence_present=false' in proof_evidence_blocker:
|
|
2829
2906
|
decision = 'failed_proof_evidence'
|
|
2830
2907
|
reasons.append('The capture reached usable page context, but the proof evidence explicitly failed its own required audio gate.')
|
|
2908
|
+
elif interaction_capture_blocker:
|
|
2909
|
+
reasons.append('The capture produced conclusive structured interaction-failure evidence, so this run should block with that specific browser evidence instead of re-authoring in a loop.')
|
|
2831
2910
|
else:
|
|
2832
2911
|
reasons.append('The capture reached usable page context, but the proof script did not emit the structured evidence required for this verification mode.')
|
|
2833
2912
|
if route_mismatch:
|
|
@@ -2838,7 +2917,10 @@ def build_capture_retry_decision(after_observation, required_baseline_present, p
|
|
|
2838
2917
|
(route_mismatch.get('observed_after_path') or '(unknown)') +
|
|
2839
2918
|
'.'
|
|
2840
2919
|
)
|
|
2841
|
-
|
|
2920
|
+
if interaction_capture_blocker:
|
|
2921
|
+
reasons.append('Do not ask the authoring loop to infer a new route; the captured browser evidence is the terminal blocker.')
|
|
2922
|
+
else:
|
|
2923
|
+
reasons.append('Return to author so the capture script can expose passing proof evidence before verify asks for a supervising-agent judgment.')
|
|
2842
2924
|
summary = proof_evidence_blocker
|
|
2843
2925
|
if route_mismatch:
|
|
2844
2926
|
summary += (
|
|
@@ -2854,8 +2936,10 @@ def build_capture_retry_decision(after_observation, required_baseline_present, p
|
|
|
2854
2936
|
return {
|
|
2855
2937
|
'decision': decision,
|
|
2856
2938
|
'summary': summary,
|
|
2857
|
-
'recommended_stage': 'author',
|
|
2858
|
-
'continue_with_stage': 'author',
|
|
2939
|
+
'recommended_stage': None if interaction_capture_blocker else 'author',
|
|
2940
|
+
'continue_with_stage': None if interaction_capture_blocker else 'author',
|
|
2941
|
+
'blocking': bool(interaction_capture_blocker),
|
|
2942
|
+
'terminal_blocker': bool(interaction_capture_blocker),
|
|
2859
2943
|
'reasons': reasons,
|
|
2860
2944
|
'mismatch': route_mismatch,
|
|
2861
2945
|
}
|
|
@@ -3631,12 +3715,17 @@ if proof_evidence_required_for_mode(s.get('verification_mode')):
|
|
|
3631
3715
|
summary_lines.append('Structured proof evidence gate: ' + proof_evidence_blocker)
|
|
3632
3716
|
|
|
3633
3717
|
structured_interaction_failure_summary = ''
|
|
3718
|
+
structured_interaction_capture_failure_summary = ''
|
|
3634
3719
|
proof_evidence = evidence_bundle.get('proof_evidence')
|
|
3635
3720
|
if verification_mode in INTERACTION_MODES and proof_evidence is not None:
|
|
3636
3721
|
structured_interaction_failure_summary = failed_interaction_evidence_summary(proof_evidence)
|
|
3722
|
+
structured_interaction_capture_failure_summary = interaction_capture_failure_evidence_summary(proof_evidence)
|
|
3637
3723
|
if structured_interaction_failure_summary:
|
|
3638
3724
|
summary_lines.append('Structured interaction evidence gate: ' + structured_interaction_failure_summary)
|
|
3725
|
+
if structured_interaction_capture_failure_summary:
|
|
3726
|
+
summary_lines.append('Structured interaction capture blocker: ' + structured_interaction_capture_failure_summary)
|
|
3639
3727
|
s['structured_interaction_failure_summary'] = structured_interaction_failure_summary
|
|
3728
|
+
s['structured_interaction_capture_failure_summary'] = structured_interaction_capture_failure_summary
|
|
3640
3729
|
|
|
3641
3730
|
visual_delta_recovery = build_visual_delta_recovery_decision(
|
|
3642
3731
|
s.get('verification_mode'),
|
|
@@ -3648,6 +3737,7 @@ if visual_delta_recovery:
|
|
|
3648
3737
|
|
|
3649
3738
|
has_judgable_failed_interaction_evidence = (
|
|
3650
3739
|
bool(structured_interaction_failure_summary)
|
|
3740
|
+
and not structured_interaction_capture_failure_summary
|
|
3651
3741
|
and required_baseline_present
|
|
3652
3742
|
and not proof_evidence_blocker
|
|
3653
3743
|
and not visual_delta_recovery
|
|
@@ -3656,6 +3746,7 @@ has_good_evidence = (
|
|
|
3656
3746
|
required_baseline_present
|
|
3657
3747
|
and (after_observation.get('valid') or has_judgable_failed_interaction_evidence)
|
|
3658
3748
|
and not proof_evidence_blocker
|
|
3749
|
+
and not structured_interaction_capture_failure_summary
|
|
3659
3750
|
and not visual_delta_recovery
|
|
3660
3751
|
)
|
|
3661
3752
|
|
|
@@ -3712,7 +3803,12 @@ if has_good_evidence:
|
|
|
3712
3803
|
summary_lines.append('Proof assessment: awaiting supervising agent judgment')
|
|
3713
3804
|
summary_lines.append('Proof next stage: supervising agent decides after reviewing the evidence packet')
|
|
3714
3805
|
else:
|
|
3715
|
-
capture_retry = build_capture_retry_decision(
|
|
3806
|
+
capture_retry = build_capture_retry_decision(
|
|
3807
|
+
after_observation,
|
|
3808
|
+
required_baseline_present,
|
|
3809
|
+
proof_evidence_blocker or structured_interaction_capture_failure_summary,
|
|
3810
|
+
s.get('route_expectation') or {},
|
|
3811
|
+
)
|
|
3716
3812
|
if visual_delta_recovery:
|
|
3717
3813
|
observation_reason = str(after_observation.get('reason') or '')
|
|
3718
3814
|
observation_details = after_observation.get('details') if isinstance(after_observation.get('details'), dict) else {}
|
|
@@ -3721,6 +3817,7 @@ else:
|
|
|
3721
3817
|
or 'console/runtime errors' in observation_reason
|
|
3722
3818
|
or (observation_details.get('capture_error_messages') or [])
|
|
3723
3819
|
or proof_evidence_blocker
|
|
3820
|
+
or structured_interaction_capture_failure_summary
|
|
3724
3821
|
)
|
|
3725
3822
|
if has_primary_capture_failure:
|
|
3726
3823
|
capture_retry['visual_delta_recovery'] = visual_delta_recovery
|
|
@@ -3728,6 +3825,9 @@ else:
|
|
|
3728
3825
|
else:
|
|
3729
3826
|
capture_retry = visual_delta_recovery
|
|
3730
3827
|
next_stage_options = ['author', 'verify', 'recon'] if no_implementation_mode else ['author', 'verify', 'implement', 'recon']
|
|
3828
|
+
capture_terminal_blocker = bool(capture_retry.get('terminal_blocker') or capture_retry.get('blocking'))
|
|
3829
|
+
recommended_stage = None if capture_terminal_blocker else (capture_retry.get('recommended_stage') or 'author')
|
|
3830
|
+
continue_with_stage = None if capture_terminal_blocker else (capture_retry.get('continue_with_stage') or 'author')
|
|
3731
3831
|
s['verify_status'] = 'capture_incomplete'
|
|
3732
3832
|
s['merge_recommendation'] = 'do-not-merge'
|
|
3733
3833
|
s['proof_assessment'] = {}
|
|
@@ -3742,8 +3842,8 @@ else:
|
|
|
3742
3842
|
'latest_observation': after_observation,
|
|
3743
3843
|
'capture_quality': capture_retry,
|
|
3744
3844
|
'next_stage_options': next_stage_options,
|
|
3745
|
-
'recommended_stage':
|
|
3746
|
-
'continue_with_stage':
|
|
3845
|
+
'recommended_stage': recommended_stage,
|
|
3846
|
+
'continue_with_stage': continue_with_stage,
|
|
3747
3847
|
'fields_agent_may_update': ['capture_script', 'server_path', 'wait_for_selector', 'proof_plan'],
|
|
3748
3848
|
'instructions': [
|
|
3749
3849
|
'The after-proof evidence packet is incomplete, so use the recommended stage before proof review.',
|
|
@@ -3753,7 +3853,7 @@ else:
|
|
|
3753
3853
|
],
|
|
3754
3854
|
}
|
|
3755
3855
|
summary_lines.append('Proof assessment: not yet possible because the after capture is still incomplete')
|
|
3756
|
-
summary_lines.append('Proof next stage: ' + str(
|
|
3856
|
+
summary_lines.append('Proof next stage: blocked' if capture_terminal_blocker else 'Proof next stage: ' + str(recommended_stage or 'author'))
|
|
3757
3857
|
|
|
3758
3858
|
s['verify_summary'] = '\n'.join(summary_lines)
|
|
3759
3859
|
s['proof_summary'] = s['verify_summary']
|