| name | ddev-detail |
| description | 代码修改场景下,spec 文档确认后,需要继续以图优先方式梳理结构体定义、数据流和流程时使用 |
实现结构体与数据流工作流
作用
当 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)中搜索并读取
- 相关时序图、流程图、接口文档(如有)
- 用户明确点名的约束,如”不能新增全局变量””必须兼容现有协议”
代码现状收集方法(优先级递减)
优先使用 CodeGraph 结构化查询:
- 从 spec 文档提取涉及的模块名
codegraph_search 搜索对应结构体名/枚举名/typedef 名
codegraph_node 获取完整定义(含字段类型、注释)
codegraph_explore 批量获取相关符号源码
CodeGraph 未初始化时回退方案:
grep 在头文件(*.h)中搜索 typedef struct / enum / typedef 声明
Read 打开搜索到的头文件,确认精确定义
收集产物
收集结果必须体现在 detail 文档中:
- 每个结构体/枚举必须标注来源:源码路径和行号(若来自已有代码),或”新增”(若为本次新设计)
- 不得凭空定义与源码中已有定义冲突的结构体或枚举
基本流程
- 读取已确认的 spec 文档,先提取模块边界、主流程、关键状态和接入点。
- 只提取本次改动涉及的结构体、状态枚举、缓冲区和协议载荷。
- 区分新增、修改、复用、废弃候选。每个结构体/枚举必须标注来源:
- 复用/修改:标注源码路径和行号(如
src/module/xxx.h:42)
- 新增:标注为"新增",并确认不与源码中已有名称冲突
不要在这一步直接删历史设计。
- 先画结构关系图,再用极少文字标注职责、生命周期、所有权、读写方和状态归属。
- 再画数据流图,串清入口、转换点、状态迁移、错误出口和输出。
- 最后只为关键链路出流程图;能靠图说明的内容,不再重复写成长文。
- 如果单份文档过长或混了多个职责,就按模块或子流程继续拆分,不要硬塞。
推荐产物顺序
建议按下面顺序落盘,避免前后反复打架:
detail/<name>-overview.md
detail/structures/*.md
detail/dataflow/*.md
detail/flows/*.md
detail/<name>-overview.md 必须索引所有子文档。dataflow 和 flows 文档必须引用对应结构体文档名,保证后续 ddev-gate 能做一一映射。总览先给图,再给一句话导航。
长文档拆分策略
拆分目标是避免单份 detail 文档过长,确保 AI 和后续实现者都能快速定位,优先按图的职责拆。
什么时候必须拆
出现下面任一情况,就不要继续维持单文件:
- 一个文档同时覆盖多个彼此相对独立的子模块或子流程
- 一份数据流文档里同时塞了总览、每步细节、错误路径、状态迁移和大段图说明
- 流程图文档已经需要同时解释多条主链路,读者必须频繁上下跳转
- 同一文件里已经出现“总览”和“大段逐步骤说明”互相打架
- 预期编码时不可能每次都把这份文档完整放进上下文
拆分原则
- 先在
detail/ 根目录保留一个短总览文件,负责入口、边界、索引和导航
- 再把高细节内容拆到子文档,不要把细节继续塞回总览
- 图和长说明可以分离;图文强绑定时,保留一个简版图文文件,再把长说明拆出去
- 拆分后文件名必须让人一眼看懂层级,不要出现
final-v2、misc 这类无语义命名
- 总览文件必须反向列出所有子文档,否则拆完只会更难找
- 不要在
dataflow/、flows/ 或 structures/ 目录里创建 *-overview.md;这些目录里的文档应当是具体详述、错误路径、状态迁移、主流程图或结构体说明
推荐拆法
detail 根目录
如果主题较复杂,先建立总览入口:
其中 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 渲染。示例:
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 放长解释
如果图本身就复杂到需要独立维护,则采用:
不要把几十行图源、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 的通用编码规范:
- 先找出所有运行时状态,把它们收敛到明确的上下文结构体,而不是散落成多个全局变量
- 区分配置、会话状态、缓存、输入载荷、输出结果,不要堆进一个大而全结构体
- 为每个关键状态标注谁创建、谁修改、谁释放、谁只读
- 对阶段性流程显式定义状态枚举,禁止用裸整数或魔法值表示阶段
- 一旦发现数据流依赖大量条件拼接,回头重构结构和流程,不接受”靠更多 if/else 补齐”
- 若缓冲区、协议帧或配置存在共享读写,必须写清并发边界和责任划分
- 结构体成员注释使用 Doxygen 行内格式(
/**< */,参照 ddev-comment-gen skill),公开 API 必须有 @brief / @param / @return
- 类型名统一
_t 后缀,公开 API 统一模块前缀,宏全大写 + 模块前缀,私有函数用 static
结构体与数据流文档必须回答的问题
在结构体文档和数据流文档里,至少要明确:
- 哪些字段属于长期状态,哪些只是单次调用临时值
- 哪些缓冲区应该属于上下文,哪些应该停留在局部变量
- 是否存在任何本可封装却被设计成共享可变状态的内容
- 关键分发点是按什么字段或状态驱动的,后续实现准备使用
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 文档完成后,必须逐项核对:
- 源码溯源:每个结构体/枚举是否能追溯到实际源码中已有定义(含文件路径和行号),或明确标注为"新增"?
- 命名冲突检查:新增的结构体/枚举名称是否与源码中已有名称冲突?
- 所有权明确:每个关键状态是否标注了谁创建、谁修改、谁释放、谁只读?
- 错误路径覆盖:数据流文档是否包含了错误出口、回退路径或状态迁移?
- 下游可用性:
ddev-plan 是否能据此拆出精确的实现步骤?ddev-gate 是否能据此对照验收?
- 文档完整性:是否有总览入口?子文档之间是否能互相跳转?
- 无代码现状复述:文档是否形成了新的实现约束,而非仅仅描述代码现状?
如有任一项不通过,必须在修复后再进入下一步。
完成后
这一步确认完之后:
- 可选进入
ddev-pc-test,判断本次修改是否可在 PC 上写测试 demo 直接验证;如果可以则产出测试用例文档和 demo 代码。如果不需 PC 测试或不可测试,直接跳过。
- 再进入
ddev-plan 把已经确认的内容拆成可执行步骤。
如果实现已完成、准备验收,则把这些 detail 文档作为 ddev-gate 的直接输入。若此前通过 ddev-pc-test 产出了测试 demo,ddev-gate 阶段必须跑通该 demo。
参考