> ## 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.

# 01-提示词四件套

> 用目标、范围、约束和验证组织 Codex 任务，提供足够上下文、拆分复杂工作并形成可验收的交付闭环。

## 这页解决什么问题

“帮我改一下”“这个报错修一下”“加个功能”都像任务，实际上缺少 Codex 做出正确决定所需的信息。信息不完整时，代理会自行猜测文件、行为、技术方案和完成标准；即使最后能运行，也可能改错地方、扩大范围，或者遗漏边界条件。

这页提供一套可反复使用的提问方法：

* **目标**：任务完成后，用户或系统应该得到什么可观察的结果。
* **范围**：允许检查和修改哪些文件、函数、接口或环境。
* **约束**：哪些行为、依赖、接口、数据和权限必须保持不变。
* **验证**：用什么命令、测试、请求、截图或人工步骤证明已经完成。

四件套不是一段固定模板，也不是“把代码全部贴给模型”。它是一种决策顺序：先定义结果，再限定边界，随后补充限制，最后提供可运行的证据。每项都尽量写成可以核对的事实。

> 本页的命令、斜杠命令和配置行为以本机 Codex 版本为准。先运行 `codex --help`，需要时再查看对应子命令的帮助。本文不要求提交、推送或发布改动。

## 先看一个完整闭环

假设你发现订单详情页在接口返回空数组时显示“加载中”。不要直接输入“修一下订单页面”。可以先写成：

```text theme={null}
目标：当订单接口成功返回空数组时，页面显示“暂无订单”，并保留重新加载按钮；加载中状态只在请求尚未结束时显示。
范围：先检查订单详情页组件、请求封装和已有页面测试；优先修改 src/pages/orders/OrderDetail.tsx 及其直接测试文件。
约束：保持接口路径、响应类型和现有权限判断不变；不新增依赖；不要修改其他页面的空状态文案。
验证：补充空数组和请求失败测试，运行 pnpm test -- OrderDetail；再运行 pnpm lint。完成后报告修改文件、测试输出和未验证事项，不要提交。
```

这段话给了 Codex 四种不同的信息：要达成的用户可见行为、先后排查的范围、不能改变的合同、可以产生通过或失败结果的检查。它仍然允许代理阅读代码后调整具体实现，但不允许代理替你决定需求本身。

## 01 模糊需求与高质量需求

### 模糊不等于简洁

短句只有在双方共享足够背景时才有效。同一个会话里刚刚讨论过文件、复现步骤和验收标准，后续说“按刚才方案继续”可能足够；新会话、陌生仓库或多人交接时，这句话就不够。

下面的左列缺少的是“决定空间”，不是字数：

| 场景   | 模糊需求            | 高质量需求                                                                                                                                      |
| ---- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| 修复错误 | `登录接口挂了，修一下`    | `用户在会话过期后调用 POST /api/login 返回 500。先读取 src/auth/session.ts 和相关测试，确认能复现后修复 token 刷新分支；保持响应 JSON 结构不变，补过期会话测试，运行 pnpm test -- auth。`         |
| 增加功能 | `加个导出功能`        | `在 report service 增加 JSON 导出，复用现有 Report 类型和 CSV 导出的字段顺序；只改 src/report/ 和对应测试，不引新依赖；验收为导出的 JSON 可被现有导入器读取，运行 pytest tests/test_report.py。` |
| 性能优化 | `这个函数优化下`       | `将 src/search/index.ts 的 search 在 10,000 条固定数据上的耗时从当前基线降低到 200ms 内；不改函数签名、排序规则和分页结果；先记录基线，再改实现，运行指定性能测试和完整单测。`                             |
| 写测试  | `给 parser 加点测试` | `为 parser.py 的 parse_date 增加空字符串、闰年、非法月份和时区后缀测试；沿用 tests/ 中的 pytest 风格，不 mock 标准库解析器；运行 pytest tests/test_parser.py。`                      |
| 页面调整 | `按钮位置不对`        | `在截图所示的 390px 宽视口中，把“保存”按钮放在表单底部且不遮挡错误提示；保留桌面布局和键盘焦点顺序；检查现有组件 CSS、提供的截图，运行前端测试并在 390px 和 1440px 视口人工确认。`                                   |
| 代码理解 | `这个模块怎么写成这样`    | `只读 src/transform/ 及最近五次相关提交，总结输入输出、主要调用方、已知兼容性约束和最近一次行为变化；不要修改文件，结论引用路径和行号。`                                                              |

