Curso práctico de specs: skills y agentes en cada etapa

¿Tienes 10 minutos? Empieza por la ruta exprés: tu primer ciclo completo, con tu primera skill y tu primer agente. ¿Quieres llegar a experto? Sigue con las misiones: un caso guiado de punta a punta con Spec Kit y OpenSpec que incluye los temas avanzados, como el trabajo en paralelo, el drift, el legacy y la modernización. Poca teoría: haces, pegas el prompt y compruebas.

Comandos, archivos y salidas medidos el 2026-10-18 con Spec Kit 1.2.1 y OpenSpec 1.14.3. Lo de subagentes y hooks de Cursor sale de su documentación, consultada el 18-oct-2026.

10 min

Ruta exprés: tu primer ciclo completo

Cursor + OpenSpec · cinco pasos de copiar y pegar

Al terminar vas a tener un cambio propuesto, validado, implementado, revisado por un agente y archivado, más tu primera skill y tu primer agente. Eso no te hace experto, pero te pone el ciclo completo en la mano. Lo experto viene en las misiones.

Antes: Cursor abierto y Node 20.19 o más (node --version). Los comandos de terminal tardan segundos medido; lo que más tarda es que el agente escriba estimado.

  1. Haz
    npm install -g @fission-ai/openspec@1.14.3
    mkdir -p ~/lab-expres && cd ~/lab-expres && git init -b main
    openspec init --tools cursor --language es
    git add -A && git commit -m "Base: OpenSpec"
    cursor .
    Debes ver medido
    $ openspec init --tools cursor --language es
    ▌ OpenSpec structure created
    ✔ Setup complete for Cursor
    
    OpenSpec Setup Complete
    
    Created: Cursor
    6 skills and 6 commands in .cursor/
    Config: openspec/config.yaml (schema: spec-driven)
    
    Getting started:
      Start your first change: /opsx-propose "your idea"
    
    Note: 6 more workflows are available (new, continue, ff, bulk-archive, verify, onboard).
    Add them with `openspec config profile`.
    
    Learn more: https://github.com/Fission-AI/OpenSpec
    Feedback:   https://github.com/Fission-AI/OpenSpec/issues
    
    Restart your IDE to refresh commands.
  2. Haz (en la terminal, dentro de ~/lab-expres; es un solo bloque)
    mkdir -p .cursor/skills/revisar-spec
    cat > .cursor/skills/revisar-spec/SKILL.md <<'FIN_DEL_ARCHIVO'
    ---
    name: revisar-spec
    description: Revisa una spec de Spec Kit o de OpenSpec sin editarla y señala requisitos que no se pueden probar, palabras ambiguas, requisitos sin escenario, tecnología que se coló y criterios de éxito sin número. Usar después de especificar y antes de planear, o cuando pidan revisar una spec.
    ---
    
    # Revisar una spec
    
    Sólo lees. No edites ningún archivo.
    
    1. Ubica la spec: la ruta que te den; si no, `.specify/feature.json` (Spec Kit) o el cambio activo de `openspec list` (OpenSpec).
    2. Revisa cada requisito:
       - ¿Se puede probar con un escenario concreto? Si no, es un hallazgo.
       - ¿Usa palabras sin número («rápido», «fácil», «adecuado», «robusto», «intuitivo»)?
       - ¿Tiene al menos un escenario? En OpenSpec, ¿lleva SHALL o MUST y escenarios con cuatro `#`?
       - ¿Menciona clases, tablas, librerías o frameworks? Eso va en el plan o en el diseño.
    3. Revisa los criterios de éxito: cada uno con número y sin tecnología.
    4. Entrega una tabla `ubicación | problema | propuesta`, de lo más grave a lo menos grave.
    5. Termina con una línea: «Lista para planear» o «Necesita cambios (N hallazgos)».
    FIN_DEL_ARCHIVO
    mkdir -p .claude/agents
    cat > .claude/agents/revisor-conformidad.md <<'FIN_DEL_ARCHIVO'
    ---
    name: revisor-conformidad
    description: Revisa, sólo leyendo, si el cambio de la rama cumple su spec requisito por requisito (implementado, con prueba que cita su ID, criterio cumplido), qué se coló fuera de la spec y si alguna prueba se apagó, se aflojó o se borró. Usar antes de abrir el PR o con /conformidad. No edita nada.
    tools: Read, Grep, Glob, Bash
    readonly: true
    ---
    
    # Revisor de conformidad
    
    No escribiste este código: lo revisas contra su spec. Sólo lees. Bash es sólo para `git` y `rg`.
    
    ## Cómo revisas
    
    1. Lista los requisitos de la spec: los `FR-###` de Spec Kit, o los `### Requirement:` de OpenSpec con sus escenarios.
    2. Lee el diff: `git diff --stat <base>...HEAD`, `git diff <base>...HEAD` y lo que no tiene commit.
    3. Por cada requisito: ¿el diff lo implementa? (cita `archivo:línea`). ¿Qué prueba lo cita en su nombre? ¿Se cumple su criterio?
    4. Al revés: ¿qué cambios del diff no rastrean a ningún requisito? Repórtalos aunque sean un refactor válido.
    5. Busca pruebas apagadas, aflojadas o borradas: `@Disabled`, `@Ignore`, `.skip`, aserciones borradas o comentadas, un valor concreto que pasó a `any()`.
    6. Revisa que el diff no rompa una regla de `AGENTS.md`, de la constitución o de `openspec/config.yaml`.
    7. Por cada firma pública que cambió, busca con `rg` quién la llama fuera del diff.
    
    ## Reglas
    
    - Todo hallazgo lleva `archivo:línea`. Si no lo puedes citar, no lo afirmes.
    - Máximo 3 bloqueantes, en orden de gravedad. No comentes estilo ni rediseñes.
    - Si te falta la spec o la base, dilo y para.
    
    ## Salida
    
    ```
    ## Conformidad: NO LISTO | LISTO CON PENDIENTES | LISTO PARA PR
    
    | Requisito | ¿Implementado? | Prueba | ¿Criterio cumplido? |
    |---|---|---|---|
    
    Fuera de la spec: …
    Pruebas apagadas, aflojadas o borradas: …
    Reglas rotas: …
    
    ### Bloqueantes (máximo 3)
    1. `archivo:línea` — qué pasa, por qué importa y cómo se arregla.
    ```
    FIN_DEL_ARCHIVO
    Debes ver

    Dos archivos: la skill revisar-spec, que revisa una spec, y el agente revisor-conformidad, de sólo lectura, que revisa el código contra la spec. El bloque está probado: crea los archivos idénticos a los de la misión 5. Abre un chat nuevo para que Cursor los vea.

  3. Pega (en el chat de Cursor)
    /opsx-propose bloquear-marcas: Gobierno de Datos puede bloquear una marca, y el alta de productos de una marca bloqueada se rechaza con el código MARCA_BLOQUEADA. Fuera de alcance: bajar lo ya publicado. Un comportamiento por requisito, cada uno con un escenario feliz y uno de error.

    Y después:

    /revisar-spec openspec/changes/bloquear-marcas
    Comprueba (en la terminal)
    $ openspec validate bloquear-marcas --strict
    Change 'bloquear-marcas' is valid
    $ echo $?
    0
  4. Pega
    /opsx-apply bloquear-marcas

    Cuando termine:

    Usa el subagente revisor-conformidad para revisar este cambio contra openspec/changes/bloquear-marcas, con base main.
    Debes ver

    Un veredicto (LISTO PARA PR, LISTO CON PENDIENTES o NO LISTO) con una fila por requisito. Si dice NO LISTO, pide que se arregle y repite la revisión.

  5. Pega
    /opsx-archive bloquear-marcas
    Comprueba medido (el nombre de la capacidad lo elige el agente; el tuyo puede ser otro)
    $ openspec list --specs
    Specs:
      bloqueo-de-marcas     requirements 2

Lo lograste. Recorriste cinco etapas del mapa: especificar, revisar con una skill, implementar, pasar la conformidad con un agente y archivar. Para llegar a experto te falta esto, y aquí se practica:

  • La base del repo: reglas, contexto y mapa de specs → misión 1.
  • Spec Kit para servicios nuevos: constitución, clarify, plan, checklists y analyze → misiones 2 a 5.
  • Un hook que bloquea saltarse pruebas → misión 4.
  • Verify, drift y candados en CI → misiones 6 y 8.
  • Varios cambios a la vez con worktrees e integración por riesgo → misión 7.
  • Legacy sin spec y modernización por módulos → misiones 9 y 10.

Cómo funciona

Vas a construir un servicio de catálogo de marcas en un repo de práctica. Nace con Spec Kit, recibe cambios con OpenSpec y lo cuidan agentes de revisión. Al final rescatas un módulo viejo sin documentar y lo modernizas. Después de la ruta exprés vienen las misiones 0 a 10, de 10 a 30 minutos cada una.

Cada tarea tiene una casilla, y tu avance se guarda en este navegador. Dentro de cada tarea vas a ver:

Haz

Lo que haces tú, en la terminal o en el chat.

Pega

El prompt exacto, con botón de copiar.

Debes ver

Lo que tiene que aparecer: archivos, salidas o un informe.

Comprueba

Un comando que confirma que salió bien antes de seguir.

Los recuadros Taller son donde escribes tus propias skills, agentes y hooks. La teoría va plegada en «¿Por qué?»: ábrela si la necesitas.

Lo mínimo de teoría

Spec

Qué debe hacer el sistema y por qué, sin decir cómo. Se escribe antes que el código y manda sobre él.

Requisito y escenario

