从需求到 commit:一套更稳的 AI 编程工作流
AI 已经可以从一句需求写到一份 diff。甚至再往前一步它还能顺手生成 commit message。这听起来像一种效率革命。但在真实项目里最危险的往往不是 AI 写得不够快而是它太容易把“从需求到 commit”压缩成一口气。你说“帮我做一个用户导出功能。”它开始改接口、写按钮、补工具函数。你说“这个页面偶尔报错帮我修一下。”它开始加空判断、包 try-catch、改默认值。你说“看下这次能不能提交。”它开始总结改动生成一个看上去很专业的 commit message。每一步都很积极。每一步也都可能埋雷。因为软件交付不是“把代码写出来”。软件交付是一条链路需求要被确认方案要被选择行为要被锁定结果要被验证diff 要被 review最后才轮到 commit。AI 可以参与每一环。但不能跳过任何一环。这就是我现在越来越坚持的一件事不要让 AI 从模糊需求直接冲到 commit。要给它一套更稳的工作流。一、第一步不是写代码而是把需求变成契约很多 AI 编程翻车源头不在代码。源头在第一句话。“加个导出功能。”“优化一下列表页。”“修一下登录问题。”这些话在日常沟通里没有问题因为人会追问。导出哪些字段谁有权限导出数据量大时怎么处理失败后怎么提示优化列表页是优化性能、布局、交互还是加载体验登录问题是 token 过期、接口 401、页面跳转还是多端状态不同步人类开发者会停下来问。AI 不一定。AI 的默认倾向是补全空白。它会把你没说清楚的东西自动填成一个它认为合理的版本。问题是工程里最要命的往往不是“不合理”而是“看起来合理但不是我们要的”。所以从需求到 commit 的第一步不是让 AI 写代码。而是让 AI 帮你把需求变成一份可对齐的契约。这份契约至少要写清五件事我们要解决的真实问题是什么本次范围包括什么本次明确不包括什么有哪些假设和风险怎样才算完成如果这五件事说不清后面的代码写得越快风险就扩散得越快。这也是dev-skills里dev-grill-docs/dev-spec这类入口存在的意义。它们不是为了写一篇漂亮文档。它们是在阻止 AI 过早进入实现。把“帮我做一下”变成“我们确认要做的是这些不做的是那些验收标准是这里”。这一步看似变慢了。但它省掉的往往是后面三轮返工。二、复杂需求不要直接实现先让方案站出来需求对齐之后很多人会立刻进入下一句“好开始写代码吧。”简单改动当然可以。但只要改动跨模块、涉及权限、数据迁移、公开 API、支付、缓存、并发、兼容性就别急。这种任务真正危险的地方通常不是“某一行怎么写”而是“该选哪条路”。举个例子。你要做用户数据导出。有三种方案前端拿当前列表导出。后端同步生成文件。后端异步创建导出任务再通知用户下载。这三种都能叫“导出”。但它们的边界完全不同。前端导出最快但只能覆盖当前列表数据量和权限都容易出问题。后端同步更完整但可能超时可能拖垮接口。异步导出最稳但要引入任务状态、文件存储、过期清理和通知机制。如果你直接让 AI 写它很可能选择一个“常见实现”。常见不等于合适。所以复杂需求需要先过方案。方案不是长篇大论而是把关键取舍摆在桌面上有哪些可选路径各自代价是什么我们为什么选这一条会改哪些模块最大的风险在哪里验证要怎么做这就是dev-plan应该承担的角色。它把“AI 准备怎么写”提前暴露出来让你有机会在动手前纠偏。很多工程事故并不是写错了某一行代码。而是从一开始就选错了实现路径。先看方案是为了不让 AI 带着错误方向一路狂奔。三、写代码时不要从实现开始要从可证明的行为开始真正进入编码阶段也不要把目标设成“把功能写出来。”更稳的目标应该是“先定义什么行为必须成立。”这就是为什么 feature 适合走dev-tdd。不是因为所有项目都必须严格教条地测试先行。而是因为 AI 太擅长写“看起来完整”的实现。如果没有行为约束它很容易写出一套表面顺滑、边界缺失的代码。测试的价值不只是防回归。测试还是一种防止 AI 跑偏的锚。比如导出功能至少要锁住有权限时能导出。无权限时被拒绝。筛选条件能正确传递。空数据有明确结果。异常时有可观察的错误。这些行为先被写下来AI 的实现就不再是自由发挥。它必须围着这些证据转。bug 修复更是如此。修 bug 时不应该让 AI 直接“猜一个补丁”。应该先让问题复现。再列假设。再沿着调用链、状态流、数据流往前追。最后确认根因。这就是dev-fix和普通“帮我修一下”的区别。普通修复经常只处理症状。根因式修复要留下失败证据和回归证明。一个 bug 被真正修掉应该能说清它以前为什么会失败。我怎么稳定复现它。根因是哪一处。这次改动为什么解决根因。以后同类问题怎么被测试挡住。没有这些东西所谓“修好了”只是一个乐观判断。而工程不能靠乐观判断交付。四、AI 说“完成”之前必须拿出证据AI 很喜欢说“已完成”。这句话本身没有意义。真正有意义的是它后面有没有证据。跑了哪些测试哪些路径被覆盖有没有手动验证有没有 lint 或 build有没有没覆盖到的风险如果这些问题答不上来那“完成”只是“代码已经生成”。从需求到 commit 的流程里dev-verify是非常关键的一关。它的作用不是再写代码。它的作用是把完成声明变成证据声明。你不能只说“权限问题修好了。”你要说“我跑了权限相关测试有权限和无权限路径都通过。”你不能只说“导出功能完成了。”你要说“我验证了筛选条件、空数据、异常提示和成功下载路径。”你不能只说“这次重构没有影响行为。”你要说“我跑了受影响模块测试关键调用路径仍然通过。”这听起来像细节。但对 AI 编程来说这是从玩具走向工程的分界线。没有验证AI 生成的是候选答案。有了验证候选答案才有资格进入下一关。五、commit 不是收尾动作而是最后一道门很多人把 commit 当成流程的尾巴。代码写完了测试看起来过了生成一个 message提交。但在 AI 编程里commit 不能只是“保存一下进度”。它应该是最后一道门。因为 AI 的 diff 经常有几个问题它可能顺手改了无关文件。它可能引入了和项目风格不一致的新 helper。它可能把临时代码留在里面。它可能为了让测试过弱化了真实约束。它可能在一个 commit 里混进多个意图。这些问题不一定会被测试发现。它们需要 review。所以 commit 前最好有一轮dev-code-review。这轮 review 不应该只看语法。它要问的是这次改动是否符合最初需求有没有超出范围有没有和方案或 ADR 偏离有没有缺少测试有没有隐藏风险有没有可以更小的改法如果 review 发现问题就回到前面对应的环节。需求不清回需求。方案错了回方案。实现有问题回实现。验证不足回验证。只有当 diff 真的经得住检查commit message 才有意义。否则一个漂亮的 commit message 只是在给一份不稳的改动包装纸。六、三条路径覆盖大多数真实工作一套工作流如果每次都要求从头跑到尾最后一定没人愿意用。真正好用的流程应该能按风险选择路径。对新功能或中等复杂度改动可以走dev-grill-docs - dev-plan(可选) - dev-tdd - dev-verify - dev-code-review - git commit如果是 UI 或产品界面类工作前面可以加dev-design-context对 bug 修复可以走dev-fix - dev-verify - dev-code-review - git commit对很小的 hotfix可以压缩成dev-tdd - dev-verify - dev-code-review - git commit关键不是把所有 skill 都背下来。关键是理解每一关挡的是什么风险。需求关挡的是“没听懂就开始写”。方案关挡的是“方向错了还越跑越快”。测试关挡的是“实现看起来对但行为没锁住”。根因关挡的是“症状没了问题还在”。验证关挡的是“生成完成被误当成交付完成”。review 关挡的是“无关改动和隐藏风险混进 commit”。commit 关挡的是“把不清楚的变化写进历史”。流程不是为了让 AI 慢。流程是为了让 AI 的快有边界。七、稳定的 AI 工作流本质是把人的工程判断前置很多人担心加流程会不会降低 AI 编程效率。我的感受正好相反。没有流程时你看起来很快。一句话生成一屏 diff马上运行。但后面会不断补洞。需求补一次。边界补一次。测试补一次。review 再补一次。最后你花掉的时间可能比一开始慢下来更多。稳定的工作流不是把 AI 捆住。它是把人的工程判断前置。先问清楚再写。先选方案再改。先锁行为再实现。先找根因再补丁。先验证再宣布完成。先 review再 commit。当这些动作变成默认路径AI 的能力才会真正进入工程系统。否则它只是一个速度很快的代码生成器。而速度很快的代码生成器既能提高效率也能快速制造混乱。从需求到 commit真正值得追求的不是“一口气全自动”。而是每一步都知道自己为什么往前走。这也是我理解的更稳的 AI 编程工作流不是让 AI 少做。而是让 AI 在正确的位置做正确的事。如果你现在的 AI 编程流程经常翻车不妨先检查一个问题你是在哪一步把方向盘交给 AI 的如果答案是“第一句需求之后”那就太早了。先把需求变成契约。再让它开始写。