fix: 墙层审查修复——10位号穿透/CC轮回显closing用CC句/breach号码观测/拼接分隔
审查(With fixes)四项:
- Important-1: LONG_NUMBER_RE {9,17}→{8,17}——旧量词最小匹配 11 字符,
纯 10 位号(沙特裸号 0501234567,CC 模板范例市场本体)穿透。实测钉死
行为边界: 逗号不在字符类,"50,000,000" 千分位形态仍放行(与
"45,000 km" 同机制,审查预估会命中系漏算逗号);空格分隔 ≥10 位命中;
DN110/5000m/VIN 规格形态全放行
- Important-2: CC 触发轮回显被零号码墙拦下时(violation==no_contact),
closing 改用 CC 模板句而非 NO_CONTACT_ALREADY——GLM 有 3/3 回显倾向,
客户该收到追问而非"稍后联系"虚假承诺;价格墙路径不变。设计文档 §2
补记该裁决
- Minor-4: breach_rate.py 补号码回显(≥10位,与墙同形)与邮箱回显两条
观测模式,补上漏放观测盲区
- Minor-5: violated 收尾与已流出前缀之间补空格分隔("...xxxx? Got it —"),
空格随 closing 一起流出,客户所见与落库一致;CC/触发轮缓冲未流出,
emitted 恒空天然不受影响
测试 256 passed(253+3)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -199,7 +199,11 @@ def deflection_for(user_msg: str, rotate: int = 0,
|
||||
|
||||
# ---- 15.3: 零号码墙(doctrine v2) ----
|
||||
# AI 绝不输出任何号码/邮箱: 与价格墙并列的第二道确定性红线。
|
||||
LONG_NUMBER_RE = re.compile(r"\+?\d[\d\s\-().]{9,17}\d") # ≥10位连续数字(允许分隔形态)
|
||||
# Important-1(审查修复): 量词 {8,17} 最小匹配 10 字符——纯 10 位号
|
||||
# (沙特裸号 0501234567,CC 模板范例市场本体)必须命中。',' 不在字符类:
|
||||
# "50,000,000" 千分位形态放行(与 "45,000 km" 放行同机制),空格/横线
|
||||
# 分隔的 ≥10 位数字串命中;规格形态(DN110/5000m)经实测仍全放行。
|
||||
LONG_NUMBER_RE = re.compile(r"\+?\d[\d\s\-().]{8,17}\d") # ≥10位连续数字(允许分隔形态)
|
||||
ANY_EMAIL_RE = re.compile(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}")
|
||||
|
||||
# 12 小时口径与 system.md 对齐(Task 3 质量审查 Minor 4: 原句 "replies fast"
|
||||
|
||||
@@ -368,9 +368,17 @@ class ConversationManager:
|
||||
logger.warning(
|
||||
"No-contact wall replaced sentence (conv=%s): %r",
|
||||
conv.id, dirty[:60])
|
||||
closing = (NO_CONTACT_ALREADY if has_contact
|
||||
else (NO_CONTACT_APP if conv.source.value == "app"
|
||||
else NO_CONTACT_WEB))
|
||||
if cc_wall:
|
||||
# Important-2(审查修复): CC 触发轮回显被拦 → closing 改用
|
||||
# CC 模板句而非 NO_CONTACT_ALREADY——GLM 有 3/3 回显倾向,
|
||||
# 该路径概率高,客户该收到追问而非"稍后联系"虚假承诺;
|
||||
# 价格墙路径(violation=="boundary")不变
|
||||
closing = (_CC_WALL_ZH if _CJK_RE.search(content or "")
|
||||
else _CC_WALL_EN)
|
||||
else:
|
||||
closing = (NO_CONTACT_ALREADY if has_contact
|
||||
else (NO_CONTACT_APP if conv.source.value == "app"
|
||||
else NO_CONTACT_WEB))
|
||||
else:
|
||||
logger.warning(
|
||||
"Boundary filter intercepted sentence (conv=%s): %r | tail=%r",
|
||||
@@ -378,6 +386,12 @@ class ConversationManager:
|
||||
closing = (pivot_for(content, has_contact) if emitted
|
||||
else deflection_for(content, _boundary_rotate(),
|
||||
has_contact=has_contact))
|
||||
# Minor-5(审查修复): 已流出前缀与替换句之间补一个空格分隔
|
||||
# ("...xxxx? Got it —"——英文衔接无空格会粘连);CC/触发轮缓冲
|
||||
# 未流出,emitted 恒空,天然不受影响。空格随 closing 一起流出,
|
||||
# 客户所见与落库保持一致
|
||||
if emitted and not emitted.endswith((" ", "\n")):
|
||||
closing = " " + closing
|
||||
for i in range(0, len(closing), 40):
|
||||
yield {"type": "stream_chunk", "content": closing[i:i + 40]}
|
||||
emitted += closing
|
||||
|
||||
Reference in New Issue
Block a user