Open source: código revisado por quem não me conhece
O que entrou e o que está na fila
Em agosto de 2026 eu comecei a mandar correção para projeto que não é meu. Não como exercício: escolhendo defeito de verdade, escrevendo o teste que falha sem a correção, e mandando pelo processo que cada projeto pede, o que em alguns casos quer dizer abrir issue primeiro e esperar resposta antes de escrever uma linha.
As duas tabelas abaixo são o estado de tudo, lido da API do GitHub e regravado por um script deste site. Mesclado é mesclado. Em revisão pode virar qualquer coisa, inclusive nada. Mesclado e em revisão nunca aparecem somados, porque essa soma seria a primeira mentira fácil desta página.
Um deles fecha um laço. O BetonQuest é um plugin de missões para servidor de Minecraft, e a primeira coisa que eu tentei programar, aos dez anos, foi um mod de Minecraft que não deu em nada. Dessa vez o código entrou.
Onde o código entrou
Os mais fortes entre os 44 projetos
que já mesclaram correção minha. O critério não é só a contagem: o
pnpm com um pull request diz mais a quem lê do que um
projeto de dois que ninguém reconhece. A lista dos
68, com recusados e substituídos,
abre no fim da seção.
| Projeto | O que é | Mesclados | Em revisão |
|---|---|---|---|
| warren | painel de controle para agentes de código que rodam isolados | 29 | 0 |
| isomorphic-git | git escrito em JavaScript, rodando no navegador | 16 | 0 |
| orval | gera cliente tipado a partir de OpenAPI | 13 | 0 |
| lexical | o framework de editor de texto do Meta | 10 | 0 |
| kaneo | gestão de projeto open source | 5 | 0 |
| postal | agente de código de terminal, escrito em Python | 4 | 0 |
| zigbee2mqtt | ponte entre dispositivo Zigbee e MQTT, sem bridge proprietária | 4 | 0 |
| urwid | biblioteca de interface de terminal em Python | 4 | 0 |
| redocly-cli | valida, junta e publica descrição OpenAPI | 2 | 1 |
| pnpm | gerenciador de pacote que não duplica dependência em disco | 2 | 0 |
| pino | o logger que roda debaixo do Fastify | 1 | 1 |
| MathCAT | converte matemática em fala e braile para leitor de tela | 1 | 0 |
| luigi | framework de micro frontend, mantido pela SAP | 1 | 0 |
Abrir a lista inteira: 68 projetos, um por um
Projetos que aceitaram
| Projeto | O que é | Mesclados | Em revisão | Recusados | Substituídos |
|---|---|---|---|---|---|
| warren | painel de controle para agentes de código que rodam isolados | 29 | 0 | 0 | 0 |
| isomorphic-git | git escrito em JavaScript, rodando no navegador | 16 | 0 | 0 | 0 |
| RustPython | interpretador de Python escrito em Rust, que também roda em WebAssembly | 15 | 0 | 0 | 0 |
| orval | gera cliente tipado a partir de OpenAPI | 13 | 0 | 0 | 0 |
| lexical | o framework de editor de texto do Meta | 10 | 0 | 0 | 0 |
| coreutils | o ls, o cp e o resto dos utilitários do GNU reescritos em Rust | 6 | 0 | 0 | 0 |
| compiler-explorer | roda compilador no navegador e mostra o assembly que sai | 5 | 3 | 0 | 0 |
| mongoose | a camada de modelagem que quase todo Node com MongoDB usa | 5 | 0 | 0 | 0 |
| kaneo | gestão de projeto open source | 5 | 0 | 0 | 0 |
| skillfile | busca e instala skills de agente, e registra qual versão está onde | 4 | 1 | 0 | 0 |
| postal | agente de código de terminal, escrito em Python | 4 | 0 | 0 | 0 |
| zigbee2mqtt | ponte entre dispositivo Zigbee e MQTT, sem bridge proprietária | 4 | 0 | 0 | 0 |
| urwid | biblioteca de interface de terminal em Python | 4 | 0 | 0 | 0 |
| CodeceptJS | framework de teste ponta a ponta | 3 | 0 | 0 | 0 |
| hls.js | toca streaming HLS no navegador, sem plugin | 3 | 0 | 0 | 0 |
| undici | o cliente HTTP dentro do fetch do Node | 2 | 3 | 0 | 5 |
| redocly-cli | valida, junta e publica descrição OpenAPI | 2 | 1 | 0 | 0 |
| brush | shell compatível com bash e POSIX, escrito em Rust | 2 | 1 | 0 | 0 |
| gitlab-ci-local | roda o pipeline do GitLab CI na própria máquina | 2 | 0 | 0 | 0 |
| loopx | kernel de estado para times de agentes de IA que rodam por muito tempo | 2 | 0 | 0 | 0 |
| marked | converte Markdown em HTML, e é o conversor que muita ferramenta embute | 2 | 0 | 0 | 0 |
| pokerogue | RPG de navegador com batalha de Pokémon e mapa que muda a cada partida | 2 | 0 | 0 | 0 |
| pnpm | gerenciador de pacote que não duplica dependência em disco | 2 | 0 | 0 | 0 |
| react-jsonschema-form | monta formulário React a partir de um JSON Schema | 2 | 0 | 0 | 0 |
| syft | lê a imagem de contêiner e lista tudo que tem dentro dela | 1 | 1 | 0 | 0 |
| grafana | o painel de observabilidade que quase toda empresa tem aberto | 1 | 1 | 0 | 0 |
| playwright-skill | automação de navegador com Playwright, empacotada como skill de agente | 1 | 1 | 0 | 0 |
| openeverest | provisionamento e gestão de banco de dados, automatizados | 1 | 1 | 0 | 0 |
| pino | o logger que roda debaixo do Fastify | 1 | 1 | 0 | 0 |
| BetonQuest | plugin de missões para servidor de Minecraft, com diálogo e condição | 1 | 0 | 0 | 0 |
| MathCAT | converte matemática em fala e braile para leitor de tela | 1 | 0 | 0 | 0 |
| sigma-rule-deployment | leva regra de detecção Sigma para o alerta do Grafana | 1 | 0 | 0 | 0 |
| ciso-assistant | gestão de risco e conformidade, com os controles de ISO 27001 e NIST | 1 | 0 | 0 | 0 |
| sunsynk | lê inversor solar Deye e Sunsynk dentro do Home Assistant | 1 | 0 | 0 | 0 |
| zigbee-herdsman-converters | as definições de dispositivo que o zigbee2mqtt usa para entender cada aparelho | 1 | 0 | 0 | 0 |
| likec4 | arquitetura de sistema escrita como código e desenhada a partir dele | 1 | 0 | 0 | 0 |
| luigi | framework de micro frontend, mantido pela SAP | 1 | 0 | 0 | 0 |
| herb | ferramentaria para HTML com ERB, o template do Rails | 1 | 0 | 1 | 0 |
| pyright | o verificador de tipo de Python que roda dentro do VS Code | 1 | 0 | 0 | 0 |
| mloda | acesso a dado para IA e ML, por plugin e com rastro de origem | 1 | 0 | 0 | 0 |
| plur | memória compartilhada entre agentes de IA | 1 | 0 | 0 | 0 |
| black | o formatador de código de Python que não aceita configuração | 1 | 0 | 0 | 0 |
| semantica | infraestrutura de grafo para contexto de agente | 1 | 0 | 0 | 0 |
| webdriverio | automação de navegador e celular para teste | 1 | 0 | 0 | 0 |
Em revisão, recusados e substituídos
Recusado e substituído não são a mesma coisa. Recusado quer dizer que o mantenedor fechou o pull request. Substituído quer dizer que fui eu, porque o mesmo conserto virou outro pull request no mesmo projeto. Somar os dois diria que o projeto me disse não onde ele pediu outra coisa.
| Projeto | O que é | Em revisão | Recusados | Substituídos |
|---|---|---|---|---|
| payload | CMS headless em Next.js | 5 | 0 | 1 |
| luxon | datas e fusos em JavaScript, sucessor do Moment | 2 | 0 | 0 |
| axios | o cliente HTTP mais usado do JavaScript | 1 | 0 | 0 |
| freebuff | agente de código de linha de comando | 1 | 1 | 0 |
| discord.js | a biblioteca sobre a qual a maior parte dos bots de Discord é escrita | 1 | 0 | 0 |
| DSpace | repositório digital que universidade usa para publicar acervo e pesquisa | 1 | 0 | 0 |
| open-design | alternativa aberta e local ao Claude Design | 1 | 0 | 0 |
| node | o runtime de JavaScript fora do navegador | 1 | 0 | 0 |
| nx | sistema de build para monorepo, que só recompila o que mudou | 1 | 0 | 0 |
| pygments | colore código em centenas de linguagens, e é o que o Sphinx e o Jekyll usam | 1 | 0 | 0 |
| mypy | o verificador de tipo estático do Python, mantido junto do projeto da linguagem | 1 | 0 | 0 |
| rollup | o bundler de módulos ES | 1 | 0 | 0 |
| storybook | monta, documenta e testa componente de interface isolado | 1 | 0 | 0 |
| strapi | CMS headless em JavaScript | 1 | 0 | 0 |
| supabase | Postgres gerenciado com API, auth e storage | 1 | 0 | 0 |
| svelte | o compilador de interface | 1 | 0 | 0 |
| next.js | o framework React da Vercel | 1 | 0 | 0 |
| zwave-js | fala o protocolo Z-Wave a partir do Node, para automação residencial | 1 | 0 | 0 |
| angular | o framework de aplicação web do Google | 0 | 1 | 0 |
| apollo-client | o cliente GraphQL do Apollo | 0 | 1 | 0 |
| celery | a fila de tarefa em segundo plano do mundo Python | 0 | 0 | 1 |
| three.js | a biblioteca de 3D no navegador | 0 | 1 | 0 |
| nest | framework de back-end em Node, com a arquitetura em módulo que o Angular popularizou | 0 | 1 | 0 |
| opensre | kit para montar agente que investiga incidente de produção | 0 | 1 | 0 |
A mesma chave quebrada em 10 projetos
__proto__ não é um nome de propriedade como os outros.
Num objeto literal, o['__proto__'] = x não guarda nada:
troca o protótipo do objeto. E ler o['__proto__'] devolve
o protótipo herdado, não um valor que alguém pôs ali. Todo lugar que
monta um dicionário a partir de string que veio de fora tem esse
buraco, e o buraco é sempre o mesmo.
Achei o primeiro num logger e fui atrás dos outros:
15 pull requests em
10 projetos: axios,
svelte, apollo-client, angular, storybook, next.js, undici
(6 só nele), pino, orval
e lexical. No axios e no undici a string é um
cabeçalho HTTP, ou seja, vem de quem estiver do outro lado da conexão.
Não é curiosidade de laboratório.
o[ns].push(nextPath)
return o
// The keys here are the first segment of each redact path, so they are the
// user's strings. On a plain object a path like 'constructor.secret' reads
// the inherited function, and `o[ns] = o[ns] || []` keeps it.
}, Object.create(null))
// the redactor assigned to the format symbol key
// provides top level redaction for instances where
// an object is interpolated into the msg string
// Same reason as the shape above: the keys come from the redact paths, and
// this object is later indexed with them by `asJson`.
const result = Object.assign(Object.create(null), {
[redactFmtSym]: Redact({ paths, censor, serialize, strict, remove })
})
Os comentários desse trecho são meus e estão em inglês, porque o repositório é de outra pessoa. É a mesma regra que vale aqui ao contrário: os comentários deste site estão em português porque quem mantém sou eu.
As 4 que entraram foram junto com o teste que falha sem elas. Nenhum mantenedor pediu. É o que faz o revisor conseguir dizer sim sem precisar confiar em mim.
No undici o mantenedor pediu para juntar os call sites num
pull request só, em vez de um por lugar. Fechei os
4 e abri o
#5688, com a
guarda num util em vez de quatro cópias da mesma função. Eles estão na
tabela como substituídos, e não como recusados, porque não foram
recusados: "o mantenedor não quis" e "o mantenedor quis de outro jeito"
não são a mesma coisa.
16 pull requests mesclados dentro do git de outra pessoa
O isomorphic-git é git de verdade, escrito em JavaScript
puro, rodando dentro do navegador.
16
correções minhas entraram nele e outras
0
estão na fila. As que mexem em comportamento estão na lista abaixo. A
que falta nela é um ajuste na integração contínua deles, que entrou
junto:
core.autocrlfnão era respeitado quando ostatuscalculava o hash da cópia de trabalho: no Windows, arquivo em que ninguém tocou aparecia como modificado.splitLinespartia um CRLF que caísse bem na fronteira entre dois pedaços do fluxo, e uma linha virava duas.- o
.gitignoreera aplicado também a arquivo já rastreado, que é justamente o caso em que o git manda ignorar o ignore. - expandir uma ref varria junto os arquivos de sistema do git.
- uma tag anotada cujo alvo o filtro de prefixo tinha removido derrubava a leitura inteira.
- credencial escrita dentro da URL passou a ser lida pelo parser WHATWG, em vez de por expressão regular.
- a sintaxe no estilo scp com usuário diferente de
gitnão era reconhecida. checkoutcomfilepathse semrefrestaurava doHEADem vez do índice, e jogava fora o que estava no stage.- com
core.symlinksdesligado o git materializa o link simbólico como arquivo comum, e o mapa de links das fixtures do navegador saía vazio.
Tem uma piada na segunda dessa lista. Este site já documentava um primo dela antes de qualquer um desses pull requests existir: a checagem que confere o hash da política de segurança normaliza CRLF para LF antes de calcular, porque o que vai ao ar é LF, e quem já apanhou de fronteira de CRLF reconhece a marca.
O que ainda está em revisão
A maior parte dos pull requests continua aberta,
37 deles, e a página diz isso em vez
de arredondar. Em alguns projetos a fila é longa por bom motivo: o
undici roda dentro do fetch do Node, e errar
ali custa caro para muita gente.
Eu tenho número para essa espera porque medi. O merge-odds amostra os últimos cem pull requests fechados de um projeto e calcula que fração veio de autor de fora: nos que ele mediu, a taxa vai de um terço a nove décimos. Pull request aberto não é pull request aceito, e taxa alta descreve cem pessoas que não são você.
7 foram recusados, e estão na
tabela pelo mesmo motivo dos outros. No
apollo-client eu abri a issue antes, como a política deles
pede, marquei o pull request com o emoji de robô que eles exigem de
contribuição assistida por IA, e discuti a solução com o mantenedor,
inclusive para dizer que um dos meus três testes estava errado, e por
quê. Ele fechou como “solution in search of a
problem”: queria ver o defeito machucando alguém em produção,
não só em teoria. É uma régua justa, e ela vale para o resto desta
página também.
As outras foram mais curtas. No angular o mantenedor
respondeu que já havia um pull request esperando revisão para o mesmo
defeito, que é o melhor motivo que existe para fechar o meu. No
opensre fecharam sem comentar nada, e eu não sei por quê.
E o que é meu
Esta página é o que eu mando para projeto que não é meu. O outro lado, o que eu publico e outra pessoa instala, saiu daqui e ganhou página própria: o que eu publico. São duas bibliotecas no npm e dois plugins de Claude Code, e um deles é o merge-odds citado ali em cima.