Files
egutierrez ca67f343df docs: documentar dependencias de runtime (sqlite_api, call_monitor, dev_console)
La tab Work (issue 0102) y su backend dev_console no estaban documentados.
Se anade una seccion que mapea las tres apps de las que depende el dashboard
en tiempo de ejecucion, su tipo de acoplamiento y el comportamiento degradado
cuando cada una falta.
2026-06-03 17:37:36 +02:00

13 KiB

name, lang, domain, version, description, tags, uses_functions, uses_types, uses_modules, framework, entry_point, dir_path, repo_url, icon
name lang domain version description tags uses_functions uses_types uses_modules framework entry_point dir_path repo_url icon
registry_dashboard cpp tui 0.1.0 Dashboard ImGui para visualizar el estado del fn_registry. Consume datos via sqlite_api HTTP (fallback a SQLite directo). KPIs, charts, tablas, desglose por lenguaje/dominio/pureza.
dashboard
imgui
visualization
registry
http
kpi_card_cpp_viz
bar_chart_cpp_viz
pie_chart_cpp_viz
table_view_cpp_viz
sparkline_cpp_viz
dashboard_panel_cpp_core
dashboard_grid_cpp_core
fullscreen_window_cpp_core
page_header_cpp_core
badge_cpp_core
empty_state_cpp_core
button_cpp_core
icon_button_cpp_core
toolbar_cpp_core
modal_dialog_cpp_core
text_input_cpp_core
select_cpp_core
toast_cpp_core
tree_view_cpp_core
process_runner_cpp_core
process_state_machine_cpp_core
data_table_cpp
imgui main.cpp projects/fn_monitoring/apps/registry_dashboard https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/dataforge/registry_dashboard
phosphor accent
gauge #059669

Arquitectura

Dashboard C++ con dos modos de acceso a datos:

  1. HTTP API (primario): Conecta a sqlite_api via HTTP para obtener datos de registry.db. No requiere acceso al filesystem.
  2. SQLite directo (fallback): Lee registry.db directamente si la API no esta disponible.

Data layers:

  • data_http.cpp: Carga datos via HTTP POST a sqlite_api (cpp-httplib + nlohmann/json)
  • data.cpp: Carga directa desde SQLite C API

Views (views.cpp): Compone funciones del registry C++ para renderizar:

  • 8 KPI cards: functions, types, apps, analysis, unit tests, proposals, tested%, pure%
  • Bar charts: funciones por lenguaje, por dominio
  • Pie charts: pureza (pure/impure), kind (function/pipeline/component)
  • Tablas: ultimas 20 funciones, apps, analysis, tipos

Dependencias de runtime (otras apps)

Ademas de las funciones, tipos y modulos del registry declarados en el frontmatter (uses_functions, uses_modules), el dashboard depende en tiempo de ejecucion de tres apps del ecosistema fn_monitoring. Estas dependencias no se expresan en el frontmatter porque el schema de la tabla apps no tiene un campo para dependencias entre apps; se documentan aqui.

App Acoplamiento Para que Si falta
sqlite_api (projects/fn_monitoring/apps/sqlite_api, servicio HTTP en :8484) HTTP POST /api/databases/... + WebSocket /api/events/call_monitor Fuente primaria de datos (registry.db) y stream en vivo del Monitor tab El dashboard cae al modo SQLite directo (--api "" mas un path a registry.db). El Monitor tab pierde el stream en vivo y solo muestra el snapshot inicial.
call_monitor (projects/fn_monitoring/apps/call_monitor, telemetria) Indirecto: escribe su operations.db, que sqlite_api lee y reenvia por WebSocket Eventos del Monitor tab (calls, violations, ejecuciones recientes) El Monitor tab queda vacio. El WebSocket de sqlite_api se cierra con snapshot failed si la operations.db de call_monitor no esta registrada en el pool. El registro ocurre al arrancar sqlite_api, por lo que un reinicio del servicio la recoge si la base de datos se creo despues.
dev_console (apps/dev_console, CLI Go) Subproceso: dev_console work dashboard --json invocado via popen() cada 30 s (con cache) Backend de la tab Work (issue 0102): issues, flows y KPIs de DoD La tab Work muestra un placeholder con el comando de build, sin crash. work_tab.cpp::find_dev_console() busca el binario en $FN_REGISTRY_ROOT/apps/dev_console/dev_console, asi que el dashboard debe lanzarse con FN_REGISTRY_ROOT apuntando a la raiz del repo para que la tab cobre vida.

Build

# Linux
cd cpp && cmake -B build/linux -S . && cmake --build build/linux --target registry_dashboard -j$(nproc)

# Windows (cross-compile)
cd cpp && cmake -B build/windows -S . -DCMAKE_TOOLCHAIN_FILE=toolchains/mingw-w64.cmake && cmake --build build/windows --target registry_dashboard -j$(nproc)

Ejecucion

