Mantener especificaciones, pruebas y código sincronizados en el desarrollo de IA

Evita que los agentes de IA se desvíen de las especificaciones, las pruebas y el código.

Índice

Los agentes de codificación con IA implementan características rápidamente, pero las especificaciones, las pruebas y el código se desvían silenciosamente entre sí. Esta guía cubre un modelo de trazabilidad, el mapeo de especificación a prueba y de especificación a código, y las verificaciones de integración continua (CI) que detectan la desviación antes de una fusión.

Una especificación que nadie vuelve a verificar contra el sistema en ejecución es peor que no tener especificación en absoluto, porque crea una confianza falsa. Los revisores confían en el documento en lugar de en la diferencia de código (diff), y un agente de IA solicitado a “seguir el patrón existente” seguirá felizmente lo que el código realmente hace, incluso cuando eso contradiga el requisito que se suponía debía satisfacer.

La solución no es más documentación. Es un pequeño vínculo ejecutable entre cuatro cosas que ya existen en la mayoría de los repositorios: el requisito, la decisión de diseño detrás de él, las pruebas que lo demuestran y los commits o solicitudes de extracción (pull requests) que lo modificaron.

enlaces de trazabilidad conectando especificaciones, pruebas y código

Una vez que ese vínculo existe como datos en lugar de como un entendimiento compartido, puedes consultarlo. Puedes preguntar qué requisitos no tienen cobertura de pruebas, qué pruebas ya no se mapean a ningún requisito y qué archivos cambiaron en una solicitud de extracción sin un ID de requisito coincidente. Esa consulta es el entregable real de este artículo, y el resto de la publicación explica cómo construirlo con herramientas que probablemente ya ejecutas.

El problema de la desviación: Por qué las especificaciones, las pruebas y el código se desincronizan

La desviación aparece en cuatro formas reconocibles, y los equipos asistidos por IA tienden a encontrarse con las cuatro más rápido que los equipos que escriben cada línea a mano.

  • La especificación cambia, el código no. Un requisito se clarifica en una conversación de seguimiento o en un hilo de comentarios, pero nadie regenera o edita la implementación para que coincida.
  • El código cambia, la especificación no. Un agente o un desarrollador corrige un error o refactoriza un módulo, y la especificación sigue describiendo el comportamiento antiguo como si todavía estuviera vigente.
  • Las pruebas cubren la implementación, no la intención. Las pruebas unitarias afirman lo que el código hace actualmente, lo cual es circular: pasan por construcción incluso cuando el código satisface el requisito equivocado.
  • Las solicitudes de extracción no hacen referencia a los requisitos. Los revisores aprueban una diferencia en base a que “parece razonable” porque no hay una afirmación explícita contra la cual verificarla.

La investigación de procesos reciente sobre marcos de desarrollo de IA identifica la desviación de especificaciones como un riesgo recurrente precisamente porque los agentes regeneran código rápidamente y repetidamente, y cada regeneración es una nueva oportunidad para que la especificación y la implementación se desvíen un poco más. El debate sobre el Desarrollo Guiado por Especificaciones vs. Codificación por Vibe es realmente una discusión sobre este mismo modo de fallo: una especificación que nadie aplica se degrada en la misma desviación que obtienes sin ella, solo con más formalismos.

Los flujos de trabajo modernos de estilo “spec-kit” enmarcan cada vez más esto como putrefacción de especificaciones: la especificación sigue pareciendo autoritativa mientras pierde silenciosamente su conexión con lo que el sistema realmente hace. La definición central del desarrollo guiado por especificaciones trata la especificación como la fuente de verdad, pero una fuente de verdad solo se mantiene verdadera si algo la verifica constantemente contra la realidad.

Un modelo de trazabilidad para el desarrollo asistido por IA

Un modelo de trazabilidad funcional necesita seis identificadores que conecten un requisito comercial hasta llegar a las líneas de código y la solicitud de extracción que lo implementó. La mayoría de los equipos ya tienen tres o cuatro de estos; los que faltan suelen ser el ID de decisión de diseño y el vínculo explícito de regreso desde las pruebas y los commits.

Identificador Vive en Ejemplo
ID de Requisito requirements.md o herramienta de especificación REQ-014
ID de Decisión de Diseño ADR / registro de decisiones ADR-0032
ID de Tarea desglose de tareas o rastreador de incidencias TASK-014-3
ID de Prueba archivo de prueba o nombre de prueba test_req_014_password_reset
Enlace de Commit / PR historial de Git PR #482
Archivos cambiados diferencia de Git auth/reset.go, auth/reset_test.go

