☰
用Skills任务拆分防止AI编码跑偏:从需求拆解到工程实践
2026/10/5 9:04:29 网站建设 项目流程

用 AI 写代码这件事,我在真实项目里断断续续试了快半年。最让人头疼的不是模型写不出代码,而是写着写着就跑偏:你要它修一个按钮的样式问题,它顺手把整个组件重写了;你让它加个筛选功能,它把数据结构也给改了。每次看到这种“自由发挥”,我都得花更多时间去回滚和返工。

直到我把 Matt Pocock 那套 skills 的思路真正用在项目里,才找到问题的关键:AI 跑偏不是因为模型笨,而是因为需求没有被拆成任务。你给它一个模糊目标,它就只能靠猜。你给它一份明确的任务清单,它反而能老实干活。这篇文章我会把这套“先把需求拆成任务,再让 AI 动手”的方法完整记录下来,包括目录怎么建、技能文件怎么写、实测对比结果怎么样,以及我踩过的一些坑。适合正在用 Claude Code、Codex、Cursor 这类 AI 编码工具的前端、全栈开发者参考,尤其是那种“明明让 AI 干活,最后还得自己改半天”的人。

1. 先把需求拆成任务:这种思路到底在解决什么问题

1.1 跑偏的本质:模型不是全知助手,它在“尽量合理”地猜

很多人误以为大模型是在“理解需求”。其实从工程角度看,它更像一个下一 token 预测器:你给它一段输入,它根据已有上下文和训练数据,生成一个概率上“最像样”的后续输出。如果你给的输入是一个模糊的意图,那它生成的就是一个模糊意图的“合理还原”,而不是你心里想的那个精确结果。

举个例子。我在一个 React 项目里发现待办列表有个 bug:编辑完一项内容之后,列表里的排序会随机变。我当时的原始 prompt 是“修复待办列表状态更新导致排序错乱的问题”。模型给了我一个很完整的新组件代码,把原来的 useReducer 换成了 useState,还加了副作用。表面上看很努力,但实际上完全没有定位到问题源头,反而把原本稳定的状态管理逻辑推翻了。

这就是跑偏的本质。模型没有能力“分清主次”,它在每一行代码上的选择都近似于“当前上下文下最合理的结果”。当整体目标不清晰时,它就只能用“动得更狠”来替代“动得准”。真正的解法,是把模糊目标变成一串足够小、足够具体的子任务,让模型不必在每个环节里猜下一步要做什么。

1.2 任务拆分不是嘴上说说,要变成可复用的“技能”

可能你会说:“我也知道要拆任务,每次我都把需求写得很细。”但问题在于,手工拆任务这件事,你自己写 prompt 的时候还能控制得住,一旦对话变长、上下文变多,拆出来的任务就逐渐被稀释,最后模型又回到了自由发挥的状态。

我看到的 Matt Pocock 那套 skills 思路,核心不是“教你怎么拆任务”,而是把拆任务这件事固化成技能文件,让 AI 在动手前必须执行一次。这就好比训练一个新人:光告诉他“你处理事情要有条理”是不够的,你得给他一张 checklist,告诉他每一步必须做什么、完成到什么样才算通过。

在实际操作里,一个任务拆分技能文件长这样:

--- name: task-breakdown description: 在开始编码前,把需求拆解为可执行的任务列表 --- # 技能说明 收到需求后,禁止直接写代码。你必须先完成以下步骤: 1. 提取需求的输入、输出和约束条件,判断这是新增功能、修复问题还是重构。 2. 将需求拆解成不超过 8 个小任务,每个任务必须是一个独立可验证的改动点。 3. 为每个任务明确验收标准:改动什么文件、应有的行为、需要覆盖的边界情况。 4. 按依赖关系排列任务顺序,先做数据层/接口层,再做 UI 层,最后做联调和自测。 5. 把任务列表展示给用户,等用户确认后再开始动手。

如果每个需要 AI 动代码的场景都先过一个这样的技能文件,模型的行为就从“生成一个最可能的大改动”变成了“按清单走流程”。区别是巨大的。

2. 实操准备:我把 skills 用成了自己的外挂工作流

2.1 目录结构:别把技能文件全塞在一个文件夹里

Matt Pocock 的系统让我受益最大的地方,是把 skills 做成了人人都能复制粘贴的目录。它不是一个只能跑在你某个特定 IDE 里的魔法,而是以普通 Markdown 文件为载体的提示词模板,只要你的 AI 工具支持读取文件上下文,就能用起来。

