> ## Documentation Index
> Fetch the complete documentation index at: https://aicoding.cscitech.top/llms.txt
> Use this file to discover all available pages before exploring further.

# 04-开发新功能

> 用一套可验证的流程澄清需求、复用现有模式、设计接口与数据、实现跨文件功能，并在兼容性和交付前完成测试与审查。

## 用途

新增功能不是“让 Codex 写几段代码”，而是把一个业务结果安全地放进已有系统。可靠的顺序是：先把需求说成可判定的行为，再读懂项目已有的做法，随后确认接口、数据、错误和兼容性，拆成可验证的小步骤，最后实现、测试、审查和交付。

本页只讲“开发新功能”这一类任务。修复已有故障，重点是复现和根因；重构，重点是行为不变；新增功能，重点是新行为与旧行为同时成立。如果需求还不清楚，先不要让 Codex 修改文件。

本页使用一个具体案例贯穿全文：给已有的任务管理 API 增加“标记任务完成”功能。假设系统已经有任务列表和创建接口，但还没有完成状态。案例中的路径、语言和命令是示意，实际项目必须以仓库里的路由、模型、测试和脚本为准。

> 本页中的命令、界面文案和参数可能随 Codex 版本变化。请以本机 `codex --help`、项目说明和官方文档为准。参考资料：`参考/codex/14-workflows.md`、`参考/codex/34-capstone.md`、`参考/codex/13-prompting.md`。

## 一张流程图

一个完整的新功能任务，可以压缩成下面九个阶段：

```text theme={null}
需求澄清
  -> 现有模式探索
  -> 接口、数据与错误设计
  -> 分步计划
  -> 先补契约和测试
  -> 实现最小闭环
  -> 跨文件验证
  -> 兼容性与差异审查
  -> 交付说明
```

每个阶段都应该有看得见的产出。没有产出，就容易从“讨论需求”直接跳到“改代码”，最终只能依靠人工猜测来验收。

| 阶段    | 关键问题            | 应有产出           |
| ----- | --------------- | -------------- |
| 需求澄清  | 用户要完成什么？什么不算成功？ | 行为清单、非目标、验收标准  |
| 探索模式  | 项目中类似功能怎么做？     | 文件清单、调用链、约定    |
| 接口和数据 | 输入、输出、状态如何表达？   | 契约、迁移方案、错误表    |
| 分步计划  | 如何控制改动范围？       | 每步文件、验证命令、回滚点  |
| 测试设计  | 正常和失败路径怎么证明？    | 测试矩阵、回归用例      |
| 实现    | 哪个最小闭环能先跑通？     | 代码、迁移、接口接线     |
| 审查交付  | 能否合并、部署和回滚？     | diff、测试结果、风险说明 |

**原则：先让 Codex 观察和提问，再让它计划，最后才让它编辑。** 越是跨文件的功能，越需要先建立上下文，否则代理会把“项目惯例”替换成自己的通用想象。

## 01 开工前：确认工作区和安全边界

先在正确的仓库根目录操作。不要在生产目录、包含真实客户数据的目录或错误分支中试做功能。

```bash theme={null}
pwd
git status --short --branch
git branch --show-current
codex --version
```

预期输出至少能回答三件事：当前目录确实是目标项目；当前分支适合开发；工作区原本有哪些改动。

如果 `git status` 已经显示修改，不要让 Codex 顺手覆盖它们。把现有修改记下来，并在提示中明确“保留任务开始前已有改动”。如果当前分支不是任务分支，先按团队流程建立分支或工作副本。

### 先写非目标

新功能很容易不断扩张。开始前明确本次不做什么，例如：

* 不重新设计任务列表接口。
* 不迁移到新的 ORM 或 Web 框架。
* 不增加第三方依赖。
* 不改变已有创建和查询接口的响应结构。
* 不自动批量完成历史任务。
* 不提交、推送或部署，除非交付阶段明确批准。

非目标为变更画边界。它还能帮助 Codex 在发现“顺便优化”的机会时停下来报告，而不是自行扩大范围。

### 启动只读探索

探索阶段推荐让 Codex 只读。不同版本的权限选项可能不同，使用当前版本的帮助确认；核心要求是这一轮只允许读取文件、搜索文本和运行低风险检查，不允许编辑。

```text theme={null}
请先只读探索，不要修改、创建或删除任何文件，也不要提交或联网。
读取项目说明、构建脚本、相关路由、数据模型和现有测试。
最后给出：入口文件、调用链、相似功能、测试命令和需要我确认的问题。
```

