跳至内容

计划栈:Plan、Goal、Todo、Schedule 与 Workflow

证据范围:本文解释上游 deepseek-ai/deepseek-harness 固定提交 aa6c361a972c8369148dea7380bb5c21c24e07ec0.1.1-rc.2)中计划栈五个包的公开入口。依据是各包 src/index.ts 的源码顶部注释与本仓库逐文件索引的静态读数;本文没有运行真实 DSH,没有验证调度触发时序或 provider 行为。

模型会"边干边改主意":建一份任务清单、切到计划模式、定一个提醒、把一段工作交给循环脚本反复跑。DSH 把这些能力拆成五个包——Todo、Goal、Plan、Schedule、Workflow——它们有一个共同点:状态全部落在 Session 日志里。本课把五件东西放在一起看,回答三个问题:各自的入口在哪、谁写给谁读、和 Turn 的关系是什么。

一张图先记住分工

text
模型侧(Turn 内可调用)            用户侧                    时间侧
├─ todo_write   整表替换快照       ├─ /goal   目标命令        └─ schedule 定时提醒
├─ get/create/update_goal 目标工具  └─ /plan off 退出计划
├─ exit_plan_mode 计划提交审阅
└─ workflow 循环派子代理
        计划态(Plan):激活时向每次请求注入引导段

Todo:整表替换的快照

入口 tool-todo 的模块入口。顶注把它定位为 "Model-facing whole-list replacement":模型每调用一次 todo_write,就往调用方的 Session 追加一份整表快照。重放语义是 last-write-wins——最后一份快照就是当前清单;界面从 Session 事件渲染,不另存副本。非 agent 调用者没有归属清单,会被拒绝。它不是增量增删接口:想改清单,就提交改完后的整表。

Goal:同一份目标域,两个入口

入口 command-goal 的模块入口。顶注把它定位为 "Human-facing /goal command over the persisted same-session goal domain":这是给人用的斜杠命令,解析(parseGoalCommand)后应用到同一会话内已持久化的目标域。packages/goal/ 下其实还有第三个入口——tool-goal 给模型提供 get_goalcreate_goalupdate_goal 三个工具,读写同一个目标域;所以"Todo 是给模型的工具,Goal 是给人的命令"这个说法只对了一半:Goal 的命令入口给人的,模型也有自己的 goal 工具。goal-round-driver 则负责按轮次驱动这个目标域。共同点是全部落在同一份会话数据上。

Plan:协作状态本身就是日志

入口 plan-mode 的模块入口。顶注把它定位为 "Plan mode is logged per-agent collaboration state":计划激活期间,部署方提供的一段引导文本会进入每一次模型请求;模型完成计划后调用 exit_plan_mode 把成品提交给用户审阅;用户用 /plan off 随时退出。注意这里的机制与第 05 课同源——既然是 logged state,恢复会话时计划态也随日志原样回来,不需要额外快照文件。

Schedule:日志上的一次性与固定频率提醒

入口 schedule 的模块入口。顶注把它定位为 "Agent-scoped durable one-shot and fixed-rate reminders over the session event log":提醒按 agent 归属、持久保存,支持一次性与固定频率两种形态,底层同样是会话事件日志。它能做到持久,正是因为复用了第 05 课那套"事件序号即坐标"的重放机制。

Workflow:固定脚本的 foreground 循环

入口 tool-ralph 的模型入口。顶注把它定位为 "Model-facing foreground Ralph loop over the workflow and subagent seams":一个固定脚本每轮启动一个新的结构化输出子代理,只携带两样东西——不可变的目标,以及上一轮有界的交接摘要。它与第 03 课的 subagent 委派共用接缝,但循环次数由脚本而非模型决定。

它们共享的不变量

五个包都遵守第 05/06 课那条仓库级不变式:模型可见 ⟺ 可从日志重建。Todo 快照、计划态、提醒登记都以事件形式入册;都能通过 ctx.effect 注册并在插件卸载时清理;都不引入第二份需要同步的状态存储。区别只在读写角色:Todo/Workflow/tool-goal 是模型写入,/goal 命令是用户写入,Plan 是部署方注入+用户退出,Schedule 双向皆有。

这一层不证明什么

以上全部来自源码顶部注释与静态索引读数。真实的定时触发时序、提醒错过后的补偿策略、Ralph 循环在真实 provider 上的收敛行为、/goal 命令的完整语法表——都需要按研究与 Debug 协作的流程拿到运行证据后再下结论。

相关源码和测试

读完本课,回到从这里开始的推荐表选下一条线;想动手验证其中任何一条,先读学习工作簿再写记录。本课的 Todo、Plan 和 Goal 三层各有一个可交互状态机:计划栈实验逐步推 todo_write 的整表替换校验、plan/mode 的四词迁移和 goal 的 revision 生命周期。Workflow 层的 Host⇄Worker 双向协议(握手、RPC 配对、取消路径)在 Worker 协议实验里有可步进的消息流。