forked from admin/PlantAI-rag-new
test: 176 手工测试 13 项缺陷验收用例(r3)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,556 @@
|
||||
# 验收用例:176 手工测试 13 项缺陷(r3)
|
||||
|
||||
- 状态:修复前落库(测试设计),复测在修复完成后按 TL 通知执行。
|
||||
- 范围:176 手工测试 Excel 缺陷 #7、#27、#28、#31、#32、#37/38、#39、#40、#42、#47、#52、#55。
|
||||
- 修复分工:Debug-1 前端(ui/)、Debug-2 后端(sdk/ + agent/ + deploy/)。本文件是修复目标与复测依据。
|
||||
- 对应修复基准:仓库 `feature/bioflow-conversation-orchestration` @ f463194;修复落在 175 本地 debug worktree 分支。
|
||||
|
||||
## 0. 环境与执行约定
|
||||
|
||||
| 标识 | 环境 | 用途 |
|
||||
|---|---|---|
|
||||
| S1 | 175 dev 实例(vite dev server + 独立 dev BFF 9090) | 功能正确性复测。绝不可打生产 8090。浏览器实测用 vite dev server + Mac 隧道,端口由 TL 在复测时提供。 |
|
||||
| S2 | 176 终验(生产拓扑 80 端口,真实 QA/Neo4j/MinerU,CPU 无 GPU) | 性能阈值、真实 mineru、真实图谱数据。 |
|
||||
|
||||
通用约定:
|
||||
|
||||
- 浏览器证据:DevTools → Console(错误)、Network(请求/响应体)、Performance(计时);关键帧截图存 `~/acceptance-r3/缺陷号-步骤.png`(175 或本机均可,缺陷单里写路径)。
|
||||
- API 证据:curl 响应全文粘贴进缺陷单,或 `-o /tmp/acceptance-r3/xx.json` 存档。
|
||||
- 时序测量:UI 动画用 `performance.now()` 差值(本地动画,隧道网络不影响);API 时延用 `curl -w 'time_total: %{time_total}s'`。
|
||||
- 所有「<Ns」阈值的测量起点/终点在各用例内写死;±10% 记 PASS(备注实测值),超阈值记 FAIL。
|
||||
- 会话/消息接口基础约定:创建会话 `POST /api/sessions {"title":"r3-xx"}` 返回 `id` 即 `SID`,下文引用。
|
||||
|
||||
文案事实源(修复前后均以源码为准,断言文案若与修复实现有出入,以修复后 i18n 键为准并在缺陷单注明):
|
||||
|
||||
- `ui/src/i18n/labels.js`:TAB「检索过程 / 文献来源 / 提取任务 / 知识图谱」、`sourceEmpty: '本次检索未命中文献'`、`retrievalEmpty: '发起提问后,这里会实时展示检索过程'`、`skipReveal: '跳过'`、`extractRunLog`(运行日志按钮)。
|
||||
- `ui/src/i18n/docgen.js`:文档 TAB「文档」、`docPaneExportPdf: '导出 PDF'`、`docPaneExportDocx: '导出 DOCX'`、`docPaneExporting: '导出中…'`、`docPaneExportReady: '下载'`、内置模板键 official(通用公文(红头))/ report / application / contract / speech / plan / document、`docPaneEmpty` 空态文案。
|
||||
- `ui/src/i18n/private.js`:`libraryTitle: '📁 我的资料'`、`libraryEmpty`、`libraryLoading`。
|
||||
- 端点契约(修复目标):`POST /api/docgen/generate → 202 {ok,task_id,status:"queued"}`;`GET /api/docgen/tasks/{task_id} → 200 {ok,task:{id,session_id,status,progress[],artifact|null,error}}`;`GET /api/docgen/tasks?session_id=`;`POST /api/qa/search` 超时 → 200 降级体;`GET /api/kg/entities*` 超时 504 TIMEOUT / 实例不可用 503 UPSTREAM_DOWN。
|
||||
|
||||
---
|
||||
|
||||
## 1. 缺陷 #7 答案揭示动画
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1(动画/序号/跳过);S2 复跑一次终验 |
|
||||
| 用户原话 | 「标题章节没有序号,且超时」 |
|
||||
|
||||
**前置数据**
|
||||
1. 新建会话(或使用无历史的新会话),关闭「减少动态效果」类系统设置,确认 `prefers-reduced-motion` 未命中(否则揭示动画被跳过,用例失效)。
|
||||
2. 准备两个问题:
|
||||
- Q1(序号断言):「请列出水稻基因组分析的主要步骤,每个步骤给出详细说明,包括数据准备、质控、比对、变异检测、注释五个阶段」——期望答案含多级 markdown 标题。
|
||||
- Q2(超时断言):「请写一篇关于水稻基因组学研究的综述文章,内容不少于 3000 字,分章节论述」——期望答案 >2000 字符。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **短答案 30ms/字符节奏**(Q1,若答案 ≤2000 字符):
|
||||
- 发送 Q1,答案开始揭示。在消息区观察:字符以逐块节奏出现(源码常量 REVEAL_STEP_MS=30),非一次整段闪出。
|
||||
- 断言:stream 块可见 `.stream-cursor`(尾部光标)+ `.shimmer-line`(shimmer 条),揭示中「跳过」按钮可见(`T.skipReveal` 文案)。
|
||||
- 断言:总揭示时长 ≈ 字符数 × 30ms(±20%),可用 `performance.now()` 从首字符到光标消失测量。
|
||||
2. **长答案总时长上限**(Q2):
|
||||
- 发送 Q2,答案完成后进入揭示阶段。用 `performance.now()` 记录 stream 块首帧出现 → 光标消失(揭示完成)的时长 T。
|
||||
- 断言:T ≤ 8.5s(需求:>2000 字符自动加速,总时长上限 8s,留 0.5s 计时误差)。
|
||||
- 注意:若实际答案 <2000 字符,标注「条件未达成,按短答案节奏校验」,不计 FAIL,需换更强的 prompt 重试一次。
|
||||
3. **跳过**:
|
||||
- 揭示进行中点击「跳过」按钮。断言:全文立即完整显示、`.stream-cursor`/`.shimmer-line`/「跳过」按钮消失;消息状态为 done;Console 无残留 `setInterval` 报错、无未捕获异常。
|
||||
4. **标题编号注入**(Q1 答案):
|
||||
- 揭示完成后,检查消息区 markdown 渲染结果:一级标题文本以「一、」开头、二级以「1.1」开头、三级以「1.2.3」形式开头。
|
||||
- 断言:所有 h1/h2/h3 标题均有编号;若答案中已有编号(如「1. 概述」),不得重复编号(原文保持)。
|
||||
5. **图片注入预算**(含图答案,依赖 Debug-2):
|
||||
- 提问要求答案含图(如「用图表说明水稻基因组分析流程」),若 QA 答案带图片,断言:SSE 最后一个 answer/progress 帧到 `complete` 帧间隔 ≤3s(修复目标:图片注入总预算 2.5s,留 0.5s 网络抖动;3~5s 记 WARN 备注)。
|
||||
- 测量方法:curl -N 直连 dev BFF `/api/qa/chat/stream` 打时间戳,或浏览器 Network 的 SSE 消息时间线。
|
||||
|
||||
**通过标准**:1~4 全过;5 若环境产生图片答案则必过,否则记 N/A。
|
||||
**证据**:时间戳测量(console 日志或截图带时间)、答案渲染截图、Network SSE 帧时间线;失败时录 browser console 全量日志 + 答案长度(字符数)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 缺陷 #27 会话级来源聚合
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1(功能);S2 终验一次 |
|
||||
| 用户原话 | 「聚合后,文献的 id 对应不上,会往后+1」 |
|
||||
|
||||
**前置数据**
|
||||
1. 新建会话 SID。
|
||||
2. 在同一会话内连续问两个相关检索问题(如「水稻抗病基因有哪些」「水稻抗病育种研究进展」),使两轮答案各产生若干文献来源(答案卡下方来源行、文献来源 TAB 均有条目)。
|
||||
3. 记录每轮答案中来源的 paper_id(Network 中 `/api/qa/search` 与 `/api/qa/chat/stream` evidence 帧的 `sources[].paper_id` / `id`)。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **API 聚合正确**:
|
||||
- `curl "http://<devBFF>/api/sessions/<SID>/sources"`(S1 打 9090,下同)。
|
||||
- 断言:200,`{ok:true, sources:[...]}`;按 paper_id 去重(无 paper_id 按 id);每个条目 `count` 等于该 paper_id 在两轮中出现的总次数;条目 `id/paper_id` 与前端展示一致。
|
||||
2. **文献来源 TAB 徽标**:
|
||||
- 右工作台切到「文献来源」TAB,筛选「本会话全部」(聚合视图)。
|
||||
- 断言:条目数 = API 去重后的条目数;每条徽标显示的文献 id 与 API 返回的 `paper_id`/`id` 完全一致,无「+1」偏移;`count` 徽标数字与 API `count` 一致。
|
||||
3. **两轮重复文献场景**:
|
||||
- 断言:两轮都出现的同一篇文献只显示一条(不重复列出),count ≥ 2。
|
||||
|
||||
**通过标准**:1~3 全过。
|
||||
**证据**:`/api/sessions/<SID>/sources` 响应体全文、文献来源 TAB 截图(徽标清晰)、两轮答案的来源截图对照。
|
||||
|
||||
---
|
||||
|
||||
## 3. 缺陷 #28 检索空态 / 超时降级
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1(正常空结果 + 前端文案);S2(超时降级、正常空态终验) |
|
||||
| 用户原话 | 「检索显示超时,应该提示『没有检索到此问题的有效回答』」 |
|
||||
|
||||
**前置数据**
|
||||
1. 准备一个正常空结果问题:「请问 1234567890qwertyuiop 这种字符串与植物有什么关系」(无意义问题,期望 `sources: []`)。
|
||||
2. 准备一个可触发上游检索超时的问题(176 终验):针对大体量库的复杂检索问题,或由 TL 在复测时指定;S1 若 dev QA 实例可复现超时则顺带测,否则该项留 S2。
|
||||
3. 修复要求确认:BFF `/api/qa/search` 请求体注入 `native_chain_enabled:false`;超时返回 200 降级体 `{"mode":"search","answer":"","sources":[],"degraded":true,"reason":"TIMEOUT"}`。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **BFF 注入断言**(API 层):
|
||||
- 在浏览器 Network 面板观察发送检索问题时 `POST /api/qa/search` 的请求体。
|
||||
- 断言:请求体含 `"native_chain_enabled": false`(或 BFF 层等价禁用图链的字段)。
|
||||
2. **正常空结果(S1 可测)**:
|
||||
- 检索模式(输入框下方模式 pill 选「检索」,或直接发送使意图路由到 search)发送空结果问题。
|
||||
- 断言:消息区出现明确提示文案「没有检索到此问题的有效回答」(修复后文案,以源码 i18n 为准);不显示 pipeline 五相位卡或错误样式。
|
||||
- 切到「检索过程」TAB:显示「本次检索未命中文献」(`T.sourceEmpty`)。
|
||||
- Network:`POST /api/qa/search` 响应 200,`sources:[]`、`degraded:false`(正常空结果不得误标 degraded)。
|
||||
3. **超时降级(S2)**:
|
||||
- 发送触发超时的问题。
|
||||
- 断言:消息区出现超时专属文案(如「检索超时」+「没有检索到此问题的有效回答」区分展示,与空结果文案可区分);不显示错误信封样式。
|
||||
- Network:`/api/qa/search` 响应 status=200,body 含 `degraded:true`、`reason:"TIMEOUT"`、`mode:"search"`。
|
||||
- 时序断言:请求发起到收到 200 降级体的时长 ≤120s(修复目标:检索模式超时上限 120s;当前源码 SEARCH_READ_TIMEOUT=180,修复后应缩短)。用 `curl -w time_total` 复核一次。
|
||||
4. **降级与空结果可区分**:
|
||||
- 断言:降级(TIMEOUT)与正常空结果在 UI 呈现不同文案/样式;两者都不会让「检索过程」TAB 显示检索进度卡死(如有 pipeline 卡,应终态化而非永远 loading)。
|
||||
|
||||
**通过标准**:1、2、4 全过;3 在 S2 过。
|
||||
**证据**:Network 请求/响应体截图或复制、消息区提示文案截图、`curl -w` 时延输出。
|
||||
|
||||
---
|
||||
|
||||
## 4. 缺陷 #31 图谱节点详情
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1(交互竞态);S2(实体端点最坏 30s 串行观察,随 neo4j 适配消失) |
|
||||
| 用户原话 | 「点击图节点没办法显示出实体属性…重新点击搜索…才能显示,同时,弹出频率异常」 |
|
||||
|
||||
**前置数据**
|
||||
1. 「知识图谱」TAB 打开,KgPane 图谱已渲染(含节点/边)。
|
||||
2. 准备 2 个已知实体节点(如「水稻」「拟南芥」或图谱中实际存在的节点,先在搜索框确认)。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **点击节点弹详情**:
|
||||
- 原地单击(位移 <4px)节点 A。
|
||||
- 断言:≤1s 内右侧/侧滑出现 KgEntityDetail 面板,展示实体属性(properties 键值,如名称/类型/别名);无需二次点击搜索。
|
||||
- Network:`GET /api/kg/entities/<A> → 200 {ok:true, ...}` 且仅 1 次请求(无重复触发)。
|
||||
2. **拖拽不触发点击**(修复目标:位移阈值 4px 判定拖拽):
|
||||
- 按住节点 A 拖动 2~3px 释放(微拖):断言不弹出详情面板。
|
||||
- 按住空白处拖动平移画布(≥5px):断言不弹出详情面板。
|
||||
- 再原地点击节点 B:详情面板更新为 B 的属性,内容与 B 一致(无串台)。
|
||||
3. **快速连点竞态**(旧缺陷「弹出频率异常」):
|
||||
- 快速依次点击节点 A → 节点 B(间隔 <500ms)。
|
||||
- 断言:始终只有一个详情面板;最终显示的内容 = 最后点击的节点 B 的实体属性;面板内容与节点一一对应,无闪烁/无「点了没反应、再点一次才出」现象。
|
||||
- 检查 Console:无「response 与请求不匹配」类竞态日志(修复目标 :key 重建+序号守卫后无竞态)。
|
||||
4. **详情面板交互**:
|
||||
- 面板内关闭按钮 → 面板关闭;再次点击同一节点可重新打开。
|
||||
- 邻域展开(若面板提供):点击邻域实体 → `GET /api/kg/entities/<id>/neighborhood` 200,渲染邻域图。
|
||||
5. **超时/不可用分流**(S2 或 dev 模拟):
|
||||
- 查询超时 → `504` + `{error:{code:"TIMEOUT"}}`;Neo4j 实例不可用 → `503` + `{error:{code:"UPSTREAM_DOWN"}}`。两者 UI 均显示可读错误提示,不白屏。
|
||||
- 模拟方法(仅 dev):临时将 dev BFF 的 NEO4J_URI 指向空端口复现 503;验后还原配置并重启 BFF。
|
||||
- 实体端点最坏 30s 串行:连续请求多个实体详情,观察在适配修复后不再出现「最坏 30s 串行」排队(S2 观察项,若仍存在记 WARN 并留证据)。
|
||||
|
||||
**通过标准**:1~4 全过;5 中 504/503 分流必过,30s 串行观察为 S2 记录项。
|
||||
**证据**:节点点击/拖拽过程录屏或连拍截图、Network 面板 `/api/kg/entities*` 请求列表与状态码、Console 日志。
|
||||
|
||||
---
|
||||
|
||||
## 5. 缺陷 #32 实体搜索(「水稻」)
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1(功能:搜索/命中/渲染);S2(时延 <1s、真实数据、索引脚本执行后) |
|
||||
| 用户原话 | 「输入水稻 响应超时」 |
|
||||
|
||||
**前置数据**
|
||||
1. S2 前置:176 上执行修复提供的 neo4j normalized schema Cypher 适配 + 索引脚本(部署 agent 负责,复测前由 TL 确认已执行)。
|
||||
2. 175 dev Neo4j 数据与生产同源,可用于 S1 功能验证。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **API 前缀/精确匹配**:
|
||||
- `curl -w 'time_total:%{time_total}s' "http://<BFF>/api/kg/entities?q=水稻&limit=20"`。
|
||||
- 断言:200;`results[]` 含 name 以「水稻」开头或精确等于的实体(字段 id/name/type/support_count);时延 S1 ≤3s、S2 <1s(修复目标)。
|
||||
- 超时场景:504 + `code:"TIMEOUT"`;Neo4j 不可用:503 + `code:"UPSTREAM_DOWN"`(与 #31-5 同分流)。
|
||||
2. **UI 搜索**:
|
||||
- 知识图谱 TAB 搜索框输入「水稻」→ 回车/点搜索。
|
||||
- 断言:结果列表 ≤1s(S2)渲染命中实体;无「响应超时」提示;无卡死(旧缺陷)。
|
||||
3. **邻域渲染**:
|
||||
- 点击任一命中实体。
|
||||
- 断言:详情面板/邻域图渲染该实体及其邻域(nodes/edges 非空),`/api/kg/entities/<id>/neighborhood` 200;图谱画布无长时间白屏。
|
||||
|
||||
**通过标准**:1~3 全过(S1 过功能与 ≤3s,S2 过 <1s)。
|
||||
**证据**:curl 输出(含 time_total)全文、UI 搜索截图、Network 响应时间。
|
||||
|
||||
---
|
||||
|
||||
## 6. 缺陷 #37/#38 PDF 上传提取(mineru)
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1(错误可读性/上传链路);S2(176 MinerU CPU 裸部署后真实提取) |
|
||||
| 用户原话 | 「【Error2】No such file or dictionary:'/home/xzq/miniconda3/envs/minerupy312/bin/mineru'」 |
|
||||
|
||||
**前置数据**
|
||||
1. 样例 PDF(≥2 个,含文字+图片,5MB 左右),存放 175 `~/acceptance-r3/samples/` 与 176 相应目录。
|
||||
2. 修复要求:mineru 路径 X_OK 预检返回可读错误;`MINERU_CMD` env 可覆盖;GPU 预检开关(176 设 0);`GF_PYTHON_ENV` env 化;figures.py 常量 env 化。
|
||||
3. S2 前置:176 MinerU CPU 裸部署完成(部署 agent 并行进行),`MINERU_CMD` 指向 176 部署路径。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **上传链路(S1)**:
|
||||
- 「提取任务」TAB 点「上传」选 PDF。
|
||||
- 断言:上传进度可见(loading 文案/进度),上传成功提示(✓);任务列表出现新任务,状态 queued → running。
|
||||
- Network:`POST /api/extraction/upload` 200/201。
|
||||
2. **mineru 缺失/不可用时的可读错误(S1,若 175 无可用 mineru)**:
|
||||
- 任务进入 mineru 阶段后失败。
|
||||
- 断言:任务详情或运行日志出现中文可读错误,明确包含:不可用的 mineru 路径 + 原因(文件不存在/不可执行)+ 修复提示(如「请设置 MINERU_CMD 环境变量」),不得再出现原始 `No such file or directory:'...mineru'` 裸英文错误。
|
||||
- 若 175 存在可用 mineru(minerupy312 可用),则任务应成功进入 llm 阶段,本项改为断言成功路径。
|
||||
3. **S2 真实提取(176)**:
|
||||
- 上传含图 PDF,任务 queued → mineru(35%)→ llm → done。
|
||||
- 断言:运行日志无 `No such file or directory`、无 GPU 相关报错(176 无 GPU,GPU 预检开关已设 0,不得因无 GPU 拒绝任务);提取产物(结构化内容/图表)可查看;时延记录(CPU 时延仅记录,不设阈值)。
|
||||
- 断言:env 化生效——BFF 进程环境含 `MINERU_CMD`/`GF_PYTHON_ENV`(由 Debug-2 提供检查命令),且任务按 env 指定路径执行。
|
||||
|
||||
**通过标准**:1 过;2 或 3 按环境满足其一;S2 真实提取全链过。
|
||||
**证据**:任务详情/运行日志截图、BFF 日志(`/tmp/plantai-bff*.log` 或 dev BFF 日志路径,复测时确认)、上传 Network 截图。
|
||||
|
||||
---
|
||||
|
||||
## 7. 缺陷 #39 运行日志
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1 |
|
||||
| 用户原话 | 「日志无法刷新加载」 |
|
||||
|
||||
**前置数据**
|
||||
1. 「提取任务」TAB 有历史任务(或新上传一个 PDF 制造 running 任务)。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **打开总是重拉**:
|
||||
- 点「运行日志」展开按钮。
|
||||
- 断言:每次打开(收起→再展开)都会发起新的 `GET /api/extraction/run-log` 请求(Network 可见),内容为最新日志,而非仅首次加载后不刷新(旧缺陷)。
|
||||
2. **running 时 5s 轮询**:
|
||||
- 存在 running 任务时保持日志展开,观察 15s。
|
||||
- 断言:Network 中 `/api/extraction/run-log` 每约 5s 出现一次(15s 内 ≥2 次);日志内容随时间变化(出现新行)。
|
||||
3. **刷新按钮**:
|
||||
- 若修复提供手动刷新按钮:点击 → 立即发起一次 run-log 请求并更新内容。
|
||||
4. **展示形态**:
|
||||
- 断言:日志区为 mono 字体(元素 `.run-log`,font-family monospace 系);最大高度受限(样式 max-height 生效,超高滚动);自动贴底——新日志行到达后滚动条停在底部(可强制向上滚动后观察是否被拉回底部,若实现为「仅当已贴底才跟随」则验证该语义)。
|
||||
|
||||
**通过标准**:1、2、4 过;3 若存在按钮则必过。
|
||||
**证据**:Network 面板 run-log 请求时间线截图、日志区滚动截图。
|
||||
|
||||
---
|
||||
|
||||
## 8. 缺陷 #40 提取任务轮询刷新
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1 |
|
||||
| 用户原话 | 「轮询存在…tab内容没有刷新」 |
|
||||
|
||||
**前置数据**
|
||||
1. 上传一个 PDF 制造 running 任务(或复用 #39 的任务)。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **每 5s 轮询且内容刷新**:
|
||||
- 停在「提取任务」TAB,任务 running。观察 15s。
|
||||
- 断言:Network 中 `/api/extraction/jobs`(及任务详情端点)每约 5s 出现一次;任务列表卡片内容随状态/进度更新(旧缺陷:轮询存在但 TAB 内容不刷新)。
|
||||
2. **切走暂停**:
|
||||
- running 期间切到「检索过程」TAB(任何离开 extract 的 TAB)。
|
||||
- 断言:切换后 Network 中 10s 内不再出现 `/api/extraction/jobs` 轮询请求(轮询暂停)。
|
||||
3. **切回恢复**:
|
||||
- 切回「提取任务」TAB。
|
||||
- 断言:≤5s 内恢复轮询,列表刷新为最新状态。
|
||||
4. **全部终态停止**:
|
||||
- 等任务全部进入终态(done/error),停留 15s。
|
||||
- 断言:终态后轮询停止(Network 无周期请求),列表不再刷新。
|
||||
5. **详情/日志展开态保留**:
|
||||
- 展开任务 A 的详情与运行日志 → 切到「文献来源」→ 切回。
|
||||
- 断言:任务 A 详情仍展开、日志仍展开且内容保留(提升到 store,切回不丢;旧缺陷相反)。
|
||||
|
||||
**通过标准**:1~5 全过。
|
||||
**证据**:Network 时间线截图(标注切换 TAB 的时刻)、前后列表内容对照截图。
|
||||
|
||||
---
|
||||
|
||||
## 9. 缺陷 #42 docgen 模板选择
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1 |
|
||||
| 用户原话 | 「UI中没有模板选择选项」 |
|
||||
|
||||
**前置数据**
|
||||
1. 上传 1 份资料(任意 PDF/TXT)并在「我的资料」将该资料勾选/标记为「设为模板」(as_template=true;如 UI 尚无标记入口,用 API:`PATCH /api/docgen/library/<id> {"as_template":true}`,复测时以修复后 UI 为准)。
|
||||
2. 确认 `GET /api/docgen/library?as_template=true` 返回该资料。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **模板下拉出现**:
|
||||
- Composer 输入写作需求(如「帮我写一份项目申报材料」),在 docgen 意图被识别/输入态(修复目标:docgen 模式)下观察 Composer 区域。
|
||||
- 断言:出现模板选择下拉(或等价控件),含「自动推荐」默认项 + 内置模板列表:通用公文(红头)/ 报告总结 / 申报材料 / 合同协议 / 讲话稿 / 方案计划 / 通用文档 + 用户 as_template 资料。
|
||||
2. **payload 携带 template_id**:
|
||||
- 下拉选择「通用公文(红头)」→ 发送。
|
||||
- 断言:Network 中 `POST /api/docgen/generate` 请求体含 `template_id`,值为该模板的 id(与 `/api/docgen/library` 或模板索引对应);返回 202(修复后契约)+ `task_id`。
|
||||
3. **产物模板生效**:
|
||||
- 生成完成后(轮询 task 至 done,见 #52),文档 TAB / DocCard 显示「模版:通用公文(红头)」;产物 JSON `artifact.template_name`(或 `template_key`)为 official。
|
||||
4. **自动推荐**:
|
||||
- 不手动选模板直接发送 → payload 无 template_id 或为自动推荐结果,生成正常,产物模板名与自动推荐一致(记录实际推荐结果)。
|
||||
|
||||
**通过标准**:1~4 全过。
|
||||
**证据**:Composer 下拉截图、Network generate 请求体复制、产物信息截图/JSON。
|
||||
|
||||
---
|
||||
|
||||
## 10. 缺陷 #47 导出 DOCX(红头)与文档占用
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1(功能与格式);S2 终验一次 |
|
||||
| 用户原话 | 「导出 DOCX…格式不一致,删除红头文件对话内容,红头文件还占用在文档界面中(不刷新网页下)」 |
|
||||
|
||||
**前置数据**
|
||||
1. 生成一份「通用公文(红头)」文档,正文含表格(模板自带或让 QA 生成含表格内容)与图片(生成时附带含图资料,见 #52)。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **47a 导出 DOCX 格式一致**:
|
||||
- 文档 TAB 打开该文档 → 点「导出 DOCX」按钮。
|
||||
- 断言:按钮变「导出中…」→ 完成后触发下载(文件名合理,.docx);Network:`POST /api/docgen/artifacts/<id>/export {"format":"docx"}` 成功。
|
||||
- 打开下载的 .docx(本地 Word / LibreOffice):断言红头文字为红色且居中、标题层级与预览一致、表格有边框且内容完整、图片存在。与「导出 PDF」或 HTML 预览对照,整体版式一致(修复目标:HTML 同源转换)。
|
||||
- 异常回退路径(HTML 转换失败回退 md2docx)由 Debug-1/2 单元测试覆盖,复测仅记录正常路径;若导出失败,按缺陷单登记。
|
||||
2. **47b 会话切换 resetSession**:
|
||||
- 在会话 A 生成红头文档(文档 TAB 被其占用)→ 切换到会话 B(无文档)。
|
||||
- 断言:文档 TAB 显示空态文案「尚无文档。在对话中提出写作需求…」,不再显示会话 A 的红头文档。
|
||||
- 切回会话 A:文档 TAB 恢复显示红头文档(resetSession 只清不丢)。
|
||||
3. **删除对话不残留**(旧缺陷场景):
|
||||
- 会话 A 中删除该 docgen 对话消息(或删除整个会话)。
|
||||
- 断言:不刷新网页的前提下,文档 TAB 立即回到空态/资料库视图,红头文件不再占用文档界面。
|
||||
|
||||
**通过标准**:1~3 全过。
|
||||
**证据**:导出 DOCX 打开截图(红头/表格/图片)、文档 TAB 前后截图、删除消息操作截图。
|
||||
|
||||
---
|
||||
|
||||
## 11. 缺陷 #52 上传资料生成文档(异步任务化)
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1(功能);S2 终验一次 |
|
||||
| 用户原话 | 「上传成功了,但是没办法进行对话…删除对话文件,保留资料内容,可以进行总结」 |
|
||||
|
||||
**前置数据**
|
||||
1. 准备 1~2 份资料 PDF(内容与「水稻」相关,便于断言生成基于上传内容)。
|
||||
2. 修复契约:`POST /api/docgen/generate → 202 {ok:true, task_id, status:"queued"}`;`GET /api/docgen/tasks/{task_id} → 200 {ok, task:{id, session_id, status, progress:[{section,title,state}], artifact:{id,title,template_name,template_key,has_html,letterhead,file_name}|null, error:null|中文可读}}`。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **上传进度与资料留存**:
|
||||
- Composer 拖拽 PDF → 附件 chips 出现 + 上传进度可见(百分比/进度条,0→100%)。
|
||||
- 断言:上传成功后资料出现在「我的资料」列表;`POST /api/docgen/library → 201`。
|
||||
2. **异步生成 202+task_id**:
|
||||
- 发送「根据上传资料生成一篇总结文档」。
|
||||
- 断言:Network `POST /api/docgen/generate` 返回 status=202,body `ok:true`、`task_id` 为 uuid、`status:"queued"`(修复前是同步 200,重点断言 202)。
|
||||
- 消息区出现生成卡片(流水线五步或 DocCard),状态「排队中/生成中」。
|
||||
3. **task 轮询与进度**:
|
||||
- `curl "http://<BFF>/api/docgen/tasks/<task_id>"` 每 2~3s 一次直到终态。
|
||||
- 断言:status 按 queued → running → done 演进;`progress[]` 含 section/title/state(done|running|pending),与前端五步卡片一致;done 后 `artifact` 非空:title 非空、template_name 非空、has_html 布尔、letterhead 布尔、file_name 非空;error 为 null 或(失败时)中文可读。
|
||||
- `GET /api/docgen/tasks?session_id=<SID>`:返回该会话 task 列表,含上述 task_id。
|
||||
4. **生成期间可继续对话**(核心旧缺陷):
|
||||
- 生成任务 running 期间(5~15s 窗口),在对话中输入「你好,介绍一下你自己」发送。
|
||||
- 断言:该消息得到正常回答(消息区出现 assistant 回复),不被文档生成阻塞(旧缺陷:上传成功后无法进行对话)。
|
||||
5. **删除对话文件保留资料**:
|
||||
- 生成完成后,删除该 docgen 对话消息。
|
||||
- 断言:上传的资料仍在「我的资料」列表,未被级联删除;资料仍可发起新对话/总结(用该资料再发一次总结请求,可正常生成)。
|
||||
6. **失败重试与重启中断标记**:
|
||||
- 失败路径(可强制:生成时 BFF 侧制造一次失败,或依赖真实失败):断言失败展示中文错误 + 提供「重试」按钮;点击重试 → 重新发起 generate(Network 新 task_id),可最终成功。
|
||||
- 重启中断:生成 running 时重启 dev BFF(仅 dev 9090)→ 重新打开页面,该任务在 UI 显示中断/失败态(不永久挂「生成中」),可重试。
|
||||
|
||||
**通过标准**:1~5 全过;6 中重试必过,重启中断为 S1 可测项必过。
|
||||
**证据**:Network 202 响应体、task 轮询 curl 输出全文、对话并发的两条消息截图、删除消息前后「我的资料」对照截图。
|
||||
|
||||
---
|
||||
|
||||
## 12. 缺陷 #55 上传资料入库与文档 TAB 占用
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 环境 | S1;S2 终验一次 |
|
||||
| 用户原话 | 「一旦进行过文档生成任务,文档TAB就会被生成的文档占用,导致上传的资料无法正常显示」 |
|
||||
|
||||
**前置数据**
|
||||
1. 完成一次文档生成(文档 TAB 被生成文档占用)。
|
||||
|
||||
**操作步骤与断言**
|
||||
|
||||
1. **视图切换按钮**:
|
||||
- 文档 TAB 被文档占用时,DocPane 顶部出现「资料库」/「关闭文档」视图切换按钮(修复新增,文案以实现为准)。
|
||||
- 断言:点「资料库」→ 文档区切换为「我的资料」面板(`libraryTitle: '📁 我的资料'`),列表显示已上传资料。
|
||||
- 点「关闭文档」(或等价返回)→ 回到文档视图/空态。
|
||||
2. **上传资料可见**:
|
||||
- 生成文档占用期间上传新资料(拖拽)。
|
||||
- 断言:上传进度可见(同 #52-1);完成后提示「已入库」(修复目标文案,以 i18n 为准);通过「资料库」按钮即可在文档 TAB 查看该资料(旧缺陷:上传的资料无法正常显示)。
|
||||
3. **API 佐证**:
|
||||
- `GET /api/docgen/library → 200`,列表含新上传条目(id/名称/大小/时间);`GET /api/docgen/library?as_template=true` 与资料列表共存正常。
|
||||
|
||||
**通过标准**:1~3 全过。
|
||||
**证据**:文档 TAB 两个视图切换截图、「我的资料」列表截图(含新上传条目)、上传进度截图。
|
||||
|
||||
---
|
||||
|
||||
## 13. 回归矩阵
|
||||
|
||||
修复波及面 → 逐条「做什么 + 看什么」。执行于 S1,任一条失败登记缺陷单并标注关联修复项。
|
||||
|
||||
### A. 知识库 sheet #6-12(聊天流/时间线/动画,关联 #7)
|
||||
|
||||
| 回归项 | 操作 | 看什么 |
|
||||
|---|---|---|
|
||||
| A1 检索时间线 | 提一个正常检索问题 | 检索过程 TAB 实时出现检索步骤时间线,顺序正确,不卡死 |
|
||||
| A2 流式五相位卡 | 问答模式提问 | 消息区 pipeline 五相位卡(规划/检索/证据/生成/完成)按序点亮 |
|
||||
| A3 答案揭示/跳过 | 任意答案 | 揭示动画正常、跳过生效(复测 #7 已覆盖,此处抽查短答案) |
|
||||
| A4 停止按钮 | 流式回答中点「停止」 | 立即停止,消息状态 done,无残留定时器;再发消息正常 |
|
||||
| A5 错误重试 | 制造一次失败(或点重试) | 重试重新发起请求,错误文案中文可读 |
|
||||
| A6 来源卡/证据帧 | 带来源的答案 | 答案卡来源行与文献来源 TAB 一致(关联 #27) |
|
||||
| A7 多轮历史 | 同会话连续 2 轮问答 | 第二轮携带 history,回答连贯,无 422 |
|
||||
|
||||
### B. docgen 全链 #41-53(关联 #42/#47/#52/#55)
|
||||
|
||||
| 回归项 | 操作 | 看什么 |
|
||||
|---|---|---|
|
||||
| B1 上传无大小限制 | 上传 >10MB PDF(≤50MB) | 正常上传(修复前曾移除 100MB 门槛,回归确认 50MB 校验仍在) |
|
||||
| B2 模板 HTML 预览 | 生成文档后打开预览 | 白底、排版正确、图片显示 |
|
||||
| B3 修改文档(prompt 修改) | 编辑模式输入修改指令 | 修改生效,自动保存,无「修改失败」 |
|
||||
| B4 导出按钮文字 | 点导出 | 按钮文字保持「导出 PDF/导出 DOCX」,不变成「下载」;导出中显示「导出中…」 |
|
||||
| B5 导出文件名 | 导出 | 文件名按 prompt 核心意思命名 |
|
||||
| B6 编辑还原 | 编辑模式改动 → 切预览 → 切回 | 手动修改内容不丢 |
|
||||
| B7 二次预览 | 开文档 A 预览后,再开文档 B | B 正常渲染,无空白 |
|
||||
| B8 意图路由 | 输入「帮我写一份报告」与普通提问 | 写文档意图进 docgen,普通问答不进;生物问答不进生信流(收紧回归) |
|
||||
|
||||
### C. 生信 sheet #32-35 图谱(关联 #31/#32)
|
||||
|
||||
| 回归项 | 操作 | 看什么 |
|
||||
|---|---|---|
|
||||
| C1 图谱概览 | 打开知识图谱 TAB | `GET /api/kg/overview` 200,节点/边渲染 |
|
||||
| C2 实体搜索 | 搜索已知实体 | 命中渲染(关联 #32) |
|
||||
| C3 实体详情 | 点节点 | 属性面板(关联 #31) |
|
||||
| C4 邻域展开 | 详情内展开邻域 | 邻域图正确 |
|
||||
| C5 图谱状态 | `GET /api/kg/status` | 200,状态正确 |
|
||||
|
||||
### D. 轮询与提取历史用例(关联 #39/#40)
|
||||
|
||||
| 回归项 | 操作 | 看什么 |
|
||||
|---|---|---|
|
||||
| D1 离线降级 | 停 dev 上游(或模拟)后打开提取 TAB | 显示离线降级块 + 「重试」按钮,点重试恢复 |
|
||||
| D2 上传校验 | 上传非 PDF / >50MB | 中文错误提示,不上传 |
|
||||
| D3 任务详情 | 展开任务 | 详情加载正常,错误态有重试按钮 |
|
||||
| D4 多任务列表 | 连续上传 2 个文件 | 列表两条任务,状态互不干扰 |
|
||||
|
||||
### E. 会话切换全家桶(关联 #47b/#40-5)
|
||||
|
||||
| 回归项 | 操作 | 看什么 |
|
||||
|---|---|---|
|
||||
| E1 切会话消息隔离 | A/B 两会话各有消息,来回切 | 消息列表各自正确,无串台 |
|
||||
| E2 切换时流不串 | A 会话流式中切到 B | A 的流式不影响 B;切回 A 状态正确(完成或已停止) |
|
||||
| E3 删除会话 | 删除会话 A | 列表移除,B 正常;文档 TAB 不残留 A 的文档 |
|
||||
| E4 新建会话 | 新建 | 空态正确,检索过程 TAB 显示「发起提问后,这里会实时展示检索过程」 |
|
||||
| E5 轮询会话隔离 | A 有 running 提取任务,切 B | 轮询随 TAB 暂停/恢复(关联 #40),B 无 A 的轮询 |
|
||||
|
||||
### F. 能力集成抽查(仅抽查,不回归全量)
|
||||
|
||||
| 回归项 | 操作 | 看什么 |
|
||||
|---|---|---|
|
||||
| F1 联网搜索开关 | 打开 web_search 开关提问 | 命中联网结果时展示 web 来源 |
|
||||
| F2 停止/中断 | SSE 流中途停止 | 无「断流崩溃」(BFF 日志无异常栈) |
|
||||
|
||||
---
|
||||
|
||||
## 14. 复测流程约定
|
||||
|
||||
1. **完成门禁**:13 项缺陷中全部 S1 项通过,缺陷单清零(S2 项见下),才算修复完成;S1 失败项回归修复后重测该项 + 其回归矩阵关联行。
|
||||
2. **S2 标记「176 终验」的项**:#7(时长终验)、#27、#28-3(超时降级)、#31-5(30s 串行观察)、#32(时延 <1s)、#37/38(真实 mineru)、#47(格式终验)、#52、#55。S1 全过后由 TL 组织 176 终验。
|
||||
3. **176 执行清单与数据准备**:
|
||||
- 数据:含图样例 PDF、水稻相关资料 PDF(≥2 份)、触达图谱「水稻」实体的 neo4j 数据、超时问题样例、>3000 字答案问题。
|
||||
- 部署前置:索引脚本已执行(问 TL/部署 agent)、MinerU CPU 裸部署完成且 `MINERU_CMD` 已设、GPU 预检开关=0。
|
||||
- 执行顺序:先 API(curl 层)后 UI;#37/38 上传提取;#32「水稻」时延;#28 超时;其余终验项按本文用例跑一遍并记录实测值。
|
||||
4. **复测环境纪律**:S1 只用 175 dev(vite dev + dev BFF 9090),绝不碰生产 8090;dev BFF 的模拟配置(如 NEO4J_URI 指向空端口)用后即还原并重启。
|
||||
|
||||
## 15. 缺陷单模板
|
||||
|
||||
复测发现缺陷按此登记(记入复测报告,由 TL 归档):
|
||||
|
||||
```
|
||||
缺陷编号: r3-<原始缺陷号>-<序号>(如 r3-31-01)
|
||||
关联修复项: #31(前端 KgGraphView/KgEntityDetail / 后端 entity 端点)
|
||||
复现步骤: 1. … 2. …
|
||||
实际结果: …
|
||||
期望结果: …
|
||||
证据: 截图路径 / API 响应全文 / 日志路径(BFF /tmp/plantai-bff*.log 或 dev 日志)
|
||||
严重级: P0(阻断) / P1(功能错误) / P2(体验) / P3(建议)
|
||||
复测环境: S1(175 dev) / S2(176)
|
||||
```
|
||||
|
||||
## 附录 A:快速 curl 断言清单(S1,dev BFF)
|
||||
|
||||
```bash
|
||||
BFF=http://127.0.0.1:9090 # dev BFF,复测时以 TL 给的地址为准
|
||||
|
||||
# #27 会话来源聚合
|
||||
curl -s $BFF/api/sessions/<SID>/sources | jq '.sources[] | {id, paper_id, count, title}'
|
||||
|
||||
# #28 检索模式(观察 200 降级体/空结果体;测量时延)
|
||||
curl -s -w '\ntime_total:%{time_total}s\n' -X POST $BFF/api/qa/search \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"question":"<问题>","session_id":"<SID>","use_llm":false}'
|
||||
|
||||
# #31/#32 图谱
|
||||
curl -s -w '\ntime_total:%{time_total}s\n' "$BFF/api/kg/entities?q=水稻&limit=20"
|
||||
curl -s "$BFF/api/kg/entities/<entity_id>"
|
||||
curl -s "$BFF/api/kg/entities/<entity_id>/neighborhood?depth=1&limit=50"
|
||||
|
||||
# #52 docgen 异步任务
|
||||
curl -s -X POST $BFF/api/docgen/generate -H 'Content-Type: application/json' \
|
||||
-d '{"description":"根据上传资料生成一篇总结","session_id":"<SID>","library_ids":["<lib_id>"],"template_id":"<template_id>"}'
|
||||
curl -s $BFF/api/docgen/tasks/<task_id>
|
||||
curl -s "$BFF/api/docgen/tasks?session_id=<SID>"
|
||||
|
||||
# #55 资料库
|
||||
curl -s "$BFF/api/docgen/library"
|
||||
curl -s "$BFF/api/docgen/library?as_template=true"
|
||||
|
||||
# #39/#40 提取
|
||||
curl -s "$BFF/api/extraction/jobs"
|
||||
curl -s "$BFF/api/extraction/run-log"
|
||||
```
|
||||
|
||||
## 附录 B:修复目标契约速查(断言按此)
|
||||
|
||||
```
|
||||
POST /api/docgen/generate(请求体同现状+可选 template_id)
|
||||
→ 202 {"ok":true,"task_id":"<uuid>","status":"queued"}
|
||||
GET /api/docgen/tasks/{task_id}
|
||||
→ 200 {"ok":true,"task":{"id","session_id","status":"queued|running|done|error",
|
||||
"progress":[{"section":1,"title":"…","state":"done|running|pending"}],
|
||||
"artifact":{id,title,template_name,template_key,has_html,letterhead,file_name}|null,
|
||||
"error":null|中文可读}}
|
||||
GET /api/docgen/tasks?session_id=<sid> → 列表
|
||||
POST /api/qa/search 超时 → 200 {"mode":"search","answer":"","sources":[],
|
||||
"degraded":true,"reason":"TIMEOUT"};正常空结果 → degraded:false
|
||||
GET /api/kg/entities* 查询超时 → 504 TIMEOUT;实例不可用 → 503 UPSTREAM_DOWN
|
||||
```
|
||||
Reference in New Issue
Block a user