1. 从一个内部项目改造说起:为什么我们需要 intent.md
去年下半年,我接手了一个内部工具链项目的改造任务。这个项目本身不复杂,是一个面向运营团队的配置管理后台,前端 React,后端 Node.js,数据库 PostgreSQL,代码量大概两万行出头。团队一共四个人,之前一直是“需求来了就改”的模式,没有严格的文档沉淀,代码注释也写得比较随意。
改造的起因很简单:业务方希望这个后台能支持更复杂的配置编排逻辑,同时要把原来手工操作的几个流程自动化掉。听起来是个常规迭代,但我们很快发现了一个致命问题——没人能说清楚这个系统当前到底在干什么。前端页面上有十几个配置项,每个配置项背后对应哪些后端逻辑、哪些数据库字段、哪些外部依赖,全靠口口相传。新来的同学想改一个按钮的文案,结果不小心触发了一个隐藏的审批流,导致线上配置被锁死。
这就是很多内部项目的典型状态:代码还在跑,但知识已经丢失了。我们决定借这次改造,把 AIcoding 的工作流引入进来,核心抓手就是两个东西:一个是intent.md,一个是持续评测机制。
先说intent.md是什么。你可以把它理解成项目意图的单一事实来源。它不是需求文档,不是技术方案,也不是 API 文档,而是一份用自然语言写清楚“这个系统为什么存在、每个模块解决什么问题、哪些行为是刻意设计的、哪些是历史包袱”的说明文件。它的读者有两个:一个是人,一个是 AI 编码助手。
为什么是这两个读者?因为在实际操作中,我发现 AI 编码工具最大的问题不是写不出代码,而是它不知道你的意图。你让它“优化一下这个函数”,它会按照通用的最佳实践去改,但你的项目可能有特殊的历史原因不能那么改。比如我们那个配置管理后台,有一个字段叫status,按常理应该用枚举值active/inactive,但我们实际用的是1/2/3,因为要和上游一个老系统的协议保持一致。如果 AI 不知道这个约束,它就会“好心”地把1/2/3改成active/inactive,然后整个链路就断了。
intent.md就是用来解决这个问题的。它把那些代码里看不出来、但必须遵守的隐性知识显性化,让 AI 在生成代码之前先读一遍,相当于给 AI 戴上了一副“业务眼镜”。
2. intent.md 到底怎么写:结构、内容和避坑指南
2.1 一份合格的 intent.md 应该包含哪些部分
我参考了 CLAUDE.md 的社区实践,结合我们项目的实际情况,把intent.md分成了六个固定章节。这里要说明的是,CLAUDE.md 本身是 Anthropic 为 Claude Code 设计的项目说明文件格式,社区里已经有不少人在用,它的核心思路就是“把项目上下文写清楚,让 AI 少犯错”。我们的intent.md在这个基础上做了裁剪和扩展,更适合内部项目改造的场景。
第一章:项目定位与边界。用三到五句话说明这个系统是给谁用的、解决什么核心问题、明确不做什么。比如我们写的是:“本系统面向运营团队,用于管理下游渠道的配置参数。不负责用户认证,不负责数据报表,不负责定时任务调度。”这一章的目的是防止 AI 在改造过程中“越界”,把不属于这个系统的功能塞进来。
第二章:核心领域模型。把系统里最重要的五到十个实体列出来,每个实体用一句话说明它的业务含义,再用一句话说明它的技术约束。比如:“配置项(ConfigItem):代表一个可调整的业务参数。技术约束:status字段必须使用1/2/3,分别对应启用、禁用、待审核,不可改为字符串枚举。”
第三章:关键流程与状态机。用文字描述系统里最重要的两到三个业务流程,包括正常路径和异常路径。这一章不需要画流程图,用有序列表写清楚每一步做什么、涉及哪些实体、有哪些分支条件就行。AI 对有序列表的理解能力很强,写清楚了它就能按照你的意图生成代码。
第四章:技术栈与架构约束。列出项目使用的语言、框架、数据库、中间件,以及那些“不能动”的部分。比如:“前端使用 React 17,不可升级到 18,因为内部组件库不兼容。后端使用 Express 4,路由必须放在routes/目录下,不可使用装饰器风格。”
第五章:编码规范与风格偏好。这一章可以根据团队习惯来写,但有几条是必须的:命名规则、错误处理方式、日志格式、注释语言。我们团队要求注释用中文,错误处理统一用AppError类,日志必须包含traceId。这些写进intent.md之后,AI 生成的代码基本不需要再手动调整风格。
第六章:已知问题与技术债。这一章最容易被忽略,但恰恰是最有价值的。把那些“我们知道有问题但暂时不改”的地方写清楚,比如:“utils/legacy.js中的parseConfig函数存在性能问题,但当前调用量小,暂不优化。AI 在改造时不要动这个文件。”有了这一条,AI 就不会自作主张地去“优化”那些你不想让它碰的地方。
2.2 写 intent.md 时最容易踩的三个坑
第一个坑是写得太像需求文档。有些人会把 PRD 直接复制过来,里面全是“用户应该能够……”“系统需要支持……”。这种写法对 AI 没用,因为 AI 需要的是约束和事实,不是愿望。正确的写法是陈述句:“系统当前支持三种配置类型,分别是……”“配置项的状态流转规则是……”。
第二个坑是写得太抽象。比如“本系统采用微服务架构”这种话,AI 读了等于没读。要具体到“本系统由三个服务组成:config-service负责配置读写,audit-service负责操作日志,notify-service负责消息推送。服务之间通过 HTTP 调用,不使用消息队列。”越具体,AI 的产出越可控。
第三个坑是写完就不管了。intent.md不是一次性文档,它需要随着项目演进而更新。我们的做法是:每次迭代结束后,由当次迭代的负责人检查intent.md是否需要补充新的约束或废弃旧的约束。这个动作只花五分钟,但能避免后面大量的返工。
提示:
intent.md建议放在项目根目录,和README.md平级。文件名统一用小写,避免在大小写敏感的系统上出问题。如果团队同时使用多个 AI 编码工具,可以把intent.md的内容同步到 CLAUDE.md 或其他工具要求的文件名中,保持单一事实来源。
3. 持续评测:让 AIcoding 的产出质量可量化
3.1 为什么需要持续评测
有了intent.md之后,AI 生成的代码确实更符合预期了。但新的问题出现了:你怎么知道 AI 这次改对了,下次还能改对?我们遇到过好几次这样的情况:同一个需求,第一次让 AI 改,它改对了;过了两周,另一个同学用类似的提示词让 AI 改另一个模块,结果 AI 忽略了intent.md里的某条约束,引入了 bug。
这说明光有intent.md不够,还需要一套持续评测机制,用来验证 AI 在不同场景下是否真的理解了项目意图。这里的“持续评测”不是指传统的单元测试,而是针对 AIcoding 工作流的专项评测,核心思路是:把项目里那些“AI 容易犯错的地方”整理成评测用例,每次 AI 生成代码后自动跑一遍,看它有没有踩坑。
3.2 评测用例的设计方法
我们的评测用例分为三类,每类都有不同的设计逻辑。
第一类:约束遵守评测。从intent.md里提取那些“不可违反”的约束,每条约束设计一个评测用例。比如intent.md里写了“status字段必须使用1/2/3”,那评测用例就是:给 AI 一个修改配置状态的提示词,看它生成的代码里是否使用了1/2/3。如果用了字符串枚举,评测不通过。
第二类:边界条件评测。针对那些“AI 容易想当然”的地方设计用例。比如我们的配置管理后台有一个逻辑:当配置项被引用时,不允许删除。AI 在生成删除接口时,很容易只写“删除数据库记录”,而忽略引用检查。评测用例就是:给 AI 一个删除配置项的提示词,看它生成的代码里是否包含引用检查逻辑。
第三类:回归评测。把历史上 AI 犯过的错误整理成用例,每次生成代码后跑一遍,确保同样的错误不会犯第二次。比如有一次 AI 把日志级别从warn改成了error,导致监控告警泛滥。这个错误就被固化成了一个评测用例:检查 AI 生成的代码中日志级别是否符合intent.md里的规定。
3.3 评测的执行方式
评测的执行方式可以很轻量,不需要搭建复杂的平台。我们的做法是:在项目里建一个evals/目录,每个评测用例是一个 Markdown 文件,里面包含三部分:输入提示词、期望输出、检查脚本。
输入提示词就是模拟开发者会怎么跟 AI 说话。期望输出是用自然语言描述“正确的代码应该满足什么条件”。检查脚本是一个简单的 Node.js 脚本,用正则表达式或 AST 解析来检查 AI 生成的代码是否符合期望。
每次 AI 生成代码后,开发者手动或通过 CI 触发评测脚本,脚本会输出一份报告,列出哪些用例通过、哪些不通过。不通过的用例会附带具体的差异说明,方便开发者判断是 AI 真的错了,还是评测用例本身需要调整。
注意:评测用例不是越多越好。我们一开始写了五十多个用例,结果维护成本太高,很多用例半年都没跑过。后来精简到十五个核心用例,覆盖了百分之八十的常见错误,维护起来轻松很多,效果反而更好。
4. 把 intent.md 和持续评测串起来:一个完整的改造流程
4.1 改造前的准备动作
在正式让 AI 参与改造之前,我们花了大概两天时间做准备工作。第一天上午,团队四个人一起过了一遍现有代码,把intent.md的六个章节填完。这个过程本身就是一次知识梳理,很多之前模糊的地方在写的过程中变清晰了。第一天下午,我们把intent.md同步给了 AI 编码工具,让它先读一遍,然后问它几个关于项目的问题,比如“配置项的状态有哪些”“删除配置项时需要注意什么”。通过 AI 的回答,我们能判断它是否真的理解了项目意图。
第二天上午,我们设计了第一批评测用例,一共八个,覆盖了最核心的约束和最容易犯错的边界条件。第二天下午,我们用一个小的改造需求做了一次试运行:让 AI 根据intent.md生成代码,然后跑评测用例,看通过率如何。第一次试运行的通过率只有百分之六十,主要问题是 AI 忽略了intent.md里关于日志格式的约束。我们调整了提示词,把日志格式的约束放在更显眼的位置,第二次通过率就上到了百分之九十。
4.2 改造中的实际操作节奏
正式改造开始后,我们形成了一个固定的工作节奏:每天早上,负责人把当天的改造任务拆成若干个小的提示词,每个提示词对应一个具体的代码改动。提示词里会明确引用intent.md的相关章节,比如“根据 intent.md 第三章的状态机描述,修改配置项审核流程”。
AI 生成代码后,开发者先做一次人工审查,重点看intent.md里的约束有没有被遵守。人工审查通过后,跑一遍评测用例。评测通过后,代码才能提交到仓库。这个流程听起来有点繁琐,但实际跑下来,每个改动的平均处理时间只比原来多了三到五分钟,而代码返工率下降了大概百分之七十。
4.3 改造后的复盘与迭代
改造完成后,我们做了一次复盘,主要看两件事:一是intent.md里有哪些内容在实际操作中被证明是没用的,二是评测用例里有哪些是从来没触发过的。复盘的结果是:intent.md的第六章“已知问题与技术债”使用频率最高,几乎每次改造都会参考;而第一章“项目定位与边界”使用频率最低,因为大家心里都清楚这个系统是干什么的。评测用例方面,八个用例里有三个从来没失败过,我们把这几个用例标记为“低频”,降低了执行频率。
复盘之后,我们把intent.md和评测用例都更新了一版,作为下一个迭代的起点。这个“改造-复盘-更新”的循环,就是我们所说的“持续评测”的真正含义:不是一次性验收,而是持续校准 AI 对项目意图的理解。
5. 常见问题与排查技巧实录
5.1 AI 不读 intent.md 怎么办
这是最常见的问题。AI 编码工具通常会把intent.md作为上下文的一部分,但如果文件太长,它可能会“忘记”中间的内容。我们的解决办法是:把最重要的约束放在文件开头和结尾,因为 AI 对开头和结尾的记忆最牢。另外,在提示词里显式引用intent.md的章节号,比如“请参考 intent.md 第 2.3 节关于状态字段的约束”,也能显著提高遵守率。
5.2 评测用例误报怎么处理
评测用例误报通常有两种原因:一是检查脚本写得太严格,把正确的代码判成了错误;二是 AI 用了另一种正确的方式实现了需求,但不符合脚本的预期。我们的处理原则是:先人工判断 AI 的产出是否真的正确,如果正确,就调整检查脚本;如果不正确,就保留用例并补充说明。千万不要为了让评测通过而修改 AI 的产出,那样就本末倒置了。
5.3 团队协作时 intent.md 冲突怎么办
如果多个人同时修改intent.md,可能会出现冲突。我们的做法是:把intent.md纳入版本控制,每次修改都走 Pull Request 流程。修改者需要在 PR 描述里说明为什么修改、影响了哪些约束。这样既能避免冲突,又能留下修改记录,方便回溯。
5.4 评测执行太慢怎么优化
评测脚本如果每次都全量跑,确实会慢。我们的优化方式是:根据代码改动的范围,只跑相关的评测用例。比如这次改动只涉及配置项的删除逻辑,那就只跑和删除相关的三个用例,其他的跳过。这个映射关系可以手动维护,也可以根据代码路径自动推断。
| 常见问题 | 排查思路 | 解决方法 |
|---|---|---|
| AI 忽略 intent.md 约束 | 检查约束是否在文件开头或结尾 | 调整约束位置,提示词显式引用章节号 |
| 评测用例误报 | 人工判断 AI 产出是否正确 | 正确则调整脚本,错误则保留用例 |
| intent.md 多人冲突 | 检查是否有版本控制 | 纳入 Git,走 PR 流程 |
| 评测执行慢 | 检查是否全量跑 | 按改动范围选择性执行 |
提示:评测用例的检查脚本尽量用简单的字符串匹配或正则表达式,不要引入复杂的 AST 解析。我们试过用 AST,维护成本太高,后来全部改成了正则,准确率反而更高,因为 AI 生成的代码风格比较固定,正则足够用了。
6. 一些实操心得和后续扩展方向
这套工作流跑了大半年,最大的感受是:AIcoding 的瓶颈不在 AI 的能力,而在项目本身的知识管理。如果项目本身的知识是混乱的,AI 只会把混乱放大。intent.md和持续评测的价值,就是逼着团队把知识整理清楚,然后用一种 AI 能理解的方式表达出来。
另一个心得是:不要追求一步到位。我们一开始想把intent.md写得尽善尽美,结果写了三天还没写完,后来改成“先写核心约束,后续迭代补充”,反而推进得更快。评测用例也是一样,先写五个最关键的,跑起来之后再慢慢加。
后续我们计划把这套工作流扩展到更多的内部项目,同时探索两个方向:一是把评测用例和 CI 流水线更紧密地集成,让 AI 生成的代码在合并前自动跑评测;二是把intent.md和项目文档系统打通,让文档更新时自动同步intent.md的相关章节。这两个方向都还在试验阶段,等跑通了再跟大家分享。
最后分享一个小技巧:如果你的项目里有一些“祖传代码”实在说不清楚意图,可以在intent.md里直接写“此模块为历史遗留,AI 不要修改”。这比强行解释要有效得多,AI 会老老实实地绕开这些地方。