What changed in the X algorithm — May 2026 release
On May 15, 2026, X shipped the largest update yet to its open-source algorithm: 187 files changed, roughly 18,000 lines added. The headline additions are Grox — a content-understanding service with classifiers for spam, post categories, and policy enforcement — a runnable end-to-end Phoenix inference pipeline with pre-trained model artifacts, and the first open look at how ads are blended into the For You feed.
View the raw diff on GitHub ↗aaa167b…0bfc279
The shape of the release
This was the first scheduled update after the January launch, and it was not a maintenance drop: 187 files changed, 18,263 lines added, 926 removed — figures we verified directly against the repository history rather than taking from the release notes. Technically it landed as two commits the same day: the release proper, plus a small follow-up fixing the Git LFS pointer for the packaged model artifacts.
The May 15, 2026 release changed 187 files (+18,263/−926 lines), adding: a runnable end-to-end inference pipeline (phoenix/run_pipeline.py), pre-trained mini Phoenix model artifacts, the Grox content-understanding service, an ads blending module (home-mixer/ads/), and new query hydrators, candidate hydrators, and candidate sources.
Grox arrives — the safety layer goes open
The most consequential addition for anyone who cares about reach and penalties is grox/: a content-understanding service that did not exist in the January release. Its classifier directory reads like a map of exactly the machinery people have speculated about for years — spam detection, post-category classification, and PTOS ("Public Tools and Operational Safety") policy enforcement, alongside files whose names speak for themselves: a "banger" initial screen and a deluxe post-safety screen.
The May 2026 release includes Grox, a content-understanding service with classifiers for spam detection, post-category classification, and PTOS policy enforcement — including spam.py, safety_ptos.py, banger_initial_screen.py, post_safety_screen_deluxe.py, and reply_ranking.py.
Before this release, claims about how X screens posts for spam or policy were almost entirely folklore. Now there are named, inspectable classifiers. We are sourcing dedicated explainers for each — they will appear under the penalties pillar as they clear verification.
The pipeline becomes runnable
January gave us the architecture; May made it executable. A single entry point now runs retrieval and ranking end-to-end from exported checkpoints, mirroring how the two stages compose in production, and a pre-trained mini Phoenix model (256-dimension embeddings, 4 attention heads, 2 transformer layers) ships as a ~3 GB artifact so the pipeline runs without training anything first. For researchers — and for us — this is the difference between reading the system and probing it.
Ads, and what X loads about you
Two quieter additions matter. First, home-mixer/ads/ opens the ad-injection and positioning logic, including brand-safety boundaries — the first public look at how paid posts interleave with organic ranking. Second, the query hydrators now enumerate what the system loads about you before ranking a single post: followed topics, mutual-follow graphs, impression bloom filters (what you've already been shown), and served history.
What did not change
The scoring spine is the same: Phoenix predicts per-post engagement probabilities and a weighted scorer combines them — now across nineteen predicted actions, from replies and dwell time down to predicted blocks, mutes, and reports on the negative side.
The current WeightedScorer combines predicted probabilities for: favorite, reply, retweet, photo expand, click, profile click, video quality view, share, share via DM, share via copied link, dwell, quote, quoted click, continuous dwell time, follow author, not interested, block author, mute author, and report.
And the numeric weights remain withheld, exactly as they were in January: the scorer references a parameters module whose values appear nowhere in the published tree. We re-verified that absence at this release's commit.
The numeric values of the current weights are not included in the open-source release: weighted_scorer.rs references a params module (e.g. p::FAVORITE_WEIGHT, p::REPLY_WEIGHT) whose values are not present anywhere in the published repository.
What this means for you
Three practical takeaways. If your reach depends on staying clear of safety screens, the screens now have names and code — generic "shadowban" anxiety can be replaced with specific, inspectable mechanisms. If you optimize content, the action list in the weighted scorer is the authoritative map of what the model predicts about your posts. And if anyone quotes you current numeric ranking weights, they are guessing: the values are not in the code, this release included.