Architecture Drift Score: ¿tu documentación dice la verdad? - Archyl Blog

El Architecture Drift Score es un número del 0 al 100 que mide cuánto de tu arquitectura documentada sigue existiendo en tu codebase. Esto es el mecanismo: la fórmula, qué entra en el denominador, qué se excluye deliberadamente, qué no puede ver la comprobación y cómo imponerlo en CI.

Architecture Drift Score: ¿tu documentación dice la verdad?

Una métrica que nadie puede auditar es una métrica sobre la que nadie debería actuar. Así que este post es la aritmética: cómo se produce el Architecture Drift Score, qué acaba en el denominador, qué dejamos fuera deliberadamente y las cuatro cosas que la comprobación no puede ver.

La puntuación responde a una sola pregunta. ¿Qué porcentaje de tu arquitectura documentada sigue existiendo en tu codebase? Es un número del 0 al 100, calculado a partir de una única petición a tu proveedor Git, sin IA de por medio y sin leer el contenido de ningún archivo.

Si lo que quieres es el problema en lugar de la aritmética, la guía de architecture drift cubre qué es el drift, por qué ocurre y las otras formas de detectarlo. Empieza por ahí y vuelve. Esta página da por hecho que ya quieres un número y quieres saber si creértelo.

Cómo leer el número

Abre cualquier proyecto en Archyl, haz clic en el icono de latido en el encabezado y pulsa "Compute Drift Score". En unos segundos tienes un número:

  • 90-100% — Excelente. Tu documentación coincide estrechamente con la codebase.
  • 70-89% — Bien. Mayormente precisa, algunas brechas por resolver.
  • 50-69% — Regular. Drift significativo detectado. Es hora de actualizar.
  • Por debajo de 50% — Tu documentación es ficción.

Esas franjas son nuestro criterio sobre qué merece la pena atender, no una medición de nada. El número que hay debajo es exacto.

Cómo se calcula el número

Cada elemento de tu modelo se clasifica en un bucket, y la puntuación es la proporción que ha sobrevivido:

score = floor( (matched + 0.5 × partial) / total × 100 )

total = matched + partial + missing_in_code + new_in_code
  • matched — el modelo dice que existe, el repositorio está de acuerdo.
  • missing_in_code — documentado y no encontrado. Un container cuyo directorio ha desaparecido, un elemento de código cuyo archivo se ha borrado.
  • new_in_code — encontrado en el repositorio, ausente del modelo. Sin documentar, que es drift en la otra dirección y cuenta en tu contra exactamente con la misma dureza.

partial vale medio crédito y está reservado a los elementos que coinciden pero con diferencias. Las comprobaciones actuales no lo producen: cada elemento acaba en una de las otras tres, así que en la práctica la puntuación es la fracción de matched. Te lo contamos porque una fórmula con un término que nunca se activa es el tipo de cosa que deberías oír de nosotros en lugar de descubrirla.

Dos detalles que importan cuando comparas dos ejecuciones. El resultado se trunca, no se redondea, así que 89,9 se reporta como 89. Y los elementos sin documentar agrandan el denominador, que es la razón por la que añadir tres servicios nuevos sin documentarlos baja tu puntuación aunque nada de lo que habías escrito se haya vuelto falso.

Qué se verifica realmente

El análisis de drift es ligero por diseño: una única petición recursiva de árbol a tu proveedor Git, sin IA, sin contenido de archivos obtenido. Valida tu arquitectura en cinco dimensiones:

Systems — ¿El nombre de tu repositorio coincide con el sistema documentado? Usamos la misma convención de nombres PascalCase que el pipeline de descubrimiento IA, con coincidencia difusa para que EkoAuthz coincida con un repositorio llamado authz.

Containers — ¿Los directorios de primer nivel de tu repositorio corresponden a los containers documentados? frontend/ coincide con FrontendWebApp. backend/ coincide con BackendApiServer. Los containers de infraestructura (bases de datos, colas, monitorización) que no tienen directorios de código fuente se excluyen, porque son documentación válida de servicios externos y no drift. La siguiente sección cubre lo que cuesta esa exclusión.

