@ -98,6 +98,7 @@ Resultados esperados después del refactor: disminución drástica de duplicados
- Lote 3 — Tipos y endurecimiento suave: Completado.
- Lote 3 — Tipos y endurecimiento suave: Completado.
- Lote 4 — ICS central y rutas homogéneas: Completado.
- Lote 4 — ICS central y rutas homogéneas: Completado.
- Lote 5 — Svelte: dividir componentes grandes: Completado.
- Lote 5 — Svelte: dividir componentes grandes: Completado.
- Lote 5.5 — Refactor de servicios grandes (god classes): Pendiente.
- Lote 6 — DB Locator / DI ligera: Pendiente.
- Lote 6 — DB Locator / DI ligera: Pendiente.
- Lote 7 — Cobertura en módulos flojos: Pendiente.
- Lote 7 — Cobertura en módulos flojos: Pendiente.
@ -186,6 +187,117 @@ Cada lote incluye objetivo, cambios, métricas y comprobaciones. Mantener tests
- Comprobaciones:
- Comprobaciones:
- Pruebas E2E web verdes.
- Pruebas E2E web verdes.
### Lote 5.5 — Refactor de servicios grandes (god classes)
- Objetivo general:
- Reducir acoplamiento y responsabilidades múltiples en servicios grandes para mejorar testabilidad, DX y preparar Lote 6 (locator/DI) sin cambios funcionales.
- Mantener APIs públicas y rutas de import estables, delegando a nuevos módulos internos.
- Alcance y orden de PRs:
1) PR 5.5-a — ResponseQueue (673 LOC)
- Motivos: mezcla de repositorio (SQLite), backoff, envío HTTP (texto/reacciones), idempotencia, limpieza/retención, métricas y lógica de onboarding.
- Cambios clave:
- Extraer cliente Evolution (HTTP):
- Nuevo módulo: `src/clients/evolution.ts` con `buildHeaders()` , `sendText(payload)` , `sendReaction(payload)` y manejo de errores/logging.
- Tipar metadata y parsers:
- Tipo `QueueMetadata = { kind: 'onboarding' | 'reaction'; ... }` , helpers `parseQueueMetadata()` , `isReactionJob()` .
- Aislar limpieza/retención:
- Nuevo módulo: `src/services/queue/cleanup.ts` con `runCleanupOnce()` , `startCleanupScheduler()` , `stopCleanupScheduler()` .
- ResponseQueue queda como orquestador (claim → enviar → marcar), delegando a EvolutionClient y Cleanup.
- Archivos a consultar:
- `src/services/response-queue.ts` (origen), `src/utils/datetime.ts` , `src/services/metrics.ts` , `src/services/identity.ts` , `src/utils/whatsapp.ts` , `src/db/migrations/index.ts` (esquema `response_queue` ), tests `tests/unit/services/response-queue.test.ts` .
- Métricas de aceptación:
- `src/services/response-queue.ts` < 350 LOC .
- No variación en defaults (`MAX_ATTEMPTS`, `REACTIONS_MAX_ATTEMPTS` , backoff).
- Idempotencia de reacciones (24h) intacta.
- Comprobaciones y comandos:
```bash
bunx tsc -p tsconfig.core.json --noEmit --pretty false
bun test --coverage
git grep -n "sendReaction\\|sendText" src
```
2) PR 5.5-c — TaskService (708 LOC)
- Motivos: mezcla de creación (códigos display), queries de listado/contadores, reglas de negocio (claim/unassign), y reacción al completar.
- Cambios clave:
- Extraer generación de display_code:
- Nuevo: `src/tasks/display-code.ts` con `pickNextDisplayCode(db)` .
- Extraer reacción al completar:
- Nuevo: `src/tasks/complete-reaction.ts` con `enqueueCompletionReactionIfEligible(db, taskId)` .
- Extraer mapeos a DTO:
- Nuevo: `src/tasks/mappers.ts` con `mapRowToTask()` , `mapRowsToListItem()` .
- `TaskService.createTask/completeTask/list*` delegan en estos helpers.
- Archivos a consultar:
- `src/tasks/service.ts` (origen), `src/services/allowed-groups.ts` , `src/services/response-queue.ts` (reacción), `src/utils/whatsapp.ts` , `src/db/migrations/index.ts` , tests `tests/unit/tasks/*.test.ts` , `tests/unit/services/command.*.test.ts` .
- Métricas de aceptación:
- `src/tasks/service.ts` < 500 LOC .
- TTL y gating de reacciones sin cambios de comportamiento.
- Comprobaciones y comandos:
```bash
bunx tsc -p tsconfig.core.json --noEmit --pretty false
bun test --coverage
git grep -n "display_code" src
```
3) PR 5.5-b — GroupSyncService (1310 LOC)
- Motivos: agrupa API (Evolution), parseos, upsert/caché, scheduling, reconciliación de miembros, allowed-groups y publicación de onboarding.
- Cambios clave:
- Extraer acceso Evolution API:
- Nuevo: `src/services/group-sync/api.ts` con `fetchGroups()` , `fetchMembers(groupId)` y parseos robustos.
- Extraer repositorio/caché:
- Nuevo: `src/services/group-sync/repo.ts` con `upsertGroups()` , `ensureGroupExists()` , `getActiveCount()` , `cacheActiveGroups()` , `listActiveMemberIds()` , getters/setters `onboarding_prompted_at` .
- Nuevo: `src/services/group-sync/cache.ts` para la `Map<string,string>` y helpers.
- Extraer reconciliación:
- Nuevo: `src/services/group-sync/reconcile.ts` con `reconcileGroupMembers(db, groupId, snapshot, nowIso?)` .
- Mover publicación de mensajes de cobertura de alias a OnboardingService:
- Añadir método en `src/services/onboarding.ts` : `publishGroupCoveragePrompt(db, groupId, ratio, options)` .
- `GroupSyncService` queda como fachada (APIs públicas y schedulers), delegando internamente.
- Archivos a consultar:
- `src/services/group-sync.ts` (origen), `src/services/allowed-groups.ts` , `src/services/identity.ts` , `src/services/metrics.ts` , `src/utils/datetime.ts` , `src/db/migrations/index.ts` , tests `tests/unit/services/group-sync.*.test.ts` .
- Métricas de aceptación:
- `src/services/group-sync.ts` ≈ 600– 700 LOC (fase 1), sin cambios funcionales.
- Caché y métricas sin variaciones de semántica.
- Comprobaciones y comandos:
```bash
bunx tsc -p tsconfig.core.json --noEmit --pretty false
bun test --coverage
git grep -n "fetchAllGroups\\|participants" src/services/group-sync*
```
4) PR 5.5-d — WebhookServer (665 LOC)
- Motivos: `src/server.ts` mezcla handlers HTTP (/metrics, /health), bootstrap y manejo del webhook (message upsert).
- Cambios clave:
- Controladores HTTP dedicados:
- Nuevo: `src/http/metrics.ts` (render y headers).
- Nuevo: `src/http/health.ts` (cálculo payload; usa `GroupSyncService.getSecondsUntilNextGroupSync()` ).
- Nuevo: `src/http/webhook-handler.ts` con `handleWebhookRequest(req)` y `handleMessageUpsert(data)` .
- Nuevo: `src/http/bootstrap.ts` con `startServices()` (webhook-manager, schedulers, queues, maintenance).
- `src/server.ts` queda como wire-up (validateEnv → migrate → Bun.serve) y reexporta fachada `WebhookServer` para no romper tests.
- Archivos a consultar:
- `src/server.ts` (origen), `src/services/webhook-manager.ts` , `src/services/response-queue.ts` , `src/services/maintenance.ts` , `src/services/reminders.ts` , `src/services/group-sync.ts` , `src/services/admin.ts` , `src/services/allowed-groups.ts` , `src/services/contacts.ts` , `src/services/command.ts` .
- Métricas de aceptación:
- `src/server.ts` < 350 LOC .
- Rutas/contratos HTTP y logs sin cambios de comportamiento.
- Comprobaciones y comandos:
```bash
bunx tsc -p tsconfig.core.json --noEmit --pretty false
bun test --coverage
git grep -n "handleRequest(\\|handleMessageUpsert" src
```
- Métricas de aceptación (global Lote 5.5):
- Tests verdes y sin cambios funcionales observables.
- Reducción de LOC por fichero objetivo:
- response-queue.ts < 350 , tasks / service . ts < 500 , group-sync . ts ≈ 600 – 700 , server . ts < 350 .
- `bunx tsc --noEmit` limpio en core.
- Cobertura igual o superior en piezas extraídas (api/reconcile/cleanup/complete-reaction).
- Riesgos y mitigación:
- Dividir módulos puede introducir imports cíclicos:
- Mitigación: módulos nuevos sin importar servicios de alto nivel; inyectar `db` como parámetro; reexportar desde fachada.
- Cambios en logging o tiempos:
- Mitigación: mantener mensajes/claves existentes; conservar defaults; validar en tests de integración.
### Lote 6 — DB Locator / DI ligera
### Lote 6 — DB Locator / DI ligera
- Objetivo:
- Objetivo: