Añades una feature. Algo no relacionado deja de funcionar. Arreglas eso, y se rompe una tercera cosa. Cada paso adelante te cuesta un paso en un sitio donde no mirabas, y la app que antes crecía en minutos ahora se mueve como si vadeara barro. Si has sentido esto, no estás siendo descuidado. Te falta una cosa concreta, y tiene nombre.
Lo que falta es un contrato entre tus features. Nada en la app dice qué promete cada parte a las demás, así que nada impide que una parte viole en silencio las asunciones de otra. Junta suficientes partes y los choques no son mala suerte, son aritmética.
Por qué pasa esto, con precisión
Cada feature de una app vibe-coded se generó más o menos por su cuenta. El agente tuvo esa feature a la vista, la hizo funcionar, y asumió que el resto de la app se quedaría quieta a su alrededor. Esa asunción casi siempre es tácita, y casi siempre es falsa.
La feature dos asumió que el registro de usuario tenía cierta forma. La feature seis cambió esa forma para hacer su propio trabajo. Nada registró que la feature dos dependía de la forma vieja, así que nada avisó a nadie. La feature dos ahora está rota, y seguirá rota hasta que un usuario la encuentre, porque no había ningún contrato que violar en voz alta.
Multiplica esto a través de una app que crece. El número de maneras en que las features pueden depender en silencio unas de otras crece mucho más rápido que el número de features. Por eso el dolor es leve al principio y luego, pasado un puñado de features, parece explotar. Es el mismo componer que produce el ajuste de cuentas hacia el mes 3: lo que te desborda son las interacciones, no las features.
Por qué los agentes lo agudizan
Un humano que construye despacio tiende a llevar un contrato informal en la cabeza. Recuerda que a la feature dos le importa la forma del usuario, así que cuando la toca para la feature seis, salta una alarma callada. Es frágil y no escala, pero existe.
Un agente no tiene esa memoria entre sesiones. Cada ejecución empieza de cero, ve el código tal como está ahora, y no puede saber con qué contaba en silencio una feature anterior a menos que algo en el código lo diga. El agente no es descuidado. Trabaja exactamente como se le indicó, ciego a una promesa que nadie escribió. Generar más rápido solo significa que llegas antes a la zona de choque. Esta es una cara de la verdad más amplia de que los cambios correctos en local producen un sistema globalmente incoherente: cada edición está bien por su cuenta y el conjunto deriva hasta dejar de estar de acuerdo consigo mismo.
El arreglo no es “ten más cuidado”
No puedes resolver esto esforzándote más en recordar. La memoria es justo lo que no escala aquí, y si usas agentes, la memoria en la que te apoyarías ni siquiera está en la sala. El cuidado no es un mecanismo.
El arreglo es hacer el contrato explícito, para que una violación sea visible en vez de silenciosa. Tiene dos capas, y quieres las dos.
El contrato como spec escrita. Cada feature debería tener una declaración pequeña y llana de qué promete y de qué depende: esta feature garantiza que este total siempre cuadra, esta feature asume que el registro de usuario tiene un rol. Cuando esas promesas están escritas junto al código, un cambio que rompería una tiene algo contra lo que chocar. Esto es lo que significa que la spec sea el contrato en vez de un documento que nadie abre: es la cosa que dice qué debe seguir siendo cierto, para que una violación sea una regla rota en vez de una sorpresa en producción.
El contrato como comprobación ejecutable. Una promesa escrita todavía necesita dientes. Los dientes son tests de caracterización que fijan el comportamiento garantizado de cada feature, para que cuando un cambio posterior viole la promesa, un test falle de inmediato en vez de un usuario reportar un bug tres semanas después. El contrato escrito dice qué se promete; el test lo hace cumplir en el momento en que se rompe. Un build en verde por sí solo no prueba nada de esto; la comprobación tiene que ejercitar de verdad el comportamiento que el contrato nombra.
Juntas, convierten un choque silencioso en un fallo ruidoso, inmediato y localizado, en el momento en que aún puedes arreglarlo barato.
Instalar el contrato en una app que ya tienes
No necesitas una reescritura para conseguir esto. Instalas el contrato sobre la app en marcha, en el mismo orden seguro que sigue cualquier refuerzo.
Escribe qué promete y qué asume cada una de tus features existentes, empezando por las que más duelen cuando se rompen. Fija esas promesas con tests que fallen ante la violación. Después, según añades features, los choques se anuncian durante el desarrollo en vez de emboscar a los usuarios en producción. Con el tiempo la app deja de ser un sitio donde el progreso cuesta regresiones. La versión completa por etapas de esto, para una app entera en vez de una feature, es el cruce en de vibe coding a producción, y la mecánica concreta de reforzar una app frágil en su sitio está en arreglar una app vibe-coded sin reescribirla.
Dónde encaja PaellaDoc
Mantener el contrato de cada feature en la cabeza es justo el trabajo que falla según la app crece, y es el trabajo que haces en silencio cada vez que te preparas antes de un cambio. El papel de PaellaDoc es sostener esos contratos fuera de tu cabeza: mantiene la especificación de cada feature pegada al código que la implementa, y vuelve a ejecutar la app para comprobar que un cambio no rompió una promesa de la que dependía otra feature. El punto no es más disciplina por tu parte. Es que el contrato entre features viva en algún sitio duradero y se compruebe automáticamente, para que la siguiente feature sea un añadido en vez de un choque.
Se supone que las features nuevas suman. Cuando cada una resta en otro sitio, no tienes un problema de disciplina. Tienes un contrato que falta, y los contratos se pueden instalar.
Preguntas frecuentes
¿Por qué cada feature nueva rompe una vieja en mi app hecha con IA? Cada feature se generó asumiendo que el resto de la app se queda quieta, y esa asunción nunca se escribió. Cuando una feature posterior cambia algo de lo que dependía una anterior, nada avisa a nadie, porque no había un contrato que violar en voz alta.
¿Por qué los agentes de código lo empeoran? Un agente no tiene memoria entre sesiones de lo que dependen en silencio las features anteriores. A menos que el código declare esas dependencias, el agente no puede saber que está rompiendo una. Generar más rápido solo llega antes a la zona de choque.
¿Cómo evito que las features se rompan entre sí? Haz el contrato explícito: escribe qué promete y de qué depende cada feature, y fija esas promesas con tests que fallen en el instante en que un cambio las viole. Eso convierte una rotura silenciosa en producción en un fallo inmediato y localizado durante el desarrollo.