Components — ¿Los componentes bajo cada container siguen siendo válidos? Si el directorio del container padre existe, sus componentes se presumen válidos. Si el directorio del container ha desaparecido, todos sus componentes se marcan.

Code Elements — Esta es la verificación más precisa. Cada elemento de código de tu modelo C4 tiene un filePath. Verificamos que cada archivo siga existiendo en el repositorio. ¿Archivo renombrado? ¿Clase eliminada? ¿Módulo movido? El drift score lo detecta al instante.

Relationships — Una relación es válida si tanto su elemento de origen como el de destino pasaron la validación. Si cualquiera de los extremos ha derivado, la relación se marca.

El resultado es un desglose por elemento que muestra exactamente qué coincidió, qué falta y qué es nuevo: no una puntuación opaca, sino un informe accionable.

Qué se excluye del denominador

Una puntuación solo es tan honesta como las cosas que se niega a contar. Tres exclusiones, todas deliberadas:

Sistemas externos y personas. Todo lo tipado como sistema externo o como persona se descarta antes de la comparación, en ambos lados. Stripe, tu proveedor de identidad y "Cliente" pertenecen a un diagrama de System Context y ninguno de ellos aparecerá jamás en tu repositorio. Contarlos como ausentes te penalizaría por haber dibujado un diagrama correcto.

Containers de infraestructura sin directorio de código fuente. Un container documentado que no coincide con ningún directorio se elimina del recuento de containers en lugar de contarse como drift. Tu instancia de PostgreSQL, tu clúster de Kafka y tu cuenta de Datadog son containers legítimos y ninguno de ellos es una carpeta.

Esa regla tiene un coste y deberías conocerlo: un directorio de servicio real que borraste también queda excluido del recuento de containers, porque la comprobación no sabe distinguir "base de datos" de "servicio que eliminamos el sprint pasado". Sus componentes no quedan excluidos. Siguen resolviéndose como ausentes, porque su container padre no coincidió, así que un servicio eliminado sí aparece en la puntuación, un nivel más abajo de donde esperarías encontrarlo.

Elementos de código sin ruta de archivo registrada. Si un elemento de código de tu modelo no tiene filePath, no hay nada que verificar, así que se omite en lugar de adivinarlo. No puntúa ni a tu favor ni en tu contra. Las rutas generadas y de dependencias empaquetadas (vendor/, node_modules/, dist/, target/, __pycache__/ y el resto de la lista habitual) se filtran del árbol de archivos antes de que nada de esto se ejecute.

Por qué importa la ligereza

Elegimos deliberadamente no ejecutar el pipeline completo de descubrimiento IA para la detección de drift. He aquí por qué:

Velocidad. El análisis IA tarda minutos en repositorios grandes. El cálculo del drift score tarda segundos. Puedes ejecutarlo en cada push sin ralentizar tu pipeline.

Determinismo. La IA puede producir resultados diferentes sobre la misma codebase dependiendo de la temperatura del modelo, las variaciones de prompts y los límites de tokens. La existencia de una ruta de archivo es binaria: o el archivo está ahí o no. Tu puntuación es reproducible.

Coste. Sin tokens de IA consumidos. Sin límites de tasa de API alcanzados. Ejecútalo cien veces al día si quieres.

Simplicidad. El algoritmo es auditable. Verificar rutas de archivos, hacer coincidir nombres de directorios, validar relaciones. Sin caja negra.

Qué no puede ver la puntuación

Cada una de esas propiedades se compra con el mismo intercambio: la comprobación lee estructura, no código. Cuatro consecuencias, y ninguna de ellas es un bug que pretendamos ocultar.

