---
title: "可见性过滤（Visibility Filtering）"
description: "visibility-filtering 按标签、关系、账号状态与国家，对每条帖子给出放行、提示、遮罩或丢弃的裁定"
---

> Documentation Index
> Fetch the complete documentation index at: https://x-algorithm.vergego.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 可见性过滤（Visibility Filtering）

## 这一页回答什么

- `visibility-filtering/`（下称 VF，即可见性过滤服务）对一条帖子和一位查看者给出哪几种裁定，每种裁定在内部对应哪些动作。
- 规则清单定义在哪里、按什么顺序执行；For You 用哪两个“安全级别”（safety level，即一张规则清单的名称），各含哪些规则。
- 规则读取哪些输入：帖子标签、账号标签、拉黑/静音/关注关系、受保护/封禁/停用状态、订阅、查看者设置与国家。
- VF 怎样实现“只在站外推荐中丢弃、对关注者放行”的规则。
- 国家下架与法律下架（takedown）怎样生效。
- `home-mixer` 怎样调用 VF，又怎样使用返回结果。

标签的来源见 [打标签规则](https://x-algorithm.vergego.ai/concepts/labeling-rules/)、[账号级信号](https://x-algorithm.vergego.ai/concepts/account-signals/)、[处置与标签聚合](https://x-algorithm.vergego.ai/concepts/enforcement/)。

## 核心结论

1. **排序和可见性是两套系统。** 排序决定帖子的先后，VF 决定帖子能否出现。VF 读取标签和关系，不读取模型预测分。
2. **对外有四种裁定，内部有七种动作。** README 列出 ALLOW / NOTICE / INTERSTITIAL / DROP 四种裁定。它们对应内部 `Verdict` 的三个分支：`Withheld`（Drop、Tombstone）、`Fosnr`（SoftIntervention、Appealable，即 NOTICE）、`Shown`。`Shown` 有三个“槽位”，分别可放标签遮罩、媒体遮罩和互动限制（`visibility-filtering/models/verdict.rs:20-29`、`visibility-filtering/rules/action_kind.rs:4-13`）。
3. **README 提到的 `rules/registry.rs` 在 2e2295b 中不存在。** 规则定义在 `rules/author_rules.rs` 与 `rules/tweet_rules.rs` 中。各安全级别的规则清单在 `rules/levels.rs` 中。
4. **For You 用两个安全级别。** 站内候选用 `TimelineHome`。站外候选、祖先帖、被引用帖用 `TimelineHomeRecommendations`（`home-mixer/candidate_hydrators/vf_candidate_hydrator.rs:70-106`）。后者是前者的超集，测试代码强制检查这一点（`visibility-filtering/rules/levels.rs:492-498`）。
5. **VF 先跑账号规则，后跑帖子规则；第一个“扣留”裁定结束评估。** VF 把每张清单按动作严重度稳定排序，Drop 排在遮罩之前（`visibility-filtering/rules/engine.rs:38`、`engine.rs:104-108`、`engine.rs:560-569`）。
6. **“只对站外生效”有两层实现。** 第一层是安全级别：站外专属规则只在 `TimelineHomeRecommendations` 中。第二层是规则的 `audience`（生效对象）：`NonFollowers` 规则对关注者不生效（`visibility-filtering/rules/rule_spec/engine.rs:76`）。
7. **作者本人总能看到自己的帖子。** 绝大多数丢弃规则的 audience 是 `NonAuthors` 或 `NonFollowers`，两者都排除作者本人（`visibility-filtering/rules/rule_spec/rule.rs:100-115`）。
8. **home-mixer 只剔除 Drop 一类。** home-mixer 剔除 `Drop`、`Tombstone`、`NotEvaluated`，保留 `Interstitial` 等其他结果（`home-mixer/filters/vf_filter.rs:22-27`）。`filter_tweets` 接口把 NOTICE 压成 Allow（`visibility-filtering/treatment.rs:608-640`）。

## 四种裁定与内部动作

| README 裁定 | 内部 `Verdict` | 动作（`ActionKind`） | 严重度 | `filter_tweets` 返回 | home-mixer 处理 |
|---|---|---|---|---|---|
| DROP | `Withheld` | `Drop` | 17 | `Drop` | 剔除 |
| DROP | `Withheld` | `Tombstone`（显示“此帖不可用”占位） | 16 | `Drop` | 剔除 |
| NOTICE | `Fosnr` | `Appealable`（作者看到可申诉提示） | 18 | `Allow` | 保留 |
| NOTICE | `Fosnr` | `SoftIntervention` | 8 | `Allow` | 保留 |
| INTERSTITIAL | `Shown.media` | `MediaRestriction`（模糊遮罩） | 10 | `Interstitial` | 保留 |
| INTERSTITIAL | `Shown.label_interstitial` | `LabelInterstitial`（公共利益/紧急提示） | 11 | `Allow` | 保留 |
| ALLOW | `Shown.engagement` | `LimitedEngagement`（禁止回复/转发等） | 6 | `Allow` | 保留 |
| ALLOW | `Shown`（三槽皆空） | — | — | `Allow` | 保留 |

依据：严重度与落点见 `visibility-filtering/rules/action_kind.rs:56-132`；映射见 `visibility-filtering/treatment.rs:608-640`。

FOSNR 通常解读为 “Freedom of Speech, Not Reach”（言论自由，不保证触达），源码未给出全称。Under the Hood 对 FOSNR 标签的说明是“帖子的可发现性仅限作者主页，所有人都能看到受限说明”（`under-the-hood/strato/lib/underTheHoodLabels.strato:75-98`）。`Appealable` 只对作者本人生效。它同时禁用一组操作，包括点赞、回复、转发、引用等，共 13 项（`visibility-filtering/rules/tweet_rules.rs:89-139`）。

## 规则的写法与执行顺序

一条规则由四个字段组成：`id`、`audience`、`when`（条件）、`action`（动作）。示例：

```rust
// visibility-filtering/rules/author_rules.rs:239-244
pub(super) const DO_NOT_AMPLIFY_USER_LABEL_DROP_UNSPECIFIED: UserRule = Rule {
    id: RuleId::DoNotAmplifyUserLabel,
    audience: NonFollowers,
    when: all![AuthorHasLabel(AuthorLabel::DoNotAmplify)],
    action: drop_post(DropAs::UnspecifiedReason),
};
```

`audience` 有四种取值（`visibility-filtering/rules/rule_spec/rule.rs:100-115`）：

| audience | 含义 | 展开条件 |
|---|---|---|
| `Everyone` | 对所有查看者 | 无 |
| `NonAuthors` | 查看者不是作者 | `!ViewerIsAuthor` |
| `NonFollowers` | 查看者既不是作者、也没关注作者 | `!ViewerIsAuthor && !ViewerFollowsAuthor`（`rule_spec/engine.rs:76`） |
| `OnlyAuthor` | 只对作者 | `ViewerIsAuthor` |

执行顺序如下：

```mermaid
flowchart TD
    A["账号规则清单 user"] --> B{"命中 Drop 或 Tombstone?"}
    B -- "是" --> W["Withheld: 结束评估"]
    B -- "否" --> C["帖子规则清单 post"]
    C --> D{"命中扣留或 FOSNR?"}
    D -- "扣留" --> W
    D -- "FOSNR" --> F["Fosnr: 结束评估"]
    D -- "否" --> E["填槽: 标签遮罩 / 媒体遮罩 / 互动限制"]
    E --> S["Shown"]
```

- VF 先跑账号规则，再跑帖子规则（`visibility-filtering/rules/engine.rs:560-569`）。
- VF 把每张清单按动作严重度降序稳定排序；同一动作内的规则保持列出顺序（`visibility-filtering/rules/engine.rs:38`）。
- 出现终结裁定（`Withheld` 或 `Fosnr`）后，VF 不再执行后面的规则（`visibility-filtering/rules/engine.rs:104-108`）。
- 遮罩类动作只“填槽”，不结束评估。同一槽位已被填时，VF 忽略后来的动作（`visibility-filtering/rules/engine.rs:196-258`）。
- 数据源失败时，规则结果为 `Unknown`。如果评估依赖“必需”数据源，VF 返回 `Partial`（`visibility-filtering/rules/engine.rs:144-177`）。

## 规则的输入

| 输入类别 | 例子（谓词） | 来源 |
|---|---|---|
| 帖子安全标签 | `TweetHasLabel(SPAM)`、`TweetHasLabel(NSFW_HIGH_PRECISION)` | `safety-label-source/` 读出的 `SafetyLabelMap`（`visibility-filtering/hydration/sources/safety_labels.rs:10-30`） |
| 账号标签 | `AuthorHasLabel(SpamHighRecall)` 等 16 种 | Gizmoduck（用户资料服务）的用户标签（`visibility-filtering/models/author.rs:20-37`、`hydration/decode/author.rs:200-243`） |
| 账号状态 | 封禁、停用、抹除、下线、受保护、`nsfw_user`、`nsfw_admin` | Gizmoduck safety 字段（`visibility-filtering/hydration/decode/author.rs:205-213`） |
| 关系 | 拉黑、静音、静音转发、关注、作者拉黑查看者 | `socialgraph`（`visibility-filtering/rules/author_rules.rs:42-65`） |
| 订阅与小圈子 | 超级关注（订阅者专属）、Trusted Friends | `visibility-filtering/rules/tweet_rules.rs:396-452` |
| 查看者设置 | 是否允许敏感媒体、是否登录、年龄、是否新账号 | `visibility-filtering/rules/tweet_rules.rs:294-394` |
| 国家 | 请求国家、法律下架国家、媒体地理限制 | `visibility-filtering/models/tweet.rs:74-98` |

## For You 的两个安全级别

`TimelineHome` 与 `TimelineHomeRecommendations` 的规则清单在 `visibility-filtering/rules/levels.rs:298-361`。下表按类别整理。“站外专属”指规则只出现在 `TimelineHomeRecommendations` 中。

### 账号规则（user 清单）

| 规则 | 条件 | audience | 动作 | 站外专属 | 定义 |
|---|---|---|---|---|---|
| `SUSPENDED_AUTHOR_DROP` | 作者被封禁 | NonAuthors | Drop | 否 | `author_rules.rs:7-12` |
| `DEACTIVATED_AUTHOR_DROP` | 作者已停用 | NonAuthors | Drop | 否 | `author_rules.rs:14-19` |
| `ERASED_AUTHOR_DROP_INACTIVE` / `OFFBOARDED_AUTHOR_DROP_INACTIVE` | 作者被抹除 / 下线 | NonAuthors | Drop | 否 | `author_rules.rs:21-33` |
| `PROTECTED_AUTHOR_DROP` | 作者是受保护账号 | NonFollowers | Drop | 否 | `author_rules.rs:35-40` |
| `VIEWER_BLOCKS_AUTHOR_DROP` | 查看者拉黑作者 | Everyone | Drop | 否 | `author_rules.rs:42-47` |
| `VIEWER_MUTES_AUTHOR_DROP` | 查看者静音作者 | Everyone | Drop | 否 | `author_rules.rs:49-54` |
| `NSFW_USER_AUTHOR_DROP_NSFW_MEDIA` | 作者自标 `nsfw_user` | NonAuthors | Drop | 是 | `author_rules.rs:155-160` |
| `NSFW_ADMIN_AUTHOR_DROP_NSFW_MEDIA` | 作者被审核员标 `nsfw_admin` | NonAuthors | Drop | 是 | `author_rules.rs:162-167` |
| `NSFW_*_USER_LABEL_DROP`（5 条） | 账号标签 NsfwHighRecall / NsfwHighPrecision / NsfwAvatarImage / NsfwBannerImage / NsfwNearPerfect | NonAuthors | Drop | 是 | `author_rules.rs:169-202` |
| `SPAM_HIGH_RECALL_USER_LABEL_DROP` | 账号标签 SpamHighRecall | NonAuthors | Drop | 是 | `author_rules.rs:204-209` |
| `COMPROMISED_USER_LABEL_DROP` | 账号标签 Compromised | NonAuthors | Drop | 是 | `author_rules.rs:211-216` |
| `READ_ONLY_USER_LABEL_DROP` | 账号标签 ReadOnly | NonAuthors | Drop | 是 | `author_rules.rs:218-223` |
| `IMPERSONATION_HIGH_PRECISION_USER_LABEL_DROP` | 账号标签 ImpersonationHighPrecision | NonAuthors | Drop | 是 | `author_rules.rs:225-230` |
| `ABUSIVE_HIGH_RECALL_USER_LABEL_DROP` | 账号标签 AbusiveHighRecall | NonFollowers | Drop | 是 | `author_rules.rs:232-237` |
| `DO_NOT_AMPLIFY_USER_LABEL_DROP_UNSPECIFIED` | 账号标签 DoNotAmplify | NonFollowers | Drop | 是 | `author_rules.rs:239-244` |

站外账号规则的分组常量：NSFW 组见 `levels.rs:322-330`，`OON_AUTHOR_LABEL_DROPS` 见 `levels.rs:65-72`。

`NotGraduated`、`AgathaSpamTopUser`、`EngagementSpammer`、`BlinkWorst`、`DownrankSpamReply` 五种账号标签只出现在通知类级别中（`levels.rs:89-100`），不出现在 For You 的两个级别中。

### 帖子规则（post 清单，两级共有）

| 类别 | 规则 | 条件 | audience | 动作 | 定义 |
|---|---|---|---|---|---|
| 关系 | `VIEWER_MUTES_RETWEETS_DROP` | 转发帖，且查看者静音了作者的转发 | Everyone | Drop | `author_rules.rs:56-65` |
| 违规 | `PDNA_DROP` | 帖子标签 PDNA | NonAuthors | Drop | `tweet_rules.rs:28-33` |
| 违规 | `BOUNCE_DROP` | 帖子标签 BOUNCE | NonAuthors | Drop | `tweet_rules.rs:35-40` |
| 垃圾 | `SPAM_DROP_UNDESIRABLE` | 帖子标签 SPAM | NonAuthors | Drop | `tweet_rules.rs:49-54` |
| 应急 | `FOR_EMERGENCY_USE_ONLY_DROP` | 帖子标签 FOR_EMERGENCY_USE_ONLY | Everyone | Drop | `tweet_rules.rs:56-61` |
| FOSNR | `FOSNR_{HATEFUL_CONDUCT,VIOLENT_SPEECH,ABUSE,CIVIC_INTEGRITY}_DROP` | 对应 FOSNR 帖子标签 | NonAuthors | Drop | `tweet_rules.rs:141-167` |
| 帖子状态 | `NULLCASTED_TWEET_DROP` | 帖子是 nullcast（不进时间线的帖子），非转发、非社区帖 | Everyone | Drop | `tweet_rules.rs:215-220` |
| 帖子状态 | `STALE_TWEET_DROP` | 帖子已被编辑，不是最新版本 | Everyone | Drop | `tweet_rules.rs:222-232` |
| 法律 | `LEGAL_TAKEDOWN_DROP` / `LOCAL_LAWS_TAKEDOWN_DROP` | 请求国家命中下架 | NonAuthors | Drop | `tweet_rules.rs:244-256` |
| 年龄门控 | `SENSITIVE_VIEWER_{LOGGED_OUT,UNDERAGE,NO_STATED_AGE}_DROP_*`（9 条） | 未登录 / 未成年 / 未填年龄，且帖子带成人或血腥标签 | NonAuthors | Drop | `tweet_rules.rs:294-380` |
| 订阅 | `EXCLUSIVE_TWEET_DROP_*`（3 条） | 订阅者专属帖，查看者未订阅 | Everyone / NonAuthors | Drop | `tweet_rules.rs:396-424` |
| 小圈子 | `TRUSTED_FRIENDS_TWEET_DROP` | Trusted Friends 帖，查看者不在名单 | NonAuthors | Drop | `tweet_rules.rs:444-452` |
| 国家 | `GEO_RESTRICTED_MEDIA_DROP` | 媒体在请求国家受地理限制 | NonAuthors | Drop | `tweet_rules.rs:891-896` |
| 遮罩 | `NSFW_HIGH_PRECISION_BLUR_{NUDITY,SENSITIVE}` | 帖子标签 NSFW_HIGH_PRECISION，查看者未允许敏感媒体 | NonAuthors | 媒体遮罩 | `tweet_rules.rs:454-476` |
| 遮罩 | `GORE_AND_VIOLENCE_HIGH_PRECISION_BLUR` | 帖子标签 GORE_AND_VIOLENCE_HIGH_PRECISION | NonAuthors | 媒体遮罩 | `tweet_rules.rs:586-594` |
| 遮罩 | `NSFW_CARD_IMAGE_BLUR_SENSITIVE` | 帖子标签 NSFW_CARD_IMAGE | NonAuthors | 媒体遮罩 | `tweet_rules.rs:669-677` |
| 遮罩 | `NSFW_ADMIN_BLUR_SENSITIVE` / `NSFW_USER_BLUR_SENSITIVE_USER` | 作者或帖子被标 nsfw_admin / nsfw_user，帖子有媒体 | NonAuthors | 媒体遮罩 | `tweet_rules.rs:751-787` |

清单分组：`FOSNR_DROPS` `levels.rs:102-107`、`TAKEDOWN_DROPS` `levels.rs:109-112`、`AGE_GATING_DROPS` `levels.rs:114-124`、`EXCLUSIVE_CONTENT_DROPS` `levels.rs:126-131`、`HOME_BLURS` `levels.rs:133-140`。

### 帖子规则（只在 `TimelineHomeRecommendations`）

| 类别 | 规则 | 条件 | audience | 动作 | 定义 |
|---|---|---|---|---|---|
| 版权 | `DMCA_MEDIA_DROP` | 帖子含 DMCA 媒体 | Everyone | Drop | `tweet_rules.rs:884-889` |
| 成人/血腥 | `NSFW_USER_TWEET_FLAG_DROP` / `NSFW_ADMIN_TWEET_FLAG_DROP` | 帖子带 nsfw 标记 | Everyone | Drop | `tweet_rules.rs:898-910` |
| 成人/血腥 | `GORE_AND_VIOLENCE_HIGH_PRECISION_DROP` | 帖子标签 GORE_AND_VIOLENCE_HIGH_PRECISION | NonAuthors | Drop | `tweet_rules.rs:596-603` |
| 成人/血腥 | `NSFW_HIGH_RECALL_DROP` / `NSFW_HIGH_PRECISION_DROP` / `NSFW_CARD_IMAGE_DROP` | 对应帖子标签 | NonAuthors | Drop | `tweet_rules.rs:912-917`、`478-483`、`679-684` |
| 成人/血腥 | `SOFT_NSFW_NEW_USER_DROP` | 请求开启该开关、查看者是新账号、帖子标签 SOFT_NSFW | NonAuthors | Drop | `tweet_rules.rs:919-928` |
| 垃圾/链接 | `DO_NOT_AMPLIFY_DROP` | 帖子标签 DO_NOT_AMPLIFY | NonAuthors | Drop | `tweet_rules.rs:930-935` |
| 垃圾/链接 | `MALICIOUS_URL_DROP` | 帖子标签 MALICIOUS_URL | NonAuthors | Drop | `tweet_rules.rs:937-942` |
| 垃圾/链接 | `SPAM_HIGH_RECALL_DROP_UNDESIRABLE` | 帖子标签 SPAM_HIGH_RECALL | NonAuthors | Drop | `tweet_rules.rs:944-949` |
| 法律 | `BRAZIL_ELECTION_LEGAL_DROP` | 帖子标签 BRAZIL_ELECTION_LEGAL，且请求国家是 `br` | NonAuthors | Drop | `tweet_rules.rs:951-959` |
| 辱骂 | `FOSNR_ABUSE_INSULTS_DROP` | 帖子标签 FOSNR_ABUSE_INSULTS | NonAuthors | Drop | `tweet_rules.rs:169-174` |

分组：`OON_POST_DROPS` `levels.rs:147-152`；站外帖子规则整体 `levels.rs:348-359`。

2e2295b 中，`BRAZIL_ELECTION_LEGAL_DROP` 仍在 VF 规则清单中。上游在 10-26 移除的是 home-mixer 的 `Brazil2026ElectionFilter`，不是这条 VF 规则。

## 例子：只在站外推荐中丢弃、对关注者放行

例 1：账号标签 `DoNotAmplify`。

- 规则 `DO_NOT_AMPLIFY_USER_LABEL_DROP_UNSPECIFIED` 只在 `TimelineHomeRecommendations` 的账号清单中（`levels.rs:65-72`、`levels.rs:331`）。
- 它的 audience 是 `NonFollowers`（`author_rules.rs:239-244`）。
- 结果：关注者在 For You 的站内部分照常看到帖子；非关注者在推荐中看不到；作者本人不受影响。

例 2：帖子标签 `SPAM_HIGH_RECALL`。

- 规则 `SPAM_HIGH_RECALL_DROP_UNDESIRABLE` 的 audience 是 `NonAuthors`（`tweet_rules.rs:944-949`），且只在站外级别中（`levels.rs:147-152`）。
- 站内候选走 `TimelineHome`。该级别不含这条规则，所以关注者能看到帖子。
- 例外：VF 一律按站外级别评估被引用帖与祖先帖（`vf_candidate_hydrator.rs:76-81`）。被引用帖带 SPAM_HIGH_RECALL 时，`AncillaryVFFilter` 会连带剔除引用它的站内帖（`vf_candidate_hydrator.rs:155-160`）。

例 3：`FOSNR_ABUSE_INSULTS`。在 For You 两个级别中，它只在站外级别作为 Drop 出现（`levels.rs:359`）。在 `TimelineHomeHydration` 级别中，它拆成两条规则：对非关注者 Drop，对关注者 SoftIntervention（`tweet_rules.rs:176-199`）。

## 国家下架与法律下架（takedown）

1. tweet entity service 合并帖子的下架原因列表 `takedown_reasons`：帖子自身的原因加上作者账号级的原因（`takedowns/tweet-entity-service/TakedownReasonsTransform.scala:52-69`）。它只查询 `hasTakedown` 为真的帖子（同文件 `:52-55`）。
2. Gizmoduck 读取账号时，先删掉“不执行”的账号级下架。这些下架包括：国家码为 `xy`（全球版权）的 LegalRequest / UnspecifiedReason，国家码为 `xx`/`xy` 的 BystanderReport，以及全部 Dmca（`takedowns/gizmoduck/RedactUnenforcedTakedownsFilter.scala:68-78`）。该过滤器挂在读过滤链的末尾（`takedowns/gizmoduck/ReadFilters.scala:37`）。
3. VF 用请求国家做判断（`visibility-filtering/models/tweet.rs:74-139`）：
   - `LegalRequest(cc)` 与 `UnspecifiedReason(cc)` 归入“法律下架”；`Dmca` 映射为 `xy`。
   - `BystanderReport(cc)`（第三方举报，确认违反当地法律）归入“当地法律下架”，国家码为 `xx`/`xy` 的除外。
   - 国家码等于请求国家，或为 `xx`/`xy`（全球）时，即为命中。
4. 命中后，`LEGAL_TAKEDOWN_DROP` / `LOCAL_LAWS_TAKEDOWN_DROP` 丢弃帖子，作者本人不受影响（`tweet_rules.rs:244-256`）。两个 For You 级别都包含这两条规则（`levels.rs:310`、`levels.rs:343`）。
5. VF 单独判断媒体地理限制，满足任一条件即命中：允许列表非空且不含请求国家；拒绝列表含请求国家（`visibility-filtering/models/tweet.rs:92-98`）。

请求国家来自 home-mixer 传入的 `request_country_code`（`visibility-filtering-client/vf_client.rs:596-598`）。

## home-mixer 怎样调用 VF 并使用结果

```mermaid
flowchart LR
    SEL["TopK 选出的候选"] --> H["VFCandidateHydrator"]
    H -- "站内 id + 被转发原帖" --> L1["TimelineHome"]
    H -- "站外 id + 祖先帖 + 被引用帖" --> L2["TimelineHomeRecommendations"]
    L1 --> M["合并结果"]
    L2 --> M
    M --> F1["VFFilter: 剔除 Drop / Tombstone / NotEvaluated"]
    F1 --> F2["AncillaryVFFilter: 祖先、引用或被转发帖被丢弃时连带剔除"]
```

- 位置：VF 水合器是选后水合器（post-selection hydrator，在 TopK 选择之后运行），两个过滤器是选后过滤器（`home-mixer/candidate_pipeline/phoenix_candidate_pipeline.rs:485-513`）。只有进入 TopK 的候选才会查询 VF。
- 客户端：参数 `EnableXaiVfClient` 开源默认为 `true`，此时 home-mixer 调用 Rust VF；否则回退到 Strato 旧接口（`vf_candidate_hydrator.rs:60-65`、`home-mixer/params/param.rs:1350-1355`）。
- 批量与超时：每批 50 条，默认超时 400 ms（`visibility-filtering-client/vf_client.rs:249-251`）。
- 合并：同一 id 在两个级别都有结果时，站内结果覆盖站外结果（`vf_candidate_hydrator.rs:108-110`）。
- 剔除口径：`Drop`、`Tombstone`、`NotEvaluated` 被剔除；`Allow`、`Interstitial`、`Avoid`、`Downrank` 被保留（`home-mixer/filters/vf_filter.rs:22-27`）。
- 失败行为（依据代码推断）：
  - 响应中缺少某条帖子的结果时，客户端填入 `NotEvaluated`，该帖子被剔除。这是“失败即关闭”（`vf_client.rs:547-565`）。
  - 整批 RPC 失败时，客户端对每条返回错误（`vf_client.rs:567-580`）。水合器对该候选返回 `Err`（`vf_candidate_hydrator.rs:119-121`），框架不更新字段（`candidate-pipeline/hydrator.rs:63-69`），`visibility_action` 保持为空，`VFFilter` 保留该候选。这是“失败即放行”。
- 连带剔除：祖先帖（已墓碑化的除外）、被引用帖、被转发原帖中任一被判 Drop 或 Tombstone 时，候选本身被剔除（`vf_candidate_hydrator.rs:140-170`）。
- Interstitial 帖子留在信息流中。仓库中没有绘制遮罩的代码（上游 README Labeling Path 第 5 段）。
- “关注”时间线（按时间倒序）全部使用 `TimelineHome`（`home-mixer/candidate_hydrators/vf_following_candidate_hydrator.rs:11`）。

其他过滤器见 [过滤流水线](https://x-algorithm.vergego.ai/concepts/filtering-pipeline/)。

## 设计决策

| 决策 | 理由 |
|---|---|
| 规则用 Rust 常量声明，服务启动时校验 | 规则写错时，服务在接收流量前就失败（`visibility-filtering/rules/engine.rs:276-292`） |
| 按严重度排序，第一个扣留裁定结束评估 | 结果与规则书写顺序无关，最严重的处置总是最先判定 |
| 站外级别是站内级别的超集 | 站外推荐只会更严，不会更松；测试代码锁定这一点 |
| 大量规则用 `NonFollowers` / `NonAuthors` | 限制“放大”，不限制“表达”：作者和关注者仍能看到帖子 |
| NOTICE 与标签遮罩在 `filter_tweets` 中返回 Allow | 这两类属于展示层处理，For You 只需要知道帖子能否出现 |
| 缺少结果时填 `NotEvaluated` 并剔除 | 宁可少推，也不推未经检查的帖子 |

## 源码锚点

- `visibility-filtering/models/verdict.rs:20-29` —— `Verdict` 三分支
- `visibility-filtering/rules/action_kind.rs:56-132` —— 七种动作的严重度与落点
- `visibility-filtering/rules/levels.rs:298-361` —— For You 两个级别的规则清单
- `visibility-filtering/rules/author_rules.rs:155-244` —— 站外账号标签规则
- `visibility-filtering/rules/tweet_rules.rs:884-959` —— 站外帖子规则
- `visibility-filtering/rules/engine.rs:38`、`:84-142` —— 排序与折叠
- `visibility-filtering/rules/rule_spec/rule.rs:100-115` —— audience
- `visibility-filtering/models/tweet.rs:74-139` —— 下架与国家判断
- `visibility-filtering/treatment.rs:608-640` —— 裁定到接口动作的映射
- `takedowns/tweet-entity-service/TakedownReasonsTransform.scala:52-69` —— 合并帖子与账号下架原因
- `home-mixer/candidate_hydrators/vf_candidate_hydrator.rs:52-170` —— 分级调用与连带剔除
- `home-mixer/filters/vf_filter.rs:22-27` —— 剔除口径

## 相关页面

- [过滤流水线](https://x-algorithm.vergego.ai/concepts/filtering-pipeline/) —— home-mixer 全部过滤器
- [打标签规则](https://x-algorithm.vergego.ai/concepts/labeling-rules/) —— scarecrow 与 botmaker 如何写入标签
- [账号级信号](https://x-algorithm.vergego.ai/concepts/account-signals/) —— agatha、bdsm、user-cred-v2
- [处置与标签聚合](https://x-algorithm.vergego.ai/concepts/enforcement/) —— abuse-enforcement-service、safety-label-user-agg
- [Under the Hood 透明度报告](https://x-algorithm.vergego.ai/concepts/under-the-hood/) —— 用户能看到哪些标签
- [Grox 分类器](https://x-algorithm.vergego.ai/concepts/grox-classifiers/)、[媒体模型](https://x-algorithm.vergego.ai/concepts/media-models/) —— 帖子标签的模型来源
- [限流与 shadowban](https://x-algorithm.vergego.ai/guide/visibility-and-shadowban/) —— 白话版

Source: https://x-algorithm.vergego.ai/concepts/visibility-filtering/index.mdx
