<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: VH Costa</title>
    <description>The latest articles on DEV Community by VH Costa (@vhcosta).</description>
    <link>https://dev.to/vhcosta</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F618204%2F0bf4a81d-0bdc-464b-9404-c4ddb207b84a.jpg</url>
      <title>DEV Community: VH Costa</title>
      <link>https://dev.to/vhcosta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vhcosta"/>
    <language>en</language>
    <item>
      <title>Do Not Be the Courier</title>
      <dc:creator>VH Costa</dc:creator>
      <pubDate>Sat, 09 May 2026 18:36:08 +0000</pubDate>
      <link>https://dev.to/vhcosta/do-not-be-the-courier-13dk</link>
      <guid>https://dev.to/vhcosta/do-not-be-the-courier-13dk</guid>
      <description>&lt;h6&gt;
  
  
  &lt;em&gt;LLMs can help you write code faster. Semantic ownership is what keeps the answer from becoming something you merely carried from one box to another.&lt;/em&gt;
&lt;/h6&gt;




&lt;p&gt;The unsettling part of the Chinese Room is not that the person inside gives bad answers.&lt;/p&gt;

&lt;p&gt;It is that the answers can be good.&lt;/p&gt;

&lt;p&gt;John Searle's thought experiment asks us to imagine a person locked in a room who does not understand Chinese. Sheets of Chinese text arrive under the door. The person has a rulebook, written in a language they do understand, which tells them how to match incoming symbols with outgoing symbols. They follow the instructions, send replies back out, and from the outside it can look as if the room understands Chinese.&lt;/p&gt;

&lt;p&gt;Inside the room, nobody does.&lt;/p&gt;

&lt;p&gt;That is the useful part of the metaphor for programming with AI. Not the entire philosophy-of-mind argument. We do not need to settle whether machines understand anything before breakfast. That way lies tweed, office hours, and a whiteboard with the word "intentionality" written on it like a threat.&lt;/p&gt;

&lt;p&gt;The practical warning is smaller.&lt;/p&gt;

&lt;p&gt;Convincing output can pass through a system without anyone in the loop understanding what it means.&lt;/p&gt;

&lt;p&gt;Sometimes that system is an AI assistant.&lt;/p&gt;

&lt;p&gt;Sometimes it is the person using one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The room is comfortable
&lt;/h2&gt;

&lt;p&gt;AI-assisted programming can feel miraculous when you are learning.&lt;/p&gt;

&lt;p&gt;You paste in an error. It explains the error. You paste in a function. It rewrites the function. You ask what the compiler wants. It gives you something that makes the compiler stop complaining.&lt;/p&gt;

&lt;p&gt;This is useful. There is no virtue in staring at a cryptic error message until character has been built. Character is overrated. Documentation is nicer.&lt;/p&gt;

&lt;p&gt;A good assistant can help you map unfamiliar code, explain vocabulary, suggest test cases, and show you the next thing to inspect. Used well, it compresses the distance between confusion and the first useful question.&lt;/p&gt;

&lt;p&gt;The trouble starts when it also lets you skip the question.&lt;/p&gt;

&lt;p&gt;You do not need to know what the error means if the patch works. You do not need to know why the type changed if the warning disappeared. You do not need to know what the command does if the build finally passes. You can keep sliding paper under the door.&lt;/p&gt;

&lt;p&gt;Input. Output. Input. Output.&lt;/p&gt;

&lt;p&gt;After a while, the workflow has momentum. The code changes. The terminal turns green. The page loads. The assistant sounds confident. The room is warm.&lt;/p&gt;

&lt;p&gt;And you still do not know what happened.&lt;/p&gt;

&lt;p&gt;That is the risk: not confusion, but productive-looking confusion. The kind that moves quickly enough to avoid being inspected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax is not ownership
&lt;/h2&gt;

&lt;p&gt;Programming has always had a syntax trap.&lt;/p&gt;

&lt;p&gt;A beginner learns where semicolons go, how braces nest, how to copy a loop, how to call a function, how to satisfy the compiler for one more minute. That is normal. Everyone starts by moving symbols around before the symbols fully mean anything.&lt;/p&gt;

&lt;p&gt;There is nothing shameful about that stage.&lt;/p&gt;

&lt;p&gt;The shame would be building a home there and naming it senior engineering.&lt;/p&gt;

&lt;p&gt;Syntax matters. The machine is not impressed by your intentions. If the language expects a semicolon, a semicolon-shaped absence will become your afternoon.&lt;/p&gt;

&lt;p&gt;But syntax is the visible skin of the work. Meaning lives underneath it.&lt;/p&gt;

&lt;p&gt;When you write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the important part is not that the line is valid C. The important part is what you believe about &lt;code&gt;count&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What does it count? Can it be negative? How large can it get? Who changes it? What happens if it overflows? Is &lt;code&gt;int&lt;/code&gt; large enough on the platform you care about? Is zero a real value or a sentinel? Does the name match the role it plays in the program?&lt;/p&gt;

&lt;p&gt;The compiler can accept the line without caring about most of that.&lt;/p&gt;

&lt;p&gt;Your program cannot.&lt;/p&gt;

&lt;p&gt;This is where semantic ownership begins.&lt;/p&gt;

&lt;p&gt;Semantic ownership means you can explain what the code means in the context where it runs.&lt;/p&gt;

&lt;p&gt;It is the difference between recognising the shape of an answer and understanding the job that answer is doing.&lt;/p&gt;

&lt;p&gt;You know what the code is supposed to represent, what assumptions it makes, what it changes, and what would count as being wrong.&lt;/p&gt;

&lt;p&gt;That is the difference between carrying an answer and owning one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The code can run while the idea is broken
&lt;/h2&gt;

&lt;p&gt;A passing program is nice.&lt;/p&gt;

&lt;p&gt;It is not a confession of truth from the universe.&lt;/p&gt;

&lt;p&gt;Programs run for many reasons. Some of those reasons are embarrassing.&lt;/p&gt;

&lt;p&gt;A cast can silence a warning while hiding the bug. A larger integer type can postpone overflow without fixing the assumption. A null check can avoid a crash while making the caller's contract meaningless. A copied &lt;code&gt;malloc&lt;/code&gt; example can produce the right output once while leaking memory every time after that. A test can pass because it checks the shape of the answer rather than the promise the code was meant to keep.&lt;/p&gt;

