AI规格驱动开发实战:给扫描器立规矩

用规格驱动开发约束AI代理,让意图在代码前显式化,避免审核崩溃。
文章讲述了作者从敏捷开发中审核崩溃的困境出发,转向规格驱动开发(Spec-Driven Development)的实践。通过构建小型端口扫描器的案例,作者展示了如何将意图写入规格、让代理质疑需求,并通过Git规则、AGENTS.md引导文件、.ai目录、术语表和规则分析流程来约束AI行为。核心发现包括:代理能主动发现规则疏漏、术语表可强制前置查询、规则变更需经分析批准。但严格流程也带来输出量负担,作者强调“只能批准能检查的小步骤”。设置约需半天,部分工作可复用为模板。
敏捷开发能快速产出代码,但当你审核速度跟不上AI写代码的速度时,问题就来了。本文作者以自己构建小型端口扫描器的经历,展示了如何用规格驱动开发(Spec-Driven Development)约束AI行为,让意图在代码之前显式化。
从审核崩溃到规格先行
作者在前一篇《When Agile Is Not Enough》中提到,一个代理团队产出的拉取请求(PR)比他审核的还快。根源在于:他没有把对软件的期望写清楚,代理替他做了决定,他只能在diff里发现这些决定,同时还要审核实现和那些他根本没意识到需要做的决策。
解决办法是把对话提前到代码存在之前:把意图写进规格,让代理质疑它,双方就“要构建什么”达成一致。作者以自己平台工程和安全背景,选择开发一个小型端口扫描器用于授权渗透测试。
据B站UP主和YouTube频道分析,目前行业对规格驱动开发的讨论集中在GitHub Spec Kit和Anatoly Volkhover的《Agentic Spec-Driven Development》等方案上。Spec Kit将这一理念描述为“反转”:规格不再服务于代码,代码服务于规格。作者选择了Volkhover的书作为起点,因为Spec Kit的文件夹和命令太多让他感到不知所措。

