@riddledc/riddle-proof 0.8.29 → 0.8.31

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.
Files changed (46) hide show
  1. package/dist/advanced/engine-harness.cjs +188 -11
  2. package/dist/advanced/engine-harness.js +2 -2
  3. package/dist/advanced/index.cjs +188 -11
  4. package/dist/advanced/index.d.cts +2 -2
  5. package/dist/advanced/index.d.ts +2 -2
  6. package/dist/advanced/index.js +4 -4
  7. package/dist/advanced/proof-run-core.cjs +3 -1
  8. package/dist/advanced/proof-run-core.d.cts +1 -1
  9. package/dist/advanced/proof-run-core.d.ts +1 -1
  10. package/dist/advanced/proof-run-core.js +1 -1
  11. package/dist/advanced/proof-run-engine.cjs +136 -2
  12. package/dist/advanced/proof-run-engine.d.cts +2 -2
  13. package/dist/advanced/proof-run-engine.d.ts +2 -2
  14. package/dist/advanced/proof-run-engine.js +2 -2
  15. package/dist/advanced/runner.js +2 -2
  16. package/dist/{chunk-3OTO7IDH.js → chunk-C2NHHBFV.js} +1 -1
  17. package/dist/{chunk-YC77HZVF.js → chunk-IOI6QR3B.js} +134 -2
  18. package/dist/{chunk-FJPZZ4JO.js → chunk-U73JPBZW.js} +1 -1
  19. package/dist/{chunk-K6HZUSHH.js → chunk-X7SQTCIQ.js} +3 -1
  20. package/dist/{chunk-AM3K5FPW.js → chunk-ZREWMTFA.js} +53 -10
  21. package/dist/cli/index.js +3 -3
  22. package/dist/cli.cjs +188 -11
  23. package/dist/cli.js +3 -3
  24. package/dist/engine-harness.cjs +188 -11
  25. package/dist/engine-harness.js +2 -2
  26. package/dist/index.cjs +188 -11
  27. package/dist/index.js +3 -3
  28. package/dist/{proof-run-core-C8FDUhle.d.cts → proof-run-core-B1GeqkR8.d.cts} +2 -0
  29. package/dist/{proof-run-core-C8FDUhle.d.ts → proof-run-core-B1GeqkR8.d.ts} +2 -0
  30. package/dist/proof-run-core.cjs +3 -1
  31. package/dist/proof-run-core.d.cts +1 -1
  32. package/dist/proof-run-core.d.ts +1 -1
  33. package/dist/proof-run-core.js +1 -1
  34. package/dist/{proof-run-engine-D80hVFMf.d.cts → proof-run-engine-4dM37pEx.d.cts} +1 -1
  35. package/dist/{proof-run-engine-By7oLsF-.d.ts → proof-run-engine-BqaeqAze.d.ts} +1 -1
  36. package/dist/proof-run-engine.cjs +136 -2
  37. package/dist/proof-run-engine.d.cts +2 -2
  38. package/dist/proof-run-engine.d.ts +2 -2
  39. package/dist/proof-run-engine.js +2 -2
  40. package/dist/runner.js +2 -2
  41. package/lib/workspace-core.mjs +62 -7
  42. package/package.json +2 -2
  43. package/runtime/lib/riddle_core_call.mjs +662 -40
  44. package/runtime/lib/util.py +117 -40
  45. package/runtime/lib/verify.py +17 -4
  46. package/runtime/tests/recon_verify_smoke.py +137 -1
package/dist/cli.cjs CHANGED
@@ -157,6 +157,7 @@ function buildSetupArgs(params, config) {
157
157
  discord_thread_id: params.discord_thread_id || "",
158
158
  discord_message_id: params.discord_message_id || "",
159
159
  discord_source_url: params.discord_source_url || "",
160
+ ship_mode: params.ship_mode || "",
160
161
  leave_draft: params.leave_draft ? "true" : ""
161
162
  };
162
163
  }
@@ -746,7 +747,8 @@ function mergeStateFromParams(statePath, params) {
746
747
  "auth_headers_json",
747
748
  "proof_plan",
748
749
  "implementation_notes",
749
- "implementation_mode"
750
+ "implementation_mode",
751
+ "ship_mode"
750
752
  ];
