# Codex 编程完整工作流教程：Spec → Plan → Execute → Review

> 来源基础：Rick Hightower 关于 Claude Code spec-driven development 的文章总结，以及 Hermes 场景下的工程化调整。
>
> 适用对象：使用 Codex / Claude Code / Hermes 这类编码 Agent 开发中等以上复杂度功能，尤其是运维自动化、监控、告警、诊断 Agent。
>
> 来源限制：原文 Medium 页面在当前环境受 Cloudflare/403 阻断，本文基于已提取摘要与片段整理，不引用未验证全文细节。

## 1. 核心原则

不要直接让 Codex “帮我写一个系统”。

更稳的方式是把一次开发拆成四层：

1. **Spec：合同**
   - 说明要解决什么问题、不解决什么问题、成功标准是什么。
2. **Plan：配方**
   - 说明按什么顺序改哪些文件、怎么测试、怎么回滚。
3. **Execute：小步执行**
   - 每次只做一个小任务，验证后再继续。
4. **Review：独立审查**
   - 让另一个上下文检查是否符合 spec、是否有安全/质量问题。

一句话：

> Spec 决定“做什么”；Plan 决定“怎么做”；Execute 负责“小步落地”；Review 防止“自己证明自己正确”。

## 2. 为什么不能直接写代码

长时间 AI 编程会话常见失败模式：

- 需求越聊越散；
- 代码写了一半，但不知道哪些验收标准还没满足；
- 模型开始根据上下文里的旧讨论做隐含假设；
- 测试为了通过被错误修改；
- 运维脚本不小心引入真实副作用，例如删除、重启、写数据库、误发告警；
- 最后只能靠人肉 review 整理烂摊子。

Spec-driven workflow 的价值不是多写文档，而是提前消灭歧义。

## 3. 推荐目录结构

一个小型运维 Agent 项目可以这样组织：

```text
ops-agent/
├── README.md
├── pyproject.toml
├── .env.example
├── docs/
│   ├── specs/
│   │   └── ops-agent.md
│   ├── plans/
│   │   └── ops-agent-implementation.md
│   └── reviews/
├── src/
│   └── ops_agent/
│       ├── __init__.py
│       ├── config.py
│       ├── checks.py
│       ├── collector.py
│       ├── diagnosis.py
│       ├── notifier.py
│       └── main.py
└── tests/
    ├── test_config.py
    ├── test_checks.py
    ├── test_diagnosis.py
    └── test_notifier.py
```

## 4. 阶段一：写 Spec

Spec 应该回答这些问题：

- 目标：这个 Agent 解决什么运维问题？
- 非目标：明确不做什么？
- 输入：读取哪些数据？系统指标、日志、K8s API、数据库、HTTP endpoint？
- 输出：告警、诊断报告、JSON、企业微信通知？
- 权限边界：是否只读？是否允许自动修复？
- 失败策略：采集失败、API 超时、配置错误时怎么处理？
- 验收标准：哪些测试/命令通过才算完成？
- 安全边界：禁止执行哪些操作？

### Spec 示例

```markdown
# Ops Agent Spec

## Goal
开发一个只读运维 Agent，用于周期性检查 Linux 主机健康状态，并在异常时生成诊断报告和企业微信告警。

## Non-goals
- 不自动重启服务。
- 不删除文件。
- 不执行修复命令。
- 不连接生产数据库。
- 不把 token 写入代码或日志。

## Requirements
- R1: 读取 CPU、内存、磁盘使用率。
- R2: 支持配置阈值。
- R3: 当指标超过阈值时生成结构化诊断结果。
- R4: 支持 dry-run 模式，只打印告警内容，不发送企业微信。
- R5: 企业微信 Webhook 从环境变量读取。
- R6: 所有外部调用必须有 timeout。
- R7: 单元测试覆盖阈值判断、配置加载、告警格式。

## Acceptance Criteria
- `pytest -q` 通过。
- `ruff check .` 通过。
- 没有硬编码 token/IP/密码。
- dry-run 模式不会发送真实 HTTP 请求。
- 配置缺失时给出明确错误，而不是 traceback 泄漏。

## Safety
- 默认只读。
- 自动修复必须作为未来单独 spec，不在本期实现。
```

