Codex 写的 PR 描述太敷衍:怎么逼出结构化 before/after

Codex 的 PR body 只有一句 "重构组件"。如何用 PR template + AGENTS.md + CI 关卡逼出 before/after、why、test plan,外加 Codex Cloud 按钮的坑。

你打开 Codex 的 PR:title 是 “Update components”,body 是 “Refactored several components for better readability”——完。12 个文件、400 行 diff,没说改了什么、为什么、怎么测的。Reviewer 现在只能冷读全部 diff,没有作者意图作为参照。

**最快的修法:**加一个 .github/pull_request_template.md,写清你要的每一节,再在 AGENTS.md 里要求 Codex 从自己的 commit log 把每节填满。如果你是从 Codex Cloud 网页端(“Create PR” 按钮)发 PR,还有一个坑下面会讲:截至 2026 年 6 月,那个按钮不会自动套用你 repo 的 PR template,所以你还得让 agent 通过 gh CLI 来开 PR。

这不是 Codex 能力问题。让它写一份好 PR 描述完全办得到,默认糟糕是因为大多数 repo 没有 PR template、AGENTS.md 没写描述格式,model 就用最泛的语气填空。

先对号入座

现象最可能的原因跳到
template 存在,但只有网页端发的 PR 不套用Cloud “Create PR” 按钮绕过了 template原因 1
ls .github/pull_request_template.md 是空的repo 里没有 PR template原因 2
template 填上了,但每节都很泛AGENTS.md 没写 PR 格式规则原因 3
PR body 详细度跟你那行任务 prompt 一致瓶颈在 prompt原因 4
GitHub 上的 body 比 agent transcript 短harness 把 body 截断了原因 5
PR body 和第一个 commit subject 一字不差agent 复用了 commit message原因 6

常见原因

1. Codex Cloud “Create PR” 按钮跳过了 template

这个最容易漏,因为 template 确实在 repo 里,从 CLI 发的 PR 也好好的。截至 2026 年 6 月,Codex Cloud 网页端的 “Create PR” 按钮会把它自己生成的 summary 直接写进 PR body,并套用 .github/pull_request_template.md(upstream 跟踪在 openai/codex issue #6750)。于是你的 Fixes #123 行和各节标题都不会出现,PR 也不会在 merge 时自动关掉关联的 issue。

同一个任务走 Codex CLIcodex 通过 gh pr create --template ... 开 PR)则会正确填上 template。这个差异就是判断点。

如何判断:手动开的 PR 和 CLI 开的 PR 都能渲染出 template,唯独 cloud agent 按钮开的 PR 缺了每一节。修法在 Step 1(用 CLI 开 PR,别用按钮)。

2. Repo 没有 PR template

GitHub “New pull request” 弹出来是空的。Codex 没锚点,写一句话就发了。

如何判断ls .github/pull_request_template.md 没东西(也检查一下 repo 根目录和 docs/)。PR 描述直接从 model 的散文开始。

3. AGENTS.md 没写 PR 描述格式

Codex 读 AGENTS.md 拿 repo 约定。这个文件一句都没写 PR 格式,agent 就退回训练数据里的 default,通常很泛。

如何判断grep -i 'pull request\|pr description\|pr body' AGENTS.md 没结果。

4. 任务 prompt 本身就一行

你说 “修一下 date picker 的 bug”。Codex 写的 PR body 详细度大约等于你的 prompt。短输入短输出。

如何判断:对比 Codex 任务描述和 PR body。都是一句话——瓶颈在 prompt。

5. Harness 把 PR body 截断了

有些 Codex wrapper 走 CLI flag 传 body,有长度上限;或者中间经过 script 把换行抹掉。Model 写得很详细,上传那一步被截了。(注意:gh pr create --body 本身没有实际意义上的长度上限,所以要怀疑的是自定义 wrapper,不是 gh。)

如何判断:对比 git log(或 agent transcript)里看到的 body 和 GitHub 上的 body。GitHub 上短,就是 harness 吃了。

6. Codex 把第一个 commit message 当成了 body

没有其他指引时 agent 会复制第一个 commit subject 同时当 title 和 body。结果 PR body 和 commit subject 完全一样,没有展开。

如何判断:看 PR body 是不是等于第一个 commit message。是的话,prompt 或 harness 没要求更丰富的 body。

最短修复路径

Step 1:写 PR template 并强制套用

新建 .github/pull_request_template.md。GitHub 认这个文件的三个位置:repo 根目录、.github/docs/;文件名大小写不敏感(pull_request_template.mdPULL_REQUEST_TEMPLATE.md 都行)。template 只有在 merge 进默认分支后才生效,所以测之前先把它提交到 main

## 改了什么

<一段总结>

## 为什么

<问题、动机、或关联的 issue>

## Before / After

<行为变化的话:写清楚或贴图 before 和 after>

## 怎么测的

- [ ] `npm test` 本地通过
- [ ] 手动检查:<步骤>
- [ ] 新增测试覆盖:<场景>

## 风险

<什么可能坏,谁依赖被改的代码>

## 相关

<关联 issue、关联 PR>

手动开和 CLI 开的 PR,GitHub 会自动把这份 template 填到 body,Codex 看到空的 section 会填。

如果你用 Codex Cloud 的 “Create PR” 按钮,template 不会自动套用(原因 1)。改成强制走 CLI 开 PR,template 才会被尊重。最干净的位置是你的 Codex Cloud 环境 setup script(比如 scripts/codex/cloud/startup.sh),可以包一层 gh,让每个 PR 都带上 template:

