OpenSpec 병합
openspec/specs/ 아래의 여러 관련 기능 폴더를 하나의 메인 기능 스펙으로
병합합니다. 두 단계(스테이징/승인) 워크플로우를 통해 진행됩니다.
openspec/specs/<capability>/ 아래의 내용은 사람이 명시적으로 승인하기 전에는
절대 변경되지 않습니다.
적용 시점
OpenSpec의 아카이브 워크플로우는 각 변경사항을 openspec/specs/<capability>/spec.md로 동기화합니다.
관련 변경사항이 서로 다른 기능 이름으로 아카이브될 때(예: 변경이 단계별로 이루어져
user-show, user-detail, user-permissions와 같이 나뉜 경우),
실질적으로 하나의 기능을 설명하는 여러 개의 스펙 폴더가 생성됩니다.
이 스킬은 이러한 폴더들을 하나로 병합하며, 실제 내용이 교체되기 전에
사람의 승인을 요구하는 스테이징 영역을 사용합니다.
두 단계
- Phase A — 스테이징: 소스 스펙을 읽고, 병합된 초안을
openspec/specs/.merged-specs/<feature>/spec.md에Approved-by-human: no상태로 작성합니다. 다른 것은 변경되지 않습니다. - Phase B — 적용: 사용자가 frontmatter를
Approved-by-human: yes로 변경하면 트리거됩니다. 승인된 내용으로 소스 폴더를 교체하고 스테이징 파일을 제거합니다.
항상 어떤 단계가 적용되는지 감지해야 합니다. openspec/specs/.merged-specs/<feature>/가
이미 존재하면, 처음부터 다시 스테이징하지 않고 먼저 Approved-by-human 필드를 확인하세요.
Phase 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. 요구사항 병합
규칙, 순서대로:
- 추가된 요구사항의 합집합: 모든 소스 폴더의 모든 고유 요구사항을 유지합니다.
- 충돌/중복 요구사항 (동일한 이름, 또는 동일한 동작이 두 번 설명됨): 가장 완전하고 최신 버전을 유지하고, 충돌하지 않는 세부사항은 묵시적으로 버리지 않고 병합합니다.
- 제거/폐기된 요구사항: 병합된 스펙에서 제외합니다.
- 요구사항을 절대 새로 만들지 마십시오. 모호함이나 모순을 인라인으로 표시하십시오
(예:
<!-- CONFLICT: 소스 A는 X라고 말하고, 소스 B는 Y라고 말함 — 사람의 결정 필요 -->) 묵시적으로 하나를 선택하지 마십시오. - 가능하면 원본 시나리오 텍스트를 보존하고, 두 개의 겹치는 요구사항을 하나로 병합할 때만 산문을 다시 작성하세요.
5. 스테이징 파일 작성
다음 위치에 작성:
openspec/specs/.merged-specs/<inferred-name>/spec.md
다음 frontmatter를 맨 위에 추가:
---
Approved-by-human: no
merged-from:
- user-show
- user-detail
- user-permissions
---
그 뒤에 병합된 스펙 내용을 추가합니다.
6. 사용자에게 간략히 알림
- 어떤 소스 폴더가 병합되었는지, 그리고 추론된 대상 이름
- 인라인으로 표시된 충돌 중 결정이 필요한 사항
- 다음에 해야 할 일:
openspec/specs/.merged-specs/<inferred-name>/spec.md를 열고, 검토하고, 필요하면 편집한 후, frontmatter에서Approved-by-human: yes로 설정하세요. openspec/specs/<capability>/아래의 내용은 아직 건드리지 않았음을 알립니다.
Phase B — 적용
트리거: 사용자가 병합을 적용/최종화하도록 요청하거나,
openspec/specs/.merged-specs/<feature>/spec.md의 Approved-by-human이 yes임을 발견한 경우.
- 스테이징 파일을 다시 읽고
Approved-by-human: yes를 확인합니다. 여전히no이면 중단하고 사용자에게 먼저 승인이 필요하다고 알리세요 — 적용하지 마십시오. - frontmatter에서
merged-from을 읽어 어떤 소스 폴더를 교체할지 확인합니다. - 스테이징된 내용에서 frontmatter(두 필드 모두)를 제거하고, frontmatter가 없는
깨끗한
spec.md를 만듭니다. - 소스 폴더를 병합된 결과로 교체합니다:
- frontmatter가 제거된 내용으로
openspec/specs/<inferred-name>/spec.md를 생성/덮어씁니다. merged-from에 나열된 다른 소스 폴더 중 대상 이름과 다른 폴더를 제거합니다.
- frontmatter가 제거된 내용으로
- 스테이징 폴더
openspec/specs/.merged-specs/<inferred-name>/를 제거합니다. - 사용자에게 무엇이 교체/제거되었는지 확인하여 커밋 전에 git diff와 비교하기 쉽게 합니다.
파일에 명시적인 Approved-by-human: yes가 있는 상태가 아니라면 절대 4단계를 수행하지 마십시오.
채팅에서 사용자에게 구두 승인을 요청하는 것을 대체 수단으로 사용하지 마십시오.
승인은 frontmatter 필드 자체가 변경된 것이어야 합니다.
예시
Phase 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
## 요구사항: ...
...
사용자에게 메시지: user-show, user-detail, user-permissions에서 추론된 기능 user로 병합됨
(폴더 이름을 user-management로 변경하려면 이름을 바꾸세요); 충돌 없음;
openspec/specs/.merged-specs/user/spec.md를 검토하고 준비가 되면
Approved-by-human: yes로 설정하세요.
Phase B — 사용자가 Approved-by-human: yes로 설정하고 적용을 요청하면:
openspec/specs/user/spec.md가 frontmatter 없는 병합된 내용으로 생성/덮어쓰여지고,
user-show/, user-detail/, user-permissions/가 제거되며,
openspec/specs/.merged-specs/user/가 삭제됩니다.