Saltar al contenido
Volver a todas las notas sdd · 7 min

Añadir specs a un repo existente sin parar el mundo

Casi todo el software ya existe. El spec-driven tiene que encontrarse con un repositorio vivo donde está, no donde lo finge un tutorial de proyecto nuevo.

nota de campo 7 min

Todos los tutoriales de spec-driven empiezan con una carpeta vacía. Corres un comando, describes una feature y ves cómo un agente la construye limpia. Es una demo bonita y describe casi nada del software que existe de verdad.

Tu situación real es un repositorio con cuatro años de historia, patrones que nadie escribió y un puñado de módulos que todo el mundo tiene miedo de tocar. No puedes dejar de publicar para escribir specs de todo, y no puedes pedirle a un agente que trabaje contra un contrato que no existe. Así que el desarrollo guiado por especificaciones queda archivado como «gran idea, repo equivocado» y vuelves a describir cambios en un chat y a cruzar los dedos.

Ese planteamiento es el error. No añades specs a un repo existente especificándolo todo. Las añades donde va a caer el próximo cambio, y dejas que la cobertura crezca desde ahí.

Por qué falla aquí el manual del proyecto nuevo

En un repo vacío, la spec va antes que el código, así que la intención se captura mientras aún es barata. En un repo existente, el código fue primero y la intención que hay detrás está repartida entre mensajes de commit, tickets cerrados y la memoria de la gente. Escribir una spec ahora significa hacer ingeniería inversa de una decisión que se tomó hace dos años por alguien que quizá ya no está.

Eso es trabajo de verdad, y no se paraleliza en un único sprint heroico. Intentar especificar el sistema entero por adelantado produce un montón de documentos que ya están derivando cuando se escribe el último. Acabas con spec drift el día uno, que es peor que no tener specs, porque ahora los documentos mienten de forma activa.

La unidad que funciona es el cambio, no el sistema. No le debes al código una especificación completa. Le debes al próximo cambio un contrato.

Especifica en la frontera del próximo cambio

El movimiento es este. Cuando un cambio va a tocar una parte del sistema, escribe la spec de esa parte, acotada a lo que el cambio necesita, y no más ancha.

Digamos que vas a modificar la lógica del cupón en checkout. Antes de que el agente empiece, escribes qué hace hoy el checkout que tiene que seguir siendo cierto, qué puede alterar este cambio y cómo reconocerás un resultado correcto. Eso es una spec. Cubre el checkout, no la app entera. Te llevó veinte minutos porque solo especificaste la superficie que el cambio toca de verdad.

Ahora el agente tiene un contrato. Conoce los invariantes que no puede romper, que es exactamente la información que impide que sea correcto en local e incoherente en global, arreglando tu feature mientras rompe en silencio una vecina. La spec no necesitaba cubrir el universo. Necesitaba cubrir el radio de la explosión.

Repite esto en cada cambio y pasa algo útil: las partes del sistema que cambian a menudo acumulan specs rápido, y las partes que nadie toca se quedan sin especificar, lo cual está bien, porque el código estable sin especificar no es lo que te está haciendo daño.

Hay un segundo beneficio fácil de pasar por alto. La primera vez que especificas la superficie de un cambio, pagas el coste de la ingeniería inversa una sola vez. El siguiente cambio a ese mismo módulo arranca desde un contrato que ya existe, así que estás editando una spec en lugar de reconstruir la intención desde cero. Los módulos que más se mueven son justo aquellos donde este efecto compuesto más importa, y son los primeros en cruzar el trinquete. Estás adelantando la arqueología en el código que te haría cavar otra vez de todos modos, y saltándotela en el código que no la pide nunca.

Lee el código y saca un primer borrador

No tienes que escribir estas specs desde una página en blanco. El código ya es la descripción más precisa de lo que hace el sistema, solo que está en la forma equivocada. Un agente puede leer el módulo que vas a cambiar y producir un borrador de spec de su comportamiento actual: las entradas que acepta, los invariantes que parece mantener, los caminos que cubre.

Ese borrador estará mal en algunos sitios, y estar mal es útil. Corregir un borrador es mucho más rápido que redactar desde cero, y cada corrección que haces es una decisión que estás recuperando del código y volviendo a escribir. Esta es la versión práctica de leer un repo y sacar artefactos de producto: el repositorio deja de ser un muro opaco y empieza a soltar las historias, criterios y restricciones enterrados en él.

Para que esto funcione, el agente tiene que entender de verdad la forma del código, no solo hacerle grep. Ese es el argumento a favor de mapas del código en lugar de prompts más largos: un modelo de cómo se relacionan los módulos da al borrador de spec muchas más probabilidades de nombrar los invariantes correctos.

Mantén el trinquete girando

El objetivo no es el cien por cien de cobertura. El objetivo es un trinquete que solo gira en una dirección: cada cambio deja detrás una spec, así que la superficie especificada crece de forma monótona y nunca se encoge. No necesitas una congelación, una reescritura ni un mandato de cobertura. Necesitas una regla: un cambio no se publica sin un contrato para la superficie que tocó. Esa regla es barata de enunciar y cabe dentro del trabajo que ya ibas a hacer, porque tenías que entender la superficie para cambiarla sin romper nada de todos modos. La spec es justo ese entendimiento, escrito donde el agente y la siguiente persona puedan leerlo los dos.

Sostenido, esto produce justo la cobertura que quieres. Los caminos calientes que cambian cada mes acaban bien especificados porque siguen pasando por el trinquete. El código frío se queda desnudo, y eso es correcto, porque no es el código que te genera incidencias. Esta es la versión ligera del desarrollo guiado por especificaciones, donde la spec se gana su sitio por cambio en lugar de llegar como un impuesto burocrático sobre todo.

Dónde encaja PaellaDoc

Añadir specs a un repo vivo es justo la situación para la que está construido PaellaDoc. Puede leer un código existente y convertirlo en un modelo local, redactar el comportamiento del módulo que vas a cambiar y dejarte corregirlo hasta un contrato real antes de que el agente empiece. Esa spec se queda después unida al código que la implementa, así que la próxima vez que el módulo cambie estarás editando un contrato que ya existe en lugar de volver a hacer ingeniería inversa de todo.

No paras el mundo para adoptar el desarrollo guiado por especificaciones. Enganchas un contrato al próximo cambio, luego al siguiente, y dejas que la superficie especificada crezca a la velocidad a la que se mueve de verdad el código.

Preguntas frecuentes

¿Tengo que especificar todo mi repo para que esto ayude? No. Ese es el modo de fallo. Especificas la superficie del próximo cambio, lo publicas y repites. La cobertura crece en las partes que cambian a menudo, que son las que la necesitan.

¿Y los módulos estables que nadie toca? Déjalos sin especificar. El código estable que nunca cambia no te genera incidencias. Gasta el esfuerzo donde de verdad está cayendo el cambio.

¿Puede un agente escribir la primera spec de código viejo? Sí, como borrador. Lee el módulo y describe su comportamiento actual, y tú corriges el borrador. Arreglar un borrador equivocado es mucho más rápido que escribir desde una página en blanco, y cada arreglo recupera una decisión que el código escondía.