# Via API (default, intenta conectar a localhost:8484)
./registry_dashboard

# API explicita
./registry_dashboard --api http://192.168.1.10:8484

# Con SQLite fallback
./registry_dashboard --api http://127.0.0.1:8484 /path/to/registry.db

# Solo SQLite (sin API)
./registry_dashboard /path/to/registry.db

# Windows (PowerShell)
.\registry_dashboard.ps1

Dependencias vendored

Libreria Version Archivo
cpp-httplib v0.18.3 vendor/httplib.h
nlohmann/json v3.11.3 vendor/nlohmann/json.hpp

Roadmap

  • Filtros interactivos por lenguaje/dominio en sidebar
  • Busqueda FTS5 integrada via API
  • Detalles de funcion al hacer click en tabla
  • Extraer ws_client a cpp/functions/network/ cuando un segundo app C++ necesite WS
  • SHA1 + Sec-WebSocket-Accept verification (hoy se confia en el handshake 101)
  • Migrar nhooyr.io/websocketgithub.com/coder/websocket (mismo paquete, deprecation upstream)

Notas

  • Por defecto intenta conectar a sqlite_api en http://127.0.0.1:8484. Si falla, usa SQLite directo.
  • SQLite compilado estaticamente en Windows via amalgamation vendoreada. En Linux usa libsqlite3 del sistema.
  • cpp-httplib usa sockets nativos (no OpenSSL) — solo HTTP, no HTTPS.

Estado actual

Fase — actions bar + projects tab + Add modal [done 2026-04-25]

Cambios estructurales (requieren sqlite_api v0.2 con endpoints de mutacion):

  • Actions bar en el page header (fn_ui::toolbar): Reindex (Primary) → http_post_reindex via process_runner; + Add (Secondary) → abre modal; Reload (Subtle) → re-fetch via UserData flag; toast_inbox_button con badge.
  • Modal Add (modal_dialog): select para Kind (App/Analysis/Vault), select de proyecto (obligatorio para Vault), text_input Name + Description + campos especificos. process_runner para el POST. Toast de exito/error + reload al completar.
  • Tab Projects (tree_view + tabs): columna izquierda con proyectos + entrada "(orphans)"; columna derecha con detalle nested (Apps/Analysis/Vaults). Click dispara load_project_detail_http.

RegistryData gana projects[], orphan_apps, orphan_analyses, orphan_vaults. Tipos nuevos ProjectRow, VaultRow, ProjectDetail. Layer data_http.cpp gana load_projects_http, load_project_detail_http, http_post_{reindex,add_app,add_analysis,add_vault}.

AnalysisRow gana campo lang para coherencia con la tabla analysis (la query SQL pasa de SELECT id,name,domain,description a SELECT id,name,lang,domain,description).

views_set_api_url(url) invocado desde main.cpp para que las vistas puedan disparar mutaciones.

Bug fixes operativos [done 2026-04-25]

  • Vibracion al redimensionar: fullscreen_window v0.2 (NoScrollbar), altura de charts fija 260 px, kpi_card v1.2 (78 px + scale 1.4 + NoScrollbar). Ver project.md para detalle.
  • HTTP POST timeout 5 ms en Windows: http_client.cpp::request() usaba struct timeval en setsockopt(SO_RCVTIMEO), que Windows interpreta como DWORD ms → 5 ms efectivos. Fix: rama _WIN32 con DWORD timeout_ms = timeout_sec * 1000. wsa_init envuelto en std::call_once.
  • Mensajes de toast vacios: post_json ahora siempre escribe en out_body (extrae output del JSON en exito; sintetiza "connect() failed to host:port (err=N)" con codigo Winsock en error de conexion). Em dash sustituido por ASCII : para evitar render como ? en fuentes sin ese codepoint.
  • Inbox popup en otra pantalla: toast_inbox_button antes usaba posicion calculada con btn_pos.x - 332 que podia caer fuera del WorkRect del viewport principal; con viewports = true ImGui lo movia a otra ventana del OS. Fix: clamp al WorkRect, anclar con ImGuiCond_Appearing (no Always), SetNextWindowViewport(vp->ID).

Toolchain MinGW para Windows [importante]

El cross-compile pasa de thread model win32 a posix (x86_64-w64-mingw32-g++-posix) para que std::mutex/std::thread funcionen — necesario para process_runner y toast. Linker: -static-libgcc -static-libstdc++ -static -lwinpthread. Configurado en cpp/toolchains/mingw-w64.cmake.

Lo siguiente que pega

  • Filtros del Roadmap: el select de proyecto del modal Add ya prueba que filtrar por proyecto es trivial; aplicar mismo patron a las tablas Apps/Analysis/Types.
  • Detalles al click: cuando un row de la tabla Apps (o Functions) se selecciona, abrir un panel lateral con metadata + boton "Open in editor" (segun OS, xdg-open/explorer).
  • Integracion FTS5: el endpoint /api/databases/registry/fts ya existe; falta cablearlo desde la actions bar como text_input con resultados live.

