[ISSUE-0033] 第四轮 agent 找到 ISSUE-0031 第 4 兄弟¶
第四轮 agent convergence test 仍失败:又找到 1 个 P1 + 2 个 dead listener + 1 个工具盲区。
Bug J (P1):ISSUE-0031 三胞胎的第 4 兄弟¶
位置:scrape-watchdog.ts:207-211 alarm-create-fail 兜底分支
// v0.10.47 修了 cooldown=0 分支 + onWatchdogResume(2/3 路径)
// 漏了 alarm-create-fail 兜底
} catch (e) {
pumpTasks().catch(() => {});
manageQueue();
// ❌ 缺 pumpAllSchedulers
}
与 ISSUE-0028 / ISSUE-0031 是同一家族,但在同一个 90 行函数内:
| 分支 | v0.10.47 状态 | v0.10.49 修 |
|---|---|---|
cooldown<=0 |
✓ 已补 pumpAllSchedulers | ↓ helper |
alarm-create-fail catch |
❌ 漏 | ✅ helper |
onWatchdogResume(alarm 触发) |
✓ 已补 | ↓ helper |
修法:抽 watchdogResumePump() helper¶
function watchdogResumePump(): void {
pumpTasks().catch(() => {});
pumpAllSchedulers().catch(() => {});
manageQueue();
}
3 个分支都改成调一行 watchdogResumePump()。视觉上无法漏看第 N 个分支。
Bug K:'clear-search-data' 孤儿 listener¶
位置:content-search/index.tsx:144-157
唯一发送方在 page-results/index.tsx:105 整段已注释。listener 永不触发。
scan:protocol v0.10.48 没抓到 — 因为它是 browser.runtime.onMessage + if(type==='x') router-dispatch 模式,工具故意不扫(router-dispatch 实测 22/23 FP)。
修法:删整段 useEffect。
Bug L:'search-api-response' 孤儿 listener(工具自身盲区)¶
位置:content-search/index.tsx:74
全仓 0 websiteMessager.sendMessage('search-api-response', ...)。injected.ts 只发 'search-api-url'。
讽刺:这是 webext-bridge onMessage 模式,新 scan:protocol 工具理论上应抓到。
但 v0.10.48 工具用 (?:^|[^a-zA-Z_.])onMessage\( 排除 method call —— 因为
原来想排除 websiteMessager.onMessage(...) 的发送方在 injected 层我们扫不到。
工具自身盲区暴露:
# v0.10.49 修
LISTENER_PATTERNS = [
# 主:webext-bridge 顶层
(r"(?:^|[^a-zA-Z_.])onMessage\(\s*['\"]([^'\"]+)['\"]", "webext-bridge"),
# 🆕 自定义 messager:限定 messager 后缀
(r"\w*[Mm]essager\.onMessage\(\s*['\"]([^'\"]+)['\"]", "custom-messager"),
]
修法:删整段 listener + pushData 死函数(删 listener 后 0 调用)+ parseSearchData import。
元-观察(agent 提出)¶
四轮 P0/P1 共同模式:
| 轮 | bug | 共同特征 |
|---|---|---|
| 1 (v0.10.44) | 拦截恢复漏 pumpScheduler(ISSUE-0028) | resume 路径漏 pump |
| 3 (v0.10.47) | watchdog onWatchdogResume 漏 pump(ISSUE-0031) | resume 路径漏 pump |
| 4 (v0.10.49) | watchdog alarm-fail 漏 pump(ISSUE-0033 本 issue) | resume 路径漏 pump |
共同 100%:resume-after-failure 路径漏调 pump 链。
深层根因:
1. 修复者只 grep 触发的具体函数名,不 grep 同函数内多个分支
2. try-catch 视觉切割导致认知盲区
3. 已抽 helper(pumpAllSchedulers)但作者复用到"主路径",catch 兜底分支被遗忘
4. scan 工具偏"数据"而非"控制流"
agent 建议的下一步(todo):
- 写 scan-pump-coverage.py 检测 nukeAllSchedulerState / forceCloseSharedWindow 调用后控制流是否经过 pumpAllSchedulers(控制流分析需 AST)
改动文件¶
| 文件 | 改了什么 |
|---|---|
src/utils/scrape-watchdog.ts |
+ watchdogResumePump helper,3 个分支统一调用 |
src/sections/content-search/index.tsx |
删 'clear-search-data' listener + 'search-api-response' listener + 死 pushData + 死 import |
scripts/scan-protocol-orphan.py |
+ \w*[Mm]essager\.onMessage 自定义 messager 扫描(修工具盲区) |
.protocol-orphan-baseline.json |
19 → 18(search-api-response 删了 1) |
package.json |
0.10.48 → 0.10.49 |
验证¶
- ✅
pnpm compile0 错 - ✅
pnpm build7.32s - ✅
pnpm scan:mv3 --diff0 新增 - ✅
pnpm scan:protocol现在 0 dead + 18 lost(更新基线后)
复盘¶
第四轮 agent 元-观察精彩:
修复者只 grep 触发的具体函数名,不 grep 同函数内多个分支 try-catch 视觉切割导致认知盲区
这正是 v0.10.47 我 ISSUE-0031 修复的现场重演 —— 我看了 onWatchdogResume + cooldown=0 但没看 cooldown>0 的 try-catch 内部 catch 分支。视觉上 if/else + try/catch 嵌套有 3 个分支,我只看了 2 个。
未来准则:修任何"在某分支补缺失调用"的 bug 时,必须看同一函数所有分支,最好抽 helper。
累计 4 轮 agent 共同发现¶
轮 1: ISSUE-0028 Bug A (P0) — 拦截恢复路径
轮 2: ISSUE-0029 Bug E (中-高) — 浪费索引
ISSUE-0029 Bug S4 (中) — listener cleanup
轮 3: ISSUE-0031 Bug I (P0 镜像) — watchdog 主路径
ISSUE-0031 Bug F1 (中) — has-new-data 孤儿
ISSUE-0031 Bug H (中-低) — 正则姊妹漂移
轮 4: ISSUE-0033 Bug J (P1) — watchdog 第 4 兄弟
ISSUE-0033 Bug K (中) — clear-search-data 孤儿
ISSUE-0033 Bug L (中) — search-api-response 孤儿(工具盲区)
4 轮独立 agent 共 9 个真发现,其中 4 个 P0/P1 全是"resume 路径漏 pump"同源 bug 在不同位置展开。