Files
fn_registry/CHANGELOG.md
T
egutierrez ca1bf5a59b feat(infra): auto-commit con 29 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 02:06:44 +02:00

273 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
Todos los cambios notables de `fn_registry` se documentan aquí.
Formato basado en [Keep a Changelog](https://keepachangelog.com/es-ES/1.1.0/). 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-14
### Added
- **Issue 0086 — Monitor tab del `registry_dashboard`** (sub-repo `dataforge/registry_dashboard`). Pestaña `Monitor` primera y por defecto del TabBar, landing del bucle reactivo construir->ejecutar->recopilar->analizar->mejorar.
- 7 KPIs (Calls / MCP / Reg % / Errors / Violations / Copies / Versions) filtradas por ventana temporal (1h/24h/7d/30d/All).
- Sub-tab `Recent Executions` con columnas When/Function/Tool/ms/OK/Error. Columna Function muestra `$ <snippet>` en gris cuando `function_id` vacio, hover tooltip con comando completo. Checkbox `Only registry functions` filtra por `function_id != ''`.
- Sub-tab `Failed Functions` (5a) — subset filtrado a registry-functions fallidas, columnas When/Function/Tool/Error class/Error snippet, function_id en rojo.
- Live scatter `duracion (ms)` vs `time`: eje X auto-scroll a `now`, ventana configurable (1m/5m/15m/1h/6h) independiente del filtro de KPIs, eje Y dinamico `0..max(visible)+500ms`. Hora local (`UseLocalTime`). Series ok/error en verde/rojo. Hover sobre punto = tooltip Function/Tool/Duration/Error.
- Indicador `live`/`offline` con timestamp del ultimo evento WS.
- **WebSocket live stream sqlite_api -> registry_dashboard** (sub-repo `dataforge/sqlite_api`). Endpoint `GET /api/events/call_monitor`. Hub global con subscribers; ticker arranca solo con >=1 subscriber (cero overhead si nadie mira). Cliente recibe snapshot inicial (KPIs + 100 ultimas filas + watermark) y luego deltas `id > watermark`. Cliente puede mandar `{watermark: N}` para resumir tras reconexion.
- **WS client C++** hand-rolled RFC6455 en `ws_client.{h,cpp}` (~330 LOC) en el dashboard. Localhost-only (no TLS). Thread propio, reconnect exponencial 0.5s->8s, FIN/text/ping/pong/close handling, queue thread-safe drenada cada frame.
- **Migration 007 `command_snippet` en `calls`** (`projects/fn_monitoring/apps/call_monitor/migrations/007_calls_command_snippet.sql`). Aditiva, idempotente. Llena por hook `hook_call_monitor.sh` solo cuando `function_id == ''`. Redactado de `password=`/`token=`/`secret=`/`api_key=`/`bearer=`. Truncado 200 chars.
- **Issue 0087 — Capability Discovery Acceleration**. Modelo 5 capas + 7 piezas (ver `dev/issues/0087-*.md`).
- **`fn match`** (`cmd/fn/match.go`) — subcommand fuzzy-FTS5 que dado un comando devuelve top-N funciones del registry candidates. Latencia 6-7ms. Output JSON con `score` (normalizado top=1.0) + `raw_score` (absoluto pre-normalizacion) + `high_confidence` gate (`raw_score >= 4.0 AND top1.raw/top2.raw > 1.5`).
- **`fn doctor capabilities --emit-claude-md`** (`cmd/fn/doctor.go` + `functions/infra/emit_capabilities_md.go`) — emite bloque markdown con secciones TOP 20 (por `calls_total`), Fresh 7d, Pipelines top 5. Fallback si `call_monitor.operations.db` ausente.
- **`call_monitor sequences --detect [--propose]`** (`projects/fn_monitoring/apps/call_monitor/sequences.go` + `migrations/006_function_sequences.sql`). Detecta secuencias A->B(->C) en `calls` (same session, gap < 30s, occ >= 5, sess >= 2, success_rate >= 0.9) y abre proposals `new_pipeline` automaticamente.
- **Hook `PreToolUse` `hook_fn_match.sh`** — denylist + `fn match` con timeout 0.2s. Inyecta `<system-reminder>FUZZY-MATCH: USE ./fn run <id>` cuando confidence alta. Latencia 113ms trigger / 32ms denylist. Registrado en `.claude/settings.local.json` (Bash matcher).
- **Hook `UserPromptSubmit` `hook_capabilities_inject.sh`** — cache 1h en `~/.cache/fn_registry/capabilities.txt`. Emite JSON `hookSpecificOutput.additionalContext` con linea compacta `CAPABILITIES: TOP / FRESH / PIPELINES`. Latencia cold 33ms / warm 18ms.
- **Timer systemd user** `call_monitor_sequences.timer` (OnCalendar 0/6h) + `.service` oneshot ejecutando `call_monitor sequences --detect --propose --report`. Versionado en `projects/fn_monitoring/apps/call_monitor/systemd/`.
- **3 funciones nuevas grupo `cpp-windows`** + pagina madre `docs/capabilities/cpp-windows.md`:
- `launch_cpp_app_windows_bash_infra``cmd.exe`/`PowerShell Start-Process` para lanzar exe en Windows desde WSL2.
- `is_cpp_app_running_windows_bash_infra``tasklist.exe /FI` con exit code 0/1 + stdout `RUNNING: PID=N MEM=K` o `NOT_RUNNING`.
- `redeploy_cpp_app_windows_bash_pipelines` — pipeline build? + deploy + launch + verify en 1 invocacion. Reemplaza ~6 commands manuales.
- **ADR 0004 `docs/adr/0004-telemetry-driven-capability-growth.md`** — formaliza el bucle telemetria -> proposal -> capability group -> discovery acceleration como motor de crecimiento del registry.
- **Regla `.claude/rules/function_growth_and_self_docs.md`** (entry #30 en `INDEX.md`) — contrato `.md` autosuficiente (Ejemplo + Cuando usarla + Gotchas + Growth log) + crecimiento del registry por promocion de composiciones, NO por inflado de funciones individuales.
### Changed
- **`.claude/CLAUDE.md` Norte ampliado** — 4o objetivo `PROMOVER COMPOSICIONES A PIPELINES` (el registry crece por composicion, no por inflado). Linea sobre auto-discovery zero-second-lookup.
- **`.claude/rules/registry_calls.md`** — clausula nueva: hooks e infraestructura de telemetria (`fn_match`, `fn doctor`, `call_monitor`) pueden leer `registry.db` directo con conexion read-only. NO sujeto a regla MCP-first (no son acciones del agente).
- **`/fn_claude` command** mejorado con objetivos del Monitor + interpretacion de `FUZZY-MATCH` hint + `CAPABILITIES` line + threshold semantica.
### Fixed
- **`launch_cpp_app_windows` quoting bug** — `cmd.exe /c "cd /d \"$dir\" && start ..."` rompia con paths Windows (el `\"` final se interpretaba como escape de comilla -> string sin cerrar -> "Windows cannot find \\"). Fix: reescribir a `powershell.exe -Command "Start-Process -FilePath ... -WorkingDirectory ..."` (single-quote PowerShell es literal, sin procesar `\` ni `$`).
- **`fn match high_confidence` siempre true** — debido a normalizacion `top=1.0`. Fix: añadir `raw_score` preservado pre-normalizacion + gate dual `raw_score >= 4.0 AND top1.raw/top2.raw > 1.5`. Threshold 4.0 tuneado contra 14 patrones del analysis `domain_coverage_gaps` (~93% precision).
## 2026-05-07
### Added
- **`fn doctor` CLI** (`cmd/fn/doctor.go`) — entrypoint unico read-only para diagnostico del registry y artefactos. Subcomandos: `artefacts` (git/venv/app.md/upstream), `services` (apps tag service + systemctl + puerto), `sync` (drift `pc_locations` BD vs disco), `uses-functions` (imports reales vs declarados en `app.md`), `unused` (funciones sin consumidores). Flag `--json` para agentes/scripts. Cada subcomando es wrapper fino sobre una funcion del registry.
- `.claude/rules/fn_doctor.md` — regla 23 en `INDEX.md`. Documenta cuando usar, mapeo subcomando → funcion del registry, y acciones derivadas (que hacer cuando reporta un drift).
- `bash/functions/infra/backup_sqlite_db` (`backup_sqlite_db_bash_infra`, **impure**) — snapshot atomico de SQLite via `VACUUM INTO`. Mas seguro que `cp` con escrituras concurrentes.
- `bash/functions/infra/rotate_backups` (`rotate_backups_bash_infra`, **impure**) — retention rsnapshot-style `daily.N/weekly.M/monthly.K`.
- `bash/functions/infra/wait_for_http` (`wait_for_http_bash_infra`, **impure**) — poll URL hasta 2xx con timeout, util en deploys/smoke tests.
- `bash/functions/infra/wait_for_port` (`wait_for_port_bash_infra`, **impure**) — poll TCP host:puerto. Usa `nc` o `/dev/tcp` builtin (sin deps).
- `bash/functions/infra/port_kill` (`port_kill_bash_infra`, **impure**) — mata proceso(s) escuchando un puerto. Idempotente, fallback `KILL` tras `TERM`.
- `bash/functions/infra/tail_journal` (`tail_journal_bash_infra`, **impure**) — wrapper `journalctl` con auto-deteccion `--user` vs sistema, prioridad y `--since`.
- `bash/functions/infra/pre_commit_hook_install` (`pre_commit_hook_install_bash_infra`, **impure**) — instala hook que llama `scan_secrets_in_dirty_bash_cybersecurity` antes de cada commit. Idempotente con marca `fn_registry-pre-commit-v1`.
- `functions/infra/notify_telegram` (`notify_telegram_go_infra`, **impure**) — envia mensaje a chat Telegram via Bot API. Trunca >4096 chars.
- `functions/infra/artefact_doctor` (`artefact_doctor_go_infra`, **impure**) — audita salud de cada app/analysis: dir existe, `.git` presente, manifest parseable, `.venv` valido (analyses), upstream configurado.
- `functions/infra/services_status` (`services_status_go_infra`, **impure**) — apps con tag `service` + `systemctl is-active` (user/system) + puerto declarado en notes/description + check TCP localhost.
- `functions/infra/pc_locations_drift` (`pc_locations_drift_go_infra`, **impure**) — detecta drift `pc_locations` BD vs disco para el PC actual (`~/.fn_pc`). Tres tipos: `missing_on_disk`, `untracked_on_disk`, `status_should_be_active`.
- `functions/infra/audit_uses_functions` (`audit_uses_functions_go_infra`, **impure**) — para cada app Go/Py compara imports reales contra `uses_functions` del `app.md`. Reporta `missing_in_app_md` y `unused_in_app_md`. Heuristica documentada (puede dar falsos positivos en `unused`).
- `functions/infra/find_unused_functions` (`find_unused_functions_go_infra`, **impure**) — funciones del registry sin consumidores en otras funciones, apps o analyses. Pipelines sin tag `launcher` tambien aparecen.
- `bash/functions/pipelines/backup_all` (`backup_all_bash_pipelines`, **impure**, tag `launcher`) — orquesta `backup_sqlite_db` + `rotate_backups` sobre `registry.db`, cada `apps/*/operations.db`, y rsync `--link-dest` para vaults declarados en `projects/*/vaults/vault.yaml`.
### Changed
- `.claude/CLAUDE.md` — seccion CLI ampliada con comandos `fn doctor [subcommand] [--json]` y enlace a la regla.
- `.claude/rules/INDEX.md` — anadida fila 23 para `fn_doctor.md`.
### Fixed
- `functions/infra/pc_locations_drift.go``filepath.Join(absoluto, absoluto)` producia paths corruptos cuando `dir_path` ya era absoluto (caso comun: filas `pc_locations` traen path absoluto al disco del PC). Fix: chequear `filepath.IsAbs` antes de unir. Sintoma previo: todos los artefactos reportados como `missing_on_disk` aunque existieran.
- `go.mod``golang.org/x/net` movido a deps directas (`go mod tidy` tras anadir `notify_telegram`).
### Notes
- Hallazgo de la primera ejecucion `fn doctor uses-functions`: 7/12 apps con drift real (`auto_metabase`, `dag_engine`, `deploy_server`, `docker_tui`, `kanban`, `metabase_registry`, `script_navegador`). Pendiente sincronizar sus `app.md` con los imports reales en sesion futura.
- `fn doctor unused` muestra muchas funciones core sin consumidores aun (`compose2_go_core`, `curry2_go_core`, etc.). Esperado: el registry crece antes que las apps que las consuman.
## 2026-05-04
### Added
- `cpp/functions/viz/graph_labels_select` (`graph_labels_select_cpp_viz`, **pure**) — TU separado de `graph_labels` con los helpers puros `graph_compute_degrees` y `graph_labels_select` (frustum cull + always_for_* + top-N por `size * (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 de `graph_viewport` con `clear_selection`, `is_selected`, `add_to_selection`, `toggle_selection`. Mantienen sincronizados `state.selection` y `nodes[i].flags & NF_SELECTED`.
- `cpp/functions/viz/graph_types` (`graph_types_cpp_viz`, **pure**) — TU de implementacion de `GraphData::update_bounds()` y `GraphData::find_node_by_user_data()`. Pareja obligatoria del header del tipo (`graph_types.h` indexado en `types/viz/`).
- `cpp/apps/chart_demo/app.md` — la demo de primitivos viz (line/scatter/bar/heatmap) ahora aparece en el registry como `chart_demo_cpp_viz`.
- `cpp/apps/shaders_lab/app.md` — el live GLSL playground con DAG ahora tiene `app.md` propio (antes solo existia entrada legacy en BD sin `.md` en 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 veia `apps/` y `projects/*/apps/` — las apps en `cpp/apps/` quedaban invisibles. `./fn index` reporta 17 apps (antes 15).
- `cpp/functions/viz/graph_labels.md``signature` reducida a `graph_labels_draw` y `graph_labels_draw_at` (los helpers puros pasan a entrada propia). `uses_functions` apunta a la nueva entrada `graph_labels_select_cpp_viz`.
- `cpp/functions/viz/graph_viewport.md``uses_functions` añade `graph_viewport_selection_cpp_viz`.
- `projects/osint_graph/apps/graph_explorer/app.md``uses_functions` sincronizado con `CMakeLists.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_functions` sincronizado con `CMakeLists.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 en `fn_framework`, no se declara).
### Decisions
- ADR `0003-orphan-tu-as-separate-function-entry.md` — cuando una funcion del registry necesita partir 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. El parent declara la nueva entrada en `uses_functions`. Razon: el indexer asume `1 .cpp = 1 .md`; un `file_path` multi-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_md` cacheado.
- `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, endpoints `GET /` (HTML) y `POST /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:
1. snake_case verbal labels (`works_at`, `ceo_of`, `headquartered_in`, `agreement_with`...)
2. threshold 0.3 (configurable)
3. chunking automatico > 1500 chars
4. post-filter typed (`(person, organization)` validos por relacion)
5. coreferencia normalize+substring
6. layout server-side via `networkx.spring_layout`
7. render Sigma.js (sin fisica → sin loops de ResizeObserver)
### Added — issues
- `dev/issues/0050-jupyter-exec-collab-client-failure.md` — bug `jupyter_exec` con cliente colaborativo + workaround documentado.
- `projects/osint_graph/apps/graph_explorer/issues/0041-split-confidence-thresholds.md` — split `confidence_threshold` en `entity_threshold` + `relation_threshold`.
- `projects/osint_graph/apps/graph_explorer/issues/0042-gliner2-unified-extractor.md` ⭐ — sustituir GLiREL por GLiNER2 en `extract_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_DIR` y `_DASH_DIR` sobreescribibles via `-D<...>=<path>` para builds en worktrees (commit `e72d6364`). Habilita `parallel-fix-issues` sobre apps C++.
- `python/functions/datascience/glirel_load_model.py` — workaround compat `huggingface_hub` 1.x: classmethod monkey-patch idempotente para inyectar `proxies`/`resume_download` que el HF nuevo dejo de pasar (commit `3b3378cf`).
- Sub-repo `dataforge/graph_explorer` master local: merges `--no-ff` de `issue/0035e-polish-and-tests` (commit `f614a51`) + `issue/0013-paste-extract-panel` (commit `2a49c2b`). 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 con `about_window_set_info(project, version, description)`, `about_window_menu_item("About...")` y `about_window_render()`. Render automatico via `fn::run_app` (cableado en `cpp/framework/app_base.cpp`).
- `bash/functions/infra/ensure_repo_synced` (`ensure_repo_synced_bash_infra`) — pipeline idempotente que compone `gitea_create_repo` + `gitea_push_directory`: crea repo Gitea si falta, inicializa `.git` local si falta, commitea cambios pendientes y pushea. Defaults: owner `dataforge`, branch `master`.
- `analysis.md` para 6 analyses que estaban en disco pero sin indexar: `agent_coding_eval`, `estudio_embeddings`, `estudio_mercados`, `ontology_graph`, `pruebas_jupyter`, `retrieving_graphs`. Ahora `./fn index` reporta 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 `.gitignore` apropiado para excluir binarios, `.venv/`, `node_modules/`, `.jupyter*`, `operations.db*`.
### Changed
- `cpp/functions/core/app_menubar`: el item top-level `Settings...` pasa a ser un `BeginMenu("Settings")` con dos subitems: `Settings...` (ventana de `app_settings`) y `About...` (nuevo, ventana de `app_about`). Las apps que usan `fn_ui::app_menubar(nullptr, 0, nullptr)` heredan el cambio sin tocar nada.
- `projects/fn_monitoring/apps/registry_dashboard/main.cpp`: cablea `fn_ui::about_window_set_info("fn_registry Dashboard", "0.2.0", "...")` antes de `fn::run_app`. Tabla `Apps` gana columna `Git` con valores `remote` (repo_url poblado), `local` (.git/ presente) o `-`.
- `data.h`/`data.cpp`/`data_http.cpp` del dashboard: `AppRow` extendido con `repo_url` y `dir_path`.
- 10 repos migrados de branch `main` a `master` para 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"}`), branch `main` remota borrada.
- `git config --global init.defaultBranch master` para que los proximos `git init` sean consistentes.
- `/full-git-push`: descubre apps/analyses sin `.git` y ofrece inicializarlos con `ensure_repo_synced` automaticamente. Excluye `subrepos/` para evitar duplicacion (mirrors upstream).
- `/full-git-pull`: tras `fn sync`, segunda pasada que clona los `dataforge/<name>` registrados en `apps`/`analysis` que no existan localmente — soluciona el "no pude recuperar la app en el otro PC".
- `bash/functions/infra/ensure_repo_synced.sh`: localiza dependencias via `FN_REGISTRY_INFRA_DIR` o `FN_REGISTRY_ROOT`, robusto a sourcing desde zsh/bash.
### Fixed
- `projects/fn_monitoring/apps/sqlite_api/handlers.go|main.go|handlers_test.go` + nuevos `handlers_mutations.go` y `handlers_projects.go`: cableados endpoints `POST /add_app|add_analysis|add_vault|reindex` y `GET /projects` para que el dashboard pueda crear artefactos y navegar projects desde la actions bar (estado pendiente de varios dias en uncommitted, ahora versionado en `dataforge/sqlite_api`).
- Bug operativo en `sqlite_api` (Windows): `SO_RCVTIMEO` se pasaba como `struct timeval` cuando Windows espera `DWORD ms` → timeout efectivo de 5 ms. Ya documentado en `app.md` del 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_pipelines` que compone las anteriores: genera unit file + install + enable + start + status.
- Servicio systemd `sqlite_api.service` instalado y habilitado en aurgi-pc — arranque automático al iniciar WSL en `127.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`](.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_diario` para añadir entradas.
- `CHANGELOG.md` (este archivo).
- Submódulo `cpp/vendor/glfw` re-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.db` ahora está gitignorada. Es regenerable con `fn index` + completable con `fn sync`. Evita conflictos entre ramas y PCs.
- `sqlite_api` ahora se distribuye como binario compilado (`projects/fn_monitoring/apps/sqlite_api/sqlite_api`) en lugar de `go run` al vuelo.
### Fixed
- `http_client.cpp` del 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 al `ImGuiStyle` global.
- `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_dashboard` migrado a los nuevos componentes: `page_header_begin/end` en el header, `empty_state` en 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 de `systemctl` redirigido a stderr para no contaminar el JSON capturado por el pipeline.
- `.gitmodules`: entry fantasma `cpp/vendor/glfw` con path absoluto `/home/lucas/...` que bloqueaba `git submodule status` y el cross-compile Windows.
### Removed
- Integración de GitButler de Claude Code — binario `~/.local/bin/but`, plugin `gitbutler-tools`, skill `.claude/skills/gitbutler/`, hooks en `settings.json`, ramas `gitbutler/*` + `e-branch-*`, estado interno `.git/gitbutler/`. Ver [ADR 0001](docs/adr/0001-gitbutler-experiment.md) para motivos.