@riddledc/riddle-proof 0.5.47 → 0.5.48

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.
@@ -281,6 +281,20 @@ function checkpointContinueStage(result) {
281
281
  const resume = recordValue(result.checkpointContract?.resume);
282
282
  return nonEmptyString(resume?.continue_with_stage);
283
283
  }
284
+ function checkpointRecommendedStage(result) {
285
+ const resumeStage = checkpointContinueStage(result);
286
+ if (resumeStage) return resumeStage;
287
+ return nonEmptyString(result.checkpointContract?.recommended_advance_stage) || nonEmptyString(result.decisionRequest?.continue_with_stage) || nonEmptyString(result.decisionRequest?.recommended_advance_stage) || nonEmptyString(recordValue(result.decisionRequest)?.continueWithStage) || nonEmptyString(recordValue(result.decisionRequest)?.recommendedAdvanceStage);
288
+ }
289
+ function stageCheckpointContinuation(result) {
290
+ const stage = checkpointRecommendedStage(result);
291
+ if (!stage) return null;
292
+ return {
293
+ action: "run",
294
+ state_path: String(result.state_path || ""),
295
+ advance_stage: stage
296
+ };
297
+ }
284
298
  function recommendedContinuation(result) {
285
299
  const continueStage = checkpointContinueStage(result);
286
300
  if (!continueStage) return null;
@@ -323,6 +337,18 @@ function defaultStageForProofCheckpointDecision(decision) {
323
337
  if (decision === "needs_richer_proof") return "author";
324
338
  return null;
325
339
  }
340
+ function checkpointContractFromPacket(packet) {
341
+ return recordValue(packet.evidence_excerpt?.checkpoint_contract) || recordValue(recordValue(packet.state_excerpt?.stage_decision_request)?.checkpoint_contract) || null;
342
+ }
343
+ function stageFromCheckpointResponse(response, packet) {
344
+ if (response.decision === "needs_recon") return "recon";
345
+ if (response.decision === "needs_implementation") return "implement";
346
+ const payload = recordValue(response.payload) || {};
347
+ const contract = checkpointContractFromPacket(packet);
348
+ const resume = recordValue(contract?.resume);
349
+ const stage = response.continue_with_stage || nonEmptyString(payload.continue_with_stage) || nonEmptyString(payload.recommended_stage) || nonEmptyString(resume?.continue_with_stage) || (response.decision === "retry_stage" ? packet.stage : "");
350
+ return stage ? stage : null;
351
+ }
326
352
  function proofAssessmentPayloadFromCheckpointResponse(response) {
327
353
  if (![
328
354
  "ready_to_ship",
@@ -425,6 +451,13 @@ function visualDeltaEvidenceRecoveryAssessment(state, payload, blocker) {
425
451
  blockers: [...blockers, blocker]
426
452
  };
427
453
  }
454
+ function isRecoverableStageCheckpoint(checkpoint) {
455
+ return [
456
+ "ship_gate_blocked",
457
+ "verify_required",
458
+ "verify_supervisor_judgment_required"
459
+ ].includes(checkpoint);
460
+ }
428
461
  function contextFor(request, state, result) {
429
462
  return {
430
463
  request,
@@ -771,6 +804,18 @@ function checkpointResponseContinuation(state, value) {
771
804
  };
772
805
  }
773
806
  }
807
+ if (response.decision === "continue_stage" || response.decision === "retry_stage" || response.decision === "needs_implementation") {
808
+ const stage = stageFromCheckpointResponse(response, packet);
809
+ if (stage) {
810
+ appendCheckpointResponse(state, response);
811
+ return {
812
+ next: {
813
+ ...base,
814
+ advance_stage: stage
815
+ }
816
+ };
817
+ }
818
+ }
774
819
  appendCheckpointResponse(state, response, { clear_packet: false });
775
820
  return {
776
821
  blocker: {
@@ -893,18 +938,23 @@ async function handleImplementation(request, state, result, agent) {
893
938
  adapter_details: implementation.details || null
894
939
  })
895
940
  });
896
- return {
897
- blocker: {
898
- code: "implementation_diff_missing",
941
+ recordEvent(state, {
942
+ kind: "agent.implementation.retry_requested",
943
+ checkpoint: result.checkpoint || null,
944
+ stage: "implement",
945
+ summary: "Implementation adapter left no detectable diff; retrying the implement checkpoint inside the bounded loop.",
946
+ details: compactRecord({
947
+ worktree_path: workdir || null,
899
948
  checkpoint: result.checkpoint || null,
900
- message: "The implementation adapter returned, but the after worktree has no detectable git diff. The harness will not advance to verify.",
901
- details: compactRecord({
902
- worktree_path: workdir || null,
903
- changed_files: implementation.changedFiles || [],
904
- tests_run: implementation.testsRun || [],
905
- implementation_notes: implementation.implementationNotes || null,
906
- adapter_details: implementation.details || null
907
- })
949
+ next_stage: "implement"
950
+ })
951
+ });
952
+ return {
953
+ next: {
954
+ action: "run",
955
+ state_path: String(result.state_path || ""),
956
+ advance_stage: "implement",
957
+ implementation_notes: implementation.implementationNotes || implementation.summary || "Implementation adapter returned without a detectable git diff; retry the implement checkpoint."
908
958
  }
909
959
  };
910
960
  }
@@ -940,16 +990,32 @@ async function routeCheckpoint(request, state, result, agent, input) {
940
990
  terminal: terminalResult(state, "completed", result, result.summary || "Riddle Proof engine completed.")
941
991
  };
942
992
  }
993
+ if (isRecoverableStageCheckpoint(checkpoint) && !input.dry_run && !request.dry_run) {
994
+ if (input.checkpoint_mode === "yield") {
995
+ return { terminal: checkpointAwaitingResult(state, result, input.checkpoint_visibility) };
996
+ }
997
+ const next = stageCheckpointContinuation(result);
998
+ if (next) {
999
+ recordEvent(state, {
1000
+ kind: "checkpoint.recovery_continuation",
1001
+ checkpoint,
1002
+ stage: stageFromCheckpoint(result),
1003
+ summary: `Routing recoverable checkpoint ${checkpoint} back to ${next.advance_stage}.`,
1004
+ details: {
1005
+ next,
1006
+ checkpointContract: result.checkpointContract || null
1007
+ }
1008
+ });
1009
+ return { next };
1010
+ }
1011
+ }
943
1012
  const failureBlocker = engineFailureBlocker(result, checkpoint);
944
1013
  if (failureBlocker) {
945
1014
  return { blocker: failureBlocker };
946
1015
  }
947
1016
  if ([
948
1017
  "recon_human_escalation",
949
- "verify_human_escalation",
950
- "ship_gate_blocked",
951
- "verify_required",
952
- "verify_supervisor_judgment_required"
1018
+ "verify_human_escalation"
953
1019
  ].includes(checkpoint) && result.ok === false) {
954
1020
  return {
955
1021
  blocker: {
package/dist/cli.cjs CHANGED
@@ -1747,9 +1747,27 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1747
1747
  }
1748
1748
  return "inspect the ship gate details, repair the missing invariant, then resume the run";
1749
1749
  };
1750
+ const shipGateRecoveryStage = (shipGate) => {
1751
+ const reasons = shipGate.reasons || [];
1752
+ if (reasons.some((reason) => reason.includes("before_cdn") || reason.includes("prod_cdn") || reason.includes("prod_url"))) {
1753
+ return "recon";
1754
+ }
1755
+ if (reasons.some((reason) => reason.includes("implementation"))) {
1756
+ return "implement";
1757
+ }
1758
+ if (reasons.some((reason) => reason.includes("after_cdn") || reason.includes("verify_status") || reason.includes("visual_delta"))) {
1759
+ return "verify";
1760
+ }
1761
+ if (reasons.some((reason) => reason.includes("proof_assessment"))) {
1762
+ return "verify";
1763
+ }
1764
+ return "verify";
1765
+ };
1750
1766
  const shipGateBlocked = (state, executed, details = {}) => {
1751
1767
  const shipGate = validateShipGate(state);
1752
1768
  const nextAction = primaryShipGateNextAction(shipGate);
1769
+ const recoveryStage = shipGateRecoveryStage(shipGate);
1770
+ const advanceOptions = Array.from(/* @__PURE__ */ new Set([recoveryStage, "verify", "author", "implement", "recon", "ship"]));
1753
1771
  return checkpoint(
1754
1772
  "verify",
1755
1773
  "ship_gate_blocked",
@@ -1757,12 +1775,13 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1757
1775
  {
1758
1776
  ok: false,
1759
1777
  nextActions: ["inspect_ship_gate", "advance_run_to_verify", "supply_proof_assessment_json", "return_to_recon_if_baseline_is_missing"],
1760
- advanceOptions: ["verify", "author", "implement", "recon"],
1761
- recommendedAdvanceStage: "verify",
1762
- continueWithStage: "verify",
1778
+ advanceOptions,
1779
+ recommendedAdvanceStage: recoveryStage,
1780
+ continueWithStage: recoveryStage,
1763
1781
  blocking: true,
1764
- details: { ...details, shipGate, next_action: nextAction, executed },
1782
+ details: { ...details, shipGate, next_action: nextAction, recovery_stage: recoveryStage, executed },
1765
1783
  nextAction,
1784
+ recoveryStage,
1766
1785
  shipGate,
1767
1786
  verifyStatus: state?.verify_status || null,
1768
1787
  mergeRecommendation: state?.merge_recommendation || null,
@@ -4180,6 +4199,20 @@ function checkpointContinueStage2(result) {
4180
4199
  const resume = recordValue(result.checkpointContract?.resume);
4181
4200
  return nonEmptyString(resume?.continue_with_stage);
4182
4201
  }
4202
+ function checkpointRecommendedStage(result) {
4203
+ const resumeStage = checkpointContinueStage2(result);
4204
+ if (resumeStage) return resumeStage;
4205
+ return nonEmptyString(result.checkpointContract?.recommended_advance_stage) || nonEmptyString(result.decisionRequest?.continue_with_stage) || nonEmptyString(result.decisionRequest?.recommended_advance_stage) || nonEmptyString(recordValue(result.decisionRequest)?.continueWithStage) || nonEmptyString(recordValue(result.decisionRequest)?.recommendedAdvanceStage);
4206
+ }
4207
+ function stageCheckpointContinuation(result) {
4208
+ const stage = checkpointRecommendedStage(result);
4209
+ if (!stage) return null;
4210
+ return {
4211
+ action: "run",
4212
+ state_path: String(result.state_path || ""),
4213
+ advance_stage: stage
4214
+ };
4215
+ }
4183
4216
  function recommendedContinuation(result) {
4184
4217
  const continueStage = checkpointContinueStage2(result);
4185
4218
  if (!continueStage) return null;
@@ -4222,6 +4255,18 @@ function defaultStageForProofCheckpointDecision(decision) {
4222
4255
  if (decision === "needs_richer_proof") return "author";
4223
4256
  return null;
4224
4257
  }
4258
+ function checkpointContractFromPacket(packet) {
4259
+ return recordValue(packet.evidence_excerpt?.checkpoint_contract) || recordValue(recordValue(packet.state_excerpt?.stage_decision_request)?.checkpoint_contract) || null;
4260
+ }
4261
+ function stageFromCheckpointResponse(response, packet) {
4262
+ if (response.decision === "needs_recon") return "recon";
4263
+ if (response.decision === "needs_implementation") return "implement";
4264
+ const payload = recordValue(response.payload) || {};
4265
+ const contract = checkpointContractFromPacket(packet);
4266
+ const resume = recordValue(contract?.resume);
4267
+ const stage = response.continue_with_stage || nonEmptyString(payload.continue_with_stage) || nonEmptyString(payload.recommended_stage) || nonEmptyString(resume?.continue_with_stage) || (response.decision === "retry_stage" ? packet.stage : "");
4268
+ return stage ? stage : null;
4269
+ }
4225
4270
  function proofAssessmentPayloadFromCheckpointResponse(response) {
4226
4271
  if (![
4227
4272
  "ready_to_ship",
@@ -4324,6 +4369,13 @@ function visualDeltaEvidenceRecoveryAssessment(state, payload, blocker) {
4324
4369
  blockers: [...blockers, blocker]
4325
4370
  };
4326
4371
  }
4372
+ function isRecoverableStageCheckpoint(checkpoint) {
4373
+ return [
4374
+ "ship_gate_blocked",
4375
+ "verify_required",
4376
+ "verify_supervisor_judgment_required"
4377
+ ].includes(checkpoint);
4378
+ }
4327
4379
  function contextFor(request, state, result) {
4328
4380
  return {
4329
4381
  request,
@@ -4670,6 +4722,18 @@ function checkpointResponseContinuation(state, value) {
4670
4722
  };
4671
4723
  }
4672
4724
  }
4725
+ if (response.decision === "continue_stage" || response.decision === "retry_stage" || response.decision === "needs_implementation") {
4726
+ const stage = stageFromCheckpointResponse(response, packet);
4727
+ if (stage) {
4728
+ appendCheckpointResponse(state, response);
4729
+ return {
4730
+ next: {
4731
+ ...base,
4732
+ advance_stage: stage
4733
+ }
4734
+ };
4735
+ }
4736
+ }
4673
4737
  appendCheckpointResponse(state, response, { clear_packet: false });
4674
4738
  return {
4675
4739
  blocker: {
@@ -4792,18 +4856,23 @@ async function handleImplementation(request, state, result, agent) {
4792
4856
  adapter_details: implementation.details || null
4793
4857
  })
4794
4858
  });
4795
- return {
4796
- blocker: {
4797
- code: "implementation_diff_missing",
4859
+ recordEvent(state, {
4860
+ kind: "agent.implementation.retry_requested",
4861
+ checkpoint: result.checkpoint || null,
4862
+ stage: "implement",
4863
+ summary: "Implementation adapter left no detectable diff; retrying the implement checkpoint inside the bounded loop.",
4864
+ details: compactRecord({
4865
+ worktree_path: workdir || null,
4798
4866
  checkpoint: result.checkpoint || null,
4799
- message: "The implementation adapter returned, but the after worktree has no detectable git diff. The harness will not advance to verify.",
4800
- details: compactRecord({
4801
- worktree_path: workdir || null,
4802
- changed_files: implementation.changedFiles || [],
4803
- tests_run: implementation.testsRun || [],
4804
- implementation_notes: implementation.implementationNotes || null,
4805
- adapter_details: implementation.details || null
4806
- })
4867
+ next_stage: "implement"
4868
+ })
4869
+ });
4870
+ return {
4871
+ next: {
4872
+ action: "run",
4873
+ state_path: String(result.state_path || ""),
4874
+ advance_stage: "implement",
4875
+ implementation_notes: implementation.implementationNotes || implementation.summary || "Implementation adapter returned without a detectable git diff; retry the implement checkpoint."
4807
4876
  }
4808
4877
  };
4809
4878
  }
@@ -4839,16 +4908,32 @@ async function routeCheckpoint(request, state, result, agent, input) {
4839
4908
  terminal: terminalResult(state, "completed", result, result.summary || "Riddle Proof engine completed.")
4840
4909
  };
4841
4910
  }
4911
+ if (isRecoverableStageCheckpoint(checkpoint) && !input.dry_run && !request.dry_run) {
4912
+ if (input.checkpoint_mode === "yield") {
4913
+ return { terminal: checkpointAwaitingResult(state, result, input.checkpoint_visibility) };
4914
+ }
4915
+ const next = stageCheckpointContinuation(result);
4916
+ if (next) {
4917
+ recordEvent(state, {
4918
+ kind: "checkpoint.recovery_continuation",
4919
+ checkpoint,
4920
+ stage: stageFromCheckpoint2(result),
4921
+ summary: `Routing recoverable checkpoint ${checkpoint} back to ${next.advance_stage}.`,
4922
+ details: {
4923
+ next,
4924
+ checkpointContract: result.checkpointContract || null
4925
+ }
4926
+ });
4927
+ return { next };
4928
+ }
4929
+ }
4842
4930
  const failureBlocker = engineFailureBlocker(result, checkpoint);
4843
4931
  if (failureBlocker) {
4844
4932
  return { blocker: failureBlocker };
4845
4933
  }
4846
4934
  if ([
4847
4935
  "recon_human_escalation",
4848
- "verify_human_escalation",
4849
- "ship_gate_blocked",
4850
- "verify_required",
4851
- "verify_supervisor_judgment_required"
4936
+ "verify_human_escalation"
4852
4937
  ].includes(checkpoint) && result.ok === false) {
4853
4938
  return {
4854
4939
  blocker: {
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  createDisabledRiddleProofAgentAdapter,
4
4
  readRiddleProofRunStatus,
5
5
  runRiddleProofEngineHarness
6
- } from "./chunk-ALP5KOS2.js";
6
+ } from "./chunk-2RS4PBYK.js";
7
7
  import "./chunk-4ASMX4R6.js";
8
8
  import "./chunk-JFQXAJH2.js";
9
9
  import {
@@ -1747,9 +1747,27 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1747
1747
  }
1748
1748
  return "inspect the ship gate details, repair the missing invariant, then resume the run";
1749
1749
  };
1750
+ const shipGateRecoveryStage = (shipGate) => {
1751
+ const reasons = shipGate.reasons || [];
1752
+ if (reasons.some((reason) => reason.includes("before_cdn") || reason.includes("prod_cdn") || reason.includes("prod_url"))) {
1753
+ return "recon";
1754
+ }
1755
+ if (reasons.some((reason) => reason.includes("implementation"))) {
1756
+ return "implement";
1757
+ }
1758
+ if (reasons.some((reason) => reason.includes("after_cdn") || reason.includes("verify_status") || reason.includes("visual_delta"))) {
1759
+ return "verify";
1760
+ }
1761
+ if (reasons.some((reason) => reason.includes("proof_assessment"))) {
1762
+ return "verify";
1763
+ }
1764
+ return "verify";
1765
+ };
1750
1766
  const shipGateBlocked = (state, executed, details = {}) => {
1751
1767
  const shipGate = validateShipGate(state);
1752
1768
  const nextAction = primaryShipGateNextAction(shipGate);
1769
+ const recoveryStage = shipGateRecoveryStage(shipGate);
1770
+ const advanceOptions = Array.from(/* @__PURE__ */ new Set([recoveryStage, "verify", "author", "implement", "recon", "ship"]));
1753
1771
  return checkpoint(
1754
1772
  "verify",
1755
1773
  "ship_gate_blocked",
@@ -1757,12 +1775,13 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1757
1775
  {
1758
1776
  ok: false,
1759
1777
  nextActions: ["inspect_ship_gate", "advance_run_to_verify", "supply_proof_assessment_json", "return_to_recon_if_baseline_is_missing"],
1760
- advanceOptions: ["verify", "author", "implement", "recon"],
1761
- recommendedAdvanceStage: "verify",
1762
- continueWithStage: "verify",
1778
+ advanceOptions,
1779
+ recommendedAdvanceStage: recoveryStage,
1780
+ continueWithStage: recoveryStage,
1763
1781
  blocking: true,
1764
- details: { ...details, shipGate, next_action: nextAction, executed },
1782
+ details: { ...details, shipGate, next_action: nextAction, recovery_stage: recoveryStage, executed },
1765
1783
  nextAction,
1784
+ recoveryStage,
1766
1785
  shipGate,
1767
1786
  verifyStatus: state?.verify_status || null,
1768
1787
  mergeRecommendation: state?.merge_recommendation || null,
@@ -4184,6 +4203,20 @@ function checkpointContinueStage2(result) {
4184
4203
  const resume = recordValue(result.checkpointContract?.resume);
4185
4204
  return nonEmptyString(resume?.continue_with_stage);
4186
4205
  }
4206
+ function checkpointRecommendedStage(result) {
4207
+ const resumeStage = checkpointContinueStage2(result);
4208
+ if (resumeStage) return resumeStage;
4209
+ return nonEmptyString(result.checkpointContract?.recommended_advance_stage) || nonEmptyString(result.decisionRequest?.continue_with_stage) || nonEmptyString(result.decisionRequest?.recommended_advance_stage) || nonEmptyString(recordValue(result.decisionRequest)?.continueWithStage) || nonEmptyString(recordValue(result.decisionRequest)?.recommendedAdvanceStage);
4210
+ }
4211
+ function stageCheckpointContinuation(result) {
4212
+ const stage = checkpointRecommendedStage(result);
4213
+ if (!stage) return null;
4214
+ return {
4215
+ action: "run",
4216
+ state_path: String(result.state_path || ""),
4217
+ advance_stage: stage
4218
+ };
4219
+ }
4187
4220
  function recommendedContinuation(result) {
4188
4221
  const continueStage = checkpointContinueStage2(result);
4189
4222
  if (!continueStage) return null;
@@ -4226,6 +4259,18 @@ function defaultStageForProofCheckpointDecision(decision) {
4226
4259
  if (decision === "needs_richer_proof") return "author";
4227
4260
  return null;
4228
4261
  }
4262
+ function checkpointContractFromPacket(packet) {
4263
+ return recordValue(packet.evidence_excerpt?.checkpoint_contract) || recordValue(recordValue(packet.state_excerpt?.stage_decision_request)?.checkpoint_contract) || null;
4264
+ }
4265
+ function stageFromCheckpointResponse(response, packet) {
4266
+ if (response.decision === "needs_recon") return "recon";
4267
+ if (response.decision === "needs_implementation") return "implement";
4268
+ const payload = recordValue(response.payload) || {};
4269
+ const contract = checkpointContractFromPacket(packet);
4270
+ const resume = recordValue(contract?.resume);
4271
+ const stage = response.continue_with_stage || nonEmptyString(payload.continue_with_stage) || nonEmptyString(payload.recommended_stage) || nonEmptyString(resume?.continue_with_stage) || (response.decision === "retry_stage" ? packet.stage : "");
4272
+ return stage ? stage : null;
4273
+ }
4229
4274
  function proofAssessmentPayloadFromCheckpointResponse(response) {
4230
4275
  if (![
4231
4276
  "ready_to_ship",
@@ -4328,6 +4373,13 @@ function visualDeltaEvidenceRecoveryAssessment(state, payload, blocker) {
4328
4373
  blockers: [...blockers, blocker]
4329
4374
  };
4330
4375
  }
4376
+ function isRecoverableStageCheckpoint(checkpoint) {
4377
+ return [
4378
+ "ship_gate_blocked",
4379
+ "verify_required",
4380
+ "verify_supervisor_judgment_required"
4381
+ ].includes(checkpoint);
4382
+ }
4331
4383
  function contextFor(request, state, result) {
4332
4384
  return {
4333
4385
  request,
@@ -4674,6 +4726,18 @@ function checkpointResponseContinuation(state, value) {
4674
4726
  };
4675
4727
  }
4676
4728
  }
4729
+ if (response.decision === "continue_stage" || response.decision === "retry_stage" || response.decision === "needs_implementation") {
4730
+ const stage = stageFromCheckpointResponse(response, packet);
4731
+ if (stage) {
4732
+ appendCheckpointResponse(state, response);
4733
+ return {
4734
+ next: {
4735
+ ...base,
4736
+ advance_stage: stage
4737
+ }
4738
+ };
4739
+ }
4740
+ }
4677
4741
  appendCheckpointResponse(state, response, { clear_packet: false });
4678
4742
  return {
4679
4743
  blocker: {
@@ -4796,18 +4860,23 @@ async function handleImplementation(request, state, result, agent) {
4796
4860
  adapter_details: implementation.details || null
4797
4861
  })
4798
4862
  });
4799
- return {
4800
- blocker: {
4801
- code: "implementation_diff_missing",
4863
+ recordEvent(state, {
4864
+ kind: "agent.implementation.retry_requested",
4865
+ checkpoint: result.checkpoint || null,
4866
+ stage: "implement",
4867
+ summary: "Implementation adapter left no detectable diff; retrying the implement checkpoint inside the bounded loop.",
4868
+ details: compactRecord({
4869
+ worktree_path: workdir || null,
4802
4870
  checkpoint: result.checkpoint || null,
4803
- message: "The implementation adapter returned, but the after worktree has no detectable git diff. The harness will not advance to verify.",
4804
- details: compactRecord({
4805
- worktree_path: workdir || null,
4806
- changed_files: implementation.changedFiles || [],
4807
- tests_run: implementation.testsRun || [],
4808
- implementation_notes: implementation.implementationNotes || null,
4809
- adapter_details: implementation.details || null
4810
- })
4871
+ next_stage: "implement"
4872
+ })
4873
+ });
4874
+ return {
4875
+ next: {
4876
+ action: "run",
4877
+ state_path: String(result.state_path || ""),
4878
+ advance_stage: "implement",
4879
+ implementation_notes: implementation.implementationNotes || implementation.summary || "Implementation adapter returned without a detectable git diff; retry the implement checkpoint."
4811
4880
  }
4812
4881
  };
4813
4882
  }
@@ -4843,16 +4912,32 @@ async function routeCheckpoint(request, state, result, agent, input) {
4843
4912
  terminal: terminalResult(state, "completed", result, result.summary || "Riddle Proof engine completed.")
4844
4913
  };
4845
4914
  }
4915
+ if (isRecoverableStageCheckpoint(checkpoint) && !input.dry_run && !request.dry_run) {
4916
+ if (input.checkpoint_mode === "yield") {
4917
+ return { terminal: checkpointAwaitingResult(state, result, input.checkpoint_visibility) };
4918
+ }
4919
+ const next = stageCheckpointContinuation(result);
4920
+ if (next) {
4921
+ recordEvent(state, {
4922
+ kind: "checkpoint.recovery_continuation",
4923
+ checkpoint,
4924
+ stage: stageFromCheckpoint2(result),
4925
+ summary: `Routing recoverable checkpoint ${checkpoint} back to ${next.advance_stage}.`,
4926
+ details: {
4927
+ next,
4928
+ checkpointContract: result.checkpointContract || null
4929
+ }
4930
+ });
4931
+ return { next };
4932
+ }
4933
+ }
4846
4934
  const failureBlocker = engineFailureBlocker(result, checkpoint);
4847
4935
  if (failureBlocker) {
4848
4936
  return { blocker: failureBlocker };
4849
4937
  }
4850
4938
  if ([
4851
4939
  "recon_human_escalation",
4852
- "verify_human_escalation",
4853
- "ship_gate_blocked",
4854
- "verify_required",
4855
- "verify_supervisor_judgment_required"
4940
+ "verify_human_escalation"
4856
4941
  ].includes(checkpoint) && result.ok === false) {
4857
4942
  return {
4858
4943
  blocker: {
@@ -2,7 +2,7 @@ import {
2
2
  createDisabledRiddleProofAgentAdapter,
3
3
  readRiddleProofRunStatus,
4
4
  runRiddleProofEngineHarness
5
- } from "./chunk-ALP5KOS2.js";
5
+ } from "./chunk-2RS4PBYK.js";
6
6
  import "./chunk-4ASMX4R6.js";
7
7
  import "./chunk-JOXTKWX6.js";
8
8
  import "./chunk-PLSGW2GI.js";
package/dist/index.cjs CHANGED
@@ -1747,9 +1747,27 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1747
1747
  }
1748
1748
  return "inspect the ship gate details, repair the missing invariant, then resume the run";
1749
1749
  };
1750
+ const shipGateRecoveryStage = (shipGate) => {
1751
+ const reasons = shipGate.reasons || [];
1752
+ if (reasons.some((reason) => reason.includes("before_cdn") || reason.includes("prod_cdn") || reason.includes("prod_url"))) {
1753
+ return "recon";
1754
+ }
1755
+ if (reasons.some((reason) => reason.includes("implementation"))) {
1756
+ return "implement";
1757
+ }
1758
+ if (reasons.some((reason) => reason.includes("after_cdn") || reason.includes("verify_status") || reason.includes("visual_delta"))) {
1759
+ return "verify";
1760
+ }
1761
+ if (reasons.some((reason) => reason.includes("proof_assessment"))) {
1762
+ return "verify";
1763
+ }
1764
+ return "verify";
1765
+ };
1750
1766
  const shipGateBlocked = (state, executed, details = {}) => {
1751
1767
  const shipGate = validateShipGate(state);
1752
1768
  const nextAction = primaryShipGateNextAction(shipGate);
1769
+ const recoveryStage = shipGateRecoveryStage(shipGate);
1770
+ const advanceOptions = Array.from(/* @__PURE__ */ new Set([recoveryStage, "verify", "author", "implement", "recon", "ship"]));
1753
1771
  return checkpoint(
1754
1772
  "verify",
1755
1773
  "ship_gate_blocked",
@@ -1757,12 +1775,13 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1757
1775
  {
1758
1776
  ok: false,
1759
1777
  nextActions: ["inspect_ship_gate", "advance_run_to_verify", "supply_proof_assessment_json", "return_to_recon_if_baseline_is_missing"],
1760
- advanceOptions: ["verify", "author", "implement", "recon"],
1761
- recommendedAdvanceStage: "verify",
1762
- continueWithStage: "verify",
1778
+ advanceOptions,
1779
+ recommendedAdvanceStage: recoveryStage,
1780
+ continueWithStage: recoveryStage,
1763
1781
  blocking: true,
1764
- details: { ...details, shipGate, next_action: nextAction, executed },
1782
+ details: { ...details, shipGate, next_action: nextAction, recovery_stage: recoveryStage, executed },
1765
1783
  nextAction,
1784
+ recoveryStage,
1766
1785
  shipGate,
1767
1786
  verifyStatus: state?.verify_status || null,
1768
1787
  mergeRecommendation: state?.merge_recommendation || null,
@@ -4773,6 +4792,20 @@ function checkpointContinueStage2(result) {
4773
4792
  const resume = recordValue(result.checkpointContract?.resume);
4774
4793
  return nonEmptyString(resume?.continue_with_stage);
4775
4794
  }
4795
+ function checkpointRecommendedStage(result) {
4796
+ const resumeStage = checkpointContinueStage2(result);
4797
+ if (resumeStage) return resumeStage;
4798
+ return nonEmptyString(result.checkpointContract?.recommended_advance_stage) || nonEmptyString(result.decisionRequest?.continue_with_stage) || nonEmptyString(result.decisionRequest?.recommended_advance_stage) || nonEmptyString(recordValue(result.decisionRequest)?.continueWithStage) || nonEmptyString(recordValue(result.decisionRequest)?.recommendedAdvanceStage);
4799
+ }
4800
+ function stageCheckpointContinuation(result) {
4801
+ const stage = checkpointRecommendedStage(result);
4802
+ if (!stage) return null;
4803
+ return {
4804
+ action: "run",
4805
+ state_path: String(result.state_path || ""),
4806
+ advance_stage: stage
4807
+ };
4808
+ }
4776
4809
  function recommendedContinuation(result) {
4777
4810
  const continueStage = checkpointContinueStage2(result);
4778
4811
  if (!continueStage) return null;
@@ -4815,6 +4848,18 @@ function defaultStageForProofCheckpointDecision(decision) {
4815
4848
  if (decision === "needs_richer_proof") return "author";
4816
4849
  return null;
4817
4850
  }
4851
+ function checkpointContractFromPacket(packet) {
4852
+ return recordValue(packet.evidence_excerpt?.checkpoint_contract) || recordValue(recordValue(packet.state_excerpt?.stage_decision_request)?.checkpoint_contract) || null;
4853
+ }
4854
+ function stageFromCheckpointResponse(response, packet) {
4855
+ if (response.decision === "needs_recon") return "recon";
4856
+ if (response.decision === "needs_implementation") return "implement";
4857
+ const payload = recordValue(response.payload) || {};
4858
+ const contract = checkpointContractFromPacket(packet);
4859
+ const resume = recordValue(contract?.resume);
4860
+ const stage = response.continue_with_stage || nonEmptyString(payload.continue_with_stage) || nonEmptyString(payload.recommended_stage) || nonEmptyString(resume?.continue_with_stage) || (response.decision === "retry_stage" ? packet.stage : "");
4861
+ return stage ? stage : null;
4862
+ }
4818
4863
  function proofAssessmentPayloadFromCheckpointResponse(response) {
4819
4864
  if (![
4820
4865
  "ready_to_ship",
@@ -4917,6 +4962,13 @@ function visualDeltaEvidenceRecoveryAssessment(state, payload, blocker) {
4917
4962
  blockers: [...blockers, blocker]
4918
4963
  };
4919
4964
  }
4965
+ function isRecoverableStageCheckpoint(checkpoint) {
4966
+ return [
4967
+ "ship_gate_blocked",
4968
+ "verify_required",
4969
+ "verify_supervisor_judgment_required"
4970
+ ].includes(checkpoint);
4971
+ }
4920
4972
  function contextFor(request, state, result) {
4921
4973
  return {
4922
4974
  request,
@@ -5263,6 +5315,18 @@ function checkpointResponseContinuation(state, value) {
5263
5315
  };
5264
5316
  }
5265
5317
  }
5318
+ if (response.decision === "continue_stage" || response.decision === "retry_stage" || response.decision === "needs_implementation") {
5319
+ const stage = stageFromCheckpointResponse(response, packet);
5320
+ if (stage) {
5321
+ appendCheckpointResponse(state, response);
5322
+ return {
5323
+ next: {
5324
+ ...base,
5325
+ advance_stage: stage
5326
+ }
5327
+ };
5328
+ }
5329
+ }
5266
5330
  appendCheckpointResponse(state, response, { clear_packet: false });
5267
5331
  return {
5268
5332
  blocker: {
@@ -5385,18 +5449,23 @@ async function handleImplementation(request, state, result, agent) {
5385
5449
  adapter_details: implementation.details || null
5386
5450
  })
5387
5451
  });
5388
- return {
5389
- blocker: {
5390
- code: "implementation_diff_missing",
5452
+ recordEvent(state, {
5453
+ kind: "agent.implementation.retry_requested",
5454
+ checkpoint: result.checkpoint || null,
5455
+ stage: "implement",
5456
+ summary: "Implementation adapter left no detectable diff; retrying the implement checkpoint inside the bounded loop.",
5457
+ details: compactRecord({
5458
+ worktree_path: workdir || null,
5391
5459
  checkpoint: result.checkpoint || null,
5392
- message: "The implementation adapter returned, but the after worktree has no detectable git diff. The harness will not advance to verify.",
5393
- details: compactRecord({
5394
- worktree_path: workdir || null,
5395
- changed_files: implementation.changedFiles || [],
5396
- tests_run: implementation.testsRun || [],
5397
- implementation_notes: implementation.implementationNotes || null,
5398
- adapter_details: implementation.details || null
5399
- })
5460
+ next_stage: "implement"
5461
+ })
5462
+ });
5463
+ return {
5464
+ next: {
5465
+ action: "run",
5466
+ state_path: String(result.state_path || ""),
5467
+ advance_stage: "implement",
5468
+ implementation_notes: implementation.implementationNotes || implementation.summary || "Implementation adapter returned without a detectable git diff; retry the implement checkpoint."
5400
5469
  }
5401
5470
  };
5402
5471
  }
@@ -5432,16 +5501,32 @@ async function routeCheckpoint(request, state, result, agent, input) {
5432
5501
  terminal: terminalResult(state, "completed", result, result.summary || "Riddle Proof engine completed.")
5433
5502
  };
5434
5503
  }
5504
+ if (isRecoverableStageCheckpoint(checkpoint) && !input.dry_run && !request.dry_run) {
5505
+ if (input.checkpoint_mode === "yield") {
5506
+ return { terminal: checkpointAwaitingResult(state, result, input.checkpoint_visibility) };
5507
+ }
5508
+ const next = stageCheckpointContinuation(result);
5509
+ if (next) {
5510
+ recordEvent(state, {
5511
+ kind: "checkpoint.recovery_continuation",
5512
+ checkpoint,
5513
+ stage: stageFromCheckpoint2(result),
5514
+ summary: `Routing recoverable checkpoint ${checkpoint} back to ${next.advance_stage}.`,
5515
+ details: {
5516
+ next,
5517
+ checkpointContract: result.checkpointContract || null
5518
+ }
5519
+ });
5520
+ return { next };
5521
+ }
5522
+ }
5435
5523
  const failureBlocker = engineFailureBlocker(result, checkpoint);
5436
5524
  if (failureBlocker) {
5437
5525
  return { blocker: failureBlocker };
5438
5526
  }
5439
5527
  if ([
5440
5528
  "recon_human_escalation",
5441
- "verify_human_escalation",
5442
- "ship_gate_blocked",
5443
- "verify_required",
5444
- "verify_supervisor_judgment_required"
5529
+ "verify_human_escalation"
5445
5530
  ].includes(checkpoint) && result.ok === false) {
5446
5531
  return {
5447
5532
  blocker: {
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ import {
32
32
  createDisabledRiddleProofAgentAdapter,
33
33
  readRiddleProofRunStatus,
34
34
  runRiddleProofEngineHarness
35
- } from "./chunk-ALP5KOS2.js";
35
+ } from "./chunk-2RS4PBYK.js";
36
36
  import "./chunk-4ASMX4R6.js";
37
37
  import "./chunk-JFQXAJH2.js";
38
38
  import {
@@ -1745,9 +1745,27 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1745
1745
  }
1746
1746
  return "inspect the ship gate details, repair the missing invariant, then resume the run";
1747
1747
  };
1748
+ const shipGateRecoveryStage = (shipGate) => {
1749
+ const reasons = shipGate.reasons || [];
1750
+ if (reasons.some((reason) => reason.includes("before_cdn") || reason.includes("prod_cdn") || reason.includes("prod_url"))) {
1751
+ return "recon";
1752
+ }
1753
+ if (reasons.some((reason) => reason.includes("implementation"))) {
1754
+ return "implement";
1755
+ }
1756
+ if (reasons.some((reason) => reason.includes("after_cdn") || reason.includes("verify_status") || reason.includes("visual_delta"))) {
1757
+ return "verify";
1758
+ }
1759
+ if (reasons.some((reason) => reason.includes("proof_assessment"))) {
1760
+ return "verify";
1761
+ }
1762
+ return "verify";
1763
+ };
1748
1764
  const shipGateBlocked = (state, executed, details = {}) => {
1749
1765
  const shipGate = validateShipGate(state);
1750
1766
  const nextAction = primaryShipGateNextAction(shipGate);
1767
+ const recoveryStage = shipGateRecoveryStage(shipGate);
1768
+ const advanceOptions = Array.from(/* @__PURE__ */ new Set([recoveryStage, "verify", "author", "implement", "recon", "ship"]));
1751
1769
  return checkpoint(
1752
1770
  "verify",
1753
1771
  "ship_gate_blocked",
@@ -1755,12 +1773,13 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
1755
1773
  {
1756
1774
  ok: false,
1757
1775
  nextActions: ["inspect_ship_gate", "advance_run_to_verify", "supply_proof_assessment_json", "return_to_recon_if_baseline_is_missing"],
1758
- advanceOptions: ["verify", "author", "implement", "recon"],
1759
- recommendedAdvanceStage: "verify",
1760
- continueWithStage: "verify",
1776
+ advanceOptions,
1777
+ recommendedAdvanceStage: recoveryStage,
1778
+ continueWithStage: recoveryStage,
1761
1779
  blocking: true,
1762
- details: { ...details, shipGate, next_action: nextAction, executed },
1780
+ details: { ...details, shipGate, next_action: nextAction, recovery_stage: recoveryStage, executed },
1763
1781
  nextAction,
1782
+ recoveryStage,
1764
1783
  shipGate,
1765
1784
  verifyStatus: state?.verify_status || null,
1766
1785
  mergeRecommendation: state?.merge_recommendation || null,
@@ -781,9 +781,27 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
781
781
  }
782
782
  return "inspect the ship gate details, repair the missing invariant, then resume the run";
783
783
  };
784
+ const shipGateRecoveryStage = (shipGate) => {
785
+ const reasons = shipGate.reasons || [];
786
+ if (reasons.some((reason) => reason.includes("before_cdn") || reason.includes("prod_cdn") || reason.includes("prod_url"))) {
787
+ return "recon";
788
+ }
789
+ if (reasons.some((reason) => reason.includes("implementation"))) {
790
+ return "implement";
791
+ }
792
+ if (reasons.some((reason) => reason.includes("after_cdn") || reason.includes("verify_status") || reason.includes("visual_delta"))) {
793
+ return "verify";
794
+ }
795
+ if (reasons.some((reason) => reason.includes("proof_assessment"))) {
796
+ return "verify";
797
+ }
798
+ return "verify";
799
+ };
784
800
  const shipGateBlocked = (state, executed, details = {}) => {
785
801
  const shipGate = validateShipGate(state);
786
802
  const nextAction = primaryShipGateNextAction(shipGate);
803
+ const recoveryStage = shipGateRecoveryStage(shipGate);
804
+ const advanceOptions = Array.from(/* @__PURE__ */ new Set([recoveryStage, "verify", "author", "implement", "recon", "ship"]));
787
805
  return checkpoint(
788
806
  "verify",
789
807
  "ship_gate_blocked",
@@ -791,12 +809,13 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
791
809
  {
792
810
  ok: false,
793
811
  nextActions: ["inspect_ship_gate", "advance_run_to_verify", "supply_proof_assessment_json", "return_to_recon_if_baseline_is_missing"],
794
- advanceOptions: ["verify", "author", "implement", "recon"],
795
- recommendedAdvanceStage: "verify",
796
- continueWithStage: "verify",
812
+ advanceOptions,
813
+ recommendedAdvanceStage: recoveryStage,
814
+ continueWithStage: recoveryStage,
797
815
  blocking: true,
798
- details: { ...details, shipGate, next_action: nextAction, executed },
816
+ details: { ...details, shipGate, next_action: nextAction, recovery_stage: recoveryStage, executed },
799
817
  nextAction,
818
+ recoveryStage,
800
819
  shipGate,
801
820
  verifyStatus: state?.verify_status || null,
802
821
  mergeRecommendation: state?.merge_recommendation || null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.5.47",
3
+ "version": "0.5.48",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",