Unchallenged Authority & Double Standards

This essay is a first-person account. It was written, challenged, and revised multiple times to separate legitimate critique from self-serving narrative. If the direct address feels like rehearsal — the author arguing with someone who is not in the room — the accompanying case study presents the same evidence in third person, without advocacy.


What Happened

I submitted a pull request to an open source project recently — a small, recently public library for distributed Python work — proposing a coordinated protocol upgrade. The changes replaced polling with blocking reads, inlined small results to eliminate network round-trips, swapped JSON with base64 encoding for msgpack, and introduced wire protocol versioning via a version byte to enable future upgrades without breaking existing deployments. The production delta was 214 lines. The remaining 80% of the diff was test code: 43 unit tests, integration tests, and load tests. The PR included benchmarks, a structured breakdown, and detailed commit messages explaining every decision.

The maintainer closed it without reviewing the code. He then permanently banned me from the organisation after a single exchange in which I politely asked how I should contribute instead. This essay is about what that rejection reveals: a leader enforcing standards he does not follow, governing by authority he has never had to justify.


The Exchange

The maintainer’s initial response:

I’m closing this PR. Some of the ideas here are good, but this is not the right way to approach improving production code like this. PRs need to be inspired by real-world issues, not an LLMs assessment of bad implementation.

  • This is a huge green diff, that’s bad! [repo] is mini!
  • Public tests is a good idea, but should start with a single full integration test in CI
  • some of these improvements make sense, but PRs need a single improvement at the time

My response:

Your assessment doesn’t make complete sense to me.

This is a breaking change upgrade of the protocol - there are going to be changes that need to happen at once. Most of the green diff is 80% test code, which is what you’d want for an upgrade like this. msgpack is a negligible addition to the dependencies that doesn’t have any dependencies itself - it’s the right tool for the job. The production line changes are 214 lines, which I think is reasonable.

msgpack changing the wire format and inline results requiring the new message types in that wire format are interdependent changes. If I split msgpack and inline results, you’d have two breaking changes instead of one coordinated upgrade.

Regarding the BLOP changes (10 lines), I agree it should be a separate PR. And yes, I could’ve opened an issue first to discuss the upgrade. However, I think the PR itself is still valid.

With regards to your comment about being inspired by ‘real-world issues’ to make changes, it doesn’t really make sense to me. Polling with time.sleep(0.1) instead of blocking reads, unnecessary network round-trips for small payloads, and base64-encoding binary inside JSON are textbook inefficiencies. One of the first things I look at on projects like this is the communication protocol.

Sure, I had an LLM write many of the changes. However, I think enough people would understand why I submitted the PR for these changes. If the PR doesn’t fit your process, let me know how to follow it rather than just ditching the changes at first glance.

You closed this without offering a path forward, and I think that is unfair. I understand you might be busy, and [organisation] might not want to accept code for the production systems from an unknown contributor; however, this is the point of PR reviews.

Would you be open to a smaller PR that addresses only the BLPOP polling?

Cheers, Jacob

The maintainer’s final response, accompanied by a permanent ban:

I permanently blocked you from [organisation]. As I said, the ideas are good, I don’t like JSON either. Using central redis for small results is a good idea.

However, ALL PRs to ALL software projects need to be inspired real-world issues. If you make “technical” improvements that don’t address a current use case of a real user, you’re wasting everyone’s time. You’re adding complexity and most likely introducing bugs someone else has to deal with no known improvement. Does the json overhead matter in the use-cases miniray is used? Is it worth the added lines and making the readable parts of the string unreadable in ASCII? You have no idea, because you’re not a real user nor have you made any attempt to be one.

The only exception to this rule is when you have PRs that simplify the code with clean red diffs. Obviously not the case here.


Not Prepared

When you make a repository public, you are inviting the world in. If you are not ready to receive contributions — if you have no process for handling them, no framework for evaluating them, no capacity to engage with a stranger who takes your project seriously — then you are not ready to be public. There is no CONTRIBUTING.md. No issue templates. No documented process. The project was not prepared for external contribution, and when one arrived, the maintainer treated it as an intrusion rather than a consequence of his own decision to open the door.

Every rule he cited — PRs must address real-world issues, changes must come one at a time, contributors must be existing users — was improvised in the moment of rejection. These may be reasonable norms. But norms that only surface when someone violates them are not norms. They are reactions. And a leader who governs by reaction is a leader who was not prepared to lead.

If you want contributors to follow a specific process, the minimum requirement is that the process be discoverable before someone violates it. Anything less is enforcing rules that only insiders know — which is not quality control. It is social sorting.


The Double Standard

The maintainer’s own commits to the same repository, from the same day he rejected my PR, tell a different story about his relationship to the standards he enforced.

He pushed directly to master with no PR review. He reverted his own commits within an hour. His commit messages included “why custom alerts” — a question, not an explanation — alongside “simpler,” “much simpler,” and “No leeway, crack the whip!” None of these describe what changed or why. One is a motivational poster.

The contrast is instructive. My PR included a detailed description with benchmarks, commit messages explaining each decision, a structured breakdown of interdependent changes, and 43 documented tests. His own contributions were cowboy commits to master with no review, and messages that are either cryptic or aspirational.

This is not someone enforcing standards. This is someone enforcing hierarchy. Insiders push to master with commit messages that explain nothing. Outsiders get rejected for providing too much documentation and too many tests. The stated concern is quality. The actual mechanism is social standing.


The Real Objection

The “LLM-generated” comment was not about code quality. It was a gut reaction to something that looked too polished from someone without standing in the project. The real objection was not “this code is bad” but “who are you to submit this?”