El drift de comportamiento es invisible. Si dos servicios conservan sus nombres y sus directorios mientras la llamada HTTP síncrona entre ellos se convierte en un mensaje de cola, la puntuación no se mueve. Nada estructural ha cambiado. Este es el mayor punto ciego y no hay solución barata: detectarlo significa leer código o revisar el modelo con personas.

Un movimiento es idéntico a un borrado. Los elementos de código se validan por ruta de archivo exacta y sensible a mayúsculas. Mueve internal/auth/token.go a internal/identity/token.go sin tocar ni una línea y el elemento se reporta como ausente. Es técnicamente correcto, ya que la ruta documentada está mal, y significa que un refactoring que renombra directorios baja tu puntuación de una forma que parece alarmante y se resuelve con una edición de una línea por elemento.

La precisión a nivel de componente se hereda, no se verifica. Si el directorio de un container existe, todos los componentes que hay debajo se presumen válidos. La comprobación nunca mira dentro. Así que un container que sigue existiendo pero ha sido vaciado y reescrito puntúa como limpio a nivel de componente, y el número está más seguro de tu diagrama de Nivel 3 de lo que la evidencia respalda.

La coincidencia de nombres es generosa. Systems y containers se emparejan por nombre en tres pasadas: exacta sin distinguir mayúsculas, luego contención de subcadena en cualquiera de los dos sentidos, y luego tokens solapados tras dividir PascalCase y kebab-case. EkoAuthz coincide con un repositorio llamado authz; BackendApiServer coincide con un directorio llamado backend. Esto es lo que evita que diferencias triviales de nombres se reporten como drift, y se inclina a dar a tu modelo el beneficio de la duda. Si quieres una lectura estricta, usa el desglose por elemento en lugar del número de portada.

En conjunto, la puntuación es una buena medida de si tu modelo sigue describiendo el mismo sistema, y una medida débil de si lo describe correctamente. Trata una puntuación alta como "sin sorpresas estructurales", no como "la documentación es correcta".

Rastrea tendencias, no solo instantáneas

Una puntuación aislada es útil. Una tendencia es poderosa.

Cada cálculo de drift se almacena con su desglose completo. La pestaña Overview muestra un gráfico de barras de tu puntuación a lo largo del tiempo. Haz clic en cualquier barra para cargar ese informe histórico y ver exactamente qué cambió.

Esto convierte el drift scoring de una auditoría puntual en una métrica de salud continua. Puedes ver:

  • ¿El refactoring de la semana pasada mejoró o degradó la precisión de la documentación?
  • ¿El drift está empeorando con el tiempo, y algo de lo que cambiaste en el flujo de trabajo lo ha frenado?
  • ¿Qué sprint introdujo más cambios sin documentar?

Imponlo en CI

Una métrica que no impones es una métrica que ignorarás. Por eso construimos una GitHub Action.

on:
  push:
    branches: [main]

jobs:
  drift:
    runs-on: ubuntu-latest
    steps:
      - uses: archyl-com/actions/drift-score@v1
        with:
          api-key: ${{ secrets.ARCHYL_API_KEY }}
          organization-id: ${{ secrets.ARCHYL_ORG_ID }}
          project-id: 'your-project-uuid'
          threshold: '70'

Define threshold: '70' y la action falla si la precisión de tu documentación de arquitectura cae por debajo del 70%. El resumen del job muestra una tabla formateada con el desglose completo, visible directamente en los checks de tu PR.

También puedes publicar la puntuación como comentario de PR:

- uses: archyl-com/actions/drift-score@v1
  id: drift
  with:
    api-key: ${{ secrets.ARCHYL_API_KEY }}
    organization-id: ${{ secrets.ARCHYL_ORG_ID }}
    project-id: 'your-project-uuid'

- uses: actions/github-script@v7
  if: github.event_name == 'pull_request'
  with:
    script: |
      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: '## Architecture Drift: ' +
              '${{ steps.drift.outputs.score }}%\n' +
              'Matched: ${{ steps.drift.outputs.matched-count }}' +
              ' / ${{ steps.drift.outputs.total-elements }}'
      })

