Codex 新人上手——从需求到上线的完整工作流

本文基于 codex 仓库当前代码结构与仓库规范整理,描述的是该仓库的一种典型开发工作流,不代表所有 Codex 项目都完全一致 假设你今天刚拿到 Codex 的代码权限,mentor 在 Slack 上丢给你一个需求:

"给 TUI 的 composer 增加一个粘贴 burst 模式------当用户一次性粘贴多行文本时,不要把 Enter 键识别为提交,而是当作换行符,等粘贴结束后再统一提交。"

你打开仓库,看到了 docs/codex-rs/.codex/skills/tools/......目录很多,但你不知道该从哪下手。

本文就是这个场景下的操作手册。


第一步:判断要不要写设计文档

Codex 没有"所有功能都必须写设计文档"的规定。你的判断标准是:

这个子系统的交互复杂度,是否超出了代码本身能表达的范围?

对于"粘贴 burst 模式"这个需求:

  • 它涉及 TUI 输入事件的处理顺序(键盘事件 → composer 状态机 → paste detection)
  • 它有一个边界条件:非 ASCII 字符和 ASCII 字符的处理方式不同
  • 它会影响现有的 Enter 键提交行为

需要写设计文档。

但如果你的需求只是"给某个配置项增加一个新选项",直接写代码 + 内联注释就够了。

复制代码
接到需求
  │
  ▼
