"把门户主页完善一下"这句话,背后可能藏着好几项不同的工作。促销列表缺少筛选器;横幅按钮指向了错误页面;排行榜数据准备逻辑写了两遍,每次修改都得多花一倍时间。至于促销页面的地址到底从哪里来,几乎没人记得清楚。

听到这样的要求,人多半会追问。Claude Code 也可能会问,但它经常会自己填补空白,做出看似合理、实际上没人要求的工作。不同类型的任务,各自会引出不同的额外操作:筛选器旁边多出搜索功能,修复链接时顺手改了样式,重构时顺便"修好"排序,而调查最后变成了直接修改。

应该发生什么变化

区分任务类型,最简单的方法是看工作结束后,什么会变得不同:

  • 出现了以前没有的行为 - feature,也就是新功能;
  • 行为恢复到预期状态 - bugfix,也就是修复错误。已经实现、但从一开始就没有按约定运行的情况也属于这一类;
  • 外部表现保持不变,内部代码结构有所不同 - refactoring;
  • 您得到关于项目的答案,源代码保持原样 - research,也就是调查。

任务类型能提示您在请求中明确哪些边界,以及应该检查什么。给智能体多大的自由度,还取决于出错的代价和任务规模:修改用户正在使用的代码,需要比在练习项目中新增页面更加谨慎。也有混合任务,例如先调查,再修改。这时每个阶段都应有各自的结果和边界。

新增功能

促销列表需要一个开关,只显示正在生效的促销。先明确条件:带有 active: true 标记的促销才算有效,促销 A 和 C 启用此标记,B 未启用。这里的数据只是练习用示例,下面的请求也可以直接改写后用于您的项目。

智能体很可能会执行"添加有效促销筛选器"这个请求,而且会做得更多。结果可能是:开关做好了,旁边还多了个搜索框,"既然都筛选了嘛",另外还加上结束日期排序。每项额外功能单独看都挺合理,加在一起却把一个新功能扩成了没人要求、还得额外检查的小型子系统。

至少,额外添加的功能还能在页面上看到。更糟的是,智能体悄悄替您做了决定。Andrej Karpathy 曾分享过他的 MenuGen 项目:用户通过 Google 登录,用 Stripe 付款,智能体根据电子邮件把购买记录关联到用户账户。如果两个服务中的邮箱地址不同,付款记录就无法对应到账户。数据该如何关联、项目里现有数据该怎么处理,这些决定应该由您来做,最好直接写进请求。我们这里的问题简单些:如果促销记录根本没有 active 标记,该怎么办?

另一个容易引出额外操作的因素是参考示例。智能体会在项目中寻找相似代码并照着实现,而它找到的可能恰恰是大家早就想重写的那部分。如果项目里有合适的示例,请您明确指出。

新增功能时,需要说明一个用户场景,并明确列出本次任务不包含什么:

在主页的促销列表中添加一个"仅显示有效促销"开关。
带有 active: true 的记录表示促销有效,没有此字段的记录表示无效。
用当前数据检查:开关启用时显示 A 和 C,关闭时显示 A、B 和 C。
不要添加搜索、排序或其他筛选器,这些属于独立任务。
如果项目中已有类似开关,请沿用相同做法,
并指出参考的是哪个开关。
先用一句话说明你准备实现的用户场景,
然后等我回复。在此之前不要修改文件。

最后两行成本很低,却很有用:如果智能体复述的场景与您的想法不一致,修改之前就能发现。智能体给出计划后,可以简短地问它:这个方案是否过于复杂,是否还有没做完的部分,它为什么这么认为?任何计划都可以这样检查,feature 尤其如此,因为额外添加的内容往往藏在这里。完成后,检查开关开启和关闭两种状态,也看看页面上有没有多出不需要的东西。

修复错误

主页横幅按钮应该打开显示促销条款的 /campaign/ 页面,但目前却指向 /old/。

对智能体来说,最快的做法是直接把 /campaign/ 写进按钮链接。如果地址原本就写在链接里,这样确实足够。但如果地址来自多个按钮共用的数据,这种硬编码只会掩盖症状:这个按钮能用了,数据中的错误却仍然存在。另一个常见做法是,既然文件已经打开,就顺手调整横幅的间距和颜色。

地址来自共享数据:修改按钮只修复横幅,另一个按钮仍指向 /old/;修改数据则会同时修正两个按钮的地址修改按钮修改数据data/promo.jsonurl: /old/横幅/campaign/另一个按钮/old/data/promo.jsonurl: /campaign/横幅/campaign/另一个按钮/campaign/
应该在哪里修复,取决于按钮从哪里获取地址

光看按钮无法判断属于哪种情况,只有查看代码才能确定。

