我是怎么给 AI 写执行需求书的:以 HAL 分层重构为例
实例:一份 250 行的执行需求书《garden-driver HAL 分层重构》(V1.1),交付对象是另一个 AI(CodeBuddy,嵌入式 + C 方向)。档案全文见知识库 HAL 分层重构执行需求书,本文讲它为什么长这样。
#引言:让 AI 翻车的从来不是模型
把一个任务交给 AI 执行,结果的好坏差距可以非常大:同一天、同一个模型,有的任务一遍跑通,有的任务改三遍还在原地。复盘多了会发现,分水岭往往不在模型的智力,而在交出去的那份需求书里写没写三样东西:现状是什么、边界在哪里、坑在什么地方。
这一个月我把香橙派智能花园的驱动重构写成了给 AI 的执行需求书,前后迭代了两个版本。V1.0(9 月底)交出去之前我自己先读了三遍,发现它「目标清楚但地基糊」——于是推翻重写。到 V1.1 定稿,它从 8 条坑位长到 14 条、从 8 条验收长到 10 条、多了整整一节「任务 0:现状盘点」。这篇文章把这份需求书拆开给你看:六个部件,各自回答执行者一定会问的一个问题。
#一、需求书的六个部件
- 现状盘点——回答「我从什么地基上开始动」;
- 契约签名——回答「接口到底长什么样,谁说了算」;
- 移植红线——回答「哪些行为已经验证过,动了就是事故」;
- 坑位清单——回答「前人流过血的地方在哪」;
- 验收标准——回答「做到什么程度算完」;
- 版本记录——回答「这份文档本身可不可信」。
下面逐个展开,每节都给需求书里的真实例子。
#二、现状盘点:把「既成事实」摆上桌
写 V1.0 时我犯的错:只写了「目标架构长什么样」,没写「现在这套系统已经长成了什么样」。而这两个月里,面板、语音、HA 仪表盘、微信小程序、华为云全都接上来了——它们全是 garden-cli 的消费方。执行者不知道这些,就敢按教科书式重构去改 JSON 输出格式,改完五个下游一起炸。
V1.1 的解法是两张表。第一张表列出全部上层消费方和它们对 CLI 的依赖方式,然后一句总约束:「重构只许换工程内部结构,不许动任何对外行为」。第二张表盘点现状资产:SSH 地址、sudo 密码用法、板上工程路径、硬件描述定稿在哪个头文件、哪个目录的数据丢不得。最后加上一句容易被忽略的:电机子系统 09-25 已全链路打通,标定 40/12 已实测定稿——V1.0 里写的占位值作废。
给 AI 的需求书尤其需要这一节:AI 没有你的项目记忆,它对「现状」的全部认知就是你给它的这份文档。文档里没有的现状,对它来说就不存在。
对应的执行动作是「任务 0:现状盘点」——先 grep 出现有适配函数与命令全集跟签名表核对,再从 server.py 提取实际调用的全部 CLI 命令作为回归清单,最后备好二进制和数据两份备份。先对齐,后动手;差异写进提交说明。这一步把「文档与代码的出入」从事故变成了流程。
#三、契约先行:签名写死,但留一条「以现状为准」
需求书第五节把 8 个 HAL 模块的函数签名一个一个写死:返回值语义(0 成功 / -1 离线)、初始化策略(惰性初始化)、跨进程状态放哪个文件,连「PWM 的 period/enable 必须幂等写,只有 duty 每次写」这种约束都写在签名旁边。写死的原因很简单:接口是这次重构唯一的新增公共面,模糊一处,执行者就会替你发明一处。
但有个矛盾:我是凭记忆和文档整理的签名表,跟代码现状可能有出入。硬装作没这回事,执行者要么按错误签名硬写(编译过不了),要么自作主张改签名(契约失效)。解法是在签名表开头加了一行:
以下为 V1.1 目标签名(按 10-08 现状整理)。凡与 cli_main.c 现有 drv_*/cmd_* 实际不符之处,以现状为准修订签名,并把差异写进提交说明。
这条「以现状为准」是整个文档里我最满意的一句话。它承认了文档会过时,把裁决权交给现实,同时用「差异写进提交说明」保住可追溯性。对 AI 执行者来说,这句话的另一个作用是授权:它明确允许执行者修订签名,不需要停下来问——但必须留下记录。
#四、移植红线:已验证的行为一条都不许动
重构最容易死在「顺手优化」上。执行者看到一段写得很绕的代码——比如「速度帧加速度按目标 RPM/0.6 反算」——很难忍住不把它改成「更合理」的恒定加速度。但那段绕代码是两天联调换来的:固定加速度会让 300RPM 三秒起步、高速定位来回震荡,最后才收敛到「恒定加速时间」这个反直觉的方案。
所以需求书里给电机子系统单独立了 7 条移植红线,每条都是「已验证行为 + 为什么长这样」:
- 0x36 位置解析字节序——曾有 256 倍 bug,已修,不许回退;
- 速度帧加速度 = 目标 RPM/0.6 反算(恒定加速时间,不是恒定加速度);
- 定位单次探测 + 真实位移回填速率 + 单段按剩余封顶 x1.2(防高速震荡);
- 收尾梯形降速(最低 8%);急停保留梯形收尾;
- 同构判据在 jog 与 goto 两处都必须存在——曾因只改一处漏掉另一处;
- tcflush 必须发生在 flock 成功之后(先锁后清);
- 用完串口立即释放 flock(常驻进程也要借锁)。
每条红线后面那句「为什么」比红线本身更重要:不知道为什么不能动的人,总会在某个下午以「代码整洁」的名义把它动掉。红线 = 行为 + 理由,缺一不可。
#五、坑位清单:给执行者的护身符
V1.0 有 8 条坑位,V1.1 长到 14 条。新增的 6 条全部来自博客成文之后的新事故:systemd 沙箱让 sudo 失效、pkill -f 匹配到自己的命令行、garden-data 目录删了要重新标定、24V 域没上电先查供电再查代码……每一条都是真实踩过的,标着「违反必炸」。
坑位清单对 AI 执行者的价值比对人大得多。人排障会调动直觉和经验,AI 只会按文档走——文档里没有的坑,它会一个不落全部踩一遍。几条真实发挥过作用的:
- 坑 3(PowerShell 远程命令):复杂命令一律「写 .sh → scp → 执行」,本项目 140+ 个 board_*.sh 脚本就是这条坑的纪念碑;
- 坑 7(JSON 只允许英文):板子 C locale,中文提示由前端渲染——AI 最爱在输出里加中文提示,必须提前封死;
- 坑 12(garden-data 丢不得):配合任务 0 的备份动作,把「删库重标定」这种最难挽回的事故挡在动手之前。
写坑位清单有个技巧:不只写「不许做什么」,要写「症状 → 第一嫌疑」。比如「直连正常、经服务失败 → 第一嫌疑是 systemd 沙箱」。执行者撞到症状时能直接对号入座,而不是把每个坑重新踩一遍。
#六、验收标准:每一条都要能跑出结果
「确保重构不破坏现有功能」不是验收标准,是愿望。V1.1 的 10 条 DoD 每条都能跑出结果,典型的三类:
- 机械可查:
grep -n "aht20\|bh1750\|..." cli_main.c零匹配——上层不再直接 include 芯片头文件,一条命令验证铁律; - 逐字段对比:回归清单全部命令的 JSON 输出与重构前 diff 逐字段一致(含离线降级结构)——「JSON 契约逐字节不变」从这里落实;
- 物理量验收:电机 move 25/50/75/100 实测误差 <2%、软限位零撞限位开关——性能没有回退。
还有一条容易被漏掉的:「语音 / HA / 华为云 / 小程序零感知,各跑一轮冒烟」。它验收的不是代码,是第二节那张消费方表——五个下游每个都摸一遍,才算真的没动它们。
#七、版本化与自包含
需求书本身也是工程产物,也要版本管理。V1.1 文末的版本记录老老实实写了这次改了什么:IP 修正、水位标定定稿、灯光接口拆分、电机接口扩到 5 个、坑位 8→14、DoD 8→10。版本记录的作用是让执行者敢信这份文档——它知道自己拿到的是最新裁决,而不是某个过时副本。
「自包含」是另一个容易被低估的要求。文档开头一句「本文档自包含,执行前通读全文,尤其第 7 节」,意味着执行者不需要任何额外上下文就能开工:不需要读历史聊天记录、不需要猜「上文提到的那个文件」。给 AI 的文档尤其如此——你没法在它执行到一半时给它补上下文,能补的都必须提前写进去。开头还有个「30 秒版」:一段话讲清背景和目标,让执行者(和人)在深入细节前先有全局。
#八、可复用的六件套模板
把这份需求书压成一个可复用的骨架:
| 部件 | 写什么 | 自检问题 |
|---|---|---|
| 1. 现状盘点 | 资产清单、消费方表、既成事实约束、备份动作 | 执行者动手前知不知道会炸到谁? |
| 2. 契约签名 | 接口逐个写死 + 语义 + 「以现状为准」对齐条款 | 接口模糊处执行者会不会替我发明? |
| 3. 移植红线 | 已验证行为 + 每条的理由 | 「为什么不能动」写了吗? |
| 4. 坑位清单 | 症状 → 第一嫌疑 → 修法,标「违反必炸」 | 最近一次事故进清单了吗? |
| 5. 验收标准 | 每条可执行:能 grep、能 diff、能量出数 | 每条都能跑出结果吗? |
| 6. 版本记录 | 每次修订改了什么、为什么 | 执行者敢信这是最新版吗? |
最后留一个反直觉的观察:给 AI 写需求书的这套功夫,收益最大的是人自己。为了写清「现状资产」我把两份交接文档重新读了一遍,发现一处标定值已经作废;为了写「移植红线」我把 7 个已验证行为重新论证了一遍,顺手发现一条判据在两处实现不一致。需求书交出去之前,执行者已经先被它校准了一遍——这大概就是「写作即思考」在工程里的样子。
#相关阅读
- 知识库:HAL 分层重构执行需求书(V1.1 档案)——本文的完整实例
- 知识库:智能花园养护机项目总览——需求书背后的那套系统
- 知识库:踩坑索引(34 坑主题分组)——坑位清单的素材库
- 一次嵌入式联调踩的 17 个坑——坑位清单里前 17 条的完整复盘
- 同场竞技:DSH 与 opencode 一起写博客的那晚——AI 协作的另一个切面
#更新日志
| 日期 | 更新内容 |
|---|---|
| 2026-10-08 | 初稿发布:以 HAL 分层重构需求书 V1.1 为实例,拆解执行需求书的六个部件(现状盘点 / 契约签名 / 移植红线 / 坑位清单 / 验收标准 / 版本记录) |