# Análisis del algoritmo de recomendación de X

> Informe basado en el código publicado en este repositorio. El foco es el feed **For You** y el comportamiento de contenido sensible, NSFW y VRChat. No representa una garantía sobre todas las superficies o configuraciones de producción.

## Resumen ejecutivo

El sistema no es un único algoritmo. Es una cadena de recuperación, hidratación, filtrado, predicción de acciones, ranking y filtrado de visibilidad.

La conclusión más importante para NSFW es esta:

- **El ranking decide el orden, pero Visibility Filtering decide si un post puede mostrarse.**
- Los posts NSFW se pueden conservar para seguidores en el cache in-network, pero los posts etiquetados como NSFW se excluyen del índice general de recomendación de Phoenix y se bloquean para recomendaciones out-of-network.
- Para un adulto que sigue a la cuenta, el resultado puede ser `ALLOW` o un `INTERSTITIAL` con blur, según el label y la configuración de contenido sensible.
- Para un no-seguidor, los labels y flags NSFW relevantes producen `DROP`, incluso si el viewer permite contenido sensible.
- Menores, usuarios logged-out y usuarios sin edad declarada en jurisdicciones concretas reciben `DROP` en los casos definidos por las reglas.
- El repositorio no contiene los prompts completos de Grox, algunas reglas de Botmaker ni todos los parámetros de producción. Por eso no es válido afirmar que el código publicado explica cada decisión real de X.

## 1. Qué problema resuelve el repositorio

El README del proyecto describe dos caminos principales:

1. **Request path:** construye una respuesta de For You para un viewer concreto.
2. **Labeling path:** analiza posts, media y cuentas continuamente, genera labels y los almacena para que el request path pueda consultarlos.

La separación es deliberada. Un post puede tener un score alto y aun así ser eliminado por seguridad. Del mismo modo, un post visible puede tener un score bajo y quedar fuera de los primeros puestos.

## 2. Pipeline del feed For You

La implementación principal se encuentra en `home-mixer/` y `candidate-pipeline/`.

### 2.1 Hidratación de la consulta

El sistema reúne información del viewer:

- Secuencia reciente de acciones: likes, replies, reposts, quotes, shares, clicks, dwell y acciones negativas.
- Cuentas seguidas.
- Bloqueos, mutes y keywords silenciadas.
- Posts vistos o servidos previamente.
- Topics incluidos o excluidos.
- Contexto de usuario y cliente, incluido país, edad disponible y configuración de media sensible.

La secuencia de acciones recientes es una entrada central para Phoenix. El modelo no intenta calcular una relevancia universal; predice acciones concretas que ese viewer podría realizar sobre cada post.

### 2.2 Fuentes de candidatos

Las fuentes se consultan en paralelo:

| Fuente | Tipo | Función |
| --- | --- | --- |
| Thunder | In-network | Posts recientes de cuentas que el viewer sigue. |
| Phoenix retrieval | Out-of-network | Recupera posts cercanos al embedding del viewer. |
| SimClusters | Out-of-network | Busca posts de clusters creados a partir de relaciones de engagement. |
| Cached posts | Mixta | Puede aportar posts cacheados según la configuración. |

El repositorio define Phoenix retrieval y SimClusters como mecanismos de descubrimiento. Sin embargo, los posts que el sistema de indexado considera no elegibles para recomendaciones no llegan al índice normal de Phoenix.

### 2.3 Hidratación de candidatos

Antes de puntuar, el sistema intenta cargar:

- Texto y media.
- Datos del autor.
- Flags y user labels.
- Tweet safety labels.
- Engagement y counts.
- Quotes, replies, retweets y ancestros.
- Suscripciones, idioma y otros metadatos.

Si fallan datos fundamentales, `CoreDataHydrationFilter` descarta el candidato.

### 2.4 Filtros antes del ranking

El pipeline aplica, entre otros, estos filtros:

