Padrão de documentação
Status: canônico · Escopo: Todo arquivo .md do repositório · Atualizado em: 2026-07-28
Este documento define como todo .md deste repositório deve ser escrito. Não é sugestão: as
regras aqui são verificadas por pnpm docs:lint, que faz parte do gate bloqueante pnpm quality.
Vale para quem escreve à mão e para agentes de IA. Se uma regra aqui atrapalha um caso legítimo, mude a regra e o gate juntos — nunca contorne em silêncio.
1. Idioma: documentação em português, código em inglês
Seção intitulada “1. Idioma: documentação em português, código em inglês”A regra mais importante, e ela é absoluta:
| O que | Idioma |
|---|---|
Prosa de documentação (.md) | Português |
| Código, identificadores, nomes de arquivo, commits, comentários no código | Inglês |
Termos técnicos, nomes de produto, caminhos, comandos, trechos de código dentro de .md | Inglês (permanecem como são) |
Ou seja: um .md explica em português, mas cita runInTenantScope, apps/api-worker/src/,
pnpm boundaries e blocos de código em inglês. O linter ignora blocos de código, código inline,
URLs e caminhos ao avaliar idioma — ele julga só a prosa.
Não traduza termos consagrados. Escreva “endpoint”, “deploy”, “gate”, “webhook”, “commit” — traduzir prejudica a busca e conflita com o código.
2. Linha de metadados
Seção intitulada “2. Linha de metadados”Todo .md fora de docs/archive/ traz uma linha de metadados logo depois do H1:
# Título do documento
**Status:** `canônico` · **Escopo:** A que parte do produto ou do código se aplica · **Atualizado em:** 2026-07-28Significado de cada status:
| Status | Significado | Manutenção |
|---|---|---|
canônico | Guia atual e confiável | Revisar quando o assunto mudar |
corrigir | Conteúdo útil com trechos desatualizados | Corrigir ao tocar no assunto |
estacionado | Capacidade que ainda queremos, fora do foco atual | Nenhuma |
histórico | Superado; valor de arqueologia | Nenhuma — não usar como guia |
gerado | Produzido por script a partir do código | Nunca editar à mão |
Por que não YAML frontmatter. A primeira versão deste padrão exigia um bloco --- no topo de
todo arquivo. O GitHub renderiza esse bloco como uma tabela crua acima do título, então justamente os
documentos mais visíveis abriam com titulo: … status: … escopo: … na cara do leitor. Metadado que
suja a página que ele descreve é o gate servindo a si mesmo em vez de servir quem lê. A linha acima
resolve os dois lados: renderiza como prosa e continua sendo verificável por pnpm docs:lint.
A capa é exceção
Seção intitulada “A capa é exceção”README.md não leva linha de metadados. É a capa do repositório — o status dela é o status do
projeto, e qualquer metadado ali aparece antes do que o leitor veio ver. A capa também escapa das
regras de §3 que pressupõem documento interno: um README bem feito abre com hero centralizado (H1 com
o nome, H3 com a tagline, badges), não com parágrafo corrido. Idioma, tabelas, links e seções vazias
continuam valendo.
3. Estrutura: início, meio e fim
Seção intitulada “3. Estrutura: início, meio e fim”Todo documento segue a mesma forma:
- Início — um
#H1 com o título, seguido de um parágrafo de abertura que responde: o que este documento resolve, e para quem? Sem enrolação, sem “neste documento iremos”. - Meio — seções
##numeradas quando a ordem importa (## 1.,## 2.), ou sem número quando são independentes. Subseções###só dentro de uma##. - Fim — uma seção final de saída: para onde ir depois, referências, ou estado/lacunas conhecidas. Documento não termina no meio de uma tabela.
Regras verificadas pelo linter:
- Exatamente um H1, e ele abre o documento.
- Sem pular nível de heading (
##não pode ser seguido de####). - Toda tabela tem linha de cabeçalho e separador — sem linha de tabela órfã.
- Todo link relativo resolve.
- Documento vivo não linka para
docs/archive/.
4. Escrita: o que é “apresentável”
Seção intitulada “4. Escrita: o que é “apresentável””- Frase curta, voz ativa. “O gate falha quando…” e não “É feita uma verificação na qual…”.
- Tabela para comparar, lista para enumerar, prosa para explicar o porquê. Escolha uma; não repita a mesma informação em dois formatos.
- Afirme o estado real, com data. “Construído mas não entrega — falta
TWILIO_*” vale mais que “parcialmente implementado”. - Registre o porquê, não só o quê. O código já mostra o quê. Documento existe para a decisão.
- Sem “TODO”, sem seção vazia, sem placeholder. Se não tem conteúdo, não tem seção.
- Emoji ajuda a escanear, não a decorar. Use em título de seção (
## 🎯 O problema), como marcador de status em tabela (✅ ⚠️ ❌ 📦 📚) e como ícone de linha. Não use no meio da prosa. - Formate para ser lido. Tabela alinhada, bloco de código com linguagem declarada, diagrama
mermaidquando o fluxo importa mais que o texto,> [!NOTE]e> [!IMPORTANT]para destacar o que não pode passar batido. Documento é interface, não despejo de texto. - Números e nomes precisos. Cite
arquivo:linhaquando aponta para código.
5. Onde cada tipo de documento mora
Seção intitulada “5. Onde cada tipo de documento mora”| Tipo | Onde | Ciclo de vida |
|---|---|---|
| Escopo e direção do produto | DIRECTION.md (raiz) | Vivo, revisado sempre |
| Mapa do código | ARCHITECTURE.md (raiz) | Vivo |
| Porta de entrada do repositório | README.md (raiz) | Vivo |
| Índice das pastas | docs/README.md | Porta — live/ · parked/ · text-pipeline/ · archive/ |
| Guia do dia a dia | docs/live/** | Vivo ou corrigir |
| Decisão arquitetural | docs/live/adr/NNNN-titulo.md | Imutável |
| Pipeline de texto/chat (não voz) | docs/text-pipeline/ | Fora do foco diário; pode citar archive/ |
| Ainda queremos, fora do foco | docs/parked/ | estacionado; pode citar archive/ |
| Superado | docs/archive/ | Sem manutenção, sem metadados obrigatórios |
| Gerado do código | docs/gerado/ | Nunca editar |
6. Registro de decisão (ADR)
Seção intitulada “6. Registro de decisão (ADR)”Decisão arquitetural não vira parágrafo dentro de um documento grande — vira um ADR próprio, pequeno e imutável. Prosa que envelhece foi a causa da bagunça que este padrão corrige: 66 documentos sem dono e sem validade.
Formato de docs/live/adr/NNNN-titulo-curto.md:
# ADR 0001 — Título da decisão
**Status:** `canônico` · **Escopo:** O que a decisão afeta · **Atualizado em:** AAAA-MM-DD
Uma ou duas frases dizendo o que este ADR registra e por que ele existe.
## ContextoO que era verdade quando decidimos, e qual pressão gerou a decisão.
## DecisãoO que foi decidido, em uma ou duas frases afirmativas.
## ConsequênciasO que fica mais fácil, o que fica mais difícil, o que passa a ser proibido.
## Alternativas descartadasCada alternativa e por que perdeu.Um ADR nunca é editado para “atualizar”. Se a decisão mudou, escreva outro ADR e marque o antigo com
status histórico mais a linha Substituído por ADR-NNNN.
Alternativa rejeitada mora no ADR — e só nele
Seção intitulada “Alternativa rejeitada mora no ADR — e só nele”O linter rejeita seções do tipo “Fora do plano”, “Não planejado” ou “Alternativas descartadas” em
qualquer documento que não seja um ADR. O motivo é critério de parada: uma lista de tecnologias que
não usamos é infinita. Se cabe NestJS e Nx, por que não Express, Fastify, Prisma, Kafka, MongoDB?
Sem linha divisória, a lista cresce, se espalha e vira ruído — exatamente o que aconteceu: a mesma
lista estava repetida em quatro documentos vivos, inclusive no README.md.
A regra que limita: registra-se uma alternativa rejeitada uma única vez, dentro do ADR da decisão que ela perdeu, e só se ela foi de fato proposta e custou deliberação. Isso é limitado por definição — o conjunto de coisas realmente consideradas é pequeno — e mantém o valor que importa: impedir que a mesma pergunta seja re-litigada do zero.
Documento vivo descreve o que é. O que não é fica no ADR, com o porquê.
Onde continuar
Seção intitulada “Onde continuar”- Índice com status de todos os documentos:
docs/README.md - Escopo do produto:
DIRECTION.md - Mapa do código:
ARCHITECTURE.md - Verificação:
pnpm docs:lint(dentro depnpm quality)