Este artículo cuenta un experimento concreto: qué ocurrió cuando un agente de IA modernizó un sistema y un arnés de caracterización decidió si el resultado era equivalente. Es la versión con números del criterio que planteé en el artículo 042.
1. El experimento, y lo que no es
Conviene empezar por lo que no es. No es un caso de cliente ni un proyecto real. Es un laboratorio propio con un sistema de referencia sintético: un motor de liquidación de siniestros de hogar en Java 8, construido para este ejercicio con defectos típicos de una migración a Java moderno introducidos a propósito, y su versión en Java 21. Los datos son generados y no hay ninguna organización detrás. El detalle del laboratorio está en el proyecto 045.
La tesis que quería poner a prueba es sencilla: el agente moderniza en minutos; lo que no puede hacer es firmar que el resultado es equivalente. Para comprobarlo hacía falta algo que dijera, con evidencia, si lo que el agente produce hace lo mismo que lo anterior.
2. El arnés: registrar lo que el sistema hace
La técnica es la de las pruebas de caracterización: no se escribe lo que el sistema debería hacer, se registra lo que hace y se exige que el nuevo se comporte igual. En el laboratorio se concreta así:
- 5.000 expedientes generados por rangos de negocio (capital asegurado, porcentaje de daño, franquicia, antigüedad, fechas de siniestro y de pago), con semilla fija, de modo que cada ejecución es reproducible al céntimo.
- Dos revisiones vivas de la misma aplicación en Azure Container Apps, una con el sistema viejo y otra con el nuevo, para comparar lo que se va a servir y no dos clases en local.
- Un comparador que clasifica cada divergencia por causa raíz, calcula su impacto económico y emite un acta con un veredicto explícito.
- Un árbitro que el agente no controla. El agente escribe el código; los casos y la comparación son de otra parte del circuito.
3. Lo que dijo el arnés
El agente produjo una versión que compilaba en una sola ronda, con unos 1.900 tokens y unos 23 segundos. A primera vista, un éxito. El arnés dijo otra cosa:
| Medida | Resultado |
|---|---|
| Expedientes ejecutados | 5.000 |
| Idénticos | 2.963 |
| Divergentes | 2.037 (40,74 %) |
| Causas raíz | Una sola: los días de demora |
| Impacto económico acumulado | 5.642,25 € |
| Veredicto inicial | No equivalente |
Son cifras de una ejecución real con un modelo de lenguaje sobre un sistema sintético, no un benchmark.
Lo interesante es la causa. No es un fallo de compilación ni una errata: es una diferencia de semántica. La versión Java 8 calcula los días de demora restando milisegundos y dividiendo entre 86.400.000; cuando el intervalo cruza el cambio de hora de marzo, pierde una hora y la división entera se come un día. La versión Java 21 cuenta días de calendario a partir de fechas, y por eso cuenta un día más en esos intervalos. Las dos son coherentes consigo mismas; no coinciden entre sí.
La dirección también importa: en 1.998 de las 2.037 divergencias la versión nueva liquida más intereses de demora que la vieja. Un tester puede tardar días en dar con una diferencia así; un arnés la saca en una ejecución. Sin el arnés, el código nuevo habría pasado por correcto: compilaba, parecía razonable y nadie lo habría contrastado, y el cambio de comportamiento habría llegado a producción sin que nadie lo hubiera decidido.
4. Equivalente no es idéntico
Aquí aparece la decisión que no es técnica. Cuando las dos versiones cuentan los días de forma distinta, alguien tiene que decidir qué cuenta es la que se quiere. Exigir igualdad exacta obligaría al sistema nuevo a reproducir el comportamiento del viejo, incluido el que quizá no se quería; aceptar la diferencia sin más es dejar que el cambio entre sin que nadie lo decida. Lo que hace falta es una categoría explícita, que llamo diferencia controlada:
- Una divergencia concreta: una causa raíz, un número de casos y un impacto estimado.
- Aprobada por escrito por quien responde del proceso de negocio.
- Con un alcance estricto: cubre esa forma exacta y no una familia de casos. Si aparece otra divergencia, el veredicto vuelve a ser negativo.
La puerta de promoción lo aplica. Con el acta en rojo, deniega el cambio de tráfico y el tráfico sigue entero en la versión vieja. Se puede forzar, pero queda escrito en el acta quién, cuándo y qué divergencias se ignoraron: saltarse la puerta es un acto deliberado y con nombre. Con la diferencia controlada aprobada, el veredicto pasa a ser «equivalente con excepciones aprobadas» y el cambio puede avanzar. El agente propone; la firma es de una persona.
5. Lo que rompió el propio laboratorio
La parte más útil del ejercicio fueron los fallos, porque son los que aparecerían en un caso real:
- El agente a veces empeora el código al iterar. En una ejecución con segunda ronda, introdujo días de demora negativos y el arnés rechazó el resultado. Por eso el árbitro no puede depender del agente.
- La primera versión de la puerta promocionó con el acta en rojo. El parámetro y una variable local se llamaban igual salvo por las mayúsculas, y PowerShell no distingue entre ellas: asignar el objeto JSON lo convirtió en texto sin avisar y la puerta leyó cero divergencias. Ahora la puerta comprueba que ha leído el acta de verdad y, si las propiedades esperadas vienen vacías, aborta. Un acta que no se puede leer no es un acta limpia.
- El acta sobrevive al entorno. Al destruir y redesplegar, el fichero del acta se quedaba en disco y la puerta lo habría leído tal cual: un acta verde de un despliegue anterior habría abierto el tráfico del nuevo. Se resolvió con una huella de procedencia que registra contra qué entorno se generó.
- Prompt Shields es una capa, no una garantía. En la pasarela de gobierno del proyecto 044, con cuatro variantes de instrucción escondida en el código, la ruta de documentos bloqueó las cuatro y la ruta de prompt de usuario, tres.
- Un falso positivo real: un reintento legítimo con rutas de disco dentro del mensaje recibió un 403. El agente limpia ahora las rutas antes de reenviar errores.
- Un límite práctico: la pasarela admite unos 10.000 caracteres por ventana, así que el código enviado al modelo debe caber o hay que trocearlo.
6. Alcance de laboratorio
Es un entorno efímero y no debe leerse como un patrón de producción. Hay servicios con red pública (almacén de secretos, Foundry, Content Safety) y un API Management en nivel Developer, sin SLA: son decisiones razonables en un laboratorio que se destruye y no en un sistema que sirve tráfico real. Además, el sistema es sintético y de un solo tipo de transformación; un código real es más grande, tiene más dependencias y peor documentación, y otro tipo de migración (base de datos, plataforma) pide otros arneses. No enlazo al entorno porque ya está destruido o programado para destruirse.
7. Qué hacer el lunes
- Caracteriza antes de pedir nada al agente: congela un conjunto de entradas representativo y guarda las salidas del sistema actual.
- Saca el árbitro del alcance del agente y versiona la referencia.
- Compara lo desplegado: dos revisiones vivas, con una comprobación de que cada una responde por sí misma.
- Define la diferencia controlada antes de ver el primer resultado, con quién la firma y qué alcance tiene.
- Haz que la puerta falle cerrada y que el acta lleve su procedencia.
Las opiniones expresadas en este artículo son personales.
Fuentes
Las cifras proceden de una ejecución real de un laboratorio propio con un sistema sintético, realizada en octubre de 2026; no se han contrastado con fuentes externas porque no describen un producto ni un caso de terceros. Los detalles técnicos del circuito están en el proyecto 045.