高质量需求不要求你预先知道实现方式。你可以只规定“结果、边界和证据”，把实现方案交给 Codex；但不能把“结果是什么”也交出去。例如，“使用缓存优化”是方案，“重复请求相同参数时在 30 秒内复用结果”才是可验收的目标。

### 四个缺口分别会造成什么

| 缺口   | 代理可能做出的猜测         | 常见后果                |
| ---- | ----------------- | ------------------- |
| 没有目标 | 自行选择“看起来合理”的改动    | 做了重构、加了注释，却没有解决用户问题 |
| 没有范围 | 从整个仓库寻找类似代码       | 修改无关模块，diff 难以审查    |
| 没有约束 | 按熟悉的库或个人风格实现      | 引入依赖、破坏兼容性、改变数据格式   |
| 没有验证 | 以文件能编译或代码看起来完整为完成 | 边界条件未覆盖，回归到交付后才暴露   |

提问前逐项问自己：

1. 完成后谁能观察到什么变化？
2. 它应该从哪里开始查，最多动到哪里？
3. 哪些接口、目录、依赖、数据或行为不能改变？
4. 哪条命令或哪组步骤能证明成功，失败时能定位到什么？

## 02 目标：把结果写成可观察行为

目标应描述“结束时世界有什么不同”，而不是描述代理要做的动作。优先写输入、条件、输出和不变项。

### 目标的三种颗粒度

**行为目标**适合 bug 和功能：

```text theme={null}
当用户提交没有标题的表单时，服务返回 400，错误字段为 title，数据库不产生新记录。
```

**质量目标**适合性能、可靠性和兼容性：

```text theme={null}
在 1,000 个并发请求下，p95 延迟低于 300ms；超时请求不会重复扣费。
```

**交付目标**适合文档、测试和审查：

```text theme={null}
补齐导入器的四类边界测试，测试命名与 tests/importer/ 现有风格一致，并让目标测试套件通过。
```

避免只写这些无法直接判定的词：

* “更优雅”
* “更健壮”
* “体验更好”
* “全面优化”
* “按最佳实践重写”

如果确实要改善体验，把它翻译成用户动作和结果：点击提交后 2 秒内显示成功或明确错误；移动端 390px 宽度不出现横向滚动；键盘可以从输入框移动到提交按钮。

### 目标与方案分开

把方案写成不可更改的指令，会过早限制排查；把方案完全省略，又可能让代理选择不符合项目约定的实现。更稳妥的写法是区分“必须满足的结果”和“允许采用的方向”：

```text theme={null}
目标：重复请求相同资源时避免短时间内重复访问上游，返回内容和错误语义保持不变。
方向：优先沿用 src/cache/ 现有的 TTL 封装；如果现有封装不能覆盖该场景，先说明原因和备选方案，不要直接引入依赖。
```

目标中的数字、接口字段、状态码、文件格式和用户动作都应尽量来自真实需求。不要为了显得精确而编造指标；未知指标可以明确要求先测基线并回报。

## 03 范围：给出边界和探索路径

范围回答两个问题：Codex 可以读什么，最终可以改什么。两者不一定相同。排查一个接口可能需要阅读路由、配置、日志和调用方，但最终只应修改服务实现和测试。

### 文件上下文怎么给

优先点名最相关的文件，并说明它们的关系：

```text theme={null}
请先阅读：
- src/api/orders.ts：路由入口
- src/services/orderService.ts：业务实现
- src/types/order.ts：响应类型
- tests/orders.test.ts：现有行为
```

如果不知道文件在哪里，可以给探索范围和停止条件：

