- Sources read: 1
- Canon files updated: 1
- Radar entries: 0
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 switch is named
- 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.
- The two slot probability fields (
- 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 switch is named
- 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_spreadandleast_movementwere added to the ads blender choices, and the default is still multi-risk verified —selectors/blender_selector.rs:62-67.- The
param.rsdiff of this commit has noAdsBlenderTypeline.
- The
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_spreadfirst 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_movementpicks 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_movementand 8 forslot_spread.
assert!( total >= baseline_total, "{name} served {total} ads vs multi_risk {baseline_total}" );- 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
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.
- It is named
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
NotFoundinstead ofFailed. 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
- The day the exploration switch turns on in the X cron mirror — from then on probabilities accumulate in the page log, making offline RL training possible.
- Whether the
AdsBlenderTypedefault changes to slot_spread or least_movement — a direct signal of an ads placement policy change. - Whether the V2 verdict switch turns on again — a fifth flip would further firm up the experiment bucket reading (inferred).
Lookup failed: ai.meta.com/blog — the list only shows posts up to 2026-07, so we could not confirm recent posts Lookup failed: research.netflix.com/publications — HTTP 404