Dejé que CodeSpeak se hiciera cargo de mi repositorio

han evolucionado significativamente con el tiempo, volviéndose cada vez más abstractos y más fáciles de entender para los humanos. En los primeros días de la informática, los programadores trabajaban directamente con código de máquina, ingresando manualmente instrucciones binarias sin procesar mediante tarjetas perforadas, donde los agujeros codificaban datos y comandos para las primeras computadoras centrales. Este proceso era tedioso y muy propenso a errores: un único agujero fuera de lugar podía romper todo el programa y obligar a los desarrolladores a empezar de nuevo desde cero.

Para reducir esta fricción, surgió el lenguaje ensamblador, que reemplazó el código binario sin formato con mnemónicos legibles por humanos como ADD o MOV, que luego se tradujeron nuevamente a instrucciones de máquina.

El siguiente gran salto se produjo en la década de 1950, cuando aparecieron los primeros lenguajes compilados de alto nivel, como FORTRAN y COBOL. Introdujeron una sintaxis más cercana a la notación matemática y al lenguaje natural. Más tarde, lenguajes como ALGOL, C y C++ trajeron programación estructurada, abstracción de memoria y conceptos orientados a objetos, reduciendo drásticamente la complejidad del software y mejorando la mantenibilidad.

Los lenguajes modernos como Python y Java continuaron esta tendencia al priorizar la legibilidad y ofrecer vastos ecosistemas de bibliotecas integradas, lo que permite a los ingenieros concentrarse más en resolver problemas comerciales en lugar de lidiar con detalles a nivel de hardware.

Sin embargo, más recientemente, la forma en que escribimos código ha comenzado a cambiar nuevamente con el aumento y la adopción generalizada de la IA. Naturalmente, esto plantea la pregunta: ¿evolucionarán también los lenguajes de programación?

Parece cada vez más plausible que algún día terminemos codificando en inglés sencillo. Es por eso que estaba emocionado de probar uno de estos lenguajes potenciales del futuro: CodeSpeak, actualmente disponible en versión preliminar alfa. Veamos cómo funciona.

Configurando todo

Como de costumbre, antes de empezar a construir, primero debemos configurar todo. Afortunadamente, el proceso es bastante sencillo. Podemos instalar CodeSpeak usando el administrador de paquetes uv:

instalación de la herramienta uv codespeak-cli codespeak –versión # CodeSpeak CLI 0.4.1

A continuación, debemos iniciar sesión. Al ejecutar el siguiente comando, se abre una ventana del navegador donde puede autenticarse con su cuenta de Google o crear un nombre de usuario y contraseña exclusivos de CodeSpeak. Después de aceptar los Términos y condiciones, serás autorizado exitosamente.

iniciar sesión en código

El último paso es configurar su clave API, ya que CodeSpeak sigue una política de Traiga su propia clave. Por el momento, solo admite una clave API de Anthropic, lo cual tiene sentido dado lo populares que son los modelos Anthropic para tareas de codificación en este momento. Puede generar su clave en https://platform.claude.com/settings/keys y exportarla como una variable de entorno.

exportar ANTHROPIC_API_KEY=

Y eso es todo. Estamos listos para comenzar a construir.

Construyendo con CodeSpeak

CodeSpeak admite el desarrollo totalmente nuevo cuando se reúne una especificación y se construye a partir de ella. Sin embargo, pensé que sería más interesante probarlo en un proyecto algo más maduro (o al menos uno que ya sea funcional) y ver qué tan bien maneja una base de código existente.

En mi artículo anterior, creé una aplicación web para rastrear y analizar datos de entrenamiento mediante un desarrollo basado en especificaciones. Lo he estado usando activamente desde entonces y ya encontré varias áreas de mejora, por lo que me pareció un buen candidato para probar CodeSpeak.

Tomar el control

Antes de usar CodeSpeak para implementar nuevas funciones, primero debemos generar una versión inicial de las especificaciones. Afortunadamente, CodeSpeak también puede ayudar con eso.

Comencé copiando todo el código de mi aplicación de fitness en un nuevo repositorio. Luego, eliminé todas las especificaciones existentes y el archivo de constitución para emular un escenario más realista cuando codificaste algo rápidamente y ahora quieres migrar el proyecto a un flujo de trabajo más estructurado con CodeSpeak.

