Archiver un changement terminé dans le workflow expérimental.
Sélection du store : Si l'utilisateur nomme un store (un store est un dépôt OpenSpec autonome enregistré sur cette machine) ou si le travail se trouve dans un store, exécutez openspec store list --json pour découvrir les identifiants de store enregistrés, puis passez --store <id> sur les 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é, considérez --store <id> comme persistant pour le reste du workflow. 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>", et non la forme non cadrée montrée ci-dessous. Les autres commandes ne prennent pas l'indicateur. Les conseils imprimés par les commandes portent déjà l'indicateur ; conservez-le dans les suivis. Sans store, les commandes agissent sur la racine openspec/ locale la plus proche.
Vérification du projet : Ces étapes s'attendent à ce qu'un projet 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 store est sélectionné, car le store 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 par effet de bord. La commande se termine également avec un code non nul, ce qui est la réponse plutôt qu'une interface CLI cassée, donc lisez le JSON au lieu de réessayer ou de contourner le problème.
Un cas de "root": null n'est pas une question de configuration : lorsqu'un message d'erreur status commence par Declared in ou Invalid store declaration in et nomme le openspec/config.yaml (ou config.yml) de ce projet, le projet utilise OpenSpec via un store qu'il déclare, que cette machine ne peut pas résoudre (le store n'est pas enregistré, ou la ligne store: est mal formée). Ne le traitez pas comme non initialisé et n'ignorez 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 ne nomme OpenSpec, ne nomme cette compétence ou n'exécute sa commande slash. Arrêtez d'utiliser OpenSpec et répondez normalement à la demande, comme vous le feriez sans OpenSpec installé. Ne leur 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, a nommé cette compétence ou a exécuté sa commande slash. Arrêtez-vous avant d'écrire et demandez comment procéder : configurer ce projet (
openspec init), cibler un store qu'ils possèdent 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 par effet de bord : n'exécutez pas openspec init tant que l'utilisateur ne le demande pas, ne créez pas manuellement de fichiers openspec/ et ne laissez pas une commande la créer.
<chemin-de-la-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. 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 changements disponibles.
Étapes
-
Sélectionner le changement
Si un nom est fourni, utilisez-le. Sinon :
- Déduisez-le 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
Lors de la demande, montrez uniquement les changements actifs (pas encore archivés). Incluez le schéma utilisé pour chaque changement, si disponible.
Annoncez toujours : « Changement utilisé : » et comment remplacer (ex.
/opsx:archive <autre>).Charger les entrées d'archive actuelles avant les vérifications d'archive existantes :
Après avoir résolu le changement sélectionné et la racine planifiée, exécutez :
openspec instructions archive --change "<nom>" --jsonConservez les mêmes indicateurs de racine sélectionnée sur cette commande. Cette recherche est consultative et facultative : elle fournit uniquement des entrées d'invite supplémentaires, elle ne doit donc jamais bloquer l'archivage. Si elle se termine avec un code non nul ou renvoie un JSON invalide — par exemple sur une ancienne CLI qui ne prend pas encore en charge cette commande — continuez le workflow d'archivage sans contexte et sans indication d'opération. Ne signalez pas d'erreur et ne vous arrêtez pas.
Une réponse réussie peut omettre les deux champs facultatifs. Traitez
contextcomme une entrée d'invite requise au niveau du prompt : lisez-la et tenez-en compte, et appliquez les faits, conventions et contraintes pertinents du projet. TraitezoperationGuidancecomme un conseil additif facultatif : lisez et considérez chaque entrée, et suivez les entrées qui sont applicables et compatibles avec le workflow d'archivage intégré.Gardez les deux champs séparés des étapes intégrées, des choix explicites de l'utilisateur, des chemins résolus, des vérifications CLI et des contrats de commande. Si le contexte entre en conflit avec l'une de ces entrées de contrôle, signalez le conflit et conservez la valeur de contrôle. Si les conseils sont inapplicables ou en conflit avec une entrée de contrôle, ne les suivez pas et expliquez pourquoi. N'inférez pas de chemins de remplacement, d'invites ignorées ou d'indicateurs à partir de l'un ou l'autre champ, et ne copiez pas leur texte textuellement dans les spécifications, les artefacts de changement, ou les résumés d'archive, sauf si l'utilisateur le demande séparément. Ce sont des contrats de comportement au niveau du prompt, et non des vérifications exécutoires.
-
Vérifier l'état d'achèvement des artefacts
Exécutez
openspec status --change "<nom>" --jsonpour vérifier l'achèvement des artefacts.Analysez le JSON pour comprendre :
schemaName: Le workflow utiliséplanningHome,changeRoot,artifactPaths, etactionContext: contexte de chemin et de portéeartifacts: Liste des artefacts avec leur statut (done,skipped, ou autre)
Si des artefacts ne sont ni
doneniskipped(les artefacts ignorés satisfont à l'exigence - le changement déclare skip_specs) :- Affichez un avertissement listant les artefacts incomplets
- Demandez à l'utilisateur de confirmer qu'il souhaite continuer
- Continuez si l'utilisateur confirme
-
Vérifier l'état d'achèvement des tâches
Exécutez
openspec list --jsonavec les mêmes indicateurs de racine sélectionnée et trouvez l'entrée danschangesdont lenamecorrespond exactement au changement sélectionné. Exigez exactement une correspondance et des entiers non négatifstotalTasksetcompletedTasks, aveccompletedTasks <= totalTasks. La CLI résout les fichiers de tâches suivis du schéma, y compris les noms d'artefacts personnalisés, les chemins de sortie et les globs. Tâches incomplètes =totalTasks - completedTasks.N'inférez pas l'achèvement des tâches à partir de l'état des artefacts ou de l'absence d'un
tasks.mdde premier niveau. Si la recherche échoue, renvoie un JSON invalide, omet ou duplique le changement sélectionné, ou renvoie des comptes invalides, signalez le problème et arrêtez-vous avant de synchroniser ou d'archiver. La CLI ne compte que les marqueurs de case à cocherx/Xcomme complets ; les autres marqueurs, y compris ceux non familiers, restent incomplets.Si des tâches incomplètes sont trouvées :
- Affichez un avertissement indiquant le nombre de tâches incomplètes
- Demandez à l'utilisateur de confirmer qu'il souhaite continuer
- Continuez si l'utilisateur confirme
Si
totalTasksest zéro : Continuez sans avertissement lié aux tâches. -
Évaluer l'état de synchronisation des spécifications delta
Utilisez
artifactPaths.specs.existingOutputPathsdu statut JSON comme seule source de spécifications delta. Si l'entréespecsest manquante ou qu'existingOutputPathsest vide, continuez sans invite de synchronisation et n'inférez pas de spécifications delta à partir d'autres artefacts.Si des spécifications delta existent :
- Comparez chaque spécification delta avec sa spécification principale correspondante à
<planningHome.root>/openspec/specs/<chemin-de-la-capacité>/spec.md(utilisez leplanningHome.roottenant compte du store de l'étape 2, et non un chemin de dépôt codé en dur) - Une spécification principale manquante n'est pas automatiquement « déjà synchronisée ». Pour une nouvelle capacité, la spécification principale est une sortie de la synchronisation, pas une entrée :
- Si le delta a des exigences MODIFIÉES ou RENOMMÉES, signalez que seules les exigences AJOUTÉES peuvent créer une nouvelle spécification principale et marquez cette capacité comme bloquée pour la synchronisation. N'inventez jamais d'exigence qui n'a pas de version actuelle.
- Sinon, si le delta a uniquement des exigences SUPPRIMÉES et que le
.openspec.yamldu changement déclareretire_capabilities: true, la capacité est déjà retirée : comptez-la comme déjà synchronisée, avertissez qu'il n'y a plus rien à supprimer, et ne recréez pas la spécification principale. Appliquez cette règle à la fois maintenant et lors de la vérification d'une synchronisation terminée. - Sinon, si le delta n'a pas d'exigences AJOUTÉES, signalez qu'aucune synchronisation n'est possible et marquez cette capacité comme bloquée pour la synchronisation. Pour un delta avec uniquement des SUPPRESSIONS, avertissez qu'il n'y a pas de spécification principale à partir de laquelle supprimer et laissez l'arborescence de la spécification principale inchangée.
openspec archiverefuse le cas de SUPPRESSION uniquement non marqué avecSpec must have at least one requirement. - Sinon, comptez la capacité comme nécessitant une synchronisation et nommez-la dans le résumé (
<chemin-de-la-capacité> : une nouvelle spécification principale sera créée). Si le delta a également des exigences SUPPRIMÉES, avertissez qu'elles seront ignorées car il n'y a pas de spécification principale à partir de laquelle supprimer. La synchronisation crée la spécification principale à partir des seules exigences AJOUTÉES du delta, exactement comme le faitopenspec archive.
- Déterminez quels changements seraient appliqués (ajouts, modifications, suppressions, renommages)
- Continuez à évaluer les capacités restantes même lorsqu'une est bloquée pour la synchronisation. Affichez un résumé combiné avant de demander.
Options d'invite :
- Si une capacité est bloquée pour la synchronisation : expliquez pourquoi et proposez uniquement « Archiver sans synchronisation », « Annuler »
- Sinon, si des changements sont nécessaires : « Synchroniser maintenant (recommandé) », « Archiver sans synchronisation »
- Sinon, si déjà synchronisé : « Archiver maintenant », « Synchroniser quand même », « Annuler »
Acheminez en fonction de la réponse :
- « Annuler » — arrêtez, n'archivez pas
- « Archiver sans synchronisation » ou « Archiver maintenant » — procédez à l'archivage
- « Synchroniser maintenant » ou « Synchroniser quand même » — synchronisez, puis vérifiez (ci-dessous). Ne démarrez aucune synchronisation tant qu'une capacité est bloquée pour la synchronisation ; expliquez le blocage et répétez les choix disponibles.
- Autre chose — demandez à nouveau plutôt que d'archiver
Avant qu'une synchronisation sélectionnée n'écrive une spécification principale, exécutez
openspec instructions specs --change "<nom>" --jsonune fois avec les mêmes indicateurs de racine sélectionnée. Exigez un code de sortie zéro et un JSON d'instruction d'artefact valide. Si la recherche échoue ou renvoie un JSON invalide, signalez l'erreur et arrêtez-vous avant d'écrire une spécification principale ou de déplacer le changement. Une réponse valide avec desrulesomises est le cas sans règles. Appliquez lesrulesrenvoyées uniquement au contenu et à la forme des spécifications principales produites par cette fusion ; ne les utilisez pas comme conseil d'archivage, ne modifiez pas le comportement de la CLI et ne copiez pas le texte de la règle dans un fichier de sortie.Exécutez ensuite le workflow
openspec-sync-specsen ligne (fusion intelligente pilotée par agent) pour le changement '', en transmettant l'analyse de la spécification delta et l'instantané des règles de spécifications récupérées ci-dessus, et attendez qu'il se termine. La synchronisation en ligne doit réutiliser cet instantané sans récupérer les instructionsspecsà nouveau. Ne le déléguez pas à une tâche en arrière-plan — l'étape 5 déplaceraitchangeRootsous une synchronisation qui est encore en train de le lire, laissant le changement archivé et les spécifications principales jamais mises à jour. Si votre agent ne peut l'exécuter que par délégation, déléguez de manière synchrone et attendez le résultat.Si la synchronisation signale une condition d'arrêt ou de blocage, traitez la synchronisation comme ayant échoué. Arrêtez immédiatement l'archivage. N'effectuez pas la comparaison de contenu post-synchronisation et ne déplacez pas son
changeRoot. Rien n'a été déplacé, donc l'utilisateur peut corriger la condition de blocage ou réexécuter la synchronisation.Après que la synchronisation a écrit chaque spécification principale, vérifiez sa structure par rapport au contrat de synchronisation canonique :
- Une nouvelle spécification principale commence par un titre
# <capacité> Specification. Une spécification principale existante conserve son titre exactement tel quel. - Conservez les sections
## Purposeexistantes complètement intactes pour les spécifications principales établies. - Pour une nouvelle spécification principale, copiez le
## Purposedu delta textuellement. Avertissez uniquement si le texte de l'objectif est plus court que ce que la validation standard attend. Ne régénérez pas et ne réécrivez pas un objectif créé existant. Si aucun## Purposeutilisable n'est fourni, utilisez le comportement et l'avertissement TBD Purpose existants. - Vérifiez qu'aucun en-tête de section de style delta (
## ADDED Requirements,## MODIFIED Requirements,## REMOVED Requirements,## RENAMED Requirements) ne reste dans la spécification principale, en adhérant strictement aux règles de formatage du workflow de synchronisation. - Les blocs d'exigences que la synchronisation a écrits ou modifiés utilisent des en-têtes
### Requirement:, et leurs scénarios utilisent des en-têtes#### Scenario:, sous la section## Requirementsde la spécification. Laissez le contenu que le delta ne mentionne pas exactement tel quel.
Réexécutez ensuite la comparaison depuis le début de cette étape, y compris le cas de spécification manquante explicitement retiré, pour chaque capacité qui a une spécification delta dans
artifactPaths.specs.existingOutputPaths— pas seulement celles que la synchronisation signale avoir touchées. Une synchronisation réussie ne laisse rien à appliquer, donc chaque capacité doit maintenant être lue comme déjà synchronisée :- Exigences AJOUTÉES présentes
- Exigences MODIFIÉES portant les modifications de scénario et de description nommées dans le delta, avec leurs autres scénarios intacts
- Exigences SUPPRIMÉES disparues — et lorsque cette synchronisation a retiré une capacité (supprimé sa dernière exigence, laissant
## Requirementsvide), sa spécification principale a été supprimée plutôt que laissée vide. - Exigences RENOMMÉES présentes sous le nouveau nom et absentes sous l'ancien
Si la synchronisation a échoué, ou si une capacité ne correspond pas, signalez ce qui diffère et arrêtez-vous — n'archivez pas. Rien n'a été déplacé et
changeRootest intact, donc l'utilisateur peut corriger la discordance ou réexécuter la synchronisation et recommencer l'archivage. - Comparez chaque spécification delta avec sa spécification principale correspondante à
-
Effectuer l'archivage
Créez un répertoire
archivesousplanningHome.changesDirs'il n'existe pas :mkdir -p "<planningHome.changesDir>/archive"Générez le nom cible : utilisez le nom du changement tel quel lorsqu'il commence déjà par un préfixe
AAAA-MM-JJ-; sinon, ajoutez la date actuelle au formatAAAA-MM-JJ-.Utilisez la date actuelle (pas la date de début du changement, sauf si elle est utilisée dans le nom d'origine). Exemple :
2025-03-24-nom-du-changement.Déplacez ensuite
changeRootdans le répertoire d'archive sous le nom cible :mv "<changeRoot>" "<planningHome.changesDir>/archive/<nom-cible>"Confirmez le déplacement en listant les fichiers d'archive :
ls "<planningHome.changesDir>/archive/<nom-cible>/" -
Rapport d'archivage final
Signalez le résultat final à l'utilisateur:
- Confirmez que l'archivage s'est terminé
- Donnez le chemin de l'archive (
<planningHome.changesDir>/archive/<nom-cible>) - Résumez ce qui a été archivé en fonction des informations disponibles (artefacts, spécifications, tâches)
- Signalez tout avertissement ou problème notable qui s'est produit même si le processus s'est terminé