That is a legitimate gatekeeping stance for a private project. Maintainers have finite time. Not every contribution merits engagement. But you do not get to dress hierarchy up as process concerns when your own commit history stands against the notion of standards at all. If your actual position is “I don’t accept contributions from people I don’t know,” say that. Write it down. It is an honest position. What is dishonest is rejecting a contribution on fabricated procedural grounds while exempting yourself from every procedure you cite.

The maintainer said the code “most likely” introduces bugs. But he did not review the code. He did not point to a single line. He did not identify a gap in test coverage. He assumed bugs exist because the contributor was unknown, which is not unreasonable as a prior — but the entire function of a PR review is to update that prior by actually reading the work. He skipped that step and treated his assumption as sufficient. “There are probably bugs” is not a review. It is a dismissal wearing a reviewer’s clothing.


The Catch-22

The maintainer’s strongest claim was that contributions must come from “real users” addressing “real-world issues.” But the project is a 24-star repository that was only recently made public. It has two forks. The documentation describes nothing about use cases, deployment patterns, or the problems it solves for its users.

This creates a closed loop. You cannot become a real user because there is no documentation explaining what a real user does. You cannot learn the contribution norms because they are not written down. You cannot engage with the community because the community is one person who bans strangers after a single interaction. The requirement to be an insider before contributing is a requirement that no outsider can fulfil — which means it is not a contribution standard. It is a closed door with an “Open” sign on it.

The timing argument compounds the contradiction. The maintainer invoked “existing users” to justify rejection, but also called me out for not being a “real user” of what is essentially internal tooling. Both framings cannot be true simultaneously. Either there is a meaningful external user base whose needs I should have considered, or the project is too internal for outsiders to understand. He selected whichever framing supported rejection in the moment, which is not reasoning — it is rationalisation.

If anything, the project’s early stage argued in favour of the PR. The project is versioned at v0.1 — breaking changes are expected at this stage. Few external users means low cost of those changes. Early in the public lifecycle is the ideal time to address protocol debt. Less accumulated complexity means cleaner refactoring. If you are going to swap out JSON with base64 for msgpack, you want to do it before people build on top of it, not after.

The PR also introduced wire protocol versioning — a version byte in the msgpack header that would allow future upgrades without breaking existing deployments. The upgrade could have been released on a separate branch, and any existing users would simply reference the version they need. This is how software works. The maintainer’s concern about breaking users was not only premature for a v0.1 project — the PR itself addressed it with a versioning mechanism he never reviewed.


The Response

Whether I should have submitted the PR the way I did is a separate question from how the maintainer responded to it. Even if the contribution was poorly sequenced — and it was — the response should have been proportionate. A real review engages with the substance. “Line 47 doesn’t handle the timeout edge case.” “Missing test for malformed msgpack payloads.” “The wire format change breaks backward compatibility in a way that matters for our deployment.” These are responses. What I received was a rejection based on priors that were never tested against the actual work — followed by a permanent ban when I asked, politely, how to contribute differently.

The maintainer said twice that the ideas were good. He agreed that JSON was a problem. He acknowledged that inlining small results in Redis made sense. If he genuinely believed this, the obvious next step was to say: “Here’s how to break this into changes I can accept.” That is what leadership looks like — you take something imperfect, recognise its value, and guide it toward a form that works. He did none of that. He agreed with the substance, rejected the contribution, and banned the contributor. That is not a maintainer who thought the ideas were good and the execution was wrong. That is a maintainer who did not want to do the work of engaging, and found it easier to close the door.


The Gap Between Open and Ready

The repository was released without the infrastructure for meaningful external engagement. No contribution guidelines. No documented use cases or architecture. No issue templates. No explanation of what the project does for its users or what problems it considers worth solving. The README said “minimal library for distributed python work” and little else.

I had no reference points to calibrate my contribution against — no way to understand the project’s priorities, its deployment context, or what the maintainer considered in-scope. He had no framework to evaluate a stranger’s PR against — no documented standards to point to, no process to fall back on, no shared language for saying “good direction, wrong approach.” When a contribution arrived that did not fit his unstated expectations, he had nothing to reach for except instinct and authority.

That absence of infrastructure explains how the conversation went wrong. It does not explain what happened next. I asked how to contribute. He made the gap permanent. That is not a failure of preparation. That is a choice.

I am disappointed because I expected better. This is one consequence of having standards. And seeing someone else fail to meet theirs is a useful reminder to maintain my own.


What I Got Wrong

I should have opened an issue first. A breaking protocol change is a conversation before it is a contribution, and arriving with a finished implementation as a first interaction skips that conversation. The maintainer would have been within his rights to say: “Good ideas, wrong sequence — open an issue, let’s discuss the upgrade, then we’ll figure out the right way to land it.”

Instead, I got a rejection without review, standards cited but not followed, and a permanent ban in response to a polite question about how to contribute. The sequencing mistake was mine. Everything that followed was his.


On Not Becoming This

None of my mistakes justify what happened next. Closing without reviewing the code. Citing standards contradicted by your own commit history. Permanently banning someone whose only follow-up was “how should I contribute instead?” Those are not responses to a tactical error. They are the reflexes of someone who has confused authority with competence, and comfort with correctness.

What I witnessed was someone who has been in a position of unchallenged authority long enough that he has forgotten how to be questioned. That is not inevitable. It is a choice made repeatedly over time — every time you shut down instead of engage, every time you enforce rules you do not follow, every time you protect your ego instead of your standards.

The commitments I take from this are simple. Open issues before opening pull requests for breaking changes. Write down the contribution standards you believe in, and follow them yourself. When someone gets it wrong, show them how to get it right. If you close a contribution, offer a path forward. If you are questioned, sit with it. Stay in communities where you are not the authority. Get reviewed. Get rejected. Stay calibrated.

Jacob Sussmilch