Ralph Loop 2026-03-16: Candidate Review State Blockers
Change
Bounded PRD-003 improvement: candidate-review diagnostics now split blocker tallies by candidate state.
Added fields:
top_review_candidate_invalidation_reasonstop_research_candidate_invalidation_reasons
These sit alongside the existing combined, local, and global blocker tallies. The point is to separate:
- live rows that are already review-worthy but blocked by the loop-level deployment gate
- rows that are still mostly sleeve-mismatch research candidates
Without this split, a summary dominated by research-candidate sleeve mismatches could hide the fact that review candidates are mainly blocked by global replay confidence.
Files changed
research/candidate_review.pyresearch/continuous_loop.pyresearch/status.pyresearch/discord_status.pyresearch/README.mdtests/test_candidate_review.pytests/test_continuous_loop.pytests/test_research_status.py
Validation
Focused tests:
pytest tests/test_candidate_review.py -q
pytest tests/test_continuous_loop.py -q
pytest tests/test_research_status.py -q
Observed:
6 passedintests/test_candidate_review.py3 passedintests/test_continuous_loop.py8 passedintests/test_research_status.py
Operator smoke:
python3 main.py research-status --json | rg -n "top_review_candidate_invalidation_reasons|top_research_candidate_invalidation_reasons" -n -C 1
Observed on March 16, 2026:
research-status --jsonemitted both new fields in the live packet- the packet still showed
deployment_gate_ready: false, so this change did not relax the hard deployment gate
Why this is useful
The current loop is still blocked globally by weak replay metrics. This patch makes that explicit for review candidates while separately showing that the research-candidate pool is dominated by local sleeve mismatch blockers. That is better candidate-review signal quality without changing trading behavior.