AI code conventions for shared repos that stay readable
AI code conventions help teams keep mixed human and model output clear. Cover naming, comments, tests, reviews, and ownership rules.

Why mixed code gets messy fast
A shared repo gets hard to read when people and models write in different styles. One file uses short function names and no comments. The next uses long names, broad comments, and tests that follow a different pattern. Before anyone can judge the logic, they have to decode the style.
That drift starts early and spreads fast. Most developers copy the code closest to the change. If one generated helper uses vague names, the next helper often does too. If one pull request adds noisy comments, that tone can take over a folder in days.
The problem shows up in regular work. A developer opens a bug ticket, searches the repo, and finds three ways to do the same thing. Reviewers spend time fixing naming and comment style instead of checking behavior. New team members take longer to learn what "good" looks like because the repo gives mixed signals.
Ownership makes the mess worse when it is unclear. If a generated test fails, who fixes it? The person who merged it, the person who wrote the prompt, or the teammate who owns that service? When nobody can answer that quickly, fixes sit in review queues and small bugs keep coming back.
Even a simple example shows the cost. A model adds an API handler with different error names, a comment that says nothing, and tests in the wrong folder. The code may still work, but the next person now has to guess which pattern the team actually wants. That guesswork slows everything down.
Pick the ground rules first
Before anyone pastes a prompt into a coding tool, the team should decide where AI can help and where it cannot. That sounds strict, but it saves time.
Start with file boundaries. Many teams are fine with AI drafting tests, small UI pieces, internal tools, and low-risk docs. They block it from database migrations, auth, billing, secrets, deployment files, and anything that could damage data or security in one bad merge.
A short written rule set is enough:
- List the file types AI can edit without special approval.
- List the file types a person must write or heavily rewrite.
- Mark the changes that always need a second human review.
- State when draft docs or comments are fine and when they are not.
Human review should never be optional for code that changes schemas, permissions, public APIs, or incident handling. Reviewers should check more than syntax. They should ask whether the code fits the repo style, uses the right names, and adds only the layers the team actually needs.
Comments need limits too. Generated comments often explain the obvious, repeat the code, or sound more certain than the code deserves. Keep comments for intent, odd business rules, and real gotchas. If a comment only says what the next line does, delete it.
The same goes for docs. Let AI draft them if you want, but require a person to rewrite anything that will guide future work. A rough draft is fine. A vague page nobody trusts is not.
If model output sounds unlike the rest of the repo, invents helper functions the team would never keep, or uses names that break your normal patterns, rewrite it. Most useful rules are simple boundary rules. Once they are written down, review gets easier and arguments get shorter.
Set naming rules people can follow
If people and AI both write code in the same repo, naming drifts fast. One file says user_service.ts, another says UserHelpers.ts, and a third hides work in misc.ts. That kind of mess slows reviews more than teams expect.
Pick one style for each layer and write it down. File names should match the language norm. Functions should use verbs. Variables should use plain nouns. Booleans should start with is, has, or can.
Short names need rules too. id and url are fine because everyone knows them. cfg, tmp, and proc are usually too vague unless the scope is tiny and obvious. If a new hire has to stop and guess, the name is too short.
Avoid clever names. Jokes, internal slang, and broad buckets like utils, helpers, data, or manager hide intent. A good name tells the reviewer what the code does before they even open the file. createInvoiceDraft, retryCount, isArchived, and billing_report.ts are clear. doStuff, x, flag, and misc.ts are not.
If your repo spans languages, keep the meaning consistent even when casing changes. A TypeScript function and a Go function can follow local style, but both should describe the same action in the same words. That gives the model fewer chances to invent a new naming pattern.
Boring names win. They improve search, speed up reviews, and make handoffs less annoying.
Keep comments short and useful
Most bad comments age faster than code. When the code already says what it does, the comment should stay out of the way. A line that explains price * quantity adds nothing. A line that explains why you round before saving, or why you retry only once, can prevent a bad edit later.
This matters even more in mixed human and model output. Generated code often arrives with too many comments, and many of them say nothing. They restate function names, describe obvious loops, or add friendly filler nobody needs. Cut those first. They make a file look longer and less clear than it is.
Use comments for intent, limits, and odd choices. If a rule comes from finance, a vendor API, or a messy migration, say that in one or two plain sentences. That gives the reader context without turning the file into a manual.
TODO and FIXME notes need a little discipline too:
- Use TODO for planned work with a real owner.
- Use FIXME for a known bug, risky shortcut, or broken edge case.
- Add a name, team, or ticket tag.
- Remove notes that nobody plans to act on.
Module headers can help, but only when a file would confuse a new reader without one. Good examples include adapters around old systems, files with strict ordering rules, or modules that hide a vendor quirk. Keep the header short: what the module does, one limit, and one assumption if the reader needs it.
Short comments are one of the easiest rules to enforce, and one of the most useful. They speed up reviews, reduce noise, and leave room for the few notes that actually prevent mistakes.
Define test rules before merge
If a change alters what users see or what the app accepts, ask for a test in the same pull request. That rule keeps mixed human and model-written code honest, especially when the code looks neat but changes behavior in small ways.
Test names should describe behavior, not internals. A name like "uses formatOrderDate" says very little. "Shows the order date in local time on the receipt page" is better because anyone on the team can understand what broke.
Keep test names close to the user story. Six months later, the suite should still teach readers what the product does, not just how one helper worked at the time.
Snapshot tests help in narrow cases. They work for stable markup, generated config files, or email templates where full output matters. They are weak for permissions, pricing, or branching business rules, where a large snapshot can hide a real bug inside a wall of changed lines.
Most teams do well with a small floor for behavior changes. Cover the normal case, one bad input or failed action, one boundary case such as empty data or max length, and the visible error or fallback state if users can hit it.
That does not mean every pull request needs a huge test pack. A text change on a static page may need nothing. A new checkout rule, import parser, or access check needs more than a happy-path test.
One review question catches a lot of weak pull requests before they land: "What behavior changed, and where is that covered?"
Make ownership visible
Clear ownership should sit next to your repository rules, not in someone's head. Mixed human and model output gets messy when nobody knows who makes the final call.
Each area of the repo needs one named owner. That can be a person on a small team or a team name on a larger one, but it still needs to point to a real reviewer who answers questions and decides when code is ready.
A simple setup works well:
- Give every service, package, or folder a named owner.
- Send AI-heavy pull requests to a small review group that is good at judging generated code.
- When code moves to another team, require a short handoff note and a new owner.
- Record who approved any style exception.
This matters most when generated code crosses boundaries. A model can rename files, move logic, or add tests in areas the author barely knows. If billing code changes during an auth refactor, the billing owner should review it even if the pull request started somewhere else.
Teams also need a handoff rule. If one group builds a feature and another group will maintain it, make the transfer explicit. Name the new owner, note the date, and add one short summary of what changed and what still looks risky.
Style exceptions need the same visibility. If someone approves a different naming pattern, skips a test rule, or keeps an odd comment because a generator depends on it, write down who approved it. Months later, that note saves a lot of guesswork.
Oleg Sotnikov often works with lean teams where a few people cover a large codebase. In that setup, visible ownership is not paperwork. It is how small teams keep review quality high without slowing every merge.
Use a simple pull request flow
Most review problems start before anyone opens the pull request. If the task is vague, AI will fill gaps with guesses, and reviewers will spend their time untangling intent instead of checking the code.
Start each change with a short task note and a few acceptance points. Keep them plain: what should change, what should not change, and how someone can tell the work is done.
The flow does not need to be fancy. Define one small scope. Generate or write code only for that scope. Clean up awkward names and unnecessary comments before review. Run tests. Remove noisy diffs such as unrelated formatting churn. Then open the pull request with a brief note on where AI helped.
That last part matters more than people think. Reviewers do not need a transcript. They need a quick summary such as: AI drafted the handler, suggested test cases, and rewrote comments. Now they know where to look harder.
Scope is the part teams skip most often. A pull request that changes a parser, rewrites tests, renames files, and updates docs all at once is tiring to review even if the code is fine. Smaller pull requests make mixed human and model output easier to trust.
Before review, fix the obvious rough edges yourself. If a comment explains what the code already says, delete it. If a generated name feels awkward, rename it. The point is not to prove AI wrote something useful. The point is to make the final pull request easy for another person to read, test, and own.
A realistic example from a shared repo
A small team adds one feature: users can pause weekly invoice reminder emails for 7 days. Sam writes the product note and edge cases first. The model drafts the first pass of the code, and Sam edits it before opening a pull request.
The repo already uses one rule for this area: every file uses the same domain name, invoiceReminder. That keeps the feature easy to scan. The pull request touches invoiceReminderService.ts, useInvoiceReminder.ts, invoiceReminderService.test.ts, and InvoiceReminderPanel.tsx.
Nothing uses emailPause, reminderToggle, or some other side name. A reviewer can search one phrase and see the whole feature without guessing.
Sam also keeps the comments thin. The model first added lines like "This function checks whether reminders should be sent." The reviewer cuts that and asks for one useful comment instead: why the service rounds the pause window to midnight. That note helps the next person. Five obvious comments do not.
Ownership removes the usual delay. The repo marks notifications as Priya's area, so the review request goes straight to her when Sam opens the pull request. She does not need to guess who should approve it, and Sam does not need to tag three people just in case.
Priya checks three things: the names match the rest of the repo, the tests cover the 7-day pause and the boundary cases, and the one comment explains the only surprising choice.
She approves after one small rename. pauseUntil becomes reminderPauseUntil because that is the term the repo already uses. That tiny edit is the point. Mixed human and model output stays readable when the team protects small rules every time.
Quick checks before you merge
A fast review catches most of the mess these rules are meant to prevent. You do not need a long audit. You need a few blunt checks that keep the code readable.
- Match new names to the repo style.
- Cut comments that only repeat the code.
- Make tests prove the changed behavior.
- Name the owner in the pull request summary.
- Ask whether a rewrite is cheaper than another review pass.
This review does not need to feel heavy. In a small pull request, the decision is often obvious. If a generated helper uses odd names, adds three empty comments, and ships with no test for the bug it claims to fix, the problem is not subtle.
One more check helps: look for code that nobody wants to touch next month. That is usually the clearest sign that the pull request is not ready. Clean code does not need perfect wording or clever structure. It needs clear names, useful tests, and a human owner who will still recognize it later.
Mistakes that cause trouble later
Teams often create bigger problems by letting the model invent a new style in every folder. One package uses short function names, another switches to long abstract names, and a third adds helper files nobody asked for. After a few weeks, the repo feels patched together. People spend time decoding style instead of reading logic.
Long generated comments create a different kind of clutter. They look helpful when the code is fresh, but most of them repeat what the next line already says. A block of text above every function makes real warnings harder to spot. Short comments work better because people actually read them.
Ownership slips through the cracks too. A team merges generated code into a shared area, but nobody marks who owns that part of the repo. Later, a bug shows up and everyone hesitates. One engineer wrote the prompt, another reviewed the pull request, and a third deployed it. If nobody owns the area, even small fixes become slow and awkward.
Passing tests can hide bad decisions. Tests may prove that code returns the expected value, but they do not show whether the naming is confusing, whether the new code copies old logic, or whether the next edit will be painful. Generated code can pass the suite and still make the repo harder to maintain.
The last mistake is writing rules so strict that people stop following them. If a tiny change needs too many labels, approvals, or template fields, the team will cut corners. Good rules fit on one page, make sense in daily work, and leave room for judgment. If people ignore a rule more than once, fix the rule.
Next steps for your team
Most teams do better when they stop debating edge cases and write down a short default. Keep it to one page. If a rule needs a long defense, it is probably too hard to follow in a busy repo.
Your team standard only needs to answer a few recurring questions: how AI-generated code should be named, when comments are required or removed, what tests must exist before merge, who owns the code after it lands, and how reviewers should flag mixed human and model output.
Start with one active repo, not the whole company. Pick a codebase that gets regular pull requests and has at least two reviewers. That gives you enough traffic to see where the rules help and where they only add friction.
Then try the standard on two or three real pull requests. Do not judge it in theory. One PR may expose noisy comments. Another may show that your test rules are too loose or too strict. Real work reveals the weak spots quickly.
After that, edit the document once. Cut anything people ignored. Clarify anything reviewers argued about twice. If a rule did not change a decision, remove it. Good standards are easy to remember and boring to apply.
If your team needs outside help, keep the ask narrow. A focused review of naming, comments, tests, and ownership rules can prevent weeks of cleanup later. Oleg Sotnikov helps startups and small teams with practical engineering policy and AI-first development workflows, and his work at oleg.is fits this kind of hands-on review well.
Frequently Asked Questions
What files should we keep off-limits for AI edits?
Start with low-risk work such as tests, small UI changes, internal tools, and draft docs. Keep people in charge of migrations, auth, billing, secrets, deploy files, and anything that can break data or security in one merge.
How do we stop naming drift in a shared repo?
Write one naming rule for each layer and stick to it. Use verbs for functions, plain nouns for variables, and booleans like isActive or hasAccess. If a new name makes someone stop and guess, rename it before review.
When should we remove AI-generated comments?
Delete them when they only repeat the code or fill space with obvious notes. Keep comments only for intent, odd business rules, limits, or a choice that would confuse the next person.
What tests should every behavior change include?
Ask for a test whenever the change affects what users see, what the app accepts, or how a rule works. Cover the normal path, one failure or bad input, and one boundary case so the pull request proves the behavior changed on purpose.
Are snapshot tests enough for AI-written code?
No. Snapshots help for stable output like markup, email templates, or generated config, but they hide bugs in permissions, pricing, and branch-heavy rules. For those cases, write direct behavior tests with plain names.
Who owns AI-generated code after it lands?
Give each folder, service, or package one named owner before problems show up. After merge, that owner answers questions, reviews follow-up changes, and decides when an exception makes sense.
What should reviewers check besides whether the code works?
They should check fit, not just correctness. Look at names, comments, test coverage, folder placement, and whether the code adds extra layers the repo does not need. Working code still hurts a team when it reads unlike everything around it.
How should we mention AI use in a pull request?
Keep it short and concrete. Say what AI drafted, what you rewrote by hand, and where reviewers should look harder. A one-line note gives enough context without turning the pull request into a prompt log.
Why do mixed human and AI pull requests become hard to review?
Usually the scope got too wide. A pull request that rewrites names, moves files, changes behavior, and updates docs at the same time forces reviewers to guess intent. Smaller changes with cleaned-up diffs are much easier to trust.
How do we roll out these rules without slowing the team down?
Start with one active repo and write a one-page default. Try it on a few real pull requests, then cut rules people ignore and tighten rules that miss obvious problems. If the process feels heavy for small changes, simplify it.