# KAPPA Hub

> Asistente multi-proyecto para KAPPA. Semilla de RUMBO.
> POC → validación diaria → lo que funciona migra a RUMBO.

## Stack

| Capa | Tecnología | Versión |
|------|-----------|---------|
| Desktop shell | Tauri v2 | 2.11 |
| Frontend | Vue 3 + TypeScript + Vite | 3.4 / 5.x |
| Runtime JS | Bun | 1.3+ |
| Estado | Pinia | 2.1 |
| BD local | Turso (libSQL) | Embedded |
| HTTP | fetch() directo a KAPPA (proxy Vite en dev) |
| Auth | Bearer token (POST /api/users/login/) |
| UI | shadcn-vue (New York) + Tailwind CSS v4 | 2.7 |
| Tablas | AG Grid Community + tanstack/vue-table | 35.3 |
| i18n | vue-i18n (es.json + en.json) — **PROHIBIDO hardcodear texto** | 11.4 |

## Reglas de código

1. **PROHIBIDO hardcodear texto visible al usuario.** Todo texto debe usar `t('clave')` de vue-i18n. Si no existe la clave, agregarla a `es.json` y `en.json`.
2. **KAPPA retorna tipos mixtos**: strings, números y booleanos para el mismo campo (ej: `status` puede ser `"active"`, `true`, o `3`). Siempre usar `String(valor)` o `safeStr()` antes de operar.
3. **No usar `.catch(() => {})`** sin loguear el error. Siempre `console.error()`.
4. **Los nombres de funciones y archivos van en español** cuando son semánticos del dominio (ej: `syncHUsToTurso` → OK, pero labels visibles van en i18n).
5. **Toda función debe tener observabilidad**: loguear entrada con `[Alpha]` + acción + datos clave, loguear errores con `[Alpha]` + descripción + error completo. Sin logs no se puede diagnosticar.
6. **IDs jerárquicos obligatorios en componentes**: todo elemento raíz de sección debe tener `id="{view}-{section}-{element}"` en kebab-case. Ej: `dashboard-stats-epics`, `login-card`, `users-table`. Permite ubicar cualquier componente por su ID sin ambigüedad.

## Sincronización entre máquinas (Mac Mini ↔ MacBook Air)

El proyecto vive en iCloud Drive: `com~apple~CloudDocs/AI/Teloprax/02_productos/kappa-hub/`.

- **Código**: se sincroniza automáticamente vía iCloud. Solo `bun install` una vez por máquina.
- **Datos de KAPPA**: viven en el servidor (kappa.lambdaanalytics.co). El Hub es solo un cliente.
- **Token**: localStorage del navegador. Loguearse una vez por máquina.
- **Datos locales futuros** (borradores, caché): se guardarán como archivos en `data/` dentro del proyecto, sincronizados vía iCloud. Ver `../rumbo/sincronizacion.md`.

## Calendarios externos (K-21)

| Servicio | Auth | Capacidad |
|----------|------|-----------|
| Google Calendar | OAuth2 | Leer eventos, escribir eventos |
| Microsoft Graph (Outlook/Teams) | OAuth2 | Leer eventos, escribir eventos |
| iCal (.ics) | Archivo | Importar/exportar |

### Flujo post-reunión (K-22)

```
1. RUMBO lee calendario (Google/Outlook)
2. Detecta: "Reunión con Cliente X, 8-9am"
3. Después de la reunión (+15/30 min):
   → 🔔 "Terminó tu reunión con Cliente X"
   → "¿Ya capturaste las notas?"
   → "¿Hay transcripción?"
   → "¿Se extrajeron las tareas?"
4. Si no → RUMBO guía a completar
```

**Analogía**: RUMBO como Apple Watch — te alerta cuando llevas mucho tiempo sentado (reuniones sin seguimiento = deuda de contexto).

### API de recordatorios (futuro)

```typescript
interface Reminder {
  id: string
  trigger_at: string        // ISO datetime
  title: string
  body: string
  action_url?: string      // deep link a la vista correspondiente
  dismissed: boolean
  source: 'calendar' | 'scheduler' | 'hu_deadline'
}
```

## APIs KAPPA integradas

| Endpoint | Método | Uso en el hub |
|----------|--------|--------------|
| `/users/login/` | POST | Auth |
| `/initiatives-all/` | GET | Listar proyectos |
| `/users/all/` | GET | Listar usuarios |
| `/userstorys/create/` | POST | Crear HU desde transcripción |
| `/logbooks_master/create/` | POST | Crear bitácora |
| `/logbooks/create/` | POST | Entrada de bitácora |
| `/plannings_master/create/` | POST | Crear planeación |
| `/plannings/create/` | POST | Entrada de planeación |
| `/business-rules/create/` | POST | Reglas de negocio |
| `/functionalrequirements/create/` | POST | Requisitos funcionales/no funcionales |