**预期输出**不是代码，而是一份依据文件路径的地图。如果 Codex 一开始就提出修改而没有指出它读过什么，先要求它补充证据。

## 02 需求澄清：把一句话变成可验收行为

“增加标记完成功能”还不是开发需求。它没有说明谁能操作、任务不存在时怎样、重复操作是否幂等、列表是否显示新状态，也没有说明是否需要数据库迁移。

可以用“目标、范围、约束、验证”四件套整理需求：

| 要件 | 要回答的问题      | 案例中的写法              |
| -- | ----------- | ------------------- |
| 目标 | 用户最终能做什么？   | 用户可将自己拥有的任务标记为完成    |
| 范围 | 哪些模块和行为会改变？ | 新增完成接口、状态字段、相关测试和文档 |
| 约束 | 什么不能改变？     | 保持现有创建和列表接口兼容，不引新库  |
| 验证 | 什么结果算成功？    | 成功、未找到、无权限、重复请求均有测试 |

### 先确认名词和状态

要求 Codex 把模糊名词列成问题，而不是自行选择实现：

```text theme={null}
在修改前，请从现有代码中确认：
1. 任务的主键字段叫什么，创建者字段叫什么。
2. 任务状态目前是否已经存在，允许哪些值。
3. 当前认证信息如何进入控制器或服务层。
4. 项目使用什么迁移工具、测试框架和响应错误格式。
5. 列表接口是否会暴露新增字段，客户端是否依赖严格响应结构。

对无法从代码确定的事项列出问题，不要猜测。
```

如果业务方尚未决定，可把选项写清楚后再确认。例如“完成”可以是布尔值 `completed`，也可以是状态枚举 `pending/completed/archived`。选择应由已有模型、未来状态和查询需求决定，而不是由 Codex 方便与否决定。

### 案例的澄清结果

经过确认，案例采用以下定义：

* 已登录用户调用 `PATCH /api/tasks/{id}/complete`。
* 只有任务创建者可以操作该任务。
* 成功返回 `200` 和更新后的任务。
* 任务不存在返回 `404`。
* 任务属于其他用户时返回 `403`，不泄露额外敏感信息。
* 已完成任务再次调用仍返回 `200`，结果保持已完成，接口幂等。
* 创建接口继续接受原有请求，默认新任务为未完成。
* 列表接口在原有字段基础上增加 `completed`；如果客户端严格校验响应，先检查兼容策略。
* 不在本次功能中增加“取消完成”、批量操作、通知或筛选参数。

这份结果已经比“加一个完成按钮”更接近可实现的契约，也明确了失败处理，避免实现完成后才争论状态码。

### 把验收写成是或否

好的验收标准能由测试、命令或人工步骤给出明确答案：

```text theme={null}
- [ ] 已登录任务所有者调用完成接口得到 200。
- [ ] 响应中的 completed 为 true，持久化后再次查询仍为 true。
- [ ] 未登录请求得到项目既有的认证错误格式。
- [ ] 不存在的任务得到 404，且不写入数据。
- [ ] 其他用户的任务得到 403，且不改变任务。
- [ ] 重复调用保持成功且不重复生成副作用。
- [ ] 旧的创建、列表和详情测试仍然通过。
- [ ] 格式检查、类型检查、单元测试和项目构建通过。
```

## 03 探索现有模式：复用，不发明平行体系

新增功能最常见的返工原因，不是语法错误，而是没有遵循已有项目模式：重复造一个认证中间件、使用另一种错误格式、绕过服务层直接写数据库，或用新库解决已有工具能解决的问题。

### 推荐的探索顺序

按“从面到线”的顺序阅读：

1. 读 `README`、`AGENTS.md`、包配置和测试脚本，确认运行方式与硬性约定。
2. 找任务资源的路由、控制器、服务、模型、迁移和测试文件。
3. 找一个已有的“更新资源”或“权限检查”功能，逐层追踪调用链。
4. 找同类错误响应、事务处理、日志和测试夹具。
5. 读相关提交历史或注释，确认某些看似奇怪的兼容逻辑是否有原因。

可直接交给 Codex 的只读提示：

```text theme={null}
请探索新增任务完成接口所需的现有模式，只读不要改文件。
重点对照一个已有的任务更新接口和一个需要权限检查的接口。
请按表格输出：
- 文件路径和职责
- 请求如何进入控制器、服务和数据层
- 认证与资源所有权在哪里判断
- 成功和失败响应如何统一生成
- 现有测试如何构造用户、任务和数据库
- 建议复用的函数或模式
- 你无法确定、需要我确认的事项
每个结论都附上文件路径和符号名。
```

