Herramientas de usuario

Herramientas del sitio


clase:daw:daw-proyecto:tema05

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
clase:daw:daw-proyecto:tema05 [2026/10/14 01:47] – Los CRUD con cc-sdd: steering con backend.md y frontend.md condicionales, en lugar de la skill /crud claudeclase:daw:daw-proyecto:tema05 [2026/10/14 14:08] (actual) – Tema nuevo «2. IA y agentes»: los temas 2 a 7 pasan a ser 3 a 8, con sus referencias cruzadas renumeradas claude
Línea 1: Línea 1:
-====== 5. Automatizando el proyecto con IA ======+====== 5. IA en el proyecto ======
  
-Objetivo del tema: que la calidad la vigilen **tests que genera la IA** en los cuatro niveles (arquitectura, unitarios, API y E2E) y que ningún issue llegue a ''develop'' sin pasar una revisión. Al acabar, cerrar un issue es ''/git-flow finalizar'' y todo lo demás ocurre solo, y un CRUD nuevo es una sola orden.+Objetivo del tema: usar bien al agente para programar. No se enseña a programar; se enseña a **pedir** el trabajo como una especificación y a comprobar que ha salido bien. Al acabar, el proyecto tiene su primer CRUD completo hecho así y la arquitectura del proyecto escrita donde el agente la lee antes de diseñar nada.
  
