fix(polymarket): admit failed-state containment in recovery gate admission - #752
Conversation
…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
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughRecovery now handles eligible ChangesGoverned 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
Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (2)
deployment/aliyun/polymarket-raw-ops-gate-control.shdeployment/aliyun/test-polymarket-raw-ops-control-plane.sh
- 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
Change contract
recoverindeployment/aliyun/polymarket-raw-ops-gate-control.shadmitted onlyinactiveunits and refusedfailedones — the modal post-incident containment state — leaving no governed path forward except manualsystemctl reset-failedoutside the control lock. This PR makes one behavior change: recovery admission now acceptsinactiveorfailed(withMainPID == 0and every exact-identity check unchanged), performs a governedsystemctl reset-failedfor failed units insideCONTROL_LOCK, re-reads every snapshot field post-reset so the recorded baseline snapshot staysinactive(downstream binding predicates in shadow-gate/policy/cutover keep their exact"inactive"contract untouched), serializes admission by takingCONTROL_LOCKat the top ofrecover_gate, and writes an immutablerecovery-admission.json(schemamonday.polymarket_gate_recovery_admission.v1: admitted/refused, exact candidate/baseline/probe identities, refusal reason, reset units) under the gate evidence root on everyrecoverinvocation. Follows thehost-rust-lob-restore.shprecedent perdocs/reports/2026-08-08-polymarket-raw-ops-gate-recover-known-issue.md.Issue relationship
Refs #748
Out of scope
polymarket-raw-ops-shadow-gate.sh,polymarket-raw-ops-cutover.sh, gate policy, or README.Dependencies and merge order
None
Focused validation
bash -nandshellcheckclean on both touched scripts../deployment/aliyun/test-polymarket-raw-ops-control-plane.shpasses in full (Polymarket raw-ops control-plane tests passed, exit 0). New harness coverage:failedbaseline is admitted after a governedreset-failed; the recorded snapshot readsactive_state == "inactive",main_pid == 0,restarts == 0(post-reset re-read);reset-failed;systemctl reset-failedexits 9 unless the caller holdsCONTROL_LOCK, proving reset happens only inside the lock; aninactiveadmission performs noreset-failed;recovery-admission.jsonwith exact identities and reason, asserted via jq;active/activating/deactivatingbaselines, 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.date(date -d); unmodifiedorigin/mainharness fails identically without agdateshim, so this is a pre-existing environment gap, not a regression. Production/CI are Linux.git diff --checkclean.reset-failedcannot reachinactiveis 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
Tests