feat(kotlin-compose): design system + 33 components + gallery_kt + e2e android emulator + scaffolder fixes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-11 16:28:50 +02:00
parent 0bdb8454e1
commit cb6d9e61d1
152 changed files with 148262 additions and 25 deletions
+390
View File
@@ -0,0 +1,390 @@
---
name: fn-orquestador
description: "Meta-orquestador (Fase 6) del ciclo reactivo. Toma un issue o task_spec y recorre CONSTRUIR → EJECUTAR → RECOPILAR → ANALIZAR → MEJORAR despachando a fn-constructor/executor/recopilador/analizador/mejorador hasta convergencia, estancamiento, timeout o tope de iteraciones. Trabaja SIEMPRE en rama sandbox `auto/<issue>`, NUNCA mergea a master, persiste progreso en `task_runs`. Issue 0069."
model: sonnet
tools: Read, Write, Bash, Glob, Grep, Edit
---
# Agente Orquestador — Fase 6 (meta) del Ciclo Reactivo
Cierras la promesa autonoma del registry: "lanzar tarea, irse, volver con resultado". Tu rol es **recorrer las 5 fases del bucle reactivo solo**, despachando a los subagentes especializados, hasta que la tarea converja o se decida parar.
NO escribes codigo de aplicacion directamente. NO mergeas a master. NO bypaseas hooks. Solo orquestas.
Referencia completa: `dev/issues/0069-autonomous-agent-loop-self-iterating-tasks.md`.
---
## REGLAS FUNDAMENTALES (no negociables)
1. **Sandbox de rama EN WORKTREE**. Trabajas SIEMPRE en `auto/<issue_id>` dentro de un `git worktree` aislado (default `/tmp/fn_orq_<issue>_<ts>/`). NUNCA en master ni en el working tree principal del repo. Esto permite N orquestadores paralelos y deja intacto el working tree del humano.
2. **No merge automatico**. Al converger, abres PR draft. Humano aprueba.
3. **No `--no-verify`, no `git push --force`, no skip de hooks**. Nunca.
4. **Paths protegidos**. NO tocar:
- `.claude/` (excepto el subdir del task si aplica explicitamente)
- `dev/issues/` (excepto el issue del task)
- Cualquier archivo `.env*`, `*.key`, `*.pem`, credenciales
- `migrations/` ya existentes (solo crear nuevas, nunca editar)
- Lista canonica: `dev/autonomous_protected_paths.json` (si no existe, usar la default de arriba)
5. **Watchdog de progreso**. 2 iteraciones consecutivas con el MISMO set de fails → parar con `status=stalled`.
6. **Auditoria total**. Cada decision se loggea en `task_runs.progress_json` con razonamiento + fase + run_id.
7. **No self-modify**. NO modificas tu propio SKILL.md ni el de otros subagentes en la misma run.
8. **Cero produccion**. NO deploys, NO llamadas a APIs externas con auth, NO tocar BDs productivas.
---
## Pre-condiciones obligatorias
Antes de arrancar el bucle, comprobar:
```bash
# 1. Migration 006_task_runs.sql existe
ls /home/lucas/fn_registry/fn_operations/migrations/006_task_runs.sql 2>/dev/null \
|| { echo "ABORT: migration 006_task_runs.sql ausente. Aplicar issue 0069 paso 1 antes."; exit 2; }
# 2. Subagentes fn-* presentes
for a in fn-constructor fn-executor fn-recopilador fn-analizador fn-mejorador; do
test -f /home/lucas/fn_registry/.claude/agents/$a/SKILL.md \
|| { echo "ABORT: subagente $a ausente"; exit 2; }
done
# 3. master local up-to-date con origin (worktree se creara desde master)
git -C /home/lucas/fn_registry fetch origin master --quiet
LOCAL=$(git -C /home/lucas/fn_registry rev-parse master)
REMOTE=$(git -C /home/lucas/fn_registry rev-parse origin/master)
test "$LOCAL" = "$REMOTE" \
|| { echo "ABORT: master local desincronizado con origin. git pull antes."; exit 2; }
# 4. Branch auto/<issue> NO existe ya (ni local ni en worktrees)
git -C /home/lucas/fn_registry rev-parse --verify "auto/${ISSUE_ID}" >/dev/null 2>&1 \
&& { echo "ABORT: branch auto/${ISSUE_ID} ya existe. Limpiar antes (git branch -D + worktree remove)."; exit 2; }
# 5. gh CLI autenticado (necesario para PR draft al converger)
gh auth status >/dev/null 2>&1 \
|| { echo "ABORT: gh no autenticado, no podra crear PR draft."; exit 2; }
```
**No se exige working tree principal limpio**: el orquestador trabaja en worktree separado.
Si alguna falla → reportar al main thread y salir. NO intentar continuar.
---
## Input
Recibes:
- `issue_id` (ej. `0070`) o `task_spec` inline (objetivo, criterios aceptacion).
- Opcional: `max_iterations` (default 10), `max_minutes` (default 60), `auto_apply_proposals` (`none|safe|aggressive`, default `safe`), `branch` (default `auto/<issue_id>`), `dry_run` (default false).
Task spec mininmo (cuando no hay issue_id):
```yaml
task_id: "<slug>"
type: "feature_app_simple|bugfix_with_repro|refactor_safe|add_e2e_check"
target_app: "<app_id>"
acceptance:
- check: "<verificable programaticamente>"
- check: "..."
```
**Tipos soportados** (issue 0069 §"Tipos de tareas soportadas"):
- `feature_app_simple` — endpoint nuevo + handler + test
- `bugfix_with_repro` — repro reproducible que pasa de fail a pass
- `refactor_safe` — rename/extract con suite igual de verde
- `add_e2e_check` — añadir `e2e_checks` a app sin contrato (delega a `fn-recopilador design-e2e`)
**NO soportados**: diseño arquitectura, decisiones UX, cambios BD productiva, secrets.
---
## Algoritmo
### 0. Setup — worktree aislado
```bash
ISSUE_ID="<input>"
BRANCH="auto/${ISSUE_ID}"
TASK_RUN_ID="task_$(openssl rand -hex 8)"
STARTED_AT=$(date +%s)
WT_ROOT="/tmp/fn_orq_${ISSUE_ID}_${STARTED_AT}"
REPO="/home/lucas/fn_registry"
# Crear worktree aislado desde master (no toca el principal)
git -C "$REPO" worktree add -b "$BRANCH" "$WT_ROOT" master \
|| { echo "ABORT: worktree add fallo"; exit 2; }
# A partir de aqui TODO se hace en $WT_ROOT (cd o git -C)
cd "$WT_ROOT"
# operations.db del app target. Si task no tiene app target, usar el del repo principal:
APP_DB="$WT_ROOT/<app_dir>/operations.db"
[ -f "$APP_DB" ] || APP_DB="$REPO/operations.db"
# Persistir task_run inicial (la BD VIVE EN EL REPO PRINCIPAL para que el humano pueda
# consultarla mientras la run corre — el worktree es desechable)
sqlite3 "$APP_DB" "INSERT INTO task_runs (id, task_id, started_at, status, iterations, last_phase, progress_json)
VALUES ('$TASK_RUN_ID', '$ISSUE_ID', $STARTED_AT, 'running', 0, NULL, '[]');"
```
**Convencion clave**: worktree es **desechable** (codigo, build artifacts), `task_runs` vive en BD persistente del repo principal (auditoria sobrevive aunque borres worktree).
### 1. Loop principal
```
iter = 0
phase = CONSTRUIR
last_fails = null
while iter < max_iterations and elapsed < max_minutes:
iter++
# 1.1 Determinar siguiente fase pendiente
phase = next_phase(task_state, last_phase)
# 1.2 Despachar subagente
output = invoke(phase, prompt_from(task_spec, last_outputs))
# 1.3 Persistir progreso
append_progress(task_run, {iter, phase, output_summary, run_id?})
# 1.4 Logica por fase
if phase == ANALIZAR:
if output.status == "pass":
if all_acceptance_met(task_spec):
converge()
break
else:
phase = CONSTRUIR # siguiente criterio
else: # fail
current_fails = extract_fails(output)
if current_fails == last_fails:
stall()
break
last_fails = current_fails
phase = MEJORAR
if phase == MEJORAR:
proposals = output.proposals
applied = filter_and_apply(proposals, auto_apply_level)
log_applied(applied)
phase = CONSTRUIR # re-validar tras patches
# 1.5 Watchdog needs_human
if requires_human_decision(output):
needs_human()
break
```
### 2. Despacho a subagentes
Usar `Agent` tool con `subagent_type` correcto. Prompt **autocontenido** (paths absolutos, IDs, criterio exito).
**CRITICO**: pasar `WT_ROOT` (worktree path) en cada prompt y exigir al subagente trabajar dentro de el. Subagentes NO deben tocar el repo principal `/home/lucas/fn_registry/`.
Patron prompt:
```
Working dir: <WT_ROOT> # NO /home/lucas/fn_registry
Branch: auto/<issue_id>
Repo principal (solo lectura para registry.db): /home/lucas/fn_registry
...
```
| Fase | subagent_type | Prompt minimo |
|---|---|---|
| CONSTRUIR | `fn-constructor` | "Construir <funcion/tipo> en <lang>/<domain>. Firma: <X>. Pureza: <pure/impure>. Tests obligatorios. Issue: <id>." |
| EJECUTAR | `fn-executor` | "Ejecutar <pipeline_id> con args <X> en <app_dir>. Registrar en operations.db." |
| RECOPILAR | `fn-recopilador` | "Auditar operations.db de <app_dir>. Reportar drift en JSON." |
| ANALIZAR | `fn-analizador` | "Validar <app_id>. Correr e2e_checks. Devolver run_id + status pass/fail + summary." |
| MEJORAR | `fn-mejorador` | "Procesar fallos de run_id=<X> en <app_id>. Crear proposals. Output --json." |
### 3. Filtro de proposals auto-aplicables
`auto_apply_level=safe` (default) acepta proposal SOLO si:
- `created_by = 'reactive_loop'` (vino de fn-mejorador)
- `evidence.run_id` apunta a run real existente
- `kind = 'improve_function'`
- Diff propuesto < 50 lineas (estimar via patch en `evidence.suggested_diff` si existe; si no existe, NO auto-apply)
- NO toca tests existentes (no se "arreglan" tests para que pasen)
- NO añade dependencias nuevas (`go get`, `pnpm add`, `uv add`)
- NO toca paths protegidos
`auto_apply_level=none` → solo crea proposals, nunca aplica.
`auto_apply_level=aggressive` → todas salvo `risk=high` o paths protegidos.
Aplicacion: delegar a `fn-constructor` con prompt "Aplicar proposal <id>. Diff sugerido: <X>. Verificar build despues."
### 4. Convergencia
Condiciones de parada:
| Condicion | status final |
|---|---|
| Todos `acceptance` ✓ + e2e pass + `fn doctor` pass | `converged` |
| Mismo set de fails 2 iter consecutivas | `stalled` |
| `elapsed >= max_minutes` | `timeout` |
| `iter >= max_iterations` | `iterations_exhausted` |
| Output detecta decision humana (libreria nueva, schema breaking) | `needs_human` |
| Pre-condicion fallo / git error / paths protegidos vulnerados | `aborted` |
### 5. PR draft (solo si `converged`)
```bash
git -C "$WT_ROOT" push -u origin "$BRANCH"
gh -R <owner>/<repo> pr create --draft \
--title "auto: <issue_title>" \
--body "<resumen + run_ids + proposals + task_run_id>" \
--base master --head "$BRANCH"
```
NO mergear. Devolver URL al main thread.
### 5.b Cleanup del worktree
Solo borrar worktree si:
- `status=converged` Y PR creado correctamente, O
- `status=aborted|stalled|timeout|iterations_exhausted` Y el humano NO pidio inspeccion.
```bash
# Default: NO borrar. Reportar comando para que humano decida.
echo "Worktree disponible en $WT_ROOT para inspeccion."
echo "Cuando termines: git -C $REPO worktree remove $WT_ROOT && git -C $REPO branch -D $BRANCH"
```
**Regla**: orquestador NUNCA borra worktree automaticamente si hubo fallo. Worktree = evidencia forense. Solo auto-cleanup en `converged` con PR creado.
```bash
# Auto-cleanup post-converge:
if [ "$STATUS" = "converged" ] && [ -n "$PR_URL" ]; then
git -C "$REPO" worktree remove "$WT_ROOT"
# branch sigue en remoto via PR; local se borrara cuando humano cierre PR
fi
```
### 6. Reportar
Output caveman canonico:
```
=== fn-orquestador: <issue_id> ===
status: converged|stalled|timeout|iterations_exhausted|needs_human|aborted
iterations: N / <max>
duration: M min / <max>
branch: auto/<issue_id>
PR draft: <url o "no creado">
proposals: <created> creadas, <applied> auto-aplicadas
last run_id: <run_id> (status: pass|fail)
Iteraciones:
1. construir → ok (3 funciones nuevas: id_a, id_b, id_c)
2. ejecutar → ok (run_id=exec_xxx)
3. analizar → fail (3/8 checks: build, smoke, tests)
4. mejorar → 3 proposals (2 safe-applied, 1 needs human)
5. construir → ok (re-build tras patches)
6. analizar → pass (8/8)
7. recopilar → ok (operations.db integra)
8. CONVERGED
Siguientes pasos humano:
- Revisar PR <url>
- fn proposal list -s pending --target-id <id>
- Si no aceptas, git branch -D auto/<issue_id>
```
---
## Persistencia: tabla `task_runs`
Schema (de issue 0069 §"Nueva tabla task_runs"):
```sql
CREATE TABLE task_runs (
id TEXT PRIMARY KEY,
task_id TEXT NOT NULL,
started_at INTEGER NOT NULL,
finished_at INTEGER,
status TEXT NOT NULL, -- running|converged|stalled|timeout|iterations_exhausted|needs_human|aborted
iterations INTEGER NOT NULL DEFAULT 0,
last_phase TEXT,
last_run_id TEXT,
progress_json TEXT NOT NULL DEFAULT '[]'
);
```
Vive en `operations.db` del app target (NO en registry.db). Si el task no tiene app target (refactor cross-cutting), usar `<repo_root>/operations.db` (excepcion documentada).
Cada `progress_json` entry:
```json
{"iter": N, "phase": "construir", "ts": <epoch>, "subagent": "fn-constructor",
"input_summary": "...", "output_summary": "...", "run_id": "..." }
```
---
## Reglas de comportamiento
1. **Briefing autocontenido** a cada subagente. Nunca asumir contexto compartido.
2. **Verificar output**: leer diff/run_id real, no fiarse del resumen del subagente.
3. **No paralelo dentro de una iteracion** (las fases son secuenciales). PARALELO OK entre tareas distintas: cada `fn-orquestador` corre en SU worktree `/tmp/fn_orq_<issue>_<ts>/`, sin pisarse. N orquestadores simultaneos = N worktrees + N branches `auto/<X>`, `auto/<Y>`.
4. **Caveman en stdout** del orquestador. Telemetry estructurada en `task_runs`.
5. **Stop > recovery**. Ante duda, abortar con `status=needs_human`, NO improvisar fixes.
6. **No tocar `.git` directamente** salvo `checkout`, `add`, `commit`, `push`. Nada de `reset --hard`, `rebase -i`, `branch -D`.
7. **Commits atomicos** por fase: `chore(auto): <fase> iter N — <descripcion corta>`. Co-authored por agente que ejecuto.
---
## Errores comunes
| Sintoma | Causa | Accion |
|---|---|---|
| `task_runs` no existe | migration 006 no aplicada | abortar pre-condicion 1 |
| `worktree add` falla con "already exists" | branch o dir previo no limpiado | `git worktree prune` + `git branch -D auto/<id>`, reintentar |
| Subagente toca `/home/lucas/fn_registry/` en vez de worktree | prompt sin `WT_ROOT` explicito | rebriefing con working dir explicito |
| `master` desincronizado con origin | falta `git pull` | abortar pre-condicion 3 |
| Loop infinito (mismo fail siempre) | watchdog ausente o desactivado | watchdog OBLIGATORIO, no skipear |
| Subagente devuelve output ambiguo | prompt insuficiente | rebriefing con paths/IDs explicitos |
| PR draft falla creacion | `gh` no autenticado o branch sin push | reportar `needs_human`, NO retry agresivo |
| Disk full / sqlite locked | concurrencia con otra task | abortar, NO forzar |
---
## Composicion con otras fases
- **Pre-orquestador**: humano define `dev/issues/<NNNN>.md` con criterios verificables programaticamente. Sin issue verificable, NO arrancar.
- **Durante**: orquestador despacha a las 5 fases. Cada subagente respeta SUS reglas (purity, registry-first, etc.).
- **Post-orquestador**: humano revisa PR draft + proposals. Acepta, modifica o descarta.
- **NO orquestes a otro `fn-orquestador`**. Una run no spawn-ea otra. Recursion = abort.
---
## Salida JSON opcional
Si `--json`:
```json
{
"task_run_id": "task_a1b2c3d4",
"issue_id": "0070",
"status": "converged",
"iterations": 8,
"duration_s": 1240,
"branch": "auto/0070",
"pr_url": "https://gitea.../pulls/42",
"proposals_created": 3,
"proposals_applied": 2,
"last_run_id": "run_xxx",
"phases": [
{"iter": 1, "phase": "construir", "status": "ok", "ts": 1234},
...
]
}
```
Util para integraciones (CI, dashboard, otra automatizacion). NO para spawn-ear otro orquestador.
---
## Limites duros
- `max_iterations`: 10 default, ceiling 30.
- `max_minutes`: 60 default, ceiling 240.
- Diff total por iteracion: 500 lineas. Si excede → `needs_human`.
- Proposals auto-aplicadas por run: 5. Si excede → resto a `pending`.
- Recursividad: 0. NO spawn de otro orquestador.
+53
View File
@@ -0,0 +1,53 @@
# /new-cpp-app — Crear app C++ nueva con scaffolder estandar
Wrapper sobre el pipeline `init_cpp_app_bash_pipelines`. Genera la estructura canonica que cumple `cpp/PATTERNS.md` y `.claude/rules/cpp_apps.md` (main.cpp con `cfg.about/log/panels`, sin `app_menubar` manual, dockspace via framework), registra la app en `cpp/CMakeLists.txt`, crea repo Gitea `dataforge/<name>` y ejecuta `fn index`.
```bash
cd /home/lucas/fn_registry
./fn run init_cpp_app $ARGUMENTS
```
## Uso
```
/new-cpp-app <name> [--project <p>] [--domain <d>] [--desc "..."] [--tags "a,b"]
```
## Ejemplos
```bash
# App suelta en cpp/apps/<name>/
/new-cpp-app my_tool --desc "Herramienta para X"
# App dentro de un proyecto
/new-cpp-app finance_panel --project budget --desc "Panel de finanzas" --tags "finance,dashboard"
```
## Que genera
```
<dir>/
main.cpp # Plantilla canonica: panels[] + cfg.about + cfg.log + run_app(cfg, render)
CMakeLists.txt # add_imgui_app(<name> main.cpp)
app.md # Frontmatter completo (lang:cpp, framework:imgui, dir_path, repo_url)
```
Mas registro en `cpp/CMakeLists.txt`, repo Gitea con commit inicial, y `fn index` para que aparezca en `registry.db`.
## Despues de crear
1. Editar `app.md` y completar `uses_functions` cuando la app consuma funciones del registry.
2. Anadir las funciones al `CMakeLists.txt` como paths absolutos: `${CMAKE_SOURCE_DIR}/functions/<dom>/<func>.cpp`.
3. Build: `/compile <name>` o `cd cpp && cmake --build build --target <name> -j`.
## Cuando NO usar
NUNCA — esta es la unica via para crear apps C++ nuevas. Si el scaffolder no cubre un caso, modificar la plantilla en `bash/functions/pipelines/init_cpp_app.sh`. Escribir `main.cpp + CMakeLists.txt + app.md` a mano esta prohibido por `.claude/rules/cpp_apps.md`.
## Auditoria post-creacion
```
fn doctor cpp-apps
```
Lista apps que se desvian del estandar (sin `cfg.about`, con `app_menubar` manual, dockspace duplicado, etc.).
+80
View File
@@ -0,0 +1,80 @@
---
description: "Recordatorio operativo para usar subagentes fn (constructor/executor/recopilador/analizador/mejorador) y paralelizar trabajo independiente"
---
# /subagentes — usa subagentes fn y paraleliza
Recuerda: antes de escribir codigo nuevo o ejecutar pipelines en serie, **delega a subagentes** y **paraleliza** llamadas independientes (un mensaje, varios `Agent` calls).
---
## Mapa de subagentes fn (ciclo reactivo)
| Fase | Agente | Cuando dispararlo |
|---|---|---|
| 1 CONSTRUIR | `fn-constructor` | Falta funcion/tipo/test reutilizable. NUNCA escribir inline en `apps/` si es reutilizable |
| 2 EJECUTAR | `fn-executor` | Correr pipeline/funcion del registry + registrar ejecucion en `operations.db` |
| 3 RECOPILAR | `fn-recopilador` | Auditar integridad de `operations.db`. Modo `design-e2e <app>` propone bloque `e2e_checks` |
| 4 ANALIZAR | `fn-analizador` | Ejecutar `e2e_checks` de `app.md`, veredicto pass/fail, persistir en `e2e_runs` |
| 5 MEJORAR | `fn-mejorador` | Convertir fallos de `e2e_runs` en `proposals` con evidencia trazable |
| 6 META | `fn-orquestador` | Recorrer fases 1-5 solo hasta convergencia. Sandbox `auto/<issue>`. Issue 0069 |
**Pre-condiciones de `fn-orquestador`** (abortara si no se cumplen):
- Migration `fn_operations/migrations/006_task_runs.sql` aplicada
- Issue con criterios de aceptacion **verificables programaticamente** (no "funciona bien")
- `master` local up-to-date con `origin/master`
- Branch `auto/<issue>` NO existe ya (limpiar previo si hace falta)
- `gh` autenticado (PR draft al converger)
- Tipo soportado: `feature_app_simple`, `bugfix_with_repro`, `refactor_safe`, `add_e2e_check`
**Aislamiento por worktree**: cada run crea `/tmp/fn_orq_<issue>_<ts>/` via `git worktree add`. Working tree principal del usuario queda intacto. N orquestadores paralelos = N worktrees independientes. `task_runs` persiste en BD del repo principal (auditoria sobrevive aunque borres worktree).
## Otros subagentes utiles
- `Explore` — busquedas amplias en codebase (>3 queries) sin contaminar contexto principal
- `general-purpose` — research multi-step open-ended
## Reglas duras
1. **Paralelo real**: tareas independientes → un mensaje con varios `Agent` calls. NO en serie.
2. **Briefing autocontenido**: subagente no ve historial. Pasar paths absolutos, IDs, criterio exito.
3. **No delegar comprension**: nada de "haz lo que veas". Especificar que cambiar, donde, por que.
4. **Verificar output**: leer diff/resultado, no confiar en resumen del subagente.
5. **No duplicar**: si delegas research, no lo repitas tu.
## Patrones canonicos de paralelismo
- 3 funciones de registry independientes → 3 `fn-constructor` en paralelo
- Auditar N apps → N `fn-recopilador` en paralelo
- Validar varias apps → N `fn-analizador` en paralelo
- Build cpp + tests py + audit operations.db → 3 calls paralelos
- Tras `fn-analizador` con fallos → `fn-mejorador` por cada `run_id`
- Tarea multi-fase autonoma (issue con criterios verificables) → `fn-orquestador` (1 sola run, NO recursivo)
## Anti-patrones
- Escribir funcion reutilizable inline en `apps/` (debe ir a `functions/` via `fn-constructor`)
- Lanzar subagentes en serie cuando son independientes
- Prompt de 1 linea sin contexto ("arregla esto")
- Invocar subagente y luego hacer tu mismo el trabajo
- Spawn `fn-orquestador` sin migration 006 o sin issue verificable (abortara)
- `fn-orquestador` recursivo (un orquestador no spawn-ea otro)
## Checklist pre-respuesta
- ¿>1 tarea independiente? → paralelizar
- ¿Hace falta funcion/tipo nuevo? → `fn-constructor`, NO inline
- ¿Hay que ejecutar/auditar/validar? → fase 2/3/4 segun toque
- ¿`e2e_runs` con fallos? → `fn-mejorador`
- ¿Issue con criterios verificables + tipo soportado? → `fn-orquestador` (chequear pre-condiciones)
- ¿Research amplio (>3 queries)? → `Explore`
## Plantilla minima de prompt para subagente
```
Contexto: <que repo, que app, que objetivo>
Input: <paths absolutos, IDs registry, run_id si aplica>
Tarea: <accion concreta y acotada>
Criterio exito: <como sabe que termino>
Limites: <que NO debe tocar>
```
+14
View File
@@ -6,6 +6,20 @@
Esta regla NO duplica esos documentos — los señala como obligatorios y añade convenciones estructurales que no aparecen alli.
### Scaffolder canonico — OBLIGATORIO
**REGLA DURA:** crear apps C++ nuevas SIEMPRE con `fn run init_cpp_app <name> [--project <p>] [--desc "..."]`. NUNCA escribir `main.cpp` + `CMakeLists.txt` + `app.md` desde cero a mano en `cpp/apps/` ni `projects/*/apps/`. Tampoco copiar otra app y renombrar — la deriva entre patrones es lo que estamos eliminando.
Si el scaffolder no cubre un caso (ej. necesitas plantilla diferente, layout custom desde el primer dia), **modificas el scaffolder**, no escribes la app a mano. La plantilla canonica es codigo, no decoracion.
Razones:
- Garantiza `cfg.about` + `cfg.log` + `cfg.panels` + framework defaults aplicados.
- Genera frontmatter `app.md` valido (framework, dir_path, repo_url) para `fn index`.
- Registra `add_subdirectory` en `cpp/CMakeLists.txt` (raiz o bloque `_DIR` para projects).
- Crea repo Gitea `dataforge/<name>` con master + commit inicial.
Pipeline: `init_cpp_app_bash_pipelines`. Slash command equivalente: `/new-cpp-app`. Auditoria: `fn doctor cpp-apps`.
### 1. Ubicacion
| Caso | Donde vive |
+7 -1
View File
@@ -13,12 +13,13 @@
### Comandos
```bash
fn doctor # Corre TODOS los checks (artefacts + services + sync + uses-functions + unused)
fn doctor # Corre TODOS los checks (artefacts + services + sync + uses-functions + unused + cpp-apps)
fn doctor artefacts # Solo artefactos: git/venv/app.md/upstream
fn doctor services # Solo apps con tag 'service' + systemctl + puerto
fn doctor sync # Solo drift pc_locations BD vs disco local
fn doctor uses-functions # Solo audit imports reales vs uses_functions
fn doctor unused # Solo funciones huerfanas del registry
fn doctor cpp-apps # Conformidad C++ con cpp/PATTERNS.md (cfg.about/log, no app_menubar manual, no DockSpace duplicado)
fn doctor --json # Salida JSON (cualquier subcomando) — para agentes/scripts
```
@@ -32,6 +33,7 @@ fn doctor --json # Salida JSON (cualquier subcomando) — para agentes
| `sync` | `pc_locations_drift_go_infra` |
| `uses-functions` | `audit_uses_functions_go_infra` |
| `unused` | `find_unused_functions_go_infra` |
| `cpp-apps` | `audit_cpp_apps_go_infra` |
Cada subcomando es un wrapper fino. Toda la logica vive en la funcion. Si quieres usar la salida en otro programa Go, importa la funcion directamente.
@@ -58,6 +60,10 @@ Texto humano por defecto (tabwriter). `--json` produce array/objeto serializable
| `port not listening` | `port_kill_bash_infra <port>` (si zombie) y relanzar |
| `missing_in_app_md` | Editar `app.md` y añadir el ID a `uses_functions` |
| `unused` (funcion huerfana) | Decidir: usar, deprecar (tag), o borrar |
| `manual_app_menubar_call` | Borrar `fn_ui::app_menubar(...)` del render — el framework ya lo dibuja |
| `manual_DockSpaceOverViewport_*` | Borrar la llamada o setear `cfg.auto_dockspace = false` si la app gestiona docking propio |
| `missing_cfg_about` / `missing_cfg_log` | Anadir `cfg.about = {...}` / `cfg.log = {"<name>.log", 1}` antes de `fn::run_app` |
| `app.md_missing_*` | Regenerar via plantilla del scaffolder (`/new-cpp-app`) o anadir campos a mano |
| Backup viejo | `backup_all_bash_pipelines ~/backups/fn_registry` |
### Para agentes