# 验收与演示说明

更新日期：2026-09-09。验收口径依据《语音销售助手-Demo方案.md》§9 十二条。

每条结论标注：**实测通过**（本次实施中实际执行）/ **模拟验证**（以测试替身或代码路径证明）/ **待用户真机确认**（需要真实手机/浏览器交互）。

## 0. 访问方式

- 入口：`https://sosp.zhuxincn.com/`（手机浏览器）
- 演示访问码：由运维方安全提供；服务端无默认值，文档不记录明文
- 当前模式：页面顶部固定徽章「演示数据」（mock）；保存结果提示「已保存到 Demo」

## 1. 五分钟演示脚本（对应主 Plan §7）

> 前提：演示数据已初始化（3 个机会、6 条历史日志）。若数据被演示过程改动，运行：
> `cd /var/www/demo/sosp-assistant && SOSP_SEED_ALLOW_RESET=1 node --experimental-sqlite scripts/init-db.js --force && systemctl restart sosp-assistant`
>
> 页面结构对照原始截图：底部导航 5 个页签 主页/机会/**中央大麦克风「记日志」**/简报/我的（截图 1）；日志页录音状态内嵌输入卡，录音时输入卡变红、麦克风显示「正在听… 12″（点此停止）」（截图 2）。在日志页再点中央麦克风可直接开始/停止录音。

**第一步，录入与追问（底部中央 🎤 → 日志对话页）**

1. 点底部导航中央麦克风进入日志页，再点输入卡内「点此录音」开始讲话；输入卡变红并显示“正在听… X″”，讯飞转写文字会逐步出现在输入框。再次点击停止后，最终转写自动发送给 AI 并生成草稿，原录音随日志保存，详情页可回放。也可直接输入下面文字作为真机不可用时的备用：
   > 今天拜访了东莞供电局 SVG 项目，客户说预算没问题，技术方案已经提交并进入评审，预计下周出结果，采购处长在牵头。我准备下周一再跟一下。
2. 预期：停止后提示“讯飞转写完成，正在生成日志草稿”；草稿卡自动关联「东莞供电局 · SVG…」，提取出预算（**待确认**——"预算没问题"不得变成金额）、采购/评审计划（已确认）、联系人（采购处长牵头）、下一步（下周一）；活动时间"今天"→ 具体日期；完整度只统计已确认项；出现一条缺口追问。
3. 追问应答输入：
   > 采购处长主要负责采购协调，最终由分管领导拍板，名字暂时不知道。
4. 预期：草稿更新为 v2，决策链角色明确，**姓名保持未知，不生成任何姓名**。
5. 点「确认保存（保存到 Demo）」→ 提示「已保存到 Demo」。连续点两次：第二次提示幂等拦截，不产生重复记录。

**第二步，时间线（机会详情页）**

- 首页 → 点击「东莞供电局 · SVG…」→ 时间线出现新日志，展开「字段与来源」可见证据引文与日志 ID；完整度按最新已确认数据重算。
- 如演示前用录音按钮录过音，新日志带播放器可回放。

**第三步，阶段建议（机会详情页 → 「加载阶段建议」）**

- 预期：「初步方案 → 方案验证」建议（对应会议示例 40%→60%，概率标注为演示配置），展示规则依据（如「采购/评审计划」命中「方案已提交」）与缺口；点「确认推进」→ 提示仅修改 Demo 数据。

**第四步，简报与停滞提醒**

- 回日志对话输入：> 帮我整理这个项目的拜访前简报，重点说进展、风险和见客户要确认什么
- 预期：助手切换到简报能力（不把输入当新日志），插入可追溯简报卡（每条结论挂日志来源 ID），分节：项目概况/近期进展/关键关系/风险与未知项/拜访前建议确认。
- 回首页：可见佛山局的停滞提醒（187 天无有效活动 / 阶段停留 210 天，双口径），支持「仍在跟进 / 稍后 / 置休眠」；置休眠与丢单分开。
- 演示多机会纠正：日志对话里说 > 不对，把这条日志关联到东莞供电局的配电网智能巡检终端那个机会 → 草稿换关联并提示。

## 2. 十二条验证逐项核对

