Tabla de Contenidos
1. Introducción
Este módulo no enseña a programar en Java ni en Angular: eso ya lo hacéis en otros módulos. Enseña todo lo que rodea a programar cuando se trabaja con un agente de IA: el repositorio, las ramas, los contenedores, la especificación, los tests, el despliegue y las skills que hacen que todo eso se ejecute solo.
En la 1ª evaluación cada alumno monta su arnés: un repositorio preparado para trabajar así. A esto, a poner el esfuerzo en el entorno que rodea al agente (scripts, skills, tests, revisiones, CI) en vez de en programar a mano, se le llama ingeniería de arneses; en inglés, harness engineering. En la 2ª evaluación se usa ese arnés para hacer el proyecto (ver las aplicaciones de la 2ª evaluación).
Para saber a dónde se llega, lo mejor es ver cómo se trabaja cuando el arnés ya está montado. No hace falta entender ahora cada pieza: cada una se explica en su tema. Fíjate sobre todo en lo poco que hace el alumno y en lo que no hace.
Un día de trabajo en el proyecto
El proyecto es una tienda. Hoy toca el issue #12, «Alta de clientes», que está en el tablero de GitHub en Todo.
1. Start
En la carpeta del repositorio abre Claude Code y escribe:
/git-flow start 12
En unos segundos el agente responde:
Issue #12: Alta de clientes Rama <alumno>-12-alta-clientes creada desde develop. Worktree en ../tienda-wt-12-alta-clientes, con sus puertos en .env Para arrancar la aplicación: cd ../tienda-wt-12-alta-clientes && ./app.sh start
Tiene una carpeta nueva con una copia del proyecto y una rama solo para este issue. Entra en ella y arranca su aplicación:
cd ../tienda-wt-12-alta-clientes ./app.sh start
Aplicación en http://localhost:4212
Base de datos, backend y frontend, en Docker, con datos de prueba, en un puerto que no choca con nada. Si por la tarde empieza el #13, tendrá otra carpeta y otra aplicación en otro puerto, y las dos conviven. Un script y nada más: ./app.sh start, stop, status y logs.
2. Specification
Antes de escribir código, un fichero que diga qué se va a hacer. Hay dos formas, según el issue: la A, con una especificación, para los CRUD; la B, con un plan, para todo lo demás.
Forma A: SDD
El #12 es un CRUD (una entidad con su listado, alta, edición y borrado), así que va por especificación. Se abre Claude Code en el worktree y se pide:
/sdd spec create
El agente sabe qué issue es por el nombre de la rama. Lee el issue, hace dos preguntas (¿el NIF es único?, ¿el email es obligatorio?) y escribe tres ficheros en .kiro/specs/12-alta-clientes/: requisitos, diseño y tareas. Y se para. El de requisitos acaba así:
## Criterios de aceptación - Al guardar un cliente válido aparece en el listado. - Si el NIF ya existe, el formulario muestra «NIF repetido» y no se crea. - Si falta el nombre, el botón Guardar no hace nada y el campo se marca.
Y el de tareas, así:
- [ ] 1. Migración V3__clientes.sql y datos de prueba R__clientes.sql - [ ] 2. Backend: Cliente, ClienteRepository, ClienteService, ClienteController, DTO y mapper - [ ] 3. Frontend: componente cliente-form en /clientes/nuevo con validación de NIF y email
Leer y corregir esos ficheros es el trabajo importante del día. Arreglar una frase aquí cuesta un minuto; arreglar el código que sale de una frase mal escrita cuesta una tarde. Se añade un criterio que faltaba al de requisitos y se vuelve a lanzar /sdd spec create: el diseño y las tareas se rehacen con el cambio. El diseño sale igual que el de los demás CRUD de la tienda, porque el agente lee antes la arquitectura del proyecto.
Forma B: Plan
Cuando el issue no es un CRUD (por ejemplo, el #13: un filtro por provincia en el listado de clientes), en vez de usar SDD se crea directamente un plan. Se pone el agente en modo plan, en el que solo lee y no toca código, y se le dice lo que se quiere y que escriba el plan en plan_filtro-provincia.md. El agente lee el código, pregunta lo que no esté claro y deja en ese fichero la lista de tareas:
- [ ] 1. Backend: parámetro provincia en GET /api/clientes y filtro en ClienteRepository - [ ] 2. Frontend: desplegable de provincia en el listado, enlazado al parámetro
Al salir del modo plan, el fichero queda guardado en el worktree. Se lee y se corrige igual que la spec: que no falte una tarea y que cada una se pueda hacer y probar sola. Y aquí acaba la fase: el plan no se implementa en esta conversación. Si se hiciera, el contexto estaría lleno de todo lo que el agente ha leído para planificar, y eso empeora lo que programa después.
3. Implementation
Conversación nueva (/clear). Primero, lo que otros hayan cerrado en develop desde ayer, a la rama, para programar sobre el código actual:
/git-flow update
Y una sola orden, que depende de la forma:
Forma A: SDD
/sdd spec impl
Implementa las tareas de la spec del worktree.
Forma B: Plan
/code impl plan_filtro-provincia.md
Implementa las tareas del plan que se le pasa, en una conversación nueva que solo contiene el plan y el código que toca, no la planificación.
En las dos el agente va tarea a tarea: escribe la migración, las clases del backend en sus capas, el componente de Angular y los datos de prueba, siguiendo las convenciones del proyecto que tiene escritas. Después de cada tarea pasa los tests unitarios y de arquitectura y la marca como hecha en el fichero de tareas. Mientras tanto no se escribe código: se revisa lo que va saliendo.
Como el backend ha cambiado, lo reconstruye:
./app.sh start
El mismo script: reconstruye lo que ha cambiado y lo vuelve a levantar. El frontend ni eso: se recarga solo al guardar.
4. Testing
Los tests también los escribe el agente. Cuatro tipos, y para los cuatro los mismos tres verbos. Primero crearlos:
/test unit create /test arch create <reglas> /test api create <escenarios> /test e2e create <escenarios>
unit create: sin argumento, genera los tests unitarios de todas las clases que no los tienen, uno por comportamiento. Con una clase o un paquete, solo esos.arch create <reglas>: recibe las reglas de arquitectura en castellano y las convierte en tests de ArchUnit. Se lanza al empezar el proyecto y cuando cambia una regla.api create <escenarios>: recibe los escenarios que hay que probar en la API: cada endpoint con sus errores (alta válida, NIF repetido, sin nombre).e2e create <escenarios>: recibe los escenarios de extremo a extremo; lo normal, los criterios de aceptación de la spec.
Cada test se ejecuta al crearlo y se deja pasando.
Después, lanzarlos a mano, uno a uno, para verlo:
/test unit run /test arch run /test api run /test e2e run
Todo en verde. Después se abre http://localhost:4212, se da de alta un cliente, se prueba un NIF repetido. El mensaje de error no convence y se pide cambiarlo en la misma conversación. ./app.sh start y listo. Pero el cambio del mensaje rompe el test E2E que comprobaba el texto antiguo. Para eso está el tercer verbo, uno por tipo:
/test unit repair /test arch repair /test api repair /test e2e repair
Como lo que ha fallado es un test E2E, se lanza /test e2e repair. El agente mira por qué falla: el test está desactualizado por un cambio intencionado del código, así que actualiza el test. Si hubiera sido un error del código, habría arreglado el código y no el test. Y si no lo tuviera claro, no tocaría nada y preguntaría.
5. Review & Finish
Antes de cerrar, el agente revisa su propio trabajo:
/code review
Compara el código con la spec y con las reglas de calidad del proyecto, y los tests con los criterios de aceptación. No toca nada: deja cada hallazgo como una tarea en review.md, junto a la spec. Hoy salen dos cosas mejorables y un criterio de aceptación que solo se probaba a medias. Se lee, se está de acuerdo, y se le pasa el fichero al agente para que lo haga:
/code impl review.md
Luego los commits y el cierre:
/git-flow commit /git-flow finish
commit mira los cambios y los agrupa en tres commits con sentido (feat(#12): migración y entidad de clientes, feat(#12): formulario de alta…). finish comprueba antes de hacer nada: que no queda ninguna tarea pendiente, que review.md no tiene hallazgos abiertos y que todos los tests pasan. Si falta algo, lo dice y no hace nada. Como está todo, fusiona la rama en develop, hace push, para la aplicación, borra la base de datos del worktree y borra el worktree. En GitHub, el issue #12 se cierra solo y el tablero lo pasa a Done. Con el push, GitHub compila y pasa todos los tests otra vez: CI en verde en develop. No podía ser de otra forma: son los mismos tests que finish acaba de pasar en el worktree. No se ha tocado la web.
Por la tarde empieza el #13 igual. No le da tiempo a terminarlo: ./app.sh stop y se va. Mañana ./app.sh start y la aplicación está como la dejó, con sus datos.
6. Publish
El viernes, con tres issues cerrados en develop:
/git-flow publish
develop pasa a main. GitHub pasa la misma CI que en develop y, si está en verde, despliega en el servidor. Cinco minutos después la tienda está actualizada en http://<alumno>.proyectosdaw.cip.fpmislata.com. Si algún día algo fallara, copiaría el log del workflow y se lo preguntaría al agente; no hace falta más.
Lo que no se ha hecho
Esto es lo que aporta el arnés. En todo el día no se ha:
- escrito un comando de git: ni
branch, niworktree, nimerge, nipush; - buscado un puerto libre ni tocado un
docker compose; - escrito una clase de Java ni un componente de Angular;
- escrito un test, ni arreglado uno que se rompió;
- revisado a mano que el código sigue las convenciones del proyecto;
- cerrado un issue ni movido una tarjeta en el tablero;
- entrado al servidor.
Lo que sí se ha hecho es lo que solo puede hacer una persona: decidir qué se construye (el issue y la spec), comprobar que es lo que quería (los tests y el navegador) y dar el visto bueno (leer la revisión y cerrar). Programar con esta arquitectura es eso: pensar y comprobar, y que el resto se ejecute solo. Y hay una regla que lo hace posible: ningún comando se queda esperando a nadie. Los que generan trabajo lo dejan en ficheros del repositorio (la spec, las tareas, la revisión); los que hacen algo irreversible solo comprueban que esos ficheros están como tienen que estar. Se decide entre comandos, no dentro de ellos.
El ciclo de vida de un cambio
Lo de arriba, resumido. Es lo que se repite con cada issue: al finalizar uno se empieza el siguiente, y solo de vez en cuando, cuando hay una versión que sacar, se publica. La figura no lo dice, pero se da por hecho: cada fase empieza con una conversación nueva, /clear. Lo que una fase necesita de la anterior está en ficheros, no en la conversación.
La gramática de los comandos
Todo lo que se ha escrito en el día tiene la misma forma: familia, sustantivo y verbo, como docker container ls o gh issue create. Cinco familias, pocos verbos, y los mismos verbos significan lo mismo en todas. Cuando el sustantivo es evidente se omite, como en docker login: /git-flow start y /code review actúan sobre el issue en el que se está.
| Familia | Subcomandos | De qué se ocupa |
|---|---|---|
/git-flow | start N, commit, update, finish, publish | El issue en git: ramas, worktrees, commits, cierre y publicación |
./app.sh | start, stop, status, logs | La aplicación en Docker, en el worktree y en el servidor |
/sdd | spec create, spec impl | La especificación del issue y su implementación |
/test | unit, arch <reglas>, api <escenarios>, e2e <escenarios>, cada uno con create, run o repair. Siempre con el tipo delante: no hay un «todos» | Los cuatro tipos de tests |
/code | review, impl <plan> | El código del issue: revisarlo, y hacer las tareas de un plan: el plan_<algo>.md de un issue que no es CRUD, o review.md |
Lo que empieza por / es una skill del agente; lo que acaba en .sh es un script. Quien sabe que existe /test e2e run deduce /test e2e create y /test api repair sin haberlos visto. Esa es la idea: no hay que memorizar una lista, hay que saber la gramática.
Lo que hay que montar
Para que ese día de trabajo sea posible, en la 1ª evaluación se construye cada pieza, en este orden:
| Tema | Pieza | Lo que hace posible |
|---|---|---|
| 2 | Qué es un agente, Claude Code y OpenCode, skills, MCP, subagentes y bucles | El vocabulario con el que se entiende todo lo demás |
| 3 | Repositorio con instrucciones para el agente, tablero de issues y la skill /git-flow | Pasos 1, 5 y 6: ramas, worktrees, commits, cierre del issue, publicación |
| 4 | La aplicación en Docker, una copia por worktree, con datos de prueba, y el script app.sh | Paso 1: la aplicación propia en su puerto |
| 5 | La skill /sdd sobre cc-sdd, /code impl para los planes y el steering con la arquitectura del proyecto | Pasos 2 y 3: especificar o planificar, y que el código salga como tiene que salir |
| 6 | La skill /test y /code review | Pasos 4 y 5: los tests, la revisión y sus correcciones, y que finish pueda comprobar que todo está |
| 7 | CI y despliegue automático, con el mismo app.sh | Pasos 5 y 6: CI en cada push, despliegue al publicar |
| 8 | Resumen y lista de comprobación | Todo junto, para tenerlo a mano en la 2ª evaluación |
Las skills son las instrucciones que le dicen al agente cómo se hace cada cosa en este proyecto. Las escribe el alumno durante el trimestre, con ayuda del propio agente, y son lo que convierte una lista de pasos en una sola orden. Lo que no necesita inteligencia (arrancar, parar, ver los logs) no es una skill: es un script.
Herramientas
Todo esto tiene que estar instalado y funcionando antes del tema 3:
- git y gh (la CLI de GitHub) autenticado:
gh auth statusdebe decir que estás conectado. En Windows, Git se instala con las opciones del tema 3, que traen bash: el script del proyecto es de bash y funciona igual en los tres sistemas. - Docker con Docker Compose:
docker compose version. - JDK 25 y Maven:
mvn -v. - Node (para
npxy Angular):node -v. - Claude Code u OpenCode, con una cuenta que aguante un trimestre generando código. Los apuntes explican todo con Claude Code y señalan lo que cambia en OpenCode.
Qué es una skill, un agente o un MCP, cómo se maneja OpenCode y qué es cc-sdd (Kiro) está contado en el curso de programación con IA: Skills, Agentes y MCP, OpenCode y Kiro. Claude Code está en Proyecto 8.
Ejercicios
Ejercicio 1
- Comprueba que tienes todas las herramientas:
git,gh auth status,docker compose version,mvn -v,node -vy Claude Code u OpenCode arrancando. - Lee qué es una skill y qué es Kiro.
Ejercicio 2
- Crea en GitHub el repositorio de tu proyecto, vacío, con
READMEy.gitignore. Es el que se usa en todo el módulo. - Crea el tablero del proyecto: en GitHub, menú
+de arriba a la derecha → New project → Start from scratch → plantilla Board → nombre del proyecto → Create. Salen las tres columnas, Todo, In Progress y Done. Después, en la pestaña Projects del repositorio, Link a project para enlazarlo. - Clónalo y pide al agente que genere en
backend/un Spring Boot con Maven y Java 25, sin JPA (la base de datos llega en el tema 4), con unGET /api/holaque devuelva un texto, y enfrontend/un Angular que lo llame y lo muestre. - Arranca los dos a mano,
mvn spring-boot:runyng serve, y comprueba en el navegador que el texto aparece. - Haz commit y push. En este tema los commits se hacen a mano:
/git-flowllega en el siguiente.