CodeSpeak te permite migrar solo partes o módulos seleccionados de un proyecto, pero yo decidí hacer todo lo posible y mover toda la aplicación. El repositorio contiene alrededor de 13.000 líneas de código, por lo que, si bien no es enorme, sigue siendo un proyecto de tamaño razonable para un experimento como este.

Podemos comenzar a generar especificaciones con el siguiente comando.

adquisición de lenguaje de código

Luego, CodeSpeak dedica algún tiempo a analizar sus archivos locales. En mi caso, todo el proceso tomó alrededor de un minuto. Después de eso, abrió una página web con una estructura propuesta para el código base. Sugirió dividir mi aplicación en cuatro módulos: Frontend, API de backend, capa de datos y pruebas de backend.

Los módulos son un concepto de programación bien establecido y es fácil ver por qué son útiles: crean dominios autónomos más pequeños, mejoran la legibilidad y facilitan la reutilización de componentes en todos los proyectos. Entonces, es maravilloso que CodeSpeak nos sugiera crear 4 especificaciones diferentes en lugar de intentar poner todo en un documento largo.

Imagen del autor

En el navegador, puede revisar cada módulo y pedirle a CodeSpeak que lo divida, fusione o lo reconsidere. En mi caso, la estructura sugerida parecía razonable, por lo que decidí mantener todo como está y migrar todos los módulos, permitiendo que CodeSpeak administre todo el repositorio.

Después de seleccionar todos los módulos e iniciar la adquisición, CodeSpeak los procesó uno por uno: leyendo archivos, generando especificaciones, refinándolos y ejecutando pruebas.

Imagen del autor

Al final, creó un directorio de especificaciones que contiene cuatro archivos de especificaciones (uno para cada módulo). Echemos un vistazo a uno de ellos, frontend.cs.md.

El documento comienza con una declaración de importación: import specs/backend_api.cs.md. Las importaciones se utilizan para rastrear las dependencias entre módulos y mantener el contexto para el agente. Por ejemplo, cuando el agente trabaja con la especificación de frontend, sabe que debe cargar primero la especificación de API de backend. Dado que la especificación de la API de backend importa la especificación de la capa de datos, el agente también la incorpora automáticamente. Como resultado, obtiene todo el contexto necesario antes de realizar cambios en la interfaz. Esto es bastante conveniente y permite una descomposición limpia del código base, similar a cómo se manejan las dependencias y abstracciones en la ingeniería de software tradicional.

El resto del documento sigue un formato estructurado y describe todas las partes principales de la interfaz: desde la pila tecnológica hasta la autenticación, la funcionalidad a nivel de página y la cobertura de prueba existente.

Frontend SPA ├── Pila y configuración ├── Autenticación ├── Diseño y navegación ├── Cliente API ├── Páginas │ ├── Historial (/history) │ │ ├── Tarjeta de resumen semanal │ │ ├── Gráfico de tendencias de entrenamiento de 12 semanas │ │ └── Lista de sesiones │ ├── Registro de entrenamiento (/log) │ │ ├── Forma cardiovascular │ │ └── Forma de fuerza │ ├── Detalle de la sesión (/sessions/:id) │ │ ├── Detalle de sesión de fuerza │ │ └── Detalle de sesión de cardio │ ├── Plantillas (/templates) │ ├── Configuración (/settings) │ │ ├── Tipos de actividad │ │ ├── Tipos de ejercicios │ │ └── Ejercicios │ └── Iniciar sesión (/login) ├── Componentes compartidos │ ├── EjercicioEntryBlock │ ├── TimeInput │ └── ProtectedRoute ├── Módulos de utilidad │ ├── dateUtils │ └── unitUtils └── Pruebas ├── LoginPage.test.tsx └── TimeInput.test.tsx

A primera vista, las especificaciones generadas parecían bastante completas y parecían capturar bien la mayoría de los detalles de implementación (incluso cosas pequeñas como mi preferencia por la fuente Montserrat).

Por supuesto, las primeras impresiones pueden ser engañosas, así que decidí probarlas adecuadamente. Convenientemente, todavía tenía todas las especificaciones originales utilizadas para crear la aplicación. Esto hizo posible comparar las especificaciones generadas por CodeSpeak con las originales mediante un LLM.

