Pular para o conteúdo

Propostas de ADRs

Seis ADRs no formato Archgate fundamentados nas evidências do estudo — com arquivos .rules.ts companheiros e regras de lint customizadas prontas para soltar em um codebase no estilo Sentry.

Esta página resume seis Architecture Decision Records fundamentados nas conclusões do estudo. Cada ADR é publicado como um artefato completo no repositório do estudo, formatado para corresponder à convenção de ADRs do Archgate — frontmatter, seções e (quando aplicável) um arquivo .rules.ts companheiro que implementa verificações determinísticas. Para o schema autoritativo de ADRs e o guia de autoria de regras, consulte cli.archgate.dev.

O Archgate é o projeto que hospeda este estudo. Sua convenção de ADRs é opinativa por um motivo: todo ADR tem um frontmatter parseável (id, domínio, globs de arquivo escopados), seções estruturadas (Contexto com alternativas, Decisão, Do’s and Don’ts, Padrão de implementação, Consequências, Conformidade e Enforcement) e um arquivo .rules.ts companheiro opcional que o motor archgate check pode executar para aplicar as regras automaticamente.

Ao publicar as propostas no formato Archgate, a equipe do Sentry (ou qualquer equipe que rode o Archgate) poderia literalmente soltar esses arquivos em .archgate/adrs/ e começar a aplicá-los imediatamente.

Todos os arquivos de ADR vivem em studies/sentry-pr-review-friction/proposed-adrs/:

ArquivoDomínioTem regras
GEN-001-pr-scope-boundaries.md + .rules.tsgeneralSim
BE-001-api-contract-evolution.md + .rules.tsbackendSim
GEN-002-test-evidence-matrix.md + .rules.tsgeneralSim
FE-001-frontend-component-conventions.md + .rules.tsfrontendSim
BE-002-security-review-protocol.md + .rules.tsbackendSim
GEN-003-bot-finding-promotion.mdgeneralNão (ADR de workflow)

Mais regras de lint customizadas em proposed-lint-rules/:

ArquivoFerramentaAlvos
eslint-frontend-conventions.jsESLintEstilos inline, Stack gap=0, try/finally de estado assíncrono
semgrep-doesnotexist.yamlSemgrepTratamento ausente de Model.DoesNotExist
semgrep-filter-first-unreachable.yamlSemgrep.filter().first() com except DoesNotExist inalcançável
semgrep-high-cardinality-metrics.yamlSemgrepTags de métricas de alta cardinalidade
semgrep-direct-dict-access-api.yamlSemgrepAcesso direto a dict em respostas de API externas

As regras de lint são projetadas para serem instaladas em .archgate/lint/ segundo a convenção de pasta de lint do Archgate. Consulte cli.archgate.dev para detalhes.

Problema: PRs grandes (≥10 arquivos ou ≥400 de churn) atingem o quartil de alto atrito 57,4% das vezes contra 9,8% para PRs minúsculos.

Decisão: limites de tamanho flexíveis (≤5 arquivos, ≤200 de churn) com seção obrigatória de “Scope Rationale” na descrição do PR para PRs acima do limite. Limiar rígido no corte empírico de PR grande.

Regras (GEN-001-pr-scope-boundaries.rules.ts):

  • pr-size-warning — alerta quando o limiar flexível ou rígido é excedido
  • scope-rationale-required — bloqueia o merge se um PR acima do limite não tiver a seção Scope Rationale

Problema: design de API e valores padrão é o principal tema de discussão (38,3% dos PRs de alto atrito). Achados recorrentes de bots incluem UnionType str | None no registro de opções, divergências de Literal do Pydantic e divergências de chave de opção entre escritor/leitor.

Decisão: tipos callable concretos no registro de opções; constantes de chave tipadas em um único registro; defaults None exigem explicação semântica; opções conflitantes rejeitadas em tempo de validação.

Regras (BE-001-api-contract-evolution.rules.ts):

  • no-union-type-in-option-registration — sinaliza padrões type=str | None
  • option-keys-must-use-constants — sinaliza chaves de opção como literais de string em chamadas options.get/set
  • no-none-default-without-nullable-comment — exige comentário explicando a semântica de None

Problema: evidência de testes está empatada como principal tema de discussão (38,3%). Revisores e bots pedem testes específicos (caminhos de erro, casos extremos, valores sentinela) — não apenas “mais testes”.

Decisão: matriz de testes por tipo de mudança com cenários mínimos explícitos para cada tipo de mudança (novo endpoint, componente modificado, tratamento de erro, migração etc.). A descrição do PR deve incluir uma seção Test Plan mapeando a mudança para entradas da matriz.

Regras (GEN-002-test-evidence-matrix.rules.ts):

  • test-plan-section-required — a descrição do PR deve incluir ## Test Plan
  • test-plan-references-must-exist — os nomes de testes listados no plano devem ser encontrados nos arquivos de teste alterados
  • no-bare-except-pass-in-testsexcept: pass solto em arquivos de teste indica asserção ausente

Problema: padrões de componentes aparecem em 35,0% dos PRs de alto atrito. O comentário de revisão mais repetido em todo o conjunto de dados — “can we avoid this inline style w/ prop of some kind?” — apareceu 6 vezes só no PR #111529.

Decisão: sem props style= inline (com comentário de escape hatch); design system primeiro; regras de seleção de componente de layout; try/finally para estado de carregamento assíncrono.

