> For the complete documentation index, see [llms.txt](https://zhouhao4221.gitbook.io/haiqing-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://zhouhao4221.gitbook.io/haiqing-docs/05-workflow/spec-code-alignment.md).

# 规格与代码对齐

不同 AI 工具如何共同消费同一份规格文档，以及如何防止文档和代码随时间漂移。

***

## 问题

规格文档和代码是两个独立演进的系统。工程师用 Cursor 写代码时，AI 看到的是代码；产品经理在 Notion 更新需求时，工程师不一定知道。随着时间推移，两者出现漂移——代码里有规格没提到的行为，规格里有代码没实现的约束。

这个问题用 AI 工具来写代码后会放大。AI 生成代码时，它只能根据它拿到的上下文来生成。如果规格不在它的上下文里，它就只能猜。

**根本原因**：AI 写代码时没有读规格，不是因为规格不存在，而是因为没有人传给它。

***

## 三个对齐机制

### 机制一：显式传递规格，在每次实现之前

最可靠、工具无关的方式。实现任何功能前，先让 AI 读对应的规格文档。

```
先读 docs/requirements/active/REQ-042.md，
了解验收标准和约束后，再实现支付模块的退款流程。
```

这一步不应该省略，也不应该依赖 AI"可能已经知道"。规格是输入，不是可选背景。

**使用需求工具时**：`/req:dev` 命令会在开发前自动读取对应的 REQ 文档，把显式传递这一步内嵌到工作流里，不需要每次手动操作。

### 机制二：测试编码验收标准

把 REQ 的验收标准直接写成测试用例。测试是代码，任何 AI 工具在读取代码库时都会看到它。

```python
# REQ-042 验收标准：退款金额不得超过原订单金额
def test_refund_cannot_exceed_original_amount():
    ...

# REQ-042 验收标准：退款请求在 48 小时内必须处理
def test_refund_request_expires_after_48_hours():
    ...
```

这样做的效果：即使 AI 没有读 REQ 文档，测试文件已经把规格的关键约束转换成了可见的代码。任何工具读到这些测试，都能理解这些行为是有意的，而不是意外的。

**原则**：一条验收标准 = 一个测试用例。不能写成测试的验收标准，要么是写得不够具体，要么是需要拆分。

### 机制三：工具特定的上下文配置

每个 AI 工具都有"告诉它默认读什么"的配置文件。这类配置应该明确指向规格文档的位置，而不只是写代码规范。

| 工具             | 配置文件                              | 配置建议                                       |
| -------------- | --------------------------------- | ------------------------------------------ |
| Claude Code    | `CLAUDE.md`                       | 说明 `docs/requirements/` 结构，写明开发前必须读 REQ 文档 |
| Cursor         | `.cursor/rules/*.mdc`             | 用 `@docs/requirements/` 引用规格目录             |
| Windsurf       | `.windsurfrules`                  | 同上，指向规格目录                                  |
| GitHub Copilot | `.github/copilot-instructions.md` | 写明关键约束和规格位置                                |
| 任何工具           | 对话开始时手动粘贴                         | 粘贴 REQ 文档相关章节，而不是整个文档                      |

这些配置的作用是降低每次传递规格的摩擦，不是消除传递规格这一步。

***

## 漂移的来源

了解规格和代码为什么漂移，有助于在对的地方建立检查点。

**规格漂移**：代码实现后，新情况出现了，工程师直接改代码，没有同步更新 REQ 文档。几个迭代后，REQ 描述的是已经不存在的行为。

**代码漂移**：REQ 更新了，但开发分支上的代码还是旧版本，或者新的 AI 生成的代码没有读新版 REQ。

**两种漂移的共同根因**：修改一处，没有同步检查另一处。

***

## 防漂移的检查点

在两个关键时刻建立明确的检查：

**代码改变时**：修改影响到某个已有 REQ 描述的行为时，打开对应 REQ 文档确认验收标准是否还成立。不成立则更新 REQ，同步更新测试。

**REQ 改变时**：更新 REQ 后，检查对应的测试是否需要同步修改。如果有 AI 工具正在相关功能上工作，重新传入新版 REQ。

这两个检查点不依赖工具，也不需要自动化——它们是判断，不是机械步骤。

***

## 不同工具的协作边界

当一个项目里同时使用多个 AI 工具时（Claude Code 做架构分析，Cursor 做日常开发，CI 里用 AI 做代码审查），对齐的核心问题是：**谁是规格的权威来源？**

答案必须是单一的：`docs/requirements/` 里的 Markdown 文件。

每个工具都从这里读取，不维护自己的"理解版本"。工具特定的配置文件（`.cursorrules`、`CLAUDE.md`）只是告诉工具"去哪里找规格"，不是规格本身的副本。

```
docs/requirements/REQ-042.md   ← 唯一权威来源
       ↓
CLAUDE.md    → Claude Code 读取时的入口说明
.cursorrules → Cursor 读取时的引用配置
测试文件     → 验收标准的可执行形式
```

如果两个工具对同一个功能有不同的"理解"，根因是其中一个没有读最新版的 REQ，不是工具之间需要同步。

***

## 最低实践

1. 每次开发新功能前：先读 REQ，再写代码
2. 每个 REQ 的验收标准：至少对应一个测试用例
3. 修改已有行为时：检查对应 REQ 是否需要同步更新
4. 工具配置文件：写明规格目录位置，而不只是代码规范


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://zhouhao4221.gitbook.io/haiqing-docs/05-workflow/spec-code-alignment.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