我第一次搭目录的时候非常冲动,把十几个技能文件全放在一个文件夹里,想着“越多越好”。结果模型反而迷失了:它不知道该用哪个技能,偶尔还会把两个技能文件里的规则混在一起执行。后来我改成下面这种结构,问题立刻少了很多。

~/.claude/skills/ ├── task-breakdown/ │ ├── SKILL.md │ └── examples/ │ └── bug-fix-example.md ├── code-review/ │ ├── SKILL.md │ └── rules/ │ └── react-hooks.md ├── spec-writer/ │ ├── SKILL.md │ └── templates/ │ └── feature-spec.md └── commit-helper/ └── SKILL.md

注意这里的关键点:每个技能不是单个 Markdown 文件,而是一个带说明文件的目录。说明文件里写清楚“什么时候用、怎么用、步骤是什么”,可选的 examples 子目录用来放实际案例。模型在遇到对应场景时,会优先读取描述,再决定是否加载整个技能。这样既不会把无关内容塞进上下文,也能保证规则完整。

2.2 三个我实测下来最有用的技能

先说task-breakdown。这是最核心的一个,也是本次测试的主角。它的作用是在 AI 动手前强制完成需求拆解。我把它放在每个项目的根目录里,并要求 AI 每次开工前先找这个技能文件。它看起来是一套简单的提问框架,实际上是在帮 AI 建立“先计划后行动”的思维路径。

然后是code-review。这个技能用来约束 AI 在改完代码后必须做一轮自检。它不是简单的“检查代码是否有问题”,而是要求模型对照任务清单逐一核验:这个改动是否超出了任务范围、是否有未覆盖的边界条件、是否存在引入回归的风险。很多 AI 生成的 bug,其实就是在没人做这轮自检的情况下溜进去的。

最后是commit-helper。这个技能的价值不在生成规范 commit message,而在于强迫模型自己看清 diff 里到底改了什么。如果 diff 里出现了任务清单之外的文件,它会在 commit 信息里标出“意外改动”。有了这个反馈机制,我就能及时发现 AI 又跑偏了。这三个技能组合起来,相当于给 AI 装了一圈围栏:任务拆分阻止它乱跑,代码审查发现它跑偏,commit 记录让跑偏的痕迹无处可藏。

2.3 在不同 AI 客户端里的加载方式

虽然我叫它们 skills,但实际上手方式取决于你用的工具。Claude Code 和类似的 CLI 工具通常支持把技能目录放在某个全局配置路径下,模型会自动检索可用技能;Cursor 这类 IDE 插件则是通过规则文件和 MCP 配置来加载;Codex 也有自己的 skills 市场。

如果你用的工具暂时不支持自动发现技能,也可以把它降级为“项目规则”来使用:把技能说明放进项目的 AGENTS.md 或者 CLAUDE.md 里,再在 prompt 中指名道姓地要求模型“先执行 task-breakdown 技能再动手”。实测下来效果并不差,因为关键不是技能文件被谁发现,而是模型在动手前有没有真正看到那一串步骤。

3. 实测记录:同样的需求,三种不同喂法差距比我预想的大

3.1 基线测试:直接给出需求让 AI 自由发挥

为了验证“skills 到底有没有用、有多大用”,我做了一组很朴素的对比测试。测试项目是一个 TypeScript 编写的待办事项管理应用,需求是我从真实项目里抽出来的一个 bug:

修复:更新待办事项完成后,列表的顺序会错乱,应该保持原来添加的顺序。

第一种喂法是最常见的:把这句话直接丢给模型,没有附加任何技能文件。模型给出的方案是把列表渲染处的 sort 逻辑删掉,改用一个新的字段来记录创建时间。这个方案本身不算错,但它做了三个我没有要求的事:改了接口返回结构、给每一条待办数据新增了一个字段、顺带调整了另一处过滤逻辑。结果一次修改牵动了四五个文件,测试跑完还挂了一条原有的用例。

这就是 AI 跑偏的真实写照:模型并不是不理解需求,而是它在“修复 bug”这个模糊指令下,自动假设了一大堆额外需求。它从概率分布里挑了一个“看起来周全”的答案,而不是你要的“最小改动”。

3.2 测试一:我手动把需求拆成 5 个任务再交给 AI

第二次测试,我没用技能文件,而是自己先把需求拆成了带验收标准的任务清单:

1. 定位:找到更新待办完成后排序错位的根因 2. 修复:在状态更新层保持原数组顺序不变 3. 验证:添加三条待办,分别完成第一条,确认顺序不变 4. 回归:跑一遍现有测试,确保没有破坏其他行为 5. 提交:给出修改文件和原因

