Architecture Drift Score: a sua documentação está dizendo a verdade? - Archyl Blog

O Architecture Drift Score é um número de 0 a 100 que mede quanto da sua arquitetura documentada ainda existe na sua codebase. Isto aqui é o mecanismo: a fórmula, o que entra no denominador, o que é deliberadamente excluído, o que a verificação não consegue enxergar e como impor tudo isso na CI.

Architecture Drift Score: a sua documentação está dizendo a verdade?

Uma métrica que ninguém consegue auditar é uma métrica sobre a qual ninguém deveria agir. Então este post é a aritmética: como o Architecture Drift Score é produzido, o que vai parar no denominador, o que deixamos de fora deliberadamente e as quatro coisas que a verificação não consegue enxergar.

O score responde a uma única pergunta. Qual percentual da sua arquitetura documentada ainda existe na sua codebase? É um número de 0 a 100, calculado a partir de uma única requisição ao seu provedor Git, sem IA no caminho e sem ler o conteúdo de nenhum arquivo.

Se você quer o problema em vez da aritmética, o guia de architecture drift cobre o que é drift, por que ele acontece e as outras formas de detectá-lo. Comece por lá e depois volte. Esta página parte do princípio de que você já quer um número e quer saber se pode acreditar nele.

Lendo o número

Abra qualquer projeto no Archyl, clique no ícone de batimento cardíaco no cabeçalho e pressione "Compute Drift Score". Em poucos segundos você tem um número:

  • 90-100% — Excelente. Sua documentação corresponde fielmente à codebase.
  • 70-89% — Bom. Majoritariamente precisa, algumas lacunas a resolver.
  • 50-69% — Regular. Drift significativo detectado. Hora de atualizar.
  • Abaixo de 50% — Sua documentação é ficção.

Essas faixas são o nosso julgamento sobre o que vale a pena tratar, não a medição de coisa alguma. O número que está por baixo delas é exato.

Como o número é calculado

Cada elemento do seu modelo é classificado em um bucket, e o score é a fatia que sobreviveu:

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

total = matched + partial + missing_in_code + new_in_code
  • matched — o modelo diz que existe, o repositório concorda.
  • missing_in_code — documentado e não encontrado. Um container cujo diretório sumiu, um elemento de código cujo arquivo foi deletado.
  • new_in_code — encontrado no repositório, ausente no modelo. Não documentado, o que é drift na direção oposta e pesa contra você exatamente com a mesma força.

partial vale meio crédito e é reservado a elementos que correspondem, mas com diferenças. As verificações de hoje não o produzem: cada elemento cai em uma das outras três categorias, então na prática o score é a fração de matched. Estamos contando isso porque uma fórmula com um termo que nunca dispara é o tipo de coisa que você deveria ouvir de nós em vez de descobrir sozinho.

Dois detalhes que importam quando você compara duas execuções. O resultado é truncado, não arredondado, então 89,9 é reportado como 89. E elementos não documentados aumentam o denominador, e é por isso que adicionar três serviços novos sem documentá-los derruba seu score mesmo que nada do que você já tinha escrito tenha se tornado falso.

O que é realmente verificado

A análise de drift é leve por design: uma única requisição recursiva de árvore ao seu provedor Git, sem IA, sem conteúdo de arquivo obtido. Ela valida sua arquitetura em cinco dimensões:

Systems — O nome do seu repositório corresponde ao sistema documentado? Usamos a mesma convenção de nomenclatura PascalCase do pipeline de discovery IA, com correspondência fuzzy para que EkoAuthz corresponda a um repositório chamado authz.

Containers — Os diretórios de primeiro nível no seu repositório correspondem aos containers documentados? frontend/ corresponde a FrontendWebApp. backend/ corresponde a BackendApiServer. Containers de infraestrutura (bancos de dados, filas, monitoramento) que não possuem diretórios de código-fonte são excluídos, porque são documentação válida de serviços externos e não drift. A próxima seção mostra o que essa exclusão custa.

Components — Os componentes sob cada container ainda são válidos? Se o diretório do container pai existe, seus componentes são presumidos válidos. Se o diretório do container desapareceu, todos os seus componentes são sinalizados.

Code Elements — Esta é a verificação mais precisa. Cada elemento de código no seu modelo C4 tem um filePath. Verificamos se cada arquivo ainda existe no repositório. Arquivo renomeado? Classe deletada? Módulo movido? O drift score detecta instantaneamente.

Relationships — Uma relação é válida se tanto o elemento de origem quanto o de destino passaram na validação. Se qualquer um dos extremos sofreu drift, a relação é sinalizada.

