Sincroniza especificações delta de uma alteração para as especificações principais.
Esta é uma operação orientada por agente — você lerá as especificações delta e editará diretamente as especificações principais para aplicar as alterações. Isso permite uma mesclagem inteligente (por exemplo, adicionar um cenário sem copiar todo o requisito).
Seleção de loja: Se o usuário nomear uma loja (uma loja é um repositório OpenSpec independente registrado nesta máquina) ou o trabalho estiver em uma, execute openspec store list --json para descobrir os IDs de lojas registradas e, em seguida, passe --store <id> nos comandos que leem ou escrevem especificações e alterações (new change, status, instructions, list, show, validate, archive, doctor, context, schemas, view). Uma vez selecionado, trate --store <id> como fixo para o resto do fluxo de trabalho. Cada exemplo sem escopo desses comandos abaixo é uma abreviação: antes de executá-lo, anexe a flag. Por exemplo, execute openspec status --change "<nome>" --json --store "<id>", não a forma sem escopo mostrada abaixo. Outros comandos não aceitam a flag. Dicas impressas pelos comandos já carregam a flag; mantenha-a nos acompanhamentos. Sem uma loja, os comandos atuam na raiz local openspec/ mais próxima.
Verificação do projeto: Estas etapas esperam um projeto que já usa OpenSpec. Antes da primeira etapa que escreve qualquer coisa (new change, archive, sync specs ou criação de um arquivo de artefato), confirme que o projeto tem uma raiz: execute openspec list --json (com --store <id> quando uma loja está selecionada, pois a loja é então a raiz) e leia root. Um objeto raiz significa que o projeto está configurado. "root": null significa que não está — não há um diretório openspec/ aqui, e uma operação de escrita como openspec new change o criaria como efeito colateral. O comando também sai com código não zero, o que é essa resposta em vez de um CLI quebrado, então leia o JSON em vez de tentar novamente ou contorná-lo.
Um caso em que "root": null não é sobre configuração: quando uma mensagem de erro status começa com Declared in ou Invalid store declaration in e nomeia o openspec/config.yaml (ou config.yml) deste projeto, o projeto realmente usa OpenSpec por meio de uma loja que declara, mas esta máquina não pode resolver (a loja não está registrada, ou a linha store: está malformada). Não trate como não inicializado e pule as ramificações abaixo: pare antes de escrever e mostre ao usuário a message e fix desse erro.
Caso contrário, sem raiz, o que acontece a seguir depende de como este fluxo de trabalho foi alcançado:
- Auto-selecionado: você escolheu este fluxo de trabalho por conta própria, sem o usuário nomear OpenSpec, nomear esta skill ou executar seu comando de barra. Pare de usar OpenSpec e responda à solicitação normalmente, como faria sem OpenSpec instalado. Não peça para eles configurarem nada e não mencione a configuração do OpenSpec.
- Solicitação explícita de OpenSpec: o usuário nomeou OpenSpec, nomeou esta skill ou executou seu comando de barra. Pare antes de escrever e pergunte como proceder: configurar este projeto (
openspec init), direcionar uma loja que eles já têm (--store <id>), ou continuar sem OpenSpec para esta solicitação. Aguarde a resposta deles.
Em ambas as ramificações, nunca crie a raiz como efeito colateral: não execute openspec init até que o usuário peça, não crie manualmente arquivos openspec/ e não deixe um comando criá-la.
<caminho-da-capacidade> é o diretório da especificação relativo a specs/ (por exemplo, user-auth ou identity/user-auth). Preserve o caminho completo de cada especificação delta ao resolver sua especificação principal.
Entrada: Opcionalmente, especifique um nome de alteração. Se omitido, verifique se pode ser inferido do contexto da conversa. Se vago ou ambíguo, você DEVE solicitar as alterações disponíveis.
Etapas
-
Selecionar a alteração
Se um nome for fornecido, use-o. Caso contrário:
- Inferir do contexto da conversa se o usuário mencionou uma alteração
- Auto-selecionar se apenas uma alteração ativa existir
- Se ambíguo, execute
openspec list --jsonpara obter as alterações disponíveis e peça ao usuário para selecionar uma
Ao solicitar, mostre as alterações que têm especificações delta (no diretório
specs/).Sempre anuncie: "Usando alteração: " e como substituir (por exemplo,
/openspec-sync-specs <outro>). -
Resolver o contexto da alteração
Execute:
openspec status --change "<nome>" --jsonO JSON inclui
planningHome.root. As especificações principais estão sob<planningHome.root>/openspec/specs/— use essa raiz (ciente da loja) para cada caminho de especificação principal abaixo, não um caminho de repositório codificado. Quando uma loja é selecionada, ela aponta para a loja, não para o repositório atual. -
Encontrar especificações delta
Use
artifactPaths.specs.existingOutputPathsdo JSON de status como a única fonte de caminhos de especificações delta. Se a entradaspecsestiver faltando ouexistingOutputPathsestiver vazio, relate que não há especificações delta para sincronizar, não as infira de outros artefatos, e pare sem solicitar instruções de artefato ou escrever uma especificação principal.Sincronize cada caminho em
existingOutputPathsa menos que o chamador tenha reduzido o conjunto. Um chamador reduz ao nomear uma lista explícita de entradas completas deexistingOutputPaths— copie esses valores absolutos textualmente. Archive faz isso inline, e um usuário também pode (por exemplo, selecionando a entrada que termina em/specs/billing/invoices/spec.md). Em seguida, sincronize apenas os caminhos nomeados e deixe as especificações delta restantes intocadas: arquivar em massa exclui um delta cuja implementação não pôde encontrar, e sincronizá-lo de qualquer maneira escreveria uma especificação principal que o chamador deliberadamente reteve. Carregue essa seleção reduzida pela etapa 4; nunca a amplie de volta para a lista completa. Se um caminho nomeado não estiver emexistingOutputPaths, não o sincronize — relate-o e pare, em vez de descartá-lo silenciosamente. Se a lista nomeada estiver vazia, relate que não há nada para sincronizar e pare sem escrever uma especificação principal.Cada arquivo de especificação delta contém seções como:
## REQUISITOS ADICIONADOS- Novos requisitos para adicionar## REQUISITOS MODIFICADOS- Alterações em requisitos existentes## REQUISITOS REMOVIDOS- Requisitos para remover## REQUISITOS RENOMEADOS- Requisitos para renomear (formato DE:/PARA:)
Se nenhuma especificação delta for encontrada, informe o usuário e pare.
-
Para cada especificação delta, aplicar alterações às especificações principais
Antes da primeira escrita de especificação principal, obtenha um snapshot atual das regras de especificações:
- Se archive invocou este fluxo de trabalho inline e forneceu um snapshot válido de
openspec instructions specs --change "<nome>" --json, reutilize-o e não busque as mesmas instruções novamente. - Caso contrário, execute esse comando uma vez agora com as mesmas flags de raiz selecionada.
- Se a consulta direta sair com código não zero ou retornar JSON de instrução de artefato inválido, relate o erro e pare antes de escrever qualquer especificação principal. Não trate a falha como um conjunto de regras ausente.
- Uma resposta válida com
rulesomitido significa que nenhuma regra de artefato está configurada e a mesclagem semântica existente continua.
Aplique as
rulesretornadas apenas ao conteúdo e forma das especificações principais produzidas por esta mesclagem. Regras de artefato não são orientação de operação e não podem alterar raízes selecionadas, caminhos delta, verificações CLI ou etapas do fluxo de trabalho. Use seu texto como restrições sem copiá-lo textualmente em uma especificação principal ou resumo.Para cada caminho de especificação delta de capacidade selecionado na etapa 3 — a lista completa de
existingOutputPaths, ou o subconjunto reduzido quando um chamador forneceu um (estes podem pertencer a uma loja selecionada, não ao repositório):a. Leia a especificação delta para entender as alterações pretendidas
b. Leia a especificação principal em
<planningHome.root>/openspec/specs/<caminho-da-capacidade>/spec.md(pode não existir ainda)Se não existir ainda (uma nova capacidade), corresponda ao que
openspec archivefaz: apenas requisitos ADICIONADOS podem ser aplicados - a etapa d cria a especificação a partir deles. MODIFICADOS e RENOMEADOS não têm requisito para atuar, então pare a sincronização para essa capacidade e relate que sua especificação principal não existe e apenas ADICIONADOS é permitido para uma nova especificação; nunca invente o requisito ausente. REMOVIDOS não tem nada para remover - pule e avise.c. Aplicar alterações de forma inteligente:
REQUISITOS ADICIONADOS:
- Se o requisito não existe na especificação principal → adicione-o
- Se o requisito já existe → atualize-o para corresponder (trate como MODIFICADO implícito)
REQUISITOS MODIFICADOS:
- Encontre o requisito na especificação principal
- Aplique as alterações - isso pode ser:
- Adicionar novos cenários que a especificação principal ainda não tem
- Modificar cenários existentes
- Alterar a descrição do requisito
- Preserve cenários/conteúdo não mencionados no delta
REQUISITOS REMOVIDOS:
- Remova o bloco de requisito inteiro da especificação principal
- Aposentando a capacidade. Exclua todo o
spec.md- e o diretório uma vez que nada mais reste nele - apenas quando TODAS as seguintes condições forem atendidas:- remover os requisitos desta execução não deixou blocos de requisitos;
- o resto da especificação está bem formado (ainda tem um
## Propósito); - a especificação principal não estava já vazia antes desta sincronização - se você removeu nada, não altere nada;
- cada outra linha não branca no arquivo inteiro é contabilizada como título, Propósito, cabeçalho de Requisitos, ou a declaração, cenários ou exemplos entre crases de um requisito canônico;
- o
.openspec.yamlda alteração declararetire_capabilities: true; - o
spec.mdresolve dentro da raiz real de especificações (não siga um link simbólico de diretório de capacidade para excluir um arquivo externo). Se remover os requisitos selecionados deixaria nenhum bloco de requisitos e qualquer condição de aposentadoria não for satisfeita, não modifique a especificação principal. Pare a sincronização para essa capacidade, relate a condição bloqueadora e diga ao usuário como resolvê-la. Nunca escreva ou deixe uma seção## Requisitosvazia. Quando apenas o marcador estiver faltando, diga isso também - é a única coisa que o usuário pode adicionar para fazer a aposentadoria passar.
- Excluir o arquivo também exclui seu
## Propósito; qualquer outra seção bloqueia a aposentadoria. Nomeie Propósito quando você relatar a aposentadoria. Inclua umgit checkoutcopiável apenas quando a especificação viver no checkout do chamador; caso contrário, dê orientação de recuperação com escopo de checkout.
REQUISITOS RENOMEADOS:
- Encontre o requisito DE, renomeie para PARA
## Propósitono delta:- A especificação principal já tem um e é autoritativo - deixe-o em paz
(isso é o que
openspec archivefaz; avisa e segue em frente)
d. Criar nova especificação principal se a capacidade ainda não existir:
- Apenas quando o delta tem requisitos ADICIONADOS para colocar nela e nenhum MODIFICADO ou
RENOMEADO bloqueou esta capacidade na etapa b. Caso contrário, não crie nada e deixe o diretório de especificações intocado. Para um delta apenas com REMOVIDOS, se o
.openspec.yamlda alteração declararretire_capabilities: true, relate-o como já aposentado e continue sem recriar a especificação. Sem esse marcador, relate a sincronização como bloqueada:openspec archiverejeita comA especificação deve ter pelo menos um requisito. Um delta vazio não tem operações para sincronizar; relate-o como bloqueado também. Nunca escreva uma seção## Requisitosvazia. - Crie
<planningHome.root>/openspec/specs/<caminho-da-capacidade>/spec.md - Adicione a seção Propósito: copie o corpo do delta
## Propósitotextualmente quando ele tiver um (isso é o queopenspec archivefaz); escreva apenas um espaço reservado TBD breve quando não tiver - Adicione a seção de Requisitos com os requisitos ADICIONADOS
- Siga o Formato de Referência da Especificação Principal abaixo
- Se archive invocou este fluxo de trabalho inline e forneceu um snapshot válido de
-
Validar as especificações principais atualizadas
Execute
openspec validate --specscom as mesmas flags de raiz selecionada usadas anteriormente. Se a validação falhar, relate os problemas e não afirme que a sincronização foi bem-sucedida. -
Mostrar resumo
Após aplicar todas as alterações, resuma:
- Quais capacidades foram atualizadas
- Quais alterações foram feitas (requisitos adicionados/modificados/removidos/renomeados)
- Qualquer nova especificação principal deixada com um espaço reservado TBD Propósito, para que seja escrita agora em vez de ficar pendente
- Qualquer capacidade aposentada, nomeando o
spec.mdexcluído, seu Propósito e ou umgit checkoutcopiável ou orientação de recuperação com escopo de checkout
Formato de Referência da Especificação Delta
# Delta de Especificação
## Propósito
Apenas em um delta que introduz uma capacidade totalmente nova. Semeia a nova especificação principal.
## REQUISITOS ADICIONADOS
### Requisito: Nova Funcionalidade
O sistema DEVE fazer algo novo.
#### Cenário: Caso básico
- **QUANDO** usuário faz X
- **ENTÃO** sistema faz Y
## REQUISITOS MODIFICADOS
### Requisito: Funcionalidade Existente
O sistema DEVE continuar fazendo a coisa existente, agora também lidando com A.
#### Cenário: Cenário que a especificação principal já tem
- **QUANDO** usuário faz X
- **ENTÃO** sistema faz Y
#### Cenário: Novo cenário para adicionar
- **QUANDO** usuário faz A
- **ENTÃO** sistema faz B
## REQUISITOS REMOVIDOS
### Requisito: Funcionalidade Obsoleta
## REQUISITOS RENOMEADOS
- DE: `### Requisito: Nome Antigo`
- PARA: `### Requisito: Nome Novo`
Formato de Referência da Especificação Principal
As especificações principais são onde o delta é MESCLADO. Elas nunca devem conter cabeçalhos de operação delta (## REQUISITOS ADICIONADOS/MODIFICADOS/REMOVIDOS/RENOMEADOS) - após a sincronização, cada requisito vive sob uma única seção ## Requisitos:
# Especificação de <capacidade>
## Propósito
Breve descrição do que esta capacidade faz e por que existe.
## Requisitos
### Requisito: Nova Funcionalidade
O sistema DEVE fazer algo novo.
#### Cenário: Caso básico
- **QUANDO** usuário faz X
- **ENTÃO** sistema faz Y
Princípio Chave: Mesclagem Inteligente
Ao contrário da mesclagem programática, você mescla em vez de sobrescrever:
- Um bloco MODIFICADO carrega o requisito inteiro - corpo mais cada cenário que sobrevive à alteração. Tanto
openspec validatequantoopenspec archiverejeitam um que descarta um cenário que a especificação principal ainda tem. - Mantenha qualquer coisa que o delta não menciona, na ordem existente da especificação principal (presumivelmente a ordem que o arquivamento inicial estabeleceu). Não reordene requisitos ou cenários.
- As regras acima se aplicam a cada tipo de alteração delta. Uma REMOVIDO bem-sucedida deixa arquivo ou diretório órfão (não retire a menos que todas as condições acima sejam atendidas).
- Por fim, valide com
openspec validate --specs.