Arquitetura — a planta, em aberto
Este site é o argumento. Esta página é a planta — como ele é construído, e como você construiria o seu.
Comecei o ano perdido
Um projeto que não estava indo bem, um monte de obrigações de catch-up nas ferramentas de IA, e a coisa foi degradando até o fim do ano. O Kiro já estava à mão fazia um tempo, e eu comecei o ano disposto a aprender a usar a ferramenta. E tem um detalhe que eu suspeito que muita gente sênior está vivendo e não diz em voz alta: eu tinha a ferramenta de desenvolvimento agêntico na mão — e mesmo assim me sentia de fora do hype.
Porque o problema não era a ferramenta; era onde eu ia usá-la. Naquele começo de ano, todo trabalho com IA de que eu estava perto se dividia em duas metades: a modelagem, que é forte, e o resto — systems integration, legado que não dá pra trocar, as complicações comuns de TI corporativa. É nessa segunda metade que eu passei dezoito anos, e é ela que não tem use case pronto pra você aprender — o caso tem que aparecer sozinho, no trabalho de verdade.
O caso que virou o jogo não foi este site. No início do ano, em janeiro, comecei a construir por fora um mecanismo de autenticação e autorização com regras de negócio densas, custom em Spring Boot e Spring Security, integrando sistemas legados. Eu jamais teria conseguido desenvolver aquilo sem uma agentic development tool — e não era só o prazo: eu dividia as responsabilidades de tech lead naquele projeto ao mesmo tempo. É essa a parte que a ferramenta comprou. Não velocidade de digitação: as duas coisas caberem na mesma semana. E nada me diverte mais que ver uma aplicação funcionando bonito — numa escala que sozinho eu não alcançava. Foi ali que eu vi uma coisa que não via fazia tempo: se o requisito é onde eu fico e o código é trabalhado por AI-DLC, projeto de software engineering pode ser mais audacioso. Não como previsão — como o que eu enxerguei naquele momento, com aquilo rodando na minha frente.
"Computer programming is an art, because it applies accumulated knowledge to the world, because it requires skill and ingenuity, and especially because it produces objects of beauty."
— Donald Knuth, 1974

As férias foram em maio, em São Francisco e no Vale, e é dali que sai o resto desta página. Não teve lugar por onde eu passei sem alguma oferta de IA — no trem, na rua, na vitrine, no crachá de quem estava do lado. Voltei com a ideia do que fazer, e desde então toco isso em duas frentes: uma interna, no trabalho, com Kiro, e esta, pública, com Claude Code. Dois harness rodando o mesmo tipo de trabalho é o que me deixa separar o que é do modelo do que é do setup em volta dele.
Numa manhã eu peguei o Caltrain para sul — 8h57, próxima parada Palo Alto. O vagão era laptop aberto de ponta a ponta, loop rodando, gente trocando ideia em voz alta a caminho do trabalho. Não era evento, não era comunidade, não era nada combinado. O que eu concluí dali, e não o que eu vi: um monte de gente fazendo o mesmo tipo de trabalho, no mesmo lugar, na mesma hora — perto o suficiente para ouvir sem pedir e para responder sem marcar. Eu estive dentro disso por uma semana, em maio. No resto do ano, não estou.