## Estructura

```
kappa-hub/
├── src/
│   ├── types/kappa.ts          # Tipos TypeScript
│   ├── services/kappa-api.ts   # Cliente HTTP KAPPA
│   ├── stores/                 # Pinia
│   │   ├── auth.ts
│   │   ├── projects.ts
│   │   └── workitems.ts
│   ├── views/
│   │   ├── LoginView.vue
│   │   └── DashboardView.vue
│   ├── components/layout/
│   │   └── AppShell.vue
│   ├── App.vue
│   └── main.ts
├── package.json
└── vite.config.ts
```

## Cómo ejecutar

```bash
cd "02_productos/kappa-hub"
bun install   # una vez por máquina
bun dev       # http://localhost:5173
```

Abre http://localhost:5173. El proxy de Vite redirige `/api/*` a `https://kappa.lambdaanalytics.co`.

## Pipeline de transcripciones (K-10) ✅

Nueva vista **Transcripciones** en la barra lateral (icono upload).

**Flujo:**
1. Configurar API key de OpenRouter (DeepSeek) — se guarda en localStorage
2. Seleccionar proyecto destino desde el dropdown
3. Arrastrar o seleccionar archivo (.docx, .vtt, .txt, .md)
4. El archivo se parsea localmente (mammoth.js para docx, parseo manual para VTT)
5. Click "Analizar con IA" → se envía a OpenRouter DeepSeek
6. La IA devuelve HUs estructuradas (título, descripción, criterios de aceptación, prioridad, tipo)
7. Revisar, seleccionar/deseleccionar, eliminar HUs
8. Click "Crear en KAPPA" → se crean vía API
9. Las HUs creadas se marcan en verde y se refresca el store de workitems

**Archivos nuevos:**
- `src/services/ai.ts` — Cliente OpenRouter DeepSeek
- `src/services/parse-transcription.ts` — Parseo de .docx/.vtt/.txt/.md
- `src/stores/transcriptions.ts` — Pinia store del pipeline
- `src/views/TranscriptionsView.vue` — Vista completa con upload, preview, análisis, resultados

**Modelo usado:** `deepseek/deepseek-chat-v3-0324:free` (free tier de OpenRouter)

## Próximos pasos

1. ~~Agregar Dexie.js para cache offline~~ (K-15)
2. ~~Pipeline de transcripciones~~ (K-10)
3. ⬜ **Dashboard multi-proyecto** (K-11)
4. ⬜ **Priorizador diario** (K-12)
5. ⬜ **Generador de reportes** (K-13)
6. ⬜ **Integración calendario Google/Outlook** (K-21)
7. ⬜ **Alertas post-reunión** (K-22)

---

## Changelog — Decisiones técnicas

### 2026-05-29: Asignación HU + Status desde KAPPA

**Asignado (employee_id vs user_id)**
- KAPPA devuelve `asignado_a: [1135]` donde 1135 es **employee_id**, no user_id.
- Employee 1135 → user 1115 (Felipe Crespo). El mapeo está en `usersStore.employees`.
- `parseAssignedUser()` en `stores/workitems.ts` separa:
  - `asignado_a` → `_assignedEmployeeId` (employee_id)
  - `assigned_to` → `_assignedUserId` (user_id directo)
- `DashboardView.resolveEmployeeToUser()` busca en `usersStore.employees.find(e.id === employeeId)?.user`
- Para persistencia en Turso (un solo campo `assigned_to`): employee_id se guarda como **negativo** (`-1135`).
  `parseAssignedUser()` detecta negativos y los trata como employee_id.

**Status**
- KAPPA devuelve `status: 6` (número) + `status_name: "QA-Client"`.
- `enrichHU()` usa `hu.status_name` primero; fallback a `resolveStatusName(hu.status)`.
- `STATUS_MAP` en `services/statuses-db.ts` ahora mapea valores numéricos (`'1'`–`'7'`) y nombres KAPPA.

**Prioridad**
- KAPPA devuelve `priority: "3"` (string numérico). `PRIORITY_MAP` mapea `"1"`/`"2"`/`"3"` y texto.

**UI - Tabla HUs**
- Columna Asignado: texto plano (no Select). Muestra nombre real o `asignado_a_names` de KAPPA.
- Columna Estado: muestra `status_name` de KAPPA (ej: QA-Client) con badge de color.
- Filtros con placeholder "Estado"/"Prioridad"/"Asignado". Filtro Asignado solo lista desarrolladores con HUs.

**Dexie (browser)**
- Schema v8: nueva tabla `user_stories` con `&id, initiative_id`.
- Fallback en `tauri-db.ts` para get/save user_stories (antes solo Tauri).
