# Gates de Qualidade

> **Regra:** o gate decide se o dossiê está pronto. Julgamento humano entra
> **dentro** do documento, nunca **sobre** ele.
>
> Todos os gates são executados por `auditar.py` e `gerar-readme.py`.
> `auditar.py` sai com código **1** se encontrar qualquer problema.

---

## 1. Gates de forma (automáticos, determinísticos)

| # | Gate | Regra | Por que |
|---|---|---|---|
| **G1** | **Estrutura** | Toda pasta de módulo tem os 9 arquivos canônicos | O dossiê precisa ser navegável por um leitor que não conhece o projeto |
| **G2** | **Caminhos citados** | Todo caminho `prefixo/...` citado existe no workspace | Dossiê com caminho errado reconstrói errado |
| **G3** | **Tamanho** | 100 ≤ linhas ≤ 400 por arquivo | Arquivo curto = conteúdo raso; arquivo longo = conteúdo que ninguém lê |
| **G4** | **Placeholder** | Nenhum `TODO`, `FIXME`, `XXX`, `<NOME>` na prosa | Texto por preencher passa em todos os outros gates |
| **G5** | **Corrupção** | Nenhum caractere CJK / fora do esperado | Corrupção de encoding vem de um paste truncado |
| **G6** | **Mapa entre versões** | Toda pasta de módulo tem o comparativo, **em qualquer arquivo da pasta** | É a informação que responde "o que mudou?" |
| **G7** | **Cobertura do registro** | Todo módulo do registro tem dossiê | Módulo sem dono = funcionalidade que ninguém documentou |
| **G8** | **Cobertura de código** | Todo controller/model do inventário tem módulo dono | O inverso do G7: código sem dono |

> **G6 exige a distinção requisito × local** (lição 11). O gate exige
> *existence* da informação, não que ela esteja num arquivo específico.

### Gates condicionais

Nenhum gate é universal — cada um carrega as premissas do caso para o qual
foi escrito (lição 17):

| Gate | Só se aplica quando | Por quê |
|---|---|---|
| G3 (tamanho) | Projeto com estado `completo` ou `em_andamento` | Em projeto `preparado`, o esqueleto de um dossiê ainda não é entrega |
| G6 (mapa entre versões) | Projeto com **2 ou mais** versões | Versão única não tem comparativo |
| G7 (cobertura do registro) | Projeto com estado `completo` | Em preparo, acusaria dossiês que nem foram pedidos |
| G4 (placeholder) | Fora de blocos de código | Marcador dentro de exemplo é ilustração, não buraco (limite conhecido — ver §5) |
| G3, G4, G5 | Fora de arquivos **gerados** | Tamanho de artefato de ferramenta é consequência, não defeito (lição 16) |

### Escopo

O gate varre **apenas o projeto atual**: pastas de módulo e pastas
auxiliares `_xxx` dele. Dossiês de **outros projetos** mapeados no mesmo
diretório ficam fora (lição 15).

---

## 2. Lacunas de cobertura: destino obrigatório, resolução opcional

O gate **G8** cruza o `inventario.json` (F1) com o texto de todos os
dossiês e aponta classes de domínio (controller, model) que **não são
mencionadas em lugar nenhum** do dossiê. É um sinal fraco por nome de
classe, mas é barato e acha órfão de verdade.

A regra do protocolo não é "toda lacuna tem que estar resolvida" — isso
tornaria o gate impossível de passar em qualquer base real. A regra é:

> **Toda lacuna tem DESTINO.** Ela está documentada, ou está formalmente
> declarada fora do escopo. Lacuna sem destino é defeito do dossiê.

Por isso o gate aceita duas formas de destino:

| Destino | Onde se registra | Efeito no gate |
|---|---|---|
| Documentada | O dossiê do módulo de destino menciona a classe | Some da lista |
| Fora de escopo, decidido | `projetos.json` → `cobertura.lacunas` | Contada como "lacuna registrada" |
| **Nenhum** | — | **Reprova** |

O formato em `projetos.json`:

```json
"cobertura": {
  "lacunas": [
    "app/Http/Model/Prefecture/Entity.php"
  ],
  "nota": "Lacunas conhecidas. Cada entrada tem destino decidido na F2."
}
```

> **O destino é decidido na F2**, quando a taxonomia de módulos é fechada.
> Registrar a lacuna é um ato de decisão, não de dispensa: "não documentado
> porque é infraestrutura transversal" é uma decisão legítima; "não
> documentado porque não deu tempo" não é.

### Saída do gate

```
classes de código: 319 (sem dossiê: 0, lacunas registradas: 13)
```

