Files
ai-kefu-admin/docs/superpowers/plans/2026-11-02-jiancai-dual-contact-ask.md
T

312 lines
23 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.
# 建材(jiancai)双要话术实施计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** jiancai 首次索要联系方式的话术改为 WhatsApp + 邮箱一起要(双要),已留资收尾话术渠道中性化,缺失渠道补问通用化——纯话术层(3 个 seed_profiles 文件 + 同包测试锚同步),引擎代码零改动,生产经 admin API 整体对齐出厂。
**Architecture:** 词表/提示词全配置化(CLAUDE.md Phase 1),话术分布在 `seed_profiles/jiancai/prompts/system.md`(LLM 索要话术池与原则节)与 `seed_profiles/jiancai/wall.json`(deflections/pivots 注入 $DEFLECTION_POOL、reminders 系统提醒逐字句)。引擎的邮箱轻补注入机制(`_email_asked` 一次性 + `cc_settled` 串行门控)与防骚扰墙(放行"索要缺失渠道")原样保留。spec:`docs/superpowers/specs/2026-11-02-jiancai-dual-contact-ask-design.md`。
**Tech Stack:** pytest(静态锚 + 引擎行为测试,Windows 需 `PYTHONUTF8=1`,venv 在 `.venv/Scripts/python`);生产为 admin HTTPS API(`https://chat.ai.hnxinyouhe.com/api/platform`,配置版本管线热生效)。
**纪律(全程有效):**
- 临时文件用完即删,验收 = `git status` 干净(CLAUDE.md 硬约束)
- 每个 commit 必须绿(测试锚同步与数据文件改动同 commit)
- 生产凭据**不写入任何仓库文件**,执行时向用户取
---
## 统一措辞常量(全计划引用,逐字使用)
- **通用化补问子句(三处 reminder 内嵌)**:
- `lead_given.forbidden` 专用(带"仅"):`缺失渠道(号码或邮箱)仅可再礼貌提一次:邮箱按轻补指引逐字句、号码自然补问,不纠缠`
- `contact_ask.app_already` / `lead_given.boundary_tail` 共用(无"仅"):`缺失渠道——号码或邮箱——可再礼貌提一次:邮箱按轻补指引逐字句、号码自然补问,不纠缠`
- ("仅可"版与"可"版的前缀差异是测试 :684/:693 的判别依据——`缺失渠道(号码或邮箱)仅可…` 不含子串 `缺失渠道——号码或邮箱——可…`,判别力保留)
- **App 反向留资句(三处一字不差)**:`Drop your WhatsApp and email — our manager will reach out to you directly with the full quote!`
(wall `no_contact.app` = `reminders.contact_ask.app` 逐字句 = system.md L214;现状 "full quotation!" vs "full quote!" 一词分叉,本次统一为上句)
- **已留资确认句(渠道中性)**:`Got it — our manager will reach out to you shortly with the full quote!`
---
### Task 1: wall.json 双要 + 中性化 + 提醒通用化,同包测试锚同步
**Files:**
- Modify: `seed_profiles/jiancai/wall.json`
- Create: `tests/test_dual_ask_static.py`
- Modify: `tests/test_lead_email_trigger.py:681,692-693`、`tests/test_cc_integration.py:122`
- [ ] **Step 1: 新增 wall 侧静态锚测试(先红)**
创建 `tests/test_dual_ask_static.py`:
```python
"""双要话术静态锚(spec 2026-11-02-jiancai-dual-contact-ask §5.3)。
首次索要联系方式 = WhatsApp+邮箱一起要(双要);已留资后的确认/收尾话术
渠道中性(邮箱-only 客户不再听到"发到你 WhatsApp")。wall.json 侧锚在
本文件前半,system.md/company_facts.md 侧锚在后半(Task 2 追加)。
"""
import json
from pathlib import Path
SEED = Path(__file__).resolve().parents[1] / "seed_profiles" / "jiancai"
def _wall() -> dict:
return json.loads((SEED / "wall.json").read_text(encoding="utf-8"))
# ---- wall 侧 ----
def test_deflections_dual_ask_all_languages():
w = _wall()
assert any("and email" in s for s in w["deflections"]["en"])
assert any("和邮箱" in s for s in w["deflections"]["zh"])
assert any("y tu correo" in s for s in w["deflections"]["es"])
def test_pivots_dual_ask_all_languages():
w = _wall()
assert "and email" in w["pivots"]["en"][0]
assert "和邮箱" in w["pivots"]["zh"][0]
assert "y tu correo" in w["pivots"]["es"][0]
def test_post_contact_templates_channel_neutral():
"""已留资确认/收尾模板不含渠道词(三语逐一钉死,防只用 en 子串漏检)。"""
w = _wall()
for group in ("deflections_contact", "pivots_contact"):
for lang, items in w[group].items():
for s in items:
assert "whatsapp" not in s.lower(), (group, lang, s)
assert "whatsapp" not in w["no_contact"]["already"].lower()
def test_app_reverse_ask_dual_and_synced():
"""App 反向留资句双要,且 no_contact.app = contact_ask.app 逐字句同源。"""
w = _wall()
app = w["no_contact"]["app"]
assert "and email" in app
assert app in w["reminders"]["contact_ask"]["app"]
```
- [ ] **Step 2: 跑新测试确认红**
Run: `PYTHONUTF8=1 .venv/Scripts/python -m pytest tests/test_dual_ask_static.py -q`
Expected: 4 failed(deflections 仍为 "or email"、contact 模板仍含 WhatsApp、app 句未双要)
- [ ] **Step 3: 改 wall.json(逐字段替换值,键结构不动)**
| 字段 | 新值 |
|---|---|
| `deflections.en`(3 条全换) | ① `Prices vary a lot by config and shipping — our manager will prepare an exact quote for you. What's your WhatsApp and email?` ② `For an exact price our manager needs your config and destination — drop your WhatsApp and email and you'll have the quote today.` ③ `I'd rather give you an exact number than a rough guess — leave your WhatsApp and email and our manager will send it over.` |
| `deflections.zh`(2 条全换) | ① `价格要看配置和目的地,客户经理会给你准确报价——留个WhatsApp和邮箱?` ② `我让客户经理按你的情况出准确报价,留个WhatsApp和邮箱,今天就能发你。` |
| `deflections.es`(3 条全换) | ① `El precio exacto depende de la especificación y el flete — nuestro gerente te lo prepara. ¿Me dejas tu WhatsApp y tu correo?` ② `Para un precio exacto, nuestro gerente necesita tu especificación y destino — déjanos tu WhatsApp y correo y lo tienes hoy.` ③ `Prefiero darte una cifra exacta y no un estimado — déjanos tu WhatsApp y correo y nuestro gerente te lo envía.` |
| `pivots.en[0]` | `Actually, for the exact price — what's your WhatsApp and email? Our manager will send it over.` |
| `pivots.zh[0]` | `具体的报价,客户经理会发给你——留个WhatsApp和邮箱?` |
| `pivots.es[0]` | `Para el precio exacto — ¿me dejas tu WhatsApp y correo? Nuestro gerente te lo envía.` |
| `deflections_contact.en[0]` | `Our manager will send you the exact quote shortly. Anything else about our pipes?` |
| `deflections_contact.zh[0]` | `客户经理稍后会把准确报价发给你。还想了解什么管道产品?` |
| `deflections_contact.es[0]` | `Nuestro gerente te enviará el precio exacto en breve. ¿Algo más sobre nuestras tuberías?` |
| `pivots_contact.en[0]` | `Our manager will send you the exact price shortly.` |
| `pivots_contact.zh[0]` | `客户经理稍后会把准确报价发给你。` |
| `pivots_contact.es[0]` | `Nuestro gerente te enviará el precio exacto en breve.` |
| `no_contact.app` | `Drop your WhatsApp and email — our manager will reach out to you directly with the full quote!` |
| `no_contact.already` | `Got it — our manager will reach out to you shortly with the full quote!` |
| `reminders.contact_ask.app` 逐字句 | 整段改为:`⚠️ 客户正在索要我方联系方式(最高意向信号)。当前为 App 会话,没有页面按钮——禁止使用任何 tap/button 按钮话术!请逐字使用这句:"Drop your WhatsApp and email — our manager will reach out to you directly with the full quote!"(中文同理引导客户留联系方式)。绝对禁止输出任何号码或邮箱。` |
| `reminders.contact_ask.app_already` | 整段改为:`⚠️ 客户正在索要我方联系方式,且客户已留过自己的联系方式。请逐字使用这句:"Our manager will reach out to you shortly with the full quote!"(中文同理)。绝对禁止输出任何号码或邮箱,也绝对禁止再索要客户已提供过的联系方式(缺失渠道——号码或邮箱——可再礼貌提一次:邮箱按轻补指引逐字句、号码自然补问,不纠缠;号码缺国家代码时按系统提醒回显补全后的完整号码请客户确认——仅系统提供的号码,禁止自编)。` |
| `reminders.lead_given.forbidden` | 整段改为:`⚠️ 客户已提供联系方式({shown})。绝对禁止再索要客户已提供过的联系方式;缺失渠道(号码或邮箱)仅可再礼貌提一次:邮箱按轻补指引逐字句、号码自然补问,不纠缠;号码缺国家代码时按系统提醒回显补全后的完整号码请客户确认(仅系统提供的号码,禁止自编)。` |
| `reminders.lead_given.boundary_tail` | 整段改为:`客户已留过联系方式——边界请求直接告知'客户经理会把准确报价/安排发给你'即可,禁止再索要联系方式(缺失渠道——号码或邮箱——可再礼貌提一次:邮箱按轻补指引逐字句、号码自然补问,不纠缠;号码缺国家代码时按系统提醒回显补全后的完整号码请客户确认——仅系统提供的号码,禁止自编)。` |
**不动**:`reminders.email_light`、`cc_templates`、`cc_guide`、`reask_patterns`、`triggers`、`zero_number`、`no_contact.web`、`reminders.contact_ask.web`、`reminders.lead_given.respond_script/suspect`、`reminders.boundary.*`、`reminders.language_follow.*`。
**锚串自检(改后必在)**:`。绝对禁止再索要客户已提供过`(forbidden)、`也绝对禁止再索要客户已提供过`(app_already)、`即可,禁止再索要联系方式`(boundary_tail),三处各自 260 字符内都有 `回显补全后的完整号码`。
- [ ] **Step 4: 同步既有测试锚(4 处 + 1 处注释)**
- `tests/test_cc_integration.py:122`:`assert "缺失渠道仅可按轻补指引提一次" in text` → `assert "缺失渠道(号码或邮箱)仅可再礼貌提一次" in text`(行尾注释保留)
- `tests/test_lead_email_trigger.py:454`:`assert "缺失渠道可按轻补指引提一次" in text` → `assert "缺失渠道——号码或邮箱——可再礼貌提一次" in text`
- `tests/test_lead_email_trigger.py:681`:`assert "reach out to you at your WhatsApp" in text` → `assert "reach out to you shortly with the full quote" in text`
- `tests/test_lead_email_trigger.py:692-693`:`:692` 同 :681 替换;`:693` `assert "缺失渠道可按轻补指引提一次" in text` → `assert "缺失渠道——号码或邮箱——可再礼貌提一次" in text`;同步更新 :686-688 注释:内联引文 `缺失渠道可按轻补指引提一次` → `缺失渠道——号码或邮箱——可再礼貌提一次`,括注 `(:651 版是"仅可按",不构成子串)` → `(forbidden 版是"仅可",不构成子串)`
- `tests/test_boundary_filter.py:104`:`assert "WhatsApp?" in pivot_for("how much?")` → `assert "WhatsApp" in pivot_for("how much?")`(新 pivots.en[0] 为 `…WhatsApp and email?`,带问号的 `WhatsApp?` 子串消失,计划审查实证必红;:105 反向断言不受影响)
- [ ] **Step 5: 跑受影响测试文件全量**
Run: `PYTHONUTF8=1 .venv/Scripts/python -m pytest tests/test_dual_ask_static.py tests/test_lead_email_trigger.py tests/test_cc_integration.py tests/test_boundary_filter.py -q`
Expected: 全绿。若有其他硬编码旧句红掉(如 no_contact 墙测试锚旧句),按同一语义同步锚串后重跑至绿。
- [ ] **Step 6: Commit**
```bash
git add seed_profiles/jiancai/wall.json tests/test_dual_ask_static.py tests/test_lead_email_trigger.py tests/test_cc_integration.py tests/test_boundary_filter.py
git commit -m "feat(wall): 建材首次索要改双要(WhatsApp+邮箱一起要)+已留资话术渠道中性+缺失渠道补问通用化"
```
---
### Task 2: system.md + company_facts.md 双要改写
**Files:**
- Modify: `seed_profiles/jiancai/prompts/system.md`(16 处点位)
- Modify: `seed_profiles/jiancai/prompts/company_facts.md:30`
- Modify: `tests/test_dual_ask_static.py`(追加 md 侧锚)
- [ ] **Step 1: 追加 md 侧静态锚(先红)**
在 `tests/test_dual_ask_static.py` 末尾追加:
```python
# ---- system.md / company_facts.md 侧 ----
def _md(name: str) -> str:
return (SEED / "prompts" / name).read_text(encoding="utf-8")
def test_system_md_dual_ask_principle_and_pool():
src = _md("system.md")
assert "双渠道一次要齐" in src
assert "WhatsApp and email" in src # en 话术池
assert "WhatsApp和邮箱" in src # zh 话术池
# 邮箱轻补两条逐字句原文存活(与引擎 email_light 模板逐字一致)
assert ("Got it! And an email address would help too — our manager "
"will send the formal quotation PDF there.") in src
assert "收到!邮箱也留一个呗?客户经理把正式报价单 PDF 发你邮箱。" in src
def test_app_reverse_ask_line_matches_wall():
w = _wall()
assert w["no_contact"]["app"] in _md("system.md") # L214 与 wall 一字不差
def test_company_facts_dual_ask():
assert "WhatsApp 和邮箱" in _md("company_facts.md")
```
Run: `PYTHONUTF8=1 .venv/Scripts/python -m pytest tests/test_dual_ask_static.py -q`
Expected: 追加的 3 个测试红,Task 1 的 4 个保持绿。
- [ ] **Step 2: 改 system.md(逐点位精确替换)**
改写原则:**保留锚串**——`with the country code`、`formal quotation PDF`、`轻补`、`国家代码`(≥2 处)、`已在手的渠道`、`缺失渠道`、`邮箱轻补句`、`唯一例外`、`回显补全后的完整号码`(≥4 处)、`客户自己的号码也不回显`、`is that right`;**邮箱轻补 en/zh 两条逐字句原文不动**;CC 回显节(L196-199)与好/差例 L157-167 不动。
| 点位(现行内容特征) | 改为 |
|---|---|
| L7 模板句族:`转接句 "drop your WhatsApp and they'll reach out directly."、互留句 "Drop yours too..."` | `转接句 "drop your WhatsApp and email and they'll reach out directly."、互留句 "Drop your WhatsApp and email too..."`;同句内 `**缺失渠道**可按【联系方式引导策略】轻补一次` → `**缺失渠道**(号码或邮箱)可再礼貌提一次(见【联系方式引导策略】)`;`邮箱轻补句` 条目与其余句族不动 |
| L25 转接句 | `I'll connect you with our manager to arrange that — drop your WhatsApp and email and they'll reach out directly.` |
| L35 | `Tell me your WhatsApp and email — our manager will work out an accurate quotation and send the PDF over.` |
| L69 | `…That's exactly why I want our manager to send you the full quotation — drop your WhatsApp and email and our manager will reply within 12 hours.` |
| L74 | `Got it — our manager will reach out to you shortly!`(去 `at your WhatsApp`) |
| L140 中文好例 | `…AI用中文回复"价格要看规格、数量和目的地——我让客户经理给你出准确报价,留个WhatsApp和邮箱?"` |
| L152 样品好例 | `I'll connect you with our manager to arrange that — drop your WhatsApp and email and they'll reach out directly.`(与 L25 一字不差) |
| L155 | `Our manager will send you the full quotation.`(去 `to your WhatsApp`) |
| L179-182 en 话术池(4 条全换) | ① `What's your WhatsApp and email? Our manager will reach out on WhatsApp and send the full quotation PDF to your email.` ② `Let me connect you with our manager who handles [country] market — drop your WhatsApp and email and they'll reach out directly.` ③ `I can have our team send you a full quotation PDF — leave your WhatsApp and email here.` ④ `Want an exact quote? Drop your WhatsApp with the country code (like +966 5x xxx xxxx) and your email — our manager will take it from there.`(④保住 `with the country code` 锚) |
| L185-188 zh 话术池(4 条全换) | ① `留个WhatsApp和邮箱呗?客户经理 WhatsApp 联系你,正式报价单 PDF 发你邮箱。` ② `我让负责[国家]市场的同事对接你,留个WhatsApp和邮箱?` ③ `客户经理按你的项目出完整报价单,PDF 发你邮箱——WhatsApp 和邮箱都留一下吧。` ④ `你给我个联系方式(WhatsApp 和邮箱),我让客户经理按你的项目给你出方案。` |
| L190 节标题 | `### 双渠道与国家代码(双要)` |
| L192 原则行 | `- **双渠道一次要齐**:首次索要就把 WhatsApp 和邮箱一起要(天然理由=客户经理 WhatsApp 联系你 + 正式报价单 PDF 发你邮箱);客户只给一个时,另一渠道**轻补一次**(邮箱按系统轻补指引逐字句;号码礼貌补问一句),不成就不再提,绝不纠缠(转化率优先):`(其下两条逐字话术行 L193-194 原文不动) |
| L214 | `Drop your WhatsApp and email — our manager will reach out to you directly with the full quote!`(与 wall `no_contact.app` 一字不差) |
| L216 互留句 | `Drop your WhatsApp and email too — and our manager will send the full quotation!` |
| L221 | `缺失渠道可轻补一次` → `缺失渠道(号码或邮箱)可再礼貌提一次,仅一次不纠缠`;同段确认式例句 `"Our manager will send the full quotation to your WhatsApp."` → `"Our manager will send you the full quotation."` |
| L173、L227 括注 | `(缺失渠道轻补一次、号码缺国家代码时…)` → `(缺失渠道——号码或邮箱——可再礼貌提一次、号码缺国家代码时…)`(两处同构,锚串 `回显补全后的完整号码` 保留) |
- [ ] **Step 3: 改 company_facts.md L30**
`留个 WhatsApp,他直接联系你` → `留个 WhatsApp 和邮箱,他直接联系你`(仅插入 ` 和邮箱`,其余标点不动)
- [ ] **Step 4: 跑 md 侧锚 + 提示词静态测试**
Run: `PYTHONUTF8=1 .venv/Scripts/python -m pytest tests/test_dual_ask_static.py tests/test_system_prompt_dual_contact.py tests/test_prompt_static.py -q`
Expected: 全绿(既有锚全部存活)。红则按锚串自检表逐项排查,缺哪个锚补哪个。
- [ ] **Step 5: Commit**
```bash
git add seed_profiles/jiancai/prompts/system.md seed_profiles/jiancai/prompts/company_facts.md tests/test_dual_ask_static.py
git commit -m "feat(prompts): 建材 system.md/company_facts.md 双要改写——话术池/原则节/App反向留资/互留句/提醒配合全量对齐"
```
---
### Task 3: 全量回归 + 仓库洁净验收
- [ ] **Step 1: 根目录全量**
Run: `PYTHONUTF8=1 .venv/Scripts/python -m pytest -q`
Expected: 现状 collect 819(CLAUDE.md 的 632 基线已被 site-import 等后续工作推高,计划审查实测),改后预期 **826 collected(≈824 passed + 2 skipped,+7 = 新增静态锚)**;若数目对不上,验收标准退为两条:根目录与 tests/ 子目录双跑数字一致 + 相对改前基线差值恰为 +7(执行 Task 1 前先跑一次全量记录改前基线)
- [ ] **Step 2: tests/ 子目录全量(双跑一致性)**
Run: `cd tests && PYTHONUTF8=1 ../.venv/Scripts/python -m pytest -q`(跑完回到根目录)
Expected: 与 Step 1 数字一致
- [ ] **Step 3: 洁净验收**
Run: `git status --short`
Expected: 空(无临时文件、无漂移)。有残留即删。
---
### Task 4: 生产整体对齐出厂 + 三路径验证 + 清理
生产信息:admin API `https://chat.ai.hnxinyouhe.com/api/platform`;聊天域名 `chat2.agent.hnxinyouhe.com`(Host 路由 jiancai);凭据执行时向用户取(不写入任何文件)。本次**不涉及镜像重建/SSH**——配置经 admin API 直推租户配置组。
- [ ] **Step 1: 登录 + 拉取生产当前配置**
```bash
TOKEN=$(curl -s -X POST https://chat.ai.hnxinyouhe.com/api/platform/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"<向用户取>","password":"<向用户取>"}' | python -c "import sys,json;print(json.load(sys.stdin)['token'])")
curl -s -H "Authorization: Bearer $TOKEN" https://chat.ai.hnxinyouhe.com/api/platform/tenants/jiancai/config/prompts > /tmp/prod_prompts.json
curl -s -H "Authorization: Bearer $TOKEN" https://chat.ai.hnxinyouhe.com/api/platform/tenants/jiancai/config/wall > /tmp/prod_wall.json
```
(登录 409 = must_change_password → 停下找用户;`/tmp/` 为临时文件,任务收尾删除)
- [ ] **Step 2: 漂移审计(PUT 前置闸)**
对比 `/tmp/prod_prompts.json`、`/tmp/prod_wall.json` 与仓库出厂(`seed_profiles/jiancai/` 改后版本):
- 预期漂移 = 出厂侧演进未推生产(cd3b58a 翻译规则等)+ 本次双要改动
- **出现预期外差异(生产侧独有定制)→ 停下报告用户**,不得盲目覆盖
- [ ] **Step 3: 验证守卫(按用户全局纪律:测试绝不打扰线上正式收件/推送)**
PUT 临时配置:`email` 组 `notify_emails` → `["clany@hnxinyouhe.com"]`(测试收件箱);`push` 组 `enabled` → `false`。记录两组当前版本号(验证后恢复用)。
- [ ] **Step 4: 整组 PUT 出厂最新版**
以 Step 1 GET 响应的键结构为准,prompts 组四件(system/extractor/evaluator/company_facts)与 wall 组整组替换为仓库出厂内容后 PUT(读-改-写;PUT = 整组替换语义)。PUT 后 `GET /tenants/jiancai/config/versions` 确认两组版本各 +1。
- [ ] **Step 5: 三路径真实验证(REST,与 WS 同 code path)**
```bash
SID=$(curl -s -X POST https://chat2.agent.hnxinyouhe.com/api/chat/session \
-H 'Content-Type: application/json' -d '{"context":{}}' | python -c "import sys,json;print(json.load(sys.stdin)['session_id'])")
curl -s -X POST https://chat2.agent.hnxinyouhe.com/api/chat/message \
-H 'Content-Type: application/json' -d "{\"session_id\":\"$SID\",\"content\":\"...\"}"
```
- **路径 a 双要首问**:先 `How much for DN110 PE100 pipe?`(预期先问需求一轮)→ `For water supply project in Saudi Arabia` → 预期回复同时索要 WhatsApp **和** 邮箱
- **路径 b 号码-only**:新会话走一轮需求后发裸号 `0501234567` → 预期 CC 回显确认(完整号)→ `yes` → 下一轮预期邮箱轻补(`email address would help too`)
- **路径 c 邮箱-only**:新会话走一轮需求后 `My email is test@example.com, please send the quote` → 预期礼貌补问号码一次;回复拒绝(`I'd rather not`)→ 预期不再追要、正常继续
- 三路径回复存临时文件人工核对后删除;限流 30 条/小时/租户/IP,消息总量控制在其内
- [ ] **Step 6: 恢复守卫 + 清理**
- PUT 恢复 `email`/`push` 两组原值(对照 Step 3 记录),GET 确认内容一致
- 删除验证会话:`GET /tenants/jiancai/conversations?limit=50` 找当日 app 来源测试会话 → `DELETE /tenants/jiancai/conversations/{conv_id}` 逐个删
- 删除全部临时文件(`/tmp/prod_*.json`、回复存档等)
- [ ] **Step 7: 回滚预案(只在异常时执行)**
`POST /tenants/jiancai/config/rollback`(body 带回 PUT 前版本号,prompts/wall 两组各回退),恢复守卫同 Step 6。
- [ ] **Step 8: 观察注记**
向用户报告:留资率、双渠道齐收率、breach_rate 纳入阶段④日检观察项;若留资率异常下滑,回滚预案同 Step 7(配置版本秒级回退)。
---
## 验收标准(对齐 spec §7)
1. 全量 pytest 绿(新增 7 静态锚计入,双跑数字一致)
2. 引擎代码 diff 为零;auto 租户与生成器模板 diff 为零
3. 生产 jiancai prompts/wall 版本各 +1 = 出厂最新版;三路径真实行为符合预期
4. 验证会话与临时文件清零;守卫配置恢复原值