<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>spf13</title><link>https://spf13.com/tags/maintenance/</link><description>Recent content on spf13</description><generator>Hugo</generator><language>en-us</language><copyright>Copyright (c) 2008 - 2022, Steve Francia; all rights reserved.</copyright><atom:link href="https://spf13.com/tags/maintenance/index.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Wed, 20 May 2026 10:00:00 -0400</lastBuildDate><item><title>The Maintainer's Dilemma</title><link>https://spf13.com/p/the-maintainers-dilemma/</link><pubDate>Wed, 20 May 2026 10:00:00 -0400</pubDate><guid>https://spf13.com/p/the-maintainers-dilemma/</guid><media:content url="https://spf13.com/p/the-maintainers-dilemma/hero-alt.jpg" medium="image"/><media:thumbnail url="https://spf13.com/p/the-maintainers-dilemma/hero-alt.jpg"/><description>&lt;p>A protected branch requires a second person to review a change before code ships. The rule exists because humans make mistakes, and a second pair of eyes catches what the first one missed. But what happens when one of those reviewers is a robot? What if both are?&lt;/p>
&lt;p>Currently I can ask an AI to open a pull request on my repository and then merge it myself. Or I can write the code and ask an AI to review it. In both cases, the branch is technically &amp;ldquo;protected.&amp;rdquo; But what does that even mean now?&lt;/p></description><content:encoded>&lt;![CDATA[<p><img src="https://spf13.com/p/the-maintainers-dilemma/hero-alt.jpg" alt="The Maintainer's Dilemma"/><p>A protected branch requires a second person to review a change before code ships. The rule exists because humans make mistakes, and a second pair of eyes catches what the first one missed. But what happens when one of those reviewers is a robot? What if both are?</p><p>Currently I can ask an AI to open a pull request on my repository and then merge it myself. Or I can write the code and ask an AI to review it. In both cases, the branch is technically &ldquo;protected.&rdquo; But what does that even mean now?</p><p>Those are questions worth asking. But they tend to get all the attention while a more immediate problem goes unaddressed. Right now, across my repositories, there are open pull requests from people who took time to understand the codebase, write tests, and submit clean patches. I haven&rsquo;t reviewed them. Sadly, the ironic part is I haven&rsquo;t reviewed them because I deeply care. I know how big of a deal it is to take the time to open a pull request on a project, and even more so on a popular one. I know that each one deserves an honest review and that that takes time I don&rsquo;t have for projects I maintain as a volunteer. For every open source project with a funded maintainer, there are millions with an unpaid human staring at a growing backlog, wondering whether the right thing to do is spend their weekend triaging issues or just close the laptop and go outside.</p><p>AI tools can now do credible code reviews, write patches, and triage issues. The question is no longer whether they&rsquo;re good enough to be useful. The real questions are where &ldquo;useful&rdquo; becomes &ldquo;liability,&rdquo; and whether leaning on them breaks something we can&rsquo;t easily rebuild — the trust between maintainers and contributors, the judgment that comes from experience, and the community that forms around that exchange.</p><h2 id="118-open-pull-requests">118 Open Pull Requests</h2><p>I checked my GitHub notifications last week and closed the tab.<a href="https://cobra.dev">Cobra</a> has 243 open issues and 118 open pull requests.<a href="https://github.com/spf13/afero">Afero</a> has 114 issues and 55 PRs. I created both projects. I haven&rsquo;t meaningfully reviewed a PR on either in months.</p><p>In spite of my inaction as a reviewer, these are actively maintained projects. Cobra powers kubectl, GitHub CLI,<a href="https://gohugo.io">Hugo</a>, and hundreds of thousands of other tools. When you type<code>kubectl get pods</code> or<code>gh pr list</code>, Cobra parses your command. Afero sits inside Hugo, inside Cobra itself, inside hundreds of thousands of other projects. A careless merge on Cobra could break Kubernetes tooling. A bad review on Afero could open a filesystem vulnerability that quietly propagates through everything downstream.</p><p>I created Cobra because I needed a specific CLI UX for Hugo and no existing library could support it. I split it out as its own project, thinking others might find it useful. I never imagined I&rsquo;d still be maintaining it a decade later, or that both projects would become critical infrastructure for so many others. I just wanted to build something useful for me and maybe a few friends. But does open sourcing code mean I&rsquo;m obligated to maintain it indefinitely? With each new project I release, there&rsquo;s less time for the existing ones. Some of those PRs have been waiting for years. There&rsquo;s a reported security vulnerability in Afero&rsquo;s<code>BasePathFs</code> that&rsquo;s been sitting open since June 2025 — which, until I wrote this post, I didn&rsquo;t realize was there, because the backlog is that overwhelming.</p><p>The math of maintenance doesn&rsquo;t work. It&rsquo;s a well-known problem across open source (<a href="https://xkcd.com/2347/">relevant XKCD</a>). The number of contributions grows faster than the number of maintainers, and the time required to review each one grows with a project&rsquo;s complexity and impact. Some projects attract volunteer co-maintainers, but that brings its own problem: no one is clearly responsible, so everyone picks what matters to them and the rest just sits. Cobra is intentionally slow to change — too many projects depend on it to casually merge anything — so each change requires more thorough review, not less. Many of my other projects fall into the gray area between maintained and abandoned. I&rsquo;d describe it as optimized maintenance around the most critical paths, but that distinction matters a lot more to me than it does to the person who submitted a fix eight months ago and never heard back.</p><p>This isn&rsquo;t just my problem. GitHub hosts over 420 million repositories. I was very fortunate to be a part of the inaugural cohort of the<a href="/p/cobra-viper-join-github-secure-fund/">Secure Open Source Fund</a> — a real investment that made a real difference. But even after expanding to several cohorts, it covers about 200 projects.<a href="https://securityscorecards.dev">OpenSSF</a> scans a million critical projects weekly.<a href="https://tidelift.com">Tidelift</a> pays maintainers. Add it all up and you&rsquo;re covering thousands of projects. It&rsquo;s meaningful work. It&rsquo;s also a rounding error against the actual surface area.</p><p><a href="https://www.blackduck.com/resources/analyst-reports/open-source-security-risk-analysis.html">Ninety-six percent of codebases contain open source components</a>, and the foundations they build on are maintained by people staring at a backlog they&rsquo;ll never clear, wondering if this is the weekend they finally burn out or just stop checking. And that&rsquo;s before you get to maintainer guilt — the knowledge that people are counting on your work, that you have the capacity to help, but that you can&rsquo;t keep up.</p><h2 id="enter-the-robots">Enter the Robots</h2><figure><img src="/p/the-maintainers-dilemma/mechanical-reviewer.jpg" alt="Brass clockwork automaton inspecting a scroll at a candlelit desk, with a rack of waiting scrolls behind it"/><p>I&rsquo;ve been experimenting with AI tools across a couple of repositories —<a href="https://jules.google.com/">Jules</a> on<a href="https://github.com/spf13/fileflow">fileflow</a> and<a href="https://github.com/spf13/pathologize">pathologize</a>, which have fewer dependencies and more room to try things. I&rsquo;ve also been running<a href="https://github.com/features/copilot">GitHub Copilot</a> on Afero, which has more dependencies, but its modular architecture lets me extend new backends without touching the critical paths other projects depend on.</p><p>I turned Jules loose and watched email after email arrive with new PRs. Looked promising. Then I went on a cruise. While I was at sea, Jules kept going, opening more pull requests each day because I hadn&rsquo;t merged the first ones yet. By the time I got home, I had over 120 PRs across the two projects. I set aside a morning to review them all, only to find they represented roughly five distinct change sets, each submitted daily over several weeks. The PRs themselves weren&rsquo;t wrong, Jules had found real issues. But none were quite right either; each needed course correction before I could merge. With guidance Jules made the adjustments, and the overall direction showed promise. But the experiment so far has created more maintenance work, not less: I had to verify each of those 120 PRs was actually a duplicate before closing it. The tool meant to reduce my backlog had added to it.</p><p>Jules also created these PRs as me, not as Jules — which raises its own questions about attribution and accountability. From the repository&rsquo;s perspective, I authored those changes. But I didn&rsquo;t write a line of them. If one of those patches introduced a bug or a vulnerability, the commit history points to me. Most contributor policies weren&rsquo;t written with this scenario in mind, and the standard CLA doesn&rsquo;t distinguish between code a human wrote and code a human directed an AI to write on their behalf.</p><p>Currently, it appears that Jules has no memory of its own previous work and doesn&rsquo;t have the ability to check open PRs. It scans the repository, finds an issue, opens a PR, and stops. If you don&rsquo;t merge it, Jules finds the same issue next time and opens another PR. It has no way to know you&rsquo;re aware of the problem and haven&rsquo;t merged it for your own reasons: maybe you disagree with the fix, maybe it&rsquo;s lower priority, maybe you&rsquo;re on a boat and won&rsquo;t get to it for a couple weeks. That context is invisible to the tool. Jules found a real vulnerability — TOCTOU bugs in file operations are a genuine class of security problem — and it was right to flag it&hellip; once.</p><figure><img src="/p/the-maintainers-dilemma/jules-duplicate-prs.jpg" alt="GitHub pull request list with dozens of duplicate Jules PRs across fileflow and pathologize"/><p>For the mechanical work — flagging issues, updating dependencies, drafting boilerplate responses — the tools are genuinely useful. But Jules and Copilot couldn&rsquo;t tell me whether one of those 55 Afero PRs belongs in the project at all. That judgment requires knowing the codebase&rsquo;s past and future, not just its present state.</p><p>These tools work only from what&rsquo;s visible: the code, the open issues, the PR history. Maintainers work from the visible and the invisible: the context that never made it into comments, the constraints nobody wrote down, the internal debates that shaped the API. The gap between those two things is where human judgment is most irreplaceable, and where AI is most blind.</p><p>Russ Cox, who I worked with on the Go team, put this well in a<a href="https://groups.google.com/g/golang-dev/c/4Li4Ovd_ehE/m/8L9s_jq4BAAJ">recent discussion</a> about AI contributions: &ldquo;People brag about codebases of hundreds of thousands of lines that have never been viewed by people, churned out in record time. On closer inspection, these codebases invariably turn out to be more like dancing elephants than useful engineering artifacts.&rdquo;</p><p>He&rsquo;s right about novel code. But I keep coming back to the distinction between writing new software and maintaining existing software. Dependency updates aren&rsquo;t dancing elephants. Triaging a stale issue isn&rsquo;t a creative act. Telling a contributor &ldquo;thanks, we&rsquo;re not accepting changes to this API&rdquo; is just keeping the lights on. And right now, for millions of projects, the lights are off.</p><p>That isn&rsquo;t the biggest challenge, though. What most people don&rsquo;t realize is that evaluating and merging changes is far harder than writing new code. Understanding how a change fits into the existing codebase, its history, and its plans requires knowledge that&rsquo;s partly invisible — not in the code, not in the comments, not in the issues. It&rsquo;s in the maintainer&rsquo;s head. And some of it is deeply creative work, requiring the kind of judgment no model can replicate.</p><h2 id="what-protected-actually-protects">What &ldquo;Protected&rdquo; Actually Protects</h2><p>The Go project is genuinely beautiful to me — meticulous reviews, design discussions that ran for months before anything shipped, a review culture refined over 15 years. That&rsquo;s the ideal. But Go is exceptional in ways most projects can&rsquo;t replicate: full-time contributors funded by Google, a mandate to build a language meant to last 50 years, rare external deadline pressure.</p><p>The Go team had a<a href="https://groups.google.com/g/golang-dev/c/4Li4Ovd_ehE/m/8L9s_jq4BAAJ">long thread recently</a> about whether to accept AI-authored contributions — the same discussion where Russ Cox&rsquo;s quote above originated. These are people I worked with for years — same reviews, same proposals, same arguments at the same whiteboards. Reading the thread, I could hear their voices. And I could see how every one of them was right, and why that was the problem.</p><p>Rob Pike went first and didn&rsquo;t equivocate: &ldquo;This is a very slippery slope. Be careful on your first step. I recommend simply saying, no.&rdquo; That&rsquo;s Rob. Direct, principled, and usually right. Then Alan Donovan pointed out the uncomfortable reality: &ldquo;I suspect a significant fraction of CLs we receive today already include fragments of LLM-generated code, whether the authors admit it or not.&rdquo; The horse, in other words, has already left the barn.</p><p>Russ Cox wrote the most thoughtful response I&rsquo;ve seen anyone write about this. His core point: &ldquo;The most important thing we can do is to maintain our usual processes around code review and code quality&hellip; That same bar must still apply when some or all of the code was written with the help of AI-based tools.&rdquo; And: &ldquo;Your responsibilities are not lessened when you use AI tools for your work.&rdquo;</p><p>Every one of these positions is reasonable. And every one of them shares an assumption that exposes the core of the dilemma: they assume there are humans available to review.</p><p>Go can afford to say &ldquo;maintain the same bar&rdquo; because it has full-time contributors funded by Google. It has reviewers. It has a review culture that&rsquo;s been refined for over a decade. Rob can say &ldquo;just say no&rdquo; because Go has enough people to say &ldquo;yes&rdquo; to the important things.</p><p>Afero doesn&rsquo;t. Most open source projects don&rsquo;t. When Rob Pike says no, the Go project keeps functioning. When I say no, the PR just sits there. Those are different kinds of &ldquo;no.&rdquo;</p><p>There&rsquo;s a spectrum, and where you land on it depends on what you&rsquo;re actually choosing between. In practice, maintainers face five options:</p><ol><li>Human writes, human reviews.</li><li>AI writes, human reviews.</li><li>Human writes, AI reviews.</li><li>AI writes, AI reviews, human clicks merge.</li><li>AI writes, AI reviews, AI clicks merge.</li></ol><p>Each step down that list typically trades rigor for velocity, and trust for throughput. But for most projects — certainly for many of mine — there&rsquo;s a sixth option that doesn&rsquo;t appear on that list: human or AI writes, nobody reviews.</p><h2 id="what-were-really-protecting">What We&rsquo;re Really Protecting</h2><figure><img src="/p/the-maintainers-dilemma/the-handshake.jpg" alt="Human and brass clockwork hands reaching toward each other in darkness, with a faint glow between them"/><p>When a maintainer reviews a contributor&rsquo;s PR, there&rsquo;s an unspoken contract. The contributor invested hours understanding the codebase, writing tests, and submitting something clean. The reviewer invests hours evaluating it, pushing back, and suggesting improvements. Both people learn. The reviewer understands a new corner of the project. The contributor gets better at the codebase&rsquo;s idioms. A relationship forms. That exchange is a big part of what makes open source a community instead of just a supply chain.</p><p>Bryan Cantrill at Oxide described this contract precisely in their<a href="https://rfd.shared.oxide.computer/rfd/0576">internal policy on LLM use</a>: ordinarily, &ldquo;it is presumed that of the reader and the writer, it is the writer that has undertaken the greater intellectual exertion.&rdquo; When the writing is AI-generated, &ldquo;this social contract becomes ripped up.&rdquo; The same holds for code review — we expect the reviewer to invest effort because the author invested effort. If neither did, what&rsquo;s the review even for? Oxide&rsquo;s answer is that the human stays accountable regardless; the tool doesn&rsquo;t absorb the responsibility. That&rsquo;s the right instinct. But it assumes someone is actually there to take responsibility.</p><p>For most projects, nobody is. The social contract isn&rsquo;t being broken by AI — it&rsquo;s already being broken by silence. The contributor who submitted a clean, well-tested patch six months ago and never heard back isn&rsquo;t experiencing a degraded version of the ideal. They&rsquo;re experiencing nothing.</p><p>Is a perfect social contract that never happens better than an imperfect one that does?</p><p><span class="highlight-inline">A response from an AI in a day might be more respectful than silence from a human forever.</span></p><h2 id="the-experiment-ahead">The Experiment Ahead</h2><p>I&rsquo;ve decided to find out. I&rsquo;ve been staring at 55 open PRs on Afero long enough to know that deliberation has become its own form of neglect.</p><p>Will AI tools make me more engaged, freeing me to focus on decisions that actually need me? Or will it feel less connected — the human element reduced by one more degree? I don&rsquo;t know how it feels to have an AI review a PR instead of a human, or whether accountability holds when the effort on both sides is diminished. That&rsquo;s the experiment.</p><p>Russ said something else in that thread I keep returning to: &ldquo;The most important thing is to keep thinking. The tools make it very easy to turn off your brain, but if you are careful to avoid that trap, you can produce good work.&rdquo; That&rsquo;s the line I&rsquo;m trying to walk. Let AI handle the volume. Stay responsible for the judgment.</p><p>There&rsquo;s no universal policy that works for both Go and Afero. There shouldn&rsquo;t be.</p><p>The protected branch is still protected. I&rsquo;m just not sure what that even means anymore.</p><p>Have you run into this? I&rsquo;d especially like to hear from maintainers who&rsquo;ve tried AI review — what held, and what broke.</p>
]]></content:encoded></item></channel></rss>