平台说"没听到"的时候,最直觉的反应是停下来重说——而那恰恰是亲手制造它抱怨的那件事。这套守卫的目标从来不是"像真人说话",而是像真人那样守规矩。
打断 = 两步:① 立即停止当前播报;② 把播报队列整个清空。真实代价是损失这一轮答案的后半截。
自我强化死循环:打断 → 队列清空 → 无内容可播 → 继续沉默 → 平台静默超时(23~26s)再发提示 → 又被当插话 → 又打断……
该场成绩:入队 47 批 / 只播出 8 批(83% 丢弃),播报总时长占全场 12%。
关键测量:gap_probe 测得批间纯静音仅 2.0s / 2.5s(健康);18.9s / 58.8s / 52.9s 那些大空隙全部来自打断后清空队列,不是分批造成的。
若无这次测量,很可能去优化分批策略——一个完全错误但看起来很合理的方向。
| 分类 | 判定 | 动作 |
|---|---|---|
| strong_nudge | 命中 NUDGE_STRONG_RE(明确"我没听到/请再说/回答不完整") | exempt_nudge——既不等待、也不打断 |
| soft_nudge | 命中 NUDGE_SOFT_RE(语义模糊) | 按正常提问处理(保留打断能力) |
| normal 且 ≥12 字 | SIM_BARGE_IN_MIN_CHARS | interrupt(立即停播 + 清空队列) |
| normal 但 <12 字 | 短过渡语 | mark 仅记时刻 |
反直觉钩子 1:平台的"没听到"恰恰发生在我们正在播、但它没听清的时候(sim4 实测 micPeak 低至 0.010~0.04)→ 此时打断 = 亲手制造它抱怨的那个"没听到"。
豁免的第二层作用:催场句不刷新 lastFinalTs → 不触发"不抢话"等待窗口。未分级时一句话同时制造两个坏事:① 拖住播报 ② 若正在播就打断。
平台静默超时后还会发很短的过渡语(嗯、好的、有时只是半句)→ 被判成 normal → 打断 + 清空 → 整轮答案作废。门槛 SIM_BARGE_IN_MIN_CHARS = 12。
真人被"嗯""好的"打断是常事,但不该因此把整段答案丢掉。
反向限定(比门槛本身更重要):短句保护只对 normal 生效。soft_nudge("没关系""等一下")虽短但语义模糊,更可能是真实插话 → 必须保留打断能力,否则成过度豁免。
收窄原则:宁可漏判(退回改动前行为),绝不误伤正常提问。
真实误报:早期词表含裸子串 重复 / 订阅 → 面试官讲业务的"消息重复消费""发布订阅"被判成平台纠正(sim4 实测误报)。现在只收整句级特征。
NUDGE_STRONG_RE(触发豁免):好像没有听到 / 没有听到您的声音 / 听不到您的声音 / 听不到我的声音 / 麻烦再说一次 / 请再说一次 / 回答不完整 / 您没有回答NUDGE_SOFT_RE(仅审计,不豁免):您能具体讲讲 / 回答比较简略 / 没有回答 / 自我介绍似乎还没说完 / 介绍似乎被打断 / 请您回到正题SOFT 是否升级豁免 → 由 3 场实测(sim16~18)审计数据决定,不预设。每次打断记账带 [kind=…] 标记,用于量化"打断其实是平台重问"的占比。
这些判断原先内联在 WS 回调里 → 只有平台真的说"没听到"才被执行到;而修复的目的恰恰是让平台不再催场 → 修好后永远不会被真跑覆盖。
出路:lib/guard.js 抽成纯函数(无浏览器 / 无 I/O),所有阈值与词表放 config.js,用离线回放驱动。
verify_all.js 离线回放闸门:hard = nudge / stream;soft = barge / stutter / wire_test;退出码 3 = 不得开场(有牙齿,不是警告)。
关键断言:一条催场句到达后运行状态不得改变——不刷新 lastFinalTs、不触发 stopFlagAt、不清空队列。一条断言锁住三个副作用。
| # | 守卫 | 参数 |
|---|---|---|
| 1 | 不抢话:说完到开口至少隔 1200ms;等到 6000ms 仍在说 → 放弃本轮 | SIM_IDLE_GUARD_MS / SIM_MAX_WAIT_MS |
| 2 | 等待留痕:答案就绪后超 15000ms 未开口 → 记账 | SIM_WAIT_LOG_MS |
| 3 | 重音检测:自相关 0.98、间隔 <0.5s 才算可疑;命中重合成一次,仍中则记账不播 | SIM_STUTTER_* |
| 4 | 播前守门:解码测非空/时长/RMS,不过不播;测量异常则记账照播 | — |
| 5 | 通道守卫:开场 15s 内必须见过 WS open;断线容忍 60s 才 FATAL | ASSIST_WS_* |
第 5 条立项理由:sim2 实测开跑 38.8s 后 WS close 且未重连 → 0 轮跑完 11 分钟还"归档成功"。
最坏的情况不是失败,是假成功。失败会让人去看,假成功会让人以为一切正常。
场级红旗:看门狗 ≥2 / 等待过久 ≥3 / 播报中平台麦克风线 60s 零电平 → session_red_flag,只判败不中止。验收六项:打断 ≤2、等待过久 = 0、批作废率 ≤10%、轮完成 ≥5、无停滞 >30s、无红旗。
教的是在该停的地方停下来,不是怎么骗过平台。从未做任何反检测与伪装,摄像头始终真人。
AGENTS.md §「模拟真人」守卫子系统(三分类三动作、收窄原则、自指悖论、场级红旗与验收六项);autobot/lib/guard.js(classifyFinal / decideFinal / applyFinal,纯逻辑无 I/O);autobot/config.js SIM_* 与 NUDGE_STRONG_RE / NUDGE_SOFT_RE 词表及注释(sim4 / demo 场实测依据);verify_all.js 离线回放闸门。