看起来足够具体了,对吧?但真实执行结果被打脸了。模型在完成第 2 步之后,跳过了第 3 步,直接去执行第 4 步,并且在第 4 步里为了“让测试更完整”,额外新增了两个测试文件。我反复往回拉,它才承认“为了覆盖更多场景而加东西”。

为什么手动拆任务还不行?因为任务清单虽然被模型看到了,但它没有被编进强约束的流程里。模型看到第 4 步“跑一遍现有测试”,很自然地联想到了“我还可以顺手加几个测试”。在缺少“禁止做清单之外任何事”这条规则的时候,模型总会在下一步选择那个概率最高的“看起来合理”的动作。

3.3 测试二:让 task-breakdown 技能先接管流程

第三次测试,我启用了 task-breakdown 技能,并且给它配了一条硬性指令:所有步骤必须逐项执行,任何一步没有完成都不允许进入下一步。

模型先调用了技能文件,输出了一个任务列表。它比我自己手写的清单更克制,每个任务都带了“不要做什么”的禁区描述。比如说在第 2 项里它写了“禁止新增字段、禁止修改接口结构、禁止改动其他组件”。看到这个输出的时候,我就知道这次大概率稳了。

实际结果也确实没让我失望。模型完成修改后,只动了两个文件:状态处理函数和对应测试文件。没有额外字段,没有重构,没有多余的“顺手优化”。我把测试跑了一遍,原有用例全部通过。这才是“把需求拆成任务再让 AI 干活”该有的效果。

三种喂法的核心差异,我在下面的表格里整理了一下:

喂法是否拆分任务是否强制顺序改动文件数是否超出任务范围
直接给需求否否4 个以上是,顺带修了无关逻辑
手动拆任务是否3 个是,新增了测试文件
task-breakdown 技能是是2 个否,严格限定范围

4. 拆任务为什么能防止 AI 跑偏:从机制层面拆解

4.1 窄化任务空间,模型的选择面变小

很多人以为技能文件只是“把话说清楚了”,这种理解不完整。真正起作用的是:任务拆分把模型的生成空间一步一步压缩了。

大语言模型在每一步生成的时候,都会面对一个巨大的候选空间。直接让它“修复 bug”,它可以重写组件、改数据结构、加依赖、调样式,甚至重构整个文件夹。但当它先执行 task-breakdown,把目标定义为“在状态更新层保持原数组顺序”,模型每一步的选择面就窄多了:候选方案里不太可能出现“重构整个组件”这种选项。

打个简单的比方:你让一个实习生“整理这块业务”,他大概率会把文档结构、代码注释、甚至团队协作流程都改一遍。但你让他“把第 38 行那个变量名拼写错误改掉”,他能做的就只有一件事。任务拆分在 AI 场景里干的就是这事,把“整理业务”拆成“修变量名”“补注释”“更新文档”,它就不会越界。

4.2 制造验收点,让模型每一步都有“回头确认”的机会

技能文件里的验收标准,不仅仅是给模型读的,也是给模型的一个“强制暂停点”。每完成一个子任务,模型必须重新阅读下一个子任务的目标和验收条件。这一步看起来多余,实际上非常关键。

在没有验收点的情况下,模型的注意力会逐渐漂移。对话越长,它越只看得到最近的上下文,老早就忘了最开始的约束。而任务列表就像给代码变更打了一个个锚点:每一步开始时模型都会回头看一眼“我这一步要做到什么样才算完”。从这个角度看,task-breakdown 技能真正提供的不是“计划”,而是注意力管理。

这也解释了一个有意思的现象:有时候我们手动写的任务清单比模型自己拆出来的还细致,但效果反而不如技能生成的好。因为手动清单没有内置“每步开始前重新确认范围”的触发器,模型只是把任务清单当背景信息,而技能文件是把每步都变成了强制跳转点。

5. 实测中踩过的坑:这些细节不注意,技能也会失效

5.1 常见的失效模式和处理方法

技能文件不是写出来就有用的。我在一周多的实测里,遇到过好几次“明明用了技能,AI 还是跑偏”的情况。后来我把这些情况整理成了问题清单,基本覆盖了新手可能遇到的绝大多数问题。

