用 Claude Code 和 Codex 之前,先写好三个规格文件
我花了一年时间从 Claude Code 和 Codex 得到反复无常的结果。三个职责分明的规格文件解决了这个问题。
用 AI 编程智能体将近每天工作了一年,困扰我的不是幻觉代码或者调错了 API,而是结果的不一致性。同一个任务,措辞稍有不同,某天跑出来干净利落,第二天却一塌糊涂。会话越长情况越差,因为智能体会把二十条消息之前达成的共识忘得一干二净。
根本原因是结构性的。我没有一套跨会话向智能体传达意图的框架,所以每次对话都从零开始,漂向难以预测的方向。
改变结果的三个层次
把指令拆分成三个职责分明的文件,一致性问题几乎在一夜之间得到了解决。
第一层 CLAUDE.md 在每次会话时自动加载。它存放项目级别的常量:构建命令、技术栈版本、目录结构、编码规范,以及行为边界(必须做、先确认再做、绝对不做)。
第二层 SPEC.md 记录某个具体功能的”做什么”和”为什么做”。目的、需求、成功标准、技术约束、范围边界。不涉及任何实现细节。
第三层 plan.md 将规格拆解成每个耗时两到五分钟的可执行任务,附上明确的文件路径、测试优先的执行顺序,以及提交检查点。
把所有东西塞进一个文件为什么不管用
研究 LLM 指令跟随能力的论文把这个现象称为”指令诅咒”(Curse of Instructions)。单一上下文中的指令数量越多,模型对每条单独指令的遵守率就跌得越厉害。我亲自验证过:把项目规则、功能规格、任务清单全塞进一个文件,智能体大约忽略了后半段将近一半的指令。
按职责分离解决了这个问题。智能体从第一层读取全局规则,从第二层读取功能意图,从第三层读取执行步骤。每个文件都足够短,让模型能够完整地关注到。
CLAUDE.md 保持精简效果最好
由于这个文件在每次会话都会加载,它只需要包含普遍适用的内容。构建命令、栈版本、目录结构、命名规范。加上三档行为边界:必须做、先确认再做、绝对不做。
效果最好的做法是从最小化开始,每当发现智能体反复犯同一个错误时再增量添加规则。一开始就试图写出面面俱到的 CLAUDE.md,反而会导致臃肿,触发我本想避免的遵守率下降。
几个具体的陷阱:不要把 API 密钥或代码片段放进来,它们会很快过期。不要重复 linter 已经在强制执行的规则。把任何只针对单一功能的内容移入第二层。
规格文件聚焦于”做什么”和”为什么”,把”怎么做”留给智能体
与传统 PRD 的区别在于,这些规格是为智能体消费而结构化的。五个部分就够了:目的、需求、成功标准、技术约束、边界。
把实现决策交给智能体。它可以分析现有代码库,选择合适的方案。当我试图规定”怎么做”时,智能体要么盲目照做导致与现有模式冲突,要么直接无视。
手写规格之外的另一种方式:让智能体来采访你。设定两条规则,每次只问一个问题,尽量用选择题。这样产出的规格,比我自己从头写的版本遗漏更少。
把完成的规格存到 docs/specs/YYYY-MM-DD-topic.md 并提交到 Git。这样智能体可以通过 git diff 追溯规格变更历史,代码审查者也有了一份记录代码变更背后意图的文件。
会话分割是最容易被忽视的做法
规格撰写过程中的头脑风暴和问答消耗了大量的上下文窗口。从同一个会话直接跳入实现,意味着智能体会逐渐失去对早期上下文的访问能力。
我把工作重组成三个会话:会话 1 产出 SPEC.md,会话 2 创建 plan.md,会话 3 起逐条执行任务。精度的提升在第一周内就感受得到。
让这套方法发挥作用的三个习惯:在每个任务里写明确的文件路径,让智能体不再猜测;把 TDD 顺序(测试、实现、验证、提交)固定在 plan.md 里;以及上下文使用量达到大约 50% 时开启新会话。
成熟度模型指向”规格即源头”
Martin Fowler 的团队最近定义了一套基于智能体的软件开发成熟度模型,分三个级别。第一级:写规格、实现、丢掉规格。第二级:把规格作为与代码并行演进的活文档来维护。第三级:规格成为唯一事实来源,代码是生成的产物。
我认识的大多数团队和个人还没到第一级。他们发一次性提示词,然后寄望于结果。
从第一级升到第二级只需要一个习惯:把规格文件提交到 Git。从第二级升到第三级意味着在改代码之前先更新规格。今天能迈出的最小一步,是为你的项目创建一个 CLAUDE.md,并在下一个功能开始前写一份 SPEC.md。
订阅通讯
获取关于我最新项目、文章以及 AI 和 Web 开发实验的更新。