Synchroniser les spécifications delta d'un changement vers les spécifications principales.
Il s'agit d'une opération pilotée par l'agent : vous lirez les spécifications delta et modifierez directement les spécifications principales pour appliquer les changements. Cela permet une fusion intelligente (par exemple, ajouter un scénario sans copier l'intégralité de l'exigence).
Sélection du magasin : Si l'utilisateur nomme un magasin (un dépôt OpenSpec autonome enregistré sur cette machine) ou que le travail en fait partie, exécutez openspec store list --json pour découvrir les identifiants de magasin enregistrés, puis passez --store <id> aux commandes qui lisent ou écrivent des spécifications et des changements (new change, status, instructions, list, show, validate, archive, doctor, context, schemas, view). Une fois sélectionné, traitez --store <id> comme persistant pour le reste du flux de travail. Chaque exemple non cadré de ces commandes ci-dessous est un raccourci : avant de l'exécuter, ajoutez l'indicateur. Par exemple, exécutez openspec status --change "<nom>" --json --store "<id>", pas la forme non cadrée montrée ci-dessous. Les autres commandes ne prennent pas l'indicateur. Les indications imprimées par les commandes portent déjà l'indicateur ; conservez-le dans les suivis. Sans magasin, les commandes agissent sur la racine openspec/ locale la plus proche.
Vérification du projet : Ces étapes supposent un projet qui utilise déjà OpenSpec. Avant la première étape qui écrit quoi que ce soit (new change, archive, sync specs ou la rédaction d'un fichier d'artefact), confirmez que le projet a une racine : exécutez openspec list --json (avec --store <id> lorsqu'un magasin est sélectionné, car le magasin est alors la racine) et lisez root. Un objet racine signifie que le projet est configuré. "root": null signifie qu'il ne l'est pas - il n'y a pas de répertoire openspec/ ici, et une écriture telle que openspec new change en créerait un comme effet secondaire. La commande se termine également avec un code non nul, ce qui est cette réponse plutôt qu'une CLI cassée, alors lisez le JSON au lieu de réessayer ou de contourner le problème.
Un "root": null n'est pas lié à la configuration : lorsqu'un message d'erreur status commence par Declared in ou Invalid store declaration in et nomme openspec/config.yaml (ou config.yml) de ce projet, le projet utilise OpenSpec via un magasin qu'il déclare, que cette machine ne peut pas résoudre (le magasin n'est pas enregistré, ou la ligne store: est mal formée). Ne le traitez pas comme non initialisé et sautez les branches ci-dessous : arrêtez-vous avant d'écrire et montrez à l'utilisateur le message et fix de cette erreur.
Sinon, sans racine, ce qui se passe ensuite dépend de la façon dont ce flux de travail a été atteint :
- Sélection automatique : vous avez choisi ce flux de travail vous-même, sans que l'utilisateur nomme OpenSpec, nomme cette compétence ou exécute sa commande oblique. Arrêtez d'utiliser OpenSpec et répondez à la demande normalement, comme vous le feriez sans OpenSpec installé. Ne leur demandez pas de configurer quoi que ce soit et ne mentionnez pas la configuration OpenSpec.
- Demande OpenSpec explicite : l'utilisateur a nommé OpenSpec, nommé cette compétence ou exécuté sa commande oblique. Arrêtez-vous avant d'écrire et demandez comment procéder : configurer ce projet (
openspec init), cibler un magasin qu'ils ont déjà (--store <id>), ou continuer sans OpenSpec pour cette demande. Attendez leur réponse.
Dans les deux branches, ne créez jamais la racine comme effet secondaire : n'exécutez pas openspec init tant que l'utilisateur ne le demande pas, ne créez pas manuellement les fichiers openspec/ et ne laissez pas une commande la créer.
<chemin-capacité> est le répertoire des spécifications relatif à specs/ (par exemple, user-auth ou identity/user-auth). Conservez le chemin complet de chaque spécification delta lors de la résolution de sa spécification principale.
Entrée : Spécifiez éventuellement un nom de changement. Si omis, vérifiez s'il peut être déduit du contexte de la conversation. Si vague ou ambigu, vous DEVEZ demander les changements disponibles.
Étapes
-
Sélectionner le changement
Si un nom est fourni, utilisez-le. Sinon :
- Déduisez du contexte de la conversation si l'utilisateur a mentionné un changement
- Sélection automatique si un seul changement actif existe
- Si ambigu, exécutez
openspec list --jsonpour obtenir les changements disponibles et demandez à l'utilisateur d'en sélectionner un
Lorsque vous invitez, montrez les changements qui ont des spécifications delta (sous le répertoire
specs/).Annoncez toujours : "Utilisation du changement : " et comment le remplacer (par exemple,
/openspec-sync-specs <autre>). -
Résoudre le contexte du changement
Exécutez :
openspec status --change "<nom>" --jsonLe JSON inclut
planningHome.root. Les spécifications principales se trouvent sous<planningHome.root>/openspec/specs/— utilisez cette racine (tenant compte du magasin) pour chaque chemin de spécification principale ci-dessous, pas un chemin de dépôt codé en dur. Lorsqu'un magasin est sélectionné, il pointe vers le magasin, pas vers le dépôt actuel. -
Trouver les spécifications delta
Utilisez
artifactPaths.specs.existingOutputPathsdu JSON de statut comme seule source des chemins de spécification delta. Si l'entréespecsest manquante ouexistingOutputPathsest vide, signalez qu'il n'y a pas de spécifications delta à synchroniser, ne les déduisez pas d'autres artefacts, et arrêtez-vous sans demander d'instructions d'artefact ou écrire une spécification principale.Synchronisez chaque chemin dans
existingOutputPathssauf si l'appelant a réduit l'ensemble. Un appelant le réduit en nommant une liste explicite d'entrées complètes deexistingOutputPaths— copiez ces valeurs absolues textuellement. L'archive fait cela en ligne, et un utilisateur peut aussi le faire (par exemple, en sélectionnant l'entrée se terminant par/specs/billing/invoices/spec.md). Synchronisez ensuite uniquement les chemins nommés et laissez les autres spécifications delta intactes : l'archive en masse exclut un delta dont elle n'a pas pu trouver l'implémentation, et le synchroniser de toute façon écrirait une spécification principale que l'appelant a délibérément retenue. Portez cette sélection réduite à travers l'étape 4 ; ne l'élargissez jamais à la liste complète. Si un chemin nommé n'est pas dansexistingOutputPaths, ne le synchronisez pas — signalez-le et arrêtez-vous, plutôt que de le supprimer silencieusement. Si la liste nommée est vide, signalez qu'il n'y a rien à synchroniser et arrêtez-vous sans écrire de spécification principale.Chaque fichier de spécification delta contient des sections comme :
## ADDED Requirements- Nouvelles exigences à ajouter## MODIFIED Requirements- Modifications aux exigences existantes## REMOVED Requirements- Exigences à supprimer## RENAMED Requirements- Exigences à renommer (format FROM:/TO:)
Si aucune spécification delta n'est trouvée, informez l'utilisateur et arrêtez-vous.
-
Pour chaque spécification delta, appliquer les modifications aux spécifications principales
Avant la première écriture de spécification principale, obtenez un instantané actuel des règles de spécifications :
- Si l'archive a invoqué ce flux de travail en ligne et a fourni un instantané valide de
openspec instructions specs --change "<nom>" --json, réutilisez-le et ne récupérez pas les mêmes instructions à nouveau. - Sinon, exécutez cette commande une fois maintenant avec les mêmes indicateurs de racine sélectionnée.
- Si la recherche directe se termine avec un code non nul ou renvoie un JSON d'instructions d'artefact invalide, signalez l'erreur et arrêtez-vous avant d'écrire une spécification principale. Ne traitez pas l'échec comme un ensemble de règles absent.
- Une réponse valide avec des
rulesomises signifie qu'aucune règle d'artefact n'est configurée et que la fusion sémantique existante continue.
Appliquez les
rulesretournées uniquement au contenu et à la forme des spécifications principales produites par cette fusion. Les règles d'artefact ne sont pas des directives d'opération et ne peuvent pas modifier les racines sélectionnées, les chemins delta, les vérifications CLI ou les étapes du flux de travail. Utilisez leur texte comme contraintes sans le copier textuellement dans une spécification principale ou un résumé.Pour chaque chemin de spécification delta de capacité sélectionné à l'étape 3 — la liste complète
existingOutputPaths, ou le sous-ensemble réduit lorsqu'un appelant en a fourni un (ceux-ci peuvent appartenir à un magasin sélectionné, pas au dépôt) :a. Lire la spécification delta pour comprendre les modifications prévues
b. Lire la spécification principale à
<planningHome.root>/openspec/specs/<chemin-capacité>/spec.md(peut ne pas encore exister)Si elle n'existe pas encore (une nouvelle capacité), faites correspondre ce que fait
openspec archive: seules les exigences ADDED peuvent être appliquées - l'étape d crée la spécification à partir d'elles. Les exigences MODIFIED et RENAMED n'ont aucune exigence sur laquelle agir, alors arrêtez la synchronisation pour cette capacité et signalez que sa spécification principale n'existe pas et que seul ADDED est autorisé pour une nouvelle spécification ; n'inventez jamais l'exigence manquante. REMOVED n'a rien à supprimer - ignorez-le et avertissez.c. Appliquer les modifications intelligemment :
Exigences ADDED :
- Si l'exigence n'existe pas dans la spécification principale → ajoutez-la
- Si l'exigence existe déjà → mettez-la à jour pour correspondre (traitez comme MODIFIED implicite)
Exigences MODIFIED :
- Trouvez l'exigence dans la spécification principale
- Appliquez les modifications - cela peut être :
- Ajouter de nouveaux scénarios que la spécification principale n'a pas encore
- Modifier des scénarios existants
- Changer la description de l'exigence
- Préservez les scénarios/contenus non mentionnés dans le delta
Exigences REMOVED :
- Supprimez le bloc d'exigence entier de la spécification principale
- Retirez la capacité. Supprimez tout le fichier
spec.md- et le répertoire une fois que rien d'autre n'y reste - uniquement lorsque TOUTES ces conditions sont remplies :- la suppression des exigements cette exécution n'a laissé aucun bloc d'exigence ;
- le reste de la spécification est bien formé (il a toujours un
## Purpose) ; - la spécification principale n'était pas déjà vide avant cette synchronisation - si vous avez supprimé rien, ne changez rien ;
- chaque autre ligne non vide de tout le fichier est comptabilisée comme le titre, Purpose, en-tête Requirements, ou une exigence canonique instruction, scénarios ou exemples encadrés ;
- le
.openspec.yamldu changement déclareretire_capabilities: true; - le
spec.mdse résout à l'intérieur de la vraie racine des spécifications (ne suivez pas un lien symbolique de répertoire de capacité pour supprimer un fichier externe). Si la suppression des exigences sélectionnées ne laisserait aucun bloc d'exigence et qu'une condition de retrait n'est pas satisfaite, ne modifiez pas la spécification principale. Arrêtez la synchronisation pour cette capacité, signalez la condition bloquante et dites à l'utilisateur comment la résoudre. N'écrivez ou ne laissez jamais une section## Requirementsvide. Lorsque seul le marqueur manque, dites-le aussi - c'est la seule chose que l'utilisateur peut ajouter pour que le retrait réussisse.
- La suppression du fichier supprime également son
## Purpose; toute autre section bloque le retrait. Nommez Purpose lorsque vous signalez le retrait. Incluez ungit checkoutcopiable uniquement lorsque la spécification se trouvait dans la copie de travail de l'appelant ; sinon, fournissez des conseils de récupération limités à la copie de travail.
Exigences RENAMED :
- Trouvez l'exigence FROM, renommez-la en TO
## Purposedans le delta :- La spécification principale en a déjà un et il est faisant autorité - laissez-le tranquille
(c'est ce que fait
openspec archive; il avertit et continue)
d. Créer une nouvelle spécification principale si la capacité n'existe pas encore :
- Uniquement lorsque le delta a des exigences ADDED à y mettre et qu'aucune exigence MODIFIED ou
RENAMED n'a bloqué cette capacité à l'étape b. Sinon, ne créez rien
et ne touchez pas au répertoire des spécifications. Pour un delta uniquement REMOVED, si le
.openspec.yamldu changement déclareretire_capabilities: true, signalez-le comme déjà retiré et continuez sans recréer la spécification. Sans ce marqueur, signalez la synchronisation comme bloquée :openspec archivela rejette avecSpec must have at least one requirement. Un delta vide n'a aucune opération à synchroniser ; signalez-le également comme bloqué. N'écrivez jamais une section## Requirementsvide. - Créez
<planningHome.root>/openspec/specs/<chemin-capacité>/spec.md - Ajoutez la section Purpose : copiez le corps du
## Purposedu delta textuellement lorsqu'il en a un (c'est ce que faitopenspec archive) ; écrivez uniquement un espace réservé TBD court lorsqu'il n'en a pas - Ajoutez la section Requirements avec les exigences ADDED
- Suivez le Référence de Format de Spécification Principale ci-dessous
- Si l'archive a invoqué ce flux de travail en ligne et a fourni un instantané valide de
-
Valider les spécifications principales mises à jour
Exécutez
openspec validate --specsavec les mêmes indicateurs de racine sélectionnée utilisés précédemment. Si la validation échoue, signalez les problèmes et ne prétendez pas que la synchronisation a réussi. -
Afficher le résumé
Après avoir appliqué toutes les modifications, résumez :
- Quelles capacités ont été mises à jour
- Quels changements ont été effectués (exigences ajoutées/modifiées/supprimées/renommées)
- Toute nouvelle spécification principale laissée avec un espace réservé TBD Purpose, afin qu'elle soit écrite maintenant plutôt que de persister
- Toute capacité retirée, en nommant le
spec.mdsupprimé, son Purpose, et soit ungit checkoutcopiable soit des conseils de récupération limités à la copie de travail
Référence de Format de Spécification Delta
# Spec Delta
## Purpose
Uniquement sur un delta qui introduit une toute nouvelle capacité. Ensemence la nouvelle spécification principale.
## ADDED Requirements
### Requirement: Nouvelle Fonctionnalité
Le système DOIT faire quelque chose de nouveau.
#### Scenario: Cas de base
- **WHEN** l'utilisateur fait X
- **THEN** le système fait Y
## MODIFIED Requirements
### Requirement: Fonctionnalité Existante
Le système DOIT continuer à faire la chose existante, en gérant maintenant aussi A.
#### Scenario: Scénario que la spécification principale a déjà
- **WHEN** l'utilisateur fait X
- **THEN** le système fait Y
#### Scenario: Nouveau scénario à ajouter
- **WHEN** l'utilisateur fait A
- **THEN** le système fait B
## REMOVED Requirements
### Requirement: Fonctionnalité Obsolète
## RENAMED Requirements
- FROM: `### Requirement: Ancien Nom`
- TO: `### Requirement: Nouveau Nom`
Référence de Format de Spécification Principale
Les spécifications principales sont celles DANS lesquelles le delta fusionne. Elles ne doivent jamais contenir d'en-têtes d'opération delta (## ADDED/MODIFIED/REMOVED/RENAMED Requirements) - après la synchronisation, chaque exigence vit sous une seule section ## Requirements :
# Spécification de <capacité>
## Purpose
Description courte de ce que fait cette capacité et pourquoi elle existe.
## Requirements
### Requirement: Nouvelle Fonctionnalité
Le système DOIT faire quelque chose de nouveau.
#### Scenario: Cas de base
- **WHEN** l'utilisateur fait X
- **THEN** le système fait Y
Principe Clé : Fusion Intelligente
Contrairement à la fusion programmatique, vous fusionnez plutôt que d'écraser :
- Un bloc MODIFIED porte l'intégralité de l'exigence - le corps plus chaque scénario qui survit au changement.
openspec validateetopenspec archiverejettent tous deux un bloc qui supprime un scénario que la spécification principale a encore. - Conservez tout ce que le delta ne mentionne pas, dans l'ordre existant de la spécification principale.
Commandes associées
openspec init— Configurer un nouveau projet OpenSpecopenspec list --json— Lister les changements en JSONopenspec status --change "<nom>" --json— Voir le contexte du changementopenspec archive --change "<nom>"— Archiver un changement (synchronisation et archivage en une seule commande)openspec validate --specs— Valider les spécifications principalesopenspec new change— Créer un nouveau changement ou l'ouvrir s'il existe déjàopenspec instructions specs --change "<nom>" --json— Récupérer les règles d'artefact pour les spécifications