Skip to content

C5|Plan / Goal:计划是方法,Goal 是完成条件 ​

先别把三样「计划」当成一个按钮 ​

长任务面前,产品里至少有三个叫 plan 的东西:/plan 协作模式、update_plan 工具、以及你自己在仓库里写的 plan.md。再叠一个 /goal,很容易理解成「再开一种会跑更久的模型」。

判断先说清楚:

  • /plan 改的是这一轮怎么合作:先调查、先问清楚、先出可交接的方案,默认不改仓库。
  • /goal 给这条 thread 挂上完成条件,agent 跨很多 turn 对着同一个 objective 干活,直到完成、暂停或被清掉。
  • update_plan 只是 Default 模式下的 待办清单 Event,进不了 Plan mode。

计划是方法;Goal 是挂在 thread 上的完成条件。E7 的 Automations 是时刻表,不是 Goal。并行两条 Goal 抢同一份工作区,才需要 E2 的 worktree。


1. /plan:先调查再改,是协作模式不是工具 ​

/plan 的说明是「switch to Plan mode」(tui/src/slash_command.rs:129)。实现是套上 Plan 的 collaboration mask(slash_dispatch.rs:86-96),不是调用 update_plan。TUI 可见的 mode 只有 Default 和 Plan(protocol/src/config_types.rs:673-685)。任务正在跑时 /plan 不可用(官方 CLI slash 文档;slash 表把 Plan 标成 task 期间受限)。模式作为 developer 说明书预设、和子代理 / /side 怎么切开,见 G5。

Plan 的行为写在 collaboration-mode-templates/templates/plan.md(crate 以 PLAN 常量 include,:1),不是你仓库根上那份可选的 markdown:

  • 直到 developer 消息明确结束,一直停在 Plan Mode;用户说「快去改」也只当成 规划这次执行,不当成执行(:7-9)。
  • 可以探索、读文件、跑不改仓库跟踪文件的测试/构建;不许 apply_patch、格式化改写、迁移、任何「在做计划里的活」(:17-39)。
  • 三阶段:先环境里找事实,再聊意图,再聊实现;能搜到的不要问用户(:41-58)。
  • 问人优先 request_user_input。ModeKind::allows_request_user_input 只对 Plan 为真(config_types.rs:699-701)。

自动 turn 既不能进入也不能离开 Plan(turn_input.rs:70-77)。mailbox 叫醒的后台工作不会把你从 Default 拽进 Plan,也不会在你规划时偷偷执行。这是 B1 InputQueue 在协作模式上的具体禁令。

没有独立的 Plan mode 会怎样?「先想想」变成普通 Regular turn,模型一边调查一边 apply_patch。方法必须是 mode,才能关掉变异工具、打开提问工具,而不靠 prompt 里的「请先不要改代码」。


2. update_plan 和外置 plan.md:都不是 Plan mode ​

update_plan 是 B2 那张表里的控制工具:参数是 explanation + [{step, status}],同时最多一个 in_progress(plan_spec.rs:7-47)。Handler 只做一件事:解析参数,发 EventMsg::PlanUpdate(handlers/plan.rs:93-96)。UI 画 checklist,磁盘上不一定出现文件。

它和 Plan mode 互斥。模板自己写了(plan.md:11-15):update_plan 不进入也不退出 Plan;在 Plan 里调用会报错。Handler 落地检查 turn.mode() == ModeKind::Plan 就拒绝(plan.rs:87-90)。Plan 的交付物是模型文本里的 <proposed_plan>(session/turn.rs 用 extract_proposed_plan_text),TUI 把它渲染成提案卡片,不是 待办工具的状态机。

仓库里再写一份 plan.md / PLAN.md,只是普通文件。发现链不会自动当说明书(C1 只认 AGENTS.md 和 fallback)。那是给人看的设计文档,或你让 agent 去 view 的材料,不是 collaboration template,也不是 Goal。官方建议 Goal 难写时先 /plan 把完成条件聊清楚,再 /goal——那是工作流,不是把 plan.md 配进 config。

三份「计划」焊在一起会怎样?Plan mode 里刷待办清单,一边说不改代码一边改清单;或把 git 里的 plan.md 当成完成条件,thread 重启后 Goal 丢了、文件还在,状态对不上。


