Extrae al registry funciones del proyecto interno footprint_aurgi: - core (6): slugify_ascii, normalize_for_join, cp_provincia_es, infer_provincia_from_cp, safe_read_csv_fallback, csv_to_parquet_duckdb - geo puras (7): haversine_km, point_in_ring, point_in_polygon, point_in_polygons_bbox, polygon_bbox, extent_with_padding, distance_bucket - geo I/O (4): load_geojson_polygons, load_boundary_gdf, add_basemap_osm, add_basemap_with_timeout - valhalla client (4): valhalla_route, valhalla_isochrone, valhalla_isochrones_async, valhalla_matrix_1_to_n - datascience stats (7): trimmed_mean, geometric_mean, detect_distribution_type, best_central_tendency, summary_stats, kde_density_levels, alpha_shape_concave_hull - datascience fuzzy (3): fuzzy_merge_adaptive (rapidfuzz), words_to_dataset, remove_words_from_column - datascience viz (2): plot_kde_2d, plot_heatmap_log - infra (4): compress_pdf_ghostscript, render_table_page_pdfpages, add_header_logo, osm2pgsql_ingest - pipelines (4): setup_geo_stack_docker, compute_centers_reachability, generate_isochrones_by_zone, count_points_per_zone - types geo (4): LonLat, BBox, IsochroneRequest, Centro Incluye: - apps/footprint_geo_stack/ (PostGIS + Martin + Valhalla via docker-compose) - 131/132 tests pasan (1 skip esperado: osm2pgsql en PATH) - Issue tracker dev/issues/0052-footprint-aurgi-extraction.md - Atribucion uniforme: source_repo internal:footprint_aurgi, source_license internal-aurgi - Build con 9 agentes en paralelo (8 wave 1 + 1 wave 2 pipelines) Tambien commitea trabajo previo no commiteado: aggregate_extraction_results, chunk_with_overlap, clean_pdf_text, merge_entity_aliases, extract_graph_gliner2, extract_relations_mrebel, extract_triples_spacy_es, gliner2/mrebel/marianmt/rebel/spacy_es load_model, parse_rebel_output, translate_es_to_en, issue 0050/0051. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
18 KiB
Changelog
Todos los cambios notables de fn_registry se documentan aquí.
Formato basado en Keep a Changelog. Al no haber releases semver formales, las entradas se ordenan por fecha.
Para contexto detallado del trabajo diario ver docs/diary/. Para decisiones arquitecturales ver docs/adr/.
[Unreleased]
2026-05-04
Added
cpp/functions/viz/graph_labels_select(graph_labels_select_cpp_viz, pure) — TU separado degraph_labelscon los helpers purosgraph_compute_degreesygraph_labels_select(frustum cull + always_for_* + top-N porsize * (degree+1)). Vive en su propio archivo para que los tests unitarios lo cubran sin abrir ImGui.cpp/functions/viz/graph_viewport_selection(graph_viewport_selection_cpp_viz, pure) — TU separado degraph_viewportconclear_selection,is_selected,add_to_selection,toggle_selection. Mantienen sincronizadosstate.selectionynodes[i].flags & NF_SELECTED.cpp/functions/viz/graph_types(graph_types_cpp_viz, pure) — TU de implementacion deGraphData::update_bounds()yGraphData::find_node_by_user_data(). Pareja obligatoria del header del tipo (graph_types.hindexado entypes/viz/).cpp/apps/chart_demo/app.md— la demo de primitivos viz (line/scatter/bar/heatmap) ahora aparece en el registry comochart_demo_cpp_viz.cpp/apps/shaders_lab/app.md— el live GLSL playground con DAG ahora tieneapp.mdpropio (antes solo existia entrada legacy en BD sin.mden disco).
Changed
registry/indexer.go— el indexer ahora escanea tambien<lang>/apps/*/app.md(mismo patron que ya usaba para<lang>/functions/y<lang>/types/). Antes solo veiaapps/yprojects/*/apps/— las apps encpp/apps/quedaban invisibles../fn indexreporta 17 apps (antes 15).cpp/functions/viz/graph_labels.md—signaturereducida agraph_labels_drawygraph_labels_draw_at(los helpers puros pasan a entrada propia).uses_functionsapunta a la nueva entradagraph_labels_select_cpp_viz.cpp/functions/viz/graph_viewport.md—uses_functionsañadegraph_viewport_selection_cpp_viz.projects/osint_graph/apps/graph_explorer/app.md—uses_functionssincronizado conCMakeLists.txt: ahora declara las 23 funciones del registry que enlaza (antes 15). Añadidas:graph_viewport_selection,graph_labels_select,graph_types,graph_spatial_hash,button,icon_button,badge,empty_state.projects/fn_monitoring/apps/registry_dashboard/app.md—uses_functionssincronizado conCMakeLists.txt(21 deps, antes 9). Añadidas:badge,button,empty_state,icon_button,modal_dialog,page_header,process_runner,process_state_machine,select,text_input,toast,toolbar,tree_view. Removido:fps_overlay(vive enfn_framework, no se declara).
Decisions
- ADR
0003-orphan-tu-as-separate-function-entry.md— cuando una funcion del registry necesita partir su.cppen varios TUs por testabilidad o separacion ImGui-vs-puro, cada TU adicional se registra como entrada propia con su.mden lugar de extenderfile_pathpara listar varios archivos. El parent declara la nueva entrada enuses_functions. Razon: el indexer asume1 .cpp = 1 .md; unfile_pathmulti-archivo rompe la convencion y deja apps nuevas sin saber que TUs enlazar.
Added — sesion NER+RE para graph_explorer (tarde, 980 → 990 funciones)
18 funciones nuevas sobre el ecosistema NER+RE, en dos rondas de fn-constructor:
Ronda 1 — extraccion de relaciones (mREBEL/REBEL/MarianMT):
python/functions/datascience/parse_rebel_output.py(pure) — parser wire<triplet>REBEL/mREBEL.python/functions/datascience/align_relations_to_entities.py(pure) — string-match aligner.python/functions/datascience/mrebel_load_model.py(impure, CC BY-NC-SA 4.0 — NO comercial).python/functions/datascience/mrebel_base_load_model.py(impure, misma licencia).python/functions/datascience/rebel_load_model.py(impure, Apache 2.0, EN-only).python/functions/datascience/marianmt_es_en_load_model.py(impure) — Helsinki-NLP/opus-mt-es-en.python/functions/datascience/translate_es_to_en.py(impure) — wrapper traduccion frase a frase.python/functions/datascience/extract_relations_mrebel.py(impure) — pipeline mREBEL frase-a-frase + alineamiento.- 21 tests pytest verdes.
Ronda 2 — pipeline GLiNER2 + OpenIE schema-less + composicion (tarde):
python/functions/core/clean_pdf_text.py(pure) — limpia artefactos PyPDF2.python/functions/core/chunk_with_overlap.py(pure) — sliding window con avance forzado.python/functions/core/merge_entity_aliases.py(pure) — coreferencia normalize+substring.python/functions/core/filter_relations_by_entity_types.py(pure) — post-filter typed.python/functions/core/aggregate_extraction_results.py(pure) — dedupe + Counter sobre N chunks.python/functions/datascience/gliner2_load_model.py(impure, Apache 2.0) —fastino/gliner2-large-v1.python/functions/datascience/extract_graph_gliner2.py(impure) — wrapper schema + threshold + include_confidence.python/functions/datascience/spacy_es_load_model.py(impure) —es_core_news_mdcacheado.python/functions/datascience/extract_triples_spacy_es.py(impure) — OpenIE schema-less ES por reglas de dependencia (verbo del texto = predicado).python/functions/pipelines/extract_graph_from_text.py(impure pipeline) — composicion E2E: chunk → extract_graph_gliner2 (×N) → aggregate → filter typed → merge aliases → grafo final.- 39 tests pytest verdes.
Added — analysis gliner_glirel_tuning
projects/osint_graph/analysis/gliner_glirel_tuning/ — investigacion empirica de modelos NER/RE. 9 notebooks ejecutados:
| # | Notebook | Hallazgo clave |
|---|---|---|
| 01 | 01_gliner_glirel_tuning.ipynb |
Calibracion de thresholds GLiNER+GLiREL |
| 02 | 02_e2e_spanish_graph.ipynb |
E2E texto ES — descubrimiento del fail de GLiREL en castellano |
| 03 | 03_mrebel_vs_glirel.ipynb |
mREBEL gana a GLiREL pero CC BY-NC-SA |
| 04 | 04_gliner2_winner.ipynb ⭐ |
GLiNER2 (Apache 2.0, NER+RE joint, 340M) elegido como motor principal |
| 05 | 05_long_text_and_pdf.ipynb |
Pipeline PDF E2E sobre politica_proteccion_datos.pdf (BBVA, 89.882 chars) |
| 06 | 06_improvements.ipynb |
Threshold 0.3 (vs default 0.5) → +187% relaciones; coref reduce 18% aislados |
| 07 | 07_nuextract_vs_gliner2.ipynb |
NuExtract GPU 2.6× mas lento, calidad similar — descartado por defecto |
| 08 | 08_improving_gliner2.ipynb |
snake_case verbal labels + post-filter typed = mejor combo |
| 09 | 09_spacy_es_openie.ipynb |
spaCy ES dep-rules: schema-less, predicado = verbo del texto |
Added — vault osint_nlp_models
projects/osint_graph/vaults/osint_nlp_models (symlink a ~/vaults/osint_nlp_models/):
models/— fichas de gliner, glirel, mrebel, gliner2, candidates a probar.decisions/— 3 ADRs cortos del 2026-05-04 (mrebel-over-glirel mañana, gliner2-over-mrebel tarde, license-constraint).benchmarks/corpus_v1.md+results_log.csv(15 filas de experimentos).test_documents/politica_proteccion_datos.pdf(PDF de BBVA copiado para reproducibilidad).
Added — playground HTML
projects/osint_graph/analysis/gliner_glirel_tuning/playground/:
server.py— FastAPI con GLiNER2 cacheado, endpointsGET /(HTML) yPOST /extract(texto → grafo).index.html— UI: textarea, KPIs (nodos/aristas/tiempo), grafo Sigma.js, JSON exportable.static/sigma.min.js+graphology.umd.min.js(servidos localmente para evitar bloqueo CDN por extensiones tipo MetaMask/SES).
Stack aplicado por el server:
- snake_case verbal labels (
works_at,ceo_of,headquartered_in,agreement_with...) - threshold 0.3 (configurable)
- chunking automatico > 1500 chars
- post-filter typed (
(person, organization)validos por relacion) - coreferencia normalize+substring
- layout server-side via
networkx.spring_layout - render Sigma.js (sin fisica → sin loops de ResizeObserver)
Added — issues
dev/issues/0050-jupyter-exec-collab-client-failure.md— bugjupyter_execcon cliente colaborativo + workaround documentado.projects/osint_graph/apps/graph_explorer/issues/0041-split-confidence-thresholds.md— splitconfidence_thresholdenentity_threshold+relation_threshold.projects/osint_graph/apps/graph_explorer/issues/0042-gliner2-unified-extractor.md⭐ — sustituir GLiREL por GLiNER2 enextract_graph_hybrid. Reemplaza 0042-mrebel.projects/osint_graph/apps/graph_explorer/issues/0042-mrebel-relation-extractor.md.superseded— version mREBEL del 0042 archivada al ganar GLiNER2.
Changed
cpp/CMakeLists.txt—_GE_DIRy_DASH_DIRsobreescribibles via-D<...>=<path>para builds en worktrees (commite72d6364). Habilitaparallel-fix-issuessobre apps C++.python/functions/datascience/glirel_load_model.py— workaround compathuggingface_hub1.x: classmethod monkey-patch idempotente para inyectarproxies/resume_downloadque el HF nuevo dejo de pasar (commit3b3378cf).- Sub-repo
dataforge/graph_explorermaster local: merges--no-ffdeissue/0035e-polish-and-tests(commitf614a51) +issue/0013-paste-extract-panel(commit2a49c2b). 125/125 tests pytest verdes. Sin push aun — pendiente confirmacion + validacion Windows.
Fixed (bugs encontrados + raiz + fix)
| Bug | Raiz | Fix |
|---|---|---|
chunk_with_overlap bucle infinito |
Frase mas larga que max_chars, no avanzaba i, OOM-killed por overlap acumulado |
Avance forzado: meter al menos UNA frase aunque exceda max_chars |
| NuExtract degenera en texto largo | Sin repetition_penalty, decoder entra en bucle de tokens repetidos hasta agotar 2048 max_new_tokens |
repetition_penalty=1.15 + chunking obligatorio (179/179 chunks parsed OK tras fix) |
NuExtract AutoProcessor.from_pretrained rota en transformers 5.x |
Sub-processor de video tira TypeError: argument of type 'NoneType' is not iterable (Qwen2-VL) |
Bypass: AutoTokenizer + AutoModelForImageTextToText directamente |
| Vis-network ResizeObserver loop spam (en SES/MetaMask) | Vis-network usa physics simulation → ResizeObserver dispara warnings amplificados por SES | Migrar a Sigma.js + layout server-side via networkx.spring_layout (sin fisica frontend) |
jupyter_exec append HTTP 405 |
jupyter_nbmodel_client espera collab WebSocket Y.js, no soportado al 100% por jupyter-collaboration nuevo |
Documentado en issue 0050; workaround actual: build_notebook scripts con nbformat + nbconvert --execute |
| Kernel startup shadows pip packages | 00_fn_registry.py añade cada subdir de python/functions/ a sys.path top-level → bigquery/datasets.py shadows HF datasets package needed by transformers |
Workaround per-notebook: sys.path = [p for p in sys.path if not p.startswith(_pf+'/')] + añadir solo el padre. Issue futuro pendiente. |
Decisions — vault ADRs
| Decision | Razon |
|---|---|
GLiNER2 (Apache 2.0) sustituye a GLiREL en extract_graph_hybrid |
6/8 relaciones correctas vs 0/1 de GLiREL en es_corporate_short, 1.18s vs 22s de mREBEL, NER+RE en una pasada |
| mREBEL queda como fallback (no comercial) | 4/5 correctas pero CC BY-NC-SA 4.0 + 25× mas lento |
| spaCy ES dep-rules para OpenIE schema-less | Predicado = verbo del texto (querer, abrazar), 5ms/frase, sin alucinaciones |
Threshold 0.3 (vs default 0.5) sweet spot |
+187% relaciones manteniendo precision; 0.2 mete +22% entidades dudosas |
| Coreferencia normalize+substring + post-filter typed = gratis y decisivos | Coref −18% aislados; post-filter elimina Madrid president_of Persona |
| Translate ES→EN + triplet-extract EN NO vale la pena | Pierdes verbos del texto (querer → loves), +500ms-1s, +300MB MarianMT, riesgo nombres propios |
2026-04-28
Added
cpp/functions/core/app_about(app_about_cpp_core) — ventana flotante About conabout_window_set_info(project, version, description),about_window_menu_item("About...")yabout_window_render(). Render automatico viafn::run_app(cableado encpp/framework/app_base.cpp).bash/functions/infra/ensure_repo_synced(ensure_repo_synced_bash_infra) — pipeline idempotente que componegitea_create_repo+gitea_push_directory: crea repo Gitea si falta, inicializa.gitlocal si falta, commitea cambios pendientes y pushea. Defaults: ownerdataforge, branchmaster.analysis.mdpara 6 analyses que estaban en disco pero sin indexar:agent_coding_eval,estudio_embeddings,estudio_mercados,ontology_graph,pruebas_jupyter,retrieving_graphs. Ahora./fn indexreporta 8 analyses (antes 2).- Repos
dataforge/<name>creados en Gitea para apps y analyses que no estaban subidos:agents_and_robots,element_matrix_chat,deploy_server,shaders_lab,voice_guide,agent_coding_eval,ontology_graph,turismo_spain. Cada uno con.gitignoreapropiado para excluir binarios,.venv/,node_modules/,.jupyter*,operations.db*.
Changed
cpp/functions/core/app_menubar: el item top-levelSettings...pasa a ser unBeginMenu("Settings")con dos subitems:Settings...(ventana deapp_settings) yAbout...(nuevo, ventana deapp_about). Las apps que usanfn_ui::app_menubar(nullptr, 0, nullptr)heredan el cambio sin tocar nada.projects/fn_monitoring/apps/registry_dashboard/main.cpp: cableafn_ui::about_window_set_info("fn_registry Dashboard", "0.2.0", "...")antes defn::run_app. TablaAppsgana columnaGitcon valoresremote(repo_url poblado),local(.git/ presente) o-.data.h/data.cpp/data_http.cppdel dashboard:AppRowextendido conrepo_urlydir_path.- 10 repos migrados de branch
mainamasterpara unificar convencion:apps/{docker_tui,fuzzygraph,metabase_registry,pipeline_launcher,rapid_dashboards,script_navegador},analysis/{estudio_embeddings,estudio_mercados,pruebas_jupyter,retrieving_graphs}. Default branch en Gitea actualizado via API (PATCH /repos/{owner}/{repo}con{"default_branch":"master"}), branchmainremota borrada. git config --global init.defaultBranch masterpara que los proximosgit initsean consistentes./full-git-push: descubre apps/analyses sin.gity ofrece inicializarlos conensure_repo_syncedautomaticamente. Excluyesubrepos/para evitar duplicacion (mirrors upstream)./full-git-pull: trasfn sync, segunda pasada que clona losdataforge/<name>registrados enapps/analysisque no existan localmente — soluciona el "no pude recuperar la app en el otro PC".bash/functions/infra/ensure_repo_synced.sh: localiza dependencias viaFN_REGISTRY_INFRA_DIRoFN_REGISTRY_ROOT, robusto a sourcing desde zsh/bash.
Fixed
projects/fn_monitoring/apps/sqlite_api/handlers.go|main.go|handlers_test.go+ nuevoshandlers_mutations.goyhandlers_projects.go: cableados endpointsPOST /add_app|add_analysis|add_vault|reindexyGET /projectspara que el dashboard pueda crear artefactos y navegar projects desde la actions bar (estado pendiente de varios dias en uncommitted, ahora versionado endataforge/sqlite_api).- Bug operativo en
sqlite_api(Windows):SO_RCVTIMEOse pasaba comostruct timevalcuando Windows esperaDWORD ms→ timeout efectivo de 5 ms. Ya documentado enapp.mddel dashboard.
2026-04-24
Added
- 6 funciones
bash/infra/systemd_local_*(install_unit, enable, start, restart, status, uninstall) para gestionar servicios systemd del sistema desde el registry (complementa las versiones remotas SSH ya existentes). - Pipeline
install_systemd_service_bash_pipelinesque compone las anteriores: genera unit file + install + enable + start + status. - Servicio systemd
sqlite_api.serviceinstalado y habilitado en aurgi-pc — arranque automático al iniciar WSL en127.0.0.1:8484. projects/fn_monitoring/launcher.sh— launcher del dashboard (arranca API si no está + lanza ventana + cleanup).- Regla
.claude/rules/kiss.md— filosofía KISS para proyectos y apps. - Documentación ADR en
docs/adr/con plantilla y ADR 0001 (experimento GitButler). - Diario en
docs/diary/+ slash command/entrada_diariopara añadir entradas. CHANGELOG.md(este archivo).- Submódulo
cpp/vendor/glfwre-registrado con path limpio (antes heredado con path absoluto/home/lucas/...). - aurgi-pc registrado en el server centralizado (
registry.organic-machine.com) con 18 pc_locations.
Changed
registry.dbahora está gitignorada. Es regenerable confn index+ completable confn sync. Evita conflictos entre ramas y PCs.sqlite_apiahora se distribuye como binario compilado (projects/fn_monitoring/apps/sqlite_api/sqlite_api) en lugar dego runal vuelo.
Fixed
http_client.cppdel dashboard: añadido#include <cstdint>requerido por mingw-w64 para cross-compile Windows (g++ Linux lo incluía transitivamente).registry_dashboard.exe(Windows) ya no abre ventana de consola al lanzarse — enlazado como GUI app (WIN32_EXECUTABLE TRUE/-mwindows).
Added (design system C++)
cpp/functions/core/tokens— design tokens para dashboards ImGui (colors, spacing, radius, font_size) inspirados en@fn_library(Mantine v9). Paleta dark + indigo primary.apply_dark_theme()aplica los tokens alImGuiStyleglobal.cpp/functions/core/badge— etiqueta inline con 6 variantes (Default/Success/Warning/Error/Info/Outline). Equivalente a<Badge>de@fn_library.cpp/functions/core/empty_state— placeholder centrado para tablas/listas vacías.cpp/functions/core/page_header— header de página con título/subtítulo + hueco para acciones + separator.registry_dashboardmigrado a los nuevos componentes:page_header_begin/enden el header,empty_stateen las 4 tablas cuando están vacías,apply_dark_theme()al primer frame. Sin hardcode de colores disperso.systemd_local_{enable,start,restart}: stdout desystemctlredirigido a stderr para no contaminar el JSON capturado por el pipeline..gitmodules: entry fantasmacpp/vendor/glfwcon path absoluto/home/lucas/...que bloqueabagit submodule statusy el cross-compile Windows.
Removed
- Integración de GitButler de Claude Code — binario
~/.local/bin/but, plugingitbutler-tools, skill.claude/skills/gitbutler/, hooks ensettings.json, ramasgitbutler/*+e-branch-*, estado interno.git/gitbutler/. Ver ADR 0001 para motivos.