Las relaciones entre estos identificadores forman un grafo en lugar de una línea recta, porque un requisito puede generar varias tareas, y una solicitud de extracción puede tocar varios requisitos a la vez.

graph TD REQ["Requisito
REQ-014"] --> ADR["Decisión de Diseño
ADR-0032"] ADR --> TASK["Tarea
TASK-014-3"] TASK --> CODE["Cambio de Código
auth/reset.go"] TASK --> TEST["Prueba
test_req_014_password_reset"] CODE --> PR["Solicitud de Extracción
#482"] TEST --> PR PR --> COMMIT["Historial de Commits"]

Almacenar este grafo como datos estructurados, no como prosa, es lo que te permite consultarlo más tarde. El ecosistema Spec Kit de GitHub se ha movido exactamente en esta dirección: extensiones como spec-kit-trace escanean tokens REQ-XXX incrustados en archivos de especificación y archivos de prueba y generan una matriz determinista a partir de esa coincidencia literal de texto, evitando deliberadamente las conjeturas difusas basadas en nombres que producen falsos positivos silenciosos.

Mapeo de Especificación a Prueba: Transformando Criterios de Aceptación en Casos de Prueba

Cada criterio de aceptación en una especificación es, por construcción, una afirmación de comportamiento: dado este estado, cuando el actor hace esto, entonces el sistema debería responder de esa manera. Esa es ya la forma de un caso de prueba, que es por qué los flujos de trabajo SDD (Desarrollo Guiado por Especificaciones) más fuertes generan pruebas a partir de los mismos criterios de aceptación que generan el código, en lugar de pedirle al agente generador de código que también invente sus propias pruebas después del hecho.

Un formato ampliamente utilizado para escribir estos criterios es EARS (Enfoque Fácil para la Sintaxis de Requisitos), que obliga a cada requisito a un patrón inequívoco y probable como “Cuando <disparador>, el sistema deberá <respuesta>.” Esa estructura se mapea limpiamente a cuatro categorías de prueba que cada requisito debe llevar:

  • Pruebas positivas — el camino feliz que el requisito describe explícitamente.
  • Pruebas negativas — entradas o estados que el requisito dice que deben ser rechazados.
  • Pruebas de límites — los bordes de rangos, límites y umbrales mencionados en los criterios de aceptación.
  • Pruebas de migración — comportamiento para datos o estados que preceden al requisito, para que un registro antiguo no omita silenciosamente una nueva regla.
Tipo de Requisito Categoría de Prueba a agregar Error Común
“El sistema debe rechazar X” Negativa Solo se prueba el camino de aceptación
“El límite es de N elementos” Límite N-1, N y N+1 no están todos cubiertos
“Nuevo campo reemplaza campo antiguo” Migración Los registros antiguos sin nuevo campo fallan silenciosamente
“Dentro de 60 segundos” Límite + temporización La prueba afirma la lógica, no el presupuesto de tiempo real

Las pruebas unitarias escritas de esta manera siguen siendo importantes como la capa rápida y económica de la pirámide; los patrones prácticos para estructurarlas se cubren en la guía de pruebas unitarias en Go y la guía de pruebas unitarias en Python. Lo que la trazabilidad añade encima es un token de requisito literal y estable incrustado en el nombre de la prueba o en un comentario de prueba, para que una consulta posterior pueda demostrar — no asumir — que REQ-014 tiene cobertura.

Mapeo de Especificación a Código: De Planes de Diseño a una Tabla de Trazabilidad

El mapeo de especificación a prueba demuestra el comportamiento; el mapeo de especificación a código demuestra el alcance. Responde a una pregunta diferente: ¿qué archivos se suponía que debían cambiar para este requisito, y se mantuvo la diferencia dentro de ese límite o se derramó en módulos no relacionados?

Un plan de diseño que liste los archivos afectados de antemano — incluso una lista aproximada — te da algo contra lo cual comparar la solicitud de extracción real más tarde. Los comentarios en el código solo deben hacer referencia a un ID de requisito cuando hacerlo añade información que un revisor no puede obtener de la especificación en sí; un comentario que repite el texto del requisito textualmente es ruido, pero // aplica límite de REQ-014: máximo 5 intentos de restablecimiento por hora justifica su lugar porque el número es invisible en la diferencia.

Una tabla de trazabilidad generada convierte esto en algo revisable en segundos en lugar de algo que un revisor tiene que reconstruir leyendo ambos documentos lado a lado:

Requisito Decisión de Diseño Archivos Cambiados Pruebas Estado
REQ-014 ADR-0032 auth/reset.go, auth/reset_test.go test_req_014_* (4) Cubierto
REQ-015 ADR-0032 auth/reset.go ninguna Brecha
REQ-016 auth/notify.go test_notify_basic Enlace de especificación huérfano

Esa única tabla muestra de un vistazo dos de los patrones de fallo más comunes: REQ-015 cambió código con cero pruebas coincidentes, y la prueba adjunta a REQ-016 no hace referencia a un ID de requisito, lo que significa que o bien falta la especificación o la prueba fue archivada incorrectamente.

El flujo de trabajo de la solicitud de extracción: Revisando especificaciones, código y diferencias de pruebas juntos

Una solicitud de extracción construida alrededor de la trazabilidad revisa tres diferencias lado a lado en lugar de una: qué cambió en la especificación, qué cambió en el código y qué cambió en las pruebas. La pregunta de revisión deja de ser “¿esto parece correcto?” y se convierte en la mucho más específica “¿qué requisito satisface este cambio y la evidencia lo demuestra?”.

sequenceDiagram participant Dev as Desarrollador o Agente participant PR as Solicitud de Extracción participant CI como Pipeline de CI participant Rev como Revisor Dev->>PR: Abrir PR con diferencia de especificación + diferencia de código + diferencia de pruebas PR->>CI: Disparar verificaciones de trazabilidad CI->>CI: Verificar que el ID de REQ esté presente en la descripción del PR CI->>CI: Ejecutar verificación de cobertura de especificación a prueba CI->>CI: Ejecutar verificación de alcance de archivos de especificación a código CI-->>PR: Publicar informe de trazabilidad como comentario en el PR Rev->>PR: Revisar contra "¿qué requisito satisface esto?" Rev->>PR: Aprobar o solicitar cambios

Una lista de verificación de revisión corta y concreta funciona mejor aquí que una larga, porque los revisores omiten listas largas bajo presión de plazos:

  1. ¿La descripción de la solicitud de extracción nombra el/los ID(s) de requisito que satisface?
  2. ¿Cada archivo cambiado aparece en la lista de archivos afectados del plan de diseño, o se explica el alcance adicional?
  3. ¿Al menos una nueva o prueba existente hace referencia a cada ID de requisito tocado por esta solicitud de extracción?
  4. Si la especificación cambió, ¿el código y las pruebas cambiaron en la misma solicitud de extracción, o hay un seguimiento registrado?

Automatizando la trazabilidad en CI

La revisión manual detecta la desviación solo tan a menudo como los revisores recuerden buscarla, que es por qué las verificaciones anteriores pertenecen en CI en lugar de en una página de wiki que nadie vuelve a leer. Los mismos patrones de hoja de trucos de GitHub Actions que ya usas para trabajos de compilación y prueba se aplican directamente aquí: las verificaciones de trazabilidad son solo otro trabajo en la misma canalización.

Ideas prácticas de automatización, aproximadamente en orden de esfuerzo:

  • Verificaciones CI para archivos de especificación — fallar la compilación si un archivo de especificación fue editado sin un cambio de código o prueba correspondiente en la misma solicitud de extracción, o viceversa.
  • Requerir IDs de requisito en títulos o descripciones de solicitudes de extracción — una verificación ligera de expresión regular (REQ-\d+) bloquea fusiones que no nombran lo que implementan.
  • Resúmenes de trazabilidad generados por agente — tener un agente que produzca un resumen corto de qué requisitos toca una solicitud de extracción, para que un humano confirme en lugar de escribir desde cero.
  • Cobertura de pruebas por criterio de aceptación, no solo por línea — la cobertura de líneas te dice que el código se ejecutó; la cobertura de requisitos te dice que una afirmación fue verificada.
  • Advertencias de especificaciones obsoletas — marcar especificaciones que no han sido tocadas en N commits que tocan sus archivos vinculados, ya que las especificaciones silenciosas durante mucho tiempo son las más propensas a haberse putrefactos silenciosamente.

Las extensiones construidas sobre el Spec Kit de GitHub ya implementan varias de estas mecánicamente: una escanea tokens literales REQ-XXX a través de archivos de especificación y prueba para construir una matriz y marcar pruebas huérfanas, y un paquete más estricto orientado al Modelo V va más allá, generando una especificación de prueba emparejada para cada especificación de desarrollo y produciendo múltiples matrices de trazabilidad para equipos que trabajan bajo marcos regulatorios como IEC 62304 o ISO 26262. No necesitas ese nivel de formalismos para la mayoría de los proyectos, pero la idea subyacente — una matriz determinista generada por script en lugar de una hoja de cálculo mantenida a mano — escala hacia abajo tan bien como escala hacia arriba.

Usando agentes de IA para la trazabilidad, no como un oráculo

Los agentes de IA son adecuados para las partes mecánicas de la trazabilidad y poco adecuados para ser el juez final de si un requisito fue realmente satisfecho. Tres tareas encajan directamente en las fortalezas de un agente:

  • Comparar especificación y diferencia — pedir al agente que liste cada requisito mencionado en los archivos de especificación tocados por una solicitud de extracción, y cada uno para el cual no encontró código correspondiente.
  • Encontrar requisitos no cubiertos — pedir al agente que escanee el conjunto de pruebas en busca de tokens de requisito y reporte qué requisitos en la especificación no tienen ninguno.
  • Detectar código no descrito por la especificación — pedir al agente que marque archivos o funciones cambiadas que toquen módulos con requisitos pero que no correspondan a ningún ID de requisito en la diferencia.

El modo de fallo contra el cual hay que protegerse es confiar en el resumen del agente como verdad fundamental en lugar de como punto de partida para el revisor. Un agente puede malinterpretar un comentario, omitir un token de requisito dividido en dos archivos o declarar con confianza cobertura para una prueba que solo ejercita el camino del código superficialmente. Trata cada informe de trazabilidad generado por agente como tratarías el paso de un revisor junior: útil, rápido y aún sujeto a una segunda mirada antes de que bloquee una fusión. Esta es la misma precaución que se aplica a los registros de decisiones para el desarrollo impulsado por IA — el registro solo se mantiene confiable si algo distinto del agente que lo escribió eventualmente lo verifica.

Una plantilla de trazabilidad mínima que puedes copiar

No necesitas un marco de trabajo pesado para comenzar. Una plantilla de cinco archivos, registrada en el repositorio junto al código que describe, cubre lo esencial:

docs/
  requirements.md     # IDs de REQ con criterios de aceptación estilo EARS
  design.md           # IDs de ADR, archivos afectados, decisiones de arquitectura
  tasks.md            # IDs de TAREA mapeados a uno o más IDs de REQ
  tests.md            # qué archivos/funciones de prueba hacen referencia a qué IDs de REQ
  traceability.md     # tabla generada: REQ -> ADR -> TAREA -> archivos -> pruebas -> PR

requirements.md, design.md y tasks.md son escritos o editados por humanos y agentes juntos, de la misma manera que ya describe el flujo de trabajo de desarrollo guiado por especificaciones. tests.md y traceability.md deberían ser generados, no mantenidos a mano, incluso si el generador es un script corto que simplemente busca REQ-\d+ a través del directorio de pruebas y los archivos de especificación — las tablas de trazabilidad mantenidas a mano son en sí mismas una forma de riesgo de desviación, porque nadie actualiza una hoja de cálculo bajo presión de plazos.

Conclusión

El desarrollo guiado por especificaciones no termina en el momento en que el código sale de un agente; solo es útil una vez que el código, las pruebas y las especificaciones se mantienen honestos entre sí con el tiempo, a través de solicitudes de extracción, refactorizaciones y cambios de requisitos que llegan meses aparte. Un modelo de trazabilidad construido a partir de seis identificadores simples, aplicado por un puñado de verificaciones de CI y revisado con una lista de verificación corta de solicitudes de extracción, te da la mayor parte del beneficio sin la sobrecarga de un marco de cumplimiento completo. Comienza con la plantilla mínima, conecta primero la verificación de CI más barata — IDs de requisito en descripciones de solicitudes de extracción — y añade la tabla de trazabilidad y las advertencias de especificaciones obsoletas una vez que ese hábito se adquiera.

La trazabilidad es una pieza de una disciplina más amplia de pruebas y documentación cubierta en el clúster de Arquitectura de Aplicaciones en Producción, y se sitúa junto a las preguntas de herramientas exploradas en el clúster de Herramientas de Desarrollo para IA para equipos que eligen qué flujos de trabajo de agentes estandarizar.

Suscribirse

Recibe nuevas publicaciones sobre sistemas, infraestructura e ingeniería de IA.