- Duplicados entre fuentes.
- Posts de más de 48 horas.
- Posts propios del viewer.
- Replies y reposts out-of-network en condiciones no permitidas.
- Posts ya vistos o servidos.
- Keywords silenciadas.
- Autores bloqueados o muteados.
- Topics excluidos.
- Videos cuando la consulta los excluye.
- Suscripciones inaccesibles.
- Umbrales de engagement para usuarios nuevos.
- Holdout experimental.
- `OONNsfwSimclustersFilter`.

El filtro NSFW de SimClusters (`home-mixer/filters/oon_nsfw_simclusters_filter.rs`) elimina un candidato cuando se cumplen simultáneamente:

```text
served_type == ForYouSimclusters
in_network == false
nsfw_author == true
```

`nsfw_author` se hidrata como verdadero si el autor tiene `nsfw_admin`, `nsfw_user` o el user label `NSFW_HIGH_PRECISION`.

### 2.5 Predicción de acciones

Phoenix predice probabilidades para acciones positivas, clicks, atención, seguimiento y acciones negativas:

```text
Engagement: favorite, reply, repost, quote, share, share via DM, copy link
Clicks: post, profile, link, photo expand, video open, quoted post
Attention: video quality view, dwell, dwell time, click dwell time, active seconds
Author: follow author
Negative: not interested, mute author, block author, report, not dwelled
```

El `RankingScorer` combina las probabilidades:

```text
Final score = Σ(weight_i × P(action_i))
```

Los valores publicados en `home-mixer/params/param.rs` incluyen:

| Acción | Peso |
| --- | ---: |
| Favorite | 0.5 |
| Reply | 5.0 |
| Retweet | 1.0 |
| Quote | 5.0 |
| Share | 2.0 |
| Share via DM | 5.0 |
| Share via copy link | 20.0 |
| Click | 0.4 |
| Open link | 0.2 |
| Follow author | 4.0 |
| Photo expand | 0.05 |
| Video open | 0.05 |
| Not interested | -43.2 |
| Block author | -31.2 |
| Mute author | -58.8 |
| Report | -234.0 |
| Not dwelled | -0.02 |

Después se aplican ajustes:

- **Author diversity:** decay `0.5`, con floor `0.25`, para no llenar el feed con un solo autor.
- **Out-of-network discount:** factor `0.75` para posts de autores no seguidos.
- **Topic OON factor:** `0.5` cuando la consulta está restringida a topics.
- **New-author/cold start:** ciertas cuentas pequeñas pueden recibir tratamiento especial.
- **VMRanker:** reordena para reducir la repetición de posts demasiado similares.

### 2.6 Selección y filtrado final

`TopKScoreSelector` ordena por score y conserva candidatos principales. Después, `VFCandidateHydrator` consulta `visibility-filtering` con el post y el viewer.

Los resultados son:

- `ALLOW`: el post puede mostrarse.
- `INTERSTITIAL`: el post permanece, pero el cliente puede mostrarlo detrás de un aviso o blur.
- `DROP`: el post se elimina del resultado.

Si se descarta un ancestro, quote o repost asociado, `AncillaryVFFilter` puede eliminar también el post principal.

## 3. Cómo se generan los labels NSFW

El sistema utiliza varios signals. El repositorio muestra partes de cada uno, no una única decisión binaria.

### 3.1 Content understanding

`grox/flows/ptos/` clasifica categorías como:

- `AdultContent`.
- `ViolentMedia`.
- `ChildSafety`.
- `Spam`.
- `HateOrAbuse`.
- `CivicIntegrity`.

Dentro de AdultContent aparecen, entre otros:

- `AdultContentSexualHard`.
- `AdultContentSexualSoft`.

En `task_write_safety_post_annotations_result_sink.py` se observa esta traducción:

- Sexual hard: `NsfwHighRecall` y, si hay media, `NsfwHighPrecision`.
- Sexual soft: `SoftNsfw`.

