We Built an AI Coding Tools Validation Pipeline That Catches 94% of Convention Violations Before Code Review

1 comment
(AI Coding Tools) - AI coding tools write fast code, but they'll happily ignore your team's conventions. Here's the exact validation pipeline we built to catch 94% of violations before they hit code review.

We Built an AI Coding Tools Validation Pipeline That Catches 94% of Convention Violations Before Code Review

Let me be blunt: AI coding tools are incredible at generating code fast. But they’re terrible at respecting your team’s conventions.

I’ve seen it happen dozens of times. A junior dev prompts Cursor to generate a new API endpoint. The code works perfectly. But it uses `var` instead of `const`. The error handling pattern is inconsistent. The file is 400 lines when your team caps at 200.

Why Vietnam Outsourcing Is the Smartest Move Your Tech Team Can Make in 2025

Why Vietnam Outsourcing Is the Smartest Move Your Tech Team Can Make in 2025

TL;DR: Vietnam outsourcing delivers enterprise-grade developers at 60% lower cost than the US, with a rapidly maturing ecosystem… ...

And then someone has to fix it in code review.

That’s the hidden tax of AI coding tools. You save time on writing code, but you lose it on cleaning up the mess.

Why Outsourcing Software Development Beats Building In-House in 2025

Why Outsourcing Software Development Beats Building In-House in 2025

TL;DR: Outsourcing software to elite offshore teams slashes costs by 40-60%, accelerates time-to-market, and unlocks specialized talent. We’ll… ...

We decided to fix this. Here’s the exact validation pipeline we built for our team in Ho Chi Minh City. It catches 94% of convention violations before they ever reach a human reviewer.

The Real Problem Isn’t Hallucination — It’s Convention Drift

Most teams focus on whether AI-generated code *works*. That’s the wrong metric.

AI coding tools produce syntactically correct code almost every time. The real problem is convention drift — the gradual erosion of your codebase’s style, patterns, and architectural decisions.

Here’s what we measured over three months with a team of 8 developers using Cursor and Claude Code:

Violation Type Occurrences Caught by Standard Linting Caught by Our Pipeline
Import ordering 147 92 (62%) 145 (98%)
Naming conventions 89 41 (46%) 83 (93%)
Error handling patterns 63 12 (19%) 58 (92%)
File size limits 34 0 (0%) 33 (97%)
Architectural violations 28 0 (0%) 25 (89%)
Total 361 145 (40%) 344 (94%)

Standard linters caught 40%. Our pipeline caught 94%.

The difference? We moved beyond syntax checking into semantic convention enforcement.

The Architecture: Three Layers of Validation

We built this pipeline using the ECOA AI Platform ACP to orchestrate the validation agents. But you can replicate it with open-source tools.

Here’s the stack:

  • Layer 1: Pre-commit hooks (husky + lint-staged)
  • Layer 2: AST-based convention checks (custom ESLint plugins + TypeScript compiler API)
  • Layer 3: AI-powered semantic validation (Claude API + custom prompts)

Layer 1: The Pre-commit Gate

This is the fastest layer. It catches obvious stuff before anything else runs.

json
// .lintstagedrc.json
{
  "*.{ts,tsx}": [
    "eslint --fix --max-warnings 0",
    "prettier --write",
    "tsc --noEmit --pretty"
  ],
  "*.{py}": [
    "ruff check --fix",
    "mypy --strict"
  ]
}

But here’s the key: we added custom checks that standard linters miss.

javascript
// .husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# Check file size
MAX_LINES=200
for file in $(git diff --cached --name-only --diff-filter=ACM | grep '\.ts$'); do
  lines=$(wc -l < "$file")
  if [ "$lines" -gt "$MAX_LINES" ]; then
    echo "❌ $file has $lines lines (max $MAX_LINES)"
    exit 1
  fi
done

Honestly, this alone caught 30% of our violations. Simple, fast, effective.

Layer 2: AST-Based Convention Enforcement

Standard ESLint rules don't know your team's specific patterns. So we wrote custom rules.

Here's one we built to enforce our error handling pattern. We require all async functions to use a specific error wrapper:

typescript
// eslint-plugin-team-conventions/rules/require-error-wrapper.ts
import { TSESTree } from '@typescript-eslint/utils';
import { createRule } from '../utils';

export const requireErrorWrapper = createRule({
  name: 'require-error-wrapper',
  meta: {
    type: 'suggestion',
    docs: {
      description: 'Require async functions to use errorWrapper',
    },
    schema: [],
    messages: {
      missingWrapper: 'Async function "{{name}}" must use errorWrapper',
    },
  },
  defaultOptions: [],
  create(context) {
    return {
      'FunctionDeclaration[async=true], ArrowFunctionExpression[async=true]'(node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression) {
        const sourceCode = context.getSourceCode();
        const text = sourceCode.getText(node);
        
        if (!text.includes('errorWrapper') && !text.includes('try {')) {
          context.report({
            node,
            messageId: 'missingWrapper',
            data: { 
              name: (node as TSESTree.FunctionDeclaration).id?.name || 'anonymous' 
            },
          });
        }
      },
    };
  },
});

We deployed 12 custom rules like this. They cover naming conventions, import patterns, architectural boundaries, and error handling.

The AI coding tools never learned these patterns. But our pipeline enforced them every single time.

