docs(issues): cerrar 0041, 0042, 0044, 0047 + actualizar README

This commit is contained in:
2026-04-28 23:45:40 +02:00
parent 50c7452df3
commit b2d7b29e00
4 changed files with 4 additions and 4 deletions
@@ -0,0 +1,124 @@
# 0041 — C++ app shell estandarizado: BEST_PRACTICES + AppConfig extendido
## Metadata
| Campo | Valor |
|-------|-------|
| **ID** | 0041 |
| **Estado** | pendiente |
| **Prioridad** | alta |
| **Tipo** | feature — C++ framework (`cpp/framework/`) + docs |
## Dependencias
Ninguna. Habilita **0043** (estandarizar apps existentes) y todo desarrollo futuro de apps C++.
---
## Objetivo
1. Documentar el patron canonico de apps C++ del registry en `cpp/PATTERNS.md` con checklist obligatorio.
2. Extender `fn::AppConfig` para que `fn::run_app()` registre About + paneles + theming en una sola llamada, eliminando boilerplate por app.
## Contexto
La auditoria muestra que `chart_demo`, `primitives_gallery`, `shaders_lab` y `registry_dashboard` arrancan distinto: solo `shaders_lab` aprovecha `app_menubar` con paneles, solo `registry_dashboard` registra About + Settings, `primitives_gallery` llama `apply_dark_theme()` + `gl_loader_init()` a mano que el resto delega a `run_app()`. Sin estandar, cada app proxima reinventa esto.
## Arquitectura
```
cpp/
├── PATTERNS.md # NEW — checklist y patrones
├── framework/
│ ├── app_base.h # MOD — extender AppConfig
│ └── app_base.cpp # MOD — aplicar nuevos campos
└── functions/core/
└── (sin cambios — app_menubar/app_about/app_settings ya existen)
```
### AppConfig extendido (propuesta)
```cpp
struct AppAboutInfo {
const char* name = nullptr;
const char* version = nullptr;
const char* description = nullptr;
};
struct AppConfig {
const char* title = "fn app";
int width = 1280;
int height = 800;
bool vsync = true;
bool viewports = false;
ThemeMode theme = ThemeMode::FnDark;
float bg_r=0,bg_g=0,bg_b=0;
// NEW — registra About si name != nullptr.
AppAboutInfo about{};
// NEW — paneles toggleables del menubar (si != nullptr).
const fn_ui::PanelToggle* panels = nullptr;
size_t panel_count = 0;
// NEW — callbacks de layouts persistentes (si != nullptr).
fn_ui::LayoutCallbacks* layouts_cb = nullptr;
// NEW — si true, llama gl_loader_init() antes del primer frame.
bool init_gl_loader = false;
};
```
`run_app()` aplica:
- Si `about.name != nullptr``fn_ui::about_window_set_info(...)`.
- Si `init_gl_loader``fn::gfx::gl_loader_init()` tras crear el contexto GL.
- Cada frame, si `panels != nullptr` o `layouts_cb != nullptr`, llama `app_menubar(panels, panel_count, layouts_cb)` automaticamente — la app NO la llama.
## Tareas
### Fase 1 — Doc
1.1 Crear `cpp/PATTERNS.md` con checklist:
- Usa `fn::run_app()` con `AppConfig` (jamas `glfwInit` directo).
- Registra About via `AppConfig::about` o `about_window_set_info()`.
- Registra Settings extras via `settings_window_add_section()`.
- Si tienes paneles, define `static constexpr fn_ui::PanelToggle panels[]` y pasalo en `AppConfig::panels`.
- Si necesitas layouts, implementa `LayoutCallbacks` y pasalas en `AppConfig::layouts_cb`.
- Usa `fn_tokens::colors|spacing|radius` siempre. Nunca colores hex literales.
- Evita `ImGui::BeginTable / Selectable / BeginPopupModal / BeginChild` con styling manual — usa `dashboard_grid`, `tree_view`/`select`, `modal_dialog`, `dashboard_panel`.
### Fase 2 — Framework
2.1 Anadir campos `about`, `panels`, `panel_count`, `layouts_cb`, `init_gl_loader` a `AppConfig` en `app_base.h`.
2.2 En `run_app()` (`app_base.cpp`):
- Tras `gl_loader_init` opcional.
- Tras `about_window_set_info` si procede.
- Antes del `render_fn()` por frame, llama `app_menubar(panels, panel_count, layouts_cb)` si alguno != nullptr.
2.3 Backward-compat: campos nuevos opcionales con defaults — apps existentes compilan sin tocarlas.
### Fase 3 — Validacion
3.1 Compilar todas las apps existentes sin cambios, verificar que no rompe.
3.2 Build Linux + cross-compile Windows.
### Fase 4 — Indexar
4.1 `./fn index` para refrescar metadata (no cambia funciones — solo doc).
## Decisiones de diseno
- `AppConfig` con campos opcionales (no nuevos overloads de `run_app`) — minimiza la API surface.
- La menubar se llama desde `run_app` solo si la app declara paneles/layouts; en otro caso la app puede llamar `app_menubar(nullptr,0,nullptr)` ella misma (compat).
## Riesgos
- Apps que ya llaman `app_menubar` manualmente con `panels` distintos al `AppConfig`: documentar — `run_app` la llama una vez al inicio del frame, la app puede dejar de hacerlo.
## Validacion
- `cpp/PATTERNS.md` legible en GitHub.
- `chart_demo` (la mas simple) puede ahora declararse asi:
```cpp
fn::run_app({.title="chart demo", .about={.name="chart demo", .version="0.1", .description="..."}}, render);
```
- Tests de compilacion OK para shaders_lab/chart_demo/primitives_gallery/registry_dashboard sin modificar.
@@ -0,0 +1,84 @@
# 0044 — Auditar 52 funciones C++ huerfanas y poblar uses_functions
## Metadata
| Campo | Valor |
|-------|-------|
| **ID** | 0044 |
| **Estado** | pendiente |
| **Prioridad** | media |
| **Tipo** | chore — registry hygiene |
## Dependencias
Ninguna.
---
## Objetivo
Resolver las 52 funciones C++ que aparecen sin `uses_functions` en `registry.db`: o son legitimamente independientes, o se usan pero no se registra la dependencia (caso `fps_overlay` que se invoca desde `app_base.cpp` pero no aparece). Resultado: `uses_functions` reflejando la verdad.
## Contexto
Ejemplos detectados:
- `fps_overlay` — usado por `app_base.cpp`, no registrado.
- `tokens` — usado por 16+ componentes, ya registrado bien.
- `tween_curves`, `orbit_camera`, `time_series_buffer`, `graph_force_layout`, `plot_theme` — sin consumidores visibles. Verificar si estan en gallery/chart_demo o son scaffolding.
- `app_settings`, `app_about`, `app_menubar`, `icon_font` — usados por `app_base.cpp`, no registrados.
## Arquitectura
Este issue NO modifica codigo C++. Solo modifica:
- Frontmatter `.md` de funciones huerfanas para anadir `uses_functions: [...]` reflejando llamadas reales.
- Eventualmente borrar funciones que se confirmen sin uso real ni plan de uso (con el OK del usuario via comment en el issue).
## Tareas
### Fase 1 — Lista exacta
1.1 Generar la lista actual:
```bash
sqlite3 registry.db "SELECT id FROM functions WHERE lang='cpp' AND uses_functions = '[]' ORDER BY id;"
```
1.2 Para cada id, hacer `grep -rn "<name>" cpp/ projects/*/apps/*/` y ver donde se invoca.
### Fase 2 — Categorizar
Para cada huerfana, asignar uno de estos estados (anotar en una tabla en este issue):
- **USED** — se invoca desde otra funcion/app. Anadir el caller a `uses_functions` del consumidor (no del huerfano).
- **DEMO_ONLY** — solo en `primitives_gallery` o demos. OK como esta. Documentar en `.md` como `# scaffolding/demo only`.
- **PLANNED** — sin uso pero hay issue/plan futuro. Anotar en `.md` con referencia.
- **DEAD** — sin uso real ni plan. Candidato a borrar (preguntar al usuario antes).
### Fase 3 — Actualizar frontmatter
3.1 Para cada **USED**: editar el `.md` del CONSUMIDOR para anadir el huerfano a su `uses_functions`. Ejemplo: `app_base.cpp` consume `fps_overlay_cpp_core`, `app_settings_cpp_core`, `app_about_cpp_core`, `app_menubar_cpp_core`, `icon_font_cpp_core`, `tokens_cpp_core`. Pero `app_base` NO esta en functions/ del registry — es un .cpp del framework. **Corregir**: si `app_base.cpp` no esta indexado, registrar como funcion en `cpp/framework/` o documentar la convencion en notes.
3.2 Para **DEMO_ONLY**: anadir nota en frontmatter `notes: "demo en primitives_gallery, scaffolding"`.
3.3 Para **PLANNED**: anadir `notes: "planned use in issue NNNN"`.
3.4 Para **DEAD**: listar en este issue y abrir un sub-issue de delete (no borrar de oficio).
### Fase 4 — Reindex
4.1 `./fn index` para regenerar `registry.db`.
4.2 Verificar:
```bash
sqlite3 registry.db "SELECT COUNT(*) FROM functions WHERE lang='cpp' AND uses_functions = '[]';"
```
La cifra debe bajar significativamente (objetivo: <20 huerfanas reales).
### Fase 5 — Documentar la convencion
5.1 Anadir a `.claude/rules/uses_functions.md` (NEW) la regla: cada vez que un .cpp llama a otra funcion del registry, el `.md` del CONSUMIDOR debe listar la dependencia en `uses_functions`. El indexer no lo deduce automaticamente (el codigo C++ no es trivial de parsear).
## Decisiones
- No borrar funciones sin OK explicito.
- `app_base.cpp` no esta hoy indexado como funcion del registry (es framework). Si decidimos indexarlo, eso es 0048 — ahora solo registramos en uses_functions de los CONSUMIDORES que si esten indexados (gallery, dashboard, etc.).
## Validacion
- `uses_functions` poblados para los casos reales (verificable por SQL).
- `cpp/PATTERNS.md` (de 0041) referencia esta convencion.
- Nada compilado se rompe (este issue NO toca .cpp/.h).
@@ -0,0 +1,114 @@
# 0047 — C++ tests foundation: Catch2 + tests para top-20 primitivos
## Metadata
| Campo | Valor |
|-------|-------|
| **ID** | 0047 |
| **Estado** | pendiente |
| **Prioridad** | alta |
| **Tipo** | feature — testing infra |
## Dependencias
Ninguna.
---
## Objetivo
Montar Catch2 (single-header, vendoreado) en `cpp/`, integrar con CMake y `ctest`, y escribir tests unitarios para el top-20 de primitivos puros del registry. Pasar de 4% a >25% de cobertura en C++.
## Contexto
Hoy hay 3 funciones C++ con `tested: true` (3.7% de 81). El indexer ya soporta extraer tests automaticamente al campo `tests` del `.md` cuando hay `test_file_path`. Falta el framework, la integracion y la cobertura inicial.
## Arquitectura
```
cpp/
├── vendor/catch2/
│ └── catch_amalgamated.{hpp,cpp} # NEW — Catch2 v3 amalgamated, MIT
├── tests/
│ ├── CMakeLists.txt # NEW — un test per-file
│ ├── test_tokens.cpp # NEW
│ ├── test_button.cpp # NEW (state-only — sin GUI render)
│ ├── test_select.cpp # NEW
│ ├── test_text_input.cpp # NEW
│ ├── test_badge.cpp # NEW
│ ├── test_kpi_card.cpp # NEW (calculo de delta/format)
│ ├── test_pie_chart.cpp # NEW (slice_at logic)
│ ├── test_bar_chart.cpp # NEW (label rotation logic)
│ ├── test_tree_view.cpp # NEW
│ ├── test_modal_dialog.cpp # NEW
│ ├── test_toolbar.cpp # NEW
│ ├── test_toast.cpp # NEW
│ ├── test_empty_state.cpp # NEW
│ ├── test_page_header.cpp # NEW
│ ├── test_dashboard_panel.cpp # NEW
│ ├── test_dashboard_grid.cpp # NEW
│ ├── test_sparkline.cpp # NEW
│ ├── test_table_view.cpp # NEW
│ ├── test_icon_button.cpp # NEW
│ └── test_tween_curves.cpp # NEW (puro, ideal candidato)
└── CMakeLists.txt # MOD — anadir tests subdir si BUILD_TESTING
```
## Tareas
### Fase 1 — Vendoreado de Catch2
1.1 Bajar `catch_amalgamated.hpp` + `catch_amalgamated.cpp` (Catch2 v3 single-header) a `cpp/vendor/catch2/`. Anadir LICENSE y README pequeno.
1.2 No usar FetchContent — stay offline. Catch2 v3 es BSL-1.0.
### Fase 2 — Integracion CMake
2.1 En `cpp/CMakeLists.txt`, anadir option `BUILD_TESTING` (default ON). Si activo, `add_subdirectory(tests)`.
2.2 `cpp/tests/CMakeLists.txt`: una funcion CMake `add_fn_test(name srcs)` que:
- Crea un executable test linkeado contra `fn_framework`, ImGui (sin GLFW si no hace falta), Catch2.
- Anade al `ctest` con `add_test(NAME ${name} COMMAND ${name})`.
### Fase 3 — Tests para puros (sin GUI)
3.1 `tween_curves`: lerp, ease_in, ease_out, edge cases (t=0, t=1, valores fuera de rango).
3.2 `slice_at` de pie_chart (es funcion interna — exponer via header de test o moverla a `pie_math.h`).
3.3 Cualquier helper puro de `bar_chart` (rotacion de labels), `kpi_card` (formato de delta).
### Fase 4 — Tests para componentes con state pero sin render (parcial)
4.1 Para `process_state_machine`, `file_poll_diff`, `sql_parse` (creados en 0045 si existen): tests directos.
4.2 Para componentes UI (`button`, `select`, `tree_view`, etc.): solo logica accesible sin contexto ImGui (callbacks, state setters, formateo). Render real queda para tests visuales (issue 0048).
### Fase 5 — Hook con el indexer
5.1 Para cada funcion testeada, actualizar su `.md`: `tested: true`, `test_file_path: cpp/tests/test_<name>.cpp`. El indexer puebla `tests` automaticamente desde el archivo.
5.2 `./fn index` y verificar:
```bash
sqlite3 registry.db "SELECT COUNT(*) FROM functions WHERE lang='cpp' AND tested=1;"
```
Meta: >=20 (de 81 = 25%).
### Fase 6 — CI gate (warmup, sin failure)
6.1 Anadir `cpp/scripts/run_tests.sh` que hace `cmake --build && ctest --output-on-failure`.
6.2 Documentar en `cpp/PATTERNS.md` (issue 0041) que toda funcion nueva debe tener `tested: true`.
## Decisiones
- Catch2 v3 amalgamated (no header-only) — compila mas rapido despues del primer build.
- Tests **no** intentan renderizar ImGui — pintar requiere GL context, complicado en CI. Tests visuales se hacen en issue 0048 con primitives_gallery + screenshots.
## Riesgos
- Algunos primitivos no tienen logica testeable sin contexto ImGui (ej. `toolbar` solo concatena items). En esos casos, escribir test trivial que verifica que el codigo compila + linkea, o saltarlo y documentar en `notes`.
- Catch2 puede tardar 30-60s la primera vez. Aceptable.
## Validacion
```bash
cd cpp/build && cmake -DBUILD_TESTING=ON .. && cmake --build . -j
ctest --output-on-failure
sqlite3 registry.db "SELECT id FROM functions WHERE lang='cpp' AND tested=1;"
```
20+ tests pasando, 20+ funciones con `tested: true`.