1. 为什么 Codex 启动回复合格,前端改动还是不敢合并
Codex 启动回复合格,只说明它把任务边界、主 Skill、后备 Skill 和排除项讲清楚了。放到前端 TDD 场景里,这顶多算“开工前对齐”,离“可以合并”还差一段验收闭环。我见过太多类似情况:启动回复里写着 TDD 做主 Skill、webapp-testing 做后备,改完代码只回一句“已完成”,测试怎么跑、页面路径怎么走、哪些 GitHub Skill 规则最后留下来,全都没有交代。
前端改动和纯后端改动不一样。后端接口改完,跑一遍测试基本能判断行为对不对;前端多了一层状态和交互,输入框里的草稿值、已提交的查询条件、分页游标、重置动作,任何一个环节错位,页面看着能跑,实际交互会变得很别扭。所以启动回复合格之后,我会继续要求三类证据:行为证据、测试日志、Git diff。这三类证据合在一起,才能判断这次改动是否真的可审计、可合并。
这篇聚焦 Codex 驱动前端 TDD 的验收闭环,交付一份可复制的 TaoToken 统一 Key/API 配置骨架,以及 webapp-testing Skill 的验证动作。适合正在用 Codex 做前端任务、但苦于“改完不知道对不对”的开发者。读完你可以在本地复现一套可审计的前端验收流程,而不是只靠一句“已完成”拍脑袋。
2. TaoToken 前置:统一 Key 与 API 配置骨架
在讲三类证据之前,先把 TaoToken 的接入配置说清楚。Codex 要稳定跑前端 TDD,模型调用这一层不能每次任务都换 Key、换地址。我习惯用 TaoToken 做统一入口,官网是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api ,注意 API 地址不加 UTM 参数。
统一 Key 的好处很直接:Codex 的 settings.json、config.toml、以及 webapp-testing Skill 里的模型调用,全部指向同一个入口。这样验收时不会出现“测试环境用了一个 Key、页面验证用了另一个 Key”的混乱。下面给两份配置骨架,一份给 Codex 的 settings.json,一份给 config.toml,你可以按自己的工具链选一份或两份都用。
2.1 settings.json 配置骨架
{ "model_provider": "taotoken", "api_base": "https://taotoken.net/api", "api_key": "sk-你的TaoToken统一Key", "model": "claude-sonnet-4-20250514", "timeout_seconds": 120, "max_retries": 2, "skills": { "primary": "tdd", "fallback": "webapp-testing", "excluded": ["web-artifacts-builder", "systematic-debugging"] }, "evidence_required": ["behavior", "page", "rule"] }这份骨架里,api_base指向 TaoToken 的 API 地址,api_key用你在控制台生成的统一 Key。skills字段把主 Skill 和后备 Skill 写死,避免 Codex 每次任务重新选一遍。evidence_required是我自己加的字段,用来提醒交付时必须带三类证据。
2.2 config.toml 配置骨架
[provider] name = "taotoken" api_base = "https://taotoken.net/api" api_key = "sk-你的TaoToken统一Key" model = "claude-sonnet-4-20250514" timeout = 120 retries = 2 [skills] primary = "tdd" fallback = "webapp-testing" excluded = ["web-artifacts-builder", "systematic-debugging"] [evidence] required = ["behavior", "page", "rule"] behavior_sample = true page_path = true rule_review = true两份配置的核心字段一致,区别只是格式。如果你用的是 Codex 的 coding-plan 模式,建议把api_base和api_key放在环境变量里,配置文件只引用变量名,避免 Key 进 Git。TaoToken 的 API Keys 管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_campaign=rewrite ,生成 Key 后直接填进配置即可。
注意:配置里的
api_base必须是 https://taotoken.net/api ,不要带 UTM 参数,也不要拼成对话页地址。对话页是给模型对话用的,API 地址是给程序调用的,两者不要混。
3. 可复制配置:三类证据的交付要求
配置好 TaoToken 之后,下一步是把三类证据写进交付要求。启动回复通过后,我会追加一段固定话术,让 Codex 进入代码修改阶段时就知道交付标准。这段话术可以直接复制到你的任务描述里。
启动回复已确认。现在可以进入代码修改。 交付时必须包含三类证据。 行为证据 - 若项目有测试入口,提供最小测试及结果 - 若没有测试入口,提供行为样例和对应代码位置 页面证据 - 提供查询、重置、翻页路径 - 标明自动验证或人工复核 - 标明未覆盖的账号、数据或环境 规则证据 - 列出采用的 GitHub Skill 规则 - 列出排除的 GitHub Skill 规则 - 说明哪些规则只留在本次任务记录这段话的作用是把启动模板的承诺带到交付阶段。Codex 如果只改代码、不交证据,任务就没有结束。它如果交了证据但对不上主 Skill,也要继续追问。比如主 Skill 是 TDD,却没有行为样例;后备 Skill 是 webapp-testing,却没有页面路径。这些都说明前面的选择没有真正落地。
3.1 行为证据:草稿值与已提交条件要分开
以“新增筛选项”为例,核心不在界面上,而在查询行为上。我会让 Codex 先拿 TDD 的思路交行为证据。项目有测试入口,就写最小测试;项目暂时没有测试入口,就先交行为样例和对应代码位置,不能为了这一个任务新装测试框架。
行为证据清单如下:
- 输入筛选值后点击查询,请求参数包含该值
- 查询动作会让分页回到第一页
- 点击重置后,请求参数移除该值
- 查询后翻页,仍使用已提交筛选条件
- 输入但未查询时,翻页不使用草稿值
这里有一个细节:草稿值和已提交条件要分开。用户在输入框里打了字,还没点查询,此时翻页到底用不用这个新值?多数后台列表会继续使用上一次已提交条件。Codex 如果把输入框值直接绑到请求参数里,页面看着能跑,交互会变得很别扭。这就是行为证据的价值,它逼 Codex 先讲状态关系,再讲代码实现。
3.2 页面证据:webapp-testing 的验证动作
行为证据过了,还要看页面。webapp-testing 在这里负责收尾。它不一定每次都要写完整自动化脚本。页面能本地打开、登录态可用、数据可控时,可以走浏览器脚本;条件不齐,就写人工路径和未覆盖项。
页面证据清单如下:
- 打开列表页,确认新增筛选项显示在正确位置
- 输入筛选值,点击查询
- 检查列表请求或页面结果是否使用该条件
- 点击重置,确认输入框清空
- 重置后列表回到默认查询状态
- 查询后翻页,确认条件没有丢
- 记录无法验证的账号、接口或数据条件
这类证据不能只写“页面正常”。正常两个字太松。我更愿意看到具体路径:点了什么,输入了什么,页面或请求发生了什么,哪一步没法在当前环境确认。哪怕只是人工路径,也比一句正常可靠。
3.3 规则证据:GitHub Skill 的去处
任务结束以后,我会让 Codex 回到 GitHub Skill 规则本身。新增筛选项这次借了 TDD 和 webapp-testing,排除了 web-artifacts-builder 和 systematic-debugging。最后要记录哪些规则值得下次继续用。
规则证据清单如下:
- 本次采用 TDD 的哪几条行为要求
- 本次采用 webapp-testing 的哪些页面路径
- 哪些 GitHub Skill 被排除
- 排除原因是否仍然成立
- 哪些规则只适合本次任务
- 哪些规则可以下次继续用
我不会把“新增筛选项要写这些行为样例”立刻塞进项目长期规则。它更适合先留在任务记录里。等同类任务再出现几次,仍然稳定有效,再考虑写成项目规则。规则进长期文档要克制,写多了,Codex 每次读任务都会背负一堆局部经验。
4. 验证请求与成功结果:三类证据怎么收
配置和交付要求都就位后,接下来是实际验证。我习惯分三步收证据:先跑行为测试,再看页面路径,最后对 Git diff。
4.1 行为测试与测试日志
如果项目有测试入口,让 Codex 跑最小测试并贴出日志。以 Jest 为例,命令和输出大概是这样:
npx jest src/features/filter/__tests__/filter.spec.ts --verbosePASS src/features/filter/__tests__/filter.spec.ts 新增筛选项 ✓ 输入筛选值后点击查询,请求参数包含该值 (12 ms) ✓ 查询动作会让分页回到第一页 (8 ms) ✓ 点击重置后,请求参数移除该值 (6 ms) ✓ 查询后翻页,仍使用已提交筛选条件 (10 ms) ✓ 输入但未查询时,翻页不使用草稿值 (7 ms) Test Suites: 1 passed, 1 total Tests: 5 passed, 5 total Time: 2.341 s这份日志就是行为证据的硬凭证。如果项目没有测试入口,就让 Codex 交行为样例和对应代码位置,比如src/features/filter/useFilterQuery.ts第 42 行到第 68 行,说明草稿值和已提交条件分别存在哪个 state 里。
4.2 页面路径与截图
页面证据我一般让 Codex 走 webapp-testing 的浏览器脚本,或者给人工路径。浏览器脚本用 Playwright 的话,大概是这样:
const { test, expect } = require('@playwright/test'); test('新增筛选项查询与重置', async ({ page }) => { await page.goto('http://localhost:3000/list'); await page.fill('[data-testid="filter-input"]', 'alpha'); await page.click('[data-testid="filter-submit"]'); await expect(page).toHaveURL(/page=1/); await expect(page.locator('[data-testid="filter-input"]')).toHaveValue('alpha'); await page.click('[data-testid="filter-reset"]'); await expect(page.locator('[data-testid="filter-input"]')).toHaveValue(''); });跑完之后,截图和日志一起贴进任务记录。截图要能看到筛选框、查询按钮、列表结果和分页控件。如果登录态不可用,就写人工路径,标明哪一步没法在当前环境确认。
4.3 Git diff 与规则证据
最后一步是看 Git diff。我让 Codex 贴出改动文件列表和关键 diff,确认没有引入新依赖、没有改公共封装、没有塞测试专用逻辑。
git diff --stat git diff src/features/filter/useFilterQuery.tssrc/features/filter/useFilterQuery.ts | 28 +++++++++++++++----- src/features/filter/FilterBar.tsx | 12 ++++++---- src/features/filter/__tests__/filter.spec.ts | 45 +++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 7 deletions(-)diff 里如果出现package.json新增依赖,或者公共组件被大改,就要追问原因。规则证据则跟着 diff 一起交:本次采用 TDD 的哪几条行为要求,采用 webapp-testing 的哪些页面路径,排除了哪些 GitHub Skill,排除原因是否仍然成立。
5. 本篇常见错排查
实际跑下来,最容易出问题的地方集中在配置、Skill 选择和证据降级三块。下面按现象、原因、处理方式列出来。
5.1 配置类报错
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 401 Unauthorized | api_key 填错或过期 | 到 API Keys 页重新生成,填进 settings.json |
| 404 Not Found | api_base 拼成了对话页地址 | 改成 https://taotoken.net/api |
| 超时无响应 | timeout 太短或网络抖动 | 把 timeout_seconds 调到 120,max_retries 设 2 |
| 模型名不识别 | model 字段写了不存在的版本 | 用配置骨架里的默认模型名,或到文档页核对 |
配置类问题基本都能通过核对 api_base 和 api_key 解决。如果你不确定当前 Key 是否可用,可以先用模型对话页发一条测试消息,确认 Key 有效后再填进配置文件。
5.2 Skill 选择类问题
主 Skill 是 TDD,却没有行为样例;后备 Skill 是 webapp-testing,却没有页面路径。这两种情况说明前面的选择没有真正落地。处理方式是回到交付要求,让 Codex 补齐对应证据。如果它说“项目没有测试入口”,就让它交行为样例和代码位置,而不是直接跳过行为证据。
还有一种情况是 Codex 擅自引入新依赖来造证据。比如为了跑一个测试装了新的测试框架,或者为了页面验证改了公共封装。这种要直接拒绝,证据应该服务任务,不能反过来改造项目。
5.3 证据降级与边界
我允许降级,但降级要写清楚。测试入口找不到,可以把 TDD 降级为行为样例;页面依赖登录态,可以把浏览器脚本降级为人工路径;接口没有可控数据,可以把结果验证降级为请求参数检查和待复核项。
降级要把当前环境做不到的事说清楚。我不接受两种情况:一种是没有证据还说已经验收;另一种是为了制造证据,引入新依赖、改公共封装或塞测试专用逻辑。前者是自欺,后者是给项目埋雷。
提示:如果你在排障时发现是接入层的问题,优先看 API Keys 和接入文档;如果是模型行为不符合预期,去模型对话页复现;如果是长期编码任务,考虑用 Coding Plan 统一管理。
6. 把三类证据固定成你的验收习惯
Codex 的启动回复合格以后,任务还没有完成。前端改动需要三类证据往回收:行为证据管状态和参数,页面证据管真实路径,规则证据管 GitHub Skill 的去处。三类证据合在一起,才能判断这次新增筛选项是否真的可合并。
我自己的做法是把这套流程固定下来:每次 Codex 任务启动回复通过后,先贴 TaoToken 配置骨架,再贴三类证据交付要求,最后按行为测试、页面路径、Git diff 的顺序收证据。跑顺了之后,验收时间反而比“改完再看”更短,因为问题在交付阶段就暴露了。
下一篇可以换一个方向,用“分页错位”来跑同一套模板。新增功能看状态,bug 修复看根因,两种任务的主 Skill 会变,证据结构也会跟着变。如果你想把模型对话、Coding Plan 和 API Keys 统一管起来,可以从 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_campaign=rewrite 生成统一 Key,再回到 https://taotoken.net/api 接入你的 Codex 工作流。