Archivar un cambio completado en el flujo de trabajo experimental.
Selección de almacén: Si el usuario nombra un almacén (un repositorio OpenSpec independiente registrado en esta máquina) o el trabajo reside en uno, ejecuta openspec store list --json para descubrir los IDs de almacén registrados, 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 seleccionado, trata --store <id> como fijo 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 "<name>" --json --store "<id>", no la forma sin ámbito mostrada a continuación. Otros comandos no toman la bandera. Los avisos impresos por los comandos ya llevan la bandera; mantenla en los seguimientos. Sin un almacén, los comandos actúan en 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 escribir un archivo de artefacto), confirma que el proyecto tenga una raíz: ejecuta openspec list --json (con --store <id> cuando se seleccione un almacén, ya que el almacén 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 código no cero, lo cual es esa respuesta en lugar de un CLI roto, así que lee el JSON en lugar de reintentar o solucionarlo.
Un "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 openspec/config.yaml (o config.yml) de este proyecto, el proyecto sí usa OpenSpec a través de un almacén que declara, el cual esta máquina no puede resolver (el almacén no está registrado, o la línea store: está mal formada). No lo trates como no inicializado y omite las ramas a continuación: detente antes de escribir y muestra 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 alcanzó este flujo de trabajo:
- Auto-seleccionado: elegiste este flujo de trabajo tú mismo, sin que el usuario nombre OpenSpec, nombre esta habilidad o ejecute 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 habilidad o ejecutó su comando de barra. Detente antes de escribir y pregunta cómo proceder: configurar este proyecto (
openspec init), apuntar a un almacén que ya tenga (--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 manualmente archivos openspec/, y no dejes que un comando la cree.
<capability-path> 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:
- Inferir del contexto de la conversación si el usuario mencionó un cambio
- Auto-seleccionar si solo existe un cambio activo
- Si es ambiguo, ejecuta
openspec list --jsonpara obtener los cambios disponibles y pide al usuario que seleccione uno
Al solicitar, muestra solo los cambios activos (no archivados). Incluye el esquema utilizado para cada cambio si está disponible.
Siempre anuncia: "Usando cambio: " y cómo sobrescribir (por ejemplo,
/openspec-archive-change <other>).Cargar 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 "<name>" --jsonMantén las mismas banderas de raíz seleccionada en este comando. Esta consulta es consultiva y opcional: solo proporciona entradas de aviso adicionales, por lo que nunca debe bloquear el archivado. Si sale con código no cero o devuelve JSON no válido — por ejemplo, en un CLI anterior que no soporta este comando todavía — continúa el flujo de trabajo de archivo 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 requerida a nivel de aviso: léelo y considéralo, y aplica hechos relevantes del proyecto, convenciones y restricciones. TrataoperationGuidancecomo consejo adicional opcional: léelo y considera cada entrada, y sigue las entradas que sean aplicables y compatibles con el flujo de trabajo de archivo integrado.Mantén ambos campos separados de los pasos integrados, elecciones explícitas del usuario, rutas resueltas, verificaciones CLI y contratos de comando. Si el contexto entra en conflicto con una de esas entradas de control, informa el conflicto y preserva el valor de control. Si la guía no es aplicable o entra en conflicto con una entrada de control, no la sigas y explica por qué. No infieras rutas de reemplazo, avisos omitidos o banderas de cualquiera de los dos campos, y no copies su texto palabra por palabra 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 aviso, no verificaciones ejecutables.
-
Verificar el estado de finalización de artefactos
Ejecuta
openspec status --change "<name>" --jsonpara verificar la finalización de artefactos.Analiza el JSON para entender:
schemaName: El flujo de trabajo que se está utilizandoplanningHome,changeRoot,artifactPaths, yactionContext: contexto de ruta y alcanceartifacts: Lista de artefactos con su estado (done,skipped, u otro)
Si algún artefacto no está ni
doneniskipped(los artefactos omitidos satisfacen el requisito - el cambio declara skip_specs):- Muestra una advertencia listando los artefactos incompletos
- Pide 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 globs. Tareas incompletas =totalTasks - completedTasks.No infieras la finalización de tareas del estado del artefacto o la ausencia de un
tasks.mdde nivel superior. Si la consulta falla, devuelve JSON no válido, omite o duplica el cambio seleccionado, o devuelve conteos 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, incluyendo los no familiares, permanecen incompletos.Si se encuentran tareas incompletas:
- Muestra una advertencia con el conteo de tareas incompletas
- Pide 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ío, continúa sin un aviso 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/<capability-path>/spec.md(usa elplanningHome.rootconsciente del almacén del paso 2, no una ruta de repositorio hardcodeada) - 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 la sincronización 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 cual eliminar y deja el árbol de especificaciones principal 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 que necesita sincronización y nómbrala en el resumen (
<capability-path>: 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 cual 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 aviso:
- 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 (abajo). 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 "<name>" --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 consulta 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 forma de las especificaciones principales producidas por esta fusión; no las uses como guía de archivo, cambio de 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 la especificación delta y la instantánea de reglas de especificaciones obtenida arriba, 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 ejecutarlo por delegación, delega de manera síncrona 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
# <capability> Specification. Una especificación principal existente mantiene su título exactamente como está. - Preserva las secciones
## Purposeexistentes completamente intactas para las especificaciones principales establecidas. - Para una nueva especificación principal, copia el
## Purposedel delta palabra por palabra. 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 por el autor. Si no se proporciona un## Purposeutilizable, usa el comportamiento y advertencia existentes de TBD Purpose. - 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 especificación faltante explícitamente retirada, contra cada capacidad que tenga una especificación delta en
artifactPaths.specs.existingOutputPaths— no solo las que la sincronización informó que tocó. Una sincronización exitosa no deja nada por aplicar, por lo que cada capacidad debe ahora leerse como ya sincronizada:- Requisitos AGREGADOS presentes
- Requisitos MODIFICADOS llevando 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 eliminada en lugar de dejada 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 la discrepancia o volver a ejecutar la sincronización y comenzar el archivo de nuevo. - 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 comienza con un prefijo
YYYY-MM-DD-; de lo contrario, antepone la fecha actual