【codex】使用 PLANS.md 进行长时间问题解决

作者:是魔丸啊日期:2025/11/20

转载

Codex 和 gpt-5-codex 模型能够用于实现需要大量时间进行研究、设计和开发的复杂任务。本文介绍的方法是引导模型实现这些任务并促使其成功完成项目的一种有效方式。

这些计划既是详尽的设计文档,也是"动态文档"。作为 Codex 的使用者,您可以借助这些文档来审核 Codex 在启动漫长开发流程前所采取的实施方法。下文包含的 PLANS.md 与让 Codex 能够通过单次提示连续工作超过七小时的文档版本非常相似。

我们通过首先更新 AGENTS.md 来说明何时使用 PLANS.md,然后将 PLANS.md 文件加入代码库,从而让 Codex 能够利用这些文档。

AGENTS.md

AGENTS.md 是一个用于指导编程代理(如 Codex)的简单格式。我们定义了一个用户可以使用的简写术语,以及何时使用规划文档的简单规则。这里我们称之为"ExecPlan"。需要注意的是,这是一个自定义术语,Codex 并未经过相关训练。这个简写可以在提示 Codex 时用来将其引导至特定的计划定义。

以下是一个指导代理何时使用计划的 AGENTS.md 示例部分:

1# ExecPlans
2
3在开发复杂功能或执行重要重构时,从设计到实现全过程采用 ExecPlan(详见 .agent/PLANS.md)。
4

PLANS.md

以下是完整的文档内容。此文档中的提示经过精心设计,旨在为用户提供充分反馈,并引导模型精确实现计划规范。用户可能会发现,根据自身需求定制文件,或增删所需部分会更有帮助。

