Open source: code reviewed by people who don't know me
What got in and what is in the queue
In August 2026 I started sending fixes to projects that are not mine. Not as an exercise: picking real defects, writing the test that fails without the fix, and sending it through whatever process each project asks for, which in some cases means opening an issue first and waiting for a reply before writing a line.
The two tables below are the state of everything, read from the GitHub API and rewritten by a script on this site. Merged is merged. In review can turn into anything, including nothing. Merged and in review never appear added together, because that sum would be this page's first easy lie.
One of them closes a loop. BetonQuest is a quest plugin for Minecraft servers, and the first thing I ever tried to program, at ten years old, was a Minecraft mod that came to nothing. This time the code made it in.
Where the code landed
The strongest of the 44 projects
that have merged a fix of mine. Count is not the only criterion:
pnpm with one pull request says more to a reader than a
project with two that nobody recognizes. The full list of
68, rejected and superseded
included, opens at the end of the section.
| Project | What it is | Merged | In review |
|---|---|---|---|
| warren | a control plane for coding agents running in isolation | 29 | 0 |
| isomorphic-git | git written in JavaScript, running in the browser | 16 | 0 |
| orval | generates a typed client from OpenAPI | 13 | 0 |
| lexical | Meta's text editor framework | 10 | 0 |
| kaneo | open source project management | 5 | 0 |
| postal | a terminal coding agent written in Python | 4 | 0 |
| zigbee2mqtt | a bridge from Zigbee devices to MQTT, with no proprietary hub | 4 | 0 |
| urwid | a terminal user interface library for Python | 4 | 0 |
| redocly-cli | lints, bundles and publishes OpenAPI descriptions | 2 | 1 |
| pnpm | a package manager that doesn't duplicate dependencies on disk | 2 | 0 |
| pino | the logger underneath Fastify | 1 | 1 |
| MathCAT | turns math into speech and braille for screen readers | 1 | 0 |
| luigi | a micro frontend framework, maintained by SAP | 1 | 0 |
Open the full list: 68 projects, one by one
Projects that accepted
| Project | What it is | Merged | In review | Rejected | Superseded |
|---|---|---|---|---|---|
| warren | a control plane for coding agents running in isolation | 29 | 0 | 0 | 0 |
| isomorphic-git | git written in JavaScript, running in the browser | 16 | 0 | 0 | 0 |
| RustPython | a Python interpreter written in Rust, which also runs in WebAssembly | 15 | 0 | 0 | 0 |
| orval | generates a typed client from OpenAPI | 13 | 0 | 0 | 0 |
| lexical | Meta's text editor framework | 10 | 0 | 0 | 0 |
| coreutils | ls, cp and the rest of the GNU utilities rewritten in Rust | 6 | 0 | 0 | 0 |
| compiler-explorer | runs compilers in the browser and shows the assembly they emit | 5 | 3 | 0 | 0 |
| mongoose | the modelling layer almost every Node app with MongoDB uses | 5 | 0 | 0 | 0 |
| kaneo | open source project management | 5 | 0 | 0 | 0 |
| skillfile | finds and installs agent skills, and tracks which version is where | 4 | 1 | 0 | 0 |
| postal | a terminal coding agent written in Python | 4 | 0 | 0 | 0 |
| zigbee2mqtt | a bridge from Zigbee devices to MQTT, with no proprietary hub | 4 | 0 | 0 | 0 |
| urwid | a terminal user interface library for Python | 4 | 0 | 0 | 0 |
| CodeceptJS | end-to-end testing framework | 3 | 0 | 0 | 0 |
| hls.js | plays HLS streaming in the browser, with no plugin | 3 | 0 | 0 | 0 |
| undici | the HTTP client inside Node's fetch | 2 | 3 | 0 | 5 |
| redocly-cli | lints, bundles and publishes OpenAPI descriptions | 2 | 1 | 0 | 0 |
| brush | a bash and POSIX compatible shell, written in Rust | 2 | 1 | 0 | 0 |
| gitlab-ci-local | runs GitLab CI pipelines on your own machine | 2 | 0 | 0 | 0 |
| loopx | a state kernel for long-running AI agent teams | 2 | 0 | 0 | 0 |
| marked | turns Markdown into HTML, and is the converter many tools embed | 2 | 0 | 0 | 0 |
| pokerogue | a browser RPG with Pokémon battles and a map that changes every run | 2 | 0 | 0 | 0 |
| pnpm | a package manager that doesn't duplicate dependencies on disk | 2 | 0 | 0 | 0 |
| react-jsonschema-form | builds a React form out of a JSON Schema | 2 | 0 | 0 | 0 |
| syft | reads a container image and lists everything inside it | 1 | 1 | 0 | 0 |
| grafana | the observability dashboard almost every company keeps open | 1 | 1 | 0 | 0 |
| playwright-skill | Playwright browser automation packaged as an agent skill | 1 | 1 | 0 | 0 |
| openeverest | automated database provisioning and management | 1 | 1 | 0 | 0 |
| pino | the logger underneath Fastify | 1 | 1 | 0 | 0 |
| BetonQuest | a quest plugin for Minecraft servers, with dialogue and conditions | 1 | 0 | 0 | 0 |
| MathCAT | turns math into speech and braille for screen readers | 1 | 0 | 0 | 0 |
| sigma-rule-deployment | ships Sigma detection rules into Grafana Alerting | 1 | 0 | 0 | 0 |
| ciso-assistant | risk and compliance management, with ISO 27001 and NIST controls | 1 | 0 | 0 | 0 |
| sunsynk | reads Deye and Sunsynk solar inverters inside Home Assistant | 1 | 0 | 0 | 0 |
| zigbee-herdsman-converters | the device definitions zigbee2mqtt uses to understand each appliance | 1 | 0 | 0 | 0 |
| likec4 | system architecture written as code and drawn from it | 1 | 0 | 0 | 0 |
| luigi | a micro frontend framework, maintained by SAP | 1 | 0 | 0 | 0 |
| herb | an HTML-aware toolchain for ERB, Rails' template language | 1 | 0 | 1 | 0 |
| pyright | the Python type checker running inside VS Code | 1 | 0 | 0 | 0 |
| mloda | data access for AI and ML, plugin-based and with lineage | 1 | 0 | 0 | 0 |
| plur | shared memory across AI agents | 1 | 0 | 0 | 0 |
| black | the Python code formatter that refuses to be configured | 1 | 0 | 0 | 0 |
| semantica | graph infrastructure for agent context | 1 | 0 | 0 | 0 |
| webdriverio | browser and mobile automation for testing | 1 | 0 | 0 | 0 |
In review, rejected and superseded
Rejected and superseded are not the same thing. Rejected means the maintainer closed the pull request. Superseded means I closed it, because the same fix became another pull request in the same project. Adding the two together would say the project told me no where it asked for something else.
| Project | What it is | In review | Rejected | Superseded |
|---|---|---|---|---|
| payload | headless CMS on Next.js | 5 | 0 | 1 |
| luxon | dates and time zones in JavaScript, Moment's successor | 2 | 0 | 0 |
| axios | the most used HTTP client in JavaScript | 1 | 0 | 0 |
| freebuff | a command-line coding agent | 1 | 1 | 0 |
| discord.js | the library most Discord bots are written on top of | 1 | 0 | 0 |
| DSpace | the digital repository universities use to publish collections and research | 1 | 0 | 0 |
| open-design | an open, local-first alternative to Claude Design | 1 | 0 | 0 |
| node | the JavaScript runtime outside the browser | 1 | 0 | 0 |
| nx | a monorepo build system that only rebuilds what changed | 1 | 0 | 0 |
| pygments | highlights code in hundreds of languages, and is what Sphinx and Jekyll use | 1 | 0 | 0 |
| mypy | Python's static type checker, maintained alongside the language project | 1 | 0 | 0 |
| rollup | the ES module bundler | 1 | 0 | 0 |
| storybook | builds, documents and tests UI components in isolation | 1 | 0 | 0 |
| strapi | headless CMS in JavaScript | 1 | 0 | 0 |
| supabase | managed Postgres with API, auth and storage | 1 | 0 | 0 |
| svelte | the UI compiler | 1 | 0 | 0 |
| next.js | Vercel's React framework | 1 | 0 | 0 |
| zwave-js | speaks the Z-Wave protocol from Node, for home automation | 1 | 0 | 0 |
| angular | Google's web application framework | 0 | 1 | 0 |
| apollo-client | Apollo's GraphQL client | 0 | 1 | 0 |
| celery | the background task queue of the Python world | 0 | 0 | 1 |
| three.js | 3D in the browser | 0 | 1 | 0 |
| nest | a Node backend framework, with the module architecture Angular made popular | 0 | 1 | 0 |
| opensre | a toolkit for building agents that investigate production incidents | 0 | 1 | 0 |
The same broken key in 10 projects
__proto__ is not a property name like the others. In an
object literal, o['__proto__'] = x doesn't store
anything: it swaps the object's prototype. And reading
o['__proto__'] returns the inherited prototype, not a
value someone put there. Every place that builds a dictionary from a
string that came from outside has this hole, and the hole is always
the same one.
I found the first one in a logger and went after the rest:
15 pull requests across
10 projects: axios,
svelte, apollo-client, angular, storybook, next.js, undici
(6 in that one alone),
pino, orval and lexical. In axios and undici the
string is an HTTP header, meaning it comes from whoever is on the
other end of the connection. It's not a lab curiosity.
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 })
})
The comments in this excerpt are mine, and they're in English, because the repository belongs to someone else. It's the same rule in reverse here: the comments on this site are in Portuguese, because I'm the one who maintains it.
The 4 that got merged came together with the test that fails without them. No maintainer asked for it. That's what lets the reviewer say yes without having to trust me.
In undici the maintainer asked me to fold the call sites
into a single pull request instead of one per site. I closed the
4 and opened
#5688, with
the guard in one util instead of four copies of the same function.
They sit in the table as superseded, and not as rejected, because they
weren't rejected: "the maintainer didn't want it" and "the maintainer
wanted it another way" are not the same thing.
16 merged pull requests inside someone else's git
isomorphic-git is real git, written in pure JavaScript,
running inside the browser.
16
of my fixes made it in, and another
0
are in the queue. The ones that change behavior are in the list below.
The one missing from it is a fix to their continuous integration, which
went in with them:
core.autocrlfwasn't respected whenstatushashed the working copy: on Windows, a file nobody had touched showed up as modified.splitLinessplit a CRLF that happened to land right on the boundary between two stream chunks, and one line became two..gitignorewas applied to files already tracked too, which is exactly the case where git says to ignore the ignore.- expanding a ref swept up git's own system files along with it.
- an annotated tag whose target the prefix filter had removed brought down the entire read.
- a credential written inside the URL is now read by the WHATWG parser, instead of a regular expression.
- scp-style syntax with a user other than
gitwasn't recognized. checkoutwithfilepathsand norefrestored fromHEADinstead of from the index, throwing away whatever was staged.- with
core.symlinksoff, git materializes a symlink as a regular file, and the browser fixtures' symlink map came out empty.
There's a joke in the second item on this list. This site already documented a cousin of it before any of these pull requests existed: the check that verifies the security policy's hash normalizes CRLF to LF before hashing, because what actually ships is LF, and anyone who has been bitten by a CRLF boundary before recognizes the mark.
What is still in review
Most of the pull requests are still open,
37 of them, and the page says so
instead of rounding up. In some projects the queue is long for a
good reason: undici runs inside Node's
fetch, and getting it wrong there is expensive for a
lot of people.
I have a number for that wait because I measured it. merge-odds samples a project's last hundred closed pull requests and works out what fraction came from an outside author: in the ones it measured, the rate runs from a third to nine tenths. An open pull request is not an accepted pull request, and a high rate describes a hundred people who are not you.
7 were rejected, and they are in
the table for the same reason as the
rest. On apollo-client I opened the issue first, as
their policy asks, tagged the pull request with the robot emoji they
require for AI-assisted contributions, and discussed the fix with
the maintainer, including to say that one of my three tests was
wrong, and why. They closed it as “solution in search of a
problem”: they wanted to see the bug hurting someone in production,
not just in theory. It is a fair bar, and it holds for the rest of
this page too.
The others were shorter. On angular the maintainer
replied that a pull request for the same bug was already waiting for
review, which is the best reason there is to close mine. On
opensre they closed it without a comment, and I do not
know why.
And what is mine
This page is what I send to projects that are not mine. The other side, what I publish and other people install, moved out of here and got its own page: what I publish. Two npm packages and two Claude Code plugins, one of them the merge-odds quoted above.