Files
yunke/docs/superpowers/plans/2026-09-08-management-batch-a-verification.md
T

164 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 批次A Task 0 核实记录:五项核实 + 回测名单
- **日期**:2026-09-09
- **方式**:`docker exec -i yunke-mysql-1 mysql -uyunke -pyunke yunke -e "<SQL>"`(容器名以 `docker ps` 实测为准,确认为 `yunke-mysql-1`)
- **用途**:本记录的全部结论直接约束批次A(数据底座)后续任务的实现细节;偏差处显式标注「影响 Task N」。任务编号引用 [2026-09-08-management-console-batch-a-data-foundation.md](./2026-09-08-management-console-batch-a-data-foundation.md)。
- **数据快照范围**:`stat_daily_staff` / `msg_daily_stats` 覆盖 20251024 ~ 20260907;`phone_call.start_call_time` 覆盖 2025-10-18 ~ 2026-09-05。
---
## ① 员工主数据(staff 表)
| 指标 | 实测 |
|---|---|
| staff 总数 | **41**(与计划假设 ≈41 一致) |
| `is_on_job=1` | 41(全部在职) |
| `wechat_account` DISTINCT user_id | 41 |
| `whatsapp_account` DISTINCT user_id | 20 |
| 微信幽灵账号(user_id 不在 staff) | **0** |
| WA 幽灵账号(补充核实) | **0** |
| `stat_daily_staff` DISTINCT user_id | 40(其 user_id 全部在 staff 内;员工 `FD685A5620184156BE75A8D73FB72F64` 无任何消息统计行) |
**结论**:账号表 → staff 无幽灵映射,`known_user_ids` 过滤(v2 §1.3 #11)零损耗,不会意外丢行。两个渠道的 account_map 产出 user_id 均能落到 staff。**无偏差,Task 5/6 按计划实现即可。**
---
## ② phone_call 列与单位
表结构关键列:`call_id`(PK)、`channel`、`start_call_time`(bigint)、`call_duration`(int)、`call_status`(int)、`incoming_call`(int)、`user_id`、`call_number`、`fetched_at`、`updated_at`。
### channel 分布
| channel | 行数 |
|---|---|
| `voice_call` | 2,504 |
| `wa_voice_call` | 686 |
| 合计 | **3,190**(与已知 3,190 条一致) |
### call_duration 单位:**秒**(确认)
| 指标 | 实测 |
|---|---|
| 总和 | 263,651 秒 = **73.24 小时**(对照已知约 73 小时,吻合) |
| 均值 | 82.65 秒(对照预期均值 ≈82 秒,吻合) |
### call_status × duration 交叉
| call_status | 行数 | duration=0 | duration>0 | 语义判定 |
|---|---|---|---|---|
| 1 | 1,508 | 31 | 1,477 | **接通**(含 31 条 0 秒即挂) |
| 2 | 1,682 | 1,682 | 0 | **未接通**(未接/拒接/取消,与方向无关) |
### incoming_call 分布
| incoming_call | 行数 | 语义 |
|---|---|---|
| 1 | 1,764 | 呼入 |
| 0 | 1,426 | 呼出 |
### start_call_time:**毫秒 epoch**(确认)
13 位整数;`FROM_UNIXTIME(x/1000)` 解出 max = 2026-09-05 16:00:55(合理近期),按秒解释则超范围。min = 2025-10-18。与 `message.timestamp` 毫秒同口径。
### call_number 形态(按 channel 完全可分)
- `voice_call` → 微信 ID:`wxid_*` 或自定义微信号(`csf7169708`、`yuanye751380`、`Maple_1988` 等)
- `wa_voice_call` → WA JID:`2348182388888@s.whatsapp.net` 等
### 与计划默认假设的偏差(重要)
1. **计划假设 #4「PhoneCall.channel 是通话类型(phone_call/voice_call)非消息渠道」不完全成立**:实测无 `phone_call`(蜂窝)值,且 `wa_voice_call` **能**从 channel 列判别 WA。计划 Task 5 注释「voice_call 行无法从列判别微信/WA」不成立。**影响 Task 5**:`_followup_exists` 可按渠道收窄——`voice_call` 只查该员工 wechat 账号的 1:1 消息、`wa_voice_call` 只查 whatsapp 账号(当前双渠道任一匹配的写法也不会错——wxid 不会撞 WA JID,仅多一次无效查询;收窄属优化非必需)。
2. `call_duration` 单位=秒、`start_call_time`=毫秒 epoch:**与计划默认一致,Task 5 无需换算**(`day_bounds_ms` 直接用)。
3. 接通判定:计划默认 `duration>0`。实测 `call_status=1 AND duration>0` = 1,477 行,`duration>0` 口径与之差 31 行(31 条接通但 0 秒,占 1.0%)。**影响 Task 5**:`answered=dur>0` 口径可用;若追求语义精确可改 `call_status=1`(含 0 秒接通),差异 ≤1%,实现时任选其一并在表注释写明。
---
## ③ customer 归属字段填充率
| 指标 | 实测 |
|---|---|
| 总行数 | 16,339 |
| `user_id` 填充 | 16,339(**100%**) |
| `owner_account_id` 填充 | 16,339(**100%**) |
| `delete_flag=1` | 53 |
分渠道:wechat 7,040(owner 填充 7,040)/ whatsapp 9,299(owner 填充 9,299)。
### 两条归属路径一致性(全表校验,非抽样)
`customer.user_id` vs `owner_account_id → wechat_account.wx_id / whatsapp_account.uid → user_id`:
| 渠道 | 校验行数 | 一致 |
|---|---|---|
| whatsapp | 9,299 | 9,299 |
| wechat | 7,040 | 7,040 |
**结论**:两条路径 100% 等价、零冲突。生命周期归属覆盖面完整。**影响 Task 6**:默认 `owner_account_id → account_map → user_id` 路径确认可用;`customer.user_id` 列可直接当冗余等价路径使用(如需省一次 join,实测安全)。
补充观察(**影响 Task 3/6 的 peer 对齐**):`customer.friend_id` 形态有三种——微信 `25984981693625561@openim`、WA `12022946448@s.whatsapp.net`、WA `108976926654482@lid`。与 `message.talker_id` 对齐时须注意后缀形态一致(Task 3 实现 peer 匹配时以此为准,不做猜测性截断)。
---
## ④ 群占比(msg_daily_stats,量化混合口径偏差)
| channel | peer_kind | 行数 | 消息量(send+recv) | 会话线程(cust_threads) |
|---|---|---|---|---|
| wechat | friend | 38,343 | 269,074 | 82,879 |
| wechat | room | 16,234 | 609,089 | 26,220 |
| whatsapp | friend | 11,673 | 77,994 | 14,178 |
| whatsapp | room | 866 | 8,086 | 1,402 |
| **合计** | | **67,116** | **964,243** | **124,679** |
占比汇总:
| 维度 | room 占比 | 说明 |
|---|---|---|
| 微信消息量 | **69.4%**(609,089/878,163) | 微信消息近七成来自群 |
| WA 消息量 | 9.4%(8,086/86,080) | WA 几乎纯 1:1 |
| 总消息量 | **64.0%**(617,175/964,243) | |
| 总会话线程 | **22.2%**(27,622/124,679) | |
**结论**:若现有看板首响/回复率不分 `peer_kind`,消息量维度被群污染 64%、线程维度 22%——污染主要来自微信侧(微信消息 69% 是群消息)。批次A `first_reply_fact` / `employee_metric_daily` 强制 `peer_kind='friend'` 过滤是必要的,不能沿用混合口径。
---
## ⑤ call_followup join 键(call_number ↔ message.talker_id,1:1 消息)
| channel | 分母(call_number 非空) | 命中(talker_id 匹配且非群消息) | 命中率 |
|---|---|---|---|
| `voice_call` | 2,504 | 2,378 | **95.0%** |
| `wa_voice_call`(补充核实) | 686 | 681 | **99.3%** |
**结论**:双渠道命中率均远超 50% 阈值,`call_followup_count` 一期**高置信**,无需降级标记、无需在口径中注记低置信。**影响 Task 5**:24h 跟进判定按计划实现;未命中的 5%多为客户删除/无文字往来的纯通话对象,属正常损耗。
---
## 回测员工名单
选取依据:消息量/WA 量/活跃群排名 + 低样本端(见文末各候选分渠道数据)。覆盖:微信为主、WA 为主、群运营为主、高负载、低样本(前三类与高负载有合并)。
| # | user_id | 名字 | 覆盖类型 | 关键数据(20251024~20260907) |
|---|---|---|---|---|
| 1 | `369D257EEC9A4357935FDE19DDD99CAA` | 王云青 | **高负载 + 群运营为主 + 微信为主**(合并) | 消息量 #1(162,740:微信 162,371 / WA 369);活跃群 #1(4,036);通话 431+9 |
| 2 | `9C0B195A2C234C829FF507E011B4B460` | 田瑞志 | **WA 为主** | WA 消息 9,986 / 总 11,597 = 86%;WA 通话 28 |
| 3 | `F99F6557C2904A7E8F4C5A3BD8A597A1` | 张士蓓 | **双通道混合**(WA 量 #1,群 #2) | 微信 91,936 + WA 12,529;活跃群 2,273;通话最多(471 微信 + 97 WA) |
| 4 | `DC48798A5EA24DBB8B31A89CB858E08B` | 15639270965 | **纯微信无 WA 行**(验证 WA 缺失路径) | 微信 78,680,`stat_daily_staff` 无 whatsapp 行;通话 3 |
| 5 | `946C08639BF84DFEBBF5EC2A607AE1FA` | 18539430257 | **低样本**(验证空数据路径) | 消息 8 条,无群、无通话、无 WA |
> 名单中的 #1/#3 建议作为 Task 8「本地全量回填实测」的 2 名回测员工(数据最厚、双通道+通话+群全齐)。
---
## 偏差汇总(对后续任务的约束清单)
| # | 偏差/确认 | 影响 |
|---|---|---|
| 1 | `phone_call.channel` 实测仅 `voice_call`(微信)/`wa_voice_call`(WA)两值,**无蜂窝 `phone_call` 值**;channel 可判别渠道,计划「无法从列判别微信/WA」结论修正 | Task 5(followup 可按渠道收窄,属优化非必需) |
| 2 | `call_duration` 单位=**秒**(263,651s=73.24h≈已知 73h);`start_call_time`=**毫秒 epoch** | Task 5(默认口径正确,无需换算) |
| 3 | 接通判定 `dur>0` vs `call_status=1` 差 31 行(1.0%),前者少计 31 条 0 秒接通 | Task 5(任选其一,注释写明) |
| 4 | `customer.owner_account_id` 填充 **100%**,与 `user_id` 列全表 100% 等价 | Task 6(默认 owner 路径确认;可直接用 user_id 列省 join) |
| 5 | `customer.friend_id` 有 `@openim` / `@lid` / `@s.whatsapp.net` 三种后缀形态 | Task 3/6(peer 对齐按实测形态匹配,勿截断) |
| 6 | 群消息占总消息量 64%(微信侧 69%) | Task 3/6(friend 过滤必须,佐证 spec 口径) |
| 7 | call_number↔talker_id 命中率 voice_call 95.0% / wa_voice_call 99.3% | Task 5(call_followup_count 高置信,不降级) |
| 8 | staff 41 行无幽灵账号;`stat_daily_staff` 仅 40 名员工有行 | Task 5/6(known_user_ids 过滤零损耗) |