751
753
  for (const field of stringFields) {
752
754
  if (params[field] !== void 0) {
@@ -1365,6 +1367,72 @@ function updateState(statePath, mutate) {
1365
1367
  function nowIso() {
1366
1368
  return (/* @__PURE__ */ new Date()).toISOString();
1367
1369
  }
1370
+ function missingExecutableError(error) {
1371
+ return error?.code === "ENOENT" || /\bENOENT\b/.test(String(error?.message || error || ""));
1372
+ }
1373
+ function pythonScriptsForBundledStage(step) {
1374
+ if (step === "setup") return ["preflight.py", "setup.py"];
1375
+ if (step === "recon") return ["recon.py"];
1376
+ if (step === "author") return ["author.py"];
1377
+ if (step === "implement") return ["implement.py"];
1378
+ if (step === "verify") return ["verify.py"];
1379
+ if (step === "ship") return ["ship.py"];
1380
+ return [];
1381
+ }
1382
+ function runBundledPythonStage(step, runtimeDir, env) {
1383
+ const scripts = pythonScriptsForBundledStage(step);
1384
+ if (!scripts.length) {
1385
+ return {
1386
+ ok: false,
1387
+ error: `No bundled Python fallback is defined for ${step}.`
1388
+ };
1389
+ }
1390
+ const pythonCommand = process.env.RIDDLE_PROOF_PYTHON_COMMAND || "python3";
1391
+ const libDir = import_node_path2.default.join(runtimeDir, "lib");
1392
+ const stdout = [];
1393
+ const stderr = [];
1394
+ const executed = [];
1395
+ try {
1396
+ for (const script of scripts) {
1397
+ const scriptPath = import_node_path2.default.join(libDir, script);
1398
+ if (!(0, import_node_fs2.existsSync)(scriptPath)) {
1399
+ return {
1400
+ ok: false,
1401
+ stdout: stdout.join(""),
1402
+ stderr: stderr.join(""),
1403
+ error: `Riddle Proof bundled Python fallback missing ${scriptPath}`
1404
+ };
1405
+ }
1406
+ executed.push(script);
1407
+ stdout.push((0, import_node_child_process.execFileSync)(pythonCommand, [scriptPath], {
1408
+ encoding: "utf-8",
1409
+ env,
1410
+ stdio: ["ignore", "pipe", "pipe"]
1411
+ }));
1412
+ }
1413
+ } catch (error) {
1414
+ return {
1415
+ ok: false,
1416
+ stdout: `${stdout.join("")}${String(error?.stdout || "")}`,
1417
+ stderr: `${stderr.join("")}${String(error?.stderr || "")}`,
1418
+ error: error?.message || String(error),
1419
+ raw: {
1420
+ runner: "bundled_python_fallback",
1421
+ scripts: executed
1422
+ }
1423
+ };
1424
+ }
1425
+ return {
1426
+ ok: true,
1427
+ stdout: stdout.join(""),
1428
+ stderr: stderr.join(""),
1429
+ raw: {
1430
+ ok: true,
1431
+ runner: "bundled_python_fallback",
1432
+ scripts: executed
1433
+ }
1434
+ };
1435
+ }
1368
1436
  function appendRuntimeEventToState(state, event) {
1369
1437
  const events = Array.isArray(state.runtime_events) ? state.runtime_events : [];
1370
1438
  state.runtime_events = [...events, event].slice(-RUNTIME_EVENT_LIMIT);
@@ -1931,6 +1999,17 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1931
1999
  })
1932
2000
  );
1933
2001
  } catch (error) {
2002
+ if (!process.env.RIDDLE_PROOF_LOBSTER_SCRIPT && missingExecutableError(error)) {
2003
+ const fallback = runBundledPythonStage(step, config.riddleProofDir, env);
2004
+ return finishRuntimeStep(config.statePath, action, {
2005
+ ok: fallback.ok,
2006
+ step,
2007
+ raw: fallback.raw,
2008
+ stdout: fallback.stdout,
2009
+ stderr: fallback.stderr,
2010
+ error: fallback.error
2011
+ }, timer);
2012
+ }
1934
2013
  return finishRuntimeStep(config.statePath, action, {
1935
2014
  ok: false,
1936
2015
  step,
@@ -2684,6 +2763,60 @@ ${implementRes.stderr || ""}`;
2684
2763
  verifyRes = runOne("verify");
2685
2764
  executed.push(executedStep(verifyRes));
2686
2765
  if (!verifyRes.ok || verifyRes.haltedForApproval) {
2766
+ const failedVerifyState = readState(config.statePath);
2767
+ const failedVerifyStatus = failedVerifyState?.verify_status || "";
2768
+ if (!verifyRes.haltedForApproval && (failedVerifyStatus === "capture_incomplete" || failedVerifyStatus === "capture_error")) {
2769
+ const verifyDecisionRequest2 = failedVerifyState?.verify_decision_request || null;
2770
+ const captureQuality = verifyDecisionRequest2?.capture_quality || {};
2771
+ const conclusiveVerifyBlockers2 = proofAssessmentHardBlockersForState({
2772
+ ...failedVerifyState,
2773
+ structured_interaction_capture_failure_summary: stringValue(verifyDecisionRequest2?.structured_interaction_capture_failure_summary) || stringValue(failedVerifyState?.structured_interaction_capture_failure_summary) || void 0,
2774
+ structured_interaction_failure_summary: stringValue(verifyDecisionRequest2?.structured_interaction_failure_summary) || stringValue(failedVerifyState?.structured_interaction_failure_summary) || void 0
2775
+ });
2776
+ const structuredInteractionFailureSummary2 = stringValue(verifyDecisionRequest2?.structured_interaction_capture_failure_summary) || stringValue(verifyDecisionRequest2?.structured_interaction_failure_summary) || stringValue(failedVerifyState?.structured_interaction_capture_failure_summary) || stringValue(failedVerifyState?.structured_interaction_failure_summary) || stringValue(conclusiveVerifyBlockers2[0]);
2777
+ const captureTerminalBlocker = failedVerifyStatus === "capture_error" || conclusiveVerifyBlockers2.length > 0 || Boolean(structuredInteractionFailureSummary2) || captureQuality?.terminal_blocker === true || captureQuality?.blocking === true;
2778
+ const terminalCaptureQualitySummary = captureQuality?.terminal_blocker === true || captureQuality?.blocking === true ? stringValue(captureQuality?.summary) : "";
2779
+ const checkpointName = captureTerminalBlocker ? "verify_capture_blocked" : "verify_capture_retry";
2780
+ const summary = terminalCaptureQualitySummary || structuredInteractionFailureSummary2 || stringValue(verifyDecisionRequest2?.summary) || stringValue(failedVerifyState?.verify_summary) || stringValue(failedVerifyState?.proof_summary) || stringValue(verifyRes.error) || "Verify capture failed before the evidence could be judged.";
2781
+ const failedVerifyDetails = {
2782
+ executed,
2783
+ verifyStatus: failedVerifyStatus,
2784
+ verifySummary: failedVerifyState?.verify_summary || failedVerifyState?.proof_summary || null,
2785
+ afterCdn: failedVerifyState?.after_cdn || null,
2786
+ mergeRecommendation: failedVerifyState?.merge_recommendation || null,
2787
+ verifyDecisionRequest: verifyDecisionRequest2,
2788
+ conclusiveVerifyBlockers: conclusiveVerifyBlockers2,
2789
+ verifyError: verifyRes.error || null,
2790
+ verifyStdout: verifyRes.stdout || "",
2791
+ verifyStderr: verifyRes.stderr || ""
2792
+ };
2793
+ recordAttempt("verify", "checkpoint", summary, {
2794
+ autoApproved: verifyRes.autoApproved || false,
2795
+ checkpoint: checkpointName,
2796
+ error: verifyRes.error || null,
2797
+ details: failedVerifyDetails
2798
+ });
2799
+ return checkpoint(
2800
+ "verify",
2801
+ checkpointName,
2802
+ summary,
2803
+ {
2804
+ ok: true,
2805
+ 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"],
2806
+ advanceOptions: needsImplementation ? ["author", "implement", "ship", "verify", "recon"] : ["author", "verify", "recon"],
2807
+ recommendedAdvanceStage: captureTerminalBlocker ? null : verifyDecisionRequest2?.recommended_stage || verifyDecisionRequest2?.continue_with_stage || "author",
2808
+ continueWithStage: captureTerminalBlocker ? null : verifyDecisionRequest2?.continue_with_stage || verifyDecisionRequest2?.recommended_stage || "author",
2809
+ blocking: captureTerminalBlocker,
2810
+ details: failedVerifyDetails,
2811
+ verifyStatus: failedVerifyStatus,
2812
+ verifySummary: failedVerifyDetails.verifySummary,
2813
+ afterCdn: failedVerifyState?.after_cdn || null,
2814
+ mergeRecommendation: failedVerifyState?.merge_recommendation || null,
2815
+ verifyDecisionRequest: verifyDecisionRequest2,
2816
+ executed
2817
+ }
2818
+ );
2819
+ }
2687
2820
  return failedRun("verify", verifyRes.haltedForApproval ? "verify halted for approval" : "verify failed", verifyRes, {
2688
2821
  checkpoint: "verify_failed",
2689
2822
  details: { executed },
@@ -2737,8 +2870,9 @@ ${implementRes.stderr || ""}`;
2737
2870
  });
2738
2871
  state = readState(config.statePath);
2739
2872
  }
