Files
git-learn/.agents/skills/dev-flow/SKILL.md
T
zhuyongxin 24a71e78f1 Harden dev-flow: pre-authorization marker, alternatives log, check script
- Record rejected answers in decision.md at the moment they are rejected

- Allow explicit pre-authorized Build via a pre-authorized marker line

- Land scripts/check-dev-flow.sh and derive devflow/index.md from archives

- Add dev-flow process artifacts (decisions, prd) for open changes
2026-09-18 18:23:18 +08:00

9.7 KiB

name, description
name description
dev-flow 轻量开发流程:想清楚 → 做出来 → 收好尾。编排 OpenSpec 的 propose / apply / archive 三个能力,并为每个非平凡变更留下 decision.md——记录为什么这么做、否决了哪些备选、代价是什么。在用户显式调用 /dev-flow,或明确要求走开发流程时使用。

Dev Flow

三个阶段,两个确认点,不分档。

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/<slug>/proposal.md,并用 OpenSpec 补全 design.md / specs/ / tasks.md。
  4. 写下 decision.md 的 ## Problem 和 ## Alternatives considered。 理由在这一刻最新鲜;留到事后补写会变成回忆录。

退出:proposal 能说清做什么、范围、非目标;decision.md 有 ## Problem 和至少一条备选(或用 <!-- alternatives-not-recorded --> 显式声明没有)。

⏸ 确认点 1 —— 向用户汇报方案方向、关键假设、主要风险,然后等待明确的实现授权。

未获授权不得进入 Build。 方案讨论中的任何一次确认,都不等于实现授权。 快节奏交付下可以预授权,但必须显式:Think 退出时在 decision.md 写下 <!-- pre-authorized: 日期 + 范围/原因 -->。静默跳过不允许——旁路是有意识的选择,不是遗忘。 授权状态以这行标记为准,恢复会话时读它,不靠对话记忆。

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/<class>/(这里只兜底检查)。

退出:decision.md 五节齐全;收尾检查通过;用户已被询问是否归档。

核心规则

规则 说明
必须写 decision.md 每个非平凡变更
## Alternatives considered 强制 没有记录"打败了什么"的决策会招来重新争论
备选是记录的,不是编造的 当时没记录就写 <!-- alternatives-not-recorded -->
实现前必须有授权 确认点 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/<slug>/decision.md 存在
  2. 含 ## Alternatives considered,或显式的 <!-- alternatives-not-recorded -->
  3. ## Verification 里没有"已确认 X 存在"这类不可重跑的结论

纯机械改动可以豁免。豁免必须显式,但可以廉价——目的是让"跳过"变成有意识的选择,而不是静默遗忘。

已落地:scripts/check-dev-flow.sh <slug> 执行上述三项检查;--index 扫描归档派生 devflow/index.md(不手写);--all 检查全部活跃 change。

目录

openspec/changes/<slug>/
├── proposal.md   design.md   specs/   tasks.md
└── decision.md              ← 人向:为什么、放弃了什么、代价
       ↓ 随归档一起冻存

devflow/
├── glossary/CONTEXT.md      ← 跨项目术语
├── rejected/<class>/        ← 未实施的提案(否决发生时写入,不是 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 — 背景、技术演进、设计取舍