&lt;p&gt;The machine will let you be accidentally correct.&lt;/p&gt;

&lt;p&gt;It has no professional obligation to stop you.&lt;/p&gt;

&lt;p&gt;This gets worse when the first answer arrives with explanations attached. The prose has gravity. It feels like reasoning. Sometimes it is reasoning. Sometimes it is a very elegant path to the wrong house.&lt;/p&gt;

&lt;p&gt;"The code runs" is too weak as a standard.&lt;/p&gt;

&lt;p&gt;A better question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can I explain why this code should be right?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question does not require you to become a compiler engineer before lunch. It does require you to connect the syntax to the meaning.&lt;/p&gt;

&lt;p&gt;If the answer changed a type, what range problem did it solve?&lt;/p&gt;

&lt;p&gt;If the answer added a condition, what state did it protect against?&lt;/p&gt;

&lt;p&gt;If the answer moved validation earlier, what invalid value used to travel too far?&lt;/p&gt;

&lt;p&gt;If the answer changed a build command, what part of the build was missing before?&lt;/p&gt;

&lt;p&gt;If the answer added memory allocation, who owns that memory, and where does ownership end?&lt;/p&gt;

&lt;p&gt;These are not ceremonial questions. They are the work.&lt;/p&gt;

&lt;p&gt;A working patch is only the start of the trail. Understanding is being able to follow the footprints back without needing the assistant to hold the torch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your hunch changes the answer
&lt;/h2&gt;

&lt;p&gt;There is another trap hiding inside the conversation.&lt;/p&gt;

&lt;p&gt;The assistant absorbs your framing.&lt;/p&gt;

&lt;p&gt;Ask a chatbot about a health problem and suggest blood pressure, and it may start arranging the symptoms around blood pressure. Start a different chat with the same symptoms and suggest diet, and it may start arranging the symptoms around diet instead. The prose can sound careful in both cases. It can justify both paths. It can make each hunch feel like the responsible one to investigate.&lt;/p&gt;

&lt;p&gt;That does not make either answer useless.&lt;/p&gt;

&lt;p&gt;It means your suggestion was not neutral.&lt;/p&gt;

&lt;p&gt;The same thing happens in code.&lt;/p&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this a memory leak?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and the assistant may go hunting for ownership problems.&lt;/p&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this an off-by-one error?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and it may start measuring loop bounds with great seriousness.&lt;/p&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this because of async?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and suddenly the callback has motive, opportunity, and a suspicious alibi.&lt;/p&gt;

&lt;p&gt;Sometimes your hunch is right. Hunches are part of debugging. But a suggestible tool can turn a hunch into a tunnel.&lt;/p&gt;

&lt;p&gt;The answer usually arrives with reasons attached. Not just a verdict. A story.&lt;/p&gt;

&lt;p&gt;And stories are sticky.&lt;/p&gt;

&lt;p&gt;Once the assistant has explained why your suspected cause makes sense, you may stop looking for causes that make more sense. The tool did not only give you information. It helped your first guess put on a lab coat.&lt;/p&gt;

&lt;p&gt;This is one reason semantic ownership matters.&lt;/p&gt;

&lt;p&gt;A plausible answer is not enough if your question quietly dragged it into place.&lt;/p&gt;

&lt;p&gt;A better debugging prompt gives the assistant room to disagree with you:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here is the symptom, the relevant code, and what I have already checked. Give me three plausible causes, what evidence would support each one, and what test would separate them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That prompt asks for a map instead of a blessing.&lt;/p&gt;

&lt;p&gt;You can still include your hunch. Just label it as a hunch.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My suspicion is a memory leak, but I do not want to anchor on that. What else could explain this behaviour?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sentence is small, but it changes the shape of the exchange. It reminds both you and the machine that the goal is diagnosis, not agreement.&lt;/p&gt;

&lt;p&gt;Keep some salt nearby.&lt;/p&gt;

&lt;p&gt;Fluent agreement tastes better than it should.&lt;/p&gt;

&lt;h2&gt;
  
  
  Semantic ownership is allowed to be partial
&lt;/h2&gt;

&lt;p&gt;There is a bad version of this argument that turns into macho nonsense.&lt;/p&gt;

&lt;p&gt;Real programmers know every instruction. Real programmers never need help. Real programmers write their own linker in a cave using a magnetised needle and spite.&lt;/p&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Nobody understands every layer all the time. Modern software is a stack of abstractions balanced on older abstractions, vendor promises, historical accidents, and one shell script nobody wants to touch because it has been load-bearing since 2017.&lt;/p&gt;

&lt;p&gt;Using tools is normal. Looking things up is normal. Asking AI for an explanation is normal. Copying a small pattern while you are learning is normal.&lt;/p&gt;

&lt;p&gt;Semantic ownership does not require you to hold the entire machine in your head.&lt;/p&gt;

&lt;p&gt;It means you know which part you are trusting and which part you have checked.&lt;/p&gt;

&lt;p&gt;A developer who says "I do not fully understand the allocator yet, but I know this function returns owned memory and the caller frees it here" is in a better position than one who says "the assistant added &lt;code&gt;free()&lt;/code&gt; and the tests pass".&lt;/p&gt;

&lt;p&gt;The first developer has a boundary.&lt;/p&gt;

&lt;p&gt;The second has a vibe.&lt;/p&gt;

&lt;p&gt;Vibes are lovely in music. They are less lovely in resource management.&lt;/p&gt;

&lt;p&gt;Semantic ownership is often partial. The useful habit is making the boundary explicit.&lt;/p&gt;

&lt;p&gt;I understand this part.&lt;/p&gt;

&lt;p&gt;I am trusting this library contract.&lt;/p&gt;

&lt;p&gt;I have not checked this edge case.&lt;/p&gt;

&lt;p&gt;I need to verify this behaviour on Windows.&lt;/p&gt;

&lt;p&gt;I know this compiles, but I do not yet know why this flag fixes the link step.&lt;/p&gt;

&lt;p&gt;That is not weakness. That is a map.&lt;/p&gt;

&lt;p&gt;The dangerous beginner is not the one who does not know.&lt;/p&gt;

&lt;p&gt;The dangerous beginner is the one who cannot tell where their knowledge ends.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use AI to leave the room
&lt;/h2&gt;

