# Rubrica: Arquitetura (Peso 30%)

Avalia se a implementação segue o padrão arquitetural definido no spec.md e mandate.md.

## Verificações mecânicas obrigatórias (auto-reprovação se falhar)

Estas duas checagens são objetivas — não dependem de julgamento sobre estilo — e cobrem bugs reais que
já derrubaram uma app em produção (ver `backend/integrations/neon-auth/neon-auth.md` → "Known Failure
Modes"). Rode ambas sempre que o diff tocar endpoints minimal API ou fetch de dados cross-camada, mesmo
que o mandate não as mencione explicitamente. Uma violação em qualquer uma delas é bloqueante — não
"ressalva" — independente do resto do score de arquitetura.

1. **DI de todo serviço injetado em endpoint.** Para cada parâmetro de tipo serviço em uma lambda de
   endpoint minimal API (qualquer tipo que não seja `TRequest`, `CancellationToken`, `ClaimsPrincipal`
   ou um primitivo de rota/query), confirme que existe `AddScoped<T>()` / `AddSingleton<T>()` /
   `AddTransient<T>()` correspondente em `Program.cs` (ou registro via assembly-scanning). Um serviço
   não registrado é inferido como `[FromBody]` pelo Minimal API e derruba a app inteira no startup —
   isso é "Score 1-2", não "Score 5-6 com ressalva", porque não é estilo: é a aplicação não subir.
2. **Nenhum prefixo de rota reusado para dois propósitos.** Se o projeto tem chamadas server-direct ao
   backend E chamadas client-side via proxy same-origin, confirme que existem DUAS constantes
   nomeadas distintas (uma por propósito) e que nenhuma delas aparece do lado errado (grep: arquivos de
   Server Component só importam a constante server-direct; hooks/Client Component só importam a
   constante de proxy). Uma única constante reusada para os dois quebra silenciosamente um dos dois
   caminhos em runtime, sem sinal em build — também bloqueante.

## Score 9-10 — Exemplar

- Segue o padrão de feature folder rigorosamente: cada feature tem seus próprios handlers, commands/queries, validators e endpoints.
- Zero dependências diretas entre features — comunicação cross-feature via interface, evento ou shared kernel explícito.
- Domain logic completamente isolado de infraestrutura: nenhum import de ORM, HTTP client ou I/O direto em objetos de domínio.
- Inversão de dependência aplicada onde a arquitetura exige.

## Score 7-8 — Bom

- Segue o padrão com desvios menores e justificados.
- Dependências cross-feature existem mas são poucas, documentadas e via abstração.
- Pequenas impurezas de infraestrutura em domain que não afetam testabilidade.
- Estrutura de pastas correta, responsabilidades bem definidas.

## Score 5-6 — Aceitável com ressalvas

- Estrutura de pastas correta mas responsabilidades começam a se misturar.
- Dependências cross-feature sem justificativa clara.
- Domain logic com acoplamento a infraestrutura que dificulta testes unitários.
- Padrão seguido na maior parte, mas com violações perceptíveis.

## Score 3-4 — Problemático

- Desvios significativos do padrão definido no spec.md.
- Múltiplas violações de separação de responsabilidades.
- Feature não isolada — mudanças nela provavelmente afetam outras.
- Difícil de testar sem mocks de infraestrutura.

## Score 1-2 — Reprovado

- Ignora completamente a arquitetura definida.
- Implementação plana sem estrutura de feature.
- Dependências circulares ou acoplamento total entre camadas.
- Requer refatoração antes de qualquer entrega.
- Qualquer violação das "Verificações mecânicas obrigatórias" acima (DI faltando, prefixo de rota
  reusado) — teto de score 2 independente de quão bem o resto segue o padrão.

## Perguntas de avaliação

1. Os arquivos estão nas pastas corretas da feature conforme o padrão do projeto?
2. Há imports diretos entre features sem passar por abstração?
3. Objetos de domínio importam de infraestrutura (ORM, HTTP, I/O)?
4. Se remover esta feature, alguma outra quebra?
5. O padrão arquitetural descrito no spec.md foi seguido?
6. Todo serviço injetado numa lambda de endpoint minimal API tem `AddScoped`/`AddSingleton`/
   `AddTransient` correspondente em `Program.cs`?
7. Se o diff tem chamada server-direct ao backend E chamada client-side via proxy para o mesmo
   recurso, elas usam duas constantes de prefixo distintas — nenhuma reusada para o outro propósito?

## Tetos de prova de mídia (Gate 3)

Quando — e **somente** quando — a feature gera mídia (alguma task de `tasks.json` cita, em
`standards[]`, um dos três standards de mídia de `ai-agents/`), o avaliador independente também
aplica `.morph/framework/evals/proof-rubrics/media-claims.md` e grava ` media={n}` na linha
`**Proof-Scores:**`.

Ela **não** é uma quinta dimensão do composto — nenhum peso muda por causa dela. Ela entra aqui,
como teto sobre esta dimensão, pelo mesmo mecanismo do teto de prova em Cobertura.

**Por que aqui e não em Cobertura:** as quatro afirmações que ela cobra — custo, revisão humana,
marcação, hot path não bloqueado — são **propriedades estruturais**: onde a chamada mora, que
estados existem, o que é persistido, o que é publicado. Uma feature que gera mídia dentro do turno
de conversa está arquiteturalmente errada, não mal testada. E há uma consequência técnica: o `min`
que limita Cobertura é calculado sobre a lista explícita das quatro provas de evidência, com `media`
**fora** dela — senão um `media=4` derrubaria o teto de teste por um motivo que não tem nada a ver
com teste.

| Proof-Score de media | teto nesta dimensão |
|---|---|
| 9 a 10 | sem teto |
| 7 a 8 | 8 |
| 4 a 6 | 6 |
| 0 a 3 | 3, e o item entra como **bloqueante** listado no relatório |

Sem a chave `media`, não há teto a aplicar. Mas a ausência da seção `## Mídia gerada` num relatório
de feature que gera mídia **pausa o Gate 3** por conta própria (`src/lib/risk-detector.js`), antes
de qualquer discussão de nota. Feature que não gera mídia é isenta automaticamente — a chave não
aparece e o sinal é falso.
