# Plan de Refactor Técnico — 2025-11-01

Este documento describe un plan de refactor seguro, incremental y medible para estabilizar tipado, reducir duplicación, mejorar estructura y preparar la base para evolución a largo plazo. Se prioriza no añadir dependencias externas y mantener el comportamiento actual cubierto por tests.

## Objetivos

- Reducir duplicación (fechas/horas, validaciones, helpers de tests, cripto).
- Endurecer tipado y contratos en TypeScript (mientras mantenemos compatibilidad).
- Clarificar capas (utils compartidos, servicios, API web, UI SvelteKit, tests).
- Estabilizar convenciones (UTC, formato SQLite, alias/imports, nombres).
- Mantener comportamiento: cambios sin funcionalidad nueva, validados por tests.

## Hallazgos clave (del diagnóstico inicial)

- Archivos grandes:
  - apps/web/src/lib/ui/data/TaskItem.svelte ~911 LOC (punto caliente claro).
  - Varias páginas Svelte de 250–335 LOC (AppShell, /app, /app/groups, etc.).

- Duplicación evidente:
  - Formateo SQL-UTC con `toISOString().replace('T',' ').replace('Z','')` aparece 35+ veces en app y tests.
  - `normalizeTime` duplicado en API y page.server.
  - `ymdUTC` y `addMonthsUTC` definidas 3 veces en rutas ICS y también en tests.
  - `sha256Hex` reimplementado en múltiples tests pese a existir en `src/utils/crypto.ts`.
  - SimulatedResponseQueue replicado en varios tests.

- Tipado/infra:
  - tsc falla en apps/web por `$lib` y `./$types` (faltan tipos generados SvelteKit) y por DOM (navigator/document) y Bun types (HeadersInit/fetch).
  - apps/web/vite.config.ts incompatibilidad de tipos (UserConfig).
  - Errores “unknown” por resultados de SQLite (faltan tipos/casts).
  - Inconsistencias null vs undefined (p. ej., groupColor, whatsapp utils).

- Cobertura mejorable:
  - webhook-manager (~32%), maintenance (~17%), contacts (~26%), onboarding (~30%), response-queue (~50%).

- Organización:
  - Inyección de DB mediante propiedades estáticas dispersas; funcional pero frágil. Falta un “locator” central.

## Fase 1 — Diagnóstico asistido (Completada)

Comandos ejecutados con éxito el 2025-11-01; a continuación se conservan para referencia y repetibilidad:

```bash
git ls-files '*.ts' '*.tsx' '*.svelte' | xargs wc -l | sort -nr | head -n 30
```

```bash
git grep -n "toISOString().replace('T', ' ').replace('Z', '')"
```

```bash
git grep -n "normalizeTime(" && git grep -n "ymdUTC(" && git grep -n "addMonthsUTC(" && git grep -n "isValidYmd("
```

```bash
git grep -n "sha256Hex(" && git grep -n "SimulatedResponseQueue"
```

```bash
bunx tsc --noEmit --pretty false
```

```bash
bun test --coverage
```

Resultados esperados después del refactor: disminución drástica de duplicados, tsc limpio por paquete, y cobertura estable o al alza.

## Progreso

- 2025-11-01:
  - Documento creado y versionado (commit a104b69).
  - Diagnóstico ejecutado (wc -l, git grep, tsc, coverage) y hallazgos consolidados en este documento.
  - Pendiente iniciar Lote 0 (Infra de typecheck): a la espera de revisar tsconfig raíz, apps/web/tsconfig y apps/web/vite.config.
- 2025-11-02:
  - Lote 1 completado: util canónica de fechas/UTC creada (src/utils/datetime.ts) y wrapper web (apps/web/src/lib/server/datetime.ts); migración de rutas ICS y reemplazos en producción (hooks, login, complete/uncomplete, calendar tokens, dev-seed, response-queue, maintenance, group-sync, migrator).
  - Commits relevantes: f4f7d95, 882f5c9, c1f12ff, df27161, a0f35b8.
  - Tests verdes. Cobertura actual: 85.91% funciones / 82.12% líneas.
- 2025-11-07:
  - Lote 0 completado: scripts `typecheck:core` y `typecheck:web` configurados y verificados. Se utiliza `tsconfig.core.json` para aislar el typecheck del core con reglas laxas, mientras que la web usa su propia configuración de SvelteKit. Los shims en `src/types/shims.d.ts` resuelven conflictos de tipos entre Bun y el DOM.
  - Verificación exitosa: `bun run typecheck:core` y `bun run typecheck:web` se ejecutan sin errores.
