Community生产力与协作github.com

OpenSpec 合并

通过两阶段审批工作流,将 `openspec/specs/` 下多个零散的能力文件夹合并为一个主功能规范。当用户抱怨规范文件夹杂乱、重叠或需要合并时使用此技能。

OpenSpec 合并 是什么?

OpenSpec Merge 是一项 AI 代理技能,旨在清理和整合 `openspec/specs/` 中分散的、功能重叠的规范文件夹。它通过“阶段 A(暂存)”和“阶段 B(应用)”两个阶段来工作:首先读取所有源规范,合并成一个草稿并写入 `openspec/specs/.merged-specs/<功能名>/spec.md`,同时在该文件的 frontmatter 中设置 `Approved-by-human: no`;在人类审查并手动将标记改为 `yes` 之前,不会修改任何原有文件。第二阶段在检测到 `Approved-by-human: yes` 后执行,用合并后的内容替换源文件夹,清除暂存文件,并通知用户变更详情。该技能适用于用户明确要求合并多个已存档的能力文件夹的情况,不适合单个变更的常规归档。它可运行在任何支持文件系统操作和 Markdown 处理的 AI 代理平台上(如 Claude Code、Codex)。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/duongphuhiep/dakubo-skills/tree/HEAD/package/skills/dakubo-openspec-merge

Installed? Explore more 生产力与协作 skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

OpenSpec 合并 是做什么的?

通过两阶段暂存/审批工作流,将 openspec/specs/ 中几个相关的能力文件夹合并为一个主要功能规范。在人类明确批准合并之前,绝不会修改 openspec/specs/<能力名称>/ 下的任何内容。

何时适用

OpenSpec 的归档工作流会将每次变更的增量同步到 openspec/specs/<能力名称>/spec.md 中。当相关变更被归档到不同的能力名称下(通常是因为它们分阶段构建,例如 user-show、user-detail、user-permissions),最终会得到多个描述单一功能的规范文件夹。此技能通过一个需要人工签核的暂存区域来合并这些文件夹,在真正替换任何文件之前先获得批准。

两个阶段

  • 阶段 A — 暂存:读取源规范,将合并后的草稿写入 openspec/specs/.merged-specs/<功能名称>/spec.md,frontmatter 中设置 Approved-by-human: no。不改变其他任何内容。
  • 阶段 B — 应用:当用户将 frontmatter 中的 Approved-by-human 改为 yes 后触发。用审批通过的内容替换源文件夹,并删除暂存文件。

始终先判断当前应触发哪个阶段:如果 openspec/specs/.merged-specs/<功能名称>/ 已存在,则首先检查其 Approved-by-human 字段,而不是从头重新暂存。

阶段 A — 暂存

1. 识别候选文件夹

列出 openspec/specs/* 并查找符合以下条件的文件夹:

  • 共享共同名称前缀或领域词(例如 user-show、user-detail、user-permissions)
  • 在其需求中引用相同的实体/资源(相同的模型、相同的 API 端点、相同的 UI 页面)
  • 归档时间相近(检查 openspec/changes/archive/ 的日期)

如果用户明确指定了文件夹名称,则直接使用,不再猜测。

如果存在多个可能的分组,则暂停并询问用户哪些文件夹应归为一组,然后再进行暂存。

2. 完整读取每个候选 spec.md

对于每个文件夹,读取完整的 spec.md,而不仅仅是标题。记录需求名称、场景、弃用标记,以及任何看起来会修改/取代其他候选文件夹中需求的内容。

3. 推断目标能力名称

根据候选文件夹的共同前缀或共享领域名词推导(例如 user-show + user-detail + user-permissions → user,或者如果 user-management 读起来更自然则使用后者)。

  • 有清晰的共同前缀/领域 → 直接使用,无需询问。
  • 没有明显的共享名称(例如 checkout-flow 和 invoice-export 仅因模糊的“计费”主题相关)→ 在处理前询问用户目标能力名称。

在输出中明确声明推断出的名称,以便用户覆盖。

4. 合并需求

规则,按顺序执行:

  • ADDED 需求的并集:保留每个源文件夹中的每个不同需求。
  • 冲突/重复需求(同名,或相同行为描述两次):保留最完整/最新的版本,合并非冲突细节,而不是静默丢弃任何一个。
  • REMOVED/弃用的需求:从合并后的规范中排除。
  • 绝不发明需求。 在行内标记歧义或矛盾(例如 <!-- CONFLICT: 源 A 说 X,源 B 说 Y — 需要人类决策 -->),而不是静默选择。
  • 尽可能保留原始场景文本;仅在将两个重叠需求合并为一个时才重写散文。

5. 写入暂存文件

写入:

openspec/specs/.merged-specs/<推断名称>/spec.md

在文件开头添加以下 frontmatter:

---
Approved-by-human: no
merged-from:
  - user-show
  - user-detail
  - user-permissions
---

随后跟上合并后的规范内容。

6. 简要告知用户

  • 哪些源文件夹被合并,以及推断出的目标名称
  • 行内标记的任何需要决策的冲突
  • 下一步具体操作:打开 openspec/specs/.merged-specs/<推断名称>/spec.md,审查它,必要时编辑,并在满意后设置 Approved-by-human: yes
  • openspec/specs/<能力名称>/ 下的任何内容尚未被修改

阶段 B — 应用

触发条件:用户要求应用/完成合并,或者你发现 openspec/specs/.merged-specs/<功能名称>/spec.md 的 Approved-by-human 为 yes。

  1. 重新读取暂存文件并确认 Approved-by-human: yes。如果仍然是 no,则停止并告知用户需要先批准 — 不要执行应用。
  2. 从 frontmatter 中读取 merged-from,以确定要替换哪些源文件夹。
  3. 从暂存内容中剥离 frontmatter(两个字段),得到不含 frontmatter 的干净 spec.md。
  4. 用合并结果替换源文件夹:
    • 创建/覆盖 openspec/specs/<推断名称>/spec.md,内容为剥离 frontmatter 后的结果。
    • 删除 merged-from 中列出的、不是目标名称本身的其他源文件夹。
  5. 删除暂存文件夹 openspec/specs/.merged-specs/<推断名称>/。
  6. 向用户确认替换/删除了哪些内容,以便在提交前通过 git diff 轻松检查。

绝不要在文件中没有显式 Approved-by-human: yes 的情况下执行第 4 步 — 也不要要求用户在聊天中口头批准作为替代;批准必须是翻转的 frontmatter 字段本身。

示例

阶段 A — 输入:openspec/specs/user-show/、openspec/specs/user-detail/、openspec/specs/user-permissions/ — 全部描述同一用户档案功能的不同方面。

输出:openspec/specs/.merged-specs/user/spec.md:

---
Approved-by-human: no
merged-from:
  - user-show
  - user-detail
  - user-permissions
---

# User

## Requirement: ...
...

给用户的消息:已从 user-show、user-detail、user-permissions 合并为推断的能力名称 user(如果更倾向于 user-management 可重命名文件夹);未发现冲突;请审查 openspec/specs/.merged-specs/user/spec.md 并在准备好后设置 Approved-by-human: yes。

阶段 B — 一旦用户设置了 Approved-by-human: yes 并要求应用:创建/覆盖 openspec/specs/user/spec.md,内容为剥离 frontmatter 后的合并结果;删除 user-show/、user-detail/、user-permissions/;以及删除 openspec/specs/.merged-specs/user/。

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

相关技能