Archive d'un changement terminé
Archive un changement terminé dans le workflow expérimental.
Sélection du magasin : Si l'utilisateur nomme un magasin (un dépôt OpenSpec autonome enregistré sur cette machine) ou si le travail réside dans un magasin, 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 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 une abréviation : avant de l'exécuter, ajoutez le drapeau. Par exemple, exécutez openspec status --change "<name>" --json --store "<id>", pas la forme non cadrée montrée ci-dessous. Les autres commandes ne prennent pas le drapeau. Les indices imprimés par les commandes portent déjà le drapeau ; 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 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é, lisez donc le JSON au lieu de réessayer ou de contourner.
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 le openspec/config.yaml (ou config.yml) de ce projet, le projet utilise bien OpenSpec via un magasin qu'il déclare, mais que cette machine ne peut pas résoudre (le magasin n'est pas enregistré ou la ligne store: est malformé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 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 :
- Auto-sélectionné : 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 requête, 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.
- Requête explicite 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'ils ont déjà (--store <id>), ou continuer sans OpenSpec pour cette requête. 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.
<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 changement. S'il est 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
- Auto-sélectionnez 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 déjà archivés). Incluez le schéma utilisé pour chaque changement si disponible.
Annoncez toujours : "Utilisation du changement : " et comment le remplacer (par exemple,
/openspec-archive-change <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 planifié la racine, exécutez :
openspec instructions archive --change "<name>" --jsonConservez les mêmes drapeaux de racine sélectionnée sur cette commande. Cette recherche est consultative et optionnelle : 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 un ancien CLI qui ne prend pas encore en charge cette commande – continuez le workflow d'archive sans contexte et sans guide 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 au niveau de l'invite requise : lisez-la et considérez-la, 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'archive 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 le guide est inapplicable ou entre en conflit avec une entrée de contrôle, ne le suivez pas et expliquez pourquoi. N'inférez pas de chemins de remplacement, d'invites ignorées ou de drapeaux à 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 de l'invite, pas des vérifications exécutoires.
-
Vérifier l'état d'achèvement des artefacts
Exécutez
openspec status --change "<name>" --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,skippedou 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 drapeaux 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. Le 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 du statut 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. Le CLI compte uniquement les marqueurs de case à cocherx/Xcomme complets ; les autres marqueurs, y compris les marqueurs non familiers, restent incomplets.Si des tâches incomplètes sont trouvées :
- Affichez un avertissement montrant 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 JSON de statut comme seule source de spécifications delta. Si l'entréespecsest manquante ouexistingOutputPathsest 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/<capability-path>/spec.md(utilisez leplanningHome.roottenant compte du magasin de l'étape 2, pas 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 une 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 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 uniquement SUPPRIMÉ, 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 uniquement SUPPRIMÉ 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é (
<capability-path> : 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 uniquement des exigences AJOUTÉES du delta, exactement comme le faitopenspec archive.
- Déterminez quelles modifications seraient appliquées (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 d'inviter.
Options d'invite :
- Si une capacité est bloquée pour la synchronisation : expliquez pourquoi et proposez uniquement "Archiver sans synchronisation", "Annuler"
- Sinon, si des modifications 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-vous, n'archivez pas
- "Archiver sans synchronisation" ou "Archiver maintenant" — passez à l'archivage
- "Synchroniser maintenant" ou "Synchroniser quand même" — synchronisez, puis vérifiez (ci-dessous). Ne démarrez aucune synchronisation pendant qu'une capacité est bloquée pour la synchronisation ; expliquez le bloqueur et répétez les choix disponibles.
- Tout autre chose — redemandez plutôt que d'archiver
Avant qu'une synchronisation sélectionnée n'écrive une spécification principale, exécutez
openspec instructions specs --change "<name>" --jsonune fois avec les mêmes drapeaux de racine sélectionnée. Exigez un code de sortie zéro et un JSON d'instructions 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 guide d'archive, pour modifier le comportement du CLI, ou pour copier le texte des règles dans un fichier de sortie.Exécutez ensuite le workflow
openspec-sync-specsen ligne (fusion intelligente pilotée par agent) pour le changement '', en passant l'analyse des spécifications 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 à nouveau les instructionsspecs. Ne la déléguez pas à une tâche en arrière-plan – l'étape 5 déplaceraitchangeRootsous une synchronisation qui le lit encore, 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'archive. 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 relancer 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
# <capability> 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 rédigé 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 type 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.
Relancez 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 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 divergence ou relancer la synchronisation et recommencer l'archivage. - Comparez chaque spécification delta avec sa spécification principale correspondante à
-
Effectuer l'archive
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
YYYY-MM-DD-; sinon, préfixez la date actuelle
...