- 2025-11-09:
  - Lote 2 completado: centralización de helpers de tests (sha256Hex, toIsoSql), unificación de SimulatedResponseQueue y helpers ICS (ymdUTC, addDays) en tests.
  - Commits relevantes: 77e318e, 1ad36ee, y este commit.
- 2025-11-10:
  - Lote 3 completado: endurecimiento de tipos (noImplicitAny, exactOptionalPropertyTypes, strictNullChecks), centralización de normalizeTime y tipado ligero de SQLite en servicios; inclusión de servicios en typecheck; limpieza de as any en puntos clave.
  - Verificación: typecheck core/web limpios y tests verdes.
  - Lote 4 completado: ICS central y rutas homogéneas; rate limiting por token; títulos “Wtask.org Tareas – Personal/Grupo/Agregado” y PRODID “-/Wtask.org//ICS 1.0//ES”; eventos de día completo; ETag/304 y Cache-Control; actualización de last_used_at solo en 200.
  - Commit relevante: 234053c.
  - Lote 5 completado: división de TaskItem en subcomponentes (SVGs a iconos, TaskDueBadge, TaskAssignees, TaskCompleteButton, TaskActions, TaskText, TaskMeta); sin cambios funcionales; tests verdes y typecheck web limpio.
  - Lote 5.5-a completado: ResponseQueue extraído (EvolutionClient, limpieza modular, parseo de metadata); sin cambios funcionales; commits: 1b7420e, 2032712.
  - Lote 5.5-c completado: TaskService extraído (display_code, reacción al completar, mapeadores); sin cambios funcionales; LOC actual en src/tasks/service.ts ≈ 621; commits: e3ec820, a72184f.
  - Lote 5.5-b completado: GroupSyncService modularizado (api.ts, repo.ts, cache.ts, reconcile.ts) y desacople de Onboarding A3 (publishGroupCoveragePrompt); umbral aplicado; tests y typecheck limpios; commits: 1b0d2ec, 0ce3ecb, 2f24806.
  - Lote 5.5-d completado: WebhookServer modularizado (/metrics, /health y bootstrap a src/http; handleMessageUpsert extraído a src/http/webhook-handler.ts); sin cambios funcionales; tests verdes; commits: 46bec52, 7189756, e430fc1.
  - Lote 6.0-6.2 completados: DB Locator mínimo, conexión en bootstrap con setDb y ruta única de DB (centralización y reexport en web); sin cambios funcionales; tests y typecheck limpios; commits: 9222242, 6196dba, 2669d42.
  - Lote 6.3 completado: adopción piloto con fallback en ResponseQueue y TaskService; añadido smoke test de fallback (tests/unit/locator.fallback.test.ts); tests y typecheck limpios; commit relevante: 77ad9d7.
  - Lote 6.4 completado: adopción progresiva de servicios al locator (fallback parámetro → .dbInstance → getDb()) en CommandService, RemindersService, MaintenanceService, AdminService y fachada de GroupSync; tests y typecheck limpios; commits: cd83455, f786ba8.
  - Lote 6.5 completado: limpieza de .dbInstance, añadido resetDb/clearDb en locator, migración de tests al locator; nota: ~8 tests frágiles en paralelo; en CI ejecutar la suite en un solo worker.
  - Estado: Lote 6 completado.

## Estado actual (2025-11-10)

- Fase 1 — Diagnóstico asistido: Completada.
- Fase 2 — Plan de refactor por lotes: En curso.
  - Lote 0 — Infra de typecheck: Completado.
  - Lote 1 — Utilidades de fecha/hora y validaciones: Completado.
  - Lote 2 — Helpers de test y cripto: Completado.
  - Lote 3 — Tipos y endurecimiento suave: Completado.
  - Lote 4 — ICS central y rutas homogéneas: Completado.
  - Lote 5 — Svelte: dividir componentes grandes: Completado.
  - Lote 5.5 — Refactor de servicios grandes (god classes): Completado.
  - Lote 6 — DB Locator / DI ligera: Completado (PRs 6.0–6.5).
  - Lote 7 — Cobertura en módulos flojos: Pendiente.

## Fase 2 — Plan de refactor por lotes (PRs pequeñas y seguras)

Cada lote incluye objetivo, cambios, métricas y comprobaciones. Mantener tests verdes en cada paso.

### Lote 0 — Infra de typecheck (preparación) - Completado

- Objetivo:
  - Separar el chequeo de tipos por paquete (core vs web) para aislar errores de SvelteKit/Bun/DOM.
