Skip to content

fix(polymarket-release): gate contained bootstrap recovery - #644

Merged
proerror77 merged 1 commit into
mainfrom
codex/polymarket-recovery-gate-637
Aug 3, 2026
Merged

fix(polymarket-release): gate contained bootstrap recovery#644
proerror77 merged 1 commit into
mainfrom
codex/polymarket-recovery-gate-637

Conversation

@proerror77

@proerror77 proerror77 commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Change contract

Add one candidate-only recover Gate for a verified, contained direct Rust bootstrap baseline after the known Gamma tagged-500 failure. Admission binds the stopped baseline, exact candidate probe, inactive uploader/timer units, existing 900-second Gate, real-market preflight, OSS readback, immutable receipt, cutover, and rollback.

Issue relationship

Closes #637

Out of scope

Runtime rollout #632; deployment; collector or uploader restart; OSS cleanup; uploader behavior changes; Gamma failure-policy changes; research work; execution runtime.

Dependencies and merge order

None.

Focused validation

  • cargo test -p hft-collector --locked closed_discovery_500_retries_then_falls_back_without_the_crypto_tag
  • cargo test -p hft-collector --locked untagged_gamma_fallback_requires_a_closed_final_500
  • PATH=/opt/homebrew/opt/coreutils/libexec/gnubin:$PATH bash deployment/aliyun/test-polymarket-raw-ops-control-plane.sh
  • bash -n for changed shell scripts; jq -n -f deployment/aliyun/polymarket-shadow-gate-policy.jq; git diff --check; .github/scripts/agent-worktree-preflight.sh check
  • Refusal coverage: active baseline, active uploader/timer, wrong ExecStart, stale/missing probe, candidate-SHA mismatch, and baseline identity drift.

Rollout and rollback

Merge publishes control-plane code only. No runtime action occurs from this PR; #632 retains rollout authority. Revert this commit to remove the recovery control path; a governed runtime recovery retains its own transactional rollback receipt.

Scope exception

This is an inseparable 5-file, 988 non-generated-line fail-closed safety contract. Controller admission, Gate/policy receipt evidence, cutover/rollback behavior, and contract tests cannot be independently merged or safely rolled back. Named review approval: standards_review (Codex Standards Review).

Summary by CodeRabbit

  • New Features

    • Added a controlled recovery path for degraded deployments.
    • Recovery checks now validate candidate integrity, source identity, baseline services, and recent probe results.
    • Recovery metadata is carried through deployment admission and recorded in cutover evidence.
  • Bug Fixes

    • Improved rollback handling for contained recoveries without unnecessarily restarting preserved services.
    • Added safeguards to detect unexpected collector or journal restarts and prevent unsafe promotion.
  • Tests

    • Expanded coverage for recovery admission, validation, rollback, service containment, and failure scenarios.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds a contained Rust bootstrap recovery path. It validates candidate probes, baseline identity, systemd state, and uploader containment. Gate, policy, cutover, rollback, evidence, and control-plane tests now support recovery metadata.

Changes

Contained bootstrap recovery

Layer / File(s) Summary
Recovery admission and Gate request
deployment/aliyun/polymarket-raw-ops-gate-control.sh
Adds the recover command, validates the candidate-bound Gamma probe and stopped baseline, checks uploader units, and writes recovery metadata into the Gate request.
Recovery Gate validation and evidence
deployment/aliyun/polymarket-raw-ops-shadow-gate.sh, deployment/aliyun/polymarket-shadow-gate-policy.jq
Adds recovery evidence validation, contained baseline selection, recovery-specific policy branches, and separate recovery or legacy runtime evidence output.
Recovery cutover and rollback
deployment/aliyun/polymarket-raw-ops-cutover.sh
Consumes recovery evidence, validates the baseline before promotion, persists recovery state, skips incompatible legacy checks, and restores inactive saved units without restarting the collector.
Recovery fixtures and contract tests
deployment/aliyun/test-polymarket-raw-ops-control-plane.sh
Adds systemd fixtures, successful recovery admission tests, refusal cases, policy fixtures, and cutover ordering checks.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant GateControl
  participant ShadowGate
  participant Cutover
  participant Rollback
  Operator->>GateControl: submit recover command
  GateControl->>ShadowGate: start Gate with recovery metadata
  ShadowGate->>ShadowGate: validate probe, baseline, and uploader state
  ShadowGate->>Cutover: emit recovery evidence
  Cutover->>Cutover: validate contained baseline and promote candidate
  Cutover->>Rollback: persist recovery state for rollback
  Rollback->>Cutover: restore inactive units without restarting collector
Loading

Possibly related issues

  • proerror77/monday#632 — Covers the same recovery-aware Gate, cutover, and rollback control-plane behavior.
  • proerror77/monday#627 — Covers contained recovery admission, evidence, rollback, and regression tests.
  • proerror77/monday#631 — Covers bounded bootstrap recovery admission and supervised cutover behavior.
  • proerror77/monday#636 — Covers the contained degraded-bootstrap recovery path across Gate, policy, cutover, rollback, and tests.
  • proerror77/monday#499 — Covers the same Polymarket Rust deployment Gate, cutover, rollback, and policy paths.