El veredicto fue en gran medida positivo: las especificaciones generadas capturaron bien la gran mayoría de los detalles de implementación. Sin embargo, faltaban algunas cosas.

Las principales brechas fueron la misión del proyecto (por qué estamos construyendo esto) y la hoja de ruta (planes futuros), lo cual es bastante esperado ya que ninguno de los dos se puede inferir fácilmente solo del código.

También faltaron algunos matices de implementación más pequeños, como qué significa exactamente un "cambio de plantilla" o las fórmulas precisas utilizadas para generar automáticamente títulos para entrenamientos de fuerza y ​​​​cardio. No consideraría críticas estas omisiones, ya que en muchos casos un LLM probablemente podría inferirlas cuando sea necesario.

En general, CodeSpeak hizo un excelente trabajo generando especificaciones que explican una base de código existente. Pero generar especificaciones nunca fue el objetivo final aquí, así que pongámoslas en práctica y construyamos algo.

Implementando una característica

Ya estoy usando la aplicación para realizar un seguimiento de mis entrenamientos, pero también me gustaría recibir comentarios de un entrenador de IA para saber si mi entrenamiento va por el camino correcto. Con el tiempo, me encantaría tener un asistente de IA totalmente integrado dentro de la aplicación, pero comencemos poco a poco y agreguemos la capacidad de generar un resumen del entrenamiento como texto que se pueda copiar y compartir con una IA.

Dado que estamos trabajando en un flujo de trabajo de desarrollo basado en especificaciones, la implementación de esta característica comienza con la actualización de la especificación. El cambio está principalmente relacionado con la interfaz de usuario, por lo que edité frontend.cs.md y agregué una descripción de la nueva funcionalidad.

Imagen del autor

Después de eso, podría crear la función con el siguiente comando, que implementa los cambios y garantiza que todas las pruebas pasen. Hasta donde tengo entendido, para implementar el cambio, CodeSpeak analiza la diferencia de especificaciones e intenta generar código que coincida.

codespeak construir frontend.cs.md

Consejo: si solo desea una implementación rápida sin el flujo de validación completo, puede usar codespeak impl en su lugar.

Después de ejecutar el comando, CodeSpeak comenzó leyendo las especificaciones y analizando lo que era necesario cambiar. Inicialmente, comenzó a agregar encabezados CodeSpeak a muchos archivos, lo cual fue un poco confuso ya que obviamente no estaba relacionado con mi solicitud. Con suerte, esto sucede sólo en la primera ejecución.

# Generado por CodeSpeak a partir del archivo de especificaciones: specs/backend_api.cs.md # Se DESACONSEJA modificar este archivo manualmente. # CodeSpeak intentará conservar los cambios manuales, pero no está garantizado.

Una vez que terminó con los encabezados, identificó correctamente la tarea principal: agregar un botón de copia de resumen del entrenamiento a cada fila de sesión en la página Historial. Implementó el cambio, pasaron todas las pruebas y la compilación se marcó como exitosa.

Imagen del autor

Es hora de probarlo. La forma más sencilla de validar un cambio en la interfaz de usuario es simplemente ejecutar la aplicación e inspeccionarla. Entonces, lancé el proyecto localmente con Docker Compose. El nuevo botón de copiar apareció al lado de cada sesión en la vista del historial y funcionó correctamente para los entrenamientos de fuerza. Sin embargo, cuando intenté copiar una sesión de cardio, falló. Peor aún, falló silenciosamente sin errores ni en la consola del navegador ni en los registros de Docker.

Imagen del autor

Entonces ahora teníamos un error. Es importante destacar que el problema no estaba en la especificación, sino en la implementación misma. Para solucionar este problema, podemos utilizar una solicitud de cambio de código. Para cambios más pequeños, CodeSpeak admite una cómoda frase breve.

codespeak change frontend.cs.md -m "Formato de soporte de entrenamiento cardiovascular para el botón copiar"

En mi caso, la solicitud era un poco más compleja, por lo que elegí crear un archivo de solicitud de cambio dedicado.

cambio de codespeak –new # Solicitud de cambio de plantilla creada en # /Users/marie/Documents/github/trainlytics_codespeak/change-request.cs.md

