2.5 AI 协作调试法——从报错到修复的可复制方法论

2 阅读17分钟

模块二:AI 协作方法论 | 第05讲:AI 协作调试法——从报错到修复的可复制方法论

项目:VibeNote 智能笔记 · Next.js / React / TypeScript / Tailwind
本讲目标:用工序替代运气;用结构化信息替代复制整页日志


一、开场:无效调试循环,本质是信息不对称

reference/practice/vibe-coding-methodology.md 把「按了葫芦起了瓢」写得很具体:模型在错误假设上反复打补丁,代码越改越乱;你如果只是验证者,模型会在无效循环里消耗算力与你的耐心。课程原稿 课程内容/2.5 从报错到修复:一套可复制的AI协作调试法.md 只有骨架;本讲补齐:三连跪规则、结构化报错、读栈方法、隔离工具箱、根因声明、验证分层、何时重置会话、VibeNote 场景清单

我想先把话说白:调试不是模型「再试一次」的抽奖游戏。它是信息收集与假设检验。你把信息组织得越像工单,模型越像合格协作方;你把信息组织得像情绪发泄,模型就只能陪你掷骰子。

flowchart TD
  R[Reproduce 复现] --> I[Isolate 隔离]
  I --> D[Diagnose 诊断根因]
  D --> F[Fix 修复]
  F --> V[Verify 验证]
  V -->|失败| R
flowchart LR
  A[尝试1] --> B[尝试2]
  B --> C[尝试3]
  C --> S[停止盲试]
  S --> H[人类定位根因]
  H --> F2[基于根因修复]

二、三次尝试规则(3-strikes):给协作装刹车

同一问题连续三次修复仍失败,停止让模型继续「盲试」。 参考文章把它当作危险信号:说明模型可能困在错误框架里。此时标准动作不是「换模型」,而是:

  1. 你亲自读栈与相关代码,写出「目前最可信的失败链路」
  2. 用最小复现把范围砍到最小面
  3. 写「根因一句话」或「未定位但已排除清单」
  4. 再开新会话,携带以上结构化信息让模型重生补丁

这条规则的价值是保护你的仓库:补丁堆叠是最贵的技术债之一


三、结构化报错:最低八字段(缺一补一)

  1. 现象:用户可见 / API 返回 / 监控指标
  2. 复现步骤:从冷启动到失败的可重复路径
  3. 期望 vs 实际:对照写,别混写
  4. 环境:分支、commit、Node、OS、是否 Docker
  5. 错误栈:保留顶部与 Caused by,删中间重复帧
  6. 相关代码:只贴失败路径,不要整文件
  7. 已排除假设:防止模型回到死胡同
  8. 根因一句话:未知就写「尚未定位」

你可以把这段直接复制成 issue 模板。字段齐全的意义是:把调试从聊天变成数据库查询——缺列的查询,优化器再强也没用。


四、读懂报错:先回答三个问题再贴给 AI

  1. 哪一层错了:编译期、运行时、网络、权限、数据一致性?
  2. 根因 vs 连锁:谁是第一块倒下的骨牌?
  3. 失败语义:401/403/404/500 在业务里分别意味着什么?

把答案写进工单,比多贴两百行日志更有用。很多「AI 修不好」其实是人类没把语义分类做对,模型只能猜。


五、五步法详解(Reproduce / Isolate / Diagnose / Fix / Verify)

Reproduce

不能稳定复现就不要大规模改代码。先补日志、加最小用例、或在本地脚本复现。

Isolate

用 mock、特性开关、二分注释、git bisect 把问题缩小到「一个函数、一个路由、一个组件」。

Diagnose

人类必须下场。 参考方法论强调:你先定位根因,再明确告诉模型「之前的假设错在哪」。

Fix

让模型基于根因与机制出补丁,而不是基于「还是不行」出补丁。

Verify

至少 lint + build;涉及资金/权限/删除要走更强验证;AI 功能要测降级。


六、读栈:从上到下找「第一帧你的代码」