Fora daquela semana o vagão não existe, e é ele que a frente pública substitui — tem uma razão para ela existir em vez de um caderno. Há opções de configuração demais — qual harness, quais hooks, que persona, que gate, qual modelo — e ninguém tem sessões suficientes para testar todas sozinho. Trocar a experiência de cada um usando IA é o que vai acelerar esse aprendizado, e por isso o que está aqui é o setup inteiro, não só a conclusão a que ele chegou.
O que o requisito exigia, e a arquitetura que ele justificou
O requisito desta frente pública é curto: publicar conteúdo, em dois idiomas, com a construção inteira em aberto. É ele que decide a arquitetura, a conta, e o resto desta página.
E ela não foi construída enxuta. Foi construída inteira e depois cortada: havia uma plataforma com backend — BFF em Lambda, DynamoDB, Cognito, SES —, um Lambda@Edge renderizando imagens OG a cada requisição, um serviço de unfurl de links, GitFlow com staging e produção, e um PWA offline-first. Um banco sem nada para guardar. Auth sem ninguém para autenticar. Um staging para um site cujo revert é um merge. Cada uma era defensável quando foi decidida, e nenhuma sobreviveu à pergunta "para que isso serve, aqui" — e cada reversão está registrada junto com a decisão que a substituiu: 0025, 0026, 0027, 0028, 0029.
O corte não é o assunto desta página; ele é a consequência. O que sobrou são três coisas — um site estático, um plugin de dev-loop e um runtime de agente — e elas não são camadas de um mesmo sistema: cada uma existe sem as outras duas. O site roda sem o plugin. O plugin instala em qualquer repositório. O runtime não é meu. O que fica no meio é a única coisa que nenhuma das três entrega sozinha — e é ali que mora o jeito como eu construo isto, que é o jeito como eu quero ser contratado pra construir: desenvolvimento AI-native com o rigor de SDLC que a maior parte do trabalho com IA dispensa, num loop construído sobre Context & Harness Engineering, com AI-DLC rodando dentro dele.
O que fica na interseção é o trabalho de verdade: decidir o que o harness barra, o que ele aconselha e o que ele só documenta — e depois provar que o inventário disso continua verdadeiro.
O lançamento mostrou o resultado. A vitrine mostra a máquina.
Pilar 1 · a solução
Uma SPA totalmente estática — React + Vite + TypeScript — servida a partir de S3 atrás do CloudFront, com uma pequena CloudFront Function reescrevendo URLs limpas. Sem servidor, sem banco, sem auth. O conteúdo é markdown no próprio repositório, e cada rota publicada é prerenderizada no build, nos dois idiomas — um artigo pode ficar retido antes de ser publicado, e um retido é compilado no bundle sem nunca ser prerenderizado.
(→ ADR-0002 totalmente estático / sem backend · ADR-0013 S3 + CloudFront)
De ponta a ponta, com os bastidores junto — e o que interessa nesse desenho é o que não está nele:
A ausência é deliberada, não uma lacuna. Um desenho desses, para um sistema assim, costuma ter uma coluna de aplicação, um banco e integrações internas entre o frontend e a infra; aqui não há coluna nenhuma ali, e o que o leitor pede vem inteiro de um bucket. O único terceiro em tempo de execução é a analytics, e ela depende de consentimento. E "sem backend" levanta uma pergunta antes das outras — como um crawler enxerga isto —, cuja resposta é que nada precisa ser renderizado para ele enxergar: o que ele pede vem como HTML completo, com as tags OG dentro, direto de um arquivo estático. Sem SSR, sem renderização na borda — a função de reescrita da borda roda a cada requisição de página e mexe na URL, nada mais.
O limite viaja junto com a afirmação, porque é a parte que um leitor consegue derrubar: uma URL que não existe responde 200, não 404 — e o que volta é a landing page, com as tags OG da própria landing, sob um endereço que nunca existiu. O CloudFront mapeia 403 e 404 para /index.html, que é o que deixa uma SPA funcionar em rotas profundas e é uma troca real, não um detalhe. Já mordeu aqui uma vez: um desvio de caminho jogou as imagens de OG por artigo nesse mesmo fallback, e cada uma respondeu 200 text/html a todo scraper que a pediu.
A única lógica que roda entre um leitor e um arquivo é essa função: dez linhas executáveis, com testes unitários próprios e uma verificação pós-deploy de que a função no ar continua sendo a deste repositório. E o bucket não é público em nenhum sentido: só responde a s3:GetObject vindo desta distribuição.
(→ ADR-0004 render no build, sem SSR · ADR-0005 toda URL OG-completa · ADR-0033 analytics dependente de consentimento · iac/frontend.tf a distribuição e as policies)
R$ 34,31 por mês
Esse número mede o que este site acrescentou, não aquilo de que ele depende, e mede aquilo em que ele roda, não aquilo com que eu o construo. Dizer "custo quase zero" é a coisa mais fácil desta página, e a mais fácil de ninguém conferir — então segue a conta, com as linhas de hospedagem lidas do custo diário da conta no fim de julho de 2026 e o registro lido da tabela do registrador. Nenhuma estimada. A fatura da AWS é em dólar, e o câmbio usado aqui é R$ 5,222/USD, o fechamento de 14 de agosto de 2026 — fixo no texto, não buscado a cada build, para que o número publicado só mude quando alguém decidir mudá-lo. É com ele que você desfaz qualquer linha abaixo de volta ao valor da fatura:
- O domínio — R$ 370,76/ano pelo
.io, uma cobrança anual que cai num mês só. R$ 30,91/mês amortizado. Escolhi o.iopor branding, não por custo: é a razão honesta, e a única linha daqui que você pode recusar. - Route 53 — R$ 2,61/mês, fixo. A hosted zone, com ou sem visitante.
- S3 — cerca de R$ 0,78/mês, e são escritas de deploy, não leituras.
- CloudFront — na prática R$ 0,00 com esse volume: o tráfego deste site não chega a arranhar o piso do serviço.
Some as linhas e você chega a R$ 34,30, um centavo abaixo do título. Cada linha é arredondada por conta própria, e o total lá em cima é a conversão dos USD 6,57 — que não são uma fatura só: USD 0,65 saem do custo diário da AWS e USD 5,92 são o .io amortizado, da tabela do registrador. Os dois nascem em dólar, e o real desta seção inteira é derivado deles.
Fora da AWS o critério é o mesmo. GitHub Team e Claude Max são pagos e ficam fora do total — a assinatura do GitHub Team é anterior ao site, embora a carga de CI em cima dela seja inteiramente dele; GitHub Actions e SonarCloud são zero porque os repositórios são públicos — propriedade dos repositórios, não do plano — e Terraform Cloud é zero porque a infraestrutura é pequena. E o iCloud+ é a linha que mostra o critério sendo aplicado em vez de anunciado: ele é anterior ao site, mas carrega o e-mail com domínio próprio no apex e o iac/email.tf provisiona os registros MX, DKIM e SPF dele — então não é adjacente a esta infraestrutura, está dentro dela. (→ ADR-0016)
Fora do total ficam também todas as minhas horas: R$ 34,31 por mês é o que custa manter isto no ar, não o que custou construir. Em pessoas, custou uma — fins de semana, em paralelo com consultoria. E a mesma leitura mostrou cerca de R$ 66,84 por mês que o site não estava usando: web ACLs de WAF e IPv4 públicos ociosos, esquecidos quando o backend foi aposentado. Descobri lendo a fatura, o que é tarde — infraestrutura que você para de usar não para de cobrar —, e quem vigia agora é um orçamento em iac/budget.tf deliberadamente não escopado às tags deste projeto: se fosse, só enxergaria gasto que este repo criou, e este era justamente do tipo que ele não criou.
Pilar 2 · a customização
A parte interessante não é a stack — é como ela é construída: agent-led verification, human-residual. O agente prova o "pronto" com gates mecânicos e evidência real (lint, tipos, testes ≥85%, build verde, SonarCloud, E2E funcional, um revisor de contexto fresco); o humano fica com as decisões irreversíveis e arquiteturais. Esse loop vive num plugin à parte — tadeumendonca-skills —, então é uma metodologia que você pode adotar, não algo sob medida só pra este site.
Eu apareço nas duas pontas, e são trabalhos diferentes: no começo abrindo a Issue, e no fim, só no que é classe de fronteira, decidindo se aquilo sobe. Entre uma ponta e outra não há humano nenhum no caminho. E o desenho afirma uma coisa mais estrita do que "no plano": eu sou a única origem de demanda — nada entra na fila por conta própria —, e quem fecha a admissão é o rótulo ready, que é o artefato que diz que a descrição foi fechada; do ready para baixo, só a classe segura atravessa sozinha. Nenhuma raia passa por fora do gate, nem a que constrói o próprio loop. Uma mudança na maquinaria é escrita pelo agents-lead e chega na mesma caixa, e ali ela responde por mais, e não por menos: a mesma Definition of Done, a mesma pergunta sobre produção, e em cima das duas uma exigência que nenhuma outra raia tem — que o agents-lead tenha deixado o marcador de veredito dele antes de o gate poder fazer merge. É um revisor a mais que precisa ter passado, não uma revisão que deixa de acontecer. E o custo disso, já que o resto desta página assume os seus: quem decide que uma mudança é segura é o mesmo tipo de coisa que escreveu a mudança. Classifique uma errado e ela pega o caminho vazio. O que torna isso aceitável aqui é raio de impacto, não confiança — é um site estático, e reverter é um merge.
(→ ADR-0003 trunk-based, ambiente único · ADR-0018 os gates de CI)
Do que o harness é feito
Dos componentes do próprio plugin, exatamente um tipo consegue te barrar, e essa é a versão honesta do convite a adotar: três dos catorze registros no hooks.json devolvem uma negativa antes do ato, e o ato não acontece. E eles fazem isso em dois formatos diferentes, que é a parte que vale ter: o permission-guard no Bash e o mcp-guard nas ferramentas MCP estão no PreToolUse e recusam uma chamada de ferramenta; o preflight está no UserPromptSubmit e recusa o prompt, antes do turno começar. os três hooks de — riscado: daquelas quatro afirmações, sobrou uma. Dois desses guards foram apagados no plugin e o PreToolUse — o permission-guard e o wip-guard no Bash, e o orchestrator-write-guard nas ferramentas que escrevem arquivomcp-guard nunca tinha aparecido nesta página. E nada aqui pegou isso — que é a perna atrasada descrita dois parágrafos abaixo, chegando como instância e não como ressalva: o desenho concordava com o manifesto, então aquela checagem ficou verde com os dois lados desatualizados juntos, e um apagamento de lá não dispara nada deste lado. E o preflight está desenhado em duas colunas da grade acima, porque está registrado duas vezes com uma classe diferente em cada evento — que é a única coisa aqui que ninguém escrevendo à mão teria desenhado.
Os outros onze registros só reportam, e não pelo mesmo motivo — e essa distinção esta página te deve, não dá pra arredondar. Cinco deles estão em eventos que não recusam nada, o SessionStart e o SubagentStart, então esses cinco não conseguiriam barrar nem se quisessem; e repare que o motivo é o evento, e não a ausência de uma chamada de ferramenta, porque o UserPromptSubmit também não tem chamada nenhuma na frente e recusa assim mesmo. Os outros seis conseguiriam. O Stop consegue barrar o fim do turno e o SubagentStop consegue barrar a parada de um subagente, e todos esses scripts escolhem não barrar: toda saída deles é de sucesso. O zombie-loop-detect percebe, um turno atrasado e uma vez por sessão pra aquele head, que tem branch parado em cima de um veredito do gate que ninguém tratou; o dispatch-metrics-stop registra os números do acionamento e sai da frente; o orchestrator-tool-census nomeia o que o orquestrador fez com as próprias mãos, as chamadas que escrevem e postam separadas das que só leem, e não decide nada sobre isso. Seis hooks escolhendo não ser mecanismo dizem mais sobre este harness do que um dizia. E as personas aconselham — o julgamento delas não é verificado por nada, e o guia deste repositório diz com todas as letras que uma lente que ninguém aciona falha em silêncio. Essa é a garantia que o loop dá — e ela vale exatamente o que valer o inventário do desenho acima.
E o inventário desse desenho é conferível — é essa a segunda garantia, e ela é de outra natureza. Renomeie uma persona no plugin e o build deste repositório fica vermelho. O diagrama acima é escrito à mão: um teste compara o desenho, nó a nó e contagem a contagem, com um manifesto versionado, nas duas edições; e um job de CI compara esse manifesto com a árvore viva do plugin. A diferença entre desenhar um harness e provar que o desenho ainda é ele é exatamente essa, e ela é mecânica. E ela tem duas pernas, com limites diferentes, ditos aqui e não depois. Do desenho para o manifesto, a comparação inclui a classe de força de cada uma das doze células, nas duas edições: dar denies a uma persona no manifesto deixa isto vermelho, e é essa a afirmação central da grade. Do manifesto para a árvore viva do plugin, a checagem chega tarde, porque nada deste lado enxerga um merge de lá, e a classe de cada componente sai de uma regra sobre o formato dele — em que evento um hook está registrado —, não de uma leitura do que o script faz: relendo o manifesto, o que se confere é que a classe é um valor legal, não que ela é verdadeira daquele componente.
E é por isso que eu chamo isto de uma coisa, e não de outra. AI-DLC não é meu — é o nome que a AWS deu a um ciclo de entrega cujas etapas são executadas e verificadas por agentes; eu adoto, não inventei, e ele roda dentro disto, não ao lado. Context & Harness Engineering é a afirmação que eu faço, e as duas palavras são duas coisas diferentes de construir. O contexto é o que um agente lê antes de agir: as skills, os registros, os briefs que dizem a ele o que já foi decidido, para que ele não decida de novo e diferente. O harness é o que fica entre ele e o ato: os hooks, os gates, as personas que leem o que ele produziu — e a grade acima é o inventário de quais deles conseguem de fato barrá-lo. Nenhuma das metades é a disciplina sozinha — contexto sem nada que o sustente é conselho, e harness sem nada para ler é um muro — e construir, versionar e provar as duas é o trabalho. Adotar uma metodologia não custa nada dizer — e é justamente por isso que dizer não vale nada. Essa aqui é paga, e o pagamento está no parágrafo acima: um build que quebra quando o inventário deixa de ser verdade. É a mesma régua de agent-led verification que o resto desta página aplica ao código, virada para a metodologia: quem afirma é quem produz a evidência.
(→ ADR-0043 o inventário ancorado no plugin)
Oito personas, contra quem cada uma argumenta — e o que cada uma carrega ao ser acionada. A última coluna é o preload de cada brief: as skills que entram na sessão da persona antes de ela ler a primeira linha da tarefa.
| quem | o que é dele | contra quem argumenta | que skills carrega ao ser acionada |
|---|---|---|---|
product-lead | o leitor, valor, ordem, tamanho da fatia — e posicionamento, voz, e a verdade de qualquer coisa publicada fora da via de content | o tech-lead; e num diff de product ou loop barra um merge diante de uma afirmação publicada que não é verdade — por convenção, não por hook. Em content esse veto acabou em 2026-09-03: lá ele fica com a intake e nada mais, e nenhuma persona tem bloqueio de copy nessa via | agents-configuration · engineering-standards · definition-of-ready · shell |
tech-lead | arquitetura, medição, sequenciamento — e é ele que escreve os registros de decisão de produto e de sistema; os do próprio loop não são dele, são do agents-lead | o product-lead, de propósito: produto-e-mercado e sistema são otimizações genuinamente diferentes | agents-configuration · engineering-standards · definition-of-ready · documentation-standard · devops · shell |
developer | a fatia inteira — aplicação, infraestrutura, pipeline, e os testes escritos junto | ninguém. Ele constrói, e é pra ele que o gate está apontado | agents-configuration · engineering-standards · code-review · quality-gates · devops · shell |
quality-assurance | a entrega contra a Definition of Done, e, à parte, se a mudança pode quebrar a produção | o developer, nos dois eixos numa passada só — e é o único que o hook de permissão deixa fazer merge | agents-configuration · engineering-standards · definition-of-done · quality-gates · devops · shell |
content-writer | redige artigos, texto do site e a linguagem dos posts de rede social na voz do dono — molda, corta, estrutura e traduz uma experiência que ele já tem, nunca origina uma | o content-reviewer, e é só isso: ele lê o rascunho contra a mesma régua com que ele foi escrito, e desde 2026-09-03 o product-lead não roda a lente de copy nesta trilha — o papel dele em content é a admissão do item, e nada além | agents-configuration · engineering-standards · shell · published-voice · content-publishing |
content-reviewer | levantar a régua de um rascunho antes de ele chegar a mim — no máximo duas rodadas contra o published-voice, e ele não barra nada — conserta o rascunho ali mesmo, por dois motivos e só dois: quando consegue citar uma cláusula dessa skill, ou quando a afirmação é falsa contra a fonte | o content-writer, e este é o primeiro par de verdade do elenco: tudo que não cai em nenhum dos dois motivos volta rotulado como opinião descartável, e o texto fica como está | agents-configuration · engineering-standards · shell · published-voice · content-publishing |
agents-lead | a maquinaria em si: hooks, permissões, instruções das personas, skills e comandos, o plugin — e é ele que escreve os registros de decisão sobre o loop, a outra metade da divisão acima | eu — e esse é o caso interessante: o contraponto dele não é outra persona, é a única cadeira deste loop que não tinha com quem discutir | agents-configuration · engineering-standards · documentation-standard · definition-of-ready · devops · shell |
scrum-master | que os ritos aconteçam, na ordem, e que nada seja pulado — ele ordena a fila elegível e nomeia, num registro, qual profile age em seguida | ninguém, e ele não tem ferramenta nenhuma: não aciona, não edita, não roda comando e não põe label, então o que ele produz é um registro que a sessão principal executa — e que nada lê | agents-configuration · engineering-standards |
Duas coisas dessa última coluna valem ser ditas. agents-configuration e engineering-standards estão nas oito — é o preload universal: entender o próprio loop, e os padrões de engenharia contra os quais ele roda, não é assunto de especialidade nenhuma. A shell — a disciplina de arquivo e comando — está em sete das oito, e a que fica de fora é a scrum-master, que não tem nem Write nem Bash, então a regra não teria o que governar ali. E só 11 das 15 skills da biblioteca são pré-carregadas por alguém: as quatro que ninguém carrega — backend, cloud-infrastructure, frontend e planning-poker — só chegam numa sessão se o modelo as encontrar sozinho, pela descrição delas.
E esta tabela é escrita à mão — a coluna nova inclusive. Os nomes de persona do desenho lá em cima são comparados com o manifesto e com a árvore viva do plugin, então aposentar uma persona deixa um build daqui vermelho. Aqui, nada compara coisa nenhuma: o check-harness-drift confere nomes e contagem de personas, e não confere quais skills cada uma carrega. Basta alguém mudar o bloco skills: de um brief para esta coluna passar a mentir no dia seguinte, sem nenhum sinal. E um papel mudando de mãos também não deixa nada vermelho: o que essa checagem compara de uma persona é o nome dela, e quantas personas existem — nunca o que uma linha afirma que ela faz. A autoria dos registros de decisão se dividiu entre duas destas linhas e build nenhum percebeu; aquelas duas células foram corrigidas à mão, como todo o resto desta tabela.
Uma linha corre por baixo de tudo isso, e ela é sobre consentimento, não sobre ferramenta. Tudo o que está no desenho acima é versionado — hooks, personas, skills, comandos — e isso é deliberado: é o que faz o trabalho ser reproduzível, de modo que um fork herde o piso em si, e não uma descrição dele. O que não é versionado, e não vai ser, é a configuração que faz o operador ser alcançável. Toda sessão que eu rodo tem Remote Control ligado desde o primeiro segundo — remoteControlAtStartup, que abre uma ponte para eu acompanhar a sessão local viva e aprovar as chamadas de ferramenta dela do meu celular. Não é o sandbox na nuvem que o Claude Code também oferece, e os dois não se substituem: dentro de uma sessão na nuvem o Remote Control se declara indisponível, porque ali não existe a sessão local que ele existe para alcançar. Essa chave mora em ~/.claude/settings.json, na minha máquina, no único arquivo que este repositório não consegue publicar.
Essa assimetria parece um buraco no harness, e a ferramenta já tinha resolvido a discussão — eu é que nunca tinha lido. Então eu li: não o nome da chave, que não é especificação, mas o binário publicado. Configuração com escopo de repositório não consegue ligar o Remote Control. Comite "remoteControlAtStartup": true no .claude/settings.json de um projeto e a CLI ignora e diz por quê — "repo-scoped settings cannot enable Remote Control; set it at user scope". A única coisa que um repositório consegue fazer com essa chave é colocá-la em false, e essa direção é respeitada na hora, à frente do que prefira a pessoa que está rodando a sessão. Ligar é decisão de uma pessoa; desligar é decisão de um projeto; e só a segunda viaja através de um clone.
O que é a mão certa para um repositório cuja premissa inteira é ser forkado. Comitar o true teria entregado uma capacidade de sessão a todo mundo que clonasse isto e à CI, sem que nenhum deles escolhesse — e, pelo parágrafo acima, nem sequer teria funcionado: uma linha que não faz nada parecendo que faz é exatamente o defeito que esta página não para de nomear. Então o passo de configuração está no README, com os dois métodos e o que cada um custa. Esta página guarda a linha, não as instruções.
Pilar 3 · o runtime
O orquestrador é a parte do harness que você não consegue instalar. Ele não está em nada do inventário acima — nem na grade de componentes, nem no manifesto, embora o fluxo dos tiers o desenhe bem no meio do trecho AFK — e é a sessão principal: o contexto que lê uma Issue, decide qual persona acionar e pesa o que volta. O ator não é componente do plugin, a política dele em parte é, e o que você põe é o contexto que roda aquilo. É também a parte contra a qual as fronteiras acima foram desenhadas: a coluna do meio não consegue afirmar nada além de que uma persona aconselha, e o motivo de não conseguir é que nada obriga um acionamento — o que nomeia o modo de falha sem nomear quem aciona. Quem aciona é ele, e uma lente que ele esquece é uma lente que ninguém rodou.
E o contexto dele acaba. É isso que um subagente compra: ele lê, roda, erra e refaz dentro da sessão dele, e o que chega ao orquestrador é a conclusão. Uma tarefa custa ao orquestrador o veredito, não a execução, e por isso a única alavanca real deste harness é o tamanho do veredito, girada escrevendo as instruções de cada persona. Medi uma vez, na sessão deste repositório, em 7–8 de agosto de 2026, lendo as transcrições: o que ficou dentro dos subagentes foi mais de uma ordem de grandeza maior do que o que voltou. E a economia tem teto — mesmo assim, os vereditos que voltaram foram uma fatia grande de tudo que o orquestrador consumiu vindo de uma ferramenta. Não é fuga: aquela sessão compactou duas vezes de qualquer jeito. O número não é publicado porque a fonte é uma transcrição de sessão privada, que gate nenhum alcança.
E o chão embaixo dele se mexe. Esta é a parte que o resto desta página não tem: o site eu controlo, o plugin eu controlo, o runtime não. Quem o produz publica mudança o tempo todo, e cada modelo novo muda qual configuração ainda faz sentido — não porque a configuração tenha ficado errada, mas porque ela estava compensando uma fraqueza que sumiu.
Não é dedução minha. Quando o Opus 5 saiu, o time do Claude Code apagou mais de 80% do próprio system prompt — o do produto deles, não a configuração pessoal de alguém — e o modelo ficou melhor sem o andaime. E não como evento único: a cada upgrade grande de modelo é menos andaime necessário, então se apaga regra e se recoloca só onde o modelo ainda erra. Isso é um ciclo, não uma faxina.
A tese que vem junto é a que me interessa, e ela é dura: modelos de fronteira estão sendo limitados por produtos construídos para os modelos fracos de ontem, e a vantagem fica com quem põe esforço de engenharia em verificação, e não em instrução. É a pessoa que construiu a ferramenta dizendo isso — e o nome que eu dou a esse movimento, agent-led verification, é meu, não dele. Não estou citando isso de enfeite: é corroboração independente de uma escolha que eu já tinha feito, vinda de quem tem o dado que eu não tenho.
E é por isso que este loop é feito de hooks e de gates, e não de um prompt gigante explicando ao agente como se comportar. Instrução envelhece a cada modelo novo, e envelhece calada. Um gate, não: ele confere o resultado, e o resultado é a mesma coisa antes e depois do upgrade. Se o argumento acima estiver certo, a parte do meu harness que vai sobreviver é a que verifica — e a que manda é a que eu vou apagar.
Boris Cherny, que construiu o Claude Code, no canal do Y Combinator:
O registro de decisões É a documentação
O argumento clássico para ADRs é o humano do futuro: registre por que a decisão foi tomada, para que daqui a dois anos alguém não a desfaça sem saber o que estava em jogo. Aqui o argumento é outro, e é ele que decide o formato.
Num repositório onde quem desenvolve são agentes, o registro é contexto de inferência. O agente não tem memória do que foi discutido — ele tem o repositório, e é dali que infere o que fazer. Se a arquitetura que se formou ao longo do tempo não estiver ancorada em algum lugar do próprio código, cada mudança nova é decidida sem ela, e o resultado não é uma decisão errada isolada: é uma decisão nova que contradiz uma decisão que ninguém lembra de ter tomado. Por isso uma decisão revertida continua aqui e diz que foi revertida. Sem essa marca, o registro de uma arquitetura aposentada lê como instrução — que é a forma mais barata que existe de fazer um agente reconstruir aquilo que foi cortado de propósito. Com uma exceção, e é a única que existe: havia duas web ACLs de WAF e só a regional tem ADR — a da borda do CloudFront foi construída, foi cortada, e o registro dela é esta frase e não um arquivo.
É esse propósito que escolhe o formato, e não o contrário. MADR: contexto, as opções que estavam na mesa, a decidida, e a consequência. Um documento curto por decisão, um arquivo por decisão, tudo no mesmo repositório que o agente já lê — nada de wiki, nada de ferramenta à parte. O que um formato assim entrega para um leitor humano é rastreabilidade; o que ele entrega para um agente é o que ele precisa para não contradizer.
São 49 decisões — e o que é mecânico aqui é o índice, não este número. O índice é gerado a partir de docs/adr/, commitado como artefato e conferido no CI: acrescentar ou substituir uma decisão sem regenerar o índice deixa o pipeline vermelho, então o artefato e o diretório não têm como se separar. O 49 desta frase é digitado à mão: enquanto a tabela era renderizada aqui, ele vinha conferido de graça; cortá-la tirou essa amarração, e o que sustenta o número agora é o link abaixo, a um clique de você contar. As linhas não estão impressas aqui de propósito — esta página aponta o detalhe canônico em vez de repeti-lo, e uma cópia de 49 linhas seria a própria regra sendo quebrada na única seção que existe para defendê-la.
(→ a biblioteca de decisões · ADR-0001 enxuto por design)
Replique para o seu contexto
Está tudo público — dois repos, sem segredos.
tedeuxx/tadeumendonca-ioTypeScriptEste site e o Terraform que o serve — uma SPA estática em S3 + CloudFront, prerenderizada nos dois idiomas, com a biblioteca de decisões que registra as decisões que sustentam peso e o que cada uma custou.→ Ver no GitHub tedeuxx/tadeumendonca-skillsShellO plugin reutilizável do dev-loop: a camada de princípios, as personas dos agentes, os guardas de permissão. A metade que dá pra adotar sem nenhuma conta em nuvem.→ Ver no GitHubOs passos de "do fork até no ar" estão nos READMEs, não nesta página: o deste repo traz o caminho de nuvem inteiro, do domínio até o primeiro merge, e o do plugin traz a metade do loop, que se instala sem nenhuma conta em nuvem. E a régua que um projeto precisa passar pra entrar no portfólio daqui também é pública, em docs/catalog-ready.md — o gate de prova de engenharia.
Uma coisa eu recomendaria copiar sem pensar duas vezes. O deploy entra na AWS por OIDC, então não há segredo guardado: uma chave vazada é acesso até alguém revogar, e um token vazado é acesso até expirar — e só se quem o pegou também satisfizer a condição do trust, que aqui é o subject imutável daquele repositório, por ID numérico e não por nome, porque nome pode ser transferido pra outra pessoa e os IDs não. A troca é que a raiz dessa confiança precisa nascer fora: o Terraform daqui não cria o provedor OIDC, nem a role que roda o próprio Terraform. É um buraco documentado num piso, e nenhum plan vai te avisar que ela saiu do lugar.
(→ ADR-0042 raiz de confiança fora do Terraform · ADR-0015 subject imutável)
O que eu ficaria nervoso de ver alguém copiar sem o resto é o merge direto pra produção. Trunk-based com ambiente único é rápido e implacável na mesma medida; sem os gates na frente, sobra só a segunda metade.
Isto está em aberto porque há mais escolhas de configuração do que sessões que uma pessoa sozinha consegue rodar. Se você rodou alguma dessas escolhas de outro jeito, é você que tem a metade que falta nesta página: me conte o contra-exemplo, ou compartilhe dizendo o que faria diferente.