## 5. 阶段二：写 Plan

Plan 不是重复 Spec，而是把实现拆成可执行步骤。

每个任务都要包含：

- 文件路径；
- 改动内容；
- 测试方式；
- 完成标准；
- 回滚方式。

### Plan 示例

```markdown
# Ops Agent Implementation Plan

## Task 1: 项目骨架
- 创建 `src/ops_agent/` 与 `tests/`。
- 添加 `pyproject.toml`、`.env.example`、`README.md`。
- 验证：`pytest -q` 至少有 import smoke test。

## Task 2: 配置加载
- 创建 `src/ops_agent/config.py`。
- 使用 dataclass 定义阈值配置。
- Webhook 只从环境变量读取。
- 测试：`tests/test_config.py` 覆盖默认值、非法值、缺失 webhook。

## Task 3: 指标采集
- 创建 `collector.py`。
- 读取 CPU、内存、磁盘。
- 外部命令必须 timeout，不使用 `shell=True`。
- 测试：mock 采集结果。

## Task 4: 阈值判断与诊断
- 创建 `checks.py` 和 `diagnosis.py`。
- 输入指标，输出结构化诊断。
- 测试：正常、警告、严重三类场景。

## Task 5: 企业微信通知
- 创建 `notifier.py`。
- 支持 dry-run。
- 真实发送使用 timeout。
- 测试：mock HTTP，不发真实请求。

## Task 6: CLI 入口
- 创建 `main.py`。
- 支持 `--dry-run`。
- 验证：`python -m ops_agent.main --dry-run` 输出诊断 JSON。

## Final Verification
- `pytest -q`
- `ruff check .`
- 检查无硬编码密钥：搜索 `token|secret|password|webhook`。
```

## 6. 阶段三：执行 Plan

执行时不要让 Codex 一次完成全部任务。

推荐节奏：

1. 只执行 Task 1；
2. 跑 Task 1 的验证；
3. review diff；
4. 再执行 Task 2；
5. 每个任务完成后更新 todo；
6. 如果实现发现需求不对，先改 Spec，再改 Plan，不要直接改代码。

给 Codex 的执行提示词可以这样写：

```text
请只执行 plan 中的 Task 1。
不要执行后续任务。
完成后返回：
1. 修改的文件列表；
2. 运行的验证命令；
3. 命令退出码；
4. 未完成项；
5. 是否偏离 spec。
```

## 7. 阶段四：独立审查

审查要分两层：

1. **Spec compliance review**
   - 是否满足 spec？
   - 是否遗漏验收标准？
   - 是否做了非目标里的内容？

2. **Code quality review**
   - 是否有安全问题？
   - 是否硬编码秘密？
   - 是否缺少 timeout？
   - 是否错误使用 `shell=True`？
   - 测试是否真的覆盖关键行为？

审查提示词：

```text
你是独立代码审查员。请只读审查当前 diff，不要修改文件。

审查目标：
1. 对照 docs/specs/ops-agent.md 检查实现是否符合要求。
2. 对照 docs/plans/ops-agent-implementation.md 检查是否只完成当前任务，没有越界。
3. 检查安全问题：硬编码 token、shell=True、无 timeout、真实外部请求、路径遍历。
4. 检查测试是否覆盖关键行为。

输出：
- Verdict: APPROVE / REQUEST_CHANGES / BLOCKED
- Spec gaps:
- Security issues:
- Logic issues:
- Test gaps:
- Required fixes:
```

## 8. 运维 Agent 的完整 Codex 提示词