O número "lacunas registradas" é o passivo conhecido do dossiê. Ele deve
**diminuir** a cada ciclo do protocolo e nunca ser omitido do relatório.

---

## 3. Gates de conteúdo (humano, com apoio de máquina)

Estes não são automatizáveis. São o critério de aceite da F3 e da revisão
da F4.

| # | Pergunta | Como avaliar |
|---|---|---|
| **C1** | O `00-RESUMO.md` é autossuficiente? | Ler **só** ele e tentar explicar o módulo a alguém |
| **C2** | Toda afirmação tem âncora? | Toda afirmação de comportamento tem `arquivo:linha` |
| **C3** | O comportamento observável está descrito? | Dá para escrever um teste de aceitação a partir do texto? |
| **C4** | A estrutura de dados está completa? | Colunas, tipos, nullability, relations, views, migrations, seeds |
| **C5** | As armadilhas estão sinalizadas? | SQL concatenado, N+1, rota em controller, sessão, duplicação |
| **C6** | O plano de migração é executável? | Dá para escrever a migration moderna **sem abrir o legado**? |
| **C7** | Os testes são concretos? | Arrange/Act/Assert por caso, não "testar o CRUD" |
| **C8** | As perguntas em aberto são reais? | Afeta decisão de negócio, e a decisão **não** está no código |

---

## 4. Gates de execução (F5)

| # | Gate | Verificação |
|---|---|---|
| **E1** | **Todo crítico é reproduzido** | Registro da requisição/consulta e da saída observada |
| **E2** | **O que não reproduziu foi rebaixado** | A mudança de severidade está escrita, com a razão |
| **E3** | **O ambiente está no estado original** | Contagem antes/depois de cada tabela tocada |
| **E4** | **Não há vestígio de teste** | Sem usuário, perfil, papel ou vínculo artificial |

> **E3/E4 são gates de hygiene, não de documentação.** Se o dossiê está
> pronto mas o banco ficou com um usuário `teste_seguranca@tmp.local`, a
> entrega está incompleta.

---

## 5. Limiares e o que eles significam

| Limiar | Valor | Justificativa |
|---|---|---|
| Linhas por arquivo | 100–400 | Abaixo de 100 o arquivo é esqueleto; acima de 400 perde-se a leitura |
| Extensões de caminho | `php, blade, sql, json, md, env, yml, js` | Cobrem o que é citado neste tipo de projeto; **a ordem importa** (lição 7) |
| Verbos de negação | `não existe`, `inexistente`, `removido`, `ausente`, `foi excluído`, `perdido` | Allowlist do auditor: um caminho citado num contexto de negação **deve** poder não existir |
| Módulos com mapa de versão | 100% | É a informação que responde a pergunta mais comum sobre um módulo |
| Críticos sem prova de execução | 0 | Princípio P3 |
| Lacunas de cobertura sem destino | 0 | Gate G8 |

---

## 6. O que o gate **não** cobre

Transparência sobre os limites do automatismo:

| Não é coberto | Por quê | Quem cobre |
|---|---|---|
| Se o comportamento descrito é **correto** | Exige executar o sistema | F5 / revisão humana |
| Se a severidade é a **certa** | Exige julgamento de impacto | Julgamento humano no documento |
| Se a migração proposta é **boa** | Exige critério de arquitetura | Revisão de arquitetura |
| Se o dossiê é **completo** no todo | Exige ler 66 pastas | Amostragem + o `00-RESUMO.md` |
| Corrupção sem CJK | Só CJK é detectável por regex | Revisão de amostra |
| Código-fonte alterado pelo agente | O gate audita `.md`, não o repo | `git status` por pasta de projeto |

> **O gate é uma rede, não uma prova.** Ele garante que o dossiê está
> *bem formado*; a revisão garante que ele está *bem escrito*. Uma entrega
> só está pronta quando as duas passam.

---

## 7. Como rodar

```bash
# gate completo
python3 dossie_modules/_tools/auditar.py --projeto <id>

# saída esperada
#   pastas de módulo : 66
#   arquivos .md     : 678
#   linhas totais    : 147964
#   caminhos citados : 2036 (inexistentes: 0)
#   OK — nenhum problema encontrado.

# índice (idempotente) e revalidação
python3 dossie_modules/_tools/gerar-readme.py --projeto <id>
python3 dossie_modules/_tools/auditar.py     --projeto <id>
```

O `--projeto` é lido de [`projetos.json`](projetos.json). Sem argumento, a
ferramenta usa o projeto marcado como `padrao`.
