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

Ralph Loop 2026-03-16: Unmatched Semantic Blockers

Why

The prior no_semantic_sleeve_match fix stopped mislabeling unmatched rows as belonging to an arbitrary sleeve, but the live packet still summarized those rows using only the “least bad” sleeve blockers. That made unmatched Elections and other out-of-sleeve rows look like simple price-band misses instead of a sleeve-coverage gap.

Change

  1. Updated research/candidate_review.py so unmatched rows now carry semantic_invalidation_reasons, derived from semantic blockers across all sleeve checks.
  2. Added candidate-review summary fields for unmatched_semantic_sleeve_count and top_unmatched_semantic_invalidation_reasons.
  3. Extended the loop event payload and both human/Discord status renderers so Ralph can see unmatched semantic bottlenecks directly.
  4. 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 - 18 passed in 0.10s
  2. python3 main.py research-status - Candidate review now reports unmatched_semantic=17 - Top unmatched semantic blockers are market_family!=threshold=17, model_source!=threshold_ladder=17, signal_action!=review=17 - The top research candidate now includes semantic_blockers=category!=Economics, category!=Politics, market_family!=threshold, model_source!=threshold_ladder, signal_action!=review

Outcome

Ralph can now distinguish “this row belongs to the wrong sleeve family entirely” from “this sleeve almost fits but failed on price or tradeability.” That improves candidate-review quality without lowering the deployment gate or changing trade selection logic.