待办任务
对话是你得坐在它面前的东西。任务则是你写下来之后就可以走开的东西。
待办任务就是这样一个队列,智能体会自己一件件做完。每个任务都会拿到一份独立的代码副本——项目旁边的一个 git worktree——因此可以同时跑好几个,既不会互相干扰,也不会打扰你手头正在改的那份代码。某个任务做完后,它不会自行合并:它会移到验收那一列等你过目。你读一下 diff,或者打回去让它改,或者点通过——只有到这时候,它才会落到你的分支上。(你也可以让某个文件夹自己把已验收的任务落地,但在你主动要求之前它是关闭的。)


截图摄于 0.23——那时这个页面还叫「任务看板」,带着 Beta 角标和一个「全部处理」按钮。这两样如今都没有了,其余部分与今天一致。
任务是什么
一个任务就是一个标题、一段描述,以及用来执行它的 composer 状态——一个智能体、一种模式,以及该智能体接受的各种选项。仅此而已。其余的一切由 Codeg 提供:隔离的检出、分支、调度,以及末尾那道验收关卡。
它沿着一条固定的流水线推进:
待办 → 排队中 → 初始化中 → 进行中 ⇄ 等待输入 → 待验收 → 合并中 → 已完成失败和已取消是从它旁边岔出去的支路。全程有两条规则成立。「已完成」只由两处写入——一次经 git 核实确实落地的合并,以及对没有东西可合并的任务点完成——而一旦写入就绝不回退。以及任务绝不会跳过验收这一停顿:通往已完成的每一条路都要经过它,自动合并也不例外。
这正是任务与它旁边那两样东西的区别所在。对话是你和一个智能体一轮一轮地聊,在你自己的工作树里。自动化是一个按时钟触发的会话。任务两者都不是:它是一份工作单元,有明确的起点、一个用来发生的隔离场所,以及末尾的一道验收关卡。
打开待办任务
待办任务位于左侧边栏,在自动化下方。它像自动化一样接管主区域——右上角的返回箭头可以带你回到会话,你原先打开的标签页依旧在那儿——并在有任务等着你时带上一个小小的计数徽标:凡是处于等待输入、待验收或失败的任务都算,因此你在任何界面上都能看出有东西需要看一眼。
它自己的两个控件位于窗口右上角那一簇,就在设置齿轮旁边:一个视图切换,一个任务设置。它们不占额外宽度——整页路由本来就会隐藏终端与辅助面板开关(此刻它们无处作用),这两个按钮正好接管那两个位置。
看板还是列表
看板分为四列:
| 列 | 里面是什么 |
|---|---|
| 待办 | 已写下但尚未开始——以及所有卡在并发上限后面排队的、和定时到点才开始的任务 |
| 进行中 | 正在初始化,或者智能体此刻正在处理它 |
| 等你处理 | 卡在提问上、已完成待验收、正在合并,或者失败了 |
| 已完成 | 已合并,或没有东西可合并而直接完成(以及在你要求显示时的已取消任务) |
每一列都按最近更新在前排序,所以刚刚移动、重试或完成的任务就在列首,而不是被更早的工作压在下面。
列表则把同样这些任务排成一张扁平的表,同样最近在前——状态 · 任务 · 位置 · 变更 · 更新——并带一个说着那四个列名的状态筛选器。列表的每一行会把它所提供的操作全部显示为带说明的图标按钮,而不是把大多数藏进溢出菜单里,因此当任务多到四列装不下时,列表是更快的那一面。你选的视图会被记住。
卡片上先是状态,然后是一行元信息:文件夹 / 分支 · +/− 行数 · 一个相对时间。最后这一项是任务真正抵达过的最近一个节点——已完成或已取消,否则是待验收或失败,否则是开始执行,再否则就是被创建。而在任务处于活动状态时,卡片还会带上智能体最近上报的进展,因此不必打开任何东西,这一列就能告诉你正在发生什么。点击卡片可打开它的详情面板;右侧的圆形按钮是它的操作。
添加一个任务
新建任务会打开编辑器:
- 标题——要做什么?
- 任务描述——完整的 composer,与你在对话中使用的是同一个:
@引用文件,/唤起命令,$唤起 Codex 技能,+ 菜单里还有技能与快捷消息,以及附件。一份 bug 报告可以就是一张截图,别的什么都不写。 - 目标——它运行所在的项目文件夹。这里只会提供项目根目录;任务不能以某个 worktree 为基础,因为它自己会创建一个。已经跑过的任务会被固定在它的文件夹上。
- 智能体与模式——这两项起初处于继承自任务设置,并会一直如此,直到你动它们为止。为本任务覆盖其中一项后,会出现一个恢复继承的控件把它还回去。
而且这不只是新建任务那个框。每一个待办输入框都是完整的 composer——编辑任务、对已验收的任务继续处理、给重试留一段说明——所以无论你在哪里打字,都能引用文件或粘贴一张图。
模板把一整个任务保存为蓝图:把当前内容存为模板会以一个名字存下标题初值和所捕获的 composer 状态,而从列表中选一个则会用它重新填充编辑器。用一个已用过的名字保存会就地更新那个模板,而不是堆出一堆副本。
另外还有两扇门通向这里:
- 来自一条消息。 读回复时发现了一个后续要做的事?任意消息的复制按钮旁边就有由此消息创建任务——它会把那段文本放进一个新任务,并预先填好项目文件夹,然后把你切到待办任务。
- 来自一个自动化,或者智能体自己。 自动化可以不启动会话,而是排入一条任务;而在你允许之后,对话中的智能体也可以自己排一条。→ 自动化
让它跑起来
除非你发话,否则什么都不会自己开始。有三种方式启动一个任务:
- 卡片上的开始。
- 把一条待办拖到进行中那一列——当指针进入时,它会显示松开即开始执行。
- 给它定一个时间——见下文。
无论用哪种方式,并发上限都会生效:超出上限的任务会停在排队中,等有空位时再开始。这个上限按文件夹计算,默认为 2。
排队中就只是这个意思,不多不少——在等一个空位。一旦拿到空位,任务就会转到进行中列里的初始化中,此时正在创建它的 worktree、执行它的初始化命令;一个装了三分钟依赖的任务本来就该待在这儿。整个过程都可以取消,而且取消是真的会中止安装,不会把 pnpm install 丢在后台跑完。
在任务设置中打开自动处理,你就什么都不用按了——待办会在有空位时自行认领,这条队列也就真正变成了一条工作队列。
待办列中的卡片还可以拖动排序,而这个顺序正是自动处理器所遵循的。(排序需要选中单个文件夹——顺序是按文件夹存储的,混合文件夹的一列没有任何可以持久化的东西。)
让它在你指定的时间开始
待办卡片上的定时运行要你选一个日期和一个时间。任务会原地待到那一刻,然后就像你亲手按了「开始」一样启动——文件夹的并发上限依然决定真正能启动多少,所以定时是一次「到点请开始」的请求,而不是插队的承诺。
对话框打开时是空的,这样一个从未安排过的任务就不会看起来像被安排过;日历旁边还有1 小时后、3 小时后和明天 9:00。选好日期后它会替你填一个合适的钟点——当天就填下一个整点,隔天则填 09:00——而不是留给你半个存不下去的值。定好的卡片会显示计划于 …… 开始;清除定时可以把它撤掉。
有三处边界值得知道:
- Codeg 关着的时候错过的时间点,会在下次启动时触发,而不是被悄悄跳过。
- 你亲手按「开始」会接管这个计划。
- 取消任务会一并清除它的定时,因此之后重新排队时,不会被一个你早已忘掉的时间点唤醒。
一次运行究竟做了什么
任务开始的那一刻,在任何智能体介入之前:
- 创建一个 worktree,就在你的项目旁边——目录为
<项目>-task-<id>,分支为task/<id>——并钉在你项目 HEAD 当时所指的那个确切提交上,因此中途切换分支也无法让它漂移。这个 worktree 会在该任务之后的每次运行中被复用。 - 运行初始化命令(如果文件夹设置了的话,比如
pnpm install)。它只在新建的 worktree 中运行,绝不会在复用的 worktree 上重跑;非零退出码会中止本次启动,而不是让智能体在装了一半的环境里开工。出于同样的理由,被中断的安装——你取消了,或者 Codeg 退出了——下次会重新执行。 - 启动智能体,工作目录就是那个 worktree,输入是你的任务描述,外加一条常驻指令:尽管往任务分支上提交,但不要合并进、变基到或推送基线分支——结果由用户在验收之后落地。
从这里开始它就是一个真实的智能体会话,并且会产生一次真实的对话,你可以在侧边栏中该 worktree 文件夹下找到它。
在它工作期间,智能体多出两个只存在于任务运行中的工具:
task_progress——一行进展里程碑("测试通过了,开始清理"),会实时出现在卡片和推进记录上。task_complete——结论,在最后调用一次:success(成功)、needs_review(能用,但这一处请看一下)或 blocked(做不下去,以及为什么)。success 和 needs_review 会把任务送去验收;blocked 则把它标记为失败。
这两个工具与通用设置的开关无关
task_progress 和 task_complete 只会注入到任务运行中,因此它们不依赖委派、实时反馈或设置 → 通用中的任何东西。而且它们只是建议性的:即便智能体从未调用 task_complete,任务仍会在其回合结束时正常落定。
当任务需要你时
任务会因为四种不同的原因落到等你处理,卡片上的状态会告诉你是哪一种:
- 等待输入——智能体卡在一个权限请求、一道选择题,或一次计划批准上。在你回答之前什么都不会推进。
- 待验收——它做完了。见下文。
- 合并中——合并正在进行。这是唯一一个你无法取消的状态。
- 失败——运行出错、被重启打断,或者智能体报告了 blocked。重试会在同一个 worktree 中接着做,并被告知上一次尝试被中断了、请继续;你还可以给这一轮补上一段说明。
查看会话是你解开第一种情况的地方。它会打开该任务智能体会话的只读实时视图——虽然对发送提示词而言是只读的,但它确实会渲染权限对话框和提问卡片,所以你就是在这里作答。对于运行中的任务,这个视图是实时流式的;对于已落定的任务,它显示存下来的记录,并按任务经历过的阶段分段:任务执行、重试执行、继续处理和合并变更。
如果它的 worktree 不见了
把一个任务的检出目录从磁盘上删掉——手工删,或者从分支选择器里删——这个任务以前就无路可走了:合并需要 worktree,而「完成」当时只在没有改动时才提供,并且会因为目录不存在而报错。现在它能自己恢复:
- 每张卡片都会标注,无论处于什么状态,都会显示 Worktree 已删除。
- 待验收的卡片会把「合并」换成「完成」,对话框的文案会说明原因。若工作分支上仍有未落地的提交,该分支会被保留,而不是被删掉。
- 重试或继续处理会重建检出——依据任务记录下来的分支,在它原本的基线上重建——因此已提交的工作会被重新接上,而不是被晾在一棵崭新的空树后面。
验收结果
打开一个待验收的任务,详情面板会把你判断所需的一切摆出来:
- 结果——智能体在调用
task_complete时写下的摘要,按 Markdown 渲染,因此其中的标题、列表和代码都会正常显示。内容较长时会折叠在展开之后。 - 变更文件——相对于任务所记录基线的每一个文件,带
+/−计数。点击其中一个看它的 diff,或用查看全部差异一次看完。 - 推进记录——这个任务的时间线:创建、状态变化、实际生效的启动配置、初始化命令的输出、智能体的里程碑与结论、预检、合并尝试,以及你自己的操作。
- 详情——分支、有了之后的合并提交、变更总量、计划开始时间,以及创建 / 开始 / 完成的时间戳。总 token 用量在标题栏中。
如果文件夹设置了预检命令,它会在任务抵达验收的那一刻在 worktree 中运行——这就是你的验收测试,在卡片上表现为一盏红灯或绿灯。失败时它会把输出的末尾就地保留下来,于是你不必打开终端就能看到是哪里坏了。
出口有四个:
- 合并——通过。见下文。
- 继续处理——再来一轮。见下文。
- 完成——直接标记为完成,完全不做合并。当任务没有改动任何文件时提供——它只是回答了一个问题,或者核实了本来就没问题的工作——因此没有东西需要落地,也不会产生一条空的合并提交。是否保留它的 worktree 仍由你决定。
- 放弃——不合并就丢掉,并可以顺手把原因记到时间线上。任务转为已取消,其 worktree 会被保留,因此之后仍可用重新排队把它捡回来。
说清楚你要的是哪一种「继续」
继续处理会先问你意图、再问你内容,因为同一句话可以是四件完全不同的事:
| 意图 | 它告诉智能体什么 |
|---|---|
| 修改返工 | 把这里改掉。默认项,也是原先「打回」所做的事 |
| 继续推进 | 再做一件事——已经做完的部分原样保留 |
| 提问答疑 | 不要改任何文件,只回答问题 |
| 自查验证 | 在我验收之前,你自己先过一遍 |
这个区分最值钱的地方是提问答疑:一个被告知工作「被打回」的智能体,无论如何都会开始改文件——而当你只是想问某个函数是做什么的时候,这恰恰是最不该发生的事。自查验证则是唯一一个可以留空发送的意图——「你自己看一遍」不需要多解释,而把它变成一次点击,本来就是它大部分的价值所在。
无论选哪一种,工作都会在同一个 worktree 中继续,然后再次回到验收。Codeg 会尽可能恢复原来的那个会话,让智能体保留全部上下文;若该智能体无法恢复会话,则会在同一个 worktree 中新开一个会话接手,并把任务本身和你的反馈一并重放给它,同时在推进记录中留下这次回退。
合并它
合并是由智能体在它自己的会话中完成的——正是这一点让它能够解决冲突,而不是把冲突甩给你。合并任务对话框只问两件事:
- 提交信息——让智能体自动生成提交信息默认勾选,智能体会根据实际改动写出一行 Conventional Commits 风格的信息。取消勾选即可自己写;输入框中已预填任务标题。
- 合并后删除 worktree——初值取自该文件夹的任务设置。
策略不在这里问——它是在合并开始时从该文件夹的任务设置中读取的。合并为一条提交(squash,默认)把整个任务作为一条历史记录落地;保留完整提交历史则保留任务过程中的每一条提交,另加一条合并记录。想用另一种,请在合并之前先去那里改。
接着,智能体会把任务分支上尚未提交的内容提交掉,把基线分支合并进这个 worktree 并在那里解决每一处冲突,然后才把结果落到你项目文件夹的基线分支上。
这里面没有一步是 Codeg 听智能体一面之词的。回合结束时它会核对 git 的事实——基线分支的 HEAD 真的前进了吗?它真的包含这些工作吗?如果不是,任务会退回验收并附上原因,同时把任何做了一半的合并从你的项目文件夹里清理干净。
合并对你的项目文件夹有要求
合并落地在你正在使用的那个文件夹里,所以它会先检查:该文件夹必须位于基线分支上,且暂存区为空。而且每个项目同时只能有一次合并——在第一次结束之前,第二次会被拒绝。任何一条不满足,你都会拿到一句直白的说明,且什么都不会被改动。
让文件夹替你落地
文件夹「流程」设置中的自动合并,做的正是你点合并会做的事——同样由智能体撰写提交信息,同样应用按阶段的提示词,同样沿用删除 worktree 的默认值。打开它的文件夹会自己把验收那一列排空,从最早落定的开始,一次只合并一个。
它刻意不做的,是硬闯过一个问题:
- 预检为红灯或尚未出结果时,会留给你。 只有绿灯才算合格;没有配预检命令时,则根本没有这道关卡。
- 没有任何改动的任务不会被动——那是完成的地盘,由你来判断。
- worktree 已丢失的任务同样不会被动,理由相同。
- 失败会在卡片上留下提示并停下。 它绝不会无人值守地重试——失败过一次的合并只会循环地失败下去,所以这一行会等一个人来处理,而这一轮扫描继续往下走。
任务设置
任务设置对话框(右上角那一簇里的滑块图标)有一个作用域开关:全部文件夹(全局默认),或某一个特定的文件夹。一个文件夹要么使用全局默认——那边一改,这边自动跟着变——要么有自己的单独配置;而切到单独配置时,它会从今天实际生效的那套值开始。
其下分为三个标签页:
| 标签页 | 设置 | 作用 |
|---|---|---|
| 常规 | 默认智能体 | 此文件夹中的任务所使用的智能体,除非某个任务另行覆盖 |
| 自动处理 | 待办自行开始,受并发上限约束 | |
| 最大并发任务数 | 同时运行多少个,按文件夹计。默认 2;0 表示不限制 | |
| 流程 | 默认合并策略 | squash 还是完整历史,以并排的两个选项呈现。在合并开始时读取——合并对话框不会再问 |
| 自动合并 | 不用点击就落地已验收的任务——见上文 | |
| 合并后删除 worktree | 在合并对话框里默认勾选那一项;到时仍可临时改 | |
| Worktree 初始化命令 | 在新建的 worktree 中、智能体开始之前运行 | |
| 预检命令 | 任务抵达验收时在 worktree 中运行——那盏验收灯 | |
| 提示词 | 按阶段追加的说明 | 见下文 |
按阶段追加你自己的说明
每一次启动都已经带着一段内置提示词——任务本身、worktree 规则,合并时还包括具体的 git 步骤。提示词标签页就是你往上添内容的地方:选一个阶段,写下你的项目所需要的东西,你的文字会以补充说明为标题追加在 Codeg 自己那段措辞之后。它是对内置内容的细化,绝不会替换它们,所以其中任何一条你都不必重述。
一共五个阶段,各自带有自己的示例占位文本,已经写了内容的阶段会带一个圆点:
| 阶段 | 何时发送 |
|---|---|
| 全部阶段 | 智能体收到的每一段提示词,包括合并那一轮 |
| 任务执行 | 任务首次执行时 |
| 重试执行 | 重新接手被中断或失败的任务时 |
| 继续处理 | 你对一个待验收的任务继续处理时——返工、追加工作或自查 |
| 合并变更 | 智能体把任务合并到基线分支时 |
这样拆分是有价值的,因为适合放进某一个阶段的内容,和适合放进另一个阶段的完全不是一回事。全部阶段适合放通用规矩——"遵循 AGENTS.md 中的约定;最终总结不超过两句话。" 继续处理才是写 "逐条处理反馈中的每一点;不要顺手重构无关的东西" 的地方。而 "落地提交信息用英文;手工解决过的冲突要说明" 只在合并变更阶段说得通,放在别处都没有意义。
让看板保持整洁
- 用下拉框按文件夹筛选,在列表视图中按状态筛选,用筛选菜单按可见性筛选:显示已取消(默认开启)和显示已归档(默认关闭)。当你偏离了这两个默认值时,筛选按钮会自己带上徽标。
- 归档会在任务走到终点后——已完成、失败或已取消——把它从看板上拿走而不删除它;全部归档会清空已完成列当前显示的一切。已归档的卡片只提供一个操作——取消归档。
- 重新排队把一个已取消的任务放回待办,并复用它的 worktree,同时可以附上一段说明,讲清楚这一次该有什么不同。
- 删除会彻底移除一个任务,并先取消正在进行的运行,同时提供一个可选的复选框来同时删除其 worktree。
- 如果 worktree 无法被移除——有东西打开着它、有锁文件被占用——卡片会显示清理失败或保留 worktree,并提供重试清理。没有任何东西会被悄悄留下。
须知
- 任务以项目为界。 它们从项目根目录运行,绝不从 worktree 运行;一个任务的看板就是该文件夹的看板。
- 每个任务都是一个完整的智能体会话。 有它自己的令牌开销、自己的记录、在你历史中自己的条目。同时跑四个,就是四个会话的花费。→ Token 用量
- 在服务器上同样可用。 任务引擎在桌面应用和
codeg-server中都会运行——每个数据目录只有一个引擎,因此共享同一个数据目录的桌面应用与服务器不会同时驱动看板。 - 重启不会丢工作。 Codeg 退出时正在运行的任务回来后会标记为已中断,而重试会在同一个 worktree 中继续——那里面还留着智能体已经做完的一切。
- 重试是从干净状态开始的。 它不会再带着上一轮运行给自己写下的那份结果。
- 删除 worktree 不会删掉它的对话。 这些对话会被重新挂到项目文件夹下,而且 Codeg 记得它们最初是在哪里运行的,因此它们的历史依然能被解析出来。
- 基线在创建时就钉住了。 任务是相对于其 worktree 分出来的那个提交做 diff 的,而不是相对于你的分支此后漂到的位置——这也正是合并那一步要先把基线合进来的原因。
后续步骤
- Git 与 Worktree——任务所依托的 worktree 机制,以及如何管理它留下的那些 worktree。
- 自动化——按计划触发,并排入一条待办而不是启动一个会话。
- 使用智能体——任务所重放的智能体、模式与选项。
- 多智能体协作——并行推进工作的另一种方式:在一次对话内由一个智能体进行委派。