# Ddev Plan

> 在已有规格或多步骤任务需求、且在动代码之前使用。若上游 ddev-pc-test 已产出测试用例，自动走 TDD 流程：先实现测试 demo 代码（红灯），再实现被测代码（绿灯），测试覆盖不到的部分直接开发。

- Skill: `docevilock/ddev-plan` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add docevilock/ddev-plan`
- Raw SKILL.md: https://api.skillmd.com/api/skills/docevilock/ddev-plan/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: docevilock (https://skillmd.com/u/docevilock)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/docevilock/ddev-plan

---


# 编写计划

## 概述

`ddev-plan` 的职责是把上游已经确认的设计映射成可执行的实施顺序，避免展开成详细代码草稿。计划里要清楚说明：每个任务对应哪些已确认文档、允许改哪些文件、必须遵守哪些约束、完成后用什么证据证明实现结果与文档一致。

计划文档只正向描述本次实现要做什么、分别在哪一步做、做到什么结果。不要专门写“明确不做什么”或“范围外不做什么”的条目。凡是计划里没有列出的任务、步骤、文件改动和验证动作，默认都不属于这次实现范围。

## 只规划执行步骤（硬性约束）

计划里只允许出现**实现、验证、记录**三类执行步骤。

禁止出现：

- 划分阶段或任务后，额外设置“审查阶段”“review 阶段”“验收阶段”“复核阶段”；
- 把派发审查 subagent、执行代码审查、一致性验收、注释审查、清理单独列为任务或步骤；
- 用“审查通过”作为任务完成或进入下一阶段的前置条件。

任务内的验证和自检属于执行动作，可以保留，但不得单独成阶段，也不得写成对全部产出的正式审查。

所有审查统一由 `ddev-gate` 在收口时完成：gate 会同时派发一致性审查和代码评审（编码规范/质量/注释/清理合并为一个）两个独立 subagent。计划不得提前承担、安排或转述这些审查动作。

要假设后续执行者是熟练开发者，但对当前仓库上下文并不熟，所以计划必须告诉他先读哪些 spec / detail / flow / dataflow 文档，以及这些文档在当前任务里分别约束什么。

这个 skill 只消费已经确认过的 spec 文档、结构设计文档和图，不负责重新决定架构，也不负责在计划阶段发明新的数据结构、状态流或接口契约。上游通常先经过 `ddev-spec`，图形细化则交给 `ddev-diagram`，结构和数据流细化则交给 `ddev-detail`。

如果上游已经为嵌入式 C / 纯 C 场景定义了”禁止业务全局变量、限制长链 `if/else`、优先 context/状态机/表驱动”的 spec 约束，这里必须原样传递到执行计划，不能在任务拆解时弱化成泛泛的”优化代码结构”。对于其他语言项目，同样需要原样传递上游定义的模块边界、接口契约和实现约束。

对于 C 项目（`.c` / `.h`），本阶段必须加载 `ddev-c-pro` 和 `ddev-comment-gen` skill，将设计规范、命名规范、Doxygen 注释标准、风格偏好作为实现约束写入计划，确保执行者明确知道编码规范要求。对于其他语言项目，如果有对应的编码规范 skill，也应在本阶段加载并写入计划约束。

**开始时声明：** “我正在使用 ddev-plan skill 来创建实现计划。”

**上下文：** 这个 skill 应该在专门的 worktree 里运行（由上游设计流程创建）。

**计划保存到：** `docs/plans/YY-MM-DD_name/exec_plans/<feature-name>.md`
- （如果用户对计划位置有偏好，以用户偏好为准）

## 范围检查

默认一份确认过的 spec 对应一份执行计划。

只有当 spec 已经拆成多份、且各改动面属于完全不同的子系统时，才为每份 spec 各写一份计划；每份计划独立产出可运行、可测试的软件。若 spec 本身是一份合并文档（同一改动的多个模块、入口或流程），就只写一份计划，不得按模块、文件或技术层自行拆计划。

如果 spec 文档、结构设计文档或流程图还没确认，或者还在反复改，就先回上游把设计定住，不要在 `ddev-plan` 里提前写实现细节。

范围写法也必须保持正向：只列本计划实际覆盖的子系统、文件、任务和验证。没有写进计划的内容，不补充、不顺带、不默认实现。

## TDD 优先策略

如果上游 `ddev-pc-test` 已产出测试用例文档（`detail/tests/`）和测试 demo 代码大纲，计划必须走 TDD 流程。如果不存在测试用例，跳过本节，按常规流程直接规划实现。

### 判断步骤

1. 检查 `docs/plans/YY-MM-DD_<topic>/detail/tests/` 目录是否存在测试用例文档
2. 如果存在，读取测试总览文档，确认覆盖了哪些接口/路径/状态
3. 将测试用例映射到计划任务中：每个测试用例对应一个 TDD 子任务

### TDD 任务编排

TDD 模式下的任务必须按红-绿-重构拆成三个连续子步骤：

- **红灯（Test First）**：先按 `ddev-pc-test` 的测试 demo 大纲，把测试脚本/测试代码写完整、跑通红灯（被测代码未实现，测试必然失败）
- **绿灯（Implement）**：再实现被测代码，跑通绿灯
- **重构（Refactor）**：最后在测试保护下清理代码结构

### 覆盖拆分

计划必须把本次改动拆成两块：

1. **测试覆盖部分（TDD）**：测试用例能覆盖的接口/状态/路径，按 TDD 红-绿-重构顺序编排
2. **测试未覆盖部分（直接开发）**：硬件依赖、中断时序、板级外设等测试无法覆盖的部分，按常规实现 → 验证 → 任务内自检编排

计划文档中必须显式标明每个任务属于哪一块，以及为什么某个部分无法走 TDD。

### TDD 任务引用

TDD 任务在"必读文档"中必须额外引用：
- `docs/plans/.../detail/tests/<name>-overview.md`：可测试性结论与覆盖范围
- `docs/plans/.../detail/tests/<name>-cases.md`：具体测试用例及输入/预期输出
- 对应的测试 demo 代码路径（如 `test/YY-MM-DD-<feature>/`）

## 文档依赖原则

- `ddev-plan` 不定义新的业务状态、接口契约、数据结构语义或流程分支
- 计划中出现的关键设计项，必须能追溯到已确认的 spec / detail / flow / dataflow 文档
- 每个任务都要明确列出执行前必须阅读的文档和章节，避免执行者只看计划不看设计
- 如果某个关键实现约束无法追溯到上游文档，就停止写计划，回到上游补文档，而不是在计划里临时补设计

## 代码现状验证（强制）

在编写计划的任务和文件结构之前，必须验证计划涉及的文件路径和符号是否存在于实际代码中。**计划中的所有文件路径、函数名、结构体名必须能在源码中找到对应，或来自已确认的上游文档。**

### 验证步骤

1. **文件路径验证**：对计划中要新建/修改的每个文件——
   - 若是**修改已有文件**：用 `Glob` 确认文件路径存在
   - 若是**新建文件**：确认其父目录存在，不存在则标注需要在哪个任务中创建
2. **符号验证**：对计划中引用的函数名/结构体名/枚举名——
   - 用 `grep` 确认在源码中的实际签名
   - 如果符号来自上游 ddev-pc-test 的 API 签名清单或 ddev-detail 的代码分析，直接引用，无需重复搜索
3. **目标函数结构确认**：对计划中要修改的每个函数——
   - 用 `Read` 读取目标函数的**完整代码**（不是 grep 片段）
   - 确认完整 if-else 分支结构、已有的错误/异常处理块、return 点
   - 在此结构基础上设计修改插入点
   - 禁止仅凭 grep/explore 的片段信息决定插入位置
4. **TDD 任务 API 验证**：TDD 任务的测试代码引用的 API 签名必须——
   - 来自 ddev-pc-test 产出的 API 签名清单，或
   - 来自 ddev-detail 的代码现状收集结果
   - 禁止在计划中凭空写出测试代码要调用的函数名

### 不通过时的处理

- 如果文件路径不存在且不是新建文件 → 回上游确认 spec/detail 是否覆盖了正确的代码范围
- 如果符号在源码中找不到 → 确认是拼写错误还是上游设计文档遗漏，修正后再继续

## 文件结构

在定义任务之前，先把需要创建或修改哪些文件、每个文件负责什么理清楚，并把它们和对应的上游设计文档绑定起来。这一步会把拆分决策固定下来。

- 设计边界清晰、接口明确的单元。每个文件都应该只有一个明确职责。
- 你最擅长处理能一次放进上下文里的代码，而且文件越聚焦，修改越可靠。优先小而专注的文件，不要用一个大文件做太多事。
- 需要一起变动的文件应该放在一起。按职责拆分，不要按技术层拆分。
- 在已有代码库里，要遵循既有模式。如果代码库本来就有大文件，不要擅自重构；但如果你要改的文件已经臃肿了，在计划里包含拆分是合理的。
- 如果存在 `ddev-pc-test` 产出的测试 demo 代码目录（`test/YY-MM-DD-<feature>/`），必须把测试脚本/测试代码文件列在对应的 TDD 任务里，并标注其为"红灯"阶段产物。

对于嵌入式 C / 纯 C 计划，还要把这些点写进任务拆分：

- 哪个步骤先定义 `context` / session / handle 结构体
- 哪个步骤把状态枚举和错误码落地
- 哪个步骤把长链条件改成 `switch`、状态机或表驱动
- 哪个步骤拆出私有 `static` 辅助函数，避免主函数吞下全部职责
- 哪个步骤验证没有新增业务全局变量和魔法状态值

对于其他语言项目，任务拆分应包含对应的结构约束（如 Rust 的 ownership 边界、Python 的类型注解策略、Go 的 error handling 约定等），由对应语言的编码规范 skill 决定具体约束项。

这个结构会影响任务拆分。每个任务都应该产出自包含、彼此独立、合理的改动，并能明确回答“本任务落实的是哪份设计文档的哪一部分”。

## 小步任务粒度

计划要拆到”可稳定执行、可独立验证、可明确对照设计”的粒度，但不需要把任务机械拆成 2-5 分钟的小动作，也不需要把上游文档已经写清楚的实现细节再重复展开成完整代码。

推荐的任务粒度是：
- 一个任务对应一个明确模块、流程段或一致性交付点
- 一个任务内可以包含”阅读文档 -> 实现 -> 验证 -> 任务内自检”这一组完整动作
- 如果两个步骤引用的设计文档、修改文件范围或验证方式明显不同，就拆成两个任务

## 计划文档头部

**每个计划都必须以这个头部开始：**

```markdown
# [功能名] 实现计划

