Skip to content

fix(polymarket): admit failed-state containment in recovery gate admission - #752

Merged
proerror77 merged 6 commits into
mainfrom
codex/pm-gate-recover-failed-admission-748
Aug 8, 2026
Merged

fix(polymarket): admit failed-state containment in recovery gate admission#752
proerror77 merged 6 commits into
mainfrom
codex/pm-gate-recover-failed-admission-748

Conversation

@proerror77

@proerror77 proerror77 commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Change contract

recover in deployment/aliyun/polymarket-raw-ops-gate-control.sh admitted only inactive units and refused failed ones — the modal post-incident containment state — leaving no governed path forward except manual systemctl reset-failed outside the control lock. This PR makes one behavior change: recovery admission now accepts inactive or failed (with MainPID == 0 and every exact-identity check unchanged), performs a governed systemctl reset-failed for failed units inside CONTROL_LOCK, re-reads every snapshot field post-reset so the recorded baseline snapshot stays inactive (downstream binding predicates in shadow-gate/policy/cutover keep their exact "inactive" contract untouched), serializes admission by taking CONTROL_LOCK at the top of recover_gate, and writes an immutable recovery-admission.json (schema monday.polymarket_gate_recovery_admission.v1: admitted/refused, exact candidate/baseline/probe identities, refusal reason, reset units) under the gate evidence root on every recover invocation. Follows the host-rust-lob-restore.sh precedent per docs/reports/2026-08-08-polymarket-raw-ops-gate-recover-known-issue.md.

Issue relationship

Refs #748

Out of scope

Dependencies and merge order

None

Focused validation

  • bash -n and shellcheck clean on both touched scripts.
  • ./deployment/aliyun/test-polymarket-raw-ops-control-plane.sh passes in full (Polymarket raw-ops control-plane tests passed, exit 0). New harness coverage:
    • a failed baseline is admitted after a governed reset-failed; the recorded snapshot reads active_state == "inactive", main_pid == 0, restarts == 0 (post-reset re-read);
    • each of the four failed uploader units/timers is admitted individually after a governed reset-failed;
    • the fake systemctl reset-failed exits 9 unless the caller holds CONTROL_LOCK, proving reset happens only inside the lock; an inactive admission performs no reset-failed;
    • both admitted and refused invocations write recovery-admission.json with exact identities and reason, asserted via jq;
    • regression: active/activating/deactivating baselines, stuck post-reset state (FAKE_RESET_FAILED_STUCK), active uploaders, and all pre-existing refusal cases (stale/missing/wrong-candidate probe, ExecStart drift) still refuse; the no-start/stop/restart/enable/disable mutation guard is preserved.
  • Environment note: on macOS the harness requires GNU date (date -d); unmodified origin/main harness fails identically without a gdate shim, so this is a pre-existing environment gap, not a regression. Production/CI are Linux.
  • git diff --check clean.
  • Safety boundary counterexample: a failed unit whose governed reset-failed cannot reach inactive is still refused (fail-closed), with durable refused evidence.

Rollout and rollback

None — repo-only change to the control-plane script and its harness. Production application is a separately authorized cutover. Rollback: revert this commit; the previous inactive-only admission is fail-closed.

Scope exception

None

Summary by CodeRabbit

  • Bug Fixes

    • Recovery now safely handles failed system services by resetting them and confirming they become inactive.
    • Recovery continues to reject active, transitioning, managed, or unrecoverable services.
    • Recovery records admission and refusal outcomes, including diagnostic details, and preserves evidence when recovery fails.
    • Recovery protection remains active throughout admission and startup.
  • Tests

    • Expanded coverage for service-specific states, guarded resets, recovery verification, refusal records, and cleanup behavior.

…ssion

recover refused failed-state baseline/uploader units even though a
failed unit is fully contained (no managed process, restart budget
exhausted), forcing ungoverned manual reset-failed outside the control
lock during incident response.

Admit inactive or failed units: failed units receive a governed
systemctl reset-failed inside CONTROL_LOCK with every snapshot field
re-read post-reset, so the recorded baseline snapshot stays inactive
and all downstream binding predicates keep their exact contract.
recover now takes CONTROL_LOCK before admission reads and writes an
immutable recovery-admission.json (admitted/refused, exact identities,
refusal reason, reset units) under the gate evidence root on every
invocation, mirroring the host-rust-lob-restore recovery.json bar.

Refs #748
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4c9cad37-178e-4822-9591-d9e6e348bd54

📥 Commits

Reviewing files that changed from the base of the PR and between 30e6481 and 61fd1c4.

📒 Files selected for processing (2)
  • deployment/aliyun/polymarket-raw-ops-gate-control.sh
  • deployment/aliyun/test-polymarket-raw-ops-control-plane.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • deployment/aliyun/polymarket-raw-ops-gate-control.sh

📝 Walkthrough

Walkthrough

Recovery now handles eligible failed systemd units with lock-protected reset-failed calls. It records admission and refusal evidence, preserves failure details, and expands tests for per-uploader state and recovery outcomes.

Changes

Governed recovery

