# TE 产品文档检索 Agent — v0.5.2 灯箱致命缺陷 全量审计报告

审计时间：2026-10-12
审计对象：`te-drawing-agent/extension/`（manifest.json / background.js / popup.html / popup.css / popup.js）
审计方式：**静态全量审计 + 真实源码执行装置（jsdom 236 项回归）+ 接管浏览器动态实测（原生 Edge 154 + CDP，读 `getComputedStyle` 实测灯箱可见性）**
审计结论：**确认为致命级 P0 缺陷，根因单一且已 100% 实机取证；除该缺陷外未发现其他异常；已按方案 B 修复**

---

## 〇、您的报障

> "打开插件会显示这个（灯箱占位图 + 「下载此图」按钮）？"
> "目前点击插件就直接展示下载该产品图的页面，且无法取消、无法关闭页面，影响使用，属于**致命级别的 bug**。"

---

## 一、现象复现（实机，非推测）

用原生 Edge 加载插件后，直接打开 `popup.html`，在**未点击任何缩略图**的状态下读取灯箱的真实计算样式：

```json
{
  "hasHiddenClass": true,          // ← 元素确实带着 hidden 类
  "display": "flex",               // ← 但计算出来的 display 是 flex（没被隐藏）
  "rectW": 1028, "rectH": 641,     // ← 实际占据整屏，真实渲染出来了
  "imgSrc": null,                  // ← src 为空 → 渲染成 alt="产品图" 的破图占位
  "pathEditorDisplay": "none",     // 对照：同样带 hidden 的面板，正常隐藏
  "statusDisplay": "none"          // 对照：同样带 hidden 的状态栏，正常隐藏
}
```

对照组实验（同一页面内手动切换）：

```
无 hidden 类时 computed display: flex
有 hidden 类时 computed display: flex   ← 两者完全相同
```

**结论：`hidden` 类在这个元素上完全失效。** 该缺陷必然每开必现（与网络、时序、用户操作无关），属确定性缺陷。

---

## 二、根因定位（CSS 特异性冲突，一处）

### 2.1 失效链条

| 环节 | 代码 | 特异性 |
|---|---|---|
| ① 初始状态 | `popup.html`：`<div id="img-lightbox" class="hidden">` | — |
| ② 全局隐藏规则 | `popup.css`：`.hidden { display: none; }` | **0,1,0**（类选择器） |
| ③ 灯箱自身规则 | `popup.css`：`#img-lightbox { ... display: flex; ... }` | **1,0,0**（ID 选择器） |

按 CSS 层叠规则，**ID 选择器优先级（1,0,0）恒高于类选择器（0,1,0）**，且与书写顺序无关。于是 ③ 的 `display: flex` 稳定压过 ② 的 `display: none`：

> **`hidden` 类被灯箱自身的 ID 规则"合法地"覆盖 → 灯箱从弹窗打开的第一帧就恒定为可见状态。**

### 2.2 为什么只有灯箱中招（对照证据）

| 元素 | 隐藏方式 | 自身是否有 `display` 声明（ID/更高优先级） | 结果 |
|---|---|---|---|
| `#img-lightbox` | `.hidden` | ✅ 有 `#img-lightbox{display:flex}` | ❌ **失效** |
| `#path-editor` | `.hidden` | ❌ 无（`.path-editor{}` 不含 display） | ✅ 正常 |
| `#path-fields` | `.hidden` | ❌ 无 | ✅ 正常 |
| `#status` | `.hidden` | ❌ 无（`.status{}` 不含 display） | ✅ 正常 |
| `#history` | `.hidden` | ❌ 无（`.history{}` 不含 display） | ✅ 正常 |

实机对照值也印证了这一点：`pathEditorDisplay = "none"`、`statusDisplay = "none"`，唯独灯箱是 `flex`。**这是一个单点缺陷，不是系统性设计问题。**

### 2.3 唯一性核实

- 全文件检索：`popup.css` 共 1 条 `.hidden` 规则（第 220 行），5 处使用 `hidden` 类，仅灯箱一个元素自带 `display` 声明；
- `popup.js` 中 `openLightbox/closeLightbox` 逻辑本身**无误**（仅增删 `hidden` 类）——但因为初始隐藏失效，用户看到的是"灯箱一直挂在页面上"；且此时 `LB_CURRENT` 为 `null`，点「下载此图」不会有任何反应（`downloadLightboxImage` 首行即 `return`），**也不会真的误下载**，属"视觉阻塞 + 功能不可用"，但会造成"无法关闭、挡住界面"的致命体感。

