Aprende a crear especificaciones de funciones de Claude Code a partir del código extrayendo el comportamiento real de rutas y componentes, y generando una especificación viva y una lista de brechas.

La gente discute sobre lo que hace una app porque recuerda distintas versiones. Soporte recuerda el último ticket enojado. Ventas recuerda la ruta de la demo. Ingenieros recuerdan lo que la funcionalidad debía hacer. Pregunta a tres personas y obtendrás tres respuestas seguras, y ninguna coincide con la versión actual.
Con el tiempo, el código se convierte en la única fuente que se mantiene actual. La documentación se desvía, los tickets se cierran y las correcciones rápidas se acumulan. Una ruta obtiene una nueva regla de validación. Un interruptor de UI cambia un valor por defecto. Un handler empieza a devolver errores distintos. Nadie actualiza la especificación porque parece opcional y cada cambio parece demasiado pequeño para documentarlo.
Eso crea problemas previsibles. Los equipos envían cambios que rompen casos límite que no conocían. QA prueba la ruta feliz y pierde reglas ocultas en los handlers. Los nuevos integrantes copian el comportamiento desde la UI sin entender las restricciones reales. Los interesados discuten opiniones en lugar de señalar un comportamiento acordado.
Un buen resultado no es un documento perfecto. Es claridad compartida. Todo el mundo debería poder responder: "¿Qué pasa si hago X?" y "¿Qué garantiza el sistema?" sin adivinar. Obtienes menos sorpresas, ciclos de revisión más cortos y menos momentos de “Espera, eso ya lo hace” porque el equipo mira la misma verdad.
Cuando una spec coincide con el código, es seguro planear cambios. Puedes ver qué es estable, qué es accidental y qué falta antes de hacer el release.
Una especificación viva es una descripción corta y editable de lo que la app hace hoy. No es un documento único. Cambia cada vez que cambia el comportamiento, para que el equipo pueda confiar en ella.
Cuando la gente habla de especificaciones de funciones escritas desde el código (por ejemplo, usando Claude Code), el objetivo es simple: leer el comportamiento real desde rutas, handlers y pantallas, y luego escribirlo en lenguaje llano.
Una especificación viva útil se centra en lo que los usuarios ven y en lo que el sistema promete. Debe cubrir:
Lo que no debe cubrir es cómo está organizado el código. Si empiezas a nombrar archivos y planes de refactor, estás entrando en detalles de implementación. Evita:
La lista de brechas es algo aparte. Es una pequeña lista de desajustes e incógnitas que encuentras al redactar la spec.
Ejemplo: una ruta rechaza archivos mayores de 10MB, pero la UI dice 25MB. Eso es una brecha hasta que el equipo decida qué regla es la real y actualice el código o la spec.
Empieza pequeño. Si intentas documentar toda la app, acabarás con un montón de notas en las que nadie confía. Elige una porción que los usuarios puedan describir en una frase, como “invitar a un compañero”, “checkout” o “restablecer contraseña”. Buenos alcances son un área de funcionalidad, un módulo o un recorrido de usuario desde el punto de entrada hasta el resultado.
Elige tu punto de entrada según dónde viva la verdad:
Antes de leer código, recopila algunas entradas para que los desajustes sobresalgan rápido: cualquier doc de API existente, notas antiguas de producto, tickets de soporte y los “puntos de dolor conocidos” que la gente menciona. Estos no anulan el código, pero te ayudan a notar estados faltantes como errores, casos límite y permisos.
Mantén el formato de la spec aburrido y consistente. Los equipos se alinean más rápido cuando cada spec se lee igual.
Usa esta estructura repetidamente y tus especificaciones serán legibles, comparables y fáciles de actualizar.
Empieza por puntos de entrada del servidor. Rutas y handlers muestran “qué hace la app” en términos concretos: quién puede llamarla, qué deben enviar, qué reciben y qué cambia en el sistema.
Lista las rutas en alcance y mapea cada una a una intención de usuario. No escribas “POST /api/orders.” Escribe “Realizar un pedido” o “Guardar un borrador.” Si no puedes nombrar la intención en palabras simples, eso ya es una brecha en la spec.
Mientras lees cada handler, captura inputs y reglas de validación como requisitos visibles para el usuario. Incluye campos obligatorios, formatos permitidos y las reglas que generan errores reales. Por ejemplo: “El email debe ser válido”, “La cantidad debe ser al menos 1”, “La fecha de inicio no puede ser en el pasado.”
Escribe las comprobaciones de auth y roles de la misma forma. En lugar de “middleware: requireAdmin”, documenta: “Solo los administradores pueden cancelar cualquier pedido. Los usuarios regulares solo pueden cancelar su propio pedido dentro de 10 minutos.” Si el código comprueba propiedad, feature flags o límites por tenant, inclúyelos también.
Luego anota salidas y resultados. ¿Qué devuelve el éxito (un ID creado, un objeto actualizado)? ¿Cómo lucen los fallos comunes (401 no autenticado, 403 no permitido, 404 no encontrado, 409 conflicto, 422 error de validación)?
Finalmente, registra los efectos secundarios porque son parte del comportamiento: registros creados o actualizados, emails o notificaciones enviados, eventos publicados, jobs en background encolados y cualquier cosa que desencadene otros flujos. Estos detalles evitan sorpresas cuando los equipos confían en la spec más adelante.
Las rutas te dicen qué puede hacer la app. Los componentes te dicen lo que los usuarios realmente experimentan. Trata la UI como parte del contrato: qué aparece, qué se bloquea y qué pasa cuando algo falla.
Empieza por encontrar las pantallas de entrada para la funcionalidad. Busca el componente de página, el layout y algunos componentes de “decisión” que controlan fetch, permisos y navegación. Ahí suele estar el comportamiento real.
Al leer componentes, captura reglas que los usuarios pueden percibir: cuándo las acciones están deshabilitadas, pasos requeridos, campos condicionales, estados de carga y cómo aparecen los errores (errores inline bajo el campo vs toast, reintento automático, botones de “intentar de nuevo”). También anota comportamiento de estado y caché como datos obsoletos mostrando primero, actualizaciones optimistas o timestamps de “último guardado”.
Fíjate en flujos ocultos que cambian silenciosamente lo que los usuarios ven. Busca feature flags, buckets de experimentos y puertas solo para admins. Anota redirecciones silenciosas también, como enviar usuarios desconectados al inicio de sesión o enviar usuarios sin acceso a una pantalla de upgrade.
Un ejemplo concreto: en una pantalla de “Cambiar email”, documenta que Guardar permanece deshabilitado hasta que el email sea válido, aparece un spinner durante la petición, el éxito muestra un banner de confirmación y los errores de validación del backend se renderizan bajo el input. Si el código muestra una flag como newEmailFlow, anota ambas variantes y qué difiere.
Escribe cada flujo de UI como pasos cortos (qué hace el usuario, qué hace la UI a cambio) y mantiene condiciones y errores junto al paso que afectan. Eso mantiene la spec legible y hace que las brechas sean más fáciles de detectar.
Las notas crudas de rutas y componentes son útiles, pero difíciles de discutir. Reescribe lo que observaste en una spec que un PM, diseñador, QA e ingeniero puedan leer y acordar.
Un patrón práctico es una historia de usuario por ruta o pantalla. Manténlo pequeño y específico. Por ejemplo: “Como usuario autenticado, puedo restablecer mi contraseña para recuperar el acceso.” Si el código muestra comportamiento distinto por rol (admin vs usuario), sepáralo en historias distintas en lugar de esconderlo en notas al pie.
Luego escribe criterios de aceptación que reflejen rutas reales del código, no el producto ideal. Si el handler devuelve 401 cuando falta el token, ese es un criterio. Si la UI deshabilita enviar hasta que un campo sea válido, ese es un criterio.
Incluye reglas de datos en lenguaje claro, especialmente las que causan sorpresas: límites, ordenamientos, unicidad, campos obligatorios. “Los nombres de usuario deben ser únicos (comprobado al guardar)” es más claro que “índice único.”
Los casos límite suelen ser la diferencia entre un buen documento y uno útil. Señala estados vacíos, valores nulos, reintentos, timeouts y qué ven los usuarios cuando una llamada a la API falla.
Cuando topes con incógnitas, márcalas en lugar de adivinar:
Esos marcadores se convierten en preguntas rápidas para el equipo en lugar de suposiciones silenciosas.
Una lista de brechas no es un segundo Jira. Es un registro corto y basado en evidencia de dónde el código y el comportamiento previsto no coinciden, o dónde nadie puede explicar claramente qué es “correcto”. Bien hecha, se convierte en una herramienta de acuerdo, no en una pelea de planificación.
Sé estricto sobre lo que cuenta como brecha:
Cuando registres una brecha, incluye tres partes para que se mantenga fundamentada:
La evidencia es lo que evita que la lista se convierta en opiniones. Por ejemplo: “POST /checkout/apply-coupon acepta cupones expirados, pero CouponBanner.tsx los bloquea en la UI. Impacto: ingresos y confusión del usuario. Tipo: bug o decisión faltante (confirmar regla real).”
Manténla corta. Pon un límite, como 10 ítems en la primera pasada. Si encuentras 40 problemas, agrúpalos en patrones (inconsistencias de validación, comprobaciones de permisos, estados vacíos) y conserva solo los ejemplos más representativos.
Evita fechas y programación dentro de la lista de brechas. Si necesitas propiedad, mantenlo ligero: anota quién debe tomar la decisión (producto) o quién puede verificar el comportamiento (ingeniería) y traslada la planificación real a tu backlog.
Elige un alcance pequeño y de alto tráfico: checkout con códigos promocionales y opciones de envío. El objetivo no es reescribir todo el producto, sino capturar lo que la app hace hoy.
Empieza por las rutas del backend. Ahí suelen aparecer las reglas primero. Podrías encontrar rutas como POST /checkout/apply-promo, GET /checkout/shipping-options y POST /checkout/confirm.
Desde esos handlers, redacta el comportamiento en palabras claras:
Luego verifica componentes de UI. Un PromoCodeInput puede mostrar que los totales solo se actualizan tras una respuesta exitosa y que los errores se muestran inline bajo el input. Un componente ShippingOptions puede seleccionar automáticamente la opción más barata al cargar y desencadenar una actualización completa del desglose de precios cuando el usuario la cambia.
Ahora tienes una spec legible y una pequeña lista de brechas. Por ejemplo: los mensajes de error difieren entre la ruta de promo y la UI (“Invalid code” vs “Not eligible”), y nadie puede señalar una regla clara de redondeo de impuestos (por línea vs total del pedido).
En la planificación, el equipo acuerda la realidad primero y luego decide qué cambiar. En lugar de debatir opiniones, revisas comportamientos documentados, eliges una inconsistencia a arreglar y dejas el resto como “comportamiento actual conocido” hasta que valga la pena revisarlo.
Una spec solo ayuda si el equipo acuerda que coincide con la realidad. Haz una lectura corta con un ingeniero y una persona de producto. Manténla estrecha: 20–30 minutos centrados en lo que los usuarios pueden hacer y qué hace el sistema en respuesta.
Durante la revisión, convierte afirmaciones en preguntas de sí/no. “Cuando un usuario llama a esta ruta, ¿siempre devolvemos 403 sin sesión?” “¿Este estado vacío es intencional?” Esto separa el comportamiento intencional del accidental que se coló con el tiempo.
Alineen el vocabulario antes de editar. Usa las palabras que ven los usuarios en la UI (etiquetas de botones, títulos de página, mensajes). Añade nombres internos solo cuando ayuden a los ingenieros a encontrar el código (nombres de rutas, nombres de componentes). Esto evita desajustes como que producto diga “Workspace” mientras la spec dice “Org”.
Para mantenerla actual, haz explícita la propiedad y la cadencia:
Si usas una herramienta como Koder.ai, los snapshots y rollback pueden ayudarte a comparar “antes” y “después” del comportamiento cuando actualizas una spec, especialmente tras un refactor grande.
La forma más rápida de perder la confianza en una spec es describir el producto que quieres, no el producto que tienes. Mantén una regla dura: cada afirmación debe respaldarse con algo que puedas señalar en el código o en una pantalla real.
Otra trampa común es copiar la forma del código en el documento. Una spec que lee “Controller -> Service -> Repository” no es una spec, es un mapa de carpetas. Escribe en términos visibles para el usuario: qué desencadena la acción, qué ve el usuario, qué se guarda y cómo lucen los errores.
Los permisos y roles a menudo se ignoran hasta el final y entonces todo falla. Añade reglas de acceso temprano, incluso si son desordenadas. Señala qué roles pueden ver, crear, editar, borrar, exportar o aprobar, y dónde se aplica la regla (solo UI, solo API o ambos).
No omitas los caminos no felices. El comportamiento real se esconde en reintentos, fallos parciales y reglas basadas en tiempo como expiraciones, cooldowns, jobs programados o límites “solo una vez al día”. Trata estos casos como comportamientos de primera clase.
Una forma rápida de sacar brechas es comprobar:
Finalmente, mantén tu lista de brechas en movimiento. Cada brecha debe etiquetarse como: “desconocido, necesita decisión”, “bug, arreglar” o “feature faltante, planificar”. Si nada se etiqueta, la lista se atora y la spec deja de ser “viva”.
Haz una pasada rápida por claridad, cobertura y accionabilidad. Alguien que no la escribió debe entender qué hace la función hoy y qué sigue sin estar claro.
Lee la spec como un nuevo compañero en su primer día. Si puede resumir la función en un minuto, estás cerca. Si sigue preguntando “¿dónde empieza esto?” o “¿cuál es la ruta feliz?”, ajusta la apertura.
Comprueba:
Cada brecha debe ser específica y comprobable. En lugar de “Manejo de errores poco claro”, escribe: “Si el proveedor de pagos devuelve 402, la UI muestra un toast genérico; confirmar mensaje deseado y comportamiento de reintento.” Añade una única acción siguiente (preguntar a producto, añadir un test, inspeccionar logs) y anota quién debe responder.
Elige una área funcional y ponle un límite de tiempo de 60 minutos. Escoge algo pequeño pero real (login, checkout, búsqueda, una pantalla de admin). Escribe una oración de alcance: qué incluye y qué queda fuera.
Ejecuta el flujo una vez de extremo a extremo: revisa por encima rutas/handlers clave, traza el flujo UI principal y anota comportamientos observables (inputs, outputs, validación, estados de error). Si te quedas atascado, registra la pregunta como brecha y sigue adelante.
Cuando termines, comparte la spec donde el equipo pueda comentar y establece una regla: cualquier cambio de comportamiento enviado debe actualizar la spec en la misma ventana de entrega, aunque sean cinco líneas.
Mantén las brechas separadas del backlog. Agrúpalas en “comportamiento desconocido”, “comportamiento inconsistente” y “tests faltantes”, y repásalas brevemente cada semana para decidir qué importa ahora.
Si redactar e iterar se siente lento, un generador en chat como Koder.ai puede ayudarte a conseguir una primera versión rápidamente. Describe la función, pega fragmentos clave o nombres de rutas, refina el texto en conversación y exporta la fuente cuando la necesites. La idea es velocidad y claridad compartida, no un proceso mayor.
Comienza con una porción pequeña y visible para el usuario (por ejemplo, “restablecer contraseña” o “invitar a un compañero”). Lee las rutas/handlers para captar reglas y resultados, luego revisa el flujo de UI para registrar lo que los usuarios realmente ven (estados deshabilitados, errores, redirecciones). Redáctalo usando una plantilla consistente y registra las incógnitas en una lista de brechas separada.
Por defecto: trata el comportamiento actual del código como la fuente de la verdad y documéntalo.
Si el comportamiento parece accidental o inconsistente, no lo “arregles” en la especificación: márcalo como una brecha con evidencia (dónde lo viste y qué hace) y pide una decisión para actualizar el código o la especificación.
Mantenla aburrida y repetible. Una plantilla práctica es:
Esto mantiene las especificaciones legibles y facilita detectar desajustes.
Escribe las reglas como requisitos visibles para el usuario, no como notas de código.
Ejemplos:
Incluye qué desencadena un error y qué experimenta el usuario cuando ocurre.
Céntrate en lo observable:
Los efectos secundarios importan porque afectan a otras funciones y a las expectativas de soporte/ops.
Si la UI bloquea algo que la API permite (o al revés), regístralo como una brecha hasta que se tome una decisión.
Anota:
Luego acuerden una regla y actualicen tanto el código como la especificación para que coincidan.
Mantén la lista de brechas pequeña y basada en evidencia. Cada ítem debe incluir:
Evita programar o convertirla en una segunda lista de tareas.
Documenta explícitamente en lugar de esconderlos.
Incluye:
Ahí suelen aparecer sorpresas y bugs.
Hazlo corto: una lectura de 20–30 minutos con un ingeniero y una persona de producto.
Convierte las afirmaciones en comprobaciones de sí/no (por ejemplo, “¿Siempre devolvemos 403 si no hay sesión?”). Alineen el vocabulario usando las palabras que aparecen en la UI (etiquetas y mensajes) para que todos signifiquen lo mismo.
Acerca la especificación al código y haz que las actualizaciones sean parte del envío.
Defaults prácticos:
La meta son ediciones pequeñas y frecuentes, no una gran reescritura.