### 如何判断“复用”是对的

看到一个相似函数，不要只按名字复制。检查四个维度：

| 维度 | 要看什么               | 典型问题         |
| -- | ------------------ | ------------ |
| 入口 | 路由参数、HTTP 方法、认证装饰器 | 是否统一在路由层鉴权？  |
| 业务 | 服务层输入和返回值          | 权限判断是否集中？    |
| 数据 | 模型更新、事务、并发策略       | 是否使用既有更新方法？  |
| 输出 | 状态码、错误码、字段命名       | 客户端是否依赖统一格式？ |

如果项目已经有 `update_task`，完成接口可能应调用同一个服务方法，而不是再写一套 SQL。若现有服务只支持允许字段白名单，就把 `completed` 纳入白名单并补测试；不要在控制器里绕过它。

### 预期的探索报告

```text theme={null}
入口：src/routes/tasks.ts::patchTask
业务：src/services/task-service.ts::updateTask
权限：src/policies/task-policy.ts::canEdit
数据：src/models/task.ts，迁移目录 migrations/
错误：src/http/errors.ts::toResponse
测试：tests/tasks/update-task.test.ts，使用 createUser/createTask 夹具

建议：复用 updateTask 的事务和权限入口，为 completed 增加明确的输入校验；
不要在新路由中直接访问 ORM。需要确认：列表响应新增字段是否允许旧客户端忽略。
```

如果输出只有“我会创建路由、模型和测试”，说明它还没有完成探索，应继续追问。

## 04 接口设计：先定契约，再接实现

接口是客户端、服务端和测试之间的共同边界。先写出请求、响应、状态码和错误格式，能减少“后端完成了但客户端接不上”的返工。

### 案例接口契约

```http theme={null}
PATCH /api/tasks/42/complete
Authorization: Bearer <token>
Content-Type: application/json
```

本例不需要请求体。如果项目约定所有 `PATCH` 必须带 JSON，也应使用空对象 `{}`，并遵循已有约定，不要自行另创形式。

成功响应示例：

```http theme={null}
HTTP/1.1 200 OK
Content-Type: application/json
```

```json theme={null}
{
  "id": 42,
  "title": "整理发布清单",
  "completed": true,
  "createdAt": "2026-09-05T09:00:00Z"
}
```

错误响应应与项目既有格式一致。若项目使用以下结构，案例可以这样表达：

```json theme={null}
{
  "error": {
    "code": "TASK_NOT_FOUND",
    "message": "任务不存在"
  }
}
```

| 情况       | 状态码 | 错误码或行为               | 是否写入   |
| -------- | --- | -------------------- | ------ |
| 成功标记     | 200 | 返回 `completed: true` | 是      |
| 重复标记     | 200 | 返回相同完成状态             | 无重复副作用 |
| 未登录      | 401 | 沿用认证错误               | 否      |
| 无权操作     | 403 | 沿用权限错误               | 否      |
| 任务不存在    | 404 | `TASK_NOT_FOUND`     | 否      |
| 数据库暂时不可用 | 5xx | 沿用内部错误格式             | 不应部分写入 |

### 接口设计检查表

* HTTP 方法是否符合项目惯例。
* 路径参数的类型和非法值如何处理。
* 是否需要请求体；空体和缺字段是否有不同含义。
* 成功状态码是否与同类更新接口一致。
* 错误响应是否包含稳定的机器可读错误码。
* 是否会暴露资源存在性或其他敏感信息。
* 重试是否安全，重复请求是否幂等。
* 是否需要权限、限流、审计日志或事务。

不要让 Codex 用“行业惯例”替代项目证据。提示中应写“对照现有更新接口保持一致”，并要求它指出参考文件。

## 05 数据设计：默认值、迁移和旧数据

新增功能经常意味着新增字段或表。数据设计不能只看新代码能否编译，还要回答旧记录、部署顺序和回滚问题。

### 案例的数据变更

任务表增加 `completed` 字段，旧记录默认 `false`。设计时确认：

* 字段类型是布尔值还是项目既有状态枚举。
* 数据库默认值和应用层默认值是否都需要。
* 旧数据迁移是一次完成，还是需要分阶段。
* 字段是否允许为空；如果允许，业务层如何解释 `null`。
* 是否需要索引；完成状态是否用于高频筛选。
* ORM 模型序列化是否会自动暴露该字段。
* 回滚迁移会不会丢失已写入的数据。

推荐提示：