1# Codex 执行计划 (ExecPlans):
2
3本文档阐述了执行计划("ExecPlan")的要求,这是一种编程代理可以遵循、用于交付可用功能或系统变更的设计文档。请将读者视为本代码库的完全新手:他们仅拥有当前工作树和您提供的单一 ExecPlan 文件。没有历史计划记忆,也不涉及外部上下文。
4
5## ExecPlans  PLANS.md 的使用方法
6
7编写可执行规范(ExecPlan)时,必须 _严格遵循_ PLANS.md。若相关内容不在上下文中,请通读 PLANS.md 文件以重新熟悉。要透彻阅读(和重读)源材料以生成准确的规范。创建规范时,从框架开始,在研究过程中逐步充实。
8
9实现可执行规范(ExecPlan)时,不要向用户询问"下一步";直接进入下一个里程碑。保持所有部分更新,在每个暂停点添加或拆分列表项,明确说明进展和下一步行动。自主解决模糊问题,并频繁提交。
10
11讨论可执行规范(ExecPlan)时,在规范日志中记录决策以备查阅;必须明确说明对规范进行任何修改的原因。ExecPlans 是动态文档,应该始终能够仅凭 ExecPlan 重新开始工作,无需其他辅助。
12
13研究具有挑战性需求或大量不确定因素的设计时,利用里程碑实施概念验证、"玩具实现"等,以验证用户方案的可行性。通过查找或获取库源码进行深入研究,并包含原型以指导更完整的实现。
14
15## 要求
16
17**不可协商的要求:**
18
19* 每个 ExecPlan 必须完全自包含。自包含意味着其当前形态包含了新手成功所需的所有知识和指导。
20* 每个 ExecPlan 是动态文档。贡献者必须在取得进展、发现新问题和设计决策确定时更新文档。每次修订都必须保持完全自包含。
21* 每个 ExecPlan 必须使完全新手能够在没有代码库先验知识的情况下端到端实现功能。
22* 每个 ExecPlan 必须产生可验证的工作行为,而非仅仅满足定义的代码修改。
23* 每个 ExecPlan 必须用通俗语言定义每个专业术语,否则避免使用。
24
25目的和意图优先。先用几句话说明为何这项工作从用户视角很重要:用户在此修改后能做什么以前做不到的事,以及如何验证其工作状态。然后引导读者按确切步骤实现该结果,包括编辑内容、运行指令和应该观察到的现象。
26
27执行您计划的代理可以列出文件、读取文件、搜索、运行项目和执行测试。它不了解任何先前的上下文,也无法从早期里程碑推断您的意图。重申您依赖的任何假设。不要指向外部博客或文档;如需相关知识,请用您的语言将其嵌入计划中。如果 ExecPlan 基于先前的 ExecPlan 且该文件已提交,请通过引用纳入。如未提交,则必须包含该计划的所有相关上下文。
28
29## 格式规范
30
31格式和结构简单而严格。每个 ExecPlan 必须是标记为 `md` 的单一代码块,以三个反引号开始和结束。不要在其中嵌套额外的三反引代码块;当需要显示命令、记录、差异或代码时,将其作为该块内的缩进内容呈现。在 ExecPlan 内使用缩进而非代码块以求清晰,避免过早关闭 ExecPlan 的代码块。每个标题后使用两个换行符,采用 #  ## 等标题标记,并正确使用有序和无序列表语法。
32
33当将 ExecPlan 写入 Markdown (.md) 文件时,若文件内容 __ 包含单个 ExecPlan,应省略三个反引号。
34
35采用通俗散文体写作。优先使用完整句子而非列表。除非简洁会影响表意清晰,否则避免检查清单、表格和长枚举。检查清单仅允许在 `Progress` 部分使用,且在该部分是必需的。叙述部分必须保持散文风格。
36
37## 指导原则
38
39自包含和通俗语言至关重要。如果引入非日常英语的术语(如"daemon"、"middleware"、"RPC gateway"、"filter graph"),请立即定义并提醒读者它在代码库中的具体体现(如相关文件名或命令名)。不要说"如前所述"或"根据架构文档"。即使需要重复,也要在此处包含必要解释。
40
41避免常见失败模式。不要依赖未定义的专业术语。不要过度狭隘地描述"功能的字面要求",导致代码能编译但缺乏实际意义。不要将关键决策推给读者。当存在模糊性时,在计划中明确解决并说明选择该路径的原因。描述用户可见效果时倾向于充分说明,描述附带实现细节时倾向于简要说明。
42
43以可观察的结果来锚定计划。说明用户在实现后可以做什么、要运行的命令以及应该看到的输出。验收标准应表述为人类可验证的行为("启动服务器后,访问 [http://localhost:8080/health](http://localhost:8080/health) 返回 HTTP 200,响应体为 OK"),而非内部属性("添加了 HealthCheck 结构体")。如果变更是内部的,说明其影响如何验证(如运行变更前失败、变更后通过的测试,并展示使用新功能的场景)。
44
45明确指定代码库上下文。使用完整的代码库相对路径命名文件,精确命名函数和模块,并说明新文件创建位置。如果涉及多个区域,请包含简短的导向段落,说明各部分的关联方式,以便新手能自信地导航。运行命令时,显示工作目录和确切命令行。当结果依赖于环境时,说明假设条件并提供合理替代方案。
46
47确保幂等性和安全性。编写步骤时要支持多次运行而不会造成损坏或状态偏移。如果步骤可能中途失败,请说明重试或适应方法。如果需要迁移或破坏性操作,请明确备份策略或安全回退方案。优先采用可逐步验证的增量、可测试变更。
48
49验证是必须的,不是可选的。包含运行测试、启动系统(如适用)并观察其执行有用操作的指导。描述任何新功能或能力的全面测试。包含预期输出和错误消息,以便新手能区分成功与失败。尽可能展示如何证明变更是有效的(如通过小型端到端场景、CLI 调用或 HTTP 请求/响应记录)。说明适合项目工具链的确切测试命令及结果解读方法。
50
51收集证据。当步骤产生终端输出、简短差异或日志时,将其作为缩进示例包含在单一代码块内。保持内容简洁,专注证明成功的关键信息。如需包含补丁,优先使用文件范围差异或读者可按您指导重新创建的小段摘录,而非粘贴大型代码块。
52
53## 里程碑
54
55里程碑是叙述性的,非官僚化的。如果将工作分解为里程碑,请用简短段落介绍每个里程碑,描述范围、里程碑结束时新增的内容、要运行的命令及预期验证结果。保持其故事般的可读性:目标、工作、结果、验证。进展和里程碑是不同的:里程碑讲述故事,进展跟踪细粒度工作。两者都必须存在。不要仅因简洁而缩写里程碑,不要省略对未来实现可能关键的信息。
56
57每个里程碑必须独立验证并逐步实现执行计划的整体目标。
58
59## 动态计划和设计决策
60
61* ExecPlans 是动态文档。当做出关键设计决策时,更新计划以记录决策和背后的思考过程。将所有决策记录在 `Decision Log` 部分。
62* ExecPlans 必须包含和维护 `Progress` 部分、`Surprises & Discoveries` 部分、`Decision Log`  `Outcomes & Retrospective` 部分。这些都是必需的。
63* 当发现优化器行为、性能权衡、意外错误或逆向/撤销应用语义影响您的方法时,在 `Surprises & Discoveries` 部分记录这些观察,并附上简短证据(测试输出最佳)。
64* 如在实现过程中改变方向,请在 `Decision Log` 中记录原因,并在 `Progress` 中反映影响。计划既是下一位贡献者的指南,也是您的检查清单。
65* 在完成主要任务或整个计划时,撰写 `Outcomes & Retrospective` 条目,总结取得的成就、剩余工作和经验教训。
66
67# 原型里程碑和并行实现
68
69包含明确的原型里程碑是可接受的——且常受鼓励——当能降低更大变更的风险时。例如:向依赖项添加底层操作符以验证可行性,或在测量优化器效果的同时探索两种组合顺序。保持原型的增量性和可测试性。明确标记范围为"原型";描述运行和观察结果的方法;并说明升级或废弃原型的标准。
70
71优先采用保持测试通过的增量代码变更,后跟清理操作。并行实现(如在迁移期间同时维护适配器与旧路径)在降低风险或确保大型迁移期间测试持续通过时是可行的。描述如何验证两个路径及如何通过测试安全淘汰一个。当处理多个新库或功能区域时,考虑创建探索点来独立评估各功能的可行性,证明外部库按预期执行并在隔离环境中实现所需功能。
72
73## 优秀 ExecPlan 的框架
74
75```md
76# <简短、面向行动的描述>
77
78 ExecPlan 是动态文档。`Progress``Surprises & Discoveries``Decision Log`  `Outcomes & Retrospective` 部分必须在开发过程中保持更新。
79
80如果 PLANS.md 文件已提交到代码库,请在此处从代码库根目录引用该文件路径,并注意此文档必须根据 PLANS.md 进行维护。
81
82## 目的/大局观
83
84用几句话说明用户在此变更后获得了什么及如何验证其工作效果。说明您将启用的用户可见行为。
85
86## 进展
87
88使用带复选框的列表总结细粒度步骤。每个暂停点都必须在此记录,即使需要将部分完成的任务拆分为两个("已完成"vs."剩余")。此部分必须始终反映工作的实际当前状态。
89
90- [x] (2025-10-01 13:00Z) 示例已完成步骤。
91- [ ] 示例未完成步骤。
92- [ ] 示例部分完成步骤(已完成:X;剩余:Y)。
93
94使用时间戳衡量进展速度。
95
96## 意外与发现
97
98记录实现过程中发现的意外行为、错误、优化或洞察。提供简洁证据。
99
100- 观察:...
101  证据:...
102
103## 决策日志
104
105按以下格式记录执行计划时做出的每个决策:
106
107- 决策:...
108  理由:...
109  日期/作者:...
110
111## 结果与回顾
112
113在主要里程碑或完成时总结结果、差距和经验教训。将结果与原始目的进行对比。
114
115## 上下文和导向
116
117描述与任务相关的当前状态,假设读者对此一无所知。使用完整路径命名关键文件和模块。定义您将使用的任何非显而易见术语。不要引用先前的计划。
118
119## 工作计划
120
121用散文风格描述编辑和添加的序列。对每次编辑,命名文件和位置(函数、模块)及要插入或更改的内容。保持具体和最小化。
122
123## 具体步骤
124
125陈述要运行的确切命令及运行位置(工作目录)。当命令产生输出时,显示简短的预期记录以便读者对比。此部分必须在开发过程中更新。
126
127## 验证和验收
128
129描述如何启动或运行系统及要观察什么。将验收标准表述为行为,具有特定输入和输出。如涉及测试,请说明"运行 <项目测试命令> 并期望 <N> 个通过;新测试 <名称> 在变更前失败,变更后通过"。
130
131## 幂等和恢复
132
133如步骤可安全重复,请说明。如步骤有风险,请提供安全重试或回滚路径。完成后保持环境整洁。
134
135## 产物和注释
136
137包含最重要的记录、差异或代码摘录作为缩进示例。保持内容简洁,专注证明成功的关键信息。
138
139## 接口和依赖
140
141具有规定性。命名要使用的库、模块和服务并说明原因。指定里程碑结束时必须存在的类型、特征/接口和函数签名。优先使用稳定的名称和路径,如 `crate::module::function`  `package.submodule.Interface`。例如:
142
143 crates/foo/planner.rs 中,定义:
144
145    pub trait Planner {
146        fn plan(&self, observed: &Observed) -> Vec<Action>;
147    }
148

如果您遵循上述指导,单个无状态代理——或人类新手——可以从头到尾阅读您的 ExecPlan 并产出可运行的、可观察的结果。这就是标准:自包含、自给自足、新手友好、结果导向。

当修订计划时,必须确保您的更改全面反映在所有部分中,包括动态文档部分,并且必须在计划底部撰写说明,描述变更内容和原因。ExecPlans 必须说明几乎所有内容的缘由和方式。


【codex】使用 PLANS.md 进行长时间问题解决》 是转载文章,点击查看原文


相关推荐


基于C++的游戏引擎开发
普通网友2025/11/19

1、非修改序列算法 这些算法不会改变它们所操作的容器中的元素。 1.1 find 和 find_if find(begin, end, value):查找第一个等于 value 的元素,返回迭代器(未找到返回 end)。find_if(begin, end, predicate):查找第一个满足谓词的元素。find_end(begin, end, sub_begin, sub_end):查找子序列最后一次出现的位置。 vector<int> nums = {1, 3, 5, 7, 9};


Python 的内置函数 vars
IMPYLH2025/11/17

Python 内建函数列表 > Python 的内置函数 vars Python 的内置函数 vars() 是一个非常有用的工具函数,主要用于返回对象的 __dict__ 属性。它可以应用于模块、类、实例以及其他具有 __dict__ 属性的对象。以下是关于 vars() 函数的详细说明: 基本用法 不带参数调用: 当 vars() 不带参数调用时,它等同于 locals() 函数,返回当前局部作用域的符号表(通常是当前函数的局部变量)。 def example(): x = 1


Python 的内置函数 reversed
IMPYLH2025/11/16

Python 内建函数列表 > Python 的内置函数 reversed Python 的内置函数 reversed() 是一个用于序列反转的高效工具函数,它返回一个反向迭代器对象。以下是关于该函数的详细说明: 基本用法 语法:reversed(seq)参数:seq 可以是任何实现了 __reversed__() 方法的对象,或者支持序列协议(__len__() 和 __getitem__() 方法)的对象返回值:返回一个反向迭代器对象 支持的数据类型 列表:reversed([1,


Python 的内置函数 min
IMPYLH2025/11/15

Python 内建函数列表 > Python 的内置函数 min Python 的内置函数 min() 是一个非常有用的工具函数,用于返回给定参数中的最小值。这个函数可以接受两种形式的参数: 多个单独的参数 min(a, b, c, ...) 它会返回这些参数中的最小值。 一个可迭代对象(如列表、元组、集合等) min(iterable, *[, key, default]) 它会遍历可迭代对象,并返回其中的最小值。 参数说明: iterable:必须是一个可迭代对象(如列表、元


12 节课解锁 AI Agents,让AI替你打工(一): 简介
AI大模型2025/11/14

本文较长,建议点赞收藏。更多AI大模型应用开发学习视频及资料,在智泊AI。 本系列教程主要是为了探索 AI Agent 的设计原理与真实世界应用 随着大语言模型(LLMs)的出现,人工智能取得了巨大飞跃。这些强大的系统彻底改变了自然语言处理,但当它们与智能体(即自主推理、规划和行动的能力)相结合时,其真正潜力才得以释放。这就是大语言模型智能体发挥作用的地方,它代表了我们与人工智能交互和利用方式的范式转变。 图片来源:letta 本文旨在全面概述 AI Agent,深入探讨其特征、组件和类


Lua 的 Coroutine 模块
hubenchang05152025/11/13

#Lua 的 Coroutine 模块 请查看 Lua 标准库模块列表 了解更多相关 API。 函数说明coroutine.create创建协程对象coroutine.close 关闭协程对象coroutine.resume恢复协程coroutine.yield让出协程coroutine.wrap创建协程对象,返回一个恢复函数coroutine.isyieldable检查协程能否让出coroutine.running获取正在运行的协程对象coroutine.status获取协程状态 Lua


Node.js 开发环境搭建全攻略(2025版)
Java私教2025/11/11

本文将详细介绍如何在本地搭建一个高效、可维护的 Node.js 开发环境,适用于 Windows、macOS 与 Linux。无论你是后端新手还是资深全栈工程师,都能通过本文快速构建一个标准化的 Node.js 开发环境。 一、什么是 Node.js? Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,它让开发者可以在服务器端运行 JavaScript。 它以 事件驱动、非阻塞 I/O 的特性著称,非常适合构建高性能的 Web 服务和微服务架构。 二、安


类比前端知识来学习Java的Spring Boot实现MySql的全栈CRUD功能——搭配Svelte+Vite
水冗水孚2025/11/9

前言 本文梳理了后端的相关操作流程环节 使用Svelte+Vite(前端)搭配Spring Boot(后端) 实现了一个增删改查全栈项目 有助于前端更好理解后端java的分层思想,数据流转控制 和Svelte尝鲜学习了解 完整前后端代码在github:github.com/shuirongshu… 大道至简,一些知识点是相通的比如——python里面也有闭包这个概念 所谓编程即:学习规则语法、理解规则语法、合理运用规则语法、从而自定义规则... Java、Spring、Spring Bo


Bash 的 if 条件语句
hubenchang05152025/11/7

#Bash 的 if 条件语句 Bash 的 if 条件语句的语法为: if 条件命令 then 命令 ... elif 条件命令 then 命令 ... else 命令 ... fi 其中,条件命令返回成功(0)时为真(true),返回失败(非 0)时为假(false)。 如果省略(部分)换行,则需要使用分号(;)区分: if 条件命令; then 命令; 命令; elif 条件命令; then 命令; 命令; else 命令; 命令; fi


hive的SQL练习3
普通网友2025/11/3

根据如上表格信息,实现如下需求: 查询五一期间(2023-05-01 ~ 2023-05-07),每个餐厅的订单总数量及排名with t as ( select *,        count(1) over(partition by restaurant_id) countNum        from orders where substr(order_date,1,10)     between '2023-05-01' and '2023-05-07' ) select d

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读