&lt;p&gt;Use AI against the room.&lt;/p&gt;

&lt;p&gt;Ask questions that build your model instead of only repairing the current symptom.&lt;/p&gt;

&lt;p&gt;When you hit an error, do not stop at:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fix this error.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Push for the idea underneath it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Explain what this error means in terms of the type system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When a function looks wrong, avoid treating the rewrite as the finish line:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What assumptions does this function make about its inputs?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When the build fails, ask what promise you broke:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What was the compiler protecting me from here?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you add a test, ask what it proves:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What behaviour should this test protect, and what bug would still slip through?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When an answer looks correct, make the tool attack it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give me three ways this could still be wrong.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That shift changes your role.&lt;/p&gt;

&lt;p&gt;You stop matching inputs to outputs and start using the tool to build the meaning that lets you judge the output.&lt;/p&gt;

&lt;p&gt;The assistant can still be wrong. It can explain beautifully and still hallucinate a function, invent a flag, or describe a version of the library that exists only in the same dimension as perfect project estimates.&lt;/p&gt;

&lt;p&gt;Fine.&lt;/p&gt;

&lt;p&gt;The useful outcome is not obedience to the tool. It is becoming harder to fool.&lt;/p&gt;

&lt;p&gt;A useful AI session should leave residue in your head.&lt;/p&gt;

&lt;p&gt;You should come away with a better name for the problem, a clearer model of the system, one new thing to check, or a sharper reason for the change.&lt;/p&gt;

&lt;p&gt;If the only thing you leave with is a patch, you may still be inside the room.&lt;/p&gt;

&lt;h2&gt;
  
  
  The meaning test
&lt;/h2&gt;

&lt;p&gt;Before you keep an AI-generated change, try the meaning test.&lt;/p&gt;

&lt;p&gt;Move away from the chat transcript and explain the change in boring words.&lt;/p&gt;

&lt;p&gt;What was broken?&lt;/p&gt;

&lt;p&gt;What changed?&lt;/p&gt;

&lt;p&gt;Why should that change fix the problem?&lt;/p&gt;

&lt;p&gt;What did you test?&lt;/p&gt;

&lt;p&gt;What might still be wrong?&lt;/p&gt;

&lt;p&gt;Where would you look if it failed again?&lt;/p&gt;

&lt;p&gt;If you cannot answer those questions, you may not own the change yet.&lt;/p&gt;

&lt;p&gt;The change may still be good. It just arrived before the understanding did.&lt;/p&gt;

&lt;p&gt;So slow down.&lt;/p&gt;

&lt;p&gt;Ask the assistant to explain the missing concept. Read the surrounding code. Check the documentation. Make a tiny experiment. Delete the patch and recreate it from memory. Change the test and see what breaks. Add a print statement. Use the debugger. Do the unglamorous thing that turns a working answer into your answer.&lt;/p&gt;

&lt;p&gt;This is especially important in C, because C is generous in the way a cliff edge is generous. It gives you freedom, then lets you discover gravity at runtime.&lt;/p&gt;

&lt;p&gt;But the rule is not limited to C.&lt;/p&gt;

&lt;p&gt;Every language has a version of this problem. JavaScript will let you misunderstand truthiness. Python will let you misunderstand mutability. SQL will let you misunderstand joins and quietly ruin your afternoon with duplicates. Shell scripts will let you misunderstand quoting, which is less a topic than a haunted forest.&lt;/p&gt;

&lt;p&gt;The details change.&lt;/p&gt;

&lt;p&gt;The ownership problem does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning is the part where meaning catches up
&lt;/h2&gt;

&lt;p&gt;There is a kind of productivity that is really just deferred confusion.&lt;/p&gt;

&lt;p&gt;You move faster today by refusing to understand the thing you will need tomorrow. The debt does not disappear. It waits. Then it charges interest during a bug, a review, an interview, an outage, or one of those evenings where the code you copied becomes the code you have to explain.&lt;/p&gt;

&lt;p&gt;AI can accelerate that debt.&lt;/p&gt;

&lt;p&gt;It can also accelerate the repayment.&lt;/p&gt;

&lt;p&gt;That is the fork.&lt;/p&gt;

&lt;p&gt;Used badly, it gives you answers that outrun your understanding.&lt;/p&gt;

&lt;p&gt;Used well, it gives you handles. A term to search. A mental model. A smaller experiment. A comparison between two approaches. A translation from compiler anger into human language.&lt;/p&gt;

&lt;p&gt;This is why fundamentals still matter.&lt;/p&gt;

&lt;p&gt;Not as tribute to tradition. Not as an initiation ritual where beginners must suffer before they are allowed to build anything fun.&lt;/p&gt;

&lt;p&gt;Fundamentals matter because they give meaning somewhere to land.&lt;/p&gt;

&lt;p&gt;A pointer carries claims about addresses, indirection, lifetime, and ownership. The little &lt;code&gt;*&lt;/code&gt; has a lot of nerve for something that small.&lt;/p&gt;

&lt;p&gt;A compiler error often tells you which promise you failed to make precise. Annoying, yes. Also annoyingly useful.&lt;/p&gt;

&lt;p&gt;A type constrains a value, signals intent, and occasionally acts as a warning label next to a name.&lt;/p&gt;

&lt;p&gt;A test states behaviour you expect to remain true. The green checkmark is only the receipt.&lt;/p&gt;

&lt;p&gt;Once those ideas start connecting, AI becomes more useful. You ask better questions. You reject bad answers faster. You notice when the explanation skips the hard part. You can tell the difference between a fix, a workaround, and a ceremonial pile of tokens arranged to appease the build gods.&lt;/p&gt;

&lt;p&gt;The tool becomes less like the book in the room and more like a way out of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not be the courier
&lt;/h2&gt;

&lt;p&gt;The person in the Chinese Room is not stupid.&lt;/p&gt;

&lt;p&gt;They are doing exactly what the system asks them to do. Symbols come in. Rules get applied. Symbols go out.&lt;/p&gt;

&lt;p&gt;That is why the metaphor is uncomfortable.&lt;/p&gt;

&lt;p&gt;It is possible to be diligent, fast, and still detached from meaning.&lt;/p&gt;

&lt;p&gt;AI-assisted programming can put you in that position quietly. Prompt goes in. Patch comes out. Error goes in. Fix comes out. The loop feels like progress because something is always moving.&lt;/p&gt;