Notas — Settings menubar (sesion 2026-04-25)

  • render() ahora llama fn_ui::app_menubar(nullptr, 0, nullptr) al inicio para exponer el item Settings... en la MainMenuBar. La app no tiene paneles toggleables ni layouts propios, asi que solo aparece Settings.
  • El usuario puede cambiar fuente (DroidSans/Karla/Roboto/Cousine) y tamaño (10..32 px) en runtime, y togglear el FPS overlay. Persistencia en app_settings.ini junto al registry_dashboard.exe.
  • CMakeLists.txt limpiado: fps_overlay.cpp y tokens.cpp ya viven en fn_framework — no listarlos explicitamente o el linker da multiple-definition.
  • 5 TTFs (Karla/Roboto/DroidSans/Cousine/Tabler) copiadas junto al exe via add_imgui_app post-build.

Fase — Monitor tab + WebSocket live stream [done 2026-05-14, issue 0086]

Rebranding "Claude Usage" → Monitor, ahora primera y por defecto en el TabBar. Es el landing del bucke reactivo (construir → ejecutar → recopilar → analizar → mejorar).

Nuevos elementos UI:

  • Toolbar interna del Monitor con preset de ventana temporal (1h / 24h / 7d / 30d / All), boton Refresh manual, LED live/offline con timestamp del ultimo evento WS.
  • 5 KPI cards (era 4): añadido "Errors" derivado de COUNT(*) FROM calls WHERE success = 0 filtrado por la ventana activa.
  • Sub-tab "Recent Executions" (la primera) con columnas: When, Function, Tool, ms, OK, Error. Backed by calls table, sorted by ts DESC, limit 100, filtrada por ventana.
  • Violations sub-tab gana columna "When" con ts formateado.

Pipeline en vivo (low-latency, push-based):

Hook PostToolUse ──► call_monitor CLI ──► INSERT calls  (siempre, sincrono)
                                              │
                                              ▼
                                      ops:call_monitor.db
                                              ▲
                                              │ (ticker 250ms cuando subs>0)
sqlite_api /api/events/call_monitor ──► WS hub ──► subscribers (dashboards)
  • sqlite_api: nuevo endpoint GET /api/events/call_monitor. Hub gestiona subscribers, ticker arranca solo con >=1 sub (cero overhead si no hay dashboards). Cliente recibe snapshot inicial (KPIs + 100 ultimas) y luego deltas (id > watermark). Intervalo adaptativo: 250ms activo → 2s idle (tras 30s sin eventos).
  • registry_dashboard: cliente WS minimal RFC6455 en ws_client.{h,cpp} (no TLS, thread propio, reconnect exponencial 0.5s → 8s). main.cpp consume deltas y los aplica a g_data.claude (incrementa KPIs, anade filas, dedup por id).
  • Fallback: si WS cae, los datos siguen registrandose en SQLite via call_monitor CLI. Al reconectar, el cliente puede mandar {"watermark": N} para reanudar sin perder eventos.

Cambios en data.{h,cpp} y data_http.{h,cpp}:

  • RecentExecutionRow, window_secs, ws_connected, last_event_ts, last_seen_call_id en ClaudeUsageData.
  • load_claude_usage_http(api, out, window_secs) filtra calls y violations por ventana.
  • load_recent_executions_http() standalone para refetch parcial (preparado para WS, no esta cableado todavia — actualmente las deltas WS bastan).

Decisiones de scope:

  • Sec-WebSocket-Accept verification se omite (server controlado, localhost only).
  • TLS fuera (ws://, no wss://).
  • WS client no extraido al registry todavia: hasta que un segundo app C++ lo necesite.

Notas — Settings submenu + Git column (sesion 2026-04-28)

  • fn_ui::app_menubar reemplaza el item plano Settings... por un BeginMenu("Settings") con dos subitems: Settings... (existente) y About... (nuevo modulo app_about_cpp_core). El registry_dashboard cablea la info via fn_ui::about_window_set_info("fn_registry Dashboard", "0.2.0", "Dashboard ImGui...") antes de fn::run_app.
  • Tabla Apps gana columna Git: remote si repo_url esta poblado en apps.repo_url, local si existe <dir_path>/.git/, - si nada. AppRow extendido con repo_url y dir_path; SELECT en data.cpp y data_http.cpp ampliado a 8 columnas.
  • Build OK: cmake --build build --target registry_dashboard (Linux). La columna "Git" se ve sin reindexar.

Capability growth log

Una linea por bump SemVer. Bump-type segun .claude/commands/version.md:

  • major: breaking observable (CLI args, schema BBDD propia, formato wire).

  • minor: feature aditiva (nuevo panel, endpoint, opcion).

  • patch: bugfix sin cambio observable.

  • v0.1.0 (2026-05-18) — baseline.