```text theme={null}
请先检查任务表、模型映射和迁移约定，提出新增 completed 字段的方案。
说明旧记录如何获得默认值、应用发布与迁移的先后关系、回滚会损失什么，
以及是否需要分阶段发布。此步骤只给方案，不修改文件。
```

### 向后兼容的迁移顺序

对已有线上数据，常见顺序是：

1. 先增加可选或带默认值的字段，让旧版本程序仍能读取。
2. 发布能写入新字段、同时兼容旧记录的应用版本。
3. 回填历史数据，并监控失败记录。
4. 确认所有读取路径不再依赖空值后，再收紧约束。

实际顺序必须结合数据库和部署系统。不要让 Codex 擅自执行生产迁移；它可以生成迁移和本地验证命令，但执行生产变更需要单独审批、备份和回滚方案。

### 数据层失败处理

如果“更新成功响应”发出前数据库写入失败，应该返回项目规定的 5xx 错误，不要返回成功。若写入包含多个表，使用已有事务边界；没有事务时，先要求 Codex 说明部分成功如何恢复。

预期的失败测试至少包括数据库约束失败、并发更新（如果系统支持并发）、迁移后读取旧记录。不要只测试内存对象被改成 `true`。

## 06 错误处理：把失败当成产品行为

新功能的质量主要体现在失败路径。让 Codex 先画错误表，再实现：

```text theme={null}
请为任务完成接口列出错误矩阵：触发条件、HTTP 状态、稳定错误码、
用户可见消息、日志字段、是否允许重试、是否发生写入。
对照项目现有错误处理中间件，不要新造响应格式。
```

### 错误分类

**输入错误**：任务 ID 不是合法格式、请求体字段类型错误。应尽早返回，不能访问不必要的数据，也不能产生写入。

**身份错误**：没有凭据、凭据过期或用户不存在。沿用认证中间件的状态码和结构，不在功能路由中重复解析令牌。

**权限错误**：用户已登录但不是任务所有者。调用既有策略函数；不要只在前端隐藏按钮。

**资源错误**：任务不存在。确认项目对“查询不到”和“无权访问”的信息披露策略，避免通过响应差异泄露敏感信息。

**依赖错误**：数据库、队列或外部服务暂时失败。遵循项目的超时、重试和日志约定；不要让客户端重复请求造成非幂等副作用。

### 错误处理的反例

```text theme={null}
try:
    task.completed = true
except Exception:
    return {"ok": false}
```

这种写法把所有错误压成一个结果，丢失状态码、错误码和日志上下文，也可能掩盖编程错误。应复用项目的异常类型和错误转换层，让不同失败保持可诊断。

### 失败时的代理行为

```text theme={null}
如果测试或构建失败，请停止扩大范围，贴出完整命令和错误摘要，
说明失败属于代码、环境、依赖还是测试假设。先提出最小修复方案，
不要删除失败测试、降低断言、跳过检查或修改无关配置。
```

如果 Codex 报告“测试通过”但没有命令、退出码或测试数量，要求它补充证据。没有证据的“通过”只是摘要，不是验收结果。

## 07 分步计划：每一步都能审、能测、能回滚

跨文件功能不应一次性实现。先用 `/plan` 或普通提示要求计划；是否使用具体命令取决于本机版本。

```text theme={null}
请根据刚才的探索结果制定实现计划，先不要修改文件。
计划必须逐步列出：目标、涉及文件、关键符号、验证命令、预期结果和回滚点。
要求尽量复用现有模式，保持旧接口兼容，不引入第三方依赖。
如果存在未决需求，先列出问题，不要用假设替代答案。
```

### 案例计划

```text theme={null}
步骤 1：确认任务状态模型、权限策略和错误格式；输出文件证据。
步骤 2：添加 completed 字段迁移和模型默认值；运行迁移检查与模型测试。
步骤 3：在服务层增加幂等的完成操作；补成功、重复、资源不存在和权限测试。
步骤 4：接入 PATCH 路由和响应序列化；补请求级测试。
步骤 5：更新列表或详情响应的契约测试；确认旧创建请求仍通过。
步骤 6：运行格式、类型、单元、集成和构建检查。
步骤 7：审查 diff、生成交付摘要；未经明确批准不提交、不推送、不部署。
```

计划要足够具体，但不必把每一行代码都预先决定。实现中如果发现已有模式与假设不同，应暂停并更新计划，而不是悄悄扩大改动。

### 什么时候需要重新规划

* 发现状态字段其实由事件表驱动。
* 权限策略不允许按任务所有者判断。
* 旧客户端会因新增响应字段失败。
* 数据迁移需要停机或分阶段发布。
* 一个接口需要同时改动公共 SDK、后台任务和文档。