```text theme={null}
先只读 src/、tests/ 和 package.json，搜索处理订单状态的入口。找到路由、服务和测试后停止搜索并汇报路径；暂时不要修改任何文件。
```

不要把“全仓库”当作默认上下文。范围越大，代理越难判断哪些内容与任务相关；同时，输出中的无关文件会占用上下文窗口。

### 文件名、选区、日志和截图

不同材料适合不同的上下文方式：

| 材料    | 提供方式            | 需要保留的内容                       |
| ----- | --------------- | ----------------------------- |
| 源码    | 点名路径或在 IDE 选中代码 | 函数名、调用方、类型、注释和相关测试            |
| 配置    | 点名配置文件和生效环境     | 配置键名、默认值、环境差异；删除密钥值           |
| 日志    | 粘贴相关时间窗口和完整错误链  | 时间、请求 ID、路由、状态码、错误类型和堆栈；脱敏用户值 |
| 截图    | 直接附图并标注视口或操作步骤  | 页面状态、设备尺寸、可见错误、期望位置           |
| 设计稿   | 附设计稿并说明可变与固定内容  | 间距、断点、交互状态、无障碍要求              |
| Issue | 提取复现条件和期望行为     | 原始描述、版本、环境、最小复现和附件            |

日志不要只写“报了空指针”。应保留调用坐标和前后事件：

```text theme={null}
发生时间：2026-09-05 14:03:22 UTC
请求：POST /api/profile，request_id=<request-id>
结果：500
日志：
TypeError: Cannot read properties of null (reading 'userId')
    at getUserProfile (src/services/user.ts:42:18)
    at async ProfileController.getProfile (src/controllers/profile.ts:15:20)
```

截图上下文也要可执行：

```text theme={null}
附件 screenshot-mobile.png：390x844 视口。
复现：登录成功后打开订单页，向下滚动到表单底部。
现象：错误提示被固定底栏遮住，无法读完整。
目标：错误提示完整可见，提交按钮仍可点击，桌面视图不改变。
```

截图不能替代 DOM、日志或测试。它说明“看到了什么”，不一定说明根因；要求代理结合组件、样式和实际交互验证。

### 保护敏感上下文

提交上下文前先脱敏：

| 原始内容                          | 可用写法                               |
| ----------------------------- | ---------------------------------- |
| `Authorization: Bearer ey...` | `Authorization: Bearer <redacted>` |
| `user@example.com`            | `<user-email>`                     |
| `order_20260905_1234`         | `<order-id>`                       |
| `?token=secret`               | `?token=<redacted>`                |
| 内部 IP 或私有域名                   | `<internal-host>`                  |

保留时间、状态码、错误类型、路由形状、请求 ID 的脱敏版本和数据结构。不要把 `.env`、SSH 私钥、完整客户记录、生产令牌或可直接访问的私有链接粘贴到提示词中。线上操作先规定“只读取证，不改生产状态”，需要改变权限、数据、计费、通知或部署时单独确认。

## 04 约束：写清楚不能变的东西

约束不是“请写得好一点”，而是实现必须服从的边界。常见约束包括：

* **代码边界**：只改指定目录，不改迁移、锁文件或生成文件。
* **接口边界**：函数签名、HTTP 方法、状态码、字段名和排序保持不变。
* **依赖边界**：只用已有依赖，或只能使用标准库。
* **兼容性边界**：支持的运行时、数据库版本和旧客户端行为不变。
* **数据边界**：不读取或写入生产数据，不修改历史记录，不记录敏感值。
* **流程边界**：不提交、不推送、不发布；失败后停止扩大范围。
* **风格边界**：沿用现有目录、命名、测试框架和错误处理方式。

把“不要动某物”配上可替代路径，代理更容易完成任务：

```text theme={null}
不要修改数据库 schema；如果当前实现必须依赖新字段，先停止并说明迁移需求。
不要引入第三方日期库；优先使用项目已存在的 dateUtils，无法满足时先报告缺口。
不要更新 lockfile；如果安装步骤会自动修改它，只进行代码分析并等待确认。
```

