Módulo 2: Mental Models para AI Code
Circuit Breaker: Checkpoints de Verificación
Circuit Breaker: Checkpoints de Verificación
Descripción de la cápsula
En la cápsula anterior aprendiste cómo supervisar (Managing an Intern). Ahora necesitas saber cuándo pausar. El patrón Circuit Breaker viene de la ingeniería de software: cuando un servicio falla, el circuit breaker se activa y detiene los requests para evitar cascadas de errores. Aplicado a tu flujo con AI code, el concepto es similar: defines checkpoints donde pausas, verificas, y decides si continúas o detienes.
Sin checkpoints, el flujo con Claude Code se vuelve peligroso. Le pides que genere 5 archivos, los aceptas todos sin pausar, haces commit, y descubres el problema 3 días después cuando algo falla en producción. Con checkpoints, pausas después de cada archivo (o cada grupo lógico), verificas lo que importa, y solo continúas cuando tienes confianza en lo que ya tienes.
Esta cápsula te enseña a definir checkpoints para tu flujo de trabajo, qué verificar en cada uno, y cuándo "trip the breaker" — detenerte por completo porque algo no está bien.
El Patrón Circuit Breaker en Software
El patrón original
En software distribuido, el Circuit Breaker pattern previene fallos en cascada:
Sin Circuit Breaker:
Service A → Service B (caído) → timeout → retry → timeout → retry
→ Service A se queda sin threads
→ Service C que depende de A también falla
→ Cascada de fallos
Con Circuit Breaker:
Service A → Service B (caído) → circuit breaker se activa
→ Service A recibe error inmediato
→ No gasta recursos en retries inútiles
→ Puede responder con fallback
→ Se recupera cuando Service B vuelve
La adaptación a code review
La misma lógica aplica a tu flujo con AI code:
Sin checkpoints:
Pides 5 archivos → Aceptas los 5 → Commit → Push → Deploy
→ Descubres bug en archivo 2
→ Archivos 3, 4, 5 dependían de archivo 2
→ Todo está mal → Revert completo
Con checkpoints:
Pides 5 archivos → Revisas archivo 1 → OK → Continúas
→ Revisas archivo 2 → Issue en lógica → PAUSA
→ Corriges archivo 2 → Regeneras archivos 3-5 con el fix
→ Revisas 3, 4, 5 → OK → Commit
La diferencia es dramática: sin checkpoints, un error en un archivo temprano contamina todo lo que sigue. Con checkpoints, detectas y corriges antes de que el error se propague.
Tipos de Checkpoints
Los 4 checkpoints del flujo con AI code
Checkpoint 1: DESPUÉS DE GENERAR
├── ¿El output es lo que pediste?
├── ¿La estructura general es correcta?
├── ¿Hay algo claramente mal?
└── → Decisión: continuar, regenerar, o editar
Checkpoint 2: ANTES DE INTEGRAR
├── ¿El código se integra con lo existente?
├── ¿Los imports son reales?
├── ¿Las interfaces coinciden?
└── → Decisión: integrar, ajustar, o desechar
Checkpoint 3: ANTES DE COMMIT
├── ¿Pasan los tests?
├── ¿Pasa el linter?
├── ¿El diff muestra solo los cambios esperados?
└── → Decisión: commit, ajustar, o revertir
Checkpoint 4: ANTES DE MERGE/DEPLOY
├── ¿Code review está completo?
├── ¿Los tests de CI pasan?
├── ¿Hay riesgos no mitigados?
└── → Decisión: merge, iterar, o bloquear
Qué verificar en cada checkpoint
Cada checkpoint tiene un scope diferente. No verificas lo mismo en todos — eso sería ineficiente.
Checkpoint 1: Después de generar
Este es el checkpoint más frecuente. Lo aplicas cada vez que Claude Code genera output.
# Claude Code acaba de generar este archivo.
# CHECKPOINT 1: ¿Qué verifico?
# 1. ¿Es lo que pedí?
# Pedí un endpoint de búsqueda de productos.
# ¿El output es un endpoint de búsqueda de productos?
# 2. ¿La estructura es razonable?
# ¿Usa FastAPI? ¿Tiene validación? ¿Tiene error handling?
# 3. ¿Hay algo claramente mal?
# ¿Imports que no reconozco? ¿Lógica que no tiene sentido?
# ¿Un approach completamente diferente al que esperaba?
Tiempo típico: 1-3 minutos para código simple, 5-10 minutos para código complejo.
Checkpoint 2: Antes de integrar
Este checkpoint aplica cuando el código generado debe coexistir con código existente.
# Tengo una app existente y Claude Code generó un nuevo módulo.
# CHECKPOINT 2: ¿Se integra correctamente?
# 1. ¿Los imports referencian módulos que existen en MI proyecto?
from app.models.user import User # ¿Existe este módulo?
from app.core.security import get_current_user # ¿Esta función existe?
from app.db.session import get_db # ¿Este patrón es el que uso?
# 2. ¿Las interfaces coinciden?
# Si el módulo existente espera User.id como int,
# ¿el nuevo módulo lo trata como int? ¿O asume string?
# 3. ¿Hay conflictos de naming?
# ¿El nuevo módulo define funciones con nombres que ya existen?
Tiempo típico: 3-8 minutos.
Checkpoint 3: Antes de commit
Este checkpoint es técnico — verificas que todo funciona antes de grabar el estado.
# CHECKPOINT 3: Antes de commit
# 1. ¿Pasan los tests?
pytest tests/ -v
# Si hay tests que fallan → NO hagas commit. Investiga primero.
# 2. ¿Pasa el linter?
ruff check .
mypy .
# Errores de lint pueden indicar problemas reales, no solo estilo.
# 3. ¿El diff es lo que esperas?
git diff --stat
# ¿Solo cambió lo que debería cambiar?
# ¿Hay archivos inesperados modificados?
git diff
# Lee el diff completo. ¿Todo tiene sentido?
Tiempo típico: 2-5 minutos.
Checkpoint 4: Antes de merge/deploy
Este es el checkpoint final y más riguroso.
CHECKPOINT 4: Antes de merge
1. ¿El code review está completo?
- ¿Apliqué Managing an Intern con los niveles correctos?
- ¿Revisé Nivel 1 para código de alto riesgo?
- ¿Encontré y resolví los issues?
2. ¿Los tests de CI pasan?
- Tests unitarios
- Tests de integración
- Linter y type checker
3. ¿Hay riesgos no mitigados?
- ¿Hay código de seguridad sin tests?
- ¿Hay lógica de negocio sin verificar contra requisitos?
- ¿Hay dependencias nuevas sin evaluar?
Tiempo típico: 5-15 minutos.
Cuándo "Trip the Breaker"
Señales de que debes detenerte
"Trip the breaker" significa detenerte por completo. No continúas hasta resolver el issue. Estas son las señales:
🛑 DETENTE INMEDIATAMENTE si:
1. El código hace algo que no pediste y no entiendes por qué
→ Claude Code a veces "inventa" features que nadie pidió.
→ Si no entiendes por qué algo está ahí, no lo aceptes.
2. Hay un import que no reconoces
→ Puede ser una hallucination (librería que no existe).
→ Puede ser una dependencia que introduce vulnerabilidades.
→ Verifica antes de continuar.
3. La lógica de seguridad "se ve rara"
→ Tu instinto detectó algo. Investiga.
→ Mejor perder 15 minutos verificando que perder 15 días
respondiendo a un incidente.
4. Los tests pasan pero no testean lo que deberían
→ Tests que pasan no significa código correcto.
→ Si los tests no cubren los escenarios de riesgo, no confíes.
5. El output es significativamente diferente a lo esperado
→ Si pediste un endpoint REST y generó un WebSocket,
algo se perdió en la comunicación.
→ Para, revisa tu prompt, regenera.
El costo de NO detenerte
Escenario: Claude Code genera 3 archivos para un sistema de pagos.
Sin Circuit Breaker:
├── Archivo 1: models.py → "Se ve bien" → Continúa
├── Archivo 2: payment_service.py → "Se ve bien" → Continúa
├── Archivo 3: routes.py → "Se ve bien" → Commit
├── 2 días después: test de integración falla
├── Investigación: payment_service.py calcula mal el tax
├── Pero routes.py ya usa los cálculos de payment_service
├── Y otros módulos ya dependen de routes.py
└── Costo: 4 horas de debugging + refactor
Con Circuit Breaker:
├── Archivo 1: models.py → Checkpoint → OK
├── Archivo 2: payment_service.py → Checkpoint
│ └── "¿Los cálculos de tax son correctos?" → NO
│ └── BREAKER TRIPPED → Corregir antes de continuar
├── Archivo 2 corregido → Checkpoint → OK
├── Archivo 3: routes.py → Checkpoint → OK (usa cálculos correctos)
└── Costo: 15 minutos de revisión en el checkpoint
Circuit Breaker en la Práctica
Ejemplo 1: Generación de múltiples archivos
Le pides a Claude Code: "Genera un módulo de inventario con modelos, servicio, y endpoints."
Plan de checkpoints:
PASO 1: Claude Code genera models.py
└── CHECKPOINT:
├── ¿Los campos del modelo tienen sentido para inventario?
├── ¿Los tipos son correctos? (quantity como int, price como Decimal)
├── ¿Las relaciones entre modelos son lógicas?
└── → Si OK, pedir el servicio
PASO 2: Claude Code genera inventory_service.py
└── CHECKPOINT:
├── ¿Usa los modelos que generó en paso 1?
├── ¿La lógica de negocio es correcta?
│ (¿Resta stock correctamente? ¿Valida stock negativo?)
├── ¿Maneja errores? (¿Qué pasa si el producto no existe?)
└── → Si OK, pedir los endpoints
PASO 3: Claude Code genera routes.py
└── CHECKPOINT:
├── ¿Los endpoints usan el servicio del paso 2?
├── ¿Las validaciones de input son correctas?
├── ¿Los status codes son apropiados?
├── ¿Hay auth donde debería haber?
└── → Si OK, integrar y preparar commit
Ejemplo 2: Generación iterativa con correcciones
A veces el checkpoint te lleva a corregir y regenerar:
# PASO 1: Claude Code genera un servicio de inventario
class InventoryService:
def __init__(self, db: Session):
self.db = db
def reduce_stock(self, product_id: int, quantity: int) -> Product:
product = self.db.query(Product).filter(
Product.id == product_id
).first()
if not product:
raise ValueError("Product not found")
product.stock -= quantity
self.db.commit()
return product
# CHECKPOINT 1: Revisión
# ⚠️ No valida que quantity sea positivo
# ⚠️ No valida que haya stock suficiente
# ⚠️ product.stock puede quedar negativo
# 🛑 BREAKER TRIPPED — lógica de negocio incorrecta
# PASO 2: Corriges y pides que regenere con las correcciones
# Prompt a Claude Code:
# "Corrige reduce_stock para que:
# 1. Valide que quantity > 0
# 2. Verifique que hay stock suficiente
# 3. Use select_for_update para evitar race conditions"
class InventoryService:
def __init__(self, db: Session):
self.db = db
def reduce_stock(self, product_id: int, quantity: int) -> Product:
if quantity <= 0:
raise ValueError("Quantity must be positive")
product = (
self.db.query(Product)
.filter(Product.id == product_id)
.with_for_update()
.first()
)
if not product:
raise ValueError("Product not found")
if product.stock < quantity:
raise ValueError(
f"Insufficient stock: {product.stock} available, "
f"{quantity} requested"
)
product.stock -= quantity
self.db.commit()
self.db.refresh(product)
return product
# CHECKPOINT 2: Revisión
# ✅ Valida quantity > 0
# ✅ Verifica stock suficiente
# ✅ Usa with_for_update() para race conditions
# ✅ Mensaje de error descriptivo
# ✅ refresh() para devolver datos actualizados
# → PASS — continuar con el siguiente archivo
Ejemplo 3: Checkpoint antes de commit
# Has integrado el código. Antes de commit:
# 1. Tests
$ pytest tests/test_inventory.py -v
# tests/test_inventory.py::test_reduce_stock_success PASSED
# tests/test_inventory.py::test_reduce_stock_insufficient PASSED
# tests/test_inventory.py::test_reduce_stock_negative_quantity PASSED
# tests/test_inventory.py::test_reduce_stock_not_found PASSED
# 4 passed in 0.3s
# → ✅ Tests pasan
# 2. Linter
$ ruff check src/inventory/
# All checks passed!
# → ✅ Linter OK
# 3. Diff
$ git diff --stat
# src/inventory/models.py | 25 +++++++
# src/inventory/service.py | 48 ++++++++++++
# src/inventory/routes.py | 62 ++++++++++++++++
# tests/test_inventory.py | 85 ++++++++++++++++++++
# 4 files changed, 220 insertions(+)
# → ✅ Solo los archivos esperados
# → CHECKPOINT PASSED — commit
Templates de Checkpoints
Template 1: Checkpoint por archivo
Usa este template cuando Claude Code genera múltiples archivos:
CHECKPOINT: [nombre del archivo]
Fecha: [fecha]
Nivel MIT: [1/2/3]
□ ¿Es lo que pedí?
□ ¿La estructura es correcta?
□ ¿Los imports son reales?
□ [Si Nivel 1] ¿Revisé cada línea de lógica crítica?
□ [Si Nivel 1] ¿Los valores de negocio son correctos?
□ [Si Nivel 2] ¿Los edge cases están manejados?
□ [Si Nivel 2] ¿El error handling existe?
□ [Si Nivel 3] ¿Se ve razonable?
Resultado: PASS / FAIL / NEEDS EDIT
Notas: [observaciones]
Acción: [continuar / editar / regenerar / detenerse]
Template 2: Checkpoint pre-commit
CHECKPOINT PRE-COMMIT
Fecha: [fecha]
Tests:
□ pytest pasa: [sí/no]
□ Tests cubren escenarios de riesgo: [sí/no]
□ Cantidad de tests nuevos: [número]
Calidad:
□ Linter pasa: [sí/no]
□ Type checker pasa: [sí/no]
Diff:
□ Solo archivos esperados modificados: [sí/no]
□ No hay archivos sensibles en el diff: [sí/no]
□ Diff revisado manualmente: [sí/no]
Resultado: COMMIT / FIX AND RETRY / REVERT
Template 3: Checkpoint pre-merge
CHECKPOINT PRE-MERGE
Fecha: [fecha]
PR: [número/link]
Code Review:
□ Managing an Intern aplicado: [sí/no]
□ Nivel 1 revisado exhaustivamente: [sí/no]
□ Issues encontrados y resueltos: [lista]
CI:
□ Pipeline verde: [sí/no]
□ Coverage no disminuyó: [sí/no]
Riesgos:
□ ¿Hay código de seguridad sin tests? [sí/no]
□ ¿Hay lógica de negocio sin verificar? [sí/no]
□ ¿Hay dependencias nuevas evaluadas? [sí/no]
Resultado: MERGE / ITERATE / BLOCK
Circuit Breaker en Diferentes Workflows
Workflow 1: Generación rápida (prototipo)
Cuando estás haciendo un prototipo, los checkpoints son más ligeros:
Prototipo — checkpoints ligeros:
Checkpoint 1 (Después de generar):
- ¿Funciona? (compila, responde, no crashea)
- ¿La estructura general tiene sentido?
- ⚡ 1-2 minutos por archivo
Checkpoint 2 (Antes de commit):
- ¿El prototipo demuestra lo que quiero?
- ⚡ 1 minuto
Checkpoint 3 (Pre-merge):
- ❌ No aplica en prototipo
Nota: Los checkpoints ligeros son para PROTOTIPOS.
Cuando el código pase a producción, aplica
checkpoints completos.
Workflow 2: Feature para producción
Para código que va a producción, los checkpoints son rigurosos:
Producción — checkpoints rigurosos:
Checkpoint 1 (Después de generar):
- Aplicar las 5 preguntas del manager
- Clasificar en nivel MIT
- Revisar según nivel
- ⏱️ 5-15 minutos por archivo
Checkpoint 2 (Integración):
- ¿Se integra con el código existente?
- ¿Los tests pasan con el código nuevo?
- ⏱️ 5-10 minutos
Checkpoint 3 (Pre-commit):
- Tests completos, linter, diff review
- ⏱️ 5-10 minutos
Checkpoint 4 (Pre-merge):
- Code review, CI pipeline, evaluación de riesgos
- ⏱️ 10-20 minutos
Workflow 3: Debugging con Claude Code
Cuando usas Claude Code para debugging, los checkpoints son diferentes:
Debugging — checkpoints de validación:
Checkpoint 1 (Después de sugerencia):
- ¿El diagnóstico tiene sentido?
- ¿La explicación del bug es plausible?
- ⏱️ 2-3 minutos
Checkpoint 2 (Después de fix sugerido):
- ¿El fix resuelve el bug?
- ¿El fix introduce bugs nuevos?
- ¿El fix toca solo lo necesario?
- ⏱️ 5-10 minutos
Checkpoint 3 (Después de aplicar):
- ¿El bug original está resuelto?
- ¿Los tests de regresión pasan?
- ¿No hay side effects?
- ⏱️ 5-10 minutos
Anti-Patrones de Circuit Breaker
Anti-patrón 1: Checkpoints sin criterio
❌ "Pongo un checkpoint cada 10 líneas de código"
→ Ineficiente: interrumpes el flujo constantemente
→ Los checkpoints no se basan en líneas de código
→ Se basan en unidades lógicas (archivos, funciones, features)
Anti-patrón 2: Checkpoints que nunca "trip"
❌ "Siempre paso el checkpoint — nunca detengo nada"
→ Si nunca detienes nada, no estás verificando de verdad
→ O tu código AI es perfecto (improbable)
→ O tus checkpoints son demasiado superficiales
→ Revisa qué estás verificando en cada checkpoint
Anti-patrón 3: Checkpoints solo al final
❌ "Reviso todo al final, antes de commit"
→ Si el error está en el primer archivo,
ya generaste 4 archivos basados en código incorrecto
→ El costo de corrección es exponencialmente mayor
→ Checkpoint temprano = corrección barata
Anti-patrón 4: Breaker que nunca se resetea
❌ "Claude Code generó un bug una vez, ahora reviso
cada import de cada archivo para siempre"
→ El breaker debe resetearse después de resolver el issue
→ Si el issue era específico (un import falso), no means
que todo lo demás es sospechoso
→ Ajusta tu calibración, no tu paranoia
Conexión con Proyecto
Cómo usarás Circuit Breaker en el Módulo 8
En el proyecto integrador recibirás un codebase con múltiples archivos. Tu flujo de revisión usará checkpoints:
- Checkpoint por módulo: Revisas cada módulo del codebase por separado. No intentas revisar todo de una vez.
- Checkpoint por tipo de issue: Primero buscas issues de seguridad (Red Zone). Después lógica de negocio. Después edge cases.
- Breaker si encuentras algo grave: Si un módulo tiene un problema de seguridad serio, paras y lo documentas antes de seguir con el siguiente módulo.
- Checkpoint final: Antes de entregar, verificas que todos los issues están documentados y que tu revisión fue completa.
Troubleshooting
Problema 1: "Mis checkpoints toman demasiado tiempo"
Causa: Estás verificando demasiado en cada checkpoint. Solución: Combina con Managing an Intern. En un checkpoint de archivo Nivel 3, solo haces revisión visual (30 segundos). En Nivel 1, sí inviertes 10-15 minutos. El promedio debería ser 3-5 minutos por checkpoint.
Problema 2: "No sé cuándo 'trip the breaker'"
Causa: Falta de experiencia reconociendo señales de alarma. Solución: Usa la lista de señales de esta cápsula. Si no estás seguro, detente de todos modos. Es mejor detenerte innecesariamente (pierdes 5 minutos) que no detenerte cuando debías (pierdes horas o días).
Problema 3: "Mi equipo no usa checkpoints y les va bien"
Causa: "Les va bien" puede significar que no han tenido un incidente todavía, o que no están detectando los problemas. Solución: Empieza aplicando checkpoints tú. Cuando tu tasa de bugs disminuya o detectes issues que otros no, tendrás evidencia para proponer el proceso al equipo.
Problema 4: "Claude Code genera todo de golpe y no puedo hacer checkpoints intermedios"
Causa: Estás pidiendo demasiado scope en un solo prompt. Solución: Divide tu request. En vez de "genera todo el módulo de inventario", pide: "genera los modelos de inventario", revisa, y después "genera el servicio que use esos modelos". Cada request es un checkpoint natural.
Ejercicios
Ejercicio 1: Definir checkpoints (Fácil)
Define los checkpoints para este flujo: le pides a Claude Code que genere un sistema de comentarios para un blog.
Archivos esperados:
models.py— modelos de Commentservice.py— lógica CRUD de comentariosroutes.py— endpoints RESTmoderation.py— filtrado de contenido inapropiado
Ver solución
Checkpoint 1: Después de models.py (Nivel MIT: 3)
├── ¿El modelo tiene los campos correctos? (author, content, post_id, created_at)
├── ¿Las relaciones con Post están bien definidas?
├── Tiempo: 1-2 minutos
└── Acción: Continuar si los campos hacen sentido
Checkpoint 2: Después de service.py (Nivel MIT: 2)
├── ¿Usa los modelos del checkpoint 1?
├── ¿El CRUD es completo? (create, read, update, delete)
├── ¿Verifica que el post existe antes de agregar comentario?
├── ¿Maneja errores? (comentario no encontrado, post no encontrado)
├── Tiempo: 5-8 minutos
└── Acción: Continuar si la lógica es correcta
Checkpoint 3: Después de routes.py (Nivel MIT: 2)
├── ¿Los endpoints usan el servicio?
├── ¿Hay auth? (¿quién puede editar/borrar comentarios?)
├── ¿Los status codes son correctos?
├── Tiempo: 5-8 minutos
└── Acción: Continuar si los endpoints son correctos
Checkpoint 4: Después de moderation.py (Nivel MIT: 1)
├── ⚠️ Este archivo es Nivel 1: filtrado de contenido tiene
│ implicaciones legales y de UX
├── ¿Qué criterio usa para "inapropiado"?
├── ¿Hay false positives que censurarían contenido legítimo?
├── ¿Se puede bypassear el filtro fácilmente?
├── Tiempo: 10-15 minutos
└── Acción: Revisar exhaustivamente antes de continuar
Checkpoint 5: Pre-commit
├── Tests pasan
├── Linter OK
├── Diff solo tiene los 4 archivos + tests
└── Acción: Commit
La clave: moderation.py recibe el checkpoint más riguroso porque el filtrado de contenido tiene consecuencias reales (censurar contenido legítimo o permitir contenido dañino).
Ejercicio 2: Identificar dónde "trip" (Medio)
Claude Code genera estos 3 archivos secuencialmente. ¿En cuál deberías "trip the breaker"?
Archivo 1: models.py
from pydantic import BaseModel, Field
from typing import Optional
from datetime import datetime
class OrderCreate(BaseModel):
product_id: int
quantity: int = Field(..., gt=0)
shipping_address: str = Field(..., min_length=10)
class Order(OrderCreate):
id: int
total_price: float
status: str = "pending"
created_at: datetime
Archivo 2: order_service.py
from models import Order, OrderCreate
from database import get_db
class OrderService:
def create_order(self, order_data: OrderCreate) -> Order:
db = get_db()
product = db.get_product(order_data.product_id)
total = product.price * order_data.quantity
order = db.create_order(
product_id=order_data.product_id,
quantity=order_data.quantity,
total_price=total,
)
return order
Archivo 3: routes.py
from fastapi import APIRouter, Depends
from models import OrderCreate, Order
from order_service import OrderService
router = APIRouter(prefix="/orders", tags=["orders"])
@router.post("/", response_model=Order)
async def create_order(order: OrderCreate):
service = OrderService()
return service.create_order(order)
@router.get("/{order_id}", response_model=Order)
async def get_order(order_id: int):
service = OrderService()
return service.get_order(order_id)
Ver solución
Archivo 1 (models.py): PASS con observación menor.
total_price: floatdebería serDecimalpara dinero, pero es aceptable para un primer pass.- Validaciones presentes (gt=0, min_length=10).
- Observación:
status: str = "pending"debería ser un Enum. - → Continuar (no es razón para trip, son mejoras).
Archivo 2 (order_service.py): TRIP THE BREAKER.
- ⚠️ No verifica que el producto existe (
db.get_productpuede retornar None). - ⚠️ No verifica stock disponible. ¿Qué pasa si pides 100 unidades y hay 5?
- ⚠️ No hay manejo de errores. Si
get_productfalla, el error sube sin contexto. - ⚠️
total = product.price * order_data.quantity— ¿y los impuestos? ¿shipping? ¿descuentos? - ⚠️ No hay transacción. Si
create_orderfalla después de calcular el total, queda en estado inconsistente. - → DETENER. Corregir antes de generar routes.py, porque routes.py dependerá de esta lógica.
Archivo 3 (routes.py): NO DEBERÍA HABERSE GENERADO AÚN.
- Si hubieras hecho checkpoint en Archivo 2, habrías detenido la generación.
- Adicionalmente:
service = OrderService()se instancia en cada request (no usa dependency injection). Y el endpoint POST no tiene autenticación. - → Si ya existe, necesita regenerarse después de corregir Archivo 2.
Lección: El checkpoint temprano en Archivo 2 habría evitado generar un Archivo 3 basado en lógica incorrecta.
Ejercicio 3: Diseñar checkpoints para tu proyecto (Medio)
Piensa en un proyecto en el que estés trabajando (o un proyecto personal). Lista 5 archivos o módulos que Claude Code podría generar y define:
- El orden de generación
- El checkpoint para cada uno
- El nivel MIT de cada checkpoint
- Qué haría que "trip the breaker" en cada uno
Ver solución
No hay respuesta única — depende de tu proyecto. Tu diseño de checkpoints debería:
- ✅ Generar primero los archivos de los que otros dependen (models antes de services antes de routes)
- ✅ Tener checkpoints más rigurosos para archivos de seguridad y lógica de negocio
- ✅ Tener checkpoints ligeros para boilerplate y configuración
- ✅ Definir criterios específicos de "trip" para cada archivo
- ✅ Cada checkpoint debería listar qué verificar (no solo "revisar")
Ejemplo para un proyecto de e-commerce:
| Orden | Archivo | Nivel MIT | Trip si... | Tiempo |
|---|---|---|---|---|
| 1 | models.py | 3 | Campos no tienen sentido para el dominio | 2 min |
| 2 | auth_service.py | 1 | Cualquier issue de seguridad | 20 min |
| 3 | product_service.py | 2 | Lógica de pricing incorrecta | 8 min |
| 4 | cart_service.py | 1 | Cálculos de totales incorrectos | 15 min |
| 5 | routes.py | 2 | Endpoints sin auth donde debería haber | 8 min |
Ejercicio 4: Post-mortem con Circuit Breaker (Difícil)
Lee este escenario y responde: ¿Qué checkpoints habrían prevenido el incidente?
Escenario:
Un developer usa Claude Code para generar un sistema de
invitaciones por email para una app SaaS.
Día 1: Genera models, service, routes. Acepta todo. Commit. Push.
Día 2: QA prueba y dice "funciona bien."
Día 3: Deploy a producción.
Día 5: Un usuario reporta que puede invitar a cualquier persona
a cualquier equipo, no solo al suyo.
Día 5: Investigación revela que el endpoint POST /invitations
no verifica que el usuario que invita es miembro del
equipo al que está invitando.
Día 5: 47 usuarios ya fueron invitados a equipos incorrectos.
Día 6: Hotfix, notificación a usuarios afectados, post-mortem.
Ver solución
Checkpoints que habrían prevenido el incidente:
Checkpoint 1 (Después de generar service.py): Si el developer hubiera aplicado las 5 preguntas del manager:
- Pregunta 3: "¿Hay algo que un atacante podría explotar?"
- → "¿El servicio verifica que el usuario pertenece al equipo?"
- → Issue detectado antes de generar routes.py
Checkpoint 2 (Antes de integrar routes.py): Si el developer hubiera verificado las interfaces:
- "¿El endpoint verifica permisos?"
- → Un endpoint POST sin verificación de permisos es una señal de breaker trip
Checkpoint 3 (Antes de commit): Si el developer hubiera revisado el diff con ojo de seguridad:
- POST /invitations sin Depends(verify_team_membership) → Red flag
Checkpoint 4 (Pre-merge / QA): QA probó "funciona bien" pero no probó el caso negativo:
- "¿Qué pasa si intento invitar a un equipo del que no soy miembro?"
- → Si hubiera un checklist de QA basado en Circuit Breaker, este caso estaría incluido
Root cause: No hubo checkpoint de seguridad en ningún punto del flujo. El primer checkpoint real fue cuando un usuario reportó el bug en producción — 5 días y 47 usuarios después.
Checkpoints mínimos que habrían bastado:
- Checkpoint en service.py con pregunta: "¿verifica permisos?" (Día 1)
- Checkpoint pre-merge con criterio: "¿endpoints que modifican datos tienen auth?" (Día 1)
Cualquiera de los dos habría sido suficiente.
Ejercicio 5: Checkpoint rápido vs completo (Difícil)
Para cada archivo generado por Claude Code, decide si aplicas checkpoint rápido (1-2 min) o completo (10+ min). Justifica.
Dockerfilepara una app Pythonauth/permissions.pycon decoradores de permisos por rolutils/formatters.pycon funciones de formateo de fechas y stringspayments/stripe_integration.pycon lógica de cobrotests/test_models.pycon 20 tests de modelos Pydantic
Ver solución
-
Dockerfile → Checkpoint rápido (1-2 min). Boilerplate estándar. Verificar: imagen base correcta, no copia secrets, multi-stage si aplica. Nivel 3.
-
auth/permissions.py → Checkpoint completo (15-20 min). Seguridad crítica. Verificar: cada decorador de permiso funciona correctamente, no se puede bypassear, maneja roles correctamente, falla seguro (deny by default). Nivel 1.
-
utils/formatters.py → Checkpoint rápido (1-2 min). Utilidades de bajo riesgo. Verificar: funciones se ven correctas, nombres descriptivos. Si formatean datos financieros, sube a checkpoint medio. Nivel 3.
-
payments/stripe_integration.py → Checkpoint completo (20-30 min). Código financiero + integración con servicio externo. Verificar: API keys no hardcoded, montos correctos, idempotency keys, error handling para pagos fallidos, webhooks validados. Nivel 1.
-
tests/test_models.py → Checkpoint medio (5-8 min). Los tests no son código de producción, pero tests incorrectos dan falsa confianza. Verificar: que testen lo correcto (no solo que pasen), que cubran edge cases, que las assertions sean significativas. Nivel 2.
Resumen
En esta cápsula aprendiste:
- Circuit Breaker adaptado de software engineering: defines checkpoints donde pausas y verificas antes de continuar
- 4 tipos de checkpoints: después de generar, antes de integrar, antes de commit, antes de merge
- Cada checkpoint tiene un scope diferente — no verificas lo mismo en todos
- "Trip the breaker" cuando: código hace algo que no pediste, imports desconocidos, lógica de seguridad sospechosa, tests que no testean lo correcto
- El costo de no detenerte es exponencialmente mayor que el costo de detenerte temprano
- Templates de checkpoints te dan un proceso reproducible
- Los checkpoints se combinan con Managing an Intern: el nivel MIT determina la profundidad del checkpoint
Próxima cápsula: Trust Calibration — cuánto confiar por tipo de tarea, con una tabla que puedes usar mañana.
Recursos Adicionales
- Circuit Breaker Pattern — Martin Fowler - El patrón original adaptado a code review
- Google — Code Review Speed - Cómo Google balancea velocidad y rigor en code review
- Conventional Commits - Estructura de commits que facilita checkpoints
- Ship / Show / Ask — Rouan Wilsenach - Framework de cuándo necesitas review y cuándo no
- Anthropic — Claude Code Documentation - Documentación oficial de Claude Code
- The Checklist Manifesto — Atul Gawande - Por qué los checklists salvan vidas (y código)
Debugging & Code Review with Claude Code — Módulo 2, Cápsula 03 Claude Code Agentic Development Path — Guía #6 de 11