Technical note

用GitHub让ChatGPT与Codex接力开发

过去的研发流程一直以本机Codex为主。需求分析、阅读源码、修改代码、运行测试、处理环境问题,基本都在同一个任务里完成。Codex能直接看到本机工作树、依赖、数据库、容器和未提交差异,遇到问题可以反复执行“修改—测试—诊断—再修改”,这套方式很顺手。

ChatGPT能够通过GitHub读取项目以后,也可以进入这套研发流程。ChatGPT更适合长时间讨论需求、比较方案和做独立审阅,Codex则仍然适合留在本机实施。两者不必争夺“主力开发者”的位置,也不应该同时修改同一个工作区。比较自然的分工是:ChatGPT在上游定义问题、在下游检查结果,Codex完成中间那段需要本地反馈的工作。

ChatGPT:定义问题、形成需求、设计方案、独立审阅
Codex:本地实施、测试迭代、环境操作、修复审阅问题
负责人:确认产品取舍、接受风险、合并、发布

GitHub:保存分支、提交、PR、Issue和交接记录
仓库文档:保存正式需求、设计、实施和版本事实

模型能力当然重要,但在研发流程中,能不能访问真实环境同样重要。ChatGPT可以读懂一段迁移代码,却不能因此宣布数据库迁移已经成功;Codex可以在本机把测试跑通,也不代表它在经历完整个实现过程后仍能像陌生审阅者一样发现设计盲点。把这两种能力串起来,比让它们重复做同一件事更合适。

不需要再发明一套ChatGPT流程

如果仓库已经有需求、设计、实施和审阅记录,没有必要增加“ChatGPT任务”“Codex任务”之类的新流程对象。无论由谁完成,工作性质并没有改变:

  • ChatGPT修改需求、设计、测试或代码,仍然是一轮正常的实施工作;
  • ChatGPT针对固定提交做正式独立审阅,仍然是一轮工程审阅;
  • 负责人在真实界面和环境中使用产品,仍然属于真实使用验证,ChatGPT不能代替;
  • 普通PR里的一条Review意见,不需要为了显得正式而单独建立审阅流程;
  • 对话中确认的需求和设计,最后仍要写回REQ、设计文档或ADR,不能只留在聊天记录里。

Agent只是当前工作的执行者。流程如果绑定了某个模型名称,换工具以后就要重写;把规则落在分支、提交、验证证据和正式文档上,即使以后换成其他Agent,也不影响协作方式。

GitHub只是协作枢纽

引入ChatGPT以后,很容易把Issue和PR当成新的事实源,最终形成两套互相矛盾的记录。正式事实仍应保存在仓库里,GitHub负责讨论、交接和合入。

对象保存的内容
REQ为什么改变产品,希望得到什么结果
系统设计、能力设计和ADR系统应该怎样工作,为什么作出这个选择
实施、使用和审阅记录实际做过什么,得到什么结果
GitHub Issue外部反馈、待办、讨论和跨会话提醒
GitHub PR一组具体差异的讨论、审阅和合入过程
Git分支一项工作的临时候选
Commit SHA某次交接或审阅面对的准确版本
Git标签已经冻结的正式版本

这种分层也不依赖GitHub。以后换成GitLab、Forgejo甚至只使用本地Git,REQ、设计和Commit SHA仍然成立,变化的只是协作界面。

ChatGPT连接GitHub的具体能力可能随使用的App、插件和权限配置而不同,因此流程不能假定它一定能直接写仓库。连接具备写操作时,ChatGPT可以建立分支、提交候选和更新PR;只有读取能力时,它给出设计或Review结果,再由Codex写回仓库。无论使用哪种连接方式,交接对象都应该是正式文档、PR和固定SHA。

用两类PR把定义和实现分开

所有修改都塞进一个PR看起来省事,实际会让需求、设计和代码同时变化。ChatGPT审阅实现时,找不到已经确认的设计基线;Codex写到一半,也不知道对话里的新想法是不是正式范围。

PR可以区分为Definition PR和Implementation PR。这里的名称只是说明用途,不需要增加复杂的GitHub类型或自动化。

Definition PR:先确认改成什么样

产品行为、业务规则、接口含义、权限、安全、数据或交付范围发生变化时,先准备Definition PR:

原始想法
  → 负责人和ChatGPT讨论范围
  → ChatGPT检查已有REQ、设计、源码和历史决定
  → 建立或修改REQ
  → 修改受影响的系统设计和能力设计
  → 必要时准备ADR
  → 在Draft PR中讨论阻塞问题
  → 负责人确认
  → 合入主分支

通常可以把REQ和受影响的设计放进同一个Definition PR,不必为了流程机械拆分。只有改动很大、横跨多个领域,或者必须先单独确定产品方向时,才把需求和设计分成两个PR。

未确认的设计不要和实现混在一起。Definition PR合入以后,Codex面对的是主分支上已经接受的设计,不需要从聊天记录中猜测哪个版本才算最终决定;ChatGPT后续审阅代码时,也有稳定的比较对象。

Implementation PR:实现已经确认的设计

Definition PR合入以后,Codex从新的主分支建立任务分支和本机worktree:

已经接受的REQ和设计
  → Codex建立任务分支与worktree
  → 实现代码和测试
  → 运行针对性检查
  → 运行仓库规定的完整验证
  → 推送分支并更新Draft PR
  → 固定HEAD SHA
  → 交给ChatGPT审阅

ChatGPT在Implementation PR里不必重新设计整个功能,主要检查这些问题:

  • 实现是否符合REQ和已经接受的设计;
  • 修改是否悄悄扩大了需求范围;
  • 失败场景、权限边界和恢复行为是否遗漏;
  • 测试有没有覆盖真正的风险;
  • 代码、实施记录和验证证据能否互相对应;
  • 是否为了一个局部需求引入了不必要的复杂结构。

发现阻塞问题后,由Codex在本机修复并重新验证。负责人看到的不是一段“应该没问题”的回答,而是固定候选、Review意见和对应的验证结果。

不同工作交给谁

ChatGPT并非不适合修改代码,真正缺少的通常是完整的本地反馈循环。它可以写出第一版代码,但数据库、并发、容器和部署类修改仍要在真实工作树中收口。

工作类型默认主导者处理方式
原始需求讨论、范围收敛ChatGPT对话分析后形成REQ候选
产品设计、架构设计、ADRChatGPT通过Definition PR确认
文档Review和重写ChatGPT修改候选或给出明确差异
小范围纯逻辑修改ChatGPT或CodexChatGPT可以准备第一版,Codex本机验证
中等规模代码修改CodexChatGPT先明确设计和实施边界
数据库、并发、事务和RuntimeCodex本机实现,ChatGPT针对固定SHA审阅
Docker、部署、环境和SecretCodexChatGPT分析方案,不替代环境操作
测试方案和遗漏分析ChatGPTCodex补充测试并实际运行
自动化验证Codex在本机或受控开发机执行
真实界面使用负责人记录真实使用中发现的问题
正式工程审阅新的ChatGPT会话固定提交,独立阅读
合并、标签和正式发布负责人Agent准备候选和证据

这张表不是硬性权限表。一个很小的文案错误没必要先开Definition PR,一个已经确定行为的局部修复也可以直接交给Codex。判断依据仍然是改动有没有改变正式设计,以及验证是否依赖本地环境。

一个分支同时只能有一个写入者

ChatGPT和Codex可以共同处理同一项工作,但只能串行接棒,不能同时写同一个分支。否则很容易出现远端分支已经变化、本机仍然基于旧提交修改,或者一方为了整理提交而覆盖另一方历史的情况。

协作时遵守这些规则:

  1. 一项任务只保留一个主要分支。
  2. 一个分支在任一时刻只有一个当前写入者。
  3. 交接前,当前写入者提交并推送全部候选变化。
  4. 交接记录写出完整HEAD SHA,不使用含糊的“最新提交”。
  5. 接棒者开始前确认远端HEAD仍然等于交接SHA。
  6. 共享分支不做force push,交接后不重写历史。
  7. 试错提交需要整理时,在最终合入主分支时squash。
  8. 两个Agent要尝试不同方案时,分别建立分支或PR,不在同一个分支里互相覆盖。
一项任务
  → 一轮实施工作
    → 一个短期分支
      → 一个隔离工作空间
        → 一个当前写入者

对Codex来说,隔离工作空间通常是本机worktree;对通过GitHub工作的ChatGPT来说,隔离空间是远端分支和Draft PR。同一项任务可以在不同阶段更换写入者,换人之前必须先形成可以准确定位的提交。