范围和约束要能被 diff 检查。比如“只改一个函数”不等于“只能有一个文件变化”：如果需要补测试，应明确允许测试文件变化；如果不允许改动配置，也应明确列出配置文件为禁止项。

## 05 验证：从“看起来完成”到证据

验证是四件套中最容易漏掉、却最能减少返工的一项。好的验证至少包含命令、对象和通过条件：

```text theme={null}
运行 pytest tests/test_parser.py；所有测试通过，且新增的空字符串和非法日期用例均被执行。
```

而不是：

```text theme={null}
改完确认一下没问题。
```

### 分层验证

按风险从近到远排列验证，失败时更容易定位：

1. **语法或格式**：格式化、lint、静态检查。
2. **局部行为**：目标函数或组件的单元测试。
3. **模块行为**：相关服务、页面或接口测试。
4. **系统行为**：构建、集成测试、启动后请求或浏览器操作。
5. **回归审查**：查看 diff、检查未预期文件、确认兼容性和安全边界。

提示中写出“先跑什么、再跑什么、哪个失败需要停下”：

```text theme={null}
先运行 pnpm test --filter order-service，失败时先报告，不要继续改其他模块；通过后运行 pnpm lint 和 pnpm build。最后查看 git diff --check，并列出仍未验证的生产行为。
```

### 验证必须覆盖负面路径

只验证成功路径不能证明修复有效。根据任务补齐至少一个失败或边界条件：空输入、重复请求、权限拒绝、超时、网络断开、旧格式、并发访问、窄屏布局或已有数据。

### 让代理报告证据

要求交付摘要包含：

```text theme={null}
- 修改文件：逐项列出
- 实际运行命令：完整命令和结果
- 验收对应关系：每条标准的证据
- 未验证事项：原因、影响和下一步
- 不确定假设：需要谁确认
- 回滚方式：补丁、反向提交或对应环境的回退操作
```

“测试通过”不是证据，除非说明测试命令、范围和退出结果；“没有改其他地方”也应通过 `git status` 或 diff 证明。

## 06 什么时候先用 `/plan`

小任务可以直接执行：目标明确、影响范围单一、实现方式已有项目先例，且你能在一句话里描述预期 diff。比如“在现有函数入口增加空值判断，补一个单测，运行目标测试”。

以下情况先进入 `/plan` 或要求“只读并出方案”：

* 不熟悉的代码库或找不到真实入口。
* 跨多个模块、接口、数据库或部署配置。
* 迁移、重构、权限、并发、缓存、计费和数据修复。
* 需求仍有多个合理解释。
* 验证方式未知，或者失败成本很高。
* 需要并行拆分或新建工作树。

在计划阶段要求它回答四个问题：

```text theme={null}
先不要修改。请检查相关文件、测试和配置，输出：
1. 当前实现和调用链的事实；
2. 计划修改的文件及每个文件的目的；
3. 风险、未决问题和不应触碰的文件；
4. 每一步对应的验证命令和停止条件。
```

计划不是审批的替代品。阅读计划后核对它是否找到了真实入口、是否把一次性需求误写成全局重构、是否遗漏失败路径。确认后再让它执行，必要时把计划拆成多个独立任务。

## 07 `/goal` 适合什么任务

当任务有明确、可持续检查的完成标准，可以使用 `/goal` 把目标和完成条件放在一起。一个好的目标能由命令、测试或明确的用户步骤判断为“是”或“否”：

```text theme={null}
/goal 修复导入器：对空文件、重复 ID 和非法日期分别返回明确错误；保持合法 CSV 的导入结果不变；pytest tests/test_importer.py 和 ruff check src/importer.py 均通过；不要修改数据库迁移。
```

不适合直接写成 `/goal 让代码更优雅`、`/goal 全面提升性能`，因为代理无法稳定判断是否达成。目标不清晰时，先 `/plan`，让它列出事实、问题和可测标准，再整理成目标。

`/goal` 的具体可用性取决于当前版本和账号配置。如果命令不显示，运行本地帮助或查看官方文档，不要凭旧教程修改未知配置。无论是否使用 `/goal`，仍需人工审查 diff、权限和敏感操作；长期任务也要定期检查进度和上下文，不要把“目标模式”理解成无需监督。