这些是需求边界发生变化的信号。让 Codex 报告影响范围，并由你确认新方案。

## 08 先写契约和测试：给新行为上锁

测试不是实现之后的装饰。先写测试可以固定需求，也能让 Codex 在实现中自我验证。测试应遵循项目已有测试框架、夹具、命名和数据库清理方式。

### 测试矩阵

| 层次   | 测试内容       | 案例预期          |
| ---- | ---------- | ------------- |
| 服务单元 | 完成操作的业务规则  | 所有者成功，重复调用幂等  |
| 权限   | 不同用户操作     | 返回 403，不写入    |
| 资源   | 不存在的 ID    | 返回 404，不写入    |
| 请求集成 | 路由、认证、序列化  | 真实状态码和响应格式    |
| 数据   | 迁移和持久化     | 旧记录默认未完成，新值可读 |
| 回归   | 旧接口        | 创建、列表、详情行为不变  |
| 构建   | 类型、打包、生成代码 | 退出码为 0        |

### 先让测试失败

在功能尚未实现时，允许契约测试先失败，但要确认失败原因是“路由或字段尚不存在”，而不是测试环境坏了。失败测试应具有明确的预期：

```text theme={null}
测试：任务所有者调用 PATCH /api/tasks/42/complete
预期：200，响应 completed=true，重新查询仍为 true

测试：其他用户调用相同接口
预期：403，任务值保持 false

测试：重复调用
预期：第二次仍为 200，不产生重复事件或重复通知
```

如果 Codex 提议通过放宽断言、跳过测试或把测试改成“只要不是 500 就算成功”，应拒绝。测试必须锁定业务行为，而不是迎合当前实现。

## 09 实现：从数据层到入口逐步接线

实现顺序应服从项目架构。常见顺序是数据模型和迁移、业务服务、路由控制器、序列化和文档；有些项目先由接口契约驱动，按已有模式调整即可。

### 第一步：数据和模型

让 Codex 只完成数据层，并立即运行数据层测试。检查：

* 新字段默认值是否覆盖旧记录。
* ORM 的创建和更新白名单是否同步。
* 序列化字段名是否与 API 契约一致。
* 迁移是否可重复执行或由工具正确标记。
* 回滚迁移是否有明确的数据损失说明。

预期结果：旧的创建和查询测试仍通过，模型可以保存和读取 `completed`。

### 第二步：业务服务

服务层负责业务规则，不应依赖 HTTP 请求对象。它应接收用户身份和任务 ID，执行资源查找、权限判断、幂等更新，并返回项目规定的结果或异常。

```text theme={null}
现在只实现服务层完成操作，暂不接路由。
复用现有任务更新、权限和事务模式。
完成后只运行服务层相关测试，并报告新增和未通过的用例。
```

预期结果：服务层测试覆盖所有者、重复操作、其他用户、不存在任务和数据库失败。

### 第三步：路由和响应

路由只负责解析参数、调用认证和服务、转换响应。检查它是否错误地把权限判断移到了控制器，是否把异常吞掉，是否返回了与其他接口不同的 JSON 结构。

预期成功输出：

```text theme={null}
PATCH /api/tasks/42/complete 200
{
  "id": 42,
  "completed": true
}
```

预期失败输出：

```text theme={null}
PATCH /api/tasks/999/complete 404
{
  "error": {"code": "TASK_NOT_FOUND", "message": "任务不存在"}
}
```

实际字段和消息必须服从项目现有格式。示例中的“预期”是行为说明，不是要求复制文本。

### 第四步：客户端或界面

如果项目包含前端，再接按钮、状态展示和加载错误。界面按钮不是权限边界；即使按钮被隐藏，服务端仍必须拒绝越权请求。

检查三种状态：

* 成功后按钮、标签和列表状态同步更新。
* 请求进行中禁止重复提交或明确显示处理中。
* 401、403、404 和 5xx 显示符合产品约定的消息，并保留重试入口或刷新路径。

如果 UI 需要新增 API 字段，先确认类型定义、客户端缓存和 mock 响应同步更新。不要只改界面让类型检查失去意义。

## 10 跨文件变更：维护影响清单

跨文件很正常，但“跨文件”不等于“可以随便改”。维护影响清单，逐项说明为什么要改：

