Style errors double when nobody enforces them.
TL;DR: Wire your standards into hooks, skills, and a judge, so the harness blocks violations before a human opens the diff.
You paste your coding standards into AGENTS.md and trust the AI to remember them.
Then a human reviewer manually checks naming, indentation, and spacing on every pull request.
Nobody wires a hook, a skill, or a judge that blocks the diff before a human ever opens it.
The standards live in prose, and prose is optional.
Standards enforcement isn't new.
Stephen C. Johnson wrote the first lint in 1978 to catch mistakes in C code that nobody wanted to check by eye.
Checkstyle, PMD, and ESLint followed, each one refusing to trust a human to notice a mixed indentation.
SonarQube added a server that gates a whole pipeline, not just a single file.
Mago does the same for PHP now, running a linter, a formatter, and a static analyzer in one Rust binary fast enough to run on every keystroke.
None of these tools ever asked a human to vote on a tab versus a space or a mixedCase versus snake_case name.
AI coding didn't remove that need.
It multiplied it.
A CodeRabbit analysis of 470 pull requests found AI-generated code carries about 1.7x more defects overall than human-only code.
Naming and style consistency errors came in at nearly 2x, the exact class of mistake a linter was built to catch decades ago.
A model can now write in any human language, misspell an identifier, or reorder parameters inconsistently across two files that it never compared side by side.
A linter still catches the syntactic version of these mistakes.
The semantic version, like a name that lies about its role, needs a judge who reads intent, not just tokens.
That's where an LLM-as-judge step fits: a second AI pass, wired into the same harness that runs the linter, checking the rules no regular expression can express.
Skills are the natural home for that judge.
A skill reads the standards file fresh every time, instead of trusting a memory that decays across sessions.
Pair the judge with a criteria check before the task ends, so the AI can't say a task is done until the standards gate reports zero violations.
A gate that blocks the diff is just another way to force the AI to obey you, not by asking nicely, but by refusing to let a violation through.
This doesn't replace reviewing every line before commit.
It removes the mechanical part of that review, so a human is free to judge design instead of counting spaces.
When the judge catches a new violation, log it the same way you'd log a pitfall, so the harness never makes that mistake twice.
Please follow our coding standards for this feature.
Use consistent naming and formatting like the rest of the codebase.
I'll check it during code review before we merge.
Before you say this task is done, run this standards checklist:
- [ ] Run the linter on every changed file, fix every violation.
- [ ] Run the formatter, don't hand-format a single line.
- [ ] Invoke the code-standards-validator skill on the full diff.
- [ ] Check every identifier: no abbreviations, no misleading names.
- [ ] Check indentation matches the project config, no mixed tabs.
- [ ] Check casing: one convention, no mixedCase next to snake_case.
- [ ] Check parameter order against other functions in the file.
- [ ] Check spelling in every identifier, comment, and string.
- [ ] Judge comment quality: flag dead comments and restated code.
- [ ] Judge naming intent: does each name say what it does?
- [ ] Confirm no file mixes languages in identifiers or comments.
- [ ] Log any new violation type as a rule for the next run.
- [ ] Don't report the task done until every box above is checked.
Show me the completed checklist, not just the final code.
A linter still beats an LLM judge on speed and cost for anything syntactic.
Reserve the judge for rules that need intent, not tokens.
A gate that blocks too aggressively gets bypassed with --no-verify, which defeats the whole point.
Review the judge's false positives the same way you'd review a flaky linter rule.
[X] Semi-Automatic
An LLM judge costs tokens and time on every gate, so it doesn't replace a linter.
It complements one.
A judge can disagree with itself across two runs on borderline style calls, so keep the deterministic rules in the linter and reserve the judge for what's genuinely ambiguous.
[X] Intermediate
A linter never asks permission to reject bad code.
Neither should your harness.
Wire the standards into hooks, skills, and a judge, so the diff gets rejected before a human ever has to say so.
The views expressed here are my own.
I am a human who writes as best as possible for other humans.
I use AI proofreading tools to improve some texts.
I welcome constructive criticism and dialogue.
I shape these insights through 30 years in the software industry, 25 years of teaching, and writing over 500 articles and a book.
This article is part of the AI Coding Tip series.