0x00 한

Research / Daily reports

  • Sources read: 1
  • Canon files updated: 1
  • Radar entries: 0
In one lineX For You started recording the order and scores of the feed it actually served, page by page. The serving log for training page RL re-ranking is on for the first time.

1Serving page log turned on and ads V2 verdict turned off — X

Source xai-org/x-algorithm@606b254 — xAI, 2026-10-29, code. In the numbering these notes use, it is Gen4+52 (Gen4+N is the number these notes assigned in order to commits after the 2026-08-13 Gen4 release).

Background The previous day's commit added page decoder (an RL re-ranking model that picks, in slot order, the posts to place on a page from the top-scoring candidates) re-ranking, exploration sampling, and a serving page log to home-mixer (the service that handles For You requests), all off by default. To train RL re-ranking, data on "which order was served and how users reacted" must accumulate first. The defaults in this commit are the values from the 2026-10-28T16:00 sync of the cron mirror (a parameter file that copies production feature-switch defaults every day). This commit turns on only the log of those three switches, and on the ads side it turns off the brand safety verdict switch and adds two new kinds of ads blenders (the stage that decides ad slots among organic posts).

What we learnedA. For You started recording the order and scores of the feed it actually served, page by page

  • The serving page log switch changed from false to true by default verified — params/param.rs:312-317.
    • The switch is named EnablePageLogging (rust_home_mixer_enable_page_logging), and the default TTL of 3600 seconds is unchanged.
    • This log is used only in the production environment. The condition is is_prod() && EnablePageLogging — phoenix_request_cache_side_effect.rs:304-306.
  • The log contains the first posts of the feed actually served, in the order served, with their weighted-sum scores and final scores verified — same file:201-277.
    • The two slot probability fields (reward_rerank_slot_prob, page_decode_slot_prob) are filled only when the exploration or decoder switch is on.
    • The two switches (EnablePageRlExploration, EnablePageDecodeRerank) are still false by default in this commit. So the logs accumulating now hold only the order and scores, without probabilities.
  • X appears to have started by recording the pages served by the existing policy before turning on RL re-ranking inferred. The evidence is that, of the three switches, only the log was turned on first.

What we learnedB. The ads brand safety V2 verdict was turned off for the third time

  • The switch that judges the risk level of posts next to ads under V2 rules changed from true to false verified — params/param.rs:938-943.
    • The switch is named EnableAdsBrandSafetyVerdictV2 (rust_home_mixer_ads_bs_v2_exp_enabled).
    • Its history: introduced off on 2026-08-17, on 08-25, off 09-16, on 10-03, off 10-29.
  • The fallback switch that fills gaps with an author-level safety label did not change verified — the same diff has no line for it.
  • The reason for turning it off is not in the code inferred. The switch key contains exp, so it appears to be a value that opens and closes an experiment bucket, and four changes in two months fit that reading.

What we learnedC. Two ads blenders that follow the same safety rules were introduced as options

  • slot_spread and least_movement were added to the ads blender choices, and the default is still multi-risk verified — selectors/blender_selector.rs:62-67.

    • The param.rs diff of this commit has no AdsBlenderType line.
  • Both blenders find two organic posts that can sit above and below each ad verified — ads/neighbours.rs.

    • Posts fall into four grades: Safe, Low, Medium, and High. A High post cannot sit next to any ad, and a Medium post can sit only next to an ad whose advertiser allows that context (BSR-high).
    • A post containing a handle or an excluded keyword specified by the advertiser also cannot be a neighbor.
  • slot_spread first sets ad slots evenly across the whole page, then pulls the nearest safe posts above and below each slot verified — ads/slot_spread_blender.rs:1293-1303.

    • It keeps the minimum gap and divides the remaining positions equally between slots.
    • If sensitive ads remain for later, it uses Low posts first to save Safe posts.
  • least_movement picks the placement that disturbs the original order of organic posts the least verified — ads/least_movement_blender.rs.

    • When deciding whether to accept an ad, it checks by bipartite matching (augmenting path) whether every ad, including those already chosen, can be given two non-overlapping neighbors.
    • When comparing slot candidates, it uses a slack weight of 50 (FIRST_AD_SLACK_WEIGHT) for the first ad and 2 (SLACK_WEIGHT) for later ads. This appears to be a value meant to strongly avoid placements that delay the first ad inferred.
  • The tests pin that both blenders keep the same safety conditions as multi-risk and do not serve fewer ads than multi-risk verified — ads/tests/blender_comparison_test.rs.

    • On the same mixed feed, both serve 7 ads and drop 3 for the gap limit, so the results are the same. The number of organic posts moved is 6 for least_movement and 8 for slot_spread.
    assert!(
        total >= baseline_total,
        "{name} served {total} ads vs multi_risk {baseline_total}"
    );
    

