DEV Community

Cover image for Dejé de vibecodeear y empecé a entregar: Task-Driven Development con AI
Luis A. Obando
Luis A. Obando

Posted on

Dejé de vibecodeear y empecé a entregar: Task-Driven Development con AI

Hace un año escribí sobre cómo construí ExamGenius con vibe coding y Claude. La premisa era simple: le dices al AI qué quieres, él genera el código, tú ajustas, y en 20 horas tienes una app completa que normalmente tomaría semanas. Reducción del 85% en tiempo. Código funcional. Todo bien.

Un año después, la industria avanzó a pasos agigantados. Los modelos son más capaces, los IDEs integran AI de forma nativa, y cada vez más equipos están shipeando código generado por IA a producción. Pero hay un problema que nadie quiere admitir: estamos generando cantidades masivas de código que nadie revisó de verdad.

Se siente productivo. Pero el resultado muchas veces es código difícil de mantener, sin tests, sin estructura clara, y sin trazabilidad de por qué se tomaron ciertas decisiones. Vibe coding se siente bien hasta que tienes que debuggear algo que ni tú ni el AI recuerdan por qué existe.

Este post es sobre lo que viene después del vibe coding.

El problema real: sin estructura, hasta el mejor dev genera ruido

Seamos honestos: el AI produce código que muchos senior devs no podrían escribir tan rápido ni tan limpio. El problema no es la calidad del código — es la falta de dirección.

Sin tareas claras, el AI divaga. Le dices "arregla este bug" y te refactoriza medio módulo. Sin scope definido, un "mejora esto" se convierte en un cambio de 15 archivos que nadie pidió. El dev pierde visibilidad de qué se hizo, qué falta, y qué se rompió en el camino. No es un problema de competencia — es un problema de contexto. El AI no sabe qué decisiones ya tomaste, qué patrones sigue tu codebase, ni cuál es el scope real de lo que necesitas.

Con ExamGenius funcionó porque era un proyecto greenfield — una sola sesión, sin código legacy, sin otros colaboradores. Pero en proyectos reales que evolucionan semana a semana, el vibe coding puro no escala.

Y en el enterprise — donde hay equipos, code reviews, compliance, y producción real — es simplemente insuficiente. No puedes llegar a un PR review diciendo "el AI lo generó y se veía bien". Necesitas poder explicar qué se hizo, por qué, y bajo qué criterios se validó.

La alternativa: Task-Driven Development

La idea es simple: definir el trabajo antes de ejecutarlo.

En vez de abrir el chat y decir "hazme esto", defines una tarea con scope claro, la descompones en subtasks si es necesario, y le das al AI el contexto preciso para ejecutar cada pieza. El flujo se ve así:

  1. Spec — defines qué quieres lograr y por qué
  2. Tasks — descompones el trabajo en unidades manejables
  3. Subtasks — si una tarea es grande, la partes más
  4. Plan — antes de codear, el AI investiga el codebase y escribe un plan de implementación en la tarea. Tú lo revisas y apruebas antes de que toque una línea de código
  5. Ejecución — el AI trabaja dentro del scope definido
  6. Revisión — tú validas antes de avanzar

El paso 4 es clave y muchos se lo saltan. Pedirle al AI que planifique antes de ejecutar te da un checkpoint de revisión que vale oro. El plan refleja el estado actual del codebase — no es teoría, es una propuesta concreta que puedes aprobar, ajustar, o rechazar. Es la diferencia entre "hazlo" y "dime cómo lo harías, y luego lo haces".

El programador vuelve a ser arquitecto y revisor, no espectador. Tú decides qué se hace, el AI ejecuta. Y si algo no te convence, lo corriges antes de que se propague.

Y acá hay algo que cierra el círculo: el AI no solo ejecuta las tareas — también te ayuda a definirlas. Puedes pedirle que te sugiera subtasks, que identifique edge cases, o que proponga DoDs basados en el contexto del proyecto. Tú das la dirección general, el AI te ayuda a especificar con suficiente detalle, y luego ejecuta contra esa especificación. Es un ciclo colaborativo donde ambos aportan lo que mejor hacen.

Esto aplica tanto para side projects como para equipos enterprise. La diferencia es que en enterprise no es opcional.

Definition of Done: el AI también tiene que cumplir criterios

Acá es donde la cosa se pone interesante. Cada tarea puede tener un conjunto de Definition of Done (DoDs) — criterios que deben cumplirse antes de marcarla como completa.

Esto no es burocracia. Es calidad verificable:

  • Los tests pasan
  • No hay regresiones
  • El código sigue los patrones del proyecto
  • Las traducciones están completas
  • El logging es consistente

El AI deja de ser una caja negra que "genera código" y se convierte en un ejecutor que tiene que cumplir criterios concretos. Si no los cumple, la tarea no está terminada.

En un contexto enterprise, los DoDs son el puente entre "el AI generó código" y "este código está listo para producción". Son la evidencia de que alguien (humano o AI) validó que el trabajo cumple con los estándares del equipo.

Backlog.md: el backlog que vive en tu repo

La herramienta que uso para esto es Backlog.md — un sistema de gestión de tareas que vive directamente en tu repositorio como archivos markdown.

¿Por qué no Jira o Trello? Porque el AI no puede leer tu board de Jira. Backlog.md se integra con el IDE vía MCP (Model Context Protocol), lo que significa que el AI puede:

  • Leer las tareas pendientes
  • Entender el contexto de lo que tiene que hacer
  • Actualizar el estado cuando termina
  • Consultar los DoDs antes de marcar algo como Done