别从栈底开始梦游。优先定位仓库内第一帧,再看是否误用 API,最后才深入 node_modules。对 Next.js:构建日志浏览器控制台服务端终端是三个不同战场,先分清战场再贴栈。


七、何时重置上下文(新开会话)

满足任一条就建议新开:

  • 模型引用不存在文件或旧 API
  • 同题三轮以上
  • 对话混入多个需求
  • 你重复粘贴同一段约束超过两次

新会话只带:摘要 + 根因/排除项 + 最小相关文件。这是第03讲「会话脏了要换盆」的调试版。


八、常见 AI 调试坑(自查表)

  1. 只贴最后一行错误
  2. 贴整页日志但没有分支与版本
  3. 一次让模型修三件事
  4. 不说「禁止改动范围」
  5. 把猜测写成了事实

九、可运行示例:解析 tsc 单行错误(结构化习惯)

// scripts/parse-tsc-line.mjs
// node scripts/parse-tsc-line.mjs "src/note.ts(12,5): error TS2322: ..."
const line = process.argv[2] || "";
const m = line.match(/^(?<file>[^:]+)\((?<line>\d+),(?<col>\d+)\):\s*error\s*(?<code>TS\d+):\s*(?<msg>.*)$/);
console.log(m ? m.groups : { raw: line, hint: "未识别的 tsc 行" });

十、可运行示例:从栈提取「文件:行」候选

// scripts/stacktrace-files.mjs
const text = process.argv[2] || "";
const re = /\(?([A-Za-z]:[^)\n]+|\/[^)\n]+):(\d+):(\d+)\)?/g;
const seen = new Set();
let m;
while ((m = re.exec(text)) !== null) {
  const key = `${m[1]}:${m[2]}`;
  if (!seen.has(key) && !m[1].includes("node_modules")) {
    seen.add(key);
    console.log(key);
  }
}

十一、与 Workflow 的映射(第02讲)

Bugfix 工单字段应对应五步法:复现→隔离范围→根因→补丁→验证命令。这样 PR 描述本身就是调试剧本,而不是事后补写。


十二、VibeNote 案例:AI Route 500

坏工单:「AI 挂了修一下。」
好工单:保存笔记触发 /api/ai/expand 返回 500;复现路径为选中文本点扩写;期望 200 与流式 chunk;实际 JSON 报错;分支 main Node 20;栈顶指向 adapter;已排除代理;根因未知→下一步检查环境变量加载与模型名配置。


十三、VibeNote 流式与 React 专项清单

  • useEffect 清理是否取消 fetch/stream?
  • 组件卸载后是否仍 setState
  • 是否把仅服务端可用的 key 间接串进 client props?
  • 是否在 Strict Mode 下双调用导致状态错乱?

十四、调试与安全:脱敏是硬要求

调试时最容易手滑把用户笔记正文、token、内网地址贴进对话。默认脱敏:ID 哈希化、正文截断、密钥占位符。安全不是「合规同学的洁癖」,是你职业底线。


十五、协作时序图:人类何时介入

sequenceDiagram
  participant You as 你
  participant AI as AI
  You->>AI: 结构化工单
  AI-->>You: 补丁1
  AI-->>You: 补丁2
  AI-->>You: 补丁3
  You->>You: 停:自定位根因
  You->>AI: 根因+允许范围+验证命令
  AI-->>You: 补丁4
  You->>You: lint/build/手工→合并

十六、根因声明怎么写才「可执行」

推荐句式:根因 = 模块 + 条件 + 错误行为 + 机制。若机制未知,写「未定位 + 下一步实验」而不是编造故事。调试里最贵的是假根因,因为它会让后续所有补丁建立在沙上。


十七、让 AI 写补丁的 Prompt 骨架(调试专用)

  • 这是我的根因判断(或未知声明)
  • 这是允许修改的文件列表
  • 这是禁止事项(依赖/schema/目录)
  • 这是验证命令与期望输出
  • 如果需要假设,请列出假设并标注未验证

这就是把第01讲 RCTFC 用在调试场景。


