计划栈:Plan、Goal、Todo、Schedule 与 Workflow
证据范围:本文解释上游
deepseek-ai/deepseek-harness固定提交aa6c361a972c8369148dea7380bb5c21c24e07ec(0.1.1-rc.2)中计划栈五个包的公开入口。依据是各包src/index.ts的源码顶部注释与本仓库逐文件索引的静态读数;本文没有运行真实 DSH,没有验证调度触发时序或 provider 行为。
模型会"边干边改主意":建一份任务清单、切到计划模式、定一个提醒、把一段工作交给循环脚本反复跑。DSH 把这些能力拆成五个包——Todo、Goal、Plan、Schedule、Workflow——它们有一个共同点:状态全部落在 Session 日志里。本课把五件东西放在一起看,回答三个问题:各自的入口在哪、谁写给谁读、和 Turn 的关系是什么。
一张图先记住分工
模型侧(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_goal、create_goal、update_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 协作的流程拿到运行证据后再下结论。
相关源码和测试
- 计划态:plan-mode 的模块入口、
invariant.ts - 目标命令:command-goal 的模块入口、测试
command-goal.spec.ts - 目标工具:tool-goal 的模块入口
- 待办工具:tool-todo 的模块入口、invariant.ts
- 定时提醒:schedule 的模块入口、
domain.ts - 工作流循环:tool-ralph 的模型入口、集成测试
integration.spec.ts
读完本课,回到从这里开始的推荐表选下一条线;想动手验证其中任何一条,先读学习工作簿再写记录。本课的 Todo、Plan 和 Goal 三层各有一个可交互状态机:计划栈实验逐步推 todo_write 的整表替换校验、plan/mode 的四词迁移和 goal 的 revision 生命周期。Workflow 层的 Host⇄Worker 双向协议(握手、RPC 配对、取消路径)在 Worker 协议实验里有可步进的消息流。