## 08 复杂任务拆分

复杂任务的最小单位不是“一个文件”，而是“一次可以独立验证的行为变化”。每个小步都要有目标、范围、约束和验证，并尽量让下一步建立在前一步已通过的结果上。

### 一个认证迁移的拆法

不要直接说“把认证系统改成 OAuth”。可以拆成：

| 步骤 | 产出                    | 验证                 | 停止条件             |
| -- | --------------------- | ------------------ | ---------------- |
| 1  | 盘点登录入口、会话存储和调用方       | 输出路径、接口和兼容性清单      | 找不到真实入口或存在未决协议   |
| 2  | 定义 provider 配置和回调数据结构 | 类型检查、配置解析测试        | 需要新增密钥或生产配置      |
| 3  | 增加本地回调处理              | 回调成功、state 错误和超时测试 | 权限或安全语义不明确       |
| 4  | 接入会话创建，保留旧登录          | 新旧路径测试和接口契约测试      | 旧客户端行为改变         |
| 5  | 增加登出、过期和失败提示          | 过期、重复回调和撤销测试       | 无法模拟 provider 失败 |
| 6  | 切换入口并补文档              | 构建、集成测试和人工路径       | 需要发布或迁移批准        |

步骤 1 只是探索，不应顺手改代码；步骤 2 的结构先确认，再进入实现。每完成一步查看一次 diff，让变更保持可回退。

### 用依赖关系判断顺序

先做被多个后续步骤依赖的稳定合同，再做外围适配：类型和接口先于页面，复现测试先于修复，数据备份和迁移方案先于写入逻辑。把可以并行的只读工作分出去，例如一个任务梳理调用链，另一个任务整理测试缺口；两条线不要同时修改同一批文件。

### 什么时候不要拆

改错别字、单个变量重命名、已知位置的一行日志和一个明确的边界判断，不需要铺设长计划。拆分本身也会产生沟通成本。判断标准是：你能否在开始前写出预期 diff、能否在几分钟内运行局部验证、失败是否容易撤回。三项都满足时直接执行即可。

## 09 提速：减少猜测和返工

提速的主要来源不是让代理少思考，而是让它少走错误路径。按以下顺序优化：

### 先减少往返

一次提供目标、相关文件、日志、约束和验收，比先发“帮我看看”再补五次信息更快。已知文件用 `@` 或路径点名，已知错误贴完整堆栈，已知期望给输入输出示例。

### 控制上下文

* 一个任务一个会话，相关讨论保留在同一线程。
* 不相关任务新开会话，不让旧需求污染判断。
* 对话很长时先查看状态，必要时使用本机支持的压缩命令。
* 只提供相关文件，不把整个仓库、无关日志和重复代码全部粘贴。
* 把持久规则放进项目约定文件，把一次性要求留在当前提示中。

具体命令以本地帮助为准。不要因为“上下文越多越好”而大量附加材料；上下文应覆盖决策所需事实，而不是覆盖所有事实。

### 按任务选择算力

改一处文案或补一个已知测试，使用较快、较低推理设置通常足够；跨模块调试、协议迁移和安全审查需要更多推理。模型、推理级别和快速模式的名称与计费会变化，先查看当前配置，不要把旧版本的模型名写死在团队规则里。

### 并行但要隔离

并行适合独立的只读调查、测试运行、日志分析和文档整理。若两个任务都要修改代码，使用独立的 git worktree 或不同工作目录，并在合并前分别审查 diff。不要让两条会话同时写同一个配置、锁文件、迁移目录或生成文件。

### 让代理自验，但保留人工闸门

提示末尾明确要求它运行测试、lint、构建或复现路径，并报告证据。人工仍需核对高风险动作：安装依赖、删除文件、访问网络、修改生产数据、写入密钥、提交、推送和发布。少一次无效返工，不等于取消边界检查。

## 10 失败时怎么追问