Una regla que se puede probar (FR-002 o ### Requirement:) y un ejemplo concreto que la prueba. Cada escenario se vuelve una prueba.

Cambio y delta (OpenSpec)

Un cambio propone qué se agrega, modifica o quita en la spec viva del sistema. Al archivarlo, la spec viva se actualiza.

Skill

Una carpeta con SKILL.md: un procedimiento que el agente sigue en tu misma conversación, cuando aplica o cuando escribes /nombre.

Agente (subagente)

Otro agente con su propio contexto, limpio. Sólo le devuelve al principal su mensaje final. Sirve para revisar sin sesgo, investigar mucho o trabajar en paralelo.

Hook

Un script que se dispara en un evento (antes de un comando, antes de editar) y puede bloquearlo. Es el candado que no depende de la buena voluntad del agente.

Cómo leer las etiquetas

Medido lo corrimos y es la salida real. Simulado lo escribimos como lo haría el agente, sobre las plantillas reales; los ejemplos de OpenSpec además pasaron su validador estricto. Citado lo dice la documentación oficial o la regla de un equipo. Inferido es una deducción nuestra.

El mapa: qué skill, agente o hook en cada etapa

Ésta es la tabla que vas a usar todo el curso. Cada fila es una etapa del trabajo con specs; cada misión te dice en qué filas estás. Filtra por flujo:

EtapaQué hacesSkill o comandoAgente (contexto aparte)CandadoMisión
Base del repoReglas, contexto, constitución, mapa de specs y config.yaml, una vez y en su propio PRspecify init, openspec init, /speckit-constitution—La base va primero y en secuencia0, 1
EntenderInvestigar el código y las specs vivas antes de proponer/opsx-exploreOpcional: un explorador de sólo lecturaNo escribe código6
EspecificarEl qué y el porqué/speckit-specify · /opsx-propose o /opsx-new + /opsx-continue · tu skill revisar-spec—🛑 Apruebas la spec2, 6
AclararCerrar huecos antes de planear/speckit-clarify · en OpenSpec, el prompt de ambigüedades—Lo que nadie sabe queda como pregunta2, 6
Revisión cruzada¿Choca con otras specs en curso?Lo pides tú, sólo si hay specs en paralelorevision-cruzada, de sólo lecturaUn concepto, una spec dueña7
PlanearEl cómo/speckit-plan (en OpenSpec, design.md)—La constitución o config.yaml como compuerta3
Tareas y análisisPartir el trabajo y revisar que todo cuadre/speckit-tasks, /speckit-analyze—🛑 Cero CRITICAL3
ImplementarProgramar contra las tareas, con las pruebas primero/speckit-implement, /opsx-apply—Tu hook no-saltar-pruebas4, 6
Verificar¿El código cumple lo que dicen los artefactos?Pruebas, revisión requisito → prueba, /speckit-converge, /opsx-verify—Ningún CRITICAL antes de cerrar4, 6
ConformidadRevisión independiente antes del PRTu skill /conformidadrevisor-conformidad, de sólo lecturaQuien implementó no se revisa5
Trabajar en paraleloVarios cambios a la vez, cada uno en su worktree, y juntarlos al finalgit worktree y el prompt de integraciónUn agente por worktreeLa base no se paraleliza; se integra por orden de riesgo7
EntregarPR con la tabla de conformidadgh pr create—🛑 CI verde, análisis de seguridad y revisión humana5
ArchivarFusionar el cambio en la spec viva/opsx-archive, /opsx-bulk-archive—openspec validate --archived en CI6, 7
Mantener¿Spec y código siguen diciendo lo mismo?La pides cada semanaauditor-drift, de sólo lectura y en sesión nuevaDecide una persona: regularizar, corregir o escalar8
Entender un legacyReconstruir qué hace hoy, con evidencia, sin tocarloPrompts de reconocimiento, anomalías y entrevistaUn investigador de sólo lectura🛑 2 de 3 testigos; no se inventan respuestas de negocio9
ModernizarReemplazar por módulos sin cambiar el comportamiento/speckit-specify (spec de sustitución), specs delta—🛑 Tres anillos de equivalencia en verde10

Los tres niveles de SDD: ¿qué pasa con la spec al terminar?

NivelQué pasa con la specHerramientaEn este curso
Spec-firstUna spec por feature. Sirve para construirla, se cierra y queda como un capítulo del libro; lo nuevo va en otra specSpec Kit: por eso numera las specs y crea una rama por specMisiones 1 a 5
Spec-anchoredUna spec viva por capacidad, que cada cambio modifica: es el contrato de la aplicación. Su gran reto es el driftOpenSpecMisiones 6 a 8
Spec-as-sourceUna spec por archivo de código. Sólo se tocan las specs, y una herramienta genera el código a partir de ellasHerramientas todavía en desarrolloSólo se explica

El curso de SDD que sigue el equipo recomienda spec-first como el más mantenible en entornos profesionales, porque mantener una sola spec viva en el tiempo exige mucho cuidado; los otros dos siguen siendo válidos curso de SDD, sección 5. Aquí se usan los dos primeros según la vida del servicio: spec-first mientras nace y spec-anchored cuando ya vive.

La regla para decidir: ¿skill, agente, regla o hook?

Si necesitas…UsaEn el curso
Que algo pase siempre, aunque el agente no quieraHookno-saltar-pruebas
Contexto que aplica a todo el repo, en cada turnoRegla: AGENTS.md, la constitución o config.yamlStack fijo y no negociables
Un procedimiento corto y repetible que el agente use cuando apliqueSkillrevisar-spec
Lo mismo, pero sólo cuando tú lo pidasSkill con disable-model-invocation: true/conformidad
Ojos frescos, revisar el trabajo de otro, una investigación larga o trabajo en paraleloAgente, de sólo lectura si revisarevisor-conformidad, auditor-drift

La documentación de Cursor da la misma regla: un subagente sirve para aislar una investigación larga, correr trabajo en paralelo o verificar de forma independiente; si la tarea es simple, como «generar un changelog», usa una skill cursor.com/docs/subagents.

Misión 0

Arma tu laboratorio

10 minutos · un repo de práctica con las dos herramientas

  1. Haz
    git --version && uv --version && node --version
    Comprueba

    Node debe ser 20.19 o más. Con Node 18, OpenSpec ni arranca: responde SyntaxError: Unexpected token 'with' medido. Si te falta uv, instálalo con su instalador oficial (docs.astral.sh/uv).

  2. Haz
    uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@v1.2.1
    npm install -g @fission-ai/openspec@1.14.3
    specify --version && openspec --version
    Debes ver

    specify 1.2.1 y 1.14.3 medido. Si specify no se encuentra, corre uv tool update-shell y abre otra terminal.

  3. Haz
    mkdir -p ~/lab-specs && cd ~/lab-specs && git init
    specify init --here --force --integration cursor-agent --script sh
    openspec init --tools cursor --language es

    En Cursor se invocan /speckit-… y /opsx-….

    Comprueba

    Existen .specify/ y openspec/. Spec Kit pide --force porque la carpeta ya tiene .git: sin él, en modo no interactivo se niega medido.

  4. El perfil por defecto trae 6 flujos; el curso usa también new, continue, ff, verify y bulk-archive. Es configuración global de tu máquina, y openspec update regenera los archivos del repo.

    Haz
    openspec config set profile custom
    openspec config set workflows '["propose","explore","new","continue","apply","update","ff","sync","archive","bulk-archive","verify","onboard"]'
    openspec update
    Debes ver
    $ openspec update
    Updating 2 tool(s): claude (1.14.3 → 1.14.3), cursor (1.14.3 → 1.14.3)
    
    ✔ Updated Claude Code
    ✔ Updated Cursor
    
    ✓ Updated: Claude Code, Cursor (v1.14.3)
    Tools: Claude Code, Cursor
    
    Restart your IDE to refresh commands.
    Comprueba
    ls .cursor/skills | wc -l      # 10 de Spec Kit + 12 de OpenSpec = 22
    git add -A && git commit -m "Laboratorio: Spec Kit y OpenSpec"

    Reinicia el IDE o abre un chat nuevo para que aparezcan los comandos.

Misión 1

La base del repo

15 minutos · las reglas que todo agente lee

Aquí no hace falta ni skill ni agente: son reglas. Las lee cualquier agente, en cada turno.

  1. Haz

    Crea AGENTS.md en la raíz y, para Claude Code, un CLAUDE.md que sólo diga @AGENTS.md. Así hay una sola copia de las reglas. En este workspace, Cursor aplica los dos archivos como reglas del proyecto observado.

    # AGENTS.md — reglas del repo para cualquier agente
    
    ## Stack (fijo; no se renegocia en una propuesta)
    - Java 21, Spring Boot 3.3 WebFlux y MongoDB. Pruebas: JUnit 5 y Testcontainers.
    
    ## No negociables
    - La spec primero: nada de código sin una spec o un cambio aprobado. Servicio que nace → Spec Kit (`specs/`); servicio que ya vive → OpenSpec (`openspec/`).
    - Cada requisito tiene una prueba que lo cita en su nombre (`FR-002: …`, o el nombre del escenario en OpenSpec).
    - Prohibido saltarse o apagar pruebas para llegar a verde. Lo bloquea un hook.
    - Sin secretos en el código, en los logs ni en las pruebas.
    
    ## Cómo trabajas aquí
    - Si falta información para un paso, para y pregunta; no adivines.
    - Un cambio = una rama. No toques código fuera del alcance del cambio.
    - Si a mitad de camino algo de la spec está mal, corrige el artefacto (spec, design o tasks), no el código por fuera.
    - Antes del PR: corre todas las pruebas y pide la revisión de conformidad (`/conformidad`).
    
    ## Dónde está cada cosa
    - Contexto del negocio: `contexto-proyecto.md`. Mapa de specs del equipo: `specs/README.md`.
    - Reglas de OpenSpec: `openspec/config.yaml`. Constitución de Spec Kit: `.specify/memory/constitution.md`.
    Taller: tus reglas

    Cambia el stack por el tuyo y deja máximo diez líneas de «no negociables». Cada línea se paga en cada turno, y una regla que nadie puede verificar («código limpio») no sirve.

  2. Haz

    Uno solo para todo el repo. Las specs lo heredan; no se recrea por feature.

    # Contexto del proyecto
    
    **Qué es:** el servicio de catálogo de marcas. Gobierno de Datos administra las marcas; los sistemas que dan de alta productos consultan si una marca se puede usar.
    
    **Quién lo usa:** Gobierno de Datos (administra), Compras (consulta) y los vendedores, que dan de alta productos desde otro sistema.
    
    **Términos:** marca activa, inactiva o bloqueada. «Alta» es crear un producto.
    
    **Qué NO hace:** no guarda productos ni precios, y no tiene pantalla propia.
    
    **Quién decide:** las reglas de negocio, Gobierno de Datos; la arquitectura, el arquitecto del equipo.
  3. Pega
    /speckit-constitution Proyecto: servicio de catálogo de marcas.
    Principios:
    1. La spec manda: no se programa nada sin spec aprobada.
    2. Pruebas primero (no negociable): cada FR tiene una prueba que lo cita en su nombre.
    3. Contratos antes que implementación: OpenAPI en contracts/.
    4. Errores RFC 7807 con un código de negocio estable.
    5. Lo más simple que cumpla; toda complejidad extra se justifica en el plan.
    Restricciones: Java 21, Spring Boot 3.3, MongoDB, inyección por constructor, ningún secreto en el repo.
    Escribe el contenido en español y deja los encabezados de la plantilla como están.
    Debes ver

    .specify/memory/constitution.md sin marcadores entre corchetes, con versión 1.0.0 y un «Sync Impact Report» arriba simulado. Ábrelo en el explorador de la misión 3, etapa 2.

  4. Haz

    specs/README.md es el único lugar donde el equipo ve qué está especificado, quién es dueño de cada concepto y qué se decidió no hacer.

    # Mapa de Specs
    
    Índice versionado del equipo: qué se especificó, en qué estado va y quién es dueño de cada concepto.
    Se actualiza al abrir un feature (`prevista` o `en curso`) y al cerrarlo (`publicada`).
    
    | # | Nombre | Qué aporta | Estado | Dueño | Depende de | Rama |
    |---|---|---|---|---|---|---|
    | 001 | catalogo-de-marcas | Alta, consulta, desactivación e historial de marcas | prevista | dev A | — | — |
    
    > Estados: `prevista` · `en curso` · `publicada` · `sustituye a NNN`.
    
    ## Conceptos con dueño
    
    Cada concepto lo define una sola spec; las demás la citan. Si dos lo definen distinto, corre la revisión cruzada.
    
    - (todavía ninguno)
    
    ## Fuera de alcance acumulado
    
    - (todavía nada)
  5. Haz

    Reemplaza openspec/config.yaml. context va en todos los artefactos que genera OpenSpec; rules, sólo en el artefacto de su sección. Fija ahí el stack: sin él, cada design.md puede proponer uno distinto.

    schema: spec-driven
    
    # context se inyecta en TODOS los artefactos que genera OpenSpec: que sea corto.
    context: |
      Catálogo de marcas: administra las marcas que se pueden usar al dar de alta productos.
      Language: es
      All artifacts must be written in es.
      Keep OpenSpec structural headings and SHALL/MUST keywords in English.
    
      Stack técnico (fijado; no se renegocia en propuestas):
      - Java 21 + Spring Boot 3.3 WebFlux; MongoDB.
      - Pruebas: JUnit 5 + Testcontainers. Cada escenario tiene una prueba que se llama como el escenario.
    
      Principios innegociables:
      1. La spec es la fuente de verdad: lo que openspec/specs/ no describe es un defecto, aunque funcione.
      2. Lo más simple que cumpla.
      3. Una marca nunca se borra: se desactiva o se bloquea.
    
    # rules sólo se inyecta al generar ese artefacto.
    rules:
      proposal:
        - Incluye siempre qué NO cambia.
        - Registra cada decisión de negocio con su fecha y quién la tomó.
      specs:
        - Si la capacidad ya existe en openspec/specs/, modifícala (MODIFIED); no la dupliques con ADDED.
        - Reutiliza los términos de las specs vivas; no inventes sinónimos.
      design:
        - Ninguna dependencia nueva sin justificación escrita (ADR en estado Proposed).
    Comprueba
    openspec new change prueba-reglas
    openspec instructions specs --change prueba-reglas
    rm -rf openspec/changes/prueba-reglas
    Debes ver

    Tu context y las rules de specs dentro de las instrucciones que recibe el agente medido:

    $ openspec instructions specs --change prueba-reglas
    (…)
    <project_context>
    <!-- This is background information for you. Do NOT include this in your output. -->
    Catálogo de marcas: administra las marcas que se pueden usar al dar de alta productos.
    Language: es
    All artifacts must be written in es.
    Keep OpenSpec structural headings and SHALL/MUST keywords in English.
    
    Stack técnico (fijado; no se renegocia en propuestas):
    - Java 21 + Spring Boot 3.3 WebFlux; MongoDB.
    - Pruebas: JUnit 5 + Testcontainers. Cada escenario tiene una prueba que se llama como el escenario.
    
    Principios innegociables:
    1. La spec es la fuente de verdad: lo que openspec/specs/ no describe es un defecto, aunque funcione.
    2. Lo más simple que cumpla.
    3. Una marca nunca se borra: se desactiva o se bloquea.
    </project_context>
    
    <rules>
    <!-- These are constraints for you to follow. Do NOT include this in your output. -->
    - Si la capacidad ya existe en openspec/specs/, modifícala (MODIFIED); no la dupliques con ADDED.
    - Reutiliza los términos de las specs vivas; no inventes sinónimos.
    </rules>
    (…)
  6. Haz
    git switch -c base-del-repo
    git add -A && git commit -m "Base del repo: reglas, contexto, constitución, mapa de specs y config de OpenSpec"
    ¿Por qué en su propio PR?

    Si dos devs arman la base a la vez dentro de sus features, quedan dos constituciones o dos AGENTS.md que no se fusionan bien. La base va primero y en secuencia; los features arrancan cuando se integra regla del kit de un equipo.

Misión 2

Especifica con Spec Kit y estrena tu primera skill

25 minutos · el qué y el porqué, y una skill que lo revisa

Usas: las skills /speckit-specify y /speckit-clarify, la extensión git de Spec Kit si la quieres, y escribes tu skill revisar-spec.

  1. Spec Kit se amplía con extensiones: paquetes que agregan comandos y hooks que corren antes o después de cada comando. La extensión git crea la rama de la feature antes de especificar y puede hacer commit antes y después de cada fase.

    Haz (si la quieres)
    specify extension add git
    specify extension list
    Debes ver medido
    $ specify extension list
    
    Installed Extensions:
    
      ✓ Git Branching Workflow (v1.0.1)
         git
         Feature branch creation, numbering (sequential/timestamp), templating,
    validation, and Git remote detection
         Commands: 5 | Hooks: 18 | Priority: 10 | Status: Enabled

    Sus 18 hooks quedan en .specify/extensions.yml. optional: false quiere decir que el agente debe correrlo; con true, te pregunta medido:

    before_constitution: speckit.git.initialize optional: false
    before_specify: speckit.git.feature optional: false
    before_clarify: speckit.git.commit optional: true
    before_plan: speckit.git.commit optional: true
    before_tasks: speckit.git.commit optional: true
    before_implement: speckit.git.commit optional: true
    before_checklist: speckit.git.commit optional: true
    before_analyze: speckit.git.commit optional: true
    before_taskstoissues: speckit.git.commit optional: true
    after_constitution: speckit.git.commit optional: true
    after_specify: speckit.git.commit optional: true
    after_clarify: speckit.git.commit optional: true
    after_plan: speckit.git.commit optional: true
    after_tasks: speckit.git.commit optional: true
    after_implement: speckit.git.commit optional: true
    after_checklist: speckit.git.commit optional: true
    after_analyze: speckit.git.commit optional: true
    after_taskstoissues: speckit.git.commit optional: true

    El autocommit viene apagado. Se enciende en .specify/extensions/git/git-config.yml: pon auto_commit.default en true y el enabled de cada comando que quieras. Ahí también se ajusta el nombre de la rama a la convención del equipo con branch_template o branch_prefix medido el archivo. Un ejemplo simulado:

    branch_template: "feature/{number}-{slug}"   # el último tramo debe empezar con {number}-
    auto_commit:
      default: true
      before_plan:
        enabled: true

    Los hooks de Spec Kit no son candados. Son instrucciones que el agente lee en cada comando, y el curso de SDD muestra que a veces no se ejecutan curso de SDD, sección 4. Lo que no puede fallar va en un hook del agente (misión 4) o en el CI.

    Si no la quieres, por ejemplo porque tu equipo ya tiene su convención de ramas, apágala y crea tú la rama en la tarea siguiente medido:

    $ specify extension disable git
    ✓ Extension 'Git Branching Workflow' disabled
    
    Commands will no longer be available. Hooks will not execute.
    To re-enable: specify extension enable git
  2. Haz
    git switch -c 001-catalogo-de-marcas

    Spec Kit no crea la rama: eso lo hace su extensión de git, que no instalamos. La carpeta de la spec y la rama son independientes medido de la skill.

  3. Pega (en un chat nuevo)
    /speckit-specify Catálogo de marcas.
    Quién lo usa: Gobierno de Datos administra las marcas; otros sistemas consultan si una marca se puede usar.
    Qué necesita: dar de alta, editar, desactivar (sin borrar) y consultar marcas. El nombre no se repite aunque cambien mayúsculas o espacios.
    Por qué: hoy hay marcas duplicadas y productos con marcas retiradas.
    Criterios de aceptación (los escribo yo):
    - Dar de alta "Zeta" cuando ya existe "zeta" se rechaza con MARCA_DUPLICADA.
    - Una marca desactivada sigue existiendo y la consulta dice que está inactiva.
    Fuera de alcance: la pantalla y la carga inicial de marcas.
    Reglas: no menciones tecnología. Lo que no esté claro márcalo [NEEDS CLARIFICATION] en vez de suponerlo. Escribe en español y deja los encabezados de la plantilla.

    Los criterios los escribes tú. El curso de SDD pide escribir a mano la primera versión de la spec, con criterios de aceptación que se puedan verificar; la IA la mejora, no la inventa curso de SDD, sección 3. Si no tienes tiempo para la spec entera, al menos escribe tú los criterios, como en el prompt.

    Debes ver

    specs/001-catalogo-de-marcas/spec.md, checklists/requirements.md y .specify/feature.json. Si quedan dudas, como máximo tres preguntas con opciones A, B y C medido de la skill.

    Comprueba
    ls specs/001-*/ && cat .specify/feature.json && git branch --show-current
    grep -c "FR-0" specs/001-*/spec.md     # cada requisito con su ID
  4. Taller: tu primera skill

    Etapa: entre especificar y planear. Por qué skill y no agente: es corta, repetible y la quieres dentro de tu conversación mientras corriges la spec.

    Guárdala en .cursor/skills/revisar-spec/SKILL.md (Claude Code: .claude/skills/; Codex: .agents/skills/, que Cursor también lee).

    ---
    name: revisar-spec
    description: Revisa una spec de Spec Kit o de OpenSpec sin editarla y señala requisitos que no se pueden probar, palabras ambiguas, requisitos sin escenario, tecnología que se coló y criterios de éxito sin número. Usar después de especificar y antes de planear, o cuando pidan revisar una spec.
    ---
    
    # Revisar una spec
    
    Sólo lees. No edites ningún archivo.
    
    1. Ubica la spec: la ruta que te den; si no, `.specify/feature.json` (Spec Kit) o el cambio activo de `openspec list` (OpenSpec).
    2. Revisa cada requisito:
       - ¿Se puede probar con un escenario concreto? Si no, es un hallazgo.
       - ¿Usa palabras sin número («rápido», «fácil», «adecuado», «robusto», «intuitivo»)?
       - ¿Tiene al menos un escenario? En OpenSpec, ¿lleva SHALL o MUST y escenarios con cuatro `#`?
       - ¿Menciona clases, tablas, librerías o frameworks? Eso va en el plan o en el diseño.
    3. Revisa los criterios de éxito: cada uno con número y sin tecnología.
    4. Entrega una tabla `ubicación | problema | propuesta`, de lo más grave a lo menos grave.
    5. Termina con una línea: «Lista para planear» o «Necesita cambios (N hallazgos)».
    • name es el comando y debe ser igual a la carpeta: minúsculas y guiones, 64 caracteres como máximo.
    • description dice qué hace y cuándo usarla. Es lo único que el agente lee para decidir si la carga sola.
    • No lleva disable-model-invocation: queremos que el agente la use cuando le pidas «revisa la spec».
  5. Pega (en un chat nuevo, para que vea la skill)
    /revisar-spec specs/001-catalogo-de-marcas/spec.md
    Debes ver simulado
    ubicaciónproblemapropuesta
    FR-006Queda un [NEEDS CLARIFICATION]: no dice cuánto tiempo se guarda el historialResolverlo en /speckit-clarify
    FR-003«Sistema autorizado» no dice cuáles ni cómo se autenticanDefinir la lista o el criterio
    SC-001«En menos de 1 minuto» no dice cómo se mideMedirlo en la prueba de aceptación

    Necesita cambios (3 hallazgos)

    Si falla

    Si /revisar-spec no aparece, revisa que name sea igual a la carpeta y abre otro chat: en Cursor, la lista de skills se fija al empezar el chat foro oficial de Cursor.

  6. Pega
    /speckit-clarify Enfócate en reglas de negocio y casos límite: duplicados, concurrencia e historial. No preguntes de tecnología. Si no sé una respuesta, déjala como pregunta abierta, no como requisito.
    Debes ver

    Como máximo cinco preguntas, de una en una. Cada respuesta queda en ## Clarifications y cambia el requisito que toca: FR-006 se resuelve y aparece FR-007 simulado.

    Comprueba
    grep -n "### Session" specs/001-*/spec.md
    grep -c "NEEDS CLARIFICATION" specs/001-*/spec.md     # debe ser 0
    git add -A && git commit -m "Spec 001: catálogo de marcas"
    Reto: ¿qué tiene de malo este requisito?
    - **FR-008**: El sistema MUST guardar las marcas en MongoDB con un índice único y responder rápido.

    Respuesta: tres cosas. Mete tecnología (MongoDB, índice), que va en el plan. «Rápido» no se puede probar: necesita un número, como el SC-002. Y mezcla dos comportamientos en un requisito. Debería decir: «El sistema MUST rechazar un nombre de marca repetido» (y el rendimiento va como criterio de éxito con número).

Misión 3

Planea, divide y analiza

20 minutos · el cómo, las tareas y la revisión cruzada de artefactos

Usas: /speckit-plan, /speckit-tasks y /speckit-analyze. Un chat nuevo por paso: el estado vive en los archivos.

  1. Haz

    Mira specs/README.md. Si otro dev tiene una spec en curso, corre antes la revisión cruzada (misión 7): los choques se arreglan en la spec, no en el merge. En el laboratorio estás solo: sigue.

  2. Pega
    /speckit-plan Stack: Java 21, Spring Boot 3.3 WebFlux y MongoDB; pruebas con JUnit 5 y Testcontainers.
    Contrato OpenAPI en contracts/. Nada de caché ni mensajería, salvo que un criterio de éxito lo exija.
    Si algo viola la constitución, detente y dime qué principio y por qué.
    Al final, propón qué decisiones transversales de este plan deben pasar a AGENTS.md.
    Debes ver

    plan.md, research.md, data-model.md, contracts/ y quickstart.md, con la «Constitution Check» en ✅ simulado.

    Comprueba
    ls specs/001-*/ specs/001-*/contracts/
    grep -A8 "Constitution Check" specs/001-*/plan.md
  3. Una checklist no prueba el código: prueba si los requisitos de un tema están completos, claros y son medibles. Haz una por cada dominio delicado y resuelve las casillas pendientes antes de las tareas curso de SDD, sección 3.

    Pega
    /speckit-checklist seguridad: roles, autenticación entre sistemas y qué pasa cuando se niega un permiso
    Debes ver

    checklists/seguridad.md, con casillas CHK001, CHK002… y entre corchetes qué revisan: [Gap], [Ambiguity] o [Consistency] simulado. Cada casilla sin marcar es un hueco de la spec: corrígelo con /speckit-clarify o editando la spec, y vuelve a correr la checklist. Ábrela en el explorador de esta misión, etapa 6.

  4. Pega
    /speckit-tasks Pruebas primero en cada historia (la constitución lo exige). Cada prueba lleva en su nombre el FR que cubre, por ejemplo "FR-002: rechaza nombre repetido". Tareas de medio día como máximo.
    Comprueba
    grep -c "^- \[ \] T" specs/001-*/tasks.md      # cuántas tareas
    for fr in $(grep -oE "FR-[0-9]{3}" specs/001-*/spec.md | sort -u); do
      grep -q "$fr" specs/001-*/tasks.md || echo "$fr no aparece en ninguna tarea"
    done
  5. Pega
    /speckit-analyze Dame primero los CRITICAL y HIGH, cada uno con el arreglo que propones. No edites nada hasta que yo apruebe.
    Debes ver

    Un informe en el chat, sin archivos nuevos: analyze sólo lee medido de la skill. Un ejemplo simulado:

    IDCategorySeverityLocation(s)SummaryRecommendation
    C1CoverageHIGHspec.md FR-005 · tasks.mdFR-005 (quién y cuándo) sólo tiene tarea en el altaAgregarlo a T015
    A1AmbiguityMEDIUMspec.md FR-003«Sistema autorizado» no está definidoAclararlo

    🛑 Cero CRITICAL antes de implementar. Aprueba los arreglos y vuelve a correr analyze.

  6. Avanza el explorador hasta la etapa en la que vas. Lo de specify init y las plantillas es medido; lo que escribe el agente es simulado. Verde = nuevo en esa etapa; ámbar = cambió.

    git add -A && git commit -m "Spec 001: plan, tareas y análisis"
Misión 4

Implementa con candados

25 minutos · un hook, las pruebas primero y nada sin rastro

Usas: tu hook no-saltar-pruebas, /speckit-implement y /speckit-converge.

  1. Taller: tu primer hook

    Etapa: implementar. Por qué hook: una regla en AGENTS.md el agente la puede olvidar; un hook corre siempre, y si sale con código 2, la acción no ocurre.

    Regístralo en .cursor/hooks.json y guarda el script en .cursor/hooks/:

    {
      "version": 1,
      "hooks": {
        "beforeShellExecution": [
          {
            "command": ".cursor/hooks/no-saltar-pruebas.sh",
            "failClosed": true
          }
        ]
      }
    }
    #!/usr/bin/env bash
    # Bloquea los comandos que se saltan pruebas o verificaciones.
    # Cursor lo llama en beforeShellExecution y le manda {"command": …} por stdin.
    # Claude Code lo llama en PreToolUse (matcher Bash) y le manda {"tool_input": {"command": …}}.
    # Código de salida 2 = bloquear en los dos.
    
    leido="$(python3 -c 'import sys, json
    d = json.load(sys.stdin)
    if "command" in d:
        print("cursor\t" + d["command"])
    else:
        print("claude\t" + d.get("tool_input", {}).get("command", ""))' 2>/dev/null)"
    origen="${leido%%$'\t'*}"
    comando="${leido#*$'\t'}"
    
    saltos='-DskipTests|maven\.test\.skip=true|maven\.test\.failure\.ignore=true|jacoco\.skip=true|--no-verify'
    saltos_gradle='gradlew?( [^|;&]*)? (-x|--exclude-task)[ =]?[^ ]*(test|check|jacoco)'
    
    if printf '%s' "$comando" | grep -Eq -e "$saltos" -e "$saltos_gradle"; then
      if [ "$origen" = "cursor" ]; then
        echo '{"permission": "deny", "user_message": "Bloqueado: no se permite saltarse pruebas ni verificaciones.", "agent_message": "Corre la suite completa; en este repo está prohibido saltarse pruebas."}'
      fi
      echo "Bloqueado: no se permite saltarse pruebas ni verificaciones. Corre la suite completa." >&2
      exit 2
    fi
    
    [ "$origen" = "cursor" ] && echo '{"permission": "allow"}'
    exit 0
    chmod +x .cursor/hooks/no-saltar-pruebas.sh

    En Claude Code el mismo script va como hook PreToolUse con "matcher": "Bash" en .claude/settings.json o ~/.claude/settings.json. Cursor también aplica esos hooks de Claude Code cursor.com/docs/reference/third-party-hooks. Si ya los tienes ahí, no los registres dos veces.

    Comprueba

    Que deja pasar lo normal, en los dos formatos de entrada medido:

    $ echo '{"command":"./gradlew test","cwd":"/repo"}' | .cursor/hooks/no-saltar-pruebas.sh; echo "código de salida: $?"
    {"permission": "allow"}
    código de salida: 0
    
    $ echo '{"tool_name":"Bash","tool_input":{"command":"./gradlew test"}}' | .cursor/hooks/no-saltar-pruebas.sh; echo "código de salida: $?"
    código de salida: 0

    Y que bloquea: pídele al agente «corre la build saltándote las pruebas». El comando no debe ejecutarse y debes ver el mensaje del hook. Si no pasa nada, revisa el canal de salida «Hooks» de Cursor.

    Lo que pasó al preparar este curso

    El caso «bloquea» de este script no lo pudimos correr aquí. El hook del equipo, registrado sólo en ~/.claude/settings.json, bloqueó un comando del propio agente de Cursor que llevaba esos textos como datos de prueba medido. Eso enseña dos cosas: Cursor sí aplica los hooks de Claude Code, y el candado mira el texto del comando, no la intención. Diseña tus patrones con cuidado para que no frenen lo que no deben.

  2. Pega
    /speckit-implement Sólo las fases 1 a 3 (el producto mínimo). Escribe cada prueba primero y confirma que falla antes de programar. Al terminar cada fase, corre las pruebas y detente para que revise.
    Debes ver

    Las tareas T001 a T011 marcadas con [X], y pruebas que citan su requisito en el nombre simulado:

    package mx.ejemplo.marcas.integracion;
    
    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.Test;
    
    class AltaMarcaTest extends PruebaConMongo {
    
        @Test
        @DisplayName("FR-002: rechaza ' ZETA ' cuando ya existe 'Zeta'")
        void rechazaNombreRepetidoSinImportarMayusculasNiEspacios() {
            darDeAlta("Zeta").expectStatus().isCreated();
    
            darDeAlta(" ZETA ")
                    .expectStatus().isEqualTo(409)
                    .expectBody().jsonPath("$.code").isEqualTo("MARCA_DUPLICADA");
        }
    
        @Test
        @DisplayName("FR-001: un usuario de Compras no puede dar de alta marcas")
        void soloGobiernoDeDatosDaDeAlta() {
            darDeAltaComo("compras", "Zeta").expectStatus().isForbidden();
        }
    }
    Si falla

    Si se detiene a preguntar por checklists, hay casillas sin marcar en checklists/: resuélvelas o contesta que sigues a propósito.

  3. Haz (desde la raíz del repo)
    spec=specs/001-catalogo-de-marcas/spec.md
    for fr in $(grep -oE "FR-[0-9]{3}" "$spec" | sort -u); do
      if grep -rqE "\"$fr[^0-9]" src/test; then echo "✅ $fr tiene prueba"; else echo "❌ $fr sin prueba"; fi
    done
    Debes ver

    Con sólo el producto mínimo, faltan pruebas medido sobre el ejemplo:

    $ spec=specs/001-catalogo-de-marcas/spec.md
      for fr in $(grep -oE "FR-[0-9]{3}" "$spec" | sort -u); do
        if grep -rqE "\"$fr[^0-9]" src/test; then echo "✅ $fr tiene prueba"; else echo "❌ $fr sin prueba"; fi
      done
    ✅ FR-001 tiene prueba
    ✅ FR-002 tiene prueba
    ❌ FR-003 sin prueba
    ❌ FR-004 sin prueba
    ❌ FR-005 sin prueba
    ❌ FR-006 sin prueba
    ❌ FR-007 sin prueba

    Implementa las fases 4 a 6 (/speckit-implement Fases 4 a 6) y repite hasta que todo salga ✅.

  4. Pega
    /speckit-converge
    Debes ver

    Al final de tasks.md, una «Phase 7: Convergence» con lo que falta, cada tarea rastreable a su requisito. Converge sólo agrega: no toca spec, plan ni código medido de la skill. Ejemplo simulado:

    ## Phase 7: Convergence
    
    - [ ] T018 [US3] Registrar la reactivación en el historial (FR-007): hoy aplicacion/ReactivacionDeMarca.java cambia `activa` pero no escribe en `marcas_historial`
    - [ ] T019 [P] [US1] Agregar la prueba "FR-002: dos altas simultáneas de 'Zeta' dejan una sola marca" (Edge Cases)
    Comprueba
    # después de /speckit-implement "Sólo la fase Convergence":
    ./gradlew test && git add -A && git commit -m "Spec 001: implementación"
Misión 5

Un agente que revisa antes del PR

15 minutos · tu primer subagente, de sólo lectura

Usas: tu agente revisor-conformidad y tu skill /conformidad, que lo lanza.

  1. Taller: tu primer agente

    Etapa: antes del PR. Por qué agente y no skill: quien implementó no se revisa a sí mismo. El subagente empieza con contexto limpio, sin tu conversación ni tus suposiciones, y sólo te devuelve el veredicto cursor.com/docs/subagents.

    Guárdalo en .claude/agents/revisor-conformidad.md. Lo leen Claude Code y Cursor; si sólo usas Cursor, también vale .cursor/agents/, que gana si hay dos con el mismo nombre cursor.com/docs/subagents.

    ---
    name: revisor-conformidad
    description: Revisa, sólo leyendo, si el cambio de la rama cumple su spec requisito por requisito (implementado, con prueba que cita su ID, criterio cumplido), qué se coló fuera de la spec y si alguna prueba se apagó, se aflojó o se borró. Usar antes de abrir el PR o con /conformidad. No edita nada.
    tools: Read, Grep, Glob, Bash
    readonly: true
    ---
    
    # Revisor de conformidad
    
    No escribiste este código: lo revisas contra su spec. Sólo lees. Bash es sólo para `git` y `rg`.
    
    ## Cómo revisas
    
    1. Lista los requisitos de la spec: los `FR-###` de Spec Kit, o los `### Requirement:` de OpenSpec con sus escenarios.
    2. Lee el diff: `git diff --stat <base>...HEAD`, `git diff <base>...HEAD` y lo que no tiene commit.
    3. Por cada requisito: ¿el diff lo implementa? (cita `archivo:línea`). ¿Qué prueba lo cita en su nombre? ¿Se cumple su criterio?
    4. Al revés: ¿qué cambios del diff no rastrean a ningún requisito? Repórtalos aunque sean un refactor válido.
    5. Busca pruebas apagadas, aflojadas o borradas: `@Disabled`, `@Ignore`, `.skip`, aserciones borradas o comentadas, un valor concreto que pasó a `any()`.
    6. Revisa que el diff no rompa una regla de `AGENTS.md`, de la constitución o de `openspec/config.yaml`.
    7. Por cada firma pública que cambió, busca con `rg` quién la llama fuera del diff.
    
    ## Reglas
    
    - Todo hallazgo lleva `archivo:línea`. Si no lo puedes citar, no lo afirmes.
    - Máximo 3 bloqueantes, en orden de gravedad. No comentes estilo ni rediseñes.
    - Si te falta la spec o la base, dilo y para.
    
    ## Salida
    
    ```
    ## Conformidad: NO LISTO | LISTO CON PENDIENTES | LISTO PARA PR
    
    | Requisito | ¿Implementado? | Prueba | ¿Criterio cumplido? |
    |---|---|---|---|
    
    Fuera de la spec: …
    Pruebas apagadas, aflojadas o borradas: …
    Reglas rotas: …
    
    ### Bloqueantes (máximo 3)
    1. `archivo:línea` — qué pasa, por qué importa y cómo se arregla.
    ```
    • description dice cuándo delegarle. El agente principal la lee para decidir; también lo puedes pedir por nombre.
    • Sólo lectura, en los dos agentes. En Claude Code, tools sin Edit ni Write. En Cursor, readonly: true: Cursor no documenta tools, y sus subagentes heredan todas las herramientas del principal cursor.com/docs/subagents.
    • El cuerpo es su prompt: cómo revisa, sus reglas y una salida con formato fijo y veredicto.
  2. Taller: una skill manual

    Con disable-model-invocation: true la skill sólo corre cuando escribes /conformidad: no queremos que el agente lance una revisión cara por su cuenta cursor.com/docs/skills.

    ---
    name: conformidad
    description: Lanza al subagente revisor-conformidad para revisar, sólo leyendo, si el cambio de la rama cumple su spec requisito por requisito. Usar antes de abrir el PR o cuando pregunten «¿ya cumple la spec?».
    disable-model-invocation: true
    ---
    
    # /conformidad
    
    1. Ubica la spec del cambio: la ruta que te den; si no, `.specify/feature.json` (Spec Kit) o el cambio activo de `openspec list` (OpenSpec). Si hay más de una candidata, pregunta cuál.
    2. Ubica la rama base: la que te den; si no, `origin/main`.
    3. Lanza el subagente `revisor-conformidad` con la ruta de la spec y la base. No revises tú: quien implementó no se revisa a sí mismo.
    4. Muestra el veredicto tal cual. Si sale NO LISTO, ofrece arreglarlo, pero no edites nada hasta que te lo pidan.
  3. Pega (en un chat nuevo)
    /conformidad specs/001-catalogo-de-marcas main
    Debes ver simulado
    ## Conformidad: LISTO CON PENDIENTES
    
    Spec: specs/001-catalogo-de-marcas · Base: main · Alcance: 14 archivos, 6 de prueba
    
    | Requisito | ¿Implementado? | Prueba | ¿Criterio cumplido? |
    |---|---|---|---|
    | FR-001 | sí, `web/Seguridad.java:22` | `AltaMarcaTest.java:18` | sí |
    | FR-002 | sí, `dominio/Marca.java:19` | `AltaMarcaTest.java:9` | sí |
    | FR-003 | sí, `web/RutasMarcas.java:41` | `DisponibilidadTest.java:12` | sí |
    | …      | …                              | …                           | … |
    
    Fuera de la spec: `web/RutasMarcas.java:60` agrega GET /marcas (listado), que ningún FR pide.
    Pruebas apagadas, aflojadas o borradas: ninguna
    Reglas rotas: sin hallazgos
    
    ### Bloqueantes (máximo 3)
    Ninguno. Pendiente: explica el listado en el PR o quítalo.
    Comprueba

    Que el veredicto cita archivo:línea en cada fila. Si dice NO LISTO, corrige y repite; no edites el agente para que «apruebe».

  4. Mientras el servicio nace, los cambios siguen en Spec Kit. La regla, del curso y del kit del equipo curso de SDD, sección 4:

    • La spec cumplió su objetivo y llega algo nuevo: esa spec se cierra y lo nuevo va en otra (/speckit-specify, número siguiente). En el mapa de specs puede decir sustituye a NNN.
    • El resultado no fue el esperado: se itera la misma spec, en una sesión nueva y con el modelo más potente que tengas.
    Pega (para iterar)
    /speckit-specify Reescribe la spec existente @specs/001-catalogo-de-marcas/spec.md; no crees una spec nueva. Los criterios nuevos son: <…>.

    Si el cambio es de fondo, borra de esa spec plan.md, tasks.md, research.md, data-model.md, quickstart.md y contracts/, y repite plan → tasks → analyze → implement. Si es menor, pide al plan que reutilice lo existente y cambie sólo lo necesario.

  5. Haz
    git push -u origin 001-catalogo-de-marcas
    gh pr create --title "Spec 001: catálogo de marcas" --body-file pr.md   # pr.md = qué, por qué, cómo verificar + la tabla de /conformidad

    🛑 El merge lo deciden el CI en verde, el análisis de seguridad y una revisión humana. Antes, repasa la Definition of Done:

    • Pruebas verdes de verdad, sin saltarse ninguna.
    • Cada requisito con al menos una prueba que cita su ID.
    • Ninguna prueba apagada, aflojada o borrada, y lo que quedó fuera de la spec, explicado en el PR.
    • specs/README.md con la spec 001 como publicada.

    Con el merge, el servicio ya vive. De aquí en adelante, cada mejora es un cambio de OpenSpec.

Misión 6

Gradúate a OpenSpec: tu primer cambio

25 minutos · explorar, proponer, aplicar, verificar y archivar

Cambias de nivel: de spec-first a spec-anchored. Ya no escribes una spec por feature: modificas la spec viva del sistema. Usas: /opsx-explore, /opsx-new + /opsx-continue, /opsx-apply, /opsx-verify y /opsx-archive. El cambio: Gobierno de Datos puede bloquear una marca, y el alta de productos de esa marca se rechaza.

  1. Haz
    git switch main && git pull && git switch -c bloquear-marcas
    openspec list && openspec list --specs

    ¿Ya hay un cambio abierto con la misma intención? Actualízalo en vez de abrir otro. ¿Dependes de uno abierto? Ése se archiva primero regla del kit de un equipo.

  2. Pega
    /opsx-explore Quiero que una marca pueda bloquearse para que nadie dé de alta productos de esa marca. Revisa con `openspec list --specs` qué capacidades existen, dime cuáles toca, qué preguntas hay y dos o tres formas de resolverlo con sus pros y contras. No crees archivos.
    Debes ver

    Análisis y preguntas, sin archivos. Explore nunca escribe código, y sólo crea artefactos de un cambio si se lo confirmas medido de la skill.

  3. Pega
    /opsx-new bloquear-marcas

    Y luego, una vez por artefacto (propuesta, delta, diseño y tareas), revisando cada uno antes de seguir:

    /opsx-continue bloquear-marcas

    Si el alcance ya está claro desde el principio, /opsx-propose hace los cuatro de un jalón; /opsx-ff crea los que falten de corrido. OpenSpec no tiene clarify: pide «lista las ambigüedades que requieran decisión de negocio» y contéstalas una por una.

    Debes ver

    Por debajo, la skill crea el cambio y pide su estado medido:

    $ openspec status --change bloquear-marcas
    Change: bloquear-marcas
    Schema: spec-driven
    Change root: ~/mi-proyecto/openspec/changes/bloquear-marcas
    Progress: 0/4 artifacts complete
    
    [ ] proposal
    [-] specs (blocked by: proposal)
    [-] design (blocked by: proposal)
    [-] tasks (blocked by: specs, design)
    
    Next: openspec instructions proposal --change "bloquear-marcas" --json

    Al terminar, los cuatro artefactos. El delta es una capacidad nueva, así que lleva ## Purpose y ## ADDED Requirements simulado, pasó el validador estricto:

    # Spec Delta
    
    ## Purpose
    
    Decidir qué marcas no se pueden usar al dar de alta productos, quién puede bloquearlas y qué pasa con las altas de esas marcas.
    
    ## ADDED Requirements
    
    ### Requirement: Bloquear y desbloquear una marca
    El sistema SHALL permitir que sólo un usuario con rol Gobierno de Datos bloquee o desbloquee una marca, y SHALL guardar quién lo hizo y cuándo.
    
    #### Scenario: Gobierno de Datos bloquea una marca
    - **WHEN** un usuario con rol Gobierno de Datos bloquea la marca "ACME"
    - **THEN** la marca queda bloqueada con su usuario y la fecha y hora del bloqueo
    
    #### Scenario: Otro rol intenta bloquear
    - **WHEN** un usuario con rol Compras intenta bloquear la marca "ACME"
    - **THEN** la operación se rechaza con el código SIN_PERMISO y la marca no cambia
    
    ### Requirement: Rechazar altas de productos de marcas bloqueadas
    El sistema MUST rechazar el alta de un producto cuya marca esté bloqueada, con el código MARCA_BLOQUEADA.
    
    #### Scenario: Alta de un producto de marca bloqueada
    - **WHEN** un vendedor da de alta un producto de la marca bloqueada "ACME"
    - **THEN** el alta se rechaza con el código MARCA_BLOQUEADA y no se crea el producto
    
    #### Scenario: Alta de un producto de marca no bloqueada
    - **WHEN** un vendedor da de alta un producto de la marca "Zeta", que no está bloqueada
    - **THEN** el alta sigue con las validaciones de siempre
    Comprueba
    $ openspec validate bloquear-marcas --strict
    Change 'bloquear-marcas' is valid
    $ echo $?
    0
  4. Pega
    /opsx-apply bloquear-marcas Empieza por el grupo 1. Por cada tarea: escribe la prueba de su escenario con el nombre del escenario, hazla pasar, márcala [x] y dime con qué comando se verifica. Detente al terminar cada grupo.
    Debes ver

    Una prueba por escenario, con el nombre del requisito y del escenario simulado:

    package mx.ejemplo.marcas.web;
    
    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.Test;
    
    /** Una prueba por escenario de openspec/changes/bloquear-marcas/specs/bloqueo-de-marcas/spec.md */
    class BloqueoDeMarcaTest extends PruebaConMongo {
    
        @Test
        @DisplayName("Bloquear y desbloquear una marca · Gobierno de Datos bloquea una marca")
        void gobiernoDeDatosBloquea() {
            bloquearComo("gobierno-de-datos", "ACME").expectStatus().isOk();
            assertThat(marca("ACME").bloqueada()).isTrue();
            assertThat(marca("ACME").bloqueadaPor()).isEqualTo("gobierno-de-datos");
        }
    
        @Test
        @DisplayName("Bloquear y desbloquear una marca · Otro rol intenta bloquear")
        void otroRolNoPuedeBloquear() {
            bloquearComo("compras", "ACME")
                    .expectStatus().isForbidden()
                    .expectBody().jsonPath("$.code").isEqualTo("SIN_PERMISO");
        }
    
        @Test
        @DisplayName("Rechazar altas de productos de marcas bloqueadas · Alta de un producto de marca bloqueada")
        void rechazaAltaDeMarcaBloqueada() {
            bloquearComo("gobierno-de-datos", "ACME");
            altaDeProducto("ACME")
                    .expectStatus().isEqualTo(422)
                    .expectBody().jsonPath("$.code").isEqualTo("MARCA_BLOQUEADA");
        }
    }

    La regla anti-drift. Si a mitad de camino descubres que la spec o el diseño están mal, no edites el código por fuera: corrige el artefacto y deja que /opsx-continue regenere lo que depende de él. Retocar el código fuera del flujo es la forma más común de que spec y código se separen regla del kit de un equipo.

  5. Pega
    /opsx-verify bloquear-marcas
    Debes ver

    Un informe en tres ejes: completitud (tareas y cobertura de la spec), corrección (requisitos y escenarios) y coherencia (apego al diseño). Cada hallazgo es CRITICAL, WARNING o SUGGESTION medido de la skill. Un CRITICAL se arregla antes de archivar. En un WARNING decides tú: o el código se ajusta al diseño, o el diseño se actualiza a la decisión real.

  6. Pega
    /opsx-archive bloquear-marcas
    Debes ver medido
    $ openspec archive bloquear-marcas -y
    Task status: ✓ Complete
    
    Specs to update:
      bloqueo-de-marcas: create
    Applying changes to openspec/specs/bloqueo-de-marcas/spec.md:
      + 2 added
    Totals: + 2, ~ 0, - 0, → 0
    Specs updated successfully.
    Change 'bloquear-marcas' archived as '2026-10-18-bloquear-marcas'.
    $ openspec list --specs
    Specs:
      bloqueo-de-marcas     requirements 2

    Ahora existe openspec/specs/bloqueo-de-marcas/spec.md, generada por OpenSpec. Recórrela en el explorador, etapa 4. Después, /conformidad y el PR, como en la misión 5.

Misión 7

Varios cambios en paralelo, con worktrees

25 minutos · qué no se paraleliza, specs que chocan e integración por orden de riesgo

Usas: git worktrees, un agente por worktree y tu agente revision-cruzada. El caso: el dev B (o un segundo agente) hace motivo-al-bloquear, en el que el bloqueo exige un motivo, mientras el dev A hace desbloqueo-temporal. Los dos tocan el mismo requisito.

  1. La base se acuerda junta y en secuencia: la constitución (o config.yaml), el dominio básico, el esquema de datos y las convenciones. Si dos personas la escriben a la vez, pueden fijar principios contradictorios que después no se consolidan curso de SDD, sección 6. En este laboratorio ya quedó en la misión 1, así que puedes seguir.

  2. Un worktree es otra carpeta del mismo repo con su propia rama. Así dos agentes trabajan a la vez sin pisarse archivos.

    Haz (desde la carpeta del repo, en main)
    git worktree add ../lab-specs-motivo -b motivo-al-bloquear
    git worktree add ../lab-specs-desbloqueo -b desbloqueo-temporal
    git worktree list
    Debes ver medido
    $ git worktree add ../lab-specs-motivo -b motivo-al-bloquear
    Preparing worktree (new branch 'motivo-al-bloquear')
    HEAD is now at <commit> Base del repo
    $ git worktree add ../lab-specs-desbloqueo -b desbloqueo-temporal
    Preparing worktree (new branch 'desbloqueo-temporal')
    HEAD is now at <commit> Base del repo
    $ git worktree list
    ~/lab-specs             <commit> [main]
    ~/lab-specs-desbloqueo  <commit> [desbloqueo-temporal]
    ~/lab-specs-motivo      <commit> [motivo-al-bloquear]

    Abre cada carpeta en su propia ventana de Cursor. En cada una, su dev o su agente corre /opsx-propose de su cambio. Las tareas y la implementación también van en paralelo, cada una en su worktree. Haz commit en cada worktree antes de integrar.

  3. Taller: un agente que lee otras ramas

    Etapa: antes de planear o aplicar, sólo si hay specs en paralelo. Por qué agente: lee mucho (varias ramas y specs) y conviene que no llene tu contexto. Además debe ser de sólo lectura: lee con git show, sin cambiar de rama.

    ---
    name: revision-cruzada
    description: Compara, sólo leyendo, las specs que se escriben en paralelo en distintas ramas y encuentra conceptos definidos dos veces, reglas que se contradicen y escrituras sobre los mismos datos; propone una spec dueña por concepto. Usar antes de planear o de aplicar cuando hay otras specs en curso en el repo.
    tools: Read, Grep, Glob, Bash
    readonly: true
    ---
    
    # Revisión cruzada
    
    Sólo lees: no cambias de rama, no entras a otros worktrees y no editas specs.
    
    1. Ramas: las que te den; si no, las filas `en curso` de `specs/README.md`, más `git branch -r`.
    2. Lee cada spec desde su rama sin hacer checkout: `git show <rama>:<ruta>`. Si una spec no tiene commit, di de qué rama falta y para.
    3. Busca:
       - conceptos definidos en más de una spec, aunque usen otras palabras (estados, permisos, umbrales);
       - reglas que una spec fija y otra contradice o reinventa;
       - escrituras sobre las mismas colecciones, tópicos o estados;
       - dependencias: una spec que necesita algo que otra todavía no publica.
    4. Cita cada choque textual, con rama y archivo. Propón la spec dueña de cada concepto; no resuelvas tú.
    
    ## Salida
    
    ```
    ## Revisión cruzada: SIN CHOQUES | CHOQUES MENORES | CHOQUES A RESOLVER
    
    | ID | Severidad | Specs | Qué chocan | Cita (rama:archivo) | Dueño propuesto |
    |---|---|---|---|---|---|
    
    Orden de implementación que sale de las dependencias: …
    ```
  4. Pega
    Usa el subagente revision-cruzada para comparar las ramas motivo-al-bloquear y desbloqueo-temporal.
    Debes ver simulado
    ## Revisión cruzada: CHOQUES A RESOLVER
    
    | ID | Severidad | Specs | Qué chocan | Cita (rama:archivo) | Dueño propuesto |
    |---|---|---|---|---|---|
    | C-1 | alta | motivo-al-bloquear, desbloqueo-temporal | Las dos modifican «Bloquear y desbloquear una marca» con textos distintos | motivo-al-bloquear:openspec/changes/motivo-al-bloquear/specs/bloqueo-de-marcas/spec.md «…y, al bloquear, el motivo…» / desbloqueo-temporal:…/spec.md «…o la desbloquee hasta una fecha…» | bloqueo-de-marcas (spec viva) |
    
    Orden de implementación: primero motivo-al-bloquear (se archiva); después desbloqueo-temporal rehace su MODIFIED sobre la spec viva ya actualizada.
  5. Haz

    Anota en specs/README.md, sección «Conceptos con dueño», que «marca bloqueada» la define la capacidad bloqueo-de-marcas. Nadie edita la spec de otro worktree: cada dev ajusta la suya en su rama, con /opsx-continue.

    Reto: ¿qué está mal en este delta del dev A?
    ## ADDED Requirements
    
    ### Requirement: Bloquear y desbloquear una marca
    El sistema SHALL permitir bloquear una marca o desbloquearla hasta una fecha.

    Respuesta: el requisito ya existe en la spec viva, así que debe ir en ## MODIFIED Requirements, copiando el bloque completo con todos sus escenarios. Un ADDED sobre algo que ya existe deja dos specs describiendo lo mismo: drift desde el primer día. Además, le falta al menos un escenario.

  6. Debes ver

    El MODIFIED del dev B copia el bloque entero (texto y tres escenarios) y lo edita simulado, pasó el validador estricto:

    # Spec Delta
    
    ## MODIFIED Requirements
    
    ### Requirement: Bloquear y desbloquear una marca
    El sistema SHALL permitir que sólo un usuario con rol Gobierno de Datos bloquee o desbloquee una marca, y SHALL guardar quién lo hizo, cuándo y, al bloquear, el motivo (de 10 a 300 caracteres).
    
    #### Scenario: Gobierno de Datos bloquea una marca
    - **WHEN** un usuario con rol Gobierno de Datos bloquea la marca "ACME" con el motivo "Imitaciones reportadas por Legal"
    - **THEN** la marca queda bloqueada con su usuario, la fecha y hora del bloqueo y el motivo
    
    #### Scenario: Bloqueo sin motivo
    - **WHEN** un usuario con rol Gobierno de Datos intenta bloquear la marca "ACME" sin motivo
    - **THEN** la operación se rechaza con el código MOTIVO_REQUERIDO y la marca no cambia
    
    #### Scenario: Otro rol intenta bloquear
    - **WHEN** un usuario con rol Compras intenta bloquear la marca "ACME"
    - **THEN** la operación se rechaza con el código SIN_PERMISO y la marca no cambia
    Comprueba medido
    $ openspec show motivo-al-bloquear --diff
    # Proposal
    
    ## Why
    
    Auditoría pidió saber por qué se bloqueó cada marca. Hoy el bloqueo guarda quién y cuándo, pero no el motivo.
    
    ## What Changes
    
    - Bloquear una marca exige un motivo de 10 a 300 caracteres.
    - Desbloquear no pide motivo.
    
    ## Capabilities
    
    ### New Capabilities
    
    - (ninguna)
    
    ### Modified Capabilities
    
    - `bloqueo-de-marcas`: el requisito "Bloquear y desbloquear una marca" exige el motivo.
    
    ## Impact
    
    - **API:** `PATCH /marcas/{id}/bloqueo` recibe `motivo`; sin él responde `MOTIVO_REQUERIDO`.
    - **Datos:** campo `motivoBloqueo` en la marca.
    
    
    Specifications Changed (diffs)
    
    bloqueo-de-marcas
    
      MODIFIED: Bloquear y desbloquear una marca
        @@ -1,10 +1,14 @@
         ### Requirement: Bloquear y desbloquear una marca
        -El sistema SHALL permitir que sólo un usuario con rol Gobierno de Datos bloquee o desbloquee una marca, y SHALL guardar quién lo hizo y cuándo.
        +El sistema SHALL permitir que sólo un usuario con rol Gobierno de Datos bloquee o desbloquee una marca, y SHALL guardar quién lo hizo, cuándo y, al bloquear, el motivo (de 10 a 300 caracteres).
    
         #### Scenario: Gobierno de Datos bloquea una marca
        -- **WHEN** un usuario con rol Gobierno de Datos bloquea la marca "ACME"
        -- **THEN** la marca queda bloqueada con su usuario y la fecha y hora del bloqueo
        +- **WHEN** un usuario con rol Gobierno de Datos bloquea la marca "ACME" con el motivo "Imitaciones reportadas por Legal"
        +- **THEN** la marca queda bloqueada con su usuario, la fecha y hora del bloqueo y el motivo
    
        +#### Scenario: Bloqueo sin motivo
        +- **WHEN** un usuario con rol Gobierno de Datos intenta bloquear la marca "ACME" sin motivo
        +- **THEN** la operación se rechaza con el código MOTIVO_REQUERIDO y la marca no cambia
        +
         #### Scenario: Otro rol intenta bloquear
         - **WHEN** un usuario con rol Compras intenta bloquear la marca "ACME"
         - **THEN** la operación se rechaza con el código SIN_PERMISO y la marca no cambia
    Si falla

    Si tu MODIFIED omite escenarios, la versión 1.14.3 lo detiene en la validación y al archivar, sin tocar archivos medido:

    $ openspec validate texto-de-bloqueo --strict
    Change 'texto-de-bloqueo' has issues
    ✗ [ERROR] bloqueo-de-marcas/spec.md: MODIFIED "Bloquear y desbloquear una marca" omits scenario(s) the current spec still has: "Bloqueo sin motivo", "Otro rol intenta bloquear". The modified block has 1 scenario; the current spec has 3 scenarios. It adds none. Copy the omitted scenarios into the MODIFIED block (a MODIFIED requirement replaces the whole block, so archive refuses to drop them).
    Next steps:
      - Ensure change has deltas in specs/: use headers ## ADDED/MODIFIED/REMOVED/RENAMED Requirements
      - Each requirement MUST include at least one #### Scenario: block
      - Debug parsed deltas: openspec show texto-de-bloqueo --json --deltas-only
    $ echo $?
    1
  7. No se integra por orden de llegada: primero lo que menos puede romper (algo de sólo lectura, como un reporte) y al final lo que escribe en la base de datos curso de SDD, sección 6. Aquí, motivo-al-bloquear primero, porque desbloqueo-temporal depende de él.

    Pega (en un chat nuevo, en la carpeta principal, en main)
    Estás en main. Integra la rama motivo-al-bloquear, que tiene su propio worktree: haz el merge. Si da conflictos, analiza cada uno y propón la solución completa antes de aplicarla. Si entra limpio, corre todas las pruebas; si fallan, analiza por qué y propón cómo resolverlo. No borres worktrees ni ramas todavía.

    Repite con la siguiente rama. Para resolver conflictos conviene el modelo más potente que tengas curso de SDD, sección 6. Si choca .specify/feature.json, el puntero de Spec Kit a la spec activa, quédate con la versión de main.

  8. Pega
    /opsx-archive motivo-al-bloquear
    $ openspec archive motivo-al-bloquear -y
    Task status: ✓ Complete
    
    Specs to update:
      bloqueo-de-marcas: update
    Applying changes to openspec/specs/bloqueo-de-marcas/spec.md:
      ~ 1 modified
    Totals: + 0, ~ 1, - 0, → 0
    Specs updated successfully.
    Change 'motivo-al-bloquear' archived as '2026-10-18-motivo-al-bloquear'.

    Si el squad cerró varios cambios que tocan la misma spec, usa /opsx-bulk-archive: detecta los conflictos y los fusiona en orden de creación, pidiendo confirmación regla del kit de un equipo.

    Haz (al terminar de integrar todo)
    git worktree remove ../lab-specs-motivo && git branch -d motivo-al-bloquear
    git worktree remove ../lab-specs-desbloqueo && git branch -d desbloqueo-temporal

    Y en specs/README.md, marca como publicada cada cambio integrado.

Misión 8

Mantén viva la spec: auditoría de drift

15 minutos · cada semana, en una sesión nueva

Usas: tu agente auditor-drift. Aunque cada cambio pase por verify, el drift entra por fuera: un hotfix directo al código, un cambio que alguien retocó sin OpenSpec, dos specs que describen lo mismo.

  1. Haz

    En el laboratorio, edita a mano el código del bloqueo para que Compras también pueda desbloquear, sin tocar ninguna spec, y haz commit con el mensaje «hotfix desbloqueo».

  2. Taller: un agente para tareas largas

    Por qué agente: recorre todas las specs vivas, el código y el git reciente; eso llenaría tu chat. En Cursor puedes agregarle is_background: true para que corra en segundo plano y no te bloquee cursor.com/docs/subagents.

    ---
    name: auditor-drift
    description: Audita, sólo leyendo, si las specs vivas de openspec/specs/ y el código siguen diciendo lo mismo, en las dos direcciones, y entrega un informe de drift con evidencia. Usar cada semana o antes de cerrar un sprint, en una sesión nueva.
    tools: Read, Grep, Glob, Bash
    readonly: true
    ---
    
    # Auditor de drift
    
    Sólo auditas e informas: no editas specs, código ni pruebas, y no creas cambios de OpenSpec.
    
    1. **Código → spec:** por cada requisito y escenario de `openspec/specs/`, ¿el código lo sigue haciendo así? Fíjate en estados, validaciones, límites y mensajes.
    2. **Spec → código:** busca comportamiento observable (endpoints, validaciones, mensajes publicados) que ninguna spec menciona o que la contradice. Empieza por lo que cambió en git en los últimos 30 días.
    3. **Además:** escenarios sin prueba, cambios activos ya implementados y sin archivar, y dos capacidades que describen lo mismo.
    
    ## Reglas
    
    - Cada hallazgo lleva evidencia: `archivo:línea` o el commit.
    - Ante la duda entre «cumple» y «drift», márcalo como drift de severidad baja y explica la duda.
    - Severidad alta si toca dinero, contratos o datos que consumen otros sistemas; media si lo nota el usuario; baja si es interno.
    
    ## Salida
    
    ```
    ## Drift: SINCRONIZADO | DRIFT LEVE | DRIFT GRAVE
    
    | ID | Tipo | Severidad | Capacidad y requisito | Evidencia | Qué pasa |
    |---|---|---|---|---|---|
    
    Por hallazgo, una salida que decide una persona:
    (a) regularizar la spec · (b) corregir el código · (c) escalar a negocio
    ```
  3. Pega (en un chat nuevo)
    Usa el subagente auditor-drift con los últimos 7 días de git.
    Debes ver simulado
    ## Drift: DRIFT GRAVE
    
    | ID | Tipo | Severidad | Capacidad y requisito | Evidencia | Qué pasa |
    |---|---|---|---|---|---|
    | D-1 | Código → spec | alta | bloqueo-de-marcas · «Bloquear y desbloquear una marca» | web/BloqueoHandler.java:41 (commit «hotfix desbloqueo») | El código deja desbloquear a Compras; la spec dice que sólo Gobierno de Datos |
    | D-2 | Pruebas | media | bloqueo-de-marcas · escenario «Bloqueo sin motivo» | BloqueoDeMarcaTest.java | El escenario no tiene prueba |
    
    Por hallazgo, una salida que decide una persona:
    D-1: (b) corregir el código, porque el hotfix contradice una regla acordada.
    D-2: agregar la prueba.
  4. Haz
    • (a) Regularizar la spec, si lo que hace el código es lo deseado: /opsx-propose "regulariza: Compras puede desbloquear". Como el comportamiento ya existe, sólo faltan las pruebas.
    • (b) Corregir el código, si la spec es lo deseado: un cambio normal (misión 6).
    • (c) Escalar a negocio, si no está claro cuál de los dos es el correcto.

    La decisión es de una persona, no del agente.

  5. Haz
    - uses: actions/setup-node@v4
      with:
        node-version: 22
    - run: npx -y @fission-ai/openspec@1.14.3 validate --all --strict --no-interactive
    - run: npx -y @fission-ai/openspec@1.14.3 validate --archived --no-interactive

    El primero falla si un delta o una spec viva está mal formada; el segundo, si alguien archivó con tareas pendientes. Los comandos están medidos en local; el pipeline no lo corrimos. Ojo: openspec archive -y archiva aunque falten tareas, sólo avisa medido:

    $ openspec validate --archived
    ✗ change/2026-10-18-bloquear-marcas
      ✗ 5 incomplete tasks (0/5 completed)
    Totals: 0 passed, 1 failed (1 items)
    $ echo $?
    1
Misión 9

Entiende un legacy sin spec (reverse-spec)

30 minutos · observar, clasificar, preguntar, congelar y especificar

El caso: un módulo viejo de facturación cobra la baja a mitad de mes por dos caminos distintos, y nadie sabe cuál es el bueno. Primero se observa, luego se clasifica y se pregunta, después se congela con pruebas y al final se escribe la spec de lo que hay. Cambiar el comportamiento es otro trabajo: la misión 10 curso de SDD, sección 7, y kit de un equipo.

  1. Haz
    git tag foto-base      # el punto contra el que se compara todo
    Pega
    Arranca la aplicación sin modificar ningún archivo; sólo instala las dependencias que hagan falta. Después dime cómo recorrerla a mano: pantallas, endpoints y procesos programados.

    Recórrela tú como usuario. El README se lee con desconfianza: dice lo que alguien creyó, no lo que hay. Luego, la constitución de la fase, que aquí son prohibiciones, no aspiraciones:

    Pega
    /speckit-constitution Fase: documentar y proteger, no mejorar. Principios:
    1. El comportamiento actual es sagrado: ningún cambio observable sin una decisión de negocio por escrito, aunque parezca un error.
    2. Toda afirmación lleva evidencia (archivo y líneas, dato real o testimonio con nombre y fecha); lo que no la tiene es una pregunta.
    3. Los hallazgos no se corrigen: se registran.
    4. Cero dependencias nuevas y cero refactors; las pruebas usan el framework que ya existe.
  2. Taller: escríbelo tú

    Diseña .claude/agents/investigador-legacy.md: lee código sin tocarlo, cita archivo:línea en cada afirmación y marca como PENDIENTE lo que tenga un solo testigo. Pista: readonly: true, tools sin Edit ni Write, y una salida con cuatro documentos.

    Ver una solución
    ---
    name: investigador-legacy
    description: Investiga, sólo leyendo, código legacy sin documentar y reconstruye qué hace hoy, con evidencia archivo:línea en cada afirmación. Usar al empezar un reverse-spec o cuando nadie sabe qué hace un módulo.
    tools: Read, Grep, Glob, Bash
    readonly: true
    ---
    
    # Investigador de legacy
    
    No tocas nada: lees, citas y registras. El README miente un poco; el código es la fuente, pero poco confiable.
    
    Entrega cuatro documentos en specs/000-reconocimiento/:
    1. mapa-sistema.md: cada módulo con su responsabilidad en una frase de negocio, dependencias y criticidad. Cierra con las zonas oscuras.
    2. flujo-<entidad>.md: el ciclo de vida de la entidad principal por TODOS los caminos que la cambian. Señala dónde dos caminos hacen lo mismo con código distinto.
    3. registro-riesgos.md: lo que puede romperse hoy, de mayor a menor, todavía sin soluciones.
    4. memoria-historica.md: incidentes, decisiones con nombre y avisos de "no tocar" que dejan los comentarios y el git.
    
    Reglas: cada afirmación con archivo:línea; con un solo testigo, PENDIENTE y la pregunta exacta que lo destrabaría.
    Pega
    Usa el subagente investigador-legacy sobre el módulo de facturación.
    Debes ver

    Los cuatro documentos, y en flujo-baja.md el hallazgo clave: dos cálculos de la misma baja simulado:

    BigDecimal cargoPorDias(BigDecimal mensual, int diasUsados) {                       // camino A
        return mensual.divide(BigDecimal.valueOf(30), 2, HALF_UP).multiply(BigDecimal.valueOf(diasUsados));
    }
    BigDecimal cargoProporcional(BigDecimal mensual, int diasUsados, int diasDelMes) {  // camino B
        return mensual.multiply(BigDecimal.valueOf(diasUsados)).divide(BigDecimal.valueOf(diasDelMes), 2, HALF_UP);
    }

    Con una mensualidad de 60.00 y una baja del 16 al 30 de julio (15 días de un mes de 31), el camino A cobra 30.00 y el B, 29.03 calculado.

  3. Cada comportamiento se clasifica como INTENCIONAL, ACCIDENTAL o DUDOSO. Un concepto implementado dos veces con resultados distintos es una contradicción: se documenta con un ejemplo donde divergen, y no se decide cuál es el bueno. Nada se da por confirmado con un solo testigo: hacen falta 2 de 3 entre código, datos y negocio.

    Debes ver simulado
    ## A-01 · Dos cálculos distintos del cargo por baja a mitad de mes
    - Testigos: CÓDIGO Facturacion.java:41 y :58 · DATOS (pendiente: dos facturas reales de julio) · NEGOCIO (pendiente)
    - Clasificación: PENDIENTE
    - Depende de esto: las facturas ya emitidas con cualquiera de los dos cálculos
    - Tratamiento: especificar tal cual hasta que negocio decida; la corrección no es retroactiva
    - Pregunta: "Hoy una baja del 16 al 30 de julio se cobra de dos formas: 30.00 o 29.03. ¿Cuál es la correcta? (A / B)"

    🛑 La pregunta se puede contestar sin ambigüedad, trae un ejemplo con números y no sugiere la respuesta. La IA no la contesta por el negocio: si no hay con quién hablar, el paso queda bloqueado.

  4. Pega
    Escribe pruebas de caracterización del cargo por baja: el valor esperado es el que produce el código actual, aunque parezca un error. Si una prueba falla, corrige la prueba, nunca el código. Nombre de la prueba de la anomalía: "CONGELA comportamiento actual: A-01 · …". Usa el framework de pruebas que ya existe.
    Debes ver simulado
    @Test
    @DisplayName("CONGELA comportamiento actual: A-01 · baja del 16 al 30 de julio: 30.00 por días y 29.03 proporcional")
    void congelaLosDosCalculosDeLaBaja() {
        assertThat(facturacion.cargoPorDias(new BigDecimal("60.00"), 15)).isEqualByComparingTo("30.00");
        assertThat(facturacion.cargoProporcional(new BigDecimal("60.00"), 15, 31)).isEqualByComparingTo("29.03");
    }

    Súmale un golden master del flujo principal: de 8 a 12 casos fijos cuya salida completa se guarda y se compara campo a campo en cada corrida. Sólo se regenera con una decisión de negocio documentada.

  5. Sólo con los tres candados: la partición en specs aprobada, cero PENDIENTES en el registro y la red de caracterización en verde.

    Pega
    /speckit-specify Spec de ingeniería inversa: documenta el comportamiento EXISTENTE del cargo por baja. No es una feature nueva: es la especificación de lo que el sistema ya hace, para que sirva de contrato. Las anomalías no se corrigen ni se omiten: se especifican tal como funcionan hoy, con su ID del registro (A-01). Cada criterio de aceptación cita la prueba de caracterización que lo verifica, y cada decisión de negocio cita el acta.
  6. Si hay que presentarlo a quien decide, el entregable es un specs/SPEC-PACK.md curso de SDD, sección 7:

    Pega
    Arma specs/SPEC-PACK.md, la entrada al paquete: un resumen ejecutivo sin tecnicismos (qué se hizo, qué se encontró con ejemplos en dinero, qué protección se instaló y qué decisiones quedan pendientes), los riesgos priorizados, un índice comentado de los documentos y qué quedó fuera de la red de pruebas.

    🛑 Y la decisión, sólo con los tres candados cerrados: las specs aprobadas, cero PENDIENTES y la red en verde. Hay tres opciones: documentarlo y dejarlo vivo, modernizarlo (misión 10) o marcarlo obsoleto. Decide quien tiene la autoridad, no el agente.

Misión 10

Moderniza por módulos (strangler fig)

30 minutos · cambiar la implementación sin que nadie lo note

La idea: modernizar no es mejorar el código. Es cambiar la implementación por módulos, incluso con otra tecnología, sin que cambie el comportamiento: el éxito es que nadie lo note. Las correcciones aprobadas llegan después, como specs delta curso de SDD, sección 8, y kit de un equipo.

  1. Pega
    /speckit-constitution Enmienda la constitución: termina la fase de documentación y empieza la de modernización. Principios:
    1. El comportamiento es sagrado por defecto: sólo cambia con una decisión registrada en registro-de-anomalias.md, que cite quién la tomó y cuándo.
    2. Las pruebas de caracterización son el árbitro: un test en rojo sin decisión que lo ampare se resuelve revirtiendo el código, no ajustando el test.
    3. Estrangular antes que reescribir: un módulo a la vez, cada uno con su spec, su extracción y su prueba de equivalencia.
    4. Dependencias nuevas sólo con justificación en la spec y un ADR aprobado por una persona.
    5. Cero retroactividad: lo ya emitido no se toca.
    Comprueba

    Que la constitución tiene versión nueva y fecha de enmienda, y que sigue diciendo que el comportamiento no cambia sin una decisión.

  2. Pega
    Compara los módulos candidatos a modernizar con tres criterios, en este orden: valor (qué cambios o decisiones pendientes bloquea), red (cuántas pruebas de caracterización lo cubren; sin red no se estrangula) y acoplamiento (cuántos consumidores tiene y si toca base de datos, red o reloj). Deja en specs/000-reconocimiento/consumidores-<módulo>.md la lista completa de quién lo usa, con archivo:línea. No elijas tú: recomienda.

    🛑 Decides tú o el arquitecto, con la recomendación delante. Si ningún candidato tiene red suficiente, vuelve a la misión 9 y amplíala primero.

  3. Pega
    /speckit-specify Spec de sustitución del módulo de facturación. Las specs del comportamiento actual son el contrato inmutable. Nueva implementación con las mismas funciones y firmas; cero cambios de comportamiento, anomalías incluidas. Criterios de aceptación: (a) la suite de caracterización completa pasa contra el módulo nuevo; (b) el golden master pasa sin regenerarse; (c) una prueba comparativa corre el módulo viejo y el nuevo sobre muchos casos con semilla fija y exige igualdad campo a campo. La entrada vieja queda como fachada que delega en el nuevo; los consumidores no se tocan. Fuera de alcance: los consumidores, las correcciones de anomalías y cualquier otro módulo.

    Después, el ciclo de siempre: clarify, plan, tasks, analyze e implement (misiones 2 a 4). Si el plan propone tocar consumidores o corregir algo «de paso», devuélvelo: está fuera de alcance.

  4. Haz

    Corre los tres anillos: la suite completa, el golden master sin regenerar y la prueba comparativa. Lee la salida real.

    🛑 Los tres en verde antes de seguir. Si un anillo falla, se corrige el módulo nuevo, nunca la prueba ni el master. Si va a producción con tráfico real, vienen después la paridad en QA, el feature flag y el plan de rollback kit de un equipo. Luego, de vuelta a la tarea 2 con el siguiente módulo.

  5. Con el módulo ya modernizado y la decisión del negocio en mano (D-01: «el correcto es el proporcional»):

    Pega
    /speckit-specify Spec DELTA sobre la spec del cargo por baja: ejecuta la decisión D-01 y cierra la anomalía A-01. Di qué requisitos revoca y cuáles conserva; el comportamiento nuevo con un ejemplo antes y después; cero retroactividad (aplica desde el despliegue). Fuera de alcance: las otras anomalías, cada una en su delta. Criterio: la prueba "CONGELA comportamiento actual: A-01" se sustituye por la del comportamiento nuevo, citando A-01 y D-01.

    Si el negocio todavía no ha decidido, no hay delta: la anomalía sigue congelada.

  6. Una funcionalidad nueva se especifica desde la arquitectura que ya hay, no desde la que te gustaría tener. Meter otro stack aparte deja dos arquitecturas y el doble de lugares donde fallar: un segundo legacy. Si la arquitectura actual no la soporta, primero se moderniza el módulo que hace falta (tareas 2 a 4) curso de SDD, sección 8.

    Comprueba

    Que el plan no mete tecnología que el repo no usa, salvo con un ADR aprobado. Cuando termine la modernización, enmienda otra vez la constitución para dejarla como la de un servicio normal.

Taller: tu kit de skills, agentes y hooks

Así queda tu kit al terminar el curso, misión por misión. Todo es simulado salvo donde se indica.

El kit mínimo, por etapa

PiezaTipoEtapaCuándo correEscribe
AGENTS.md, constitución, config.yamlReglasTodasSiempre—
revisar-specSkillEspecificar → planearCuando pides revisar una specNo
no-saltar-pruebasHookImplementarAntes de cada comando de shell—
conformidadSkill manualAntes del PRSólo con /conformidadNo (lanza al agente)
revisor-conformidadAgenteAntes del PRLo lanza /conformidadNo
revision-cruzadaAgenteAntes de planear o aplicarSi hay specs en paraleloNo
auditor-driftAgenteMantenimientoCada semana, en sesión nueva o en segundo planoNo
investigador-legacyAgenteLegacyAl empezar un reverse-specSólo sus documentos de reconocimiento

Fíjate en el patrón: los agentes revisan y no escriben código, y las skills hacen trabajo corto dentro de tu conversación. Lo que no puede fallar va en un hook.

Plantillas para copiar

---
name: <nombre-en-minusculas>          # igual a la carpeta; 64 caracteres como máximo
description: <Qué hace, en tercera persona>. Usar cuando <frases con que la pediría alguien del equipo>.
disable-model-invocation: true        # quítalo si quieres que el agente la use por su cuenta
---

# <Título>

<Una línea: qué haces y qué NO haces (por ejemplo, "sólo lees").>

1. <Paso concreto, con el comando o el archivo exacto.>
2. <Paso.>
3. <Qué entregas y con qué formato.>

Si falta algo para decidir, dilo y para; no lo supongas.

En Cursor, el cuerpo conviene que quede por debajo de unos 5 000 tokens, y description en 1 024 caracteres o menos cursor.com.

Dónde vive cada pieza

PiezaCursorClaude CodeCodexGitHub Copilot
Skills del repo.cursor/skills/ y .agents/skills/; también lee .claude/skills/ y .codex/skills/.claude/skills/.agents/skills/.github/skills/
Comandos.cursor/commands/.claude/commands/—.github/prompts/*.prompt.md
Agentes.cursor/agents/; también lee .claude/agents/ y .codex/agents/.claude/agents/no lo verificamosno lo verificamos
Hooks.cursor/hooks.json; también aplica los de .claude/settings.json.claude/settings.jsonno lo verificamosSin hooks que bloqueen: exige la suite en CI
Personales (todos tus repos)~/.cursor/skills/, ~/.cursor/agents/, ~/.cursor/hooks.json~/.claude/skills/, ~/.claude/agents/, ~/.claude/settings.json——

Cursor cursor.com/docs: skills, subagents, hooks y third-party-hooks. Rutas de skills y prompts de Claude, Codex y Copilot medidas con lo que instalan Spec Kit y OpenSpec. Lo de Copilot sin hooks kit de un equipo.

No instales de más. Como Cursor también lee .claude/, .agents/ y .codex/, si instalas las mismas skills para dos agentes es probable que en Cursor las veas dos veces inferido de la documentación. Con agentes repetidos, gana el de .cursor/agents/ cursor.com/docs/subagents.

Buenas prácticas que se notan

  • Un propósito por pieza. Si la description necesita «y también…», son dos skills.
  • La description decide todo: qué hace y cuándo usarla, en tercera persona, con las frases que usaría alguien del equipo.
  • Quien revisa no escribe: agentes de revisión siempre con readonly: true y tools sin Edit ni Write.
  • Salida con formato fijo y veredicto (LISTO, NO LISTO…): así se compara de una corrida a otra y se pega en el PR.
  • Evidencia o nada: cada hallazgo con archivo:línea; lo que no se puede citar no se afirma.
  • Máximo tres bloqueantes. Si todo es bloqueante, nada lo es.
  • Fail-fast: si falta un dato, la pieza para y lo pide. Nunca lo adivina.
  • Prueba cada pieza con un caso que debe pasar y otro que no, antes de dársela al equipo.

Antipatrones

AntipatrónQué pasaEn su lugar
Un agente para algo simple («genera el changelog»)Gastas un contexto entero en una tarea de una líneaUna skill
Un agente revisor que puede editar«Arregla» para aprobar, y la revisión deja de ser independientereadonly: true y tools sin Edit ni Write
Una regla crítica sólo en AGENTS.mdEl agente la olvida en un chat largoUn hook
Una description vaga («ayuda con specs»)El agente nunca la carga, o la carga siempreQué hace y cuándo, con frases concretas
Una skill gigante que hace todo el flujoCara en tokens y difícil de corregirUna skill por etapa
Un hook con un patrón demasiado amplioBloquea comandos legítimos y el equipo lo apagaPatrones precisos, probados con casos que pasan y casos que no

Ejercicio final: diseña el kit de tu equipo

El escenario: seis devs, tres servicios en producción y uno nuevo. Quieren specs en español, que nadie se salte pruebas, una revisión antes de cada PR, una auditoría semanal y entender un módulo viejo antes de reemplazarlo. Usan Cursor y Claude Code.

Tu turno: decide qué piezas, de qué tipo, en qué etapa y dónde guardarlas.

Ver una solución
  • Reglas: AGENTS.md con el stack y los no negociables, más CLAUDE.md con @AGENTS.md. openspec/config.yaml en los tres servicios vivos, con --language es y las rules del equipo. Constitución sólo en el servicio nuevo.
  • Hook no-saltar-pruebas en .claude/settings.json. Así lo aplican Claude Code y Cursor sin registrarlo dos veces. Además, la suite completa en CI.
  • Skills en .claude/skills/, que leen los dos: revisar-spec (automática) y conformidad (manual).
  • Agentes en .claude/agents/, todos de sólo lectura: revisor-conformidad, revision-cruzada (son seis devs: habrá specs en paralelo), auditor-drift e investigador-legacy.
  • Flujos: Spec Kit para el servicio nuevo; OpenSpec para los vivos. El módulo viejo pasa por reverse-spec y, si se moderniza, por strangler fig.
  • CI: openspec validate --all --strict y --archived.

Temas avanzados: dónde se practica cada uno

Cada tema avanzado del curso de SDD que sigue el equipo (secciones 4 a 8), con la misión y la tarea donde lo practicas aquí. Los fundamentos (secciones 2 y 3: instalación, constitución, una buena spec, clarify, plan, tasks, analyze, implement, iterar y checklists) están en la ruta exprés y en las misiones 0 a 5.

Sección del cursoTemaDónde se practica
4 · Flujo profesional con gitGit en SDD y el ciclo profesional: una rama por spec, commit por fase, PRMisiones 2 a 5
Gestión de specs con CLAUDE.md y AGENTS.mdMisión 1, tarea 1; decisiones transversales en la misión 3
Extensiones y hooks de Spec KitMisión 2, «quién crea la rama y los commits»
Mapa de SpecsMisión 1, tarea 4, y misión 7
Modificar specs existentesMisión 5, «¿iterarla o crear otra?»
5 · Niveles de SDD con OpenSpecSpec-first, spec-anchored y spec-as-sourceEl mapa, «los tres niveles», y la misión 6
Instalar OpenSpec y config.yamlMisión 0 y misión 1, tarea 5
Primer, segundo y tercer cambio; implementar y archivarRuta exprés, misión 6 y misión 7
Spec drift y cómo evitarlo: continue, verify, MODIFIED en vez de ADDED, bulk-archiveMisión 6 (regla anti-drift y verify) y misión 7
Identificar y resolver driftsMisión 8
Spec-as-sourceSólo se explica, en el mapa
6 · Trabajo en paraleloLo que no se paralelizaMisión 1 (la base en su propio PR) y misión 7, tarea 1
Git worktreesMisión 7, tarea 2
Specs, plan, tareas e implementación en paraleloMisión 7: un agente por worktree
Identificar y resolver conflictos entre specsMisión 7: agente revision-cruzada y «un concepto, una spec dueña»
Integración por orden de riesgoMisión 7, «integra por orden de riesgo»
7 · Reverse specsExploración manual y constitución de la faseMisión 9, tarea 1
Exploración, clasificación y contradiccionesMisión 9, tareas 2 y 3
Entrevista al negocioMisión 9, tarea 3
Characterization tests y specs formalesMisión 9, tareas 4 y 5
Spec Pack, el entregableMisión 9, tarea 6
8 · ModernizaciónConstitución para modernizarMisión 10, tarea 1
Strangler fig y el primer móduloMisión 10, tareas 2 a 4
Corregir contradicciones, anomalías y bugsMisión 10, tarea 5
Funcionalidades nuevas sin erroresMisión 10, tarea 6

Lo que no se practica aquí: modelos locales, entorno gráfico y los modos de aprobación automática de cada agente, que dependen de tu herramienta. Spec-as-source tampoco: sólo se explica.

Biblioteca de prompts

Cambia lo que va entre < y >. Están con los nombres de Cursor; en Claude Code, OpenSpec usa /opsx:…, y en Codex, Spec Kit usa $speckit-….

Especificar desde notas de un tallerSpec Kit · specify

Cuándo: ya hubo sesiones con negocio y no quieres que la IA invente.

/speckit-specify <nombre>. Fuente única: estas notas del taller (<fecha>): <pegar notas o ruta>.
Cada FR termina con su origen entre paréntesis. Lo que las notas no decidan va como [NEEDS CLARIFICATION]; no lo completes con supuestos. Si dos notas se contradicen, escribe la contradicción y no elijas. Al final agrega "## Trazabilidad" con la tabla | FR | Origen | Evidencia |.
Reescribir una spec que ya existeSpec Kit · specify

Cuándo: el resultado no fue el esperado y hay que iterar la misma spec (mientras el servicio nace).

/speckit-specify Reescribe la spec existente @specs/<NNN-nombre>/spec.md; no crees una spec nueva. Los criterios nuevos son: <…>.

Si el cambio es de fondo, borra de esa spec plan, tareas, research, data-model, quickstart y contracts, y repite plan → tasks → analyze → implement.

Implementar por fasesSpec Kit · implement
/speckit-implement Sólo la fase <N>. Por cada tarea: escribe la prueba, confirma que falla, programa, confirma que pasa y marca [X]. Al terminar la fase, corre toda la suite y detente para que revise.
Proponer un comportamiento nuevoOpenSpec · propose
/opsx-propose <nombre-en-kebab>: <qué y por qué en tres líneas>. Fuera de alcance: <…>.
Un comportamiento por requisito, cada uno con un escenario feliz y uno de error. design.md sólo si hay decisiones técnicas. Cada tarea dice cómo se verifica.
Cambiar un requisito que ya existeOpenSpec · propose
/opsx-propose <nombre>: cambia el requisito "<título exacto>" de la capacidad <ruta en openspec/specs> para que <…>. Usa MODIFIED copiando primero el bloque completo actual (texto y todos sus escenarios) y luego edítalo.
Listar ambigüedades (OpenSpec no tiene clarify)OpenSpec · propose
Lista las ambigüedades de la propuesta <cambio> que requieran decisión de negocio. Pregúntamelas una por una y registra cada respuesta en proposal.md con su fecha. Lo que decide otra persona queda como duda; no lo adivines.
Corregir un artefacto a mitad de caminoOpenSpec · continue
En el cambio <cambio>, el delta dice <…> pero lo correcto es <…>. Corrige el artefacto y regenera con /opsx-continue lo que dependa de él. No edites el código por fuera.
Regularizar un driftOpenSpec · propose
/opsx-propose regulariza-<tema>: el código ya hace <…> (evidencia: <archivo:línea>) y es lo deseado. Escribe el delta para que la spec viva lo describa. No implementes nada salvo las pruebas que falten.
Revisión de conformidadAgente
/conformidad <ruta de la spec o del cambio> <rama base>

Sin la skill: «Usa el subagente revisor-conformidad con la spec <ruta> y la base <rama>.»

Revisión cruzada de specs en paraleloAgente
Usa el subagente revision-cruzada para comparar las ramas <rama-1> y <rama-2>. Si no te doy ramas, toma las filas "en curso" de specs/README.md.
Auditoría de drift semanalAgente
Usa el subagente auditor-drift con los últimos <N> días de git. No edites nada; dame el informe y, por hallazgo, la salida que recomiendas.
Integrar una rama por orden de riesgoParalelo

Cuándo: varios cambios hechos en worktrees; se integra primero lo que menos puede romper.

Estás en main. Integra la rama <rama>, que tiene su propio worktree: haz el merge. Si da conflictos, analiza cada uno y propón la solución completa antes de aplicarla. Si entra limpio, corre todas las pruebas; si fallan, analiza por qué y propón cómo resolverlo. No borres worktrees ni ramas todavía.
Limpiar al terminar de integrarParalelo
Ya integré las ramas <ramas>. Detén lo que esté corriendo en sus worktrees, borra esos worktrees y sus ramas, cierra sus specs y marca cada una como publicada en specs/README.md. Muéstrame git worktree list y git status al final.
Requisitos sin pruebaRevisión
Lista los requisitos de <spec> (FR-### o "### Requirement:" con sus escenarios) y busca en <carpeta de pruebas> qué prueba cita cada uno en su nombre. Tabla: requisito | prueba | archivo. Marca los que no tienen prueba y enséñame el comando de búsqueda que usaste.
Crear una skillSkills
Crea una skill en .cursor/skills/<nombre>/SKILL.md que <qué hace>, para la etapa <etapa>. name igual a la carpeta y en minúsculas; description en tercera persona, con qué hace y cuándo usarla; <con o sin> disable-model-invocation; menos de 150 líneas. Después dame un caso de prueba que debe funcionar y uno que no.
Crear un agente de sólo lecturaSkills
Crea un subagente en .claude/agents/<nombre>.md que <qué revisa>, para la etapa <etapa>. Sólo lectura en los dos agentes: tools: Read, Grep, Glob, Bash y readonly: true. Que cite archivo:línea en cada hallazgo, entregue máximo 3 bloqueantes y una salida con formato fijo y veredicto.
Crear un hookHooks
Crea un hook de proyecto en .cursor/hooks.json que <qué bloquea o revisa> en el evento <evento>. El script va en .cursor/hooks/, lee el JSON de stdin y sale con 2 para bloquear. Pruébalo con una entrada que debe pasar y otra que debe bloquearse antes de darlo por bueno.
Convertir un comando en skillSkills
Convierte el comando <ruta del .md> en una skill personal en ~/.cursor/skills/<nombre>/SKILL.md, con disable-model-invocation: true, sin cambiar sus pasos. Dime qué partes dependían de otra herramienta.
Reconocimiento por capasLegacy
Investiga <módulo> sólo leyendo y entrega en specs/000-reconocimiento/: mapa-sistema.md, flujo-<entidad>.md, registro-riesgos.md y memoria-historica.md. Cada afirmación con archivo:línea. Lo que tenga un solo testigo, PENDIENTE con la pregunta exacta que lo destrabaría.
Preguntas decidibles para el negocioLegacy
Con los PENDIENTES de registro-de-anomalias.md, redacta preguntas para negocio: contexto mínimo, lenguaje no técnico, un ejemplo con números reales, respuesta sí/no o a elegir, sin sugerir la respuesta, ordenadas por impacto económico y dirigidas a una persona.
Elegir el siguiente módulo a modernizarModernización
Compara los módulos candidatos a modernizar por valor (qué cambios pendientes bloquea), red (cuántas pruebas de caracterización lo cubren) y acoplamiento (consumidores y si toca base de datos, red o reloj). Deja la lista de consumidores de cada uno con archivo:línea. Recomienda; no elijas tú.
Funcionalidad nueva sin «feature isla»Modernización
/speckit-specify <funcionalidad>. Especifícala desde la arquitectura que ya tiene el repo (ver AGENTS.md); no propongas otro stack ni un servicio aparte. Si la arquitectura actual no la soporta, dime qué módulo habría que modernizar primero.
Pruebas de caracterizaciónLegacy
Escribe pruebas de caracterización de <módulo>: el valor esperado es el que produce el código actual. Si una prueba falla, corrige la prueba, nunca el código. Una prueba por anomalía con nombre "CONGELA comportamiento actual: A-xx · …"; toda frontera en tres puntos (debajo, el valor y encima). Usa el framework de pruebas que ya existe.

Formato de OpenSpec y trampas

Qué quieresEncabezadoRegla
Agregar comportamiento## ADDED RequirementsSi la capacidad es nueva, el delta empieza con ## Purpose (una o dos oraciones, 50 caracteres o más)
Cambiar comportamiento## MODIFIED RequirementsCopia el bloque completo de la spec viva y edítalo; el título debe coincidir
Quitar comportamiento## REMOVED RequirementsLleva **Reason** y **Migration**
Sólo renombrar## RENAMED RequirementsFormato FROM: / TO:
  • Cada requisito: ### Requirement: <nombre> y un texto con SHALL o MUST, en mayúsculas y como palabra completa.
  • Cada escenario: #### Scenario: con exactamente cuatro #, y las líneas - **WHEN** … / - **THEN** …. Al menos uno por requisito.
  • Descripción de un requisito nuevo: 500 caracteres o menos; si no, --strict falla.
  • Un cambio sin cambio de comportamiento (refactor, documentación) pone skip_specs: true en su .openspec.yaml; no inventa un requisito.
  • En español: el contenido va en español; los encabezados y SHALL/MUST, en inglés. El init con --language es lo deja escrito en config.yaml.

Todo medido de openspec instructions specs y del validador.

Trampas medidas

Escribir «DEBE» en lugar de SHALL o MUST
$ openspec validate debe-en-espanol
Change 'debe-en-espanol' is valid
⚠ [WARNING] prueba-de-idioma/spec.md: ADDED "Rechazar altas de productos de marcas bloqueadas" should contain SHALL or MUST (RFC 2119 best practice for English specs)
$ openspec validate debe-en-espanol --strict
Change 'debe-en-espanol' has issues
⚠ [WARNING] prueba-de-idioma/spec.md: ADDED "Rechazar altas de productos de marcas bloqueadas" should contain SHALL or MUST (RFC 2119 best practice for English specs)
Next steps:
  - Ensure change has deltas in specs/: use headers ## ADDED/MODIFIED/REMOVED/RENAMED Requirements
  - Each requirement MUST include at least one #### Scenario: block
  - Debug parsed deltas: openspec show debe-en-espanol --json --deltas-only
$ echo $?
1
Archivar con tareas pendientes usando -y
$ openspec archive bloquear-marcas -y
Task status: 0/5 tasks
Warning: 5 incomplete task(s) found. Continuing due to --yes flag.

Specs to update:
  bloqueo-de-marcas: create
Applying changes to openspec/specs/bloqueo-de-marcas/spec.md:
  + 2 added
Totals: + 2, ~ 0, - 0, → 0
Specs updated successfully.
Change 'bloquear-marcas' archived as '2026-10-18-bloquear-marcas'.
Un MODIFIED que omite escenarios
$ openspec archive texto-de-bloqueo -y
Task status: ✓ Complete

Specs to update:
  bloqueo-de-marcas: update
bloqueo-de-marcas MODIFIED failed for header "### Requirement: Bloquear y desbloquear una marca" - current spec contains scenario(s) not present in the modified block: "Bloqueo sin motivo", "Otro rol intenta bloquear". The modified block has 1 scenario; the current spec has 3 scenarios. It adds none. Refresh the change spec before archiving to avoid dropping scenarios.
Aborted. No files were changed.
$ echo $?
1

Problemas comunes

Un hook bloqueó un comando que no se saltaba nada

El hook mira el texto del comando: si tu comando contiene el patrón, aunque sea como dato, lo bloquea. Ajusta el patrón para que sea preciso. Si el hook es del equipo, no lo rodees; dilo.

Los hooks de Spec Kit no se ejecutaron (no creó la rama o no hizo commit)

Los hooks de .specify/extensions.yml son instrucciones que el agente debe seguir, y a veces se las salta. Revisa specify extension list y pídele que corra el hook. Si algo no puede fallar, ponlo en un hook del agente (misión 4) o en el CI.

Al integrar ramas, choca .specify/feature.json

Es el puntero de Spec Kit a la spec activa, y cada rama lo cambia. Quédate con la versión de la rama principal.

Mi agente no aparece o el principal no lo usa

Revisa la carpeta (.cursor/agents/ o .claude/agents/) y que description diga cuándo usarlo. Pídelo por nombre: «Usa el subagente <nombre>…» o /<nombre>. Abre un chat nuevo después de crearlo.

Mi agente revisor editó archivos

En Cursor le falta readonly: true: tools no está documentado ahí y los subagentes heredan todas las herramientas. En Claude Code, quítale Edit y Write de tools.

Mi hook no se dispara

Revisa "version": 1 en hooks.json, que el script tenga chmod +x y la ruta relativa a la raíz del proyecto. Mira el canal de salida «Hooks» de Cursor. En los de Claude Code, cada entrada debe traer la clave matcher foro oficial de Cursor.

SyntaxError: Unexpected token 'with' al correr openspec

Tu Node es anterior a 20.19. Actualízalo y abre otra terminal; con nvm, cambia también la versión predeterminada.

Veo cada skill dos veces en Cursor

Instalaste las mismas skills para dos agentes. Cursor lee también .claude/skills/ y .agents/skills/. Deja una: specify integration uninstall <agente>.

openspec validate --strict pide SHALL o MUST

Escribiste «DEBE». Usa SHALL o MUST; el resto puede ir en español.

«Ensure change has deltas in specs/»

Falta el delta o los encabezados no son exactos (## ADDED Requirements, #### Scenario: con cuatro #). Depura con openspec show <cambio> --json --deltas-only.

/speckit-plan trabaja sobre otra feature

Las skills leen la feature activa de .specify/feature.json. Ábrelo o pásale la ruta de la spec.

No aparecen los comandos después de instalar

Reinicia el IDE (OpenSpec lo pide al terminar) o abre un chat nuevo, y confirma que abriste el agente en la carpeta donde corriste init.

Chuleta de comandos

specify init --here --force --integration <agente> --script shInstalar en el repo actual
specify integration list | install | status | upgrade | switch | uninstallAdministrar agentes y sus skills
specify self check · specify self upgradeBuscar y aplicar actualización
/speckit-constitution · -specify · -clarify · -plan · -checklist · -tasks · -analyze · -implement · -convergeEl ciclo, en el chat

Fuentes y versiones

Cómo se midió. Un script corre las dos herramientas de verdad en una carpeta temporal y guarda sus archivos y salidas. Mide la inicialización para Cursor, Claude, Codex y Copilot, el ciclo de dos cambios de OpenSpec, la extensión git de Spec Kit y sus hooks, los worktrees, las reglas de config.yaml llegando al agente, los casos permitidos del hook y la revisión requisito → prueba. El bloque que crea la skill y el agente de la ruta exprés se ejecuta y se compara con los originales cada vez que se genera la página. Las rutas de la máquina se reemplazaron por ~/mi-proyecto. Las misiones, los flujos de reverse-spec y modernización, y los agentes de revisión se basan en el kit de un equipo que trabaja así. Aquí van en versiones genéricas.

Fecha de la medición: 2026-10-18.