# A base de código é o harness

> Original em inglês. Tradução gerada por IA, não pelo autor. [Ler o original em inglês](https://www.ferueda.com/writing/the-codebase-is-the-harness).

> Componentes práticos para um harness em que agentes e pessoas possam confiar.

Antes escrevi sobre [o que quero dizer com engenharia de harnesses](/pt/writing/reflexoes-sobre-engenharia-de-harnesses): o harness do modelo ao redor do LLM e o harness do projeto que você realmente controla. Este é o complemento prático. Então, o que precisa estar na base de código para o agente não perguntar as mesmas coisas toda vez ou, pior, inventar respostas?

Sem harness? As mesmas perguntas em toda sessão. O que ler, o que prova que terminou, como preparar o ambiente, onde ficam os testes, quais comandos são seguros. O agente esquece. A base de código lembra.

Minha visão é simples: **a base de código é o harness.** Não um prompt. Não Cursor ou Codex. É a camada do próprio projeto que transforma intenção, preparação e verificações em algo que o agente consegue conferir.

## O modelo prevê. A base de código faz cumprir.

- **O harness do modelo** é o produto: sessões, ferramentas, permissões, MCP. Você configura. Não é seu.
- **O harness do projeto** é o que vive na base de código: documentação, comandos, testes, scripts, integração com CI e hábitos que transformam erros repetidos em mecanismos de proteção.

O modelo prevê o próximo token plausível. A base de código determina o que conta como concluído. Mesmo prompt, outra execução, outra resposta. As duas podem parecer certas. Por isso você precisa de verificações que o agente consiga executar sem perguntar.

> Prompts são sugestões. Linters são lei.

## O harness mínimo que vale a pena

Você pode ampliar isso com o tempo. Estas são as peças que eu não deixaria de fora.

**Um mapa, não um livro.** O `AGENTS.md` da raiz deve responder: o que é este projeto, quais são as regras inegociáveis, onde está a intenção do produto, onde está a arquitetura, qual verificação executar para cada tipo de mudança e o que fazer quando ela falha. Referências a arquivos reais. Não um despejo de instruções de 50 páginas.

**Intenção do projeto.** Um documento focado que diga o que é o produto, para quem é, o que prioriza, o que explicitamente _não_ prioriza e quais suposições são perigosas. Sem isso, o agente basicamente deduz a direção do produto a partir do código ao redor. Aceitável para a cor de um botão. Inaceitável para decidir a quem pertencem os dados, cobrança, privacidade ou o que se pode quebrar na API.

**Um comando que signifique concluído.** `make verify`, `pnpm verify`, `npm run validate`, o que combinar com seu stack. Documentado no mapa. Amplo o suficiente para detectar regressões entre componentes. A verificação local antes da entrega deve ser pelo menos tão rigorosa quanto o CI no trabalho normal.

**Verificações delimitadas para iterar.** Mexeu só no pacote da API? Execute a verificação da API. Migração de banco? Execute a do banco. A verificação final define a entrega; as delimitadas mantêm o ciclo rápido.

**Verificar e preparar o ambiente local.** Uma verificação somente de leitura que diga o que falta. Uma preparação explícita que crie estado local seguro. Segredos reais nunca são inventados. Valores locais não vazios não são sobrescritos. A preparação deve ser um comando, não uma conversa no Slack.

**Guia de camadas de testes.** Diga ao agente onde a prova deve estar: testes unitários ao lado do código, testes de persistência quando o banco for o foco, smoke tests só quando precisar de transporte real, E2E completo por último. Use por padrão a camada mais barata que comprove a intenção.

**Inventário de scripts.** Scripts fazem parte da API pública, quer você tenha planejado isso ou não. Documente onde ficam, se apenas leem ou modificam, quem é responsável e qual alvo Make/npm os expõe aos agentes. Nome ruim: `setup.sh`. Melhor: `prepare-local-env`, para ninguém destruir produção por acidente.

**O CI chama comandos da base de código.** GitHub Actions, ou o que você usar, deve ser simples: checkout, instalação e execução do alvo de verificação do repositório. Não duplique a lógica de “mexeram na API?” em três arquivos de workflow. Mantenha isso na base de código para sincronizar o ambiente local e o CI.

**Hooks baratos.** Formatar e rodar lint no commit é bom. Hooks são higiene, não a definição de concluído. Não pendure a suíte inteira de testes ou as verificações de banco no pre-commit.

| Peça                                 | Função                                                   |
| ------------------------------------ | -------------------------------------------------------- |
| `AGENTS.md`                          | Encaminhar o agente para os documentos e comandos certos |
| Intenção do projeto                  | Limites do produto antes de escrever código              |
| Verificação final                    | Uma resposta para “terminamos?”                          |
| Verificações delimitadas             | Iteração rápida sem pular a entrega                      |
| Verificação / preparação do ambiente | Preparação autônoma                                      |
| Camadas de testes                    | A prova certa pelo custo certo                           |
| Inventário de scripts                | Sem comandos que alterem coisas de surpresa              |
| CI                                   | A mesma lógica do repositório usada localmente           |

Não despeje tudo isso no agente em toda sessão. Torne fácil de encontrar: um mapa curto no início e documentos focados que ele abra quando a tarefa realmente precisar. O agente deve conseguir encontrar a peça certa sem você colar metade do repositório no chat.

## Caminho de adoção

Comece pequeno. Acrescente o resto conforme a dor aparecer. Você não precisa de tudo no primeiro dia.

**Mapeie a base de código.** Um arquivo curto para agentes na raiz, intenção do projeto, referências de arquitetura e documentos específicos onde algum domínio precise de tratamento especial. Torne a base de código navegável antes de escrever uma enciclopédia.

**Defina concluído.** Uma verificação final. Executável localmente. Documentada. Determinística o suficiente para que as falhas indiquem o que fazer. O CI invoca a mesma lógica ou um equivalente claramente documentado.

**Adicione verificações delimitadas.** Acompanhe como a base de código realmente muda: só frontend, só backend, um pacote, contratos, documentação. Iteração rápida; a verificação final continua responsável pela entrega.

**Torne o CI reproduzível localmente.** Filtros por caminho em um manifesto ou script com testes. Workflows chamam comandos do repositório. Sem seleção de alvos duplicada entre arquivos YAML.

**Torne a preparação explícita.** Verifique o que falta. Prepare o que for seguro. Documente o que a verificação pode redefinir localmente e por quê.

**Documente as camadas de testes e o inventário de scripts.** Assim o agente não escolhe sempre o teste mais lento ou um script de shell aleatório.

**Transforme revisões repetidas em proteções.** Se você ou um revisor dizem a mesma coisa duas vezes, é um sinal: documente, teste, crie uma regra de lint ou um script. Não continue explicando em cada PR.

## Modelos que você pode aproveitar

Estruturas independentes do stack. Troque Make por npm, Vitest por `go test` ou pelo que você usa.

**Mapa da raiz (`AGENTS.md`):**

```markdown
# Project name

Short description. Read `docs/project-intent.md` before product decisions.

## Non-negotiables

- Invariant one
- Invariant two

## Where to read

- Intent: `docs/project-intent.md`
- Architecture: `docs/architecture.md`
- Testing: `docs/testing.md`

## Checks

- Area changed only: `make check-<area>`
- Normal handoff: `make verify`

## When checks fail

Run `make fix` if available, then re-run the scoped gate or `make verify`.
```

**Intenção do projeto (`docs/project-intent.md`):**

```markdown
# Project intent

## What this is

One paragraph. Present tense. Real behavior today.

## What this is not

Explicit non-goals.

## Optimizes for

## Does not optimize for

## Unsafe assumptions

Things the agent must not infer from nearby code.

## Hard invariants

Violations are bugs, not style preferences.
```

**Matriz de comandos (na documentação do harness ou de contribuição):**

| Comando                  | Quando                         | Altera?              |
| ------------------------ | ------------------------------ | -------------------- |
| `make check-local-env`   | Antes do trabalho pesado       | Não                  |
| `make prepare-local-env` | Faltam arquivos locais         | Sim (apenas local)   |
| `make check-api`         | Caminhos da API mudaram        | Não                  |
| `make verify`            | Entrega que muda comportamento | Talvez (documentado) |
| `make fix`               | Após falhas de formato/lint    | Sim                  |

**Verificação final (Makefile ou script do pacote):**

```makefile
.PHONY: verify
verify: check fix-if-needed db-check-if-needed
	@echo "verify: ok"
```

**Linha do inventário de scripts:**

| Caminho                 | Domínio | Público                  | Modo   | Notas                  |
| ----------------------- | ------- | ------------------------ | ------ | ---------------------- |
| `scripts/seed-local.sh` | dev     | `make prepare-local-env` | altera | Apenas local; nunca CI |

**Ambiente local:**

```makefile
check-local-env:
	@test -f .env.local || (echo "run: make prepare-local-env"; exit 1)

prepare-local-env:
	@test -f .env.local || cp .env.example .env.local
```

**Workflow mínimo de CI:**

```yaml
jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - run: make verify
```

O ponto não é a sintaxe. É fazer cada camada apontar para os mesmos contratos.

## Não é só teoria

Não escrevo sobre isso apenas de forma abstrata. Eu construo isso na maioria dos meus projetos e do meu trabalho. Um repositório que mantenho por fora é o [harness](https://github.com/ferueda/harness): uma CLI, workflows invocáveis, skills empacotadas e o executor que conecta tudo. O repositório do seu produto ainda precisa do próprio mapa, das verificações e da preparação. Harness é o que uso para revisar mudanças, encaminhar trabalho de agentes e manter os ciclos explícitos.

Se os modelos acima ajudam a projetar, esse repositório ajuda a ver exemplos funcionando: integração de workflows, estrutura de skills e documentação para colaboradores. Continua evoluindo. Copie o que servir. Mais contexto: [/projects/harness](/pt/projects/harness).

## O que o harness não faz

Não substitui julgamento. As verificações detectam desvios e erros mecânicos. Não escolhem sua estratégia de produto.

Verificações desatualizadas mentem. Se `verify` não corresponde ao que o CI executa, ou o guia de testes diz uma coisa e o código faz outra, o agente aprende a lição errada.

Agentes pulam etapas se você permitir. Verificações delimitadas não executam a suíte inteira. Versões erradas de ferramentas ainda estragam sua tarde. Verificações de banco precisam do Docker rodando. **O harness reduz a adivinhação. Não substitui seu bom senso.**

> Chat não é memória. A base de código é.

Essa é toda a aposta. Coloque intenção, preparação e prova onde o agente, e a próxima pessoa, possam executá-las sem depender de você. Construa o harness junto com o produto. Toda vez que você explica a mesma coisa duas vezes, provavelmente falta uma proteção na base de código.
