Hotdry.

Article

SpecDD 实战:用本地规格终结 AI 上下文断裂问题

通过 SpecDD 规格驱动开发框架,将项目分解为本地规格单元,为 AI 编码代理提供持久上下文,实现上下文连续性的工程实践。

2026-05-03ai-systems

在大型软件项目中,AI 编码代理面临一个根本性挑战:上下文断裂。随着代码库规模扩大,代理遗忘了早期的架构决策、约束条件和业务规则,导致实现与原始意图渐行渐远。SpecDD(Specification-Driven Development)提供了一种务实解决方案 —— 通过在代码旁边放置小型规格文件,让 AI 每次都能获取准确的项目上下文。

上下文丢失的工程本质

AI 代理的记忆丧失并非技术故障,而是工程现实。当代理处理跨越数十个文件的复杂任务时,初始的系统架构约束、模块边界、非目标行为等关键信息会在长上下文窗口中被稀释。传统的解决方案是将完整的架构文档塞入每一次提示,但这会导致提示膨胀、上下文污染,且难以维护 —— 架构文档与实现代码之间的脱节是必然的。

SpecDD 改变了这一范式。它不依赖外部文档,而是将规格声明为代码的 “邻居”,让每个规格文件描述其邻近代码的目的、所有权、约束和任务。这种设计使得代理在工作目录下即可获取完整的上下文链,无需依赖全局记忆。

SpecDD 的核心机制

SpecDD 的设计理念简洁而有效:规格文件使用 .sdd 扩展名,放置在代码同一目录或其父目录中,形成隐式的规格继承链。当代理在特定路径工作时,它自动收集从项目根目录到该路径的所有祖先规格,构成完整的上下文。

一个典型的 SpecDD 项目结构如下:

.specdd/
  bootstrap.md              # 告诉代理如何解释和解析规格
app.sdd                     # 应用级全局约束
src/
  billing/
    module.sdd             # 模块级规格
    invoice.sdd            # 服务级规格
    invoice.ts             # 实际代码

当代理在 src/billing/invoice.ts 上工作时,它自动继承 app.sddmodule.sddinvoice.sdd 三层规格的约束。这种继承是隐式的,代理无需手动配置 —— 只需按目录结构 Resolve 规格链即可。

规格文件的关键字段

每个 .sdd 文件使用结构化语言描述代码单元的关键属性。实践中,以下字段对上下文保持最为关键:

Purpose(目的) 字段声明代码存在的原因,为代理提供 “为什么做” 的答案。Owns(拥有) 字段明确该规格管理的文件和职责,建立清晰的边界。Must(必须) 字段列出强制性行为规则,而 Must not(禁止) 字段则声明负向约束 —— 后者对 AI 代理尤为有价值,因为禁止规则往往能防止整类错误实现。

Depends on(依赖)Forbids(禁止依赖) 字段共同定义模块间的协作边界。Tasks(任务) 字段提供轻量级的实现清单,使代理能够将大型任务分解为可管理的子步骤。Scenario(场景) 字段用类似 Gherkin 的语法描述具体行为示例,可直接转化为测试用例。

以下是一个实际可用的最小规格示例:

Spec: Invoice Service

Purpose:
  协调发票验证、提供商创建和持久化。

Owns:
  invoice.ts
  invoice.test.ts

Must:
  在调用提供商前验证发票输入。
  在提供商成功后持久化发票记录。

Must not:
  直接调用 Stripe。
  计算税费。
  发送邮件。

Tasks:
  [ ] 添加对不支持币种的验证。
  [ ] 为无效输入添加单元测试。

引导机制与代理入口

为了让 AI 代理正确使用规格系统,SpecDD 在项目根目录提供 .specdd/bootstrap.md 引导文件。该文件向代理解释如何解析规格继承链、遵循本地权限、解释任务、处理冲突,以及避免大范围修改。代理只需在开始工作前读取此文件,即可理解整个规格系统的运作方式。

实际工作流程推荐采用 “规格优先” 模式:先编写或更新相关规格,审查直到其准确表达预期行为和边界,然后才提示代理实现。这种模式与行为驱动开发(BDD)的理念一脉相承,但专注于为 AI 提供可操作的上下文单元。

实践参数与工程阈值

在生产环境中使用 SpecDD 时,以下参数值得参考:

规格粒度控制是首要考量。建议每个规格文件控制在 200 行以内,最小可用规格仅需 SpecPurpose 两个字段即可工作。过长规格难以维护,也会降低代理的解析效率。

任务粒度应保持在本地可完成的范围。一个任务通常应能在单一规格的 OwnsCan modify 边界内完成。如果任务需要修改多个规格域的文件,这通常意味着规格划分需要重新审视。

继承冲突处理遵循严格优先原则:当父子规格冲突时,更严格的规则胜出;Must notForbids 的权重高于 MustDepends onTasks。代理不应利用任务来突破约束。

规格与代码同步是持久有效的关键。过时规格比没有规格危害更大 —— 它们会误导代理并侵蚀对规格链的信任。最佳实践是将规格变更与代码变更放在同一提交中,确保两者始终对齐。

防止上下文断裂的最佳实践

基于 SpecDD 的实验经验,以下做法能最大化上下文保持效果:

从最小可用规格开始,逐步迭代。初始仅需 SpecPurpose 和若干 Must not 规则,运行工作流观察代理表现,然后针对性添加字段补充。过于简薄的规格产生无重点输出,过于详细的规格则成为维护负担 —— 迭代直到找到适合项目规模的平衡点。

积极使用 Must not 字段声明非目标行为。对于 AI 代理而言,明确的禁止规则往往比正向需求更有价值,因为它们直接排除了错误路径,而无需代理自行推理替代方案。

保持任务本地化。每个任务应有明确的作用域边界,能够在当前规格的权限范围内完成。跨越边界的任务是规格划分或所有权定义的信号。

使用 Done when 字段明确完成标准。缺乏清晰的完成信号时,代理倾向于过早停止或过度实现。明确的完成条件为代理和审查者提供可验证的检查清单。

局限性与适用边界

SpecDD 是实验性技术,尚未包含官方的验证器、解析器或语言服务器。当前实现依赖纯文本文件和代理的自觉遵循。这意味着人类审查仍然不可或缺 —— 所有代理输出都需要检验,代码、测试和规格的变更都应在合并前经过验证。

该方法最适合需要多人协作的中大型项目,或需要长期维护的代码库。对于小型脚本或一次性原型,引入规格系统的开销可能超过其收益。SpecDD 也不应替代测试 —— 规格可以指导测试,但测试仍然是验证行为的事实来源。


SpecDD 通过将规格声明为代码的 “邻居”,为 AI 代理提供了持久的、可导航的上下文单元。垂直继承自动携带约束,水平引用显式声明协作,规格与代码同步变更 —— 这套机制从根本上解决了大型项目中 AI 上下文断裂的问题。随着社区贡献的 tooling 逐步完善,规格驱动的开发有望成为 AI 时代软件工程的基础实践之一。

资料来源:SpecDD 官方网站(specdd.ai)

ai-systems