gh pr create --template .github/pull_request_template.md

然后在 AGENTS.md 里加一行,让 agent 走 CLI 而不是网页按钮:

Always open pull requests with `gh pr create --template .github/pull_request_template.md`.
Do not use the Codex web "Create PR" button, which skips the template.

Step 2:AGENTS.md 写要求

追加到 AGENTS.md

## PR 描述

你开的每个 PR 都必须严格遵循 `.github/pull_request_template.md`。每节都填。具体:

- **改了什么**:列出对用户可见的行为变化,或者按 file path 列结构性变化。
  不要写 "重构组件"——要写 "把 `useSession``Header.tsx` 抽出来,
  dashboard 可以复用了"。
- **为什么**:有 issue 就链,没有就描述 bug / 需求。
- **Before / After**:UI 或行为变化要展示两个状态。
- **怎么测的**:列具体跑过的命令,不要写 "本地测过了"。
- **风险**:至少指出一个可能坏的地方。

某节不适用时写 "N/A — <原因>",不许留空。

这样把 template 变成强制结构。

Step 3:用 commit log 起草 body

AGENTS.md 里加:

起草 PR body 时,"改了什么" 一节基于 commit log:

    git log --reverse origin/main..HEAD --pretty=format:'- %s'

每个 commit 变成一条 bullet。然后每条 bullet 用一句话扩展 context。
这样 PR body 和真实改动对得上。

agent 写描述就有具体素材了,不是 vibes。

Step 4:CI 验证描述长度

加 workflow 拦短 body:

# .github/workflows/pr-description.yml
name: PR description check
on:
  pull_request:
    types: [opened, edited, synchronize]
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - name: Require non-trivial description
        env:
          BODY: ${{ github.event.pull_request.body }}
        run: |
          if [ -z "$BODY" ] || [ ${#BODY} -lt 200 ]; then
            echo "PR body 太短(需要 200+ 字符)。用 template。"
            exit 1
          fi
          for section in "改了什么" "为什么" "怎么测的"; do
            if ! echo "$BODY" | grep -q "$section"; then
              echo "缺少节:$section"
              exit 1
            fi
          done

这个 workflow 设为 required status check,Codex 一句话 body 就 merge 不了。

Step 5:写更好的任务 prompt

agent 镜像你的 prompt 详细度。用 prompt template:

TITLE: <一句话,祈使句>
CONTEXT: <为什么重要,链 issue>
SCOPE: <文件 / glob>
ACCEPTANCE:
  - <具体测试或行为 1>
  - <具体测试或行为 2>
NOTES FOR PR BODY:
  - "Before / After" 一节提到 <X>
  - 链 issue #<N>

Codex 把这些 note 翻译成 PR section。

怎么确认修好了

用你平时的 Codex 流程开一个新 PR,然后在 GitHub 的 PR 页面上(不是 transcript 里)检查:

  1. body 包含 template 的每个标题(改了什么为什么怎么测的 等),没有留空。
  2. 改了什么 列的是具体 file path 或行为,不是 “重构组件”。
  3. 怎么测的 写的是真正跑过的命令(比如 npm test),不是 “本地测过了”。
  4. 如果你链了 issue,PR 的 “Development” 处应该显示它,并在 merge 时自动关闭(也就是 Cloud 按钮以前会丢掉的那行 Fixes #N)。
  5. PR description check workflow 是绿勾,不是红叉。

如果第 5 步是红的但 body 看着没问题,是你的节标题和 workflow grep 的字符串对不上;把它们改成完全一致。

FAQ

为什么 CLI 能套上 template,网页按钮不行? 截至 2026 年 6 月,Codex Cloud “Create PR” 按钮会把它自己的 auto-summary 写进 body,跳过 .github/pull_request_template.mdopenai/codex #6750)。CLI 走的是 gh pr create,会套用 template。在 OpenAI 修好之前,把开 PR 的动作走 CLI(Step 1)。

这是 AGENTS.md 还是 CLAUDE.md 控制的? Codex 读 AGENTS.md。PR 格式规则放那里。CLAUDE.md 是 Claude Code 的文件,Codex 不读;如果你两个 agent 都用,把 PR 格式那块放在 AGENTS.md,在 CLAUDE.md 里引用它。

body 已经很详细了,但 title 还是 “Update components”,怎么修标题?AGENTS.md 里加一条 title 规则(“PR title = 祈使句总结,60 字符以内,不要只用 Update/Refactor 这种泛动词”),让 agent 从最重要的那个 commit 取,而不是第一个。

不加 CI 关卡能不能强制 template? 能,但没有东西去执行它。是 required status check(Step 4)才真正挡住一句话 body 进 merge。再配 branch protection,绿勾就变成必须的。

GitHub 到哪找 template,我的为什么不加载? 根目录、.github/docs/,文件名 pull_request_template.md(大小写不敏感)。最常见的坑:它只有在 merge 进默认分支后才生效,所以只活在 feature 分支上的 template 不会填进来。

预防

  • .github/pull_request_template.md 提交进 repo 的默认分支,节就是你真正想要的那些
  • AGENTS.md 要求填每一节,不许无理由的 “N/A”
  • Codex Cloud 上用 gh pr create --template 开 PR,别用网页按钮
  • 让 agent 用 git log 起草 “改了什么”,不要新写一份总结
  • CI 检查 PR body 长度和节标题,设为 required status check
  • 任务 prompt 也用结构化模板,agent 才有 PR body 素材
  • 看 GitHub 上的真实 body,不只是 transcript——harness 可能截断

相关

标签: #Codex #agent #排查 #约定