ADR 0009 — Churn desde git, sin romper el determinismo
Desarrollo
Estado: aceptado ✅ · Fecha: 2026-10-20
Contexto
Sección titulada «Contexto»La lente de riesgo de M0 usa 0,5·complejidad + 0,32·churn + 0,18·tamaño. Hasta M1 no había
churn: el render renormalizaba los pesos y el mapa seguía siendo útil, pero perdía la señal de
cambio, que es la mitad de la cuña del producto (PR/CI).
Necesitamos historial por fichero sin convertir el snapshot en un artefacto dependiente de la hora de ejecución, del locale o de la máquina.
Decisión
Sección titulada «Decisión»- Un solo
git logpor análisis. No se ejecutagit log --followpor fichero. Se lanza:y se parsea una vez. Los commits merge se excluyen para no duplicar cambios.git -c core.quotePath=false log --no-merges --numstat --format=__CODARCH__%H%x09%ae - Métricas por fichero:
number_of_commitsynumber_of_authors. El autor se identifica por email. Los ficheros sin historial reciben0, no se omiten. - Todo el historial por defecto. Una ventana relativa (
--since "12 months ago") cambiaría el resultado con el paso del tiempo para el mismo commit. Si más adelante hace falta una ventana, será una fecha absoluta o un parámetro explícito. - Sin seguir renames. Un rename aparece como borrado + alta. Es una aproximación deliberada: seguir renames por fichero multiplica el coste y complica el determinismo.
- El snapshot solo guarda números derivados. No guarda fechas, autores, mensajes ni rutas absolutas. El checksum sigue siendo canónico.
- Si no hay git, se omite la señal.
codarch analyzefunciona en un directorio sin repo; el render renormaliza el riesgo. Un clon shallow produce un warning: los conteos pueden ser incompletos. - Tests sin git. Los fixtures de análisis pasan
git: false; el churn se prueba en un repo temporal con commits reales.
Consecuencias
Sección titulada «Consecuencias»- El mapa gana la señal de cambio sin una base de datos ni un servicio externo.
- El coste es lineal con el tamaño del historial. Un repo grande puede tardar más que el parser; se medirá y, si duele, se añadirá caché incremental.
- El análisis del working tree no incluye cambios sin commitear. Para CI se analiza un commit, que es exactamente el caso de uso.
- Un shallow clone no es equivalente a un clone completo. El warning evita una garantía falsa.
Alternativas descartadas
Sección titulada «Alternativas descartadas»git log --followpor fichero. Preciso para renames, pero N procesos y mucho más lento.- Librería de git en JS. Añade dependencia y superficie para algo que el binario de git ya hace.
- Churn calculado en el render. El render no debe ejecutar git ni depender del entorno.
- Guardar el historial completo en el snapshot. El snapshot es un mapa, no un archivo de git.
Hoja de ruta
Sección titulada «Hoja de ruta»Sin fases abiertas; esta decisión se aplica en M2.