-===== Tests de arquitectura con ArchUnit =====+Lo que ya está contado en el [[cursos:sdd:start|curso de programación con IA]] y aquí no se repite: qué es el [[cursos:sdd:10-spec-driven-development|Spec-driven development]] y por qué encaja con los agentes, [[cursos:sdd:11-kiro|cc-sdd (Kiro)]] con sus fases y su memoria del proyecto, y la [[cursos:sdd:04-ingenieria#ingenieria_de_contexto|ingeniería de contexto]].
  
-Las reglas de arquitectura (las de Programación y DWS: capas, nombres, sin ciclos, ''domain'' sin Spring) las hace cumplir ArchUnit con tests que fallan cuando una clase está donde no debe. Lo nuevo es que **los escribe la IA** a partir de las reglas en castellano:+===== Dos caminos: spec para los CRUD, plan para el resto =====
  
-<code> +En este proyecto hay dos clases de issue y cada una tiene su camino:
-/crear-test-arquitectura +
-- Las clases de controller solo dependen de domain. +
-- Las de persistence solo dependen de domain. +
-- Nada en domain importa org.springframework ni jakarta.persistence. +
-- Los controladores acaban en Controller y están en ..controller.. +
-- Los repositorios de persistence acaban en RepositoryImpl e implementan una interfaz de domain. +
-- Sin ciclos entre paquetes. +
-</code>+
  
-Cada test lleva en su ''@DisplayName'' y en un comentario **qué comprueba, por qué y las excepciones**:+  * **Un CRUD** (una entidad con su listado, alta, edición y borrado) va por **especificación**: requisitos, diseño y tareas en ficheros, generados por cc-sdd y revisados por el alumno. Un CRUD tiene una forma conocida y la spec, con el steering, es lo que garantiza que sale igual que los demás. 
 +  * **Todo lo demás** (un filtro, un informe, una regla de negocio, un cambio en una pantalla) va por **plan**: en modo plan se le dice al agente lo que se quiere y él escribe un fichero ''plan_<algo>.md'' con las tareas; el alumno lo revisa y, en otra conversación, se implementa con ''/code impl''. Es trabajo pequeño y variado: una spec entera sería más papel que código.
  
-<sxh java> +En los dos, la regla es la misma: primero un fichero que el alumno lee y corrige, después la implementación con el contexto limpio.
-@Test +
-@DisplayName("domain no depende de Spring: el dominio tiene que compilar y probarse sin el framework") +
-void domainSinSpring() { +
-    noClasses().that().resideInAPackage("..domain..") +
-        .should().dependOnClassesThat().resideInAPackage("org.springframework..") +
-        .check(clases); +
-} +
-</sxh>+
  
-**No hay un documento aparte con la arquitectura.** Mantener un Markdown sincronizado con los tests es un trabajo que nadie hace, así que la fuente de verdad son los tests con su descripción. Para cambiar una regla se le pide a la skill que cambie el test. Cuando se añade una regla que el código actual aún no cumple, ''FreezingArchRule.freeze(regla)'' congela las violaciones existentes y solo falla con las nuevas. +La spec la genera **cc-sdd** (la versión libre del flujo de Kiro), pero el alumno no escribe sus comandos: los envuelve una skill del proyecto, ''/sdd'', con dos subcomandos. Así el vocabulario es el del tema 1 y no el de la herramienta. cc-sdd se instala una vez en la raíz del repositorio:
- +
-===== Tests unitarios con JUnit ===== +
- +
-Los tests unitarios prueban la lógica del dominio **sin Spring y sin base de datos**: un servicio con sus repositorios sustituidos por mocks de Mockito. Son los más rápidos y los que mejor localizan un error. ''/crear-test-unitarios'' los genera para una clase o un paquete del dominio:+
  
 <code> <code>
-/crear-test-unitarios PedidoService+npx cc-sdd@latest --claude-skills --lang es      (OpenCode: --opencode-skills)
 </code> </code>
  
-Lo que hace: lee la clase, identifica cada comportamiento (lo que devuelve, lo que valida, lo que lanza) y escribe un test por comportamiento en ''backend/src/test/java'', con el mismo paquete, ''@DisplayName'' en castellano que diga el caso y Mockito para las dependencias. Los ejecuta con ''mvn test'' y se para si alguno falla por un error del código, en vez de retocar el test para que pase.+Ese es el flujo de cada issue:
  
-Qué no prueban: controladores ni repositorios. Eso es de los tests de API.+<uml> 
 +start 
 +:/git-flow start N 
 +y ./app.sh start; 
 +if (¿es un CRUD?) then (sí) 
 +  :/sdd spec create 
 +  requisitos, diseño y tareas 
 +  en .kiro/specs/N-slug/; 
 +  :Leer y corregir los tres ficheros; 
 +  :/clear y /git-flow update; 
 +  :/sdd spec impl 
 +  una tarea tras otra; 
 +else (no) 
 +  :Modo plan: el agente lee el código 
 +  y escribe plan_<algo>.md; 
 +  :Leer y corregir el plan; 
 +  :/clear y /git-flow update; 
 +  :/code impl plan_<algo>.md 
 +  una tarea tras otra; 
 +endif 
 +:Tests unitarios y de arquitectura 
 +después de cada tarea; 
 +:Probar en el navegador; 
 +stop 
 +</uml>
  
-===== Tests de API con Playwright =====+==== /sdd spec create ====
  
-Los tests de API prueban cada endpoint **de verdad**: peticiones HTTP contra el backend del worktree, comprobando el código de estado y el JSON. Se escriben con Playwright, igual que los E2E (mismo lenguaje, misma configuración, misma carpeta): Playwright trae para esto el fixture ''request'', que hace peticiones sin abrir ningún navegador.+Se lanza en el worktree del issue, sin argumentos: el número del issue está en el nombre de la rama. Lo que hace, por dentro, son las cuatro fases de cc-sdd encadenadas:
  
-**No forman parte del build**: ''mvn test'' no los ejecuta. Se lanzan aparte, cuando se quiere, con ''npm run api-test'' (tema 3), que resetea la base de datos del worktree, levanta la aplicación y ejecuta el proyecto ''api'' de Playwright. ''/crear-test-api'' los genera para una entidad:+  - ''/kiro-spec-init'' con el título y el cuerpo del issue (''gh issue view N''). 
 +  - ''/kiro-spec-requirements'': los requisitos y los **criterios de aceptación**. 
 +  - ''/kiro-spec-design -y'': el diseño, leyendo antes el //steering// con la arquitectura del proyecto (abajo). 
 +  - ''/kiro-spec-tasks -y'': la lista de tareas, en orden y pequeñas.
  
-<code> +Y se para. El resultado son tres ficheros en ''.kiro/specs/<N>-<slug>/'': ''requirements.md'', ''design.md'' y ''tasks.md''. Antes de generar nada, si el issue no deja claro algo (¿el NIF es único?), pregunta.
-/crear-test-api Pedido +
-</code>+
  
-Por cada endpoint del controlador, en ''frontend/tests/api/pedidos.spec.ts'', un test del caso bueno y uno por cada error que el plan o las validaciones prevén: ''400'' con un campo obligatorio vacío, ''404'' con un id que no existe, ''409'' con un valor único repetido. Los datos de partida son los del ''%%R__%%'' de la entidad; los tests que escriben se limpian a sí mismos (borran lo que crean) para que se puedan pasar dos veces seguidas.+**Revisar esos ficheros es el trabajo humano del flujo.** Es mucho más barato corregir una frase de la spec que corregir el código que sale de ella. Qué mirar en cada uno:
  
-<sxh typescript> +^ Fichero ^ Qué tiene que tener ^ 
-test('POST /api/pedidos sin número devuelve 400 y el nombre del campo', async ({ request }) => { +| ''requirements.md'' | Los criterios de aceptación en frases **comprobables** («al guardar un cliente sin NIF, el formulario muestra el error y no se crea»), y entre ellos **los casos de error**: campo vacío, valor repetido, id que no existe. En el tema 6 cada frase se convierte en un test | 
-  const res = await request.post('/api/pedidos', { data: { fecha: '2026-10-14', clienteId: 1 } }); +| ''design.md'' | Que es **igual** que el CRUD de referencia del proyecto: las mismas capas, los mismos nombres, migración y datos de prueba. Si no lo es, lo que falla no es el diseño sino el steering (abajo): se corrige el steering y se vuelve a generar | 
-  expect(res.status()).toBe(400); +| ''tasks.md'' | Tareas pequeñas y en orden: migración y datos, backend, frontend. Cada una se puede hacer y probar sola |
-  expect((await res.json()).errores.numero).toBeDefined(); +
-}); +
-</sxh> +
- +
-Los de API y los E2E son dos **proyectos** del mismo ''playwright.config.ts'', separados por carpeta; el de API no necesita navegador: +
- +
-<sxh typescript;title:frontend/playwright.config.ts> +
-export default defineConfig({ +
-  use: { baseURL: process.env.BASE_URL ?? 'http://localhost:4200' }, +
-  projects: [ +
-    { name: 'api', testDir: 'tests/api' }, +
-    { name: 'e2e', testDir: 'tests/e2e', use: { browserName: 'chromium' } }, +
-  ], +
-}); +
-</sxh>+
  
-''mvn test'' corre unitarios y arquitectura en cada build; ''npm run api-test'' y ''npm run e2e-test'' corren API y E2E cuando se pide. Son los mismos comandos para el alumno, para el agente y para CI.+Si se cambia algo en ''requirements.md'', se vuelve a lanzar ''/sdd spec create'': rehace el diseño y las tareas a partir de los requisitos corregidos. Se repite hasta que los tres ficheros digan lo que se quiere.
  
-===== Tests E2E con Playwright =====+==== /sdd spec impl ====
  
-Los tests E2E prueban la aplicación completa desde el navegador, como lo haría el usuario. Los criterios de aceptación del plan son frases comprobables. ''/crear-test-e2e'' las convierte en tests de Playwright en TypeScript, ''frontend/tests/e2e/<entidad>.spec.ts'', y los deja pasando:+Conversación nueva (''/clear'') y una sola orden:
  
 <code> <code>
-/crear-test-e2e planes/12-alta-clientes.md+/sdd spec impl
 </code> </code>
  
-Cómo trabaja: lee los criterios, abre la aplicación del worktree con el Playwright MCP para ver qué hay en pantalla, escribe el test y lo ejecuta con ''npm run e2e-test''; si falla por un selector o un texto, lo arregla y lo vuelve a pasar. La IA interviene **al generar**, no al ejecutar: lo que queda en el repositorio es un ''.spec.ts'' normal, determinista, que CI ejecuta sin ninguna IA.+Por dentro es ''/kiro-impl'' sobre las tareas pendientes de la spec del worktree, una detrás de otra. Después de cada tarea pasa los tests unitarios y de arquitectura (''/test unit run'', tema 6) y la marca como hecha en ''tasks.md''. Si un test falla por un error del código, se para en esa tarea y lo dice, en vez de retocar el test para que pase. Cuando termina, el alumno prueba la aplicación en la URL del worktree y, si algo no está bien, se le pide en la misma conversación.
  
-Reglas que la skill tiene que respetar (están en ''convenciones-frontend''):+Solo implementa la spec. Los planes (abajo) y las correcciones de una revisión (tema 6) se hacen con ''/code impl''.
  
-  * Selectores por ''data-testid'' y por rol (''getByRole'', ''getByLabel''), nunca por clase CSS. Un test que depende del CSS se rompe al primer cambio de estilo. +Por qué el ''/clear'' entre los dos: la conversación de especificar arrastra todo lo que el agente ha leído y descartado mientras pensaba. Ese ruido empeora el resultado y encarece cada petición. Con la spec en ficheros, esa conversación es desechable.
-  * Un test por criterio de aceptación, con el criterio como nombre del test. +
-  * Los tests cuentan con los datos de prueba del tema 3 y **se pasan sobre la base de datos recién reseteada** (''docker compose down -v && docker compose up -d'').+
  
-===== Revisión por IA antes de cerrar =====+==== El modo plan y /code impl: lo que no es un CRUD ====
  
-Sin pull request nadie mira el código antes de que llegue a ''develop''. Lo mira la IA. ''/revisar'' compara el diff de la rama contra ''develop'' con dos cosas:+Claude Code y OpenCode tienen un **modo plan** en el que el agente solo lee: explora el código, piensa y propone, pero no toca nada. En Claude Code se entra con ''Shift+Tab'' hasta que la barra dice //plan mode//; en OpenCode, con la tecla ''Tab'' ([[cursos:sdd:03-opencode#plan_y_buildla_tecla_tab|Plan y Build]]). Es el camino de los issues que no son un CRUD:
  
-  * **El plan del issue**: ¿hace lo que se pidió, y como se pidió? ¿Falta algún criterio de aceptación? ¿Ha hecho cosas que no estaban en el plan? +  - En el worktree del issue, modo plan, y se le dice lo que se quiere (lo que pone el issue) y que escriba el plan como **lista de tareas** (''- [ ] ...'') en ''plan_<algo>.md'', por ejemplo ''plan_filtro-provincia.md''. El agente lee el código, pregunta lo que le falte y escribe el fichero: es lo único que escribe en modo plan. 
-  * **Las skills de convenciones**: ¿está en las capas correctas, con los nombres correctos, con migración y datos de prueba, con ''data-testid''? +  - Se sale del modo plan. El fichero queda en el worktree. 
- +  - Se lee y se corrige a mano, igual que una spec: tareas pequeñas, en orden, y que no falte ninguna pantalla ni ningún caso de error. 
-Y clasifica cada cosa que encuentra en **grave** (no cumple el plan, rompe una convención, falta un test) o **mejorable**. ''/git-flow finalizar'' lanza ''/revisar'' como primer paso y **no fusiona si hay algo grave**: enseña la revisión y se para. El alumno corrige (o le pide al agente que corrija) y vuelve a finalizar. +  - **Conversación nueva** (''/clear'') y se implementa:
- +
-<note important>El alumno lee la revisión. El código lo ha escrito la IA, pero el commit lo firma él y es responsable de lo que hay en ''develop''. La revisión es una ayuda para leer, no una excusa para no leer.</note> +
- +
-===== Calidad del código: las reglas y quien las aplica ===== +
- +
-''/revisar'' dice si el código hace lo que pedía el plan y si sigue las convenciones. No dice si el código es **bueno**: métodos que hacen tres cosas, clases que se conocen demasiado, comentarios que repiten el código, tests que copian los valores que prueban. Para eso hacen falta dos skills más: una de **conocimiento** con las reglas de calidad y una de **tarea** que las aplica a un trozo de código y cuenta lo que encuentra. +
- +
-==== calidad-codigo: las reglas ==== +
- +
-Una skill de conocimiento, como las de convenciones, pero sobre cómo se escribe código bueno en general. Se escribe una vez y se va completando cuando una revisión saca algo que no estaba. ''SKILL.md'' lleva la máxima y el índice; cada grupo de reglas, en su fichero:+
  
 <code> <code>
-.claude/skills/calidad-codigo/ +/code impl plan_filtro-provincia.md
-├── SKILL.md          <- la máxima, el orden de prioridades y la tabla de ficheros +
-├── metodos.md +
-├── clases.md +
-├── comentarios.md +
-└── tests.md+
 </code> </code>
  
-**La máxima**: el código se escribe para que **una persona lo entienda al leerlo** y para que **un agente lo pueda modificar sin equivocarse**. Consecuencia que lo cambia todo: una repetición pequeña y visible es aceptable; una indirección para ahorrar dos líneas (un método que solo reenvía, un genérico) no lo es, porque el agente no olvida los dos sitios que hay que tocar y la persona sí pierde el hilo. +Por qué en dos conversaciones y no seguidas: al planificar, el agente ha leído medio proyecto y ha descartado alternativas, y todo eso sigue en el contexto. Si implementa en la misma conversación, programa con ese ruido. Con el plan en un fichero, la conversación de planificar se tira y la de implementar empieza limpia, solo con el plan. Es la misma razón del ''/clear'' entre ''spec create'' y ''spec impl''.
- +
-Cuando dos reglas chocan, gana la primera de esta lista: mantenibilidad, testabilidad, determinismo, separación de responsabilidades.+
  
-^ Fichero ^ Reglas (las que entran; se amplía con lo que salga en las revisiones) ^ +''/code impl <plan>'' hace las tareas pendientes del fichero, una detrás de otra, y las va marcando; después de cada una pasa los tests unitarios y de arquitectura y, si uno falla por el código, se para y lo dice. Es lo que hace ''/sdd spec impl'' con ''tasks.md'', pero para cualquier lista de tareas en markdown: en el tema 6 se usa también con la revisión.
-| ''metodos.md'' | El método público cuenta la historia entera y se lee de arriba abajo. Se trocea por **cosa** que hace, no por fase. Con pocos casos (hasta 4), un método lineal por caso en vez de un genérico. El nombre dice qué hace, no cómo. Cabe en una pantalla y tiene como mucho tres parámetros. El cálculo puro se separa de la entrada/salida (base de datos, HTTP) para poder probarlo sin montar nada | +
-| ''clases.md'' | Una clase, una responsabilidad. Composición antes que herencia. Un DTO o record agrupa solo lo homogéneo y sus campos se nombran por lo que son, no por quién los usa. Nada estático con estado. La interfaz del ''Repository'' en ''domain'' dice lo que el dominio necesita, no lo que la base de datos ofrece | +
-| ''comentarios.md'' | El código se explica solo: si hace falta un comentario para entender qué hace, el nombre está mal. El único comentario que se escribe es el **porqué** que leer el código no revela (una decisión, una restricción externa). Nada de comentarios que repiten la línea de debajo ni de código comentado | +
-| ''tests.md'' | Un test por comportamiento, con el caso en el nombre. El test **no copia los valores del código que prueba** (si el IVA es una constante, el test la lee de producción y comprueba la relación, no escribe 21 otra vez). Sin lógica en el test: ni ''if'' ni bucles. Lo que se prepara se ve en el propio test |+
  
-Y en ''SKILL.md'', cuatro olores de **diseño** que vienen antes del código y que el agente tiene que buscar aunque no haya regla concreta: una decisión que se toma en dos sitios; un método que vive en una clase que no es la dueña del concepto; un ''if'' que no cubre todos los casos; un retorno defensivo (''return null'', lista vacía) que tapa un error en vez de fallar.+La skill ''/code'' nace en este tema con el verbo ''impl''; en el tema 6 se le añade ''review''.
  
-La ''description'' de la skill dice cuándo cargarla: «Reglas de calidad del código del proyecto. Cargar al escribir o revisar cualquier clase Java o TypeScript, y siempre desde ''/revisar-calidad''».+==== La carpeta de la spec ====
  
-==== /revisar-calidad: quien las aplica ====+''.kiro/specs/'' se sube a git: la spec viaja con la rama, entra en ''develop'' en el mismo commit que el código, y las skills del tema 6 la usan para generar los tests y para revisar que el código hace lo que se pidió.
  
-Una skill de tarea que recibe una ruta (una clase, un paquete, ''backend/src/main/java'' entero) y devuelve un informe. **No toca el código**: el alumno decide qué corregir y lo pide después.+Es un **registro** de lo que se pidió, no documentación: cuando el código cambie después, la spec no se actualiza. Para que el agente no se confunda con specs viejas, ''AGENTS.md'' lleva esta línea:
  
 <code> <code>
-/revisar-calidad backend/src/main/java/com/tienda/pedidos+.kiro/specs/ es histórico: la fuente de verdad es el código. No leas specs de otros issues salvo que te lo pidan.
 </code> </code>
  
-Lo que hace, en orden:+==== La skill /sdd ====
  
-  - Carga ''calidad-codigo'' y las skills de convenciones. +Es corta, porque el trabajo lo hacen los comandos de cc-sdd. Recibe el subcomando en ''$ARGUMENTS'' y hace una cosa u otra:
-  - Lee el código de la ruta. Solo lee: ''allowed-tools: Read, Grep, Glob''. Sin ''Bash'' y sin ''Edit''. +
-  - Por cada cosa que encuentra, un hallazgo con: la **regla** incumplida (fichero y sección de ''calidad-codigo''), el **sitio** (''fichero:línea'') y el **coste** del código tal como está (qué se duplica, qué no se puede probar, qué se rompe al cambiarlo). **Sin coste no hay hallazgo**: eso separa un defecto de una preferencia. +
-  - Antes de proponer cambiar la **forma** de algo sin cambiar lo que hace (extraer, mover, renombrar), mira cómo lo resuelven tres clases hermanas (otros controladores, otros servicios). Si lo hacen igual, es una convención del proyecto y no se reporta. Si se aparta, se reporta citando una hermana como referencia. +
-  - Clasifica en **grave** (rompe una regla con coste claro, o un olor de diseño) y **mejorable**, y ordena de más a menos grave.+
  
-Un hallazgo bien hecho y dos mal hechos: +<sxh yaml;title:.claude/skills/sdd/SKILL.md (cabecera)> 
- +--- 
-<code> +name: sdd 
-GRAVE  PedidoService.java:48  metodos.md «cálculo puro y efectos secundarios» +description: Especificar e implementar el issue del worktree actual con cc-sdd. Subcomandos: "spec create" (requisitos, diseño y tareas en .kiro/specs/N-slug/) y "spec impl" (implementa las tareas pendientes). 
-       calcularTotal() lee los pedidos de la base de datos y los suma en el mismo método. +allowed-tools: Bash(gh issue view:*), Bash(git branch:*), Bash(mvn:*), Read, Write, Edit, Skill 
-       Coste: no se puede probar la suma sin base de datos; el test unitario actual la monta entera. +--- 
- +</sxh>
-MAL    "extraer las líneas 20-24 a un método privado para mejorar la legibilidad" +
-       (no mira las clases hermanas: todos los servicios lo escriben así; y no dice qué cuesta) +
-MAL    "el método es demasiado largo" +
-       (sin regla ni coste: es una opinión) +
-</code>+
  
-Después del informe, el alumno lee, decide y pide: «corrige los graves» o «el segundo no, es así a propósito». Ahí sí se edita el código, en la conversación normal, y se vuelve a pasar ''/revisar-calidad'' para confirmar.+Todas las skills de tarea del proyecto son así: ''/<familia> <sustantivo> <verbo>'', con el subcomando en los argumentos. Es lo que hace que ''/test e2e run'' y ''/test e2e create'' sean la misma skill con dos subcomandos.
  
-**Cuándo se pasa**: después de cada ''/crud'' (es donde más código sale de golpe), sobre el paquete de un issue antes de ''finalizar'' si ha sido grande, y sobre todo el backend antes de cada ''publicar''. Lo que ''/revisar-calidad'' saca una y otra vez es una regla que falta en las convenciones: se añade y deja de salir.+===== El primer CRUD =====
  
-===== Los CRUD con cc-sdd =====+La práctica central del tema es el primer CRUD del proyecto, hecho con ''/sdd''. Pero hay un problema de huevo y gallina: el diseño tiene que salir como la arquitectura del proyecto, y la arquitectura todavía no está escrita en ningún sitio que el agente lea.
  
-Los CRUD de este proyecto son siempre iguales: solo cambian la entidad y sus campos. Para que salgan iguales **de verdad**, con las mismas capas, los mismos nombres y los mismos tests, no basta con pedirlos bien: el agente tiene que tener la arquitectura escrita y leerla antes de diseñar nada. Eso es lo que hace el //steering// de cc-sdd, y por eso los CRUD se hacen con él.+Se resuelve con el primer CRUD y solo con él: se genera la spec, y en ''design.md'' el alumno **corrige a mano** todo lo que no sea la arquitectura que ya conocéis de Programación y DWS (capas ''controller'' / ''domain'' / ''persistence'', ''Repository'' definido en ''domain'' e implementado en ''persistence'', DTO ''XxxRequest'' / ''XxxResponse'', ''XxxJpaEntity'', MapStruct, ''ApiExceptionHandler''). Aquí no se inventa una arquitectura nueva. Después de implementarlo se lee **clase por clase** y se corrige hasta que esté como tiene que estar: es el código de referencia de todo lo que viene después, y de él sale el steering.
  
-Cómo se instala cc-sdd y cómo funcionan sus cinco fases está en el curso de SDD: [[cursos:sdd:11-kiro|Kiro: comandos SDD]]. Aquí solo lo que es de este proyecto: que tiene **dos arquitecturas**, la del cliente y la del servidor, y cómo se le cuentan.+===== El steering: las dos arquitecturas =====
  
-==== Cuándo se genera la memoria del proyecto ====+Para que el segundo CRUD salga igual que el primero **de verdad**, con las mismas capas, los mismos nombres y los mismos tests, no basta con pedirlo bien: el agente tiene que tener la arquitectura escrita y leerla antes de diseñar. Eso es el //steering// de cc-sdd, y ''/sdd spec create'' lo carga en la fase de diseño. Cómo funciona está en [[cursos:sdd:11-kiro#la_memoria_del_proyecto|la memoria del proyecto]]; aquí solo lo que es de este proyecto: que tiene **dos arquitecturas**, la del cliente y la del servidor, y cómo se le cuentan.
  
-''/kiro-steering'' describe lo que ve en el código. Por eso se lanza **después del primer CRUD del tema 4**, ya revisado, y no antes: con el esqueleto vacío describiría nada, y con un CRUD mal hecho convertiría el error en norma.+==== Cuándo se genera ====
  
-Se instala y se lanza una vez, en la raíz del repositorio:+''/kiro-steering'' describe lo que ve en el código. Por eso se lanza **después del primer CRUD**, ya revisado, y no antes: con el esqueleto vacío describiría nada, y con un CRUD mal hecho convertiría el error en norma. Se lanza una vez, a mano, en la raíz del repositorio:
  
 <code> <code>
-npx cc-sdd@latest --claude-skills --lang es      (OpenCode: --opencode-skills) 
 /kiro-steering /kiro-steering
 </code> </code>
Línea 187: Línea 145:
 Los tres ficheros que genera, ''product.md'', ''tech.md'' y ''structure.md'', entran en el contexto **siempre**, en todas las fases de todas las specs. Así que se revisan y se dejan cortos, con solo lo común: qué es el proyecto, que es Spring Boot más Angular más MariaDB, el reparto ''backend/'' y ''frontend/'', los comandos de arrancar y probar y las dos ramas. Los tres ficheros que genera, ''product.md'', ''tech.md'' y ''structure.md'', entran en el contexto **siempre**, en todas las fases de todas las specs. Así que se revisan y se dejan cortos, con solo lo común: qué es el proyecto, que es Spring Boot más Angular más MariaDB, el reparto ''backend/'' y ''frontend/'', los comandos de arrancar y probar y las dos ramas.
  
-==== Dos arquitecturas, dos ficheros de steering ====+==== Dos arquitecturas, dos ficheros ====
  
 Lo específico de cada parte no va en esos tres, sino en dos ficheros de steering **condicionales**, que solo entran en el contexto cuando la spec toca esa carpeta. Se crean con ''/kiro-steering-custom'' y llevan en la cabecera el patrón de ficheros que los activa: Lo específico de cada parte no va en esos tres, sino en dos ficheros de steering **condicionales**, que solo entran en el contexto cuando la spec toca esa carpeta. Se crean con ''/kiro-steering-custom'' y llevan en la cabecera el patrón de ficheros que los activa:
  
-<sxh markdown;title:.kiro/steering/backend.md>+<sxh plain;title:.kiro/steering/backend.md>
 --- ---
 inclusion: fileMatch inclusion: fileMatch
Línea 200: Línea 158:
 </sxh> </sxh>
  
-Y ''frontend.md'' igual, con ''frontend/**''. **Concretar las dos arquitecturas es trabajo del alumno**: ''/kiro-steering-custom'' pone la cabecera y un borrador; el contenido se escribe mirando el CRUD de referencia, y tiene que responder a esto:+Y ''frontend.md'' igual, con ''%%frontend/**%%''. **Concretar las dos arquitecturas es trabajo del alumno**: ''/kiro-steering-custom'' pone la cabecera y un borrador; el contenido se escribe mirando el CRUD de referencia, y tiene que responder a esto:
  
 ^ ''backend.md'' ^ ''frontend.md'' ^ ^ ''backend.md'' ^ ''frontend.md'' ^
Línea 207: Línea 165:
 | Dónde se valida (Bean Validation en el ''Request'') y cómo se devuelven los errores: ''ApiExceptionHandler'', códigos 400 / 404 / 409 y el formato del JSON de error | El servicio HTTP de cada entidad y cómo se llama a la API | | Dónde se valida (Bean Validation en el ''Request'') y cómo se devuelven los errores: ''ApiExceptionHandler'', códigos 400 / 404 / 409 y el formato del JSON de error | El servicio HTTP de cada entidad y cómo se llama a la API |
 | Migraciones ''%%V<n>__%%'' y datos de prueba ''%%R__%%'', con un ejemplo | Formularios reactivos y cómo se muestran las validaciones | | Migraciones ''%%V<n>__%%'' y datos de prueba ''%%R__%%'', con un ejemplo | Formularios reactivos y cómo se muestran las validaciones |
-| Cómo se prueba: ''mvn test'' y qué prueban los unitarios | ''data-testid'' en todo lo que un test toca; cómo se prueba: ''npm run api-test'' y ''npm run e2e-test'' |+| Cómo se prueban los unitarios: JUnit 5 y Mockito, sin Spring | ''data-testid'' en todo lo que un test toca, nunca selectores por clase CSS |
  
-Son exactamente las reglas de ''convenciones-backend'' y ''convenciones-frontend'' del tema 4. Para no mantener el mismo texto en dos sitios, **la fuente pasa a ser el steering**: las dos skills de convenciones se quedan en una línea, «lee ''.kiro/steering/backend.md''», y así el flujo de plan de los issues normales y las specs de cc-sdd leen lo mismo.+La lección: **lo que el steering no dice, el agente lo inventa distinto cada vez.** Si el segundo CRUD sale distinto del primero, falta una línea en el steering, no un prompt mejor.
  
-==== Un CRUD de principio a fin ====+==== Las skills de convenciones ====
  
-<code> +El steering solo lo leen los comandos de cc-sdd. Las demás skills del proyecto (''/test'', ''/code'') también necesitan saber cómo se escribe el código aquí. Para eso hay dos **skills de conocimiento** (no se invocan: el agente las carga solo cuando va a tocar backend o frontend) que no repiten nada: remiten al steering.
-/kiro-spec-init CRUD de pedidos: numero (texto, único, obligatorio), fecha (obligatoria), +
-                cliente (relación con Cliente, obligatoria), total (decimal, >= 0) +
-/kiro-spec-requirements +
-/kiro-spec-design -y +
-/kiro-spec-tasks -y +
-/kiro-impl +
-</code>+
  
-  * En **requirements** se revisa que estén los casos de error (campo vacío, NIF repetido, id inexistente): son los que luego prueban los tests. +<sxh yaml;title:.claude/skills/convenciones-backend/SKILL.md> 
-  * En **design** se comprueba una sola cosa: que es igual que el CRUD de referencia. Si no lo es, lo que falla no es el diseño sino el steering: se añade la línea que faltaba en ''backend.md'' o ''frontend.md'' y se repite la fase. Así cada CRUD deja el steering un poco mejor para el siguiente. +--- 
-  * Los tests se generan igual que en cualquier issue, pero a partir de la spec: ''/crear-test-api .kiro/specs/crud-pedidos/requirements.md'' y lo mismo con ''/crear-test-e2e''. Y ''/revisar'' compara el diff con esa spec en lugar de con un plan.+name: convenciones-backend 
 +description: Cómo se escribe el código del backend en este proyecto (capas, nombres, DTO, migraciones, tests). Cargar siempre antes de crear, modificar o revisar cualquier clase Java, test de Java o fichero SQL. 
 +--- 
 +Lee .kiro/steering/backend.md y aplícalo. Es la única fuente de la arquitectura del servidor. 
 +</sxh>
  
-La lección: **lo que el steering no dice, el agente lo inventa distinto cada vez.** Si el segundo CRUD sale distinto del primero, falta una línea en el steering, no un prompt mejor.+Y ''convenciones-frontend'' igual, hacia ''frontend.md''. Una sola fuente: cuando cambia una convención, cambia en un sitio. 
 + 
 +===== El contexto del agente ===== 
 + 
 +El contexto es todo lo que el modelo tiene delante en una conversación: ''AGENTS.md'', las skills cargadas, el steering, los ficheros que ha leído, la salida de los comandos que ha ejecutado y todo lo que se ha hablado. Cada mensaje lo reenvía entero. Cuanto más lleno, peor trabaja y más cuesta. Reglas: 
 + 
 +  * **Una conversación por tarea.** ''/clear'' entre tareas. Lo que tenga que sobrevivir, a un fichero. 
 +  * **El modelo bueno para especificar, el barato para implementar** cosas claras. ''/model'' en Claude Code, ''/models'' en OpenCode. 
 +  * **No pegar logs enteros.** Solo el error y las líneas de alrededor. 
 +  * **Mirar el contador.** ''/context'' y ''/cost'' en Claude Code; OpenCode lo muestra junto a la caja de entrada. Cuando el contexto pasa de la mitad, o se cierra la tarea o se hace ''/compact''. 
 + 
 +===== MCP ===== 
 + 
 +Dos servidores MCP y ninguno más (qué es un MCP: [[cursos:sdd:02-skills-agentes-mcp#mcp|MCP]]): 
 + 
 +  * **Context7**: documentación actualizada de Spring Boot y Angular. Sin él, el agente escribe código de la versión que recuerda, que no es la que usáis. 
 +  * **Playwright MCP**: el agente abre la aplicación en un navegador y la ve. Sirve para que compruebe por sí mismo que una pantalla funciona, y en el tema 6 para generar los tests E2E. 
 + 
 +Se configuran con ''claude mcp add'' en Claude Code y en ''opencode.json'' en OpenCode, siguiendo la página de cada servidor. 
 + 
 +===== Permisos del agente ===== 
 + 
 +En el tema 3 se permitió lo básico. Para programar, el agente tiene que poder compilar, pasar tests y levantar la aplicación sin preguntar en cada paso. La lista de ''.claude/settings.json'' queda así: 
 + 
 +  * **Permitido**: ''mvn'', ''npm'', ''npx'' (incluido ''npx playwright''), ''docker compose'', ''./app.sh'', ''gh issue'', ''gh run'' y las lecturas de git (''status'', ''diff'', ''log'', ''worktree list''). 
 +  * **Pregunta**: escribir ficheros fuera del worktree, ''docker'' a secas, cualquier ''curl'' a un sitio que no sea ''localhost''. 
 +  * **Denegado**: ''git push --force'', ''rm -rf'', y cualquier ''git'' que cambie el repositorio (''commit'', ''merge'', ''push''), que solo puede ejecutar ''/git-flow'' por su ''allowed-tools''. 
 + 
 +En OpenCode, lo mismo en la clave ''permission'' de ''opencode.json''.
  
 ===== Ejercicios ===== ===== Ejercicios =====
  
 ==== Ejercicio 1 ==== ==== Ejercicio 1 ====
-  * Crea un issue «Tests de arquitectura» e inícialo. +  * Configura Context7 y el MCP de Playwright en Claude Code (''claude mcp add'') y en OpenCode (''opencode.json''). 
-  * Escribe la skill ''/crear-test-arquitectura'': recibe reglas en castellano y genera los tests ArchUnit en ''backend/src/test'', cada uno con ''@DisplayName'' y comentario con qué comprueba, por qué y las excepciones. +  * Comprueba que funcionan: pide al agente la forma actual de declarar una ruta en Angular y que abra la aplicación del worktree y te diga qué ve. 
-  * Lánzala con las seis reglas del tema. ''mvn test'' tiene que pasar. +  * Completa ''.claude/settings.json'' con los permisos de este tema y súbelo.
-  * Mueve a mano el servicio del CRUD al paquete ''controller'' y comprueba que ''mvn test'' falla con el mensaje del test. Deshazlo. +
-  * Finaliza el issue.+
  
 ==== Ejercicio 2 ==== ==== Ejercicio 2 ====
-  * Crea un issue «Tests unitarios y de API del CRUD» e inícialo. +  * Crea un issue «Skill /sdd» e inícialo con ''/git-flow start''. 
-  * Instala Playwright en ''frontend/'' (''npm init playwright@latest'') con los proyectos ''api'' y ''e2e'' y los scripts ''api-test'' y ''e2e-test'' del tema 3. +  * Instala cc-sdd en la raíz del repositorio y comprueba que ''/kiro-spec-init'' aparece como skill. 
-  * Escribe la skill ''/crear-test-unitarios'': recibe una clase o un paquete del dominio y genera un test JUnit 5 por comportamiento, con Mockito y sin Spring. +  * Escribe la skill ''/sdd'' con los dos subcomandos: ''spec create'' (lee el issue del nombre de la rama, pregunta lo que no esté claro y encadena las cuatro fases de cc-sdd, con ''-y'' en diseño y tareas) y ''spec impl'' (''/kiro-impl'' de las tareas pendientes, tests después de cada una, y parar si un test falla por el código). 
-  * Lánzala con el servicio del CRUD del tema 4. ''mvn test'' tiene que pasar. +  * Añade a ''AGENTS.md'' la línea sobre ''.kiro/specs/''. Finaliza el issue.
-  * Escribe la skill ''/crear-test-api'': recibe una entidad y genera ''tests/api/<entidad>.spec.ts'' con un test por endpoint del caso bueno y uno por cada error previsto, y lo ejecuta con ''npm run api-test'' hasta que pase. +
-  * Lánzala con la entidad del CRUD. ''mvn test'' no debe ejecutarlos; ''npm run api-test'' tiene que pasar dos veces seguidas. +
-  * Introduce un error a mano en una validación del servicio, reconstruye el backend y comprueba qué tests lo detectan: tiene que caer al menos un unitario y uno de API. Deshazlo. +
-  * Finaliza el issue.+
  
 ==== Ejercicio 3 ==== ==== Ejercicio 3 ====
-  * Crea un issue «Tests E2E del CRUD» e inícialo. +  * Crea un issue para la primera entidad de tu proyecto con un CRUD completo (por ejemplo «CRUD de productos») e inícialo. 
-  * Escribe la skill ''/crear-test-e2e'': recibe un fichero de plan, resetea la base de datos, abre la aplicación con el MCP de Playwright, escribe un ''.spec.ts'' por criterio de aceptación y lo ejecuta hasta que pase. +  * ''/sdd spec create''. Lee ''requirements.md'': comprueba que los criterios de aceptación son comprobables y que están los casos de error. Corrige lo que falte y vuelve a generar. 
-  * Lánzala con el plan del CRUD del tema 4. ''npm run e2e-test'' tiene que pasar dos veces seguidas. +  * Lee ''design.md'' y corrígelo a mano hasta que sea la arquitectura de Programación y DWS, clase por clase, con migración y datos de prueba. Lee ''tasks.md'' y comprueba que las tareas son pequeñas y van en orden. 
-  * Finaliza el issue.+  * ''/clear'' y ''/sdd spec impl''. Comprueba que marca las tareas hechas y que pasa los tests después de cada una. 
 +  * Prueba la aplicación en la URL del worktree: listado, alta, edición, borrado y las validaciones. Lo que no esté bien se pide en la misma conversación. 
 +  * Lee el código generado clase por clase y corrígelo: es la referencia de todos los CRUD que vienen después.
  
 ==== Ejercicio 4 ==== ==== Ejercicio 4 ====
-  * Crea un issue «Revisión por IA» e inícialo. +  * En el mismo worktree, lanza ''/kiro-steering''. Lee los tres ficheros y déjalos cortos, con solo lo común. 
-  * Escribe la skill ''/revisar'': diff de la rama contra ''develop'', comparación con el plan del issue y con las skills de convenciones, salida clasificada en grave / mejorable. +  * Con ''/kiro-steering-custom'' crea ''backend.md'' y ''frontend.md'' condicionales y rellénalos con la tabla del tema, mirando el CRUD que acabas de hacer. 
-  * Amplía ''/git-flow finalizar'' para que lance ''/revisar'' primero y se pare si hay algo grave. +  * Escribe ''convenciones-backend'' y ''convenciones-frontend'' apuntando a ellos. Comprueba que la ''description'' dice cuándo cargarlas. 
-  * Finaliza el issue.+  * ''/clear'' y pide un cambio pequeño en el backend. Comprueba que el agente carga ''convenciones-backend'' sin que se lo digas. 
 +  * ''/git-flow commit'' y ''/git-flow finish''. Comprueba que la spec ha entrado en ''develop'' en el mismo commit que el código. 
 +  * Mira ''/context'' al final de la conversación de implementación y anota cuánto ha ocupado.
  
 ==== Ejercicio 5 ==== ==== Ejercicio 5 ====
-  * Crea un issue «Revisión de calidad» e inícialo. +  * Crea un issue «Skill /code: impl» e inícialo. Escribe la skill ''/code'' con el verbo ''impl <plan>'': tareas pendientes del fichero, marcarlas, tests unitarios y de arquitectura tras cada una, y parar si un test falla por el código. Finaliza el issue. 
-  * Escribe la skill de conocimiento ''calidad-codigo'' con los cuatro ficheros de la tabla y los olores de diseño en ''SKILL.md''. Pide al agente un primer borrador a partir de la tabla y corrígelo: cada regla con una frase de ejemplo de código que la cumple y otra que no. +  * Crea un issue que no sea un CRUD (un filtro en el listado, un campo calculado, un informe) e inícialo. 
-  * Escribe la skill ''/revisar-calidad'' con los cinco pasos, ''allowed-tools'' solo de lectura y el formato de hallazgo del ejemplo. +  * En modo plan, dile lo que quieres y que escriba el plan en ''plan_<algo>.md''. Sal del modo plan y léelo: si falta una tarea o una está mal, corrígela a mano. 
-  * Pásala sobre el paquete del CRUD del tema 4. Lee el informe: para cada hallazgo, decide si es un defecto o una preferencia y por qué. +  * ''/clear'' y ''/code impl'' con el plan. Comprueba que marca las tareas y pasa los tests tras cada una. Prueba el cambio en el navegador y finaliza el issue.
-  * Pide que corrija solo los graves y vuelve a pasarla: no deben salir. +
-  * Finaliza el issue. +
- +
-==== Ejercicio 6 ==== +
-  * Crea un issue «cc-sdd y steering» e inícialo. +
-  * Instala cc-sdd en la raíz y lanza ''/kiro-steering''. Lee los tres ficheros y déjalos cortos, con solo lo común. +
-  * Con ''/kiro-steering-custom'' crea ''backend.md'' y ''frontend.md'' condicionales y rellénalos con la tabla de arriba, mirando el CRUD del tema 4. Deja las dos skills de convenciones apuntando a ellos. +
-  * Finaliza el issue. +
- +
-==== Ejercicio 7 ==== +
-  * Crea un issue para la segunda entidad de tu proyecto e inícialo. +
-  * Haz el CRUD con las cinco fases de cc-sdd. En la fase de diseño, compáralo con el CRUD del tema 4: cada diferencia es una línea que falta en el steering. Corrígela y repite la fase hasta que salga igual. +
-  * Genera los tests con ''/crear-test-api'' y ''/crear-test-e2e'' a partir de ''requirements.md'' y comprueba que ''mvn test'', ''npm run api-test'' y ''npm run e2e-test'' pasan. +
-  * Quita a mano de ''requirements.md'' un caso de error sin quitar su código y lanza ''/git-flow finalizar''. ''/revisar'' tiene que marcarlo como grave y la fusión no debe hacerse. Restaura el fichero y finaliza.+
  
clase/daw/daw-proyecto/tema05.1791935227.txt.gz · Última modificación: por claude