Archivar un cambio completado en el flujo de trabajo experimental.
Selección de tienda: Si el usuario nombra una tienda (una tienda es un repositorio independiente de OpenSpec registrado en esta máquina) o el trabajo reside en una, ejecuta openspec store list --json para descubrir los IDs de tiendas registradas, luego pasa --store <id> en los comandos que leen o escriben especificaciones y cambios (new change, status, instructions, list, show, validate, archive, doctor, context, schemas, view). Una vez seleccionada, trata --store <id> como persistente para el resto del flujo de trabajo. Cada ejemplo sin ámbito de esos comandos a continuación es una abreviatura: antes de ejecutarlo, añade la bandera. Por ejemplo, ejecuta openspec status --change "<nombre>" --json --store "<id>", no la forma sin ámbito que se muestra a continuación. Otros comandos no aceptan la bandera. Las sugerencias impresas por los comandos ya llevan la bandera; mantenla en los seguimientos. Sin una tienda, los comandos actúan sobre la raíz local openspec/ más cercana.
Verificación del proyecto: Estos pasos esperan un proyecto que ya use OpenSpec. Antes del primer paso que escriba algo (new change, archive, sync specs o la creación de un archivo de artefacto), confirma que el proyecto tenga una raíz: ejecuta openspec list --json (con --store <id> cuando se haya seleccionado una tienda, ya que la tienda es entonces la raíz) y lee root. Un objeto raíz significa que el proyecto está configurado. "root": null significa que no lo está; no hay un directorio openspec/ aquí, y una escritura como openspec new change lo crearía como efecto secundario. El comando también sale con un código distinto de cero, lo cual es esa respuesta y no un CLI roto, así que lee el JSON en lugar de reintentar o evitar el problema.
Un caso de "root": null no se trata de configuración: cuando un mensaje de error de status comienza con Declared in o Invalid store declaration in y nombra el openspec/config.yaml (o config.yml) de este proyecto, el proyecto sí usa OpenSpec a través de una tienda que declara, pero esta máquina no puede resolverla (la tienda no está registrada, o la línea store: tiene un formato incorrecto). No lo trates como no inicializado y no omitas las ramas a continuación: detente antes de escribir y muéstrale al usuario el message y fix de ese error.
De lo contrario, sin raíz, lo que sucede a continuación depende de cómo se llegó a este flujo de trabajo:
- Seleccionado automáticamente: elegiste este flujo de trabajo tú mismo, sin que el usuario nombrara OpenSpec, nombrara esta skill o ejecutara su comando de barra. Deja de usar OpenSpec y responde a la solicitud normalmente, como lo harías sin OpenSpec instalado. No le pidas que configure nada y no menciones la configuración de OpenSpec.
- Solicitud explícita de OpenSpec: el usuario nombró OpenSpec, nombró esta skill o ejecutó su comando de barra. Detente antes de escribir y pregunta cómo proceder: configurar este proyecto (
openspec init), apuntar a una tienda que ya tengan (--store <id>), o continuar sin OpenSpec para esta solicitud. Espera su respuesta.
En ambas ramas, nunca crees la raíz como efecto secundario: no ejecutes openspec init hasta que el usuario lo solicite, no crees archivos openspec/ manualmente y no dejes que un comando la cree.
<ruta-de-capacidad> es el directorio de especificaciones relativo a specs/ (por ejemplo, user-auth o identity/user-auth). Conserva la ruta completa de cada especificación delta al resolver su especificación principal.
Entrada: Opcionalmente especifica un nombre de cambio. Si se omite, verifica si se puede inferir del contexto de la conversación. Si es vago o ambiguo, DEBES solicitar los cambios disponibles.
Pasos
-
Seleccionar el cambio
Si se proporciona un nombre, úsalo. De lo contrario:
- Infiere del contexto de la conversación si el usuario mencionó un cambio
- Selecciona automáticamente si solo existe un cambio activo
- Si es ambiguo, ejecuta
openspec list --jsonpara obtener los cambios disponibles y pídele al usuario que seleccione uno
Al solicitar, muestra solo los cambios activos (no archivados aún). Incluye el esquema utilizado para cada cambio si está disponible.
Siempre anuncia: "Usando cambio: " y cómo sobrescribir (ej.,
/opsx:archive <otro>).Cargar las entradas de archivo actuales antes de las verificaciones de archivo existentes:
Después de resolver el cambio seleccionado y planificar la raíz, ejecuta:
openspec instructions archive --change "<nombre>" --jsonMantén las mismas banderas de raíz seleccionada en este comando. Esta búsqueda es de carácter consultivo y opcional: solo proporciona entradas de indicación adicionales, por lo que nunca debe bloquear el archivado. Si sale con un código distinto de cero o devuelve JSON no válido (por ejemplo, en un CLI más antiguo que no soporta este comando aún), continúa el flujo de trabajo de archivado sin contexto y sin guía de operación. No informes un error y no te detengas.
Una respuesta exitosa puede omitir ambos campos opcionales. Trata
contextcomo una entrada de indicación a nivel de indicación requerida: léelo y considéralo, y aplica los hechos, las convenciones y las restricciones relevantes del proyecto. TrataoperationGuidancecomo consejo aditivo opcional: lee y considera cada entrada, y sigue las entradas que sean aplicables y compatibles con el flujo de trabajo de archivado integrado.Mantén ambos campos separados de los pasos integrados, las elecciones explícitas del usuario, las rutas resueltas, las verificaciones del CLI y los contratos de comandos. Si el contexto entra en conflicto con una de esas entradas controladoras, informa el conflicto y conserva el valor controlador. Si la guía no es aplicable o entra en conflicto con una entrada controladora, no la sigas y explica por qué. No infieras rutas de reemplazo, indicaciones omitidas o banderas de ningún campo, y no copies su texto textualmente en especificaciones, artefactos de cambio o resúmenes de archivo a menos que el usuario lo solicite por separado. Estos son contratos de comportamiento a nivel de indicación, no verificaciones exigibles.
-
Verificar el estado de finalización de artefactos
Ejecuta
openspec status --change "<nombre>" --jsonpara verificar la finalización de artefactos.Analiza el JSON para entender:
schemaName: El flujo de trabajo que se está utilizandoplanningHome,changeRoot,artifactPathsyactionContext: contexto de ruta y ámbitoartifacts: Lista de artefactos con su estado (done,skippedu otro)
Si algún artefacto no está ni
doneniskipped(los artefactos omitidos cumplen el requisito: el cambio declaraskip_specs):- Muestra una advertencia listando los artefactos incompletos
- Pídele al usuario que confirme que desea continuar
- Continúa si el usuario confirma
-
Verificar el estado de finalización de tareas
Ejecuta
openspec list --jsoncon las mismas banderas de raíz seleccionada y encuentra la entrada enchangescuyonamecoincida exactamente con el cambio seleccionado. Requiere exactamente una coincidencia y enteros no negativostotalTasksycompletedTasks, concompletedTasks <= totalTasks. El CLI resuelve los archivos de tareas rastreados del esquema, incluyendo nombres de artefactos personalizados, rutas de salida y patrones glob. Tareas incompletas =totalTasks - completedTasks.No infieras la finalización de tareas a partir del estado del artefacto o la ausencia de un
tasks.mdde nivel superior. Si la búsqueda falla, devuelve JSON no válido, omite o duplica el cambio seleccionado, o devuelve recuentos no válidos, informa el problema y detente antes de sincronizar o archivar. El CLI cuenta solo los marcadores de casilla de verificaciónx/Xcomo completos; otros marcadores, incluidos los desconocidos, permanecen incompletos.Si se encuentran tareas incompletas:
- Muestra una advertencia con el recuento de tareas incompletas
- Pídele al usuario que confirme que desea continuar
- Continúa si el usuario confirma
Si
totalTaskses cero: Continúa sin una advertencia relacionada con tareas. -
Evaluar el estado de sincronización de especificaciones delta
Usa
artifactPaths.specs.existingOutputPathsdel JSON de estado como la única fuente de especificaciones delta. Si la entradaspecsfalta oexistingOutputPathsestá vacía, continúa sin una solicitud de sincronización y no infieras especificaciones delta de otros artefactos.Si existen especificaciones delta:
- Compara cada especificación delta con su especificación principal correspondiente en
<planningHome.root>/openspec/specs/<ruta-de-capacidad>/spec.md(usa elplanningHome.rootconsciente de la tienda del paso 2, no una ruta de repositorio codificada). - Una especificación principal faltante no es automáticamente "ya sincronizada". Para una nueva capacidad, la especificación principal es una salida de la sincronización, no una entrada:
- Si el delta tiene requisitos MODIFICADOS o RENOMBRADOS, informa que solo los requisitos AGREGADOS pueden crear una nueva especificación principal y marca esa capacidad como bloqueada para sincronización. Nunca inventes un requisito que no tenga una versión actual.
- De lo contrario, si el delta tiene solo requisitos ELIMINADOS y el
.openspec.yamldel cambio declararetire_capabilities: true, la capacidad ya está retirada: cuéntala como ya sincronizada, advierte que no queda nada que eliminar y no recrees la especificación principal. Aplica esta regla tanto ahora como al verificar una sincronización completada. - De lo contrario, si el delta no tiene requisitos AGREGADOS, informa que no es posible sincronizar y marca esa capacidad como bloqueada para sincronización. Para un delta solo con ELIMINADOS, advierte que no hay una especificación principal de la que eliminar y deja el árbol de especificaciones principales sin cambios.
openspec archiverechaza el caso solo con ELIMINADOS no marcado conSpec must have at least one requirement. - De lo contrario, cuenta la capacidad como necesitada de sincronización y nómbrala en el resumen (
<ruta-de-capacidad>: se creará una nueva especificación principal). Si el delta también tiene requisitos ELIMINADOS, advierte que serán ignorados porque no hay una especificación principal de la que eliminar. La sincronización crea la especificación principal solo a partir de los requisitos AGREGADOS del delta, exactamente como lo haceopenspec archive.
- Determina qué cambios se aplicarían (adiciones, modificaciones, eliminaciones, renombres)
- Continúa evaluando las capacidades restantes incluso cuando una está bloqueada para sincronización. Muestra un resumen combinado antes de solicitar.
Opciones de solicitud:
- Si alguna capacidad está bloqueada para sincronización: explica por qué y ofrece solo "Archivar sin sincronizar", "Cancelar"
- De lo contrario, si se necesitan cambios: "Sincronizar ahora (recomendado)", "Archivar sin sincronizar"
- De lo contrario, si ya está sincronizado: "Archivar ahora", "Sincronizar de todos modos", "Cancelar"
Enruta según la respuesta:
- "Cancelar" — detente, no archives
- "Archivar sin sincronizar" o "Archivar ahora" — procede a archivar
- "Sincronizar ahora" o "Sincronizar de todos modos" — sincroniza, luego verifica (a continuación). No inicies ninguna sincronización mientras una capacidad esté bloqueada para sincronización; explica el bloqueador y repite las opciones disponibles.
- Cualquier otra cosa — pregunta de nuevo en lugar de archivar
Antes de que una sincronización seleccionada escriba cualquier especificación principal, ejecuta
openspec instructions specs --change "<nombre>" --jsonuna vez con las mismas banderas de raíz seleccionada. Requiere un estado de salida cero y JSON de instrucciones de artefacto válido. Si la búsqueda falla o devuelve JSON no válido, informa el error y detente antes de escribir cualquier especificación principal o mover el cambio. Una respuesta válida conrulesomitido es el caso sin reglas. Aplica lasrulesdevueltas solo al contenido y la forma de las especificaciones principales producidas por esta fusión; no las uses como guía de archivo, cambies el comportamiento del CLI ni copies el texto de la regla en ningún archivo de salida.Luego ejecuta el flujo de trabajo
openspec-sync-specsen línea (fusión inteligente impulsada por agente) para el cambio '', pasando el análisis de especificaciones delta y la instantánea de reglas de especificaciones obtenida anteriormente, y espera a que termine. La sincronización en línea debe reutilizar esa instantánea sin obtener las instrucciones despecsnuevamente. No la delegues a una tarea en segundo plano: el paso 5 moveríachangeRootdebajo de una sincronización que todavía lo está leyendo, dejando el cambio archivado y las especificaciones principales nunca actualizadas. Si tu agente solo puede ejecutarla mediante delegación, delegala de forma sincrónica y espera el resultado.Si la sincronización informa alguna condición de detención o bloqueo, trata la sincronización como fallida. Detén el archivo inmediatamente. No realices la comparación de contenido posterior a la sincronización y no muevas su
changeRoot. Nada se ha movido, por lo que el usuario puede corregir la condición de bloqueo o volver a ejecutar la sincronización.Después de que la sincronización escriba cada especificación principal, verifica su estructura contra el contrato de sincronización canónico:
- Una nueva especificación principal comienza con un título
# <capacidad> Especificación. Una especificación principal existente mantiene su título exactamente como está. - Conserva las secciones
## Propósitoexistentes completamente intactas para las especificaciones principales establecidas. - Para una nueva especificación principal, copia el
## Propósitodelta textualmente. Advierte solo si el texto del propósito es más corto de lo que la validación estándar espera. No regeneres ni reescribas el propósito existente creado. Si no se proporciona un## Propósitoutilizable, usa el comportamiento y la advertencia de Propósito TBD existentes. - Verifica que no queden encabezados de sección de estilo delta (
## ADDED Requirements,## MODIFIED Requirements,## REMOVED Requirements,## RENAMED Requirements) en la especificación principal, adhiriéndose estrictamente a las reglas de formato del flujo de trabajo de sincronización. - Los bloques de requisitos que la sincronización escribió o cambió usan encabezados
### Requirement:y sus escenarios usan encabezados#### Scenario:, bajo la sección## Requirementsde la especificación. Deja el contenido que el delta no menciona exactamente como está.
Luego vuelve a ejecutar la comparación desde el inicio de este paso, incluyendo el caso de retiro explícito y especificación faltante, contra cada capacidad que tenga una especificación delta en
artifactPaths.specs.existingOutputPaths— no solo las que la sincronización informa que tocó. Una sincronización exitosa no deja nada por aplicar, por lo que cada capacidad ahora debe leerse como ya sincronizada:- Requisitos AGREGADOS presentes
- Requisitos MODIFICADOS que llevan los cambios de escenario y descripción nombrados en el delta, con sus otros escenarios intactos
- Requisitos ELIMINADOS desaparecidos — y donde esta sincronización retiró una capacidad (eliminó su último requisito, dejando
## Requirementsvacío), su especificación principal se eliminó en lugar de dejarse vacía. - Requisitos RENOMBRADOS presentes bajo el nuevo nombre y ausentes bajo el antiguo
Si la sincronización falló, o cualquier capacidad no coincide, informa qué difiere y detente — no archives. Nada se ha movido y
changeRootestá intacto, por lo que el usuario puede corregir el desajuste o volver a ejecutar la sincronización y comenzar el archivo nuevamente. - Compara cada especificación delta con su especificación principal correspondiente en
-
Realizar el archivo
Crea un directorio
archivebajoplanningHome.changesDirsi no existe:mkdir -p "<planningHome.changesDir>/archive"Genera el nombre de destino: usa el nombre del cambio tal cual cuando ya comience con un prefijo
YYYY-MM-DD-; de lo contrario, antepone la fecha actual como `YYYY-
…
[truncado para traducción]