Codex:把本地代理改动关进可审查工作区
一个修复“只改文案”的任务,最后把构建脚本删掉,往往不是模型把 rm 拼错了,而是执行链一开始就没有边界。事故通常是这样发生的:开发者在桌面应用里打开了父目录,提示里说“清理旧的发布说明”,代理搜索到了多个同名文件;终端命令又把一个临时目录当成可删目录;任务结束时只留下“已完成”的自然语言总结,没有 git diff、没有退出码、也没有人知道它读过哪些环境变量。第二天 CI 才告诉团队静态站点已经无法构建。
Codex 适合承担本地仓库中的分析、编辑、命令执行、浏览器验证和审查工作,但它不是一个替团队承担变更责任的黑箱。可靠的用法把聊天任务变成短而清晰的证据链:入口固定在正确工作区,持久规则写进仓库,工具权限按动作收紧,补丁通过实际测试和 diff 证明,Git 只承载被授权的历史变化。下面用一个虚构的 sample-inventory 项目重建这条链。
安装与认证先证明“正在运行哪一个 Codex”
CLI 适合在终端、脚本和 CI 中建立可重复入口。已经具备受支持 Node.js 与 npm 的开发机,可以从 OpenAI 发布的 npm 包安装;升级也应沿用同一来源,避免系统包、旧全局包和编辑器内置二进制互相覆盖。
npm install --global @openai/codex
codex --version
Get-Command codex | Format-List Source,Version
codex login
codex login statuscodex login 默认进入浏览器登录流程;codex login status 用来确认当前认证方式,而不是打印凭据。需要 API key 的人工终端不要把 key 放进命令行参数或仓库文件,使用标准输入完成登录;非交互作业则把 CODEX_API_KEY 只注入单次 codex exec 进程。ChatGPT 登录、API key 与企业工作区发放的 Codex access token 是不同的认证路径:前两者分别受 ChatGPT 工作区策略和 API 组织策略约束,access token 只适合管理员允许的可信脚本或私有 runner。不能因为桌面应用已登录,就假设另一个 shell、WSL 或 CI runner 自动共享会话。
printenv OPENAI_API_KEY | codex login --with-api-key
codex login status
# 共享机器退出时清除当前 Codex 凭据
codex logout企业自动化确实需要 ChatGPT 工作区能力时,由管理员发放并轮换 access token,再通过标准输入登录;普通 API 调用仍使用 Platform API key,不要把两者做成同名 secret。无论采用哪条路径,runner 都应是私有且受信任的,凭据只在任务进程中出现,并在作业结束后撤销环境引用。
正向验证是版本、可执行文件路径、登录状态和项目根都符合预期,再启动一次只读调查。反向验证是在 Windows 与 WSL 各执行 codex login status:若两边状态不同,这是两个 CODEX_HOME 与凭据存储没有共享的证据,不应复制 auth.json 到仓库解决。若升级后仍启动旧版本,先检查 Get-Command codex -All 或 command -v -a codex 的路径顺序,再移除已经确认不用的旧入口。
桌面应用、IDE 扩展与 CLI 共享一部分工作理念,却不是同一个安装和权限进程。Windows 桌面应用可使用原生 PowerShell 代理或切换 WSL2;切换后要重启应用,而且仓库最好放在与代理运行环境一致的文件系统一侧。混用 C:\work、/mnt/c/work 与 \\wsl$\... 会带来路径、Git、文件监听和权限判断差异,团队应选择一个主运行环境并在真实工具链上验证。
先把事故还原成可判断的对象
最先要解决的不是“让代理更聪明”,而是让它知道什么是任务目标、什么是工作区、什么是禁止区。一个目录可以同时包含 Web、服务端、迁移脚本、运维草稿和本机缓存;人眼看到的是项目名,工具看到的是可达路径。若启动点太宽,搜索和 shell 的成功率越高,误碰文件的机会也越高。
在开始编辑前,先由人确认当前目录、分支和已有改动。这里的命令不修改仓库,输出构成后续判断的起点。PowerShell、bash 和 zsh 的细节可以不同,但要保留同一组事实:当前位置、Git 根目录、分支、未提交文件和目标路径。
Get-Location
git rev-parse --show-toplevel
git branch --show-current
git status --short
Get-ChildItem -Force .\AGENTS.md, .\.codex -ErrorAction SilentlyContinue预期现象是 git rev-parse --show-toplevel 指向 sample-inventory,git status --short 中的每一项都能解释来源。若命令输出的根目录是更大的聚合目录,或者状态中已有不认识的 .env、锁文件、草稿和他人变更,就不要把“顺便整理一下”交给代理。先缩小到项目根,或者只开一个隔离工作树;必要时将任务改成只读调查。
这一步是正向实验:在正确根目录提出“定位订单 API 的校验逻辑,先不要编辑”后,代理应只给出文件路径、调用关系和疑点。反向实验则是故意从父目录启动同一请求。预期失败证据不是“它看起来有点慢”,而是搜索结果同时包含两个项目的 package.json,或 git rev-parse 返回了错误仓库。那时应退出任务并重新进入正确目录,不要让后续提示词抵消一个错误的文件系统入口。
桌面、CLI 与工作区不是同一个权限域
Codex 可以在桌面应用、CLI、IDE 以及托管任务等不同入口工作。对一个需要连续检查、本地运行和人工确认的仓库修复,桌面或 CLI 的本地工作区通常更直观:人可以看见路径、diff、终端输出和浏览器页面。对纯阅读、设计讨论或不允许写入的调查,先使用只读状态;这会让“分析完成”与“代码已变”保持可区分。
不要把“本机可访问”误认为“任务允许访问”。本机浏览器可能已登录生产后台,shell 可能带着云凭据,父目录可能含有多个客户仓库。这些能力必须按任务收缩。一个实际可执行的工作说明可以这样写进提示,而不是把秘密和全盘路径贴进对话:
在当前 Git 工作区处理 ISSUE-DEMO-17。
允许读取 src、tests、package.json 与 AGENTS.md;不要读取 .env、secrets、dist 或上级目录。
先解释最小修改计划,获得确认后再编辑。
只运行 package.json 已声明的检查;不要安装依赖、不要访问外网、不要提交或推送。
结束时给出改动文件、git diff --check、实际运行命令及其退出码;未运行项单独列出。这段文字不能取代系统层的沙箱和审批,却能让代理在调用工具前有稳定的判断基线。Codex 的审批策略决定何时需要用户同意某个命令;沙箱策略决定可读写的路径和可用能力。两者分别处理“是否询问”和“即使不询问也能否越界”。默认保持收紧,只有当一个可信仓库、一个明确动作和一个可观察的必要性同时存在时,才临时扩大授权。
浏览器也应被当作有副作用的工具,而不是搜索框。访问本地开发地址通常可以验证渲染、登录跳转和网络错误;访问真实管理台可能暴露客户数据,点击保存还会改变状态。测试浏览器使用合成账号、隔离环境和可撤销记录。页面截图只是视觉证据,不能证明后端断言、权限规则或数据库迁移正确。
AGENTS.md 让重复判断落在仓库里
一次次在聊天里重复“不要改锁文件”“测试后给 diff”容易漂移。仓库级 AGENTS.md 更适合保存长期有效的构建命令、目录所有权、测试约定、审查标准和敏感信息规则。Codex 会在工作区中采用适用的指令;更靠近当前目录的指令可以表达子目录的特殊要求。因此它应短、可验证、贴近真实摩擦,而不是堆砌口号。
下面是合成项目的最小样例。它没有把 access token 写进文件,也没有授予提交权限;它只告诉工具怎样证明变化正确。
# sample-inventory agent guidance
- 修改 `src/` 前先读取相邻测试;不要编辑 `infra/`、`.env*`、`secrets/` 和 `dist/`。
- Node 命令统一使用 `npm run <script>`,禁止临时更改 lockfile。
- API 行为变化必须更新 `tests/api/`,页面变化必须运行对应的浏览器测试。
- 完成时执行 `git diff --check` 与最小相关测试,报告命令、退出码和未执行检查。
- 未经明确请求,不执行 `git commit`、`git push`、发布、数据迁移或外网写入。反向实验很简单:将一条模糊规则写成“谨慎处理文件”。让代理处理一个包含 src/、generated/ 和 dist/ 的改动,观察它是否能在动手前指出边界。大概率不能,因为“谨慎”没有文件模式、验证命令和失败动作。替换成上面的规则后,成功证据应是它先读取测试、将构建产物排除在 diff 外,并在要执行 Git 写操作前停下来请求决定。
指令文件不是访问控制器。它不能可靠阻止恶意脚本、插件或用户主动复制秘密,也不能替代操作系统权限、Git 服务端规则和密钥管理。把它当作团队可审查的行为契约:规则变更要走普通代码评审,失效后要回到事故修改,而非悄悄继续增厚。
配置层级把个人偏好、项目约束和组织策略分开
Codex 的持久设置使用 TOML。个人默认值放在 ~/.codex/config.toml,可信仓库可在 .codex/config.toml 放项目设置;Codex 从项目根走到当前目录加载沿途配置,离当前目录更近的项目层覆盖更远的项目层。命令行参数和 -c key=value 适合单次覆盖。项目配置只有在仓库被信任时才加载,而且不能重定向认证提供方、遥测或机器级通知等宿主设置。这条限制避免克隆一个仓库就悄悄把凭据送往另一个地址。
下面的项目配置为普通开发任务保留工作区写入,在需要突破沙箱时询问。approval_policy 控制何时询问,sandbox_mode 控制进程实际能够触达什么;两者不是同一个开关。
# .codex/config.toml
approval_policy = "on-request"
sandbox_mode = "workspace-write"
allow_login_shell = false
[sandbox_workspace_write]
network_access = false用 CLI 做等价的临时实验时,可以显式运行 codex --sandbox workspace-write --ask-for-approval on-request。正向现象是在项目内读取、编辑和运行已有测试,而访问外部目录或网络时停下并说明理由。反向实验改成 --sandbox read-only 后请求写入合成文件,正确结果是写入被拒绝;若文件仍然产生,应检查实际入口是否读取了另一份配置或是否运行在全访问模式,而不是继续用提示词假装只读。
sandbox_mode = "danger-full-access" 与 approval_policy = "never" 组合意味着既没有工作区沙箱,也没有交互审批,不应成为开发机默认值。组织还可以用受管 requirements.toml 限制允许的沙箱与审批组合;本地 config.toml 不能把管理员的上限放宽。架构师应把“默认能力”与“任务临时升级”分开记录:谁申请、为何需要、持续多久、执行了哪些外部动作、何时收回。
配置失败的证据通常很具体:启动警告指出项目键被忽略,写入根目录被拒绝,网络命令没有出口,或一次性 -c 覆盖解析成了字符串。排查顺序是确认信任状态、配置文件位置、TOML 语法、层级覆盖和命令行参数;不要直接切换到全访问来证明业务代码能跑。
MCP 与 hooks 都是新的执行入口
MCP server 把工单、浏览器、文档、数据库或内部 API 变成代理工具。添加 server 前先问四个问题:它能读什么、能写什么、凭据由谁发放、输出是否可能包含不可信指令。CLI 可以列出和添加 server,但共享配置只能保存公开地址、命令和环境变量名,token 仍由本机密钥存储或 CI secret 注入。
codex mcp add issue-readonly -- node ./tools/issue-mcp.mjs
codex mcp list
codex mcp --help生产落地在受控配置中引用环境变量,并让 server 只暴露所需的只读工具。正向实验调用合成工单 DEMO-17,记录工具名、返回字段和零写入;反向实验撤掉凭据后必须认证失败,不能静默使用某位开发者的缓存身份。停用时移除 server、撤销 OAuth 或 token,并检查它是否留下本地缓存和外部写入。
hooks 解决的是生命周期中的机械拦截与记录,不是替代沙箱。Codex 可从配置层旁边的 hooks.json 或 config.toml 内联 [hooks] 加载 hook;可信项目的 .codex hook 才会生效。一个层同时放两种表示会造成重复加载警告,因此选一种即可。
[[hooks.PreToolUse]]
matcher = "^Bash$"
[[hooks.PreToolUse.hooks]]
type = "command"
command = 'python "$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py"'
timeout = 30
statusMessage = "Checking shell policy"PreToolUse 适合在动作发生前拒绝破坏性命令;执行后的 hook 只能观察已经发生的事实。非受管命令 hook 在首次运行或内容发生变化后还需要重新审查其定义,未建立信任时会被跳过。多个匹配 hook 可能并发启动,所以一个阻断 hook 不能阻止同一事件上的另一个 hook 已经开始执行;涉及强制合规时,应由受管配置、沙箱和操作系统权限共同兜底。hook 本身也是代码,要固定解释器和依赖、限制超时、审查输入输出,并避免记录完整环境变量和工具载荷。反向实验应使用合成临时目录,验证危险命令被拒绝且目录仍存在;不能在真实工作区用破坏性命令“测试拦截是否可靠”。
计划先暴露假设,再进入 apply patch
复杂任务中,“先计划”不是多写一页文档,而是让依赖、风险和验证顺序在编辑前可见。Codex 的计划模式适合先搜索、提问和拆解,再进入实现;小改动则可以用短计划代替冗长分解。有效计划应包含目标文件、预期行为、最小测试、可能的回退点和不应触碰的对象。没有这些事实的计划只是把不确定性换成编号列表。
例如,库存接口在负数数量时返回 500。一个可审查的计划会说:先追踪 POST /adjustments 的参数校验与异常映射;再只修改校验分支和 API 测试;最后运行该测试文件与类型检查。它不会承诺“顺手重构全部库存模块”,也不会把数据库表、部署流水线和无关 UI 纳入同一个补丁。
编辑时优先使用结构清晰、补丁最小的方式。apply_patch 的价值不在名字,而在于它要求明确的旧文本和新文本,使修改天然靠近可审查 diff。下面的示例表达一次有限修复:
*** Begin Patch
*** Update File: src/adjustments/validate.ts
@@
- if (!Number.isInteger(input.quantity)) {
+ if (!Number.isInteger(input.quantity) || input.quantity < 0) {
throw new ValidationError("quantity must be an integer");
}
*** End Patch正向证据不只是补丁成功应用。补丁后应立即读回附近代码,确认错误信息、调用方和测试语义仍一致;随后新增或调整一个明确的失败用例。反向实验可以把旧文本故意改成相近但不相同的版本。安全的补丁工具应拒绝模糊命中或产生冲突,而不是猜测替换。拒绝输出是好证据:它迫使执行者重新读取文件,而不是让“差不多”进入代码库。
大范围格式化、依赖升级和生成文件最容易把一个修复膨胀成难以审查的 diff。此时分两次变更:先完成行为修复和聚焦测试,再单独提出机械变更。审查者能够把每个测试失败映射到一个原因,回滚也不会把不相关清理一起丢掉。
shell、浏览器和外部工具都要有审批理由
工具调用的风险不按“是不是 AI”划分,而按效果划分。搜索代码和读取 Markdown 通常低风险;写文件、执行 shell、安装包、访问网络、打开浏览器、调用 MCP 服务和操作 Git 的风险依次增加。任何能间接调用 shell 的工具同样算 shell 风险,例如一个 MCP server 可能在后台访问数据库或创建工单。
对 shell 命令,先说明它读什么、写什么、为何必须执行、预计多久完成。命令应尽量可重复、参数固定、针对当前仓库。避免带变量展开的删除、全局安装、把远程内容直接管道给解释器,以及“先试试”的发布命令。下面是一组用于补丁检查的低副作用序列:
git diff --check
git diff -- src/adjustments/validate.ts tests/api/adjustments.test.ts
npm run test:api -- --runInBand adjustments
npm run typecheck预期输出包括空的 git diff --check、仅限两个目标文件的 diff、测试用例通过以及类型检查退出码为零。任何一个失败都应被保留,而不是在总结里改写成“基本完成”。例如,git diff --check 报出 trailing whitespace,说明补丁还没有达到提交质量;类型检查报错可能揭示接口返回值已被改变。先修复或明确记录阻塞,才谈继续。
浏览器验证也采用同样顺序。先启动合成项目的本地服务,再在 http://127.0.0.1 的测试页面输入负数,确认页面给出校验错误且没有发出写入请求;不要拿生产 URL 做“冒烟”。若必须调试已授权的远端环境,使用最小权限账号,先记录目标环境和允许动作,完成后关闭会话并清除下载文件。浏览器保存的 cookie、自动填充和下载目录都是凭据边界的一部分。
任务协作的产物是结论,不是互相扩权
一个较大的任务可以拆成调查、实现、测试设计和代码审查等并行工作。协作的收益来自减少主线程的等待,不来自让多个执行者同时拥有全盘写权限。适用的 AGENTS.md 或任务说明可以要求委派;而每个协作任务仍继承当前的沙箱和审批约束。把一个任务委派出去不会自动让它获得额外目录、网络或 Git 权限。
可采用“读多写少”的分工:调查者只返回文件路径、调用链和假设;测试设计者只提出可执行断言;实现者在单一工作树写补丁;审查者只检查 diff、错误路径、测试缺口和敏感数据。主线程合并这些结论时,要逐条回到文件与命令输出。一个流畅的汇总不等于多个独立事实已经成立。
协作最常见的失败是两个执行者编辑同一文件,或者一个执行者依据过期 diff 编写测试。症状是补丁无法应用、同一行反复被改写、测试名称与最终行为不对应。恢复动作不是让双方“再同步一下”,而是停止其中的写入,将当前 diff 作为唯一基线,重新分配不重叠的文件所有权。对于跨目录大改动,使用独立 Git worktree 能隔离未提交状态;但 worktree 不是复制权限,敏感文件、远端凭据和受保护分支依旧需要单独控制。
任务交接应包含可运行的信息:当前分支与基线、已改文件、尚未解决的问题、实际执行的命令和结果、没有运行的检查、风险以及推荐的下一步。不要把完整对话、浏览器 cookie、终端历史或含用户数据的日志当作交接附件。
Git 边界让“完成”停在可恢复的位置
Git 是判断代理是否真的只改了预期内容的第一道工具,但它不会自动保证正确。每次编码循环至少要检查三件事:状态中是否有陌生文件、diff 是否只含预期路径、暂存区是否没有混入他人工作。下面的检查先观察再决定,不会创建提交。
git status --short
git diff --name-only
git diff --check
git diff --stat
git diff -- src/adjustments/validate.ts tests/api/adjustments.test.ts若 git status --short 出现不属于当前任务的 M docs/roadmap.md 或 ?? .env.local,正确反应是停止并保留它,而不是用 git restore .、git clean -fd 一把清空。那些命令可能删除他人未保存成果或本机配置。若自身补丁需要撤销,优先用路径精确的恢复操作,并在执行前再次读取差异;已经共享的提交则应使用可追踪的 git revert,而不是重写公共历史。
提交和推送是独立动作。测试通过、diff 干净,不自动等于可以提交;提交完成,也不自动等于可以推送或创建拉取请求。团队要在指令中明确谁拥有分支、提交信息约定、是否允许自动推送、是否需要签名以及保护分支要求。代理可以准备变更说明和建议命令,但没有授权时应把 Git 写操作留给负责人。
审查时把 AI 的自然语言结论降级为索引。审查者先看被修改的入口、错误分支、配置影响、测试断言和依赖变化,再回看工具摘要。对于权限、鉴权、支付、迁移、删除、外部请求和序列化等高风险区域,额外追问:反例在哪里?失败是否被测试?错误会不会把秘密写入日志?回滚是否不依赖原作者在线?
验证要区分已经发生与只是建议发生
一次代理任务的交付可用一个固定而简短的事实格式。它避免把“建议运行”伪装成“已经运行”,也让接手者能独立重放关键判断:
改动:src/adjustments/validate.ts;tests/api/adjustments.test.ts
已运行:git diff --check(退出码 0);npm run test:api -- --runInBand adjustments(退出码 0)
未运行:npm run e2e(本机未启动浏览器测试依赖)
审查观察:负数分支新增;未发现 lockfile 与生成目录变化
残余风险:未验证真实支付网关;该任务没有访问远端环境
回退入口:恢复上述两文件的工作树改动,或对已共享提交执行 git revert这里的“未运行”不是失败,也不是瑕疵。它是对证据强度的准确描述。真正危险的是测试未跑、权限未获批或环境不可用时,仍宣称“已验证”。若任务涉及 UI,浏览器测试、截图和人工点击都应说明运行环境与观察结果;若涉及接口,记录请求、状态码和断言而不是复制真实响应体。
正反实验应围绕同一行为设计。正向:quantity=3 返回成功且库存变化符合预期。反向:quantity=-1 返回客户端错误,库存不变,错误消息不泄露内部堆栈。若只测正向成功,负数修复可能依旧从另一条路径穿透;若只测错误文本,服务可能已先写库后报错。测试必须将可观察结果绑定到不变量,而不只是绑定到某次实现。
非交互任务使用 codex exec,它适合窄而可判定的检查,不适合无人监督地自由修改、提交和发布。自动化调用应固定工作目录、沙箱与审批策略,把输出交给 schema 校验和后续门禁。--json 输出事件流,--output-schema 约束最终结果结构;两者都不能代替真实测试。
CODEX_API_KEY="$CI_CODEX_KEY" codex exec \
--sandbox read-only \
--json \
--output-schema ./ci/codex-review.schema.json \
"审查当前 diff,只报告带文件证据的正确性、安全与测试缺口;不要编辑、提交、推送或调用外部写操作。" \
> codex-review.jsonl
node ./ci/validate-codex-review.mjs codex-review.jsonlCI 只在受信任事件中注入短期 secret,并关闭仓库凭据持久化。对 fork、issue 文本、网页和 MCP 返回值一律按不可信输入处理,不能让它们决定 shell 参数或扩大权限。设置 runner 超时、并发上限、输出保留期和人工审批;代理退出码为零只说明进程完成,不说明测试通过、补丁安全或发布获批。
数据出站与遥测必须分别建账
“代码在本机执行”不等于“代码内容不离开本机”。为了生成结果,当前提示、模型输出以及被放进上下文的代码和工具结果会沿所选认证路径发送给 OpenAI;ChatGPT 登录遵循所在 ChatGPT 工作区的数据控制、保留与驻留策略,API key 遵循对应 API 组织的策略。团队在批准仓库接入前,应先确定身份类型、允许进入上下文的数据级别、禁止读取的目录、会话输出保存位置和离职撤权路径,不能拿个人账户的设置推断企业工作区。
Codex 的 OpenTelemetry 导出默认关闭,只有在用户级配置显式启用 exporter 后才向团队采集端发送运行事件。即使默认不发送,启用前仍要审查事件字段:会话标识、模型、沙箱和审批结果属于运维元数据,log_user_prompt 会进一步扩大数据面,工具结果事件还可能包含输出片段。项目级 .codex/config.toml 不能设置 otel,这是宿主控制面;采集端要设置访问控制、保留期和脱敏规则,不得把原始 prompt、secret 或客户代码当作普通指标。
可以用一个不含业务代码的合成仓库做反证:用户配置不声明 [otel] 时,企业采集端不应出现该会话;随后只在隔离环境启用指向测试 collector 的 exporter,运行一次只读任务,预期只看到经过批准的元数据。若 collector 收到 prompt 或工具输出片段,应先停止导出并清理测试事件,再检查 log_user_prompt、collector 处理器和下游存储,而不是把“已经加密传输”当作允许长期保存的理由。
清理、回滚与资源成本是每天都在发生的维护
代理任务会留下会话上下文、终端输出、下载文件、浏览器缓存、临时测试数据、worktree、插件配置和可能的凭据引用。退出不是关掉窗口,而是复核这些副本仍是否必要。示例项目中的清理顺序可以是:停止本地服务;删除合成数据;关闭浏览器测试上下文;确认没有把 .env、日志或截图加入 Git;删除不再使用的 worktree;撤销为任务临时开放的目录和网络权限。
回滚也要先分类。未提交的局部补丁使用精确路径恢复;已提交但尚未共享的分支变更可在负责人确认后重写;已经共享的改动采用新提交反转;涉及外部服务或数据迁移时,代码回滚和数据恢复是两条不同链路,必须分别演练。绝不能用“回滚代码即可”掩盖已发送的消息、已创建的工单或已写入的远端数据。
资源成本不仅是调用费用。长上下文会带入无关代码与敏感信息,反复搜索会消耗时间,递归协作会增加 token、延迟和本机资源,宽权限会增加审查成本。团队应把复杂任务先切成可验证阶段;为调查设置明确的问题和停止点;为非交互或批量运行设置轮次、预算、超时和输出大小上限;把浏览器与 MCP 调用作为可计量的外部动作记录。不要在公开文档中写死会变化的套餐、价格或可用额度,而应在组织的采购和账户控制面查看当前数据。
长期维护的关键不是收集更多提示词,而是把重复事故反映到可以审查的资产中:把误改目录写入 AGENTS.md,把危险 shell 模式加入审批或 hook 规则,把失败用例留在测试套件,把敏感文件排除规则写进仓库设置,把工具升级纳入小范围回归。这样,下一次代理开始工作时继承的是团队已经证明过的边界,而不是上一位使用者的记忆。
故障分层与日常检查表
当一次执行不符合预期时,排查顺序也应固定在动作层,而不是从生成的解释里找安慰。先确认任务是否仍在预期工作区,随后重读适用指令和最近的 Git 状态;再查看最后一次工具调用到底是被拒绝、在沙箱外失败、还是命令本身返回非零;最后才判断补丁、测试或浏览器观察是否需要重跑。三种失败的恢复方式不同。权限拒绝说明动作需要重新授权或缩小;路径拒绝说明工作区或沙箱边界不正确;命令失败说明代码、依赖或环境尚未满足断言。把它们混成“代理没成功”会诱导下一次直接扩大权限。
例如,代理请求执行测试却收到“找不到命令”,第一证据是 package.json 中是否存在对应脚本,以及 shell 是否位于项目根;不应马上授予网络权限去安装包。浏览器页面打不开时,先检查本地服务端口、启动日志和页面 URL;不要改用一个真实环境来证明 UI。补丁应用失败时,读取目标文件的当前文本和 Git diff,确认是否有并行改动;不要把旧补丁强行放宽为全局替换。每个诊断分支都应留下短记录:观察到的错误、已排除的条件、采取的最小恢复动作和恢复后的可观察结果。
证据保留也必须克制。应保留命令名称、退出码、关键错误行、被改文件和必要截图;不应默认保留完整提示、终端滚屏、环境变量、生产响应体或浏览器存储。对于需要交给他人复现的故障,提供一个不含秘密的最小命令和合成输入比上传全量日志更有用。对于无法在本机验证的路径,写明限制和下一位应执行的检查,不要用模拟输出替换真实执行。这样既能让审查者恢复判断过程,也不会为调试再制造数据泄露面。
回退前也要复核权限变化。有时补丁本身已经撤销,但为排障临时允许的网络访问、额外目录、浏览器登录或 MCP 连接还留在会话与配置中。把这些状态逐项还原到任务开始前:关闭临时服务、删除测试数据、收回目录访问、退出外部登录并确认 Git 只剩预期改动。一个完成得很快但遗留宽权限的任务,会把风险转移给下一次看似无关的操作。
最后重新执行一次 git status --short,把它作为退出前的状态快照,而不是依赖记忆判断工作树是否干净;若状态与任务开始时不同,逐项说明来源。
工作区、分支和已有改动已确认,目标文件与禁止目录清楚。适用的 AGENTS.md 已读到,任务提示只补充本次目标与风险。读取、编辑、shell、浏览器、MCP、网络和 Git 写入按动作分别授权。
每个补丁都有对应 diff;每个“通过”都有命令、输出或可观察断言。未执行检查、环境限制和残余风险与成功结果分开写。清理临时数据、会话副本、worktree、浏览器状态和暂时授权;共享历史只用可追踪方式恢复。
当工作区、规则、工具调用、补丁、测试和退出动作都能被另一位工程师重新检查时,Codex 才是把工作推进得更快的协作者,而不是一个需要事后猜测的第二个操作者。
