Cuando una funcion del registry parte su .cpp en varios TUs por testabilidad o separacion ImGui-vs-puro, cada TU adicional se registra como entrada propia con su .md en lugar de extender file_path para listar varios archivos. Aplicado a: - graph_labels_select_cpp_viz: helpers puros (compute_degrees + labels_select). - graph_viewport_selection_cpp_viz: clear/add/toggle/is_selected puros. - graph_types_cpp_viz: TU de update_bounds + find_node_by_user_data. graph_labels y graph_viewport actualizados para declarar las nuevas entradas en uses_functions. Razon detallada en docs/adr/0003 + regla actualizada en .claude/rules/uses_functions.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.5 KiB
ADR 0003 — TUs adicionales de una funcion C++ se registran como entrada propia
- Fecha: 2026-05-04
- Estado: accepted
Contexto
Algunas funciones C++ del registry necesitan dividir su implementacion en varios .cpp por motivos legitimos:
- Testabilidad sin ImGui:
graph_labelstienegraph_labels_draw(depende deImDrawList) ygraph_labels_select(logica pura). Mantenerlos en el mismo.cppobliga a los tests unitarios a linkear ImGui solo para ejercer la seleccion de candidatos. - Separacion impl/header:
graph_types.hdeclaraGraphData(tipo del registry, vive entypes/viz/graph_types.md). Sus metodos miembro (update_bounds,find_node_by_user_data) se implementan engraph_types.cpppara no inlinear en cada TU consumidor. - Separacion logica vs render:
graph_viewporttiene la mecanica de pan/zoom/click (ImGui) y la mecanica de seleccion (vectores + flags, sin ImGui). Tests unitarios de seleccion no deberian abrir ventana.
El indexer asume 1 .cpp = 1 .md — el campo file_path del frontmatter es un solo path. Si una funcion partia su impl en varios .cpp, los .cpp adicionales quedaban como huerfanos: el CMakeLists.txt los listaba para enlazar, pero no aparecian en registry.db. Resultado: una app nueva que consultaba el registry para reusar graph_labels recibia file_path: graph_labels.cpp y al compilar fallaba con undefined reference to graph_labels_select.
Esta sesion (2026-05-04) detecto 3 huerfanos asi:
cpp/functions/viz/graph_labels_select.cppcpp/functions/viz/graph_viewport_selection.cppcpp/functions/viz/graph_types.cpp
Decision
Cada TU adicional se registra como una entrada propia del registry con su .md. El parent declara la nueva entrada en uses_functions.
Estructura tras aplicar la decision:
cpp/functions/viz/
graph_labels.cpp ← parent: graph_labels_draw, graph_labels_draw_at (impure, ImGui)
graph_labels.md ← uses_functions: ["graph_labels_select_cpp_viz"]
graph_labels_select.cpp ← TU split: graph_compute_degrees, graph_labels_select (pure)
graph_labels_select.md ← entrada propia, purity: pure
graph_viewport.cpp ← parent: widget completo (impure, ImGui)
graph_viewport.md ← uses_functions: [..., "graph_viewport_selection_cpp_viz"]
graph_viewport_selection.cpp ← TU split: helpers de seleccion (pure)
graph_viewport_selection.md ← entrada propia, purity: pure
graph_types.h ← header del tipo (indexado en types/viz/graph_types.md)
graph_types.cpp ← TU impl de metodos miembro
graph_types.md ← entrada propia kind: function, purity: pure
Alternativas descartadas
- Extender
file_patha[paths](lista). Romperia la convencion vigente y obligaria a tocar parser, store, schema FTS, sync API y vista del dashboard. Ganancia: ninguna, las apps siguen necesitando la informacion para enlazar. notes:con instruccion de enlazar el TU adicional. Frágil: ningun parser lo enforce, las apps lo olvidan.- Un solo
.cppmacro con flags de compilacion. Mantiene los tests acoplados a ImGui, no resuelve el problema raiz. - Mover el TU puro a
core/. Rompe la cohesion del modulo (los helpers son intimos agraph_labels/graph_viewport) y crea ciclos de includes.
Consecuencias
- Nuevas funciones registradas:
graph_labels_select_cpp_viz,graph_viewport_selection_cpp_viz,graph_types_cpp_viz. cpp/functions/viz/graph_labels.mdycpp/functions/viz/graph_viewport.mddeclaran las nuevas entradas enuses_functions.graph_explorer/app.mddeclara explicitamente las 3 entradas en suuses_functions— antes solo declaraba el parent y el.cppadicional pasaba "de matute" viaCMakeLists.txt.- Convencion para futuros splits: si un parent añade un TU
<name>_<sufijo>.cppy exporta funciones nuevas, crear<name>_<sufijo>.mdconkind: function, su propia firma,purityreal (normalmentepureya que ese es el motivo del split), y dependencias correctas. El parent enlaza viauses_functions.
Aprendizaje
El registry funciona como API publica: lo que esta indexado define lo que las apps externas pueden consumir. Un .cpp que existe en disco pero no en la BD es invisible — y la unica garantia de "una app nueva sabra que enlazar" es que toda dependencia este declarada formalmente. El TU split no es un problema de organizacion del codigo: es un problema de superficie de API que tiene que reflejarse en el contrato del registry.