Layer 3: AI-Powered Semantic Validation

This is where it gets interesting. Some violations are too complex for AST checks.

For example: "Does this function have too many responsibilities?" or "Is this component properly decoupled from business logic?"

We built a Claude-powered validation agent that runs on staged changes:

python
# validate_semantics.py
import subprocess
import json
from anthropic import Anthropic

client = Anthropic()

def get_staged_diff():
    result = subprocess.run(
        ['git', 'diff', '--cached', '--unified=3'],
        capture_output=True, text=True
    )
    return result.stdout

def validate_conventions(diff: str) -> list:
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1000,
        messages=[{
            "role": "user",
            "content": f"""Review this code diff for convention violations.
Check for:
1. Single responsibility violations
2. Business logic leaking into UI components
3. Missing error handling for edge cases
4. Functions that exceed 7 parameters
5. Deeply nested conditionals (depth > 3)

Return a JSON array of violations:
[{{"file": "path", "line": number, "type": string, "message": string}}]

Diff:
{diff}"""
        }]
    )
    
    return json.loads(response.content[0].text)

if __name__ == "__main__":
    diff = get_staged_diff()
    violations = validate_conventions(diff)
    
    if violations:
        for v in violations:
            print(f"❌ {v['file']}:{v['line']} - {v['message']}")
        exit(1)
    else:
        print("✅ Semantic checks passed")

This runs in about 8 seconds on a typical commit. Worth every millisecond.

The Results: What Changed After 3 Months

We rolled this pipeline out to our team of 8 developers in Ho Chi Minh City. All of them use AI coding tools daily — Cursor, Claude Code, and GitHub Copilot.

Before the pipeline:

  • Average 12 convention violations per PR
  • Code review time: 45 minutes per PR
  • 30% of PRs required significant refactoring

After the pipeline:

  • Average 0.7 convention violations per PR
  • Code review time: 18 minutes per PR
  • 4% of PRs required significant refactoring

The pipeline blocked 94% of violations at commit time. Developers fixed them immediately instead of waiting for a reviewer to point them out weeks later.

How We Integrated This with AI Coding Tools

Here's the controversial take: we didn't change how developers use AI coding tools.

We let them generate code however they want. The pipeline catches the mess.

This is important. If you try to force AI coding tools to follow conventions through prompts alone, you'll fail. The models don't have enough context about your specific codebase conventions.

Instead, let AI generate fast. Then validate hard.

The Cost vs. Benefit

Building this pipeline took our team about 40 hours spread across two weeks. That's roughly $3,000 in developer time.

In the first month, it saved us an estimated 120 hours of code review time. That's a 3x ROI in month one.

More importantly, it prevented convention drift. Our codebase stayed consistent even as we scaled from 4 to 8 developers.

Why Most Teams Get This Wrong

I see teams make two mistakes:

  1. They trust AI coding tools too much. They assume the generated code follows their conventions. It doesn't.
  1. They block AI coding tools entirely. They ban Cursor or Copilot because "it writes bad code." That's throwing the baby out with the bathwater.

The right approach is a validation pipeline. Let AI write fast. Then validate ruthlessly.

The Bottom Line

AI coding tools aren't going anywhere. They're getting better every month. But they'll never fully understand your team's specific conventions and architectural decisions.

That's your job.

Build a validation pipeline. Enforce your conventions programmatically. And let your developers use AI tools without worrying about the mess they leave behind.

Our pipeline catches 94% of violations before code review. Yours can too.

---

Want to see this in action? We're building similar validation pipelines for our clients using the ECOA AI Platform ACP. Our Vietnamese engineering teams combine AI tooling with rigorous validation workflows. You get 5x development speed without sacrificing code quality.

Frequently Asked Questions

Q: Will this pipeline slow down my development workflow?

A: The entire pipeline runs in under 30 seconds for a typical commit. Layer 1 (pre-commit hooks) takes 2-3 seconds. Layer 2 (AST checks) takes 5-10 seconds. Layer 3 (AI semantic validation) takes 8-15 seconds. The time saved in code review far outweighs this overhead.

Q: Can I use this pipeline with any AI coding tool?

A: Yes. The pipeline operates on the staged changes in git, not on the tool that generated them. It works identically whether your team uses Cursor, Claude Code, Copilot, or even manual coding. The validation is tool-agnostic.

Q: How often do we need to update the custom ESLint rules?

A: We review our custom rules quarterly. As our conventions evolve, we add or modify rules. The AI-powered semantic validation layer adapts automatically since we update the prompt to reflect new conventions. Plan for about 4 hours of maintenance per quarter.

Q: Does this work for non-TypeScript codebases?

A: Absolutely. We've deployed similar pipelines for Python (using Ruff + mypy + custom checks), Go (using golangci-lint + custom analyzers), and Ruby (using RuboCop + custom cops). The architecture is language-agnostic. The specific tools change, but the three-layer approach stays the same.

Related reading: Why Smart CTOs Hire Vietnamese Developers Over Other Offshore Teams

Related reading: Vietnam Outsourcing: The Strategic Edge for Scaling Your Tech Team in 2025

Leave a Comment

Your email address will not be published. Required fields are marked *

Ready to Build with AI-Powered Developers?

Hire Vietnamese engineers augmented by ECOA AI Platform + Claude Code. 5x faster, 40% cheaper.