15 KiB
name, description, tags, repo_url
| name | description | tags | repo_url | |||||
|---|---|---|---|---|---|---|---|---|
| fn_monitoring | Monitoreo y visualizacion del estado del fn_registry. API HTTP read-only sobre las bases de datos SQLite y dashboard ImGui que consume la API. |
|
Apps
| App | Lang | Descripcion |
|---|---|---|
| sqlite_api | Go | API REST HTTP read-only sobre registry.db y todas las operations.db. Puerto 8484. |
| registry_dashboard | C++ / ImGui | Dashboard con KPIs, charts y tablas del registry. Consume sqlite_api (HTTP) con fallback a SQLite directo. |
Cada app.md es la referencia canonica del binario — endpoints completos, flags, dependencias. Este documento cubre como operar el proyecto como un todo: arranque, service, flujo de datos, troubleshooting.
Arquitectura
registry.db (raiz)
apps/*/operations.db
projects/*/apps/*/operations.db
│ (read-only, mode=ro)
▼
┌──────────────────────────────────────────────┐
│ sqlite_api (Go net/http, :8484) │
│ /health │
│ /api/databases │
│ /api/databases/:db/tables │
│ /api/databases/:db/schema │
│ /api/databases/:db/query (POST, SELECT) │
│ /api/databases/:db/fts │
└──────────────────────────────────────────────┘
▲
│ HTTP GET/POST
│ (cpp-httplib + nlohmann/json)
│
┌──────────────────────────────────────────────┐
│ registry_dashboard (C++ / ImGui + ImPlot) │
│ main.cpp → reload_data() │
│ data_http.cpp (primario, HTTP) │
│ data.cpp (fallback, SQLite C API) │
│ views.cpp → KPI row, charts, tables │
└──────────────────────────────────────────────┘
Separacion de responsabilidades:
sqlite_apino conoce el dashboard. Es una API generica: expone cualquier DB SQLite defn_registry/read-only con FTS5.registry_dashboardno conoce la estructura de registry.db directamente, solo a traves del JSON que devuelve la API. El modo SQLite directo es fallback para entornos sin red.
Puerto 8484 — elegido para no colisionar con Metabase (3000), Jupyter (8888) ni deploy_server (9090).
Servicio sqlite_api
Modos de arranque
| Modo | Comando | Cuando usarlo |
|---|---|---|
Dev (foreground, go run) |
cd projects/fn_monitoring/apps/sqlite_api && go run -tags fts5 . |
Iteracion rapida, ver logs en la terminal |
| Dev (background) | ./start.sh (dentro de apps/sqlite_api/) |
Probar el dashboard rapido sin systemd. Escribe PID en sqlite_api.pid y log en sqlite_api.log |
| Production (systemd) | sudo systemctl start sqlite_api |
Arranque en boot, restart on failure, logs en journal |
Variables de entorno
| Var | Valor | Proposito |
|---|---|---|
FN_REGISTRY_ROOT |
ruta absoluta a la raiz del registry | Evita que el binario busque registry.db subiendo por el cwd. Obligatoria bajo systemd. |
Instalar como servicio systemd (local)
Usar el pipeline del registry install_systemd_service_bash_pipelines:
cd /home/lucas/fn_registry
# 1. Build del binario
CGO_ENABLED=1 go build -tags fts5 \
-o projects/fn_monitoring/apps/sqlite_api/sqlite_api \
./projects/fn_monitoring/apps/sqlite_api/
# 2. Instalar unit + enable + start (requiere sudo sin password para systemctl)
source bash/functions/pipelines/install_systemd_service.sh
install_systemd_service \
--name sqlite_api \
--exec "$(pwd)/projects/fn_monitoring/apps/sqlite_api/sqlite_api" \
--workdir "$(pwd)" \
--env "FN_REGISTRY_ROOT=$(pwd)" \
--description "fn_registry SQLite HTTP API" \
--after network.target \
--restart on-failure
Operacion
sudo systemctl status sqlite_api # estado + ultimas lineas del journal
sudo systemctl restart sqlite_api # tras rebuild del binario
sudo systemctl stop sqlite_api # parar
journalctl -u sqlite_api -f # logs en vivo
curl http://127.0.0.1:8484/health # health check
Redeploy tras cambios en el codigo Go
cd /home/lucas/fn_registry
CGO_ENABLED=1 go build -tags fts5 \
-o projects/fn_monitoring/apps/sqlite_api/sqlite_api \
./projects/fn_monitoring/apps/sqlite_api/
sudo systemctl restart sqlite_api
No hace falta reinstalar el unit — solo recompilar y reiniciar.
Dashboard registry_dashboard
Build
cd cpp
cmake -B build/linux -S .
cmake --build build/linux --target registry_dashboard -j$(nproc)
El binario queda en cpp/build/linux/registry_dashboard (o projects/fn_monitoring/apps/registry_dashboard/registry_dashboard.exe en Windows).
Ejecucion
# Modo API (por defecto, intenta localhost:8484)
./registry_dashboard
# API remoto
./registry_dashboard --api http://192.168.1.10:8484
# API + fallback SQLite
./registry_dashboard --api http://127.0.0.1:8484 /home/lucas/fn_registry/registry.db
# Solo SQLite (sin API)
./registry_dashboard /home/lucas/fn_registry/registry.db
La UI muestra en la cabecera de donde vienen los datos (HTTP vs SQLite). F5 recarga.
Flujo de datos
main.cpp::reload_data()intenta HTTP primero viaload_registry_data_http().- Si la API responde
200y el JSON parsea, los datos pueblanRegistryData. - Si falla la API (timeout, 5xx, JSON invalido) y hay
--db, cae aload_registry_data()(SQLite directo). - Si ninguno funciona, la UI muestra un mensaje de error y no hay reintento automatico — hay que pulsar reload.
Vistas
| Seccion | Datos | Query subyacente |
|---|---|---|
| KPI row (8 cards) | totales y porcentajes | SELECT COUNT(*) sobre functions, types, apps, analysis, unit_tests, proposals + agregados tested/pure |
| Charts (bar + pie) | funciones por lang/domain, reparto pure/impure, kind | GROUP BY lang, GROUP BY domain, GROUP BY purity, GROUP BY kind |
| Tablas | ultimas 20 functions, apps, analysis, types | ORDER BY updated_at DESC LIMIT 20 |
Detalle de composicion de componentes viz en apps/registry_dashboard/app.md.
Troubleshooting
| Sintoma | Causa probable | Verificacion / Fix |
|---|---|---|
| Dashboard dice "HTTP API failed, falling back to SQLite" | sqlite_api no esta corriendo |
curl http://127.0.0.1:8484/health — si falla, systemctl status sqlite_api o ./start.sh |
sqlite_api arranca y muere inmediatamente |
No encuentra registry.db |
Exportar FN_REGISTRY_ROOT=/home/lucas/fn_registry o correr desde la raiz del registry |
systemctl start sqlite_api pide password |
Falta sudoers para systemctl | Ver .claude/rules/deploy.md — el usuario necesita NOPASSWD para systemctl, mv a /etc/systemd/system/ |
| Dashboard abre pero todas las cifras son 0 | API conecta pero devuelve DB vacia | curl -X POST http://127.0.0.1:8484/api/databases/registry/query -d '{"sql":"SELECT COUNT(*) FROM functions"}' |
| API responde lento / timeout | Query pesada sobre FTS5 | Timeout hardcoded a 5s en handlers.go. Revisar la query en journal. |
Bind rechazado (address already in use) |
Otro proceso en 8484 |
`ss -tlnp |
Logs
# systemd
journalctl -u sqlite_api -n 100 --no-pager
journalctl -u sqlite_api -f
# start.sh
tail -f projects/fn_monitoring/apps/sqlite_api/sqlite_api.log
Como extender
Anadir un endpoint a sqlite_api
- Registrar la ruta en
Server.Routes()(handlers.go). - Handler lee
r.URL.Path/r.Body, delega enDBPoolpara resolver la DB, ejecuta SQL read-only. - Test en
handlers_test.go(patron: tabla de casos HTTP). - Rebuild +
systemctl restart sqlite_api. - Documentar en
apps/sqlite_api/app.md(tabla de endpoints).
Anadir una vista al dashboard
- Nuevo campo en
RegistryData(data.h) + su equivalente en la respuesta JSON. - Parseo en
data_http.cppy carga SQL endata.cpp(ambos paths, para mantener el fallback). - Renderizado en
views.cppusando componentes del dominioviz(kpi_card,bar_chart, etc.) — ver reglafrontend_theminganaloga para C++: usar primitivos del registry antes que ImGui crudo. - Rebuild con CMake.
Anadir una DB nueva
La descubre automaticamente DiscoverDatabases() escaneando apps/*/operations.db y projects/*/apps/*/operations.db. No hay que registrar nada — al reiniciar sqlite_api aparecen con alias ops:{app_name}.
Deploy en otros PCs
Este proyecto se instala identico en cualquier maquina con el registry clonado:
fn syncpara traer los metadatos del proyecto.- Build + systemd install (seccion "Instalar como servicio systemd" arriba).
- Build del dashboard.
Los datos son los .db locales — cada PC ve su propio estado del registry y sus propias operations.db. No hay sincronizacion remota de datos en este servicio: para eso existe fn sync contra registry_api (proyecto diferente, ver memoria project_registry_api).
Estado actual
Fase — projects view + mutaciones desde el dashboard [done 2026-04-25]
El dashboard pasa de read-only a manipular el registry via la API. Ampliacion en tres patas:
Backend (sqlite_api) — endpoints nuevos en handlers_projects.go y handlers_mutations.go:
| Metodo | Path | Que hace |
|---|---|---|
GET |
/api/projects |
Lista con conteos apps_count / analyses_count / vaults_count por proyecto + bloque orphans (entidades con project_id vacio). |
GET |
/api/projects/{id} |
Detalle: apps[], analyses[], vaults[]. Acepta id="orphans" para devolver las huerfanas. |
POST |
/api/reindex |
Ejecuta fn index desde registryRoot, devuelve {ok, output}. |
POST |
/api/add/app |
Body {name, lang, domain, project, description} → crea apps/{name}/ o projects/{p}/apps/{name}/ con app.md minimo + fn index. |
POST |
/api/add/analysis |
Body {name, project, packages[], description} → invoca fn run init_jupyter_analysis [--project p] name pkg1 pkg2 .... |
POST |
/api/add/vault |
Body {name, project, path, description} → crea dir o symlink en projects/{p}/vaults/ + entry append en vault.yaml. |
Server.registryRoot se inyecta en NewServer(pool, root) (rebajado de findRegistryRoot() en main.go). Helpers runFN() y runShell() ejecutan con cmd.Dir = registryRoot y FN_REGISTRY_ROOT en el env.
Dashboard (registry_dashboard) — actions bar + tab Projects + modal Add:
- Toolbar nueva en el header (
fn_ui::toolbar): botonReindex(Primary) → disparahttp_post_reindexviaprocess_runner; boton+ Add→ abremodal_dialog; botonReload;toast_inbox_buttoncon badge. - Modal Add con
selectpara kind (App / Analysis / Vault),selectde proyecto (obligatorio para Vault, opcional para resto),text_inputName + Description y campos especificos por kind (lang/domain para App, packages CSV para Analysis, abs path para Vault). Submit dispara el endpoint correspondiente viaprocess_runner. Toast al completar + reload automatico. - Tab Projects con dos columnas:
tree_viewizquierda (proyectos + entrada "(orphans)" cuando hay entidades huerfanas), detalle derecha con tabs internas Apps / Analysis / Vaults. Click en un proyecto disparaload_project_detail_http.
Datos en RegistryData: nuevos projects[], orphan_apps, orphan_analyses, orphan_vaults. Tipos nuevos ProjectRow, VaultRow, ProjectDetail. load_registry_data_http llama a load_projects_http al final como best-effort (no fatal si falla).
Bug fix — vibracion al redimensionar [done 2026-04-25]
Dos fuentes de "vibracion" durante drag-resize de la ventana:
fullscreen_window_cpp_corev0.2: anadidoNoScrollbar | NoScrollWithMouse. Sin esto, si el contenido excedia por 1-2px aparecia un scrollbar fugaz que reducia el ancho ~14px y reflowaba todo.views.cpp::draw_dashboard: altura de charts pasa deGetContentRegionAvail().y * 0.35a constante 260 px. La proporcion relativa propagaba el resize a todos los plots.kpi_card_cpp_vizv1.2: altura fija 78 px (antes 108) + scale 1.4x (antes 1.8) + padding sm +NoScrollbar. ElAutoResizeYcon 8 cards generaba lag perceptible al redimensionar.
Bug fix — HTTP POST timeout en thread de background [done 2026-04-25]
http_client.cpp::request() pasaba struct timeval a setsockopt(SO_RCVTIMEO) en Windows, donde MSDN especifica DWORD ms. Resultado: timeout efectivo de 5 ms en lugar de 5 s. Se nota especialmente en POST desde threads (background runners) porque la latencia de scheduling puede pasar de 5 ms. Fix: rama _WIN32 con DWORD timeout_ms. Tambien wsa_init envuelto en std::call_once para evitar race entre main thread + runners. Mensajes de error formateados con ASCII (em dash U+2014 falla render con la fuente default).
Tooling sibling — primitives_gallery [done 2026-04-25]
Nueva app dev en cpp/apps/primitives_gallery/ (no es app del registry, vive en el source tree). Catalogo visual interactivo de los 19 primitivos UI de cpp/functions/{core,viz} con sidebar + panel + snippet por demo. Doble rol: smoke test visual al modificar tokens/componentes y build gate (esta en el CMake principal — si un primitivo rompe API la gallery no compila).
Demo destacada: graph_viewport con sliders de Nodes (100-20 000), Clusters (2-16) y los tres parametros de ForceLayoutConfig (Repulsion / Attraction / Gravity) aplicados en vivo. Util tambien como benchmark de rendimiento del stack graph_renderer + graph_force_layout + graph_spatial_hash.
README.md propio en cpp/apps/primitives_gallery/README.md.
Lo siguiente que pega
- Tests unitarios de logica pura (Phase A del plan de tests): vendoreado de
doctest, ~6 tests paralabel_stride,slice_at,process_runnertransitions,toastqueue,tokenssanity,parse_url. Cierra el ciclo gallery (visual) + ctest (logica). - Para que algunos tests sean posibles hace falta exponer funciones internas de
bar_chart.cppypie_chart.cpp(actualmente en namespace anonimo). loginctl enable-linger lucaspara que elsqlite_api.service(user-level systemd) sobreviva al logout. Requiere sudo una vez. Decision pendiente del usuario.