| 文件类别   | 可能变更     | 审查重点        |
| ------ | -------- | ----------- |
| 迁移     | 新字段或表    | 默认值、回滚、部署顺序 |
| 模型/类型  | 字段和允许更新项 | 空值、序列化、类型兼容 |
| 服务     | 新业务操作    | 权限、事务、幂等    |
| 路由     | 新入口      | 参数、认证、状态码   |
| 前端     | 按钮和状态    | 加载、失败、缓存    |
| 测试     | 单元和集成用例  | 正常、边界、旧行为   |
| 文档/SDK | 契约和示例    | 与实际接口一致     |
| 配置     | 仅必要的开关   | 默认值和敏感信息    |

要求 Codex 在每次阶段结束时汇报：

```text theme={null}
本阶段改动文件：
- path/to/file: 原因

未改动但检查过的文件：
- path/to/related-file: 为什么不需要改

下一步：...
验证：命令、退出码、测试数量
```

如果出现未计划的新文件，先问“为什么需要它”。尤其注意临时脚本、生成物、锁文件和配置文件是否真的属于交付。

## 11 兼容性：新功能不能破坏旧用户

兼容性检查要覆盖接口、数据、客户端和部署，而不只是“旧测试全绿”。

### API 兼容

* 旧请求是否仍被接受。
* 旧响应字段和类型是否保持不变。
* 新增字段是否会让严格解析客户端失败。
* 状态码是否改变了已有错误语义。
* 是否需要版本化路径或能力协商。

### 数据兼容

* 旧记录读取是否安全。
* 新旧应用版本短暂并存时是否互相可用。
* 回滚应用后，新字段写入如何处理。
* 数据库迁移失败时是否有停止条件和恢复步骤。

### 行为兼容

* 默认新任务仍是未完成。
* 列表排序和分页不因新增字段改变。
* 权限边界与既有更新操作一致。
* 重试不会生成重复事件、通知或审计记录。

```text theme={null}
请对照任务创建、列表、详情和更新的现有测试，列出本功能可能破坏的兼容性。
每项给出证据、风险等级、测试或迁移措施。没有证据的结论标为“待确认”。
```

## 12 验证：从小到大运行检查

按成本和反馈速度从小到大：

1. 格式化和静态检查。
2. 新增服务或组件的单元测试。
3. 路由或 API 集成测试。
4. 相关模块回归测试。
5. 类型检查和生成代码检查。
6. 全量测试和构建。
7. 必要时在临时环境做人工接口或 UI 验证。

```text theme={null}
请按项目已有脚本从快到慢运行验证。
每条命令报告：命令、退出码、测试数量、失败摘要和是否修改了文件。
任何失败都先停下来分类，不要跳过、删除或弱化检查。
```

### 预期验证报告

```text theme={null}
格式检查：通过，退出码 0
服务测试：通过，12 passed
API 测试：通过，8 passed
回归测试：通过，旧接口 31 passed
类型检查：通过，退出码 0
构建：通过，退出码 0
```

数量和格式会随项目变化。关键是报告可复核，且没有把“没有运行”写成“通过”。

### 验证失败怎么办

**测试失败**：保留完整错误、定位到断言或堆栈，判断是实现错误、测试夹具错误还是环境问题。实现错误应修代码；测试假设错误要先说明并确认；环境问题要给出重现命令。

**类型失败**：先检查公共类型、序列化和 mock 是否同步，不要直接加 `any` 或关闭严格检查。

**构建失败**：确认生成步骤、依赖和环境版本。未经确认不要升级依赖或改锁文件。

**迁移失败**：停止应用层扩大改动，保存数据库错误和迁移状态，按项目回滚文档处理。不要手工删除迁移记录。

**接口手测失败**：记录请求、响应码、响应体和服务端日志关联 ID；不要只说“按钮没反应”。

## 13 Diff 审查：看代码之外的变化

测试全绿仍需审查 diff。Codex 可以帮忙总结，但最终要自己查看实际差异：

```bash theme={null}
git status --short
git diff --stat
git diff --check
git diff
```

重点审查：

* 是否只修改了计划中的文件。
* 是否出现无关格式化、重命名或依赖升级。
* 是否把密钥、令牌、真实数据或本地路径写入文件。
* 错误路径是否真的没有写入。
* 权限检查是否在服务端执行。
* 重复请求是否幂等。
* 迁移默认值是否覆盖旧数据。
* 测试是否测试行为，而不是只测试 mock 被调用。
* 公共接口的响应、类型和文档是否一致。
* 日志是否包含足够上下文但没有敏感信息。

```text theme={null}
请只审查当前 diff，不修改文件。
按严重程度列出功能遗漏、权限问题、数据迁移风险、兼容性风险、
错误处理缺口和测试缺口。每条引用文件和符号，并说明如何验证。
如果没有发现问题，也要列出未覆盖的假设。
```

