El problema de la revisión

El consejo estándar para el código generado por IA es “revísalo cuidadosamente”.

Ese consejo es correcto e inútil a escala.

Un desarrollador que revisa la salida de IA detecta problemas cuando está alerta, familiarizado con el dominio y sin presión de tiempo. En cualquier otra condición — que es la mayoría de las condiciones — las cosas se escapan.

Un revisor de IA detectando problemas generados por IA es aún menos confiable. Estás pidiendo a un sistema probabilístico que verifique la salida de otro sistema probabilístico. Los modos de fallo están correlacionados.

El único patrón que escala es el enforcement determinista. Reglas que se verifican en cada commit, que no pueden ser anuladas por el cansancio o el optimismo, y que fallan la compilación cuando se violan.

Qué significa determinista

Determinista significa que la verificación produce el mismo resultado cada vez, independientemente de quién la ejecute o cuándo.

  • Una regla de linter es determinista.
  • Una verificación de tipos es determinista.
  • Una restricción de importación de límites es determinista.
  • Un contract test es determinista.
  • La capacidad de atención de un revisor humano no lo es.
  • La evaluación de un LLM no lo es.

Esta distinción importa más en codebases generados por IA porque el volumen de código generado excede lo que cualquier equipo puede revisar manualmente. No puedes escalar la revisión linealmente con la velocidad de generación. Puedes escalar las verificaciones deterministas trivialmente.

La pila de barreras de protección

Para codebases generados por IA, la pila de barreras de protección tiene cuatro capas:

Capa 1: Sistema de tipos

El sistema de tipos es la primera barrera. Los tipos estrictos capturan una clase de errores que ningún proceso de revisión — humano o IA — detecta consistentemente:

  • Violaciones de nulidad
  • Incompatibilidades de interface
  • Manejo de casos faltantes
  • Tipos de argumentos incorrectos

Si el proyecto usa TypeScript, strict: true es innegociable. Si usa un lenguaje sin un sistema de tipos fuerte, añade uno mediante herramientas o elige un lenguaje diferente.

Capa 2: Reglas de arquitectura

Las reglas de arquitectura aplican la disciplina de límites:

  • Ninguna pantalla importa desde los internos de otra pantalla.
  • La lógica de dominio no importa infraestructura directamente.
  • Ningún module evita el composition root para acceder a dependencias.
  • Ningún SDK de proveedor aparece fuera de su module adaptador.

Herramientas como Semgrep, ArchUnit, dependency-cruiser o reglas personalizadas de ESLint pueden aplicar esto de forma estática. La clave es que se ejecutan en CI y fallan la compilación. Una advertencia que los desarrolladores pueden ignorar no es una barrera de protección.

Capa 3: Contract tests

Los contract tests verifican que los módulos satisfacen sus interfaces sin ejecutar el sistema completo:

  • El adaptador de autenticación satisface la interface de autenticación.
  • El adaptador de analítica satisface la interface de analítica.
  • El adaptador de almacenamiento satisface la interface de almacenamiento.

Estos se ejecutan rápido, prueban los límites de integración y detectan el modo de fallo específico donde el código generado por IA satisface la firma de tipos pero viola el contract de comportamiento.

Capa 4: Verificaciones de integración deterministas

A nivel de integración, las verificaciones validan propiedades de todo el sistema:

  • El composition root resuelve todas las dependencias sin errores en tiempo de ejecución.
  • El grafo de dependencias no contiene ciclos.
  • Todas las variables de entorno requeridas están declaradas.
  • La configuración es válida en tiempo de compilación, no solo en tiempo de ejecución.

Semgrep para código generado por IA

Semgrep merece mención específica porque sobresale en expresar reglas de arquitectura como código:

  • Coincidencia de patrones sobre la estructura AST, no coincidencia de cadenas de texto.
  • Reglas personalizadas por proyecto, no solo linting genérico.
  • Suficientemente rápido para ejecutarse en cada commit.
  • Suficientemente expresivo para codificar violaciones de límites.

Un equipo que usa generación por IA extensivamente debería mantener un conjunto de reglas de Semgrep que codifique sus límites arquitectónicos. Cuando la IA genera código que viola un límite, la compilación falla antes del merge. Sin necesidad de atención humana.

