[ISSUE-0040] 第 6 轮 agent 发现 6 个真 bug —「补丁不彻底」家族¶
用户截图:"我已验证完,继续" 按钮报错
[webext-bridge] No handler registered in 'background',验证通过也提示拦截。 第 6 轮独立 agent 在用户截图同时找出 6 处漏修 — 全是前序 ISSUE 修了触发点没扫所有同模式。
6 个 bug 全部修复¶
A1 (高):updateTask/removeTask 同 ISSUE-0036 漏修¶
src/utils/task-store.ts v0.10.54 修了 addTask 但 update/remove 仍:
controlTask 所有路径(pause/resume/stop/delete/rename)经过 update/remove。storage write 失败 → caller 仍 success → toast 成功但任务未变 → UI 状态错位。
修:照 addTask 模板分离 next + writeChain。
A2 (高):interception-banner 用 webext-bridge 但 background 用原生¶
src/sections/layout/interception-banner.tsx:18 用 webext-bridge/popup 的 sendMessage,但 background runtime.onMessage.addListener 是 chrome 原生 — 协议完全不通。
→ 用户点「我已验证完」/「打开验证页」直接报错:
[webext-bridge] No handler registered in 'background' to accept messages with id 'resume-all-intercepted'
与 ISSUE-0035 同精神(API 混用),但用户从没遇到拦截才一直没暴露。
修:改用 browser.runtime.sendMessage({ type: 'xxx' }) 与项目其他 main/popup 一致。
A3 (中):task-create-dialog 整国选择 catch 退化空 + 误导提示¶
用户明明选了整国,被告知"没选" — ISSUE-0037 同款语义混淆。
修:catch 内 notice.error('加载...地区列表失败:' + e + ',请重试') + return。
A4 (中):task-detail-dialog 双轴 overflow(ISSUE-0038 同款)¶
修:overflowX: 'hidden', overflowY: 'auto'。
A5 (中):popup signalToMain 没 try/catch¶
src/sections/popup/index.tsx:61:
async function signalToMain(action) {
await storage.setItem('local:popup-action', full); // ❌ 失败抛错,停在 openWindow 之前
}
storage 写失败 → reject 进 unhandledrejection + 主面板不开。
修:try/catch + console.warn + 不 re-throw(让 caller openWindow 保底)。
A6 (低):location-picker retryStat 漏 catch¶
修:补 .catch((e) => console.warn(...)).
A7 (高):task-create-dialog website 分支漏检查 resp(ISSUE-0036 漏修同款)¶
v0.10.54 修了 maps 分支,website 分支被漏:
// v0.10.58 之前 ❌
await browser.runtime.sendMessage({ type: 'create-task', task: { type: 'website', ... } });
notice.success('任务已创建'); // 不论 resp.success 都 toast 成功
修:同 maps 分支套路检查 resp2.success。
元-洞察:「补丁不彻底」家族¶
| 原 ISSUE | 修了 | 漏修(第 6 轮 agent 找到) |
|---|---|---|
| 0036 (writeChain 吞错) | addTask | updateTask / removeTask (A1) |
| 0036 (sendMessage 不查 resp) | maps 分支 | website 分支 (A7) |
| 0037 (catch 吞错 → 误显示) | location-picker | task-create catch=>locations=[] (A3) |
| 0038 (overflow 双轴) | location-picker city list | task-detail-dialog list (A4) |
| 0035 (API 混用) | local-data-view 按钮 | interception-banner 两按钮 (A2) |
5 个原 ISSUE,每个都漏了至少 1 处同款。Agent 总结:
修复经常只修触发点,没扫所有同模式。建议下一轮 focus 把每个修过的 bug 在仓内做「全字典扫描」(同 utils 的所有 export 都修了吗 / 同 type 的所有 caller 都检查了吗)。
防再犯:audit_grep 扩 + scan-error-handling todo¶
audit_grep:
- pattern: "sendMessage\\([^)]*\\)\\s*\\.\\s*then"
description: 用户主动操作的 sendMessage 必须 .then 检查 resp.success
scan-error-handling.py(todo,未来做):自动扫所有 .catch(() => {}) 并区分 user-action vs fire-and-forget。
改动文件¶
| 文件 | 改了什么 |
|---|---|
src/utils/task-store.ts |
updateTask/removeTask 错误传播(A1) |
src/sections/layout/interception-banner.tsx |
webext-bridge → chrome 原生 sendMessage + import 改(A2) |
src/entrypoints/background/index.ts |
resume-all/open-verify 加 try-catch return success/error |
src/sections/task/task-create-dialog.tsx |
整国 catch 友好提示(A3)+ website 分支检查 resp(A7) |
src/sections/task/task-detail-dialog.tsx |
overflow 分轴(A4) |
src/sections/popup/index.tsx |
signalToMain try/catch(A5) |
src/components/locations-select/location-picker-dialog.tsx |
retryStat 补 catch(A6) |
package.json |
0.10.57 → 0.10.58 |
验证¶
- ✅
pnpm compile0 错 - ✅
pnpm build9.6s - 📋 实测:触发拦截 → 完成验证 → 点「我已验证完」→ 应正常恢复(不再报 webext-bridge 错)
沉淀:修 bug 必走「全字典扫描」¶
每次修 ISSUE-XXXX 后必做:
1. grep 同文件 export 的姊妹函数(addX → updateX/removeX)
2. grep 同 message type 的所有 sendMessage caller
3. grep 同 catch 反模式(.catch(() => {}))的全仓使用
4. grep 同 overflow / 布局模式的其他 Dialog 容器
第 6 轮 agent 用一次扫描验证了 5 个原 ISSUE 全有漏修。这是 anchor bias 的另一种表现:修的人聚焦"看到的那一处",忘了横向扫所有同源。