预期审查输出应区分“必须修复”和“可后续改进”。不要因为审查报告很长就自动接受，也不要因为没有报告就认为没有风险。

## 14 交付：让别人能运行、审查和恢复

交付不是一句“已完成”。应提供足够信息，让接手者知道改了什么、怎么验证、怎样发布和怎样回滚。

```text theme={null}
功能：新增任务完成接口
变更文件：列出实际路径及每个文件的原因
接口：方法、路径、认证要求、成功和失败状态
数据：迁移名称、默认值、执行顺序、回滚限制
验证：命令、退出码、测试数量
兼容性：旧接口和旧数据的结论
未验证：例如真实外部服务未连接、生产迁移未执行
风险：并发、缓存、客户端版本或权限方面的剩余风险
回滚：代码回滚、迁移回滚和数据恢复步骤
```

### 提交边界

默认让 Codex 停在交付摘要，不自动提交、推送或部署。若团队允许提交，也要先看 `git status` 和 `git diff`，再确认暂存范围与提交信息。提交前检查是否混入任务开始前已有改动。

```text theme={null}
请先展示最终 diff、测试结果和交付摘要。
不要执行 git add、git commit、git push 或部署。
等我确认后再进行下一步。
```

如果明确授权提交，仍应只暂存相关文件；如果授权发布，先确认目标环境、迁移顺序、监控指标和回滚开关。生产操作需要单独审批和凭据管理，不能把本地测试通过当成发布授权。

## 15 完整案例：从“加个完成按钮”到交付

下面把前面的步骤合成一段可以改写后使用的任务提示。它不是让 Codex 跳过探索，而是把目标和边界写清楚。

```text theme={null}
我要给现有任务管理系统增加“标记任务完成”功能。

背景：目前用户可以创建、查看和更新自己的任务，但没有明确的完成操作。

目标：已登录用户可以调用 PATCH /api/tasks/{id}/complete，将自己拥有的任务
标记为完成。成功返回现有任务响应格式，并包含 completed=true。

范围：检查并按现有模式修改任务模型/迁移、服务层、路由、响应类型、相关前端
和测试。先找出真实文件路径再修改。保留项目开始前已有的工作区改动。

业务规则：
- 新任务默认 completed=false。
- 任务所有者成功得到 200。
- 重复调用保持幂等，不重复生成副作用。
- 任务不存在得到项目既有的 404 错误格式。
- 其他用户操作得到项目既有的 403 错误格式。
- 未登录沿用现有认证错误。

兼容性：已有创建、列表、详情和更新请求继续通过；不要改变旧字段含义，
不要引入第三方依赖。确认旧客户端能否接受新增 completed 字段。

工作方式：
1. 先只读探索 README、项目规则、相似更新接口、权限策略、迁移、类型和测试。
2. 输出文件地图、调用链、复用点和未决问题，暂不编辑。
3. 得到确认后给出分步计划，每步列文件、验证命令和回滚点。
4. 先补服务和 API 契约测试，再实现最小闭环。
5. 分阶段运行格式、类型、单元、集成、回归和构建检查。
6. 任何失败都贴命令和错误摘要，停止扩大范围；不要删除测试、跳过检查、
   修改无关配置或降低断言。
7. 最后展示 git status、git diff --stat、git diff --check、完整测试结果和交付摘要。
8. 不要提交、推送、部署或执行生产迁移。
```

### 案例的阶段性预期输出

**探索阶段**：列出任务路由、更新服务、权限策略、模型、迁移和测试夹具，并指出复用哪个现有更新操作。若无法确认响应兼容性，列为问题。

**计划阶段**：至少包含迁移、服务、路由和测试四个边界，每步有可执行验证。计划不应出现“重写整个任务模块”之类无边界描述。

**实现阶段**：测试从“路由不存在”或“字段不存在”失败，到正确行为通过；旧测试不应无理由变化。每一阶段的 diff 文件都与计划相符。

**最终阶段**：成功请求得到 `200` 和 `completed=true`；不存在、无权、未登录分别得到稳定错误；重复请求不会产生重复副作用；全量检查通过。

### 案例的失败处理

如果迁移工具不允许安全默认值，停止实现路由，先补迁移方案和旧数据策略。

如果列表接口的严格客户端因新增字段失败，停止前端接线，确认是否要版本化、使用已有扩展字段机制，或先更新客户端。

如果权限测试显示“其他用户”能完成任务，优先修服务层权限边界，不要只禁用前端按钮。