提出请求前,先亲自重现故障:点击按钮,看看它会跳转到哪里。如果您无法重现错误,别急着关闭任务,先确认当时的操作步骤和数据。重现故障后,下一步才是找原因。不知道按钮从哪里获取地址?没关系,这正是要先问智能体的问题:

主页横幅按钮目前指向 /old/,应该指向 /campaign/。
先找到按钮从哪里获取地址,并指出对应位置。
暂时不要修改文件。
等我确认后,再修改定义地址的位置。
不要改动横幅样式。

修改后,重复最初的操作:点击按钮,核对地址,并确认页面显示了促销条款。如果修改的是多个按钮共用的数据,还要检查另一个使用该数据的地方。

调整代码结构

排行榜的数据准备逻辑几乎一模一样地写了两遍,每次修改都得改两处。任务是保留一个版本,同时不改变排行榜内容。

修改时必须保持不变的部分称为不变量。在这里,就是相同数据下的参赛者顺序和表格中的数值。

重构出错时往往没有明显提示。相同分数的排序可能变了,数值取整方式也可能不同,却没有错误消息,表格只是显示了错误内容。智能体合并两个版本后,甚至可能什么都没运行就报告"行为没有变化"。它也可能顺手"改进"排序,因为觉得原来的规则很奇怪。

按这个顺序取一组数据:A 得 10 分,C 得 20 分,B 得 20 分,D 得 15.5 分。现在表格显示为 C: 20、B: 20、D: 15.5、A: 10。重构的对照标准就是当前代码的这个输出,即使您希望结果不同也一样。这组数据是特意挑选的:C 排在 B 前面,所以如果新版本开始按名字排列同分选手,B 就会跑到前面。小数分数则能帮助发现取整是否发生变化。

重构前,数据经过两份准备逻辑;重构后只经过一个版本;输入和最终表格 C 20、B 20、D 15.5、A 10 保持一致之前之后=输入和表格不变,只有中间过程发生了变化数据集 A、B、C、D数据集 A、B、C、D副本 1副本 2准备数据一个版本表格C 20, B 20, D 15.5, A 10表格C 20, B 20, D 15.5, A 10
不变量就是图中两端保持不变的部分

下面的请求可以同时避免这两类问题:

排行榜的数据准备逻辑在两处重复了,请合并为一份。
不要改变表格的行为,即使有些地方看起来很奇怪,
请把这些地方单独列出来。
修改前运行现有检查,并输出以下数据对应的表格:
A: 10、C: 20、B: 20、D: 15.5。保存两次输出。
修改后重复同样的操作并进行比较。
在报告中说明现在的数据准备逻辑位于何处。

请亲自比较保存的输出,而不只是看报告里写着"结果一致"。这只能说明这些数据下的行为保持不变,仅此而已。请求的最后一句还用于检查任务本身:表格相同,并不代表重复逻辑真的已经合并。

这种任务里,半途而废比不做更糟。假设一份副本还留着,部分调用却已经切换到新版本。表格没变,但准备数据的方式仍有两套,智能体下一次可能基于旧版本继续工作,因为它不知道该以哪套为准。开始合并后,就尽量完成到只剩一个版本;如果时间不够,就先停下来并记录还剩什么。

只调查,不修改

Research 与其他类型最大的区别在于,最终交付的不是修改后的项目,而是答案。我们要调查的问题是:促销按钮的目标地址在哪里设置?这和修复错误时遇到的是同一个问题,但这里完全没有要求修改。这就是混合任务的样子:先调查,再单独进入修复阶段。

智能体在这里常见两种偏差。第一种是调查途中直接开始修复:它发现一段代码不太对,觉得直接改掉比描述问题更省事。这样调查就变成了没有明确任务、也没有验证的修改。第二种更隐蔽:智能体读完代码后,自信地解释页面如何运行,尽管它并没有启动页面。从旁观者看来,转述代码和实际观察到的行为很难区分。

第三种偏差从请求本身就开始了。如果您写明接下来打算怎么做,智能体就可能围绕这个目标组织答案:它给出的不再是当前实现方式,而是它认为更好的方案。所以做 research 时,应询问目前的实现方式,把后续想法留给下一阶段。下面的请求没有提到之后要修正地址。

找到主页横幅按钮从哪里获取地址。不要修复任何内容。
回复中请列出相关文件和代码位置,以及它们之间的关系,
说明哪些结论是通过阅读代码得出的,哪些是通过运行得出的,
以及目前还有哪些未知信息。

这类请求的理想回复大致如下:"在 pages/home.html 中,按钮地址取自 promo.url,它在 data/promo.json 中被设为 /old/。这是通过阅读这两个文件确认的。我没有启动页面,也没有检查脚本是否会修改地址。"文件之间的关系可以核对,已知与未知的边界也说得很坦诚。