worktree只隔离代码目录,并不会自动隔离数据库、容器、端口、缓存和凭据。多个本机Agent并行工作时,这些资源仍要单独分配。相关约束在让多个Agent在不同worktree工作中有更完整的记录。

尽早建立Draft PR

ChatGPT和Codex共同参与的任务,可以在工作稳定之前就建立Draft PR。它不是“准备合并”的信号,而是两边共同使用的交接面。

PR正文顶部只保留当前状态:

## 协作状态

当前阶段:需求 / 设计 / 实现 / 验证 / 评审 / 待确认
当前写入者:ChatGPT / Codex / 负责人
当前候选:<完整HEAD SHA>
下一接棒者:ChatGPT / Codex / 负责人
下一步:一句话说明需要做什么

这些字段会随着任务推进而更新。每次正式交接再增加一条不可变的PR评论,保留当时的准确状态。

ChatGPT把已经确认的定义交给Codex时,可以使用下面的格式:

### 交接给Codex

- 基线:main@<SHA>
- 当前候选:<HEAD SHA>
- 正式依据:REQ-000123、CAP-005、ADR-0012
- 本轮目标:……
- 明确不做:……
- 可以修改:……
- 已经完成:……
- 已运行验证:……
- 未验证和风险:……
- 下一步:在本机worktree实施并运行……

Codex完成本机工作后,再把固定候选交给ChatGPT:

### 交接给ChatGPT审阅

- 比较起点:main@<SHA>
- 固定候选:<HEAD SHA>
- 实际修改:……
- 本机验证:……
- 失败、跳过和警告:……
- 明确未验证:……
- 重点审阅:……

PR原有的来源、范围、设计、验证和恢复内容可以继续保留,只需增加这段很短的协作状态,不必再造一份复杂清单。

Token省在交接,而不是省掉必要信息

让ChatGPT和Codex协作,如果每次都把仓库、全部文档和完整聊天记录重新发一遍,Token只会比原来更多。需要减少的是重复上下文,而不是把需求和验证记录删短。

可以给不同阶段准备不同的上下文包:

阶段应该提供通常不需要提供
需求与设计原始问题、相关REQ、现有设计、历史决定、必要源码本机缓存、完整测试日志、无关模块
本机实施已接受的REQ和设计、验收条件、允许修改范围、相关代码前期所有方案争论、已经否决的长篇讨论
独立审阅比较起点、固定HEAD SHA、REQ、已接受设计、验证摘要实现过程的完整聊天、Agent的思考过程
负责人确认PR摘要、阻塞问题、验证结果、未解决风险每次命令输出和全部中间尝试

这里有几个很实际的节省点。

ChatGPT完成需求讨论后,不把整段对话交给Codex,而是写成REQ、设计和一条交接评论。Codex只读取实施所需的正式结论。需求为什么改变、哪些方案已经否决,如果将来仍有价值,就写进ADR;没有进入正式文档的闲聊不再反复传递。

Codex完成实现后,也不把本机终端的全部输出塞给ChatGPT。PR记录执行了什么验证、结果如何、哪些检查失败或跳过,详细日志只在需要诊断时按链接或附件读取。

独立审阅使用新的ChatGPT会话,只给固定SHA和相关事实源。它不需要恢复实施会话的全部历史,也不会因为读过每一步尝试而沿用实现者的判断。

另外,不再让两个Agent各做一次全仓库调查。ChatGPT在Definition阶段确认受影响的能力和设计,Codex实施时围绕这部分代码工作;如果Codex发现实际依赖超出原范围,再把新的事实写回PR,而不是默默扩大任务。

这套方法没有一个固定的Token节省比例。项目结构、文档质量和任务大小不同,差异会很大。可以确定的是,长对话不再成为唯一的记忆载体,每位接棒者也不必从项目起点重新建立上下文。

Review发现的问题放在哪里

ChatGPT审阅PR时,并不是每条意见都要建立Issue:

  • 当前PR内可以直接修复并验证的问题,留在PR评论中;
  • 修复会明显扩大当前范围的问题,建立待复核的GitHub Issue;
  • 需要长期追踪的问题,再登记到仓库内的正式问题台账;
  • 会改变产品行为的问题,从Issue转入REQ和设计流程;
  • 只有改进建议、还不能说明存在缺陷时,保留为建议,不机械建Issue。