下面是一份可以直接复制给 Codex 的完整提示词。建议在一个空仓库或已有项目根目录中使用。

```text
你是一个资深 Python 运维自动化工程师。请使用 spec-driven development 流程开发一个只读 Linux 运维健康检查 Agent。

硬性要求：
- 先写 spec，再写 plan，再执行 plan。
- 不要在没有 spec 和 plan 的情况下写业务代码。
- 默认只读，不允许自动修复。
- 禁止使用 shell=True。
- 禁止硬编码 token、密码、IP、Webhook。
- Webhook 只能从环境变量读取。
- 所有外部调用必须设置 timeout。
- 所有新增函数必须有参数和返回值类型注解。
- 新增代码必须有 pytest 单元测试。
- 真实告警发送必须可通过 --dry-run 禁用。
- 不要提交代码，除非我明确要求 commit。

项目目标：
开发一个名为 ops-agent 的 Python 运维 Agent，用于检查单台 Linux 主机健康状态，并在异常时生成结构化诊断报告。第一版只支持本机只读检查，不做自动修复。

功能范围：
1. 读取 CPU、内存、磁盘使用率。
2. 支持通过配置设置阈值。
3. 根据阈值输出 OK / WARNING / CRITICAL。
4. 生成结构化诊断报告，包含：
   - hostname
   - timestamp
   - metrics
   - triggered_checks
   - severity
   - summary
   - suggested_manual_actions
5. 支持企业微信机器人 Webhook 通知。
6. 支持 dry-run 模式：只打印将要发送的消息，不发真实 HTTP 请求。
7. 支持 CLI：`python -m ops_agent.main --dry-run`。

非目标：
- 不自动重启服务。
- 不执行清理磁盘、kill 进程、delete 文件等修复动作。
- 不连接 Kubernetes。
- 不连接数据库。
- 不做长期 daemon/scheduler，第一版只做单次运行。
- 不引入复杂依赖，优先 Python 标准库；如确需第三方依赖，先说明原因并等待确认。

推荐目录结构：
ops-agent/
├── README.md
├── pyproject.toml
├── .env.example
├── docs/
│   ├── specs/
│   │   └── ops-agent.md
│   └── plans/
│       └── ops-agent-implementation.md
├── src/
│   └── ops_agent/
│       ├── __init__.py
│       ├── config.py
│       ├── collector.py
│       ├── checks.py
│       ├── diagnosis.py
│       ├── notifier.py
│       └── main.py
└── tests/
    ├── test_config.py
    ├── test_collector.py
    ├── test_checks.py
    ├── test_diagnosis.py
    └── test_notifier.py

执行流程：

Phase 1: 写 spec
- 创建 `docs/specs/ops-agent.md`。
- 必须包含：Goal、Non-goals、Requirements、Acceptance Criteria、Safety、Validation、Rollback/Stop Conditions。
- 写完后停止，等待我确认。

Phase 2: 写 plan
- 在我确认 spec 后，创建 `docs/plans/ops-agent-implementation.md`。
- 把实现拆成 2-5 分钟粒度的小任务。
- 每个任务必须包含：目标文件、改动内容、测试、验证命令、回滚方式。
- 写完后停止，等待我确认。

Phase 3: 执行 plan
- 在我确认 plan 后，一次只执行一个任务。
- 每个任务必须先写或更新测试，再写实现。
- 每个任务完成后运行对应测试。
- 每个任务结束时返回：
  1. 修改文件；
  2. 运行命令；
  3. 命令退出码；
  4. 是否满足 spec；
  5. 是否有未完成项。
- 不要跳到后续任务。

Phase 4: 最终验证
完成所有任务后运行：
- `python -m pytest -q`
- `ruff check .`（如果已配置 ruff）
- `python -m ops_agent.main --dry-run`
- 检查没有硬编码 secret/token/password/webhook。

Phase 5: 独立审查
请生成一个 review 请求，供另一个 Codex/Claude session 独立审查当前 diff。
审查重点：
- 是否符合 spec；
- 是否越过 non-goals；
- 是否有 shell=True；
- 是否有硬编码密钥；
- 是否所有外部请求有 timeout；
- dry-run 是否不会发送真实 HTTP；
- 测试是否覆盖阈值判断、诊断输出、通知 dry-run。

代码设计建议：
- `config.py`: 使用 dataclass 定义配置，例如 CPU/MEM/DISK 阈值和 webhook URL。
- `collector.py`: 定义 `SystemMetrics` dataclass，采集只读系统指标。
- `checks.py`: 输入 metrics + thresholds，输出 check result。
- `diagnosis.py`: 把 check results 聚合成诊断报告。
- `notifier.py`: 负责企业微信消息格式化和发送；dry-run 时只返回消息内容。
- `main.py`: CLI 入口，组合配置、采集、诊断、通知。

质量要求：
- 函数短小，职责单一。
- 使用 early return，减少嵌套。
- 不使用 print 作为库函数日志；CLI 层可以输出结果。
- 异常信息要可读，但不能泄漏 secret。
- 测试中 mock HTTP 请求，不发真实请求。

现在请先执行 Phase 1：只写 spec，不写实现代码。
```