失败追问的目标是缩小不确定性，不是重复“再试一次”。先保留错误输出和当前 diff，再按证据追问。

### 验证命令失败

```text theme={null}
测试命令失败了。先不要扩大修改范围：
1. 原样引用失败命令、退出码和第一处相关错误；
2. 区分代码错误、环境缺依赖、测试数据问题和命令选错；
3. 指出涉及文件和最小修复；
4. 只在确认原因后修改，并重新运行同一条测试；
5. 如果不能确认，停止并列出需要我提供的环境信息。
```

### 改错文件或范围扩大

```text theme={null}
当前 diff 包含我没有授权的文件。请停止修改，说明每个额外文件为何被改动；不要自动恢复或覆盖我的已有工作。把任务收敛到 src/cart/ 和 tests/cart/，如确实需要其他文件，先请求确认。
```

### 结果与需求不符

```text theme={null}
实现没有满足目标：输入为空时仍然显示加载中。请不要继续重构。重新读取组件状态转换和对应测试，列出“已验证事实、当前假设、下一步验证”，先补一个能稳定复现该行为的失败测试。
```

### 环境或权限不足

```text theme={null}
你无法访问生产日志。不要猜测已恢复，也不要申请更高权限。请说明缺失的证据、可以在本地或测试环境验证的部分，以及需要有权限的同事提供的脱敏字段。
```

### 反复失败

第三次失败后不要继续堆补丁。让代理总结失败轨迹、已尝试方案、排除的假设、未读的关键文件和最小复现；必要时回到 `/plan`，重新确认目标和范围。反复失败通常说明目标、上下文、约束或验证中有一项写错或缺失。

## 11 案例一：修复 Python 空输入错误

这是一个可运行的最小示例，展示从模糊需求到四件套。先在临时目录执行：

```bash theme={null}
mkdir prompt-demo
cd prompt-demo
```

创建 `stats.py`：

```python theme={null}
def average(nums):
    return sum(nums) / len(nums)
```

创建 `test_stats.py`：

```python theme={null}
from stats import average


def test_average_numbers():
    assert average([2, 4]) == 3
```

先运行基线：

```bash theme={null}
python -m pytest -q
```

向 Codex 提供模糊需求：

```text theme={null}
@stats.py 帮我改改这个函数。
```

这个请求没有定义空列表的目标，也没有说明是否要改测试。代理可能添加类型、改变返回值，或只做格式调整。更高质量的请求是：

```text theme={null}
目标：average([]) 返回 0，不再因为除以零抛异常；非空输入的平均值保持不变。
范围：只修改 stats.py 中的 average，并允许修改 test_stats.py；先阅读现有测试。
约束：只用 Python 标准语法，不新增依赖，不改变函数名和参数。
验证：补充空列表和 [2, 4] 两个测试，运行 python -m pytest -q；最后展示 git diff 和测试结果，不要提交。
```

验收不只看“函数里有 `if`”：

```bash theme={null}
python -m pytest -q
python - <<'PY'
from stats import average
assert average([]) == 0
assert average([2, 4]) == 3
print("manual checks passed")
PY
```

检查点：空列表有证据，原有非空行为有证据，修改范围只有两个预期文件；如果项目规定空列表应返回 `None` 而不是 `0`，应以项目合同为准，先追问而不是照搬示例。

## 12 案例二：用日志和截图修复页面状态

准备一个前端页面问题时，不要只说“按钮错位”。同时提供视口、操作步骤、截图和相关入口：

```text theme={null}
目标：移动端订单表单在提交失败后，错误提示完整可见；提交按钮不遮挡提示，用户可以再次提交。
上下文：附件 order-error-390.png，视口 390x844；复现为打开 /orders/new，填写有效商品，断开网络后点击提交。请读取 src/pages/orders/NewOrder.tsx、src/components/FormError.tsx、相关 CSS 和测试。
范围：允许修改订单表单组件、错误提示组件的样式和对应测试；不要修改全局 reset、接口路径或桌面端布局。
约束：保持键盘焦点顺序和 aria 属性；不新增 UI 库；优先沿用项目现有断点和间距变量。
验证：运行 pnpm test -- NewOrder，运行 pnpm lint；在 390x844 和 1440x900 复现成功、失败和再次提交三条路径，报告截图或明确说明无法进行的人工验证。
```