Cada desarrollador ve el impacto en el drift de sus cambios antes del merge. La documentación de arquitectura se convierte en ciudadana de primera clase en tu pipeline CI, junto a los tests, el linting y los análisis de seguridad.

MCP: agentes IA que conocen su precisión

Si usas Claude Code, Cursor o cualquier agente IA compatible con MCP junto al servidor MCP de Archyl, el drift scoring está disponible como herramienta:

compute_drift_score({ projectId: "..." })
get_drift_score({ projectId: "..." })
get_drift_history({ projectId: "..." })
get_drift_details({ scoreId: "..." })

Esto significa que un agente IA puede comprobar la precisión de la documentación antes de empezar a trabajar. La herramienta get_agent_context ya proporciona el modelo C4 completo, los ADRs y las reglas de conformidad. Ahora también puede comprobar cuán fiable es esa documentación.

Un agente que ve un drift score del 45% sabe que debe ser cauto con el contexto de arquitectura que ha recibido. Un agente que ve un 95% puede apoyarse con confianza en la estructura documentada. Esta es la base para agentes IA autoconscientes que ajustan su comportamiento según la calidad de la documentación.

Alertas por webhook: entérate cuando ocurre el drift

Dos nuevos eventos de webhook te permiten estar informado sin consultar dashboards:

  • drift.score_computed — Se dispara cada vez que termina de calcularse un drift score. Envíalo a un canal de Slack para dar visibilidad.
  • drift.score_degraded — Se dispara cuando la puntuación cae 10 puntos o más respecto al cálculo anterior. Este es tu sistema de aviso temprano: la arquitectura está derivando rápido.

Configúralos en los ajustes de webhooks de Archyl. Funcionan con Slack, Microsoft Teams, Discord y cualquier endpoint HTTP genérico.

La API REST

Para equipos que quieren control programático completo:

# Iniciar cálculo
curl -X POST https://api.archyl.com/api/v1/drift/compute \
  -H "X-API-Key: $API_KEY" \
  -H "X-Organization-ID: $ORG_ID" \
  -H "Content-Type: application/json" \
  -d '{"projectId": "your-project-uuid"}'

# Obtener última puntuación
curl https://api.archyl.com/api/v1/drift/latest?projectId=...

# Obtener historial de puntuaciones
curl https://api.archyl.com/api/v1/drift/history?projectId=...&limit=20

El cálculo es asíncrono: el POST devuelve inmediatamente un ID de puntuación, y haces polling hasta que status pasa a completed. La GitHub Action gestiona esto automáticamente.

Dónde encaja esto en el bucle

Una puntuación es un paso dentro de un ciclo: agentes y personas leen el modelo, el código cambia, la puntuación mide la brecha, la CI mantiene un umbral, el equipo reconcilia. Sin el paso de medición el ciclo no tiene retroalimentación y la documentación deriva sin que nadie la cuestione. Ese argumento, y el resto de la defensa de detectar el drift, está en la guía.

De lo que este post se hace responsable es de que el paso de medición sea fiable. De ahí la fórmula, las exclusiones y las cuatro cosas que no puede ver.

Para empezar

  1. Abre cualquier proyecto en Archyl
  2. Haz clic en el icono de latido en la barra de herramientas del encabezado
  3. Haz clic en "Compute Drift Score"
  4. Configura la GitHub Action para monitorización continua
  5. Configura un webhook de Slack para las alertas drift.score_degraded

Tu documentación de arquitectura refleja la realidad o no la refleja. Ahora tienes un número que te dice cuál de las dos, y suficiente de su aritmética como para discutir con él.


El resto del cluster: detección de architecture drift para el problema y los demás métodos de detección, documentación de arquitectura viva para las prácticas que evitan que una puntuación vuelva a caer. Definiciones: architecture drift. Página de producto: drift detection.