O resultado é um detalhamento por elemento mostrando exatamente o que correspondeu, o que está faltando e o que é novo — não um score opaco, mas um relatório acionável.

O que é excluído do denominador

Um score só é tão honesto quanto as coisas que ele se recusa a contar. Três exclusões, todas deliberadas:

Sistemas externos e pessoas. Tudo o que é tipado como sistema externo ou como pessoa é descartado antes da comparação, dos dois lados. Stripe, seu provedor de identidade e "Cliente" pertencem a um diagrama de System Context e nenhum deles jamais vai aparecer no seu repositório. Contá-los como ausentes seria punir você por ter desenhado um diagrama correto.

Containers de infraestrutura sem diretório de código-fonte. Um container documentado que não corresponde a nenhum diretório é removido da contagem de containers em vez de ser contado como drift. Sua instância PostgreSQL, seu cluster Kafka e sua conta Datadog são containers legítimos e nenhum deles é uma pasta.

Essa regra tem um custo e você precisa saber qual é: um diretório de serviço real que você deletou também fica de fora da contagem de containers, porque a verificação não sabe diferenciar "banco de dados" de "serviço que removemos na sprint passada". Os componentes dele não ficam de fora. Eles continuam sendo resolvidos como ausentes, porque o container pai não correspondeu, então um serviço removido aparece sim no score — um nível abaixo de onde você esperaria encontrá-lo.

Elementos de código sem caminho de arquivo registrado. Se um elemento de código no seu modelo não tem filePath, não há nada a verificar, então ele é pulado em vez de ser adivinhado. Não pontua nem a seu favor nem contra você. Caminhos gerados e de dependências vendorizadas (vendor/, node_modules/, dist/, target/, __pycache__/ e o resto da lista de sempre) são filtrados da árvore de arquivos antes de qualquer coisa disso rodar.

Por que a leveza importa

Escolhemos deliberadamente não executar o pipeline completo de discovery IA para detecção de drift. Eis o motivo:

Velocidade. A análise IA leva minutos para repositórios grandes. O cálculo do drift score leva segundos. Você pode executá-lo a cada push sem desacelerar seu pipeline.

Determinismo. A IA pode produzir resultados diferentes na mesma codebase dependendo da temperatura do modelo, variações de prompts e limites de tokens. A existência de um caminho de arquivo é binária — ou o arquivo está lá ou não está. Seu score é reproduzível.

Custo. Nenhum token de IA consumido. Nenhum limite de taxa de API atingido. Execute cem vezes por dia se quiser.

Simplicidade. O algoritmo é auditável. Verificar caminhos de arquivos, corresponder nomes de diretórios, validar relações. Sem caixa preta.

O que o score não consegue enxergar

Cada uma dessas propriedades é comprada com a mesma troca: a verificação lê estrutura, não código. Quatro consequências, e nenhuma delas é um bug que pretendemos esconder.

Drift comportamental é invisível. Se dois serviços mantêm seus nomes e seus diretórios enquanto a chamada HTTP síncrona entre eles vira uma mensagem em fila, o score não se mexe. Nada estrutural mudou. Este é o maior ponto cego e não existe solução barata para ele: pegá-lo significa ler código ou revisar o modelo com pessoas.

Uma movimentação parece exatamente uma exclusão. Elementos de código são validados por caminho de arquivo exato e sensível a maiúsculas. Mova internal/auth/token.go para internal/identity/token.go sem tocar em uma linha sequer e o elemento é reportado como ausente. Isso está tecnicamente correto, já que o caminho documentado está errado, e significa que um refactoring que renomeia diretórios derruba seu score de um jeito que parece alarmante e se resolve com uma edição de uma linha por elemento.

A precisão no nível de componente é herdada, não verificada. Se o diretório de um container existe, todo componente abaixo dele é presumido válido. A verificação nunca olha lá dentro. Então um container que ainda existe mas foi esvaziado e reescrito pontua como limpo no nível de componente, e o número está mais confiante sobre o seu diagrama de Nível 3 do que as evidências sustentam.

A correspondência de nomes é generosa. Systems e containers são correspondidos por nome em três passagens: exata sem diferenciar maiúsculas, depois contenção de substring em qualquer uma das direções, depois tokens sobrepostos após dividir PascalCase e kebab-case. EkoAuthz corresponde a um repositório chamado authz; BackendApiServer corresponde a um diretório chamado backend. É isso que impede que diferenças triviais de nomenclatura sejam reportadas como drift, e o erro tende a favorecer o seu modelo. Se você quer uma leitura estrita, use o detalhamento por elemento em vez do número de manchete.