&lt;p&gt;But movement is not understanding.&lt;/p&gt;

&lt;p&gt;At some point, the question has to change from:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What should I paste next?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What do I now understand that I did not understand before?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the difference between using the tool and disappearing into it.&lt;/p&gt;

&lt;p&gt;Do not be the courier for code you cannot read.&lt;/p&gt;

&lt;p&gt;Make the answer pass through your own model of the problem. Give names to the moving parts. Check the assumption the assistant smoothed over. Ask what would prove the fix wrong. Notice when your first hunch is being flattered instead of tested.&lt;/p&gt;

&lt;p&gt;Programming has always required help. Documentation, colleagues, debuggers, search engines, forum threads, weird comments from 2014. The issue is not needing help. The issue is treating fluency as a substitute for meaning.&lt;/p&gt;

&lt;p&gt;Semantic ownership begins when the code is no longer something the room handed back to you.&lt;/p&gt;

&lt;p&gt;It begins when you can point at the answer and say what it means.&lt;/p&gt;

&lt;p&gt;Everything before that is just paper under the door.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>programming</category>
    </item>
    <item>
      <title>Code Is Cheap. Review Isn't.</title>
      <dc:creator>VH Costa</dc:creator>
      <pubDate>Wed, 29 Apr 2026 22:13:19 +0000</pubDate>
      <link>https://dev.to/vhcosta/code-is-cheap-review-isnt-3mja</link>
      <guid>https://dev.to/vhcosta/code-is-cheap-review-isnt-3mja</guid>
      <description>&lt;h6&gt;
  
  
  &lt;em&gt;AI made it easier to produce code-shaped output. Good contribution still means making your work easy to understand, review, and trust.&lt;/em&gt;
&lt;/h6&gt;




&lt;p&gt;You can now produce a pull request in the time it takes to make a coffee.&lt;/p&gt;

&lt;p&gt;Often less.&lt;/p&gt;

&lt;p&gt;This depends on the coffee, obviously. If you grind the beans, heat the water properly, and have opinions about extraction, the pull request may win by a comfortable margin.&lt;/p&gt;

&lt;p&gt;That should make us pause.&lt;/p&gt;

&lt;p&gt;Fast tools are useful. A coding assistant can help you read unfamiliar code, sketch an approach, write a test, or spot an edge case you would have missed. There is no virtue in doing everything the slow way just because it gives the work a faint smell of candle wax and suffering.&lt;/p&gt;

&lt;p&gt;The problem starts when the diff becomes almost free.&lt;/p&gt;

&lt;p&gt;A pull request has never been only a diff. It asks someone else to spend attention, apply judgment, take responsibility, and decide whether this change belongs in a project other people depend on.&lt;/p&gt;

&lt;p&gt;That cost still lands on a human.&lt;/p&gt;

