La IA ya escribe código que parece razonable. Ese no es el problema.
El problema aparece cuando confundimos una respuesta plausible con una entrega confiable. Un diff puede compilar, tener tests verdes y seguir introduciendo un error que un usuario va a encontrar antes que nosotros.
En nuestro trabajo construimos software real para empresas. No evaluamos una herramienta por una demo ni aprobamos un PR porque el modelo explicó bien lo que hizo. La evaluamos por la evidencia que deja y por el comportamiento que entrega.
Por eso verificamos en capas. Cada capa responde una pregunta distinta. Ninguna reemplaza a las demás.
El caso que nos obligó a afinar el proceso
Hace un tiempo trabajamos en un cambio acotado. Había que distinguir dos estados cuya representación se parecía parcialmente. A primera vista, la condición parecía simple. La primera implementación resolvía el caso más visible y los tests iniciales estaban en verde.
No alcanzaba.
Los fixtures no representaban las respuestas que llegaban en la operación real. El PR introducía un falso positivo: identificaba como válido un caso que no debía serlo. Para entender el comportamiento hubo que consultar otro contrato relacionado, no sólo la condición que estábamos modificando.
Corregimos la lógica y ampliamos los tests. Después apareció otro problema durante la QA funcional: la interfaz mostraba un texto que sugería una situación distinta de la que realmente estaba ocurriendo. El código podía estar más cerca del contrato, pero la persona que usaba el sistema recibía una señal equivocada.
Hubo correcciones sucesivas. Se agregaron escenarios que faltaban. Recién al final la CI y las pruebas end-to-end quedaron verdes con evidencia suficiente.
Ese caso no demuestra que los tests sean inútiles. Demuestra algo más importante: los tests sólo verifican lo que fue especificado. Si el fixture no representa una respuesta real, un test verde prueba ese fixture, no el mundo.
Tampoco demuestra que la revisión de PR sea un trámite. La revisión y la QA funcional miran riesgos distintos. Una revisa la propuesta de cambio contra el contrato y el diff. La otra observa qué entiende y qué puede hacer una persona en el producto.
Un candidato de PR, no una impresión general
La unidad que verificamos es un candidato concreto de PR. Tiene un objetivo, criterios de aceptación, un diff acotado y evidencia asociada. Eso evita discutir sobre “el código” en abstracto.
Antes de implementar, intentamos dejar claras estas preguntas:
- ¿Qué comportamiento debe cambiar?
- ¿Qué comportamiento no debe cambiar?
- ¿Qué escenarios representan datos y usos reales?
- ¿Cómo vamos a saber que la entrega está lista?
Los criterios de aceptación no son burocracia. Son el punto de comparación cuando el modelo propone una solución. Si no existe ese punto, el review termina midiendo estilo, intuición o confianza en la explicación del agente.
También acotamos el diff. Un cambio pequeño no es automáticamente seguro, pero es más fácil de comprender, probar y revertir. Si un candidato crece sin una razón clara, primero revisamos el alcance. No usamos un PR grande como bolsa para todo lo que apareció durante el trabajo.
La QA es una cadena de evidencia
La secuencia cambia según el riesgo, pero las capas se mantienen. Cada una puede detectar una clase diferente de error.
1. Chequeos estáticos y pruebas automáticas
Tipos, lint, análisis estático y tests son la primera barrera. Son rápidos, repetibles y muy útiles para detectar contratos rotos, errores de integración y regresiones conocidas.
Pero no convierten un requisito incompleto en un requisito correcto. Si el caso relevante no está en la especificación, la suite puede pasar sin haberlo mirado.
Por eso buscamos pruebas que hablen de escenarios. No sólo de ramas de código. En el caso anterior, el cambio real fue incorporar respuestas que los fixtures no estaban representando.
2. QA asistida por modelos, con desacuerdo útil
La IA que implementa no debería ser la única voz que valide su resultado. Pedimos otra mirada con una tarea concreta: buscar supuestos débiles, comparar el diff con los criterios de aceptación, detectar casos límite y cuestionar lo que parece demasiado obvio.
Los modelos no tienen los mismos errores. Sus datos de entrenamiento y su post-entrenamiento son distintos. También lo son sus puntos ciegos. Usar modelos diversos puede reducir errores correlacionados: si dos revisores llegan a la misma conclusión por caminos diferentes, tenemos una señal adicional. No tenemos una garantía de corrección.
Hoy usamos modelos de NaN.Builders dentro de esta capa de QA. La comunidad la llevan Cristian Córdova / @barckcode, fundador de Helmcode, y Borja Pérez / @borjaperfra. Conozco y aprecio a los dos, así que objetividad absoluta no prometo. Uso real, sí. En nuestro QA, NaN nos suma perfiles distintos sin convertir una salida de modelo en aprobación automática.
La revisión se enfoca en el riesgo y en la evidencia disponible. A veces un cambio exige una lectura línea por línea. Otras veces el riesgo está en una decisión de contrato, en un límite no cubierto o en una interacción entre componentes. La intensidad del review tiene que seguir el problema, no un ritual fijo.
3. QA funcional humana
Después está la parte que no se resuelve leyendo un diff. Una persona recorre el flujo, observa los mensajes, prueba decisiones reales y contrasta el resultado con la intención original.
Esta capa encontró el texto engañoso en el caso que contamos. No era una excepción técnica. Era una comunicación incorrecta en una pantalla real. Un usuario no ve la cobertura de tests ni la explicación del modelo. Ve una acción y una consecuencia.
La QA funcional también obliga a hacer preguntas incómodas: ¿el dato que mostramos significa lo que la interfaz dice? ¿el estado se entiende? ¿hay un camino de error que la automatización no recorrió? ¿el comportamiento sigue siendo consistente para quien usa el sistema?
Pi, Gentle AI y la responsabilidad de cerrar bien
Nos movimos a Pi con gentle-pi porque necesitábamos un entorno donde el trabajo con agentes tuviera límites claros, contexto controlado y verificación explícita. Es la integración nativa para Pi del ecosistema Gentle AI, impulsado por Alan Buscaglia / @G_Programming. A Alan lo nombro con especial cariño porque lo veo de cerca: le pone una cantidad absurda de trabajo, sin pedir nada, con un afán real de ayudar. Con Alan y con todo ese equipo divino de Gentle AI aprendo un montón. Poder dar una mano ahí adentro, la verdad, es un orgullo.
Con gentle-pi trabajo desde dos lugares: lo usamos para entregar software real y, como parte del equipo de maintainers de Gentleman Programming, también tengo responsabilidad sobre los flujos que lo sostienen. Esa doble perspectiva obliga a revisar qué se delega, qué evidencia se exige, cuándo hay que detener una entrega y quién conserva la decisión final.
Una herramienta puede ayudarnos a separar tareas, limitar un candidato y registrar la evidencia. No puede asumir la responsabilidad de llevar un cambio a producción. Esa decisión sigue siendo humana.
Por eso el cierre no es “los tests pasaron”. Revisamos la evidencia disponible y decidimos si el candidato se entrega, si necesita otra corrección o si hay que volver a entender el requisito. Una aprobación responsable puede ser también un no.
Producción también verifica
La verificación no termina cuando se integra un PR.
Un despliegue necesita observabilidad. Miramos señales del sistema, errores, comportamientos inesperados y las métricas que puedan indicar que el supuesto inicial era incompleto. También necesitamos un rollback posible y entendido antes de necesitarlo.
Esto no es pesimismo. Es reconocer que la producción es donde aparecen combinaciones de datos, uso y contexto que ningún entorno replica por completo.
El aprendizaje del caso fue menos elegante que una fórmula: la primera versión parecía correcta porque el escenario equivocado estaba en verde. El problema apareció cuando contrastamos el contrato, los datos reales y lo que la interfaz comunicaba.
Llevar código generado por IA a producción exige cerrar esa distancia antes de que la cierre un usuario. No se trata de desconfiar de la herramienta ni de convertir cada cambio en un ritual. Se trata de reunir evidencia suficiente para ese candidato, decidir con ella y seguir mirando después del despliegue.
