Metodologia e estado das ferramentas
Resumo
Como cada dado foi coletado até agora, o que funciona por automação em setembro de 2026 e o que está bloqueado. Atualizar sempre que algo mudar. A seção 11 traz as sete portas que a task 4 abriu por curl e a lição de que capacidade não é demanda.
1. O que já foi feito (rodada 0, 04/09/2026)
Dois workflows de agentes em paralelo, no Claude Code, com verificação adversarial:
-
Workflow 1, pesquisa de mercado: 6 frentes (marketplaces, custo de entrada, nichos, loja própria contra marketplace, legal e tributário, rentabilidade), cada uma com um verificador independente instruído a refutar os 4 ou 5 números mais decisivos, mais um crítico de completude. 13 agentes, 1,23 milhão de tokens de subagente, 650 chamadas de ferramenta, 38 minutos. Resultado bruto em
data/brutos/2026-09-04-workflow-01-pesquisa-mercado-6-frentes.json. Placar da verificação: 17 confirmados, 24 imprecisos, 10 errados, 8 não verificáveis (detalhe em_meta/verificacao.md). -
Workflow 2, reconhecimento de fontes: 6 varreduras (YouTube, fóruns e comunidades, empresas, nichos, mídia e dados de mercado, dados comparativos de máquina e filamento) mais um crítico que buscou o que faltava e conferiu URLs suspeitas. 7 agentes, 1,17 milhão de tokens, 646 chamadas, 49 minutos. 592 fontes mapeadas, a maioria aberta e lida. Bruto em
data/brutos/2026-09-04-workflow-02-recon-fontes-7-frentes.json. -
Workflow 3, rascunhos da rodada 0: 7 agentes redatores, um por frente do workflow 1 (mais o crítico de completude), cada um lendo o bloco de dados verificado e escrevendo de 1 a 5 documentos com as correções aplicadas, seguidos de um revisor de forma. 8 agentes, 1,62 milhão de tokens, 329 chamadas, 24 minutos. 16 documentos, 72 fontes novas no catálogo. Bruto em
data/brutos/2026-09-04-workflow-03-rascunhos-rodada-0.json. Ressalva registrada pelos redatores: nenhuma página oficial de taxa de marketplace abriu por curl (Shopee é casca em JavaScript, Mercado Livre devolve 403), então toda tabela de taxa é de fonte secundária e está rotulada assim.
O scripts/carregar-dados-iniciais.py transformou esses dois brutos nos YAML do dossiê. Os números de canal, comunidade e tópico foram lidos das páginas em 04/09/2026; os de empresa vieram de listagens e precisam de confirmação (task 3).
Aviso importante sobre o workflow 2: a cota de WebSearch da sessão (200 chamadas) já estava esgotada quando ele começou. Tudo foi feito por curl, WebFetch e navegador via MCP. Isso explica por que o método abaixo é tão detalhado: foi descoberto na marra.
2. Buscadores: quase tudo bloqueado por automação
Testados e falharam por curl em 04/09/2026: Google (só JavaScript, e /sorry quando detecta bot), DuckDuckGo html e lite (CAPTCHA), Mojeek (CAPTCHA), Startpage (vazio), Brave (429), Ecosia (403), Yandex (redirect), instâncias públicas de SearXNG (429 ou desafio de prova de trabalho). O Bing responde 200 mas devolve resultado envenenado e desconexo, inclusive no modo format=rss. Não confiar em Bing por curl.
O que funciona:
- Navegador real via MCP (
chrome-devtoolsouclaude-in-chrome). DuckDuckGo emhttps://duckduckgo.com/?q=...&kl=br-pt&ia=webrenderiza normal. Seletor:article[data-testid="result"], título e href ema[data-testid="result-title-a"], resumo em[data-result="snippet"]. O DDG devolve zero para consulta com aspas combinada com OR. Frase natural em português, sem operador. Nome próprio rende muito mais que termo genérico. - Google News RSS:
https://news.google.com/rss/search?q=CONSULTA&hl=pt-BR&gl=BR&ceid=BR:pt-419, XML limpo por curl, até 100 itens com título, veículo e data. O<link>é redirecionador que não resolve comcurl -L. Para chegar no artigo, reconstruir a URL pelo veículo e título, ou implementar o resolvedor via POST emhttps://news.google.com/_/DotsSplashUi/data/batchexecute(f.reqno formato[[["Fbv4je","[\"garturlreq\",...]",null,"generic"]]], comdata-n-a-id,data-n-a-tsedata-n-a-sgextraídos do HTML). - REST API do WordPress:
/wp-json/wp/v2/posts?search=TERMO&per_page=100em blog setorial e de fabricante. - WebSearch, quando disponível: contar as chamadas. Cota típica de 200 por sessão. Usar só para o que curl não resolve.
3. YouTube sem chave de API (testado, funciona)
- Descobrir canais:
https://www.youtube.com/results?search_query=TERMO&sp=EgIQAg%253D%253D(filtra só canais). Extrairvar ytInitialData = {...};</script>,json.loads, andar recursivamente atrás dechannelRenderer. Pegadinha: no layout atualsubscriberCountTextcontém o handle evideoCountTextcontém os inscritos. - Ficha do canal:
https://www.youtube.com/@HANDLE/about, chaveaboutChannelViewModel: descrição, inscritos, vídeos, visualizações totais exatas, data de criação,country, e links externos emchannelExternalLinkViewModel(é aqui que aparece quem vende curso, tem loja ou comunidade paga). - Vídeos do canal:
https://www.youtube.com/@HANDLE/videos, rendererlockupViewModel(não maisvideoRenderer), título emmetadata.lockupMetadataViewModel.title, views e data emmetadataParts. Cerca de 30 por carga. - Vídeos por visualização:
https://www.youtube.com/results?search_query=TERMO&sp=CAMSAhAB, renderervideoRenderercomownerText,viewCountTextepublishedTimeText. - Mandar
Accept-Language: en-USpara canal estrangeiro, senão o YouTube autotraduz o título. - Ficha de um vídeo (data exata, contagem exata, duração e tipo de legenda):
https://www.youtube.com/watch?v=ID, blocoytInitialPlayerResponse, chavesvideoDetailsemicroformat.playerMicroformatRenderer. É a única forma de ter data exata: a aba/videossó dá o relativo (“há 2 meses”), que rende aproximação de até um mês, e contagem arredondada (“37 mil”). - Limite descoberto em 04/09/2026: a página
/watchcai em CAPTCHA (recaptcha enterprise, resposta de 3.347 bytes) depois de cerca de 100 requisições feitas por três processos em paralelo, e o bloqueio dura mais de meia hora. As páginas/aboute/videoscontinuaram abrindo normalmente no mesmo período, ou seja, o limite é por endpoint. Rodar/watchem um processo só, com pausa de 2 a 3 segundos. - Receita que passa (medida no mesmo dia, depois do bloqueio acima): um processo só, 4 segundos de pausa, sem cookie e sem navegador. Assim saíram 283 páginas
/watchseguidas com zero falha, mais 75 que tinham falhado antes. O que derruba é o paralelismo, não o volume: três processos a 1,5 segundo bloqueiam, um processo a 4 segundos não. Quem apanhar do 429 não precisa migrar para navegador, precisa serializar e esperar. - Paginação da busca: a primeira carga de
/resultstraz só cerca de 20 itens. O resto vem por POST emhttps://www.youtube.com/youtubei/v1/search?key=<INNERTUBE_API_KEY>com corpo{"context":{"client":{"clientName":"WEB","clientVersion":<INNERTUBE_CLIENT_VERSION>,"hl":"pt","gl":"BR"}},"continuation":<token>}. A chave, a versão e o token (emcontinuationItemRenderer.continuationEndpoint.continuationCommand.token) estão todos no HTML da primeira página. Duas continuações levam a 40 resultados, que é onde a maioria dos termos satura. - O
videoDetails.titledo/watché o título original, mesmo comAccept-Language: pt-BR. A tela de busca autotraduz; a página do vídeo não. Quando o título importa (citação literal, id de entrada), pegar do/watch, nunca da busca. ytInitialPlayerResponsenão termina em};</script>: termina em};var meta = .... Regex não-guloso até</script>devolve nada e o parse falha em silêncio, com o script caindo no<meta itemprop="name">e perdendo contagem e data. Ler o objeto contando chaves, respeitando string e escape.- O link externo do canal vem embrulhado em
youtube.com/redirect?...&q=<url escapada>. Sem desembrulhar oq, o que se salva é o redirecionador, que não serve para inferir monetização. - Números curtos vêm em dois locais e o parse precisa saber disso: em en-US o ponto é decimal (“1.18M”, “92.4K”), em pt-BR é a vírgula (“1,18 mi”). Com sufixo de escala nunca há separador de milhar, então o único separador presente é sempre o decimal. Tratar o ponto como milhar nesse caso multiplica o número por cem.
- Transcrição:
yt-dlp --write-auto-sub --sub-lang pt --skip-download --convert-subs srtouyoutube-transcript-api. Registrar se a legenda é automática ou humana. Número tirado de legenda automática tem confiança baixa até confirmar.
4. Reddit: só pelo arctic-shift
about.json devolve 403 mesmo com user agent de navegador, old.reddit.com devolve bloqueio, r.jina.ai também 403. Não insistir.
https://arctic-shift.photon-reddit.com/api/, sem chave:
/subreddits/search?subreddit=<nome>: ficha com inscritos, criação e_metacom totais./subreddits/search?subreddit_prefix=<prefixo>&limit=100: descobrir subreddit./posts/search?subreddit=<sub>&query=<termo>&limit=100&sort=desc: caçar tópico./comments/search?link_id=<id>: fio inteiro.- Varredura completa:
sort=ascmaisafter=<epoch>, cursor no maiorcreated_utcda página, mais 1 no empate.after=0falha. De 1 a 1,2 s entre chamadas e retry com backoff, senão{"data":null,"error":"Timeout..."}e página perdida em silêncio. O r/impressao3dbrasil inteiro (5.427 posts, 30.135 comentários) levou 12 minutos. num_commentsdo arquivo é congelado na captura e subestima fio antigo. Contar os comentários baixados.
5. Outros bloqueios e atalhos
- Cloudflare barra por curl: All3DP, MakerWorld, Printables, MyMiniFactory, Thangs, 3D Lab, Comex Stat (portal e API), OLX, Indeed. Navegador.
- Mercado Livre e Amazon Brasil bloqueiam raspagem; a API pública do Mercado Livre exige token (403).
consultas.anvisa.gov.brdevolve 403.- Grupo de Facebook exige login. Discord:
https://discord.com/api/v10/invites/<codigo>?with_counts=truedá contagem. Disboard indexa servidores por tag. aditivabrasil.com.brpagina de 12 em 12 e ignora parâmetro de URL: clicar próxima por script.- Base bruta do comércio exterior aceita curl:
https://balanca.economia.gov.br/balanca/bd/comexstat-bd/ncm/IMP_2025.csve.../tabelas/PAIS.csv. NCM 8485 (fabricação aditiva, criada em 2022; antes era 8477.80.90). - Dados abertos sem bloqueio: consumidor.gov.br, INPI (
dadosabertos.inpi.gov.br), BDTD (bdtd.ibict.br/vufind/api/v1/search), OpenAlex, iTunes Search API para podcast, Agência Sebrae via WordPress API. - Perfis de filamento e de máquina: clonar
OrcaSlicer,BambuStudioePrusaSlicerdo GitHub e lerresources/profiles/*/filament/*.jsone*/machine/*.json. Desduplicar por bico. - Ensaio mecânico de filamento: só My Tech Fun e CNC Kitchen publicam método e número.
7. O que a task 1 acrescentou (04/09/2026)
- Comércio exterior aceita curl e não tem Cloudflare.
balanca.economia.gov.br/balanca/bd/comexstat-bd/ncm/IMP_AAAA.csvbaixa em segundos. O portal Comex Stat e a API dele bloqueiam. NCM correta: 8485 (antes de 2022, 8477.80.90). Arquivo anual tem de 100 a 170 MB: filtre e apague. - PrusaSlicer não usa JSON, usa
.ini. A extração de perfis cobre OrcaSlicer e BambuStudio, que dão 8.758 perfis de filamento de 52 fabricantes. - Herança de perfil precisa ser resolvida. Sem seguir
inheritsrecursivamente, cerca de metade dos campos sai vazia. - YouTube tem limite de taxa. A página
/watchpassou a devolver HTTP 429 depois de cerca de 100 requisições em três processos paralelos. O/aboute o/videosaguentam mais. Para a task 2, use menos paralelismo e pausa maior. - Link externo de canal vem embrulhado em
youtube.com/redirect?...&q=<url escapada>. Sem desembrulhar oq, a inferência de monetização é impossível. - Rodapé de linktr.ee é anúncio. As últimas oito entradas de todo linktree são publicidade da própria Linktree, não links do criador. Quem raspar sem descartar vai classificar criador brasileiro como afiliado de marca americana.
- Preço por plataforma de loja (o caminho que funciona em cada uma): Nuvemshop no atributo
data-variantsdos cards e no objetoLS.variantsda página de produto (não existe/products.json, isso é Shopify); Loja Integrada no HTML (preco-venda,data-sell-price,desconto-a-vista); WooCommerce na Store API/wp-json/wc/store/products; Shopify em/products.json?limit=250; Tray nodataLayer.listProducts; VNDA nozarazProductsmais/produto/preco/<id>. - Desconto no Pix varia de 0 a 10 por cento e é política de loja. 3D Fila não dá nenhum, Onyon 3D dá 3, Multfila, DynaLabs, Voolt3D e Brasfila dão 5, Slim3D dá 8 (e chama de “à vista com desconto”), F3D, 3D Brothers, ArtBox3D e Central Print 3D dão 10. Na ArtBox3D promoção e Pix são excludentes.
- Armadilha de paginação: a ArtBox3D repete a última página quando o
?page=passa do fim, em vez de devolver vazio. A primeira coleta trouxe 59 páginas idênticas. Sempre compare o conteúdo da página com a anterior. - Vários apex de loja não respondem, só o
www: lojanational3d.com.br e loja3dxfilamentos.com.br devolvem conexão recusada no domínio semwww. - MakerHero é intransponível por automação: Cloudflare em curl, sitemap, robots e r.jina.ai, e a Store API devolve 403 até no fetch same-origin de dentro da página aprovada no navegador.
8. O que a task 2 acrescentou (04/09/2026)
8.1 Legenda de YouTube: yt-dlp resolve, e resolve rápido
yt-dlpbaixa legenda por outro caminho que a página/watch, e por isso não sofre o bloqueio de 429 que derrubou a task 1. Instale combrew install yt-dlpe, para ter falsificação de impressão digital de TLS, também no venv:pip install "yt-dlp[default,curl-cffi]", que habilita--impersonate Chrome-136.- Receita que rodou 80 vídeos com 79 acertos de primeira, um processo só, pausa aleatória de 4 a 7 segundos entre vídeos:
yt-dlp --skip-download --write-auto-sub --write-sub --sub-langs "pt-orig,en-orig" --sub-format vtt/best --impersonate Chrome-136 --sleep-requests 2 -o "%(id)s.%(ext)s" URL - Peça sempre o idioma original (
-orig), nunca a tradução. O sufixo-origé a legenda no idioma em que o vídeo foi falado. Pedirptnum vídeo em espanhol faz o YouTube gerar tradução na hora, e é exatamente aí que vem o 429. O único vídeo que falhou na primeira passada era em espanhol e passou de primeira quando o pedido viroues-orig. - Cadeia de tentativa que funciona:
pt-orig,en-orig, depoises-orig,de-orig,fr-orig, depois.*-orig, e só por últimopt,pt-BR,en. --print-to-filecom a máscara entre aspas simples no zsh grava a máscara literal em vez do valor. Use aspas duplas com tabulação real, ou--printredirecionado.- Rendimento medido: 80 vídeos, 247.454 palavras de legenda, cerca de 50 minutos de relógio, zero bloqueio prolongado.
8.2 O VTT automático do YouTube repete tudo três vezes
Quem converter o VTT ingenuamente produz uma transcrição com cada frase duplicada ou triplicada, e um agente que a leia vai gastar o triplo de contexto lendo eco.
- A legenda automática vem em blocos que rolam: o bloco novo repete no topo a linha anterior e só a última linha traz palavra nova, marcada com
<00:00:00.000><c>palavra</c>. - A regra que resolve: se o arquivo contém tag
<c>ou marcação de tempo por palavra, o texto novo está SÓ nas linhas que têm essa marcação. Descarte as outras. Se não houver tag nenhuma (legenda humana), aí sim vale desduplicar linha repetida e prefixo repetido. - Implementação em
scripts/converter-legendas-em-transcricoes.py.
8.3 Reclame Aqui: bloqueado, com uma janela estreita
curldevolve 403 com desafio da Cloudflare no site, emiosearch.reclameaqui.com.bre viar.jina.ai.- No navegador real via MCP, a primeira ficha carregou (Voolt3d, ficha completa lida) e a partir da segunda o domínio inteiro travou em “Executando verificação de segurança”, inclusive depois de esperar 90 segundos, recarregar e fechar as abas extras.
fetchde dentro da própria página aprovada devolve 403, ewindow.openpara outra página do mesmo domínio devolveSecurityErrorao ler odocument.- O que funciona:
WebSearch. O buscador indexa as fichas e devolve, no resumo, nota geral, nota de 6 meses, número de reclamações, percentual de resposta, percentual de solução, tempo médio e percentual de quem voltaria a fazer negócio. É fonte secundária e precisa ser rotulada assim.
8.4 consumidor.gov.br: a base bruta não sai por automação
https://consumidor.gov.br/pages/dadosabertos/externo/abre por curl, mas a tabela vem vazia e é preenchida por Ajax em/pages/publicacao/externo/publicacoes.json?indicadorTipoPublicacao=2, que devolve 504 do WAF F5 (“The requested URL was rejected”) tanto por curl quanto de dentro do navegador.- A aba “Dados Abertos” da página é a mesma lista de publicações de indicador, não a base de reclamações.
- A API do
dados.gov.brdevolve 401 sem chave, tanto em/api/publico/conjuntos-dadosquanto em/api/3/action/package_search. A página do conjunto “Dados Consumidor.gov.br” diz ter 87 recursos, mas a lista não renderiza no navegador. - Achado que vale mais que a base: a participação no consumidor.gov.br é voluntária e só vale para quem assinou termo de adesão. Nenhuma empresa do setor de impressão 3D aparece no autocompletar de empresa. Ou seja, o consumidor brasileiro não tem canal público de reclamação contra fabricante de filamento nem contra loja de impressora, e a única base existente é o Reclame Aqui, que é privado.
8.5 Reddit: o arctic-shift entrega fio inteiro por link_id, sem dor
GET /comments/search?link_id=<id do post>&limit=100&sort=asc&after=<epoch>pagina o fio inteiro. O fio de 1.536 comentários registrados devolveu 1.573 comentários reais, ou seja, onum_commentsdo arquivo subestima mesmo em fio recente.- Trinta e um dos 46 fios pedidos vieram completos do arctic-shift em cerca de 4 minutos, com 1,2 segundo entre chamadas.
- O bruto local dos cinco subs brasileiros cobriu os posts, mas quase sempre com menos comentários que o arctic-shift devolve por
link_id: vale sempre comparar e ficar com o maior. - Para o agente ler, o JSON cru é ruim.
scripts/montar-fio-legivel.pymonta a árvore em Markdown, primeiro nível ordenado por pontuação e respostas identadas, com autor, pontuação e data. 46 fios viraram 1,5 MB de texto legível.
9. Registro de falha
Toda tentativa que falhar entra em _meta/log-de-coleta.md com a mensagem de erro. Isso vale tanto quanto o dado coletado, porque evita que o próximo chat repita a batida de cabeça.
10. O que a task 3 acrescentou (06/09/2026)
10.1 Duas fontes que pareciam fechadas e abriram
- Aditiva Brasil sai inteiro por API, sem navegador. O método antigo registrado aqui (paginar de 12 em 12 clicando em próxima por script) ficou obsoleto. O site é um front que consome uma API REST do Supabase, com a chave anônima pública embutida no bundle JavaScript. Achar o endpoint é ler o bundle com curl. As views são
v_mapa_public,v_empresas_detalhe,v_fornecedores_public,v_prestadores_publicev_startups_icts_public. Saíram as 249 organizações de uma vez, com UF e cidade em todas e CNPJ em 174. Nenhum cadastro foi feito e nenhum formulário foi preenchido. Esse padrão vale para qualquer site que pareça exigir navegador: antes de abrir o Chrome, procure/api/,supabase,wp-jsonou__NEXT_DATA__no HTML e no bundle. - CNPJ vira cidade confirmada pela BrasilAPI.
https://brasilapi.com.br/api/cnpj/v1/<cnpj>devolve razão social, município e UF sem chave e sem bloqueio. É o que transformou “cidade extraída por regex, confiança baixa” em cidade confirmada em fonte primária. O caminho que funciona é: achar o CNPJ no rodapé da loja (quase sempre está na página de política de privacidade ou de termos, que quase ninguém abre), consultar a BrasilAPI e comparar com o que a empresa diz de si.
10.2 O que continua fechado, confirmado nesta rodada
- Reclame Aqui: igual à task 2. Só a primeira ficha do dia passa no navegador, e da segunda em diante o domínio inteiro trava na Cloudflare.
WebSearchcontinua sendo o caminho, devolvendo nota, contagem, percentual de resposta e tempo médio no próprio resumo, como fonte secundária. - consumidor.gov.br: a task 3 não tentou de novo, e não deve tentar. O endpoint devolve 504 do WAF F5, a API do dados.gov.br exige chave, e a adesão é voluntária, então nenhuma empresa do setor está lá. A linha do método da própria task 3 que dizia “consumidor.gov.br é aberto e já deve ter sido baixado na task 2” está errada. Fica registrado aqui para o próximo chat não gastar uma hora nisso.
- MakerHero continua intransponível por automação.
10.3 Onde mora a cidade de uma loja brasileira
A ordem que funcionou, em dezenas de sites: página de política de privacidade e de termos (traz CNPJ e endereço completo, e quase ninguém olha), rodapé de qualquer página, /contato, /quem-somos, /sobre, /institucional. Depois do CNPJ em mãos, a BrasilAPI fecha. Deduzir cidade por DDD de telefone só vale se o registro disser que foi isso.
Dois erros de cadastro que essa rotina pegou e que valem como aviso: a National3D estava fichada com cidade “Premium” e UF “MG”, que são pedaço do nome de um produto (“ABS Premium MG 94”) capturado por regex, e a 3D Fila estava como Betim quando o CNPJ na Receita diz Belo Horizonte. Campo preenchido por regex a partir de texto livre erra desse jeito, e o erro sobrevive por rodadas se ninguém abrir o site.
10.4 A terceira auditoria do classificador de reclamação, e o limite que ela achou
Este é o achado de método mais importante da task 3, e ele vale para qualquer classificação lexical de tom.
O histórico. A versão 1 foi auditada por amostra de 45 casos e reprovou com 33,3 por cento de precisão estrita na classe reclamação. A versão 2 corrigiu as três causas medidas (limite de palavra no nome da marca, palavra genérica rebaixada a sinal fraco, texto multimarca em classe própria) e foi reauditada nesta task, com amostra nova e semente diferente: reprovou de novo, com os mesmos 33,3 por cento, e a classe elogio caiu de 53,3 para 40,0.
O diagnóstico mostrou que as três causas antigas morreram de fato (zero reclamação disparada só por palavra genérica, zero texto multimarca, zero “ender” casando dentro de outra palavra), mas o erro mudou de natureza: 15 dos 20 erros restantes eram “a palavra de tom não se refere a essa marca”. O classificador lia o texto inteiro como um saco de palavras, e bastava a marca aparecer num canto e um xingamento em outro para os dois virarem par.
A versão 3 passou a classificar frase a frase (um sinal só conta para a marca que está na mesma frase), a descartar sinal precedido de negador, a mandar pedido de ajuda técnica para uma classe própria, e a exigir folga de dois sinais em avaliação mista. Auditada pelo mesmo método, com amostra nova: reclamação subiu para 48,3 por cento e elogio para 73,3 por cento.
O que só apareceu ao separar por classe de marca, e é a parte que importa:
- marca de insumo (filamento e resina): 86,7 por cento de precisão estrita na classe reclamação, intervalo de 95 por cento de 62,1 a 96,3.
- marca de equipamento (impressora): 7,1 por cento, intervalo de 1,3 a 31,5.
Os dois intervalos não se sobrepõem, então a diferença não é ruído de amostra pequena. E a causa é do corpus, não da regra: quando alguém reclama de filamento, a marca é o sujeito da queixa (“o filamento da 3D Lab entope”); quando o assunto é impressora, a marca é o cenário de um pedido de ajuda técnica (“minha Ender está com o bico entupido, o que faço?”). Nenhuma regra lexical separa isso, porque a informação que falta não está nas palavras: está em quem é o alvo da frase.
Por isso não existe versão 4. Continuar mexendo em regra lexical não resolve um problema que não é lexical. O que o script passou a fazer é declarar o próprio limite: cada marca sai com classe e utilizavel_para_ordenar, e quem consumir o JSON sabe qual número pode usar. Fechar a parte de equipamento exigiria classificação semântica, com um modelo lendo cada texto, e isso é outra tarefa.
A regra prática para o resto do dossiê: número de reputação de marca de filamento pode ser citado para ordenar marca entre si; número de reputação de marca de impressora não pode ser citado, nem para ordenar.
10.5 Auditar de novo é barato e paga
As três auditorias custaram, cada uma, um agente lendo 44 ou 45 textos com semente fixa. Duas delas derrubaram o número que estava valendo. A lição para as próximas tasks: classificador automático sem auditoria por amostra é palpite com aparência de estatística, e a auditoria custa uma fração do que custou construir o classificador.
Duas regras que a sequência ensinou:
- Amostra nova a cada versão. Se a versão nova for ajustada olhando os erros da amostra auditada, a auditoria antiga deixa de valer para ela. Cada versão foi auditada com sorteio próprio, e é isso que permite comparar 33,3 com 48,3.
- Agregado esconde. A versão 3 parecia um avanço modesto no número agregado (33,3 para 48,3) e era, ao mesmo tempo, um resultado ótimo numa metade do corpus e um resultado inútil na outra. Separar por classe antes de concluir mudou a recomendação inteira.
10.6 Economia de tempo, decidida pelo founder em 06/09/2026
A task 3 levou muito mais tempo que as anteriores e o founder cortou o excesso no meio da execução. As regras abaixo valem da task 4 em diante e mudam o desenho, não só o ritmo.
Verificação em segunda fonte deixa de ser padrão. A regra passa a ser: achou o dado, registrou a fonte por id com data, acabou. Segunda fonte só quando o número for decisivo para uma conclusão do dossiê e duas fontes se contradisserem. Rodar um agente atrás de confirmar o que já está confirmado foi o que mais consumiu relógio nesta task, e quase nunca mudou o número.
O agente crítico fica, mas só na parte local. O que ele faz bem e barato é recontar com grep -c e wc -l, achar id de fonte que não existe, achar travessão, e cruzar o que o YAML afirma com o que está em disco. Foi assim que a task 2 achou um número errado replicado em 54 documentos. O que ele fazia caro e com pouco retorno era reabrir URL na internet para reconferir número já registrado: isso sai.
Ler o disco antes da internet, sempre. Nesta task, o agente que varreu os arquivos locais primeiro terminou em minutos e trouxe 90 fichas de operador; os que foram direto para a web levaram meia hora para trazer menos. O dossiê já tem quase tudo depois de três rodadas.
Gravar parcial a cada 4 ou 5 itens. Não é conselho, é o que salvou esta task: quando a cota da sessão estourou e derrubou 20 agentes de uma vez, o que estava em disco sobreviveu inteiro e só o que estava em memória se perdeu. Todo prompt de agente leva essa instrução.
Lotes de 6 agentes, não de 12. O limite de concorrência é min(16, CPUs menos 2), então um lote de 12 já enfileira metade. Pior: se a cota estourar, o lote inteiro morre junto. E dois workflows rodando ao mesmo tempo disputam o mesmo limite e ficam os dois lentos.
Um agente por documento longo, não três em sequência. Os agentes de nicho escreviam três documentos cada e viraram o gargalo do lote: os outros terminaram e eles seguiram sozinhos por quase uma hora. Documento longo paraleliza bem, sequência dentro do agente não.
Uma armadilha de edição de workflow. Ao acrescentar uma fase nova num script, a chamada await parallel da fase anterior pode ser substituída sem aviso, e aí a fase simplesmente não roda. Custou trinta minutos nesta task. Antes de disparar, conferir com grep -n "await parallel" que existe uma chamada para cada phase().
11. O que a task 4 acrescentou (06/09/2026)
11.1 Sete portas que abriram, e todas por curl
Nenhuma delas precisou de navegador, e cinco não gastaram uma única busca.
- My Tech Fun publica o dado bruto de cada ensaio. O site não tem planilha única nem API, e por isso o dossiê passou três rodadas achando que não havia número de resistência disponível. Mas cada vídeo de ensaio deixa a planilha aberta em
mytechfun.com/download/<id do video>/<arquivo>.xlsx. Listando os ids em/videos/material_teste/videos/filamentsaíram 145 páginas, 69 planilhas e 6 PDFs, que viraram 160 medições de tração, impacto e deflexão em 22 famílias de material e 34 marcas. Esse foi o maior buraco do dossiê e ele fechou em uma sessão. - A Amazon Brasil tem fonte primária aberta:
venda.amazon.com.br/precosdevolve, por curl, as 35 categorias com comissão, os dois grupos de comissão mínima e os dois planos de venda. O dossiê estava usando blog para isso. - A Shopee também, por um caminho indireto: a página do Centro de Educação do Vendedor devolve casca de JavaScript, mas a API que ela mesma consome responde sem login, e as tabelas que aparecem como imagem saem do CDN. Os artigos 18483 (política de comissão), 18484 (adicional de CPF) e 26839 (comunicado de 04/02/2026) foram lidos assim. O resultado refutou duas leituras que circulavam em quatro blogs: abaixo de R$ 8,00 a cobrança é de 70 por cento do preço (20 por cento de comissão mais metade do preço como adicional), não 50 por cento; e a taxa fixa acima de R$ 500 continua em R$ 26,00, não sobe para R$ 28,00.
- A tabela completa de custo operacional do Mercado Livre saiu de uma fonte já catalogada, a Ferax, por curl: 29 faixas de peso por 8 faixas de preço, o que fechou as três faixas de peso que interessam sem nenhuma estimativa.
- A calculadora oficial da Copel dá a tarifa homologada com a decomposição de TUSD e TE, o que permite montar o valor com impostos em vez de copiar agregador. Foi assim que o dossiê trocou os R$ 0,88 por kWh (agregador que refletia homologações até março de 2026, antes da revisão) pelos R$ 1,05 de bolso em Curitiba.
- As APIs de dados abertos da Câmara e do Senado resolvem status de tramitação sem interpretação:
dadosabertos.camara.leg.brcom os endpointsproposicoes,proposicoes/{id}/tramitacoeseproposicoes/{id}/autores, e a API do Senado commateria/pesquisa/listaeprocesso/{id}. É o jeito de nunca mais tratar projeto de lei como lei. - O CNC Kitchen tem RSS com 114 artigos e passa por curl.
11.2 O erro de coordenação que esta task cometeu
Um agente gerou o CSV de taxas efetivas a partir do JSON de tarifas enquanto o agente que produzia esse JSON ainda estava escrevendo nele. O CSV saiu com quatro linhas estimadas por razão onde, minutos depois, havia dado publicado, e a estimativa errava para cima em até 5,9 por cento. Não quebrou nada porque o produtor avisou no relatório e o derivado foi refeito, mas a regra que fica é simples: derivado se gera depois que o produtor do insumo fecha, ou se regera no fim, sempre. Em workflow paralelo, arquivo de insumo é alvo móvel.
11.3 Capacidade não é demanda, e essa é a diferença entre modelo e propaganda
A primeira versão do modelo financeiro partiu da capacidade da máquina, 480 horas por mês, e supôs que tudo o que ela produz vende. O resultado foi payback de 0,2 mês, seis dias, exatamente o tipo de número que as fontes comerciais de sublimação prometem e que este dossiê recusa. O modelo estava aritmeticamente certo e economicamente absurdo.
A correção foi limitar a produção pelo menor entre três tetos, hora de máquina, hora humana e demanda, com a demanda ancorada em faturamento declarado por operador brasileiro (R$ 1.000 por máquina no primeiro mês de um relato, R$ 867 por máquina de um operador com cinco máquinas, R$ 2.000 projetados por uma franqueadora que vende franquia, de R$ 2.143 a R$ 3.286 de um relato com 70 máquinas). Com isso o payback vai de 1,0 a 15,1 meses conforme o cenário e se o dono é ou não remunerado, e aparece o achado que atravessa o dossiê inteiro: a máquina fica ociosa entre 4 e 20 por cento do tempo disponível, e o gargalo é a demanda, não a máquina.
A lição de método: num modelo de negócio, a premissa que ninguém quer declarar é a que decide o resultado. Se o modelo não tem uma linha chamada demanda, ele está supondo demanda infinita.
11.4 Contagem de números: o critério agora é executável
O dossiê atravessou três tasks com dois critérios convivendo para numeros_criticos, contar ocorrência de número e contar frase com número, e a diferença chegava a cinco vezes no mesmo arquivo. O critério canônico agora está em scripts/contar-numeros-criticos.py e escrito em _meta/convencoes.md: cada valor numérico afirmado no corpo, sem ano, data, norma, id de fonte nem código, com repetição na mesma frase contando uma vez. Os 43 documentos das seis pastas foram recontados por script.
11.5 A cota da sessão estourou de novo, e o que salvou
No quinto lote de escrita a cota da sessão estourou e derrubou 8 dos 28 agentes de uma vez. 23 dos 28 documentos sobreviveram inteiros porque a instrução de gravar a cada seção estava dentro do prompt de cada agente. E a recuperação custou quase nada: o resumeFromRunId do Workflow devolveu os 20 concluídos do cache e re-rodou só os 8 que morreram, sem refazer trabalho nenhum. Duas regras que valem para a próxima task: a instrução de gravar parcial vai em todo prompt de agente, e workflow interrompido se retoma por resumeFromRunId, nunca se redispara do zero.
11.6 O critico local ficou script, e deixou de ser agente
Na task 3 o crítico local era um agente. Na task 4 virou scripts/task-04-critico-local.py, que roda em dois segundos e confere travessão, id de fonte inexistente, id sem data, contagem de números contra o critério canônico, número já refutado que ressuscitou, importação sem período na mesma frase, tabela de Markdown em prosa, status e data do frontmatter, e documento faltando. O agente crítico continua existindo, mas para o que só um leitor faz: refazer conta, checar se o número existe no arquivo de origem e achar incoerência entre documentos. Separar as duas coisas fez a checagem mecânica sair de graça e liberou o agente para o que é caro.
12. O que a task 5 acrescentou (06/09/2026)
12.1 A rodada final: 25 afirmações, 3 lentes, 75 agentes
O desenho que a task 5 pedia era 25 afirmações vezes 3 verificadores independentes. O que fez diferença não foi o número de agentes, foi dar uma lente diferente para cada um, em vez de três céticos genéricos:
- Fonte primária pergunta se o número existe, com esse valor exato, no arquivo que o dossiê declara como origem, e se o id de fonte citado existe no catálogo.
- Aritmética refaz a conta com as parcelas que o próprio dossiê publica, roda o script gerador e compara.
- Atualidade e interesse pergunta se o dado está vencido e quem ganhava alguma coisa ao declará lo.
Placar: 11 de 25 sobreviveram, 14 caíram. Quase toda queda foi impreciso, não errado: o
número estava certo e a frase que o carregava não estava. Isso é o resultado esperado num
dossiê que já passou por quatro rodadas, e é o motivo de o critério ser “na dúvida, refutada”.
O achado que só a lente de fonte primária pegaria: quatro ids de fonte usados em campo
fonte: de YAML não existiam em catálogo nenhum, e três deles sustentavam doze premissas do
modelo financeiro, incluindo o denominador de 480 horas que produz a faixa de utilização
inteira. O crítico local só conferia citação no corpo de arquivo Markdown, então YAML de dado
passava batido. Corrigido nos dois lados: as quatro fontes foram catalogadas em
_meta/fontes-novas-task-05.yaml e o crítico passou a varrer os YAML de dado.
12.2 Um número que circulou quatro rodadas e não existia
O dossiê usava R$ 867 por máquina por mês como o contraponto brasileiro real contra os R$ 2.000
projetados pela franqueadora. Ele não existia em fonte nenhuma. Era divisão feita pelo
próprio dossiê, e caiu por três motivos, todos conferidos no dump bruto do Reddit e registrados
em data/brutos/task-05/achado-kresnik-contradicao.json:
- o divisor de cinco máquinas foi declarado em 24/06/2026, um mês depois do faturamento de R$ 13.000 em três meses declarado em 26/05/2026, então é o parque de depois e não o de durante;
- o mesmo usuário havia declarado em 25/04/2026, um mês antes, faturar R$ 10.000 por mês, o que não fecha com a outra declaração;
- ele não era o único operador brasileiro com número no corpus.
A lição de método: número derivado por divisão dentro do próprio dossiê é o mais perigoso que existe, porque ele nasce com aparência de apuração e nunca teve fonte. Quando aparecer um, a pergunta certa é “quem publicou isso?”, e se a resposta for “nós calculamos”, ele precisa do mesmo rótulo de um palpite.
12.3 Cruzar o que existe não é o mesmo que caçar o que sobrou
O cruzador da task 4 pergunta se o valor novo aparece em algum documento, e dá ok com uma
única citação. Quando a margem por hora do B2B mudou de R$ 47,69 para R$ 48,82, ele passou
dizendo “ok, citado em 1 documentos” enquanto o valor antigo seguia escrito 33 vezes em 10
documentos.
Daí nasceu scripts/task-05-valor-vencido.py, que faz a pergunta inversa: quem ainda repete o
número que o arquivo gerado já não produz. Duas armadilhas apareceram ao construí lo, e as duas
valem para qualquer checagem desse tipo:
- Perdão por parágrafo esconde tudo. A primeira versão perdoava a ocorrência quando a janela de 400 caracteres continha “caiu”, “virou” ou “antiga”. Documento que discute o próprio histórico de correção casa isso em todo parágrafo, e um agente descobriu que três ocorrências vivas passaram invisíveis. A unidade certa do perdão é a frase.
- Valor ambíguo vira ruído. R$ 18,48 continua sendo o custo direto correto da peça de PLA e só está vencido quando descreve o B2B. Sem exigir a menção explícita ao B2B, o script acusava texto certo, e checagem que acusa texto certo deixa de ser lida.
12.4 Defeito de rótulo dentro do gerador
O bloco b2b_peca_tecnica do modelo se descrevia como peça de 100 g em PETG e rodava a conta
com o custo do PLA. Achado por agentes de documento que foram conferir a decomposição, não
por script.
Vale como padrão de erro: quando um gerador monta a vitrine (descrição, rótulo) num lugar e a conta em outro, os dois divergem em silêncio e nenhum validador percebe, porque cada um está internamente coerente. Corrigir só a descrição teria sido pior que o defeito original, porque passaria a exibir uma peça e calcular outra. A correção certa foi na origem, e depois a propagação nos 16 documentos que citavam o resultado.
12.5 A cota estourou de novo, e a instrução de gravar parcial salvou de novo
A cota da sessão derrubou os 49 agentes de correção de uma vez. O resumeFromRunId não
recuperou nada, porque nenhum agente chegou a concluir: todos morreram ao devolver o
resultado. O que salvou trabalho foi a outra regra: cinco agentes já haviam gravado o JSON
em disco, e o texto que eles tinham escrito nos documentos sobreviveu inteiro.
Duas lições novas:
resumeFromRunIdsó recupera agente concluído. Quando a queda é por cota, e portanto simultânea, o cache costuma estar vazio. A instrução de gravar em disco antes de responder é o que de fato protege, e ela precisa estar em todo prompt de agente.- Estado parcial mente. Cinco documentos ficaram marcados
status: finalcom o trabalho pela metade, porque o agente carimbou o frontmatter antes de terminar. Ao retomar, o prompt passou a avisar que status de frontmatter não é prova de trabalho concluído, e que o agente deve conferir no próprio texto.
12.6 Agente que recusa apontamento com prova vale mais que agente obediente
Dos apontamentos entregues aos 49 agentes de correção, 88 foram recusados com prova, e a maioria das recusas estava certa. Os três padrões:
- O achado envelheceu. Vários verificadores acusaram ids de fonte inexistentes que o orquestrador catalogou no meio da execução. Os agentes conferiram, viram que o achado deixara de valer, e registraram isso no documento em vez de apagar.
- Endereço errado. Verificador apontando correção de energia para o documento de filamento,
de payback para o de custo por peça. Pego com
grepem segundos. - A correção proposta repetiria o erro. Um verificador mandou publicar R$ 3.333 por máquina como novo contraponto; o agente foi ao bruto e viu que a declaração falava em “5 produtos”, não cinco máquinas.
A regra que fica: todo prompt de agente de correção precisa de um campo
apontamentos_recusados com justificativa, e recusar com prova precisa ser dito explicitamente
como resultado tão bom quanto aplicar. Sem isso o agente aplica o que vier, e verificador
também erra.
12.7 O que passou a ser conferido por script
Três checagens novas, todas de graça:
scripts/task-05-critico-local.py, superconjunto do crítico da task 4: cobre o dossiê inteiro (301 arquivos contra 43), varre id de fonte dentro de YAML de dado, e caça as armadilhas de número da task (ocupação trocada por ociosidade, reputação de marca de impressora usada para ordenar, payback sem as duas versões, projeto de lei como lei, tarifa vencida da Shopee, e os R$ 867). Corrigiu também dois defeitos do crítico anterior: o regex de id truncava id de vídeo do YouTube, que é base64 de caixa mista, acusando 6 fichas à toa, e a lista de perdão não reconhecia texto que nega a existência de um número refutado.scripts/task-05-valor-vencido.py, descrito acima.scripts/task-05-recontar-tudo.py, que aplica o critério canônico denumeros_criticosaos 301 documentos e não só aos 43 da task 4, e define a regra denumeros_verificadospor tipo de documento: transcrição sempre 0, porque é registro literal de legenda automática que reconhecidamente erra número; derivado de leitura preserva a proporção declarada aplicada ao denominador novo; documento analítico mantém o valor apurado.
13. O que a task 6 acrescentou (07/09/2026)
Esta foi a primeira task que não pesquisou impressão 3D. Ela pesquisou como se publica pesquisa com dados, e o método precisou mudar em três pontos, porque o objeto mudou.
13.1 Pesquisa de decisão técnica envelhece em meses, não em anos
Nas cinco tasks anteriores, uma fonte de 2024 ainda valia. Aqui, uma fonte de seis meses atrás já mente: versão de pacote, limite de plano gratuito e preço de plataforma mudam sem aviso e sem changelog visível. Três achados desta rodada mostram o tamanho do problema.
O comparativo que quase todo blog de 2026 publica, de que o gerador escolhido leva de 10 a 30 segundos para mil páginas, foi recusado pelo agente com medição própria: sobre este acervo, 308 páginas saem em 2,84 segundos. O limite de registros do plano gratuito de um serviço de busca estava escrito como 50.000 em material recente e a página de preços diz 100.000. E o nome da diretiva de privacidade que o eixo de hospedagem escreveu era o antigo, aposentado, o que significa que a linha simplesmente não fazia nada, em silêncio.
A regra que fica: em pesquisa de decisão técnica, fonte secundária serve para descobrir que uma coisa existe, nunca para afirmar quanto ela custa, quanto ela pesa ou qual versão está no ar. Isso se confere no registro do pacote, na página de preços e no binário.
13.2 O erro não estava dentro dos eixos, estava entre eles
Sete agentes pesquisaram sete eixos, cada um com pergunta específica, e a auditoria confirmou que todos os sete estavam bem no mérito: quatro medições refeitas por conta própria bateram na segunda casa decimal. Os quatro problemas graves eram todos de costura. A política de segurança de um eixo bloqueava o WebAssembly da busca de outro. O processador de markdown de um não rodava o plugin de outro. A ilha sem framework de um anulava o critério que tinha escolhido o gerador de outro. E a nota de margem que um prescrevia tinha sido refutada por medição em outro.
Nenhum desses aparece lendo um eixo isolado, e nenhum aparece perguntando ao agente se ele tem certeza. Aparecem quando alguém pergunta se a decisão de A cabe na decisão de F.
A regra que fica: quando a pesquisa é dividida por eixo, a auditoria de costura não é opcional, e ela é uma etapa própria, com prompt próprio, que só pergunta se as peças encaixam.
13.3 Construir para decidir é mais barato que discutir para decidir
As quatro costuras foram resolvidas montando seis projetos, e três decisões mudaram por causa disso, duas delas contra o parecer do auditor.
O caso mais claro: o auditor afirmou, com fonte, que o processador de fábrica do gerador não roda plugin do outro ecossistema, e concluiu que era preciso trocar o pipeline. O agente construiu as duas rotas inteiras sobre os documentos reais, e o resultado foi que a rota nativa funciona, entrega HTML idêntico byte a byte e custa 42 vezes menos tempo de render. O parecer estava certo na premissa e errado na conclusão.
O segundo caso: a política de segurança quebrava a busca de verdade, com erro de compilação. O conserto que o auditor propôs estava incompleto, e a causa real só apareceu no teste cruzado: o cabeçalho que governa é o do arquivo do worker, não o do documento.
A regra que fica: quando duas decisões técnicas se contradizem, construir as duas custa umas horas de agente e produz número. Discutir custa o mesmo e produz opinião. Este projeto já sabia disso para número de dossiê, e agora sabe para decisão de ferramenta.
13.4 Todo mundo mediu o acervo, e ninguém mediu a mesma coisa
Sete eixos declararam cinco tamanhos diferentes para o mesmo acervo: 307, 317, 322, 328 e 370 arquivos, e três contagens diferentes de palavras. Cada um contou o que quis, e três dos sete ficaram dimensionados para acervos que não existem.
O conserto foi um script versionado, scripts/site-inventario.py, com critério de corte escrito
no cabeçalho, modo de verificação que falha se o número mudar, e a URL de cada página. Ele fecha
em 307 páginas, que é exatamente o número oficial do dossiê, com 936.617 palavras de corpo da obra
fora do aparato de _meta.
A regra que fica: antes de distribuir trabalho sobre um acervo, publique a contagem canônica dele em script, e mande todo agente citar esse número em vez de contar de novo.
13.5 Agente que recusa com prova, de novo, e agora contra o auditor
A regra veio da task 5, quando 88 de 913 apontamentos foram recusados com prova. Nesta rodada ela apareceu num nível acima: os agentes de conciliação recusaram o auditor, e estavam certos. Um recusou o pipeline que o auditor mandou adotar, com medição de tempo. Outro recusou a duração de sessão sugerida, com o motivo. Outro recusou a forma de detectar sessão vencida, mostrando que ela não é implementável, porque a busca faz a requisição dentro de um worker que não expõe ponto de entrada.
Também apareceu a recusa produtiva contra o próprio enunciado. O enunciado do eixo de dados apresentava duas estratégias como equivalentes, e o agente recusou a equivalência com prova. O enunciado do eixo de busca pedia um critério de três cliques, e o agente entregou dois cliques recusando o critério, porque contar clique não é o que faz alguém achar coisa.
13.6 Medição que muda de resultado quando o fundo muda
A paleta de gráfico foi validada por um agente contra superfícies que não eram as do site, e ele mesmo avisou que o resultado mudaria e mandou rodar de novo. Rodou: reprovava, com o verde em 2,72 para 1 de contraste. Escurecer o laranja, e não o verde, resolveu contraste e daltonismo ao mesmo tempo.
E ficou provado por medição um teto que normalmente é regra de gosto: não existe quarta cor de série neste site. Um roxo acrescentado às três dá 4,8 de separação em deuteranopia contra o azul, e 14,2 em visão normal, abaixo do piso duro de 15.
A regra que fica: validação de cor é relativa ao fundo. Paleta aprovada em outro contexto é paleta não aprovada.
13.7 Ferramenta feita para humano quebra quando vira insumo de script
O gerador do modelo financeiro imprime, no modo de sensibilidade, um recorte de 1.200 caracteres para leitura rápida. O recorte corta no meio de uma string e portanto não é JSON válido. Isso nunca incomodou ninguém, porque até aqui só gente lia a saída. Na hora em que o site precisa comparar a conta do navegador com a conta em Python, caso a caso, o recorte vira impedimento.
Resolvido com uma flag aditiva, --json-completo, que não toca no cálculo. Vale como padrão:
quando uma ferramenta de leitura humana vira insumo de outra ferramenta, o caminho é acrescentar
uma saída, nunca mudar a que já existe.
14. O que a task 7 acrescentou (07/09/2026)
A task 7 construiu o site inteiro de uma vez, sobre decisões já tomadas e medidas. O método que funcionou foi o de obra com muitos operários na mesma casa: dono por arquivo, uma trava de build, revisão adversarial por lente, e correção só depois de reprovação com evidência. O que segue é o que vale para qualquer construção grande com agentes, e não só para este site.
14.1 Copiar o protótipo medido vale mais do que reescrever
A task 6 deixou no scratchpad os seis projetos que decidiram a stack: a rota A do Astro com o plugin de citação, a ilha do modelo, a bateria de paridade, o teste da política de segurança, o gráfico com o Observable Plot e o site de teste da busca. Nada disso foi reescrito. O esqueleto da etapa 1 buildou as 307 páginas em 1,83 segundo com os mesmos números do conferidor da task 6 (2.343 de 2.344 citações, 2.576 marcadores, zero perda), porque o núcleo do parser é o mesmo arquivo. Cada módulo da rodada 2 recebeu o caminho do protótipo e a ordem de copiar e adaptar.
A regra que fica: protótipo que decidiu com medição é código de produção em estado bruto. Reescrever é jogar fora a medição.
14.2 Seis agentes na mesma árvore: dono por arquivo, trava de build e pedido de integração
Os seis módulos da rodada 2 e os corretores das rodadas seguintes trabalharam ao mesmo tempo no
mesmo projeto. Três mecanismos evitaram que se pisassem: cada agente só cria ou edita os arquivos
do próprio escopo, e o que precisa em arquivo alheio vira um pedido de integração com o trecho
pronto para colar; a build é serializada por uma trava feita com mkdir, que é atômico, e cada
agente grava numa pasta de saída própria (--saida dist-x); e o layout base expõe ganchos
(uma folha de estilo por módulo, três scripts com defer, dois slots) para ninguém precisar
editar o layout.
Onde isso falhou, falhou de forma previsível: um agente que corrige uma regra global de CSS muda a medição de outro; o agente que colocou um atributo no rótulo quebrou o regex do teste de navegação de um terceiro. A solução foi sempre a mesma: o orquestrador aplica os pedidos cruzados entre rodadas, numa passada só, e rebuilda.
14.3 A cache do content layer engana quando só o plugin muda
O Astro guarda o HTML renderizado de cada markdown e o reaproveita quando o arquivo não mudou.
Quando o que mudou foi o plugin de citação, a build saiu com HTML velho, sem aviso, duas vezes.
O build.sh passou a chamar astro build --force sempre; custa um segundo.
14.4 O minificador tira as aspas e a fonte some sem erro nenhum
Este é o achado mais caro da task. O sistema tipográfico chamava a serifada de “Serif Dossie”. O
minificador de CSS da build tira as aspas quando acha que pode, e deixa font-family:Serif Dossie; o Chromium rejeita nome de família sem aspas que começa por palavra genérica, o
@font-face fica sem nome, e todo o texto cai na reserva, Georgia, que tem métrica casada em
98,66 por cento e por isso ninguém percebe. Três rodadas mediram largura de linha, alvo de toque e
altura de caixa em Georgia. O agente de aceitação de carga achou porque mediu o instante em que a
face é aplicada, não o instante em que o arquivo chega. As famílias passaram a chamar “Leitura
Dossie” e “Leitura Reserva”, e as medidas de linha foram refeitas com a fonte real.
A regra que fica: antes de medir qualquer coisa de tipografia, conferir em
document.fonts que a face está com status loaded; document.fonts.check devolve verdadeiro
quando não existe face nenhuma para casar, e por isso não serve.
14.5 O WebKit honra upgrade-insecure-requests até em localhost
O teste local em Safari e no simulador de iOS derrubava CSS, fontes e JavaScript com erro de SSL:
o WebKit tenta https em 127.0.0.1 quando a política manda, e o Chromium isenta localhost. O
servidor de teste ganhou a opção SEM_UPGRADE=1, que tira só essa diretiva; em produção o site é
https e a política fica inteira. Com isso, o risco que a task 6 tinha nomeado caiu: o cabeçalho do
próprio arquivo do worker governa a compilação do WebAssembly também no WebKit 26.6 e no Safari
do iOS 26.3, com os mesmos 40 resultados do Chromium para “payback” e zero violação.
14.6 Revisão adversarial por lente acha o que o construtor não vê
Três revisores, cada um com uma lente da régua (abertura e texto; número, figura e cor; interação
e os dois turnos do papel), sem permissão de corrigir nada, devolveram 22 reprovações e 19 ajustes
com evidência. Nenhum construtor tinha visto que a figura 3 saía sem a curva (um ariaLabel em
string constante faz o Plot devolver zero caminhos), que todo texto do site abaixo de 18 px
rodava de 82 a 142 caracteres por linha, ou que a página de verificação deixava 24 citações como
texto cru. A etapa 8 (aceitação em WebKit, iOS, impressão, carga e acessibilidade) achou o resto:
o glifo do marcador de <summary> que o subset da fonte não tem e sai como “?” no iOS, e a
serifada que nunca carregava.
A regra que fica: quem constrói aplica a régua e não a enxerga; a reprovação precisa vir de quem não construiu, com o item exato da régua e a evidência, e a correção volta para o dono do arquivo.
14.7 Enriquecer o documento sem tocar no markdown
A página de custos precisava de prosa, citação, tabela navegável e o modelo interativo juntos, e
o acervo é imutável. A entrada da coleção expõe o HTML renderizado; um fatiador corta esse HTML
no fim da seção cujo h2 tem o id pedido e a página renderiza os componentes entre as fatias.
Slug que não existe quebra a build, porque um gráfico colado na seção errada é pior que gráfico
nenhum. O enriquecimento fica fora do índice de busca (provado abrindo os 308 fragmentos do
Pagefind), e o conferidor de citações continua contando os mesmos marcadores.
14.8 O que o Workflow ensinou desta vez
parallel()devolvenullpara agente que morreu; embrulhar o resultado num objeto antes de filtrar esconde o nulo e derruba o script inteiro. O embrulho tem de preservar o nulo.- A cota da sessão caiu no meio da rodada 3 com três revisores no ar. Os três agentes de
integração já tinham fechado e voltaram do cache no
resumeFromRunId; os revisores rodaram de novo. Nada foi redisparado do zero. - Três revisores abrindo navegadores ao mesmo tempo esgotaram a memória da máquina. Um navegador por vez, contexto fechado depois de cada captura, e servidor morto ao terminar entraram no prompt de toda rodada seguinte.
- Agente que recusa com prova continuou valendo mais: o corretor do modelo trocou o décimo segundo controle da especificação depois de varrer 4.096 cantos e provar que o gargalo nunca troca de lado; o corretor de gráficos recusou legenda, tooltip e canto arredondado que a skill de visualização manda por padrão, com a linha da régua que cada um fere.
14.9 Ferramentas que faltavam, e o que serviu no lugar
A máquina não tem poppler, então PDF virou imagem pelo Quick Look do macOS (qlmanage) página a
página, depois de dividir com pypdf na venv. Leitor de tela não é automatizável: sobrou a árvore
de acessibilidade do Chromium, gravada por página, que diz o que o leitor ouviria. O Safari
testado é o WebKit do Playwright e o do simulador de iOS, não o Safari.app instalado nem um
iPhone físico. Tudo isso está escrito como lacuna, não como aprovação.
14.10 Validador com falso positivo herdado, e um acerto no meio dele
scripts/task-05-valor-vencido.py já saía com nove ocorrências antes de a task 7 tocar em
qualquer arquivo, e a ordem de serviço exigia os cinco validadores em zero no fechamento. Lidas
uma a uma, oito são frases que registram a queda de um número (“Os R$ 867 saem do documento”,
“a saída dos R$ 867”, “nunca citou os R$ 867”, “não existem em fonte nenhuma”, “carregava”,
“descrevia”) ou o valor correto da peça de PLA (R$ 18,48) num parágrafo que também fala do B2B.
A nona é prosa defasada de verdade: 01-custo-de-entrada.md diz que o YAML do modelo “ainda
carrega os R$ 867 no piso da faixa”, e o YAML regerado em 06/09/2026 tem R$ 1.000.
A decisão foi em duas partes. O perdão do validador ganhou as formas que faltavam, e a frase, e
não o parágrafo, passou a decidir se um valor ambíguo fala do B2B; o teste de não regressão
continua acusando “R$ 47,69” e “R$ 867” escritos como vigentes. A frase defasada ficou acusada,
registrada em _meta/lacunas.md, porque o acervo não se edita para um validador passar. O
validador fecha a task 7 com uma ocorrência, e ela é verdadeira.
A regra que fica: validador que acusa nove e acerta uma não se desliga nem se aceita; lê se as nove, corrige se a heurística onde ela erra e deixa se em pé o que ela acertou.