十八、验证分层:别只用「我点过了」

  1. 静态检查(lint/tsc)
  2. 构建(build)
  3. 业务路径(手工 + 边界)
  4. 回归(至少一条自动化或脚本化检查)

十九、团队机制:看板列「Stuck > 3」

进入该列必须附:时间线、证据链、根因或排除项。没有根因分析不允许继续「再试」。这会把调试从个人玄学变成组织流程。


二十、练习建议:每天 15 分钟读栈训练

挑一条真实栈,手写:第一帧你的代码、可能的根因假设、下一步验证动作。两周后你会明显变快——不是因为你更聪明,是因为路径依赖形成了


二十一、FAQ

Q:三连跪会不会太死板?
A:它防的是仓库被补丁淹没;你可以把阈值调成 2 或 4,但不能没有阈值。

Q:我不会定位怎么办?
A:从最小复现与二分法开始;定位是技能,不是天赋。

Q:要不要让 AI 先列假设?
A:要,但必须标注未验证,避免当事实。


二十二、本讲小结

  • 三连跪是刹车,不是认输。
  • 结构化报错决定模型上限。
  • 五步法让调试可复盘、可教学。
  • 新会话 + 蒸馏信息对抗上下文污染。
  • 人负责根因,模型负责在正确假设下加速。

二十三、思考题

  1. 你上一次三连跪,如果真写根因一句话,会怎么写?
  2. 你愿意把「三连跪停手」写进 AGENTS.md 吗?
  3. 你如何训练同事「先读懂栈再贴栈」?

二十四、下讲预告

下一讲深潜「方案先行、实现为后」:如何把设计文档当作模型锚点,如何分模块推进与逐步验证,如何用文档驱动开发把 VibeNote 做到可维护。


二十五、延伸阅读:把「无效循环」画成检查清单

当你发现模型开始同时改多个无关文件、开始引入可疑依赖、开始解释「这可能是缓存问题」却没有任何验证步骤,你就该问自己:我是不是没给够结构化信息?我是不是该亲自下场? 这张心智检查清单比任何「调试提示词」都稳。


二十六、调试中的「时间盒」

给自己设 45 分钟:前 15 分钟只复现与读栈,中间 15 分钟隔离,最后 15 分钟才允许大规模改代码。时间盒能防止「越急越改越乱」。调试最怕的是焦虑驱动的编辑,AI 只是把这种编辑加速了而已。


二十七、与测试的关系:调试结束要有「防回归锚点」

哪怕只加一个最小测试或一个脚本化检查,也比「我记得修好了」强。参考方法论强调验证前移;调试是验证缺失的代价,别付两次


二十八、Next.js 常见坑位速查(补充)

  • Server Component 里误用浏览器 API
  • use client 边界放错导致打包异常
  • Route Handler 里未处理 OPTIONS 或 CORS
  • fetch 缓存策略导致「改了但像没改」

这些坑当你结构化描述时,会更容易被模型一次命中。


