Cap 11: Plan Mode y Refinamiento Iterativo

Por: Artiko
claude-certifiedplan-modeiteracióntestingworkflow

Plan Mode vs Direct Execution

No todo requiere planificación. La clave es saber cuándo cada approach es apropiado.

Cuándo usar Plan Mode

SituaciónPor qué planificar
Tareas complejasMúltiples pasos interdependientes
Large-scale changesAfectan muchos archivos o módulos
Decisiones arquitectónicasTrade-offs que necesitan evaluación
Multi-file refactoringRiesgo de inconsistencias entre archivos

Ejemplo: “Migrar la autenticación de JWT custom a OAuth2 con refresh tokens.”

Esto requiere plan porque involucra cambios en: middleware, rutas, modelos, tests, configuración, y potencialmente frontend.

Cuándo usar Direct Execution

SituaciónPor qué ejecutar directo
Cambios simplesUn solo archivo, intención clara
Bug fixes bien definidosSe sabe exactamente qué corregir
Single-file changesSin dependencias cross-file
Tareas mecánicasRenaming, formatting, imports

Ejemplo: “Corrige el typo en la línea 42 de config.ts.”

No necesita plan — es una corrección atómica y clara.

Plan Mode permite exploración segura

La ventaja clave del plan mode es que Claude explora sin commitear cambios. Puede leer archivos, analizar dependencias, y proponer una estrategia antes de tocar código. Si el plan no convence, se ajusta sin haber modificado nada.

Explore Subagent

Para tareas de investigación extensas, usa un explore subagent que aísle el discovery verboso:

<!-- .claude/skills/explore/SKILL.md -->
---
context: fork
allowed-tools: ["Read", "Grep", "Glob"]
argument-hint: "tema o área del codebase a explorar"
---

# Explorar codebase

1. Usa Grep para encontrar archivos relevantes
2. Lee los archivos principales
3. Traza flujos de datos y dependencias
4. Retorna un resumen estructurado con hallazgos

Con context: fork, toda la lectura de archivos y búsquedas queda aislada. Solo el resumen final llega a la conversación principal.

Combinar plan + direct execution

El workflow más efectivo para tareas medianas:

1. Plan mode → investigación y diseño
   "Analiza cómo está implementado el sistema de caché actual"
   → Claude explora, lee archivos, propone plan

2. Direct execution → implementación
   "Implementa el paso 1 del plan: crear la interfaz CacheProvider"
   → Claude ejecuta con cambios concretos

Esto separa el pensar del hacer, reduciendo errores.

Comunicar transformaciones efectivamente

Concrete input/output > prose descriptions

En lugar de describir la transformación en prosa:

❌ "Transforma los datos del usuario para que el nombre esté capitalizado
   y el email normalizado"

Proporciona ejemplos concretos de input y output:

✅ Input:
   { "name": "juan pérez", "email": "[email protected]" }

   Output esperado:
   { "name": "Juan Pérez", "email": "[email protected]" }

Los ejemplos concretos eliminan ambigüedad. Claude entiende exactamente qué transformación aplicar sin interpretar prosa que puede ser imprecisa.

Más ejemplos para edge cases

Input: { "name": "", "email": "[email protected]" }
Output: { "name": "", "email": "[email protected]" }
// nombre vacío se mantiene vacío, no se capitaliza

Input: { "name": "María José", "email": "[email protected]" }
Output: { "name": "María José", "email": "[email protected]" }
// ya capitalizado se mantiene, email siempre lowercase

Test-Driven Iteration

Escribir tests primero, iterar compartiendo failures

El patrón más efectivo para desarrollo con Claude:

Paso 1: "Escribe tests para un servicio de descuentos que:
         - Aplique 10% a compras > $100
         - Aplique 20% a compras > $500
         - No aplique descuento a compras <= $100
         - Rechace montos negativos"

Paso 2: "Ejecuta los tests"
        → 4 tests failing (no hay implementación)

Paso 3: "Implementa el servicio para que pasen los tests"
        → 3 passing, 1 failing

Paso 4: "El test de montos negativos falla: expected error
         pero recibió 0. Corrige la implementación."
        → 4 passing

Por qué funciona

Compartir failures, no solo descripciones

❌ "El test de descuentos no funciona"

✅ "El test falla con:
    Expected: Error('Monto no puede ser negativo')
    Received: 0
    En: src/services/discount.test.ts:34"

El mensaje de error exacto le da a Claude toda la información que necesita para corregir.

Interview Pattern

En lugar de dar todas las instrucciones upfront, deja que Claude pregunte:

Usuario: "Necesito implementar un sistema de notificaciones"

Claude: "Antes de implementar, necesito entender algunos aspectos:
1. ¿Qué canales? (email, push, SMS, in-app)
2. ¿Las notificaciones son en tiempo real o batch?
3. ¿Hay templates predefinidos o contenido dinámico?
4. ¿Necesitas retry para fallos de delivery?
5. ¿Hay preferencias de usuario (opt-out por canal)?"

Cuándo es útil el interview pattern

Cuándo NO usar interview pattern

Batching de issues

Todos los issues en un solo mensaje

Apropiado cuando los issues interactúan entre sí:

"Corrige estos 3 issues en el componente UserForm:
1. El validation message no se limpia al corregir el campo
2. El botón submit se habilita antes de que todos los campos sean válidos
3. El estado del form no se resetea después de submit exitoso"

→ Claude ve las 3 correcciones juntas y puede implementar
   una solución coherente que no cree conflictos entre fixes.

Issues secuenciales (uno a uno)

Apropiado cuando los issues son independientes:

Mensaje 1: "Agrega lazy loading a las imágenes del catálogo"
→ Claude implementa, tú verificas

Mensaje 2: "Cambia el formato de fecha en el dashboard a DD/MM/YYYY"
→ Claude implementa, tú verificas

Regla de decisión

Si corregir issue A puede afectar la solución de issue B → envíalos juntos. Si son completamente independientes → envíalos secuencial para verificar cada uno.


← Cap 10: Commands y Skills · Índice · Cap 12: Claude Code en CI/CD →