Regras (FE-001-frontend-component-conventions.rules.ts):

  • no-inline-style — sinaliza style= em JSX sem comentário de escape hatch
  • no-stack-with-zero-gap — sinaliza <Stack gap={0}>
  • async-state-try-finally — alerta quando o setter de estado de carregamento reinicia no try mas não no finally

Plugin de ESLint companheiro (eslint-frontend-conventions.js) fornece feedback na IDE em tempo de edição para os mesmos padrões.


Problema: a discussão de segurança aparece em 20% dos PRs de alto atrito, mas com riscos desproporcionais. O escopo github tem a maior mediana de contagem de revisões (5,5) de qualquer escopo devido à superfície de segurança do pipeline de OAuth.

Decisão: PRs que tocam caminhos de auth/integração/API devem incluir uma seção Security Considerations respondendo a cinco perguntas obrigatórias; atribuição de revisor de segurança orientada por CODEOWNERS; sem remoção silenciosa de defense-in-depth; IDs fornecidos pelo usuário validados antes da vinculação de estado do pipeline.

Regras (BE-002-security-review-protocol.rules.ts):

  • security-considerations-section-required — PRs que tocam caminhos sensíveis devem ter a seção
  • no-pipeline-bind-before-validationpipeline.bind_state() deve seguir as verificações de autorização
  • no-unscoped-model-get-in-api — sinaliza Model.objects.get() em endpoints de API sem escopo de organização

Problema: revisores bot (sentry[bot], sentry-warden[bot], cursor[bot]) encontram bugs reais, mas as mesmas categorias de bug se repetem entre os PRs. Veja a página de Atrito de revisão automatizada para o catálogo completo de padrões.

Decisão: rastrear categorias de achados de bots. Quando uma categoria acumula ≥3 ocorrências em 90 dias, comprometer-se a promovê-la para uma verificação determinística (modo strict do mypy, regra de lint de AST, validação de schema/registro ou fixture de teste). Suprimir a categoria do bot uma vez que a verificação entre em produção, liberando o bot para encontrar padrões genuinamente novos.

Regras: este é um ADR de workflow — sem .rules.ts companheiro. O enforcement é procedural via a revisão trimestral de promoção e o rastreador de achados de bots. Os outros cinco ADRs acima (BE-001, BE-002, FE-001) e as regras de lint propostas são, eles próprios, o resultado de aplicar o GEN-003 aos achados de bots neste estudo.

ADRTema(s) alvoCobertura de PRs de alto atritoMecanismo
GEN-001Atrito orientado por tamanho57,4% dos PRs grandesReduzir tamanho do PR + forçar rationale de escopo
BE-001Design de API (38,3%) + gerenciamento de estado (35,0%)~40%Registros tipados + tipos callable concretos
GEN-002Evidência de testes (38,3%) + segurança de tipos (30,0%)~40%Matriz de testes por tipo de mudança no template de PR
FE-001Padrões de componentes (35,0%) + nomenclatura (11,7%)~35%Regras de ESLint eliminando comentários recorrentes de estilo
BE-002Segurança (20,0%)~20%Análise de segurança antecipada + gating por CODEOWNERS
GEN-003Atrito de revisão de bots (68,3%)~68%Promover achados agênticos recorrentes para verificações determinísticas
  1. FE-001 (Convenções de frontend) — menor custo, maior sinal imediato. O plugin de ESLint para estilos inline elimina o comentário de revisão mais repetido do nosso conjunto de dados. Ganho rápido.

  2. GEN-001 (Limites de escopo de PR) — alto impacto, custo moderado. A regra de aviso de tamanho é fácil de implementar e mira diretamente o preditor de atrito mais forte.

  3. GEN-003 + as regras de lint (Promoção de achados de bots) — maior alavancagem de longo prazo. As 4 regras de Semgrep em proposed-lint-rules/ poderiam entrar em produção em dias e imediatamente suprimir as categorias mais comuns de achados de bots.

  4. GEN-002 (Matriz de evidência de testes) — custo médio, alto impacto em clareza. A matriz pode ser publicada como uma mudança de template de PR e imediatamente referenciada pelos revisores.

  5. BE-001 (Evolução de contrato de API) — custo mais alto, alto impacto de longo prazo. Migrar para um registro tipado de chaves de opção é uma refatoração significativa, mas elimina permanentemente uma classe inteira de bugs.

  6. BE-002 (Protocolo de segurança) — especializado, mas crítico. Afeta cerca de 20% dos PRs, mas esses PRs carregam o maior risco de descuido de segurança.

Se você roda um codebase no estilo Sentry (backend em Python + frontend em TypeScript) e quer adotar essas propostas:

Terminal window
# 1. Initialize archgate in your repo (if not already)
cd your-repo
archgate init
# 2. Drop the ADR files into .archgate/adrs/
cp /path/to/study/proposed-adrs/*.md .archgate/adrs/
cp /path/to/study/proposed-adrs/*.rules.ts .archgate/adrs/
# 3. Drop the lint rules into .archgate/lint/
mkdir -p .archgate/lint/semgrep
cp /path/to/study/proposed-lint-rules/eslint-frontend-conventions.js .archgate/lint/eslint.js
cp /path/to/study/proposed-lint-rules/semgrep-*.yaml .archgate/lint/semgrep/
# 4. Adjust the file globs in each ADR's frontmatter to match your repo layout
# 5. Run the checks
archgate check

Cada ADR é independente — você pode adotá-los um de cada vez, na ordem de prioridade acima, sem se comprometer com o pacote completo de antemão. Para a referência completa de comandos, consulte cli.archgate.dev.