建议先让代理只读：

```text theme={null}
先不要改代码。请确认截图中的遮挡来自 fixed 底栏、容器溢出还是错误状态布局，并列出将检查的选择器、组件和测试。
```

如果它直接把按钮挪到页面顶部，追问：

```text theme={null}
这会改变正常提交路径，且没有证明是根因。请引用当前 DOM/CSS 的事实，先补一个能表现遮挡问题的失败测试或最小复现，再提出不影响桌面布局的修复方案。
```

验收包括三个层面：自动测试证明状态转换，两个视口证明布局，人工操作证明网络失败后仍能重试。单张截图变好看，不等于键盘、错误状态和桌面回归都通过。

## 13 案例三：增加 CSV 导出而不改变数据合同

假设已有 `src/report/exportCsv.ts`、`src/report/types.ts` 和 `tests/report/export.test.ts`。可运行的提示如下：

```text theme={null}
目标：为 Report 增加 exportJson，输出可被现有 importReport 读取的 JSON；字段名、字段顺序语义和日期格式与 CSV 导出一致。
范围：先读取 src/report/exportCsv.ts、src/report/types.ts、src/report/importReport.ts 和 tests/report/；实现允许修改 src/report/exportJson.ts 与对应测试，除非现有导出入口必须注册，否则不要修改其他文件。
约束：复用 Report 类型和现有日期格式化函数，不引入依赖，不改变 exportCsv、importReport 的签名，不把内部字段写入输出。
验证：测试普通报告、空报告、包含逗号和换行的文本、无效日期；运行 pytest tests/report/ 或项目实际测试命令，并验证 exportJson 的结果可通过 importReport 读回。展示 JSON 示例、diff、命令和结果。
```

要求代理先给出字段映射表：

| 内部字段               | JSON 字段     | 允许为空 | 验证       |
| ------------------ | ----------- | ---- | -------- |
| `report.id`        | `id`        | 否    | 导出后读回相同值 |
| `report.title`     | `title`     | 是    | 空标题不丢失字段 |
| `report.createdAt` | `createdAt` | 否    | 沿用既有格式   |
| `report.rows`      | `rows`      | 是    | 空数组可读回   |

如果代理建议“顺便统一 CSV 和 JSON 的序列化架构”，应先判断是否属于范围。当前任务的验收是新导出合同，不是重构两个导出器；重构可以另开任务，避免把功能 diff 和架构 diff 混在一起。

失败追问示例：

```text theme={null}
importReport 无法读回新 JSON。请保留失败样例，比较 importReport 期待的字段和实际输出；不要修改导入器来掩盖不兼容。先说明应调整导出映射还是需求合同，并指出影响哪些已有测试。
```

## 14 案例四：陌生仓库中定位登录 500

这是一个“先证据、后修改”的案例。提示分两阶段。

第一阶段只读：

```text theme={null}
目标：找出会话过期后 POST /api/login 返回 500 的可证实原因。
范围：只读 apps/api/src/auth、apps/api/src/routes、apps/api/tests、package.json 和脱敏日志；可以搜索调用链，但不要修改文件。
约束：不要访问生产数据库，不要重放含真实 token 的请求，不要安装依赖，不要修改配置。
上下文：时间窗口为 2026-09-05 14:03-14:05 UTC；状态码 500；request_id=<request-id>；堆栈指向 src/services/user.ts:42 和 src/controllers/profile.ts:15。
输出：按“已验证事实、待确认假设、最小复现、建议修复、验证命令”报告，并给出准确文件路径。
```

第二阶段在确认根因后再改：

