diff --git a/docs/superpowers/specs/2026-10-08-cc-ip-country-confirm-design.md b/docs/superpowers/specs/2026-10-08-cc-ip-country-confirm-design.md index 8bfef7f..99ddc57 100644 --- a/docs/superpowers/specs/2026-10-08-cc-ip-country-confirm-design.md +++ b/docs/superpowers/specs/2026-10-08-cc-ip-country-confirm-design.md @@ -17,7 +17,7 @@ | 职责 | 归属 | 理由 | |---|---|---| | 判定(有无码/建议国)、E.164 补全、状态机、邮件渲染 | **Python 确定性**(新模块 `cc_completion` + phonenumberslite) | 状态不可能被幻觉;可离线确定性测试;邮件触发不押在 LLM | -| 客户答语理解(肯定/否定/国名) | **extractor LLM**(schema 加 `cc_reply` 可选字段,单轮无状态分类) | "yeah that's right"/"naur"/"我在迪拜"正则极脆弱,恰是 LLM 强项;extractor 本每轮跑,零额外调用 | +| 客户答语理解(肯定/否定/国名) | **extractor LLM**(schema 加 `cc_reply` 可选字段,单轮无状态分类) | "yeah that's right"/"naur"/"我在迪拜"正则极脆弱,恰是 LLM 强项;extractor 本每轮跑,零额外调用。**双门控**:extractor.md 声明"仅当客户在回应号码确认时填写 cc_reply";Python 侧仅在 `_cc` 等待态(未 confirmed 且 attempts 未耗尽)时消费——防止对无关问题的 yes 被误当确认 | | 话术生成与确认句必出 | 提醒注入 + **既有墙骨架**(白名单放行/缓冲替换——四轮生产实测过的机制) | GLM 对反惯性指令 0/8 服从的血泪教训,确认回显必须墙保 | ## 3. 判定树(`cc_completion.classify(number, ip_iso)`) @@ -42,10 +42,17 @@ raw_info["_cc"] = { "canon": "0712345678"}} ``` -- **canon 组**:phone 与 whatsapp 同号(canon 相同)共享一个确认流,确认一次; - 不同号各自独立状态——**换号(canon 变化)即重置该组状态机重走判定树** - (结构性解决"改号残留":旧补全永不跟随新号) -- attempts 只被 canon 变化重置;国名重述不重置(防"无限换国名") +- **canon 组**:phone 与 whatsapp 同号(canon 相同)共享一个确认流,确认一次 + (实现:`_cc` 以 canon 字符串为组键或渠道间 canon 相等时联动,attempts + 以组为计数主体);不同号各自独立——**换号(canon 变化)即重置该组状态机 + 重走判定树**(结构性解决"改号残留":旧补全永不跟随新号) +- **source 语义钉死**:`prefix_normalized` → **confirmed=true**(码是客户自己 + 写的,首封**无**"未经确认"标注);`customer_stated`=客户报国名重算后确认; + attempts 耗尽落定时 source 改写为 `fallback`(标注保留"未经客户确认"); + 标注按 `(confirmed, source)` 分派而非仅 confirmed +- attempts 只被 canon 变化重置;国名重述不重置(防"无限换国名");no_ip 路径 + 上限 1 轮(attempts 上限口径与邮箱轻补解锁条件=「confirmed=true 或 + attempts 耗尽或 source∈{prefix_normalized,no_ip,fallback}」统一) - **回显确认轮**(NEED_CC 且有建议国):AI 注入逐字句 "…reach you at {intl} — is that right?"(中英双语);**墙白名单**放行该精确号码 (`no_contact_value(allow_number=...)`,逐匹配段 digits_only 比对,只放 @@ -65,6 +72,27 @@ raw_info["_cc"] = { - **存量迁移**:升级部署时存量 `_cc_asked=True` 且号码裸的会话 → 映射为 `_cc{confirmed:false, source:fallback}`(已问过,不再追问,直通邮箱轻补) +## 4b. 提示词层改写(终审补——不改则回显机制与红线自相矛盾) + +v2 核心是让 AI **回显补全号**,而现行提示词全线教的是"不回显+请重发"—— +不改提示词,GLM 会拒写号、确认句墙轮轮整段替换(重演锚点竞争教训): + +1. **system.md 五处禁令例外句**(:59/:175/:223/:229/引导策略节)从"号码缺国家 + 代码时可请客户重发完整号一次"改为"号码缺国家代码时,按系统提醒**回显补全 + 后的完整号码**请客户确认(仅系统提供的号码,禁止自编)" +2. **好差示例**(裸号组)改为回显确认形态;新增差例:"AI 自己拼号码/回显客户 + 裸号原文"——只允许回显系统注入的补全号 +3. **conversation.py CC 轮让位句**("回复中绝不写出号码数字")改为"回复中 + 绝不写出号码数字——**唯一例外是系统提供的补全号原文**(逐字)" +4. **确认句墙检测词钉死**:缓冲裁决标准 = **系统注入的 e164(digits_only + 等值)在场**(辅锚 "is that right"/"对吗"),替换现有 "country code" 检测 +5. **测试迁移补项**:tests/test_system_prompt_dual_contact.py 全部断言按新 + 语义更新(五处例外句/好差示例/模板句同源) +6. **拆除/改造清单**(206beae..cbf234d 刚上线机制的处置):`_CC_ASK_EN/_ZH` + 追问句 → 改为回显确认模板(`_CC_ECHO_*`,与 reminder/墙三方同源); + `_CC_WALL_*` 检测词替换(见 4);`_cc_asked` 计数 → 存量映射(§4)+ + 新代码不再写入;`_contact_completion_note` 的 cc 分支重写(判定树挂接) + ## 5. 邮件/推送时序(需求方定案:首封即发补全号) | 时点 | 发什么 | 标注 | @@ -81,12 +109,20 @@ raw_info["_cc"] = { 补全、后台显裸号"的分裂) - 邮箱轻补串行:号码确认流落定(confirmed 或 attempts 耗尽)后才注入 -## 6. IP 入口与基础修复 +## 6. 管道接入点与 IP 入口(终审钉死) -- `/session` 路由注入 `Request`,XFF 第一段合并进 `conv.client_info`(WS 路由 - 已有同款;chat_rest.py:107 只喂限流修不到数据流) +- **两个钩子**(锚点错了"首封即发补全号"会静默失效): + 1. **轮末**:联系方式四层合并之后、`_maybe_send_lead_email` **之前** + (conversation.py 约 :500-526 区间)同步跑判定树写 `_cc`——首封补全号 + 与推送派生都依赖它 + 2. **轮前**:reminder 构建时读 `_cc`,等待态注入回显确认句(4b-3 让位句) +- `/session` 路由注入 `Request`,XFF 第一段合并进 `conv.client_info` + (**服务端 XFF 优先于客户端自报 ip**——WS 现状是客户端覆盖服务端、可伪造, + 一并修正);chat_rest.py:107 只喂限流修不到数据流 - `ip_service` 新增 `resolve_region_code(ip) -> ISO`(iptocc 直透); **修既有 bug**:`"AU": "加拿大"` 重复键(应为 CA) +- 面板同步载体:`ev.contact_info` 值尾注(canon() 纯数字提取,尾注不影响 + 24h 去重/更正判定) ## 7. 依赖与测试 @@ -99,7 +135,10 @@ raw_info["_cc"] = { 4. 邮件时序(首封带补全+标注、确认后不补发、改号走更正、no_ip 兜底) 5. 墙(白名单精确放行:同号放/异号拦;确认句缓冲替换) 6. 存量迁移;推送 contact 纯 e164;`NAME_TO_REGION` 映射 - 7. 真实 LLM 验收(cc_reply 分类质量、回显确认全流程、误判对照) + 7. 提示词静态断言(4b-5):五处例外句新语义/回显好差示例/让位句例外/ + _CC_ECHO 三方同源 +8. 真实 LLM 验收(cc_reply 分类质量与门控、回显确认全流程、误判对照—— + 无关问题的 yes 不得触发确认) - 既有测试迁移:D1 断言"confirmed 即发"若 fixture 用本地格式号 → 更新为 "confirmed 且判定树已同步跑"(行为等价,渲染值变化)