跳转至

[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 仍:

.catch(() => {});  // ❌ 静默吞错

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:18webext-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 退化空 + 误导提示

// v0.10.58 之前 ❌
} catch (e) {
  locations = [];  // → locationEntries=0 → 报"未能创建任务(请检查是否选了具体州/城市)"
}

用户明明选了整国,被告知"没选" — ISSUE-0037 同款语义混淆。

:catch 内 notice.error('加载...地区列表失败:' + e + ',请重试') + return。

A4 (中):task-detail-dialog 双轴 overflow(ISSUE-0038 同款)

// v0.10.58 之前 ❌
maxHeight: '50vh',
overflow: 'auto',  // ❌ 同时允许 X/Y → 横向溢出吃滚轮

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

invalidate(iso2).then(() => preloadAll(...))  // ❌ 漏 catch → unhandled rejection

:补 .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 compile 0 错
  • pnpm build 9.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 的另一种表现:修的人聚焦"看到的那一处",忘了横向扫所有同源。