--- id: "0109" title: "App skill_tree: mapa interactivo de issues+flows en anillos concentricos por estado (roadmap)" status: in-progress type: epic domain: - meta - cpp-stack scope: cross-stack priority: media depends: [] blocks: [] related: - "0069" - "0085" - "0086" - "0087" - "0100" created: 2026-05-17 updated: 2026-05-17 tags: - skill-tree - roadmap - meta - cpp - imgui - gamification --- # 0109 — skill_tree app (roadmap) ## Vision App C++ ImGui que muestra los **79 issues + 7 flows** del registry como un mapa de capacidades en **anillos concentricos por estado** (centro = `completado`, exterior = `locked`/`deferred`), con **sectores radiales por dominio**. Click en nodo → panel `Inspector` con DoD + funciones del registry asociadas + 2 botones: - **Generate ideas (`claude -p`)** → escribe a tabla `idea_drafts` para revision manual. - **Run autonomous-task (`fn-orquestador`)** → spawn subagente en sandbox `auto/` con tail de logs. Centro NO es nodo — es **HUD overlay** con LV, XP, conteos por dominio. Animacion lerp 1s cuando un nodo migra de anillo (cambio de status). Sin fisicas — layout estatico y determinista. ## Por que - Discovery visual: lo que hoy es `ls dev/issues/` + lectura individual de 79 .md, se reduce a panoramica de 5s. - Dispatcher unificado: lanzar `claude -p` o `/autonomous-task` desde 1 click contextual (hoy: copiar ID + tipear comando). - Gamificacion derivada (XP/nivel) sin inflar nada artificial — todo deriva de trabajo real (status frontmatter + telemetria). ## No-goals (fuera de scope) - NO editor de issues. Solo lectura + dispatch. Editar issue = boton "Open in editor" → `code `. - NO orquestador propio. Reusa `fn-orquestador` + `/autonomous-task` (issue 0069). - NO base de datos paralela de issues. `registry.db` y `dev/issues/*.md` siguen siendo fuente unica. ## Modelo ### Tipos de nodo | Tipo | Origen | Ring | Render | |---|---|---|---| | Issue (epic) | `dev/issues/NNNN-*.md` (`type=epic`) | segun status | nodo grande, color accent del dominio | | Issue (feature/bugfix/refactor/...) | mismo, otros types | segun status | nodo medio, tono mas claro | | Flow | `dev/flows/NNNN-*.md` | segun status (flow.status) | nodo distinto shape (rombo) | ### Aristas - `issue.depends` / `issue.blocks` → DAG (linea solida). - `flow.related_issues` → linea punteada flow → issue. - On-hover: aristas al cinturon perimetral de funciones del registry (`uses_functions` cruzado con tags del issue). ### Estado lock/unlock (DERIVADO — nunca manual) | Status visual | Regla | |---|---| | `done` | `status=completado` (issues) o `status=completed` (flows) | | `in-progress` | `status=in-progress` | | `unlocked` | `status=pendiente` Y todos `depends[]` resueltos | | `locked` | `status=pendiente` Y algun `depends[]` no resuelto | | `bloqueado` | `status=bloqueado` | | `deferred` | `status=deferred` | Flows sin `depends` usan `related_issues` — flow unlocked si todos los related estan done. ### XP / nivel - `xp_value` por tipo: `epic=10, feature=3, bugfix=1, refactor=2, chore=1, docs=1, flow=5`. - `xp_total = SUM(xp_value WHERE status in {completado, completed})`. - `level = floor(sqrt(xp_total))`. - HUD muestra: `LV X · N done · M open · K in-progress · domains mastered: ...`. ## Layout: anillos concentricos | Ring | Radio (px) | Que contiene | Notas | |---|---|---|---| | 0 | 0 - 150 | `completado` | Si > 30 nodos, mostrar top-N por recencia + bucket "+N mas" | | 1 | 150 - 280 | `in-progress` | Pulse animation suave | | 2 | 280 - 450 | `unlocked` pendiente | Color pleno, clickable | | 3 | 450 - 650 | `locked` (depends sin cumplir) | Gris, aristas hacia bloqueantes | | 4 | 650+ | `deferred` + `bloqueado` | Semi-transparente | Cada ring subdividido en **18 sectores radiales = 1 dominio** (allowlist de `dev/TAXONOMY.md`). Aristas curvas hacia el centro siguiendo el sector. Cuando un issue cambia status → lerp 1s entre posicion vieja y nueva. ## Stack tecnico - **App C++ ImGui** via `fn::run_app` (scaffolder `init_cpp_app_bash_pipelines`). - **Viz**: `graph_renderer_cpp_viz` (solo draw — sin force layout) + `graph_viewport_cpp_viz` + `graph_labels_cpp_viz` + `graph_spatial_hash_cpp_core` (picking O(1)). - **Layout**: nueva fn `compute_ring_layout_cpp_core` (pure) — input `[{node_id, status, domain, recency}]`, output `[{node_id, x, y, ring, sector}]`. - **Parser**: nueva fn `parse_md_frontmatter_cpp_core` (pure) — extrae bloque `---...---` + parse YAML simple (subset: key:value, key:list). - **BD propia**: `apps/skill_tree/local_files/skill_tree.db` con tablas: - `node_state_cache` (denormalizacion para render rapido) - `agent_jobs` (claude -p + fn-orquestador spawns) - `xp_events` (append-only para timeline) - `idea_drafts` (drafts de `claude -p` antes de promover a proposal) - **Registry.db**: read-only (`?mode=ro`), solo para enriquecer Inspector con info de `functions/types`. ## Sub-issues (rompimiento) | ID | Titulo | DoD resumido | |---|---|---| | 0109a | App shell + parsers | Scaffolder corre. App abre. Lee 79 issues + 7 flows. Log conteos en stdout. e2e_checks build OK. | | 0109b | Layout anillos + render estatico | Nodos pintados en su ring+sector. Aristas depends/related visibles. Sin interaccion clic. | | 0109c | Panel Inspector + estado derivado | Click nodo → panel derecho con DoD + uses_functions. Lock/unlock derivado de depends. Reload manual F5. | | 0109d | HUD XP + animacion migracion | Overlay HUD arriba-izq. Lerp 1s en cambio de status. xp_events append-only. | | 0109e | Boton Ideas (claude -p → drafts) | Spawn `claude -p` con prompt contextual. Persiste en `idea_drafts`. UI aprobar/rechazar → proposals. | | 0109f | Boton Auto-run (fn-orquestador) | Spawn `Agent(fn-orquestador)` background. Panel inferior con tail logs. Barra progreso vive (`task_runs.checks_pass/total`). | ## Riesgos / mitigaciones | Riesgo | Mitigacion | |---|---| | Ring 0 con ~72 done satura visualmente | Top-N por recencia + bucket "+N mas..." expandible | | 18 sectores * 158 nodos = legibilidad pobre | Zoom semantico: zoom-out muestra solo epics + flows | | `claude -p` puede consumir tokens en bucle | Rate-limit UI: 1 invocacion por nodo por hora (`idea_drafts.last_request_at`) | | Drift status del .md vs cache | F5 manual fuerza re-scan. Sin file watcher en fase A. | | Parser YAML C++ frágil con campos exoticos | Test golden sobre los 79 issues actuales antes de mergear 0109a | ## DoD del epic - [ ] App `skill_tree` indexada en `registry.db` con `framework=imgui`, trio icon completo, `e2e_checks` declarados, `uses_functions` no vacio. - [ ] Compila en Linux + Windows. Desplegada via `redeploy_cpp_app_windows`. - [ ] Tarjeta visible en `app_hub_launcher`. - [ ] Los 6 sub-issues (a-f) mergeados a master de su sub-repo Gitea. - [ ] Pipeline `fn doctor cpp-apps` limpio para `skill_tree`. - [ ] `fn doctor uses-functions` sin drift para `skill_tree`. ## Funciones nuevas previstas (delegar a fn-constructor) 1. `parse_md_frontmatter_cpp_core` (pure) — parser frontmatter YAML simple en C++. 2. `compute_ring_layout_cpp_core` (pure) — posiciones determinsticas por anillo+sector. 3. `spawn_claude_p_bash_infra` o `_go_infra` — lanza `claude -p ""` con timeout + captura stdout JSON. Reusable. ## Decisiones | Tema | Decision | Razon | |---|---|---| | Centro del mapa | HUD overlay, NO nodo | Centro = "estado actual del usuario" — no es un item, es un agregado. | | Layout | Estatico anillos+sectores | Sin fisicas. Usuario dijo "no quiero que se muevan, nos volveran locos". | | Animacion | Lerp 1s entre rings | Da sensacion de progreso sin caos visual. | | Boton Ideas dest | `idea_drafts` (revision manual) | Evita ruido en `proposals`. | | Refresh | F5 manual | Simplicidad MVP. File watcher en fase posterior. | | Service tag | NO | App interactiva, no daemon. | | Ubicacion | `apps/skill_tree/` | Meta-tool del registry entero, no de proyecto. |