Files
fn_registry/dev/issues/completed/0107-modules-standardization.md
egutierrez b9716a7cd6 chore: snapshot WIP previo + flow 0008 + 7 sub-issues (0112-0119)
Snapshot de WIP acumulado de sesiones previas antes de merge wave 1
del flow 0008 (kanban_cpp + agent_runner_api + DoD schema).

Incluye:
- dev/flows/0008-kanban-cpp-and-agent-workflows.md
- dev/issues/0112-0119*.md (7 sub-issues)
- WIP previo en cmd/fn/doctor.go, registry/*, modules/, cpp/, etc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:17:08 +02:00

14 KiB

id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
id title status type domain scope priority depends blocks related created updated tags
0107 Estandarizar sistema de modulos C++: limpiar drift data_table + politica API + version pinning + /version command pendiente refactor
meta
cpp-stack
tooling
multi-app alta
0108
0097
0081
0086
2026-05-17 2026-05-17
modules
cpp
data-table
framework
refactor
fn-doctor
versioning

0107 — Estandarizar sistema de modulos C++

Problema

Auditoria 2026-05-17 sobre modules/ (framework + data_table) revela que el sistema de modulos C++ esta a medio camino: la idea (modulos opt-in versionados con manifest auditable) es solida, pero su implementacion tiene fugas que invalidan el contrato.

Drift uses_modules ↔ uses_functions (7/7 apps consumidoras)

module.md dice "cuando declaras uses_modules, NO repetir los miembros en uses_functions". Realidad medida hoy:

App uses_functions total miembros data_table duplicados
services_monitor 12 12
dag_engine_ui 13 12
odr_console 5 5
navegator_dashboard 20 12
graph_explorer 42 12
registry_dashboard 37 11
app_gestion 12 12

7 de 7 apps violan la regla clave que justifica el sistema. fn doctor cpp-apps no detecta el drift.

data_table.cpp = 4777 LOC

El "modulo" es un god-file con UI entera (chips, viz, grid, drill, joins, AI, button, color rules) dentro de un .cpp. Imposible auditar consumidores parciales, imposible registrar miembros como funciones reales del registry (cada uno con su .md).

Boundary modulo vs funcion borrosa

lua_engine, llm_anthropic, join_tables son members de data_table. Pero lua/llm/join son utiles fuera de tablas. Forzar membership infla el surface del modulo y obliga a las apps a tragarse lua+llm+anthropic+join aunque solo quieran render simple. No hay tier "data_table_core" vs "data_table_full".

Versionado declarado, no enforced

module.md tiene version: 1.4.0. app.md dice uses_modules: [data_table_cpp] sin version. Bump breaking de modulo → todas las apps rompen sin warning hasta compile error.

Codegen silencioso

execute_process(... codegen_app_modules) emite WARNING solo si rc != 0 y != 2. Si Python falta → stub vacio sin error. About panel muestra "0 modules" en apps que SI deberian tener 1.

Hard dep oculto

fn_module_data_table linkea fn_framework PRIVATE para fn::local_path(). module.md no lo documenta como precondicion publica. Si alguien intenta usar el modulo en una app no-framework, falla en link sin mensaje claro.

Sin doc API de modulos

No hay un sitio canonico que diga "para usar el modulo X, incluye Y.h, llama X::render(...), pasa State Z". Cada modulo lo improvisa en su module.md.

Sin /version command

No hay flujo estandar para bumpear semver de un modulo o framework. Cada PR lo hace a ojo, sin coherencia entre module.md::version y ## Capability growth log.

Decision

Issue desglosado en 6 sub-issues independientes detras de feature flag modules-v2:

  1. 0107afn doctor modules que detecta drift uses_modules vs uses_functions.
  2. 0107b — Limpiar uses_functions de las 7 apps consumidoras de data_table (eliminar miembros duplicados).
  3. 0107c — Partir modules/data_table/data_table.cpp (4777 LOC) en sub-funciones del registry (data_table_chips, data_table_grid, data_table_viz_panels, data_table_drill, data_table_ai_panel, data_table_color_rules). Cada una con .md propio. Entrypoint queda thin.
  4. 0107d — Mover members generales (lua_engine, llm_anthropic, join_tables, auto_detect_type) fuera de data_table module. Quedan funciones sueltas que el modulo USA pero no posee. Crear tiers explicitos.
  5. 0107e — Version pinning en uses_modules (uses_modules: [{name: data_table_cpp, min_version: "1.4"}]) + codegen fail-loud (error si Python falta o count=0 cuando deberia ser >0).
  6. 0107fmodules/README.md (catalogo) + docs/MODULES_API.md (contrato publico por modulo: header path, namespace, entry function, State struct, lifecycle).

Ademas:

  • /version slash command para bumpear semver de modulo/framework consistentemente (module.md::version + ## Capability growth log + git commit).
  • /fix-issue referenciara /version cuando el cambio toque framework/modules.

Feature flag modules-v2 activado solo cuando 0107a-f cierran. Antes de cerrar, recompilar TODAS las apps cpp para verificar que el refactor no rompe linkage. Aceptamos coste de recompilacion total.

Restriccion explicita

Prohibido empezar chat_ia (proximo modulo planeado) hasta que 0107 cierre. Razon: si arrancamos otro modulo sin estandar estable, replicamos los mismos bugs en el doble de superficie.

Tareas (resumen — detalle en sub-issues)

  • 1 Auditoria automatizada → fn doctor modules (0107a)
  • 2 Limpiar drift en 7 apps consumidoras (0107b)
  • 3 Partir data_table.cpp en sub-funciones del registry (0107c)
  • 4 Politica members generales + tiers (0107d)
  • 5 Version pinning + codegen fail-loud (0107e)
  • 6 Docs API publica modulos (0107f)
  • 7 Recompilar todas las apps cpp + verificar smoke (al cerrar)
  • 8 Activar feature flag modules-v2
  • 9 /version + /fix-issue (no son sub-issues; tareas inline en este issue principal)

Desglose multi-issue

Sub-issue Rama Alcance Estado
0107a-fn-doctor-modules issue/0107a-fn-doctor-modules Check drift uses_modules vs uses_functions + version skew pendiente
0107b-clean-data-table-consumers issue/0107b-clean-data-table-consumers Eliminar miembros duplicados en 7 app.md pendiente
0107c-split-data-table issue/0107c-split-data-table Partir data_table.cpp 4777 LOC en sub-funciones del registry pendiente
0107d-module-tiers-policy issue/0107d-module-tiers-policy Sacar lua/llm/join del modulo data_table; tiers + politica pendiente
0107e-version-pinning-codegen issue/0107e-version-pinning-codegen min_version en uses_modules + codegen fail-loud pendiente
0107f-modules-api-docs issue/0107f-modules-api-docs modules/README.md + docs/MODULES_API.md pendiente

Feature flag

Nombre: modules-v2 Se activa cuando 0107a-f cierran + recompilacion total verificada + fn doctor modules reporta 0 drift.

Progreso por tarea

  • 1.1 Implementar check drift en fn doctor cpp-apps o sub-comando nuevo — 0107a
  • 1.2 Output JSON con apps que violan regla — 0107a
  • 1.3 Tests sobre fixture sintetica (1 modulo, 3 apps simuladas) — 0107a
  • 2.1 Editar 7 app.md removiendo miembros data_table — 0107b
  • 2.2 Verificar build pasa post-clean (no rompe nada — solo metadata) — 0107b
  • 3.1 Identificar fronteras funcionales en data_table.cpp 4777 LOC — 0107c
  • 3.2 Crear cpp/functions/viz/data_table_chips.cpp + .h + .md — 0107c
  • 3.3 Crear cpp/functions/viz/data_table_grid.cpp + .h + .md — 0107c
  • 3.4 Crear cpp/functions/viz/data_table_viz_panels.cpp + .h + .md — 0107c
  • 3.5 Crear cpp/functions/viz/data_table_drill.cpp + .h + .md — 0107c
  • 3.6 Crear cpp/functions/viz/data_table_ai_panel.cpp + .h + .md — 0107c
  • 3.7 Crear cpp/functions/viz/data_table_color_rules.cpp + .h + .md — 0107c
  • 3.8 data_table.cpp queda como entrypoint thin que compone las sub-funciones — 0107c
  • 3.9 Bump module.md::version a 2.0.0 (breaking interno, API publica data_table::render intacta) — 0107c
  • 4.1 Crear cpp/functions/core/lua_engine.cpp (ya existe) como funcion suelta; quitar de module.md::members — 0107d
  • 4.2 Idem llm_anthropic, join_tables, auto_detect_type — 0107d
  • 4.3 Actualizar modules/data_table/CMakeLists.txt: estos .cpp ya no se enlazan dentro del modulo; apps que los necesiten los anaden a su CMakeLists — 0107d
  • 4.4 Definir tiers en module.md: core_members (esenciales) vs optional_members (deps externas pesadas) — 0107d
  • 5.1 Parser app.md::uses_modules acepta string corto y dict largo — 0107e
  • 5.2 Codegen comprueba min_version vs module.md::version — error si no cumple — 0107e
  • 5.3 Codegen: si Python3 NOT FOUND y app tiene uses_modules → CMake FATAL_ERROR — 0107e
  • 5.4 Codegen: si parser devuelve count=0 pero app.md declara uses_modules no-vacio → FATAL_ERROR — 0107e
  • 6.1 modules/README.md con tabla modulos + version + descripcion + link a contrato — 0107f
  • 6.2 docs/MODULES_API.md con contrato canonico (template + ejemplos data_table + framework) — 0107f
  • 6.3 Actualizar .claude/rules/cpp_apps.md referenciando docs/MODULES_API.md — 0107f
  • 7.1 redeploy_all_cpp_apps_bash_pipelines + verificar 0 errores de link — issue principal, al cerrar
  • 7.2 Smoke manual de cada app con data_table::render — issue principal, al cerrar
  • 8 Flip modules-v2: enabled: true en dev/feature_flags.json — issue principal
  • 9.1 Crear .claude/commands/version.md (slash command bump semver) — issue principal, ya en este turno
  • 9.2 Crear .claude/commands/fix-issue.md que referencie /version — issue principal, ya en este turno

Arquitectura

Archivos afectados

0107a (fn doctor modules):

  • functions/infra/audit_modules_drift.go (NEW) — funcion del registry
  • functions/infra/audit_modules_drift.md (NEW)
  • cmd/fn/doctor.go — subcomando modules
  • apps/registry_mcp/... — exponer via mcp__registry__fn_doctor subcommand="modules"

0107b:

  • 7 app.md editados: services_monitor, dag_engine_ui, odr_console, navegator_dashboard, graph_explorer, registry_dashboard, app_gestion.

0107c:

  • modules/data_table/data_table.cpp — pasa de 4777 LOC a ~400 (entrypoint que compone).
  • cpp/functions/viz/data_table_chips.cpp/.h/.md (NEW) — ~600 LOC
  • cpp/functions/viz/data_table_grid.cpp/.h/.md (NEW) — ~1200 LOC
  • cpp/functions/viz/data_table_viz_panels.cpp/.h/.md (NEW) — ~800 LOC
  • cpp/functions/viz/data_table_drill.cpp/.h/.md (NEW) — ~300 LOC
  • cpp/functions/viz/data_table_ai_panel.cpp/.h/.md (NEW) — ~500 LOC
  • cpp/functions/viz/data_table_color_rules.cpp/.h/.md (NEW) — ~400 LOC
  • modules/data_table/module.md — bump version + actualizar members.
  • modules/data_table/CMakeLists.txt — anadir las sub-funciones a la static lib.

0107d:

  • modules/data_table/module.md — quitar lua_engine, llm_anthropic, join_tables, auto_detect_type de members.
  • modules/data_table/CMakeLists.txt — estos .cpp salen.
  • Apps consumidoras que necesiten lua/llm/join → declarar en uses_functions + anadir el .cpp a su CMake.

0107e:

  • python/functions/infra/codegen_app_modules.py — soporte dict largo {name, min_version}.
  • cpp/CMakeLists.txt::add_imgui_app — fail-loud en codegen errors.
  • registry/parser.go — indexer entiende dict largo.

0107f:

  • modules/README.md (NEW)
  • docs/MODULES_API.md (NEW)
  • .claude/rules/cpp_apps.md — link nuevo doc.

Slash commands (este issue):

  • .claude/commands/version.md (NEW)
  • .claude/commands/fix-issue.md (NEW si no existe)

pkg/ puro vs shell/ impuro

audit_modules_drift_go_infra (0107a) es impuro — lee registry.db + filesystem (app.md, module.md). Vive en functions/infra/. Core logico (comparar listas de IDs, detectar miembros duplicados) es puro y vive como sub-funcion interna del paquete infra.

Ejemplo de uso

# 1. Detectar drift
fn doctor modules
# Output:
# Module drift report
# ===================
# data_table_cpp (v1.4.0): 7/7 consumers list members in uses_functions
#   services_monitor — duplicates: data_table_cpp_viz, viz_render_cpp_viz, ...
#   dag_engine_ui — duplicates: ...
# Total apps with drift: 7
# Total modules: 2
# Exit: 1

# 2. Bump version de un modulo (slash command)
/version modules/data_table minor "split data_table.cpp into 6 sub-functions; API publica intacta"
# - Detecta version actual en module.md (1.4.0)
# - Calcula proxima (1.5.0 si minor, 2.0.0 si major)
# - Anade entrada a ## Capability growth log con fecha de hoy
# - Stage en git pero NO commit

# 3. Pinning version en una app
# app.md:
# uses_modules:
#   - name: data_table_cpp
#     min_version: "1.4"
# Codegen falla en cmake si module.md::version < 1.4

# 4. fix-issue referencia /version
/fix-issue 0107c
# Flow normal del fix-issue + "¿este cambio bumpea version de modulo/framework? si si → /version"

Decisiones de diseno

  1. No tocar API publica data_table::render(...). Refactor interno. Apps existentes no cambian su llamada.
  2. Aceptamos recompilacion total. El usuario lo dijo explicito. Coste de tiempo razonable a cambio de limpieza.
  3. Feature flag modules-v2 no protege codigo runtime — protege la "promesa" del sistema. Cuando flag flip, fn doctor modules debe pasar verde.
  4. /version NO hace commit. Solo edita archivos + stage. El commit final lo hace el flujo normal del fix-issue.
  5. Bloqueamos chat_ia. Si saltamos a otro modulo sin estandar, el caos se duplica.

Prerequisitos

  • Issue 0097 (modules infra inicial) — completado, esto es la evolucion.
  • fn doctor cpp-apps existe (0081) — reutilizamos paths.

Riesgos

  • Refactor 4777 LOC: alto riesgo de regresion visual/funcional. Mitigacion: smoke manual app-por-app + primitives_gallery --capture golden images antes/despues.
  • Apps que dependen indirectamente de lua/llm/join sin declararlo: post-0107d podrian fallar en link. Mitigacion: fn doctor uses-functions + recompilacion total como gate.
  • Codegen fail-loud rompe builds que hoy pasan con stub: deliberado, parte de la idea — pero hay que arreglar todos los app.md antes de mergear 0107e.

Notas

  • /version se referenciara desde /fix-issue con prompt: "este cambio toca modules/ o cpp/framework/? si si → run /version <path> [major|minor|patch] [reason] antes de commit".
  • Politica: bump de modulo SIN bump de version = bug. fn doctor modules lo detectara via diff hash de members + description vs ultima version registrada.