Ninety-one percent of developers now use AI coding assistants. That’s the data point everyone’s celebrating. What nobody talks about? The code that passes TypeScript, runs in dev, and still breaks production—because the AI skipped the .safeParse() and went straight to .parse(), or fired off database mutations without checking the result.
That’s the problem this developer solved. And they did it without switching to a different AI model or waiting for Claude to get “smarter.”
The Problem Nobody Wants to Admit
Here’s the thing about AI-assisted coding: it’s genuinely fast when you already know what you’re doing. But it’s also consistently wrong in ways that are brutally hard to spot. The code compiles. The code runs. The code passes your tests (maybe). But it uses the wrong API flavor, nests async logic four levels deep, or—my personal favorite—treats your database like it’s a toy project.
The original author manages about ten SvelteKit repositories on Cloudflare Workers, all built with Claude Code assistance. After a few close calls, they noticed a pattern: every “always” and “never” statement living in their CLAUDE.md file was functionally optional. The AI reads it. The AI might follow it. The AI also might not. There’s no enforcement. No compiler error. Just… compliance roulette.
“The problem is that if you add guidance to your CLAUDE.md file such as ‘always use safeParse()’ and ‘never interpolate SQL’, those are just suggestions, not constraints. The AI reads them, and might follow them, but also it might not.”
So they did something brilliant: they moved every rule out of prose and into code.
From Wishful Thinking to Mechanical Resistance
In hydraulics, backpressure is resistance applied to a flow to regulate it. In software, it’s making bad patterns structurally impossible rather than merely discouraged. A sign on the pipe that says “please don’t overflow” can be ignored. A pressure valve cannot.
The strategy: migrate every actionable rule out of documentation into something mechanical—a type, a lint rule, a test, a structural check. What stays in CLAUDE.md becomes context and intent. The why, not the what.
They deployed three layers of enforcement:
oxlint does the heavy lifting (~50ms, checks ~200 JS/TS rules). Fast, universal, Rust-based. But it’s dumb about framework patterns.
ESLint + custom Svelte plugin understands .svelte files as a whole. The custom rules are where the magic happens—no-raw-html (sanitization checks), no-binding-leak (platform.env exposure), no-schema-parse (.parse() vs .safeParse()), no-silent-catch (error swallowing).
Then comes ast-grep. This is the newest and most interesting tool in the stack. It uses tree-sitter to match code by structure, not tokens. Rules are declarative YAML. You can describe patterns like: “a database query nested inside an array map.” Neither oxlint nor ESLint can express that. The AI generates it constantly because it looks correct and works on small datasets. It’s a performance catastrophe at scale.
One ast-grep rule catches N+1 queries:
id: n-plus-one-query-map
language: TypeScript
severity: warning
message: Potential N+1 query: database call inside .map(). Use db.batch() or WHERE IN instead.
rule:
pattern: $ARR.map($$$ARGS)
has:
pattern: $DB.prepare($$$SQL)
stopBy: end
It catches structural antipatterns that look correct on first read but explode under real load.
Why This Matters (and Why It Scares AI Vendors)
Since deploying, these rules flagged:
- Template literal SQL injection in load functions
- N+1 patterns where the AI awaited each item individually
- Unbounded
.all()queries that worked in dev (5 rows) and would timeout in production (50,000 rows) - Empty catch blocks where D1 errors vanished silently
None produced TypeScript errors. None were caught by oxlint or ESLint. All would have shipped.
This is the uncomfortable truth: your type system doesn’t care about your domain. TypeScript can’t tell the difference between safe and unsafe SQL patterns. It can’t prevent an N+1 query. The linter is the only thing standing between you and a production outage.
Which means AI vendors have a problem. They can’t guarantee code quality because code quality isn’t binary—it’s contextual. What works for a tutorial breaks under load. What follows style guidelines might be structurally unsound. You can’t fix this with a better model or a longer system prompt. You fix it with mechanical enforcement.
The Audit Layer That Catches Churn
Here’s where this gets even more sophisticated. Svelte and Cloudflare ship constantly. SvelteKit has had 50+ releases since 5.0. The AI doesn’t know about features released last week.
So they built a “what’s new” audit—a shell script that fetches their SvelteKit patterns feed (a JSON Feed 1.1 endpoint with grep-friendly search signatures) and the Cloudflare changelog RSS. It filters changelog entries to only the products each repo uses (by reading wrangler.jsonc bindings), then searches source code for legacy patterns.
Output: “repo x has 3 files still using writable() stores—$state class replacement available since Svelte 5.29.”
When the audit discovers features not in the feed, it flags those as gaps. The feed stays current because the audit tells you when it’s behind. The whole thing runs in about 10 seconds across all ten repos. It’s a shell script, not an AI call.
All rules, configs, and workflows live in one .github repo. A sync script distributes to ten consumer repos. One command updates everything. No drift. No decision fatigue.
Why This Is Actually About Human Judgment
Here’s the uncomfortable truth nobody wants to say out loud: better AI models won’t solve this problem. Smarter prompts won’t solve this problem. What solves it is making the implicit explicit and then making the explicit mechanical.
Every rule here came from a mistake they caught. Not a theoretical mistake. Not a “this could theoretically happen.” A real production incident or a close call. That judgment—knowing what matters, knowing what breaks—is irreducibly human. The AI’s job is to generate code fast. Your job is to decide what “safe” actually means for your specific infrastructure, domain, and load profile.
That’s why this approach scales. You’re not arguing with Claude about coding style. You’re not adding another paragraph to your system prompt and hoping it sticks. You’re encoding your actual, hard-won knowledge into structural constraints that can’t be violated.
The irony? The AI’s existence forced this level of rigor. Before Claude Code, maybe nobody bothered. Now? Now you have to be explicit about what’s acceptable. And that’s not a bad thing.
FAQ
Can I use these rules with other AI coding assistants? Yes. These rules are language and tool agnostic—they catch structural mistakes regardless of whether Claude, ChatGPT, or Copilot generated them. The rules are in ESLint, ast-grep, and shell scripts. They work on any code.
What if my linter rules slow down my development? They don’t, according to this setup. oxlint runs in ~50ms. ESLint + custom rules add negligible overhead. ast-grep runs in about 10 seconds across ten repos. The time saved debugging production issues pays for this many times over.
Do I need all three linting tools? No. Start with ESLint + custom rules for framework-specific issues. Add ast-grep only if you’re catching complex structural antipatterns (like N+1 queries) that ESLint can’t express. oxlint is the universal first pass.