Răsfoiți Sursa

[Docs] 第三轮审计 R3-B 批改动说明(docs/ai-changes)

lizuo 1 zi în urmă
părinte
comite
4fe382072e
2 a modificat fișierele cu 110 adăugiri și 0 ștergeri
  1. 82 0
      docs/ai-changes/20260921-audit-r3-bugs.md
  2. 28 0
      docs/ai-changes/README.md

+ 82 - 0
docs/ai-changes/20260921-audit-r3-bugs.md

@@ -0,0 +1,82 @@
+# 第三轮审计整改 · B 批 bug 组(R3-8 / R3-9)
+
+## ① 头部
+
+| 项 | 值 |
+|---|---|
+| 对照网址 | http://39.97.59.228:8013/hrx/mky-vent-base/compare/master...fix/audit-r3-bugs-20260921 |
+| 依据文档 | `tools/verify/代码审核-第三轮-mky-vent-base-20260921.md`(R3-8、R3-9) |
+| 分支 | `fix/audit-r3-bugs-20260921` |
+| 基线 | `upstream/master` = `4e311cb6`(behind=0) |
+| 日期 | 2026-09-21(Asia/Shanghai) |
+| 状态 | 仅本地提交、未推送,待人工审核 |
+
+## ② 提交清单
+
+- `ce74a288` `[Fix R3-8] 恢复 resetMicroContentWH 的 onTimeout 形参(修 4 调用方失配致遮罩永久卡死)`
+- `c046275a` `[Fix R3-9] 缩小重新生成去重删除范围(服务端时间戳基线,防误删历史同文案提问)`
+- `a54f990e` `[Docs] 第三轮审计 R3-B 批改动说明(docs/ai-changes)`
+
+## ③ 改动面
+
+`git diff --stat`(基线 `4e311cb6` → 本分支):
+
+```
+ src/utils/domUtils.ts                            | 12 +++++++++-
+ .../components/AiAssistantModal.vue               | 26 +++++++++++++++++-----
+ 2 files changed, 32 insertions(+), 6 deletions(-)
+```
+
+另新增本说明目录:`docs/ai-changes/README.md`(本分支基线无该目录;规范要求仓库内补建)+ 本文件。
+
+## ④ 逐项说明
+
+### R3-8【🟠 已采纳功能失效】`resetMicroContentWH` 形参被删但 4 个调用方未同步
+
+- **原来的行为**:团队提交 `7e9858ec` 把签名从 `(domId, callBack?, onTimeout?, maxWaitMs = 60000)` 改为 `(domId, callBack?, maxWaitMs = 60000)` 并删掉了超时分支里的 `onTimeout()` 调用,但 4 个调用方(`needAir.vue`、`ventDoc.vue`、`ventModal.vue`、`ventModal2D.vue`)仍按旧签名传 3 个参数(第 3 个是**错误态回调**)→ 回调落进 `maxWaitMs`,`Date.now() - start >= maxWaitMs`(number 与 function 比较)恒 false → 60s 超时兜底永不触发:子应用加载失败时遮罩永久转圈、`loadFailed` 永不置位(`MicroLoadError` 错误态与重试入口成死代码)、每秒一次 `setTimeout` 轮询永不停止。
+- **现在的行为**:`src/utils/domUtils.ts:174` 签名恢复为 `(domId, callBack?: Function, onTimeout?: Function, maxWaitMs = 60000)`(照我方原始实现 `2eb75d33 [Fix SEC-20260913]`,顺序一致:超时分支先 `onTimeout()` 后 `callBack()`),并新增加固:函数开头 `if (typeof maxWaitMs !== 'number') maxWaitMs = 60000;`。
+- **为什么这么改**:这是**恢复 09-14 人工审核已采纳的"子应用加载超时错误态与重试"功能**,不是新功能开发。调用方本来就是对的,本次只改被回滚的函数本体。
+- **与原来的差别**:相对 `4e311cb6`(master 现状)是"恢复 + 加固"——多了一条类型防御,防止将来再出现"回调被塞进数值参数"这类失配导致兜底静默失效。
+- 4 个调用方**未改**(它们按旧签名传参本来就是对的)。
+
+### R3-9【🟠 数据丢失】"重新生成"的去重会删掉历史上所有同文案用户消息
+
+- **原来的行为**:`removeDuplicateRegenerateUserMessage` 只豁免"第一条"user 消息,凡内容同文案的历史提问("继续"、"总结一下"这类极常见)都会被 `deleteMessage` 静默删除。
+- **现在的行为**:采用**服务端时间戳基线方案**(同一时钟域内比较)。`handleRegenerate` 在发起重发**之前**取一次 `getDetail` 服务端快照,取其中 `created_at` 的最大值 `baselineMs` 作为基线(快照无可解析时间戳则 `NaN`);去重过滤条件为"内容一致 + `idx > 0` + `id != null` + `created_at` 可解析 + **严格大于** `baselineMs`"——只删**本次重发产生的那一条**重复用户消息,历史同文案消息全部保留。`baselineMs` 为 `NaN` 时退化为"只删匹配项中最后一条"(本次重发产生的即最新一条),仍不删全部;`created_at` 缺失/不可解析的消息一律不删。
+- **为什么这么改**:先查了 `src/views/ventAI/manageAssistent/api.ts` 的 `getDetail`(`'/ventAI/api/chat/history/' + session_id`),消息对象含 **`created_at`** 字符串字段(本组件 958 行已用 `dayjs(item.created_at)` 解析展示时间,格式可靠)。基线取自**服务端**快照而非浏览器 `Date.now()`:前后端时钟偏差(矿内网常见分钟级)下,若用浏览器时钟比较,服务器时钟超前时历史消息会被误判为"晚于重发"而**真丢数据**(第一次实现有此缺陷,本次收口修正)。基线与候选消息同属服务端 `created_at` 时钟域,偏差被消除。用**严格大于**(不用 `>=`)是因为基线那条本身可能就是上一次的同文案提问,且 `created_at` 若为秒级精度,同秒的新消息宁可**漏删**也不能误删。
+- **与原来的差别**:删除范围从"所有同文案匹配项(除第一条)"收窄为"仅本次重发新产生的那条(或退化方案的仅最后一条)";`created_at` 缺失或无法解析的消息**不删**(宁留重复、不误删历史)。
+- 关键业务取舍:**只动"重新生成"这一条去重逻辑**,不改 `handleEditResend`、不改后端、不改其它重发路径。
+- 调用点同步:`handleRegenerate` 里 `removeDuplicateRegenerateUserMessage(userInput)` → `removeDuplicateRegenerateUserMessage(userInput, baselineMs)`(全仓仅这一个调用点,已 grep 确认)。
+
+## ⑤ 验收证据
+
+- **逻辑走查(R3-8)**:grep 确认 4 个调用点均传 3 个参数(`domId`、成功回调、错误态回调),与新签名 `(domId, callBack?, onTimeout?, maxWaitMs?)` 逐位对齐;超时分支执行顺序与原始实现 `2eb75d33` 一致(`onTimeout()` 在前、`callBack()` 在后)。
+- **逻辑走查(R3-9)**:模拟"历史上存在 2 条同文案提问 + 本次重发新增 1 条"场景,基线为重发前快照最大 `created_at`,过滤条件只放行严格大于基线的那条(同秒同值不会被误删);快照无时间戳时走退化分支只删最后一条匹配;`created_at` 缺失/非法(`dayjs` 解析出 Invalid Date → `NaN`)时拦截,不删除。
+- **未验证项**:浏览器实测(子应用加载失败时遮罩转错误态、重试入口可点;"重新生成"后历史消息不丢)**待父方在 192.168.1.88 上部署后验收**;本机未跑构建(按任务要求)。
+
+## ⑥ 静态检查
+
+软链依赖 `node_modules -> /root/VentAnaly60/mky-vent-base/node_modules`(只读使用)。
+
+1. `src/utils/domUtils.ts` —— `@babel/parser@7.29.7`(.pnpm 嵌套路径,`@babel/parser` 未提升,任务书给的一行命令在本环境报 MODULE_NOT_FOUND,故用嵌套真实路径,解析器版本一致):
+   ```
+   OK src/utils/domUtils.ts
+   ```
+2. `AiAssistantModal.vue` —— `@vue/compiler-sfc` 的 `parse` + `compileScript`(script 块语法+类型检查通过):
+   ```
+   OK src/views/ventAI/manageAssistent/components/AiAssistantModal.vue
+   ```
+3. 未跑 `vite build` / `pnpm install`(任务书明令禁止);无既有 lint 报错基线对比,本次两个文件解析均通过。
+
+关键 hunk 见 `git diff`(③中 stat,④中说明)。
+
+## ⑦ 已知取舍
+
+- **R3-9 方案局限**:① `created_at` 若为**秒级精度**,重发新消息与基线同秒时 `>` 不成立会**漏删**一条重复(宁留重复、不误删历史,属有意取舍);② 退化分支(服务端时间戳不可得时"只删最后一条匹配")依赖消息顺序,后端若提供可靠时间戳建议切回主方案。
+- R3-8 的浏览器实测、遮罩/错误态/重试验收:待父方部署到 88 后验证。
+- 本轮**只做 R3-8、R3-9**,未做顺手重构;第三轮审计的其余条目不在本分支。
+
+## ⑧ 交付状态
+
+- 仅本地提交,**未推送、未部署**;推送与合并由父方/用户决定。
+- 基线:`upstream/master` = `4e311cb6`(behind=0,开工时已确认)。

+ 28 - 0
docs/ai-changes/README.md

@@ -0,0 +1,28 @@
+# AI 改动说明(docs/ai-changes)
+
+本目录存放每一轮 AI 辅助改动的交付说明,供人工审核对照。
+
+## 命名
+
+```
+<YYYYMMDD>-<简短主题>.md
+```
+
+- 日期 = 改动/交付当天(Asia/Shanghai);
+- 主题 = ASCII 小写短横线词;
+- 同一天同一分支追加说明时更新同一个文件。
+
+## 必备章节
+
+1. **头部**:对照网址、依据文档、分支、基线、日期、状态;
+2. **提交清单**;
+3. **改动面**(涉及文件及各自改了什么,数字取自命令输出);
+4. **逐项说明**:原行为 / 现行为 / 为什么 / 与原来的差别(关键业务取舍必须写清);
+5. **验收证据**;
+6. **静态检查**(命令与结果,明确哪些是既有问题);
+7. **已知取舍**;
+8. **交付状态与上游同步**。
+
+## 交付方式
+
+只以分支形式推送,不直接合并 master;人工审核后由人工合并。