Los prompts `.j2` usados por algunos clasificadores no están publicados.

### 3.2 Modelos de media

El repositorio incluye dos caminos relacionados:

- `media-model-proxy/`: expone modelos como `XX_NSFW` y `VIOLENCE_AND_GORE`. El descriptor NSFW devuelve features continuas como `nsfw.default.probability`, `score`, `precision`, `recall` y `fpr`.
- `grox/flows/ptos/task_safety_ptos_safemodel_sex_nudity.py`: usa el clasificador `sex-and-nudity` y considera positivos los buckets `R` y `X`.

El modelo experimental de `pnsfwmedia/` combina embedding de imagen, score calibrado de Agatha, score textual del usuario, score de seguidores y flags de datos ausentes.

### 3.3 Umbrales publicados

En las reglas de Scarecrow aparecen señales de clasificación:

- `precisionNewNsfw >= 0.95` → high precision.
- `precisionNewNsfw >= 0.999` → near perfect.
- `recallNewNsfw <= 0.8568428` para no-video y `<= 0.6` para video → high recall.

`NsfwTweetMediaProcessor.bot` traduce los resultados del modelo:

- `label == "3"` → `NSFW_HIGH_PRECISION`.
- `label == "3"` y `score > 0.99` → `NSFW_NEAR_PERFECT`.
- `label == "4"` → `NSFW_HIGH_RECALL`.

El servicio de visibility filtering no evalúa la probabilidad directamente: normalmente comprueba si el label existe. Por eso un threshold que parece importante puede haberse aplicado antes, durante el etiquetado.

### 3.4 Labels de cuenta

Una cuenta puede recibir labels por acumulación o por flags directos:

- `nsfw_user`: flag de usuario o de producto según el sistema que lo escriba.
- `nsfw_admin`: flag aplicado por X.
- `NSFW_HIGH_PRECISION` y `NSFW_HIGH_RECALL` como user labels.
- `NSFW_NEAR_PERFECT`.
- `NSFW_AVATAR_IMAGE` y `NSFW_BANNER_IMAGE`.
- `POSSIBLY_NSFW_ACCOUNT`.

`scarecrow` incluye una ruta donde más de dos posts NSFW en un día pueden activar el proceso de user label. `safety-label-user-agg` también define reglas config-driven sobre el timeline del usuario:

- `NSFW_HIGH_PRECISION`: 3 de los últimos 5 posts coincidentes, con posts de hasta 60 días.
- `POSSIBLY_NSFW_ACCOUNT`: la configuración publicada declara `minimumMatchingPosts = 11` y `windowSize = 10`; esa combinación aparece como una exigencia efectiva de coincidencia total del window y debe interpretarse literalmente como configuración publicada, no como una garantía de la política completa de producción.

Los labels de usuario tienen TTLs publicados, normalmente 7 días, con variantes de 3 días para ciertas cuentas de alto PageRank.

### 3.5 Agatha y señales de comportamiento

`agatha/` construye modelos sobre features de usuarios y labels históricos. Para NSFW, el conjunto positivo se extrae de usuarios que ya tienen labels como `NsfwHighPrecision`, `NsfwAvatarImage` o `NsfwBannerImage`.

El sistema usa PMI y calibración para generar un score de usuario, entre ellos `agatha_calibrated_nsfw_score`. Agatha también calcula ratios relacionados con blocks, reports y spam reports frente a favoritos.

Esto no equivale a una regla simple como “un report = ban”. Son features agregadas que alimentan modelos y reglas posteriores.

## 4. Visibility Filtering: orden y alcance

La lista principal está en `visibility-filtering/rules/registry.rs`.

### 4.1 Reglas que aplican a ambas superficies

Entre las reglas base se encuentran:

- Autor suspendido, desactivado, borrado o protegido según el contexto.
- Viewer bloquea o mutea al autor.
- Spam, PDNA, bounce y ciertos labels de integridad o abuso.
- Takedowns legales.
- Age gating para media y labels sensibles.
- Interstitials de NSFW, gore, card image y autor marcado.

### 4.2 Reglas solo para recomendaciones

`TimelineHomeRecommendations` añade drops out-of-network para:

- Flags NSFW del autor: `is_nsfw_user`, `is_nsfw_admin`.
- Flags NSFW del tweet: `nsfw.user`, `nsfw.admin`.
- Labels del post: `NSFW_HIGH_RECALL`, `NSFW_HIGH_PRECISION`, `NSFW_CARD_IMAGE`, `NSFW_TEXT`, gore y otros.
- Labels del usuario: `NSFW_HIGH_RECALL`, `NSFW_HIGH_PRECISION`, `NSFW_NEAR_PERFECT`, avatar y banner.
- Algunas señales de spam, abuso y `DO_NOT_AMPLIFY`.

La primera regla que devuelve `DROP` termina la evaluación. Un `INTERSTITIAL` puede quedar registrado mientras se siguen evaluando reglas posteriores; un `DROP` posterior gana.

## 5. Age gating y opt-in

`visibility-filtering/rules/nsfw_age_gating.rs` usa una lista explícita de países:

```text
ar, au, br, ca, de, es, fr, gb, id, it, kr, mx, nl, ph, pt, th
```

La condición sensible incluye:

- `NSFW_HIGH_PRECISION`.
- `NSFW_HIGH_RECALL`.
- Flags NSFW del autor o tweet con media.
- `NSFW_TEXT` y `NSFW_CARD_IMAGE` aunque no haya media convencional.
- `GORE_AND_VIOLENCE_HIGH_PRECISION`.

Casos publicados en los tests:

- Viewer menor: `DROP`, aunque tenga opt-in.
- Viewer logged-out: `DROP`.
- Viewer sin edad declarada en una jurisdicción gating: `DROP`.
- Viewer adulto: la regla de underage permite el contenido.
- Viewer con edad desconocida fuera de la lista: esta regla concreta permite el contenido.

El opt-in solo evita el interstitial que depende de `viewer_allows_sensitive_media`. No convierte un post OON en elegible, ni permite que un menor vea contenido sensible.

## 6. Casos prácticos

Para distinguir los resultados, usamos dos cuentas hipotéticas:

- **Cuenta A:** publica VRChat NSFW y puede estar marcada como sensible.
- **Cuenta B:** publica VRChat SFW: gameplay, avatares normales, mundos y eventos.

### Caso 1: Cuenta A publica VRChat NSFW

Si los clasificadores aplican labels NSFW:

- El post puede recibir `NSFW_HIGH_RECALL`, `NSFW_HIGH_PRECISION` o ambos, según el camino de detección.
- No se incluye en el índice general de recomendaciones de Phoenix cuando `phoenix-rankall-strato` lo considera NSFW o Visibility Filtering lo dropea.
- Un SimClusters candidate OON puede eliminarse antes del ranking si el autor ya está marcado NSFW.
- Seguidores adultos pueden verlo; sin opt-in, ciertos labels de media producen blur.
- No-seguidores reciben `DROP` para los labels/flags NSFW relevantes.
- Menores y viewers logged-out no lo reciben.

### Caso 2: Cuenta A publica VRChat NSFW explícito

“Explícito” no es un enum único en el repositorio, pero corresponde al caso de mayor severidad del clasificador, por ejemplo `AdultContentSexualHard` o un resultado de alta precisión.

El efecto esperado es más restrictivo:

- Puede activar simultáneamente high recall y high precision.
- Un score de media superior a `0.99` en el camino publicado puede producir `NSFW_NEAR_PERFECT`.
- Se refuerza el user label si la cuenta acumula posts coincidentes.
- OON permanece bloqueado aunque el viewer haya activado contenido sensible.
- In-network queda sujeto a blur, edad y configuración.
- Si aparecen señales de explotación sexual infantil o contenido ilegal equivalente, el flujo es de enforcement, no de simple ranking; el repositorio muestra rutas de suspensión para Child Safety.

### Caso 3: Cuenta B publica VRChat SFW

No hay tratamiento especial por ser VRChat. Si no se generan labels de seguridad:

- Puede entrar por Thunder si el viewer sigue a la cuenta.
- Puede entrar por Phoenix retrieval o SimClusters si es relevante.
- Se puntúa con las probabilidades normales de Phoenix.
- Puede beneficiarse de señales de autor nuevo y diversidad.
- No activa el filtro NSFW de SimClusters.
- No hay blur por NSFW ni drop por contenido adulto.

### Caso 4: Cuenta B publica NSFW una sola vez

El label normalmente se aplica al **post**, no automáticamente a toda la cuenta. Ese post puede ser bloqueado OON o mostrar interstitial in-network.

La cuenta puede permanecer sin user label si no alcanza condiciones de acumulación como 3 de 5 posts o más de dos detecciones en el periodo de la regla. La cuenta no queda convertida automáticamente en “NSFW para siempre”.

### Caso 5: Cuenta A publica contenido SFW

Depende de cómo esté marcada la cuenta:

- Si solo el post anterior tenía label NSFW, el nuevo post puede tratarse normalmente.
- Si la cuenta tiene `nsfw_user` o `nsfw_admin`, las reglas OON por author flag pueden dropear posts del autor aunque el post nuevo sea SFW.
- En-network, `NsfwAuthorInterstitialRule` puede poner interstitial a media de una cuenta marcada.
- `POSSIBLY_NSFW_ACCOUNT` se usa en la hidratación de brand safety de anuncios, no equivale por sí solo a un drop general en las reglas VF mostradas.

### Caso 6: Cuenta B publica un avatar sugerente, pero no explícito

Hay dos decisiones distintas:

- Grox puede producir `SoftNsfw`, que no aparece como drop directo en las reglas VF enumeradas.
- El modelo de media puede producir high precision o high recall de todos modos, en cuyo caso sí aplican las reglas correspondientes.

Por eso “sugerente” no tiene un resultado determinista solo con el texto. Depende de los labels efectivos.

### Caso 7: El viewer sigue a la Cuenta A y activó contenido sensible

Para un adulto con edad válida, el interstitial de media puede no mostrarse y el post puede quedar `ALLOW`.

La cuenta sigue limitada para descubrimiento OON: seguirla cambia el contexto a in-network, pero no convierte el post en recomendación general para no-seguidores.

### Caso 8: El viewer sigue a la Cuenta A, pero no activó contenido sensible

El post puede aparecer con interstitial si tiene un label que lo active, especialmente `NSFW_HIGH_PRECISION`, `NSFW_CARD_IMAGE`, un label de gore o un autor/tweet flag NSFW con media.

No significa necesariamente que el post desaparezca: queda detrás de la acción de revelar contenido.

### Caso 9: El viewer es menor, logged-out o no declara edad

- **Menor:** `DROP` incluso con opt-in.
- **Logged-out:** `DROP` para las condiciones sensibles de la regla.
- **Sin edad declarada:** `DROP` en países de la lista gating; la regla usa primero `account_country_code` y luego `country_code`.
- **Edad desconocida:** el test del repositorio diferencia edad desconocida de edad no declarada. No debe mezclarse ambos estados.

### Caso 10: NSFW solo en texto

`NSFW_TEXT` tiene reglas OON y participa en age gating, aunque no haya media.

Para un adulto que sigue al autor, la regla específica de interstitial de media no se activa solo por `NSFW_TEXT`; puede permitirse normalmente. Para un no-seguidor, menor o logged-out, puede dropearse.