3. /goal:完成条件挂在 thread 上,不是再开一种 mode ​

/goal:「set or view the goal for a long-running task」(slash_command.rs:131)。用法:/goal [<objective>|clear|edit|pause|resume](goal_display.rs:5)。feature goals 默认 开(features/src/lib.rs:1609-1612);没有这条 slash,再查 features.goals。

Goal 是 app-server 资源,不是 collaboration mode:

RPC作用
thread/goal/set设 objective / status / token_budget
thread/goal/get读当前
thread/goal/clear摘掉

ThreadGoal 带 thread_id、objective、status、token 与时间用量(app-server-protocol/.../v2/thread.rs:800-814)。状态机:Active / Paused / Blocked(UI 显示 stalled)/ UsageLimited / BudgetLimited / Complete(goal_display.rs:33-41)。官方:goal 文本既是起始提示也是完成标准;agent 可以连续工作很多步,你仍可以 steer。

约束来自持久化,不是来自 Plan 的「不许写文件」:

  • ephemeral thread 不能挂 Goal(thread_goal_actions.rs:18-21, 360-365)。codex exec --ephemeral 没有可 resume 的 session,完成条件无处安放。
  • objective 非空,过长(协议上限 MAX_THREAD_GOAL_OBJECTIVE_CHARS,官方写 4000 字)会落到附件 goal-objective.md,objective 改成「去读这个文件」(goal_files.rs:17-20)。
  • 已有 Active/Paused/… 时再 /goal 新目标 要确认替换;Complete 视为终态,可以直接开新 Goal(:368-378)。
  • 暂停的 Goal 在 /resume thread 之后会提示要不要继续(:54-84)。

模型侧曾用 <goal_context>…</goal_context> 注入(internal_model_context.rs:10-11),现归内部 fragment。Goal 不改 SandboxPolicy,也不自动进 Plan mode。长跑仍然受 B3 三套旋钮和 B4 compact 约束;它只是让 Session 在很多个 Regular turn 里记得「什么叫做完」。

没有「挂在 thread 上的完成条件」会怎样?你每轮把同一段目标贴回 composer,compact 之后模型忘掉验收命令;或者把 Goal 做成 mode,调查阶段也被强制「一直改到测试绿」。方法和完成条件必须分开。


4. 并行 Goal 必须配 worktree ​

Goal 的主键是 thread_id。一条 thread 同一时间一个 Goal。两条长任务 = 两条 thread。若都指向 同一份 Local checkout,两次 apply_patch 抢同一工作区,turn diff 和 git 索引一起烂——B2 并行门闩管的是一次 turn 里的工具,不管两条 Session。

产品把隔离放在 Git worktree 上(Worktrees):每个 checkout 一份文件树,共享 .git。自动化默认后台 worktree,避免冲人手上的 Local。本仓库有 Feature::Worktrees 和 codex-worktree;E2 写 Handoff 与 .worktreeinclude。C5 只钉一句:并行 Goal 是多 thread 问题,必须多工作区,不能靠再开一套沙箱政策。

没有 worktree、两条 Goal 并行会怎样?不是审批弹两次,是两个 agent 写同一组文件。沙箱的 workspace-write 对它们是同一块磁盘。隔离单位是 checkout,不是 AskForApproval。


5. 和 C 章其余部分怎么选 ​

你要的用
先搞清再动手/plan
跨很多 turn 做到可验证的完/goal,目标里写清验收
当前 Default turn 的步骤条update_plan(模型调,不是 slash)
给人看的设计文档仓库里的 markdown,不当协议
项目永远适用的测试命令AGENTS.md(C1)
你个人的做事偏好Memories(C2)
定时触发,不是完成条件Automations(E7)

难写的 Goal 先 Plan:官方 prompting 也这么接。Plan 结束(developer 消息退出 mode)再 /goal,完成条件才是聊出来的,不是第一句空话。


6. 结语:带走一句话 ​

/plan 是「先调查再改」的协作模式,/goal 是挂在可持久化 thread 上的完成条件——update_plan 和仓库里的 plan.md 都不是它们;两条 Goal 并行时,隔离靠 worktree,不靠再拧一档沙箱。