如果一个GitHub Issue已经关联仓库内的正式问题记录,PR合入不一定代表问题已经验证关闭。这时PR使用Refs #123更准确,等实施、验证和正式台账都收口以后再关闭Issue。只有没有进入正式台账、并且合入本PR就能真实结束的问题,才适合使用Closes #123

这样做会多一步状态确认,但能避免GitHub显示“已关闭”,仓库记录却仍然等待验证的矛盾。

普通Review和独立Review

ChatGPT参与过需求和设计,随后在同一段对话中检查代码是否符合自己的设计,这种Review效率很高,普通PR完全可以这样做。不过它仍然可能受之前方案影响,对权限、Secret、事务、并发、迁移、删除和恢复等高风险修改,应使用新的会话做独立Review:

  1. 固定完整HEAD SHA;
  2. 新建一个没有参与实施讨论的ChatGPT会话;
  3. 只提供PR、REQ、已接受的设计、相关源码和审阅目标;
  4. 不把原实现讨论全部复制过去;
  5. 审阅期间不继续修改被审候选;
  6. 结论需要长期保存时,写入正式审阅记录。

固定SHA保证审阅者看到的内容不会在审阅途中变化。新会话减少了对原方案的锚定,也顺便缩小了上下文。OpenAI当前的Codex用例同样包含GitHub PR审阅,它可以作为额外的代码审阅入口,但没有必要让ChatGPT和Codex对每一个普通PR重复给出相同Review。

验证责任仍然留在本机

ChatGPT可以阅读测试代码、判断覆盖是否充分、补充测试、查看GitHub Actions结果和分析失败日志。它也可以指出“这里应该补一组事务回滚测试”,但不能因为代码看起来合理,就把没有执行过的测试写成通过。

本机Codex负责运行仓库规定的验证命令,并记录:

  • 验证对应的HEAD SHA和比较起点;
  • 当时的Git tree是否干净;
  • 运行过哪些命令;
  • 哪些检查通过、失败或跳过;
  • 是否使用数据库、容器、浏览器或其他外部环境;
  • 哪些风险仍然没有验证。

本机测试、远端CI、数据库检查、容器运行和负责人真实使用解决的是不同问题,不能互相替代。ChatGPT给出的代码候选,也要先由Codex拉到本机worktree中验证,再进入合并判断。

权限从最小范围开始

ChatGPT的GitHub连接先只开放需要协作的仓库。读取源码、文档、Issue、PR和CI结果可以作为日常能力;任何写操作都只进入自己的短期分支,不直接推送主分支。

操作建议边界
读取源码、文档、Issue、PR和CI结果允许
建立短期分支、更新Draft PR连接支持时允许
向任务分支提交写入前确认
添加Review意见或待登记Issue允许
直接推送主分支禁止
合并PR、创建标签、正式Release负责人确认
修改Secret或真实环境交给本机Codex,另行确认
修改Workflow权限独立任务处理
删除分支、Issue或历史证据负责人确认

这里约束的是动作风险,不是对某个模型的信任程度。即使以后连接能力更强,也没有必要让远端Agent绕过PR直接修改主分支。

落到仓库只需要几处小改动

这套协作不需要马上增加新的CI门禁或GitHub自动化。先修改四个位置就够了:

  • AGENTS.md继续保持工具无关,只写产品取舍、合并和发布等通用权限边界,不塞入某个模型的操作说明;
  • Git协作规范增加“一个分支一个当前写入者、固定SHA交接、共享分支不强推”几条规则;
  • PR模板增加当前阶段、当前写入者、当前候选、下一接棒者和下一步;
  • 研发手册补充本地worktree、远端分支、普通Review和固定SHA独立Review的关系。

最终形成的链路是:

原始想法

负责人和ChatGPT分析需求

Definition Draft PR
  ├─REQ
  ├─受影响的设计
  └─必要的ADR

负责人确认并合入主分支

Codex建立任务分支和本机worktree

实现、针对性测试、完整验证

Implementation Draft PR并固定HEAD

新的ChatGPT会话Review
  ├─阻塞问题:Codex修复并重新验证
  ├─后续问题:建立待复核Issue
  └─普通建议:明确记录去向

负责人确认并合并

记录实际合入提交、同步问题与版本关系

这样安排以后,ChatGPT不必复制Codex的本机开发过程,Codex也不必重新经历ChatGPT的全部需求讨论。GitHub保存两边交接时的准确状态,仓库文档保存最终结论,长对话只负责帮助形成判断,不再负责充当项目记忆。