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:
@@ -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.
|
||||
@@ -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.).
|
||||
@@ -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>
|
||||
```
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user