Somando tudo, o score é uma boa medida de se o seu modelo ainda descreve o mesmo sistema, e uma medida fraca de se ele o descreve corretamente. Trate um score alto como "sem surpresas estruturais", não como "a documentação está certa".

Rastreie tendências, não apenas snapshots

Um score isolado é útil. Uma tendência é poderosa.

Cada cálculo de drift é armazenado com seu detalhamento completo. A aba Overview mostra um gráfico de barras do seu score ao longo do tempo. Clique em qualquer barra para carregar aquele relatório histórico e ver exatamente o que mudou.

Isso transforma o drift scoring de uma auditoria pontual em uma métrica de saúde contínua. Você consegue ver:

  • O refactoring da semana passada melhorou ou piorou a precisão da documentação?
  • O drift está piorando com o tempo, e alguma coisa que você mudou no fluxo de trabalho o desacelerou?
  • Qual sprint introduziu mais mudanças não documentadas?

Imponha na CI

Uma métrica que você não impõe é uma métrica que você vai ignorar. Por isso construímos uma 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'

Defina threshold: '70' e a action falha se a precisão da documentação da sua arquitetura cair abaixo de 70%. O resumo do job mostra uma tabela formatada com o detalhamento completo — visível diretamente nos checks da sua PR.

Você também pode publicar o score como comentário 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 desenvolvedor vê o impacto das suas mudanças no drift antes do merge. A documentação de arquitetura vira cidadã de primeira classe no seu pipeline CI — ao lado dos testes, do linting e das varreduras de segurança.

MCP: agentes IA que conhecem a própria precisão

Se você usa Claude Code, Cursor ou qualquer agente IA compatível com MCP junto ao servidor MCP do Archyl, o drift scoring está disponível como ferramenta:

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

Isso significa que um agente IA pode checar a precisão da documentação antes de começar a trabalhar. A ferramenta get_agent_context já fornece o modelo C4 completo, os ADRs e as regras de conformidade. Agora ela também pode checar o quanto essa documentação é confiável.

Um agente que vê um drift score de 45% sabe que deve ter cautela com o contexto de arquitetura que recebeu. Um agente que vê 95% pode confiar na estrutura documentada. Esta é a base para agentes IA autoconscientes que ajustam seu comportamento conforme a qualidade da documentação.

Alertas por webhook: saiba quando o drift acontece

Dois novos eventos de webhook permitem que você fique informado sem checar dashboards:

  • drift.score_computed — Dispara toda vez que um drift score termina de ser calculado. Envie para um canal do Slack para dar visibilidade.
  • drift.score_degraded — Dispara quando o score cai 10 pontos ou mais em relação ao cálculo anterior. Este é o seu sistema de alerta precoce — a arquitetura está derivando rápido.

Configure-os nas configurações de webhook do Archyl. Eles funcionam com Slack, Microsoft Teams, Discord e qualquer endpoint HTTP genérico.

A API REST

Para times que querem controle 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"}'

# Obter último score
curl https://api.archyl.com/api/v1/drift/latest?projectId=...

# Obter histórico de scores
curl https://api.archyl.com/api/v1/drift/history?projectId=...&limit=20

O cálculo é assíncrono — o POST retorna imediatamente com um ID de score, e você faz polling até que status se torne completed. A GitHub Action cuida disso automaticamente.

Onde isso se encaixa no ciclo

Um score é um passo dentro de um ciclo: agentes e pessoas leem o modelo, o código muda, o score mede a lacuna, a CI segura um limite, o time reconcilia. Sem o passo da medição o ciclo não tem retorno e a documentação vai derivando sem que ninguém a conteste. Esse argumento, e o resto da defesa de detectar drift, está no guia.

O que este post assume como responsabilidade é que o passo da medição seja confiável. Daí a fórmula, as exclusões e as quatro coisas que ele não consegue enxergar.

Primeiros passos

  1. Abra qualquer projeto no Archyl
  2. Clique no ícone de batimento cardíaco na barra de ferramentas do cabeçalho
  3. Clique em "Compute Drift Score"
  4. Configure a GitHub Action para monitoramento contínuo
  5. Configure um webhook do Slack para alertas drift.score_degraded

Sua documentação de arquitetura reflete a realidade ou não reflete. Agora você tem um número que diz qual das duas — e aritmética suficiente para discutir com ele.


O resto do cluster: detecção de architecture drift para o problema e os demais métodos de detecção, documentação de arquitetura viva para as práticas que impedem um score de escorregar de volta. Definições: architecture drift. Página de produto: drift detection.