如果调查途中发现可疑代码,可以单独列在回复中:目前能观察到什么,还缺少什么才能下结论。修复则属于有明确任务描述的下一阶段。

使用 Plan 进行调查

在 Plan 模式下进行调查比较方便:源文件不会被修改(但如果终端会话已允许 bypassPermissions,就不会有修改拦截,即使您没有主动开启该模式)。只读命令无需确认,其他命令则会请求许可或经过自动检查,所以仍要查看实际运行的内容。结束时不必批准计划,因为批准后就会开始修改。先保存回复,然后反复按 Shift+Tab 退出 Plan,直到状态栏显示 manual mode on。如果您可以使用 auto 模式,在这个切换循环中它可能紧跟在 Plan 之后。

第一步与任务边界

把要点放在一张表里。

类型先问什么智能体可能自行做什么应该检查什么
Feature用户需要什么新操作?添加相关便利功能,自行决定如何处理数据指定场景可正常使用,没有多余内容
Bugfix实际发生了什么,而不是预期发生什么?修补表面症状或顺手调整附近样式原有操作流程产生了预期结果
Refactoring哪些内容必须保持不变?不运行就报告结果、"改进"行为,或只做到一半前后输出一致,重复逻辑已全部移除
Research目前的实现方式是什么?开始修改,或把阅读代码说成实际观察回复包含文件、依据和未知事项

第三列列出了应该在请求中明确限制的内容。第四列则是您自己要检查的内容,或者要求智能体在回复中展示的内容。

反过来说,任务类型本身并不代表智能体可以任意操作。"这只是重构"并不意味着可以重写半个模块;"这只是修复错误"也不代表可以顺手改变样式。类型可以提示您该问什么、检查什么,但任务边界仍然要由您来说明。

重写六个请求

下面列出六个常见请求。请为每个请求判断类型,并重新表述,减少智能体自行补充的空间:说明结果、边界和检查方式。后面紧接着就是解析,先试着自己判断。

  1. "添加排行榜 CSV 导出功能"。
  2. "排行榜有时会把同一位参赛者显示两次,修一下"。
  3. "把 pages/home.html 拆分一下,这文件太大了"。
  4. "为什么主页加载这么慢?"
  5. "修复链接,顺便重写样式"。
  6. "把门户做得更好"。

以下是一种可能的解析方式。您的表述可以不同,重要的是包含相同的关键要素。

1. 导出排行榜。
Feature。缺少用户场景:哪些列要导出、行的顺序是什么、导出按钮放在哪里?还有一个容易漏掉的数据问题:没有得分的参赛者是否也要导出?请您自己决定,否则智能体会替您决定。还要单独写明不做什么:导入、选择列或其他格式。检查很简单:用 A、B、C、D 这组数据导出,再将行与屏幕上的表格核对。

2. 参赛者重复出现。
这是 Bugfix,但重点在"有时",而不只是"修一下"。目前还不知道重复行何时出现,智能体也就无从着手;它最可能会在显示表格前删除重复项。这正是被掩盖的症状。先确认在哪种操作和数据下会出现重复,再要求智能体找出发生位置,但暂不修改。检查时重现同一个会导致重复的场景。

3. 拆分大文件。
这是 Refactoring,但没有说明不变量,也没有办法检查是否"什么都没弄坏"。补充说明:页面的外观和行为应保持原样,包括横幅、促销列表和排行榜;并在修改前记录现有检查的结果。还要限制智能体的额外操作:把标记拆分到不同文件时,它很容易顺手调整间距或重命名 class。

4. 页面加载很慢。
这是 Research:您是在提问,不是在要求加速。但智能体很容易将其理解为"让它快一些";如果没写明"不要修改",它可能会随意优化。请它在回复中区分测量结果和代码阅读所得:如果智能体实际检查过,"图片占用了好几 MB"就是事实;"可能是脚本拖慢了速度"则只是猜测。等找出原因后,再进入修复阶段。

5. 修复链接并重写样式。
一个请求里包含两个结果。修复链接属于 Bugfix。重写样式则很难归入这四种类型:行为没有变化,变化的是外观。它最接近 Feature,只是结果不是由用户场景定义,而是由设计稿或截图这样的示例定义。先按照 Bugfix 一节的请求修复链接并完成检查,再处理样式:

现在请按照设计稿 @banner-mockup.png 修改横幅样式。
不要修改按钮地址和文字。

6. 把门户做得更好。
无法判断任务类型,也不必猜。应该先向提出请求的人确认:目前具体有什么问题?如果是您自己提出的,就问问自己。也可以让智能体协助澄清:

在修改任何内容之前,先问我最多五个问题,
以便了解具体要改进什么。
不要修改文件。

得到回答后,任务类型通常就会清楚起来。