將變更中的 Delta 規格同步至主要規格。
這是一個代理驅動的操作——你將讀取 Delta 規格並直接編輯主要規格來套用變更。這樣可以實現智慧合併(例如,在不複製整個需求的情況下新增場景)。
商店選擇: 如果使用者指定了一個商店(商店是在此機器上註冊的獨立 OpenSpec 倉庫),或者工作是在某個商店內進行的,請執行 openspec store list --json 以探索已註冊的商店 ID,然後在讀取或寫入規格與變更的指令中傳入 --store <id>(例如 new change、status、instructions、list、show、validate、archive、doctor、context、schemas、view)。一旦選定,將 --store <id> 視為後續工作流程的黏性參數。以下未限定範圍的指令範例全是簡寫:在執行前,請加上該旗標。例如,執行 openspec status --change "<name>" --json --store "<id>",而非下方未限定範圍的形式。其他指令不接收該旗標。指令輸出的提示訊息已自帶該旗標;後續操作請保留它。若無商店,指令則作用於最近的本地 openspec/ 根目錄。
專案檢查: 這些步驟預期一個已經使用 OpenSpec 的專案。在執行第一個寫入動作(new change、archive、sync specs 或撰寫產出檔案)之前,請確認專案有根目錄:執行 openspec list --json(若已選取商店,則加上 --store <id>,因為此時商店即為根目錄),並讀取 root。若 root 是物件,表示專案已設定。若 "root": null 表示尚未設定——此處沒有 openspec/ 目錄,而像 openspec new change 這樣的寫入動作會副作用地建立一個。該指令的結束碼也非零,這並非 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)。解析其對應的主要規格時,請保留每個 Delta 規格的完整路徑。
輸入:可選擇性地指定變更名稱。若省略,請檢查是否能從對話上下文推斷。若模糊不清,你必須提示可用的變更。
步驟
-
選取變更
若提供了名稱,則使用它。否則:
- 若使用者在對話中提到了某個變更,則從上下文推斷
- 若只有一個活躍的變更,則自動選取
- 若不明確,則執行
openspec list --json以取得可用的變更,並請使用者選取一個
提示時,請顯示那些含有 Delta 規格(位於
specs/目錄下)的變更。一律宣告:「正在使用變更:」以及如何覆蓋(例如
/opsx:sync <other>)。 -
解析變更上下文
執行:
openspec status --change "<name>" --jsonJSON 中包含
planningHome.root。主要規格位於<planningHome.root>/openspec/specs/之下——請使用該(具商店感知能力的)根目錄作為以下所有主要規格路徑的基準,而非硬編碼的倉庫路徑。當選取了商店時,它指向的是商店,而非當前儲存庫。 -
尋找 Delta 規格
使用
statusJSON 中的artifactPaths.specs.existingOutputPaths作為 Delta 規格路徑的唯一來源。如果specs項目缺失或existingOutputPaths為空,請回報沒有要同步的 Delta 規格,不要從其他產出推斷它們,並停止,而不要請求產出指令或寫入主要規格。同步
existingOutputPaths中的每個路徑,除非呼叫者縮小了範圍。 呼叫者可以透過提供一個明確的、來自existingOutputPaths的完整項目列表來縮小範圍——請逐字複製那些絕對路徑值。歸檔動作會內聯執行此操作,使用者也可以(例如,選取以/specs/billing/invoices/spec.md結尾的項目)。 然後僅同步那些指定的路徑,並保留其餘 Delta 規格不變:大量歸檔會排除那些找不到實現的 Delta,而無論如何同步它會寫入呼叫者刻意保留的主要規格。 將該縮小後的選取範圍延續到步驟 4;永遠不要將其擴展回完整列表。如果指定路徑不在existingOutputPaths中,請勿同步它——請回報並停止,而不是靜默地忽略它。如果指定列表為空,請回報沒有要同步的內容並停止,而不要寫入主要規格。每個 Delta 規格檔案包含如下章節:
## ADDED Requirements- 要新增的需求## MODIFIED Requirements- 對現有需求的變更## REMOVED Requirements- 要移除的需求## RENAMED Requirements- 要重新命名的需求(FROM:/TO: 格式)
若未找到 Delta 規格,請通知使用者並停止。
-
針對每個 Delta 規格,將變更套用到主要規格
在第一次寫入主要規格之前,取得一份當前的規格規則快照:
- 若歸檔動作內聯呼叫了此工作流程,並提供了來自
openspec instructions specs --change "<name>" --json的有效快照,則重複使用它,不要再擷取相同的指令。 - 否則,現在使用相同已選取根目錄的旗標執行該指令一次。
- 若直接查詢以非零結束碼退出或回傳無效的產出指令 JSON,請回報錯誤並在寫入任何主要規格之前停止。請勿將此失敗視為規則集不存在。
- 一個含省略
rules的有效回應表示未設定產出規則,且現有的語意合併持續進行。
僅將回傳的
rules套用至此合併所產生的主要規格的內容與形式。產出規則不是操作指引,無法變更選取的根目錄、Delta 路徑、CLI 檢查或工作流程步驟。將其文字視為約束條件,而不要逐字複製到主要規格或摘要中。針對在步驟 3 中選取的每個能力 Delta 規格路徑——完整的
existingOutputPaths列表,或當呼叫者提供時縮小後的子集(這些可能屬於一個已選取的商店,而非儲存庫):a. 讀取 Delta 規格 以了解預期的變更
b. 讀取位於
<planningHome.root>/openspec/specs/<capability-path>/spec.md的主要規格(可能尚不存在)若尚不存在(一個新的能力),比照
openspec archive的做法: 只能套用 ADDED 需求——步驟 d 會從它們建立規格。 MODIFIED 和 RENAMED 沒有要操作的需求,因此停止針對該能力的同步,並回報其主規格不存在,且僅允許 ADDED 用於新規格;永遠不要憑空編造缺失的需求。REMOVED 沒有要移除的內容——跳過它並發出警告。c. 智慧地套用變更:
ADDED Requirements:
- 若主要規格中不存在該需求 → 新增它
- 若需求已存在 → 更新它以符合(視為隱含的 MODIFIED)
MODIFIED Requirements:
- 在主要規格中找到該需求
- 套用變更——這可以是:
- 新增主要規格尚未擁有的場景
- 修改現有場景
- 變更需求描述
- 保留 Delta 中未提及的場景/內容
REMOVED Requirements:
- 從主要規格中移除整個需求區塊
- 將能力歸檔。僅在全部下列條件成立時,才刪除整個
spec.md——以及一旦目錄中沒有其他內容時也刪除目錄:- 此次執行的移除動作後沒有留下任何需求區塊;
- 規格的其餘部分格式良好(它仍然有
## Purpose); - 在此次同步之前主要規格並非為空——若你未移除任何內容,則不做任何變更;
- 整個檔案中的其他非空行都可歸因於標題、Purpose、Requirements 標題,或一個標準需求的陳述、場景或圍欄範例;
- 變更的
.openspec.yaml宣告了retire_capabilities: true; spec.md解析在真實的規格根目錄內(請勿遵循能力目錄的符號連結來刪除外部檔案)。 若移除選取的需求後沒有留下任何需求區塊,且任何歸檔條件不滿足,請勿修改主要規格。針對該能力停止同步,回報阻擋條件,並告知使用者如何解決。永遠不要寫入或留下一個空的## Requirements章節。當僅缺少標記時,也請說明——這是使用者可以新增以使歸檔通過的唯一條件。
- 刪除檔案也會刪除其
## Purpose;任何其他章節都會阻擋歸檔。當你回報歸檔時,請指出 Purpose。僅當規格位於呼叫者的檢出目錄中時,才提供可貼上的git checkout;否則,提供限於檢出範圍的復原指引。
RENAMED Requirements:
- 找到 FROM 需求,重新命名為 TO
Delta 中的
## Purpose:- 主要規格已經有一個,且它是權威來源——請保留它(這就是
openspec archive的做法;它會發出警告並繼續)
d. 若能力尚不存在,則建立新的主要規格:
- 僅當 Delta 有要放入的 ADDED 需求,且在步驟 b 中 MODIFIED 或 RENAMED 需求沒有阻擋此能力時。否則,不建立任何內容,保持規格目錄不變。對於僅有 REMOVED 的 Delta,若變更的
.openspec.yaml宣告了retire_capabilities: true,則回報它已歸檔並繼續,而不重新建立規格。若無此標記,則回報同步被阻擋:openspec archive會以「Spec must have at least one requirement」拒絕它。空的 Delta 沒有要同步的操作;也將其回報為受阻。 永遠不要寫入一個空的## Requirements章節。 - 建立
<planningHome.root>/openspec/specs/<capability-path>/spec.md - 新增 Purpose 章節:當 Delta 有
## Purpose時,逐字複製其主體(這就是openspec archive的做法);僅在它沒有的時候寫入一個簡短的 TBD 佔位 - 新增含 ADDED 需求的 Requirements 章節
- 遵循下方的主要規格格式參考
- 若歸檔動作內聯呼叫了此工作流程,並提供了來自
-
驗證已更新的主要規格
使用與之前相同的已選取根目錄旗標執行
openspec validate --specs。 若驗證失敗,請回報問題,且不要宣稱同步成功。 -
顯示摘要
套用所有變更後,摘要說明:
- 哪些能力已更新
- 做了哪些變更(需求新增/修改/移除/重新命名)
- 任何新建立的主要規格若留有 TBD Purpose 佔位,則應在此時填寫,而非懸而未決
- 任何歸檔的能力,指出已刪除的
spec.md、其 Purpose,以及一個可貼上的git checkout或限於檢出範圍的復原指引
Delta 規格格式參考
# Spec Delta
## Purpose
僅在引入全新能力的 Delta 中使用。為新的主要規格播種。
## ADDED Requirements
### Requirement: New Feature
The system SHALL do something new.
#### Scenario: Basic case
- **WHEN** user does X
- **THEN** system does Y
## MODIFIED Requirements
### Requirement: Existing Feature
The system SHALL keep doing the existing thing, now also handling A.
#### Scenario: Scenario the main spec already has
- **WHEN** user does X
- **THEN** system does Y
#### Scenario: New scenario to add
- **WHEN** user does A
- **THEN** system does B
## REMOVED Requirements
### Requirement: Deprecated Feature
## RENAMED Requirements
- FROM: `### Requirement: Old Name`
- TO: `### Requirement: New Name`
主要規格格式參考
主要規格是 Delta 合併的目標。它們絕不能包含 Delta 操作標題(## ADDED/MODIFIED/REMOVED/RENAMED Requirements)——同步後,所有需求都應位於單一的 ## Requirements 章節下:
# <capability> Specification
## Purpose
Short description of what this capability does and why it exists.
## Requirements
### Requirement: New Feature
The system SHALL do something new.
#### Scenario: Basic case
- **WHEN** user does X
- **THEN** system does Y
關鍵原則:智慧合併
與程式化合併不同,你應合併而非覆寫:
- 一個 MODIFIED 區塊承載了整個需求——包括主體以及每個在變更中保留下來的場景。
openspec validate和openspec archive都會拒絕一個丟棄了主要規格仍擁有的場景的區塊。 - 保留 Delta 未提及的任何內容,並維持主要規格現有的順序
- 使用 y