1. Quality issues in Vibe Coding
Andrej Karpathy when introducing Vibe Coding said: "I just see things, say things, run things, and copy-paste things, and it mostly works." But "mostly works" not enough for production code.
Actual data (2025-2026):
| Source | Detection |
|---|---|
| GitClear (2025) | “Code churn” increases after applying AI — more code is written and then edited/deleted |
| VeraCode (2026) | 72% of applications using AI-generated code have at least 1 security vulnerability |
| CodeRabbit (2026) | AI code review detects bugs that human reviewers miss |
2. How to Review AI-Generated Code
2.1. Checklist review for AI code
- ✅ Logical correctness: Does the code do what is required?
- ✅ Edge cases: AI often misses null, empty, boundary cases
- ✅ Error handling: Is catch errors appropriate?
- ✅ Security: Input validation, auth checks, SQL injection
- ✅ Performance: N+1 queries, unnecessary re-renders
- ✅ Naming: Do variables, functions make sense?
- ✅ Duplication: AI often generates instead of reusing existing code
2.2. Use Copilot to review its own code
// Prompt: Review this code for: 1. Security vulnerabilities 2. Performance issues 3. Edge cases not handled 4. Code that doesn't follow our project conventions 5. Potential bugs
Be critical and thorough. List every issue found.
2.3. Anti-patterns are common in AI code
| Anti-pattern | For example | Fix |
|---|---|---|
| God function | One 200 line function that does everything | Split into smaller functions |
| Copy-paste the code | Repeat logic instead of extracting | Extract shared utilities |
| Hardcoded values | Magic numbers, URLs in code | Move to config/env |
| Weak error handling | Silent catch or generic errors | Specific error handling |
| Missing validation | Trust user input completely | Validate at boundaries |
| Over-engineering | Abstract too early, factory pattern for 1 case | YAGNI — build only when needed |
3. Automated Quality Gates
3.1. ESLint + Prettier + Copilot Hooks
// .vscode/settings.json
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"github.copilot.chat.hooks": {
"postSave": [
{
"command": "npx eslint --fix ${file}",
"pattern": "**/*.{ts,tsx}"
}
]
}
}
3.2. Pre-commit hooks
// package.json
{
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix",
"prettier --write"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"pre-push": "npm test"
}
}
}
3.3. CI/CD quality checks
# .github/workflows/quality.yml
name: Code Quality
on: [pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
- run: npx tsc --noEmit # Type check
- run: npx eslint . # Lint
- run: npm test -- --coverage # Tests + coverage
- run: npx knip # Dead code detection
4. Type Safety — First line of defense
TypeScript strict mode catches many bugs that AI creates:
// tsconfig.json
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"exactOptionalPropertyTypes": true
}
}
// Prompt mẫu yêu cầu type safety:
Ensure all functions have explicit return types.
Use discriminated unions for API responses.
No 'any' types — use 'unknown' with type guards instead.
5. Test Coverage Strategy
AI code needed test more, not less:
// Prompt:
Write tests for the TaskService focusing on:
1. Happy path for each method
2. Edge cases: empty input, null values, max length
3. Authorization: user can only access own projects
4. Concurrent modifications
5. Database constraint violations
Minimum coverage targets:
| Layer | Target | Reason |
|---|---|---|
| Business logic | 90%+ | Core domain needs to be accurate |
| API endpoints | 80%+ | Integration tests for contracts |
| UI components | 70%+ | Interaction tests for UX |
| Utilities | 95%+ | Pure functions are easy to test |
6. Metrics & KPIs for Vibe Coding
| Metric | What to measure? | Target |
|---|---|---|
| Acceptance rate | % AI suggestions accepted | 30-40% (too high = no review) |
| Code churn | % code edited/deleted within 2 weeks | <25% |
| Bug density | Bugs per 1000 LOC | Reduced or kept the same compared to before AI |
| Review comments | Number of times reviewers request to fix AI code | Decreases over time |
| Time to PR merge | Time from PR creation to merge | Reduced but not because of skipping review |
7. Summary of Best Practices
- Do not accept blindly: Read EACH AI generated line
- Ask AI to explain: "Explain why you chose this approach"
- Test-first when possible: Write tests first, use AI to implement
- Incremental generation: Generate each small part, review it before continuing
- Custom instructions: Enforce coding standards passed
copilot-instructions.md - Automated gates: CI/CD catches bugs that human reviewers miss
- Measure quality: Track metrics to know whether AI is helping or harming
8. Summary
Vibe Coding Responsibly = take advantage of the speed of AI + maintain the quality of human engineering.
The generated AI code needs to be reviewed more carefully human-written code, because:
- AI does not understand business context
- AI prioritizes code that "looks right" over code that "runs right"
- AI does not know what code is currently in the project
Next article: Security in Vibe Coding — common security vulnerabilities and how to avoid them.