--- name: dev-flow description: 轻量开发流程:想清楚 → 做出来 → 收好尾。编排 OpenSpec 的 propose / apply / archive 三个能力,并为每个非平凡变更留下 decision.md——记录为什么这么做、否决了哪些备选、代价是什么。在用户显式调用 /dev-flow,或明确要求走开发流程时使用。 --- # Dev Flow 三个阶段,两个确认点,不分档。 ```text Think 想清楚 → Build 做出来 → Close 收好尾 ⏸ 确认点 1 ⏸ 确认点 2 授权进入实现 是否归档 ``` **每个非平凡变更留下一份 `decision.md`**——记录代码和规格承载不了的东西:**为什么这么做,以及放弃了什么。** ## 能力来源 dev-flow 编排已有能力,**不重复实现它们**: | 阶段 | 能力 | 用途 | |---|---|---| | Think | `grill-with-docs` | 澄清:一次一问、能查代码的自己查、术语沉淀进 `CONTEXT.md` | | Think | `openspec-propose` | 生成 `proposal.md` / `design.md` / `specs/` / `tasks.md` | | Build | `openspec-apply-change` | 按规格实现 | | Build | `diagnose` / `tdd` | 按需:bug 排查 / 测试驱动 | | Close | `openspec-archive-change` | 归档 | **按能力绑定,不按路径绑定**:优先用平台原生 skill;不可用时读本地 `SKILL.md` 并按其协议执行;仍不可用时按最小等价协议直接产出文件。**不可用时在 `decision.md` 里注明。** **不使用 `to-prd`**:它把 PRD 发布到 issue tracker(本仓库没有),且内容与 `proposal.md` + `specs/` 重复。 **不设 `audit` 阶段**:`zoom-out` 保留为按需能力(不熟悉代码区域时拉高视角),但它不是一个必须走的关卡。 ### 冲突裁决 被组合的子 skill 与本流程会冲突——这是组合的固有代价。**靠规则裁决,不靠内置。** > **子 skill 管"这一步怎么做";dev-flow 管"做多少、结果放哪"。** > **冲突时,流程赢。** 当前组合里,由 dev-flow 覆盖子 skill 默认的有三处: | 子 skill 的默认 | dev-flow 的覆盖 | |---|---| | `grill-with-docs` 要求 relentlessly 追问 | **范围收窄**:只问答案会改变产物的问题 | | ADR 写入 `docs/adr/`,用 `ADR-FORMAT.md` | **落点改为 `decision.md`**,格式用 `decision-note.md`,**不创建 `docs/adr/`** | | 假设根目录 `CONTEXT.md` | 用 **`devflow/glossary/CONTEXT.md`** | **归属规则解决不了的冲突,不要靠内置解决,而是不组合它。** > 理由:内置只在被组合 skill **消失**时才消除冲突。只要它还装在目录里(用户可以直接调用), > 内置就只是让 dev-flow 多出一份**会漂移的私有副本**——重复实现加上版本漂移,两个问题。 > `to-prd` 就是这么处理的:直接排除,而不是改造成 dev-flow 的版本。 ## Think — 想清楚 **进入**:用户给出需求——粗略想法、issue、草稿、已有 PRD 都算。 **动作**: 1. **澄清** —— 用 `grill-with-docs` 的方法,但按上面的 **「冲突裁决」** 覆盖它的默认: 范围收窄(只问答案会改变产物的问题)、ADR 落点为 `decision.md`、`CONTEXT.md` 用 `devflow/glossary/` 下那份。 **被否决的答案当场记进 `decision.md` 的 `## Alternatives considered`**(一行一条:问过什么、为什么输)——这是 Q&A 形态,见 `references/decision-note.md`)。 2. **读上下文**:`devflow/glossary/CONTEXT.md`,并搜索 `devflow/rejected/` 与已归档的 `decision.md`—— **避免重新提出已经被否决过的方案。** 3. 写 `openspec/changes//proposal.md`,并用 OpenSpec 补全 `design.md` / `specs/` / `tasks.md`。 4. **写下 `decision.md` 的 `## Problem` 和 `## Alternatives considered`。** 理由在这一刻最新鲜;留到事后补写会变成回忆录。 **退出**:proposal 能说清做什么、范围、非目标;`decision.md` 有 `## Problem` 和至少一条备选(或用 `` 显式声明没有)。 **⏸ 确认点 1** —— 向用户汇报方案方向、关键假设、主要风险,然后**等待明确的实现授权**。 > 未获授权不得进入 Build。 > **方案讨论中的任何一次确认,都不等于实现授权。** > 快节奏交付下可以预授权,但必须显式:Think 退出时在 `decision.md` 写下 > ``。静默跳过不允许——旁路是有意识的选择,不是遗忘。 > 授权状态以这行标记为准,恢复会话时读它,不靠对话记忆。 ## Build — 做出来 **进入**:确认点 1 已过。 **动作**: - 按 `tasks.md` 的纵向切片实现,按 `specs/` 验收。 - **分步验证**:每完成一层再继续,不要一次写完再验。 - **tasks/design 里提到"参考 XXX 实现"的,实现前先完整读它**——设计文档点名参考而实现时没看,是返工最常见的来源。 - **冲突先分类再处理**: | 分类 | 处理 | |---|---| | 规格不准(遗漏、边界未覆盖、验收口径缺失) | 暂停,修正 OpenSpec,再继续 | | 代码偏离(实现没按规格做) | 修正代码,不改 OpenSpec | | 不确定、或涉及设计方向 | **暂停,问用户** | - 遇到 bug 或行为不明 → 用 `diagnose`;需要测试驱动 → 用 `tdd`。两者都不强制。 **退出**:tasks 完成或剩余已明确记录;已运行验证,或记录了未验证的原因;已知限制已列出。 Build 结束**自动进入 Close**,中间不设确认点。 ## Close — 收好尾 **进入**:实现达到可交接状态。 **动作**: 1. **补齐 `decision.md`**——把 `## Decision` 校准为**实际发布的做法**(现在时),补 `## Consequences` 和 `## Verification`。 2. **执行收尾检查**(见下)。 3. 检查澄清阶段的新术语**已**沉淀进 `devflow/glossary/CONTEXT.md`(写入时机在术语确认的当场,见「冲突裁决」;这里只查漏)。 4. 有被否决的提案 → 确认**已在否决发生时**写入 `devflow/rejected//`(这里只兜底检查)。 **退出**:`decision.md` 五节齐全;收尾检查通过;用户已被询问是否归档。 ## 核心规则 | 规则 | 说明 | |---|---| | **必须写 `decision.md`** | 每个非平凡变更 | | **`## Alternatives considered` 强制** | 没有记录"打败了什么"的决策会招来重新争论 | | **备选是记录的,不是编造的** | 当时没记录就写 `` | | **实现前必须有授权** | 确认点 1 | | **冲突先分类再处理** | 三分法 | | **一个事实只有一个权威** | 见下表 | **"非平凡"的判据**:改变行为、架构、跨文件或跨包的契约、流程或工具、测试策略、磁盘/线缆/配置格式,或其他维护者可能重新考察的决策。 **豁免**:纯机械或局部编辑。**小修不值得触发本流程**——dev-flow 是显式触发的 opt-in 流程,轻的第一道防线是不进来;后来发现重要时,允许事后补录 `decision.md`(retrofit 已验证)。 ### 事实的唯一权威 | 内容 | 权威 | |---|---| | 为什么这么做、放弃了什么、代价 | `decision.md` | | 实现设计、接口影响 | `design.md` | | 可观察行为、验收场景 | `specs/` | | 执行切片与完成状态 | `tasks.md` | | 跨项目术语 | `devflow/glossary/CONTEXT.md` | | 未实施的提案 | `devflow/rejected/` | **任何一句话只能在一个地方是权威。出现第二处,就是错**——两边会各自腐化,而且没人知道以哪边为准。 ## 为什么这么轻 这三条是有意为之。**不要"补全"它们。** 1. **义务挂在已有动作上。** 写规划产物的时刻,就是写 `decision.md` 的时刻。不设独立的归档阶段,不做事后提取。 2. **确认点只有两个。** 进入实现、是否归档。不新增。 3. **"是否该写"是判断。** 规则 + 收尾看一眼。机器只校验**已经写下**的东西是否合规,不用脚本强制这件事本身。 ## 收尾检查 1. `openspec/changes//decision.md` 存在 2. 含 `## Alternatives considered`,或显式的 `` 3. `## Verification` 里没有"已确认 X 存在"这类**不可重跑的结论** 纯机械改动可以豁免。**豁免必须显式,但可以廉价**——目的是让"跳过"变成有意识的选择,而不是静默遗忘。 > **已落地**:`scripts/check-dev-flow.sh ` 执行上述三项检查;`--index` 扫描归档派生 `devflow/index.md`(不手写);`--all` 检查全部活跃 change。 ## 目录 ```text openspec/changes// ├── proposal.md design.md specs/ tasks.md └── decision.md ← 人向:为什么、放弃了什么、代价 ↓ 随归档一起冻存 devflow/ ├── glossary/CONTEXT.md ← 跨项目术语 ├── rejected// ← 未实施的提案(否决发生时写入,不是 Close 时) └── index.md ← scripts/check-dev-flow.sh --index 派生,不手写 ``` `rejected/` 的保留条件:它**仍能防止一个诱人的、有意义的错误**。否则整体删除。 **边界**:`decision.md` 的 Alternatives 记"变更内"的方案备选;`rejected/` 收"整个提案被否决"的方向。提案在确认点 1 被整个否决时,当场写入 `rejected/`——那时流程已终止,Close 不会执行。 ## 触发规则 - 用户输入 `/dev-flow`。 - 用户明确要求走开发流程。 不要因为任务涉及 OpenSpec、跨模块、架构决策或 devflow 目录就自动触发。 未被这样要求之前,按普通工程任务处理。 **`decision.md` 义务只覆盖经本流程的非平凡变更**——不经 dev-flow 的普通工程任务没有这个义务。 ## 相关文档 - `references/phases.md` — 三阶段契约与判断细则 - `references/decision-note.md` — `decision.md` 格式规范、校准案例、反模式 - `skill-workbench/docs/dev-flow/background-and-evolution.md` — 背景、技术演进、设计取舍