### Caso 11: Cuenta B retuitea o cita un post NSFW de Cuenta A

Los labels del contenido original siguen siendo relevantes:

- Un repost de un post NSFW puede conservar el tratamiento de seguridad.
- Las replies y reposts OON tienen filtros adicionales.
- En un quote, si el post citado es `DROP`, `AncillaryVFFilter` puede quitar el quote completo.

Una cuenta SFW no “limpia” el post original al compartirlo.

### Caso 12: Cuenta A intenta promocionar contenido NSFW con spam o URLs problemáticas

Labels como `SPAM`, `PDNA`, `MALICIOUS_URL` o `DO_NOT_AMPLIFY` tienen efectos adicionales. Algunas reglas de spam y PDNA están en la base y pueden aplicar también in-network, a diferencia de los drops NSFW específicos que suelen ser OON-only.

### Caso 13: Cuenta A recibe muchos reports, blocks o mutes

Agatha y otros sistemas pueden convertir los patrones agregados en scores o labels de calidad/seguridad. El código no define una fórmula pública del tipo “N reportes = drop”; usa ratios, features y modelos. Las acciones negativas también son predicciones negativas en Phoenix, pero los reportes de seguridad pueden provocar decisiones separadas de enforcement.

### Caso 14: Cuenta A quita el marcado sensible y repite el comportamiento

Las detecciones de media y contenido no dependen únicamente del checkbox del usuario. El código publicado incluye una ruta donde un label removido recientemente puede llevar a `MEDIA_PROACTIVE_REVIEW` en vez de limitarse a reaplicar el label. La evasión repetida puede escalar a revisión o enforcement.

### Caso 15: Cuenta A es grande, verificada o de alto PageRank

El tratamiento de etiquetado puede cambiar: ciertas reglas consideran un TTL distinto o envían un reporte para revisión. Pero una vez que el post tiene un label que Visibility Filtering reconoce, la fama no anula el drop OON ni el age gating.

### Caso 16: Contenido de VRChat con apariencia ambigua

En este repositorio no aparece un clasificador específico para “VRChat”. X aplica clasificadores generales de texto y media. Un render 3D, un avatar anime, ropa ajustada, poses o iluminación pueden producir:

- Falso positivo: high precision e interstitial/drop.
- Falso negativo: no se genera el label esperado.
- High recall sin high precision: restricciones OON y age gating, pero no necesariamente interstitial para un adulto in-network.

El resultado depende de los modelos y labels efectivos, no de que el contenido venga de VRChat.

### Caso 17: El viewer interactúa mucho con NSFW

Phoenix usa la secuencia de acciones del viewer, por lo que las interacciones pueden cambiar las predicciones de acciones para contenido relacionado. Aun así, el post NSFW sigue sujeto a indexación y Visibility Filtering; una preferencia del viewer no elimina las reglas de seguridad.

### Caso 18: Monetización y anuncios

`home-mixer/models/brand_safety.rs` agrupa varios labels NSFW como riesgo medio. Además, `nsfw_author_ads` considera `POSSIBLY_NSFW_ACCOUNT`. Esto afecta la elegibilidad de anuncios y su colocación, pero el repositorio no debe interpretarse como una especificación completa de monetización o revenue share.

## 7. Qué no se puede concluir del repositorio

No se debe presentar como hecho aquello que el código no publica:

- Los prompts exactos de Grox.
- Algunas reglas Botmaker omitidas para evitar gaming.
- Todos los valores experimentales de producción.
- Los pesos internos completos del transformer Phoenix.
- La implementación de cada superficie Search, Explore, perfiles o notificaciones.
- El cableado exacto de los índices `nsfw_video` y `evergreen_nsfw_video` al feed For You.
- Una política legal completa para cada país.

El análisis sí permite afirmar la arquitectura y las reglas visibles: candidate generation, ranking, labels, `ALLOW`/`INTERSTITIAL`/`DROP`, age gating y diferencias entre in-network y out-of-network.

