A post can rank above another post with six times the likes. That sentence
is true for the same reason a creator with a quiet but thoughtful follower
base can outperform one with bigger absolute numbers. The 2026 X ranker
does not score posts on a scalar "engagement." It runs nineteen separate
probabilistic predictions per candidate, combines them with weights, and
the resulting score decides feed position. This piece is the index of
those nineteen heads. The structure of the score is in
home-mixer/scorers/weighted_scorer.rs. The output
shape of the model is documented in
phoenix/README.md. The index-to-name mapping is
partially redacted; we will be explicit about what is verified and what
is inferred. A1
of this series walks the wider architectural change. This is the
deep dive on the scoring layer.
The two-line summary of how the math works
Phoenix outputs a tensor of shape [batch, num_candidates, num_actions]
with num_actions = 19. Each value is P(action_i), the predicted
probability that the viewer takes action i if the candidate is served.
home-mixer/scorers/weighted_scorer.rs then runs the
following:
combined = Σ_i (P(action_i) × WEIGHT_i)
final = offset_score(combined)
That is the entire scoring formula. The weights WEIGHT_i are static per
action, defined in the redacted params module. offset_score is an
asymmetric branch: if the combined score is positive (the model expects
net engagement), the value passes through largely unchanged. If the
combined score is negative (the model expects more mutes and
"not interested" reactions than likes and replies), the value is rescaled
through (combined + NEGATIVE_WEIGHTS_SUM) / WEIGHTS_SUM × NEGATIVE_SCORES_OFFSET so that the resulting score is strongly
penalised. A5
walks the offset branch in detail; for now the takeaway is that
predicted negatives compete on the same scoring formula as predicted
positives, and one strong predicted mute can sink the score even of a
post with several strong predicted positives.
All nineteen heads
The next three tables enumerate the nineteen heads. The first is what we
can verify directly from
phoenix/run_pipeline.py: six index-to-name pairs
that appear as named constants in the public source. The second is the
remaining thirteen, where the WEIGHT constant exists in
weighted_scorer.rs and the field name exists in the PhoenixScores
proto referenced by home-mixer/scorers/vm_ranker.rs,
but the specific output index is not spelled out in the README.
Source: phoenix/run_pipeline.py + phoenix/README.md
| Index | Head | Weight constant | UI gesture that fires it |
|---|---|---|---|
| 1 | Favorite (like) | FAVORITE_WEIGHT | tap the heart |
| 4 | Reply | REPLY_WEIGHT | compose and send a reply |
| 5 | Quote | QUOTE_WEIGHT | compose a quote-post |
| 6 | Repost | RETWEET_WEIGHT | tap repost (formerly retweet) |
| 11 | Dwell (binary) | DWELL_WEIGHT | viewer paused on the post above a threshold |
| 13 | Video quality view | VQV_WEIGHT | video played past MIN_VIDEO_DURATION_MS |
Source: home-mixer/scorers/weighted_scorer.rs + home-mixer/scorers/vm_ranker.rs (PhoenixScores proto)
| Head | Weight constant | UI gesture that fires it | Sign |
|---|---|---|---|
| Quoted click inferred | QUOTED_CLICK_WEIGHT | tap the embedded quoted post inside a quote-post | positive |
| Photo expand inferred | PHOTO_EXPAND_WEIGHT | tap a photo to open it full screen | positive |
| Click inferred | CLICK_WEIGHT | tap a link inside the post body | positive |
| Profile click inferred | PROFILE_CLICK_WEIGHT | tap the author's name or avatar | positive |
| Share inferred | SHARE_WEIGHT | system share sheet | positive |
| Share via DM inferred | SHARE_VIA_DM_WEIGHT | send to a specific user via direct message | positive |
| Share via copy link inferred | SHARE_VIA_COPY_LINK_WEIGHT | copy the post URL to clipboard | positive |
| Continuous dwell time inferred | CONT_DWELL_TIME_WEIGHT | regression target over the actual time the viewer paused | positive |
| Follow author inferred | FOLLOW_AUTHOR_WEIGHT | tap follow from inside the post unit | positive |
| Not interested inferred | NOT_INTERESTED_WEIGHT | long-press menu, "Not interested in this post" | negative |
| Block author inferred | BLOCK_AUTHOR_WEIGHT | block the author from inside the post menu | negative |
| Mute author inferred | MUTE_AUTHOR_WEIGHT | mute the author from inside the post menu | negative |
| Report inferred | REPORT_WEIGHT | report the post for a policy violation | negative |
One subtle item: home-mixer/scorers/vm_ranker.rs's
PhoenixScores proto contains a not_dwelled_score field that does not
appear among the nineteen-head outputs and does not pair with a WEIGHT
constant in the simpler weighted scorer. The presence of this field
suggests that an experimental scoring path through vm_ranker.rs is
running with at least one extra signal the public weighted_scorer.rs
does not use. A6
walks the four dwell-related signals including this implicit one.
The third table places the open 2026 stack next to the only widely distributed reference point we have for comparable numeric weights: the 2023 release. The 2023 numbers are not authoritative for 2026 in any way; they are included only because they are the loudest existing reference. Treat them as directional indicators of relative weight magnitudes, not as production values.
Source: 2023 from twitter/the-algorithm-ml SrcEngagementWeights.scala; 2026 from xai-org/x-algorithm with params/ excluded
| Head | 2023 leaked weight | 2026 status | Polarity |
|---|---|---|---|
| Favorite 2023 ref | 0.5 | redacted | + |
| Retweet (repost) 2023 ref | 1.0 | redacted | + |
| Reply 2023 ref | 13.5 or 27.0 (two constant sets) | redacted | + |
| Profile click 2023 ref | 12 | redacted | + |
| Dwell (continuous) 2023 ref | 0.0001 | redacted | + |
| Not interested 2023 ref | minus 74 | redacted | minus |
| Mute author 2023 ref | approximately minus 100 | redacted | minus |
| Block author 2023 ref | approximately minus 100 | redacted | minus |
Two relative-magnitude properties survive across both stacks. Reply is
worth far more than favorite per action (the 2023 ratio is roughly 27 to
0.5, a factor of 54). Profile click is worth more than favorite by a
similar order. Continuous-dwell time is a very small per-unit weight
multiplied by a number that can be tens or hundreds of milliseconds, so
its expected contribution per impression is in the same range as the
discrete heads despite the tiny constant. And the negative heads dwarf
the positive heads in absolute magnitude. A single predicted mute, at
roughly minus 100 to the favorite's plus 0.5, costs the equivalent of
roughly two hundred favorites of expected score in the 2023 numbers. The
2026 redaction prevents us from claiming a current ratio, but the
asymmetric offset_score branch and the four explicit negative WEIGHT
constants in the 2026 code make clear that the structural property
(negatives outweigh positives per action) persists.
The four heads everyone teaches and why they are not the most important
Most public algorithm coverage focuses on four heads: favorite, retweet (repost), reply, and follow. These are the visible engagement actions, in the sense that the post unit on the screen displays counts for the first three and that follower count is an obviously trackable metric. The fourth, follow author from a post, was the prized 2023 signal because the public Twitter algorithm code described follow as the conversion event the ranker most wanted.
Three structural reasons those four are not the most predictive of feed position in 2026.
First, like and retweet are the lowest-weighted positive heads in the 2023 reference and there is no reason to expect that to invert in 2026. The relative ratios suggest they exist to nudge the score, not to drive it. Reply has a much higher per-action weight, but reply requires composing text and shipping it; the volume of replies per impression on any given post is structurally a fraction of the volume of likes. The math works out to reply being a heavier per-action signal but a lighter total-volume contribution than its constant suggests for most posts.
Second, follow author depends on the viewer not already following the author. If the viewer is in your follower base, that head is zero for every one of your posts they see. The signal exists primarily for out-of-network candidates served via the Phoenix retrieval lane, where the viewer is meeting you for the first time.
Third, all four of these heads are visible-engagement heads. The model also predicts probability of profile click, photo expand, click, share, and three dwell-related variants for the same impression. A creator optimising for visible counts is leaving the per-impression score of nine of the fifteen positive heads on the table. Posts that fire only the visible heads run into a ceiling. Posts that fire visible plus invisible heads break through.
The six heads nobody teaches
A creator who has read three Twitter-algorithm explainers in the last year has probably never seen the following heads enumerated. They are the ones worth understanding in detail.
Video quality view (VQV_WEIGHT, index 13). Gated on
video_duration_ms exceeding a MIN_VIDEO_DURATION_MS threshold. Below
the threshold, the video earns zero on this head no matter how many times
it plays. Above the threshold, every qualifying play contributes. For
creators shipping video, this single threshold means a 4-second loop and
a 15-second cut produce categorically different score contributions on
the same content. Production thresholds are not in the public source.
Verified at index 13 in phoenix/run_pipeline.py.
Photo expand (PHOTO_EXPAND_WEIGHT). A viewer taps a photo to open
it full screen. That gesture is far more deliberate than scroll-past or
like. Posts whose photos are detail-rewarding (text in the photo, chart
detail, layered image) fire this head; posts whose photos are decorative
do not.
Profile click (PROFILE_CLICK_WEIGHT). Viewer taps the author's
name or avatar to view the profile. Authority-and-curiosity signal. The
ratio of profile clicks to impressions is one of the cleanest indicators
of "this post made me want to learn who you are." The 2023 reference
weight for this was 12, the second highest after reply.
Click (CLICK_WEIGHT). Tap on a link inside the post body. Note
that this is the link click, not the post click. Posts that earn the
click are posts that have made the case for the link inside the 280
characters above it. A short post with a link and no setup gets very few
clicks; a short post with a one-sentence setup that earns the click
fires both this head and the continuous dwell head while the viewer
reads the setup.
Share via DM (SHARE_VIA_DM_WEIGHT). The viewer sent your post to a
specific other person via direct message. The most under-discussed
positive signal on the platform. It encodes "I think this is worth a
specific other human's attention." Idiosyncratic, opinionated, useful,
and well-framed posts fire it. Generic engagement-shaped posts almost
never do.
Share via copy link (SHARE_VIA_COPY_LINK_WEIGHT). The viewer
copied the URL to send out of channel. Slack, Notion, an email, an
external forum. Same intent as share via DM, different surface. Combined
with share via DM, these two heads are the platform's best proxies for
"this post will be referenced again later."
These six are all in the inferred-index table above. The WEIGHT constants and proto field names exist in the public code. The exact Phoenix output index they pair with is inferred from field-name correspondence.
The four negative heads and the math that makes them outweigh dozens of positives
Not interested, mute, block, report. Four explicit negative WEIGHT
constants in home-mixer/scorers/weighted_scorer.rs.
Each is a one-action gesture by a viewer that tells the ranker "show me
less of this." Each carries a large-magnitude negative weight.
The math: the weighted sum combined = Σ_i (P(action_i) × WEIGHT_i)
runs over all nineteen heads with their respective weights. Phoenix's
predicted probability for each negative action sits between 0 and 1 like
every other head, but multiplied by weights that are an order of
magnitude larger and negative in sign. In the 2023 numbers, a predicted
mute probability of even five percent applied to a weight of minus 100
yields a contribution of minus 5. That single contribution dominates the
contribution of dozens of predicted favorites at weight 0.5.
Two consequences for creators. First, posts that drift off voice trigger
non-trivial predicted mute probability from followers who built the
follow on a different voice. A8
walks the embedding mechanism behind that prediction. Second, the
offset_score branch makes the penalty asymmetric: a post that nets
positive scores roughly linearly, while a post that nets negative
through predicted mutes and not-interested gets rescaled into a different
range entirely. Net-negative posts are not just lower-scored; they sit in
a different regime.
The negative-signal economy is the single most defensible reason to build a voice-fidelity check into a writing tool. Tweet Hunter and similar template-driven generators have no concept of voice match; they optimise visible-engagement template fit, which is exactly the surface that drifts away from a creator's audience-anchored voice. The downstream math is the negative-head economy multiplying that drift across every predicted mute.
There is also a hard-filter layer running in parallel to the weighted
score. home-mixer/filters/muted_keyword_filter.rs
removes candidates whose tokens match the viewer's muted-keyword list
before they ever reach the scorer.
home-mixer/filters/author_socialgraph_filter.rs runs
six explicit conditions including block-author and mute-author boolean
gates, regardless of what Phoenix predicts. The four negative heads in
the weighted scorer handle the probabilistic case (the viewer will
probably want to mute this if served). The filter layer handles the
deterministic case (the viewer has already muted this author, do not
serve their posts at all). Both layers feed the same "less of this"
intent, on different signal pathways. A creator who drifts off voice
faces probabilistic predicted-mute penalties first, and accrues
deterministic mute-filters from followers second. The two effects
compound: each actual mute removes that follower from your impression
pool entirely while raising the predicted-mute prior for similar
followers next time.
Continuous dwell time as the silent kingmaker
Discrete dwell is index 11, verified. Continuous dwell time
(CONT_DWELL_TIME_WEIGHT) is inferred and operates on the actual
duration the viewer's eye sat on your post in the scroll feed. The
per-millisecond weight is tiny in the 2023 reference (0.0001) but the
total contribution scales with the duration. A post that holds a viewer
for twelve seconds, at 12,000 milliseconds times 0.0001, contributes 1.2
on a single head. Compare that to the favorite weight of 0.5 per like.
One twelve-second dwell, in the 2023 numbers, is worth more than two
likes.
That math is structurally important because dwell is unfakeable in a way favorites are not. Likes can be reciprocated, traded, automated. Dwell happens or does not happen on the basis of whether the viewer actually reads the post. Hook density, line-break rhythm, second-line payoff, narrative arcs that need to be finished to make sense, all of these fire continuous-dwell. Generic engagement-bait does the opposite: it delivers its full payload in the first three words and the viewer scrolls past.
The graph below sketches the score-shape difference between a likes-only post and a balanced post that fires multiple heads. Numbers are illustrative, not from production telemetry.
Source: illustrative simulation, weights and counts notional
Read the right column carefully. The multi-head post earns less than half the favorites but lights up four other heads at material contribution. The sum of the right column is structurally several times the sum of the left, even though only one head is "higher" on the visible-counts surface. That is the central property of the 2026 ranker. It rewards distribution of contribution across heads, not concentration on one.
Voice as a meta-head
The argument that closes this piece is the one most algorithm coverage will not make because it requires connecting the model architecture to audience-specific reaction patterns. Phoenix conditions every prediction on the viewer's history sequence. That sequence is a record of which heads each viewer has historically fired on, for which authors. A viewer whose history sequence is dominated by long-form thread reads with twelve-second dwells has, encoded in their history embedding, a strong prior on dwell-firing posts from accounts they have engaged with.
When a new candidate from you arrives in front of that viewer, Phoenix's prediction for your dwell head is conditioned on two things: the candidate post itself, and the viewer's per-creator history pattern. If your past posts in that viewer's history have systematically fired their dwell head, the model has a high prior for your next post firing it too. If your past posts have systematically fired favorite-only, the prior is concentrated on favorite, not on dwell.
Voice consistency feeds that per-creator prior. A creator whose posts systematically fire dwell, replies, and DMs in their follower base builds up a per-creator history pattern across all those followers' history sequences that anchors Phoenix's prediction for new posts. A creator whose recent posts diverge from that pattern (off-voice generic engagement-bait, suddenly) breaks the prior, and Phoenix falls back on the candidate-only signal, which is much weaker. The drift is felt as quieter posts. The mechanism is the predicted-action mix collapsing toward the cold-start baseline.
That is the structural argument for voice as a writing-product surface worth measuring. Auden's job, inside VoiceMoat, is to keep posts on a creator's historical distribution across the heads their audience reliably fires on. The full inventory of how Auden does this lives in the product docs; the algorithm-level reason it matters lives in the nineteen heads above.
A practical framework for writing toward multiple heads
The framework that falls out of the nineteen heads is shorter than most "X algorithm playbooks" by an order of magnitude. Five operational moves, each backed by a specific head.
One: end with something replyable, not a takeaway. Replies have the heaviest per-action positive weight in every reference set we have, and the cost of "writing for replies" is low: ask one question your audience has a real answer to, or land on one opinion they will want to push back on. Generic CTAs ("agree?", "thoughts?") underperform specific prompts because the predicted-reply head is conditioned on the viewer's history of which kinds of posts they actually reply to. Specific prompts that match historical reply patterns fire the head; generic ones do not.
Two: write a second-line payoff that earns the dwell. Continuous dwell rewards posts whose first line opens a loop the second line closes. "I shipped three products in 2025. Two failed. Here is what the third did differently." That structure fires the dwell head because the viewer has to read past the hook to extract the value. Headline-only posts deliver the payload in the first line and lose the dwell.
Three: include exactly one click-worthy element when the post needs it, and otherwise omit the link. The click head rewards posts that make the case for the link inside the post body. Linkless posts lose the click head but win on other surfaces; link-heavy posts that fail to earn the click hurt the predicted-click probability across the creator's history pattern. Be deliberate.
Four: prefer posts that someone would specifically DM another person about. The share-via-DM head is the cleanest signal of "this is worth referencing later." Posts that fire it tend to be opinionated, operational, or counter-conventional. Posts that are simply pleasant or mildly informative do not fire it. The test is concrete: would a specific person you know send this to a specific person they know? If yes, the head fires. If no, it does not.
Five: do not optimise visible counts at the expense of voice. The nine invisible-engagement heads (profile click, photo expand, click, three share variants, two dwell variants, follow-author) are not visible to the creator or the audience, but they sum to the majority of the weighted score for most posts. Visible-count optimisation usually means template fit, which usually means voice drift, which means raising predicted-mute probability across the follower base. That is a worse trade per impression than the visible-count gain pays for.
That is the entire framework. Five moves. Each maps onto a specific head or head cluster. Each survives the redacted weights because each rests on the relative-ratio property (replies and clicks and dwell weigh more than likes; negatives weigh more than positives in magnitude; multiple heads distribute risk; voice consistency anchors the per-creator prior) rather than any specific numeric weight.
Up next in this series: A5
on the negative-signal economy, which expands the four negative
heads into the full filter stack and the off-voice-drift pipeline.
A6 walks the
four dwell heads in particular, including the not_dwelled_score
puzzle. A8
returns to the embedding mechanism that makes voice-as-a-meta-head
operational.