Files
fn_registry/modules
egutierrez 2f7fdd407b feat(0133-3): wire filter/sort readers to columnar snapshot
Change 3 of issue 0133 — rewire compute_visible_rows, filter eval,
and sort comparators to read from the SnapshotCache when available.

Hot paths rewired:
- compute_visible_rows (overload with snap): filter eval uses
  compare_snap (fast i64/f64 numeric compare for Int/Float cols;
  id-compare for low-cardinality string Eq/Neq; raw cells fallback
  for Contains/StartsWith/EndsWith).
- Sort comparators: direct i64/f64 array compare for Int/Float cols
  (goto sort_done skips string fallback); string sort uses uint32_t
  id compare with pool lookup only on mismatch.
- Stage>0 filter/sort: same snapshot overload.

Materialization paths (build_so, s0_backing, mat_backing, config popup)
kept on raw cells — they copy into std::string anyway, no benefit from
snapshot and snprintf-per-cell was 2M extra calls per frame.

Bug fixes (required for correctness):
1. StringPool::intern() realloc safety: force reserve before
   emplace_back so string_view keys in the map never go dangling.
2. SnapshotCache::pool_size_built sentinel: detects when a new State
   is created with an empty pool but same cells pointer (begin_scenario
   pattern). Prevents str_ids from indexing into an empty pool (SIGSEGV).
3. Cardinality cap (2048 uniques / 25% sample): high-cardinality string
   cols (timestamps-as-strings, UUIDs, names) skip interning — str_ids
   stays empty and compare_snap falls back to raw cells. Prevents 30MB+
   pool bloat that hurt cache for filter/sort on other cols.

Bench delta vs baseline (100k rows, LIBGL_ALWAYS_SOFTWARE=1):
  linear_scroll: 16.0 -> 15.5 fps p50  (-3%, baseline already FAIL)
  filter_like:   59.7 -> 56.0 fps p50  (-6%, still PASS at 56fps)
  sort_numeric:   3.9 ->  9.0 fps p50 (+131%, snapshot i64 sort)
  color_rule:    15.2 -> 14.8 fps p50  (-3%, baseline already FAIL)

Build: green for all 10 available Linux consumers (text_editor_smoke
linker failure is preexisting, not caused by this change).

API public intact. TableEvent.row indexing TableInput preserved.
Pointer-identity invalidation preserved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 00:21:09 +02:00
..

Modulos C++ del registry

Bundles versionados de funciones del registry expuestos como static libs cmake. Apps opt-in via app.md::uses_modules + target_link_libraries(... fn_module_<X>).

Modulo Version Static lib Header Entry Linkage Descripcion Contrato
framework_cpp 1.1.0 fn_framework framework/app_base.h fn::run_app(cfg, render) transitivo via add_imgui_app Shell ImGui (GLFW+OpenGL+ImGui+ImPlot+themas+layouts+logger) framework_cpp
data_table_cpp 2.1.0 fn_module_data_table data_table/data_table.h data_table::render(id, tables, state, events_out, show_chrome) explicito Tabla completa TQL + 9 renderers declarativos + viz + drill + AI + button events data_table_cpp

Diferencia members vs uses_functions (post 0107d)

Cada module.md declara DOS listas:

  • members: funciones del registry que el modulo POSEE. Viven en cpp/functions/<dominio>/ y NO se usan fuera del modulo. Apps consumidoras del modulo NO listan estos miembros en su uses_functions (cobertura transitiva).
  • uses_functions: funciones del registry que el modulo CONSUME pero NO posee. Utiles fuera del modulo. Si una app necesita estas STANDALONE, las declara en su propio uses_functions directamente (no es duplicacion — es uso independiente).

Ejemplo data_table_cpp v2.1.0:

  • members: las 7 sub-funciones data_table_*_cpp_viz (renderizan dentro del modulo).
  • uses_functions: lua_engine, llm_anthropic, join_tables, auto_detect_type, tql_*, compute_*, viz_render (consumidas por el modulo pero utiles solas).

Como anadir un modulo

  1. mkdir modules/<name>/ con:

    • module.md (frontmatter: name, version, description, members, uses_functions, dir_path).
    • CMakeLists.txt definiendo add_library(fn_module_<name> STATIC ...).
    • <name>.cpp + <name>.h (entry function).
    • <name>_internal.h si tiene >1 archivo + UiState compartido.
  2. Anadir add_subdirectory(${CMAKE_SOURCE_DIR}/../modules/<name> ${CMAKE_BINARY_DIR}/modules/<name>) en cpp/CMakeLists.txt.

  3. Anadir fila en este catalogo + seccion en docs/MODULES_API.md siguiendo el template.

  4. fn index registra el modulo en registry.db::modules.

  5. Cada bump de version: /version modules/<name> <major|minor|patch> "<reason>". Edita module.md::version + ## Capability growth log.

Auditoria

  • fn doctor modules (0107a): detecta drift uses_modules vs uses_functions en apps. Hoy: 0 drift en 8 apps consumidoras de data_table_cpp post-0107b.
  • audit_data_table_usage_go_infra (capability del registry): audita patrones de uso del modulo data_table en apps. Detecta inline_begintable, state_not_persistent, no_child_host, no_event_sink, cmake_missing_link. Output en dev/data_table_integration_audit.md.

Ciclo de vida + version policy

Ver docs/MODULES_API.md::Ciclo de vida de un modulo y .claude/rules/cpp_apps.md.

Semver estricto:

  • Major = breaking ABI/API publica del modulo (entry function, State struct expuesto, eliminacion de members).
  • Minor = additive backward-compatible (nuevo renderer, nuevo evento, refactor interno sin cambio de API).
  • Patch = bugfix sin cambio de API.

Slash command para bumpear: /version modules/<name> <bump-type> "<reason>".

Modulos en roadmap (post 0107)

  • chat_ia_cpp — sera el siguiente modulo. Bloqueado hasta cierre completo de 0107 (estandarizacion modulos). Issue 0109 cuando 0107 cierre.
  • Otros candidatos detectados por uso repetido en apps: TBD (auditar con audit_data_table_usage pattern para otros bundles).