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

Codex 的 PR body 只有一句 "重构组件"。如何用 PR template + AGENTS.md 强制写出 before/after、why、test plan。

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

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

修法:.github/PULL_REQUEST_TEMPLATE.md + AGENTS.md 里告诉 Codex 必须用它,每节怎么从自己的 commit log 抽内容。

常见原因

1. Repo 没有 PR template

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

如何判断ls .github/PULL_REQUEST_TEMPLATE.md 没东西。PR 描述直接从 model 的散文开始。

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

Codex 听 AGENTS.md。这个文件一句都没写 PR 格式,agent 就用训练数据里的 default,通常很泛。

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

3. 任务 prompt 本身就一行

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

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

4. Harness 把 PR body 截断了

有些 Codex CLI/wrapper 走 CLI flag 传 body,有长度上限;或者中间经过 script 把换行抹掉。Model 写得很详细,上传那一步被截了。

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

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

## 改了什么

<一段总结>

## 为什么

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

## Before / After

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

## 怎么测的

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

## 风险

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

## 相关

<关联 issue、关联 PR>

GitHub 会自动把这份 template 填到 PR body。Codex 看到空的 section 会填。

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。

预防

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

相关

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