Plan state
版本 5.0.0。状态:稳定。 本文档规定了 Deep Work Plan 方法论的机器可读计划状态层,现已与 DWP 标准自身的版本号对齐——此次重新编号不削弱任何既有要求。本次修订还记录了受保护的状态更新器、经验证的计划发布,以及一份已完成计划必须满足的证据真实性规则(见下文)。关键词 MUST、MUST NOT、SHOULD、SHOULD NOT 与 MAY 应按 RFC 2119 中所述加以解释。
两个 JSON 产物——manifest.json(计划的静态标识)与 state.json(包含验证关卡结果的实时逐任务执行状态)——每份计划 MAY 将其与 Markdown 文件一并携带,而无人值守执行(参见 代理协议)与无 git 的工作区(参见 原型 §3)MUST 携带。
Markdown 计划仍是人类可读的事实来源。JSON 层是一份派生投影:由代理在既定的协议节点处重新生成,从不手动编辑,也绝不允许与 Markdown 静默地产生分歧。其目的是实现互操作性——代码检查、符合性核验、差异对比、仪表板、注册表发现,以及与外部会话基础设施的同步——而这些都无法可靠地建立在散文之上。
为何需要它
在 v1.1 之前,计划仅为散文 Markdown。这保持了其可审计性与代理无关性,但没有留下任何工具可以验证、差异对比或消费的内容:没有符合性关卡,没有 README.md 与 PROGRESS.md 之间的去同步检测,守护进程或云端会话也无法在不解析散文的情况下知晓计划的状态。v1.2 在不降低 Markdown 地位的情况下添加了 JSON 投影——该投影从 Markdown 派生,就如同锁文件从清单派生一样。
存放位置
使用状态层的计划具有以下布局:
.dwp/plans/PLAN_{name}/
├── README.md ← 人类事实来源(不变)
├── PROGRESS.md ← 叙事日志(不变)
├── PROMPTS.md ← 不变
├── manifest.json ← 静态标识(在物化时写入)
├── state.json ← 实时状态(在协议节点处重写)
├── analysis_results/
└── {N}.task_{...}.md
manifest.json MUST 在 create 流程物化计划时恰好写入一次,此后 MUST NOT 更改,除非在 PROGRESS.md 中记录了规范版本迁移。
state.json MUST 由代理在以下每个协议节点处重写:计划物化(所有任务 pending)、任务开始(in_progress)、每次验证关卡运行(关卡记录追加或更新)、任务完成(completed,作为 DWP 规范 中任务完成协议的一部分)、任何计划内中断之前的一个检查点,以及一次 blocked 停止。
两个文件均 MUST 原子性写入:先向同目录下的临时文件写入,再重命名覆盖目标文件。崩溃写入 MUST NOT 在原位留下被截断的 JSON 文件。
何时需要该层
- 对于在 git 代码仓库中进行的交互式执行,状态层对新计划 RECOMMENDED,对 v1.2 之前的计划 OPTIONAL。没有它的计划仍然符合规范。
- 对于无人值守执行,状态层 REQUIRED。
- 在没有 git 的代理工作区中,状态层 REQUIRED:
state.json携带了 git 日志在代码仓库中所携带的恢复信息。
manifest.json —— 计划标识
{
"schema": "https://deepworkplan.com/schema/plan-manifest/v2.json",
"spec_version": "2.4.0",
"name": "PLAN_payment_webhooks",
"title": "Add payment webhook handling",
"archetype": "individual",
"rigor": "standard",
"plan_format": "full",
"created_at": "2026-06-09T14:00:00Z",
"created_by": { "agent": "claude-code", "model": "claude-fable-5" },
"tags": ["backend", "payments"],
"task_count": 7,
"parent_plan": null
}
schema、spec_version、name、archetype、rigor、created_at、task_count 与 plan_format 为 REQUIRED。
archetype MUST 为 individual、orchestrator-hub、agent-workspace 之一。
rigor MUST 为 micro、standard、deep 之一(参见 比例严格度)。
plan_format MUST 为 lite、full 之一——即创建时所选择的形态(参见 Lite 计划)。它在清单层面是不可变的:后续从 Lite 到 Full 的晋升记录在 state.json 中,绝不通过重写清单来完成。
parent_plan 将子计划链接至其编排者计划({repo}:{plan_name},或 null)。
created_by SHOULD 标识创建代理与模型。它 MUST NOT 包含机密信息、令牌或显示名称以外的用户标识符。
state.json —— 实时执行状态
{
"schema": "https://deepworkplan.com/schema/plan-state/v2.json",
"plan": "PLAN_payment_webhooks",
"updated_at": "2026-06-09T16:42:10Z",
"updated_by": { "agent": "claude-code", "model": "claude-fable-5" },
"status": "in_progress",
"completed_count": 2,
"task_count": 7,
"format": "full",
"materialization": "ready",
"approval": "approved",
"promotion": null,
"tasks": [
{
"id": 1,
"locator": { "kind": "file", "value": "1.task_webhook_endpoint.md" },
"title": "Create webhook endpoint",
"status": "completed",
"started_at": "2026-06-09T14:10:00Z",
"completed_at": "2026-06-09T15:02:33Z",
"commit": "a1b2c3d",
"gates": [
{
"command": "pnpm run test",
"passes": true,
"exit_code": 0,
"last_run": "2026-06-09T15:01:50Z",
"evidence": "42 passed, 0 failed"
}
],
"outcome": {
"tried": ["raw body parsing via middleware"],
"failed": ["initial signature check used wrong header"],
"worked": "verify signature against X-Sig header before JSON parse",
"notes": "stripe-style HMAC; see analysis_results/webhook_notes.md"
}
},
{
"id": 3,
"locator": { "kind": "file", "value": "3.task_retry_queue.md" },
"title": "Add retry queue",
"status": "in_progress",
"started_at": "2026-06-09T16:30:00Z",
"gates": []
}
],
"checkpoint": {
"task": 3,
"step": "instructions:4",
"at": "2026-06-09T16:42:10Z",
"note": "queue table migrated; worker loop not yet wired"
},
"blocked": null
}
一份 Lite 计划的任务条目使用 inline 定位符,指向该任务在 README.md 中的锚点,而非单独的文件——条目的其余部分(关卡、outcome、状态)工作方式完全相同:
{
"format": "lite",
"materialization": "ready",
"approval": "pre_approved",
"promotion": null,
"tasks": [
{
"id": 2,
"locator": { "kind": "inline", "value": "#task-2" },
"title": "Add retry queue",
"status": "pending",
"gates": []
}
]
}
格式、物化、批准与晋升
format MUST 为 lite、full 之一,并与清单的 plan_format 保持一致——但此处可变,与清单不同,因为一份 Lite 计划 MAY 之后晋升为 Full。materialization MUST 为 materializing(计划文件夹正在写入)、ready(物化已完成)或 promoting(一次 Lite 到 Full 的晋升正在进行)之一。approval MUST 为 pending、approved、pre_approved 之一;它在本模式中是 OPTIONAL 的,使得在其被记录之前写入的计划仍然符合规范——当它缺失时,将 README 的 Approval 行视为其值,若两者皆无则视为 pending。promotion 在晋升之外为 null,或者在 materialization 为 promoting 期间,是一个记录晋升意图与目标任务的对象。这些字段所编码的完整生命周期参见 Lite 计划。
任务条目
每项任务——在 Full 计划中是单独的文件,在 Lite 计划中是内联的 {#task-N} 记录——MUST 在 tasks 中恰好有一条记录,以其编号(id)与其 locator 为键。locator.kind MUST 为 file(Full——value 是任务的文件名)或 inline(Lite——value 是任务的锚点,#task-N)。
status MUST 为 pending、in_progress、completed、blocked、skipped 之一。skipped 仅在用户通过 refine 明确将任务从范围中移除时有效;state.json MUST NOT 被用于静默跳过工作。
completed 条目 MUST 携带 completed_at,以及在计划提交的情况下,携带短 commit 哈希——这是计划到代码的可追溯性链接。
关卡记录
验证命令的每次运行都 SHOULD 被记录为一条关卡记录:command、passes(布尔值)、exit_code、last_run,以及一段简短的人类可读 evidence 字符串(摘要行或 计划自身 analysis_results/(位于计划自身的文件夹内,绝不在仓库根目录)下的路径,绝非完整的命令输出)。
任务 MUST NOT 在 state.json 中被标记为 completed,如果其任何关卡记录的 passes: false 且没有后续通过的运行。关卡记录是“在没有证据的情况下绝不标记完成”这一模式的机器等价物——每条记录中 passes 标志防止过早完成的模式。
作为情节记忆的 outcome 记录
已 completed 的任务 SHOULD 携带一条 outcome 记录:尝试了什么(tried)、失败了什么(failed)、有效的是什么(worked),以及自由格式的 notes。每条记录保持一行。
outcome 记录使已完成的计划成为可检索的情节记忆:代理(或记忆索引平台)日后可以回想起某个问题是如何解决的,而不仅仅是知道它被解决了。它们馈送给任务内的技能处置与 Final Review 的技能决策核对,后者在挖掘模式时读取它们。在 Hermes 等对代理记忆建立索引的平台上,state.json 中的 outcome 记录使已完成的计划可在未来的会话中直接检索。
检查点与阻塞状态
checkpoint 记录当前任务内最细粒度的续行点:任务 id、自由格式的 step 定位符、时间戳,以及一行备注。代理 SHOULD 在任何时候暂停任务内部时更新它;在无人值守模式下的任何计划中断前 MUST 更新它。
blocked 为 null 或 { "task": N, "reason": "...", "since": "...", "needs": "..." }。遇到停止条件的无人值守代理 MUST 在停止前填充 blocked——这是守护进程的下一次心跳或人类了解计划为何停止的方式。
投影与协调
Markdown MUST 在每次分歧中获胜。若 state.json 显示任务 4 已 completed,但计划 README 显示未勾选的复选框,则状态文件已过时。
续行代理 MUST 在继续之前将 README 复选框列表与 state.json 进行比较。若出现去同步,它 MUST 从 Markdown(以及在有 git 的情况下从 git 日志)重新生成 state.json,在 PROGRESS.md 中记录此次协调,然后才能继续。
verify 子技能 MUST 将去同步视为符合性发现:报告哪些任务产生分歧以及分歧方向。
执行代理以外的工具 MUST 将两个 JSON 文件视为只读。
受保护的状态更新
日常进度写入通过一个随技能一同分发的定向更新器完成,而非整份文件重写。它会直接拒绝格式错误的状态,并且拒绝在没有附带非空关卡证据的情况下将任务标记为 completed——对于自身输出包含竖线字符的命令,提供了 --gate-json 形式,更新器接受上文所述的同一个封闭关卡对象。重试仅替代其自身命令;不同的命令各自保留独立的记录。--block-reason 记录一个阻塞;--resolve-blocker 仅解除当前任务的阻塞,绝不涉及其他任务。被跳过的工作永远不能使一份计划变为 completed。--reopen-reason 记录调用者通过 refine 修订计划的意图——该修订及其使之失效的任何证据 MUST 首先记录在任务日志中。--expected-sha256 会拒绝针对已经发生变化的状态快照的写入。一个协作式的 .lock 目录对并发写入者进行序列化;在移除之前,MUST 先检查已崩溃写入者的锁,且不对绕过该锁的编辑器提供任何保护。这些记录只是断言结果——它们本身并不能证明某条命令确实执行过,或其输出在语义上被接受。
经验证的计划发布
在宣布完成之前,已完成的任务日志(每条都携带其技能处置,以及在 Final Review 中的文档决定)、README 索引与 PROGRESS.md MUST 基于已获得的来源与验收结果撰写。计划的最终任务随后通过随技能分发的终结器关闭:其终结转换会在写入状态之前,对照计划的每一项产物验证已完成的候选,之后再核验文件,并记录一份 analysis_results/FINALIZATION.json 收据。绝不能用一个凭空捏造的通过关卡来支撑此次转换——该收据是对实际检查内容的外部证据,绝非自身的前提条件。随后针对磁盘上的真实产物运行 bash ../verify/conformance.sh --plan PLAN_name。
一次被中断的发布会留下一个 .finalizing.json 标记;在检视证据、且恢复辅助工具针对同一候选成功运行之前,常规验证会失败——不会凭假设恢复任何发布。一个过期的协作锁在移除之前,需要确认没有写入者仍处于活动状态。此层中的任何内容都不会提交、推送、执行已存储的关卡命令,也不会静默修复计划的 Markdown。缺少 Python 解释器会产生 UNVERIFIED,绝不会产生 completed。
证据真实性与修订
对任务范围、验收标准或延期的每一次变更,都携带一条持久的修订记录:原始标准的原文、观察到的内容、处置方式、理由、其背后的权威来源(用户、开发者或证据)、受影响的任务,以及哪些证据被使无效或被保留。修订被追加,绝不倒填日期;manifest.json 保留其创建时的出处,绝不会为匹配已变更的实时范围而被重写。
五种证据状态描述了一条任务记录可以据以关闭的依据:
- 已完成的调查 —— 真实记录的工作;它仅能针对一条点名它的修订标准关闭任务,绝不能针对原始标准本身关闭。
- 未执行的场景 —— 记录为未执行;它在任何时代都不构成通过证据。
- 延期的要求 —— 该标准移至一个具名的目标任务,并附带已记录的权威来源;只有该修订才能关闭源任务。
- 失败的关卡 —— 在同一验收意图被重新运行并通过之前,始终保持失败状态;一次重试仅替代其自身命令。
- 达成的产品成果 —— 按原文所写的标准,由其自身关卡验证;这是唯一能够使任务在不作改动的情况下完成的状态。
只要记录允许,强制执行就是机械化的。标记为「因 refine 而失效」的关卡证据是被保留的历史记录,绝非通过证据,一项仍依赖它的已完成任务会被检查器报告。一条通过记录,若其自身文本承认该检查从未真正运行过(例如「从未进入」「未运行」或「无法测量」),即构成矛盾,会以同样方式被报告——一项完成状态的任务,若其自身日志仍写着 Status: pending,同样如此。超出这些范围的叙事性矛盾——例如一份报告的结论与其自身检查清单相悖——需要人工审阅;检查器只报告记录所言,而非散文所暗示的含义。用户 MAY 明确接受一项附带已记录权威来源的有限例外;无人值守的预先批准绝不等同于放弃核心目标的全面许可,一项无法满足的强制性标准是一个阻塞,绝非已完成的工作。
模式版本控制
两个模式均通过 URL 进行版本控制。版本内允许添加字段;重命名或重新定义字段类型需要新的模式版本以及规范变更日志中的迁移说明。本次修订为两个模式引入了 /v2.json:任务条目的 file 字段变为一个带类型的 locator({"kind": "file" | "inline", "value": ...}),清单新增 plan_format,状态文件新增 format、materialization、approval 与 promotion——这些字段共同满足了 Lite 计划的需要(参见 Lite 计划)。/v1.json 的清单与状态文件仍然有效,绝不会被静默重写为 v2;一次 refine 会话 MAY 有意迁移它。清单中的 spec_version 字段固定了计划创建时所依据的 DWP 规范版本;遇到比其已安装规范更新的计划时,代理 SHOULD 明确说明,而非猜测。