Muchas veces la cantidad de nuevo software que la IA genera para acelerar nuestra productividad en el desarrollo de software es tan grande que cuesta procesarla, y algo que no ha cambiado es que seguimos siendo responsables del código que hacemos y las funcionalidades que implementamos, asumiendo brechas de seguridad, deuda técnica, fallos en funcionalidad, etcétera. Es por ello que no solo tenemos que usar guías que orienten a la IA en la construcción de software, sino que también tenemos que usar sensores, que no son más que alarmas que saltan cuando hay algo mal; es decir, se degrada la arquitectura software, se produce deuda técnica, vemos que algunos test revientan porque se ha roto una funcionalidad que no debería haberse roto, etcétera. Y de eso trata este vídeo. Así que nada, lo primero que vamos a ver son los dos tipos de sensores, pero antes recordemos que el agente, antes de producir el código, utiliza unas guías que lo orientan en el proceso de construcción de software, como por ejemplo AGENTS.md o skills. Si no has visto el vídeo de las guías, te lo recomiendo. Una vez que el agente ha producido una salida, que no es más que ficheros de código editados, nuevos ficheros de código, ficheros de código eliminados, la IA ejecuta sensores que le permiten recibir feedback, y ese feedback le permite autocorregirse e ir controlando que la calidad del código o los patrones que implementa el código cumplen con los estándares que nosotros hemos definido. También es importante subrayar que los sensores no solo son para las inteligencias artificiales, sino también para nosotros: hay sensores de integración continua o pruebas end-to-end o testing unitario que nos sirven a nosotros para decidir si todo el proceso se ha efectuado de manera exitosa. Hay dos tipos de sensores: sensores inferenciales y sensores computacionales. Los sensores inferenciales son aquellos en los que utilizamos otras inteligencias artificiales para evaluar el resultado del agente que ha estado creando código; por ejemplo, utilizar un LLM como juez, que suele ser más agnóstico y, basándose en ciertos criterios, puntúa, o, por ejemplo, una skill que se dispara cada vez que modificamos un componente de Angular para controlar que cumple con unos patrones que nosotros hemos determinado. Como vemos, este tipo de sensores son más inteligentes, no son simples. Por otro lado, tenemos los sensores computacionales, que son a los que dedicaremos este vídeo. Estos sensores suelen ser baratos, suelen ser rápidos y son muy mecánicos y automáticos. Por ejemplo, una vez que el agente ha modificado el proyecto, disparamos unos sensores que controlan que el tipado y la compilación están bien. Continuamos controlando la calidad del código: que se cumplen reglas arquitectónicas, buenos patrones de desarrollo de software, que la IA no se pasa metiendo comentarios en todo el código, por ejemplo. Y tras esto también podemos pasar test unitarios, que lo que hacen es probar que la funcionalidad especificada se cumple, e incluso, si modificamos ciertas áreas de nuestro proyecto y eso afecta a otras áreas, que los test unitarios revienten para avisarnos de "oye, esto está afectando a otra área, así que contrólalo". Y después tenemos ya sensores más a nivel de sistema completo, como pruebas end-to-end o construcción de imágenes que no produzcan fallos, etcétera. Y aquí hay algo muy importante también: dentro de cada uno de estos bloques vemos tecnologías muy específicas; por ejemplo, para tipos y compilación vemos TypeScript compiler o Pyright, y para test unitarios vemos Vitest, Jest, pytest. Esto es para mi stack, que mi stack principalmente es TypeScript, Node.js y Python. Entonces todas estas tecnologías están muy acopladas a mi stack, pero es verdad que si tú trabajas en Java o trabajas en PHP o en cualquier otro lenguaje, probablemente tengas que utilizar tus propias tecnologías. Lo importante aquí es quedarse con los conceptos: tipos y compilación, calidad de código, test unitarios y más a nivel de sistema completo. Bueno, antes de aterrizar en el código tenemos que entender que, al igual que con las guías, buscamos ser independientes del proveedor, y para lograr esto tenemos que tener un único punto centralizado donde tenemos la configuración de nuestros hooks o nuestros ciclos, que son los que nos permitirán configurar los sensores, en la carpeta .agents, y a partir de ese único punto de verdad, con scripts de sincronización, distribuimos entre los diferentes proveedores. Esto lo hacemos sobre todo porque cada proveedor, a lo mejor un mes tiene un código promocional que te regalan un montón de tokens, otro mes uno saca un modelo mucho más potente, y cada proveedor va cambiando y va mejorando a lo largo del tiempo. Entonces nuestra idea es cambiar muy rápido de uno a otro, con mucha facilidad. Viéndolo un poco más aterrizado a nivel de código, nosotros tenemos un archivo centralizado dentro de la carpeta .agents que se llama hooks-config.json, y aquí nosotros utilizamos un vocabulario nuestro: evento "parar" o evento "después de editar" es un vocabulario nuestro, y luego cada uno de estos se mapea a las necesidades de cada proveedor. Por ejemplo, en Antigravity el patrón es este, pero en Claude podemos ver que el patrón es este de aquí, es diferente. Entonces nosotros lo que hacemos es tener un único punto centralizado y a partir de aquí, con scripts automáticos, adaptamos a las necesidades de cada proveedor de IA. Visto esto, nuestros sensores ya automáticamente se sincronizarán también, no solo la definición de los ciclos. Bueno, este sensor de aquí, por ejemplo, lo que hace es comprobar qué archivos han cambiado con respecto al último commit, y a partir de eso comprueba si el linter de Python pasa, si el compilador o el type checker de Python pasa y también si el TypeScript compiler pasa sobre esos archivos que han cambiado. Entonces vemos aquí que lo que hace es comprobar y ejecutar esos sensores. El segundo concepto que vimos en la diapositiva eran sensores que controlaban la calidad del código. Nosotros aquí ejecutamos ESLint y Stylelint en los archivos que han cambiado, y a partir de eso controlamos bastantes cosas, como arquitectura, calidad de código, etcétera. Vamos a ver, por ejemplo en el backend, cómo están definidas esas reglas. Buscamos el archivo, eslint.config.mjs, y aquí lo que vemos es que controlamos muchísimas cosas. Controlamos que entre carpetas hermanas no haya importaciones, es decir, que exams no importe cosas de academy o academy no importe cosas de culture. Esto es una norma de Clean Architecture: tienen que estar separados los contextos, no puede haber dependencias entre ellos. Aquí lo que hacemos también es controlar que la capa de aplicación no debe depender de framework o infraestructura, o, por ejemplo, que la capa de dominio debe ser independiente. Todo esto son reglas avanzadas de arquitectura clean aplicadas a nivel de lint; es decir, con el lint podemos controlar cosas incluso relativamente complejas. Y también es muy importante que los mensajes sean lo más explícitos posible, sobre todo para orientar a la IA de, cuando se produce un error, cómo debe solucionarlo. Aquí dice: bueno, define un puerto e impleméntalo en infraestructura. Esto es de puertos y adaptadores, de la arquitectura hexagonal. Un ejemplo práctico que vemos aquí: yo le he pedido a la IA que arregle un error y ella va generando todo el contenido, modificando y consultando, y una vez que acaba, uno de los sensores que ejecuta es ESLint, y aquí lo que podemos ver es que ella misma reflexiona: "ESLint marca un error mío: el comentario tiene dos líneas y el máximo es una". Esto es una guerra que yo tengo con las inteligencias artificiales, porque cuando van generando código dejan comentarios por todos lados, y yo le he puesto a través del lint que no puede haber comentarios más largos que cierta longitud, y fijaos que aquí ya ella lo ha corregido sin yo decirle nada. El tercer concepto que vimos en las diapositivas eran los test unitarios. En este caso nosotros lo hemos aplicado en el pre-push, es decir, antes de subir al servidor. Esto es un estándar de Git que se puede aplicar con diferentes tecnologías; yo lo he aplicado con Husky porque estoy más familiarizado con Node, pero es verdad que, dependiendo de la tecnología, puedes usar otro framework que te permita ejecutar ciertos scripts antes de subir al servidor. Y aquí lo que comprobamos es los linters, estilos, testing, vale, test de inteligencia artificial, test de front; es decir, ya aquí nosotros estamos comprobando que toda la calidad y que compile y también los test unitarios antes de subir a nuestro repositorio. Entonces esto también es un sensor que nos avisaría a nosotros, o, si nosotros automatizamos con IA que ella misma suba al repositorio a través de su commit, pues también le saltaría esto como sensor diciéndole "oye, tienes algo mal". El cuarto aspecto que vimos en las diapositivas es integración continua. Esta nos permite ejecutar una serie de trabajos antes de desplegar en servidores reales y que afecte a usuarios reales. Aquí lo que hacemos sobre todo es controlar que el versionado está bien mediante los lockfiles, pruebas del linter nuevamente en front y en back, testing unitario tanto en front como en back, así como la construcción de las imágenes que se desplegarán en producción. Un aspecto muy interesante de esta integración continua es que se ha disparado para comprobar si un bot puede mergear en una rama, es decir, para un proceso automático que nosotros no controlamos. Y aquí quiero pararme en una cosa importante: hoy en día, con las inteligencias artificiales, está habiendo muchísimos ataques, y es muy importante que automaticemos la subida de versiones de nuestras librerías, porque cada dos por tres las librerías suben de versión arreglando vulnerabilidades críticas o problemas de seguridad. Por eso es importante que tengamos automatizado que suban las versiones menores, y que en el caso de versiones críticas nos lo soliciten mediante pull request; versiones críticas que pueden afectar a nuestro código y tenemos que revisarlas nosotros. A modo de resumen, los sensores los hemos distribuido en los diferentes ciclos que podemos tener cuando aceleramos nuestra productividad con inteligencia artificial. Aquí hay un ciclo extra que no mostré a nivel de código, sobre todo para ver que el único ciclo que está asociado a un agente no es el de parada tras realizar una tarea, sino que también podemos poner otro ciclo como PostToolUse, que lo que hace es comprobar la calidad del código. En la documentación de los diferentes proveedores de inteligencia artificial tienes todos los ciclos diferentes que hay, en un agente. También vemos que en el preproceso y en el postproceso sobre todo nos hemos enfocado en testing unitario, testing end-to-end y la construcción de imágenes. Adicionalmente tenemos las quality gates, que actúan como bloqueadores si no se cumplen ciertos umbrales que establecemos. Por poner dos ejemplos: en el caso de que el paquete final de producción, bien de front o de backend, supere cierto tamaño, podemos bloquear por temas de eficiencia y rendimiento. También podemos establecer umbrales en el testing, en la cobertura de testing, de tal manera que al principio empezamos con unas expectativas muy bajas, es decir, que el testing cubra el veinte por ciento del código, y poco a poco ir subiendo, pero nunca permitir que baje de un umbral establecido previamente. Por último, pero no por ello menos importante, tenemos que controlar nuevos riesgos derivados de la aceleración de productividad con inteligencia artificial. Por ejemplo, con el paquete react-fast-utilz evitamos que las inteligencias artificiales instalen librerías de terceros extrañas o poco seguras. También tenemos que controlar que los secretos no se fugan a los repositorios, con Gitleaks, y también con Semgrep podemos controlar patrones vulnerables conocidos en nuestro código. Dependiendo de las necesidades de tu proyecto puedes necesitar unos sensores u otros. Yo aquí he enseñado los que considero más importantes aplicados a Eurmes, pero es verdad que, dependiendo de las necesidades de tu proyecto, puedes necesitar hacer una investigación más profunda y buscar otros sensores diferentes. También hay que destacar que cada poco tiempo salen nuevos tipos de sensores, nuevas estrategias; por lo tanto, esto sirve como orientación para empezar a construir los sensores más básicos. Espero que te haya gustado este vídeo, y nos vemos pronto.