## 8. Referencias principales del código

- `README.md` — arquitectura, scoring y límites del repositorio.
- `home-mixer/candidate_pipeline/phoenix_candidate_pipeline.rs` — orden del pipeline.
- `home-mixer/params/param.rs` — pesos y parámetros.
- `home-mixer/scorers/ranking_scorer.rs` — combinación y ajustes del score.
- `home-mixer/filters/oon_nsfw_simclusters_filter.rs` — filtro NSFW de SimClusters.
- `home-mixer/candidate_hydrators/gizmoduck_hydrator.rs` — cálculo de `nsfw_author`.
- `visibility-filtering/rules/registry.rs` — orden de reglas.
- `visibility-filtering/rules/nsfw_interstitial.rs` — interstitials.
- `visibility-filtering/rules/nsfw_age_gating.rs` — edad, país y contenido sensible.
- `visibility-filtering/rules/tweet_label_drops.rs` — drops por labels del tweet.
- `visibility-filtering/rules/user_label_drops.rs` — drops por labels de cuenta.
- `visibility-filtering/rules/user_rules.rs` — drops por flags del autor.
- `phoenix-rankall-strato/lib/eventProcessing.strato` — consulta previa a VF y elegibilidad.
- `phoenix-rankall-strato/columns/phoenix_rank_all/phoenixRankAllCandidateProcessor.strato` — exclusión del índice.
- `grox/flows/ptos/task_write_safety_post_annotations_result_sink.py` — traducción de categorías a labels.
- `botmaker-rules/scarecrow/bot/NsfwTweetMediaProcessor.bot` — labels high precision/high recall.
- `safety-label-user-agg/postToUserLabelRules.strato` — agregación post → user label.
- `under-the-hood/strato/lib/underTheHoodLabels.strato` — descripciones de efectos de labels.

## 9. Anexo práctico: qué implica esto para el alcance de un post

> Sección orientativa para creadores, derivada de los defaults publicados y de las reglas visibles. No es una garantía de métricas: los pesos del transformer de Phoenix, las configuraciones de producción y los experimentos pueden diferir de estos valores.

### 9.1 Lo que puede ayudar a aumentar el alcance

1. **Las shares son la acción más valiosa del score publicado.** Compartir enlace copiado pesa `20.0`; compartir por DM y citar pesan `5.0`; el like pesa `0.5` (`home-mixer/params/param.rs`). Pedir a la comunidad que comparta el enlace es la palanca más fuerte que aparece en los pesos publicados.

2. **Las respuestas entre follow mutuo reciben un boost de +15.** `BidirectionalFollowReplyWeightBoost = 15.0` (`param.rs`): si el viewer te sigue y tú le sigues, el peso de la respuesta pasa de `5.0` a `20.0`, solo en posts originales (`ranking_scorer.rs`). Fomentar hilos de respuesta con followers mutuales puntúa por encima de un like.

3. **Cold start real: cuentas pequeñas con posts originales y frescos.** Los umbrales publicados son `ColdStartFollowerCap = 1000`, `ColdStartImpressionThreshold = 1000`, `ColdStartMaxPostAgeSecs = 86400` y slots de boost 15-16 (`param.rs`, `author_cold_start.rs`). La elegibilidad exige post original (ni reply ni repost), dentro del primer día y con pocas impresiones. Para cuentas de menos de 1.000 seguidores, cada post original en las primeras 24 horas compite por ese boost.

4. **Publicar espaciado en lugar de en ráfagas.** La diversidad de autor decae `0.5^k` con floor `0.25` (`param.rs`, `ranking_scorer.rs`): el segundo post del día vale ~0.63×, el tercero ~0.44× y el cuarto ~0.34×. Varias publicaciones seguidas se canibalizan el score entre sí.

