---
id: 0081
title: tables playground — promote a registry + migrar apps C++ (fase 12)
status: done
priority: high
created: 2026-05-12
updated: 2026-05-15
notes: |
  0081-A DONE: 20 types extraidos a cpp/functions/core/data_table_types.h con .md por type
   (17 core + 3 viz). Playground includes via "core/data_table_types.h", no duplicacion.
   603 tests pass, e2e linux+windows OK.
  0081-B..L DONE (2026-05-15): 10 funciones registry (8 core + 2 viz), 1 lib fn_table_viz,
   3 apps migradas (chart_demo no aplica, graph_explorer parcial 1/9, registry_dashboard parcial 8/12),
   fn doctor cpp-apps check anadido (BeginTable inline detection: CANDIDATE/MIXED),
   docs/TQL.md actualizado con joins, views, main_source, 24 viz tokens, color_rules,
   derived columns, fn.* sandbox completo (20 builtins), funciones bloqueadas.
   Deuda: sqlite_api + deploy_server NO migrados (Go apps, requieren TS table system aparte);
   graph_explorer + registry_dashboard + otras apps C++ marcadas CANDIDATE por fn doctor
   (migrar en waves futuras con rama TBD dedicada por app).
related_components: [cpp/apps/primitives_gallery/playground/tables, cpp/functions, fn_framework]
---

## Contexto

Fase 12 final del roadmap. Extraer el playground completo al registry como
funciones reutilizables. Migrar todas las apps C++ que renderizan tablas para
que usen `data_table_cpp_viz` en vez de codigo propio.

## Extraccion al registry

### Funciones a crear

| ID                            | Lang | Domain   | Purity | Que hace |
|-------------------------------|------|----------|--------|----------|
| `data_table_cpp_viz`          | cpp  | viz      | impure | UI completa: chips + tabla + viz + extras + joins + TQL |
| `compute_stage_cpp_core`      | cpp  | core     | pure   | Ejecuta un Stage (filter+breakout+agg+sort) |
| `compute_pipeline_cpp_core`   | cpp  | core     | pure   | Chain de stages 0..N -> StageOutput final |
| `tql_emit_cpp_core`           | cpp  | core     | pure   | State -> Lua text |
| `tql_apply_cpp_core`          | cpp  | core     | pure   | Lua text -> State (+ warnings) |
| `viz_render_cpp_viz`          | cpp  | viz      | impure | Dispatcher ImPlot sobre StageOutput |
| `lua_engine_cpp_core`         | cpp  | core     | impure | Eval de formulas Lua sandboxed |
| `join_tables_cpp_core`        | cpp  | core     | pure   | Hash join multi-key, 4 estrategias |
| `auto_detect_type_cpp_core`   | cpp  | core     | pure   | Auto-detect ColumnType desde sample (ya existe en logic) |
| `compute_column_stats_cpp_core` | cpp | core     | pure   | Stats por col (mean/p25/p50/p75/uniq/missing/hist) |

### Tipos

| ID                          | Algebraic |
|-----------------------------|-----------|
| `ColumnType_cpp_core`       | sum       |
| `Op_cpp_core`               | sum       |
| `Filter_cpp_core`           | product   |
| `Stage_cpp_core`            | product   |
| `StageOutput_cpp_core`      | product   |
| `Aggregation_cpp_core`      | product   |
| `Join_cpp_core`             | product   |
| `TableInput_cpp_core`       | product   |
| `ViewMode_cpp_viz`          | sum       |
| `ViewConfig_cpp_viz`        | product   |
| `VizPanel_cpp_viz`          | product   |
| `State_cpp_viz`             | product   |
| `ColStats_cpp_core`         | product   |

### Estructura en el registry

```
cpp/functions/core/
  compute_stage.{h,cpp,md}
  compute_pipeline.{h,cpp,md}
  tql_emit.{h,cpp,md}
  tql_apply.{h,cpp,md}
  lua_engine.{h,cpp,md}
  join_tables.{h,cpp,md}
  data_table_logic.h          # tipos compartidos (Stage, ColumnType, etc.)
  ...
cpp/functions/viz/
  data_table.{h,cpp,md}        # UI principal
  viz_render.{h,cpp,md}        # dispatcher ImPlot
```

Dominio nuevo `viz` para funciones de visualizacion. Alternativa: usar `tui`
si encaja, pero `viz` es mas explicito.

### Bundle en `fn_framework`

`fn_framework` ya bundle a `lua54`, `implot`. Añadir las funciones core/viz
como parte del lib estatico opcional `fn_table_viz` que las apps linkan via
`target_link_libraries(<app> PRIVATE fn_table_viz)`.

## Migracion de apps existentes

Apps con tabla custom hoy:

| App                                          | Cambios |
|----------------------------------------------|---------|
| `cpp/apps/chart_demo`                        | Sustituir tabla por `data_table::render({tables}, state)`. Persistir State en SQLite local. |
| `projects/osint_graph/apps/graph_explorer`   | Reemplaza panels que listan entities/relations con render(). Pasa multiples TableInput (entities, relations, jobs). |
| `projects/fn_monitoring/apps/registry_dashboard` | Tablas de funciones/types/apps via render. Joinables: cross-references entre tablas. |
| `projects/fn_monitoring/apps/sqlite_api`     | Resultado de query como TableInput. |
| `apps/kanban`                                | NO migrar — kanban no es tabla, es board. |
| `apps/deploy_server`                         | Tabla de deploys + targets. |

Cada migracion en su rama TBD propia (ver `apps_tbd.md`).

## TQL como contrato textual

Documento `docs/TQL.md` ya existe pero hay que actualizar:
- Anadir `joins`, `views`, `main_source` (faltan)
- Listado completo de viz tokens
- Funciones Lua disponibles + sandbox

## Tests

- `compute_stage/pipeline` ya tienen tests en playground self_test. Mover a `cpp/functions/core/*_test.cpp`.
- Smoke test: app fake con TableInput hardcoded -> render() compila + tests basicos pasan.
- `fn run` debe poder ejecutar tests de las nuevas funciones.

## Doctor

`fn doctor cpp-apps` añadir check: apps con tablas custom (heuristica: `ImGui::BeginTable` en main.cpp) sugieren migracion a `data_table_cpp_viz`.

## Riesgos

- Linker bloat: cada app que use `data_table_cpp_viz` arrastra lua54 (~150KB) + implot (~200KB). Aceptable.
- API stability: una vez en registry hay que mantener `render()` signature. Cualquier breaking change requiere proposal.
- Tests duplicados: borrar self_test.cpp del playground si los tests se mueven al registry.

## No-objetivos

- Migrar a otras tecnologias (web, mobile) — fase futura via TS/Kotlin equivalentes.
- Reescribir apps que no usen tablas — fuera de scope.