症状常见原因处理方式
AI 只读技能前两行,后面步骤完全没执行技能文件太长,模型在上下文窗口有限的情况下丢失了后半部分规则把最重要的一句放在文件第一行,比如“禁止直接写代码,先拆任务”;同时控制单个技能文件不超过 60 行
任务拆出来了,但每个任务内部还是自由发挥任务没有附带“禁止做什么”的边界描述每个任务后面都要写“禁改范围”,明确列出不改的模块和文件
拆完任务后 AI 依然跳步,先写了后一步的代码技能里缺少强制顺序的措辞在技能文件最前面写明“必须按任务编号顺序执行,未完成当前任务不得进入下一个任务”
模型把所有技能文件的内容都混在一起加载了太多无关技能,上下文里全是互相冲突的规则按项目最小化技能集合,只保留 task-breakdown 和当前任务需要的技能

5.2 写技能文件时最容易犯的一个错误:规则太空

“确保代码质量”这种描述,等于没有描述。模型无法把“代码质量”映射到具体的操作。好的技能文件里,每个规则都应该是一个模型可确认的动作,而不是一个抽象的品质要求。

我举一个简单的例子。如果你在代码审查技能里写“注意代码规范”,模型只会点点头然后继续按它的习惯输出。但如果你写“逐行检查新改动是否引用了未定义的变量,发现一处就给出一处修改建议”,模型就有了明确的操作抓手。

我后来写技能文件都遵循一个模板:触发条件、执行步骤、每步验收标准、禁用列表。前三个决定模型敢不敢做,禁用列表决定它做的时候敢不敢乱来。这个模板可以直接复制去用,我是在 Matt Pocock 那套 skills 仓库的启发下逐步打磨出来的。

--- name: custom-skill description: 一句话说明这个技能在什么场景下使用 --- ## 触发条件 在什么情况下模型必须走这个流程。 ## 执行步骤 1. 第一步要做什么,做到什么程度。 2. 第二步要做什么,做到什么程度。 ## 验收标准 - 完成的标志是什么,可以用什么命令或测试验证。 ## 禁止事项 - 不许做超出步骤范围的事情。 - 不许跳过任何一步。 - 不许在未确认前修改其他文件。

6. 把 skill 工程变成常用能力:给团队的建议

6.1 先建立“技能库”,再让每个成员按需加载

单人使用 skills 是提高效率,多人使用 skills 是统一行为标准。在我实践这个玩法的第二周,我把一套基础的 skills 文件放进了项目仓库的.claude/skills目录,并且让团队里的其他人也拉取一遍。

效果比我想象中更好。原本每个开发者向 AI 描述需求的方式千奇百怪,有人给一段话,有人只发一个截图。但现在大家共用同一个 task-breakdown 技能,AI 收到的输入结构就一致了:先拆任务、再写代码、最后自测。产出的代码风格和边界控制也因此变得更可预测。

团队使用技能库有一个额外的好处:技能文件可以被持续迭代。某个成员在项目里发现 AI 经常犯某一类错误,他就可以把这个错误写进对应的禁用列表。比如我们在一个后端项目里发现模型总爱自己改数据库索引,就在 code-review 技能里加了一条“未经需求确认不得修改数据库 schema 文件”。下次再遇到同类任务,模型就不会踩同样的坑。

6.2 把业务常识封装进技能,而不是每次重复解释

关于 skills 扩展我还有一个小方法:把项目里的业务规则也做成技能文件。这样新开发者加入项目时可以快速获得上下文,而且随时更新,团队共识就沉淀在技能里,而不是散落在群聊里朝令夕改。

测试驱动开发的团队可以做一个 test-first 技能,要求模型在实现功能前先根据验收标准产出测试用例;做接口联调的团队可以做一个 api-mock 技能,把 mock 数据格式和字段约束写死在技能文件里。最重要的一点是:技能文件不是静态的。我建议每个月回头整理一次,删掉不再适用的规则,补充新踩坑时发现的问题。技能是活的,AI 的工作方式才能跟着变稳。

用 skills 这个思路还有一个隐藏好处:你不用换更强的模型也能提升结果质量。每次跑偏背后都是概率问题,而技能文件把随机冒险变成了有边界的流程,这也是“大模型时代”里我目前看到的最实用的工程化手段。

最后再分享一个小小的收尾经验:新写完一个技能文件,别急着用到真实任务上。先拿一个“故意挖坑的需求”去测它,比如给一个前后矛盾的描述,或者一个超出它文件范围的请求。技能文件如果在对抗测试里都不跑偏,那它才真正有资格进入你的工作流。我就是靠这个方法,把一次次的“AI 跑偏”变成了“AI 按章办事”。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询