El Code Review es la práctica de mayor ROI para mantener un codebase sano, pero mal gestionado es el mayor cuello de botella. En 2026, mi flujo de revisión cambió radicalmente: IA para la mecánica, humano para la estrategia. Resultado: ciclo de feedback de días a horas, menos fatiga, código más robusto.
El Flujo Completo: 3 Fases, 0 Fricción
flowchart TD
A[Dev abre PR] --> B[Claude Code: Filtro Automático]
B --> C{¿Issues críticos?}
C -->|Sí| D[Dev arregla + re-push]
C -->|No| E[Reviewer Humano: 3 Pilares]
E --> F[Aprobado + Merge]
F --> G[Post-merge: Docs sync via MCP]
Fase 1: Filtro Automático — Claude Code (Pre-Review)
Antes de que yo abra el PR, el autor ejecuta (o CI ejecuta):
# En terminal del autor (o GitHub Action)
claude-code review \
--base main \
--head feature/nueva-feature \
--prompt-file .claude/prompts/code-review.md \
--output github-comments
Prompt Estándar (.claude/prompts/code-review.md)
# Code Review Automático — Proyecto: [Nombre]
## Contexto del Repositorio
- Stack: Laravel 11 + Vue 3 + Inertia + TypeScript + Pest
- Arquitectura: Modular Monolith (app/Modules/)
- Patrones: Action pattern, DTOs, Domain Events, Form Requests
- Testing: Pest (feature > unit), Vitest (components), Playwright (E2E crítico)
- Convenciones: PSR-12, Laravel Pint, TypeScript strict, Conventional Commits
## Qué Buscar (Prioridad Alta → Baja)
### 1. Seguridad (Crítico)
- Bypass de auth/autorización (Policy/Gate ausente)
- SQL Injection (DB::raw sin bindings, query builder inseguro)
- XSS (datos sin sanitizar en Blade/Vue)
- Exposición PII en logs, APIs, responses
- Pagos/auth/crypto: validación de entrada, idempotencia, PCI
### 2. Rendimiento (Alto)
- N+1 queries (falta `with()` / `loadMissing()`)
- Índices ausentes en migraciones (composite para queries multi-col)
- Jobs síncronos en request (email, PDF, webhook → cola)
- Cache misses evitables (config, traducciones, permisos)
- Sin batching en APIs externas (Stripe, ERPs)
### 3. Correctidad (Alto)
- Off-by-one, desreferencia null, race conditions
- Migraciones no reversibles en prod (`dropColumn` en SQLite test)
- Tests frágiles (dependen de orden, datos fijos, timers)
- Tipos: `any` en TS, `mixed` en PHP sin justificación
### 4. Arquitectura y Patrones (Medio)
- Lógica de negocio en Controller (→ Action/Service)
- DTOs tipados para props Inertia (TS interfaces = Laravel Resources)
- Eventos de dominio para desacoplamiento (no llamados directos cross-module)
- Form Requests para validación + autorización (no en Controller)
### 5. Mantenibilidad y Simplicidad (Medio)
- Funciones/clases > 1 responsabilidad (god classes)
- Duplicación lógica (DRY mal aplicado = acoplamiento)
- Nombrado: lenguaje ubicuo del dominio, no técnico genérico
- Complejidad ciclomática > 10 (refactor a funciones pequeñas)
### 6. Estilo y Convenciones (Bajo - IA maneja)
- PSR-12 / Laravel Pint
- TypeScript strict + ESLint
- Conventional Commits
- Imports ordenados, variables sin usar
## Formato de Salida
- Comentarios en GitHub (file:line) con severidad: 🔴 Crítico | 🟠 Alto | 🟡 Medio | 🔵 Bajo
- Sugerencia concreta de fix
- Referencia a patrón/ADR si aplica
Fase 2: Revisión Humana — Los 3 Pilares (Donde Gasto Mi Tiempo)
Una vez pasa el filtro auto (o autor arregla críticos), entro yo. Mi revisión se centra exclusivamente en lo que IA no domina:
Pilar 1: Intencionalidad de Negocio
Pregunta clave: “¿Este código resuelve el problema real del ticket, o solo el problema técnico que el dev asumió?”
## Ejemplo Real
Ticket: "Usuario puede cancelar suscripción mensual"
❌ PR implementa: Cancelación inmediata + reembolso automático
✅ Negocio requería: Cancelación al fin de período + prorrateo + email confirmación
Comentario PR:
> "Ticket LINEAR-1234 especifica 'cancelación al final del período actual con prorrateo'.
> Aquí cancela inmediata y reembolsa total.
> Confirmar con PO si comportamiento inmediato es intencional (cambio alcance) o bug.
> Si intencional, actualizar ticket y añadir test para prorrateo."
Pilar 2: Arquitectura y Escalabilidad (Vista a 6 Meses)
Pregunta clave: “¿Este cambio introduce acoplamiento que dolerá en 6 meses?”
// ❌ PR propone: Lógica facturación directo en Controller
class InvoiceController extends Controller {
public function store(StoreInvoiceRequest $request) {
$invoice = Invoice::create($request->validated());
// Lógica negocio: 50 líneas cálculos, Stripe, ERP sync, emails
$this->syncToERP($invoice);
$this->sendConfirmationEmail($invoice);
return $invoice;
}
}
// ✅ Comentario Reviewer:
// "Esta lógica pertenece a `CreateInvoiceAction` (Action pattern).
// Controller solo: autoriza + valida + despacha Action + responde.
// Por qué? 1) Testable sin HTTP 2) Reutilizable CLI/Job/API 3) Separa concerns
// Ver app/Modules/Billing/Actions/CreateInvoiceAction.php para patrón existente."
Pilar 3: Mantenibilidad y Simplicidad
Pregunta clave: “¿El próximo dev (o yo en 6 meses) entenderá esto sin depurar?”
// ❌ PR propone: Helper "inteligente" con 15 params opcionales
function formatCurrency(
amount: number,
currency: string,
locale?: string,
showSymbol?: boolean,
compact?: boolean,
roundingMode?: 'ceil' | 'floor' | 'round',
fallback?: string,
// ... 8 más
): string { /* 80 líneas */ }
// ✅ Comentario Reviewer:
// "Esto es 'clever' pero frágil. Preferimos 2 funciones simples:
// 1) formatCurrency(amount, currency, locale?) → string (95% casos)
// 2) formatCurrencyCompact(amount, currency) → string (5% casos)
// Menos params = menos bugs, mejor autocomplete, testeable.
// DRY forzado aquí aumenta complejidad cognitiva, no la reduce."
Plantilla PR Obligatoria (.github/pull_request_template.md)
## 📋 Contexto
- **Ticket**: [LINEAR-XXXX](link) / [JIRA-XXXX](link)
- **Problema**: Qué resuelve este PR en una frase
- **Decisiones Clave**: ADR referenciado si aplica (ej. `docs/adr/014-stripe-webhook-idempotency.md`)
## 🧪 Testing
- [ ] Pest feature tests: happy path + edge cases (validación, auth, límites)
- [ ] Vitest component tests: props, events, states
- [ ] Playwright E2E: flujo crítico (si toca checkout, auth, pagos)
- [ ] Mutation testing (Infection): ≥ 80% en código nuevo
- [ ] Tests pasan en CI: `php artisan test --parallel` + `npm test`
## 🤖 Revisión IA (Pre-check)
- [ ] `claude-code review --base main` ejecutado localmente
- [ ] 🔴/🟠 issues resueltos antes de pedir revisión humana
- [ ] Commits atómicos, mensajes convencionales (`feat:`, `fix:`, `refactor:`)
## 👀 Para Reviewer Humano
- **Intencionalidad**: ¿Resuelve el ticket real?
- **Arquitectura**: ¿Encaja en `app/Modules/*/Actions|DTOs|Events`?
- **Simplicidad**: ¿Se lee sin depurar?
- **Nombrado**: Lenguaje ubicuo del dominio
## 🚀 Deploy
- [ ] Feature flag si cambio riesgoso (`config/feature-flags.php`)
- [ ] Migraciones reversibles (`down()` testeado)
- [ ] Runbook actualizado si nueva alerta/métrica
Métricas de Ciclo (Lo Que Medimos)
| Métrica | Antes (Solo Humano) | Después (Humano + IA) | Objetivo |
|---|---|---|---|
| Time to First Review | 18-48h | 2-4h | < 4h |
| Ciclos de Review/PR | 3-5 | 1-2 | ≤ 2 |
| PR Cycle Time | 3-5 días | 4-12h | < 24h |
| Comentarios “Nitpick”/PR | 8-15 | 1-3 | ≤ 3 |
| Bugs Prod/Release | 2-3 | 0-1 | 0 |
| Fatiga Reviewer (encuesta) | 3.2/5 | 4.6/5 | ≥ 4.5 |
Cultura: “IA para Mecánica, Humano para Estrategia”
Reglas de Equipo (En CONTRIBUTING.md)
- Autor ejecuta filtro IA ANTES de pedir revisión — “No me hagas perder tiempo en punto y coma”
- Reviewer humano SOLO comenta Pilares 1-3 — Si ves comentario de estilo, es fallo de proceso
- PRs pequeños (<300 líneas, 1 propósito) — Si no cabe, divídelo. IA revisa mejor PRs pequeños.
- SLA Revisión: 4h laborables — Si no puedes, reasigna. Botones “Approve/Request Changes” en GitHub.
- Post-merge: MCP sincroniza docs — ADRs, OpenAPI, CHANGELOG actualizados automáticamente vía MCP server.
Ejemplo de Comentario Humano “Bien Hecho”
> **Arquitectura** (Pilar 2)
>
> En `app/Modules/Billing/Actions/CreateSubscriptionAction.php:45`
>
> `SyncToERPJob` se despacha sincrónicamente dentro de la transacción BD.
> Si ERP falla → rollback suscripción → usuario sin suscripción pero Stripe cobró.
>
> **Propuesta**: Mover `SyncToERPJob` fuera de transacción (after_commit) + compensación:
> ```php
> DB::transaction(function () {
> $subscription = $this->createSubscription($data);
> // Solo BD local aquí
> });
>
> // After commit - si falla, compensar vía webhook Stripe + retry
> SyncToERPJob::dispatch($subscription)->afterCommit();
> ```
>
> Ver `docs/adr/012-erp-sync-reliability.md` para patrón completo.
>
> ¿Opiniones? Si acordado, implementar en este PR o ticket seguimiento.
Lo Que NUNCA Delego a IA (Lista Roja)
| Área | Por Qué |
|---|---|
| Decisiones arquitectónicas | IA optimiza local, pierde trade-offs sistémicos + negocio |
| Seguridad crítica (auth, pagos, crypto) | Reviso línea a línea; IA asiste, no decide |
| Intencionalidad de negocio | Solo humano valida contra ticket/PO/cliente |
| Merge final | Apruebo diff completo en GitHub antes de merge |
| Nombrado dominio | Lenguaje ubicuo = acuerdo equipo, no sugerencia IA |
Stack de Herramientas (2026)
| Herramienta | Rol |
|---|---|
| Claude Code | Pre-review automático, refactoring, scaffolding tests |
| GitHub Actions | Puerta CI: tests, PHPStan, Pint, Lighthouse CI, Mutation testing |
| Sentry + Pulse | Observabilidad post-merge (error rate, perf, cron) |
| MCP Servers | Post-merge doc sync (ADR, OpenAPI, CHANGELOG) |
| Linear/GitHub Projects | Ticket ↔ PR ↔ Deploy tracking |
¿Quieres Implementar Esto en Tu Equipo?
Disponible para consultoría técnica (2-4 semanas) o contratación como Senior que trae este workflow listo.
Modalidades:
- EOR (Deel, Remote, Oyster) — roles core indefinidos
- Freelance B2B (Autónomo, factura intracomunitaria 0% IVA) — proyectos 3-12 meses
- Indefinido directo — si tenéis entidad española
Stack: Laravel 11, PHP 8.3+, Vue 3 + TS, Inertia.js, Livewire 3, Astro, Docker, GitHub Actions, Laravel Pulse, Sentry, Claude Code / Cursor / MCP servers.
Ver Mi Perfil, Stack Completo y Condiciones →
Artículos Relacionados en Este Blog
- Cómo uso Claude Code en producción con Laravel y Vue — Flujo matutino, escritura, refactoring, MCP
- Métricas que un Senior Full-Stack debe defender — Cycle Time, MTTR, Core Web Vitals, coste infra, Bus Factor
- Laravel + Vue para equipos distribuidos — Arquitectura Inertia, workflow async, onboarding
- Async-first: Cómo trabajo en remoto desde Barcelona — Comunicación, tooling, rituales
- Guía CTO para contratar desarrolladores Laravel en España — Mercado, perfiles, proceso entrevista