Possibly related PRs

  • proerror77/monday#29 — Extends the same Rust collector cutover and Gate control-plane scripts with recovery handling.
  • proerror77/monday#44 — Modifies the same cutover and shadow-Gate validation paths with runtime identity and restart safeguards.
  • proerror77/monday#629 — Extends the rust_bootstrap recovery path across cutover, Gate control, policy, and rollback.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue [#637] by implementing candidate-only recovery admission, evidence binding, validation, transactional rollback, and focused tests.
Out of Scope Changes check ✅ Passed The changes remain within the linked recovery-control objective and do not add runtime rollout, deployment, restart, cleanup, or unrelated behavior changes.
Title check ✅ Passed The title clearly identifies the main change: gating contained bootstrap recovery for the Polymarket release.
Description check ✅ Passed The description includes all required sections and clearly documents scope, validation, dependencies, rollout, rollback, and the safety-contract exception.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/polymarket-recovery-gate-637

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@proerror77
proerror77 force-pushed the codex/polymarket-recovery-gate-637 branch from 33600d2 to 5f186c2 Compare August 3, 2026 03:16

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
deployment/aliyun/polymarket-raw-ops-cutover.sh (1)

1265-1294: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Move the saved-unit precondition before the destructive restore steps.

The guard at Line 1266 rejects a rollback whose snapshot recorded an active collector or timer. It runs after restore_legacy already stopped units, reinstalled unit files, and reinstalled the active binary at Line 1150 through Line 1263. A refusal therefore leaves a partially mutated host.

Evaluate the same jq -e check right after contained_recovery is read at Line 1127. Keep the post-transition assertions at Line 1283 through Line 1291 where they are.

♻️ Proposed placement
   contained_recovery=$(jq -er \
     '(.contained_recovery // false) | select(type == "boolean") | tostring' \
     "$rollback_dir/state.json") \
     || die 'rollback snapshot has no valid contained recovery state'
+  if [[ $contained_recovery == true ]]; then
+    jq -e --arg collector "$COLLECTOR_UNIT" --arg reference_timer "$REFERENCE_UPLOAD_TIMER" \
+      --arg market_timer "$MARKET_UPLOAD_TIMER" '
+        .units[$collector].active == false
+        and .units[$reference_timer].active == false
+        and .units[$market_timer].active == false
+      ' "$rollback_dir/state.json" >/dev/null \
+      || die 'contained recovery rollback would restart a saved baseline unit'
+  fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deployment/aliyun/polymarket-raw-ops-cutover.sh` around lines 1265 - 1294,
Move the saved-unit activity precondition from the start of the
contained_recovery restore block to immediately after contained_recovery is
read, before restore_legacy or any other destructive restore operations.
Preserve the existing jq check and failure message, and keep the post-transition
assertions and state verification in the contained recovery block unchanged.
deployment/aliyun/polymarket-shadow-gate-policy.jq (1)

64-95: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Consider binding the probe timestamp to the Gate window in the policy.

contained_bootstrap_recovery validates the probe format and the baseline identity. It does not relate .candidate_probe.observed_at to .started_at. The 900-second freshness bound exists only in the shell admission checks, so the immutable receipt cannot be re-verified for staleness later.

Add an ordering and lag predicate so the receipt proves freshness on its own.

♻️ Proposed addition to recovery_matches_gate
 def recovery_matches_gate:
   . as $gate
   | ($gate.recovery | contained_bootstrap_recovery(
-      $gate.candidate_sha256; $gate.deployment_source_revision));
+      $gate.candidate_sha256; $gate.deployment_source_revision))
+  and (($gate.recovery.candidate_probe.observed_at | utc_iso8601_unix) as $observed
+    | ($gate.started_at | utc_iso8601_unix) as $started
+    | $observed <= $started and ($started - $observed) <= 900);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deployment/aliyun/polymarket-shadow-gate-policy.jq` around lines 64 - 95,
Update recovery_matches_gate and its contained_bootstrap_recovery validation to
bind candidate_probe.observed_at to the gate's started_at, requiring the
observation timestamp to be no earlier than the gate start and no more than 900
seconds later. Ensure the timestamp is parsed consistently with the existing
utc_iso8601_unix handling so the immutable receipt independently proves
freshness.
deployment/aliyun/test-polymarket-raw-ops-control-plane.sh (1)

4048-4060: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add drift cases for the recovery-specific exclusivity rules.

The table covers candidate binding, source binding, baseline state, and runtime stability. Three predicates that gate the new branch have no counterexample: a null .recovery, a non-null .legacy_runtime, and a .recovery.baseline.binary_sha256 equal to the candidate. The coding guidelines require a targeted counterexample test for safety boundaries.

If you adopt the probe-freshness predicate suggested for deployment/aliyun/polymarket-shadow-gate-policy.jq, also derive observed_at at Line 4034 from .started_at instead of the fixed literal.