5. **Vídeos de al menos 10 segundos activan un término extra.** `MinVideoDurationMs = 10000` habilita el peso `VqvWeight = 0.05` (`param.rs`, `candidates_util.rs`). Los vídeos más cortos no generan ese signal.

6. **El tiempo de lectura suma al score.** `ContDwellTimeWeight = 0.004` por segundo de dwell (`param.rs`). El contenido que se lee entero puntúa más que el que se scrollea.

7. **Los posts nuevos tienen un pequeño bonus in-network.** `PostUnexploredWeight = 0.02`, solo para seguidores (`param.rs`). Publicar cuando la audiencia está activa aprovecha el bonus de novedad.

8. **La retención de seguidores multiplica el score.** El descuento out-of-network es `0.75` (`param.rs`): el público que no sigue al autor vale un 25 % menos por post. El feed de seguidores (Thunder) es la vía principal; el descubrimiento es el bono, no la base.

9. **La originalidad ayuda a pasar el re-ranker.** VMRanker usa DPP con `VMRankerDppTheta = 0.65` (`param.rs`): los posts demasiado similares a otros ya colocados en el slate se reordenan hacia abajo.

10. **La propia actividad del viewer entrena el modelo.** La secuencia de acciones recientes es la entrada principal de Phoenix (README). Interactuar con una comunidad hace que el retrieval recupere y puntúe contenido similar para ese viewer.

### 9.2 Lo que conviene evitar

1. **Contenido que genera rechazo activo.** Pesos negativos publicados: report `-234.0`, mute `-58.8`, not interested `-43.2`, block `-31.2` (`param.rs`). Un solo “no me interesa” pesa más que decenas de likes, y los patrones agregados de blocks y reports alimentan además los modelos de salud de cuenta (Agatha).

2. **Patrones de spam, aunque haya seguidores.** Los labels `SPAM`, `PDNA` y `BOUNCE` son drops de la base y aplican también in-network (`visibility-filtering/rules/registry.rs`). No es una reducción de alcance: el post no se sirve a nadie.

3. **NSFW como estrategia de alcance.** Un post NSFW queda fuera del índice general de Phoenix (`phoenix-rankall-strato/columns/phoenix_rank_all/phoenixRankAllCandidateProcessor.strato`), los autores con flag NSFW se filtran del descubrimiento de SimClusters (`home-mixer/filters/oon_nsfw_simclusters_filter.rs`) y los labels producen drops OON y age gating. Además, la acumulación de `NSFW_HIGH_PRECISION` (3 de 5 posts) aplica un user label de 7 días que también bloquea OON los posts SFW posteriores.

4. **Reposts y replies con expectativa de alcance.** Los reposts y respuestas de cuentas no seguidas se filtran antes del ranking (`home-mixer/filters/oon_retweet_reply_filter.rs`). En For You solo circulan in-network.

5. **Depender de posts viejos.** `AgeFilter` descarta posts de más de 48 horas (`home-mixer/params/config.rs`) y los ya servidos se excluyen durante la ventana publicada (`param.rs`).

6. **Clickbait sin permanencia.** “Not dwelled” pesa `-0.02` (`param.rs`) y el valor del clic (`0.4`) se pierde con un bounce rápido.

7. **Contenido sensible para público que no puede verlo.** Menores, logged-out y viewers sin edad en países gating reciben `DROP` aunque tengan opt-in (`visibility-filtering/rules/nsfw_age_gating.rs`).

8. **Optimizar métricas que el score no premia.** Visitas de perfil pesan `0.0` y expandir foto `0.05` (`param.rs`); el score publicado se concentra en acciones de contenido, shares y tiempo de permanencia.

9. **Esperar descubrimiento para usuarios nuevos.** El factor OON publicado para usuarios nuevos es `0.00001` (`home-mixer/params/config.rs`): hasta que un usuario nuevo sigue varias cuentas, su feed es prácticamente solo in-network.