二十九、调试记录模板(建议放 docs/debug/

  • 日期 / 分支 / 触发人
  • 现象与影响面
  • 复现步骤
  • 时间线(发现→定位→修复→验证)
  • 根因与修复摘要
  • 防回归措施(测试/监控/告警)

这份记录会成为团队真正的「被动上下文」:下次类似问题,先搜索 docs/debug 再开新对话


三十、结语

调试是最能检验「AI 协作成熟度」的场景之一。你会立刻看到:没有流程的人,会把模型当成算命先生;有流程的人,会把模型当成在正确坐标系里的加速器。把坐标系建好,速度才有意义。


参考阅读reference/practice/vibe-coding-methodology.md(无效调试循环、亲自定位根因);课程内容/2.5 从报错到修复:一套可复制的AI协作调试法.md

三十一、把「根因—修复—验证」写成一页纸(团队版)

很多团队在复盘时只会写「修了」,不会写「为什么发生」。建议你固定一页纸结构:根因链条(触发条件→失效机制→外部表现)、修复策略(临时/永久)、验证证据(命令输出截图或日志行号)、防复发(监控/测试/规则)。这一页纸比十屏聊天更适合放进仓库,也更适合作为下一次 AI 对话的附件。


三十二、调试时如何写「已排除假设」

已排除假设不是摆设,它会显著降低模型的搜索空间。示例:已排除数据库连接失败(其他读写正常);已排除未登录(请求带 cookie);已排除前端旧 bundle(硬刷新与无痕模式复现)。写法要像证据列表,而不是情绪列表。


三十三、当你不得不同时修多个问题时:排队规则

如果线上同时爆了两个问题,先把它们拆成两张工单,两张会话。不要在同一个 thread 里混聊。上下文串线会让调试成本指数上升。你可以用优先级排队,但别用「一锅炖」。


三十四、调试中的「回滚意识」

任何调试补丁都要回答:如果更糟,怎么回滚?尤其在数据库迁移或权限变更场景。把回滚路径写进工单,模型更少会给出「不可逆」的花活。


三十五、用日志而不是用printf:为了下一次AI协作

结构化日志(requestId、userId 哈希、route、耗时)在调试时是你给模型的黄金上下文。临时 console.log 可以,但要记得升级成可检索日志,否则下次你还要靠记忆。


三十六、前端调试:别忽视「状态机不完整」

很多 bug 不是算法错,而是 UI 只有 happy path。调试时先问:loading/error/empty 是否都存在?VibeNote 这种编辑器产品尤其典型:网络失败时如果还能「看起来像保存成功」,用户会恨你,你也会恨自己。


三十七、后端调试:先确认「输入契约」

Route Handler 的 Zod 校验失败与业务异常是两条路径。调试时把 body 打印成结构化 JSON(脱敏后)比猜字段名有效得多。让 AI 改代码前,先让输入输出契约稳定。


三十八、AI 相关调试:分清「提供商错误」与「你的集成错误」

429/401/402 往往是密钥、配额、账单;5xx 可能是提供商不稳定,也可能是你传参不合法。把它们分类写进工单,模型更容易一次命中。


三十九、性能问题也是 bug:调试要换量纲

卡顿与慢请求要用 profiling 或最少也要有耗时日志。不要把「有点慢」丢给模型:它无法从你的感觉里读出瓶颈。


四十、结语补一句

调试能力的提升,会让你对 AI 的态度更健康:你会更少迷信「更强模型」,更多相信「更清楚的问题」。这才是工程师该走的路线。



四十一、从「背锅」到「可学习」:调试文化的团队收益

当调试记录可检索,新同学不会重复踩坑;当调试记录不可检索,老人会变成瓶颈。把调试写成文档,不是额外工作,是把隐性经验显性化。AI 时代显性化经验尤其值钱,因为它能被动挂载、能被复制、能被审查。

四十二、调试与 Code Review 的接口

Review 时不只看代码风格,要看:有没有验证?有没有边界?有没有回滚?有没有把根因写清楚?这些问题的答案,决定这次修复是资产还是负债。

四十三、调试时如何与产品经理沟通

用现象与影响面说话,而不是用栈。栈给工程,影响面给产品。两边对齐后,优先级才合理,你也更容易拿到「允许下线的窗口」去做更深验证。

四十四、调试与监控:把「事后救火」变成「事前预警」

同类错误第二次出现,就该加监控或告警,而不是第二次再人肉排查。调试的终点不是「修好了」,是系统更不容易再坏

四十五、给 solo 开发者的建议

你没有同事帮你 review,更要写调试记录与未来自己对话。你可以很短,但不能没有:根因一句话 + 验证命令 + 相关 commit。

四十六、再谈三连跪:不是惩罚,是保护

三连跪停手保护的是你的注意力和仓库健康。它不是否认 AI,是否认「在错误坐标系里继续加速」。

四十七、你可以今天就改的一个习惯

从今天起,每次把错误贴给 AI 之前,先自己用中文写三行:我认为错在哪一层;我下一步怎么验证;我不确定的是什么。写完再贴栈,你会惊讶地发现:很多时候你已经不需要 AI 了。

四十八、与第01讲的关系

调试是 Prompt 的极限场景:信息噪声最大、情绪最强、时间最紧。把调试工单写好,你的日常需求 Prompt 会自动变好。

四十九、与第04讲的关系

把三连跪与结构化模板写进规则文件,让团队默认遵守。规则会让个人习惯变成集体默认。

五十、收束

调试方法论不性感,但它决定你能不能长期用 AI。长期用的关键不是炫技,是少返工、少欠债、少熬夜

五十一、把调试变成「可教学案例」(训练营用法)

你可以每周挑一个真实 bug,脱敏后做成内部案例:坏工单 vs 好工单 vs 最终根因 vs 防回归措施。训练营里最值钱的不是听讲座,而是反复看「当时哪里信息不够」。VibeNote 这种产品调试案例特别丰富:离线、同步、流式、权限、富文本,每一个都值得沉淀。

五十二、调试中的「情绪管理」其实是流程管理

焦虑时人会更倾向「多改一点试试」。流程的意义就是把动作变慢:先复现、先隔离、先验证假设。AI 会放大你的动作速度,所以流程也要同步升级,否则你会更快地把仓库弄乱。

五十三、常见误判:把连锁反应当根因

例如 UI 显示错误,根因可能在数据层;数据层异常,根因可能是上游超时。调试时要区分「第一因」与「放大器」。写根因一句话时,明确你指的是哪一层的第一因。

五十四、调试与文档同步

如果根因是「文档写错/约定不清」,修复代码同时修文档。否则你会迎来第二次、第三次同样的工单。文档修复也是调试产出物,而且是最便宜的那种。

五十五、把「调试」写进 on-call playbook

即便你没有正式 on-call,也建议有半页 playbook:先查哪些日志、先跑哪些命令、先联系谁、哪些事绝对不能做(例如生产环境直接改数据)。 playbook 是规则文件的应急版。

五十六、收束语

调试是工程师的底色。AI 不会拿走底色,只会让你更频繁地面对「更快出错」的风险。把工序立起来,你才能把风险变成优势。


五十七、最后一页:调试自检表(打印贴显示器)

  • 我是否稳定复现?
  • 我是否知道失败语义(HTTP/TS/网络)?
  • 我是否找到第一帧我的代码?
  • 我是否写清允许修改范围?
  • 我是否准备验证命令与回滚?
  • 我是否已经三连跪却仍不愿下场?

五十八、与下一讲的桥

当你调试结束,你会更理解为什么「方案先行」重要:很多 bug 来自实现前没把契约写清。下一讲我们把设计—实现—测试串成一条铁链,让 VibeNote 的迭代成本持续下降。

五十九、再补八个「你应该问自己的问题」

  1. 这是回归吗?哪次提交引入?
  2. 只在生产发生吗?还是本地也可复现?
  3. 是否与特定数据相关?
  4. 是否与并发相关?
  5. 是否与缓存相关?
  6. 是否与权限相关?
  7. 是否与第三方相关?
  8. 是否与时间/时区相关?

六十、结语后语

把调试当成手艺练,你会越来越不怕 AI。怕 AI 的根源往往是怕失控;工序就是可控性来源。愿你的 VibeNote 少点深夜救火,多点白天迭代。

六十一、把「调试」写进 Definition of Done(再强调)

合并前:根因是否记录?验证是否可重复?是否需要更新监控?三条任一缺失,就当作没修完。DoD 不是官僚,是把个人记忆变成团队默认

六十二、最后一句话

别用更大的模型替代更清楚的问题;先用结构化调试把问题变清楚,模型自然会变强。

六十三、练习作业(可选)

本周每次调试都保存一张「结构化工单」截图或文本到 docs/debug/,月底你会得到一本比任何教程都真的教材。真的,去做。真的,去做,别收藏就算了。收藏不会帮你修 bug,工序才会。从下一次报错开始,你就按模板写,坚持七天,你会感到明显轻松。轻松来自可控,可控来自结构化,结构化来自你愿意慢那五分钟。五分钟很值得。别省这五分钟。省了之后会后悔。真的别省。就这样。去练。加油。行。好。