Una tanda de notificaciones de prueba salió al chat donde el sistema publica sus avisos, todas anunciando reparaciones que habían terminado hacía semanas. El sistema no olvida nada, y elige el peor momento para acordarse. Y no era la primera vez que pasaba.
No había un bug nuevo: la regla de siempre, "apaga las notificaciones antes de probar y déjalas en normal cuando termines", se rompe sola en cuanto hay dos agentes trabajando a la vez.
Las pruebas pueden disparar notificaciones reales
Mis agentes de IA verifican sus cambios sobre el sistema real de la tienda, no sobre una copia de juguete. Una prueba que marca una reparación como lista dispara el aviso de verdad. Para eso existía el interruptor de silencio: sin él, una prueba descuidada termina en un aviso que nadie pidió.
Con un solo agente el interruptor funciona, y yo casi nunca trabajo con un solo agente.
El cartel que cualquiera descuelga
El modo de notificaciones era un campo con dos valores: normal o apagado. El agente A lo apaga y arranca sus pruebas. El agente B, en otra rama, lo apaga también, termina quince minutos antes y lo devuelve a normal, tal como pide la instrucción. A sigue corriendo y el sistema no tiene cómo saberlo.
Culpé primero a los agentes, seguro de que alguno había ignorado la regla. La seguían al pie de la letra, todos. El campo no guardaba quién pidió el silencio ni hasta cuándo, así que "restaurar" significaba "apagar el silencio de todos", incluido el de quien seguía adentro. Era el cartel de "no molestar" de una sala de reuniones: había uno solo, y el último que salía lo descolgaba aunque quedara gente trabajando adentro.
Los agentes ignoraron la instrucción
La seguían al pie de la letra
Cada agente cuelga su propio cartel
Cambiamos el valor único por una tabla de permisos temporales. Cada agente toma su fila con su nombre, el motivo y una hora de vencimiento: 180 minutos por defecto, con un techo duro para los olvidos. Libera solo la suya y no puede tocar la de otro.
Una sola función responde cuál es el modo actual, y la usan todos los canales. Si hay al menos un permiso vigente, devuelve apagado; si no queda ninguno, lee la configuración normal. Durante las pruebas ya no tocamos esa configuración, así que desapareció el paso de restaurar, que era justo el que fallaba.
El vencimiento cubre al agente que se cuelga a mitad de camino: un permiso huérfano sin caducidad silenciaría las notificaciones reales para siempre. La lectura también falla cerrada, y si la consulta a la tabla da error la función devuelve apagado. Prefiero que un aviso legítimo espere unos minutos antes que otra tanda de pruebas salga a anunciar reparaciones de hace semanas.
El entorno duplicado que no montamos
Podíamos armar un turno, una cola o un párrafo más severo en la política del repo, pero con instrucciones ya habíamos perdido varias veces.
Tampoco levantamos un entorno de pruebas duplicado, que es la solución de manual. Duplicar el sistema completo, con sus bases de datos y sus tareas programadas, es un proyecto de semanas, y el riesgo que teníamos encima se arreglaba con una tabla.
Quién tiene el cartel se ve de un vistazo
Desde el cambio no volvió a salir una notificación de prueba. Una pantalla de administración muestra en vivo quién tiene un permiso y por qué, así que cuando una notificación no llega, miro esa pantalla en lugar de preguntar. La suite de pruebas toma su propio permiso al arrancar y lo libera al final, y la política del repo exige tomar uno antes de cualquier verificación que pueda escribir.
El caso malo pasó de silencio eterno a silencio con hora de vencimiento, y un silencio con hora se nota. El silencio se levanta cuando cae el último cartel, y las reparaciones de hace semanas ya no tienen nada que anunciar.