规格驱动开发(Spec-Driven Development) 是一种将软件规格作为唯一真相来源的开发方法论,强调先写规格、再生成代码,代码不得手动编辑。与敏捷开发强调“可工作的软件优于详尽文档”不同,规格驱动开发认为AI代理的介入让文档重新成为核心——因为代理需要明确、可执行的意图来约束行为。GitHub Spec Kit将其描述为一次“反转”:传统开发中规格服务于代码,而在规格驱动开发中代码服务于规格。这一方法论与意图显式化(making intent explicit)紧密相关:所有决策必须在代码存在之前写入规格,避免代理在diff中自行决定。Anatoly Volkhover的《Agentic Spec-Driven Development》进一步提出,规格不仅是文档,更是代理与人类之间的契约,代理有权质疑规格中的遗漏与冲突。
让代理使用Git:一条规则的完整分析
Volkhover的工作流规定规格是唯一真相来源,代码由规格生成,不能手动编辑。代理在仓库中有一组持久规则,规定它如何工作以及规则如何变更。
作者首先想改变的是Git限制。书中不让AI接触Git,但作者认为如果已审核并批准了一个变更,为什么不让代理提交?他要求代理在特性分支上工作,每个逻辑步骤一个提交,使用Conventional Commits,推送和合并到main保留给自己。
在这个工作流中,作者不是直接编辑规则文件,而是告诉代理需求,让它先分析提议的规则。代理会读取rule-analysis.md,分析允许和禁止的事项,检查与现有规则的冲突,并解决文件引用问题。
代理的回应指出了几个疏漏:没有明确禁止合并到main(虽然作者本意是保留给自己);“禁止reset”也覆盖了取消暂存,应使用git restore --staged;第一次的规则格式打包了多个要求,被重写为十二条规则。作者批准后,又追加了条件:未经询问不得丢弃未提交的工作,并通过同样的分析流程。
Conventional Commits 是一种提交信息规范,格式为 <类型>(<范围>): <描述>,常见类型包括 feat、fix、docs、chore 等。它让提交历史可读、可自动化生成变更日志。在规格驱动工作流中,代理使用Conventional Commits意味着每条提交都携带语义信息,便于人类审核和追溯规则变更。特性分支(feature branch) 是Git中从主分支分出的独立开发线,代理在此分支上提交,人类保留推送和合并到main的权限。Fixup提交 是用于修正未合并提交的小提交,通过 git commit --fixup 生成,后续可用 git rebase --autosquash 合并,保持历史整洁。这些Git机制共同构成了代理与人类之间的权限边界:代理可在分支内自由提交,但涉及历史重写和主分支的操作必须由人类控制。
规则文件的管理:AGENTS.md与.ai目录
引导文件使用CLAUDE.md,但作者换成了AGENTS.md,因为不想让名字绑定到某个工具。Claude Code从2.1.277版本开始支持该文件,默认情况下当没有项目CLAUDE.md时加载AGENTS.md。
作者还将支持文件移入.ai/目录,包括rule-analysis.md(规则变更前的检查)、rule-conflict-protocol.md(冲突处理程序)、logs/日志目录和glossary.md(项目术语表)。
AGENTS.md开头是项目目标的简短描述,如果代理被要求与目标不符的事情,它应该询问关联。它还包含处理未定义术语和冲突规则的指令:当两条规则无法同时遵守时,代理记录冲突并询问如何继续。
文件注册表放在底部,说明每个文件的用途以及代理可以对其执行的操作。代理可以编辑某些文件,只能读取其他文件,只能追加到日志。在创建文件之前,它必须提议注册条目并获得批准,不能悄悄发明新的文件类型或处理协议。
AGENTS.md 是一种工具无关的引导文件格式,旨在替代CLAUDE.md等绑定特定工具的名称。Claude Code从2.1.277版本开始支持该文件,当项目中没有CLAUDE.md时自动加载AGENTS.md。这种设计让同一套代理指令可以跨多个AI编码工具复用,避免供应商锁定。规则冲突协议(rule-conflict-protocol) 是当两条规则无法同时遵守时的处理程序:代理必须记录冲突并询问如何继续,而不是自行选择一条。文件注册表 位于AGENTS.md底部,明确每个文件的用途和代理权限(编辑、只读、追加),代理在创建新文件前必须提议注册条目并获得批准,防止代理悄悄发明新的文件类型或处理协议。这些机制共同确保代理的行为边界清晰、可审计。
souvlaki-case:一个术语表的微型实验
术语表让作者有机会观察代理如何处理无法从通用知识查找的内容。熟悉的foo-bar约定称为kebab-case,作者偏爱用souvlaki-case(同样的连字符,不同的午餐)。
代理停下来问作者是什么意思——公平地说,作者给了名字,没有给定义。书中的术语表记录含义和反含义。对于souvlaki-case,含义是小写字母和数字由连字符连接;snake_case和camelCase被明确排除。
作者还添加了一条规则:在询问不清楚的术语之前先查阅术语表。之后,代理查找定义而不再询问。这个小例子展示了作者对项目术语的期望:一旦达成一致的含义,就记录在代理会查阅的地方。
据GitHub Spec Kit文档和Volkhover的独立分析,这种显式定义术语的方法在规格驱动开发中很常见,但将其作为代理的强制前置步骤是作者自己的改进。
kebab-case 是一种命名约定,使用连字符连接小写单词,如 my-variable-name。snake_case 使用下划线连接小写单词,如 my_variable_name。camelCase 将首个单词小写、后续单词首字母大写,如 myVariableName。术语表(glossary) 在规格驱动开发中记录项目专有术语的含义和反含义(明确排除的解释),确保代理不会基于通用知识做出错误假设。作者用 souvlaki-case 替代 kebab-case 的命名实验表明:当代理遇到无法从通用知识查找的术语时,会主动询问;一旦术语表记录了定义,代理便会先查阅术语表再提问。这种“先查术语表再提问”的强制前置步骤,将术语管理从被动记录变为主动约束,减少了重复澄清的成本。
历史记录与可追溯性
每个批准的规则变更都有自己的提交。例如:chore: bootstrap from agentic-spec.com、docs(agents): add version control rules、docs(agents): require fixup commits for unmerged corrections等。
如果需要知道代理何时获得提交权限,可以找到该变更并阅读条件。随着规格增长,作者希望对软件有同样的可追溯性:为什么某个功能存在、我们同意它应该做什么以及如何变化。这对审计和合规很重要,也对几个月后回顾自己项目时有用。
这个流程值得每个仓库都用吗?
设置用了大约半天。引导是通用的,所以部分时间用于适配软件开发,部分用于制定自己的规则。作者不会为每个工具重复所有这些工作。在 enterprise 环境或构建多个工具时,将共享设置放在可重用模板中是有意义的,包括Python、Go或Java的约定。如果有平台团队,维护该模板应是其职责的一部分。
在自己的规则内工作也需要适应。作者让流程足够严格,甚至重命名文件夹都需要分析和批准,这部分是他自己造成的。更多熟悉的问题是输出量——代理可以像生成长diff一样轻松生成长篇规则分析,仍然需要阅读后才能批准。作者要求更小的步骤。把对话移到Markdown并没有给他更多时间或注意力。
“我只能批准我能检查的东西,我只能检查小步骤。”这是作者的核心结论。
下一步:扫描器规格
设置给作者提供了一个记录决策的地方,以及在决策成为规则之前质疑它们的过程。Git例子已经捕捉到指令中的遗漏。接下来,作者想看看这对实际扫描器需求如何工作。在第二部分中,作者添加代码生成所需的内容并编写第一个功能规格。在编码代理写下一行代码之前,它会回来问八个问题。
相关推荐

Workbuddy零基础入门:桌面AI智能体如何落地工作流
Workbuddy桌面AI智能体零基础教程解读:从安装、积分领取到文件管理与自动化工作流搭建,对比CodeX的适用场景与成本差异,帮助职场人完成从AI提问者到AI管理者的思维转变。

OpenAI智能体新栈:计算机操作、决策API与超速工作流
OpenAI Dev Day发布智能体新栈:Computer Use操作速度超越普通人,Decisions API基于Luna实现极低延迟分类,Agents API开放同源计算机操作能力,GPT-6.1 Sol成本仅为Astra七分之一。本文梳理核心更新、实测数据与开发者落地要点。

梁文峰开源推理框架DeepInfo,硬刚美国禁令
DeepSeek在开源模型后再开源推理框架DeepInfo,包含GPU/CPU交叉流水线、小模型预判大模型复核、华为昇腾与英伟达芯片全面适配等技术,直面美国联邦禁令。本文解析其对AI产业落地的意义与开源策略。