&lt;p&gt;Ashley Wolf on the &lt;strong&gt;GitHub Blog&lt;/strong&gt; recently described open source as entering its own “Eternal September”: contribution friction has dropped, volume is rising, and maintainers are having to respond with better trust signals, triage systems, and project-level controls. The key sentence is brutally simple: “&lt;em&gt;The cost to create has dropped but the cost to review has not.&lt;/em&gt;” (&lt;a href="https://github.blog/open-source/maintainers/welcome-to-the-eternal-september-of-open-source-heres-what-we-plan-to-do-for-maintainers/" rel="noopener noreferrer"&gt;Source: GitHub Blog&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Abigail Mayes, also on the &lt;strong&gt;GitHub Blog&lt;/strong&gt;, made the same point in their writing on mentorship in the AI era, noting that developers merged nearly 45 million pull requests per month in 2025, up 23% year over year. More pull requests. Same maintainer hours. (&lt;a href="https://github.blog/open-source/maintainers/rethinking-open-source-mentorship-in-the-ai-era/" rel="noopener noreferrer"&gt;Source: GitHub Blog&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;That is the bridge from “&lt;a href="https://blog.csystemslab.com/blog/2026-04-26-dont-open-a-pull-request-yet/" rel="noopener noreferrer"&gt;&lt;strong&gt;Don’t Open a Pull Request Yet&lt;/strong&gt;&lt;/a&gt;”. In that piece, the point was: learn the project before asking it to absorb your change.&lt;/p&gt;

&lt;p&gt;This is the next step: once your work reaches a maintainer, make the review cheaper than the diff was to create.&lt;/p&gt;

&lt;h2&gt;
  
  
  A pull request is a question
&lt;/h2&gt;

&lt;p&gt;A pull request looks like a contribution because GitHub gives it a nice interface.&lt;/p&gt;

&lt;p&gt;It has a title. It has a diff. It has a button. It may even have a green checkmark, which is the software equivalent of a tiny approving priest.&lt;/p&gt;

&lt;p&gt;But to a maintainer, a pull request starts as a series of questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Is this needed?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is this correct?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does this fit the project?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What behaviour changes?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What did the author test?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What happens if we merge it and they disappear?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code matters. Broken code is rarely rescued by a charming personality. But the diff alone does not answer enough.&lt;/p&gt;

&lt;p&gt;A one-line change can still be expensive if it arrives without context. Someone has to work out why it exists, whether the issue is real, whether the change is too narrow or too broad, whether it matches the project’s direction, and whether the contributor can respond to review.&lt;/p&gt;

&lt;p&gt;That is why “small PR” and “easy PR” are different things.&lt;/p&gt;

&lt;p&gt;A small PR changes few lines.&lt;/p&gt;

&lt;p&gt;An easy PR reduces guesswork.&lt;/p&gt;

&lt;p&gt;Aim for the second one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The new problem is polished uncertainty
&lt;/h2&gt;

&lt;p&gt;Polished uncertainty is work that looks credible before anyone knows whether it is correct.&lt;/p&gt;

&lt;p&gt;That is the new burden.&lt;/p&gt;

&lt;p&gt;Weak contributions used to look weak faster. Not always. People have been confidently wrong for longer than we have had package managers. But there were usually signs. The issue description was vague. The patch ignored the contribution guide. The author had not read the surrounding code. The proposed fix had that special “I changed the thing that looked closest to the error message” aroma.&lt;/p&gt;

&lt;p&gt;AI changes the packaging.&lt;/p&gt;

&lt;p&gt;A shallow contribution can now arrive with a polite description, a reasonable structure, a test plan, and the emotional posture of a senior engineer in a calm meeting room.&lt;/p&gt;

&lt;p&gt;Lovely.&lt;/p&gt;

&lt;p&gt;Now someone has to find out whether any of it is real.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Register&lt;/strong&gt; recently reported on this shift in &lt;strong&gt;curl&lt;/strong&gt;. Daniel Stenberg, curl’s founder and lead developer, said the project had largely stopped receiving obvious AI-slop security reports. Instead, it was receiving more good-looking, AI-assisted reports, faster than before, which still created a growing workload because maintainers had to verify them. (&lt;a href="https://www.theregister.com/2026/04/06/ai_coding_tools_more_work/" rel="noopener noreferrer"&gt;Source: The Register&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Obvious nonsense is annoying. Plausible uncertainty is expensive.&lt;/p&gt;

&lt;p&gt;When something looks credible, you cannot dismiss it quickly. You have to inspect it, reproduce it, and compare it against the project’s actual behaviour rather than the story around it.&lt;/p&gt;

&lt;p&gt;Developers already know this feeling from their own AI-assisted work. Stack Overflow’s 2025 Developer Survey found that 84% of developers use or plan to use AI tools, while 46% said they do not trust the accuracy of AI output. The most common frustration was AI answers that are “almost right, but not quite”, cited by 66% of developers. (&lt;a href="https://stackoverflow.co/company/press/archive/stack-overflow-2025-developer-survey/" rel="noopener noreferrer"&gt;Source: Stack Overflow&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;“Almost right” sounds harmless until you have lived inside it.&lt;/p&gt;

&lt;p&gt;It means the import exists, but not in this version. The API call is real, but the arguments are wrong. The algorithm works for the example, then quietly eats the edge case. The explanation sounds confident until you realise it skipped the one constraint the whole project cares about.&lt;/p&gt;

&lt;p&gt;Clean code can still be the wrong code. A passing test can still test the wrong promise. A tidy refactor can still erase a weird-looking behaviour that was there because three users, one browser, and a printer from 2011 formed a pact with the underworld.&lt;/p&gt;

&lt;p&gt;Maintainers know this because they have seen the ghosts.&lt;/p&gt;

&lt;p&gt;A contributor who wants to help should respect that. The goal is not to perform confidence. The goal is to make verification cheaper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make verification cheaper
&lt;/h2&gt;

&lt;p&gt;This is the contributor standard I would use now:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A good contribution reduces the amount of guessing required to review it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That applies whether you used AI or not.&lt;/p&gt;

&lt;p&gt;Before you open a pull request, make sure the reviewer can see the path from problem to change. Do not make them reverse-engineer your reasoning from the diff like a crime scene investigator with worse lighting.&lt;/p&gt;

&lt;p&gt;A useful pull request explains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;what problem you are solving&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;where that problem was discussed or observed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;why this change is the right size&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;what alternatives you considered&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;what you tested&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;what could still be wrong&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last part matters.&lt;/p&gt;

&lt;p&gt;A contributor who says “I am least sure about this branch because I could not find an existing test for this behaviour” is easier to review than one who arrives with a polished paragraph of total certainty.&lt;/p&gt;

&lt;p&gt;Total certainty is cheap now. You can generate it in seconds.&lt;/p&gt;

&lt;p&gt;Specific uncertainty is more useful. It tells the maintainer where to look. It shows that you understand the edge of your own understanding. It turns review into collaboration instead of excavation.&lt;/p&gt;

&lt;p&gt;A good pull request does not need a novel attached.&lt;/p&gt;

&lt;p&gt;Please do not write a novel. Maintainers have families, hobbies, pets, and in some tragic cases, other repositories.&lt;/p&gt;

&lt;p&gt;But the PR should contain enough context to be reviewable without guesswork. For many projects, that means five small things.&lt;/p&gt;

&lt;p&gt;First, link the reason. If there is an issue, discussion, bug report, failing test, or documented confusion, point to it. If there is no prior discussion, explain why you are opening code first.&lt;/p&gt;

&lt;p&gt;Second, explain the change in project terms. “Refactored logic” is vague. “Moves validation before normalisation so invalid input fails before it reaches the parser” is useful.&lt;/p&gt;

&lt;p&gt;Third, describe the test. Name the command you ran. Mention the case you added. If you did not test something, say so. Silence does not create confidence. It creates homework.&lt;/p&gt;

&lt;p&gt;Fourth, keep the diff aligned with the claim. If the PR says it fixes one bug, it should not also rename files, reformat half a module, and introduce a new helper because the old one offended your sense of symmetry.&lt;/p&gt;

&lt;p&gt;Fifth, stay available. A pull request is a conversation until it is merged or closed. If you disappear after opening it, the maintainer has to decide whether they are reviewing a contribution or adopting an orphan.&lt;/p&gt;

&lt;p&gt;That is the minimum. Not perfection. Reviewable shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use AI before you ask for attention
&lt;/h2&gt;

&lt;p&gt;There is a good way to use AI in open-source contribution.&lt;/p&gt;

&lt;p&gt;Use it before the public part.&lt;/p&gt;

&lt;p&gt;Ask it to explain unfamiliar code. Ask it to compare two possible fixes. Ask it to list edge cases. Ask it to help you turn messy notes into a clearer issue comment. Ask it what assumptions your approach might be making.&lt;/p&gt;

&lt;p&gt;Then do the work a contributor has always had to do:&lt;/p&gt;

&lt;p&gt;Read the relevant files. Run the tests. Check the project’s conventions. Compare your change with past pull requests. Remove the parts that are too broad. Write the explanation yourself.&lt;/p&gt;

&lt;p&gt;The public artefact should show your understanding, not the tool’s fluency.&lt;/p&gt;

&lt;p&gt;A useful rule:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not submit anything you cannot explain with the tab closed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is responsibility, not purity.&lt;/p&gt;

&lt;p&gt;The maintainer is not merging your chat transcript. They are merging a change into a living project.&lt;/p&gt;

&lt;p&gt;Your name is on the work. Your judgment has to be in it.&lt;/p&gt;

&lt;p&gt;That also gives us a practical rule for disclosure: disclose when AI materially shaped the code, test, security claim, or design choice.&lt;/p&gt;

&lt;p&gt;GitHub’s recent writing on mentorship in the AI era uses three filters for deciding where maintainers should invest attention: comprehension, context, and continuity. Does the contributor understand the problem? Have they given enough information to review the work? Do they keep engaging after the first interaction? (&lt;a href="https://github.blog/open-source/maintainers/rethinking-open-source-mentorship-in-the-ai-era/" rel="noopener noreferrer"&gt;Source: GitHub Blog&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;AI use can affect all three. The point is not to force ritual humiliation. Nobody needs a little badge that says “assisted by robot, spiritually complicated”.&lt;/p&gt;

&lt;p&gt;The point is to help the reviewer calibrate.&lt;/p&gt;

&lt;p&gt;A simple note is enough:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I used an AI tool to help trace the call path and draft the initial test case. I reviewed the final change manually and can explain the touched code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That tells the maintainer where the tool helped, and where your judgment entered the process.&lt;/p&gt;

&lt;p&gt;The dangerous version is unowned work. If the tool wrote something you do not understand, you are handing the project an IOU made of fog.&lt;/p&gt;

&lt;p&gt;Do not do that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boundaries protect useful attention
&lt;/h2&gt;

&lt;p&gt;When projects tighten contribution rules, it is easy to read that as hostility.&lt;/p&gt;

&lt;p&gt;Sometimes it is. Some communities do become opaque, defensive, or needlessly sharp. “Quality standards” can be a real principle, or it can be a decorative shield for bad manners.&lt;/p&gt;

&lt;p&gt;But many boundaries are less dramatic than that.&lt;/p&gt;

&lt;p&gt;They are attention budgets.&lt;/p&gt;

&lt;p&gt;GitHub has shipped repository settings that let maintainers disable pull requests entirely or restrict them to collaborators. It describes these controls as useful for read-only projects, mirrors, or projects that want to share code publicly without managing outside contributions. (&lt;a href="https://github.blog/changelog/2026-02-13-new-repository-settings-for-configuring-pull-request-access/" rel="noopener noreferrer"&gt;Source: GitHub Changelog&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;That sounds severe until you remember the imbalance.&lt;/p&gt;

&lt;p&gt;A contributor may spend ten minutes generating a patch. A maintainer may spend forty minutes proving it does not belong. Repeat that across a popular project, and the “open” in open source starts to feel less like generosity and more like an inbox with a roof leak.&lt;/p&gt;

&lt;p&gt;Clearer rules are not automatically a rejection of newcomers. Done well, they protect the conditions that let good newcomers receive real attention.&lt;/p&gt;

&lt;p&gt;If every drive-by patch gets a careful mentorship session, nobody gets mentored for long.&lt;/p&gt;

&lt;h2&gt;
  
  
  The boring skills got more important
&lt;/h2&gt;

&lt;p&gt;There is a comforting fantasy that better tools make fundamentals optional.&lt;/p&gt;

&lt;p&gt;I would love this to be true. I have many fundamentals I would like to place gently in a lake.&lt;/p&gt;

&lt;p&gt;But better generation makes review skill more important.&lt;/p&gt;

&lt;p&gt;When code appears quickly, you need a stronger model for deciding whether it deserves to stay. That means reading code carefully. Understanding tests. Knowing how data moves. Noticing ownership, boundaries, side effects, and failure modes.&lt;/p&gt;

&lt;p&gt;This is where the C Systems Lab bias enters the room wearing steel-toed boots.&lt;/p&gt;

&lt;p&gt;Low-level programming is not useful because everyone needs to write C every day. Most people do not. The world has suffered enough segmentation faults for several lifetimes.&lt;/p&gt;

&lt;p&gt;It is useful because it makes certain review questions harder to avoid.&lt;/p&gt;

&lt;p&gt;Where does this memory live? Who owns this resource? What happens at the boundary? What does the caller assume? What fails if the input is weird? Which part of the system now has to carry the cost?&lt;/p&gt;

&lt;p&gt;Those questions still matter when the code is written in a friendlier language. They matter even more when the first draft came from a machine that can produce plausible code without understanding the project’s ghosts.&lt;/p&gt;

&lt;p&gt;Machines remain machines, even when the assistant explains them in a soothing voice.&lt;/p&gt;

&lt;p&gt;So yes, learn the boring things. Not because boredom is noble. Boredom is often just bad documentation wearing a tie.&lt;/p&gt;

&lt;p&gt;Learn them because they make you harder to fool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trust is the contribution
&lt;/h2&gt;

&lt;p&gt;The first post ended with a simple idea: good contribution starts before the pull request.&lt;/p&gt;

&lt;p&gt;This one adds the pressure of 2026: the pull request itself is easier to produce than ever, so the work around it matters more.&lt;/p&gt;

&lt;p&gt;Do not let the tool’s fluency become your public judgment. Do not make maintainers guess why your change exists. Do not send code you cannot explain once the tab is closed.&lt;/p&gt;

&lt;p&gt;The diff is the visible part.&lt;/p&gt;

&lt;p&gt;The contribution is the trust you build around it.&lt;/p&gt;

&lt;p&gt;Everything else is just another notification.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Don't Open a Pull Request Yet</title>
      <dc:creator>VH Costa</dc:creator>
      <pubDate>Tue, 28 Apr 2026 23:51:18 +0000</pubDate>
      <link>https://dev.to/vhcosta/dont-open-a-pull-request-yet-14p5</link>
      <guid>https://dev.to/vhcosta/dont-open-a-pull-request-yet-14p5</guid>
      <description>&lt;h6&gt;
  
  
  &lt;em&gt;How to become a genuinely useful open-source contributor before you write a line of code.&lt;/em&gt;
&lt;/h6&gt;




&lt;p&gt;You want to contribute to open source, but you do not want to be &lt;em&gt;that&lt;/em&gt; person.&lt;/p&gt;

&lt;p&gt;Not the one who opens a pointless pull request just to add their name to a &lt;code&gt;README.md&lt;/code&gt;. Not the one who pastes in AI-generated code, wraps it in a polished PR description, and assumes “looks right” means “is right”. And not the one who leaves a maintainer with more work than before they saw your name in the notifications.&lt;/p&gt;

&lt;p&gt;That fear is healthy.&lt;/p&gt;

&lt;p&gt;Because the uncomfortable truth is this: a lot of visible contribution is not useful contribution. A maintainer is rarely asking, “Did this person submit something?” They are asking three quieter questions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is this needed?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Is this correct?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Is this easy to trust?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most weak contributions fail on one of those three points before the code itself matters.&lt;/p&gt;

&lt;p&gt;That is why good open-source contribution starts earlier than most people think. It does not start with a pull request. It starts with context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context comes first
&lt;/h2&gt;

&lt;p&gt;People love to say, “Just find an issue and start.”&lt;/p&gt;

&lt;p&gt;That is fine advice if your goal is activity. It is bad advice if your goal is usefulness.&lt;/p&gt;

&lt;p&gt;A repository is not a bucket of chores waiting for strangers. It is a living system with trade-offs, history, backlog pressure, and people trying to keep it moving. If you open a pull request before you understand any of that, you are not really helping yet. You are asking someone else to assess your judgment.&lt;/p&gt;

&lt;p&gt;That is why tiny, visible changes can still be poor contributions. A one-line diff is not automatically a one-minute ask. Someone still has to read it, place it in context, decide whether it belongs, and often explain why it does not.&lt;/p&gt;

&lt;p&gt;The “add your name to the README” wave made that painfully clear. In February 2024, Express contributors were openly discussing how to curb spammy &lt;code&gt;README.md&lt;/code&gt; pull requests from new contributors because they were creating noise and extra moderation work rather than meaningful progress. &lt;/p&gt;

&lt;p&gt;That gives you a better test than “Can I open a PR?”&lt;/p&gt;

&lt;p&gt;Ask instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Does this change solve a real problem the project actually has? &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can I explain why this approach makes sense here? &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Have I made it easy for someone else to trust what I’m proposing? &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the answer is not yet “yes”, you probably need more context, not more code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the project’s social architecture
&lt;/h2&gt;

&lt;p&gt;Open-source projects do not just have technical architecture. They have social architecture too.&lt;/p&gt;

&lt;p&gt;There is usually a pattern to how decisions get made, how questions get answered, what gets prioritised, and what gets pushed back on. If you miss that layer, you can write a technically decent patch and still make a poor contribution.&lt;/p&gt;

&lt;p&gt;Start with the obvious documents, but treat them as operating instructions rather than admin clutter. Read the &lt;code&gt;README&lt;/code&gt;, contribution guide, issue templates, pull request template, code of conduct, and governance notes. Those pages tell you what kind of help the project wants, where different kinds of discussion belong, and what behaviour creates friction.&lt;/p&gt;

&lt;p&gt;Then look past the documents and study the project in motion.&lt;/p&gt;

&lt;p&gt;Read a few open issues from start to finish. Read a few recently merged pull requests. Then read a few that were closed without merging. That comparison is often more useful than any generic open-source advice because it shows you how this project behaves in practice.&lt;/p&gt;

&lt;p&gt;You will start to notice patterns.&lt;/p&gt;

&lt;p&gt;Maybe small, scoped changes land faster than broad clean-ups.&lt;br&gt;&lt;br&gt;
Maybe maintainers care a lot about tests.&lt;br&gt;&lt;br&gt;
Maybe they want discussion before implementation on larger changes.&lt;br&gt;&lt;br&gt;
Maybe support questions belong somewhere else entirely.&lt;br&gt;&lt;br&gt;
Maybe the project values consistency more than cleverness.&lt;/p&gt;

&lt;p&gt;That is the social architecture. It tells you what “helpful” means &lt;em&gt;here&lt;/em&gt;, not in theory.&lt;/p&gt;

&lt;p&gt;It also changes how you ask questions.&lt;/p&gt;

&lt;p&gt;A weak question hands your confusion to someone else.&lt;br&gt;&lt;br&gt;
A strong question shows the thinking you have already done.&lt;/p&gt;

&lt;p&gt;“Can someone explain this whole module?” is a weak question.&lt;/p&gt;

&lt;p&gt;“I traced this behaviour to this file, and I think this branch is why the bug appears, but I’m not sure whether that behaviour is intentional” is a strong one.&lt;/p&gt;

&lt;p&gt;The second question gives someone something concrete to respond to. It narrows uncertainty instead of exporting it.&lt;/p&gt;

&lt;p&gt;That is the habit you want.&lt;/p&gt;

&lt;h2&gt;
  
  
  Find the project’s pressure points
&lt;/h2&gt;

&lt;p&gt;If the social architecture tells you how the project behaves, the pressure points tell you why.&lt;/p&gt;

&lt;p&gt;From the outside, an open-source project can look like a simple list of issues and pull requests. From the inside, it is usually a bundle of maintenance costs competing for limited attention. Bugs need reproducing. Pull requests need review. Regressions need testing. Releases need preparing. Duplicate reports need closing. Docs need updating.&lt;/p&gt;

&lt;p&gt;That is why project behaviour can look harsher than it really is.&lt;/p&gt;

&lt;p&gt;A slow reply is not always dismissive.&lt;br&gt;&lt;br&gt;
A short reply is not always rude.&lt;br&gt;&lt;br&gt;
A closed issue is not always a judgment on you.&lt;/p&gt;

&lt;p&gt;Sometimes it just means the project has learned to protect scarce attention.&lt;/p&gt;

&lt;p&gt;If you want to be useful, figure out where the pressure actually is.&lt;/p&gt;

&lt;p&gt;If the issue tracker is full of vague reports, a careful reproduction is useful.&lt;br&gt;&lt;br&gt;
If pull requests keep stalling on tests, test work is useful.&lt;br&gt;&lt;br&gt;
If the same confusion keeps appearing in issues, a precise docs fix is useful.&lt;br&gt;&lt;br&gt;
If maintainers keep redirecting people to the same answer, someone who reads first is already easier to work with.&lt;/p&gt;

&lt;p&gt;This is where many contributors go wrong. They choose work that &lt;em&gt;looks&lt;/em&gt; like contribution instead of work that relieves pressure.&lt;/p&gt;

&lt;p&gt;Maintainers do not need more contribution-shaped activity. They need fewer unknowns, fewer unnecessary reviews, and fewer loose ends.&lt;/p&gt;

&lt;p&gt;That is the day-to-day reality you need to acquaint yourself with before you try to change anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the codebase like an investigator
&lt;/h2&gt;

&lt;p&gt;A lot of new contributors open a repository and try to understand the whole thing.&lt;/p&gt;

&lt;p&gt;That is usually wasted effort.&lt;/p&gt;

&lt;p&gt;You do not need total understanding. You need enough local understanding to make a trustworthy change.&lt;/p&gt;

&lt;p&gt;The best way to do that is to read the codebase like an investigator, not a tourist. Start from a concrete question and follow the path that question takes through the system.&lt;/p&gt;

&lt;p&gt;If you are looking at a bug, start where the bug appears and trace inward.&lt;br&gt;&lt;br&gt;
If you are looking at a feature, start where the user encounters it and follow the flow.&lt;br&gt;&lt;br&gt;
If you are looking at an error message, search for the exact text and find where it originates.&lt;/p&gt;

&lt;p&gt;This is much more effective than browsing files until something feels familiar.&lt;/p&gt;

&lt;p&gt;Look for landmarks. Where is the setup logic? Where are the tests? Which modules appear repeatedly in recent pull requests? Are there architecture notes? Are there directories whose names keep coming up in issue discussions?&lt;/p&gt;

&lt;p&gt;Those clues tell you where the important paths are.&lt;/p&gt;

&lt;p&gt;Tests are especially valuable here. They tell you what the project thinks “correct” means. They also show you how contributors are expected to express changes. If you want to understand how a piece of behaviour is meant to work, the test suite often explains it more clearly than the implementation.&lt;/p&gt;

&lt;p&gt;Past pull requests help too. Find a recent change in the same part of the codebase. Read the diff, then read the review comments. You will often learn more from what had to be clarified, shrunk, or reworked than from the final code alone.&lt;/p&gt;

&lt;p&gt;The goal is not to read widely. It is to become specific.&lt;/p&gt;

&lt;p&gt;When you can say, “The bug starts here, seems to flow through these two modules, and is probably covered by this test,” you are in a much better position to contribute.&lt;/p&gt;

&lt;p&gt;Not because you know the whole codebase, but because you know the part you are touching well enough to make your reasoning visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use AI to compress learning, not responsibility
&lt;/h2&gt;

&lt;p&gt;AI is now part of open-source contribution whether people like it or not. The real question is not whether you use it. The question is whether you use it in a way that makes your contribution better or just faster-looking.&lt;/p&gt;

&lt;p&gt;A simple rule cuts through most of the noise:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use AI to compress learning. Do not use it to compress responsibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That means AI can help you understand a pattern, compare approaches, summarise documentation, suggest cases you might want to test, or help you phrase a question more clearly before you post it. CPython’s contributor guide allows this kind of use, while making clear that contributors remain responsible for the usefulness and quality of what they submit. It also says maintainers may close issues and pull requests that are not useful or productive, including ones that are fully generated by AI. &lt;/p&gt;

&lt;p&gt;What AI should not do is become your proxy.&lt;/p&gt;

&lt;p&gt;NumPy’s AI policy is unusually clear: contributors are responsible for any code they submit, whether written manually or generated by AI; they must understand it and be able to explain it. NumPy also says it will reject pull requests it deems “AI slop” and tells contributors not to use AI to automatically generate normal project communication such as issue descriptions, pull request descriptions, or comments. &lt;/p&gt;

&lt;p&gt;That is the right standard because maintainers are not reviewing for local plausibility. They are reviewing for fit.&lt;/p&gt;

&lt;p&gt;Does this solve the real problem?&lt;br&gt;&lt;br&gt;
Does it match the project’s conventions?&lt;br&gt;&lt;br&gt;
Does it introduce churn for little benefit?&lt;br&gt;&lt;br&gt;
Can the author explain why this approach makes sense here?&lt;/p&gt;

&lt;p&gt;AI is often decent at producing plausible-looking code. Plausible-looking code is not the same thing as a good contribution.&lt;/p&gt;

&lt;p&gt;So use AI privately if it helps you think. But do not let it speak for you in public, and do not submit work you cannot defend line by line.&lt;/p&gt;

&lt;p&gt;If you would struggle to answer “Why this change?” in a review, AI has not saved you time. It has just delayed the cost until someone else has to pay it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose work that removes ambiguity
&lt;/h2&gt;

&lt;p&gt;Once you have context, understand the project’s pressure points, and know your way around the relevant code, you still do not need to start with a grand fix.&lt;/p&gt;

&lt;p&gt;Start with the kind of contribution that removes ambiguity.&lt;/p&gt;

&lt;p&gt;That is the sweet spot for first contributions because ambiguity is what drains maintainers. They are constantly trying to work out whether a report is reproducible, whether a bug is current, whether a change is safe, whether a proposed fix matches the project’s direction, and whether a contributor understands what they are touching.&lt;/p&gt;

&lt;p&gt;The best early contributions make those answers easier.&lt;/p&gt;

&lt;p&gt;A strong first contribution might be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a bug report with exact reproduction steps &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a focused test that proves a failure clearly &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a docs fix that removes a common point of confusion &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a small patch in an area you have already traced properly and can explain with confidence &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a careful confirmation that an issue still exists in a current version &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What matters is not whether the change is glamorous. It is whether the thinking is legible.&lt;/p&gt;

&lt;p&gt;That is a better filter than “good first issue”, which can be useful but often hides the real question. The real question is not “Is this easy?” It is “Can I understand this fully enough to make a change that is needed, correct, and easy to trust?”&lt;/p&gt;

&lt;p&gt;That is how you choose a first contribution that actually helps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make it easier to trust you
&lt;/h2&gt;

&lt;p&gt;Good open-source contribution starts earlier than code.&lt;/p&gt;

&lt;p&gt;It starts when you learn how a project makes decisions, where it is under pressure, and what kind of work reduces uncertainty rather than adding more of it. It starts when you read the codebase with a concrete question in mind. And it starts when you use AI, if you use it at all, as a tool for understanding rather than a way to outsource judgment.&lt;/p&gt;

&lt;p&gt;That is the standard worth aiming for.&lt;/p&gt;

&lt;p&gt;Not “I opened a pull request.”&lt;br&gt;&lt;br&gt;
Not “I got something merged.”&lt;br&gt;&lt;br&gt;
But: &lt;strong&gt;I made this project easier to work on.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is what maintainers notice. That is what builds trust. And that is what turns you from someone showing up in the notifications into someone the project is genuinely glad to see.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>beginners</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
