# 486 桌宠（2D Electron 版）代码审查清单

来源：子代理审查 /root/refs/486-desktop-pet（pet.js 1109 行 + main.js 211 行 + preload.js + pet.html）
日期：2026-10-01　模型：deepseek-v4-flash-vision-exp（5 次调用）

## 一、问题清单（按严重度）

1. **窗口几何只在启动时算一次**（main.js:129-150, 198）
   无任何 `screen.on('display-metrics-changed'/'display-added'/'display-removed')` 处理。
   拔外接屏 / 改分辨率 / 改 DPI 后窗口停在旧 workArea，**且无托盘 → 宠物可能永远找不回来，只能任务管理器杀进程**。
   修：监听这三个事件 → `win.setBounds(newArea)` + 通知渲染端 re-clamp；工作区坐标唯一来源收敛到主进程。

2. **初始化失败 / 渲染崩溃无恢复路径**（pet.js:1044-1108, main.js:128-170）
   5 张图全加载完才注册保命监听（contextmenu/onScaleChanged），任一 PNG 失败只剩一行"加载失败"；主进程无 `render-process-gone`、无 Tray。
   修：① 保命监听挪到图片加载之前 ② 加 Tray（大小/退出）当逃生口 ③ `render-process-gone` → reload 一次，再崩 quit ④ loadImage 加超时 + 逐张降级。

3. **朝左时点击命中左右相反**（pet.js:481-490）
   `hitPet` 直接拿 `clientX - rect.left` 查源图，但显示是 `transform: scaleX(-1)` 镜像的 → face=-1 时命中区域与看到**完全相反**。
   修：`const ux = state.face < 0 ? rect.width - localX : localX;`

4. **冷启动宠物先在左上角闪一下再跳到左下角**（pet.html:13 + pet.css + pet.js:1076-1083）
   init 完成前宠物已可见且坐标 (0,0)。每次开机都看得见。
   修：`#pet` 先 `visibility:hidden`，init 后加 `.ready`；或把起始坐标直接写成左下角。

5. **鼠标热路径重活**（pet.js:924 → 469-479）
   每个 mousemove 都 `getContext + getImageData`（每次新建对象），命中后还叠 2×clearTimeout + 2×setTimeout + Math.random。全屏窗口下 60-144 次/秒。
   修：把 alpha 抽成 Uint8Array 掩码；`resetActivityChain` 用 lastInteractionAt 做 400ms 节流。

6. **`displayMode:'pixel'` 是半成品**（pet.js:38-44, 1025-1027）
   命中判定会切到 pixel 图，但 pet.css 里没有任何 -pixel 规则 → 画面永远用 fine 图。开了等于没开。
   修：补 pixel 显示层，或把这个开关连同配置一并删掉。

7. **死代码 + 死帧占图 17%**（pet.js:492-494, 623, 698, 447 + 164-169, 187-193, 359, 363）
   showBubble 已空函数但仍传参、startPout 无调用方（poutChance 静默无效）、turnAway/lookMouse 帧无目标。占 transition 图 22 格 ≈ 1.4MP、解码 ~5.6MiB。
   修：接通或删净（含 config.json 的 poutChance、CSS 选择器、图行）。

8. **拖拽后两条活动链都不再启动**（pet.js:901-906 + 519-532, 586-587）
   拖拽期间 randomTimer 回调 return 且不重排、sleepTimer 被挡 → **拽十几秒松手后，如果鼠标不动，宠物永远只 idle/微笑，不走路不睡**。
   修：`endDrag()` 末尾补 `resetActivityChain()`；守卫分支里补重排。

## 二、优化清单

1. **alpha 掩码按需构建**（pet.js:1050-1073）：5 个 canvas ~10MiB → ~2.3MiB；删掉每帧 getImageData。
2. **两阶段加载**（pet.js:1044-1048）：先 main（可加 look）→ 立即显示；walk/interact/transition 丢 requestIdleCallback。首帧记忆 ~68MiB↓。
3. **降采样**：单元格 364×360 → 256（或 128/384 分档）。transition 解码 67→33/8 MiB，磁盘 12.4MB → ~4/1.5MB。
4. **合图**：5 张 → 1~2 张（须先降采样，≤8192px/边）；CSS 134 条规则 → 生成；每帧只改 background-position。
5. **窗口缩到宠物大小**（架构级，风险最高）：全屏透明窗合成面积降 ~1/120；先做 rAF 合帧过渡版。
6. **削样式写放大**：setFrame 用 classList.replace；CSS 变量只在变化时写。
7. **默认关逐帧日志**：pet.js:331 + main.js:154-159 挂到 MRWU_PET_DEBUG 后面。

## 三、已做过但没落地的

- transition 图仓库里还是原图（2912×5760，解码 64 MiB）。**已经缩好的 50% 版**（1456×2880，每格 182×180，网格不变、CSS 零改动）在取件页：`spritesheet-transition.png`，覆盖进 assets/ 即可。
