docs: ADR 0002 + CHANGELOG + reglas para dataforge/<name>+master

- docs/adr/0002-apps-analyses-as-dataforge-master.md: decision arquitectural
  con contexto, alternativas descartadas y cambios concretos del 2026-04-28.
- CHANGELOG.md: entrada 2026-04-28 con Added/Changed/Fixed.
- .claude/CLAUDE.md: nota sobre /full-git-push y dataforge/<name>+master.
- .claude/rules/apps_tbd.md: tronco unico master + init.defaultBranch.
- cpp/functions/core/app_menubar.md: notas del submenu Settings con About.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-28 22:41:55 +02:00
parent 363fc07e74
commit 836ff02578
5 changed files with 88 additions and 1 deletions
+2
View File
@@ -8,6 +8,8 @@ Registry personal de codigo reutilizable con busqueda FTS. Diseñado para compos
**Sync entre PCs:** `fn sync` sincroniza datos no regenerables (proposals, apps, projects, analysis, vaults, pc_locations) contra `registry_api` en `https://registry.organic-machine.com`. Config: `~/.fn_pc` (identidad del PC), `FN_REGISTRY_API` (URL con basicAuth), `REGISTRY_API_TOKEN` (token).
**Sub-repos:** cada app y cada analysis es su propio repo Gitea en `dataforge/<basename>` con branch `master` (ver ADR 0002). Los slash commands `/full-git-push` y `/full-git-pull` orquestan push/pull/clone de fn_registry + todos los sub-repos + `fn sync`. `/full-git-push` auto-inicializa apps/analyses sin `.git` via `ensure_repo_synced_bash_infra`. Los `vaults/` y `subrepos/` NO entran en este flujo.
**Reglas y convenciones:** ver `.claude/rules/INDEX.md`
---
+3 -1
View File
@@ -1,6 +1,8 @@
## Trunk-based development (TBD) en apps generadas con `fn`
**El registry NO usa TBD** (push directo a master OK). Pero **toda app generada con `fn`** que viva en `apps/`, `projects/<name>/apps/` o que se despliegue a un VPS via `deploy_server` **DEBE seguir TBD** mientras se desarrolla:
**El registry NO usa TBD** (push directo a master OK). Pero **toda app generada con `fn`** que viva en `apps/`, `projects/<name>/apps/` o que se despliegue a un VPS via `deploy_server` **DEBE seguir TBD** mientras se desarrolla.
**Tronco unico: `master`** en todos los repos `dataforge/<name>` del ecosistema (apps + analyses). Ver ADR 0002. El default de `git init` debe estar en `master` (`git config --global init.defaultBranch master`) — los pipelines de scaffolding y `ensure_repo_synced_bash_infra` ya pasan `master` explicitamente.
```
master ← siempre deployable
+25
View File
@@ -8,6 +8,31 @@ Para contexto detallado del trabajo diario ver `docs/diary/`. Para decisiones ar
## [Unreleased]
## 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
+11
View File
@@ -124,3 +124,14 @@ El render efectivo de la ventana ocurre al final del frame en `fn::run_app` via
Apps sin paneles ni layouts (gallery, chart_demo, registry_dashboard) usan `fn_ui::app_menubar(nullptr, 0, nullptr)` solo para exponer el item `Settings...` en la menubar.
`uses_functions` ahora incluye `app_settings_cpp_core` (no añadido al frontmatter para evitar re-indexar; documentado aqui).
## Notas — Settings submenu con About (sesion 2026-04-28)
El item plano `Settings...` pasa a ser un `BeginMenu("Settings")` con dos subitems separados por un separator:
- `Settings...` → abre ventana de `app_settings` (Display + Typography + secciones extra).
- `About...` → abre ventana de `app_about_cpp_core` (project + version + description). La info se setea via `fn_ui::about_window_set_info(project, version, description)` desde el init de la app antes de `fn::run_app`.
`fn::run_app` ahora llama tambien `fn_ui::about_window_render()` al final del frame, justo despues de `settings_window_render()`. Apps que no usan `fn::run_app` deben llamar ambos manualmente.
Cambio retro-compatible: las apps que solo invocan `fn_ui::app_menubar(nullptr, 0, nullptr)` no necesitan tocar nada — el menu `Settings` aparece con About vacio (defaults `"fn_registry app"` / sin version) hasta que llamen `about_window_set_info`.
@@ -0,0 +1,47 @@
# ADR 0002 — Apps y analyses como repos `dataforge/<name>` en branch `master`
- **Fecha:** 2026-04-28
- **Estado:** accepted
## Contexto
Cada app (`apps/<name>`, `projects/*/apps/<name>`) y cada analysis (`analysis/<name>`, `projects/*/analysis/<name>`) en `fn_registry` vive como repo git independiente: el repo padre los `.gitignore`a y solo conserva su metadata indexada en `registry.db`. Esto permite clonar/desplegar/compartir cada artefacto sin arrastrar el monorepo entero.
Hasta 2026-04-28 el sistema tenia tres inconsistencias:
1. **Owners mezclados en Gitea**: la mayoria pusheaba a `dataforge/<name>`, pero `projects/element_agents/apps/{agents_and_robots,element_matrix_chat}` apuntaban a `egutierrez/<name>` (uno no existia, otro sin permisos de push).
2. **Apps/analyses sin `.git`**: `apps/{deploy_server,shaders_lab,voice_guide}` y `analysis/{agent_coding_eval,ontology_graph}` + `projects/app_turismo/analysis/turismo_spain` no estaban en Gitea — imposibles de recuperar en otro PC.
3. **Mezcla de ramas `main` vs `master`**: 10 repos en `main` (creados antes de unificar convencion), 14 en `master`. La causa raiz era `init.defaultBranch` sin configurar globalmente, asi que `git init` daba lo que la version de git decidiera, y las primeras pushes fijaban el default branch en Gitea.
## Decision
1. **Owner unico en Gitea: `dataforge`**. Toda app/analysis del registry vive en `https://gitea.../dataforge/<basename>`. `dataforge` es un *user* en Gitea (no org), asi que `gitea_create_repo` cae al endpoint `/api/v1/user/repos` automaticamente.
2. **Branch unico: `master`**. Coherente con `fn_registry` (raiz), con la mayoria de apps/analyses, y con `subrepos/fn-design-system`. Configuracion enforced con `git config --global init.defaultBranch master` en cada PC.
3. **Vaults NO siguen esta regla**. Los vaults son datos puros — su mecanismo de compartir queda pendiente (TBD: object storage, rsync programado, restic). Hasta entonces, no se versionan en Gitea.
4. **`subrepos/` NO entran**. Son mirrors upstream (Claude Design, etc.); se gestionan con su propio remote dual y no participan de `/full-git-push` / `/full-git-pull`.
### Helpers introducidos
- `ensure_repo_synced_bash_infra` — pipeline idempotente que crea repo Gitea + init local + commit + push.
- `/full-git-push` descubre apps/analyses sin `.git` y los inicializa.
- `/full-git-pull` tras `fn sync` clona los `dataforge/<name>` faltantes localmente.
## Alternativas descartadas
- **Owner por usuario** (`egutierrez/<name>`): obligaria a tener tokens distintos por PC y limitaria colaboracion. Descartado.
- **Submodules en `fn_registry`**: se probo (ver ADR 0001 — GitButler). Bugs con gitlinks, commits cruzados y duplicacion. Descartado.
- **Branch `main`**: estandar moderno (GitHub default), pero `fn_registry` raiz, deploy scripts y la mayoria de apps ya estaban en `master`. Migrar todo a `main` requeria mas cambios que migrar 10 repos a `master`. Decidido por minimizar churn.
## Consecuencias
- Recuperar todo el ecosistema en un PC nuevo: `git clone fn_registry` + `/full-git-pull` (clona los dataforge/* registrados via `fn sync`).
- Crear app/analysis nueva: el pipeline `init_jupyter_analysis` o el flujo manual debe invocar `ensure_repo_synced` con defaults `owner=dataforge branch=master`.
- Cualquier outlier en otro owner o branch se detecta facilmente con la query del audit (ver `.claude/rules/apps_own_repo.md`).
- Si se anaden mas branches (feature, issue/*), siguen las reglas de `apps_tbd.md`. La convencion solo fija el tronco principal.
## Cambios concretos aplicados (2026-04-28)
- 2 repos movidos a `dataforge/`: `agents_and_robots`, `element_matrix_chat`.
- 6 repos creados desde cero: `deploy_server`, `shaders_lab`, `voice_guide`, `agent_coding_eval`, `ontology_graph`, `turismo_spain`.
- 10 repos migrados `main``master`: `apps/{docker_tui,fuzzygraph,metabase_registry,pipeline_launcher,rapid_dashboards,script_navegador}`, `analysis/{estudio_embeddings,estudio_mercados,pruebas_jupyter,retrieving_graphs}`.
- `git config --global init.defaultBranch master`.