## 9. 独立审查提示词

当 Codex 完成实现后，把下面提示词给另一个 session：

```text
你是独立审查员。请只读审查这个 ops-agent 项目，不要修改文件。

请读取：
- docs/specs/ops-agent.md
- docs/plans/ops-agent-implementation.md
- 当前 git diff
- src/ 和 tests/ 下相关文件

请检查：
1. 实现是否满足 spec 的每条 requirement。
2. 是否违反 non-goals，例如自动修复、真实删除、真实重启、连接 K8s/数据库。
3. 是否存在硬编码 secret/token/password/webhook。
4. 是否使用 shell=True。
5. 所有外部请求是否有 timeout。
6. dry-run 是否不会发真实 HTTP 请求。
7. 测试是否覆盖配置、阈值判断、诊断报告、通知 dry-run。
8. CLI 是否可用。
9. 是否有不必要依赖或过度工程化。

输出格式：
- Verdict: APPROVE / REQUEST_CHANGES / BLOCKED
- Blocking issues:
- Important issues:
- Minor suggestions:
- Evidence checked:
- Required next patch scope:
```

## 10. 最小验收清单

开发完成前至少满足：

- `docs/specs/ops-agent.md` 存在。
- `docs/plans/ops-agent-implementation.md` 存在。
- `python -m pytest -q` 通过。
- dry-run 不发真实请求。
- 没有硬编码密钥。
- 没有 `shell=True`。
- 所有 HTTP 请求有 timeout。
- 独立审查没有 blocking issue。

## 11. 常见失败与处理

### 失败 1：Codex 直接开始写代码

处理：停止它，要求先补 spec 和 plan。

### 失败 2：实现做了自动修复

处理：回滚该部分。自动修复必须另开 spec。

### 失败 3：测试 mock 了自己的纯函数

处理：只 mock 外部边界，例如 HTTP、系统命令、文件系统；不要 mock 纯判断逻辑。

### 失败 4：dry-run 仍然调用 Webhook

处理：这是 blocking issue。必须先写 regression test，再修复。

### 失败 5：Plan 太大

处理：把任务拆小。一个任务最好 2-5 分钟可完成。

## 12. 实战建议

- 对普通业务功能：spec 可以轻一点。
- 对运维 Agent：spec 必须写清楚安全边界。
- 对能影响生产系统的功能：默认只读，自动修复另开阶段。
- 对告警系统：先 dry-run，再真实发送。
- 对 Hermes/Agent 工作流：review 是 gate，不是形式。

最终原则：

> 让 Agent 写代码前，先让它知道边界；让 Agent 说完成前，先让另一个上下文审查证据。
