spec-driven
기본 워크플로우의 산출물: 순서, 형식, 그리고 생성되는 change 폴더.
spec-driven는 OpenSpec의 내장 기본 스키마입니다. schema.yaml에서 설정하는 필드를 정의합니다.
산출물
이 워크플로우는 네 가지 산출물을 작성합니다:
| 산출물 | 파일 | 목적 |
|---|---|---|
proposal | proposal.md | 변경이 필요한 이유 |
specs | specs/<capability-path>/spec.md, 기능당 하나 | 변경되는 동작 |
design | design.md | 구축 방법 |
tasks | tasks.md | 구현 체크리스트 |
작성 순서
┌─ specs ──┐
proposal ────┤ ├── tasks ── apply
└─ design ─┘제안서가 먼저 옵니다. 스펙과 설계는 순서에 관계없이 따르며, 작업은 둘 다 필요합니다. 구현(apply)은 tasks.md가 준비된 후 시작됩니다.
두 가지 산출물은 건너뛸 수 있습니다:
design: 해당 조건이 하나도 적용되지 않으면 에이전트는 이를 생략하고tasks를 작성합니다.specs: 변경의.openspec.yaml에skip_specs: true를 설정합니다.
예시 변경 폴더
add-user-auth라는 이름의 변경으로, 모든 산출물이 작성된 경우:
openspec/changes/add-user-auth/
├── .openspec.yaml change metadata, written when the change is created
├── proposal.md
├── specs/
│ └── user-auth/
│ └── spec.md one delta spec per capability
├── design.md
└── tasks.mdproposal.md
변경이 왜 필요한지 설명합니다.
구조
에이전트가 출력 형식으로 받는 템플릿 (templates/proposal.md):
# Proposal
## Why
<!-- 이 변경의 동기를 설명하세요. 어떤 문제를 해결하나요? 왜 지금인가요? -->
## What Changes
<!-- 무엇이 변경될지 설명하세요. 새로운 기능, 수정, 제거에 대해 구체적으로 설명하세요. -->
## Capabilities
### New Capabilities
<!-- 도입되는 기능(capabilities)입니다. 시스템이 진화함에 따라 관련 요구 사항을 소유할 수 있는 응집력 있는 시스템 동작을 위해 각 기능에 이름을 지정하세요. 구현 작업이나 제안서 섹션의 이름을 사용하지 마세요. 광범위한 포괄적인 이름은 피하세요. 프로젝트의 기존 스펙 구성을 따르는 경로 세그먼트에는 kebab-case를 사용하세요 (예: user-auth 또는 identity/user-auth). 각각은 specs/<capability-path>/spec.md를 생성합니다. -->
- `<capability-path>`: <brief description of what this capability covers>
### Modified Capabilities
<!-- 요구 사항(REQUIREMENTS)이 변경되는 기존 기능입니다 (구현만 변경되는 경우 제외).
스펙 수준의 동작 변경이 있을 때만 여기에 나열하세요. 각각 델타 스펙 파일이 필요합니다.
openspec/specs/ 아래의 정확한 기존 경로를 사용하세요. 요구 사항 변경이 없으면 비워 두세요.
기능이 전혀 없는 변경 (순수 리팩토링, 도구, 문서)은 .openspec.yaml에 `skip_specs: true`를 설정해야 합니다 - openspec validate는 해당 마커 없이 델타가 0인 변경을 거부합니다. 검증을 통과하기 위해 요구 사항을 지어내지 마세요. -->
- `<existing-capability-path>`: <what requirement is changing>
## Impact
<!-- 영향을 받는 코드, API, 의존성, 시스템 -->지침
에이전트가 이 산출물을 작성할 때 전송되는 지침 (schema.yaml):
이 변경이 왜 필요한지 설명하는 제안서 문서를 작성하세요.
섹션:
- **Why**: 문제나 기회에 대한 1-2문장. 어떤 문제를 해결하나요? 왜 지금인가요?
- **What Changes**: 변경 사항의 글머리 기호 목록. 새로운 기능, 수정, 제거에 대해 구체적으로 설명하세요. 주요 변경 사항은 **BREAKING**으로 표시하세요.
- **Capabilities**: 생성되거나 수정될 스펙을 식별하세요:
- **New Capabilities**: 도입되는 기능을 나열하세요. 각각은 새로운 `specs/<capability-path>/spec.md`가 됩니다. 각 기능에 지속적인 시스템 동작 이름을 지정하세요 (예: `user-auth`), 이 변경의 작업 이름이 아니라 (예: `add-login-endpoint`). 시스템이 진화함에 따라 관련 요구 사항을 소유할 수 있는 응집력 있는 경계를 선택하세요; 광범위한 포괄적인 기능은 피하세요. 도입하는 경로 세그먼트에는 kebab-case를 사용하고 (예: `user-auth` 또는 `identity/user-auth`) 프로젝트의 기존 스펙 구성을 따르세요.
- **Modified Capabilities**: 요구 사항(REQUIREMENTS)이 변경되는 기존 기능을 나열하세요. 스펙 수준의 동작 변경이 있을 때만 포함하세요 (구현 세부 사항만 변경되는 경우 제외). 각각 델타 스펙 파일이 필요합니다. `openspec/specs/` 아래의 정확한 기존 경로를 사용하세요. 요구 사항 변경이 없으면 비워 두세요.
- **Impact**: 영향을 받는 코드, API, 의존성 또는 시스템.
중요: Capabilities 섹션은 중요합니다. 제안서와 스펙 단계 간의 계약을 만듭니다. 작성하기 전에 기존 스펙을 조사하세요: 프로젝트의 기능 인벤토리를 위해 `openspec list --specs`를 실행한 다음, 관련 있어 보이는 항목에 대해 `openspec show "<spec-id>" --type spec --json --no-scenarios`를 실행하세요 - 이는 전체 스펙 파일을 컨텍스트로 가져오지 않고 기능의 목적과 요구 사항 텍스트를 반환합니다. 등록된 독립 스토어에 대해서만 두 명령에 `--store "<id>"`를 추가하고, `--type spec`을 유지하세요: 그렇지 않으면 변경과 스펙이 이름을 공유할 때 모호한 항목 오류가 발생합니다. `--specs` 없이 `openspec list`를 실행하면 진행 중인 변경 사항을 나열하며, 스펙이 아닙니다 - 프로젝트가 이미 다루는 내용을 표시하지 않습니다. 거의 중복된 이름을 도입하는 대신 기존 기능의 정확한 경로를 재사용하세요. 필터링된 읽기는 개요일 뿐입니다. 이미 다루어졌거나 변경되어야 할 내용을 결정하기 전에, 시나리오를 포함하여 각 관련 스펙을 전체적으로 읽으세요: `openspec show "<spec-id>" --type spec` (동일한 `--store` 규칙). 여기에 나열된 각 기능은 해당 스펙 파일이 필요합니다.
모든 변경은 최소한 하나의 기능(신규 또는 수정)을 선언하거나 명시적으로 스펙을 제외해야 합니다: `openspec validate`는 변경의 `.openspec.yaml`에 `skip_specs: true`가 설정되지 않은 한 델타가 0인 변경을 거부합니다. `skip_specs: true`는 스펙 수준의 동작 변경이 없을 때만 사용하세요 (순수 리팩토링, 도구, 문서) - 스펙은 동작을 설명하므로, 동작이 변경되지 않으면 스펙도 변경되어서는 안 됩니다. 검증을 통과하기 위해 요구 사항을 지어내지 마세요.
간결하게 유지하세요 (1-2페이지). "어떻게"가 아니라 "왜"에 집중하세요 - 구현 세부 사항은 design.md에 속합니다.
이것이 기초입니다 - 스펙, 설계, 작업 모두 이를 기반으로 합니다.델타 스펙 (spec.md)
동작 변경을 정의하며, 제안서에 나열된 각 기능에 대해 하나의 델타 스펙이 있습니다.
각 델타 스펙은 해당 기능 폴더 안의 spec.md입니다. openspec validate와 openspec archive는 specs/ 아래의 다른 파일에 작성된 델타 섹션(예: specs/user-auth.md)을 거부합니다. 아카이브가 이를 병합하지 않기 때문입니다.
구조
에이전트가 출력 형식으로 받는 템플릿 (templates/spec.md):
# Spec Delta
## Purpose
<!-- 새 기능 전용: 이 기능이 무엇을 위한 것인지 1-2문장 (50자 이상)으로 설명하세요. 기존 기능에는 이 섹션을 삭제하세요. -->
## ADDED Requirements
### Requirement: <!-- 요구 사항 이름 -->
<!-- 요구 사항 텍스트 -->
#### Scenario: <!-- 시나리오 이름 -->
- **WHEN** <!-- 조건 -->
- **THEN** <!-- 예상 결과 -->지침
에이전트가 이 산출물을 작성할 때 전송되는 지침 (schema.yaml):
시스템이 무엇을 해야 하는지 정의하는 사양 파일을 작성하세요.
스펙은 동작 계약이지 구현 계획이 아닙니다.
좋은 스펙 내용:
- 사용자나 다운스트림 시스템이 의존하는 관찰 가능한 동작
- 입력, 출력, 오류 조건
- 외부 제약 (보안, 개인정보, 신뢰성, 호환성)
- 테스트하거나 명시적으로 검증할 수 있는 시나리오
스펙에서 피할 것:
- 내부 클래스/함수 이름
- 라이브러리 또는 프레임워크 선택
- 단계별 구현 세부 사항
- 상세 실행 계획 (이러한 것은 design.md 또는 tasks.md에 속함)
빠른 테스트: 구현이 외부에서 보이는 동작을 변경하지 않고 변경될 수 있다면, 아마도 스펙에 속하지 않습니다.
제안서의 Capabilities 섹션에 나열된 각 기능에 대해 하나의 스펙 파일을 작성하세요.
`<capability-path>`는 `specs/`에 대한 상대 경로의 스펙 디렉터리입니다 (예: `user-auth` 또는 `identity/user-auth`). 전체 경로를 유지하세요:
- 새 기능: 제안서의 정확한 경로를 `specs/<capability-path>/spec.md`에 사용하세요. 제안서에서 새로 도입된 경로 세그먼트는 kebab-case여야 합니다. 프로젝트의 기존 구성을 따르세요; 프로젝트가 평면 레이아웃을 사용할 때 새 도메인 수준을 추가하지 마세요.
- 수정된 기능: `specs/<capability-path>/spec.md`에 델타를 만들 때 `openspec/specs/<capability-path>/`의 정확한 기존 경로를 사용하세요. 델타를 작성하기 전에 `openspec list --specs`를 실행하여 해당 경로를 확인하고, 등록된 독립 스토어에 대해서만 `--store "<id>"`를 추가하세요 - 오타나 잘못된 경로는 의도한 기능이 아닌 존재하지 않는 기능을 대상으로 합니다. 기능을 이동하거나 이름을 바꾸지 마세요.
스펙 파일을 한 번에 하나씩 작성하여 사용자가 진행 상황을 볼 수 있고, 중단된 실행이 이미 작성한 파일을 유지하도록 하세요:
- 아무것도 작성하기 전에, 제안서에 나열된 기능과 이미 존재하는 `specs/<capability-path>/spec.md` 파일을 비교하고, 파일이 없는 첫 번째 기능부터 시작하세요. 사용자가 요청하지 않는 한 기존 파일을 다시 작성하지 마세요.
- 각 파일 전에, 어떤 기능을 작성 중인지 한 줄로 말하세요.
- 각 파일을 초안을 작성하는 즉시 작성하세요. 첫 번째 파일을 작성하기 전에 모든 파일을 계획하지 마세요.
- 제안서에 나열된 모든 기능에 파일이 생기면 중단하세요.
변경의 `.openspec.yaml`에 `skip_specs: true`가 설정되지 않은 한 최소한 하나의 스펙 파일이 있어야 합니다 (스펙 수준의 동작 변경 없음) - `openspec validate`는 해당 마커 없이 델타가 0인 변경을 거부합니다. 제안서에 기능이 나열되지 않고 `skip_specs`가 설정되지 않은 경우, 먼저 제안서를 다시 검토하세요.
델타 작업 (## 헤더 사용):
- **ADDED Requirements**: 새 기능
- **MODIFIED Requirements**: 변경된 동작 - 전체 업데이트된 내용을 포함해야 함
- **REMOVED Requirements**: 더 이상 사용되지 않는 기능 - **Reason**과 **Migration**을 포함해야 함
- **RENAMED Requirements**: 이름 변경만 - FROM:/TO: 형식 사용
형식 요구 사항:
- 각 요구 사항: `### Requirement: <name>` 뒤에 설명
- 규범적 요구 사항에는 SHALL/MUST를 사용하세요 (should/may는 피하세요)
- 각 시나리오: `#### Scenario: <name>` WHEN/THEN 형식
- **CRITICAL**: 시나리오는 정확히 4개의 해시태그(`####`)를 사용해야 합니다. 3개의 해시태그나 글머리 기호를 사용하면 조용히 실패합니다.
- 모든 요구 사항은 최소한 하나의 시나리오를 가져야 합니다.
- 모든 시나리오는 WHEN/GIVEN 단계(트리거)와 THEN 단계(결과)를 가져야 합니다. AND 줄만 있거나 일반 산문만 있는 시나리오도 여전히 시나리오로 간주되지만, `openspec validate`는 이를 경고로 표시합니다: 일반 검증은 여전히 통과하지만, `openspec validate --strict`는 실패합니다.
- 각 요구 사항의 설명(`### Requirement:`와 첫 번째 시나리오 사이의 텍스트)을 500자 이하로 유지하세요. `openspec validate`는 ADDED 요구 사항과 기본 스펙에서 더 긴 설명을 표시합니다. 이는 경고입니다: 일반 검증은 여전히 통과하지만, `openspec validate --strict`는 실패합니다. 새 요구 사항을 작성할 때, 요구 사항당 하나의 동작을 명시하세요: 예제와 경계 사례를 시나리오로 옮기고, 여러 동작을 다루는 요구 사항을 각각 자체 시나리오가 있는 별도의 `### Requirement:` 블록으로 분할하세요. MODIFIED에서는 기존 요구 사항 블록을 전체로 유지하세요; 길이를 맞추기 위해 기존 텍스트를 분할, 축소 또는 다시 작성하지 마세요. 사용자가 요청할 때만, 그 목적을 위해 만들어진 변경에서 기존의 긴 요구 사항을 분할하세요: MODIFIED에서 헤더와 모든 시나리오를 유지하고 설명을 의미를 바꾸지 않고 하나의 동작으로 줄인 다음, 제거한 각 동작을 자체 시나리오가 있는 별도의 ADDED 요구 사항으로 추가하세요.
새 기능 전용: 델타 스펙의 첫 번째 섹션은 `## Purpose`입니다 - 기능이 무엇을 위한 것인지 설명하는 1-2문장 (50자 이상, 또는 `openspec validate --strict`가 너무 짧다고 보고함). 아카이브는 이를 생성하는 기본 스펙에 복사합니다; 그것 없이는 새 기본 스펙에 수동으로 채울 `TBD ... Update Purpose after archive` 플레이스홀더가 남습니다. 기존 기능에 대한 델타에 `## Purpose`를 추가하지 마세요 - 해당 스펙에는 이미 하나가 있고 델타의 것은 무시됩니다. 기존 기능의 Purpose를 변경하려면 - 남은 `TBD` 플레이스홀더를 포함하여 - `<planningHome.root>/openspec/specs/<capability-path>/spec.md`를 직접 편집하세요. `planningHome.root`는 `openspec instructions ... --json` 응답에서 나옵니다. 저장소 상대 경로보다 항상 사용하세요: 변경이 스토어에 있을 때마다 스토어로 해석됩니다 - `--store`, 프로젝트 `store:` 포인터, 또는 전역 기본 스토어에서 온 것인지 여부와 관계없이 - 그 외에는 현재 저장소로 해석됩니다. 어떤 경우가 적용되는지 알아내려고 하지 마세요; 필드가 이미 가지고 있습니다.
MODIFIED 요구 사항 워크플로우:
1. 위와 동일한 스토어 인식 루트인 `<planningHome.root>/openspec/specs/<capability-path>/spec.md`에서 기존 요구 사항을 찾으세요.
2. 전체 요구 사항 블록을 복사하세요 (`### Requirement:`부터 모든 시나리오까지).
3. `## MODIFIED Requirements` 아래에 붙여넣고 새 동작을 반영하도록 편집하세요.
4. 헤더 텍스트가 정확히 일치하는지 확인하세요 (공백은 무시).
일반적인 함정: 부분 내용으로 MODIFIED를 사용하면 아카이브 시 세부 사항이 손실됩니다. 기존 동작을 변경하지 않고 새로운 관심사를 추가하는 경우 ADDED를 대신 사용하세요.
예시 (새 기능이므로 첫 번째 섹션은 `## Purpose`):Spec Delta
## 목적
사용자가 자신의 데이터를 휴대 가능한 형식으로 제품 외부로 가져갈 수 있게 합니다.
## 추가된 요구사항
### 요구사항: 사용자가 데이터를 내보낼 수 있음
시스템은 사용자가 자신의 데이터를 CSV 형식으로 내보낼 수 있도록 허용해야 합니다.
#### 시나리오: 성공적인 내보내기
- **WHEN** 사용자가 "Export" 버튼을 클릭하면
- **THEN** 시스템이 모든 사용자 데이터가 포함된 CSV 파일을 다운로드합니다
## 제거된 요구사항
### 요구사항: 레거시 내보내기
**이유**: 새 내보내기 시스템으로 대체됨
**마이그레이션**: /api/v2/export의 새 내보내기 엔드포인트를 사용하세요.명세는 테스트 가능해야 하며, 각 시나리오는 잠재적인 테스트 사례입니다.
## design.md
변경 사항을 구현하는 방법을 설명합니다. 변경에 설계가 필요할 때만 작성합니다.
### 구조
에이전트가 출력 형식으로 받는 템플릿([templates/design.md](https://github.com/Fission-AI/OpenSpec/blob/main/schemas/spec-driven/templates/design.md)):
```md
# Design
## Context
<!-- Current state and constraints that shape the approach. See proposal.md for motivation - don't restate it -->
## Goals / Non-Goals
**Goals:**
<!-- What this design aims to achieve -->
**Non-Goals:**
<!-- What is explicitly out of scope -->
## Decisions
<!-- Key design decisions with rationale and alternatives considered -->
## Risks / Trade-offs
<!-- Known risks and trade-offs -->
```
### 지침
에이전트가 이 산출물을 작성할 때 받는 지침([schema.yaml](https://github.com/Fission-AI/OpenSpec/blob/main/schemas/spec-driven/schema.yaml)):
```md
Create the design document that explains HOW to implement the change.
When to include design.md (create only if any apply):
- Cross-cutting change (multiple services/modules) or new architectural pattern
- New external dependency or significant data model changes
- Security, performance, or migration complexity
- Ambiguity that benefits from technical decisions before coding
Sections:
- **Context**: Only the current state and constraints needed to explain the approach. Reference the proposal for motivation instead of restating it (e.g., "See proposal.md - Why").
- **Goals / Non-Goals**: What this design achieves and explicitly excludes. Don't restate the proposal's scope - add only design-level boundaries.
- **Decisions**: Key technical choices with rationale (why X over Y?). Include alternatives considered for each decision.
- **Risks / Trade-offs**: Known limitations, things that could go wrong. Format: [Risk] → Mitigation
- **Migration Plan**: Steps to deploy, rollback strategy (if applicable)
- **Open Questions**: Unknowns that can safely be answered later without
changing the specs, the approach, or the task breakdown. Omit if none.
Open questions are for genuinely deferrable unknowns, not decisions you
skipped. If a question would change the specs, the chosen approach, or
the task breakdown, resolve it now - ask the user instead of guessing.
Focus on architecture and approach, not line-by-line implementation.
The proposal covers why and what; design covers how. Reference the
proposal for motivation and, once written, the specs for requirements -
if a section would only restate them, point to them instead.
Good design docs explain the "why" behind technical decisions.
```
## tasks.md
구현을 체크 가능한 작업으로 나눕니다. [apply](#apply)가 여기에서 진행 상황을 추적합니다.
### 구조
에이전트가 출력 형식으로 받는 템플릿([templates/tasks.md](https://github.com/Fission-AI/OpenSpec/blob/main/schemas/spec-driven/templates/tasks.md)):
```md
# Tasks
## 1. <!-- Task Group Name -->
- [ ] 1.1 <!-- Task description -->
- [ ] 1.2 <!-- Task description -->
## 2. <!-- Task Group Name -->
- [ ] 2.1 <!-- Task description -->
- [ ] 2.2 <!-- Task description -->
```
### 지침
에이전트가 이 산출물을 작성할 때 받는 지침([schema.yaml](https://github.com/Fission-AI/OpenSpec/blob/main/schemas/spec-driven/schema.yaml)):
````md
Create the task list that breaks down the implementation work.
Before writing tasks, check design.md for Open Questions. If any of them
would change what gets built, resolve them with the user first - do not
bake an unstated assumption into the task list.
**IMPORTANT: Follow the template below for tracked tasks.** The apply phase parses
checkbox format to track progress. A box holding only `x` counts as done,
upper or lower case and with any spacing, so `- [ x]` is done too. Every
other marker, including `- [~]`, `- [-]` and an empty `- []`, reads as
unfinished. A line with no checkbox is not tracked at all.
Guidelines:
- Group related tracked tasks under ## numbered headings
- Each tracked task MUST be a checkbox: `- [ ] X.Y Task description`
- Tasks should be small enough to complete in one session
- Order tasks by dependency (what must be done first?)
- Track implementation and verification work that can be completed before
archive. If the requested workflow includes archive or work that requires
this change to be archived, preserve those steps as plain bullets in an
optional `## Workflow follow-up` section at the end of tasks.md. These
bullets are reference information outside tracked task progress.
- Each task MUST state how to verify completion (a test, command,
observable behavior, or delivered artifact). Put the verification in
that task's checkbox description. Use a separate verification task only
when it checks broader integration or system behavior that spans
multiple implementation tasks.
- Each task group MUST land the tests and documentation its own work
calls for. Do NOT collect testing or documentation into a final group -
when a late group first exercises work from an early one, the failures
cascade back through every group in between and force rework. A group
whose work calls for neither, such as scaffolding or dependency setup,
carries neither. A final group is for integration checks only, not for
the tests and docs an earlier group owed.
Example:
```
# Tasks
## 1. Setup
- [ ] 1.1 Create new module structure and verify expected files are present
- [ ] 1.2 Add dependencies to package.json and verify package installation succeeds
## 2. Core Implementation
- [ ] 2.1 Implement data export function and verify the export test passes
- [ ] 2.2 Add CSV formatting utilities and verify unit tests cover quoting and delimiters
- [ ] 2.3 Document the export API in docs/export.md and verify the documented command runs as written
```
When applicable, append workflow follow-up as plain bullets, for example:
```
## Workflow follow-up
- Archive the change after the project's review requirements are satisfied.
- Verify the archived result.
```
Reference specs for what needs to be built, design for how to build it.Apply
계획에서 구현으로 넘어가는 인계 단계입니다. Apply는 tasks.md를 진행하는 단계이며, 산출물이 아닙니다.
- 시작:
tasks.md가 존재하고 하나 이상의 작업을 나열하면 시작됩니다. - 추적:
tasks.md의 체크박스입니다. 체크하는 것이 진행 기록입니다. - 종료: 모든 체크박스가 체크된 상태입니다. 그러면 OpenSpec이 변경 사항을 아카이브할 것을 제안합니다.
설정
apply 설정(schema.yaml):
apply:
requires: [tasks]
tracks: tasks.md
# instruction: shown below지침
구현이 시작될 때 에이전트가 받는 지침(schema.yaml):
Read context files, work through pending tasks, mark complete as you go.
Pause if you hit blockers or need clarification.schema.yaml
지침 본문을 생략한 전체 schema.yaml입니다. 각 지침은 위의 해당 섹션에 전체 내용이 나와 있습니다.
name: spec-driven
version: 1
description: Default OpenSpec workflow - proposal → specs → design → tasks
artifacts:
- id: proposal
generates: proposal.md
description: Initial proposal document outlining the change
template: proposal.md
# instruction: shown in full under proposal.md above
requires: []
- id: specs
generates: "specs/**/*.md"
description: Detailed specifications for the change
template: spec.md
# instruction: shown in full under Delta specs above
requires:
- proposal
- id: design
generates: design.md
description: Technical design document with implementation details
template: design.md
# instruction: shown in full under design.md above
requires:
- proposal
- id: tasks
generates: tasks.md
description: Implementation checklist with trackable tasks
template: tasks.md
# instruction: shown in full under tasks.md above
requires:
- specs
- design
apply:
requires: [tasks]
tracks: tasks.md
# instruction: shown in full under Apply above