From 2d35f5e1fbdab982adbb0d2d18705a72e038736c Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Sat, 25 Apr 2026 21:26:12 +0200 Subject: [PATCH] =?UTF-8?q?chore:=20a=C3=B1adir=20slash=20command=20/docum?= =?UTF-8?q?entar=20y=20entrada=20de=20diario=202026-04-25?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/commands/documentar.md | 260 ++++++++++++++++++++++++ docs/diary/2026-04-25.md | 352 +++++++++++++++++++++++++++++++++ 2 files changed, 612 insertions(+) create mode 100644 .claude/commands/documentar.md create mode 100644 docs/diary/2026-04-25.md diff --git a/.claude/commands/documentar.md b/.claude/commands/documentar.md new file mode 100644 index 00000000..f4894e66 --- /dev/null +++ b/.claude/commands/documentar.md @@ -0,0 +1,260 @@ +# /documentar — Distribuir la conversacion en la documentacion del registry + +Documenta la **conversacion actual** repartiendo el contenido en TODOS los `.md` que correspondan: artefactos del registry (funciones, tipos, apps, projects, analysis, vaults) **y documentacion global del repo** (`docs/*`, `docs/adr/`, `CHANGELOG.md`, `dev/issues/*`, `.claude/rules/*`, `.claude/CLAUDE.md`, sub-CLAUDEs, READMEs/SPECs en apps). Cierra con una entrada en `/entrada_diario`. El objetivo es que **otro LLM (o yo en otra sesion) pueda continuar** sin haber visto la conversacion: contexto, decisiones, gotchas, paths, IDs, comandos exactos, "lo siguiente que pega". + +## Uso + +``` +/documentar # documenta todo lo relevante de la sesion +/documentar shaders_lab fase 6 # acota a artefactos/temas concretos (opcional) +``` + +`$ARGUMENTS` es opcional: si va vacio, documenta toda la sesion. Si lleva texto, usalo como hilo conductor para decidir que es relevante. + +--- + +## Reglas duras + +1. **NUNCA** escribir secretos en ningun `.md` ni en el diario: + - Passwords, tokens, API keys, GPG keys, ssh private keys, valores reales de variables de entorno sensibles (`REGISTRY_API_TOKEN`, `*_SECRET`, `*_PASSWORD`, `*_TOKEN`, basicAuth en URLs). + - Si el usuario lo pide explicitamente, OK. Por defecto, redactar como `` / `` o referenciar el origen (`pass entry registry_api`, `~/.fn_pc`). + - URLs publicas, hosts, puertos, paths, IDs, nombres de servicios, env var **names** (no values), licencias, hashes de commit cortos: SI se documentan. +2. **NUNCA** sobreescribir secciones existentes ni reordenar contenido previo. Solo **append** o seccion nueva con timestamp/fase si encaja. +3. **SIEMPRE** consultar `registry.db` con FTS5 para encontrar el `.md` correcto antes de editar (no asumir paths). +4. **SIEMPRE** cerrar invocando `/entrada_diario` con un resumen del bloque (a no ser que el usuario diga lo contrario). +5. **Densidad util > prosa**: comandos exactos, IDs del registry, paths relativos, error messages literales, flags de build, decisiones (con el "porque"), bugs encontrados (con el fix), proximos pasos. Sin fluff. + +--- + +## PASO 0 — Recopilar el material de la sesion + +Antes de escribir nada, repasar la conversacion y juntar: + +1. **Artefactos tocados** (creados, editados, ejecutados, mencionados): + - Funciones / tipos del registry → IDs `{name}_{lang}_{domain}`. + - Apps (`apps/*` o `projects/*/apps/*`). + - Projects (`projects/*`). + - Analyses (`analysis/*` o `projects/*/analysis/*`). + - Vaults (`projects/*/vaults/vault.yaml`). + - Reglas (`.claude/rules/*.md`), ADRs (`docs/adr/*.md`), templates (`docs/templates/*`). + - Issues (`dev/issues/*.md`, `dev/issues/completed/*.md`). + - Docs globales (`docs/*.md`: architecture, integrity, execution_standard, fn_operations, sync_setup, init-pipelines, testing, functions, types, fn-registry-system-complete). + - CLAUDE.md raiz (`.claude/CLAUDE.md`) y sub-CLAUDEs (`apps/*/.claude/CLAUDE.md`, `projects/*/apps/*/.claude/CLAUDE.md`, `analysis/*/.claude/CLAUDE.md`, `projects/*/analysis/*/.claude/CLAUDE.md`). + - Docs sueltas en apps (`apps/*/SPEC.md`, `apps/*/README.md`, `apps/*/docs/*.md`, `cpp/DESIGN_SYSTEM.md`). + - `CHANGELOG.md` raiz. + +2. **Cambios concretos** desde git: + ```bash + cd /home/lucas/fn_registry + git status --short + git diff --stat + git log --since="6 hours ago" --oneline + ``` + Cada path modificado mapea a un artefacto — convertir a su `.md`. + +3. **Material no codigo** que vale la pena dejar registrado: + - Decisiones de diseño y por que (anti-bitrot: el porque suele perderse). + - Bugs encontrados + raiz + fix (no solo "fix"). + - Atajos / convenciones nuevas. + - Pendientes y "lo siguiente que pega" para la proxima sesion. + - Aprendizajes operativos (build flags, cross-compile gotchas, env requerido). + +4. **Filtrar secretos** segun la regla dura #1. + +Si el material es solo conversacion exploratoria sin artefactos tocados, ir directo a PASO 4 (solo diary). + +--- + +## PASO 1 — Mapear cada bloque de informacion a su `.md` + +Para cada artefacto identificado, localizar su `.md` consultando `registry.db`: + +```bash +cd /home/lucas/fn_registry + +# Funcion / tipo +sqlite3 registry.db "SELECT id, file_path FROM functions WHERE id IN (SELECT id FROM functions_fts WHERE functions_fts MATCH 'name:NAME* OR description:NAME*');" +sqlite3 registry.db "SELECT id, file_path FROM types WHERE id IN (SELECT id FROM types_fts WHERE types_fts MATCH 'name:NAME* OR description:NAME*');" + +# App / project / analysis (los .md son nombres fijos) +sqlite3 registry.db "SELECT id, dir_path FROM apps WHERE name = 'NAME';" # → {dir_path}/app.md +sqlite3 registry.db "SELECT id, dir_path FROM projects WHERE name = 'NAME';" # → projects/NAME/project.md +sqlite3 registry.db "SELECT id, dir_path FROM analysis WHERE name = 'NAME';" # → {dir_path}/analysis.md +sqlite3 registry.db "SELECT id, name, path FROM vaults WHERE name = 'NAME';" # → vault.yaml entry +``` + +Si el `.md` aun no existe (artefacto recien creado en la sesion y todavia no indexado), el path se deduce de la convencion: +- Funcion: `functions/{domain}/{name}.md`, `python/functions/{domain}/{name}.md`, `bash/functions/{domain}/{name}.md`, `frontend/functions/{domain}/{name}.md`, `cpp/functions/{domain}/{name}.md`. +- Tipo: `types/{domain}/{name}.md` (codigo en `functions/{domain}/{name}.go`). +- App: `apps/{name}/app.md` o `projects/{proyecto}/apps/{name}/app.md`. +- Project: `projects/{name}/project.md`. +- Analysis: `analysis/{name}/analysis.md` o `projects/{proyecto}/analysis/{name}/analysis.md`. + +### Donde escribir dentro de cada `.md` + +| Tipo de `.md` | Seccion preferida para append | +|-----------------------|----------------------------------------------------------------------------------------------------------------| +| Funcion / tipo | `## Notas` al final. Si no existe, crearla. NO tocar el frontmatter salvo que el usuario pida cambiar metadata. | +| App (`app.md`) | `## Estado actual` con sub-fases si el app ya las usa (ej. `### Fase 7 — ... [done]`). Si no, `## Notas`. Tambien `## Lo siguiente que pega` para futuros pasos. | +| Project (`project.md`)| `## Notas` o seccion del area afectada (`## Apps`, `## Operacion`, `## Troubleshooting`). | +| Analysis (`analysis.md`)| `## Notas` o `## Hallazgos` (crearla si no existe). | +| Vault (`vault.yaml`) | Comentario al final del entry o crear `vaults/{name}/README.md` con notas operativas (NO meter datos sensibles). | +| Regla (`.claude/rules/*`)| Solo si el usuario explicitamente formaliza una regla nueva — entonces archivo nuevo + entrada en `INDEX.md`. | +| ADR (`docs/adr/*`) | Solo si la decision es arquitectural y persistente — archivo nuevo numerado. | + +### Documentacion global / cross-cutting (NO saltarse) + +Estos `.md` describen el sistema entero, no un artefacto concreto. Cuando un cambio impacta convenciones, comportamiento de agentes, decisiones, issues abiertos o features visibles al usuario, **tambien** se actualizan aqui: + +| Archivo / carpeta | Cuando tocarlo | Como | +|---------------------------------------|-----------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------| +| `CHANGELOG.md` (raiz) | Cambio visible al usuario o agentes: nueva funcion/pipeline/app, breaking change, fix relevante, rename, deprecate. | Append bajo seccion del dia (`## YYYY-MM-DD`) con `### Added/Changed/Fixed/Removed/Deprecated`. NUNCA reescribir entradas previas. Si es trabajo en curso, usar `## [Unreleased]`. | +| `docs/adr/NNNN-slug.md` | **Decision arquitectural** persistente con alternativas descartadas (no es regla operativa, es historia del por que). | Archivo nuevo numerado siguiendo plantilla en `docs/adr/README.md`. Estado inicial: `accepted` o `proposed`. | +| `docs/architecture.md` | Cambia la arquitectura general (BDs, layers, flujo de datos, capas). | Append en seccion afectada o nueva subseccion. Mantener tablas y diagramas existentes. | +| `docs/integrity.md` | Nueva regla de integridad / referencia cruzada que el indexer valida. | Append a la lista de reglas. Reflejar tambien en codigo del indexer si toca. | +| `docs/execution_standard.md` | Cambia el estandar de ejecucion (`fn run`, despacho por lenguaje, env vars). | Append seccion. Sincronizar con `.claude/CLAUDE.md` si menciona los mismos comandos. | +| `docs/sync_setup.md` | Cambia el flujo de `fn sync`, env vars (`FN_REGISTRY_API`, `REGISTRY_API_TOKEN`), `~/.fn_pc`, troubleshooting. | Append. Recordatorio: NO escribir el valor del token, solo el nombre. | +| `docs/init-pipelines.md` | Nuevo pipeline de scaffolding o cambio en uno existente. | Append seccion del pipeline. | +| `docs/testing.md` | Cambia convencion de tests, runners, layout de `*_test.go`/`test_*.py`. | Append seccion afectada. | +| `docs/functions.md` / `docs/types.md` | Cambia el schema de la tabla `functions` o `types` (columnas, FTS5, enums, `params_schema`). | Append. Sincronizar con `.claude/CLAUDE.md` schema rapido. | +| `docs/fn_operations.md` | Cambia el schema/comportamiento de `operations.db` o el bucle reactivo (entities, relations, executions, assertions). | Append seccion afectada. | +| `docs/fn-registry-system-complete.md` | Snapshot completo del sistema — solo si la sesion implico un rediseño grande. Normalmente NO se toca por sesion. | Si toca, append seccion con timestamp. | +| `docs/templates/*.md` | Cambia el frontmatter obligatorio de un tipo de artefacto (function/pipeline/component/type/app/project/analysis). | Editar la plantilla correspondiente. Tambien actualizar ejemplos en `.claude/CLAUDE.md`. | +| `dev/issues/NNNN-*.md` | Sesion trabajo en un issue: progreso, blockers, decisiones del scope. | Append `## Notas / Progreso` con timestamp. NO mover de `dev/issues/` a `dev/issues/completed/` salvo que el issue cierre. | +| `dev/issues/completed/NNNN-*.md` | Issue completado en esta sesion. | Mover el archivo a `completed/` (`git mv`) y actualizar la fila en `dev/issues/README.md` (estado `completado`, link a `completed/...`). | +| `dev/issues/README.md` | Issue creado, cambia estado, prioridad, dependencias. | Editar la fila correspondiente o anadir nueva al final de la tabla. | +| `.claude/rules/*.md` + `INDEX.md` | El usuario formaliza una nueva regla operativa. | Archivo nuevo + fila en `INDEX.md`. Numerar en el indice manteniendo orden. | +| `.claude/CLAUDE.md` (raiz) | Cambio en convenciones globales del proyecto, comandos `fn` nuevos, env vars, estructura de carpetas, schema BDs. | Append en seccion afectada. Sincronizar con `docs/` si hay overlap. | +| Sub-CLAUDE (`apps/*/.claude/CLAUDE.md`, `analysis/*/.claude/CLAUDE.md`, `projects/*/apps/*/.claude/CLAUDE.md`) | Cambio especifico en como un agente debe trabajar dentro de esa app/analysis (no global). | Append. NO duplicar reglas que ya estan en CLAUDE.md raiz. | +| `cpp/DESIGN_SYSTEM.md` | Cambia tokens, layout, primitivas visuales del stack C++. | Append seccion afectada. | +| `apps/*/SPEC.md`, `apps/*/README.md`, `apps/*/docs/*.md`, `apps/*/NEXT_STEPS_*.md` | App tiene docs propias mas alla de `app.md`. | Append. Si el contenido encaja mejor en `app.md`, preferir `app.md` y mencionar el SPEC desde ahi. | + +### Reglas de decision rapidas + +- **¿Cambio visible / breaking / nueva feature?** → `CHANGELOG.md` SI. +- **¿Decision con alternativas descartadas?** → ADR SI. Una regla operativa "haz X" sin alternativas → `.claude/rules/`. +- **¿Cambia como un agente debe comportarse?** → `.claude/rules/` o `.claude/CLAUDE.md` (global) o sub-CLAUDE (local). +- **¿Cambia el schema de BDs o columnas?** → `docs/functions.md`/`docs/types.md`/`docs/fn_operations.md` + `.claude/CLAUDE.md` schema rapido. +- **¿Trabajo en un issue?** → `dev/issues/NNNN-*.md` + tabla en `dev/issues/README.md`. +- **¿Cross-cutting sin artefacto y sin encajar arriba?** → solo diario (PASO 4). + +--- + +## PASO 2 — Escribir las actualizaciones + +Para cada `.md` identificado: + +1. `Read` el archivo para ver estructura actual y secciones. +2. Decidir si **append a seccion existente** o **crear seccion nueva**. +3. Usar `Edit` para append (preferible) o `Write` solo si es archivo nuevo. +4. **Mantener el estilo** del archivo (markdown, viñetas cortas, bloques de codigo con lenguaje). +5. **No tocar el frontmatter** salvo que el usuario haya cambiado metadata explicita (`description`, `tags`, `uses_functions`, `version`). Si se toca, re-indexar al final. + +### Plantilla de bloque para append en `.md` de artefacto + +```markdown + +### {Fase / Tema corto} `[done|wip|notes]` + +{1-3 lineas de contexto: que se hizo y por que.} + +- Hecho: {cambio concreto, con path y/o ID si aplica}. +- Hecho: {cambio concreto}. +- Bug + fix: {sintoma → raiz → fix} (si procede). +- Decision: {opcion elegida vs alternativa} — porque {razon} (si procede). +- Pendiente: {algo que queda} (si procede). + +{Comando(s) exacto(s) si la operacion vale la pena reproducir.} +``` + +### Plantilla para `## Lo siguiente que pega` (apps maduras) + +```markdown +- {Tarea proxima}: {contexto minimo, que tocar, criterio de hecho}. +``` + +--- + +## PASO 3 — Reindexar si tocaste frontmatter o creaste artefacto + +Si los cambios de la sesion incluyen creacion de funciones/tipos/apps/projects/analysis/vaults o modificacion de frontmatter: + +```bash +cd /home/lucas/fn_registry && ./fn index +``` + +Y verificar: + +```bash +./fn show {id_creado_o_modificado} +``` + +Si solo se editaron secciones de prosa (Notas, Estado actual, etc.) sin tocar frontmatter, el indexado igual recoge `documentation`/`notes` actualizados — re-indexar es barato y deja la BD coherente. + +--- + +## PASO 4 — Cerrar con entrada al diario + +Invocar `/entrada_diario` con un resumen conciso de la sesion (3-6 viñetas, verbos en pasado para lo hecho, infinitivo para pendientes). Referenciar: + +- IDs de artefactos tocados. +- Paths relativos clave. +- Hashes de commit cortos si la sesion termino con commits. +- ADRs / issues / proposals abiertos. + +Ejemplo de invocacion: + +``` +/entrada_diario shaders_lab fase 6 — menubar reusable (View + Layouts) cableado, persistencia de layouts en shaders_lab.db +``` + +Si el usuario ya invoco `/entrada_diario` antes en esta sesion para este bloque, **no duplicar**: solo añadir lo que no estaba. + +--- + +## PASO 5 — Reportar al usuario + +Resumen breve (formato texto, no tabla a no ser que sean muchos): + +``` +=== DOCUMENTADO === + +Artefactos (.md de registry): + - apps/shaders_lab/app.md (Fase 6 — menubar) + - cpp/functions/core/app_menubar.md (notas de uso) + - cpp/functions/core/layouts_menu.md (notas de cableado) + +Globales: + - CHANGELOG.md (Added: app_menubar, layouts_menu) + - docs/adr/0002-menubar-arch.md (nuevo ADR — decision menubar reusable) + - dev/issues/README.md (issue 0027 → completado) + - dev/issues/completed/0027-...md (movido) + - .claude/rules/cpp_icons.md (regla nueva, anadida a INDEX.md) + +Diario: docs/diary/2026-04-25.md (## 18:30 — ...) + +Re-indexado: si | no +Pendientes registrados: {N} +Secretos omitidos: {lista de tipos redactados, ej. "REGISTRY_API_TOKEN"} +``` + +--- + +## Checklist final + +- [ ] Cada artefacto tocado tiene su `.md` actualizado (append, no overwrite). +- [ ] Ningun secreto, password, token o key en los archivos. +- [ ] Comandos exactos, IDs y paths para que otro LLM reproduzca. +- [ ] Decisiones con su "porque", bugs con su raiz+fix. +- [ ] `CHANGELOG.md` actualizado si el cambio es visible al usuario / agentes. +- [ ] ADR creado (`docs/adr/NNNN-*.md`) si hay decision arquitectural con alternativas descartadas. +- [ ] `dev/issues/*.md` y `dev/issues/README.md` actualizados si la sesion toco issues. +- [ ] `docs/{architecture,integrity,functions,types,fn_operations,execution_standard,sync_setup,init-pipelines,testing}.md` actualizado si el cambio afecta lo que cada uno documenta. +- [ ] `.claude/CLAUDE.md` raiz actualizado si cambian convenciones / comandos / schema globales. +- [ ] `.claude/rules/*` + `INDEX.md` actualizado si el usuario formaliza una regla nueva. +- [ ] Sub-CLAUDE de la app/analysis afectada actualizado si cambia comportamiento agente local. +- [ ] `/entrada_diario` invocado con resumen de la sesion. +- [ ] `./fn index` corrido si hubo creacion o cambio de frontmatter. +- [ ] Reporte final al usuario con la lista de archivos tocados (artefactos + globales). + +$ARGUMENTS diff --git a/docs/diary/2026-04-25.md b/docs/diary/2026-04-25.md new file mode 100644 index 00000000..ea0de405 --- /dev/null +++ b/docs/diary/2026-04-25.md @@ -0,0 +1,352 @@ +# 2026-04-25 + +## 15:32 — shaders_lab fase 7 (UX node editor + correcciones DAG) + +Pulido de la edición visual del DAG y corrección de fugas en el render. Coexiste con la Fase 6 (menubar View + Layouts) que añadió otro agente en paralelo. + +### Hecho — UX nodos + +- Hecho: nodos más grandes para conectar más rápido. `PIN_RADIUS` 9 → 14, `CABLE_THICK` 2.5 → 3.5, `CONTROL_WIDTH` 150 → 220, `COL_GAP` 8 → 14, `NodePadding` vertical 8 → 12, espaciado inicial entre nodos 220 → 320. +- Hecho: bug fix `solid` "sin nombre ni parámetro". El control `Color` se renderizaba con `ImGuiColorEditFlags_NoLabel`. Ahora `TextUnformatted(label) + SameLine` antes del swatch (aplica a todos los Color, no solo a `solid`). + +### Hecho — Drop comportamiento (paleta + nodos del canvas) + +- Hecho: drop sobre nodo del **mismo `DagKind`** (no Output) → replace. Conserva `id`, `editor_uid`, posición, `source_ids[]`, `preview_open`. Limpia slots de input que sobran. +- Hecho: drop sobre cable → splice. `new.source_ids[0] = src.id`, `dst.source_ids[slot] = new.id`. Hit-test = distancia punto-segmento entre cursor y línea (`src.right_mid → dst.left_at_slot_k`). Threshold 18 px canvas-space. +- Hecho: arrastrar **nodo Op/Blend ya colocado** sobre cable también splica. Tracking via `s_drag_existing_uid` (set en `IsMouseClicked(0)` con node hovered y sin pin hovered). Al soltar, refs hacia el nodo movido se limpian antes del rewire (queda exclusivamente en la nueva posición). +- Hecho: prioridad cable-hit > node-hit > add-vacío. + +### Hecho — Splice highlight (preview visual) + +- Hecho: cable candidato se pinta `SPLICE_COLOR (1.00, 0.82, 0.18, 1)` + `CABLE_THICK + 2` en `ed::Link()`. +- Hecho: además se redibuja como bezier dorado en `ImGui::GetForegroundDrawList()` (canvas → screen via `ed::CanvasToScreen`) para no depender del compositing interno de imgui-node-editor. +- Hecho: detección sin gates. La versión inicial gateaba con `IsMouseDown` + `window_hovered` y silenciaba el highlight. Basta payload `DAG_NODE_TYPE` (paleta) o `s_drag_existing_uid` (nodo del canvas). + +### Hecho — Correctness DAG + +- Hecho: **strict output** en `compile_dag_to_glsl`. Eliminado el fallback `last_valid_out` que filtraba el output del último nodo cuando `Output` no tenía source o no existía. Ahora regla: solo se emite lo conectado al `Output`; en cualquier otro caso `seed()` (gris oscuro). El `resolve()` interno de inputs también devuelve `vec4(0,0,0,1)` para slots vacíos (antes caía a `last_valid_out`). +- Hecho: `dag_uniforms_apply` resetea `u_preview_target = -1` al final, para que la rama de preview quede desactivada en el render principal del Canvas DAG. +- Hecho: nuevo `compile_dag_to_glsl_baked(pipeline)` en `dag_compile.{h,cpp}`. Sustituye `uniform vec4 u_params[64]` por `const vec4 u_params[N] = vec4[N](...)` con valores actuales empaquetados, y `uniform int u_preview_target` por `const int u_preview_target = -1`. El panel `Generated GLSL` muestra esta variante: pegarla en el editor `Code` reproduce el render del DAG en el momento del copy, sin depender de uniforms externos. Edits posteriores al DAG no afectan al Code. +- Hecho: `Canvas Code` ya NO recibe `dag_uniforms_apply` (versión anterior lo acoplaba). Es totalmente independiente del DAG. + +### Hecho — Tests + builds + +- Hecho: `dag_compile` 6/6 → **8/8** (test 4b strict output sin Output, test 7 baked variant). +- Hecho: `dag_catalog` 8/8 (19 nodos), `code_to_generator` 7/7, `uniform_parser` 6/6, `shaderlab_db` 7/7. Total **35 asserts** en gfx tras la fase. +- Hecho: build linux + windows OK. `./fn index` pasa a 899 funciones. +- Hecho: sync de `shaders_lab.exe` a `apps/shaders_lab/` (in-repo) y a `/mnt/c/Users/lucas/Desktop/`. MD5 final `33fa56c60584adc074679d39f307e19e`. + +### Hecho — Operativo + +- Hecho: regla nueva en memoria persistente — `feedback_no_adminlocal.md`. **Nunca** copiar binarios Windows a `/mnt/c/Users/AdminLocal/`. Solo `/mnt/c/Users/lucas/Desktop/`. Borrado el `shaders_lab.exe` que quedaba allí. +- Hecho: `cpp/CMakeLists.txt` centraliza `sqlite3_vendored` (top-level) para que `shaders_lab` y `registry_dashboard` lo compartan sin colisión de target. Ambos CMakeLists internos usan `find_package(SQLite3 QUIET)` + `if (NOT SQLite3_FOUND AND NOT TARGET sqlite3_vendored)`. + +### Pendiente + +- Pendiente: panel `View` con listado / borrado de generators custom desde la UI (hoy solo via DB directa). +- Pendiente: botón `Push to registry` que extrae un generator custom a `cpp/functions/gfx/.{cpp,md}` con tag `shaders_lab` y dispara `fn index`. +- Pendiente: persistencia de pipelines con nombre. +- Pendiente: `Save as Op` (1 input `a`) y `Save as Blend` (2 inputs). + +### Referencias + +- App: `apps/shaders_lab/app.md` — Fase 7 documentada en `## Estado actual`. +- Funciones tocadas: `dag_node_editor_cpp_gfx`, `dag_compile_cpp_gfx`, `dag_uniforms_cpp_gfx`, `dag_catalog_cpp_gfx`. Notas appended en cada `.md`. +- Funciones nuevas (Fase 5, ya documentadas): `code_to_generator_cpp_gfx`, `shaderlab_db_cpp_gfx`. +- Memoria: `feedback_no_adminlocal.md`. + +## 15:33 — Projects view + mutaciones desde el dashboard, gallery de primitivos + +Sesion larga repartida en tres fases (plan acordado al principio): primitivos UI nuevos en `cpp/functions/core/`, endpoints de mutacion en `sqlite_api`, e integracion en el dashboard. Cierra con la primera capa del plan de tests (gallery interactiva). + +### Hecho — Fase A (9 primitivos UI nuevos) + +Todos con `.cpp + .h + .md`, compilando Linux + MinGW posix: + +- `button_cpp_core`, `icon_button_cpp_core`, `toolbar_cpp_core` — interaccion basica con tokens. +- `modal_dialog_cpp_core`, `text_input_cpp_core`, `select_cpp_core` — formularios. +- `toast_cpp_core` v1.1 — push thread-safe + render por frame + `toast_inbox_button` con badge no-leidos + popover con historial 50 entradas. +- `process_runner_cpp_core` — `std::thread` + `std::atomic state` + widget `runner_status` con spinner. +- `tree_view_cpp_core` — low-level (`tree_leaf` / `tree_branch_begin/end` / `tree_node_clicked`); el caller gestiona la seleccion. + +**Toolchain MinGW**: switch de `win32` a `posix` (`x86_64-w64-mingw32-g++-posix`) para que `std::mutex/std::thread` compilen. Linker: `-static-libgcc -static-libstdc++ -static -lwinpthread`. Sin esto, toast/process_runner no compilan en Windows. Configurado en `cpp/toolchains/mingw-w64.cmake`. + +### Hecho — Fase B (sqlite_api v0.2) + +Split de handlers en 3 ficheros: `handlers.go` (read-only previo), `handlers_projects.go` (nuevo), `handlers_mutations.go` (nuevo). + +- `GET /api/projects` — proyectos con conteos `apps_count/analyses_count/vaults_count` (subqueries) + bloque `orphans`. +- `GET /api/projects/{id}` — detalle apps/analyses/vaults; `id="orphans"` para huerfanas. Helper `scanAll(ctx, db, query, arg)`. +- `POST /api/reindex` — `exec.CommandContext` de `{registryRoot}/fn index` con timeout 60 s. +- `POST /api/add/app` — body `{name, lang, domain, project, description}` → crea dir + `app.md` minimo + reindex. +- `POST /api/add/analysis` — invoca pipeline `init_jupyter_analysis` via `fn run`. +- `POST /api/add/vault` — solo dentro de proyecto. Crea dir/symlink en `projects/{p}/vaults/` + entry append en `vault.yaml`. + +`Server` gana campo `registryRoot string`. `NewServer(pool, root)`. Tests adaptados con `sed -i 's/NewServer(pool)/NewServer(pool, "")/g'`. Reiniciado: `systemctl --user restart sqlite_api`. Smoke OK. + +### Hecho — Fase C (dashboard integration) + +- **Actions bar** en page header (`fn_ui::toolbar`): `Reindex` (Primary) → `process_runner` con `http_post_reindex`; `+ Add` → modal; `Reload`; `toast_inbox_button("##inbox")`. +- **Modal Add** con kind selector (App/Analysis/Vault), `select` de proyecto, `text_input` Name + Description, campos especificos por kind. Submit dispara endpoint con `process_runner` + toast + reload. +- **Tab Projects** (`tree_view` izquierda + tabs derecha): proyectos + entrada "(orphans)"; click → `load_project_detail_http`. + +`RegistryData` gana `projects[]`, `orphan_apps`, `orphan_analyses`, `orphan_vaults`. Tipos nuevos `ProjectRow`, `VaultRow`, `ProjectDetail`. `data_http.cpp` gana `load_projects_http`, `load_project_detail_http`, `http_post_{reindex,add_app,add_analysis,add_vault}`. `AnalysisRow` gana `lang` (query SQL pasa de 4 cols a 5). `views_set_api_url(url)` invocado desde main. + +### Bug fix — vibracion al redimensionar + +Tres causas combinadas: + +- `fullscreen_window` v0.2: `NoScrollbar | NoScrollWithMouse` para evitar scrollbar fugaz cuando el contenido excede la ventana por 1-2 px (reflow del ancho ~14 px). +- `views.cpp::draw_dashboard`: altura de charts pasa de `GetContentRegionAvail().y * 0.35` a constante 260 px. La proporcion relativa propagaba el resize a todos los plots. +- `kpi_card` v1.2: 78 px fijo + scale 1.4 + padding sm + `NoScrollbar`. Antes `AutoResizeY` × 8 cards × cada frame era el lag. + +### Bug fix — Reindex POST con timeout 5 ms en Windows + +`http_client.cpp::request()` pasaba `struct timeval` (8 bytes en x86_64) a `setsockopt(SO_RCVTIMEO)` en Windows, que MSDN especifica como `DWORD` ms. Resultado: 5 ms efectivos en lugar de 5 s. Critico en POST desde threads de background. Fix: rama `_WIN32` con `DWORD timeout_ms = timeout_sec * 1000`. Tambien `wsa_init` envuelto en `std::call_once` para evitar race entre main thread + runners. + +### Bug fix — toast vacio + popup en otra pantalla + +- `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 real en error de conexion. Em dash `—` (U+2014) sustituido por `:` ASCII (la fuente default no tenia el codepoint y rendia como `?`). +- `toast_inbox_button` antes usaba `btn_pos.x - 332` que podia caer fuera del `WorkRect`; con `viewports = true` ImGui lo enviaba a otra ventana del OS. Fix: clamp al `WorkRect`, `ImGuiCond_Appearing` (no `Always`), `SetNextWindowViewport(vp->ID)`. + +### Hecho — Gallery + plan de tests + +Implementada Capa 1 del plan de tests (Gallery + doctest + TestEngine + snapshot PNG): + +- **`cpp/apps/primitives_gallery/`** — app dev con sidebar de 19 primitivos + panel con demo + snippet por cada uno. Linkea todos los `core/*.cpp` y `viz/*.cpp` relevantes; al estar en `cpp/CMakeLists.txt` actua como build gate. 3 ficheros de demos: `demos_core.cpp` (13 primitivos), `demos_viz.cpp` (6 charts), `demos_graph.cpp` (graph_viewport, fichero aparte). +- **Demo `graph_viewport`** con sliders `Nodes` (100–20 000), `Clusters` (2–16), `Repulsion` (100–20 000), `Attraction` (0.001–0.5), `Gravity` (0.0–0.05), aplicados en vivo a `ForceLayoutConfig`. Stats en una sola linea fija (`hover` y `sel` siempre presentes con `-`, sin filas condicionales que vibren). +- **`README.md`** propio en `cpp/apps/primitives_gallery/` (primer .md en `cpp/apps/*/`; `chart_demo` y `shaders_lab` no tienen). +- `gl_loader_cpp_gfx` v1.1: ampliado con 11 funciones (`glBufferData`, `glDrawArraysInstanced`, `glEnableVertexAttribArray`, `glVertexAttribDivisor`, `glVertexAttribPointer`, `glBindRenderbuffer`, `glDeleteRenderbuffers`, `glFramebufferRenderbuffer`, `glGenRenderbuffers`, `glRenderbufferStorage`, `glFramebufferTexture`) — necesarias para que `graph_renderer` compile en cross-compile MinGW. +- `graph_renderer_cpp_viz` v1.1: cambia raw `` por `gfx/gl_loader.h`. Sin cambios funcionales (Linux bit-equivalente). Cualquier app que use `graph_renderer` debe linkear `gl_loader.cpp` y llamar `fn::gfx::gl_loader_init()` una vez tras crear el contexto GL. + +### Investigacion paralela + +Pregunta del usuario: motor de grafos eficiente en C++ con miles de circulos compatible con ImGui. Recomendacion: hasta 50 k nodos el stack del registry (`graph_renderer` instanced + `graph_force_layout` Barnes-Hut + `graph_spatial_hash` + `graph_viewport`) es la opcion correcta. `imgui-node-editor` (vendoreado) NO es para visualizacion masiva sino para edicion de DAGs (caso del shaderlab); ImPlot scatter es alternativa rapida si no necesitas aristas; OGDF si Barnes-Hut se queda corto. La gallery sirve como benchmark rapido para validar rendimiento real. + +### Pendiente + +- Vendora `doctest` (single-header, MIT) + 6 tests de logica + `ctest` (Capa 2 del plan): `label_stride` (bar_chart), `slice_at` (pie_chart), `process_runner` transitions, `toast` queue, `tokens` sanity, `parse_url` (http_client). +- Exponer `label_stride` y `slice_at` fuera de `namespace { ... }` para que sean testables. +- `loginctl enable-linger lucas` para que `sqlite_api.service` (user systemd) sobreviva al logout (decision pendiente). +- Filtros interactivos en sidebar (filtrar tablas Apps/Functions/Types por proyecto). +- Permisos/auth en mutaciones de `sqlite_api` si se considera deploy a VPS. + +### Referencias + +- `cpp/functions/gfx/gl_loader.md` v1.1 (tabla de cobertura). +- `cpp/functions/viz/graph_renderer.md` v1.1. +- `cpp/functions/core/toast.md` v1.1. +- `projects/fn_monitoring/project.md` — seccion Estado actual con Fase projects view, bug fixes, gallery sibling. +- `projects/fn_monitoring/apps/sqlite_api/app.md` — endpoints `[v0.2]` + Estado actual. +- `projects/fn_monitoring/apps/registry_dashboard/app.md` — Fase actions bar + bug fixes + toolchain MinGW. +- `cpp/apps/primitives_gallery/README.md` — nuevo. +- Commits en sesiones previas (mismo dia): `3f622561` (cpp/viz static-plot + tooltips), `b828fd6a` (kpi v1.2 + bar v1.1), `d6bdab8` en `dataforge/registry_dashboard`. Cambios de esta sesion en working tree, sin commit todavia. +- Reindex final: 899 funciones, 153 types, 13 apps, 2 analysis, 3 projects, 1 vaults, 1293 unit_tests. + +## 15:51 — cpp icons via Tabler (TI_* macros, atlas auto-cargado) + +Glyphs en apps C++ no renderizaban (cuadritos vacios) porque ImGui usa ProggyClean default sin codepoints simbolicos. Integrado set Tabler v3.41.1 (espejo del frontend `@tabler/icons-react`). + +- Hecho: vendoreado `cpp/vendor/tabler-icons/tabler-icons.ttf` (2.7 MB, MIT) + LICENSE + README + `gen_header.py` para regenerar. +- Hecho: generado `cpp/functions/core/icons_tabler.h` con 5093 macros `TI_*` (TI_PLUS, TI_TRASH, TI_REFRESH, TI_DEVICE_FLOPPY, TI_SETTINGS, ...) en formato `#define TI_NAME "\xee\xac\x8b"`. +- Hecho: nueva funcion del registry `icon_font_cpp_core` (impure, error_go_core) con `fn_ui::load_default_fonts(text_px=15, icon_px=14)` — carga texto default + mergea Tabler en el mismo `ImFont` con `MergeMode + GlyphMinAdvanceX = icon_px + GlyphOffset.y = 1` (range U+E000..U+FCFF). +- Hecho: hook en `cpp/framework/app_base.cpp` — llama `fn_ui::load_default_fonts()` justo despues de `ImGui::CreateContext()`. Cualquier app que use `fn::run_app` obtiene los iconos sin tocar nada. +- Hecho: `cpp/CMakeLists.txt` — capturado `FN_CPP_ROOT_DIR` a nivel root, define `FN_CPP_ROOT` en `fn_framework`, y `add_imgui_app` añade post-build copy de la TTF junto al exe (no depende de FN_CPP_ROOT en runtime, portable). +- Hecho: path resolver en runtime busca la TTF en orden: `./tabler-icons.ttf` → `./assets/` → `$FN_ASSETS_DIR` → `${FN_CPP_ROOT}/vendor/tabler-icons/`. Fallback a stderr + solo texto si no la encuentra. +- Hecho: `demos_core.cpp` (gallery) — `demo_icon_button` y `demo_toolbar` migrados de hex UTF-8 a `TI_*` (12 iconos en la fila: TI_REFRESH, TI_PLUS, TI_TRASH, TI_CHEVRON_DOWN, TI_SETTINGS, TI_CHECK, TI_X, TI_PENCIL, TI_DEVICE_FLOPPY, TI_SEARCH, TI_HELP, TI_HOME). Botones text+icon: `button(TI_PLUS " New", V::Primary)`. +- Hecho: regla en `cpp/DESIGN_SYSTEM.md` seccion 11 — uso obligatorio de `TI_*`, anti-patrones (hex UTF-8, emojis, otras icon fonts), upgrade procedure, checklist. +- Hecho: notas en `cpp/functions/core/icon_button.md` (la tabla hex original queda como historica) y `cpp/apps/primitives_gallery/README.md` (`## Iconos en los demos`). +- Hecho: memoria persistente `feedback_cpp_icons.md` para futuras sesiones. + +Bug + fix: +- `add_imgui_app` resolvia `${CMAKE_CURRENT_SOURCE_DIR}/vendor/tabler-icons/...` desde el dir del caller (no del root). → Capturar `FN_CPP_ROOT_DIR` con `set(... CACHE INTERNAL)` a nivel root y usarlo dentro de la funcion. +- Indexer rechazo `icon_font` como impuro sin error_type → añadido `error_type: error_go_core` (convencion cpp del registry). + +Build verificado: +```bash +cd cpp/build/linux && cmake --build . --target primitives_gallery +# 100% Built target primitives_gallery +ls apps/primitives_gallery/tabler-icons.ttf # copiado post-build +``` + +Pendiente: +- Recompilar Windows cross (`cpp/build/windows/`) para apps que se distribuyan a /mnt/c/Users/lucas/Desktop — el `add_imgui_app` ya copia la TTF, basta `cmake --build cpp/build/windows --target `. +- Auditar el resto de apps (`cpp/apps/shaders_lab/main.cpp`, `dataforge/*`) por hex UTF-8 inline o emojis y migrar a `TI_*`. +- Si el atlas completo (5093 glyphs a 14 px) resulta pesado en VRAM, recortar `tabler_ranges[]` en `icon_font.cpp` a los rangos efectivamente usados (U+EA5E..U+EC00 cubre la mayoria comun). + +Reindex: 900 funciones (+1 icon_font_cpp_core), 153 types, 13 apps. Working tree con cambios sin commit. + +## 16:05 — Cross-build Windows + sync a Desktop/apps + +Recompilados los 3 .exe afectados por el cambio de fuentes en `app_base.cpp` y desplegados al escritorio Windows del usuario (donde ejecuta las apps nativas, ya que en WSL no hay GUI). + +- Hecho: `cmake --build cpp/build/windows --target primitives_gallery registry_dashboard shaders_lab -j$(nproc)` — los 3 binarios MinGW listos en `cpp/build/windows/apps//`. +- Hecho: `add_imgui_app` ya copia `tabler-icons.ttf` junto al exe post-build (verificado, 2.7 MB en cada dir). +- Hecho: sync a `/mnt/c/Users/lucas/Desktop/apps//` para los tres apps. Estado final por dir: + - `primitives_gallery/`: `primitives_gallery.exe` (15.2 MB) + `tabler-icons.ttf` + - `registry_dashboard/`: `registry_dashboard.exe` (20.6 MB) + `tabler-icons.ttf` + `imgui.ini` (preservado) + - `shaders_lab/`: `shaders_lab.exe` (23.0 MB) + `tabler-icons.ttf` + `imgui.ini` + `shaders_lab.db` (preservados) +- Hecho: actualizada memoria persistente `feedback_no_adminlocal.md` con la convencion **WSL → Desktop/apps**: el destino canonico es `/mnt/c/Users/lucas/Desktop/apps//` (no la raiz del Desktop), y SIEMPRE hay que copiar exe + assets adyacentes (TTF). Sin la TTF los `TI_*` salen como cuadritos. + +Convencion documentada (memoria + diario): +```bash +APP=shaders_lab +cmake --build cpp/build/windows --target $APP -j$(nproc) +cp cpp/build/windows/apps/$APP/{$APP.exe,tabler-icons.ttf} /mnt/c/Users/lucas/Desktop/apps/$APP/ +``` + +Pendiente: +- Probar cada app en Windows y confirmar que los iconos `TI_*` rinden correctamente (usuario). +- Si algun app C++ futuro mete assets adicionales al lado del exe (texturas, shaders, .db seed), hay que añadirlos al cp tambien — el patron post-build de `add_imgui_app` solo cubre la TTF de Tabler. + +## 16:25 — Fix regresion de tamaño + tipografia vectorial + +El cambio de las 15:51 metio una regresion: `load_default_fonts(text_px=15, icon_px=14)` cargaba ProggyClean default a 15 px. ProggyClean es bitmap (13 px nativo), asi que en todas las apps el texto salia mas grande Y borroso/escalado. Ademas firma con dos parametros de tamaño distintos rompia line-height al mezclar texto+icono. + +- Hecho: `icon_font.h` — firma simplificada a `void load_default_fonts(float size_px = 13.0f)`. Un solo tamaño compartido por texto e iconos = line-height uniforme. +- Hecho: `icon_font.cpp` reescrita — carga **Karla-Regular** (vectorial, 17 KB, vendoreado por ImGui en `vendor/imgui/misc/fonts/`) en lugar de ProggyClean. OversampleH=2 para nitidez. Mergea Tabler al mismo tamaño. Si Karla no se encuentra, fallback a `AddFontDefault()` (ProggyClean) para no romper la app. +- Hecho: helper `find_asset(filename, repo_subpath)` factorizado — mismo path resolver para los dos TTFs (./, ./assets/, $FN_ASSETS_DIR, ${FN_CPP_ROOT}/). +- Hecho: nueva API `fn_ui::text_font_loaded()` ademas de `tabler_font_loaded()` para diagnostico. +- Hecho: `cpp/CMakeLists.txt` `add_imgui_app` — el post-build copy ahora copia AMBAS TTFs (Karla y Tabler) junto al exe. +- Hecho: actualizadas `cpp/functions/core/icon_font.md`, `cpp/DESIGN_SYSTEM.md` seccion 11 (path resolution), y `feedback_no_adminlocal.md` (lista completa de assets a sincronizar). +- Hecho: recompilados los 3 binarios Linux + Windows. Sincronizados a `/mnt/c/Users/lucas/Desktop/apps//` con `Karla-Regular.ttf` + `tabler-icons.ttf` al lado. + +Estado final binarios Windows en Desktop/apps: +- `primitives_gallery/`: exe (15.2 MB) + Karla (17 KB) + Tabler (2.7 MB) +- `registry_dashboard/`: exe (20.6 MB) + Karla + Tabler + imgui.ini preservado +- `shaders_lab/`: exe (23.0 MB) + Karla + Tabler + imgui.ini + shaders_lab.db preservados + +Pendiente: +- Probar en Windows: texto debe verse igual o mejor que antes (Karla 13 px vectorial vs ProggyClean 13 px bitmap), iconos `TI_*` renderizan. +- Si Karla no encaja (estilo poco "Geist"-like), evaluar bajar Geist Sans desde `vercel/geist-font` y vendoreara en `cpp/vendor/fonts/`. Karla es la opcion KISS (cero descarga) pero no es exactamente el espejo del frontend. + +## 17:30 — Settings window con FPS toggle + font picker (todas las apps) + +Texto a 13 px se sentia pequeño, y queriamos que el usuario pudiera elegir fuente/tamaño y togglear el FPS overlay sin recompilar. Implementado un sistema de settings reutilizable por todas las apps C++ del registry. + +- Hecho: nueva funcion `app_settings_cpp_core` (impure, error_go_core) — estado global `AppSettings { show_fps, font_id, font_size_px }`, persistencia en `/app_settings.ini`, ventana flotante con `CollapsingHeader` para Display + Typography + secciones extra registrables, auto-save al cambiar. +- Hecho: API publica: + - `settings()` → ref mutable + - `settings_load() / settings_save()` → INI I/O + - `settings_window_set_open(bool) / toggle()` + - `settings_window_menu_item("Settings...")` → MenuItem componible + - `settings_window_render()` → render no-op si cerrada + - `settings_window_add_section(id, title, callback)` → extender desde apps + - `settings_mark_font_dirty() / consume_font_dirty()` → coordinacion con icon_font +- Hecho: `icon_font` reescrita — `load_fonts_from_settings()` lee `font_id` del settings y carga la TTF correspondiente (Karla / Roboto / DroidSans / Cousine / ProggyClean). Default global `font_size_px = 15` (antes 13, se sentia pequeño). +- Hecho: `app_base.cpp` orquesta: + 1. `settings_load()` antes de cargar fuentes + 2. `load_fonts_from_settings()` aplica el font del .ini + 3. Cada frame: si `consume_font_dirty()`, `io.Fonts->Clear()` + reload (ImGui 1.92+ refresca GPU texture solo via `UpdateTexture`) + 4. Despues de `render_fn()`: `settings_window_render()` (no-op si cerrada) + 5. Si `settings().show_fps`: `fps_overlay()` + 6. Al exit: `settings_save()` +- Hecho: `app_menubar` añade siempre el MenuItem "Settings..." como tercer item (junto a View / Layouts). +- Hecho: `fn_framework` (libreria static) ahora incluye `tokens.cpp + icon_font.cpp + app_settings.cpp + fps_overlay.cpp + panel_menu.cpp + layouts_menu.cpp + app_menubar.cpp`. Cualquier app que use `add_imgui_app` los enlaza automaticamente. Removidos de los CMakeLists individuales para evitar multiple-definition (shaders_lab, registry_dashboard, gallery, chart_demo). +- Hecho: gallery + dashboard ahora llaman `fn_ui::app_menubar(nullptr, 0, nullptr)` para exponer Settings (no tienen paneles ni layouts propios). +- Hecho: shaders_lab — removida llamada explicita a `fps_overlay()` en panel Controls. Ahora siempre se respeta el toggle de Settings. +- Hecho: `add_imgui_app` post-build copia las 4 TTFs vectoriales (Karla 17 KB, Roboto 163 KB, DroidSans 190 KB, Cousine 44 KB) + Tabler (2.7 MB) junto a cada exe. +- Hecho: `cpp/DESIGN_SYSTEM.md` seccion 12 nueva — Settings (UI, persistencia, extension, anti-patrones). +- Hecho: `app_settings.md` con docs completas en el registry. + +Bug + fix: +- Build inicial fallo: `ImGui_ImplOpenGL3_DestroyFontsTexture/CreateFontsTexture` no existen en ImGui 1.92+ (renombrados/removidos). Fix: dejar que la atlas se recree y el backend la actualice solo via `UpdateTexture` en `NewFrame()`. Mas simple ademas. + +Pendiente: +- Cerrar `primitives_gallery.exe` en Windows: el .exe esta locked y no se sincronizo (TTFs si). Reintentar `cp` cuando la app este cerrada. +- Probar en Windows que el menu Settings... abre la ventana, que cambiar fuente/tamaño rebuildea atlas en el siguiente frame, que toggle FPS funciona, que `app_settings.ini` se crea junto al exe con los valores correctos. +- Si una app quiere settings propios (shaders_lab podria querer "auto-compile on save"), ejemplo de uso en `app_settings.md`. + +Reindex: 901 funciones (+1 app_settings_cpp_core), 153 types, 13 apps. Working tree con cambios sin commit. + +## 17:50 — Settings menubar en chart_demo + gallery resync + +- Hecho: `chart_demo/main.cpp` — removida llamada explicita a `fps_overlay()`, añadida `fn_ui::app_menubar(nullptr, 0, nullptr)` para exponer Settings (mismo patron que gallery y dashboard). +- Hecho: removido `#include "core/fps_overlay.h"` (ya no necesario en la app — vive en fn_framework). +- Hecho: build Linux + Windows OK. Gallery resynced (`primitives_gallery.exe` 15.2 MB, timestamp 20:06). +- Hecho: nueva carpeta `Desktop/apps/chart_demo/` con `chart_demo.exe` (14.9 MB) + 5 TTFs. + +Estado final apps deployed con Settings menubar + multi-font: +- `Desktop/apps/primitives_gallery/` ✓ +- `Desktop/apps/registry_dashboard/` ✓ +- `Desktop/apps/shaders_lab/` ✓ +- `Desktop/apps/chart_demo/` ✓ (nueva) + +Las 4 apps comparten la misma menubar pattern (`View` opcional, `Layouts` opcional, `Settings...` siempre) y la misma seleccion de fuente/tamaño + toggle FPS via Settings. + +## 18:10 — Fix: cambio de tamaño en runtime ahora es instantaneo + +Usuario reportaba que el slider de tamaño no aplicaba inmediatamente. Causa: rebuild de atlas (Clear + AddFont + UpdateTexture) tarda 1+ frame y se notaba lag/flicker. + +ImGui 1.92+ (junio 2025) introdujo el sistema **escalable**: `style.FontSizeBase` cambia el tamaño de render dinamicamente sin rebuild de atlas — el atlas se rasteriza una vez y se escala via vector at draw time (cuando `BackendFlags_RendererHasTextures` esta activo, que lo esta con el backend OpenGL3 nuevo). + +- Hecho: `app_base.cpp` cada frame: `style.FontSizeBase = settings().font_size_px` + `style._NextFrameFontSizeBase = ...` (FIXME-hack documentado en imgui_demo.cpp:8520). Tamaño cambia al instante sin rebuild. +- Hecho: `settings_window`: el slider/combo de Size ya NO marca font dirty. Cambio puro de `font_size_px` (sin cambio de `font_id`) NO rebuildea atlas. +- Hecho: cambio de `font_id` (TTF distinta) sigue rebuildeando atlas — necesario porque las metricas de glyph difieren entre TTFs. +- Hecho: inicializacion en `run_app`: `style.FontSizeBase = settings().font_size_px` justo despues de `load_fonts_from_settings()`, asi el primer frame ya respeta el .ini. +- Hecho: footer de la ventana actualizado: "Tamaño aplica al instante. Cambio de fuente = 1 frame.". +- Hecho: rebuild Linux + Windows OK. Las 4 .exe sincronizadas a `Desktop/apps/` (timestamp 20:12). + +Referencias en imgui: +- `imgui.cpp:439` — changelog 1.92.6 sobre escalado dinamico +- `imgui.h:2370` — comment de `FontSizeBase` +- `imgui_demo.cpp:8519-8520` — patron de slider sobre `style.FontSizeBase` + `_NextFrameFontSizeBase` + +## 18:30 — Defaults DroidSans 15, kpi_card v1.3 con icono, shader_canvas en gallery + +Tres cambios en un sweep: + +### Defaults globales + +- Hecho: `AppSettings::font_id = FontId::DroidSans` (antes Karla). DroidSans tiene mejor legibilidad solida a 15 px en ImGui sin hinting. +- Hecho: `font_size_px = 15` y `show_fps = false` confirmados como defaults. +- Comentario actualizado en `app_settings.cpp` para que el .ini deje claro cual es el default. + +### kpi_card v1.3.0 — icono + Tabler arrows + +- Hecho: nueva firma con parametro opcional al final: `kpi_card(label, value, delta, history, count, format, icon = nullptr)`. Icono se renderiza inline antes del label en text_muted. +- Hecho: arrows del delta migradas de UTF-8 hex (`\xe2\x96\xb2` / `\xe2\x96\xbc`) a `TI_TRENDING_UP` / `TI_TRENDING_DOWN` — los anteriores no estan en el atlas de DroidSans/Karla y salian como cuadritos. Mismo fix en el placeholder de "no data": `\xe2\x80\x94` (em dash) → `TI_MINUS`. +- Hecho: card altura 78 → 86 px para acomodar el row icono+label sin apretar el resto. +- Hecho: gallery demo actualizado con iconos: `TI_CASH` (Revenue), `TI_USERS` (Users), `TI_CHART_BAR` (Churn), `TI_ALERT_CIRCLE` (Errors). +- Hecho: `kpi_card.md` bumped a v1.3, frontmatter con nuevo param `icon`. + +### shader_canvas en primitives_gallery + +shaders_lab tiene como pieza distintiva el preview live de fragment shaders. Añadido como demo en la gallery para documentar/showcase. + +- Hecho: nuevo dominio "Gfx" en el sidebar, primer item: `shader_canvas`. +- Hecho: `demos_gfx.cpp` con un fragment shader sintetico (gradiente animado de celdas con focus en mouse), compilado en el primer frame con `compile_fragment` y renderizado a 480x300 px via `canvas_render(canvas, time)`. +- Hecho: `demos.h` registra `demo_shader_canvas`. `main.cpp` añade entry al array `k_demos[]` con categoria "Gfx". +- Hecho: `gallery/CMakeLists.txt` añade el shader stack: `gl_shader.cpp + gl_framebuffer.cpp + fullscreen_quad.cpp + shader_canvas.cpp + demos_gfx.cpp`. +- Estado del binario: gallery crece de 15.2 → 18.1 MB (shader stack). + +### Build + sync + +- Hecho: rebuild Linux + Windows OK. +- Hecho: `Desktop/apps/` resynced — los 4 exes a las 20:20 con la nueva default config (DroidSans 15) y los iconos renderizando en kpi_card. + +Pendiente: +- Probar en Windows que defaults aplican en la primera apertura (sin `app_settings.ini` previo): DroidSans 15, FPS off. +- Probar shader_canvas demo en gallery: el shader debe compilar y animarse. +- Considerar mas demos gfx: `dag_palette` / `dag_panel` (node editor) — mas trabajo, lo dejo para otra sesion si hace falta. +- Añadir `app_menubar` / `panel_menu` / `layouts_menu` / `app_settings` como demos explicitos en la gallery (ahora se ven via la propia menubar de la gallery, pero un demo dedicado documentaria mejor el API). Skip por ahora. + +Reindex: 901 funciones (kpi_card y app_settings ya estaban en sesiones previas), 153 types. + +## 20:43 — /documentar — cierre de sesion C++ icons + settings + fuentes + +Wrap-up: distribucion de la conversacion a los `.md` que faltaban tras todos los cambios C++ del dia. + +- Hecho: `cpp/functions/core/app_menubar.md` — bloque "Notas — Settings menu" describiendo la inclusion automatica del item `Settings...` y la dependencia implicita en `app_settings_cpp_core`. +- Hecho: `cpp/functions/core/fps_overlay.md` — bloque "Notas — Auto-render via app_settings": `fn::run_app` lo invoca segun `settings().show_fps`; anti-patron de llamarlo directo desde la app. +- Hecho: `cpp/functions/viz/kpi_card.md` — bumped a v1.3, nuevo param `icon`, glyphs Tabler en delta/placeholder, comentario obsoleto sobre rangos UTF-8 marcado. +- Hecho: `apps/shaders_lab/app.md` — bloque "Notas — Settings + iconos" + "Lo siguiente que pega" (auditar hex inline en uniform_panel/dag_panel; ejemplo de seccion extra de settings). +- Hecho: `projects/fn_monitoring/apps/registry_dashboard/app.md` — bloque "Notas — Settings menubar" con el cambio de `render()` (ahora llama `app_menubar(nullptr,0,nullptr)`) y limpieza de CMake. +- Hecho: reindex final → 901 funciones, 153 types, 13 apps. + +Pendiente para proxima sesion: +- Migrar a `TI_*` cualquier hex UTF-8 (`"\x..\x.."`) o emoji Unicode hardcoded en uniform_panel, dag_panel, dag_node_editor (apps en uso ya tienen Tabler en atlas, no estamos aprovechando). +- Demos extra en gallery: `app_menubar`, `app_settings` y/o un par de items del DAG (`dag_palette` mostrando la paleta drag-source). Skip esta sesion porque requieren state pesado. +- Ejemplo concreto de `settings_window_add_section` en `shaders_lab` (auto-compile + debounce_ms persistido en `shaders_lab.db`). + +Estado final del working tree: cambios sin commit. Las 4 .exe en `Desktop/apps/` con build de las 20:20 (DroidSans 15 default, kpi cards con icono, gallery con shader_canvas demo).