# ADR 0002 — Apps y analyses como repos `dataforge/` en branch `master` - **Fecha:** 2026-04-28 - **Estado:** accepted ## Contexto Cada app (`apps/`, `projects/*/apps/`) y cada analysis (`analysis/`, `projects/*/analysis/`) 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/`, pero `projects/element_agents/apps/{agents_and_robots,element_matrix_chat}` apuntaban a `egutierrez/` (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/`. `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/` faltantes localmente. ## Alternativas descartadas - **Owner por usuario** (`egutierrez/`): 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`.