KahWee - Web Development, AI Tools & Tech Trends

What I actually run: Claude Code workflows, static blogs on Cloudflare, React/Vite tooling, and AI cost notes. By KahWee.

AI Is Making Some Code Quality Debates Obsolete

AI is making some code quality debates obsolete. I am less worried about imperfect generated code than I am about asking a teammate to approve code neither of us can explain.

Those are different problems. Teams keep bundling them together as “code quality,” then spend expensive review time litigating taste.

The current models I use produce much better code than the ones I used when I copied snippets out of ChatGPT. The older output often needed a human to sand down every rough edge. I would spend longer simplifying its first attempt than I saved by generating it.

That has changed in my workflow. A strong current model can read a messy change from an older model, identify an unnecessary abstraction, and rewrite it into something smaller. I expect the cost of correcting yesterday's AI code to keep falling.

That makes some technical debt less permanent than it used to be. We should change the review standard accordingly.

A prompt turns constraints into architecture

I usually get a working implementation. The trouble starts when the model treats every detail in my prompt as a first-class system concern.

I describe an airport feature and stress its boundaries: who can access it, when it applies, which cases should not qualify, and what must happen at the edges. The model responds by building gates around every condition. It writes a long ladder of if statements, feature flags, eligibility checks, and fallbacks.

Each condition sounds reasonable in isolation. Together, the code resembles a rule engine that nobody requested.

The model struggles to decide whether those conditions belong in a component, a domain rule, or a policy boundary. It also struggles to distinguish a passing requirement from a constraint that deserves a durable abstraction. It gives similar weight to every sentence because the prompt is its whole specification. A human engineer usually gets that distinction from the roadmap, previous arguments, and the cost of changing the code later.

This creates an awkward review. The working diff contains three layers of gating. A reviewer asks why, and the honest answer is often: “Claude did it.” That explains the origin. It never justifies the design.

The cost has moved from writing to approval

Better future models will clean up a meaningful share of the excess. We should ship some of it and move on.

For a reversible feature, spending an hour polishing a model's awkward first draft can cost more than merging a working change and asking a later model to simplify it when the code proves worth keeping. The rewrite is cheap. The business value arrives sooner.

Reviewers still pay a cost now. They need enough legibility to decide whether the change is safe, matches the product intent, or silently widens the system's behavior. A future model cannot retroactively make today's approval informed.

I lower the bar for polish and keep the bar for comprehension. Generated components do not need beauty on their first merge. Reviewers need explainable control flow and tradeoffs.

I would also separate a real maintenance concern from a team preference dressed up as one. Code review has always carried local taste: whether a helper belongs above or below a component, which abstraction feels clean, and how much indirection looks respectable. Those arguments consume real time because everybody has a mental picture of neat code.

In my experience, AI tends to write toward the most common pattern it has seen. That makes the result less tied to one engineer's private style. Stable, discoverable, cheap-to-change code does not need to satisfy the team's aesthetic ideal.

Every blocking review comment should name the cost it avoids: a failure mode, an ownership boundary, a likely future extension, or a path that will make incidents harder to diagnose. “This feels ugly” is not a cost. If a team wants a style, it should encode it in a formatter, a linter, or a short written convention. It should not rediscover the rule in every pull request.

The same shift is why fast validation matters more in AI workflows. AI writes the initial diff quickly, but the team still needs feedback before the context disappears. I made that case while moving to Biome: fast checks keep the review loop from becoming a CI archaeology project.

Line-by-line review is the wrong interface

Line-by-line review does not scale to generated code. It survives because humans used to write every line slowly and reviewers had time to follow.

Spelling, formatting, imports, dead branches, and simple convention violations should never consume reviewer attention. A formatter, linter, or targeted check can catch them more consistently than a tired engineer scanning a large diff. Teams already know this. They still leave too much of it for pull-request discussion.

AI needs a distinct review job. One agent writes the change. Another examines the diff against the ticket, the relevant tests, and the parts of the repository it touches. It should flag expanded permissions, duplicate business rules, missing tests, and behavior that does not match the stated requirement.

An AI reviewer needs an independent prompt, an independent model or context, and deterministic checks beneath it. Human reviewers can then focus on the remaining questions: did we choose the right behavior, is the risk acceptable, and are we changing a boundary that will be hard to undo?

Reversibility should set the bar

I would accept an inelegant AI-generated condition tree in code that is easy to replace: a local UI flow, an internal tool, or a feature whose behavior is covered by ordinary tests. The team can ship, observe, and refactor once reality tells us which rules matter.

Payments, authentication, and shared infrastructure require the stricter standard. Those systems accumulate callers, permissions, data, and operational assumptions. The cost of a bad abstraction rises before the next model gets a chance to repair it. “We can ask Opus to clean it up later” cannot serve as a rollback plan.

Review AI code. Stop treating all code quality defects, and all review objections, as equally expensive. The rule applies to human-written code too. AI only makes the waste easier to see.

For low-stakes code, the question is whether the change works and remains cheap to rewrite. For high-stakes code, the old standard holds: understand it, challenge the design, and reject the abstraction if it is not earned.

The useful metric is no longer whether an AI diff looks polished enough to survive forever. It is whether the team can safely live with it until the next rewrite becomes cheaper than the discussion happening today. Models will make that day arrive sooner.

The end state is review aimed at the decisions that matter, with machines checking the code that machines increasingly write. Human attention is too expensive to spend on a missing comma while the actual business boundary slips through unnoticed.