Files
ai-kefu-jc/docs/superpowers/plans/2026-09-29-building-materials-ai-kefu.md
T
2026-09-29 12:09:58 +08:00

566 lines
24 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.
# HESUPIPE 建材 AI 客服 实施计划
> **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:** 复制 D:\refactor\ai-kefu 汽车AI客服到本项目并完成建材(HESUPIPE 管道外贸)行业定制。
**Architecture:** 方案A"完整拷贝+定制"——保留参考项目全部架构(FastAPI+SQLite+智谱GLM、WebSocket/REST 双通道、三重输出墙、联系方式管道、邮件+UniService推送、管理后台、170+测试),只定制约15%行业相关内容(4个提示词、多语言正则墙、前端文案、品牌更名)。
**Tech Stack:** Python 3.13 / FastAPI / SQLAlchemy(async)+aiosqlite / 智谱GLM(glm-4-flash) / 原生HTML-JS-CSS前端 / pytest+pytest-asyncio / Docker+OpenResty
**设计文档:** `docs/superpowers/specs/2026-09-29-building-materials-ai-kefu-design.md`(本计划的所有决策依据)
**参考项目:** `D:\refactor\ai-kefu`(只读,绝不修改)
**重要约束:**
- ⚠️ 绝不拷贝参考项目的 `.env`(含真实密钥)和 `data/cc_ai_kefu.db`(含生产数据)
- 开发期 `PUSH_ENABLED=false`、NOTIFY_EMAIL 用测试邮箱(Task 11 验收通过后才切生产)
- 每个任务结束必须 `pytest -q` 全绿后才能 commit
---
### Task 1: 项目拷贝、清理与测试基线
**Files:**
- Create: 整个项目骨架(从参考项目拷贝)
- Delete: `static/blog.html`、redis 相关配置
- [ ] **Step 1: 拷贝项目(排除密钥/数据/缓存)**
```bash
cd /d/refactor
MSYS_NO_PATHCONV=1 robocopy "D:\\refactor\\ai-kefu" "D:\\refactor\\ai-kefu-jc" /E \
/XD .git data __pycache__ .pytest_cache .ruff_cache .playwright-mcp .superpowers .vscode \
/XF .env
```
⚠️ Git Bash 下 MSYS 会把 `/E` `/XD` 等开关当路径转换导致 robocopy 报"无效参数",
**必须加 `MSYS_NO_PATHCONV=1` 前缀**(实测验证;替代写法是 `//E //XD //XF` 双斜杠)。
robocopy 返回码 0-7 都算成功(1=有文件拷贝),≥8 才是失败。
`docs/superpowers/` 下会合入参考项目的汽车 specs/plans 归档,与本项目的建材设计文档共存,无冲突(文件名不同)。
**git 仓库说明**:本项目在设计阶段已 `git init` 并有 3 个 docs commit 在案;
robocopy 的 `/XD .git` 只排除源目录的 .git,不影响目标已有仓库。Step 6 前用
`git rev-parse --is-inside-work-tree` 确认输出 `true` 即可(若在全新环境重跑本计划则先 `git init`)。
- [ ] **Step 2: 验证拷贝结果**
```bash
cd /d/refactor/ai-kefu-jc && ls app/ static/ tests/ scripts/
# 预期:四个目录都在;确认不存在 .env 和 data/cc_ai_kefu.db
test ! -f .env && echo OK-no-env
mkdir -p data
```
- [ ] **Step 3: 清理无用件**
```bash
rm static/blog.html
```
移除 redis 三处:
1. `requirements.txt` 删除 `redis>=5.0.0` 行
2. `docker-compose.yml` 删除整个 redis service 块(`cc-ai-kefu-redis`)
3. `.env.example` 删除 `REDIS_URL`/`REDIS_PASSWORD` 行及注释
- [ ] **Step 4: 安装依赖并建 .env 占位**
```bash
pip install -r requirements.txt -r requirements-dev.txt
cp .env.example .env
```
`.env` 中 `ZHIPU_API_KEY` 先留占位(跑测试不需真实 Key,LLM 全 mock)。
- [ ] **Step 5: 基线测试——未改任何代码前必须全绿**
```bash
python -m pytest -q
```
预期:170+ passed(参考项目全绿,拷贝后应同样全绿)。若有 Windows 环境性失败,先修复环境再继续(参考项目 conftest.py 头部有 Windows aiosqlite 清理说明)。
- [ ] **Step 6: Commit**
```bash
git add -A && git commit -m "chore: 从汽车AI客服项目拷贝骨架并清理(blog页/redis)"
```
---
### Task 2: 公司事实卡 company_facts.md
**Files:**
- Modify: `app/prompts/company_facts.md`(整体重写)
- Test: `tests/test_company_facts.py`(更新断言)
- [ ] **Step 1: 抓取官网资料**
用 WebFetch 依次抓取(提取硬事实,忽略模板化文案):
- `https://hesupipe.com/`(已抓取过:公司概况/十大产品线/联系方式)
- `https://hesupipe.com/about-us/`(或等价关于页)
- 产品分类页(HDPE/PVC/PPR 等主要品类页,取规格范围)
- `https://hesupipe.com/certificates/`(认证清单)
- `https://hesupipe.com/sales-network/`(销售网络/出口国家)
- 新闻页 1-2 篇真实项目案例(如智利农业供水管项目)
- [ ] **Step 2: 重写事实卡**
保留参考项目事实卡的**结构框架和使用规则段**(防编造的"统一兜底/不扩展"原则原样保留),替换内容段。结构:
```markdown
# HESUPIPE 公司事实卡
## 公司概况
(1998年成立/2007年起出口/河南郑州/高新技术企业——只写官网可验证的)
## 产品线总表
(HDPE管道及管件/HDPE波纹管/PVC管道及管件/PVC电工套管/PPR管道/球墨铸铁管/法兰阀门/HDPE渔网箱/门窗类——每类一行主要规格范围,如 DN20-DN1200)
## 应用领域
(市政给水/燃气油气/排水排污/农业灌溉/电气保护/疏浚/海水养殖)
## 认证
(证书页实际列出的,逐条;没有就整节省略,不编)
## 销售网络与出口市场
(官网实际提及的国家/地区)
## 使用规则(原样保留参考项目的兜底原则)
(未列出的一律说"转客户经理确认";禁止推测/扩展/编造)
```
**红线自查**:不含价格、交期、MOQ、产能数字;不收录"world-class"类模板化空话。
- [ ] **Step 3: 更新 test_company_facts.py 断言**
改为断言建材关键词(如 `HESUPIPE`、`HDPE` 或实际产品词)存在、汽车词(`BYD`/`Hesu Auto`/`vehicle`)不存在。
- [ ] **Step 4: 跑测试**
```bash
python -m pytest tests/test_company_facts.py -q
```
预期:PASS
- [ ] **Step 5: Commit**
```bash
git add -A && git commit -m "feat: HESUPIPE 公司事实卡(官网硬事实+防编造规则)"
```
**⚠️ 审核关卡(设计文档§4.2)**:事实卡完成后请需求方业务侧过目确认后方可上线(可异步,不阻塞后续任务)。
---
### Task 3: 系统提示词 system.md 重写
**Files:**
- Modify: `app/prompts/system.md`(整篇重写,框架保留)
- [ ] **Step 1: 重写 system.md**
保留参考项目的六段结构,逐段建材化:
1. **语言规则(最高优先级)**:保留"客户用什么语言就用什么语言回复,默认英语";**新增**:拒绝价格/交期/MOQ/样品费等实质问题时,回复中必须包含固定英文短句 `Please leave your contact and our manager will send the full quotation.`(保证输出墙正则可靠命中)
2. **职能边界**:AI 只做需求了解+留资;价格/交期/MOQ/装柜方案/样品费/认证清单/库存→转客户经理;问实质问题时若已知意向品类:"确认品类+引导留资"一气呵成
3. **红线**:不出现价格数字(含复述客户预算);不输出电话/邮箱;不再三索要已留资客户的联系方式
4. **说话风格**:外贸销售式简短口语;时效承诺用 "reply within 12 hours"(不提中国作息)
5. **对话推进**:预算路径改为 `"Which application? Water supply, gas, drainage or irrigation?"`;规格追问(口径/压力/标准);围绕已说品类推进
6. **好差示例**:6-8 组管道场景(例:客户说 "PE100 water pipe DN110",差:泛问 what do you need;好:确认 SDR11/SDR17? + 询问工程量;中文话术示例同步改管道语境)
- [ ] **Step 2: 自查清单**
- [ ] 所有汽车词(car/vehicle/BYD/Toyota/test drive/提车/试驾/续航)已清零:`grep -in "car\b\|vehicle\|byd\|toyota\|test drive\|试驾\|提车\|续航" app/prompts/system.md` 预期无输出
- [ ] 红线覆盖:MOQ、lead time、container loading、sample fee、certificate、price range
- [ ] 固定英文拒绝短句原样出现(与 boundary_filter 的 DEFLECTIONS 措辞协调但不冲突——prompt 是"含义",墙是"兜底")
- [ ] **Step 3: 跑全量测试(system.md 变更影响的测试)**
```bash
python -m pytest -q
```
预期:PASS(若有断言 system.md 内容的测试,同步更新)
- [ ] **Step 4: Commit**
```bash
git add -A && git commit -m "feat: 系统提示词建材化(管道外贸人设+多语言拒绝短句)"
```
---
### Task 4: 提取与评估提示词(extractor.md / evaluator.md)
**Files:**
- Modify: `app/prompts/extractor.md`、`app/prompts/evaluator.md`
- [ ] **Step 1: 重写 extractor.md 字段定义**
中文键画像字段改建材语义(设计文档§4.3):
- `意向品类`(HDPE给水管/PVC排水管/PPR…)
- `规格要求`:**自由文本保留客户原话**(如 "DN110 PE100 SDR11"),明确指示不拆分不过度结构化
- `标准要求`:单独一列(ISO4427/ASTM/EN/SCH 系列,客户提到才记)
- `采购数量`、`用途`(给水/燃气/排污/灌溉/…)、`项目类型`、`目标国家`、`预算提及`、`联系方式`字段原样保留参考项目机制
- [ ] **Step 2: 重写 evaluator.md 评估语义**
三级保留;示例改管道采购:明确品类+规格+数量=interested;仅泛泛浏览=pending;明确无采购计划=not_interested。
- [ ] **Step 3: 新增 extractor 字段静态断言测试(spec §9.1 第4条落地;严格 TDD 可提前到 Step 1 之前先写先跑红)**
`tests/test_company_facts.py` 风格,新建断言:extractor 提示词加载后包含
`意向品类`、`规格要求`、`标准要求` 字段定义,且不含 `车型`/`意向品牌` 汽车字段。
- [ ] **Step 4: 跑全量测试并 Commit**
```bash
python -m pytest -q && git add -A && git commit -m "feat: 提取/评估提示词建材化(规格自由文本+标准单列)"
```
---
### Task 5: 多语言输出墙 boundary_filter.py(TDD 核心)
**Files:**
- Modify: `app/services/boundary_filter.py`
- Test: `tests/test_boundary_filter.py`
- [ ] **Step 1: 先写失败的多语言墙测试**
在 `tests/test_boundary_filter.py` 追加(沿用该文件现有参数化风格):
```python
# ---- 多语言价格墙(建材市场扩充): 必须拦截 ----
MULTILINGUAL_PRICE_HITS = [
"El precio es 500 dólares", # 西语 词前置
"Costo por tonelada 320", # 西语
"O preço é 1200 reais", # 葡语(巴西)
"Цена 500 за тонну", # 俄语
"Стоимость 800 долларов", # 俄语
"السعر 500 دولار", # 阿语
"€500 per ton", # 欧元符号
"£420 per container", # 英镑符号
"500 dólares", # 数字+货币词后缀
"Delivery in 15 días", # 西语时间承诺
"Срок 2 недели", # 俄语时间承诺
]
# ---- 建材规格形态: 不得误杀 ----
SPEC_NON_HITS = [
"DN800 double wall corrugated pipe",
"PN16 pressure rating",
"SDR11 and SDR17 both available",
"PE100 material",
"600mm diameter",
"SCH40 and SCH80",
"3/4 inch and 2 inch sizes",
"ISO4427 certified",
"20ft container load", "40ft HQ",
"5.8m and 11.8m lengths",
"PE80 PE100 grades",
]
```
断言:前者每个 `violates_boundary(s)` 为 True;后者每个为 False。
- [ ] **Step 2: 跑测试确认失败**
```bash
python -m pytest tests/test_boundary_filter.py -q
```
预期:多语言 HITS 用例 FAIL(现有正则拦不住)
- [ ] **Step 3: 扩充 PRICE_PATTERNS**
在 `PRICE_PATTERNS` 列表追加(保持参考项目"注释说明设计意图"的风格):
```python
# ---- 多语言墙(建材市场: 欧/英/南美/俄语区/中东) ----
# 货币符号: €/£ 参考项目只有 $
re.compile(r"[€£]\s?\d"),
# 价格名词前置(西/葡/俄/阿): 词后 0-20 非数字字符内出现数字
re.compile(r"(?:precio|costo|custo|preço|цена|стоимость|سعر|ثمن)[^\d\n]{0,20}\d", re.I),
# 货币名词后置(数字+货币词)
re.compile(r"\d[\d,.]*\s*(?:d[óo]lares?|euros?\b|рублей|руб\.?)", re.I),
# 多语言时间承诺(与英文 days/weeks 组同构)
re.compile(r"\d+\s*[- ]?(?:d[ií]as?|semanas?|дн(?:ей|я)|недел[ьи]|أيام)\b"),
```
同时审查现有汽车特定排除项:
- `\d[\d,.]*\s*(usd|美元|块钱|万块?(?!\s*(公里|km)))` 的 `公里|km` 排除 → 建材语境已无里程语义,但保留无害;确认不误杀建材形态
- `(两|三|四|五|六|七|八|九|十)\s*万(?!\s*(公里|km))` 保留(中文预算)
- 时间承诺 `\d+\s*[- ]?(day|week|month)s?\b` 保留(英文交期承诺)
- [ ] **Step 4: 跑测试至全绿**
```bash
python -m pytest tests/test_boundary_filter.py -q
```
预期:PASS(含原有全部用例不回归)
- [ ] **Step 5: 迂回话术建材化 + ES 话术池(spec §6 第3层)**
1. **行业残留清零**(用户可见输出,实测在参考项目 L54/L57):
- `DEFLECTIONS_EN_CONTACT` 的 "Anything else about the cars?" → "...about pipes?"
- `DEFLECTIONS_ZH_CONTACT` 的 "还想了解什么车?" → "还想了解什么管道产品?"
- 全文件扫一遍 DEFLECTIONS/PIVOTS/NO_CONTACT 各池,确认无其他汽车措辞
2. **新增 ES 话术池**(南美第一大流量,spec §6.3):
- 新增 `DEFLECTIONS_ES`、`DEFLECTIONS_ES_CONTACT`、`PIVOTS_ES`、`PIVOTS_ES_CONTACT`
(西语版话术,如 "El precio exacto te lo envía nuestro gerente por WhatsApp, ¿me lo dejas?")
- `deflection_for()` / `pivot_for()` 现为"汉字→ZH,否则 EN"二分支,扩展为三分支:
汉字 → ZH;西语特征(`re.search(r"[áéíóúñ¿¡]", msg)` 粗匹配,与参考项目
汉字检测同构)→ ES;否则 → EN
3. **测试**:`tests/test_boundary_filter.py` 追加——西语消息选 ES 池、英文选 EN、
中文选 ZH;"cars"/"什么车" 不再出现在任何话术池
- [ ] **Step 6: 同步 scripts/breach_rate.py**
把上述新词表同步进 breach_rate.py 的统计模式(保持与墙一致,供上线观察期用)。
- [ ] **Step 7: 全量测试 + Commit**
```bash
python -m pytest -q && git add -A && git commit -m "feat: 多语言输出墙(€/£/西葡俄阿价格词+时间承诺+ES话术池)+话术建材化+防误杀"
```
---
### Task 6: 会话编排与联系方式管道建材化
**Files:**
- Modify: `app/services/conversation.py`、`app/services/contact_pipeline.py`
- Test: `tests/test_contact_pipeline.py`、`tests/test_context_seeding.py`
- [ ] **Step 1: 先写失败的阿语数字测试**
`tests/test_contact_pipeline.py` 追加:
```python
def test_arabic_digits_normalized():
# 阿语数字(中东买家)提取后应转 ASCII,CRM 可直接拨
confirmed, _ = split_validate({"whatsapp": "+٩٦٦٥٠١٢٣٤٥٦٧"})
assert confirmed["whatsapp"] == "+966501234567"
```
(具体 API 名以参考项目实际函数签名为准——`split_validate`/canon 归一化入口。)
- [ ] **Step 2: 跑测试确认失败**
```bash
python -m pytest tests/test_contact_pipeline.py -q -k arabic
```
预期:FAIL(号码原样保留阿语数字)
- [ ] **Step 3: 实现数字归一化**
`contact_pipeline.py` 顶部加:
```python
# Unicode 十进制数字 → ASCII(阿语٠-٩/波斯语۰-۹), 中东买家号码 CRM 可直接拨
_DIGIT_TRANSLATE = str.maketrans("٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹", "01234567890123456789")
```
在归一化入口(normalize_contacts/digits_only 调用链的最前端)对值做 `v.translate(_DIGIT_TRANSLATE)`。注意:正则 `\d` Unicode 模式本就匹配阿语数字,位数校验能过——本步只解决"存进去的形式"。
- [ ] **Step 4: conversation.py 建材化**
1. `BOUNDARY_TRIGGER_RE`:确认已含 MOQ/lead time/delivery time/sample/certificate 类词;补 `container loading|装柜|起订`(以实际正则现状为准增补)
2. context 种子白名单:`vehicle_name/vehicle_id` → `product_name/product_id`
3. `_build_context_reminder`/`_enrich_short_message` 中的车型话术 → 产品方案话术
4. 同步更新 `tests/test_context_seeding.py` 的键名
- [ ] **Step 5: 全量测试 + Commit**
```bash
python -m pytest -q && git add -A && git commit -m "feat: 会话编排建材化+阿语号码转ASCII"
```
---
### Task 7: 服务端杂项更名
**Files:**
- Modify: `app/main.py`、`app/services/email_service.py`、`app/api/routes/chat_rest.py`、`app/services/rate_limit.py`、`app/config.py`(如有 DB 默认名)
- [ ] **Step 1: 逐文件更名**
| 文件 | 改动 |
|---|---|
| `app/main.py` | FastAPI(title="AI汽车客服") → title="HESUPIPE AI 客服" |
| `app/services/email_service.py` | 发件人 `【XYH】` → `【HESUPIPE】`;确认无汽车字段引用 |
| `app/api/routes/chat_rest.py` | docstring "HESU app" → HESUPIPE;种子键名若此处再有引用同步 |
| `app/services/rate_limit.py` | docstring "Mirrors hesu's" 更新 |
| `app/config.py` + `.env.example` | DATABASE_URL 默认 `data/hesupipe_ai_kefu.db` |
- [ ] **Step 2: 全局残留扫描**
```bash
grep -rin "汽车\|vehicle\|byd\|toyota\|hesu auto\|borderlesscar\|VOLT\|XYH\|cc-ai-kefu\|cc_ai_kefu\|car\b\|cars\|什么车\|车型\|车价" app/ tests/ scripts/ --include="*.py" | grep -v "docs/"
```
预期:无输出(docstring/注释里的行业残留一并清零;`car\b|cars|什么车|车型` 抓 boundary_filter 话术池等用户可见输出)。
- [ ] **Step 3: 全量测试 + Commit**
```bash
python -m pytest -q && git add -A && git commit -m "chore: 服务端品牌与行业残留更名清零"
```
---
### Task 8: 部署配置更名
**Files:**
- Modify: `docker-compose.yml`、`deploy.sh`、`openresty.conf`、`.env.example`
- [ ] **Step 1: 更名**
| 文件 | 改动 |
|---|---|
| `docker-compose.yml` | 容器名 `cc-ai-kefu`→`hs-ai-kefu`;端口 `8016:8000`→`8017:8000`(redis 服务已在 Task1 删) |
| `deploy.sh` | 健康检查 URL 8016→8017 |
| `openresty.conf` | upstream `cc_ai_kefu`→`hesupipe_ai_kefu`;127.0.0.1:8016→8017;alias `/www/cc_ai_kefu/`→`/www/hesupipe_ai_kefu/`;日志名同步(含注释掉的 HTTPS 段) |
| `.env.example` | `APP_PORT=8017`;`PUSH_EXTERNAL_KEY_PREFIX=ai-kefu-jc`;`PUSH_ENABLED=false`(开发期) |
- [ ] **Step 2: 残留扫描**
```bash
grep -rn "cc_ai_kefu\|cc-ai-kefu\|8016" docker-compose.yml deploy.sh openresty.conf .env.example
```
预期:无输出。
- [ ] **Step 3: 测试 + Commit**
```bash
python -m pytest -q && git add -A && git commit -m "chore: 部署配置更名(hs-ai-kefu/8017/hesupipe_ai_kefu)"
```
---
### Task 9: 前端建材化(文案/主题/GDPR + 静态断言同步)
**Files:**
- Modify: `static/chat.html`、`static/widget.js`、`static/js/chat.js`、`static/js/theme.js`、`static/admin.html`、`static/widget-test.html`
- Test: `tests/test_invite_static.py`、`tests/test_theme_static.py`
- [ ] **Step 1: 了解静态测试的真实性质(避免走错路)**
`tests/test_invite_static.py`/`test_theme_static.py` 是**结构回归网**,不是文案断言——
它们断言的是邀请卡面板出厂 hide、pointer-events、回流顺序、theme.js 与 widget.js
调色板逐字同步、无残留旧色 hex 等结构性质。所以本任务的测试策略是:
**直接改前端文件,然后跑结构回归测试防破坏**(它们会在你漏改某处色值/结构时指路)。
- [ ] **Step 2: 前端文案与配置**
| 文件 | 改动 |
|---|---|
| `chat.html` | 标题 `HESUPIPE Support`;描述管道场景;欢迎语 "What kind of piping project are you working on?";热门话题 Get Quotation / Pipe Specifications / Delivery & Shipping;WhatsApp `+8615937108317`;邮箱 `hesu@hesuu.com` |
| `widget.js` | 默认 title/whatsapp/email 同上;邀请卡文案管道化(pipe specs, MOQ, delivery timing);话题按钮同步 |
| `js/chat.js` | WhatsApp/email fallback 默认值同步 |
| `admin.html` | VOLT → HESUPIPE(title/header/头像字母) |
| `js/theme.js` | 默认品牌色橙 `#f08a31` → HESUPIPE 品牌蓝(从 hesupipe.com CSS 取实际主色值)。⚠️ 色值有**三处**要同步:`theme.js` 的 DEFAULT_COLOR、`widget.js` 的 DEFAULT_PALETTE(内联副本,测试强制两份一致)、`css/style.css` 的 `:root` 槽位值——漏任何一处 test_theme_static 会红 |
| `widget.js` | **GDPR 行**:首次对话邀请卡/首条消息附加 "By chatting, you agree to our privacy policy."(链接指向 hesupipe.com 隐私政策页,URL 实施时与需求方确认,可先 `https://hesupipe.com/privacy-policy/` 占位) |
| 头像 | `kefu.png`/`kefu-small.png` 替换(需求方提供 logo 或用品牌蓝底 "H" 字母临时生成) |
- [ ] **Step 3: 跑静态断言与全量测试至绿**
```bash
python -m pytest tests/test_invite_static.py tests/test_theme_static.py -q
python -m pytest -q
```
- [ ] **Step 4: 残留扫描 + Commit**
```bash
grep -rin "HESU Support\|hesu auto\|vehicle\|VOLT\|borderlesscar\|1903717\|f08a31" static/ | grep -v blog
git add -A && git commit -m "feat: 前端HESUPIPE品牌化+管道文案+GDPR提示"
```
---
### Task 10: 全量回归与收尾扫描
**Files:** 无新增(验证任务)
- [ ] **Step 1: 全仓行业残留终扫**
```bash
grep -rin "汽车\|vehicle\|byd\|toyota\|test drive\|试驾\|提车\|hesu auto\|borderlesscar\|VOLT\|XYH\|cc_ai_kefu\|cc-ai-kefu\|car\b\|cars\|什么车\|车型\|车价" app/ static/ tests/ scripts/ *.yml *.sh *.conf 2>/dev/null
```
预期:仅 docs/ 归档 changelog 里有(允许——历史档案)。
- [ ] **Step 2: 全量测试**
```bash
python -m pytest -q
```
预期:全绿(170+,含新增多语言/阿语数字用例)
- [ ] **Step 3: 本地起服务冒烟**
```bash
python -m uvicorn app.main:app --port 8017 &
curl -s http://127.0.0.1:8017/health
# 预期 {"status":"ok"} 类响应; 浏览器开 http://127.0.0.1:8017/ 与 /admin 目检
```
- [ ] **Step 4: Commit(如有收尾改动)**
---
### Task 11: 真人验收(真实 LLM + mock 推送联调)
**Files:**
- Create: `docs/test-checklist.md`(基于参考项目同名文件改写)
- 临时: `.env` 填真实智谱 Key
- [ ] **Step 1: 编写真人验收清单**
按设计文档 §9.2 全项写入 `docs/test-checklist.md`(问价×2语言/MOQ/样品/交期/认证→转留资;留资→画像+邮件[测试邮箱]+mock推送;换号→更正邮件;已留资不再索要;规格聊天不误杀;后台三视图核对)。
- [ ] **Step 2: 起 mock UniService 并配置联调**
```bash
python scripts/mock_uniservice.py & # 本地假CRM, 默认端口 9099
```
`.env`:`PUSH_ENABLED=true`、`PUSH_API_URL=http://127.0.0.1:9099/open/v1/inquiry/push`、
`PUSH_API_KEY=test-key-123`(mock 脚本期待的固定 Key,不设会 401)、
NOTIFY_EMAIL=测试邮箱、真实智谱 Key。
- [ ] **Step 3: 逐项真人验收**
按清单实聊(英文+西语+中文三种语言各至少一轮完整留资流程)。核对:邮件收到、mock 推送 accepted、admin 后台画像/意向/日志正确。
- [ ] **Step 4: 修复发现的问题直至清单全过 + Commit**
```bash
git add -A && git commit -m "test: 真人验收清单+联调修复"
```
---
### Task 12: 交付物(嵌入代码/说明/CLAUDE.md)
**Files:**
- Create: `docs/embed-guide.md`、`CLAUDE.md`、`README.md`
- [ ] **Step 1: 官网嵌入说明 docs/embed-guide.md**
内容:一段可粘贴的挂件代码(script 标签+data-* 配置示例:位置/主题色/WhatsApp/自动邀请),贴到 WordPress 哪里(页脚模板或主题设置)、隐私政策页要求。给官网管理员一页读完即可操作。
- [ ] **Step 2: CLAUDE.md 血缘记录**
记录:上游参考项目 `D:\refactor\ai-kefu`、85%同源、上游修bug需对照其 `docs/` changelog 手动同步、本项目 external_key 前缀 ai-kefu-jc、开发期 PUSH 关闭约定、上线观察期跑 breach_rate.py。
- [ ] **Step 3: README.md**
项目简介/本地启动(pip install、.env、uvicorn)/测试(pytest)/部署(deploy.sh+openresty)/管理后台入口。
- [ ] **Step 4: Commit**
```bash
git add -A && git commit -m "docs: 官网嵌入指南+CLAUDE.md血缘+README"
```
---
## 上线切换(验收全过后,需求方操作确认)
1. `.env` 切生产:`PUSH_API_URL` 指真实 UniService、真实 API Key、NOTIFY_EMAIL=客户经理邮箱
2. 服务器部署:`deploy.sh`(端口 8017)+ openresty 域名配置(需求方提供,如 ai.hesupipe.com)
3. 官网按 `docs/embed-guide.md` 嵌入挂件
4. **第一周观察期**:跑 `scripts/breach_rate.py` 看漏放/误杀,发现即补正则(设计文档 §9.3)