--- id: "0099" title: "datahub app (launcher central para todas las apps)" status: pendiente type: feature domain: - apps-infra scope: app-scoped priority: alta depends: [] blocks: [] related: [] created: 2026-05-17 updated: 2026-05-17 tags: [] --- # 0099 — datahub app (launcher central para todas las apps) **Status:** pendiente **Created:** 2026-05-16 **Type:** app **Priority:** alta **Depends:** 0096 (apps/ standard) — DONE, iconos .ico (2026-05-16) — DONE **Blocks:** — ## Problema Cada app C++ del registry vive como `.exe` standalone en `/mnt/c/Users/lucas/Desktop/apps//.exe`. Para arrancar cualquiera hay que: 1. Abrir Explorer en Desktop/apps. 2. Entrar al subdir de la app. 3. Doble-click al `.exe`. Multiplicado por 11+ apps el ratio "tiempo-de-encontrar / tiempo-de-uso" es alto. Ademas: - Nada indica si la app ya esta corriendo (PID, mem). - Nada permite verla actualizada (rebuild + redeploy desde la UI). - Sin descripcion/categoria visible — solo el nombre del exe + icono. ## Objetivo v1 App C++ ImGui standalone `apps/datahub/` que actua como **launcher central**: 1. **Catalogo de apps** desde `registry.db` tabla `apps` con `lang='cpp'` (y opcionalmente `lang='go'` con `framework='cli'`). Una card / fila por app con: - **Icono** (`/appicon.ico` rasterizado a textura GL — reusar `gl_texture_load`). - **Nombre** + descripcion del frontmatter. - **Tags** (chips: `service`, `gfx`, `tui`, `tools`, ...). - **Estado**: stopped / running (PID + mem via `is_cpp_app_running_windows_bash_infra`). - **Botones**: Launch / Stop / Redeploy / Open dir. 2. **Filtro**: por dominio (`tools`, `gfx`, `tui`, `infra`, ...), por tag (`service`, ...), por texto. 3. **Live updates**: polling cada 2s al status del proceso. WS opcional si pesa demasiado el polling de 11 procesos. 4. **Logs**: cada launch redirige stdout/stderr a `Desktop/apps//launch.log`. Boton `Tail log` abre panel lateral con ultimas 200 lineas. ## Fuera de v1 - **Programar launches** (cron / schedule) — separar a issue distinto. - **Auto-update**: rebuild background al detectar `.exe` cambiado — v2. - **Multi-PC**: solo PC local. Sin remote control. - **Apps no-C++** (Go services, Python pipelines): listadas pero sin Launch button. Solo metadata. - **Grafico de dependencias** entre apps (que app llama a que sqlite_api / dag_engine). ## Arquitectura ``` apps/datahub/ app.md # frontmatter + e2e_checks CMakeLists.txt # add_imgui_app(datahub ...) main.cpp # fn::run_app + render catalog.{cpp,h} # lee registry.db apps via fn_match (SQLite read-only) process.{cpp,h} # launch/stop/is_running (wrappers a is_cpp_app_running_windows + launch_cpp_app_windows) texture_cache.{cpp,h} # carga .ico → GL texture (reusa gl_texture_load) tabs.{cpp,h} # Catalogo, Logs, Settings appicon.ico # icono propio (phosphor: 'squares-four' o 'app-window', accent #6366f1 indigo-500) ``` Fuente de verdad: - **registry.db** (read-only) — catalogo de apps + paths + tags. - **Disk Desktop/apps//** — verifica que esta desplegada antes de mostrar Launch. No tiene operations.db propia v1 — el estado de procesos es volatil. Si en v2 queremos historial de launches → `apps/datahub/operations.db` con tabla `launches`. ## Fases | Fase | Que entra | |---|---| | **A. Scaffold** | `fn run init_cpp_app datahub --desc "Launcher central de apps del registry"`. Mapping icono: phosphor `squares-four-fill` accent `#6366f1`. Genera `appicon.ico`. | | **B. catalog.cpp — query registry.db** | SELECT id, name, description, tags, dir_path FROM apps WHERE lang='cpp' (read-only `?mode=ro`). Helper `list_cpp_apps()` → `std::vector`. | | **C. UI catalog** | ImGui table (data_table o BeginTable) con filas, columnas: Icon / Name / Desc / Tags / Status / Actions. Filter bar arriba (text + tag chips). | | **D. Icon textures** | Reusa `gl_texture_load`. Cache ` → GLuint`. Lazy load primer frame visible. Fallback a icono generico si `/appicon.ico` falta. | | **E. Process control** | Wrappers a `is_cpp_app_running_windows_bash_infra` (status) + `launch_cpp_app_windows_bash_infra` (start) + taskkill (stop). Async via `process_runner_cpp_core` para no bloquear UI. | | **F. Log tail panel** | Click `Tail log` → panel lateral. Reusa `file_watcher_cpp_core` + `selectable_text_cpp_core`. | | **G. Redeploy boton** | Click `Redeploy` → spawn `./fn run redeploy_cpp_app_windows --build` en background. Progress en status bar. | | **H. e2e_checks + deploy** | build_cmake, binary_exists, self-test (--list-apps imprime JSON con N apps), cpp_apps_conformance. `redeploy_cpp_app_windows datahub`. | ## Funciones del registry usadas (sin codigo nuevo esperado) | ID | Para que | |---|---| | `is_cpp_app_running_windows_bash_infra` | Status de cada app | | `launch_cpp_app_windows_bash_infra` | Launch button | | `redeploy_cpp_app_windows_bash_pipelines` | Redeploy button | | `gl_texture_load_cpp_gfx` | .ico → GLuint | | `data_table_cpp_viz` | Tabla catalogo | | `process_runner_cpp_core` | Async shell exec | | `file_watcher_cpp_core` | Log tail | | `selectable_text_cpp_core` | Render log lines | | `app_menubar_cpp_core` | Menu bar (View / Help) | | `layouts_menu_cpp_core` | Layouts persistentes | | `sqlite_open_cpp_infra` (si existe; si no, abrir directo con sqlite3_open_v2 read-only) | Read registry.db | ## Posibles funciones nuevas a delegar | ID propuesto | Lang | Que hace | Justificacion | |---|---|---|---| | `list_registry_apps_cpp_core` | cpp core | Lee `apps` table de registry.db (read-only), devuelve `std::vector`. | Reusable: datahub + cualquier dashboard futuro que liste apps. | | `app_status_windows_cpp_core` | cpp core | Wrapper sync sobre `is_cpp_app_running_windows`. Devuelve `{pid, mem_mb, running}`. | Hoy solo existe como bash. Para C++ ImGui hace falta wrapper que parse el output. | Decidir en fase B/E si delegar a `fn-constructor` o si el codigo cabe inline en datahub (criterio: si patron se repite en otra app -> registry; si es unico → datahub-local). ## e2e_checks (borrador para fase H) ```yaml e2e_checks: - id: build cmd: "cmake --build cpp/build/linux --target datahub -j" timeout_s: 300 - id: binary_exists cmd: "test -f cpp/build/linux/apps/datahub/datahub" - id: self_test cmd: "./cpp/build/linux/apps/datahub/datahub --list-apps" expect_stdout_contains: '"name":' timeout_s: 15 - id: cpp_conformance cmd: "./fn doctor cpp-apps --json | jq '.[] | select(.app_id==\"datahub_cpp_tools\")'" ``` ## Aceptacion v1 - `datahub.exe` lanzable desde Desktop con icono propio (phosphor squares-four / indigo). - Lista las 11 apps actuales C++ con icono, nombre, descripcion, tags, estado. - Botones Launch / Stop / Redeploy funcionales. - Filtro por texto + tag funciona. - Tail log de una app corriendo se actualiza en vivo (file_watcher). - `fn doctor cpp-apps` reporta datahub conformante. - No bloquea UI al lanzar/parar/redeployar (todo async). ## Riesgos / decisiones | Riesgo | Mitigacion | |---|---| | Polling 11 procesos cada 2s es caro (taskkill.exe + tasklist.exe) | Si pesa, batch en una sola llamada `tasklist /fi "imagename eq .exe or imagename eq .exe ..."` o WS endpoint en sqlite_api que publique status. | | Icono `.ico` no se decodifica en GL (PIL → png intermedio?) | `gl_texture_load` ya soporta `.ico` via stb_image (verificar). Si no, convertir a PNG cache al primer load. | | Redeploy desde la UI puede tardar minutos | Lanzar background + barra de progreso. Permitir cancel. Lock por app (evitar dos redeploys simultaneos). | | App "Datahub" se confunde con "Data Factory" (issue 0097) | Datahub = launcher (proceso control). Data Factory = lineage de datos. Cero solape funcional. Documentar la distincion en ambos app.md. | ## Pendientes posteriores (v2+) - Schedule launches (cron-like). - Health KPIs agregados (apps_running / apps_total / cpu / mem total). - Integracion con `dag_engine_ui` para lanzar DAGs como apps. - Auto-discovery de apps no-C++ con `launch_command` declarado en frontmatter. - Sync entre PCs: ver que apps tiene desplegadas el otro PC (pc_locations). ## Referencias - Iconos `.ico`: ver `.claude/rules/cpp_apps.md §11` y `generate_app_icon_py_infra` (creada 2026-05-16). - Patron list-apps + tabla: similar a `registry_dashboard` Monitor tab. - Patron process control: replicar como `dag_engine_ui` orquesta runs.