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

Ralph Loop 2026-03-16: Matched Research Blockers

Why

research/latest_state.json and python3 main.py research-status were already splitting unmatched semantic inventory from the live packet, but the aggregate research_blockers tally still mixed those unmatched rows with semantically valid research rows.

In the current live packet that meant 15 unmatched rows dominated the research blocker summary with heuristic_direction=neutral, live_price<0.7, and category!=Economics, while the 3 semantically valid politics_eventful_reversal rows were only visible by drilling into the individual top candidate.

Change

  1. Updated research/candidate_review.py to expose: - matched_research_candidate_count - top_matched_research_candidate_invalidation_reasons
  2. Updated research/continuous_loop.py so candidate_review_done events carry the top matched-research blocker.
  3. Updated research/status.py and research/discord_status.py so operator summaries show matched_research and matched_research_blockers.
  4. Documented the new diagnostic in research/README.md.
  5. Added regression coverage in tests/test_candidate_review.py, tests/test_continuous_loop.py, and tests/test_research_status.py.

Validation

  1. pytest -q tests/test_candidate_review.py tests/test_continuous_loop.py tests/test_research_status.py - 33 passed in 0.12s
  2. python3 -m py_compile research/candidate_review.py research/continuous_loop.py research/status.py research/discord_status.py
  3. python3 research/candidate_review.py --db data/unicorn.db --recent-runs 6 --max-per-state 5 - matched_research_candidate_count=3 - top_matched_research_candidate_invalidation_reasons=[["pair_eventful=false", 3], ["abs_move_bps<100.0", 3], ["tradeability_score<0.9", 1]]
  4. python3 main.py research-status | rg -n "candidate review:|top research candidate:" -A 1 - Status now reports matched_research=3 - Status now reports matched_research_blockers=pair_eventful=false=3, abs_move_bps<100.0=3, tradeability_score<0.9=1

Result

Ralph can now distinguish “the research queue is mostly semantically uncovered inventory” from “the small set of semantically valid sleeves are repeatedly failing on pair_eventful and move-size gates.” That is a narrower PRD-003 signal for the next bounded sleeve or observation change.