Dentro del archivo, agregué la siguiente solicitud que cubre tanto la corrección de errores como un mejor soporte de depuración.

– Admite la copia de resúmenes para entrenamientos cardiovasculares, ya que actualmente falla (probablemente debido a un formato de datos diferente). – Agrega registro para fallas de copia, ya que los problemas actualmente no aparecen ni en los registros de la consola del navegador ni en los registros de Docker.

Después de eso, le pedí a CodeSpeak que implementara el cambio.

cambio de lenguaje de código frontend.cs.md

Imagen del autor

Antes de realizar modificaciones, CodeSpeak primero validó si los cambios de código solicitados eran consistentes con las especificaciones existentes. Si una solicitud contradice la especificación, lo obliga a revisar la solicitud o actualizar la especificación primero y reconstruir a partir de ahí. Esto me pareció particularmente útil, ya que ayuda a reducir la divergencia entre las especificaciones y la implementación.

Al final, CodeSpeak solucionó el problema y también agregó pruebas para evitar regresiones similares en el futuro.

Entonces, creamos y probamos con éxito una nueva característica y al mismo tiempo aprendimos cómo trabajar con un lenguaje de programación emergente diseñado para la era de la IA. Dicho esto, concluyamos y reflexionemos sobre la experiencia.

Resumen

En general, creo que este experimento fue bastante exitoso. CodeSpeak logró hacerse cargo de un repositorio con más de 10.000 líneas de código sin perder ningún detalle de implementación crucial, lo cual es realmente impresionante. Después de eso, actualizamos la especificación y creamos nuevas funciones directamente a partir de ella.

El primer intento de implementación no fue perfecto, pero después de enviar una solicitud de cambio de código, CodeSpeak no solo corrigió el error sino que también agregó pruebas para evitar que se reintroduzcan problemas similares en futuras compilaciones. Me gustaron especialmente estas barandillas automáticas, ya que ayudan a que el producto esté más preparado para el futuro.

La experiencia de construir con CodeSpeak fue bastante diferente del flujo de trabajo de desarrollo basado en especificaciones que exploré anteriormente. Permítanme resaltar algunas diferencias clave.

En el desarrollo tradicional basado en especificaciones, las especificaciones a menudo las generan los LLM y pueden llegar a ser bastante largas. Si bien son completos, esto puede hacer que sea más difícil para los humanos leerlos, mantenerlos y evolucionar con el tiempo. CodeSpeak parece seguir una filosofía muy diferente: las especificaciones son intencionalmente concisas y contienen sólo la información mínima necesaria para generar código. Están destinados a ser leídos y editados por humanos, potencialmente con algo de ayuda de IA.

Esto también deja claro que CodeSpeak está diseñado principalmente para ingenieros. Para utilizarlo de forma eficaz, aún es necesario comprender la estructura modular de un sistema y realizar cambios intencionales en las especificaciones en consecuencia. Por el contrario, se puede decir que el desarrollo basado en especificaciones se puede adoptar con mucha menos experiencia en ingeniería, ya que el flujo de trabajo suele estar más cerca de conversar con un agente y almacenar decisiones intermedias en un repositorio para preservar la intención y el contexto.

Sin embargo, debo admitir que CodeSpeak fue bastante diferente de lo que esperaba inicialmente. He usado más de una docena de lenguajes de programación antes y CodeSpeak realmente no se parece a ninguno de ellos. De hecho, la principal innovación parece tener menos que ver con el lenguaje en sí y más con las herramientas y el flujo de trabajo creados a su alrededor, lo cual es un cambio interesante.

A diferencia de los lenguajes de programación tradicionales con sintaxis y reglas semánticas estrictas, CodeSpeak le permite escribir especificaciones en inglés sencillo con muy pocas restricciones. Esta flexibilidad es poderosa, pero también conlleva desventajas obvias: como todos sabemos, una indicación mal escrita probablemente conducirá a una implementación deficiente.

Así que mi esperanza es que a medida que CodeSpeak madure (y vale la pena recordar que todavía está en la vista previa alfa), desarrolle un enfoque más obstinado para escribir especificaciones de alta calidad, junto con mejores herramientas para validarlas y mejorarlas.