Dumb OMO commit

This commit is contained in:
2026-09-01 18:44:42 -04:00
parent 676a0b77fc
commit 4242373576
5 changed files with 171 additions and 2 deletions
+21
View File
@@ -188,3 +188,24 @@ _Auto-scaffolded by /start-work. Append new entries below - never overwrite._
DB column — a direct hand-written match keeps the DB layer decoupled
from `news_core`'s serde attribute and makes the two directions
symmetric and easy to audit).
## F2/F3 final-wave fixes — cold-start percentile rule
- **Cold-start rule for trailing-window percentile ranks**: the draft specifies
a cold-start fallback only for the relevance *score* (BM25-only until 20
feedback samples; `.omo/drafts/news-triage.md:45`), not for percentile ranks.
When `PercentileTracker::percentile_rank` returns `StoreError::InsufficientData`
because the trailing 7-day window is empty, the scheduler maps it to `0.0`
with a one-line `tracing::info!` log.
- **Rationale**: conservative gate behavior. With percentile ranks at 0.0, no
story can meet the notify threshold (relevance @ p90) or digest band
[75, 90) until the window has data, preventing bogus batch-local
percentiles from driving decisions. The breaking-news bypass lane
(`source_count >= 2` or importance @ p99) is unaffected: corroboration bypass
is percentile-independent, and the importance percentile uses its own
distribution.
- **JSON boundary for blocklist veto**: `StoryRow.relevance` is `Option<f64>`,
mapped with `relevance.is_finite().then_some(relevance)`. This keeps the
`f64::NEG_INFINITY` sentinel inside the backend scorer while serializing
honestly as JSON `null` at the API boundary. `importance` remains `f64`
because it is finite by construction (multi-hot arithmetic, no veto path).