- Cambios:
  - Scripts: `typecheck:core` (tsc -p tsconfig.core.json), `typecheck:web` (apps/web: svelte-kit sync + tsc).
  - En raíz, excluir apps/web del typecheck general si hace falta hasta que esté sincronizado.
  - Ajustar lib/types: en core, definir tipos mínimos para HeadersInit/fetch si no se quiere añadir bun-types; en web, asegurar DOM y tipos SvelteKit (via `svelte-kit sync`).
  - Revisar apps/web/vite.config.ts para que encaje con tipos `UserConfig`.
- Métricas:
  - `bunx tsc --noEmit` limpio por paquete.
  - Desaparecen errores `$lib` y `./$types` tras `svelte-kit sync`.
- Comprobaciones:
  - `cd apps/web && bunx svelte-kit sync && bunx tsc --noEmit`.

### Lote 1 — Utilidades de fecha/hora y validaciones - Completado

- Objetivo:
  - Centralizar y unificar: SQL-UTC, validadores YMD y HH:mm, utilidades ICS (ymdUTC, addMonthsUTC).
- Cambios:
  - Crear helpers canónicos (por ejemplo, `toIsoSqlUTC`, `isValidYmd`, `normalizeTime`, `ymdUTC`, `addMonthsUTC`) en un módulo compartido (core o shared) y exportarlos también para web si aplica.
  - Reemplazar todas las ocurrencias del patrón `toISOString().replace(...)`.
  - Unificar las 3 rutas ICS para usar las mismas utilidades.
- Métricas:
  - `git grep "toISOString().replace('T', ' ').replace('Z', '')"` → 1 referencia (en el helper) o 0 si se encapsula internamente.
  - `git grep "ymdUTC("` y `"addMonthsUTC("` solo en helpers + imports.
- Comprobaciones:
  - Tests ICS y API siguen verdes.

### Lote 2 — Helpers de test y cripto - Completado

- Objetivo:
  - Eliminar duplicación en tests.
- Cambios:
  - Reemplazar implementaciones locales de `sha256Hex` por import desde `src/utils/crypto`.
  - Centralizar SimulatedResponseQueue en `tests/helpers/queue.ts` y reusarlo.
  - Unificar helpers de fechas en tests (`toIsoSql`, `ymdUTC`, `addDays`) en `tests/helpers/dates.ts`.
- Métricas:
  - `git grep -n "async function sha256Hex"` en tests → 0.
  - `git grep -n "SimulatedResponseQueue"` → 1 implementación única.
- Comprobaciones:
  - `bun test --coverage` estable o mejor.

### Lote 3 — Tipos y endurecimiento suave - Completado

- Objetivo:
  - Bajar ruido de TS con cambios mínimos, sin funcionalidad nueva.
- Cambios:
  - Resolver `undefined` vs `null` en utils como groupColor/whatsapp.
  - Corregir `HeadersInit`/`fetch` en servicios (group-sync, webhook-manager, contacts) para encajar con tipos.
  - Añadir refinamientos y cheques donde TS marca “posiblemente undefined”.
  - Tipar resultados de SQLite `.get()`/`.all()` en tests y servicios.
- Métricas:
  - `bunx tsc --noEmit` limpio en core.
- Comprobaciones:
  - Tests verdes.

### Lote 4 — ICS central y rutas homogéneas - Completado

- Objetivo:
  - Consolidar construcción de ICS (escape, folding, etag) en un módulo central.
- Cambios:
  - Mover `ymdUTC`/`addMonthsUTC` al módulo `apps/web/src/lib/server/ics.ts` y usarlos desde aggregate/group/personal.
  - Mantener helpers de escape/folding/etag en el mismo módulo.
- Métricas:
  - `git grep -n "function ymdUTC"` y `"function addMonthsUTC"` solo en ics.ts.
- Comprobaciones:
  - Tests ICS (`tests/web/ics.*`) verdes.

### Lote 5 — Svelte: dividir componentes grandes

- Objetivo:
  - Reducir complejidad de UI; mejorar mantenibilidad.
- Cambios:
  - Dividir `TaskItem.svelte` (~911 LOC) en subcomponentes: Header/Status, Assignees, DueBadge, Actions, Metadata, etc.
  - Revisar `AppShell` y `/app/+page` para separar lógica de datos y presentación (stores y load).
- Métricas:
  - `TaskItem.svelte` < 300 LOC.