Todo queda versionado en git. Cada tarea, cada decisión, cada cambio de estado es un commit. La trazabilidad es total — puedes ver exactamente qué se hizo, cuándo, y en qué orden.

No necesitas salir del código para gestionar tu trabajo. El backlog está ahí, al lado de tu src/.

Para proyectos personales y equipos pequeños, Backlog.md es ideal por su simplicidad. En el enterprise, el concepto es el mismo pero la herramienta se conectaría al tooling existente — Jira, Linear, Azure DevOps. Lo importante no es el tool específico, sino que el AI tenga acceso al backlog, pueda leer el contexto de las tareas, y pueda validar los DoDs. El patrón de task-driven development funciona igual independientemente de dónde vivan las tareas.

Caso real: Finia

Finia es un bot de Telegram que estoy construyendo para tracking de gastos personales en Costa Rica. Parsea notificaciones bancarias, categoriza gastos con AI, genera reportes, y soporta múltiples idiomas. El backend es Python con SQLAlchemy, corre en Kubernetes, y usa structlog para logging estructurado.

Todo el desarrollo reciente lo hice con task-driven development. Acá van tres ejemplos concretos:

Refactor de handle_message

El handler principal de mensajes era un monolito de 236 líneas — un solo async def con toda la lógica de budget input, edit amount, rate limiting, chat agent, notificaciones, y tutorial. Funcionaba, pero era imposible de testear o modificar sin romper algo.

Creé TASK-2 con 4 subtasks:

  • Extraer budget input handler
  • Extraer edit amount handler
  • Extraer chat agent invocation
  • Extraer notification sending y tutorial detection

El AI ejecutó cada subtask por separado. Yo revisé cada paso. El resultado: 7 funciones enfocadas y un handle_message de ~40 líneas que solo orquesta. Los 79 tests pasaron sin cambios.

# Antes: 236 líneas en una sola función
async def handle_message(update, context):
    # ... todo mezclado ...

# Después: orquestador limpio
async def handle_message(update, context):
    user = await get_user(update.effective_user.id)
    if user is None:
        return
    text = update.message.text.strip()

    if await _handle_budget_input(update, context, user, text):
        return
    if await _handle_edit_amount(update, context, user, text):
        return
    if not await _check_rate_limit(update, user):
        return

    response = await _run_chat_agent(update, user, text)
    await _send_expense_notifications(update, context, user, response)
Enter fullscreen mode Exit fullscreen mode

i18n sweep

Finia soporta español e inglés. Pero después de varias iteraciones de desarrollo, había ~50 mensajes hardcodeados en inglés dispersos por todo el código — botones, errores, labels, prompts.

Creé TASK-4 y el AI hizo tres pasadas:

  1. Mensajes de error y botones en callbacks.py, commands.py, chat.py
  2. Bloques de uso (/expense, /sinpe), displays de budget, labels de categorías
  3. Cambiar el idioma default pre-registro a español (la mayoría de usuarios son ticos)

El DoD era claro: todos los mensajes user-facing traducidos, admin commands excluidos intencionalmente. Cada pasada fue revisada antes de continuar.

Interaction tracking

Necesitaba métricas para un dashboard de CloudWatch. Creé TASK-5: agregar command_executed en cada command handler y callback_executed en el callback handler.

El patrón tenía que ser consistente:

logger.info("command_executed", service="finia-bot", command="help", user_id=user.id)
logger.info("callback_executed", service="finia-bot", callback="chcat", user_id=user.id)
Enter fullscreen mode Exit fullscreen mode

Durante la revisión, detecté que /start usaba telegram_id en vez de user_id (porque el usuario aún no existe). Lo corregimos para incluir ambos. También encontré que commands.py no se había incluido en el commit — el AI lo había editado pero no staged. Sin la revisión paso a paso, eso se habría ido a producción incompleto.

Vibe coding vs Task-driven: la comparación

Vibe Coding Task-Driven
Inicio "Hazme un refactor de esto" TASK-2: Refactor handle_message, 4 subtasks definidas
Scope El AI decide qué cambiar Tú defines qué se toca y qué no
Validación "Se ve bien" DoDs: tests pasan, patrón consistente, sin regresiones
Trazabilidad Chat history (si no se borró) Tasks en git con estado, plan, y notas
Rollback Ctrl+Z y rezar Cada subtask es un commit atómico
Enterprise-ready No

ExamGenius fue el capítulo 1 — vibe coding funciona para prototipos y hackathons. Finia es el capítulo 2 — task-driven para proyectos que necesitan mantenerse. El enterprise es el capítulo 3 — donde este enfoque no es un nice-to-have sino un requisito.

El control es tuyo

No se trata de dejar de usar AI. Se trata de usarlo bien.

Task-driven development no es burocracia. Es darle al AI (y a ti mismo) la estructura para entregar con confianza. Defines el trabajo, estableces los criterios, revisas la ejecución. El AI es increíblemente capaz — pero necesita dirección, igual que cualquier miembro de un equipo.

El programador que define bien el trabajo, entrega mejor software. La industria avanzó — es hora de que nuestros procesos avancen también.


Finia es un proyecto en el que estoy trabajando para simplificar el tracking de gastos en Costa Rica. Si te interesa probarlo o saber más, escríbeme — está en beta y siempre busco feedback de early adopters.

Top comments (0)