| # | 验证项 | 结论 | 证据 |
| --- | --- | --- | --- |
| 1 | mock 默认；生产无任何业务写路径 | **实测通过** | 全代码库写路径审计：SQL 写仅落 SQLite（store.js/db.js/stagnation.js/orchestrator.js/seed）；sf CLI 仅存在于 sf-readonly.js 且只允许 `data query`（默认禁用 `SOSP_ENABLE_SF_READONLY=false`）；本次实施未向生产发送任何写请求 |
| 2 | UAT 身份不符/未认证拒绝写入，不回退生产 | **实测通过（测试替身）** | `SOSP_MODE=uat` 隔离实例+DB 副本：`saveVisitLog`/`confirmStageChange` 均 `MODE_FORBIDDEN`；`SOSP_UAT_WRITE=true` 但未核验组织时同样拒绝；伪造 `mode/org` 请求参数被服务端忽略 |
| 3 | 各模式保存去向与界面标识一致 | **实测通过** | `/api/mode` 返回 label/note；保存响应 `writeTarget: demo-local`；页面固定徽章「演示数据」 |
| 4 | 多机会纠正关联；预算/姓名/决策角色不臆造；否定更新草稿 | **实测通过** | 实测对话：预算"没问题"保持待确认（未生成金额）；"名字暂时不知道"保持未知；"把这条关联到巡检终端"草稿换关联并出提示 |
| 5 | 连续保存幂等；刷新保草稿；未知结果不盲目重试 | **实测通过** | 同 clientToken 二次确认返回「幂等拦截」且日志数不变；普通待存和文件已重命名但数据库未提交两种状态均通过真实服务重启恢复；保存仅在首次落库时执行一次 |
| 6 | 时间线/完整度/简报数据一致；补录、模糊日期正确 | **实测通过** | 三者同源 `getOpportunityContext`；补录日志带标记且不计入停滞口径；日期引擎单测 9 项 PASS（下周/下周一/9月20日/本月/5天后/补录阈值等） |
| 7 | 录音→转写→修正→保存→回放→简报闭环；模拟与真实分别说明 | **实测通过（服务链路）/ 待真机采集确认** | WAV 原音真实上传→草稿版本绑定→确认保存→完整及 Range 回放→跨设备 403 均通过；讯飞官方 16k PCM 样例经直接 API、本地代理和公网 WSS 均返回正确文字；浏览器麦克风采集需用户手机确认 |
| 8 | 会话不串数据；未登录不可读；浏览器无后端凭据 | **实测通过** | 设备 owner、可撤销 auth session、旧无 owner 会话失败关闭；错误设备请求录音 403；未登录大 body 在解析前 401；退出会关闭已建立 ASR；Cookie/AI token/密钥均不暴露到前端 |
| 9 | 构建与自动化检查通过；测试用隔离数据 | **实测通过** | 全部源文件 `node --check`、`test:store`、`test:uat`、本地/公网 `test:security`、ASR 三段测试、两种重启恢复及真实 `test:recording-flow` 通过；`npm audit` 为 0 |
| 10 | 手机尺寸布局、软键盘、录音权限、断网恢复 | **待用户真机确认** | 代码具备 safe-area、16px 输入防缩放、MediaRecorder 格式探测、ASR 建连前 PCM 缓冲、IndexedDB 录音暂存和消息 outbox；当前环境无可控浏览器/真机，无法代验 |
| 11 | 同一会话意图切换不丢草稿；查询不误写 | **实测通过** | 实测同会话 日志→简报→查询→纠正关联 连续切换，草稿 v3 保留；`get_opportunity_context` 只读 |
| 12 | 工具接口与日志专项分离；参数不能绕过模式校验 | **实测通过** | 工具白名单校验（validate.js）+ 每工具声明 kind/allowedModes（tools.js）+ 唯一写路径在 store 层强制模式（store.js）；写路径审计见 #1 |

**“停止录音→草稿卡”耗时说明**：讯飞流式转写与录音同步进行，官方样例停止后正常返回最终文字；随后模型响应热请求仍可能约 12—23 秒，冷启动更长。AI 空闲 60 秒后自动退出，历史达到 12 轮后自动轮换并删除旧会话；手机实际耗时待真机记录。

## 3. 真实与模拟边界（必须向演示对象说明）

| 能力 | 状态 |
| --- | --- |
| 录音、存储、回放 | **真实**（浏览器 MediaRecorder → 服务端私有目录 → 鉴权回放） |
| 语音转写（ASR） | **真实讯飞云端调用**（语音听写流式版；本站鉴权 WSS 代理，密钥不进入浏览器） |
| 字段提取/意图路由/追问 | **真实 AI 调用**（隔离 opencode 实例 + zai/deepseek 模型） |
| 机会/日志/完整度/阶段规则/停滞提醒/简报 | **真实程序逻辑**，运行在合成演示数据上 |
| 保存 | **真实写入本地 Demo SQLite**；不写任何 Salesforce 环境（生产只读/UAT 均未启用写入） |
| 阶段推进/休眠 | 仅修改 Demo 数据，界面明确提示 |
| 阶段概率（40%/60% 等） | 演示配置，非组织真实配置（已核实阶段名，概率待 UAT 核对） |

## 4. 尚未完成 / 待用户确认项

1. **真机体验**（手机浏览器录音授权、Web Audio PCM 采集、软键盘和布局）——需用户用手机实测 `https://sosp.zhuxincn.com/`。服务端、讯飞 API 和公网 WSS 已验证，当前环境没有可驱动的浏览器或真实麦克风，不能代替真机结论。
2. **测试凭据轮换**：服务端访问码已轮换、迁出源码并改为必填，新值仅存于 `/etc/sosp-assistant/access.env`（0600）；本轮使用过的讯飞测试凭据仍应在讯飞控制台重置，并只更新 `/etc/sosp-assistant/xfyun.env`。
3. **UAT 认证**：完成认证后按《UAT接入说明》开启。
4. **阶段概率核对**：production-readonly 开启后只读核对组织真实概率配置。