Esto no se trata de encontrar errores en la salida de la IA. Se trata de hacer imposible hacer merge de violaciones estructurales independientemente de cómo fueron producidas.

Qué realmente detecta la revisión de código por IA

Las herramientas de revisión de código por IA son útiles para:

  • Consistencia de estilo
  • Vacíos en la documentación
  • Errores lógicos obvios
  • Sugerir enfoques alternativos

Las herramientas de revisión de código por IA son poco confiables para:

  • Violaciones de límites arquitectónicos
  • Acoplamiento sutil introducido entre módulos
  • Violaciones de contracts de comportamiento
  • Propiedades de seguridad que requieren razonamiento sobre todo el sistema

El modo de fallo no es que la revisión por IA omita cosas ocasionalmente. El modo de fallo es que omite cosas de forma impredecible, y no puedes saber cuándo ha omitido algo. Por eso no puede reemplazar el enforcement determinista — solo complementarlo.

La economía

Las barreras deterministas son baratas de ejecutar y costosas de construir inicialmente.

Escribir las reglas de arquitectura lleva unos pocos días. Mantener la configuración de Semgrep requiere atención continua. Configurar los contract tests requiere definir interfaces primero.

Pero una vez que existen, se ejecutan en cada commit con un costo marginal cercano a cero. No se cansan. No omiten verificaciones los viernes por la tarde. No ceden ante la antigüedad o la presión social.

Para codebases generados por IA donde el volumen de código es alto y la velocidad de generación es rápida, este perfil económico es decisivo. La alternativa — escalar la revisión humana para igualar la velocidad de generación de la IA — no es viable.

La conexión con la arquitectura AI-native

Escribí sobre este patrón más amplio en Stanford CS146S tiene razón sobre la programación con IA — El tema ausente es la arquitectura. Las barreras deterministas son el mecanismo de enforcement que hace real la arquitectura reemplazable.

Sin barreras, los límites arquitectónicos son aspiracionales. Con ellas, los límites son estructurales. La diferencia entre “intentamos mantener los módulos aislados” y “la compilación falla si se viola el aislamiento de módulos” es la diferencia entre una arquitectura que sobrevive a la iteración a velocidad de IA y una arquitectura que colapsa bajo ella.

El desarrollador de software moderno no solo necesita fluidez con herramientas de IA. Necesita una pila de barreras de protección que haga que el código generado por IA sea estructuralmente seguro de publicar a velocidad.

Preguntas frecuentes

¿Cuál es la mejor herramienta para aplicar reglas de arquitectura en código generado por IA?

Semgrep es la opción más flexible para reglas arquitectónicas personalizadas. Soporta coincidencia de patrones contra la estructura AST, se ejecuta rápido en CI y permite a los equipos codificar límites específicos del proyecto. Para proyectos JavaScript/TypeScript, dependency-cruiser y reglas personalizadas de ESLint también son efectivas.

¿Puede la revisión de código por IA reemplazar la revisión humana?

No. La revisión de código por IA complementa la revisión humana para estilo y documentación, pero es poco confiable para el enforcement de límites arquitectónicos y propiedades de seguridad. Las verificaciones deterministas (sistema de tipos, linters, reglas de arquitectura, contract tests) son el único reemplazo escalable para la revisión dependiente de la atención.

¿Cómo se configuran las barreras de protección sin ralentizar al equipo?

Comienza con el sistema de tipos (modo estricto, sin excepciones). Añade reglas de arquitectura para los tres límites de mayor riesgo. Añade contract tests para integraciones externas. Cada capa toma un día para configurarse y se ejecuta en segundos. La ralentización proviene de las violaciones, no de las verificaciones en sí.

¿Cuál es la diferencia entre una barrera de protección y un linter?

Un linter sugiere mejoras. Una barrera de protección falla la compilación. La distinción es el enforcement. En codebases generados por IA, las sugerencias se ignoran a escala porque el volumen es demasiado alto para una atención manual consistente. Solo los fallos de compilación garantizan el cumplimiento.