Synchronisez les spécifications delta d'une modification vers les spécifications principales.
Il s'agit d'une opération pilotée par agent – vous lirez les spécifications delta et modifierez directement les spécifications principales pour appliquer les modifications. 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 magasin est un dépôt OpenSpec autonome enregistré sur cette machine) ou si le travail se trouve dans un, exécutez openspec store list --json pour découvrir les identifiants de magasin enregistrés, puis passez --store <id> sur les commandes qui lisent ou écrivent des spécifications et des modifications (new change, status, instructions, list, show, validate, archive, doctor, context, schemas, view). Une fois sélectionné, traitez --store <id> comme collant pour le reste du workflow. Chaque exemple non cadré de ces commandes ci-dessous est une abréviation : avant de l'exécuter, ajoutez le drapeau. Par exemple, exécutez openspec status --change "<name>" --json --store "<id>", et non la forme non cadrée ci-dessous. Les autres commandes ne prennent pas le drapeau. Les indications imprimées par les commandes portent déjà le drapeau ; gardez-le sur 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 root 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'un CLI cassé, alors lisez le JSON au lieu de réessayer ou de contourner le problème.
Un "root": null ne concerne pas 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 bien 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 ne sautez pas les branches ci-dessous : arrêtez-vous avant d'écrire et montrez à l'utilisateur le message et le fix de cette erreur.
Sinon, sans racine, ce qui se passe ensuite dépend de la façon dont ce workflow a été atteint :
- Sélection automatique : vous avez choisi ce workflow vous-même, sans que l'utilisateur nomme OpenSpec, nomme cette compétence, ou exécute sa commande slash. Arrêtez d'utiliser OpenSpec et répondez normalement à la demande, comme vous le feriez sans OpenSpec installé. Ne lui demandez pas de configurer quoi que ce soit et ne mentionnez pas la configuration d'OpenSpec.
- Demande explicite d'OpenSpec : l'utilisateur a nommé OpenSpec, nommé cette compétence, ou exécuté sa commande slash. Arrêtez-vous avant d'écrire et demandez comment procéder : configurer ce projet (
openspec init), cibler un magasin qu'il possède déjà (--store <id>), ou continuer sans OpenSpec pour cette demande. Attendez sa 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.
<capability-path> est le répertoire de spécification 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 modification. S'il est omis, vérifiez s'il peut être déduit du contexte de la conversation. Si c'est vague ou ambigu, vous DEVEZ demander les modifications disponibles.
Étapes
-
Sélectionner la modification
Si un nom est fourni, utilisez-le. Sinon :
- Déduisez du contexte de la conversation si l'utilisateur a mentionné une modification
- Sélectionnez automatiquement si une seule modification active existe
- Si ambigu, exécutez
openspec list --jsonpour obtenir les modifications disponibles et demandez à l'utilisateur d'en sélectionner une
Lorsque vous invitez, montrez les modifications qui ont des spécifications delta (sous le répertoire
specs/).Annoncez toujours : "Utilisation de la modification : " et comment la remplacer (par exemple,
/opsx:sync <autre>). -
Résoudre le contexte de la modification
Exécutez :
openspec status --change "<name>" --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 unique source des chemins de spécifications 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 sans é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. Archive le fait 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). Ensuite, synchronisez uniquement les chemins nommés et laissez les spécifications delta restantes intactes : l'archive en masse exclut un delta dont l'implémentation n'a pas pu être trouvée, et le synchroniser quand même é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 laisser tomber silencieusement. Si la liste nommée est vide, signalez qu'il n'y a rien à synchroniser et arrêtez-vous sans écrire une spécification principale.Chaque fichier de spécification delta contient des sections comme :
## Exigences AJOUTÉES- Nouvelles exigences à ajouter## Exigences MODIFIÉES- Modifications des exigences existantes## Exigences SUPPRIMÉES- Exigences à supprimer## Exigences RENOMMÉES- Exigences à renommer (format DE:/VERS:)
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écification :
- Si l'archive a invoqué ce workflow en ligne et a fourni un instantané valide de
openspec instructions specs --change "<name>" --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 drapeaux 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
rulesrenvoyées uniquement au contenu et à la forme des spécifications principales produites par cette fusion. Les règles d'artefact ne sont pas des instructions d'opération et ne peuvent pas modifier les racines sélectionnées, les chemins delta, les vérifications CLI ou les étapes du workflow. 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/<capability-path>/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 AJOUTÉES peuvent être appliquées - l'étape d crée la spécification à partir d'elles. Les exigences MODIFIÉES et RENOMMÉES 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 AJOUTÉ est autorisé pour une nouvelle spécification ; n'inventez jamais l'exigence manquante. Les exigences SUPPRIMÉES n'ont rien à supprimer - ignorez-les et avertissez.c. Appliquer les modifications intelligemment :
Exigences AJOUTÉES :
- Si l'exigence n'existe pas dans la spécification principale → ajoutez-la
- Si l'exigence existe déjà → mettez-la à jour pour correspondre (traiter comme MODIFIÉ implicite)
Exigences MODIFIÉES :
- 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
- Conservez les scénarios/contenu non mentionnés dans le delta
Exigences SUPPRIMÉES :
- Supprimez le bloc d'exigence entier de la spécification principale
- Retrait de la capacité. Supprimez tout le
spec.md- et le répertoire une fois que rien d'autre n'y reste - seulement lorsque TOUTES ces conditions sont remplies :- la suppression des exigences lors de cette exécution n'a laissé aucun bloc d'exigence ;
- le reste de la spécification est bien formé (il a encore un
## Object) ; - la spécification principale n'était pas déjà vide avant cette synchronisation - si vous n'avez rien supprimé, ne changez rien ;
- chaque autre ligne non vide du fichier entier est prise en compte comme le titre, l'Object, l'en-tête Exigences, ou l'énoncé d'une exigence canonique, ses scénarios ou exemples encadrés ;
- le
.openspec.yamlde la modification déclareretire_capabilities: true; - le
spec.mdse résout à l'intérieur de la racine réelle 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 que l'une des conditions 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 jamais et ne laissez jamais une section## Exigencesvide. Lorsque seul le marqueur manque, dites-le aussi - c'est la seule chose que l'utilisateur peut ajouter pour que le retrait aboutisse.
- La suppression du fichier supprime également son
## Object; toute autre section bloque le retrait. Nommez l'Object lorsque vous signalez le retrait. Incluez ungit checkoutcollable uniquement lorsque la spécification se trouvait dans le répertoire de travail de l'appelant ; sinon, donnez des conseils de récupération limités au répertoire de travail.
Exigences RENOMMÉES :
- Trouvez l'exigence DE, renommez-la en VERS
## Objectdans 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 AJOUTÉES à y mettre et aucune exigence MODIFIÉE ou RENOMMÉE n'a bloqué cette capacité à l'étape b. Sinon, ne créez rien et laissez le répertoire des spécifications intact. Pour un delta uniquement SUPPRIMÉ, si le
.openspec.yamlde la modification 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 avecLa spécification doit avoir au moins une exigence. Un delta vide n'a aucune opération à synchroniser ; signalez-le aussi comme bloqué. N'écrivez jamais une section## Exigencesvide. - Créez
<planningHome.root>/openspec/specs/<capability-path>/spec.md - Ajoutez la section Object : copiez textuellement le corps du
## Objectdu delta lorsqu'il en a un (c'est ce que faitopenspec archive) ; écrivez seulement un espace réservé bref À DÉFINIR lorsqu'il n'en a pas - Ajoutez la section Exigences avec les exigences AJOUTÉES
- Suivez la Référence de format de spécification principale ci-dessous
- Si l'archive a invoqué ce workflow en ligne et a fourni un instantané valide de
-
Valider les spécifications principales mises à jour
Exécutez
openspec validate --specsavec les mêmes drapeaux 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
- Quelles modifications ont été apportées (exigences ajoutées/modifiées/supprimées/renommées)
- Toute nouvelle spécification principale laissée avec un espace réservé Object À DÉFINIR, afin qu'elle soit écrite maintenant plutôt que de traîner
- Toute capacité retirée, nommant le
spec.mdsupprimé, son Object, et soit ungit checkoutcollable ou des conseils de récupération limités au répertoire de travail
Référence de format de spécification delta
# Delta de spécification
## Object
Uniquement sur un delta qui introduit une toute nouvelle capacité. Sème la nouvelle spécification principale.
## Exigences AJOUTÉES
### Exigence : Nouvelle fonctionnalité
Le système DOIT faire quelque chose de nouveau.
#### Scénario : Cas de base
- **QUAND** l'utilisateur fait X
- **ALORS** le système fait Y
## Exigences MODIFIÉES
### Exigence : Fonctionnalité existante
Le système DOIT continuer à faire la chose existante, en gérant maintenant aussi A.
#### Scénario : Scénario que la spécification principale a déjà
- **QUAND** l'utilisateur fait X
- **ALORS** le système fait Y
#### Scénario : Nouveau scénario à ajouter
- **QUAND** l'utilisateur fait A
- **ALORS** le système fait B
## Exigences SUPPRIMÉES
### Exigence : Fonctionnalité obsolète
## Exigences RENOMMÉES
- DE : `### Exigence : Ancien nom`
- VERS : `### Exigence : Nouveau nom`
Référence de format de spécification principale
Les spécifications principales sont ce dans quoi le delta fusionne. Elles ne doivent jamais contenir d'en-têtes d'opération delta (## Exigences AJOUTÉES/MODIFIÉES/SUPPRIMÉES/RENOMMÉES) - après synchronisation, chaque exigence se trouve sous une seule section ## Exigences :
# Spécification de la <capacité>
## Object
Brève description de ce que fait cette capacité et pourquoi elle existe.
## Exigences
### Exigence : Nouvelle fonctionnalité
Le système DOIT faire quelque chose de nouveau.
#### Scénario : Cas de base
- **QUAND** l'utilisateur fait X
- **ALORS** le système fait Y
Principe clé : Fusion intelligente
Contrairement à la fusion programmatique, vous fusionnez plutôt que d'écraser :
- Un bloc MODIFIÉ porte l'exigence entière - le corps plus chaque scénario qui survit à la modification.
openspec validateetopenspec archiverejettent tous deux un bloc qui laisse tomber un scénario que la spécification principale a encore. - Gardez tout ce que le delta ne mentionne pas, dans l'ordre existant de la spécification principale
- Utilisez y
…
[tronqué pour la traduction]