Files
Alpha/AGENTS.md
T
ricardo 19c6fb3153 DashboardView: columna SP + fix priority/story_points perdidos en enrichHU
- enrichHU ahora incluye status, priority y story_points en el return
- Nueva columna SP (story points) entre Título y Estado en tabla HUs
- Filtro prioridad acepta valores numéricos (1/2/3)
2026-05-29 08:41:37 -05:00

188 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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).