> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Name Trust — 名字写入规则

> **Source of truth**: `callytics-common/src/db/schema/name-trust.ts`
> **对齐日期**: 2026-05-28

多个来源会写同一个 contact 的名字（webhook caller ID、RC Call Log API、AI 从转录提取、lead form、员工手动改）。Name Trust 是决定**哪个来源赢**的机制：给每个来源一个信任分，UPSERT 时高分覆盖低分。

存在 `contacts.first_name_trust_score`（smallint）里。用整数比较而非字符串枚举——SQL 里更快也更简单（设计见 callytics-common#160）。

## NAME\_TRUST 6 级

| 常量              | 分值  | 来源                            | 说明           |
| --------------- | --- | ----------------------------- | ------------ |
| `STAFF`         | 100 | 员工通过 UI 手动编辑                  | 最高优先级，系统永不覆盖 |
| `LEAD`          | 80  | 客户在 lead form 自报              | 客户本人填写       |
| `RC_API`        | 60  | RC Call Log API caller ID     | 权威电信数据，常为全大写 |
| `AI_TRANSCRIPT` | 40  | AI 从通话转录提取（如 "Hi, I'm Katie"） |              |
| `WEBHOOK`       | 20  | RC webhook 事件                 | 到达最早但质量最低    |
| `UNKNOWN`       | 0   | 历史/未知来源                       | 信任系统上线前的存量数据 |

所有写入方（transcribe-processor、ai-analysis-processor、message-processor、contacts-analyzer、studio-api）写 `first_name` 时都带上对应的 trust score。

## ON CONFLICT 覆盖逻辑

UPSERT 时按以下规则决定保留哪个 `first_name`：

```sql
CASE WHEN excluded.first_name_trust_score >= contacts.first_name_trust_score
     THEN excluded.first_name
     ELSE contacts.first_name END
```

- **高分覆盖低分**：新来源 trust score 更高 → 用新名字。
- **同分新值胜**：分数相等时（`>=`），用新写入的非空值（让同级来源的最新数据生效）。
- **低分不动**：新来源分数更低 → 保留原名字（例如 webhook 的 caller ID 不会覆盖员工手填的名字）。