Layer / File(s) Summary
Failed-unit recovery
deployment/aliyun/polymarket-raw-ops-gate-control.sh
Recovery validates process and unit identity, resets eligible failed units, verifies inactive state, and records reset units.
Admission evidence and lock handling
deployment/aliyun/polymarket-raw-ops-gate-control.sh
Recovery writes probe, baseline, outcome, refusal reason, and reset details. It preserves failures before cleanup and retains the control lock through Gate startup.
Per-uploader fixtures and recovery tests
deployment/aliyun/test-polymarket-raw-ops-control-plane.sh
The fixture models unit-specific state and governed resets. Tests cover refusal records, immutable evidence, reset behavior, post-reset state, and inactive recovery.

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

Sequence Diagram(s)

sequenceDiagram
  participant RecoveryCommand
  participant Systemd
  participant EvidenceStore
  participant Gate
  RecoveryCommand->>Systemd: Probe collector and uploader units
  RecoveryCommand->>Systemd: Reset eligible failed units under the control lock
  Systemd-->>RecoveryCommand: Return post-reset inactive state
  RecoveryCommand->>EvidenceStore: Write admission or refusal evidence
  RecoveryCommand->>Gate: Start Gate while retaining the control lock
Loading

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: admitting failed-state containment during recovery gate admission.
Description check ✅ Passed The description includes all required template sections and provides specific behavior, validation, safety boundaries, dependencies, and rollback details.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/pm-gate-recover-failed-admission-748

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 enabled auto-merge (squash) August 8, 2026 06:07

@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: 4

🤖 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-gate-control.sh`:
- Around line 681-688: Validate unit containment before resetting failure state:
in deployment/aliyun/polymarket-raw-ops-gate-control.sh lines 681-688, require
MainPID == 0 and the existing exact collector identity before systemctl
reset-failed; in lines 739-746, reject uploader units with nonzero MainPID
before reset-failed. In
deployment/aliyun/test-polymarket-raw-ops-control-plane.sh lines 576-627, add
failed collector and uploader cases with nonzero MainPID and assert that no
reset occurs.
- Around line 766-779: The admission writer around the recovery-admission JSON
creation must stop force-replacing a fixed filename; create a distinct,
non-replaceable record for every invocation while preserving immutable evidence.
Update deployment/aliyun/polymarket-raw-ops-gate-control.sh lines 766-779
accordingly. Extend deployment/aliyun/test-polymarket-raw-ops-control-plane.sh
lines 494-511 to perform two admissions or refusals for one candidate and verify
the first record remains available and unchanged.
- Around line 807-808: Make deployment/aliyun/polymarket-raw-ops-gate-control.sh
fail closed when flock acquisition after exec 9 fails at lines 807-808. In the
start_gate call path at lines 827-833, preserve the inherited descriptor 9 lock
through Gate start and remove the reopen/close behavior that releases it before
systemctl start.

In `@deployment/aliyun/test-polymarket-raw-ops-control-plane.sh`:
- Around line 176-182: Update uploader_state_file to always return the
unit-specific uploader-active-$1 state path, removing the shared uploader-active
fallback. Modify test setup to create a state file for every uploader unit so
missing per-uploader fixture state is exposed rather than silently substituted.
🪄 Autofix

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: 16478d89-011f-48eb-8f60-552bfcbcbea3

📥 Commits

Reviewing files that changed from the base of the PR and between d0f9fc9 and 30e6481.

📒 Files selected for processing (2)
  • deployment/aliyun/polymarket-raw-ops-gate-control.sh
  • deployment/aliyun/test-polymarket-raw-ops-control-plane.sh

Comment thread deployment/aliyun/polymarket-raw-ops-gate-control.sh Outdated
Comment thread deployment/aliyun/polymarket-raw-ops-gate-control.sh Outdated
Comment thread deployment/aliyun/polymarket-raw-ops-gate-control.sh Outdated
Comment thread deployment/aliyun/test-polymarket-raw-ops-control-plane.sh Outdated
proerror77 and others added 3 commits August 8, 2026 14:56
- Prove containment and exact identity before any governed reset-failed:
  read_baseline_identity runs before the collector reset and again after
  it, and failed uploader units are refused on nonzero MainPID before
  their reset; new harness cases assert no reset-failed is issued for
  failed units that still have a managed process.
- Publish each recover admission as a distinct content-addressed
  recovery-admission-<sha256>.json via hard-link publish that never
  replaces an existing record; the harness proves a second refusal
  leaves the first record available and unchanged.
- Make recover's CONTROL_LOCK flock fail closed and keep the lock
  continuously through start_gate (no fd 9 release/reacquire window
  between admission and gate start); standalone start keeps its own
  fail-closed lock.
- Remove the shared uploader-state fallback from the harness fake
  systemctl; every uploader unit gets its own ActiveState/MainPID state
  file in test setup.

Refs #748
@proerror77
proerror77 merged commit ede9aca into main Aug 8, 2026
45 checks passed
@proerror77
proerror77 deleted the codex/pm-gate-recover-failed-admission-748 branch August 8, 2026 08:03
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.

1 participant