- Comprobaciones:
  - 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 (Completado; ~621 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) — Completado
     - 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 `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

- Objetivo:
  - Simplificar inyección de DB en runtime y tests.

- Cambios:
  - Crear un “dbLocator” (getDb/setDb/withDb) central y migrar servicios a usarlo progresivamente, manteniendo compatibilidad con propiedades estáticas mientras dura la transición.
  - Unificar `resolveDbAbsolutePath` entre core y web (una sola fuente, con reexport en web para no romper imports).

- Métricas:
  - Sin cambios de comportamiento; tests de servicios verdes.

- PRs propuestos y archivos a tocar:

  PR 6.0 — Locator mínimo (infraestructura, sin usos en servicios) — Completado
  - Nuevos archivos:
    - src/db/locator.ts — export { setDb, getDb, withDb }.
    - tests/unit/db/locator.test.ts — pruebas básicas del locator.
  - Cambios en docs:
    - Este documento (apartado de Lote 6).

  PR 6.1 — Conexión en bootstrap (setDb al arrancar) — Completado
  - Archivos a modificar:
    - src/http/bootstrap.ts — importar setDb desde src/db/locator y llamarlo en el arranque (cuando se abra la DB).
    - src/server.ts — si es quien abre la DB, llamar setDb(db) justo después de crearla (o delegar en bootstrap).
  - Servicios: sin cambios (compatibilidad total con dbInstance estático).

  PR 6.2 — Ruta única de DB (centralizar resolveDbAbsolutePath) — Completado
  - Nuevos archivos:
    - src/env/db-path.ts — export function resolveDbAbsolutePath(filename = 'tasks.db'): string.
  - Archivos a modificar:
    - apps/web/src/lib/server/env.ts — reexportar desde src/env/db-path.ts para mantener compatibilidad (sin cambios de API pública).
    - src/server.ts o src/http/bootstrap.ts — actualizar imports a src/env/db-path.
  - Comprobaciones esperadas:
    - bunx tsc -p tsconfig.core.json --noEmit
    - bun test --coverage

  PR 6.3 — Adopción piloto con fallback (2 servicios) — Completado
  - Archivos a modificar:
    - src/services/response-queue.ts — usar (ResponseQueue as any).dbInstance ?? getDb().
    - src/tasks/service.ts — usar (TaskService as any).dbInstance ?? getDb().
  - Tests a ajustar (si aplica):
    - tests/unit/services/response-queue.test.ts — asegurar setDb(memdb) en beforeAll cuando no se inyecte dbInstance.
    - tests/unit/tasks/*.test.ts — idem.
  - Comprobaciones esperadas:
    - bunx tsc -p tsconfig.core.json --noEmit
    - bun test --coverage

  PR 6.4 — Adopción progresiva (resto de servicios principales) — Completado
  - Archivos a modificar (por tandas pequeñas):
    - src/services/group-sync/*.ts (api.ts, repo.ts, cache.ts, reconcile.ts) — fallback a getDb().
    - src/services/command.ts, src/services/reminders.ts, src/services/maintenance.ts, src/services/admin.ts, src/services/contacts.ts, src/services/webhook-manager.ts — fallback a getDb().
  - Tests a ajustar según servicio:
    - tests/unit/services/**/*.test.ts — añadir setDb(memdb) donde no se use dbInstance explícita.
  - Comprobaciones esperadas:
    - bunx tsc -p tsconfig.core.json --noEmit
    - bun test --coverage

  PR 6.5 — Limpieza final — Completado
  - Hecho:
    - Eliminadas propiedades estáticas dbInstance de servicios migrados a locator.
    - Añadidos resetDb/clearDb en src/db/locator.ts para tests.
    - Migrados tests a setDb(...) y resetDb()/clearDb(); se observa flakiness en ejecución paralela en ~8 tests. Recomendación: ejecutar la suite en un solo worker en CI.

### Lote 7 — Cobertura en módulos flojos

- Objetivo:
  - Aumentar cobertura en módulos con lógica y baja cobertura (webhook-manager, maintenance, contacts, onboarding, response-queue).
- Cambios:
  - Añadir pruebas de ramas de error y caminos menos transitados.
- Métricas:
  - Cobertura de líneas > 80% en esos módulos.

## Convenciones acordadas

- Fechas/horas:
  - Persistir en UTC en SQLite con formato ISO-SQL “YYYY-MM-DD HH:MM:SS[.SSS]”.
  - Un solo helper para serializar/deserializar timestamps.
  - Validadores canónicos: YMD (YYYY-MM-DD), HH:mm (00–23:00–59).

- Tipado:
  - TS estricto por módulos de forma incremental: `strict`, `noImplicitAny`, `noUncheckedIndexedAccess`, `exactOptionalPropertyTypes` (activación progresiva).
  - Resultados SQLite tipados (interfaces pequeñas y casts controlados).

- Organización:
  - Helpers compartidos (fecha/validaciones/cripto) en módulo único (o shared).
  - Tests reusan helpers de `tests/helpers`.

- SvelteKit:
  - `svelte-kit sync` antes de `tsc` para generar tipos.
  - Rutas ICS homogéneas con helpers de `lib/server/ics`.

## Riesgos y mitigación

- Fechas/UTC: posibles regresiones en límites y recordatorios.
  - Mitigación: snapshots/fixtures antes/después de serializaciones, comparar salidas ICS.
- DI de DB: transición puede generar inconsistencias si se mezcla estático/locator.
  - Mitigación: migración gradual y adaptador de compatibilidad temporal.
- Tipado estricto: ruido inicial.
  - Mitigación: endurecer flags por paquete/módulo en varias PRs pequeñas.

## Métricas de aceptación por lote

- Tests verdes y sin cambios funcionales.
- Reducción de duplicados medible (git grep antes/después).
- `bunx tsc --noEmit` limpio en el ámbito del lote.
- Cobertura estable o en subida en módulos afectados.

## Siguientes pasos prácticos

1) Estabilizar typecheck (Lote 0): **Completado**.
2) Unificar fechas/validaciones (Lote 1): **Completado**.
3) Centralizar helpers de tests y cripto (Lote 2): **Completado**.
4) Endurecer tipos en core (Lote 3): **Completado**.
5) Consolidar ICS (Lote 4): **Completado**.
6) Dividir TaskItem y revisar AppShell (Lote 5): **Completado**.
7) DI ligera para DB (Lote 6).
8) Aumentar cobertura en módulos flojos (Lote 7).
9) Documentación exhaustiva (Fase D): plan y PRs D0–D6.
10) Internacionalización (Fase I): plan y PRs I0–I7.

## Información adicional a recopilar (para Lote 0)

- tsconfig.json (raíz)
- apps/web/tsconfig.json
- apps/web/vite.config.ts

Con estos 3 archivos podremos definir cambios mínimos para tener un typecheck limpio por paquetes sin introducir dependencias externas.

## Fase D — Documentación (nueva)

El objetivo de esta fase es frenar la “entropía documental” actual, ofrecer una narración clara para quien llega nuevo y, a la vez, dejar una base sólida para seguir evolucionando el sistema sin añadir deuda técnica.

### Principios

- Markdown en /docs como fuente de verdad; sin dependencias nuevas; build opcional más adelante.
- Documentación estructurada por **qué quiere hacer la persona lectora** (evaluar, desplegar, operar, contribuir), no por “lista de archivos existentes”.
- README raíz orientado a adopción (pitch, casos de uso, requisitos), con enlaces claros a la documentación detallada.
- Documentación “v2” claramente separada de planes históricos y documentos de trabajo.
- Verificación simple en CI para comprobar “completitud” (p. ej., grep de variables de entorno usadas vs documentadas).

### D0: Reset estructural y guía de estilo

Objetivo: redefinir la estructura de documentación y marcar qué es canónico vs histórico, sin perder información.

Cambios:

- **README raíz (del repo)**:
  - Reescribirlo con foco en:
    - Tagline y pitch corto (qué resuelve, para quién).
    - Casos de uso y “no es para ti si…”.
    - Requisitos para desplegarlo (Evolution API, hosting, etc.).
    - Vista de alto nivel de cómo funciona.
    - Enlace claro a `docs/` (Quickstart, Guía de uso, Arquitectura, etc.).

- **Definir documentos canónicos en `docs/`** (columna vertebral “v2”):
  - `docs/README.md` — índice general y guía de estilo.
  - `docs/overview.md` — visión general y flujos clave (evaluación).
  - `docs/quickstart.md` — de cero a bot funcionando (dev/prod).
  - `docs/config/env.md` — referencia única de variables de entorno.
  - `docs/usage/commands.md` — uso por WhatsApp (comandos).
  - `docs/usage/web.md` — uso de la interfaz web.
  - `docs/architecture.md` — arquitectura lógica y DB locator.
  - `docs/operations.md` — operación, métricas, backups, health/metrics.
  - `docs/contributing.md` — cómo tocar el código sin romper convenciones.

- **Crear un área de documentación histórica**:
  - Nuevo directorio: `docs/legacy/` (o similar).
  - Mover allí:
    - Planes antiguos (`plan-*.md`, `*-plan.md`) que ya no encajen con el estado actual.
    - Documentos de trabajo y notas de diseño que han quedado superadas por este plan.
  - Añadir `docs/legacy/README.md` explicando que:
    - Son documentos históricos, útiles como contexto, pero **no** representan el estado actual ni la decisión vigente.

- **Guía de estilo mínima en `docs/README.md`**:
  - Idioma principal: español para texto narrativo; identificadores y nombres técnicos en inglés.
  - Convenciones de nombres de archivos (kebab-case, sufijos como `-guide`, etc.).
  - Expectativas por documento (público objetivo y nivel técnico).

Métricas de aceptación:

- README raíz reescrito y enlazando a la nueva estructura.
- `docs/README.md` actualizado con el índice “v2” y la guía de estilo.
- Todos los planes/documentos obsoletos movidos a `docs/legacy/` y etiquetados como históricos.

### D1: Referencia de variables de entorno

Objetivo: consolidar una tabla única y fiable de configuración por entorno.

Cambios:

- Construir un inventario completo:
  - Partir del `git grep process.env` (ya recogido en este documento).
  - Complementar con las variables definidas en `.env.example`.
  - Identificar:
    - variables usadas en código pero ausentes en `.env.example`,
    - variables presentes en `.env.example` que ya no se usan.

- Crear `docs/config/env.md`:
  - Tabla con columnas:
    - **VARIABLE** | **Descripción** | **Tipo** | **Por defecto** | **Obligatoria** | **Ámbito (core/web)** | **Sensible (sí/no)**.
  - Sección explicando:
    - cómo se cargan (ficheros `.env` vs entorno),
    - qué variables son imprescindibles para arrancar,
    - particularidades en test (variables que los tests fuerzan o suponen).

- Sincronizar `.env.example` con la tabla:
  - Mismas variables.
  - Comentarios alineados con la descripción de `docs/config/env.md`.
  - README raíz solo enumera un subconjunto (“configuración esencial”) y enlaza a este documento para el resto.

Métricas de aceptación:

- `docs/config/env.md` cubre el 100% de las variables utilizadas en código.
- `.env.example` sin variables huérfanas ni faltantes respecto al inventario.
- Potencial check de CI: script simple que compare nombres de variables entre código, `env.md` y `.env.example`.

### D2: Quickstart e instalación

Objetivo: permitir que alguien nuevo pase de “clonar el repo” a “tengo el bot funcionando” sin leer todo el resto.

Cambios:

- Crear/actualizar `docs/quickstart.md`:
  - Requisitos:
    - Bun/Node versión recomendada.
    - Instancia de Evolution API.
    - Almacenamiento para SQLite.
  - Pasos:
    - Clonar repositorio e instalar dependencias.
    - Copiar `.env.example` y rellenar variables mínimas.
    - Arrancar en desarrollo (core + web).
    - Arrancar en producción (comandos de build + start).
  - “Happy path”:
    - ejemplo de mensaje de WhatsApp para crear una tarea,
    - cómo verla en la web (/app),
    - cómo confirmar que /health y /metrics responden.

- Alinear README raíz con este quickstart:
  - Sección “Instalación rápida” condensando los pasos principales.
  - Enlace explícito a `docs/quickstart.md` para detalles.

Métricas de aceptación:

- Una persona que no conoce el proyecto puede seguir `docs/quickstart.md` en una máquina limpia y terminar con:
  - webhook recibiendo eventos,
  - tareas visibles en /app,
  - métricas en /metrics.

### D3: Uso (web + comandos)

Objetivo: documentar claramente la experiencia de uso, separando canales (WhatsApp vs web) y evitando duplicidad.

Cambios:

- Reorganizar la documentación de uso actual en dos archivos:

  - `docs/usage/commands.md`:
    - Basado en `docs/USER_GUIDE.md` y `docs/commands-inventory.md`.
    - Contenido:
      - prefijo de comandos y principios (DM vs grupo, fechas, rate limit),
      - catálogo de comandos con alias, parámetros y ejemplos,
      - notas sobre:
        - interpretación de fechas (“hoy”, “mañana”, YYYY-MM-DD),
        - menciones reales vs tokens `@número`,
        - comportamiento en grupo vs DM,
      - sección de administración (/admin…).

  - `docs/usage/web.md`:
    - Basado en `plan-diseno-web.md`, `plan-web-fases.md` y el estado actual de la UI.
    - Contenido:
      - estructura de `/app` (lista de tareas, grupos, preferencias),
      - flujo típico de uso desde web (reclamar/soltar, editar, completar),
      - relación entre lo que ves en WhatsApp y lo que ves en la web,
      - vistas de calendario/ICS y cómo se consumen.

- Dejar `docs/USER_GUIDE.md` como entrada que redirige:
  - Puede convertirse en un índice breve que apunte a `usage/commands.md` y `usage/web.md`, o bien moverse a `docs/legacy/` cuando la nueva estructura esté madura.

Métricas de aceptación:

- No hay duplicación significativa de contenido entre README, `USER_GUIDE`, `usage/commands` y `usage/web`.
- Los ejemplos de comandos están actualizados y probados manualmente (al menos los principales).

### D4: Operaciones y despliegue

Objetivo: facilitar la vida a quien opera Taskbot en producción (observabilidad, mantenimiento, CI/CD).

Cambios:

- Crear/actualizar `docs/operations.md`:
  - Basado en `operations.md`, `metrics-plan.md`, `CI-CD-PLAN.md` y `docs/grafana/`.
  - Contenido:
    - **Despliegue**:
      - opciones típicas (proceso único vs supervisado por systemd, contenedores, etc.),
      - recomendaciones de recursos y almacenamiento,
      - interacción con Evolution API (timeouts, health checks).
    - **Migraciones y base de datos**:
      - cómo y cuándo se ejecutan migraciones,
      - política de WAL y PRAGMAs más importantes,
      - estrategias de backup/restore de SQLite.
    - **Observabilidad**:
      - uso de `/health` (qué comprueba, señales de fallo),
      - uso de `/metrics` (Prometheus/JSON, flags de configuración),
      - referencia al dashboard de Grafana (`docs/grafana/taskbot-metrics.json`): qué gráficos hay y qué significan.
    - **Schedulers y tareas periódicas**:
      - sincronización de grupos,
      - recordatorios,
      - limpieza de cola de respuestas,
      - cómo ajustar intervalos y qué implicaciones tienen.

- Conectar con variables de entorno:
  - Enlazar a `docs/config/env.md` para cada opción relevante (p. ej. `GROUP_SYNC_INTERVAL_MS`, `RQ_*`, `METRICS_*`).

Métricas de aceptación:

- Operador externo puede entender:
  - qué mirar en caso de problemas (health/metrics/logs),
  - cómo hacer backup/restore sin corromper la DB,
  - cómo cambiar la frecuencia de tareas periódicas con seguridad.

### D5: Arquitectura y DB

Objetivo: ofrecer una visión clara de cómo está organizado el sistema internamente, especialmente tras el refactor (servicios extraídos, DB locator, ICS central).

Cambios:

- Consolidar `docs/architecture.md`:
  - Integrar/actualizar contenido de `architecture.md`, `overview.md`, `database.md` y este propio plan.
  - Contenido:
    - **Componentes principales**:
      - servidor HTTP (WebhookServer y handlers /webhook, /health, /metrics),
      - servicios de dominio (TaskService, ResponseQueue, GroupSync, Reminders, Admin…),
      - cola de respuestas y cliente Evolution,
      - app web SvelteKit.
    - **DB Locator**:
      - motivación,
      - API básica (`getDb`/`setDb`/`withDb`),
      - cómo se usa en servicios y tests.
    - **Flujos clave**:
      - mensaje entrante → comando → creación/actualización de tarea → encolado de respuesta/reacción,
      - sincronización de grupos y membresías,
      - recordatorios.
    - **Base de datos**:
      - tablas principales (tasks, task_assignments, groups, group_members, response_queue, user_preferences…),
      - invariantes importantes,
      - decisiones de diseño (WAL, migraciones up-only).

- Mantener `docs/database.md` como detalle de esquema:
  - Puede centrarse en:
    - descripción tabla a tabla,
    - índices relevantes,
    - ejemplos de consultas típicas,
  - enlazado desde `docs/architecture.md`.

Métricas de aceptación:

- Contributors nuevos pueden entender dónde “colgar” código nuevo (por ejemplo, un nuevo servicio, una nueva tabla o un nuevo comando).
- Este plan de refactor técnico se percibe como coherente con la arquitectura documentada (no como un documento separado y divergente).

### D6: Contribución y ADRs

Objetivo: ayudar a futuras personas contribuidoras (incluido tú mismo “del futuro”) a cambiar el sistema sin romper las convenciones ni repetir debates ya resueltos.

Cambios:

- Crear/actualizar `docs/contributing.md`:
  - Contenido:
    - cómo montar entorno de desarrollo (dependencias, comandos básicos),
    - cómo ejecutar:
      - typecheck core (`bun run typecheck:core`),
      - typecheck web (`bun run typecheck:web`),
      - tests y cobertura (`bun test --coverage`),
    - convenciones de código:
      - UTC y formato de timestamps en SQLite,
      - uso de helpers centralizados (datetime, crypto, helpers de test),
      - tipos estrictos en TS (flags activados y expectativas),
      - uso del DB locator.
    - criterios para abrir PRs:
      - tests verdes,
      - sin cambios funcionales en lotes que se declaran “refactor internos”,
      - cuándo y cómo añadir un ADR.
    - referencia rápida a how-tos existentes:
      - `how-to/adding-command.md`,
      - `how-to/adding-migration.md`,
      - `how-to/adjusting-group-sync.md`,
      - `how-to/adding-env.md`.

- Consolidar ADRs:
  - Mantener `docs/adr/*.md` como registro de decisiones de arquitectura.
  - Añadir ADRs nuevos cuando:
    - se tomen decisiones de largo plazo (p. ej., i18n, políticas de rate limiting, cambios de almacenamiento).
  - Desde `docs/contributing.md`, explicar:
    - cuándo merece la pena un ADR,
    - cómo estructurarlo (título, contexto, decisión, consecuencias).

Métricas de aceptación:

- Contributors pueden:
  - saber qué comandos ejecutar antes de abrir PR,
  - entender las decisiones ya tomadas (UTC, DB locator, ICS, estructura de servicios),
  - no tener que “descubrirlas” leyendo código o este plan.

### Orden recomendado de ejecución para Fase D

1. Ejecutar **D0** (reset estructural):
   - nuevo README raíz orientado a adopción,
   - índice v2 en `docs/README.md`,
   - movimiento de documentos antiguos a `docs/legacy/`.

2. Ejecutar **D1** (env) y **D2** (quickstart) en paralelo:
   - cerrar la historia de “cómo configuro esto” y “cómo lo echo a andar”.

3. Completar **D3** (uso commands/web) apoyándose en la guía de usuario actual, reorganizando sin perder contenido útil.

4. Redondear con **D4** (operaciones) y **D5** (arquitectura/DB) usando este plan de refactor como referencia.

5. Cerrar con **D6** (contribución+ADRs), conectando:
   - decisiones técnicas ya tomadas,
   - how-tos existentes,
   - y el pipeline de typecheck/tests.

Esta Fase D se coordina con los lotes técnicos previo/posteriores:

- depende de que el estado del core/web esté relativamente estable (Lotes 0–6),
- y sirve como preparación explícita antes de acometer cambios más invasivos (i18n, nuevos comandos, cambios de esquema), reduciendo el riesgo de deuda técnica futura.

## Fase I — Internacionalización (nueva)

- Principios:
  - Sin dependencias externas: diccionarios JSON + helper t() con plantillas {var}.
  - en-US como base del código; es-ES como primera localización.
  - Locale configurable por ENV y, en web, preferencia por usuario (con fallback).
- PR I0: Inventario y glosario
  - Auditoría de textos visibles (servicios, UI, errores “para usuario”, títulos ICS).
  - Glosario EN/ES y convenciones de keys (scope.key).
  - Aceptación: listado consolidado.
- PR I1: Normalización de identificadores a inglés
  - Renombrar funciones/variables/módulos que sigan en español (sin tocar textos visibles).
  - Aceptación: grep de identificadores no ingleses → 0 o lista de excepciones (nombres propios).
- PR I2: Infra i18n mínima (core)
  - Helper t(locale, key, params) y carga de diccionarios.
  - ENV APP_LOCALE y orden de resolución (env → usuario → default).
  - Aceptación: conmutación en 1–2 mensajes de ejemplo entre en-US/es-ES.
- PR I3: Externalización de mensajes en servicios
  - WhatsApp/CLI/respuestas de comandos → keys + params.
  - Mantener es-ES como referencia y crear en-US equivalentes.
  - Aceptación: tests de comandos verdes en ambos locales; 0 strings hardcoded en servicios.
- PR I4: UI web (SvelteKit)
  - Carga de diccionarios por ruta/layout, helper en frontend, marcadores para traducciones faltantes.
  - Preferencia de idioma por usuario y fallback Accept-Language.
  - Aceptación: cambiar idioma desde preferencias refleja cadenas principales.
- PR I5: Formatos y convenciones por locale
  - Fechas/números con Intl; labels de días; ymd→dmy solo en vistas.
  - ICS: título/PRODID localizables; contenido sigue en UTC.
  - Aceptación: pruebas de formateo y snapshots actualizados.
- PR I6: Logs y métricas
  - Política: logs en inglés estable; mensajes de usuario traducibles; métricas/labels estáticos.
  - Aceptación: política documentada y aplicada.
- PR I7: QA i18n en CI
  - Comprobador: claves sin traducción, claves huérfanas, placeholders inválidos.
  - Smoke tests en en-US y es-ES (web y comandos básicos).
  - Aceptación: CI bloquea claves faltantes.

- Orden recomendado:
  1) Completar Lote 7 (cobertura) para congelar comportamiento.
  2) PRs D0–D6 (documentación) en paralelo donde sea posible.
  3) PRs I0–I7 (i18n) en tandas pequeñas, con tests en ambos locales.
