ddev-archive — 变更归档与最终设计定型
把同一主题下经过多轮迭代的所有活跃计划中的 spec 文档 归档到 YY-MM-DD_<主题名>/ 目录,并生成一份 final-spec.md 记录最终代码事实设计。
开始时声明: "正在使用 ddev-archive skill 归档变更。"
归档范围:只归档 spec 与 final-spec
只归档两种文档:
- spec — 各轮迭代的原始 spec 文档(设计意图记录)
- final-spec.md — 综合所有 spec 生成的最终代码事实设计
不归档,归档完成后直接删除(原计划目录不保留任何残留):
detail/(结构体/数据流设计)exec_plans/、task_plan.md(实现/任务计划)implementation-notes.md(实现决策记录)progress.md(执行日志)- 其他非 spec 文档
⚠️ 执行文档存放位置(硬性规范)
progress.md / implementation-notes.md / task_plan.md / exec_plans/ 等执行文档必须写在对应计划目录下(docs/plans/YY-MM-DD_<topic>/),禁止写仓库根目录、docs/ 或其他与计划无关的位置。
- 若发现执行文档落在计划目录之外(如仓库根目录
progress.md),视为放错位置,归档时一并纠正(git mv到对应计划目录,无对应计划则删除,不保留孤儿文档)。 - 归档时这些执行文档随计划目录一并删除,不迁移进
archive/。
何时使用
- 实现 + 所有调试迭代已完成,代码已提交
- 同一功能经历了多轮 plan(初始 spec → 调试后调整 → 最终版本)
- 最终设计与原始 spec 存在差异(调试中修改了方案)
- 准备关闭 feature 分支、清理工作区或进入发布前
- 需要给后续维护者留下"实际长什么样"的最终设计文档
不使用的情况:
- 还没开始实现 → 先用 ddev-spec
- 还在调试中 → 先调完再说
- 实现与原计划完全一致且只有一个 plan → 可以归档,但 final-spec.md 只需简述"实现与初始 plan 一致,无偏离"
归档目录结构
docs/plans/archive/YY-MM-DD_<topic-name>/
├── spec/ ← 各轮迭代的 spec 文档(原文件名保留)
│ ├── <topic>.md ← 初始 spec
│ └── <topic>-iter1.md ← 迭代 spec(同名冲突时加序号前缀)
├── final-spec.md ← 综合所有 spec 的最终代码事实设计
└── archive-notes.md ← 可选,归档说明
YY-MM-DD为归档日期(当天),<topic-name>为主题英文名(kebab-case)- 多个迭代 spec 同名时,按时间顺序加
01_/02_/0N_前缀 - 只归档 spec 文档;原计划目录中非 spec 文档(detail/exec_plans/task_plan/implementation-notes/progress)在归档完成后删除,空目录随计划目录一并清理
流程
第一步:扫描活跃计划
- 确定本次变更的主题名/功能名。从当前 spec 文档标题、用户指定或对话上下文提取。
- 扫描
docs/plans/目录(排除archive/子目录),列出所有与本次主题相关的计划目录。 - 相关性判断:
- 目录名包含相同主题关键词(如
usb-hid、usb_hid、hid-report) - 目录下的 spec 文档标题或内容引用同一功能
- 用户显式指定了哪些目录属于同一变更
- 目录名包含相同主题关键词(如
- 如果扫描结果超过 5 个目录,列出清单让用户确认哪些属于本次变更。
第二步:排序与分类
按日期和时间顺序排列所有相关计划目录,标记迭代顺序(01_initial → 02_iter1 → ... → 0N_final)。排序只用于给 spec 文档命名与定位,不创建多级子目录。
- 从目录名中的日期提取时间顺序
- 如果目录名无日期,按文件修改时间排序
- 如果只有一个计划目录,直接标记为
01_initial
第三步:读取各迭代的 spec 文档
对每个迭代,只读取 spec/ 目录下的 spec 文档,提取:
- Delta Summary 表、模块边界图、联动修改清单
- 涉及的关键数据结构 / 流程(供 final-spec 综合)
不读取、不依赖非 spec 文档(detail/exec_plans/task_plan/implementation-notes/progress)。
第四步:生成 final-spec.md
基于所有迭代 spec 文档的对比分析,生成最终代码事实设计文档。
文档位置
docs/plans/archive/YY-MM-DD_<topic-name>/final-spec.md
文档结构
# [功能名] — 最终代码事实设计
> **归档日期**: YYYY-MM-DD | **迭代次数**: N
>
> 本文档综合 [N] 轮迭代的 spec 文档,记录经过实机调试后的最终代码事实。
> 如与某轮迭代的 spec 存在差异,以本文档为准。
## 1. 变更面总览 (Delta Summary)
| 类型 | 对象 | 最终状态 |
|------|------|---------|
| ADDED | ... | ... |
| MODIFIED | ... | ... |
| REMOVED | ... | ... |
> 此表综合所有迭代的最终结果。与初始计划的差异在 §2 中说明。
## 2. 与原计划的关键差异
| 迭代 | 原计划 | 最终实现 | 原因 |
|------|--------|---------|------|
| 01_initial | [初始设计要点] | [实际落地情况] | [调试发现/框架约束/...] |
| 02_iter1 | [迭代1调整] | [实际落地情况] | ... |
> 如果只有一轮且无差异,写"实现与初始 plan 一致,无偏离"。
## 3. 最终架构总览
(ASCII 图 — ddev-diagram 规范 — 反映最终代码的模块边界和调用关系)
## 4. 最终核心数据结构
(经过调试确认的最终结构体、枚举、状态机定义)
每个结构体/枚举必须标注:
- 来源:来自 `spec/<topic>-iterN.md` 的 xxx 部分
- 如果与任何一轮 spec 不同,标注差异
## 5. 最终核心流程
(ASCII 图 — 反映最终代码的实际数据流和关键流程)
## 6. 调试发现的问题及修复
### Bug 1: [标题]
| 项目 | 内容 |
|------|------|
| 发现于 | iterX |
| 症状 | ... |
| 根因 | ... |
| 修复 | ... |
| 影响的设计文档 | 对应 spec 中 xxx 部分 |
## 7. 未覆盖风险与已知限制
- [风险/限制 1]:[说明及缓解措施]
- [风险/限制 2]:[说明及缓解措施]
## 8. 设计决策记录
| 决策 | 触发迭代 | 决策内容 | 替代方案(为什么没选) |
|------|---------|---------|---------------------|
| ... | 02_iter1 | ... | ... |
⚠️ 硬门禁:画图前必须先加载 ddev-diagram
在任何 ASCII 图动笔之前,必须执行 Skill("ddev-diagram") 加载绘制规范。
第五步:创建归档目录并移动 spec
- 创建
docs/plans/archive/YY-MM-DD_<topic-name>/spec/ - 将每个迭代目录下的 spec 文档 移动到归档
spec/下- 必须使用
git mv,不要用mv或cp + rm,否则 git 会丢失文件历史 - 例:
git mv docs/plans/26-08-05_xxx/spec/xxx.md docs/plans/archive/26-08-06_xxx/spec/xxx.md - 同名冲突时按迭代顺序加
01_/02_前缀
- 必须使用
- 将
final-spec.md(和可选的archive-notes.md)写入归档根目录,git add暂存
⚠️ 门禁:归档完成后必须删除原计划目录
原计划目录清理是归档流程的强制终点,不可省略、不可保留"等确认"残留。
- 删除非 spec 文档:spec 全部
git mv移走后,原计划目录剩余的 detail/、exec_plans/、task_plan.md、implementation-notes.md、progress.md 等不再保留。删除前确认其核心内容已被 final-spec 覆盖(尤其 implementation-notes 中的决策记录),已跟踪文件用git rm,未跟踪文件直接rm - 清理原计划目录:剩余文件全部删除后,原计划目录已空,连同其空子目录一并删除
- 验证清理结果:
git status确认原计划目录路径下已无任何残留(删除全部变为 stagedD,spec 变为 stagedR),归档目录只剩 spec + final-spec(+ archive-notes)。若原计划目录仍存在非空内容,视为门禁未通过,回到第 4-5 步修正
归档结束后工作区不得残留:原计划目录本身、其中任何文档、或散落在仓库根目录的执行文档。
第六步:生成 archive-notes.md(可选)
如果存在以下情况,创建 archive-notes.md:
# 归档说明
> 归档日期:YYYY-MM-DD
## 归档范围
- spec:各轮迭代 spec 文档
- final-spec.md:最终代码事实设计
## 已删除内容
- [原计划目录中删除的非 spec 文档及删除原因,如"实现细节已被 final-spec 综合,无长期参考价值"]
## 未决项
- [Open Questions 中仍未解决的问题]
图怎么选
优先画:
- 最终架构总览(模块框 + 调用关系,反映最终代码)
- 最终核心流程(数据流/时序图)
- 关键数据结构对比(如有迭代间结构变化)
不需要画:
- 各迭代中已正确且未变化的部分(引原文档即可)
- 调试过程中被废弃的方案
写法原则
- 只写最终状态:不写"调试过程中试过 A 不行换 B 最后选了 C"
- 差异必须标注:如果最终实现与某轮 spec 不同,必须显式标注
- 图优先:能用图说清的不用长文
- 引不抄:原 spec 里正确且不变的部分,一句话引原文档,不重复写
- 代码事实为准:final-spec 描述的是代码实际行为,不是"应该是这样"
与其他 skill 的关系
- 上游:
ddev-spec(产生 spec)+ddev-exec(实现)+ 实机调试(可能产生多轮迭代 spec) - 并行:
ddev-diagram(画图规范) - 下游:
neat-freak(归档清理时引用 final-spec.md) - 替代关系:原各迭代的 spec 文档保留在归档
spec/中作为设计意图记录,final-spec.md为最终权威版本
自检
归档完成后逐项核对:
- spec 完整性:是否找到了所有相关计划目录的 spec 文档?遗漏的目录是否已确认不属于本次变更?
- Delta Summary:final-spec.md 的 Delta Summary 是否覆盖了所有迭代的最终变更面?
- 差异覆盖:是否每轮迭代的"原计划 vs 最终实现"差异都已记录?
- 最终架构图:是否反映实际代码的模块边界和调用关系(而非某轮 spec 的复制)?
- 数据结构一致性:final-spec.md 中的结构体/枚举是否与
.h中的实际定义一致? - ASCII 图规范:所有 ASCII 图是否通过 ddev-diagram 门禁?
- 只归档 spec:归档目录中是否只有 spec + final-spec(+ archive-notes)?非 spec 文档是否已删除、原计划目录是否已清理干净(含空子目录)?
- Debug bug 完整:每个调试发现的 bug 是否有症状/根因/修复三要素?
- 执行文档位置:
progress.md等执行文档是否只存在于对应计划目录?仓库根目录或其他位置是否有孤儿执行文档(如有,已纠正或删除)?