Katja pone una nueva línea base DORA junto a la síntesis semanal de Navigator y encuentra el mismo diagnóstico desde dos direcciones: ramas de larga vida, aprobaciones de sello y trabajo de recuperación en viernes que cae sobre la misma gente cada semana. Con los dos tipos de evidencia van a ver a Lukas y convierten el trunk-based development de ideología en supervivencia. Luego Stefan traza una línea en la pizarra y escribe una palabra: main. Daniel lo llama imprudente. Mariana lo llama la primera propuesta honesta que alguien ha hecho en seis meses. Hassan solo quiere dejar de pasar las noches de viernes desenredando conflictos de fusión creados por gente que se fue a las cinco.
Katja interceptó a Stefan antes de que siquiera pudiera bajar la bolsa.
La encontró en su escritorio con las dos manos rodeando una taza de café de la que ya no estaba tomando. La camiseta de Cult of Luna estaba al revés. No se había dado cuenta. Tenía puestos los lentes, lo que significaba que estaba leyendo algo que importaba, y los lentes de lectura empujados sobre la frente significaban que ya lo había leído dos veces y necesitaba que alguien más confirmara que no estaba alucinando.
“Navigator por fin tiene suficiente historial para decir algo útil”, dijo. “Y la nueva línea base DORA dice lo mismo en números.”
Stefan acercó una silla. El piso de desarrollo se estaba llenando a su alrededor. Desarrolladores entrando con audífonos y café, acomodándose en el ritmo del lunes. Todavía nadie estaba mirando la pantalla de Katja. El aire acondicionado había arrancado temprano. El calor de finales de mayo estaba llegando puntual.
La pantalla estaba partida en dos. A la izquierda: la síntesis semanal de Navigator. Tres semanas de bitácoras diarias condensadas en una narrativa brutalmente clara, con extractos resaltados y resúmenes cortos que seguían rodeando los mismos problemas desde ángulos distintos. A la derecha: una línea base DORA fresca que Katja había armado para este caso concreto.
Stefan se inclinó hacia adelante.
“¿Hasta dónde llega esto?”, preguntó.
“Tres semanas de síntesis”, dijo Katja. Señaló el primer tema resaltado y luego el panel DORA. “Suficiente para dejar de llamar a esto una mala semana y empezar a llamarlo patrón. Los números solo hacen más difícil mentir al respecto.”
Stefan no reaccionó. Todavía no.
“Lee esto primero”, dijo Katja.
Fue marcando una línea sintetizada tras otra.
Los reviews ocurren demasiado rápido para transferir comprensión.
El trabajo de integración se acumula en silencio y luego cae todo junto bajo presión de fecha.
La recuperación del viernes por la tarde recae sobre las mismas dos personas con suficiente frecuencia como para dejar de ser coincidencia y volverse estructura.
El patrón era inconfundible. Nadie estaba integrando de manera continua. Estaban acumulando cambios en ramas de feature, dejándolas crecer hasta volverse gordas y peligrosas, y luego fusionándolo todo en una carrera de pánico al final del ciclo. La línea base DORA mostraba los síntomas de entrega. La síntesis de Navigator mostraba cómo se sentía vivir adentro de eso.
Stefan se recostó.
“Entonces los reviews siguen pareciendo permisos firmados”, dijo.
“Exacto.” Katja se quitó los lentes y se frotó los ojos. Los pasadores de su moño ya no estaban sosteniendo nada. “Pero ahora no es la última semana de Tomasz y unos cuantos pull requests feos. Es un patrón escrito en todo el equipo, y la línea base DORA lo respalda.”
Stefan sacó su cuaderno de la bolsa. El cuero estaba desteñido por el sol donde había reposado sobre mesas de café en Bogotá y Ciudad de México. Lo abrió en una página en blanco y escribió cuatro frases:
Ramas de larga vida Reviews sin comprensión Trabajo de recuperación en viernes Ráfaga, silencio, pánico
Debajo trazó una línea y escribió: “Estos no son code reviews. Son ceremonias de fusión.”
Katja lo leyó de cabeza.
“Esa frase deberías guardarla para Lukas”, dijo.
“Eso pienso hacer.”
Se quedaron con el reporte otros veinte minutos. Stefan hizo preguntas. Katja abrió los extractos de apoyo y luego las pantallas reales del repositorio a un lado. La base de código de Unity estaba peor. El trabajo de Anton tocaba todo, así que sus ramas se quedaban días sin moverse porque nadie quería revisar un cambio enorme un viernes por la tarde. El backend estaba mejor, pero no bien. Los cambios de Mariana solían ser más pequeños. El trabajo de infraestructura de Hassan seguía cayendo en bloques pesados porque todo a su alrededor era frágil y nadie quería tocarlo dos veces.
“La lista de ramas”, dijo Stefan.
Katja navegó a la vista de ramas del repositorio. Cuarenta y siete ramas abiertas. Algunas con nombres como feature/new-event-system-v3. Otras con nombres como hotfix-temp-do-not-delete. Una llamada hassan-friday-night-fix con fecha de último commit de tres semanas atrás.
Stefan la señaló.
“El viernes por la noche de Hassan”, dijo.
La mandíbula de Katja se endureció.
La rama contaba una historia sin palabras. Hassan, solo un viernes por la noche, arreglando algo lo bastante urgente como para quedarse. Creando una rama porque eso exigía el proceso. Haciendo commit del arreglo. Sin fusionarlo porque las puertas de aprobación requerían dos reviewers y no había nadie conectado. Irse a casa. Llegar el lunes. La rama seguía ahí, inmóvil, mientras Hassan ya estaba en el siguiente incendio. Tres semanas después: sigue abierta. Sigue sin fusionarse. Un arreglo que existía pero no estaba desplegado, suspendido en el limbo del proceso entre el problema y la solución.
“Muéstrale esto a Lukas”, dijo Stefan. “Todo.”
“¿Cuándo?”
“Hoy. Antes de que el standup lo convierta en discusión de comité.”
Katja miró por el piso. Los desarrolladores se estaban acomodando, poniéndose los audífonos, encendiendo monitores. El escritorio de Lukas seguía vacío. Solía llegar hacia las 09:30, dejaba la bici en el rack de la entrada y cambiaba los zapatos de ciclismo por Allbirds en su puesto.
Tomó el teléfono y escribió un mensaje.
Lukas. Sala de juntas cuando llegues. Trae café. Lo vas a necesitar.
Lukas llegó cuatro minutos tarde. Zapatos de ciclismo fuera, Allbirds puestos, el Apple Watch reflejando las luces de la sala. Sostenía el café con las dos manos, como hace la gente cuando sospecha que está a punto de escuchar algo que no quiere escuchar.
“¿Qué es esto?”, dijo, mirando la pantalla.
Katja había conectado su laptop a la pantalla mural. La síntesis semanal de Navigator llenaba el lado izquierdo del panel de sesenta y cinco pulgadas. La nueva línea base DORA estaba a la derecha. Los temas resaltados bajaban por un lado. Las señales de entrega por el otro.
“Navigator sintetizó tres semanas de bitácoras diarias”, dijo Katja. “Y para este caso puntual le puse al lado una línea base DORA. No opiniones. No una queja aislada. Una descripción repetida de cómo se siente realmente el trabajo aquí, respaldada por evidencia de entrega.”
Lukas dejó el café. Estudió la pantalla como un hombre que mira un estado de cuenta cuando ya sabe que el mes salió mal.
“¿Esto pasa cada semana?”, preguntó.
“La síntesis, sí”, dijo Katja. “La línea base DORA es nueva. Las dos apuntan al mismo problema.”
Lukas volteó hacia Stefan.
Stefan se había colocado cerca de la pantalla. Sin dominarla. Solo lo bastante cerca para señalar cosas.
“Tus competidores no viven así”, dijo Stefan. “La gente que escribe bitácoras en este reporte está describiendo el mismo ciclo que la línea base DORA deja expuesto: ramas grandes, fusiones apuradas, arreglos de madrugada, alivio cuando nada se incendia. Eso no es normal. Solo es familiar.”
La mandíbula de Lukas se movió apenas. El tatuaje de Wooga en la parte interior de su muñeca asomó cuando cambió la mano sobre la mesa. Conocía esas empresas. Había trabajado en una de ellas. Sabía cómo era su cultura de despliegue. Solo que no había medido la distancia entre ese mundo y el suyo.
“La síntesis le da voz humana al problema”, dijo Stefan. “La vista DORA le da bordes duros.”
Katja abrió la evidencia de respaldo. Nombres de ramas abiertas. Comentarios de review que casi no decían nada. Una nota de Hassan de un viernes por la noche sobre desenredar conflictos solo.
“Esto no es review”, dijo Katja. “Es teatro de permiso con hashes de commit.”
Lukas se sentó.
“Son ceremonias de fusión”, dijo Stefan. “No integración continua. Los equipos acumulan cambios en ramas de feature durante días. A veces semanas. Luego lo fusionan todo de golpe. Las fusiones chocan. Los conflictos tardan horas en resolverse. La resolución mete bugs. Los bugs llegan a producción porque nadie puede revisar un cambio inflado con la suficiente rapidez como para entenderlo. Los despliegues tambalean. La recuperación cae sobre la misma gente. El ciclo se repite.”
Lukas guardó silencio largo rato. El aire acondicionado empujaba aire frío por la sala. Tras las paredes de vidrio, el piso de desarrollo seguía llenándose. Se alcanzaban a ver los cut-offs de Mariana en su escritorio de pie. El hoodie oscuro de Hassan ya estaba en su sitio, audífonos puestos.
“Entonces las puertas no están creando confianza”, dijo Lukas al fin.
“No”, dijo Stefan. “Están creando demora y sensación de seguridad. No es lo mismo.”
Lukas cerró los ojos un instante. El gesto de un hombre haciendo una cuenta que no quiere hacer.
“¿Cuál es la solución?”, preguntó.
“Trunk-based development”, dijo Stefan. “Una rama. Los desarrolladores hacen commit a main varias veces al día. Cambios pequeños. Integración continua. Tests automatizados en cada commit. Sin ramas de feature que vivan semanas. Sin PRs de dos mil líneas. Sin ceremonias de fusión.”
Lukas abrió los ojos.
“¿Sin ramas de feature?”
“Sin ramas de feature de larga vida. Ramas cortas para unas horas de trabajo, fusionadas el mismo día. Feature flags para funcionalidades incompletas. Commits pequeños y frecuentes en lugar de tandas grandes y espaciadas.”
Lukas miró a Katja.
“¿Qué piensa Daniel de esto?”
“Todavía no lo sabe”, dijo Katja.
Lukas volvió a tomar el café.
“Va a perder la cabeza”, dijo.
“Probablemente”, dijo Stefan.
“Háganlo.”
Stefan asintió.
“Muéstrenle las dos cosas”, dijo Lukas. “Si quiere discutir contra un patrón que todo el equipo sigue describiendo y la evidencia de entrega apunta al mismo sitio, ese es su problema.”
Se puso de pie. Miró el Apple Watch. 09:52. El gesto automático. El tiempo siempre corriendo.
En la puerta hizo una pausa.
“¿Cuánto falta para que los competidores desplieguen diez veces al día mientras nosotros seguimos haciendo ceremonias de fusión cada tres semanas?”, dijo.
“Ya lo hacen”, dijo Stefan.
Lukas salió. La puerta de vidrio se cerró detrás de él.
Katja soltó el aire.
“Eso salió mejor de lo que esperaba”, dijo.
“Tiene miedo”, dijo Stefan. “El miedo sirve. Significa que va a dejarnos probar cosas que no habría aprobado hace tres semanas.”
Katja miró la síntesis que seguía llenando la pantalla. El lenguaje repetido. El mismo dolor, dicho de tres maneras. El patrón.
“Esas brechas”, dijo. “Cada una es alguien como Hassan arreglando algo un viernes por la noche y sin poder desplegarlo por las puertas de aprobación.”
Stefan escribió en su cuaderno:
La brecha entre el arreglo y el despliegue es donde la frustración se vuelve resignación.
Stefan trazó una línea en la pizarra.
Una línea. Horizontal. Marcador negro.
Encima escribió una palabra: main.
Luego tapó el marcador y se dio vuelta.
Doce desarrolladores lo estaban mirando. Algunos de pie. Otros sentados sobre escritorios. Otros con las piernas cruzadas en sillas que habían rodado desde sus puestos. El piso de desarrollo se había reacomodado alrededor de la pizarra como un aula que nadie planeó.
Daniel estaba parado en el borde del grupo. Brazos cruzados. El Moleskine en la mano derecha, cerrado. La mandíbula tensa. Camisa azul claro abotonada, por dentro. Khakis. Zapatos de cuero. La única persona en la sala que no estaba en tenis ni descalza.
“¿Eso es todo?”, dijo Daniel.
“Eso es todo”, dijo Stefan. “Una rama. main. Cada commit va a main. Todos los días.”
“Eso es imprudente”, dijo Daniel.
“¿Lo es?”, dijo Stefan.
Mariana estaba apoyada en su escritorio de pie, a unos cuatro metros. La camiseta de Sepultura estaba tan gastada que el logo de la banda era más recuerdo que impresión. Cut-offs. Pies morenos descalzos sobre la alfombra de la oficina. Brazos cruzados. La media sonrisa apenas se veía, pero Stefan la vio.
“¿Entonces ahora solo empujamos a main?”, preguntó Sofia desde su silla. Camiseta blanca corta. Jeans de tiro alto. La clase de pregunta que hace alguien lo bastante nueva como para no tener opiniones todavía y lo bastante lista como para preguntar de todos modos.
“Empujan a main a través de ramas de vida corta”, dijo Stefan. “Creas una rama. Haces unas horas de trabajo. Abres un PR. Lo revisan. Lo fusionas el mismo día. La rama muere antes de crecer.”
“Eso es lo que hacemos ahora”, dijo Daniel.
“No.” Stefan volvió a destapar el marcador. Debajo de la línea dibujó varias ramas largas y diagonales saliendo de main como dedos torcidos. Aparecieron etiquetas: feature/new-match-system, feature/analytics-v2, hotfix-temp-do-not-delete, hassan-friday-night-fix. Las dibujó largas, separándose, con la distancia respecto a main creciendo con cada centímetro.
“Esto es lo que hacen ahora”, dijo Stefan. “Ramas de feature que viven días. Semanas. Hay una rama de tres semanas que sigue sin fusionarse. Siete ramas tienen conflictos de fusión activos. Su rama promedio vive seis días antes de tocar main otra vez.”
Retrocedió un paso.
“Para el día seis, la rama ya se desvió tanto de main que fusionarla se vuelve un proyecto en sí mismo. Tarda horas. Requiere resolver conflictos a mano. La persona que resuelve los conflictos normalmente no es la que escribió el código. No lo entiende. Elige un lado. A veces elige mal.”
Hassan se acomodó sobre el borde del escritorio donde estaba sentado. Capucha abajo. Audífonos en el cuello. La cara no cambió, pero las manos se fueron al regazo, entrelazando los dedos.
“He pasado cuatro de los últimos seis viernes resolviendo conflictos de fusión”, dijo Hassan. En voz baja. De esa clase de voz baja que pesa más que el volumen. “No los míos. Ramas de otra gente que chocaron con despliegues. La gente que creó el conflicto se fue a las cinco. Yo me quedé.”
La sala absorbió eso.
“¿Cuánto tiempo?”, preguntó Mariana.
“Tres horas el viernes pasado. Cuatro la semana anterior. La anterior a esa, dos, pero producción se rompió durante la fusión y me quedé hasta medianoche arreglándolo.”
Nueve horas a lo largo de tres viernes. Hassan, solo, deshaciendo los nudos que las ramas largas le estaban atando a la base de código. Mientras otros desarrolladores se iban a casa, a bares, a clubes, a dormir.
Nadie dijo nada durante varios segundos.
Los brazos cruzados de Daniel se tensaron.
“Las puertas de aprobación existen por una razón”, dijo. “Sin ellas, código no probado llega a producción.”
Stefan se volteó hacia él. No agresivo. No despectivo. Solo directo.
“Daniel, ¿puedes decirme la tasa de defectos escapados desde que implementaste las puertas de aprobación actuales?”
Daniel parpadeó.
“¿La qué?”
“Señálame una semana del último mes en la que esas puertas hayan creado confianza en lugar de demora.”
Silencio.
“Eso no es lo que dice la síntesis”, dijo Daniel.
“No”, dijo Stefan. Miró de reojo la línea base DORA en la pantalla de Katja y luego la síntesis de Navigator. “Lo que dice es peor. La línea base DORA muestra que las puertas actuales no están produciendo la seguridad de entrega que crees. Y semana tras semana la síntesis dice lo mismo en lenguaje simple: las aprobaciones llegan rápido pero no contestan las preguntas difíciles. Las fusiones ocurren tarde. Los arreglos caen en viernes. La gente espera permiso y aun así no se siente segura. Las puertas no están creando confianza. Están creando demora.”
La cara de Daniel se puso roja. No de enojo. Del calor específico que da cuando tu certeza se mide contra evidencia y encuentras un hueco donde debería haber piso.
“Eso no es justo”, dijo Daniel. “Las puertas sí atrapan cosas. No puedes probar lo que evitan.”
“Tienes razón”, dijo Stefan. “No puedo medir lo que nunca pasó. Puedo medir la forma de entrega que sí tenemos, y puedo leer lo que el equipo sigue escribiendo de todos modos. Siguen sin confiar en el resultado.”
Anton habló desde el fondo. Camiseta oscura, brazos cruzados, recargado en una columna. Su acento ruso endurecía las consonantes.
“Las puertas atrapan temas de estilo y archivos de test faltantes”, dijo Anton. “Atrapan errores tipográficos en nombres de variables. No atrapan problemas arquitectónicos porque los reviewers no entienden la arquitectura. Ese es el problema.”
Daniel se volvió hacia él.
“Para eso no están las puertas”, dijo Daniel.
“¿Entonces para qué están?”, dijo Mariana. Seguía recargada. Seguía con esa media sonrisa. Pero la voz tenía filo.
Daniel abrió el Moleskine. La mano se le fue hacia el bolígrafo del bolsillo del pecho. El gesto automático de un hombre que documenta todo porque documentación es control y control es seguridad.
“Aseguran que cada pieza de código sea revisada antes de entrar al sistema”, dijo Daniel. “Ese es el principio fundamental.”
“¿Revisada por quién?”, dijo Stefan. “¿Para qué? ¿En cuánto tiempo? Los comentarios casi no dicen nada. La comprensión no se está transfiriendo. La gente deja emojis de pulgar arriba y comentarios de LGTM y sigue de largo. Lo probamos la semana pasada con el disyuntor de Tomasz.”
El bolígrafo de Daniel se detuvo.
El disyuntor. La semana pasada. El que había protegido producción durante dieciocho meses y alguien aprobó en ocho minutos. El que nadie entendió hasta que Tomasz estaba en sus últimas setenta y dos horas en la empresa y se lo explicó a una sala que debió entenderlo el día en que lo escribió.
Nadie necesitó mencionar el nombre de Tomasz. El hoodie gris seguía visible para todos. El escritorio vacío donde antes colgaba sobre el respaldo de la silla estaba a diez metros, limpio y reasignado.
“¿Qué es exactamente lo que propones?”, dijo Daniel. La voz le había cambiado. Más baja. El borde defensivo reemplazado por algo más cauteloso. No acuerdo. Pero sí el reconocimiento de que discutir con la teoría de hoy contra la evidencia de ayer era una mala posición.
Stefan volvió a la pizarra. Borró las ramas largas y diagonales hasta dejar solo la línea horizontal.
“main”, dijo. “Una rama. Los desarrolladores crean ramas cortas que viven horas, no días. Los PRs son pequeños. Menos de doscientas líneas. Se revisan el mismo día. Se fusionan el mismo día. La rama muere.”
Dibujó líneas cortas, casi verticales, que salían de main y regresaban de inmediato. Arcos pequeños. Salidas breves y regresos rápidos.
“Integración continua. Cada fusión dispara tests automatizados. Los tests corren en minutos, no en horas. Si pasan, el código es desplegable. Si fallan, el desarrollador que los rompió los arregla de inmediato. No mañana. No después del standup. Ahora.”
“¿Y las puertas de aprobación?”, dijo Daniel.
“Se reemplazan con checks automatizados. Linting. Umbrales de cobertura. Verificación de build. La máquina hace el trabajo de puerta. Los humanos hacen el trabajo de comprensión. Reviews en pareja para contexto, no para permiso.”
Daniel miró la pizarra. La línea única. Los arcos cortos. La simplicidad de aquello chocaba con la complejidad que él había construido dentro de su proceso de aprobación durante dos años.
“Si alguien empuja código roto a main, producción se rompe”, dijo Daniel.
“Si alguien empuja un PR inflado que nadie lee de verdad, lo aprueban de todos modos y trae un bug, producción se rompe igual”, dijo Stefan. “Eso está pasando ahora. La línea base DORA te da un ángulo. La síntesis te da el vivido.”
Nota del lector: El trunk-based development no es una idea nueva. Los equipos de alto desempeño llevan más de una década trabajando así. La investigación es clara: ramas de vida corta fusionadas el mismo día, con commits a una línea principal compartida varias veces al día, producen menos defectos, recuperación más rápida y entregas más frecuentes que las ramas largas con procesos extensos de puertas.
Los pull requests fueron diseñados para proyectos de código abierto donde maintainers revisan contribuciones de desconocidos. Dentro de un equipo cohesionado de empresa, el mismo mecanismo se convierte con facilidad en un ritual de permiso. Gente sentada a diez metros empieza a comportarse como si fueran contribuyentes anónimos de internet. El PR pequeño del mismo día en este episodio es un paso de transición, no el destino. El estado final es no tener pull requests internos: commits directos a `main`, pairing para comprensión compartida y checks automatizados haciendo la portería mecánica en la que los humanos son malos.
La resistencia que muestra Daniel es común y entendible. Las puertas de aprobación se sienten seguras. Representan disciplina de proceso y responsabilidad. Pero las puertas solo sirven si alguien realmente revisa lo que pasa por ellas. Cuando los reviews se vuelven sellos de goma, la puerta es una entrada abierta con un letrero que dice "Control de seguridad". Reemplazar ese teatro con checks automatizados y colaboración humana de verdad no elimina seguridad. La mueve de la ceremonia a la práctica.
Mariana se apartó de su escritorio. Pies descalzos sobre la alfombra. Caminó hacia la pizarra y miró la línea única.
“Esta es la primera propuesta honesta que alguien ha hecho en seis meses”, dijo.
Ya no sonreía. La cara recta. El tatuaje Tupi-Guarani en el antebrazo oscuro sobre la piel morena bajo la luz de la tarde.
“El viernes pasado”, dijo, girándose hacia el grupo, “fusioné un PR de mil doscientas líneas desde una rama que llevaba nueve días viva. Me tomó cuarenta minutos resolver los conflictos. Los conflictos existían porque otras tres personas habían tocado los mismos archivos durante esos nueve días. Elegí una versión. Adiviné. Me equivoqué en una. Hassan la encontró a las once de la noche y la arregló en producción.”
Miró a Hassan.
Hassan asintió una vez.
“Nueve días”, dijo Mariana. “Si esa rama se hubiera fusionado dentro del día, los conflictos nunca habrían pasado. Yo no adivino. Hassan no se queda hasta las once.”
Stefan observó la sala. Los desarrolladores que no habían hablado estaban haciendo las cuentas. Calculando cuántas horas habían perdido en conflictos de fusión, en ramas viejas, en esa clase específica de sobrecarga cognitiva que aparece cuando manejas una rama que se desvió tanto de main que ya ni recuerdas en qué estado estaba el código cuando empezaste.
Daniel seguía de pie. Seguía sosteniendo el Moleskine. Pero el bolígrafo había vuelto al bolsillo.
“Quiero ver los checks automatizados antes de empezar”, dijo Daniel.
No era una objeción. Era una condición.
Stefan asintió.
“Los montamos esta semana. Hassan y yo configuramos el pipeline de CI. Tests automatizados, linting, verificación de build. Cuando eso esté en verde, el código está listo para revisión humana. La revisión humana trata de comprensión, no de permiso.”
“¿Cuánto dura la prueba?”, dijo Daniel.
“Dos semanas. El equipo de backend. El equipo de Mariana. Empezamos el jueves. Registramos el experimento en Navigator. Fusiones en el mismo día, si los reviews vuelven a ser reales, si Hassan recupera las noches. Después de dos semanas comparamos el patrón.”
Daniel escribió algo en el Moleskine. Corto. Preciso. Probablemente la palabra jueves y un signo de interrogación.
“Bien”, dijo Daniel.
Una palabra. No entusiasta. No derrotada. La palabra de un hombre al que le mostraron un número contra el que no podía discutir y que estaba eligiendo confiar en el proceso de probarlo equivocado.
“Bien”, repitió Stefan.
Mariana seguía junto a la pizarra. Le quitó el marcador a Stefan y dibujó un pequeño círculo sobre la línea donde estaba la palabra main.
“Jueves”, dijo. El círculo era un punto al final de una frase que el equipo llevaba meses tratando de escribir.
Los dedos de Mariana flotaban sobre el teclado.
La terminal estaba abierta. La rama se llamaba fix-leaderboard-cache-ttl. Siete archivos cambiados. Cuarenta y tres líneas. El tipo de cambio que hace dos semanas habría ido metido dentro de un PR más grande. Junto con otros tres arreglos. Enviado como un commit de seiscientas líneas. Revisado por nadie. Aprobado por todos.
Hoy estaba solo.
Hassan había pasado martes y miércoles reconstruyendo el pipeline de CI con Stefan. Linting automatizado. Suite de tests en cada push. Verificación de build. Umbral de cobertura en setenta y ocho por ciento, que era la línea base actual. Lo subirían después. Por ahora, la puerta era: ¿linta, prueba y construye? Tres preguntas. Tres respuestas automatizadas.
Las marcas verdes aparecieron cuatro minutos después del push.
“¿Eso es todo?”, dijo Sofia.
Miraba desde su silla. Crop tee negra. Jeans de tiro alto. La silla echada hacia atrás desde el escritorio para poder ver la pantalla de Mariana sin ponerse de pie.
“Eso es todo”, dijo Mariana. “CI en verde. Lint. Tests. Build.”
“¿Y ahora qué?”
“Ahora alguien lo lee.”
Hassan ya lo estaba leyendo. Había abierto el PR en su pantalla en el momento en que apareció. Siete archivos. Cuarenta y tres líneas. Los recorrió como siempre, rápido y preciso, deteniéndose donde cambiaba la lógica.
“El TTL del caché estaba en treinta minutos”, dijo. “Lo cambiaste a cinco.”
“Los datos del leaderboard se quedan viejos en treinta minutos”, dijo Mariana. “Los jugadores se ven en el puesto quince cuando en realidad están en el ocho. Mandan tickets de soporte. El equipo de Marcus se está ahogando en eso.”
“¿Por qué cinco?”
“Vi los datos de rendimiento de queries. La consulta del caché nos cuesta doce milisegundos. En intervalos de cinco minutos agregamos tal vez cuarenta queries por minuto. La base de datos ni se entera.”
Hassan asintió. Un solo asentimiento. El asentimiento de un hombre que entendía tanto el cambio como el razonamiento, porque el razonamiento estaba incluido y porque el cambio era lo bastante pequeño para caber en una cabeza humana sin perder el contexto.
“Aprobado”, dijo Hassan.
El PR se fusionó. Veintisiete minutos desde que se creó la rama hasta main.
La camiseta de Sepultura del lunes había sido reemplazada por una playera sin mangas de Kreator, rota en los hombros. El calor del estudio ya se movía hacia verano. Se había quitado los zapatos antes de las nueve. Sus pies descalzos eran silenciosos sobre la alfombra mientras iba al dispensador de agua y regresaba, con el movimiento de alguien que dejó de esperar permiso.
Para el mediodía, el equipo de backend había fusionado cuatro PRs pequeños. Ninguno fue un sello automático. Cada uno tuvo al menos un comentario que demostraba que el reviewer había leído el código.
Stefan estaba en su escritorio mirando el piso en vez de un dashboard. Las preguntas estaban llegando antes. Los reviews eran lo bastante cortos para poder entenderlos. Nadie tenía cara de estar cazado.
Daniel observaba desde su escritorio al otro lado del piso. No había cerrado el Moleskine en toda la mañana. El bolígrafo se movía en trazos pequeños y controlados. Fuera lo que fuera que estaba escribiendo, era detallado y probablemente organizado por marca de tiempo.
A las 12:15 caminó hasta el escritorio de Stefan.
“El arreglo del caché”, dijo Daniel. “¿Quién verificó que funciona en staging?”
“Los tests automatizados cubren el comportamiento del caché”, dijo Stefan. “Hassan revisó manualmente el impacto en las queries.”
“¿En staging?”
“No tenemos un entorno de staging que refleje producción”, dijo Stefan. “Tú lo sabes.”
El bolígrafo de Daniel golpeó el Moleskine.
“Esa es una brecha”, dijo Daniel.
“Sí”, dijo Stefan. “Lo es.”
Se miraron. No hostiles. Dos hombres viendo la misma brecha desde lados distintos. Daniel la veía como razón para ir más despacio. Stefan la veía como un problema que hay que resolver, pero no como razón para detenerse.
“Llevo ocho meses diciendo que necesitamos un staging de verdad”, dijo Daniel.
“Tienes razón”, dijo Stefan. “Has tenido razón en eso. Construyámoslo.”
Daniel parpadeó. La respuesta que traía preparada murió en algún lugar entre el Moleskine y la boca. Esperaba resistencia. Recibió acuerdo.
“Ayúdame a acotarlo después de la prueba de dos semanas”, dijo Stefan. “Tus requisitos de QA, el conocimiento de infraestructura de Hassan, las necesidades del equipo de Mariana. Un entorno de staging que sí refleje producción.”
Daniel cerró el Moleskine. No de golpe. Un cierre controlado. De esos que significan que la conversación terminó pero el pensamiento sigue.
“Después de la prueba”, dijo Daniel.
Regresó a su escritorio.
Mariana había observado el intercambio desde su escritorio de pie. Le sostuvo la mirada a Stefan y levantó una ceja. La pregunta más pequeña posible.
Stefan respondió con una leve inclinación de cabeza.
Va a ceder, decía ese gesto. Dale evidencia, no argumentos.
Para las 17:00 ya habían fusionado seis PRs. Seis desarrolladores habían hecho commit a main en el primer día del experimento. Nadie había roto el build. Nadie había sellado un review sin leerlo. Nadie había creado una rama que siguiera existiendo el lunes.
Hassan se fue a las 17:15.
En jueves.
Nadie lo comentó. Pero Stefan lo notó. Y Mariana lo notó. Y el hecho de que nadie comentara que Hassan se fue a las 17:15 un jueves ya era notable, porque nadie recordaba la última vez que Hassan se había ido antes de las seis un día laboral.
“¿Cuántas quedan?”, preguntó Mariana.
Estaba de pie junto al escritorio de Stefan, mirando la lista de ramas de GitHub en su pantalla. La tank de Arch Enemy era lo bastante delgada como para marcar el contorno del tirante del bra deportivo. Viernes. El piso se estaba vaciando. Desarrolladores yéndose en pares, haciendo planes para el fin de semana. Las negociaciones de la cerveza de salida habían empezado a las cuatro.
“Cuarenta y tres ramas viejas”, dijo Stefan. “Bajamos de cuarenta y siete el lunes.”
“¿Solo matamos cuatro?”
“El equipo fusionó cuatro que estaban casi listas. Las otras treinta y nueve son el cementerio. Algunas tienen semanas. Otras meses.”
Mariana recorrió la lista. Nombres que reconocía. Nombres que no. Ramas creadas por desarrolladores que ya habían dejado la empresa. Ramas creadas en épocas de crunch y abandonadas cuando el crunch terminó y nadie volvió a limpiarlas.
feature/improved-matchmaking-v2 — último commit: 14 de marzo. Dos meses fría.
experiment/new-tutorial-flow — último commit: 8 de enero. Cinco meses. Un fantasma.
hotfix-temp-do-not-delete — último commit: 22 de abril. El nombre había sido una advertencia que se volvió mentira. Nadie sabía qué arreglaba. El desarrollador que la creó estaba en el equipo de Unity y tampoco se acordaba.
“Estos son pensamientos a medio hacer”, dijo Mariana. “Cada una es alguien que empezó algo, lo jaló otra prioridad y nunca volvió.”
“Fragmentación de prioridades”, dijo Stefan. “Navigator viene describiéndolo desde hace semanas. Demasiadas cosas urgentes, demasiadas ramas sin terminar, demasiada gente jalada de lado antes de poder acabar algo. La rama se vuelve un monumento a la interrupción.”
El pulgar de Mariana recorrió el tatuaje de su antebrazo. El patrón geométrico Tupi-Guarani. El gesto que hacía cuando estaba pensando algo de verdad.
“¿Podemos borrarlas?”
“Todavía no. Algunas podrían tener trabajo que necesitamos. Marquemos a los dueños, preguntemos si siguen siendo relevantes. Si en una semana nadie responde, las archivamos.”
“¿Y la regla nueva?”
“Ninguna rama vive más de veinticuatro horas. Si no está fusionada al final del día, se discute en el standup de la mañana siguiente. Si no se puede fusionar, se rompe en piezas más pequeñas o se abandona.”
Mariana asintió. Luego sonrió. No la media sonrisa. Una sonrisa de verdad. Rápida y afilada, como si hubiera atrapado algo que venía persiguiendo.
“¿Sabes qué es diferente?”, dijo.
“¿Qué?”
“No he resuelto ni un solo conflicto de fusión esta semana.”
Stefan dejó que eso se quedara un momento.
Cero conflictos de fusión. En cinco días. Después de que cuatro de los últimos seis viernes se los habían tragado enteros. Después de que Hassan había pasado nueve horas en tres fines de semana desenredando ramas ajenas.
Cero.
“Hassan se fue ayer a las 17:15”, dijo Stefan.
“Lo sé. Lo vi pasar junto a mi escritorio, decir ‘Bis morgen’ y casi me caigo del escritorio de pie.”
Se rió. Corto. La clase de risa que se escapa antes de que decidas si contenerla.
“Eso es lo que importa”, dijo Stefan. “Si Hassan se va a casa antes de que oscurezca.”
La sonrisa de Mariana se apagó en algo más serio.
“Dos días”, dijo. “Dos días de PRs pequeños, fusiones el mismo día, checks automatizados. Y ya nadie se está quedando tarde a limpiar el desastre de otro.”
“Dos días no hacen una tendencia”, dijo Stefan.
“No. Pero sí una dirección.”
Stefan cerró la laptop. La pantalla se puso negra. La lista de ramas de GitHub desapareció, pero las cuarenta y tres ramas fantasma no. Seguían ahí, suspendidas entre la intención y la ejecución, esperando a que alguien admitiera que estaban muertas.
Guardó la laptop en la bolsa mensajera. Canvas. Desteñida por el sol.
“La próxima semana”, dijo. “Seguimos. Si el patrón aguanta, lo expandimos al equipo de Unity.”
“Anton va a querer ver evidencia”, dijo Mariana.
“Bien. La evidencia escrita es todo lo que necesitamos.”
El piso ya estaba casi vacío. La luz de finales de mayo caía por las ventanas del sur. Golden hour en Kreuzberg. El U-Bahn retumbaba abajo. La bocina Bluetooth de alguien estaba tocando jazz amortiguado desde la terraza, donde los primeros en llegar para las cervezas del viernes ya estaban acomodándose.
El escritorio de Hassan estaba a oscuras. Monitor apagado. Silla metida. Audífonos colgando del brazo del monitor. Todo en su lugar. El escritorio de un hombre que se había ido a una hora humana y volvería el lunes a una base de código que no lo había emboscado durante el fin de semana.
Mariana se dirigió hacia las escaleras, descalza.
“Mari”, dijo Stefan.
Ella se volvió.
“Gracias por escoger el jueves. El primer commit importó.”
La boca de Mariana hizo esa cosa en la que una media sonrisa intenta convertirse en algo más cálido y se queda a mitad de camino.
“Alguien tenía que ir primero”, dijo. “Bien podía ser la persona que llevaba más tiempo emputada.”
Subió las escaleras de dos en dos. Silenciosa sobre los pies descalzos. El tatuaje Tupi-Guarani desapareció al doblar la esquina.
Stefan se quedó sentado solo un momento. El piso de desarrollo zumbaba con el sonido de monitores entrando en reposo y el HVAC del edificio bajando revoluciones para el fin de semana.
Abrió su cuaderno y escribió:
Día 2 de trunk-based. Seis PRs pequeños. Comentarios de review reales. Cero limpieza de conflictos de fusión. Hassan se fue a las 17:15.
El proceso no cambió porque alguien argumentó mejor. Cambió porque alguien hizo commit primero.
Cerró el cuaderno. Tomó la bolsa. Se fue a las 17:00.
A tiempo. Como siempre.
Navigator — Katja Müller — 30 de mayo de 2026, 21:33
Primera semana de trunk-based development en el equipo de backend. Dos días. Stefan lo propuso el lunes después de que pasamos una hora leyendo la síntesis semanal de Navigator junto a una nueva línea base DORA.
El reporte dijo lo que la salida de Tomasz ya había vuelto imposible ignorar: las ramas vivían demasiado tiempo, los reviews ocurrían demasiado rápido para transferir comprensión y el trabajo de recuperación del viernes seguía cayendo sobre la misma gente. La línea base DORA no reemplazó ese diagnóstico. Lo confirmó, de una manera acotada y útil, mostrando que los síntomas de entrega coincidían con la experiencia vivida.
Stefan y yo le mostramos las dos cosas a Lukas el lunes por la mañana. Preguntó: “¿Esto pasa cada semana?” y pude ver el momento en que entendió que nuestro problema de entrega no era un sprint malo. Era el sistema operativo.
El martes, Stefan trazó una línea en la pizarra y escribió una palabra: main. Daniel objetó. Lo llamó imprudente. Stefan respondió con la síntesis y la línea base DORA: las puertas estaban frenando a la gente sin darles confianza. Daniel no tuvo contraargumento. Tuvo condiciones: ver primero los checks automatizados. Justo.
El jueves, Mariana empujó el primer PR pequeño. Un arreglo del TTL del caché que llevaba una semana sentado en una rama inflada. Hassan lo revisó con cuidado porque por fin el cambio era lo bastante pequeño para caber en un cerebro humano. Al final del día: seis PRs pequeños fusionados. Ninguna limpieza de conflictos de fusión. Ningún miedo de viernes colgando en la sala.
Hassan se fue a las 17:15 el jueves.
Ese es el dato que voy a recordar de esta semana. No porque un gráfico sea inútil. Sino porque Hassan salió del edificio mientras todavía había sol.
Dos días no hacen una tendencia. Pero llevo cinco meses viendo a Hassan trabajar después de que oscurece. He leído sus bitácoras de Navigator sobre viernes por la noche arreglando conflictos de fusión solo. He visto cómo se le marcan más las ojeras.
Si trunk-based development significa que Hassan se va a casa antes del atardecer, no necesito dos semanas de datos. Necesito al resto del equipo haciendo lo mismo.
Daniel está observando desde su escritorio. Moleskine abierto. Bolígrafo en movimiento. Va a llegar con preocupaciones para discutir el lunes. Bien. Sus preocupaciones sobre staging son válidas. Sí necesitamos un entorno de staging decente. Stefan estuvo de acuerdo con él en eso, y eso descolocó a Daniel. Nadie le había dicho a Daniel en meses que tenía razón en algo. Tal vez esa sea parte del problema.
La próxima semana: todo el equipo de backend en trunk-based. La semana siguiente: hablar con Anton sobre el equipo de Unity.
Navigator no me va a decir todo. Una línea base DORA tampoco. Pero juntas me van a decir si el mismo pánico sigue apareciendo con las mismas formas de siempre. Por primera vez en meses, creo que no.