실험적 워크플로우에서 완료된 변경사항을 보관합니다.
저장소 선택: 사용자가 저장소(이 머신에 등록된 독립형 OpenSpec 저장소) 이름을 지정하거나 작업이 특정 저장소에 속하는 경우, openspec store list --json을 실행하여 등록된 저장소 ID를 확인한 다음, 스펙 및 변경사항을 읽고 쓰는 명령어(new change, status, instructions, list, show, validate, archive, doctor, context, schemas, view)에 --store <id>를 전달합니다. 일단 선택되면, --store <id>는 워크플로우의 나머지 부분에서 고정된 값으로 처리합니다. 아래에 있는 이 명령어들의 모든 예시는 축약형입니다: 실행 전에 플래그를 추가하세요. 예를 들어, 아래 표시된 축약형 대신 openspec status --change "<name>" --json --store "<id>"를 실행하세요. 다른 명령어는 이 플래그를 사용하지 않습니다. 명령어가 출력하는 힌트에는 이미 플래그가 포함되어 있으므로 후속 작업에서도 계속 사용하세요. 저장소가 없으면 명령어는 가장 가까운 로컬 openspec/ 루트를 대상으로 동작합니다.
프로젝트 확인: 이 단계들은 이미 OpenSpec을 사용하는 프로젝트를 가정합니다. 무언가를 쓰는 첫 번째 단계(new change, archive, sync specs, 또는 아티팩트 파일 작성) 전에 프로젝트에 루트가 있는지 확인합니다: openspec list --json을 실행하고(저장소가 선택된 경우 --store <id>를 사용, 저장소가 루트이므로) root를 읽습니다. 루트 객체가 있으면 프로젝트가 설정된 것입니다. "root": null은 설정되지 않았음을 의미합니다. 여기에 openspec/ 디렉터리가 없으며 openspec new change와 같은 쓰기 명령어가 부수 효과로 디렉터리를 생성할 수 있습니다. 이 명령어는 또한 0이 아닌 종료 코드를 반환하는데, 이는 CLI가 고장난 것이 아니라 해당 상태를 나타내는 것이므로 JSON을 읽고 재시도하거나 우회하지 마세요.
하나의 "root": null은 설정과 관련이 없습니다: status 오류 메시지가 Declared in 또는 Invalid store declaration in으로 시작하고 이 프로젝트의 openspec/config.yaml(또는 config.yml)을 언급하는 경우, 프로젝트는 선언한 저장소를 통해 OpenSpec을 사용하지만 이 머신에서 해당 저장소를 확인할 수 없는 것입니다(저장소가 등록되지 않았거나 store: 줄 형식이 잘못됨). 초기화되지 않은 것으로 처리하지 말고 아래 분기를 건너뛰세요: 쓰기 전에 중단하고 사용자에게 해당 오류의 message와 fix를 보여주세요.
그 외에, 루트가 없는 경우 다음 단계는 이 워크플로우에 어떻게 도달했는지에 따라 달라집니다:
- 자동 선택: 사용자가 OpenSpec을 언급하거나, 이 스킬을 호출하거나, 슬래시 명령어를 실행하지 않고 당신이 스스로 이 워크플로우를 선택한 경우. OpenSpec 사용을 중단하고 OpenSpec이 설치되지 않은 것처럼 요청을 정상적으로 처리하세요. 사용자에게 설정을 요청하지 말고 OpenSpec 설정에 대해 언급하지 마세요.
- 명시적 OpenSpec 요청: 사용자가 OpenSpec을 언급하거나, 이 스킬을 호출하거나, 슬래시 명령어를 실행한 경우. 쓰기 전에 중단하고 어떻게 진행할지 물어보세요: 이 프로젝트를 설정(
openspec init), 이미 있는 저장소를 대상으로 지정(--store <id>), 또는 이 요청에 대해 OpenSpec 없이 계속. 사용자의 답변을 기다리세요.
두 분기 모두에서 루트를 부수 효과로 생성하지 마세요: 사용자가 요청할 때까지 openspec init을 실행하지 말고, openspec/ 파일을 직접 생성하지 말고, 명령어가 루트를 생성하도록 두지 마세요.
<capability-path>는 specs/에 상대적인 스펙 디렉터리입니다(예: user-auth 또는 identity/user-auth). 각 델타 스펙에서 메인 스펙을 확인할 때 전체 경로를 유지하세요.
입력: 선택적으로 변경사항 이름을 지정합니다. 생략된 경우 대화 컨텍스트에서 유추할 수 있는지 확인합니다. 모호하거나 애매하면 사용 가능한 변경사항을 묻는 메시지를 표시해야 합니다.
단계
-
변경사항 선택
이름이 제공되면 사용합니다. 그렇지 않으면:
- 사용자가 변경사항을 언급한 경우 대화 컨텍스트에서 유추
- 활성 변경사항이 하나만 있으면 자동 선택
- 모호한 경우
openspec list --json을 실행하여 사용 가능한 변경사항을 가져오고 사용자에게 선택하도록 요청
프롬프트를 표시할 때는 이미 보관된 변경사항이 아닌 활성 변경사항만 표시합니다. 가능한 경우 각 변경사항에 사용된 스키마를 포함합니다.
항상 알립니다: "변경사항 사용: " 및 재정의 방법(예:
/openspec-archive-change <other>).기존 보관 확인 전에 현재 보관 입력 로드:
선택한 변경사항을 확인하고 루트를 계획한 후 실행:
openspec instructions archive --change "<name>" --json선택한 루트 플래그를 이 명령어에 동일하게 유지합니다. 이 조회는 권고 사항이며 선택 사항입니다: 추가 프롬프트 입력만 제공하므로 보관을 절대 차단해서는 안 됩니다. 0이 아닌 종료 코드를 반환하거나 유효하지 않은 JSON을 반환하는 경우(예: 이 명령어를 지원하지 않는 이전 CLI) 컨텍스트나 작업 지침 없이 보관 워크플로우를 계속 진행합니다. 오류를 보고하지 말고 중단하지 마세요.
성공적인 응답은 두 선택적 필드를 모두 생략할 수 있습니다.
context를 필수 프롬프트 수준 입력으로 처리합니다: 읽고 고려하며 관련 프로젝트 사실, 규칙, 제약 조건을 적용합니다.operationGuidance를 선택적 추가 조언으로 처리합니다: 각 항목을 읽고 고려하며, 적용 가능하고 내장된 보관 워크플로우와 호환되는 항목을 따릅니다.두 필드를 내장 단계, 명시적 사용자 선택, 확인된 경로, CLI 확인, 명령어 계약과 분리하여 유지합니다. context가 이러한 제어 입력 중 하나와 충돌하면 충돌을 보고하고 제어 값을 유지합니다. guidance가 적용 불가능하거나 제어 입력과 충돌하면 따르지 말고 이유를 설명합니다. 두 필드에서 대체 경로, 건너뛴 프롬프트, 플래그를 유추하지 말고, 사용자가 별도로 요청하지 않는 한 해당 텍스트를 스펙, 변경 아티팩트, 보관 요약에 그대로 복사하지 마세요. 이는 프롬프트 수준 동작 계약이며 강제 가능한 확인 사항이 아닙니다.
-
아티팩트 완료 상태 확인
openspec status --change "<name>" --json을 실행하여 아티팩트 완료 상태를 확인합니다.JSON을 분석하여 이해:
schemaName: 사용 중인 워크플로우planningHome,changeRoot,artifactPaths,actionContext: 경로 및 범위 컨텍스트artifacts: 상태(done,skipped, 또는 기타)가 포함된 아티팩트 목록
done또는skipped가 아닌 아티팩트가 있는 경우(건너뛴 아티팩트는 요구 사항을 충족합니다 - 변경사항이 skip_specs를 선언함):- 불완전한 아티팩트를 나열하는 경고 표시
- 사용자에게 계속 진행할지 확인 요청
- 사용자가 확인하면 진행
-
작업 완료 상태 확인
선택한 루트 플래그를 사용하여
openspec list --json을 실행하고changes에서name이 선택한 변경사항과 정확히 일치하는 항목을 찾습니다. 정확히 하나의 일치 항목과 음이 아닌 정수totalTasks및completedTasks(completedTasks <= totalTasks)가 필요합니다. CLI는 스키마의 추적된 작업 파일(사용자 정의 아티팩트 이름, 출력 경로, 글로브 포함)을 확인합니다. 완료되지 않은 작업 =totalTasks - completedTasks.아티팩트 상태나 최상위
tasks.md부재로부터 작업 완료를 유추하지 마세요. 조회 실패, 유효하지 않은 JSON 반환, 선택한 변경사항 누락 또는 중복, 유효하지 않은 개수 반환 시 문제를 보고하고 동기화 또는 보관 전에 중단하세요. CLI는x/X체크박스 마커만 완료로 계산합니다. 다른 마커(익숙하지 않은 마커 포함)는 완료되지 않은 상태로 남습니다.완료되지 않은 작업이 발견된 경우:
- 완료되지 않은 작업 개수를 표시하는 경고 표시
- 사용자에게 계속 진행할지 확인 요청
- 사용자가 확인하면 진행
totalTasks가 0인 경우: 작업 관련 경고 없이 진행합니다. -
델타 스펙 동기화 상태 평가
상태 JSON에서
artifactPaths.specs.existingOutputPaths를 유일한 델타 스펙 소스로 사용합니다.specs항목이 없거나existingOutputPaths가 비어 있으면 동기화 프롬프트 없이 진행하고 다른 아티팩트에서 델타 스펙을 유추하지 마세요.델타 스펙이 있는 경우:
- 각 델타 스펙을 해당 메인 스펙(
<planningHome.root>/openspec/specs/<capability-path>/spec.md위치, 2단계의 저장소 인식planningHome.root사용, 하드코딩된 저장소 경로 사용 안 함)과 비교 - 메인 스펙이 없으면 자동으로 "이미 동기화됨"이 아닙니다. 새 기능의 경우 메인 스펙은 동기화의 출력이지 입력이 아닙니다:
- 델타에 수정 또는 이름 변경 요구 사항이 있는 경우 추가된 요구 사항만 새 메인 스펙을 생성할 수 있다고 보고하고 해당 기능을 동기화 차단으로 표시합니다. 현재 버전이 없는 요구 사항을 절대 발명하지 마세요.
- 그렇지 않고 델타에 제거된 요구 사항만 있고 변경사항의
.openspec.yaml이retire_capabilities: true를 선언하면 해당 기능은 이미 폐기된 것입니다: 이미 동기화된 것으로 계산하고, 제거할 것이 없다고 경고하며, 메인 스펙을 다시 생성하지 마세요. 이 규칙을 지금과 완료된 동기화 확인 시 모두 적용하세요. - 그렇지 않고 델타에 추가된 요구 사항이 없으면 동기화가 불가능하다고 보고하고 해당 기능을 동기화 차단으로 표시합니다. 제거 전용 델타의 경우 제거할 메인 스펙이 없다고 경고하고 메인 스펙 트리를 변경하지 않은 상태로 둡니다.
openspec archive는 표시되지 않은 제거 전용 케이스를Spec must have at least one requirement로 거부합니다. - 그렇지 않으면 해당 기능을 동기화가 필요함으로 계산하고 요약에 이름을 지정합니다(
<capability-path>: 새 메인 스펙이 생성됩니다). 델타에 제거된 요구 사항도 있는 경우 제거할 메인 스펙이 없으므로 무시된다고 경고합니다. 동기화는openspec archive가 하는 것처럼 델타의 추가된 요구 사항에서만 메인 스펙을 생성합니다.
- 적용될 변경 사항(추가, 수정, 제거, 이름 변경) 확인
- 하나가 동기화 차단된 경우에도 나머지 기능 평가를 계속합니다. 프롬프트 전에 결합된 요약을 표시합니다.
프롬프트 옵션:
- 동기화 차단된 기능이 있는 경우: 이유를 설명하고 "동기화 없이 보관", "취소"만 제공
- 그렇지 않고 변경이 필요한 경우: "지금 동기화 (권장)", "동기화 없이 보관"
- 그렇지 않고 이미 동기화된 경우: "지금 보관", "그래도 동기화", "취소"
답변에 따라 라우팅:
- "취소" — 중단, 보관하지 않음
- "동기화 없이 보관" 또는 "지금 보관" — 보관 진행
- "지금 동기화" 또는 "그래도 동기화" — 동기화 후 확인(아래). 기능이 동기화 차단된 상태에서는 동기화를 시작하지 마세요. 차단자를 설명하고 사용 가능한 선택 사항을 반복하세요.
- 그 외의 경우 — 보관하지 말고 다시 물어보세요
선택한 동기화가 메인 스펙을 쓰기 전에, 동일한 선택된 루트 플래그를 사용하여
openspec instructions specs --change "<name>" --json을 한 번 실행합니다. 0 종료 상태와 유효한 아티팩트 명령 JSON이 필요합니다. 조회 실패 또는 유효하지 않은 JSON 반환 시 오류를 보고하고 메인 스펙을 쓰거나 변경사항을 이동하기 전에 중단하세요.rules가 생략된 유효한 응답은 규칙이 없는 경우입니다. 반환된rules를 이 병합에 의해 생성된 메인 스펙의 콘텐츠와 형식에만 적용합니다. 보관 지침, CLI 동작 변경, 규칙 텍스트를 출력 파일에 복사하는 데 사용하지 마세요.그런 다음
openspec-sync-specs워크플로우를 인라인(에이전트 주도 지능형 병합)으로 실행하여 변경사항 ''에 대해 델타 스펙 분석과 위에서 가져온 specs-rule 스냅샷을 전달하고 완료될 때까지 기다립니다. 인라인 동기화는specs지침을 다시 가져오지 않고 해당 스냅샷을 재사용해야 합니다. 백그라운드 작업에 위임하지 마세요. 5단계가 동기화가 여전히 읽고 있는 동안changeRoot를 이동시켜 변경사항이 보관되고 메인 스펙이 업데이트되지 않은 채로 남을 수 있습니다. 에이전트가 위임으로만 실행할 수 있는 경우 동기식으로 위임하고 결과를 기다리세요.동기화가 중지 또는 차단 조건을 보고하면 동기화가 실패한 것으로 처리합니다. 즉시 보관을 중단하세요. 동기화 후 콘텐츠 비교를 수행하지 말고
changeRoot를 이동하지 마세요. 아무것도 이동되지 않았으므로 사용자가 차단 조건을 수정하거나 동기화를 다시 실행할 수 있습니다.동기화가 각 메인 스펙을 쓴 후, 표준 동기화 계약과 구조를 확인하세요:
- 새 메인 스펙은
# <capability> Specification제목으로 시작합니다. 기존 메인 스펙은 제목을 그대로 유지합니다. - 설정된 메인 스펙의 기존
## Purpose섹션을 완전히 그대로 유지합니다. - 새 메인 스펙의 경우 델타의
## Purpose를 있는 그대로 복사합니다. 목적 텍스트가 표준 유효성 검사에서 예상하는 것보다 짧은 경우에만 경고합니다. 기존 작성된 목적을 다시 생성하거나 다시 쓰지 마세요. 사용 가능한## Purpose가 없으면 기존 TBD 목적 동작 및 경고를 사용합니다. - 델타 스타일 섹션 헤더(
## ADDED Requirements,## MODIFIED Requirements,## REMOVED Requirements,## RENAMED Requirements)가 메인 스펙에 남아 있지 않은지 확인하며, 동기화 워크플로우 형식 규칙을 엄격히 준수합니다. - 동기화가 작성하거나 변경한 요구 사항 블록은
### Requirement:제목을 사용하고, 해당 시나리오는## Requirements섹션 아래의#### Scenario:제목을 사용합니다. 델타가 언급하지 않은 콘텐츠는 그대로 둡니다.
그런 다음 이 단계의 시작 부분에서 비교를 다시 실행하여, 명시적으로 폐기된 누락 스펙 사례를 포함하여
artifactPaths.specs.existingOutputPaths에 델타 스펙이 있는 모든 기능에 대해 — 동기화가 건드렸다고 보고한 기능뿐만 아니라. 성공적인 동기화는 적용할 것이 남지 않도록 하므로 각 기능은 이제 이미 동기화된 것으로 읽혀야 합니다:- 추가된 요구 사항 존재
- 수정된 요구 사항이 델타에 명명된 시나리오 및 설명 변경 사항을 포함하고 다른 시나리오는 그대로 유지
- 제거된 요구 사항 사라짐 — 동기화가 기능을 폐기한 경우(마지막 요구 사항 제거,
## Requirements를 비움) 메인 스펙이 빈 상태로 남지 않고 삭제됨. - 이름 변경된 요구 사항이 새 이름으로 존재하고 이전 이름으로 없음
동기화가 실패했거나 기능이 일치하지 않는 경우 차이점을 보고하고 중단하세요 — 보관하지 마세요. 아무것도 이동되지 않았고
changeRoot가 그대로이므로 사용자가 불일치를 수정하거나 동기화를 다시 실행하고 보관을 다시 시작할 수 있습니다. - 각 델타 스펙을 해당 메인 스펙(
-
보관 수행
planningHome.changesDir아래에archive디렉터리가 없으면 생성:mkdir -p "<planningHome.changesDir>/archive"대상 이름 생성: 변경사항 이름이 이미
YYYY-MM-DD-접두사로 시작하면 그대로 사용합니다. 그렇지 않으면 현재 날짜를 앞에 추가합니다....
}