Skip to content

Stop NaN/Inf Phoenix heads from poisoning For You rank - #192

Closed
Pitchfork-and-Torch wants to merge 1 commit into
xai-org:mainfrom
Pitchfork-and-Torch:cursor/nan-inf-rank-feature-fail-open-cbe1
Closed

Stop NaN/Inf Phoenix heads from poisoning For You rank#192
Pitchfork-and-Torch wants to merge 1 commit into
xai-org:mainfrom
Pitchfork-and-Torch:cursor/nan-inf-rank-feature-fail-open-cbe1

Conversation

@Pitchfork-and-Torch

@Pitchfork-and-Torch Pitchfork-and-Torch commented Sep 8, 2026

Copy link
Copy Markdown

Problem

Phoenix can emit NaN (logged in model_runner, still returned). RankingScorer::apply did unwrap_or(0.0) * weight, so Some(NaN) / Some(±Inf) entered the sum. Dwell-regret then added that NaN into the slate mean, and every candidate’s score became NaN. TopKScoreSelector kept Some(NaN) (partial_cmp → Equal). DedupConversationFilter used score > best, which is false for NaN, so a NaN first-post locked the conversation.

This is not #142 (all heads None still ranked). This is not #181 (engagement-count store errors zeroing features). A present non-finite feature fail-opened into rank.

Five-line proof

  1. Phoenix has_nan increments a metric and still reply_requests the batch (phoenix/xrex/inference/model_runner.py).
  2. RankingScorer::apply / dwell-regret means used unwrap_or(0.0)Some(NaN) stays NaN; one head NaNs mean_favorite.
  3. centered_ratio then NaNs every candidate; offset_score writes Some(NaN).
  4. TopKScoreSelector / Selector::sort treat NaN as Equal, so poisoned posts occupy For You slots; +Inf wins the slate.
  5. After: non-finite heads are missing (0); persisted scores are finite or None; TopK last-places the rest; conversation collapse ignores NaN.

Change

  • RankingScorer::finite_head / persistable_score — NaN/Inf heads do not enter the weighted sum or dwell-regret means; non-finite finals are unset.
  • PhoenixScoresRankingScorer — same persist rule.
  • TopKScoreSelector — non-finite → NEG_INFINITY.
  • DedupConversationFilter — non-finite → 0 so a finite sibling can win.

Tests

  • nan_favorite_head_does_not_poison_dwell_regret_slate
  • inf_favorite_head_does_not_win_weighted_rank
  • non_finite_final_score_is_unset_for_topk
  • nan_score_does_not_lock_the_conversation
  • non_finite_scores_sort_last

cargo test cannot run here: the public dump has no home-mixer crate manifest.

Survey

@cursor
cursor Bot force-pushed the cursor/nan-inf-rank-feature-fail-open-cbe1 branch from 4b90432 to 01fdd95 Compare September 8, 2026 02:39
@Pitchfork-and-Torch
Pitchfork-and-Torch force-pushed the cursor/nan-inf-rank-feature-fail-open-cbe1 branch from 01fdd95 to 902a06f Compare September 8, 2026 23:06
One non-finite Phoenix head was used as a real feature. Dwell-regret
means then went NaN and TopK kept the poisoned scores. Treat non-finite
heads as missing, persist only finite ranks, and last-place the rest.
@Pitchfork-and-Torch

Copy link
Copy Markdown
Author

Parking this intern-stack PR per operator GitHub cleanup (2026-09-08). Hunt notes remain local. Not a reject of the class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant