跳转至

Rule — 修 bug 必走全字典扫描

触发场景:每次修完一个 ISSUE,在写 dev log 之前必做的横向扫描。

为什么需要这个规则

v0.10.58 ISSUE-0040 的关键发现:

5 个原 ISSUE(0034~0038),每个都漏修至少 1 处同款:
  0036 修了 addTask → 漏 updateTask/removeTask
  0036 修了 maps 分支 → 漏 website 分支
  0037 修了 location-picker → 漏 task-create-dialog 同 catch
  0038 修了 city list overflow → 漏 task-detail-dialog overflow
  0035 修了 local-data-view 按钮 → 漏 interception-banner 两按钮

5 个 → 6+ 处漏修。100% 都是「修触发点,没扫所有同源」。

根本原因:作者的 anchor bias 不止"看自己写的代码",还体现在"只修看到的那一处"。

4 步全字典扫描(必做)

Step 1: grep 同文件 export 的姊妹函数

# 例:修了 addTask 的 catch 模式
grep -n "^export.*function\|export const" src/utils/task-store.ts
# 姊妹:updateTask / removeTask 是否同款?

触发点:函数命名遵循 CRUD(add/update/remove/clear)/ 操作(do/run/handle)等系列时。

Step 2: grep 同 message type 的所有 sendMessage caller

# 例:修了 create-task handler 加 try-catch
grep -rn "'create-task'" src/sections/ src/components/
# 所有 caller 是否都检查 resp.success?

触发点:改 background message handler 时。

Step 3: grep 同 catch 反模式的全仓使用

# 例:修了 .catch(() => setX([])) ISSUE-0037 模式
grep -rnE "\.catch\(\(\) => set\w+\(\[\]\)\)" src/

# 例:修了 .catch(() => {}) silent 模式
grep -rn "\.catch(() => {})" src/sections/ src/utils/

触发点:改任何 try-catch 或 .catch 时。

Step 4: grep 同布局 / overflow / 状态机模式

# 例:修了 Dialog 内 list overflow:'auto' → 改 overflowX:'hidden'+overflowY:'auto'
grep -rn "overflow: 'auto'" src/sections/ src/components/

# 例:修了某个 alarm 后 resume 路径漏 pumpAllSchedulers
grep -rn "nukeAllSchedulerState\|forceResetLocks" src/

触发点:改 UI 布局 / 调度 / 状态机时。

自动化(v0.10.59 起)

新加的 pnpm scan:error-handling 工具扫 3 类反模式:

pnpm scan:error-handling                  # 完整扫
pnpm scan:error-handling -- --save-baseline
pnpm scan:error-handling -- --diff        # pre-commit 用

类别: - silent_catch: .catch(() => {}) - catch_to_empty: .catch(() => setX([])) (ISSUE-0037 模式) - send_without_check: sendMessage(...) 后未查 resp.success

启发式分级:附近含 onClick / onSubmit / handle 等关键词 → 🔴 user-action(必修),否则 → 🟡 fire-and-forget(合理)。

类似还有: - pnpm scan:mv3 — MV3 持久化陷阱 - pnpm scan:react — React lifecycle - pnpm scan:protocol — 消息协议失配 - pnpm scan:pump-coverage — 调度恢复路径 - pnpm scan:issue-coverage — ISSUE audit_grep 反查 - pnpm scan:error-handling — 错误传播(本规则配套)

工作流

发现 bug → 修触发点 → ⚠️ 暂停!
                      4 步全字典扫描
                  发现姊妹同款?
                    ↓ 是          ↓ 否
                  一次性修        写 dev log
              更新本次 commit 覆盖全部

反模式

❌ "我只看到这一处,修完就行" — 90% 项目里有同款姊妹 ❌ "下次再扫" — 下次很可能就是用户报 bug 才被迫看 ❌ "scan 工具会扫" — pre-commit 只看 diff,已有的漏修不会再触发

audit_grep 配套(在 ISSUE 文档里)

修完 ISSUE 后在 frontmatter 加 audit_grep,让 pnpm scan:issue-coverage 全仓反查:

audit_grep:
  - pattern: "正则字符串"
    description: "为什么这个 pattern 必须 0 命中(修完后预期)"

未来有人新引入旧模式时,pre-commit hook 自动拦截。

历史价值

沉淀 防住的 bug 类别
scan:mv3 MV3 持久化陷阱(setTimeout/let)
scan:react useEffect cleanup
scan:protocol onMessage/sendMessage 失配
scan:pump-coverage 调度恢复路径
scan:issue-coverage ISSUE 改动反查
本规则 + scan:error-handling 补丁不彻底家族

每层规则 + 工具 = 把"修过一次的 bug 模式"自动化拦截下次重犯。

相关

  • [[0036-create-task-toast-ok-but-not-listed|0036-创建任务-toast成功但任务未入列表]] — 错误传播第 1 个被发现
  • [[0040-round6-agent-6-bugs-incomplete-patch|0040-第6轮agent发现6个真bug-补丁不彻底家族]] — 第 6 轮 agent 元洞察来源
  • 独立agent审查 — 跨视角防 anchor bias
  • MV3持久化陷阱清单 — 类似的"模式自查"清单