# Ddev Detail

> 代码修改场景下，spec 文档确认后，需要继续以图优先方式梳理结构体定义、数据流和流程时使用

- Skill: `docevilock/ddev-detail` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add docevilock/ddev-detail`
- Raw SKILL.md: https://api.skillmd.com/api/skills/docevilock/ddev-detail/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-detail

---


# 实现结构体与数据流工作流

## 作用

当 spec 文档已被确认，需要在编码前继续细化结构体、数据流、流程图等实现细节时使用。默认先出图，再补极少文字。本 skill 仅用于**代码改动场景**。

## 文档表达原则

detail 文档默认采用“图优先，文辅佐”表达，只写本次改动需要落地的结构体、数据流、流程和约束：

- 图: 新增或修改哪些结构
- 图: 关键数据怎么流动
- 图: 关键流程怎么分发和收敛
- 文: 补少量实现约束

不要把本可画清的关系翻写成长段说明。文字只补限制、例外和阅读提示。

不要写“明确不做什么”“这部分不负责什么”的清单。凡是 detail 文档没有写到的结构、数据流、流程和约束，默认都不属于这次改动范围。

它负责把 spec 文档进一步拆成三类图文产物：

- 结构关系图和结构定义文档
- 数据流图文档
- 关键流程图文档

### ⚠️ 硬门禁：画图前必须先加载 ddev-diagram

**在任何 ASCII 图动笔之前，必须执行 `Skill("ddev-diagram")` 加载绘制规范。加载完成前禁止写任何 ASCII 图。**

详细拆解文档默认落到 `docs/plans/YY-MM-DD_<topic>/detail/`，按职责拆成：

- `<name>-overview.md`
- `structures/<name>.md`
- `dataflow/<name>.md`
- `flows/<name>.md`
- `tests/<name>.md`（可选，由 `ddev-pc-test` skill 产出）

`overview` / `index` 类总览文档必须放在 `detail/` 根目录，不要放进 `structures/`、`dataflow/`、`flows/` 或 `tests/`。子目录只放对应职责的详述文档和图源。

根目录 overview 必须包含一张"文档分布与说明"文本图，把本次 detail 下生成的所有文档、目录层级、阅读顺序和文档用途可视化出来。

如果某一类文档过长，不要继续往单文件里堆，先在 `detail/` 根目录保留短总览，再把详述、错误路径、状态迁移、图文说明拆到对应子目录。

默认处理结构体、缓冲区、协议帧、配置和数据流等实现细节。支持 C / Rust / C++ / Python / TS 等多种语言，输出重点是”状态归属、数据边界、流程分发”。

对于 C 项目（`.c` / `.h`），本阶段必须加载 `ddev-c-pro` 和 `ddev-comment-gen` skill，将设计规范、命名规范、Doxygen 注释标准落实到结构体定义、API 签名和文档约束中。对于其他语言项目，如果有对应的编码规范 skill，也应在此阶段加载并落实。

## 何时进入这一步

只有在下面条件基本成立时才进入：

- 已能唯一定位本次改动对应的 spec 文档
- spec 文档中的模块边界、接入点、主流程已经基本确认
- 接下来准备进入实现计划或编码，需要把状态、结构体和流程进一步讲透

如果还在反复改模块边界、职责切分或接入方式，先回到 `ddev-spec`，不要在这里提前堆细节。

## 细化范围

这个 skill 只细化**本次改动真正相关**的结构体、数据流和关键流程。

这里写出来的内容，应当能直接支撑下游实现计划和最终验收；没有写进 detail 文档的部分，默认不进入这次实现拆解。

## 开始前先收集

开始前至少定位这些输入：

- 已确认的 spec 文档路径
- 本次改动涉及的功能主题或模块名
- 已知会受影响的代码范围或目录

**以下为强制步骤，不可跳过：**

- **现有结构体定义、状态枚举、协议帧定义**：必须从实际源码（头文件 `.h`）中搜索并读取
- **结构体复用检查**：在定义任何新增结构体之前，必须搜索已有结构体中是否存在可管理同类状态的候选——
  - 搜索包含同名/近名字段的已有结构体（grep 字段名）
  - 搜索已有 context/handle 结构体，判断新增状态是否可直接作为其成员
  - 搜索同模块已有的 `_t` 类型定义，避免创建功能重叠的新类型
  结果写入 detail 文档的结构体来源标注中：每个"新增"结构体必须附带"复用/扩展已有不可行的理由"（一句话即可，如"生命周期不同""所属模块不同"）。
- 相关时序图、流程图、接口文档（如有）
- 用户明确点名的约束，如”不能新增全局变量””必须兼容现有协议”

### 代码现状收集方法（优先级递减）

1. 从 spec 文档提取涉及的模块名
2. code-review-graph（`mcp__crg__query_graph_tool` 搜 `callers_of`/`callees_of`/`references_to`，`mcp__crg__get_review_context_tool` 拿定义 + 引用片段）定位结构体名/枚举名/typedef 名及其调用关系；无图先 `code-review-graph build`
3. `grep` 兜底：在头文件（`*.h`）中搜索 `typedef struct` / `enum` / `typedef` 声明，按结构体名/枚举名/typedef 名定位
4. `Read` 打开搜索到的头文件，确认精确定义（含字段类型、注释）
5. `grep` 搜索引用点，`Read` 批量查看相关符号源码

### 收集产物

收集结果必须体现在 detail 文档中：
- 每个结构体/枚举必须标注来源：源码路径和行号（若来自已有代码），或”新增”（若为本次新设计）
- 不得凭空定义与源码中已有定义冲突的结构体或枚举

## 基本流程

1. 读取已确认的 spec 文档，先提取模块边界、主流程、关键状态和接入点。
2. 只提取本次改动涉及的结构体、状态枚举、缓冲区和协议载荷。
3. 区分新增、修改、复用、废弃候选。每个结构体/枚举必须标注来源：
   - 复用/修改：标注源码路径和行号（如 `src/module/xxx.h:42`）
   - 新增：标注为"新增"，并确认不与源码中已有名称冲突
   不要在这一步直接删历史设计。
4. 先画结构关系图，再用极少文字标注职责、生命周期、所有权、读写方和状态归属。
5. 再画数据流图，串清入口、转换点、状态迁移、错误出口和输出。
6. 最后只为关键链路出流程图；能靠图说明的内容，不再重复写成长文。
7. 如果单份文档过长或混了多个职责，就按模块或子流程继续拆分，不要硬塞。

## 推荐产物顺序

建议按下面顺序落盘，避免前后反复打架：

1. `detail/<name>-overview.md`
2. `detail/structures/*.md`
3. `detail/dataflow/*.md`
4. `detail/flows/*.md`

`detail/<name>-overview.md` 必须索引所有子文档。`dataflow` 和 `flows` 文档必须引用对应结构体文档名，保证后续 `ddev-gate` 能做一一映射。总览先给图，再给一句话导航。

## 长文档拆分策略

拆分目标是避免单份 detail 文档过长，确保 AI 和后续实现者都能快速定位，优先按图的职责拆。

### 什么时候必须拆

出现下面任一情况，就不要继续维持单文件：

- 一个文档同时覆盖多个彼此相对独立的子模块或子流程
- 一份数据流文档里同时塞了总览、每步细节、错误路径、状态迁移和大段图说明
- 流程图文档已经需要同时解释多条主链路，读者必须频繁上下跳转
- 同一文件里已经出现“总览”和“大段逐步骤说明”互相打架
- 预期编码时不可能每次都把这份文档完整放进上下文

### 拆分原则

- 先在 `detail/` 根目录保留一个短总览文件，负责入口、边界、索引和导航
- 再把高细节内容拆到子文档，不要把细节继续塞回总览
- 图和长说明可以分离；图文强绑定时，保留一个简版图文文件，再把长说明拆出去
- 拆分后文件名必须让人一眼看懂层级，不要出现 `final-v2`、`misc` 这类无语义命名
- 总览文件必须反向列出所有子文档，否则拆完只会更难找
- 不要在 `dataflow/`、`flows/` 或 `structures/` 目录里创建 `*-overview.md`；这些目录里的文档应当是具体详述、错误路径、状态迁移、主流程图或结构体说明

### 推荐拆法

#### detail 根目录

如果主题较复杂，先建立总览入口：

- `<name>-overview.md`

其中 `overview` 只放范围、主链路、边界、引用关系、文档分布图、简图、子文档列表和阅读顺序。

#### 数据流目录

如果数据流较复杂，优先把细节拆成：

- `dataflow/<name>-details.md`
- `dataflow/<name>-errors.md`
- `dataflow/<name>-states.md`

其中：

- `details` 放逐步骤转换、字段流转、模块协作细节
- `errors` 放错误入口、回退、重试、异常出口
- `states` 放状态迁移、状态持有者、枚举含义、并发边界

如果规模更大，再按子链路拆，例如：

- `dataflow/rx-details.md`
- `dataflow/tx-details.md`
- `dataflow/rx-errors.md`
- `dataflow/tx-errors.md`

#### 流程图目录

如果单张流程图已经覆盖多个问题，优先把图和路径拆成：

- `flows/<name>-main.md`
- `flows/<name>-exceptions.md`

其中：

- `main` 放主流程图和必要简述
- `exceptions` 放异常路径、超时、失败处理、回退流程

#### 结构体目录

如果结构体很多，不要做一个超长总表。优先按模块或职责拆：

- `structures/<module>-context.md`
- `structures/<module>-payloads.md`
- `structures/<module>-buffers.md`
- `structures/<module>-states.md`

如果仍需总入口，再补一个：

- `detail/<name>-overview.md`

### 总览文件最低要求

总览文件必须位于 `detail/` 根目录，至少要包含：

- 这组文档覆盖什么范围
- 这组文档这次实际要落地哪些内容
- 为什么需要拆分
- 文档分布与说明文本图
- 子文档列表及一句话用途
- 关键结构体 / 关键状态 / 关键图源索引
- 阅读顺序建议

文档分布图使用手写 ASCII / text 图，不依赖 PlantUML 渲染。示例：

```text
detail/
├── printer-job-overview.md        # 总入口：范围、阅读顺序、文档分布
├── structures/
│   ├── job-context.md             # 作业上下文与状态所有权
│   └── page-buffer.md             # 页面缓冲区生命周期
├── dataflow/
│   ├── rx-details.md              # 输入到作业上下文的数据转换
│   ├── rx-errors.md               # 输入错误、回退和状态复位
│   └── rx-states.md               # 状态迁移和持有者
├── flows/
│   ├── main.md                    # 主流程图与简述
│   ├── exceptions.md              # 异常路径流程
└── tests/                         # 可选，由 ddev-pc-test 产出
    ├── protocol-overview.md       # 测试总览与可测试性结论
    ├── protocol-cases.md          # 测试用例清单
    └── protocol-env.md            # 测试环境与依赖

阅读顺序：overview -> structures/job-context -> dataflow/rx-details -> flows/main
```

### 图文分离规则

如果图本身不复杂，但文字说明很长，优先采用：

- 一个短 `detail/<name>-overview.md` 放图和 3-8 行说明
- 一个 `dataflow/<name>-details.md` 或 `flows/<name>-main.md` 放长解释

如果图本身就复杂到需要独立维护，则采用：

- `.md` 只放 ASCII 图和用途说明

不要把几十行图源、ASCII 图和长篇解释混在同一个 markdown 里。

### 引用约束

拆分后必须保证：

- `detail/<name>-overview.md` 文件能跳到所有子文档
- `details/errors/states` 文件明确回指 `detail/<name>-overview.md`
- `flows` 文档明确指向对应 `dataflow` 文档
- `dataflow` 文档明确指向对应 `structures` 文档

如果拆完之后还需要靠全文搜索才能知道去哪里看，说明拆法失败。

## 结构约束强化

根据项目语言，在 detail 阶段强化对应语言的结构约束。

### C 项目（`.c` / `.h`）

必须先加载 `ddev-c-pro` skill，这一步必须把”禁全局变量、禁分支失控、禁职责混杂”落实到结构体和数据流层，同时加入 ddev-c-pro 的通用编码规范：

- 先找出所有运行时状态，把它们收敛到明确的上下文结构体，而不是散落成多个全局变量
- **状态归属去重**：在收敛状态前，先确认同类状态是否已被已有 context 管理。如果已有 context 已管理打印机状态，新增字段应优先扩展该 context，不得创建"第二个打印机状态管理者"（无论是新 context 还是新全局变量）。
- **函数功能去重**：对每个新增函数，先搜索已有代码中是否存在功能等价的实现；如果存在可扩展的已有函数，标注为"扩展已有"而非"新增"。
- 区分配置、会话状态、缓存、输入载荷、输出结果，不要堆进一个大而全结构体
- 为每个关键状态标注谁创建、谁修改、谁释放、谁只读
- 对阶段性流程显式定义状态枚举，禁止用裸整数或魔法值表示阶段
- 一旦发现数据流依赖大量条件拼接，回头重构结构和流程，不接受”靠更多 if/else 补齐”
- 若缓冲区、协议帧或配置存在共享读写，必须写清并发边界和责任划分
- 结构体成员注释使用 Doxygen 行内格式（`/**< */`，必须用中文，参照 `ddev-comment-gen` skill），公开 API 的 `@brief` / `@param` / `@return` 必须使用中文
- 类型名统一 `_t` 后缀，公开 API 统一模块前缀，宏全大写 + 模块前缀，私有函数用 `static`
- 结构体/缓冲区声明中的大数字（≥1024）必须写成 `N * 1024` / `N * 1024 * 1024` 可读表达式并命名宏（如 `MOD_TX_BUF_SIZE (16 * 1024)`），禁止在结构体定义或示例代码里裸写大数

## 结构体与数据流文档必须回答的问题

在结构体文档和数据流文档里，至少要明确：

- 哪些字段属于长期状态，哪些只是单次调用临时值
- 哪些缓冲区应该属于上下文，哪些应该停留在局部变量
- 是否存在任何本可封装却被设计成共享可变状态的内容
- 关键分发点是按什么字段或状态驱动的，后续实现准备使用 `switch`、状态机还是表驱动
- 哪些函数只消费数据，哪些函数负责状态迁移，避免一个函数吞下整条链路
- 错误路径如何退出，资源或状态如何回滚、复位或留待下次继续处理
- 哪些字段或状态必须跨线程 / 回调边界传递，谁负责同步保护
- 公开 API 的 Doxygen 注释格式是否已按 `ddev-comment-gen` skill 在文档中明确；模块命名前缀、类型 `_t` 后缀、错误码枚举是否已按 `ddev-c-pro` skill 在文档中明确

## 文件组织

建议按职责拆成这些目录：

- `references/`：规则、模板、判断标准
- `structures/`：结构体定义文档
- `dataflow/`：数据流规划文档
- `flows/`：流程图文档
- `tests/`：PC 测试用例文档（由 `ddev-pc-test` skill 产出，可选）

如果内容复杂，可以在这些目录下继续使用“入口索引 + 分主题子文档”的方式，而不是强行维持单层平铺。

## 结果要求

- 结构体文档要能以图为主回答“干什么、谁在用、依赖什么”
- 数据流文档要能以图为主看清入口、转换、输出和边界
- 流程图文档要和结构体定义、数据流规划互相对得上，且不靠大段文字才能读懂
- 如果做了拆分，总览文档要足够短，详述文档要足够专，不能拆成多个同样冗长的文件

如果是 C 项目，还要额外满足：

- 能看出状态已经从”全局散点”收敛为”结构化上下文”
- 能看出分支复杂度是通过数据建模和流程建模被压下来的，而不是留给实现阶段堆条件
- 能直接支撑后续把函数按单一职责拆开
- 命名规范、错误码约定已按 `ddev-c-pro` skill 在文档中明确；Doxygen 注释标准已按 `ddev-comment-gen` skill 在文档中明确，可直接作为编码和审查依据

对于其他语言项目，需要满足：状态所有权清晰、数据边界明确、关键流程分发策略可在图中直接读出。具体编码规范和注释标准由对应语言的审查 skill 决定。

## 最低验收

完成这一步后，至少应能直接交给下游使用：

- `ddev-plan` 可以据此拆出精确的实现步骤
- `ddev-gate` 可以据此对照“结构体、状态、数据流、关键分支”是否按设计落地

如果当前 detail 文档还做不到下面任一项，就不算完成：

- 能唯一指出本次变更涉及哪些结构体是新增、修改还是复用
- 能通过图明确指出主数据链路的入口、出口、转换点和错误路径
- 能指出关键状态由谁持有、谁修改、谁只读
- 能指出关键流程图对应的结构体文档和数据流文档

## 常见失败模式

- 把 detail 文档写成代码现状复述，没有形成新的实现约束
- 只列字段，不写所有权、生命周期和读写方
- 数据流只写主链路，不写错误出口、回退路径或状态迁移
- 流程图覆盖过宽，把多个子问题硬揉成一张图
- 文档路径、文件名和引用关系不统一，导致下游无法定位
- 还没确认 spec 边界，就在 detail 阶段发明新的模块职责
- 明明已经过长，仍坚持单文件，导致 AI 和实现者都无法快速定位
- 拆了很多文件，但没有总览入口，导致阅读路径比拆分前更差
- 把 `overview` / `index` 总览文档放进 `dataflow/` 或 `flows/`，导致 detail 根目录没有统一入口

## 自检

detail 文档完成后，必须逐项核对：

1. **源码溯源**：每个结构体/枚举是否能追溯到实际源码中已有定义（含文件路径和行号），或明确标注为"新增"？
2. **命名冲突检查**：新增的结构体/枚举名称是否与源码中已有名称冲突？
3. **所有权明确**：每个关键状态是否标注了谁创建、谁修改、谁释放、谁只读？
4. **错误路径覆盖**：数据流文档是否包含了错误出口、回退路径或状态迁移？
5. **下游可用性**：`ddev-plan` 是否能据此拆出精确的实现步骤？`ddev-gate` 是否能据此对照验收？
6. **文档完整性**：是否有总览入口？子文档之间是否能互相跳转？
7. **无代码现状复述**：文档是否形成了新的实现约束，而非仅仅描述代码现状？
8. **结构体去重**：每个标注为"新增"的结构体，是否已确认无已有结构体可管理同类状态？是否有"扩展已有结构体"被误判为"必须新增"？
9. **全局变量合理性**：detail 文档中是否引入了文件级/全局级变量？如有，每个是否已给出无法收敛到已有 context / 局部变量的理由？
10. **依赖方向**：新增字段/函数的归属模块是否正确？是否出现在 A 模块的 context 中管理 B 模块的专属状态？是否出现底层结构体引用上层类型？

如有任一项不通过，必须在修复后再进入下一步。

## 完成后

这一步确认完之后：

- 可选进入 `ddev-pc-test`，判断本次修改是否可在 PC 上写测试 demo 直接验证；如果可以则产出测试用例文档和 demo 代码。如果不需 PC 测试或不可测试，直接跳过。
- 再进入 `ddev-plan` 把已经确认的内容拆成可执行步骤。

如果实现已完成、准备验收，则把这些 detail 文档作为 `ddev-gate` 的直接输入。若此前通过 `ddev-pc-test` 产出了测试 demo，`ddev-gate` 阶段必须跑通该 demo。

### ⚠️ 阶段交接硬门禁

**本 skill 完成后，禁止 agent 自动进入下游阶段（ddev-pc-test / ddev-plan / ddev-gate）。**

- 完成 detail 文档后，向用户报告产出路径和关键结论。
- 提示用户可选的下一步（如"进入 ddev-plan 拆解执行计划"、"进入 ddev-pc-test 评估可测试性"），但**必须等待用户明确确认后再加载对应 skill**。
- 用户未明确说"进入下一步""继续""开始 plan/pc-test/gate"等指令前，停留在当前阶段，不自行推进。

## 参考

- [结构体拆分规则](references/structure-splitting-rules.md)
- [结构体文档模板](references/structure-document-template.md)
- [数据流文档模板](references/dataflow-document-template.md)
- [流程图文档模板](references/flow-document-template.md)