```text theme={null}
根据你刚才确认的事实，只修复 token 刷新失败时的 null 处理。
目标：刷新失败返回既有 401 错误格式，不再抛 500；正常登录和有效刷新行为不变。
范围：允许修改 src/auth/session.ts 和 auth 测试；不要改变权限判断、数据库 schema 或响应字段。
验证：先运行新增的过期刷新测试，再运行完整 auth 测试；使用脱敏的本地 fixture 验证 401 响应。不要访问生产，不要提交或推送。
```

线上验收必须回到原始路径。如果没有生产权限或不能重放请求，应明确写“未验证线上恢复”，而不是把本地测试通过表述成线上已恢复。保留时间、状态码、日志行和脱敏请求 ID，方便有权限的人补证据。

## 15 最终验收清单

在接受 Codex 的“已完成”之前，逐项核对：

### 需求证据

* [ ] 目标描述的是可观察行为，而不是泛泛的质量词。
* [ ] 空输入、失败路径、兼容性或用户关键路径已经写入目标或验证。
* [ ] 每条目标都能对应到测试、命令、请求、截图或人工步骤。

### 范围证据

* [ ] 代理读取了正确入口、调用方、类型、配置和现有测试。
* [ ] `git status --short` 和 `git diff --stat` 显示的文件在授权范围内。
* [ ] 没有把一次性需求写入全局规则或无关文档。
* [ ] 没有修改生成文件、lockfile、迁移或配置，除非明确允许。

### 约束证据

* [ ] 函数签名、接口字段、状态码、权限和旧行为符合约束。
* [ ] 没有无理由新增依赖、改变架构或顺便重构。
* [ ] 日志、截图、测试夹具和输出没有泄露敏感信息。
* [ ] 没有执行未经确认的网络、删除、生产写入、提交或发布操作。

### 验证证据

* [ ] 目标测试实际运行并通过，命令和退出结果有记录。
* [ ] lint、格式、类型检查或构建已按项目要求运行。
* [ ] 至少一个失败或边界路径得到验证。
* [ ] 页面改动检查关键视口、键盘焦点和错误状态；接口改动检查响应码、超时、权限拒绝和重复请求。
* [ ] 已查看完整 diff，并运行 `git diff --check`。
* [ ] 未验证事项、环境限制和下一步责任人已明确写出。

### 交付边界

* [ ] 当前工作区的原有未提交改动没有被覆盖。
* [ ] 未要求提交时，Codex 没有自行提交或推送。
* [ ] 需要回滚时，知道应恢复哪个补丁、反向提交或环境版本。

## 16 一份可按任务填写的提示骨架

下面不是“泛化改代码模板”，而是一张提交前检查表。只保留与任务相关的行，填入真实路径、输入和命令：

```text theme={null}
背景/现象：
目标（完成后可观察到的结果）：
上下文（文件、调用方、测试、日志、截图、版本）：
范围（允许读取/修改）：
约束（接口、依赖、兼容性、数据、权限、流程）：
非目标（这次明确不做什么）：
执行方式：先只读、先 /plan，还是直接处理一个小步？
验证命令：
人工验证路径（如有）：
停止条件：
交付报告必须包含：修改文件、完整命令、结果、未验证事项和回滚方式。
```

复杂任务可以先把这张表交给 `/plan`，要求代理指出缺口；简单任务也可以只写四件套，但不能省略验证。执行过程中如果出现新事实，更新目标或约束并重新确认范围，不要让代理依据旧假设继续扩张。

## 小结

提示词四件套的核心不是写得长，而是让四类决定归位：

* **目标**决定结果，不让代理替你发明需求。
* **范围**决定边界，让探索和修改可审查。
* **约束**决定不能牺牲什么，保护接口、数据、依赖和流程。
* **验证**决定何时算完成，把“感觉应该可以”变成证据。

遇到陌生、跨模块或高风险任务，先只读、先 `/plan`，再拆成每步可验证的小任务；遇到有明确可测终点的长任务，再考虑 `/goal`。提速优先减少猜测、返工和无关上下文，其次才考虑模型或快速模式。失败时保留证据、缩小范围、追问事实，直到根因和验收都清楚。

参考资料：`参考/codex/13-prompting.md`、`参考/codex/31-speed.md`、`参考/codex/36-best-practices.md`。