As per coding guidelines: "Safety boundaries require a targeted counterexample test, not only workspace compilation."

💚 Proposed additional drift rows
 candidate_binding|.recovery.candidate_probe.candidate_sha256 = (if .candidate_sha256 == ("0" * 64) then ("1" * 64) else ("0" * 64) end)
 source_binding|.recovery.candidate_probe.source_revision = (if .deployment_source_revision == ("0" * 40) then ("1" * 40) else ("0" * 40) end)
 baseline_active|.recovery.baseline.active_state = "active"
 runtime_stability|.baseline_runtime_stability_required = true
+missing_recovery|.recovery = null
+baseline_is_candidate|.recovery.baseline.binary_sha256 = .candidate_sha256
+legacy_runtime_present|.legacy_runtime = {exec_start:"/opt/monday/bin/polymarket-raw-ops collect-reference --max-trade-polls-per-cycle 200"}
 EOF
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deployment/aliyun/test-polymarket-raw-ops-control-plane.sh` around lines 4048
- 4060, Add targeted drift rows to the recovery-policy loop for null .recovery,
non-null .legacy_runtime, and .recovery.baseline.binary_sha256 matching the
candidate value, ensuring each predicate’s safety boundary is exercised. If the
policy also introduces probe freshness, update the observed_at derivation near
the recovery fixture setup to use .started_at rather than a fixed literal.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deployment/aliyun/polymarket-raw-ops-shadow-gate.sh`:
- Around line 1341-1343: Change both `.recovery` reads in
deployment/aliyun/polymarket-raw-ops-shadow-gate.sh:1341-1343 and
deployment/aliyun/polymarket-raw-ops-cutover.sh:1672-1673 from `jq -ce` to `jq
-c`, preserving the `// null` fallback so optional recovery values produce
literal `null` without failing. Keep the existing `[[ $recovery_json != null ]]`
branching and recovery validation behavior unchanged.

In `@deployment/aliyun/test-polymarket-raw-ops-control-plane.sh`:
- Around line 434-437: Update the comment preceding the recovery admission call
in the test script by removing the sentence claiming it is intentionally red
until `recover` is implemented; retain the contract description about the
stopped bootstrap identity, fresh candidate probe, and contained
uploaders/timers.

---

Nitpick comments:
In `@deployment/aliyun/polymarket-raw-ops-cutover.sh`:
- Around line 1265-1294: Move the saved-unit activity precondition from the
start of the contained_recovery restore block to immediately after
contained_recovery is read, before restore_legacy or any other destructive
restore operations. Preserve the existing jq check and failure message, and keep
the post-transition assertions and state verification in the contained recovery
block unchanged.

In `@deployment/aliyun/polymarket-shadow-gate-policy.jq`:
- Around line 64-95: Update recovery_matches_gate and its
contained_bootstrap_recovery validation to bind candidate_probe.observed_at to
the gate's started_at, requiring the observation timestamp to be no earlier than
the gate start and no more than 900 seconds later. Ensure the timestamp is
parsed consistently with the existing utc_iso8601_unix handling so the immutable
receipt independently proves freshness.

In `@deployment/aliyun/test-polymarket-raw-ops-control-plane.sh`:
- Around line 4048-4060: Add targeted drift rows to the recovery-policy loop for
null .recovery, non-null .legacy_runtime, and .recovery.baseline.binary_sha256
matching the candidate value, ensuring each predicate’s safety boundary is
exercised. If the policy also introduces probe freshness, update the observed_at
derivation near the recovery fixture setup to use .started_at rather than a
fixed literal.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 62edcfd0-90c1-4505-8b67-e6bbd283c82c

📥 Commits

Reviewing files that changed from the base of the PR and between bbeb592 and 33600d2.

📒 Files selected for processing (5)
  • deployment/aliyun/polymarket-raw-ops-cutover.sh
  • deployment/aliyun/polymarket-raw-ops-gate-control.sh
  • deployment/aliyun/polymarket-raw-ops-shadow-gate.sh
  • deployment/aliyun/polymarket-shadow-gate-policy.jq
  • deployment/aliyun/test-polymarket-raw-ops-control-plane.sh

Comment thread deployment/aliyun/polymarket-raw-ops-shadow-gate.sh Outdated
Comment thread deployment/aliyun/test-polymarket-raw-ops-control-plane.sh Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 33600d24a9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread deployment/aliyun/polymarket-raw-ops-cutover.sh Outdated
Comment thread deployment/aliyun/polymarket-raw-ops-shadow-gate.sh Outdated
Comment thread deployment/aliyun/polymarket-raw-ops-cutover.sh Outdated
@proerror77
proerror77 force-pushed the codex/polymarket-recovery-gate-637 branch from 5f186c2 to b032423 Compare August 3, 2026 04:10
@proerror77
proerror77 merged commit 1067325 into main Aug 3, 2026
53 checks passed
@proerror77
proerror77 deleted the codex/polymarket-recovery-gate-637 branch August 3, 2026 04:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(polymarket-release): add verified candidate-only recovery Gate

1 participant