你让 Claude Code「修 invoice 渲染里的时区 bug」。PR 漂亮地回来——测试全、文档全——却完全是 invoice 列表的缓存失效 bug。它读文件时确实发现了那个 bug,但不是你要的那个。原来的时区 bug 还在。
最快的修法:别让 Claude Code 一上来就动手改文件。按 Shift+Tab 直到状态栏显示 ⏸ plan mode on,再提问。在 Plan Mode 下(Claude Code v2.1.0 及以上),Claude 会先只读地看代码、写出一份计划,在你批准之前不能改任何文件。这样你在「计划」这个便宜的阶段就能看出误读,而不是在 diff 里才发现。喜欢用文字的话,输入 /plan;或者用 claude --permission-mode plan 启动,把它设成默认。
输出和 prompt 不符,几乎总发生在 plan 阶段,而不是代码生成阶段。Claude 读 prompt、读文件、读相关 context,然后 commit 了一个偏离你所写内容的心智任务。等代码落地时,plan 已经错了——而代码忠实地反映了那个错误的 plan。所以根治办法是结构性的:在任何改动之前,强制加一道「先重述、再批准」的关卡。
你属于哪一类?
| 你看到的症状 | 最可能的原因 | 跳到 |
|---|---|---|
| 你的 prompt 能读出两种合理意思 | prompt 歧义,Claude 挑了一种 | 原因 1 |
| 第一条指令做了,后加的条件被忽略 | 长 prompt 被压缩了 | 原因 2 |
| 输出遵循了你没要求的某条惯例 | CLAUDE.md 默认值赢了 | 原因 3 |
| diff 在你从没点名的文件里 | 从文件 context 推断 intent | 原因 4 |
| 修法小得可疑 | Claude 修了旁边更容易的问题 | 原因 5 |
| 「修」完 bug 还能复现 | 症状对、根因错 | 原因 6 |
常见原因
按命中率从高到低排列。
1. Prompt 有歧义,Claude 挑了一种合理解读
「修时区 bug」可以是渲染 bug、存储 bug、解析 bug 或者比较 bug。Claude 撞上的第一个就动手了,而你想的是另一个。
如何判断:事后用新眼光看你的原 prompt。如果你能找出两种或更多合理解读,那就是歧义在作怪。
2. 长 prompt 被略读,关键句被略掉
prompt 超过约 200 字时,常被压缩成「主要诉求」——你后面加的次要约束、具体限定就丢了。Claude 按压缩后的版本干活。
如何判断:工作匹配你 prompt 里的第一个大指令,却忽略了后面加的条件(「但别影响 email 路径」)。
3. CLAUDE.md 注入了竞争性默认值
prompt 说「做 X」,CLAUDE.md 说「这块我们一直 Y」。Claude 调和成「按 Y 的风格做 X」——不是你要的。这种情况常见到 Claude Code 仓库里有专门的追踪 issue:Claude 读了 CLAUDE.md 里一条明确规则,嘴上说理解了,转头却做别的(anthropics/claude-code issue #15443)。
如何判断:输出匹配某条你忘了它还在的 CLAUDE.md 约定,尽管 prompt 写的不同。用 /memory 看看当前从各个 CLAUDE.md 加载进 context 的到底是什么。
4. Claude 从文件 context 推 intent,而不是从 prompt
你说「修 bug」,Claude 读了 invoice.ts,看到一处明显的 code smell,就判定那是 bug 并「修」了——真 bug 在另一个文件。同一个机制也会导致越界改动——你从没点名的文件被改了——这是反复出现的投诉(anthropics/claude-code issue #41707)。
如何判断:diff 在你没点名、也没预期会动的文件里。
5. Claude 解决了相关但更容易的问题
你要的是难的修法。Claude 看到一个相关但容易的问题,修了就当完事——真正的修法需要更深的查证,而模型没投入那个精力。
如何判断:一个你本来准备花数小时修的问题,改动却又小又干净——可疑。
6. Prompt 描述了症状,Claude 修了另一个原因
「用户看到错的时间戳」可能是时区、格式化、服务器时钟、浏览器 locale 或 DB 列类型。Claude 挑了一个原因修了,但真因是另一个。
如何判断:Claude「修」完 bug 还能复现。上报的症状没钉死是哪个根因。
最短修复路径
按收益从高到低。Step 1 在便宜的阶段(planning)逮住绝大多数 misalignment,而不是在昂贵的阶段(code)。
Step 1:每个非琐碎任务都先过一道你批准的计划
干这件事的原生工具就是 Plan Mode。按 Shift+Tab 循环权限模式,直到状态栏显示 ⏸ plan mode on(循环顺序是 normal → auto-accept edits → plan),或者输入 /plan。Claude 会只读地调查、写出计划,然后停下。在你接受计划之前不会改任何文件。把计划对照你的意图审一遍,然后批准;或者发回修正让它重新规划。
Plan Mode 帮你搭好了结构,但它不会逼 Claude 主动暴露它自己的疑虑。在 prompt 里加上这段,让歧义显形:
提出计划之前:
1. 用 3 条 bullet 重述任务:
- 我要你做什么(一句话)
- 成功是什么样(一个可观察的标准)
- 什么不在 scope 里(你绝不会动的东西)
2. 列出 2 个你考虑过但拒绝的替代解读。
「替代解读」这一行是杠杆——逼 Claude 把歧义说出来,而不是闷头挑一种读法。
Step 2:修 bug 时,先要失败复现
开修之前:
1. 复现 bug。给我精确的触发输入 + 精确的错误输出。
2. 把失败 trace 到负责的代码,标 file:line。
3. 提出 fix。
4. 等我批准再写代码。
这能逮住「修错 bug」,因为你在任何修改之前就看到了复现。如果它的复现和你看到的不一致,偏差当场就暴露了。
Step 3:多步任务,每步要 status 更新
每一步(改文件 / 加测试 / 跑 migration)之后:
- 贴一行总结
- 停下,等 "proceed"
- 我确认后才进入下一步
你能中途打断,而不是到最后才发现 misalign。总结一看不对就按 Esc 打断;已完成的部分会保留,你可以从那里改方向。
Step 4:偏差发生时,诊断 plan,而不是 diff
输出不符时,别只顾着改代码——先找出哪里误读了:
你的输出是 X 的正确代码,我要的是 Y。
走一遍:
1. 你理解的 task 是什么?
2. 我 prompt 里的什么导致了这个理解?
3. 什么信号会让你改成理解成 Y?
回答会告诉你撞上了六个原因里的哪一个,也会改善你下一次的 prompt。
Step 5:非琐碎工作用结构化 prompt 模板
Goal: [一句话]
Acceptance: [一个可观察的标准]
Scope: [允许动的文件]
Out of scope: [不要动的文件 / 关切]
Constraints: [必须 / 不允许]
Context: [Claude 推不出来的领域信息]
六行模板消掉绝大多数歧义驱动的误读。其中 Out of scope 那一行专门防原因 4。
Step 6:反复偏差,就把模板变成 slash command
如果类似 prompt 反复出错(「修 bug」→ 修错 bug),问题出在 prompt 的类别上,而不是单条 prompt。把这套结构化布局存成可复用的命令,别再重打。
到 2026 年 6 月,自定义命令已经并入了 skills。两种写法都还能用,都会生成一个 slash command:
- 旧写法:
.claude/commands/fix-bug.md这个 Markdown 文件 →/fix-bug - 新写法(推荐):
.claude/skills/fix-bug/SKILL.md→/fix-bug
项目级 skill 放在 .claude/skills/,随仓库共享;个人级放在 ~/.claude/skills/,跨项目跟着你走。用户在命令后面打的内容会进到 $ARGUMENTS。示例 SKILL.md:
---
description: Reproduce, locate, then propose a fix before writing any code
argument-hint: [bug description]
allowed-tools: Read, Grep, Glob, Bash
---
Bug to fix: $ARGUMENTS
Before editing any file:
1. Restate the bug in one sentence and state what is OUT of scope.
2. Reproduce it: exact input -> exact wrong output.
3. Trace to the responsible code (file:line).
4. Propose the fix and WAIT for my approval.
这样 /fix-bug timezone in invoice rendering 每次都跑完整道关卡。每个类别建一个——/fix-bug、/add-feature、/refactor——各自按那类工作校准。
如何确认真修好了
- 重跑最初的失败复现。你上报的那个症状必须消失——不是相关的另一个症状。
- 打开 diff,确认只动了你划进
Scope的文件。Scope之外出现改动,说明原因 4 漏过来了;拒掉、重新规划。 - 把 Claude 的计划总结对照你那行
Acceptance标准读一遍。如果两者描述的不是同一个结果,那计划就是错的,代码也跟着错。
预防建议
- 非琐碎工作保持 Plan Mode 开着(
Shift+Tab到⏸ plan mode on);任何改动前先批准计划。 - 修 bug 必须先要失败复现,再要 fix 方案。
- 把按类别的模板变成
/fix-bug、/add-feature、/refactor这些 skill,让这道关卡只需一个按键。 - 多步任务要每步 status,偏差可用
Esc打断。 - 偏差发生时,诊断 plan(不是 diff),并更新对应类别的 skill。
CLAUDE.md保持精简,用/memory检查;里面一条过时的惯例会悄悄盖过你的 prompt。- 五行具体的 prompt 胜过五十行含糊的。具体 > 长。
常见问题
Plan Mode 会多花 token 吗? 它会多加一轮规划,但这一轮是只读代码、不改文件,比让 Claude 写错代码、再回滚、再重来要便宜得多——「回滚再重来」那个循环才是烧 token 的元凶。
我 prompt 写得很清楚,它还是跑偏了,怎么办?
跑 Step 4 的诊断。问它把 task 理解成了什么、prompt 里的什么把它带过去了。多半指向某条 CLAUDE.md 默认值(原因 3),或者它从某个打开的文件里捡到的 context(原因 4),而不是你的措辞。
从 Sonnet 4.6 换成 Claude Opus 4.7 能修好吗? 对真正难的推理偶尔有用,但 misalignment 主要是「规划关卡」的问题,不是「模型能力」的问题。一个较弱的模型加上「先重述、再批准」的关卡,胜过一个无人盯着、放任自流的更强模型。
怎么让它别去改我没点名的文件?
两层防护:在 prompt 里写明确的 Out of scope 一行;在 slash-command 的 skill 里用 allowed-tools / disallowed-tools 约束它能碰什么。Plan Mode 也会在任何写入前把文件清单亮出来,你可以直接拒掉越界的计划。
我批准了计划,代码还是偏离了计划。 那是本文不覆盖的另一种失败——计划对,执行没跟上。用 Step 3(每步 status),在第一个偏离的步骤就逮住,而不是拖到最后。
相关阅读
- Claude Code Plan 模式偏离计划
- Claude Code 不照审计报告做
- Claude Code 重构 scope 太大
- Claude Code 新手入门
- Claude Code 工作流
- Claude Code 项目配置
外部参考:Claude Code Plan Mode(官方文档)、Slash commands 与 skills(官方文档)。
标签: #排查 #Claude Code #排查 #输出不符