> **给代理型执行者：** 必需子技能：使用 `ddev-exec` 按任务逐步实现这个计划。步骤使用复选框（`- [ ]`）语法跟踪。

**目标：** [一句话描述这个功能做什么]

**架构：** [2-3 句说明方案，并注明设计以哪些已确认文档为准]

**技术栈：** [关键技术/库]

**设计依据：**
- `docs/plans/.../spec/...`
- `docs/plans/.../detail/...`
- `docs/plans/.../flow/...`
- `docs/plans/.../dataflow/...`（如有）
- `docs/plans/.../detail/tests/...`（如有，`ddev-pc-test` 产出）
- `ddev-c-pro` skill：编码规范、命名规范（C 项目必填，其他语言项目可选——如有对应 skill 则引用）
- `ddev-comment-gen` skill：Doxygen 注释标准（C 项目必填，其他语言项目可选——如有对应 skill 则引用）

**TDD 状态：** [存在测试用例 / 无测试用例]
- 若存在，标注测试覆盖范围：[接口/状态/路径]；未覆盖范围：[硬件依赖/中断时序/...]
- 若不存在，简述原因：[不可 PC 测试 / 未触发 ddev-pc-test / 跳过]

---
```

## 任务结构

````markdown
### 任务 N： [组件名]

**依赖：** [Task X, Task Y / 无]

**目标：**
- [本任务要落地的模块、流程或交付点]

**必读文档：**
- `docs/plans/.../spec/...`：章节 / 图 / 接口定义
- `docs/plans/.../detail/...`：结构体 / 状态 / 错误码 / 数据约束
- `docs/plans/.../flow/...`：流程节点 / 分支 / 状态迁移
- `docs/plans/.../dataflow/...`：数据流约束（如有）

**文件：**
- 新建：`exact/path/to/file.py`
- 修改：`exact/path/to/existing.py:123-145`
- 测试：`tests/exact/path/to/test.py`

**实现约束：**
- 保持 [context / 状态机 / 表驱动 / 接口契约] 方案
- 不得新增 [业务全局变量 / 长链 `if/else` / 范围外接口]
- 实现命名、错误码、状态值必须与引用文档一致
- C 项目须遵守 `ddev-c-pro` skill：`_t` 类型后缀、模块前缀、显式返回码、所有权明确（其他语言项目由对应编码规范 skill 约束）
- C 项目须遵守 `ddev-comment-gen` skill：Doxygen 注释完整性（公开 API/@file/结构体成员）（其他语言项目由对应注释规范 skill 约束）

- [ ] **步骤 1：阅读并核对引用文档**

确认本任务覆盖的输入、输出、状态、接口、流程和边界条件都能在上游文档中找到依据。

- [ ] **步骤 2：按既定设计修改目标文件**

实现时只允许在本任务列出的文件范围内落地设计，不得在计划外扩展新设计。

- [ ] **步骤 3：补齐本任务需要的验证**

运行：`pytest tests/path/test.py::test_name -v`
预期：通过，且结果与引用文档描述一致

- [ ] **步骤 4：完成任务内自检**

对照引用文档做本任务的实现自检：结构、状态迁移、接口语义和流程节点是否一致；若不一致，先修正代码或回上游补文档。这是执行动作的一部分，不是独立审查阶段。

- [ ] **步骤 5：写入实现笔记**

在 `implementation-notes.md` 中追加本任务的推理记录，按 Design Decisions / Deviations / Tradeoffs / Open Questions 四个维度记录。Design Decisions 和 Deviations 为强制维度——必须检查并记入；Tradeoffs 和 Open Questions 有则必写，无则标注"无"。

- [ ] **步骤 6：记录结果与未覆盖风险**

记录本任务已经覆盖的设计点、验证证据，以及仍需后续任务或最终门禁覆盖的风险。

**验证：**
- 运行：`exact verification command`
- 预期：`expected result`
- 人工核对：`与哪份文档的哪几个点保持一致`

**完成标准：**
- 引用文档中的设计点已经落地到代码
- 没有引入文档中不存在的新设计漂移
- 验证通过，且任务内自检完成
````

对于 C 项目，如果任务涉及控制流或状态管理，步骤里不能只写”实现逻辑”，要明确写出：

- 先补或定义状态枚举 / 上下文结构体
- 再根据已确认文档落地状态迁移和错误路径验证
- 再落地分发方式，不允许默认写成长链 `if/else`
- 按 `ddev-c-pro` skill 要求遵循命名规范和风格偏好
- 按 `ddev-comment-gen` skill 要求补 Doxygen 注释
- 最后检查是否出现共享可变全局状态、参数过多未封装、注释缺失等违规

对于其他语言项目，同样需要将对应语言的实现约束明确写在步骤中，不允许含糊的”实现逻辑”占位。

## TDD 任务结构

当上游 `ddev-pc-test` 已产出测试用例时，对应任务改用以下 TDD 模板。一个 TDD 任务对应一个或一组紧密相关的测试用例。

````markdown
### 任务 N： [组件名]（TDD）

**类型：** TDD（测试覆盖）

**对应测试用例：** TC-01, TC-02（来自 `detail/tests/<name>-cases.md`）

**目标：**
- [本任务要落地的模块、流程或交付点]

**必读文档：**
- `docs/plans/.../spec/...`：章节 / 图 / 接口定义
- `docs/plans/.../detail/...`：结构体 / 状态 / 错误码 / 数据约束
- `docs/plans/.../detail/tests/<name>-overview.md`：可测试性结论与覆盖范围
- `docs/plans/.../detail/tests/<name>-cases.md`：测试用例 TC-0x 的输入/预期输出

**文件：**
- 测试代码：`test/YY-MM-DD-<feature>/host_sim/test_xxx.py`（红灯阶段产物）
- 被测代码：`src/path/to/module.c`（绿灯阶段产物）

**实现约束：**
- 保持 [context / 状态机 / 表驱动 / 接口契约] 方案
- 不得新增 [业务全局变量 / 长链 `if/else` / 范围外接口]
- 测试脚本的输入/预期输出来自 cases 文档，不得自行发明
- C 项目须遵守 `ddev-c-pro` skill（其他语言项目由对应编码规范 skill 约束）

- [ ] **步骤 1：阅读测试用例文档**

确认本任务覆盖的测试用例编号、输入数据、预期输出、前置条件都能在 cases 文档中找到。

- [ ] **步骤 2：红灯 — 先写测试代码**

按 cases 文档中的输入/预期输出，把测试脚本/测试 demo 代码写完整。**写入前必须先读取被测模块的头文件**，确认测试代码中调用的函数签名、结构体、枚举值与源码一致。运行测试，确认红灯（被测代码未实现，测试必然失败）。记录红灯输出。

- [ ] **步骤 3：绿灯 — 实现被测代码**

按 spec/detail 设计文档实现被测代码，用最小代码量让测试通过。运行测试，确认绿灯。

- [ ] **步骤 4：重构 — 测试保护下清理**

在绿灯保护下，清理重复代码、改善命名、拆分过长函数。每改一处就跑一次测试，保持绿灯。

- [ ] **步骤 5：完成任务内自检**

对照引用文档做本任务的实现自检：结构、状态迁移、接口语义和流程节点是否一致；若不一致，先修正代码或回上游补文档。这是执行动作的一部分，不是独立审查阶段。

- [ ] **步骤 6：写入实现笔记**

在 `implementation-notes.md` 中追加本任务的推理记录，按 Design Decisions / Deviations / Tradeoffs / Open Questions 四个维度记录。Design Decisions 和 Deviations 为强制维度——必须检查并记入；Tradeoffs 和 Open Questions 有则必写，无则标注"无"。

- [ ] **步骤 7：记录结果与未覆盖风险**

记录本任务覆盖的测试用例、红灯/绿灯输出摘要，以及本 TDD 任务无法覆盖的边界条件。

**验证：**
- 红灯验证：运行：`python test/.../test_xxx.py`，预期：FAIL（被测代码未实现）
- 绿灯验证：运行：`python test/.../test_xxx.py`，预期：PASS
- 人工核对：`与 cases 文档 TC-0x 的预期输出逐字段比对`

**完成标准：**
- 测试用例全部绿灯通过
- 被测代码实现与引用文档一致
- 没有引入文档中不存在的新设计漂移
- 测试输出可自动比对，无需人眼判断
````

## 不要留占位符

每一步都必须包含工程师真正需要的内容。以下都属于**计划失败**，绝对不要写：
- “TBD”“TODO”“后面再实现”“补充细节”
- “添加适当的错误处理” / “添加校验” / “处理边界情况”
- “参考前面的文档自行实现”（但没有写明具体文档和章节）
- “和任务 N 类似”（工程师可能不是按顺序读任务）
- 只说做什么、不说明要读哪些文档、改哪些文件、怎么验证一致性
- 引用了某个类型、状态、函数或方法，但这些东西无法追溯到已确认设计文档

## 记住

- 始终写清楚准确的文件路径
- 始终写清楚本任务依赖的文档路径、章节或图
- 命令要精确，预期输出也要精确
- 一致性校对点要精确，不能只写“和设计一致”这种空话
- DRY、YAGNI、频繁提交

## 自检

把完整计划写完后，要换个角度重新看一遍，对照规格和上游文档检查计划。这是你自己运行的清单，不是派发给子代理的任务。

**1. 规格覆盖：** 快速浏览规格的每个章节/要求。能不能指出一个对应的任务？把缺口列出来。

**2. 文档映射：** spec / detail / flow / dataflow 文档里的关键交付项、结构、状态和流程节点，能不能在计划里找到对应任务和验证动作？缺口列出来。

**3. 占位符扫描：** 在计划里找红旗 - 是否有上面“不要留占位符”里列出的模式？有就修掉。

**4. 类型与约束一致性：** 后续任务里使用的类型、方法签名、属性名、状态名、错误码，是否和上游文档里的命名一致？比如 detail 文档里叫 `clearLayers()`，计划里又变成 `clearFullLayers()`，这就是 bug。**同时检查这些名称是否能在实际源码中找到对应的声明或定义。**

**5. 设计漂移检查：** 计划里是否引入了上游文档没定义的新结构、新接口、新流程分支或范围外文件改动？如果有，删掉或回上游补设计，不要在计划里偷改架构。

**6. 联动覆盖检查：** 如果上游 spec/detail 文档中包含联动修改清单，计划是否已为每个联动点分配任务或明确说明为何不需要改？如果上游文档中没有联动修改清单，停止编写计划，回到 ddev-spec 阶段补充后再继续。计划中的任务是否覆盖了联动修改清单中的所有项目？

**7. 代码路径存在性：** 计划中列出的所有文件路径（新建/修改）是否真实存在于仓库中？新建文件的父目录是否存在？

**8. 实现笔记步骤：** 计划中每个任务是否都包含了"写入实现笔记"步骤？步骤描述是否指明了按 Design Decisions / Deviations / Tradeoffs / Open Questions 四个维度记录？

**9. 语言结构纪律：** 如果是 C 项目，计划里是否已经明确安排：
- 业务状态收敛到上下文结构体
- 状态值枚举化
- 长链 `if/else` 的替代方案
- 函数按职责拆分
- 对”未新增业务全局变量”的验证
- 对”实现是否仍与上游控制流文档一致”的核对
- 按 `ddev-c-pro` skill 要求遵循命名规范和风格偏好
- 按 `ddev-comment-gen` skill 要求补 Doxygen 注释

如果是其他语言项目，计划里是否已经明确安排该语言对应的结构约束（由对应编码规范 skill 决定）？

**10. TDD 覆盖核对：** 如果存在 `ddev-pc-test` 产出的测试用例：
- 每个测试用例是否都有对应的 TDD 任务？
- TDD 任务是否按红-绿-重构三步骤编排？
- 测试未覆盖的部分是否已显式标注为”直接开发”，并说明了不可测试的原因？
- TDD 任务的”必读文档”是否引用了 cases 文档和 overview 文档？
- 测试脚本的输入/预期输出是否来自 cases 文档，而非自行发明？
- 测试代码中调用的 API 签名是否能追溯到 ddev-pc-test 的签名清单或 ddev-detail 的代码分析？

**11. 执行步骤纯净化：** 计划里是否只有实现、验证、记录三类执行步骤？是否出现了独立审查阶段、审查任务、派发审查 subagent 的安排，或把"审查通过"写成任务完成条件？有就删掉，审查统一交给 `ddev-gate`。

如果发现问题，直接在原地修掉，不用重新审一遍，改完就继续。若发现某个规格要求没有对应任务，就补上任务。

## 执行交接

保存计划后，向用户报告计划文档路径、任务数量和关键里程碑。

**禁止 agent 自动进入 ddev-exec。** 必须等待用户明确确认后再加载 `ddev-exec` 开始执行。

**提示模板：**
- 告知计划已保存及路径
- 列出任务概览（任务数、关键里程碑）
- 询问："是否开始执行？"或"是否进入 ddev-exec？"
- 在用户明确回复"执行""开始""继续""进入 exec"等确认指令前，不自行推进

**执行要求（用户确认后）：**
- 使用 `ddev-exec`
- 按计划顺序逐步执行
- 执行阶段不安排中途审查；所有审查统一由 `ddev-gate` 收口

## 默认收尾

当计划对应的实现完成后，不要只停在“代码写完”或“测试跑过”。

默认收尾顺序是：

1. 用 `verification-before-completion` 补齐本轮结论所需的验证证据。
2. 进入 `ddev-gate`：gate 会同时派发两个独立 subagent——一致性审查 + 代码评审（编码规范/质量/注释/清理合并为一个）。
3. 如果 gate 返回 `blocked` / `need-info`，先修复或补齐缺失输入，再重新进入 `ddev-gate`，直到两个审查在同一份最终代码上都 `pass`。
4. 代码偏离文档规划的架构时，修正到一致；无法修正或决定不修正的偏离，写入 `implementation-notes.md` 的 Deviations（偏离点、理由、影响范围）。
5. 只有 `ddev-gate` 通过后，才能宣称“实现已经按设计完成”。

如果没有经过 `ddev-gate`，默认不应宣称“实现已经按设计完成”。