2873
+ const terminalCaptureQualitySummary = captureQuality?.terminal_blocker === true || captureQuality?.blocking === true ? stringValue(captureQuality?.summary) : "";
2740
2874
  const checkpointName = captureTerminalBlocker ? "verify_capture_blocked" : "verify_capture_retry";
2741
- const summary = structuredInteractionFailureSummary || stringValue(proofAssessment.summary) || "Verify ran, but the proof packet still needs internal capture-plan work before it should ship.";
2875
+ const summary = terminalCaptureQualitySummary || structuredInteractionFailureSummary || stringValue(proofAssessment.summary) || "Verify ran, but the proof packet still needs internal capture-plan work before it should ship.";
2742
2876
  recordAttempt("verify", "checkpoint", summary, {
2743
2877
  autoApproved: verifyRes.autoApproved || false,
2744
2878
  checkpoint: checkpointName,
@@ -4879,6 +5013,7 @@ function initialRunParams(request, input, state) {
4879
5013
  auth_headers_json: request.auth_headers_json,
4880
5014
  color_scheme: request.color_scheme,
4881
5015
  wait_for_selector: request.wait_for_selector,
5016
+ ship_mode: request.ship_mode,
4882
5017
  leave_draft: request.leave_draft || void 0,
4883
5018
  discord_channel: request.integration_context?.channel_id,
4884
5019
  discord_thread_id: request.integration_context?.thread_id,
@@ -4891,6 +5026,18 @@ function initialRunParams(request, input, state) {
4891
5026
  function effectiveShipMode(request, config) {
4892
5027
  return request.ship_mode || config?.defaultShipMode || "ship";
4893
5028
  }
5029
+ function continuationRequestsShip(next) {
5030
+ return Boolean(next && (next.advance_stage === "ship" || next.ship_after_verify === true));
5031
+ }
5032
+ function shipHeldTerminal(state, result) {
5033
+ return terminalResult(
5034
+ state,
5035
+ "ready_to_ship",
5036
+ result,
5037
+ result.summary || "Riddle Proof evidence is approved, but ship_mode=none is holding before PR/ship.",
5038
+ { ship_held: true }
5039
+ );
5040
+ }
4894
5041
  function checkpointContinueStage2(result) {
4895
5042
  const resume = recordValue(result.checkpointContract?.resume);
4896
5043
  return nonEmptyString(resume?.continue_with_stage);
@@ -5415,6 +5562,28 @@ function checkpointResponseContinuation(state, value) {
5415
5562
  const assessment = proofAssessmentPayloadFromCheckpointResponse(response);
5416
5563
  if (assessment) {
5417
5564
  appendCheckpointResponse(state, response);
5565
+ if (state.request.ship_mode !== "ship" && proofAssessmentRequestsShip(assessment)) {
5566
+ const result = {
5567
+ ok: true,
5568
+ state_path: state.request.engine_state_path || packet.state_path || "",
5569
+ checkpoint: packet.checkpoint,
5570
+ stage: packet.stage,
5571
+ summary: response.summary,
5572
+ checkpointContract: checkpointContractFromPacket(packet) || null
5573
+ };
5574
+ return {
5575
+ terminal: terminalResult(
5576
+ state,
5577
+ "ready_to_ship",
5578
+ result,
5579
+ response.summary || "Riddle Proof evidence is approved, but ship_mode=none is holding before PR/ship.",
5580
+ {
5581
+ ship_held: true,
5582
+ proof_assessment: assessment
5583
+ }
5584
+ )
5585
+ };
5586
+ }
5418
5587
  return { next: { ...base, proof_assessment_json: jsonParam(assessment) } };
5419
5588
  }
5420
5589
  if (response.decision === "blocked" || response.decision === "human_review") {
@@ -5665,6 +5834,9 @@ async function routeCheckpoint(request, state, result, agent, input) {
5665
5834
  }
5666
5835
  const next = stageCheckpointContinuation(result);
5667
5836
  if (next) {
5837
+ if (continuationRequestsShip(next) && effectiveShipMode(request, input.config) !== "ship") {
5838
+ return { terminal: shipHeldTerminal(state, result) };
5839
+ }
5668
5840
  recordEvent(state, {
5669
5841
  kind: "checkpoint.recovery_continuation",
5670
5842
  checkpoint,
@@ -5696,6 +5868,9 @@ async function routeCheckpoint(request, state, result, agent, input) {
5696
5868
  };
5697
5869
  }
5698
5870
  if (checkpoint === "ship_review") {
5871
+ if (effectiveShipMode(request, input.config) !== "ship") {
5872
+ return { terminal: shipHeldTerminal(state, result) };
5873
+ }
5699
5874
  return {
5700
5875
  terminal: terminalResult(state, "shipped", result, result.summary || "Riddle Proof shipped.")
5701
5876
  };
@@ -5731,9 +5906,7 @@ async function routeCheckpoint(request, state, result, agent, input) {
5731
5906
  return { next: { ...baseContinuation(result), ship_after_verify: true } };
5732
5907
  }
5733
5908
  return {
5734
- terminal: terminalResult(state, "ready_to_ship", result, result.summary || "Riddle Proof evidence is approved, but ship_mode=none is holding before PR/ship.", {
5735
- ship_held: true
5736
- })
5909
+ terminal: shipHeldTerminal(state, result)
5737
5910
  };
5738
5911
  }
5739
5912
  if (checkpoint === "verify_audit_complete") {
@@ -6024,18 +6197,19 @@ async function routeCheckpoint(request, state, result, agent, input) {
6024
6197
  const next = recommendedContinuation(result) || defaultAwaitingStageContinuation(result);
6025
6198
  if (next) {
6026
6199
  if (String(next.advance_stage || "") === "ship" && effectiveShipMode(request, input.config) !== "ship") {
6027
- return {
6028
- terminal: terminalResult(state, "ready_to_ship", result, result.summary || "Riddle Proof evidence is approved, but ship_mode=none is holding before PR/ship.", {
6029
- ship_held: true
6030
- })
6031
- };
6200
+ return { terminal: shipHeldTerminal(state, result) };
6032
6201
  }
6033
6202
  return { next };
6034
6203
  }
6035
6204
  }
6036
6205
  if (checkpoint.endsWith("_review")) {
6037
6206
  const next = recommendedContinuation(result);
6038
- if (next) return { next };
6207
+ if (next) {
6208
+ if (continuationRequestsShip(next) && effectiveShipMode(request, input.config) !== "ship") {
6209
+ return { terminal: shipHeldTerminal(state, result) };
6210
+ }
6211
+ return { next };
6212
+ }
6039
6213
  }
6040
6214
  return {
6041
6215
  blocker: {
@@ -6061,6 +6235,9 @@ async function runRiddleProofEngineHarness(input) {
6061
6235
  if (checkpointContinuation.blocker) {
6062
6236
  return blockerResult(state, null, checkpointContinuation.blocker);
6063
6237
  }
6238
+ if (checkpointContinuation.terminal) {
6239
+ return checkpointContinuation.terminal;
6240
+ }
6064
6241
  const request = state.request;
6065
6242
  const agent = input.agent || createDisabledRiddleProofAgentAdapter();
6066
6243
  const maxIterations = Math.max(
package/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-FJPZZ4JO.js";
2
+ import "./chunk-U73JPBZW.js";
3
3
  import "./chunk-PEWAIEER.js";
4
4
  import "./chunk-TWTEUS7R.js";
5
- import "./chunk-AM3K5FPW.js";
5
+ import "./chunk-ZREWMTFA.js";
6
6
  import "./chunk-ZQWVXQKJ.js";
7
7
  import "./chunk-RDPG554T.js";
8
- import "./chunk-K6HZUSHH.js";
8
+ import "./chunk-X7SQTCIQ.js";
9
9
  import "./chunk-OILKSY5J.js";
10
10
  import "./chunk-JFQXAJH2.js";
11
11
  import "./chunk-73EBR3YL.js";
@@ -157,6 +157,7 @@ function buildSetupArgs(params, config) {
157
157
  discord_thread_id: params.discord_thread_id || "",
158
158
  discord_message_id: params.discord_message_id || "",
159
159
  discord_source_url: params.discord_source_url || "",
160
+ ship_mode: params.ship_mode || "",
160
161
  leave_draft: params.leave_draft ? "true" : ""
161
162
  };
162
163
  }
@@ -746,7 +747,8 @@ function mergeStateFromParams(statePath, params) {
746
747
  "auth_headers_json",
747
748
  "proof_plan",
748
749
  "implementation_notes",
749
- "implementation_mode"
750
+ "implementation_mode",
751
+ "ship_mode"
750
752
  ];
751
753
  for (const field of stringFields) {
752
754
  if (params[field] !== void 0) {
@@ -1365,6 +1367,72 @@ function updateState(statePath, mutate) {
1365
1367
  function nowIso() {
1366
1368
  return (/* @__PURE__ */ new Date()).toISOString();
1367
1369
  }
1370
+ function missingExecutableError(error) {
1371
+ return error?.code === "ENOENT" || /\bENOENT\b/.test(String(error?.message || error || ""));
1372
+ }
1373
+ function pythonScriptsForBundledStage(step) {
1374
+ if (step === "setup") return ["preflight.py", "setup.py"];
1375
+ if (step === "recon") return ["recon.py"];
1376
+ if (step === "author") return ["author.py"];
1377
+ if (step === "implement") return ["implement.py"];
1378
+ if (step === "verify") return ["verify.py"];
1379
+ if (step === "ship") return ["ship.py"];
1380
+ return [];
1381
+ }
1382
+ function runBundledPythonStage(step, runtimeDir, env) {
1383
+ const scripts = pythonScriptsForBundledStage(step);
1384
+ if (!scripts.length) {
1385
+ return {
1386
+ ok: false,
1387
+ error: `No bundled Python fallback is defined for ${step}.`
1388
+ };
1389
+ }
1390
+ const pythonCommand = process.env.RIDDLE_PROOF_PYTHON_COMMAND || "python3";
1391
+ const libDir = import_node_path2.default.join(runtimeDir, "lib");
1392
+ const stdout = [];
1393
+ const stderr = [];
1394
+ const executed = [];
1395
+ try {
1396
+ for (const script of scripts) {
1397
+ const scriptPath = import_node_path2.default.join(libDir, script);
1398
+ if (!(0, import_node_fs2.existsSync)(scriptPath)) {
1399
+ return {
1400
+ ok: false,
1401
+ stdout: stdout.join(""),
1402
+ stderr: stderr.join(""),
1403
+ error: `Riddle Proof bundled Python fallback missing ${scriptPath}`
1404
+ };
1405
+ }
1406
+ executed.push(script);
1407
+ stdout.push((0, import_node_child_process.execFileSync)(pythonCommand, [scriptPath], {
1408
+ encoding: "utf-8",
1409
+ env,
1410
+ stdio: ["ignore", "pipe", "pipe"]
1411
+ }));
1412
+ }
1413
+ } catch (error) {
1414
+ return {
1415
+ ok: false,
1416
+ stdout: `${stdout.join("")}${String(error?.stdout || "")}`,
1417
+ stderr: `${stderr.join("")}${String(error?.stderr || "")}`,
1418
+ error: error?.message || String(error),
1419
+ raw: {
1420
+ runner: "bundled_python_fallback",
1421
+ scripts: executed
1422
+ }
1423
+ };
1424
+ }
1425
+ return {
1426
+ ok: true,
1427
+ stdout: stdout.join(""),
1428
+ stderr: stderr.join(""),
1429
+ raw: {
1430
+ ok: true,
1431
+ runner: "bundled_python_fallback",
1432
+ scripts: executed
1433
+ }
1434
+ };
1435
+ }
1368
1436
  function appendRuntimeEventToState(state, event) {
1369
1437
  const events = Array.isArray(state.runtime_events) ? state.runtime_events : [];
1370
1438
  state.runtime_events = [...events, event].slice(-RUNTIME_EVENT_LIMIT);
@@ -1931,6 +1999,17 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1931
1999
  })
1932
2000
  );
1933
2001
  } catch (error) {
2002
+ if (!process.env.RIDDLE_PROOF_LOBSTER_SCRIPT && missingExecutableError(error)) {
2003
+ const fallback = runBundledPythonStage(step, config.riddleProofDir, env);
2004
+ return finishRuntimeStep(config.statePath, action, {
2005
+ ok: fallback.ok,
2006
+ step,
2007
+ raw: fallback.raw,
2008
+ stdout: fallback.stdout,
2009
+ stderr: fallback.stderr,
2010
+ error: fallback.error
2011
+ }, timer);
2012
+ }
1934
2013
  return finishRuntimeStep(config.statePath, action, {
1935
2014
  ok: false,
1936
2015
  step,
@@ -2684,6 +2763,60 @@ ${implementRes.stderr || ""}`;
2684
2763
  verifyRes = runOne("verify");
2685
2764
  executed.push(executedStep(verifyRes));
2686
2765
  if (!verifyRes.ok || verifyRes.haltedForApproval) {
2766
+ const failedVerifyState = readState(config.statePath);
2767
+ const failedVerifyStatus = failedVerifyState?.verify_status || "";
2768
+ if (!verifyRes.haltedForApproval && (failedVerifyStatus === "capture_incomplete" || failedVerifyStatus === "capture_error")) {
2769
+ const verifyDecisionRequest2 = failedVerifyState?.verify_decision_request || null;
2770
+ const captureQuality = verifyDecisionRequest2?.capture_quality || {};
2771
+ const conclusiveVerifyBlockers2 = proofAssessmentHardBlockersForState({
2772
+ ...failedVerifyState,
2773
+ structured_interaction_capture_failure_summary: stringValue(verifyDecisionRequest2?.structured_interaction_capture_failure_summary) || stringValue(failedVerifyState?.structured_interaction_capture_failure_summary) || void 0,
2774
+ structured_interaction_failure_summary: stringValue(verifyDecisionRequest2?.structured_interaction_failure_summary) || stringValue(failedVerifyState?.structured_interaction_failure_summary) || void 0
2775
+ });
2776
+ const structuredInteractionFailureSummary2 = stringValue(verifyDecisionRequest2?.structured_interaction_capture_failure_summary) || stringValue(verifyDecisionRequest2?.structured_interaction_failure_summary) || stringValue(failedVerifyState?.structured_interaction_capture_failure_summary) || stringValue(failedVerifyState?.structured_interaction_failure_summary) || stringValue(conclusiveVerifyBlockers2[0]);
2777
+ const captureTerminalBlocker = failedVerifyStatus === "capture_error" || conclusiveVerifyBlockers2.length > 0 || Boolean(structuredInteractionFailureSummary2) || captureQuality?.terminal_blocker === true || captureQuality?.blocking === true;
2778
+ const terminalCaptureQualitySummary = captureQuality?.terminal_blocker === true || captureQuality?.blocking === true ? stringValue(captureQuality?.summary) : "";
2779
+ const checkpointName = captureTerminalBlocker ? "verify_capture_blocked" : "verify_capture_retry";
2780
+ const summary = terminalCaptureQualitySummary || structuredInteractionFailureSummary2 || stringValue(verifyDecisionRequest2?.summary) || stringValue(failedVerifyState?.verify_summary) || stringValue(failedVerifyState?.proof_summary) || stringValue(verifyRes.error) || "Verify capture failed before the evidence could be judged.";
2781
+ const failedVerifyDetails = {
2782
+ executed,
2783
+ verifyStatus: failedVerifyStatus,
2784
+ verifySummary: failedVerifyState?.verify_summary || failedVerifyState?.proof_summary || null,
2785
+ afterCdn: failedVerifyState?.after_cdn || null,
2786
+ mergeRecommendation: failedVerifyState?.merge_recommendation || null,
2787
+ verifyDecisionRequest: verifyDecisionRequest2,
2788
+ conclusiveVerifyBlockers: conclusiveVerifyBlockers2,
2789
+ verifyError: verifyRes.error || null,
2790
+ verifyStdout: verifyRes.stdout || "",
2791
+ verifyStderr: verifyRes.stderr || ""
2792
+ };
2793
+ recordAttempt("verify", "checkpoint", summary, {
2794
+ autoApproved: verifyRes.autoApproved || false,
2795
+ checkpoint: checkpointName,
2796
+ error: verifyRes.error || null,
2797
+ details: failedVerifyDetails
2798
+ });
2799
+ return checkpoint(
2800
+ "verify",
2801
+ checkpointName,
2802
+ summary,
2803
+ {
2804
+ ok: true,
2805
+ 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"],
2806
+ advanceOptions: needsImplementation ? ["author", "implement", "ship", "verify", "recon"] : ["author", "verify", "recon"],
2807
+ recommendedAdvanceStage: captureTerminalBlocker ? null : verifyDecisionRequest2?.recommended_stage || verifyDecisionRequest2?.continue_with_stage || "author",
2808
+ continueWithStage: captureTerminalBlocker ? null : verifyDecisionRequest2?.continue_with_stage || verifyDecisionRequest2?.recommended_stage || "author",
2809
+ blocking: captureTerminalBlocker,
2810
+ details: failedVerifyDetails,
2811
+ verifyStatus: failedVerifyStatus,
2812
+ verifySummary: failedVerifyDetails.verifySummary,
2813
+ afterCdn: failedVerifyState?.after_cdn || null,
2814
+ mergeRecommendation: failedVerifyState?.merge_recommendation || null,
2815
+ verifyDecisionRequest: verifyDecisionRequest2,
2816
+ executed
2817
+ }
2818
+ );
2819
+ }
2687
2820
  return failedRun("verify", verifyRes.haltedForApproval ? "verify halted for approval" : "verify failed", verifyRes, {
2688
2821
  checkpoint: "verify_failed",
2689
2822
  details: { executed },
@@ -2737,8 +2870,9 @@ ${implementRes.stderr || ""}`;
2737
2870
  });
2738
2871
  state = readState(config.statePath);
2739
2872
  }
2873
+ const terminalCaptureQualitySummary = captureQuality?.terminal_blocker === true || captureQuality?.blocking === true ? stringValue(captureQuality?.summary) : "";
2740
2874
  const checkpointName = captureTerminalBlocker ? "verify_capture_blocked" : "verify_capture_retry";
2741
- const summary = structuredInteractionFailureSummary || stringValue(proofAssessment.summary) || "Verify ran, but the proof packet still needs internal capture-plan work before it should ship.";
2875
+ const summary = terminalCaptureQualitySummary || structuredInteractionFailureSummary || stringValue(proofAssessment.summary) || "Verify ran, but the proof packet still needs internal capture-plan work before it should ship.";
2742
2876
  recordAttempt("verify", "checkpoint", summary, {
2743
2877
  autoApproved: verifyRes.autoApproved || false,
2744
2878
  checkpoint: checkpointName,
@@ -4792,6 +4926,7 @@ function initialRunParams(request, input, state) {
4792
4926
  auth_headers_json: request.auth_headers_json,
4793
4927
  color_scheme: request.color_scheme,
4794
4928
  wait_for_selector: request.wait_for_selector,
4929
+ ship_mode: request.ship_mode,
4795
4930
  leave_draft: request.leave_draft || void 0,
4796
4931
  discord_channel: request.integration_context?.channel_id,
4797
4932
  discord_thread_id: request.integration_context?.thread_id,
@@ -4804,6 +4939,18 @@ function initialRunParams(request, input, state) {
4804
4939
  function effectiveShipMode(request, config) {
4805
4940
  return request.ship_mode || config?.defaultShipMode || "ship";
4806
4941
  }
4942
+ function continuationRequestsShip(next) {
4943
+ return Boolean(next && (next.advance_stage === "ship" || next.ship_after_verify === true));
4944
+ }
4945
+ function shipHeldTerminal(state, result) {
4946
+ return terminalResult(
4947
+ state,
4948
+ "ready_to_ship",
4949
+ result,
4950
+ result.summary || "Riddle Proof evidence is approved, but ship_mode=none is holding before PR/ship.",
4951
+ { ship_held: true }
4952
+ );
4953
+ }
4807
4954
  function checkpointContinueStage2(result) {
4808
4955
  const resume = recordValue(result.checkpointContract?.resume);
4809
4956
  return nonEmptyString(resume?.continue_with_stage);
@@ -5328,6 +5475,28 @@ function checkpointResponseContinuation(state, value) {
5328
5475
  const assessment = proofAssessmentPayloadFromCheckpointResponse(response);
5329
5476
  if (assessment) {
5330
5477
  appendCheckpointResponse(state, response);
5478
+ if (state.request.ship_mode !== "ship" && proofAssessmentRequestsShip(assessment)) {
5479
+ const result = {
5480
+ ok: true,
5481
+ state_path: state.request.engine_state_path || packet.state_path || "",
5482
+ checkpoint: packet.checkpoint,
5483
+ stage: packet.stage,
5484
+ summary: response.summary,
5485
+ checkpointContract: checkpointContractFromPacket(packet) || null
5486
+ };
5487
+ return {
5488
+ terminal: terminalResult(
5489
+ state,
5490
+ "ready_to_ship",
5491
+ result,
5492
+ response.summary || "Riddle Proof evidence is approved, but ship_mode=none is holding before PR/ship.",
5493
+ {
5494
+ ship_held: true,
5495
+ proof_assessment: assessment
5496
+ }
5497
+ )
5498
+ };
5499
+ }
5331
5500
  return { next: { ...base, proof_assessment_json: jsonParam(assessment) } };
5332
5501
  }
5333
5502
  if (response.decision === "blocked" || response.decision === "human_review") {
@@ -5578,6 +5747,9 @@ async function routeCheckpoint(request, state, result, agent, input) {
5578
5747
  }
5579
5748
  const next = stageCheckpointContinuation(result);
5580
5749
  if (next) {
5750
+ if (continuationRequestsShip(next) && effectiveShipMode(request, input.config) !== "ship") {
5751
+ return { terminal: shipHeldTerminal(state, result) };
5752
+ }
5581
5753
  recordEvent(state, {
5582
5754
  kind: "checkpoint.recovery_continuation",
5583
5755
  checkpoint,
@@ -5609,6 +5781,9 @@ async function routeCheckpoint(request, state, result, agent, input) {
5609
5781
  };
5610
5782
  }
5611
5783
  if (checkpoint === "ship_review") {
5784
+ if (effectiveShipMode(request, input.config) !== "ship") {
5785
+ return { terminal: shipHeldTerminal(state, result) };
5786
+ }
5612
5787
  return {
5613
5788
  terminal: terminalResult(state, "shipped", result, result.summary || "Riddle Proof shipped.")
5614
5789
  };
@@ -5644,9 +5819,7 @@ async function routeCheckpoint(request, state, result, agent, input) {
5644
5819
  return { next: { ...baseContinuation(result), ship_after_verify: true } };
5645
5820
  }
5646
5821
  return {
5647
- terminal: terminalResult(state, "ready_to_ship", result, result.summary || "Riddle Proof evidence is approved, but ship_mode=none is holding before PR/ship.", {
5648
- ship_held: true
5649
- })
5822
+ terminal: shipHeldTerminal(state, result)
5650
5823
  };
5651
5824
  }
5652
5825
  if (checkpoint === "verify_audit_complete") {
@@ -5937,18 +6110,19 @@ async function routeCheckpoint(request, state, result, agent, input) {
5937
6110
  const next = recommendedContinuation(result) || defaultAwaitingStageContinuation(result);
5938
6111
  if (next) {
5939
6112
  if (String(next.advance_stage || "") === "ship" && effectiveShipMode(request, input.config) !== "ship") {
5940
- return {
5941
- terminal: terminalResult(state, "ready_to_ship", result, result.summary || "Riddle Proof evidence is approved, but ship_mode=none is holding before PR/ship.", {
5942
- ship_held: true
5943
- })
5944
- };
6113
+ return { terminal: shipHeldTerminal(state, result) };
5945
6114
  }
5946
6115
  return { next };
5947
6116
  }
5948
6117
  }
5949
6118
  if (checkpoint.endsWith("_review")) {
5950
6119
  const next = recommendedContinuation(result);
5951
- if (next) return { next };
6120
+ if (next) {
6121
+ if (continuationRequestsShip(next) && effectiveShipMode(request, input.config) !== "ship") {
6122
+ return { terminal: shipHeldTerminal(state, result) };
6123
+ }
6124
+ return { next };
6125
+ }
5952
6126
  }
5953
6127
  return {
5954
6128
  blocker: {
@@ -5974,6 +6148,9 @@ async function runRiddleProofEngineHarness(input) {
5974
6148
  if (checkpointContinuation.blocker) {
5975
6149
  return blockerResult(state, null, checkpointContinuation.blocker);
5976
6150
  }
6151
+ if (checkpointContinuation.terminal) {
6152
+ return checkpointContinuation.terminal;
6153
+ }
5977
6154
  const request = state.request;
5978
6155
  const agent = input.agent || createDisabledRiddleProofAgentAdapter();
5979
6156
  const maxIterations = Math.max(
@@ -2,10 +2,10 @@ import {
2
2
  createDisabledRiddleProofAgentAdapter,
3
3
  readRiddleProofRunStatus,
4
4
  runRiddleProofEngineHarness
5
- } from "./chunk-AM3K5FPW.js";
5
+ } from "./chunk-ZREWMTFA.js";
6
6
  import "./chunk-ZQWVXQKJ.js";
7
7
  import "./chunk-RDPG554T.js";
8
- import "./chunk-K6HZUSHH.js";
8
+ import "./chunk-X7SQTCIQ.js";
9
9
  import "./chunk-OILKSY5J.js";
10
10
  import "./chunk-VY4Y5U57.js";
11
11
  import "./chunk-MLKGABMK.js";