是否涉及多模块协调 / 复杂状态机 / 边界条件?
  │
  ├── 是 → 写 docs/*-design.md
  │
  └── 否 → 直接写代码 + rustdoc

第二步:写设计文档,同时列出 "Tests that pin behavior"

Codex 的设计文档不是"写完就放下"。它有一个固定套路:

  1. 问题定义:用户粘贴多行时,Enter 被误识别为提交
  2. 设计目标:区分"paste burst"和"正常打字"
  3. 非目标:不支持超过 1000 字符的 burst(超出范围)
  4. 实现方案 :在 ChatComposer 中增加 PasteBurst 状态机
  5. Tests that pin behavior :-非 ASCII 内容的粘贴 burst 能正确处理多行换行,且不会在中途把字符显示出来 non_ascii_burst_buffers_enter_and_flushes_multiline
    • ascii_burst_treats_enter_as_newline
    • question_mark_does_not_toggle_during_paste_burst

这一步的关键是:你还没写一行代码,但已经知道哪些行为必须被测试锁定。 这些测试名不是随便起的,它们对应设计文档里的每一个关键决策。

bash 复制代码
docs/paste-burst-design.md
  │
  ├── 问题定义
  ├── 设计目标 / 非目标
  ├── 实现方案
  └── Tests that pin behavior  ← 这一节必须有

第三步:写代码和测试,不是先写哪个,而是并排写

Codex 没有要求你先写测试再写代码。实际工作流是:设计文档定好后,代码和测试并排迭代。

3.1 代码放哪里

你的改动会涉及:

  • codex-rs/tui/src/bottom_pane/chat_composer.rs ------ 核心实现
  • codex-rs/tui/src/bottom_pane/AGENTS.md ------ 更新模块级规范(如果需要)

写代码时要遵循 AGENTS.md 的规范。根目录的 AGENTS.md(截至 2026/04 约 17KB)规定了全仓库的通用规则,而 bottom_pane/AGENTS.md 规定了该模块的特殊要求------比如"keep the docs in sync"。

3.2 测试怎么写

你的测试会写进两个地方:

集成测试 (必须):codex-rs/core/tests/suite/codex-rs/tui/tests/suite/

rust 复制代码
#[tokio::test]
async fn paste_burst_does_not_submit_on_enter() {
    let codex = test_codex().build(&server).await;
    codex.submit_turn("paste some multiline text").await;
    // 验证 composer 没有触发提交
}

单元测试 (按需):放在源码文件里的 #[test]*_tests.rs

rust 复制代码
#[test]
fn non_ascii_burst_buffers_enter_and_flushes_multiline() {
    let mut composer = ChatComposer::new(...);
    // 模拟 paste burst,验证 Enter 被当作换行
}

Codex 的 code-review-testing skill 明确规定:agent 逻辑变更必须加集成测试。 不是"尽量加",是 MUST。

3.3 本地验证循环

你的本地开发循环应该是:

bash 复制代码
# 1. 格式化(imports 粒度、换行等)
just fmt

# 2. 自动修复 + lint 检查
#    这背后会跑:cargo clippy(代码规范)、argument-comment-lint(参数注释匹配)、
#    codespell(拼写检查)、cargo-shear(死依赖检测)
just fix -p codex-tui

# 3. 运行你修改的测试
cargo test -p codex-tui paste_burst

# 4. 全量测试(如果你改了公共模块)
just test

关键原则:lint 不是 CI 的惩罚,是本地就该拦截的纠错。 如果在 just fix 阶段暴露拼写错误或参数注释不匹配,比 push 之后被 CI 打回来快 10 倍。

bash 复制代码
写代码 ──→ 写测试 ──→ just fmt ──→ just fix ──→ cargo test
  ▲                                          │
  └──────────── 失败则回修 ───────────────────┘

第四步:安全沙箱------你的命令会被拦下来

当你运行 cargo test 时,Codex 的测试会 spawn 子进程执行 shell 命令。这时你会遇到 Codex 的安全机制:

  1. 进程加固:Codex 进程已经禁用了 ptrace 和 core dumps
  2. 平台沙箱:测试中的 shell 命令在 bubblewrap(Linux)或 Seatbelt(macOS)中运行
  3. Approval:如果测试试图执行敏感操作,会弹窗请求批准
  4. 网络代理:测试中的网络请求走本地 SOCKS 代理,按策略放行

你不需要特别处理什么,只需要知道:如果测试因为沙箱被拒绝,错误信息会告诉你缺少什么权限。

常见的沙箱失败信号:

  • SandboxErr::Denied ------ 沙箱拒绝了文件写入或网络访问
  • permission denied in sandbox ------ 命令试图访问沙箱外的路径
  • 测试挂起直到超时 ------ 可能是网络请求被 SOCKS 代理阻塞,等待审批

排查方法:

  1. 先看错误信息里被拒绝的具体路径/操作

  2. 检查 codex-rs/sandboxing/ 中的权限配置

  3. 如果是远程环境不支持的测试,用 skip_if_remote! 宏跳过

  4. nextest.toml 里调整 slow-timeout 避免挂起测试拖慢整体进度

    运行测试


    测试失败


    错误信息含 SandboxErr / permission denied?

    ├── 是 → 查看具体被拒绝的路径/操作
    │ → 调整沙箱权限或 skip_if_remote!

    └── 否 → 普通代码 bug,按常规方式修复


第五步:提交 PR------PR Body 有规范

代码和测试都通过后,你要提交 PR。Codex 有一个 codex-pr-body skill 定义了 PR Body 的写法:

  1. 先解释 Why,再解释 What
  2. 保留作者原有内容(不要删掉别人放的截图)
  3. 讨论 net change,不要写"我试了什么但放弃了"
  4. 用 Markdown 格式,代码用反引号
  5. 引用相关 issue / PR

PR description 的模板很简单------What / Why / How。

markdown 复制代码
## What

增加 PasteBurst 状态机,区分 paste burst 和普通打字。

## Why

用户粘贴多行文本时,Enter 被误识别为提交,导致指令提前执行。

## How

- 在 ChatComposer 中增加 PasteBurst 状态
- 非 ASCII burst 时缓冲 Enter 作为换行
- ASCII burst 时同样处理,但保持与现有行为的兼容

## Tests

- `non_ascii_burst_buffers_enter_and_flushes_multiline`
- `ascii_burst_treats_enter_as_newline`

第六步:CI 流程------你的 PR 会经历什么

提交 PR 后,CI 会分两层跑:

PR 级快速检查(rust-ci.yml

  • 路径感知 :只跑和你修改相关的检查
    • 改了 codex-rs/* → 跑 cargo fmtcargo-shear
    • 改了 codex-rs/tui/* → 跑 TUI 相关测试
  • 速度优先:不跑完整测试矩阵
  • 失败阻断:任何 lint 失败都会阻断合并

全量 CI(rust-ci-full.yml

  • pushmain**full-ci** 分支时触发
  • tests job 用 45 分钟超时(其他 job 30 分钟)
  • 跑完整集成测试矩阵
scss 复制代码
提交 PR
  │
  ▼
┌─────────────────┐
│ rust-ci.yml     │  ← 路径感知,快速反馈
│ (PR 级)         │
└─────────────────┘
  │
  ▼
合并到 main
  │
  ▼
┌─────────────────┐
│ rust-ci-full.yml│  ← 全量测试,45min 超时
│ (Full CI)       │
└─────────────────┘

第七步:PR Babysitter------提交后还有人帮你盯着

PR 提交后,babysit-pr skill 会自动:

  1. 监控 CI 状态
  2. 如果失败,区分是"代码问题"还是"flaky 环境问题"
  3. 对 flaky 失败自动重跑:python3 .codex/skills/babysit-pr/scripts/gh_pr_watch.py --pr auto --retry-failed-now

这意味着你不需要每隔 10 分钟刷新 CI 页面------Codex 会自己 babysit。


第八步:文档同步------别忘了 AGENTS.md 的 checklist

你的代码合并后,还有一件事:检查文档是否同步。

codex-rs/tui/src/bottom_pane/AGENTS.md 里写了:

"keep the docs in sync: Update the relevant module docs... Update the narrative doc docs/tui-chat-composer.md whenever behavior/assumptions change..."

这意味着当你修改了 ChatComposer 的行为时,你必须同时更新:

  1. 模块级 rustdoc(源码里的注释)
  2. 用户文档(docs/tui-chat-composer.md
  3. 设计文档(如果行为/假设变了)

除非你有意保持不一致,并且记录了原因。

复制代码
代码合并
  │
  ▼
是否需要更新文档?
  │
  ├── 是 → 更新 rustdoc + 用户文档 + 设计文档
  │
  └── 否 → 确认 divergence 是有意且已记录的

完整流程图(决策视角)

bash 复制代码
                              接到需求
                                │
                    ┌───────────┴───────────┐
                    │                       │
              涉及多模块/复杂状态机?      简单配置变更?
                    │                       │
                    ▼                       ▼
            写 docs/*-design.md          直接写代码
            └── Tests that pin behavior    └── rustdoc
                    │
                    ▼
            ┌───────────────┐
            │ 写代码 + 测试  │
            │(并排迭代)    │
            └───────────────┘
                    │
                    ▼
            just fmt → just fix
            └── argument-comment-lint
            └── codespell / cargo-shear
                    │
                    ▼
              cargo test 通过?
                    │
            ┌───────┴───────┐
            │               │
            ▼               ▼
        通过            沙箱拦截?
                            │
                    ┌───────┴───────┐
                    │               │
                    ▼               ▼
               调整权限/      代码 bug
               skip_if_remote!      │
                    │               │
                    └───────┬───────┘
                            │
                            ▼
                      提交 PR
                      └── What / Why / How
                            │
                            ▼
                    rust-ci.yml 通过?
                            │
                    ┌───────┴───────┐
                    │               │
                    ▼               ▼
                通过            lint 失败?
                                    │
                                    ▼
                              just fmt/fix 本地重跑
                                    │
                                    ▼
                              合并到 main
                                    │
                                    ▼
                          rust-ci-full.yml
                                    │
                                    ▼
                           是否需要更新文档?
                                    │
                          ┌─────────┴─────────┐
                          │                   │
                          ▼                   ▼
                      行为变了?           无变化
                          │                   │
                          ▼                   ▼
              更新 rustdoc + 用户文档        完成
              + 设计文档
                          │
                          ▼
                        完成

新人最容易踩的三个坑

坑一:忘了集成测试

Codex 的 code-review-testing skill 说得很清楚:agent 逻辑变更 MUST 加集成测试。 不是"尽量",不是"建议",是强制。如果你只写了单元测试,reviewer 会要求你补集成测试。

坑二:改了代码没更新 AGENTS.md

AGENTS.md 不是摆设。它会被加载到 AI agent 的上下文中,agent 生成代码时会自动遵循。如果你改了模块规范但没更新 AGENTS.md,agent 以后生成的代码就会和你新的实现不一致。

避免方法: 提交前过一遍三层文档检查清单------

  1. 源码 rustdoc:新行为是否有注释说明?函数签名变更是否更新了 docstring?
  2. 用户文档docs/ 下的相关文档是否需要补充新功能说明?
  3. 设计文档 :如果行为/假设变了,Tests that pin behavior 是否需要追加新测试名?

坑三:snapshot 测试挂了不知道怎么办

TUI 改动最容易触发 snapshot 测试失败。如果你看到 .snap.new 文件:

  1. 打开 .snap.new 文件,人工确认变化是否符合预期
  2. 如果符合,执行 cargo insta accept(需先安装 cargo insta
  3. .snap 文件的变更一起提交到 PR

这不是测试坏了,而是 TUI 渲染输出变了------ Codex 用这种方式让 UI 变化可 review。


可学习点

  1. 设计先行但务实:复杂功能先写设计文档,简单功能直接写代码
  2. 测试不是补的,是一起写的:设计文档定稿时就应该列出 Tests that pin behavior
  3. AGENTS.md 是活契约:改了代码要同步更新,否则 agent 会按旧规范生成代码
  4. lint 不是惩罚,是自动纠错just fmtjust fix 应该在提交前跑,不是在 CI 挂了之后跑
  5. 安全是默认开启的:沙箱、审批、网络代理不需要你配置,但你需要知道它们的存在

系列定位

本文是 Codex 工程解读系列的实战补充篇。前五篇分别讲了 Skill 系统、Lint 哲学、安全架构、文档管理和测试哲学的底层原理,本文把它们串成了一条可操作的工作流。

相关推荐
阿斯加德D2 小时前
《霍格沃茨之遗》风灵月影修改器下载(已汉化)2026最新版
人工智能·测试工具·游戏·3d·游戏程序
HIT_Weston2 小时前
75、【Agent】【OpenCode】用户对话提示词(question 工具)
人工智能·agent·opencode
weikecms2 小时前
外卖霸王餐API接口对接
大数据·人工智能·企业微信·微客云
zhangfeng11332 小时前
带有embeding 同时训练的Lora 权重合并,合并后的权重的模型,再训练数的Loss 突然增加
人工智能·lora·sft
树獭非懒2 小时前
Claude Code 完全入门指南:让你的 AI 从"会说"到"会做"
人工智能·程序员·llm
数智工坊2 小时前
基于CLIP隐空间的层级文本条件图像生成:unCLIP核心原理与全链路解析
论文阅读·人工智能·深度学习·transformer·迁移学习
雪回2 小时前
基于 Stable Diffusion-WebUI 实现 LandPPT 本地模型绘图配置指南(SDWebUI )
人工智能·深度学习·ai·ai作画·stable diffusion·ppt
^ V ^2 小时前
1.1 具身智能 (Embodied AI)
人工智能·具身智能
薛定猫AI2 小时前
【深度解析】从 AI 超级应用到数字操作系统:基于大模型 API 构建可落地的 Agent 工作流
人工智能