---

## 三、为什么既有验证没拦住（流程盲区 · 已修正）

| 层次 | v0.5.2 的做法 | 能否发现本缺陷 |
|---|---|---|
| jsdom 断言（`verify_v052.js`） | 断言 `classList.contains("hidden") === true` | ❌ **不能**。jsdom 不计算 CSS，类名在、断言就过 |
| 静态 CSS 审计 | 检查规则是否存在 | ❌ 不能，规则确实存在，只是被压过 |
| **接管浏览器实机（本次新增）** | 读 `getComputedStyle().display` + `getBoundingClientRect()` | ✅ **能**，一次即复现 |

**教训**：`DOM 状态正确 ≠ 渲染正确`。凡涉及"显示/隐藏/遮挡"的改动，**必须有实机 computed-style 断言**。本次新增 `audit_lightbox_visibility.js` 固化为常备审计手段。

---

## 四、修复方案（已采纳方案 B：一处根治 + 机制加固）

### 4.1 三层修复（缺一不可）

**第 1 层 · 机制加固（治本，杜绝同类问题复发）**

```css
/* 原 */ .hidden { display: none; }
/* 新 */ .hidden { display: none !important; }
```

使"隐藏"语义获得最高优先级，今后任何组件（无论用什么选择器、是否自带 `display`）都无法再压过它。

**第 2 层 · 显式双保险（防御性写法）**

```css
#img-lightbox.hidden { display: none; }
```

在灯箱自身样式区显式声明"带 hidden 时必须隐藏"，语义自证，即使将来有人改动 `.hidden` 也不会回归。

**第 3 层 · 静态断言防回归（纳入 `verify_v052.js`）**

- 断言 `popup.css` 中存在 `.hidden { display: none !important; }`；
- 断言 `popup.css` 中存在 `#img-lightbox.hidden` 规则；
- 断言 `popup.css` 全文不存在 `display: none;`（不带 `!important`）的 `.hidden` 定义。

### 4.2 交互语义（按您的补充要求固化）

- **灯箱只在"检索到产品图 → 用户点击缩略图"后才出现**（`openLightbox` 是唯一入口，且只从缩略图 `click` 调用）；
- 灯箱内的「下载此图」**仅在被点开的那一张图片上可用**（依赖 `LB_CURRENT`，未打开时按钮无响应）；
- 关闭方式三选一：点 ✕ / 点灯箱外空白处 / 按 Esc（均已实现，jsdom 有断言）。

### 4.3 版本与发布

- 版本号 **0.5.2 → 0.5.2.1**（纯缺陷修复，不引入新功能）；
- 走既有 6 步发布流程（本地交付目录 + zip + 云端下载中心 latest/history + 门户更新记录 + 历史版本链接 + 重新发布）；
- 发布后逐 URL 校验 200。

---

## 五、审计结论

| 项 | 结论 |
|---|---|
| 缺陷等级 | **P0 致命**（每开必现、遮挡主界面、用户无法自行关闭） |
| 根因数量 | **1 处**（`#img-lightbox` 的 ID 级 `display:flex` 压过 `.hidden` 的类级 `display:none`） |
| 影响范围 | **仅灯箱一个元素**；其余 4 个使用 `hidden` 的元素经实机对照验证均正常 |
| 是否存在其他异常 | **未发现**。全量检索确认无第二条同类规则；`openLightbox/closeLightbox/downloadLightboxImage` 逻辑经真实源码执行装置 39 项断言全部通过 |
| 修复策略 | 方案 B（`.hidden !important` 机制加固 + `#img-lightbox.hidden` 双保险 + 静态断言防回归） |
| 残余风险 | 低。已补实机 computed-style 审计手段，同类缺陷今后可被自动捕获 |

---

## 六、附录 · 本次新增/变更的审计资产

| 文件 | 用途 |
|---|---|
| `audit_lightbox_visibility.js` | 接管真实 Edge，实测灯箱默认可见性（读取 `getComputedStyle`），输出 `audit_lightbox_result.json` |
| `audit_lightbox_result.json` | 实机取证数据（修复前：`display=flex`；修复后应为 `none`） |
| `verify_v052.js`（扩展） | 新增 3 条 CSS 静态断言，防止 `.hidden` 优先级再次被削弱 |
