用途
新增功能不是“让 Codex 写几段代码”,而是把一个业务结果安全地放进已有系统。可靠的顺序是:先把需求说成可判定的行为,再读懂项目已有的做法,随后确认接口、数据、错误和兼容性,拆成可验证的小步骤,最后实现、测试、审查和交付。 本页只讲“开发新功能”这一类任务。修复已有故障,重点是复现和根因;重构,重点是行为不变;新增功能,重点是新行为与旧行为同时成立。如果需求还不清楚,先不要让 Codex 修改文件。 本页使用一个具体案例贯穿全文:给已有的任务管理 API 增加“标记任务完成”功能。假设系统已经有任务列表和创建接口,但还没有完成状态。案例中的路径、语言和命令是示意,实际项目必须以仓库里的路由、模型、测试和脚本为准。本页中的命令、界面文案和参数可能随 Codex 版本变化。请以本机codex --help、项目说明和官方文档为准。参考资料:参考/codex/14-workflows.md、参考/codex/34-capstone.md、参考/codex/13-prompting.md。
一张流程图
一个完整的新功能任务,可以压缩成下面九个阶段:
原则:先让 Codex 观察和提问,再让它计划,最后才让它编辑。 越是跨文件的功能,越需要先建立上下文,否则代理会把“项目惯例”替换成自己的通用想象。
01 开工前:确认工作区和安全边界
先在正确的仓库根目录操作。不要在生产目录、包含真实客户数据的目录或错误分支中试做功能。git status 已经显示修改,不要让 Codex 顺手覆盖它们。把现有修改记下来,并在提示中明确“保留任务开始前已有改动”。如果当前分支不是任务分支,先按团队流程建立分支或工作副本。
先写非目标
新功能很容易不断扩张。开始前明确本次不做什么,例如:- 不重新设计任务列表接口。
- 不迁移到新的 ORM 或 Web 框架。
- 不增加第三方依赖。
- 不改变已有创建和查询接口的响应结构。
- 不自动批量完成历史任务。
- 不提交、推送或部署,除非交付阶段明确批准。
启动只读探索
探索阶段推荐让 Codex 只读。不同版本的权限选项可能不同,使用当前版本的帮助确认;核心要求是这一轮只允许读取文件、搜索文本和运行低风险检查,不允许编辑。02 需求澄清:把一句话变成可验收行为
“增加标记完成功能”还不是开发需求。它没有说明谁能操作、任务不存在时怎样、重复操作是否幂等、列表是否显示新状态,也没有说明是否需要数据库迁移。 可以用“目标、范围、约束、验证”四件套整理需求:先确认名词和状态
要求 Codex 把模糊名词列成问题,而不是自行选择实现:completed,也可以是状态枚举 pending/completed/archived。选择应由已有模型、未来状态和查询需求决定,而不是由 Codex 方便与否决定。
案例的澄清结果
经过确认,案例采用以下定义:- 已登录用户调用
PATCH /api/tasks/{id}/complete。 - 只有任务创建者可以操作该任务。
- 成功返回
200和更新后的任务。 - 任务不存在返回
404。 - 任务属于其他用户时返回
403,不泄露额外敏感信息。 - 已完成任务再次调用仍返回
200,结果保持已完成,接口幂等。 - 创建接口继续接受原有请求,默认新任务为未完成。
- 列表接口在原有字段基础上增加
completed;如果客户端严格校验响应,先检查兼容策略。 - 不在本次功能中增加“取消完成”、批量操作、通知或筛选参数。
把验收写成是或否
好的验收标准能由测试、命令或人工步骤给出明确答案:03 探索现有模式:复用,不发明平行体系
新增功能最常见的返工原因,不是语法错误,而是没有遵循已有项目模式:重复造一个认证中间件、使用另一种错误格式、绕过服务层直接写数据库,或用新库解决已有工具能解决的问题。推荐的探索顺序
按“从面到线”的顺序阅读:- 读
README、AGENTS.md、包配置和测试脚本,确认运行方式与硬性约定。 - 找任务资源的路由、控制器、服务、模型、迁移和测试文件。
- 找一个已有的“更新资源”或“权限检查”功能,逐层追踪调用链。
- 找同类错误响应、事务处理、日志和测试夹具。
- 读相关提交历史或注释,确认某些看似奇怪的兼容逻辑是否有原因。
如何判断“复用”是对的
看到一个相似函数,不要只按名字复制。检查四个维度:
如果项目已经有
update_task,完成接口可能应调用同一个服务方法,而不是再写一套 SQL。若现有服务只支持允许字段白名单,就把 completed 纳入白名单并补测试;不要在控制器里绕过它。
预期的探索报告
04 接口设计:先定契约,再接实现
接口是客户端、服务端和测试之间的共同边界。先写出请求、响应、状态码和错误格式,能减少“后端完成了但客户端接不上”的返工。案例接口契约
PATCH 必须带 JSON,也应使用空对象 {},并遵循已有约定,不要自行另创形式。
成功响应示例:
接口设计检查表
- HTTP 方法是否符合项目惯例。
- 路径参数的类型和非法值如何处理。
- 是否需要请求体;空体和缺字段是否有不同含义。
- 成功状态码是否与同类更新接口一致。
- 错误响应是否包含稳定的机器可读错误码。
- 是否会暴露资源存在性或其他敏感信息。
- 重试是否安全,重复请求是否幂等。
- 是否需要权限、限流、审计日志或事务。
05 数据设计:默认值、迁移和旧数据
新增功能经常意味着新增字段或表。数据设计不能只看新代码能否编译,还要回答旧记录、部署顺序和回滚问题。案例的数据变更
任务表增加completed 字段,旧记录默认 false。设计时确认:
- 字段类型是布尔值还是项目既有状态枚举。
- 数据库默认值和应用层默认值是否都需要。
- 旧数据迁移是一次完成,还是需要分阶段。
- 字段是否允许为空;如果允许,业务层如何解释
null。 - 是否需要索引;完成状态是否用于高频筛选。
- ORM 模型序列化是否会自动暴露该字段。
- 回滚迁移会不会丢失已写入的数据。
向后兼容的迁移顺序
对已有线上数据,常见顺序是:- 先增加可选或带默认值的字段,让旧版本程序仍能读取。
- 发布能写入新字段、同时兼容旧记录的应用版本。
- 回填历史数据,并监控失败记录。
- 确认所有读取路径不再依赖空值后,再收紧约束。
数据层失败处理
如果“更新成功响应”发出前数据库写入失败,应该返回项目规定的 5xx 错误,不要返回成功。若写入包含多个表,使用已有事务边界;没有事务时,先要求 Codex 说明部分成功如何恢复。 预期的失败测试至少包括数据库约束失败、并发更新(如果系统支持并发)、迁移后读取旧记录。不要只测试内存对象被改成true。
06 错误处理:把失败当成产品行为
新功能的质量主要体现在失败路径。让 Codex 先画错误表,再实现:错误分类
输入错误:任务 ID 不是合法格式、请求体字段类型错误。应尽早返回,不能访问不必要的数据,也不能产生写入。 身份错误:没有凭据、凭据过期或用户不存在。沿用认证中间件的状态码和结构,不在功能路由中重复解析令牌。 权限错误:用户已登录但不是任务所有者。调用既有策略函数;不要只在前端隐藏按钮。 资源错误:任务不存在。确认项目对“查询不到”和“无权访问”的信息披露策略,避免通过响应差异泄露敏感信息。 依赖错误:数据库、队列或外部服务暂时失败。遵循项目的超时、重试和日志约定;不要让客户端重复请求造成非幂等副作用。错误处理的反例
失败时的代理行为
07 分步计划:每一步都能审、能测、能回滚
跨文件功能不应一次性实现。先用/plan 或普通提示要求计划;是否使用具体命令取决于本机版本。
案例计划
什么时候需要重新规划
- 发现状态字段其实由事件表驱动。
- 权限策略不允许按任务所有者判断。
- 旧客户端会因新增响应字段失败。
- 数据迁移需要停机或分阶段发布。
- 一个接口需要同时改动公共 SDK、后台任务和文档。
08 先写契约和测试:给新行为上锁
测试不是实现之后的装饰。先写测试可以固定需求,也能让 Codex 在实现中自我验证。测试应遵循项目已有测试框架、夹具、命名和数据库清理方式。测试矩阵
先让测试失败
在功能尚未实现时,允许契约测试先失败,但要确认失败原因是“路由或字段尚不存在”,而不是测试环境坏了。失败测试应具有明确的预期:09 实现:从数据层到入口逐步接线
实现顺序应服从项目架构。常见顺序是数据模型和迁移、业务服务、路由控制器、序列化和文档;有些项目先由接口契约驱动,按已有模式调整即可。第一步:数据和模型
让 Codex 只完成数据层,并立即运行数据层测试。检查:- 新字段默认值是否覆盖旧记录。
- ORM 的创建和更新白名单是否同步。
- 序列化字段名是否与 API 契约一致。
- 迁移是否可重复执行或由工具正确标记。
- 回滚迁移是否有明确的数据损失说明。
completed。
第二步:业务服务
服务层负责业务规则,不应依赖 HTTP 请求对象。它应接收用户身份和任务 ID,执行资源查找、权限判断、幂等更新,并返回项目规定的结果或异常。第三步:路由和响应
路由只负责解析参数、调用认证和服务、转换响应。检查它是否错误地把权限判断移到了控制器,是否把异常吞掉,是否返回了与其他接口不同的 JSON 结构。 预期成功输出:第四步:客户端或界面
如果项目包含前端,再接按钮、状态展示和加载错误。界面按钮不是权限边界;即使按钮被隐藏,服务端仍必须拒绝越权请求。 检查三种状态:- 成功后按钮、标签和列表状态同步更新。
- 请求进行中禁止重复提交或明确显示处理中。
- 401、403、404 和 5xx 显示符合产品约定的消息,并保留重试入口或刷新路径。
10 跨文件变更:维护影响清单
跨文件很正常,但“跨文件”不等于“可以随便改”。维护影响清单,逐项说明为什么要改:
要求 Codex 在每次阶段结束时汇报:
11 兼容性:新功能不能破坏旧用户
兼容性检查要覆盖接口、数据、客户端和部署,而不只是“旧测试全绿”。API 兼容
- 旧请求是否仍被接受。
- 旧响应字段和类型是否保持不变。
- 新增字段是否会让严格解析客户端失败。
- 状态码是否改变了已有错误语义。
- 是否需要版本化路径或能力协商。
数据兼容
- 旧记录读取是否安全。
- 新旧应用版本短暂并存时是否互相可用。
- 回滚应用后,新字段写入如何处理。
- 数据库迁移失败时是否有停止条件和恢复步骤。
行为兼容
- 默认新任务仍是未完成。
- 列表排序和分页不因新增字段改变。
- 权限边界与既有更新操作一致。
- 重试不会生成重复事件、通知或审计记录。
12 验证:从小到大运行检查
按成本和反馈速度从小到大:- 格式化和静态检查。
- 新增服务或组件的单元测试。
- 路由或 API 集成测试。
- 相关模块回归测试。
- 类型检查和生成代码检查。
- 全量测试和构建。
- 必要时在临时环境做人工接口或 UI 验证。
预期验证报告
验证失败怎么办
测试失败:保留完整错误、定位到断言或堆栈,判断是实现错误、测试夹具错误还是环境问题。实现错误应修代码;测试假设错误要先说明并确认;环境问题要给出重现命令。 类型失败:先检查公共类型、序列化和 mock 是否同步,不要直接加any 或关闭严格检查。
构建失败:确认生成步骤、依赖和环境版本。未经确认不要升级依赖或改锁文件。
迁移失败:停止应用层扩大改动,保存数据库错误和迁移状态,按项目回滚文档处理。不要手工删除迁移记录。
接口手测失败:记录请求、响应码、响应体和服务端日志关联 ID;不要只说“按钮没反应”。
13 Diff 审查:看代码之外的变化
测试全绿仍需审查 diff。Codex 可以帮忙总结,但最终要自己查看实际差异:- 是否只修改了计划中的文件。
- 是否出现无关格式化、重命名或依赖升级。
- 是否把密钥、令牌、真实数据或本地路径写入文件。
- 错误路径是否真的没有写入。
- 权限检查是否在服务端执行。
- 重复请求是否幂等。
- 迁移默认值是否覆盖旧数据。
- 测试是否测试行为,而不是只测试 mock 被调用。
- 公共接口的响应、类型和文档是否一致。
- 日志是否包含足够上下文但没有敏感信息。
14 交付:让别人能运行、审查和恢复
交付不是一句“已完成”。应提供足够信息,让接手者知道改了什么、怎么验证、怎样发布和怎样回滚。提交边界
默认让 Codex 停在交付摘要,不自动提交、推送或部署。若团队允许提交,也要先看git status 和 git diff,再确认暂存范围与提交信息。提交前检查是否混入任务开始前已有改动。
15 完整案例:从“加个完成按钮”到交付
下面把前面的步骤合成一段可以改写后使用的任务提示。它不是让 Codex 跳过探索,而是把目标和边界写清楚。案例的阶段性预期输出
探索阶段:列出任务路由、更新服务、权限策略、模型、迁移和测试夹具,并指出复用哪个现有更新操作。若无法确认响应兼容性,列为问题。 计划阶段:至少包含迁移、服务、路由和测试四个边界,每步有可执行验证。计划不应出现“重写整个任务模块”之类无边界描述。 实现阶段:测试从“路由不存在”或“字段不存在”失败,到正确行为通过;旧测试不应无理由变化。每一阶段的 diff 文件都与计划相符。 最终阶段:成功请求得到200 和 completed=true;不存在、无权、未登录分别得到稳定错误;重复请求不会产生重复副作用;全量检查通过。
案例的失败处理
如果迁移工具不允许安全默认值,停止实现路由,先补迁移方案和旧数据策略。 如果列表接口的严格客户端因新增字段失败,停止前端接线,确认是否要版本化、使用已有扩展字段机制,或先更新客户端。 如果权限测试显示“其他用户”能完成任务,优先修服务层权限边界,不要只禁用前端按钮。 如果重复请求创建了两条完成事件,保留失败测试,检查幂等键、状态转换和事务边界;不要把第二次请求简单改成静默返回而不确认副作用语义。 如果全量构建失败但相关测试通过,按构建错误定位类型、生成文件或打包入口;不能以“功能测试通过”交付一个无法构建的版本。 如果发现代理修改了计划外的配置、锁文件或其他模块,先停止,查看完整 diff,说明每项是否必要;不要覆盖任务开始前已有的用户修改。16 可复用提示词模板
需求澄清模板
现有模式探索模板
计划模板
实现模板
最终审查模板
17 常见失误与纠正
18 小结
开发新功能的核心不是提示词更长,而是每一步都减少一个未验证的假设:- 用目标、范围、约束、验证把需求变成可判定行为。
- 先读项目规则和相似功能,复用入口、权限、错误、数据和测试模式。
- 在实现前确定接口契约、状态、默认值、迁移、失败处理和幂等语义。
- 把跨文件任务拆成每步有文件、有命令、有预期输出和回滚点的计划。
- 先用测试固定正常路径、边界路径、权限路径、持久化和旧行为。
- 从数据层到服务、路由、客户端逐步接线,每步都检查 diff 和验证结果。
- 用兼容性清单审查旧请求、旧数据、并存版本和回滚影响。
- 交付时给出变更、接口、测试、未验证项、风险和回滚,而不是只说“完成”。