如果重复请求创建了两条完成事件，保留失败测试，检查幂等键、状态转换和事务边界；不要把第二次请求简单改成静默返回而不确认副作用语义。

如果全量构建失败但相关测试通过，按构建错误定位类型、生成文件或打包入口；不能以“功能测试通过”交付一个无法构建的版本。

如果发现代理修改了计划外的配置、锁文件或其他模块，先停止，查看完整 diff，说明每项是否必要；不要覆盖任务开始前已有的用户修改。

## 16 可复用提示词模板

### 需求澄清模板

```text theme={null}
我要实现：[用户可观察的功能]
背景：[当前行为和问题]
目标：[成功后具体发生什么]
范围：[允许修改的模块/文件]
非目标：[本次明确不做的事]
约束：[接口、依赖、性能、安全、兼容性要求]
验收：[可测的成功和失败标准]

先列出你无法从仓库确定的问题，不要猜测，不要修改文件。
```

### 现有模式探索模板

```text theme={null}
只读检查与目标功能最相似的入口、服务、模型、错误处理和测试。
输出真实文件路径、符号、调用链、可复用模式和风险。
不要创建或修改文件；结论附证据。
```

### 计划模板

```text theme={null}
给出分步实现计划。每步包含：目标、文件和符号、验证命令、预期输出、
失败处理和回滚点。保持旧行为兼容，优先复用现有模式。
```

### 实现模板

```text theme={null}
只实现计划中的第 N 步。
先读取该步涉及的现有代码，保持命名、错误格式和测试风格一致。
完成后运行该步验证，报告改动文件、命令、退出码和未决问题。
不要扩大范围，不要提交。
```

### 最终审查模板

```text theme={null}
只审查当前 diff，不修改文件。
检查需求覆盖、权限、接口契约、数据迁移、错误处理、并发/幂等、兼容性、
测试质量和敏感信息。按严重程度列出问题并引用文件和符号。
同时列出已验证项、未验证假设和建议的交付/回滚步骤。
```

## 17 常见失误与纠正

| 失误          | 后果             | 纠正                   |
| ----------- | -------------- | -------------------- |
| 只说“加个功能”    | Codex 自行猜接口和范围 | 写目标、范围、约束、验证         |
| 不读相似代码      | 产生第二套架构和错误格式   | 点名现有入口、服务和测试         |
| 先改路由后想数据    | 接口能调但不能持久化     | 先确认模型、迁移和默认值         |
| 只测成功路径      | 权限和不存在资源暴露缺陷   | 先列失败矩阵并写测试           |
| 只改前端按钮      | 服务端被直接越权调用     | 在服务端强制认证和权限          |
| 一次改十几个模块    | 无法定位回归原因       | 拆成每步可验证的计划           |
| 测试失败就删断言    | “通过”但行为错误      | 保留失败，修实现或澄清需求        |
| 顺手升级依赖      | 引入不必要兼容风险      | 依赖变更单独说明并批准          |
| 忽略旧数据       | 部署后读取空值或崩溃     | 设计默认值、回填和发布顺序        |
| 只看 Codex 总结 | 计划外文件混入交付      | 亲自看 status、stat、diff |
| 未经确认直接提交部署  | 难以撤回且越过审批      | 停在交付摘要，明确放行          |

## 18 小结

开发新功能的核心不是提示词更长，而是每一步都减少一个未验证的假设：

1. 用目标、范围、约束、验证把需求变成可判定行为。
2. 先读项目规则和相似功能，复用入口、权限、错误、数据和测试模式。
3. 在实现前确定接口契约、状态、默认值、迁移、失败处理和幂等语义。
4. 把跨文件任务拆成每步有文件、有命令、有预期输出和回滚点的计划。
5. 先用测试固定正常路径、边界路径、权限路径、持久化和旧行为。
6. 从数据层到服务、路由、客户端逐步接线，每步都检查 diff 和验证结果。
7. 用兼容性清单审查旧请求、旧数据、并存版本和回滚影响。
8. 交付时给出变更、接口、测试、未验证项、风险和回滚，而不是只说“完成”。

可以把整页压缩成一句工作指令：**先问清要做成什么，再证明项目通常怎么做；先定契约和失败行为，再分步实现；先看证据和测试，再交付。**

下一页 [05-重构与补测试](/04-日常工作流/05-重构与补测试) 会转向“行为不变”的改造任务；完成新功能后，如果发现重复逻辑或测试薄弱，再用重构流程处理，不要把两类目标混在同一次无边界修改里。
