pam ▸ docs/generated/ralph_loop_2026-03-16_candidate_review_gate_fix.md
updated 2026-03-28

Ralph Loop 2026-03-16: Candidate Review Gate Fix

Change

Tightened PRD 003 candidate-review classification so research-sleeve actions are no longer labeled deployable_trade unless both of these are true:

  1. the row itself clears the hard edge gate (live_edge_bps >= minimum_edge_bps)
  2. the current loop-level deployment gate is ready (confidence.confident == true)

When either gate fails, the row now stays in review_candidate and records explicit deployment blockers such as live_edge_bps<100.0 and global:score<5.0.

Files: - research/candidate_review.py - research/continuous_loop.py - research/status.py - research/discord_status.py - research/README.md - tests/test_candidate_review.py

Why

The previous packet was overstating live readiness. Politics midprice rows with only 25 bps of modeled edge were being emitted as deployable_trade purely because the research sleeve returned a non-watch action.

That violated the hard deployment gate in PRD 003 and made the status output look more live-ready than the replay confidence justified.

Result

Focused smoke on current data now shows:

This keeps current live rows visible for review without blurring them into tradable output.

Validation

Commands run:

pytest -q tests/test_candidate_review.py tests/test_research_status.py
python3 -m py_compile research/candidate_review.py research/continuous_loop.py research/status.py research/discord_status.py
python3 research/candidate_review.py --db data/unicorn.db --recent-runs 6 --max-per-state 3
python3 research/status.py
python3 research/discord_status.py

Observed behavior:

  1. 5 passed on the focused research status and candidate-review tests.
  2. Candidate-review smoke no longer emits any deployable_trades while the loop confidence gate is false.
  3. Human and Discord summaries now report gate_ready=False and show the review candidate’s deployment blockers.

Next bottleneck

The status output still reflects a stale loop snapshot next to a fresher current replay check. The next bounded change should tighten freshness semantics so latest_state.json carries an explicit age or freshness warning for candidate-review and replay handoff consumers.