Imported from DavidS30/examen-fullstack-david (
AGENTS.md). Install upstream withnpx skills add DavidS30/examen-fullstack-david. Copyright stays with the author.
AGENTS.md — Bolsillo de Ahorro Programado
Contexto de proyecto para agentes de OpenCode. Léelo completo antes de cualquier cambio. Estas reglas tienen prioridad sobre comportamientos por defecto del agente.
1. Objetivo del proyecto
Aplicación full stack para gestión de metas de ahorro ("Bolsillos"). El usuario puede crear metas, consultar su progreso, registrar abonos y recibir una notificación distintiva en tiempo real cuando una meta llega al 100%.
Esto es una prueba técnica con sustentación en vivo (30 min). El objetivo evaluado NO es la cantidad de features, sino el criterio de ingeniería: separación de responsabilidades, patrones de diseño, tipado estricto, estrategia de pruebas y la capacidad de justificar cada decisión y sus trade-offs.
Historias de usuario (alcance cerrado — no agregar features fuera de esto)
- Dashboard de Metas: listar metas (nombre, monto objetivo, monto acumulado, % de progreso) con actualización inmediata al registrar un abono.
- Registro de Abonos: seleccionar una meta y abonarle un valor, con validaciones de negocio (monto > 0, no exceder el objetivo).
- Procesamiento de Abonos (backend): validar, aplicar la regla, persistir y notificar el nuevo estado.
- Notificación de Meta Alcanzada: al completar el 100%, emitir un evento especial que dispare un diálogo/confirmación visual distintiva en la UI.
2. Stack técnico (decidido — no cambiar sin justificar en docs/arquitectura.md)
| Capa | Tecnología |
|---|---|
| Backend | Java 21 + Spring Boot 3 |
| Persistencia | H2 en memoria (Spring Data JPA) |
| Tiempo real | SSE nativo (SseEmitter / EventSource) |
| Frontend | Angular (LTS) + Signals + Reactive Forms |
| Tests backend | JUnit 5 + Mockito + @WebMvcTest/MockMvc |
| Tests frontend | Vitest |
| Contenedores | Docker multi-stage + docker-compose |
Sin packages/ compartido: Java y TypeScript no comparten runtime. Los contratos se
duplican como DTOs Java (Bean Validation) e interfaces TS espejo. Es una decisión
consciente documentada en docs/arquitectura.md (el enunciado la contempla como válida).
3. Arquitectura — Hexagonal ligero (Ports & Adapters)
Regla dura de dependencias: domain ← application ← infrastructure.
El dominio no depende de nada; la infraestructura depende hacia adentro, nunca al revés.
backend/src/main/java/.../
domain/ Entidades (Bolsillo), Value Objects (Money), reglas puras
application/ Casos de uso: CrearBolsilloUseCase, RegistrarAbonoUseCase
application/ports/ Interfaces: BolsilloRepository, NotificadorPort
infrastructure/
persistence/ Adaptador JPA que implementa BolsilloRepository
web/ BolsilloController (REST), NotificacionesController (SSE)
events/ @EventListener que traduce eventos de dominio a SSE
frontend/src/app/
features/bolsillos/ dashboard, formulario de abono, modal meta-alcanzada
core/ servicio SSE (EventSource), cliente HTTP, modelos TS
Prohibiciones de arquitectura (el agente NO debe violarlas)
domain/NO puede importarorg.springframework.*,jakarta.persistence.*ni nada de infraestructura. Solo Java puro. (Anotaciones de validación van en los DTOs deweb/, no en las entidades de dominio.)application/solo conoce interfaces deapplication/ports, nunca clases concretas deinfrastructure/.- La lógica de negocio vive en
domain/yapplication/, nunca en los controllers. - En el frontend, la lógica de negocio y el acceso HTTP/SSE viven en servicios de
core/, no en los componentes.
4. Patrones de diseño (obligatorio: mínimo 2, implementados explícitamente)
- Repository —
BolsilloRepository(puerto enapplication/ports) implementado por un adaptador que envuelve Spring Data JPA. El caso de uso no conoce JPA directamente. - Observer / Pub-Sub — el caso de uso publica
AbonoRegistradoEventyMetaAlcanzadaEventvíaApplicationEventPublisher; un@EventListenereninfrastructure/eventslos traduce a mensajes SSE. Desacopla dominio de la notificación.
Opcional si sobra tiempo: Strategy para validaciones (List<AbonoValidationRule>).
5. Reglas de negocio (fuente de verdad)
- Monto del abono debe ser > 0 (rechazar 0 y negativos).
- Un abono no puede hacer que
acumulado > objetivo(rechazar el exceso). - Al alcanzar exactamente el 100% (
acumulado == objetivo), además del evento normal de actualización, se emiteMetaAlcanzadaEvent(dispara el modal distintivo en la UI). - Monto objetivo de una meta debe ser > 0 al crearla.
6. Estándares de código
- Tipado estricto de punta a punta.
- Java: sin raw types, sin
Objectgenérico, sinnullcomo flujo de control (usarOptionalen puertos). Bean Validation (@NotNull,@Positive) en los DTOs de entrada. - TypeScript:
strict: true. Prohibidoanysalvo justificación técnica en comentario en la misma línea (// eslint-disable ... razón).
- Java: sin raw types, sin
- Commits incrementales con mensajes descriptivos (el checklist lo evalúa). Un commit por unidad lógica de trabajo, NO un único commit gigante al final.
- Nombres de dominio en español (Bolsillo, Abono, Meta) para alinear con el negocio; nombres técnicos en inglés está bien.
7. Estrategia de pruebas (obligatoria en backend y frontend)
- Backend: tests unitarios de casos de uso y lógica de negocio (JUnit + Mockito con un
fake in-memory del repositorio) + test de endpoint principal (
@WebMvcTest+ MockMvc). Cubrir casos borde: monto 0, monto negativo, abono que excede el objetivo, y el disparo del evento de meta alcanzada. - Frontend: Vitest. Tests de componente/servicio para los flujos clave (listado, formulario de abono, actualización de estado por SSE).
- Usar el subagente
@test-writerpara generarlos; revisar siempre la salida a mano.
8. Gobernanza de IA — mantener docs/ia.md en vivo (NO al final)
Cada vez que aceptes o rechaces una sugerencia relevante de la IA, anótalo en el momento
en docs/ia.md. Ese archivo debe contener:
- Skills/Prompts automatizados: el comando
/gen-test(.opencode/command/gen-test.md). - Agents/Sub-agentes:
@test-writer(generación de pruebas) y@arch-guard(auditor de arquitectura y tipado estricto). - Bitácora de co-creación: qué generó la IA vs. qué escribiste/corregiste a mano, con
mínimo 2 ejemplos concretos de sugerencias de IA que rechazaste/modificaste y por qué
(ej.
anyen un DTO, lógica de negocio en un controller, sobre-ingeniería con NgRx).
9. Flujo de trabajo esperado del agente
- Antes de cerrar cada feature, corre
@arch-guardpara validar dependencias y tipado. - Genera/actualiza tests con
@test-writerpara el código nuevo. - Actualiza
docs/arquitectura.mdydocs/ia.mden la misma sesión, no después. - Haz commit incremental con mensaje claro.
10. Despliegue
docker compose uplevanta backend (:8080) y frontend (nginx:80→4200).- nginx hace
proxy_pass /api/*al backend para evitar CORS. - Dockerfiles multi-stage; los tests NO corren dentro del build de imagen (se corren aparte).
- Plan B documentado: servir el build de Angular desde
static/del jar de Spring (un solo contenedor, un solo puerto) como red de seguridad para la demo en vivo.
11. Comandos útiles
# Backend
cd backend && ./mvnw spring-boot:run # levantar
cd backend && ./mvnw test # pruebas
# Frontend
cd frontend && npm start # levantar (ng serve)
cd frontend && npm test # pruebas headless (vitest run)
# Todo junto
docker compose up --build