What we learnedD. Phoenix trains the lead-generation conversion in the window right after the click

  • The ads lead-generation conversion (ADS_LEADGEN_CONVERSION) entered a new head group that trains "only on clicks, in the fresh window" verified — ads_head_masking.py.
    • This action was added to the proto in the previous day's commit. The existing web and app conversion heads train in the delayed window (the window that waits for late-arriving conversions).
    • The training mask is fresh_ct & fresh & kept & click.
  • The page RL training config gained a variant that switches the dwell loss to CREAD (a method that trains binary classifiers for whether dwell time exceeded several thresholds, then recovers the expectation) verified — configs/xrecsys.py.
    • It is named immersive_page_rl_cread. It sets the Tweedie and MAE weights to 0, sets the two CREAD losses to 0.1 each, and turns on the dwell bucket table.
    • The default home config already switched to CREAD on 2026-10-08. Now the page RL side can use the same loss.

What we learnedOther changes

  • The video carousel ranking score gained a "probability of opening the video × expected dwell time on the immersive surface" term, with a weight defaulting to 0.0 verified — util/video_carousel.rs:178-190.
  • Carousel module items were removed from the recent impression history, so carousel videos are not counted as "already seen posts" of the main feed verified — served_history_query_hydrator.rs:94-110. The carousel is off by default, so default behavior is unchanged.
  • An option that also updates the user token in the candidate-only layer (the last Transformer layer that updates only candidate tokens) was introduced, off by default, so that page RL can run with that layer verified — models/transformer.py.
  • An option that restricts ads head metrics to the window each head trains on was introduced, off by default verified — models/recsys_model.py.
  • Metrics that count ad placement results and supply limits were attached to the two new blenders verified — ads/health_metrics.rs.
  • VF (visibility-filtering, a service that decides for each post whether this viewer may see it) is a refactor. The rules, the per-safety-level rule lists, and the client switch defaults did not change verified — 606b254.
    • It merged quote-relationship lookup into the Flock source, fixing a problem where answers got mixed when the viewer was the quote author.
    • It returns posts it cannot find as NotFound instead of Failed. Either way, the post is not served.
    • The golden corpus (tests of expected verdicts per rule) gained cases for the For You recommendation and immersive recommendation surfaces.
  • The ranker cluster label was removed from training statistics, and the multimodal embedding lookup uses only the O2 store with no fallback path verified — 606b254.
  • grox (the Grok-based annotation pipeline) gained an affiliate-company badge image field and a helper that extracts JSON from LLM output verified — same commit.

Canon update services/x.md raised the reference commit in ## Summary and ## Sources to 606b254. In the scorer chain bullet of the Phoenix section under ## Ranking, it corrected "the serving page log, off by default" and added a bullet for the switch to on by default. It corrected the V2 verdict sentence in the ## Ads introduction to off by default, and added a sentence on the new blenders and a list of "this section's change log". It added bullets to the blender choice list in the The final placement is not score order subsection, to the carousel ranking score in the Feed surfaces section, and to question 2 on the 2026-10-14 commit in ## Open questions, and it added a Gen4+52 row to the Commit summary table.

Why it matters The serving log, the first of the three steps toward page-level RL re-ranking, is now on as a production default. Because the log currently has no probabilities, the exploration switch must also be turned on to use it for offline RL inferred. On the ads side, X turned off the V2 verdict again and widened the blender candidates, so brand safety placement still appears to be under experiment inferred.

What to check next