name: wechat-recv-liveness-triage description: 判「微信是不是收不到消息了」的收信侧活性分诊——三态判据(没人说话 / Dozing 期整库写入冻结 / 真收信中断)、探针与真身路径、同段基线与禁区(禁 force-stop、禁读静态副本)、汇报口径。触发词:收信中断、收不到消息、微信静默、收信活性、isSend=0 空档、静默几小时、要不要 force-stop、DB 入库滞后。 version: 1.0
category: wechat
微信收信活性分诊(收信侧)
用途:一轮任务里读到「群里/私聊好几小时没有新消息」时,判它到底是
① 真的没人说话、② App 层写入冻结、还是 ③ 收信链路真断。
这是收信侧判读;发送侧闸口(进程 + hook 在线)见 wechat-login-gate,两者互不替代:
闸口 ready=true 只说明能发,不代表能收。
⚠️ 本 skill 为什么单独存在:本机 cron / wechat / meta 三族里「带判据」的 skill 全部
created_by=None⇒skill_manage的patch/write_file一律Refusing … not agent-created(零写入)。实测被拒名单含cron-round-triage(§18.3 收信判定)、unattended-round-reading-calibration(§二 单轮读数 ≠ 连续态)、unattended-round-escalation-discipline(§4 收信静默那条)、wechat-login-gate、probe-reading-verification等。 2026-10-01 19:00 轮连试 3 个目标全被拒(3 次白烧调用 + 3 条Refusing污染errors.log) ⇒ 新的收信侧实测落本 skill,别再逐个试探旧 skill。 相关但只读的判据层:cron-round-triage§18.3(收信中断误判)、unattended-round-reading-calibration§二(读数当轮现测 / 形态可跨轮)、unattended-round-escalation-discipline§1–§3(升不升级、发不发通知)。
一、三态判据(先看「最新一行是谁发的」)
主探针一次输出就能分完三态,别只看 isSend=0 那一半:
python3 -u ~/.hermes/skills/cron/cron-round-triage/scripts/recv_liveness_baseline.py 3
# 段 1: newest 12 messages(任意 talker,带 isSend) ← 判据在这里
# 段 2: 近 N 日逐小时 isSend=0 计数 ← 同段基线用
| 读数形态 | 定性 | 动作 |
|---|---|---|
isSend=0 有近期行 |
收信正常(空档只是没人说话) | 零动作 |
isSend=1 与 isSend=0 同期齐停 |
App / 系统冻结(Dozing 期整库写入冻结) |
观察项,零动作 |
isSend=1 有近期行、isSend=0 长时间为零 |
才成立「收信疑似中断」 | 走第三节复核,仍不得单轮定案 |
关键机理(这条判据为什么成立):我方外发(自动回复 / 日报发送)经 hook 落库是即时的, 不需要屏幕亮起。所以:
- DB 里连
isSend=1的行也停在同一时刻 ⇒ 停的是写入通道本身(App/系统冻结层), 与收信链路、网络、登录态无关; - 反过来说:只有当
isSend=0停、而同期存在isSend=1新行时,「收信不进来」才是独立信号。
⚠️ 只比 isSend=0 逐小时桶是假阳性高发口径:本机确有「收信中断」这类待查项,
当日空档 vs 前日同段有行时,读数看起来就是断了,很容易顺势升级成 force-stop。
(2026-10-01 19:00 轮实测:差点这么判 —— 见 references/2026-10-01-dozing-freeze-case.md。)
二、基线与口径(别用固定门槛)
- 读数滞后:
Dozing≈ 2h、醒着 ≈ 40min(DB 入库滞后是常态,不是故障)。 - ⚠️ 读三态必须走对库/表(2026-10-15 00:00 轮实测踩坑):
~/wechat-viewer/circle.db里的messages表不是微信消息表 (列 =id / conversation_id / role / content / created_at;拿createTime/isSend去查直接no such column: createTime) ⇒ 收信三态的唯一正确读法 =sys.path.insert(0, "~/wechat-viewer")+import wechat_db, 查它的message表(列 =createTime(毫秒 epoch)/talker/type/isSend), 且wechat_db.query()只吃 1 个参数(sql 字符串,无参数绑定)。要「最新isSend=1行」时:SELECT createTime, talker, isSend FROM message WHERE isSend=1 ORDER BY createTime DESC LIMIT 3。 - ⚠️
isSend=1通道天然稀疏:它只记我方外发(自动回复 / 日报发送)⇒ 若当天我方没发过消息, 「isSend=1无新行」不构成任何冻结证据(表里它最新可能是十几小时前)。判「同期齐停 ⇒ App 冻结」 之前先确认近期确实有过 isSend=1 行,否则该判据不可用,改用长链ANYCGI同分钟打点(§二 旁证)。 - ⭐ 文件级写入通道旁证(2026-10-15 16:00 轮实测新增,
isSend=1稀疏时的替代读数): 「App 到底还在不在写」还有一条独立于 sqlcipher 查询的读数 = 活动账号 DB 文件自身的 mtime:bash su -c "stat -c '%Y %s %n' /data/data/com.tencent.mm/MicroMsg/*/EnMicroMsg.db" | sort -rn | head -3 su -c "stat -c '%Y %s %n' /data/data/com.tencent.mm/MicroMsg/*/EnMicroMsg.db-wal" | sort -rn | head -2判据:-walmtime 停在数小时前 ⇒ 文件级零写,与「查询到的最后一行时间」互相印证(可排除 「读错库 / 读到静态副本」,同 §四 禁读静态副本那条);反之若-walmtime 新鲜而查询无新行 ⇒ 先怀疑自己读错账号/库(本机MicroMsg/下有 ~18 个同形目录,只有一个非 0 大小;活动账号靠wechat_db实际用的config.get_current_account()["db_path"]认定,别按目录名猜)。 实测形态(10-15):末条消息 13:04:51、EnMicroMsg.dbmtime 14:04:38、-walmtime 14:10:46 ⇒ 与「微信主进程 ≈14:07:45 重启(pid 6341→24538,ps -A -o PID,ETIME反推)」时刻吻合。 - ⚠️ 本机
ls是 toybox,不支持--time-style=+…(报Unknown option;经su -c包裹时甚至整条输出为空 ⇒ 极易被读成「目录不存在 / 没有文件」)⇒ 取时间戳一律stat -c '%y %s %n'或stat -c '%Y'+date -d @<epoch>。 - 必须与前一日同段比,不用固定 2h / 6h 门槛;凌晨 / 清晨数小时空档是常态 (本机实测:凌晨段经常 0~4 条)。
- ⚠️
cron-handoff-lifecycle/scripts/inbox_last_inbound.py的>6h ⇒ 判收信仍中断(真故障)是启发式,会假阳性(2026-10-13 23:00 轮实测):只要单个群(如 nmm)静默超 6 h 而其它 8 个 TGO 群照常在收,它就打印「真故障」——而权威三态判据看的是isSend=0是否仍在进来:该轮recv_liveness_baseline.py 3段 1 最新 12 行全为isSend=0、时间戳 23:01:00–23:01:13(8 群同刻收到同一篇分享)⇒ 收信链路正常,nmm 静默 = 「没人说话」态,零动作、不外发。 ⇒ 该探针只可用来读「哪个群最后一次来信 / 静默多久」,不得单独据其结论定「收信中断」;定性一律回段 1 的isSend三态。 - 单轮读数不下结论:至少「前日同段基线 + 跨轮 ≥2 次复读一致 + 任一活跃群出现新
isSend=0行」 三条同看。 - ⚠️ 夜间连续多轮同形态不得累加成「收信中断」:「上一轮也没行」不是增量证据
(形态可跨轮引用,读数当轮现测,同
unattended-round-reading-calibration§二)。 - 旁证(可选,用于排除「链路真死」):LSPosed verbose 段里的
ANYCGI url=(predownload_check/getcdndns/findersync)是否仍在同分钟打点 ⇒ 长链活着。 ⚠️grep -c newSync恒 ~0,不是断线证据。 - 用户侧「有没有未答来信」另用
~/tmp/check_user_reply.py <当日> <前日>(真身在~/tmp/, 不在任何 skill 目录;探针包nonwindow_round_probes.sh的 06 段就是它)。
三、真「疑似中断」的复核(三条同时成立才够升级资格)
- 空档超前日同段基线;
- 跨轮 ≥2 次复读一致;
- 长链不活(ANYCGI 无同分钟打点)。
三条同时成立 ⇒ 记观察项 + 交下一轮,仍不做 force-stop;要动手必须先拿到用户拍板。
四、禁区与汇报口径
- 🚫 禁止 force-stop 微信(丢平板登录、要扫码重登);轮内不动登录态。
- 🚫 禁止读静态副本判活性(要现场读 viewer 侧 DB / 跑探针)。
- 🚫 别把「探针读不到」写成「对象消失」(termux 侧可见集不完整,
pidof com.tencent.mm直连恒空 ⇒ 必须su -c pidof;同unattended-round-escalation-discipline§2.1)。 - 汇报口径:阴性/空读数只写「观察项 + 本轮形态 + 交下一轮复查条件」, 不写成故障;涉及用户可见动作(force-stop / 重发)一律先问。
五、支持文件
references/2026-10-01-dozing-freeze-case.md—— 三态判据的原始实测读数: 锁屏Dozing8h 期间「最新一行 =isSend=1」的完整证据表、10-01 vs 09-30 同段桶对照、 以及「差一步就误报收信中断」的临界点。
六、相关 skill(多为 created_by=None,只读参考)
- 发送侧:
wechat-login-gate(进程 + hook 闸口)、wechat-send-delivery-verification(送达签名)。 - 判读/口径层:
cron-round-triage§18.3、unattended-round-reading-calibration§二、unattended-round-escalation-discipline§1–§4。 - 数据侧:
wechat-db-access(EnMicroMsg.db查询)。